[
  {
    "path": ".gitattributes",
    "content": "# Windows-specific files that require CRLF:\n*.bat       eol=crlf\n*.txt        eol=crlf\n\n# Unix-specific files that require LF:\n*.java        eol=lf\n*.sh        eol=lf\n\n*.js linguist-language=Java"
  },
  {
    "path": ".gitignore",
    "content": "target/\n!.mvn/wrapper/maven-wrapper.jar\n\n### STS ###\n.apt_generated\n.classpath\n.factorypath\n.project\n.settings\n.springBeans\n\n### IntelliJ IDEA ###\n.idea/*\n*.iws\n*.iml\n*.ipr\n\n### JRebel ###\nrebel.xml\n\n### MAC ###\n.DS_Store\n\n### Other ###\nlogs/\ntemp/\n\n/.idea/\n"
  },
  {
    "path": "README.md",
    "content": "## YMall\n\n## 开发环境\n\n- 操作系统：Windows 10 Enterprise\n- 开发工具：Intellij IDEA\n- 数据库：MySQL 8.0.13\n- Java SDK：Oracle JDK 1.8.152\n\n## 项目管理工具\n\n- 项目构建：Maven\n- 代码管理：Git\n\n## 后台主要技术栈\n\n- 核心框架：Spring + Spring MVC + MyBatis\n- 数据库连接池：Alibaba Druid\n- 数据库缓存：Redis\n- 接口文档引擎：Swagger2 RESTful 风格 API 文档生成\n- 全文检索引擎：Elasticsearch\n- 系统任务调度：Quartz\n\n## 前后分离\n\n- 前端框架：NodeJS + Vue + Axios\n- 前端模板：ElementUI\n\n## 项目截图\n\n### YMall 商城前台\n\n- 首页\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/首页.png)\n\n\n![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/首页-1.png)\n\n![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/首页-2.png)\n\n- 分类商品页\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/分类商品页.png)\n\n- 商品详情页\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/商品详情页-1.png)\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/商品详情页-2.png)\n\n- 购物车\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/购物车.png)\n\n- 下单\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/下单-1.png)\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/下单-2.png)\n\n- 支付\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/支付-1.png)\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/支付-2.png)\n\n- 会员中心-我的订单\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/会员中心-1.png)\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/会员中心-1-1.png)\n\n- 会员中心-账号资料\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/会员中心-2.png)\n\n- 会员中心-修改地址\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/会员中心-3.png)\n\n- 注册\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/注册.png)\n\n- 登录\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/登录.png)\n\n- 忘记密码\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/忘记密码.png)\n\n\n\n### YMall 商城后台\n\n- 首页\n\n![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/后台首页.png)\n\n## 项目部署\n### 1. 运行项目所需环境\n\n- JDK 1.8\n- IDEA\n- MySQL 5.5 以上\n- Tomcat 8\n- Elasticsearch 5.6\n- Redis\n\n确保你已经安装上述环境，以上安装教程可自行百度...，安装记得修改 `ymall-web-api` 和 `ymall-web-admin` 的 Redis 和 Elasticsearch 的连接地址\n![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_2020-09-06_13-13-20.png)\n\n- 还需要七牛云的图片服务器和阿里云沙箱支付的密钥，请自行申请\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_2020-09-06_13-51-23.png)\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_2020-09-06_13-51-45.png)\n\n### 2. 导入项目\n\n- `IDEA` -> `open`\n\n![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_20191113094747.png)\n\n\n- 手动安装 `alipay` 依赖到本地仓库\n\n    因为 Mavan 中央仓库没有 alipay 的依赖所以需要手动安装依赖本地仓库，`alipay` 的 jar 文件在 `ymall-dependencies` 下的 `lib` 目录\n    \n    在 jar 包的目录，执行 Maven 安装依赖的命令：\n    ```java\n    mvn install:install-file -DgroupId=com.alipay -DartifactId=alipay-trade-sdk -Dversion=20161215 -Dpackaging=jar -Dfile=alipay-trade-sdk-20161215.jar\n    ```\n\n- 刷新依赖\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_20191113095010.png)\n\n###　3. 导入 SQL 文件\n\n sql 文件在 `sql\\ymall.sql`\n\n![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_20191113103213.png)\n\n### ４. 部署接口项目\n\n  由于前台使用的是前后分离，所以接口项目是给前台 Vue 项目使用的\n\n- 配置 `Tomcat`\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_20191113103534.png)\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_20191113103657.png)\n\n\n\n- 选择文件部署\n\n![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_20191113104301.png)\n\n- 配置端口号 `9090` JMX port `1100`\n\n![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_20191113104354.png)\n\n- 运行\n\n  ![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_20191113104506.png)\n\n### 5. 部署后台项目\n\n后台项目暂时为 SSM + Jsp 项目，后期可能会重构为 VUE 项目\n\n部署方式与接口项目一致，只需要改端口号和 JMX port 即可\n\n![](https://yuu-blog.oss-cn-shenzhen.aliyuncs.com/Yuu_20191113104946.png)\n\n### 6. 启动前台 vue 项目\n\n- 确保已安装 `node.js`\n- `npm install` 安装依赖\n- `npm install node-sass` 安装 sass\n- `npm run dev` 运行项目\n\n"
  },
  {
    "path": "pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <groupId>com.yuu</groupId>\n    <artifactId>ymall</artifactId>\n    <version>1.0.0-SNAPSHOT</version>\n    <packaging>pom</packaging>\n\n    <modules>\n        <module>ymall-dependencies</module>\n        <module>ymall-commons</module>\n        <module>ymall-domain</module>\n        <module>ymall-web-admin</module>\n\t\t<module>ymall-web-api</module>\n    </modules>\n</project>"
  },
  {
    "path": "sql/ymall.sql",
    "content": "/*\nSQLyog Ultimate v12.5.0 (64 bit)\nMySQL - 5.5.60 : Database - ymall\n*********************************************************************\n*/\n\n/*!40101 SET NAMES utf8 */;\n\n/*!40101 SET SQL_MODE=''*/;\n\n/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;\n/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;\n/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;\n/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;\nCREATE DATABASE /*!32312 IF NOT EXISTS*/`ymall` /*!40100 DEFAULT CHARACTER SET utf8 */;\n\nUSE `ymall`;\n\n/*Table structure for table `tb_address` */\n\nDROP TABLE IF EXISTS `tb_address`;\n\nCREATE TABLE `tb_address` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '地址编号',\n  `user_id` bigint(20) DEFAULT NULL COMMENT '会员编号',\n  `user_name` varchar(255) DEFAULT NULL COMMENT '名称',\n  `tel` varchar(255) DEFAULT NULL COMMENT '电话',\n  `street_name` varchar(255) DEFAULT NULL COMMENT '地址详细信息',\n  `is_default` tinyint(1) DEFAULT NULL COMMENT '是否为默认地址',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;\n\n/*Data for the table `tb_address` */\n\ninsert  into `tb_address`(`id`,`user_id`,`user_name`,`tel`,`street_name`,`is_default`) values \n(14,78,'Yuu','13055206361','福建省厦门市集美区集美大学诚毅学院',0),\n(15,78,'杨雨衡','13055206361','福建省厦门市集美区集美大学诚毅学院',1);\n\n/*Table structure for table `tb_express` */\n\nDROP TABLE IF EXISTS `tb_express`;\n\nCREATE TABLE `tb_express` (\n  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '快递编号',\n  `express_name` varchar(255) DEFAULT NULL COMMENT '快递名称',\n  `sort_order` int(11) DEFAULT NULL COMMENT '排序值',\n  `created` datetime DEFAULT NULL COMMENT '创建时间',\n  `updated` datetime DEFAULT NULL COMMENT '更新时间',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8 COMMENT='商品描述表';\n\n/*Data for the table `tb_express` */\n\ninsert  into `tb_express`(`id`,`express_name`,`sort_order`,`created`,`updated`) values \n(4,'顺丰快递',1,'2019-07-10 11:05:50','2019-07-10 11:05:50'),\n(5,'中通快递',2,'2019-07-10 11:05:58','2019-07-10 11:05:58'),\n(6,'韵达快递',3,'2019-07-10 11:06:05','2019-07-10 11:06:05'),\n(7,'申通快递',4,'2019-07-10 11:06:15','2019-07-10 11:06:15'),\n(8,'Y速运',0,'2019-07-10 11:06:26','2019-07-10 11:06:26');\n\n/*Table structure for table `tb_item` */\n\nDROP TABLE IF EXISTS `tb_item`;\n\nCREATE TABLE `tb_item` (\n  `id` bigint(20) NOT NULL COMMENT '商品编号',\n  `title` varchar(100) DEFAULT NULL COMMENT '商品标题',\n  `sell_point` varchar(100) DEFAULT NULL COMMENT '商品卖点',\n  `price` decimal(10,2) DEFAULT '0.00' COMMENT '商品价格',\n  `num` int(11) DEFAULT NULL COMMENT '库存数量',\n  `limit_num` int(11) DEFAULT NULL COMMENT '售卖数量限制',\n  `image` varchar(2000) DEFAULT NULL COMMENT '商品图片',\n  `cid` bigint(11) DEFAULT NULL COMMENT '所属分类',\n  `status` int(1) DEFAULT '1' COMMENT '商品状态 1正常 0下架',\n  `created` datetime DEFAULT NULL COMMENT '创建时间',\n  `updated` datetime DEFAULT NULL COMMENT '更新时间',\n  PRIMARY KEY (`id`),\n  KEY `cid` (`cid`),\n  KEY `status` (`status`),\n  KEY `updated` (`updated`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';\n\n/*Data for the table `tb_item` */\n\ninsert  into `tb_item`(`id`,`title`,`sell_point`,`price`,`num`,`limit_num`,`image`,`cid`,`status`,`created`,`updated`) values \n(156268231822963,'HUAWEI P30 Pro 麒麟980 超感光徕卡四摄 屏内指纹 双景录像 ','8GB+128GB 全网通版（天空之境）',5488.00,999,10,'http://pub7lsomw.bkt.clouddn.com/FpKQOpEUgDUuda0qObUovy454Ubd,http://pub7lsomw.bkt.clouddn.com/FkdP5QRm_0H3abio19Aie39RRF9j,http://pub7lsomw.bkt.clouddn.com/Fux2wRIMI1HDFm42BKro3J5V1-8p,http://pub7lsomw.bkt.clouddn.com/Fqg2ASg782ZQOlwZKC2z_-ukbNYD,http://pub7lsomw.bkt.clouddn.com/FptgIlZ-ukR4_XAxl5Pg5iUaDw6T',1235,1,'2019-07-09 22:25:18','2019-07-09 22:48:06'),\n(156268365230771,'HUAWEI nova 5 8GB+128GB 全网通版','【nova 5新品将于7.13日开始预订，7.20日首销，敬请期待】',2799.00,999,5,'http://pub7lsomw.bkt.clouddn.com/FnK_JTCL57pocGQVz-Zp20HGNvqW,http://pub7lsomw.bkt.clouddn.com/Fr_aVXduBnaInGL7s4f-i43vgAiM,http://pub7lsomw.bkt.clouddn.com/Fjt_DKhvAo4Xwj3yNXT7k5LIHOYi,http://pub7lsomw.bkt.clouddn.com/FsHn1FemvV1hGiHyFhPRtcqcSEWa,http://pub7lsomw.bkt.clouddn.com/Fs2_dvgllnhG-4Vr2-dpFO8x371_',1247,1,'2019-07-09 22:47:32','2019-07-09 23:02:50'),\n(156269705828174,'荣耀Note10 全网通 6GB+64GB 幻影蓝 AMOLED全面屏手机 AI智能 GT游戏加速 双卡双待 长续航','【到手价1899】①限时优惠900元②享3期/6期免息； 麒麟970AI芯片|液冷双Turbo|6.95英寸全面屏',1899.00,999,20,'http://pub7lsomw.bkt.clouddn.com/FvQQ7z7CmNs_RCAW0cundgE6Ho9S,http://pub7lsomw.bkt.clouddn.com/Fl5RdjBWrM2HYgCClA8IMZo9HXq0,http://pub7lsomw.bkt.clouddn.com/Ft9LWvfh6c-VTQe2VX2iDzW_Wno7,http://pub7lsomw.bkt.clouddn.com/FmZY-Du13VkJIC-ul_JHtXRGtVFJ,http://pub7lsomw.bkt.clouddn.com/FmTwXP4qzFIMqzwYYU2XTPGqJdS2',1234,1,'2019-07-10 02:30:58','2019-07-10 02:57:49'),\n(156269945407026,'荣耀8X Max 骁龙660 7.12英寸高屏占比珍珠屏 5000mAh大电池 全网通 6GB+64GB（魅海蓝）',' 7.12英寸90%屏占比珍珠屏 随身影院 5000mAh大电池',1399.00,998,20,'http://pub7lsomw.bkt.clouddn.com/FtUbjDFl4PJtNwALeVNgve9QcnIv,http://pub7lsomw.bkt.clouddn.com/FhyzRQUYRw6PaV-wE1Cz0vlmkR8s,http://pub7lsomw.bkt.clouddn.com/FsgkuYsYjhVFQ4wyi8DzZSHln27f,http://pub7lsomw.bkt.clouddn.com/FkkXEzlxkGgCPhQnlDEpCQDulQgJ,http://pub7lsomw.bkt.clouddn.com/FnHh-OAB9C9IxjWl75SlhQm3-VTE',1234,1,'2019-07-10 03:10:54','2019-07-10 03:20:31'),\n(156271863486747,'荣耀10青春版 幻彩渐变 2400万AI自拍 6.21英寸高屏占比珍珠屏 全网通 4GB+64GB（渐变蓝）','优惠300，成交价1099！',1099.00,999,10,'http://pub7lsomw.bkt.clouddn.com/FsD8plGUl9aSSTEobuQsewLd4l8e,http://pub7lsomw.bkt.clouddn.com/FpjsmsV6g0c2h08Azl6-MujgtTFX,http://pub7lsomw.bkt.clouddn.com/FmideoIREC0_50lxsxI7umVYVag6,http://pub7lsomw.bkt.clouddn.com/Fm87xVbflJUQw7c33EiDsfLmjcFD,http://pub7lsomw.bkt.clouddn.com/FgzUwHgH46jz7fxPJKLtpEHvNipZ',1234,1,'2019-07-10 08:30:34','2019-07-10 08:30:34'),\n(156271954394859,'HUAWEI Mate 20 X 6GB+128GB 全网通版（宝石蓝）','麒麟980新一代人工智能芯片，4000万超大广角徕卡三摄，5000mAh大电池，石墨烯液冷散热技术加持旗舰手机',4099.00,999,10,'http://pub7lsomw.bkt.clouddn.com/FujL3yUs0vkqKYiz70Kewx5Wm6G-,http://pub7lsomw.bkt.clouddn.com/Fj6xJ3l-WqDh-EM6mEBXw9PKJNu-,http://pub7lsomw.bkt.clouddn.com/Ft0mfQuRx8-OK3ON2MFi18XzSP_E,http://pub7lsomw.bkt.clouddn.com/FoKCzHlOBv3PhUqBg5y03ZyEZuT4,http://pub7lsomw.bkt.clouddn.com/FoJpbDfzSNjxJtIBD347z6V0vYXn',1248,1,'2019-07-10 08:45:43','2019-07-10 08:45:43'),\n(156272085015807,'荣耀Magic2 魔法全视屏 麒麟980AI芯片 屏内指纹 超广角AI三摄 全网通 6GB+128GB 渐变黑','麒麟980 AI处理器，后置2400万 AI三摄，40W安全超级快充。',2499.00,999,10,'http://pub7lsomw.bkt.clouddn.com/FvaioHuROssa58-WubEN6RzsLkMX,http://pub7lsomw.bkt.clouddn.com/Fl2yKYN91x7MYP-1-mMS-zU5ihQK,http://pub7lsomw.bkt.clouddn.com/FjrY2auIZ6F2W3SUBXcKXnd57YAf,http://pub7lsomw.bkt.clouddn.com/Fob962hE38xjhuGuT90OkzNGSkVi,http://pub7lsomw.bkt.clouddn.com/FvnIfbbBJBCTTjEjWljJKUHh-_Dh',1234,1,'2019-07-10 09:07:30','2019-07-10 09:07:30'),\n(156272096620228,'HUAWEI nova 4 4800万超广角三摄 自拍极点全面屏 高配 8GB+128GB 全网通版（蜜语红·星耀版）',' 6.4英寸极点全面屏，4800万超广角三摄，2500万海报级自拍，AI微塑美颜，来电视频铃声，AI视频专家自动剪辑主角故事。',2799.00,998,10,'http://pub7lsomw.bkt.clouddn.com/Fo2lgi24IsyTcUy8Vzx_6-PHNI33,http://pub7lsomw.bkt.clouddn.com/Fi6ZLAkm362MZvqug0WKpODNvr1d,http://pub7lsomw.bkt.clouddn.com/FviVJduugrDkGigsVP89taEFpKvP,http://pub7lsomw.bkt.clouddn.com/FmHIIRxJnBXkz-EYUM_iYcEjuDig,http://pub7lsomw.bkt.clouddn.com/FjE__GdtP-aEWYKFkrjkttdO0ccY',1247,1,'2019-07-10 09:09:26','2019-07-10 09:09:26'),\n(156272121662666,'荣耀畅玩8A 6.09英寸珍珠全面屏 震撼大音量 标配版 全网通 3GB+32GB（幻夜黑）','【到手价：749元】①下单立减50！②送原厂手机壳 ③晒单抽奖赢好礼！④送超值券包',799.00,998,10,'http://pub7lsomw.bkt.clouddn.com/FjkGpyu7wzBeRD0Sb3ePgNk3y9sl,http://pub7lsomw.bkt.clouddn.com/FgMuNXTHEhhzgvoUx0e9M_Sxqvlx,http://pub7lsomw.bkt.clouddn.com/FnX606l3BbD1I7zHYSrGIglfT68U,http://pub7lsomw.bkt.clouddn.com/FpowJ1Pd24F2Qv45QSmy4Nabb0Vw,http://pub7lsomw.bkt.clouddn.com/FtRWHvpISqVRUFM3YptPzYCXRYyz',1249,1,'2019-07-10 09:13:36','2019-07-10 09:13:36'),\n(156272133543147,'HUAWEI nova 4e 3200万立体美颜 AI超广角三摄 4GB+128GB 全网通版（雀翎蓝）',' 3200万立体美颜，AI超广角三摄，3D曲面玻璃，128GB大内存',1799.00,999,10,'http://pub7lsomw.bkt.clouddn.com/FtExSRPJRGsDXEDLFjly_ZMjSljI,http://pub7lsomw.bkt.clouddn.com/FtB2HlS25f9-9jPu0AYQIkPYboyM,http://pub7lsomw.bkt.clouddn.com/Fp_aY2PfiNtscRLclwKXcr75KldO,http://pub7lsomw.bkt.clouddn.com/FoL7ZyfaY7WjM9tUMDUjUePikz-Y',1247,1,'2019-07-10 09:15:35','2019-07-10 09:15:35');\n\n/*Table structure for table `tb_item_cat` */\n\nDROP TABLE IF EXISTS `tb_item_cat`;\n\nCREATE TABLE `tb_item_cat` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '分类编号',\n  `parent_id` bigint(20) DEFAULT NULL COMMENT '父分类ID=0时代表一级根分类',\n  `name` varchar(50) DEFAULT NULL COMMENT '分类名称',\n  `status` int(1) DEFAULT '1' COMMENT '状态 1启用 0禁用',\n  `sort_order` int(4) DEFAULT NULL COMMENT '排列序号',\n  `is_parent` tinyint(1) DEFAULT '1' COMMENT '是否为父分类 1为true 0为false',\n  `created` datetime DEFAULT NULL COMMENT '创建时间',\n  `updated` datetime DEFAULT NULL COMMENT '更新时间',\n  PRIMARY KEY (`id`),\n  KEY `parent_id` (`parent_id`,`status`) USING BTREE,\n  KEY `sort_order` (`sort_order`)\n) ENGINE=InnoDB AUTO_INCREMENT=1250 DEFAULT CHARSET=utf8 COMMENT='商品类目';\n\n/*Data for the table `tb_item_cat` */\n\ninsert  into `tb_item_cat`(`id`,`parent_id`,`name`,`status`,`sort_order`,`is_parent`,`created`,`updated`) values \n(-1,0,'所有商品',1,0,1,'2019-07-09 17:08:00','2019-07-09 17:08:03'),\n(1214,0,'手机',1,1,1,'2019-07-09 17:08:56','2019-07-09 17:08:56'),\n(1221,0,'笔记本&平板',1,2,1,NULL,'2019-07-09 22:05:38'),\n(1234,1214,'荣耀系列',1,1,0,NULL,'2019-07-10 08:42:54'),\n(1235,1214,'HUAWEI P系列',1,2,0,'2019-07-09 22:06:15','2019-07-09 22:06:15'),\n(1236,1221,'平板电脑',1,1,0,'2019-07-09 22:07:10','2019-07-09 22:07:10'),\n(1237,1221,'笔记本电脑',1,2,0,'2019-07-09 22:07:21','2019-07-09 22:07:21'),\n(1238,1221,'笔记本配件',1,3,0,'2019-07-09 22:07:30','2019-07-09 22:07:30'),\n(1239,0,'智能穿戴',1,3,1,'2019-07-09 22:07:43','2019-07-09 22:07:43'),\n(1240,1239,'手环',1,1,0,'2019-07-09 22:07:52','2019-07-09 22:07:52'),\n(1241,1239,'电视盒子',1,2,0,'2019-07-09 22:07:58','2019-07-09 22:07:58'),\n(1242,1239,'照明',1,3,0,'2019-07-09 22:08:06','2019-07-09 22:08:06'),\n(1243,0,'热销配件',1,4,1,'2019-07-09 22:08:13','2019-07-09 22:08:13'),\n(1244,1243,'保护壳',1,1,0,'2019-07-09 22:08:20','2019-07-09 22:08:20'),\n(1245,1243,'移动电源',1,2,0,'2019-07-09 22:08:26','2019-07-09 22:08:26'),\n(1246,1243,'耳机',1,3,0,NULL,'2019-07-09 22:08:39'),\n(1247,1214,'HUAWEI nova系列',1,3,0,NULL,'2019-07-10 09:17:22'),\n(1248,1214,'Mate 系列',1,4,0,'2019-07-10 08:42:50','2019-07-10 08:42:50'),\n(1249,1214,'畅玩系列',1,5,0,'2019-07-10 09:10:33','2019-07-10 09:10:33');\n\n/*Table structure for table `tb_item_desc` */\n\nDROP TABLE IF EXISTS `tb_item_desc`;\n\nCREATE TABLE `tb_item_desc` (\n  `item_id` bigint(20) NOT NULL COMMENT '商品编号',\n  `item_desc` text COMMENT '商品描述',\n  `created` datetime DEFAULT NULL COMMENT '创建时间',\n  `updated` datetime DEFAULT NULL COMMENT '更新时间',\n  PRIMARY KEY (`item_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品描述表';\n\n/*Data for the table `tb_item_desc` */\n\ninsert  into `tb_item_desc`(`item_id`,`item_desc`,`created`,`updated`) values \n(156266413524759,'<p><img style=\\\"max-width:100%;\\\" src=\\\"http://pub7lsomw.bkt.clouddn.com/FgFzGQ1ErxI8TVxfo4cAZu1RcWOR\\\"><img style=\\\"max-width:100%;\\\" src=\\\"http://pub7lsomw.bkt.clouddn.com/FpNugyQTtHpVDW3O1xhCVCzl9RHx\\\"></p><p><img style=\\\"max-width:100%;\\\" src=\\\"http://pub7lsomw.bkt.clouddn.com/FnkZDuiG2tnliVWV3SwFw2PmGqGQ\\\"><img style=\\\"max-width:100%;\\\" src=\\\"http://pub7lsomw.bkt.clouddn.com/Fv0NQMvATI6YQ1DFx4B7I7W2bXtd\\\"><img style=\\\"max-width:100%;\\\" src=\\\"http://pub7lsomw.bkt.clouddn.com/FjwOrCdiGXcmDRhWwat2qNa_ugse\\\"><img style=\\\"max-width:100%;\\\" src=\\\"http://pub7lsomw.bkt.clouddn.com/Fn6LkE_1EfkofRvMqydkCUKooFIu\\\"><img style=\\\"max-width:100%;\\\" src=\\\"http://pub7lsomw.bkt.clouddn.com/Fn0U9WORRsWsoNf_1Ij014BX9CZD\\\"><img style=\\\"max-width:100%;\\\" src=\\\"http://pub7lsomw.bkt.clouddn.com/FqUcMZB5bZJtYhtc0WLFN42gRtG2\\\"><img style=\\\"max-width:100%;\\\" src=\\\"http://pub7lsomw.bkt.clouddn.com/FqdPmUqxC_z60aDCqzrzrrBV7uW6\\\"><b></b><i></i><u></u><sub></sub><sup></sup><strike></strike><br></p>','2019-07-09 17:22:15','2019-07-09 17:25:47'),\n(156267056226257,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/FsQ0_KGIHunwcub4kUmg-qZBNbrg\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-09 19:09:22','2019-07-09 20:51:29'),\n(156267834403843,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/FsU-MGJ1Rn-_DyDR-igw3dqROkaj\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-09 21:19:04','2019-07-09 21:24:27'),\n(156267929355630,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/FnXJRoKBdVPqpLh0N6xl25OmW7Uq\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-09 21:34:55','2019-07-09 21:39:00'),\n(156268007938096,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/FpbBVoRbk0C3V-yRzlivAb4hAcaI\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-09 21:47:59','2019-07-09 22:04:24'),\n(156268231822963,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/FsU-MGJ1Rn-_DyDR-igw3dqROkaj\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-09 22:25:18','2019-07-09 22:48:06'),\n(156268365230771,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/lgepvbcpxvKr47jm-vpKEklJfLwJ\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-09 22:47:32','2019-07-09 23:02:50'),\n(156269705828174,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/ljWozpWDNgoQxU7Rr_Dx9EA8jows\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-10 02:30:58','2019-07-10 02:57:49'),\n(156269945407026,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/lt48nkiYdkXFMG65rWkW1JMqf9Uw\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-10 03:10:54','2019-07-10 03:20:31'),\n(156271863486747,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/lvtRbvNgr22sNouj9Hyidp6WGnJG\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-10 08:30:34','2019-07-10 08:30:34'),\n(156271954394859,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/FujL3yUs0vkqKYiz70Kewx5Wm6G-\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-10 08:45:43','2019-07-10 08:45:43'),\n(156272085015807,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/FvaioHuROssa58-WubEN6RzsLkMX\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-10 09:07:30','2019-07-10 09:07:30'),\n(156272096620228,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/Fo2lgi24IsyTcUy8Vzx_6-PHNI33\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-10 09:09:26','2019-07-10 09:09:26'),\n(156272121662666,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/FjkGpyu7wzBeRD0Sb3ePgNk3y9sl\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-10 09:13:36','2019-07-10 09:13:36'),\n(156272133543147,'<p><img src=\\\"http://pub7lsomw.bkt.clouddn.com/FtExSRPJRGsDXEDLFjly_ZMjSljI\\\" style=\\\"max-width:100%;\\\"><br></p>','2019-07-10 09:15:35','2019-07-10 09:15:35');\n\n/*Table structure for table `tb_member` */\n\nDROP TABLE IF EXISTS `tb_member`;\n\nCREATE TABLE `tb_member` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '会员编号',\n  `username` varchar(50) DEFAULT NULL COMMENT '用户名',\n  `password` varchar(32) NOT NULL COMMENT '密码，加密存储',\n  `phone` varchar(20) DEFAULT NULL COMMENT '注册手机号',\n  `email` varchar(50) DEFAULT NULL COMMENT '注册邮箱',\n  `sex` varchar(2) DEFAULT NULL COMMENT '性别',\n  `state` int(1) DEFAULT '0' COMMENT '会员状态 1正常 2封禁',\n  `file` varchar(255) DEFAULT 'https://yuu-1257159061.cos.ap-guangzhou.myqcloud.com/ymall/default-user-avatar.png' COMMENT '头像',\n  `description` varchar(500) DEFAULT NULL COMMENT '会员描述',\n  `created` datetime DEFAULT NULL COMMENT '创建时间',\n  `updated` datetime DEFAULT NULL COMMENT '更新时间',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `phone` (`phone`) USING BTREE,\n  UNIQUE KEY `email` (`email`) USING BTREE,\n  KEY `username` (`username`)\n) ENGINE=InnoDB AUTO_INCREMENT=79 DEFAULT CHARSET=utf8 COMMENT='用户表';\n\n/*Data for the table `tb_member` */\n\ninsert  into `tb_member`(`id`,`username`,`password`,`phone`,`email`,`sex`,`state`,`file`,`description`,`created`,`updated`) values \n(78,NULL,'93bb7f2ba5d3d4be1af978726b97b4be','13055206361',NULL,NULL,1,'http://pub7lsomw.bkt.clouddn.com/1562726657635.png',NULL,'2019-07-10 10:38:34','2019-07-10 10:38:34');\n\n/*Table structure for table `tb_order` */\n\nDROP TABLE IF EXISTS `tb_order`;\n\nCREATE TABLE `tb_order` (\n  `id` varchar(50) COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '订单编号',\n  `payment` decimal(10,2) DEFAULT NULL COMMENT '实付金额',\n  `payment_type` int(1) DEFAULT NULL COMMENT '支付类型 1在线支付 2货到付款',\n  `post_fee` decimal(10,2) DEFAULT NULL COMMENT '邮费',\n  `status` int(1) DEFAULT NULL COMMENT '状态 0未付款 1已付款 2未发货 3已发货 4交易成功 5交易关闭 6交易失败',\n  `payment_time` datetime DEFAULT NULL COMMENT '付款时间',\n  `consign_time` datetime DEFAULT NULL COMMENT '发货时间',\n  `end_time` datetime DEFAULT NULL COMMENT '交易完成时间',\n  `close_time` datetime DEFAULT NULL COMMENT '交易关闭时间',\n  `shipping_name` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流名称',\n  `shipping_code` varchar(20) COLLATE utf8_bin DEFAULT NULL COMMENT '物流单号',\n  `user_id` bigint(20) DEFAULT NULL COMMENT '会员编号',\n  `buyer_message` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '买家留言',\n  `buyer_nick` varchar(50) COLLATE utf8_bin DEFAULT NULL COMMENT '买家昵称',\n  `buyer_comment` tinyint(1) DEFAULT NULL COMMENT '买家是否已经评价',\n  `created` datetime DEFAULT NULL COMMENT '订单创建时间',\n  `updated` datetime DEFAULT NULL COMMENT '订单更新时间',\n  PRIMARY KEY (`id`),\n  KEY `buyer_nick` (`buyer_nick`),\n  KEY `status` (`status`),\n  KEY `payment_type` (`payment_type`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n/*Data for the table `tb_order` */\n\ninsert  into `tb_order`(`id`,`payment`,`payment_type`,`post_fee`,`status`,`payment_time`,`consign_time`,`end_time`,`close_time`,`shipping_name`,`shipping_code`,`user_id`,`buyer_message`,`buyer_nick`,`buyer_comment`,`created`,`updated`) values \n('156272657441294',9195.00,NULL,NULL,4,NULL,NULL,NULL,NULL,NULL,NULL,78,NULL,'13055206361',NULL,'2019-07-10 10:42:54','2019-07-10 10:42:54');\n\n/*Table structure for table `tb_order_item` */\n\nDROP TABLE IF EXISTS `tb_order_item`;\n\nCREATE TABLE `tb_order_item` (\n  `id` varchar(20) COLLATE utf8_bin NOT NULL,\n  `item_id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '商品id',\n  `order_id` varchar(50) COLLATE utf8_bin NOT NULL COMMENT '订单id',\n  `num` int(10) DEFAULT NULL COMMENT '商品购买数量',\n  `title` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '商品标题',\n  `price` decimal(10,2) DEFAULT NULL COMMENT '商品单价',\n  `total_fee` decimal(10,2) DEFAULT NULL COMMENT '商品总金额',\n  `pic_path` varchar(1000) COLLATE utf8_bin DEFAULT NULL COMMENT '商品图片地址',\n  PRIMARY KEY (`id`),\n  KEY `item_id` (`item_id`),\n  KEY `order_id` (`order_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;\n\n/*Data for the table `tb_order_item` */\n\ninsert  into `tb_order_item`(`id`,`item_id`,`order_id`,`num`,`title`,`price`,`total_fee`,`pic_path`) values \n('156272657442857','156272121662666','156272657441294',1,'荣耀畅玩8A 6.09英寸珍珠全面屏 震撼大音量 标配版 全网通 3GB+32GB（幻夜黑）',799.00,799.00,'http://pub7lsomw.bkt.clouddn.com/FjkGpyu7wzBeRD0Sb3ePgNk3y9sl'),\n('156272657444263','156272096620228','156272657441294',1,'HUAWEI nova 4 4800万超广角三摄 自拍极点全面屏 高配 8GB+128GB 全网通版（蜜语红·星耀版）',2799.00,2799.00,'http://pub7lsomw.bkt.clouddn.com/Fo2lgi24IsyTcUy8Vzx_6-PHNI33'),\n('156272657444438','156269945407026','156272657441294',2,'荣耀8X Max 骁龙660 7.12英寸高屏占比珍珠屏 5000mAh大电池 全网通 6GB+64GB（魅海蓝）',1399.00,2798.00,'http://pub7lsomw.bkt.clouddn.com/FtUbjDFl4PJtNwALeVNgve9QcnIv'),\n('156272657444678','156268365230771','156272657441294',1,'HUAWEI nova 5 8GB+128GB 全网通版',2799.00,2799.00,'http://pub7lsomw.bkt.clouddn.com/FnK_JTCL57pocGQVz-Zp20HGNvqW');\n\n/*Table structure for table `tb_order_shipping` */\n\nDROP TABLE IF EXISTS `tb_order_shipping`;\n\nCREATE TABLE `tb_order_shipping` (\n  `order_id` varchar(50) NOT NULL COMMENT '订单ID',\n  `receiver_name` varchar(20) DEFAULT NULL COMMENT '收货人全名',\n  `receiver_phone` varchar(20) DEFAULT NULL COMMENT '固定电话',\n  `receiver_mobile` varchar(30) DEFAULT NULL COMMENT '移动电话',\n  `receiver_province` varchar(10) DEFAULT NULL COMMENT '省份',\n  `receiver_city` varchar(10) DEFAULT NULL COMMENT '城市',\n  `receiver_district` varchar(20) DEFAULT NULL COMMENT '区/县',\n  `receiver_address` varchar(200) DEFAULT NULL COMMENT '收货地址，如：xx路xx号',\n  `receiver_zip` varchar(6) DEFAULT NULL COMMENT '邮政编码,如：310001',\n  `created` datetime DEFAULT NULL COMMENT '创建时间',\n  `updated` datetime DEFAULT NULL COMMENT '更新时间',\n  PRIMARY KEY (`order_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8;\n\n/*Data for the table `tb_order_shipping` */\n\ninsert  into `tb_order_shipping`(`order_id`,`receiver_name`,`receiver_phone`,`receiver_mobile`,`receiver_province`,`receiver_city`,`receiver_district`,`receiver_address`,`receiver_zip`,`created`,`updated`) values \n('156272657441294','杨雨衡','13055206361',NULL,NULL,NULL,NULL,'福建省厦门市集美区集美大学诚毅学院',NULL,'2019-07-10 10:42:54','2019-07-10 10:42:54');\n\n/*Table structure for table `tb_panel` */\n\nDROP TABLE IF EXISTS `tb_panel`;\n\nCREATE TABLE `tb_panel` (\n  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '类目ID',\n  `name` varchar(50) DEFAULT NULL COMMENT '板块名称',\n  `type` int(1) DEFAULT NULL COMMENT '类型 0轮播图 1板块种类一 2板块种类二 3板块种类三 ',\n  `sort_order` int(4) DEFAULT NULL COMMENT '排列序号',\n  `position` int(1) DEFAULT NULL COMMENT '所属位置 0首页 1商品推荐 2我要捐赠',\n  `limit_num` int(4) DEFAULT NULL COMMENT '板块限制商品数量',\n  `status` int(1) DEFAULT '1' COMMENT '状态',\n  `created` datetime DEFAULT NULL COMMENT '创建时间',\n  `updated` datetime DEFAULT NULL COMMENT '更新时间',\n  PRIMARY KEY (`id`),\n  KEY `parent_id` (`status`) USING BTREE,\n  KEY `sort_order` (`sort_order`)\n) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COMMENT='内容分类';\n\n/*Data for the table `tb_panel` */\n\ninsert  into `tb_panel`(`id`,`name`,`type`,`sort_order`,`position`,`limit_num`,`status`,`created`,`updated`) values \n(11,'轮播图',0,0,0,5,1,'2019-07-09 17:00:00','2019-07-09 17:00:00'),\n(12,'活动板块1',1,1,0,4,1,'2019-07-09 18:56:18','2019-07-09 18:56:18'),\n(13,'热销单品',2,2,0,4,1,NULL,'2019-07-09 23:28:48'),\n(14,'精品推荐',3,3,0,8,1,NULL,'2019-07-10 00:10:52'),\n(15,'手机',3,4,0,8,1,NULL,'2019-07-10 00:10:59'),\n(16,'精品平板',3,6,0,8,1,NULL,'2019-07-10 00:37:49'),\n(17,'笔记本电脑',3,5,0,8,1,NULL,'2019-07-10 00:47:24'),\n(18,'智能穿戴',3,7,0,7,1,NULL,'2019-07-10 00:53:54'),\n(19,'智能家居',3,8,0,7,1,NULL,'2019-07-10 00:54:14'),\n(20,'热销配件',3,9,0,7,1,NULL,'2019-07-10 00:54:19'),\n(21,'生态精品',3,10,0,7,1,NULL,'2019-07-10 00:54:21'),\n(22,'精选配件',3,11,0,7,1,NULL,'2019-07-10 00:54:24');\n\n/*Table structure for table `tb_panel_content` */\n\nDROP TABLE IF EXISTS `tb_panel_content`;\n\nCREATE TABLE `tb_panel_content` (\n  `id` int(11) NOT NULL AUTO_INCREMENT,\n  `panel_id` int(11) NOT NULL COMMENT '所属板块id',\n  `type` int(1) DEFAULT NULL COMMENT '类型 0关联商品 1其他链接 2关联商品（封面）3关联商品（封面）',\n  `product_id` bigint(20) DEFAULT NULL COMMENT '关联商品id',\n  `sort_order` int(4) DEFAULT NULL COMMENT '排序值',\n  `full_url` varchar(500) DEFAULT NULL COMMENT '其他链接',\n  `pic_url` varchar(500) DEFAULT NULL COMMENT '图片',\n  `pic_url2` varchar(500) DEFAULT NULL COMMENT '3d轮播图备用',\n  `pic_url3` varchar(500) DEFAULT NULL COMMENT '3d轮播图备用',\n  `created` datetime DEFAULT NULL COMMENT '创建时间',\n  `updated` datetime DEFAULT NULL COMMENT '更新时间',\n  PRIMARY KEY (`id`),\n  KEY `category_id` (`panel_id`),\n  KEY `updated` (`updated`)\n) ENGINE=InnoDB AUTO_INCREMENT=158 DEFAULT CHARSET=utf8;\n\n/*Data for the table `tb_panel_content` */\n\ninsert  into `tb_panel_content`(`id`,`panel_id`,`type`,`product_id`,`sort_order`,`full_url`,`pic_url`,`pic_url2`,`pic_url3`,`created`,`updated`) values \n(78,11,0,156268231822963,1,'','http://pub7lsomw.bkt.clouddn.com/FgboEB3GoUaOhhVVrV2iUs_0j4rd',NULL,NULL,NULL,'2019-07-09 22:30:02'),\n(79,11,0,156268365230771,2,'','http://pub7lsomw.bkt.clouddn.com/FmRYkuEFYde6xI-dDcXqsOfSKK3o',NULL,NULL,'2019-07-09 22:48:34','2019-07-09 22:48:34'),\n(80,12,0,156268365230771,1,'','http://pub7lsomw.bkt.clouddn.com/FnK_JTCL57pocGQVz-Zp20HGNvqW',NULL,NULL,'2019-07-09 23:07:15','2019-07-09 23:07:15'),\n(81,12,0,156268231822963,2,'','http://pub7lsomw.bkt.clouddn.com/FmyoVNNUwRlMq9L65u6rsJnX-_jD',NULL,NULL,'2019-07-09 23:09:56','2019-07-09 23:09:56'),\n(82,12,0,156268365230771,3,'','http://pub7lsomw.bkt.clouddn.com/FtvjyajKpyy6xteuuDeUmVpxkq2z',NULL,NULL,'2019-07-09 23:10:19','2019-07-09 23:10:19'),\n(83,12,0,156268231822963,4,'','http://pub7lsomw.bkt.clouddn.com/FmYF8urf5luGTp7EzETexBMTvAz5',NULL,NULL,'2019-07-09 23:10:31','2019-07-09 23:10:31'),\n(84,13,0,156268365230771,1,'','http://pub7lsomw.bkt.clouddn.com/FurHro4g_v6KrvZVVumIdtD3VRVf',NULL,NULL,'2019-07-09 23:26:27','2019-07-09 23:26:27'),\n(85,13,0,156268365230771,0,'','http://pub7lsomw.bkt.clouddn.com/FmyoVNNUwRlMq9L65u6rsJnX-_jD',NULL,NULL,'2019-07-09 23:27:26','2019-07-09 23:27:26'),\n(86,14,0,156268365230771,1,'','http://pub7lsomw.bkt.clouddn.com/FrekC0IfRuSfFdZMh9pxVdfEWzFI',NULL,NULL,NULL,'2019-07-09 23:51:14'),\n(87,14,0,156268231822963,2,'','http://pub7lsomw.bkt.clouddn.com/FhVtfCRfReyM37ELaa7canqnSDJy',NULL,NULL,'2019-07-09 23:39:49','2019-07-09 23:39:49'),\n(88,14,0,156268231822963,3,'','http://pub7lsomw.bkt.clouddn.com/FuxZbjWZL3g0ZltDwhPGEjju7ynv',NULL,NULL,'2019-07-09 23:40:31','2019-07-09 23:40:31'),\n(89,14,0,156268365230771,4,'','http://pub7lsomw.bkt.clouddn.com/FncB80rXZ6K-549TYrLom-VOQPKb',NULL,NULL,'2019-07-09 23:40:54','2019-07-09 23:40:54'),\n(91,14,0,156268231822963,6,'','http://pub7lsomw.bkt.clouddn.com/FnEmbcH6sDuaBZW47d6hXOFqeUx5',NULL,NULL,'2019-07-09 23:47:20','2019-07-09 23:47:20'),\n(92,14,0,156268365230771,7,'','http://pub7lsomw.bkt.clouddn.com/FtXF9v_EbPcinP4sIQvaAWZq5NxC',NULL,NULL,'2019-07-09 23:47:37','2019-07-09 23:47:37'),\n(93,14,0,156268231822963,0,'','http://pub7lsomw.bkt.clouddn.com/FsTOANA4z23QZDbOnlWijWyeTWOZ',NULL,NULL,NULL,'2019-07-10 00:11:31'),\n(94,15,0,156269705828174,1,'','http://pub7lsomw.bkt.clouddn.com/FiAl6TJLp__NvL8_3f0vbLxUhO03',NULL,NULL,NULL,'2019-07-10 02:58:49'),\n(95,15,0,156271863486747,2,'','http://pub7lsomw.bkt.clouddn.com/FiNn5h9bT1Wg0EDT2bs4ak5wn0G7',NULL,NULL,NULL,'2019-07-10 08:30:46'),\n(96,15,0,156271954394859,3,'','http://pub7lsomw.bkt.clouddn.com/FhmzWEQ5aJxi00lS90199e34YLy7',NULL,NULL,NULL,'2019-07-10 08:46:01'),\n(97,14,0,156268231822963,8,'','http://pub7lsomw.bkt.clouddn.com/FnKW_5yeMQJ7W2plr6Yk7TE-6A5k',NULL,NULL,NULL,'2019-07-10 00:12:27'),\n(98,15,0,156272085015807,4,'','http://pub7lsomw.bkt.clouddn.com/FvaioHuROssa58-WubEN6RzsLkMX',NULL,NULL,NULL,'2019-07-10 09:08:01'),\n(99,15,0,156272096620228,5,'','http://pub7lsomw.bkt.clouddn.com/Fo2lgi24IsyTcUy8Vzx_6-PHNI33',NULL,NULL,NULL,'2019-07-10 09:09:45'),\n(100,15,0,156272121662666,6,'','http://pub7lsomw.bkt.clouddn.com/Fi2cL3eRANv3iMysg3t0DCsqFpH5',NULL,NULL,NULL,'2019-07-10 09:15:47'),\n(101,15,0,156272133543147,7,'','http://pub7lsomw.bkt.clouddn.com/FnEmbcH6sDuaBZW47d6hXOFqeUx5',NULL,NULL,NULL,'2019-07-10 09:15:53'),\n(102,15,0,156269945407026,1,'','http://pub7lsomw.bkt.clouddn.com/FtUbjDFl4PJtNwALeVNgve9QcnIv',NULL,NULL,NULL,'2019-07-10 03:11:13'),\n(103,11,0,156268365230771,3,'','http://pub7lsomw.bkt.clouddn.com/Fn5aIOj1sPy9_HPAyy3Us_CRwmLb',NULL,NULL,'2019-07-10 00:21:52','2019-07-10 00:21:52'),\n(104,11,0,156268365230771,4,'','http://pub7lsomw.bkt.clouddn.com/FpkqZw5MHFGD0iOaP6DwfbCfkiof',NULL,NULL,'2019-07-10 00:22:10','2019-07-10 00:22:10'),\n(105,11,1,NULL,5,'https://www.71yuu.com/','http://pub7lsomw.bkt.clouddn.com/Fka1NhCLE19wPupRlGSSR-UxtD12',NULL,NULL,'2019-07-10 00:22:36','2019-07-10 00:22:36'),\n(106,16,0,156268365230771,1,'','http://pub7lsomw.bkt.clouddn.com/Fkb_AeosFyYNFe_giwHo-Gr2IMv2',NULL,NULL,'2019-07-10 00:27:44','2019-07-10 00:27:44'),\n(107,16,0,156268231822963,2,'','http://pub7lsomw.bkt.clouddn.com/Fh41PYzAklpyqqApDFfCTfYljcab',NULL,NULL,'2019-07-10 00:29:12','2019-07-10 00:29:12'),\n(108,16,0,156268365230771,3,'','http://pub7lsomw.bkt.clouddn.com/Fm4gchBeRRVHvzik8PlHxVk02p5H',NULL,NULL,'2019-07-10 00:31:19','2019-07-10 00:31:19'),\n(109,16,0,156268231822963,4,'','http://pub7lsomw.bkt.clouddn.com/FpA6Nge5X8hMsC4tGz8TkVMrpnQI',NULL,NULL,'2019-07-10 00:32:27','2019-07-10 00:32:27'),\n(110,16,0,156268231822963,5,'','http://pub7lsomw.bkt.clouddn.com/FnGy7u1Mtw9xpin9nbBgxFDT8GsZ',NULL,NULL,'2019-07-10 00:33:54','2019-07-10 00:33:54'),\n(111,16,0,156268365230771,6,'','http://pub7lsomw.bkt.clouddn.com/FlD1YI-YO4n8Sm502c9WeGBbV7sS',NULL,NULL,'2019-07-10 00:34:58','2019-07-10 00:34:58'),\n(112,16,0,156268365230771,7,'','http://pub7lsomw.bkt.clouddn.com/FjsM5dug05E_vzFox7Nh24vxItVI',NULL,NULL,'2019-07-10 00:35:40','2019-07-10 00:35:40'),\n(113,16,0,156268365230771,8,'','http://pub7lsomw.bkt.clouddn.com/FvkKDWnd_dNViTlDYkNEW9qUDDQ7',NULL,NULL,'2019-07-10 00:36:00','2019-07-10 00:36:00'),\n(114,17,0,156268365230771,1,'','http://pub7lsomw.bkt.clouddn.com/FsTUuP-MY2p8_Rtu75yshgLc9HAA',NULL,NULL,'2019-07-10 00:41:47','2019-07-10 00:41:47'),\n(115,17,0,156268365230771,2,'','http://pub7lsomw.bkt.clouddn.com/FsHMvN6Sh5bYfS1hUwDSSUovV1Iz',NULL,NULL,'2019-07-10 00:42:34','2019-07-10 00:42:34'),\n(116,17,0,156268231822963,3,'','http://pub7lsomw.bkt.clouddn.com/Fhq53yhpC8sRp5sYCDCuKMdsxR5x',NULL,NULL,'2019-07-10 00:43:07','2019-07-10 00:43:07'),\n(117,17,0,156268365230771,4,'','http://pub7lsomw.bkt.clouddn.com/FpX5ofiu2JRNceYT1KKfhZEwk5hV',NULL,NULL,'2019-07-10 00:45:14','2019-07-10 00:45:14'),\n(118,17,0,156268365230771,5,'','http://pub7lsomw.bkt.clouddn.com/Fmg1g_m9jvOkI_C0_oZxrEYnjbMk',NULL,NULL,'2019-07-10 00:45:33','2019-07-10 00:45:33'),\n(119,17,0,156268365230771,6,'','http://pub7lsomw.bkt.clouddn.com/FkOP4JouTXsE3XxRcl4Qs3cD70Sa',NULL,NULL,'2019-07-10 00:46:21','2019-07-10 00:46:21'),\n(120,17,0,156268365230771,7,'','http://pub7lsomw.bkt.clouddn.com/FnOZnlOUbVJPZwdDWYyJOGDz5Wao',NULL,NULL,'2019-07-10 00:46:38','2019-07-10 00:46:38'),\n(121,17,0,156268365230771,8,'','http://pub7lsomw.bkt.clouddn.com/FuuLFcc1xLCcOwj5QeyWCA2dfxTl',NULL,NULL,'2019-07-10 00:47:09','2019-07-10 00:47:09'),\n(122,18,2,156268365230771,1,'','http://pub7lsomw.bkt.clouddn.com/FmeWoAGMO4arsC-mswaCRP6Cf2Om',NULL,NULL,NULL,'2019-07-10 00:53:23'),\n(123,18,0,156268231822963,2,'','http://pub7lsomw.bkt.clouddn.com/FjHoRljhhq9JQBcVbH7878v-H7_s',NULL,NULL,'2019-07-10 00:49:51','2019-07-10 00:49:51'),\n(124,18,0,156268365230771,3,'','http://pub7lsomw.bkt.clouddn.com/FmnICU_SGBZTSGCf2ofNz56onMJI',NULL,NULL,'2019-07-10 00:50:34','2019-07-10 00:50:34'),\n(125,18,0,156268365230771,4,'','http://pub7lsomw.bkt.clouddn.com/FhCPEwQhyqSYziYqMekP4EO-9Kfk',NULL,NULL,'2019-07-10 00:51:04','2019-07-10 00:51:04'),\n(126,18,0,156268365230771,5,'','http://pub7lsomw.bkt.clouddn.com/FgelPcSEB2lkd-4t620GUgaAlf4h',NULL,NULL,'2019-07-10 00:51:38','2019-07-10 00:51:38'),\n(127,18,0,156268231822963,6,'','http://pub7lsomw.bkt.clouddn.com/FjAI4QZEHoyvE7jNepqhx3h1zZnJ',NULL,NULL,'2019-07-10 00:52:12','2019-07-10 00:52:12'),\n(128,18,0,156268365230771,7,'','http://pub7lsomw.bkt.clouddn.com/Fg5atYssfQJFLtDJmQzpXByxfWER',NULL,NULL,'2019-07-10 00:52:38','2019-07-10 00:52:38'),\n(130,19,2,156268231822963,1,'','http://pub7lsomw.bkt.clouddn.com/FmPsY2qDUIdQ5mUOyWNz_LDWVLFc',NULL,NULL,'2019-07-10 00:54:59','2019-07-10 00:54:59'),\n(131,19,0,156268365230771,2,'','http://pub7lsomw.bkt.clouddn.com/FrpvBCfcQNauK6z8ntxayEbThtbn',NULL,NULL,'2019-07-10 00:55:15','2019-07-10 00:55:15'),\n(132,19,0,156268365230771,3,'','http://pub7lsomw.bkt.clouddn.com/FhEGelnrvmfRP7LHxYuf3CK7QBAZ',NULL,NULL,'2019-07-10 00:55:31','2019-07-10 00:55:31'),\n(133,19,0,156268365230771,4,'','http://pub7lsomw.bkt.clouddn.com/FgS8KX5kQ43ze3Jrmxqb-OzcHb12',NULL,NULL,'2019-07-10 00:55:45','2019-07-10 00:55:45'),\n(134,19,0,156268365230771,6,'','http://pub7lsomw.bkt.clouddn.com/FjmtIGK_CbH1lWkz1F2IqDROWNrQ',NULL,NULL,'2019-07-10 00:56:07','2019-07-10 00:56:07'),\n(135,19,0,156268365230771,5,'','http://pub7lsomw.bkt.clouddn.com/FgS8KX5kQ43ze3Jrmxqb-OzcHb12',NULL,NULL,'2019-07-10 00:56:25','2019-07-10 00:56:25'),\n(136,19,0,156268365230771,7,'','http://pub7lsomw.bkt.clouddn.com/FkxA9knjUc29Vw-XNYWHnxHzmf6v',NULL,NULL,'2019-07-10 00:56:38','2019-07-10 00:56:38'),\n(137,20,2,156268365230771,1,'','http://pub7lsomw.bkt.clouddn.com/FoYaHbVA1_6fln3Zht2F0SoaMTOj',NULL,NULL,NULL,'2019-07-10 00:58:47'),\n(138,20,0,156268365230771,2,'','http://pub7lsomw.bkt.clouddn.com/Fv9DBHm1MEHEMJhRnmMrW58p45w4',NULL,NULL,'2019-07-10 00:57:22','2019-07-10 00:57:22'),\n(139,20,0,156268365230771,3,'','http://pub7lsomw.bkt.clouddn.com/FlEvT-WvZBjuiHtAwL4QCDWRMVgs',NULL,NULL,'2019-07-10 00:57:33','2019-07-10 00:57:33'),\n(140,20,0,156268365230771,4,'','http://pub7lsomw.bkt.clouddn.com/FrlETSAFEVnIWUvjpUgJcPu_a7AL',NULL,NULL,'2019-07-10 00:57:47','2019-07-10 00:57:47'),\n(141,20,0,156268365230771,5,'','http://pub7lsomw.bkt.clouddn.com/Flrx2EBC2lobY2eJmAeNALZF_BNI',NULL,NULL,'2019-07-10 00:58:01','2019-07-10 00:58:01'),\n(142,20,0,156268365230771,6,'','http://pub7lsomw.bkt.clouddn.com/Ftq4x8X8oSzjNq8c9JTfh_kwUKiY',NULL,NULL,'2019-07-10 00:58:12','2019-07-10 00:58:12'),\n(143,20,0,156268365230771,7,'','http://pub7lsomw.bkt.clouddn.com/Fkd9mlW2K23UooLUsSgL05wggcxN',NULL,NULL,'2019-07-10 00:58:28','2019-07-10 00:58:28'),\n(144,21,2,156268365230771,1,'','http://pub7lsomw.bkt.clouddn.com/Fi8CiUEL5N57JoTFOc4i4mm9AEjO',NULL,NULL,'2019-07-10 00:59:07','2019-07-10 00:59:07'),\n(145,21,0,156268365230771,2,'','http://pub7lsomw.bkt.clouddn.com/FivVNRyn8aNjFpwXbD4nzh_-3qZu',NULL,NULL,'2019-07-10 00:59:29','2019-07-10 00:59:29'),\n(146,21,0,156268365230771,3,'','http://pub7lsomw.bkt.clouddn.com/Foox3uBjTPgWIOjVRDLqWTLRx3bp',NULL,NULL,NULL,'2019-07-10 01:00:11'),\n(147,21,0,156268231822963,4,'','http://pub7lsomw.bkt.clouddn.com/Fttk_HMnMpUy4in9PRxOc7uZjMg5',NULL,NULL,'2019-07-10 01:00:00','2019-07-10 01:00:00'),\n(148,21,0,156268365230771,5,'','http://pub7lsomw.bkt.clouddn.com/FrzmdkpUdoHe32DRog7jafiLff9c',NULL,NULL,'2019-07-10 01:00:28','2019-07-10 01:00:28'),\n(149,21,0,156268365230771,6,'','http://pub7lsomw.bkt.clouddn.com/FrTiUKMvry8N2as8DN6TQfbQUfUW',NULL,NULL,'2019-07-10 01:00:45','2019-07-10 01:00:45'),\n(150,21,0,156268365230771,7,'','http://pub7lsomw.bkt.clouddn.com/Fj8scPW_HBIo4MMJbXQA6ajs5LFF',NULL,NULL,'2019-07-10 01:00:58','2019-07-10 01:00:58'),\n(151,22,2,156268365230771,1,'','http://pub7lsomw.bkt.clouddn.com/FoZIcvdU6vkX2HDAshrG7np_07wY',NULL,NULL,NULL,'2019-07-10 01:02:34'),\n(152,22,0,156268231822963,2,'','http://pub7lsomw.bkt.clouddn.com/FjY39dK5GGIekyCMggPuM1W7LCEA',NULL,NULL,NULL,'2019-07-10 01:02:27'),\n(153,22,0,156268365230771,3,'','http://pub7lsomw.bkt.clouddn.com/Fq9IcTpReMj9SgjEqZX4YSf5HoBO',NULL,NULL,'2019-07-10 01:02:46','2019-07-10 01:02:46'),\n(154,22,0,156268365230771,4,'','http://pub7lsomw.bkt.clouddn.com/FrgJHhcQNf5UyufKhyyBoFDMWeQg',NULL,NULL,'2019-07-10 01:03:00','2019-07-10 01:03:00'),\n(155,22,0,156268231822963,5,'','http://pub7lsomw.bkt.clouddn.com/FurE0pcGxMisGkmxCTrzb8uyAAP3',NULL,NULL,'2019-07-10 01:03:10','2019-07-10 01:03:10'),\n(156,22,0,156268231822963,6,'','http://pub7lsomw.bkt.clouddn.com/Fg02vwvb86oQGOwQgGoxz6DAIEWV',NULL,NULL,'2019-07-10 01:03:19','2019-07-10 01:03:19'),\n(157,22,0,156268365230771,7,'','http://pub7lsomw.bkt.clouddn.com/Fm7d4f9IAx1vb3cPklDh704LvsD1',NULL,NULL,'2019-07-10 01:03:30','2019-07-10 01:03:30');\n\n/*Table structure for table `tb_user` */\n\nDROP TABLE IF EXISTS `tb_user`;\n\nCREATE TABLE `tb_user` (\n  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '管理员编号',\n  `username` varchar(50) NOT NULL COMMENT '用户名',\n  `password` varchar(32) NOT NULL COMMENT '密码 md5加密存储',\n  `created` datetime NOT NULL COMMENT '创建时间',\n  `updated` datetime NOT NULL COMMENT '更新时间',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `username` (`username`) USING BTREE\n) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户表';\n\n/*Data for the table `tb_user` */\n\ninsert  into `tb_user`(`id`,`username`,`password`,`created`,`updated`) values \n(1,'admin','e10adc3949ba59abbe56e057f20f883e','2017-09-05 21:27:54','2017-10-18 22:57:08');\n\n/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;\n/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;\n/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;\n/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;\n"
  },
  {
    "path": "ymall-commons/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.yuu</groupId>\n        <artifactId>ymall-dependencies</artifactId>\n        <version>1.0.0-SNAPSHOT</version>\n        <relativePath>../ymall-dependencies/pom.xml</relativePath>\n    </parent>\n\n    <artifactId>ymall-commons</artifactId>\n    <packaging>jar</packaging>\n\n    <name>ymall-commons</name>\n    <description>General Tool Class</description>\n\n    <dependencies>\n        <!-- Test Begin -->\n        <dependency>\n            <groupId>junit</groupId>\n            <artifactId>junit</artifactId>\n            <version>${junit.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-test</artifactId>\n            <version>${spring.version}</version>\n        </dependency>\n        <!-- Test End -->\n\n        <!-- Commons Begin -->\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-lang3</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.apache.commons</groupId>\n            <artifactId>commons-io</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>commons-net</groupId>\n            <artifactId>commons-net</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>commons-fileupload</groupId>\n            <artifactId>commons-fileupload</artifactId>\n        </dependency>\n        <!-- Commons End -->\n\n        <!-- HttpClient Begin -->\n        <dependency>\n            <groupId>org.apache.httpcomponents</groupId>\n            <artifactId>httpclient</artifactId>\n        </dependency>\n        <!-- HttpClient End -->\n\n        <!-- Jackson Begin -->\n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-databind</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-core</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.fasterxml.jackson.core</groupId>\n            <artifactId>jackson-annotations</artifactId>\n        </dependency>\n        <!-- Jackson End -->\n\n        <!-- Json Begin -->\n        <dependency>\n            <groupId>org.json</groupId>\n            <artifactId>json</artifactId>\n        </dependency>\n        <!-- Json End -->\n\n        <!-- Log Begin-->\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-api</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>slf4j-log4j12</artifactId>\n            <version>${slf4j.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>jcl-over-slf4j</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.slf4j</groupId>\n            <artifactId>jul-to-slf4j</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>log4j</groupId>\n            <artifactId>log4j</artifactId>\n        </dependency>\n        <!-- Log End -->\n\n        <!-- Lombok Begin -->\n        <dependency>\n            <groupId>org.projectlombok</groupId>\n            <artifactId>lombok</artifactId>\n        </dependency>\n        <!-- Lombok End -->\n\n        <!-- Spring Begin -->\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-context</artifactId>\n        </dependency>\n        <!-- Spring End -->\n\n        <!-- AliYun SMS Begin -->\n        <dependency>\n            <groupId>com.aliyun</groupId>\n            <artifactId>aliyun-java-sdk-core</artifactId>\n        </dependency>\n        <!-- AliYun SMS End-->\n\n        <!-- Redis Begin -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.data</groupId>\n            <artifactId>spring-data-redis</artifactId>\n        </dependency>\n        <!-- Redis End -->\n\n        <!-- Elasticsearch Begin-->\n        <dependency>\n            <groupId>org.elasticsearch</groupId>\n            <artifactId>elasticsearch</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.elasticsearch.client</groupId>\n            <artifactId>transport</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.data</groupId>\n            <artifactId>spring-data-elasticsearch</artifactId>\n        </dependency>\n        <!-- Elasticsearch End -->\n    </dependencies>\n\n</project>\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/consts/Consts.java",
    "content": "package com.yuu.ymall.commons.consts;\n\n/**\n * @author by Yuu\n * @classname Consts\n * @date 2019/6/24 16:52\n */\npublic class Consts {\n\n    /**\n     * ####### 会员状态 1 正常，2 封禁\n     */\n\n    /**\n     * 会员状态正常\n     */\n    public static final Integer MEMBER_STATUS_NORMAL = 1;\n\n    /**\n     * 会员状态封禁\n     */\n    public static final Integer MEMBER_STATUS_BAN = 2;\n\n    /**\n     * ###### 订单状态 0 未支付，1 已支付，2 未发货，3 已发货，4 交易成功，5 交易关闭\n     */\n\n    /**\n     * 未支付\n     */\n    public static final Integer ORDER_STATUS_NOPAY = 0;\n\n    /**\n     * 已支付\n     */\n    public static final Integer ORDER_STATUS_PAY = 1;\n\n    /**\n     * 未发货\n     */\n    public static final Integer ORDER_STATUS_NOSEND = 2;\n\n    /**\n     * 已发货\n     */\n    public static final Integer ORDER_STATUS_SEND = 3;\n\n    /**\n     * 交易成功\n     */\n    public static final Integer ORDER_STATUS_SUCCESS = 4;\n\n    /**\n     * 交易关闭\n     */\n    public static final Integer ORDER_STATUS_CLOSE = 5;\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/dto/BaseResult.java",
    "content": "package com.yuu.ymall.commons.dto;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\n\n/**\n * 前后端交互数据标准\n *\n * @Classname BaseResult\n * @Date 2019/5/12 12:25\n * @Created by Yuu\n */\n@Data\npublic class BaseResult implements Serializable {\n    public static final int STATUS_SUCCESS = 200;\n    public static final int STATUS_FALL = 500;\n\n    /**\n     * 返回状态码\n     */\n    private int status;\n\n    /**\n     * 返回消息\n     */\n    private String message;\n\n    /**\n     * 返回数据\n     */\n    private Object result;\n\n    /**\n     * 返回时间\n     */\n    private long timestamp = System.currentTimeMillis();\n\n    /**\n     * 创建返回对象\n     *\n     * @param status 返回状态\n     * @param message 返回消息\n     * @param result  返回数据\n     * @return\n     */\n    private static BaseResult createResult(int status, String message, Object result) {\n        BaseResult baseResult = new BaseResult();\n        baseResult.setStatus(status);\n        baseResult.setMessage(message);\n        baseResult.setResult(result);\n        return baseResult;\n    }\n\n    /**\n     * 默认返回成功方法\n     *\n     * @return\n     */\n    public static BaseResult success() {\n        return BaseResult.createResult(STATUS_SUCCESS, \"成功\", null);\n    }\n\n    /**\n     * 返回成功带消息\n     *\n     * @param message 返回消息\n     * @return\n     */\n    public static BaseResult success(String message) {\n        return BaseResult.createResult(STATUS_SUCCESS, message, null);\n    }\n\n    /**\n     * 返回成功带数据\n     *\n     * @param result 返回数据\n     * @return\n     */\n    public static BaseResult success(Object result) {\n        return BaseResult.createResult(STATUS_SUCCESS, \"成功\", result);\n    }\n\n    /**\n     * 返回成功带消息和数据\n     *\n     * @param message 返回消息\n     * @param result 返回数据\n     * @return\n     */\n    public static BaseResult success(String message, Object result) {\n        return BaseResult.createResult(STATUS_SUCCESS, message, result);\n    }\n\n    /**\n     * 默认返回失败方法\n     *\n     * @return\n     */\n    public static BaseResult fail() {\n       return BaseResult.createResult(STATUS_FALL, \"失败\", null);\n    }\n\n    /**\n     * 返回失败带消息\n     *\n     * @param message 返回消息\n     * @return\n     */\n    public static BaseResult fail(String message) {\n        return BaseResult.createResult(STATUS_FALL, message, null);\n    }\n\n    /**\n     * 返回失败带消息和数据\n     *\n     * @param message 返回消息\n     * @param result 返回数据\n     * @return\n     */\n    public static BaseResult fail(String message, Object result) {\n        return BaseResult.createResult(STATUS_FALL, message, result);\n    }\n\n\n\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/execption/YmallUploadException.java",
    "content": "package com.yuu.ymall.commons.execption;\n\n/**\n * @Classname YMallUploadException\n * @Date 2019/5/24 20:53\n * @Created by Yuu\n */\npublic class YmallUploadException extends RuntimeException {\n\n    private String msg;\n\n    public YmallUploadException(String msg) {\n        this.msg = msg;\n    }\n\n    public String getMsg() {\n        return msg;\n    }\n\n    public void setMsg(String msg) {\n        this.msg = msg;\n    }\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/geetest/GeetInit.java",
    "content": "package com.yuu.ymall.commons.geetest;\n\nimport java.io.Serializable;\n\n/**\n * @author by Yuu\n * @classname GeetInit\n * @date 2019/6/26 8:47\n */\npublic class GeetInit implements Serializable {\n\n    private int success;\n\n    private String challenge;\n\n    private String gt;\n\n    private String statusKey;\n\n    public int getSuccess() {\n        return success;\n    }\n\n    public void setSuccess(int success) {\n        this.success = success;\n    }\n\n    public String getChallenge() {\n        return challenge;\n    }\n\n    public void setChallenge(String challenge) {\n        this.challenge = challenge;\n    }\n\n    public String getGt() {\n        return gt;\n    }\n\n    public void setGt(String gt) {\n        this.gt = gt;\n    }\n\n    public String getStatusKey() {\n        return statusKey;\n    }\n\n    public void setStatusKey(String statusKey) {\n        this.statusKey = statusKey;\n    }\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/geetest/GeetestLib.java",
    "content": "package com.yuu.ymall.commons.geetest;\n\nimport org.json.JSONException;\nimport org.json.JSONObject;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.OutputStreamWriter;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\nimport java.security.MessageDigest;\nimport java.security.NoSuchAlgorithmException;\nimport java.util.HashMap;\n\n/**\n * 极验 SDK\n *\n * @author by Yuu\n * @classname GeetestLib\n * @date 2019/6/26 8:17\n */\npublic class GeetestLib {\n\n    public static final String id = \"33d7d578860c50a433de5a48e55c6b1d\";\n    public static final String key = \"1a92d3aa44daa8e5501cbcf1a6a0ed7f\";\n    public static final boolean newfailback = true;\n\n    protected final String verName = \"4.0\";\n    protected final String sdkLang = \"java\";\n\n    protected final String apiUrl = \"http://api.geetest.com\";\n\n    protected final String registerUrl = \"/register.php\";\n    protected final String validateUrl = \"/validate.php\";\n\n    protected final String json_format = \"1\";\n\n    /**\n     * 极验验证二次验证表单数据 chllenge\n     */\n    public static final String fn_geetest_challenge = \"geetest_challenge\";\n\n    /**\n     * 极验验证二次验证表单数据 validate\n     */\n    public static final String fn_geetest_validate = \"geetest_validate\";\n\n    /**\n     * 极验验证二次验证表单数据 seccode\n     */\n    public static final String fn_geetest_seccode = \"geetest_seccode\";\n\n    /**\n     * 公钥\n     */\n    private String captchaId = \"\";\n\n    /**\n     * 私钥\n     */\n    private String privateKey = \"\";\n\n    /**\n     * 是否开启新的failback\n     */\n    private boolean newFailback = false;\n\n    /**\n     * 返回字符串\n     */\n    private String responseStr = \"\";\n\n    /**\n     * 调试开关，是否输出调试日志\n     */\n    public boolean debugCode = true;\n\n    /**\n     * 极验验证API服务状态Session Key\n     */\n    public String gtServerStatusSessionKey = \"gt_server_status\";\n\n    /**\n     * 带参数构造函数\n     *\n     * @param captchaId\n     * @param privateKey\n     */\n    public GeetestLib(String captchaId, String privateKey, boolean newFailback) {\n\n        this.captchaId = captchaId;\n        this.privateKey = privateKey;\n        this.newFailback = newFailback;\n    }\n\n    /**\n     * 获取本次验证初始化返回字符串\n     *\n     * @return 初始化结果\n     */\n    public String getResponseStr() {\n\n        return responseStr;\n\n    }\n\n    public String getVersionInfo() {\n\n        return verName;\n\n    }\n\n    /**\n     * 预处理失败后的返回格式串\n     *\n     * @return\n     */\n    private String getFailPreProcessRes() {\n\n        Long rnd1 = Math.round(Math.random() * 100);\n        Long rnd2 = Math.round(Math.random() * 100);\n        String md5Str1 = md5Encode(rnd1 + \"\");\n        String md5Str2 = md5Encode(rnd2 + \"\");\n        String challenge = md5Str1 + md5Str2.substring(0, 2);\n\n        JSONObject jsonObject = new JSONObject();\n        try {\n\n            jsonObject.put(\"success\", 0);\n            jsonObject.put(\"gt\", this.captchaId);\n            jsonObject.put(\"challenge\", challenge);\n            jsonObject.put(\"new_captcha\", this.newFailback);\n\n        } catch (JSONException e) {\n\n            gtlog(\"json dumps error\");\n\n        }\n\n        return jsonObject.toString();\n\n    }\n\n    /**\n     * 预处理成功后的标准串\n     *\n     */\n    private String getSuccessPreProcessRes(String challenge) {\n\n        gtlog(\"challenge:\" + challenge);\n\n        JSONObject jsonObject = new JSONObject();\n        try {\n\n            jsonObject.put(\"success\", 1);\n            jsonObject.put(\"gt\", this.captchaId);\n            jsonObject.put(\"challenge\", challenge);\n\n        } catch (JSONException e) {\n\n            gtlog(\"json dumps error\");\n\n        }\n\n        return jsonObject.toString();\n\n    }\n\n    /**\n     * 验证初始化预处理\n     *\n     * @return 1表示初始化成功，0表示初始化失败\n     */\n    public int preProcess(HashMap<String, String> data) {\n\n        if (registerChallenge(data) != 1) {\n\n            this.responseStr = this.getFailPreProcessRes();\n            return 0;\n\n        }\n\n        return 1;\n\n    }\n\n    /**\n     * 用captchaID进行注册，更新challenge\n     *\n     * @return 1表示注册成功，0表示注册失败\n     */\n    private int registerChallenge(HashMap<String, String>data) {\n\n        try {\n            String userId = data.get(\"user_id\");\n            String clientType = data.get(\"client_type\");\n            String ipAddress = data.get(\"ip_address\");\n\n            String getUrl = apiUrl + registerUrl + \"?\";\n            String param = \"gt=\" + this.captchaId + \"&json_format=\" + this.json_format;\n\n            if (userId != null){\n                param = param + \"&user_id=\" + userId;\n            }\n            if (clientType != null){\n                param = param + \"&client_type=\" + clientType;\n            }\n            if (ipAddress != null){\n                param = param + \"&ip_address=\" + ipAddress;\n            }\n\n            gtlog(\"GET_URL:\" + getUrl + param);\n            String result_str = readContentFromGet(getUrl + param);\n            if (result_str == \"fail\"){\n\n                gtlog(\"gtServer register challenge failed\");\n                return 0;\n\n            }\n\n            gtlog(\"result:\" + result_str);\n            JSONObject jsonObject = new JSONObject(result_str);\n            String return_challenge = jsonObject.getString(\"challenge\");\n\n            gtlog(\"return_challenge:\" + return_challenge);\n\n            if (return_challenge.length() == 32) {\n\n                this.responseStr = this.getSuccessPreProcessRes(this.md5Encode(return_challenge + this.privateKey));\n\n                return 1;\n\n            }\n            else {\n\n                gtlog(\"gtServer register challenge error\");\n\n                return 0;\n\n            }\n        } catch (Exception e) {\n\n            gtlog(e.toString());\n            gtlog(\"exception:register api\");\n\n        }\n        return 0;\n    }\n\n    /**\n     * 判断一个表单对象值是否为空\n     *\n     * @param gtObj\n     * @return\n     */\n    protected boolean objIsEmpty(Object gtObj) {\n\n        if (gtObj == null) {\n\n            return true;\n\n        }\n\n        if (gtObj.toString().trim().length() == 0) {\n\n            return true;\n\n        }\n\n        return false;\n    }\n\n    /**\n     * 检查客户端的请求是否合法,三个只要有一个为空，则判断不合法\n     * @param challenge\n     * @param validate\n     * @param seccode\n     * @return\n     */\n    private boolean resquestIsLegal(String challenge, String validate, String seccode) {\n\n        if (objIsEmpty(challenge)) {\n\n            return false;\n\n        }\n\n        if (objIsEmpty(validate)) {\n\n            return false;\n\n        }\n\n        if (objIsEmpty(seccode)) {\n\n            return false;\n\n        }\n\n        return true;\n    }\n\n\n    /**\n     * 服务正常的情况下使用的验证方式,向gt-server进行二次验证,获取验证结果\n     *\n     * @param challenge\n     * @param validate\n     * @param seccode\n     * @return 验证结果,1表示验证成功0表示验证失败\n     */\n    public int enhencedValidateRequest(String challenge, String validate, String seccode, HashMap<String, String> data) {\n\n        if (!resquestIsLegal(challenge, validate, seccode)) {\n\n            return 0;\n\n        }\n\n        gtlog(\"request legitimate\");\n\n        String userId = data.get(\"user_id\");\n        String clientType = data.get(\"client_type\");\n        String ipAddress = data.get(\"ip_address\");\n\n        String postUrl = this.apiUrl + this.validateUrl;\n        String param = String.format(\"challenge=%s&validate=%s&seccode=%s&json_format=%s\",\n                challenge, validate, seccode, this.json_format);\n\n        if (userId != null){\n            param = param + \"&user_id=\" + userId;\n        }\n        if (clientType != null){\n            param = param + \"&client_type=\" + clientType;\n        }\n        if (ipAddress != null){\n            param = param + \"&ip_address=\" + ipAddress;\n        }\n\n        gtlog(\"param:\" + param);\n\n        String response = \"\";\n        try {\n\n            if (validate.length() <= 0) {\n\n                return 0;\n\n            }\n\n            if (!checkResultByPrivate(challenge, validate)) {\n\n                return 0;\n\n            }\n\n            gtlog(\"checkResultByPrivate\");\n\n            response = readContentFromPost(postUrl, param);\n\n            gtlog(\"response: \" + response);\n\n        } catch (Exception e) {\n\n            e.printStackTrace();\n\n        }\n\n        String return_seccode = \"\";\n\n        try {\n\n            JSONObject return_map = new JSONObject(response);\n            return_seccode = return_map.getString(\"seccode\");\n            gtlog(\"md5: \" + md5Encode(return_seccode));\n\n            if (return_seccode.equals(md5Encode(seccode))) {\n\n                return 1;\n\n            } else {\n\n                return 0;\n\n            }\n\n        } catch (JSONException e) {\n\n\n            gtlog(\"json load error\");\n            return 0;\n\n        }\n\n    }\n\n    /**\n     * failback使用的验证方式\n     *\n     * @param challenge\n     * @param validate\n     * @param seccode\n     * @return 验证结果,1表示验证成功0表示验证失败\n     */\n    public int failbackValidateRequest(String challenge, String validate, String seccode) {\n\n        gtlog(\"in failback validate\");\n\n        if (!resquestIsLegal(challenge, validate, seccode)) {\n            return 0;\n        }\n        gtlog(\"request legitimate\");\n\n        return 1;\n    }\n\n    /**\n     * 输出debug信息，需要开启debugCode\n     *\n     * @param message\n     */\n    public void gtlog(String message) {\n        if (debugCode) {\n            System.out.println(\"gtlog: \" + message);\n        }\n    }\n\n    protected boolean checkResultByPrivate(String challenge, String validate) {\n        String encodeStr = md5Encode(privateKey + \"geetest\" + challenge);\n        return validate.equals(encodeStr);\n    }\n\n    /**\n     * 发送GET请求，获取服务器返回结果\n     * @param URL\n     * @return\n     * @throws IOException\n     */\n    private String readContentFromGet(String URL) throws IOException {\n\n        java.net.URL getUrl = new URL(URL);\n        HttpURLConnection connection = (HttpURLConnection) getUrl\n                .openConnection();\n\n        connection.setConnectTimeout(2000);// 设置连接主机超时（单位：毫秒）\n        connection.setReadTimeout(2000);// 设置从主机读取数据超时（单位：毫秒）\n\n        // 建立与服务器的连接，并未发送数据\n        connection.connect();\n\n        if (connection.getResponseCode() == 200) {\n            // 发送数据到服务器并使用Reader读取返回的数据\n            StringBuffer sBuffer = new StringBuffer();\n\n            InputStream inStream = null;\n            byte[] buf = new byte[1024];\n            inStream = connection.getInputStream();\n            for (int n; (n = inStream.read(buf)) != -1;) {\n                sBuffer.append(new String(buf, 0, n, \"UTF-8\"));\n            }\n            inStream.close();\n            connection.disconnect();// 断开连接\n\n            return sBuffer.toString();\n        }\n        else {\n\n            return \"fail\";\n        }\n    }\n\n    /**\n     * 发送POST请求，获取服务器返回结果\n     * @param URL\n     * @param data\n     * @return\n     * @throws IOException\n     */\n    private String readContentFromPost(String URL, String data) throws IOException {\n\n        gtlog(data);\n        URL postUrl = new URL(URL);\n        HttpURLConnection connection = (HttpURLConnection) postUrl\n                .openConnection();\n\n        connection.setConnectTimeout(2000);// 设置连接主机超时（单位：毫秒）\n        connection.setReadTimeout(2000);// 设置从主机读取数据超时（单位：毫秒）\n        connection.setRequestMethod(\"POST\");\n        connection.setDoInput(true);\n        connection.setDoOutput(true);\n        connection.setRequestProperty(\"Content-Type\", \"application/x-www-form-urlencoded\");\n\n        // 建立与服务器的连接，并未发送数据\n        connection.connect();\n\n        OutputStreamWriter outputStreamWriter = new OutputStreamWriter(connection.getOutputStream(), \"utf-8\");\n        outputStreamWriter.write(data);\n        outputStreamWriter.flush();\n        outputStreamWriter.close();\n\n        if (connection.getResponseCode() == 200) {\n            // 发送数据到服务器并使用Reader读取返回的数据\n            StringBuffer sBuffer = new StringBuffer();\n\n            InputStream inStream = null;\n            byte[] buf = new byte[1024];\n            inStream = connection.getInputStream();\n            for (int n; (n = inStream.read(buf)) != -1;) {\n                sBuffer.append(new String(buf, 0, n, \"UTF-8\"));\n            }\n            inStream.close();\n            connection.disconnect();// 断开连接\n\n            return sBuffer.toString();\n        }\n        else {\n\n            return \"fail\";\n        }\n    }\n\n    /**\n     * md5 加密\n     *\n     * @time 2014年7月10日 下午3:30:01\n     * @param plainText\n     * @return\n     */\n    private String md5Encode(String plainText) {\n        String re_md5 = new String();\n        try {\n            MessageDigest md = MessageDigest.getInstance(\"MD5\");\n            md.update(plainText.getBytes());\n            byte b[] = md.digest();\n            int i;\n            StringBuffer buf = new StringBuffer(\"\");\n            for (int offset = 0; offset < b.length; offset++) {\n                i = b[offset];\n                if (i < 0){\n                    i += 256;\n                }\n\n                if (i < 16){\n                    buf.append(\"0\");\n                }\n                buf.append(Integer.toHexString(i));\n            }\n\n            re_md5 = buf.toString();\n\n        } catch (NoSuchAlgorithmException e) {\n            e.printStackTrace();\n        }\n        return re_md5;\n    }\n\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/persistence/BaseMapper.java",
    "content": "package com.yuu.ymall.commons.persistence;\n\n\nimport java.util.List;\n\n/**\n * 所有数据访问层的基类\n *\n * @Classname BaseMapper\n * @Date 2019/5/22 11:14\n * @Created by Yuu\n */\npublic interface BaseMapper<T> {\n\n    /**\n     * 新增\n     *\n     * @param record 对象\n     * @return\n     */\n    int insert(T record);\n\n    /**\n     * 根据主键 id 查询\n     *\n     * @param id\n     * @return\n     */\n    T selectByPrimaryKey(Long id);\n\n    /**\n     * 查询所有数据\n     *\n     * @return\n     */\n    List<T> selectAll();\n\n    /**\n     * 根据主键 id 更新\n     *\n     * @param record\n     * @return\n     */\n    int updateByPrimaryKey(T record);\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/redis/RedisCacheManager.java",
    "content": "package com.yuu.ymall.commons.redis;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.stereotype.Component;\nimport org.springframework.util.CollectionUtils;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * 缓存管理\n *\n * @author by Yuu\n * @classname RegisCacheManager\n * @date 2019/6/26 8:23\n */\n@Component\npublic class RedisCacheManager {\n    @Autowired\n    private RedisTemplate redisTemplate;\n\n    /**\n     * 指定缓存失效时间\n     *\n     * @param key 键\n     * @param time 失效时间\n     * @return\n     */\n    public boolean expire(String key, long time) {\n        try {\n            if (time > 0) {\n                redisTemplate.expire(key, time, TimeUnit.SECONDS);\n            }\n            return true;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n    }\n\n    /**\n     * 根据 key 获取过期时间\n     *\n     * @param key 键\n     * @return\n     */\n    public long getExpire(String key) {\n        return redisTemplate.getExpire(key);\n    }\n\n    /**\n     * 判断 key 是否存在\n     *\n     * @param key 键\n     * @return\n     */\n    public boolean hasKey(String key) {\n        try {\n            return redisTemplate.hasKey(key);\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n    }\n\n    /**\n     * 删除缓存\n     *\n     * @param key 键\n     */\n    public boolean del(String... key) {\n        try {\n            if (key != null && key.length > 0) {\n                if (key.length == 1) {\n                    redisTemplate.delete(key[0]);\n                } else {\n                    redisTemplate.delete(CollectionUtils.arrayToList(key));\n                }\n            }\n            return true;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n    }\n\n    /**\n     * 普通缓存获取\n     *\n     * @param key 键\n     * @return\n     */\n    public Object get(String key) {\n        return key == null ? null : redisTemplate.opsForValue().get(key);\n    }\n\n    /**\n     * 普通缓存放入\n     *\n     * @param key 键\n     * @param value 值\n     * @return\n     */\n    public boolean set(String key, Object value) {\n        try {\n            redisTemplate.opsForValue().set(key, value);\n            return true;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n    }\n\n    /**\n     * 普通缓存放入并设置时间\n     * time 要大于 0，如果 time 小于等于 0 ，将设置无限期\n     *\n     *\n     * @param key\n     * @param value\n     * @param time\n     * @return\n     */\n    public boolean set(String key, Object value, long time) {\n        try {\n            if (time > 0) {\n                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);\n            }  else{\n                set(key, value);\n            }\n            return true;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n    }\n\n    /**\n     * 存放单个 Hash\n     *\n     * @param key Redis key\n     * @param hashKey Hash key\n     * @param hashValue Hash value\n     * @return\n     */\n    public boolean setHash(String key, String hashKey, String hashValue) {\n        try {\n            redisTemplate.opsForHash().put(key, hashKey, hashValue);\n            return true;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n    }\n\n    /**\n     * 存放 HashMap 值\n     *\n     * @param key redis key\n     * @param hashKey hash key\n     * @param hashValue hash value\n     * @return\n     */\n    public boolean setHashMap(String key, HashMap hashMap) {\n        try {\n            redisTemplate.opsForHash().putAll(key, hashMap);\n            return true;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n    }\n\n    /**\n     * 判断 Hash Key 是否存在\n     *\n     * @param key Redis 缓存 key\n     * @param field Hash key\n     * @return\n     */\n    public boolean hasHashKye(String key, String field) {\n        try {\n            return redisTemplate.opsForHash().hasKey(key, field);\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n    }\n\n    /**\n     * 获取 Hash 值\n     *\n     * @param key Redis 缓存 key\n     * @param field Hash key\n     * @return\n     */\n    public Object getHash(String key, String field) {\n        return key == null || field == null ? null : redisTemplate.opsForHash().get(key, field);\n    }\n\n    /**\n     * 根据 Redis key, 获取 Hash\n     * @param key\n     * @return\n     */\n    public Map<String, Object> getHashByKey(String key) {\n        return key == null ? null : redisTemplate.opsForHash().entries(key);\n    }\n\n    /**\n     * 删除 Hash\n     *\n     * @param key redis key\n     * @param field hash key\n     * @return\n     */\n    public boolean deleteHash(String key, String field) {\n        try {\n            redisTemplate.opsForHash().delete(key, field);\n            return true;\n        } catch (Exception e) {\n            e.printStackTrace();\n            return false;\n        }\n    }\n\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/utils/EsUtil.java",
    "content": "package com.yuu.ymall.commons.utils;\n\nimport org.springframework.stereotype.Component;\n\n/**\n * ElasticSearch 客户端连接工具\n *\n * @author by Yuu\n * @classname EsUtil\n * @date 2019/6/29 17:51\n */\n@Component\npublic class EsUtil {\n\n\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/utils/HttpUtil.java",
    "content": "package com.yuu.ymall.commons.utils;\n\nimport org.apache.http.HttpEntity;\nimport org.apache.http.client.entity.UrlEncodedFormEntity;\nimport org.apache.http.client.methods.CloseableHttpResponse;\nimport org.apache.http.client.methods.HttpGet;\nimport org.apache.http.client.methods.HttpPost;\nimport org.apache.http.impl.client.CloseableHttpClient;\nimport org.apache.http.impl.client.HttpClients;\nimport org.apache.http.message.BasicNameValuePair;\nimport org.apache.http.util.EntityUtils;\n\nimport java.io.IOException;\nimport java.util.Arrays;\n\n/**\n *\n * @Classname HttpUtil\n * @Date 2019/5/13 17:01\n * @Created by Yuu\n */\npublic class HttpUtil {\n\n    public static final String GET = \"get\";\n    public static final String POST = \"post\";\n\n    public static final String REQUEST_HEADER_CONNECTION = \"keep-alive\";\n    public static final String REQUEST_HEADER_USER_AGENT = \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36\";\n\n    /**\n     * GET 请求\n     *\n     * @param url 请求地址\n     * @return\n     */\n    public static String doGet(String url) {\n        return createRequest(url, GET, null);\n    }\n\n    /**\n     * GET 请求\n     *\n     * @param url    请求地址\n     * @param cookie cookie\n     * @return\n     */\n    public static String doGet(String url, String cookie) {\n        return createRequest(url, GET, cookie);\n    }\n\n    /**\n     * POST 请求\n     *\n     * @param url    请求地址\n     * @param params 请求参数（可选）\n     * @return\n     */\n    public static String doPost(String url, BasicNameValuePair... params) {\n        return createRequest(url, POST, null, params);\n    }\n\n    /**\n     * POST 请求\n     *\n     * @param url    请求地址\n     * @param cookie cookie\n     * @param params 请求参数（可选）\n     * @return\n     */\n    public static String doPost(String url, String cookie, BasicNameValuePair... params) {\n        return createRequest(url, POST, cookie, params);\n    }\n\n    /**\n     * 创建请求\n     *\n     * @param url           请求地址\n     * @param requestMethod 请求方式 GET/POST\n     * @param cookie        cookie\n     * @param params        请求参数 仅限于 POST 请求用\n     * @return\n     */\n    private static String createRequest(String url, String requestMethod, String cookie, BasicNameValuePair... params) {\n        CloseableHttpClient httpClient = HttpClients.createDefault();\n        String result = null;\n\n        try {\n            // 请求结果\n            result = null;\n\n            // 请求方式\n            HttpGet httpGet = null;\n            HttpPost httpPost = null;\n\n            // 响应\n            CloseableHttpResponse httpResponse = null;\n\n            // GET 请求\n            if (GET.equals(requestMethod)) {\n                httpGet = new HttpGet(url);\n                httpGet.setHeader(\"Connection\", REQUEST_HEADER_CONNECTION);\n                httpGet.setHeader(\"Cookie\", cookie);\n                httpGet.setHeader(\"User-Agent\", REQUEST_HEADER_USER_AGENT);\n\n                httpResponse = httpClient.execute(httpGet);\n            }\n\n            // POST 请求\n            else if (POST.equals(requestMethod)) {\n                httpPost = new HttpPost(url);\n                httpPost.setHeader(\"Connection\", REQUEST_HEADER_CONNECTION);\n                httpPost.setHeader(\"Cookie\", cookie);\n                httpPost.setHeader(\"User-Agent\", REQUEST_HEADER_USER_AGENT);\n\n                // 有参数进来\n                if (params != null && params.length > 0) {\n                    httpPost.setEntity(new UrlEncodedFormEntity(Arrays.asList(params), \"UTF-8\"));\n                }\n\n                httpResponse = httpClient.execute(httpPost);\n            }\n\n            HttpEntity httpEntity = httpResponse.getEntity();\n            result = EntityUtils.toString(httpEntity);\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            if (httpClient != null) {\n                try {\n                    httpClient.close();\n                } catch (IOException e) {\n                    e.printStackTrace();\n                }\n            }\n        }\n\n        return result;\n    }\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/utils/IDUtil.java",
    "content": "package com.yuu.ymall.commons.utils;\n\nimport java.util.Random;\n\n/**\n * @Classname IDUtil\n * @Date 2019/6/5 23:46\n * @Created by Yuu\n */\npublic class IDUtil {\n\n    /**\n     * 随机 id 生成\n     *\n     * @return\n     */\n    public static Long getRandomId() {\n        Long millis = System.currentTimeMillis();\n        // 加上两位随机数\n        Random random = new Random();\n        int end = random.nextInt(99);\n        // 如果不足两位前面补 0\n        String str = millis + String.format(\"%02d\", end);\n        Long id = new Long(str);\n        return id;\n    }\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/utils/MapperUtil.java",
    "content": "package com.yuu.ymall.commons.utils;\n\nimport com.fasterxml.jackson.annotation.JsonInclude;\nimport com.fasterxml.jackson.core.type.TypeReference;\nimport com.fasterxml.jackson.databind.DeserializationFeature;\nimport com.fasterxml.jackson.databind.JavaType;\nimport com.fasterxml.jackson.databind.JsonNode;\nimport com.fasterxml.jackson.databind.ObjectMapper;\n\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * JSON 转换工具类\n *\n * @Classname MapperUtil\n * @Date 2019/5/13 19:46\n * @Created by Yuu\n */\npublic class MapperUtil {\n    private final static ObjectMapper objectMapper = new ObjectMapper();\n\n    public static ObjectMapper getInstance() {\n        return objectMapper;\n    }\n\n    /**\n     * 转换为 JSON 字符串\n     *\n     * @param obj\n     * @return\n     * @throws Exception\n     */\n    public static String obj2json(Object obj) throws Exception {\n        return objectMapper.writeValueAsString(obj);\n    }\n\n    /**\n     * 转换为 JSON 字符串，忽略空值\n     *\n     * @param obj\n     * @return\n     * @throws Exception\n     */\n    public static String obj2jsonIgnoreNull(Object obj) throws Exception {\n        ObjectMapper mapper = new ObjectMapper();\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n        return mapper.writeValueAsString(obj);\n    }\n\n    /**\n     * 转换为 JavaBean\n     *\n     * @param jsonString\n     * @param clazz\n     * @return\n     * @throws Exception\n     */\n    public static <T> T json2pojo(String jsonString, Class<T> clazz) throws Exception {\n        objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);\n        return objectMapper.readValue(jsonString, clazz);\n    }\n\n    /**\n     * 将指定节点的 JSON 数据转换为 JavaBean\n     *\n     * @param jsonString\n     * @param clazz\n     * @return\n     * @throws Exception\n     */\n    public static <T> T json2pojoByTree(String jsonString, String treeNode, Class<T> clazz) throws Exception {\n        JsonNode jsonNode = objectMapper.readTree(jsonString);\n        JsonNode data = jsonNode.findPath(treeNode);\n        return json2pojo(data.toString(), clazz);\n    }\n\n    /**\n     * 字符串转换为 Map<String, Object>\n     *\n     * @param jsonString\n     * @return\n     * @throws Exception\n     */\n    public static <T> Map<String, Object> json2map(String jsonString) throws Exception {\n        ObjectMapper mapper = new ObjectMapper();\n        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);\n        return mapper.readValue(jsonString, Map.class);\n    }\n\n    /**\n     * 字符串转换为 Map<String, T>\n     */\n    public static <T> Map<String, T> json2map(String jsonString, Class<T> clazz) throws Exception {\n        Map<String, Map<String, Object>> map = objectMapper.readValue(jsonString, new TypeReference<Map<String, T>>() {\n        });\n        Map<String, T> result = new HashMap<String, T>();\n        for (Map.Entry<String, Map<String, Object>> entry : map.entrySet()) {\n            result.put(entry.getKey(), map2pojo(entry.getValue(), clazz));\n        }\n        return result;\n    }\n\n    /**\n     * 深度转换 JSON 成 Map\n     *\n     * @param json\n     * @return\n     */\n    public static Map<String, Object> json2mapDeeply(String json) throws Exception {\n        return json2MapRecursion(json, objectMapper);\n    }\n\n    /**\n     * 把 JSON 解析成 List，如果 List 内部的元素存在 jsonString，继续解析\n     *\n     * @param json\n     * @param mapper 解析工具\n     * @return\n     * @throws Exception\n     */\n    private static List<Object> json2ListRecursion(String json, ObjectMapper mapper) throws Exception {\n        if (json == null) {\n            return null;\n        }\n\n        List<Object> list = mapper.readValue(json, List.class);\n\n        for (Object obj : list) {\n            if (obj != null && obj instanceof String) {\n                String str = (String) obj;\n                if (str.startsWith(\"[\")) {\n                    obj = json2ListRecursion(str, mapper);\n                } else if (obj.toString().startsWith(\"{\")) {\n                    obj = json2MapRecursion(str, mapper);\n                }\n            }\n        }\n\n        return list;\n    }\n\n    /**\n     * 把 JSON 解析成 Map，如果 Map 内部的 Value 存在 jsonString，继续解析\n     *\n     * @param json\n     * @param mapper\n     * @return\n     * @throws Exception\n     */\n    private static Map<String, Object> json2MapRecursion(String json, ObjectMapper mapper) throws Exception {\n        if (json == null) {\n            return null;\n        }\n\n        Map<String, Object> map = mapper.readValue(json, Map.class);\n\n        for (Map.Entry<String, Object> entry : map.entrySet()) {\n            Object obj = entry.getValue();\n            if (obj != null && obj instanceof String) {\n                String str = ((String) obj);\n\n                if (str.startsWith(\"[\")) {\n                    List<?> list = json2ListRecursion(str, mapper);\n                    map.put(entry.getKey(), list);\n                } else if (str.startsWith(\"{\")) {\n                    Map<String, Object> mapRecursion = json2MapRecursion(str, mapper);\n                    map.put(entry.getKey(), mapRecursion);\n                }\n            }\n        }\n\n        return map;\n    }\n\n    /**\n     * 将 JSON 数组转换为集合\n     *\n     * @param jsonArrayStr\n     * @param clazz\n     * @return\n     * @throws Exception\n     */\n    public static <T> List<T> json2list(String jsonArrayStr, Class<T> clazz) throws Exception {\n        JavaType javaType = getCollectionType(ArrayList.class, clazz);\n        List<T> list = (List<T>) objectMapper.readValue(jsonArrayStr, javaType);\n        return list;\n    }\n\n    /**\n     * 将指定节点的 JSON 数组转换为集合\n     * @param jsonStr JSON 字符串\n     * @param treeNode 查找 JSON 中的节点\n     * @return\n     * @throws Exception\n     */\n    public static <T> List<T> json2listByTree(String jsonStr, String treeNode, Class<T> clazz) throws  Exception {\n        JsonNode jsonNode = objectMapper.readTree(jsonStr);\n        JsonNode data = jsonNode.findPath(treeNode);\n        return json2list(data.toString(), clazz);\n    }\n\n    /**\n     * 获取泛型的 Collection Type\n     *\n     * @param collectionClass 泛型的Collection\n     * @param elementClasses  元素类\n     * @return JavaType Java类型\n     * @since 1.0\n     */\n    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {\n        return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);\n    }\n\n    /**\n     * 将 Map 转换为 JavaBean\n     *\n     * @param map\n     * @param clazz\n     * @return\n     */\n    public static <T> T map2pojo(Map map, Class<T> clazz) {\n        return objectMapper.convertValue(map, clazz);\n    }\n\n    /**\n     * 将 Map 转换为 JSON\n     *\n     * @param map\n     * @return\n     */\n    public static String mapToJson(Map map) {\n        try {\n            return objectMapper.writeValueAsString(map);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return \"\";\n    }\n\n    /**\n     * 将 JSON 对象转换为 JavaBean\n     *\n     * @param obj\n     * @param clazz\n     * @return\n     */\n    public static <T> T obj2pojo(Object obj, Class<T> clazz) {\n        return objectMapper.convertValue(obj, clazz);\n    }\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/utils/SendSmsUtil.java",
    "content": "package com.yuu.ymall.commons.utils;\n\nimport com.aliyuncs.CommonRequest;\nimport com.aliyuncs.CommonResponse;\nimport com.aliyuncs.DefaultAcsClient;\nimport com.aliyuncs.IAcsClient;\nimport com.aliyuncs.exceptions.ClientException;\nimport com.aliyuncs.exceptions.ServerException;\nimport com.aliyuncs.http.MethodType;\nimport com.aliyuncs.profile.DefaultProfile;\n\n/**\n * @author by Yuu\n * @classname SendSmsUtil\n * @date 2019/6/24 9:06\n */\npublic class SendSmsUtil {\n\n    /**\n     * 阿里云短信 accesskey_id\n     */\n    private static final String ACCESSKEYID = \"LTAIF9a6WQp8ubSP\";\n\n    /**\n     * 阿里云短信 secret\n     */\n    private static final String SECRET = \"VL5pg3reFZcWckwS9uwyCy5XP64Yll\";\n\n    /**\n     * 阿里云短信签名名称\n     */\n    private static final String SIGNNAME = \"YMall\";\n\n    /**\n     * 阿里云短信模板Code\n     */\n    private static final String TEMPLATECODE = \"SMS_168592535\";\n\n    /**\n     * 阿里云短信模板变量对应的实际值，JSON 格式\n     */\n    private static final String TEMPLATEPARAM = \"{\\\"code\\\":\\\"123\\\"}\";\n\n    /**\n     * 发送短信\n     *\n     * @param phone 手机号\n     * @return\n     */\n    public static String sendSms(String phone) {\n        DefaultProfile profile = DefaultProfile.getProfile(\"default\", ACCESSKEYID, SECRET);\n        IAcsClient client = new DefaultAcsClient(profile);\n\n        CommonRequest request = new CommonRequest();\n        request.setMethod(MethodType.POST);\n        request.setDomain(\"dysmsapi.aliyuncs.com\");\n        request.setVersion(\"2017-05-25\");\n        request.setAction(\"SendSms\");\n        request.putQueryParameter(\"PhoneNumbers\", phone);\n        request.putQueryParameter(\"SignName\", SIGNNAME);\n        request.putQueryParameter(\"TemplateCode\", TEMPLATECODE);\n        String numeric = String.valueOf((int)((Math.random() * 9 + 1) * 100000));\n        request.putQueryParameter(\"TemplateParam\", \"{\\\"code\\\":\\\"\"+ numeric +\"\\\"}\");\n        String result = \"\";\n        try {\n            CommonResponse response = client.getCommonResponse(request);\n            result = response.getData();\n            System.out.println(result);\n        } catch (ServerException e) {\n            e.printStackTrace();\n        } catch (ClientException e) {\n            e.printStackTrace();\n        }\n        return numeric;\n    }\n}\n"
  },
  {
    "path": "ymall-commons/src/main/java/com.yuu.ymall.commons/utils/TimeUtil.java",
    "content": "package com.yuu.ymall.commons.utils;\n\nimport java.sql.Timestamp;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.GregorianCalendar;\n\n/**\n * 时间工具类\n *\n * @author by Yuu\n * @classname TimeUtil\n * @date 2019/6/21 13:26\n */\npublic class TimeUtil {\n\n    /**\n     * 获取本周的开始时间\n     *\n     * @return\n     */\n    public static Date getBeginDayOfWeek() {\n        Date date = new Date();\n        if (date == null) {\n            return null;\n        }\n        Calendar cal = Calendar.getInstance();\n        cal.setTime(date);\n        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);\n        if (dayofweek == 1) {\n            dayofweek += 7;\n        }\n        cal.add(Calendar.DATE, 2 - dayofweek);\n        return getDayStartTime(cal.getTime());\n    }\n\n    /**\n     * 获取本周的结束时间\n     *\n     * @return\n     */\n    public static Date getEndDayOfWeek(){\n        Calendar cal = Calendar.getInstance();\n        cal.setTime(getBeginDayOfWeek());\n        cal.add(Calendar.DAY_OF_WEEK, 6);\n        Date weekEndSta = cal.getTime();\n        return getDayEndTime(weekEndSta);\n    }\n\n    /**\n     * 获取本月的开始时间\n     *\n     * @return\n     */\n    public static Date getBeginDayOfMonth() {\n        Calendar calendar = Calendar.getInstance();\n        calendar.set(getNowYear(), getNowMonth() - 1, 1);\n        return getDayStartTime(calendar.getTime());\n    }\n\n    /**\n     * 获取本月的结束时间\n     *\n     * @return\n     */\n    public static Date getEndDayOfMonth() {\n        Calendar calendar = Calendar.getInstance();\n        calendar.set(getNowYear(), getNowMonth() - 1, 1);\n        int day = calendar.getActualMaximum(5);\n        calendar.set(getNowYear(), getNowMonth() - 1, day);\n        return getDayEndTime(calendar.getTime());\n    }\n\n    /**\n     * 获取上个月的开始时间\n     *\n     * @return\n     */\n    public static Date getBeginDayOfLastMonth() {\n        Calendar calendar = Calendar.getInstance();\n        calendar.set(getNowYear(), getNowMonth() - 2, 1);\n        return getDayStartTime(calendar.getTime());\n    }\n\n    /**\n     * 获取上个月的结束时间\n     *\n     * @return\n     */\n    public static Date getEndDayOfLastMonth() {\n        Calendar calendar = Calendar.getInstance();\n        calendar.set(getNowYear(), getNowMonth() - 2, 1);\n        int day = calendar.getActualMaximum(5);\n        calendar.set(getNowYear(), getNowMonth() - 2, day);\n        return getDayEndTime(calendar.getTime());\n    }\n\n    /**\n     * 获取本年的开始时间\n     *\n     * @return\n     */\n    public static Date getBeginDayOfYear(Integer year) {\n        Calendar cal = Calendar.getInstance();\n        cal.set(Calendar.YEAR, year);\n        // cal.set\n        cal.set(Calendar.MONTH, Calendar.JANUARY);\n        cal.set(Calendar.DATE, 1);\n\n        return getDayStartTime(cal.getTime());\n    }\n\n    /**\n     * 获取本年的结束时间\n     *\n     * @return\n     */\n    public static Date getEndDayOfYear(Integer year) {\n        Calendar cal = Calendar.getInstance();\n        cal.set(Calendar.YEAR, year);\n        cal.set(Calendar.MONTH, Calendar.DECEMBER);\n        cal.set(Calendar.DATE, 31);\n        return getDayEndTime(cal.getTime());\n    }\n\n    /**\n     * 获取某个日期的开始时间\n     *\n     * @param d\n     * @return\n     */\n    public static Timestamp getDayStartTime(Date d) {\n        Calendar calendar = Calendar.getInstance();\n        if(null != d){\n            calendar.setTime(d);\n        }\n        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),    calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);\n        calendar.set(Calendar.MILLISECOND, 0);\n        return new Timestamp(calendar.getTimeInMillis());\n    }\n\n    /**\n     * 获取某个日期的结束时间\n     *\n     * @param d\n     * @return\n     */\n    public static Timestamp getDayEndTime(Date d) {\n        Calendar calendar = Calendar.getInstance();\n        if(null != d) {\n            calendar.setTime(d);\n        }\n        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),    calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);\n        calendar.set(Calendar.MILLISECOND, 999);\n        return new Timestamp(calendar.getTimeInMillis());\n    }\n\n    /**\n     * 获取今年是哪一年\n     *\n     * @return\n     */\n    public static Integer getNowYear() {\n        Date date = new Date();\n        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();\n        gc.setTime(date);\n        return Integer.valueOf(gc.get(1));\n    }\n\n    /**\n     * 获取本月是哪一月\n     *\n     * @return\n     */\n    public static int getNowMonth() {\n        Date date = new Date();\n        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();\n        gc.setTime(date);\n        return gc.get(2) + 1;\n    }\n}\n"
  },
  {
    "path": "ymall-dependencies/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.yuu</groupId>\n        <artifactId>ymall</artifactId>\n        <version>1.0.0-SNAPSHOT</version>\n        <relativePath>../pom.xml</relativePath>\n    </parent>\n\n    <artifactId>ymall-dependencies</artifactId>\n    <packaging>pom</packaging>\n\n    <name>ymall-dependencies</name>\n    <description>Unified Dependency Management</description>\n\n    <properties>\n        <!-- 环境配置 -->\n        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>\n        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>\n        <java.version>1.8</java.version>\n\n        <!-- 统一的依赖管理 -->\n        <alibaba-druid.version>1.1.6</alibaba-druid.version>\n        <aliyun-sms.version>4.1.0</aliyun-sms.version>\n        <alipay.version>3.7.110.ALL</alipay.version>\n        <commons-lang3.version>3.3.2</commons-lang3.version>\n        <commons-logging.version>1.1.1</commons-logging.version>\n        <commons-io.version>1.3.2</commons-io.version>\n        <commons-net.version>3.3</commons-net.version>\n        <commons-fileupload.version>1.3.3</commons-fileupload.version>\n        <elasticsearch.version>5.6.2</elasticsearch.version>\n        <freemarker.version>2.3.23</freemarker.version>\n        <httpclient.version>4.5.3</httpclient.version>\n        <hutool.version>4.0.5</hutool.version>\n        <jackson.version>2.9.1</jackson.version>\n        <javassist.version>3.21.0-GA</javassist.version>\n        <jedis.version>2.9.0</jedis.version>\n        <jstl.version>1.2</jstl.version>\n        <json.version>20171018</json.version>\n        <joda-time.version>2.9.9</joda-time.version>\n        <junit.version>4.12</junit.version>\n        <log4j.version>1.2.17</log4j.version>\n        <log4j-core.version>2.9.1</log4j-core.version>\n        <lombok.version>1.16.18</lombok.version>\n        <mail.version>1.5.0-b01</mail.version>\n        <mybaits-spring.version>1.3.1</mybaits-spring.version>\n        <mybatis.version>3.4.5</mybatis.version>\n        <mysql.version>5.1.44</mysql.version>\n        <mybatis-paginator.version>1.2.15</mybatis-paginator.version>\n        <pagehelper.version>4.1.6</pagehelper.version>\n        <qiniuyun.version>7.2.0</qiniuyun.version>\n        <quartz.version>2.2.3</quartz.version>\n        <servlet-api.version>3.1.0</servlet-api.version>\n        <slf4j.version>1.8.0-alpha2</slf4j.version>\n        <spring.version>5.0.4.RELEASE</spring.version>\n        <spring-data-redis.version>1.8.22.RELEASE</spring-data-redis.version>\n        <spring-data-elasticsearch.version>3.0.5.RELEASE</spring-data-elasticsearch.version>\n        <shiro.version>1.4.0</shiro.version>\n        <swegger2.version>2.9.2</swegger2.version>\n        <thymeleaf.version>3.0.5.RELEASE</thymeleaf.version>\n    </properties>\n\n    <dependencyManagement>\n        <dependencies>\n            <!-- Test Begin -->\n            <dependency>\n                <groupId>junit</groupId>\n                <artifactId>junit</artifactId>\n                <version>${junit.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-test</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n            <!-- Test End -->\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-core</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n\n            <!-- joda-time Begin -->\n            <dependency>\n                <groupId>joda-time</groupId>\n                <artifactId>joda-time</artifactId>\n                <version>${joda-time.version}</version>\n            </dependency>\n            <!-- joda-time End -->\n\n            <!-- Apache Begin -->\n            <dependency>\n                <groupId>org.apache.commons</groupId>\n                <artifactId>commons-lang3</artifactId>\n                <version>${commons-lang3.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.apache.commons</groupId>\n                <artifactId>commons-io</artifactId>\n                <version>${commons-io.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>commons-net</groupId>\n                <artifactId>commons-net</artifactId>\n                <version>${commons-net.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>commons-fileupload</groupId>\n                <artifactId>commons-fileupload</artifactId>\n                <version>${commons-fileupload.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>commons-logging</groupId>\n                <artifactId>commons-logging</artifactId>\n                <version>${commons-logging.version}</version>\n            </dependency>\n            <!-- Apache End -->\n\n            <!-- Jackson Begin -->\n            <dependency>\n                <groupId>com.fasterxml.jackson.core</groupId>\n                <artifactId>jackson-databind</artifactId>\n                <version>${jackson.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.fasterxml.jackson.core</groupId>\n                <artifactId>jackson-core</artifactId>\n                <version>${jackson.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.fasterxml.jackson.core</groupId>\n                <artifactId>jackson-annotations</artifactId>\n                <version>${jackson.version}</version>\n            </dependency>\n            <!-- Jackson End -->\n\n            <!-- HttpClient Begin -->\n            <dependency>\n                <groupId>org.apache.httpcomponents</groupId>\n                <artifactId>httpclient</artifactId>\n                <version>${httpclient.version}</version>\n            </dependency>\n            <!-- HttpClient End -->\n\n            <!-- Log Begin -->\n            <dependency>\n                <groupId>org.slf4j</groupId>\n                <artifactId>slf4j-api</artifactId>\n                <version>${slf4j.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.slf4j</groupId>\n                <artifactId>slf4j-log4j12</artifactId>\n                <version>${slf4j.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.slf4j</groupId>\n                <artifactId>jcl-over-slf4j</artifactId>\n                <version>${slf4j.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.slf4j</groupId>\n                <artifactId>jul-to-slf4j</artifactId>\n                <version>${slf4j.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>log4j</groupId>\n                <artifactId>log4j</artifactId>\n                <version>${log4j.version}</version>\n            </dependency>\n            <!-- Log End -->\n\n            <!-- Database Begin -->\n            <dependency>\n                <groupId>com.alibaba</groupId>\n                <artifactId>druid</artifactId>\n                <version>${alibaba-druid.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>mysql</groupId>\n                <artifactId>mysql-connector-java</artifactId>\n                <version>${mysql.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.mybatis</groupId>\n                <artifactId>mybatis</artifactId>\n                <version>${mybatis.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.mybatis</groupId>\n                <artifactId>mybatis-spring</artifactId>\n                <version>${mybaits-spring.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-jdbc</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.github.miemiedev</groupId>\n                <artifactId>mybatis-paginator</artifactId>\n                <version>${mybatis-paginator.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.github.pagehelper</groupId>\n                <artifactId>pagehelper</artifactId>\n                <version>${pagehelper.version}</version>\n            </dependency>\n            <!-- Database End -->\n\n            <!-- Spring Begin -->\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-context</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-webmvc</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-aspects</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-tx</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-context-support</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n            <!-- Spring End -->\n\n            <!-- Servlet Begin -->\n            <dependency>\n                <groupId>javax.servlet</groupId>\n                <artifactId>javax.servlet-api</artifactId>\n                <version>${servlet-api.version}</version>\n                <scope>provided</scope>\n            </dependency>\n            <dependency>\n                <groupId>javax.servlet</groupId>\n                <artifactId>jstl</artifactId>\n                <version>${jstl.version}</version>\n            </dependency>\n            <!-- Servlet End -->\n\n            <!-- Redis Begin -->\n            <dependency>\n                <groupId>redis.clients</groupId>\n                <artifactId>jedis</artifactId>\n                <version>${jedis.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework.data</groupId>\n                <artifactId>spring-data-redis</artifactId>\n                <version>${spring-data-redis.version}</version>\n            </dependency>\n            <!-- Redis End -->\n\n            <!-- Freemarker Begin -->\n            <dependency>\n                <groupId>org.freemarker</groupId>\n                <artifactId>freemarker</artifactId>\n                <version>${freemarker.version}</version>\n            </dependency>\n            <!-- Freemarker End -->\n\n            <!-- Javassist Begin -->\n            <dependency>\n                <groupId>org.javassist</groupId>\n                <artifactId>javassist</artifactId>\n                <version>${javassist.version}</version>\n            </dependency>\n            <!-- Javassist End -->\n\n            <!-- Elasticsearch Begin-->\n            <dependency>\n                <groupId>org.elasticsearch</groupId>\n                <artifactId>elasticsearch</artifactId>\n                <version>${elasticsearch.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.elasticsearch.client</groupId>\n                <artifactId>transport</artifactId>\n                <version>${elasticsearch.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework.data</groupId>\n                <artifactId>spring-data-elasticsearch</artifactId>\n                <version>${spring-data-elasticsearch.version}</version>\n                <exclusions>\n                    <exclusion>\n                        <groupId>org.elasticsearch.plugin</groupId>\n                        <artifactId>transport-netty3-clientn</artifactId>\n                    </exclusion>\n                </exclusions>\n            </dependency>\n            <!-- Elasticsearch End -->\n\n            <!-- Shiro Begin -->\n            <dependency>\n                <groupId>org.apache.shiro</groupId>\n                <artifactId>shiro-all</artifactId>\n                <version>${shiro.version}</version>\n            </dependency>\n            <!-- Shiro End -->\n\n            <!--Mail Begin -->\n            <dependency>\n                <groupId>org.json</groupId>\n                <artifactId>json</artifactId>\n                <version>${json.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>javax.mail</groupId>\n                <artifactId>mail</artifactId>\n                <version>${mail.version}</version>\n            </dependency>\n            <!-- Mail End -->\n\n            <!-- Hutool Begin -->\n            <dependency>\n                <groupId>cn.hutool</groupId>\n                <artifactId>hutool-all</artifactId>\n                <version>${hutool.version}</version>\n            </dependency>\n            <!-- Hutool End -->\n\n            <!-- Json Begin -->\n            <dependency>\n                <groupId>org.json</groupId>\n                <artifactId>json</artifactId>\n                <version>${json.version}</version>\n            </dependency>\n            <!-- Json End -->\n\n            <!-- Thymeleaf Begin -->\n            <dependency>\n                <groupId>org.thymeleaf</groupId>\n                <artifactId>thymeleaf-spring4</artifactId>\n                <version>${thymeleaf.version}</version>\n            </dependency>\n            <!-- Thymeleaf End -->\n\n            <!-- Lombok Begin -->\n            <dependency>\n                <groupId>org.projectlombok</groupId>\n                <artifactId>lombok</artifactId>\n                <version>${lombok.version}</version>\n            </dependency>\n            <!-- Lombok End -->\n\n            <!-- Swagger2 Begin -->\n            <dependency>\n                <groupId>io.springfox</groupId>\n                <artifactId>springfox-swagger2</artifactId>\n                <version>${swegger2.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>io.springfox</groupId>\n                <artifactId>springfox-swagger-ui</artifactId>\n                <version>${swegger2.version}</version>\n            </dependency>\n            <!-- Swagger2 End -->\n\n            <!-- QiNiuYun Begin -->\n            <dependency>\n                <groupId>com.qiniu</groupId>\n                <artifactId>qiniu-java-sdk</artifactId>\n                <version>${qiniuyun.version}</version>\n            </dependency>\n            <!-- QiNiuYun End -->\n\n            <!-- AliYun SMS Begin -->\n            <dependency>\n                <groupId>com.aliyun</groupId>\n                <artifactId>aliyun-java-sdk-core</artifactId>\n                <version>${aliyun-sms.version}</version>\n            </dependency>\n            <!-- AliYun SMS End-->\n\n            <!-- AliPay Begin -->\n            <dependency>\n                <groupId>com.alipay.sdk</groupId>\n                <artifactId>alipay-sdk-java</artifactId>\n                <version>${alipay.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>com.alipay</groupId>\n                <artifactId>alipay-trade-sdk</artifactId>\n                <version>20161215</version>\n            </dependency>\n            <!-- AliPay End -->\n\n            <!-- Quartz Begin -->\n            <dependency>\n                <groupId>org.quartz-scheduler</groupId>\n                <artifactId>quartz</artifactId>\n                <version>${quartz.version}</version>\n            </dependency>\n            <dependency>\n                <groupId>org.springframework</groupId>\n                <artifactId>spring-web</artifactId>\n                <version>${spring.version}</version>\n            </dependency>\n            <!-- Quartz End -->\n\n        </dependencies>\n    </dependencyManagement>\n\n    <build>\n        <pluginManagement>\n            <plugins>\n                <plugin>\n                    <groupId>org.apache.maven.plugins</groupId>\n                    <artifactId>maven-install-plugin</artifactId>\n                    <version>2.5.2</version>\n                </plugin>\n            </plugins>\n        </pluginManagement>\n\n        <plugins>\n            <!-- Compiler 插件, 设定 JDK 版本 -->\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <version>3.7.0</version>\n                <configuration>\n                    <source>${java.version}</source>\n                    <target>${java.version}</target>\n                    <encoding>${project.build.sourceEncoding}</encoding>\n                    <showWarnings>true</showWarnings>\n                    <compilerArguments>\n                        <extdirs>${project.basedir}/src/main/webapp/lib</extdirs>\n                    </compilerArguments>\n                </configuration>\n            </plugin>\n\n            <!-- Maven 解决依赖无法下载插件 -->\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-install-plugin</artifactId>\n                <version>2.5.2</version>\n                <executions>\n                    <execution>\n                        <id>install-external-alipay</id>\n                        <!-- 触发时机：执行 mvn clean 命令时自动触发插件 -->\n                        <phase>clean</phase>\n                        <configuration>\n                            <!-- 存放依赖文件的位置 -->\n                            <file>${project.basedir}/libs/alipay-trade-sdk-20161215.jar</file>\n                            <repositoryLayout>default</repositoryLayout>\n                            <!-- 自定义 groupId -->\n                            <groupId>com.alibaba</groupId>\n                            <!-- 自定义 artifactId -->\n                            <artifactId>alipay-trade-sdk</artifactId>\n                            <!-- 自定义版本号 -->\n                            <version>20161215</version>\n                            <!-- 打包方式 -->\n                            <packaging>jar</packaging>\n                            <!-- 是否自动生成 POM -->\n                            <generatePom>true</generatePom>\n                        </configuration>\n                        <goals>\n                            <goal>install-file</goal>\n                        </goals>\n                    </execution>\n                </executions>\n            </plugin>\n        </plugins>\n\n        <!-- 资源文件配置 -->\n        <resources>\n            <resource>\n                <directory>src/main/java</directory>\n                <excludes>\n                    <exclude>**/*.java</exclude>\n                </excludes>\n            </resource>\n            <resource>\n                <directory>src/main/resources</directory>\n            </resource>\n        </resources>\n    </build>\n</project>\n"
  },
  {
    "path": "ymall-domain/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.yuu</groupId>\n        <artifactId>ymall-dependencies</artifactId>\n        <version>1.0.0-SNAPSHOT</version>\n        <relativePath>../ymall-dependencies/pom.xml</relativePath>\n    </parent>\n\n    <artifactId>ymall-domain</artifactId>\n    <packaging>jar</packaging>\n\n    <name>ymall-domain</name>\n    <description>Domain Model</description>\n\n    <dependencies>\n        <dependency>\n            <groupId>com.yuu</groupId>\n            <artifactId>ymall-commons</artifactId>\n            <version>${project.parent.version}</version>\n        </dependency>\n    </dependencies>\n</project>"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbAddress.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 地址实体\n */\n@Data\npublic class TbAddress implements Serializable {\n    /**\n     * 地址 id\n     */\n    private Long id;\n\n    /**\n     * 用户 id\n     */\n    private Long userId;\n\n    /**\n     * 用户名\n     */\n    private String userName;\n\n    /**\n     * 电话\n     */\n    private String tel;\n\n    /**\n     * 省份\n     */\n    private String state;\n\n    /**\n     * 城市\n     */\n    private String city;\n\n    /**\n     * 区/县\n     */\n    private String district;\n\n    /**\n     * 街道地址\n     */\n    private String streetName;\n\n    /**\n     * 是否为默认地址\n     */\n    private Boolean isDefault;\n\n    /**\n     * 创建日期\n     */\n    private Date created;\n\n    /**\n     * 更新日期\n     */\n    private Date updated;\n\n    /**\n     * 详细地址\n     */\n    private String detailsAddress;\n}\n"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbExpress.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 快递实体\n */\n@Data\npublic class TbExpress implements Serializable {\n    /**\n     * 快递 id\n     */\n    private Integer id;\n\n    /**\n     * 快递名称\n     */\n    private String expressName;\n\n    /**\n     * 排列序号\n     */\n    private Integer sortOrder;\n\n    /**\n     * 创建时间\n     */\n    private Date created;\n\n    /**\n     * 更新时间\n     */\n    private Date updated;\n\n}"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbItem.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\nimport org.apache.commons.lang3.StringUtils;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\nimport java.util.Date;\n\n/**\n * 商品实体\n */\n@Data\npublic class TbItem implements Serializable {\n    /**\n     * 商品 id\n     */\n    private Long id;\n\n    /**\n     * 商品标题\n     */\n    private String title;\n\n    /**\n     * 商品卖点\n     */\n    private String sellPoint;\n\n    /**\n     * 商品价格\n     */\n    private BigDecimal price;\n\n    /**\n     * 商品库存\n     */\n    private Integer num;\n\n    /**\n     * 一次最多购买多少件\n     */\n    private Integer limitNum;\n\n    /**\n     * 商品图片\n     */\n    private String image;\n\n    /**\n     * 商品分类 id\n     */\n    private Long cid;\n\n    /**\n     * 商品状态\n     */\n    private Integer status;\n\n    /**\n     * 创建时间\n     */\n    private Date created;\n\n    /**\n     * 更新时间\n     */\n    private Date updated;\n\n    /**\n     * 获取图片地址数组\n     *\n     * @return\n     */\n    public String[] getImages() {\n        if (!StringUtils.isBlank(this.image)) {\n            String[] images = this.image.split(\",\");\n            return images;\n        }\n        return null;\n    }\n\n}\n"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbItemCat.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 商品类目实体\n */\n@Data\npublic class TbItemCat implements Serializable {\n    /**\n     * 类目 id\n     */\n    private Long id;\n\n    /**\n     * 父分类 ID = 0 代表一级根分类\n      */\n    private Long parentId;\n\n    /**\n     * 分类名称\n     */\n    private String name;\n\n    /**\n     * 分类状态\n     */\n    private Integer status;\n\n    /**\n     * 排列序号\n     */\n    private Integer sortOrder;\n\n    /**\n     * 是否为父分类 1 为 true 0 为 false\n     */\n    private Boolean isParent;\n\n    /**\n     * 创建时间\n     */\n    private Date created;\n\n    /**\n     * 更新时间\n     */\n    private Date updated;\n\n}"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbItemDesc.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 商品描述实体\n */\n@Data\npublic class TbItemDesc implements Serializable {\n    /**\n     * 商品 id\n     */\n    private Long itemId;\n\n    /**\n     * 商品描述信息\n     */\n    private String itemDesc;\n\n    /**\n     * 创建时间\n     */\n    private Date created;\n\n    /**\n     * 更新时间\n     */\n    private Date updated;\n}"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbMember.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 会员实体\n */\n@Data\npublic class TbMember implements Serializable {\n    /**\n     * 会员 id\n     */\n    private Long id;\n\n    /**\n     * 会员用户名\n     */\n    private String username;\n\n    /**\n     * 会员密码\n     */\n    private String password;\n\n    /**\n     * 会员手机号\n     */\n    private String phone;\n\n    /**\n     * 会员邮箱\n     */\n    private String email;\n\n    /**\n     * 会员性别\n     */\n    private String sex;\n\n    /**\n     * 会员状态\n     */\n    private Integer state;\n\n    /**\n     * 会员头像\n     */\n    private String file;\n\n    /**\n     * 会员描述\n     */\n    private String description;\n\n    /**\n     * 创建时间\n     */\n    private Date created;\n\n    /**\n     * 更新时间\n     */\n    private Date updated;\n\n    /**\n     * 前台登录 Token\n     */\n    private String token;\n}"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbOrder.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\nimport java.util.Date;\n\n/**\n * 订单实体\n */\n@Data\npublic class TbOrder implements Serializable {\n    /**\n     * 订单 id\n     */\n    private String id;\n\n    /**\n     * 实付金额\n     */\n    private BigDecimal payment;\n\n    /**\n     * 支付类型 1 在线支付 2 货到付款\n     */\n    private Integer paymentType;\n\n    /**\n     * 邮费\n     */\n    private BigDecimal postFee;\n\n    /**\n     * 0 未付款\n     * 1 已付款\n     * 2 未发货\n     * 3 已发货\n     * 4 交易成功\n     * 5 交易关闭\n     * 6 交易失败\n     */\n    private Integer status;\n\n    /**\n     * 付款时间\n     */\n    private Date paymentTime;\n\n    /**\n     * 发货时间\n     */\n    private Date consignTime;\n\n    /**\n     * 交易完成时间\n     */\n    private Date endTime;\n\n    /**\n     * 交易关闭时间\n     */\n    private Date closeTime;\n\n    /**\n     * 物流名称\n     */\n    private String shippingName;\n\n    /**\n     * 物流单号\n     */\n    private String shippingCode;\n\n    /**\n     * 用户 id\n     */\n    private Long userId;\n\n    /**\n     * 买家留言\n     */\n    private String buyerMessage;\n\n    /**\n     * 买家昵称\n     */\n    private String buyerNick;\n\n    /**\n     * 买家是否已经评论\n     */\n    private Boolean buyerComment;\n\n    /**\n     * 创建时间\n     */\n    private Date created;\n\n    /**\n     * 更新时间\n     */\n    private Date updated;\n\n}"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbOrderItem.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\n\n/**\n * 订单项实体\n */\n@Data\npublic class TbOrderItem implements Serializable {\n    /**\n     * 订单项 id\n     */\n    private String id;\n\n    /**\n     * 商品 id\n     */\n    private String itemId;\n\n    /**\n     * 订单 id\n     */\n    private String orderId;\n\n    /**\n     * 商品购买数量\n     */\n    private Integer num;\n\n    /**\n     * 商品标题\n     */\n    private String title;\n\n    /**\n     * 商品单价\n     */\n    private BigDecimal price;\n\n    /**\n     * 商品总金额\n     */\n    private BigDecimal totalFee;\n\n    /**\n     * 商品图片地址\n     */\n    private String picPath;\n\n    /**\n     * 本周卖出总数\n     */\n    private Integer total;\n\n}"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbOrderShipping.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 订单物流信息实体\n */\n@Data\npublic class TbOrderShipping implements Serializable {\n    /**\n     * 订单物流 id\n     */\n    private String orderId;\n\n    /**\n     * 收货人全名\n     */\n    private String receiverName;\n\n    /**\n     * 固定电话\n     */\n    private String receiverPhone;\n\n    /**\n     * 移动电话\n     */\n    private String receiverMobile;\n\n    /**\n     * 省份\n     */\n    private String receiverProvince;\n\n    /**\n     * 城市\n     */\n    private String receiverCity;\n\n    /**\n     * 区/县\n     */\n    private String receiverDistrict;\n\n    /**\n     * 收获地址\n     */\n    private String receiverAddress;\n\n    /**\n     * 邮政编码\n     */\n    private String receiverZip;\n\n    /**\n     * 创建时间\n     */\n    private Date created;\n\n    /**\n     * 更新时间\n     */\n    private Date updated;\n}"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbPanel.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 板块实体\n */\n@Data\npublic class TbPanel implements Serializable {\n    /**\n     * 板块 id\n     */\n    private Integer id;\n\n    /**\n     * 板块名称\n     */\n    private String name;\n\n    /**\n     * 板块类型 0 轮播图 1 板块种类一 2  板块种类二 3 板块种类三\n     */\n    private Integer type;\n\n    /**\n     * 排列序号\n     */\n    private Integer sortOrder;\n\n    /**\n     * 所属位置 0 首页 1 商品推荐 2 我要捐赠\n     */\n    private Integer position;\n\n    /**\n     * 板块限制商品数量\n     */\n    private Integer limitNum;\n\n    /**\n     * 板块状态\n     */\n    private Integer status;\n\n    /**\n     * 创建时间\n     */\n    private Date created;\n\n    /**\n     * 更新时间\n     */\n    private Date updated;\n\n}\n"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbPanelContent.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\nimport java.util.Date;\n\n/**\n * 板块内容实体\n */\n@Data\npublic class TbPanelContent implements Serializable {\n    /**\n     * 板块内容 id\n     */\n    private Integer id;\n\n    /**\n     * 所属板块 id\n     */\n    private Integer panelId;\n\n    /**\n     * 板块内容类型 0 关联商品 1 其他链接\n     */\n    private Integer type;\n\n    /**\n     * 关联商品 id\n     */\n    private Long productId;\n\n    /**\n     * 排列序号\n     */\n    private Integer sortOrder;\n\n    /**\n     * 其它链接\n     */\n    private String fullUrl;\n\n    /**\n     * 图片地址\n     */\n    private String picUrl;\n\n    /**\n     * 3d 轮播图备用1\n     */\n    private String picUrl2;\n\n    /**\n     * 3d 轮播图备用2\n     */\n    private String picUrl3;\n\n    /**\n     * 创建时间\n     */\n    private Date created;\n\n    /**\n     * 更新时间\n     */\n    private Date updated;\n\n    /**\n     * 关联商品价格\n     */\n    private BigDecimal salePrice;\n\n    /**\n     * 关联商品名称\n     */\n    private String productName;\n\n    /**\n     * 关联商品标题\n     */\n    private String subTitle;\n\n}\n"
  },
  {
    "path": "ymall-domain/src/main/java/com/yuu/ymall/domain/TbUser.java",
    "content": "package com.yuu.ymall.domain;\n\nimport lombok.Data;\n\nimport java.io.Serializable;\nimport java.util.Date;\n\n/**\n * 用户实体\n */\n@Data\npublic class TbUser implements Serializable {\n    /**\n     * 用户 id\n     */\n    private Long id;\n\n    /**\n     * 用户名\n     */\n    private String username;\n\n    /**\n     * 用户密码\n     */\n    private String password;\n\n    /**\n     * 创建时间\n     */\n    private Date created;\n\n    /**\n     * 更新时间\n     */\n    private Date updated;\n}"
  },
  {
    "path": "ymall-web-admin/.rebel.xml.bak",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<!--\n  This is the JRebel configuration file. It maps the running application to your IDE workspace, enabling JRebel reloading for this project.\n  Refer to https://manuals.zeroturnaround.com/jrebel/standalone/config.html for more information.\n-->\n<application generated-by=\"intellij\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.zeroturnaround.com\" xsi:schemaLocation=\"http://www.zeroturnaround.com http://update.zeroturnaround.com/jrebel/rebel-2_1.xsd\">\n\n\t<classpath>\n\t\t<dir name=\"C:/workspace/project/ymall-manager/target/classes\">\n\t\t</dir>\n\t</classpath>\n\n\t<web>\n\t\t<link target=\"/\">\n\t\t\t<dir name=\"C:/workspace/project/ymall-manager/src/main/webapp\">\n\t\t\t</dir>\n\t\t</link>\n\t</web>\n\n</application>\n"
  },
  {
    "path": "ymall-web-admin/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.yuu</groupId>\n        <artifactId>ymall-dependencies</artifactId>\n        <version>1.0.0-SNAPSHOT</version>\n        <relativePath>../ymall-dependencies/pom.xml</relativePath>\n    </parent>\n\n    <artifactId>ymall-web-admin</artifactId>\n    <packaging>war</packaging>\n\n    <name>ymall-web-admin</name>\n    <description>Back Admin Management</description>\n\n    <dependencies>\n\n        <!-- Database Begin -->\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>druid</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>mysql</groupId>\n            <artifactId>mysql-connector-java</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.mybatis</groupId>\n            <artifactId>mybatis</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.mybatis</groupId>\n            <artifactId>mybatis-spring</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-jdbc</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.github.miemiedev</groupId>\n            <artifactId>mybatis-paginator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.github.pagehelper</groupId>\n            <artifactId>pagehelper</artifactId>\n        </dependency>\n        <!-- Database End -->\n\n        <!-- Project Begin -->\n        <dependency>\n            <groupId>com.yuu</groupId>\n            <artifactId>ymall-commons</artifactId>\n            <version>${project.parent.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>com.yuu</groupId>\n            <artifactId>ymall-domain</artifactId>\n            <version>${project.parent.version}</version>\n        </dependency>\n        <!-- Project End -->\n\n        <!-- Spring Begin -->\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-webmvc</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-aspects</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-context-support</artifactId>\n        </dependency>\n        <!-- Spring End -->\n\n        <!-- Servlet Begin -->\n        <dependency>\n            <groupId>javax.servlet</groupId>\n            <artifactId>javax.servlet-api</artifactId>\n            <scope>provided</scope>\n        </dependency>\n        <dependency>\n            <groupId>javax.servlet</groupId>\n            <artifactId>jstl</artifactId>\n        </dependency>\n        <!-- Servlet End -->\n\n        <!-- Shiro Begin -->\n        <dependency>\n            <groupId>org.apache.shiro</groupId>\n            <artifactId>shiro-all</artifactId>\n        </dependency>\n        <!-- Shiro End -->\n\n        <!-- Swagger2 Begin -->\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger2</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger-ui</artifactId>\n        </dependency>\n        <!-- Swagger2 End -->\n\n        <!-- QiNiuYun Begin -->\n        <dependency>\n            <groupId>com.qiniu</groupId>\n            <artifactId>qiniu-java-sdk</artifactId>\n        </dependency>\n        <!-- QiNiuYun End -->\n\n        <!-- Hutool Begin -->\n        <dependency>\n            <groupId>cn.hutool</groupId>\n            <artifactId>hutool-all</artifactId>\n            <version>${hutool.version}</version>\n        </dependency>\n        <!-- Hutool End -->\n    </dependencies>\n\n    <build>\n        <plugins>\n            <!-- MyBatis Generator Plugin -->\n            <plugin>\n                <groupId>org.mybatis.generator</groupId>\n                <artifactId>mybatis-generator-maven-plugin</artifactId>\n                <version>1.3.2</version>\n                <configuration>\n                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>\n                    <verbose>true</verbose>\n                    <overwrite>true</overwrite>\n                </configuration>\n                <dependencies>\n                    <dependency>\n                        <groupId>mysql</groupId>\n                        <artifactId>mysql-connector-java</artifactId>\n                        <version>${mysql.version}</version>\n                    </dependency>\n                </dependencies>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/consts/Consts.java",
    "content": "package com.yuu.ymall.web.admin.commons.consts;\n\n/**\n * 常量类\n *\n * @Classname Consts\n * @Date 2019/6/15 20:13\n * @Created by Yuu\n */\npublic class Consts {\n\n    /**\n     * ####### 订单状态\n     */\n\n    /**\n     * 订单未付款\n     */\n    public static final Integer ORDER_STATE_UNPAID = 0;\n    \n    /**\n     * 订单已付款\n     */\n    public static final Integer ORDER_STATE_PAID = 1;\n    \n    /**\n     * 订单未发货\n     */\n    public static final Integer ORDER_STATE_UNSHIPPED = 2;\n \n    /**\n     * 订单已发货\n     */\n    public static final Integer ORDER_STATE_SHIPPED = 3;\n \n    /**\n     * 订单交易成功\n     */\n    public static final Integer ORDER_STATE_SUCCESS = 4;\n \n    /**\n     * 订单交易关闭\n     */\n    public static final Integer ORDER_STATE_CLOSE = 5;\n\n    /**\n     * 交易失败\n     */\n    public static final Integer ORDER_STATE_FAILED = 6;\n\n\n    /**\n     * ######### 会员状态\n     */\n\n    /**\n     * 会员启用，正常状态\n     */\n    public static final Integer MEMBER_START = 1;\n\n    /**\n     * 会员被封禁\n     */\n    public static final Integer MEMBER_BAN = 2;\n\n\n    /**\n     * ######### 报表统计\n     */\n\n    /**\n     * 自定义查询报表\n     */\n    public static final Integer CUSTOM_DATE = -1;\n\n    /**\n     * 按年统计\n     */\n    public static final Integer CUSTOM_YEAR = -2;\n\n    /**\n     * 本周\n     */\n    public static final Integer THIS_WEEK = 0;\n\n    /**\n     * 本月\n     */\n    public static final Integer THIS_MONTH = 1;\n\n    /**\n     * 上个月\n     */\n    public static final Integer LAST_MONTH = 2;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/dto/ChartData.java",
    "content": "package com.yuu.ymall.web.admin.commons.dto;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * EChart 数据传输对象\n *\n * @author by Yuu\n * @classname ChartData\n * @date 2019/6/21 11:00\n */\npublic class ChartData implements Serializable {\n\n    /**\n     * x 轴数据\n     */\n    private List<Object> xDatas;\n\n    /**\n     * y 轴数据\n     */\n    private List<Object> yDatas;\n\n    /**\n     * 总计\n     */\n    private Object countAll;\n\n    public List<Object> getxDatas() {\n        return xDatas;\n    }\n\n    public void setxDatas(List<Object> xDatas) {\n        this.xDatas = xDatas;\n    }\n\n    public List<Object> getyDatas() {\n        return yDatas;\n    }\n\n    public void setyDatas(List<Object> yDatas) {\n        this.yDatas = yDatas;\n    }\n\n    public Object getCountAll() {\n        return countAll;\n    }\n\n    public void setCountAll(Object countAll) {\n        this.countAll = countAll;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/dto/City.java",
    "content": "package com.yuu.ymall.web.admin.commons.dto;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\n\nimport java.io.Serializable;\n\n/**\n * @Classname City\n * @Date 2019/5/13 19:43\n * @Created by Yuu\n */\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class City implements Serializable {\n\n    /**\n     * 城市\n     */\n    String city;\n\n    /**\n     * 区域\n     */\n    String distrct;\n\n    public String getCity() {\n        return city;\n    }\n\n    public void setCity(String city) {\n        this.city = city;\n    }\n\n    public String getDistrct() {\n        return distrct;\n    }\n\n    public void setDistrct(String distrct) {\n        this.distrct = distrct;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/dto/DataTablesResult.java",
    "content": "package com.yuu.ymall.web.admin.commons.dto;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * 分页展示对象\n *\n * @Classname PageInfo\n * @Date 2019/5/16 23:53\n * @Created by Yuu\n */\n@Setter\n@Getter\npublic class DataTablesResult<T> implements Serializable {\n    private int draw;\n    private int recordsTotal;\n    private int recordsFiltered;\n    private List<T> data;\n    private String error;\n    private int start = 0;\n    private int length = 10;\n    private int pageNum = 1;\n\n    /**\n     * 初始化 DataTables 数据\n     * @param request\n     */\n    public DataTablesResult(HttpServletRequest request) {\n        String strDraw = request.getParameter(\"draw\");\n        String strStart = request.getParameter(\"start\");\n        String strLength = request.getParameter(\"length\");\n\n        this.draw = strDraw == null ? 0 : Integer.parseInt(strDraw);\n        this.start = strStart == null ? 0 : Integer.parseInt(strStart);\n        this.length = strLength == null ? 10 : Integer.parseInt(strLength);\n\n        // 计算页面\n        this.pageNum = start/length + 1;\n    }\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/dto/IpWeatherResult.java",
    "content": "package com.yuu.ymall.web.admin.commons.dto;\n\nimport com.fasterxml.jackson.annotation.JsonIgnoreProperties;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * @Classname IpWeatherResult\n * @Date 2019/5/13 19:42\n * @Created by Yuu\n */\n@JsonIgnoreProperties(ignoreUnknown = true)\npublic class IpWeatherResult implements Serializable {\n\n    /**\n     * 消息\n     */\n    String msg;\n\n    /**\n     * 返回数据\n     */\n    List<City> result;\n\n    public String getMsg() {\n        return msg;\n    }\n\n    public void setMsg(String msg) {\n        this.msg = msg;\n    }\n\n    public List<City> getResult() {\n        return result;\n    }\n\n    public void setResult(List<City> result) {\n        this.result = result;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/dto/ItemDto.java",
    "content": "package com.yuu.ymall.web.admin.commons.dto;\n\nimport com.yuu.ymall.domain.TbItem;\nimport lombok.Data;\n\n/**\n * @Classname ItemDto\n * @Date 2019/6/5 23:19\n * @Created by Yuu\n */\n@Data\npublic class ItemDto extends TbItem {\n    /**\n     * 商品描述\n     */\n    private String detail;\n\n    /**\n     * 商品分类名称\n     */\n    private String cname;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/dto/OrderChartData.java",
    "content": "package com.yuu.ymall.web.admin.commons.dto;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\nimport java.util.Date;\n\n/**\n * 订单统计数据传输对象\n *\n * @author by Yuu\n * @classname OrderChartData\n * @date 2019/6/21 11:31\n */\npublic class OrderChartData implements Serializable {\n\n    /**\n     * 日期\n     */\n    Date time;\n\n    /**\n     * 总销量\n     */\n    BigDecimal money;\n\n    public Date getTime() {\n        return time;\n    }\n\n    public void setTime(Date time) {\n        this.time = time;\n    }\n\n    public BigDecimal getMoney() {\n        return money;\n    }\n\n    public void setMoney(BigDecimal money) {\n        this.money = money;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/dto/OrderDetail.java",
    "content": "package com.yuu.ymall.web.admin.commons.dto;\n\nimport com.yuu.ymall.domain.TbOrder;\nimport com.yuu.ymall.domain.TbOrderItem;\nimport com.yuu.ymall.domain.TbOrderShipping;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * 订单详情\n *\n * @Classname OrderDetail\n * @Date 2019/6/14 22:09\n * @Created by Yuu\n */\npublic class OrderDetail implements Serializable {\n\n    /**\n     * 订单信息\n     */\n    private TbOrder tbOrder;\n\n    /**\n     * 订单项集合\n     */\n    private List<TbOrderItem> tbOrderItemList;\n\n    /**\n     * 订单收货信息\n     */\n    private TbOrderShipping tbOrderShipping;\n\n    public TbOrder getTbOrder() {\n        return tbOrder;\n    }\n\n    public void setTbOrder(TbOrder tbOrder) {\n        this.tbOrder = tbOrder;\n    }\n\n    public List<TbOrderItem> getTbOrderItemList() {\n        return tbOrderItemList;\n    }\n\n    public void setTbOrderItemList(List<TbOrderItem> tbOrderItemList) {\n        this.tbOrderItemList = tbOrderItemList;\n    }\n\n    public TbOrderShipping getTbOrderShipping() {\n        return tbOrderShipping;\n    }\n\n    public void setTbOrderShipping(TbOrderShipping tbOrderShipping) {\n        this.tbOrderShipping = tbOrderShipping;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/dto/ZTreeNode.java",
    "content": "package com.yuu.ymall.web.admin.commons.dto;\n\nimport lombok.Getter;\nimport lombok.Setter;\n\nimport java.io.Serializable;\n\n/**\n * @Classname ZTreeNode\n * @Date 2019/5/20 8:48\n * @Created by Yuu\n */\n@Getter\n@Setter\npublic class ZTreeNode implements Serializable {\n\n    private int id;\n\n    private int pId;\n\n    private String name;\n\n    private Boolean isParent;\n\n    private Boolean open;\n\n    private String icon;\n\n    private int status;\n\n    private int sortOrder;\n\n    private String remark;\n\n    /**\n     * 板块限制商品数量\n     */\n    private int limitNum;\n\n    /**\n     * 板块类型\n     */\n    private int type;\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/es/ESItem.java",
    "content": "package com.yuu.ymall.web.admin.commons.es;\n\nimport org.springframework.data.annotation.Id;\nimport org.springframework.data.elasticsearch.annotations.Document;\nimport org.springframework.data.elasticsearch.annotations.Field;\nimport org.springframework.data.elasticsearch.annotations.FieldType;\n\n/**\n * Elasticsearch 对应实体类\n *\n * @author by Yuu\n * @classname ESItem\n * @date 2019/6/29 21:39\n */\n@Document(indexName = \"item\", type = \"itemList\", shards = 1, replicas = 0)\npublic class ESItem {\n    /**\n     * 商品 ID\n     */\n    @Id\n    private Long id;\n\n    /**\n     * 商品名称\n     */\n    @Field(type = FieldType.text, analyzer = \"ik_max_word\")\n    private String productName;\n\n    /**\n     * 商品副标题\n     */\n    @Field(type = FieldType.text, analyzer = \"ik_max_word\")\n    private String subTitle;\n\n    /**\n     * 商品 id\n     */\n    @Field(type = FieldType.Long)\n    private Long productId;\n\n    /**\n     * 分类 id\n     */\n    @Field(type = FieldType.Long)\n    private Long cid;\n\n    /**\n     * 商品售价\n     */\n    @Field(type = FieldType.Double)\n    private Double salePrice;\n\n    /**\n     * 商品大图 1 张\n     */\n    @Field(type = FieldType.keyword)\n    private String picUrl;\n\n    /**\n     * 商品销量\n     */\n    @Field(type = FieldType.Integer)\n    private Integer orderNum;\n\n    /**\n     * 商品限制购买数量\n     */\n    @Field(type = FieldType.Integer)\n    private Integer limit;\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getProductName() {\n        return productName;\n    }\n\n    public void setProductName(String productName) {\n        this.productName = productName;\n    }\n\n    public String getSubTitle() {\n        return subTitle;\n    }\n\n    public void setSubTitle(String subTitle) {\n        this.subTitle = subTitle;\n    }\n\n    public Long getProductId() {\n        return productId;\n    }\n\n    public void setProductId(Long productId) {\n        this.productId = productId;\n    }\n\n    public Long getCid() {\n        return cid;\n    }\n\n    public void setCid(Long cid) {\n        this.cid = cid;\n    }\n\n    public Double getSalePrice() {\n        return salePrice;\n    }\n\n    public void setSalePrice(Double salePrice) {\n        this.salePrice = salePrice;\n    }\n\n    public String getPicUrl() {\n        return picUrl;\n    }\n\n    public void setPicUrl(String picUrl) {\n        this.picUrl = picUrl;\n    }\n\n    public Integer getOrderNum() {\n        return orderNum;\n    }\n\n    public void setOrderNum(Integer orderNum) {\n        this.orderNum = orderNum;\n    }\n\n    public Integer getLimit() {\n        return limit;\n    }\n\n    public void setLimit(Integer limit) {\n        this.limit = limit;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/shiro/MyRealm.java",
    "content": "package com.yuu.ymall.web.admin.commons.shiro;\n\nimport com.yuu.ymall.domain.TbUser;\nimport com.yuu.ymall.web.admin.service.UserService;\nimport org.apache.shiro.authc.AuthenticationException;\nimport org.apache.shiro.authc.AuthenticationInfo;\nimport org.apache.shiro.authc.AuthenticationToken;\nimport org.apache.shiro.authc.SimpleAuthenticationInfo;\nimport org.apache.shiro.authz.AuthorizationInfo;\nimport org.apache.shiro.realm.AuthorizingRealm;\nimport org.apache.shiro.subject.PrincipalCollection;\nimport org.springframework.beans.factory.annotation.Autowired;\n\n/**\n * @Classname MyRealm\n * @Date 2019/5/11 18:47\n * @Created by Yuu\n */\npublic class MyRealm extends AuthorizingRealm {\n\n    @Autowired\n    private UserService userService;\n\n\n    /**\n     * 先执行登录验证\n     *\n     * @param authenticationToken\n     * @return\n     * @throws AuthenticationException\n     */\n    @Override\n    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {\n        // 获取用户名密码\n        String username = authenticationToken.getPrincipal().toString();\n        TbUser tbUser = userService.getUserByUsername(username);\n        if (tbUser != null) {\n            // 得到用户账号和密码存放到 authenticationInfo 用于 Controller 层的权限判断，第三个参数随意不能为空\n            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(tbUser.getUsername(), tbUser.getPassword(),\n                    tbUser.getUsername());\n            return authenticationInfo;\n        }\n        return null;\n    }\n\n    @Override\n    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {\n        return null;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/swagger/SwaggerConfiguration.java",
    "content": "package com.yuu.ymall.web.admin.commons.swagger;\n\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.servlet.config.annotation.EnableWebMvc;\nimport springfox.documentation.builders.ApiInfoBuilder;\nimport springfox.documentation.builders.PathSelectors;\nimport springfox.documentation.builders.RequestHandlerSelectors;\nimport springfox.documentation.service.ApiInfo;\nimport springfox.documentation.service.Contact;\nimport springfox.documentation.spi.DocumentationType;\nimport springfox.documentation.spring.web.plugins.Docket;\nimport springfox.documentation.swagger2.annotations.EnableSwagger2;\n\n/**\n * @Classname Swagger2Confinguration\n * @Date 2019/5/12 11:33\n * @Created by Yuu\n */\n@Configuration  // 让 Spring 来加载该配置类\n@EnableWebMvc   // 非 Spring Boot 需启用\n@EnableSwagger2 // 启用 Swagger2\n@ComponentScan(basePackages = \"com.yuu.ymall.web.admin.web.controller\")\npublic class SwaggerConfiguration {\n\n    public static final Logger log = LoggerFactory.getLogger(SwaggerConfiguration.class);\n\n    @Bean\n    public Docket createRestApi() {\n        log.info(\"开始加载Swagger2...\");\n        return new Docket(DocumentationType.SWAGGER_2)\n                .apiInfo(apiInfo())\n                .select()\n                // 扫描指定包中的 swagger 注解\n                //.apis(RequestHandlerSelectors.basePackage(\"com.yuu.ymall.controller.admin.controller\"))\n                // 扫描所有有注解的 api，用这种方式更灵活\n                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))\n                .paths(PathSelectors.any())\n                .build();\n    }\n\n    private ApiInfo apiInfo() {\n        return new ApiInfoBuilder()\n                .title(\"YMall API Documentation\")\n                .description(\"YMall 商城管理后台API接口\")\n                .termsOfServiceUrl(\"https://www.71yuu.com\")\n                .contact(new Contact(\"Yuu\", \"https://www.71yuu.com\", \"1225459207@qq.com\"))\n                .version(\"1.0.0\")\n                .build();\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/utils/DtoUtil.java",
    "content": "package com.yuu.ymall.web.admin.commons.utils;\n\nimport com.yuu.ymall.domain.TbItemCat;\nimport com.yuu.ymall.domain.TbPanel;\nimport com.yuu.ymall.web.admin.commons.dto.ZTreeNode;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\n/**\n * @Classname DtoUtil\n * @Date 2019/5/20 9:21\n * @Created by Yuu\n */\npublic class DtoUtil {\n\n    private final static Logger log = LoggerFactory.getLogger(DtoUtil.class);\n\n    /**\n     * 板块类目封装 ZTreeNode 对象\n     *\n     * @param tbPanel 板块类目\n     * @return\n     */\n    public static ZTreeNode TbPanel2ZTreeNode(TbPanel tbPanel) {\n        ZTreeNode zTreeNode = new ZTreeNode();\n        zTreeNode.setId(tbPanel.getId());\n        zTreeNode.setIsParent(false);\n        zTreeNode.setPId(0);\n        zTreeNode.setName(tbPanel.getName());\n        zTreeNode.setSortOrder(tbPanel.getSortOrder());\n        zTreeNode.setStatus(tbPanel.getStatus());\n        zTreeNode.setLimitNum(tbPanel.getLimitNum());\n        zTreeNode.setType(tbPanel.getType());\n        return zTreeNode;\n    }\n\n\n    /**\n     * 商品分类封装 ZTreeNode 对象\n     *\n     * @param tbItemCat 商品分类\n     * @return\n     */\n    public static ZTreeNode TbItemCat2ZTreeNode(TbItemCat tbItemCat) {\n        ZTreeNode zTreeNode = new ZTreeNode();\n        zTreeNode.setId(Math.toIntExact(tbItemCat.getId()));\n        zTreeNode.setStatus(tbItemCat.getStatus());\n        zTreeNode.setSortOrder(tbItemCat.getSortOrder());\n        zTreeNode.setName(tbItemCat.getName());\n        zTreeNode.setPId(Math.toIntExact(tbItemCat.getParentId()));\n        zTreeNode.setIsParent(tbItemCat.getIsParent());\n        return zTreeNode;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/utils/IDUtil.java",
    "content": "package com.yuu.ymall.web.admin.commons.utils;\n\nimport java.util.Random;\n\n/**\n * @Classname IDUtil\n * @Date 2019/6/5 23:46\n * @Created by Yuu\n */\npublic class IDUtil {\n\n    /**\n     * 随机 id 生成\n     *\n     * @return\n     */\n    public static Long getRandomId() {\n        Long millis = System.currentTimeMillis();\n        // 加上两位随机数\n        Random random = new Random();\n        int end = random.nextInt(99);\n        // 如果不足两位前面补 0\n        String str = millis + String.format(\"%02d\", end);\n        Long id = new Long(str);\n        return id;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/utils/IPInfoUtil.java",
    "content": "package com.yuu.ymall.web.admin.commons.utils;\n\nimport com.yuu.ymall.commons.utils.HttpUtil;\nimport com.yuu.ymall.commons.utils.MapperUtil;\nimport com.yuu.ymall.web.admin.commons.dto.IpWeatherResult;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\n\n/**\n * IP 信息工具类\n *\n * @Classname IPInfoUtil\n * @Date 2019/5/13 14:09\n * @Created by Yuu\n */\npublic class IPInfoUtil {\n\n    private static final Logger log = LoggerFactory.getLogger(IPInfoUtil.class);\n\n    /**\n     * Mob全国天气预报接口\n     */\n    private final static String GET_WEATHER=\"http://apicloud.mob.com/v1/weather/ip?key=2b1e8ccdabd32&ip=\";\n\n    /**\n     * 获取客户端 IP 地址\n     *\n     * @param request 请求\n     * @return\n     */\n    public static String getIpAddr(HttpServletRequest request) {\n        String ip = request.getHeader(\"x-forwarded-for\");\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"Proxy-Client-IP\");\n        }\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"WL-Proxy-Client-IP\");\n        }\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getRemoteAddr();\n            if (ip.equals(\"127.0.0.1\")) {\n                //根据网卡取本机配置的IP\n                InetAddress inet = null;\n                try {\n                    inet = InetAddress.getLocalHost();\n                } catch (UnknownHostException e) {\n                    e.printStackTrace();\n                }\n                ip = inet.getHostAddress();\n            }\n        }\n        // 对于通过多个代理的情况下，第一个 IP 为客户端真实 IP ，多个 IP 按照‘，’分割\n        if (ip != null && ip.length() > 15) {\n            if (ip.indexOf(\",\") > 0) {\n                ip = ip.substring(0, ip.indexOf(\",\"));\n            }\n        }\n        if(\"0:0:0:0:0:0:0:1\".equals(ip)){\n            ip=\"127.0.0.1\";\n        }\n        return ip;\n    }\n\n    /**\n     * 获取 IP 返回天气\n     * @param ip ip 地址\n     * @return\n     */\n    public static String getIpInfo(String ip) {\n        if (null != ip) {\n            String url = GET_WEATHER + ip;\n            String result = HttpUtil.doGet(url);\n            return result;\n        }\n        return null;\n    }\n\n    /**\n     * 获取 IP 返回地理信息\n     *\n     * @param ip ip 地址\n     * @return\n     */\n    public static String getIpCity(String ip) {\n        if (ip != null) {\n            String url = GET_WEATHER + ip;\n            String json = HttpUtil.doGet(url);\n            IpWeatherResult weather = null;\n            String result = \"未知\";\n            try {\n                weather = MapperUtil.json2pojo(json, IpWeatherResult.class);\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n            result = weather.getResult().get(0).getCity() + \" \" + weather.getResult().get(0).getDistrct();\n            return result;\n        }\n        return null;\n    }\n\n    public static void main(String[] args) {\n        log.info(getIpInfo(\"192.168.23.1\"));\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/utils/ObjectUtil.java",
    "content": "package com.yuu.ymall.web.admin.commons.utils;\n\nimport com.google.common.collect.Maps;\nimport com.yuu.ymall.commons.utils.MapperUtil;\nimport org.springframework.cglib.beans.BeanMap;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @Classname ObjectUtil\n * @Date 2019/5/13 16:26\n * @Created by Yuu\n */\npublic class ObjectUtil {\n\n    /**\n     * Bean 转 Map\n     * @param bean\n     * @param <T>\n     * @return\n     */\n    public static <T> Map<String, Object> beanToMap(T bean) {\n        Map<String, Object> map = Maps.newHashMap();\n        if (bean != null) {\n            BeanMap beanMap = BeanMap.create(bean);\n            for (Object key : beanMap.keySet()) {\n                map.put(key+\"\", beanMap.get(key));\n            }\n        }\n        return map;\n    }\n\n    public static String mapToStringAll(Map<String, String[]> paramMap) throws Exception {\n        if (paramMap == null) {\n            return \"\";\n        }\n        Map<String, Object> params = new HashMap<>(16);\n        for (Map.Entry<String, String[]> param : paramMap.entrySet()) {\n            String key = param.getKey();\n            String paramValue = (param.getValue() != null && param.getValue().length > 0 ? param.getValue()[0] : \"\");\n            params.put(key, paramValue);\n        }\n        return MapperUtil.obj2json(params);\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/utils/QiniuUtil.java",
    "content": "package com.yuu.ymall.web.admin.commons.utils;\n\nimport com.google.gson.Gson;\nimport com.qiniu.common.QiniuException;\nimport com.qiniu.common.Zone;\nimport com.qiniu.http.Response;\nimport com.qiniu.storage.Configuration;\nimport com.qiniu.storage.UploadManager;\nimport com.qiniu.storage.model.DefaultPutRet;\nimport com.qiniu.util.Auth;\nimport com.qiniu.util.StringMap;\nimport com.qiniu.util.UrlSafeBase64;\nimport com.yuu.ymall.commons.execption.YmallUploadException;\nimport okhttp3.OkHttpClient;\nimport okhttp3.Request;\nimport okhttp3.RequestBody;\nimport org.apache.commons.fileupload.servlet.ServletFileUpload;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.HashMap;\n\n/**\n * 七牛云图片上传工具类\n * @Classname QiniuUtil\n * @Date 2019/5/24 20:38\n * @Created by Yuu\n */\npublic class QiniuUtil {\n\n    private final static Logger log = LoggerFactory.getLogger(QiniuUtil.class);\n\n    /**\n     * 生成上传凭证，然后准备上传\n     */\n    private static String accessKey = \"1v01i-JOwyKIbxFKhrDj6YfwRREUR47W_nh0sSEh\";\n    private static String secretKey = \"mFmbgY9JehH9ovJvPXQMajMWJv5feqNXaXi9_r6B\";\n    private static String bucket = \"ymall\";\n    private static String origin = \"http://pub7lsomw.bkt.clouddn.com/\";\n    private static Auth auth = Auth.create(accessKey, secretKey);\n\n    /**\n     * 普通方式上传\n     * @param filePath\n     * @return\n     */\n    public static String qiniuUpload(String filePath){\n\n        //构造一个带指定Zone对象的配置类 zone2华南\n        Configuration cfg = new Configuration(Zone.zone2());\n\n        UploadManager uploadManager = new UploadManager(cfg);\n\n        String localFilePath = filePath;\n        //默认不指定key的情况下，以文件内容的hash值作为文件名\n        String key = null;\n        Auth auth = Auth.create(accessKey, secretKey);\n        String upToken = auth.uploadToken(bucket);\n\n        try {\n            Response response = uploadManager.put(localFilePath, key, upToken);\n            //解析上传成功的结果\n            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);\n            return origin + putRet.key;\n        }catch(QiniuException ex){\n            Response r = ex.response;\n            log.warn(r.toString());\n            try {\n                return r.bodyString();\n            } catch (QiniuException e) {\n                throw new YmallUploadException(e.toString());\n            }\n        }\n    }\n\n    /**\n     * 文件流上传\n     * @param file\n     * @param key 文件名\n     * @return\n     */\n    public static String qiniuInputStreamUpload(FileInputStream file, String key){\n\n        //构造一个带指定Zone对象的配置类 zone2华南\n        Configuration cfg = new Configuration(Zone.zone2());\n\n        UploadManager uploadManager = new UploadManager(cfg);\n\n        Auth auth = Auth.create(accessKey, secretKey);\n        String upToken = auth.uploadToken(bucket);\n\n        try {\n            Response response = uploadManager.put(file,key,upToken,null, null);\n            //解析上传成功的结果\n            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);\n            return origin+putRet.key;\n        } catch (QiniuException ex) {\n            Response r = ex.response;\n            log.warn(r.toString());\n            try {\n                return r.bodyString();\n            } catch (QiniuException e) {\n                throw new YmallUploadException(e.toString());\n            }\n        }\n    }\n\n    public static String getUpToken() {\n        return auth.uploadToken(bucket, null, 3600, new StringMap().put(\"insertOnly\", 1));\n    }\n\n    public static String qiniuBase64Upload(String data64){\n\n        String key = renamePic(\".png\");\n        Auth auth = Auth.create(accessKey, secretKey);\n        String upToken = auth.uploadToken(bucket);\n        //服务端http://up-z2.qiniup.com\n        String url = \"http://up-z2.qiniup.com/putb64/-1/key/\"+ UrlSafeBase64.encodeToString(key);\n        RequestBody rb = RequestBody.create(null, data64);\n        Request request = new Request.Builder().\n                url(url).\n                addHeader(\"Content-Type\", \"application/octet-stream\")\n                .addHeader(\"Authorization\", \"UpToken \" + getUpToken())\n                .post(rb).build();\n        OkHttpClient client = new OkHttpClient();\n        okhttp3.Response response = null;\n        try {\n            response = client.newCall(request).execute();\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        return origin+key;\n    }\n\n    public static String base64Data(String data){\n\n        if(data==null||data.isEmpty()){\n            return \"\";\n        }\n        String base64 =data.substring(data.lastIndexOf(\",\")+1);\n        return base64;\n    }\n\n    /**\n     * 以时间戳重命名\n     * @param fileName\n     * @return\n     */\n    public static String renamePic(String fileName){\n        String extName = fileName.substring(fileName.lastIndexOf(\".\"));\n        return System.currentTimeMillis()+extName;\n    }\n\n    public static String isValidImage(HttpServletRequest request, MultipartFile file){\n        //最大文件大小\n        long maxSize = 5242880;\n        //定义允许上传的文件扩展名\n        HashMap<String, String> extMap = new HashMap<String, String>();\n        extMap.put(\"image\", \"gif,jpg,jpeg,png,bmp\");\n\n        if(!ServletFileUpload.isMultipartContent(request)){\n            return \"请选择文件\";\n        }\n\n        if(file.getSize() > maxSize){\n            return \"上传文件大小超过5MB限制\";\n        }\n        //检查扩展名\n        String fileName=file.getOriginalFilename();\n        String fileExt = fileName.substring(fileName.lastIndexOf(\".\") + 1).toLowerCase();\n        if(!Arrays.<String>asList(extMap.get(\"image\").split(\",\")).contains(fileExt)){\n            return \"上传文件扩展名是不允许的扩展名\\n只允许\" + extMap.get(\"image\") + \"格式\";\n        }\n\n        return \"valid\";\n    }\n\n    public static String checkExt(String fileName,String dirName){\n        //定义允许上传的文件扩展名\n        HashMap<String, String> extMap = new HashMap<String, String>();\n        extMap.put(\"image\", \"gif,jpg,jpeg,png,bmp\");\n        extMap.put(\"flash\", \"swf,flv\");\n        extMap.put(\"media\", \"swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb\");\n\n        //检查扩展名\n        String fileExt = fileName.substring(fileName.lastIndexOf(\".\") + 1).toLowerCase();\n        if(!Arrays.<String>asList(extMap.get(dirName).split(\",\")).contains(fileExt)){\n            return \"上传文件扩展名是不允许的扩展名\\n只允许\" + extMap.get(dirName) + \"格式\";\n        }\n        return \"valid\";\n    }\n\n    public static void main(String[] args){\n        base64Data(\"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2\");\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/commons/utils/ThreadPoolUtil.java",
    "content": "package com.yuu.ymall.web.admin.commons.utils;\n\nimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.BlockingQueue;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * 线程池工具类\n *\n * @Classname ThreadPoolUtil\n * @Date 2019/5/13 16:43\n * @Created by Yuu\n */\npublic class ThreadPoolUtil {\n\n    //线程缓冲队列\n    private static BlockingQueue<Runnable> bqueue = new ArrayBlockingQueue<Runnable>(100);\n    // 核心线程数，会一直存活，即使没有任务，线程池也会维护线程的最少数量\n    private static final int SIZE_CORE_POOL = 5;\n    // 线程池维护线程的最大数量\n    private static final int SIZE_MAX_POOL = 10;\n    // 线程池维护线程所允许的空闲时间\n    private static final long ALIVE_TIME = 2000;\n\n    private static ThreadPoolExecutor pool = new ThreadPoolExecutor(SIZE_CORE_POOL, SIZE_MAX_POOL, ALIVE_TIME, TimeUnit.MILLISECONDS, bqueue, new ThreadPoolExecutor.CallerRunsPolicy());\n    static {\n        pool.prestartAllCoreThreads();\n    }\n\n    public static ThreadPoolExecutor getPool() {\n        return pool;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbAddressMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbAddress;\n\npublic interface TbAddressMapper extends BaseMapper<TbAddress> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(Long id);\n\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbExpressMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbExpress;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface TbExpressMapper extends BaseMapper<TbExpress> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(Integer id);\n\n    /**\n     * 获取快递列表\n     *\n     * @param params 参数\n     * @return\n     */\n    List<TbExpress> getExpressList(Map<String, Object> params);\n\n    /**\n     * 获取快递总数\n     *\n     * @param params 参数\n     * @return\n     */\n    int getTbExpressCount(Map<String, Object> params);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbItemCatMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbItemCat;\n\nimport java.util.List;\n\npublic interface TbItemCatMapper extends BaseMapper<TbItemCat> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(Long id);\n\n    /**\n     * 根据父 ID 查询分类列表\n     *\n     * @param parentId 父 id\n     * @return\n     */\n    List<TbItemCat> getItemCatList(Long parentId);\n\n    /**\n     * 查询该分类最大的排序值\n     *\n     * @param parentId 父 id\n     * @return\n     */\n    int getMaxSortOrder(Long parentId);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbItemDescMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbItemDesc;\n\npublic interface TbItemDescMapper extends BaseMapper<TbItemDesc> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(Long id);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbItemMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbItem;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface TbItemMapper extends BaseMapper<TbItem> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(Long id);\n\n    /**\n     * 获取商品总数\n     *\n     * @return\n     */\n    int getAllItemCount();\n\n    /**\n     * 有条件的查询商品集合\n     * @param cid 分类 id\n     * @return\n     */\n    List<TbItem> selectItemByCondition(@Param(\"cid\") Long cid, @Param(\"search\") String search);\n\n    /**\n     * 根据分类 id 查询商品集合\n     *\n     * @param params 查询条件\n     * @return\n     */\n    List<TbItem> getItemByCid(Map<String, Object> params);\n\n    /**\n     * 查询分类商品总数\n     *\n     * @param params 查询条件\n     * @return\n     */\n    int getTbItemByCidCount(Map<String, Object> params);\n\n    /**\n     * 下架商品\n     *\n     * @param id 商品 id\n     */\n    int stopItemById(Long id);\n\n    /**\n     * 发布商品\n     *\n     * @param id 商品 id\n     */\n    int startItemById(Long id);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbMemberMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbMember;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\npublic interface TbMemberMapper extends BaseMapper<TbMember> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(Long id);\n\n    /**\n     * 获取会员总数\n     *\n     * @return\n     */\n    int getAllMemberCount();\n\n    /**\n     * 获取会员列表\n     *\n     * @param search 查询条件\n     * @return\n     */\n    List<TbMember> getMemberList(@Param(\"search\") String search);\n\n    /**\n     * 获取会员列表总数\n     *\n     * @param search 查询条件\n     * @return\n     */\n    int getMemberListCount(@Param(\"search\") String search);\n\n    /**\n     * 根据会员名查询会员\n     *\n     * @param username 会员名\n     * @return\n     */\n    TbMember getMemberByUsername(String username);\n\n    /**\n     * 根据手机号查询会员\n     *\n     * @param phone 手机号\n     * @return\n     */\n    TbMember getMemberByPhone(String phone);\n\n    /**\n     * 根据邮箱查询会员\n     *\n     * @param email 邮箱\n     * @return\n     */\n    TbMember getMemberByEmail(String email);\n\n    /**\n     * 获取被封禁的会员列表\n     *\n     * @param search 搜索条件\n     * @return\n     */\n    List<TbMember> getMemberBanList(@Param(\"search\") String search);\n\n    /**\n     * 获取被封禁的会员总数\n     *\n     * @param search 搜索条件\n     * @return\n     */\n    int getMemberBanListCount(@Param(\"search\") String search);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbOrderItemMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbOrderItem;\n\nimport java.util.List;\n\npublic interface TbOrderItemMapper extends BaseMapper<TbOrderItem> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(String id);\n\n    /**\n     * 获取本周热门商品\n     *\n     * @return\n     */\n    List<TbOrderItem> getWeekHot();\n\n    /**\n     * 查看商品是否有订单项\n     *\n     * @param id 商品 id\n     * @return\n     */\n    int selectByItemId(Long id);\n\n    /**\n     * 根据订单 id，查询所有订单项\n     *\n     * @param id 订单 id\n     * @return\n     */\n    List<TbOrderItem> selectOrderItemByOrderId(String orderId);\n\n    /**\n     * 查询该商品订单数量\n     *\n     * @param itemId 商品 id\n     * @return\n     */\n    int selectOrderNumByItemId(Long itemId);\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbOrderMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbOrder;\nimport com.yuu.ymall.web.admin.commons.dto.OrderChartData;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.Date;\nimport java.util.List;\nimport java.util.Map;\n\npublic interface TbOrderMapper extends BaseMapper<TbOrder> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(String id);\n\n    /**\n     * 根据主键 id 查询\n     *\n     * @param id\n     * @return\n     */\n    TbOrder selectByPrimaryKey(String id);\n\n\n    /**\n     * 获取订单总数\n     *\n     * @return\n     */\n    int getAllOrderCount();\n\n    /**\n     * 获取订单列表\n     *\n     * @param params 参数\n     * @return\n     */\n    List<TbOrder> getOrderList(Map<String, Object> params);\n\n    /**\n     * 获取订单列表数量\n     *\n     * @param params 参数\n     * @return\n     */\n    int getTbOrderCount(Map<String, Object> params);\n\n\n    /**\n     * 查询图表数据\n     *\n     * @param startTime 开始时间\n     * @param endTime 结束时间\n     * @return\n     */\n    List<OrderChartData> selectOrderChart(@Param(\"startTime\") Date startTime, @Param(\"endTime\") Date endTime);\n\n    /**\n     * 按年份查询图表数据\n     *\n     * @param year 年份\n     * @return\n     */\n    List<OrderChartData> selectOrderChartByYear(int year);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbOrderShippingMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbOrderShipping;\n\npublic interface TbOrderShippingMapper extends BaseMapper<TbOrderShipping> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(String id);\n\n    /**\n     * 根据主键 id 查询\n     *\n     * @param id\n     * @return\n     */\n    TbOrderShipping selectByPrimaryKey(String id);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbPanelContentMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbPanelContent;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface TbPanelContentMapper extends BaseMapper<TbPanelContent> {\n\n    /**\n     * 根据主键 id 删除数据\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(Integer id);\n\n    /**\n     *  添加查询板块内容\n     * @param params 参数\n     * @return\n     */\n    List<TbPanelContent> getTbPanelContentByPanelId(Map<String, Object> params);\n\n\n    /**\n     * 条件查询板块内容总数目\n     * @param params 查询参数\n     * @return\n     */\n    int getTbPanelContentCount(Map<String, Object> params);\n\n    /**\n     * 根据商品 ID 查询商品是否关联首页内容\n     * @param id 商品 id\n     * @return\n     */\n    int selectContentByIid(Long id);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbPanelMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbPanel;\n\nimport java.util.List;\nimport java.util.Map;\n\npublic interface TbPanelMapper extends BaseMapper<TbPanel> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(Integer id);\n\n    /**\n     * 根据条件查询所有板块\n     *\n     * @param params\n     * @return\n     */\n    List<TbPanel> getPanelList(Map<String, Object> params);\n\n    /**\n     * 根据板块的类型查询板块\n     *\n     * @param type\n     * @return\n     */\n    TbPanel getPanelByType(int type);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/mapper/TbUserMapper.java",
    "content": "package com.yuu.ymall.web.admin.mapper;\n\nimport com.yuu.ymall.commons.persistence.BaseMapper;\nimport com.yuu.ymall.domain.TbUser;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\npublic interface TbUserMapper extends BaseMapper<TbUser> {\n\n    /**\n     * 根据主键 id 删除数据\n     *\n     * @param id\n     * @return\n     */\n    int deleteByPrimaryKey(Long id);\n\n    /**\n     * 根据用户名获取用户\n     *\n     * @param username 用户名\n     * @return\n     */\n    TbUser getUserByUsername(String username);\n\n    /**\n     * 获取用户列表\n     *\n     * @param search 搜索条件\n     * @return\n     */\n    List<TbUser> getUserList(@Param(\"search\") String search);\n\n    /**\n     * 获取用户总数\n     *\n     * @param search 搜索条件\n     * @return\n     */\n    int getUserListCount(@Param(\"search\") String search);\n\n    /**\n     * 根据手机号获取用户\n     *\n     * @param phone 手机号\n     * @return\n     */\n    TbUser getUserByPhone(String phone);\n\n    /**\n     * 根据邮箱获取用户\n     *\n     * @param email 邮箱\n     * @return\n     */\n    TbUser getUserByEmail(String email);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/repositories/ItemRepository.java",
    "content": "package com.yuu.ymall.web.admin.repositories;\n\nimport com.yuu.ymall.web.admin.commons.es.ESItem;\nimport org.springframework.data.elasticsearch.repository.ElasticsearchRepository;\n\n/**\n * @author by Yuu\n * @classname ItemRepository\n * @date 2019/7/9 19:51\n */\npublic interface ItemRepository extends ElasticsearchRepository<ESItem, Long> {\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/ContentService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbPanelContent;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname ContentService\n * @Date 2019/5/16 23:52\n * @Created by Yuu\n */\npublic interface ContentService {\n\n\n    /**\n     * 通过板块 id 分页查询板块内容\n     *\n     * @param request 请求\n     * @param panelId 板块 id\n     * @param search 搜索条件\n     * @return\n     */\n    DataTablesResult<TbPanelContent> getPanelContentListByPanelId(HttpServletRequest request, int panelId, String search);\n\n    /**\n     * 删除板块内容\n     *\n     * @param id 板块内容 id 集合\n     * @return\n     */\n    BaseResult deletePanelContent(int[] ids);\n\n    /**\n     * 新增或编辑板块内容\n     *\n     * @param tbPanelContent 板块内容\n     * @return\n     */\n    BaseResult saveContent(TbPanelContent tbPanelContent);\n\n    /**\n     * 查询商品是否关联首页板块内容\n     *\n     * @param id 商品 id\n     */\n    int selectContentByIid(Long id);\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/CountService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\n\n/**\n * @author by Yuu\n * @classname CountService\n * @date 2019/6/21 11:03\n */\npublic interface CountService {\n\n    /**\n     * 订单销量统计\n     *\n     * @param type 类型\n     * @param startTime 开始时间\n     * @param endTime 结束时间\n     * @param year 年份\n     * @return\n     */\n    BaseResult countOrder(int type, String startTime, String endTime, int year);\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/ExpressService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbExpress;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname ExpressService\n * @Date 2019/6/15 18:59\n * @Created by Yuu\n */\npublic interface ExpressService {\n\n    /**\n     * 获取快递列表\n     *\n     * @param request 请求\n     * @param search 搜索参数\n     * @return\n     */\n    DataTablesResult<TbExpress> getExpressList(HttpServletRequest request, String search);\n\n    /**\n     * 保存快递\n     *\n     * @param tbExpress 快递\n     * @return\n     */\n    BaseResult save(TbExpress tbExpress);\n\n    /**\n     * 删除快递\n     * @param ids\n     * @return\n     */\n    BaseResult delete(Integer[] ids);\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/ItemCatService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbItemCat;\nimport com.yuu.ymall.web.admin.commons.dto.ZTreeNode;\n\nimport java.util.List;\n\n/**\n * @Classname ItemCatService\n * @Date 2019/6/3 14:52\n * @Created by Yuu\n */\npublic interface ItemCatService {\n\n    /**\n     * 根据父类 id 查询分类列表\n     *\n     * @param parentId 根据父类 id 查询分类列表\n     * @param type zTree 展示数据类型 -1 不展示所有商品，0 展示所有商品\n     * @return\n     */\n    List<ZTreeNode> getItemCatList(Long parentId, int type);\n\n    /**\n     * 添加编辑商品分类\n     *\n     * @param tbItemCat 商品分类\n     * @return\n     */\n    BaseResult saveItemCat(TbItemCat tbItemCat);\n\n    /**\n     * 删除商品分类\n     *\n     * @param id 分类 id\n     * @return\n     */\n    BaseResult deleteItemCat(Long id);\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/ItemService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbItem;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.commons.dto.ItemDto;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname ItemService\n * @Date 2019/5/15 22:28\n * @Created by Yuu\n */\npublic interface ItemService {\n\n    /**\n     * 获取商品总数\n     * @return\n     */\n    int getAllItemCount();\n\n\n    /**\n     * 分页搜索排序获取商品列表\n     *\n     * @param request 请求\n     * @param cid 分类 id\n     * @param search 查询条件\n     * @return\n     */\n    DataTablesResult<TbItem> getItemListByCid(HttpServletRequest request, Long cid, String search);\n\n    /**\n     * 根据商品 id 集合，删除商品\n     *\n     * @param ids 商品 id 集合\n     * @return\n     */\n    BaseResult deleteItem(Long[] ids);\n\n    /**\n     * 根据商品 id 下架商品\n     *\n     * @param id 商品 id\n     * @return\n     */\n    BaseResult stopItem(Long id);\n\n    /**\n     * 根据商品 id 发布商品\n     *\n     * @param id 商品 id\n     * @return\n     */\n    BaseResult startItem(Long id);\n\n    /**\n     * 保存商品：有 id 编辑商品，无 id 新增商品\n     *\n     * @param itemDto 商品 DTO\n     * @return\n     */\n    BaseResult saveItem(ItemDto itemDto);\n\n    /**\n     * 根据商品 ID 获取商品\n     *\n     * @param itemId 商品 ID\n     * @return\n     */\n    BaseResult getItemById(Long itemId);\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/MemberService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbMember;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname MemberService\n * @Date 2019/5/15 22:12\n * @Created by Yuu\n */\npublic interface MemberService {\n    /**\n     * 获取会员总数\n     *\n     * @return\n     */\n    int getAllMemberCount();\n\n    /**\n     * 获取会员列表\n     *\n     * @param request 请求\n     * @param search 搜索条件\n     * @return\n     */\n    DataTablesResult<TbMember> getMemberList(HttpServletRequest request, String search);\n\n    /**\n     * 封禁会员\n     *\n     * @param id 会员 id\n     * @return\n     */\n    BaseResult banMember(Long id);\n\n    /**\n     * 解封会员\n     *\n     * @param id 会员 id 集合\n     * @return\n     */\n    BaseResult startMember(Long[] ids);\n\n    /**\n     * 保存会员\n     *\n     * @param tbMember 会员\n     * @return\n     */\n    BaseResult saveMember(TbMember tbMember);\n\n    /**\n     * 根据会员名获取会员\n     *\n     * @param username 会员名\n     * @param  id 会员 id\n     * @return\n     */\n    Boolean getMemberByUsername(String username, Long id);\n\n    /**\n     * 根据手机号获取会员\n     *\n     * @param phone 手机号\n     * @param id 会员 id\n     * @return\n     */\n    Boolean getMemberByPhone(String phone, Long id);\n\n    /**\n     * 根据邮箱获取会员\n     *\n     * @param email 邮箱\n     * @param id 会员 id\n     * @return\n     */\n    Boolean getMemberByEmail(String email, Long id);\n\n    /**\n     * 修改会员密码\n     *\n     * @param id 会员 id\n     * @param password 会员 密码\n     * @return\n     */\n    BaseResult changeMemberPassword(Long id, String password);\n\n    /**\n     * 删除会员\n     * @param ids\n     * @return\n     */\n    BaseResult deleteMember(Long[] ids);\n\n    /**\n     * 获取被封禁的会员列表\n     *\n     * @param request 请求\n     * @param search 搜索条件\n     * @return\n     */\n    DataTablesResult<TbMember> getMemberBanList(HttpServletRequest request, String search);\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/OrderService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbOrder;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname OrderService\n * @Date 2019/5/15 22:35\n * @Created by Yuu\n */\npublic interface OrderService {\n\n    /**\n     * 获取订单总数\n     *\n     * @return\n     */\n    int getAllOrderCount();\n\n    /**\n     * 获取订单列表\n     *\n     * @param request 请求\n     * @param search 查询条件\n     * @param status 订单状态\n     * @return\n     */\n    DataTablesResult<TbOrder> getOrderList(HttpServletRequest request, String search, int status);\n\n    /**\n     * 获取订单详情\n     *\n     * @param id 订单 id\n     * @return\n     */\n    BaseResult getOrderDetail(String id);\n\n    /**\n     * 订单发货\n     *\n     * @param orderId 订单 id\n     * @param shippingName 快递名称\n     * @param shippingCode 快递单号\n     * @return\n     */\n    BaseResult deliver(String orderId, String shippingName, String shippingCode);\n\n    /**\n     * 管理员取消订单\n     *\n     * @param orderId 订单id\n     * @return\n     */\n    BaseResult cancelOrderByAdmin(String orderId);\n\n    /**\n     * 根据订单 id 集合删除订单\n     *\n     * @param ids 订单 id 集合\n     * @return\n     */\n    BaseResult deleteOrderByIds(String[] ids);\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/PanelService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbPanel;\nimport com.yuu.ymall.web.admin.commons.dto.ZTreeNode;\n\nimport java.util.List;\n\n/**\n * @Classname PanelService\n * @Date 2019/5/20 8:54\n * @Created by Yuu\n */\npublic interface PanelService {\n\n    /**\n     * 获取板块类目\n     *\n     * @param type\n     * @return\n     */\n    List<ZTreeNode> getPanelList(int type);\n\n    /**\n     * 编辑内容板块\n     *\n     * @param tbPanel 板块\n     * @return\n     */\n    BaseResult updatePanel(TbPanel tbPanel);\n\n    /**\n     * 根据板块 id 删除板块\n     *\n     * @param id 板块 id\n     * @return\n     */\n    BaseResult deletePanelById(int id);\n\n    /**\n     * 新增内容板块\n     *\n     * @param tbPanel 板块\n     * @return\n     */\n    BaseResult addPanel(TbPanel tbPanel);\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/SearchService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\n/**\n * 搜索服务\n *\n * @author by Yuu\n * @classname SearchService\n * @date 2019/7/9 19:48\n */\npublic interface SearchService {\n\n    /**\n     * 同步单个索引\n     *\n     * @param type 0 更新索引 1 删除索引\n     * @param itemId 商品 id\n     * @return\n     */\n    void refreshItem(int type, Long itemId);\n\n    /**\n     * 同步所有索引\n     *\n     * @return\n     */\n    void importAllItems();\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/SystemService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\n\n/**\n * @Classname SystemService\n * @Date 2019/5/11 20:21\n * @Created by Yuu\n */\npublic interface SystemService {\n\n    /**\n     * 获取本周热销商品\n     *\n     * @return\n     */\n    BaseResult getWeekHot();\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/UserService.java",
    "content": "package com.yuu.ymall.web.admin.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbUser;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname UserService\n * @Date 2019/5/11 18:49\n * @author by Yuu\n */\npublic interface UserService {\n\n    /**\n     * 根据用户名获取用户信息\n     *\n     * @param username\n     * @return\n     */\n    TbUser getUserByUsername(String username);\n\n    /**\n     * 获取用户列表\n     * @param request 请求\n     * @param search 搜索条件\n     * @return\n     */\n    DataTablesResult<TbUser> getUserList(HttpServletRequest request, String search);\n\n    /**\n     * 验证用户名是否存在\n     *\n     * @param id 用户 id\n     * @param username 用户名\n     * @return\n     */\n    Boolean validateUsername(Long id, String username);\n\n    /**\n     * 验证手机号是否存在\n     *\n     * @param id 用户 id\n     * @param phone 手机号\n     * @return\n     */\n    Boolean validatePhone(Long id, String phone);\n\n    /**\n     * 验证邮箱是否存在\n     *\n     * @param id 用户 id\n     * @param email 邮箱\n     * @return\n     */\n    Boolean validateEmail(Long id, String email);\n\n    /**\n     * 保存用户\n     *\n     * @param tbUser 用户\n     * @return\n     */\n    BaseResult save(TbUser tbUser);\n\n    /**\n     * 修改密码\n     *\n     * @param id 用户 id\n     * @param password 用户密码\n     * @return\n     */\n    BaseResult changePass(Long id, String password);\n\n    /**\n     * 删除用户\n     *\n     * @param ids 用户 id 的集合\n     * @return\n     */\n    BaseResult delete(Long[] ids);\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/ContentServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport com.github.pagehelper.PageHelper;\nimport com.github.pagehelper.PageInfo;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.domain.TbItem;\nimport com.yuu.ymall.domain.TbPanelContent;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.mapper.TbItemMapper;\nimport com.yuu.ymall.web.admin.mapper.TbPanelContentMapper;\nimport com.yuu.ymall.web.admin.service.ContentService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @Classname ContentServiceImpl\n * @Date 2019/5/16 23:52\n * @Created by Yuu\n */\n@Service\n@Transactional(readOnly = true)\npublic class ContentServiceImpl implements ContentService {\n\n    @Autowired\n    private TbPanelContentMapper tbPanelContentMapper;\n\n    @Autowired\n    private TbItemMapper tbItemMapper;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    /**\n     * 首页商品缓存 key\n     */\n    @Value(\"PRODUCT_HOME\")\n    private String PRODUCT_HOME;\n\n    @Value(\"0\")\n    private int HEADER_PANEL_ID;\n\n    @Value(\"HEADER_PANEL\")\n    private String HEADER_PANEL;\n\n    @Override\n    public DataTablesResult<TbPanelContent> getPanelContentListByPanelId(HttpServletRequest request, int panelId, String search) {\n        DataTablesResult<TbPanelContent> result = new DataTablesResult<>(request);\n\n        Map<String, Object> params = new HashMap<>();\n        params.put(\"panelId\", panelId);\n        params.put(\"search\", search);\n\n        // 分页查询\n        PageHelper.startPage(result.getPageNum(), result.getLength());\n        List<TbPanelContent> tbPanelContentList = tbPanelContentMapper.getTbPanelContentByPanelId(params);\n\n        // 封装内容\n        for (TbPanelContent tbPanelContent : tbPanelContentList) {\n            if (tbPanelContent.getProductId() != null) {\n                TbItem tbItem = tbItemMapper.selectByPrimaryKey(tbPanelContent.getProductId());\n                tbPanelContent.setProductName(tbItem.getTitle());\n                tbPanelContent.setSalePrice(tbItem.getPrice());\n                tbPanelContent.setSubTitle(tbItem.getSellPoint());\n            }\n        }\n\n        PageInfo<TbPanelContent> tbPanelContentPageInfo = new PageInfo<>(tbPanelContentList);\n        result.setRecordsFiltered((int) tbPanelContentPageInfo.getTotal());\n        result.setRecordsTotal(tbPanelContentMapper.getTbPanelContentCount(params));\n        result.setDraw(result.getDraw());\n        result.setData(tbPanelContentList);\n\n        return result;\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult deletePanelContent(int[] ids) {\n        // 删除板块内容\n        int result = 0;\n        for (int id : ids) {\n            result = tbPanelContentMapper.deleteByPrimaryKey(id);\n            if (result != 1) {\n                return BaseResult.fail(\"删除板块内容失败！\");\n            }\n            // 同步导航栏缓存\n            if (id == HEADER_PANEL_ID) {\n                updateNavListRedis();\n            }\n        }\n        // 同步缓存\n        deleteHomeRedis();\n        return BaseResult.success();\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult saveContent(TbPanelContent tbPanelContent) {\n        tbPanelContent.setUpdated(new Date());\n\n        int result;\n\n        // 新增\n        if (tbPanelContent.getId() == null) {\n            tbPanelContent.setCreated(new Date());\n            result = tbPanelContentMapper.insert(tbPanelContent);\n\n            if (result == 0) {\n                return BaseResult.fail(\"添加导航栏失败！\");\n            }\n        }\n\n        // 编辑\n        else {\n            result = tbPanelContentMapper.updateByPrimaryKey(tbPanelContent);\n\n            // 更新失败\n            if (result != 1) {\n                return BaseResult.fail(\"更新板块内容失败！\");\n            }\n        }\n\n        // 删除导航栏缓存\n        if (tbPanelContent.getPanelId() == HEADER_PANEL_ID) {\n            updateNavListRedis();\n        }\n\n        // 删除首页缓存\n        deleteHomeRedis();\n        return BaseResult.success(\"保存导航栏成功！\");\n    }\n\n    @Override\n    public int selectContentByIid(Long id) {\n        return tbPanelContentMapper.selectContentByIid(id);\n    }\n\n    /**\n     * 删除导航栏缓存\n     */\n    private void updateNavListRedis() {\n        redisCacheManager.del(HEADER_PANEL);\n    }\n\n    /**\n     * 同步缓存\n     */\n    private void deleteHomeRedis() {\n        redisCacheManager.del(PRODUCT_HOME);\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/CountServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport cn.hutool.core.date.DateUnit;\nimport cn.hutool.core.date.DateUtil;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.utils.TimeUtil;\nimport com.yuu.ymall.web.admin.commons.consts.Consts;\nimport com.yuu.ymall.web.admin.commons.dto.ChartData;\nimport com.yuu.ymall.web.admin.commons.dto.OrderChartData;\nimport com.yuu.ymall.web.admin.mapper.TbOrderMapper;\nimport com.yuu.ymall.web.admin.service.CountService;\nimport org.apache.commons.lang3.time.DateUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.math.BigDecimal;\nimport java.util.ArrayList;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @author by Yuu\n * @classname CountServiceImpl\n * @date 2019/6/21 11:03\n */\n@Service\npublic class CountServiceImpl implements CountService {\n\n    @Autowired\n    private TbOrderMapper tbOrderMapper;\n\n    @Override\n    public BaseResult countOrder(int type, String startTime, String endTime, int year) {\n        ChartData chartData = new ChartData();\n        Date startDate = null, endDate = null;\n        if (type == Consts.CUSTOM_DATE) {\n            startDate = DateUtil.beginOfDay(DateUtil.parse(startTime));\n            endDate = DateUtil.endOfDay(DateUtil.parse(endTime));\n            long betweenDay = DateUtil.between(startDate, endDate, DateUnit.DAY);\n            if (betweenDay > 31) {\n                return BaseResult.fail(\"所选日期范围过长，最多不能超过31天\");\n            }\n        }\n        List<OrderChartData> list = getOrderCountData(type, startDate, endDate, year);\n        List<Object> xDatas = new ArrayList<>();\n        List<Object> yDatas = new ArrayList<>();\n        BigDecimal countAll = new BigDecimal(\"0\");\n        for (OrderChartData orderChartData : list) {\n            if (type == Consts.CUSTOM_YEAR) {\n                xDatas.add(DateUtil.format(orderChartData.getTime(), \"yyyy-MM\"));\n            } else {\n                xDatas.add(DateUtil.formatDate(orderChartData.getTime()));\n            }\n            yDatas.add(orderChartData.getMoney());\n            countAll = countAll.add(orderChartData.getMoney());\n        }\n        chartData.setxDatas(xDatas);\n        chartData.setyDatas(yDatas);\n        chartData.setCountAll(countAll);\n        return BaseResult.success(chartData);\n    }\n\n    private List<OrderChartData> getOrderCountData(int type, Date startTime, Date endTime, int year) {\n        List<OrderChartData> fullData = new ArrayList<>();\n\n        List<OrderChartData> data;\n\n        switch (type) {\n            // 本周\n            case 0:\n                data = tbOrderMapper.selectOrderChart(TimeUtil.getBeginDayOfWeek(), TimeUtil.getEndDayOfWeek());\n                fullData = getFullData(data, TimeUtil.getBeginDayOfWeek(), TimeUtil.getEndDayOfWeek());\n                break;\n            // 本月\n            case 1:\n                data = tbOrderMapper.selectOrderChart(TimeUtil.getBeginDayOfMonth(), TimeUtil.getEndDayOfMonth());\n                fullData = getFullData(data, TimeUtil.getBeginDayOfMonth(), TimeUtil.getEndDayOfMonth());\n                break;\n            // 上月\n            case 2:\n                data = tbOrderMapper.selectOrderChart(TimeUtil.getBeginDayOfLastMonth(), TimeUtil.getEndDayOfLastMonth());\n                fullData = getFullData(data, TimeUtil.getBeginDayOfLastMonth(), TimeUtil.getEndDayOfLastMonth());\n                break;\n            // 自定义\n            case -1:\n                data = tbOrderMapper.selectOrderChart(startTime, endTime);\n                fullData = getFullData(data, startTime, endTime);\n                break;\n            // 按年份\n            case -2:\n                data = tbOrderMapper.selectOrderChartByYear(year);\n                fullData = getFullYearData(data, year);\n                break;\n        }\n        return fullData;\n    }\n\n    /**\n     * 无数据补0\n     *\n     * @param data      数据\n     * @param startTime 开始时间\n     * @param endTime   结束时间\n     * @return\n     */\n    private List<OrderChartData> getFullData(List<OrderChartData> data, Date startTime, Date endTime) {\n        List<OrderChartData> fullData = new ArrayList<>();\n\n        // 相差\n        long betweenDay = DateUtil.between(startTime, endTime, DateUnit.DAY);\n\n        // 起始时间\n        Date everyday = startTime;\n\n        int count = -1;\n        for (int i = 0; i <= betweenDay; i++) {\n            boolean flag = true;\n            for (OrderChartData chartData : data) {\n                if (DateUtils.isSameDay(chartData.getTime(), everyday)) {\n                    // 有数据\n                    flag = false;\n                    count++;\n                    break;\n                }\n            }\n            if (!flag) {\n                fullData.add(data.get(count));\n            } else {\n                OrderChartData orderChartData = new OrderChartData();\n                orderChartData.setTime(everyday);\n                orderChartData.setMoney(new BigDecimal(\"0\"));\n                fullData.add(orderChartData);\n            }\n\n            // 时间 +1 天\n            Calendar cal = Calendar.getInstance();\n            cal.setTime(everyday);\n            cal.add(Calendar.DAY_OF_MONTH, 1);\n            everyday = cal.getTime();\n        }\n        return fullData;\n    }\n\n    /**\n     * 无数据补0\n     *\n     * @param data 数据\n     * @param year 年份\n     * @return\n     */\n    public List<OrderChartData> getFullYearData(List<OrderChartData> data, int year) {\n\n        List<OrderChartData> fullData = new ArrayList<>();\n        //起始月份\n        Date everyMonth = TimeUtil.getBeginDayOfYear(year);\n        int count = -1;\n        for (int i = 0; i < 12; i++) {\n            boolean flag = true;\n            for (OrderChartData chartData : data) {\n                if (DateUtil.month(chartData.getTime()) == DateUtil.month(everyMonth)) {\n                    //有数据\n                    flag = false;\n                    count++;\n                    break;\n                }\n            }\n            if (!flag) {\n                fullData.add(data.get(count));\n            } else {\n                OrderChartData orderChartData = new OrderChartData();\n                orderChartData.setTime(everyMonth);\n                orderChartData.setMoney(new BigDecimal(\"0\"));\n                fullData.add(orderChartData);\n            }\n\n            //时间+1天\n            Calendar cal = Calendar.getInstance();\n            cal.setTime(everyMonth);\n            cal.add(Calendar.MONTH, 1);\n            everyMonth = cal.getTime();\n        }\n        return fullData;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/ExpressServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport com.github.pagehelper.PageHelper;\nimport com.github.pagehelper.PageInfo;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbExpress;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.mapper.TbExpressMapper;\nimport com.yuu.ymall.web.admin.service.ExpressService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @Classname ExpressServiceImpl\n * @Date 2019/6/15 19:00\n * @Created by Yuu\n */\n@Service\n@Transactional(readOnly = true)\npublic class ExpressServiceImpl implements ExpressService {\n\n    @Autowired\n    private TbExpressMapper tbExpressMapper;\n\n    @Override\n    public DataTablesResult<TbExpress> getExpressList(HttpServletRequest request, String search) {\n        DataTablesResult<TbExpress> result = new DataTablesResult<>(request);\n\n        Map<String, Object> params = new HashMap<>();\n        params.put(\"search\", search);\n\n        // 分页查询\n        PageHelper.startPage(result.getPageNum(), result.getLength());\n        List<TbExpress> tbExpressList = tbExpressMapper.getExpressList(params);\n\n        // 封装 PageInfo\n        PageInfo<TbExpress> tbItemPageInfo = new PageInfo<>(tbExpressList);\n        result.setRecordsFiltered((int) tbItemPageInfo.getTotal());\n        result.setRecordsTotal(tbExpressMapper.getTbExpressCount(params));\n        result.setDraw(result.getDraw());\n        result.setData(tbExpressList);\n\n        return result;\n\n    }\n\n    @Transactional\n    @Override\n    public BaseResult save(TbExpress tbExpress) {\n\n        // 设置更新时间\n        tbExpress.setUpdated(new Date());\n\n        // 新增\n        if (tbExpress.getId() == null) {\n            tbExpress.setCreated(new Date());\n            tbExpressMapper.insert(tbExpress);\n        }\n\n        // 编辑\n        else {\n            tbExpressMapper.updateByPrimaryKey(tbExpress);\n        }\n        return BaseResult.success(\"保存物流信息成功！\");\n    }\n\n    @Transactional\n    @Override\n    public BaseResult delete(Integer[] ids) {\n        for (Integer id : ids) {\n            tbExpressMapper.deleteByPrimaryKey(id);\n        }\n        return BaseResult.success(\"删除快递成功！\");\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/ItemCatServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.domain.TbItemCat;\nimport com.yuu.ymall.web.admin.commons.dto.ZTreeNode;\nimport com.yuu.ymall.web.admin.commons.utils.DtoUtil;\nimport com.yuu.ymall.web.admin.mapper.TbItemCatMapper;\nimport com.yuu.ymall.web.admin.service.ItemCatService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.ArrayList;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @Classname ItemCatServiceImpl\n * @Date 2019/6/3 14:53\n * @Created by Yuu\n */\n@Service\n@Transactional(readOnly = true)\npublic class ItemCatServiceImpl implements ItemCatService {\n\n    @Autowired\n    private TbItemCatMapper tbItemCatMapper;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    @Value(\"${HEADER_CATE}\")\n    private String HEADER_CATE;\n\n    @Override\n    public List<ZTreeNode> getItemCatList(Long parentId, int type) {\n\n        // 根据父 id 查询分类列表\n        List<TbItemCat> tbItemCats = tbItemCatMapper.getItemCatList(parentId);\n\n        // 转换成 ZTreeNode\n        List<ZTreeNode> resultList = new ArrayList<>();\n\n        // 如果 type = -1 不展示所有商品，type = 0 展示所有商品\n        if (type == -1 && parentId == 0) {\n            tbItemCats.remove(0);\n        }\n        for (TbItemCat tbItemCat : tbItemCats) {\n            ZTreeNode node = DtoUtil.TbItemCat2ZTreeNode(tbItemCat);\n            resultList.add(node);\n        }\n\n        return resultList;\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult saveItemCat(TbItemCat tbItemCat) {\n        tbItemCat.setUpdated(new Date());\n\n        int result;\n        // 编辑商品分类\n        if (tbItemCat.getId() != null) {\n            result = tbItemCatMapper.updateByPrimaryKey(tbItemCat);\n        }\n\n        // 添加商品分类\n        else {\n            // 查询该子分类最大的排序值\n            int maxSortOrder = tbItemCatMapper.getMaxSortOrder(tbItemCat.getParentId());\n            // 默认排序值 +1\n            tbItemCat.setSortOrder(maxSortOrder + 1);\n            // 设置默认状态，开启\n            tbItemCat.setStatus(1);\n            tbItemCat.setCreated(new Date());\n            result = tbItemCatMapper.insert(tbItemCat);\n        }\n\n        // 删除 Redis 缓存\n        redisCacheManager.del(HEADER_CATE);\n\n        if (result != 1) {\n            return BaseResult.fail(\"保存商品分类失败\");\n        }\n\n        return BaseResult.success(\"保存商品分类成功\");\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult deleteItemCat(Long id) {\n\n        // 查询该节点所有子节点\n        List<ZTreeNode> nodes = getItemCatList(id, -1);\n        if (nodes.size() > 0) {\n            // 如果有子节点，则遍历删除子节点\n            for (ZTreeNode node : nodes) {\n                deleteItemCat((long) node.getId());\n            }\n        }\n\n        // 没有则直接删除节点\n        int result = tbItemCatMapper.deleteByPrimaryKey(id);\n        if (result != 1) {\n            return BaseResult.fail(\"删除商品分类失败！\");\n        }\n\n        // 删除 Redis 缓存\n        redisCacheManager.del(HEADER_CATE);\n\n        return BaseResult.success(\"删除商品分类成功\");\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/ItemServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport com.github.pagehelper.PageHelper;\nimport com.github.pagehelper.PageInfo;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.domain.TbItem;\nimport com.yuu.ymall.domain.TbItemCat;\nimport com.yuu.ymall.domain.TbItemDesc;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.commons.dto.ItemDto;\nimport com.yuu.ymall.web.admin.commons.utils.IDUtil;\nimport com.yuu.ymall.web.admin.mapper.*;\nimport com.yuu.ymall.web.admin.service.ItemService;\nimport com.yuu.ymall.web.admin.service.SearchService;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @Classname ItemServcieImpl\n * @Date 2019/5/15 22:28\n * @Created by Yuu\n */\n@Service\n@Transactional(readOnly = true)\npublic class ItemServiceImpl implements ItemService {\n\n    @Autowired\n    private TbItemMapper tbItemMapper;\n\n    @Autowired\n    private TbItemDescMapper tbItemDescMapper;\n\n    @Autowired\n    private TbItemCatMapper tbItemCatMapper;\n\n    @Autowired\n    private TbPanelContentMapper tbPanelContentMapper;\n\n    @Autowired\n    private TbOrderItemMapper tbOrderItemMapper;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    @Autowired\n    private SearchService searchService;\n\n    @Value(\"${PRODUCT_ITEM}\")\n    private String PRODUCT_ITEM;\n\n    @Override\n    public int getAllItemCount() {\n        int itemCount = tbItemMapper.getAllItemCount();\n        return itemCount;\n    }\n\n    @Override\n    public DataTablesResult<TbItem> getItemListByCid(HttpServletRequest request, Long cid, String search) {\n        DataTablesResult<TbItem> result = new DataTablesResult<>(request);\n\n        Map<String, Object> params = new HashMap<>();\n        params.put(\"cid\", cid);\n        params.put(\"search\", search);\n\n        // 分页查询\n        PageHelper.startPage(result.getPageNum(), result.getLength());\n        List<TbItem> tbItemList = tbItemMapper.getItemByCid(params);\n\n        // 封装 PageInfo\n        PageInfo<TbItem> tbItemPageInfo = new PageInfo<>(tbItemList);\n        result.setRecordsFiltered((int) tbItemPageInfo.getTotal());\n        result.setRecordsTotal(tbItemMapper.getTbItemByCidCount(params));\n        result.setDraw(result.getDraw());\n        result.setData(tbItemList);\n\n        return result;\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult deleteItem(Long[] ids) {\n        // 删除商品\n        for (Long id : ids) {\n            tbItemMapper.deleteByPrimaryKey(id);\n        }\n        return BaseResult.success(\"删除商品成功！\");\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult stopItem(Long id) {\n        tbItemMapper.stopItemById(id);\n        // 删除 ES 索引\n        searchService.refreshItem(-1, id);\n        return BaseResult.success(\"下架商品成功！\");\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult startItem(Long id) {\n        tbItemMapper.startItemById(id);\n        // 增加索引\n        searchService.refreshItem(0, id);\n        return BaseResult.success(\"发布商品成功！\");\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult saveItem(ItemDto itemDto) {\n        // 封装 TbItem\n        TbItem newTbItem = new TbItem();\n        BeanUtils.copyProperties(itemDto, newTbItem);\n        newTbItem.setUpdated(new Date());\n\n        // 封装 TbItemDesc\n        TbItemDesc tbItemDesc = new TbItemDesc();\n        tbItemDesc.setItemDesc(itemDto.getDetail());\n        tbItemDesc.setUpdated(new Date());\n\n        // 编辑商品\n        if (itemDto.getId() != null) {\n            // 编辑商品\n            TbItem oldTbItem = tbItemMapper.selectByPrimaryKey(itemDto.getId());\n            newTbItem.setStatus(oldTbItem.getStatus());\n            newTbItem.setCreated(oldTbItem.getCreated());\n            tbItemMapper.updateByPrimaryKey(newTbItem);\n\n            // 编辑商品详情\n            tbItemDesc.setItemId(newTbItem.getId());\n            tbItemDesc.setCreated(oldTbItem.getCreated());\n            tbItemDescMapper.updateByPrimaryKey(tbItemDesc);\n\n            // 同步缓存\n            redisCacheManager.del(PRODUCT_ITEM + \":\" + newTbItem.getId());\n\n            // 更新 ES 索引库\n            searchService.refreshItem(0, itemDto.getId());\n        }\n\n        // 新增商品\n        else {\n            // 新增商品\n            Long id = IDUtil.getRandomId();\n            newTbItem.setId(id);\n            newTbItem.setStatus(1);\n            newTbItem.setCreated(new Date());\n            tbItemMapper.insert(newTbItem);\n\n            // 新增商品详情\n            tbItemDesc.setItemId(id);\n            tbItemDesc.setCreated(new Date());\n            tbItemDescMapper.insert(tbItemDesc);\n\n            // 更新 ES 索引库\n            searchService.refreshItem(0, id);\n        }\n\n\n        return BaseResult.success(\"保存商品成功！\");\n    }\n\n    @Override\n    public BaseResult getItemById(Long itemId) {\n        ItemDto itemDto = new ItemDto();\n\n        // 封装 TbItem 属性\n        TbItem tbItem = tbItemMapper.selectByPrimaryKey(itemId);\n        BeanUtils.copyProperties(tbItem, itemDto);\n\n        // 封装 Cname\n        TbItemCat tbItemCat = tbItemCatMapper.selectByPrimaryKey(tbItem.getCid());\n        itemDto.setCname(tbItemCat.getName());\n\n        // 封装 TbItemDesc\n        TbItemDesc tbItemDesc = tbItemDescMapper.selectByPrimaryKey(itemId);\n        itemDto.setDetail(tbItemDesc.getItemDesc());\n\n        return BaseResult.success(itemDto);\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/MemberServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport com.github.pagehelper.PageHelper;\nimport com.github.pagehelper.PageInfo;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbMember;\nimport com.yuu.ymall.web.admin.commons.consts.Consts;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.mapper.TbMemberMapper;\nimport com.yuu.ymall.web.admin.service.MemberService;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.DigestUtils;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @Classname MemberServiceImpl\n * @Date 2019/5/15 22:12\n * @Created by Yuu\n */\n@Service\n@Transactional(readOnly = true)\npublic class MemberServiceImpl implements MemberService {\n\n    @Autowired\n    private TbMemberMapper tbMemberMapper;\n\n    @Override\n    public int getAllMemberCount() {\n        int memberCount = tbMemberMapper.getAllMemberCount();\n        return memberCount;\n    }\n\n    @Override\n    public DataTablesResult<TbMember> getMemberList(HttpServletRequest request, String search) {\n        // 初始化 DataTableResult\n        DataTablesResult<TbMember> result = new DataTablesResult<>(request);\n\n        // 设置 PageHelper\n        PageHelper.startPage(result.getPageNum(), result.getLength());\n        List<TbMember> tbMemberList = tbMemberMapper.getMemberList(search);\n\n        // 删除密码\n        for (TbMember tbMember : tbMemberList) {\n            tbMember.setPassword(\"\");\n        }\n\n        // 封装 PageHelper\n        PageInfo<TbMember> tbMemberPageInfo = new PageInfo<>(tbMemberList);\n        result.setRecordsFiltered((int) tbMemberPageInfo.getTotal());\n        result.setRecordsTotal(tbMemberMapper.getMemberListCount(search));\n        result.setDraw(result.getDraw());\n        result.setData(tbMemberList);\n\n        return result;\n    }\n\n    @Transactional\n    @Override\n    public BaseResult banMember(Long id) {\n        // 查询会员\n        TbMember tbMember = tbMemberMapper.selectByPrimaryKey(id);\n\n        // 设置会员状态\n        tbMember.setState(Consts.MEMBER_BAN);\n        tbMember.setUpdated(new Date());\n\n        // 更新会员\n        tbMemberMapper.updateByPrimaryKey(tbMember);\n\n        return BaseResult.success(\"封禁会员成功！\");\n    }\n\n    @Transactional\n    @Override\n    public BaseResult startMember(Long[] ids) {\n        for (Long id : ids) {\n            // 查询会员\n            TbMember tbMember = tbMemberMapper.selectByPrimaryKey(id);\n\n            // 设置会员状态\n            tbMember.setState(Consts.MEMBER_START);\n            tbMember.setUpdated(new Date());\n\n            // 更新会员\n            tbMemberMapper.updateByPrimaryKey(tbMember);\n        }\n        return BaseResult.success(\"解封会员成功！\");\n    }\n\n    @Transactional\n    @Override\n    public BaseResult saveMember(TbMember tbMember) {\n\n        // 查询用户名、手机号、邮箱是否被注册\n        if (!getMemberByUsername(tbMember.getUsername(), tbMember.getId())) {\n            return BaseResult.fail(\"用户名已被注册!\");\n        } else if (!getMemberByPhone(tbMember.getPhone(), tbMember.getId())) {\n            return BaseResult.fail(\"手机号已被注册！\");\n        } else if (!getMemberByEmail(tbMember.getEmail(), tbMember.getId())) {\n            return BaseResult.fail(\"邮箱已被注册！\");\n        }\n\n        // 封装 TbMember\n        TbMember newTbMember = new TbMember();\n        BeanUtils.copyProperties(tbMember, newTbMember);\n        newTbMember.setUpdated(new Date());\n\n\n        // 编辑会员\n        if (tbMember.getId() != null && tbMember.getId() != 0) {\n            // 查询出旧会员，封装数据\n            TbMember oldTbMember = tbMemberMapper.selectByPrimaryKey(tbMember.getId());\n            newTbMember.setState(oldTbMember.getState());\n            newTbMember.setCreated(oldTbMember.getCreated());\n            newTbMember.setPassword(oldTbMember.getPassword());\n\n            // 更新会员\n            tbMemberMapper.updateByPrimaryKey(newTbMember);\n        }\n\n        // 新增会员\n        else {\n            // 设置初始值\n            newTbMember.setCreated(new Date());\n            newTbMember.setState(Consts.MEMBER_START);\n\n            // 加密密码\n            newTbMember.setPassword(DigestUtils.md5DigestAsHex(tbMember.getPassword().getBytes()));\n\n            // 新增会员\n            tbMemberMapper.insert(newTbMember);\n        }\n        return BaseResult.success(\"保存会员成功！\");\n    }\n\n    @Override\n    public Boolean getMemberByUsername(String username, Long id) {\n        TbMember tbMember = tbMemberMapper.getMemberByUsername(username);\n\n        TbMember idTebMember = null;\n        if (id != null || id != 0) {\n            idTebMember = tbMemberMapper.selectByPrimaryKey(id);\n            if (idTebMember != null && tbMember != null) {\n                if (idTebMember.getUsername().equals(tbMember.getUsername())) {\n                    return true;\n                }\n            }\n        }\n\n        // 会员不存在，返回 true\n        if (tbMember == null) {\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public Boolean getMemberByPhone(String phone, Long id) {\n        TbMember tbMember = tbMemberMapper.getMemberByPhone(phone);\n\n        TbMember idTebMember = null;\n        if (id != null || id != 0) {\n            idTebMember = tbMemberMapper.selectByPrimaryKey(id);\n            if (idTebMember != null && tbMember != null) {\n                if (idTebMember.getPhone().equals(tbMember.getPhone())) {\n                    return true;\n                }\n            }\n        }\n\n        // 会员不存在，返回 true\n        if (tbMember == null) {\n            return true;\n        }\n        return false;\n    }\n\n    @Override\n    public Boolean getMemberByEmail(String email, Long id) {\n        TbMember tbMember = tbMemberMapper.getMemberByEmail(email);\n\n        TbMember idTebMember = null;\n        if (id != null || id != 0) {\n            idTebMember = tbMemberMapper.selectByPrimaryKey(id);\n            if (idTebMember != null && tbMember != null) {\n                if (idTebMember.getEmail().equals(tbMember.getEmail())) {\n                    return true;\n                }\n            }\n        }\n\n        // 会员不存在，返回 true\n        if (tbMember == null) {\n            return true;\n        }\n        return false;\n    }\n\n    @Transactional\n    @Override\n    public BaseResult changeMemberPassword(Long id, String password) {\n\n        // 根据 id 查询会员\n        TbMember tbMember = tbMemberMapper.selectByPrimaryKey(id);\n\n        // 用户不存在\n        if (tbMember == null) {\n            return BaseResult.fail(\"用户不存在！\");\n        }\n\n        // 设置新密码\n        tbMember.setPassword(DigestUtils.md5DigestAsHex(password.getBytes()));\n\n        // 更新会员\n        tbMemberMapper.updateByPrimaryKey(tbMember);\n\n        return BaseResult.success(\"更改密码成功！\");\n    }\n\n    @Transactional\n    @Override\n    public BaseResult deleteMember(Long[] ids) {\n        for (Long id : ids) {\n            tbMemberMapper.deleteByPrimaryKey(id);\n        }\n        return BaseResult.success(\"删除会员成功！\");\n    }\n\n    @Override\n    public DataTablesResult<TbMember> getMemberBanList(HttpServletRequest request, String search) {\n        // 初始化 DataTableResult\n        DataTablesResult<TbMember> result = new DataTablesResult<>(request);\n\n        // 设置 PageHelper\n        PageHelper.startPage(result.getPageNum(), result.getLength());\n        List<TbMember> tbMemberList = tbMemberMapper.getMemberBanList(search);\n\n        // 删除密码\n        for (TbMember tbMember : tbMemberList) {\n            tbMember.setPassword(\"\");\n        }\n\n        // 封装 PageHelper\n        PageInfo<TbMember> tbMemberPageInfo = new PageInfo<>(tbMemberList);\n        result.setRecordsFiltered((int) tbMemberPageInfo.getTotal());\n        result.setRecordsTotal(tbMemberMapper.getMemberBanListCount(search));\n        result.setDraw(result.getDraw());\n        result.setData(tbMemberList);\n\n        return result;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/OrderServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport com.github.pagehelper.PageHelper;\nimport com.github.pagehelper.PageInfo;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbOrder;\nimport com.yuu.ymall.domain.TbOrderItem;\nimport com.yuu.ymall.domain.TbOrderShipping;\nimport com.yuu.ymall.web.admin.commons.consts.Consts;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.commons.dto.OrderDetail;\nimport com.yuu.ymall.web.admin.mapper.TbOrderItemMapper;\nimport com.yuu.ymall.web.admin.mapper.TbOrderMapper;\nimport com.yuu.ymall.web.admin.mapper.TbOrderShippingMapper;\nimport com.yuu.ymall.web.admin.service.OrderService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Date;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @Classname OrderServiceImpl\n * @Date 2019/5/15 22:35\n * @Created by Yuu\n */\n@Service\n@Transactional(readOnly = true)\npublic class OrderServiceImpl implements OrderService {\n\n    @Autowired\n    private TbOrderMapper tbOrderMapper;\n\n    @Autowired\n    private TbOrderItemMapper tbOrderItemMapper;\n\n    @Autowired\n    private TbOrderShippingMapper tbOrderShippingMapper;\n\n    @Override\n    public int getAllOrderCount() {\n        int orderCount = tbOrderMapper.getAllOrderCount();\n        return orderCount;\n    }\n\n    @Override\n    public DataTablesResult<TbOrder> getOrderList(HttpServletRequest request, String search, int status) {\n        DataTablesResult<TbOrder> result = new DataTablesResult<>(request);\n\n        Map<String, Object> params = new HashMap<>();\n        params.put(\"search\", search);\n        params.put(\"status\", status);\n\n        // 分页查询\n        PageHelper.startPage(result.getPageNum(), result.getLength());\n        List<TbOrder> tbOrderList = tbOrderMapper.getOrderList(params);\n\n        // 封装 PageInfo\n        PageInfo<TbOrder> tbOrderPageInfo = new PageInfo<>(tbOrderList);\n        result.setRecordsFiltered((int) tbOrderPageInfo.getTotal());\n        result.setRecordsTotal(tbOrderMapper.getTbOrderCount(params));\n        result.setDraw(result.getDraw());\n        result.setData(tbOrderList);\n\n        return result;\n    }\n\n    @Override\n    public BaseResult getOrderDetail(String id) {\n\n        // 根据 id 查询订单信息\n        OrderDetail orderDetail = new OrderDetail();\n        TbOrder tbOrder = tbOrderMapper.selectByPrimaryKey(id);\n\n        // 查询所有订单项\n        List<TbOrderItem> tbOrderItemList = tbOrderItemMapper.selectOrderItemByOrderId(id);\n\n        // 查询订单收货信息\n        TbOrderShipping tbOrderShipping = tbOrderShippingMapper.selectByPrimaryKey(id);\n\n        // 封装 OrderDetail\n        orderDetail.setTbOrder(tbOrder);\n        orderDetail.setTbOrderItemList(tbOrderItemList);\n        orderDetail.setTbOrderShipping(tbOrderShipping);\n\n        return BaseResult.success(orderDetail);\n    }\n\n    @Transactional\n    @Override\n    public BaseResult deliver(String orderId, String shippingName, String shippingCode) {\n        // 查询出订单\n        TbOrder tbOrder = tbOrderMapper.selectByPrimaryKey(orderId);\n\n        // 设置快递信息\n        tbOrder.setShippingName(shippingName);\n        tbOrder.setShippingCode(shippingCode);\n        // 发货时间\n        tbOrder.setConsignTime(new Date());\n        tbOrder.setUpdated(new Date());\n        // 订单状态\n        tbOrder.setStatus(Consts.ORDER_STATE_SHIPPED);\n\n        // 更新订单信息\n        tbOrderMapper.updateByPrimaryKey(tbOrder);\n        return BaseResult.success();\n    }\n\n    @Transactional\n    @Override\n    public BaseResult cancelOrderByAdmin(String orderId) {\n        // 查询订单\n        TbOrder tbOrder = tbOrderMapper.selectByPrimaryKey(orderId);\n\n        // 设置订单状态\n        tbOrder.setStatus(Consts.ORDER_STATE_CLOSE);\n\n        // 更新订单\n        tbOrderMapper.updateByPrimaryKey(tbOrder);\n\n        return BaseResult.success(\"取消订单成功\");\n    }\n\n    @Transactional\n    @Override\n    public BaseResult deleteOrderByIds(String[] ids) {\n        // 遍历删除订单\n        for (String id : ids) {\n            tbOrderMapper.deleteByPrimaryKey(id);\n        }\n        return BaseResult.success(\"删除订单成功\");\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/PanelServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.domain.TbPanel;\nimport com.yuu.ymall.web.admin.commons.dto.ZTreeNode;\nimport com.yuu.ymall.web.admin.commons.utils.DtoUtil;\nimport com.yuu.ymall.web.admin.mapper.TbPanelMapper;\nimport com.yuu.ymall.web.admin.service.PanelService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.*;\n\n/**\n * @Classname PanelServiceImpl\n * @Date 2019/5/20 8:54\n * @Created by Yuu\n */\n@Service\n@Transactional(readOnly = true)\npublic class PanelServiceImpl implements PanelService {\n\n    @Autowired\n    private TbPanelMapper tbPanelMapper;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    @Value(\"PRODUCT_HOME\")\n    private String PRODUCT_HOME;\n\n    @Override\n    public List<ZTreeNode> getPanelList(int type) {\n        Map<String, Object> params = new HashMap<>();\n\n        // type = 1 时，查询所有，不需要 type 条件\n        if (type != 1) {\n            params.put(\"type\", type);\n        }\n\n        // 首页板块\n        params.put(\"position\", \"0\");\n        List<TbPanel> tbPanelList = tbPanelMapper.getPanelList(params);\n\n        // 封装 ZTreeNode\n        List<ZTreeNode> zTreeNodeList = new ArrayList<>();\n        for (TbPanel tbPanel : tbPanelList) {\n            ZTreeNode zTreeNode = DtoUtil.TbPanel2ZTreeNode(tbPanel);\n            zTreeNodeList.add(zTreeNode);\n        }\n\n        return zTreeNodeList;\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult updatePanel(TbPanel tbPanel) {\n        tbPanel.setUpdated(new Date());\n        int result = tbPanelMapper.updateByPrimaryKey(tbPanel);\n\n        // 更新失败\n        if (result != 1) {\n            return BaseResult.fail(\"更新板块失败\");\n        }\n\n        // 同步缓存\n        deleteHomeRedis();\n        return BaseResult.success(\"更新板块成功\");\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult deletePanelById(int id) {\n        int result = tbPanelMapper.deleteByPrimaryKey(id);\n\n        // 删除失败\n        if (result != 1) {\n            return BaseResult.fail(\"删除板块失败\");\n        }\n\n        // 同步缓存\n        deleteHomeRedis();\n        return BaseResult.success(\"删除板块成功\");\n    }\n\n    @Transactional(readOnly = false)\n    @Override\n    public BaseResult addPanel(TbPanel tbPanel) {\n\n        // 判断是否为轮播图板块，首页只能有一个轮播图板块\n        if (tbPanel.getType() == 0) {\n            TbPanel isExistTbPanel = tbPanelMapper.getPanelByType(0);\n            if (isExistTbPanel != null) {\n                return BaseResult.fail(\"已有轮播图板块，轮播图板块仅能添加 1 个\");\n            }\n        }\n\n        tbPanel.setCreated(new Date());\n        tbPanel.setUpdated(new Date());\n\n        int result = tbPanelMapper.insert(tbPanel);\n\n        // 添加板块失败\n        if (result != 1) {\n            return BaseResult.fail(\"添加板块失败！\");\n        }\n\n        // 同步缓存\n        deleteHomeRedis();\n        return BaseResult.success(\"添加板块成功！\");\n    }\n\n    /**\n     * 删除首页缓存\n     */\n    private void deleteHomeRedis() {\n        redisCacheManager.del(PRODUCT_HOME);\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/SearchServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport com.yuu.ymall.domain.TbItem;\nimport com.yuu.ymall.web.admin.commons.es.ESItem;\nimport com.yuu.ymall.web.admin.mapper.TbItemMapper;\nimport com.yuu.ymall.web.admin.mapper.TbOrderItemMapper;\nimport com.yuu.ymall.web.admin.repositories.ItemRepository;\nimport com.yuu.ymall.web.admin.service.SearchService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author by Yuu\n * @classname SearchSeviceImpl\n * @date 2019/7/9 19:50\n */\n@Service\npublic class SearchServiceImpl implements SearchService {\n\n    @Autowired\n    private ItemRepository itemRepository;\n\n    @Autowired\n    private TbItemMapper tbItemMapper;\n\n    @Autowired\n    private TbOrderItemMapper tbOrderItemMapper;\n\n\n    @Override\n    public void refreshItem(int type, Long itemId) {\n        // 更新索引\n        if (type == 0) {\n            // 从数据库中查出数据\n            TbItem tbItem = tbItemMapper.selectByPrimaryKey(itemId);\n            // 设置 ESItem\n            if (tbItem != null) {\n                ESItem esItem = new ESItem();\n                esItem.setId(tbItem.getId());\n                esItem.setProductId(tbItem.getId());\n                esItem.setProductName(tbItem.getTitle());\n                esItem.setSubTitle(tbItem.getSellPoint());\n                esItem.setSalePrice(tbItem.getPrice().doubleValue());\n                esItem.setPicUrl(tbItem.getImages()[0]);\n                esItem.setCid(tbItem.getCid());\n                if (tbItem.getLimitNum() > tbItem.getNum()) {\n                    esItem.setLimit(tbItem.getNum());\n                } else {\n                    esItem.setLimit(tbItem.getLimitNum());\n                }\n                // 查询该商品订单数量\n                int orderNum = tbOrderItemMapper.selectOrderNumByItemId(tbItem.getId());\n                esItem.setOrderNum(orderNum);\n                // 更新索引\n                itemRepository.save(esItem);\n            }\n        }\n\n        // 删除索引\n        else {\n            itemRepository.deleteById(itemId);\n        }\n    }\n\n    @Override\n    public void importAllItems() {\n        // 从数据库中查询所有商品\n        List<TbItem> tbItemList = tbItemMapper.selectAll();\n\n        List<ESItem> esItems = new ArrayList<>();\n        for (TbItem tbItem : tbItemList) {\n            ESItem esItem = new ESItem();\n            esItem.setId(tbItem.getId());\n            esItem.setProductId(tbItem.getId());\n            esItem.setProductName(tbItem.getTitle());\n            esItem.setSubTitle(tbItem.getSellPoint());\n            esItem.setSalePrice(tbItem.getPrice().doubleValue());\n            esItem.setPicUrl(tbItem.getImages()[0]);\n            esItem.setCid(tbItem.getCid());\n            if (tbItem.getLimitNum() > tbItem.getNum()) {\n                esItem.setLimit(tbItem.getNum());\n            } else {\n                esItem.setLimit(tbItem.getLimitNum());\n            }\n            esItems.add(esItem);\n        }\n\n        // 批量新增\n        itemRepository.saveAll(esItems);\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/SystemServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbOrderItem;\nimport com.yuu.ymall.web.admin.mapper.TbOrderItemMapper;\nimport com.yuu.ymall.web.admin.service.SystemService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.List;\n\n/**\n * @Classname SystemServiceImpl\n * @Date 2019/5/11 20:21\n * @Created by Yuu\n */\n@Service\n@Transactional(readOnly = true)\npublic class SystemServiceImpl implements SystemService {\n\n    @Autowired\n    private TbOrderItemMapper tbOrderItemMapper;\n\n    @Override\n    public BaseResult getWeekHot() {\n        List<TbOrderItem> tbOrderItemList = tbOrderItemMapper.getWeekHot();\n        if (tbOrderItemList.size() == 0) {\n            TbOrderItem tbOrderItem = new TbOrderItem();\n            tbOrderItem.setTotal(0);\n            tbOrderItem.setTitle(\"暂无数据\");\n            tbOrderItem.setPicPath(\"\");\n            return BaseResult.success(tbOrderItem);\n        }\n        return BaseResult.success(tbOrderItemList.get(0));\n    }\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/service/impl/UserServiceImpl.java",
    "content": "package com.yuu.ymall.web.admin.service.impl;\n\nimport com.github.pagehelper.PageHelper;\nimport com.github.pagehelper.PageInfo;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbUser;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.mapper.TbUserMapper;\nimport com.yuu.ymall.web.admin.service.UserService;\nimport org.springframework.beans.BeanUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.DigestUtils;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @Classname UserServiceImpl\n * @Date 2019/5/11 18:49\n * @Created by Yuu\n */\n@Service\n@Transactional(readOnly = true)\npublic class UserServiceImpl implements UserService {\n\n    @Autowired\n    private TbUserMapper tbUserMapper;\n\n    @Override\n    public TbUser getUserByUsername(String username) {\n        return tbUserMapper.getUserByUsername(username);\n    }\n\n    @Override\n    public DataTablesResult<TbUser> getUserList(HttpServletRequest request, String search) {\n        DataTablesResult<TbUser> result = new DataTablesResult<>(request);\n\n        // 分页查询\n        PageHelper.startPage(result.getPageNum(), result.getLength());\n        List<TbUser> tbUserList = tbUserMapper.getUserList(search);\n\n        // 封装 PageInfo\n        PageInfo<TbUser> tbItemPageInfo = new PageInfo<>(tbUserList);\n        result.setRecordsFiltered((int) tbItemPageInfo.getTotal());\n        result.setRecordsTotal(tbUserMapper.getUserListCount(search));\n        result.setDraw(result.getDraw());\n        result.setData(tbUserList);\n\n        return result;\n    }\n\n    @Override\n    public Boolean validateUsername(Long id, String username) {\n        // 根据用户名查询出会员\n        TbUser tbUser = tbUserMapper.getUserByUsername(username);\n\n        // 判断用户名是否为用户原用户名\n        if (id != 0 && tbUser != null) {\n            TbUser idTbUser = tbUserMapper.selectByPrimaryKey(id);\n            if (idTbUser.getUsername().equals(tbUser.getUsername())) {\n                return true;\n            }\n        }\n\n        // 用户名不存在\n        if (tbUser == null) {\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public Boolean validatePhone(Long id, String phone) {\n        // 根据用户手机号查询出会员\n        TbUser tbUser = tbUserMapper.getUserByPhone(phone);\n\n        /*// 判断用户名是否为用户原用户名\n        if (id != 0 && tbUser != null) {\n            TbUser idTbUser = tbUserMapper.selectByPrimaryKey(id);\n            if (idTbUser.getPhone().equals(tbUser.getPhone())) {\n                return true;\n            }\n        }*/\n\n        // 用户名不存在\n        if (tbUser == null) {\n            return true;\n        }\n\n        return false;\n    }\n\n    @Override\n    public Boolean validateEmail(Long id, String email) {\n        // 根据用户手机号查询出会员\n        TbUser tbUser = tbUserMapper.getUserByEmail(email);\n\n        // 判断用户名是否为用户原用户名\n        if (id != 0 && tbUser != null) {\n            /*TbUser idTbUser = tbUserMapper.selectByPrimaryKey(id);\n            if (idTbUser.getEmail().equals(tbUser.getEmail())) {\n                return true;\n            }*/\n        }\n\n        // 用户名不存在\n        if (tbUser == null) {\n            return true;\n        }\n\n        return false;\n    }\n\n    @Transactional\n    @Override\n    public BaseResult save(TbUser tbUser) {\n        // 查询用户名是否被注册\n        if (!validateUsername(tbUser.getId(), tbUser.getUsername())) {\n            return BaseResult.fail(\"用户名已被注册!\");\n        }\n\n        // 封装 TbUser\n        TbUser newTbUser = new TbUser();\n        BeanUtils.copyProperties(tbUser, newTbUser);\n        newTbUser.setUpdated(new Date());\n        newTbUser.setCreated(new Date());\n        // 加密密码\n        newTbUser.setPassword(DigestUtils.md5DigestAsHex(newTbUser.getPassword().getBytes()));\n\n        // 新增会员\n        tbUserMapper.insert(newTbUser);\n        return BaseResult.success(\"保存用户成功！\");\n    }\n\n    @Transactional\n    @Override\n    public BaseResult changePass(Long id, String password) {\n\n        // 查询出旧的用户\n        TbUser tbUser = tbUserMapper.selectByPrimaryKey(id);\n\n        // 用户不存在\n        if (tbUser == null) {\n            return BaseResult.fail(\"用户不存在！\");\n        }\n\n        // 设置新密码\n        tbUser.setPassword(DigestUtils.md5DigestAsHex(password.getBytes()));\n\n        // 更新用户\n        tbUserMapper.updateByPrimaryKey(tbUser);\n\n        return BaseResult.success(\"更改密码成功！\");\n    }\n\n    @Transactional\n    @Override\n    public BaseResult delete(Long[] ids) {\n        for (Long id : ids) {\n            if (id.equals(1l)) {\n                return BaseResult.success(\"不能删除超级管理员！！！\");\n            }\n            tbUserMapper.deleteByPrimaryKey(id);\n        }\n        return BaseResult.success(\"删除用户成功！\");\n    }\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/ContentController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbPanelContent;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.service.ContentService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname ContentController\n * @Date 2019/5/16 23:51\n * @Created by Yuu\n */\n@RestController\n@Api(description = \"内容列表信息\")\n@RequestMapping(\"content\")\npublic class ContentController {\n\n    @Autowired\n    private ContentService contentService;\n\n    /**\n     * 通过 panelId 获取板块内容列表\n     *\n     * @param panelId 板块 id\n     * @return\n     */\n    @GetMapping(\"list/{panelId}\")\n    @ApiOperation(\"通过 panelId 获取板块内容列表\")\n    public DataTablesResult<TbPanelContent> getContentByCid(@PathVariable int panelId, HttpServletRequest request, @RequestParam(value = \"search[value]\", required = false) String search) {\n         DataTablesResult<TbPanelContent> result = contentService.getPanelContentListByPanelId(request, panelId, search);\n         return result;\n    }\n\n    /**\n     * 新增或编辑内容\n     * 有 id 则为编辑，无 id 则为 新增\n     *\n     * @param tbPanelContent\n     * @return\n     */\n    @PostMapping(\"save\")\n    @ApiOperation(value = \"新增或编辑内容\")\n    public BaseResult saveContent(@ModelAttribute TbPanelContent tbPanelContent) {\n        BaseResult baseResult = contentService.saveContent(tbPanelContent);\n        return baseResult;\n    }\n\n    /**\n     * 删除板块内容\n     *\n     * @param ids 板块内容的 id 数组\n     * @return\n     */\n    @DeleteMapping(\"delete/{ids}\")\n    @ApiOperation(value = \"删除板块内容\")\n    public BaseResult deleteContent(@PathVariable int[] ids) {\n        BaseResult baseResult = contentService.deletePanelContent(ids);\n        return baseResult;\n    }\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/CountController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.web.admin.service.CountService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * 统计 Controler\n *\n * @author by Yuu\n * @classname CountController\n * @date 2019/6/21 10:56\n */\n@RestController\n@Api(description = \"统计\")\n@RequestMapping(\"count\")\npublic class CountController {\n\n    @Autowired\n    private CountService countService;\n\n    /**\n     * 订单销量\n     *\n     * @param type 类型\n     * @param startTime 开始时间\n     * @param endTime 结束时间\n     * @param year 年份\n     * @return\n     */\n    @GetMapping(\"order\")\n    @ApiOperation(value = \"订单销量统计\")\n    public BaseResult countOrder(@RequestParam int type,\n                                 @RequestParam(required = false) String startTime,\n                                 @RequestParam(required = false) String endTime,\n                                 @RequestParam(required = false) int year) {\n        BaseResult baseResult = countService.countOrder(type, startTime, endTime, year);\n        return baseResult;\n    }\n\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/ExpressController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbExpress;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.service.ExpressService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname ExpressController\n * @Date 2019/6/15 18:58\n * @Created by Yuu\n */\n@RestController\n@Api(description = \"快递管理\")\n@RequestMapping(\"express\")\npublic class ExpressController {\n\n    @Autowired\n    private ExpressService expressService;\n\n    /**\n     * 获取快递列表\n     *\n     * @param request 请求\n     * @param search 搜索参数\n     * @return\n     */\n    @GetMapping(\"list\")\n    @ApiOperation(value = \"获得所有快递\")\n    public DataTablesResult<TbExpress> getEXPressList(HttpServletRequest request, @RequestParam(value = \"search[value]\", required = false) String search) {\n        DataTablesResult<TbExpress> dataTablesResult = expressService.getExpressList(request, search);\n        return dataTablesResult;\n    }\n\n    /**\n     * 保存快递信息\n     *\n     * @param tbExpress 快递信息\n     * @return\n     */\n    @PostMapping(\"save\")\n    @ApiOperation(value = \"保存快递\")\n    public BaseResult save(TbExpress tbExpress) {\n        BaseResult baseResult = expressService.save(tbExpress);\n        return baseResult;\n    }\n\n    /**\n     * 删除快递信息\n     *\n     * @param ids 快递的 id 集合\n     * @return\n     */\n    @DeleteMapping(\"delete/{ids}\")\n    @ApiOperation(value = \"删除快递\")\n    public BaseResult delete(@PathVariable Integer[] ids) {\n        BaseResult baseResult = expressService.delete(ids);\n        return baseResult;\n    }\n\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/ItemCatController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbItemCat;\nimport com.yuu.ymall.web.admin.commons.dto.ZTreeNode;\nimport com.yuu.ymall.web.admin.service.ItemCatService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n/**\n * @Classname ItemCatController\n * @Date 2019/6/3 14:51\n * @Created by Yuu\n */\n@RestController\n@Api(description = \"商品分类管理\")\n@RequestMapping(\"item/cat\")\npublic class ItemCatController {\n\n    @Autowired\n    private ItemCatService itemCatService;\n\n    /**\n     * 通过父 ID 获取商品分类列表\n     *\n     * @param parentId 父 ID\n     * @param type zTree 展示数据类型 -1 不展示所有商品，0 展示所有商品\n     * @return\n     */\n    @GetMapping(\"list/{type}\")\n    @ApiOperation(value = \"通过父 ID 获取商品分类列表\")\n    public List<ZTreeNode> getItemCatList(@RequestParam(name = \"id\", defaultValue = \"0\") Long parentId, @PathVariable int type) {\n        List<ZTreeNode> list = itemCatService.getItemCatList(parentId, type);\n        return list;\n    }\n\n    /**\n     * 编辑或添加商品分类\n     *\n     * @param tbItemCat 商品分类\n     * @return\n     */\n    @PostMapping(\"save\")\n    @ApiOperation(value = \"编辑商品分类\")\n    public BaseResult saveItemCategory(@ModelAttribute TbItemCat tbItemCat) {\n        BaseResult baseResult = itemCatService.saveItemCat(tbItemCat);\n        return baseResult;\n    }\n\n    /**\n     * 删除商品分类\n     *\n     * @param id 商品分类 id\n     * @return\n     */\n    @DeleteMapping(\"del/{id}\")\n    @ApiOperation(value = \"删除商品分类\")\n    public BaseResult deleteItemCategory(@PathVariable Long id) {\n        BaseResult baseResult = itemCatService.deleteItemCat(id);\n        return baseResult;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/ItemController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbItem;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.commons.dto.ItemDto;\nimport com.yuu.ymall.web.admin.mapper.TbOrderItemMapper;\nimport com.yuu.ymall.web.admin.service.ContentService;\nimport com.yuu.ymall.web.admin.service.ItemService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname ItemController\n * @Date 2019/5/15 22:23\n * @Created by Yuu\n */\n@RestController\n@Api(description = \"商品管理\")\n@RequestMapping(\"item\")\npublic class ItemController {\n\n\n    @Autowired\n    private ItemService itemService;\n\n    @Autowired\n    private ContentService contentService;\n\n    @Autowired\n    private TbOrderItemMapper tbOrderItemMapper;\n\n    /**\n     * 获取商品总数目\n     *\n     * @return\n     */\n    @GetMapping(\"count\")\n    @ApiOperation(value = \"获取商品总数目\")\n    public BaseResult getAllItemCount() {\n        int itemCount = itemService.getAllItemCount();\n        return BaseResult.success(itemCount);\n    }\n\n    /**\n     * 通过 Cid 获取商品列表\n     *\n     * @param cid 分类 id\n     * @param request 请求\n     * @param search 查询条件\n     * @return\n     */\n    @GetMapping(\"list/{cid}\")\n    @ApiOperation(value = \"分页搜索排序获取商品列表\")\n    public DataTablesResult<TbItem> getItemList(@PathVariable Long cid, HttpServletRequest request, @RequestParam(\"search[value]\") String search) {\n        DataTablesResult<TbItem> result = itemService.getItemListByCid(request, cid, search);\n        return result;\n    }\n\n    /**\n     * 删除商品\n     *\n     * @param ids 商品 id 集合\n     * @return\n     */\n    @DeleteMapping(\"delete/{ids}\")\n    @ApiOperation(value = \"删除商品\")\n    public BaseResult deleteItem(@PathVariable Long[] ids) {\n        // 判断首页是否关联\n        for (Long id : ids) {\n            int result = contentService.selectContentByIid(id);\n            if (result > 0) {\n                return BaseResult.fail(\"删除商品失败！包含首页展示关联的商品,商品ID：\"+ id +\"，请先从首页配置中删除该商品关联\");\n            }\n            // 判断商品是否已有订单，有订单则不能删除\n            result = tbOrderItemMapper.selectByItemId(id);\n            if (result > 0) {\n                return BaseResult.fail(\"删除商品失败！包含已有订单的商品,商品ID：\"+ id +\"，请使用下架处理该商品！\");\n            }\n        }\n        BaseResult baseResult = itemService.deleteItem(ids);\n        return baseResult;\n    }\n\n    /**\n     * 下架商品\n     *\n     * @param id 商品 id\n     * @return\n     */\n    @DeleteMapping(\"stop/{id}\")\n    @ApiOperation(value = \"下架商品\")\n    public BaseResult stopItem(@PathVariable Long id) {\n        // 判断首页是否关联\n        int result = contentService.selectContentByIid(id);\n        if (result > 0) {\n            return BaseResult.fail(\"下架商品失败！包含首页展示关联的商品,商品ID：\"+ id +\"，请先从首页配置中删除该商品关联\");\n        }\n        BaseResult baseResult = itemService.stopItem(id);\n        return baseResult;\n    }\n\n    /**\n     * 发布商品\n     *\n     * @param id 商品 id\n     * @return\n     */\n    @DeleteMapping(\"start/{id}\")\n    @ApiOperation(value = \"发布商品\")\n    public BaseResult startItem(@PathVariable Long id) {\n        BaseResult baseResult = itemService.startItem(id);\n        return baseResult;\n    }\n\n    /**\n     * 保存商品：有 id 编辑商品，无 id 新增商品\n     *\n     * @param itemDto 商品 DTO\n     * @return\n     */\n    @PostMapping(\"save\")\n    @ApiOperation(value = \"保存商品\")\n    public BaseResult saveItem(ItemDto itemDto) {\n        BaseResult baseResult = itemService.saveItem(itemDto);\n        // 更新索引库\n        return baseResult;\n    }\n\n    /**\n     * 根据商品 ID 获取商品\n     *\n     * @param itemId 商品 ID\n     * @return\n     */\n    @GetMapping(\"{itemId}\")\n    @ApiOperation(value = \"通过商品ID获取商品\")\n    public BaseResult getItemById(@PathVariable Long itemId) {\n        BaseResult baseResult = itemService.getItemById(itemId);\n        return baseResult;\n    }\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/MemberController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbMember;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.service.MemberService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname MemberController\n * @Date 2019/5/15 22:08\n * @Created by Yuu\n */\n@RestController\n@Api(description = \"会员管理\")\n@RequestMapping(\"member\")\npublic class MemberController {\n\n    private final static Logger log = LoggerFactory.getLogger(MemberController.class);\n\n    @Autowired\n    private MemberService memberService;\n\n    /**\n     * 获取总会员数目\n     *\n     * @return\n     */\n    @GetMapping(\"count\")\n    @ApiOperation(value = \"获取总会员数目\")\n    public BaseResult getAllMemberCount() {\n        int memberCount = memberService.getAllMemberCount();\n        return BaseResult.success(memberCount);\n    }\n\n    /**\n     * 获取会员列表\n     *\n     * @param request 请求\n     * @param search 搜索条件\n     * @return\n     */\n    @GetMapping(\"list\")\n    @ApiOperation(value = \"获取会员列表\")\n    public DataTablesResult<TbMember> getMemberList(HttpServletRequest request, @RequestParam(\"search[value]\") String search) {\n        DataTablesResult<TbMember> dataTablesResult = memberService.getMemberList(request, search);\n        return dataTablesResult;\n    }\n\n    /**\n     * 封禁会员\n     *\n     * @param id 会员 id\n     * @return\n     */\n    @DeleteMapping(\"ban/{id}\")\n    @ApiOperation(value = \"封禁会员\")\n    public BaseResult banMember(@PathVariable Long id) {\n        BaseResult baseResult = memberService.banMember(id);\n        return baseResult;\n    }\n\n    /**\n     * 解封会员\n     *\n     * @param id 会员 id\n     * @return\n     */\n    @DeleteMapping(\"start/{ids}\")\n    @ApiOperation(value = \"解封会员\")\n    public BaseResult startMember(@PathVariable Long[] ids) {\n        BaseResult baseResult = memberService.startMember(ids);\n        return baseResult;\n    }\n\n    /**\n     * 验证注册会员名是否存在\n     *\n     * @param username 会员名\n     * @return\n     */\n    @GetMapping(\"username\")\n    @ApiOperation(value = \"验证注册会员名是否存在\")\n    public Boolean validateUsername(String username, Long id) {\n        Boolean flag = memberService.getMemberByUsername(username, id);\n        return flag;\n    }\n\n    /**\n     * 验证注册手机号是否存在\n     *\n     * @param phone 手机号\n     * @return\n     */\n    @GetMapping(\"phone\")\n    @ApiOperation(value = \"验证注册手机号是否存在\")\n    public Boolean validatePhone(String phone, Long id) {\n        Boolean flag = memberService.getMemberByPhone(phone, id);\n        return flag;\n    }\n\n    /**\n     * 验证注册邮箱是否存在\n     *\n     * @param email 邮箱\n     * @return\n     */\n    @GetMapping(\"email\")\n    @ApiOperation(value = \"验证注册邮箱是否存在\")\n    public Boolean validateEmail(String email, Long id) {\n        Boolean flag = memberService.getMemberByEmail(email, id);\n        return flag;\n    }\n\n    /**\n     * 保存会员\n     *\n     * @param tbMember 会员\n     * @return\n     */\n    @PostMapping(\"save\")\n    @ApiOperation(value = \"保存会员\")\n    public BaseResult saveMember(TbMember tbMember) {\n        BaseResult baseResult = memberService.saveMember(tbMember);\n        return baseResult;\n    }\n\n    /**\n     * 修改会员密码\n     *\n     * @param id 会员 id\n     * @param tbMember 会员\n     * @return\n     */\n    @PostMapping(\"changePass/{id}\")\n    @ApiOperation(value = \"修改会员密码\")\n    public BaseResult changeMemberPassword(@PathVariable Long id, String password) {\n        BaseResult baseResult = memberService.changeMemberPassword(id, password);\n        return baseResult;\n    }\n\n    /**\n     * 删除会员\n     *\n     * @param ids 会员 id 集合\n     * @return\n     */\n    @DeleteMapping(\"delete/{ids}\")\n    @ApiOperation(value = \"删除会员\")\n    public BaseResult deleteMember(@PathVariable Long[] ids) {\n        BaseResult baseResult = memberService.deleteMember(ids);\n        return baseResult;\n    }\n\n    /**\n     * 封禁的会员列表\n     *\n     * @param request 请求\n     * @param search 搜索条件\n     * @return\n     */\n    @GetMapping(\"ban/list\")\n    @ApiOperation(value = \"封禁的会员列表\")\n    public DataTablesResult<TbMember> getBanMemberList(HttpServletRequest request, @RequestParam(\"search[value]\") String search) {\n        DataTablesResult<TbMember> dataTablesResult = memberService.getMemberBanList(request, search);\n        return dataTablesResult;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/OrderController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbOrder;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.service.OrderService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @Classname OrderController\n * @Date 2019/5/15 22:31\n * @Created by Yuu\n */\n@RestController\n@Api(description = \"订单管理\")\n@RequestMapping(\"order\")\npublic class OrderController {\n\n    private final static Logger logger = LoggerFactory.getLogger(OrderController.class);\n\n    @Autowired\n    private OrderService orderService;\n\n    /**\n     * 获取订单总数目\n     *\n     * @return\n     */\n    @GetMapping(\"count\")\n    @ApiOperation(value = \"获取订单总数目\")\n    public BaseResult getOrderCount() {\n        int orderCount = orderService.getAllOrderCount();\n        return BaseResult.success(orderCount);\n    }\n\n    /**\n     * 获取订单列表\n     *\n     * @return\n     */\n    @GetMapping(\"list\")\n    @ApiOperation(value = \"获取订单列表\")\n    public DataTablesResult<TbOrder> getOrderList(HttpServletRequest request, @RequestParam(\"search[value]\") String search,@RequestParam(defaultValue = \"-1\") int status) {\n        DataTablesResult<TbOrder> result = orderService.getOrderList(request, search, status);\n        return result;\n    }\n\n    /**\n     * 获取订单详情\n     *\n     * @param id 订单 id\n     * @return\n     */\n    @GetMapping(\"detail/{id}\")\n    @ApiOperation(value = \"获取订单详情\")\n    public BaseResult getOrderDetail(@PathVariable String id) {\n        BaseResult baseResult = orderService.getOrderDetail(id);\n        return baseResult;\n    }\n\n    /**\n     * 订单发货\n     *\n     * @param orderId 订单 id\n     * @param shippingName 快递名称\n     * @param shippingCode 快递单号\n     * @param postFee 运费\n     * @return\n     */\n    @PostMapping(\"deliver\")\n    @ApiOperation(value = \"订单发货\")\n    public BaseResult deliver(@RequestParam String orderId,\n                              @RequestParam String shippingName,\n                              @RequestParam String shippingCode) {\n        BaseResult baseResult = orderService.deliver(orderId, shippingName, shippingCode);\n        return baseResult;\n    }\n\n    /**\n     * 管理员取消订单\n     *\n     * @param orderId 订单 id\n     * @return\n     */\n    @DeleteMapping(\"cancel/{orderId}\")\n    @ApiOperation(value = \"订单取消\")\n    public BaseResult cancelOrderByAdmin(@PathVariable String orderId) {\n        BaseResult baseResult = orderService.cancelOrderByAdmin(orderId);\n        return baseResult;\n    }\n\n    /**\n     * 删除订单\n     *\n     * @param ids 订单集合\n     * @return\n     */\n    @DeleteMapping(\"delete/{ids}\")\n    @ApiOperation(value = \"删除订单\")\n    public BaseResult deleteOrderByIds(@PathVariable String[] ids) {\n        BaseResult baseResult = orderService.deleteOrderByIds(ids);\n        return baseResult;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/PageController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.ModelAttribute;\nimport org.springframework.web.bind.annotation.PathVariable;\n\n/**\n * 页面跳转\n *\n * @Classname PageController\n * @Date 2019/5/11 22:22\n * @Created by Yuu\n */\n@Controller\npublic class PageController {\n\n    /**\n     * 跳转到首页\n     *\n     * @return\n     */\n    @GetMapping(\"/\")\n    public String showIndex() {\n        return \"index\";\n    }\n\n    /**\n     * 通用的跳转方法\n     *\n     * @param page\n     * @return\n     */\n    @GetMapping(\"{page}\")\n    public String showPage(@PathVariable String page) {\n        return page;\n    }\n\n    /**\n     * 通用的板块内容管理页面跳转\n     *\n     * @param type 类型 -1 板块内容管理 0 轮播图管理\n     * @return\n     */\n    @GetMapping(\"content-common-list\")\n    public String contentCommonListPage(@ModelAttribute(\"type\") Integer type) {\n        return \"content-common-list\";\n    }\n}\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/PanelController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbPanel;\nimport com.yuu.ymall.web.admin.commons.dto.ZTreeNode;\nimport com.yuu.ymall.web.admin.service.PanelService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiImplicitParam;\nimport io.swagger.annotations.ApiImplicitParams;\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport java.util.List;\n\n/**\n * @Classname PanelController\n * @Date 2019/5/20 8:46\n * @Created by Yuu\n */\n@RestController\n@Api(description = \"内容板块管理\")\n@RequestMapping(\"panel\")\npublic class PanelController {\n\n    private final static Logger log = LoggerFactory.getLogger(PanelController.class);\n\n    @Autowired\n    private PanelService panelService;\n\n    /**\n     * 通过的获取板块内容\n     * type: 0 仅含轮播，-1 非轮播，1 所有\n     *\n     * @param type 类型\n     * @param showAll\n     * @return\n     */\n    @GetMapping(\"common/list/{type}\")\n    @ApiOperation(value = \"通用的获取板块内容\")\n    @ApiImplicitParams({\n            @ApiImplicitParam(name = \"type\", value = \"类型\", required = true, dataType = \"int\", paramType = \"path\"),\n    })\n    public List<ZTreeNode> getCommonPanel(@PathVariable int type) {\n        List<ZTreeNode> zTreeNodeList = panelService.getPanelList(type);\n        return zTreeNodeList;\n    }\n\n    /**\n     * 编辑板块\n     *\n     * @param tbPanel 板块信息\n     * @return\n     */\n    @PostMapping(\"update\")\n    @ApiOperation(value = \"编辑内容板块\")\n    public BaseResult updateContentPanel(@ModelAttribute TbPanel tbPanel) {\n        BaseResult baseResult = panelService.updatePanel(tbPanel);\n        return baseResult;\n    }\n\n    /**\n     * 删除内容板块\n     *\n     * @param id 板块 id\n     * @return\n     */\n    @DeleteMapping(\"del/{id}\")\n    @ApiOperation(value = \"删除内容板块\")\n    public BaseResult deleteContentPanel(@PathVariable int id) {\n        BaseResult baseResult = panelService.deletePanelById(id);\n        return baseResult;\n    }\n\n    /**\n     * 添加内容板块\n     *\n     * @param tbPanel 板块\n     * @return\n     */\n    @PostMapping(\"add\")\n    @ApiOperation(value = \"添加内容板块\")\n    public BaseResult addContentPanel(@ModelAttribute TbPanel tbPanel) {\n        BaseResult baseResult = panelService.addPanel(tbPanel);\n        return baseResult;\n    }\n\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/SwaggerController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.http.ResponseEntity;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport springfox.documentation.swagger.web.ApiResourceController;\nimport springfox.documentation.swagger.web.SwaggerResource;\n\nimport java.util.List;\n\n/**\n * @Classname SwaggerController\n * @Date 2019/5/20 19:32\n * @Created by Yuu\n */\n@RestController\npublic class SwaggerController {\n\n    @Autowired\n    private ApiResourceController apiResourceController;\n\n    /**\n     * swagger-resources 路径映射\n     *\n     * @return\n     */\n    @GetMapping(\"/swagger-resources\")\n    public ResponseEntity<List<SwaggerResource>> swaggerResources() {\n        return apiResourceController.swaggerResources();\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/SystemController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.web.admin.commons.utils.IPInfoUtil;\nimport com.yuu.ymall.web.admin.service.SystemService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RestController;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * 系统Controller\n *\n * @Classname SystemController\n * @Date 2019/5/12 21:54\n * @Created by Yuu\n */\n@RestController\n@Api(description = \"系统配置管理\")\n@RequestMapping(\"sys\")\npublic class SystemController {\n\n    @Autowired\n    private SystemService systemService;\n\n    /**\n     * 获取天气信息\n     *\n     * @param request\n     * @return\n     */\n    @GetMapping(\"weather\")\n    @ApiOperation(value = \"获取天气信息\")\n    public BaseResult getWeather(HttpServletRequest request) {\n        // todo 修改 ip\n         String result = IPInfoUtil.getIpInfo(IPInfoUtil.getIpAddr(request));\n        return BaseResult.success((Object)result);\n    }\n\n    /**\n     * 获取本周热销商品数据\n     *\n     * @return\n     */\n    @GetMapping(\"weekHot\")\n    @ApiOperation(value = \"获取本周热销商品数据\")\n    public BaseResult getWeekHot() {\n        BaseResult baseResult = systemService.getWeekHot();\n        return baseResult;\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/UploadController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.web.admin.commons.utils.QiniuUtil;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.web.bind.annotation.PostMapping;\nimport org.springframework.web.bind.annotation.RestController;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.io.File;\nimport java.io.IOException;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @Classname UploadController\n * @Date 2019/5/24 20:21\n * @Created by Yuu\n */\n@RestController\n@Api(description = \"图片上传统一接口\")\npublic class UploadController {\n\n    private static final String UPLOAD_PATH = \"/static/upload/\";\n\n    /**\n     * 文件上传\n     *\n     * @param dropFile 文件\n     * @param request 请求\n     * @return\n     */\n    @PostMapping(\"upload\")\n    @ApiOperation(value = \"DropZone 图片上传\")\n    public Map<String, Object> uploadFile(MultipartFile dropFile, MultipartFile[] editorFiles, MultipartFile userFile, HttpServletRequest request) {\n        Map<String, Object> result = new HashMap<String, Object>();\n\n        String imagePath = \"\";\n\n        // Dropzone 上传\n        if (dropFile != null) {\n            imagePath = writeFile(dropFile, request);\n                    if (imagePath.contains(\"error\")) {\n                result.put(\"status\", 500);\n                result.put(\"message\", \"上传图片失败\");\n            } else {\n                result.put(\"status\", 200);\n                result.put(\"fileName\", imagePath);\n            }\n        }\n\n        // wangEditor 上传\n        if (editorFiles != null && editorFiles.length > 0) {\n            List<String> imagePaths = new ArrayList<>();\n\n            for (MultipartFile editorFile : editorFiles) {\n                imagePath = writeFile(editorFile, request);\n                if (imagePath.contains(\"error\")) {\n                    result.put(\"errno\", 1);\n                    return result;\n                }\n                imagePaths.add(imagePath);\n            }\n\n            result.put(\"errno\", 0);\n            result.put(\"data\", imagePaths);\n        }\n\n        // 头像上传\n        if (userFile != null) {\n            imagePath = writeFile(userFile, request);\n            if (imagePath.contains(\"error\")) {\n                result.put(\"status\", 500);\n                result.put(\"message\", \"上传图片失败\");\n            } else {\n                result.put(\"status\", 200);\n                result.put(\"imagePath\", imagePath);\n            }\n        }\n\n        return result;\n    }\n\n    /**\n     * 将图片上传到服务器\n     *\n     * @param multipartFile\n     * @param request\n     * @return 返回文件完整路径\n     */\n    private String writeFile(MultipartFile multipartFile, HttpServletRequest request) {\n        // 七牛云上传图片路径地址\n        String imagePath = \"\";\n\n        // 文件保存路径\n        String filePath = request.getSession().getServletContext().getRealPath(UPLOAD_PATH);\n\n        // 转存文件\n        try {\n            File file = new File(filePath);\n            if (!file.exists()) {\n                file.mkdirs();\n            }\n            // 重命名\n            file = new File(filePath, QiniuUtil.renamePic(multipartFile.getOriginalFilename()));\n            // 保存至本地\n            multipartFile.transferTo(file);\n            // 上传到七牛云服务器\n            imagePath = QiniuUtil.qiniuUpload(file.getPath());\n            // 本地路径为文件且不为空则进行删除\n            if (file.isFile() && file.exists()) {\n                file.delete();\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        return imagePath;\n    }\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/controller/UserController.java",
    "content": "package com.yuu.ymall.web.admin.web.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.geetest.GeetestLib;\nimport com.yuu.ymall.domain.TbUser;\nimport com.yuu.ymall.web.admin.commons.dto.DataTablesResult;\nimport com.yuu.ymall.web.admin.service.UserService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.apache.shiro.SecurityUtils;\nimport org.apache.shiro.authc.UsernamePasswordToken;\nimport org.apache.shiro.subject.Subject;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.util.DigestUtils;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpSession;\nimport java.util.HashMap;\n\n/**\n * 用户 Controller\n *\n * @Classname UserController\n * @Date 2019/5/11 22:20\n * @Created by Yuu\n */\n@RestController\n@Api(description = \"管理员管理\")\n@RequestMapping(\"user\")\npublic class UserController {\n\n    public static Logger log = LoggerFactory.getLogger(UserController.class);\n\n    @Autowired\n    private UserService userService;\n\n    /**\n     * 极验初始化\n     *\n     * @param session\n     * @return\n     */\n    @GetMapping(\"geetestInit\")\n    @ApiOperation(value = \"极验初始化\")\n    public String geetestInit(HttpSession session) {\n\n        GeetestLib gtSdk = new GeetestLib(GeetestLib.id, GeetestLib.key, GeetestLib.newfailback);\n\n        String resStr = \"{}\";\n\n        // 自定义参数，可选择添加\n        HashMap<String, String> param = new HashMap<>();\n\n        // 进行验证预处理\n        int getServerStatus = gtSdk.preProcess(param);\n\n        session.setAttribute(gtSdk.gtServerStatusSessionKey, getServerStatus);\n\n        resStr = gtSdk.getResponseStr();\n\n        return resStr;\n    }\n\n    /**\n     * 用户登录\n     *\n     * @param username 用户名\n     * @param password 密码\n     * @return\n     */\n    @PostMapping(\"login\")\n    @ApiOperation(value = \"用户登录\")\n    public BaseResult login(String username, String password, String challenge, String validate, String seccode, HttpSession session) {\n\n        // 极验验证\n        GeetestLib gtSdk = new GeetestLib(GeetestLib.id, GeetestLib.key,GeetestLib.newfailback);\n\n        // 从 session 中获取 gt-server 状态\n        int gt_server_status_code = (int) session.getAttribute(gtSdk.gtServerStatusSessionKey);\n\n        // 自定义参数，可选择添加\n        HashMap<String, String> param = new HashMap<>();\n\n        int gtResult = 0;\n\n        if (gt_server_status_code == 1) {\n            // gt-server 正常，向 gt-server 进行二次验证\n            gtResult = gtSdk.enhencedValidateRequest(challenge, validate, seccode, param);\n        } else {\n            // gt-server 非正常情况下，进行 failback 模式验证\n            gtResult = gtSdk.failbackValidateRequest(challenge, validate, seccode);\n        }\n\n        // 验证成功\n        if (gtResult == 1) {\n            Subject subject = SecurityUtils.getSubject();\n\n            // MD5 加密\n            String md5Pass = DigestUtils.md5DigestAsHex(password.getBytes());\n            UsernamePasswordToken token = new UsernamePasswordToken(username, md5Pass);\n\n            // 登录\n            try {\n                subject.login(token);\n                return BaseResult.success();\n            } catch (Exception e) {\n                return BaseResult.fail(\"用户名或密码错误\");\n            }\n        }\n\n        // 验证失败\n        else {\n            return BaseResult.fail(\"验证失败\");\n        }\n    }\n\n    /**\n     * 退出登录\n     *\n     * @return\n     */\n    @GetMapping(\"logout\")\n    @ApiOperation(value = \"退出登录\")\n    public BaseResult logout() {\n        Subject subject = SecurityUtils.getSubject();\n        subject.logout();\n        return BaseResult.success();\n    }\n\n    /**\n     * 获取用户信息\n     *\n     * @return\n     */\n    @GetMapping(\"userInfo\")\n    @ApiOperation(value = \"获取用户信息\")\n    public BaseResult getUserInfo() {\n        String username = SecurityUtils.getSubject().getPrincipal().toString();\n        TbUser tbUser = userService.getUserByUsername(username);\n        if (tbUser == null) {\n            return BaseResult.fail(\"获取用户信息失败！\");\n        }\n        tbUser.setPassword(null);\n        return BaseResult.success(tbUser);\n    }\n\n    /**\n     * 用户解锁\n     *\n     * @param password 密码\n     * @return\n     */\n    @GetMapping(\"unlock\")\n    @ApiOperation(value = \"用户解锁\")\n    public BaseResult unlock(String password) {\n        String username = SecurityUtils.getSubject().getPrincipal().toString();\n        TbUser tbUser = userService.getUserByUsername(username);\n        if (tbUser == null) {\n            return BaseResult.fail(\"用户不存在！\");\n        }\n        String md5Pwd = DigestUtils.md5DigestAsHex(password.getBytes());\n        if (!tbUser.getPassword().equals(md5Pwd)) {\n            return BaseResult.fail(\"密码不正确!\");\n        }\n        return BaseResult.success();\n    }\n\n    /**\n     * 获取用户列表\n     *\n     * @param request 请求\n     * @param search 搜索条件\n     * @return\n     */\n    @GetMapping(\"list\")\n    @ApiOperation(value = \"获取用户列表\")\n    public DataTablesResult<TbUser> getUserList(HttpServletRequest request, @RequestParam(\"search[value]\") String search) {\n        DataTablesResult<TbUser> dataTablesResult = userService.getUserList(request, search);\n        return dataTablesResult;\n    }\n\n    /**\n     * 验证用户名是否存在\n     *\n     * @param id 用户 id\n     * @param username 用户名\n     * @return\n     */\n    @GetMapping(\"username/{id}\")\n    @ApiOperation(value = \"验证用户名是否存在\")\n    public Boolean validateUsername(@PathVariable Long id, String username) {\n        Boolean flag = userService.validateUsername(id, username);\n        return flag;\n    }\n\n    /**\n     * 验证手机号是否存在\n     *\n     * @param id 用户 id\n     * @param phone 手机号\n     * @return\n     */\n    @GetMapping(\"phone/{id}\")\n    @ApiOperation(value = \"验证手机号是否存在\")\n    public Boolean validatePhone(@PathVariable Long id, String phone) {\n        Boolean flag = userService.validatePhone(id, phone);\n        return flag;\n    }\n\n    /**\n     * 验证邮箱是否存在\n     *\n     * @param id 用户 id\n     * @param email 邮箱\n     * @return\n     */\n    @GetMapping(\"email/{id}\")\n    @ApiOperation(value = \"验证邮箱是否存在\")\n    public Boolean validateEmail(@PathVariable Long id, String email) {\n        Boolean flag = userService.validateEmail(id, email);\n        return flag;\n    }\n\n    /**\n     * 保存用户\n     *\n     * @param tbUser 用户\n     * @return\n     */\n    @PostMapping(\"save\")\n    @ApiOperation(value = \"保存用户\")\n    public BaseResult save(TbUser tbUser) {\n        BaseResult baseResult = userService.save(tbUser);\n        return baseResult;\n    }\n\n    /**\n     * 修改密码\n     *\n     * @param id 用户 id\n     * @param password 用户密码\n     * @return\n     */\n    @PostMapping(\"changePass\")\n    @ApiOperation(value = \"修改密码\")\n    public BaseResult changePass(Long id, String password) {\n        BaseResult baseResult = userService.changePass(id, password);\n        return baseResult;\n    }\n\n    /**\n     * 删除用户\n     *\n     * @param ids\n     * @return\n     */\n    @DeleteMapping(\"delete/{ids}\")\n    @ApiOperation(value = \"删除用户\")\n    public BaseResult delete(@PathVariable Long[] ids) {\n        BaseResult baseResult = userService.delete(ids);\n        return baseResult;\n    }\n\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/java/com/yuu/ymall/web/admin/web/interceptor/PermissionInterceptor.java",
    "content": "package com.yuu.ymall.web.admin.web.interceptor;\n\nimport org.apache.shiro.SecurityUtils;\nimport org.apache.shiro.subject.Subject;\nimport org.springframework.web.servlet.HandlerInterceptor;\nimport org.springframework.web.servlet.ModelAndView;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpServletResponse;\n\n/**\n * 权限拦截器\n *\n * @Classname PermissionInterceptor\n * @Date 2019/5/12 22:31\n * @Created by Yuu\n */\npublic class PermissionInterceptor implements HandlerInterceptor {\n    @Override\n    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {\n        return true;\n    }\n\n    @Override\n    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {\n        // 以 login 结尾的请求\n        if (modelAndView != null && modelAndView.getViewName() != null && modelAndView.getViewName().endsWith(\"login\")) {\n            Subject subject = SecurityUtils.getSubject();\n            if (subject.isAuthenticated()) {\n                httpServletResponse.sendRedirect(\"/\");\n            }\n        }\n    }\n\n    @Override\n    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {\n\n    }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/resources/generatorConfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE generatorConfiguration\n        PUBLIC \"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd\">\n\n<generatorConfiguration>\n    <!-- 引入数据库连接配置 -->\n    <properties resource=\"ymall.properties\"/>\n\n    <context id=\"Mysql\" targetRuntime=\"MyBatis3Simple\" defaultModelType=\"flat\">\n        <property name=\"beginningDelimiter\" value=\"`\"/>\n        <property name=\"endingDelimiter\" value=\"`\"/>\n\n        <!-- 去除自动生成的注释 -->\n        <commentGenerator>\n            <property name=\"suppressAllComments\" value=\"true\" />\n        </commentGenerator>\n\n        <!-- 配置数据库连接 -->\n        <jdbcConnection\n                driverClass=\"${jdbc.driverClass}\"\n                connectionURL=\"${jdbc.connectionURL}\"\n                userId=\"${jdbc.username}\"\n                password=\"${jdbc.password}\">\n        </jdbcConnection>\n\n        <!-- 配置实体类存放路径 -->\n        <javaModelGenerator targetPackage=\"com.yuu.ymall.domain\" targetProject=\"src/main/java\"/>\n\n        <!-- 配置 XML 存放路径 -->\n        <sqlMapGenerator targetPackage=\"demo\" targetProject=\"src/main/resources\"/>\n\n        <!-- 配置 DAO 存放路径 -->\n        <javaClientGenerator\n                targetPackage=\"com.yuu.ymall.web.admin.demo.mapper\"\n                targetProject=\"src/main/java\"\n                type=\"XMLMAPPER\"/>\n\n        <!-- 配置需要指定生成的数据库和表，% 代表所有表 -->\n        <table tableName=\"%\" enableCountByExample=\"true\" enableDeleteByExample=\"true\"\n               enableSelectByExample=\"true\" enableUpdateByExample=\"true\">\n            <!-- mysql 配置 -->\n            <generatedKey column=\"id\" sqlStatement=\"Mysql\" identity=\"true\"/>\n        </table>\n    </context>\n\n</generatorConfiguration>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/log4j.properties",
    "content": "log4j.rootLogger=INFO, console, file\n\nlog4j.appender.console=org.apache.log4j.ConsoleAppender\nlog4j.appender.console.layout=org.apache.log4j.PatternLayout\nlog4j.appender.console.layout.ConversionPattern=%d %p [%c] - %m%n\n\nlog4j.appender.file=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.file.File=logs/log.log\nlog4j.appender.file.layout=org.apache.log4j.PatternLayout\nlog4j.appender.A3.MaxFileSize=1024KB\nlog4j.appender.A3.MaxBackupIndex=10\nlog4j.appender.file.layout.ConversionPattern=%d %p [%c] - %m%n"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbAddressMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbAddressMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbAddress\">\n    <id column=\"id\" jdbcType=\"BIGINT\" property=\"id\" />\n    <result column=\"user_id\" jdbcType=\"BIGINT\" property=\"userId\" />\n    <result column=\"user_name\" jdbcType=\"VARCHAR\" property=\"userName\" />\n    <result column=\"tel\" jdbcType=\"VARCHAR\" property=\"tel\" />\n    <result column=\"street_name\" jdbcType=\"VARCHAR\" property=\"streetName\" />\n    <result column=\"is_default\" jdbcType=\"BIT\" property=\"isDefault\" />\n    <result column=\"created\" jdbcType=\"TIMESTAMP\" property=\"created\" />\n    <result column=\"updated\" jdbcType=\"TIMESTAMP\" property=\"updated\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\">\n    delete from tb_address\n    where id = #{id,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbAddress\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.Long\">\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_address (user_id, user_name, tel, \n      street_name, is_default, created, \n      updated)\n    values (#{userId,jdbcType=BIGINT}, #{userName,jdbcType=VARCHAR}, #{tel,jdbcType=VARCHAR}, \n      #{streetName,jdbcType=VARCHAR}, #{isDefault,jdbcType=BIT}, #{created,jdbcType=TIMESTAMP}, \n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbAddress\">\n    update tb_address\n    set user_id = #{userId,jdbcType=BIGINT},\n      user_name = #{userName,jdbcType=VARCHAR},\n      tel = #{tel,jdbcType=VARCHAR},\n      street_name = #{streetName,jdbcType=VARCHAR},\n      is_default = #{isDefault,jdbcType=BIT},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=BIGINT}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Long\" resultMap=\"BaseResultMap\">\n    select id, user_id, user_name, tel, street_name, is_default, created, updated\n    from tb_address\n    where id = #{id,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select id, user_id, user_name, tel, street_name, is_default, created, updated\n    from tb_address\n  </select>\n</mapper>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbExpressMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbExpressMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbExpress\">\n    <id column=\"id\" jdbcType=\"INTEGER\" property=\"id\" />\n    <result column=\"express_name\" jdbcType=\"VARCHAR\" property=\"expressName\" />\n    <result column=\"sort_order\" jdbcType=\"INTEGER\" property=\"sortOrder\" />\n    <result column=\"created\" jdbcType=\"TIMESTAMP\" property=\"created\" />\n    <result column=\"updated\" jdbcType=\"TIMESTAMP\" property=\"updated\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Integer\">\n    delete from tb_express\n    where id = #{id,jdbcType=INTEGER}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbExpress\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.Integer\">\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_express (express_name, sort_order, created, \n      updated)\n    values (#{expressName,jdbcType=VARCHAR}, #{sortOrder,jdbcType=INTEGER}, #{created,jdbcType=TIMESTAMP}, \n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbExpress\">\n    update tb_express\n    set express_name = #{expressName,jdbcType=VARCHAR},\n      sort_order = #{sortOrder,jdbcType=INTEGER},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=INTEGER}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Integer\" resultMap=\"BaseResultMap\">\n    select id, express_name, sort_order, created, updated\n    from tb_express\n    where id = #{id,jdbcType=INTEGER}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select id, express_name, sort_order, created, updated\n    from tb_express\n  </select>\n\n    <sql id=\"tbExpressBaseColumns\">\n        a.id,\n        a.express_name,\n        a.sort_order,\n        a.created,\n        a.updated\n    </sql>\n\n    <!-- 获取快递列表 -->\n    <select id=\"getExpressList\" resultMap=\"BaseResultMap\" parameterType=\"map\">\n      select <include refid=\"tbExpressBaseColumns\"/>\n      from tb_express as a\n      order by sort_order asc\n    </select>\n\n    <!-- 获取快递总数 -->\n    <select id=\"getTbExpressCount\" resultType=\"int\" parameterType=\"map\">\n        select count(*)\n        from tb_express as a\n    </select>\n</mapper>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbItemCatMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbItemCatMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbItemCat\">\n    <id column=\"id\" jdbcType=\"BIGINT\" property=\"id\" />\n    <result column=\"parent_id\" jdbcType=\"BIGINT\" property=\"parentId\" />\n    <result column=\"name\" jdbcType=\"VARCHAR\" property=\"name\" />\n    <result column=\"status\" jdbcType=\"INTEGER\" property=\"status\" />\n    <result column=\"sort_order\" jdbcType=\"INTEGER\" property=\"sortOrder\" />\n    <result column=\"is_parent\" jdbcType=\"BIT\" property=\"isParent\" />\n    <result column=\"created\" jdbcType=\"TIMESTAMP\" property=\"created\" />\n    <result column=\"updated\" jdbcType=\"TIMESTAMP\" property=\"updated\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\">\n    delete from tb_item_cat\n    where id = #{id,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbItemCat\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.Long\">\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_item_cat (parent_id, name, status, \n      sort_order, is_parent, created, updated\n      )\n    values (#{parentId,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{status,jdbcType=INTEGER}, \n      #{sortOrder,jdbcType=INTEGER}, #{isParent,jdbcType=BIT}, #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP}\n      )\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbItemCat\">\n    update tb_item_cat\n    set parent_id = #{parentId,jdbcType=BIGINT},\n      name = #{name,jdbcType=VARCHAR},\n      status = #{status,jdbcType=INTEGER},\n      sort_order = #{sortOrder,jdbcType=INTEGER},\n      is_parent = #{isParent,jdbcType=BIT},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=BIGINT}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Long\" resultMap=\"BaseResultMap\">\n    select id, parent_id, name, status, sort_order, is_parent, created,\n    updated\n    from tb_item_cat\n    where id = #{id,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select id, parent_id, name, status, sort_order, is_parent, created,\n    updated\n    from tb_item_cat\n  </select>\n\n    <!-- 根据父 id 查询分类 id -->\n    <select id=\"getItemCatList\" resultType=\"tbItemCat\">\n        select * from tb_item_cat\n        where parent_id = #{parentId}\n        order by sort_order\n    </select>\n\n    <!-- 查询该分类下的最分类最大的排序值 -->\n    <select id=\"getMaxSortOrder\" resultType=\"int\">\n        select IFNULL(max(sort_order), 0) from tb_item_cat where parent_id = #{parentId}\n    </select>\n</mapper>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbItemDescMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbItemDescMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbItemDesc\">\n    <id column=\"item_id\" jdbcType=\"BIGINT\" property=\"itemId\" />\n    <result column=\"created\" jdbcType=\"TIMESTAMP\" property=\"created\" />\n    <result column=\"updated\" jdbcType=\"TIMESTAMP\" property=\"updated\" />\n    <result column=\"item_desc\" jdbcType=\"LONGVARCHAR\" property=\"itemDesc\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\">\n    delete from tb_item_desc\n    where item_id = #{itemId,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbItemDesc\">\n    insert into tb_item_desc (item_id, created, updated, item_desc\n      )\n    values (#{itemId,jdbcType=BIGINT}, #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP}, #{itemDesc,jdbcType=LONGVARCHAR}\n      )\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbItemDesc\">\n    update tb_item_desc\n    set created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP},\n      item_desc = #{itemDesc,jdbcType=LONGVARCHAR}\n    where item_id = #{itemId,jdbcType=BIGINT}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Long\" resultMap=\"BaseResultMap\">\n    select item_id, created, updated, item_desc\n    from tb_item_desc\n    where item_id = #{itemId,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select item_id, created, updated, item_desc\n    from tb_item_desc\n  </select>\n</mapper>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbItemMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbItemMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbItem\">\n    <id column=\"id\" jdbcType=\"BIGINT\" property=\"id\" />\n    <result column=\"title\" jdbcType=\"VARCHAR\" property=\"title\" />\n    <result column=\"sell_point\" jdbcType=\"VARCHAR\" property=\"sellPoint\" />\n    <result column=\"price\" jdbcType=\"DECIMAL\" property=\"price\" />\n    <result column=\"num\" jdbcType=\"INTEGER\" property=\"num\" />\n    <result column=\"limit_num\" jdbcType=\"INTEGER\" property=\"limitNum\" />\n    <result column=\"image\" jdbcType=\"VARCHAR\" property=\"image\" />\n    <result column=\"cid\" jdbcType=\"BIGINT\" property=\"cid\" />\n    <result column=\"status\" jdbcType=\"INTEGER\" property=\"status\" />\n    <result column=\"created\" jdbcType=\"TIMESTAMP\" property=\"created\" />\n    <result column=\"updated\" jdbcType=\"TIMESTAMP\" property=\"updated\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\">\n    delete from tb_item\n    where id = #{id,jdbcType=BIGINT}\n  </delete>\n    <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbItem\">\n    insert into tb_item (id, title, sell_point, price,\n      num, limit_num, image,\n      cid, status, created,\n      updated)\n    values (#{id,jdbcType=BIGINT}, #{title,jdbcType=VARCHAR}, #{sellPoint,jdbcType=VARCHAR}, #{price,jdbcType=DECIMAL},\n      #{num,jdbcType=INTEGER}, #{limitNum,jdbcType=INTEGER}, #{image,jdbcType=VARCHAR},\n      #{cid,jdbcType=BIGINT}, #{status,jdbcType=INTEGER}, #{created,jdbcType=TIMESTAMP},\n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbItem\">\n    update tb_item\n    set title = #{title,jdbcType=VARCHAR},\n      sell_point = #{sellPoint,jdbcType=VARCHAR},\n      price = #{price,jdbcType=DECIMAL},\n      num = #{num,jdbcType=INTEGER},\n      limit_num = #{limitNum,jdbcType=INTEGER},\n      image = #{image,jdbcType=VARCHAR},\n      cid = #{cid,jdbcType=BIGINT},\n      status = #{status,jdbcType=INTEGER},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=BIGINT}\n  </update>\n    <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Long\" resultMap=\"BaseResultMap\">\n    select id, title, sell_point, price, num, limit_num, image, cid, status, created,\n    updated\n    from tb_item\n    where id = #{id,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select id, title, sell_point, price, num, limit_num, image, cid, status, created,\n    updated\n    from tb_item\n  </select>\n\n    <!-- sql 片断 -->\n    <sql id=\"tbItemColumns\">\n        a.id,\n        a.title,\n        a.sell_point,\n        a.price,\n        a.num,\n        a.limit_num,\n        a.image,\n        a.cid,\n        a.status,\n        a.created,\n        a.updated\n    </sql>\n\n    <!-- 获取商品总数 -->\n    <select id=\"getAllItemCount\" resultType=\"java.lang.Integer\">\n        select count(*) from tb_item;\n    </select>\n\n    <!-- 条件查询商品集合 -->\n    <select id=\"selectItemByCondition\" resultType=\"com.yuu.ymall.domain.TbItem\">\n        select <include refid=\"tbItemColumns\"/>\n        from tb_item as a\n        <where>\n            <if test=\"search != null and != ''\">\n                AND title like concat(concat('%', #{search} ), '%')\n                OR sell_point like concat(concat('%', #{search} ), '%')\n                OR price like concat(concat('%', #{search} ), '%')\n                OR id like concat(concat('%', #{search} ), '%')\n            </if>\n            <if test=\"cid != -1\">\n                AND cid = #{cid}\n            </if>\n        </where>\n    </select>\n\n    <!-- 根据分类 id 获取商品列表 -->\n    <select id=\"getItemByCid\" resultType=\"com.yuu.ymall.domain.TbItem\" parameterType=\"map\">\n        select <include refid=\"tbItemColumns\"/>\n        from tb_item as a\n        <where>\n            <if test=\"cid != -1\">\n                AND a.cid = #{cid}\n            </if>\n            <if test=\"search != null and search != ''\">\n                AND (title like concat(concat('%', #{search} ), '%')\n                OR sell_point like concat(concat('%', #{search} ), '%')\n                OR price like concat(concat('%', #{search} ), '%')\n                OR id like concat(concat('%', #{search} ), '%'))\n            </if>\n        </where>\n        order by updated desc\n    </select>\n\n    <!-- 查询分类商品总数 -->\n    <select id=\"getTbItemByCidCount\" resultType=\"java.lang.Integer\" parameterType=\"map\">\n        select count(*)\n        from tb_item as a\n        <where>\n            <if test=\"cid != -1\">\n                AND a.cid = #{cid}\n            </if>\n        </where>\n    </select>\n\n    <!-- 下架商品 -->\n    <update id=\"stopItemById\">\n        update tb_item\n        set status = 0\n        where id = #{id}\n    </update>\n\n    <!-- 发布商品 -->\n    <update id=\"startItemById\">\n        update tb_item\n        set status = 1\n        where id = #{id}\n    </update>\n</mapper>\n"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbMemberMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbMemberMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbMember\">\n    <id column=\"id\" jdbcType=\"BIGINT\" property=\"id\" />\n    <result column=\"username\" jdbcType=\"VARCHAR\" property=\"username\" />\n    <result column=\"password\" jdbcType=\"VARCHAR\" property=\"password\" />\n    <result column=\"phone\" jdbcType=\"VARCHAR\" property=\"phone\" />\n    <result column=\"email\" jdbcType=\"VARCHAR\" property=\"email\" />\n    <result column=\"sex\" jdbcType=\"VARCHAR\" property=\"sex\" />\n    <result column=\"state\" jdbcType=\"INTEGER\" property=\"state\" />\n    <result column=\"file\" jdbcType=\"VARCHAR\" property=\"file\" />\n    <result column=\"description\" jdbcType=\"VARCHAR\" property=\"description\" />\n    <result column=\"created\" jdbcType=\"TIMESTAMP\" property=\"created\" />\n    <result column=\"updated\" jdbcType=\"TIMESTAMP\" property=\"updated\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\">\n    delete from tb_member\n    where id = #{id,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbMember\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.Long\">\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_member (username, password, phone, \n      email, sex,\n      state, file, description, \n      created, updated)\n    values (#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR}, \n      #{email,jdbcType=VARCHAR}, #{sex,jdbcType=VARCHAR},\n      #{state,jdbcType=INTEGER}, #{file,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, \n      #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbMember\">\n    update tb_member\n    set username = #{username,jdbcType=VARCHAR},\n      password = #{password,jdbcType=VARCHAR},\n      phone = #{phone,jdbcType=VARCHAR},\n      email = #{email,jdbcType=VARCHAR},\n      sex = #{sex,jdbcType=VARCHAR},\n      state = #{state,jdbcType=INTEGER},\n      file = #{file,jdbcType=VARCHAR},\n      description = #{description,jdbcType=VARCHAR},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=BIGINT}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Long\" resultMap=\"BaseResultMap\">\n    select id, username, password, phone, email, sex, state, file, description,\n    created, updated\n    from tb_member\n    where id = #{id,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select id, username, password, phone, email, sex, state, file, description,\n    created, updated\n    from tb_member\n  </select>\n\n    <!-- sql 片断 -->\n    <sql id=\"tbMemberBaseColumns\">\n        a.id,\n        a.username,\n        a.password,\n        a.phone,\n        a.email,\n        a.sex,\n        a.state,\n        a.file,\n        a.description,\n        a.created,\n        a.updated\n    </sql>\n\n    <!-- 获取会员总数 -->\n    <select id=\"getAllMemberCount\" resultType=\"java.lang.Integer\">\n        select count(*) from tb_member;\n    </select>\n\n    <!-- 获取会员列表 -->\n    <select id=\"getMemberList\" resultMap=\"BaseResultMap\">\n        select <include refid=\"tbMemberBaseColumns\"/>\n        from tb_member as a\n        <where>\n            <if test=\"search != null and search != ''\">\n                AND id like concat('%', #{search}, '%')\n                OR username like concat('%', #{search}, '%')\n                OR phone like concat('%', #{search}, '%')\n                OR email like concat('%', #{search}, '%')\n            </if>\n        </where>\n    </select>\n\n    <!-- 获取会员列表总数 -->\n    <select id=\"getMemberListCount\" resultType=\"int\">\n        select count(*)\n        from tb_member\n        <where>\n            <if test=\"search != null and search != ''\">\n                AND id like concat('%', #{search}, '%')\n                OR username like concat('%', #{search}, '%')\n                OR phone like concat('%', #{search}, '%')\n                OR email like concat('%', #{search}, '%')\n            </if>\n        </where>\n    </select>\n\n    <!-- 根据会员名查询会员 -->\n    <select id=\"getMemberByUsername\" resultMap=\"BaseResultMap\" parameterType=\"string\">\n        select <include refid=\"tbMemberBaseColumns\"/>\n        from tb_member as a\n        where username = #{username}\n    </select>\n\n    <!-- 根据手机号查询会员 -->\n    <select id=\"getMemberByPhone\" resultMap=\"BaseResultMap\" parameterType=\"string\">\n        select <include refid=\"tbMemberBaseColumns\"/>\n        from tb_member as a\n        where phone = #{phone}\n    </select>\n\n    <!-- 根据邮箱查询会员 -->\n    <select id=\"getMemberByEmail\" resultMap=\"BaseResultMap\" parameterType=\"string\">\n        select <include refid=\"tbMemberBaseColumns\"/>\n        from tb_member as a\n        where email = #{email}\n    </select>\n\n    <!-- 获取被封禁的会员列表 -->\n    <select id=\"getMemberBanList\" resultMap=\"BaseResultMap\">\n        select <include refid=\"tbMemberBaseColumns\"/>\n        from tb_member as a\n        <where>\n            a.state = 2\n            <if test=\"search != null and search != ''\">\n                AND (id like concat('%', #{search}, '%')\n                OR username like concat('%', #{search}, '%')\n                OR phone like concat('%', #{search}, '%')\n                OR email like concat('%', #{search}, '%'))\n            </if>\n        </where>\n    </select>\n\n    <!-- 获取被封禁的会员总数 -->\n    <select id=\"getMemberBanListCount\" resultType=\"int\">\n        select count(*)\n        from tb_member\n        <where>\n            state = 2\n            <if test=\"search != null and search != ''\">\n                AND (id like concat('%', #{search}, '%')\n                OR username like concat('%', #{search}, '%')\n                OR phone like concat('%', #{search}, '%')\n                OR email like concat('%', #{search}, '%'))\n            </if>\n        </where>\n    </select>\n</mapper>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbOrderItemMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbOrderItemMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbOrderItem\">\n    <id column=\"id\" jdbcType=\"VARCHAR\" property=\"id\" />\n    <result column=\"item_id\" jdbcType=\"VARCHAR\" property=\"itemId\" />\n    <result column=\"order_id\" jdbcType=\"VARCHAR\" property=\"orderId\" />\n    <result column=\"num\" jdbcType=\"INTEGER\" property=\"num\" />\n    <result column=\"title\" jdbcType=\"VARCHAR\" property=\"title\" />\n    <result column=\"price\" jdbcType=\"DECIMAL\" property=\"price\" />\n    <result column=\"total_fee\" jdbcType=\"DECIMAL\" property=\"totalFee\" />\n    <result column=\"pic_path\" jdbcType=\"VARCHAR\" property=\"picPath\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\">\n    delete from tb_order_item\n    where id = #{id,jdbcType=VARCHAR}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbOrderItem\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.String\">\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_order_item (item_id, order_id, num,\n      title, price, total_fee,\n      pic_path\n      )\n    values (#{itemId,jdbcType=VARCHAR}, #{orderId,jdbcType=VARCHAR}, #{num,jdbcType=INTEGER},\n      #{title,jdbcType=VARCHAR}, #{price,jdbcType=DECIMAL}, #{totalFee,jdbcType=DECIMAL},\n      #{picPath,jdbcType=VARCHAR}\n      )\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbOrderItem\">\n    update tb_order_item\n    set item_id = #{itemId,jdbcType=VARCHAR},\n      order_id = #{orderId,jdbcType=VARCHAR},\n      num = #{num,jdbcType=INTEGER},\n      title = #{title,jdbcType=VARCHAR},\n      price = #{price,jdbcType=DECIMAL},\n      total_fee = #{totalFee,jdbcType=DECIMAL},\n      pic_path = #{picPath,jdbcType=VARCHAR},\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n    select id, item_id, order_id, num, title, price, total_fee, pic_path\n    from tb_order_item\n    where id = #{id,jdbcType=VARCHAR}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select id, item_id, order_id, num, title, price, total_fee, pic_path\n    from tb_order_item\n  </select>\n\n    <sql id=\"tbOrderItemBaseColumns\">\n        a.id,\n        a.item_id,\n        a.order_id,\n        a.num,\n        a.title,\n        a.price,\n        a.total_fee,\n        a.pic_path\n    </sql>\n\n    <!-- 获取本周最热商品 -->\n    <select id=\"getWeekHot\" resultType=\"TbOrderItem\">\n        SELECT\n        i.title,\n        i.pic_path picPath,\n        count(*) total\n        FROM\n        tb_order_item i\n        LEFT JOIN tb_order o ON i.order_id = o.id\n        WHERE\n        YEARWEEK(date_format(o.created, '%Y-%m-%d'), 1) = YEARWEEK(now(), 1)\n        AND o.status = 4\n        GROUP BY\n        i.item_id\n        ORDER BY\n        COUNT(*) DESC\n    </select>\n\n    <!-- 查看商品是否有订单 -->\n    <select id=\"selectByItemId\" resultType=\"java.lang.Integer\">\n        select IFNULL(count(*), 0)\n        from tb_order_item\n        where item_id = #{id}\n    </select>\n\n    <!-- 根据订单 id， 查询订单项集合 -->\n    <select id=\"selectOrderItemByOrderId\" resultType=\"tbOrderItem\">\n        select <include refid=\"tbOrderItemBaseColumns\"/>\n        from tb_order_item as a\n        where order_id = #{orderId}\n    </select>\n\n    <!-- 查询商品订单数量 -->\n    <select id=\"selectOrderNumByItemId\" resultType=\"java.lang.Integer\">\n        select count(*)\n        from tb_order_item\n        where item_id = #{itemId}\n    </select>\n</mapper>\n"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbOrderMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbOrderMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbOrder\">\n    <id column=\"id\" jdbcType=\"VARCHAR\" property=\"id\" />\n    <result column=\"payment\" jdbcType=\"DECIMAL\" property=\"payment\" />\n    <result column=\"payment_type\" jdbcType=\"INTEGER\" property=\"paymentType\" />\n    <result column=\"post_fee\" jdbcType=\"DECIMAL\" property=\"postFee\" />\n    <result column=\"status\" jdbcType=\"INTEGER\" property=\"status\" />\n    <result column=\"created\" jdbcType=\"TIMESTAMP\" property=\"created\" />\n    <result column=\"updated\" jdbcType=\"TIMESTAMP\" property=\"updated\" />\n    <result column=\"payment_time\" jdbcType=\"TIMESTAMP\" property=\"paymentTime\" />\n    <result column=\"consign_time\" jdbcType=\"TIMESTAMP\" property=\"consignTime\" />\n    <result column=\"end_time\" jdbcType=\"TIMESTAMP\" property=\"endTime\" />\n    <result column=\"close_time\" jdbcType=\"TIMESTAMP\" property=\"closeTime\" />\n    <result column=\"shipping_name\" jdbcType=\"VARCHAR\" property=\"shippingName\" />\n    <result column=\"shipping_code\" jdbcType=\"VARCHAR\" property=\"shippingCode\" />\n    <result column=\"user_id\" jdbcType=\"BIGINT\" property=\"userId\" />\n    <result column=\"buyer_message\" jdbcType=\"VARCHAR\" property=\"buyerMessage\" />\n    <result column=\"buyer_nick\" jdbcType=\"VARCHAR\" property=\"buyerNick\" />\n    <result column=\"buyer_comment\" jdbcType=\"BIT\" property=\"buyerComment\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\">\n    delete from tb_order\n    where id = #{id,jdbcType=VARCHAR}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbOrder\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.String\">\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_order (payment, payment_type, post_fee,\n      status, created, updated,\n      payment_time, consign_time, end_time,\n      close_time, shipping_name, shipping_code,\n      user_id, buyer_message, buyer_nick,\n      buyer_comment)\n    values (#{payment,jdbcType=DECIMAL}, #{paymentType,jdbcType=INTEGER}, #{postFee,jdbcType=DECIMAL},\n      #{status,jdbcType=INTEGER}, #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP},\n      #{paymentTime,jdbcType=TIMESTAMP}, #{consignTime,jdbcType=TIMESTAMP}, #{endTime,jdbcType=TIMESTAMP},\n      #{closeTime,jdbcType=TIMESTAMP}, #{shippingName,jdbcType=VARCHAR}, #{shippingCode,jdbcType=VARCHAR},\n      #{userId,jdbcType=BIGINT}, #{buyerMessage,jdbcType=VARCHAR}, #{buyerNick,jdbcType=VARCHAR},\n      #{buyerComment,jdbcType=BIT})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbOrder\">\n    update tb_order\n    set payment = #{payment,jdbcType=DECIMAL},\n      payment_type = #{paymentType,jdbcType=INTEGER},\n      post_fee = #{postFee,jdbcType=DECIMAL},\n      status = #{status,jdbcType=INTEGER},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP},\n      payment_time = #{paymentTime,jdbcType=TIMESTAMP},\n      consign_time = #{consignTime,jdbcType=TIMESTAMP},\n      end_time = #{endTime,jdbcType=TIMESTAMP},\n      close_time = #{closeTime,jdbcType=TIMESTAMP},\n      shipping_name = #{shippingName,jdbcType=VARCHAR},\n      shipping_code = #{shippingCode,jdbcType=VARCHAR},\n      user_id = #{userId,jdbcType=BIGINT},\n      buyer_message = #{buyerMessage,jdbcType=VARCHAR},\n      buyer_nick = #{buyerNick,jdbcType=VARCHAR},\n      buyer_comment = #{buyerComment,jdbcType=BIT}\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n    select id, payment, payment_type, post_fee, status, created, updated, payment_time,\n    consign_time, end_time, close_time, shipping_name, shipping_code, user_id, buyer_message,\n    buyer_nick, buyer_comment\n    from tb_order\n    where id = #{id,jdbcType=VARCHAR}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select id, payment, payment_type, post_fee, status, created, updated, payment_time,\n    consign_time, end_time, close_time, shipping_name, shipping_code, user_id, buyer_message,\n    buyer_nick, buyer_comment\n    from tb_order\n  </select>\n\n    <sql id=\"tbOrderBaseColumns\">\n        a.id,\n        a.payment,\n        a.payment_type,\n        a.post_fee,\n        a.status,\n        a.created,\n        a.updated,\n        a.payment_time,\n        a.consign_time,\n        a.end_time,\n        a.close_time,\n        a.shipping_name,\n        a.shipping_code,\n        a.user_id,\n        a.buyer_message,\n        a.buyer_nick,\n        a.buyer_comment\n    </sql>\n\n    <!-- 获取订单总数 -->\n    <select id=\"getAllOrderCount\" resultType=\"int\">\n        select count(*) from tb_order;\n    </select>\n\n\n    <!-- 获取订单列表 -->\n    <select id=\"getOrderList\" resultType=\"tbOrder\" parameterType=\"map\">\n        select <include refid=\"tbOrderBaseColumns\"/>\n        from tb_order as a\n        <where>\n            <if test=\"search != null and search != ''\">\n                AND (id like concat('%', #{search}, '%'))\n                OR (buyer_nick like concat('%', #{search}, '%'))\n            </if>\n            <if test=\"status != -1\">\n                AND status = #{status}\n            </if>\n        </where>\n        order by created desc\n    </select>\n\n    <!-- 获取订单列表数量 -->\n    <select id=\"getTbOrderCount\" resultType=\"int\">\n        select count(*)\n        from tb_order\n        <where>\n            <if test=\"search != null and search != ''\">\n                AND (id like concat('%', #{search}, '%'))\n                OR (buyer_nick like concat('%', #{search}, '%'))\n            </if>\n            <if test=\"status != -1\">\n                AND status = #{status}\n            </if>\n        </where>\n    </select>\n\n    <!-- 查询图表数据 -->\n    <select id=\"selectOrderChart\" resultType=\"com.yuu.ymall.web.admin.commons.dto.OrderChartData\">\n      select\n      sum(payment) money, DATE(created) time\n      from tb_order\n      where\n      created BETWEEN #{startTime} and #{endTime}\n      and status = 4\n      GROUP BY DAY(created)\n    </select>\n\n    <!-- 按年份查询图表数据 -->\n    <select id=\"selectOrderChartByYear\" resultType=\"com.yuu.ymall.web.admin.commons.dto.OrderChartData\">\n      select\n      sum(payment) money, DATE(created) time\n      from tb_order\n      where\n      year(created) = #{year}\n      and status = 4\n      group by month(created)\n    </select>\n\n</mapper>\n"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbOrderShippingMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbOrderShippingMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbOrderShipping\">\n    <id column=\"order_id\" jdbcType=\"VARCHAR\" property=\"orderId\" />\n    <result column=\"receiver_name\" jdbcType=\"VARCHAR\" property=\"receiverName\" />\n    <result column=\"receiver_phone\" jdbcType=\"VARCHAR\" property=\"receiverPhone\" />\n    <result column=\"receiver_mobile\" jdbcType=\"VARCHAR\" property=\"receiverMobile\" />\n    <result column=\"receiver_province\" jdbcType=\"VARCHAR\" property=\"receiverProvince\" />\n    <result column=\"receiver_city\" jdbcType=\"VARCHAR\" property=\"receiverCity\" />\n    <result column=\"receiver_district\" jdbcType=\"VARCHAR\" property=\"receiverDistrict\" />\n    <result column=\"receiver_address\" jdbcType=\"VARCHAR\" property=\"receiverAddress\" />\n    <result column=\"receiver_zip\" jdbcType=\"VARCHAR\" property=\"receiverZip\" />\n    <result column=\"created\" jdbcType=\"TIMESTAMP\" property=\"created\" />\n    <result column=\"updated\" jdbcType=\"TIMESTAMP\" property=\"updated\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\">\n    delete from tb_order_shipping\n    where order_id = #{orderId,jdbcType=VARCHAR}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbOrderShipping\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.String\">\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_order_shipping (receiver_name, receiver_phone, receiver_mobile, \n      receiver_province, receiver_city, receiver_district,\n      receiver_address, receiver_zip, created, \n      updated)\n    values (#{receiverName,jdbcType=VARCHAR}, #{receiverPhone,jdbcType=VARCHAR}, #{receiverMobile,jdbcType=VARCHAR}, \n      #{receiverProvince,jdbcType=VARCHAR}, #{receiverCity,jdbcType=VARCHAR}, #{receiverDistrict,jdbcType=VARCHAR},\n      #{receiverAddress,jdbcType=VARCHAR}, #{receiverZip,jdbcType=VARCHAR}, #{created,jdbcType=TIMESTAMP}, \n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbOrderShipping\">\n    update tb_order_shipping\n    set receiver_name = #{receiverName,jdbcType=VARCHAR},\n      receiver_phone = #{receiverPhone,jdbcType=VARCHAR},\n      receiver_mobile = #{receiverMobile,jdbcType=VARCHAR},\n      receiver_province = #{receiverProvince,jdbcType=VARCHAR},\n      receiver_city = #{receiverCity,jdbcType=VARCHAR},\n      receiver_district = #{receiverDistrict,jdbcType=VARCHAR},\n      receiver_address = #{receiverAddress,jdbcType=VARCHAR},\n      receiver_zip = #{receiverZip,jdbcType=VARCHAR},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where order_id = #{id,jdbcType=VARCHAR}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.String\" resultMap=\"BaseResultMap\">\n    select order_id, receiver_name, receiver_phone, receiver_mobile, receiver_province, receiver_city,\n    receiver_district, receiver_address, receiver_zip, created, updated\n    from tb_order_shipping\n    where order_id = #{id,jdbcType=VARCHAR}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select order_id, receiver_name, receiver_phone, receiver_mobile, receiver_province, receiver_city,\n    receiver_district, receiver_address, receiver_zip, created, updated\n    from tb_order_shipping\n  </select>\n</mapper>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbPanelContentMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbPanelContentMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbPanelContent\">\n    <id column=\"id\" jdbcType=\"INTEGER\" property=\"id\" />\n    <result column=\"panel_id\" jdbcType=\"INTEGER\" property=\"panelId\" />\n    <result column=\"type\" jdbcType=\"INTEGER\" property=\"type\" />\n    <result column=\"product_id\" jdbcType=\"BIGINT\" property=\"productId\" />\n    <result column=\"sort_order\" jdbcType=\"INTEGER\" property=\"sortOrder\" />\n    <result column=\"full_url\" jdbcType=\"VARCHAR\" property=\"fullUrl\" />\n    <result column=\"pic_url\" jdbcType=\"VARCHAR\" property=\"picUrl\" />\n    <result column=\"pic_url2\" jdbcType=\"VARCHAR\" property=\"picUrl2\" />\n    <result column=\"pic_url3\" jdbcType=\"VARCHAR\" property=\"picUrl3\" />\n    <result column=\"created\" jdbcType=\"TIMESTAMP\" property=\"created\" />\n    <result column=\"updated\" jdbcType=\"TIMESTAMP\" property=\"updated\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Integer\">\n    delete from tb_panel_content\n    where id = #{id,jdbcType=INTEGER}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbPanelContent\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.Integer\">\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_panel_content (panel_id, type, product_id, \n      sort_order, full_url, pic_url, \n      pic_url2, pic_url3, created, \n      updated)\n    values (#{panelId,jdbcType=INTEGER}, #{type,jdbcType=INTEGER}, #{productId,jdbcType=BIGINT}, \n      #{sortOrder,jdbcType=INTEGER}, #{fullUrl,jdbcType=VARCHAR}, #{picUrl,jdbcType=VARCHAR}, \n      #{picUrl2,jdbcType=VARCHAR}, #{picUrl3,jdbcType=VARCHAR}, #{created,jdbcType=TIMESTAMP}, \n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbPanelContent\">\n    update tb_panel_content\n    set panel_id = #{panelId,jdbcType=INTEGER},\n      type = #{type,jdbcType=INTEGER},\n      product_id = #{productId,jdbcType=BIGINT},\n      sort_order = #{sortOrder,jdbcType=INTEGER},\n      full_url = #{fullUrl,jdbcType=VARCHAR},\n      pic_url = #{picUrl,jdbcType=VARCHAR},\n      pic_url2 = #{picUrl2,jdbcType=VARCHAR},\n      pic_url3 = #{picUrl3,jdbcType=VARCHAR},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=INTEGER}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Integer\" resultMap=\"BaseResultMap\">\n    select id, panel_id, type, product_id, sort_order, full_url, pic_url, pic_url2, pic_url3, \n    created, updated\n    from tb_panel_content\n    where id = #{id,jdbcType=INTEGER}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select id, panel_id, type, product_id, sort_order, full_url, pic_url, pic_url2, pic_url3, \n    created, updated\n    from tb_panel_content\n  </select>\n\n    <!-- sql 片断 -->\n    <sql id=\"tbPanelContentColumns\">\n        a.id,\n        a.panel_id,\n        a.type,\n        a.product_id,\n        a.sort_order,\n        a.full_url,\n        a.pic_url,\n        a.pic_url2,\n        a.pic_url3,\n        a.created,\n        a.updated\n    </sql>\n\n    <!-- 根据板块 id 获取板块内容 -->\n    <select id=\"getTbPanelContentByPanelId\" resultType=\"TbPanelContent\" parameterType=\"map\">\n        select <include refid=\"tbPanelContentColumns\"/>\n        from tb_panel_content as a\n        <where>\n            <if test=\"panelId != null\">\n                AND a.panel_id = #{panelId}\n            </if>\n            <if test=\"search != null and search != ''\">\n                AND (a.id like concat('%', #{search}, '%')\n                OR a.product_id like concat('%', #{search}, '%')\n                OR a.full_url like concat('%', #{search}, '%')\n                OR a.pic_url like concat('%', #{search}, '%'))\n            </if>\n        </where>\n        order by sort_order\n    </select>\n\n    <!-- 条件查询板块内容总数 -->\n    <select id=\"getTbPanelContentCount\" resultType=\"java.lang.Integer\" parameterType=\"map\">\n        select count(*)\n        from tb_panel_content\n        <where>\n            <if test=\"panelId != null\">\n                AND panel_id = #{panelId}\n            </if>\n        </where>\n    </select>\n\n    <!-- 查询商品是否关联首页商品 -->\n    <select id=\"selectContentByIid\" resultType=\"int\">\n        select count(*)\n        from tb_panel_content\n        where product_id = #{id}\n    </select>\n\n</mapper>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbPanelMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbPanelMapper\">\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Integer\">\n    delete from tb_panel\n    where id = #{id,jdbcType=INTEGER}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbPanel\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.Integer\">\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_panel (name, type, sort_order, \n      position, limit_num, status, \n       created, updated\n      )\n    values (#{name,jdbcType=VARCHAR}, #{type,jdbcType=INTEGER}, #{sortOrder,jdbcType=INTEGER}, \n      #{position,jdbcType=INTEGER}, #{limitNum,jdbcType=INTEGER}, #{status,jdbcType=INTEGER}, \n       #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP}\n      )\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbPanel\">\n    update tb_panel\n    set name = #{name,jdbcType=VARCHAR},\n      type = #{type,jdbcType=INTEGER},\n      sort_order = #{sortOrder,jdbcType=INTEGER},\n      position = #{position,jdbcType=INTEGER},\n      limit_num = #{limitNum,jdbcType=INTEGER},\n      status = #{status,jdbcType=INTEGER},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=INTEGER}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Integer\" resultType=\"tbPanel\">\n    select id, name, type, sort_order, position, limit_num, status, created,\n    updated\n    from tb_panel\n    where id = #{id,jdbcType=INTEGER}\n  </select>\n  <select id=\"selectAll\" resultType=\"tbPanel\">\n    select id, name, type, sort_order, position, limit_num, status, created,\n    updated\n    from tb_panel\n  </select>\n\n    <!-- sql 封装 -->\n    <sql id=\"tbPanelColumns\">\n        a.id,\n        a.name,\n        a.type,\n        a.sort_order,\n        a.position,\n        a.limit_num,\n        a.status,\n        a.created,\n        a.updated\n    </sql>\n\n    <!-- 根据条件查询所有板块 -->\n    <select id=\"getPanelList\" parameterType=\"map\" resultType=\"tbPanel\">\n        SELECT\n        <include refid=\"tbPanelColumns\" />\n        FROM\n        tb_panel AS a\n        <where>\n            <if test=\"type == -1\">\n                AND a.type != 0\n            </if>\n            <if test=\"type == 0\">\n                AND a.type = #{type}\n            </if>\n            AND a.position = #{position}\n        </where>\n        ORDER BY a.sort_order\n    </select>\n\n    <!-- 根据板块的类型查询板块 -->\n    <select id=\"getPanelByType\" resultType=\"tbPanel\">\n        SELECT\n        <include refid=\"tbPanelColumns\" />\n        FROM\n        tb_panel AS a\n        WHERE a.type = #{type}\n    </select>\n</mapper>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mapper/TbUserMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.admin.mapper.TbUserMapper\">\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\">\n    delete from tb_user\n    where id = #{id,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbUser\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.Long\">\n      SELECT LAST_INSERT_ID()\n  </selectKey>\n    insert into tb_user (username, password, created, updated)\n    values (#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},\n     #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP}\n      )\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbUser\">\n    update tb_user\n    set username = #{username,jdbcType=VARCHAR},\n      password = #{password,jdbcType=VARCHAR},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=BIGINT}\n  </update>\n  <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Long\" resultType=\"tbUser\">\n    select id, username, password, created, updated\n    from tb_user\n    where id = #{id,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultType=\"tbUser\">\n    select id, username, password, created, updated\n    from tb_user\n  </select>\n\n    <!-- sql 片断封装 -->\n    <sql id=\"tbUserColumns\">\n        a.id,\n        a.username,\n        a.password,\n        a.created,\n        a.updated\n    </sql>\n\n    <!-- 根据用户名获取用户 -->\n    <select id=\"getUserByUsername\" resultType=\"TbUser\">\n        select <include refid=\"tbUserColumns\" />\n        from tb_user as a\n        where username = #{username}\n    </select>\n\n    <!-- 获取用户列表 -->\n    <select id=\"getUserList\" resultType=\"tbUser\">\n        select <include refid=\"tbUserColumns\"/>\n        from tb_user as a\n        <where>\n            <if test=\"search != null and search != ''\">\n                AND username like concat(concat('%', #{search} ), '%')\n                OR id like concat(concat('%', #{search} ), '%')\n            </if>\n        </where>\n    </select>\n\n    <!-- 获取用户总数 -->\n    <select id=\"getUserListCount\" resultType=\"int\">\n        select count(*)\n        from tb_user\n        <where>\n            <if test=\"search != null and search != ''\">\n                AND username like concat(concat('%', #{search} ), '%')\n                OR id like concat(concat('%', #{search} ), '%')\n            </if>\n        </where>\n    </select>\n\n</mapper>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/mybatis-config.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE configuration PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n<configuration>\n    <!-- 全局参数 -->\n    <settings>\n        <!-- 打印 SQL 语句 -->\n        <setting name=\"logImpl\" value=\"STDOUT_LOGGING\" />\n\n        <!-- 使全局的映射器启用或禁用缓存。 -->\n        <setting name=\"cacheEnabled\" value=\"false\"/>\n\n        <!-- 全局启用或禁用延迟加载。当禁用时，所有关联对象都会即时加载。 -->\n        <setting name=\"lazyLoadingEnabled\" value=\"true\"/>\n\n        <!-- 当启用时，有延迟加载属性的对象在被调用时将会完全加载任意属性。否则，每种属性将会按需要加载。 -->\n        <setting name=\"aggressiveLazyLoading\" value=\"true\"/>\n\n        <!-- 是否允许单条 SQL 返回多个数据集 (取决于驱动的兼容性) default:true -->\n        <setting name=\"multipleResultSetsEnabled\" value=\"true\"/>\n\n        <!-- 是否可以使用列的别名 (取决于驱动的兼容性) default:true -->\n        <setting name=\"useColumnLabel\" value=\"true\"/>\n\n        <!-- 允许 JDBC 生成主键。需要驱动器支持。如果设为了 true，这个设置将强制使用被生成的主键，有一些驱动器不兼容不过仍然可以执行。 default:false  -->\n        <setting name=\"useGeneratedKeys\" value=\"false\"/>\n\n        <!-- 指定 MyBatis 如何自动映射 数据基表的列 NONE：不映射 PARTIAL：部分 FULL:全部  -->\n        <setting name=\"autoMappingBehavior\" value=\"PARTIAL\"/>\n\n        <!-- 这是默认的执行类型 （SIMPLE: 简单； REUSE: 执行器可能重复使用prepared statements语句；BATCH: 执行器可以重复执行语句和批量更新） -->\n        <setting name=\"defaultExecutorType\" value=\"SIMPLE\"/>\n\n        <!-- 使用驼峰命名法转换字段。 -->\n        <setting name=\"mapUnderscoreToCamelCase\" value=\"true\"/>\n\n        <!-- 设置本地缓存范围 session:就会有数据的共享 statement:语句范围 (这样就不会有数据的共享 ) defalut:session -->\n        <setting name=\"localCacheScope\" value=\"SESSION\"/>\n\n        <!-- 设置 JDBC 类型为空时,某些驱动程序 要指定值, default:OTHER，插入空值时不需要指定类型 -->\n        <setting name=\"jdbcTypeForNull\" value=\"NULL\"/>\n    </settings>\n\n    <plugins>\n        <plugin interceptor=\"com.github.pagehelper.PageHelper\">\n            <!--<property name=\"dialect\" value=\"mysql\"/>-->\n            <property name=\"offsetAsPageNum\" value=\"false\"/>\n            <property name=\"rowBoundsWithCount\" value=\"false\"/>\n            <property name=\"pageSizeZero\" value=\"true\"/>\n            <property name=\"reasonable\" value=\"true\"/>\n            <property name=\"supportMethodsArguments\" value=\"false\"/>\n            <property name=\"returnPageInfo\" value=\"none\"/>\n        </plugin>\n    </plugins>\n</configuration>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/resource.properties",
    "content": "# Ʒ黺ǰ׺\nPRODUCT_ITEM=PRODUCT_ITEM\n\n# ໺ key\nHEADER_CATE=HEADER_CATE\n"
  },
  {
    "path": "ymall-web-admin/src/main/resources/spring-context-druid.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:context=\"http://www.springframework.org/schema/context\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\">\n\n    <!-- 加载配置属性文件 -->\n    <context:property-placeholder ignore-unresolvable=\"true\" location=\"classpath:*.properties\"/>\n\n    <!-- 数据源配置, 使用 Druid 数据库连接池 -->\n    <bean id=\"dataSource\" class=\"com.alibaba.druid.pool.DruidDataSource\" init-method=\"init\" destroy-method=\"close\">\n        <!-- 数据源驱动类可不写，Druid默认会自动根据URL识别DriverClass -->\n        <property name=\"driverClassName\" value=\"${jdbc.driverClass}\"/>\n\n        <!-- 基本属性 url、user、password -->\n        <property name=\"url\" value=\"${jdbc.connectionURL}\"/>\n        <property name=\"username\" value=\"${jdbc.username}\"/>\n        <property name=\"password\" value=\"${jdbc.password}\"/>\n\n        <!-- 配置初始化大小、最小、最大 -->\n        <property name=\"initialSize\" value=\"${jdbc.pool.init}\"/>\n        <property name=\"minIdle\" value=\"${jdbc.pool.minIdle}\"/>\n        <property name=\"maxActive\" value=\"${jdbc.pool.maxActive}\"/>\n\n        <!-- 配置获取连接等待超时的时间 -->\n        <property name=\"maxWait\" value=\"60000\"/>\n\n        <!-- 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒 -->\n        <property name=\"timeBetweenEvictionRunsMillis\" value=\"60000\"/>\n\n        <!-- 配置一个连接在池中最小生存的时间，单位是毫秒 -->\n        <property name=\"minEvictableIdleTimeMillis\" value=\"300000\"/>\n\n        <property name=\"validationQuery\" value=\"${jdbc.testSql}\"/>\n        <property name=\"testWhileIdle\" value=\"true\"/>\n        <property name=\"testOnBorrow\" value=\"false\"/>\n        <property name=\"testOnReturn\" value=\"false\"/>\n\n        <!-- 配置监控统计拦截的filters -->\n        <property name=\"filters\" value=\"stat\"/>\n    </bean>\n</beans>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/spring-context-elasticsearch.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:elasticsearch=\"http://www.springframework.org/schema/data/elasticsearch\"\n       xsi:schemaLocation=\"\n        http://www.springframework.org/schema/beans\n        http://www.springframework.org/schema/beans/spring-beans.xsd\n        http://www.springframework.org/schema/data/elasticsearch\n        http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd\n        \">\n\n    <!-- client 客户端配置 -->\n    <elasticsearch:transport-client id=\"client\"  cluster-nodes=\"192.168.106.155:9300\" cluster-name=\"elasticsearch\"/>\n\n    <!-- 扫描Dao包，自动创建实例 -->\n    <elasticsearch:repositories base-package=\"com.yuu.ymall.web.admin.repositories\"/>\n\n    <!-- ElasticSearch模版对象 -->\n    <bean id=\"elasticsearchTemplate\" class=\"org.springframework.data.elasticsearch.core.ElasticsearchTemplate\">\n        <constructor-arg name=\"client\" ref=\"client\"></constructor-arg>\n    </bean>\n\n</beans>\n"
  },
  {
    "path": "ymall-web-admin/src/main/resources/spring-context-mybatis.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\">\n\n    <!-- 配置 SqlSession -->\n    <bean id=\"sqlSessionFactory\" class=\"org.mybatis.spring.SqlSessionFactoryBean\">\n        <property name=\"dataSource\" ref=\"dataSource\"/>\n        <!-- 用于配置对应实体类所在的包，多个 package 之间可以用 ',' 号分割 -->\n        <property name=\"typeAliasesPackage\" value=\"com.yuu.ymall.domain\"/>\n        <!-- 用于配置对象关系映射配置文件所在目录 -->\n        <property name=\"mapperLocations\" value=\"classpath:/mapper/**/*.xml\"/>\n        <property name=\"configLocation\" value=\"classpath:/mybatis-config.xml\"/>\n    </bean>\n\n    <!-- 扫描 Mapper -->\n    <bean class=\"org.mybatis.spring.mapper.MapperScannerConfigurer\">\n        <property name=\"basePackage\" value=\"com.yuu.ymall.web.admin.mapper\" />\n    </bean>\n</beans>\n"
  },
  {
    "path": "ymall-web-admin/src/main/resources/spring-context-redis.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:context=\"http://www.springframework.org/schema/context\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\">\n\n    <!-- 加载配置文件 -->\n    <context:property-placeholder location=\"classpath:ymall.properties\"/>\n\n    <!-- redis 数据源 -->\n    <bean id=\"poolConfig\" class=\"redis.clients.jedis.JedisPoolConfig\">\n        <!-- 最大空闲数 -->\n        <property name=\"maxIdle\" value=\"${redis.maxIdle}\"/>\n        <!-- 最大空连接数 -->\n        <property name=\"maxTotal\" value=\"${redis.maxTotal}\"/>\n        <!-- 最大等待时间 -->\n        <property name=\"maxWaitMillis\" value=\"${redis.maxWaitMillis}\"/>\n        <!-- 连接超时时是否阻塞，false 时报异常，true 阻塞直到超时，默认 true -->\n        <property name=\"blockWhenExhausted\" value=\"${redis.blockWhenExhausted}\"/>\n        <!-- 返回连接时，检查连接是否成功 -->\n        <property name=\"testOnBorrow\" value=\"${redis.testOnBorrow}\"/>\n    </bean>\n\n    <!-- spring-redis 连接池管理工厂 -->\n    <bean id=\"jedisConnectionFactory\" class=\"org.springframework.data.redis.connection.jedis.JedisConnectionFactory\">\n        <!-- IP 地址 -->\n        <property name=\"hostName\" value=\"${redis.host}\"/>\n        <!-- 端口号 -->\n        <property name=\"port\" value=\"${redis.port}\"/>\n        <!-- 超时时间，默认 2000 -->\n        <property name=\"timeout\" value=\"${reids.timeout}\"/>\n        <!-- 连接池配置引用 -->\n        <property name=\"poolConfig\" ref=\"poolConfig\"/>\n        <!-- usePool: 是否使用连接池 -->\n        <property name=\"usePool\" value=\"true\"/>\n    </bean>\n\n    <!-- redis template definition -->\n    <bean id=\"redisTemplate\" class=\"org.springframework.data.redis.core.RedisTemplate\">\n        <property name=\"connectionFactory\" ref=\"jedisConnectionFactory\" />\n        <property name=\"keySerializer\">\n            <bean class=\"org.springframework.data.redis.serializer.StringRedisSerializer\" />\n        </property>\n        <property name=\"valueSerializer\">\n            <bean class=\"org.springframework.data.redis.serializer.JdkSerializationRedisSerializer\" />\n        </property>\n        <property name=\"hashKeySerializer\">\n            <bean class=\"org.springframework.data.redis.serializer.StringRedisSerializer\" />\n        </property>\n        <property name=\"hashValueSerializer\">\n            <bean class=\"org.springframework.data.redis.serializer.JdkSerializationRedisSerializer\" />\n        </property>\n        <!--开启事务  -->\n        <property name=\"enableTransactionSupport\" value=\"true\"></property>\n    </bean>\n</beans>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/spring-context-shiro.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd\">\n\n    <!-- 配置自定义Realm -->\n    <bean id=\"myRealm\" class=\"com.yuu.ymall.web.admin.commons.shiro.MyRealm\"/>\n\n    <!-- 安全管理器 -->\n    <bean id=\"securityManager\" class=\"org.apache.shiro.web.mgt.DefaultWebSecurityManager\">\n        <property name=\"realm\" ref=\"myRealm\"/>\n    </bean>\n\n    <!-- Shiro过滤器 核心-->\n    <bean id=\"shiroFilter\" class=\"org.apache.shiro.spring.web.ShiroFilterFactoryBean\">\n        <!-- Shiro的核心安全接口,这个属性是必须的 -->\n        <property name=\"securityManager\" ref=\"securityManager\"/>\n        <!-- 身份认证失败，则跳转到登录页面的配置 -->\n        <property name=\"loginUrl\" value=\"/login\"/>\n        <!-- 登录成功之后的 跳转页面 -->\n        <property name=\"successUrl\" value=\"/\"/>\n        <!-- 权限认证失败，则跳转到指定页面 -->\n        <property name=\"unauthorizedUrl\" value=\"/403\"/>\n        <!-- Shiro连接约束配置,即过滤链的定义 -->\n        <property name=\"filterChainDefinitions\">\n            <value>\n                /static/assets/** = anon\n                /user/geetestInit = anon\n                /user/login = anon\n                /** = authc\n            </value>\n        </property>\n    </bean>\n\n</beans>\n"
  },
  {
    "path": "ymall-web-admin/src/main/resources/spring-context.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:context=\"http://www.springframework.org/schema/context\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:tx=\"http://www.springframework.org/schema/tx\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd\n\thttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd\">\n\n\n\n    <context:annotation-config />\n    <context:component-scan base-package=\"com.yuu.ymall.web.admin,com.yuu.ymall.commons\">\n        <context:exclude-filter type=\"annotation\" expression=\"org.springframework.stereotype.Controller\" />\n    </context:component-scan>\n\n\n    <!-- 配置事务管理器 -->\n    <bean id=\"transactionManager\" class=\"org.springframework.jdbc.datasource.DataSourceTransactionManager\">\n        <property name=\"dataSource\" ref=\"dataSource\"/>\n    </bean>\n\n    <!-- 开启事务注解驱动 -->\n    <tx:annotation-driven transaction-manager=\"transactionManager\" />\n</beans>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/spring-mvc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:context=\"http://www.springframework.org/schema/context\"\n       xmlns:mvc=\"http://www.springframework.org/schema/mvc\" xmlns:aop=\"http://www.springframework.org/schema/aop\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\n        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd\">\n\n    <description>Spring MVC Configuration</description>\n\n    <!-- 启动对@AspectJ注解的支持 -->\n    <aop:aspectj-autoproxy/>\n\n    <!-- 加载配置属性文件 -->\n    <context:property-placeholder ignore-unresolvable=\"true\" location=\"classpath:ymall.properties\"/>\n\n    <!-- 使用 Annotation 自动注册 Bean,只扫描 @Controller -->\n    <context:component-scan base-package=\"com.yuu.ymall.web.admin\" use-default-filters=\"false\">\n        <context:include-filter type=\"annotation\" expression=\"org.springframework.stereotype.Controller\"/>\n    </context:component-scan>\n\n    <!-- 默认的注解映射的支持 -->\n    <mvc:annotation-driven />\n\n    <!-- 定义视图文件解析 -->\n    <bean class=\"org.springframework.web.servlet.view.InternalResourceViewResolver\">\n        <property name=\"prefix\" value=\"${web.view.prefix}\"/>\n        <property name=\"suffix\" value=\"${web.view.suffix}\"/>\n    </bean>\n\n    <!-- 静态资源映射 -->\n    <mvc:resources mapping=\"/static/**\" location=\"/static/\" cache-period=\"31536000\"/>\n\n    <!-- Swagger 配置 -->\n    <mvc:resources mapping=\"/swagger-ui.html\" location=\"classpath:/META-INF/resources/*\" />\n    <mvc:resources mapping=\"/webjars/**\" location=\"classpath:/META-INF/resources/webjars/\" />\n    <!--<mvc:resources mapping=\"/swagger-resources/configuration/ui\" location=\"classpath:/META-INF/resources/swagger-resources/configuration/ui/\"/>-->\n    <!--<mvc:resources mapping=\"/api/swagger/**\" location=\"classpath:/META-INF/resources/\"/>-->\n\n    <!-- 拦截器配置 -->\n    <mvc:interceptors>\n        <mvc:interceptor>\n            <mvc:mapping path=\"/**\"/>\n            <bean class=\"com.yuu.ymall.web.admin.web.interceptor.PermissionInterceptor\" />\n        </mvc:interceptor>\n    </mvc:interceptors>\n\n    <!-- 上传文件拦截，设置最大上传文件大小 10M = 10*1024*1024(B) = 10485760 bytes -->\n    <bean id=\"multipartResolver\" class=\"org.springframework.web.multipart.commons.CommonsMultipartResolver\">\n        <property name=\"maxUploadSize\" value=\"${web.maxUploadSize}\"/>\n    </bean>\n</beans>"
  },
  {
    "path": "ymall-web-admin/src/main/resources/ymall.properties",
    "content": "#============================#\n#==== Database settings ====#\n#============================#\n\n# JDBC\njdbc.driverClass=com.mysql.jdbc.Driver\njdbc.connectionURL=jdbc:mysql:///ymall?useUnicode=true&characterEncoding=utf-8&useSSL=false\njdbc.username=root\njdbc.password=123456\n\n# JDBC Pool\njdbc.pool.init=1\njdbc.pool.minIdle=3\njdbc.pool.maxActive=20\n\n# JDBC Test\njdbc.testSql=SELECT 'x' FROM DUAL\n\n#============================#\n#==== Redis settings ====#\n#============================#\nredis.host=192.168.106.154\nredis.port=6379\nredis.password=\"\nredis.maxIdle=400\nredis.maxTotal=6000\nredis.maxWaitMillis=1000\nredis.blockWhenExhausted=true\nredis.testOnBorrow=true\nreids.timeout=10000\n\n\n\n#============================#\n#==== Framework settings ====#\n#============================#\n\n# \\u89c6\\u56fe\\u6587\\u4ef6\\u5b58\\u653e\\u8def\\u5f84\nweb.view.prefix=/WEB-INF/views/\nweb.view.suffix=.jsp\n\nweb.maxUploadSize=52428800\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/includes/footer.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n\n<!-- Base -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery/1.9.1/jquery.min.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/layer/2.4/layer.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/static/h-ui/js/H-ui.min.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/static/h-ui.admin/js/H-ui.admin.js\"></script>\n\n<!-- DataTables -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/datatables/1.10.0/jquery.dataTables.min.js\"></script>\n\n<!-- jQuery Validation -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/jquery.validate.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/validate-methods.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/messages_zh.js\"></script>\n\n<!-- iCheck 1.0.1 -->\n<script src=\"/static/assets/plugins/iCheck/icheck.min.js\"></script>\n\n<!-- App -->\n<script type=\"text/javascript\" src=\"/static/assets/app/const.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/app/common.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/app/app.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/app/validate.js\"></script>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/includes/header.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n\n<meta charset=\"utf-8\">\n<meta name=\"renderer\" content=\"webkit|ie-comp|ie-stand\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no\" />\n<meta http-equiv=\"Cache-Control\" content=\"no-siteapp\" />\n<link rel=\"Shortcut Icon\" href=\"/static/assets/icon/logo.png\" />\n<!--[if lt IE 9]>\n<script type=\"text/javascript\" src=\"/static/assets/lib/html5shiv.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/respond.min.js\"></script>\n<![endif]-->\n<link rel=\"stylesheet\" type=\"text/css\" href=\"/static/assets/static/h-ui/css/H-ui.min.css\" />\n<link rel=\"stylesheet\" type=\"text/css\" href=\"/static/assets/static/h-ui.admin/css/H-ui.admin.css\" />\n<link rel=\"stylesheet\" type=\"text/css\" href=\"/static/assets/lib/Hui-iconfont/1.0.8/iconfont.css\" />\n<link rel=\"stylesheet\" type=\"text/css\" href=\"/static/assets/static/h-ui.admin/skin/default/skin.css\" id=\"skin\" />\n<link rel=\"stylesheet\" type=\"text/css\" href=\"/static/assets/static/h-ui.admin/css/style.css\" />\n<!--[if IE 6]>\n<script type=\"text/javascript\" src=\"/static/assets/lib/DD_belatedPNG_0.0.8a-min.js\" ></script>\n<script>DD_belatedPNG.fix('*');</script>\n<![endif]-->\n\n<!-- iCheck -->\n<link rel=\"stylesheet\" href=\"/static/assets/plugins/iCheck/all.css\">\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/admin-form.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>编辑管理员</title>\n</head>\n<body>\n<article class=\"page-container\">\n    <form class=\"form form-horizontal\" id=\"form-admin-add\">\n        <input type=\"text\" hidden value=\"\" placeholder=\"\" id=\"id\" name=\"id\">\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>管理员：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"\" id=\"username\" name=\"username\">\n            </div>\n        </div>\n        <div class=\"password row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>初始密码：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"password\" class=\"input-text\" autocomplete=\"off\" value=\"\" placeholder=\"密码\" id=\"password\" name=\"password\">\n            </div>\n        </div>\n        <div class=\"password row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>确认密码：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"password\" class=\"input-text\" autocomplete=\"off\"  placeholder=\"确认新密码\" id=\"password2\" name=\"password2\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <div class=\"col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-3\">\n                <input id=\"saveButton\" class=\"btn btn-primary radius\" type=\"submit\" value=\"&nbsp;&nbsp;提交&nbsp;&nbsp;\">\n            </div>\n        </div>\n    </form>\n</article>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<script type=\"text/javascript\">\n\n    var id = parent.userId;\n    if (id != \"\") {\n        $(\".password\").hide();\n    }\n\n    $(\"#id\").val(parent.userId);\n    $(\"#username\").val(parent.username);\n\n    /**\n     * 美化单选\n     */\n    function radioCheck() {\n        $('.skin-minimal input').iCheck({\n            checkboxClass: 'icheckbox-blue',\n            radioClass: 'iradio-blue',\n            increaseArea: '20%'\n        });\n    }\n\n    $(function () {\n        radioCheck();\n\n        $(\"#form-admin-add\").validate({\n            rules: {\n                username: {\n                    required: true,\n                    minlength: 1,\n                    maxlength: 16,\n                    remote: \"/user/username/\" + parent.userId\n                },\n                password: {\n                    required: true,\n                    minlength: 6\n                },\n                password2: {\n                    required: true,\n                    minlength: 6,\n                    equalTo: \"#password\"\n                }\n            },\n            messages: {\n                username: {\n                    required: \"请填写用户名\",\n                    remote: \"该用户名已被注册\"\n                },\n                password: {\n                    required: \"请填写密码\",\n                },\n                password2: {\n                    required: \"请确认密码\",\n                    equalTo: \"两次密码输入不一致\"\n                }\n            },\n            onkeyup: false,\n            focusCleanup: false,\n            success: \"valid\",\n            submitHandler: function (form) {\n                var index = layer.load(3);\n                if ($(\"#select\").val() == 2) {\n                    $(\"#description\").val(\"游客\");\n                } else {\n                    $(\"#description\").val(\"超级管理员\");\n                }\n                $(form).ajaxSubmit({\n                    url: \"/user/save\",\n                    type: \"POST\",\n                    success: function (data) {\n                        layer.close(index);\n                        if (data.status == 200) {\n                            parent.refresh();\n                            parent.App.msgSuccess(data.message);\n                            var index = parent.layer.getFrameIndex(window.name);\n                            parent.layer.close(index);\n                        } else {\n                            layer.alert(data.message, {title: '错误信息', icon: 2});\n                        }\n                    },\n                    error: function (XMLHttpRequest) {\n                        layer.close(index);\n                        layer.alert('数据处理失败! 错误码:' + XMLHttpRequest.status, {\n                            title: '错误信息',\n                            icon: 2\n                        });\n                    }\n                });\n            }\n        });\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/admin-list.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>管理员列表</title>\n</head>\n<style>\n    .table>tbody>tr>td{\n        text-align:center;\n    }\n</style>\n<body>\n\n<div>\n    <nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 管理员管理 <span class=\"c-gray en\">&gt;</span> 管理员列表 <a class=\"btn btn-success radius r\" style=\"line-height:1.6em;margin-top:3px\" href=\"javascript:location.replace(location.href);\" title=\"刷新\" ><i class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n    <form class=\"page-container\">\n        <div class=\"cl pd-5 bg-1 bk-gray mt-20\"> <span class=\"l\"><a href=\"javascript:;\" onclick=\"datadel()\" class=\"btn btn-danger radius\"><i class=\"Hui-iconfont\">&#xe6e2;</i> 批量删除</a> <a class=\"btn btn-primary radius\" onclick=\"admin_add('添加管理员','admin-form',400,300)\" href=\"javascript:;\"><i class=\"Hui-iconfont\">&#xe600;</i> 添加管理员</a></span></div>\n        <div class=\"mt-20\">\n            <div class=\"mt-20\" style=\"margin-bottom: 70px\">\n                <table id=\"dataTable\" class=\"table table-border table-bordered table-bg table-hover table-sort\" width=\"100%\">\n                    <thead>\n                    <tr class=\"text-c\">\n                        <th width=\"25\"><input type=\"checkbox\" class=\"minimal icheck_master\"/></th>\n                        <th width=\"40\">ID</th>\n                        <th width=\"150\">登录名</th>\n                        <th width=\"130\">创建时间</th>\n                        <th width=\"100\">操作</th>\n                    </tr>\n                    </thead>\n                </table>\n            </div>\n        </div>\n    </form>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n<script type=\"text/javascript\">\n\n    /**\n     * 初始化 DataTables\n     */\n    var _dataTables;\n    $(function () {\n        const _columns = [\n            { \"data\": null,\n                render : function(data,type, row, meta) {\n                    return '<input id=\"' + row.id + '\" type=\"checkbox\" class=\"minimal\" />';\n                }\n            },\n            { \"data\": \"id\"},\n            { \"data\": \"username\"},\n            { \"data\": \"created\",\n                render : function(data,type, row, meta) {\n                    return date(data);\n                }\n            },\n            {\n                \"data\": null,\n                render : function(data,type, row, meta) {\n                    if(row.state==1){\n                        return \"<a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"change_password('修改密码','change-admin-password',\"+row.id+\",'600','270')\\\" href=\\\"javascript:;\\\" title=\\\"修改密码\\\"><i class=\\\"Hui-iconfont\\\">&#xe63f;</i></a> <a title=\\\"删除\\\" href=\\\"javascript:;\\\" onclick=\\\"admin_del(this,\"+row.id+\")\\\" class=\\\"ml-5\\\" style=\\\"text-decoration:none\\\"><i class=\\\"Hui-iconfont\\\">&#xe6e2;</i></a>\";\n                    } else{\n                        return \"<a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"change_password('修改密码','change-admin-password',\"+row.id+\",'600','270')\\\" href=\\\"javascript:;\\\" title=\\\"修改密码\\\"><i class=\\\"Hui-iconfont\\\">&#xe63f;</i></a> <a title=\\\"删除\\\" href=\\\"javascript:;\\\" onclick=\\\"admin_del(this,\"+row.id+\")\\\" class=\\\"ml-5\\\" style=\\\"text-decoration:none\\\"><i class=\\\"Hui-iconfont\\\">&#xe6e2;</i></a>\";\n                    }\n                }\n            }\n        ];\n\n        _dataTables = App.initDataTables(\"/user/list/\", _columns);\n    });\n\n    // 初始化数据\n    var username=\"\",userId=\"\",phone=\"\",email=\"\",roleNames=\"\",sex=\"\",description=\"\";\n\n    /**\n     * 管理员增加\n     **/\n    function admin_add(title,url,w,h){\n        username=\"\",userId=0,phone=\"\",email=\"\",roleNames=\"\",sex=\"\",description=\"\"\n        layer_show(title,url,w,h);\n    }\n\n    /**\n     * 管理员编辑\n     **/\n    function admin_edit(title,url,id,w,h){\n        userId=id;\n        var table = $('.table').DataTable();\n        $('.table tbody').on( 'click', 'tr', function () {\n            username = table.row(this).data().username;\n            phone = table.row(this).data().phone;\n            email = table.row(this).data().email;\n            roleNames = table.row(this).data().description;\n            sex = table.row(this).data().sex;\n            description = table.row(this).data().description;\n        });\n        layer_show(title,url,w,h);\n    }\n\n    /**\n     * 删除用户\n     **/\n    function admin_del(obj,id){\n        // 确认消息\n        var confirmMsg = '确定删除ID为 '+ id +' 的用户吗？';\n\n        // 提交请求路径\n        var url = '/user/delete/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 2, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 批量删除\n     */\n    function datadel() {\n        // 请求路径\n        var url = \"/user/delete/\";\n\n        // 请求成功执行方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon:1, time:1000});\n        }\n\n        App.deleteMulti(url, successMethod);\n    }\n\n\n    /**\n     * 密码修改\n     */\n    function change_password(title,url,id,w,h){\n        userId=id;\n        var table = $('.table').DataTable();\n        $('.table tbody').on( 'click', 'tr', function () {\n            username = table.row(this).data().username;\n        });\n        layer_show(title,url,w,h);\n    }\n\n</script>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/change-admin-password.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!--_meta 作为公共模版分离出去-->\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>修改密码</title>\n</head>\n<body>\n<article class=\"page-container\">\n    <form action=\"\" method=\"\" class=\"form form-horizontal\" id=\"form-change-password\">\n        <input type=\"text\" class=\"input-text\" hidden name=\"id\" id=\"id\">\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>账号：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\"><span id=\"username\"></span></div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>新密码：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"password\" class=\"input-text\" autocomplete=\"off\" placeholder=\"密码长度不得小于6位\" name=\"password\"\n                       id=\"password\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>确认密码：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"password\" class=\"input-text\" autocomplete=\"off\" placeholder=\"请再次输入密码\" name=\"password2\"\n                       id=\"password2\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <div class=\"col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-3\">\n                <input class=\"btn btn-primary radius\" type=\"submit\" value=\"&nbsp;&nbsp;保存&nbsp;&nbsp;\">\n            </div>\n        </div>\n    </form>\n</article>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n<script type=\"text/javascript\">\n\n    $(\"#id\").val(parent.userId);\n    $(\"#username\").html(parent.username);\n    $(function () {\n        $(\"#form-change-password\").validate({\n            rules: {\n                password: {\n                    required: true,\n                    minlength: 6,\n                    maxlength: 16\n                },\n                password2: {\n                    required: true,\n                    minlength: 6,\n                    maxlength: 16,\n                    equalTo: \"#password\"\n                },\n            },\n            onkeyup: false,\n            focusCleanup: false,\n            success: \"valid\",\n            submitHandler: function (form) {\n                var index = layer.load(3);\n                $(form).ajaxSubmit({\n                    url: \"/user/changePass\",\n                    type: \"POST\",\n                    success: function (data) {\n                        layer.close(index);\n                        if (data.status == 200) {\n                            parent.App.msgSuccess(data.message);\n                            var index = parent.layer.getFrameIndex(window.name);\n                            parent.layer.close(index);\n                        } else {\n                            layer.alert('提交失败! ' + data.message, {title: '错误信息', icon: 2});\n                        }\n                    },\n                    error: function (XMLHttpRequest) {\n                        layer.close(index);\n                        layer.alert('数据处理失败! 错误码:' + XMLHttpRequest.status, {title: '错误信息', icon: 2});\n                    }\n                });\n            }\n        });\n    });\n</script>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/change-password.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!--_meta 作为公共模版分离出去-->\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>修改密码 - 会员管理</title>\n</head>\n<body>\n<article class=\"page-container\">\n    <form action=\"\" method=\"\" class=\"form form-horizontal\" id=\"validate-form\">\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>账号：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\"> <span id=\"username\"></span> </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>新密码：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"password\" class=\"input-text\" autocomplete=\"off\" placeholder=\"密码长度不得小于6位\" name=\"password\" id=\"password\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>确认密码：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"password\" class=\"input-text\" autocomplete=\"off\" placeholder=\"请再次输入密码\" name=\"password2\" id=\"password2\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <div class=\"col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-3\">\n                <input class=\"btn btn-primary radius\" type=\"submit\" value=\"&nbsp;&nbsp;保存&nbsp;&nbsp;\">\n            </div>\n        </div>\n    </form>\n</article>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<script type=\"text/javascript\">\n\n    // 接收父页面传的 id\n    var id = parent.Id;\n    $(\"#username\").html(parent.username);\n\n    /**\n     * 修改密码\n     * @param data\n     */\n    function successMethod(data) {\n        parent.App.msgSuccess(data.message);\n        var index = parent.layer.getFrameIndex(window.name);\n        parent.layer.close(index);\n    }\n    Validate.validate(\"/member/changePass/\" + id, \"\", successMethod);\n\n</script>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/chart-order.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>订单销量统计</title>\n</head>\n<body>\n<nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 统计管理 <span\n        class=\"c-gray en\">&gt;</span> 订单销量统计 <a class=\"btn btn-success radius r\"\n                                                style=\"line-height:1.6em;margin-top:3px\"\n                                                href=\"javascript:location.replace(location.href);\" title=\"刷新\"><i\n        class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n<div class=\"page-container\">\n    <div class=\"cl pd-5 bg-1 bk-gray mt-20\">\n\t\t<span class=\"l\">\n\t\t\t<a href=\"javascript:;\" onclick=\"getChartData(0)\" class=\"btn btn-secondary-outline radius\">本周</a>\n\t\t\t<a href=\"javascript:;\" onclick=\"getChartData(1)\" class=\"btn btn-secondary-outline radius\">本月</a>\n\t\t\t<a href=\"javascript:;\" onclick=\"getChartData(2)\" class=\"btn btn-secondary-outline radius\">上个月</a>\n\t\t\t<select class=\"select-box\" style=\"width: 100px\" id=\"year\" onchange=\"getYearData()\">\n\n\t\t\t</select>\n\t\t\t&nbsp;&nbsp;指定日期范围：\n            <input type=\"text\" onfocus=\"WdatePicker({ maxDate:'#F{$dp.$D(\\'startDate\\')||\\'%y-%M-%d\\'}' })\"\n                   id=\"startDate\" name=\"startDate\" class=\"input-text Wdate\" style=\"width:120px;\">\n            -\n            <input type=\"text\" onfocus=\"WdatePicker({ minDate:'#F{$dp.$D(\\'endDate\\')}',maxDate:'%y-%M-%d' })\"\n                   id=\"endDate\" name=\"endDate\" class=\"input-text Wdate\" style=\"width:120px;\">\n\t\t\t&nbsp;&nbsp;<a href=\"javascript:;\" onclick=\"getCustomData()\" class=\"btn btn-success\">确定</a>\n\t\t</span>\n        <span class=\"r\">总销售额：<strong id=\"countAll\">0.00</strong> ￥</span>\n    </div>\n    <div id=\"container\" style=\"min-width:700px;height:450px;margin-top: 10px;\"></div>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n\n<!-- WdatePicker -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/My97DatePicker/4.8/WdatePicker.js\"></script>\n\n<!-- echarts -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/echarts.common.min.js\"></script>\n<script type=\"text/javascript\">\n\n    /**\n     * 初始化年份信息\n     */\n    $(document).ready(function () {\n        $(\"#year\").append(\"<option selected value='-1'>按年统计</option>\");\n        var startYear = 2019, nowYear = new Date().getFullYear();\n        for (var i = 0; i <= nowYear - startYear + 1; i++) {\n            $(\"#year\").append(\"<option value='\" + startYear + \"'>\" + startYear + \"年</option>\");\n            startYear += 1;\n        }\n    });\n\n    // 基于准备好的dom，初始化echarts实例\n    var myChart = echarts.init(document.getElementById('container'), 'light');\n    var xDatas = [], yDatas = [], startDate, endDate, year = 0;\n    getChartData(0, null, null);\n\n\n    /**\n     * 获取图表数据\n     * @param type\n     */\n    function getChartData(type) {\n        var index = layer.load(3);\n        $.ajax({\n            type: 'GET',\n            url: '/count/order',\n            dataType: 'json',\n            data: {\n                type: type,\n                startTime: startDate,\n                endTime: endDate,\n                year: year\n            },\n            success: function (data) {\n                layer.close(index);\n                if (data.status == 500) {\n                    layer.alert(data.message, {title: '错误信息', icon: 2});\n                    return;\n                }\n                console.log(data)\n                xDatas = data.result.xDatas;\n                yDatas = data.result.yDatas;\n                $(\"#countAll\").html(data.result.countAll);\n                drawChart();\n            },\n            error: function (XMLHttpRequest) {\n                layer.close(index);\n                layer.alert('数据处理失败! 错误码:' + XMLHttpRequest.status, {title: '错误信息', icon: 2});\n            }\n        });\n    }\n\n    function getCustomData() {\n        startDate = $('#startDate').val();\n        if (startDate == \"\" || startDate == null) {\n            $('#startDate').focus();\n            return;\n        }\n        endDate = $('#endDate').val();\n        if (endDate == \"\" || endDate == null) {\n            $('#endDate').focus();\n            return;\n        }\n        getChartData(-1);\n    }\n\n    function getYearData() {\n        console.log(1)\n        year = $('#year').val();\n        if (year == \"\" || year == \"-1\" || year == null) {\n            return;\n        }\n        getChartData(-2);\n    }\n\n    function drawChart() {\n        // 指定图表的配置项和数据\n        var option = {\n            title: {\n                text: '订单销量统计',\n                subtext: 'YMall'\n            },\n            tooltip: {\n                trigger: 'axis'\n            },\n            legend: {\n                data: ['销售金额']\n            },\n            toolbox: {\n                show: true,\n                feature: {\n                    dataZoom: {\n                        yAxisIndex: 'none'\n                    },\n                    dataView: {readOnly: false},\n                    magicType: {type: ['line', 'bar']},\n                    restore: {},\n                    saveAsImage: {}\n                }\n            },\n            xAxis: {\n                boundaryGap: false,\n                data: xDatas\n            },\n            yAxis: {\n                type: 'value',\n                axisLabel: {\n                    formatter: '{value} ￥'\n                }\n            },\n            series: [{\n                name: '销售金额',\n                type: 'line',\n                data: yDatas\n            }]\n        };\n\n        // 使用刚指定的配置项和数据显示图表。\n        myChart.setOption(option);\n    }\n</script>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/choose-category.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <!-- ZTree -->\n    <link rel=\"stylesheet\" href=\"/static/assets/lib/zTree/v3/css/zTreeStyle/zTreeStyle.css\" type=\"text/css\">\n    <title>产品分类</title>\n</head>\n<body>\n<table class=\"table\">\n    <tr>\n        <td width=\"200\" class=\"va-t\"><ul id=\"myTree\" class=\"ztree\"></ul></td>\n    </tr>\n</table>\n\n<jsp:include page=\"../includes/footer.jsp\"></jsp:include>\n\n<!-- ZTree -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/zTree/v3/js/jquery.ztree.all-3.5.js\"></script>\n<script type=\"text/javascript\">\n\n    /**\n     * ZTree 回调函数\n     * */\n    var callback = {\n        beforeClick: function(treeId, treeNode) {\n            if (treeNode.isParent) {\n                return false;\n            } else {\n                var cid = treeNode.id;\n                var cname = treeNode.name;\n                if (cid == -1) {\n                    layer.confirm('该类别不能选择！', {\n                       btn: ['知道了'],\n                       icon: 2\n                    });\n                    return true;\n                }\n                parent.setCid(cid);\n                parent.setCname(cname);\n                var index = parent.layer.getFrameIndex(window.name);\n                parent.layer.close(index);\n                return true;\n            }\n        }\n    };\n    App.initZtree(\"/item/cat/list/-1\" , callback);\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/choose-parent-category.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <!-- ZTree -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"/static/assets/lib/zTree/v3/css/zTreeStyle/zTreeStyle.css\" type=\"text/css\"/>\n    <title>产品分类</title>\n</head>\n<body>\n<table class=\"table\">\n    <tr>\n        <td width=\"200\" class=\"va-t\"><ul id=\"myTree\" class=\"ztree\"></ul></td>\n    </tr>\n</table>\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!--请在下方写此页面业务相关的脚本-->\n<script type=\"text/javascript\" src=\"/static/assets/lib/zTree/v3/js/jquery.ztree.all-3.5.js\"></script>\n\n<script type=\"text/javascript\">\n\n    var oldCid = parent.id;\n\n\n    /**\n     * ZTree 回调函数\n     * */\n    var callback = {\n        beforeClick: function(treeId, treeNode) {\n            if(treeNode.id == oldCid) {\n                layer.confirm('不能选择自己', {\n                    btn: ['知道了'], icon: 2\n                });\n                return false;\n            }\n            if (treeNode.isParent) {\n                parent.setParentId(treeNode.id, treeNode.name);\n                var index = parent.layer.getFrameIndex(window.name);\n                parent.layer.close(index);\n                return false;\n            } else {\n                layer.confirm('请选择一父节点！', {\n                    btn: ['知道了'], icon: 2\n                });\n            }\n        }\n    };\n    App.initZtree(\"/item/cat/list/0\" , callback);\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/choose-product.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>选择商品</title>\n</head>\n<style>\n    .table>tbody>tr>td{\n        text-align:center;\n    }\n</style>\n<body>\n<div style=\"padding:2vw\">\n    <table id=\"dataTable\" class=\"table table-border table-bordered table-bg table-hover table-sort\" width=\"100%\">\n        <thead>\n        <tr class=\"text-c\">\n            <th width=\"70\">ID</th>\n            <th width=\"70\">缩略图</th>\n            <th width=\"130\">商品名称</th>\n            <th width=\"90\">描述</th>\n            <th width=\"60\">单价</th>\n            <th width=\"95\">创建日期</th>\n            <th width=\"95\">更新日期</th>\n            <th width=\"50\">状态</th>\n            <th width=\"80\">操作</th>\n        </tr>\n        </thead>\n    </table>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- DataTables -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/datatables/1.10.0/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\">\n\n    /**\n     * 初始化 DataTables\n     */\n    var _dataTable;\n    $(function(){\n        const _columns = [\n            { \"data\": \"id\"},\n            {\n                \"data\": \"image\",\n                render: function (data, type, row, meta) {\n                    return '<img src=\"'+ data.split(',')[0] +'\" style=\"width:80px; height: 60px;\"/>';\n                }\n            },\n            {\n                \"data\": \"title\",\n                render: function (data, type, row, meta) {\n                    if (data.length > 20) {\n                        return '<span title='+ data +'>'+ data.substr(0, 50) +'...</span>'\n                    } else {\n                        return '<span title='+ data +'>'+ data +'</span>';\n                    }\n                    return data;\n                }\n            },\n            {\n                \"data\": \"sellPoint\",\n                render: function (data, type, row, meta) {\n                    if (type == 'display') {\n                        if (data.length > 20) {\n                            return '<span title=' + data + '>' + data.substr(0, 20) + '...</span>';\n                        } else {\n                            return '<span title=' + data + '>' + data + '</span>';\n                        }\n                    }\n                    return data;\n                }\n            },\n            {\"data\": \"price\"},\n            {\n                \"data\": \"created\",\n                render: function (data, type, row, meta) {\n                    return date(data);\n                }\n            },\n            {\n                \"data\": \"updated\",\n                render: function (data, type, row, meta) {\n                    return date(data);\n                }\n            },\n            {\n                \"data\": \"status\",\n                render : function(data,type, row, meta) {\n                    if(data==0){\n                        return \"<span class=\\\"label label-defant radius td-status\\\">已下架</span>\";\n                    }else if(data==1){\n                        return \"<span class=\\\"label label-success radius td-status\\\">已发布</span>\";\n                    }else{\n                        return \"<span class=\\\"label label-warning radius td-status\\\">其它态</span>\";\n                    }\n                }\n            },\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    return \"<input onclick='chooseProduct()' class='btn btn-danger-outline size-S radius' type='button' value='选择该商品'>\";\n                }\n            }\n        ];\n\n        _dataTable = App.initDataTables(\"/item/list/-1\", _columns);\n    });\n\n\n    /**\n     * 选择商品\n     * @param id\n     */\n    function chooseProduct(id) {\n        $(\"#dataTable tbody\").on('click', 'tr', function () {\n            var status = _dataTable.row(this).data().status;\n            if (status == 0) {\n                layer.alert(\"此商品已下架，暂时不能选择噢！\", {title: \"错误消息\", icon: 2});\n                return ;\n            }\n            var id = _dataTable.row(this).data().id;\n            var title = _dataTable.row(this).data().title;\n            parent.setIdAndTitle(id, title);\n            var index = parent.layer.getFrameIndex(window.name);\n            parent.layer.close(index);\n        })\n    }\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/content-common-form.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n\n    <!-- DropZone -->\n    <link rel=\"stylesheet\" href=\"/static/assets/plugins/dropzone/min/dropzone.min.css\" />\n    <link rel=\"stylesheet\" href=\"/static/assets/plugins/dropzone/min/basic.min.css\" />\n</head>\n\n<body>\n<div class=\"page-container\">\n    <form name=\"product-add\" action=\"\" method=\"post\" class=\"form form-horizontal\" id=\"validate-form\">\n        <input type=\"text\" hidden class=\"input-text\" id=\"id\" name=\"id\">\n        <input type=\"text\" hidden class=\"input-text\" id=\"panelId\" name=\"panelId\">\n        <input type=\"text\" hidden class=\"input-text\" id=\"position\" name=\"position\">\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\">所属板块：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <span id=\"name\" name=\"name\"></span>\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\">\n                <span class=\"c-red\">*</span>\n                类型：</label>\n            <div class=\"formControls col-xs-6 col-sm-3\">\n                <select id=\"type\" class=\"select-box\" name=\"type\">\n                    <option value=\"0\">关联商品</option>\n                    <option value=\"1\">其他链接</option>\n                </select>\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>排序优先值：</label>\n            <div class=\"formControls col-xs-8 col-sm-4\">\n                <input type=\"text\" class=\"input-text\" placeholder=\"请输入0~9999，值越小排序越前\" id=\"sortOrder\" name=\"sortOrder\">\n            </div>\n        </div>\n        <div class=\"row cl\" id=\"oUrl\" style=\"display:none\">\n            <label class=\"form-label col-xs-4 col-sm-2\">其他链接：</label>\n            <div class=\"formControls col-xs-8 col-sm-4\">\n                <input type=\"text\" class=\"input-text\" placeholder=\"http://\" id=\"fullUrl\" name=\"fullUrl\">\n            </div>\n        </div>\n        <div class=\"row cl product\">\n            <label class=\"form-label col-xs-4 col-sm-2\">选择展示商品：</label>\n            <div class=\"formControls col-xs-8 col-sm-6\">\n                <input type=\"text\" onclick='App.show(\"选择展示商品\",\"choose-product\",900,600)' readonly class=\"input-text\" placeholder=\"请点击选择按钮选择关联商品\" id=\"title\" name=\"title\" style=\"width: 65%\">\n                <input type=\"button\" onclick='App.show(\"选择展示商品\",\"choose-product\",900,600)' class=\"btn btn-secondary radius\" value=\"选择关联商品\">\n            </div>\n        </div>\n        <div class=\"row cl product\">\n            <label class=\"form-label col-xs-4 col-sm-2\">所选商品ID：</label>\n            <div class=\"formControls col-xs-8 col-sm-4\">\n                <input type=\"text\" onclick='App.show(\"选择展示商品\",\"choose-product\",900,600)' readonly placeholder=\"请点击选择按钮选择关联商品\" class=\"input-text\" id=\"productId\" name=\"productId\">\n            </div>\n        </div>\n        <input type=\"text\" name=\"picUrl\" id=\"picUrl\" hidden/>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\">3D轮播图图片上传：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <div id=\"dropz\" class=\"dropzone\"></div>\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <div class=\"col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-2\">\n                <button class=\"btn btn-primary radius\" type=\"submit\"><i class=\"Hui-iconfont\">&#xe632;</i> 保存并提交</button>\n                <button onClick=\"layer_close();\" class=\"btn btn-default radius\" type=\"button\">&nbsp;&nbsp;取消&nbsp;&nbsp;</button>\n            </div>\n        </div>\n    </form>\n</div>\n\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- DropZone -->\n<script src=\"/static/assets/plugins/dropzone/min/dropzone.min.js\"></script>\n\n<!-- App -->\n<script type=\"text/javascript\" src=\"/static/assets/app/validate.js\"></script>\n\n<script type=\"text/javascript\">\n\n    /**\n     * 获取父窗口的值\n     */\n    $(\"#id\").val(parent.id);\n    $(\"#productId\").val(parent.productId);\n    $(\"#name\").html(parent.name);\n    $(\"#panelId\").val(parent.panelId);\n    $(\"#title\").val(parent.productName);\n    $(\"#picUrl\").val(parent.picUrl);\n    $(\"#fullUrl\").val(parent.fullUrl);\n    $(\"#sortOrder\").val(parent.sortOrder);\n\n    /**\n     * 板块类型：0：轮播图 -1：其他板块内容\n     * */\n    var panelType = parent.panelType;\n\n    /**\n     * 是否已有封面\n     * */\n    var cover = parent.cover;\n\n    /**\n     * 若不是关联商品，显示其他链接\n     * */\n    if (parent.type == 1 || parent.type == 3) {\n        $(\".product\").hide();\n        $(\"#oUrl\").show();\n    }\n\n    /**\n     * 轮播图没有封面选择，其他板块内容添加封面选项\n     * */\n    if (panelType == -1) {\n        $(\"#type option:last\").remove();\n        if (cover == 1) {\n            $(\"#type\").append(\"<option value=\\\"2\\\">封面(关联商品)</option>\");\n            $(\"#type\").append(\"<option value=\\\"3\\\">封面(其它链接)</option>\");\n        }\n    }\n    $(\"#type\").val(parent.type);\n\n    /**\n     * 选项改变更换\n     * */\n    $(\"#type\").change(function () {\n       var type = $(\"#type\").val();\n       if (type == 1 || type == 3) {\n           $(\"#title\").val(\"\");\n           $(\"#productId\").val(\"\");\n           $(\".product\").hide();\n           $(\"#oUrl\").show();\n       } else if (type == 0 || type == 2) {\n           $(\"#fullUrl\").val(\"\");\n           $(\"#oUrl\").hide();\n           $(\".product\").show();\n       }\n    });\n\n    /**\n     * 获取轮播图的地址\n     * */\n    var picUrl = parent.picUrl;\n\n    /**\n     * 表单提交之前执行的方法\n     * */\n    function beforeMethod() {\n        var type = $(\"#type\").val();\n        var fullUrl = $(\"#fullUrl\").val();\n        var selectProductId = $(\"#productId\").val();\n        var image = $(\"#picUrl\").val();\n        if ((type == 0 && selectProductId == \"\") || (type == 2 && selectProductId == \"\")) {\n            layer.alert('请选择关联商品！', {title: '错误信息', icon: 0});\n            return false;\n        }\n        if (type == 1 && fullUrl == \"\") {\n            layer.alert('请填写跳转链接！', {title: '错误信息', icon: 0});\n            return false;\n        }\n        if (image == \"\") {\n            layer.alert('请上传轮播图片！', {title: '错误信息', icon: 0});\n            return false;\n        }\n        return true;\n    }\n    /**\n     * 提交成功后执行的方法\n     * */\n    function successMethod(data) {\n        parent.refresh();\n        parent.App.msgSuccess(data.message);\n        parent.updateCurrentCount();\n        var index = parent.layer.getFrameIndex(window.name);\n        parent.layer.close(index);\n    }\n    Validate.validate('/content/save', beforeMethod, successMethod);\n\n    /**\n     * 初始化 Dropzone\n     */\n    Dropzone.autoDiscover = false;\n    var myDropzone = new Dropzone(\"#dropz\", {\n        url: \"/upload\", // 文件提交地址\n        method: \"post\",  // 也可用put\n        paramName: \"dropFile\", // 默认为file\n        maxFiles: 1,// 一次性上传的文件数量上限\n        maxFilesize: 10, // 文件大小，单位：MB\n        acceptedFiles: \".jpg,.gif,.png,.jpeg\", // 上传的类型\n        addRemoveLinks: true,\n        parallelUploads: 1,// 一次上传的文件数量\n        dictDefaultMessage: '拖动文件至此或者点击上传',\n        dictMaxFilesExceeded: \"您最多只能上传1个文件！\",\n        dictResponseError: '文件上传失败!',\n        dictInvalidFileType: \"文件类型只能是*.jpg,*.gif,*.png,*.jpeg。\",\n        dictFallbackMessage: \"浏览器不受支持\",\n        dictFileTooBig: \"文件过大上传文件最大支持.\",\n        dictRemoveLinks: \"删除\",\n        dictCancelUpload: \"取消\",\n        init: function () {\n            this.emit(\"initimage\", picUrl); // 以逗号分开\n            this.on(\"success\", function (file, data) {\n                if (data.status == 200) {\n                    // 上传成功触发的事件\n                    $(\"#picUrl\").val(data.fileName);\n                } else {\n                    layer.alert(data.message, {title: \"错误信息\", icon: 2});\n                }\n            });\n        }\n    });\n\n    /**\n     * 选择完成设置商品的 id 和标题\n     * @param id\n     * @param title\n     */\n    function setIdAndTitle(id, title) {\n        $(\"#productId\").val(id);\n        $(\"#title\").val(title);\n    }\n</script>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/content-common-list.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <!-- ZTree -->\n    <link rel=\"stylesheet\" href=\"/static/assets/lib/zTree/v3/css/zTreeStyle/zTreeStyle.css\" type=\"text/css\">\n    <!-- iCheck -->\n    <link rel=\"stylesheet\" href=\"/static/assets/plugins/iCheck/all.css\">\n</head>\n<style>\n    .table>tbody>tr>td{\n        text-align:center;\n    }\n</style>\n\n<body class=\"pos-r\">\n<div class=\"pos-a\" style=\"width:200px;left:0;top:0; bottom:0; height:100%; border-right:1px solid #e5e5e5; background-color:#f5f5f5; overflow:auto;\">\n    <ul style=\"margin-top: 15px;margin-left: 20px\"><i class=\"Hui-iconfont Hui-iconfont-fenlei\"></i> 首页板块</ul>\n    <ul id=\"myTree\" style=\"margin-left: 10px\" class=\"ztree\"></ul>\n</div>\n<div style=\"margin-left:200px;\">\n    <input id=\"type\" type=\"hidden\" value=\"${type}\" />\n    <nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 商城管理 <span class=\"c-gray en\">&gt;</span> 首页${type == -1 ? \"板块内容\" : \"轮播图\"}管理 <span class=\"c-gray en\">&gt;</span><span id=\"name\"></span> <a class=\"btn btn-success radius r\" style=\"line-height:1.6em;margin-top:3px\" href=\"javascript:location.replace(location.href);\" title=\"刷新\" ><i class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n    <form id=\"form-search\" class=\"page-container\">\n        <div class=\"cl pd-5 bg-1 bk-gray mt-20\"> <span class=\"l\"><a href=\"javascript:;\" onclick=\"deleteMulti()\" class=\"btn btn-danger radius\"><i class=\"Hui-iconfont\">&#xe6e2;</i> 批量删除</a> <a class=\"btn btn-primary radius\" onclick=\"common_add('添加展示内容','content-common-form')\" href=\"javascript:;\"><i class=\"Hui-iconfont\">&#xe600;</i> 添加展示内容</a></span> <span class=\"r\">最大容纳内容(商品)数：<strong id=\"limitNum\"></strong></span> </div>\n        <div class=\"mt-20\">\n            <div class=\"mt-20\" style=\"margin-bottom: 70px\">\n                <table id=\"dataTable\" class=\"table table-border table-bordered table-bg table-hover table-sort\" width=\"100%\">\n                    <thead>\n                    <tr class=\"text-c\">\n                        <th width=\"30\"><input type=\"checkbox\" class=\"minimal icheck_master\" ></th>\n                        <th width=\"40\">ID</th>\n                        <th width=\"50\">类型</th>\n                        <th width=\"70\">缩略图</th>\n                        <th width=\"150\">跳转链接</th>\n                        <th width=\"100\">展示商品ID</th>\n                        <th width=\"150\">商品名称</th>\n                        <th width=\"60\">排序值</th>\n                        <th width=\"95\">更新日期</th>\n                        <th width=\"90\">操作</th>\n                    </tr>\n                    </thead>\n                </table>\n            </div>\n        </div>\n    </form>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- ZTree -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/zTree/v3/js/jquery.ztree.all-3.5.min.js\"></script>\n<!-- DataTables -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/datatables/1.10.0/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/laypage/1.2/laypage.js\"></script>\n<!-- iCheck -->\n<script type=\"text/javascript\" src=\"/static/assets/plugins/iCheck/icheck.min.js\"></script>\n\n<script type=\"text/javascript\">\n    /**\n     * 初始化\n     * */\n    var index = layer.load(3);\n    /**\n     * panelType = 0 时，为轮播图板块内容管理，type = -1 时，为其他板块内容管理\n     * */\n    var panelType = $(\"#type\").val();\n    /**\n     * 初始化类别数据\n     * */\n    var panelId = 1, name = \"\", limitCount = 0, currentCount = 0;\n    $.ajax({\n        url: '/panel/common/list/' + panelType,\n        type: 'GET',\n        dataType: 'json',\n        success: function (data) {\n            if (data.length <= 0 || data == \"\") {\n                return ;\n            }\n            panelId = data[0].id;\n            name = data[0].name;\n            $(\"#name\").html(name);\n            limitCount = data[0].limitNum;\n            $(\"#limitNum\").html(limitCount);\n            initTable(\"/content/list/\" + panelId);\n            updateCurrentCount();\n        },\n        error: function () {\n            layer.alert(ERROR_REQUEST_MESSAGE, {title: \"错误信息\", icon: 2});\n        }\n    });\n    /**\n     * 初始化 iCheck\n     */\n    App.initICheck();\n    /**\n     * 初始化 DataTables\n     */\n    var _dataTable;\n    function initTable(url) {\n        const _columns = [\n            { \"data\": null,\n                render : function(data,type, row, meta) {\n                    return '<input id=\"' + row.id + '\" type=\"checkbox\" class=\"minimal\">';\n                }\n            },\n            { \"data\": \"id\"},\n            { \"data\": \"type\",\n                render : function(data,type, row, meta) {\n                    if (data == 0){\n                        return \"<span class=\\\"label label-success radius td-status type\\\">关联商品</span>\";\n                    } else if(data == 1){\n                        return \"<span class=\\\"label label-warning radius td-status type\\\">其他链接</span>\";\n                    } else if(data == 2){\n                        return \"<span  class=\\\"label label-primary radius td-status type\\\">封面(关联商品)</span>\";\n                    } else if(data == 3){\n                        return \"<span class=\\\"label label-primary radius td-status type\\\">封面(其它链接)</span>\";\n                    }\n                }\n            },\n            { \"data\": \"picUrl\",\n                render: function(data, type, row, meta) {\n                    return '<img id=\"picUrl\" src=\"'+ data +'\" style=\"width: 80px;height: 60px\" alt=\"\" onclick=\"App.previewImg(this, 700, 400)\" />';\n                }\n            },\n            {\"data\": \"fullUrl\",\n                render: function(data, type, row, meta) {\n                    if (data == null || data == \"\") {\n                        return \"无\";\n                    } else {\n                        return data;\n                    }\n                }\n            },\n            { \"data\": \"productId\",\n                render: function(data, type, row, meta) {\n                    if (data == null || data == \"\") {\n                        return \"无\";\n                    } else {\n                        return data;\n                    }\n                }\n            },\n            { \"data\": \"productName\",\n                render: function(data, type, row, meta) {\n                    if (data == null || data == \"\") {\n                        return \"无\";\n                    } else {\n                        return data;\n                    }\n                }\n            },\n            {\"data\": \"sortOrder\"},\n            { \"data\": \"updated\",\n                render : function(data,type, row, meta) {\n                    return date(data);\n                }\n            },\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    return \"<a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"common_edit('内容编辑','content-common-form')\\\" href=\\\"javascript:;\\\" title=\\\"编辑\\\"><i class=\\\"Hui-iconfont\\\">&#xe6df;</i></a> \" +\n                        \"<a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"deleteSinge(\"+row.id+\")\\\" href=\\\"javascript:;\\\" title=\\\"删除\\\"><i class=\\\"Hui-iconfont\\\">&#xe6e2;</i></a>\";\n                }\n            }\n        ];\n        _dataTable = App.initDataTables(url, _columns);\n    }\n    /**\n     * ZTree 回调函数\n     * */\n    var callback = {\n        onAsyncSuccess: function(){\n            layer.close(index);\n        },\n        beforeClick: function(treeId, treeNode) {\n            if (treeNode.isParent) {\n                return false;\n            } else {\n                panelId = treeNode.id;\n                name = treeNode.name;\n                $(\"#name\").html(name);\n                limitCount = treeNode.limitNum;\n                $(\"#limitNum\").html(limitCount);\n                updateCurrentCount();\n                var url=\"/content/list/\"+panelId;\n                _dataTable.ajax.url(url).load();\n                return true;\n            }\n        }\n    };\n    App.initZtree(\"/panel/common/list/\" + panelType, callback);\n    /**\n     * 更新当前数量\n     * */\n    function updateCurrentCount() {\n        $.ajax({\n            url: \"/content/list/\" + panelId,\n            type: 'GET',\n            dataType: 'json',\n            success: function (data) {\n                currentCount = data.data.length;\n            },\n            error: function () {\n                layer.alert(ERROR_REQUEST_MESSAGE, {title: '错误信息', icon: 2});\n            }\n        })\n    }\n    /**\n     * 判断是否有封面\n     * */\n    function isExistCover() {\n        let cover = 1;\n        $(\".type\").each(function () {\n            if ($(this).html().indexOf('封面') != -1) {\n                cover = 0;\n                return cover;\n            }\n        });\n        return cover;\n    }\n    /**\n     * 编辑板块内容\n     */\n    var id, productId, productName, picUrl, type, cover;\n    function common_edit(title, url) {\n        $(\"#dataTable tbody\").on('click', 'tr', function () {\n            id = _dataTable.row(this).data().id;\n            productId = _dataTable.row(this).data().productId;\n            productName = _dataTable.row(this).data().productName;\n            fullUrl = _dataTable.row(this).data().fullUrl;\n            picUrl = _dataTable.row(this).data().picUrl;\n            type = _dataTable.row(this).data().type;\n            sortOrder = _dataTable.row(this).data().sortOrder;\n            cover = isExistCover();\n            if (type == 2 || type == 3) {\n                cover = 1;\n            }\n        });\n        var index = layer.open({\n            type: 2,\n            title: title,\n            content: url\n        });\n        layer.full(index);\n    }\n    /**\n     * 添加板块内容\n     * */\n    function common_add(title, url) {\n        id = \"\", productId = \"\", productName = \"\", picUrl = \"\", type = \"\";\n        cover = isExistCover();\n        if (type == 2 || type == 3) {\n            cover = 1;\n        }\n        if (currentCount >= limitCount) {\n            layer.alert('当前板块内容数量已达上限', {title: '错误信息', icon: 0});\n            return;\n        }\n        var index = layer.open({\n            type: 2,\n            title: title,\n            content: url\n        });\n        layer.full(index);\n    }\n    /**\n     * 删除单个板块内容\n     *\n     * @param id 板块内容 id\n     */\n    function deleteSinge(id) {\n        // 确认消息\n        var confirmMsg = '确定要删除ID为\\''+ id +'\\'的数据吗？';\n        // 提交请求\n        var url = '/content/delete/' + id;\n        // 成功回调方法\n        function successMethod() {\n            updateCurrentCount('/content/delete/' + id);\n            refresh();\n            layer.msg(\"删除成功！\", {icon:1, time:1000});\n        }\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n    /**\n     * 批量删除\n     * */\n    function deleteMulti() {\n        // 请求路径\n        var url = \"/content/delete/\";\n        // 请求成功执行方法\n        function successMethod() {\n            updateCurrentCount();\n            refresh();\n            layer.msg(\"删除成功！\", {icon:1, time:1000});\n        }\n        App.deleteMulti(url, successMethod);\n    }\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/content-header-list.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>导航栏管理</title>\n    <!-- iCheck -->\n    <link rel=\"stylesheet\" href=\"/static/assets/plugins/iCheck/all.css\">\n</head>\n<style>\n    .table>tbody>tr>td{\n        text-align:center;\n    }\n</style>\n<body>\n\n<div>\n    <nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 商城管理 <span class=\"c-gray en\">&gt;</span> 导航栏管理 <a class=\"btn btn-success radius r\" style=\"line-height:1.6em;margin-top:3px\" href=\"javascript:location.replace(location.href);\" title=\"刷新\" ><i class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n    <form class=\"page-container\">\n        <div class=\"cl pd-5 bg-1 bk-gray mt-20\">\n            <span class=\"l\">\n                <a href=\"javascript:;\" onclick=\"datadel()\" class=\"btn btn-danger radius\"><i class=\"Hui-iconfont\">&#xe6e2;</i> 批量删除</a>\n                <a class=\"btn btn-primary radius\" onclick=\"add('添加导航栏内容','/content-header-form',700,350)\" href=\"javascript:;\"><i class=\"Hui-iconfont\">&#xe600;</i> 添加导航栏内容</a>\n            </span>\n        </div>\n        <div class=\"mt-20\">\n            <div class=\"mt-20\" >\n                <table id=\"dataTable\" class=\"table table-border table-bordered table-bg table-hover table-sort\" width=\"100%\">\n                    <thead>\n                    <tr class=\"text-c\">\n                        <th width=\"15\"><input type=\"checkbox\" class=\"minimal icheck_master\"></th>\n                        <th width=\"30\">ID</th>\n                        <th width=\"80\">名称</th>\n                        <th width=\"100\">跳转链接</th>\n                        <th width=\"60\">类型</th>\n                        <th width=\"50\">排序值</th>\n                        <th width=\"50\">操作</th>\n                    </tr>\n                    </thead>\n                    <tbody>\n                    </tbody>\n                </table>\n            </div>\n        </div>\n    </form>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- DataTables -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/datatables/1.10.0/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/laypage/1.2/laypage.js\"></script>\n<!-- iCheck 1.0.1 -->\n<script src=\"/static/assets/plugins/iCheck/icheck.min.js\"></script>\n\n<script type=\"text/javascript\">\n\n    // 初始化 iCheck\n    App.initICheck();\n\n   /**\n    * 初始化 DataTables\n    */\n   $(function () {\n        const _columns = [\n            {\n                \"data\": null,\n                render: function(data,type, row, meta) {\n                    return '<input id=\"' + row.id + '\" type=\"checkbox\" class=\"minimal\" />';\n                }\n            },\n            { \"data\": \"id\"},\n            { \"data\": \"picUrl\"},\n            {\n                \"data\": \"fullUrl\",\n                render: function (data, type, row, meta) {\n                    return '<a href=\"'+ row.fullUrl+'\" target=\"_blank\">'+ row.fullUrl +'</a>';\n                }\n            },\n            {\n                \"data\": \"type\",\n                render: function (data, type, row, meta) {\n                    if(data == 0){\n                        return \"<span class=\\\"label label-warning radius td-status\\\">站外</span>\";\n                    }else if(data == 1){\n                        return \"<span class=\\\"label label-success radius td-status\\\">站内</span>\";\n                    }\n                }\n            },\n            { \"data\": \"sortOrder\"},\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    return \"<a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"edit('编辑','/content-header-form',700,350)\\\" href=\\\"javascript:;\\\" title=\\\"编辑\\\"><i class=\\\"Hui-iconfont\\\">&#xe6df;</i></a> \" +\n                        \"<a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"del(\"+row.id+\")\\\" href=\\\"javascript:;\\\" title=\\\"删除\\\"><i class=\\\"Hui-iconfont\\\">&#xe6e2;</i></a>\";\n                }\n            }\n        ];\n\n       App.initDataTables(\"/content/list/0\", _columns);\n    });\n\n\n   /**\n    * 编辑导航栏内容\n    */\n   var id, picUrl, fullUrl, sortOrder, type;\n   function edit(title,url,w,h){\n        var table = $('.table').DataTable();\n        $('.table tbody').on( 'click', 'tr', function () {\n            id = table.row(this).data().id;\n            picUrl = table.row(this).data().picUrl;\n            fullUrl = table.row(this).data().fullUrl;\n            sortOrder = table.row(this).data().sortOrder;\n            type = table.row(this).data().type;\n        });\n        App.show(title,url,w,h);\n    }\n\n    /**\n     * 添加导航栏内容\n     * */\n    function add(title, url, w, h) {\n        id = \"\";\n        picUrl = \"\";\n        fullUrl = \"\";\n        sortOrder = \"\";\n        type = \"\";\n        App.show(title, url, w, h);\n    }\n\n\n   /**\n    * 删除单个导航栏\n    *\n    * @param id 导航栏 id\n    */\n   function del(id) {\n\n       // 确认消息\n       var confirmMsg = '确定要删除ID为\\''+ id +'\\'的数据吗？';\n\n       // 提交请求\n       var url = '/content/delete/' + id;\n\n       // 成功回调方法\n       function successMethod() {\n           refresh();\n           layer.msg(\"删除导航栏成功！\", {icon:2, time:1000});\n       }\n\n       App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 批量删除\n     * */\n    function datadel() {\n\n       // 请求路径\n        var url = \"/content/delete/\";\n\n        // 请求成功执行方法\n       function successMethod() {\n           refresh();\n           layer.msg(\"删除导航栏成功！\", {icon:1, time:1000});\n       }\n\n       App.deleteMulti(url, successMethod);\n    }\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/content-panel-add.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>添加板块</title>\n</head>\n<body>\n<div class=\"page-container\">\n    <form action=\"\" method=\"post\" class=\"form form-horizontal\" id=\"validate-form\">\n        <input type=\"text\" hidden class=\"input-text\" value=\"1\" id=\"status\" name=\"status\">\n        <input type=\"text\" hidden class=\"input-text\" value=\"0\" name=\"position\">\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\">\n                <span class=\"c-red\">*</span>\n                板块名称：</label>\n            <div class=\"formControls col-xs-6 col-sm-6\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"\" id=\"name\" name=\"name\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\">\n                <span class=\"c-red\">*</span>\n                类型：</label>\n            <div class=\"formControls col-xs-6 col-sm-6\">\n                <select id=\"type\" class=\"select-box\" name=\"type\" style=\"width:200px\">\n                    <option value=\"0\">轮播图</option>\n                    <option value=\"1\">板块种类一</option>\n                    <option value=\"2\">板块种类二</option>\n                    <option value=\"2\">板块种类三</option>\n                </select>\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\">\n                <span class=\"c-red\">*</span>\n                排序优先值：</label>\n            <div class=\"formControls col-xs-6 col-sm-6\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"请输入0~9999，值越小排序越前\" id=\"sortOrder\" name=\"sortOrder\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\">\n                <span class=\"c-red\">*</span>\n                最大容纳内容(商品)数：</label>\n            <div class=\"formControls col-xs-6 col-sm-6\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"请输入0~999\" id=\"limitNum\" name=\"limitNum\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>是否启用：</label>\n            <div class=\"formControls col-xs-6 col-sm-6\">\n                <div id=\"mySwitch\" class=\"switch\" data-on-label=\"启用\" data-on=\"info\" data-off-label=\"禁用\">\n                    <input type=\"checkbox\" checked />\n                </div>\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <div class=\"col-9 col-offset-2\">\n                <input class=\"btn btn-primary radius\" type=\"submit\" value=\"&nbsp;&nbsp;提交并保存&nbsp;&nbsp;\">\n            </div>\n        </div>\n    </form>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- jQuery Validation -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/jquery.validate.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/validate-methods.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/messages_zh.js\"></script>\n\n<!-- App -->\n<script type=\"text/javascript\" src=\"/static/assets/app/validate.js\"></script>\n\n<script type=\"text/javascript\">\n\n    // 备注文本框输入限制\n    $(\".textarea\").Huitextarealength({\n        minlength: 0,\n        maxlength: 100\n    });\n\n    // 同步 status 数据\n    $('#mySwitch').on('switch-change', function (e, data) {\n       if (data.value == true) {\n           $(\"#status\").val(1);\n       } else {\n           $(\"#status\").val(0);\n       }\n    });\n\n    // 新增提交验证\n    function successMethod(data) {\n        layer.alert(data.message, {icon: 1}, function (index) {\n            parent.App.initZtree(\"/panel/common/list/1\", parent.callback);\n            var index = parent.layer.getFrameIndex(window.name);\n            parent.layer.close(index);\n        });\n    }\n    Validate.validate(\"/panel/add\", \"\", successMethod);\n\n</script>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/content-panel.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>首页板块</title>\n    <!-- ZTree -->\n    <link rel=\"stylesheet\" href=\"/static/assets/lib/zTree/v3/css/zTreeStyle/zTreeStyle.css\" type=\"text/css\"/>\n</head>\n<body>\n<nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 商城管理 <span class=\"c-gray en\">&gt;</span> 首页板块 <a class=\"btn btn-success radius r\" style=\"line-height:1.6em;margin-top:3px\" href=\"javascript:location.replace(location.href);\" title=\"刷新\" ><i class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n<div style=\"margin-left: 1vw;margin-right: 1vw\" class=\"cl pd-5 bg-1 bk-gray mt-20\"> <span class=\"l\"><a href=\"javascript:;\" onclick=\"delSingle()\" class=\"btn btn-danger radius\"><i class=\"Hui-iconfont\">&#xe6e2;</i> 删除所选板块</a> <a class=\"btn btn-primary radius\" onclick=\"App.openAndFull('添加板块', 'content-panel-add')\" href=\"javascript:;\"><i class=\"Hui-iconfont\">&#xe600;</i> 添加首页板块</a></span> </div>\n<table class=\"table\">\n    <tr>\n        <td style=\"padding-left: 4vw\" width=\"200\" class=\"va-t\"><ul id=\"myTree\" class=\"ztree\"></ul></td>\n        <td class=\"va-t\">\n            <div class=\"page-container\">\n                <form action=\"\" method=\"post\" class=\"form form-horizontal\" id=\"validate-form\">\n                    <input type=\"text\" hidden class=\"input-text\" id=\"id\" name=\"id\">\n                    <input type=\"text\" hidden class=\"input-text\" value=\"1\" id=\"status\" name=\"status\">\n                    <input type=\"text\" hidden class=\"input-text\" value=\"0\" name=\"position\">\n                    <div class=\"row cl\">\n                        <label class=\"form-label col-xs-4 col-sm-2\">\n                            <span class=\"c-red\">*</span>\n                            板块名称：</label>\n                        <div class=\"formControls col-xs-6 col-sm-6\">\n                            <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"\" id=\"name\" name=\"name\">\n                        </div>\n                    </div>\n                    <div class=\"row cl\">\n                        <label class=\"form-label col-xs-4 col-sm-2\">\n                            <span class=\"c-red\">*</span>\n                            类型：</label>\n                        <div class=\"formControls col-xs-6 col-sm-6\">\n                            <select id=\"type\" class=\"select-box\" name=\"type\" style=\"width:200px\">\n                                <option value=\"0\">轮播图</option>\n                                <option value=\"1\">板块种类一</option>\n                                <option value=\"2\">板块种类二</option>\n                                <option value=\"3\">板块种类三</option>\n                            </select>\n                        </div>\n                    </div>\n                    <div class=\"row cl\">\n                        <label class=\"form-label col-xs-4 col-sm-2\">\n                            <span class=\"c-red\">*</span>\n                            排序优先值：</label>\n                        <div class=\"formControls col-xs-6 col-sm-6\">\n                            <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"请输入0~9999，值越小排序越前\" id=\"sortOrder\" name=\"sortOrder\">\n                        </div>\n                    </div>\n                    <div class=\"row cl\">\n                        <label class=\"form-label col-xs-4 col-sm-2\">\n                            <span class=\"c-red\">*</span>\n                            最大容纳内容(商品)数：</label>\n                        <div class=\"formControls col-xs-6 col-sm-6\">\n                            <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"请输入0~999\" id=\"limitNum\" name=\"limitNum\">\n                        </div>\n                    </div>\n                    <div class=\"row cl\">\n                        <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>是否启用：</label>\n                        <div class=\"formControls col-xs-6 col-sm-6\">\n                            <div id=\"mySwitch\" class=\"switch\" data-on-label=\"启用\" data-on=\"info\" data-off-label=\"禁用\">\n                                <input type=\"checkbox\" checked />\n                            </div>\n                        </div>\n                    </div>\n                    <div class=\"row cl\">\n                        <div class=\"col-9 col-offset-2\">\n                            <input class=\"btn btn-primary radius\" type=\"submit\" value=\"&nbsp;&nbsp;提交修改&nbsp;&nbsp;\">\n                        </div>\n                    </div>\n                </form>\n            </div>\n        </td>\n    </tr>\n</table>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- jQuery Validation -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/zTree/v3/js/jquery.ztree.all-3.5.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/jquery.validate.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/validate-methods.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/messages_zh.js\"></script>\n\n<!-- App -->\n<script type=\"text/javascript\" src=\"/static/assets/app/validate.js\"></script>\n\n<script type=\"text/javascript\">\n\n    // 加载中...\n    var index = layer.load(3);\n\n\n    // treeNode 初始化值\n    var id = -1, name = \"\";\n\n    /**\n     * ZTree callback\n     */\n    var callback = {\n        onAsyncSuccess: function () {\n            layer.close(index);\n        },\n        // 点击之前的操作\n        beforeClick: function (treeId, treeNode) {\n            $(\"#name\").val(treeNode.name);\n            $(\"#id\").val(treeNode.id);\n            $(\"#type\").val(treeNode.type);\n            $(\"#sortOrder\").val(treeNode.sortOrder);\n            $(\"#limitNum\").val(treeNode.limitNum);\n            changeSwitch(treeNode.status);\n            id = treeNode.id;\n            name = treeNode.name;\n            if (treeNode.isParent) {\n                return false;\n            } else {\n                return true;\n            }\n        }\n    };\n    /**\n     * 初始化 ZTree\n     */\n    App.initZtree(\"/panel/common/list/1\", callback);\n\n    /**\n     * 切换按钮\n     *\n     * @param value\n     */\n    function changeSwitch(value) {\n        if (value == 1) {\n            $(\"#mySwitch\").bootstrapSwitch('setState', true);\n        } else {\n            $(\"#mySwitch\").bootstrapSwitch('setState', false);\n        }\n    }\n\n    /**\n     * 同步 status 的值\n     * */\n    $(\"#mySwitch\").on('switch-change', function (e, data) {\n        if (data.value == true) {\n            $(\"#status\").val(1);\n        } else {\n            $(\"#status\").val(0);\n        }\n    });\n\n    /**\n     * 备注文本输入框限制\n     * */\n    $(\".textarea\").Huitextarealength({\n        minlength: 0,\n        maxlength: 100\n    });\n\n    /**\n     * 验证之前的触发的方法\n     */\n    function beforeSubmit() {\n        if ($(\"#id\").val() == null || $(\"#id\").val() == \"\") {\n            layer.alert('请点击选择要修改的板块！请勿自己填写！', {title: '错误信息', icon: 0});\n            return false;\n        }\n        return true;\n    }\n    /**\n     * 验证成功触发的方法\n     *\n     * @param data\n     */\n    function successMethod(data) {\n        layer.alert(data.message, {icon: 1}, function (index) {\n            App.initZtree(\"/panel/common/list/1\", callback);\n            layer.close(index);\n        });\n    }\n    Validate.validate(\"/panel/update\", beforeSubmit, successMethod);\n\n    /**\n     * 删除单个板块\n     */\n    function delSingle() {\n        if(id == -1){\n            layer.alert('请点击选择要删除的板块! ', {title: '错误信息',icon: 0});\n            return;\n        }\n\n        // 确认消息\n        var confirmMsg = '确定要删除所选的\\''+ name +'\\'板块吗？';\n\n        // 提交请求\n        var url = '/panel/del/' + id;\n\n        // 成功回调方法\n        function successMethod() {\n            App.initZtree(\"/panel/common/list/1\", callback);\n            App.msgSuccess(\"删除成功!\");\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/index.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>YMall后台管理系统</title>\n</head>\n<body>\n<header class=\"navbar-wrapper\">\n    <div class=\"navbar navbar-fixed-top\">\n        <div class=\"container-fluid cl\"> <a class=\"logo navbar-logo f-l mr-10 hidden-xs\" href=\"/\">YMall后台管理系统</a> <a class=\"logo navbar-logo-m f-l mr-10 visible-xs\" href=\"/\">YMall后台管理系统</a>\n            <a aria-hidden=\"false\" class=\"nav-toggle Hui-iconfont visible-xs\" href=\"javascript:;\">&#xe667;</a>\n            <nav class=\"nav navbar-nav\">\n                <ul class=\"cl\">\n                    <li ><a href=\"http://localhost:9999\" target=\"_blank\">商城前台</a></li>\n                    </li>\n                </ul>\n            </nav>\n            <nav id=\"Hui-userbar\" class=\"nav navbar-nav navbar-userbar hidden-xs\">\n                <ul class=\"cl\">\n                    <li style=\"right:5px\" id=\"role\"></li>\n                    <li class=\"dropDown dropDown_hover\">\n                        <a href=\"#\" class=\"dropDown_A\"><sapn id=\"username\"></sapn> <i class=\"Hui-iconfont\">&#xe6d5;</i></a>\n                        <ul class=\"dropDown-menu menu radius box-shadow\">\n                            <li><a onclick=\"logout()\">切换账户</a></li>\n                            <li><a onclick=\"logout()\">退出</a></li>\n                        </ul>\n                    </li>\n                    <li id=\"LockScreen\"> <a href=\"/lock-screen\" title=\"锁屏\"><i class=\"Hui-iconfont\" style=\"font-size:18px\">&#xe60e;</i></a> </li>\n                    <li id=\"Hui-skin\" class=\"dropDown right dropDown_hover\"> <a href=\"javascript:;\" class=\"dropDown_A\" title=\"换肤\"><i class=\"Hui-iconfont\" style=\"font-size:18px\">&#xe62a;</i></a>\n                        <ul class=\"dropDown-menu menu radius box-shadow\">\n                            <li><a href=\"javascript:;\" data-val=\"default\" title=\"默认（蓝色）\">默认（蓝色）</a></li>\n                            <li><a href=\"javascript:;\" data-val=\"black\" title=\"黑色\">黑色</a></li>\n                            <li><a href=\"javascript:;\" data-val=\"green\" title=\"绿色\">绿色</a></li>\n                            <li><a href=\"javascript:;\" data-val=\"red\" title=\"红色\">红色</a></li>\n                            <li><a href=\"javascript:;\" data-val=\"yellow\" title=\"黄色\">黄色</a></li>\n                            <li><a href=\"javascript:;\" data-val=\"orange\" title=\"橙色\">橙色</a></li>\n                        </ul>\n                    </li>\n                </ul>\n            </nav>\n        </div>\n    </div>\n</header>\n<aside class=\"Hui-aside\">\n    <div class=\"menu_dropdown bk_2\">\n        <dl id=\"menu-article\">\n            <dt><i class=\"Hui-iconfont\">&#xe616;</i> 首页管理<i class=\"Hui-iconfont menu_dropdown-arrow\">&#xe6d5;</i></dt>\n            <dd>\n                <ul>\n                    <li><a data-href=\"/content-panel\" data-title=\"板块管理\" href=\"javascript:void(0)\">首页板块管理</a></li>\n                    <li><a data-href=\"/content-common-list?type=0\" data-title=\"轮播图管理\" href=\"javascript:void(0)\">首页轮播图管理</a></li>\n                    <li><a data-href=\"/content-common-list?type=-1\" data-title=\"板块内容管理\" href=\"javascript:void(0)\">首页板块内容管理</a></li>\n                </ul>\n            </dd>\n        </dl>\n        <dl id=\"menu-product\">\n            <dt><i class=\"Hui-iconfont\">&#xe620;</i> 商品管理<i class=\"Hui-iconfont menu_dropdown-arrow\">&#xe6d5;</i></dt>\n            <dd>\n                <ul>\n                    <li><a data-href=\"product-list\" data-title=\"商品列表\" href=\"javascript:void(0)\">商品列表</a></li>\n                </ul>\n            </dd>\n        </dl>\n        <dl id=\"menu-category\">\n            <dt><i class=\"Hui-iconfont\">&#xe620;</i> 分类管理<i class=\"Hui-iconfont menu_dropdown-arrow\">&#xe6d5;</i></dt>\n            <dd>\n                <ul>\n                    <li><a data-href=\"product-category\" data-title=\"分类列表\" href=\"javascript:void(0)\">分类列表</a></li>\n                </ul>\n            </dd>\n        </dl>\n        <dl id=\"menu-order\">\n            <dt><i class=\"Hui-iconfont\">&#xe627;</i> 订单管理<i class=\"Hui-iconfont menu_dropdown-arrow\">&#xe6d5;</i></dt>\n            <dd>\n                <ul>\n                    <li><a data-href=\"order-list\" data-title=\"订单列表\" href=\"javascript:void(0)\">订单列表</a></li>\n                </ul>\n            </dd>\n        </dl>\n        <dl id=\"menu-member\">\n            <dt><i class=\"Hui-iconfont\">&#xe60d;</i> 会员管理<i class=\"Hui-iconfont menu_dropdown-arrow\">&#xe6d5;</i></dt>\n            <dd>\n                <ul>\n                    <li><a data-href=\"member-list\" data-title=\"会员列表\" href=\"javascript:;\">会员列表</a></li>\n                    <li><a data-href=\"member-ban\" data-title=\"封禁的会员\" href=\"javascript:;\">封禁的会员</a></li>\n                </ul>\n            </dd>\n        </dl>\n        <dl id=\"menu-admin\">\n            <dt><i class=\"Hui-iconfont\">&#xe62d;</i> 管理员管理<i class=\"Hui-iconfont menu_dropdown-arrow\">&#xe6d5;</i></dt>\n            <dd>\n                <ul>\n                    <li><a data-href=\"admin-list\" data-title=\"管理员列表\" href=\"javascript:void(0)\">管理员列表</a></li>\n                </ul>\n            </dd>\n        </dl>\n        <dl id=\"menu-admin\">\n            <dt><i class=\"Hui-iconfont\">&#xe687;</i> 报表管理<i class=\"Hui-iconfont menu_dropdown-arrow\">&#xe6d5;</i></dt>\n            <dd>\n                <ul>\n                    <li><a data-href=\"chart-order\" data-title=\"订单销量统计\" href=\"javascript:void(0)\">订单销量统计</a></li>\n                </ul>\n            </dd>\n        </dl>\n        <dl id=\"menu-system\">\n            <dt><i class=\"Hui-iconfont\">&#xe62e;</i> 快递管理<i class=\"Hui-iconfont menu_dropdown-arrow\">&#xe6d5;</i></dt>\n            <dd>\n                <ul>\n                    <li><a data-href=\"system-express\" data-title=\"快递管理\" href=\"javascript:void(0)\">快递列表</a></li>\n                </ul>\n            </dd>\n        </dl>\n    </div>\n    <div class=\"menu_dropdown bk_2\" style=\"display:none\">\n        <dl id=\"menu-thank\">\n            <dt><i class=\"Hui-iconfont\">&#xe6b7;</i> 捐赠管理<i class=\"Hui-iconfont menu_dropdown-arrow\">&#xe6d5;</i></dt>\n            <dd>\n                <ul>\n                    <li><a data-href=\"thanks-list\" data-title=\"捐赠列表\" href=\"javascript:void(0)\">捐赠列表</a></li>\n                </ul>\n            </dd>\n        </dl>\n    </div>\n</aside>\n<div class=\"dislpayArrow hidden-xs\"><a class=\"pngfix\" href=\"javascript:void(0);\" onClick=\"displaynavbar(this)\"></a></div>\n<section class=\"Hui-article-box\">\n    <div id=\"Hui-tabNav\" class=\"Hui-tabNav hidden-xs\">\n        <div class=\"Hui-tabNav-wp\">\n            <ul id=\"min_title_list\" class=\"acrossTab cl\">\n                <li class=\"active\">\n                    <span title=\"我的首页\" data-href=\"welcome\">我的首页</span>\n                    <em></em></li>\n            </ul>\n        </div>\n        <div class=\"Hui-tabNav-more btn-group\"><a id=\"js-tabNav-prev\" class=\"btn radius btn-default size-S\" href=\"javascript:;\"><i class=\"Hui-iconfont\">&#xe6d4;</i></a><a id=\"js-tabNav-next\" class=\"btn radius btn-default size-S\" href=\"javascript:;\"><i class=\"Hui-iconfont\">&#xe6d7;</i></a></div>\n    </div>\n    <div id=\"iframe_box\" class=\"Hui-article\">\n        <div class=\"show_iframe\">\n            <div style=\"display:none\" class=\"loading\"></div>\n            <iframe scrolling=\"yes\" frameborder=\"0\" src=\"welcome\"></iframe>\n        </div>\n    </div>\n</section>\n\n<div class=\"contextMenu\" id=\"Huiadminmenu\">\n    <ul>\n        <li id=\"closethis\">关闭当前 </li>\n        <li id=\"closeall\">关闭全部 </li>\n    </ul>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!--请在下方写此页面业务相关的脚本-->\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery.contextmenu/jquery.contextmenu.r2.js\"></script>\n<script type=\"text/javascript\">\n\n    // 获取用户信息\n    var username=\"\",description=\"\",sex=\"\",phone=\"\",email=\"\",address=\"\",created=\"\",file=\"\";\n    function successMethod(data) {\n        $(\"#role\").html(data.result.description);\n        $(\"#username\").html(data.result.username);\n        username = data.result.username;\n        description = data.result.description;\n        sex = data.result.sex;\n        phone = data.result.phone;\n        email = data.result.email;\n        address = data.result.address;\n        created = data.result.created;\n        file = data.result.file;\n    }\n    App.ajax(\"/user/userInfo\", \"GET\", successMethod);\n\n    // 退出登录\n    function logout() {\n        function successMethod() {\n            window.location.href = \"/login\";\n        }\n        App.ajax(\"/user/logout\", \"GET\", successMethod());\n    }\n\n    // 弹出感谢窗口\n    function thanks(){\n        layer.open({\n            title: '捐赠',\n            type: 2,\n            skin: 'layui-layer-rim', //加上边框\n            area: ['525px', '300px'], //宽高\n            content: ['/thanks-pic','no']\n        });\n    }\n</script>\n</body\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/lock-screen.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"Yuu\">\n    <link rel=\"Shortcut Icon\" href=\"/static/assets/icon/logo.png\" />\n    <title>YMall后台管理系统 v1.0</title>\n    <meta name=\"keywords\" content=\"YMall后台管理系统 v1.0,YMall,YMall购物商城后台管理系统\">\n    <meta name=\"description\" content=\"YMall后台管理系统 v1.0，是一款电商后台管理系统，适合中小型CMS后台系统。\">\n\n    <title>Lock Screen</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"/static/assets/lib/flatlab/css/bootstrap.min.css\" rel=\"stylesheet\">\n    <link href=\"/static/assets/lib/flatlab/css/bootstrap-reset.css\" rel=\"stylesheet\">\n    <!--external css-->\n    <link href=\"/static/assets/lib/flatlab/assets/font-awesome/css/font-awesome.css\" rel=\"stylesheet\" />\n    <!-- Custom styles for this template -->\n    <link href=\"/static/assets/lib/flatlab/css/style.css\" rel=\"stylesheet\">\n    <link href=\"/static/assets/lib/flatlab/css/style-responsive.css\" rel=\"stylesheet\" />\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 tooltipss and media queries -->\n    <!--[if lt IE 9]>\n    <script src=\"/static/assets/lib/flatlab/js/html5shiv.js\"></script>\n    <script src=\"/static/assets/lib/flatlab/js/respond.min.js\"></script>\n    <![endif]-->\n\n</head>\n\n<body class=\"lock-screen\" onload=\"startTime()\">\n\n<div class=\"lock-wrapper\">\n\n    <div id=\"time\"></div>\n\n    <div class=\"lock-box text-center\">\n        <img id=\"avatar\" width=\"85px\" height=\"85px\" src=\"/static/assets/static/h-ui/images/ucnter/avatar-default.jpg\" alt=\"lock avatar\"/>\n        <h1 id=\"username\">Yuu</h1>\n        <span class=\"locked\">Locked</span>\n        <form role=\"form\" class=\"form-inline\">\n            <div class=\"form-group col-lg-12\">\n                <input type=\"password\" placeholder=\"Password\" id=\"password\" class=\"form-control lock-input\">\n                <button id=\"unlockButton\" class=\"btn btn-lock\" type=\"button\">\n                    <i class=\"icon-arrow-right\"></i>\n                </button>\n            </div>\n        </form>\n    </div>\n</div>\n<script type=\"text/javascript\" src=\"/static/assets/lib/jquery/1.9.1/jquery.min.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/layer/2.4/layer.js\"></script>\n\n<!-- App -->\n<script type=\"text/javascript\" src=\"/static/assets/app/app.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/app/const.js\"></script>\n<script>\n\n    // 获取用户信息\n    function successMethod(data) {\n        $('#username').html(data.result.username);\n        if (data.result.file != null && data.result.file != \"\") {\n            $('#avatar').attr('src', data.result.file);\n        }\n    }\n    App.ajax(\"/user/userInfo\", \"GET\", successMethod);\n\n    // 解锁\n    $(\"#unlockButton\").click(function () {\n        var password = $(\"#password\").val();\n        if (password == null || password == \"\") {\n            layer.msg(\"密码不能为空\");\n            return ;\n        }\n        var data = {password: password};\n        function successMethod() {\n            window.location.href = \"/\";\n        }\n        App.ajaxWithData(\"/user/unlock\", \"GET\", data, successMethod);\n    });\n\n    /**\n     * 设置时间\n     */\n    function startTime()\n    {\n        var today=new Date();\n        var h=today.getHours();\n        var m=today.getMinutes();\n        var s=today.getSeconds();\n        // add a zero in front of numbers<10\n        m=checkTime(m);\n        s=checkTime(s);\n        document.getElementById('time').innerHTML=h+\":\"+m+\":\"+s;\n        t=setTimeout(function(){startTime()},500);\n    }\n\n    /**\n     * 计时\n     * @param i\n     * @returns {*}\n     */\n    function checkTime(i)\n    {\n        if (i<10)\n        {\n            i=\"0\" + i;\n        }\n        return i;\n    }\n</script>\n</body>\n</html>\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/login.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html lang=\"en\">\n<head>\n    <title>YMall后台管理系统</title>\n    <link rel=\"Shortcut Icon\" href=\"/static/assets/icon/logo.png\" />\n    <!-- Meta tag Keywords -->\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n\n    <!-- css files -->\n    <link rel=\"stylesheet\" href=\"/static/assets/lib/login/style.css\" type=\"text/css\" media=\"all\" /> <!-- Style-CSS -->\n    <link rel=\"stylesheet\" href=\"/static/assets/lib/login/font-awesome.css\"> <!-- Font-Awesome-Icons-CSS -->\n    <link rel=\"stylesheet\" href=\"/static/assets/lib/layer/2.4/skin/layer.css\"> <!-- Font-Awesome-Icons-CSS -->\n    <!-- js -->\n    <script type=\"text/javascript\" src=\"/static/assets/lib/jquery/jquery-2.1.4.min.js\"></script>\n    <script src=\"/static/assets/lib/login/jquery.vide.min.js\"></script>\n    <script type=\"text/javascript\" src=\"/static/assets/lib/layer/2.4/layer.js\"></script>\n    <script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/jquery.validate.js\"></script>\n    <script type=\"text/javascript\" src=\"/static/assets/lib/jquery.validation/1.14.0/validate-methods.js\"></script>\n    <script type=\"text/javascript\" src=\"/static/assets/lib/gt.js\"></script>\n\n    <style>\n        html,body{\n            height: 100%;\n        }\n        .title,h6{\n            font-family: \"黑体\";\n        }\n        .layui-layer-title {\n            padding-right: 305px;\n            font-family:\"Microsoft Yahei\"\n        }\n        .layui-layer-dialog .layui-layer-content{\n            font-family:\"Microsoft Yahei\"\n        }\n        .layui-layer-btn{\n            font-family:\"Microsoft Yahei\"\n        }\n        span.icon1 {\n            top: 25%;\n        }\n        span.icon2 {\n            top: 46%;\n        }\n        #wait {\n            text-align: left;\n            color: #ffffff;\n            margin: 0;\n            font-family: \"黑体\";\n        }\n    </style>\n\n</head>\n<body>\n<!-- main -->\n<div style=\"height: 100%;background: url('/static/assets/images/login-img.png') no-repeat fixed center\">\n    <div class=\"center-container\" style=\"height: 100%;\">\n        <!--header-->\n        <div class=\"header-w3l\">\n            <h1>YMall<span class=\"title\">后台管理系统</span></h1>\n        </div>\n        <!--//header-->\n        <div class=\"main-content-agile\">\n            <div class=\"sub-main-w3\">\n                <div class=\"wthree-pro\">\n                    <h2>Login Here</h2>\n                </div>\n                <form id=\"login\" action=\"\" method=\"post\" width=\"100%\">\n                    <input placeholder=\"用户名\" name=\"username\" id=\"username\" class=\"user\" type=\"text\" required=\"\">\n                    <span class=\"icon1\"><i class=\"fa fa-user\" aria-hidden=\"true\"></i></span><br><br>\n                    <input  placeholder=\"密码\" name=\"password\" id=\"password\" class=\"pass\" type=\"password\" required=\"\">\n                    <span class=\"icon2\"><i class=\"fa fa-unlock\" aria-hidden=\"true\"></i></span><br><br>\n\n                    <div id=\"captcha\">\n                        <p id=\"wait\" class=\"show\">正在加载验证码...</p>\n                    </div>\n\n                    <div class=\"sub-w3l\">\n                        <div class=\"right-w3l\">\n                            <input id=\"loginButton\" type=\"button\" class=\"login\" value=\"登录\">\n                        </div>\n                    </div>\n                </form>\n            </div>\n        </div>\n        <!--//main-->\n\n        <!--footer-->\n        <div class=\"footer\">\n            <p>&copy; 2019 YMall. All rights reserved | Design by <a href=\"https://www.71yuu.com/\" target=\"_blank\">Yuu</a></p>\n        </div>\n        <!--//footer-->\n\n    </div>\n</div>\n\n<!-- App -->\n<script type=\"text/javascript\" src=\"/static/assets/app/const.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/app/app.js\"></script>\n\n<script type=\"text/javascript\">\n\n    // 登录验证\n    var handler = function (captchaObj) {\n        captchaObj.appendTo('#captcha');\n        captchaObj.onReady(function () {\n            $(\"#wait\").hide();\n        });\n        $('#loginButton').click(function () {\n            $(\"#loginButton\").val(\"登录中...\");\n            $(\"#loginButton\").attr(\"disabled\",\"disabled\");\n            var name=$(\"#username\").val();\n            var pass=$(\"#password\").val();\n            if(name==\"\"||pass==\"\"){\n                layer.msg(\"用户名或密码不能为空\");\n                $(\"#loginButton\").val(\"登录\");\n                $(\"#loginButton\").removeAttr(\"disabled\");\n                return;\n            }\n            var reg = /^[0-9A-Za-z]+$/;\n            if(!reg.exec(name))\n            {\n                layer.msg(\"用户名格式有误\");\n                $(\"#loginButton\").val(\"登录\");\n                $(\"#loginButton\").removeAttr(\"disabled\");\n                return;\n            }\n            var result = captchaObj.getValidate();\n            if (!result) {\n                layer.msg(\"请完成验证\");\n                $(\"#loginButton\").val(\"登录\");\n                $(\"#loginButton\").removeAttr(\"disabled\");\n                return ;\n            }\n            $.ajax({\n                url: '/user/login?t=' + (new Date()).getTime(), // 加随机数防止缓存\n                type: 'POST',\n                dataType: 'json',\n                data: {\n                    username: name,\n                    password: pass,\n                    challenge: result.geetest_challenge,\n                    validate: result.geetest_validate,\n                    seccode: result.geetest_seccode\n                },\n                success: function (data) {\n                    if(data.status == 200){\n                        window.location.href=\"/\";\n                    } else {\n                        layer.msg(data.message);\n                        captchaObj.reset();\n                        $(\"#loginButton\").val(\"登录\");\n                        $(\"#loginButton\").removeAttr(\"disabled\");\n                    }\n                },\n                error:function(){\n                    layer.alert(ERROR_REQUEST_MESSAGE, {title: \"错误信息\", icon: 2});\n                    $(\"#loginButton\").val(\"登录\");\n                    $(\"#loginButton\").removeAttr(\"disabled\");\n                }\n            });\n        })\n        window.gt = captchaObj;\n    };\n\n    // 获取极验\n    $.ajax({\n        url: '/user/geetestInit?t=' + (new Date()).getTime(), // 加随机数防止缓存\n        type: \"GET\",\n        dataType: 'json',\n        success: function (data) {\n            initGeetest({\n                gt: data.gt,\n                challenge: data.challenge,\n                new_captcha: data.new_captcha, // 用于宕机时表示是新验证码的宕机\n                offline: !data.success, // 表示用户后台检测极验服务器是否宕机，一般不需要关注\n                product: \"popup\", // 产品形式，包括：float，popup\n                width: \"100%\"\n            }, handler);\n        }\n    });\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/member-ban.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>删除的用户</title>\n</head>\n<style>\n    .table > tbody > tr > td {\n        text-align: center;\n    }\n</style>\n<body>\n<nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 用户中心 <span\n        class=\"c-gray en\">&gt;</span> 删除的用户<a class=\"btn btn-success radius r\" style=\"line-height:1.6em;margin-top:3px\"\n                                              href=\"javascript:location.replace(location.href);\" title=\"刷新\"><i\n        class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n<div class=\"page-container\">\n    <div class=\"cl pd-5 bg-1 bk-gray mt-20\"><span class=\"l\"><a href=\"javascript:;\" onclick=\"datadel()\"\n                                                               class=\"btn btn-danger radius\"><i class=\"Hui-iconfont\">&#xe6e2;</i> 批量删除</a> <a\n            href=\"javascript:;\" onclick=\"restoreAll()\" class=\"btn btn-primary radius\"><i\n            class=\"Hui-iconfont\">&#xe66b;</i> 批量还原</a></span></div>\n    <div class=\"mt-20\" style=\"margin-bottom: 70px\">\n        <table id=\"dataTable\" class=\"table table-border table-bordered table-hover table-bg table-sort\" width=\"100%\">\n            <thead>\n            <tr class=\"text-c\">\n                <th width=\"30\"><input type=\"checkbox\" class=\"minimal icheck_master\"/></th>\n                <th width=\"40\">ID</th>\n                <th width=\"80\">用户名</th>\n                <th width=\"40\">性别</th>\n                <th width=\"90\">手机</th>\n                <th width=\"110\">邮箱</th>\n                <th width=\"130\">地址</th>\n                <th width=\"100\">创建时间</th>\n                <th width=\"50\">状态</th>\n                <th width=\"100\">操作</th>\n            </tr>\n            </thead>\n        </table>\n    </div>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n<script type=\"text/javascript\">\n\n    /**\n     * 初始化 DataTables\n     */\n    var _dataTables;\n    $(function () {\n        const _columns = [\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    return '<input id=\"' + row.id + '\" type=\"checkbox\" class=\"minimal\" />';\n                }\n            },\n            {\"data\": \"id\"},\n            {\"data\": \"username\"},\n            {\n                \"data\": \"sex\",\n                render: function (data, type, row, meta) {\n                    if (data == null || data == \"\") {\n                        return \"用户未设置该信息！\";\n                    } else {\n                        return data;\n                    }\n                }\n            },\n            {\"data\": \"phone\"},\n            {\n                \"data\": \"email\",\n                render: function (data, type, row, meta) {\n                    if (data == null || data == \"\") {\n                        return \"用户未设置该信息！\";\n                    } else {\n                        return data;\n                    }\n                }\n            },\n            {\n                \"data\": \"address\",\n                render: function (data, type, row, meta) {\n                    if (data == null || data == \"\") {\n                        return \"用户未设置该信息！\";\n                    } else {\n                        return data;\n                    }\n                }\n            },\n            {\n                \"data\": \"created\",\n                render: function (data, type, row, meta) {\n                    return date(data);\n                }\n            },\n            {\n                \"data\": \"state\",\n                render: function (data, type, row, meta) {\n                    if (data == 1) {\n                        return \"<span class=\\\"label label-defant radius td-status\\\">已启用</span>\";\n                    } else if (data == 2) {\n                        return \"<span class=\\\"label label-warning radius td-status\\\">已被封禁</span>\";\n                    }\n                }\n            },\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    return \"<a style=\\\"text-decoration:none\\\" href=\\\"javascript:;\\\" onClick=\\\"member_restore(this,\" + row.id + \")\\\" title=\\\"还原\\\"><i class=\\\"Hui-iconfont\\\">&#xe66b;</i></a> <a title=\\\"彻底删除\\\" href=\\\"javascript:;\\\" onclick=\\\"member_del(this,\" + row.id + \")\\\" class=\\\"ml-5\\\" style=\\\"text-decoration:none\\\"><i class=\\\"Hui-iconfont\\\">&#xe6e2;</i></a>\";\n                }\n            }\n        ];\n\n        _dataTables = App.initDataTables(\"/member/ban/list\", _columns);\n    });\n\n\n    /**\n     * 解封会员\n     **/\n    function member_restore(obj, id) {\n        // 确认消息\n        var confirmMsg = '确定要解封ID为 '+ id +' 的会员吗？';\n\n        // 提交请求路径\n        var url = '/member/start/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 5, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 用户删除\n     **/\n    function member_del(obj, id) {\n        // 确认消息\n        var confirmMsg = '确定要要彻底删除ID为 '+ id +' 的会员吗？';\n\n        // 提交请求路径\n        var url = '/member/delete/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 5, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 批量删除\n     */\n    function datadel() {\n        // 请求路径\n        var url = \"/member/delete/\";\n\n        // 请求成功执行方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon:1, time:1000});\n        }\n\n        App.deleteMulti(url, successMethod);\n    }\n\n    /**\n     * 批量还原\n     * @param obj\n     * @param id\n     */\n    function restoreAll(obj, id) {\n        // 请求路径\n        var url = \"/member/start/\";\n\n        // 请求成功执行方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon:1, time:1000});\n        }\n\n        App.deleteMulti(url, successMethod);\n    }\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/member-form.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!--_meta 作为公共模版分离出去-->\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n\n    <title>添加用户</title>\n</head>\n<body>\n<article class=\"page-container\">\n    <form class=\"form form-horizontal\" id=\"validate-form\">\n        <input id=\"id\" name=\"id\" type=\"hidden\"/>\n        <input id=\"address\" name=\"address\" type=\"hidden\"/>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>用户名：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"\" id=\"username\" name=\"username\">\n            </div>\n        </div>\n        <div class=\"row cl password\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>设置密码：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"password\" class=\"input-text\" autocomplete=\"off\" value=\"\" placeholder=\"\" id=\"password\"\n                       name=\"password\">\n            </div>\n        </div>\n        <div class=\"row cl password\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>确认密码：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"password\" class=\"input-text\" autocomplete=\"off\" placeholder=\"\" id=\"password2\"\n                       name=\"password2\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>手机：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"\" id=\"phone\" name=\"phone\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>邮箱：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" class=\"input-text\" placeholder=\"@\" name=\"email\" id=\"email\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\">头像：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <span class=\"btn-upload\">\n                    <input id=\"file\" name=\"file\" type=\"hidden\"/>\n                    <img id=\"fileImg\" width=\"140\" height=\"140\" src=\"/static/assets/icon/avatar.png\" alt=\"...\" class=\"round\">\n                    <a href=\"javascript:void(0);\" class=\"btn btn-primary radius upload-btn\"><i\n                            class=\"Hui-iconfont\">&#xe642;</i> 上传头像</a>\n                    <input type=\"file\" id=\"fileBtn\" name=\"userFile\" accept='image/gif,image/jpeg,image/jpg,image/png,image/svg' class=\"input-file\" onchange=\"upload()\">\n                </span>\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <div class=\"col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-3\">\n                <input id=\"saveButton\" class=\"btn btn-primary radius\" type=\"submit\" value=\"&nbsp;&nbsp;提交&nbsp;&nbsp;\">\n            </div>\n        </div>\n    </form>\n</article>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- AjaxFileUpload -->\n<script type=\"text/javascript\" src=\"/static/assets/plugins/ajaxfileupload/ajaxfileupload.js\"></script>\n\n<script type=\"text/javascript\">\n\n    var id = parent.Id;\n\n    if (id == \"\") {\n        id = 0;\n        $(\"#id\").val(0);\n    }\n\n    // 编辑，隐藏密码\n    if (id != \"\") {\n        $(\"#id\").val(id);\n        $(\".password\").hide();\n    }\n\n    // 获取父页面的值\n    $(\"#username\").val(parent.username);\n    $(\"#phone\").val(parent.phone);\n    $(\"#email\").val(parent.email);\n    $(\"#description\").val(parent.description);\n    $(\"#phone\").val(parent.phone);\n\n    if (parent.sex == '男') {\n        $(\"#sex-1\").attr('checked', 'checked');\n        radioCheck();\n    } else if (parent.sex == '女') {\n        $(\"#sex-2\").attr('checked', 'checked');\n        radioCheck();\n    } else if (parent.sex == '保密') {\n        $(\"#sex-3\").attr('checked', 'checked');\n        radioCheck();\n    }\n    if (parent.file != \"\") {\n        $(\"#file\").val(parent.file);\n        $(\"#fileImg\").attr(\"src\", parent.file);\n    }\n\n    /**\n     * iCheck 美化单选按钮\n     **/\n    function radioCheck() {\n        $('.skin-minimal input').iCheck({\n            checkboxClass: 'icheckbox-blue',\n            radioClass: 'iradio-blue',\n            increaseArea: '20%'\n        });\n    }\n\n    /**\n     * 文本输入限制\n     */\n    $(\".textarea\").Huitextarealength({\n        minlength: 0,\n        maxlength: 100\n    });\n\n    /**\n     * 上传头像\n     **/\n    function upload() {\n        $.ajaxFileUpload({\n            url: 'upload',\n            type: 'post',\n            dataType: 'json',\n            fileElementId: 'fileBtn',\n            success: function (data) {\n                if (data.status == 200) {\n                    $(\"#file\").val(data.imagePath);\n                    $(\"#fileImg\").attr(\"src\", data.imagePath);\n                } else {\n                    layer.alert(data.message, {title: \"错误信息\", icon: 2});\n                }\n            },\n            error: function () {\n                layer.alert(ERROR_REQUEST_MESSAGE, {title: \"错误信息\", icon: 2});\n            }\n        })\n    }\n\n    $(function () {\n        /**\n         * 初始化 iCheck\n         */\n        radioCheck();\n\n\n        $(\"#validate-form\").validate({\n            ignore: \":hidden\", //不验证的元素\n            rules: {\n                username: {\n                    required: true,\n                    minlength: 2,\n                    maxlength: 16,\n                    remote: \"/member/username?id=\" + id\n                },\n                password: {\n                    required: true,\n                    minlength: 6,\n                },\n                password2: {\n                    required: true,\n                    minlength: 6,\n                    equalTo: \"#password\"\n                },\n                phone: {\n                    required: true,\n                    isMobile: true,\n                    remote: \"/member/phone?id=\" + id\n                },\n                email: {\n                    required: true,\n                    email: true,\n                    remote: \"/member/email?id=\" + id\n                },\n                sex: {\n                    required: true,\n                },\n                province: {\n                    required: true,\n                }\n            },\n            messages: {\n                username: {\n                    required: \"请填写用户名\",\n                    remote: \"该用户名已被注册\"\n                },\n                password: {\n                    required: \"请填写密码\",\n                },\n                password2: {\n                    required: \"请确认密码\",\n                    equalTo: \"两次密码输入不一致\"\n                },\n                phone: {\n                    required: \"请输入手机号\",\n                    isMobile: \"请输入正确的手机格式\",\n                    remote: \"该手机号已被注册\"\n                },\n                email: {\n                    required: \"请输入邮箱\",\n                    remote: \"该邮箱已被注册\"\n                },\n                sex: {\n                    required: \"请输入性别\"\n                },\n                province: {\n                    required: \"请选择所在城市\"\n                }\n            },\n            submitHandler: function (form) {\n                var fileVal = $(\"#file\").val();\n                if (fileVal == null || fileVal == \"\") {\n                    layer.msg(\"请上传头像\", {icon: 1, time: 3000});\n                    return false;\n                }\n                var province = $(\"#province\").find(\"option:selected\").text();\n                var city = $(\"#city\").find(\"option:selected\").text();\n                var district = $(\"#district\").find(\"option:selected\").text();\n                $(\"#address\").val(province + \" \" + city + \" \" + district);\n                var index = layer.load(3);\n                $(form).ajaxSubmit({\n                    url: \"/member/save\",\n                    type: \"POST\",\n                    success: function (data) {\n                        layer.close(index);\n                        if (data.status == 200) {\n                            if (parent.location.pathname != '/') {\n                                parent.refresh();\n                                parent.App.msgSuccess(data.message);\n                                var index = parent.layer.getFrameIndex(window.name);\n                                parent.layer.close(index);\n                            } else {\n                                layer.confirm('添加成功!', {\n                                    btn: ['确认'], icon: 1\n                                }, function () {\n                                    var index = parent.layer.getFrameIndex(window.name);\n                                    parent.layer.close(index);\n                                });\n                            }\n                        } else {\n                            layer.alert(data.message, {title: '错误信息', icon: 2});\n                        }\n                    },\n                    error: function () {\n                        layer.close(index);\n                        layer.alert(ERROR_REQUEST_MESSAGE, {title: \"错误信息\", icon: 2});\n                    }\n                });\n            }\n        });\n    });\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/member-list.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>用户管理</title>\n</head>\n<style>\n    .table > tbody > tr > td {\n        text-align: center;\n    }\n</style>\n<body>\n<nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 用户中心 <span\n        class=\"c-gray en\">&gt;</span> 用户管理 <a id=\"btn-refresh\" class=\"btn btn-success radius r\"\n                                              style=\"line-height:1.6em;margin-top:3px\"\n                                              href=\"javascript:location.replace(location.href);\" title=\"刷新\"><i\n        class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n<div class=\"page-container\">\n    <div class=\"cl pd-5 bg-1 bk-gray mt-20\">\n        <span class=\"l\">\n            <a href=\"javascript:;\" onclick=\"datadel()\" class=\"btn btn-danger radius\"><i\n                    class=\"Hui-iconfont\">&#xe6e2;</i> 批量删除</a>\n            <a href=\"javascript:;\" onclick=\"member_add('添加用户','member-form')\" class=\"btn btn-primary radius\"><i\n                    class=\"Hui-iconfont\">&#xe600;</i> 添加用户</a>\n        </span>\n    </div>\n    <div class=\"mt-20\" style=\"margin-bottom: 70px\">\n        <table id=\"dataTable\" class=\"table table-border table-bordered table-hover table-bg table-sort\" width=\"100%\">\n            <thead>\n            <tr class=\"text-c\">\n                <th width=\"30\"><input type=\"checkbox\" class=\"minimal icheck_master\"/></th>\n                <th width=\"40\">ID</th>\n                <th width=\"80\">用户名</th>\n                <th width=\"90\">手机</th>\n                <th width=\"100\">邮箱</th>\n                <th width=\"90\">创建时间</th>\n                <th width=\"90\">更新时间</th>\n                <th width=\"50\">状态</th>\n                <th width=\"110\">操作</th>\n            </tr>\n            </thead>\n        </table>\n    </div>\n</div>\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<script type=\"text/javascript\">\n\n    /**\n     * 初始化 DataTables\n     */\n    var _dataTables;\n    $(function () {\n        const _columns = [\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    return '<input id=\"' + row.id + '\" type=\"checkbox\" class=\"minimal\" />';\n                }\n            },\n            {\"data\": \"id\"},\n            {\"data\": \"username\"},\n            {\"data\": \"phone\"},\n            {\n                \"data\": \"email\",\n                render: function (data, type, row, meta) {\n                    if (data == null || data == \"\") {\n                        return \"用户未设置该信息！\";\n                    } else {\n                        return data;\n                    }\n                }\n            },\n            {\n                \"data\": \"created\",\n                render: function (data, type, row, meta) {\n                    return date(data);\n                }\n            },\n            {\n                \"data\": \"updated\",\n                render: function (data, type, row, meta) {\n                    return date(data);\n                }\n            },\n            {\n                \"data\": \"state\",\n                render: function (data, type, row, meta) {\n                    if (data == 1) {\n                        return \"<span class=\\\"label label-defant radius td-status\\\">已启用</span>\";\n                    } else if (data == 2) {\n                        return \"<span class=\\\"label label-warning radius td-status\\\">已被封禁</span>\";\n                    }\n                }\n            },\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    if(row.state == 1){\n                        return \"<a id=\\\"td-manage\\\" style=\\\"text-decoration:none\\\" onClick=\\\"member_ban(this,\"+row.id+\")\\\" href=\\\"javascript:;\\\" title=\\\"封禁\\\"><i class=\\\"Hui-iconfont\\\">&#xe60e;</i></a> <a title=\\\"编辑\\\" href=\\\"javascript:;\\\" onclick=\\\"member_edit('编辑','member-form',\"+row.id+\")\\\" class=\\\"ml-5\\\" style=\\\"text-decoration:none\\\"><i class=\\\"Hui-iconfont\\\">&#xe6df;</i></a> <a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"change_password('修改密码','change-password',\"+row.id+\",'600','270')\\\" href=\\\"javascript:;\\\" title=\\\"修改密码\\\"><i class=\\\"Hui-iconfont\\\">&#xe63f;</i></a> <a title=\\\"删除\\\" href=\\\"javascript:;\\\" onclick=\\\"member_del(this,\"+row.id+\")\\\" class=\\\"ml-5\\\" style=\\\"text-decoration:none\\\"><i class=\\\"Hui-iconfont\\\">&#xe6e2;</i></a>\";\n                    } else{\n                        return \"<a id=\\\"td-manage\\\" style=\\\"text-decoration:none\\\" onClick=\\\"member_start(this,\"+row.id+\")\\\" href=\\\"javascript:;\\\" title=\\\"解封\\\"><i class=\\\"Hui-iconfont\\\">&#xe605;</i></a> <a title=\\\"编辑\\\" href=\\\"javascript:;\\\" onclick=\\\"member_edit('编辑','member-form',\"+row.id+\")\\\" class=\\\"ml-5\\\" style=\\\"text-decoration:none\\\"><i class=\\\"Hui-iconfont\\\">&#xe6df;</i></a> <a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"change_password('修改密码','change-password',\"+row.id+\",'600','270')\\\" href=\\\"javascript:;\\\" title=\\\"修改密码\\\"><i class=\\\"Hui-iconfont\\\">&#xe63f;</i></a> <a title=\\\"删除\\\" href=\\\"javascript:;\\\" onclick=\\\"member_del(this,\"+row.id+\")\\\" class=\\\"ml-5\\\" style=\\\"text-decoration:none\\\"><i class=\\\"Hui-iconfont\\\">&#xe6e2;</i></a>\";\n                    }\n                }\n            }\n        ];\n\n        _dataTables = App.initDataTables(\"/member/list/\", _columns);\n    });\n\n    /**\n     * 封禁会员\n     **/\n    function member_ban(obj, id) {\n        // 确认消息\n        var confirmMsg = '确定封禁ID为 '+ id +' 的会员吗？';\n\n        // 提交请求路径\n        var url = '/member/ban/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 5, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 解封会员\n     **/\n    function member_start(obj, id) {\n        // 确认消息\n        var confirmMsg = '确定解封ID为 '+ id +' 的会员吗？';\n\n        // 提交请求路径\n        var url = '/member/start/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 5, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 初始化会员数据\n     **/\n    var Id = \"\", username = \"\", phone = \"\", email = \"\", description = \"\", sex = \"\", address = \"\", file = \"\";\n\n    /**\n     * 添加会员\n     **/\n    function member_add(title, url) {\n        // 会员数据设置为空值\n        Id = \"\", username = \"\", phone = \"\", email = \"\", description = \"\", sex = \"\", address = \"\", file = \"\";\n        App.openAndFull(title, url);\n    }\n\n    /**\n     * 编辑会员\n     **/\n    function member_edit(title, url, id) {\n        Id = id;\n        var table = $('.table').DataTable();\n        $('.table tbody').on('click', 'tr', function () {\n            username = table.row(this).data().username;\n            phone = table.row(this).data().phone;\n            email = table.row(this).data().email;\n            description = table.row(this).data().description;\n            sex = table.row(this).data().sex;\n            address = table.row(this).data().address;\n            file = table.row(this).data().file;\n        });\n        App.openAndFull(title, url);\n    }\n\n    /**\n     * 修改密码\n     **/\n    function change_password(title, url, id, w, h) {\n        Id = id;\n        var table = $('.table').DataTable();\n        $('.table tbody').on('click', 'tr', function () {\n            username = table.row(this).data().username;\n        });\n        layer_show(title, url, w, h);\n    }\n\n    /**\n     * 删除会员\n     **/\n    function member_del(obj, id) {\n        // 确认消息\n        var confirmMsg = '确定删除ID为 '+ id +' 的会员吗？';\n\n        // 提交请求路径\n        var url = '/member/delete/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 5, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 批量删除\n     */\n    function datadel() {\n        // 请求路径\n        var url = \"/member/delete/\";\n\n        // 请求成功执行方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon:1, time:1000});\n        }\n\n        App.deleteMulti(url, successMethod);\n    }\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/order-deliver.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>发货</title>\n</head>\n<body>\n<article class=\"page-container\">\n    <form class=\"form form-horizontal\" id=\"validate-form\">\n        <input type=\"text\" hidden id=\"orderId\" name=\"orderId\">\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>快递名称：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <select id=\"shippingName\" class=\"select\" name=\"shippingName\" size=\"1\">\n\n                </select>\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>快递单号：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" class=\"input-text\" autocomplete=\"off\" value=\"\" placeholder=\"\" id=\"shippingCode\"\n                       name=\"shippingCode\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <div class=\"col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-3\">\n                <input id=\"saveButton\" class=\"btn btn-primary radius\" type=\"submit\" value=\"提交\">\n            </div>\n        </div>\n    </form>\n</article>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n<script type=\"text/javascript\">\n\n    // 初始化快递数据\n    $(\"#orderId\").val(parent.orderId);\n    $.ajax({\n        url: '/express/list',\n        type: 'GET',\n        success: function (data) {\n            var i = 0;\n            for (i = 0; i < data.data.length; i++) {\n                $(\"#shippingName\").append(\"<option value='\" + data.data[i].expressName + \"'>\" + data.data[i].expressName + \"</option>\");\n            }\n        }\n    })\n\n    /**\n     * 提交成功后执行的方法\n     * */\n    function successMethod() {\n        parent.refresh();\n        parent.App.msgSuccess(\"发货成功!\");\n        var index = parent.layer.getFrameIndex(window.name);\n        parent.layer.close(index);\n    }\n    Validate.validate('/order/deliver', \"\", successMethod);\n</script>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/order-list.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>订单列表</title>\n\n</head>\n<style>\n    .table > tbody > tr > td {\n        text-align: center;\n    }\n</style>\n<body>\n\n<div>\n    <nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 订单管理 <span\n            class=\"c-gray en\">&gt;</span> 订单列表 <a class=\"btn btn-success radius r\"\n                                                  style=\"line-height:1.6em;margin-top:3px\"\n                                                  href=\"javascript:location.replace(location.href);\" title=\"刷新\"><i\n            class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n    <form class=\"page-container\">\n        <div class=\"cl pd-5 bg-1 bk-gray mt-20\">\n            <span class=\"l\">\n                <a href=\"javascript:;\" onclick=\"deleteMulti()\" class=\"btn btn-danger radius\"><i class=\"Hui-iconfont\">&#xe6e2;</i> 批量删除</a>\n                <a href=\"javascript:;\" onclick=\"orderPrint()\" class=\"btn btn-primary radius\"><i class=\"Hui-iconfont\">&#xe652;</i> 订单打印</a>\n            </span>\n            <span class=\"l\" style=\"margin-top: 5px;margin-left: 1200px;\">\n              <select class=\"select\" size=\"1\" id=\"orderType\" style=\"height:35px;width: 200px;\">\n                <option value=\"-1\" selected>所有订单</option>\n                <option value=\"0\">待付款订单</option>\n                <option value=\"2\">待发货订单</option>\n                <option value=\"4\">交易成功订单</option>\n                <option value=\"5\">交易失败订单</option>\n              </select>\n            </span>\n        </div>\n        <div class=\"mt-20\">\n            <div class=\"mt-20\" style=\"margin-bottom: 70px\">\n                <table id=\"dataTable\" class=\"table table-border table-bordered table-bg table-hover table-sort\"\n                       width=\"100%\">\n                    <thead>\n                    <tr class=\"text-c\">\n                        <th width=\"25\"><input type=\"checkbox\" class=\"minimal icheck_master\"/></th>\n                        <th width=\"80\">订单号</th>\n                        <th width=\"80\">支付金额(￥)</th>\n                        <th width=\"70\">用户账号</th>\n                        <th width=\"100\">物流号</th>\n                        <th width=\"100\">备注</th>\n                        <th width=\"100\">创建时间</th>\n                        <th width=\"100\">支付时间</th>\n                        <th width=\"100\">关闭时间</th>\n                        <th width=\"100\">完成时间</th>\n                        <th width=\"80\">订单状态</th>\n                        <th width=\"100\">操作</th>\n                    </tr>\n                    </thead>\n                </table>\n            </div>\n        </div>\n    </form>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<script type=\"text/javascript\">\n\n    /**\n     * 初始化 DataTables\n     */\n    var _dataTables;\n    $(function () {\n        const _columns = [\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    return '<input id=\"' + row.id + '\" type=\"checkbox\" class=\"minimal\" />';\n                }\n            },\n            {\"data\": \"id\"},\n            {\"data\": \"payment\"},\n            {\"data\": \"buyerNick\"},\n            {\n                \"data\": \"shippingCode\",\n                render: function (data, type, row, meta) {\n                    if (data == null || data == \"\") {\n                        return \"暂无物流信息！\";\n                    } else {\n                        return data;\n                    }\n                }\n            },\n            {\n                \"data\": \"buyerMessage\",\n                render: function (data, type, row, meta) {\n                    if (data == null || data == \"\") {\n                        return \"暂无买家备注信息！\"\n                    } else {\n                        return data;\n                    }\n                }\n            },\n            {\n                \"data\": \"created\",\n                render: function (data, type, row, meta) {\n                    return date(data);\n                }\n            },\n            {\n                \"data\": \"paymentTime\",\n                render: function (data, type, row, meta) {\n                    if (data == null) {\n                        if (row.status == 0) {\n                            return \"该买家还未支付!\";\n                        } else if (row.status == 5) {\n                            return \"交易已关闭！\";\n                        } else if (row.status == 6) {\n                            return \"交易失败！\";\n                        }\n                    } else {\n                        return date(data);\n                    }\n                }\n            },\n            {\n                \"data\": \"closeTime\",\n                render: function (data, type, row, meta) {\n                    if (data == null) {\n                        if (row.status == 4) {\n                            return \"交易成功！\";\n                        } else if (row.status == 6) {\n                            return \"交易失败！\";\n                        } else {\n                            return \"交易正在进行中！\";\n                        }\n                    } else {\n                        return date(data);\n                    }\n                }\n            },\n            {\n                \"data\": \"endTime\",\n                render: function (data, type, row, meta) {\n                    if (data == null) {\n                        if (row.status == 5) {\n                            return \"交易关闭！\";\n                        } else if (row.status == 6) {\n                            return \"交易失败！\";\n                        } else {\n                            return \"交易正在进行中！\";\n                        }\n                    } else {\n                        return date(data);\n                    }\n                }\n            },\n            {\n                \"data\": \"status\",\n                render: function (data, type, row, meta) {\n                    if (data == 0) {\n                        return \"<span class=\\\"label label-defant radius td-status\\\">待支付</span>\";\n                    } else if (data == 1) {\n                        return \"<span class=\\\"label label-warning radius td-status\\\">已支付</span>\";\n                    } else if (data == 2) {\n                        return \"<span class=\\\"label label-primary radius td-status\\\">待发货</span>\";\n                    } else if (data == 3) {\n                        return \"<span class=\\\"label label-secondary radius td-status\\\">已发货</span>\";\n                    } else if (data == 4) {\n                        return \"<span class=\\\"label label-success radius td-status\\\">交易成功</span>\";\n                    } else if (data == 5) {\n                        return \"<span class=\\\"label label-danger radius td-status\\\">交易关闭</span>\";\n                    } else if (data == 6) {\n                        return \"<span class=\\\"label label-defant radius td-status\\\">支付失败</span>\";\n                    } else {\n                        return \"<span class=\\\"label label-warning radius td-status\\\">其它态</span>\";\n                    }\n                }\n            },\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    return \"<a title=\\\"发货\\\" href=\\\"javascript:;\\\" onclick=\\\"order_deliver(\" + row.id + \", \"+ row.status +\")\\\" class=\\\"ml-5\\\" style=\\\"text-decoration:none\\\"><i class=\\\"Hui-iconfont\\\">&#xe603;</i></a>\" +\n                        \"<a title=\\\"取消订单\\\" href=\\\"javascript:;\\\" onclick=\\\"order_cancel(\" + row.id + \", \"+ row.status +\")\\\" class=\\\"ml-5\\\" style=\\\"text-decoration:none\\\"><i class=\\\"Hui-iconfont\\\">&#xe60b;</i></a>\" +\n                        \"<a title=\\\"删除\\\" href=\\\"javascript:;\\\" onclick=\\\"order_del(this,\" + row.id + \")\\\" class=\\\"ml-5\\\" style=\\\"text-decoration:none\\\"><i class=\\\"Hui-iconfont\\\">&#xe6e2;</i></a>\";\n                }\n            }\n        ];\n\n        _dataTables = App.initDataTables(\"/order/list/\", _columns);\n    });\n\n\n    var orderId = \"\";\n\n    function orderPrint() {\n        var _idArray = new Array();\n        // 获取全部 Checkbox 集合\n        var _checkbox = $('input[type=\"checkbox\"].minimal');\n\n        // 将选中的元素 ID 放入数组中\n        _checkbox.each(function () {\n            var _id = $(this).attr(\"id\");\n            if (_id != null && _id != \"undefine\" && $(this).is(\":checked\")) {\n                orderId = _id;\n                _idArray.push(_id);\n            }\n        });\n\n        // 判断用户是否选择了数据项\n        if (_idArray.length === 0) {\n            layer.msg('您还未勾选任何数据！', {icon: 5, time: 3000});\n            return;\n        }\n\n        // 判断是否只选择了一个数据项\n        if (_idArray.length > 1) {\n            layer.msg('只能选择一个订单！', {icon: 5, time: 3000});\n            return;\n        }\n\n        var index = layer.open({\n            type: 2,\n            title: '打印预览',\n            content: 'order-print'\n        });\n        layer.full(index);\n    }\n\n    /**\n     * 发货\n     **/\n    function order_deliver(id, status) {\n        if (status == 1 || status == 2) {\n            orderId = id;\n            layer_show(\"发货\", \"order-deliver\", 500, 280);\n        } else if (status == 0) {\n            layer.alert(\"订单还未付款\", {title: \"错误信息\", icon: 2});\n        } else if (status == 3 || status == 4) {\n            layer.alert(\"订单已发货\", {title: \"错误信息\", icon: 2});\n        } else if (status == 5) {\n            layer.alert(\"订单已关闭\", {title: \"错误信息\", icon: 2});\n        }\n    }\n\n    /**\n     * 备注\n     **/\n    var oldRemark = \"\";\n    function order_remark(message, id) {\n        oldRemark = message;\n        orderId = id;\n        layer_show(\"备注\", \"order-remark\", 500, 250);\n    }\n\n    /**\n     * 取消订单\n     **/\n    function order_cancel(id, status) {\n        if (status == 4) {\n            layer.alert(\"交易已成功，无法取消！\");\n            return;\n        } else if (status == 5) {\n            layer.alert(\"交易已经取消！\");\n            return;\n        } else if (status == 6) {\n            layer.alert(\"交易已经失败\");\n            return;\n        }\n\n        // 确认消息\n        var confirmMsg = '确定取消ID为 '+ id +' 的订单吗？';\n\n        // 提交请求路径\n        var url = '/order/cancel/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 1, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 删除订单\n     * */\n    function order_del(obj, id) {\n        // 确认消息\n        var confirmMsg = '确定删除ID为 '+ id +' 的订单吗？';\n\n        // 提交请求路径\n        var url = '/order/delete/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 1, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n\n    }\n\n    /**\n     * 批量删除\n     * */\n    function deleteMulti() {\n\n        // 请求路径\n        var url = \"/order/delete/\";\n\n        // 请求成功执行方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon:1, time:1000});\n        }\n\n        App.deleteMulti(url, successMethod);\n    }\n\n    /**\n     * 选择订单类型\n     */\n    $(\"#orderType\").on(\"change\",function(){\n        let type = $(\"#orderType\").val()\n\n        let param = {\n            \"status\": type\n        }\n\n        _dataTables.settings()[0].ajax.data = param\n        _dataTables.ajax.reload()\n    })\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/order-print.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>订单信息</title>\n</head>\n<style>\n    .title {\n        margin-bottom: 15px;\n    }\n\n    .item {\n        width: 24%;\n        text-align: left;\n        display: inline-block;\n        line-height: 30px;\n    }\n\n    .itemAdress {\n        width: 50%;\n        text-align: left;\n        display: inline-block;\n        line-height: 30px;\n    }\n</style>\n<body>\n<div class=\"page-container\">\n    <div id=\"print\">\n        <form class=\"form form-horizontal\">\n            <div>\n                <h3 class=\"text-c title\">YMall商城订单信息</h3>\n                <div class=\"item\">会员名称：<span id=\"customerName\"></span></div>\n                <div class=\"item\">下单时间：<span id=\"createTime\"></span></div>\n                <div class=\"item\">订单编号：<span id=\"orderCode\"></span></div>\n                <div class=\"item\">支付方式：<span id=\"payType\"></span></div>\n                <div class=\"item\">付款时间：<span id=\"payTime\"></span></div>\n                <div class=\"item\">发货时间：<span id=\"deliverTime\"></span></div>\n                <div class=\"item\">发货单号：<span id=\"expressId\"></span></div>\n                <div class=\"item\">收货人：<span id=\"receiver\"></span></div>\n                <div class=\"item\">手机：<span id=\"telephone\"></span></div>\n                <div class=\"itemAdress\">收货地址：<span id=\"expressAdress\"></span></div>\n            </div>\n        </form>\n\n        <div class=\"mt-20\">\n            <table class=\"table table-border table-bg table-bordered table-striped table-hover\">\n                <thead>\n                <tr class=\"text-c\">\n                    <th width=\"40\">商品名称</th>\n                    <th width=\"40\">商品ID号</th>\n                    <th width=\"20\">价格(￥)</th>\n                    <th width=\"10\">数量(件)</th>\n                    <th width=\"20\">小计(￥)</th>\n                </tr>\n                </thead>\n                <tbody id=\"products\">\n\n                </tbody>\n\n            </table>\n        </div>\n\n        <div class=\"text-r\" style=\"margin-top: 1vw\">\n            订单总金额：￥<span id=\"orderPriceAll\"></span>\n        </div>\n        <div class=\"text-l\">订单备注：<span id=\"remark\"></div>\n    </div>\n\n    <div class=\"row cl\" style=\"margin-top: 1vw\">\n        <div class=\"text-c\">\n            <input id=\"saveButton\" class=\"btn btn-primary radius\" onclick=\"print()\" value=\"打印\">\n        </div>\n    </div>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- jQuery print -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/jQuery.print.js\"></script>\n<script type=\"text/javascript\">\n    function print() {\n        jQuery('#print').print();\n    }\n\n    //加载数据\n    function successMethod(data) {\n        $(\"#customerName\").html(data.result.tbOrder.buyerNick);\n        $(\"#createTime\").html(date(data.result.tbOrder.created));\n        $(\"#orderCode\").html(data.result.tbOrder.id);\n        if (data.result.tbOrder.paymentType == 1) {\n            $(\"#payType\").html(\"在线支付\");\n        } else if (data.result.tbOrder.paymentType == 2) {\n            $(\"#payType\").html(\"货到付款\");\n        } else {\n            $(\"#payType\").html(\"未支付\");\n        }\n        if (data.result.tbOrder.consignTime == null) {\n            $(\"#deliverTime\").html(\"未发货\");\n        }\n        $(\"#deliverTime\").html(date(data.result.tbOrder.consignTime));\n        $(\"#expressId\").html(data.result.tbOrder.shippingCode);\n        $(\"#expressAdress\").html(data.result.tbOrderShipping.receiverAddress);\n        if (data.result.tbOrder.paymentTime == null) {\n            $(\"#payTime\").html(\"未付款\")\n        } else {\n            $(\"#payTime\").html(date(data.result.tbOrder.paymentTime));\n        }\n        $(\"#receiver\").html(data.result.tbOrderShipping.receiverName);\n        $(\"#telephone\").html(data.result.tbOrderShipping.receiverPhone);\n\n        var products = data.result.tbOrderItemList;\n        var i = 0;\n        for (i = 0; i < products.length; i++) {\n            $(\"#products\").append(\"<tr class='text-c'><td>\" + products[i].title + \"</td>\" +\n                \"<td>\" + products[i].itemId + \"</td><td>\" + products[i].price + \"</td><td>\" + products[i].num + \"</td>\" +\n                \"<td>\" + products[i].totalFee + \"</td></tr>\");\n        }\n        if (data.result.tbOrder.postFee == null || data.result.tbOrder.postFee == \"\") {\n            data.result.tbOrder.postFee = 0;\n        }\n        $(\"#expressCost\").html(data.result.tbOrder.postFee);\n        $(\"#orderPriceAll\").html(data.result.tbOrder.payment);\n        $(\"#remark\").html(data.result.tbOrder.buyerMessage);\n    }\n    App.ajax('/order/detail/' + parent.orderId, 'GET', successMethod);\n\n</script>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/product-category-add.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>添加产品分类</title>\n</head>\n<body>\n<div class=\"page-container\">\n    <form action=\"\" method=\"post\" class=\"form form-horizontal\" id=\"validate-form\">\n        <input type=\"text\" hidden class=\"input-text\" value=\"0\" id=\"parentId\" name=\"parentId\">\n        <input type=\"text\" hidden class=\"input-text\" value=\"true\" id=\"isParent\" name=\"isParent\">\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\">\n                <span class=\"c-red\">*</span>\n                分类名称：</label>\n            <div class=\"formControls col-xs-6 col-sm-6\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"\" id=\"name\" name=\"name\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>是否为父节点：</label>\n            <div class=\"formControls col-xs-6 col-sm-6\">\n                <div id=\"parentSwitch\" class=\"switch\" data-on-label=\"是\" data-on=\"info\" data-off-label=\"否\">\n                    <input type=\"checkbox\" checked />\n                </div>\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <div class=\"col-7 col-offset-4\">\n                <input id=\"saveButton\" class=\"btn btn-primary radius\" type=\"submit\" value=\"&nbsp;&nbsp;保存并提交&nbsp;&nbsp;\">\n            </div>\n        </div>\n    </form>\n</div>\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- Validate -->\n<script type=\"text/javascript\" src=\"/static/assets/app/validate.js\"></script>\n<script type=\"text/javascript\">\n\n    /**\n     * 备注文本输入限制\n     */\n    $(\".textarea\").Huitextarealength({\n        minlength:0,\n        maxlength:100\n    });\n\n    /**\n     * 判断是否是父节点\n     */\n    if(!parent.isRoot){\n        $('#parentSwitch').bootstrapSwitch('setState', false);\n        $(\"#isParent\").val(0);\n    }else{\n        $('#parentSwitch').bootstrapSwitch('setState', true);\n        $(\"#isParent\").val(1);\n    }\n\n    /**\n     * 若父节点节点不为空\n     */\n    if(parent.id != \"\"){\n        $(\"#parentId\").val(parent.id);\n    }\n\n    /**\n     * 同步更新节点值\n     */\n    $('#parentSwitch').on('switch-change', function (e, data) {\n        if(data.value == true){\n            $(\"#isParent\").val(true);\n        }else{\n            $(\"#isParent\").val(false);\n        }\n    });\n\n    /**\n     * 验证成功触发的方法\n     *\n     * @param data\n     */\n    function successMethod(data) {\n        parent.App.initZtree(\"/item/cat/list/-1\", parent.callback);\n        parent.App.msgSuccess(data.message);\n        var index = parent.layer.getFrameIndex(window.name);\n        parent.layer.close(index);\n    }\n    Validate.validate(\"/item/cat/save\", \"\", successMethod);\n\n</script>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/product-category.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <!-- ZTree -->\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"/static/assets/lib/zTree/v3/css/zTreeStyle/zTreeStyle.css\" type=\"text/css\"/>\n    <title>商品分类</title>\n</head>\n<body>\n<nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 商品管理 <span class=\"c-gray en\">&gt;</span> 商品分类 <a class=\"btn btn-success radius r\" style=\"line-height:1.6em;margin-top:3px\" href=\"javascript:location.replace(location.href);\" title=\"刷新\" ><i class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n<div style=\"margin-left: 1vw;margin-right: 1vw\" class=\"cl pd-5 bg-1 bk-gray mt-20\">\n    <span class=\"l\">\n        <a href=\"javascript:;\" onclick=\"delSingle()\" class=\"btn btn-danger radius\"><i class=\"Hui-iconfont\">&#xe6e2;</i> 删除所选分类</a>\n        <a class=\"btn btn-primary radius\" onclick=\"categoryAdd('添加子级分类','product-category-add')\" href=\"javascript:;\"><i class=\"Hui-iconfont\">&#xe600;</i> 添加子级分类</a>\n        <a class=\"btn btn-primary radius\" onclick=\"categoryRootAdd('添加根节点分类','product-category-add')\" href=\"javascript:;\"><i class=\"Hui-iconfont\">&#xe600;</i> 添加根节点分类</a>\n    </span>\n</div>\n<table class=\"table\">\n    <tr>\n        <td style=\"padding-left: 4vw\" width=\"200\" class=\"va-t\"><ul id=\"myTree\" class=\"ztree\"></ul></td>\n        <td class=\"va-t\">\n            <div class=\"page-container\">\n                <form action=\"\" method=\"post\" class=\"form form-horizontal\" id=\"validate-form\">\n                    <input type=\"text\" hidden class=\"input-text\" id=\"id\" name=\"id\">\n                    <input type=\"text\" hidden class=\"input-text\" value=\"0\" id=\"parentId\" name=\"parentId\">\n                    <input type=\"text\" hidden class=\"input-text\" value=\"1\" id=\"status\" name=\"status\">\n                    <input type=\"text\" hidden class=\"input-text\" value=\"true\" id=\"isParent\" name=\"isParent\">\n                    <div class=\"row cl\">\n                        <label class=\"form-label col-xs-4 col-sm-2\">\n                            <span class=\"c-red\">*</span>\n                            分类名称：</label>\n                        <div class=\"formControls col-xs-6 col-sm-6\">\n                            <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"\" id=\"name\" name=\"name\">\n                        </div>\n                    </div>\n                    <div class=\"row cl\">\n                        <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>是否为父节点：</label>\n                        <div class=\"formControls col-xs-6 col-sm-6\">\n                            <div id=\"parentSwitch\" class=\"switch\" data-on-label=\"是\" data-on=\"info\" data-off-label=\"否\">\n                                <input type=\"checkbox\" checked />\n                            </div>\n                        </div>\n                    </div>\n                    <div class=\"row cl\" id=\"choose-parent\">\n                        <label class=\"form-label col-xs-4 col-sm-2\">选择父节点：</label>\n                        <div class=\"formControls col-xs-8 col-sm-9\">\n                            <input type=\"text\" onclick='App.show(\"选择父节点分类\",\"choose-parent-category\",300,510)' readonly class=\"input-text\" value=\"\" placeholder=\"请点击选择其父节点分类\" id=\"parentName\" name=\"parentName\" style=\"width:48%\">\n                            <input type=\"button\" onclick='App.show(\"选择父节点分类\",\"choose-parent-category\",300,510)' class=\"btn btn-secondary radius\" value=\"选择父节点分类\">\n                        </div>\n                    </div>\n                    <div class=\"row cl\">\n                        <label class=\"form-label col-xs-4 col-sm-2\">\n                            <span class=\"c-red\">*</span>\n                            排序优先值：</label>\n                        <div class=\"formControls col-xs-6 col-sm-6\">\n                            <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"请输入0~9999，值越小排序越前\" id=\"sortOrder\" name=\"sortOrder\">\n                        </div>\n                    </div>\n                    <div class=\"row cl\">\n                        <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>是否启用：</label>\n                        <div class=\"formControls col-xs-6 col-sm-6\">\n                            <div id=\"mySwitch\" class=\"switch\" data-on-label=\"启用\" data-on=\"info\" data-off-label=\"禁用\">\n                                <input type=\"checkbox\" checked />\n                            </div>\n                        </div>\n                    </div>\n                    <div class=\"row cl\">\n                        <div class=\"col-9 col-offset-2\">\n                            <input class=\"btn btn-primary radius\" type=\"submit\" value=\"&nbsp;&nbsp;提交修改&nbsp;&nbsp;\">\n                        </div>\n                    </div>\n                </form>\n            </div>\n        </td>\n    </tr>\n</table>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- ZTree -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/zTree/v3/js/jquery.ztree.all-3.5.js\"></script>\n\n<!-- Validate -->\n<script type=\"text/javascript\" src=\"/static/assets/app/validate.js\"></script>\n\n\n<script type=\"text/javascript\">\n\n    /**\n     * 备注文本框输入限制\n     * */\n    $(\".textarea\").Huitextarealength({\n        minlength:0,\n        maxlength:100\n    });\n\n    // 初始值\n    var isParent = false,id = \"\",name = \"\";\n\n    // 加载中...\n    var index = layer.load(3);\n\n\n    /**\n     * ZTree 回调函数\n     * */\n    var callback = {\n        onAsyncSuccess: function(){\n            layer.close(index);\n        },\n        beforeClick: function(treeId, treeNode) {\n            $(\"#name\").val(treeNode.name);\n            $(\"#id\").val(treeNode.id);\n            $(\"#sortOrder\").val(treeNode.sortOrder);\n            $(\"#parentId\").val(treeNode.pid);\n            $(\"#parentName\").val(treeNode.parentName);\n            if($(\"#parentId\").val() == \"\"){\n                $(\"#parentId\").val(0);\n            }\n            if(treeNode.pId != 0){\n                $(\"#parentName\").val(treeNode.getParentNode().name);\n            }\n            changeSwitch2(treeNode.status);\n            id = treeNode.id;\n            name = treeNode.name;\n\n            if (treeNode.isParent) {\n                isParent = true;\n                changeSwitch1(1);\n                return false;\n            } else {\n                isParent = false;\n                changeSwitch1(0);\n                return true;\n            }\n        }\n    };\n    App.initZtree(\"/item/cat/list/-1\" , callback);\n\n    /**\n     * 是否为父节点\n     * */\n    function changeSwitch1(value){\n        if(value == 1){\n            $('#parentSwitch').bootstrapSwitch('setState', true);\n        }else{\n            $('#parentSwitch').bootstrapSwitch('setState', false);\n        }\n    }\n\n    /**\n     * 同步更新父节点值\n     * */\n    $('#parentSwitch').on('switch-change', function (e, data) {\n        if(data.value == true){\n            $(\"#isParent\").val(true);\n        }else{\n            $(\"#isParent\").val(false);\n        }\n    });\n\n    /**\n     * 是否禁用\n     * */\n    function changeSwitch2(value){\n        if(value == 1){\n            $('#mySwitch').bootstrapSwitch('setState', true);\n        }else{\n            $('#mySwitch').bootstrapSwitch('setState', false);\n        }\n    }\n\n    /**\n     * 同步更新禁用节点值\n     * */\n    $('#mySwitch').on('switch-change', function (e, data) {\n        if(data.value==true){\n            $(\"#status\").val(1);\n        }else{\n            $(\"#status\").val(0);\n        }\n    });\n\n\n    /**\n     * 提交之前触发的方法\n     */\n    function beforeMethod() {\n        if (id == \"\") {\n            layer.alert(\"请选择要修改的分类\", {title: \"警告\", icon: 2});\n            return false;\n        }\n        return true;\n    }\n    /**\n     * 验证成功触发的方法\n     *\n     * @param data\n     */\n    function successMethod(data) {\n        layer.alert(data.message, {icon: 1}, function (index) {\n            App.initZtree(\"/item/cat/list/-1\", callback);\n            layer.close(index);\n        });\n    }\n    Validate.validate(\"/item/cat/save\", beforeMethod, successMethod);\n\n\n\n    var isRoot = false;\n\n    /**\n     * 添加子分类\n     * */\n    function categoryAdd(title, url) {\n        if (!isParent) {\n            layer.alert('请点击选择一个父级分类', {title: '错误信息', icon: 0});\n            return ;\n        }\n        isRoot = false;\n        layer_show(title, url, 700, 350);\n    }\n\n\n    /**\n     * 添加根节点分类\n     * */\n    function categoryRootAdd(title, url) {\n        id = \"\";\n        isRoot = true;\n        layer_show(title, url, 700, 350);\n    }\n\n    /**\n    * 删除单个分类\n    */\n    function delSingle() {\n        if(id == -1){\n            layer.alert('请点击选择要删除的分类! ', {title: '错误信息',icon: 0});\n            return;\n        }\n\n        // 确认消息\n        var confirmMsg = '确定要删除所选的\\''+ name +'\\'分类吗？该操作会删除所有子分类！！！';\n\n        // 提交请求\n        var url = '/item/cat/del/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            App.initZtree(\"/item/cat/list/-1\", callback);\n            App.msgSuccess(data.message);\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 设置父类 id 和名称\n     * @param parentId\n     * @param parentName\n     */\n    function setParentId(parentId, parentName) {\n        $(\"#parentId\").val(parentId);\n        $(\"#parentName\").val(parentName);\n    }\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/product-form.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<%\n    request.setCharacterEncoding(\"UTF-8\");\n    String htmlData = request.getParameter(\"detail\") != null ? request.getParameter(\"detail\") : \"\";\n%>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n\n    <!-- DropZone -->\n    <link rel=\"stylesheet\" href=\"/static/assets/plugins/dropzone/min/dropzone.min.css\" />\n    <link rel=\"stylesheet\" href=\"/static/assets/plugins/dropzone/min/basic.min.css\" />\n\n    <!-- wangEditor -->\n    <link rel=\"stylesheet\" href=\"/static/assets/plugins/wangEditor/wangEditor.min.css\"/>\n    <link rel=\"stylesheet\" href=\"/static/assets/plugins/wangEditor/wangEditor-fullscreen-plugin.css\"/>\n</head>\n<body>\n<div class=\"page-container\">\n    <%=htmlData%>\n    <form name=\"product-add\" action=\"\" method=\"post\" class=\"form form-horizontal\" id=\"validate-form\">\n        <input type=\"hidden\" id=\"id\" name=\"id\"/>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>产品标题：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"\" name=\"title\" id=\"title\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>简介描述：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"\" name=\"sellPoint\" id=\"sellPoint\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>商品分类：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" hidden class=\"input-text\" id=\"cid\" name=\"cid\" >\n                <input type=\"text\" onclick='App.show(\"选择商品分类\",\"choose-category\",300,510)' readonly class=\"input-text\" value=\"\" placeholder=\"请点击选择按钮选择商品分类\" id=\"cname\" name=\"cname\" style=\"width:50%\">\n                <input type=\"button\" onclick='App.show(\"选择商品分类\",\"choose-category\",300,510)' class=\"btn btn-secondary radius\" value=\"选择类别\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>产品展示价格：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" id=\"price\" name=\"price\" placeholder=\"请输入正确金额\" value=\"\" class=\"input-text\" style=\"width:50%\">\n                元</div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>库存数量：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" name=\"num\" id=\"num\" placeholder=\"0~99999\" value=\"\" class=\"input-text\" style=\"width:50%\">\n                件</div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>购买限制数量：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" name=\"limitNum\" id=\"limitNum\" placeholder=\"0~999\" value=\"\" class=\"input-text\" style=\"width:50%\">\n                件</div>\n        </div>\n        <input type=\"text\" name=\"image\" id=\"image\" hidden/>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\"><span class=\"c-red\">*</span>展示缩略图片上传：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <div id=\"dropz\" class=\"dropzone\"></div>\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-2\">商品详情：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <div id=\"editor\"></div>\n                <textarea id=\"detail\" name=\"detail\" style=\"visibility:hidden;\"></textarea>\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <div class=\"col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-2\">\n                <button id=\"saveButton\" class=\"btn btn-primary radius\" type=\"submit\"><i class=\"Hui-iconfont\">&#xe632;</i> 保存并发布</button>\n                <button onClick=\"layer_close();\" class=\"btn btn-default radius\" type=\"button\">&nbsp;&nbsp;取消&nbsp;&nbsp;</button>\n            </div>\n        </div>\n    </form>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- DropZone -->\n<script src=\"/static/assets/plugins/dropzone/dropzone.js\"></script>\n\n<!-- wangEditor -->\n<script src=\"/static/assets/plugins/wangEditor/wangEditor.min.js\"></script>\n<script src=\"/static/assets/plugins/wangEditor/wangEditor-fullscreen-plugin.js\"></script>\n\n<script type=\"text/javascript\">\n\n    var editor;\n\n    // 获取父窗口 ID 值\n    var id = parent.getId();\n\n    // 编辑商品\n    var images = parent.images;\n    var imageArray = new Array();\n    if (images != \"\") {\n        $(\"#image\").val(images);\n        imageArray = images.split(\",\");\n    }\n    function successMethod2(data) {\n        $(\"#id\").val(data.result.id);\n        $(\"#title\").val(data.result.title);\n        $(\"#sellPoint\").val(data.result.sellPoint);\n        $(\"#price\").val(data.result.price);\n        $(\"#cname\").val(data.result.cname);\n        $(\"#cid\").val(data.result.cid);\n        $(\"#num\").val(data.result.num);\n        $(\"#limitNum\").val(data.result.limitNum);\n        $(\"#detail\").val(data.result.detail);\n        editor.txt.html(data.result.detail);\n    }\n    if (id != 0) {\n        App.ajax('/item/' + id, 'GET', successMethod2);\n    }\n\n    /**\n     * 设置 cid\n     * */\n    function setCid(cid) {\n        $(\"#cid\").val(cid);\n    }\n\n    /**\n     * 设置 cname\n     **/\n    function setCname(cname) {\n        $(\"#cname\").val(cname);\n    }\n\n    /**\n     * 初始化 Dropzone\n     */\n    Dropzone.autoDiscover = false;\n    let first = true;\n    var myDropzone = new Dropzone(\"#dropz\", {\n        url: \"/upload\", // 文件提交地址\n        method: \"post\",  // 也可用put\n        paramName: \"dropFile\", // 默认为file\n        maxFiles: 5,// 一次性上传的文件数量上限\n        maxFilesize: 10, // 文件大小，单位：MB\n        acceptedFiles: \".jpg,.gif,.png,.jpeg\", // 上传的类型\n        addRemoveLinks: true,\n        parallelUploads: 1,// 一次上传的文件数量\n        dictDefaultMessage: '拖动文件至此或者点击上传,最多上传5张！',\n        dictMaxFilesExceeded: \"您最多只能上传5个文件！\",\n        dictResponseError: '文件上传失败!',\n        dictInvalidFileType: \"文件类型只能是*.jpg,*.gif,*.png,*.jpeg。\",\n        dictFallbackMessage: \"浏览器不受支持\",\n        dictFileTooBig: \"文件过大上传文件最大支持.\",\n        dictRemoveLinks: \"删除\",\n        dictCancelUpload: \"取消\",\n        init: function () {\n            this.emit(\"initimage\", images); // 以逗号分开\n            this.on(\"success\", function (file, data) {\n                if (data.status == 200) {\n                    // 上传成功触发的事件\n                    if (imageArray.length == 0) {\n                        images = data.fileName;\n                        $(\"#image\").val(images);\n                    } else {\n                        images += \",\";\n                        images += data.fileName;\n                        $(\"#image\").val(images);\n                    }\n                    imageArray.push(file.name);\n                } else {\n                    layer.alert(data.message, {title: \"错误信息\", icon: 2});\n                }\n            });\n            this.on(\"removedfile\", function (file) {\n                for (let i = 0; i < imageArray.length; i++) {\n                    let imageStr = imageArray[i];\n                    let index = imageStr.indexOf(file.name);\n                    if (index > -1) {\n                        let imageArray1 = images.split(\",\");\n                        imageArray1.splice(i, 1);\n                        imageArray.splice(i, 1);\n                        images = imageArray1.toString();\n                        $(\"#image\").val(images);\n                    }\n                }\n            })\n        }\n    });\n\n    /**\n     * 初始化 wangEditor\n     */\n    initWangEditor();\n    function initWangEditor() {\n        var E = window.wangEditor;\n        editor = new E('#editor');\n        // 配置服务端地址\n        editor.customConfig.uploadImgServer = '/upload';\n        editor.customConfig.uploadFileName = 'editorFiles';\n        editor.customConfig.uploadImgMaxSize = 50 * 1024 * 1024\n        // 将 timeout 时间改为 3s\n        editor.customConfig.uploadImgTimeout = 200000\n        editor.create();\n        E.fullscreen.init('#editor');\n\n        $(\"#saveButton\").bind(\"click\", function () {\n            var detailHtml = editor.txt.html();\n            $(\"#detail\").val(detailHtml);\n        });\n    }\n\n    /**\n     * 表单提交之前执行的方法\n     * */\n    function beforeMethod() {\n        var image = $(\"#image\").val();\n        if (image == \"\") {\n            layer.alert('请上传展示缩略图片！', {title: '错误信息', icon: 0});\n            return false;\n        }\n        return true;\n    }\n    /**\n     * 提交成功后执行的方法\n     * */\n    function successMethod(data) {\n        parent.refresh();\n        parent.App.msgSuccess(data.message);\n        var index = parent.layer.getFrameIndex(window.name);\n        parent.layer.close(index);\n    }\n    Validate.validate('/item/save', beforeMethod, successMethod);\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/product-list.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>商品列表</title>\n    <!-- ZTree -->\n    <link rel=\"stylesheet\" href=\"/static/assets/lib/zTree/v3/css/zTreeStyle/zTreeStyle.css\" type=\"text/css\">\n    <!-- iCheck -->\n    <link rel=\"stylesheet\" href=\"/static/assets/plugins/iCheck/all.css\">\n</head>\n<style>\n    .table>tbody>tr>td{\n        text-align:center;\n    }\n</style>\n\n<body class=\"pos-r\">\n<div class=\"pos-a\" style=\"width:200px;left:0;top:0; bottom:0; height:100%; border-right:1px solid #e5e5e5; background-color:#f5f5f5; overflow:auto;\">\n    <ul style=\"margin-top: 15px;margin-left: 20px\"><i class=\"Hui-iconfont Hui-iconfont-fenlei\"></i> 商品分类</ul>\n    <ul id=\"myTree\" style=\"margin-left: 10px\" class=\"ztree\"></ul>\n</div>\n<div style=\"margin-left:200px;\">\n    <nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 商品管理 <span class=\"c-gray en\">&gt;</span> 商品列表 <span class=\"c-gray en\">&gt;</span><span id=\"category\">所有商品</span> <a class=\"btn btn-success radius r\" style=\"line-height:1.6em;margin-top:3px\" href=\"javascript:location.replace(location.href);\" title=\"刷新\" ><i class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n    <form id=\"form-search\" class=\"page-container\">\n        <div class=\"cl pd-5 bg-1 bk-gray mt-20\"> <span class=\"l\"><a href=\"javascript:;\" onclick=\"deleteMulti()\" class=\"btn btn-danger radius\"><i class=\"Hui-iconfont\">&#xe6e2;</i> 批量删除</a> <a class=\"btn btn-primary radius\" onclick=\"product_add('添加商品','product-form')\" href=\"javascript:;\"><i class=\"Hui-iconfont\">&#xe600;</i> 添加商品</a></span> <span class=\"r\"></div>\n        <div class=\"mt-20\">\n            <div class=\"mt-20\" style=\"margin-bottom: 70px\">\n                <table id=\"dataTable\" class=\"table table-border table-bordered table-bg table-hover table-sort\" width=\"100%\">\n                    <thead>\n                    <tr class=\"text-c\">\n                        <th width=\"30\"><input type=\"checkbox\" class=\"minimal icheck_master\"/></th>\n                        <th width=\"40\">ID</th>\n                        <th width=\"70\">缩略图</th>\n                        <th width=\"150\">商品名称</th>\n                        <th width=\"100\">描述</th>\n                        <th width=\"60\">单价</th>\n                        <th width=\"95\">创建日期</th>\n                        <th width=\"95\">更新日期</th>\n                        <th width=\"60\">发布状态</th>\n                        <th width=\"90\">操作</th>\n                    </tr>\n                    </thead>\n                </table>\n            </div>\n        </div>\n    </form>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n\n<!-- ZTree -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/zTree/v3/js/jquery.ztree.all-3.5.min.js\"></script>\n\n<!-- DataTables -->\n<script type=\"text/javascript\" src=\"/static/assets/lib/datatables/1.10.0/jquery.dataTables.min.js\"></script>\n<script type=\"text/javascript\" src=\"/static/assets/lib/laypage/1.2/laypage.js\"></script>\n\n<!-- iCheck 1.0.1 -->\n<script src=\"/static/assets/plugins/iCheck/icheck.min.js\"></script>\n\n<script type=\"text/javascript\">\n\n\n    // 初始化 iCheck\n    App.initICheck();\n\n    // 初始化类别数据 -1：所有数据\n    var cid = -1;\n\n    /**\n     * 初始化 ZTree\n     **/\n    var callback = {\n        onAsyncSuccess: function(){\n            layer.close(index);\n        },\n        beforeClick: function(treeId, treeNode) {\n            if (treeNode.isParent) {\n                return false;\n            } else {\n                cid = treeNode.id;\n                $(\"#category\").html(treeNode.name);\n                let param = {\n                    \"cid\": treeNode.cid\n                };\n                _dataTables.settings()[0].ajax.url = '/item/list/' + cid;\n                _dataTables.ajax.reload();\n                return true;\n            }\n        }\n    };\n    App.initZtree(\"/item/cat/list/-1\" , callback);\n\n    /**\n     * 分割图片\n     * */\n    function imageShow(data) {\n        var images = new Array(); // 定义数组\n        images = data.split(\",\"); // 字符分割\n        if (images.length > 0) {\n            return images[0];\n        } else {\n            return data;\n        }\n    }\n\n    /**\n     * 初始化 DataTables\n     */\n    var _dataTables;\n    $(function () {\n        const _columns = [\n            {\n                \"data\": null,\n                render: function(data,type, row, meta) {\n                    return '<input id=\"' + row.id + '\" type=\"checkbox\" class=\"minimal\" />';\n                }\n            },\n            { \"data\": \"id\"},\n            {\n                \"data\": \"image\",\n                render: function (data, type, row, meta) {\n                    return '<img src=\"'+ imageShow(data) +'\" style=\"width: 80px;height: 70px;\" onclick=\"App.previewImg(this, 500, 500)\"/>'\n                }\n            },\n            {\n                \"data\": \"title\",\n                render: function (data, type, row, meta) {\n                    if (type === 'display') {\n                        if (data.length > 20) {\n                            return '<span title=\"'+ data +'\">'+ data.substr(0, 50) +'...</span>';\n                        } else {\n                            return '<span title='+ data +'>'+ data +'</span>'\n                        }\n                    }\n                    return data;\n                }\n            },\n            {\n                \"data\": \"sellPoint\",\n                render: function (data, type, row, meta) {\n                    if (type === 'display') {\n                        if (data.length > 25) {\n                            return '<span title='+ data +'>'+ data +'</span>';\n                        } else {\n                            return '<span title='+ data +'>'+ data +'</span>'\n                        }\n                    }\n                    return data;\n                }\n            },\n            {\"data\": \"price\"},\n            {\n                \"data\": \"created\",\n                render: function (data, type, row, meta) {\n                    return date(data);\n                }\n            },\n            {\n                \"data\": \"updated\",\n                render: function (data, type, row, meta) {\n                    return date(data);\n                }\n            },\n            {\n              \"data\": \"status\",\n              render: function(data, type, row, meta) {\n                  if (data == 0) {\n                      return '<span class=\"label label-default radius td-status\">已下架</span>';\n                  } else if (data == 1) {\n                      return '<span class=\"label label-success radius td-status\">已发布</span>';\n                  } else {\n                      return '<span class=\"label label-warning radius td-status\">其它态</span>';\n                  }\n              }\n            },\n            {\n                \"data\": null,\n                render: function (data  , type, row, meta) {\n                    if (row.status == 1) {\n                        return '<a style=\"text-decoration:none\" onClick=\"product_stop('+ row.id +')\" href=\"javascript:;\" title=\"下架\"><i class=\"Hui-iconfont\">&#xe6de;</i></a>' +\n                            '<a style=\"text-decoration:none\" class=\"ml-5\" onClick=\"product_edit(\\'商品编辑\\', \\'product-form\\', '+ row.id +')\" href=\"javascript:;\" title=\"编辑\"><i class=\"Hui-iconfont\">&#xe6df;</i></a>' +\n                            '<a style=\"text-decoration:none\" class=\"m1-5\" onClick=\"product_del('+ row.id +')\" href=\"javascript:;\" title=\"删除\"><i class=\"Hui-iconfont\">&#xe6e2;</i></a>';\n                    } else {\n                        return \"<a style=\\\"text-decoration:none\\\" onClick=\\\"product_start(\"+row.id+\")\\\" href=\\\"javascript:;\\\" title=\\\"发布\\\"><i class=\\\"Hui-iconfont\\\">&#xe603;</i></a> \" +\n                            \"<a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"product_edit('商品编辑','product-form',\"+row.id+\")\\\" href=\\\"javascript:;\\\" title=\\\"编辑\\\"><i class=\\\"Hui-iconfont\\\">&#xe6df;</i></a> \" +\n                            \"<a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"product_del(\"+row.id+\")\\\" href=\\\"javascript:;\\\" title=\\\"删除\\\"><i class=\\\"Hui-iconfont\\\">&#xe6e2;</i></a>\";\n                    }\n                }\n            }\n        ];\n\n        _dataTables = App.initDataTables(\"/item/list/\" + cid, _columns);\n    });\n\n\n    // 加载中...\n    var index = layer.load(3);\n\n    /**\n     * 产品下架\n     * */\n    function product_stop(id) {\n        // 确认消息\n        var confirmMsg = '确定下架ID为 '+ id +' 的商品吗？';\n\n        // 提交请求路径\n        var url = '/item/stop/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 1, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 产品发布\n     * */\n    function product_start(id) {\n        // 确认消息\n        var confirmMsg = '确定发布ID为 '+ id +' 的商品吗？';\n\n        // 提交请求路径\n        var url = '/item/start/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 1, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    // 初始化 ID 值\n    var ID = 0;\n    /**\n     * 设置 ID\n     **/\n    function setId(id) {\n        ID = id;\n    }\n    /**\n     * 获取 ID\n     * */\n    function getId() {\n        return ID;\n    }\n\n    /**\n     * 产品新增\n     * */\n    function product_add(title, url) {\n        setId(0);\n        images = \"\";\n        var index = layer.open({\n            type: 2,\n            title: title,\n            content: url\n        });\n        layer.full(index);\n    }\n\n    /**\n     * 产品编辑\n     * */\n    var images = \"\";\n    function product_edit(title, url, id) {\n        setId(id);\n        $(\"#dataTable tbody\").on('click', 'tr', function () {\n            images = _dataTables.row(this).data().image;\n        });\n        var index = layer.open({\n            type: 2,\n            title: title,\n            content: url\n        });\n        layer.full(index);\n    }\n\n    /**\n     * 删除单个商品\n     * */\n    function product_del(id) {\n\n        // 确认消息\n        var confirmMsg = '确定删除ID为 '+ id +' 的商品吗？';\n\n        // 提交请求路径\n        var url = '/item/delete/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 2, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 批量删除\n     * */\n    function deleteMulti() {\n\n        // 请求路径\n        var url = \"/item/delete/\";\n\n        // 请求成功执行方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon:1, time:1000});\n        }\n\n        App.deleteMulti(url, successMethod);\n    }\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/system-express-form.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>编辑快递</title>\n</head>\n<body>\n<article class=\"page-container\">\n    <form action=\"\" method=\"post\" class=\"form form-horizontal\" id=\"validate-form\">\n        <div class=\"row cl\">\n            <input type=\"text\" class=\"input-text\" hidden value=\"\" placeholder=\"\" id=\"id\" name=\"id\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>快递名称：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"快递名称\" id=\"expressName\" name=\"expressName\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <label class=\"form-label col-xs-4 col-sm-3\"><span class=\"c-red\">*</span>排序值：</label>\n            <div class=\"formControls col-xs-8 col-sm-9\">\n                <input type=\"text\" class=\"input-text\" value=\"\" placeholder=\"值越小排序越前\" id=\"sortOrder\" name=\"sortOrder\">\n            </div>\n        </div>\n        <div class=\"row cl\">\n            <div class=\"col-xs-8 col-sm-9 col-xs-offset-4 col-sm-offset-3\">\n                <button id=\"saveButton\" type=\"submit\" class=\"btn btn-success radius\" id=\"admin-role-save\" name=\"admin-role-save\"><i class=\"icon-ok\"></i> 确定</button>\n            </div>\n        </div>\n    </form>\n</article>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n<script type=\"text/javascript\">\n\n    $(\"#id\").val(parent.id);\n    $(\"#expressName\").val(parent.expressName);\n    $(\"#sortOrder\").val(parent.sortOrder);\n\n    /**\n     * 提交成功后执行的方法\n     * */\n    function successMethod(data) {\n        parent.refresh();\n        parent.App.msgSuccess(data.message);\n        var index = parent.layer.getFrameIndex(window.name);\n        parent.layer.close(index);\n    }\n    Validate.validate('/express/save', \"\", successMethod);\n\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/system-express.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE HTML>\n<html>\n<head>\n    <jsp:include page=\"../includes/header.jsp\"/>\n    <title>快递管理</title>\n</head>\n<style>\n    .table > tbody > tr > td {\n        text-align: center;\n    }\n</style>\n<body>\n\n<div>\n    <nav class=\"breadcrumb\"><i class=\"Hui-iconfont\">&#xe67f;</i> 首页 <span class=\"c-gray en\">&gt;</span> 系统管理 <span\n            class=\"c-gray en\">&gt;</span> 快递管理 <a class=\"btn btn-success radius r\"\n                                                  style=\"line-height:1.6em;margin-top:3px\"\n                                                  href=\"javascript:location.replace(location.href);\" title=\"刷新\"><i\n            class=\"Hui-iconfont\">&#xe68f;</i></a></nav>\n    <form class=\"page-container\">\n        <div class=\"cl pd-5 bg-1 bk-gray mt-20\">\n            <span class=\"l\">\n                <a href=\"javascript:;\" onclick=\"datadel()\" class=\"btn btn-danger radius\"><i class=\"Hui-iconfont\">&#xe6e2;</i> 批量删除</a>\n                <a class=\"btn btn-primary radius\" onclick=\"add('添加快递','system-express-form',500,250)\"\n                   href=\"javascript:;\"><i class=\"Hui-iconfont\">&#xe600;</i> 添加快递</a>\n            </span>\n        </div>\n        <div class=\"mt-20\">\n            <div class=\"mt-20\" style=\"margin-bottom: 70px\">\n                <table id=\"dataTable\" class=\"table table-border table-bordered table-bg table-hover table-sort\" width=\"100%\">\n                    <thead>\n                    <tr class=\"text-c\">\n                        <th width=\"15\"><input type=\"checkbox\" class=\"minimal icheck_master\"/></th>\n                        <th width=\"30\">ID</th>\n                        <th width=\"80\">快递名称</th>\n                        <th width=\"20\">排序值</th>\n                        <th width=\"50\">操作</th>\n                    </tr>\n                    </thead>\n                </table>\n            </div>\n        </div>\n    </form>\n</div>\n\n<jsp:include page=\"../includes/footer.jsp\"/>\n<script type=\"text/javascript\">\n\n    /**\n     * 初始化 DataTables\n     */\n    var _dataTables;\n    $(function () {\n        const _columns = [\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    return '<input id=\"\\' + row.id + \\'\" type=\"checkbox\" class=\"minimal\" />';\n                }\n            },\n            {\"data\": \"id\"},\n            {\"data\": \"expressName\"},\n            {\"data\": \"sortOrder\"},\n            {\n                \"data\": null,\n                render: function (data, type, row, meta) {\n                    return \"<a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"edit('快递编辑','system-express-form',500,250)\\\" href=\\\"javascript:;\\\" title=\\\"编辑\\\"><i class=\\\"Hui-iconfont\\\">&#xe6df;</i></a> \" +\n                        \"<a style=\\\"text-decoration:none\\\" class=\\\"ml-5\\\" onClick=\\\"del(\" + row.id + \")\\\" href=\\\"javascript:;\\\" title=\\\"删除\\\"><i class=\\\"Hui-iconfont\\\">&#xe6e2;</i></a>\";\n                }\n            }\n        ];\n\n        _dataTables = App.initDataTables(\"/express/list/\", _columns);\n    });\n\n    // 定义初始化数据\n    var id, expressName, sortOrder;\n\n    /**\n     * 添加快递\n     **/\n    function add(title, url, w, h) {\n        id = \"\", expressName = \"\", sortOrder = \"\";\n        layer_show(title, url, w, h);\n    }\n\n    /**\n     * 编辑快递\n     **/\n    function edit(title, url, w, h) {\n        var table = $('.table').DataTable();\n        $('.table tbody').on('click', 'tr', function () {\n            id = table.row(this).data().id;\n            expressName = table.row(this).data().expressName;\n            sortOrder = table.row(this).data().sortOrder;\n        });\n        layer_show(title, url, w, h);\n    }\n\n    /**\n     * 删除快递\n     **/\n    function del(id) {\n        // 确认消息\n        var confirmMsg = '确定删除ID为 '+ id +' 的快递吗？';\n\n        // 提交请求路径\n        var url = '/express/delete/' + id;\n\n        // 成功回调方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon: 2, time: 1000});\n        }\n\n        App.deleteSinge(confirmMsg, url, successMethod);\n    }\n\n    /**\n     * 批量删除快递\n     */\n    function datadel() {\n        // 请求路径\n        var url = \"/express/delete/\";\n\n        // 请求成功执行方法\n        function successMethod(data) {\n            refresh();\n            layer.msg(data.message, {icon:1, time:1000});\n        }\n\n        App.deleteMulti(url, successMethod);\n    }\n\n    function msgSuccess(content) {\n        layer.msg(content, {icon: 1, time: 3000});\n    }\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/views/welcome.jsp",
    "content": "<%@ page contentType=\"text/html;charset=UTF-8\" language=\"java\" %>\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <meta name=\"description\" content=\"\">\n    <meta name=\"author\" content=\"Yuu\">\n    <link rel=\"Shortcut Icon\" href=\"/static/assets/icon/logo.png\" />\n    <title>YMall后台管理系统 v1.0</title>\n\n    <!-- Bootstrap core CSS -->\n    <link href=\"/static/assets/lib/flatlab/css/bootstrap.min.css\" rel=\"stylesheet\">\n    <link href=\"/static/assets/lib/flatlab/css/bootstrap-reset.css\" rel=\"stylesheet\">\n    <!--external css-->\n    <link href=\"/static/assets/lib/flatlab/assets/font-awesome/css/font-awesome.css\" rel=\"stylesheet\" />\n    <link href=\"/static/assets/lib/flatlab/assets/jquery-easy-pie-chart/jquery.easy-pie-chart.css\" rel=\"stylesheet\" type=\"text/css\" media=\"screen\"/>\n    <link rel=\"stylesheet\" href=\"/static/assets/lib/flatlab/css/owl.carousel.css\" type=\"text/css\">\n    <!-- Custom styles for this template -->\n    <link href=\"/static/assets/lib/flatlab/css/style.css\" rel=\"stylesheet\">\n    <link href=\"/static/assets/lib/flatlab/css/style-responsive.css\" rel=\"stylesheet\" />\n\n    <!-- HTML5 shim and Respond.js IE8 support of HTML5 tooltipss and media queries -->\n    <!--[if lt IE 9]>\n    <script src=\"/static/assets/lib/flatlab/js/html5shiv.js\"></script>\n    <script src=\"/static/assets/lib/flatlab/js/respond.min.js\"></script>\n    <![endif]-->\n</head>\n<style>\n    #main-content {\n        margin-left: 20px;\n        margin-top: -50px;\n    }\n    .site-footer .text-center a{\n        color: #53bee6;\n    }\n</style>\n<body>\n<section id=\"container\" >\n    <!--main content start-->\n    <section id=\"main-content\">\n        <section class=\"wrapper\">\n            <!--state overview start-->\n            <div class=\"row state-overview\">\n                <div class=\"col-lg-4 col-sm-6\">\n                    <section class=\"panel\">\n                        <div class=\"symbol terques\">\n                            <i class=\"icon-user\"></i>\n                        </div>\n                        <div class=\"value\">\n                            <h1 class=\"count\">\n                                ...\n                            </h1>\n                            <p>用户总数</p>\n                        </div>\n                    </section>\n                </div>\n                <div class=\"col-lg-4 col-sm-6\">\n                    <section class=\"panel\">\n                        <div class=\"symbol red\">\n                            <i class=\"icon-tags\"></i>\n                        </div>\n                        <div class=\"value\">\n                            <h1 class=\" count2\">\n                                ...\n                            </h1>\n                            <p>商品总数</p>\n                        </div>\n                    </section>\n                </div>\n                <div class=\"col-lg-4 col-sm-6\">\n                    <section class=\"panel\">\n                        <div class=\"symbol yellow\">\n                            <i class=\"icon-shopping-cart\"></i>\n                        </div>\n                        <div class=\"value\">\n                            <h1 class=\" count3\">\n                                ...\n                            </h1>\n                            <p>订单总数</p>\n                        </div>\n                    </section>\n                </div>\n            </div>\n            <!--state overview end-->\n\n            <div class=\"row\">\n\n                <div class=\"col-lg-6\">\n                    <!--user info table start-->\n                    <section class=\"panel\">\n                        <div class=\"panel-body\">\n                            <a href=\"http://blog.Yuu.cn\" target=\"_blank\" class=\"task-thumb\">\n                                <img width=\"83px\" height=\"83px\" src=\"/static/assets/lib/flatlab/img/avatar1.jpg\" alt=\"\">\n                            </a>\n                            <div class=\"task-thumb-details\">\n                                <h1><a href=\"https://blog.csdn.net/qq_37581282\" target=\"_blank\">Yuu</a></h1>\n                                <p>Author</p>\n                            </div>\n                        </div>\n                        <table class=\"table table-hover personal-task\">\n                            <tbody>\n                            <tr>\n                                <td>\n                                    <i class=\" icon-tasks\"></i>\n                                </td>\n                                <td>\n                                    <a target=\"_blank\" href=\"https://blog.csdn.net/qq_37581282\">\n                                        个人简介\n                                    </a>\n                                </td>\n                                <td> <span style=\"margin-top: -1px\" class=\"label label-primary pull-right r-activity\">01</span></td>\n                            </tr>\n                            <tr>\n                                <td>\n                                    <i class=\"icon-book\"></i>\n                                </td>\n                                <td>\n                                    <a target=\"_blank\" href=\"https://blog.csdn.net/qq_37581282/\">\n                                        个人博客\n                                    </a>\n                                </td>\n                                <td> <span style=\"margin-top: -1px\" class=\"label label-info pull-right r-activity\">01</span></td>\n                            </tr>\n                            <tr>\n                                <td>\n                                    <i class=\" icon-music\"></i>\n                                </td>\n                                <td>\n                                    <a target=\"_blank\" href=\"https://music.163.com/#/user/home?id=327286657\">\n                                        网易云音乐\n                                    </a>\n                                </td>\n                                <td> <span style=\"margin-top: -1px\" class=\"label label-info pull-right r-activity\">01</span></td>\n                            </tr>\n                            <tr>\n                                <td>\n                                    <i class=\"icon-envelope\"></i>\n                                </td>\n                                <td>\n                                    <a href=\"mailto:yuu71@qq.com\" target=\"_blank\">yuu71@qq.com</a>\n                                </td>\n                                <td> <span style=\"margin-top: -1px\" class=\"label label-warning pull-right r-activity\">01</span></td>\n                            </tr>\n                            <tr>\n                                <td>\n                                    <i class=\" icon-bell-alt\"></i>\n                                </td>\n                                <td>\n                                    <a target=\"_blank\" href=\"https://github.com/71yuu\">\n                                        Github\n                                    </a>\n                                </td>\n                                <td> <span style=\"margin-top: -1px\" class=\"label label-success pull-right r-activity\">01</span></td>\n                            </tr>\n                            </tbody>\n                        </table>\n                    </section>\n                    <!--user info table end-->\n                </div>\n\n                <div class=\"col-lg-6\">\n                    <!--widget start-->\n                    <section class=\"panel\">\n                        <header class=\"panel-heading tab-bg-dark-navy-blue\">\n                            <ul class=\"nav nav-tabs nav-justified \">\n                                <li class=\"active\">\n                                    <a href=\"#popular\" data-toggle=\"tab\">\n                                        公告\n                                    </a>\n                                </li>\n                            </ul>\n                        </header>\n                        <div class=\"panel-body\" >\n                            <div class=\"tab-content tasi-tab\">\n                                <div class=\"tab-pane active\" id=\"popular\">\n                                    <article class=\"media\">\n                                        <a class=\"pull-left thumb p-thumb\">\n                                            <img src=\"/static/assets/lib/flatlab/img/avatar-mini.jpg\">\n                                        </a>\n                                        <div class=\"media-body\">\n                                            <a class=\"p-head\" href=\"#\">\n                                                尊敬的 <span id=\"username\"></span>，\n                                                <span id=\"hello\"></span>\n                                                现在时间是：<span id=\"currentTime\"></span></a>\n                                            <p style=\"font-size: 20px;\"><br>YMALL 商城系统是基于 SSM 的电商 B2C 购物商城系统。前后端开发分离，前台基于 Vue 开发，主要功能有会员登录注册、首页管理、分类商品页、商品详情页、购物车、订单、在线支付、会员中心等。后台管理系统主要包括登录、首页管理、分类管理、商品管理、订单管理、会员管理、管理员管理、报表管理、快递管理等等。<br><br>\n                                                By: Yuu\n                                            </p>\n                                        </div>\n                                    </article>\n                                </div>\n                            </div>\n                        </div>\n                    </section>\n                    <!--widget end-->\n                </div>\n            </div>\n            <div class=\"row\">\n                <div class=\"col-lg-8\">\n                    <!--timeline start-->\n                    <section class=\"panel\">\n                        <div class=\"panel-body\">\n                            <div class=\"text-center mbot30\">\n                                <h3 class=\"timeline-title\">YMall项目日志</h3>\n                                <p class=\"t-info\">This is a project timeline</p>\n                            </div>\n\n                            <div class=\"timeline\">\n                                <article class=\"timeline-item alt\">\n                                    <div class=\"timeline-desk\">\n                                        <div class=\"panel\">\n                                            <div class=\"panel-body\">\n                                                <span class=\"arrow-alt\"></span>\n                                                <span class=\"timeline-icon purple\"></span>\n                                                <span class=\"timeline-date\">04:00 pm</span>\n                                                <h1 class=\"purple\">2019年7月12日</h1>\n                                                <p><a href=\"https://www.71yuu.com/\" target=\"_blank\">Yuu</a> 正在进行项目评审与答辩</p>\n                                            </div>\n                                        </div>\n                                    </div>\n                                </article>\n                                <article class=\"timeline-item\">\n                                    <div class=\"timeline-desk\">\n                                        <div class=\"panel\">\n                                            <div class=\"panel-body\">\n                                                <span class=\"arrow-alt\"></span>\n                                                <span class=\"timeline-icon purple\"></span>\n                                                <span class=\"timeline-date\">02:05 am</span>\n                                                <h1 class=\"purple\">2019年7月11日</h1>\n                                                <p><a href=\"https://www.71yuu.com/\" target=\"_blank\">Yuu</a> 完成\n                                                    <a href=\"https://github.com/71yuu/YMall\" target=\"_blank\">ymall-web-ui</a>项目\n                                            </div>\n                                        </div>\n                                    </div>\n                                </article>\n                                <article class=\"timeline-item alt\">\n                                    <div class=\"timeline-desk\">\n                                        <div class=\"panel\">\n                                            <div class=\"panel-body\">\n                                                <span class=\"arrow-alt\"></span>\n                                                <span class=\"timeline-icon purple\"></span>\n                                                <span class=\"timeline-date\">08:00 am</span>\n                                                <h1 class=\"purple\">2019年6月22日</h1>\n                                                <p><a href=\"https://www.71yuu.com/\" target=\"_blank\">Yuu</a> 启动\n                                                    <a href=\"https://github.com/71yuu/YMall\" target=\"_blank\">ymall-web-ui</a>项目\n                                            </div>\n                                        </div>\n                                    </div>\n                                </article>\n                                <article class=\"timeline-item\">\n                                    <div class=\"timeline-desk\">\n                                        <div class=\"panel\">\n                                            <div class=\"panel-body\">\n                                                <span class=\"arrow\"></span>\n                                                <span class=\"timeline-icon red\"></span>\n                                                <span class=\"timeline-date\">07:00 am</span>\n                                                <h1 class=\"red\">2019年6月21日</h1>\n                                                <p><a href=\"https://www.71yuu.com/\" target=\"_blank\">Yuu</a> 完成\n                                                    <a href=\"https://github.com/71yuu/YMall\" target=\"_blank\">YMall 后台管理系统</a>\n                                            </div>\n                                        </div>\n                                    </div>\n                                </article>\n                                <article class=\"timeline-item alt\">\n                                    <div class=\"timeline-desk\">\n                                        <div class=\"panel\">\n                                            <div class=\"panel-body\">\n                                                <span class=\"arrow-alt\"></span>\n                                                <span class=\"timeline-icon green\"></span>\n                                                <span class=\"timeline-date\">07:00 pm</span>\n                                                <h1 class=\"green\">2019年6月20日</h1>\n                                                <p><a href=\"https://www.71yuu.com/\" target=\"_blank\">Yuu</a> 启动\n                                                    <a href=\"https://github.com/71yuu/YMall\" target=\"_blank\">YMall</a> 项目\n                                            </div>\n                                        </div>\n                                    </div>\n                                </article>\n                                <article class=\"timeline-item\">\n                                    <div class=\"timeline-desk\">\n                                        <div class=\"panel\">\n                                            <div class=\"panel-body\">\n                                                <span class=\"arrow\"></span>\n                                                <span class=\"timeline-icon blue\"></span>\n                                                <span class=\"timeline-date\">05:00 pm</span>\n                                                <h1 class=\"blue\">2019年6月20日</h1>\n                                                <p><a href=\"https://www.71yuu.com/\" target=\"_blank\">Yuu</a> 完成了\n                                                    数据库设计文档\n                                            </div>\n                                        </div>\n                                    </div>\n                                </article>\n                                <article class=\"timeline-item alt\">\n                                    <div class=\"timeline-desk\">\n                                        <div class=\"panel\">\n                                            <div class=\"panel-body\">\n                                                <span class=\"arrow-alt\"></span>\n                                                <span class=\"timeline-icon purple\"></span>\n                                                <span class=\"timeline-date\">02:30 pm</span>\n                                                <h1 class=\"purple\">2019年6月19日</h1>\n                                                <p><a href=\"https://www.71yuu.com/\" target=\"_blank\">Yuu</a> 完成了\n                                                    需求分析文档\n                                            </div>\n                                        </div>\n                                    </div>\n                                </article>\n                                <article class=\"timeline-item\">\n                                <div class=\"timeline-desk\">\n                                    <div class=\"panel\">\n                                        <div class=\"panel-body\">\n                                            <span class=\"arrow\"></span>\n                                            <span class=\"timeline-icon light-green\"></span>\n                                            <span class=\"timeline-date\">05:00 pm</span>\n                                            <h1 class=\"light-green\">2019年6月18日</h1>\n                                            <p><a href=\"https://www.71yuu.com/\" target=\"_blank\">Yuu</a> 完成了\n                                                项目计划文档\n                                        </div>\n                                    </div>\n                                </div>\n                            </article>\n                            </div>\n\n                            <div class=\"clearfix\">&nbsp;</div>\n                        </div>\n                    </section>\n                    <!--timeline end-->\n                </div>\n                <div class=\"col-lg-4\">\n\n                    <!--weather statement start-->\n                    <section class=\"panel\">\n                        <div class=\"weather-bg\">\n                            <div class=\"panel-body\">\n                                <div class=\"row\">\n                                    <div class=\"col-xs-6\">\n                                        <i id=\"weather\" class=\"icon-cloud\"></i>\n                                        <span id=\"city\">...</span>\n                                    </div>\n                                    <div class=\"col-xs-6\">\n                                        <div class=\"degree\">\n                                            <span id=\"degree\">...</span>\n                                        </div>\n                                    </div>\n                                </div>\n                            </div>\n                        </div>\n\n                        <footer class=\"weather-category\">\n                            <ul>\n                                <li class=\"active\">\n                                    <h5>湿度</h5>\n                                    <span id=\"humidity\">...</span>\n                                </li>\n                                <li>\n                                    <h5>空气质量</h5>\n                                    <span id=\"airCondition\">...</span>\n                                </li>\n                                <li>\n                                    <h5>风力</h5>\n                                    <span id=\"wind\">...</span>\n                                </li>\n                            </ul>\n                        </footer>\n                    </section>\n                    <!--weather statement end-->\n                </div>\n\n                <div class=\"col-lg-4\">\n                    <!--latest product info start-->\n                    <section class=\"panel post-wrap pro-box\">\n                        <aside>\n                            <div class=\"post-info\">\n                                <span class=\"arrow-pro right\"></span>\n                                <div class=\"panel-body\">\n                                    <h1><strong>popular</strong> <br> 本周热门商品</h1>\n                                    <div class=\"desk yellow\">\n                                        <h3 id=\"hot-title\">商品名称</h3>\n                                        <p>共卖出 <span id=\"hot-num\"></span> 件</p>\n                                    </div>\n                                    <div class=\"post-btn\">\n                                        <a href=\"javascript:;\">\n                                            <i class=\"icon-chevron-sign-left\"></i>\n                                        </a>\n                                        <a href=\"javascript:;\">\n                                            <i class=\"icon-chevron-sign-right\"></i>\n                                        </a>\n                                    </div>\n                                </div>\n                            </div>\n                        </aside>\n                        <aside class=\"post-highlight yellow v-align\">\n                            <div class=\"panel-body text-center\">\n                                <div class=\"pro-thumb\">\n                                    <img id=\"hot-img\" width=\"112px\" height=\"112px\" src=\"/static/assets/icon/none.png\" alt=\"\">\n                                </div>\n                            </div>\n                        </aside>\n                    </section>\n                    <!--latest product info end-->\n                    <!--twitter feedback start-->\n                    <section class=\"panel post-wrap pro-box\">\n                        <aside>\n                            <div class=\"post-info\">\n                                <span class=\"arrow-pro left\"></span>\n                                <div class=\"panel-body\">\n                                    <div class=\"text-center twite\">\n                                        <h1>Follow Me</h1>\n                                    </div>\n\n                                    <footer class=\"social-footer\">\n                                        <ul>\n                                            <li>\n                                                <a href=\"https://github.com/71yuu\" target=\"_blank\">\n                                                    <i class=\"icon-github\"></i>\n                                                </a>\n                                            </li>\n                                            <li class=\"active\">\n                                                <a target=\"_blank\" href=\"http://wpa.qq.com/msgrd?v=3&uin=1225459207&site=qq&menu=yes\">\n                                                    <img style=\"margin-bottom: 3px\" width=\"24px\" height=\"24px\" src=\"/static/assets/icon/qq.png\"/>\n                                                </a>\n                                            </li>\n                                            <li>\n                                                <a href=\"https://www.71yuu.com/\" target=\"_blank\">\n                                                    <i class=\"icon-book\"></i>\n                                                </a>\n                                            </li>\n                                        </ul>\n                                    </footer>\n                                </div>\n                            </div>\n                        </aside>\n                    </section>\n                    <!--twitter feedback end-->\n                </div>\n            </div>\n        </section>\n    </section>\n    <!--main content end-->\n    <!--footer start-->\n    <footer class=\"site-footer\">\n        <div class=\"text-center\">\n            Copyright &copy;2019 <a href=\"https://www.71yuu.com/\" target=\"_blank\">Yuu</a> All Rights Reserved.\n            本后台系统由<a href=\"http://www.h-ui.net/\" target=\"_blank\"> H-ui</a>、<a href=\"https://themeforest.net/item/flatlab-bootstrap-3-responsive-admin-template/5902687\" target=\"_blank\">FlatLab </a>提供前端静态页面支持\n            <a href=\"#\" class=\"go-top\">\n                <i class=\"icon-angle-up\"></i>\n            </a>\n        </div>\n    </footer>\n    <!--footer end-->\n</section>\n\n<!-- js placed at the end of the document so the pages load faster -->\n<script src=\"/static/assets/lib/flatlab/js/jquery.js\"></script>\n<script src=\"/static/assets/lib/flatlab/js/jquery-1.8.3.min.js\"></script>\n<script src=\"/static/assets/lib/flatlab/js/bootstrap.min.js\"></script>\n<script src=\"/static/assets/lib/flatlab/js/jquery.scrollTo.min.js\"></script>\n<script src=\"/static/assets/lib/flatlab/js/jquery.nicescroll.js\" type=\"text/javascript\"></script>\n<script src=\"/static/assets/lib/flatlab/js/jquery.sparkline.js\" type=\"text/javascript\"></script>\n<script src=\"/static/assets/lib/flatlab/assets/jquery-easy-pie-chart/jquery.easy-pie-chart.js\"></script>\n<script src=\"/static/assets/lib/flatlab/js/respond.min.js\" ></script>\n\n<!--common script for all pages-->\n<script type=\"text/javascript\" src=\"/static/assets/lib/layer/2.4/layer.js\"></script>\n\n<!--script for this page-->\n<script src=\"/static/assets/lib/flatlab/js/count.js\"></script>\n\n<!-- App -->\n<script type=\"text/javascript\" src=\"/static/assets/app/const.js\"></script>\n\n<script>\n\n    // 获取用户名\n    $(\"#username\").html(parent.username);\n\n    // 显示现在时段\n    var now = new Date(),hour = now.getHours();\n    if (hour < 5 || hour > 22) {$(\"#hello\").html(\"深夜好！\");}\n    if(hour < 6){ $(\"#hello\").html(\"凌晨好！\");}\n    else if (hour < 9){$(\"#hello\").html(\"早上好！\");}\n    else if (hour < 12){$(\"#hello\").html(\"上午好！\");}\n    else if (hour < 14){$(\"#hello\").html(\"中午好！\");}\n    else if (hour < 17){$(\"#hello\").html(\"下午好！\");}\n    else if (hour < 19){$(\"#hello\").html(\"傍晚好！\");}\n    else if (hour < 22){$(\"#hello\").html(\"晚上好！\");}\n\n    // 获取当前时间\n    $(function(){\n        setInterval(function(){\n            $(\"#currentTime\").text(new Date().toLocaleString());\n        },1000);\n    });\n\n\n    // 统计用户数\n    $.ajax({\n        url:\"/member/count\",\n        type:\"GET\",\n        success:function (data) {\n            countUp(data.result);\n        },\n        error:function(){\n            layer.alert(ERROR_REQUEST_MESSAGE, {title: '错误信息',icon: 2});\n        }\n    });\n\n    // 统计商品总数\n    $.ajax({\n        url:\"/item/count\",\n        type: 'GET',\n        success:function (data) {\n            countUp2(data.result);\n        },\n        error:function(){\n            layer.alert(ERROR_REQUEST_MESSAGE, {title: '错误信息',icon: 2});\n        }\n    });\n\n    // 统计订单总数\n    $.ajax({\n        url:\"/order/count\",\n        type: 'GET',\n        success:function (data) {\n            countUp3(data.result);\n        },\n        error:function(){\n            layer.alert(ERROR_REQUEST_MESSAGE, {title: '错误信息',icon: 2});\n        }\n    });\n\n    // 获取天气数据\n    $.ajax({\n        url:\"/sys/weather\",\n        type: 'GET',\n        success:function (data) {\n            if(data.result == null || data.result == \"\" || data.result.indexOf('错误') >= 0) {\n                layer.msg(\"无法获取您的IP，天气信息获取失败\");\n                return ;\n            }\n            var json = JSON.parse(data.result);\n            var param = json.result[0];\n            var weather = param.weather;\n            if (weather.indexOf(\"雨\") >= 0) {\n                $(\"#weather\").removeAttr(\"class\");\n                $(\"#weather\").attr(\"class\",\"icon-umbrella\");\n            } else if (weather.indexOf(\"晴\") >= 0){\n                $(\"#weather\").removeAttr(\"class\");\n                $(\"#weather\").attr(\"class\",\"icon-sun\");\n            }\n            $(\"#city\").html(param.city);\n            $(\"#degree\").html(param.temperature);\n            $(\"#humidity\").html(param.humidity);\n            $(\"#airCondition\").html(param.airCondition);\n            $(\"#wind\").html(param.wind);\n        },\n        error:function(){\n            layer.alert(ERROR_REQUEST_MESSAGE, {title: '错误信息',icon: 2});\n        }\n    });\n\n    //本周热门商品\n    $.ajax({\n        url:\"/sys/weekHot\",\n        type: 'GET',\n        success:function (data) {\n            if (data.status == 200) {\n                $(\"#hot-title\").html(data.result.title);\n                $(\"#hot-num\").html(data.result.total);\n                if(data.result.picPath != \"\" && data.result.picPath != null) {\n                    $(\"#hot-img\").attr(\"src\", data.result.picPath);\n                }\n            } else {\n                layer.alert(data.message, {title: '错误信息',icon: 2});\n            }\n        },\n        error:function(){\n            layer.alert(ERROR_REQUEST_MESSAGE,{title: '错误信息',icon: 2});\n        }\n    });\n\n    // 如果标题太长，截取前 18 个\n    if($(\"#hot-title\").text().length > 18){\n        $(\"#hot-title\").text($(\"#hot-title\").text().substring(0,18) + \"...\");\n    }\n\n</script>\n\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/WEB-INF/web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd\"\n         version=\"4.0\">\n\n    <!-- 加载 Spring 容器 -->\n    <context-param>\n        <param-name>contextConfigLocation</param-name>\n        <param-value>classpath:spring-context*.xml</param-value>\n    </context-param>\n    <listener>\n        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>\n    </listener>\n\n      <!-- Shiro 过滤器 -->\n    <filter>\n        <filter-name>shiroFilter</filter-name>\n        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>\n        <init-param>\n            <!-- 默认值 false,表示生命周期由 SpringApplicationContext 管理,设置为 true 则表示由 ServletContainer 管理 -->\n            <param-name>targetFilterLifecycle</param-name>\n            <param-value>true</param-value>\n        </init-param>\n    </filter>\n    <filter-mapping>\n        <filter-name>shiroFilter</filter-name>\n        <url-pattern>/*</url-pattern>\n    </filter-mapping>\n\n    <!-- 解决 POST 乱码 -->\n    <filter>\n        <filter-name>encodingFilter</filter-name>\n        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>\n        <init-param>\n            <param-name>encoding</param-name>\n            <param-value>UTF-8</param-value>\n        </init-param>\n        <init-param>\n            <param-name>forceEncoding</param-name>\n            <param-value>true</param-value>\n        </init-param>\n    </filter>\n    <filter-mapping>\n        <filter-name>encodingFilter</filter-name>\n        <url-pattern>/*</url-pattern>\n    </filter-mapping>\n\n    <!-- Spring MVC 前端控制器 -->\n    <servlet>\n        <servlet-name>springServlet</servlet-name>\n        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>\n        <init-param>\n            <param-name>contextConfigLocation</param-name>\n            <param-value>classpath*:/spring-mvc*.xml</param-value>\n        </init-param>\n        <load-on-startup>1</load-on-startup>\n    </servlet>\n    <servlet-mapping>\n        <servlet-name>springServlet</servlet-name>\n        <url-pattern>/</url-pattern>\n    </servlet-mapping>\n\n    <!-- Druid Servlet -->\n    <servlet>\n        <servlet-name>DruidStatView</servlet-name>\n        <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>\n    </servlet>\n    <servlet-mapping>\n        <servlet-name>DruidStatView</servlet-name>\n        <url-pattern>/druid/*</url-pattern>\n    </servlet-mapping>\n    \n    <!-- Swagger2 配置 -->\n    <servlet-mapping>\n        <servlet-name>default</servlet-name>\n        <url-pattern>/swagger-ui.html</url-pattern>\n    </servlet-mapping>\n</web-app>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/app/app.js",
    "content": "var App = function () {\n\n    // iCheck\n    var _masterCheckbox;\n    var _checkbox;\n\n    // 用于存放 ID 的数组\n    var _idArray;\n\n    /**\n     * 私有方法，初始化 ICheck\n     */\n    var handlerInitCheckbox = function () {\n        // 激活\n        $('input[type=\"checkbox\"].minimal, input[type=\"radio\"].minimal').iCheck({\n            checkboxClass: 'icheckbox_minimal-blue',\n            radioClass   : 'iradio_minimal-blue'\n        });\n\n        // 获取控制端 Checkbox\n        _masterCheckbox = $('input[type=\"checkbox\"].minimal.icheck_master');\n\n        // 获取全部 Checkbox 集合\n        _checkbox = $('input[type=\"checkbox\"].minimal');\n    };\n\n    /**\n     * Checkbox 全选功能\n     */\n    var handlerCheckboxAll = function () {\n        _masterCheckbox.on(\"ifClicked\", function (e) {\n            // 返回 true 表示未选中\n            if (e.target.checked) {\n                _checkbox.iCheck(\"uncheck\");\n            }\n\n            // 选中状态\n            else {\n                _checkbox.iCheck(\"check\");\n            }\n        })\n    };\n\n    /**\n     * 消息提示方法\n     */\n    var handlerMsgSuccess = function (content) {\n        layer.msg(content, {icon: 1, time: 3000});\n    };\n\n    /**\n     * 初始化 DataTables\n     */\n    var handlerInitDataTables = function (url, columns) {\n        var _dataTable = $(\"#dataTable\").DataTable({\n            \"ordering\": false,\n            \"processing\": true,\n            \"searching\": true,\n            \"serverSide\": true,\n            \"deferRender\": true,\n            \"ajax\": {\n                url: url,\n                type: 'GET'\n            },\n            \"columns\": columns,\n            language: {\n                url: '/static/assets/lib/datatables/Chinese.json'\n            },\n            \"drawCallback\": function () {\n                handlerInitCheckbox();\n                handlerCheckboxAll();\n            }\n        });\n        return _dataTable;\n    };\n\n    /**\n     * 初始化 zTree\n     *\n     * @param url 请求路径\n     * @param autoParam\n     * @param callback\n     */\n    var handlerInitZTree = function (url, callback) {\n        var setting = {\n            view: {\n                // 禁止多选\n                selectedMulti: false\n            },\n            data: {\n                simpleData: {\n                    enable:true,\n                    idKey: \"id\",\n                    pIdKey: \"pId\",\n                    rootPId: \"\"\n                }\n            },\n            async: {\n                // 开启异步加载\n                enable: true,\n                // 远程访问地址\n                url: url,\n                // 请求方式\n                type: \"GET\",\n                contentType: \"application/json\",\n                autoParam: [\"id\"]\n            },\n            callback: callback\n        };\n\n        $.fn.zTree.init($(\"#myTree\"), setting);\n\n    };\n\n    /**\n     * 弹窗并全屏打开\n     *\n     * @param title 标题\n     * @param url 打开的页面路径\n     */\n    var handlerOpenAndFull = function (title, url) {\n        var index = layer.open({\n            type: 2,\n            title: title,\n            content: url\n        });\n        layer.full(index);\n    };\n\n    /**\n     * 自定义弹窗\n     *\n     * @param title 标题\n     * @param url 打开的页面路径\n     * @param w 宽度\n     * @param h 高度\n     */\n    var handlerShow = function (title, url, w, h) {\n        layer_show(title, url, w, h);\n    };\n\n    /**\n     * 删除单笔数据\n     *\n     * @param confirmMsg 确认消息\n     * @param url 请求路径\n     * @param successMethod 成功回调方法\n     */\n    var handlerDeleteSingle = function (confirmMsg, url, successMethod) {\n        layer.confirm(confirmMsg, {icon:0},function () {\n            var index = layer.load(3);\n            $.ajax({\n                type: 'DELETE',\n                url: url,\n                dataType: 'json',\n                success: function (data) {\n                    layer.close(index);\n                    if (data.status == 200) {\n                        successMethod(data);\n                    } else {\n                        layer.alert(data.message, {title: \"错误信息\", icon: 2});\n                    }\n                },\n                error: function () {\n                    layer.close(index);\n                    layer.alert(ERROR_REQUEST_MESSAGE, {title: \"错误信息\", icon: 2});\n                }\n            })\n        });\n    };\n\n    /**\n     * 批量删除\n     *\n     * @param url 路径\n     * @param successMsg 成功回调方法\n     */\n    var handlerDeleteMulti = function (url, successMethod) {\n        _idArray = new Array();\n\n        // 将选中的元素 ID 放入数组中\n        _checkbox.each(function () {\n            var _id = $(this).attr(\"id\");\n            if (_id != null && _id != \"undefine\" && $(this).is(\":checked\")) {\n                _idArray.push(_id);\n            }\n        });\n\n        // 判断用户是否选择了数据项\n        if (_idArray.length === 0) {\n            layer.msg('您还未勾选任何数据！', {icon:5, time:3000});\n            return;\n        }\n\n        // 确认删除\n        layer.confirm('确定要删除所选的'+ _idArray.length +'条数据吗？', {icon:0}, function () {\n            var index = layer.load(3);\n            $.ajax({\n                type: 'DELETE',\n                url: url + _idArray,\n                dataType: 'json',\n                success: function (data) {\n                    layer.close(index);\n                    if (data.status == 200) {\n                        successMethod(data);\n                    } else {\n                        layer.alert(data.message, {title: \"错误信息\", icon: 2});\n                    }\n                },\n                error: function () {\n                    layer.close(index);\n                    layer.alert(ERROR_REQUEST_MESSAGE, {title: \"错误信息\", icon: 2});\n                }\n            });\n        });\n    };\n\n    /**\n     * 通用的 Ajax 请求方法,不带数据\n     *\n     * @param url 请求地址\n     * @param type 请求类型\n     * @param successMethod 请求成功调用的方法\n     */\n    var handlerAjax = function (url, type, successMethod) {\n        $.ajax({\n            url: url,\n            type: type,\n            dataType: 'json',\n            success:function (data) {\n                if (data.status == 200) {\n                    successMethod(data);\n                } else {\n                    layer.alert(data.message, {title: \"错误信息\", icon: 2});\n                }\n            },\n            error:function(){\n                layer.alert(ERROR_REQUEST_MESSAGE, {title: '错误信息',icon: 2});\n            }\n        });\n    };\n\n    /**\n     * 通用的 Ajax 请求方法,带数据\n     *\n     * @param url\n     * @param type\n     * @param data\n     * @param successMethod\n     */\n    var handlerAjaxWithData = function (url, type, data, successMethod) {\n        $.ajax({\n            url: url,\n            type: type,\n            dataType: 'json',\n            data: data,\n            success:function (data) {\n                if (data.status == 200) {\n                    successMethod(data);\n                } else {\n                    layer.alert(data.message, {title: \"错误信息\", icon: 2});\n                }\n            },\n            error:function(){\n                layer.alert(ERROR_REQUEST_MESSAGE, {title: '错误信息',icon: 2});\n            }\n        });\n    };\n\n    /**\n     * 图片预览\n     *\n     * @param obj\n     */\n    var handlerPreviewImg= function (obj, w, h) {\n        var img = new Image();\n        img.src = obj.src;\n        var imgHtml = \"<img src='\" + obj.src + \"' width='100%' height='100%'/>\";\n        //弹出层\n        layer.open({\n            type: 1,\n            shade: 0.8,\n            offset: 'auto',\n            area: [w + 'px',h+'px'],\n            shadeClose:true,\n            scrollbar: false,\n            title: \"图片预览\", //不显示标题\n            content: imgHtml, //捕获的元素，注意：最好该指定的元素要存放在body最外层，否则可能被其它的相对元素所影响\n            cancel: function () {\n                //layer.msg('捕获就是从页面已经存在的元素上，包裹layer的结构', { time: 5000, icon: 6 });\n            }\n        });\n    };\n\n\n    return {\n        /**\n         * ICheck 初始化\n         */\n        initICheck: function () {\n            handlerInitCheckbox();\n            handlerCheckboxAll();\n        },\n\n        /**\n         * 消息提示\n         *\n         * @param content 内容\n         */\n        msgSuccess: function (content) {\n            handlerMsgSuccess(content);\n        },\n\n        /**\n         * 初始化 DataTables\n         *\n         * @param url 请求路径\n         * @param columns 返回参数映射\n         * @returns {jQuery|*}\n         */\n        initDataTables: function (url, columns) {\n            return handlerInitDataTables(url, columns);\n        },\n\n        /**\n         * 初始化 zTree\n         *\n         * @param url 请求路径\n         * @param callback 回调方法\n         */\n        initZtree: function (url, callback) {\n            handlerInitZTree(url, callback);\n        },\n\n        /**\n         * 弹窗并全屏打开\n         *\n         * @param title 标题\n         * @param url 打开的页面路径\n         */\n        openAndFull: function (title, url) {\n            handlerOpenAndFull(title, url);\n        },\n\n        /**\n         * 自定义弹窗\n         *\n         * @param title 标题\n         * @param url 打开的页面路径\n         * @param w 宽度\n         * @param h 高度\n         */\n        show: function(title, url, w, h) {\n            handlerShow(title, url, w, h);\n        },\n\n        /**\n         * 删除单笔数据\n         *\n         * @param confirmMsg 确认消息\n         * @param url 请求路径\n         * @param successMethod 成功回调方法\n         */\n        deleteSinge: function (confirmMsg, url, successMethod) {\n            handlerDeleteSingle(confirmMsg, url, successMethod);\n        },\n\n        /**\n         * 批量删除\n         *\n         * @param url 路径\n         * @param successMsg 成功回调方法\n         */\n        deleteMulti: function (url, successMethod) {\n            handlerDeleteMulti(url, successMethod);\n        },\n\n        /**\n         * 通用的 Ajax 请求方法\n         *\n         * @param url 请求地址\n         * @param type 请求类型\n         * @param successMethod 请求成功调用的方法\n         */\n        ajax: function (url, type, successMethod) {\n            handlerAjax(url, type, successMethod);\n        },\n\n        /**\n         * 通用的 Ajax 请求方法,带数据\n         *\n         * @param url\n         * @param type\n         * @param data\n         * @param successMethod\n         */\n        ajaxWithData: function (url, type, data, successMethod) {\n            handlerAjaxWithData(url, type, data, successMethod);\n        },\n\n        /**\n         * 图片预览\n         *\n         * @param obj\n         */\n        previewImg: function (obj, w, h) {\n            handlerPreviewImg(obj, w, h);\n        }\n    }\n}();\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/app/common.js",
    "content": "/*刷新表格*/\nfunction refresh(){\n    var table = $('.table').DataTable();\n    table.ajax.reload(null,false);// 刷新表格数据，分页信息不会重置\n}\n\n/*时间转换*/\nfunction date(data){\n    if(data==null||data==\"\"){\n        return \"\";\n    }\n    var time = new Date(data);\n    var y = time.getFullYear();//年\n    var m = time.getMonth() + 1;//月\n    if (m >= 0 && m <= 9) {\n        m = \"0\" + m;\n    }\n    var d = time.getDate();//日\n    if (d >= 0 && d <= 9) {\n        d = \"0\" + d;\n    }\n    var h = time.getHours();//时\n    if (h >= 0 && h <= 9) {\n        h = \"0\" + h;\n    }\n    var mm = time.getMinutes();//分\n    if (mm >= 0 && mm <= 9) {\n        mm = \"0\" + mm;\n    }\n    return (y+\"-\"+m+\"-\"+d+\" \"+h+\":\"+mm);\n}\n\n/*时间转换2*/\nfunction dateAll(data){\n    if(data==null||data==\"\"){\n        return \"\";\n    }\n    var time = new Date(data);\n    var y = time.getFullYear();//年\n    var m = time.getMonth() + 1;//月\n    if (m >= 0 && m <= 9) {\n        m = \"0\" + m;\n    }\n    var d = time.getDate();//日\n    if (d >= 0 && d <= 9) {\n        d = \"0\" + d;\n    }\n    var h = time.getHours();//时\n    if (h >= 0 && h <= 9) {\n        h = \"0\" + h;\n    }\n    var mm = time.getMinutes();//分\n    if (mm >= 0 && mm <= 9) {\n        mm = \"0\" + mm;\n    }\n    var ss = time.getSeconds();//秒\n    if (ss >= 0 && ss <= 9) {\n        ss = \"0\" + ss;\n    }\n    return (y+\"-\"+m+\"-\"+d+\" \"+h+\":\"+mm+\":\"+ss);\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/app/const.js",
    "content": "// 通用的常量\nvar ERROR_REQUEST_MESSAGE = \"连接服务器失败，请检查您的网络信息\";\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/app/validate.js",
    "content": "/**\n * 函数对象\n */\nvar Validate = function () {\n\n    /**\n     * 增加自定义验证规则\n     */\n    var handlerInitDecimalsValidate = function () {\n        jQuery.validator.addMethod(\"decimalsValue\",function(value, element) {\n            var decimalsValue =/^(?!0+(?:\\.0+)?$)(?:[1-9]\\d*|0)(?:\\.\\d{1,2})?$/ ;\n            return this.optional(element) || (decimalsValue.test(value));\n        }, \"金额必须大于0并且只能精确到分\");\n    };\n\n    /**\n     * 初始化 Validae\n     */\n    var handlerInitValidate = function (url, beforeSubmit, successMethod) {\n        $(\"#validate-form\").validate({\n            ignore: \":hidden\",//不验证的元素\n            rules: {\n                picUrl: {\n                    required: true,\n                    minlength: 1,\n                    maxlength: 20\n                },\n                fullUrl: {\n                    required: true,\n                    minlength: 10\n                },\n                sortOrder: {\n                    required: true,\n                    digits: true,\n                    maxlength: 4\n                },\n                name: {\n                    required: true,\n                    minlength: 1,\n                    maxlength: 25\n                },\n                limitNum: {\n                    required: true,\n                    digits: true,\n                    maxlength: 3\n                },\n                title: {\n                    required: true\n                },\n                sellPoint: {\n                    required: true\n                },\n                cname: {\n                    required: true\n                },\n                price: {\n                    decimalsValue: true,\n                    required: true,\n                    maxlength: 10\n                },\n                num: {\n                    digits: true,\n                    required: true,\n                    maxlength: 5\n                },\n                shippingName: {\n                    required: true\n                },\n                shippingCode: {\n                    required: true\n                },\n                password: {\n                    required: true,\n                    minlength: 6,\n                },\n                password2: {\n                    required: true,\n                    minlength: 6,\n                    equalTo: \"#password\"\n                },\n                expressName:{\n                    required:true,\n                }\n            },\n            messages: {\n                picUrl: {\n                    required: \"名称不能为空\"\n                },\n                fullUrl: {\n                    required: \"跳转链接不能为空\"\n                },\n                sortOrder: {\n                    required: \"排序值不能为空\",\n                },\n                name: {\n                    required: \"板块名称不能为空\"\n                },\n                limitNum: {\n                    required: \"限制数量不能为空\"\n                },\n                cname: {\n                    required: \"商品分类不能\"\n                },\n                price: {\n                    required: \"产品展示价格不能为空\"\n                },\n                num: {\n                    required: \"库存数量不能为空\"\n                },\n                shippingName: {\n                    required: \"请选择快递名称\"\n                },\n                shippingCode: {\n                    required: \"请填写快递单号\"\n                },\n                password: {\n                    required: \"请填写密码\",\n                },\n                password2: {\n                    required: \"请确认密码\",\n                    equalTo: \"两次密码输入不一致\"\n                },\n                expressName:{\n                    required: \"快递名称不能为空\"\n                }\n            },\n            submitHandler: function (form) {\n                if (beforeSubmit != \"\") {\n                    if(!beforeSubmit()) {\n                        return;\n                    }\n                }\n                var index = layer.load(3);\n                $(form).ajaxSubmit({\n                    url: url,\n                    type: \"POST\",\n                    success: function (data) {\n                        layer.close(index);\n                        if (data.status == 200) {\n                            successMethod(data);\n                        } else {\n                            layer.alert(data.message, {title: '错误信息', icon: 2});\n                        }\n                    },\n                    error: function () {\n                        layer.close(index);\n                        layer.alert(ERROR_REQUEST_MESSAGE, {title: \"错误信息\", icon: 2});\n                    }\n                });\n            }\n        });\n    };\n\n    return {\n        /**\n         * 验证\n         */\n        validate: function (url, beforeSubmit, successMethod) {\n            handlerInitDecimalsValidate();\n            handlerInitValidate(url, beforeSubmit, successMethod);\n        }\n    }\n}();\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/DD_belatedPNG_0.0.8a-min.js",
    "content": "/**\n* DD_belatedPNG: Adds IE6 support: PNG images for CSS background-image and HTML <IMG/>.\n* Author: Drew Diller\n* Email: drew.diller@gmail.com\n* URL: http://www.dillerdesign.com/experiment/DD_belatedPNG/\n* Version: 0.0.8a\n* Licensed under the MIT License: http://dillerdesign.com/experiment/DD_belatedPNG/#license\n*\n* Example usage:\n* DD_belatedPNG.fix('.png_bg'); // argument is a CSS selector\n* DD_belatedPNG.fixPng( someNode ); // argument is an HTMLDomElement\n**/\nvar DD_belatedPNG={ns:\"DD_belatedPNG\",imgSize:{},delay:10,nodesFixed:0,createVmlNameSpace:function(){if(document.namespaces&&!document.namespaces[this.ns]){document.namespaces.add(this.ns,\"urn:schemas-microsoft-com:vml\")}},createVmlStyleSheet:function(){var b,a;b=document.createElement(\"style\");b.setAttribute(\"media\",\"screen\");document.documentElement.firstChild.insertBefore(b,document.documentElement.firstChild.firstChild);if(b.styleSheet){b=b.styleSheet;b.addRule(this.ns+\"\\\\:*\",\"{behavior:url(#default#VML)}\");b.addRule(this.ns+\"\\\\:shape\",\"position:absolute;\");b.addRule(\"img.\"+this.ns+\"_sizeFinder\",\"behavior:none; border:none; position:absolute; z-index:-1; top:-10000px; visibility:hidden;\");this.screenStyleSheet=b;a=document.createElement(\"style\");a.setAttribute(\"media\",\"print\");document.documentElement.firstChild.insertBefore(a,document.documentElement.firstChild.firstChild);a=a.styleSheet;a.addRule(this.ns+\"\\\\:*\",\"{display: none !important;}\");a.addRule(\"img.\"+this.ns+\"_sizeFinder\",\"{display: none !important;}\")}},readPropertyChange:function(){var b,c,a;b=event.srcElement;if(!b.vmlInitiated){return}if(event.propertyName.search(\"background\")!=-1||event.propertyName.search(\"border\")!=-1){DD_belatedPNG.applyVML(b)}if(event.propertyName==\"style.display\"){c=(b.currentStyle.display==\"none\")?\"none\":\"block\";for(a in b.vml){if(b.vml.hasOwnProperty(a)){b.vml[a].shape.style.display=c}}}if(event.propertyName.search(\"filter\")!=-1){DD_belatedPNG.vmlOpacity(b)}},vmlOpacity:function(b){if(b.currentStyle.filter.search(\"lpha\")!=-1){var a=b.currentStyle.filter;a=parseInt(a.substring(a.lastIndexOf(\"=\")+1,a.lastIndexOf(\")\")),10)/100;b.vml.color.shape.style.filter=b.currentStyle.filter;b.vml.image.fill.opacity=a}},handlePseudoHover:function(a){setTimeout(function(){DD_belatedPNG.applyVML(a)},1)},fix:function(a){if(this.screenStyleSheet){var c,b;c=a.split(\",\");for(b=0;b<c.length;b++){this.screenStyleSheet.addRule(c[b],\"behavior:expression(DD_belatedPNG.fixPng(this))\")}}},applyVML:function(a){a.runtimeStyle.cssText=\"\";this.vmlFill(a);this.vmlOffsets(a);this.vmlOpacity(a);if(a.isImg){this.copyImageBorders(a)}},attachHandlers:function(i){var d,c,g,e,b,f;d=this;c={resize:\"vmlOffsets\",move:\"vmlOffsets\"};if(i.nodeName==\"A\"){e={mouseleave:\"handlePseudoHover\",mouseenter:\"handlePseudoHover\",focus:\"handlePseudoHover\",blur:\"handlePseudoHover\"};for(b in e){if(e.hasOwnProperty(b)){c[b]=e[b]}}}for(f in c){if(c.hasOwnProperty(f)){g=function(){d[c[f]](i)};i.attachEvent(\"on\"+f,g)}}i.attachEvent(\"onpropertychange\",this.readPropertyChange)},giveLayout:function(a){a.style.zoom=1;if(a.currentStyle.position==\"static\"){a.style.position=\"relative\"}},copyImageBorders:function(b){var c,a;c={borderStyle:true,borderWidth:true,borderColor:true};for(a in c){if(c.hasOwnProperty(a)){b.vml.color.shape.style[a]=b.currentStyle[a]}}},vmlFill:function(e){if(!e.currentStyle){return}else{var d,f,g,b,a,c;d=e.currentStyle}for(b in e.vml){if(e.vml.hasOwnProperty(b)){e.vml[b].shape.style.zIndex=d.zIndex}}e.runtimeStyle.backgroundColor=\"\";e.runtimeStyle.backgroundImage=\"\";f=true;if(d.backgroundImage!=\"none\"||e.isImg){if(!e.isImg){e.vmlBg=d.backgroundImage;e.vmlBg=e.vmlBg.substr(5,e.vmlBg.lastIndexOf('\")')-5)}else{e.vmlBg=e.src}g=this;if(!g.imgSize[e.vmlBg]){a=document.createElement(\"img\");g.imgSize[e.vmlBg]=a;a.className=g.ns+\"_sizeFinder\";a.runtimeStyle.cssText=\"behavior:none; position:absolute; left:-10000px; top:-10000px; border:none; margin:0; padding:0;\";c=function(){this.width=this.offsetWidth;this.height=this.offsetHeight;g.vmlOffsets(e)};a.attachEvent(\"onload\",c);a.src=e.vmlBg;a.removeAttribute(\"width\");a.removeAttribute(\"height\");document.body.insertBefore(a,document.body.firstChild)}e.vml.image.fill.src=e.vmlBg;f=false}e.vml.image.fill.on=!f;e.vml.image.fill.color=\"none\";e.vml.color.shape.style.backgroundColor=d.backgroundColor;e.runtimeStyle.backgroundImage=\"none\";e.runtimeStyle.backgroundColor=\"transparent\"},vmlOffsets:function(d){var h,n,a,e,g,m,f,l,j,i,k;h=d.currentStyle;n={W:d.clientWidth+1,H:d.clientHeight+1,w:this.imgSize[d.vmlBg].width,h:this.imgSize[d.vmlBg].height,L:d.offsetLeft,T:d.offsetTop,bLW:d.clientLeft,bTW:d.clientTop};a=(n.L+n.bLW==1)?1:0;e=function(b,p,q,c,s,u){b.coordsize=c+\",\"+s;b.coordorigin=u+\",\"+u;b.path=\"m0,0l\"+c+\",0l\"+c+\",\"+s+\"l0,\"+s+\" xe\";b.style.width=c+\"px\";b.style.height=s+\"px\";b.style.left=p+\"px\";b.style.top=q+\"px\"};e(d.vml.color.shape,(n.L+(d.isImg?0:n.bLW)),(n.T+(d.isImg?0:n.bTW)),(n.W-1),(n.H-1),0);e(d.vml.image.shape,(n.L+n.bLW),(n.T+n.bTW),(n.W),(n.H),1);g={X:0,Y:0};if(d.isImg){g.X=parseInt(h.paddingLeft,10)+1;g.Y=parseInt(h.paddingTop,10)+1}else{for(j in g){if(g.hasOwnProperty(j)){this.figurePercentage(g,n,j,h[\"backgroundPosition\"+j])}}}d.vml.image.fill.position=(g.X/n.W)+\",\"+(g.Y/n.H);m=h.backgroundRepeat;f={T:1,R:n.W+a,B:n.H,L:1+a};l={X:{b1:\"L\",b2:\"R\",d:\"W\"},Y:{b1:\"T\",b2:\"B\",d:\"H\"}};if(m!=\"repeat\"||d.isImg){i={T:(g.Y),R:(g.X+n.w),B:(g.Y+n.h),L:(g.X)};if(m.search(\"repeat-\")!=-1){k=m.split(\"repeat-\")[1].toUpperCase();i[l[k].b1]=1;i[l[k].b2]=n[l[k].d]}if(i.B>n.H){i.B=n.H}d.vml.image.shape.style.clip=\"rect(\"+i.T+\"px \"+(i.R+a)+\"px \"+i.B+\"px \"+(i.L+a)+\"px)\"}else{d.vml.image.shape.style.clip=\"rect(\"+f.T+\"px \"+f.R+\"px \"+f.B+\"px \"+f.L+\"px)\"}},figurePercentage:function(d,c,f,a){var b,e;e=true;b=(f==\"X\");switch(a){case\"left\":case\"top\":d[f]=0;break;case\"center\":d[f]=0.5;break;case\"right\":case\"bottom\":d[f]=1;break;default:if(a.search(\"%\")!=-1){d[f]=parseInt(a,10)/100}else{e=false}}d[f]=Math.ceil(e?((c[b?\"W\":\"H\"]*d[f])-(c[b?\"w\":\"h\"]*d[f])):parseInt(a,10));if(d[f]%2===0){d[f]++}return d[f]},fixPng:function(c){c.style.behavior=\"none\";var g,b,f,a,d;if(c.nodeName==\"BODY\"||c.nodeName==\"TD\"||c.nodeName==\"TR\"){return}c.isImg=false;if(c.nodeName==\"IMG\"){if(c.src.toLowerCase().search(/\\.png$/)!=-1){c.isImg=true;c.style.visibility=\"hidden\"}else{return}}else{if(c.currentStyle.backgroundImage.toLowerCase().search(\".png\")==-1){return}}g=DD_belatedPNG;c.vml={color:{},image:{}};b={shape:{},fill:{}};for(a in c.vml){if(c.vml.hasOwnProperty(a)){for(d in b){if(b.hasOwnProperty(d)){f=g.ns+\":\"+d;c.vml[a][d]=document.createElement(f)}}c.vml[a].shape.stroked=false;c.vml[a].shape.appendChild(c.vml[a].fill);c.parentNode.insertBefore(c.vml[a].shape,c)}}c.vml.image.shape.fillcolor=\"none\";c.vml.image.fill.type=\"tile\";c.vml.color.fill.on=false;g.attachHandlers(c);g.giveLayout(c);g.giveLayout(c.offsetParent);c.vmlInitiated=true;g.applyVML(c)}};try{document.execCommand(\"BackgroundImageCache\",false,true)}catch(r){}DD_belatedPNG.createVmlNameSpace();DD_belatedPNG.createVmlStyleSheet();"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/Hui-iconfont/1.0.8/demo.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\"/>\n<title>Hui-iconfont_v1.0.8</title>\n<link href=\"http://static.h-ui.net/h-ui/css/H-ui.min.css\" rel=\"stylesheet\" type=\"text/css\" />\n<link rel=\"stylesheet\" href=\"iconfont.css\">\n<style type=\"text/css\">\n.main {padding: 30px 100px;}\n.main h1{font-size:36px; line-height:1.6; color:#333; text-align:center;margin-bottom:30px; font-weight:normal}\n.main h2{ font-size:24px;line-height:1.6;color:#333;margin-bottom:30px; border-bottom: 1px solid #eee; font-weight:normal}\n\n.helps { margin-top: 40px}\n.helps pre{padding: 20px;margin: 10px 0;border: solid 1px #e7e1cd;background-color: #fffdef;overflow: auto}\n.icon_lists li{float: left;width: 100px;height: 190px;text-align: center}\n.icon_lists .Hui-iconfont{font-size: 42px;line-height: 100px;margin: 10px 0;color: #333;-webkit-transition: font-size 0.25s ease-out 0s;-moz-transition: font-size 0.25s ease-out 0s;transition: font-size 0.25s ease-out 0s}\n.icon_lists .Hui-iconfont:hover { font-size: 100px}\n</style>\n</head>\n<body>\n<div class=\"main\">\n\t<h1>Hui-iconfont_v1.0.8</h1>\n\t<p class=\"text-c c-999\">最后更新日期：2016.06.21  比1.0.7版本增加10个图标</p>\n\t\n\t<h2>操作相关</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe684;</i>\n\t\t\t<div class=\"name\">返回顶部</div>\n\t\t\t<div class=\"code\">&amp;#xe684;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-gotop</div>\n\t\t</li>\n\t\t<li><i class=\"icon Hui-iconfont\">&#xe667;</i>\n            <div class=\"name\">列表</div>\n            <div class=\"code\">&amp;#xe667;</div>\n            <div class=\"fontclass\">.Hui-iconfont-menu</div>\n        </li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe64e;</i>\n\t\t\t<div class=\"name\">剪切</div>\n\t\t\t<div class=\"code\">&amp;#xe64e;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-jiandao</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe665;</i>\n\t\t\t<div class=\"name\">搜索2</div>\n\t\t\t<div class=\"code\">&amp;#xe665;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-search2</div>\n\t\t</li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe709;</i>\n            <div class=\"name\">搜索1</div>\n            <div class=\"code\">&amp;#xe709;</div>\n            <div class=\"fontclass\">.Hui-iconfont-search1</div>\n        </li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe632;</i>\n\t\t\t<div class=\"name\">保存</div>\n\t\t\t<div class=\"code\">&amp;#xe632;</div>\n\t\t\t<div class=\"fontclass\">.save</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe66b;</i>\n\t\t\t<div class=\"name\">撤销</div>\n\t\t\t<div class=\"code\">&amp;#xe66b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-chexiao</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe66c;</i>\n\t\t\t<div class=\"name\">重做</div>\n\t\t\t<div class=\"code\">&amp;#xe66c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-zhongzuo</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe640;</i>\n\t\t\t<div class=\"name\">下载</div>\n\t\t\t<div class=\"code\">&amp;#xe640;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-down</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe63d;</i>\n\t\t\t<div class=\"name\">切换器右</div>\n\t\t\t<div class=\"code\">&amp;#xe63d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-slider-right</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe67d;</i>\n\t\t\t<div class=\"name\">切换器左</div>\n\t\t\t<div class=\"code\">&amp;#xe67d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-slider-left</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe603;</i>\n\t\t\t<div class=\"name\">发布</div>\n\t\t\t<div class=\"code\">&amp;#xe603;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-fabu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe604;</i>\n\t\t\t<div class=\"name\">添加</div>\n\t\t\t<div class=\"code\">&amp;#xe604;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-add2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe68f;</i>\n\t\t\t<div class=\"name\">换一批</div>\n\t\t\t<div class=\"code\">&amp;#xe68f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-huanyipi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe606;</i>\n\t\t\t<div class=\"name\">等待</div>\n\t\t\t<div class=\"code\">&amp;#xe606;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-dengdai</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe644;</i>\n\t\t\t<div class=\"name\">导出</div>\n\t\t\t<div class=\"code\">&amp;#xe644;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-daochu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe645;</i>\n\t\t\t<div class=\"name\">导入</div>\n\t\t\t<div class=\"code\">&amp;#xe645;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-daoru</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe60b;</i>\n\t\t\t<div class=\"name\">删除</div>\n\t\t\t<div class=\"code\">&amp;#xe60b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-del</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe609;</i>\n\t\t\t<div class=\"name\">删除</div>\n\t\t\t<div class=\"code\">&amp;#xe609;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-del2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6e2;</i>\n\t\t\t<div class=\"name\">删除</div>\n\t\t\t<div class=\"code\">&amp;#xe6e2;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-del3</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe647;</i>\n\t\t\t<div class=\"name\">输入</div>\n\t\t\t<div class=\"code\">&amp;#xe647;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-shuru</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe600;</i>\n\t\t\t<div class=\"name\">添加</div>\n\t\t\t<div class=\"code\">&amp;#xe600;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-add</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6a1;</i>\n\t\t\t<div class=\"name\">减号</div>\n\t\t\t<div class=\"code\">&amp;#xe6a1;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-jianhao</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe60c;</i>\n\t\t\t<div class=\"name\">编辑</div>\n\t\t\t<div class=\"code\">&amp;#xe60c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-edit2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6df;</i>\n\t\t\t<div class=\"name\">编辑</div>\n\t\t\t<div class=\"code\">&amp;#xe6df;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-edit</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe61d;</i>\n\t\t\t<div class=\"name\">管理</div>\n\t\t\t<div class=\"code\">&amp;#xe61d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-manage</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe610;</i>\n\t\t\t<div class=\"name\">添加</div>\n\t\t\t<div class=\"code\">&amp;#xe610;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-add3</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe61f;</i>\n\t\t\t<div class=\"name\">添加</div>\n\t\t\t<div class=\"code\">&amp;#xe61f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-add4</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe63f;</i>\n\t\t\t<div class=\"name\">密码</div>\n\t\t\t<div class=\"code\">&amp;#xe63f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-key</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe605;</i>\n\t\t\t<div class=\"name\">解锁</div>\n\t\t\t<div class=\"code\">&amp;#xe605;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-jiesuo</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe60e;</i>\n\t\t\t<div class=\"name\">锁定</div>\n\t\t\t<div class=\"code\">&amp;#xe60e;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-suoding</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6a6;</i>\n\t\t\t<div class=\"name\">关闭</div>\n\t\t\t<div class=\"code\">&amp;#xe6a6;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-close</div>\n\t\t</li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe706;</i>\n            <div class=\"name\">关闭2</div>\n            <div class=\"code\">&amp;#xe706;</div>\n            <div class=\"fontclass\">.Hui-iconfont-close2</div>\n        </li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6a7;</i>\n\t\t\t<div class=\"name\">选择</div>\n\t\t\t<div class=\"code\">&amp;#xe6a7;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-xuanze</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe608;</i>\n\t\t\t<div class=\"name\">未选</div>\n\t\t\t<div class=\"code\">&amp;#xe608;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-weigouxuan2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6a8;</i>\n\t\t\t<div class=\"name\">选中</div>\n\t\t\t<div class=\"code\">&amp;#xe6a8;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-xuanzhong1</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe676;</i>\n\t\t\t<div class=\"name\">选中</div>\n\t\t\t<div class=\"code\">&amp;#xe676;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-xuanzhong</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe677;</i>\n\t\t\t<div class=\"name\">未选中</div>\n\t\t\t<div class=\"code\">&amp;#xe677;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-weixuanzhong</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe601;</i>\n\t\t\t<div class=\"name\">启用</div>\n\t\t\t<div class=\"code\">&amp;#xe601;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-gouxuan2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6f7;</i>\n\t\t\t<div class=\"name\">重启</div>\n\t\t\t<div class=\"code\">&amp;#xe6f7;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-chongqi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe617;</i>\n\t\t\t<div class=\"name\">勾选</div>\n\t\t\t<div class=\"code\">&amp;#xe617;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-selected</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6dc;</i>\n\t\t\t<div class=\"name\">上架</div>\n\t\t\t<div class=\"code\">&amp;#xe6dc;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-shangjia</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6de;</i>\n\t\t\t<div class=\"name\">下架</div>\n\t\t\t<div class=\"code\">&amp;#xe6de;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-xiajia</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe642;</i>\n\t\t\t<div class=\"name\">上传</div>\n\t\t\t<div class=\"code\">&amp;#xe642;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-upload</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe641;</i>\n\t\t\t<div class=\"name\">下载</div>\n\t\t\t<div class=\"code\">&amp;#xe641;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-yundown</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6bc;</i>\n\t\t\t<div class=\"name\">剪裁</div>\n\t\t\t<div class=\"code\">&amp;#xe6bc;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-caiqie</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6bd;</i>\n\t\t\t<div class=\"name\">旋转</div>\n\t\t\t<div class=\"code\">&amp;#xe6bd;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-xuanzhuan</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe615;</i>\n\t\t\t<div class=\"name\">启用</div>\n\t\t\t<div class=\"code\">&amp;#xe615;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-gouxuan</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6e1;</i>\n\t\t\t<div class=\"name\">未勾选</div>\n\t\t\t<div class=\"code\">&amp;#xe614;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-weigouxuan</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe619;</i>\n\t\t\t<div class=\"name\">录音</div>\n\t\t\t<div class=\"code\">&amp;#xe619;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-luyin</div>\n\t\t</li>\n\t\t\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe695;</i>\n\t\t\t<div class=\"name\">预览</div>\n\t\t\t<div class=\"code\">&amp;#xe695;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-yulan</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6e0;</i>\n\t\t\t<div class=\"name\">审核不通过</div>\n\t\t\t<div class=\"code\">&amp;#xe6e0;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-shenhe-weitongguo</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6dd;</i>\n\t\t\t<div class=\"name\">审核不通过</div>\n\t\t\t<div class=\"code\">&amp;#xe6dd;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-shenhe-butongguo2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6e1;</i>\n\t\t\t<div class=\"name\">审核通过</div>\n\t\t\t<div class=\"code\">&amp;#xe6e1;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-shenhe-tongguo</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe631;</i>\n\t\t\t<div class=\"name\">停用</div>\n\t\t\t<div class=\"code\">&amp;#xe631;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-shenhe-tingyong</div>\n\t\t</li>\n\t\t<li>\n            <i class=\"icon Hui-iconfont\">&#xe6e6;</i>\n            <div class=\"name\">播放</div>\n            <div class=\"code\">&amp;#xe6e6;</div>\n            <div class=\"fontclass\">.Hui-iconfont-bofang</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6db;</i>\n            <div class=\"name\">上一首</div>\n            <div class=\"code\">&amp;#xe6db;</div>\n            <div class=\"fontclass\">.Hui-iconfont-shangyishou</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6e3;</i>\n            <div class=\"name\">下一首</div>\n            <div class=\"code\">&amp;#xe6e3;</div>\n            <div class=\"fontclass\">.Hui-iconfont-xiayishou</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6e5;</i>\n            <div class=\"name\">暂停</div>\n            <div class=\"code\">&amp;#xe6e5;</div>\n            <div class=\"fontclass\">.Hui-iconfont-zanting</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6e4;</i>\n            <div class=\"name\">停止</div>\n            <div class=\"code\">&amp;#xe6e4;</div>\n            <div class=\"fontclass\">.Hui-iconfont-tingzhi</div>\n        </li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe720;</i>\n\t\t\t<div class=\"name\">阅读</div>\n\t\t\t<div class=\"code\">&amp;#xe720;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-yuedu</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe725;</i>\n\t\t\t<div class=\"name\">眼睛</div>\n\t\t\t<div class=\"code\">&amp;#xe725;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-yanjing</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe726;</i>\n\t\t\t<div class=\"name\">电源</div>\n\t\t\t<div class=\"code\">&amp;#xe726;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-power</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe72a;</i>\n\t\t\t<div class=\"name\">图标2_橡皮擦</div>\n\t\t\t<div class=\"code\">&amp;#xe72a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-xiangpicha</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe728;</i>\n\t\t\t<div class=\"name\">计时器</div>\n\t\t\t<div class=\"code\">&amp;#xe728;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-jishiqi</div>\n\t\t</li>\n\t\t\n\t</ul>\n\t<h2>菜单相关</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe625;</i>\n\t\t\t<div class=\"name\">home</div>\n\t\t\t<div class=\"code\">&amp;#xe625;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-home</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe67f;</i>\n\t\t\t<div class=\"name\">小箭头</div>\n\t\t\t<div class=\"code\">&amp;#xe67f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-home2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe616;</i>\n\t\t\t<div class=\"name\">cmstop新闻</div>\n\t\t\t<div class=\"code\">&amp;#xe616;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-news</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe613;</i>\n\t\t\t<div class=\"name\">图片</div>\n\t\t\t<div class=\"code\">&amp;#xe613;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tuku</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe60f;</i>\n\t\t\t<div class=\"name\">音乐</div>\n\t\t\t<div class=\"code\">&amp;#xe60f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-music</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe64b;</i>\n\t\t\t<div class=\"name\">标签</div>\n\t\t\t<div class=\"code\">&amp;#xe64b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tags</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe66f;</i>\n\t\t\t<div class=\"name\">语音</div>\n\t\t\t<div class=\"code\">&amp;#xe66f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-yuyin3</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe62e;</i>\n\t\t\t<div class=\"name\">系统</div>\n\t\t\t<div class=\"code\">&amp;#xe62e;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-system</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe633;</i>\n\t\t\t<div class=\"name\">帮助</div>\n\t\t\t<div class=\"code\">&amp;#xe633;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-help</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe634;</i>\n\t\t\t<div class=\"name\">出库</div>\n\t\t\t<div class=\"code\">&amp;#xe634;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-chuku</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe646;</i>\n\t\t\t<div class=\"name\">图片</div>\n\t\t\t<div class=\"code\">&amp;#xe646;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-picture</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe681;</i>\n\t\t\t<div class=\"name\">分类</div>\n\t\t\t<div class=\"code\">&amp;#xe681;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-fenlei</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe636;</i>\n\t\t\t<div class=\"name\">合同管理</div>\n\t\t\t<div class=\"code\">&amp;#xe636;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-hetong</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe687;</i>\n\t\t\t<div class=\"name\">全部订单</div>\n\t\t\t<div class=\"code\">&amp;#xe687;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-quanbudingdan</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe637;</i>\n\t\t\t<div class=\"name\">任务管理</div>\n\t\t\t<div class=\"code\">&amp;#xe637;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-renwu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe691;</i>\n\t\t\t<div class=\"name\">问题反馈</div>\n\t\t\t<div class=\"code\">&amp;#xe691;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-feedback</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe692;</i>\n\t\t\t<div class=\"name\">意见反馈</div>\n\t\t\t<div class=\"code\">&amp;#xe692;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-feedback2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe639;</i>\n\t\t\t<div class=\"name\">合同</div>\n\t\t\t<div class=\"code\">&amp;#xe639;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-dangan</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe623;</i>\n\t\t\t<div class=\"name\">日志</div>\n\t\t\t<div class=\"code\">&amp;#xe623;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-log</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe626;</i>\n\t\t\t<div class=\"name\">列表页面</div>\n\t\t\t<div class=\"code\">&amp;#xe626;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-pages</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe63e;</i>\n\t\t\t<div class=\"name\">文件</div>\n\t\t\t<div class=\"code\">&amp;#xe63e;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-file</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe63c;</i>\n\t\t\t<div class=\"name\">管理</div>\n\t\t\t<div class=\"code\">&amp;#xe63c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-manage2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe627;</i>\n\t\t\t<div class=\"name\">订单</div>\n\t\t\t<div class=\"code\">&amp;#xe627;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-order</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6a4;</i>\n\t\t\t<div class=\"name\">语音</div>\n\t\t\t<div class=\"code\">&amp;#xe6a4;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-yuyin2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6a5;</i>\n\t\t\t<div class=\"name\">语音</div>\n\t\t\t<div class=\"code\">&amp;#xe6a5;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-yuyin</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe612;</i>\n\t\t\t<div class=\"name\">图片</div>\n\t\t\t<div class=\"code\">&amp;#xe612;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-picture1</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe685;</i>\n\t\t\t<div class=\"name\">图文详情</div>\n\t\t\t<div class=\"code\">&amp;#xe685;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tuwenxiangqing</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe72d;</i>\n\t\t\t<div class=\"name\">模版</div>\n\t\t\t<div class=\"code\">&amp;#xe72d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-moban-2</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe727;</i>\n\t\t\t<div class=\"name\">节日</div>\n\t\t\t<div class=\"code\">&amp;#xe727;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-jieri</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe72b;</i>\n\t\t\t<div class=\"name\">随你后台-网站</div>\n\t\t\t<div class=\"code\">&amp;#xe72b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-moban</div>\n\t\t</li>\n\t</ul>\n\t<h2>天气相关</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6ac;</i>\n\t\t\t<div class=\"name\">多云</div>\n\t\t\t<div class=\"code\">&amp;#xe6ac;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tianqi-duoyun</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6ad;</i>\n\t\t\t<div class=\"name\">霾</div>\n\t\t\t<div class=\"code\">&amp;#xe6ad;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tianqi-mai</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6ae;</i>\n\t\t\t<div class=\"name\">晴</div>\n\t\t\t<div class=\"code\">&amp;#xe6ae;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tianqi-qing</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6af;</i>\n\t\t\t<div class=\"name\">雾</div>\n\t\t\t<div class=\"code\">&amp;#xe6af;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tianqi-wu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6b0;</i>\n\t\t\t<div class=\"name\">雪</div>\n\t\t\t<div class=\"code\">&amp;#xe6b0;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tianqi-xue</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6b1;</i>\n\t\t\t<div class=\"name\">阴</div>\n\t\t\t<div class=\"code\">&amp;#xe6b1;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tianqi-yin</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6b2;</i>\n\t\t\t<div class=\"name\">雨</div>\n\t\t\t<div class=\"code\">&amp;#xe6b2;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tianqi-yu</div>\n\t\t</li>\n\t</ul>\n\t<h2>用户相关</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe62c;</i>\n\t\t\t<div class=\"name\">用户</div>\n\t\t\t<div class=\"code\">&amp;#xe62c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-user</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe60d;</i>\n\t\t\t<div class=\"name\">用户</div>\n\t\t\t<div class=\"code\">&amp;#xe60d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-user2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe60a;</i>\n\t\t\t<div class=\"name\">用户头像</div>\n\t\t\t<div class=\"code\">&amp;#xe60a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-avatar</div>\n\t\t</li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe705;</i>\n            <div class=\"name\">个人中心</div>\n            <div class=\"code\">&amp;#xe705;</div>\n            <div class=\"fontclass\">.Hui-iconfont-avatar2</div>\n        </li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe607;</i>\n\t\t\t<div class=\"name\">添加用户</div>\n\t\t\t<div class=\"code\">&amp;#xe607;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-user-add</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe602;</i>\n\t\t\t<div class=\"name\">用户ID</div>\n\t\t\t<div class=\"code\">&amp;#xe602;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-userid</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe638;</i>\n\t\t\t<div class=\"name\">证照管理</div>\n\t\t\t<div class=\"code\">&amp;#xe638;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-zhizhao</div>\n\t\t</li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe70d;</i>\n            <div class=\"name\">执业证</div>\n            <div class=\"code\">&amp;#xe70d;</div>\n            <div class=\"fontclass\">.Hui-iconfont-practice</div>\n        </li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe62b;</i>\n\t\t\t<div class=\"name\">群组</div>\n\t\t\t<div class=\"code\">&amp;#xe62b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-user-group</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe653;</i>\n\t\t\t<div class=\"name\">站长</div>\n\t\t\t<div class=\"code\">&amp;#xe653;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-user-zhanzhang</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe62d;</i>\n\t\t\t<div class=\"name\">管理员</div>\n\t\t\t<div class=\"code\">&amp;#xe62d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-root</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe643;</i>\n\t\t\t<div class=\"name\">公司</div>\n\t\t\t<div class=\"code\">&amp;#xe643;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-gongsi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6b4;</i>\n\t\t\t<div class=\"name\">会员卡</div>\n\t\t\t<div class=\"code\">&amp;#xe6b4;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-vip-card2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6cc;</i>\n\t\t\t<div class=\"name\">会员</div>\n\t\t\t<div class=\"code\">&amp;#xe6cc;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-vip</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe611;</i>\n\t\t\t<div class=\"name\">群组</div>\n\t\t\t<div class=\"code\">&amp;#xe611;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-usergroup2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6d0;</i>\n\t\t\t<div class=\"name\">客服</div>\n\t\t\t<div class=\"code\">&amp;#xe6d0;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-kefu</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe72c;</i>\n\t\t\t<div class=\"name\">版主</div>\n\t\t\t<div class=\"code\">&amp;#xe72c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-banzhu</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe6d3;</i>\n\t\t\t<div class=\"name\">皇冠</div>\n\t\t\t<div class=\"code\">&amp;#xe6d3;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-huangguan</div>\n\t\t</li>\n\t</ul>\n\t<h2>表情相关</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe68e;</i>\n\t\t\t<div class=\"name\">表情</div>\n\t\t\t<div class=\"code\">&amp;#xe68e;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe668;</i>\n\t\t\t<div class=\"name\">表情</div>\n\t\t\t<div class=\"code\">&amp;#xe668;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe656;</i>\n\t\t\t<div class=\"name\">微笑</div>\n\t\t\t<div class=\"code\">&amp;#xe656;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-weixiao</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe688;</i>\n\t\t\t<div class=\"name\">哭脸</div>\n\t\t\t<div class=\"code\">&amp;#xe688;</div>\n\t\t\t<div class=\"fontclass\">.face-ku</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe657;</i>\n\t\t\t<div class=\"name\">吃惊</div>\n\t\t\t<div class=\"code\">&amp;#xe657;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-chijing</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe658;</i>\n\t\t\t<div class=\"name\">呆</div>\n\t\t\t<div class=\"code\">&amp;#xe658;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-dai</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe659;</i>\n\t\t\t<div class=\"name\">耍酷</div>\n\t\t\t<div class=\"code\">&amp;#xe659;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-shuaku</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe65a;</i>\n\t\t\t<div class=\"name\">魔鬼</div>\n\t\t\t<div class=\"code\">&amp;#xe65a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-mogui</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe65b;</i>\n\t\t\t<div class=\"name\">尴尬</div>\n\t\t\t<div class=\"code\">&amp;#xe65b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-ganga</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe65c;</i>\n\t\t\t<div class=\"name\">亲</div>\n\t\t\t<div class=\"code\">&amp;#xe65c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-qin</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe65d;</i>\n\t\t\t<div class=\"name\">怒</div>\n\t\t\t<div class=\"code\">&amp;#xe65d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-nu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe65e;</i>\n\t\t\t<div class=\"name\">眨眼</div>\n\t\t\t<div class=\"code\">&amp;#xe65e;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-zhayan</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe65f;</i>\n\t\t\t<div class=\"name\">生气</div>\n\t\t\t<div class=\"code\">&amp;#xe65f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-shengqi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe660;</i>\n\t\t\t<div class=\"name\">骂</div>\n\t\t\t<div class=\"code\">&amp;#xe660;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-ma</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe661;</i>\n\t\t\t<div class=\"name\">鄙视</div>\n\t\t\t<div class=\"code\">&amp;#xe661;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-bishi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe662;</i>\n\t\t\t<div class=\"name\">卖萌</div>\n\t\t\t<div class=\"code\">&amp;#xe662;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-maimeng</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe663;</i>\n\t\t\t<div class=\"name\">惊呆</div>\n\t\t\t<div class=\"code\">&amp;#xe663;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-jingdai</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe664;</i>\n\t\t\t<div class=\"name\">晕</div>\n\t\t\t<div class=\"code\">&amp;#xe664;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-face-yun</div>\n\t\t</li>\n\t</ul>\n\t<h2>社区相关</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe666;</i>\n\t\t\t<div class=\"name\">分享</div>\n\t\t\t<div class=\"code\">&amp;#xe666;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6aa;</i>\n\t\t\t<div class=\"name\">分享</div>\n\t\t\t<div class=\"code\">&amp;#xe6aa;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6d8;</i>\n\t\t\t<div class=\"name\">人人网</div>\n\t\t\t<div class=\"code\">&amp;#xe6d8;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share-renren</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6d9;</i>\n\t\t\t<div class=\"name\">腾讯微博</div>\n\t\t\t<div class=\"code\">&amp;#xe6d9;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share-tweibo</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe67c;</i>\n\t\t\t<div class=\"name\">豆瓣</div>\n\t\t\t<div class=\"code\">&amp;#xe67c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share-douban</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe693;</i>\n\t\t\t<div class=\"name\">朋友圈</div>\n\t\t\t<div class=\"code\">&amp;#xe693;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share-pengyouquan</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe694;</i>\n\t\t\t<div class=\"name\">微信</div>\n\t\t\t<div class=\"code\">&amp;#xe694;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share-weixin</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe67b;</i>\n\t\t\t<div class=\"name\">QQ</div>\n\t\t\t<div class=\"code\">&amp;#xe67b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share-qq</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe6c8;</i>\n\t\t\t<div class=\"name\">QQ空间</div>\n\t\t\t<div class=\"code\">&amp;#xe6c8;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share-qzone</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe6da;</i>\n\t\t\t<div class=\"name\">微博</div>\n\t\t\t<div class=\"code\">&amp;#xe6da;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share-weibo</div>\n\t\t</li>\n\t\t\t<li> <i class=\"icon Hui-iconfont\">&#xe689;</i>\n\t\t\t<div class=\"name\">知乎</div>\n\t\t\t<div class=\"code\">&amp;#xe689;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-share-zhihu</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe715;</i>\n\t\t\t<div class=\"name\">更多</div>\n\t\t\t<div class=\"code\">&amp;#xe715;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-gengduo</div>\n\t\t</li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe716;</i>\n            <div class=\"name\">更多</div>\n            <div class=\"code\">&amp;#xe716;</div>\n            <div class=\"fontclass\">.Hui-iconfont-gengduo2</div>\n        </li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6f9;</i>\n            <div class=\"name\">更多</div>\n            <div class=\"code\">&amp;#xe6f9;</div>\n            <div class=\"fontclass\">.Hui-iconfont-engduo3</div>\n        </li>\n         <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe717;</i>\n            <div class=\"name\">更多</div>\n            <div class=\"code\">&amp;#xe717;</div>\n            <div class=\"fontclass\">.Hui-iconfont-gengduo4</div>\n        </li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe649;</i>\n\t\t\t<div class=\"name\">喜欢</div>\n\t\t\t<div class=\"code\">&amp;#xe649;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-like</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe648;</i>\n\t\t\t<div class=\"name\">喜欢</div>\n\t\t\t<div class=\"code\">&amp;#xe648;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-like2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe680;</i>\n\t\t\t<div class=\"name\">已关注</div>\n\t\t\t<div class=\"code\">&amp;#xe680;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-yiguanzhu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe622;</i>\n\t\t\t<div class=\"name\">评论</div>\n\t\t\t<div class=\"code\">&amp;#xe622;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-comment</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe686;</i>\n\t\t\t<div class=\"name\">累计评价</div>\n\t\t\t<div class=\"code\">&amp;#xe686;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-leijipingjia</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe68a;</i>\n\t\t\t<div class=\"name\">消息</div>\n\t\t\t<div class=\"code\">&amp;#xe68a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-xiaoxi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe61b;</i>\n\t\t\t<div class=\"name\">收藏</div>\n\t\t\t<div class=\"code\">&amp;#xe61b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-cang</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe630;</i>\n\t\t\t<div class=\"name\">收藏-选中</div>\n\t\t\t<div class=\"code\">&amp;#xe630;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-cang-selected</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe69e;</i>\n\t\t\t<div class=\"name\">收藏</div>\n\t\t\t<div class=\"code\">&amp;#xe69e;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-cang2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe69d;</i>\n\t\t\t<div class=\"name\">收藏-选中</div>\n\t\t\t<div class=\"code\">&amp;#xe69d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-cang2-selected</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe68b;</i>\n\t\t\t<div class=\"name\">关注-更多操作</div>\n\t\t\t<div class=\"code\">&amp;#xe68b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-more</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe66d;</i>\n\t\t\t<div class=\"name\">赞扬</div>\n\t\t\t<div class=\"code\">&amp;#xe66d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-zan</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe66e;</i>\n\t\t\t<div class=\"name\">批评</div>\n\t\t\t<div class=\"code\">&amp;#xe66e;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-cai</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe697;</i>\n\t\t\t<div class=\"name\">点赞</div>\n\t\t\t<div class=\"code\">&amp;#xe697;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-zan2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe62f;</i>\n\t\t\t<div class=\"name\">通知</div>\n\t\t\t<div class=\"code\">&amp;#xe62f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-msg</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe63b;</i>\n\t\t\t<div class=\"name\">消息管理</div>\n\t\t\t<div class=\"code\">&amp;#xe63b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-email</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6a9;</i>\n\t\t\t<div class=\"name\">已关注店铺</div>\n\t\t\t<div class=\"code\">&amp;#xe6a9;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-yiguanzhu1</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6ab;</i>\n\t\t\t<div class=\"name\">转发</div>\n\t\t\t<div class=\"code\">&amp;#xe6ab;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-zhuanfa</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6b3;</i>\n\t\t\t<div class=\"name\">待评价</div>\n\t\t\t<div class=\"code\">&amp;#xe6b3;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-daipingjia</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6b5;</i>\n\t\t\t<div class=\"name\">积分</div>\n\t\t\t<div class=\"code\">&amp;#xe6b5;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-jifen</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6c5;</i>\n\t\t\t<div class=\"name\">消息</div>\n\t\t\t<div class=\"code\">&amp;#xe6c5;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-xiaoxi1</div>\n\t\t</li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe70b;</i>\n            <div class=\"name\">已读</div>\n            <div class=\"code\">&amp;#xe70b;</div>\n            <div class=\"fontclass\">.Hui-iconfont-read</div>\n        </li>\n    \n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe70c;</i>\n            <div class=\"name\">用户反馈</div>\n            <div class=\"code\">&amp;#xe70c;</div>\n            <div class=\"fontclass\">.Hui-iconfont-feedback1</div>\n        </li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6ce;</i>\n\t\t\t<div class=\"name\">订阅</div>\n\t\t\t<div class=\"code\">&amp;#xe6ce;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-dingyue</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6cd;</i>\n\t\t\t<div class=\"name\">提示</div>\n\t\t\t<div class=\"code\">&amp;#xe6cd;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tishi</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe702;</i>\n            <div class=\"name\">star-o</div>\n            <div class=\"code\">&amp;#xe702;</div>\n            <div class=\"fontclass\">.Hui-iconfont-star-o</div>\n        </li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe6ff;</i>\n            <div class=\"name\">star</div>\n            <div class=\"code\">&amp;#xe6ff;</div>\n            <div class=\"fontclass\">.Hui-iconfont-star</div>\n        </li>\n        <li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe700;</i>\n            <div class=\"name\">star-half</div>\n            <div class=\"code\">&amp;#xe700;</div>\n            <div class=\"fontclass\">.Hui-iconfont-star-half</div>\n        </li>\n        <li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe701;</i>\n            <div class=\"name\">star-half-empty</div>\n            <div class=\"code\">&amp;#xe701;</div>\n            <div class=\"fontclass\">.Hui-iconfont-star-halfempty</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe70a;</i>\n            <div class=\"name\">我的评价</div>\n            <div class=\"code\">&amp;#xe70a;</div>\n            <div class=\"fontclass\">.Hui-iconfont-comment1</div>\n        </li>\n\t</ul>\n\t<h2>统计相关</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe621;</i>\n\t\t\t<div class=\"name\">数据统计</div>\n\t\t\t<div class=\"code\">&amp;#xe621;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tongji-bing</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe635;</i>\n\t\t\t<div class=\"name\">统计管理</div>\n\t\t\t<div class=\"code\">&amp;#xe635;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-ad</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe61e;</i>\n\t\t\t<div class=\"name\">数据统计</div>\n\t\t\t<div class=\"code\">&amp;#xe61e;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-shujutongji</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe61a;</i>\n\t\t\t<div class=\"name\">统计</div>\n\t\t\t<div class=\"code\">&amp;#xe61a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tongji</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe618;</i>\n\t\t\t<div class=\"name\">柱状统计</div>\n\t\t\t<div class=\"code\">&amp;#xe618;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tongji-zhu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe61c;</i>\n\t\t\t<div class=\"name\">线状统计</div>\n\t\t\t<div class=\"code\">&amp;#xe61c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tongji-xian</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6cf;</i>\n\t\t\t<div class=\"name\">排行榜</div>\n\t\t\t<div class=\"code\">&amp;#xe6cf;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-paixingbang</div>\n\t\t</li>\n\t</ul>\n\t<h2>箭头相关</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe678;</i>\n\t\t\t<div class=\"name\">向左</div>\n\t\t\t<div class=\"code\">&amp;#xe678;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow1-bottom</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe674;</i>\n\t\t\t<div class=\"name\">向下</div>\n\t\t\t<div class=\"code\">&amp;#xe674;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow1-bottom</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe679;</i>\n\t\t\t<div class=\"name\">向上</div>\n\t\t\t<div class=\"code\">&amp;#xe679;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow1-top</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe67a;</i>\n\t\t\t<div class=\"name\">向右</div>\n\t\t\t<div class=\"code\">&amp;#xe67a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow1-right</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6d4;</i>\n\t\t\t<div class=\"name\">向左</div>\n\t\t\t<div class=\"code\">&amp;#xe6d4;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow2-left</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6d6;</i>\n\t\t\t<div class=\"name\">向上</div>\n\t\t\t<div class=\"code\">&amp;#xe6d6;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow2-top</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6d7;</i>\n\t\t\t<div class=\"name\">向右</div>\n\t\t\t<div class=\"code\">&amp;#xe6d7;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow2-right</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6d5;</i>\n\t\t\t<div class=\"name\">向下</div>\n\t\t\t<div class=\"code\">&amp;#xe6d5;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow2-bottom</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe69b;</i>\n\t\t\t<div class=\"name\">向左</div>\n\t\t\t<div class=\"code\">&amp;#xe69b;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow3-left</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe699;</i>\n\t\t\t<div class=\"name\">向上</div>\n\t\t\t<div class=\"code\">&amp;#xe699;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow3-top</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe69a;</i>\n\t\t\t<div class=\"name\">向右</div>\n\t\t\t<div class=\"code\">&amp;#xe69a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow3-right</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe698;</i>\n\t\t\t<div class=\"name\">向下</div>\n\t\t\t<div class=\"code\">&amp;#xe698;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-arrow3-bottom</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe67e;</i>\n\t\t\t<div class=\"name\">向右</div>\n\t\t\t<div class=\"code\">&amp;#xe67e;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-sanjiao</div>\n\t\t</li>\n\t</ul>\n\t<h2>电商相关</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe669;</i>\n\t\t\t<div class=\"name\">物流</div>\n\t\t\t<div class=\"code\">&amp;#xe669;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-wuliu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe66a;</i>\n\t\t\t<div class=\"name\">店铺</div>\n\t\t\t<div class=\"code\">&amp;#xe66a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-dianpu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe670;</i>\n\t\t\t<div class=\"name\">购物车</div>\n\t\t\t<div class=\"code\">&amp;#xe670;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-cart2-selected</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe672;</i>\n\t\t\t<div class=\"name\">购物车满</div>\n\t\t\t<div class=\"code\">&amp;#xe672;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-cart2-man</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe673;</i>\n\t\t\t<div class=\"name\">购物车空</div>\n\t\t\t<div class=\"code\">&amp;#xe673;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-card2-kong</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6b8;</i>\n\t\t\t<div class=\"name\">购物车-选中</div>\n\t\t\t<div class=\"code\">&amp;#xe6b8;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-cart-selected</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6b9;</i>\n\t\t\t<div class=\"name\">购物车</div>\n\t\t\t<div class=\"code\">&amp;#xe6b9;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-cart-kong</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6ba;</i>\n\t\t\t<div class=\"name\">降价</div>\n\t\t\t<div class=\"code\">&amp;#xe6ba;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-jiangjia</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe628;</i>\n\t\t\t<div class=\"name\">信用卡还款</div>\n\t\t\t<div class=\"code\">&amp;#xe628;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-bank</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6bb;</i>\n\t\t\t<div class=\"name\">礼物</div>\n\t\t\t<div class=\"code\">&amp;#xe6bb;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-liwu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6b6;</i>\n\t\t\t<div class=\"name\">优惠券</div>\n\t\t\t<div class=\"code\">&amp;#xe6b6;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-youhuiquan</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6b7;</i>\n\t\t\t<div class=\"name\">红包</div>\n\t\t\t<div class=\"code\">&amp;#xe6b7;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-hongbao</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6ca;</i>\n\t\t\t<div class=\"name\">优惠券</div>\n\t\t\t<div class=\"code\">&amp;#xe6ca;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-hongbao2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe63a;</i>\n\t\t\t<div class=\"name\">资金</div>\n\t\t\t<div class=\"code\">&amp;#xe63a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-money</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe620;</i>\n\t\t\t<div class=\"name\">商品</div>\n\t\t\t<div class=\"code\">&amp;#xe620;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-goods</div>\n\t\t</li>\n\t</ul>\n\t<h2>编辑器</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6ee;</i>\n            <div class=\"name\">code</div>\n            <div class=\"code\">&amp;#xe6ee;</div>\n            <div class=\"fontclass\">.Hui-iconfont-code</div>\n        </li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe710;</i>\n            <div class=\"name\">左对齐</div>\n            <div class=\"code\">&amp;#xe710;</div>\n            <div class=\"fontclass\">.Hui-iconfont-align-left</div>\n        </li>\n    \t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe70e;</i>\n            <div class=\"name\">居中对齐</div>\n            <div class=\"code\">&amp;#xe70e;</div>\n            <div class=\"fontclass\">.Hui-iconfont-align-center</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe711;</i>\n            <div class=\"name\">右对齐</div>\n            <div class=\"code\">&amp;#xe711;</div>\n            <div class=\"fontclass\">.Hui-iconfont-align-right</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe70f;</i>\n            <div class=\"name\">两头对齐</div>\n            <div class=\"code\">&amp;#xe70f;</div>\n            <div class=\"fontclass\">.Hui-iconfont-align-justify</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6ec;</i>\n            <div class=\"name\">字体</div>\n            <div class=\"code\">&amp;#xe6ec;</div>\n            <div class=\"fontclass\">.Hui-iconfont-font</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6e7;</i>\n            <div class=\"name\">加粗</div>\n            <div class=\"code\">&amp;#xe6e7;</div>\n            <div class=\"fontclass\">.Hui-iconfont-bold</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6e9;</i>\n            <div class=\"name\">倾斜</div>\n            <div class=\"code\">&amp;#xe6e9;</div>\n            <div class=\"fontclass\">.Hui-iconfont-italic</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6fe;</i>\n            <div class=\"name\">下划线</div>\n            <div class=\"code\">&amp;#xe6fe;</div>\n            <div class=\"fontclass\">.Hui-iconfont-underline</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6fc;</i>\n            <div class=\"name\">text-height</div>\n            <div class=\"code\">&amp;#xe6fc;</div>\n            <div class=\"fontclass\">.Hui-iconfont-text-height</div>\n        </li>\n    \n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6fd;</i>\n            <div class=\"name\">text-width</div>\n            <div class=\"code\">&amp;#xe6fd;</div>\n            <div class=\"fontclass\">.Hui-iconfont-text-width</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6f1;</i>\n            <div class=\"name\">link</div>\n            <div class=\"code\">&amp;#xe6f1;</div>\n            <div class=\"fontclass\">.Hui-iconfont-link</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6f3;</i>\n            <div class=\"name\">有序列表</div>\n            <div class=\"code\">&amp;#xe6f3;</div>\n            <div class=\"fontclass\">.Hui-iconfont-ordered-list</div>\n        </li>\n    \n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6f5;</i>\n            <div class=\"name\">无序列表</div>\n            <div class=\"code\">&amp;#xe6f5;</div>\n            <div class=\"fontclass\">.Hui-iconfont-unordered-list</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6ef;</i>\n            <div class=\"name\">剪切</div>\n            <div class=\"code\">&amp;#xe6ef;</div>\n            <div class=\"fontclass\">.Hui-iconfont-cut</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6ea;</i>\n            <div class=\"name\">复制</div>\n            <div class=\"code\">&amp;#xe6ea;</div>\n            <div class=\"fontclass\">.Hui-iconfont-copy</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6eb;</i>\n            <div class=\"name\">粘贴</div>\n            <div class=\"code\">&amp;#xe6eb;</div>\n            <div class=\"fontclass\">.Hui-iconfont-paste</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6f2;</i>\n            <div class=\"name\">新建</div>\n            <div class=\"code\">&amp;#xe6f2;</div>\n            <div class=\"fontclass\">.Hui-iconfont-new</div>\n        </li>\n\t</ul>\n\t<h2>银行、支付相关</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe71f;</i>\n\t\t\t<div class=\"name\">支付宝支付1</div>\n\t\t\t<div class=\"code\">&amp;#xe71f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-pay-alipay-1</div>\n\t\t</li>  \n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe71c;</i>\n\t\t\t<div class=\"name\">支付宝支付2</div>\n\t\t\t<div class=\"code\">&amp;#xe71c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-pay-alipay-2</div>\n\t\t</li>\n\t\t<li>\n\t\t\t<i class=\"icon Hui-iconfont\">&#xe719;</i>\n\t\t\t<div class=\"name\">微信支付</div>\n\t\t\t<div class=\"code\">&amp;#xe719;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-pay-weixin</div>\n\t\t</li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe722;</i>\n            <div class=\"name\">中国银行</div>\n            <div class=\"code\">&amp;#xe722;</div>\n            <div class=\"fontclass\">.Hui-iconfont-zhongguoyinxing</div>\n        </li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe71d;</i>\n            <div class=\"name\">工商银行</div>\n            <div class=\"code\">&amp;#xe71d;</div>\n            <div class=\"fontclass\">.Hui-iconfont-gongshangyinxing</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6f8;</i>\n            <div class=\"name\">建设银行</div>\n            <div class=\"code\">&amp;#xe6f8;</div>\n            <div class=\"fontclass\">.Hui-iconfont-jiansheyinxing</div>\n        </li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe71a;</i>\n            <div class=\"name\">交通银行</div>\n            <div class=\"code\">&amp;#xe71a;</div>\n            <div class=\"fontclass\">.Hui-iconfont-jiaotongyinxing</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe713;</i>\n            <div class=\"name\">中国农业银行</div>\n            <div class=\"code\">&amp;#xe713;</div>\n            <div class=\"fontclass\">.Hui-iconfont-zhongguonongyeyinxing</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe721;</i>\n            <div class=\"name\">邮政银行</div>\n            <div class=\"code\">&amp;#xe721;</div>\n            <div class=\"fontclass\">.Hui-iconfont-youzhengyinxing</div>\n        </li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe71b;</i>\n            <div class=\"name\">浦发银行</div>\n            <div class=\"code\">&amp;#xe71b;</div>\n            <div class=\"fontclass\">.Hui-iconfont-pufayinxing</div>\n        </li>  \n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe71e;</i>\n            <div class=\"name\">华夏银行</div>\n            <div class=\"code\">&amp;#xe71e;</div>\n            <div class=\"fontclass\">.Hui-iconfont-huaxiayinxing</div>\n        </li>\n    \t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe704;</i>\n            <div class=\"name\">招商银行</div>\n            <div class=\"code\">&amp;#xe704;</div>\n            <div class=\"fontclass\">.Hui-iconfont-zhaoshangyinxing</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe723;</i>\n            <div class=\"name\">中信银行</div>\n            <div class=\"code\">&amp;#xe723;</div>\n            <div class=\"fontclass\">.Hui-iconfont-zhongxinyinxing</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe724;</i>\n            <div class=\"name\">上海银行</div>\n            <div class=\"code\">&amp;#xe724;</div>\n            <div class=\"fontclass\">.Hui-iconfont-shanghaiyinxing</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6ed;</i>\n            <div class=\"name\">温州银行</div>\n            <div class=\"code\">&amp;#xe6ed;</div>\n            <div class=\"fontclass\">.Hui-iconfont-wenzhouyinxing</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6f0;</i>\n            <div class=\"name\">光大银行</div>\n            <div class=\"code\">&amp;#xe6f0;</div>\n            <div class=\"fontclass\">.Hui-iconfont-guangdayinxing</div>\n        </li>\n    \n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6f4;</i>\n            <div class=\"name\">民生银行</div>\n            <div class=\"code\">&amp;#xe6f4;</div>\n            <div class=\"fontclass\">.Hui-iconfont-minshengyinxing</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6f6;</i>\n            <div class=\"name\">青岛银行</div>\n            <div class=\"code\">&amp;#xe6f6;</div>\n            <div class=\"fontclass\">.Hui-iconfont-qingdaoyinxing</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe6fb;</i>\n            <div class=\"name\">北京银行</div>\n            <div class=\"code\">&amp;#xe6fb;</div>\n            <div class=\"fontclass\">.Hui-iconfont-beijingyinxing</div>\n        </li>\n    \n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe703;</i>\n            <div class=\"name\">广东发展银行</div>\n            <div class=\"code\">&amp;#xe703;</div>\n            <div class=\"fontclass\">.Hui-iconfont-guangdongfazhanyinxing</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe712;</i>\n            <div class=\"name\">浙商银行</div>\n            <div class=\"code\">&amp;#xe712;</div>\n            <div class=\"fontclass\">.Hui-iconfont-zheshangyinxing</div>\n        </li> \n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe714;</i>\n            <div class=\"name\">成都银行</div>\n            <div class=\"code\">&amp;#xe714;</div>\n            <div class=\"fontclass\">.Hui-iconfont-cdbank</div>\n        </li>\n        <li>\n        \t<i class=\"icon Hui-iconfont\">&#xe718;</i>\n            <div class=\"name\">杭州银行</div>\n            <div class=\"code\">&amp;#xe718;</div>\n            <div class=\"fontclass\">.Hui-iconfont-hangzhouyinxing</div>\n        </li>\n\t</ul>\n\t<h2>其他</h2>\n\t<ul class=\"icon_lists cl\">\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6c7;</i>\n\t\t\t<div class=\"name\">电话</div>\n\t\t\t<div class=\"code\">&amp;#xe6c7;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tel</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6a3;</i>\n\t\t\t<div class=\"name\">电话</div>\n\t\t\t<div class=\"code\">&amp;#xe6a3;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-tel2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe696;</i>\n\t\t\t<div class=\"name\">iphone手机</div>\n\t\t\t<div class=\"code\">&amp;#xe696;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-phone</div>\n\t\t</li>\n\t\t<li>\n        \t<i class=\"icon Hui-iconfont\">&#xe708;</i>\n            <div class=\"name\">安卓手机</div>\n            <div class=\"code\">&amp;#xe708;</div>\n            <div class=\"fontclass\">.Hui-iconfont-phone-android</div>\n        </li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe64c;</i>\n\t\t\t<div class=\"name\">平板电脑</div>\n\t\t\t<div class=\"code\">&amp;#xe64c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-pad</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe64f;</i>\n\t\t\t<div class=\"name\">PC</div>\n\t\t\t<div class=\"code\">&amp;#xe64f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-xianshiqi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe650;</i>\n\t\t\t<div class=\"name\">照相机</div>\n\t\t\t<div class=\"code\">&amp;#xe650;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-zhaoxiangji</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe651;</i>\n\t\t\t<div class=\"name\">单反相机</div>\n\t\t\t<div class=\"code\">&amp;#xe651;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-danfanxiangji</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe652;</i>\n\t\t\t<div class=\"name\">打印机</div>\n\t\t\t<div class=\"code\">&amp;#xe652;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-dayinji</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe64d;</i>\n\t\t\t<div class=\"name\">轮胎</div>\n\t\t\t<div class=\"code\">&amp;#xe64d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-lunzi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe654;</i>\n\t\t\t<div class=\"name\">插件</div>\n\t\t\t<div class=\"code\">&amp;#xe654;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-chajian</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe655;</i>\n\t\t\t<div class=\"name\">节日</div>\n\t\t\t<div class=\"code\">&amp;#xe655;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-jieri</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe675;</i>\n\t\t\t<div class=\"name\">排序</div>\n\t\t\t<div class=\"code\">&amp;#xe675;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-paixu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe624;</i>\n\t\t\t<div class=\"name\">匿名</div>\n\t\t\t<div class=\"code\">&amp;#xe624;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-niming</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe62a;</i>\n\t\t\t<div class=\"name\">换肤</div>\n\t\t\t<div class=\"code\">&amp;#xe62a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-pifu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6cb;</i>\n\t\t\t<div class=\"name\">二维码</div>\n\t\t\t<div class=\"code\">&amp;#xe6cb;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-2code</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe682;</i>\n\t\t\t<div class=\"name\">扫一扫</div>\n\t\t\t<div class=\"code\">&amp;#xe682;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-saoyisao</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe683;</i>\n\t\t\t<div class=\"name\">搜索</div>\n\t\t\t<div class=\"code\">&amp;#xe683;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-search</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe68c;</i>\n\t\t\t<div class=\"name\">中图模式</div>\n\t\t\t<div class=\"code\">&amp;#xe68c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-zhongtumoshi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe68d;</i>\n\t\t\t<div class=\"name\">大图模式</div>\n\t\t\t<div class=\"code\">&amp;#xe68d;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-datumoshi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6be;</i>\n\t\t\t<div class=\"name\">大图模式</div>\n\t\t\t<div class=\"code\">&amp;#xe6be;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-bigpic</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6c0;</i>\n\t\t\t<div class=\"name\">中图模式</div>\n\t\t\t<div class=\"code\">&amp;#xe6c0;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-middle</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6bf;</i>\n\t\t\t<div class=\"name\">列表模式</div>\n\t\t\t<div class=\"code\">&amp;#xe6bf;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-list</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe690;</i>\n\t\t\t<div class=\"name\">时间</div>\n\t\t\t<div class=\"code\">&amp;#xe690;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-shijian</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe69c;</i>\n\t\t\t<div class=\"name\">更多</div>\n\t\t\t<div class=\"code\">&amp;#xe69c;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-more2</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe629;</i>\n\t\t\t<div class=\"name\">SIM卡</div>\n\t\t\t<div class=\"code\">&amp;#xe629;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-sim</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6c1;</i>\n\t\t\t<div class=\"name\">火热</div>\n\t\t\t<div class=\"code\">&amp;#xe6c1;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-hot</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6c2;</i>\n\t\t\t<div class=\"name\">拍摄</div>\n\t\t\t<div class=\"code\">&amp;#xe6c2;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-paishe</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6c3;</i>\n\t\t\t<div class=\"name\">热销</div>\n\t\t\t<div class=\"code\">&amp;#xe6c3;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-hot1</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6c4;</i>\n\t\t\t<div class=\"name\">上新</div>\n\t\t\t<div class=\"code\">&amp;#xe6c4;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-new</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6c6;</i>\n\t\t\t<div class=\"name\">产品参数</div>\n\t\t\t<div class=\"code\">&amp;#xe6c6;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-canshu</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6c9;</i>\n\t\t\t<div class=\"name\">定位</div>\n\t\t\t<div class=\"code\">&amp;#xe6c9;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-dingwei</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe671;</i>\n\t\t\t<div class=\"name\">定位</div>\n\t\t\t<div class=\"code\">&amp;#xe671;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-weizhi</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe69f;</i>\n\t\t\t<div class=\"name\">HTML</div>\n\t\t\t<div class=\"code\">&amp;#xe69f;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-html</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6a0;</i>\n\t\t\t<div class=\"name\">CSS</div>\n\t\t\t<div class=\"code\">&amp;#xe6a0;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-css</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe64a;</i>\n\t\t\t<div class=\"name\">苹果</div>\n\t\t\t<div class=\"code\">&amp;#xe64a;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-apple</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6a2;</i>\n\t\t\t<div class=\"name\">android</div>\n\t\t\t<div class=\"code\">&amp;#xe6a2;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-android</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6d1;</i>\n\t\t\t<div class=\"name\">github</div>\n\t\t\t<div class=\"code\">&amp;#xe6d1;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-github</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6d2;</i>\n\t\t\t<div class=\"name\">html5</div>\n\t\t\t<div class=\"code\">&amp;#xe6d2;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-html5</div>\n\t\t</li>\n\t\t<li> <i class=\"icon Hui-iconfont\">&#xe6d3;</i>\n\t\t\t<div class=\"name\">皇冠</div>\n\t\t\t<div class=\"code\">&amp;#xe6d3;</div>\n\t\t\t<div class=\"fontclass\">.Hui-iconfont-huangguan</div>\n\t\t</li>\n\t</ul>\n\t<div class=\"helps\">\n\t\t<p>挑选相应图标并获取字体编码，应用于页面</p>\n\t\t<pre>&lt;i class=\"Hui-iconfont\"&gt;&amp;#xe684;&lt;/i&gt;</pre>\n\t</div>\n</div>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/Hui-iconfont/1.0.8/iconfont.css",
    "content": "/* -----------H-ui前端框架-------------\n* iconfont.css v1.0.8\n* http://www.h-ui.net/\n* Created & Modified by guojunhui\n* Date modified 2016.06.21\n*\n* Copyright 2013-2015 北京颖杰联创科技有限公司 All rights reserved.\n* Licensed under MIT license.\n* http://opensource.org/licenses/MIT\n*\n*/\n@font-face {font-family: \"Hui-iconfont\";\n  src: url('iconfont.eot'); /* IE9*/\n  src: url('iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */\n  url('iconfont.woff') format('woff'), /* chrome、firefox */\n  url('iconfont.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/\n  url('iconfont.svg#Hui-iconfont') format('svg'); /* iOS 4.1- */\n}\n\n.Hui-iconfont {\n  font-family:\"Hui-iconfont\" !important;\n  font-style:normal;\n  -webkit-font-smoothing: antialiased;\n  -webkit-text-stroke-width: 0.2px;\n  -moz-osx-font-smoothing: grayscale;\n}\n.Hui-iconfont-gotop:before { content: \"\\e684\"; }\n.Hui-iconfont-music:before { content: \"\\e60f\"; }\n.Hui-iconfont-tags:before { content: \"\\e64b\"; }\n.Hui-iconfont-jieri:before { content: \"\\e727\"; }\n.Hui-iconfont-jishiqi:before { content: \"\\e728\"; }\n.Hui-iconfont-pad:before { content: \"\\e64c\"; }\n.Hui-iconfont-lunzi:before { content: \"\\e64d\"; }\n.Hui-iconfont-jiandao:before { content: \"\\e64e\"; }\n.Hui-iconfont-xianshiqi:before { content: \"\\e64f\"; }\n.Hui-iconfont-zhaoxiangji:before { content: \"\\e650\"; }\n.Hui-iconfont-danfanxiangji:before { content: \"\\e651\"; }\n.Hui-iconfont-dayinji:before { content: \"\\e652\"; }\n.Hui-iconfont-user-zhanzhang:before { content: \"\\e653\"; }\n.Hui-iconfont-chajian:before { content: \"\\e654\"; }\n.Hui-iconfont-arrow1-bottom:before { content: \"\\e674\"; }\n.Hui-iconfont-arrow1-left:before { content: \"\\e678\"; }\n.Hui-iconfont-arrow1-top:before { content: \"\\e679\"; }\n.Hui-iconfont-arrow1-right:before { content: \"\\e67a\"; }\n.Hui-iconfont-jieri1:before { content: \"\\e655\"; }\n.Hui-iconfont-face-weixiao:before { content: \"\\e656\"; }\n.Hui-iconfont-face-chijing:before { content: \"\\e657\"; }\n.Hui-iconfont-face-dai:before { content: \"\\e658\"; }\n.Hui-iconfont-face-shuaku:before { content: \"\\e659\"; }\n.Hui-iconfont-face-mogui:before { content: \"\\e65a\"; }\n.Hui-iconfont-face-ganga:before { content: \"\\e65b\"; }\n.Hui-iconfont-face-qin:before { content: \"\\e65c\"; }\n.Hui-iconfont-face-nu:before { content: \"\\e65d\"; }\n.Hui-iconfont-face-zhayan:before { content: \"\\e65e\"; }\n.Hui-iconfont-face-shengqi:before { content: \"\\e65f\"; }\n.Hui-iconfont-face-ma:before { content: \"\\e660\"; }\n.Hui-iconfont-face-bishi:before { content: \"\\e661\"; }\n.Hui-iconfont-face-maimeng:before { content: \"\\e662\"; }\n.Hui-iconfont-face-jingdai:before { content: \"\\e663\"; }\n.Hui-iconfont-face-yun:before { content: \"\\e664\"; }\n.Hui-iconfont-home2:before { content: \"\\e67f\"; }\n.Hui-iconfont-search2:before { content: \"\\e665\"; }\n.Hui-iconfont-share2:before { content: \"\\e666\"; }\n.Hui-iconfont-face:before { content: \"\\e668\"; }\n.Hui-iconfont-wuliu:before { content: \"\\e669\"; }\n.Hui-iconfont-dianpu:before { content: \"\\e66a\"; }\n.Hui-iconfont-chexiao:before { content: \"\\e66b\"; }\n.Hui-iconfont-zhongzuo:before { content: \"\\e66c\"; }\n.Hui-iconfont-zan:before { content: \"\\e66d\"; }\n.Hui-iconfont-cai:before { content: \"\\e66e\"; }\n.Hui-iconfont-yuyin3:before { content: \"\\e66f\"; }\n.Hui-iconfont-cart2-selected:before { content: \"\\e670\"; }\n.Hui-iconfont-weizhi:before { content: \"\\e671\"; }\n.Hui-iconfont-face-ku:before { content: \"\\e688\"; }\n.Hui-iconfont-down:before { content: \"\\e640\"; }\n.Hui-iconfont-cart2-man:before { content: \"\\e672\"; }\n.Hui-iconfont-card2-kong:before { content: \"\\e673\"; }\n.Hui-iconfont-luyin:before { content: \"\\e619\"; }\n.Hui-iconfont-html:before { content: \"\\e69f\"; }\n.Hui-iconfont-css:before { content: \"\\e6a0\"; }\n.Hui-iconfont-android:before { content: \"\\e6a2\"; }\n.Hui-iconfont-github:before { content: \"\\e6d1\"; }\n.Hui-iconfont-html5:before { content: \"\\e6d2\"; }\n.Hui-iconfont-huangguan:before { content: \"\\e6d3\"; }\n.Hui-iconfont-news:before { content: \"\\e616\"; }\n.Hui-iconfont-slider-right:before { content: \"\\e63d\"; }\n.Hui-iconfont-slider-left:before { content: \"\\e67d\"; }\n.Hui-iconfont-tuku:before { content: \"\\e613\"; }\n.Hui-iconfont-shuru:before { content: \"\\e647\"; }\n.Hui-iconfont-sanjiao:before { content: \"\\e67e\"; }\n.Hui-iconfont-share-renren:before { content: \"\\e6d8\"; }\n.Hui-iconfont-share-tweibo:before { content: \"\\e6d9\"; }\n.Hui-iconfont-arrow2-left:before { content: \"\\e6d4\"; }\n.Hui-iconfont-paixu:before { content: \"\\e675\"; }\n.Hui-iconfont-niming:before { content: \"\\e624\"; }\n.Hui-iconfont-add:before { content: \"\\e600\"; }\n.Hui-iconfont-root:before { content: \"\\e62d\"; }\n.Hui-iconfont-xuanzhong:before { content: \"\\e676\"; }\n.Hui-iconfont-weixuanzhong:before { content: \"\\e677\"; }\n.Hui-iconfont-arrow2-bottom:before { content: \"\\e6d5\"; }\n.Hui-iconfont-arrow2-top:before { content: \"\\e6d6\"; }\n.Hui-iconfont-like2:before { content: \"\\e648\"; }\n.Hui-iconfont-arrow2-right:before { content: \"\\e6d7\"; }\n.Hui-iconfont-shangyishou:before { content: \"\\e6db\"; }\n.Hui-iconfont-xiayishou:before { content: \"\\e6e3\"; }\n.Hui-iconfont-share-weixin:before { content: \"\\e694\"; }\n.Hui-iconfont-shenhe-tingyong:before { content: \"\\e631\"; }\n.Hui-iconfont-gouxuan2:before { content: \"\\e601\"; }\n.Hui-iconfont-selected:before { content: \"\\e617\"; }\n.Hui-iconfont-jianhao:before { content: \"\\e6a1\"; }\n.Hui-iconfont-user-group:before { content: \"\\e62b\"; }\n.Hui-iconfont-yiguanzhu:before { content: \"\\e680\"; }\n.Hui-iconfont-gengduo3:before { content: \"\\e6f9\"; }\n.Hui-iconfont-comment:before { content: \"\\e622\"; }\n.Hui-iconfont-tongji-zhu:before { content: \"\\e618\"; }\n.Hui-iconfont-like:before { content: \"\\e649\"; }\n.Hui-iconfont-shangjia:before { content: \"\\e6dc\"; }\n.Hui-iconfont-save:before { content: \"\\e632\"; }\n.Hui-iconfont-gongsi:before { content: \"\\e643\"; }\n.Hui-iconfont-system:before { content: \"\\e62e\"; }\n.Hui-iconfont-pifu:before { content: \"\\e62a\"; }\n.Hui-iconfont-menu:before { content: \"\\e667\"; }\n.Hui-iconfont-msg:before { content: \"\\e62f\"; }\n.Hui-iconfont-huangguan1:before { content: \"\\e729\"; }\n.Hui-iconfont-userid:before { content: \"\\e602\"; }\n.Hui-iconfont-cang-selected:before { content: \"\\e630\"; }\n.Hui-iconfont-yundown:before { content: \"\\e641\"; }\n.Hui-iconfont-help:before { content: \"\\e633\"; }\n.Hui-iconfont-chuku:before { content: \"\\e634\"; }\n.Hui-iconfont-picture:before { content: \"\\e646\"; }\n.Hui-iconfont-wenzhouyinxing:before { content: \"\\e6ed\"; }\n.Hui-iconfont-ad:before { content: \"\\e635\"; }\n.Hui-iconfont-fenlei:before { content: \"\\e681\"; }\n.Hui-iconfont-saoyisao:before { content: \"\\e682\"; }\n.Hui-iconfont-search:before { content: \"\\e683\"; }\n.Hui-iconfont-tuwenxiangqing:before { content: \"\\e685\"; }\n.Hui-iconfont-leijipingjia:before { content: \"\\e686\"; }\n.Hui-iconfont-hetong:before { content: \"\\e636\"; }\n.Hui-iconfont-tongji:before { content: \"\\e61a\"; }\n.Hui-iconfont-quanbudingdan:before { content: \"\\e687\"; }\n.Hui-iconfont-cang:before { content: \"\\e61b\"; }\n.Hui-iconfont-xiaoxi:before { content: \"\\e68a\"; }\n.Hui-iconfont-renwu:before { content: \"\\e637\"; }\n.Hui-iconfont-more:before { content: \"\\e68b\"; }\n.Hui-iconfont-zhizhao:before { content: \"\\e638\"; }\n.Hui-iconfont-fabu:before { content: \"\\e603\"; }\n.Hui-iconfont-shenhe-butongguo2:before { content: \"\\e6dd\"; }\n.Hui-iconfont-share-qq:before { content: \"\\e67b\"; }\n.Hui-iconfont-upload:before { content: \"\\e642\"; }\n.Hui-iconfont-add2:before { content: \"\\e604\"; }\n.Hui-iconfont-jiesuo:before { content: \"\\e605\"; }\n.Hui-iconfont-zhongtumoshi:before { content: \"\\e68c\"; }\n.Hui-iconfont-datumoshi:before { content: \"\\e68d\"; }\n.Hui-iconfont-face2:before { content: \"\\e68e\"; }\n.Hui-iconfont-huanyipi:before { content: \"\\e68f\"; }\n.Hui-iconfont-shijian:before { content: \"\\e690\"; }\n.Hui-iconfont-feedback:before { content: \"\\e691\"; }\n.Hui-iconfont-feedback2:before { content: \"\\e692\"; }\n.Hui-iconfont-share-pengyouquan:before { content: \"\\e693\"; }\n.Hui-iconfont-zan2:before { content: \"\\e697\"; }\n.Hui-iconfont-arrow3-bottom:before { content: \"\\e698\"; }\n.Hui-iconfont-arrow3-top:before { content: \"\\e699\"; }\n.Hui-iconfont-arrow3-right:before { content: \"\\e69a\"; }\n.Hui-iconfont-arrow3-left:before { content: \"\\e69b\"; }\n.Hui-iconfont-more2:before { content: \"\\e69c\"; }\n.Hui-iconfont-cang2-selected:before { content: \"\\e69d\"; }\n.Hui-iconfont-cang2:before { content: \"\\e69e\"; }\n.Hui-iconfont-dangan:before { content: \"\\e639\"; }\n.Hui-iconfont-money:before { content: \"\\e63a\"; }\n.Hui-iconfont-share-weibo:before { content: \"\\e6da\"; }\n.Hui-iconfont-email:before { content: \"\\e63b\"; }\n.Hui-iconfont-tongji-xian:before { content: \"\\e61c\"; }\n.Hui-iconfont-bank:before { content: \"\\e628\"; }\n.Hui-iconfont-home:before { content: \"\\e625\"; }\n.Hui-iconfont-user:before { content: \"\\e62c\"; }\n.Hui-iconfont-log:before { content: \"\\e623\"; }\n.Hui-iconfont-pages:before { content: \"\\e626\"; }\n.Hui-iconfont-sim:before { content: \"\\e629\"; }\n.Hui-iconfont-tingzhi:before { content: \"\\e6e4\"; }\n.Hui-iconfont-dengdai:before { content: \"\\e606\"; }\n.Hui-iconfont-user-add:before { content: \"\\e607\"; }\n.Hui-iconfont-copy:before { content: \"\\e6ea\"; }\n.Hui-iconfont-file:before { content: \"\\e63e\"; }\n.Hui-iconfont-share-douban:before { content: \"\\e67c\"; }\n.Hui-iconfont-share-zhihu:before { content: \"\\e689\"; }\n.Hui-iconfont-daochu:before { content: \"\\e644\"; }\n.Hui-iconfont-daoru:before { content: \"\\e645\"; }\n.Hui-iconfont-weigouxuan2:before { content: \"\\e608\"; }\n.Hui-iconfont-phone:before { content: \"\\e696\"; }\n.Hui-iconfont-bold:before { content: \"\\e6e7\"; }\n.Hui-iconfont-manage2:before { content: \"\\e63c\"; }\n.Hui-iconfont-edit:before { content: \"\\e6df\"; }\n.Hui-iconfont-del2:before { content: \"\\e609\"; }\n.Hui-iconfont-duigou:before { content: \"\\e6e8\"; }\n.Hui-iconfont-chongqi:before { content: \"\\e6f7\"; }\n.Hui-iconfont-avatar:before { content: \"\\e60a\"; }\n.Hui-iconfont-del:before { content: \"\\e60b\"; }\n.Hui-iconfont-edit2:before { content: \"\\e60c\"; }\n.Hui-iconfont-zanting:before { content: \"\\e6e5\"; }\n.Hui-iconfont-apple:before { content: \"\\e64a\"; }\n.Hui-iconfont-guangdayinxing:before { content: \"\\e6f0\"; }\n.Hui-iconfont-minshengyinxing:before { content: \"\\e6f4\"; }\n.Hui-iconfont-xiajia:before { content: \"\\e6de\"; }\n.Hui-iconfont-manage:before { content: \"\\e61d\"; }\n.Hui-iconfont-user2:before { content: \"\\e60d\"; }\n.Hui-iconfont-code:before { content: \"\\e6ee\"; }\n.Hui-iconfont-cut:before { content: \"\\e6ef\"; }\n.Hui-iconfont-link:before { content: \"\\e6f1\"; }\n.Hui-iconfont-new:before { content: \"\\e6f2\"; }\n.Hui-iconfont-ordered-list:before { content: \"\\e6f3\"; }\n.Hui-iconfont-unordered-list:before { content: \"\\e6f5\"; }\n.Hui-iconfont-share-qzone:before { content: \"\\e6c8\"; }\n.Hui-iconfont-suoding:before { content: \"\\e60e\"; }\n.Hui-iconfont-tel2:before { content: \"\\e6a3\"; }\n.Hui-iconfont-order:before { content: \"\\e627\"; }\n.Hui-iconfont-shujutongji:before { content: \"\\e61e\"; }\n.Hui-iconfont-del3:before { content: \"\\e6e2\"; }\n.Hui-iconfont-add3:before { content: \"\\e610\"; }\n.Hui-iconfont-add4:before { content: \"\\e61f\"; }\n.Hui-iconfont-xiangpicha:before { content: \"\\e72a\"; }\n.Hui-iconfont-key:before { content: \"\\e63f\"; }\n.Hui-iconfont-yuyin2:before { content: \"\\e6a4\"; }\n.Hui-iconfont-yuyin:before { content: \"\\e6a5\"; }\n.Hui-iconfont-close:before { content: \"\\e6a6\"; }\n.Hui-iconfont-xuanze:before { content: \"\\e6a7\"; }\n.Hui-iconfont-xuanzhong1:before { content: \"\\e6a8\"; }\n.Hui-iconfont-yiguanzhu1:before { content: \"\\e6a9\"; }\n.Hui-iconfont-share:before { content: \"\\e6aa\"; }\n.Hui-iconfont-zhuanfa:before { content: \"\\e6ab\"; }\n.Hui-iconfont-tianqi-duoyun:before { content: \"\\e6ac\"; }\n.Hui-iconfont-tianqi-mai:before { content: \"\\e6ad\"; }\n.Hui-iconfont-tianqi-qing:before { content: \"\\e6ae\"; }\n.Hui-iconfont-tianqi-wu:before { content: \"\\e6af\"; }\n.Hui-iconfont-tianqi-xue:before { content: \"\\e6b0\"; }\n.Hui-iconfont-tianqi-yin:before { content: \"\\e6b1\"; }\n.Hui-iconfont-tianqi-yu:before { content: \"\\e6b2\"; }\n.Hui-iconfont-daipingjia:before { content: \"\\e6b3\"; }\n.Hui-iconfont-vip-card2:before { content: \"\\e6b4\"; }\n.Hui-iconfont-jifen:before { content: \"\\e6b5\"; }\n.Hui-iconfont-youhuiquan:before { content: \"\\e6b6\"; }\n.Hui-iconfont-hongbao:before { content: \"\\e6b7\"; }\n.Hui-iconfont-cart-selected:before { content: \"\\e6b8\"; }\n.Hui-iconfont-cart-kong:before { content: \"\\e6b9\"; }\n.Hui-iconfont-jiangjia:before { content: \"\\e6ba\"; }\n.Hui-iconfont-liwu:before { content: \"\\e6bb\"; }\n.Hui-iconfont-caiqie:before { content: \"\\e6bc\"; }\n.Hui-iconfont-xuanzhuan:before { content: \"\\e6bd\"; }\n.Hui-iconfont-bigpic:before { content: \"\\e6be\"; }\n.Hui-iconfont-list:before { content: \"\\e6bf\"; }\n.Hui-iconfont-middle:before { content: \"\\e6c0\"; }\n.Hui-iconfont-hot:before { content: \"\\e6c1\"; }\n.Hui-iconfont-paishe:before { content: \"\\e6c2\"; }\n.Hui-iconfont-hot1:before { content: \"\\e6c3\"; }\n.Hui-iconfont-new1:before { content: \"\\e6c4\"; }\n.Hui-iconfont-xiaoxi1:before { content: \"\\e6c5\"; }\n.Hui-iconfont-canshu:before { content: \"\\e6c6\"; }\n.Hui-iconfont-tel:before { content: \"\\e6c7\"; }\n.Hui-iconfont-dingwei:before { content: \"\\e6c9\"; }\n.Hui-iconfont-hongbao2:before { content: \"\\e6ca\"; }\n.Hui-iconfont-2code:before { content: \"\\e6cb\"; }\n.Hui-iconfont-vip:before { content: \"\\e6cc\"; }\n.Hui-iconfont-tishi:before { content: \"\\e6cd\"; }\n.Hui-iconfont-dingyue:before { content: \"\\e6ce\"; }\n.Hui-iconfont-italic:before { content: \"\\e6e9\"; }\n.Hui-iconfont-yulan:before { content: \"\\e695\"; }\n.Hui-iconfont-usergroup2:before { content: \"\\e611\"; }\n.Hui-iconfont-goods:before { content: \"\\e620\"; }\n.Hui-iconfont-paixingbang:before { content: \"\\e6cf\"; }\n.Hui-iconfont-qingdaoyinxing:before { content: \"\\e6f6\"; }\n.Hui-iconfont-kefu:before { content: \"\\e6d0\"; }\n.Hui-iconfont-picture1:before { content: \"\\e612\"; }\n.Hui-iconfont-weigouxuan:before { content: \"\\e614\"; }\n.Hui-iconfont-fanqiang:before { content: \"\\e6fa\"; }\n.Hui-iconfont-shenhe-weitongguo:before { content: \"\\e6e0\"; }\n.Hui-iconfont-shenhe-tongguo:before { content: \"\\e6e1\"; }\n.Hui-iconfont-tongji-bing:before { content: \"\\e621\"; }\n.Hui-iconfont-gouxuan:before { content: \"\\e615\"; }\n.Hui-iconfont-jiansheyinxing:before { content: \"\\e6f8\"; }\n.Hui-iconfont-moban:before { content: \"\\e72b\"; }\n.Hui-iconfont-pay-weixin:before { content: \"\\e719\"; }\n.Hui-iconfont-pay-alipay-2:before { content: \"\\e71c\"; }\n.Hui-iconfont-beijingyinxing:before { content: \"\\e6fb\"; }\n.Hui-iconfont-guangdongfazhanyinxing:before { content: \"\\e703\"; }\n.Hui-iconfont-zhaoshangyinxing:before { content: \"\\e704\"; }\n.Hui-iconfont-zheshangyinxing:before { content: \"\\e712\"; }\n.Hui-iconfont-zhongguonongyeyinxing:before { content: \"\\e713\"; }\n.Hui-iconfont-cdbank:before { content: \"\\e714\"; }\n.Hui-iconfont-gengduo2:before { content: \"\\e716\"; }\n.Hui-iconfont-bofang:before { content: \"\\e6e6\"; }\n.Hui-iconfont-gengduo4:before { content: \"\\e717\"; }\n.Hui-iconfont-text-height:before { content: \"\\e6fc\"; }\n.Hui-iconfont-text-width:before { content: \"\\e6fd\"; }\n.Hui-iconfont-underline:before { content: \"\\e6fe\"; }\n.Hui-iconfont-star:before { content: \"\\e6ff\"; }\n.Hui-iconfont-star-half:before { content: \"\\e700\"; }\n.Hui-iconfont-star-halfempty:before { content: \"\\e701\"; }\n.Hui-iconfont-star-o:before { content: \"\\e702\"; }\n.Hui-iconfont-font:before { content: \"\\e6ec\"; }\n.Hui-iconfont-hangzhouyinxing:before { content: \"\\e718\"; }\n.Hui-iconfont-jiaotongyinxing:before { content: \"\\e71a\"; }\n.Hui-iconfont-gengduo:before { content: \"\\e715\"; }\n.Hui-iconfont-avatar2:before { content: \"\\e705\"; }\n.Hui-iconfont-close2:before { content: \"\\e706\"; }\n.Hui-iconfont-about:before { content: \"\\e707\"; }\n.Hui-iconfont-phone-android:before { content: \"\\e708\"; }\n.Hui-iconfont-search1:before { content: \"\\e709\"; }\n.Hui-iconfont-comment1:before { content: \"\\e70a\"; }\n.Hui-iconfont-read:before { content: \"\\e70b\"; }\n.Hui-iconfont-feedback1:before { content: \"\\e70c\"; }\n.Hui-iconfont-practice:before { content: \"\\e70d\"; }\n.Hui-iconfont-align-center:before { content: \"\\e70e\"; }\n.Hui-iconfont-align-justify:before { content: \"\\e70f\"; }\n.Hui-iconfont-align-left:before { content: \"\\e710\"; }\n.Hui-iconfont-align-right:before { content: \"\\e711\"; }\n.Hui-iconfont-paste:before { content: \"\\e6eb\"; }\n.Hui-iconfont-pay-alipay-1:before { content: \"\\e71f\"; }\n.Hui-iconfont-pufayinxing:before { content: \"\\e71b\"; }\n.Hui-iconfont-gongshangyinxing:before { content: \"\\e71d\"; }\n.Hui-iconfont-huaxiayinxing:before { content: \"\\e71e\"; }\n.Hui-iconfont-youzhengyinxing:before { content: \"\\e721\"; }\n.Hui-iconfont-zhongguoyinxing:before { content: \"\\e722\"; }\n.Hui-iconfont-zhongxinyinxing:before { content: \"\\e723\"; }\n.Hui-iconfont-shanghaiyinxing:before { content: \"\\e724\"; }\n.Hui-iconfont-banzhu:before { content: \"\\e72c\"; }\n.Hui-iconfont-yuedu:before { content: \"\\e720\"; }\n.Hui-iconfont-yanjing:before { content: \"\\e725\"; }\n.Hui-iconfont-power:before { content: \"\\e726\"; }\n.Hui-iconfont-moban-2:before { content: \"\\e72d\"; }\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/My97DatePicker/4.8/WdatePicker.js",
    "content": "/*\n * My97 DatePicker 4.8 Beta4\n * License: http://www.my97.net/dp/license.asp\n */\nvar $dp,WdatePicker;(function(){var $={\n$langList:[\n {name:\"en\",charset:\"UTF-8\"},\n {name:\"zh-cn\",charset:\"gb2312\"},\n {name:\"zh-tw\",charset:\"GBK\"}],\n$skinList:[\n {name:\"default\",charset:\"gb2312\"},\n {name:\"whyGreen\",charset:\"gb2312\"},\n {name:\"blue\",charset:\"gb2312\"},\n {name:\"green\",charset:\"gb2312\"},\n {name:\"simple\",charset:\"gb2312\"},\n {name:\"ext\",charset:\"gb2312\"},\n {name:\"blueFresh\",charset:\"gb2312\"},\n {name:\"twoer\",charset:\"gb2312\"},\n {name:\"YcloudRed\",charset:\"gb2312\"}],\n$wdate:true,\n$crossFrame:true,\n$preLoad:false,\n$dpPath:\"\",\ndoubleCalendar:false,\nenableKeyboard:true,\nenableInputMask:true,\nautoUpdateOnChanged:null,\nweekMethod:\"ISO8601\",\nposition:{},\nlang:\"auto\",\nskin:\"default\",\ndateFmt:\"yyyy-MM-dd\",\nrealDateFmt:\"yyyy-MM-dd\",\nrealTimeFmt:\"HH:mm:ss\",\nrealFullFmt:\"%Date %Time\",\nminDate:\"1900-01-01 00:00:00\",\nmaxDate:\"2099-12-31 23:59:59\",\nstartDate:\"\",\nalwaysUseStartDate:false,\nyearOffset:1911,\nfirstDayOfWeek:0,\nisShowWeek:false,\nhighLineWeekDay:true,\nisShowClear:true,\nisShowToday:true,\nisShowOK:true,\nisShowOthers:true,\nreadOnly:false,\nerrDealMode:0,\nautoPickDate:null,\nqsEnabled:true,\nautoShowQS:false,\nopposite:false,\nhmsMenuCfg:{H:[1,6],m:[5,6],s:[15,4]},\nopposite:false,\n\nspecialDates:null,specialDays:null,disabledDates:null,disabledDays:null,onpicking:null,onpicked:null,onclearing:null,oncleared:null,ychanging:null,ychanged:null,Mchanging:null,Mchanged:null,dchanging:null,dchanged:null,Hchanging:null,Hchanged:null,mchanging:null,mchanged:null,schanging:null,schanged:null,eCont:null,vel:null,elProp:\"\",errMsg:\"\",quickSel:[],has:{},getRealLang:function(){var _=$.$langList;for(var A=0;A<_.length;A++)if(_[A].name==this.lang)return _[A];return _[0]}};WdatePicker=U;var Y=window,T={innerHTML:\"\"},N=\"document\",H=\"documentElement\",C=\"getElementsByTagName\",V,A,S,G,c,X=navigator.appName;if(X==\"Microsoft Internet Explorer\")S=true;else if(X==\"Opera\")c=true;else G=true;A=$.$dpPath||J();if($.$wdate)K(A+\"skin/WdatePicker.css\");V=Y;if($.$crossFrame){try{while(V.parent!=V&&V.parent[N][C](\"frameset\").length==0)V=V.parent}catch(O){}}if(!V.$dp)V.$dp={ff:G,ie:S,opera:c,status:0,defMinDate:$.minDate,defMaxDate:$.maxDate};B();if($.$preLoad&&$dp.status==0)E(Y,\"onload\",function(){U(null,true)});if(!Y[N].docMD){E(Y[N],\"onmousedown\",D,true);Y[N].docMD=true}if(!V[N].docMD){E(V[N],\"onmousedown\",D,true);V[N].docMD=true}E(Y,\"onunload\",function(){if($dp.dd)P($dp.dd,\"none\")});function B(){try{V[N],V.$dp=V.$dp||{}}catch($){V=Y;$dp=$dp||{}}var A={win:Y,$:function($){return(typeof $==\"string\")?Y[N].getElementById($):$},$D:function($,_){return this.$DV(this.$($).value,_)},$DV:function(_,$){if(_!=\"\"){this.dt=$dp.cal.splitDate(_,$dp.cal.dateFmt);if($)for(var B in $)if(this.dt[B]===undefined)this.errMsg=\"invalid property:\"+B;else{this.dt[B]+=$[B];if(B==\"M\"){var C=$[\"M\"]>0?1:0,A=new Date(this.dt[\"y\"],this.dt[\"M\"],0).getDate();this.dt[\"d\"]=Math.min(A+C,this.dt[\"d\"])}}if(this.dt.refresh())return this.dt}return\"\"},show:function(){var A=V[N].getElementsByTagName(\"div\"),$=100000;for(var B=0;B<A.length;B++){var _=parseInt(A[B].style.zIndex);if(_>$)$=_}this.dd.style.zIndex=$+2;P(this.dd,\"block\");P(this.dd.firstChild,\"\")},unbind:function($){$=this.$($);if($.initcfg){L($,\"onclick\",function(){U($.initcfg)});L($,\"onfocus\",function(){U($.initcfg)})}},hide:function(){P(this.dd,\"none\")},attachEvent:E};for(var _ in A)V.$dp[_]=A[_];$dp=V.$dp}function E(B,_,A,$){if(B.addEventListener){var C=_.replace(/on/,\"\");A._ieEmuEventHandler=function($){return A($)};B.addEventListener(C,A._ieEmuEventHandler,$)}else B.attachEvent(_,A)}function L(A,$,_){if(A.removeEventListener){var B=$.replace(/on/,\"\");_._ieEmuEventHandler=function($){return _($)};A.removeEventListener(B,_._ieEmuEventHandler,false)}else A.detachEvent($,_)}function a(_,$,A){if(typeof _!=typeof $)return false;if(typeof _==\"object\"){if(!A)for(var B in _){if(typeof $[B]==\"undefined\")return false;if(!a(_[B],$[B],true))return false}return true}else if(typeof _==\"function\"&&typeof $==\"function\")return _.toString()==$.toString();else return _==$}function J(){var _,A,$=Y[N][C](\"script\");for(var B=0;B<$.length;B++){_=$[B].getAttribute(\"src\")||\"\";_=_.substr(0,_.toLowerCase().indexOf(\"wdatepicker.js\"));A=_.lastIndexOf(\"/\");if(A>0)_=_.substring(0,A+1);if(_)break}return _}function K(A,$,B){var D=Y[N][C](\"HEAD\").item(0),_=Y[N].createElement(\"link\");if(D){_.href=A;_.rel=\"stylesheet\";_.type=\"text/css\";if($)_.title=$;if(B)_.charset=B;D.appendChild(_)}}function F($){$=$||V;var A=0,_=0;while($!=V){var D=$.parent[N][C](\"iframe\");for(var F=0;F<D.length;F++){try{if(D[F].contentWindow==$){var E=W(D[F]);A+=E.left;_+=E.top;break}}catch(B){}}$=$.parent}return{\"leftM\":A,\"topM\":_}}function W(G,F){if(G.getBoundingClientRect)return G.getBoundingClientRect();else{var A={ROOT_TAG:/^body|html$/i,OP_SCROLL:/^(?:inline|table-row)$/i},E=false,I=null,_=G.offsetTop,H=G.offsetLeft,D=G.offsetWidth,B=G.offsetHeight,C=G.offsetParent;if(C!=G)while(C){H+=C.offsetLeft;_+=C.offsetTop;if(R(C,\"position\").toLowerCase()==\"fixed\")E=true;else if(C.tagName.toLowerCase()==\"body\")I=C.ownerDocument.defaultView;C=C.offsetParent}C=G.parentNode;while(C.tagName&&!A.ROOT_TAG.test(C.tagName)){if(C.scrollTop||C.scrollLeft)if(!A.OP_SCROLL.test(P(C)))if(!c||C.style.overflow!==\"visible\"){H-=C.scrollLeft;_-=C.scrollTop}C=C.parentNode}if(!E){var $=b(I);H-=$.left;_-=$.top}D+=H;B+=_;return{\"left\":H,\"top\":_,\"right\":D,\"bottom\":B}}}function M($){$=$||V;var B=$[N],A=($.innerWidth)?$.innerWidth:(B[H]&&B[H].clientWidth)?B[H].clientWidth:B.body.offsetWidth,_=($.innerHeight)?$.innerHeight:(B[H]&&B[H].clientHeight)?B[H].clientHeight:B.body.offsetHeight;return{\"width\":A,\"height\":_}}function b($){$=$||V;var B=$[N],A=B[H],_=B.body;B=(A&&A.scrollTop!=null&&(A.scrollTop>_.scrollTop||A.scrollLeft>_.scrollLeft))?A:_;return{\"top\":B.scrollTop,\"left\":B.scrollLeft}}function D($){try{var _=$?($.srcElement||$.target):null;if($dp.cal&&!$dp.eCont&&$dp.dd&&_!=$dp.el&&$dp.dd.style.display==\"block\")$dp.cal.close()}catch($){}}function Z(){$dp.status=2}var Q,_;function U(K,C){if(!$dp)return;B();var L={};for(var H in K)L[H]=K[H];for(H in $)if(H.substring(0,1)!=\"$\"&&L[H]===undefined)L[H]=$[H];if(C){if(!J()){_=_||setInterval(function(){if(V[N].readyState==\"complete\")clearInterval(_);U(null,true)},50);return}if($dp.status==0){$dp.status=1;L.el=T;I(L,true)}else return}else if(L.eCont){L.eCont=$dp.$(L.eCont);L.el=T;L.autoPickDate=true;L.qsEnabled=false;I(L)}else{if($.$preLoad&&$dp.status!=2)return;var F=D();if(Y.event===F||F){L.srcEl=F.srcElement||F.target;F.cancelBubble=true}L.el=L.el=$dp.$(L.el||L.srcEl);if(!L.el||L.el[\"My97Mark\"]===true||L.el.disabled||($dp.dd&&P($dp.dd)!=\"none\"&&$dp.dd.style.left!=\"-970px\")){try{if(L.el[\"My97Mark\"])L.el[\"My97Mark\"]=false}catch(A){}return}if(F&&L.el.nodeType==1&&!a(L.el.initcfg,K)){$dp.unbind(L.el);E(L.el,F.type==\"focus\"?\"onclick\":\"onfocus\",function(){U(K)});L.el.initcfg=K}I(L)}function J(){if(S&&V!=Y&&V[N].readyState!=\"complete\")return false;return true}function D(){if(G){func=D.caller;while(func!=null){var $=func.arguments[0];if($&&($+\"\").indexOf(\"Event\")>=0)return $;func=func.caller}return null}return event}}function R(_,$){return _.currentStyle?_.currentStyle[$]:document.defaultView.getComputedStyle(_,false)[$]}function P(_,$){if(_)if($!=null)_.style.display=$;else return R(_,\"display\")}function I(G,_){var D=G.el?G.el.nodeName:\"INPUT\";if(_||G.eCont||new RegExp(/input|textarea|div|span|p|a/ig).test(D))G.elProp=D==\"INPUT\"?\"value\":\"innerHTML\";else return;if(G.lang==\"auto\")G.lang=S?navigator.browserLanguage.toLowerCase():navigator.language.toLowerCase();if(!G.eCont)for(var C in G)$dp[C]=G[C];if(!$dp.dd||G.eCont||($dp.dd&&(G.getRealLang().name!=$dp.dd.lang||G.skin!=$dp.dd.skin))){if(G.eCont)E(G.eCont,G);else{$dp.dd=V[N].createElement(\"DIV\");$dp.dd.style.cssText=\"position:absolute\";V[N].body.appendChild($dp.dd);E($dp.dd,G);if(_)$dp.dd.style.left=$dp.dd.style.top=\"-970px\";else{$dp.show();B($dp)}}}else if($dp.cal){$dp.show();$dp.cal.init();if(!$dp.eCont)B($dp)}function E(K,J){var I=V[N].domain,F=false,G=\"<iframe hideFocus=true width=9 height=7 frameborder=0 border=0 scrolling=no src=\\\"about:blank\\\"></iframe>\";K.innerHTML=G;var _=$.$langList,D=$.$skinList,H;try{H=K.lastChild.contentWindow[N]}catch(E){F=true;K.removeChild(K.lastChild);var L=V[N].createElement(\"iframe\");L.hideFocus=true;L.frameBorder=0;L.scrolling=\"no\";L.src=\"javascript:(function(){var d=document;d.open();d.domain='\"+I+\"';})()\";K.appendChild(L);setTimeout(function(){H=K.lastChild.contentWindow[N];C()},97);return}C();function C(){var _=J.getRealLang();K.lang=_.name;K.skin=J.skin;var $=[\"<head><script>\",\"\",\"var doc=document, $d, $dp, $cfg=doc.cfg, $pdp = parent.$dp, $dt, $tdt, $sdt, $lastInput, $IE=$pdp.ie, $FF = $pdp.ff,$OPERA=$pdp.opera, $ny, $cMark = false;\",\"if($cfg.eCont){$dp = {};for(var p in $pdp)$dp[p]=$pdp[p];}else{$dp=$pdp;};for(var p in $cfg){$dp[p]=$cfg[p];}\",\"doc.oncontextmenu=function(){try{$c._fillQS(!$dp.has.d,1);showB($d.qsDivSel);}catch(e){};return false;};\",\"</script><script src=\",A,\"lang/\",_.name,\".js charset=\",_.charset,\"></script>\"];if(F)$[1]=\"document.domain=\\\"\"+I+\"\\\";\";for(var C=0;C<D.length;C++)if(D[C].name==J.skin)$.push(\"<link rel=\\\"stylesheet\\\" type=\\\"text/css\\\" href=\\\"\"+A+\"skin/\"+D[C].name+\"/datepicker.css\\\" charset=\\\"\"+D[C].charset+\"\\\"/>\");$.push(\"<script src=\\\"\"+A+\"calendar.js\\\"></script>\");$.push(\"</head><body leftmargin=\\\"0\\\" topmargin=\\\"0\\\" tabindex=0></body></html>\");$.push(\"<script>var t;t=t||setInterval(function(){if(doc.ready){new My97DP();$cfg.onload();$c.autoSize();$cfg.setPos($dp);clearInterval(t);}},20);</script>\");J.setPos=B;J.onload=Z;H.write(\"<html>\");H.cfg=J;H.write($.join(\"\"));H.close()}}function B(J){var H=J.position.left,C=J.position.top,D=J.el;if(D==T)return;if(D!=J.srcEl&&(P(D)==\"none\"||D.type==\"hidden\"))D=J.srcEl;var I=W(D),$=F(Y),E=M(V),B=b(V),G=$dp.dd.offsetHeight,A=$dp.dd.offsetWidth;if(isNaN(C))C=0;if(($.topM+I.bottom+G>E.height)&&($.topM+I.top-G>0))C+=B.top+$.topM+I.top-G-2;else{C+=B.top+$.topM+I.bottom;var _=C-B.top+G-E.height;if(_>0)C-=_}if(isNaN(H))H=0;H+=B.left+Math.min($.leftM+I.left,E.width-A-5)-(S?2:0);J.dd.style.top=C+\"px\";J.dd.style.left=H+\"px\"}}})()"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/My97DatePicker/4.8/calendar.js",
    "content": "/*\n * My97 DatePicker 4.8 Beta4\n * License: http://www.my97.net/dp/license.asp\n */\neval(function(p,a,c,k,e,d){e=function(c){return(c<a?\"\":e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\\\\b'+e(c)+'\\\\b','g'),k[c]);return p;}('l($4o.44){$f={};1b(q p 4r $2s)l(6p $2s[p]==\"6o\"){$f[p]={};1b(q 4G 4r $2s[p])$f[p][4G]=$2s[p][4G]}t $f[p]=$2s[p]}t $f=$2s;1b(p 4r $4o)$f[p]=$4o[p];q $c;l($69){6x.3J.7l(\"6U\",n($){l(!$)h.2m();u $});6x.3J.7k(\"5I\",n(){q $=h.5B;36($.5t!=1)$=$.7b;u $})}n 5C(){$c=h;h.3n=[];$d=1L.7i(\"z\");$d.1e=\"4P\";$d.1M=\"<z 1G=7s><z Y=\\\\\"3W 7p\\\\\"><a></a></z><z Y=\\\\\"3W 7r\\\\\"><a></a></z><z 1d=\\\\\"3q:2E\\\\\"><z Y=\\\\\"2T 7q\\\\\"></z><1z Y=47></z><z 1d=\\\\\"3q:2E\\\\\"><z Y=\\\\\"2T 76\\\\\"></z><1z Y=47></z><z Y=\\\\\"3W 78\\\\\"><a></a></z><z Y=\\\\\"3W 7x\\\\\"><a></a></z><z 1d=\\\\\"3q:62\\\\\"></z></z><z 1d=\\\\\"80:7W;7S:6q\\\\\"></z><z></z><z 1G=7V><z Y=\\\\\"2T 7U\\\\\"></z><z Y=\\\\\"2T 81\\\\\"></z><z Y=\\\\\"2T 87\\\\\"></z><1x 2q=0 2o=0 2C=0><1j><19 8a=2><4w 1G=89></4w>&42;<1z Y=83 4s=2><1z 1i=\\\\\":\\\\\" Y=6K 6t><1z Y=6u 4s=2><1z 1i=\\\\\":\\\\\" Y=6K 6t><1z Y=6u 4s=2></19><19><1S 1G=7R></1S></19></1j><1j><19><1S 1G=7E></1S></19></1j></1x></z><z 1G=7F></z><z 1G=7C><1z Y=4v 1G=7y 3k=1S><1z Y=4v 1G=7N 3k=1S><1z Y=4v 1G=7K 3k=1S></z>\";71($d,n(){3x()});A();h.5D();$f.1X=[1L,$d.1P,$d.1y,$d.2w,$d.3a,$d.2r,$d.2V,$d.2j,$d.1U];1b(q B=0;B<$f.1X.x;B++){q b=$f.1X[B];b.3e=B==$f.1X.x-1?$f.1X[1]:$f.1X[B+1];$f.3A(b,\"4k\",5a)}$();55(\"y,M,H,m,s\");$d.72.1s=n(){5g(1)};$d.75.1s=n(){5g(-1)};$d.4y.1s=n(){l($d.1H.1d.2a!=\"6G\"){$c.4Q();3G($d.1H)}t 1o($d.1H)};1L.6R.4O($d);n A(){q b=$(\"a\");1q=$(\"z\"),1J=$(\"1z\"),4t=$(\"1S\"),5G=$(\"4w\");$d.3M=b[0];$d.3K=b[1];$d.3L=b[3];$d.3N=b[2];$d.4b=1q[9];$d.1P=1J[0];$d.1y=1J[1];$d.4A=1q[0];$d.4f=1q[4];$d.2R=1q[6];$d.1H=1q[10];$d.2Z=1q[11];$d.34=1q[12];$d.5N=1q[13];$d.6P=1q[14];$d.73=1q[15];$d.4y=1q[16];$d.4e=1q[17];$d.2w=1J[2];$d.3a=1J[4];$d.2r=1J[6];$d.2V=1J[7];$d.2j=1J[8];$d.1U=1J[9];$d.72=4t[0];$d.75=4t[1];$d.5L=5G[0];n $($){u $d.74($)}}n $(){$d.3M.1s=n(){$1O=$1O<=0?$1O-1:-1;l($1O%5==0){$d.1y.22();u}$d.1y.1i=$o.y-1;$d.1y.2x()};$d.3K.1s=n(){$o.1V(\"M\",-1);$d.1P.2x()};$d.3L.1s=n(){$o.1V(\"M\",1);$d.1P.2x()};$d.3N.1s=n(){$1O=$1O>=0?$1O+1:1;l($1O%5==0){$d.1y.22();u}$d.1y.1i=$o.y+1;$d.1y.2x()}}}5C.3J={5D:n(){$1O=0;$f.5b=h;l($f.3S&&$f.Z.3S!=1h){$f.Z.3S=1c;$f.Z.4M()}h.4q();$o=h.4D=1a 1D();$1C=1a 1D();$1v=h.2B=1a 1D();$f.2N=0;h.1B=h.2P($f.1B);h.2X=$f.2X==1h?($f.18.2g&&$f.18.2g?1p:1c):$f.2X;$f.3y=$f.3y==1h?($f.4z&&$f.18.d?1p:1c):$f.3y;h.4m=h.35(\"7L\");h.6m=h.35(\"7I\");h.6d=h.35(\"7J\");h.5s=h.35(\"7M\");h.20=h.3I($f.20,$f.20!=$f.5J?$f.1T:$f.2F,$f.5J);h.1Z=h.3I($f.1Z,$f.1Z!=$f.5M?$f.1T:$f.2F,$f.5M);l(h.20.2z(h.1Z)>0)$f.4u=$1l.7Q;l(h.25()){h.5y();h.3j=$f.Z[$f.1E]}t h.3p(1p,2);3H($o);$d.5L.1M=$1l.7O;$d.2V.1i=$1l.7H;$d.2j.1i=$1l.7A;$d.1U.1i=$1l.7B;$d.1U.2e=!$c.1A($1v);h.6l();h.6V();l($f.4u)7z($f.4u);h.4B();l($f.Z.5t==1&&$f.Z[\"3V\"]===4p){$f.3A($f.Z,\"4k\",5a);$f.3A($f.Z,\"2x\",n(){l($f&&$f.1K.1d.2a==\"2u\"){$c.3c();l(!$f.2N&&$f.5b.3j!=$f.Z[$f.1E]&&$f.Z.7G)5l($f.Z,\"7D\")}});$f.Z[\"3V\"]=1p}$c.1k=$f.Z;3x()},5y:n(){q b=h.2S();l(b!=0){q $;l(b>0)$=h.1Z;t $=h.20;l($f.18.3Y){$o.y=$.y;$o.M=$.M;$o.d=$.d}l($f.18.2g){$o.H=$.H;$o.m=$.m;$o.s=$.s}}},3h:n(K,C,R,F,B,H,G,L,M){q $;l(K&&K.25)$=K;t{$=1a 1D();l(K!=\"\"){C=C||$f.1B;q I,D,Q=0,P,A=/3i|2H|3l|y|2I|3o|3R|M|1K|d|%2l|53|H|4V|m|4U|s|3u|D|4T|W|w/g,b=C.2J(A);A.2t=0;l(M)P=K.4c(/\\\\W+/);t{q E=0,N=\"^\";36((P=A.2U(C))!==1h){l(E>=0){D=C.1F(E,P.3Z);l(D&&\"-/\\\\\\\\\".1n(D)>=0)D=\"[\\\\\\\\-/]\";N+=D}E=A.2t;2Y(P[0]){1f\"3i\":N+=\"(\\\\\\\\d{4})\";1g;1f\"2H\":N+=\"(\\\\\\\\d{3})\";1g;1f\"2I\":1f\"3o\":1f\"3u\":1f\"D\":N+=\"(\\\\\\\\D+)\";1g;5v:N+=\"(\\\\\\\\d\\\\\\\\d?)\";1g}}N+=\".*$\";P=1a 3v(N).2U(K);Q=1}l(P){1b(I=0;I<b.x;I++){q J=P[I+Q];l(J)2Y(b[I]){1f\"2I\":1f\"3o\":$.M=O(b[I],J);1g;1f\"y\":1f\"3l\":J=3z(J,0);l(J<50)J+=5z;t J+=84;$.y=J;1g;1f\"2H\":$.y=3z(J,0)+$f.5w;1g;5v:$[b[I].4X(-1)]=J;1g}}}t $.d=32}}$.6Y(R,F,B,H,G,L);u $;n O(A,$){q b=A==\"2I\"?$1l.5u:$1l.2k;1b(q B=0;B<12;B++)l(b[B].3C()==$.5O(0,b[B].x).3C())u B+1;u-1}},35:n(b){q B,$=$f[b],A=\"\";l($&&$.x>0){1b(B=0;B<$.x;B++){A+=h.2P($[B]);l(B!=$.x-1)A+=\"|\"}A=A?1a 3v(\"(?:\"+A+\")\"):1h}t A=1h;u A},3d:n($){l($===4p)$=h.4F();l($f.Z[$f.1E]!=$)$f.Z[$f.1E]=$;h.4l()},4l:n($){q b=$f.$($f.86),$=3r($,h.4F($f.1T));l(b)b.1i=$;$f.Z[\"3E\"]=$},2P:n(s){q 3T=\"3m\",1r,2v,6n=/#?\\\\{(.*?)\\\\}/;s=s+\"\";1b(q i=0;i<3T.x;i++)s=s.1m(\"%\"+3T.1Q(i),h.1W(3T.1Q(i),1h,$1C));l(s.1F(0,3)==\"#F{\"){s=s.1F(3,s.x-1);l(s.1n(\"u \")<0)s=\"u \"+s;s=$f.51.4d(\"1a 88(\\\\\"\"+s+\"\\\\\");\");s=s()}36((1r=6n.2U(s))!=1h){1r.2t=1r.3Z+1r[1].x+1r[0].x-1r[1].x-1;2v=2n(4d(1r[1]));l(2v<0)2v=\"2f\"+(-2v);s=s.1F(0,1r.3Z)+2v+s.1F(1r.2t+1)}u s},3I:n(A,B,b){q $;A=h.2P(A);l(!A||A==\"\")A=b;l(6p A==\"6o\")$=A;t{$=h.3h(A,B,1h,1h,1,0,0,0,1c);$.y=(\"\"+$.y).1m(/^2f/,\"-\");$.M=(\"\"+$.M).1m(/^2f/,\"-\");$.d=(\"\"+$.d).1m(/^2f/,\"-\");$.H=(\"\"+$.H).1m(/^2f/,\"-\");$.m=(\"\"+$.m).1m(/^2f/,\"-\");$.s=(\"\"+$.s).1m(/^2f/,\"-\");l(A.1n(\"%2l\")>=0){A=A.1m(/%2l/g,\"0\");$.d=0;$.M=2n($.M)+1}$.1Y()}u $},25:n(){q A=$f.Z[$f.1E],$=h.1B,b=$f.18;l($f.7T||($f.6j!=\"\"&&A==\"\")){A=h.2P($f.6j);$=$f.1T}$o.2h(h.3h(A,$));l(A!=\"\"){q B=1;l(b.3Y&&!h.4n($o)){$o.y=$1C.y;$o.M=$1C.M;$o.d=$1C.d;B=0}l(b.2g&&!h.4h($o)){$o.H=$1C.H;$o.m=$1C.m;$o.s=$1C.s;B=0}u B&&h.1A($o)}l(!b.H)$o.H=0;l(!b.m)$o.m=0;l(!b.s)$o.s=0;u 1},4n:n($){l($.y!=1h)$=2W($.y,4)+\"-\"+$.M+\"-\"+$.d;u $.2J(/^((\\\\d{2}(([6i][7Z])|([5V][26]))[\\\\-\\\\/\\\\s]?((((0?[5S])|(1[5R]))[\\\\-\\\\/\\\\s]?((0?[1-9])|([1-2][0-9])|(3[5Z])))|(((0?[66])|(11))[\\\\-\\\\/\\\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\\\-\\\\/\\\\s]?((0?[1-9])|([1-2][0-9])))))|(\\\\d{2}(([6i][7X])|([5V][7Y]))[\\\\-\\\\/\\\\s]?((((0?[5S])|(1[5R]))[\\\\-\\\\/\\\\s]?((0?[1-9])|([1-2][0-9])|(3[5Z])))|(((0?[66])|(11))[\\\\-\\\\/\\\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\\\-\\\\/\\\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\\\s(((0?[0-9])|([1-2][0-3]))\\\\:([0-5]?[0-9])((\\\\s)|(\\\\:([0-5]?[0-9])))))?$/)},4h:n($){l($.H!=1h)$=$.H+\":\"+$.m+\":\"+$.s;u $.2J(/^([0-9]|([0-1][0-9])|([2][0-3])):([0-9]|([0-5][0-9])):([0-9]|([0-5][0-9]))$/)},2S:n($,A){$=$||$o;q b=$.2z(h.20,A);l(b>0){b=$.2z(h.1Z,A);l(b<0)b=0}u b},1A:n($,A,B){A=A||$f.18.43;q b=h.2S($,A);l(b==0){b=1;l(A==\"d\"&&B==1h)B=1I.5T((1a 1u($.y,$.M-1,$.d).1N()-$f.3U+7)%7);b=!h.5W(B)&&!h.5U($,A)}t b=0;u b},65:n(){q b=$f.Z,A=h,$=$f.Z[$f.1E];l($f.3O>=0&&$f.3O<=2&&$!=1h){l($!=\"\")A.2B.2h(A.3h($,$f.1B));l($==\"\"||(A.4n(A.2B)&&A.4h(A.2B)&&A.1A(A.2B))){l($!=\"\"){A.4D.2h(A.2B);A.3d()}t A.4l(\"\")}t u 1p}u 1c},3c:n($){3x();l(h.65()){h.3p(1c);$f.1o()}t{l($){2O($);h.3p(1p,2)}t h.3p(1p);$f.21()}},4a:n(){q E,C,D,K,A,H=1a 2A(),F=$1l.6e,G=$f.3U,I=\"\",$=\"\",b=1a 1D($o.y,$o.M,$o.d,2,0,0),J=b.y,B=b.M;A=1-1a 1u(J,B-1,1).1N()+G;l(A>1)A-=7;H.a(\"<1x Y=64 33=3s% 2C=0 2q=0 2o=0>\");H.a(\"<1j Y=61 4R=5H>\");l($f.63)H.a(\"<19>\"+F[0]+\"</19>\");1b(E=0;E<7;E++)H.a(\"<19>\"+F[(G+E)%7+1]+\"</19>\");H.a(\"</1j>\");1b(E=1,C=A;E<7;E++){H.a(\"<1j>\");1b(D=0;D<7;D++){b.25(J,B,C++);b.1Y();l(b.M==B){K=1c;l(b.2z($1v,\"d\")==0)I=\"7e\";t l(b.2z($1C,\"d\")==0)I=\"7d\";t I=($f.67&&(0==(G+D)%7||6==(G+D)%7)?\"7a\":\"77\");$=($f.67&&(0==(G+D)%7||6==(G+D)%7)?\"7o\":\"7v\")}t l($f.5A){K=1c;I=\"7t\";$=\"7h\"}t K=1p;l($f.63&&D==0&&(E<4||K))H.a(\"<19 Y=7f>\"+4E(b,$f.3U==0?1:0)+\"</19>\");H.a(\"<19 \");l(K){l(h.1A(b,\"d\",D)){l(h.5r(1I.5T((1a 1u(b.y,b.M-1,b.d).1N()-$f.3U+7)%7))||h.6c(b))I=\"7j\";H.a(\"1s=\\\\\"3b(\"+b.y+\",\"+b.M+\",\"+b.d+\");\\\\\" \");H.a(\"2G=\\\\\"h.1e=\\'\"+$+\"\\'\\\\\" \");H.a(\"2D=\\\\\"h.1e=\\'\"+I+\"\\'\\\\\" \")}t I=\"7m\";H.a(\"Y=\"+I);H.a(\">\"+b.d+\"</19>\")}t H.a(\"></19>\")}H.a(\"</1j>\")}H.a(\"</1x>\");u H.j()},5U:n(b,A){q $=h.4j(b,h.4m,A);u(h.4m&&$f.4x)?!$:$},5W:n($){u h.4i($,h.6m)},6c:n($){u h.4j($,h.6d)},5r:n($){u h.4i($,h.5s)},4j:n($,C,A){q b=A==\"d\"?$f.4N:$f.1T;l(A==\"d\"&&$f.18.d&&$f.4x){C=(C+\"\").1m(/^\\\\/\\\\(\\\\?:(.*)\\\\)\\\\/.*/,\"$1\");q B=C.1n($f.5X);l(B>=0)C=C.5O(0,B);C=1a 3v(C)}u C?C.52(h.3P(b,$)):0},4i:n(b,$){u $?$.52(b):0},3f:n(p,2Q,c,r,e,1R){q s=1a 2A(),4L=1R?\"r\"+p:p;l(1R)$o.1V(\"M\",1);5E=$o[p];s.a(\"<1x 2q=0 2o=3 2C=0\");1b(q i=0;i<r;i++){s.a(\"<1j 2K=\\\\\"2K\\\\\">\");1b(q j=0;j<c;j++){s.a(\"<19 2K \");$o[p]=4d(e);l($o[p]>2Q)s.a(\"Y=\\'1w\\'\");t l(h.1A($o,p)||($f.4x&&\"4Z\".1n(p)==-1&&h.2S($o,p)==0)){s.a(\"Y=\\'1w\\' 2G=\\\\\"h.1e=\\'2M\\'\\\\\" 2D=\\\\\"h.1e=\\'1w\\'\\\\\" 3X=\\\\\"\");s.a(\"1o($d.\"+p+\"D);$d.\"+4L+\"I.1i=\"+$o[p]+\";$d.\"+4L+\"I.4M();\\\\\"\")}t s.a(\"Y=\\'4I\\'\");s.a(\">\");l($o[p]<=2Q)s.a(p==\"M\"?$1l.2k[$o[p]-1]:$o[p]);s.a(\"</19>\")}s.a(\"</1j>\")}s.a(\"</1x>\");$o[p]=5E;l(1R)$o.1V(\"M\",-1);u s.j()},4J:n($,b){l($){q A=$.4S;l($6B)A=$.7g().2E;b.1d.2E=A}},7u:n($){h.4J($,$d.4f);$d.4f.1M=h.3f(\"M\",12,2,6,\"i+j*6+1\",$==$d.2c)},4K:n(b,B,A){q $=1a 2A();A=A||b==$d.2y;B=3r(B,$o.y-5);$.a(h.3f(\"y\",7w,2,5,B+\"+i+j*5\",A));$.a(\"<1x 2q=0 2o=3 2C=0 4R=5H><1j><19 \");$.a(h.20.y<B?\"Y=\\'1w\\' 2G=\\\\\"h.1e=\\'2M\\'\\\\\" 2D=\\\\\"h.1e=\\'1w\\'\\\\\" 3X=\\'l(2d.2m)2d.2m();2d.5e=1c;$c.4K(0,\"+(B-10)+\",\"+A+\")\\'\":\"Y=\\'4I\\'\");$.a(\">\\\\79</19><19 Y=\\'1w\\' 2G=\\\\\"h.1e=\\'2M\\'\\\\\" 2D=\\\\\"h.1e=\\'1w\\'\\\\\" 3X=\\\\\"1o($d.2R);$d.1y.4M();\\\\\">\\\\7c</19><19 \");$.a(h.1Z.y>=B+10?\"Y=\\'1w\\' 2G=\\\\\"h.1e=\\'2M\\'\\\\\" 2D=\\\\\"h.1e=\\'1w\\'\\\\\" 3X=\\'l(2d.2m)2d.2m();2d.5e=1c;$c.4K(0,\"+(B+10)+\",\"+A+\")\\'\":\"Y=\\'4I\\'\");$.a(\">\\\\8Y</19></1j></1x>\");h.4J(b,$d.2R);$d.2R.1M=$.j()},41:n(A,$){q B=$f.6Z[A],C=B[0],b=B[1];$d[A+\"D\"].1M=h.3f(A,$-1,b,1I.6C($/C/b),\"i*\"+b+\"*\"+C+\"+j*\"+C)},8U:n(){h.41(\"H\",24)},92:n(){h.41(\"m\",60)},8O:n(){h.41(\"s\",60)},4Q:n(C,A){h.6y();q $=A?[\">a/<8K\",\"8L 8S\",\"M>8T=8R \\\\\"8P:9e\\\\\"=9g \\\\\"9c.95.w\",\"98//:99\\\\\"=94 a<\"].4H(\"\").4c(\"\").9d().4H(\"\"):$1l.9b,B=h.3n,E=B.1d,b=1a 2A();b.a(\"<1x Y=64 33=3s% 2i=3s% 2C=0 2q=0 2o=0>\");b.a(\"<1j Y=61><19><z 1d=\\\\\"3q:2E\\\\\">\"+$+\"</z>\");l(!C)b.a(\"<z 1d=\\\\\"3q:62;9f:8m\\\\\" 1s=\\\\\"1o($d.1H);\\\\\">X&42;</z>\");b.a(\"</19></1j>\");1b(q D=0;D<B.x;D++)l(B[D]){b.a(\"<1j><19 1d=\\'5m-4R:2E\\' 2K=\\'2K\\' Y=\\'1w\\' 2G=\\\\\"h.1e=\\'2M\\'\\\\\" 2D=\\\\\"h.1e=\\'1w\\'\\\\\" 1s=\\\\\"\");b.a(\"3b(\"+B[D].y+\", \"+B[D].M+\", \"+B[D].d+\",\"+B[D].H+\",\"+B[D].m+\",\"+B[D].s+\");\\\\\">\");b.a(\"&42;\"+h.3P(1h,B[D]));b.a(\"</19></1j>\")}t b.a(\"<1j><19 Y=\\'1w\\'>&42;</19></1j>\");b.a(\"</1x>\");$d.1H.1M=b.j()},4q:n(){b(/w/);b(/4T|W/);b(/3u|D/);b(/3i|2H|3l|y/);b(/2I|3o|3R|M/);b(/1K|d/);b(/53|H/);b(/4V|m/);b(/4U|s/);$f.18.3Y=($f.18.y||$f.18.M||$f.18.d)?1c:1p;$f.18.2g=($f.18.H||$f.18.m||$f.18.s)?1c:1p;q $=$f.2F.2J(/%1u(.*)%5Y/);$f.5X=$?$[1]:\" \";$f.2F=$f.2F.1m(/%1u/,$f.4N).1m(/%5Y/,$f.6k);l($f.18.3Y){l($f.18.2g)$f.1T=$f.2F;t $f.1T=$f.4N}t $f.1T=$f.6k;n b(b){q $=(b+\"\").4X(1,2);$f.18[$]=b.2U($f.1B)?($f.18.43=$,1c):1p}},6l:n(){q $=0;$f.18.y?($=1,21($d.1y,$d.3M,$d.3N)):1o($d.1y,$d.3M,$d.3N);$f.18.M?($=1,21($d.1P,$d.3K,$d.3L)):1o($d.1P,$d.3K,$d.3L);$?21($d.4A):1o($d.4A);l($f.18.2g){21($d.34);3D($d.2w,$f.18.H);3D($d.3a,$f.18.m);3D($d.2r,$f.18.s)}t 1o($d.34);3g($d.2V,$f.6h);3g($d.2j,$f.6b);3g($d.1U,$f.4z);3g($d.4y,!$f.5q&&$f.18.d&&$f.8f);l($f.44||!($f.6h||$f.6b||$f.4z))1o($d.4e);t 21($d.4e)},3p:n(B,D){q A=$f.Z,b=$69?\"Y\":\"1e\";l($f.3O==-1)u;t l(B)C(A);t{l(D==1h)D=$f.3O;2Y(D){1f 0:l(8s($1l.8E)){A[$f.1E]=h.3j||\"\";C(A)}t $(A);1g;1f 1:A[$f.1E]=h.3j||\"\";C(A);1g;1f 2:$(A);1g}}n C(A){q B=A.1e;l(B){q $=B.1m(/6g/g,\"\");l(B!=$)A.6f(b,$)}}n $($){$.6f(b,$.1e+\" 6g\")}},1W:n(D,b,$){$=$||$1v;q H,C=[D+D,D],E,A=$[D],F=n($){u 2W(A,$.x)};2Y(D){1f\"w\":A=1N($);1g;1f\"D\":q G=1N($)+1;F=n($){u $.x==2?$1l.8F[G]:$1l.6e[G]};1g;1f\"W\":A=4E($);1g;1f\"y\":C=[\"3i\",\"2H\",\"3l\",\"y\"];b=b||C[0];F=n(b){u 2W((b.x<4)?(b.x<3?$.y%3s:($.y+5z-$f.5w)%8D):A,b.x)};1g;1f\"M\":C=[\"2I\",\"3o\",\"3R\",\"M\"];F=n($){u($.x==4)?$1l.5u[A-1]:($.x==3)?$1l.2k[A-1]:2W(A,$.x)};1g}b=b||D+D;l(\"3m\".1n(D)>-1&&D!=\"y\"&&!$f.18[D])l(\"4Z\".1n(D)>-1)A=0;t A=1;q B=[];1b(H=0;H<C.x;H++){E=C[H];l(b.1n(E)>=0){B[H]=F(E);b=b.1m(1a 3v(E,\"g\"),\"{\"+H+\"}\")}}1b(H=0;H<B.x;H++)b=b.1m(1a 3v(\"\\\\\\\\{\"+H+\"\\\\\\\\}\",\"g\"),B[H]);u b},3P:n(b,$){$=$||h.3h($f.Z[$f.1E],h.1B)||$1v;b=b||h.1B;l(b.1n(\"%2l\")>=0){q A=1a 1D();A.2h($);A.d=0;A.M=2n(A.M)+1;A.1Y();b=b.1m(/%2l/g,A.d)}q B=\"8J\";1b(q D=0;D<B.x;D++){q C=B.1Q(D);b=h.1W(C,b,$)}l(b.1n(\"D\")>=0){b=b.1m(/3u/g,\"%1K\").1m(/D/g,\"%d\");b=h.1W(\"M\",b,$);b=b.1m(/\\\\%1K/g,h.1W(\"D\",\"3u\")).1m(/\\\\%d/g,h.1W(\"D\",\"D\"))}t b=h.1W(\"M\",b,$);u b},8H:n(b,$){u h.1W(b,$,$o)},4F:n($){u h.3P($,h.4D)},4B:n(){$c.4q();$d.4b.1M=\"\";l($f.5q){$c.2X=1c;$f.5A=1p;$d.1e=\"4P 8v\";q $=1a 2A();$.a(\"<1x Y=8t 33=3s% 2q=0 2o=0 2C=1><1j><19 5K=5P>\");$.a(h.4a());$.a(\"</19><19 5K=5P>\");$o.1V(\"M\",1);$.a(h.4a());$d.2c=$d.1P.5Q(1c);$d.2y=$d.1y.5Q(1c);$d.4b.4O($d.2c);$d.4b.4O($d.2y);$d.2c.1i=$1l.2k[$o.M-1];$d.2c[\"3E\"]=$o.M;$d.2y.1i=$o.y;55(\"6L,6M\");$d.2c.1e=$d.2y.1e=\"47\";$o.1V(\"M\",-1);$.a(\"</19></1j></1x>\");$d.2Z.1M=$.j()}t{$d.1e=\"4P\";$d.2Z.1M=h.4a()}l(!$f.18.d||$f.8x){h.4Q(1c);3G($d.1H)}t 1o($d.1H);h.5F()},5F:n(){q b=8A.1L.74(\"8z\");1b(q C=0;C<b.x;C++){q $=$d.1d.2i;$d.1d.2i=\"\";q A=$d.2p;l(b[C].8u==8w&&A){b[C].1d.33=$d.4W+\"6W\";q B=$d.34.2p;l(B&&$d.4e.1d.2a==\"2u\"&&$d.34.1d.2a!=\"2u\"&&1L.6R.8I-A>=B){A+=B;$d.1d.2i=A}t $d.1d.2i=$;b[C].1d.2i=1I.2Q(A,$d.2p)+\"6W\"}}$d.1H.1d.33=$d.2Z.4W;$d.1H.1d.2i=$d.2Z.2p},5c:n(){$o.d=1I.6J(1a 1u($o.y,$o.M,0).3t(),$o.d);$1v.2h($o);$f.2N=0;h.3d();l(!$f.44)l(h.1A($o)){4C();1o($f.1K)}l($f.6T)2b(\"6T\")},6V:n(){$d.2V.1s=n(){l(!2b(\"8i\")){$f.2N=0;$c.3d(\"\");4C();1o($f.1K);l($f.6Q)2b(\"6Q\")}};$d.1U.1s=n(){3b()};l(h.1A($1C)){$d.2j.2e=1p;$d.2j.1s=n(){$o.2h($1C);3b()}}t $d.2j.2e=1c},6y:n(){q H,G,A,F,C=[],$=5,E=$f.6z.x,b=$f.18.43;l(E>$)E=$;t l(b==\"m\"||b==\"s\")C=[-60,-30,0,30,60,-15,15,-45,45];t 1b(H=0;H<$+9;H++)C[H]=$o[b]-2+H;1b(H=G=0;H<E;H++){A=h.3I($f.6z[H]);l(h.1A(A))h.3n[G++]=A}q B=\"3m\",D=[1,1,1,0,0,0];1b(H=0;H<=B.1n(b);H++)D[H]=$o[B.1Q(H)];1b(H=0;G<$;H++)l(H<C.x){A=1a 1D(D[0],D[1],D[2],D[3],D[4],D[5]);A[b]=C[H];A.1Y();l(h.1A(A))h.3n[G++]=A}t h.3n[G++]=1h}};n 4C(){q b=$f.Z;6F{l(b.1d.2a!=\"2u\"&&b.3k!=\"6q\"&&(b.6v.3C()==\"1z\"||b.6v.3C()==\"8d\")){b[\"3V\"]=1c;b.22()}}6s($){}8j(n(){b[\"3V\"]=1p},8p)}n 2A(){h.s=1a 8o();h.i=0;h.a=n($){h.s[h.i++]=$};h.j=n(){u h.s.4H(\"\")}}n 4E($,C){C=C||0;q A=1a 1u($.y,$.M-1,$.d+C);l($f.8X==\"8q\"){A.6N(A.3t()-(A.1N()+6)%7+3);q B=A.3F();A.8l(0);A.6N(4);u 1I.6E((B-A.3F())/(7*6D))+1}t{q b=1a 1u($.y,0,1);A=1I.6E((A.3F()-b.3F())/6D);u 1I.6C((A+(b.1N()+1))/7)}}n 1N($){q b=1a 1u($.y,$.M-1,$.d);u b.1N()}n 21(){3w(2L,\"\")}n 3G(){3w(2L,\"6G\")}n 1o(){3w(2L,\"2u\")}n 3w(b,$){1b(i=0;i<b.x;i++)b[i].1d.2a=$}n 3g(b,$){$?21(b):1o(b)}n 3D(b,$){l($)b.2e=1p;t{b.2e=1c;b.1i=\"8n\"}}n c(b,A){q $=A;l(b==\"M\")$=3B(A,1,12);t l(b==\"H\")$=3B(A,0,23);t l(\"68\".1n(b)>=0)$=3B(A,0,59);l(A==$+1)$=$1v[b];l($1v[b]!=$&&!2b(b+\"9a\")){q B=$c.2S();l(B==0)28(b,$);t l(B<0)3H($c.20);t l(B>0)3H($c.1Z);$d.1U.2e=!$c.1A($1v);l(\"8M\".1n(b)>=0)$c.4B();2b(b+\"90\")}}n 3H($){28(\"y\",$.y);28(\"M\",$.M);28(\"d\",$.d);28(\"H\",$.H);28(\"m\",$.m);28(\"s\",$.s)}n 3b(F,B,b,D,C,A){q $=1a 1D($o.y,$o.M,$o.d,$o.H,$o.m,$o.s);$o.25(F,B,b,D,C,A);l(!2b(\"93\")){q E=$.y==F&&$.M==B&&$.d==b;l(!E&&2L.x!=0){c(\"y\",F);c(\"M\",B);c(\"d\",b);$c.1k=$f.Z;49()}l($c.2X||E||2L.x==0)$c.5c()}t $o=$}n 49(){l($f.3y){$c.3d();$f.Z.22()}}n 2b($){q b;l($f[$])b=$f[$].5d($f.Z,$f);u b}n 28(b,$){l($==1h)$=$o[b];$1v[b]=$o[b]=$;l(\"8W\".1n(b)>=0)$d[b+\"I\"].1i=$;l(b==\"M\"){$d.1P[\"3E\"]=$;$d.1P.1i=$1l.2k[$-1]}}n 3B(b,$,A){l(b<$)b=$;t l(b>A)b=A;u b}n 71($,b){$f.3A($,\"4k\",n($){$=$||2d,k=($.56==4p)?$.54:$.56;l(k==9)b()})}n 2W($,b){$=$+\"\";36($.x<b)$=\"0\"+$;u $}n 3x(){1o($d.2R,$d.4f,$d.5N,$d.6P,$d.73)}n 5g(b){q A=$c.1k,$=$f.6Z;l(A!=$d.2w&&A!=$d.3a&&A!=$d.2r)A=$d.2w;2Y(A){1f $d.2w:c(\"H\",$o.H+b*$.H[0]);1g;1f $d.3a:c(\"m\",$o.m+b*$.m[0]);1g;1f $d.2r:c(\"s\",$o.s+b*$.s[0]);1g}49()}n 1D(D,A,$,C,B,b){h.25(D,A,$,C,B,b)}1D.3J={25:n(E,B,b,D,C,A){q $=1a 1u();h.y=1t(E,h.y,$.5k());h.M=1t(B,h.M,$.5h()+1);h.d=$f.18.d?1t(b,h.d,$.3t()):1;h.H=1t(D,h.H,$.5p());h.m=1t(C,h.m,$.5i());h.s=1t(A,h.s,$.5n())},2h:n($){l($)h.25($.y,$.M,$.d,$.H,$.m,$.s)},6Y:n(E,B,b,D,C,A){q $=1a 1u();h.y=1t(h.y,E,$.5k());h.M=1t(h.M,B,$.5h()+1);h.d=$f.18.d?1t(h.d,b,$.3t()):1;h.H=1t(h.H,D,$.5p());h.m=1t(h.m,C,$.5i());h.s=1t(h.s,A,$.5n())},2z:n($,C){q A=\"3m\",b,B;C=A.1n(C);C=C>=0?C:5;1b(q D=0;D<=C;D++){B=A.1Q(D);b=h[B]-$[B];l(b>0)u 1;t l(b<0)u-1}u 0},1Y:n(){q $=1a 1u(h.y,h.M-1,h.d,h.H,h.m,h.s);h.y=$.5k();h.M=$.5h()+1;h.d=$.3t();h.H=$.5p();h.m=$.5i();h.s=$.5n();u!6w(h.y)},1V:n(b,$){l(\"3m\".1n(b)>=0){q A=h.d;l(b==\"M\")h.d=1;h[b]+=$;h.1Y();h.d=A}}};n 2n($){u 8V($,10)}n 3z($,b){u 3r(2n($),b)}n 1t($,A,b){u 3z($,3r(A,b))}n 3r($,b){u $==1h||6w($)?b:$}n 5l(A,$){l($6B)A.5l(\"91\"+$);t{q b=1L.8Z(\"8N\");b.8Q($,1c,1c);A.97(b)}}n 4g($){q A,B,b=\"y,M,H,m,s,6M,6L\".4c(\",\");1b(B=0;B<b.x;B++){A=b[B];l($d[A+\"I\"]==$)u A.4X(A.x-1,A.x)}u 0}n 6X($){q A=4g(h),b=$d[A+\"D\"];l(!A)u;$c.1k=h;l(A==\"y\")h.1e=\"6H\";t l(A==\"M\"){h.1e=\"6H\";h.1i=h[\"3E\"]}6F{h.5o()}6s($){}$c[\"3f\"+A](h);3G(b);l(\"4Z\".1n(A)>=0){b.1d.8k=1I.6J(h.4S,$d.2r.4S+60-b.4W);b.1d.8e=h.8b-b.2p-2}}n 3Q(70){q p=4g(h),1R,5f,v=h.1i,6A=$o[p];l(p==0)u;$o[p]=6r(v)>=0?6r(v):$o[p];l(p==\"y\"){1R=h==$d.2y;l(1R&&$o.M==12)$o.y-=1}t l(p==\"M\"){1R=h==$d.2c;l(1R){5f=$1l.2k[$o[p]-1];l(6A==12)$o.y+=1;$o.1V(\"M\",-1)}l($1v.M==$o.M)h.1i=5f||$1l.2k[$o[p]-1];l(($1v.y!=$o.y))c(\"y\",$o.y)}4d(\"c(\\\\\"\"+p+\"\\\\\",\"+$o[p]+\")\");l(70!==1c){l(p==\"y\"||p==\"M\")h.1e=\"47\";1o($d[p+\"D\"])}49()}n 2O($){l($.2m){$.2m();$.8g()}t{$.5e=1c;$.6U=1p}l($5x)$.54=0}n 55($){q A=$.4c(\",\");1b(q B=0;B<A.x;B++){q b=A[B]+\"I\";$d[b].8C=6X;$d[b].2x=3Q}}n 5a(M){q H=M.5I||M.5B,Q=M.56||M.54;5j=$f.44?1c:$f.1K.1d.2a!=\"2u\";$f.2N=1;l(Q>=96&&Q<=8y)Q-=48;l($f.8r&&5j){l(!H.3e){H.3e=$f.1X[1];$c.1k=$f.Z}l(H==$f.Z)$c.1k=$f.Z;l(Q==27)l(H==$f.Z){$c.3c();u}t $f.Z.22();l(Q>=37&&Q<=40){q U;l($c.1k==$f.Z||$c.1k==$d.1U)l($f.18.d){U=\"d\";l(Q==38)$o[U]-=7;t l(Q==39)$o[U]+=1;t l(Q==37)$o[U]-=1;t $o[U]+=7;$o.1Y();c(\"y\",$o[\"y\"]);c(\"M\",$o[\"M\"]);c(\"d\",$o[U]);2O(M);u}t{U=$f.18.43;$d[U+\"I\"].22()}U=U||4g($c.1k);l(U){l(Q==38||Q==39)$o[U]+=1;t $o[U]-=1;$o.1Y();$c.1k.1i=$o[U];3Q.5d($c.1k,1c);$c.1k.5o()}}t l(Q==9){q D=H.3e;1b(q R=0;R<$f.1X.x;R++)l(D.2e==1c||D.2p==0)D=D.3e;t 1g;l($c.1k!=D){$c.1k=D;D.22()}}t l(Q==13){3Q.5d($c.1k);l($c.1k.3k==\"1S\")$c.1k.8B();t l($f.5b.3j==$f.Z[$f.1E])$c.5c();t $c.3c();$c.1k=$f.Z}}t l(Q==9&&H==$f.Z)$c.3c();l($f.8G&&!$5x&&!$f.3S&&$c.1k==$f.Z&&(Q>=48&&Q<=57)){q T=$f.Z,S=T.1i,F=E(T),I={29:\"\",1r:[]},R=0,K,N=0,X=0,O=0,J,b=/3i|2H|3l|y|3R|M|1K|d|%2l|53|H|4V|m|4U|s|4T|W|w/g,L=$f.1B.2J(b),B,A,$,V,W,G,J=0;l(S!=\"\"){O=S.2J(/[0-9]/g);O=O==1h?0:O.x;1b(R=0;R<L.x;R++)O-=1I.2Q(L[R].x,2);O=O>=0?1:0;l(O==1&&F>=S.x)F=S.x-1}S=S.1F(0,F)+8h.8c(Q)+S.1F(F+O);F++;1b(R=0;R<S.x;R++){q C=S.1Q(R);l(/[0-9]/.52(C))I.29+=C;t I.1r[R]=1}S=\"\";b.2t=0;36((K=b.2U($f.1B))!==1h){X=K.3Z-(K[0]==\"%2l\"?1:0);l(N>=0){S+=$f.1B.1F(N,X);l(F>=N+J&&F<=X+J)F+=X-N}N=b.2t;G=N-X;B=I.29.1F(0,G);A=K[0].1Q(0);$=2n(B.1Q(0));l(I.29.x>1){V=I.29.1Q(1);W=$*10+2n(V)}t{V=\"\";W=$}l(I.1r[X+1]||A==\"M\"&&W>12||A==\"d\"&&W>31||A==\"H\"&&W>23||\"68\".1n(A)>=0&&W>59){l(K[0].x==2)B=\"0\"+$;t B=$;F++}t l(G==1){B=W;G++;J++}S+=B;I.29=I.29.1F(G);l(I.29==\"\")1g}T.1i=S;P(T,F);2O(M)}l(5j&&$c.1k!=$f.Z&&!((Q>=48&&Q<=57)||Q==8||Q==46))2O(M);n E(A){q b=0;l($f.51.1L.6a){q B=$f.51.1L.6a.82(),$=B.5m.x;B.6I(\"4Y\",-A.1i.x);b=B.5m.x-$}t l(A.58||A.58==\"0\")b=A.58;u b}n P(b,A){l(b.6S){b.22();b.6S(A,A)}t l(b.6O){q $=b.6O();$.7P(1c);$.85(\"4Y\",A);$.6I(\"4Y\",A);$.5o()}}}1L.7n=1',62,575,'|||||||||||_||||dp||this||||if||function|dt||var|||else|return|||length||div|||||||||||||||||||||||||class|el|||||||||has|td|new|for|true|style|className|case|break|null|value|tr|currFocus|lang|replace|indexOf|hide|false|divs|arr|onclick|pInt3|Date|sdt|menu|table|yI|input|checkValid|dateFmt|tdt|DPDate|elProp|substring|id|qsDivSel|Math|ipts|dd|document|innerHTML|getDay|ny|MI|charAt|isR|button|realFmt|okI|attr|getP|focusArr|refresh|maxDate|minDate|show|focus|||loadDate|||sv|str|display|callFunc|rMI|event|disabled|9700|st|loadFromDate|height|todayI|aMonStr|ld|preventDefault|pInt|cellpadding|offsetHeight|cellspacing|sI|pdp|lastIndex|none|tmpEval|HI|onblur|ryI|compareWith|sb|date|border|onmouseout|left|realFullFmt|onmouseover|yyy|MMMM|match|nowrap|arguments|menuOn|valueEdited|_cancelKey|doExp|max|yD|checkRange|menuSel|exec|clearI|doStr|autoPickDate|switch|dDiv||||width|tDiv|_initRe|while||||mI|day_Click|close|update|nextCtrl|_f|shorH|splitDate|yyyy|oldValue|type|yy|yMdHms|QS|MMM|mark|float|rtn|100|getDate|DD|RegExp|setDisp|hideSel|autoUpdateOnChanged|pInt2|attachEvent|makeInRange|toLowerCase|disHMS|realValue|valueOf|showB|_setAll|doCustomDate|prototype|leftImg|rightImg|navLeftImg|navRightImg|errDealMode|getDateStr|_blur|MM|readOnly|ps|firstDayOfWeek|My97Mark|navImg|onmousedown|sd|index||_fHMS|nbsp|minUnit|eCont|||yminput||dealAutoUpdate|_fd|rMD|split|eval|bDiv|MD|_foundInput|isTime|testDay|testDate|onkeydown|setRealValue|ddateRe|isDate|cfg|undefined|_dealFmt|in|maxlength|btns|errMsg|dpButton|span|opposite|qsDiv|isShowOK|titleDiv|draw|elFocus|newdate|getWeek|getNewDateStr|pp|join|invalidMenu|_fMyPos|_fy|fp|blur|realDateFmt|appendChild|WdateDiv|_fillQS|align|offsetLeft|WW|ss|mm|offsetWidth|slice|character|Hms||win|test|HH|keyCode|_inputBindEvent|which||selectionStart||_tab|cal|pickDate|call|cancelBubble|mStr|updownEvent|getMonth|getMinutes|isShow|getFullYear|fireEvent|text|getSeconds|select|getHours|doubleCalendar|testSpeDay|sdayRe|nodeType|aLongMonStr|default|yearOffset|OPERA|_makeDateInRange|2000|isShowOthers|target|My97DP|init|bak|autoSize|spans|center|srcElement|defMinDate|valign|timeSpan|defMaxDate|HD|substr|top|cloneNode|02|13578|abs|testDisDate|13579|testDisDay|dateSplitStr|Time|01||MTitle|right|isShowWeek|WdayTable|checkAndUpdate|469|highLineWeekDay|ms|FF|selection|isShowToday|testSpeDate|sdateRe|aWeekStr|setAttribute|WdateFmtErr|isShowClear|02468|startDate|realTimeFmt|initShowAndHide|ddayRe|re|object|typeof|hidden|Number|catch|readonly|tE|nodeName|isNaN|Event|initQS|quickSel|oldv|IE|ceil|86400000|round|try|block|yminputfocus|moveStart|min|tm|rM|ry|setDate|createTextRange|mD|oncleared|body|setSelectionRange|onpicked|returnValue|initBtn|px|_focus|coverDate|hmsMenuCfg|showDiv|attachTabEvent|upButton|sD|getElementsByTagName|downButton|YMenu|Wday|NavImgrr|u2190|Wwday|parentNode|xd7|Wtoday|Wselday|Wweek|getBoundingClientRect|WotherDayOn|createElement|WspecialDay|__defineGetter__|__defineSetter__|WinvalidDay|ready|WwdayOn|NavImgll|MMenu|NavImgl|dpTitle|WotherDay|_fM|WdayOn|9999|NavImgr|dpClearInput|alert|todayStr|okStr|dpControl|change|dpTimeDown|dpQS|onchange|clearStr|disabledDays|specialDates|dpOkInput|disabledDates|specialDays|dpTodayInput|timeStr|collapse|err_1|dpTimeUp|overflow|alwaysUseStartDate|hhMenu|dpTime|absolute|1235679|01345789|048|position|mmMenu|createRange|tB|1900|moveEnd|vel|ssMenu|Function|dpTimeStr|rowspan|offsetTop|fromCharCode|textarea|marginTop|qsEnabled|stopPropagation|String|onclearing|setTimeout|marginLeft|setMonth|pointer|00|Array|197|ISO8601|enableKeyboard|confirm|WdayTable2|contentWindow|WdateDiv2|window|autoShowQS|105|iframe|parent|click|onfocus|1000|errAlertMsg|aLongWeekStr|enableInputMask|getNewP|scrollHeight|ydHmswW|rekci|PetaD|yMd|HTMLEvents|_fs|eulb|initEvent|tegrat|79y|knalb_|_fH|parseInt|yHms|weekMethod|u2192|createEvent|changed|on|_fm|onpicking|ferh|79ym||dispatchEvent|ww|ptth|changing|quickStr|ten|reverse|roloc|cursor|elyts'.split('|'),0,{}))"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/My97DatePicker/4.8/lang/en.js",
    "content": "var $lang={\nerrAlertMsg: \"Invalid date or the date out of range,redo or not?\",\naWeekStr: [\"wk\", \"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\naLongWeekStr:[\"wk\",\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\",\"Sunday\"],\naMonStr: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"],\naLongMonStr: [\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"],\nclearStr: \"Clear\",\ntodayStr: \"Today\",\nokStr: \"OK\",\nupdateStr: \"OK\",\ntimeStr: \"Time\",\nquickStr: \"Quick Selection\",\nerr_1: 'MinDate Cannot be bigger than MaxDate!'\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/My97DatePicker/4.8/lang/zh-cn.js",
    "content": "var $lang={\nerrAlertMsg: \"\\u4E0D\\u5408\\u6CD5\\u7684\\u65E5\\u671F\\u683C\\u5F0F\\u6216\\u8005\\u65E5\\u671F\\u8D85\\u51FA\\u9650\\u5B9A\\u8303\\u56F4,\\u9700\\u8981\\u64A4\\u9500\\u5417?\",\naWeekStr: [\"\\u5468\",\"\\u65E5\",\"\\u4E00\",\"\\u4E8C\",\"\\u4E09\",\"\\u56DB\",\"\\u4E94\",\"\\u516D\"],\naLongWeekStr:[\"\\u5468\",\"\\u661F\\u671F\\u65E5\",\"\\u661F\\u671F\\u4E00\",\"\\u661F\\u671F\\u4E8C\",\"\\u661F\\u671F\\u4E09\",\"\\u661F\\u671F\\u56DB\",\"\\u661F\\u671F\\u4E94\",\"\\u661F\\u671F\\u516D\"],\naMonStr: [\"\\u4E00\\u6708\",\"\\u4E8C\\u6708\",\"\\u4E09\\u6708\",\"\\u56DB\\u6708\",\"\\u4E94\\u6708\",\"\\u516D\\u6708\",\"\\u4E03\\u6708\",\"\\u516B\\u6708\",\"\\u4E5D\\u6708\",\"\\u5341\\u6708\",\"\\u5341\\u4E00\",\"\\u5341\\u4E8C\"],\naLongMonStr: [\"\\u4E00\\u6708\",\"\\u4E8C\\u6708\",\"\\u4E09\\u6708\",\"\\u56DB\\u6708\",\"\\u4E94\\u6708\",\"\\u516D\\u6708\",\"\\u4E03\\u6708\",\"\\u516B\\u6708\",\"\\u4E5D\\u6708\",\"\\u5341\\u6708\",\"\\u5341\\u4E00\\u6708\",\"\\u5341\\u4E8C\\u6708\"],\nclearStr: \"\\u6E05\\u7A7A\",\ntodayStr: \"\\u4ECA\\u5929\",\nokStr: \"\\u786E\\u5B9A\",\nupdateStr: \"\\u786E\\u5B9A\",\ntimeStr: \"\\u65F6\\u95F4\",\nquickStr: \"\\u5FEB\\u901F\\u9009\\u62E9\", \nerr_1: '\\u6700\\u5C0F\\u65E5\\u671F\\u4E0D\\u80FD\\u5927\\u4E8E\\u6700\\u5927\\u65E5\\u671F!'\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/My97DatePicker/4.8/lang/zh-tw.js",
    "content": "var $lang={\nerrAlertMsg: \"\\u4E0D\\u5408\\u6CD5\\u7684\\u65E5\\u671F\\u683C\\u5F0F\\u6216\\u8005\\u65E5\\u671F\\u8D85\\u51FA\\u9650\\u5B9A\\u7BC4\\u570D,\\u9700\\u8981\\u64A4\\u92B7\\u55CE?\",\naWeekStr: [\"\\u5468\",\"\\u65E5\",\"\\u4E00\",\"\\u4E8C\",\"\\u4E09\",\"\\u56DB\",\"\\u4E94\",\"\\u516D\"],\naLongWeekStr:[\"\\u5468\",\"\\u661F\\u671F\\u65E5\",\"\\u661F\\u671F\\u4E00\",\"\\u661F\\u671F\\u4E8C\",\"\\u661F\\u671F\\u4E09\",\"\\u661F\\u671F\\u56DB\",\"\\u661F\\u671F\\u4E94\",\"\\u661F\\u671F\\u516D\"],\naMonStr: [\"\\u4E00\\u6708\",\"\\u4E8C\\u6708\",\"\\u4E09\\u6708\",\"\\u56DB\\u6708\",\"\\u4E94\\u6708\",\"\\u516D\\u6708\",\"\\u4E03\\u6708\",\"\\u516B\\u6708\",\"\\u4E5D\\u6708\",\"\\u5341\\u6708\",\"\\u5341\\u4E00\",\"\\u5341\\u4E8C\"],\naLongMonStr: [\"\\u4E00\\u6708\",\"\\u4E8C\\u6708\",\"\\u4E09\\u6708\",\"\\u56DB\\u6708\",\"\\u4E94\\u6708\",\"\\u516D\\u6708\",\"\\u4E03\\u6708\",\"\\u516B\\u6708\",\"\\u4E5D\\u6708\",\"\\u5341\\u6708\",\"\\u5341\\u4E00\\u6708\",\"\\u5341\\u4E8C\\u6708\"],\nclearStr: \"\\u6E05\\u7A7A\",\ntodayStr: \"\\u4ECA\\u5929\",\nokStr: \"\\u78BA\\u5B9A\",\nupdateStr: \"\\u78BA\\u5B9A\",\ntimeStr: \"\\u6642\\u9593\",\nquickStr: \"\\u5FEB\\u901F\\u9078\\u64C7\",\nerr_1: '\\u6700\\u5C0F\\u65E5\\u671F\\u4E0D\\u80FD\\u5927\\u65BC\\u6700\\u5927\\u65E5\\u671F!'\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/My97DatePicker/4.8/skin/WdatePicker.css",
    "content": ".Wdate{\n\tbackground:#fff url(datePicker.gif) no-repeat right;\n}\n.Wdate::-ms-clear{display:none;}\n\n.WdateFmtErr{\n\tfont-weight:bold;\n\tcolor:red;\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/My97DatePicker/4.8/skin/default/datepicker.css",
    "content": "/* \n * My97 DatePicker 4.8\n */\n\n.WdateDiv{\n\twidth:180px;\n\tbackground-color:#FFFFFF;\n\tborder:#bbb 1px solid;\n\tpadding:2px;\n}\n\n.WdateDiv2{\n\twidth:360px;\n}\n.WdateDiv *{font-size:9pt;}\n\n.WdateDiv .NavImg a{\n\tdisplay:block;\n\tcursor:pointer;\n\theight:16px;\n\twidth:16px;\n}\n\n.WdateDiv .NavImgll a{\n\tfloat:left;\n\tbackground:transparent url(img.gif) no-repeat scroll 0 0;\n}\n.WdateDiv .NavImgl a{\n\tfloat:left;\n\tbackground:transparent url(img.gif) no-repeat scroll -16px 0;\n}\n.WdateDiv .NavImgr a{\n\tfloat:right;\n\tbackground:transparent url(img.gif) no-repeat scroll -32px 0;\n}\n.WdateDiv .NavImgrr a{\n\tfloat:right;\n\tbackground:transparent url(img.gif) no-repeat scroll -48px 0;\n}\n\n.WdateDiv #dpTitle{\n\theight:24px;\n\tmargin-bottom:2px;\n\tpadding:1px;\n}\n\n.WdateDiv .yminput{\n\tmargin-top:2px;\n\ttext-align:center;\n\theight:20px;\n\tborder:0px;\n\twidth:50px;\n\tcursor:pointer;\t\t\n}\n\n.WdateDiv .yminputfocus{\n\tmargin-top:2px;\n\ttext-align:center;\n\tfont-weight:bold;\n\theight:20px;\n\tcolor:blue;\n\tborder:#ccc 1px solid;\n\twidth:50px;\n}\n\n.WdateDiv .menuSel{\n\tz-index:1;\n\tposition:absolute;\n\tbackground-color:#FFFFFF;\t\n\tborder:#ddd 1px solid;\n\tdisplay:none;\n}\n\n.WdateDiv .menu{\n\tcursor:pointer;\n\tbackground-color:#fff;\n}\n\n.WdateDiv .menuOn{\n\tcursor:pointer;\n\tbackground-color:#BEEBEE;\n}\n\n.WdateDiv .invalidMenu{\n\tcolor:#aaa;\n}\n\n.WdateDiv .YMenu{\n\tmargin-top:20px;\n\t\n}\n\n.WdateDiv .MMenu{\n\tmargin-top:20px;\n\t*width:62px;\n}\n\n.WdateDiv .hhMenu{\n\tmargin-top:-90px; \n\tmargin-left:26px;\n}\n\n.WdateDiv .mmMenu{\n\tmargin-top:-46px; \n\tmargin-left:26px;\n}\n\n.WdateDiv .ssMenu{\n\tmargin-top:-24px; \n\tmargin-left:26px;\n}\n\n .WdateDiv .Wweek {\n \ttext-align:center;\n\tbackground:#DAF3F5;\n\tborder-right:#ddd 1px solid;\n }\n\n.WdateDiv .MTitle{\n\tbackground-color:#222;\n\tcolor:#fff\n}\n.WdateDiv .WdayTable2{\n\tborder-collapse:collapse;\n\tborder:#c5d9e8 1px solid;\n}\n.WdateDiv .WdayTable2 table{\n\tborder:0;\n}\n\n.WdateDiv .WdayTable{\n\tline-height:20px;\n\tborder:#c5d9e8 1px solid;\n}\n.WdateDiv .WdayTable td{\n\ttext-align:center;\n}\n\n.WdateDiv .Wday{\n\tcursor:pointer;\n}\n\n.WdateDiv .WdayOn{\n\tcursor:pointer;\n\tbackground-color:#222;\n\tcolor:#fff\n}\n\n.WdateDiv .Wwday{\n\tcursor:pointer;\n\tcolor:#FF2F2F;\n}\n\n.WdateDiv .WwdayOn{\n\tcursor:pointer;\n\tcolor:#fff;\n\tbackground-color:#222;\n}\n.WdateDiv .Wtoday{\n\tcursor:pointer;\n\tcolor:blue;\n}\n.WdateDiv .Wselday{\n\tbackground-color:#222;\n\tcolor:#fff\n}\n.WdateDiv .WspecialDay{\n\tbackground-color:#66F4DF;\n}\n\n.WdateDiv .WotherDay{ \n\tcursor:pointer;\n\tcolor:#428BCA;\t\n}\n\n.WdateDiv .WotherDayOn{ \n\tcursor:pointer;\n\tbackground-color:#222;\n\tcolor:#fff\t\n}\n\n.WdateDiv .WinvalidDay{\n\tcolor:#aaa;\n}\n\n.WdateDiv #dpTime{\n\tfloat:left;\n\tmargin-top:3px;\n\tmargin-right:30px;\n}\n\n.WdateDiv #dpTime #dpTimeStr{\n\tmargin-left:1px;\n}\n\n.WdateDiv #dpTime input{\n\twidth:18px;\n\theight:20px;\n\ttext-align:center;\n\tborder:#ccc 1px solid;\t\n}\n\n.WdateDiv #dpTime .tB{\n\tborder-right:0px;\n}\n\n.WdateDiv #dpTime .tE{\n\tborder-left:0;\n\tborder-right:0;\n}\n\n.WdateDiv #dpTime .tm{\n\twidth:7px;\n\tborder-left:0;\n\tborder-right:0;\n}\n\n.WdateDiv #dpTime #dpTimeUp{\n\theight:10px;\n\twidth:13px;\n\tborder:0px;\n\tbackground:url(img.gif) no-repeat -32px -16px;\n}\n\n.WdateDiv #dpTime #dpTimeDown{\n\theight:10px;\n\twidth:13px;\n\tborder:0px;\n    background:url(img.gif) no-repeat -48px -16px;\n}\n\n .WdateDiv #dpQS {\n \tfloat:left;\n\tmargin-right:3px;\n\tmargin-top:3px;\n\tbackground:url(img.gif) no-repeat 0px -16px;\n\twidth:20px;\n\theight:20px;\n\tcursor:pointer;\n }\n.WdateDiv #dpControl {\n\ttext-align:right;\t\n}\n.WdateDiv .dpButton{ \n\theight:20px;\n\twidth:45px;\n\tborder:#ccc 1px solid;\n\tmargin-top:2px;\n\tmargin-right:1px;\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/My97DatePicker/4.8/skin/twoer/datepicker-dev.css",
    "content": "/* \n * My97 DatePicker 4.8 \n * auther : zhangkun , hejianting(design)\n * email : zhangkun_net@hotmail.com\n * date : 2012-05-25\n */ \n.WdateDiv\n{\n\tposition:relative;\n\tpadding:5px;\n\twidth:180px;\n\t*width:190px;\n\tfont-size:12px;\n\tcolor:#333;\n\tborder:solid 1px #DEDEDE;\n\tbackground-color:#F2F0F1;\n}\n\n.WdateDiv2\n{\n\twidth:360px;\n}\n\n.WdateDiv .NavImg a,.WdateDiv .yminput,.WdateDiv .yminputfocus,.WdateDiv #dpQS \n{\n\tbackground:url(img.gif) no-repeat;\n}\n\n.WdateDiv .NavImg a\n{\n\tfloat:left;\n\twidth:16px;\n\theight:16px;\n\tcursor:pointer;\n}\n.WdateDiv .NavImgll a\n{\n\tbackground-position:0px 5px;\n}\n.WdateDiv .NavImgl a\n{\n\tbackground-position:0px -10px;\n}\n.WdateDiv .NavImgr a\n{\n\tbackground-position:0px -25px;\n\tfloat:right;\n}\n.WdateDiv .NavImgrr a\n{\n\tbackground-position:0px -40px;\n\tfloat:right;\n}\n\n.WdateDiv #dpTitle\n{\n\tpadding:3px 0px 0px 0px;\n\tline-height:0px;\n\theight:20px;\n\t*height:23;\n}\n\n.WdateDiv .yminput,.WdateDiv .yminputfocus\n{\n\tmargin-left:3px;\n\twidth:50px;\n\theight:20px;\n\tline-height:16px;\n\tborder:solid 1px #F2F0F1;\n\tcursor:pointer;\n\tbackground-position:35px -68px;\n}\n\n.WdateDiv .yminputfocus\n{\n\tbackground-color:#fff;\n\tborder:solid 1px #D8D8D8;\n}\n\n.WdateDiv .menuSel{\n\tz-index:1;\n\tposition:absolute;\n\tbackground-color:#FFFFFF;\n\tborder:#A3C6C8 1px solid;\n\tdisplay:none;\n}\n\n.WdateDiv .menu\n{\n\tbackground:#fff;\n}\n.WdateDiv .menuOn\n{\n\tcolor:#fff;\n\tbackground:#64A3F3;\n}\n\n.WdateDiv .invalidMenu{\n\tcolor:#aaa;\n}\n\n.WdateDiv .MMenu,.WdateDiv .YMenu\n{\n\tpadding:2px;\n\tmargin-top:20px;\n\tmargin-left:-1px;\n\twidth:68px;\n\tborder:solid 1px #D9D9D9;\n}\n.WdateDiv .MMenu table,.WdateDiv .YMenu table\n{\n\twidth:100%;\n}\n.WdateDiv .MMenu table td,.WdateDiv .YMenu table td\n{\n\tpadding:0px;\n\tline-height:20px;\n\ttext-align:center;\n\tfont-size:12px;\n\tcursor: pointer;\n}\n\n.WdateDiv .Wweek {\n \ttext-align:center;\n\tbackground:#DAF3F5;\n\tborder-right:#BDEBEE 1px solid;\n }\n\n.WdateDiv td\n{\n\tpadding:1px;\n\tline-height:20px;\n\tfont-size:12px;\n\tcolor:#999999;\n\tbackground:#fff;\n\tcursor:pointer;\n}\n.WdateDiv .MTitle td\n{\n\tline-height:24px;\n\tcolor:#7D7D7D;\n\tbackground:#F2F0F1;\n\tcursor: default;\n}\n\n.WdateDiv .WdayTable2\n{\n\tborder-collapse:collapse;\n\tborder:#808080 1px solid;\n}\n.WdateDiv .WdayTable2 table\n{\n\tborder:0;\n}\n\n.WdateDiv .WdayTable{\n\tline-height:20px;\t\n\tcolor:#13777e;\n\tbackground-color:#edfbfb;\n}\n.WdateDiv .WdayTable td{\n\ttext-align:center;\n}\n\n.WdateDiv .Wday\n{\n\tcolor:#323232;\n}\n\n.WdateDiv .WdayOn\n{\n\tcolor:#fff;\n\tbackground-color:#65A2F3;\t\n}\n\n.WdateDiv .Wwday\n{\n\tcolor:#65A4F3;\n}\n\n.WdateDiv .WwdayOn\n{\n\tcolor:#fff;\n\tbackground-color:#65A2F3;\t\n}\n.WdateDiv .Wtoday\n{\n\tcolor:#FF6D10;\n\tbackground:#E0EDFE;\n}\n.WdateDiv .Wselday\n{\n\tcolor:#fff;\n\tbackground-color:#65A2F3;\t\n}\n.WdateDiv .WspecialDay{\n\tbackground-color:#66F4DF;\n}\n\n.WdateDiv .WotherDay\n{ \n\tcolor:#D4D4D4;\t\n}\n.WdateDiv .WotherDayOn\n{\n\tcolor:#fff;\n\tbackground-color:#65A2F3;\t\n}\n\n.WdateDiv .WinvalidDay{\n\tcolor:#aaa;\n}\n\n.WdateDiv #dpTime\n{\n\tposition:relative;\n\tmargin-top:5px;\n}\n\n.WdateDiv #dpTime #dpTimeStr\n{\n\tdisplay:inline-block;\n\twidth:28px;\n\t*width:30px;\n\tcolor:#7d7d7d;\n}\n\n.WdateDiv #dpTime input\n{\n\tpadding:0px;\n\tmargin:0px;\n\twidth:25px;\n\theight:20px;\n\tline-height:20px;\n\ttext-align:center;\n\tcolor:#333;\n\tborder:#D9D9D9 1px solid;\t\n}\n\n.WdateDiv #dpTime .tm\n{\n\twidth:7px;\n\tborder:none;\n\tbackground:#F2F0F1;\n}\n\n.WdateDiv #dpTime #dpTimeUp\n{\n\tdisplay:none;\n}\n\n.WdateDiv #dpTime #dpTimeDown\n{\n\tdisplay:none;\n}\n\n.WdateDiv #dpQS \n {\n \tfloat:left;\n\tmargin-right:3px;\n\tmargin-top:9px;\n\t*margin-top:6px;\n\twidth:16px;\n\theight:16px;\n\tcursor:pointer;\n\tbackground-position:0px -90px;\n }\n.WdateDiv #dpControl \n{\n\ttext-align:right;\n\tmargin-top:3px;\n}\n.WdateDiv .dpButton\n{ \n\tmargin-left:2px;\n\tline-height:18px;\n\t*line-height:16px;\n\twidth:45px;\n\tbackground-color:#C3C3C3;\n\t*background-color:#64A3F3;\n\tcolor:#fff;\n\tborder:none;\n\tcursor: pointer;\n}\n.WdateDiv .dpButton:hover\n{ \n\tbackground-color:#64A3F3;\n}\n\n.WdateDiv .hhMenu,\n.WdateDiv .mmMenu,\n.WdateDiv .ssMenu\n{\n\tposition:absolute;\n\tpadding:3px;\n\tfont-size:12px;\n\tcolor:#333;\n\tborder:solid 1px #DEDEDE;\n\tbackground-color:#F2F0F1;\n}\n\n.WdateDiv #dpTime .menu,.WdateDiv #dpTime .menuOn\n{\n\twidth:18px;\n\theight:18px;\n\tline-height:18px;\n\ttext-align:center;\n\tbackground:#fff;\n}\n.WdateDiv #dpTime .menuOn\n{\n\tbackground:#65A2F3;\n}\n\n.WdateDiv #dpTime td\n{\n\tbackground:#F2F0F1;\n}\n\n.WdateDiv .hhMenu\n{\n\ttop:-87px;\n\tleft:35px;\n\tleft:32px\\9;\n}\n\n.WdateDiv .mmMenu\n{\n\ttop:-47px;\n\tleft:35px;\n\tleft:32px\\9;\n}\n\n.WdateDiv .ssMenu\n{\n\ttop:-27px;\n\tleft:35px;\n\tleft:32px\\9;\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/My97DatePicker/4.8/skin/twoer/datepicker.css",
    "content": ".WdateDiv{position:relative;width:190px;font-size:12px;color:#333;border:solid 1px #DEDEDE;background-color:#F2F0F1;padding:5px;}.WdateDiv2{width:360px;}.WdateDiv .NavImg a,.WdateDiv .yminput,.WdateDiv .yminputfocus,.WdateDiv #dpQS{background:url(img.gif) no-repeat;}.WdateDiv .NavImg a{float:left;width:16px;height:16px;cursor:pointer;}.WdateDiv .NavImgll a{background-position:0 5px;}.WdateDiv .NavImgl a{background-position:0 -10px;}.WdateDiv .NavImgr a{background-position:0 -25px;float:right;}.WdateDiv .NavImgrr a{background-position:0 -40px;float:right;}.WdateDiv #dpTitle{line-height:0;height:23px;padding:3px 0 0;}.WdateDiv .yminput,.WdateDiv .yminputfocus{margin-left:3px;width:50px;height:20px;line-height:16px;border:solid 1px #F2F0F1;cursor:pointer;background-position:35px -68px;}.WdateDiv .yminputfocus{background-color:#fff;border:solid 1px #D8D8D8;}.WdateDiv .menuSel{z-index:1;position:absolute;background-color:#FFF;border:#A3C6C8 1px solid;display:none;}.WdateDiv .menu{background:#fff;}.WdateDiv .menuOn{color:#fff;background:#FFC600;}.WdateDiv .MMenu,.WdateDiv .YMenu{margin-top:20px;margin-left:-1px;width:68px;border:solid 1px #D9D9D9;padding:2px;}.WdateDiv .MMenu table,.WdateDiv .YMenu table{width:100%;}.WdateDiv .MMenu table td,.WdateDiv .YMenu table td{line-height:20px;text-align:center;font-size:14px;cursor:pointer;padding:0;}.WdateDiv .Wweek{text-align:center;background:#DAF3F5;border-right:#BDEBEE 1px solid;}.WdateDiv td{line-height:20px;font-size:12px;color:#999;background:#fff;cursor:pointer;padding:1px;}.WdateDiv .MTitle td{line-height:24px;color:#7D7D7D;background:#F2F0F1;cursor:default;}.WdateDiv .WdayTable2{border-collapse:collapse;border:gray 1px solid;}.WdateDiv .WdayTable2 table{border:0;}.WdateDiv .WdayTable{line-height:20px;color:#13777e;background-color:#edfbfb;}.WdateDiv .WdayTable td{text-align:center;}.WdateDiv .Wday{color:#323232;}.WdateDiv .Wwday{color:#FFC600;}.WdateDiv .Wtoday{color:#FF6D10;background:#E0EDFE;}.WdateDiv .WspecialDay{background-color:#66F4DF;}.WdateDiv .WotherDay{color:#D4D4D4;}.WdateDiv #dpTime{position:relative;margin-top:5px;}.WdateDiv #dpTime #dpTimeStr{display:inline-block;width:30px;color:#7d7d7d;}.WdateDiv #dpTime input{width:25px;height:20px;line-height:20px;text-align:center;color:#333;border:#D9D9D9 1px solid;margin:0;padding:0;}.WdateDiv #dpTime .tm{width:7px;border:none;background:#F2F0F1;}.WdateDiv #dpQS{float:left;margin-right:3px;margin-top:6px;width:16px;height:16px;cursor:pointer;background-position:0 -90px;}.WdateDiv #dpControl{text-align:right;margin-top:3px;}.WdateDiv .dpButton{margin-left:2px;line-height:16px;width:45px;background-color:#FFC600;color:#fff;border:none;cursor:pointer;}.WdateDiv .dpButton:hover{background-color:#FFC600;}.WdateDiv .hhMenu,.WdateDiv .mmMenu,.WdateDiv .ssMenu{position:absolute;font-size:12px;color:#333;border:solid 1px #DEDEDE;background-color:#F2F0F1;padding:3px;}.WdateDiv #dpTime .menu,.WdateDiv #dpTime .menuOn{width:18px;height:18px;line-height:18px;text-align:center;background:#fff;}.WdateDiv #dpTime .menuOn{background:#FFC600;}.WdateDiv #dpTime td{background:#F2F0F1;}.WdateDiv .hhMenu{top:-87px;left:32px;}.WdateDiv .mmMenu{top:-47px;left:32px;}.WdateDiv .ssMenu{top:-27px;left:32px;}.WdateDiv .invalidMenu,.WdateDiv .WinvalidDay{color:#aaa;}.WdateDiv .WdayOn,.WdateDiv .WwdayOn,.WdateDiv .Wselday,.WdateDiv .WotherDayOn{background-color:#FFC600;color:#fff;}.WdateDiv #dpTime #dpTimeUp,.WdateDiv #dpTime #dpTimeDown{display:none;}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/My97DatePicker/4.8/skin/whyGreen/datepicker.css",
    "content": "/* \n * My97 DatePicker 4.8 Skin:whyGreen\n */ \n.WdateDiv{\n\twidth:180px;\n\tbackground-color:#fff;\n\tborder:#C5E1E4 1px solid;\n\tpadding:2px;\n}\n\n.WdateDiv2{\n\twidth:360px;\n}\n.WdateDiv *{font-size:9pt;}\n\n.WdateDiv .NavImg a{\n\tcursor:pointer;\n\tdisplay:block;\n\twidth:16px;\n\theight:16px;\n\tmargin-top:1px;\n}\n\n.WdateDiv .NavImgll a{\n\tfloat:left;\n\tbackground:url(img.gif) no-repeat;\n}\n.WdateDiv .NavImgl a{\n\tfloat:left;\n\tbackground:url(img.gif) no-repeat -16px 0px;\n}\n.WdateDiv .NavImgr a{\n\tfloat:right;\n\tbackground:url(img.gif) no-repeat -32px 0px;\n}\n.WdateDiv .NavImgrr a{\n\tfloat:right;\n\tbackground:url(img.gif) no-repeat -48px 0px;\n}\n\n.WdateDiv #dpTitle{\n\theight:24px;\n\tpadding:1px;\n\tborder:#c5d9e8 1px solid;\n\tbackground:url(bg.jpg);\n\tmargin-bottom:2px;\n}\n\n.WdateDiv .yminput{\n\tmargin-top:2px;\n\ttext-align:center;\n\tborder:0px;\n\theight:20px;\n\twidth:50px;\n\tcolor:#034c50;\n\tbackground-color:transparent;\n\tcursor:pointer;\n}\n\n.WdateDiv .yminputfocus{\n\tmargin-top:2px;\n\ttext-align:center;\n\tborder:#939393 1px solid;\n\tfont-weight:bold;\n\tcolor:#034c50;\t\n\theight:20px;\n\twidth:50px;\n}\n\n.WdateDiv .menuSel{\n\tz-index:1;\n\tposition:absolute;\n\tbackground-color:#FFFFFF;\n\tborder:#A3C6C8 1px solid;\n\tdisplay:none;\n}\n\n.WdateDiv .menu{\n\tcursor:pointer;\n\tbackground-color:#fff;\n\tcolor:#11777C;\n}\n\n.WdateDiv .menuOn{\n\tcursor:pointer;\n\tbackground-color:#BEEBEE;\n}\n\n.WdateDiv .invalidMenu{\n\tcolor:#aaa;\n}\n\n.WdateDiv .YMenu{\n\tmargin-top:20px;\n}\n\n.WdateDiv .MMenu{\n\tmargin-top:20px;\n\t*width:62px;\n}\n\n.WdateDiv .hhMenu{\n\tmargin-top:-90px; \n\tmargin-left:26px;\n}\n\n.WdateDiv .mmMenu{\n\tmargin-top:-46px; \n\tmargin-left:26px;\n}\n\n.WdateDiv .ssMenu{\n\tmargin-top:-24px; \n\tmargin-left:26px;\n}\n\n .WdateDiv .Wweek {\n \ttext-align:center;\n\tbackground:#DAF3F5;\n\tborder-right:#BDEBEE 1px solid;\n }\n\n.WdateDiv .MTitle{\n\tcolor:#13777e;\n\tbackground-color:#bdebee;\n}\n.WdateDiv .WdayTable2{\n\tborder-collapse:collapse;\n\tborder:#BEE9F0 1px solid;\n}\n.WdateDiv .WdayTable2 table{\n\tborder:0;\n}\n\n.WdateDiv .WdayTable{\n\tline-height:20px;\t\n\tcolor:#13777e;\n\tbackground-color:#edfbfb;\n\tborder:#BEE9F0 1px solid;\n}\n.WdateDiv .WdayTable td{\n\ttext-align:center;\n}\n\n.WdateDiv .Wday{\n\tcursor:pointer;\n}\n\n.WdateDiv .WdayOn{\n\tcursor:pointer;\n\tbackground-color:#74d2d9 ;\n}\n\n.WdateDiv .Wwday{\n\tcursor:pointer;\n\tcolor:#ab1e1e;\n}\n\n.WdateDiv .WwdayOn{\n\tcursor:pointer;\n\tbackground-color:#74d2d9;\n}\n.WdateDiv .Wtoday{\n\tcursor:pointer;\n\tcolor:blue;\n}\n.WdateDiv .Wselday{\n\tbackground-color:#A7E2E7;\n}\n.WdateDiv .WspecialDay{\n\tbackground-color:#66F4DF;\n}\n\n.WdateDiv .WotherDay{ \n\tcursor:pointer;\n\tcolor:#0099CC;\t\n}\n\n.WdateDiv .WotherDayOn{ \n\tcursor:pointer;\n\tbackground-color:#C0EBEF;\t\n}\n\n.WdateDiv .WinvalidDay{\n\tcolor:#aaa;\n}\n\n.WdateDiv #dpTime{\n\tfloat:left;\n\tmargin-top:3px;\n\tmargin-right:30px;\n}\n\n.WdateDiv #dpTime #dpTimeStr{\n\tmargin-left:1px;\n\tcolor:#497F7F;\n}\n\n.WdateDiv #dpTime input{\n\theight:20px;\n\twidth:18px;\n\ttext-align:center;\n\tcolor:#333;\n\tborder:#61CAD0 1px solid;\t\n}\n\n.WdateDiv #dpTime .tB{\n\tborder-right:0px;\n}\n\n.WdateDiv #dpTime .tE{\n\tborder-left:0;\n\tborder-right:0;\n}\n\n.WdateDiv #dpTime .tm{\n\twidth:7px;\n\tborder-left:0;\n\tborder-right:0;\n}\n\n.WdateDiv #dpTime #dpTimeUp{\n\theight:10px;\n\twidth:13px;\n\tborder:0px;\n\tbackground:url(img.gif) no-repeat -32px -16px;\n}\n\n.WdateDiv #dpTime #dpTimeDown{\n\theight:10px;\n\twidth:13px;\n\tborder:0px;\n\tbackground:url(img.gif) no-repeat -48px -16px;\n}\n\n .WdateDiv #dpQS {\n \tfloat:left;\n\tmargin-right:3px;\n\tmargin-top:3px;\n\tbackground:url(img.gif) no-repeat 0px -16px;\n\twidth:20px;\n\theight:20px;\n\tcursor:pointer;\n }\n.WdateDiv #dpControl {\n\ttext-align:right;\n\tmargin-top:3px;\n}\n.WdateDiv .dpButton{ \n\theight:20px;\n\twidth:45px;\n\tmargin-top:2px;\n\tborder:#38B1B9 1px solid;\n\tbackground-color:#CFEBEE;\n\tcolor:#08575B;\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/busuanzi.pure.mini.js",
    "content": "var bszCaller,bszTag;!function(){var c,d,e,a=!1,b=[];ready=function(c){return a||\"interactive\"===document.readyState||\"complete\"===document.readyState?c.call(document):b.push(function(){return c.call(this)}),this},d=function(){for(var a=0,c=b.length;c>a;a++)b[a].apply(document);b=[]},e=function(){a||(a=!0,d.call(window),document.removeEventListener?document.removeEventListener(\"DOMContentLoaded\",e,!1):document.attachEvent&&(document.detachEvent(\"onreadystatechange\",e),window==window.top&&(clearInterval(c),c=null)))},document.addEventListener?document.addEventListener(\"DOMContentLoaded\",e,!1):document.attachEvent&&(document.attachEvent(\"onreadystatechange\",function(){/loaded|complete/.test(document.readyState)&&e()}),window==window.top&&(c=setInterval(function(){try{a||document.documentElement.doScroll(\"left\")}catch(b){return}e()},5)))}(),bszCaller={fetch:function(a,b){var c=\"BusuanziCallback_\"+Math.floor(1099511627776*Math.random());window[c]=this.evalCall(b),a=a.replace(\"=BusuanziCallback\",\"=\"+c),scriptTag=document.createElement(\"SCRIPT\"),scriptTag.type=\"text/javascript\",scriptTag.defer=!0,scriptTag.src=a,document.getElementsByTagName(\"HEAD\")[0].appendChild(scriptTag)},evalCall:function(a){return function(b){ready(function(){try{a(b),scriptTag.parentElement.removeChild(scriptTag)}catch(c){bszTag.hides()}})}}},bszCaller.fetch(\"//busuanzi.ibruce.info/busuanzi?jsonpCallback=BusuanziCallback\",function(a){bszTag.texts(a),bszTag.shows()}),bszTag={bszs:[\"site_pv\",\"page_pv\",\"site_uv\"],texts:function(a){this.bszs.map(function(b){var c=document.getElementById(\"busuanzi_value_\"+b);c&&(c.innerHTML=a[b])})},hides:function(){this.bszs.map(function(a){var b=document.getElementById(\"busuanzi_container_\"+a);b&&(b.style.display=\"none\")})},shows:function(){this.bszs.map(function(a){var b=document.getElementById(\"busuanzi_container_\"+a);b&&(b.style.display=\"inline\")})}};"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/changyan.js",
    "content": "(function() {\n    if (window.changyan !== undefined || window.cyan !== undefined) {\n        return;\n    }\n    var createNs = function() {\n        if (window.changyan !== undefined) {\n            return;\n        } else {\n            window.changyan = {};\n            window.changyan.api = {};\n            window.changyan.api.config = function(conf) {\n                window.changyan.api.tmpIsvPageConfig = conf;\n            };\n            window.changyan.api.ready = function(fn) {\n                window.changyan.api.tmpHandles = window.changyan.api.tmpHandles || [];\n                window.changyan.api.tmpHandles.push(fn);\n            };\n            window.changyan.ready = function(fn) {\n                if (window.changyan.rendered) {\n                    fn && fn();\n                } else {\n                    window.changyan.tmpHandles = window.changyan.tmpHandles || [];\n                    window.changyan.tmpHandles.push(fn);\n                }\n            }\n        }\n    };\n\n    var createMobileNs = function() {\n        if (window.cyan) {\n            return;\n        }\n        window.cyan = {};\n        window.cyan.api = {};\n        window.cyan.api.ready = function(fn) {\n            window.cyan.api.tmpHandles = window.cyan.api.tmpHandles || [];\n            window.cyan.api.tmpHandles.push(fn);\n        };\n    };\n    var loadVersionJs = function() {\n        var loadJs = function(src, fun) {\n            var head = document.getElementsByTagName('head')[0] || document.head || document.documentElement;\n\n            var script = document.createElement('script');\n            script.setAttribute('type', 'text/javascript');\n            script.setAttribute('charset', 'UTF-8');\n            script.setAttribute('src', src);\n\n            if (typeof fun === 'function') {\n                if (window.attachEvent) {\n                    script.onreadystatechange = function() {\n                        var r = script.readyState;\n                        if (r === 'loaded' || r === 'complete') {\n                            script.onreadystatechange = null;\n                            fun();\n                        }\n                    };\n                } else {\n                    script.onload = fun;\n                }\n            }\n\n            head.appendChild(script);\n        };\n\n        var ver = + new Date() + window.Math.random().toFixed(16);\n        var url = 'https://changyan.itc.cn/upload/version-v4.js?' + ver;\n        loadJs(url);\n    };\n    createNs();\n    createMobileNs();\n    loadVersionJs();\n}());"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/datatables/Chinese.json",
    "content": "{\n  \"sProcessing\":   \"&nbsp;&nbsp;&nbsp;处理中...\",\n  \"sLengthMenu\":   \"显示 _MENU_ 条\",\n  \"sZeroRecords\":  \"没有找到匹配的记录\",\n  \"sInfo\":         \"显示 _START_ 到 _END_ ，共 _TOTAL_ 条\",\n  \"sInfoEmpty\":    \"没有数据\",\n  \"sInfoFiltered\": \"(从 _MAX_ 条中过滤)\",\n  \"sInfoPostFix\":  \"\",\n  \"sSearch\":       \"从所有数据中检索：\",\n  \"sUrl\":          \"\",\n  \"sEmptyTable\":     \"没有数据\",\n  \"sLoadingRecords\": \"载入中...\",\n  \"sInfoThousands\":  \",\",\n  \"oPaginate\": {\n    \"sFirst\":    \"首页\",\n    \"sPrevious\": \"上一页\",\n    \"sNext\":     \"下一页\",\n    \"sLast\":     \"末页\"\n  },\n  \"oAria\": {\n    \"sSortAscending\":  \": 以升序排列此列\",\n    \"sSortDescending\": \": 以降序排列此列\"\n  }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/css/font-awesome-ie7.css",
    "content": "/*!\n *  Font Awesome 3.2.1\n *  the iconic font designed for Bootstrap\n *  ------------------------------------------------------------------------------\n *  The full suite of pictographic icons, examples, and documentation can be\n *  found at http://fontawesome.io.  Stay up to date on Twitter at\n *  http://twitter.com/fontawesome.\n *\n *  License\n *  ------------------------------------------------------------------------------\n *  - The Font Awesome font is licensed under SIL OFL 1.1 -\n *    http://scripts.sil.org/OFL\n *  - Font Awesome CSS, LESS, and SASS files are licensed under MIT License -\n *    http://opensource.org/licenses/mit-license.html\n *  - Font Awesome documentation licensed under CC BY 3.0 -\n *    http://creativecommons.org/licenses/by/3.0/\n *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:\n *    \"Font Awesome by Dave Gandy - http://fontawesome.io\"\n *\n *  Author - Dave Gandy\n *  ------------------------------------------------------------------------------\n *  Email: dave@fontawesome.io\n *  Twitter: http://twitter.com/davegandy\n *  Work: Lead Product Designer @ Kyruus - http://kyruus.com\n */\n.icon-large {\n  font-size: 1.3333333333333333em;\n  margin-top: -4px;\n  padding-top: 3px;\n  margin-bottom: -4px;\n  padding-bottom: 3px;\n  vertical-align: middle;\n}\n.nav [class^=\"icon-\"],\n.nav [class*=\" icon-\"] {\n  vertical-align: inherit;\n  margin-top: -4px;\n  padding-top: 3px;\n  margin-bottom: -4px;\n  padding-bottom: 3px;\n}\n.nav [class^=\"icon-\"].icon-large,\n.nav [class*=\" icon-\"].icon-large {\n  vertical-align: -25%;\n}\n.nav-pills [class^=\"icon-\"].icon-large,\n.nav-tabs [class^=\"icon-\"].icon-large,\n.nav-pills [class*=\" icon-\"].icon-large,\n.nav-tabs [class*=\" icon-\"].icon-large {\n  line-height: .75em;\n  margin-top: -7px;\n  padding-top: 5px;\n  margin-bottom: -5px;\n  padding-bottom: 4px;\n}\n.btn [class^=\"icon-\"].pull-left,\n.btn [class*=\" icon-\"].pull-left,\n.btn [class^=\"icon-\"].pull-right,\n.btn [class*=\" icon-\"].pull-right {\n  vertical-align: inherit;\n}\n.btn [class^=\"icon-\"].icon-large,\n.btn [class*=\" icon-\"].icon-large {\n  margin-top: -0.5em;\n}\na [class^=\"icon-\"],\na [class*=\" icon-\"] {\n  cursor: pointer;\n}\n.icon-glass {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf000;');\n}\n.icon-music {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf001;');\n}\n.icon-search {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf002;');\n}\n.icon-envelope-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf003;');\n}\n.icon-heart {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf004;');\n}\n.icon-star {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf005;');\n}\n.icon-star-empty {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf006;');\n}\n.icon-user {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf007;');\n}\n.icon-film {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf008;');\n}\n.icon-th-large {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf009;');\n}\n.icon-th {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf00a;');\n}\n.icon-th-list {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf00b;');\n}\n.icon-ok {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf00c;');\n}\n.icon-remove {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf00d;');\n}\n.icon-zoom-in {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf00e;');\n}\n.icon-zoom-out {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf010;');\n}\n.icon-off {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf011;');\n}\n.icon-power-off {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf011;');\n}\n.icon-signal {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf012;');\n}\n.icon-cog {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf013;');\n}\n.icon-gear {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf013;');\n}\n.icon-trash {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf014;');\n}\n.icon-home {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf015;');\n}\n.icon-file-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf016;');\n}\n.icon-time {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf017;');\n}\n.icon-road {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf018;');\n}\n.icon-download-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf019;');\n}\n.icon-download {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01a;');\n}\n.icon-upload {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01b;');\n}\n.icon-inbox {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01c;');\n}\n.icon-play-circle {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01d;');\n}\n.icon-repeat {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01e;');\n}\n.icon-rotate-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf01e;');\n}\n.icon-refresh {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf021;');\n}\n.icon-list-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf022;');\n}\n.icon-lock {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf023;');\n}\n.icon-flag {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf024;');\n}\n.icon-headphones {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf025;');\n}\n.icon-volume-off {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf026;');\n}\n.icon-volume-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf027;');\n}\n.icon-volume-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf028;');\n}\n.icon-qrcode {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf029;');\n}\n.icon-barcode {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02a;');\n}\n.icon-tag {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02b;');\n}\n.icon-tags {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02c;');\n}\n.icon-book {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02d;');\n}\n.icon-bookmark {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02e;');\n}\n.icon-print {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf02f;');\n}\n.icon-camera {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf030;');\n}\n.icon-font {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf031;');\n}\n.icon-bold {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf032;');\n}\n.icon-italic {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf033;');\n}\n.icon-text-height {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf034;');\n}\n.icon-text-width {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf035;');\n}\n.icon-align-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf036;');\n}\n.icon-align-center {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf037;');\n}\n.icon-align-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf038;');\n}\n.icon-align-justify {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf039;');\n}\n.icon-list {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf03a;');\n}\n.icon-indent-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf03b;');\n}\n.icon-indent-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf03c;');\n}\n.icon-facetime-video {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf03d;');\n}\n.icon-picture {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf03e;');\n}\n.icon-pencil {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf040;');\n}\n.icon-map-marker {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf041;');\n}\n.icon-adjust {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf042;');\n}\n.icon-tint {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf043;');\n}\n.icon-edit {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf044;');\n}\n.icon-share {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf045;');\n}\n.icon-check {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf046;');\n}\n.icon-move {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf047;');\n}\n.icon-step-backward {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf048;');\n}\n.icon-fast-backward {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf049;');\n}\n.icon-backward {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf04a;');\n}\n.icon-play {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf04b;');\n}\n.icon-pause {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf04c;');\n}\n.icon-stop {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf04d;');\n}\n.icon-forward {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf04e;');\n}\n.icon-fast-forward {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf050;');\n}\n.icon-step-forward {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf051;');\n}\n.icon-eject {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf052;');\n}\n.icon-chevron-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf053;');\n}\n.icon-chevron-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf054;');\n}\n.icon-plus-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf055;');\n}\n.icon-minus-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf056;');\n}\n.icon-remove-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf057;');\n}\n.icon-ok-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf058;');\n}\n.icon-question-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf059;');\n}\n.icon-info-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf05a;');\n}\n.icon-screenshot {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf05b;');\n}\n.icon-remove-circle {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf05c;');\n}\n.icon-ok-circle {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf05d;');\n}\n.icon-ban-circle {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf05e;');\n}\n.icon-arrow-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf060;');\n}\n.icon-arrow-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf061;');\n}\n.icon-arrow-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf062;');\n}\n.icon-arrow-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf063;');\n}\n.icon-share-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf064;');\n}\n.icon-mail-forward {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf064;');\n}\n.icon-resize-full {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf065;');\n}\n.icon-resize-small {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf066;');\n}\n.icon-plus {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf067;');\n}\n.icon-minus {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf068;');\n}\n.icon-asterisk {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf069;');\n}\n.icon-exclamation-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf06a;');\n}\n.icon-gift {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf06b;');\n}\n.icon-leaf {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf06c;');\n}\n.icon-fire {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf06d;');\n}\n.icon-eye-open {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf06e;');\n}\n.icon-eye-close {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf070;');\n}\n.icon-warning-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf071;');\n}\n.icon-plane {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf072;');\n}\n.icon-calendar {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf073;');\n}\n.icon-random {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf074;');\n}\n.icon-comment {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf075;');\n}\n.icon-magnet {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf076;');\n}\n.icon-chevron-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf077;');\n}\n.icon-chevron-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf078;');\n}\n.icon-retweet {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf079;');\n}\n.icon-shopping-cart {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf07a;');\n}\n.icon-folder-close {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf07b;');\n}\n.icon-folder-open {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf07c;');\n}\n.icon-resize-vertical {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf07d;');\n}\n.icon-resize-horizontal {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf07e;');\n}\n.icon-bar-chart {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf080;');\n}\n.icon-twitter-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf081;');\n}\n.icon-facebook-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf082;');\n}\n.icon-camera-retro {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf083;');\n}\n.icon-key {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf084;');\n}\n.icon-cogs {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf085;');\n}\n.icon-gears {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf085;');\n}\n.icon-comments {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf086;');\n}\n.icon-thumbs-up-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf087;');\n}\n.icon-thumbs-down-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf088;');\n}\n.icon-star-half {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf089;');\n}\n.icon-heart-empty {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08a;');\n}\n.icon-signout {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08b;');\n}\n.icon-linkedin-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08c;');\n}\n.icon-pushpin {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08d;');\n}\n.icon-external-link {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf08e;');\n}\n.icon-signin {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf090;');\n}\n.icon-trophy {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf091;');\n}\n.icon-github-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf092;');\n}\n.icon-upload-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf093;');\n}\n.icon-lemon {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf094;');\n}\n.icon-phone {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf095;');\n}\n.icon-check-empty {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf096;');\n}\n.icon-unchecked {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf096;');\n}\n.icon-bookmark-empty {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf097;');\n}\n.icon-phone-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf098;');\n}\n.icon-twitter {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf099;');\n}\n.icon-facebook {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09a;');\n}\n.icon-github {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09b;');\n}\n.icon-unlock {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09c;');\n}\n.icon-credit-card {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09d;');\n}\n.icon-rss {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf09e;');\n}\n.icon-hdd {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a0;');\n}\n.icon-bullhorn {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a1;');\n}\n.icon-bell {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a2;');\n}\n.icon-certificate {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a3;');\n}\n.icon-hand-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a4;');\n}\n.icon-hand-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a5;');\n}\n.icon-hand-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a6;');\n}\n.icon-hand-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a7;');\n}\n.icon-circle-arrow-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a8;');\n}\n.icon-circle-arrow-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0a9;');\n}\n.icon-circle-arrow-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0aa;');\n}\n.icon-circle-arrow-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ab;');\n}\n.icon-globe {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ac;');\n}\n.icon-wrench {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ad;');\n}\n.icon-tasks {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ae;');\n}\n.icon-filter {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0b0;');\n}\n.icon-briefcase {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0b1;');\n}\n.icon-fullscreen {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0b2;');\n}\n.icon-group {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c0;');\n}\n.icon-link {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c1;');\n}\n.icon-cloud {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c2;');\n}\n.icon-beaker {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c3;');\n}\n.icon-cut {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c4;');\n}\n.icon-copy {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c5;');\n}\n.icon-paper-clip {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c6;');\n}\n.icon-paperclip {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c6;');\n}\n.icon-save {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c7;');\n}\n.icon-sign-blank {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c8;');\n}\n.icon-reorder {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0c9;');\n}\n.icon-list-ul {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ca;');\n}\n.icon-list-ol {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0cb;');\n}\n.icon-strikethrough {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0cc;');\n}\n.icon-underline {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0cd;');\n}\n.icon-table {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ce;');\n}\n.icon-magic {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d0;');\n}\n.icon-truck {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d1;');\n}\n.icon-pinterest {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d2;');\n}\n.icon-pinterest-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d3;');\n}\n.icon-google-plus-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d4;');\n}\n.icon-google-plus {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d5;');\n}\n.icon-money {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d6;');\n}\n.icon-caret-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d7;');\n}\n.icon-caret-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d8;');\n}\n.icon-caret-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0d9;');\n}\n.icon-caret-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0da;');\n}\n.icon-columns {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0db;');\n}\n.icon-sort {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0dc;');\n}\n.icon-sort-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0dd;');\n}\n.icon-sort-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0de;');\n}\n.icon-envelope {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e0;');\n}\n.icon-linkedin {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e1;');\n}\n.icon-undo {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e2;');\n}\n.icon-rotate-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e2;');\n}\n.icon-legal {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e3;');\n}\n.icon-dashboard {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e4;');\n}\n.icon-comment-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e5;');\n}\n.icon-comments-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e6;');\n}\n.icon-bolt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e7;');\n}\n.icon-sitemap {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e8;');\n}\n.icon-umbrella {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0e9;');\n}\n.icon-paste {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ea;');\n}\n.icon-lightbulb {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0eb;');\n}\n.icon-exchange {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ec;');\n}\n.icon-cloud-download {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ed;');\n}\n.icon-cloud-upload {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0ee;');\n}\n.icon-user-md {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f0;');\n}\n.icon-stethoscope {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f1;');\n}\n.icon-suitcase {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f2;');\n}\n.icon-bell-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f3;');\n}\n.icon-coffee {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f4;');\n}\n.icon-food {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f5;');\n}\n.icon-file-text-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f6;');\n}\n.icon-building {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f7;');\n}\n.icon-hospital {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f8;');\n}\n.icon-ambulance {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0f9;');\n}\n.icon-medkit {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0fa;');\n}\n.icon-fighter-jet {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0fb;');\n}\n.icon-beer {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0fc;');\n}\n.icon-h-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0fd;');\n}\n.icon-plus-sign-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf0fe;');\n}\n.icon-double-angle-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf100;');\n}\n.icon-double-angle-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf101;');\n}\n.icon-double-angle-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf102;');\n}\n.icon-double-angle-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf103;');\n}\n.icon-angle-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf104;');\n}\n.icon-angle-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf105;');\n}\n.icon-angle-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf106;');\n}\n.icon-angle-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf107;');\n}\n.icon-desktop {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf108;');\n}\n.icon-laptop {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf109;');\n}\n.icon-tablet {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf10a;');\n}\n.icon-mobile-phone {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf10b;');\n}\n.icon-circle-blank {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf10c;');\n}\n.icon-quote-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf10d;');\n}\n.icon-quote-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf10e;');\n}\n.icon-spinner {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf110;');\n}\n.icon-circle {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf111;');\n}\n.icon-reply {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf112;');\n}\n.icon-mail-reply {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf112;');\n}\n.icon-github-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf113;');\n}\n.icon-folder-close-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf114;');\n}\n.icon-folder-open-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf115;');\n}\n.icon-expand-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf116;');\n}\n.icon-collapse-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf117;');\n}\n.icon-smile {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf118;');\n}\n.icon-frown {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf119;');\n}\n.icon-meh {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf11a;');\n}\n.icon-gamepad {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf11b;');\n}\n.icon-keyboard {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf11c;');\n}\n.icon-flag-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf11d;');\n}\n.icon-flag-checkered {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf11e;');\n}\n.icon-terminal {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf120;');\n}\n.icon-code {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf121;');\n}\n.icon-reply-all {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf122;');\n}\n.icon-mail-reply-all {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf122;');\n}\n.icon-star-half-empty {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf123;');\n}\n.icon-star-half-full {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf123;');\n}\n.icon-location-arrow {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf124;');\n}\n.icon-crop {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf125;');\n}\n.icon-code-fork {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf126;');\n}\n.icon-unlink {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf127;');\n}\n.icon-question {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf128;');\n}\n.icon-info {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf129;');\n}\n.icon-exclamation {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf12a;');\n}\n.icon-superscript {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf12b;');\n}\n.icon-subscript {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf12c;');\n}\n.icon-eraser {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf12d;');\n}\n.icon-puzzle-piece {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf12e;');\n}\n.icon-microphone {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf130;');\n}\n.icon-microphone-off {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf131;');\n}\n.icon-shield {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf132;');\n}\n.icon-calendar-empty {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf133;');\n}\n.icon-fire-extinguisher {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf134;');\n}\n.icon-rocket {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf135;');\n}\n.icon-maxcdn {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf136;');\n}\n.icon-chevron-sign-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf137;');\n}\n.icon-chevron-sign-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf138;');\n}\n.icon-chevron-sign-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf139;');\n}\n.icon-chevron-sign-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf13a;');\n}\n.icon-html5 {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf13b;');\n}\n.icon-css3 {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf13c;');\n}\n.icon-anchor {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf13d;');\n}\n.icon-unlock-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf13e;');\n}\n.icon-bullseye {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf140;');\n}\n.icon-ellipsis-horizontal {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf141;');\n}\n.icon-ellipsis-vertical {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf142;');\n}\n.icon-rss-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf143;');\n}\n.icon-play-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf144;');\n}\n.icon-ticket {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf145;');\n}\n.icon-minus-sign-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf146;');\n}\n.icon-check-minus {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf147;');\n}\n.icon-level-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf148;');\n}\n.icon-level-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf149;');\n}\n.icon-check-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf14a;');\n}\n.icon-edit-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf14b;');\n}\n.icon-external-link-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf14c;');\n}\n.icon-share-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf14d;');\n}\n.icon-compass {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf14e;');\n}\n.icon-collapse {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf150;');\n}\n.icon-collapse-top {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf151;');\n}\n.icon-expand {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf152;');\n}\n.icon-eur {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf153;');\n}\n.icon-euro {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf153;');\n}\n.icon-gbp {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf154;');\n}\n.icon-usd {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf155;');\n}\n.icon-dollar {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf155;');\n}\n.icon-inr {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf156;');\n}\n.icon-rupee {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf156;');\n}\n.icon-jpy {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf157;');\n}\n.icon-yen {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf157;');\n}\n.icon-cny {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf158;');\n}\n.icon-renminbi {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf158;');\n}\n.icon-krw {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf159;');\n}\n.icon-won {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf159;');\n}\n.icon-btc {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15a;');\n}\n.icon-bitcoin {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15a;');\n}\n.icon-file {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15b;');\n}\n.icon-file-text {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15c;');\n}\n.icon-sort-by-alphabet {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15d;');\n}\n.icon-sort-by-alphabet-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf15e;');\n}\n.icon-sort-by-attributes {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf160;');\n}\n.icon-sort-by-attributes-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf161;');\n}\n.icon-sort-by-order {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf162;');\n}\n.icon-sort-by-order-alt {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf163;');\n}\n.icon-thumbs-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf164;');\n}\n.icon-thumbs-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf165;');\n}\n.icon-youtube-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf166;');\n}\n.icon-youtube {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf167;');\n}\n.icon-xing {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf168;');\n}\n.icon-xing-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf169;');\n}\n.icon-youtube-play {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf16a;');\n}\n.icon-dropbox {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf16b;');\n}\n.icon-stackexchange {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf16c;');\n}\n.icon-instagram {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf16d;');\n}\n.icon-flickr {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf16e;');\n}\n.icon-adn {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf170;');\n}\n.icon-bitbucket {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf171;');\n}\n.icon-bitbucket-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf172;');\n}\n.icon-tumblr {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf173;');\n}\n.icon-tumblr-sign {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf174;');\n}\n.icon-long-arrow-down {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf175;');\n}\n.icon-long-arrow-up {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf176;');\n}\n.icon-long-arrow-left {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf177;');\n}\n.icon-long-arrow-right {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf178;');\n}\n.icon-apple {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf179;');\n}\n.icon-windows {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf17a;');\n}\n.icon-android {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf17b;');\n}\n.icon-linux {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf17c;');\n}\n.icon-dribbble {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf17d;');\n}\n.icon-skype {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf17e;');\n}\n.icon-foursquare {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf180;');\n}\n.icon-trello {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf181;');\n}\n.icon-female {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf182;');\n}\n.icon-male {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf183;');\n}\n.icon-gittip {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf184;');\n}\n.icon-sun {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf185;');\n}\n.icon-moon {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf186;');\n}\n.icon-archive {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf187;');\n}\n.icon-bug {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf188;');\n}\n.icon-vk {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf189;');\n}\n.icon-weibo {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf18a;');\n}\n.icon-renren {\n  *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xf18b;');\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/css/font-awesome.css",
    "content": "/*!\n *  Font Awesome 3.2.1\n *  the iconic font designed for Bootstrap\n *  ------------------------------------------------------------------------------\n *  The full suite of pictographic icons, examples, and documentation can be\n *  found at http://fontawesome.io.  Stay up to date on Twitter at\n *  http://twitter.com/fontawesome.\n *\n *  License\n *  ------------------------------------------------------------------------------\n *  - The Font Awesome font is licensed under SIL OFL 1.1 -\n *    http://scripts.sil.org/OFL\n *  - Font Awesome CSS, LESS, and SASS files are licensed under MIT License -\n *    http://opensource.org/licenses/mit-license.html\n *  - Font Awesome documentation licensed under CC BY 3.0 -\n *    http://creativecommons.org/licenses/by/3.0/\n *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:\n *    \"Font Awesome by Dave Gandy - http://fontawesome.io\"\n *\n *  Author - Dave Gandy\n *  ------------------------------------------------------------------------------\n *  Email: dave@fontawesome.io\n *  Twitter: http://twitter.com/davegandy\n *  Work: Lead Product Designer @ Kyruus - http://kyruus.com\n */\n/* FONT PATH\n * -------------------------- */\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('../font/fontawesome-webfont.eot?v=3.2.1');\n  src: url('../font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'), url('../font/fontawesome-webfont.woff?v=3.2.1') format('woff'), url('../font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'), url('../font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n/* FONT AWESOME CORE\n * -------------------------- */\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  font-family: FontAwesome;\n  font-weight: normal;\n  font-style: normal;\n  text-decoration: inherit;\n  -webkit-font-smoothing: antialiased;\n  *margin-right: .3em;\n}\n[class^=\"icon-\"]:before,\n[class*=\" icon-\"]:before {\n  text-decoration: inherit;\n  display: inline-block;\n  speak: none;\n}\n/* makes the font 33% larger relative to the icon container */\n.icon-large:before {\n  vertical-align: -10%;\n  font-size: 1.3333333333333333em;\n}\n/* makes sure icons active on rollover in links */\na [class^=\"icon-\"],\na [class*=\" icon-\"] {\n  display: inline;\n}\n/* increased font size for icon-large */\n[class^=\"icon-\"].icon-fixed-width,\n[class*=\" icon-\"].icon-fixed-width {\n  display: inline-block;\n  width: 1.1428571428571428em;\n  text-align: right;\n  padding-right: 0.2857142857142857em;\n}\n[class^=\"icon-\"].icon-fixed-width.icon-large,\n[class*=\" icon-\"].icon-fixed-width.icon-large {\n  width: 1.4285714285714286em;\n}\n.icons-ul {\n  margin-left: 2.142857142857143em;\n  list-style-type: none;\n}\n.icons-ul > li {\n  position: relative;\n}\n.icons-ul .icon-li {\n  position: absolute;\n  left: -2.142857142857143em;\n  width: 2.142857142857143em;\n  text-align: center;\n  line-height: inherit;\n}\n[class^=\"icon-\"].hide,\n[class*=\" icon-\"].hide {\n  display: none;\n}\n.icon-muted {\n  color: #eeeeee;\n}\n.icon-light {\n  color: #ffffff;\n}\n.icon-dark {\n  color: #333333;\n}\n.icon-border {\n  border: solid 1px #eeeeee;\n  padding: .2em .25em .15em;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n}\n.icon-2x {\n  font-size: 2em;\n}\n.icon-2x.icon-border {\n  border-width: 2px;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.icon-3x {\n  font-size: 3em;\n}\n.icon-3x.icon-border {\n  border-width: 3px;\n  -webkit-border-radius: 5px;\n  -moz-border-radius: 5px;\n  border-radius: 5px;\n}\n.icon-4x {\n  font-size: 4em;\n}\n.icon-4x.icon-border {\n  border-width: 4px;\n  -webkit-border-radius: 6px;\n  -moz-border-radius: 6px;\n  border-radius: 6px;\n}\n.icon-5x {\n  font-size: 5em;\n}\n.icon-5x.icon-border {\n  border-width: 5px;\n  -webkit-border-radius: 7px;\n  -moz-border-radius: 7px;\n  border-radius: 7px;\n}\n.pull-right {\n  float: right;\n}\n.pull-left {\n  float: left;\n}\n[class^=\"icon-\"].pull-left,\n[class*=\" icon-\"].pull-left {\n  margin-right: .3em;\n}\n[class^=\"icon-\"].pull-right,\n[class*=\" icon-\"].pull-right {\n  margin-left: .3em;\n}\n/* BOOTSTRAP SPECIFIC CLASSES\n * -------------------------- */\n/* Bootstrap 2.0 sprites.less reset */\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline;\n  width: auto;\n  height: auto;\n  line-height: normal;\n  vertical-align: baseline;\n  background-image: none;\n  background-position: 0% 0%;\n  background-repeat: repeat;\n  margin-top: 0;\n}\n/* more sprites.less reset */\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: none;\n}\n/* keeps Bootstrap styles with and without icons the same */\n.btn [class^=\"icon-\"].icon-large,\n.nav [class^=\"icon-\"].icon-large,\n.btn [class*=\" icon-\"].icon-large,\n.nav [class*=\" icon-\"].icon-large {\n  line-height: .9em;\n}\n.btn [class^=\"icon-\"].icon-spin,\n.nav [class^=\"icon-\"].icon-spin,\n.btn [class*=\" icon-\"].icon-spin,\n.nav [class*=\" icon-\"].icon-spin {\n  display: inline-block;\n}\n.nav-tabs [class^=\"icon-\"],\n.nav-pills [class^=\"icon-\"],\n.nav-tabs [class*=\" icon-\"],\n.nav-pills [class*=\" icon-\"],\n.nav-tabs [class^=\"icon-\"].icon-large,\n.nav-pills [class^=\"icon-\"].icon-large,\n.nav-tabs [class*=\" icon-\"].icon-large,\n.nav-pills [class*=\" icon-\"].icon-large {\n  line-height: .9em;\n}\n.btn [class^=\"icon-\"].pull-left.icon-2x,\n.btn [class*=\" icon-\"].pull-left.icon-2x,\n.btn [class^=\"icon-\"].pull-right.icon-2x,\n.btn [class*=\" icon-\"].pull-right.icon-2x {\n  margin-top: .18em;\n}\n.btn [class^=\"icon-\"].icon-spin.icon-large,\n.btn [class*=\" icon-\"].icon-spin.icon-large {\n  line-height: .8em;\n}\n.btn.btn-small [class^=\"icon-\"].pull-left.icon-2x,\n.btn.btn-small [class*=\" icon-\"].pull-left.icon-2x,\n.btn.btn-small [class^=\"icon-\"].pull-right.icon-2x,\n.btn.btn-small [class*=\" icon-\"].pull-right.icon-2x {\n  margin-top: .25em;\n}\n.btn.btn-large [class^=\"icon-\"],\n.btn.btn-large [class*=\" icon-\"] {\n  margin-top: 0;\n}\n.btn.btn-large [class^=\"icon-\"].pull-left.icon-2x,\n.btn.btn-large [class*=\" icon-\"].pull-left.icon-2x,\n.btn.btn-large [class^=\"icon-\"].pull-right.icon-2x,\n.btn.btn-large [class*=\" icon-\"].pull-right.icon-2x {\n  margin-top: .05em;\n}\n.btn.btn-large [class^=\"icon-\"].pull-left.icon-2x,\n.btn.btn-large [class*=\" icon-\"].pull-left.icon-2x {\n  margin-right: .2em;\n}\n.btn.btn-large [class^=\"icon-\"].pull-right.icon-2x,\n.btn.btn-large [class*=\" icon-\"].pull-right.icon-2x {\n  margin-left: .2em;\n}\n/* Fixes alignment in nav lists */\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  line-height: inherit;\n}\n/* EXTRAS\n * -------------------------- */\n/* Stacked and layered icon */\n.icon-stack {\n  position: relative;\n  display: inline-block;\n  width: 2em;\n  height: 2em;\n  line-height: 2em;\n  vertical-align: -35%;\n}\n.icon-stack [class^=\"icon-\"],\n.icon-stack [class*=\" icon-\"] {\n  display: block;\n  text-align: center;\n  position: absolute;\n  width: 100%;\n  height: 100%;\n  font-size: 1em;\n  line-height: inherit;\n  *line-height: 2em;\n}\n.icon-stack .icon-stack-base {\n  font-size: 2em;\n  *line-height: 1em;\n}\n/* Animated rotating icon */\n.icon-spin {\n  display: inline-block;\n  -moz-animation: spin 2s infinite linear;\n  -o-animation: spin 2s infinite linear;\n  -webkit-animation: spin 2s infinite linear;\n  animation: spin 2s infinite linear;\n}\n/* Prevent stack and spinners from being taken inline when inside a link */\na .icon-stack,\na .icon-spin {\n  display: inline-block;\n  text-decoration: none;\n}\n@-moz-keyframes spin {\n  0% {\n    -moz-transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n  }\n}\n@-webkit-keyframes spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n  }\n}\n@-o-keyframes spin {\n  0% {\n    -o-transform: rotate(0deg);\n  }\n  100% {\n    -o-transform: rotate(359deg);\n  }\n}\n@-ms-keyframes spin {\n  0% {\n    -ms-transform: rotate(0deg);\n  }\n  100% {\n    -ms-transform: rotate(359deg);\n  }\n}\n@keyframes spin {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(359deg);\n  }\n}\n/* Icon rotations and mirroring */\n.icon-rotate-90:before {\n  -webkit-transform: rotate(90deg);\n  -moz-transform: rotate(90deg);\n  -ms-transform: rotate(90deg);\n  -o-transform: rotate(90deg);\n  transform: rotate(90deg);\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);\n}\n.icon-rotate-180:before {\n  -webkit-transform: rotate(180deg);\n  -moz-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  -o-transform: rotate(180deg);\n  transform: rotate(180deg);\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);\n}\n.icon-rotate-270:before {\n  -webkit-transform: rotate(270deg);\n  -moz-transform: rotate(270deg);\n  -ms-transform: rotate(270deg);\n  -o-transform: rotate(270deg);\n  transform: rotate(270deg);\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);\n}\n.icon-flip-horizontal:before {\n  -webkit-transform: scale(-1, 1);\n  -moz-transform: scale(-1, 1);\n  -ms-transform: scale(-1, 1);\n  -o-transform: scale(-1, 1);\n  transform: scale(-1, 1);\n}\n.icon-flip-vertical:before {\n  -webkit-transform: scale(1, -1);\n  -moz-transform: scale(1, -1);\n  -ms-transform: scale(1, -1);\n  -o-transform: scale(1, -1);\n  transform: scale(1, -1);\n}\n/* ensure rotation occurs inside anchor tags */\na .icon-rotate-90:before,\na .icon-rotate-180:before,\na .icon-rotate-270:before,\na .icon-flip-horizontal:before,\na .icon-flip-vertical:before {\n  display: inline-block;\n}\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n   readers do not read off random characters that represent icons */\n.icon-glass:before {\n  content: \"\\f000\";\n}\n.icon-music:before {\n  content: \"\\f001\";\n}\n.icon-search:before {\n  content: \"\\f002\";\n}\n.icon-envelope-alt:before {\n  content: \"\\f003\";\n}\n.icon-heart:before {\n  content: \"\\f004\";\n}\n.icon-star:before {\n  content: \"\\f005\";\n}\n.icon-star-empty:before {\n  content: \"\\f006\";\n}\n.icon-user:before {\n  content: \"\\f007\";\n}\n.icon-film:before {\n  content: \"\\f008\";\n}\n.icon-th-large:before {\n  content: \"\\f009\";\n}\n.icon-th:before {\n  content: \"\\f00a\";\n}\n.icon-th-list:before {\n  content: \"\\f00b\";\n}\n.icon-ok:before {\n  content: \"\\f00c\";\n}\n.icon-remove:before {\n  content: \"\\f00d\";\n}\n.icon-zoom-in:before {\n  content: \"\\f00e\";\n}\n.icon-zoom-out:before {\n  content: \"\\f010\";\n}\n.icon-power-off:before,\n.icon-off:before {\n  content: \"\\f011\";\n}\n.icon-signal:before {\n  content: \"\\f012\";\n}\n.icon-gear:before,\n.icon-cog:before {\n  content: \"\\f013\";\n}\n.icon-trash:before {\n  content: \"\\f014\";\n}\n.icon-home:before {\n  content: \"\\f015\";\n}\n.icon-file-alt:before {\n  content: \"\\f016\";\n}\n.icon-time:before {\n  content: \"\\f017\";\n}\n.icon-road:before {\n  content: \"\\f018\";\n}\n.icon-download-alt:before {\n  content: \"\\f019\";\n}\n.icon-download:before {\n  content: \"\\f01a\";\n}\n.icon-upload:before {\n  content: \"\\f01b\";\n}\n.icon-inbox:before {\n  content: \"\\f01c\";\n}\n.icon-play-circle:before {\n  content: \"\\f01d\";\n}\n.icon-rotate-right:before,\n.icon-repeat:before {\n  content: \"\\f01e\";\n}\n.icon-refresh:before {\n  content: \"\\f021\";\n}\n.icon-list-alt:before {\n  content: \"\\f022\";\n}\n.icon-lock:before {\n  content: \"\\f023\";\n}\n.icon-flag:before {\n  content: \"\\f024\";\n}\n.icon-headphones:before {\n  content: \"\\f025\";\n}\n.icon-volume-off:before {\n  content: \"\\f026\";\n}\n.icon-volume-down:before {\n  content: \"\\f027\";\n}\n.icon-volume-up:before {\n  content: \"\\f028\";\n}\n.icon-qrcode:before {\n  content: \"\\f029\";\n}\n.icon-barcode:before {\n  content: \"\\f02a\";\n}\n.icon-tag:before {\n  content: \"\\f02b\";\n}\n.icon-tags:before {\n  content: \"\\f02c\";\n}\n.icon-book:before {\n  content: \"\\f02d\";\n}\n.icon-bookmark:before {\n  content: \"\\f02e\";\n}\n.icon-print:before {\n  content: \"\\f02f\";\n}\n.icon-camera:before {\n  content: \"\\f030\";\n}\n.icon-font:before {\n  content: \"\\f031\";\n}\n.icon-bold:before {\n  content: \"\\f032\";\n}\n.icon-italic:before {\n  content: \"\\f033\";\n}\n.icon-text-height:before {\n  content: \"\\f034\";\n}\n.icon-text-width:before {\n  content: \"\\f035\";\n}\n.icon-align-left:before {\n  content: \"\\f036\";\n}\n.icon-align-center:before {\n  content: \"\\f037\";\n}\n.icon-align-right:before {\n  content: \"\\f038\";\n}\n.icon-align-justify:before {\n  content: \"\\f039\";\n}\n.icon-list:before {\n  content: \"\\f03a\";\n}\n.icon-indent-left:before {\n  content: \"\\f03b\";\n}\n.icon-indent-right:before {\n  content: \"\\f03c\";\n}\n.icon-facetime-video:before {\n  content: \"\\f03d\";\n}\n.icon-picture:before {\n  content: \"\\f03e\";\n}\n.icon-pencil:before {\n  content: \"\\f040\";\n}\n.icon-map-marker:before {\n  content: \"\\f041\";\n}\n.icon-adjust:before {\n  content: \"\\f042\";\n}\n.icon-tint:before {\n  content: \"\\f043\";\n}\n.icon-edit:before {\n  content: \"\\f044\";\n}\n.icon-share:before {\n  content: \"\\f045\";\n}\n.icon-check:before {\n  content: \"\\f046\";\n}\n.icon-move:before {\n  content: \"\\f047\";\n}\n.icon-step-backward:before {\n  content: \"\\f048\";\n}\n.icon-fast-backward:before {\n  content: \"\\f049\";\n}\n.icon-backward:before {\n  content: \"\\f04a\";\n}\n.icon-play:before {\n  content: \"\\f04b\";\n}\n.icon-pause:before {\n  content: \"\\f04c\";\n}\n.icon-stop:before {\n  content: \"\\f04d\";\n}\n.icon-forward:before {\n  content: \"\\f04e\";\n}\n.icon-fast-forward:before {\n  content: \"\\f050\";\n}\n.icon-step-forward:before {\n  content: \"\\f051\";\n}\n.icon-eject:before {\n  content: \"\\f052\";\n}\n.icon-chevron-left:before {\n  content: \"\\f053\";\n}\n.icon-chevron-right:before {\n  content: \"\\f054\";\n}\n.icon-plus-sign:before {\n  content: \"\\f055\";\n}\n.icon-minus-sign:before {\n  content: \"\\f056\";\n}\n.icon-remove-sign:before {\n  content: \"\\f057\";\n}\n.icon-ok-sign:before {\n  content: \"\\f058\";\n}\n.icon-question-sign:before {\n  content: \"\\f059\";\n}\n.icon-info-sign:before {\n  content: \"\\f05a\";\n}\n.icon-screenshot:before {\n  content: \"\\f05b\";\n}\n.icon-remove-circle:before {\n  content: \"\\f05c\";\n}\n.icon-ok-circle:before {\n  content: \"\\f05d\";\n}\n.icon-ban-circle:before {\n  content: \"\\f05e\";\n}\n.icon-arrow-left:before {\n  content: \"\\f060\";\n}\n.icon-arrow-right:before {\n  content: \"\\f061\";\n}\n.icon-arrow-up:before {\n  content: \"\\f062\";\n}\n.icon-arrow-down:before {\n  content: \"\\f063\";\n}\n.icon-mail-forward:before,\n.icon-share-alt:before {\n  content: \"\\f064\";\n}\n.icon-resize-full:before {\n  content: \"\\f065\";\n}\n.icon-resize-small:before {\n  content: \"\\f066\";\n}\n.icon-plus:before {\n  content: \"\\f067\";\n}\n.icon-minus:before {\n  content: \"\\f068\";\n}\n.icon-asterisk:before {\n  content: \"\\f069\";\n}\n.icon-exclamation-sign:before {\n  content: \"\\f06a\";\n}\n.icon-gift:before {\n  content: \"\\f06b\";\n}\n.icon-leaf:before {\n  content: \"\\f06c\";\n}\n.icon-fire:before {\n  content: \"\\f06d\";\n}\n.icon-eye-open:before {\n  content: \"\\f06e\";\n}\n.icon-eye-close:before {\n  content: \"\\f070\";\n}\n.icon-warning-sign:before {\n  content: \"\\f071\";\n}\n.icon-plane:before {\n  content: \"\\f072\";\n}\n.icon-calendar:before {\n  content: \"\\f073\";\n}\n.icon-random:before {\n  content: \"\\f074\";\n}\n.icon-comment:before {\n  content: \"\\f075\";\n}\n.icon-magnet:before {\n  content: \"\\f076\";\n}\n.icon-chevron-up:before {\n  content: \"\\f077\";\n}\n.icon-chevron-down:before {\n  content: \"\\f078\";\n}\n.icon-retweet:before {\n  content: \"\\f079\";\n}\n.icon-shopping-cart:before {\n  content: \"\\f07a\";\n}\n.icon-folder-close:before {\n  content: \"\\f07b\";\n}\n.icon-folder-open:before {\n  content: \"\\f07c\";\n}\n.icon-resize-vertical:before {\n  content: \"\\f07d\";\n}\n.icon-resize-horizontal:before {\n  content: \"\\f07e\";\n}\n.icon-bar-chart:before {\n  content: \"\\f080\";\n}\n.icon-twitter-sign:before {\n  content: \"\\f081\";\n}\n.icon-facebook-sign:before {\n  content: \"\\f082\";\n}\n.icon-camera-retro:before {\n  content: \"\\f083\";\n}\n.icon-key:before {\n  content: \"\\f084\";\n}\n.icon-gears:before,\n.icon-cogs:before {\n  content: \"\\f085\";\n}\n.icon-comments:before {\n  content: \"\\f086\";\n}\n.icon-thumbs-up-alt:before {\n  content: \"\\f087\";\n}\n.icon-thumbs-down-alt:before {\n  content: \"\\f088\";\n}\n.icon-star-half:before {\n  content: \"\\f089\";\n}\n.icon-heart-empty:before {\n  content: \"\\f08a\";\n}\n.icon-signout:before {\n  content: \"\\f08b\";\n}\n.icon-linkedin-sign:before {\n  content: \"\\f08c\";\n}\n.icon-pushpin:before {\n  content: \"\\f08d\";\n}\n.icon-external-link:before {\n  content: \"\\f08e\";\n}\n.icon-signin:before {\n  content: \"\\f090\";\n}\n.icon-trophy:before {\n  content: \"\\f091\";\n}\n.icon-github-sign:before {\n  content: \"\\f092\";\n}\n.icon-upload-alt:before {\n  content: \"\\f093\";\n}\n.icon-lemon:before {\n  content: \"\\f094\";\n}\n.icon-phone:before {\n  content: \"\\f095\";\n}\n.icon-unchecked:before,\n.icon-check-empty:before {\n  content: \"\\f096\";\n}\n.icon-bookmark-empty:before {\n  content: \"\\f097\";\n}\n.icon-phone-sign:before {\n  content: \"\\f098\";\n}\n.icon-twitter:before {\n  content: \"\\f099\";\n}\n.icon-facebook:before {\n  content: \"\\f09a\";\n}\n.icon-github:before {\n  content: \"\\f09b\";\n}\n.icon-unlock:before {\n  content: \"\\f09c\";\n}\n.icon-credit-card:before {\n  content: \"\\f09d\";\n}\n.icon-rss:before {\n  content: \"\\f09e\";\n}\n.icon-hdd:before {\n  content: \"\\f0a0\";\n}\n.icon-bullhorn:before {\n  content: \"\\f0a1\";\n}\n.icon-bell:before {\n  content: \"\\f0a2\";\n}\n.icon-certificate:before {\n  content: \"\\f0a3\";\n}\n.icon-hand-right:before {\n  content: \"\\f0a4\";\n}\n.icon-hand-left:before {\n  content: \"\\f0a5\";\n}\n.icon-hand-up:before {\n  content: \"\\f0a6\";\n}\n.icon-hand-down:before {\n  content: \"\\f0a7\";\n}\n.icon-circle-arrow-left:before {\n  content: \"\\f0a8\";\n}\n.icon-circle-arrow-right:before {\n  content: \"\\f0a9\";\n}\n.icon-circle-arrow-up:before {\n  content: \"\\f0aa\";\n}\n.icon-circle-arrow-down:before {\n  content: \"\\f0ab\";\n}\n.icon-globe:before {\n  content: \"\\f0ac\";\n}\n.icon-wrench:before {\n  content: \"\\f0ad\";\n}\n.icon-tasks:before {\n  content: \"\\f0ae\";\n}\n.icon-filter:before {\n  content: \"\\f0b0\";\n}\n.icon-briefcase:before {\n  content: \"\\f0b1\";\n}\n.icon-fullscreen:before {\n  content: \"\\f0b2\";\n}\n.icon-group:before {\n  content: \"\\f0c0\";\n}\n.icon-link:before {\n  content: \"\\f0c1\";\n}\n.icon-cloud:before {\n  content: \"\\f0c2\";\n}\n.icon-beaker:before {\n  content: \"\\f0c3\";\n}\n.icon-cut:before {\n  content: \"\\f0c4\";\n}\n.icon-copy:before {\n  content: \"\\f0c5\";\n}\n.icon-paperclip:before,\n.icon-paper-clip:before {\n  content: \"\\f0c6\";\n}\n.icon-save:before {\n  content: \"\\f0c7\";\n}\n.icon-sign-blank:before {\n  content: \"\\f0c8\";\n}\n.icon-reorder:before {\n  content: \"\\f0c9\";\n}\n.icon-list-ul:before {\n  content: \"\\f0ca\";\n}\n.icon-list-ol:before {\n  content: \"\\f0cb\";\n}\n.icon-strikethrough:before {\n  content: \"\\f0cc\";\n}\n.icon-underline:before {\n  content: \"\\f0cd\";\n}\n.icon-table:before {\n  content: \"\\f0ce\";\n}\n.icon-magic:before {\n  content: \"\\f0d0\";\n}\n.icon-truck:before {\n  content: \"\\f0d1\";\n}\n.icon-pinterest:before {\n  content: \"\\f0d2\";\n}\n.icon-pinterest-sign:before {\n  content: \"\\f0d3\";\n}\n.icon-google-plus-sign:before {\n  content: \"\\f0d4\";\n}\n.icon-google-plus:before {\n  content: \"\\f0d5\";\n}\n.icon-money:before {\n  content: \"\\f0d6\";\n}\n.icon-caret-down:before {\n  content: \"\\f0d7\";\n}\n.icon-caret-up:before {\n  content: \"\\f0d8\";\n}\n.icon-caret-left:before {\n  content: \"\\f0d9\";\n}\n.icon-caret-right:before {\n  content: \"\\f0da\";\n}\n.icon-columns:before {\n  content: \"\\f0db\";\n}\n.icon-sort:before {\n  content: \"\\f0dc\";\n}\n.icon-sort-down:before {\n  content: \"\\f0dd\";\n}\n.icon-sort-up:before {\n  content: \"\\f0de\";\n}\n.icon-envelope:before {\n  content: \"\\f0e0\";\n}\n.icon-linkedin:before {\n  content: \"\\f0e1\";\n}\n.icon-rotate-left:before,\n.icon-undo:before {\n  content: \"\\f0e2\";\n}\n.icon-legal:before {\n  content: \"\\f0e3\";\n}\n.icon-dashboard:before {\n  content: \"\\f0e4\";\n}\n.icon-comment-alt:before {\n  content: \"\\f0e5\";\n}\n.icon-comments-alt:before {\n  content: \"\\f0e6\";\n}\n.icon-bolt:before {\n  content: \"\\f0e7\";\n}\n.icon-sitemap:before {\n  content: \"\\f0e8\";\n}\n.icon-umbrella:before {\n  content: \"\\f0e9\";\n}\n.icon-paste:before {\n  content: \"\\f0ea\";\n}\n.icon-lightbulb:before {\n  content: \"\\f0eb\";\n}\n.icon-exchange:before {\n  content: \"\\f0ec\";\n}\n.icon-cloud-download:before {\n  content: \"\\f0ed\";\n}\n.icon-cloud-upload:before {\n  content: \"\\f0ee\";\n}\n.icon-user-md:before {\n  content: \"\\f0f0\";\n}\n.icon-stethoscope:before {\n  content: \"\\f0f1\";\n}\n.icon-suitcase:before {\n  content: \"\\f0f2\";\n}\n.icon-bell-alt:before {\n  content: \"\\f0f3\";\n}\n.icon-coffee:before {\n  content: \"\\f0f4\";\n}\n.icon-food:before {\n  content: \"\\f0f5\";\n}\n.icon-file-text-alt:before {\n  content: \"\\f0f6\";\n}\n.icon-building:before {\n  content: \"\\f0f7\";\n}\n.icon-hospital:before {\n  content: \"\\f0f8\";\n}\n.icon-ambulance:before {\n  content: \"\\f0f9\";\n}\n.icon-medkit:before {\n  content: \"\\f0fa\";\n}\n.icon-fighter-jet:before {\n  content: \"\\f0fb\";\n}\n.icon-beer:before {\n  content: \"\\f0fc\";\n}\n.icon-h-sign:before {\n  content: \"\\f0fd\";\n}\n.icon-plus-sign-alt:before {\n  content: \"\\f0fe\";\n}\n.icon-double-angle-left:before {\n  content: \"\\f100\";\n}\n.icon-double-angle-right:before {\n  content: \"\\f101\";\n}\n.icon-double-angle-up:before {\n  content: \"\\f102\";\n}\n.icon-double-angle-down:before {\n  content: \"\\f103\";\n}\n.icon-angle-left:before {\n  content: \"\\f104\";\n}\n.icon-angle-right:before {\n  content: \"\\f105\";\n}\n.icon-angle-up:before {\n  content: \"\\f106\";\n}\n.icon-angle-down:before {\n  content: \"\\f107\";\n}\n.icon-desktop:before {\n  content: \"\\f108\";\n}\n.icon-laptop:before {\n  content: \"\\f109\";\n}\n.icon-tablet:before {\n  content: \"\\f10a\";\n}\n.icon-mobile-phone:before {\n  content: \"\\f10b\";\n}\n.icon-circle-blank:before {\n  content: \"\\f10c\";\n}\n.icon-quote-left:before {\n  content: \"\\f10d\";\n}\n.icon-quote-right:before {\n  content: \"\\f10e\";\n}\n.icon-spinner:before {\n  content: \"\\f110\";\n}\n.icon-circle:before {\n  content: \"\\f111\";\n}\n.icon-mail-reply:before,\n.icon-reply:before {\n  content: \"\\f112\";\n}\n.icon-github-alt:before {\n  content: \"\\f113\";\n}\n.icon-folder-close-alt:before {\n  content: \"\\f114\";\n}\n.icon-folder-open-alt:before {\n  content: \"\\f115\";\n}\n.icon-expand-alt:before {\n  content: \"\\f116\";\n}\n.icon-collapse-alt:before {\n  content: \"\\f117\";\n}\n.icon-smile:before {\n  content: \"\\f118\";\n}\n.icon-frown:before {\n  content: \"\\f119\";\n}\n.icon-meh:before {\n  content: \"\\f11a\";\n}\n.icon-gamepad:before {\n  content: \"\\f11b\";\n}\n.icon-keyboard:before {\n  content: \"\\f11c\";\n}\n.icon-flag-alt:before {\n  content: \"\\f11d\";\n}\n.icon-flag-checkered:before {\n  content: \"\\f11e\";\n}\n.icon-terminal:before {\n  content: \"\\f120\";\n}\n.icon-code:before {\n  content: \"\\f121\";\n}\n.icon-reply-all:before {\n  content: \"\\f122\";\n}\n.icon-mail-reply-all:before {\n  content: \"\\f122\";\n}\n.icon-star-half-full:before,\n.icon-star-half-empty:before {\n  content: \"\\f123\";\n}\n.icon-location-arrow:before {\n  content: \"\\f124\";\n}\n.icon-crop:before {\n  content: \"\\f125\";\n}\n.icon-code-fork:before {\n  content: \"\\f126\";\n}\n.icon-unlink:before {\n  content: \"\\f127\";\n}\n.icon-question:before {\n  content: \"\\f128\";\n}\n.icon-info:before {\n  content: \"\\f129\";\n}\n.icon-exclamation:before {\n  content: \"\\f12a\";\n}\n.icon-superscript:before {\n  content: \"\\f12b\";\n}\n.icon-subscript:before {\n  content: \"\\f12c\";\n}\n.icon-eraser:before {\n  content: \"\\f12d\";\n}\n.icon-puzzle-piece:before {\n  content: \"\\f12e\";\n}\n.icon-microphone:before {\n  content: \"\\f130\";\n}\n.icon-microphone-off:before {\n  content: \"\\f131\";\n}\n.icon-shield:before {\n  content: \"\\f132\";\n}\n.icon-calendar-empty:before {\n  content: \"\\f133\";\n}\n.icon-fire-extinguisher:before {\n  content: \"\\f134\";\n}\n.icon-rocket:before {\n  content: \"\\f135\";\n}\n.icon-maxcdn:before {\n  content: \"\\f136\";\n}\n.icon-chevron-sign-left:before {\n  content: \"\\f137\";\n}\n.icon-chevron-sign-right:before {\n  content: \"\\f138\";\n}\n.icon-chevron-sign-up:before {\n  content: \"\\f139\";\n}\n.icon-chevron-sign-down:before {\n  content: \"\\f13a\";\n}\n.icon-html5:before {\n  content: \"\\f13b\";\n}\n.icon-css3:before {\n  content: \"\\f13c\";\n}\n.icon-anchor:before {\n  content: \"\\f13d\";\n}\n.icon-unlock-alt:before {\n  content: \"\\f13e\";\n}\n.icon-bullseye:before {\n  content: \"\\f140\";\n}\n.icon-ellipsis-horizontal:before {\n  content: \"\\f141\";\n}\n.icon-ellipsis-vertical:before {\n  content: \"\\f142\";\n}\n.icon-rss-sign:before {\n  content: \"\\f143\";\n}\n.icon-play-sign:before {\n  content: \"\\f144\";\n}\n.icon-ticket:before {\n  content: \"\\f145\";\n}\n.icon-minus-sign-alt:before {\n  content: \"\\f146\";\n}\n.icon-check-minus:before {\n  content: \"\\f147\";\n}\n.icon-level-up:before {\n  content: \"\\f148\";\n}\n.icon-level-down:before {\n  content: \"\\f149\";\n}\n.icon-check-sign:before {\n  content: \"\\f14a\";\n}\n.icon-edit-sign:before {\n  content: \"\\f14b\";\n}\n.icon-external-link-sign:before {\n  content: \"\\f14c\";\n}\n.icon-share-sign:before {\n  content: \"\\f14d\";\n}\n.icon-compass:before {\n  content: \"\\f14e\";\n}\n.icon-collapse:before {\n  content: \"\\f150\";\n}\n.icon-collapse-top:before {\n  content: \"\\f151\";\n}\n.icon-expand:before {\n  content: \"\\f152\";\n}\n.icon-euro:before,\n.icon-eur:before {\n  content: \"\\f153\";\n}\n.icon-gbp:before {\n  content: \"\\f154\";\n}\n.icon-dollar:before,\n.icon-usd:before {\n  content: \"\\f155\";\n}\n.icon-rupee:before,\n.icon-inr:before {\n  content: \"\\f156\";\n}\n.icon-yen:before,\n.icon-jpy:before {\n  content: \"\\f157\";\n}\n.icon-renminbi:before,\n.icon-cny:before {\n  content: \"\\f158\";\n}\n.icon-won:before,\n.icon-krw:before {\n  content: \"\\f159\";\n}\n.icon-bitcoin:before,\n.icon-btc:before {\n  content: \"\\f15a\";\n}\n.icon-file:before {\n  content: \"\\f15b\";\n}\n.icon-file-text:before {\n  content: \"\\f15c\";\n}\n.icon-sort-by-alphabet:before {\n  content: \"\\f15d\";\n}\n.icon-sort-by-alphabet-alt:before {\n  content: \"\\f15e\";\n}\n.icon-sort-by-attributes:before {\n  content: \"\\f160\";\n}\n.icon-sort-by-attributes-alt:before {\n  content: \"\\f161\";\n}\n.icon-sort-by-order:before {\n  content: \"\\f162\";\n}\n.icon-sort-by-order-alt:before {\n  content: \"\\f163\";\n}\n.icon-thumbs-up:before {\n  content: \"\\f164\";\n}\n.icon-thumbs-down:before {\n  content: \"\\f165\";\n}\n.icon-youtube-sign:before {\n  content: \"\\f166\";\n}\n.icon-youtube:before {\n  content: \"\\f167\";\n}\n.icon-xing:before {\n  content: \"\\f168\";\n}\n.icon-xing-sign:before {\n  content: \"\\f169\";\n}\n.icon-youtube-play:before {\n  content: \"\\f16a\";\n}\n.icon-dropbox:before {\n  content: \"\\f16b\";\n}\n.icon-stackexchange:before {\n  content: \"\\f16c\";\n}\n.icon-instagram:before {\n  content: \"\\f16d\";\n}\n.icon-flickr:before {\n  content: \"\\f16e\";\n}\n.icon-adn:before {\n  content: \"\\f170\";\n}\n.icon-bitbucket:before {\n  content: \"\\f171\";\n}\n.icon-bitbucket-sign:before {\n  content: \"\\f172\";\n}\n.icon-tumblr:before {\n  content: \"\\f173\";\n}\n.icon-tumblr-sign:before {\n  content: \"\\f174\";\n}\n.icon-long-arrow-down:before {\n  content: \"\\f175\";\n}\n.icon-long-arrow-up:before {\n  content: \"\\f176\";\n}\n.icon-long-arrow-left:before {\n  content: \"\\f177\";\n}\n.icon-long-arrow-right:before {\n  content: \"\\f178\";\n}\n.icon-apple:before {\n  content: \"\\f179\";\n}\n.icon-windows:before {\n  content: \"\\f17a\";\n}\n.icon-android:before {\n  content: \"\\f17b\";\n}\n.icon-linux:before {\n  content: \"\\f17c\";\n}\n.icon-dribbble:before {\n  content: \"\\f17d\";\n}\n.icon-skype:before {\n  content: \"\\f17e\";\n}\n.icon-foursquare:before {\n  content: \"\\f180\";\n}\n.icon-trello:before {\n  content: \"\\f181\";\n}\n.icon-female:before {\n  content: \"\\f182\";\n}\n.icon-male:before {\n  content: \"\\f183\";\n}\n.icon-gittip:before {\n  content: \"\\f184\";\n}\n.icon-sun:before {\n  content: \"\\f185\";\n}\n.icon-moon:before {\n  content: \"\\f186\";\n}\n.icon-archive:before {\n  content: \"\\f187\";\n}\n.icon-bug:before {\n  content: \"\\f188\";\n}\n.icon-vk:before {\n  content: \"\\f189\";\n}\n.icon-weibo:before {\n  content: \"\\f18a\";\n}\n.icon-renren:before {\n  content: \"\\f18b\";\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/less/bootstrap.less",
    "content": "/* BOOTSTRAP SPECIFIC CLASSES\n * -------------------------- */\n\n/* Bootstrap 2.0 sprites.less reset */\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline;\n  width: auto;\n  height: auto;\n  line-height: normal;\n  vertical-align: baseline;\n  background-image: none;\n  background-position: 0% 0%;\n  background-repeat: repeat;\n  margin-top: 0;\n}\n\n/* more sprites.less reset */\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: none;\n}\n\n\n/* keeps Bootstrap styles with and without icons the same */\n.btn, .nav {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n//    display: inline;\n    &.icon-large { line-height: .9em; }\n    &.icon-spin { display: inline-block; }\n  }\n}\n.nav-tabs, .nav-pills {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    &, &.icon-large { line-height: .9em; }\n  }\n}\n.btn {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    &.pull-left, &.pull-right {\n      &.icon-2x { margin-top: .18em; }\n    }\n    &.icon-spin.icon-large { line-height: .8em; }\n  }\n}\n.btn.btn-small {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    &.pull-left, &.pull-right {\n      &.icon-2x { margin-top: .25em; }\n    }\n  }\n}\n.btn.btn-large {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    margin-top: 0; // overrides bootstrap default\n    &.pull-left, &.pull-right {\n      &.icon-2x { margin-top: .05em; }\n    }\n    &.pull-left.icon-2x { margin-right: .2em; }\n    &.pull-right.icon-2x { margin-left: .2em; }\n  }\n}\n\n/* Fixes alignment in nav lists */\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  line-height: inherit;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/less/core.less",
    "content": "/* FONT AWESOME CORE\n * -------------------------- */\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  .icon-FontAwesome();\n}\n\n[class^=\"icon-\"]:before,\n[class*=\" icon-\"]:before {\n  text-decoration: inherit;\n  display: inline-block;\n  speak: none;\n}\n\n/* makes the font 33% larger relative to the icon container */\n.icon-large:before {\n  vertical-align: -10%;\n  font-size: 4/3em;\n}\n\n/* makes sure icons active on rollover in links */\na {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    display: inline;\n  }\n}\n\n/* increased font size for icon-large */\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  &.icon-fixed-width {\n    display: inline-block;\n    width: 16/14em;\n    text-align: right;\n    padding-right: 4/14em;\n    &.icon-large {\n      width: 20/14em;\n    }\n  }\n}\n\n.icons-ul {\n  margin-left: @icons-li-width;\n  list-style-type: none;\n\n  > li { position: relative; }\n\n  .icon-li {\n    position: absolute;\n    left: -@icons-li-width;\n    width: @icons-li-width;\n    text-align: center;\n    line-height: inherit;\n  }\n}\n\n// allows usage of the hide class directly on font awesome icons\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  &.hide {\n    display: none;\n  }\n}\n\n.icon-muted { color: @iconMuted; }\n.icon-light { color: @iconLight; }\n.icon-dark { color: @iconDark; }\n\n// Icon Borders\n// -------------------------\n\n.icon-border {\n  border: solid 1px @borderColor;\n  padding: .2em .25em .15em;\n  .border-radius(3px);\n}\n\n// Icon Sizes\n// -------------------------\n\n.icon-2x {\n  font-size: 2em;\n  &.icon-border {\n    border-width: 2px;\n    .border-radius(4px);\n  }\n}\n.icon-3x {\n  font-size: 3em;\n  &.icon-border {\n    border-width: 3px;\n    .border-radius(5px);\n  }\n}\n.icon-4x {\n  font-size: 4em;\n  &.icon-border {\n    border-width: 4px;\n    .border-radius(6px);\n  }\n}\n\n.icon-5x {\n  font-size: 5em;\n  &.icon-border {\n    border-width: 5px;\n    .border-radius(7px);\n  }\n}\n\n\n// Floats & Margins\n// -------------------------\n\n// Quick floats\n.pull-right { float: right; }\n.pull-left { float: left; }\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  &.pull-left {\n    margin-right: .3em;\n  }\n  &.pull-right {\n    margin-left: .3em;\n  }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/less/extras.less",
    "content": "/* EXTRAS\n * -------------------------- */\n\n/* Stacked and layered icon */\n.icon-stack();\n\n/* Animated rotating icon */\n.icon-spin {\n  display: inline-block;\n  -moz-animation: spin 2s infinite linear;\n  -o-animation: spin 2s infinite linear;\n  -webkit-animation: spin 2s infinite linear;\n  animation: spin 2s infinite linear;\n}\n\n/* Prevent stack and spinners from being taken inline when inside a link */\na .icon-stack,\na .icon-spin {\n  display: inline-block;\n  text-decoration: none;\n}\n\n@-moz-keyframes spin {\n  0% { -moz-transform: rotate(0deg); }\n  100% { -moz-transform: rotate(359deg); }\n}\n@-webkit-keyframes spin {\n  0% { -webkit-transform: rotate(0deg); }\n  100% { -webkit-transform: rotate(359deg); }\n}\n@-o-keyframes spin {\n  0% { -o-transform: rotate(0deg); }\n  100% { -o-transform: rotate(359deg); }\n}\n@-ms-keyframes spin {\n  0% { -ms-transform: rotate(0deg); }\n  100% { -ms-transform: rotate(359deg); }\n}\n@keyframes spin {\n  0% { transform: rotate(0deg); }\n  100% { transform: rotate(359deg); }\n}\n\n/* Icon rotations and mirroring */\n.icon-rotate-90:before {\n  -webkit-transform: rotate(90deg);\n  -moz-transform: rotate(90deg);\n  -ms-transform: rotate(90deg);\n  -o-transform: rotate(90deg);\n  transform: rotate(90deg);\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);\n}\n\n.icon-rotate-180:before {\n  -webkit-transform: rotate(180deg);\n  -moz-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  -o-transform: rotate(180deg);\n  transform: rotate(180deg);\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);\n}\n\n.icon-rotate-270:before {\n  -webkit-transform: rotate(270deg);\n  -moz-transform: rotate(270deg);\n  -ms-transform: rotate(270deg);\n  -o-transform: rotate(270deg);\n  transform: rotate(270deg);\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);\n}\n\n.icon-flip-horizontal:before {\n  -webkit-transform: scale(-1, 1);\n  -moz-transform: scale(-1, 1);\n  -ms-transform: scale(-1, 1);\n  -o-transform: scale(-1, 1);\n  transform: scale(-1, 1);\n}\n\n.icon-flip-vertical:before {\n  -webkit-transform: scale(1, -1);\n  -moz-transform: scale(1, -1);\n  -ms-transform: scale(1, -1);\n  -o-transform: scale(1, -1);\n  transform: scale(1, -1);\n}\n\n/* ensure rotation occurs inside anchor tags */\na {\n  .icon-rotate-90, .icon-rotate-180, .icon-rotate-270, .icon-flip-horizontal, .icon-flip-vertical {\n    &:before { display: inline-block; }\n  }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/less/font-awesome-ie7.less",
    "content": "/*!\n *  Font Awesome 3.2.1\n *  the iconic font designed for Bootstrap\n *  ------------------------------------------------------------------------------\n *  The full suite of pictographic icons, examples, and documentation can be\n *  found at http://fontawesome.io.  Stay up to date on Twitter at\n *  http://twitter.com/fontawesome.\n *\n *  License\n *  ------------------------------------------------------------------------------\n *  - The Font Awesome font is licensed under SIL OFL 1.1 -\n *    http://scripts.sil.org/OFL\n *  - Font Awesome CSS, LESS, and SASS files are licensed under MIT License -\n *    http://opensource.org/licenses/mit-license.html\n *  - Font Awesome documentation licensed under CC BY 3.0 -\n *    http://creativecommons.org/licenses/by/3.0/\n *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:\n *    \"Font Awesome by Dave Gandy - http://fontawesome.io\"\n *\n *  Author - Dave Gandy\n *  ------------------------------------------------------------------------------\n *  Email: dave@fontawesome.io\n *  Twitter: http://twitter.com/davegandy\n *  Work: Lead Product Designer @ Kyruus - http://kyruus.com\n */\n\n.icon-large {\n  font-size: 4/3em;\n  margin-top: -4px;\n  padding-top: 3px;\n  margin-bottom: -4px;\n  padding-bottom: 3px;\n  vertical-align: middle;\n}\n\n.nav {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    vertical-align: inherit;\n    margin-top: -4px;\n    padding-top: 3px;\n    margin-bottom: -4px;\n    padding-bottom: 3px;\n    &.icon-large {\n      vertical-align: -25%;\n    }\n  }\n}\n\n.nav-pills, .nav-tabs {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    &.icon-large {\n      line-height: .75em;\n      margin-top: -7px;\n      padding-top: 5px;\n      margin-bottom: -5px;\n      padding-bottom: 4px;\n    }\n  }\n}\n\n.btn {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    &.pull-left, &.pull-right { vertical-align: inherit; }\n    &.icon-large {\n      margin-top: -.5em;\n    }\n  }\n}\n\na [class^=\"icon-\"],\na [class*=\" icon-\"] {\n  cursor: pointer;\n}\n\n.ie7icon(@inner) { *zoom: ~\"expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '@{inner}')\"; }\n\n\n.icon-glass {\n  .ie7icon('&#xf000;');\n}\n\n\n.icon-music {\n  .ie7icon('&#xf001;');\n}\n\n\n.icon-search {\n  .ie7icon('&#xf002;');\n}\n\n\n.icon-envelope-alt {\n  .ie7icon('&#xf003;');\n}\n\n\n.icon-heart {\n  .ie7icon('&#xf004;');\n}\n\n\n.icon-star {\n  .ie7icon('&#xf005;');\n}\n\n\n.icon-star-empty {\n  .ie7icon('&#xf006;');\n}\n\n\n.icon-user {\n  .ie7icon('&#xf007;');\n}\n\n\n.icon-film {\n  .ie7icon('&#xf008;');\n}\n\n\n.icon-th-large {\n  .ie7icon('&#xf009;');\n}\n\n\n.icon-th {\n  .ie7icon('&#xf00a;');\n}\n\n\n.icon-th-list {\n  .ie7icon('&#xf00b;');\n}\n\n\n.icon-ok {\n  .ie7icon('&#xf00c;');\n}\n\n\n.icon-remove {\n  .ie7icon('&#xf00d;');\n}\n\n\n.icon-zoom-in {\n  .ie7icon('&#xf00e;');\n}\n\n\n.icon-zoom-out {\n  .ie7icon('&#xf010;');\n}\n\n\n.icon-off {\n  .ie7icon('&#xf011;');\n}\n\n.icon-power-off {\n  .ie7icon('&#xf011;');\n}\n\n\n.icon-signal {\n  .ie7icon('&#xf012;');\n}\n\n\n.icon-cog {\n  .ie7icon('&#xf013;');\n}\n\n.icon-gear {\n  .ie7icon('&#xf013;');\n}\n\n\n.icon-trash {\n  .ie7icon('&#xf014;');\n}\n\n\n.icon-home {\n  .ie7icon('&#xf015;');\n}\n\n\n.icon-file-alt {\n  .ie7icon('&#xf016;');\n}\n\n\n.icon-time {\n  .ie7icon('&#xf017;');\n}\n\n\n.icon-road {\n  .ie7icon('&#xf018;');\n}\n\n\n.icon-download-alt {\n  .ie7icon('&#xf019;');\n}\n\n\n.icon-download {\n  .ie7icon('&#xf01a;');\n}\n\n\n.icon-upload {\n  .ie7icon('&#xf01b;');\n}\n\n\n.icon-inbox {\n  .ie7icon('&#xf01c;');\n}\n\n\n.icon-play-circle {\n  .ie7icon('&#xf01d;');\n}\n\n\n.icon-repeat {\n  .ie7icon('&#xf01e;');\n}\n\n.icon-rotate-right {\n  .ie7icon('&#xf01e;');\n}\n\n\n.icon-refresh {\n  .ie7icon('&#xf021;');\n}\n\n\n.icon-list-alt {\n  .ie7icon('&#xf022;');\n}\n\n\n.icon-lock {\n  .ie7icon('&#xf023;');\n}\n\n\n.icon-flag {\n  .ie7icon('&#xf024;');\n}\n\n\n.icon-headphones {\n  .ie7icon('&#xf025;');\n}\n\n\n.icon-volume-off {\n  .ie7icon('&#xf026;');\n}\n\n\n.icon-volume-down {\n  .ie7icon('&#xf027;');\n}\n\n\n.icon-volume-up {\n  .ie7icon('&#xf028;');\n}\n\n\n.icon-qrcode {\n  .ie7icon('&#xf029;');\n}\n\n\n.icon-barcode {\n  .ie7icon('&#xf02a;');\n}\n\n\n.icon-tag {\n  .ie7icon('&#xf02b;');\n}\n\n\n.icon-tags {\n  .ie7icon('&#xf02c;');\n}\n\n\n.icon-book {\n  .ie7icon('&#xf02d;');\n}\n\n\n.icon-bookmark {\n  .ie7icon('&#xf02e;');\n}\n\n\n.icon-print {\n  .ie7icon('&#xf02f;');\n}\n\n\n.icon-camera {\n  .ie7icon('&#xf030;');\n}\n\n\n.icon-font {\n  .ie7icon('&#xf031;');\n}\n\n\n.icon-bold {\n  .ie7icon('&#xf032;');\n}\n\n\n.icon-italic {\n  .ie7icon('&#xf033;');\n}\n\n\n.icon-text-height {\n  .ie7icon('&#xf034;');\n}\n\n\n.icon-text-width {\n  .ie7icon('&#xf035;');\n}\n\n\n.icon-align-left {\n  .ie7icon('&#xf036;');\n}\n\n\n.icon-align-center {\n  .ie7icon('&#xf037;');\n}\n\n\n.icon-align-right {\n  .ie7icon('&#xf038;');\n}\n\n\n.icon-align-justify {\n  .ie7icon('&#xf039;');\n}\n\n\n.icon-list {\n  .ie7icon('&#xf03a;');\n}\n\n\n.icon-indent-left {\n  .ie7icon('&#xf03b;');\n}\n\n\n.icon-indent-right {\n  .ie7icon('&#xf03c;');\n}\n\n\n.icon-facetime-video {\n  .ie7icon('&#xf03d;');\n}\n\n\n.icon-picture {\n  .ie7icon('&#xf03e;');\n}\n\n\n.icon-pencil {\n  .ie7icon('&#xf040;');\n}\n\n\n.icon-map-marker {\n  .ie7icon('&#xf041;');\n}\n\n\n.icon-adjust {\n  .ie7icon('&#xf042;');\n}\n\n\n.icon-tint {\n  .ie7icon('&#xf043;');\n}\n\n\n.icon-edit {\n  .ie7icon('&#xf044;');\n}\n\n\n.icon-share {\n  .ie7icon('&#xf045;');\n}\n\n\n.icon-check {\n  .ie7icon('&#xf046;');\n}\n\n\n.icon-move {\n  .ie7icon('&#xf047;');\n}\n\n\n.icon-step-backward {\n  .ie7icon('&#xf048;');\n}\n\n\n.icon-fast-backward {\n  .ie7icon('&#xf049;');\n}\n\n\n.icon-backward {\n  .ie7icon('&#xf04a;');\n}\n\n\n.icon-play {\n  .ie7icon('&#xf04b;');\n}\n\n\n.icon-pause {\n  .ie7icon('&#xf04c;');\n}\n\n\n.icon-stop {\n  .ie7icon('&#xf04d;');\n}\n\n\n.icon-forward {\n  .ie7icon('&#xf04e;');\n}\n\n\n.icon-fast-forward {\n  .ie7icon('&#xf050;');\n}\n\n\n.icon-step-forward {\n  .ie7icon('&#xf051;');\n}\n\n\n.icon-eject {\n  .ie7icon('&#xf052;');\n}\n\n\n.icon-chevron-left {\n  .ie7icon('&#xf053;');\n}\n\n\n.icon-chevron-right {\n  .ie7icon('&#xf054;');\n}\n\n\n.icon-plus-sign {\n  .ie7icon('&#xf055;');\n}\n\n\n.icon-minus-sign {\n  .ie7icon('&#xf056;');\n}\n\n\n.icon-remove-sign {\n  .ie7icon('&#xf057;');\n}\n\n\n.icon-ok-sign {\n  .ie7icon('&#xf058;');\n}\n\n\n.icon-question-sign {\n  .ie7icon('&#xf059;');\n}\n\n\n.icon-info-sign {\n  .ie7icon('&#xf05a;');\n}\n\n\n.icon-screenshot {\n  .ie7icon('&#xf05b;');\n}\n\n\n.icon-remove-circle {\n  .ie7icon('&#xf05c;');\n}\n\n\n.icon-ok-circle {\n  .ie7icon('&#xf05d;');\n}\n\n\n.icon-ban-circle {\n  .ie7icon('&#xf05e;');\n}\n\n\n.icon-arrow-left {\n  .ie7icon('&#xf060;');\n}\n\n\n.icon-arrow-right {\n  .ie7icon('&#xf061;');\n}\n\n\n.icon-arrow-up {\n  .ie7icon('&#xf062;');\n}\n\n\n.icon-arrow-down {\n  .ie7icon('&#xf063;');\n}\n\n\n.icon-share-alt {\n  .ie7icon('&#xf064;');\n}\n\n.icon-mail-forward {\n  .ie7icon('&#xf064;');\n}\n\n\n.icon-resize-full {\n  .ie7icon('&#xf065;');\n}\n\n\n.icon-resize-small {\n  .ie7icon('&#xf066;');\n}\n\n\n.icon-plus {\n  .ie7icon('&#xf067;');\n}\n\n\n.icon-minus {\n  .ie7icon('&#xf068;');\n}\n\n\n.icon-asterisk {\n  .ie7icon('&#xf069;');\n}\n\n\n.icon-exclamation-sign {\n  .ie7icon('&#xf06a;');\n}\n\n\n.icon-gift {\n  .ie7icon('&#xf06b;');\n}\n\n\n.icon-leaf {\n  .ie7icon('&#xf06c;');\n}\n\n\n.icon-fire {\n  .ie7icon('&#xf06d;');\n}\n\n\n.icon-eye-open {\n  .ie7icon('&#xf06e;');\n}\n\n\n.icon-eye-close {\n  .ie7icon('&#xf070;');\n}\n\n\n.icon-warning-sign {\n  .ie7icon('&#xf071;');\n}\n\n\n.icon-plane {\n  .ie7icon('&#xf072;');\n}\n\n\n.icon-calendar {\n  .ie7icon('&#xf073;');\n}\n\n\n.icon-random {\n  .ie7icon('&#xf074;');\n}\n\n\n.icon-comment {\n  .ie7icon('&#xf075;');\n}\n\n\n.icon-magnet {\n  .ie7icon('&#xf076;');\n}\n\n\n.icon-chevron-up {\n  .ie7icon('&#xf077;');\n}\n\n\n.icon-chevron-down {\n  .ie7icon('&#xf078;');\n}\n\n\n.icon-retweet {\n  .ie7icon('&#xf079;');\n}\n\n\n.icon-shopping-cart {\n  .ie7icon('&#xf07a;');\n}\n\n\n.icon-folder-close {\n  .ie7icon('&#xf07b;');\n}\n\n\n.icon-folder-open {\n  .ie7icon('&#xf07c;');\n}\n\n\n.icon-resize-vertical {\n  .ie7icon('&#xf07d;');\n}\n\n\n.icon-resize-horizontal {\n  .ie7icon('&#xf07e;');\n}\n\n\n.icon-bar-chart {\n  .ie7icon('&#xf080;');\n}\n\n\n.icon-twitter-sign {\n  .ie7icon('&#xf081;');\n}\n\n\n.icon-facebook-sign {\n  .ie7icon('&#xf082;');\n}\n\n\n.icon-camera-retro {\n  .ie7icon('&#xf083;');\n}\n\n\n.icon-key {\n  .ie7icon('&#xf084;');\n}\n\n\n.icon-cogs {\n  .ie7icon('&#xf085;');\n}\n\n.icon-gears {\n  .ie7icon('&#xf085;');\n}\n\n\n.icon-comments {\n  .ie7icon('&#xf086;');\n}\n\n\n.icon-thumbs-up-alt {\n  .ie7icon('&#xf087;');\n}\n\n\n.icon-thumbs-down-alt {\n  .ie7icon('&#xf088;');\n}\n\n\n.icon-star-half {\n  .ie7icon('&#xf089;');\n}\n\n\n.icon-heart-empty {\n  .ie7icon('&#xf08a;');\n}\n\n\n.icon-signout {\n  .ie7icon('&#xf08b;');\n}\n\n\n.icon-linkedin-sign {\n  .ie7icon('&#xf08c;');\n}\n\n\n.icon-pushpin {\n  .ie7icon('&#xf08d;');\n}\n\n\n.icon-external-link {\n  .ie7icon('&#xf08e;');\n}\n\n\n.icon-signin {\n  .ie7icon('&#xf090;');\n}\n\n\n.icon-trophy {\n  .ie7icon('&#xf091;');\n}\n\n\n.icon-github-sign {\n  .ie7icon('&#xf092;');\n}\n\n\n.icon-upload-alt {\n  .ie7icon('&#xf093;');\n}\n\n\n.icon-lemon {\n  .ie7icon('&#xf094;');\n}\n\n\n.icon-phone {\n  .ie7icon('&#xf095;');\n}\n\n\n.icon-check-empty {\n  .ie7icon('&#xf096;');\n}\n\n.icon-unchecked {\n  .ie7icon('&#xf096;');\n}\n\n\n.icon-bookmark-empty {\n  .ie7icon('&#xf097;');\n}\n\n\n.icon-phone-sign {\n  .ie7icon('&#xf098;');\n}\n\n\n.icon-twitter {\n  .ie7icon('&#xf099;');\n}\n\n\n.icon-facebook {\n  .ie7icon('&#xf09a;');\n}\n\n\n.icon-github {\n  .ie7icon('&#xf09b;');\n}\n\n\n.icon-unlock {\n  .ie7icon('&#xf09c;');\n}\n\n\n.icon-credit-card {\n  .ie7icon('&#xf09d;');\n}\n\n\n.icon-rss {\n  .ie7icon('&#xf09e;');\n}\n\n\n.icon-hdd {\n  .ie7icon('&#xf0a0;');\n}\n\n\n.icon-bullhorn {\n  .ie7icon('&#xf0a1;');\n}\n\n\n.icon-bell {\n  .ie7icon('&#xf0a2;');\n}\n\n\n.icon-certificate {\n  .ie7icon('&#xf0a3;');\n}\n\n\n.icon-hand-right {\n  .ie7icon('&#xf0a4;');\n}\n\n\n.icon-hand-left {\n  .ie7icon('&#xf0a5;');\n}\n\n\n.icon-hand-up {\n  .ie7icon('&#xf0a6;');\n}\n\n\n.icon-hand-down {\n  .ie7icon('&#xf0a7;');\n}\n\n\n.icon-circle-arrow-left {\n  .ie7icon('&#xf0a8;');\n}\n\n\n.icon-circle-arrow-right {\n  .ie7icon('&#xf0a9;');\n}\n\n\n.icon-circle-arrow-up {\n  .ie7icon('&#xf0aa;');\n}\n\n\n.icon-circle-arrow-down {\n  .ie7icon('&#xf0ab;');\n}\n\n\n.icon-globe {\n  .ie7icon('&#xf0ac;');\n}\n\n\n.icon-wrench {\n  .ie7icon('&#xf0ad;');\n}\n\n\n.icon-tasks {\n  .ie7icon('&#xf0ae;');\n}\n\n\n.icon-filter {\n  .ie7icon('&#xf0b0;');\n}\n\n\n.icon-briefcase {\n  .ie7icon('&#xf0b1;');\n}\n\n\n.icon-fullscreen {\n  .ie7icon('&#xf0b2;');\n}\n\n\n.icon-group {\n  .ie7icon('&#xf0c0;');\n}\n\n\n.icon-link {\n  .ie7icon('&#xf0c1;');\n}\n\n\n.icon-cloud {\n  .ie7icon('&#xf0c2;');\n}\n\n\n.icon-beaker {\n  .ie7icon('&#xf0c3;');\n}\n\n\n.icon-cut {\n  .ie7icon('&#xf0c4;');\n}\n\n\n.icon-copy {\n  .ie7icon('&#xf0c5;');\n}\n\n\n.icon-paper-clip {\n  .ie7icon('&#xf0c6;');\n}\n\n.icon-paperclip {\n  .ie7icon('&#xf0c6;');\n}\n\n\n.icon-save {\n  .ie7icon('&#xf0c7;');\n}\n\n\n.icon-sign-blank {\n  .ie7icon('&#xf0c8;');\n}\n\n\n.icon-reorder {\n  .ie7icon('&#xf0c9;');\n}\n\n\n.icon-list-ul {\n  .ie7icon('&#xf0ca;');\n}\n\n\n.icon-list-ol {\n  .ie7icon('&#xf0cb;');\n}\n\n\n.icon-strikethrough {\n  .ie7icon('&#xf0cc;');\n}\n\n\n.icon-underline {\n  .ie7icon('&#xf0cd;');\n}\n\n\n.icon-table {\n  .ie7icon('&#xf0ce;');\n}\n\n\n.icon-magic {\n  .ie7icon('&#xf0d0;');\n}\n\n\n.icon-truck {\n  .ie7icon('&#xf0d1;');\n}\n\n\n.icon-pinterest {\n  .ie7icon('&#xf0d2;');\n}\n\n\n.icon-pinterest-sign {\n  .ie7icon('&#xf0d3;');\n}\n\n\n.icon-google-plus-sign {\n  .ie7icon('&#xf0d4;');\n}\n\n\n.icon-google-plus {\n  .ie7icon('&#xf0d5;');\n}\n\n\n.icon-money {\n  .ie7icon('&#xf0d6;');\n}\n\n\n.icon-caret-down {\n  .ie7icon('&#xf0d7;');\n}\n\n\n.icon-caret-up {\n  .ie7icon('&#xf0d8;');\n}\n\n\n.icon-caret-left {\n  .ie7icon('&#xf0d9;');\n}\n\n\n.icon-caret-right {\n  .ie7icon('&#xf0da;');\n}\n\n\n.icon-columns {\n  .ie7icon('&#xf0db;');\n}\n\n\n.icon-sort {\n  .ie7icon('&#xf0dc;');\n}\n\n\n.icon-sort-down {\n  .ie7icon('&#xf0dd;');\n}\n\n\n.icon-sort-up {\n  .ie7icon('&#xf0de;');\n}\n\n\n.icon-envelope {\n  .ie7icon('&#xf0e0;');\n}\n\n\n.icon-linkedin {\n  .ie7icon('&#xf0e1;');\n}\n\n\n.icon-undo {\n  .ie7icon('&#xf0e2;');\n}\n\n.icon-rotate-left {\n  .ie7icon('&#xf0e2;');\n}\n\n\n.icon-legal {\n  .ie7icon('&#xf0e3;');\n}\n\n\n.icon-dashboard {\n  .ie7icon('&#xf0e4;');\n}\n\n\n.icon-comment-alt {\n  .ie7icon('&#xf0e5;');\n}\n\n\n.icon-comments-alt {\n  .ie7icon('&#xf0e6;');\n}\n\n\n.icon-bolt {\n  .ie7icon('&#xf0e7;');\n}\n\n\n.icon-sitemap {\n  .ie7icon('&#xf0e8;');\n}\n\n\n.icon-umbrella {\n  .ie7icon('&#xf0e9;');\n}\n\n\n.icon-paste {\n  .ie7icon('&#xf0ea;');\n}\n\n\n.icon-lightbulb {\n  .ie7icon('&#xf0eb;');\n}\n\n\n.icon-exchange {\n  .ie7icon('&#xf0ec;');\n}\n\n\n.icon-cloud-download {\n  .ie7icon('&#xf0ed;');\n}\n\n\n.icon-cloud-upload {\n  .ie7icon('&#xf0ee;');\n}\n\n\n.icon-user-md {\n  .ie7icon('&#xf0f0;');\n}\n\n\n.icon-stethoscope {\n  .ie7icon('&#xf0f1;');\n}\n\n\n.icon-suitcase {\n  .ie7icon('&#xf0f2;');\n}\n\n\n.icon-bell-alt {\n  .ie7icon('&#xf0f3;');\n}\n\n\n.icon-coffee {\n  .ie7icon('&#xf0f4;');\n}\n\n\n.icon-food {\n  .ie7icon('&#xf0f5;');\n}\n\n\n.icon-file-text-alt {\n  .ie7icon('&#xf0f6;');\n}\n\n\n.icon-building {\n  .ie7icon('&#xf0f7;');\n}\n\n\n.icon-hospital {\n  .ie7icon('&#xf0f8;');\n}\n\n\n.icon-ambulance {\n  .ie7icon('&#xf0f9;');\n}\n\n\n.icon-medkit {\n  .ie7icon('&#xf0fa;');\n}\n\n\n.icon-fighter-jet {\n  .ie7icon('&#xf0fb;');\n}\n\n\n.icon-beer {\n  .ie7icon('&#xf0fc;');\n}\n\n\n.icon-h-sign {\n  .ie7icon('&#xf0fd;');\n}\n\n\n.icon-plus-sign-alt {\n  .ie7icon('&#xf0fe;');\n}\n\n\n.icon-double-angle-left {\n  .ie7icon('&#xf100;');\n}\n\n\n.icon-double-angle-right {\n  .ie7icon('&#xf101;');\n}\n\n\n.icon-double-angle-up {\n  .ie7icon('&#xf102;');\n}\n\n\n.icon-double-angle-down {\n  .ie7icon('&#xf103;');\n}\n\n\n.icon-angle-left {\n  .ie7icon('&#xf104;');\n}\n\n\n.icon-angle-right {\n  .ie7icon('&#xf105;');\n}\n\n\n.icon-angle-up {\n  .ie7icon('&#xf106;');\n}\n\n\n.icon-angle-down {\n  .ie7icon('&#xf107;');\n}\n\n\n.icon-desktop {\n  .ie7icon('&#xf108;');\n}\n\n\n.icon-laptop {\n  .ie7icon('&#xf109;');\n}\n\n\n.icon-tablet {\n  .ie7icon('&#xf10a;');\n}\n\n\n.icon-mobile-phone {\n  .ie7icon('&#xf10b;');\n}\n\n\n.icon-circle-blank {\n  .ie7icon('&#xf10c;');\n}\n\n\n.icon-quote-left {\n  .ie7icon('&#xf10d;');\n}\n\n\n.icon-quote-right {\n  .ie7icon('&#xf10e;');\n}\n\n\n.icon-spinner {\n  .ie7icon('&#xf110;');\n}\n\n\n.icon-circle {\n  .ie7icon('&#xf111;');\n}\n\n\n.icon-reply {\n  .ie7icon('&#xf112;');\n}\n\n.icon-mail-reply {\n  .ie7icon('&#xf112;');\n}\n\n\n.icon-github-alt {\n  .ie7icon('&#xf113;');\n}\n\n\n.icon-folder-close-alt {\n  .ie7icon('&#xf114;');\n}\n\n\n.icon-folder-open-alt {\n  .ie7icon('&#xf115;');\n}\n\n\n.icon-expand-alt {\n  .ie7icon('&#xf116;');\n}\n\n\n.icon-collapse-alt {\n  .ie7icon('&#xf117;');\n}\n\n\n.icon-smile {\n  .ie7icon('&#xf118;');\n}\n\n\n.icon-frown {\n  .ie7icon('&#xf119;');\n}\n\n\n.icon-meh {\n  .ie7icon('&#xf11a;');\n}\n\n\n.icon-gamepad {\n  .ie7icon('&#xf11b;');\n}\n\n\n.icon-keyboard {\n  .ie7icon('&#xf11c;');\n}\n\n\n.icon-flag-alt {\n  .ie7icon('&#xf11d;');\n}\n\n\n.icon-flag-checkered {\n  .ie7icon('&#xf11e;');\n}\n\n\n.icon-terminal {\n  .ie7icon('&#xf120;');\n}\n\n\n.icon-code {\n  .ie7icon('&#xf121;');\n}\n\n\n.icon-reply-all {\n  .ie7icon('&#xf122;');\n}\n\n\n.icon-mail-reply-all {\n  .ie7icon('&#xf122;');\n}\n\n\n.icon-star-half-empty {\n  .ie7icon('&#xf123;');\n}\n\n.icon-star-half-full {\n  .ie7icon('&#xf123;');\n}\n\n\n.icon-location-arrow {\n  .ie7icon('&#xf124;');\n}\n\n\n.icon-crop {\n  .ie7icon('&#xf125;');\n}\n\n\n.icon-code-fork {\n  .ie7icon('&#xf126;');\n}\n\n\n.icon-unlink {\n  .ie7icon('&#xf127;');\n}\n\n\n.icon-question {\n  .ie7icon('&#xf128;');\n}\n\n\n.icon-info {\n  .ie7icon('&#xf129;');\n}\n\n\n.icon-exclamation {\n  .ie7icon('&#xf12a;');\n}\n\n\n.icon-superscript {\n  .ie7icon('&#xf12b;');\n}\n\n\n.icon-subscript {\n  .ie7icon('&#xf12c;');\n}\n\n\n.icon-eraser {\n  .ie7icon('&#xf12d;');\n}\n\n\n.icon-puzzle-piece {\n  .ie7icon('&#xf12e;');\n}\n\n\n.icon-microphone {\n  .ie7icon('&#xf130;');\n}\n\n\n.icon-microphone-off {\n  .ie7icon('&#xf131;');\n}\n\n\n.icon-shield {\n  .ie7icon('&#xf132;');\n}\n\n\n.icon-calendar-empty {\n  .ie7icon('&#xf133;');\n}\n\n\n.icon-fire-extinguisher {\n  .ie7icon('&#xf134;');\n}\n\n\n.icon-rocket {\n  .ie7icon('&#xf135;');\n}\n\n\n.icon-maxcdn {\n  .ie7icon('&#xf136;');\n}\n\n\n.icon-chevron-sign-left {\n  .ie7icon('&#xf137;');\n}\n\n\n.icon-chevron-sign-right {\n  .ie7icon('&#xf138;');\n}\n\n\n.icon-chevron-sign-up {\n  .ie7icon('&#xf139;');\n}\n\n\n.icon-chevron-sign-down {\n  .ie7icon('&#xf13a;');\n}\n\n\n.icon-html5 {\n  .ie7icon('&#xf13b;');\n}\n\n\n.icon-css3 {\n  .ie7icon('&#xf13c;');\n}\n\n\n.icon-anchor {\n  .ie7icon('&#xf13d;');\n}\n\n\n.icon-unlock-alt {\n  .ie7icon('&#xf13e;');\n}\n\n\n.icon-bullseye {\n  .ie7icon('&#xf140;');\n}\n\n\n.icon-ellipsis-horizontal {\n  .ie7icon('&#xf141;');\n}\n\n\n.icon-ellipsis-vertical {\n  .ie7icon('&#xf142;');\n}\n\n\n.icon-rss-sign {\n  .ie7icon('&#xf143;');\n}\n\n\n.icon-play-sign {\n  .ie7icon('&#xf144;');\n}\n\n\n.icon-ticket {\n  .ie7icon('&#xf145;');\n}\n\n\n.icon-minus-sign-alt {\n  .ie7icon('&#xf146;');\n}\n\n\n.icon-check-minus {\n  .ie7icon('&#xf147;');\n}\n\n\n.icon-level-up {\n  .ie7icon('&#xf148;');\n}\n\n\n.icon-level-down {\n  .ie7icon('&#xf149;');\n}\n\n\n.icon-check-sign {\n  .ie7icon('&#xf14a;');\n}\n\n\n.icon-edit-sign {\n  .ie7icon('&#xf14b;');\n}\n\n\n.icon-external-link-sign {\n  .ie7icon('&#xf14c;');\n}\n\n\n.icon-share-sign {\n  .ie7icon('&#xf14d;');\n}\n\n\n.icon-compass {\n  .ie7icon('&#xf14e;');\n}\n\n\n.icon-collapse {\n  .ie7icon('&#xf150;');\n}\n\n\n.icon-collapse-top {\n  .ie7icon('&#xf151;');\n}\n\n\n.icon-expand {\n  .ie7icon('&#xf152;');\n}\n\n\n.icon-eur {\n  .ie7icon('&#xf153;');\n}\n\n.icon-euro {\n  .ie7icon('&#xf153;');\n}\n\n\n.icon-gbp {\n  .ie7icon('&#xf154;');\n}\n\n\n.icon-usd {\n  .ie7icon('&#xf155;');\n}\n\n.icon-dollar {\n  .ie7icon('&#xf155;');\n}\n\n\n.icon-inr {\n  .ie7icon('&#xf156;');\n}\n\n.icon-rupee {\n  .ie7icon('&#xf156;');\n}\n\n\n.icon-jpy {\n  .ie7icon('&#xf157;');\n}\n\n.icon-yen {\n  .ie7icon('&#xf157;');\n}\n\n\n.icon-cny {\n  .ie7icon('&#xf158;');\n}\n\n.icon-renminbi {\n  .ie7icon('&#xf158;');\n}\n\n\n.icon-krw {\n  .ie7icon('&#xf159;');\n}\n\n.icon-won {\n  .ie7icon('&#xf159;');\n}\n\n\n.icon-btc {\n  .ie7icon('&#xf15a;');\n}\n\n.icon-bitcoin {\n  .ie7icon('&#xf15a;');\n}\n\n\n.icon-file {\n  .ie7icon('&#xf15b;');\n}\n\n\n.icon-file-text {\n  .ie7icon('&#xf15c;');\n}\n\n\n.icon-sort-by-alphabet {\n  .ie7icon('&#xf15d;');\n}\n\n\n.icon-sort-by-alphabet-alt {\n  .ie7icon('&#xf15e;');\n}\n\n\n.icon-sort-by-attributes {\n  .ie7icon('&#xf160;');\n}\n\n\n.icon-sort-by-attributes-alt {\n  .ie7icon('&#xf161;');\n}\n\n\n.icon-sort-by-order {\n  .ie7icon('&#xf162;');\n}\n\n\n.icon-sort-by-order-alt {\n  .ie7icon('&#xf163;');\n}\n\n\n.icon-thumbs-up {\n  .ie7icon('&#xf164;');\n}\n\n\n.icon-thumbs-down {\n  .ie7icon('&#xf165;');\n}\n\n\n.icon-youtube-sign {\n  .ie7icon('&#xf166;');\n}\n\n\n.icon-youtube {\n  .ie7icon('&#xf167;');\n}\n\n\n.icon-xing {\n  .ie7icon('&#xf168;');\n}\n\n\n.icon-xing-sign {\n  .ie7icon('&#xf169;');\n}\n\n\n.icon-youtube-play {\n  .ie7icon('&#xf16a;');\n}\n\n\n.icon-dropbox {\n  .ie7icon('&#xf16b;');\n}\n\n\n.icon-stackexchange {\n  .ie7icon('&#xf16c;');\n}\n\n\n.icon-instagram {\n  .ie7icon('&#xf16d;');\n}\n\n\n.icon-flickr {\n  .ie7icon('&#xf16e;');\n}\n\n\n.icon-adn {\n  .ie7icon('&#xf170;');\n}\n\n\n.icon-bitbucket {\n  .ie7icon('&#xf171;');\n}\n\n\n.icon-bitbucket-sign {\n  .ie7icon('&#xf172;');\n}\n\n\n.icon-tumblr {\n  .ie7icon('&#xf173;');\n}\n\n\n.icon-tumblr-sign {\n  .ie7icon('&#xf174;');\n}\n\n\n.icon-long-arrow-down {\n  .ie7icon('&#xf175;');\n}\n\n\n.icon-long-arrow-up {\n  .ie7icon('&#xf176;');\n}\n\n\n.icon-long-arrow-left {\n  .ie7icon('&#xf177;');\n}\n\n\n.icon-long-arrow-right {\n  .ie7icon('&#xf178;');\n}\n\n\n.icon-apple {\n  .ie7icon('&#xf179;');\n}\n\n\n.icon-windows {\n  .ie7icon('&#xf17a;');\n}\n\n\n.icon-android {\n  .ie7icon('&#xf17b;');\n}\n\n\n.icon-linux {\n  .ie7icon('&#xf17c;');\n}\n\n\n.icon-dribbble {\n  .ie7icon('&#xf17d;');\n}\n\n\n.icon-skype {\n  .ie7icon('&#xf17e;');\n}\n\n\n.icon-foursquare {\n  .ie7icon('&#xf180;');\n}\n\n\n.icon-trello {\n  .ie7icon('&#xf181;');\n}\n\n\n.icon-female {\n  .ie7icon('&#xf182;');\n}\n\n\n.icon-male {\n  .ie7icon('&#xf183;');\n}\n\n\n.icon-gittip {\n  .ie7icon('&#xf184;');\n}\n\n\n.icon-sun {\n  .ie7icon('&#xf185;');\n}\n\n\n.icon-moon {\n  .ie7icon('&#xf186;');\n}\n\n\n.icon-archive {\n  .ie7icon('&#xf187;');\n}\n\n\n.icon-bug {\n  .ie7icon('&#xf188;');\n}\n\n\n.icon-vk {\n  .ie7icon('&#xf189;');\n}\n\n\n.icon-weibo {\n  .ie7icon('&#xf18a;');\n}\n\n\n.icon-renren {\n  .ie7icon('&#xf18b;');\n}\n\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/less/font-awesome.less",
    "content": "/*!\n *  Font Awesome 3.2.1\n *  the iconic font designed for Bootstrap\n *  ------------------------------------------------------------------------------\n *  The full suite of pictographic icons, examples, and documentation can be\n *  found at http://fontawesome.io.  Stay up to date on Twitter at\n *  http://twitter.com/fontawesome.\n *\n *  License\n *  ------------------------------------------------------------------------------\n *  - The Font Awesome font is licensed under SIL OFL 1.1 -\n *    http://scripts.sil.org/OFL\n *  - Font Awesome CSS, LESS, and SASS files are licensed under MIT License -\n *    http://opensource.org/licenses/mit-license.html\n *  - Font Awesome documentation licensed under CC BY 3.0 -\n *    http://creativecommons.org/licenses/by/3.0/\n *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:\n *    \"Font Awesome by Dave Gandy - http://fontawesome.io\"\n *\n *  Author - Dave Gandy\n *  ------------------------------------------------------------------------------\n *  Email: dave@fontawesome.io\n *  Twitter: http://twitter.com/davegandy\n *  Work: Lead Product Designer @ Kyruus - http://kyruus.com\n */\n\n@import \"variables.less\";\n@import \"mixins.less\";\n@import \"path.less\";\n@import \"core.less\";\n@import \"bootstrap.less\";\n@import \"extras.less\";\n@import \"icons.less\";\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/less/icons.less",
    "content": "/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n   readers do not read off random characters that represent icons */\n\n.icon-glass:before { content: @glass; }\n.icon-music:before { content: @music; }\n.icon-search:before { content: @search; }\n.icon-envelope-alt:before { content: @envelope-alt; }\n.icon-heart:before { content: @heart; }\n.icon-star:before { content: @star; }\n.icon-star-empty:before { content: @star-empty; }\n.icon-user:before { content: @user; }\n.icon-film:before { content: @film; }\n.icon-th-large:before { content: @th-large; }\n.icon-th:before { content: @th; }\n.icon-th-list:before { content: @th-list; }\n.icon-ok:before { content: @ok; }\n.icon-remove:before { content: @remove; }\n.icon-zoom-in:before { content: @zoom-in; }\n.icon-zoom-out:before { content: @zoom-out; }\n.icon-power-off:before,\n.icon-off:before { content: @off; }\n.icon-signal:before { content: @signal; }\n.icon-gear:before,\n.icon-cog:before { content: @cog; }\n.icon-trash:before { content: @trash; }\n.icon-home:before { content: @home; }\n.icon-file-alt:before { content: @file-alt; }\n.icon-time:before { content: @time; }\n.icon-road:before { content: @road; }\n.icon-download-alt:before { content: @download-alt; }\n.icon-download:before { content: @download; }\n.icon-upload:before { content: @upload; }\n.icon-inbox:before { content: @inbox; }\n.icon-play-circle:before { content: @play-circle; }\n.icon-rotate-right:before,\n.icon-repeat:before { content: @repeat; }\n.icon-refresh:before { content: @refresh; }\n.icon-list-alt:before { content: @list-alt; }\n.icon-lock:before { content: @lock; }\n.icon-flag:before { content: @flag; }\n.icon-headphones:before { content: @headphones; }\n.icon-volume-off:before { content: @volume-off; }\n.icon-volume-down:before { content: @volume-down; }\n.icon-volume-up:before { content: @volume-up; }\n.icon-qrcode:before { content: @qrcode; }\n.icon-barcode:before { content: @barcode; }\n.icon-tag:before { content: @tag; }\n.icon-tags:before { content: @tags; }\n.icon-book:before { content: @book; }\n.icon-bookmark:before { content: @bookmark; }\n.icon-print:before { content: @print; }\n.icon-camera:before { content: @camera; }\n.icon-font:before { content: @font; }\n.icon-bold:before { content: @bold; }\n.icon-italic:before { content: @italic; }\n.icon-text-height:before { content: @text-height; }\n.icon-text-width:before { content: @text-width; }\n.icon-align-left:before { content: @align-left; }\n.icon-align-center:before { content: @align-center; }\n.icon-align-right:before { content: @align-right; }\n.icon-align-justify:before { content: @align-justify; }\n.icon-list:before { content: @list; }\n.icon-indent-left:before { content: @indent-left; }\n.icon-indent-right:before { content: @indent-right; }\n.icon-facetime-video:before { content: @facetime-video; }\n.icon-picture:before { content: @picture; }\n.icon-pencil:before { content: @pencil; }\n.icon-map-marker:before { content: @map-marker; }\n.icon-adjust:before { content: @adjust; }\n.icon-tint:before { content: @tint; }\n.icon-edit:before { content: @edit; }\n.icon-share:before { content: @share; }\n.icon-check:before { content: @check; }\n.icon-move:before { content: @move; }\n.icon-step-backward:before { content: @step-backward; }\n.icon-fast-backward:before { content: @fast-backward; }\n.icon-backward:before { content: @backward; }\n.icon-play:before { content: @play; }\n.icon-pause:before { content: @pause; }\n.icon-stop:before { content: @stop; }\n.icon-forward:before { content: @forward; }\n.icon-fast-forward:before { content: @fast-forward; }\n.icon-step-forward:before { content: @step-forward; }\n.icon-eject:before { content: @eject; }\n.icon-chevron-left:before { content: @chevron-left; }\n.icon-chevron-right:before { content: @chevron-right; }\n.icon-plus-sign:before { content: @plus-sign; }\n.icon-minus-sign:before { content: @minus-sign; }\n.icon-remove-sign:before { content: @remove-sign; }\n.icon-ok-sign:before { content: @ok-sign; }\n.icon-question-sign:before { content: @question-sign; }\n.icon-info-sign:before { content: @info-sign; }\n.icon-screenshot:before { content: @screenshot; }\n.icon-remove-circle:before { content: @remove-circle; }\n.icon-ok-circle:before { content: @ok-circle; }\n.icon-ban-circle:before { content: @ban-circle; }\n.icon-arrow-left:before { content: @arrow-left; }\n.icon-arrow-right:before { content: @arrow-right; }\n.icon-arrow-up:before { content: @arrow-up; }\n.icon-arrow-down:before { content: @arrow-down; }\n.icon-mail-forward:before,\n.icon-share-alt:before { content: @share-alt; }\n.icon-resize-full:before { content: @resize-full; }\n.icon-resize-small:before { content: @resize-small; }\n.icon-plus:before { content: @plus; }\n.icon-minus:before { content: @minus; }\n.icon-asterisk:before { content: @asterisk; }\n.icon-exclamation-sign:before { content: @exclamation-sign; }\n.icon-gift:before { content: @gift; }\n.icon-leaf:before { content: @leaf; }\n.icon-fire:before { content: @fire; }\n.icon-eye-open:before { content: @eye-open; }\n.icon-eye-close:before { content: @eye-close; }\n.icon-warning-sign:before { content: @warning-sign; }\n.icon-plane:before { content: @plane; }\n.icon-calendar:before { content: @calendar; }\n.icon-random:before { content: @random; }\n.icon-comment:before { content: @comment; }\n.icon-magnet:before { content: @magnet; }\n.icon-chevron-up:before { content: @chevron-up; }\n.icon-chevron-down:before { content: @chevron-down; }\n.icon-retweet:before { content: @retweet; }\n.icon-shopping-cart:before { content: @shopping-cart; }\n.icon-folder-close:before { content: @folder-close; }\n.icon-folder-open:before { content: @folder-open; }\n.icon-resize-vertical:before { content: @resize-vertical; }\n.icon-resize-horizontal:before { content: @resize-horizontal; }\n.icon-bar-chart:before { content: @bar-chart; }\n.icon-twitter-sign:before { content: @twitter-sign; }\n.icon-facebook-sign:before { content: @facebook-sign; }\n.icon-camera-retro:before { content: @camera-retro; }\n.icon-key:before { content: @key; }\n.icon-gears:before,\n.icon-cogs:before { content: @cogs; }\n.icon-comments:before { content: @comments; }\n.icon-thumbs-up-alt:before { content: @thumbs-up-alt; }\n.icon-thumbs-down-alt:before { content: @thumbs-down-alt; }\n.icon-star-half:before { content: @star-half; }\n.icon-heart-empty:before { content: @heart-empty; }\n.icon-signout:before { content: @signout; }\n.icon-linkedin-sign:before { content: @linkedin-sign; }\n.icon-pushpin:before { content: @pushpin; }\n.icon-external-link:before { content: @external-link; }\n.icon-signin:before { content: @signin; }\n.icon-trophy:before { content: @trophy; }\n.icon-github-sign:before { content: @github-sign; }\n.icon-upload-alt:before { content: @upload-alt; }\n.icon-lemon:before { content: @lemon; }\n.icon-phone:before { content: @phone; }\n.icon-unchecked:before,\n.icon-check-empty:before { content: @check-empty; }\n.icon-bookmark-empty:before { content: @bookmark-empty; }\n.icon-phone-sign:before { content: @phone-sign; }\n.icon-twitter:before { content: @twitter; }\n.icon-facebook:before { content: @facebook; }\n.icon-github:before { content: @github; }\n.icon-unlock:before { content: @unlock; }\n.icon-credit-card:before { content: @credit-card; }\n.icon-rss:before { content: @rss; }\n.icon-hdd:before { content: @hdd; }\n.icon-bullhorn:before { content: @bullhorn; }\n.icon-bell:before { content: @bell; }\n.icon-certificate:before { content: @certificate; }\n.icon-hand-right:before { content: @hand-right; }\n.icon-hand-left:before { content: @hand-left; }\n.icon-hand-up:before { content: @hand-up; }\n.icon-hand-down:before { content: @hand-down; }\n.icon-circle-arrow-left:before { content: @circle-arrow-left; }\n.icon-circle-arrow-right:before { content: @circle-arrow-right; }\n.icon-circle-arrow-up:before { content: @circle-arrow-up; }\n.icon-circle-arrow-down:before { content: @circle-arrow-down; }\n.icon-globe:before { content: @globe; }\n.icon-wrench:before { content: @wrench; }\n.icon-tasks:before { content: @tasks; }\n.icon-filter:before { content: @filter; }\n.icon-briefcase:before { content: @briefcase; }\n.icon-fullscreen:before { content: @fullscreen; }\n.icon-group:before { content: @group; }\n.icon-link:before { content: @link; }\n.icon-cloud:before { content: @cloud; }\n.icon-beaker:before { content: @beaker; }\n.icon-cut:before { content: @cut; }\n.icon-copy:before { content: @copy; }\n.icon-paperclip:before,\n.icon-paper-clip:before { content: @paper-clip; }\n.icon-save:before { content: @save; }\n.icon-sign-blank:before { content: @sign-blank; }\n.icon-reorder:before { content: @reorder; }\n.icon-list-ul:before { content: @list-ul; }\n.icon-list-ol:before { content: @list-ol; }\n.icon-strikethrough:before { content: @strikethrough; }\n.icon-underline:before { content: @underline; }\n.icon-table:before { content: @table; }\n.icon-magic:before { content: @magic; }\n.icon-truck:before { content: @truck; }\n.icon-pinterest:before { content: @pinterest; }\n.icon-pinterest-sign:before { content: @pinterest-sign; }\n.icon-google-plus-sign:before { content: @google-plus-sign; }\n.icon-google-plus:before { content: @google-plus; }\n.icon-money:before { content: @money; }\n.icon-caret-down:before { content: @caret-down; }\n.icon-caret-up:before { content: @caret-up; }\n.icon-caret-left:before { content: @caret-left; }\n.icon-caret-right:before { content: @caret-right; }\n.icon-columns:before { content: @columns; }\n.icon-sort:before { content: @sort; }\n.icon-sort-down:before { content: @sort-down; }\n.icon-sort-up:before { content: @sort-up; }\n.icon-envelope:before { content: @envelope; }\n.icon-linkedin:before { content: @linkedin; }\n.icon-rotate-left:before,\n.icon-undo:before { content: @undo; }\n.icon-legal:before { content: @legal; }\n.icon-dashboard:before { content: @dashboard; }\n.icon-comment-alt:before { content: @comment-alt; }\n.icon-comments-alt:before { content: @comments-alt; }\n.icon-bolt:before { content: @bolt; }\n.icon-sitemap:before { content: @sitemap; }\n.icon-umbrella:before { content: @umbrella; }\n.icon-paste:before { content: @paste; }\n.icon-lightbulb:before { content: @lightbulb; }\n.icon-exchange:before { content: @exchange; }\n.icon-cloud-download:before { content: @cloud-download; }\n.icon-cloud-upload:before { content: @cloud-upload; }\n.icon-user-md:before { content: @user-md; }\n.icon-stethoscope:before { content: @stethoscope; }\n.icon-suitcase:before { content: @suitcase; }\n.icon-bell-alt:before { content: @bell-alt; }\n.icon-coffee:before { content: @coffee; }\n.icon-food:before { content: @food; }\n.icon-file-text-alt:before { content: @file-text-alt; }\n.icon-building:before { content: @building; }\n.icon-hospital:before { content: @hospital; }\n.icon-ambulance:before { content: @ambulance; }\n.icon-medkit:before { content: @medkit; }\n.icon-fighter-jet:before { content: @fighter-jet; }\n.icon-beer:before { content: @beer; }\n.icon-h-sign:before { content: @h-sign; }\n.icon-plus-sign-alt:before { content: @plus-sign-alt; }\n.icon-double-angle-left:before { content: @double-angle-left; }\n.icon-double-angle-right:before { content: @double-angle-right; }\n.icon-double-angle-up:before { content: @double-angle-up; }\n.icon-double-angle-down:before { content: @double-angle-down; }\n.icon-angle-left:before { content: @angle-left; }\n.icon-angle-right:before { content: @angle-right; }\n.icon-angle-up:before { content: @angle-up; }\n.icon-angle-down:before { content: @angle-down; }\n.icon-desktop:before { content: @desktop; }\n.icon-laptop:before { content: @laptop; }\n.icon-tablet:before { content: @tablet; }\n.icon-mobile-phone:before { content: @mobile-phone; }\n.icon-circle-blank:before { content: @circle-blank; }\n.icon-quote-left:before { content: @quote-left; }\n.icon-quote-right:before { content: @quote-right; }\n.icon-spinner:before { content: @spinner; }\n.icon-circle:before { content: @circle; }\n.icon-mail-reply:before,\n.icon-reply:before { content: @reply; }\n.icon-github-alt:before { content: @github-alt; }\n.icon-folder-close-alt:before { content: @folder-close-alt; }\n.icon-folder-open-alt:before { content: @folder-open-alt; }\n.icon-expand-alt:before { content: @expand-alt; }\n.icon-collapse-alt:before { content: @collapse-alt; }\n.icon-smile:before { content: @smile; }\n.icon-frown:before { content: @frown; }\n.icon-meh:before { content: @meh; }\n.icon-gamepad:before { content: @gamepad; }\n.icon-keyboard:before { content: @keyboard; }\n.icon-flag-alt:before { content: @flag-alt; }\n.icon-flag-checkered:before { content: @flag-checkered; }\n.icon-terminal:before { content: @terminal; }\n.icon-code:before { content: @code; }\n.icon-reply-all:before { content: @reply-all; }\n.icon-mail-reply-all:before { content: @mail-reply-all; }\n.icon-star-half-full:before,\n.icon-star-half-empty:before { content: @star-half-empty; }\n.icon-location-arrow:before { content: @location-arrow; }\n.icon-crop:before { content: @crop; }\n.icon-code-fork:before { content: @code-fork; }\n.icon-unlink:before { content: @unlink; }\n.icon-question:before { content: @question; }\n.icon-info:before { content: @info; }\n.icon-exclamation:before { content: @exclamation; }\n.icon-superscript:before { content: @superscript; }\n.icon-subscript:before { content: @subscript; }\n.icon-eraser:before { content: @eraser; }\n.icon-puzzle-piece:before { content: @puzzle-piece; }\n.icon-microphone:before { content: @microphone; }\n.icon-microphone-off:before { content: @microphone-off; }\n.icon-shield:before { content: @shield; }\n.icon-calendar-empty:before { content: @calendar-empty; }\n.icon-fire-extinguisher:before { content: @fire-extinguisher; }\n.icon-rocket:before { content: @rocket; }\n.icon-maxcdn:before { content: @maxcdn; }\n.icon-chevron-sign-left:before { content: @chevron-sign-left; }\n.icon-chevron-sign-right:before { content: @chevron-sign-right; }\n.icon-chevron-sign-up:before { content: @chevron-sign-up; }\n.icon-chevron-sign-down:before { content: @chevron-sign-down; }\n.icon-html5:before { content: @html5; }\n.icon-css3:before { content: @css3; }\n.icon-anchor:before { content: @anchor; }\n.icon-unlock-alt:before { content: @unlock-alt; }\n.icon-bullseye:before { content: @bullseye; }\n.icon-ellipsis-horizontal:before { content: @ellipsis-horizontal; }\n.icon-ellipsis-vertical:before { content: @ellipsis-vertical; }\n.icon-rss-sign:before { content: @rss-sign; }\n.icon-play-sign:before { content: @play-sign; }\n.icon-ticket:before { content: @ticket; }\n.icon-minus-sign-alt:before { content: @minus-sign-alt; }\n.icon-check-minus:before { content: @check-minus; }\n.icon-level-up:before { content: @level-up; }\n.icon-level-down:before { content: @level-down; }\n.icon-check-sign:before { content: @check-sign; }\n.icon-edit-sign:before { content: @edit-sign; }\n.icon-external-link-sign:before { content: @external-link-sign; }\n.icon-share-sign:before { content: @share-sign; }\n.icon-compass:before { content: @compass; }\n.icon-collapse:before { content: @collapse; }\n.icon-collapse-top:before { content: @collapse-top; }\n.icon-expand:before { content: @expand; }\n.icon-euro:before,\n.icon-eur:before { content: @eur; }\n.icon-gbp:before { content: @gbp; }\n.icon-dollar:before,\n.icon-usd:before { content: @usd; }\n.icon-rupee:before,\n.icon-inr:before { content: @inr; }\n.icon-yen:before,\n.icon-jpy:before { content: @jpy; }\n.icon-renminbi:before,\n.icon-cny:before { content: @cny; }\n.icon-won:before,\n.icon-krw:before { content: @krw; }\n.icon-bitcoin:before,\n.icon-btc:before { content: @btc; }\n.icon-file:before { content: @file; }\n.icon-file-text:before { content: @file-text; }\n.icon-sort-by-alphabet:before { content: @sort-by-alphabet; }\n.icon-sort-by-alphabet-alt:before { content: @sort-by-alphabet-alt; }\n.icon-sort-by-attributes:before { content: @sort-by-attributes; }\n.icon-sort-by-attributes-alt:before { content: @sort-by-attributes-alt; }\n.icon-sort-by-order:before { content: @sort-by-order; }\n.icon-sort-by-order-alt:before { content: @sort-by-order-alt; }\n.icon-thumbs-up:before { content: @thumbs-up; }\n.icon-thumbs-down:before { content: @thumbs-down; }\n.icon-youtube-sign:before { content: @youtube-sign; }\n.icon-youtube:before { content: @youtube; }\n.icon-xing:before { content: @xing; }\n.icon-xing-sign:before { content: @xing-sign; }\n.icon-youtube-play:before { content: @youtube-play; }\n.icon-dropbox:before { content: @dropbox; }\n.icon-stackexchange:before { content: @stackexchange; }\n.icon-instagram:before { content: @instagram; }\n.icon-flickr:before { content: @flickr; }\n.icon-adn:before { content: @adn; }\n.icon-bitbucket:before { content: @bitbucket; }\n.icon-bitbucket-sign:before { content: @bitbucket-sign; }\n.icon-tumblr:before { content: @tumblr; }\n.icon-tumblr-sign:before { content: @tumblr-sign; }\n.icon-long-arrow-down:before { content: @long-arrow-down; }\n.icon-long-arrow-up:before { content: @long-arrow-up; }\n.icon-long-arrow-left:before { content: @long-arrow-left; }\n.icon-long-arrow-right:before { content: @long-arrow-right; }\n.icon-apple:before { content: @apple; }\n.icon-windows:before { content: @windows; }\n.icon-android:before { content: @android; }\n.icon-linux:before { content: @linux; }\n.icon-dribbble:before { content: @dribbble; }\n.icon-skype:before { content: @skype; }\n.icon-foursquare:before { content: @foursquare; }\n.icon-trello:before { content: @trello; }\n.icon-female:before { content: @female; }\n.icon-male:before { content: @male; }\n.icon-gittip:before { content: @gittip; }\n.icon-sun:before { content: @sun; }\n.icon-moon:before { content: @moon; }\n.icon-archive:before { content: @archive; }\n.icon-bug:before { content: @bug; }\n.icon-vk:before { content: @vk; }\n.icon-weibo:before { content: @weibo; }\n.icon-renren:before { content: @renren; }\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/less/mixins.less",
    "content": "// Mixins\n// --------------------------\n\n.icon(@icon) {\n  .icon-FontAwesome();\n  content: @icon;\n}\n\n.icon-FontAwesome() {\n  font-family: FontAwesome;\n  font-weight: normal;\n  font-style: normal;\n  text-decoration: inherit;\n  -webkit-font-smoothing: antialiased;\n  *margin-right: .3em; // fixes ie7 issues\n}\n\n.border-radius(@radius) {\n  -webkit-border-radius: @radius;\n  -moz-border-radius: @radius;\n  border-radius: @radius;\n}\n\n.icon-stack(@width: 2em, @height: 2em, @top-font-size: 1em, @base-font-size: 2em) {\n  .icon-stack {\n    position: relative;\n    display: inline-block;\n    width: @width;\n    height: @height;\n    line-height: @width;\n    vertical-align: -35%;\n    [class^=\"icon-\"],\n    [class*=\" icon-\"] {\n      display: block;\n      text-align: center;\n      position: absolute;\n      width: 100%;\n      height: 100%;\n      font-size: @top-font-size;\n      line-height: inherit;\n      *line-height: @height;\n    }\n    .icon-stack-base {\n      font-size: @base-font-size;\n      *line-height: @height / @base-font-size;\n    }\n  }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/less/path.less",
    "content": "/* FONT PATH\n * -------------------------- */\n\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('@{FontAwesomePath}/fontawesome-webfont.eot?v=@{FontAwesomeVersion}');\n  src: url('@{FontAwesomePath}/fontawesome-webfont.eot?#iefix&v=@{FontAwesomeVersion}') format('embedded-opentype'),\n    url('@{FontAwesomePath}/fontawesome-webfont.woff?v=@{FontAwesomeVersion}') format('woff'),\n    url('@{FontAwesomePath}/fontawesome-webfont.ttf?v=@{FontAwesomeVersion}') format('truetype'),\n    url('@{FontAwesomePath}/fontawesome-webfont.svg#fontawesomeregular?v=@{FontAwesomeVersion}') format('svg');\n//  src: url('@{FontAwesomePath}/FontAwesome.otf') format('opentype'); // used when developing fonts\n  font-weight: normal;\n  font-style: normal;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/less/variables.less",
    "content": "// Variables\n// --------------------------\n\n@FontAwesomePath:    \"../font\";\n//@FontAwesomePath:    \"//netdna.bootstrapcdn.com/font-awesome/3.2.1/font\"; // for referencing Bootstrap CDN font files directly\n@FontAwesomeVersion: \"3.2.1\";\n@borderColor:        #eee;\n@iconMuted:          #eee;\n@iconLight:          #fff;\n@iconDark:           #333;\n@icons-li-width:     30/14em;\n\n\n  @glass: \"\\f000\";\n\n  @music: \"\\f001\";\n\n  @search: \"\\f002\";\n\n  @envelope-alt: \"\\f003\";\n\n  @heart: \"\\f004\";\n\n  @star: \"\\f005\";\n\n  @star-empty: \"\\f006\";\n\n  @user: \"\\f007\";\n\n  @film: \"\\f008\";\n\n  @th-large: \"\\f009\";\n\n  @th: \"\\f00a\";\n\n  @th-list: \"\\f00b\";\n\n  @ok: \"\\f00c\";\n\n  @remove: \"\\f00d\";\n\n  @zoom-in: \"\\f00e\";\n\n  @zoom-out: \"\\f010\";\n\n  @off: \"\\f011\";\n\n  @signal: \"\\f012\";\n\n  @cog: \"\\f013\";\n\n  @trash: \"\\f014\";\n\n  @home: \"\\f015\";\n\n  @file-alt: \"\\f016\";\n\n  @time: \"\\f017\";\n\n  @road: \"\\f018\";\n\n  @download-alt: \"\\f019\";\n\n  @download: \"\\f01a\";\n\n  @upload: \"\\f01b\";\n\n  @inbox: \"\\f01c\";\n\n  @play-circle: \"\\f01d\";\n\n  @repeat: \"\\f01e\";\n\n  @refresh: \"\\f021\";\n\n  @list-alt: \"\\f022\";\n\n  @lock: \"\\f023\";\n\n  @flag: \"\\f024\";\n\n  @headphones: \"\\f025\";\n\n  @volume-off: \"\\f026\";\n\n  @volume-down: \"\\f027\";\n\n  @volume-up: \"\\f028\";\n\n  @qrcode: \"\\f029\";\n\n  @barcode: \"\\f02a\";\n\n  @tag: \"\\f02b\";\n\n  @tags: \"\\f02c\";\n\n  @book: \"\\f02d\";\n\n  @bookmark: \"\\f02e\";\n\n  @print: \"\\f02f\";\n\n  @camera: \"\\f030\";\n\n  @font: \"\\f031\";\n\n  @bold: \"\\f032\";\n\n  @italic: \"\\f033\";\n\n  @text-height: \"\\f034\";\n\n  @text-width: \"\\f035\";\n\n  @align-left: \"\\f036\";\n\n  @align-center: \"\\f037\";\n\n  @align-right: \"\\f038\";\n\n  @align-justify: \"\\f039\";\n\n  @list: \"\\f03a\";\n\n  @indent-left: \"\\f03b\";\n\n  @indent-right: \"\\f03c\";\n\n  @facetime-video: \"\\f03d\";\n\n  @picture: \"\\f03e\";\n\n  @pencil: \"\\f040\";\n\n  @map-marker: \"\\f041\";\n\n  @adjust: \"\\f042\";\n\n  @tint: \"\\f043\";\n\n  @edit: \"\\f044\";\n\n  @share: \"\\f045\";\n\n  @check: \"\\f046\";\n\n  @move: \"\\f047\";\n\n  @step-backward: \"\\f048\";\n\n  @fast-backward: \"\\f049\";\n\n  @backward: \"\\f04a\";\n\n  @play: \"\\f04b\";\n\n  @pause: \"\\f04c\";\n\n  @stop: \"\\f04d\";\n\n  @forward: \"\\f04e\";\n\n  @fast-forward: \"\\f050\";\n\n  @step-forward: \"\\f051\";\n\n  @eject: \"\\f052\";\n\n  @chevron-left: \"\\f053\";\n\n  @chevron-right: \"\\f054\";\n\n  @plus-sign: \"\\f055\";\n\n  @minus-sign: \"\\f056\";\n\n  @remove-sign: \"\\f057\";\n\n  @ok-sign: \"\\f058\";\n\n  @question-sign: \"\\f059\";\n\n  @info-sign: \"\\f05a\";\n\n  @screenshot: \"\\f05b\";\n\n  @remove-circle: \"\\f05c\";\n\n  @ok-circle: \"\\f05d\";\n\n  @ban-circle: \"\\f05e\";\n\n  @arrow-left: \"\\f060\";\n\n  @arrow-right: \"\\f061\";\n\n  @arrow-up: \"\\f062\";\n\n  @arrow-down: \"\\f063\";\n\n  @share-alt: \"\\f064\";\n\n  @resize-full: \"\\f065\";\n\n  @resize-small: \"\\f066\";\n\n  @plus: \"\\f067\";\n\n  @minus: \"\\f068\";\n\n  @asterisk: \"\\f069\";\n\n  @exclamation-sign: \"\\f06a\";\n\n  @gift: \"\\f06b\";\n\n  @leaf: \"\\f06c\";\n\n  @fire: \"\\f06d\";\n\n  @eye-open: \"\\f06e\";\n\n  @eye-close: \"\\f070\";\n\n  @warning-sign: \"\\f071\";\n\n  @plane: \"\\f072\";\n\n  @calendar: \"\\f073\";\n\n  @random: \"\\f074\";\n\n  @comment: \"\\f075\";\n\n  @magnet: \"\\f076\";\n\n  @chevron-up: \"\\f077\";\n\n  @chevron-down: \"\\f078\";\n\n  @retweet: \"\\f079\";\n\n  @shopping-cart: \"\\f07a\";\n\n  @folder-close: \"\\f07b\";\n\n  @folder-open: \"\\f07c\";\n\n  @resize-vertical: \"\\f07d\";\n\n  @resize-horizontal: \"\\f07e\";\n\n  @bar-chart: \"\\f080\";\n\n  @twitter-sign: \"\\f081\";\n\n  @facebook-sign: \"\\f082\";\n\n  @camera-retro: \"\\f083\";\n\n  @key: \"\\f084\";\n\n  @cogs: \"\\f085\";\n\n  @comments: \"\\f086\";\n\n  @thumbs-up-alt: \"\\f087\";\n\n  @thumbs-down-alt: \"\\f088\";\n\n  @star-half: \"\\f089\";\n\n  @heart-empty: \"\\f08a\";\n\n  @signout: \"\\f08b\";\n\n  @linkedin-sign: \"\\f08c\";\n\n  @pushpin: \"\\f08d\";\n\n  @external-link: \"\\f08e\";\n\n  @signin: \"\\f090\";\n\n  @trophy: \"\\f091\";\n\n  @github-sign: \"\\f092\";\n\n  @upload-alt: \"\\f093\";\n\n  @lemon: \"\\f094\";\n\n  @phone: \"\\f095\";\n\n  @check-empty: \"\\f096\";\n\n  @bookmark-empty: \"\\f097\";\n\n  @phone-sign: \"\\f098\";\n\n  @twitter: \"\\f099\";\n\n  @facebook: \"\\f09a\";\n\n  @github: \"\\f09b\";\n\n  @unlock: \"\\f09c\";\n\n  @credit-card: \"\\f09d\";\n\n  @rss: \"\\f09e\";\n\n  @hdd: \"\\f0a0\";\n\n  @bullhorn: \"\\f0a1\";\n\n  @bell: \"\\f0a2\";\n\n  @certificate: \"\\f0a3\";\n\n  @hand-right: \"\\f0a4\";\n\n  @hand-left: \"\\f0a5\";\n\n  @hand-up: \"\\f0a6\";\n\n  @hand-down: \"\\f0a7\";\n\n  @circle-arrow-left: \"\\f0a8\";\n\n  @circle-arrow-right: \"\\f0a9\";\n\n  @circle-arrow-up: \"\\f0aa\";\n\n  @circle-arrow-down: \"\\f0ab\";\n\n  @globe: \"\\f0ac\";\n\n  @wrench: \"\\f0ad\";\n\n  @tasks: \"\\f0ae\";\n\n  @filter: \"\\f0b0\";\n\n  @briefcase: \"\\f0b1\";\n\n  @fullscreen: \"\\f0b2\";\n\n  @group: \"\\f0c0\";\n\n  @link: \"\\f0c1\";\n\n  @cloud: \"\\f0c2\";\n\n  @beaker: \"\\f0c3\";\n\n  @cut: \"\\f0c4\";\n\n  @copy: \"\\f0c5\";\n\n  @paper-clip: \"\\f0c6\";\n\n  @save: \"\\f0c7\";\n\n  @sign-blank: \"\\f0c8\";\n\n  @reorder: \"\\f0c9\";\n\n  @list-ul: \"\\f0ca\";\n\n  @list-ol: \"\\f0cb\";\n\n  @strikethrough: \"\\f0cc\";\n\n  @underline: \"\\f0cd\";\n\n  @table: \"\\f0ce\";\n\n  @magic: \"\\f0d0\";\n\n  @truck: \"\\f0d1\";\n\n  @pinterest: \"\\f0d2\";\n\n  @pinterest-sign: \"\\f0d3\";\n\n  @google-plus-sign: \"\\f0d4\";\n\n  @google-plus: \"\\f0d5\";\n\n  @money: \"\\f0d6\";\n\n  @caret-down: \"\\f0d7\";\n\n  @caret-up: \"\\f0d8\";\n\n  @caret-left: \"\\f0d9\";\n\n  @caret-right: \"\\f0da\";\n\n  @columns: \"\\f0db\";\n\n  @sort: \"\\f0dc\";\n\n  @sort-down: \"\\f0dd\";\n\n  @sort-up: \"\\f0de\";\n\n  @envelope: \"\\f0e0\";\n\n  @linkedin: \"\\f0e1\";\n\n  @undo: \"\\f0e2\";\n\n  @legal: \"\\f0e3\";\n\n  @dashboard: \"\\f0e4\";\n\n  @comment-alt: \"\\f0e5\";\n\n  @comments-alt: \"\\f0e6\";\n\n  @bolt: \"\\f0e7\";\n\n  @sitemap: \"\\f0e8\";\n\n  @umbrella: \"\\f0e9\";\n\n  @paste: \"\\f0ea\";\n\n  @lightbulb: \"\\f0eb\";\n\n  @exchange: \"\\f0ec\";\n\n  @cloud-download: \"\\f0ed\";\n\n  @cloud-upload: \"\\f0ee\";\n\n  @user-md: \"\\f0f0\";\n\n  @stethoscope: \"\\f0f1\";\n\n  @suitcase: \"\\f0f2\";\n\n  @bell-alt: \"\\f0f3\";\n\n  @coffee: \"\\f0f4\";\n\n  @food: \"\\f0f5\";\n\n  @file-text-alt: \"\\f0f6\";\n\n  @building: \"\\f0f7\";\n\n  @hospital: \"\\f0f8\";\n\n  @ambulance: \"\\f0f9\";\n\n  @medkit: \"\\f0fa\";\n\n  @fighter-jet: \"\\f0fb\";\n\n  @beer: \"\\f0fc\";\n\n  @h-sign: \"\\f0fd\";\n\n  @plus-sign-alt: \"\\f0fe\";\n\n  @double-angle-left: \"\\f100\";\n\n  @double-angle-right: \"\\f101\";\n\n  @double-angle-up: \"\\f102\";\n\n  @double-angle-down: \"\\f103\";\n\n  @angle-left: \"\\f104\";\n\n  @angle-right: \"\\f105\";\n\n  @angle-up: \"\\f106\";\n\n  @angle-down: \"\\f107\";\n\n  @desktop: \"\\f108\";\n\n  @laptop: \"\\f109\";\n\n  @tablet: \"\\f10a\";\n\n  @mobile-phone: \"\\f10b\";\n\n  @circle-blank: \"\\f10c\";\n\n  @quote-left: \"\\f10d\";\n\n  @quote-right: \"\\f10e\";\n\n  @spinner: \"\\f110\";\n\n  @circle: \"\\f111\";\n\n  @reply: \"\\f112\";\n\n  @github-alt: \"\\f113\";\n\n  @folder-close-alt: \"\\f114\";\n\n  @folder-open-alt: \"\\f115\";\n\n  @expand-alt: \"\\f116\";\n\n  @collapse-alt: \"\\f117\";\n\n  @smile: \"\\f118\";\n\n  @frown: \"\\f119\";\n\n  @meh: \"\\f11a\";\n\n  @gamepad: \"\\f11b\";\n\n  @keyboard: \"\\f11c\";\n\n  @flag-alt: \"\\f11d\";\n\n  @flag-checkered: \"\\f11e\";\n\n  @terminal: \"\\f120\";\n\n  @code: \"\\f121\";\n\n  @reply-all: \"\\f122\";\n\n  @mail-reply-all: \"\\f122\";\n\n  @star-half-empty: \"\\f123\";\n\n  @location-arrow: \"\\f124\";\n\n  @crop: \"\\f125\";\n\n  @code-fork: \"\\f126\";\n\n  @unlink: \"\\f127\";\n\n  @question: \"\\f128\";\n\n  @info: \"\\f129\";\n\n  @exclamation: \"\\f12a\";\n\n  @superscript: \"\\f12b\";\n\n  @subscript: \"\\f12c\";\n\n  @eraser: \"\\f12d\";\n\n  @puzzle-piece: \"\\f12e\";\n\n  @microphone: \"\\f130\";\n\n  @microphone-off: \"\\f131\";\n\n  @shield: \"\\f132\";\n\n  @calendar-empty: \"\\f133\";\n\n  @fire-extinguisher: \"\\f134\";\n\n  @rocket: \"\\f135\";\n\n  @maxcdn: \"\\f136\";\n\n  @chevron-sign-left: \"\\f137\";\n\n  @chevron-sign-right: \"\\f138\";\n\n  @chevron-sign-up: \"\\f139\";\n\n  @chevron-sign-down: \"\\f13a\";\n\n  @html5: \"\\f13b\";\n\n  @css3: \"\\f13c\";\n\n  @anchor: \"\\f13d\";\n\n  @unlock-alt: \"\\f13e\";\n\n  @bullseye: \"\\f140\";\n\n  @ellipsis-horizontal: \"\\f141\";\n\n  @ellipsis-vertical: \"\\f142\";\n\n  @rss-sign: \"\\f143\";\n\n  @play-sign: \"\\f144\";\n\n  @ticket: \"\\f145\";\n\n  @minus-sign-alt: \"\\f146\";\n\n  @check-minus: \"\\f147\";\n\n  @level-up: \"\\f148\";\n\n  @level-down: \"\\f149\";\n\n  @check-sign: \"\\f14a\";\n\n  @edit-sign: \"\\f14b\";\n\n  @external-link-sign: \"\\f14c\";\n\n  @share-sign: \"\\f14d\";\n\n  @compass: \"\\f14e\";\n\n  @collapse: \"\\f150\";\n\n  @collapse-top: \"\\f151\";\n\n  @expand: \"\\f152\";\n\n  @eur: \"\\f153\";\n\n  @gbp: \"\\f154\";\n\n  @usd: \"\\f155\";\n\n  @inr: \"\\f156\";\n\n  @jpy: \"\\f157\";\n\n  @cny: \"\\f158\";\n\n  @krw: \"\\f159\";\n\n  @btc: \"\\f15a\";\n\n  @file: \"\\f15b\";\n\n  @file-text: \"\\f15c\";\n\n  @sort-by-alphabet: \"\\f15d\";\n\n  @sort-by-alphabet-alt: \"\\f15e\";\n\n  @sort-by-attributes: \"\\f160\";\n\n  @sort-by-attributes-alt: \"\\f161\";\n\n  @sort-by-order: \"\\f162\";\n\n  @sort-by-order-alt: \"\\f163\";\n\n  @thumbs-up: \"\\f164\";\n\n  @thumbs-down: \"\\f165\";\n\n  @youtube-sign: \"\\f166\";\n\n  @youtube: \"\\f167\";\n\n  @xing: \"\\f168\";\n\n  @xing-sign: \"\\f169\";\n\n  @youtube-play: \"\\f16a\";\n\n  @dropbox: \"\\f16b\";\n\n  @stackexchange: \"\\f16c\";\n\n  @instagram: \"\\f16d\";\n\n  @flickr: \"\\f16e\";\n\n  @adn: \"\\f170\";\n\n  @bitbucket: \"\\f171\";\n\n  @bitbucket-sign: \"\\f172\";\n\n  @tumblr: \"\\f173\";\n\n  @tumblr-sign: \"\\f174\";\n\n  @long-arrow-down: \"\\f175\";\n\n  @long-arrow-up: \"\\f176\";\n\n  @long-arrow-left: \"\\f177\";\n\n  @long-arrow-right: \"\\f178\";\n\n  @apple: \"\\f179\";\n\n  @windows: \"\\f17a\";\n\n  @android: \"\\f17b\";\n\n  @linux: \"\\f17c\";\n\n  @dribbble: \"\\f17d\";\n\n  @skype: \"\\f17e\";\n\n  @foursquare: \"\\f180\";\n\n  @trello: \"\\f181\";\n\n  @female: \"\\f182\";\n\n  @male: \"\\f183\";\n\n  @gittip: \"\\f184\";\n\n  @sun: \"\\f185\";\n\n  @moon: \"\\f186\";\n\n  @archive: \"\\f187\";\n\n  @bug: \"\\f188\";\n\n  @vk: \"\\f189\";\n\n  @weibo: \"\\f18a\";\n\n  @renren: \"\\f18b\";\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/scss/_bootstrap.scss",
    "content": "/* BOOTSTRAP SPECIFIC CLASSES\n * -------------------------- */\n\n/* Bootstrap 2.0 sprites.less reset */\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  display: inline;\n  width: auto;\n  height: auto;\n  line-height: normal;\n  vertical-align: baseline;\n  background-image: none;\n  background-position: 0% 0%;\n  background-repeat: repeat;\n  margin-top: 0;\n}\n\n/* more sprites.less reset */\n.icon-white,\n.nav-pills > .active > a > [class^=\"icon-\"],\n.nav-pills > .active > a > [class*=\" icon-\"],\n.nav-list > .active > a > [class^=\"icon-\"],\n.nav-list > .active > a > [class*=\" icon-\"],\n.navbar-inverse .nav > .active > a > [class^=\"icon-\"],\n.navbar-inverse .nav > .active > a > [class*=\" icon-\"],\n.dropdown-menu > li > a:hover > [class^=\"icon-\"],\n.dropdown-menu > li > a:hover > [class*=\" icon-\"],\n.dropdown-menu > .active > a > [class^=\"icon-\"],\n.dropdown-menu > .active > a > [class*=\" icon-\"],\n.dropdown-submenu:hover > a > [class^=\"icon-\"],\n.dropdown-submenu:hover > a > [class*=\" icon-\"] {\n  background-image: none;\n}\n\n\n/* keeps Bootstrap styles with and without icons the same */\n.btn, .nav {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    //    display: inline;\n    &.icon-large { line-height: .9em; }\n    &.icon-spin { display: inline-block; }\n  }\n}\n.nav-tabs, .nav-pills {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    &, &.icon-large { line-height: .9em; }\n  }\n}\n.btn {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    &.pull-left, &.pull-right {\n      &.icon-2x { margin-top: .18em; }\n    }\n    &.icon-spin.icon-large { line-height: .8em; }\n  }\n}\n.btn.btn-small {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    &.pull-left, &.pull-right {\n      &.icon-2x { margin-top: .25em; }\n    }\n  }\n}\n.btn.btn-large {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    margin-top: 0; // overrides bootstrap default\n    &.pull-left, &.pull-right {\n      &.icon-2x { margin-top: .05em; }\n    }\n    &.pull-left.icon-2x { margin-right: .2em; }\n    &.pull-right.icon-2x { margin-left: .2em; }\n  }\n}\n\n/* Fixes alignment in nav lists */\n.nav-list [class^=\"icon-\"],\n.nav-list [class*=\" icon-\"] {\n  line-height: inherit;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/scss/_core.scss",
    "content": "/* FONT AWESOME CORE\n * -------------------------- */\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  @include icon-FontAwesome();\n}\n\n[class^=\"icon-\"]:before,\n[class*=\" icon-\"]:before {\n  text-decoration: inherit;\n  display: inline-block;\n  speak: none;\n}\n\n/* makes the font 33% larger relative to the icon container */\n.icon-large:before {\n  vertical-align: -10%;\n  font-size: (4em/3);\n}\n\n/* makes sure icons active on rollover in links */\na {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    display: inline;\n  }\n}\n\n/* increased font size for icon-large */\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  &.icon-fixed-width {\n    display: inline-block;\n    width: (16em/14);\n    text-align: right;\n    padding-right: (4em/14);\n    &.icon-large {\n      width: (20em/14);\n    }\n  }\n}\n\n.icons-ul {\n  margin-left: $icons-li-width;\n  list-style-type: none;\n\n  > li { position: relative; }\n\n  .icon-li {\n    position: absolute;\n    left: -$icons-li-width;\n    width: $icons-li-width;\n    text-align: center;\n    line-height: inherit;\n  }\n}\n\n// allows usage of the hide class directly on font awesome icons\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  &.hide {\n    display: none;\n  }\n}\n\n.icon-muted { color: $iconMuted; }\n.icon-light { color: $iconLight; }\n.icon-dark { color: $iconDark; }\n\n// Icon Borders\n// -------------------------\n\n.icon-border {\n  border: solid 1px $borderColor;\n  padding: .2em .25em .15em;\n  @include border-radius(3px);\n}\n\n// Icon Sizes\n// -------------------------\n\n.icon-2x {\n  font-size: 2em;\n  &.icon-border {\n    border-width: 2px;\n    @include border-radius(4px);\n  }\n}\n.icon-3x {\n  font-size: 3em;\n  &.icon-border {\n    border-width: 3px;\n    @include border-radius(5px);\n  }\n}\n.icon-4x {\n  font-size: 4em;\n  &.icon-border {\n    border-width: 4px;\n    @include border-radius(6px);\n  }\n}\n\n.icon-5x {\n  font-size: 5em;\n  &.icon-border {\n    border-width: 5px;\n    @include border-radius(7px);\n  }\n}\n\n\n// Floats & Margins\n// -------------------------\n\n// Quick floats\n.pull-right { float: right; }\n.pull-left { float: left; }\n\n[class^=\"icon-\"],\n[class*=\" icon-\"] {\n  &.pull-left {\n    margin-right: .3em;\n  }\n  &.pull-right {\n    margin-left: .3em;\n  }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/scss/_extras.scss",
    "content": "/* EXTRAS\n * -------------------------- */\n\n/* Stacked and layered icon */\n@include icon-stack();\n\n/* Animated rotating icon */\n.icon-spin {\n  display: inline-block;\n  -moz-animation: spin 2s infinite linear;\n  -o-animation: spin 2s infinite linear;\n  -webkit-animation: spin 2s infinite linear;\n  animation: spin 2s infinite linear;\n}\n\n/* Prevent stack and spinners from being taken inline when inside a link */\na .icon-stack,\na .icon-spin {\n  display: inline-block;\n  text-decoration: none;\n}\n\n@-moz-keyframes spin {\n  0% { -moz-transform: rotate(0deg); }\n  100% { -moz-transform: rotate(359deg); }\n}\n@-webkit-keyframes spin {\n  0% { -webkit-transform: rotate(0deg); }\n  100% { -webkit-transform: rotate(359deg); }\n}\n@-o-keyframes spin {\n  0% { -o-transform: rotate(0deg); }\n  100% { -o-transform: rotate(359deg); }\n}\n@-ms-keyframes spin {\n  0% { -ms-transform: rotate(0deg); }\n  100% { -ms-transform: rotate(359deg); }\n}\n@keyframes spin {\n  0% { transform: rotate(0deg); }\n  100% { transform: rotate(359deg); }\n}\n\n/* Icon rotations and mirroring */\n.icon-rotate-90:before {\n  -webkit-transform: rotate(90deg);\n  -moz-transform: rotate(90deg);\n  -ms-transform: rotate(90deg);\n  -o-transform: rotate(90deg);\n  transform: rotate(90deg);\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);\n}\n\n.icon-rotate-180:before {\n  -webkit-transform: rotate(180deg);\n  -moz-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  -o-transform: rotate(180deg);\n  transform: rotate(180deg);\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);\n}\n\n.icon-rotate-270:before {\n  -webkit-transform: rotate(270deg);\n  -moz-transform: rotate(270deg);\n  -ms-transform: rotate(270deg);\n  -o-transform: rotate(270deg);\n  transform: rotate(270deg);\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);\n}\n\n.icon-flip-horizontal:before {\n  -webkit-transform: scale(-1, 1);\n  -moz-transform: scale(-1, 1);\n  -ms-transform: scale(-1, 1);\n  -o-transform: scale(-1, 1);\n  transform: scale(-1, 1);\n}\n\n.icon-flip-vertical:before {\n  -webkit-transform: scale(1, -1);\n  -moz-transform: scale(1, -1);\n  -ms-transform: scale(1, -1);\n  -o-transform: scale(1, -1);\n  transform: scale(1, -1);\n}\n\n/* ensure rotation occurs inside anchor tags */\na {\n  .icon-rotate-90, .icon-rotate-180, .icon-rotate-270, .icon-flip-horizontal, .icon-flip-vertical {\n    &:before { display: inline-block; }\n  }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/scss/_icons.scss",
    "content": "/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n * readers do not read off random characters that represent icons */\n\n.icon-glass:before { content: $glass; }\n.icon-music:before { content: $music; }\n.icon-search:before { content: $search; }\n.icon-envelope-alt:before { content: $envelope-alt; }\n.icon-heart:before { content: $heart; }\n.icon-star:before { content: $star; }\n.icon-star-empty:before { content: $star-empty; }\n.icon-user:before { content: $user; }\n.icon-film:before { content: $film; }\n.icon-th-large:before { content: $th-large; }\n.icon-th:before { content: $th; }\n.icon-th-list:before { content: $th-list; }\n.icon-ok:before { content: $ok; }\n.icon-remove:before { content: $remove; }\n.icon-zoom-in:before { content: $zoom-in; }\n.icon-zoom-out:before { content: $zoom-out; }\n.icon-power-off:before,\n.icon-off:before { content: $off; }\n.icon-signal:before { content: $signal; }\n.icon-gear:before,\n.icon-cog:before { content: $cog; }\n.icon-trash:before { content: $trash; }\n.icon-home:before { content: $home; }\n.icon-file-alt:before { content: $file-alt; }\n.icon-time:before { content: $time; }\n.icon-road:before { content: $road; }\n.icon-download-alt:before { content: $download-alt; }\n.icon-download:before { content: $download; }\n.icon-upload:before { content: $upload; }\n.icon-inbox:before { content: $inbox; }\n.icon-play-circle:before { content: $play-circle; }\n.icon-rotate-right:before,\n.icon-repeat:before { content: $repeat; }\n.icon-refresh:before { content: $refresh; }\n.icon-list-alt:before { content: $list-alt; }\n.icon-lock:before { content: $lock; }\n.icon-flag:before { content: $flag; }\n.icon-headphones:before { content: $headphones; }\n.icon-volume-off:before { content: $volume-off; }\n.icon-volume-down:before { content: $volume-down; }\n.icon-volume-up:before { content: $volume-up; }\n.icon-qrcode:before { content: $qrcode; }\n.icon-barcode:before { content: $barcode; }\n.icon-tag:before { content: $tag; }\n.icon-tags:before { content: $tags; }\n.icon-book:before { content: $book; }\n.icon-bookmark:before { content: $bookmark; }\n.icon-print:before { content: $print; }\n.icon-camera:before { content: $camera; }\n.icon-font:before { content: $font; }\n.icon-bold:before { content: $bold; }\n.icon-italic:before { content: $italic; }\n.icon-text-height:before { content: $text-height; }\n.icon-text-width:before { content: $text-width; }\n.icon-align-left:before { content: $align-left; }\n.icon-align-center:before { content: $align-center; }\n.icon-align-right:before { content: $align-right; }\n.icon-align-justify:before { content: $align-justify; }\n.icon-list:before { content: $list; }\n.icon-indent-left:before { content: $indent-left; }\n.icon-indent-right:before { content: $indent-right; }\n.icon-facetime-video:before { content: $facetime-video; }\n.icon-picture:before { content: $picture; }\n.icon-pencil:before { content: $pencil; }\n.icon-map-marker:before { content: $map-marker; }\n.icon-adjust:before { content: $adjust; }\n.icon-tint:before { content: $tint; }\n.icon-edit:before { content: $edit; }\n.icon-share:before { content: $share; }\n.icon-check:before { content: $check; }\n.icon-move:before { content: $move; }\n.icon-step-backward:before { content: $step-backward; }\n.icon-fast-backward:before { content: $fast-backward; }\n.icon-backward:before { content: $backward; }\n.icon-play:before { content: $play; }\n.icon-pause:before { content: $pause; }\n.icon-stop:before { content: $stop; }\n.icon-forward:before { content: $forward; }\n.icon-fast-forward:before { content: $fast-forward; }\n.icon-step-forward:before { content: $step-forward; }\n.icon-eject:before { content: $eject; }\n.icon-chevron-left:before { content: $chevron-left; }\n.icon-chevron-right:before { content: $chevron-right; }\n.icon-plus-sign:before { content: $plus-sign; }\n.icon-minus-sign:before { content: $minus-sign; }\n.icon-remove-sign:before { content: $remove-sign; }\n.icon-ok-sign:before { content: $ok-sign; }\n.icon-question-sign:before { content: $question-sign; }\n.icon-info-sign:before { content: $info-sign; }\n.icon-screenshot:before { content: $screenshot; }\n.icon-remove-circle:before { content: $remove-circle; }\n.icon-ok-circle:before { content: $ok-circle; }\n.icon-ban-circle:before { content: $ban-circle; }\n.icon-arrow-left:before { content: $arrow-left; }\n.icon-arrow-right:before { content: $arrow-right; }\n.icon-arrow-up:before { content: $arrow-up; }\n.icon-arrow-down:before { content: $arrow-down; }\n.icon-mail-forward:before,\n.icon-share-alt:before { content: $share-alt; }\n.icon-resize-full:before { content: $resize-full; }\n.icon-resize-small:before { content: $resize-small; }\n.icon-plus:before { content: $plus; }\n.icon-minus:before { content: $minus; }\n.icon-asterisk:before { content: $asterisk; }\n.icon-exclamation-sign:before { content: $exclamation-sign; }\n.icon-gift:before { content: $gift; }\n.icon-leaf:before { content: $leaf; }\n.icon-fire:before { content: $fire; }\n.icon-eye-open:before { content: $eye-open; }\n.icon-eye-close:before { content: $eye-close; }\n.icon-warning-sign:before { content: $warning-sign; }\n.icon-plane:before { content: $plane; }\n.icon-calendar:before { content: $calendar; }\n.icon-random:before { content: $random; }\n.icon-comment:before { content: $comment; }\n.icon-magnet:before { content: $magnet; }\n.icon-chevron-up:before { content: $chevron-up; }\n.icon-chevron-down:before { content: $chevron-down; }\n.icon-retweet:before { content: $retweet; }\n.icon-shopping-cart:before { content: $shopping-cart; }\n.icon-folder-close:before { content: $folder-close; }\n.icon-folder-open:before { content: $folder-open; }\n.icon-resize-vertical:before { content: $resize-vertical; }\n.icon-resize-horizontal:before { content: $resize-horizontal; }\n.icon-bar-chart:before { content: $bar-chart; }\n.icon-twitter-sign:before { content: $twitter-sign; }\n.icon-facebook-sign:before { content: $facebook-sign; }\n.icon-camera-retro:before { content: $camera-retro; }\n.icon-key:before { content: $key; }\n.icon-gears:before,\n.icon-cogs:before { content: $cogs; }\n.icon-comments:before { content: $comments; }\n.icon-thumbs-up-alt:before { content: $thumbs-up-alt; }\n.icon-thumbs-down-alt:before { content: $thumbs-down-alt; }\n.icon-star-half:before { content: $star-half; }\n.icon-heart-empty:before { content: $heart-empty; }\n.icon-signout:before { content: $signout; }\n.icon-linkedin-sign:before { content: $linkedin-sign; }\n.icon-pushpin:before { content: $pushpin; }\n.icon-external-link:before { content: $external-link; }\n.icon-signin:before { content: $signin; }\n.icon-trophy:before { content: $trophy; }\n.icon-github-sign:before { content: $github-sign; }\n.icon-upload-alt:before { content: $upload-alt; }\n.icon-lemon:before { content: $lemon; }\n.icon-phone:before { content: $phone; }\n.icon-unchecked:before,\n.icon-check-empty:before { content: $check-empty; }\n.icon-bookmark-empty:before { content: $bookmark-empty; }\n.icon-phone-sign:before { content: $phone-sign; }\n.icon-twitter:before { content: $twitter; }\n.icon-facebook:before { content: $facebook; }\n.icon-github:before { content: $github; }\n.icon-unlock:before { content: $unlock; }\n.icon-credit-card:before { content: $credit-card; }\n.icon-rss:before { content: $rss; }\n.icon-hdd:before { content: $hdd; }\n.icon-bullhorn:before { content: $bullhorn; }\n.icon-bell:before { content: $bell; }\n.icon-certificate:before { content: $certificate; }\n.icon-hand-right:before { content: $hand-right; }\n.icon-hand-left:before { content: $hand-left; }\n.icon-hand-up:before { content: $hand-up; }\n.icon-hand-down:before { content: $hand-down; }\n.icon-circle-arrow-left:before { content: $circle-arrow-left; }\n.icon-circle-arrow-right:before { content: $circle-arrow-right; }\n.icon-circle-arrow-up:before { content: $circle-arrow-up; }\n.icon-circle-arrow-down:before { content: $circle-arrow-down; }\n.icon-globe:before { content: $globe; }\n.icon-wrench:before { content: $wrench; }\n.icon-tasks:before { content: $tasks; }\n.icon-filter:before { content: $filter; }\n.icon-briefcase:before { content: $briefcase; }\n.icon-fullscreen:before { content: $fullscreen; }\n.icon-group:before { content: $group; }\n.icon-link:before { content: $link; }\n.icon-cloud:before { content: $cloud; }\n.icon-beaker:before { content: $beaker; }\n.icon-cut:before { content: $cut; }\n.icon-copy:before { content: $copy; }\n.icon-paperclip:before,\n.icon-paper-clip:before { content: $paper-clip; }\n.icon-save:before { content: $save; }\n.icon-sign-blank:before { content: $sign-blank; }\n.icon-reorder:before { content: $reorder; }\n.icon-list-ul:before { content: $list-ul; }\n.icon-list-ol:before { content: $list-ol; }\n.icon-strikethrough:before { content: $strikethrough; }\n.icon-underline:before { content: $underline; }\n.icon-table:before { content: $table; }\n.icon-magic:before { content: $magic; }\n.icon-truck:before { content: $truck; }\n.icon-pinterest:before { content: $pinterest; }\n.icon-pinterest-sign:before { content: $pinterest-sign; }\n.icon-google-plus-sign:before { content: $google-plus-sign; }\n.icon-google-plus:before { content: $google-plus; }\n.icon-money:before { content: $money; }\n.icon-caret-down:before { content: $caret-down; }\n.icon-caret-up:before { content: $caret-up; }\n.icon-caret-left:before { content: $caret-left; }\n.icon-caret-right:before { content: $caret-right; }\n.icon-columns:before { content: $columns; }\n.icon-sort:before { content: $sort; }\n.icon-sort-down:before { content: $sort-down; }\n.icon-sort-up:before { content: $sort-up; }\n.icon-envelope:before { content: $envelope; }\n.icon-linkedin:before { content: $linkedin; }\n.icon-rotate-left:before,\n.icon-undo:before { content: $undo; }\n.icon-legal:before { content: $legal; }\n.icon-dashboard:before { content: $dashboard; }\n.icon-comment-alt:before { content: $comment-alt; }\n.icon-comments-alt:before { content: $comments-alt; }\n.icon-bolt:before { content: $bolt; }\n.icon-sitemap:before { content: $sitemap; }\n.icon-umbrella:before { content: $umbrella; }\n.icon-paste:before { content: $paste; }\n.icon-lightbulb:before { content: $lightbulb; }\n.icon-exchange:before { content: $exchange; }\n.icon-cloud-download:before { content: $cloud-download; }\n.icon-cloud-upload:before { content: $cloud-upload; }\n.icon-user-md:before { content: $user-md; }\n.icon-stethoscope:before { content: $stethoscope; }\n.icon-suitcase:before { content: $suitcase; }\n.icon-bell-alt:before { content: $bell-alt; }\n.icon-coffee:before { content: $coffee; }\n.icon-food:before { content: $food; }\n.icon-file-text-alt:before { content: $file-text-alt; }\n.icon-building:before { content: $building; }\n.icon-hospital:before { content: $hospital; }\n.icon-ambulance:before { content: $ambulance; }\n.icon-medkit:before { content: $medkit; }\n.icon-fighter-jet:before { content: $fighter-jet; }\n.icon-beer:before { content: $beer; }\n.icon-h-sign:before { content: $h-sign; }\n.icon-plus-sign-alt:before { content: $plus-sign-alt; }\n.icon-double-angle-left:before { content: $double-angle-left; }\n.icon-double-angle-right:before { content: $double-angle-right; }\n.icon-double-angle-up:before { content: $double-angle-up; }\n.icon-double-angle-down:before { content: $double-angle-down; }\n.icon-angle-left:before { content: $angle-left; }\n.icon-angle-right:before { content: $angle-right; }\n.icon-angle-up:before { content: $angle-up; }\n.icon-angle-down:before { content: $angle-down; }\n.icon-desktop:before { content: $desktop; }\n.icon-laptop:before { content: $laptop; }\n.icon-tablet:before { content: $tablet; }\n.icon-mobile-phone:before { content: $mobile-phone; }\n.icon-circle-blank:before { content: $circle-blank; }\n.icon-quote-left:before { content: $quote-left; }\n.icon-quote-right:before { content: $quote-right; }\n.icon-spinner:before { content: $spinner; }\n.icon-circle:before { content: $circle; }\n.icon-mail-reply:before,\n.icon-reply:before { content: $reply; }\n.icon-github-alt:before { content: $github-alt; }\n.icon-folder-close-alt:before { content: $folder-close-alt; }\n.icon-folder-open-alt:before { content: $folder-open-alt; }\n.icon-expand-alt:before { content: $expand-alt; }\n.icon-collapse-alt:before { content: $collapse-alt; }\n.icon-smile:before { content: $smile; }\n.icon-frown:before { content: $frown; }\n.icon-meh:before { content: $meh; }\n.icon-gamepad:before { content: $gamepad; }\n.icon-keyboard:before { content: $keyboard; }\n.icon-flag-alt:before { content: $flag-alt; }\n.icon-flag-checkered:before { content: $flag-checkered; }\n.icon-terminal:before { content: $terminal; }\n.icon-code:before { content: $code; }\n.icon-reply-all:before { content: $reply-all; }\n.icon-mail-reply-all:before { content: $mail-reply-all; }\n.icon-star-half-full:before,\n.icon-star-half-empty:before { content: $star-half-empty; }\n.icon-location-arrow:before { content: $location-arrow; }\n.icon-crop:before { content: $crop; }\n.icon-code-fork:before { content: $code-fork; }\n.icon-unlink:before { content: $unlink; }\n.icon-question:before { content: $question; }\n.icon-info:before { content: $info; }\n.icon-exclamation:before { content: $exclamation; }\n.icon-superscript:before { content: $superscript; }\n.icon-subscript:before { content: $subscript; }\n.icon-eraser:before { content: $eraser; }\n.icon-puzzle-piece:before { content: $puzzle-piece; }\n.icon-microphone:before { content: $microphone; }\n.icon-microphone-off:before { content: $microphone-off; }\n.icon-shield:before { content: $shield; }\n.icon-calendar-empty:before { content: $calendar-empty; }\n.icon-fire-extinguisher:before { content: $fire-extinguisher; }\n.icon-rocket:before { content: $rocket; }\n.icon-maxcdn:before { content: $maxcdn; }\n.icon-chevron-sign-left:before { content: $chevron-sign-left; }\n.icon-chevron-sign-right:before { content: $chevron-sign-right; }\n.icon-chevron-sign-up:before { content: $chevron-sign-up; }\n.icon-chevron-sign-down:before { content: $chevron-sign-down; }\n.icon-html5:before { content: $html5; }\n.icon-css3:before { content: $css3; }\n.icon-anchor:before { content: $anchor; }\n.icon-unlock-alt:before { content: $unlock-alt; }\n.icon-bullseye:before { content: $bullseye; }\n.icon-ellipsis-horizontal:before { content: $ellipsis-horizontal; }\n.icon-ellipsis-vertical:before { content: $ellipsis-vertical; }\n.icon-rss-sign:before { content: $rss-sign; }\n.icon-play-sign:before { content: $play-sign; }\n.icon-ticket:before { content: $ticket; }\n.icon-minus-sign-alt:before { content: $minus-sign-alt; }\n.icon-check-minus:before { content: $check-minus; }\n.icon-level-up:before { content: $level-up; }\n.icon-level-down:before { content: $level-down; }\n.icon-check-sign:before { content: $check-sign; }\n.icon-edit-sign:before { content: $edit-sign; }\n.icon-external-link-sign:before { content: $external-link-sign; }\n.icon-share-sign:before { content: $share-sign; }\n.icon-compass:before { content: $compass; }\n.icon-collapse:before { content: $collapse; }\n.icon-collapse-top:before { content: $collapse-top; }\n.icon-expand:before { content: $expand; }\n.icon-euro:before,\n.icon-eur:before { content: $eur; }\n.icon-gbp:before { content: $gbp; }\n.icon-dollar:before,\n.icon-usd:before { content: $usd; }\n.icon-rupee:before,\n.icon-inr:before { content: $inr; }\n.icon-yen:before,\n.icon-jpy:before { content: $jpy; }\n.icon-renminbi:before,\n.icon-cny:before { content: $cny; }\n.icon-won:before,\n.icon-krw:before { content: $krw; }\n.icon-bitcoin:before,\n.icon-btc:before { content: $btc; }\n.icon-file:before { content: $file; }\n.icon-file-text:before { content: $file-text; }\n.icon-sort-by-alphabet:before { content: $sort-by-alphabet; }\n.icon-sort-by-alphabet-alt:before { content: $sort-by-alphabet-alt; }\n.icon-sort-by-attributes:before { content: $sort-by-attributes; }\n.icon-sort-by-attributes-alt:before { content: $sort-by-attributes-alt; }\n.icon-sort-by-order:before { content: $sort-by-order; }\n.icon-sort-by-order-alt:before { content: $sort-by-order-alt; }\n.icon-thumbs-up:before { content: $thumbs-up; }\n.icon-thumbs-down:before { content: $thumbs-down; }\n.icon-youtube-sign:before { content: $youtube-sign; }\n.icon-youtube:before { content: $youtube; }\n.icon-xing:before { content: $xing; }\n.icon-xing-sign:before { content: $xing-sign; }\n.icon-youtube-play:before { content: $youtube-play; }\n.icon-dropbox:before { content: $dropbox; }\n.icon-stackexchange:before { content: $stackexchange; }\n.icon-instagram:before { content: $instagram; }\n.icon-flickr:before { content: $flickr; }\n.icon-adn:before { content: $adn; }\n.icon-bitbucket:before { content: $bitbucket; }\n.icon-bitbucket-sign:before { content: $bitbucket-sign; }\n.icon-tumblr:before { content: $tumblr; }\n.icon-tumblr-sign:before { content: $tumblr-sign; }\n.icon-long-arrow-down:before { content: $long-arrow-down; }\n.icon-long-arrow-up:before { content: $long-arrow-up; }\n.icon-long-arrow-left:before { content: $long-arrow-left; }\n.icon-long-arrow-right:before { content: $long-arrow-right; }\n.icon-apple:before { content: $apple; }\n.icon-windows:before { content: $windows; }\n.icon-android:before { content: $android; }\n.icon-linux:before { content: $linux; }\n.icon-dribbble:before { content: $dribbble; }\n.icon-skype:before { content: $skype; }\n.icon-foursquare:before { content: $foursquare; }\n.icon-trello:before { content: $trello; }\n.icon-female:before { content: $female; }\n.icon-male:before { content: $male; }\n.icon-gittip:before { content: $gittip; }\n.icon-sun:before { content: $sun; }\n.icon-moon:before { content: $moon; }\n.icon-archive:before { content: $archive; }\n.icon-bug:before { content: $bug; }\n.icon-vk:before { content: $vk; }\n.icon-weibo:before { content: $weibo; }\n.icon-renren:before { content: $renren; }\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/scss/_mixins.scss",
    "content": "// Mixins\n// --------------------------\n\n@mixin icon($icon) {\n  @include icon-FontAwesome();\n  content: $icon;\n}\n\n@mixin icon-FontAwesome() {\n  font-family: FontAwesome;\n  font-weight: normal;\n  font-style: normal;\n  text-decoration: inherit;\n  -webkit-font-smoothing: antialiased;\n  *margin-right: .3em; // fixes ie7 issues\n}\n\n@mixin border-radius($radius) {\n  -webkit-border-radius: $radius;\n  -moz-border-radius: $radius;\n  border-radius: $radius;\n}\n\n@mixin icon-stack($width: 2em, $height: 2em, $top-font-size: 1em, $base-font-size: 2em) {\n  .icon-stack {\n    position: relative;\n    display: inline-block;\n    width: $width;\n    height: $height;\n    line-height: $width;\n    vertical-align: -35%;\n    [class^=\"icon-\"],\n    [class*=\" icon-\"] {\n      display: block;\n      text-align: center;\n      position: absolute;\n      width: 100%;\n      height: 100%;\n      font-size: $top-font-size;\n      line-height: inherit;\n      *line-height: $height;\n    }\n    .icon-stack-base {\n      font-size: $base-font-size;\n      *line-height: #{$height / $base-font-size}em;\n    }\n  }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/scss/_path.scss",
    "content": "/* FONT PATH\n * -------------------------- */\n\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('#{$FontAwesomePath}/fontawesome-webfont.eot?v=#{$FontAwesomeVersion}');\n  src: url('#{$FontAwesomePath}/fontawesome-webfont.eot?#iefix&v=#{$FontAwesomeVersion}') format('embedded-opentype'),\n    url('#{$FontAwesomePath}/fontawesome-webfont.woff?v=#{$FontAwesomeVersion}') format('woff'),\n    url('#{$FontAwesomePath}/fontawesome-webfont.ttf?v=#{$FontAwesomeVersion}') format('truetype'),\n    url('#{$FontAwesomePath}/fontawesome-webfont.svg#fontawesomeregular?v=#{$FontAwesomeVersion}') format('svg');\n//  src: url('#{$FontAwesomePath}/FontAwesome.otf') format('opentype'); // used when developing fonts\n  font-weight: normal;\n  font-style: normal;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/scss/_variables.scss",
    "content": "// Variables\n// --------------------------\n\n$FontAwesomePath: \"../font\" !default;\n$FontAwesomeVersion: \"3.2.1\" !default;\n$borderColor: #eeeeee !default;\n$iconMuted: #eeeeee !default;\n$iconLight: white !default;\n$iconDark: #333333 !default;\n$icons-li-width: (30em/14);\n\n\n$glass: \"\\f000\";\n\n$music: \"\\f001\";\n\n$search: \"\\f002\";\n\n$envelope-alt: \"\\f003\";\n\n$heart: \"\\f004\";\n\n$star: \"\\f005\";\n\n$star-empty: \"\\f006\";\n\n$user: \"\\f007\";\n\n$film: \"\\f008\";\n\n$th-large: \"\\f009\";\n\n$th: \"\\f00a\";\n\n$th-list: \"\\f00b\";\n\n$ok: \"\\f00c\";\n\n$remove: \"\\f00d\";\n\n$zoom-in: \"\\f00e\";\n\n$zoom-out: \"\\f010\";\n\n$off: \"\\f011\";\n\n$signal: \"\\f012\";\n\n$cog: \"\\f013\";\n\n$trash: \"\\f014\";\n\n$home: \"\\f015\";\n\n$file-alt: \"\\f016\";\n\n$time: \"\\f017\";\n\n$road: \"\\f018\";\n\n$download-alt: \"\\f019\";\n\n$download: \"\\f01a\";\n\n$upload: \"\\f01b\";\n\n$inbox: \"\\f01c\";\n\n$play-circle: \"\\f01d\";\n\n$repeat: \"\\f01e\";\n\n$refresh: \"\\f021\";\n\n$list-alt: \"\\f022\";\n\n$lock: \"\\f023\";\n\n$flag: \"\\f024\";\n\n$headphones: \"\\f025\";\n\n$volume-off: \"\\f026\";\n\n$volume-down: \"\\f027\";\n\n$volume-up: \"\\f028\";\n\n$qrcode: \"\\f029\";\n\n$barcode: \"\\f02a\";\n\n$tag: \"\\f02b\";\n\n$tags: \"\\f02c\";\n\n$book: \"\\f02d\";\n\n$bookmark: \"\\f02e\";\n\n$print: \"\\f02f\";\n\n$camera: \"\\f030\";\n\n$font: \"\\f031\";\n\n$bold: \"\\f032\";\n\n$italic: \"\\f033\";\n\n$text-height: \"\\f034\";\n\n$text-width: \"\\f035\";\n\n$align-left: \"\\f036\";\n\n$align-center: \"\\f037\";\n\n$align-right: \"\\f038\";\n\n$align-justify: \"\\f039\";\n\n$list: \"\\f03a\";\n\n$indent-left: \"\\f03b\";\n\n$indent-right: \"\\f03c\";\n\n$facetime-video: \"\\f03d\";\n\n$picture: \"\\f03e\";\n\n$pencil: \"\\f040\";\n\n$map-marker: \"\\f041\";\n\n$adjust: \"\\f042\";\n\n$tint: \"\\f043\";\n\n$edit: \"\\f044\";\n\n$share: \"\\f045\";\n\n$check: \"\\f046\";\n\n$move: \"\\f047\";\n\n$step-backward: \"\\f048\";\n\n$fast-backward: \"\\f049\";\n\n$backward: \"\\f04a\";\n\n$play: \"\\f04b\";\n\n$pause: \"\\f04c\";\n\n$stop: \"\\f04d\";\n\n$forward: \"\\f04e\";\n\n$fast-forward: \"\\f050\";\n\n$step-forward: \"\\f051\";\n\n$eject: \"\\f052\";\n\n$chevron-left: \"\\f053\";\n\n$chevron-right: \"\\f054\";\n\n$plus-sign: \"\\f055\";\n\n$minus-sign: \"\\f056\";\n\n$remove-sign: \"\\f057\";\n\n$ok-sign: \"\\f058\";\n\n$question-sign: \"\\f059\";\n\n$info-sign: \"\\f05a\";\n\n$screenshot: \"\\f05b\";\n\n$remove-circle: \"\\f05c\";\n\n$ok-circle: \"\\f05d\";\n\n$ban-circle: \"\\f05e\";\n\n$arrow-left: \"\\f060\";\n\n$arrow-right: \"\\f061\";\n\n$arrow-up: \"\\f062\";\n\n$arrow-down: \"\\f063\";\n\n$share-alt: \"\\f064\";\n\n$resize-full: \"\\f065\";\n\n$resize-small: \"\\f066\";\n\n$plus: \"\\f067\";\n\n$minus: \"\\f068\";\n\n$asterisk: \"\\f069\";\n\n$exclamation-sign: \"\\f06a\";\n\n$gift: \"\\f06b\";\n\n$leaf: \"\\f06c\";\n\n$fire: \"\\f06d\";\n\n$eye-open: \"\\f06e\";\n\n$eye-close: \"\\f070\";\n\n$warning-sign: \"\\f071\";\n\n$plane: \"\\f072\";\n\n$calendar: \"\\f073\";\n\n$random: \"\\f074\";\n\n$comment: \"\\f075\";\n\n$magnet: \"\\f076\";\n\n$chevron-up: \"\\f077\";\n\n$chevron-down: \"\\f078\";\n\n$retweet: \"\\f079\";\n\n$shopping-cart: \"\\f07a\";\n\n$folder-close: \"\\f07b\";\n\n$folder-open: \"\\f07c\";\n\n$resize-vertical: \"\\f07d\";\n\n$resize-horizontal: \"\\f07e\";\n\n$bar-chart: \"\\f080\";\n\n$twitter-sign: \"\\f081\";\n\n$facebook-sign: \"\\f082\";\n\n$camera-retro: \"\\f083\";\n\n$key: \"\\f084\";\n\n$cogs: \"\\f085\";\n\n$comments: \"\\f086\";\n\n$thumbs-up-alt: \"\\f087\";\n\n$thumbs-down-alt: \"\\f088\";\n\n$star-half: \"\\f089\";\n\n$heart-empty: \"\\f08a\";\n\n$signout: \"\\f08b\";\n\n$linkedin-sign: \"\\f08c\";\n\n$pushpin: \"\\f08d\";\n\n$external-link: \"\\f08e\";\n\n$signin: \"\\f090\";\n\n$trophy: \"\\f091\";\n\n$github-sign: \"\\f092\";\n\n$upload-alt: \"\\f093\";\n\n$lemon: \"\\f094\";\n\n$phone: \"\\f095\";\n\n$check-empty: \"\\f096\";\n\n$bookmark-empty: \"\\f097\";\n\n$phone-sign: \"\\f098\";\n\n$twitter: \"\\f099\";\n\n$facebook: \"\\f09a\";\n\n$github: \"\\f09b\";\n\n$unlock: \"\\f09c\";\n\n$credit-card: \"\\f09d\";\n\n$rss: \"\\f09e\";\n\n$hdd: \"\\f0a0\";\n\n$bullhorn: \"\\f0a1\";\n\n$bell: \"\\f0a2\";\n\n$certificate: \"\\f0a3\";\n\n$hand-right: \"\\f0a4\";\n\n$hand-left: \"\\f0a5\";\n\n$hand-up: \"\\f0a6\";\n\n$hand-down: \"\\f0a7\";\n\n$circle-arrow-left: \"\\f0a8\";\n\n$circle-arrow-right: \"\\f0a9\";\n\n$circle-arrow-up: \"\\f0aa\";\n\n$circle-arrow-down: \"\\f0ab\";\n\n$globe: \"\\f0ac\";\n\n$wrench: \"\\f0ad\";\n\n$tasks: \"\\f0ae\";\n\n$filter: \"\\f0b0\";\n\n$briefcase: \"\\f0b1\";\n\n$fullscreen: \"\\f0b2\";\n\n$group: \"\\f0c0\";\n\n$link: \"\\f0c1\";\n\n$cloud: \"\\f0c2\";\n\n$beaker: \"\\f0c3\";\n\n$cut: \"\\f0c4\";\n\n$copy: \"\\f0c5\";\n\n$paper-clip: \"\\f0c6\";\n\n$save: \"\\f0c7\";\n\n$sign-blank: \"\\f0c8\";\n\n$reorder: \"\\f0c9\";\n\n$list-ul: \"\\f0ca\";\n\n$list-ol: \"\\f0cb\";\n\n$strikethrough: \"\\f0cc\";\n\n$underline: \"\\f0cd\";\n\n$table: \"\\f0ce\";\n\n$magic: \"\\f0d0\";\n\n$truck: \"\\f0d1\";\n\n$pinterest: \"\\f0d2\";\n\n$pinterest-sign: \"\\f0d3\";\n\n$google-plus-sign: \"\\f0d4\";\n\n$google-plus: \"\\f0d5\";\n\n$money: \"\\f0d6\";\n\n$caret-down: \"\\f0d7\";\n\n$caret-up: \"\\f0d8\";\n\n$caret-left: \"\\f0d9\";\n\n$caret-right: \"\\f0da\";\n\n$columns: \"\\f0db\";\n\n$sort: \"\\f0dc\";\n\n$sort-down: \"\\f0dd\";\n\n$sort-up: \"\\f0de\";\n\n$envelope: \"\\f0e0\";\n\n$linkedin: \"\\f0e1\";\n\n$undo: \"\\f0e2\";\n\n$legal: \"\\f0e3\";\n\n$dashboard: \"\\f0e4\";\n\n$comment-alt: \"\\f0e5\";\n\n$comments-alt: \"\\f0e6\";\n\n$bolt: \"\\f0e7\";\n\n$sitemap: \"\\f0e8\";\n\n$umbrella: \"\\f0e9\";\n\n$paste: \"\\f0ea\";\n\n$lightbulb: \"\\f0eb\";\n\n$exchange: \"\\f0ec\";\n\n$cloud-download: \"\\f0ed\";\n\n$cloud-upload: \"\\f0ee\";\n\n$user-md: \"\\f0f0\";\n\n$stethoscope: \"\\f0f1\";\n\n$suitcase: \"\\f0f2\";\n\n$bell-alt: \"\\f0f3\";\n\n$coffee: \"\\f0f4\";\n\n$food: \"\\f0f5\";\n\n$file-text-alt: \"\\f0f6\";\n\n$building: \"\\f0f7\";\n\n$hospital: \"\\f0f8\";\n\n$ambulance: \"\\f0f9\";\n\n$medkit: \"\\f0fa\";\n\n$fighter-jet: \"\\f0fb\";\n\n$beer: \"\\f0fc\";\n\n$h-sign: \"\\f0fd\";\n\n$plus-sign-alt: \"\\f0fe\";\n\n$double-angle-left: \"\\f100\";\n\n$double-angle-right: \"\\f101\";\n\n$double-angle-up: \"\\f102\";\n\n$double-angle-down: \"\\f103\";\n\n$angle-left: \"\\f104\";\n\n$angle-right: \"\\f105\";\n\n$angle-up: \"\\f106\";\n\n$angle-down: \"\\f107\";\n\n$desktop: \"\\f108\";\n\n$laptop: \"\\f109\";\n\n$tablet: \"\\f10a\";\n\n$mobile-phone: \"\\f10b\";\n\n$circle-blank: \"\\f10c\";\n\n$quote-left: \"\\f10d\";\n\n$quote-right: \"\\f10e\";\n\n$spinner: \"\\f110\";\n\n$circle: \"\\f111\";\n\n$reply: \"\\f112\";\n\n$github-alt: \"\\f113\";\n\n$folder-close-alt: \"\\f114\";\n\n$folder-open-alt: \"\\f115\";\n\n$expand-alt: \"\\f116\";\n\n$collapse-alt: \"\\f117\";\n\n$smile: \"\\f118\";\n\n$frown: \"\\f119\";\n\n$meh: \"\\f11a\";\n\n$gamepad: \"\\f11b\";\n\n$keyboard: \"\\f11c\";\n\n$flag-alt: \"\\f11d\";\n\n$flag-checkered: \"\\f11e\";\n\n$terminal: \"\\f120\";\n\n$code: \"\\f121\";\n\n$reply-all: \"\\f122\";\n\n$mail-reply-all: \"\\f122\";\n\n$star-half-empty: \"\\f123\";\n\n$location-arrow: \"\\f124\";\n\n$crop: \"\\f125\";\n\n$code-fork: \"\\f126\";\n\n$unlink: \"\\f127\";\n\n$question: \"\\f128\";\n\n$info: \"\\f129\";\n\n$exclamation: \"\\f12a\";\n\n$superscript: \"\\f12b\";\n\n$subscript: \"\\f12c\";\n\n$eraser: \"\\f12d\";\n\n$puzzle-piece: \"\\f12e\";\n\n$microphone: \"\\f130\";\n\n$microphone-off: \"\\f131\";\n\n$shield: \"\\f132\";\n\n$calendar-empty: \"\\f133\";\n\n$fire-extinguisher: \"\\f134\";\n\n$rocket: \"\\f135\";\n\n$maxcdn: \"\\f136\";\n\n$chevron-sign-left: \"\\f137\";\n\n$chevron-sign-right: \"\\f138\";\n\n$chevron-sign-up: \"\\f139\";\n\n$chevron-sign-down: \"\\f13a\";\n\n$html5: \"\\f13b\";\n\n$css3: \"\\f13c\";\n\n$anchor: \"\\f13d\";\n\n$unlock-alt: \"\\f13e\";\n\n$bullseye: \"\\f140\";\n\n$ellipsis-horizontal: \"\\f141\";\n\n$ellipsis-vertical: \"\\f142\";\n\n$rss-sign: \"\\f143\";\n\n$play-sign: \"\\f144\";\n\n$ticket: \"\\f145\";\n\n$minus-sign-alt: \"\\f146\";\n\n$check-minus: \"\\f147\";\n\n$level-up: \"\\f148\";\n\n$level-down: \"\\f149\";\n\n$check-sign: \"\\f14a\";\n\n$edit-sign: \"\\f14b\";\n\n$external-link-sign: \"\\f14c\";\n\n$share-sign: \"\\f14d\";\n\n$compass: \"\\f14e\";\n\n$collapse: \"\\f150\";\n\n$collapse-top: \"\\f151\";\n\n$expand: \"\\f152\";\n\n$eur: \"\\f153\";\n\n$gbp: \"\\f154\";\n\n$usd: \"\\f155\";\n\n$inr: \"\\f156\";\n\n$jpy: \"\\f157\";\n\n$cny: \"\\f158\";\n\n$krw: \"\\f159\";\n\n$btc: \"\\f15a\";\n\n$file: \"\\f15b\";\n\n$file-text: \"\\f15c\";\n\n$sort-by-alphabet: \"\\f15d\";\n\n$sort-by-alphabet-alt: \"\\f15e\";\n\n$sort-by-attributes: \"\\f160\";\n\n$sort-by-attributes-alt: \"\\f161\";\n\n$sort-by-order: \"\\f162\";\n\n$sort-by-order-alt: \"\\f163\";\n\n$thumbs-up: \"\\f164\";\n\n$thumbs-down: \"\\f165\";\n\n$youtube-sign: \"\\f166\";\n\n$youtube: \"\\f167\";\n\n$xing: \"\\f168\";\n\n$xing-sign: \"\\f169\";\n\n$youtube-play: \"\\f16a\";\n\n$dropbox: \"\\f16b\";\n\n$stackexchange: \"\\f16c\";\n\n$instagram: \"\\f16d\";\n\n$flickr: \"\\f16e\";\n\n$adn: \"\\f170\";\n\n$bitbucket: \"\\f171\";\n\n$bitbucket-sign: \"\\f172\";\n\n$tumblr: \"\\f173\";\n\n$tumblr-sign: \"\\f174\";\n\n$long-arrow-down: \"\\f175\";\n\n$long-arrow-up: \"\\f176\";\n\n$long-arrow-left: \"\\f177\";\n\n$long-arrow-right: \"\\f178\";\n\n$apple: \"\\f179\";\n\n$windows: \"\\f17a\";\n\n$android: \"\\f17b\";\n\n$linux: \"\\f17c\";\n\n$dribbble: \"\\f17d\";\n\n$skype: \"\\f17e\";\n\n$foursquare: \"\\f180\";\n\n$trello: \"\\f181\";\n\n$female: \"\\f182\";\n\n$male: \"\\f183\";\n\n$gittip: \"\\f184\";\n\n$sun: \"\\f185\";\n\n$moon: \"\\f186\";\n\n$archive: \"\\f187\";\n\n$bug: \"\\f188\";\n\n$vk: \"\\f189\";\n\n$weibo: \"\\f18a\";\n\n$renren: \"\\f18b\";\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/scss/font-awesome-ie7.scss",
    "content": "/*!\n *  Font Awesome 3.2.1\n *  the iconic font designed for Bootstrap\n *  ------------------------------------------------------------------------------\n *  The full suite of pictographic icons, examples, and documentation can be\n *  found at http://fontawesome.io.  Stay up to date on Twitter at\n *  http://twitter.com/fontawesome.\n *\n *  License\n *  ------------------------------------------------------------------------------\n *  - The Font Awesome font is licensed under SIL OFL 1.1 -\n *    http://scripts.sil.org/OFL\n *  - Font Awesome CSS, LESS, and SASS files are licensed under MIT License -\n *    http://opensource.org/licenses/mit-license.html\n *  - Font Awesome documentation licensed under CC BY 3.0 -\n *    http://creativecommons.org/licenses/by/3.0/\n *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:\n *    \"Font Awesome by Dave Gandy - http://fontawesome.io\"\n *\n *  Author - Dave Gandy\n *  ------------------------------------------------------------------------------\n *  Email: dave@fontawesome.io\n *  Twitter: http://twitter.com/davegandy\n *  Work: Lead Product Designer @ Kyruus - http://kyruus.com\n */\n\n.icon-large {\n  font-size: (4em/3);\n  margin-top: -4px;\n  padding-top: 3px;\n  margin-bottom: -4px;\n  padding-bottom: 3px;\n  vertical-align: middle;\n}\n\n.nav {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    vertical-align: inherit;\n    margin-top: -4px;\n    padding-top: 3px;\n    margin-bottom: -4px;\n    padding-bottom: 3px;\n    &.icon-large {\n      vertical-align: -25%;\n    }\n  }\n}\n\n.nav-pills, .nav-tabs {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    &.icon-large {\n      line-height: .75em;\n      margin-top: -7px;\n      padding-top: 5px;\n      margin-bottom: -5px;\n      padding-bottom: 4px;\n    }\n  }\n}\n\n.btn {\n  [class^=\"icon-\"],\n  [class*=\" icon-\"] {\n    &.pull-left, &.pull-right { vertical-align: inherit; }\n    &.icon-large {\n      margin-top: -.5em;\n    }\n  }\n}\n\na [class^=\"icon-\"],\na [class*=\" icon-\"] {\n  cursor: pointer;\n}\n\n@mixin ie7icon($inner) { *zoom: expression(this.runtimeStyle['zoom'] = '1', this.innerHTML = '#{$inner}'); }\n\n\n.icon-glass {\n  @include ie7icon('&#xf000;');\n}\n\n\n.icon-music {\n  @include ie7icon('&#xf001;');\n}\n\n\n.icon-search {\n  @include ie7icon('&#xf002;');\n}\n\n\n.icon-envelope-alt {\n  @include ie7icon('&#xf003;');\n}\n\n\n.icon-heart {\n  @include ie7icon('&#xf004;');\n}\n\n\n.icon-star {\n  @include ie7icon('&#xf005;');\n}\n\n\n.icon-star-empty {\n  @include ie7icon('&#xf006;');\n}\n\n\n.icon-user {\n  @include ie7icon('&#xf007;');\n}\n\n\n.icon-film {\n  @include ie7icon('&#xf008;');\n}\n\n\n.icon-th-large {\n  @include ie7icon('&#xf009;');\n}\n\n\n.icon-th {\n  @include ie7icon('&#xf00a;');\n}\n\n\n.icon-th-list {\n  @include ie7icon('&#xf00b;');\n}\n\n\n.icon-ok {\n  @include ie7icon('&#xf00c;');\n}\n\n\n.icon-remove {\n  @include ie7icon('&#xf00d;');\n}\n\n\n.icon-zoom-in {\n  @include ie7icon('&#xf00e;');\n}\n\n\n.icon-zoom-out {\n  @include ie7icon('&#xf010;');\n}\n\n\n.icon-off {\n  @include ie7icon('&#xf011;');\n}\n\n.icon-power-off {\n  @include ie7icon('&#xf011;');\n}\n\n\n.icon-signal {\n  @include ie7icon('&#xf012;');\n}\n\n\n.icon-cog {\n  @include ie7icon('&#xf013;');\n}\n\n.icon-gear {\n  @include ie7icon('&#xf013;');\n}\n\n\n.icon-trash {\n  @include ie7icon('&#xf014;');\n}\n\n\n.icon-home {\n  @include ie7icon('&#xf015;');\n}\n\n\n.icon-file-alt {\n  @include ie7icon('&#xf016;');\n}\n\n\n.icon-time {\n  @include ie7icon('&#xf017;');\n}\n\n\n.icon-road {\n  @include ie7icon('&#xf018;');\n}\n\n\n.icon-download-alt {\n  @include ie7icon('&#xf019;');\n}\n\n\n.icon-download {\n  @include ie7icon('&#xf01a;');\n}\n\n\n.icon-upload {\n  @include ie7icon('&#xf01b;');\n}\n\n\n.icon-inbox {\n  @include ie7icon('&#xf01c;');\n}\n\n\n.icon-play-circle {\n  @include ie7icon('&#xf01d;');\n}\n\n\n.icon-repeat {\n  @include ie7icon('&#xf01e;');\n}\n\n.icon-rotate-right {\n  @include ie7icon('&#xf01e;');\n}\n\n\n.icon-refresh {\n  @include ie7icon('&#xf021;');\n}\n\n\n.icon-list-alt {\n  @include ie7icon('&#xf022;');\n}\n\n\n.icon-lock {\n  @include ie7icon('&#xf023;');\n}\n\n\n.icon-flag {\n  @include ie7icon('&#xf024;');\n}\n\n\n.icon-headphones {\n  @include ie7icon('&#xf025;');\n}\n\n\n.icon-volume-off {\n  @include ie7icon('&#xf026;');\n}\n\n\n.icon-volume-down {\n  @include ie7icon('&#xf027;');\n}\n\n\n.icon-volume-up {\n  @include ie7icon('&#xf028;');\n}\n\n\n.icon-qrcode {\n  @include ie7icon('&#xf029;');\n}\n\n\n.icon-barcode {\n  @include ie7icon('&#xf02a;');\n}\n\n\n.icon-tag {\n  @include ie7icon('&#xf02b;');\n}\n\n\n.icon-tags {\n  @include ie7icon('&#xf02c;');\n}\n\n\n.icon-book {\n  @include ie7icon('&#xf02d;');\n}\n\n\n.icon-bookmark {\n  @include ie7icon('&#xf02e;');\n}\n\n\n.icon-print {\n  @include ie7icon('&#xf02f;');\n}\n\n\n.icon-camera {\n  @include ie7icon('&#xf030;');\n}\n\n\n.icon-font {\n  @include ie7icon('&#xf031;');\n}\n\n\n.icon-bold {\n  @include ie7icon('&#xf032;');\n}\n\n\n.icon-italic {\n  @include ie7icon('&#xf033;');\n}\n\n\n.icon-text-height {\n  @include ie7icon('&#xf034;');\n}\n\n\n.icon-text-width {\n  @include ie7icon('&#xf035;');\n}\n\n\n.icon-align-left {\n  @include ie7icon('&#xf036;');\n}\n\n\n.icon-align-center {\n  @include ie7icon('&#xf037;');\n}\n\n\n.icon-align-right {\n  @include ie7icon('&#xf038;');\n}\n\n\n.icon-align-justify {\n  @include ie7icon('&#xf039;');\n}\n\n\n.icon-list {\n  @include ie7icon('&#xf03a;');\n}\n\n\n.icon-indent-left {\n  @include ie7icon('&#xf03b;');\n}\n\n\n.icon-indent-right {\n  @include ie7icon('&#xf03c;');\n}\n\n\n.icon-facetime-video {\n  @include ie7icon('&#xf03d;');\n}\n\n\n.icon-picture {\n  @include ie7icon('&#xf03e;');\n}\n\n\n.icon-pencil {\n  @include ie7icon('&#xf040;');\n}\n\n\n.icon-map-marker {\n  @include ie7icon('&#xf041;');\n}\n\n\n.icon-adjust {\n  @include ie7icon('&#xf042;');\n}\n\n\n.icon-tint {\n  @include ie7icon('&#xf043;');\n}\n\n\n.icon-edit {\n  @include ie7icon('&#xf044;');\n}\n\n\n.icon-share {\n  @include ie7icon('&#xf045;');\n}\n\n\n.icon-check {\n  @include ie7icon('&#xf046;');\n}\n\n\n.icon-move {\n  @include ie7icon('&#xf047;');\n}\n\n\n.icon-step-backward {\n  @include ie7icon('&#xf048;');\n}\n\n\n.icon-fast-backward {\n  @include ie7icon('&#xf049;');\n}\n\n\n.icon-backward {\n  @include ie7icon('&#xf04a;');\n}\n\n\n.icon-play {\n  @include ie7icon('&#xf04b;');\n}\n\n\n.icon-pause {\n  @include ie7icon('&#xf04c;');\n}\n\n\n.icon-stop {\n  @include ie7icon('&#xf04d;');\n}\n\n\n.icon-forward {\n  @include ie7icon('&#xf04e;');\n}\n\n\n.icon-fast-forward {\n  @include ie7icon('&#xf050;');\n}\n\n\n.icon-step-forward {\n  @include ie7icon('&#xf051;');\n}\n\n\n.icon-eject {\n  @include ie7icon('&#xf052;');\n}\n\n\n.icon-chevron-left {\n  @include ie7icon('&#xf053;');\n}\n\n\n.icon-chevron-right {\n  @include ie7icon('&#xf054;');\n}\n\n\n.icon-plus-sign {\n  @include ie7icon('&#xf055;');\n}\n\n\n.icon-minus-sign {\n  @include ie7icon('&#xf056;');\n}\n\n\n.icon-remove-sign {\n  @include ie7icon('&#xf057;');\n}\n\n\n.icon-ok-sign {\n  @include ie7icon('&#xf058;');\n}\n\n\n.icon-question-sign {\n  @include ie7icon('&#xf059;');\n}\n\n\n.icon-info-sign {\n  @include ie7icon('&#xf05a;');\n}\n\n\n.icon-screenshot {\n  @include ie7icon('&#xf05b;');\n}\n\n\n.icon-remove-circle {\n  @include ie7icon('&#xf05c;');\n}\n\n\n.icon-ok-circle {\n  @include ie7icon('&#xf05d;');\n}\n\n\n.icon-ban-circle {\n  @include ie7icon('&#xf05e;');\n}\n\n\n.icon-arrow-left {\n  @include ie7icon('&#xf060;');\n}\n\n\n.icon-arrow-right {\n  @include ie7icon('&#xf061;');\n}\n\n\n.icon-arrow-up {\n  @include ie7icon('&#xf062;');\n}\n\n\n.icon-arrow-down {\n  @include ie7icon('&#xf063;');\n}\n\n\n.icon-share-alt {\n  @include ie7icon('&#xf064;');\n}\n\n.icon-mail-forward {\n  @include ie7icon('&#xf064;');\n}\n\n\n.icon-resize-full {\n  @include ie7icon('&#xf065;');\n}\n\n\n.icon-resize-small {\n  @include ie7icon('&#xf066;');\n}\n\n\n.icon-plus {\n  @include ie7icon('&#xf067;');\n}\n\n\n.icon-minus {\n  @include ie7icon('&#xf068;');\n}\n\n\n.icon-asterisk {\n  @include ie7icon('&#xf069;');\n}\n\n\n.icon-exclamation-sign {\n  @include ie7icon('&#xf06a;');\n}\n\n\n.icon-gift {\n  @include ie7icon('&#xf06b;');\n}\n\n\n.icon-leaf {\n  @include ie7icon('&#xf06c;');\n}\n\n\n.icon-fire {\n  @include ie7icon('&#xf06d;');\n}\n\n\n.icon-eye-open {\n  @include ie7icon('&#xf06e;');\n}\n\n\n.icon-eye-close {\n  @include ie7icon('&#xf070;');\n}\n\n\n.icon-warning-sign {\n  @include ie7icon('&#xf071;');\n}\n\n\n.icon-plane {\n  @include ie7icon('&#xf072;');\n}\n\n\n.icon-calendar {\n  @include ie7icon('&#xf073;');\n}\n\n\n.icon-random {\n  @include ie7icon('&#xf074;');\n}\n\n\n.icon-comment {\n  @include ie7icon('&#xf075;');\n}\n\n\n.icon-magnet {\n  @include ie7icon('&#xf076;');\n}\n\n\n.icon-chevron-up {\n  @include ie7icon('&#xf077;');\n}\n\n\n.icon-chevron-down {\n  @include ie7icon('&#xf078;');\n}\n\n\n.icon-retweet {\n  @include ie7icon('&#xf079;');\n}\n\n\n.icon-shopping-cart {\n  @include ie7icon('&#xf07a;');\n}\n\n\n.icon-folder-close {\n  @include ie7icon('&#xf07b;');\n}\n\n\n.icon-folder-open {\n  @include ie7icon('&#xf07c;');\n}\n\n\n.icon-resize-vertical {\n  @include ie7icon('&#xf07d;');\n}\n\n\n.icon-resize-horizontal {\n  @include ie7icon('&#xf07e;');\n}\n\n\n.icon-bar-chart {\n  @include ie7icon('&#xf080;');\n}\n\n\n.icon-twitter-sign {\n  @include ie7icon('&#xf081;');\n}\n\n\n.icon-facebook-sign {\n  @include ie7icon('&#xf082;');\n}\n\n\n.icon-camera-retro {\n  @include ie7icon('&#xf083;');\n}\n\n\n.icon-key {\n  @include ie7icon('&#xf084;');\n}\n\n\n.icon-cogs {\n  @include ie7icon('&#xf085;');\n}\n\n.icon-gears {\n  @include ie7icon('&#xf085;');\n}\n\n\n.icon-comments {\n  @include ie7icon('&#xf086;');\n}\n\n\n.icon-thumbs-up-alt {\n  @include ie7icon('&#xf087;');\n}\n\n\n.icon-thumbs-down-alt {\n  @include ie7icon('&#xf088;');\n}\n\n\n.icon-star-half {\n  @include ie7icon('&#xf089;');\n}\n\n\n.icon-heart-empty {\n  @include ie7icon('&#xf08a;');\n}\n\n\n.icon-signout {\n  @include ie7icon('&#xf08b;');\n}\n\n\n.icon-linkedin-sign {\n  @include ie7icon('&#xf08c;');\n}\n\n\n.icon-pushpin {\n  @include ie7icon('&#xf08d;');\n}\n\n\n.icon-external-link {\n  @include ie7icon('&#xf08e;');\n}\n\n\n.icon-signin {\n  @include ie7icon('&#xf090;');\n}\n\n\n.icon-trophy {\n  @include ie7icon('&#xf091;');\n}\n\n\n.icon-github-sign {\n  @include ie7icon('&#xf092;');\n}\n\n\n.icon-upload-alt {\n  @include ie7icon('&#xf093;');\n}\n\n\n.icon-lemon {\n  @include ie7icon('&#xf094;');\n}\n\n\n.icon-phone {\n  @include ie7icon('&#xf095;');\n}\n\n\n.icon-check-empty {\n  @include ie7icon('&#xf096;');\n}\n\n.icon-unchecked {\n  @include ie7icon('&#xf096;');\n}\n\n\n.icon-bookmark-empty {\n  @include ie7icon('&#xf097;');\n}\n\n\n.icon-phone-sign {\n  @include ie7icon('&#xf098;');\n}\n\n\n.icon-twitter {\n  @include ie7icon('&#xf099;');\n}\n\n\n.icon-facebook {\n  @include ie7icon('&#xf09a;');\n}\n\n\n.icon-github {\n  @include ie7icon('&#xf09b;');\n}\n\n\n.icon-unlock {\n  @include ie7icon('&#xf09c;');\n}\n\n\n.icon-credit-card {\n  @include ie7icon('&#xf09d;');\n}\n\n\n.icon-rss {\n  @include ie7icon('&#xf09e;');\n}\n\n\n.icon-hdd {\n  @include ie7icon('&#xf0a0;');\n}\n\n\n.icon-bullhorn {\n  @include ie7icon('&#xf0a1;');\n}\n\n\n.icon-bell {\n  @include ie7icon('&#xf0a2;');\n}\n\n\n.icon-certificate {\n  @include ie7icon('&#xf0a3;');\n}\n\n\n.icon-hand-right {\n  @include ie7icon('&#xf0a4;');\n}\n\n\n.icon-hand-left {\n  @include ie7icon('&#xf0a5;');\n}\n\n\n.icon-hand-up {\n  @include ie7icon('&#xf0a6;');\n}\n\n\n.icon-hand-down {\n  @include ie7icon('&#xf0a7;');\n}\n\n\n.icon-circle-arrow-left {\n  @include ie7icon('&#xf0a8;');\n}\n\n\n.icon-circle-arrow-right {\n  @include ie7icon('&#xf0a9;');\n}\n\n\n.icon-circle-arrow-up {\n  @include ie7icon('&#xf0aa;');\n}\n\n\n.icon-circle-arrow-down {\n  @include ie7icon('&#xf0ab;');\n}\n\n\n.icon-globe {\n  @include ie7icon('&#xf0ac;');\n}\n\n\n.icon-wrench {\n  @include ie7icon('&#xf0ad;');\n}\n\n\n.icon-tasks {\n  @include ie7icon('&#xf0ae;');\n}\n\n\n.icon-filter {\n  @include ie7icon('&#xf0b0;');\n}\n\n\n.icon-briefcase {\n  @include ie7icon('&#xf0b1;');\n}\n\n\n.icon-fullscreen {\n  @include ie7icon('&#xf0b2;');\n}\n\n\n.icon-group {\n  @include ie7icon('&#xf0c0;');\n}\n\n\n.icon-link {\n  @include ie7icon('&#xf0c1;');\n}\n\n\n.icon-cloud {\n  @include ie7icon('&#xf0c2;');\n}\n\n\n.icon-beaker {\n  @include ie7icon('&#xf0c3;');\n}\n\n\n.icon-cut {\n  @include ie7icon('&#xf0c4;');\n}\n\n\n.icon-copy {\n  @include ie7icon('&#xf0c5;');\n}\n\n\n.icon-paper-clip {\n  @include ie7icon('&#xf0c6;');\n}\n\n.icon-paperclip {\n  @include ie7icon('&#xf0c6;');\n}\n\n\n.icon-save {\n  @include ie7icon('&#xf0c7;');\n}\n\n\n.icon-sign-blank {\n  @include ie7icon('&#xf0c8;');\n}\n\n\n.icon-reorder {\n  @include ie7icon('&#xf0c9;');\n}\n\n\n.icon-list-ul {\n  @include ie7icon('&#xf0ca;');\n}\n\n\n.icon-list-ol {\n  @include ie7icon('&#xf0cb;');\n}\n\n\n.icon-strikethrough {\n  @include ie7icon('&#xf0cc;');\n}\n\n\n.icon-underline {\n  @include ie7icon('&#xf0cd;');\n}\n\n\n.icon-table {\n  @include ie7icon('&#xf0ce;');\n}\n\n\n.icon-magic {\n  @include ie7icon('&#xf0d0;');\n}\n\n\n.icon-truck {\n  @include ie7icon('&#xf0d1;');\n}\n\n\n.icon-pinterest {\n  @include ie7icon('&#xf0d2;');\n}\n\n\n.icon-pinterest-sign {\n  @include ie7icon('&#xf0d3;');\n}\n\n\n.icon-google-plus-sign {\n  @include ie7icon('&#xf0d4;');\n}\n\n\n.icon-google-plus {\n  @include ie7icon('&#xf0d5;');\n}\n\n\n.icon-money {\n  @include ie7icon('&#xf0d6;');\n}\n\n\n.icon-caret-down {\n  @include ie7icon('&#xf0d7;');\n}\n\n\n.icon-caret-up {\n  @include ie7icon('&#xf0d8;');\n}\n\n\n.icon-caret-left {\n  @include ie7icon('&#xf0d9;');\n}\n\n\n.icon-caret-right {\n  @include ie7icon('&#xf0da;');\n}\n\n\n.icon-columns {\n  @include ie7icon('&#xf0db;');\n}\n\n\n.icon-sort {\n  @include ie7icon('&#xf0dc;');\n}\n\n\n.icon-sort-down {\n  @include ie7icon('&#xf0dd;');\n}\n\n\n.icon-sort-up {\n  @include ie7icon('&#xf0de;');\n}\n\n\n.icon-envelope {\n  @include ie7icon('&#xf0e0;');\n}\n\n\n.icon-linkedin {\n  @include ie7icon('&#xf0e1;');\n}\n\n\n.icon-undo {\n  @include ie7icon('&#xf0e2;');\n}\n\n.icon-rotate-left {\n  @include ie7icon('&#xf0e2;');\n}\n\n\n.icon-legal {\n  @include ie7icon('&#xf0e3;');\n}\n\n\n.icon-dashboard {\n  @include ie7icon('&#xf0e4;');\n}\n\n\n.icon-comment-alt {\n  @include ie7icon('&#xf0e5;');\n}\n\n\n.icon-comments-alt {\n  @include ie7icon('&#xf0e6;');\n}\n\n\n.icon-bolt {\n  @include ie7icon('&#xf0e7;');\n}\n\n\n.icon-sitemap {\n  @include ie7icon('&#xf0e8;');\n}\n\n\n.icon-umbrella {\n  @include ie7icon('&#xf0e9;');\n}\n\n\n.icon-paste {\n  @include ie7icon('&#xf0ea;');\n}\n\n\n.icon-lightbulb {\n  @include ie7icon('&#xf0eb;');\n}\n\n\n.icon-exchange {\n  @include ie7icon('&#xf0ec;');\n}\n\n\n.icon-cloud-download {\n  @include ie7icon('&#xf0ed;');\n}\n\n\n.icon-cloud-upload {\n  @include ie7icon('&#xf0ee;');\n}\n\n\n.icon-user-md {\n  @include ie7icon('&#xf0f0;');\n}\n\n\n.icon-stethoscope {\n  @include ie7icon('&#xf0f1;');\n}\n\n\n.icon-suitcase {\n  @include ie7icon('&#xf0f2;');\n}\n\n\n.icon-bell-alt {\n  @include ie7icon('&#xf0f3;');\n}\n\n\n.icon-coffee {\n  @include ie7icon('&#xf0f4;');\n}\n\n\n.icon-food {\n  @include ie7icon('&#xf0f5;');\n}\n\n\n.icon-file-text-alt {\n  @include ie7icon('&#xf0f6;');\n}\n\n\n.icon-building {\n  @include ie7icon('&#xf0f7;');\n}\n\n\n.icon-hospital {\n  @include ie7icon('&#xf0f8;');\n}\n\n\n.icon-ambulance {\n  @include ie7icon('&#xf0f9;');\n}\n\n\n.icon-medkit {\n  @include ie7icon('&#xf0fa;');\n}\n\n\n.icon-fighter-jet {\n  @include ie7icon('&#xf0fb;');\n}\n\n\n.icon-beer {\n  @include ie7icon('&#xf0fc;');\n}\n\n\n.icon-h-sign {\n  @include ie7icon('&#xf0fd;');\n}\n\n\n.icon-plus-sign-alt {\n  @include ie7icon('&#xf0fe;');\n}\n\n\n.icon-double-angle-left {\n  @include ie7icon('&#xf100;');\n}\n\n\n.icon-double-angle-right {\n  @include ie7icon('&#xf101;');\n}\n\n\n.icon-double-angle-up {\n  @include ie7icon('&#xf102;');\n}\n\n\n.icon-double-angle-down {\n  @include ie7icon('&#xf103;');\n}\n\n\n.icon-angle-left {\n  @include ie7icon('&#xf104;');\n}\n\n\n.icon-angle-right {\n  @include ie7icon('&#xf105;');\n}\n\n\n.icon-angle-up {\n  @include ie7icon('&#xf106;');\n}\n\n\n.icon-angle-down {\n  @include ie7icon('&#xf107;');\n}\n\n\n.icon-desktop {\n  @include ie7icon('&#xf108;');\n}\n\n\n.icon-laptop {\n  @include ie7icon('&#xf109;');\n}\n\n\n.icon-tablet {\n  @include ie7icon('&#xf10a;');\n}\n\n\n.icon-mobile-phone {\n  @include ie7icon('&#xf10b;');\n}\n\n\n.icon-circle-blank {\n  @include ie7icon('&#xf10c;');\n}\n\n\n.icon-quote-left {\n  @include ie7icon('&#xf10d;');\n}\n\n\n.icon-quote-right {\n  @include ie7icon('&#xf10e;');\n}\n\n\n.icon-spinner {\n  @include ie7icon('&#xf110;');\n}\n\n\n.icon-circle {\n  @include ie7icon('&#xf111;');\n}\n\n\n.icon-reply {\n  @include ie7icon('&#xf112;');\n}\n\n.icon-mail-reply {\n  @include ie7icon('&#xf112;');\n}\n\n\n.icon-github-alt {\n  @include ie7icon('&#xf113;');\n}\n\n\n.icon-folder-close-alt {\n  @include ie7icon('&#xf114;');\n}\n\n\n.icon-folder-open-alt {\n  @include ie7icon('&#xf115;');\n}\n\n\n.icon-expand-alt {\n  @include ie7icon('&#xf116;');\n}\n\n\n.icon-collapse-alt {\n  @include ie7icon('&#xf117;');\n}\n\n\n.icon-smile {\n  @include ie7icon('&#xf118;');\n}\n\n\n.icon-frown {\n  @include ie7icon('&#xf119;');\n}\n\n\n.icon-meh {\n  @include ie7icon('&#xf11a;');\n}\n\n\n.icon-gamepad {\n  @include ie7icon('&#xf11b;');\n}\n\n\n.icon-keyboard {\n  @include ie7icon('&#xf11c;');\n}\n\n\n.icon-flag-alt {\n  @include ie7icon('&#xf11d;');\n}\n\n\n.icon-flag-checkered {\n  @include ie7icon('&#xf11e;');\n}\n\n\n.icon-terminal {\n  @include ie7icon('&#xf120;');\n}\n\n\n.icon-code {\n  @include ie7icon('&#xf121;');\n}\n\n\n.icon-reply-all {\n  @include ie7icon('&#xf122;');\n}\n\n\n.icon-mail-reply-all {\n  @include ie7icon('&#xf122;');\n}\n\n\n.icon-star-half-empty {\n  @include ie7icon('&#xf123;');\n}\n\n.icon-star-half-full {\n  @include ie7icon('&#xf123;');\n}\n\n\n.icon-location-arrow {\n  @include ie7icon('&#xf124;');\n}\n\n\n.icon-crop {\n  @include ie7icon('&#xf125;');\n}\n\n\n.icon-code-fork {\n  @include ie7icon('&#xf126;');\n}\n\n\n.icon-unlink {\n  @include ie7icon('&#xf127;');\n}\n\n\n.icon-question {\n  @include ie7icon('&#xf128;');\n}\n\n\n.icon-info {\n  @include ie7icon('&#xf129;');\n}\n\n\n.icon-exclamation {\n  @include ie7icon('&#xf12a;');\n}\n\n\n.icon-superscript {\n  @include ie7icon('&#xf12b;');\n}\n\n\n.icon-subscript {\n  @include ie7icon('&#xf12c;');\n}\n\n\n.icon-eraser {\n  @include ie7icon('&#xf12d;');\n}\n\n\n.icon-puzzle-piece {\n  @include ie7icon('&#xf12e;');\n}\n\n\n.icon-microphone {\n  @include ie7icon('&#xf130;');\n}\n\n\n.icon-microphone-off {\n  @include ie7icon('&#xf131;');\n}\n\n\n.icon-shield {\n  @include ie7icon('&#xf132;');\n}\n\n\n.icon-calendar-empty {\n  @include ie7icon('&#xf133;');\n}\n\n\n.icon-fire-extinguisher {\n  @include ie7icon('&#xf134;');\n}\n\n\n.icon-rocket {\n  @include ie7icon('&#xf135;');\n}\n\n\n.icon-maxcdn {\n  @include ie7icon('&#xf136;');\n}\n\n\n.icon-chevron-sign-left {\n  @include ie7icon('&#xf137;');\n}\n\n\n.icon-chevron-sign-right {\n  @include ie7icon('&#xf138;');\n}\n\n\n.icon-chevron-sign-up {\n  @include ie7icon('&#xf139;');\n}\n\n\n.icon-chevron-sign-down {\n  @include ie7icon('&#xf13a;');\n}\n\n\n.icon-html5 {\n  @include ie7icon('&#xf13b;');\n}\n\n\n.icon-css3 {\n  @include ie7icon('&#xf13c;');\n}\n\n\n.icon-anchor {\n  @include ie7icon('&#xf13d;');\n}\n\n\n.icon-unlock-alt {\n  @include ie7icon('&#xf13e;');\n}\n\n\n.icon-bullseye {\n  @include ie7icon('&#xf140;');\n}\n\n\n.icon-ellipsis-horizontal {\n  @include ie7icon('&#xf141;');\n}\n\n\n.icon-ellipsis-vertical {\n  @include ie7icon('&#xf142;');\n}\n\n\n.icon-rss-sign {\n  @include ie7icon('&#xf143;');\n}\n\n\n.icon-play-sign {\n  @include ie7icon('&#xf144;');\n}\n\n\n.icon-ticket {\n  @include ie7icon('&#xf145;');\n}\n\n\n.icon-minus-sign-alt {\n  @include ie7icon('&#xf146;');\n}\n\n\n.icon-check-minus {\n  @include ie7icon('&#xf147;');\n}\n\n\n.icon-level-up {\n  @include ie7icon('&#xf148;');\n}\n\n\n.icon-level-down {\n  @include ie7icon('&#xf149;');\n}\n\n\n.icon-check-sign {\n  @include ie7icon('&#xf14a;');\n}\n\n\n.icon-edit-sign {\n  @include ie7icon('&#xf14b;');\n}\n\n\n.icon-external-link-sign {\n  @include ie7icon('&#xf14c;');\n}\n\n\n.icon-share-sign {\n  @include ie7icon('&#xf14d;');\n}\n\n\n.icon-compass {\n  @include ie7icon('&#xf14e;');\n}\n\n\n.icon-collapse {\n  @include ie7icon('&#xf150;');\n}\n\n\n.icon-collapse-top {\n  @include ie7icon('&#xf151;');\n}\n\n\n.icon-expand {\n  @include ie7icon('&#xf152;');\n}\n\n\n.icon-eur {\n  @include ie7icon('&#xf153;');\n}\n\n.icon-euro {\n  @include ie7icon('&#xf153;');\n}\n\n\n.icon-gbp {\n  @include ie7icon('&#xf154;');\n}\n\n\n.icon-usd {\n  @include ie7icon('&#xf155;');\n}\n\n.icon-dollar {\n  @include ie7icon('&#xf155;');\n}\n\n\n.icon-inr {\n  @include ie7icon('&#xf156;');\n}\n\n.icon-rupee {\n  @include ie7icon('&#xf156;');\n}\n\n\n.icon-jpy {\n  @include ie7icon('&#xf157;');\n}\n\n.icon-yen {\n  @include ie7icon('&#xf157;');\n}\n\n\n.icon-cny {\n  @include ie7icon('&#xf158;');\n}\n\n.icon-renminbi {\n  @include ie7icon('&#xf158;');\n}\n\n\n.icon-krw {\n  @include ie7icon('&#xf159;');\n}\n\n.icon-won {\n  @include ie7icon('&#xf159;');\n}\n\n\n.icon-btc {\n  @include ie7icon('&#xf15a;');\n}\n\n.icon-bitcoin {\n  @include ie7icon('&#xf15a;');\n}\n\n\n.icon-file {\n  @include ie7icon('&#xf15b;');\n}\n\n\n.icon-file-text {\n  @include ie7icon('&#xf15c;');\n}\n\n\n.icon-sort-by-alphabet {\n  @include ie7icon('&#xf15d;');\n}\n\n\n.icon-sort-by-alphabet-alt {\n  @include ie7icon('&#xf15e;');\n}\n\n\n.icon-sort-by-attributes {\n  @include ie7icon('&#xf160;');\n}\n\n\n.icon-sort-by-attributes-alt {\n  @include ie7icon('&#xf161;');\n}\n\n\n.icon-sort-by-order {\n  @include ie7icon('&#xf162;');\n}\n\n\n.icon-sort-by-order-alt {\n  @include ie7icon('&#xf163;');\n}\n\n\n.icon-thumbs-up {\n  @include ie7icon('&#xf164;');\n}\n\n\n.icon-thumbs-down {\n  @include ie7icon('&#xf165;');\n}\n\n\n.icon-youtube-sign {\n  @include ie7icon('&#xf166;');\n}\n\n\n.icon-youtube {\n  @include ie7icon('&#xf167;');\n}\n\n\n.icon-xing {\n  @include ie7icon('&#xf168;');\n}\n\n\n.icon-xing-sign {\n  @include ie7icon('&#xf169;');\n}\n\n\n.icon-youtube-play {\n  @include ie7icon('&#xf16a;');\n}\n\n\n.icon-dropbox {\n  @include ie7icon('&#xf16b;');\n}\n\n\n.icon-stackexchange {\n  @include ie7icon('&#xf16c;');\n}\n\n\n.icon-instagram {\n  @include ie7icon('&#xf16d;');\n}\n\n\n.icon-flickr {\n  @include ie7icon('&#xf16e;');\n}\n\n\n.icon-adn {\n  @include ie7icon('&#xf170;');\n}\n\n\n.icon-bitbucket {\n  @include ie7icon('&#xf171;');\n}\n\n\n.icon-bitbucket-sign {\n  @include ie7icon('&#xf172;');\n}\n\n\n.icon-tumblr {\n  @include ie7icon('&#xf173;');\n}\n\n\n.icon-tumblr-sign {\n  @include ie7icon('&#xf174;');\n}\n\n\n.icon-long-arrow-down {\n  @include ie7icon('&#xf175;');\n}\n\n\n.icon-long-arrow-up {\n  @include ie7icon('&#xf176;');\n}\n\n\n.icon-long-arrow-left {\n  @include ie7icon('&#xf177;');\n}\n\n\n.icon-long-arrow-right {\n  @include ie7icon('&#xf178;');\n}\n\n\n.icon-apple {\n  @include ie7icon('&#xf179;');\n}\n\n\n.icon-windows {\n  @include ie7icon('&#xf17a;');\n}\n\n\n.icon-android {\n  @include ie7icon('&#xf17b;');\n}\n\n\n.icon-linux {\n  @include ie7icon('&#xf17c;');\n}\n\n\n.icon-dribbble {\n  @include ie7icon('&#xf17d;');\n}\n\n\n.icon-skype {\n  @include ie7icon('&#xf17e;');\n}\n\n\n.icon-foursquare {\n  @include ie7icon('&#xf180;');\n}\n\n\n.icon-trello {\n  @include ie7icon('&#xf181;');\n}\n\n\n.icon-female {\n  @include ie7icon('&#xf182;');\n}\n\n\n.icon-male {\n  @include ie7icon('&#xf183;');\n}\n\n\n.icon-gittip {\n  @include ie7icon('&#xf184;');\n}\n\n\n.icon-sun {\n  @include ie7icon('&#xf185;');\n}\n\n\n.icon-moon {\n  @include ie7icon('&#xf186;');\n}\n\n\n.icon-archive {\n  @include ie7icon('&#xf187;');\n}\n\n\n.icon-bug {\n  @include ie7icon('&#xf188;');\n}\n\n\n.icon-vk {\n  @include ie7icon('&#xf189;');\n}\n\n\n.icon-weibo {\n  @include ie7icon('&#xf18a;');\n}\n\n\n.icon-renren {\n  @include ie7icon('&#xf18b;');\n}\n\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/font-awesome/scss/font-awesome.scss",
    "content": "/*!\n *  Font Awesome 3.2.1\n *  the iconic font designed for Bootstrap\n *  ------------------------------------------------------------------------------\n *  The full suite of pictographic icons, examples, and documentation can be\n *  found at http://fontawesome.io.  Stay up to date on Twitter at\n *  http://twitter.com/fontawesome.\n *\n *  License\n *  ------------------------------------------------------------------------------\n *  - The Font Awesome font is licensed under SIL OFL 1.1 -\n *    http://scripts.sil.org/OFL\n *  - Font Awesome CSS, LESS, and SASS files are licensed under MIT License -\n *    http://opensource.org/licenses/mit-license.html\n *  - Font Awesome documentation licensed under CC BY 3.0 -\n *    http://creativecommons.org/licenses/by/3.0/\n *  - Attribution is no longer required in Font Awesome 3.0, but much appreciated:\n *    \"Font Awesome by Dave Gandy - http://fontawesome.io\"\n *\n *  Author - Dave Gandy\n *  ------------------------------------------------------------------------------\n *  Email: dave@fontawesome.io\n *  Twitter: http://twitter.com/davegandy\n *  Work: Lead Product Designer @ Kyruus - http://kyruus.com\n */\n\n@import \"variables\";\n@import \"mixins\";\n@import \"path\";\n@import \"core\";\n@import \"bootstrap\";\n@import \"extras\";\n@import \"icons\";\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/jquery-easy-pie-chart/Makefile",
    "content": "dist: all\n\t@echo Done\n\nall:\n\t@echo Compiling coffee script\n\tcoffee -c *.coffee\n\nwatch:\n\t@echo Watch coffee script files\n\tcoffee -w *.coffee\n\n.PHONY: dist all watch"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/jquery-easy-pie-chart/Readme.md",
    "content": "easy pie chart\n==============\n\nEasy pie chart is a jQuery plugin that uses the canvas element to render simple pie charts for single values.\nThese charts are highly customizable, very easy to implement and **scale to the resolution of the display of the client to provide sharp charts even on retina displays**.\n\n![](https://github.com/rendro/easy-pie-chart/raw/master/img/easy-pie-chart.png)\n\nGet started\n-----------\n\nTo use the easy pie chart plugin you need to load the current version of jQuery (testet with 1.7.2) and the source (css+js) of the plugin.\nJust add the following lines to the `head` of your website:\n\n    <script type=\"text/javascript\" src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js\"></script>\n    <script type=\"text/javascript\" src=\"/path/to/jquery.easy-pie-chart.js\"></script>\n\n    <link rel=\"stylesheet\"type=\"text/css\" href=\"/path/to/jquery.easy-pie-chart.css\">\n\nThe second step is to add a element to your site to represent chart and add the `data-percent` attribute with the percent number the pie chart should have:\n\n    <div class=\"chart\" data-percent=\"73\">73%</div>\n\nFinally you have to initialize the plugin with your desired configuration:\n\n    <script type=\"text/javascript\">\n    $(function() {\n        $('.chart').easyPieChart({\n            //your configuration goes here\n        });\n    });\n    </script>\n\nConfiguration parameter\n-----------------------\n\nYou can pass a set of these options to the initialize function to set a custom behaviour and look for the plugin.\n\n<table>\n    <tr>\n        <th>Property (Type)</th>\n        <th>Default</th>\n        <th>Description</th>\n    </tr>\n    <tr>\n        <td><strong>barColor</strong></td>\n        <td>#ef1e25</td>\n        <td>The color of the curcular bar. You can pass either a css valid color string like rgb, rgba hex or string colors. But you can also pass a function that accepts the current percentage as a value to return a dynamically generated color.</td>\n    </tr>\n    <tr>\n        <td><strong>trackColor</strong></td>\n        <td>#f2f2f2</td>\n        <td>The color of the track for the bar, false to disable rendering.</td>\n    </tr>\n    <tr>\n        <td><strong>scaleColor</strong></td>\n        <td>#dfe0e0</td>\n        <td>The color of the scale lines, false to disable rendering.</td>\n    </tr>\n    <tr>\n        <td><strong>lineCap</strong></td>\n        <td>round</td>\n        <td>Defines how the ending of the bar line looks like. Possible values are: <code>butt</code>, <code>round</code> and <code>square</code>.</td>\n    </tr>\n    <tr>\n        <td><strong>lineWidth</strong></td>\n        <td>3</td>\n        <td>Width of the bar line in px.</td>\n    </tr>\n    <tr>\n        <td><strong>size</strong></td>\n        <td>110</td>\n        <td>Size of the pie chart in px. It will always be a square.</td>\n    </tr>\n    <tr>\n        <td><strong>animate</strong></td>\n        <td>false</td>\n        <td>Time in milliseconds for a eased animation of the bar growing, or false to deactivate.</td>\n    </tr>\n    <tr>\n        <td><strong>onStart</strong></td>\n        <td>$.noop</td>\n        <td>Callback function that is called at the start of any animation (only if animate is not false).</td>\n    </tr>\n    <tr>\n        <td><strong>onStop</strong></td>\n        <td>$.noop</td>\n        <td>Callback function that is called at the end of any animation (only if animate is not false).</td>\n    </tr>\n</table>\n\n\nPublic plugin methods\n---------------------\n\nIf you want to update the current percentage of the a pie chart, you can call the `update` method. The instance of the plugin is saved in the jQuery-data.\n\n    <script type=\"text/javascript\">\n    $(function() {\n        //create instance\n        $('.chart').easyPieChart({\n            animate: 2000\n        });\n        //update instance after 5 sec\n        setTimeout(function() {\n            $('.chart').data('easyPieChart').update(40);\n        }, 5000);\n    });\n    </script>\n\nCredits\n-------\n\nThanks to [Rafal Bromirski](http://www.paranoida.com/) for making [this dribble shot](http://drbl.in/ezuc) which inspired me and [Philip Thrasher](http://philipthrasher.com/) for his [CoffeeScript jQuery boilerplate](https://github.com/pthrasher/coffee-plate)\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/jquery-easy-pie-chart/examples/excanvas.js",
    "content": "// Copyright 2006 Google Inc.\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// Known Issues:\n//\n// * Patterns are not implemented.\n// * Radial gradient are not implemented. The VML version of these look very\n//   different from the canvas one.\n// * Clipping paths are not implemented.\n// * Coordsize. The width and height attribute have higher priority than the\n//   width and height style values which isn't correct.\n// * Painting mode isn't implemented.\n// * Canvas width/height should is using content-box by default. IE in\n//   Quirks mode will draw the canvas using border-box. Either change your\n//   doctype to HTML5\n//   (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)\n//   or use Box Sizing Behavior from WebFX\n//   (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)\n// * Non uniform scaling does not correctly scale strokes.\n// * Optimize. There is always room for speed improvements.\n\n// Only add this code if we do not already have a canvas implementation\nif (!document.createElement('canvas').getContext) {\n\n(function() {\n\n  // alias some functions to make (compiled) code shorter\n  var m = Math;\n  var mr = m.round;\n  var ms = m.sin;\n  var mc = m.cos;\n  var abs = m.abs;\n  var sqrt = m.sqrt;\n\n  // this is used for sub pixel precision\n  var Z = 10;\n  var Z2 = Z / 2;\n\n  /**\n   * This funtion is assigned to the <canvas> elements as element.getContext().\n   * @this {HTMLElement}\n   * @return {CanvasRenderingContext2D_}\n   */\n  function getContext() {\n    return this.context_ ||\n        (this.context_ = new CanvasRenderingContext2D_(this));\n  }\n\n  var slice = Array.prototype.slice;\n\n  /**\n   * Binds a function to an object. The returned function will always use the\n   * passed in {@code obj} as {@code this}.\n   *\n   * Example:\n   *\n   *   g = bind(f, obj, a, b)\n   *   g(c, d) // will do f.call(obj, a, b, c, d)\n   *\n   * @param {Function} f The function to bind the object to\n   * @param {Object} obj The object that should act as this when the function\n   *     is called\n   * @param {*} var_args Rest arguments that will be used as the initial\n   *     arguments when the function is called\n   * @return {Function} A new function that has bound this\n   */\n  function bind(f, obj, var_args) {\n    var a = slice.call(arguments, 2);\n    return function() {\n      return f.apply(obj, a.concat(slice.call(arguments)));\n    };\n  }\n\n  var G_vmlCanvasManager_ = {\n    init: function(opt_doc) {\n      if (/MSIE/.test(navigator.userAgent) && !window.opera) {\n        var doc = opt_doc || document;\n        // Create a dummy element so that IE will allow canvas elements to be\n        // recognized.\n        doc.createElement('canvas');\n        doc.attachEvent('onreadystatechange', bind(this.init_, this, doc));\n      }\n    },\n\n    init_: function(doc) {\n      // create xmlns\n      if (!doc.namespaces['g_vml_']) {\n        doc.namespaces.add('g_vml_', 'urn:schemas-microsoft-com:vml',\n                           '#default#VML');\n\n      }\n      if (!doc.namespaces['g_o_']) {\n        doc.namespaces.add('g_o_', 'urn:schemas-microsoft-com:office:office',\n                           '#default#VML');\n      }\n\n      // Setup default CSS.  Only add one style sheet per document\n      if (!doc.styleSheets['ex_canvas_']) {\n        var ss = doc.createStyleSheet();\n        ss.owningElement.id = 'ex_canvas_';\n        ss.cssText = 'canvas{display:inline-block;overflow:hidden;' +\n            // default size is 300x150 in Gecko and Opera\n            'text-align:left;width:300px;height:150px}' +\n            'g_vml_\\\\:*{behavior:url(#default#VML)}' +\n            'g_o_\\\\:*{behavior:url(#default#VML)}';\n\n      }\n\n      // find all canvas elements\n      var els = doc.getElementsByTagName('canvas');\n      for (var i = 0; i < els.length; i++) {\n        this.initElement(els[i]);\n      }\n    },\n\n    /**\n     * Public initializes a canvas element so that it can be used as canvas\n     * element from now on. This is called automatically before the page is\n     * loaded but if you are creating elements using createElement you need to\n     * make sure this is called on the element.\n     * @param {HTMLElement} el The canvas element to initialize.\n     * @return {HTMLElement} the element that was created.\n     */\n    initElement: function(el) {\n      if (!el.getContext) {\n\n        el.getContext = getContext;\n\n        // Remove fallback content. There is no way to hide text nodes so we\n        // just remove all childNodes. We could hide all elements and remove\n        // text nodes but who really cares about the fallback content.\n        el.innerHTML = '';\n\n        // do not use inline function because that will leak memory\n        el.attachEvent('onpropertychange', onPropertyChange);\n        el.attachEvent('onresize', onResize);\n\n        var attrs = el.attributes;\n        if (attrs.width && attrs.width.specified) {\n          // TODO: use runtimeStyle and coordsize\n          // el.getContext().setWidth_(attrs.width.nodeValue);\n          el.style.width = attrs.width.nodeValue + 'px';\n        } else {\n          el.width = el.clientWidth;\n        }\n        if (attrs.height && attrs.height.specified) {\n          // TODO: use runtimeStyle and coordsize\n          // el.getContext().setHeight_(attrs.height.nodeValue);\n          el.style.height = attrs.height.nodeValue + 'px';\n        } else {\n          el.height = el.clientHeight;\n        }\n        //el.getContext().setCoordsize_()\n      }\n      return el;\n    }\n  };\n\n  function onPropertyChange(e) {\n    var el = e.srcElement;\n\n    switch (e.propertyName) {\n      case 'width':\n        el.style.width = el.attributes.width.nodeValue + 'px';\n        el.getContext().clearRect();\n        break;\n      case 'height':\n        el.style.height = el.attributes.height.nodeValue + 'px';\n        el.getContext().clearRect();\n        break;\n    }\n  }\n\n  function onResize(e) {\n    var el = e.srcElement;\n    if (el.firstChild) {\n      el.firstChild.style.width =  el.clientWidth + 'px';\n      el.firstChild.style.height = el.clientHeight + 'px';\n    }\n  }\n\n  G_vmlCanvasManager_.init();\n\n  // precompute \"00\" to \"FF\"\n  var dec2hex = [];\n  for (var i = 0; i < 16; i++) {\n    for (var j = 0; j < 16; j++) {\n      dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);\n    }\n  }\n\n  function createMatrixIdentity() {\n    return [\n      [1, 0, 0],\n      [0, 1, 0],\n      [0, 0, 1]\n    ];\n  }\n\n  function matrixMultiply(m1, m2) {\n    var result = createMatrixIdentity();\n\n    for (var x = 0; x < 3; x++) {\n      for (var y = 0; y < 3; y++) {\n        var sum = 0;\n\n        for (var z = 0; z < 3; z++) {\n          sum += m1[x][z] * m2[z][y];\n        }\n\n        result[x][y] = sum;\n      }\n    }\n    return result;\n  }\n\n  function copyState(o1, o2) {\n    o2.fillStyle     = o1.fillStyle;\n    o2.lineCap       = o1.lineCap;\n    o2.lineJoin      = o1.lineJoin;\n    o2.lineWidth     = o1.lineWidth;\n    o2.miterLimit    = o1.miterLimit;\n    o2.shadowBlur    = o1.shadowBlur;\n    o2.shadowColor   = o1.shadowColor;\n    o2.shadowOffsetX = o1.shadowOffsetX;\n    o2.shadowOffsetY = o1.shadowOffsetY;\n    o2.strokeStyle   = o1.strokeStyle;\n    o2.globalAlpha   = o1.globalAlpha;\n    o2.arcScaleX_    = o1.arcScaleX_;\n    o2.arcScaleY_    = o1.arcScaleY_;\n    o2.lineScale_    = o1.lineScale_;\n  }\n\n  function processStyle(styleString) {\n    var str, alpha = 1;\n\n    styleString = String(styleString);\n    if (styleString.substring(0, 3) == 'rgb') {\n      var start = styleString.indexOf('(', 3);\n      var end = styleString.indexOf(')', start + 1);\n      var guts = styleString.substring(start + 1, end).split(',');\n\n      str = '#';\n      for (var i = 0; i < 3; i++) {\n        str += dec2hex[Number(guts[i])];\n      }\n\n      if (guts.length == 4 && styleString.substr(3, 1) == 'a') {\n        alpha = guts[3];\n      }\n    } else {\n      str = styleString;\n    }\n\n    return {color: str, alpha: alpha};\n  }\n\n  function processLineCap(lineCap) {\n    switch (lineCap) {\n      case 'butt':\n        return 'flat';\n      case 'round':\n        return 'round';\n      case 'square':\n      default:\n        return 'square';\n    }\n  }\n\n  /**\n   * This class implements CanvasRenderingContext2D interface as described by\n   * the WHATWG.\n   * @param {HTMLElement} surfaceElement The element that the 2D context should\n   * be associated with\n   */\n  function CanvasRenderingContext2D_(surfaceElement) {\n    this.m_ = createMatrixIdentity();\n\n    this.mStack_ = [];\n    this.aStack_ = [];\n    this.currentPath_ = [];\n\n    // Canvas context properties\n    this.strokeStyle = '#000';\n    this.fillStyle = '#000';\n\n    this.lineWidth = 1;\n    this.lineJoin = 'miter';\n    this.lineCap = 'butt';\n    this.miterLimit = Z * 1;\n    this.globalAlpha = 1;\n    this.canvas = surfaceElement;\n\n    var el = surfaceElement.ownerDocument.createElement('div');\n    el.style.width =  surfaceElement.clientWidth + 'px';\n    el.style.height = surfaceElement.clientHeight + 'px';\n    el.style.overflow = 'hidden';\n    el.style.position = 'absolute';\n    surfaceElement.appendChild(el);\n\n    this.element_ = el;\n    this.arcScaleX_ = 1;\n    this.arcScaleY_ = 1;\n    this.lineScale_ = 1;\n  }\n\n  var contextPrototype = CanvasRenderingContext2D_.prototype;\n  contextPrototype.clearRect = function() {\n    this.element_.innerHTML = '';\n  };\n\n  contextPrototype.beginPath = function() {\n    // TODO: Branch current matrix so that save/restore has no effect\n    //       as per safari docs.\n    this.currentPath_ = [];\n  };\n\n  contextPrototype.moveTo = function(aX, aY) {\n    var p = this.getCoords_(aX, aY);\n    this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y});\n    this.currentX_ = p.x;\n    this.currentY_ = p.y;\n  };\n\n  contextPrototype.lineTo = function(aX, aY) {\n    var p = this.getCoords_(aX, aY);\n    this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y});\n\n    this.currentX_ = p.x;\n    this.currentY_ = p.y;\n  };\n\n  contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,\n                                            aCP2x, aCP2y,\n                                            aX, aY) {\n    var p = this.getCoords_(aX, aY);\n    var cp1 = this.getCoords_(aCP1x, aCP1y);\n    var cp2 = this.getCoords_(aCP2x, aCP2y);\n    bezierCurveTo(this, cp1, cp2, p);\n  };\n\n  // Helper function that takes the already fixed cordinates.\n  function bezierCurveTo(self, cp1, cp2, p) {\n    self.currentPath_.push({\n      type: 'bezierCurveTo',\n      cp1x: cp1.x,\n      cp1y: cp1.y,\n      cp2x: cp2.x,\n      cp2y: cp2.y,\n      x: p.x,\n      y: p.y\n    });\n    self.currentX_ = p.x;\n    self.currentY_ = p.y;\n  }\n\n  contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {\n    // the following is lifted almost directly from\n    // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes\n\n    var cp = this.getCoords_(aCPx, aCPy);\n    var p = this.getCoords_(aX, aY);\n\n    var cp1 = {\n      x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_),\n      y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_)\n    };\n    var cp2 = {\n      x: cp1.x + (p.x - this.currentX_) / 3.0,\n      y: cp1.y + (p.y - this.currentY_) / 3.0\n    };\n\n    bezierCurveTo(this, cp1, cp2, p);\n  };\n\n  contextPrototype.arc = function(aX, aY, aRadius,\n                                  aStartAngle, aEndAngle, aClockwise) {\n    aRadius *= Z;\n    var arcType = aClockwise ? 'at' : 'wa';\n\n    var xStart = aX + mc(aStartAngle) * aRadius - Z2;\n    var yStart = aY + ms(aStartAngle) * aRadius - Z2;\n\n    var xEnd = aX + mc(aEndAngle) * aRadius - Z2;\n    var yEnd = aY + ms(aEndAngle) * aRadius - Z2;\n\n    // IE won't render arches drawn counter clockwise if xStart == xEnd.\n    if (xStart == xEnd && !aClockwise) {\n      xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something\n                       // that can be represented in binary\n    }\n\n    var p = this.getCoords_(aX, aY);\n    var pStart = this.getCoords_(xStart, yStart);\n    var pEnd = this.getCoords_(xEnd, yEnd);\n\n    this.currentPath_.push({type: arcType,\n                           x: p.x,\n                           y: p.y,\n                           radius: aRadius,\n                           xStart: pStart.x,\n                           yStart: pStart.y,\n                           xEnd: pEnd.x,\n                           yEnd: pEnd.y});\n\n  };\n\n  contextPrototype.rect = function(aX, aY, aWidth, aHeight) {\n    this.moveTo(aX, aY);\n    this.lineTo(aX + aWidth, aY);\n    this.lineTo(aX + aWidth, aY + aHeight);\n    this.lineTo(aX, aY + aHeight);\n    this.closePath();\n  };\n\n  contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {\n    var oldPath = this.currentPath_;\n    this.beginPath();\n\n    this.moveTo(aX, aY);\n    this.lineTo(aX + aWidth, aY);\n    this.lineTo(aX + aWidth, aY + aHeight);\n    this.lineTo(aX, aY + aHeight);\n    this.closePath();\n    this.stroke();\n\n    this.currentPath_ = oldPath;\n  };\n\n  contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {\n    var oldPath = this.currentPath_;\n    this.beginPath();\n\n    this.moveTo(aX, aY);\n    this.lineTo(aX + aWidth, aY);\n    this.lineTo(aX + aWidth, aY + aHeight);\n    this.lineTo(aX, aY + aHeight);\n    this.closePath();\n    this.fill();\n\n    this.currentPath_ = oldPath;\n  };\n\n  contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {\n    var gradient = new CanvasGradient_('gradient');\n    gradient.x0_ = aX0;\n    gradient.y0_ = aY0;\n    gradient.x1_ = aX1;\n    gradient.y1_ = aY1;\n    return gradient;\n  };\n\n  contextPrototype.createRadialGradient = function(aX0, aY0, aR0,\n                                                   aX1, aY1, aR1) {\n    var gradient = new CanvasGradient_('gradientradial');\n    gradient.x0_ = aX0;\n    gradient.y0_ = aY0;\n    gradient.r0_ = aR0;\n    gradient.x1_ = aX1;\n    gradient.y1_ = aY1;\n    gradient.r1_ = aR1;\n    return gradient;\n  };\n\n  contextPrototype.drawImage = function(image, var_args) {\n    var dx, dy, dw, dh, sx, sy, sw, sh;\n\n    // to find the original width we overide the width and height\n    var oldRuntimeWidth = image.runtimeStyle.width;\n    var oldRuntimeHeight = image.runtimeStyle.height;\n    image.runtimeStyle.width = 'auto';\n    image.runtimeStyle.height = 'auto';\n\n    // get the original size\n    var w = image.width;\n    var h = image.height;\n\n    // and remove overides\n    image.runtimeStyle.width = oldRuntimeWidth;\n    image.runtimeStyle.height = oldRuntimeHeight;\n\n    if (arguments.length == 3) {\n      dx = arguments[1];\n      dy = arguments[2];\n      sx = sy = 0;\n      sw = dw = w;\n      sh = dh = h;\n    } else if (arguments.length == 5) {\n      dx = arguments[1];\n      dy = arguments[2];\n      dw = arguments[3];\n      dh = arguments[4];\n      sx = sy = 0;\n      sw = w;\n      sh = h;\n    } else if (arguments.length == 9) {\n      sx = arguments[1];\n      sy = arguments[2];\n      sw = arguments[3];\n      sh = arguments[4];\n      dx = arguments[5];\n      dy = arguments[6];\n      dw = arguments[7];\n      dh = arguments[8];\n    } else {\n      throw Error('Invalid number of arguments');\n    }\n\n    var d = this.getCoords_(dx, dy);\n\n    var w2 = sw / 2;\n    var h2 = sh / 2;\n\n    var vmlStr = [];\n\n    var W = 10;\n    var H = 10;\n\n    // For some reason that I've now forgotten, using divs didn't work\n    vmlStr.push(' <g_vml_:group',\n                ' coordsize=\"', Z * W, ',', Z * H, '\"',\n                ' coordorigin=\"0,0\"' ,\n                ' style=\"width:', W, 'px;height:', H, 'px;position:absolute;');\n\n    // If filters are necessary (rotation exists), create them\n    // filters are bog-slow, so only create them if abbsolutely necessary\n    // The following check doesn't account for skews (which don't exist\n    // in the canvas spec (yet) anyway.\n\n    if (this.m_[0][0] != 1 || this.m_[0][1]) {\n      var filter = [];\n\n      // Note the 12/21 reversal\n      filter.push('M11=', this.m_[0][0], ',',\n                  'M12=', this.m_[1][0], ',',\n                  'M21=', this.m_[0][1], ',',\n                  'M22=', this.m_[1][1], ',',\n                  'Dx=', mr(d.x / Z), ',',\n                  'Dy=', mr(d.y / Z), '');\n\n      // Bounding box calculation (need to minimize displayed area so that\n      // filters don't waste time on unused pixels.\n      var max = d;\n      var c2 = this.getCoords_(dx + dw, dy);\n      var c3 = this.getCoords_(dx, dy + dh);\n      var c4 = this.getCoords_(dx + dw, dy + dh);\n\n      max.x = m.max(max.x, c2.x, c3.x, c4.x);\n      max.y = m.max(max.y, c2.y, c3.y, c4.y);\n\n      vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z),\n                  'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(',\n                  filter.join(''), \", sizingmethod='clip');\")\n    } else {\n      vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;');\n    }\n\n    vmlStr.push(' \">' ,\n                '<g_vml_:image src=\"', image.src, '\"',\n                ' style=\"width:', Z * dw, 'px;',\n                ' height:', Z * dh, 'px;\"',\n                ' cropleft=\"', sx / w, '\"',\n                ' croptop=\"', sy / h, '\"',\n                ' cropright=\"', (w - sx - sw) / w, '\"',\n                ' cropbottom=\"', (h - sy - sh) / h, '\"',\n                ' />',\n                '</g_vml_:group>');\n\n    this.element_.insertAdjacentHTML('BeforeEnd',\n                                    vmlStr.join(''));\n  };\n\n  contextPrototype.stroke = function(aFill) {\n    var lineStr = [];\n    var lineOpen = false;\n    var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);\n    var color = a.color;\n    var opacity = a.alpha * this.globalAlpha;\n\n    var W = 10;\n    var H = 10;\n\n    lineStr.push('<g_vml_:shape',\n                 ' filled=\"', !!aFill, '\"',\n                 ' style=\"position:absolute;width:', W, 'px;height:', H, 'px;\"',\n                 ' coordorigin=\"0 0\" coordsize=\"', Z * W, ' ', Z * H, '\"',\n                 ' stroked=\"', !aFill, '\"',\n                 ' path=\"');\n\n    var newSeq = false;\n    var min = {x: null, y: null};\n    var max = {x: null, y: null};\n\n    for (var i = 0; i < this.currentPath_.length; i++) {\n      var p = this.currentPath_[i];\n      var c;\n\n      switch (p.type) {\n        case 'moveTo':\n          c = p;\n          lineStr.push(' m ', mr(p.x), ',', mr(p.y));\n          break;\n        case 'lineTo':\n          lineStr.push(' l ', mr(p.x), ',', mr(p.y));\n          break;\n        case 'close':\n          lineStr.push(' x ');\n          p = null;\n          break;\n        case 'bezierCurveTo':\n          lineStr.push(' c ',\n                       mr(p.cp1x), ',', mr(p.cp1y), ',',\n                       mr(p.cp2x), ',', mr(p.cp2y), ',',\n                       mr(p.x), ',', mr(p.y));\n          break;\n        case 'at':\n        case 'wa':\n          lineStr.push(' ', p.type, ' ',\n                       mr(p.x - this.arcScaleX_ * p.radius), ',',\n                       mr(p.y - this.arcScaleY_ * p.radius), ' ',\n                       mr(p.x + this.arcScaleX_ * p.radius), ',',\n                       mr(p.y + this.arcScaleY_ * p.radius), ' ',\n                       mr(p.xStart), ',', mr(p.yStart), ' ',\n                       mr(p.xEnd), ',', mr(p.yEnd));\n          break;\n      }\n\n\n      // TODO: Following is broken for curves due to\n      //       move to proper paths.\n\n      // Figure out dimensions so we can do gradient fills\n      // properly\n      if (p) {\n        if (min.x == null || p.x < min.x) {\n          min.x = p.x;\n        }\n        if (max.x == null || p.x > max.x) {\n          max.x = p.x;\n        }\n        if (min.y == null || p.y < min.y) {\n          min.y = p.y;\n        }\n        if (max.y == null || p.y > max.y) {\n          max.y = p.y;\n        }\n      }\n    }\n    lineStr.push(' \">');\n\n    if (!aFill) {\n      var lineWidth = this.lineScale_ * this.lineWidth;\n\n      // VML cannot correctly render a line if the width is less than 1px.\n      // In that case, we dilute the color to make the line look thinner.\n      if (lineWidth < 1) {\n        opacity *= lineWidth;\n      }\n\n      lineStr.push(\n        '<g_vml_:stroke',\n        ' opacity=\"', opacity, '\"',\n        ' joinstyle=\"', this.lineJoin, '\"',\n        ' miterlimit=\"', this.miterLimit, '\"',\n        ' endcap=\"', processLineCap(this.lineCap), '\"',\n        ' weight=\"', lineWidth, 'px\"',\n        ' color=\"', color, '\" />'\n      );\n    } else if (typeof this.fillStyle == 'object') {\n      var fillStyle = this.fillStyle;\n      var angle = 0;\n      var focus = {x: 0, y: 0};\n\n      // additional offset\n      var shift = 0;\n      // scale factor for offset\n      var expansion = 1;\n\n      if (fillStyle.type_ == 'gradient') {\n        var x0 = fillStyle.x0_ / this.arcScaleX_;\n        var y0 = fillStyle.y0_ / this.arcScaleY_;\n        var x1 = fillStyle.x1_ / this.arcScaleX_;\n        var y1 = fillStyle.y1_ / this.arcScaleY_;\n        var p0 = this.getCoords_(x0, y0);\n        var p1 = this.getCoords_(x1, y1);\n        var dx = p1.x - p0.x;\n        var dy = p1.y - p0.y;\n        angle = Math.atan2(dx, dy) * 180 / Math.PI;\n\n        // The angle should be a non-negative number.\n        if (angle < 0) {\n          angle += 360;\n        }\n\n        // Very small angles produce an unexpected result because they are\n        // converted to a scientific notation string.\n        if (angle < 1e-6) {\n          angle = 0;\n        }\n      } else {\n        var p0 = this.getCoords_(fillStyle.x0_, fillStyle.y0_);\n        var width  = max.x - min.x;\n        var height = max.y - min.y;\n        focus = {\n          x: (p0.x - min.x) / width,\n          y: (p0.y - min.y) / height\n        };\n\n        width  /= this.arcScaleX_ * Z;\n        height /= this.arcScaleY_ * Z;\n        var dimension = m.max(width, height);\n        shift = 2 * fillStyle.r0_ / dimension;\n        expansion = 2 * fillStyle.r1_ / dimension - shift;\n      }\n\n      // We need to sort the color stops in ascending order by offset,\n      // otherwise IE won't interpret it correctly.\n      var stops = fillStyle.colors_;\n      stops.sort(function(cs1, cs2) {\n        return cs1.offset - cs2.offset;\n      });\n\n      var length = stops.length;\n      var color1 = stops[0].color;\n      var color2 = stops[length - 1].color;\n      var opacity1 = stops[0].alpha * this.globalAlpha;\n      var opacity2 = stops[length - 1].alpha * this.globalAlpha;\n\n      var colors = [];\n      for (var i = 0; i < length; i++) {\n        var stop = stops[i];\n        colors.push(stop.offset * expansion + shift + ' ' + stop.color);\n      }\n\n      // When colors attribute is used, the meanings of opacity and o:opacity2\n      // are reversed.\n      lineStr.push('<g_vml_:fill type=\"', fillStyle.type_, '\"',\n                   ' method=\"none\" focus=\"100%\"',\n                   ' color=\"', color1, '\"',\n                   ' color2=\"', color2, '\"',\n                   ' colors=\"', colors.join(','), '\"',\n                   ' opacity=\"', opacity2, '\"',\n                   ' g_o_:opacity2=\"', opacity1, '\"',\n                   ' angle=\"', angle, '\"',\n                   ' focusposition=\"', focus.x, ',', focus.y, '\" />');\n    } else {\n      lineStr.push('<g_vml_:fill color=\"', color, '\" opacity=\"', opacity,\n                   '\" />');\n    }\n\n    lineStr.push('</g_vml_:shape>');\n\n    this.element_.insertAdjacentHTML('beforeEnd', lineStr.join(''));\n  };\n\n  contextPrototype.fill = function() {\n    this.stroke(true);\n  }\n\n  contextPrototype.closePath = function() {\n    this.currentPath_.push({type: 'close'});\n  };\n\n  /**\n   * @private\n   */\n  contextPrototype.getCoords_ = function(aX, aY) {\n    var m = this.m_;\n    return {\n      x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2,\n      y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2\n    }\n  };\n\n  contextPrototype.save = function() {\n    var o = {};\n    copyState(this, o);\n    this.aStack_.push(o);\n    this.mStack_.push(this.m_);\n    this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);\n  };\n\n  contextPrototype.restore = function() {\n    copyState(this.aStack_.pop(), this);\n    this.m_ = this.mStack_.pop();\n  };\n\n  function matrixIsFinite(m) {\n    for (var j = 0; j < 3; j++) {\n      for (var k = 0; k < 2; k++) {\n        if (!isFinite(m[j][k]) || isNaN(m[j][k])) {\n          return false;\n        }\n      }\n    }\n    return true;\n  }\n\n  function setM(ctx, m, updateLineScale) {\n    if (!matrixIsFinite(m)) {\n      return;\n    }\n    ctx.m_ = m;\n\n    if (updateLineScale) {\n      // Get the line scale.\n      // Determinant of this.m_ means how much the area is enlarged by the\n      // transformation. So its square root can be used as a scale factor\n      // for width.\n      var det = m[0][0] * m[1][1] - m[0][1] * m[1][0];\n      ctx.lineScale_ = sqrt(abs(det));\n    }\n  }\n\n  contextPrototype.translate = function(aX, aY) {\n    var m1 = [\n      [1,  0,  0],\n      [0,  1,  0],\n      [aX, aY, 1]\n    ];\n\n    setM(this, matrixMultiply(m1, this.m_), false);\n  };\n\n  contextPrototype.rotate = function(aRot) {\n    var c = mc(aRot);\n    var s = ms(aRot);\n\n    var m1 = [\n      [c,  s, 0],\n      [-s, c, 0],\n      [0,  0, 1]\n    ];\n\n    setM(this, matrixMultiply(m1, this.m_), false);\n  };\n\n  contextPrototype.scale = function(aX, aY) {\n    this.arcScaleX_ *= aX;\n    this.arcScaleY_ *= aY;\n    var m1 = [\n      [aX, 0,  0],\n      [0,  aY, 0],\n      [0,  0,  1]\n    ];\n\n    setM(this, matrixMultiply(m1, this.m_), true);\n  };\n\n  contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) {\n    var m1 = [\n      [m11, m12, 0],\n      [m21, m22, 0],\n      [dx,  dy,  1]\n    ];\n\n    setM(this, matrixMultiply(m1, this.m_), true);\n  };\n\n  contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) {\n    var m = [\n      [m11, m12, 0],\n      [m21, m22, 0],\n      [dx,  dy,  1]\n    ];\n\n    setM(this, m, true);\n  };\n\n  /******** STUBS ********/\n  contextPrototype.clip = function() {\n    // TODO: Implement\n  };\n\n  contextPrototype.arcTo = function() {\n    // TODO: Implement\n  };\n\n  contextPrototype.createPattern = function() {\n    return new CanvasPattern_;\n  };\n\n  // Gradient / Pattern Stubs\n  function CanvasGradient_(aType) {\n    this.type_ = aType;\n    this.x0_ = 0;\n    this.y0_ = 0;\n    this.r0_ = 0;\n    this.x1_ = 0;\n    this.y1_ = 0;\n    this.r1_ = 0;\n    this.colors_ = [];\n  }\n\n  CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {\n    aColor = processStyle(aColor);\n    this.colors_.push({offset: aOffset,\n                       color: aColor.color,\n                       alpha: aColor.alpha});\n  };\n\n  function CanvasPattern_() {}\n\n  // set up externs\n  G_vmlCanvasManager = G_vmlCanvasManager_;\n  CanvasRenderingContext2D = CanvasRenderingContext2D_;\n  CanvasGradient = CanvasGradient_;\n  CanvasPattern = CanvasPattern_;\n\n})();\n\n} // if\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/jquery-easy-pie-chart/examples/index.html",
    "content": "<!doctype html>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <title>Easy Pie Chart</title>\n        <script type=\"text/javascript\" src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js\"></script>\n        <script type=\"text/javascript\" src=\"http://html5shiv.googlecode.com/svn/trunk/html5.js\"></script>\n        <script type=\"text/javascript\" src=\"excanvas.js\"></script>\n        <script type=\"text/javascript\" src=\"../jquery.easy-pie-chart.js\"></script>\n\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" media=\"screen\">\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"../jquery.easy-pie-chart.css\" media=\"screen\">\n\n        <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n\n        <script type=\"text/javascript\">\n            var initPieChart = function() {\n                $('.percentage').easyPieChart({\n                    animate: 1000\n                });\n                $('.percentage-light').easyPieChart({\n                    barColor: function(percent) {\n                        percent /= 100;\n                        return \"rgb(\" + Math.round(255 * (1-percent)) + \", \" + Math.round(255 * percent) + \", 0)\";\n                    },\n                    trackColor: '#666',\n                    scaleColor: false,\n                    lineCap: 'butt',\n                    lineWidth: 15,\n                    animate: 1000\n                });\n\n                $('.updateEasyPieChart').on('click', function(e) {\n                  e.preventDefault();\n                  $('.percentage, .percentage-light').each(function() {\n                    var newValue = Math.round(100*Math.random());\n                    $(this).data('easyPieChart').update(newValue);\n                    $('span', this).text(newValue);\n                  });\n                });\n            };\n        </script>\n    </head>\n    <body onload=\"initPieChart();\">\n        <div class=\"container\">\n            <h1>EASY PIE CHART</h1>\n            <div class=\"chart\">\n                <div class=\"percentage success\" data-percent=\"55\"><span>55</span>%</div>\n                <div class=\"label\">New visits</div>\n            </div>\n            <div class=\"chart\">\n                <div class=\"percentage\" data-percent=\"46\"><span>46</span>%</div>\n                <div class=\"label\">Bounce rate</div>\n            </div>\n            <div class=\"chart\">\n                <div class=\"percentage\" data-percent=\"92\"><span>92</span>%</div>\n                <div class=\"label\">Server load</div>\n            </div>\n            <div class=\"chart\">\n                <div class=\"percentage\" data-percent=\"84\"><span>752</span>MB</div>\n                <div class=\"label\">Used RAM</div>\n            </div>\n            <div style=\"clear:both;\"></div>\n            <div class=\"dark\">\n                <div class=\"chart\">\n                    <div id=\"sparkline_bar\" class=\"percentage-light\" data-percent=\"55\"><span>55</span>%</div>\n                    <div class=\"label\">New visits</div>\n                </div>\n                <div class=\"chart\">\n                    <div id=\"sparkline_bar\" class=\"percentage-light\" data-percent=\"46\"><span>46</span>%</div>\n                    <div class=\"label\">Bounce rate</div>\n                </div>\n                <div class=\"chart\">\n                    <div class=\"percentage-light\" data-percent=\"92\"><span>92</span>%</div>\n                    <div class=\"label\">Server load</div>\n                </div>\n                <div class=\"chart\">\n                    <div class=\"percentage-light\" data-percent=\"84\"><span>752</span>MB</div>\n                    <div class=\"label\">Used RAM</div>\n                </div>\n                <div style=\"clear:both;\"></div>\n            </div>\n\n            <p><a href=\"#\" class=\"button updateEasyPieChart\">Update pie charts</a></p>\n\n            <p class=\"credits\">Inspired by: <a href=\"http://drbl.in/ezuc\" target=\"_blank\">Simple Pie Charts II by Rafal Bromirski on dribble</a></p>\n        </div>\n    </body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/jquery-easy-pie-chart/examples/style.css",
    "content": "body {\n    font: 13px/1.4 'Helvetica Neue', 'Helvetica','Arial', sans-serif;\n    color: #333;\n}\n\n.container {\n    width: 520px;\n    margin: auto;\n}\n\nh1 {\n    border-bottom: 1px solid #d9d9d9;\n}\n\na {\n    color: #be2221;\n    text-decoration: none;\n}\n\n.chart {\n    float: left;\n    margin: 10px;\n}\n\n.percentage,\n.label {\n    text-align: center;\n    color: #333;\n    font-weight: 100;\n    font-size: 1.2em;\n    margin-bottom: 0.3em;\n}\n\n.credits {\n    padding-top: 0.5em;\n    clear: both;\n    color: #999;\n}\n\n.credits a {\n    color: #333;\n}\n\n.dark {\n    background: #333;\n}\n\n.dark .percentage-light,\n.dark .label {\n    text-align: center;\n    color: #999;\n    font-weight: 100;\n    font-size: 1.2em;\n    margin-bottom: 0.3em;\n}\n\n\n.button {\n  -webkit-box-shadow: inset 0 0 1px #000, inset 0 1px 0 1px rgba(255,255,255,0.2), 0 1px 1px -1px rgba(0, 0, 0, .5);\n  -moz-box-shadow: inset 0 0 1px #000, inset 0 1px 0 1px rgba(255,255,255,0.2), 0 1px 1px -1px rgba(0, 0, 0, .5);\n  box-shadow: inset 0 0 1px #000, inset 0 1px 0 1px rgba(255,255,255,0.2), 0 1px 1px -1px rgba(0, 0, 0, .5);\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n  padding: 6px 20px;\n  font-weight: bold;\n  text-transform: uppercase;\n  display: block;\n  margin: auto;\n  max-width: 200px;\n  text-align: center;\n  background-color: #5c5c5c;\n  background-image: -moz-linear-gradient(top, #666666, #4d4d4d);\n  background-image: -ms-linear-gradient(top, #666666, #4d4d4d);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#666666), to(#4d4d4d));\n  background-image: -webkit-linear-gradient(top, #666666, #4d4d4d);\n  background-image: -o-linear-gradient(top, #666666, #4d4d4d);\n  background-image: linear-gradient(top, #666666, #4d4d4d);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#666666', endColorstr='#4d4d4d', GradientType=0);\n  color: #ffffff;\n  text-shadow: 0 1px 1px #333333;\n}\n.button:hover {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #616161;\n  background-image: -moz-linear-gradient(top, #6b6b6b, #525252);\n  background-image: -ms-linear-gradient(top, #6b6b6b, #525252);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#6b6b6b), to(#525252));\n  background-image: -webkit-linear-gradient(top, #6b6b6b, #525252);\n  background-image: -o-linear-gradient(top, #6b6b6b, #525252);\n  background-image: linear-gradient(top, #6b6b6b, #525252);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#6b6b6b', endColorstr='#525252', GradientType=0);\n}\n.button:active {\n  background-color: #575757;\n  background-image: -moz-linear-gradient(top, #616161, #474747);\n  background-image: -ms-linear-gradient(top, #616161, #474747);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#616161), to(#474747));\n  background-image: -webkit-linear-gradient(top, #616161, #474747);\n  background-image: -o-linear-gradient(top, #616161, #474747);\n  background-image: linear-gradient(top, #616161, #474747);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#616161', endColorstr='#474747', GradientType=0);\n  -webkit-transform: translate(0, 1px);\n  -moz-transform: translate(0, 1px);\n  -ms-transform: translate(0, 1px);\n  -o-transform: translate(0, 1px);\n  transform: translate(0, 1px);\n}\n.button:disabled {\n  background-color: #dddddd;\n  background-image: -moz-linear-gradient(top, #e7e7e7, #cdcdcd);\n  background-image: -ms-linear-gradient(top, #e7e7e7, #cdcdcd);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e7e7e7), to(#cdcdcd));\n  background-image: -webkit-linear-gradient(top, #e7e7e7, #cdcdcd);\n  background-image: -o-linear-gradient(top, #e7e7e7, #cdcdcd);\n  background-image: linear-gradient(top, #e7e7e7, #cdcdcd);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e7e7e7', endColorstr='#cdcdcd', GradientType=0);\n  color: #939393;\n  text-shadow: 0 1px 1px #fff;\n}\n\n@media screen and (max-device-width: 480px) {\n  .container{\n    width: 100%;\n  }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/jquery-easy-pie-chart/jquery.easy-pie-chart.coffee",
    "content": "###\nEasy pie chart is a jquery plugin to display simple animated pie charts for only one value\n\nDual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)\nand GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.\n\nBuilt on top of the jQuery library (http://jquery.com)\n\n@source: http://github.com/rendro/easy-pie-chart/\n@autor: Robert Fleischmann\n@version: 1.0.1\n\nInspired by: http://dribbble.com/shots/631074-Simple-Pie-Charts-II?list=popular&offset=210\nThanks to Philip Thrasher for the jquery plugin boilerplate for coffee script\n###\n\n(($) ->\n  $.easyPieChart = (el, options) ->\n\n    @el = el\n    @$el = $ el\n    @$el.data \"easyPieChart\", @\n\n    @init = =>\n      @options = $.extend {}, $.easyPieChart.defaultOptions, options\n\n      #get relevant data\n      percent = parseInt @$el.data('percent'), 10\n      @percentage = 0\n\n      #create canvas element and set the origin to the center\n      @canvas = $(\"<canvas width='#{@options.size}' height='#{@options.size}'></canvas>\").get(0)\n      @$el.append @canvas\n      G_vmlCanvasManager.initElement @canvas if G_vmlCanvasManager?\n      @ctx = @canvas.getContext '2d'\n\n      if window.devicePixelRatio > 1\n        scaleBy = window.devicePixelRatio\n        $(@canvas).css({\n          width: @options.size\n          height: @options.size\n        })\n        @canvas.width *= scaleBy\n        @canvas.height *= scaleBy\n        @ctx.scale scaleBy, scaleBy\n\n      @ctx.translate @options.size/2, @options.size/2\n      @$el.addClass 'easyPieChart'\n      @$el.css {\n        width: @options.size\n        height: @options.size\n        lineHeight: \"#{@options.size}px\"\n      }\n\n\n\n      @update percent\n      @\n\n    @update = (percent) =>\n      if @options.animate == false\n        drawLine percent\n      else\n        animateLine @percentage, percent\n\n    renderScale = =>\n      @ctx.fillStyle = @options.scaleColor\n      @ctx.lineWidth = 1\n      addScaleLine i for i in [0..24]\n\n    addScaleLine = (i) =>\n      offset = if i%6==0 then 0 else @options.size*0.017\n      @ctx.save()\n      @ctx.rotate i * Math.PI / 12\n      @ctx.fillRect @options.size/2-offset, 0, -@options.size*0.05+offset, 1\n      @ctx.restore()\n\n    renderTrack = =>\n      offset = @options.size/2-@options.lineWidth/2\n      offset -= @options.size*0.08 if @options.scaleColor != false\n\n      @ctx.beginPath()\n      @ctx.arc 0, 0, offset, 0, Math.PI * 2, true\n      @ctx.closePath()\n      @ctx.strokeStyle = @options.trackColor\n      @ctx.lineWidth = @options.lineWidth\n      @ctx.stroke()\n\n    renderBackground = =>\n      do renderScale if @options.scaleColor != false\n      do renderTrack if @options.trackColor != false\n\n    drawLine = (percent) =>\n      do renderBackground\n\n      @ctx.strokeStyle = if $.isFunction @options.barColor  then @options.barColor percent else @options.barColor\n      @ctx.lineCap = @options.lineCap\n      @ctx.lineWidth = @options.lineWidth\n\n      offset = @options.size/2-@options.lineWidth/2\n      offset -= @options.size*0.08 if @options.scaleColor != false\n\n      @ctx.save()\n      @ctx.rotate -Math.PI/2\n      @ctx.beginPath()\n      @ctx.arc 0, 0, offset, 0, Math.PI * 2 * percent/100, false\n      @ctx.stroke()\n      @ctx.restore()\n\n    animateLine = (from, to) =>\n      fps = 30\n      steps = fps * @options.animate/1000\n      currentStep = 0\n\n      @options.onStart.call @\n      @percentage = to\n\n      if @animation\n        clearInterval @animation\n        @animation = false\n\n      @animation = setInterval =>\n        @ctx.clearRect -@options.size/2, -@options.size/2, @options.size, @options.size\n        renderBackground.call @\n        drawLine.call @, [easeInOutQuad currentStep, from, to-from, steps]\n\n        currentStep++\n\n        if (currentStep/steps) > 1\n          clearInterval @animation\n          @animation = false\n          @options.onStop.call @\n\n      , 1000/fps\n\n    #t=time;b=beginning value;c=change in value;d=duration\n    easeInOutQuad = (t, b, c, d) ->\n\n      easeIn = (t) ->\n        return Math.pow(t, 2) # Quad\n      easing = (t) ->\n        if (t < 1)\n          return easeIn(t)\n        else\n          return 2 - easeIn( (t/2) * -2 + 2 )\n\n      t /= d / 2\n      return c / 2 * easing(t) + b\n\n    @init()\n\n  $.easyPieChart.defaultOptions =\n    barColor:        '#ef1e25'\n    trackColor:      '#f2f2f2'\n    scaleColor:      '#dfe0e0'\n    lineCap:         'round'\n    size:            110\n    lineWidth:       3\n    animate:         false\n    onStart:         $.noop\n    onStop:          $.noop\n\n  $.fn.easyPieChart = (options) ->\n    $.each @, (i, el) ->\n      $el = ($ el)\n\n      unless $el.data 'easyPieChart'\n        $el.data 'easyPieChart', new $.easyPieChart el, options\n\n  undefined\n)(jQuery)\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/jquery-easy-pie-chart/jquery.easy-pie-chart.css",
    "content": ".easyPieChart {\n    position: relative;\n    text-align: center;\n}\n\n.easyPieChart canvas {\n    position: absolute;\n    top: 0;\n    left: 0;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/assets/jquery-easy-pie-chart/jquery.easy-pie-chart.js",
    "content": "// Generated by CoffeeScript 1.4.0\n\n/*\nEasy pie chart is a jquery plugin to display simple animated pie charts for only one value\n\nDual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)\nand GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.\n\nBuilt on top of the jQuery library (http://jquery.com)\n\n@source: http://github.com/rendro/easy-pie-chart/\n@autor: Robert Fleischmann\n@version: 1.0.1\n\nInspired by: http://dribbble.com/shots/631074-Simple-Pie-Charts-II?list=popular&offset=210\nThanks to Philip Thrasher for the jquery plugin boilerplate for coffee script\n*/\n\n\n(function() {\n\n  (function($) {\n    $.easyPieChart = function(el, options) {\n      var addScaleLine, animateLine, drawLine, easeInOutQuad, renderBackground, renderScale, renderTrack,\n        _this = this;\n      this.el = el;\n      this.$el = $(el);\n      this.$el.data(\"easyPieChart\", this);\n      this.init = function() {\n        var percent;\n        _this.options = $.extend({}, $.easyPieChart.defaultOptions, options);\n        percent = parseInt(_this.$el.data('percent'), 10);\n        _this.percentage = 0;\n        _this.canvas = $(\"<canvas width='\" + _this.options.size + \"' height='\" + _this.options.size + \"'></canvas>\").get(0);\n        _this.$el.append(_this.canvas);\n        if (typeof G_vmlCanvasManager !== \"undefined\" && G_vmlCanvasManager !== null) {\n          G_vmlCanvasManager.initElement(_this.canvas);\n        }\n        _this.ctx = _this.canvas.getContext('2d');\n        if (window.devicePixelRatio > 1.5) {\n          $(_this.canvas).css({\n            width: _this.options.size,\n            height: _this.options.size\n          });\n          _this.canvas.width *= 2;\n          _this.canvas.height *= 2;\n          _this.ctx.scale(2, 2);\n        }\n        _this.ctx.translate(_this.options.size / 2, _this.options.size / 2);\n        _this.$el.addClass('easyPieChart');\n        _this.$el.css({\n          width: _this.options.size,\n          height: _this.options.size,\n          lineHeight: \"\" + _this.options.size + \"px\"\n        });\n        _this.update(percent);\n        return _this;\n      };\n      this.update = function(percent) {\n        if (_this.options.animate === false) {\n          return drawLine(percent);\n        } else {\n          return animateLine(_this.percentage, percent);\n        }\n      };\n      renderScale = function() {\n        var i, _i, _results;\n        _this.ctx.fillStyle = _this.options.scaleColor;\n        _this.ctx.lineWidth = 1;\n        _results = [];\n        for (i = _i = 0; _i <= 24; i = ++_i) {\n          _results.push(addScaleLine(i));\n        }\n        return _results;\n      };\n      addScaleLine = function(i) {\n        var offset;\n        offset = i % 6 === 0 ? 0 : _this.options.size * 0.017;\n        _this.ctx.save();\n        _this.ctx.rotate(i * Math.PI / 12);\n        _this.ctx.fillRect(_this.options.size / 2 - offset, 0, -_this.options.size * 0.05 + offset, 1);\n        return _this.ctx.restore();\n      };\n      renderTrack = function() {\n        var offset;\n        offset = _this.options.size / 2 - _this.options.lineWidth / 2;\n        if (_this.options.scaleColor !== false) {\n          offset -= _this.options.size * 0.08;\n        }\n        _this.ctx.beginPath();\n        _this.ctx.arc(0, 0, offset, 0, Math.PI * 2, true);\n        _this.ctx.closePath();\n        _this.ctx.strokeStyle = _this.options.trackColor;\n        _this.ctx.lineWidth = _this.options.lineWidth;\n        return _this.ctx.stroke();\n      };\n      renderBackground = function() {\n        if (_this.options.scaleColor !== false) {\n          renderScale();\n        }\n        if (_this.options.trackColor !== false) {\n          return renderTrack();\n        }\n      };\n      drawLine = function(percent) {\n        var offset;\n        renderBackground();\n        _this.ctx.strokeStyle = $.isFunction(_this.options.barColor) ? _this.options.barColor(percent) : _this.options.barColor;\n        _this.ctx.lineCap = _this.options.lineCap;\n        _this.ctx.lineWidth = _this.options.lineWidth;\n        offset = _this.options.size / 2 - _this.options.lineWidth / 2;\n        if (_this.options.scaleColor !== false) {\n          offset -= _this.options.size * 0.08;\n        }\n        _this.ctx.save();\n        _this.ctx.rotate(-Math.PI / 2);\n        _this.ctx.beginPath();\n        _this.ctx.arc(0, 0, offset, 0, Math.PI * 2 * percent / 100, false);\n        _this.ctx.stroke();\n        return _this.ctx.restore();\n      };\n      animateLine = function(from, to) {\n        var currentStep, fps, steps;\n        fps = 30;\n        steps = fps * _this.options.animate / 1000;\n        currentStep = 0;\n        _this.options.onStart.call(_this);\n        _this.percentage = to;\n        if (_this.animation) {\n          clearInterval(_this.animation);\n          _this.animation = false;\n        }\n        return _this.animation = setInterval(function() {\n          _this.ctx.clearRect(-_this.options.size / 2, -_this.options.size / 2, _this.options.size, _this.options.size);\n          renderBackground.call(_this);\n          drawLine.call(_this, [easeInOutQuad(currentStep, from, to - from, steps)]);\n          currentStep++;\n          if ((currentStep / steps) > 1) {\n            clearInterval(_this.animation);\n            _this.animation = false;\n            return _this.options.onStop.call(_this);\n          }\n        }, 1000 / fps);\n      };\n      easeInOutQuad = function(t, b, c, d) {\n        var easeIn, easing;\n        easeIn = function(t) {\n          return Math.pow(t, 2);\n        };\n        easing = function(t) {\n          if (t < 1) {\n            return easeIn(t);\n          } else {\n            return 2 - easeIn((t / 2) * -2 + 2);\n          }\n        };\n        t /= d / 2;\n        return c / 2 * easing(t) + b;\n      };\n      return this.init();\n    };\n    $.easyPieChart.defaultOptions = {\n      barColor: '#ef1e25',\n      trackColor: '#f2f2f2',\n      scaleColor: '#dfe0e0',\n      lineCap: 'round',\n      size: 110,\n      lineWidth: 3,\n      animate: false,\n      onStart: $.noop,\n      onStop: $.noop\n    };\n    $.fn.easyPieChart = function(options) {\n      return $.each(this, function(i, el) {\n        var $el;\n        $el = $(el);\n        if (!$el.data('easyPieChart')) {\n          return $el.data('easyPieChart', new $.easyPieChart(el, options));\n        }\n      });\n    };\n    return void 0;\n  })(jQuery);\n\n}).call(this);\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/css/bootstrap-reset.css",
    "content": "/*anchor*/\na {\n    color: #667fa0;\n}\n\na:hover {\n    color: #2A3542;\n}\n\n/*panel*/\n.panel {\n    border: none;\n    box-shadow: none;\n}\n\n.panel-heading {\n    border-color:#eff2f7 ;\n    font-size: 16px;\n    font-weight: 300;\n}\n\n.panel-title {\n    color: #2A3542;\n    font-size: 14px;\n    font-weight: 400;\n    margin-bottom: 0;\n    margin-top: 0;\n    font-family: 'Open Sans', sans-serif;\n}\n\n/*label*/\n\n.label {\n    padding: 0.5em 0.8em;\n}\n\n.label-default {\n    background-color: #a1a1a1;\n}\n\n.label-primary {\n    background-color: #59ace2;\n}\n\n.label-success {\n    background-color: #A9D86E;\n}\n\n.label-info {\n    background-color: #8175c7;\n}\n\n.label-warning {\n    background-color: #FCB322;\n}\n\n.label-danger {\n    background-color: #FF6C60;\n}\n\n.label-inverse {\n    background-color: #344860;\n}\n\n/*text color*/\n\n.text-danger {\n    color: #FF6C60;\n}\n\n.text-muted {\n    color: #a1a1a1;\n}\n\n.text-primary {\n    color: #59ace2;\n}\n\n.text-warning {\n    color: #FCB322;\n}\n\n.text-success {\n    color: #A9D86E;\n}\n\n.text-info {\n    color: #8175c7;\n}\n\n/*modal*/\n\n.modal-content {\n    box-shadow: none;\n    border: none;\n}\n\n.modal-header {\n    background: #00A8B3;\n    color: #fff;\n    border-radius: 5px 5px 0 0;\n    -webkit-border-radius: 5px 5px 0 0;\n    border-bottom: none;\n}\n\n.modal-header .close {\n    margin-top: 0;\n}\n\n/*text input*/\n\n.form-control {\n    border: 1px solid #e2e2e4;\n    box-shadow: none;\n    color: #c2c2c2;\n}\n\n\n.form-control:focus, #focusedInput {\n    border: 1px solid #517397;\n    box-shadow: none;\n}\n\n.form-horizontal .control-label {\n    font-weight: 300;\n    font-size: 14px;\n    text-align: left;\n}\n\ninput, textarea, select, button {\n    outline: none !important;\n}\n\n/*list*/\n\nul {\n    padding-left: 0;\n}\n\n/*button*/\n\n.btn-default {\n    background-color: #bec3c7;\n    border-color: #bec3c7;\n    color: #fff;\n}\n\n.btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default {\n    background-color: #b0b5b9;\n    border-color: #b0b5b9;\n    color: #fff;\n}\n\n.btn-primary {\n    background-color: #41cac0;\n    border-color: #41cac0;\n    color: #FFFFFF;\n}\n\n.btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary {\n    background-color: #39b2a9;\n    border-color: #39b2a9;\n    color: #FFFFFF;\n}\n\n.btn-success {\n    background-color: #78CD51;\n    border-color: #78CD51;\n    color: #FFFFFF;\n}\n\n.btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success {\n    background-color: #6dbb4a;\n    border-color: #6dbb4a;\n    color: #FFFFFF;\n}\n\n.btn-info {\n    background-color: #58c9f3;\n    border-color: #58c9f3;\n    color: #FFFFFF;\n}\n\n.btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info {\n    background-color: #53bee6;\n    border-color: #53BEE6;\n    color: #FFFFFF;\n}\n\n.btn-warning {\n    background-color: #f1c500;\n    border-color: #f1c500;\n    color: #FFFFFF;\n}\n\n.btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning {\n    background-color: #e4ba00;\n    border-color: #e4ba00;\n    color: #FFFFFF;\n}\n\n.btn-danger {\n    background-color: #ff6c60;\n    border-color: #ff6c60;\n    color: #FFFFFF;\n}\n\n.btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger {\n    background-color: #ec6459;\n    border-color: #ec6459;\n    color: #FFFFFF;\n}\n\n\n.btn-white {\n    box-shadow: none !important;\n}\n\n/*Rounded Button*/\n\n.btn-round {\n    border-radius: 30px;\n    -webkit-border-radius: 30px;\n}\n\n/*shadow button*/\n\n.btn-shadow.btn-default {\n    box-shadow: 0 4px #9c9c9c;\n}\n.btn-shadow.btn-primary {\n    box-shadow: 0 4px #29b392;\n}\n.btn-shadow.btn-success {\n    box-shadow: 0 4px #61a642;\n}\n.btn-shadow.btn-info {\n    box-shadow: 0 4px #1caadc;\n}\n.btn-shadow.btn-warning {\n    box-shadow: 0 4px #cab03f;\n}\n.btn-shadow.btn-danger {\n    box-shadow: 0 4px #d1595a;\n}\n\n\n/*dropdown shadow*/\n\n.btn-group.open .dropdown-toggle, .btn-white.active, .btn:active, .btn.active {\n    box-shadow: none;\n}\n\n/*dropdown select bg*/\n.dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus {\n    background-color: #495d74;\n    color: #FFFFFF;\n    text-decoration: none;\n}\n\n/*split dropdown btn*/\n\n.btn-white {\n    background-clip: padding-box;\n    background-color: #FFFFFF;\n    border-color: rgba(150, 160, 180, 0.3);\n    box-shadow: 0 -1px 1px rgba(0, 0, 0, 0.05) inset;\n}\n\n/*breadcrumbs*/\n\n.breadcrumb {\n    background-color: #fff;\n}\n\n\n/*tab*/\n\n.nav-tabs > li > a {\n    margin-right: 1px;\n}\n\n/*collapse*/\n\n.panel-default > .panel-heading {\n    background-color: #FFFFFF;\n    border-color: #DDDDDD;\n    color: #797979;\n}\n\n/*nav inverse*/\n\n.navbar-inverse {\n    background-color: #7087A3;\n    border-color: #7087A3;\n}\n\n.navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus,\n.navbar-inverse .navbar-nav > .open > a, .navbar-inverse .navbar-nav > .open > a:focus{\n    background-color: #61748d;\n}\n\n.navbar-inverse .navbar-nav > li a:hover {\n    color: #2A3542;\n}\n\n.navbar-inverse .navbar-nav > li > ul > li a:hover {\n    color: #fff;\n}\n\n.navbar-inverse .navbar-brand {\n    color: #FFFFFF;\n}\n\n.navbar-inverse .navbar-nav > li > a {\n    color: #fff;\n}\n\n.navbar-inverse .navbar-nav > .dropdown > a .caret {\n    border-bottom-color: #fff;\n    border-top-color: #fff;\n}\n\n.navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n    color: #000;\n}\n.navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover {\n    color: #fff;\n}\n\n/*nav justified*/\n\n.nav-justified {\n    width: auto !important;\n}\n\n.nav-justified li:last-child > a:hover, .nav-justified li.active:last-child > a {\n    border-radius: 0 4px 0 0 !important;\n    -webkit-border-radius: 0 4px 0 0 !important;\n}\n\n/*list group*/\n\n.list-group-item.active, .list-group-item.active:hover, .list-group-item.active:focus {\n    background-color: #00A8B3;\n    border-color: #00A8B3;\n    color: #FFFFFF;\n    z-index: 2;\n}\n\n.list-group-item-heading {\n    font-weight: 300;\n}\n\n/*progress*/\n\n.progress {\n    box-shadow: none;\n    background: #f0f2f7;\n}\n\n/*alert*/\n\n.alert-success, .alert-danger, .alert-info, .alert-warning {\n    border: none;\n}\n\n/*table*/\n\n.table thead > tr > th, .table tbody > tr > th, .table tfoot > tr > th, .table thead > tr > td, .table tbody > tr > td, .table tfoot > tr > td {\n    padding: 10px;\n}\n\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/css/bootstrap.css",
    "content": "/*!\n * Bootstrap v3.0.2 by @fat and @mdo\n * Copyright 2013 Twitter, Inc.\n * Licensed under http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world by @mdo and @fat.\n */\n\n/*! normalize.css v2.1.3 | MIT License | git.io/normalize */\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n  display: block;\n}\n\naudio,\ncanvas,\nvideo {\n  display: inline-block;\n}\n\naudio:not([controls]) {\n  display: none;\n  height: 0;\n}\n\n[hidden],\ntemplate {\n  display: none;\n}\n\nhtml {\n  font-family: sans-serif;\n  -webkit-text-size-adjust: 100%;\n      -ms-text-size-adjust: 100%;\n}\n\nbody {\n  margin: 0;\n}\n\na {\n  background: transparent;\n}\n\na:focus {\n  outline: thin dotted;\n}\n\na:active,\na:hover {\n  outline: 0;\n}\n\nh1 {\n  margin: 0.67em 0;\n  font-size: 2em;\n}\n\nabbr[title] {\n  border-bottom: 1px dotted;\n}\n\nb,\nstrong {\n  font-weight: bold;\n}\n\ndfn {\n  font-style: italic;\n}\n\nhr {\n  height: 0;\n  -moz-box-sizing: content-box;\n       box-sizing: content-box;\n}\n\nmark {\n  color: #000;\n  background: #ff0;\n}\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: monospace, serif;\n  font-size: 1em;\n}\n\npre {\n  white-space: pre-wrap;\n}\n\nq {\n  quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\";\n}\n\nsmall {\n  font-size: 80%;\n}\n\nsub,\nsup {\n  position: relative;\n  font-size: 75%;\n  line-height: 0;\n  vertical-align: baseline;\n}\n\nsup {\n  top: -0.5em;\n}\n\nsub {\n  bottom: -0.25em;\n}\n\nimg {\n  border: 0;\n}\n\nsvg:not(:root) {\n  overflow: hidden;\n}\n\nfigure {\n  margin: 0;\n}\n\nfieldset {\n  padding: 0.35em 0.625em 0.75em;\n  margin: 0 2px;\n  border: 1px solid #c0c0c0;\n}\n\nlegend {\n  padding: 0;\n  border: 0;\n}\n\nbutton,\ninput,\nselect,\ntextarea {\n  margin: 0;\n  font-family: inherit;\n  font-size: 100%;\n}\n\nbutton,\ninput {\n  line-height: normal;\n}\n\nbutton,\nselect {\n  text-transform: none;\n}\n\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n  cursor: pointer;\n  -webkit-appearance: button;\n}\n\nbutton[disabled],\nhtml input[disabled] {\n  cursor: default;\n}\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n  padding: 0;\n  box-sizing: border-box;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: content-box;\n     -moz-box-sizing: content-box;\n          box-sizing: content-box;\n  -webkit-appearance: textfield;\n}\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n  -webkit-appearance: none;\n}\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n  padding: 0;\n  border: 0;\n}\n\ntextarea {\n  overflow: auto;\n  vertical-align: top;\n}\n\ntable {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n@media print {\n  * {\n    color: #000 !important;\n    text-shadow: none !important;\n    background: transparent !important;\n    box-shadow: none !important;\n  }\n  a,\n  a:visited {\n    text-decoration: underline;\n  }\n  a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n  abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n  a[href^=\"javascript:\"]:after,\n  a[href^=\"#\"]:after {\n    content: \"\";\n  }\n  pre,\n  blockquote {\n    border: 1px solid #999;\n    page-break-inside: avoid;\n  }\n  thead {\n    display: table-header-group;\n  }\n  tr,\n  img {\n    page-break-inside: avoid;\n  }\n  img {\n    max-width: 100% !important;\n  }\n  @page  {\n    margin: 2cm .5cm;\n  }\n  p,\n  h2,\n  h3 {\n    orphans: 3;\n    widows: 3;\n  }\n  h2,\n  h3 {\n    page-break-after: avoid;\n  }\n  select {\n    background: #fff !important;\n  }\n  .navbar {\n    display: none;\n  }\n  .table td,\n  .table th {\n    background-color: #fff !important;\n  }\n  .btn > .caret,\n  .dropup > .btn > .caret {\n    border-top-color: #000 !important;\n  }\n  .label {\n    border: 1px solid #000;\n  }\n  .table {\n    border-collapse: collapse !important;\n  }\n  .table-bordered th,\n  .table-bordered td {\n    border: 1px solid #ddd !important;\n  }\n}\n\n*,\n*:before,\n*:after {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\nhtml {\n  font-size: 62.5%;\n  -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\nbody {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #333333;\n  background-color: #ffffff;\n}\n\ninput,\nbutton,\nselect,\ntextarea {\n  font-family: inherit;\n  font-size: inherit;\n  line-height: inherit;\n}\n\na {\n  color: #428bca;\n  text-decoration: none;\n}\n\na:hover,\na:focus {\n  color: #2a6496;\n  text-decoration: underline;\n}\n\na:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\nimg {\n  vertical-align: middle;\n}\n\n.img-responsive {\n  display: block;\n  height: auto;\n  max-width: 100%;\n}\n\n.img-rounded {\n  border-radius: 6px;\n}\n\n.img-thumbnail {\n  display: inline-block;\n  height: auto;\n  max-width: 100%;\n  padding: 4px;\n  line-height: 1.428571429;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\n.img-circle {\n  border-radius: 50%;\n}\n\nhr {\n  margin-top: 20px;\n  margin-bottom: 20px;\n  border: 0;\n  border-top: 1px solid #eeeeee;\n}\n\n.sr-only {\n  position: absolute;\n  width: 1px;\n  height: 1px;\n  padding: 0;\n  margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  border: 0;\n}\n\np {\n  margin: 0 0 10px;\n}\n\n.lead {\n  margin-bottom: 20px;\n  font-size: 16px;\n  font-weight: 200;\n  line-height: 1.4;\n}\n\n@media (min-width: 768px) {\n  .lead {\n    font-size: 21px;\n  }\n}\n\nsmall,\n.small {\n  font-size: 85%;\n}\n\ncite {\n  font-style: normal;\n}\n\n.text-muted {\n  color: #999999;\n}\n\n.text-primary {\n  color: #428bca;\n}\n\n.text-primary:hover {\n  color: #3071a9;\n}\n\n.text-warning {\n  color: #c09853;\n}\n\n.text-warning:hover {\n  color: #a47e3c;\n}\n\n.text-danger {\n  color: #b94a48;\n}\n\n.text-danger:hover {\n  color: #953b39;\n}\n\n.text-success {\n  color: #468847;\n}\n\n.text-success:hover {\n  color: #356635;\n}\n\n.text-info {\n  color: #3a87ad;\n}\n\n.text-info:hover {\n  color: #2d6987;\n}\n\n.text-left {\n  text-align: left;\n}\n\n.text-right {\n  text-align: right;\n}\n\n.text-center {\n  text-align: center;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n  font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  font-weight: 500;\n  line-height: 1.1;\n  color: inherit;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n  font-weight: normal;\n  line-height: 1;\n  color: #999999;\n}\n\nh1,\nh2,\nh3 {\n  margin-top: 20px;\n  margin-bottom: 10px;\n}\n\nh1 small,\nh2 small,\nh3 small,\nh1 .small,\nh2 .small,\nh3 .small {\n  font-size: 65%;\n}\n\nh4,\nh5,\nh6 {\n  margin-top: 10px;\n  margin-bottom: 10px;\n}\n\nh4 small,\nh5 small,\nh6 small,\nh4 .small,\nh5 .small,\nh6 .small {\n  font-size: 75%;\n}\n\nh1,\n.h1 {\n  font-size: 36px;\n}\n\nh2,\n.h2 {\n  font-size: 30px;\n}\n\nh3,\n.h3 {\n  font-size: 24px;\n}\n\nh4,\n.h4 {\n  font-size: 18px;\n}\n\nh5,\n.h5 {\n  font-size: 14px;\n}\n\nh6,\n.h6 {\n  font-size: 12px;\n}\n\n.page-header {\n  padding-bottom: 9px;\n  margin: 40px 0 20px;\n  border-bottom: 1px solid #eeeeee;\n}\n\nul,\nol {\n  margin-top: 0;\n  margin-bottom: 10px;\n}\n\nul ul,\nol ul,\nul ol,\nol ol {\n  margin-bottom: 0;\n}\n\n.list-unstyled {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-inline > li {\n  display: inline-block;\n  padding-right: 5px;\n  padding-left: 5px;\n}\n\n.list-inline > li:first-child {\n  padding-left: 0;\n}\n\ndl {\n  margin-bottom: 20px;\n}\n\ndt,\ndd {\n  line-height: 1.428571429;\n}\n\ndt {\n  font-weight: bold;\n}\n\ndd {\n  margin-left: 0;\n}\n\n@media (min-width: 768px) {\n  .dl-horizontal dt {\n    float: left;\n    width: 160px;\n    overflow: hidden;\n    clear: left;\n    text-align: right;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n  }\n  .dl-horizontal dd {\n    margin-left: 180px;\n  }\n  .dl-horizontal dd:before,\n  .dl-horizontal dd:after {\n    display: table;\n    content: \" \";\n  }\n  .dl-horizontal dd:after {\n    clear: both;\n  }\n  .dl-horizontal dd:before,\n  .dl-horizontal dd:after {\n    display: table;\n    content: \" \";\n  }\n  .dl-horizontal dd:after {\n    clear: both;\n  }\n}\n\nabbr[title],\nabbr[data-original-title] {\n  cursor: help;\n  border-bottom: 1px dotted #999999;\n}\n\nabbr.initialism {\n  font-size: 90%;\n  text-transform: uppercase;\n}\n\nblockquote {\n  padding: 10px 20px;\n  margin: 0 0 20px;\n  border-left: 5px solid #eeeeee;\n}\n\nblockquote p {\n  font-size: 17.5px;\n  font-weight: 300;\n  line-height: 1.25;\n}\n\nblockquote p:last-child {\n  margin-bottom: 0;\n}\n\nblockquote small {\n  display: block;\n  line-height: 1.428571429;\n  color: #999999;\n}\n\nblockquote small:before {\n  content: '\\2014 \\00A0';\n}\n\nblockquote.pull-right {\n  padding-right: 15px;\n  padding-left: 0;\n  border-right: 5px solid #eeeeee;\n  border-left: 0;\n}\n\nblockquote.pull-right p,\nblockquote.pull-right small,\nblockquote.pull-right .small {\n  text-align: right;\n}\n\nblockquote.pull-right small:before,\nblockquote.pull-right .small:before {\n  content: '';\n}\n\nblockquote.pull-right small:after,\nblockquote.pull-right .small:after {\n  content: '\\00A0 \\2014';\n}\n\nblockquote:before,\nblockquote:after {\n  content: \"\";\n}\n\naddress {\n  margin-bottom: 20px;\n  font-style: normal;\n  line-height: 1.428571429;\n}\n\ncode,\nkbd,\npre,\nsamp {\n  font-family: Monaco, Menlo, Consolas, \"Courier New\", monospace;\n}\n\ncode {\n  padding: 2px 4px;\n  font-size: 90%;\n  color: #c7254e;\n  white-space: nowrap;\n  background-color: #f9f2f4;\n  border-radius: 4px;\n}\n\npre {\n  display: block;\n  padding: 9.5px;\n  margin: 0 0 10px;\n  font-size: 13px;\n  line-height: 1.428571429;\n  color: #333333;\n  word-break: break-all;\n  word-wrap: break-word;\n  background-color: #f5f5f5;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\n\npre code {\n  padding: 0;\n  font-size: inherit;\n  color: inherit;\n  white-space: pre-wrap;\n  background-color: transparent;\n  border-radius: 0;\n}\n\n.pre-scrollable {\n  max-height: 340px;\n  overflow-y: scroll;\n}\n\n.container {\n  padding-right: 15px;\n  padding-left: 15px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  content: \" \";\n}\n\n.container:after {\n  clear: both;\n}\n\n.container:before,\n.container:after {\n  display: table;\n  content: \" \";\n}\n\n.container:after {\n  clear: both;\n}\n\n.row {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  content: \" \";\n}\n\n.row:after {\n  clear: both;\n}\n\n.row:before,\n.row:after {\n  display: table;\n  content: \" \";\n}\n\n.row:after {\n  clear: both;\n}\n\n.col-xs-1,\n.col-sm-1,\n.col-md-1,\n.col-lg-1,\n.col-xs-2,\n.col-sm-2,\n.col-md-2,\n.col-lg-2,\n.col-xs-3,\n.col-sm-3,\n.col-md-3,\n.col-lg-3,\n.col-xs-4,\n.col-sm-4,\n.col-md-4,\n.col-lg-4,\n.col-xs-5,\n.col-sm-5,\n.col-md-5,\n.col-lg-5,\n.col-xs-6,\n.col-sm-6,\n.col-md-6,\n.col-lg-6,\n.col-xs-7,\n.col-sm-7,\n.col-md-7,\n.col-lg-7,\n.col-xs-8,\n.col-sm-8,\n.col-md-8,\n.col-lg-8,\n.col-xs-9,\n.col-sm-9,\n.col-md-9,\n.col-lg-9,\n.col-xs-10,\n.col-sm-10,\n.col-md-10,\n.col-lg-10,\n.col-xs-11,\n.col-sm-11,\n.col-md-11,\n.col-lg-11,\n.col-xs-12,\n.col-sm-12,\n.col-md-12,\n.col-lg-12 {\n  position: relative;\n  min-height: 1px;\n  padding-right: 15px;\n  padding-left: 15px;\n}\n\n.col-xs-1,\n.col-xs-2,\n.col-xs-3,\n.col-xs-4,\n.col-xs-5,\n.col-xs-6,\n.col-xs-7,\n.col-xs-8,\n.col-xs-9,\n.col-xs-10,\n.col-xs-11 {\n  float: left;\n}\n\n.col-xs-12 {\n  width: 100%;\n}\n\n.col-xs-11 {\n  width: 91.66666666666666%;\n}\n\n.col-xs-10 {\n  width: 83.33333333333334%;\n}\n\n.col-xs-9 {\n  width: 75%;\n}\n\n.col-xs-8 {\n  width: 66.66666666666666%;\n}\n\n.col-xs-7 {\n  width: 58.333333333333336%;\n}\n\n.col-xs-6 {\n  width: 50%;\n}\n\n.col-xs-5 {\n  width: 41.66666666666667%;\n}\n\n.col-xs-4 {\n  width: 33.33333333333333%;\n}\n\n.col-xs-3 {\n  width: 25%;\n}\n\n.col-xs-2 {\n  width: 16.666666666666664%;\n}\n\n.col-xs-1 {\n  width: 8.333333333333332%;\n}\n\n.col-xs-pull-12 {\n  right: 100%;\n}\n\n.col-xs-pull-11 {\n  right: 91.66666666666666%;\n}\n\n.col-xs-pull-10 {\n  right: 83.33333333333334%;\n}\n\n.col-xs-pull-9 {\n  right: 75%;\n}\n\n.col-xs-pull-8 {\n  right: 66.66666666666666%;\n}\n\n.col-xs-pull-7 {\n  right: 58.333333333333336%;\n}\n\n.col-xs-pull-6 {\n  right: 50%;\n}\n\n.col-xs-pull-5 {\n  right: 41.66666666666667%;\n}\n\n.col-xs-pull-4 {\n  right: 33.33333333333333%;\n}\n\n.col-xs-pull-3 {\n  right: 25%;\n}\n\n.col-xs-pull-2 {\n  right: 16.666666666666664%;\n}\n\n.col-xs-pull-1 {\n  right: 8.333333333333332%;\n}\n\n.col-xs-pull-0 {\n  right: 0;\n}\n\n.col-xs-push-12 {\n  left: 100%;\n}\n\n.col-xs-push-11 {\n  left: 91.66666666666666%;\n}\n\n.col-xs-push-10 {\n  left: 83.33333333333334%;\n}\n\n.col-xs-push-9 {\n  left: 75%;\n}\n\n.col-xs-push-8 {\n  left: 66.66666666666666%;\n}\n\n.col-xs-push-7 {\n  left: 58.333333333333336%;\n}\n\n.col-xs-push-6 {\n  left: 50%;\n}\n\n.col-xs-push-5 {\n  left: 41.66666666666667%;\n}\n\n.col-xs-push-4 {\n  left: 33.33333333333333%;\n}\n\n.col-xs-push-3 {\n  left: 25%;\n}\n\n.col-xs-push-2 {\n  left: 16.666666666666664%;\n}\n\n.col-xs-push-1 {\n  left: 8.333333333333332%;\n}\n\n.col-xs-push-0 {\n  left: 0;\n}\n\n.col-xs-offset-12 {\n  margin-left: 100%;\n}\n\n.col-xs-offset-11 {\n  margin-left: 91.66666666666666%;\n}\n\n.col-xs-offset-10 {\n  margin-left: 83.33333333333334%;\n}\n\n.col-xs-offset-9 {\n  margin-left: 75%;\n}\n\n.col-xs-offset-8 {\n  margin-left: 66.66666666666666%;\n}\n\n.col-xs-offset-7 {\n  margin-left: 58.333333333333336%;\n}\n\n.col-xs-offset-6 {\n  margin-left: 50%;\n}\n\n.col-xs-offset-5 {\n  margin-left: 41.66666666666667%;\n}\n\n.col-xs-offset-4 {\n  margin-left: 33.33333333333333%;\n}\n\n.col-xs-offset-3 {\n  margin-left: 25%;\n}\n\n.col-xs-offset-2 {\n  margin-left: 16.666666666666664%;\n}\n\n.col-xs-offset-1 {\n  margin-left: 8.333333333333332%;\n}\n\n.col-xs-offset-0 {\n  margin-left: 0;\n}\n\n@media (min-width: 768px) {\n  .container {\n    width: 750px;\n  }\n  .col-sm-1,\n  .col-sm-2,\n  .col-sm-3,\n  .col-sm-4,\n  .col-sm-5,\n  .col-sm-6,\n  .col-sm-7,\n  .col-sm-8,\n  .col-sm-9,\n  .col-sm-10,\n  .col-sm-11 {\n    float: left;\n  }\n  .col-sm-12 {\n    width: 100%;\n  }\n  .col-sm-11 {\n    width: 91.66666666666666%;\n  }\n  .col-sm-10 {\n    width: 83.33333333333334%;\n  }\n  .col-sm-9 {\n    width: 75%;\n  }\n  .col-sm-8 {\n    width: 66.66666666666666%;\n  }\n  .col-sm-7 {\n    width: 58.333333333333336%;\n  }\n  .col-sm-6 {\n    width: 50%;\n  }\n  .col-sm-5 {\n    width: 41.66666666666667%;\n  }\n  .col-sm-4 {\n    width: 33.33333333333333%;\n  }\n  .col-sm-3 {\n    width: 25%;\n  }\n  .col-sm-2 {\n    width: 16.666666666666664%;\n  }\n  .col-sm-1 {\n    width: 8.333333333333332%;\n  }\n  .col-sm-pull-12 {\n    right: 100%;\n  }\n  .col-sm-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-sm-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-sm-pull-9 {\n    right: 75%;\n  }\n  .col-sm-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-sm-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-sm-pull-6 {\n    right: 50%;\n  }\n  .col-sm-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-sm-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-sm-pull-3 {\n    right: 25%;\n  }\n  .col-sm-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-sm-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-sm-pull-0 {\n    right: 0;\n  }\n  .col-sm-push-12 {\n    left: 100%;\n  }\n  .col-sm-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-sm-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-sm-push-9 {\n    left: 75%;\n  }\n  .col-sm-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-sm-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-sm-push-6 {\n    left: 50%;\n  }\n  .col-sm-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-sm-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-sm-push-3 {\n    left: 25%;\n  }\n  .col-sm-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-sm-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-sm-push-0 {\n    left: 0;\n  }\n  .col-sm-offset-12 {\n    margin-left: 100%;\n  }\n  .col-sm-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .col-sm-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-sm-offset-9 {\n    margin-left: 75%;\n  }\n  .col-sm-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-sm-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-sm-offset-6 {\n    margin-left: 50%;\n  }\n  .col-sm-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-sm-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-sm-offset-3 {\n    margin-left: 25%;\n  }\n  .col-sm-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-sm-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-sm-offset-0 {\n    margin-left: 0;\n  }\n}\n\n@media (min-width: 992px) {\n  .container {\n    width: 970px;\n  }\n  .col-md-1,\n  .col-md-2,\n  .col-md-3,\n  .col-md-4,\n  .col-md-5,\n  .col-md-6,\n  .col-md-7,\n  .col-md-8,\n  .col-md-9,\n  .col-md-10,\n  .col-md-11 {\n    float: left;\n  }\n  .col-md-12 {\n    width: 100%;\n  }\n  .col-md-11 {\n    width: 91.66666666666666%;\n  }\n  .col-md-10 {\n    width: 83.33333333333334%;\n  }\n  .col-md-9 {\n    width: 75%;\n  }\n  .col-md-8 {\n    width: 66.66666666666666%;\n  }\n  .col-md-7 {\n    width: 58.333333333333336%;\n  }\n  .col-md-6 {\n    width: 50%;\n  }\n  .col-md-5 {\n    width: 41.66666666666667%;\n  }\n  .col-md-4 {\n    width: 33.33333333333333%;\n  }\n  .col-md-3 {\n    width: 25%;\n  }\n  .col-md-2 {\n    width: 16.666666666666664%;\n  }\n  .col-md-1 {\n    width: 8.333333333333332%;\n  }\n  .col-md-pull-12 {\n    right: 100%;\n  }\n  .col-md-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-md-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-md-pull-9 {\n    right: 75%;\n  }\n  .col-md-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-md-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-md-pull-6 {\n    right: 50%;\n  }\n  .col-md-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-md-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-md-pull-3 {\n    right: 25%;\n  }\n  .col-md-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-md-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-md-pull-0 {\n    right: 0;\n  }\n  .col-md-push-12 {\n    left: 100%;\n  }\n  .col-md-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-md-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-md-push-9 {\n    left: 75%;\n  }\n  .col-md-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-md-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-md-push-6 {\n    left: 50%;\n  }\n  .col-md-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-md-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-md-push-3 {\n    left: 25%;\n  }\n  .col-md-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-md-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-md-push-0 {\n    left: 0;\n  }\n  .col-md-offset-12 {\n    margin-left: 100%;\n  }\n  .col-md-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .col-md-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-md-offset-9 {\n    margin-left: 75%;\n  }\n  .col-md-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-md-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-md-offset-6 {\n    margin-left: 50%;\n  }\n  .col-md-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-md-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-md-offset-3 {\n    margin-left: 25%;\n  }\n  .col-md-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-md-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-md-offset-0 {\n    margin-left: 0;\n  }\n}\n\n@media (min-width: 1200px) {\n  .container {\n    width: 1170px;\n  }\n  .col-lg-1,\n  .col-lg-2,\n  .col-lg-3,\n  .col-lg-4,\n  .col-lg-5,\n  .col-lg-6,\n  .col-lg-7,\n  .col-lg-8,\n  .col-lg-9,\n  .col-lg-10,\n  .col-lg-11 {\n    float: left;\n  }\n  .col-lg-12 {\n    width: 100%;\n  }\n  .col-lg-11 {\n    width: 91.66666666666666%;\n  }\n  .col-lg-10 {\n    width: 83.33333333333334%;\n  }\n  .col-lg-9 {\n    width: 75%;\n  }\n  .col-lg-8 {\n    width: 66.66666666666666%;\n  }\n  .col-lg-7 {\n    width: 58.333333333333336%;\n  }\n  .col-lg-6 {\n    width: 50%;\n  }\n  .col-lg-5 {\n    width: 41.66666666666667%;\n  }\n  .col-lg-4 {\n    width: 33.33333333333333%;\n  }\n  .col-lg-3 {\n    width: 25%;\n  }\n  .col-lg-2 {\n    width: 16.666666666666664%;\n  }\n  .col-lg-1 {\n    width: 8.333333333333332%;\n  }\n  .col-lg-pull-12 {\n    right: 100%;\n  }\n  .col-lg-pull-11 {\n    right: 91.66666666666666%;\n  }\n  .col-lg-pull-10 {\n    right: 83.33333333333334%;\n  }\n  .col-lg-pull-9 {\n    right: 75%;\n  }\n  .col-lg-pull-8 {\n    right: 66.66666666666666%;\n  }\n  .col-lg-pull-7 {\n    right: 58.333333333333336%;\n  }\n  .col-lg-pull-6 {\n    right: 50%;\n  }\n  .col-lg-pull-5 {\n    right: 41.66666666666667%;\n  }\n  .col-lg-pull-4 {\n    right: 33.33333333333333%;\n  }\n  .col-lg-pull-3 {\n    right: 25%;\n  }\n  .col-lg-pull-2 {\n    right: 16.666666666666664%;\n  }\n  .col-lg-pull-1 {\n    right: 8.333333333333332%;\n  }\n  .col-lg-pull-0 {\n    right: 0;\n  }\n  .col-lg-push-12 {\n    left: 100%;\n  }\n  .col-lg-push-11 {\n    left: 91.66666666666666%;\n  }\n  .col-lg-push-10 {\n    left: 83.33333333333334%;\n  }\n  .col-lg-push-9 {\n    left: 75%;\n  }\n  .col-lg-push-8 {\n    left: 66.66666666666666%;\n  }\n  .col-lg-push-7 {\n    left: 58.333333333333336%;\n  }\n  .col-lg-push-6 {\n    left: 50%;\n  }\n  .col-lg-push-5 {\n    left: 41.66666666666667%;\n  }\n  .col-lg-push-4 {\n    left: 33.33333333333333%;\n  }\n  .col-lg-push-3 {\n    left: 25%;\n  }\n  .col-lg-push-2 {\n    left: 16.666666666666664%;\n  }\n  .col-lg-push-1 {\n    left: 8.333333333333332%;\n  }\n  .col-lg-push-0 {\n    left: 0;\n  }\n  .col-lg-offset-12 {\n    margin-left: 100%;\n  }\n  .col-lg-offset-11 {\n    margin-left: 91.66666666666666%;\n  }\n  .col-lg-offset-10 {\n    margin-left: 83.33333333333334%;\n  }\n  .col-lg-offset-9 {\n    margin-left: 75%;\n  }\n  .col-lg-offset-8 {\n    margin-left: 66.66666666666666%;\n  }\n  .col-lg-offset-7 {\n    margin-left: 58.333333333333336%;\n  }\n  .col-lg-offset-6 {\n    margin-left: 50%;\n  }\n  .col-lg-offset-5 {\n    margin-left: 41.66666666666667%;\n  }\n  .col-lg-offset-4 {\n    margin-left: 33.33333333333333%;\n  }\n  .col-lg-offset-3 {\n    margin-left: 25%;\n  }\n  .col-lg-offset-2 {\n    margin-left: 16.666666666666664%;\n  }\n  .col-lg-offset-1 {\n    margin-left: 8.333333333333332%;\n  }\n  .col-lg-offset-0 {\n    margin-left: 0;\n  }\n}\n\ntable {\n  max-width: 100%;\n  background-color: transparent;\n}\n\nth {\n  text-align: left;\n}\n\n.table {\n  width: 100%;\n  margin-bottom: 20px;\n}\n\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n  padding: 8px;\n  line-height: 1.428571429;\n  vertical-align: top;\n  border-top: 1px solid #dddddd;\n}\n\n.table > thead > tr > th {\n  vertical-align: bottom;\n  border-bottom: 2px solid #dddddd;\n}\n\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n  border-top: 0;\n}\n\n.table > tbody + tbody {\n  border-top: 2px solid #dddddd;\n}\n\n.table .table {\n  background-color: #ffffff;\n}\n\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n  padding: 5px;\n}\n\n.table-bordered {\n  border: 1px solid #dddddd;\n}\n\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n  border: 1px solid #dddddd;\n}\n\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n  border-bottom-width: 2px;\n}\n\n.table-striped > tbody > tr:nth-child(odd) > td,\n.table-striped > tbody > tr:nth-child(odd) > th {\n  background-color: #f9f9f9;\n}\n\n.table-hover > tbody > tr:hover > td,\n.table-hover > tbody > tr:hover > th {\n  background-color: #f5f5f5;\n}\n\ntable col[class*=\"col-\"] {\n  display: table-column;\n  float: none;\n}\n\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n  display: table-cell;\n  float: none;\n}\n\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n  background-color: #f5f5f5;\n}\n\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n  background-color: #dff0d8;\n}\n\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr.success:hover > th {\n  background-color: #d0e9c6;\n}\n\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n  background-color: #f2dede;\n}\n\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr.danger:hover > th {\n  background-color: #ebcccc;\n}\n\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n  background-color: #fcf8e3;\n}\n\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr.warning:hover > th {\n  background-color: #faf2cc;\n}\n\n@media (max-width: 767px) {\n  .table-responsive {\n    width: 100%;\n    margin-bottom: 15px;\n    overflow-x: scroll;\n    overflow-y: hidden;\n    border: 1px solid #dddddd;\n    -ms-overflow-style: -ms-autohiding-scrollbar;\n    -webkit-overflow-scrolling: touch;\n  }\n  .table-responsive > .table {\n    margin-bottom: 0;\n  }\n  .table-responsive > .table > thead > tr > th,\n  .table-responsive > .table > tbody > tr > th,\n  .table-responsive > .table > tfoot > tr > th,\n  .table-responsive > .table > thead > tr > td,\n  .table-responsive > .table > tbody > tr > td,\n  .table-responsive > .table > tfoot > tr > td {\n    white-space: nowrap;\n  }\n  .table-responsive > .table-bordered {\n    border: 0;\n  }\n  .table-responsive > .table-bordered > thead > tr > th:first-child,\n  .table-responsive > .table-bordered > tbody > tr > th:first-child,\n  .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n  .table-responsive > .table-bordered > thead > tr > td:first-child,\n  .table-responsive > .table-bordered > tbody > tr > td:first-child,\n  .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n    border-left: 0;\n  }\n  .table-responsive > .table-bordered > thead > tr > th:last-child,\n  .table-responsive > .table-bordered > tbody > tr > th:last-child,\n  .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n  .table-responsive > .table-bordered > thead > tr > td:last-child,\n  .table-responsive > .table-bordered > tbody > tr > td:last-child,\n  .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n    border-right: 0;\n  }\n  .table-responsive > .table-bordered > tbody > tr:last-child > th,\n  .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n  .table-responsive > .table-bordered > tbody > tr:last-child > td,\n  .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n    border-bottom: 0;\n  }\n}\n\nfieldset {\n  padding: 0;\n  margin: 0;\n  border: 0;\n}\n\nlegend {\n  display: block;\n  width: 100%;\n  padding: 0;\n  margin-bottom: 20px;\n  font-size: 21px;\n  line-height: inherit;\n  color: #333333;\n  border: 0;\n  border-bottom: 1px solid #e5e5e5;\n}\n\nlabel {\n  display: inline-block;\n  margin-bottom: 5px;\n  font-weight: bold;\n}\n\ninput[type=\"search\"] {\n  -webkit-box-sizing: border-box;\n     -moz-box-sizing: border-box;\n          box-sizing: border-box;\n}\n\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n  margin: 4px 0 0;\n  margin-top: 1px \\9;\n  /* IE8-9 */\n\n  line-height: normal;\n}\n\ninput[type=\"file\"] {\n  display: block;\n}\n\nselect[multiple],\nselect[size] {\n  height: auto;\n}\n\nselect optgroup {\n  font-family: inherit;\n  font-size: inherit;\n  font-style: inherit;\n}\n\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\ninput[type=\"number\"]::-webkit-outer-spin-button,\ninput[type=\"number\"]::-webkit-inner-spin-button {\n  height: auto;\n}\n\noutput {\n  display: block;\n  padding-top: 7px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #555555;\n  vertical-align: middle;\n}\n\n.form-control {\n  display: block;\n  width: 100%;\n  height: 34px;\n  padding: 6px 12px;\n  font-size: 14px;\n  line-height: 1.428571429;\n  color: #555555;\n  vertical-align: middle;\n  background-color: #ffffff;\n  background-image: none;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n  -webkit-transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n          transition: border-color ease-in-out 0.15s, box-shadow ease-in-out 0.15s;\n}\n\n.form-control:focus {\n  border-color: #66afe9;\n  outline: 0;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n\n.form-control:-moz-placeholder {\n  color: #999999;\n}\n\n.form-control::-moz-placeholder {\n  color: #999999;\n}\n\n.form-control:-ms-input-placeholder {\n  color: #999999;\n}\n\n.form-control::-webkit-input-placeholder {\n  color: #999999;\n}\n\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n  cursor: not-allowed;\n  background-color: #eeeeee;\n}\n\ntextarea.form-control {\n  height: auto;\n}\n\n.form-group {\n  margin-bottom: 15px;\n}\n\n.radio,\n.checkbox {\n  display: block;\n  min-height: 20px;\n  padding-left: 20px;\n  margin-top: 10px;\n  margin-bottom: 10px;\n  vertical-align: middle;\n}\n\n.radio label,\n.checkbox label {\n  display: inline;\n  margin-bottom: 0;\n  font-weight: normal;\n  cursor: pointer;\n}\n\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n  float: left;\n  margin-left: -20px;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n  margin-top: -5px;\n}\n\n.radio-inline,\n.checkbox-inline {\n  display: inline-block;\n  padding-left: 20px;\n  margin-bottom: 0;\n  font-weight: normal;\n  vertical-align: middle;\n  cursor: pointer;\n}\n\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n  margin-top: 0;\n  margin-left: 10px;\n}\n\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\n.radio[disabled],\n.radio-inline[disabled],\n.checkbox[disabled],\n.checkbox-inline[disabled],\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"],\nfieldset[disabled] .radio,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox,\nfieldset[disabled] .checkbox-inline {\n  cursor: not-allowed;\n}\n\n.input-sm {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\nselect.input-sm {\n  height: 30px;\n  line-height: 30px;\n}\n\ntextarea.input-sm {\n  height: auto;\n}\n\n.input-lg {\n  height: 45px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\nselect.input-lg {\n  height: 45px;\n  line-height: 45px;\n}\n\ntextarea.input-lg {\n  height: auto;\n}\n\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline {\n  color: #c09853;\n}\n\n.has-warning .form-control {\n  border-color: #c09853;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-warning .form-control:focus {\n  border-color: #a47e3c;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;\n}\n\n.has-warning .input-group-addon {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #c09853;\n}\n\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline {\n  color: #b94a48;\n}\n\n.has-error .form-control {\n  border-color: #b94a48;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-error .form-control:focus {\n  border-color: #953b39;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;\n}\n\n.has-error .input-group-addon {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #b94a48;\n}\n\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline {\n  color: #468847;\n}\n\n.has-success .form-control {\n  border-color: #468847;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n\n.has-success .form-control:focus {\n  border-color: #356635;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;\n}\n\n.has-success .input-group-addon {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #468847;\n}\n\n.form-control-static {\n  margin-bottom: 0;\n}\n\n.help-block {\n  display: block;\n  margin-top: 5px;\n  margin-bottom: 10px;\n  color: #737373;\n}\n\n@media (min-width: 768px) {\n  .form-inline .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .form-inline .form-control {\n    display: inline-block;\n  }\n  .form-inline .radio,\n  .form-inline .checkbox {\n    display: inline-block;\n    padding-left: 0;\n    margin-top: 0;\n    margin-bottom: 0;\n  }\n  .form-inline .radio input[type=\"radio\"],\n  .form-inline .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n\n.form-horizontal .control-label,\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n  padding-top: 7px;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.form-horizontal .form-group {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  display: table;\n  content: \" \";\n}\n\n.form-horizontal .form-group:after {\n  clear: both;\n}\n\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after {\n  display: table;\n  content: \" \";\n}\n\n.form-horizontal .form-group:after {\n  clear: both;\n}\n\n.form-horizontal .form-control-static {\n  padding-top: 7px;\n}\n\n@media (min-width: 768px) {\n  .form-horizontal .control-label {\n    text-align: right;\n  }\n}\n\n.btn {\n  display: inline-block;\n  padding: 6px 12px;\n  margin-bottom: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1.428571429;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: middle;\n  cursor: pointer;\n  background-image: none;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n       -o-user-select: none;\n          user-select: none;\n}\n\n.btn:focus {\n  outline: thin dotted #333;\n  outline: 5px auto -webkit-focus-ring-color;\n  outline-offset: -2px;\n}\n\n.btn:hover,\n.btn:focus {\n  color: #333333;\n  text-decoration: none;\n}\n\n.btn:active,\n.btn.active {\n  background-image: none;\n  outline: 0;\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n  pointer-events: none;\n  cursor: not-allowed;\n  opacity: 0.65;\n  filter: alpha(opacity=65);\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-default {\n  color: #333333;\n  background-color: #ffffff;\n  border-color: #cccccc;\n}\n\n.btn-default:hover,\n.btn-default:focus,\n.btn-default:active,\n.btn-default.active,\n.open .dropdown-toggle.btn-default {\n  color: #333333;\n  background-color: #ebebeb;\n  border-color: #adadad;\n}\n\n.btn-default:active,\n.btn-default.active,\n.open .dropdown-toggle.btn-default {\n  background-image: none;\n}\n\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n  background-color: #ffffff;\n  border-color: #cccccc;\n}\n\n.btn-primary {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary:active,\n.btn-primary.active,\n.open .dropdown-toggle.btn-primary {\n  color: #ffffff;\n  background-color: #3276b1;\n  border-color: #285e8e;\n}\n\n.btn-primary:active,\n.btn-primary.active,\n.open .dropdown-toggle.btn-primary {\n  background-image: none;\n}\n\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n  background-color: #428bca;\n  border-color: #357ebd;\n}\n\n.btn-warning {\n  color: #ffffff;\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning:active,\n.btn-warning.active,\n.open .dropdown-toggle.btn-warning {\n  color: #ffffff;\n  background-color: #ed9c28;\n  border-color: #d58512;\n}\n\n.btn-warning:active,\n.btn-warning.active,\n.open .dropdown-toggle.btn-warning {\n  background-image: none;\n}\n\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n  background-color: #f0ad4e;\n  border-color: #eea236;\n}\n\n.btn-danger {\n  color: #ffffff;\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger:active,\n.btn-danger.active,\n.open .dropdown-toggle.btn-danger {\n  color: #ffffff;\n  background-color: #d2322d;\n  border-color: #ac2925;\n}\n\n.btn-danger:active,\n.btn-danger.active,\n.open .dropdown-toggle.btn-danger {\n  background-image: none;\n}\n\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n  background-color: #d9534f;\n  border-color: #d43f3a;\n}\n\n.btn-success {\n  color: #ffffff;\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n\n.btn-success:hover,\n.btn-success:focus,\n.btn-success:active,\n.btn-success.active,\n.open .dropdown-toggle.btn-success {\n  color: #ffffff;\n  background-color: #47a447;\n  border-color: #398439;\n}\n\n.btn-success:active,\n.btn-success.active,\n.open .dropdown-toggle.btn-success {\n  background-image: none;\n}\n\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n  background-color: #5cb85c;\n  border-color: #4cae4c;\n}\n\n.btn-info {\n  color: #ffffff;\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n\n.btn-info:hover,\n.btn-info:focus,\n.btn-info:active,\n.btn-info.active,\n.open .dropdown-toggle.btn-info {\n  color: #ffffff;\n  background-color: #39b3d7;\n  border-color: #269abc;\n}\n\n.btn-info:active,\n.btn-info.active,\n.open .dropdown-toggle.btn-info {\n  background-image: none;\n}\n\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n  background-color: #5bc0de;\n  border-color: #46b8da;\n}\n\n.btn-link {\n  font-weight: normal;\n  color: #428bca;\n  cursor: pointer;\n  border-radius: 0;\n}\n\n.btn-link,\n.btn-link:active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n  background-color: transparent;\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n  border-color: transparent;\n}\n\n.btn-link:hover,\n.btn-link:focus {\n  color: #2a6496;\n  text-decoration: underline;\n  background-color: transparent;\n}\n\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n  color: #999999;\n  text-decoration: none;\n}\n\n.btn-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\n.btn-sm,\n.btn-xs {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-xs {\n  padding: 1px 5px;\n}\n\n.btn-block {\n  display: block;\n  width: 100%;\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.btn-block + .btn-block {\n  margin-top: 5px;\n}\n\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n  width: 100%;\n}\n\n.fade {\n  opacity: 0;\n  -webkit-transition: opacity 0.15s linear;\n          transition: opacity 0.15s linear;\n}\n\n.fade.in {\n  opacity: 1;\n}\n\n.collapse {\n  display: none;\n}\n\n.collapse.in {\n  display: block;\n}\n\n.collapsing {\n  position: relative;\n  height: 0;\n  overflow: hidden;\n  -webkit-transition: height 0.35s ease;\n          transition: height 0.35s ease;\n}\n\n@font-face {\n  font-family: 'Glyphicons Halflings';\n  src: url('../fonts/glyphicons-halflings-regular.eot');\n  src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n\n.glyphicon {\n  position: relative;\n  top: 1px;\n  display: inline-block;\n  font-family: 'Glyphicons Halflings';\n  -webkit-font-smoothing: antialiased;\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n.glyphicon:empty {\n  width: 1em;\n}\n\n.glyphicon-asterisk:before {\n  content: \"\\2a\";\n}\n\n.glyphicon-plus:before {\n  content: \"\\2b\";\n}\n\n.glyphicon-euro:before {\n  content: \"\\20ac\";\n}\n\n.glyphicon-minus:before {\n  content: \"\\2212\";\n}\n\n.glyphicon-cloud:before {\n  content: \"\\2601\";\n}\n\n.glyphicon-envelope:before {\n  content: \"\\2709\";\n}\n\n.glyphicon-pencil:before {\n  content: \"\\270f\";\n}\n\n.glyphicon-glass:before {\n  content: \"\\e001\";\n}\n\n.glyphicon-music:before {\n  content: \"\\e002\";\n}\n\n.glyphicon-search:before {\n  content: \"\\e003\";\n}\n\n.glyphicon-heart:before {\n  content: \"\\e005\";\n}\n\n.glyphicon-star:before {\n  content: \"\\e006\";\n}\n\n.glyphicon-star-empty:before {\n  content: \"\\e007\";\n}\n\n.glyphicon-user:before {\n  content: \"\\e008\";\n}\n\n.glyphicon-film:before {\n  content: \"\\e009\";\n}\n\n.glyphicon-th-large:before {\n  content: \"\\e010\";\n}\n\n.glyphicon-th:before {\n  content: \"\\e011\";\n}\n\n.glyphicon-th-list:before {\n  content: \"\\e012\";\n}\n\n.glyphicon-ok:before {\n  content: \"\\e013\";\n}\n\n.glyphicon-remove:before {\n  content: \"\\e014\";\n}\n\n.glyphicon-zoom-in:before {\n  content: \"\\e015\";\n}\n\n.glyphicon-zoom-out:before {\n  content: \"\\e016\";\n}\n\n.glyphicon-off:before {\n  content: \"\\e017\";\n}\n\n.glyphicon-signal:before {\n  content: \"\\e018\";\n}\n\n.glyphicon-cog:before {\n  content: \"\\e019\";\n}\n\n.glyphicon-trash:before {\n  content: \"\\e020\";\n}\n\n.glyphicon-home:before {\n  content: \"\\e021\";\n}\n\n.glyphicon-file:before {\n  content: \"\\e022\";\n}\n\n.glyphicon-time:before {\n  content: \"\\e023\";\n}\n\n.glyphicon-road:before {\n  content: \"\\e024\";\n}\n\n.glyphicon-download-alt:before {\n  content: \"\\e025\";\n}\n\n.glyphicon-download:before {\n  content: \"\\e026\";\n}\n\n.glyphicon-upload:before {\n  content: \"\\e027\";\n}\n\n.glyphicon-inbox:before {\n  content: \"\\e028\";\n}\n\n.glyphicon-play-circle:before {\n  content: \"\\e029\";\n}\n\n.glyphicon-repeat:before {\n  content: \"\\e030\";\n}\n\n.glyphicon-refresh:before {\n  content: \"\\e031\";\n}\n\n.glyphicon-list-alt:before {\n  content: \"\\e032\";\n}\n\n.glyphicon-lock:before {\n  content: \"\\e033\";\n}\n\n.glyphicon-flag:before {\n  content: \"\\e034\";\n}\n\n.glyphicon-headphones:before {\n  content: \"\\e035\";\n}\n\n.glyphicon-volume-off:before {\n  content: \"\\e036\";\n}\n\n.glyphicon-volume-down:before {\n  content: \"\\e037\";\n}\n\n.glyphicon-volume-up:before {\n  content: \"\\e038\";\n}\n\n.glyphicon-qrcode:before {\n  content: \"\\e039\";\n}\n\n.glyphicon-barcode:before {\n  content: \"\\e040\";\n}\n\n.glyphicon-tag:before {\n  content: \"\\e041\";\n}\n\n.glyphicon-tags:before {\n  content: \"\\e042\";\n}\n\n.glyphicon-book:before {\n  content: \"\\e043\";\n}\n\n.glyphicon-bookmark:before {\n  content: \"\\e044\";\n}\n\n.glyphicon-print:before {\n  content: \"\\e045\";\n}\n\n.glyphicon-camera:before {\n  content: \"\\e046\";\n}\n\n.glyphicon-font:before {\n  content: \"\\e047\";\n}\n\n.glyphicon-bold:before {\n  content: \"\\e048\";\n}\n\n.glyphicon-italic:before {\n  content: \"\\e049\";\n}\n\n.glyphicon-text-height:before {\n  content: \"\\e050\";\n}\n\n.glyphicon-text-width:before {\n  content: \"\\e051\";\n}\n\n.glyphicon-align-left:before {\n  content: \"\\e052\";\n}\n\n.glyphicon-align-center:before {\n  content: \"\\e053\";\n}\n\n.glyphicon-align-right:before {\n  content: \"\\e054\";\n}\n\n.glyphicon-align-justify:before {\n  content: \"\\e055\";\n}\n\n.glyphicon-list:before {\n  content: \"\\e056\";\n}\n\n.glyphicon-indent-left:before {\n  content: \"\\e057\";\n}\n\n.glyphicon-indent-right:before {\n  content: \"\\e058\";\n}\n\n.glyphicon-facetime-video:before {\n  content: \"\\e059\";\n}\n\n.glyphicon-picture:before {\n  content: \"\\e060\";\n}\n\n.glyphicon-map-marker:before {\n  content: \"\\e062\";\n}\n\n.glyphicon-adjust:before {\n  content: \"\\e063\";\n}\n\n.glyphicon-tint:before {\n  content: \"\\e064\";\n}\n\n.glyphicon-edit:before {\n  content: \"\\e065\";\n}\n\n.glyphicon-share:before {\n  content: \"\\e066\";\n}\n\n.glyphicon-check:before {\n  content: \"\\e067\";\n}\n\n.glyphicon-move:before {\n  content: \"\\e068\";\n}\n\n.glyphicon-step-backward:before {\n  content: \"\\e069\";\n}\n\n.glyphicon-fast-backward:before {\n  content: \"\\e070\";\n}\n\n.glyphicon-backward:before {\n  content: \"\\e071\";\n}\n\n.glyphicon-play:before {\n  content: \"\\e072\";\n}\n\n.glyphicon-pause:before {\n  content: \"\\e073\";\n}\n\n.glyphicon-stop:before {\n  content: \"\\e074\";\n}\n\n.glyphicon-forward:before {\n  content: \"\\e075\";\n}\n\n.glyphicon-fast-forward:before {\n  content: \"\\e076\";\n}\n\n.glyphicon-step-forward:before {\n  content: \"\\e077\";\n}\n\n.glyphicon-eject:before {\n  content: \"\\e078\";\n}\n\n.glyphicon-chevron-left:before {\n  content: \"\\e079\";\n}\n\n.glyphicon-chevron-right:before {\n  content: \"\\e080\";\n}\n\n.glyphicon-plus-sign:before {\n  content: \"\\e081\";\n}\n\n.glyphicon-minus-sign:before {\n  content: \"\\e082\";\n}\n\n.glyphicon-remove-sign:before {\n  content: \"\\e083\";\n}\n\n.glyphicon-ok-sign:before {\n  content: \"\\e084\";\n}\n\n.glyphicon-question-sign:before {\n  content: \"\\e085\";\n}\n\n.glyphicon-info-sign:before {\n  content: \"\\e086\";\n}\n\n.glyphicon-screenshot:before {\n  content: \"\\e087\";\n}\n\n.glyphicon-remove-circle:before {\n  content: \"\\e088\";\n}\n\n.glyphicon-ok-circle:before {\n  content: \"\\e089\";\n}\n\n.glyphicon-ban-circle:before {\n  content: \"\\e090\";\n}\n\n.glyphicon-arrow-left:before {\n  content: \"\\e091\";\n}\n\n.glyphicon-arrow-right:before {\n  content: \"\\e092\";\n}\n\n.glyphicon-arrow-up:before {\n  content: \"\\e093\";\n}\n\n.glyphicon-arrow-down:before {\n  content: \"\\e094\";\n}\n\n.glyphicon-share-alt:before {\n  content: \"\\e095\";\n}\n\n.glyphicon-resize-full:before {\n  content: \"\\e096\";\n}\n\n.glyphicon-resize-small:before {\n  content: \"\\e097\";\n}\n\n.glyphicon-exclamation-sign:before {\n  content: \"\\e101\";\n}\n\n.glyphicon-gift:before {\n  content: \"\\e102\";\n}\n\n.glyphicon-leaf:before {\n  content: \"\\e103\";\n}\n\n.glyphicon-fire:before {\n  content: \"\\e104\";\n}\n\n.glyphicon-eye-open:before {\n  content: \"\\e105\";\n}\n\n.glyphicon-eye-close:before {\n  content: \"\\e106\";\n}\n\n.glyphicon-warning-sign:before {\n  content: \"\\e107\";\n}\n\n.glyphicon-plane:before {\n  content: \"\\e108\";\n}\n\n.glyphicon-calendar:before {\n  content: \"\\e109\";\n}\n\n.glyphicon-random:before {\n  content: \"\\e110\";\n}\n\n.glyphicon-comment:before {\n  content: \"\\e111\";\n}\n\n.glyphicon-magnet:before {\n  content: \"\\e112\";\n}\n\n.glyphicon-chevron-up:before {\n  content: \"\\e113\";\n}\n\n.glyphicon-chevron-down:before {\n  content: \"\\e114\";\n}\n\n.glyphicon-retweet:before {\n  content: \"\\e115\";\n}\n\n.glyphicon-shopping-cart:before {\n  content: \"\\e116\";\n}\n\n.glyphicon-folder-close:before {\n  content: \"\\e117\";\n}\n\n.glyphicon-folder-open:before {\n  content: \"\\e118\";\n}\n\n.glyphicon-resize-vertical:before {\n  content: \"\\e119\";\n}\n\n.glyphicon-resize-horizontal:before {\n  content: \"\\e120\";\n}\n\n.glyphicon-hdd:before {\n  content: \"\\e121\";\n}\n\n.glyphicon-bullhorn:before {\n  content: \"\\e122\";\n}\n\n.glyphicon-bell:before {\n  content: \"\\e123\";\n}\n\n.glyphicon-certificate:before {\n  content: \"\\e124\";\n}\n\n.glyphicon-thumbs-up:before {\n  content: \"\\e125\";\n}\n\n.glyphicon-thumbs-down:before {\n  content: \"\\e126\";\n}\n\n.glyphicon-hand-right:before {\n  content: \"\\e127\";\n}\n\n.glyphicon-hand-left:before {\n  content: \"\\e128\";\n}\n\n.glyphicon-hand-up:before {\n  content: \"\\e129\";\n}\n\n.glyphicon-hand-down:before {\n  content: \"\\e130\";\n}\n\n.glyphicon-circle-arrow-right:before {\n  content: \"\\e131\";\n}\n\n.glyphicon-circle-arrow-left:before {\n  content: \"\\e132\";\n}\n\n.glyphicon-circle-arrow-up:before {\n  content: \"\\e133\";\n}\n\n.glyphicon-circle-arrow-down:before {\n  content: \"\\e134\";\n}\n\n.glyphicon-globe:before {\n  content: \"\\e135\";\n}\n\n.glyphicon-wrench:before {\n  content: \"\\e136\";\n}\n\n.glyphicon-tasks:before {\n  content: \"\\e137\";\n}\n\n.glyphicon-filter:before {\n  content: \"\\e138\";\n}\n\n.glyphicon-briefcase:before {\n  content: \"\\e139\";\n}\n\n.glyphicon-fullscreen:before {\n  content: \"\\e140\";\n}\n\n.glyphicon-dashboard:before {\n  content: \"\\e141\";\n}\n\n.glyphicon-paperclip:before {\n  content: \"\\e142\";\n}\n\n.glyphicon-heart-empty:before {\n  content: \"\\e143\";\n}\n\n.glyphicon-link:before {\n  content: \"\\e144\";\n}\n\n.glyphicon-phone:before {\n  content: \"\\e145\";\n}\n\n.glyphicon-pushpin:before {\n  content: \"\\e146\";\n}\n\n.glyphicon-usd:before {\n  content: \"\\e148\";\n}\n\n.glyphicon-gbp:before {\n  content: \"\\e149\";\n}\n\n.glyphicon-sort:before {\n  content: \"\\e150\";\n}\n\n.glyphicon-sort-by-alphabet:before {\n  content: \"\\e151\";\n}\n\n.glyphicon-sort-by-alphabet-alt:before {\n  content: \"\\e152\";\n}\n\n.glyphicon-sort-by-order:before {\n  content: \"\\e153\";\n}\n\n.glyphicon-sort-by-order-alt:before {\n  content: \"\\e154\";\n}\n\n.glyphicon-sort-by-attributes:before {\n  content: \"\\e155\";\n}\n\n.glyphicon-sort-by-attributes-alt:before {\n  content: \"\\e156\";\n}\n\n.glyphicon-unchecked:before {\n  content: \"\\e157\";\n}\n\n.glyphicon-expand:before {\n  content: \"\\e158\";\n}\n\n.glyphicon-collapse-down:before {\n  content: \"\\e159\";\n}\n\n.glyphicon-collapse-up:before {\n  content: \"\\e160\";\n}\n\n.glyphicon-log-in:before {\n  content: \"\\e161\";\n}\n\n.glyphicon-flash:before {\n  content: \"\\e162\";\n}\n\n.glyphicon-log-out:before {\n  content: \"\\e163\";\n}\n\n.glyphicon-new-window:before {\n  content: \"\\e164\";\n}\n\n.glyphicon-record:before {\n  content: \"\\e165\";\n}\n\n.glyphicon-save:before {\n  content: \"\\e166\";\n}\n\n.glyphicon-open:before {\n  content: \"\\e167\";\n}\n\n.glyphicon-saved:before {\n  content: \"\\e168\";\n}\n\n.glyphicon-import:before {\n  content: \"\\e169\";\n}\n\n.glyphicon-export:before {\n  content: \"\\e170\";\n}\n\n.glyphicon-send:before {\n  content: \"\\e171\";\n}\n\n.glyphicon-floppy-disk:before {\n  content: \"\\e172\";\n}\n\n.glyphicon-floppy-saved:before {\n  content: \"\\e173\";\n}\n\n.glyphicon-floppy-remove:before {\n  content: \"\\e174\";\n}\n\n.glyphicon-floppy-save:before {\n  content: \"\\e175\";\n}\n\n.glyphicon-floppy-open:before {\n  content: \"\\e176\";\n}\n\n.glyphicon-credit-card:before {\n  content: \"\\e177\";\n}\n\n.glyphicon-transfer:before {\n  content: \"\\e178\";\n}\n\n.glyphicon-cutlery:before {\n  content: \"\\e179\";\n}\n\n.glyphicon-header:before {\n  content: \"\\e180\";\n}\n\n.glyphicon-compressed:before {\n  content: \"\\e181\";\n}\n\n.glyphicon-earphone:before {\n  content: \"\\e182\";\n}\n\n.glyphicon-phone-alt:before {\n  content: \"\\e183\";\n}\n\n.glyphicon-tower:before {\n  content: \"\\e184\";\n}\n\n.glyphicon-stats:before {\n  content: \"\\e185\";\n}\n\n.glyphicon-sd-video:before {\n  content: \"\\e186\";\n}\n\n.glyphicon-hd-video:before {\n  content: \"\\e187\";\n}\n\n.glyphicon-subtitles:before {\n  content: \"\\e188\";\n}\n\n.glyphicon-sound-stereo:before {\n  content: \"\\e189\";\n}\n\n.glyphicon-sound-dolby:before {\n  content: \"\\e190\";\n}\n\n.glyphicon-sound-5-1:before {\n  content: \"\\e191\";\n}\n\n.glyphicon-sound-6-1:before {\n  content: \"\\e192\";\n}\n\n.glyphicon-sound-7-1:before {\n  content: \"\\e193\";\n}\n\n.glyphicon-copyright-mark:before {\n  content: \"\\e194\";\n}\n\n.glyphicon-registration-mark:before {\n  content: \"\\e195\";\n}\n\n.glyphicon-cloud-download:before {\n  content: \"\\e197\";\n}\n\n.glyphicon-cloud-upload:before {\n  content: \"\\e198\";\n}\n\n.glyphicon-tree-conifer:before {\n  content: \"\\e199\";\n}\n\n.glyphicon-tree-deciduous:before {\n  content: \"\\e200\";\n}\n\n.caret {\n  display: inline-block;\n  width: 0;\n  height: 0;\n  margin-left: 2px;\n  vertical-align: middle;\n  border-top: 4px solid #000000;\n  border-right: 4px solid transparent;\n  border-bottom: 0 dotted;\n  border-left: 4px solid transparent;\n}\n\n.dropdown {\n  position: relative;\n}\n\n.dropdown-toggle:focus {\n  outline: 0;\n}\n\n.dropdown-menu {\n  position: absolute;\n  top: 100%;\n  left: 0;\n  z-index: 1000;\n  display: none;\n  float: left;\n  min-width: 160px;\n  padding: 5px 0;\n  margin: 2px 0 0;\n  font-size: 14px;\n  list-style: none;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.15);\n  border-radius: 4px;\n  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n          box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n  background-clip: padding-box;\n}\n\n.dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.dropdown-menu .divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.dropdown-menu > li > a {\n  display: block;\n  padding: 3px 20px;\n  clear: both;\n  font-weight: normal;\n  line-height: 1.428571429;\n  color: #333333;\n  white-space: nowrap;\n}\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n  color: #262626;\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n  color: #ffffff;\n  text-decoration: none;\n  background-color: #428bca;\n  outline: 0;\n}\n\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  color: #999999;\n}\n\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n  background-image: none;\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n}\n\n.open > .dropdown-menu {\n  display: block;\n}\n\n.open > a {\n  outline: 0;\n}\n\n.dropdown-header {\n  display: block;\n  padding: 3px 20px;\n  font-size: 12px;\n  line-height: 1.428571429;\n  color: #999999;\n}\n\n.dropdown-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 990;\n}\n\n.pull-right > .dropdown-menu {\n  right: 0;\n  left: auto;\n}\n\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n  border-top: 0 dotted;\n  border-bottom: 4px solid #000000;\n  content: \"\";\n}\n\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n  top: auto;\n  bottom: 100%;\n  margin-bottom: 1px;\n}\n\n@media (min-width: 768px) {\n  .navbar-right .dropdown-menu {\n    right: 0;\n    left: auto;\n  }\n}\n\n.btn-default .caret {\n  border-top-color: #333333;\n}\n\n.btn-primary .caret,\n.btn-success .caret,\n.btn-warning .caret,\n.btn-danger .caret,\n.btn-info .caret {\n  border-top-color: #fff;\n}\n\n.dropup .btn-default .caret {\n  border-bottom-color: #333333;\n}\n\n.dropup .btn-primary .caret,\n.dropup .btn-success .caret,\n.dropup .btn-warning .caret,\n.dropup .btn-danger .caret,\n.dropup .btn-info .caret {\n  border-bottom-color: #fff;\n}\n\n.btn-group,\n.btn-group-vertical {\n  position: relative;\n  display: inline-block;\n  vertical-align: middle;\n}\n\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n  position: relative;\n  float: left;\n}\n\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n  z-index: 2;\n}\n\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus {\n  outline: none;\n}\n\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n  margin-left: -1px;\n}\n\n.btn-toolbar:before,\n.btn-toolbar:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-toolbar:after {\n  clear: both;\n}\n\n.btn-toolbar:before,\n.btn-toolbar:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-toolbar:after {\n  clear: both;\n}\n\n.btn-toolbar .btn-group {\n  float: left;\n}\n\n.btn-toolbar > .btn + .btn,\n.btn-toolbar > .btn-group + .btn,\n.btn-toolbar > .btn + .btn-group,\n.btn-toolbar > .btn-group + .btn-group {\n  margin-left: 5px;\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n  border-radius: 0;\n}\n\n.btn-group > .btn:first-child {\n  margin-left: 0;\n}\n\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group > .btn-group {\n  float: left;\n}\n\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n\n.btn-group > .btn-group:first-child > .btn:last-child,\n.btn-group > .btn-group:first-child > .dropdown-toggle {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.btn-group > .btn-group:last-child > .btn:first-child {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n  outline: 0;\n}\n\n.btn-group-xs > .btn {\n  padding: 5px 10px;\n  padding: 1px 5px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-group-sm > .btn {\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\n.btn-group-lg > .btn {\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\n.btn-group > .btn + .dropdown-toggle {\n  padding-right: 8px;\n  padding-left: 8px;\n}\n\n.btn-group > .btn-lg + .dropdown-toggle {\n  padding-right: 12px;\n  padding-left: 12px;\n}\n\n.btn-group.open .dropdown-toggle {\n  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n          box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n\n.btn-group.open .dropdown-toggle.btn-link {\n  -webkit-box-shadow: none;\n          box-shadow: none;\n}\n\n.btn .caret {\n  margin-left: 0;\n}\n\n.btn-lg .caret {\n  border-width: 5px 5px 0;\n  border-bottom-width: 0;\n}\n\n.dropup .btn-lg .caret {\n  border-width: 0 5px 5px;\n}\n\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group {\n  display: block;\n  float: none;\n  width: 100%;\n  max-width: 100%;\n}\n\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after {\n  display: table;\n  content: \" \";\n}\n\n.btn-group-vertical > .btn-group:after {\n  clear: both;\n}\n\n.btn-group-vertical > .btn-group > .btn {\n  float: none;\n}\n\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n  margin-top: -1px;\n  margin-left: 0;\n}\n\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n  border-top-right-radius: 4px;\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n  border-top-right-radius: 0;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n  border-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:first-child > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child > .dropdown-toggle {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.btn-group-vertical > .btn-group:last-child > .btn:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.btn-group-justified {\n  display: table;\n  width: 100%;\n  border-collapse: separate;\n  table-layout: fixed;\n}\n\n.btn-group-justified .btn {\n  display: table-cell;\n  float: none;\n  width: 1%;\n}\n\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n  display: none;\n}\n\n.input-group {\n  position: relative;\n  display: table;\n  border-collapse: separate;\n}\n\n.input-group.col {\n  float: none;\n  padding-right: 0;\n  padding-left: 0;\n}\n\n.input-group .form-control {\n  width: 100%;\n  margin-bottom: 0;\n}\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n  height: 45px;\n  padding: 10px 16px;\n  font-size: 18px;\n  line-height: 1.33;\n  border-radius: 6px;\n}\n\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n  height: 45px;\n  line-height: 45px;\n}\n\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn {\n  height: auto;\n}\n\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n  height: 30px;\n  padding: 5px 10px;\n  font-size: 12px;\n  line-height: 1.5;\n  border-radius: 3px;\n}\n\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n  height: 30px;\n  line-height: 30px;\n}\n\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn {\n  height: auto;\n}\n\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n  display: table-cell;\n}\n\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n  border-radius: 0;\n}\n\n.input-group-addon,\n.input-group-btn {\n  width: 1%;\n  white-space: nowrap;\n  vertical-align: middle;\n}\n\n.input-group-addon {\n  padding: 6px 12px;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 1;\n  color: #555555;\n  text-align: center;\n  background-color: #eeeeee;\n  border: 1px solid #cccccc;\n  border-radius: 4px;\n}\n\n.input-group-addon.input-sm {\n  padding: 5px 10px;\n  font-size: 12px;\n  border-radius: 3px;\n}\n\n.input-group-addon.input-lg {\n  padding: 10px 16px;\n  font-size: 18px;\n  border-radius: 6px;\n}\n\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n  margin-top: 0;\n}\n\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle) {\n  border-top-right-radius: 0;\n  border-bottom-right-radius: 0;\n}\n\n.input-group-addon:first-child {\n  border-right: 0;\n}\n\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child) {\n  border-bottom-left-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.input-group-addon:last-child {\n  border-left: 0;\n}\n\n.input-group-btn {\n  position: relative;\n  white-space: nowrap;\n}\n\n.input-group-btn:first-child > .btn {\n  margin-right: -1px;\n}\n\n.input-group-btn:last-child > .btn {\n  margin-left: -1px;\n}\n\n.input-group-btn > .btn {\n  position: relative;\n}\n\n.input-group-btn > .btn + .btn {\n  margin-left: -4px;\n}\n\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:active {\n  z-index: 2;\n}\n\n.nav {\n  padding-left: 0;\n  margin-bottom: 0;\n  list-style: none;\n}\n\n.nav:before,\n.nav:after {\n  display: table;\n  content: \" \";\n}\n\n.nav:after {\n  clear: both;\n}\n\n.nav:before,\n.nav:after {\n  display: table;\n  content: \" \";\n}\n\n.nav:after {\n  clear: both;\n}\n\n.nav > li {\n  position: relative;\n  display: block;\n}\n\n.nav > li > a {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n}\n\n.nav > li > a:hover,\n.nav > li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.nav > li.disabled > a {\n  color: #999999;\n}\n\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n  color: #999999;\n  text-decoration: none;\n  cursor: not-allowed;\n  background-color: transparent;\n}\n\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n  background-color: #eeeeee;\n  border-color: #428bca;\n}\n\n.nav .open > a .caret,\n.nav .open > a:hover .caret,\n.nav .open > a:focus .caret {\n  border-top-color: #2a6496;\n  border-bottom-color: #2a6496;\n}\n\n.nav .nav-divider {\n  height: 1px;\n  margin: 9px 0;\n  overflow: hidden;\n  background-color: #e5e5e5;\n}\n\n.nav > li > a > img {\n  max-width: none;\n}\n\n.nav-tabs {\n  border-bottom: 1px solid #dddddd;\n}\n\n.nav-tabs > li {\n  float: left;\n  margin-bottom: -1px;\n}\n\n.nav-tabs > li > a {\n  margin-right: 2px;\n  line-height: 1.428571429;\n  border: 1px solid transparent;\n  border-radius: 4px 4px 0 0;\n}\n\n.nav-tabs > li > a:hover {\n  border-color: #eeeeee #eeeeee #dddddd;\n}\n\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n  color: #555555;\n  cursor: default;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-bottom-color: transparent;\n}\n\n.nav-tabs.nav-justified {\n  width: 100%;\n  border-bottom: 0;\n}\n\n.nav-tabs.nav-justified > li {\n  float: none;\n}\n\n.nav-tabs.nav-justified > li > a {\n  margin-bottom: 5px;\n  text-align: center;\n}\n\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\n}\n\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .nav-tabs.nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n\n.nav-tabs.nav-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n  border: 1px solid #dddddd;\n}\n\n@media (min-width: 768px) {\n  .nav-tabs.nav-justified > li > a {\n    border-bottom: 1px solid #dddddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .nav-tabs.nav-justified > .active > a,\n  .nav-tabs.nav-justified > .active > a:hover,\n  .nav-tabs.nav-justified > .active > a:focus {\n    border-bottom-color: #ffffff;\n  }\n}\n\n.nav-pills > li {\n  float: left;\n}\n\n.nav-pills > li > a {\n  border-radius: 4px;\n}\n\n.nav-pills > li + li {\n  margin-left: 2px;\n}\n\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n  color: #ffffff;\n  background-color: #428bca;\n}\n\n.nav-pills > li.active > a .caret,\n.nav-pills > li.active > a:hover .caret,\n.nav-pills > li.active > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.nav-stacked > li {\n  float: none;\n}\n\n.nav-stacked > li + li {\n  margin-top: 2px;\n  margin-left: 0;\n}\n\n.nav-justified {\n  width: 100%;\n}\n\n.nav-justified > li {\n  float: none;\n}\n\n.nav-justified > li > a {\n  margin-bottom: 5px;\n  text-align: center;\n}\n\n.nav-justified > .dropdown .dropdown-menu {\n  top: auto;\n  left: auto;\n}\n\n@media (min-width: 768px) {\n  .nav-justified > li {\n    display: table-cell;\n    width: 1%;\n  }\n  .nav-justified > li > a {\n    margin-bottom: 0;\n  }\n}\n\n.nav-tabs-justified {\n  border-bottom: 0;\n}\n\n.nav-tabs-justified > li > a {\n  margin-right: 0;\n  border-radius: 4px;\n}\n\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n  border: 1px solid #dddddd;\n}\n\n@media (min-width: 768px) {\n  .nav-tabs-justified > li > a {\n    border-bottom: 1px solid #dddddd;\n    border-radius: 4px 4px 0 0;\n  }\n  .nav-tabs-justified > .active > a,\n  .nav-tabs-justified > .active > a:hover,\n  .nav-tabs-justified > .active > a:focus {\n    border-bottom-color: #ffffff;\n  }\n}\n\n.tab-content > .tab-pane {\n  display: none;\n}\n\n.tab-content > .active {\n  display: block;\n}\n\n.nav .caret {\n  border-top-color: #428bca;\n  border-bottom-color: #428bca;\n}\n\n.nav a:hover .caret {\n  border-top-color: #2a6496;\n  border-bottom-color: #2a6496;\n}\n\n.nav-tabs .dropdown-menu {\n  margin-top: -1px;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar {\n  position: relative;\n  min-height: 50px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n}\n\n.navbar:before,\n.navbar:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar:after {\n  clear: both;\n}\n\n.navbar:before,\n.navbar:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .navbar {\n    border-radius: 4px;\n  }\n}\n\n.navbar-header:before,\n.navbar-header:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-header:after {\n  clear: both;\n}\n\n.navbar-header:before,\n.navbar-header:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-header:after {\n  clear: both;\n}\n\n@media (min-width: 768px) {\n  .navbar-header {\n    float: left;\n  }\n}\n\n.navbar-collapse {\n  max-height: 340px;\n  padding-right: 15px;\n  padding-left: 15px;\n  overflow-x: visible;\n  border-top: 1px solid transparent;\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n  -webkit-overflow-scrolling: touch;\n}\n\n.navbar-collapse:before,\n.navbar-collapse:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-collapse:after {\n  clear: both;\n}\n\n.navbar-collapse:before,\n.navbar-collapse:after {\n  display: table;\n  content: \" \";\n}\n\n.navbar-collapse:after {\n  clear: both;\n}\n\n.navbar-collapse.in {\n  overflow-y: auto;\n}\n\n@media (min-width: 768px) {\n  .navbar-collapse {\n    width: auto;\n    border-top: 0;\n    box-shadow: none;\n  }\n  .navbar-collapse.collapse {\n    display: block !important;\n    height: auto !important;\n    padding-bottom: 0;\n    overflow: visible !important;\n  }\n  .navbar-collapse.in {\n    overflow-y: auto;\n  }\n  .navbar-collapse .navbar-nav.navbar-left:first-child {\n    margin-left: -15px;\n  }\n  .navbar-collapse .navbar-nav.navbar-right:last-child {\n    margin-right: -15px;\n  }\n  .navbar-collapse .navbar-text:last-child {\n    margin-right: 0;\n  }\n}\n\n.container > .navbar-header,\n.container > .navbar-collapse {\n  margin-right: -15px;\n  margin-left: -15px;\n}\n\n@media (min-width: 768px) {\n  .container > .navbar-header,\n  .container > .navbar-collapse {\n    margin-right: 0;\n    margin-left: 0;\n  }\n}\n\n.navbar-static-top {\n  z-index: 1000;\n  border-width: 0 0 1px;\n}\n\n@media (min-width: 768px) {\n  .navbar-static-top {\n    border-radius: 0;\n  }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n  position: fixed;\n  right: 0;\n  left: 0;\n  z-index: 1030;\n}\n\n@media (min-width: 768px) {\n  .navbar-fixed-top,\n  .navbar-fixed-bottom {\n    border-radius: 0;\n  }\n}\n\n.navbar-fixed-top {\n  top: 0;\n  border-width: 0 0 1px;\n}\n\n.navbar-fixed-bottom {\n  bottom: 0;\n  margin-bottom: 0;\n  border-width: 1px 0 0;\n}\n\n.navbar-brand {\n  float: left;\n  padding: 15px 15px;\n  font-size: 18px;\n  line-height: 20px;\n}\n\n.navbar-brand:hover,\n.navbar-brand:focus {\n  text-decoration: none;\n}\n\n@media (min-width: 768px) {\n  .navbar > .container .navbar-brand {\n    margin-left: -15px;\n  }\n}\n\n.navbar-toggle {\n  position: relative;\n  float: right;\n  padding: 9px 10px;\n  margin-top: 8px;\n  margin-right: 15px;\n  margin-bottom: 8px;\n  background-color: transparent;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n\n.navbar-toggle .icon-bar {\n  display: block;\n  width: 22px;\n  height: 2px;\n  border-radius: 1px;\n}\n\n.navbar-toggle .icon-bar + .icon-bar {\n  margin-top: 4px;\n}\n\n@media (min-width: 768px) {\n  .navbar-toggle {\n    display: none;\n  }\n}\n\n.navbar-nav {\n  margin: 7.5px -15px;\n}\n\n.navbar-nav > li > a {\n  padding-top: 10px;\n  padding-bottom: 10px;\n  line-height: 20px;\n}\n\n@media (max-width: 767px) {\n  .navbar-nav .open .dropdown-menu {\n    position: static;\n    float: none;\n    width: auto;\n    margin-top: 0;\n    background-color: transparent;\n    border: 0;\n    box-shadow: none;\n  }\n  .navbar-nav .open .dropdown-menu > li > a,\n  .navbar-nav .open .dropdown-menu .dropdown-header {\n    padding: 5px 15px 5px 25px;\n  }\n  .navbar-nav .open .dropdown-menu > li > a {\n    line-height: 20px;\n  }\n  .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-nav .open .dropdown-menu > li > a:focus {\n    background-image: none;\n  }\n}\n\n@media (min-width: 768px) {\n  .navbar-nav {\n    float: left;\n    margin: 0;\n  }\n  .navbar-nav > li {\n    float: left;\n  }\n  .navbar-nav > li > a {\n    padding-top: 15px;\n    padding-bottom: 15px;\n  }\n}\n\n@media (min-width: 768px) {\n  .navbar-left {\n    float: left !important;\n  }\n  .navbar-right {\n    float: right !important;\n  }\n}\n\n.navbar-form {\n  padding: 10px 15px;\n  margin-top: 8px;\n  margin-right: -15px;\n  margin-bottom: 8px;\n  margin-left: -15px;\n  border-top: 1px solid transparent;\n  border-bottom: 1px solid transparent;\n  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n          box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n\n@media (min-width: 768px) {\n  .navbar-form .form-group {\n    display: inline-block;\n    margin-bottom: 0;\n    vertical-align: middle;\n  }\n  .navbar-form .form-control {\n    display: inline-block;\n  }\n  .navbar-form .radio,\n  .navbar-form .checkbox {\n    display: inline-block;\n    padding-left: 0;\n    margin-top: 0;\n    margin-bottom: 0;\n  }\n  .navbar-form .radio input[type=\"radio\"],\n  .navbar-form .checkbox input[type=\"checkbox\"] {\n    float: none;\n    margin-left: 0;\n  }\n}\n\n@media (max-width: 767px) {\n  .navbar-form .form-group {\n    margin-bottom: 5px;\n  }\n}\n\n@media (min-width: 768px) {\n  .navbar-form {\n    width: auto;\n    padding-top: 0;\n    padding-bottom: 0;\n    margin-right: 0;\n    margin-left: 0;\n    border: 0;\n    -webkit-box-shadow: none;\n            box-shadow: none;\n  }\n}\n\n.navbar-nav > li > .dropdown-menu {\n  margin-top: 0;\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n  border-bottom-right-radius: 0;\n  border-bottom-left-radius: 0;\n}\n\n.navbar-nav.pull-right > li > .dropdown-menu,\n.navbar-nav > li > .dropdown-menu.pull-right {\n  right: 0;\n  left: auto;\n}\n\n.navbar-btn {\n  margin-top: 8px;\n  margin-bottom: 8px;\n}\n\n.navbar-text {\n  float: left;\n  margin-top: 15px;\n  margin-bottom: 15px;\n}\n\n@media (min-width: 768px) {\n  .navbar-text {\n    margin-right: 15px;\n    margin-left: 15px;\n  }\n}\n\n.navbar-default {\n  background-color: #f8f8f8;\n  border-color: #e7e7e7;\n}\n\n.navbar-default .navbar-brand {\n  color: #777777;\n}\n\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n  color: #5e5e5e;\n  background-color: transparent;\n}\n\n.navbar-default .navbar-text {\n  color: #777777;\n}\n\n.navbar-default .navbar-nav > li > a {\n  color: #777777;\n}\n\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n  color: #333333;\n  background-color: transparent;\n}\n\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n  color: #555555;\n  background-color: #e7e7e7;\n}\n\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n  color: #cccccc;\n  background-color: transparent;\n}\n\n.navbar-default .navbar-toggle {\n  border-color: #dddddd;\n}\n\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n  background-color: #dddddd;\n}\n\n.navbar-default .navbar-toggle .icon-bar {\n  background-color: #cccccc;\n}\n\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n  border-color: #e7e7e7;\n}\n\n.navbar-default .navbar-nav > .dropdown > a:hover .caret,\n.navbar-default .navbar-nav > .dropdown > a:focus .caret {\n  border-top-color: #333333;\n  border-bottom-color: #333333;\n}\n\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n  color: #555555;\n  background-color: #e7e7e7;\n}\n\n.navbar-default .navbar-nav > .open > a .caret,\n.navbar-default .navbar-nav > .open > a:hover .caret,\n.navbar-default .navbar-nav > .open > a:focus .caret {\n  border-top-color: #555555;\n  border-bottom-color: #555555;\n}\n\n.navbar-default .navbar-nav > .dropdown > a .caret {\n  border-top-color: #777777;\n  border-bottom-color: #777777;\n}\n\n@media (max-width: 767px) {\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n    color: #777777;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #333333;\n    background-color: transparent;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #555555;\n    background-color: #e7e7e7;\n  }\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #cccccc;\n    background-color: transparent;\n  }\n}\n\n.navbar-default .navbar-link {\n  color: #777777;\n}\n\n.navbar-default .navbar-link:hover {\n  color: #333333;\n}\n\n.navbar-inverse {\n  background-color: #222222;\n  border-color: #080808;\n}\n\n.navbar-inverse .navbar-brand {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-text {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-nav > li > a {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n  color: #ffffff;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n  color: #ffffff;\n  background-color: #080808;\n}\n\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n  color: #444444;\n  background-color: transparent;\n}\n\n.navbar-inverse .navbar-toggle {\n  border-color: #333333;\n}\n\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n  background-color: #333333;\n}\n\n.navbar-inverse .navbar-toggle .icon-bar {\n  background-color: #ffffff;\n}\n\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n  border-color: #101010;\n}\n\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n  color: #ffffff;\n  background-color: #080808;\n}\n\n.navbar-inverse .navbar-nav > .dropdown > a:hover .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n.navbar-inverse .navbar-nav > .dropdown > a .caret {\n  border-top-color: #999999;\n  border-bottom-color: #999999;\n}\n\n.navbar-inverse .navbar-nav > .open > a .caret,\n.navbar-inverse .navbar-nav > .open > a:hover .caret,\n.navbar-inverse .navbar-nav > .open > a:focus .caret {\n  border-top-color: #ffffff;\n  border-bottom-color: #ffffff;\n}\n\n@media (max-width: 767px) {\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n    border-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n    color: #999999;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n    color: #ffffff;\n    background-color: transparent;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n    color: #ffffff;\n    background-color: #080808;\n  }\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n  .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n    color: #444444;\n    background-color: transparent;\n  }\n}\n\n.navbar-inverse .navbar-link {\n  color: #999999;\n}\n\n.navbar-inverse .navbar-link:hover {\n  color: #ffffff;\n}\n\n.breadcrumb {\n  padding: 8px 15px;\n  margin-bottom: 20px;\n  list-style: none;\n  background-color: #f5f5f5;\n  border-radius: 4px;\n}\n\n.breadcrumb > li {\n  display: inline-block;\n}\n\n.breadcrumb > li + li:before {\n  padding: 0 5px;\n  color: #cccccc;\n  content: \"/\\00a0\";\n}\n\n.breadcrumb > .active {\n  color: #999999;\n}\n\n.pagination {\n  display: inline-block;\n  padding-left: 0;\n  margin: 20px 0;\n  border-radius: 4px;\n}\n\n.pagination > li {\n  display: inline;\n}\n\n.pagination > li > a,\n.pagination > li > span {\n  position: relative;\n  float: left;\n  padding: 6px 12px;\n  margin-left: -1px;\n  line-height: 1.428571429;\n  text-decoration: none;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n}\n\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n  margin-left: 0;\n  border-bottom-left-radius: 4px;\n  border-top-left-radius: 4px;\n}\n\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n  border-top-right-radius: 4px;\n  border-bottom-right-radius: 4px;\n}\n\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n  background-color: #eeeeee;\n}\n\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n  z-index: 2;\n  color: #ffffff;\n  cursor: default;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #ffffff;\n  border-color: #dddddd;\n}\n\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n  padding: 10px 16px;\n  font-size: 18px;\n}\n\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n  border-bottom-left-radius: 6px;\n  border-top-left-radius: 6px;\n}\n\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n  border-top-right-radius: 6px;\n  border-bottom-right-radius: 6px;\n}\n\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n  padding: 5px 10px;\n  font-size: 12px;\n}\n\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n  border-bottom-left-radius: 3px;\n  border-top-left-radius: 3px;\n}\n\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n  border-top-right-radius: 3px;\n  border-bottom-right-radius: 3px;\n}\n\n.pager {\n  padding-left: 0;\n  margin: 20px 0;\n  text-align: center;\n  list-style: none;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  content: \" \";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager:before,\n.pager:after {\n  display: table;\n  content: \" \";\n}\n\n.pager:after {\n  clear: both;\n}\n\n.pager li {\n  display: inline;\n}\n\n.pager li > a,\n.pager li > span {\n  display: inline-block;\n  padding: 5px 14px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 15px;\n}\n\n.pager li > a:hover,\n.pager li > a:focus {\n  text-decoration: none;\n  background-color: #eeeeee;\n}\n\n.pager .next > a,\n.pager .next > span {\n  float: right;\n}\n\n.pager .previous > a,\n.pager .previous > span {\n  float: left;\n}\n\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n  color: #999999;\n  cursor: not-allowed;\n  background-color: #ffffff;\n}\n\n.label {\n  display: inline;\n  padding: .2em .6em .3em;\n  font-size: 75%;\n  font-weight: bold;\n  line-height: 1;\n  color: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  border-radius: .25em;\n}\n\n.label[href]:hover,\n.label[href]:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.label:empty {\n  display: none;\n}\n\n.label-default {\n  background-color: #999999;\n}\n\n.label-default[href]:hover,\n.label-default[href]:focus {\n  background-color: #808080;\n}\n\n.label-primary {\n  background-color: #428bca;\n}\n\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n  background-color: #3071a9;\n}\n\n.label-success {\n  background-color: #5cb85c;\n}\n\n.label-success[href]:hover,\n.label-success[href]:focus {\n  background-color: #449d44;\n}\n\n.label-info {\n  background-color: #5bc0de;\n}\n\n.label-info[href]:hover,\n.label-info[href]:focus {\n  background-color: #31b0d5;\n}\n\n.label-warning {\n  background-color: #f0ad4e;\n}\n\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n  background-color: #ec971f;\n}\n\n.label-danger {\n  background-color: #d9534f;\n}\n\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n  background-color: #c9302c;\n}\n\n.badge {\n  display: inline-block;\n  min-width: 10px;\n  padding: 3px 7px;\n  font-size: 12px;\n  font-weight: bold;\n  line-height: 1;\n  color: #ffffff;\n  text-align: center;\n  white-space: nowrap;\n  vertical-align: baseline;\n  background-color: #999999;\n  border-radius: 10px;\n}\n\n.badge:empty {\n  display: none;\n}\n\na.badge:hover,\na.badge:focus {\n  color: #ffffff;\n  text-decoration: none;\n  cursor: pointer;\n}\n\n.btn .badge {\n  position: relative;\n  top: -1px;\n}\n\na.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n  color: #428bca;\n  background-color: #ffffff;\n}\n\n.nav-pills > li > a > .badge {\n  margin-left: 3px;\n}\n\n.jumbotron {\n  padding: 30px;\n  margin-bottom: 30px;\n  font-size: 21px;\n  font-weight: 200;\n  line-height: 2.1428571435;\n  color: inherit;\n  background-color: #eeeeee;\n}\n\n.jumbotron h1 {\n  line-height: 1;\n  color: inherit;\n}\n\n.jumbotron p {\n  line-height: 1.4;\n}\n\n.container .jumbotron {\n  border-radius: 6px;\n}\n\n@media screen and (min-width: 768px) {\n  .jumbotron {\n    padding-top: 48px;\n    padding-bottom: 48px;\n  }\n  .container .jumbotron {\n    padding-right: 60px;\n    padding-left: 60px;\n  }\n  .jumbotron h1 {\n    font-size: 63px;\n  }\n}\n\n.thumbnail {\n  display: inline-block;\n  display: block;\n  height: auto;\n  max-width: 100%;\n  padding: 4px;\n  margin-bottom: 20px;\n  line-height: 1.428571429;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n  border-radius: 4px;\n  -webkit-transition: all 0.2s ease-in-out;\n          transition: all 0.2s ease-in-out;\n}\n\n.thumbnail > img {\n  display: block;\n  height: auto;\n  max-width: 100%;\n  margin-right: auto;\n  margin-left: auto;\n}\n\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n  border-color: #428bca;\n}\n\n.thumbnail .caption {\n  padding: 9px;\n  color: #333333;\n}\n\n.alert {\n  padding: 15px;\n  margin-bottom: 20px;\n  border: 1px solid transparent;\n  border-radius: 4px;\n}\n\n.alert h4 {\n  margin-top: 0;\n  color: inherit;\n}\n\n.alert .alert-link {\n  font-weight: bold;\n}\n\n.alert > p,\n.alert > ul {\n  margin-bottom: 0;\n}\n\n.alert > p + p {\n  margin-top: 5px;\n}\n\n.alert-dismissable {\n  padding-right: 35px;\n}\n\n.alert-dismissable .close {\n  position: relative;\n  top: -2px;\n  right: -21px;\n  color: inherit;\n}\n\n.alert-success {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.alert-success hr {\n  border-top-color: #c9e2b3;\n}\n\n.alert-success .alert-link {\n  color: #356635;\n}\n\n.alert-info {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.alert-info hr {\n  border-top-color: #a6e1ec;\n}\n\n.alert-info .alert-link {\n  color: #2d6987;\n}\n\n.alert-warning {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n\n.alert-warning hr {\n  border-top-color: #f7e1b5;\n}\n\n.alert-warning .alert-link {\n  color: #a47e3c;\n}\n\n.alert-danger {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n\n.alert-danger hr {\n  border-top-color: #e4b9c0;\n}\n\n.alert-danger .alert-link {\n  color: #953b39;\n}\n\n@-webkit-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-moz-keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n@-o-keyframes progress-bar-stripes {\n  from {\n    background-position: 0 0;\n  }\n  to {\n    background-position: 40px 0;\n  }\n}\n\n@keyframes progress-bar-stripes {\n  from {\n    background-position: 40px 0;\n  }\n  to {\n    background-position: 0 0;\n  }\n}\n\n.progress {\n  height: 20px;\n  margin-bottom: 20px;\n  overflow: hidden;\n  background-color: #f5f5f5;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n          box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n\n.progress-bar {\n  float: left;\n  width: 0;\n  height: 100%;\n  font-size: 12px;\n  line-height: 20px;\n  color: #ffffff;\n  text-align: center;\n  background-color: #428bca;\n  -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n  -webkit-transition: width 0.6s ease;\n          transition: width 0.6s ease;\n}\n\n.progress-striped .progress-bar {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-size: 40px 40px;\n}\n\n.progress.active .progress-bar {\n  -webkit-animation: progress-bar-stripes 2s linear infinite;\n          animation: progress-bar-stripes 2s linear infinite;\n}\n\n.progress-bar-success {\n  background-color: #5cb85c;\n}\n\n.progress-striped .progress-bar-success {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-info {\n  background-color: #5bc0de;\n}\n\n.progress-striped .progress-bar-info {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-warning {\n  background-color: #f0ad4e;\n}\n\n.progress-striped .progress-bar-warning {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.progress-bar-danger {\n  background-color: #d9534f;\n}\n\n.progress-striped .progress-bar-danger {\n  background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));\n  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n\n.media,\n.media-body {\n  overflow: hidden;\n  zoom: 1;\n}\n\n.media,\n.media .media {\n  margin-top: 15px;\n}\n\n.media:first-child {\n  margin-top: 0;\n}\n\n.media-object {\n  display: block;\n}\n\n.media-heading {\n  margin: 0 0 5px;\n}\n\n.media > .pull-left {\n  margin-right: 10px;\n}\n\n.media > .pull-right {\n  margin-left: 10px;\n}\n\n.media-list {\n  padding-left: 0;\n  list-style: none;\n}\n\n.list-group {\n  padding-left: 0;\n  margin-bottom: 20px;\n}\n\n.list-group-item {\n  position: relative;\n  display: block;\n  padding: 10px 15px;\n  margin-bottom: -1px;\n  background-color: #ffffff;\n  border: 1px solid #dddddd;\n}\n\n.list-group-item:first-child {\n  border-top-right-radius: 4px;\n  border-top-left-radius: 4px;\n}\n\n.list-group-item:last-child {\n  margin-bottom: 0;\n  border-bottom-right-radius: 4px;\n  border-bottom-left-radius: 4px;\n}\n\n.list-group-item > .badge {\n  float: right;\n}\n\n.list-group-item > .badge + .badge {\n  margin-right: 5px;\n}\n\na.list-group-item {\n  color: #555555;\n}\n\na.list-group-item .list-group-item-heading {\n  color: #333333;\n}\n\na.list-group-item:hover,\na.list-group-item:focus {\n  text-decoration: none;\n  background-color: #f5f5f5;\n}\n\na.list-group-item.active,\na.list-group-item.active:hover,\na.list-group-item.active:focus {\n  z-index: 2;\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\na.list-group-item.active .list-group-item-heading,\na.list-group-item.active:hover .list-group-item-heading,\na.list-group-item.active:focus .list-group-item-heading {\n  color: inherit;\n}\n\na.list-group-item.active .list-group-item-text,\na.list-group-item.active:hover .list-group-item-text,\na.list-group-item.active:focus .list-group-item-text {\n  color: #e1edf7;\n}\n\n.list-group-item-heading {\n  margin-top: 0;\n  margin-bottom: 5px;\n}\n\n.list-group-item-text {\n  margin-bottom: 0;\n  line-height: 1.3;\n}\n\n.panel {\n  margin-bottom: 20px;\n  background-color: #ffffff;\n  border: 1px solid transparent;\n  border-radius: 4px;\n  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.panel-body {\n  padding: 15px;\n}\n\n.panel-body:before,\n.panel-body:after {\n  display: table;\n  content: \" \";\n}\n\n.panel-body:after {\n  clear: both;\n}\n\n.panel-body:before,\n.panel-body:after {\n  display: table;\n  content: \" \";\n}\n\n.panel-body:after {\n  clear: both;\n}\n\n.panel > .list-group {\n  margin-bottom: 0;\n}\n\n.panel > .list-group .list-group-item {\n  border-width: 1px 0;\n}\n\n.panel > .list-group .list-group-item:first-child {\n  border-top-right-radius: 0;\n  border-top-left-radius: 0;\n}\n\n.panel > .list-group .list-group-item:last-child {\n  border-bottom: 0;\n}\n\n.panel-heading + .list-group .list-group-item:first-child {\n  border-top-width: 0;\n}\n\n.panel > .table,\n.panel > .table-responsive {\n  margin-bottom: 0;\n}\n\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive {\n  border-top: 1px solid #dddddd;\n}\n\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n  border: 0;\n}\n\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n  border-left: 0;\n}\n\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n  border-right: 0;\n}\n\n.panel > .table-bordered > thead > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:last-child > th,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-bordered > thead > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n  border-bottom: 0;\n}\n\n.panel-heading {\n  padding: 10px 15px;\n  border-bottom: 1px solid transparent;\n  border-top-right-radius: 3px;\n  border-top-left-radius: 3px;\n}\n\n.panel-heading > .dropdown .dropdown-toggle {\n  color: inherit;\n}\n\n.panel-title {\n  margin-top: 0;\n  margin-bottom: 0;\n  font-size: 16px;\n}\n\n.panel-title > a {\n  color: inherit;\n}\n\n.panel-footer {\n  padding: 10px 15px;\n  background-color: #f5f5f5;\n  border-top: 1px solid #dddddd;\n  border-bottom-right-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n\n.panel-group .panel {\n  margin-bottom: 0;\n  overflow: hidden;\n  border-radius: 4px;\n}\n\n.panel-group .panel + .panel {\n  margin-top: 5px;\n}\n\n.panel-group .panel-heading {\n  border-bottom: 0;\n}\n\n.panel-group .panel-heading + .panel-collapse .panel-body {\n  border-top: 1px solid #dddddd;\n}\n\n.panel-group .panel-footer {\n  border-top: 0;\n}\n\n.panel-group .panel-footer + .panel-collapse .panel-body {\n  border-bottom: 1px solid #dddddd;\n}\n\n.panel-default {\n  border-color: #dddddd;\n}\n\n.panel-default > .panel-heading {\n  color: #333333;\n  background-color: #f5f5f5;\n  border-color: #dddddd;\n}\n\n.panel-default > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #dddddd;\n}\n\n.panel-default > .panel-heading > .dropdown .caret {\n  border-color: #333333 transparent;\n}\n\n.panel-default > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #dddddd;\n}\n\n.panel-primary {\n  border-color: #428bca;\n}\n\n.panel-primary > .panel-heading {\n  color: #ffffff;\n  background-color: #428bca;\n  border-color: #428bca;\n}\n\n.panel-primary > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #428bca;\n}\n\n.panel-primary > .panel-heading > .dropdown .caret {\n  border-color: #ffffff transparent;\n}\n\n.panel-primary > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #428bca;\n}\n\n.panel-success {\n  border-color: #d6e9c6;\n}\n\n.panel-success > .panel-heading {\n  color: #468847;\n  background-color: #dff0d8;\n  border-color: #d6e9c6;\n}\n\n.panel-success > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #d6e9c6;\n}\n\n.panel-success > .panel-heading > .dropdown .caret {\n  border-color: #468847 transparent;\n}\n\n.panel-success > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #d6e9c6;\n}\n\n.panel-warning {\n  border-color: #faebcc;\n}\n\n.panel-warning > .panel-heading {\n  color: #c09853;\n  background-color: #fcf8e3;\n  border-color: #faebcc;\n}\n\n.panel-warning > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #faebcc;\n}\n\n.panel-warning > .panel-heading > .dropdown .caret {\n  border-color: #c09853 transparent;\n}\n\n.panel-warning > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #faebcc;\n}\n\n.panel-danger {\n  border-color: #ebccd1;\n}\n\n.panel-danger > .panel-heading {\n  color: #b94a48;\n  background-color: #f2dede;\n  border-color: #ebccd1;\n}\n\n.panel-danger > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #ebccd1;\n}\n\n.panel-danger > .panel-heading > .dropdown .caret {\n  border-color: #b94a48 transparent;\n}\n\n.panel-danger > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #ebccd1;\n}\n\n.panel-info {\n  border-color: #bce8f1;\n}\n\n.panel-info > .panel-heading {\n  color: #3a87ad;\n  background-color: #d9edf7;\n  border-color: #bce8f1;\n}\n\n.panel-info > .panel-heading + .panel-collapse .panel-body {\n  border-top-color: #bce8f1;\n}\n\n.panel-info > .panel-heading > .dropdown .caret {\n  border-color: #3a87ad transparent;\n}\n\n.panel-info > .panel-footer + .panel-collapse .panel-body {\n  border-bottom-color: #bce8f1;\n}\n\n.well {\n  min-height: 20px;\n  padding: 19px;\n  margin-bottom: 20px;\n  background-color: #f5f5f5;\n  border: 1px solid #e3e3e3;\n  border-radius: 4px;\n  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n\n.well blockquote {\n  border-color: #ddd;\n  border-color: rgba(0, 0, 0, 0.15);\n}\n\n.well-lg {\n  padding: 24px;\n  border-radius: 6px;\n}\n\n.well-sm {\n  padding: 9px;\n  border-radius: 3px;\n}\n\n.close {\n  float: right;\n  font-size: 21px;\n  font-weight: bold;\n  line-height: 1;\n  color: #000000;\n  text-shadow: 0 1px 0 #ffffff;\n  opacity: 0.2;\n  filter: alpha(opacity=20);\n}\n\n.close:hover,\n.close:focus {\n  color: #000000;\n  text-decoration: none;\n  cursor: pointer;\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\nbutton.close {\n  padding: 0;\n  cursor: pointer;\n  background: transparent;\n  border: 0;\n  -webkit-appearance: none;\n}\n\n.modal-open {\n  overflow: hidden;\n}\n\n.modal {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1040;\n  display: none;\n  overflow: auto;\n  overflow-y: scroll;\n}\n\n.modal.fade .modal-dialog {\n  -webkit-transform: translate(0, -25%);\n      -ms-transform: translate(0, -25%);\n          transform: translate(0, -25%);\n  -webkit-transition: -webkit-transform 0.3s ease-out;\n     -moz-transition: -moz-transform 0.3s ease-out;\n       -o-transition: -o-transform 0.3s ease-out;\n          transition: transform 0.3s ease-out;\n}\n\n.modal.in .modal-dialog {\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n          transform: translate(0, 0);\n}\n\n.modal-dialog {\n  position: relative;\n  z-index: 1050;\n  width: auto;\n  padding: 10px;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.modal-content {\n  position: relative;\n  background-color: #ffffff;\n  border: 1px solid #999999;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  outline: none;\n  -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n          box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n  background-clip: padding-box;\n}\n\n.modal-backdrop {\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  z-index: 1030;\n  background-color: #000000;\n}\n\n.modal-backdrop.fade {\n  opacity: 0;\n  filter: alpha(opacity=0);\n}\n\n.modal-backdrop.in {\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.modal-header {\n  min-height: 16.428571429px;\n  padding: 15px;\n  border-bottom: 1px solid #e5e5e5;\n}\n\n.modal-header .close {\n  margin-top: -2px;\n}\n\n.modal-title {\n  margin: 0;\n  line-height: 1.428571429;\n}\n\n.modal-body {\n  position: relative;\n  padding: 20px;\n}\n\n.modal-footer {\n  padding: 19px 20px 20px;\n  margin-top: 15px;\n  text-align: right;\n  border-top: 1px solid #e5e5e5;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer:before,\n.modal-footer:after {\n  display: table;\n  content: \" \";\n}\n\n.modal-footer:after {\n  clear: both;\n}\n\n.modal-footer .btn + .btn {\n  margin-bottom: 0;\n  margin-left: 5px;\n}\n\n.modal-footer .btn-group .btn + .btn {\n  margin-left: -1px;\n}\n\n.modal-footer .btn-block + .btn-block {\n  margin-left: 0;\n}\n\n@media screen and (min-width: 768px) {\n  .modal-dialog {\n    width: 600px;\n    padding-top: 30px;\n    padding-bottom: 30px;\n  }\n  .modal-content {\n    -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n  }\n}\n\n.tooltip {\n  position: absolute;\n  z-index: 1030;\n  display: block;\n  font-size: 12px;\n  line-height: 1.4;\n  opacity: 0;\n  filter: alpha(opacity=0);\n  visibility: visible;\n}\n\n.tooltip.in {\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.tooltip.top {\n  padding: 5px 0;\n  margin-top: -3px;\n}\n\n.tooltip.right {\n  padding: 0 5px;\n  margin-left: 3px;\n}\n\n.tooltip.bottom {\n  padding: 5px 0;\n  margin-top: 3px;\n}\n\n.tooltip.left {\n  padding: 0 5px;\n  margin-left: -3px;\n}\n\n.tooltip-inner {\n  max-width: 200px;\n  padding: 3px 8px;\n  color: #ffffff;\n  text-align: center;\n  text-decoration: none;\n  background-color: #000000;\n  border-radius: 4px;\n}\n\n.tooltip-arrow {\n  position: absolute;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.tooltip.top .tooltip-arrow {\n  bottom: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.top-left .tooltip-arrow {\n  bottom: 0;\n  left: 5px;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.top-right .tooltip-arrow {\n  right: 5px;\n  bottom: 0;\n  border-top-color: #000000;\n  border-width: 5px 5px 0;\n}\n\n.tooltip.right .tooltip-arrow {\n  top: 50%;\n  left: 0;\n  margin-top: -5px;\n  border-right-color: #000000;\n  border-width: 5px 5px 5px 0;\n}\n\n.tooltip.left .tooltip-arrow {\n  top: 50%;\n  right: 0;\n  margin-top: -5px;\n  border-left-color: #000000;\n  border-width: 5px 0 5px 5px;\n}\n\n.tooltip.bottom .tooltip-arrow {\n  top: 0;\n  left: 50%;\n  margin-left: -5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.tooltip.bottom-left .tooltip-arrow {\n  top: 0;\n  left: 5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.tooltip.bottom-right .tooltip-arrow {\n  top: 0;\n  right: 5px;\n  border-bottom-color: #000000;\n  border-width: 0 5px 5px;\n}\n\n.popover {\n  position: absolute;\n  top: 0;\n  left: 0;\n  z-index: 1010;\n  display: none;\n  max-width: 276px;\n  padding: 1px;\n  text-align: left;\n  white-space: normal;\n  background-color: #ffffff;\n  border: 1px solid #cccccc;\n  border: 1px solid rgba(0, 0, 0, 0.2);\n  border-radius: 6px;\n  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n  background-clip: padding-box;\n}\n\n.popover.top {\n  margin-top: -10px;\n}\n\n.popover.right {\n  margin-left: 10px;\n}\n\n.popover.bottom {\n  margin-top: 10px;\n}\n\n.popover.left {\n  margin-left: -10px;\n}\n\n.popover-title {\n  padding: 8px 14px;\n  margin: 0;\n  font-size: 14px;\n  font-weight: normal;\n  line-height: 18px;\n  background-color: #f7f7f7;\n  border-bottom: 1px solid #ebebeb;\n  border-radius: 5px 5px 0 0;\n}\n\n.popover-content {\n  padding: 9px 14px;\n}\n\n.popover .arrow,\n.popover .arrow:after {\n  position: absolute;\n  display: block;\n  width: 0;\n  height: 0;\n  border-color: transparent;\n  border-style: solid;\n}\n\n.popover .arrow {\n  border-width: 11px;\n}\n\n.popover .arrow:after {\n  border-width: 10px;\n  content: \"\";\n}\n\n.popover.top .arrow {\n  bottom: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-top-color: #999999;\n  border-top-color: rgba(0, 0, 0, 0.25);\n  border-bottom-width: 0;\n}\n\n.popover.top .arrow:after {\n  bottom: 1px;\n  margin-left: -10px;\n  border-top-color: #ffffff;\n  border-bottom-width: 0;\n  content: \" \";\n}\n\n.popover.right .arrow {\n  top: 50%;\n  left: -11px;\n  margin-top: -11px;\n  border-right-color: #999999;\n  border-right-color: rgba(0, 0, 0, 0.25);\n  border-left-width: 0;\n}\n\n.popover.right .arrow:after {\n  bottom: -10px;\n  left: 1px;\n  border-right-color: #ffffff;\n  border-left-width: 0;\n  content: \" \";\n}\n\n.popover.bottom .arrow {\n  top: -11px;\n  left: 50%;\n  margin-left: -11px;\n  border-bottom-color: #999999;\n  border-bottom-color: rgba(0, 0, 0, 0.25);\n  border-top-width: 0;\n}\n\n.popover.bottom .arrow:after {\n  top: 1px;\n  margin-left: -10px;\n  border-bottom-color: #ffffff;\n  border-top-width: 0;\n  content: \" \";\n}\n\n.popover.left .arrow {\n  top: 50%;\n  right: -11px;\n  margin-top: -11px;\n  border-left-color: #999999;\n  border-left-color: rgba(0, 0, 0, 0.25);\n  border-right-width: 0;\n}\n\n.popover.left .arrow:after {\n  right: 1px;\n  bottom: -10px;\n  border-left-color: #ffffff;\n  border-right-width: 0;\n  content: \" \";\n}\n\n.carousel {\n  position: relative;\n}\n\n.carousel-inner {\n  position: relative;\n  width: 100%;\n  overflow: hidden;\n}\n\n.carousel-inner > .item {\n  position: relative;\n  display: none;\n  -webkit-transition: 0.6s ease-in-out left;\n          transition: 0.6s ease-in-out left;\n}\n\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n  display: block;\n  height: auto;\n  max-width: 100%;\n  line-height: 1;\n}\n\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  display: block;\n}\n\n.carousel-inner > .active {\n  left: 0;\n}\n\n.carousel-inner > .next,\n.carousel-inner > .prev {\n  position: absolute;\n  top: 0;\n  width: 100%;\n}\n\n.carousel-inner > .next {\n  left: 100%;\n}\n\n.carousel-inner > .prev {\n  left: -100%;\n}\n\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n  left: 0;\n}\n\n.carousel-inner > .active.left {\n  left: -100%;\n}\n\n.carousel-inner > .active.right {\n  left: 100%;\n}\n\n.carousel-control {\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  width: 15%;\n  font-size: 20px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n  opacity: 0.5;\n  filter: alpha(opacity=50);\n}\n\n.carousel-control.left {\n  background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.5) 0), color-stop(rgba(0, 0, 0, 0.0001) 100%));\n  background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%);\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0, rgba(0, 0, 0, 0.0001) 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n\n.carousel-control.right {\n  right: 0;\n  left: auto;\n  background-image: -webkit-gradient(linear, 0 top, 100% top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));\n  background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, 0.0001) 0), color-stop(rgba(0, 0, 0, 0.5) 100%));\n  background-image: -moz-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%);\n  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0, rgba(0, 0, 0, 0.5) 100%);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n\n.carousel-control:hover,\n.carousel-control:focus {\n  color: #ffffff;\n  text-decoration: none;\n  opacity: 0.9;\n  filter: alpha(opacity=90);\n}\n\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n  position: absolute;\n  top: 50%;\n  z-index: 5;\n  display: inline-block;\n}\n\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n  left: 50%;\n}\n\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n  right: 50%;\n}\n\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n  width: 20px;\n  height: 20px;\n  margin-top: -10px;\n  margin-left: -10px;\n  font-family: serif;\n}\n\n.carousel-control .icon-prev:before {\n  content: '\\2039';\n}\n\n.carousel-control .icon-next:before {\n  content: '\\203a';\n}\n\n.carousel-indicators {\n  position: absolute;\n  bottom: 10px;\n  left: 50%;\n  z-index: 15;\n  width: 60%;\n  padding-left: 0;\n  margin-left: -30%;\n  text-align: center;\n  list-style: none;\n}\n\n.carousel-indicators li {\n  display: inline-block;\n  width: 10px;\n  height: 10px;\n  margin: 1px;\n  text-indent: -999px;\n  cursor: pointer;\n  background-color: #000 \\9;\n  background-color: rgba(0, 0, 0, 0);\n  border: 1px solid #ffffff;\n  border-radius: 10px;\n}\n\n.carousel-indicators .active {\n  width: 12px;\n  height: 12px;\n  margin: 0;\n  background-color: #ffffff;\n}\n\n.carousel-caption {\n  position: absolute;\n  right: 15%;\n  bottom: 20px;\n  left: 15%;\n  z-index: 10;\n  padding-top: 20px;\n  padding-bottom: 20px;\n  color: #ffffff;\n  text-align: center;\n  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n\n.carousel-caption .btn {\n  text-shadow: none;\n}\n\n@media screen and (min-width: 768px) {\n  .carousel-control .glyphicons-chevron-left,\n  .carousel-control .glyphicons-chevron-right,\n  .carousel-control .icon-prev,\n  .carousel-control .icon-next {\n    width: 30px;\n    height: 30px;\n    margin-top: -15px;\n    margin-left: -15px;\n    font-size: 30px;\n  }\n  .carousel-caption {\n    right: 20%;\n    left: 20%;\n    padding-bottom: 30px;\n  }\n  .carousel-indicators {\n    bottom: 20px;\n  }\n}\n\n.clearfix:before,\n.clearfix:after {\n  display: table;\n  content: \" \";\n}\n\n.clearfix:after {\n  clear: both;\n}\n\n.center-block {\n  display: block;\n  margin-right: auto;\n  margin-left: auto;\n}\n\n.pull-right {\n  float: right !important;\n}\n\n.pull-left {\n  float: left !important;\n}\n\n.hide {\n  display: none !important;\n}\n\n.show {\n  display: block !important;\n}\n\n.invisible {\n  visibility: hidden;\n}\n\n.text-hide {\n  font: 0/0 a;\n  color: transparent;\n  text-shadow: none;\n  background-color: transparent;\n  border: 0;\n}\n\n.hidden {\n  display: none !important;\n  visibility: hidden !important;\n}\n\n.affix {\n  position: fixed;\n}\n\n@-ms-viewport {\n  width: device-width;\n}\n\n.visible-xs,\ntr.visible-xs,\nth.visible-xs,\ntd.visible-xs {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-xs {\n    display: block !important;\n  }\n  tr.visible-xs {\n    display: table-row !important;\n  }\n  th.visible-xs,\n  td.visible-xs {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-xs.visible-sm {\n    display: block !important;\n  }\n  tr.visible-xs.visible-sm {\n    display: table-row !important;\n  }\n  th.visible-xs.visible-sm,\n  td.visible-xs.visible-sm {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-xs.visible-md {\n    display: block !important;\n  }\n  tr.visible-xs.visible-md {\n    display: table-row !important;\n  }\n  th.visible-xs.visible-md,\n  td.visible-xs.visible-md {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-xs.visible-lg {\n    display: block !important;\n  }\n  tr.visible-xs.visible-lg {\n    display: table-row !important;\n  }\n  th.visible-xs.visible-lg,\n  td.visible-xs.visible-lg {\n    display: table-cell !important;\n  }\n}\n\n.visible-sm,\ntr.visible-sm,\nth.visible-sm,\ntd.visible-sm {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-sm.visible-xs {\n    display: block !important;\n  }\n  tr.visible-sm.visible-xs {\n    display: table-row !important;\n  }\n  th.visible-sm.visible-xs,\n  td.visible-sm.visible-xs {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-sm {\n    display: block !important;\n  }\n  tr.visible-sm {\n    display: table-row !important;\n  }\n  th.visible-sm,\n  td.visible-sm {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-sm.visible-md {\n    display: block !important;\n  }\n  tr.visible-sm.visible-md {\n    display: table-row !important;\n  }\n  th.visible-sm.visible-md,\n  td.visible-sm.visible-md {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-sm.visible-lg {\n    display: block !important;\n  }\n  tr.visible-sm.visible-lg {\n    display: table-row !important;\n  }\n  th.visible-sm.visible-lg,\n  td.visible-sm.visible-lg {\n    display: table-cell !important;\n  }\n}\n\n.visible-md,\ntr.visible-md,\nth.visible-md,\ntd.visible-md {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-md.visible-xs {\n    display: block !important;\n  }\n  tr.visible-md.visible-xs {\n    display: table-row !important;\n  }\n  th.visible-md.visible-xs,\n  td.visible-md.visible-xs {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-md.visible-sm {\n    display: block !important;\n  }\n  tr.visible-md.visible-sm {\n    display: table-row !important;\n  }\n  th.visible-md.visible-sm,\n  td.visible-md.visible-sm {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-md {\n    display: block !important;\n  }\n  tr.visible-md {\n    display: table-row !important;\n  }\n  th.visible-md,\n  td.visible-md {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-md.visible-lg {\n    display: block !important;\n  }\n  tr.visible-md.visible-lg {\n    display: table-row !important;\n  }\n  th.visible-md.visible-lg,\n  td.visible-md.visible-lg {\n    display: table-cell !important;\n  }\n}\n\n.visible-lg,\ntr.visible-lg,\nth.visible-lg,\ntd.visible-lg {\n  display: none !important;\n}\n\n@media (max-width: 767px) {\n  .visible-lg.visible-xs {\n    display: block !important;\n  }\n  tr.visible-lg.visible-xs {\n    display: table-row !important;\n  }\n  th.visible-lg.visible-xs,\n  td.visible-lg.visible-xs {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .visible-lg.visible-sm {\n    display: block !important;\n  }\n  tr.visible-lg.visible-sm {\n    display: table-row !important;\n  }\n  th.visible-lg.visible-sm,\n  td.visible-lg.visible-sm {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .visible-lg.visible-md {\n    display: block !important;\n  }\n  tr.visible-lg.visible-md {\n    display: table-row !important;\n  }\n  th.visible-lg.visible-md,\n  td.visible-lg.visible-md {\n    display: table-cell !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .visible-lg {\n    display: block !important;\n  }\n  tr.visible-lg {\n    display: table-row !important;\n  }\n  th.visible-lg,\n  td.visible-lg {\n    display: table-cell !important;\n  }\n}\n\n.hidden-xs {\n  display: block !important;\n}\n\ntr.hidden-xs {\n  display: table-row !important;\n}\n\nth.hidden-xs,\ntd.hidden-xs {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-xs,\n  tr.hidden-xs,\n  th.hidden-xs,\n  td.hidden-xs {\n    display: none !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-xs.hidden-sm,\n  tr.hidden-xs.hidden-sm,\n  th.hidden-xs.hidden-sm,\n  td.hidden-xs.hidden-sm {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-xs.hidden-md,\n  tr.hidden-xs.hidden-md,\n  th.hidden-xs.hidden-md,\n  td.hidden-xs.hidden-md {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-xs.hidden-lg,\n  tr.hidden-xs.hidden-lg,\n  th.hidden-xs.hidden-lg,\n  td.hidden-xs.hidden-lg {\n    display: none !important;\n  }\n}\n\n.hidden-sm {\n  display: block !important;\n}\n\ntr.hidden-sm {\n  display: table-row !important;\n}\n\nth.hidden-sm,\ntd.hidden-sm {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-sm.hidden-xs,\n  tr.hidden-sm.hidden-xs,\n  th.hidden-sm.hidden-xs,\n  td.hidden-sm.hidden-xs {\n    display: none !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-sm,\n  tr.hidden-sm,\n  th.hidden-sm,\n  td.hidden-sm {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-sm.hidden-md,\n  tr.hidden-sm.hidden-md,\n  th.hidden-sm.hidden-md,\n  td.hidden-sm.hidden-md {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-sm.hidden-lg,\n  tr.hidden-sm.hidden-lg,\n  th.hidden-sm.hidden-lg,\n  td.hidden-sm.hidden-lg {\n    display: none !important;\n  }\n}\n\n.hidden-md {\n  display: block !important;\n}\n\ntr.hidden-md {\n  display: table-row !important;\n}\n\nth.hidden-md,\ntd.hidden-md {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-md.hidden-xs,\n  tr.hidden-md.hidden-xs,\n  th.hidden-md.hidden-xs,\n  td.hidden-md.hidden-xs {\n    display: none !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-md.hidden-sm,\n  tr.hidden-md.hidden-sm,\n  th.hidden-md.hidden-sm,\n  td.hidden-md.hidden-sm {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-md,\n  tr.hidden-md,\n  th.hidden-md,\n  td.hidden-md {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-md.hidden-lg,\n  tr.hidden-md.hidden-lg,\n  th.hidden-md.hidden-lg,\n  td.hidden-md.hidden-lg {\n    display: none !important;\n  }\n}\n\n.hidden-lg {\n  display: block !important;\n}\n\ntr.hidden-lg {\n  display: table-row !important;\n}\n\nth.hidden-lg,\ntd.hidden-lg {\n  display: table-cell !important;\n}\n\n@media (max-width: 767px) {\n  .hidden-lg.hidden-xs,\n  tr.hidden-lg.hidden-xs,\n  th.hidden-lg.hidden-xs,\n  td.hidden-lg.hidden-xs {\n    display: none !important;\n  }\n}\n\n@media (min-width: 768px) and (max-width: 991px) {\n  .hidden-lg.hidden-sm,\n  tr.hidden-lg.hidden-sm,\n  th.hidden-lg.hidden-sm,\n  td.hidden-lg.hidden-sm {\n    display: none !important;\n  }\n}\n\n@media (min-width: 992px) and (max-width: 1199px) {\n  .hidden-lg.hidden-md,\n  tr.hidden-lg.hidden-md,\n  th.hidden-lg.hidden-md,\n  td.hidden-lg.hidden-md {\n    display: none !important;\n  }\n}\n\n@media (min-width: 1200px) {\n  .hidden-lg,\n  tr.hidden-lg,\n  th.hidden-lg,\n  td.hidden-lg {\n    display: none !important;\n  }\n}\n\n.visible-print,\ntr.visible-print,\nth.visible-print,\ntd.visible-print {\n  display: none !important;\n}\n\n@media print {\n  .visible-print {\n    display: block !important;\n  }\n  tr.visible-print {\n    display: table-row !important;\n  }\n  th.visible-print,\n  td.visible-print {\n    display: table-cell !important;\n  }\n  .hidden-print,\n  tr.hidden-print,\n  th.hidden-print,\n  td.hidden-print {\n    display: none !important;\n  }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/css/owl.carousel.css",
    "content": "/* \n * \tCore Owl Carousel CSS File\n *\tv1.21\n */\n\n/* clearfix */\n.owl-carousel .owl-wrapper:after {\n\tcontent: \".\";\n\tdisplay: block;\n\tclear: both;\n\tvisibility: hidden;\n\tline-height: 0;\n\theight: 0;\n}\n/* display none until init */\n.owl-carousel{\n\tdisplay: none;\n\tposition: relative;\n\twidth: 100%;\n\t-ms-touch-action: pan-y;\n}\n.owl-carousel .owl-wrapper{\n\tdisplay: none;\n\tposition: relative;\n\t-webkit-transform: translate3d(0px, 0px, 0px);\n\t-webkit-perspective: 1000;\n}\n.owl-carousel .owl-wrapper-outer{\n\toverflow: hidden;\n\tposition: relative;\n\twidth: 100%;\n}\n.owl-carousel .owl-wrapper-outer.autoHeight{\n\t-webkit-transition: height 500ms ease-in-out;\n\t-moz-transition: height 500ms ease-in-out;\n\t-ms-transition: height 500ms ease-in-out;\n\t-o-transition: height 500ms ease-in-out;\n\ttransition: height 500ms ease-in-out;\n}\n\t\n.owl-carousel .owl-item{\n\tfloat: left;\n}\n.owl-controls .owl-page,\n.owl-controls .owl-buttons div{\n\tcursor: pointer;\n}\n.owl-controls {\n\t-webkit-user-select: none;\n\t-khtml-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n\t-webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\n\n/* mouse grab icon */\n.grabbing { \n    /*cursor:url(grabbing.png) 8 8, move;*/\n}\n\n/* fix */\n.owl-carousel  .owl-wrapper,\n.owl-carousel  .owl-item{\n\t-webkit-backface-visibility: hidden;\n\t-moz-backface-visibility:    hidden;\n\t-ms-backface-visibility:     hidden;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/css/style-responsive.css",
    "content": "@media (min-width: 980px) {\n    /*-----*/\n    .custom-bar-chart {\n        margin-bottom: 40px;\n    }\n}\n\n@media (min-width: 768px) and (max-width: 979px) {\n\n    .mail-box .sm-side {\n        width: 30%;\n    }\n\n    .mail-box .lg-side {\n        width: 70%;\n    }\n    /*-----*/\n    .custom-bar-chart {\n        margin-bottom: 40px;\n    }\n\n}\n\n@media (max-width: 768px) {\n\n    .header {\n        position: absolute;\n    }\n\n    /*sidebar*/\n\n    #sidebar {\n        height: auto;\n        overflow: hidden;\n        position: absolute;\n        width: 100%;\n        z-index: 1001;\n    }\n\n\n    /* body container */\n    #main-content {\n        margin: 0px!important;\n        position: none !important;\n    }\n\n    #sidebar > ul > li > a > span {\n        line-height: 35px;\n    }\n\n    #sidebar > ul > li {\n        margin: 0 10px 5px 10px;\n    }\n    #sidebar > ul > li > a {\n        height:35px;\n        line-height:35px;\n        padding: 0 10px;\n        text-align: left;\n    }\n    #sidebar > ul > li > a i{\n        /*display: none !important;*/\n    }\n\n    .mail-info, .mail-info:hover {\n        display: none !important;\n    }\n    #sidebar ul > li > a .arrow, #sidebar > ul > li > a .arrow.open {\n        margin-right: 10px;\n        margin-top: 15px;\n    }\n\n    #sidebar ul > li.active > a .arrow, #sidebar ul > li > a:hover .arrow, #sidebar ul > li > a:focus .arrow,\n    #sidebar > ul > li.active > a .arrow.open, #sidebar > ul > li > a:hover .arrow.open, #sidebar > ul > li > a:focus .arrow.open{\n        margin-top: 15px;\n    }\n\n    #sidebar > ul > li > a, #sidebar > ul > li > ul.sub > li {\n        width: 100%;\n    }\n    #sidebar > ul > li > ul.sub > li > a {\n        background: transparent !important ;\n    }\n    #sidebar > ul > li > ul.sub > li > a:hover {\n        /*background: #4A8BC2 !important ;*/\n    }\n\n\n    /* sidebar */\n    #sidebar {\n        margin: 0px !important;\n    }\n\n    /* sidebar collabler */\n    #sidebar .btn-navbar.collapsed .arrow {\n        display: none;\n    }\n\n    #sidebar .btn-navbar .arrow {\n        position: absolute;\n        right: 35px;\n        width: 0;\n        height: 0;\n        top:48px;\n        border-bottom: 15px solid #282e36;\n        border-left: 15px solid transparent;\n        border-right: 15px solid transparent;\n    }\n\n\n    /*---------*/\n\n    .btn {\n        margin-bottom: 5px;\n    }\n\n\n    .mail-box aside {\n        display: block;\n    }\n\n    .mail-box .sm-side , .mail-box .lg-side{\n        width: 100% ;\n    }\n\n    /* full calendar fix */\n    .fc-header-right {\n        left:25px;\n        position: absolute;\n    }\n\n    .fc-header-left .fc-button {\n        margin: 0px !important;\n        top: -10px !important;\n    }\n\n    .fc-header-right .fc-button {\n        margin: 0px !important;\n        top: -50px !important;\n    }\n\n    .fc-state-active, .fc-state-active .fc-button-inner, .fc-state-hover, .fc-state-hover .fc-button-inner {\n        background: none !important;\n        color: #FFFFFF !important;\n    }\n\n    .fc-state-default, .fc-state-default .fc-button-inner {\n        background: none !important;\n    }\n\n    .fc-button {\n        border: none !important;\n        margin-right: 2px;\n    }\n\n    .fc-view {\n        top: 0px !important;\n    }\n\n    .fc-button .fc-button-inner {\n        margin: 0px !important;\n        padding: 2px !important;\n        border: none !important;\n        margin-right: 2px !important;\n        background-color: #fafafa !important;\n        background-image: -moz-linear-gradient(top, #fafafa, #efefef) !important;\n        background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fafafa), to(#efefef)) !important;\n        background-image: -webkit-linear-gradient(top, #fafafa, #efefef) !important;\n        background-image: -o-linear-gradient(top, #fafafa, #efefef) !important;\n        background-image: linear-gradient(to bottom, #fafafa, #efefef) !important;\n        filter: progid:dximagetransform.microsoft.gradient(startColorstr='#fafafa', endColorstr='#efefef', GradientType=0) !important;\n        -webkit-box-shadow: 0 1px 0px rgba(255, 255, 255, .8) !important;\n        -moz-box-shadow: 0 1px 0px rgba(255, 255, 255, .8) !important;\n        box-shadow: 0 1px 0px rgba(255, 255, 255, .8) !important;\n        -webkit-border-radius: 3px !important;\n        -moz-border-radius: 3px !important;\n        border-radius: 3px !important;\n        color: #646464 !important;\n        border: 1px solid #ddd !important;\n        text-shadow: 0 1px 0px rgba(255, 255, 255, .6) !important;\n        text-align: center;\n    }\n\n    .fc-button.fc-state-disabled .fc-button-inner {\n        color: #bcbbbb !important;\n    }\n\n    .fc-button.fc-state-active .fc-button-inner {\n        background-color: #e5e4e4 !important;\n        background-image: -moz-linear-gradient(top, #e5e4e4, #dddcdc) !important;\n        background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#e5e4e4), to(#dddcdc)) !important;\n        background-image: -webkit-linear-gradient(top, #e5e4e4, #dddcdc) !important;\n        background-image: -o-linear-gradient(top, #e5e4e4, #dddcdc) !important;\n        background-image: linear-gradient(to bottom, #e5e4e4, #dddcdc) !important;\n        filter: progid:dximagetransform.microsoft.gradient(startColorstr='#e5e4e4', endColorstr='#dddcdc', GradientType=0) !important;\n    }\n\n    .fc-content {\n        margin-top: 50px;\n    }\n\n    .fc-header-title h2 {\n        line-height: 40px !important;\n        font-size: 12px !important;\n    }\n\n    .fc-header {\n        margin-bottom:0px !important;\n    }\n\n    /*--*/\n\n    /*.chart-position {*/\n        /*margin-top: 0px;*/\n    /*}*/\n\n    .timeline-desk .album a {\n        margin-bottom: 5px;\n        margin-right: 4px;\n    }\n\n    .stepy-titles li {\n        margin: 10px 3px;\n    }\n\n    .mail-option .btn {\n        margin-bottom: 0;\n    }\n\n    .boxed-page .container #sidebar {\n        position:absolute;\n    }\n\n    /*--horizontal menu--*/\n    .full-width .navbar-toggle {\n        border: 1px solid #eaeaea;\n    }\n    .full-width .navbar-toggle .icon-bar {\n        background: #c7c7c7;\n    }\n\n    .full-width .navbar-toggle {\n        float: left;\n        margin-top: 12px;\n    }\n\n    .horizontal-menu {\n        float: left;\n        margin-left:0px;\n        width: 70%;\n        margin-top: 10px;\n    }\n\n    .top-nav {\n        position: absolute;\n        right: 10px;\n        top: 0px;\n    }\n\n    .horizontal-menu .navbar-nav > li > a {\n        padding-bottom: 10px;\n        padding-top: 10px;\n    }\n    /*-----*/\n    .custom-bar-chart {\n        margin-bottom: 40px;\n    }\n\n    /*menu icon plus minus*/\n    .dcjq-icon {\n        top: 10px;\n    }\n    ul.sidebar-menu li ul.sub li a {\n        padding: 0;\n    }\n\n    /*---*/\n\n    .img-responsive {\n        width: 100%;\n    }\n\n}\n\n\n\n@media (max-width: 480px) {\n\n    .notify-row, .search, .dont-show , .inbox-head .sr-input, .inbox-head .sr-btn{\n        display: none;\n    }\n\n    .mail-box aside {\n        display: block;\n    }\n\n    .mail-box .sm-side , .mail-box .lg-side{\n        width: 100% ;\n    }\n\n    #top_menu .nav > li, ul.top-menu > li {\n        float: right;\n    }\n    .hidden-phone {\n        display: none !important;\n    }\n\n    .dataTables_filter {\n        float: left;\n    }\n\n    .dataTables_info {\n        margin-bottom: 10px;\n    }\n\n    .mail-option .btn {\n        margin-bottom: 0;\n    }\n\n    .mail-option .inbox-pagination {\n        margin-top: 10px;\n        float: left;\n    }\n\n    .chart-position {\n       margin-top: 0px;\n     }\n    /*--horizontal menu--*/\n    .full-width .navbar-toggle {\n        border: 1px solid #eaeaea;\n    }\n    .full-width .navbar-toggle .icon-bar {\n        background: #c7c7c7;\n    }\n\n    .full-width .navbar-toggle {\n        float: left;\n        margin-top: 12px;\n    }\n\n    .horizontal-menu {\n        float: left;\n        margin-left:0px;\n        width: 100%;\n    }\n\n    .top-nav {\n        position: absolute;\n        right: 10px;\n        top: 0px;\n    }\n\n    .horizontal-menu .navbar-nav > li > a {\n        padding-bottom: 10px;\n        padding-top: 10px;\n    }\n\n    .ms-container {\n        width: 100%;\n    }\n}\n\n@media (max-width:320px) {\n    .login-social-link a {\n        padding: 15px 17px !important;\n    }\n\n    .notify-row, .search, .dont-show, .inbox-head .sr-input, .inbox-head .sr-btn {\n        display: none;\n    }\n\n    .mail-box aside {\n        display: block ;\n    }\n\n    .mail-box .sm-side , .mail-box .lg-side{\n        width: 100% ;\n    }\n\n    #top_menu .nav > li, ul.top-menu > li {\n        float: right;\n    }\n\n    .hidden-phone {\n        display: none !important;\n    }\n\n    .dataTables_filter {\n        float: left;\n    }\n\n    .dataTables_info {\n        margin-bottom: 10px;\n    }\n\n    .mail-option .btn {\n        margin-bottom: 0;\n    }\n\n    .mail-option .inbox-pagination {\n        margin-top: 10px;\n        float: left;\n    }\n\n    .chart-position {\n        margin-top: 0px;\n    }\n\n    .lock-wrapper {\n        margin: 10% auto;\n        max-width: 310px;\n    }\n    .lock-input {\n        width: 82%;\n    }\n}\n\n\n\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/css/style.css",
    "content": "/*\nTemplate Name: Flat Lab Dashboard build with Bootstrap v3.0.2\nTemplate Version: 1.2.0\nAuthor: Mosaddek Hossain\nWebsite: http://thevectorlab.net/\n*/\n\n/* Import fonts */\n@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic);\n\nbody {\n    color: #797979;\n    background: #f1f2f7;\n    font-family: 'Open Sans', sans-serif;\n    padding: 0px !important;\n    margin: 0px !important;\n    font-size:13px;\n}\n\nul li {\n    list-style: none;\n}\n\na, a:hover, a:focus {\n    text-decoration: none;\n    outline: none;\n}\n::selection {\n\n    background: #FF6C60;\n    color: #fff;\n}\n::-moz-selection {\n    background: #FF6C60;\n    color: #fff;\n}\n\n#container {\n    width: 100%;\n    height: 100%;\n}\n\n/*login page*/\n\n.login-body {\n    background-color: #f1f2f7;\n}\n\n.form-signin {\n    max-width: 330px;\n    margin: 100px auto 0;\n    background: #fff;\n    border-radius: 5px;\n    -webkit-border-radius: 5px;\n}\n\n.form-signin h2.form-signin-heading {\n    margin: 0;\n    padding:20px 15px;\n    text-align: center;\n    background: #41cac0;\n    border-radius: 5px 5px 0 0;\n    -webkit-border-radius: 5px 5px 0 0;\n    color: #fff;\n    font-size: 18px;\n    text-transform: uppercase;\n    font-weight: 300;\n    font-family: 'Open Sans', sans-serif;\n}\n\n.form-signin .checkbox {\n    margin-bottom: 14px;\n}\n.form-signin .checkbox {\n    font-weight: normal;\n    color: #b6b6b6;\n    font-weight: 300;\n    font-family: 'Open Sans', sans-serif;\n}\n.form-signin .form-control {\n    position: relative;\n    font-size: 16px;\n    height: auto;\n    padding: 10px;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n}\n.form-signin .form-control:focus {\n    z-index: 2;\n}\n.form-signin input[type=\"text\"], .form-signin input[type=\"password\"] {\n    margin-bottom: 15px;\n    border-radius: 5px;\n    -webkit-border-radius: 5px;\n    border: 1px solid #eaeaea;\n    box-shadow: none;\n    font-size: 12px;\n}\n\n.form-signin .btn-login {\n    background: #f67a6e;\n    color: #fff;\n    text-transform: uppercase;\n    font-weight: 300;\n    font-family: 'Open Sans', sans-serif;\n    box-shadow: 0 4px #e56b60;\n    margin-bottom: 20px;\n}\n\n.form-signin p {\n    text-align: center;\n    color: #b6b6b6;\n    font-size: 16px;\n    font-weight: 300;\n}\n\n.form-signin a {\n    color: #41cac0;\n}\n\n.form-signin a:hover {\n    color: #b6b6b6;\n}\n\n.login-wrap {\n    padding: 20px;\n}\n\n.login-social-link  {\n    display: inline-block;\n    margin-top: 20px;\n    margin-bottom: 15px;\n}\n\n.login-social-link a {\n    color: #fff;\n    padding: 15px 28px;\n    border-radius: 4px;\n}\n\n.login-social-link a:hover {\n    color: #fff;\n}\n\n.login-social-link a i {\n    font-size: 20px;\n    padding-right: 10px;\n}\n\n.login-social-link a.facebook {\n    background: #5193ea;\n    margin-right: 22px;\n    box-shadow: 0 4px #2775e2;\n    float:left;\n}\n\n.login-social-link a.twitter {\n    background: #44ccfe;\n    box-shadow: 0 4px #2bb4e8;\n    float:left;\n}\n\n\n/*sidebar navigation*/\n\n#sidebar {\n    width: 210px;\n    height: 100%;\n    position: fixed;\n    background: #2a3542;\n}\n\n#sidebar ul li {\n    position: relative;\n}\n\n#sidebar .sub-menu > .sub li  {\n    padding-left: 32px;\n}\n\n#sidebar .sub-menu > .sub li:last-child {\n    padding-bottom: 10px;\n}\n\n/*LEFT NAVIGATION ICON*/\n.dcjq-icon {\n    height:17px;\n    width:17px;\n    display:inline-block;\n    background: url(../img/nav-expand.png) no-repeat top;\n    border-radius:3px;\n    -moz-border-radius:3px;\n    -webkit-border-radius:3px;\n    position:absolute;\n    right:10px;\n    top:15px;\n}\n.active .dcjq-icon {\n    background: url(../img/nav-expand.png) no-repeat bottom;\n    border-radius:3px;\n    -moz-border-radius:3px;\n    -webkit-border-radius:3px;\n}\n/*---*/\n\n.nav-collapse.collapse {\n    display: inline;\n}\n\nul.sidebar-menu , ul.sidebar-menu li ul.sub{\n    margin: -2px 0 0;\n    padding: 0;\n}\n\nul.sidebar-menu {\n    margin-top: 75px;\n}\n\n#sidebar > ul > li > ul.sub {\n    display: none;\n}\n\n#sidebar > ul > li.active > ul.sub, #sidebar > ul > li > ul.sub > li > a {\n    display: block;\n}\n\nul.sidebar-menu li ul.sub li{\n    background: #35404D;\n    margin-bottom: 0;\n    margin-left: 0;\n    margin-right: 0;\n}\n\nul.sidebar-menu li ul.sub li:last-child{\n    border-radius: 0 0 4px 4px;\n    -webkit-border-radius: 0 0 4px 4px;\n}\n\nul.sidebar-menu li ul.sub li a {\n    font-size: 12px;\n    padding: 6px 0;\n    line-height: 35px;\n    height: 35px;\n    -webkit-transition: all 0.3s ease;\n    -moz-transition: all 0.3s ease;\n    -o-transition: all 0.3s ease;\n    -ms-transition: all 0.3s ease;\n    transition: all 0.3s ease;\n    color: #aeb2b7;\n}\n\nul.sidebar-menu li ul.sub li a:hover, ul.sidebar-menu li ul.sub li.active a {\n    color: #FF6C60;\n    -webkit-transition: all 0.3s ease;\n    -moz-transition: all 0.3s ease;\n    -o-transition: all 0.3s ease;\n    -ms-transition: all 0.3s ease;\n    transition: all 0.3s ease;\n    display: block;\n}\n\nul.sidebar-menu li{\n    /*line-height: 20px !important;*/\n    margin-bottom: 5px;\n    margin-left:10px;\n    margin-right:10px;\n}\n\nul.sidebar-menu li.sub-menu{\n    line-height: 15px;\n}\n\nul.sidebar-menu li a span{\n    display: inline-block;\n}\n\nul.sidebar-menu li a{\n    color: #aeb2b7;\n    text-decoration: none;\n    display: block;\n    padding: 15px 0 15px 10px;\n    font-size: 12px;\n    outline: none;\n    -webkit-transition: all 0.3s ease;\n    -moz-transition: all 0.3s ease;\n    -o-transition: all 0.3s ease;\n    -ms-transition: all 0.3s ease;\n    transition: all 0.3s ease;\n}\n\nul.sidebar-menu li a.active, ul.sidebar-menu li a:hover, ul.sidebar-menu li a:focus {\n    background: #35404d;\n    color: #fff;\n    display: block;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n\n    -webkit-transition: all 0.3s ease;\n    -moz-transition: all 0.3s ease;\n    -o-transition: all 0.3s ease;\n    -ms-transition: all 0.3s ease;\n    transition: all 0.3s ease;\n}\n\n\nul.sidebar-menu li a i {\n    font-size: 15px;\n    padding-right: 6px;\n}\n\nul.sidebar-menu li a:hover i, ul.sidebar-menu li a:focus i {\n    color: #FF6C60;\n}\n\nul.sidebar-menu li a.active i {\n    color: #FF6C60;\n}\n\n\n.mail-info, .mail-info:hover {\n    margin: -3px 6px 0 0;\n    font-size: 11px;\n}\n\n/*main content*/\n\n#main-content {\n    margin-left: 210px;\n}\n\n.header, .footer {\n    min-height: 60px;\n    padding: 0 15px;\n}\n\n.header {\n    position: fixed;\n    left: 0;\n    right: 0;\n    z-index: 1002;\n}\n\n.white-bg {\n    background: #fff;\n    border-bottom: 1px solid #f1f2f7;\n}\n\n.wrapper {\n    display: inline-block;\n    margin-top: 60px;\n    padding: 15px;\n    width: 100%;\n}\n\na.logo {\n    font-size: 21px;\n    color: #2e2e2e;\n    float: left;\n    margin-top: 15px;\n    text-transform: uppercase;\n}\n\na.logo:hover, a.logo:focus {\n    text-decoration: none;\n    outline: none;\n}\n\na.logo span {\n    color: #FF6C60;\n}\n\n\n/*notification*/\n\n#top_menu .nav > li, ul.top-menu > li {\n    float: left;\n}\n\n.notify-row {\n    float: left;\n    margin-top: 15px;\n    margin-left: 92px;\n}\n\nul.top-menu > li > a {\n    color: #666666;\n    font-size: 16px;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n    border:1px solid #f0f0f8 !important;\n    padding: 2px 6px;\n    margin-right: 15px;\n}\n\nul.top-menu > li > a:hover, ul.top-menu > li > a:focus {\n    border:1px solid #f0f0f8 !important;\n    background-color: #fff!important;\n    border-color: #f0f0f8 !important;\n    text-decoration: none;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n    color: #2E2E2E !important;\n}\n\n.notify-row .badge {\n    position: absolute;\n    right: -10px;\n    top: -10px;\n    z-index: 100;\n}\n\n.dropdown-menu.extended {\n    max-width: 300px !important;\n    min-width: 160px !important;\n    top: 42px;\n    width: 235px !important;\n    padding: 0;\n    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.176) !important;\n    border: none !important;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n}\n\n@media screen and (-webkit-min-device-pixel-ratio:0) {\n    /* Safari and Chrome */\n    .dropdown-menu.extended  {\n        box-shadow: 0 2px 8px rgba(0, 0, 0, 0.176) !important;\n    };\n    }\n\n.dropdown-menu.extended li p {\n    background-color: #F1F2F7;\n    color: #666666;\n    margin: 0;\n    padding: 10px;\n    border-radius: 4px 4px 0px 0px;\n    -webkit-border-radius: 4px 4px 0px 0px;\n}\n\n.dropdown-menu.extended li p.green {\n    background-color: #a9d86e;\n    color: #fff;\n}\n\n.dropdown-menu.extended li p.red {\n    background-color: #ff6c60;\n    color: #fff;\n}\n\n.dropdown-menu.extended li p.yellow {\n    background-color: #fcb322;\n    color: #fff;\n}\n\n.dropdown-menu.extended li a {\n    border-bottom: 1px solid #EBEBEB !important;\n    font-size: 12px;\n    list-style: none;\n}\n\n.dropdown-menu.extended li a {\n    padding: 15px 10px !important;\n    width: 100%;\n    display: inline-block;\n}\n\n.dropdown-menu.extended li a:hover {\n    background-color: #F7F8F9 !important;\n    color: #2E2E2E;\n}\n\n.dropdown-menu.tasks-bar .task-info .desc {\n    font-size: 13px;\n    font-weight: normal;\n}\n\n.dropdown-menu.tasks-bar .task-info .percent {\n    display: inline-block;\n    float: right;\n    font-size: 13px;\n    font-weight: 600;\n    padding-left: 10px;\n    margin-top: -4px;\n}\n\n.dropdown-menu.extended .progress {\n    margin-bottom: 0 !important;\n    height: 10px;\n}\n\n.dropdown-menu.inbox li a .photo img {\n    border-radius: 2px 2px 2px 2px;\n    float: left;\n    height: 40px;\n    margin-right: 4px;\n    width: 40px;\n}\n\n.dropdown-menu.inbox li a .subject {\n    display: block;\n}\n\n.dropdown-menu.inbox li a .subject .from {\n    font-size: 12px;\n    font-weight: 600;\n}\n\n.dropdown-menu.inbox li a .subject .time {\n    font-size: 11px;\n    font-style: italic;\n    font-weight: bold;\n    position: absolute;\n    right: 5px;\n}\n\n.dropdown-menu.inbox li a .message {\n    display: block !important;\n    font-size: 11px;\n}\n\n.top-nav  {\n    margin-top: 7px;\n}\n\n.top-nav ul.top-menu > li .dropdown-menu.logout {\n    width: 268px !important;\n\n}\n\n.top-nav li.dropdown .dropdown-menu {\n    float: right;\n    right: 0;\n    left: auto;\n}\n\n.dropdown-menu.extended.logout > li {\n    float: left;\n    text-align: center;\n    width: 33.3%;\n}\n\n.dropdown-menu.extended.logout > li:last-child {\n    float: left;\n    text-align: center;\n    width: 100%;\n    background: #a9d96c;\n    border-radius: 0 0 3px 3px;\n}\n\n.dropdown-menu.extended.logout > li:last-child > a, .dropdown-menu.extended.logout > li:last-child > a:hover {\n    color: #fff;\n    border-bottom: none !important;\n    text-transform: uppercase;\n}\n\n.dropdown-menu.extended.logout > li:last-child > a:hover > i{\n    color: #fff;\n}\n\n.dropdown-menu.extended.logout > li > a {\n    color: #a4abbb;\n    border-bottom: none !important;\n}\n\n.full-width .dropdown-menu.extended.logout > li > a:hover {\n    background: none !important;\n    color: #50c8ea !important;\n}\n\n.dropdown-menu.extended.logout > li > a:hover {\n    background: none !important;\n}\n\n.dropdown-menu.extended.logout > li > a:hover i {\n    color: #50c8ea;\n}\n\n.dropdown-menu.extended.logout > li > a i {\n    font-size: 17px;\n}\n\n.dropdown-menu.extended.logout > li > a > i {\n    display: block;\n}\n\n.top-nav .username {\n    font-size: 13px;\n    color: #555555;\n}\n\n.top-nav ul.top-menu > li > a {\n    border: 1px solid #eeeeee;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n    padding: 6px;\n    background: none;\n    margin-right: 0;\n}\n.top-nav ul.top-menu > li {\n    margin-left: 10px;\n}\n\n.top-nav ul.top-menu > li > a:hover, .top-nav ul.top-menu > li > a:focus {\n    border:1px solid #F1F2F7;\n    background: #F1F2F7;\n\n}\n\n.top-nav .dropdown-menu.extended.logout {\n    top: 50px;\n}\n\n.top-nav .nav .caret {\n    border-bottom-color: #A4AABA;\n    border-top-color: #A4AABA;\n}\n.top-nav ul.top-menu > li > a:hover .caret {\n    border-bottom-color: #000;\n    border-top-color: #000;\n}\n\n.log-arrow-up {\n    background: url(\"../img/arrow-up.png\") no-repeat;\n    width: 20px;\n    height: 11px;\n    position: absolute;\n    right: 20px;\n    top: -10px;\n}\n\n/*----*/\n\n.notify-arrow {\n    border-style: solid;\n    border-width: 0 9px 9px;\n    height: 0;\n    margin-top: 0;\n    opacity: 0;\n    position: absolute;\n    left: 7px;\n    top: -18px;\n    transition: all 0.25s ease 0s;\n    width: 0;\n    z-index: 10;\n    margin-top: 10px;\n    opacity: 1;\n}\n\n.notify-arrow-yellow {\n    border-color: transparent transparent #FCB322;\n    border-bottom-color: #FCB322 !important;\n    border-top-color: #FCB322 !important;\n}\n.notify-arrow-red {\n    border-color: transparent transparent #ff6c60;\n    border-bottom-color: #ff6c60 !important;\n    border-top-color: #ff6c60 !important;\n}\n.notify-arrow-green {\n    border-color: transparent transparent #a9d86e;\n    border-bottom-color: #a9d86e !important;\n    border-top-color: #a9d86e !important;\n}\n\n\n/*search*/\n\n.search {\n    margin-top: 6px ;\n    width: 20px;\n    -webkit-transition: all .3s ease;\n    -moz-transition: all .3s ease;\n    -ms-transition: all .3s ease;\n    -o-transition: all .3s ease;\n    transition: all .3s ease;\n    border: 1px solid #fff;\n    box-shadow: none;\n    background: url(\"../img/search-icon.jpg\") no-repeat 10px 8px;\n    padding:0 5px 0 35px;\n    color: #fff;\n}\n\n.search:focus {\n    margin-top: 5px ;\n    width: 180px;\n    border: 1px solid #eaeaea;\n    box-shadow: none;\n    -webkit-transition: all .3s ease;\n    -moz-transition: all .3s ease;\n    -ms-transition: all .3s ease;\n    -o-transition: all .3s ease;\n    transition: all .3s ease;\n    color: #c8c8c8;\n    font-weight: 300;\n}\n\n/*--sidebar toggle---*/\n\n.sidebar-toggle-box {\n    float: left;\n    padding-right: 15px;\n    margin-top: 20px;\n}\n\n.sidebar-toggle-box .icon-reorder {\n    cursor: pointer;\n    display: inline-block;\n    font-size: 20px;\n}\n\n\n.sidebar-closed > #sidebar > ul {\n    display: none;\n}\n\n.sidebar-closed #main-content {\n    margin-left: 0px;\n}\n\n.sidebar-closed #sidebar {\n    margin-left: -180px;\n}\n\n/*state overview*/\n\n.state-overview .symbol, .state-overview .value {\n    display: inline-block;\n    text-align: center;\n}\n\n.state-overview .value  {\n    float: right;\n\n}\n\n.state-overview .value h1, .state-overview .value p  {\n    margin: 0;\n    padding: 0;\n    color: #c6cad6;\n}\n\n.state-overview .value h1 {\n    font-weight: 300;\n}\n\n.state-overview .symbol i {\n    color: #fff;\n    font-size: 50px;\n}\n\n.state-overview .symbol {\n    width: 40%;\n    padding: 25px 15px;\n    -webkit-border-radius: 4px 0px 0px 4px;\n    border-radius: 4px 0px 0px 4px;\n}\n\n.state-overview .value {\n    width: 58%;\n    padding-top: 21px;\n}\n\n.state-overview .terques {\n    background: #6ccac9;\n}\n\n.state-overview .red {\n    background: #ff6c60;\n}\n\n.state-overview .yellow {\n    background: #f8d347;\n}\n\n.state-overview .blue {\n    background: #57c8f2;\n}\n\n/*main chart*/\n\n.border-head h3 {\n    border-bottom: 1px solid #c9cdd7;\n    margin-top: 0;\n    margin-bottom: 20px;\n    padding-bottom: 5px;\n    font-weight: normal;\n    font-size: 18px;\n    display: inline-block;\n    width: 100%;\n    font-weight: 300;\n}\n\n.custom-bar-chart {\n    height: 290px;\n    margin-top: 20px;\n    margin-left: 10px;\n    position: relative;\n    border-bottom: 1px solid #c9cdd7;\n}\n\n.custom-bar-chart .bar {\n    height: 100%;\n    position: relative;\n    width: 4.3%;\n    margin: 0px 2%;\n    float: left;\n    text-align: center;\n    -webkit-border-radius: 5px 5px 0 0;\n    -moz-border-radius: 5px 5px 0 0x;\n    border-radius: 5px 5px 0 0;\n    z-index: 10;\n}\n\n.custom-bar-chart .bar .title {\n    position: absolute;\n    bottom: -30px;\n    width: 100%;\n    text-align: center;\n    font-size: 12px;\n}\n\n.custom-bar-chart .bar .value {\n    position: absolute;\n    bottom: 0;\n    background: #bfc2cd;\n    color: #bfc2cd;\n    width: 100%;\n    -webkit-border-radius: 5px 5px 0 0;\n    -moz-border-radius: 5px 5px 0 0;\n    border-radius: 5px 5px 0 0;\n    -webkit-transition: all .3s ease;\n    -moz-transition: all .3s ease;\n    -ms-transition: all .3s ease;\n    -o-transition: all .3s ease;\n    transition: all .3s ease;\n}\n\n\n\n.custom-bar-chart .bar .value:hover {\n    background: #e8403f;\n    color: #fff;\n}\n\n.y-axis {\n    color: #555555;\n    position: absolute;\n    text-align: right;\n    width: 100%;\n}\n\n.y-axis li {\n    border-top: 1px dashed #dbdce0;\n    display: block;\n    height: 58px;\n    width: 100%;\n}\n\n.y-axis li:last-child {\n    border-top: none;\n}\n\n.y-axis li span {\n    display: block;\n    margin: -10px 0 0 -25px;\n    padding: 0 10px;\n    width: 40px;\n}\n\n.y-axis {\n    color: #555555;\n    text-align: right;\n}\n\n\n\n\n/*spark line*/\n.chart {\n    display: inline-block;\n    text-align: center;\n    width: 100%;\n}\n.chart .heading {\n    text-align: left;\n}\n.chart .heading span {\n    display: block;\n}\n.panel.green-chart .chart-tittle {\n    font-size: 16px;\n    padding: 15px;\n    display: inline-block;\n    font-weight:normal;\n    background: #99c262;\n    width: 100%;\n    -webkit-border-radius: 0px 0px 4px 4px;\n    border-radius: 0px 0px 4px 4px;\n}\n\n#barchart {\n    margin-bottom: -15px;\n    display: inline-block;\n}\n\n.chart-tittle .title {\n\n}\n\n.panel.green-chart .chart-tittle .value {\n    float: right;\n    color: #c0f080;\n}\n\n.panel.green-chart {\n    background: #a9d96c;\n    color: #fff;\n}\n\n.panel.terques-chart {\n    background: #41cac0;\n    color: #fff;\n}\n\n.panel.terques-chart .chart-tittle .value {\n    float: right;\n    color: #fff;\n}\n\n.panel.terques-chart .chart-tittle .value a {\n    color: #fff;\n    font-size: 12px;\n}\n\n.panel.terques-chart .chart-tittle .value a:hover, .panel.terques-chart .chart-tittle .value a.active {\n    color: #55f2e7;\n    font-size: 12px;\n}\n\n.panel.terques-chart .chart-tittle {\n    font-size: 16px;\n    padding: 15px;\n    display: inline-block;\n    font-weight:normal;\n    background: #39b7ac;\n    width: 100%;\n    -webkit-border-radius: 0px 0px 4px 4px;\n    border-radius: 0px 0px 4px 4px;\n}\n\n.inline-block {\n    display: inline-block;\n}\n\n/**/\n\n.panel-body.chart-texture {\n    background: url(\"../img/chart-texture.jpg\");\n    -webkit-border-radius: 4px 4px 0px 0px;\n    border-radius: 4px 4px 0px 0px;\n}\n\n\n/*personal task*/\n\n.task-thumb {\n    width: 90px;\n    float: left;\n}\n\n.task-thumb img {\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n}\n\n.task-thumb-details {\n    display: inline-block;\n    margin: 25px 0 0 10px;\n}\n\n.task-progress {\n    float: left;\n}\n\n.task-thumb-details h1, .task-thumb-details h1 a, .task-progress h1, .task-progress h1 a {\n    color: #39b5aa;\n    font-size: 18px;\n    margin: 0;\n    padding: 0;\n    font-weight: 400;\n}\n\n.task-thumb-details p, .task-progress p {\n    padding-top: 5px;\n    color: #a4aaba;\n}\n\n\n.personal-task tbody tr td{\n    padding: 11px 15px;\n    border-color: #eeeff1;\n}\n\n.personal-task tbody tr td i {\n    font-size: 20px;\n    color: #c7cbd4;\n}\n\n.personal-task.table-hover > tbody > tr:hover > td,\n.table-hover > tbody > tr:hover > th {\n    background-color: #f7f8fc;\n}\n\n.personal-task.table-hover > tbody > tr:hover > td i{\n    color: #39b5aa;\n}\n\n.personal-task > tbody > tr > td:last-child {\n    text-align: right;\n}\n\n.task-option {\n    float: right;\n}\n\n.task-option select{\n    height: 35px;\n    border: 1px solid #eaeaea;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n    padding: 8px;\n    color: #a4abbb;\n}\n\n.progress-panel {\n    padding-bottom: 5px;\n}\n\n/*badge*/\n\n.badge.bg-primary {\n    background: #8075c4;\n}\n\n.badge.bg-success {\n    background: #a9d86e;\n}\n\n.badge.bg-warning {\n    background: #FCB322;\n}\n\n.badge.bg-important {\n    background: #ff6c60;\n}\n\n.badge.bg-info {\n    background: #41cac0;\n}\n\n.badge.bg-inverse {\n    background: #2A3542;\n}\n\n\n/*timeline*/\n\n.timeline {\n    border-collapse: collapse;\n    border-spacing: 0;\n    display: table;\n    position: relative;\n    table-layout: fixed;\n    width: 100%;\n}\n\n.timeline:before {\n    background-color: #C7CBD6;\n    bottom: 0px;\n    content: \"\";\n    left: 50%;\n    position: absolute;\n    top: 0;\n    width: 2px;\n    z-index: 0;\n}\n\nh3.timeline-title {\n    margin: 0;\n    color: #C8CCD7;\n    font-size: 20px;\n    font-weight: 400;\n    margin: 0 0 5px;\n    text-transform: uppercase;\n}\n\n.t-info {\n    color: #C8CCD7;\n}\n\n.timeline-item:before, .timeline-item.alt:after {\n    content: \"\";\n    display: block;\n    width: 50%;\n}\n\n.timeline-item {\n    display: table-row;\n}\n\n.timeline-desk {\n    display: table-cell;\n    vertical-align: top;\n    width: 50%;\n}\n\n.timeline-desk h1 {\n    font-size: 16px;\n    font-weight: 300;\n    margin: 0 0 5px;\n}\n\n.timeline-desk .panel {\n    display: block;\n    margin-left: 25px;\n    position: relative;\n    text-align: left;\n    background: #F4F4F4;\n}\n\n.timeline-item .timeline-desk .arrow {\n    border-bottom: 8px solid transparent;\n    border-top: 8px solid transparent;\n    display: block;\n    height: 0;\n    left: -7px;\n    position: absolute;\n    top: 13px;\n    width: 0;\n}\n.timeline-item .timeline-desk .arrow {\n    border-right: 8px solid #F4F4F4 !important;\n}\n\n.timeline-item.alt .timeline-desk .arrow-alt {\n    border-bottom: 8px solid transparent;\n    border-top: 8px solid transparent;\n    display: block;\n    height: 0;\n    right: -7px;\n    position: absolute;\n    top: 13px;\n    width: 0;\n    left: auto;\n}\n\n.timeline-item.alt .timeline-desk .arrow-alt {\n    border-left: 8px solid #F4F4F4 !important;\n}\n\n.timeline .timeline-icon {\n    left: -30px;\n    position: absolute;\n    top: 15px;\n}\n\n.timeline .timeline-icon {\n    background: #C7CBD6;\n    box-shadow: 0 0 0 3px #C7CBD6;\n}\n\n.timeline-desk span a {\n    text-transform: uppercase;\n}\n\n.timeline-desk h1.red, .timeline-desk span a.red {\n    color: #EF6F66;\n}\n\n.timeline-desk h1.green, .timeline-desk span a.green  {\n    color: #39B6AE;\n}\n.timeline-desk h1.blue, .timeline-desk span a.blue {\n    color: #56C9F5;\n}\n.timeline-desk h1.purple, .timeline-desk span a.purple {\n    color: #8074C6;\n}\n.timeline-desk h1.light-green, .timeline-desk span a.light-green {\n    color: #A8D76F;\n}\n\n.timeline .timeline-icon.red {\n    background: #EF6F66;\n    box-shadow: 0 0 0 3px #EF6F66;\n}\n\n.timeline .timeline-icon.green {\n    background: #39B6AE;\n    box-shadow: 0 0 0 3px #39B6AE;\n}\n\n.timeline .timeline-icon.blue {\n    background: #56C9F5;\n    box-shadow: 0 0 0 3px #56C9F5;\n}\n\n.timeline .timeline-icon.purple {\n    background: #8074C6;\n    box-shadow: 0 0 0 3px #8074C6;\n}\n\n.timeline .timeline-icon.light-green {\n    background: #A8D76F;\n    box-shadow: 0 0 0 3px #A8D76F;\n}\n\n.timeline .timeline-icon {\n    border: 3px solid #FFFFFF;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    display: block;\n    height: 12px;\n    width: 12px;\n}\n\n.timeline-item.alt .timeline-icon {\n    left: auto;\n    right: -32px;\n}\n\n.timeline .time-icon:before {\n    font-size: 16px;\n    margin-top: 5px;\n}\n.timeline .timeline-date {\n    left: -200px;\n    position: absolute;\n    text-align: right;\n    top: 12px;\n    width: 150px;\n}\n\n.timeline-desk h5 span {\n    color: #999999;\n    display: block;\n    font-size: 12px;\n    margin-bottom: 4px;\n}\n\n\n.timeline-item.alt:before {\n    display: none;\n}\n.timeline-item:before, .timeline-item.alt:after {\n    content: \"\";\n    display: block;\n    width: 50%;\n}\n\n.timeline-desk p {\n    font-size: 12px;\n    margin-bottom: 0;\n}\n\n.timeline-desk a {\n    color: #EF6F66;\n}\n\n.timeline-desk .panel {\n    margin-bottom: 5px;\n}\n\n.timeline-desk .album {\n    margin-top: 20px;\n}\n\n.timeline-desk .album a {\n    margin-right: 5px;\n    float: left;\n}\n\n.timeline-desk .notification {\n    background: none repeat scroll 0 0 #FFFFFF;\n    margin-top: 20px;\n    padding: 8px;\n}\n\n\n.timeline-item.alt .panel {\n    margin-left: 0;\n    margin-right: 25px;\n}\n\n.timeline-item.alt .timeline-date {\n    left: auto;\n    right: -200px;\n    text-align: left;\n}\n\n.mbot30 {\n    margin-bottom: 30px;\n}\n\n/*---revenue----*/\n\n.revenue-head {\n    background: #ff6c60;\n    -webkit-border-radius: 4px 4px 0px 0px;\n    border-radius: 4px 4px 0px 0px;\n    color: #fff;\n    line-height: 50px;\n}\n\n.revenue-head span {\n    background: #e56155;\n    padding: 16px;\n    -webkit-border-radius: 4px 0px 0px 0px;\n    border-radius: 4px 0px 0px 0px;\n}\n\n.revenue-head span i {\n    font-size: 18px;\n}\n\n.revenue-head h3 {\n    display: inline;\n    padding: 0 10px;\n    font-size: 16px;\n    font-weight: 300;\n}\n\n.revenue-head span.rev-combo {\n    background: #e56155;\n    padding: 16px;\n    line-height: normal;\n    -webkit-border-radius: 0px 4px 0px 0px;\n    border-radius: 0px 4px 0px 0px;\n}\n\n/*easy pie chart*/\n\n.easy-pie-chart {\n    display: inline-block;\n    padding: 30px 0;\n}\n\n.chart-info, .chart-info .increase, .chart-info .decrease {\n    display: inline-block;\n}\n\n.chart-info {\n    width: 100%;\n    margin-bottom:5px;\n}\n\n.chart-position {\n    margin-top: 70px;\n}\n\n.chart-info span {\n    margin: 0 3px;\n}\n\n.chart-info .increase {\n    background: #ff6c60;\n    width: 10px;\n    height: 10px;\n}\n\n.chart-info .decrease {\n    background: #f2f2f2;\n    width: 10px;\n    height: 10px;\n}\n\n.panel-footer.revenue-foot {\n    background-color: #e6e7ec;\n    -webkit-border-radius: 0px 0px 4px 4px;\n    border-radius: 0px 0px 4px 4px;\n    border: none;\n    padding: 0;\n    width: 100%;\n    display: inline-block;\n}\n\n@media screen and (-webkit-min-device-pixel-ratio:0) {\n    /* Safari and Chrome */\n    .panel-footer.revenue-foot {\n        margin-bottom: -4px;\n    };\n    }\n\n\n.panel-footer.revenue-foot ul  {\n    margin: 0;\n    padding: 0;\n    width: 100%;\n    display: inline-flex;\n}\n\n.panel-footer.revenue-foot ul li {\n    float: left;\n    width: 33.33%;\n}\n\n.panel-footer.revenue-foot ul li.first a:hover, .panel-footer.revenue-foot ul li.first a {\n    -webkit-border-radius: 0px 0px 0px 4px;\n    border-radius: 0px 0px 0px 4px;\n}\n\n.panel-footer.revenue-foot ul li.last a:hover, .panel-footer.revenue-foot ul li.last a {\n    -webkit-border-radius: 0px 0px 4px 0px;\n    border-radius: 0px 0px 4px 0px;\n    border-right: none;\n\n}\n\n.panel-footer.revenue-foot ul li a{\n    display: inline-block;\n    width: 100%;\n    padding: 14px 15px;\n    text-align: center;\n    border-right: 1px solid #d5d8df;\n    color: #797979;\n}\n\n.panel-footer.revenue-foot ul li a:hover, .panel-footer.revenue-foot ul li.active a {\n    background: #fff;\n    position: relative;\n}\n\n.panel-footer.revenue-foot ul li a i {\n    color: #c6cad5;\n    display: block;\n    font-size: 16px;\n}\n.panel-footer.revenue-foot ul li a:hover i, .panel-footer.revenue-foot ul li.active a i {\n    color: #ff6c60;\n    display: block;\n    font-size: 16px;\n}\n\n/*flatlab carousel model*/\n\n.flat-carousal {\n    background: #58c9f3;\n    -webkit-border-radius: 4px 4px 0px 0px;\n    border-radius: 4px 4px 0px 0px;\n    padding: 10px;\n    color: #fff;\n    position: relative;\n}\n\n.flat-carousal h1 {\n    text-align: center;\n    font-size: 16px;\n    margin: 30px 20px;\n    line-height: 20px;\n    font-weight: 300;\n    font-style: italic;\n}\n\na.view-all {\n    color: #fff;\n    background: rgba(0,0,0,0.1);\n    padding: 8px 15px;\n    text-align: center;\n    border-radius: 25px;\n    -webkit-border-radius: 25px;\n    margin-bottom: 18px;\n    display: inline-block;\n    text-transform: uppercase;\n    font-size: 12px;\n}\n\nul.ft-link {\n    margin: 0;\n    padding: 0;\n}\n\nul.ft-link li {\n    border-right: 1px solid #E6E7EC;\n    display: inline-block;\n    line-height: 30px;\n    margin: 8px 0;\n    text-align: center;\n    width: 24%;\n}\n\nul.ft-link li a {\n    color: #74829c;\n    text-transform: uppercase;\n    font-size: 12px;\n}\n\nul.ft-link li a:hover, ul.ft-link li.active a {\n    color: #58c9f3;\n}\n\nul.ft-link li:last-child {\n    border-right: none;\n}\n\nul.ft-link li a i {\n    display: block;\n}\n\n\n#owl-demo .item img{\n    display: block;\n    width: 100%;\n    height: auto;\n}\n\n.owl-buttons {\n    position: absolute;\n    top: 70px;\n    width: 100%;\n\n}\n\n.owl-prev, .owl-next {\n    position: absolute;\n}\n\n.owl-next {\n    right: 0;\n}\n\n.owl-buttons .owl-prev {\n    text-indent: -9999px;\n    background: url(\"../img/left-arrow.png\") no-repeat;\n    width: 6px;\n    height: 10px;\n    display: inline-block;\n}\n\n.owl-buttons .owl-next {\n    text-indent: -9999px;\n    background: url(\"../img/right-arrow.png\") no-repeat;\n    width: 6px;\n    height: 10px;\n    display: inline-block;\n}\n\n/*product post*/\n\n.post-wrap aside {\n    display: table-cell;\n    float: none;\n    height: 100%;\n    padding: 0;\n    vertical-align: top;\n}\n\n.pro-box {\n    border-collapse: collapse;\n    border-spacing: 0;\n    display: table;\n    table-layout: fixed;\n    width: 100%;\n}\n.post-info {\n    position: relative;\n}\n\n.arrow-pro.right:after {\n    border-left-color: #FFFFFF;\n    border-right-width: 0;\n    top: 85px;\n    content: \" \";\n}\n\n.arrow-pro.left:after {\n    border-right-color: #FFFFFF;\n    border-left-width: 0;\n    top: 80px;\n    content: \" \";\n}\n\n.arrow-pro.left {\n    left: -8px;\n}\n\n.arrow-pro:after {\n    border-width: 7px;\n    content: \"\";\n}\n\n.arrow-pro, .arrow-pro:after {\n    border-color: rgba(0, 0, 0, 0);\n    border-style: solid;\n    display: block;\n    height: 0;\n    position: absolute;\n    width: 0;\n    right: -5px;\n\n}\n\n.post-highlight.yellow {\n    background: #f8d347;\n    border-radius: 0px 4px 4px 0px;\n    -webkit-border-radius: 0px 4px 4px 0px;\n}\n\n.post-highlight.terques {\n    background: #41cac0;\n    border-radius: 4px 0px 0px 04px;\n    -webkit-border-radius: 4px 0px 0px 04px;\n}\n\n.post-info h1 {\n    margin: 0;\n    font-size: 18px;\n    color: #a19899;\n    font-weight: 300;\n}\n\n.post-highlight.terques h2 {\n    font-size: 16px;\n    color: #fff;\n    font-style: italic;\n    padding: 0 20px;\n    line-height: 22px;\n    margin: 0;\n    font-weight: 300;\n}\n\n.post-highlight.terques h2 span, .post-highlight.terques h2 a {\n    color: #92faf3;\n}\n\n.post-info h1 strong {\n    text-transform: uppercase;\n    color: #937b7b;\n}\n\n.post-info .desk {\n    display: inline-block;\n}\n\n.post-info .desk  h3{\n    font-size: 16px;\n}\n\n.post-info .desk.yellow h3 {\n    color:#f8d347 ;\n}\n\n.post-btn {\n\n}\n\n.post-btn a {\n    float: left;\n    margin-right: 8px;\n    font-size: 18px;\n    color: #9a9a9a;\n}\n\n.post-btn a:hover {\n    color: #727272;\n}\n\n.pro-thumb {\n    text-align: center;\n    display: inline-block;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    border: 10px solid rgba(256,256,256,0.4);\n}\n\n.pro-thumb img{\n    text-align: center;\n    width: 112px;\n    height: 112px;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n\n}\n\n.v-align {\n    vertical-align: middle !important;\n}\n\n.twite h1 {\n    margin: 50px 0;\n}\n\n\n.social-footer {\n    display: inline;\n    text-align: center;\n}\n\n.social-footer ul {\n    text-align: center;\n    margin: 0;\n    padding: 0;\n}\n\n.social-footer ul li {\n    display: inline-block;\n    margin: 0 20px;\n}\n\n.social-footer ul li a {\n    font-size: 25px;\n    color: #ceced0;\n}\n\n.social-footer ul li a:hover i.icon-facebook, .social-footer ul li.active a i.icon-facebook {\n    color: #486eac;\n}\n\n.social-footer ul li a:hover i.icon-twitter, .social-footer ul li.active a i.icon-twitter {\n    color: #58c9f3;\n}\n\n.social-footer ul li a:hover i.icon-google-plus, .social-footer ul li.active a i.icon-google-plus {\n    color: #4a4a4a;\n}\n\n.social-footer ul li a:hover i.icon-pinterest, .social-footer ul li.active a i.icon-pinterest {\n    color: #d1282d;\n}\n\n/*pie chart */\n\n.pie-foot {\n    background: #6b6b6b;\n    padding: 18px 15px;\n    color: #fff;\n    border-radius: 0 0 4px 4px;\n    -webkit-border-radius: 0 0 4px 4px;\n    text-align: center;\n    font-size: 16px;\n    font-weight: 300;\n}\n\n/*follower*/\n\n.follower {\n    background: #01a89e;\n    color: #fff;\n    text-align: center;\n    border-radius: 4px 4px 0 0;\n    -webkit-border-radius: 4px 4px 0 0;\n}\n\n.follower-foot {\n    padding: 8px 5px 5px 5px;\n    color: #757575;\n    border-radius: 0 0 4px 4px;\n    -webkit-border-radius: 0 0 4px 4px;\n    font-weight: 300;\n}\n\n.follower-foot ul {\n    padding: 0;\n    margin: 0;\n}\n.follower-foot ul li{\n    display: inline-block;\n    text-align: center;\n    width: 48%;\n    line-height: normal;\n}\n\n.follower-foot ul li h5{\n    margin: 5px 0 0 0;\n}\n\n.follower h4 {\n    margin: 0 0 10px 0;\n    font-size: 15px;\n    font-weight: 300;\n}\n\n.follow-ava {\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    border: 5px solid #18b2a6;\n    display: inline-block;\n}\n\n.follower img {\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    width: 62px;\n    height: 62px;\n    /*display: inline-block;*/\n}\n\n/*weather*/\n\n.weather-bg {\n    background: #8175c7;\n    border-radius: 4px 4px 0 0;\n    -webkit-border-radius: 4px 4px 0 0;\n    color: #fff;\n    text-align: center;\n    font-size: 16px;\n    font-weight: 300;\n}\n\n.weather-bg i {\n    font-size: 60px;\n    display: block;\n}\n\n.weather-bg .degree {\n    font-size: 60px;\n}\n\n.weather-category {\n    padding: 15px 0;\n    color: #74829C;\n}\n\n.weather-category ul {\n    padding:0;\n    margin: 0;\n    display: inline-block;\n    width: 100%;\n}\n\n.weather-category ul li {\n    display: inline-block;\n    width: 32%;\n    text-align: center;\n    border-right:1px solid #e6e6e6 ;\n    display: inline-block;\n}\n\n.weather-category ul li h5 {\n    margin: 0 0 5px 0;\n    text-transform: uppercase;\n    font-weight: 300;\n}\n\n.weather-category ul li a {\n\n}\n\n.weather-category ul li:last-child  {\n    border-right:none ;\n}\n\n/*fontawesome*/\n\n.fontawesome-icon-list h2 {\n    margin-top: 0;\n    font-size: 20px;\n    font-weight: 300;\n}\n\n.fontawesome-icon-list .col-sm-3 {\n    margin-bottom: 10px;\n}\n\n.fontawesome-icon-list .page-header {\n    border-bottom: 1px solid #C9CDD7;\n}\n\n.fontawesome-icon-list i {\n    font-size: 16px;\n    padding-right: 10px;\n}\n\n#web-application, #text-editor, #directional, #video-player, #brand, #medical, #currency {\n    margin-top: 10px;\n}\n\n/*mail inbox*/\n\n.mail-box {\n    border-collapse: collapse;\n    border-spacing: 0;\n    display: table;\n    table-layout: fixed;\n    width: 100%;\n}\n\n.mail-box aside {\n    display: table-cell;\n    float: none;\n    height: 100%;\n    padding: 0;\n    vertical-align: top;\n}\n\n.mail-box .sm-side {\n    width: 25%;\n    background: #e5e8ef;\n    border-radius: 4px 0 0 4px;\n    -webkit-border-radius: 4px 0 0 4px;\n}\n.mail-box .lg-side {\n    width: 75%;\n    background: #fff;\n    border-radius: 0px 4px 4px 0;\n    -webkit-border-radius: 0px 4px 4px 0;\n}\n\n.mail-box .sm-side .user-head {\n    background: #00a8b3;\n    border-radius: 4px 0px 0px 0;\n    -webkit-border-radius: 4px 0px 0px 0;\n    padding: 10px;\n    color: #fff;\n    min-height: 80px;\n}\n\n.user-head .inbox-avatar {\n    width: 65px;\n    float: left;\n}\n\n.user-head .inbox-avatar img {\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n}\n.user-head .user-name {\n    display: inline-block;\n    margin:0 0 0 10px;\n}\n\n.user-head .user-name h5 {\n    font-size: 14px;\n    margin-top: 15px;\n    margin-bottom: 0;\n    font-weight: 300;\n}\n.user-head .user-name h5 a {\n    color: #fff;\n}\n\n.user-head .user-name span a {\n    font-size: 12px;\n    color: #87e2e7;\n}\n\na.mail-dropdown {\n    background: #80d3d9;\n    padding:3px 5px;\n    font-size: 10px;\n    color: #01a7b3;\n    border-radius: 2px;\n    margin-top: 20px;\n}\n\n.inbox-body {\n    padding: 20px;\n}\n\n.btn-compose {\n    background: #ff6c60;\n    padding: 12px 0;\n    text-align: center;\n    width: 100%;\n    color: #fff;\n}\n.btn-compose:hover {\n    background: #f5675c;\n    color: #fff;\n}\n\nul.inbox-nav  {\n    display: inline-block;\n    width: 100%;\n    margin: 0;\n    padding: 0;\n}\n\n.inbox-divider {\n    border-bottom: 1px solid #d5d8df;\n}\n\nul.inbox-nav li {\n    display: inline-block;\n    line-height: 45px;\n    width: 100%;\n}\n\nul.inbox-nav li a  {\n    color: #6a6a6a;\n    line-height: 45px;\n    width: 100%;\n    display: inline-block;\n    padding: 0 20px;\n}\n\nul.inbox-nav li a:hover, ul.inbox-nav li.active a, ul.inbox-nav li a:focus  {\n    color: #6a6a6a;\n    background: #d5d7de;\n}\n\nul.inbox-nav li a i {\n    padding-right: 10px;\n    font-size: 16px;\n    color: #6a6a6a;\n}\n\nul.inbox-nav li a span.label {\n    margin-top: 13px;\n}\n\nul.labels-info li h4 {\n    padding-left:15px;\n    padding-right:15px;\n    padding-top: 5px;\n    color: #5c5c5e;\n    font-size: 13px;\n    text-transform: uppercase;\n}\n\nul.labels-info li  {\n    margin: 0;\n}\n\nul.labels-info li a {\n    color: #6a6a6a;\n    border-radius: 0;\n}\n\nul.labels-info li a:hover, ul.labels-info li a:focus {\n    color: #6a6a6a;\n    background: #d5d7de;\n}\n\nul.labels-info li a i {\n    padding-right: 10px;\n}\n\n.nav.nav-pills.nav-stacked.labels-info p {\n    margin-bottom: 0;\n    padding: 0 22px;\n    color: #9d9f9e;\n    font-size: 11px;\n}\n\n.inbox-head {\n    padding:20px;\n    background: #41cac0;\n    color: #fff;\n    border-radius: 0 4px 0 0;\n    -webkit-border-radius: 0 4px 0 0;\n    min-height: 80px;\n}\n\n.inbox-head  h3 {\n    margin: 0;\n    display: inline-block;\n    padding-top: 6px;\n    font-weight: 300;\n}\n\n.inbox-head  .sr-input {\n    height: 40px;\n    border: none;\n    box-shadow: none;\n    padding: 0 10px;\n    float: left;\n    border-radius: 4px 0 0 4px;\n    color: #8a8a8a;\n}\n.inbox-head  .sr-btn {\n    height: 40px;\n    border: none;\n    background: #00a6b2;\n    color: #fff;\n    padding: 0 20px;\n    border-radius: 0 4px 4px 0;\n    -webkit-border-radius: 0 4px 4px 0;\n}\n\n.table-inbox {\n    border: 1px solid #d3d3d3;\n    margin-bottom: 0;\n}\n\n.table-inbox tr td{\n    padding: 12px !important;\n}\n\n.table-inbox tr td:hover{\n    cursor: pointer;\n}\n\n.table-inbox tr td .icon-star.inbox-started ,.table-inbox tr td .icon-star:hover{\n    color: #f78a09;\n}\n\n.table-inbox tr td .icon-star{\n    color: #d5d5d5;\n}\n\n.table-inbox tr.unread td {\n    font-weight: 600;\n    background: #f7f7f7;\n}\n\nul.inbox-pagination  {\n    float: right;\n}\n\nul.inbox-pagination li {\n    float: left;\n}\n\n.mail-option {\n    display: inline-block;\n    margin-bottom: 10px;\n    width: 100%;\n}\n\n.mail-option .chk-all, .mail-option .btn-group {\n    margin-right: 5px;\n}\n\n.mail-option .chk-all, .mail-option .btn-group a.btn {\n    border: 1px solid #e7e7e7;\n    padding: 5px 10px;\n    display: inline-block;\n    background: #fcfcfc;\n    color: #afafaf;\n    border-radius: 3px !important;\n    -webkit-border-radius: 3px !important;\n}\n.inbox-pagination a.np-btn  {\n    border: 1px solid #e7e7e7;\n    padding: 5px 15px;\n    display: inline-block;\n    background: #fcfcfc;\n    color: #afafaf;\n    border-radius: 3px !important;\n    -webkit-border-radius: 3px !important;\n}\n\n.mail-option .chk-all input[type=checkbox] {\n    margin-top: 0;\n}\n\n.mail-option .btn-group a.all {\n    padding: 0;\n    border: none;\n}\n\n.inbox-pagination a.np-btn {\n    margin-left: 5px;\n}\n\n.inbox-pagination li span {\n    display: inline-block;\n    margin-top: 7px;\n    margin-right: 5px;\n}\n\n.fileinput-button {\n    border: 1px solid #e6e6e6;\n    background: #eeeeee;\n}\n\n.inbox-body .modal .modal-body input, .inbox-body .modal .modal-body textarea{\n    border: 1px solid #e6e6e6;\n    box-shadow: none;\n}\n\n.btn-send, .btn-send:hover {\n    background: #00A8B3;\n    color: #fff;\n}\n\n.btn-send:hover {\n    background: #009da7;\n}\n\n.modal-header h4.modal-title {\n    font-weight: 300;\n    font-family: 'Open Sans', sans-serif;\n}\n\n.modal-body label {\n    font-weight: 400;\n    font-family: 'Open Sans', sans-serif;\n}\n\n\n/*404 page*/\n\n.body-404 {\n    background: #18d4cb;\n    color: #fff;\n}\n\n\n.error-wrapper {\n    text-align: center;\n    margin-top: 10%;\n}\n\n.error-wrapper .icon-404{\n    background: url(\"../img/404_icon.png\") no-repeat;\n    width: 289px;\n    height: 274px;\n    display: inline-block;\n    margin-left: 30px;\n}\n\n\n.error-wrapper h1 {\n    font-size: 90px;\n    font-weight: 300;\n    margin: -50px 0 0 0;\n}\n\n.error-wrapper h2 {\n    font-size: 20px;\n    font-weight: 300;\n    margin: 0 0 30px 0;\n}\n\n.error-wrapper p, .error-wrapper p a {\n    font-size: 18px;\n    font-weight: 300;\n}\n\n.error-wrapper p.page-404  {\n    color: #7dfff7;\n}\n\n.error-wrapper p.page-404 a, .error-wrapper p.page-500 a,  .error-wrapper p.page-404 a:hover, .error-wrapper p.page-500 a:hover {\n    color: #fff;\n}\n\n\n/*500 page*/\n\n.body-500 {\n    background: #8075c6;\n    color: #fff;\n}\n\n.error-wrapper p.page-500 {\n    color: #afa5f1;\n}\n\n.error-wrapper .icon-500{\n    background: url(\"../img/500_icon.png\") no-repeat;\n    width: 289px;\n    height: 274px;\n    display: inline-block;\n    margin-left: 55px;\n}\n\n/*profile*/\n\n.profile-nav .user-heading {\n    background: #ff766c;\n    color: #fff;\n    border-radius: 4px 4px 0 0;\n    -webkit-border-radius: 4px 4px 0 0;\n    padding: 30px;\n    text-align: center;\n}\n\n.profile-nav .user-heading.round a  {\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    border: 10px solid rgba(256,256,256,0.3);\n    display: inline-block;\n}\n\n.profile-nav .user-heading a img {\n    width: 112px;\n    height: 112px;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n}\n\n.profile-nav .user-heading h1 {\n    font-size: 22px;\n    font-weight: 300;\n    margin-bottom: 5px;\n}\n\n.profile-nav .user-heading p {\n    font-size: 12px;\n}\n\n.profile-nav ul {\n    margin-top: 1px;\n}\n\n.profile-nav ul > li {\n    border-bottom: 1px solid #ebeae6;\n    margin-top: 0;\n    line-height: 30px;\n}\n\n.profile-nav ul > li:last-child {\n    border-bottom: none;\n}\n\n.profile-nav ul > li > a {\n    border-radius: 0;\n    -webkit-border-radius: 0;\n    color: #89817f;\n    border-left: 5px solid #fff;\n}\n\n.profile-nav ul > li > a:hover, .profile-nav ul > li > a:focus, .profile-nav ul li.active  a {\n    background: #f8f7f5 !important;\n    border-left: 5px solid #ff766c;\n    color: #89817f !important;\n}\n\n.profile-nav ul > li:last-child > a:last-child {\n    border-radius: 0 0 4px 4px;\n    -webkit-border-radius: 0 0 4px 4px;\n}\n\n.profile-nav ul > li > a > i{\n    font-size: 16px;\n    padding-right: 10px;\n    color: #bcb3aa;\n}\n\n.r-activity {\n    margin: 6px 0 0;\n    font-size: 12px;\n}\n\n\n.p-text-area, .p-text-area:focus {\n    border: none;\n    font-weight: 300;\n    box-shadow: none;\n    color: #c3c3c3;\n    font-size: 16px;\n}\n\n.profile-info .panel-footer {\n    background-color:#f8f7f5 ;\n    border-top: 1px solid #e7ebee;\n}\n\n.profile-info .panel-footer ul li a {\n    color: #7a7a7a;\n}\n\n.bio-graph-heading {\n    background: #41cac0;\n    color: #fff;\n    text-align: center;\n    font-style: italic;\n    padding: 40px 110px;\n    border-radius: 4px 4px 0 0;\n    -webkit-border-radius: 4px 4px 0 0;\n    font-size: 16px;\n    font-weight: 300;\n}\n\n.bio-graph-info {\n    color: #89817e;\n}\n\n.bio-graph-info h1 {\n    font-size: 22px;\n    font-weight: 300;\n    margin: 0 0 20px;\n}\n\n.bio-row {\n    width: 50%;\n    float: left;\n    margin-bottom: 10px;\n    padding:0 15px;\n}\n\n.bio-row p span {\n    width: 100px;\n    display: inline-block;\n}\n\n.bio-chart, .bio-desk {\n    float: left;\n}\n\n.bio-chart {\n    width: 40%;\n}\n\n.bio-desk {\n    width: 60%;\n}\n\n.bio-desk h4 {\n    font-size: 15px;\n    font-weight:400;\n}\n\n.bio-desk h4.terques {\n    color: #4CC5CD;\n}\n\n.bio-desk h4.red {\n    color: #e26b7f;\n}\n\n.bio-desk h4.green {\n    color: #97be4b;\n}\n\n.bio-desk h4.purple {\n    color: #caa3da;\n}\n\n.file-pos {\n    margin: 6px 0 10px 0;\n}\n\n.profile-activity h5 {\n    font-weight: 300;\n    margin-top: 0;\n    color: #c3c3c3;\n}\n\n.summary-head {\n    background: #ee7272;\n    color: #fff;\n    text-align: center;\n    border-bottom: 1px solid #ee7272;\n}\n\n.summary-head h4 {\n    font-weight: 300;\n    text-transform: uppercase;\n    margin-bottom: 5px;\n}\n\n.summary-head p {\n    color: rgba(256,256,256,0.6);\n}\n\nul.summary-list {\n    display: inline-block;\n    padding-left:0 ;\n    width: 100%;\n    margin-bottom: 0;\n}\n\nul.summary-list > li {\n    display: inline-block;\n    width: 19.5%;\n    text-align: center;\n}\n\nul.summary-list > li > a > i {\n    display:block;\n    font-size: 18px;\n    padding-bottom: 5px;\n}\n\nul.summary-list > li > a {\n    padding: 10px 0;\n    display: inline-block;\n    color: #818181;\n}\n\nul.summary-list > li  {\n    border-right: 1px solid #eaeaea;\n}\n\nul.summary-list > li:last-child  {\n    border-right: none;\n}\n\n.activity {\n    width: 100%;\n    float: left;\n    margin-bottom: 10px;\n}\n\n.activity.alt {\n    width: 100%;\n    float: right;\n    margin-bottom: 10px;\n}\n\n.activity span {\n    float: left;\n}\n\n.activity.alt span {\n    float: right;\n}\n.activity span, .activity.alt span {\n    width: 45px;\n    height: 45px;\n    line-height: 45px;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    background: #eee;\n    text-align: center;\n    color: #fff;\n    font-size: 16px;\n}\n\n.activity.terques span {\n    background: #8dd7d6;\n}\n\n.activity.terques h4 {\n    color: #8dd7d6;\n}\n.activity.purple span {\n    background: #b984dc;\n}\n\n.activity.purple h4 {\n    color: #b984dc;\n}\n.activity.blue span {\n    background: #90b4e6;\n}\n\n.activity.blue h4 {\n    color: #90b4e6;\n}\n.activity.green span {\n    background: #aec785;\n}\n\n.activity.green h4 {\n    color: #aec785;\n}\n\n.activity h4 {\n    margin-top:0 ;\n    font-size: 16px;\n}\n\n.activity p {\n    margin-bottom: 0;\n    font-size: 13px;\n}\n\n.activity .activity-desk i, .activity.alt .activity-desk i {\n    float: left;\n    font-size: 18px;\n    margin-right: 10px;\n    color: #bebebe;\n}\n\n.activity .activity-desk {\n    margin-left: 70px;\n    position: relative;\n}\n\n.activity.alt .activity-desk {\n    margin-right: 70px;\n    position: relative;\n}\n\n.activity.alt .activity-desk .panel {\n    float: right;\n    position: relative;\n}\n\n.activity-desk .panel {\n    background: #F4F4F4 ;\n    display: inline-block;\n}\n\n\n.activity .activity-desk .arrow {\n    border-right: 8px solid #F4F4F4 !important;\n}\n.activity .activity-desk .arrow {\n    border-bottom: 8px solid transparent;\n    border-top: 8px solid transparent;\n    display: block;\n    height: 0;\n    left: -7px;\n    position: absolute;\n    top: 13px;\n    width: 0;\n}\n\n.activity-desk .arrow-alt {\n    border-left: 8px solid #F4F4F4 !important;\n}\n\n.activity-desk .arrow-alt {\n    border-bottom: 8px solid transparent;\n    border-top: 8px solid transparent;\n    display: block;\n    height: 0;\n    right: -7px;\n    position: absolute;\n    top: 13px;\n    width: 0;\n}\n\n.activity-desk .album {\n    display: inline-block;\n    margin-top: 10px;\n}\n\n.activity-desk .album a{\n    margin-right: 10px;\n}\n\n.activity-desk .album a:last-child{\n    margin-right: 0px;\n}\n\n/*invoice*/\n\n.invoice-list  {\n    margin-bottom: 30px;\n}\n\n.invoice-list h4 {\n    font-weight: 300;\n    font-size: 16px;\n}\n\n.invoice-block {\n    text-align: right;\n}\n\nul.amounts li {\n    background: #f5f5f5;\n    margin-bottom: 5px;\n    padding: 10px;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n    font-weight: 300;\n}\n\n.invoice-btn a{\n    font-weight: 300;\n    margin: 0 5px;\n    font-size: 16px;\n}\n\n.corporate-id {\n    margin-bottom: 30px;\n}\n\n/*panel heading color*/\n\n.panel-primary > .panel-heading.navyblue {\n    background-color: #2A3542;\n    border-color: #2A3542;\n    color: #FFFFFF;\n}\n\n/*table*/\n\n.table-advance tr td {\n    vertical-align: middle !important;\n}\n\n.no-border {\n    border-bottom: none;\n}\n\n.dataTables_length , .dataTables_filter{\n    padding:15px;\n}\n.dataTables_info{\n    padding:0 15px;\n}\n\n.dataTables_filter {\n    float: right;\n}\n\n.dataTables_length select {\n    width: 65px;\n    padding:5px 8px;\n}\n\n.dataTables_length label, .dataTables_filter label {\n    font-weight: 300;\n}\n\n.dataTables_filter label {\n    width: 100%;\n}\n\n.dataTables_filter label input {\n    width: 78%;\n}\n\n.border-top {\n    border-top: 1px solid #ddd;\n}\n\n.dataTables_paginate.paging_bootstrap.pagination li {\n    float: left;\n    margin: 0 1px;\n    border: 1px solid #ddd;\n    border-radius: 3px;\n    -webkit-border-radius: 3px;\n}\n\n.dataTables_paginate.paging_bootstrap.pagination li.disabled a{\n    color: #c7c7c7;\n}\n.dataTables_paginate.paging_bootstrap.pagination li a{\n    color: #797979;\n    padding: 5px 10px;\n    display: inline-block;\n}\n\n.dataTables_paginate.paging_bootstrap.pagination li:hover a, .dataTables_paginate.paging_bootstrap.pagination li.active a{\n    color: #797979;\n    background: #eee;\n    border-radius: 3px;\n    -webkit-border-radius: 3px;\n}\n\n.dataTables_paginate.paging_bootstrap.pagination {\n    float: right;\n    margin-right: 15px;\n    margin-top: -5px;\n    margin-bottom: 15px;\n\n}\n\n.dataTable tr:last-child {\n    border-bottom: 1px solid #ddd;\n}\n\n/*calender*/\n\n.has-toolbar.fc {\n    margin-top: 50px;\n}\n\n.fc-header-title {\n    display: inline-block;\n    margin-top: -50px;\n    vertical-align: top;\n}\n\n.fc-view {\n    margin-top: -50px;\n    overflow: hidden;\n    width: 100%;\n}\n\n.fc-state-default, .fc-state-default .fc-button-inner {\n    background: #F3F3F3 !important;\n    border-color: #DDDDDD;\n    border-style: none solid;\n    color: #646464;\n}\n\n.fc-state-active, .fc-state-active .fc-button-inner,\n.fc-state-hover, .fc-state-hover .fc-button-inner{\n    background:  #FF6C60 !important;\n    color: #fff !important;\n}\n\n.fc-event-skin {\n    background-color: #6883a3 !important;\n    border-color: #6883a3 !important;\n    color: #FFFFFF !important;\n}\n\n.fc-grid th {\n    height: 30px;\n    line-height: 30px;\n    text-align: center;\n    background: #F3F3F3 !important;\n}\n\n.fc-header-title h2 {\n    font-size: 20px !important;\n    color: #C8CCD7;\n    font-weight: 300;\n}\n\n.external-event {\n    cursor: move;\n    display: inline-block !important;\n    margin-bottom: 6px !important;\n    margin-right: 6px !important;\n    padding: 8px;\n}\n\n#external-events p input[type=\"checkbox\"]{\n    margin: 0;\n}\n\n.drg-event-title {\n    font-weight: 300;\n    margin-top: 0;\n    margin-bottom: 15px;\n    border-bottom: 1px solid #ddd;\n    padding-bottom: 10px;\n}\n\n.fc-content .fc-event {\n    border-radius:4px;\n    webkit-border-radius:4px;\n    padding: 4px 6px;\n}\n\n.fc-corner-left {\n    border-radius: 4px 0 0 4px;\n    -webkit-border-radius: 4px 0 0 4px;\n}\n\n.fc-corner-right {\n    border-radius: 0 4px 4px 0;\n    -webkit-border-radius: 0 4px 4px 0;\n}\n\n.drp-rmv {\n    padding-top: 10px;\n    margin-top: 10px;\n}\n\n\n/*button*/\n\n.btn-row {\n    margin-bottom: 10px;\n}\n\n/*tabs*/\n\n.tab-head {\n    background: #7087a3;\n    display: inline-block;\n    width: 100%;\n    margin-top: 60px;\n}\n\n.tab-container {\n    margin-top: 10px;\n}\n\n.tab-head .nav-tabs > li > a {\n    border-radius: 0;\n    margin-right: 1px;\n    color: #fff;\n}\n\n.tab-head .nav-tabs > li.active > a, .tab-head .nav-tabs > li > a:hover, .tab-head .nav-tabs > li.active > a:hover, .tab-head .nav-tabs > li.active > a:focus {\n    background-color: #f1f2f7;\n    border-color: #f1f2f7;\n    color: #797979;\n}\n\n/*general page*/\n\n.progress-xs {\n    height: 8px;\n}\n\n.progress-sm {\n    height: 12px;\n}\n\n.panel-heading .nav {\n    border: medium none;\n    font-size: 13px;\n    margin: -10px -15px -11px;\n}\n\n.tab-bg-dark-navy-blue {\n    background: #7087A3;\n    border-radius: 5px 5px 0 0;\n    -webkit-border-radius: 5px 5px 0 0;\n    border-bottom: none;\n}\n\n.panel-heading .nav > li > a,\n.panel-heading .nav > li.active > a, .panel-heading .nav > li.active > a:hover, .panel-heading .nav > li.active > a:focus {\n    border-width: 0;\n    border-radius: 0;\n}\n\n.panel-heading .nav > li > a {\n    color: #fff;\n}\n\n.panel-heading .nav > li.active > a, .panel-heading .nav > li > a:hover {\n    color: #47596f;\n    background: #fff;\n}\n\n.panel-heading .nav > li:first-child.active > a, .panel-heading .nav > li:first-child > a:hover {\n    border-radius: 4px 0 0 0;\n    -webkit-border-radius: 4px 0 0 0;\n}\n\n\n.tab-right {\n    height: 38px;\n}\n\n.panel-heading.tab-right .nav > li:first-child.active > a, .tab-right.panel-heading .nav > li:first-child > a:hover {\n    border-radius:  0 ;\n    -webkit-border-radius: 0 ;\n}\n\n.panel-heading.tab-right .nav > li:last-child.active > a, .tab-right.panel-heading .nav > li:last-child > a:hover {\n    border-radius:  0 4px 0 0;\n    -webkit-border-radius: 0 4px 0 0;\n}\n\n.panel-heading.tab-right .nav-tabs > li > a {\n    margin-left: 1px;\n    margin-right: 0px;\n}\n\n.m-bot20 {\n    margin-bottom: 20px;\n}\n\n.m-bot-none {\n    margin-bottom: 0;\n}\n\n.wht-color {\n    color: #fff;\n}\n\n.close-sm {\n    font-size: 14px;\n}\n\n/*carousel*/\n\n.carousel-indicators li {\n    background:  rgba(0, 0, 0, 0.2) ;\n    border:  none;\n    transition:background-color 0.25s ease 0s;\n    -moz-transition:background-color 0.25s ease 0s;\n    -webkit-transition:background-color 0.25s ease 0s;\n}\n\n.carousel-indicators .active {\n    background:#ff6c60;\n    height: 10px;\n    margin: 1px;\n    width: 10px;\n}\n\n.carousel-indicators.out {\n    bottom: -5px;\n}\n\n.carousel-indicators.out {\n    bottom: -5px;\n}\n\n.carousel-control {\n    color: #999999;\n    text-shadow: none;\n    width: 45px;\n}\n\n.carousel-control i {\n    display: inline-block;\n    height: 25px;\n    left: 50%;\n    margin-left: -10px;\n    margin-top: -10px;\n    position: absolute;\n    top: 50%;\n    width: 20px;\n    z-index: 5;\n}\n\n\n.carousel-control.left, .carousel-control.right {\n    background: none;\n    filter:none;\n}\n\n.carousel-control:hover, .carousel-control:focus {\n    color: #CCCCCC;\n    opacity: 0.9;\n    text-decoration: none;\n}\n\n.carousel-inner h3 {\n    font-weight: 300;\n    font-size: 16px;\n    margin: 0;\n}\n\n.carousel-inner {\n    margin-bottom: 15px;\n}\n\n/*gritter*/\n.gritter-close {\n    left: auto !important;\n    right: 3px !important;\n}\n\n\n/*form*/\n\n\n.sm-input {\n    width: 175px;\n}\n\n.form-horizontal.tasi-form .form-group {\n    border-bottom: 1px solid #eff2f7;\n    padding-bottom: 15px;\n    margin-bottom: 15px;\n}\n\n.form-horizontal.tasi-form .form-group:last-child {\n    border-bottom: none;\n    padding-bottom: 0px;\n    margin-bottom: 0px;\n}\n\n\n.form-horizontal.tasi-form .form-group .help-block {\n    margin-bottom: 0;\n}\n\n\n.round-input {\n    border-radius: 500px;\n    -webkit-border-radius: 500px;\n}\n\n\n.m-bot15 {\n    margin-bottom: 15px;\n}\n\n.form-horizontal.tasi-form .checkbox-inline > input {\n    margin-top: 1px;\n    border:none;\n}\n\n\n/*form validation*/\n\n.cmxform .form-group label.error {\n    display: inline;\n    margin: 5px 0;\n    color: #B94A48;\n    font-weight: 400;\n}\n\ninput:focus:invalid:focus, textarea:focus:invalid:focus, select:focus:invalid:focus, .cmxform .form-group input.error , .cmxform .form-group textarea.error{\n    border-color: #B94A48 !important;\n}\n\n#signupForm label.error {\n    display: inline;\n    margin:5px 0px;\n    width: auto;\n    color: #B94A48;\n}\n\n.checkbox, .checkbox:hover, .checkbox:focus  {\n    border:none;\n}\n\n\n/*slider*/\ntable.sliders tr td {\n    padding: 30px 0;\n    border:none;\n}\n\n.slider {\n    margin-top: 3px;\n}\n\n.slider-info {\n    padding-top: 10px;\n}\n\n.sliders .ui-widget-header {\n    background: #22bacf !important;\n    border-radius: 15px !important;\n    -webkit-border-radius: 15px !important;\n}\n\n.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br {\n    border-bottom-right-radius: 0 !important;\n}\n.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl {\n    border-bottom-left-radius: 0 !important;\n}\n.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr {\n    border-top-right-radius: 0 !important;\n}\n.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl {\n    border-top-left-radius: 0 !important;\n}\n\n\n#eq span {\n    height:120px; float:left; margin:15px\n}\n\n\n.ui-widget-content {\n    background: #f0f2f7 !important;\n    border: none !important;\n    border-radius: 15px !important;\n    -webkit-border-radius: 15px !important;\n}\n\n.ui-slider-horizontal {\n    height: 8px !important;\n}\n\n.ui-slider-horizontal .ui-slider-handle {\n    top: -0.57em   !important;\n}\n\n.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default {\n    background: #fff !important;\n    border: 3px solid #22bacf !important;\n    border-radius: 50% !important;\n    -webkit-border-radius: 50% !important;\n}\n\n.ui-slider-vertical {\n    width: 8px !important;\n}\n\n.ui-slider-vertical .ui-slider-handle {\n    left: -0.5em  !important;\n}\n\n.ui-slider .ui-slider-handle {\n    cursor: default;\n    height: 1.6em;\n    position: absolute;\n    width: 1.6em;\n    z-index: 2;\n}\n\n.bound-s {\n    width: 90px;\n    margin-bottom: 15px;\n}\n\n\n/*----switch ----*/\n\n\n.has-switch {\n    border-radius: 30px;\n    -webkit-border-radius: 30px;\n    display: inline-block;\n    cursor: pointer;\n    line-height: 1.231;\n    overflow: hidden;\n    position: relative;\n    text-align: left;\n    width: 80px;\n    -webkit-mask: url('../img/mask.png') 0 0 no-repeat;\n    mask: url('../img/mask.png') 0 0 no-repeat;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n    -o-user-select: none;\n    user-select: none;\n}\n.has-switch.deactivate {\n    opacity: 0.5;\n    filter: alpha(opacity=50);\n    cursor: default !important;\n}\n.has-switch.deactivate label,\n.has-switch.deactivate span {\n    cursor: default !important;\n}\n.has-switch > div {\n    width: 162%;\n    position: relative;\n    top: 0;\n}\n.has-switch > div.switch-animate {\n    -webkit-transition: left 0.25s ease-out;\n    -moz-transition: left 0.25s ease-out;\n    -o-transition: left 0.25s ease-out;\n    transition: left 0.25s ease-out;\n    -webkit-backface-visibility: hidden;\n}\n.has-switch > div.switch-off {\n    left: -63%;\n}\n.has-switch > div.switch-off label {\n    background-color: #7f8c9a;\n    border-color: #bdc3c7;\n    -webkit-box-shadow: -1px 0 0 rgba(255, 255, 255, 0.5);\n    -moz-box-shadow: -1px 0 0 rgba(255, 255, 255, 0.5);\n    box-shadow: -1px 0 0 rgba(255, 255, 255, 0.5);\n}\n.has-switch > div.switch-on {\n    left: 0%;\n}\n.has-switch > div.switch-on label {\n    background-color: #41cac0;\n}\n.has-switch input[type=checkbox] {\n    display: none;\n}\n.has-switch span {\n    cursor: pointer;\n    font-size: 14.994px;\n    font-weight: 700;\n    float: left;\n    height: 29px;\n    line-height: 19px;\n    margin: 0;\n    padding-bottom: 6px;\n    padding-top: 5px;\n    position: relative;\n    text-align: center;\n    width: 50%;\n    z-index: 1;\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    -webkit-transition: 0.25s ease-out;\n    -moz-transition: 0.25s ease-out;\n    -o-transition: 0.25s ease-out;\n    transition: 0.25s ease-out;\n    -webkit-backface-visibility: hidden;\n}\n.has-switch span.switch-left {\n    border-radius: 30px 0 0 30px;\n    background-color: #2A3542;\n    color: #41cac0;\n    border-left: 1px solid transparent;\n}\n.has-switch span.switch-right {\n    border-radius: 0 30px 30px 0;\n    background-color: #bdc3c7;\n    color: #ffffff;\n    text-indent: 7px;\n}\n.has-switch span.switch-right [class*=\"fui-\"] {\n    text-indent: 0;\n}\n.has-switch label {\n    border: 4px solid #2A3542;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    float: left;\n    height: 29px;\n    margin: 0 -21px 0 -14px;\n    padding: 0;\n    position: relative;\n    vertical-align: middle;\n    width: 29px;\n    z-index: 100;\n    -webkit-transition: 0.25s ease-out;\n    -moz-transition: 0.25s ease-out;\n    -o-transition: 0.25s ease-out;\n    transition: 0.25s ease-out;\n    -webkit-backface-visibility: hidden;\n}\n.switch-square {\n    border-radius: 6px;\n    -webkit-border-radius: 6px;\n    -webkit-mask: url('../img/mask.png') 0 0 no-repeat;\n    mask: url('../img/mask.png') 0 0 no-repeat;\n}\n.switch-square > div.switch-off label {\n    border-color: #7f8c9a;\n    border-radius: 6px 0 0 6px;\n}\n.switch-square span.switch-left {\n    border-radius: 6px 0 0 6px;\n}\n.switch-square span.switch-left [class*=\"fui-\"] {\n    text-indent: -10px;\n}\n.switch-square span.switch-right {\n    border-radius: 0 6px 6px 0;\n}\n.switch-square span.switch-right [class*=\"fui-\"] {\n    text-indent: 5px;\n}\n.switch-square label {\n    border-radius: 0 6px 6px 0;\n    border-color: #41cac0;\n}\n\n\n/*tag input*/\n\n.tagsinput {\n    border: 1px solid #e3e6ed;\n    border-radius: 6px;\n    height: 100px;\n    padding: 6px 1px 1px 6px;\n    overflow-y: auto;\n    text-align: left;\n}\n.tagsinput .tag {\n    border-radius: 4px;\n    background-color: #41cac0;\n    color: #ffffff;\n    cursor: pointer;\n    margin-right: 5px;\n    margin-bottom: 5px;\n    overflow: hidden;\n    line-height: 15px;\n    padding: 6px 13px 8px 19px;\n    position: relative;\n    vertical-align: middle;\n    display: inline-block;\n    zoom: 1;\n    *display: inline;\n    -webkit-transition: 0.14s linear;\n    -moz-transition: 0.14s linear;\n    -o-transition: 0.14s linear;\n    transition: 0.14s linear;\n    -webkit-backface-visibility: hidden;\n}\n.tagsinput .tag:hover {\n    background-color: #39b1a8;\n    color: #ffffff;\n    padding-left: 12px;\n    padding-right: 20px;\n}\n.tagsinput .tag:hover .tagsinput-remove-link {\n    color: #ffffff;\n    opacity: 1;\n    display: block\\9;\n}\n.tagsinput input {\n    background: transparent;\n    border: none;\n    color: #34495e;\n    font-family: \"Lato\", sans-serif;\n    font-size: 14px;\n    margin: 0px;\n    padding: 0 0 0 5px;\n    outline: 0;\n    margin-right: 5px;\n    margin-bottom: 5px;\n    width: 12px;\n}\n.tagsinput-remove-link {\n    bottom: 0;\n    color: #ffffff;\n    cursor: pointer;\n    font-size: 12px;\n    opacity: 0;\n    padding: 7px 7px 5px 0;\n    position: absolute;\n    right: 0;\n    text-align: right;\n    text-decoration: none;\n    top: 0;\n    width: 100%;\n    z-index: 2;\n    display: none\\9;\n}\n.tagsinput-remove-link:before {\n    color: #ffffff;\n    content: \"\\f00d\";\n    font-family: \"FontAwesome\";\n}\n.tagsinput-add-container {\n    vertical-align: middle;\n    display: inline-block;\n    zoom: 1;\n    *display: inline;\n}\n.tagsinput-add {\n    background-color: #d6dbdf;\n    border-radius: 3px;\n    color: #ffffff;\n    cursor: pointer;\n    margin-bottom: 5px;\n    padding: 6px 9px;\n    display: inline-block;\n    zoom: 1;\n    *display: inline;\n    -webkit-transition: 0.25s;\n    -moz-transition: 0.25s;\n    -o-transition: 0.25s;\n    transition: 0.25s;\n    -webkit-backface-visibility: hidden;\n}\n.tagsinput-add:hover {\n    background-color: #3bb8af;\n}\n.tagsinput-add:before {\n    content: \"\\f067\";\n    font-family: \"FontAwesome\";\n}\n.tags_clear {\n    clear: both;\n    width: 100%;\n    height: 0px;\n}\n\n\n/*checkbox & radio style*/\n\n\n.checkboxes label, .radios label {\n    display: block;\n    cursor: pointer;\n    line-height: 20px;\n    padding-bottom: 7px;\n    font-weight: 300;\n}\n\n.radios {\n    padding-top: 18px;\n}\n\n.label_check input,\n.label_radio input {\n    margin-right: 5px;\n}\n\n.has-js .label_check,\n.has-js .label_radio {\n    padding-left: 34px;\n}\n\n.has-js .label_radio {\n    background: url(../img/checkbox/radio-off.png) no-repeat;\n}\n\n.has-js .label_check {\n    background: url(../img/checkbox/check-off.png) no-repeat;\n}\n\n.has-js label.c_on {\n    background: url(../img/checkbox/check-on.png) no-repeat;\n}\n\n.has-js label.r_on {\n    background: url(../img/checkbox/radio-on.png) no-repeat;\n}\n\n.has-js .label_check input,\n.has-js .label_radio input {\n    position: absolute;\n    left: -9999px;\n}\n\n/*date picker*/\n\n.add-on {\n    float: right;\n    margin-top: -37px;\n    padding: 3px;\n    text-align: center;\n}\n\n.add-on .btn {\n    padding: 9px;\n}\n\n.daterangepicker .ranges .range_inputs > div:nth-child(2) {\n    margin-bottom: 10px;\n    padding-left: 0px;\n}\n\n.daterangepicker .ranges label {\n    padding-bottom: 0;\n    padding-top: 8px;\n}\n\n\n.daterangepicker td.active, .daterangepicker td.active:hover,\n.datepicker td.active:hover, .datepicker td.active:hover:hover, .datepicker td.active:active, .datepicker td.active:hover:active, .datepicker td.active.active, .datepicker td.active.active:hover, .datepicker td.active.disabled, .datepicker td.active.disabled:hover, .datepicker td.active[disabled], .datepicker td.active[disabled]:hover,\n.datepicker td span.active:hover, .datepicker td span.active:active, .datepicker td span.active.active, .datepicker td span.active.disabled, .datepicker td span.active[disabled]{\n    background: #41CAC0;\n}\n\n.daterangepicker .calendar th, .daterangepicker .calendar td {\n    font-family: 'Open Sans', sans-serif;\n    font-weight: 300;\n    text-align: center;\n    white-space: nowrap;\n}\n\n.daterangepicker td.active, .daterangepicker td.active:hover, .datepicker td.active, .datepicker td.active:hover, .datepicker td span.active {\n    text-shadow: none;\n}\n\n.datepicker th.switch {\n    width: 125px;\n}\n\n.datepicker td span {\n    height: 40px;\n    line-height: 40px;\n}\n\n\n.bootstrap-timepicker table td input {\n    border: 1px solid #ccc;\n    border-radius:3px;\n    -webkit-border-radius:3px;\n}\n\n\n/*ck editor*/\n\n.cke_top, .cke_bottom {\n    background: #F5F5F5 !important;\n    background: -moz-linear-gradient(center top , #F5F5F5, #F5F5F5) repeat scroll 0 0 #F5F5F5 !important;\n    background: -webkit-linear-gradient(center top , #F5F5F5, #F5F5F5) repeat scroll 0 0 #F5F5F5 !important;\n    background: -o-linear-gradient(center top , #F5F5F5, #F5F5F5) repeat scroll 0 0 #F5F5F5 !important;\n    box-shadow: none;\n    padding: 6px 8px 2px;\n}\n\n.cke_top {\n    border-bottom: 1px solid #cccccc !important;\n}\n\n.cke_chrome {\n    display: block;\n    padding: 0;\n}\n\n/*form wizard*/\n\n.stepy-tab {\n    text-align: center;\n}\n\n.stepy-tab ul{\n    display: inline-block;\n}\n\n.stepy-tab ul li {\n    float: left;\n}\n\n.step legend {\n    border: none;\n}\n\n.button-back {\n    float: left;\n}\n\n.button-next, .finish {\n    float: right;\n}\n\n.button-back, .button-next, .finish {\n    cursor: pointer;  text-decoration: none;\n}\n\n.step {\n    clear: left;\n}\n.step label {\n    display: block;\n}\n\n\n.stepy-titles li {\n    color: #757575;\n    cursor: pointer;\n    float: left;\n    margin: 10px 15px;\n}\n\n.stepy-titles li span { display: block; }\n\n.stepy-titles li.current-step div {\n    color: #fff;\n    cursor: auto;\n    background: #A9D86E;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    width: 100px;\n    height: 100px;\n    line-height: 100px;\n}\n\n.stepy-titles li div{\n    font-size:16px;\n    font-weight: 300;\n    background: #eee;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    width: 100px;\n    height: 100px;\n    line-height: 100px;\n}\n\n\n/*widget*/\n\n.user-heading.alt {\n    display: inline-block;\n    width: 100%;\n    text-align: left;\n}\n\n.alt.green-bg {\n    background: #aec785;\n}\n\n.profile-nav.alt.green-border ul > li > a:hover, .profile-nav.alt.green-border ul > li > a:focus, .profile-nav.alt.green-border ul li.active a {\n    border-left: 5px solid #aec785;\n}\n\n.user-heading.alt a {\n    float: left;\n    margin-right: 15px;\n    margin-left: -10px;\n    display: inline-block;\n    border: 5px solid rgba(255, 255, 255, 0.3);\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n}\n.user-heading.alt a img{\n    width: 100px;\n    height: 100px;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n}\n\n.twt-feed {\n    border-radius: 4px 4px 0 0;\n    -webkit-border-radius: 4px 4px 0 0;\n    color: #FFFFFF;\n    padding: 10px;\n    position: relative;\n    text-align: center;\n}\n\n.twt-feed.blue-bg {\n    background: #58C9F3;\n}\n\n.twt-feed h1 {\n    font-size: 22px;\n    font-weight: 300;\n    margin-bottom: 5px;\n}\n\n.twt-feed a  {\n    border: 8px solid #fff;\n    border-radius: 50%;\n    -webit-border-radius: 50%;\n    display: inline-block;\n    margin-bottom: -55px;\n}\n\n.twt-feed a img {\n    height: 112px;\n    width: 112px;\n    border-radius: 50%;\n    -webit-border-radius: 50%;\n}\n\n.twt-category {\n    display: inline-block;\n    margin-bottom: 11px;\n    margin-top: 55px;\n    width: 100%;\n}\n\n\n.twt-category ul li{\n    color: #89817f;\n    font-size: 13px;\n}\n\n.twt-category h5  {\n    font-size: 20px;\n    font-weight: 300;\n}\n\n.twt-write .t-text-area {\n    border: 1px solid #eeeeee;\n    border-radius: 0;\n}\n\n.twt-footer {\n    padding: 10px 15px;\n}\n\n.btn-space {\n    padding-left: 11.6%;\n    padding-right: 11%;\n}\n\n.p-head {\n    color: #f77b6f;\n    font-weight: 400;\n    font-size: 20px;\n}\n\n.cmt-head {\n    font-weight: 400;\n    font-size: 13px;\n}\n\n.p-thumb img {\n    width: 50px;\n    height: 50px;\n    border-radius: 3px;\n    -webkit-border-radius: 3px;\n}\n\n.tasi-tab .media-body p {\n    /*color: #b8bac6;*/\n}\n\n\n/*Timeline chat*/\n\n.chat-form {\n    margin-top: 25px;\n    clear: both;\n}\n\n.chat-form .input-cont {\n    margin-bottom: 10px;\n}\n\n.chat-form .input-cont input {\n    margin-bottom: 0px;\n}\n\n.chat-form .input-cont input{\n    border: 1px solid #d3d3d3 !important;\n    margin-top:0;\n    min-height: 45px;\n}\n\n.chat-form .input-cont input {\n    background-color: #fff !important;\n}\n\n.chat-features a {\n    margin-left: 10px;\n}\n\n.chat-features a i{\n    color: #d0d0d0;\n}\n\n.timeline-messages:before {\n    background: rgba(0, 0, 0, 0.1);\n    bottom: 0;\n    top: 0;\n    width: 2px;\n}\n.timeline-messages:before, .msg-time-chat:before, .msg-time-chat .text:before {\n    content: \"\";\n    left: 60px;\n    position: absolute;\n    top: -2px;\n}\n.timeline-messages, .msg-time-chat , .timeline-messages .msg-in, .timeline-messages .msg-out {\n    position: relative;\n}\n\n\n.timeline-messages .msg-in  .arrow {\n    /*border-right: 8px solid #F4F4F4 !important;*/\n}\n.timeline-messages .msg-in .arrow {\n    border-bottom: 8px solid transparent;\n    border-top: 8px solid transparent;\n    display: block;\n    height: 0;\n    left: -8px;\n    position: absolute;\n    top: 13px;\n    width: 0;\n}\n\n.timeline-messages .msg-out  .arrow {\n    /*border-right: 8px solid #41cac0 !important;*/\n}\n.timeline-messages .msg-out .arrow {\n    border-bottom: 8px solid transparent;\n    border-top: 8px solid transparent;\n    display: block;\n    height: 0;\n    left: -8px;\n    position: absolute;\n    top: 13px;\n    width: 0;\n}\n\n.msg-time-chat:first-child:before {\n    margin-top: 16px;\n}\n.msg-time-chat:before {\n    background:#CCCCCC;\n    border: 2px solid #FAFAFA;\n    border-radius: 100px;\n    -moz-border-radius: 100px;\n    -webkit-border-radius: 100px;\n    height: 14px;\n    margin: 23px 0 0 -6px;\n    width: 14px;\n}\n.msg-time-chat:hover:before {\n    background: #41cac0;\n}\n.msg-time-chat:first-child {\n    padding-top: 0;\n}\n.message-img {\n    float: left;\n    margin-right: 30px;\n    overflow: hidden;\n}\n.message-img img {\n    display: block;\n    height: 44px;\n    width: 44px;\n}\n.message-body {\n    margin-left: 80px;\n}\n.msg-time-chat .msg-in .text {\n    border: 1px solid #e3e6ed;\n    padding: 10px;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n}\n\n.msg-time-chat .msg-out .text {\n    border: 1px solid #e3e6ed;\n    padding: 10px;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n}\n.msg-time-chat p {\n    margin: 0;\n}\n.msg-time-chat .attribution {\n    font-size: 11px;\n    margin: 0px 0 5px;\n}\n.msg-time-chat {\n    overflow: hidden;\n    padding:8px 0;\n}\n\n.msg-in a, .msg-in a:hover{\n    color: #b64c4c;\n    text-decoration: none;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n    margin-right: 10px;\n    font-weight: 400;\n    font-size: 13px;\n}\n.msg-out a, .msg-out a:hover{\n    color: #288f98;\n    text-decoration: none;\n    border-radius: 4px;\n    -webkit-border-radius: 4px;\n    margin-right: 10px;\n    font-weight: 400;\n    font-size: 13px;\n}\n\n\n/*custom select*/\n\nspan.customSelect {\n    font-size:12px;\n    background-color: #ffffff;\n    padding:10px;\n    border:1px solid #EAEAEA;\n    -moz-border-radius: 4px;\n    -webkit-border-radius: 4px;\n    border-radius: 4px;\n    color: #A4AABA;\n}\nspan.customSelect.changed {\n    background-color: #fff;\n}\n.customSelectInner {\n    background:url(../img/customSelect-arrow.gif) no-repeat center right;\n}\n\n/*boxed page */\n\n.boxed-page {\n    background-color: #ccc !important;\n}\n\n.boxed-page .container {\n    background: #2A3542;\n    padding-left: 0;\n    padding-right: 0;\n}\n\n.boxed-page .container #sidebar {\n    position:inherit;\n}\n\n.boxed-page .container .header .container{\n    background: #fff;\n}\n\n\n.boxed-page .container aside {\n    float: left;\n}\n.boxed-page .container .wrapper{\n    background: #F1F2F7;\n    min-height: 900px;\n}\n\n\n/*collapsible*/\n\n.tools a {\n    margin-left: 10px;\n    color: #a7a7a7;\n    font-size: 12px;\n}\n\n/* google maps */\n.gmaps {\n    height: 300px;\n    width: 100%;\n}\n\n/* star rating */\n.rating {\n    unicode-bidi: bidi-override;\n    direction: rtl;\n    font-size: 30px;\n}\n.rating span.star,\n.rating span.star {\n    font-family: FontAwesome;\n    font-weight: normal;\n    font-style: normal;\n    display: inline-block;\n}\n.rating span.star:hover,\n.rating span.star:hover {\n    cursor: pointer;\n}\n.rating span.star:before,\n.rating span.star:before {\n    content: \"\\f006\";\n    padding-right: 5px;\n    color: #BEC3C7;\n}\n.rating span.star:hover:before,\n.rating span.star:hover:before,\n.rating span.star:hover ~ span.star:before,\n.rating span.star:hover ~ span.star:before {\n    content: \"\\f005\";\n    color: #41CAC0;\n}\n\n/*search page*/\n\n.classic-search {\n    margin-bottom: 30px;\n}\n.classic-search h4 {\n    margin-bottom: 3px;\n    font-weight: 300;\n    font-size: 16px;\n}\n.classic-search h4 a {\n    color: #314558;\n}\n\n.classic-search h4 a:hover {\n    text-decoration: underline;\n}\n\n\n/*ckEditor*/\n\n\n#editor-container\n{\n    width: 100%;\n    margin: 10px auto 0;\n\n}\n\n\n#header-editor\n{\n    overflow: hidden;\n    padding: 0 0 30px;\n    border-bottom: 1px solid #eaeaea;\n    position: relative;\n}\n\n#headerLeft,\n#headerRight\n{\n    width: 49%;\n    overflow: hidden;\n}\n\n#headerLeft\n{\n    float: left;\n    padding: 10px 1px 1px;\n}\n\n#headerLeft h2,\n#headerLeft h3\n{\n    margin: 0;\n    overflow: hidden;\n    font-weight: normal;\n    font-family: 'Open Sans', sans-serif;\n}\n\n#headerLeft h2\n{\n    font-size: 2.6em;\n    line-height: 1.1em;\n    text-transform: capitalize;\n    color: #314558;\n    margin-bottom: 20px;\n}\n\n#headerLeft h3\n{\n    font-size: 1.5em;\n    line-height: 1.1em;\n    margin: .2em 0 0;\n    color: #757575;\n}\n\n#headerRight\n{\n    float: right;\n    padding: 1px;\n}\n\n#headerRight p\n{\n    line-height: 1.8em;\n    text-align: justify;\n    margin: 0;\n}\n\n#headerRight p + p\n{\n    margin-top: 20px;\n}\n\n#headerRight > div\n{\n    padding: 20px;\n    margin: 0 0 0 30px;\n    font-size: 1.1em;\n    color: #757575;\n}\n\n#columns\n{\n    color: #757575;\n    overflow: hidden;\n    padding: 20px 0;\n}\n\n#columns h3 {\n    color: #314558;\n}\n\n#columns > div\n{\n    float: left;\n    width: 33.3%;\n}\n\n#columns #column1 > div\n{\n    margin-left: 1px;\n}\n\n#columns #column3 > div\n{\n    margin-right: 1px;\n}\n\n#columns > div > div\n{\n    margin: 0px 10px;\n    padding: 10px 20px;\n}\n\n#columns blockquote\n{\n    margin-left: 15px;\n}\n\n\n#taglist {\n    display: inline-block;\n    margin-left: 20px;\n    font-weight: bold;\n    margin: 0 0 0 20px;\n}\n\n\n.cke_editable.cke_editable_inline.cke_focus {\n    background: #fcfcfc;\n    border: 1px solid #eaeaea;\n    cursor: text;\n    outline: medium none;\n}\n\n/*advanced table*/\n\n.adv-table table tr td {\n    padding: 10px;\n}\n\n.adv-table table.display thead th {\n    border-bottom: 1px solid #DDDDDD;\n    padding: 10px;\n}\n\ntr.odd.gradeA td.sorting_1, tr.odd td.sorting_1, tr.even.gradeA td.sorting_1 {\n    background: none;\n}\n\ntd.details {\n    background-color: #eee;\n}\n\ntd.details table tr td, .dataTable tr:last-child {\n    border: none;\n}\n\n.adv-table table.display tr.odd.gradeA {\n    background-color: #F9F9F9;\n}\n\n.adv-table table.display tr.even.gradeA {\n    background-color: #FFFFFF;\n}\n\n.adv-table .dataTables_filter label input {\n    float: right;\n    margin-left: 10px;\n    width: 78%;\n}\n\n.adv-table .dataTables_filter label {\n    line-height: 33px;\n    width: 100%;\n}\n\n.adv-table .dataTables_length select {\n    display: inline-block;\n    margin: 0 10px;\n    padding: 5px 8px;\n    width: 65px;\n}\n\n.adv-table .dataTables_info, .dataTables_paginate {\n    padding: 15px;\n}\n\n.adv-table .dataTables_length,.adv-table .dataTables_filter {\n    padding: 15px 0;\n}\n\n.cke_chrome {\n    border: none !important;\n}\n\n\n.editable-table .dataTables_filter {\n    width: 80%;\n}\n\ntr.odd.gradeX td.sorting_1, tr.even.gradeX td.sorting_1, table.display tr.even.gradeX, table.display tr.gradeX, tr.even.gradeU td.sorting_1, tr.even td.sorting_1, table.display tr.even.gradeC, table.display tr.gradeC, tr.odd.gradeC td.sorting_1, table.display tr.even.gradeU, table.display tr.gradeU, tr.odd.gradeU td.sorting_1{\n    background: none !important;\n}\n\n/*flot chart*/\n\n.flot-chart .chart, .flot-chart .pie, .flot-chart .bars {\n    height: 300px;\n}\n\n\n/*xchart*/\n\n.demo-xchart {\n    height: 400px;\n    width: 100%;\n}\n\n\n/*Horizontal menu*/\n\n.full-width #main-content {\n    margin-left: 0;\n}\n\n.horizontal-menu {\n    margin-left: 50px;\n    float: left;\n}\n\n.horizontal-menu .navbar-nav > li > a {\n    padding-bottom: 20px;\n    padding-top: 20px;\n}\n\n.full-width .navbar-header {\n    width: 100%;\n}\n\n\n.full-width .nav > li > a:hover, .full-width .nav  li.active a, .full-width .nav li.dropdown a:hover , .full-width .nav li.dropdown.open a:focus, .full-width .nav .open > a, .full-width  .nav .open > a:hover, .full-width  .nav .open > a:focus{\n    background-color: #F77B6F;\n    text-decoration: none;\n    color: #fff;\n    transition: all 0.3s ease 0s;\n    -webkit-transition: all 0.3s ease 0s;\n}\n\n\n.full-width .dropdown-menu {\n    box-shadow: none;\n}\n\n.full-width .dropdown-menu > li > a {\n    padding: 10px 20px;\n    font-size: 13px;\n}\n\n\n/*advanced form*/\n\n.form-body {\n    padding: 20px;\n}\n\n\n/*multiselect*/\n\n.ms-container .ms-selectable li.ms-hover, .ms-container .ms-selection li.ms-hover {\n    background-color: #2A3542;\n    color: #FFFFFF;\n    cursor: pointer;\n    text-decoration: none;\n}\n\n.ms-container .ms-list, .ms-container .ms-list.ms-focus {\n    box-shadow: none !important;\n}\n\n.ms-container .ms-list.ms-focus {\n    border: 1px solid #2A3542;\n}\n\n.ms-selectable .search-input, .ms-selection .search-input{\n    margin-bottom: 10px;\n}\n\n/*spinner*/\n\n.spinner-buttons.btn-group-vertical .btn {\n    height: 17px;\n    margin: 0;\n    padding-left: 6px;\n    padding-right: 6px;\n    text-align: center;\n    width: 22px;\n}\n\n.spinner-buttons.btn-group-vertical .btn i {\n    margin-top: -3px;\n}\n.spinner-buttons.btn-group-vertical .btn:first-child {\n    border-radius: 0 4px 0 0 !important;\n    -webkit-border-radius: 0 4px 0 0 !important;\n}\n\n.spinner-buttons.btn-group-vertical .btn:last-child {\n    border-radius: 0 0 4px !important;\n    -webkit-border-radius: 0 0 4px !important;\n}\n\n/**/\n\n.wysihtml5-toolbar .btn-default {\n    background: #fff;\n    color: #757575;\n}\n\n/*todolist*/\n\n#sortable {\n    list-style-type: none;\n    margin: 0 0 20px 0;\n    padding: 0;\n    width: 100%;\n}\n#sortable li {\n    padding-left: 3em;\n    font-size: 12px;\n}\n#sortable li i {\n    position: absolute;\n    left:6px;\n    padding:4px 10px 0 10px;\n    cursor: pointer;\n}\n\n#sortable li input[type=checkbox]{\n    margin-top: 0;\n}\n\n.ui-sortable > li {\n    padding: 15px 0 15px 35px !important ;\n    position: relative;\n    background: #f5f6f8;\n    margin-bottom: 2px;\n    border-bottom   : none !important;\n}\n\n.ui-sortable li.list-primary {\n    border-left: 3px solid #41CAC0;\n}\n\n.ui-sortable li.list-success {\n    border-left: 3px solid #78CD51;\n}\n\n.ui-sortable li.list-danger {\n    border-left: 3px solid #FF6C60;\n}\n\n.ui-sortable li.list-warning {\n    border-left: 3px solid #F1C500;\n}\n\n.ui-sortable li.list-info {\n    border-left: 3px solid #58C9F3;\n}\n\n.ui-sortable li.list-inverse {\n    border-left: 3px solid #BEC3C7;\n}\n\n/*lock screen*/\n\n.lock-screen {\n    background:#02bac6 url(\"../img/lock-bg.jpg\");\n    background-size: cover;\n    background-repeat: repeat;\n}\n\n.lock-wrapper {\n    margin: 10% auto;\n    max-width: 330px;\n}\n\n.lock-box {\n    background: rgba(255,255,255,.3);\n    padding: 20px;\n    border-radius: 10px;\n    -webkit-border-radius: 10px;\n    position: relative;\n}\n\n.lock-wrapper img {\n    position: absolute;\n    left: 40%;\n    top: -40px;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    border: 5px solid #fff;\n}\n\n.lock-wrapper h1 {\n    text-align: center;\n    color: #fff;\n    font-size: 18px;\n    text-transform: uppercase;\n    padding: 20px 0 0 0;\n}\n\n.lock-wrapper .locked {\n    margin-bottom: 20px;\n    display: inline-block;\n    color: #026f7a;\n}\n\n.btn-lock,.btn-lock:hover {\n    background: #02b5c2;\n    color: #fff;\n}\n\n.lock-input {\n    width: 83%;\n    border: none;\n    float: left;\n    margin-right: 3px;\n}\n\n#time {\n    width: 100%;\n    color: #fff;\n    font-size: 60px;\n    margin-bottom: 80px;\n    display: inline-block;\n    text-align: center;\n    font-family: 'Open Sans', sans-serif;\n    font-weight: 300;\n}\n\n\n/*language*/\n\n.language {\n    margin-top: 4px;\n}\n.language .dropdown-menu {\n    border: 1px solid #eee;\n    box-shadow: 0 2px 3px rgba(0, 0, 0, 0.176) !important;\n}\n.language .dropdown-menu li a{\n    border-bottom: 1px solid #eee;\n    padding: 10px;\n}\n\n.language .dropdown-menu li:last-child a {\n    border-bottom: none;\n}\n\n.language .dropdown-menu li a {\n    font-size: 13px;\n}\n\n\n\n/*product list*/\n\n.prod-cat li a{\n    border-bottom: 1px dashed #d9d9d9;\n}\n\n.prod-cat li a {\n    color: #3b3b3b;\n}\n\n.prod-cat li ul {\n    margin-left: 30px;\n}\n\n.prod-cat li ul li a{\n    border-bottom:none;\n}\n.prod-cat li ul li a:hover,.prod-cat li ul li a:focus, .prod-cat li ul li.active a , .prod-cat li a:hover,.prod-cat li a:focus, .prod-cat li a.active{\n    background: none;\n    color: #ff7261;\n}\n\n.pro-lab{\n    margin-right: 20px;\n    font-weight: normal;\n}\n\n.pro-sort {\n    padding-right: 20px;\n    float: left;\n}\n\n.pro-page-list {\n    margin: 5px 0 0 0;\n}\n\n.product-list img{\n    width: 100%;\n    border-radius: 4px 4px 0 0;\n    -webkit-border-radius: 4px 4px 0 0;\n}\n\n.product-list .pro-img-box {\n    position: relative;\n}\n.adtocart {\n    background: #fc5959;\n    width: 50px;\n    height: 50px;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n    color: #fff;\n    display: inline-block;\n    text-align: center;\n    border: 3px solid #fff;\n    left: 45%;\n    bottom: -25px;\n    position: absolute;\n}\n\n.adtocart i{\n    color: #fff;\n    font-size: 25px;\n    line-height: 42px;\n}\n\n.pro-title {\n    color: #5A5A5A;\n    display: inline-block;\n    margin-top: 20px;\n    font-size: 16px;\n}\n\n.product-list .price {\n    color:#fc5959 ;\n    font-size: 15px;\n}\n\n.pro-img-details {\n    margin-left: -15px;\n}\n\n.pro-img-details img {\n    width: 100%;\n}\n\n.pro-d-title {\n    font-size: 16px;\n    margin-top: 0;\n}\n\n.product_meta {\n    border-top: 1px solid #eee;\n    border-bottom: 1px solid #eee;\n    padding: 10px 0;\n    margin: 15px 0;\n}\n\n.product_meta span {\n    display: block;\n    margin-bottom: 10px;\n}\n.product_meta a, .pro-price{\n    color:#fc5959 ;\n}\n\n.pro-price, .amount-old {\n    font-size: 18px;\n    padding: 0 10px;\n}\n\n.amount-old {\n    text-decoration: line-through;\n}\n\n.quantity {\n    width: 120px;\n}\n\n.pro-img-list {\n    margin: 10px 0 0 -15px;\n    width: 100%;\n    display: inline-block;\n}\n\n.pro-img-list a {\n    float: left;\n    margin-right: 10px;\n    margin-bottom: 10px;\n}\n\n.pro-d-head {\n    font-size: 18px;\n    font-weight: 300;\n}\n\n/*footer*/\n\n.site-footer {\n    background: #5b6e84;\n    color: #fff;\n    padding: 10px 0;\n}\n\n.go-top {\n    margin-right: 1%;\n    float: right;\n    background: rgba(255,255,255,.5);\n    width: 20px;\n    height: 20px;\n    border-radius: 50%;\n    -webkit-border-radius: 50%;\n}\n\n.go-top i {\n    color: #2A3542;\n}\n\n.site-min-height {\n    min-height: 900px;\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/bootstrap.js",
    "content": "/*!\n * Bootstrap v3.0.2 by @fat and @mdo\n * Copyright 2013 Twitter, Inc.\n * Licensed under http://www.apache.org/licenses/LICENSE-2.0\n *\n * Designed and built with all the love in the world by @mdo and @fat.\n */\n\nif (typeof jQuery === \"undefined\") { throw new Error(\"Bootstrap requires jQuery\") }\n\n/* ========================================================================\n * Bootstrap: transition.js v3.0.2\n * http://getbootstrap.com/javascript/#transitions\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)\n  // ============================================================\n\n  function transitionEnd() {\n    var el = document.createElement('bootstrap')\n\n    var transEndEventNames = {\n      'WebkitTransition' : 'webkitTransitionEnd'\n    , 'MozTransition'    : 'transitionend'\n    , 'OTransition'      : 'oTransitionEnd otransitionend'\n    , 'transition'       : 'transitionend'\n    }\n\n    for (var name in transEndEventNames) {\n      if (el.style[name] !== undefined) {\n        return { end: transEndEventNames[name] }\n      }\n    }\n  }\n\n  // http://blog.alexmaccaw.com/css-transitions\n  $.fn.emulateTransitionEnd = function (duration) {\n    var called = false, $el = this\n    $(this).one($.support.transition.end, function () { called = true })\n    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }\n    setTimeout(callback, duration)\n    return this\n  }\n\n  $(function () {\n    $.support.transition = transitionEnd()\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: alert.js v3.0.2\n * http://getbootstrap.com/javascript/#alerts\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // ALERT CLASS DEFINITION\n  // ======================\n\n  var dismiss = '[data-dismiss=\"alert\"]'\n  var Alert   = function (el) {\n    $(el).on('click', dismiss, this.close)\n  }\n\n  Alert.prototype.close = function (e) {\n    var $this    = $(this)\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') // strip for ie7\n    }\n\n    var $parent = $(selector)\n\n    if (e) e.preventDefault()\n\n    if (!$parent.length) {\n      $parent = $this.hasClass('alert') ? $this : $this.parent()\n    }\n\n    $parent.trigger(e = $.Event('close.bs.alert'))\n\n    if (e.isDefaultPrevented()) return\n\n    $parent.removeClass('in')\n\n    function removeElement() {\n      $parent.trigger('closed.bs.alert').remove()\n    }\n\n    $.support.transition && $parent.hasClass('fade') ?\n      $parent\n        .one($.support.transition.end, removeElement)\n        .emulateTransitionEnd(150) :\n      removeElement()\n  }\n\n\n  // ALERT PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.alert\n\n  $.fn.alert = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.alert')\n\n      if (!data) $this.data('bs.alert', (data = new Alert(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.alert.Constructor = Alert\n\n\n  // ALERT NO CONFLICT\n  // =================\n\n  $.fn.alert.noConflict = function () {\n    $.fn.alert = old\n    return this\n  }\n\n\n  // ALERT DATA-API\n  // ==============\n\n  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: button.js v3.0.2\n * http://getbootstrap.com/javascript/#buttons\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // BUTTON PUBLIC CLASS DEFINITION\n  // ==============================\n\n  var Button = function (element, options) {\n    this.$element = $(element)\n    this.options  = $.extend({}, Button.DEFAULTS, options)\n  }\n\n  Button.DEFAULTS = {\n    loadingText: 'loading...'\n  }\n\n  Button.prototype.setState = function (state) {\n    var d    = 'disabled'\n    var $el  = this.$element\n    var val  = $el.is('input') ? 'val' : 'html'\n    var data = $el.data()\n\n    state = state + 'Text'\n\n    if (!data.resetText) $el.data('resetText', $el[val]())\n\n    $el[val](data[state] || this.options[state])\n\n    // push to event loop to allow forms to submit\n    setTimeout(function () {\n      state == 'loadingText' ?\n        $el.addClass(d).attr(d, d) :\n        $el.removeClass(d).removeAttr(d);\n    }, 0)\n  }\n\n  Button.prototype.toggle = function () {\n    var $parent = this.$element.closest('[data-toggle=\"buttons\"]')\n\n    if ($parent.length) {\n      var $input = this.$element.find('input')\n        .prop('checked', !this.$element.hasClass('active'))\n        .trigger('change')\n      if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')\n    }\n\n    this.$element.toggleClass('active')\n  }\n\n\n  // BUTTON PLUGIN DEFINITION\n  // ========================\n\n  var old = $.fn.button\n\n  $.fn.button = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.button')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.button', (data = new Button(this, options)))\n\n      if (option == 'toggle') data.toggle()\n      else if (option) data.setState(option)\n    })\n  }\n\n  $.fn.button.Constructor = Button\n\n\n  // BUTTON NO CONFLICT\n  // ==================\n\n  $.fn.button.noConflict = function () {\n    $.fn.button = old\n    return this\n  }\n\n\n  // BUTTON DATA-API\n  // ===============\n\n  $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {\n    var $btn = $(e.target)\n    if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')\n    $btn.button('toggle')\n    e.preventDefault()\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: carousel.js v3.0.2\n * http://getbootstrap.com/javascript/#carousel\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // CAROUSEL CLASS DEFINITION\n  // =========================\n\n  var Carousel = function (element, options) {\n    this.$element    = $(element)\n    this.$indicators = this.$element.find('.carousel-indicators')\n    this.options     = options\n    this.paused      =\n    this.sliding     =\n    this.interval    =\n    this.$active     =\n    this.$items      = null\n\n    this.options.pause == 'hover' && this.$element\n      .on('mouseenter', $.proxy(this.pause, this))\n      .on('mouseleave', $.proxy(this.cycle, this))\n  }\n\n  Carousel.DEFAULTS = {\n    interval: 5000\n  , pause: 'hover'\n  , wrap: true\n  }\n\n  Carousel.prototype.cycle =  function (e) {\n    e || (this.paused = false)\n\n    this.interval && clearInterval(this.interval)\n\n    this.options.interval\n      && !this.paused\n      && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))\n\n    return this\n  }\n\n  Carousel.prototype.getActiveIndex = function () {\n    this.$active = this.$element.find('.item.active')\n    this.$items  = this.$active.parent().children()\n\n    return this.$items.index(this.$active)\n  }\n\n  Carousel.prototype.to = function (pos) {\n    var that        = this\n    var activeIndex = this.getActiveIndex()\n\n    if (pos > (this.$items.length - 1) || pos < 0) return\n\n    if (this.sliding)       return this.$element.one('slid', function () { that.to(pos) })\n    if (activeIndex == pos) return this.pause().cycle()\n\n    return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))\n  }\n\n  Carousel.prototype.pause = function (e) {\n    e || (this.paused = true)\n\n    if (this.$element.find('.next, .prev').length && $.support.transition.end) {\n      this.$element.trigger($.support.transition.end)\n      this.cycle(true)\n    }\n\n    this.interval = clearInterval(this.interval)\n\n    return this\n  }\n\n  Carousel.prototype.next = function () {\n    if (this.sliding) return\n    return this.slide('next')\n  }\n\n  Carousel.prototype.prev = function () {\n    if (this.sliding) return\n    return this.slide('prev')\n  }\n\n  Carousel.prototype.slide = function (type, next) {\n    var $active   = this.$element.find('.item.active')\n    var $next     = next || $active[type]()\n    var isCycling = this.interval\n    var direction = type == 'next' ? 'left' : 'right'\n    var fallback  = type == 'next' ? 'first' : 'last'\n    var that      = this\n\n    if (!$next.length) {\n      if (!this.options.wrap) return\n      $next = this.$element.find('.item')[fallback]()\n    }\n\n    this.sliding = true\n\n    isCycling && this.pause()\n\n    var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction })\n\n    if ($next.hasClass('active')) return\n\n    if (this.$indicators.length) {\n      this.$indicators.find('.active').removeClass('active')\n      this.$element.one('slid', function () {\n        var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()])\n        $nextIndicator && $nextIndicator.addClass('active')\n      })\n    }\n\n    if ($.support.transition && this.$element.hasClass('slide')) {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $next.addClass(type)\n      $next[0].offsetWidth // force reflow\n      $active.addClass(direction)\n      $next.addClass(direction)\n      $active\n        .one($.support.transition.end, function () {\n          $next.removeClass([type, direction].join(' ')).addClass('active')\n          $active.removeClass(['active', direction].join(' '))\n          that.sliding = false\n          setTimeout(function () { that.$element.trigger('slid') }, 0)\n        })\n        .emulateTransitionEnd(600)\n    } else {\n      this.$element.trigger(e)\n      if (e.isDefaultPrevented()) return\n      $active.removeClass('active')\n      $next.addClass('active')\n      this.sliding = false\n      this.$element.trigger('slid')\n    }\n\n    isCycling && this.cycle()\n\n    return this\n  }\n\n\n  // CAROUSEL PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.carousel\n\n  $.fn.carousel = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.carousel')\n      var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)\n      var action  = typeof option == 'string' ? option : options.slide\n\n      if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))\n      if (typeof option == 'number') data.to(option)\n      else if (action) data[action]()\n      else if (options.interval) data.pause().cycle()\n    })\n  }\n\n  $.fn.carousel.Constructor = Carousel\n\n\n  // CAROUSEL NO CONFLICT\n  // ====================\n\n  $.fn.carousel.noConflict = function () {\n    $.fn.carousel = old\n    return this\n  }\n\n\n  // CAROUSEL DATA-API\n  // =================\n\n  $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {\n    var $this   = $(this), href\n    var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n    var options = $.extend({}, $target.data(), $this.data())\n    var slideIndex = $this.attr('data-slide-to')\n    if (slideIndex) options.interval = false\n\n    $target.carousel(options)\n\n    if (slideIndex = $this.attr('data-slide-to')) {\n      $target.data('bs.carousel').to(slideIndex)\n    }\n\n    e.preventDefault()\n  })\n\n  $(window).on('load', function () {\n    $('[data-ride=\"carousel\"]').each(function () {\n      var $carousel = $(this)\n      $carousel.carousel($carousel.data())\n    })\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: collapse.js v3.0.2\n * http://getbootstrap.com/javascript/#collapse\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // COLLAPSE PUBLIC CLASS DEFINITION\n  // ================================\n\n  var Collapse = function (element, options) {\n    this.$element      = $(element)\n    this.options       = $.extend({}, Collapse.DEFAULTS, options)\n    this.transitioning = null\n\n    if (this.options.parent) this.$parent = $(this.options.parent)\n    if (this.options.toggle) this.toggle()\n  }\n\n  Collapse.DEFAULTS = {\n    toggle: true\n  }\n\n  Collapse.prototype.dimension = function () {\n    var hasWidth = this.$element.hasClass('width')\n    return hasWidth ? 'width' : 'height'\n  }\n\n  Collapse.prototype.show = function () {\n    if (this.transitioning || this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('show.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var actives = this.$parent && this.$parent.find('> .panel > .in')\n\n    if (actives && actives.length) {\n      var hasData = actives.data('bs.collapse')\n      if (hasData && hasData.transitioning) return\n      actives.collapse('hide')\n      hasData || actives.data('bs.collapse', null)\n    }\n\n    var dimension = this.dimension()\n\n    this.$element\n      .removeClass('collapse')\n      .addClass('collapsing')\n      [dimension](0)\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.$element\n        .removeClass('collapsing')\n        .addClass('in')\n        [dimension]('auto')\n      this.transitioning = 0\n      this.$element.trigger('shown.bs.collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    var scrollSize = $.camelCase(['scroll', dimension].join('-'))\n\n    this.$element\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n      [dimension](this.$element[0][scrollSize])\n  }\n\n  Collapse.prototype.hide = function () {\n    if (this.transitioning || !this.$element.hasClass('in')) return\n\n    var startEvent = $.Event('hide.bs.collapse')\n    this.$element.trigger(startEvent)\n    if (startEvent.isDefaultPrevented()) return\n\n    var dimension = this.dimension()\n\n    this.$element\n      [dimension](this.$element[dimension]())\n      [0].offsetHeight\n\n    this.$element\n      .addClass('collapsing')\n      .removeClass('collapse')\n      .removeClass('in')\n\n    this.transitioning = 1\n\n    var complete = function () {\n      this.transitioning = 0\n      this.$element\n        .trigger('hidden.bs.collapse')\n        .removeClass('collapsing')\n        .addClass('collapse')\n    }\n\n    if (!$.support.transition) return complete.call(this)\n\n    this.$element\n      [dimension](0)\n      .one($.support.transition.end, $.proxy(complete, this))\n      .emulateTransitionEnd(350)\n  }\n\n  Collapse.prototype.toggle = function () {\n    this[this.$element.hasClass('in') ? 'hide' : 'show']()\n  }\n\n\n  // COLLAPSE PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.collapse\n\n  $.fn.collapse = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.collapse')\n      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.collapse.Constructor = Collapse\n\n\n  // COLLAPSE NO CONFLICT\n  // ====================\n\n  $.fn.collapse.noConflict = function () {\n    $.fn.collapse = old\n    return this\n  }\n\n\n  // COLLAPSE DATA-API\n  // =================\n\n  $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) {\n    var $this   = $(this), href\n    var target  = $this.attr('data-target')\n        || e.preventDefault()\n        || (href = $this.attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '') //strip for ie7\n    var $target = $(target)\n    var data    = $target.data('bs.collapse')\n    var option  = data ? 'toggle' : $this.data()\n    var parent  = $this.attr('data-parent')\n    var $parent = parent && $(parent)\n\n    if (!data || !data.transitioning) {\n      if ($parent) $parent.find('[data-toggle=collapse][data-parent=\"' + parent + '\"]').not($this).addClass('collapsed')\n      $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')\n    }\n\n    $target.collapse(option)\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: dropdown.js v3.0.2\n * http://getbootstrap.com/javascript/#dropdowns\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // DROPDOWN CLASS DEFINITION\n  // =========================\n\n  var backdrop = '.dropdown-backdrop'\n  var toggle   = '[data-toggle=dropdown]'\n  var Dropdown = function (element) {\n    var $el = $(element).on('click.bs.dropdown', this.toggle)\n  }\n\n  Dropdown.prototype.toggle = function (e) {\n    var $this = $(this)\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    clearMenus()\n\n    if (!isActive) {\n      if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {\n        // if mobile we we use a backdrop because click events don't delegate\n        $('<div class=\"dropdown-backdrop\"/>').insertAfter($(this)).on('click', clearMenus)\n      }\n\n      $parent.trigger(e = $.Event('show.bs.dropdown'))\n\n      if (e.isDefaultPrevented()) return\n\n      $parent\n        .toggleClass('open')\n        .trigger('shown.bs.dropdown')\n\n      $this.focus()\n    }\n\n    return false\n  }\n\n  Dropdown.prototype.keydown = function (e) {\n    if (!/(38|40|27)/.test(e.keyCode)) return\n\n    var $this = $(this)\n\n    e.preventDefault()\n    e.stopPropagation()\n\n    if ($this.is('.disabled, :disabled')) return\n\n    var $parent  = getParent($this)\n    var isActive = $parent.hasClass('open')\n\n    if (!isActive || (isActive && e.keyCode == 27)) {\n      if (e.which == 27) $parent.find(toggle).focus()\n      return $this.click()\n    }\n\n    var $items = $('[role=menu] li:not(.divider):visible a', $parent)\n\n    if (!$items.length) return\n\n    var index = $items.index($items.filter(':focus'))\n\n    if (e.keyCode == 38 && index > 0)                 index--                        // up\n    if (e.keyCode == 40 && index < $items.length - 1) index++                        // down\n    if (!~index)                                      index=0\n\n    $items.eq(index).focus()\n  }\n\n  function clearMenus() {\n    $(backdrop).remove()\n    $(toggle).each(function (e) {\n      var $parent = getParent($(this))\n      if (!$parent.hasClass('open')) return\n      $parent.trigger(e = $.Event('hide.bs.dropdown'))\n      if (e.isDefaultPrevented()) return\n      $parent.removeClass('open').trigger('hidden.bs.dropdown')\n    })\n  }\n\n  function getParent($this) {\n    var selector = $this.attr('data-target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && /#/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    var $parent = selector && $(selector)\n\n    return $parent && $parent.length ? $parent : $this.parent()\n  }\n\n\n  // DROPDOWN PLUGIN DEFINITION\n  // ==========================\n\n  var old = $.fn.dropdown\n\n  $.fn.dropdown = function (option) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('dropdown')\n\n      if (!data) $this.data('dropdown', (data = new Dropdown(this)))\n      if (typeof option == 'string') data[option].call($this)\n    })\n  }\n\n  $.fn.dropdown.Constructor = Dropdown\n\n\n  // DROPDOWN NO CONFLICT\n  // ====================\n\n  $.fn.dropdown.noConflict = function () {\n    $.fn.dropdown = old\n    return this\n  }\n\n\n  // APPLY TO STANDARD DROPDOWN ELEMENTS\n  // ===================================\n\n  $(document)\n    .on('click.bs.dropdown.data-api', clearMenus)\n    .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })\n    .on('click.bs.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)\n    .on('keydown.bs.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: modal.js v3.0.2\n * http://getbootstrap.com/javascript/#modals\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // MODAL CLASS DEFINITION\n  // ======================\n\n  var Modal = function (element, options) {\n    this.options   = options\n    this.$element  = $(element)\n    this.$backdrop =\n    this.isShown   = null\n\n    if (this.options.remote) this.$element.load(this.options.remote)\n  }\n\n  Modal.DEFAULTS = {\n      backdrop: true\n    , keyboard: true\n    , show: true\n  }\n\n  Modal.prototype.toggle = function (_relatedTarget) {\n    return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)\n  }\n\n  Modal.prototype.show = function (_relatedTarget) {\n    var that = this\n    var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })\n\n    this.$element.trigger(e)\n\n    if (this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = true\n\n    this.escape()\n\n    this.$element.on('click.dismiss.modal', '[data-dismiss=\"modal\"]', $.proxy(this.hide, this))\n\n    this.backdrop(function () {\n      var transition = $.support.transition && that.$element.hasClass('fade')\n\n      if (!that.$element.parent().length) {\n        that.$element.appendTo(document.body) // don't move modals dom position\n      }\n\n      that.$element.show()\n\n      if (transition) {\n        that.$element[0].offsetWidth // force reflow\n      }\n\n      that.$element\n        .addClass('in')\n        .attr('aria-hidden', false)\n\n      that.enforceFocus()\n\n      var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })\n\n      transition ?\n        that.$element.find('.modal-dialog') // wait for modal to slide in\n          .one($.support.transition.end, function () {\n            that.$element.focus().trigger(e)\n          })\n          .emulateTransitionEnd(300) :\n        that.$element.focus().trigger(e)\n    })\n  }\n\n  Modal.prototype.hide = function (e) {\n    if (e) e.preventDefault()\n\n    e = $.Event('hide.bs.modal')\n\n    this.$element.trigger(e)\n\n    if (!this.isShown || e.isDefaultPrevented()) return\n\n    this.isShown = false\n\n    this.escape()\n\n    $(document).off('focusin.bs.modal')\n\n    this.$element\n      .removeClass('in')\n      .attr('aria-hidden', true)\n      .off('click.dismiss.modal')\n\n    $.support.transition && this.$element.hasClass('fade') ?\n      this.$element\n        .one($.support.transition.end, $.proxy(this.hideModal, this))\n        .emulateTransitionEnd(300) :\n      this.hideModal()\n  }\n\n  Modal.prototype.enforceFocus = function () {\n    $(document)\n      .off('focusin.bs.modal') // guard against infinite focus loop\n      .on('focusin.bs.modal', $.proxy(function (e) {\n        if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {\n          this.$element.focus()\n        }\n      }, this))\n  }\n\n  Modal.prototype.escape = function () {\n    if (this.isShown && this.options.keyboard) {\n      this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {\n        e.which == 27 && this.hide()\n      }, this))\n    } else if (!this.isShown) {\n      this.$element.off('keyup.dismiss.bs.modal')\n    }\n  }\n\n  Modal.prototype.hideModal = function () {\n    var that = this\n    this.$element.hide()\n    this.backdrop(function () {\n      that.removeBackdrop()\n      that.$element.trigger('hidden.bs.modal')\n    })\n  }\n\n  Modal.prototype.removeBackdrop = function () {\n    this.$backdrop && this.$backdrop.remove()\n    this.$backdrop = null\n  }\n\n  Modal.prototype.backdrop = function (callback) {\n    var that    = this\n    var animate = this.$element.hasClass('fade') ? 'fade' : ''\n\n    if (this.isShown && this.options.backdrop) {\n      var doAnimate = $.support.transition && animate\n\n      this.$backdrop = $('<div class=\"modal-backdrop ' + animate + '\" />')\n        .appendTo(document.body)\n\n      this.$element.on('click.dismiss.modal', $.proxy(function (e) {\n        if (e.target !== e.currentTarget) return\n        this.options.backdrop == 'static'\n          ? this.$element[0].focus.call(this.$element[0])\n          : this.hide.call(this)\n      }, this))\n\n      if (doAnimate) this.$backdrop[0].offsetWidth // force reflow\n\n      this.$backdrop.addClass('in')\n\n      if (!callback) return\n\n      doAnimate ?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (!this.isShown && this.$backdrop) {\n      this.$backdrop.removeClass('in')\n\n      $.support.transition && this.$element.hasClass('fade')?\n        this.$backdrop\n          .one($.support.transition.end, callback)\n          .emulateTransitionEnd(150) :\n        callback()\n\n    } else if (callback) {\n      callback()\n    }\n  }\n\n\n  // MODAL PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.modal\n\n  $.fn.modal = function (option, _relatedTarget) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.modal')\n      var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)\n\n      if (!data) $this.data('bs.modal', (data = new Modal(this, options)))\n      if (typeof option == 'string') data[option](_relatedTarget)\n      else if (options.show) data.show(_relatedTarget)\n    })\n  }\n\n  $.fn.modal.Constructor = Modal\n\n\n  // MODAL NO CONFLICT\n  // =================\n\n  $.fn.modal.noConflict = function () {\n    $.fn.modal = old\n    return this\n  }\n\n\n  // MODAL DATA-API\n  // ==============\n\n  $(document).on('click.bs.modal.data-api', '[data-toggle=\"modal\"]', function (e) {\n    var $this   = $(this)\n    var href    = $this.attr('href')\n    var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\s]+$)/, ''))) //strip for ie7\n    var option  = $target.data('modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())\n\n    e.preventDefault()\n\n    $target\n      .modal(option, this)\n      .one('hide', function () {\n        $this.is(':visible') && $this.focus()\n      })\n  })\n\n  $(document)\n    .on('show.bs.modal',  '.modal', function () { $(document.body).addClass('modal-open') })\n    .on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: tooltip.js v3.0.2\n * http://getbootstrap.com/javascript/#tooltip\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // TOOLTIP PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Tooltip = function (element, options) {\n    this.type       =\n    this.options    =\n    this.enabled    =\n    this.timeout    =\n    this.hoverState =\n    this.$element   = null\n\n    this.init('tooltip', element, options)\n  }\n\n  Tooltip.DEFAULTS = {\n    animation: true\n  , placement: 'top'\n  , selector: false\n  , template: '<div class=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>'\n  , trigger: 'hover focus'\n  , title: ''\n  , delay: 0\n  , html: false\n  , container: false\n  }\n\n  Tooltip.prototype.init = function (type, element, options) {\n    this.enabled  = true\n    this.type     = type\n    this.$element = $(element)\n    this.options  = this.getOptions(options)\n\n    var triggers = this.options.trigger.split(' ')\n\n    for (var i = triggers.length; i--;) {\n      var trigger = triggers[i]\n\n      if (trigger == 'click') {\n        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))\n      } else if (trigger != 'manual') {\n        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focus'\n        var eventOut = trigger == 'hover' ? 'mouseleave' : 'blur'\n\n        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))\n        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))\n      }\n    }\n\n    this.options.selector ?\n      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :\n      this.fixTitle()\n  }\n\n  Tooltip.prototype.getDefaults = function () {\n    return Tooltip.DEFAULTS\n  }\n\n  Tooltip.prototype.getOptions = function (options) {\n    options = $.extend({}, this.getDefaults(), this.$element.data(), options)\n\n    if (options.delay && typeof options.delay == 'number') {\n      options.delay = {\n        show: options.delay\n      , hide: options.delay\n      }\n    }\n\n    return options\n  }\n\n  Tooltip.prototype.getDelegateOptions = function () {\n    var options  = {}\n    var defaults = this.getDefaults()\n\n    this._options && $.each(this._options, function (key, value) {\n      if (defaults[key] != value) options[key] = value\n    })\n\n    return options\n  }\n\n  Tooltip.prototype.enter = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    self.hoverState = 'in'\n\n    if (!self.options.delay || !self.options.delay.show) return self.show()\n\n    self.timeout = setTimeout(function () {\n      if (self.hoverState == 'in') self.show()\n    }, self.options.delay.show)\n  }\n\n  Tooltip.prototype.leave = function (obj) {\n    var self = obj instanceof this.constructor ?\n      obj : $(obj.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type)\n\n    clearTimeout(self.timeout)\n\n    self.hoverState = 'out'\n\n    if (!self.options.delay || !self.options.delay.hide) return self.hide()\n\n    self.timeout = setTimeout(function () {\n      if (self.hoverState == 'out') self.hide()\n    }, self.options.delay.hide)\n  }\n\n  Tooltip.prototype.show = function () {\n    var e = $.Event('show.bs.'+ this.type)\n\n    if (this.hasContent() && this.enabled) {\n      this.$element.trigger(e)\n\n      if (e.isDefaultPrevented()) return\n\n      var $tip = this.tip()\n\n      this.setContent()\n\n      if (this.options.animation) $tip.addClass('fade')\n\n      var placement = typeof this.options.placement == 'function' ?\n        this.options.placement.call(this, $tip[0], this.$element[0]) :\n        this.options.placement\n\n      var autoToken = /\\s?auto?\\s?/i\n      var autoPlace = autoToken.test(placement)\n      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'\n\n      $tip\n        .detach()\n        .css({ top: 0, left: 0, display: 'block' })\n        .addClass(placement)\n\n      this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)\n\n      var pos          = this.getPosition()\n      var actualWidth  = $tip[0].offsetWidth\n      var actualHeight = $tip[0].offsetHeight\n\n      if (autoPlace) {\n        var $parent = this.$element.parent()\n\n        var orgPlacement = placement\n        var docScroll    = document.documentElement.scrollTop || document.body.scrollTop\n        var parentWidth  = this.options.container == 'body' ? window.innerWidth  : $parent.outerWidth()\n        var parentHeight = this.options.container == 'body' ? window.innerHeight : $parent.outerHeight()\n        var parentLeft   = this.options.container == 'body' ? 0 : $parent.offset().left\n\n        placement = placement == 'bottom' && pos.top   + pos.height  + actualHeight - docScroll > parentHeight  ? 'top'    :\n                    placement == 'top'    && pos.top   - docScroll   - actualHeight < 0                         ? 'bottom' :\n                    placement == 'right'  && pos.right + actualWidth > parentWidth                              ? 'left'   :\n                    placement == 'left'   && pos.left  - actualWidth < parentLeft                               ? 'right'  :\n                    placement\n\n        $tip\n          .removeClass(orgPlacement)\n          .addClass(placement)\n      }\n\n      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)\n\n      this.applyPlacement(calculatedOffset, placement)\n      this.$element.trigger('shown.bs.' + this.type)\n    }\n  }\n\n  Tooltip.prototype.applyPlacement = function(offset, placement) {\n    var replace\n    var $tip   = this.tip()\n    var width  = $tip[0].offsetWidth\n    var height = $tip[0].offsetHeight\n\n    // manually read margins because getBoundingClientRect includes difference\n    var marginTop = parseInt($tip.css('margin-top'), 10)\n    var marginLeft = parseInt($tip.css('margin-left'), 10)\n\n    // we must check for NaN for ie 8/9\n    if (isNaN(marginTop))  marginTop  = 0\n    if (isNaN(marginLeft)) marginLeft = 0\n\n    offset.top  = offset.top  + marginTop\n    offset.left = offset.left + marginLeft\n\n    $tip\n      .offset(offset)\n      .addClass('in')\n\n    // check to see if placing tip in new offset caused the tip to resize itself\n    var actualWidth  = $tip[0].offsetWidth\n    var actualHeight = $tip[0].offsetHeight\n\n    if (placement == 'top' && actualHeight != height) {\n      replace = true\n      offset.top = offset.top + height - actualHeight\n    }\n\n    if (/bottom|top/.test(placement)) {\n      var delta = 0\n\n      if (offset.left < 0) {\n        delta       = offset.left * -2\n        offset.left = 0\n\n        $tip.offset(offset)\n\n        actualWidth  = $tip[0].offsetWidth\n        actualHeight = $tip[0].offsetHeight\n      }\n\n      this.replaceArrow(delta - width + actualWidth, actualWidth, 'left')\n    } else {\n      this.replaceArrow(actualHeight - height, actualHeight, 'top')\n    }\n\n    if (replace) $tip.offset(offset)\n  }\n\n  Tooltip.prototype.replaceArrow = function(delta, dimension, position) {\n    this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + \"%\") : '')\n  }\n\n  Tooltip.prototype.setContent = function () {\n    var $tip  = this.tip()\n    var title = this.getTitle()\n\n    $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)\n    $tip.removeClass('fade in top bottom left right')\n  }\n\n  Tooltip.prototype.hide = function () {\n    var that = this\n    var $tip = this.tip()\n    var e    = $.Event('hide.bs.' + this.type)\n\n    function complete() {\n      if (that.hoverState != 'in') $tip.detach()\n    }\n\n    this.$element.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    $tip.removeClass('in')\n\n    $.support.transition && this.$tip.hasClass('fade') ?\n      $tip\n        .one($.support.transition.end, complete)\n        .emulateTransitionEnd(150) :\n      complete()\n\n    this.$element.trigger('hidden.bs.' + this.type)\n\n    return this\n  }\n\n  Tooltip.prototype.fixTitle = function () {\n    var $e = this.$element\n    if ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\n      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\n    }\n  }\n\n  Tooltip.prototype.hasContent = function () {\n    return this.getTitle()\n  }\n\n  Tooltip.prototype.getPosition = function () {\n    var el = this.$element[0]\n    return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : {\n      width: el.offsetWidth\n    , height: el.offsetHeight\n    }, this.$element.offset())\n  }\n\n  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {\n    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :\n           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :\n           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :\n        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }\n  }\n\n  Tooltip.prototype.getTitle = function () {\n    var title\n    var $e = this.$element\n    var o  = this.options\n\n    title = $e.attr('data-original-title')\n      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)\n\n    return title\n  }\n\n  Tooltip.prototype.tip = function () {\n    return this.$tip = this.$tip || $(this.options.template)\n  }\n\n  Tooltip.prototype.arrow = function () {\n    return this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')\n  }\n\n  Tooltip.prototype.validate = function () {\n    if (!this.$element[0].parentNode) {\n      this.hide()\n      this.$element = null\n      this.options  = null\n    }\n  }\n\n  Tooltip.prototype.enable = function () {\n    this.enabled = true\n  }\n\n  Tooltip.prototype.disable = function () {\n    this.enabled = false\n  }\n\n  Tooltip.prototype.toggleEnabled = function () {\n    this.enabled = !this.enabled\n  }\n\n  Tooltip.prototype.toggle = function (e) {\n    var self = e ? $(e.currentTarget)[this.type](this.getDelegateOptions()).data('bs.' + this.type) : this\n    self.tip().hasClass('in') ? self.leave(self) : self.enter(self)\n  }\n\n  Tooltip.prototype.destroy = function () {\n    this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)\n  }\n\n\n  // TOOLTIP PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.tooltip\n\n  $.fn.tooltip = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.tooltip')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tooltip.Constructor = Tooltip\n\n\n  // TOOLTIP NO CONFLICT\n  // ===================\n\n  $.fn.tooltip.noConflict = function () {\n    $.fn.tooltip = old\n    return this\n  }\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: popover.js v3.0.2\n * http://getbootstrap.com/javascript/#popovers\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // POPOVER PUBLIC CLASS DEFINITION\n  // ===============================\n\n  var Popover = function (element, options) {\n    this.init('popover', element, options)\n  }\n\n  if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')\n\n  Popover.DEFAULTS = $.extend({} , $.fn.tooltip.Constructor.DEFAULTS, {\n    placement: 'right'\n  , trigger: 'click'\n  , content: ''\n  , template: '<div class=\"popover\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'\n  })\n\n\n  // NOTE: POPOVER EXTENDS tooltip.js\n  // ================================\n\n  Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)\n\n  Popover.prototype.constructor = Popover\n\n  Popover.prototype.getDefaults = function () {\n    return Popover.DEFAULTS\n  }\n\n  Popover.prototype.setContent = function () {\n    var $tip    = this.tip()\n    var title   = this.getTitle()\n    var content = this.getContent()\n\n    $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)\n    $tip.find('.popover-content')[this.options.html ? 'html' : 'text'](content)\n\n    $tip.removeClass('fade top bottom left right in')\n\n    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do\n    // this manually by checking the contents.\n    if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()\n  }\n\n  Popover.prototype.hasContent = function () {\n    return this.getTitle() || this.getContent()\n  }\n\n  Popover.prototype.getContent = function () {\n    var $e = this.$element\n    var o  = this.options\n\n    return $e.attr('data-content')\n      || (typeof o.content == 'function' ?\n            o.content.call($e[0]) :\n            o.content)\n  }\n\n  Popover.prototype.arrow = function () {\n    return this.$arrow = this.$arrow || this.tip().find('.arrow')\n  }\n\n  Popover.prototype.tip = function () {\n    if (!this.$tip) this.$tip = $(this.options.template)\n    return this.$tip\n  }\n\n\n  // POPOVER PLUGIN DEFINITION\n  // =========================\n\n  var old = $.fn.popover\n\n  $.fn.popover = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.popover')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.popover', (data = new Popover(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.popover.Constructor = Popover\n\n\n  // POPOVER NO CONFLICT\n  // ===================\n\n  $.fn.popover.noConflict = function () {\n    $.fn.popover = old\n    return this\n  }\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: scrollspy.js v3.0.2\n * http://getbootstrap.com/javascript/#scrollspy\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // SCROLLSPY CLASS DEFINITION\n  // ==========================\n\n  function ScrollSpy(element, options) {\n    var href\n    var process  = $.proxy(this.process, this)\n\n    this.$element       = $(element).is('body') ? $(window) : $(element)\n    this.$body          = $('body')\n    this.$scrollElement = this.$element.on('scroll.bs.scroll-spy.data-api', process)\n    this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)\n    this.selector       = (this.options.target\n      || ((href = $(element).attr('href')) && href.replace(/.*(?=#[^\\s]+$)/, '')) //strip for ie7\n      || '') + ' .nav li > a'\n    this.offsets        = $([])\n    this.targets        = $([])\n    this.activeTarget   = null\n\n    this.refresh()\n    this.process()\n  }\n\n  ScrollSpy.DEFAULTS = {\n    offset: 10\n  }\n\n  ScrollSpy.prototype.refresh = function () {\n    var offsetMethod = this.$element[0] == window ? 'offset' : 'position'\n\n    this.offsets = $([])\n    this.targets = $([])\n\n    var self     = this\n    var $targets = this.$body\n      .find(this.selector)\n      .map(function () {\n        var $el   = $(this)\n        var href  = $el.data('target') || $el.attr('href')\n        var $href = /^#\\w/.test(href) && $(href)\n\n        return ($href\n          && $href.length\n          && [[ $href[offsetMethod]().top + (!$.isWindow(self.$scrollElement.get(0)) && self.$scrollElement.scrollTop()), href ]]) || null\n      })\n      .sort(function (a, b) { return a[0] - b[0] })\n      .each(function () {\n        self.offsets.push(this[0])\n        self.targets.push(this[1])\n      })\n  }\n\n  ScrollSpy.prototype.process = function () {\n    var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset\n    var scrollHeight = this.$scrollElement[0].scrollHeight || this.$body[0].scrollHeight\n    var maxScroll    = scrollHeight - this.$scrollElement.height()\n    var offsets      = this.offsets\n    var targets      = this.targets\n    var activeTarget = this.activeTarget\n    var i\n\n    if (scrollTop >= maxScroll) {\n      return activeTarget != (i = targets.last()[0]) && this.activate(i)\n    }\n\n    for (i = offsets.length; i--;) {\n      activeTarget != targets[i]\n        && scrollTop >= offsets[i]\n        && (!offsets[i + 1] || scrollTop <= offsets[i + 1])\n        && this.activate( targets[i] )\n    }\n  }\n\n  ScrollSpy.prototype.activate = function (target) {\n    this.activeTarget = target\n\n    $(this.selector)\n      .parents('.active')\n      .removeClass('active')\n\n    var selector = this.selector\n      + '[data-target=\"' + target + '\"],'\n      + this.selector + '[href=\"' + target + '\"]'\n\n    var active = $(selector)\n      .parents('li')\n      .addClass('active')\n\n    if (active.parent('.dropdown-menu').length)  {\n      active = active\n        .closest('li.dropdown')\n        .addClass('active')\n    }\n\n    active.trigger('activate')\n  }\n\n\n  // SCROLLSPY PLUGIN DEFINITION\n  // ===========================\n\n  var old = $.fn.scrollspy\n\n  $.fn.scrollspy = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.scrollspy')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.scrollspy.Constructor = ScrollSpy\n\n\n  // SCROLLSPY NO CONFLICT\n  // =====================\n\n  $.fn.scrollspy.noConflict = function () {\n    $.fn.scrollspy = old\n    return this\n  }\n\n\n  // SCROLLSPY DATA-API\n  // ==================\n\n  $(window).on('load', function () {\n    $('[data-spy=\"scroll\"]').each(function () {\n      var $spy = $(this)\n      $spy.scrollspy($spy.data())\n    })\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: tab.js v3.0.2\n * http://getbootstrap.com/javascript/#tabs\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // TAB CLASS DEFINITION\n  // ====================\n\n  var Tab = function (element) {\n    this.element = $(element)\n  }\n\n  Tab.prototype.show = function () {\n    var $this    = this.element\n    var $ul      = $this.closest('ul:not(.dropdown-menu)')\n    var selector = $this.data('target')\n\n    if (!selector) {\n      selector = $this.attr('href')\n      selector = selector && selector.replace(/.*(?=#[^\\s]*$)/, '') //strip for ie7\n    }\n\n    if ($this.parent('li').hasClass('active')) return\n\n    var previous = $ul.find('.active:last a')[0]\n    var e        = $.Event('show.bs.tab', {\n      relatedTarget: previous\n    })\n\n    $this.trigger(e)\n\n    if (e.isDefaultPrevented()) return\n\n    var $target = $(selector)\n\n    this.activate($this.parent('li'), $ul)\n    this.activate($target, $target.parent(), function () {\n      $this.trigger({\n        type: 'shown.bs.tab'\n      , relatedTarget: previous\n      })\n    })\n  }\n\n  Tab.prototype.activate = function (element, container, callback) {\n    var $active    = container.find('> .active')\n    var transition = callback\n      && $.support.transition\n      && $active.hasClass('fade')\n\n    function next() {\n      $active\n        .removeClass('active')\n        .find('> .dropdown-menu > .active')\n        .removeClass('active')\n\n      element.addClass('active')\n\n      if (transition) {\n        element[0].offsetWidth // reflow for transition\n        element.addClass('in')\n      } else {\n        element.removeClass('fade')\n      }\n\n      if (element.parent('.dropdown-menu')) {\n        element.closest('li.dropdown').addClass('active')\n      }\n\n      callback && callback()\n    }\n\n    transition ?\n      $active\n        .one($.support.transition.end, next)\n        .emulateTransitionEnd(150) :\n      next()\n\n    $active.removeClass('in')\n  }\n\n\n  // TAB PLUGIN DEFINITION\n  // =====================\n\n  var old = $.fn.tab\n\n  $.fn.tab = function ( option ) {\n    return this.each(function () {\n      var $this = $(this)\n      var data  = $this.data('bs.tab')\n\n      if (!data) $this.data('bs.tab', (data = new Tab(this)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.tab.Constructor = Tab\n\n\n  // TAB NO CONFLICT\n  // ===============\n\n  $.fn.tab.noConflict = function () {\n    $.fn.tab = old\n    return this\n  }\n\n\n  // TAB DATA-API\n  // ============\n\n  $(document).on('click.bs.tab.data-api', '[data-toggle=\"tab\"], [data-toggle=\"pill\"]', function (e) {\n    e.preventDefault()\n    $(this).tab('show')\n  })\n\n}(jQuery);\n\n/* ========================================================================\n * Bootstrap: affix.js v3.0.2\n * http://getbootstrap.com/javascript/#affix\n * ========================================================================\n * Copyright 2013 Twitter, Inc.\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+function ($) { \"use strict\";\n\n  // AFFIX CLASS DEFINITION\n  // ======================\n\n  var Affix = function (element, options) {\n    this.options = $.extend({}, Affix.DEFAULTS, options)\n    this.$window = $(window)\n      .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))\n      .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))\n\n    this.$element = $(element)\n    this.affixed  =\n    this.unpin    = null\n\n    this.checkPosition()\n  }\n\n  Affix.RESET = 'affix affix-top affix-bottom'\n\n  Affix.DEFAULTS = {\n    offset: 0\n  }\n\n  Affix.prototype.checkPositionWithEventLoop = function () {\n    setTimeout($.proxy(this.checkPosition, this), 1)\n  }\n\n  Affix.prototype.checkPosition = function () {\n    if (!this.$element.is(':visible')) return\n\n    var scrollHeight = $(document).height()\n    var scrollTop    = this.$window.scrollTop()\n    var position     = this.$element.offset()\n    var offset       = this.options.offset\n    var offsetTop    = offset.top\n    var offsetBottom = offset.bottom\n\n    if (typeof offset != 'object')         offsetBottom = offsetTop = offset\n    if (typeof offsetTop == 'function')    offsetTop    = offset.top()\n    if (typeof offsetBottom == 'function') offsetBottom = offset.bottom()\n\n    var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :\n                offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :\n                offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false\n\n    if (this.affixed === affix) return\n    if (this.unpin) this.$element.css('top', '')\n\n    this.affixed = affix\n    this.unpin   = affix == 'bottom' ? position.top - scrollTop : null\n\n    this.$element.removeClass(Affix.RESET).addClass('affix' + (affix ? '-' + affix : ''))\n\n    if (affix == 'bottom') {\n      this.$element.offset({ top: document.body.offsetHeight - offsetBottom - this.$element.height() })\n    }\n  }\n\n\n  // AFFIX PLUGIN DEFINITION\n  // =======================\n\n  var old = $.fn.affix\n\n  $.fn.affix = function (option) {\n    return this.each(function () {\n      var $this   = $(this)\n      var data    = $this.data('bs.affix')\n      var options = typeof option == 'object' && option\n\n      if (!data) $this.data('bs.affix', (data = new Affix(this, options)))\n      if (typeof option == 'string') data[option]()\n    })\n  }\n\n  $.fn.affix.Constructor = Affix\n\n\n  // AFFIX NO CONFLICT\n  // =================\n\n  $.fn.affix.noConflict = function () {\n    $.fn.affix = old\n    return this\n  }\n\n\n  // AFFIX DATA-API\n  // ==============\n\n  $(window).on('load', function () {\n    $('[data-spy=\"affix\"]').each(function () {\n      var $spy = $(this)\n      var data = $spy.data()\n\n      data.offset = data.offset || {}\n\n      if (data.offsetBottom) data.offset.bottom = data.offsetBottom\n      if (data.offsetTop)    data.offset.top    = data.offsetTop\n\n      $spy.affix(data)\n    })\n  })\n\n}(jQuery);\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/common-scripts.js",
    "content": "/*---LEFT BAR ACCORDION----*/\n$(function() {\n    $('#nav-accordion').dcAccordion({\n        eventType: 'click',\n        autoClose: true,\n        saveState: true,\n        disableLink: true,\n        speed: 'slow',\n        showCount: false,\n        autoExpand: true,\n//        cookie: 'dcjq-accordion-1',\n        classExpand: 'dcjq-current-parent'\n    });\n});\n\nvar Script = function () {\n\n//    sidebar dropdown menu auto scrolling\n\n    jQuery('#sidebar .sub-menu > a').click(function () {\n        var o = ($(this).offset());\n        diff = 250 - o.top;\n        if(diff>0)\n            $(\"#sidebar\").scrollTo(\"-=\"+Math.abs(diff),500);\n        else\n            $(\"#sidebar\").scrollTo(\"+=\"+Math.abs(diff),500);\n    });\n\n//    sidebar toggle\n\n    $(function() {\n        function responsiveView() {\n            var wSize = $(window).width();\n            if (wSize <= 768) {\n                $('#container').addClass('sidebar-close');\n                $('#sidebar > ul').hide();\n            }\n\n            if (wSize > 768) {\n                $('#container').removeClass('sidebar-close');\n                $('#sidebar > ul').show();\n            }\n        }\n        $(window).on('load', responsiveView);\n        $(window).on('resize', responsiveView);\n    });\n\n    $('.icon-reorder').click(function () {\n        if ($('#sidebar > ul').is(\":visible\") === true) {\n            $('#main-content').css({\n                'margin-left': '0px'\n            });\n            $('#sidebar').css({\n                'margin-left': '-210px'\n            });\n            $('#sidebar > ul').hide();\n            $(\"#container\").addClass(\"sidebar-closed\");\n        } else {\n            $('#main-content').css({\n                'margin-left': '210px'\n            });\n            $('#sidebar > ul').show();\n            $('#sidebar').css({\n                'margin-left': '0'\n            });\n            $(\"#container\").removeClass(\"sidebar-closed\");\n        }\n    });\n\n// custom scrollbar\n/*    $(\"#sidebar\").niceScroll({styler:\"fb\",cursorcolor:\"#e8403f\", cursorwidth: '3', cursorborderradius: '10px', background: '#404040', spacebarenabled:false, cursorborder: ''});\n\n    $(\"html\").niceScroll({styler:\"fb\",cursorcolor:\"#e8403f\", cursorwidth: '6', cursorborderradius: '10px', background: '#404040', spacebarenabled:false,  cursorborder: '', zindex: '1000'});*/\n\n// widget tools\n\n    jQuery('.panel .tools .icon-chevron-down').click(function () {\n        var el = jQuery(this).parents(\".panel\").children(\".panel-body\");\n        if (jQuery(this).hasClass(\"icon-chevron-down\")) {\n            jQuery(this).removeClass(\"icon-chevron-down\").addClass(\"icon-chevron-up\");\n            el.slideUp(200);\n        } else {\n            jQuery(this).removeClass(\"icon-chevron-up\").addClass(\"icon-chevron-down\");\n            el.slideDown(200);\n        }\n    });\n\n    jQuery('.panel .tools .icon-remove').click(function () {\n        jQuery(this).parents(\".panel\").parent().remove();\n    });\n\n\n//    tool tips\n\n    $('.tooltips').tooltip();\n\n//    popovers\n\n    $('.popovers').popover();\n\n\n\n// custom bar chart\n\n    if ($(\".custom-bar-chart\")) {\n        $(\".bar\").each(function () {\n            var i = $(this).find(\".value\").html();\n            $(this).find(\".value\").html(\"\");\n            $(this).find(\".value\").animate({\n                height: i\n            }, 2000)\n        })\n    }\n\n\n}();"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/count.js",
    "content": "function countUp(count)\n{\n    var div_by = 100,\n        speed = Math.round(count / div_by),\n        $display = $('.count'),\n        run_count = 1,\n        int_speed = 24;\n\n    var int = setInterval(function() {\n        if(run_count < div_by){\n            $display.text(speed * run_count);\n            run_count++;\n        } else if(parseInt($display.text()) < count) {\n            var curr_count = parseInt($display.text()) + 1;\n            $display.text(curr_count);\n        } else {\n            clearInterval(int);\n        }\n    }, int_speed);\n}\n\n/*countUp(495);*/\n\nfunction countUp2(count)\n{\n    var div_by = 100,\n        speed = Math.round(count / div_by),\n        $display = $('.count2'),\n        run_count = 1,\n        int_speed = 24;\n\n    var int = setInterval(function() {\n        if(run_count < div_by){\n            $display.text(speed * run_count);\n            run_count++;\n        } else if(parseInt($display.text()) < count) {\n            var curr_count = parseInt($display.text()) + 1;\n            $display.text(curr_count);\n        } else {\n            clearInterval(int);\n        }\n    }, int_speed);\n}\n\n/*countUp2(947);*/\n\nfunction countUp3(count)\n{\n    var div_by = 100,\n        speed = Math.round(count / div_by),\n        $display = $('.count3'),\n        run_count = 1,\n        int_speed = 24;\n\n    var int = setInterval(function() {\n        if(run_count < div_by){\n            $display.text(speed * run_count);\n            run_count++;\n        } else if(parseInt($display.text()) < count) {\n            var curr_count = parseInt($display.text()) + 1;\n            $display.text(curr_count);\n        } else {\n            clearInterval(int);\n        }\n    }, int_speed);\n}\n\n/*countUp3(328);*/\n\nfunction countUp4(count)\n{\n    var div_by = 100,\n        speed = Math.round(count / div_by),\n        $display = $('.count4'),\n        run_count = 1,\n        int_speed = 24;\n\n    var int = setInterval(function() {\n        if(run_count < div_by){\n            $display.text(speed * run_count);\n            run_count++;\n        } else if(parseInt($display.text()) < count) {\n            var curr_count = parseInt($display.text()) + 1;\n            $display.text(curr_count);\n        } else {\n            clearInterval(int);\n        }\n    }, int_speed);\n}\n\n/*\ncountUp4(10328);*/\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/easy-pie-chart.js",
    "content": "var Script = function () {\n\n// easy pie chart\n\n    $('.percentage').easyPieChart({\n        animate: 1000,\n        size: 135,\n        barColor:'#ff6c60'\n    });\n    $('.percentage-light').easyPieChart({\n        barColor: function(percent) {\n            percent /= 100;\n            return \"rgb(\" + Math.round(255 * (1-percent)) + \", \" + Math.round(255 * percent) + \", 0)\";\n        },\n        trackColor: '#666',\n        scaleColor: false,\n        lineCap: 'butt',\n        lineWidth: 15,\n        animate: 1000\n    });\n\n    $('.update-easy-pie-chart').click(function(){\n        $('.easy-pie-chart .percentage').each(function() {\n            var newValue = Math.floor(100*Math.random());\n            $(this).data('easyPieChart').update(newValue);\n            $('span', this).text(newValue);\n        });\n    });\n\n    $('.updateEasyPieChart').on('click', function(e) {\n        e.preventDefault();\n        $('.percentage, .percentage-light').each(function() {\n            var newValue = Math.round(100*Math.random());\n            $(this).data('easyPieChart').update(newValue);\n            $('span', this).text(newValue);\n        });\n    });\n\n}();"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/html5shiv.js",
    "content": "/*\n HTML5 Shiv v3.6.2pre | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed\n*/\n(function(l,f){function m(){var a=e.elements;return\"string\"==typeof a?a.split(\" \"):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();\na.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function(\"h,f\",\"return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&(\"+m().join().replace(/\\w+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c(\"'+a+'\")'})+\");return n}\")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement(\"p\");d=d.getElementsByTagName(\"head\")[0]||d.documentElement;c.innerHTML=\"x<style>article,aside,figcaption,figure,footer,header,hgroup,nav,section{display:block}mark{background:#FF0;color:#000}</style>\";\nc=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o=\"_html5shiv\",h=0,n={},g;(function(){try{var a=f.createElement(\"a\");a.innerHTML=\"<xyz></xyz>\";j=\"hidden\"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement(\"a\");var c=f.createDocumentFragment();b=\"undefined\"==typeof c.cloneNode||\n\"undefined\"==typeof c.createDocumentFragment||\"undefined\"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||\"abbr article aside audio bdi canvas data datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video\",version:\"3.6.2pre\",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:\"default\",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);if(g)return a.createDocumentFragment();\nfor(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/jquery.dcjqaccordion.2.7.js",
    "content": "/*\n * DC jQuery Vertical Accordion Menu - jQuery vertical accordion menu plugin\n * Copyright (c) 2011 Design Chemical\n *\n * Dual licensed under the MIT and GPL licenses:\n * \thttp://www.opensource.org/licenses/mit-license.php\n * \thttp://www.gnu.org/licenses/gpl.html\n *\n */\n\n(function($){\n\n\t$.fn.dcAccordion = function(options) {\n\n\t\t//set default options \n\t\tvar defaults = {\n\t\t\tclassParent\t : 'dcjq-parent',\n\t\t\tclassActive\t : 'active',\n\t\t\tclassArrow\t : 'dcjq-icon',\n\t\t\tclassCount\t : 'dcjq-count',\n\t\t\tclassExpand\t : 'dcjq-current-parent',\n\t\t\teventType\t : 'click',\n\t\t\thoverDelay\t : 300,\n\t\t\tmenuClose     : true,\n\t\t\tautoClose    : true,\n\t\t\tautoExpand\t : false,\n\t\t\tspeed        : 'slow',\n\t\t\tsaveState\t : true,\n\t\t\tdisableLink\t : true,\n\t\t\tshowCount : false,\n//\t\t\tcookie\t: 'dcjq-accordion'\n\t\t};\n\n\t\t//call in the default otions\n\t\tvar options = $.extend(defaults, options);\n\n\t\tthis.each(function(options){\n\n\t\t\tvar obj = this;\n\t\t\tsetUpAccordion();\n//\t\t\tif(defaults.saveState == true){\n//\t\t\t\tcheckCookie(defaults.cookie, obj);\n//\t\t\t}\n\t\t\tif(defaults.autoExpand == true){\n\t\t\t\t$('li.'+defaults.classExpand+' > a').addClass(defaults.classActive);\n\t\t\t}\n\t\t\tresetAccordion();\n\n\t\t\tif(defaults.eventType == 'hover'){\n\n\t\t\t\tvar config = {\n\t\t\t\t\tsensitivity: 2, // number = sensitivity threshold (must be 1 or higher)\n\t\t\t\t\tinterval: defaults.hoverDelay, // number = milliseconds for onMouseOver polling interval\n\t\t\t\t\tover: linkOver, // function = onMouseOver callback (REQUIRED)\n\t\t\t\t\ttimeout: defaults.hoverDelay, // number = milliseconds delay before onMouseOut\n\t\t\t\t\tout: linkOut // function = onMouseOut callback (REQUIRED)\n\t\t\t\t};\n\n\t\t\t\t$('li a',obj).hoverIntent(config);\n\t\t\t\tvar configMenu = {\n\t\t\t\t\tsensitivity: 2, // number = sensitivity threshold (must be 1 or higher)\n\t\t\t\t\tinterval: 1000, // number = milliseconds for onMouseOver polling interval\n\t\t\t\t\tover: menuOver, // function = onMouseOver callback (REQUIRED)\n\t\t\t\t\ttimeout: 1000, // number = milliseconds delay before onMouseOut\n\t\t\t\t\tout: menuOut // function = onMouseOut callback (REQUIRED)\n\t\t\t\t};\n\n\t\t\t\t$(obj).hoverIntent(configMenu);\n\n\t\t\t\t// Disable parent links\n\t\t\t\tif(defaults.disableLink == true){\n\n\t\t\t\t\t$('li a',obj).click(function(e){\n\t\t\t\t\t\tif($(this).siblings('ul').length >0){\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\n\t\t\t\t$('li a',obj).click(function(e){\n\n\t\t\t\t\t$activeLi = $(this).parent('li');\n\t\t\t\t\t$parentsLi = $activeLi.parents('li');\n\t\t\t\t\t$parentsUl = $activeLi.parents('ul');\n\n\t\t\t\t\t// Prevent browsing to link if has child links\n\t\t\t\t\tif(defaults.disableLink == true){\n\t\t\t\t\t\tif($(this).siblings('ul').length >0){\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Auto close sibling menus\n\t\t\t\t\tif(defaults.autoClose == true){\n\t\t\t\t\t\tautoCloseAccordion($parentsLi, $parentsUl);\n\t\t\t\t\t}\n\n\t\t\t\t\tif ($('> ul',$activeLi).is(':visible')){\n\t\t\t\t\t\t$('ul',$activeLi).slideUp(defaults.speed);\n\t\t\t\t\t\t$('a',$activeLi).removeClass(defaults.classActive);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(this).siblings('ul').slideToggle(defaults.speed);\n\t\t\t\t\t\t$('> a',$activeLi).addClass(defaults.classActive);\n\t\t\t\t\t}\n\t\t\t\t\t\n//\t\t\t\t\t// Write cookie if save state is on\n//\t\t\t\t\tif(defaults.saveState == true){\n//\t\t\t\t\t\tcreateCookie(defaults.cookie, obj);\n//\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Set up accordion\n\t\t\tfunction setUpAccordion(){\n\n\t\t\t\t$arrow = '<span class=\"'+defaults.classArrow+'\"></span>';\n\t\t\t\tvar classParentLi = defaults.classParent+'-li';\n\t\t\t\t$('> ul',obj).show();\n\t\t\t\t$('li',obj).each(function(){\n\t\t\t\t\tif($('> ul',this).length > 0){\n\t\t\t\t\t\t$(this).addClass(classParentLi);\n\t\t\t\t\t\t$('> a',this).addClass(defaults.classParent).append($arrow);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\t$('> ul',obj).hide();\n\t\t\t\tif(defaults.showCount == true){\n\t\t\t\t\t$('li.'+classParentLi,obj).each(function(){\n\t\t\t\t\t\tif(defaults.disableLink == true){\n\t\t\t\t\t\t\tvar getCount = parseInt($('ul a:not(.'+defaults.classParent+')',this).length);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar getCount = parseInt($('ul a',this).length);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$('> a',this).append(' <span class=\"'+defaults.classCount+'\">'+getCount+'</span>');\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\t\n\t\t\tfunction linkOver(){\n\n\t\t\t$activeLi = $(this).parent('li');\n\t\t\t$parentsLi = $activeLi.parents('li');\n\t\t\t$parentsUl = $activeLi.parents('ul');\n\n\t\t\t// Auto close sibling menus\n\t\t\tif(defaults.autoClose == true){\n\t\t\t\tautoCloseAccordion($parentsLi, $parentsUl);\n\n\t\t\t}\n\n\t\t\tif ($('> ul',$activeLi).is(':visible')){\n\t\t\t\t$('ul',$activeLi).slideUp(defaults.speed);\n\t\t\t\t$('a',$activeLi).removeClass(defaults.classActive);\n\t\t\t} else {\n\t\t\t\t$(this).siblings('ul').slideToggle(defaults.speed);\n\t\t\t\t$('> a',$activeLi).addClass(defaults.classActive);\n\t\t\t}\n\n\t\t\t// Write cookie if save state is on\n\t\t\tif(defaults.saveState == true){\n\t\t\t\tcreateCookie(defaults.cookie, obj);\n\t\t\t}\n\t\t}\n\n\t\tfunction linkOut(){\n\t\t}\n\n\t\tfunction menuOver(){\n\t\t}\n\n\t\tfunction menuOut(){\n\n\t\t\tif(defaults.menuClose == true){\n\t\t\t\t$('ul',obj).slideUp(defaults.speed);\n\t\t\t\t// Reset active links\n\t\t\t\t$('a',obj).removeClass(defaults.classActive);\n\t\t\t\tcreateCookie(defaults.cookie, obj);\n\t\t\t}\n\t\t}\n\n\t\t// Auto-Close Open Menu Items\n\t\tfunction autoCloseAccordion($parentsLi, $parentsUl){\n\t\t\t$('ul',obj).not($parentsUl).slideUp(defaults.speed);\n\t\t\t// Reset active links\n\t\t\t$('a',obj).removeClass(defaults.classActive);\n\t\t\t$('> a',$parentsLi).addClass(defaults.classActive);\n\t\t}\n\t\t// Reset accordion using active links\n\t\tfunction resetAccordion(){\n\t\t\t$('ul',obj).hide();\n\t\t\t$allActiveLi = $('a.'+defaults.classActive,obj);\n\t\t\t$allActiveLi.siblings('ul').show();\n\t\t}\n\t\t});\n\n\t\t// Retrieve cookie value and set active items\n//\t\tfunction checkCookie(cookieId, obj){\n//\t\t\tvar cookieVal = $.cookie(cookieId);\n//\t\t\tif(cookieVal != null){\n//\t\t\t\t// create array from cookie string\n//\t\t\t\tvar activeArray = cookieVal.split(',');\n//\t\t\t\t$.each(activeArray, function(index,value){\n//\t\t\t\t\tvar $cookieLi = $('li:eq('+value+')',obj);\n//\t\t\t\t\t$('> a',$cookieLi).addClass(defaults.classActive);\n//\t\t\t\t\tvar $parentsLi = $cookieLi.parents('li');\n//\t\t\t\t\t$('> a',$parentsLi).addClass(defaults.classActive);\n//\t\t\t\t});\n//\t\t\t}\n//\t\t}\n\n\t\t// Write cookie\n//\t\tfunction createCookie(cookieId, obj){\n//\t\t\tvar activeIndex = [];\n//\t\t\t// Create array of active items index value\n//\t\t\t$('li a.'+defaults.classActive,obj).each(function(i){\n//\t\t\t\tvar $arrayItem = $(this).parent('li');\n//\t\t\t\tvar itemIndex = $('li',obj).index($arrayItem);\n//\t\t\t\t\tactiveIndex.push(itemIndex);\n//\t\t\t\t});\n//\t\t\t// Store in cookie\n//\t\t\t$.cookie(cookieId, activeIndex, { path: '/' });\n//\t\t}\n\t};\n})(jQuery);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/jquery.js",
    "content": "/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license\n//@ sourceMappingURL=jquery-1.10.2.min.map\n*/\n(function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f=\"1.10.2\",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,T=/\\S+/g,C=/^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,N=/^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,k=/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,E=/^[\\],:{}\\s]*$/,S=/(?:^|:|,)(?:\\s*\\[)+/g,A=/\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,j=/\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d+\\.|)\\d+(?:[eE][+-]?\\d+|)/g,D=/^-ms-/,L=/-([\\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||\"load\"===e.type||\"complete\"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener(\"DOMContentLoaded\",q,!1),e.removeEventListener(\"load\",q,!1)):(a.detachEvent(\"onreadystatechange\",q),e.detachEvent(\"onload\",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if(\"string\"==typeof e){if(i=\"<\"===e.charAt(0)&&\">\"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:\"\",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for(\"boolean\"==typeof s&&(c=s,s=arguments[1]||{},l=2),\"object\"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:\"jQuery\"+(f+Math.random()).replace(/\\D/g,\"\"),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger(\"ready\").off(\"ready\"))}},isFunction:function(e){return\"function\"===x.type(e)},isArray:Array.isArray||function(e){return\"array\"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+\"\":\"object\"==typeof e||\"function\"==typeof e?c[y.call(e)]||\"object\":typeof e},isPlainObject:function(e){var n;if(!e||\"object\"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,\"constructor\")&&!v.call(e.constructor.prototype,\"isPrototypeOf\"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||\"string\"!=typeof e)return null;\"boolean\"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:\"string\"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,\"@\").replace(j,\"]\").replace(S,\"\")))?Function(\"return \"+n)():(x.error(\"Invalid JSON: \"+n),t)},parseXML:function(n){var r,i;if(!n||\"string\"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,\"text/xml\")):(r=new ActiveXObject(\"Microsoft.XMLDOM\"),r.async=\"false\",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName(\"parsererror\").length||x.error(\"Invalid XML: \"+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,\"ms-\").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call(\"\\ufeff\\u00a0\")?function(e){return null==e?\"\":b.call(e)}:function(e){return null==e?\"\":(e+\"\").replace(C,\"\")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,\"string\"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if(\"number\"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return\"string\"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if(\"object\"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),\"complete\"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener(\"DOMContentLoaded\",q,!1),e.addEventListener(\"load\",q,!1);else{a.attachEvent(\"onreadystatechange\",q),e.attachEvent(\"onload\",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll(\"left\")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"),function(e,t){c[\"[object \"+t+\"]\"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:\"array\"===n||\"function\"!==n&&(0===t||\"number\"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b=\"sizzle\"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B=\"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",P=\"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",R=\"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",W=R.replace(\"w\",\"w#\"),$=\"\\\\[\"+P+\"*(\"+R+\")\"+P+\"*(?:([*^$|!~]?=)\"+P+\"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\"+W+\")|)|)\"+P+\"*\\\\]\",I=\":(\"+R+\")(?:\\\\(((['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\"+$.replace(3,8)+\")*)|.*)\\\\)|)\",z=RegExp(\"^\"+P+\"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\"+P+\"+$\",\"g\"),X=RegExp(\"^\"+P+\"*,\"+P+\"*\"),U=RegExp(\"^\"+P+\"*([>+~]|\"+P+\")\"+P+\"*\"),V=RegExp(P+\"*[+~]\"),Y=RegExp(\"=\"+P+\"*([^\\\\]'\\\"]*)\"+P+\"*\\\\]\",\"g\"),J=RegExp(I),G=RegExp(\"^\"+W+\"$\"),Q={ID:RegExp(\"^#(\"+R+\")\"),CLASS:RegExp(\"^\\\\.(\"+R+\")\"),TAG:RegExp(\"^(\"+R.replace(\"w\",\"w*\")+\")\"),ATTR:RegExp(\"^\"+$),PSEUDO:RegExp(\"^\"+I),CHILD:RegExp(\"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\"+P+\"*(even|odd|(([+-]|)(\\\\d*)n|)\"+P+\"*(?:([+-]|)\"+P+\"*(\\\\d+)|))\"+P+\"*\\\\)|)\",\"i\"),bool:RegExp(\"^(?:\"+B+\")$\",\"i\"),needsContext:RegExp(\"^\"+P+\"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\"+P+\"*((?:-\\\\d)?\\\\d*)\"+P+\"*\\\\)|)(?=[^-]|$)\",\"i\")},K=/^[^{]+\\{\\s*\\[native \\w/,Z=/^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\\d$/i,nt=/'|\\\\/g,rt=RegExp(\"\\\\\\\\([\\\\da-f]{1,6}\"+P+\"?|(\"+P+\")|.)\",\"ig\"),it=function(e,t,n){var r=\"0x\"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||\"string\"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&\"object\"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute(\"id\"))?m=d.replace(nt,\"\\\\$&\"):t.setAttribute(\"id\",m),m=\"[id='\"+m+\"'] \",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(\",\")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute(\"id\")}}}return kt(e.replace(z,\"$1\"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=\" \")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement(\"div\");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split(\"|\"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return\"input\"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return(\"input\"===n||\"button\"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?\"HTML\"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent(\"onbeforeunload\",function(){p()}),r.attributes=ut(function(e){return e.className=\"i\",!e.getAttribute(\"className\")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment(\"\")),!e.getElementsByTagName(\"*\").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML=\"<div class='a'></div><div class='a i'></div>\",e.firstChild.className=\"i\",2===e.getElementsByClassName(\"i\").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute(\"id\")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode(\"id\");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if(\"*\"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML=\"<select><option selected=''></option></select>\",e.querySelectorAll(\"[selected]\").length||g.push(\"\\\\[\"+P+\"*(?:value|\"+B+\")\"),e.querySelectorAll(\":checked\").length||g.push(\":checked\")}),ut(function(e){var t=n.createElement(\"input\");t.setAttribute(\"type\",\"hidden\"),e.appendChild(t).setAttribute(\"t\",\"\"),e.querySelectorAll(\"[t^='']\").length&&g.push(\"[*^$]=\"+P+\"*(?:''|\\\"\\\")\"),e.querySelectorAll(\":enabled\").length||g.push(\":enabled\",\":disabled\"),e.querySelectorAll(\"*,:x\"),g.push(\",.*:\")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,\"div\"),y.call(e,\"[s!='']:x\"),m.push(\"!=\",I)}),g=g.length&&RegExp(g.join(\"|\")),m=m.length&&RegExp(m.join(\"|\")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,\"='$1']\"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error(\"Syntax error, unrecognized expression: \"+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n=\"\",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if(\"string\"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{\">\":{dir:\"parentNode\",first:!0},\" \":{dir:\"parentNode\"},\"+\":{dir:\"previousSibling\",first:!0},\"~\":{dir:\"previousSibling\"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||\"\").replace(rt,it),\"~=\"===e[2]&&(e[3]=\" \"+e[3]+\" \"),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),\"nth\"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*(\"even\"===e[3]||\"odd\"===e[3])),e[5]=+(e[7]+e[8]||\"odd\"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(\")\",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return\"*\"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+\" \"];return t||(t=RegExp(\"(^|\"+P+\")\"+e+\"(\"+P+\"|$)\"))&&N(e,function(e){return t.test(\"string\"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute(\"class\")||\"\")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?\"!=\"===t:t?(i+=\"\",\"=\"===t?i===n:\"!=\"===t?i!==n:\"^=\"===t?n&&0===i.indexOf(n):\"*=\"===t?n&&i.indexOf(n)>-1:\"$=\"===t?n&&i.slice(-n.length)===n:\"~=\"===t?(\" \"+i+\" \").indexOf(n)>-1:\"|=\"===t?i===n||i.slice(0,n.length+1)===n+\"-\":!1):!0}},CHILD:function(e,t,n,r,i){var o=\"nth\"!==e.slice(0,3),a=\"last\"!==e.slice(-4),s=\"of-type\"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?\"nextSibling\":\"previousSibling\",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g=\"only\"===e&&!h&&\"nextSibling\"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error(\"unsupported pseudo: \"+e);return r[b]?r(t):r.length>1?(n=[e,e,\"\",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,\"$1\"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||\"\")||at.error(\"unsupported lang: \"+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute(\"xml:lang\")||t.getAttribute(\"lang\"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+\"-\");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&!!e.checked||\"option\"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>\"@\"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return\"input\"===t&&\"button\"===e.type||\"button\"===t},text:function(e){var t;return\"input\"===e.nodeName.toLowerCase()&&\"text\"===e.type&&(null==(t=e.getAttribute(\"type\"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+\" \"];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z,\" \")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r=\"\";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&\"parentNode\"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+\" \"+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||\"*\",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[\" \"],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:\" \"===e[l-2].type?\"*\":\"\"})).replace(z,\"$1\"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b=\"0\",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG(\"*\",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+\" \"];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&\"ID\"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split(\"\").sort(A).join(\"\")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement(\"div\"))}),ut(function(e){return e.innerHTML=\"<a href='#'></a>\",\"#\"===e.firstChild.getAttribute(\"href\")})||ct(\"type|href|height|width\",function(e,n,r){return r?t:e.getAttribute(n,\"type\"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML=\"<input/>\",e.firstChild.setAttribute(\"value\",\"\"),\"\"===e.firstChild.getAttribute(\"value\")})||ct(\"value\",function(e,n,r){return r||\"input\"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute(\"disabled\")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[\":\"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e=\"string\"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);\"function\"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&\"string\"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[[\"resolve\",\"done\",x.Callbacks(\"once memory\"),\"resolved\"],[\"reject\",\"fail\",x.Callbacks(\"once memory\"),\"rejected\"],[\"notify\",\"progress\",x.Callbacks(\"memory\")]],n=\"pending\",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+\"With\"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+\"With\"](this===i?r:this,arguments),this},i[o[0]+\"With\"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement(\"div\");if(d.setAttribute(\"className\",\"t\"),d.innerHTML=\"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\",n=d.getElementsByTagName(\"*\")||[],r=d.getElementsByTagName(\"a\")[0],!r||!r.style||!n.length)return t;s=a.createElement(\"select\"),u=s.appendChild(a.createElement(\"option\")),o=d.getElementsByTagName(\"input\")[0],r.style.cssText=\"top:1px;float:left;opacity:.5\",t.getSetAttribute=\"t\"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName(\"tbody\").length,t.htmlSerialize=!!d.getElementsByTagName(\"link\").length,t.style=/top/.test(r.getAttribute(\"style\")),t.hrefNormalized=\"/a\"===r.getAttribute(\"href\"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement(\"form\").enctype,t.html5Clone=\"<:nav></:nav>\"!==a.createElement(\"nav\").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement(\"input\"),o.setAttribute(\"value\",\"\"),t.input=\"\"===o.getAttribute(\"value\"),o.value=\"t\",o.setAttribute(\"type\",\"radio\"),t.radioValue=\"t\"===o.value,o.setAttribute(\"checked\",\"t\"),o.setAttribute(\"name\",\"t\"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent(\"onclick\",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c=\"on\"+f,\"t\"),t[f+\"Bubbles\"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip=\"content-box\",d.cloneNode(!0).style.backgroundClip=\"\",t.clearCloneStyle=\"content-box\"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast=\"0\"!==f,x(function(){var n,r,o,s=\"padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;\",l=a.getElementsByTagName(\"body\")[0];l&&(n=a.createElement(\"div\"),n.style.cssText=\"border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px\",l.appendChild(n).appendChild(d),d.innerHTML=\"<table><tr><td></td><td>t</td></tr></table>\",o=d.getElementsByTagName(\"td\"),o[0].style.cssText=\"padding:0;margin:0;border:0;display:none\",p=0===o[0].offsetHeight,o[0].style.display=\"\",o[1].style.display=\"none\",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML=\"\",d.style.cssText=\"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition=\"1%\"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable=\"4px\"===(e.getComputedStyle(d,null)||{width:\"4px\"}).width,r=d.appendChild(a.createElement(\"div\")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width=\"0\",d.style.width=\"1px\",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML=\"\",d.style.cssText=s+\"width:1px;padding:1px;display:inline;zoom:1\",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display=\"block\",d.innerHTML=\"<div></div>\",d.firstChild.style.width=\"5px\",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t\n}({});var B=/(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||\"string\"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),(\"object\"==typeof n||\"function\"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),\"string\"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(\" \")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute(\"classid\")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,\"parsedAttrs\"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf(\"data-\")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,\"parsedAttrs\",!0)}return o}return\"object\"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i=\"data-\"+n.replace(P,\"-$1\").toLowerCase();if(r=e.getAttribute(i),\"string\"==typeof r){try{r=\"true\"===r?!0:\"false\"===r?!1:\"null\"===r?null:+r+\"\"===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if((\"data\"!==t||!x.isEmptyObject(e[t]))&&\"toJSON\"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||\"fx\")+\"queue\",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||\"fx\";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};\"inprogress\"===i&&(i=n.shift(),r--),i&&(\"fx\"===t&&n.unshift(\"inprogress\"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+\"queueHooks\";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks(\"once memory\").add(function(){x._removeData(e,t+\"queue\"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return\"string\"!=typeof e&&(n=e,e=\"fx\",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),\"fx\"===e&&\"inprogress\"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||\"fx\",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||\"fx\",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};\"string\"!=typeof e&&(n=e,e=t),e=e||\"fx\";while(s--)r=x._data(a[s],e+\"queueHooks\"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\\t\\r\\n\\f]/g,V=/\\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=\"string\"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||\"\").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(\" \"+n.className+\" \").replace(U,\" \"):\" \")){o=0;while(i=t[o++])0>r.indexOf(\" \"+i+\" \")&&(r+=i+\" \");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||\"string\"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||\"\").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(\" \"+n.className+\" \").replace(U,\" \"):\"\")){o=0;while(i=t[o++])while(r.indexOf(\" \"+i+\" \")>=0)r=r.replace(\" \"+i+\" \",\" \");n.className=e?x.trim(r):\"\"}return this},toggleClass:function(e,t){var n=typeof e;return\"boolean\"==typeof t&&\"string\"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(\"string\"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||\"boolean\"===n)&&(this.className&&x._data(this,\"__className__\",this.className),this.className=this.className||e===!1?\"\":x._data(this,\"__className__\")||\"\")})},hasClass:function(e){var t=\" \"+e+\" \",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(\" \"+this[n].className+\" \").replace(U,\" \").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o=\"\":\"number\"==typeof o?o+=\"\":x.isArray(o)&&(o=x.map(o,function(e){return null==e?\"\":e+\"\"})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&\"set\"in r&&r.set(this,o,\"value\")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&\"get\"in r&&(n=r.get(o,\"value\"))!==t?n:(n=o.value,\"string\"==typeof n?n.replace(V,\"\"):null==n?\"\":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,\"value\");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o=\"select-one\"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute(\"disabled\"))||n.parentNode.disabled&&x.nodeName(n.parentNode,\"optgroup\"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&\"get\"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&\"set\"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+\"\"),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase(\"default-\"+n)]=e[r]=!1:x.attr(e,n,\"\"),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&\"radio\"===t&&x.nodeName(e,\"input\")){var n=e.value;return e.setAttribute(\"type\",t),n&&(e.value=n),t}}}},propFix:{\"for\":\"htmlFor\",\"class\":\"className\"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&\"set\"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&\"get\"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,\"tabindex\");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase(\"default-\"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase(\"default-\"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,\"input\")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+=\"\",\"value\"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&\"\"!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,\"\"===t?!1:t,n)}},x.each([\"width\",\"height\"],function(e,n){x.attrHooks[n]={set:function(e,r){return\"\"===r?(e.setAttribute(n,\"auto\"),r):t}}})),x.support.hrefNormalized||x.each([\"href\",\"src\"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+\"\"}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each([\"tabIndex\",\"readOnly\",\"maxLength\",\"cellSpacing\",\"cellPadding\",\"rowSpan\",\"colSpan\",\"useMap\",\"frameBorder\",\"contentEditable\"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype=\"encoding\"),x.each([\"radio\",\"checkbox\"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute(\"value\")?\"on\":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||\"\").match(T)||[\"\"],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||\"\").split(\".\").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(\".\")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent(\"on\"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||\"\").match(T)||[\"\"],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||\"\").split(\".\").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp(\"(^|\\\\.)\"+h.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&(\"**\"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,\"events\"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,\"type\")?n.type:n,m=v.call(n,\"namespace\")?n.namespace.split(\".\"):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(\".\")>=0&&(m=g.split(\".\"),g=m.shift(),m.sort()),l=0>g.indexOf(\":\")&&\"on\"+g,n=n[x.expando]?n:new x.Event(g,\"object\"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join(\".\"),n.namespace_re=n.namespace?RegExp(\"(^|\\\\.)\"+m.join(\"\\\\.(?:.*\\\\.|)\")+\"(\\\\.|$)\"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,\"events\")||{})[n.type]&&x._data(u,\"handle\"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,\"events\")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||\"click\"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||\"click\"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+\" \",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:\"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),fixHooks:{},keyHooks:{props:\"char charCode key keyCode\".split(\" \"),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:\"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:\"focusin\"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:\"focusout\"},click:{trigger:function(){return x.nodeName(this,\"input\")&&\"checkbox\"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,\"a\")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r=\"on\"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:\"mouseover\",mouseleave:\"mouseout\"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,\"form\")?!1:(x.event.add(this,\"click._submit keypress._submit\",function(e){var n=e.target,r=x.nodeName(n,\"input\")||x.nodeName(n,\"button\")?n.form:t;r&&!x._data(r,\"submitBubbles\")&&(x.event.add(r,\"submit._submit\",function(e){e._submit_bubble=!0}),x._data(r,\"submitBubbles\",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate(\"submit\",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,\"form\")?!1:(x.event.remove(this,\"._submit\"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?((\"checkbox\"===this.type||\"radio\"===this.type)&&(x.event.add(this,\"propertychange._change\",function(e){\"checked\"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,\"click._change\",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate(\"change\",this,e,!0)})),!1):(x.event.add(this,\"beforeactivate._change\",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,\"changeBubbles\")&&(x.event.add(t,\"change._change\",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate(\"change\",this.parentNode,e,!0)}),x._data(t,\"changeBubbles\",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||\"radio\"!==n.type&&\"checkbox\"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,\"._change\"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:\"focusin\",blur:\"focusout\"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if(\"object\"==typeof e){\"string\"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&(\"string\"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+\".\"+i.namespace:i.origType,i.selector,i.handler),this;if(\"object\"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||\"function\"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\\[\\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if(\"string\"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+\" \"+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,\"string\"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||\"string\"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?\"string\"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n=\"string\"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,\"parentNode\")},parentsUntil:function(e,t,n){return x.dir(e,\"parentNode\",n)},next:function(e){return pt(e,\"nextSibling\")},prev:function(e){return pt(e,\"previousSibling\")},nextAll:function(e){return x.dir(e,\"nextSibling\")},prevAll:function(e){return x.dir(e,\"previousSibling\")},nextUntil:function(e,t,n){return x.dir(e,\"nextSibling\",n)},prevUntil:function(e,t,n){return x.dir(e,\"previousSibling\",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,\"iframe\")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return\"Until\"!==e.slice(-5)&&(r=n),r&&\"string\"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=\":not(\"+e+\")\"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if(\"string\"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split(\"|\"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht=\"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",gt=/ jQuery\\d+=\"(?:null|\\d+)\"/g,mt=RegExp(\"<(?:\"+ht+\")[\\\\s/>]\",\"i\"),yt=/^\\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,bt=/<([\\w:]+)/,xt=/<tbody/i,wt=/<|&#?\\w+;/,Tt=/<(?:script|style|link)/i,Ct=/^(?:checkbox|radio)$/i,Nt=/checked\\s*(?:[^=]|=\\s*.checked.)/i,kt=/^$|\\/(?:java|ecma)script/i,Et=/^true\\/(.*)/,St=/^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,At={option:[1,\"<select multiple='multiple'>\",\"</select>\"],legend:[1,\"<fieldset>\",\"</fieldset>\"],area:[1,\"<map>\",\"</map>\"],param:[1,\"<object>\",\"</object>\"],thead:[1,\"<table>\",\"</table>\"],tr:[2,\"<table><tbody>\",\"</tbody></table>\"],col:[2,\"<table><tbody></tbody><colgroup>\",\"</colgroup></table>\"],td:[3,\"<table><tbody><tr>\",\"</tr></tbody></table>\"],_default:x.support.htmlSerialize?[0,\"\",\"\"]:[1,\"X<div>\",\"</div>\"]},jt=dt(a),Dt=jt.appendChild(a.createElement(\"div\"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,\"script\")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,\"select\")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,\"\"):t;if(!(\"string\"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||[\"\",\"\"])[1].toLowerCase()])){e=e.replace(vt,\"<$1></$2>\");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||\"string\"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,\"script\"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,\"script\"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||\"\")&&!x._data(i,\"globalEval\")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||\"\").replace(St,\"\")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,\"table\")&&x.nodeName(1===t.nodeType?t:t.firstChild,\"tr\")?e.getElementsByTagName(\"tbody\")[0]||e.appendChild(e.ownerDocument.createElement(\"tbody\")):e}function Ht(e){return e.type=(null!==x.find.attr(e,\"type\"))+\"/\"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute(\"type\"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,\"globalEval\",!t||x._data(t[r],\"globalEval\"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}\"script\"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):\"object\"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):\"input\"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):\"option\"===n?t.defaultSelected=t.selected=e.defaultSelected:(\"input\"===n||\"textarea\"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:\"append\",prependTo:\"prepend\",insertBefore:\"before\",insertAfter:\"after\",replaceAll:\"replaceWith\"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||\"*\"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||\"*\"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test(\"<\"+e.nodeName+\">\")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,\"script\"),r.length>0&&_t(r,!l&&Ft(e,\"script\")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if(\"object\"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement(\"div\")),l=(bt.exec(o)||[\"\",\"\"])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,\"<$1></$2>\")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o=\"table\"!==l||xt.test(o)?\"<table>\"!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],\"tbody\")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent=\"\";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,\"input\"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),\"script\"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||\"\")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle);\nu[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:\"GET\",dataType:\"script\",async:!1,global:!1,\"throws\":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,\"body\")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\\([^)]*\\)/i,It=/opacity\\s*=\\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp(\"^(\"+w+\")(.*)$\",\"i\"),Yt=RegExp(\"^(\"+w+\")(?!px)[a-z%]+$\",\"i\"),Jt=RegExp(\"^([+-])=(\"+w+\")\",\"i\"),Gt={BODY:\"block\"},Qt={position:\"absolute\",visibility:\"hidden\",display:\"block\"},Kt={letterSpacing:0,fontWeight:400},Zt=[\"Top\",\"Right\",\"Bottom\",\"Left\"],en=[\"Webkit\",\"O\",\"Moz\",\"ms\"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,\"none\"===x.css(e,\"display\")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,\"olddisplay\"),n=r.style.display,t?(o[a]||\"none\"!==n||(r.style.display=\"\"),\"\"===r.style.display&&nn(r)&&(o[a]=x._data(r,\"olddisplay\",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&\"none\"!==n||!i)&&x._data(r,\"olddisplay\",i?n:x.css(r,\"display\"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&\"none\"!==r.style.display&&\"\"!==r.style.display||(r.style.display=t?o[a]||\"\":\"none\"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return\"boolean\"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,\"opacity\");return\"\"===n?\"1\":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{\"float\":x.support.cssFloat?\"cssFloat\":\"styleFloat\"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&\"get\"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,\"string\"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a=\"number\"),!(null==r||\"number\"===a&&isNaN(r)||(\"number\"!==a||x.cssNumber[l]||(r+=\"px\"),x.support.clearCloneStyle||\"\"!==r||0!==n.indexOf(\"background\")||(u[n]=\"inherit\"),s&&\"set\"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&\"get\"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),\"normal\"===a&&n in Kt&&(a=Kt[n]),\"\"===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(\"\"!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left=\"fontSize\"===n?\"1em\":l,l=u.pixelLeft+\"px\",u.left=i,a&&(o.left=a)),\"\"===l?\"auto\":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||\"px\"):t}function an(e,t,n,r,i){var o=n===(r?\"border\":\"content\")?4:\"width\"===t?1:0,a=0;for(;4>o;o+=2)\"margin\"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?(\"content\"===n&&(a-=x.css(e,\"padding\"+Zt[o],!0,i)),\"margin\"!==n&&(a-=x.css(e,\"border\"+Zt[o]+\"Width\",!0,i))):(a+=x.css(e,\"padding\"+Zt[o],!0,i),\"padding\"!==n&&(a+=x.css(e,\"border\"+Zt[o]+\"Width\",!0,i)));return a}function sn(e,t,n){var r=!0,i=\"width\"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&\"border-box\"===x.css(e,\"boxSizing\",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?\"border\":\"content\"),r,o)+\"px\"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),\"none\"!==n&&n||(Pt=(Pt||x(\"<iframe frameborder='0' width='0' height='0'/>\").css(\"cssText\",\"display:block !important\")).appendTo(t.documentElement),t=(Pt[0].contentWindow||Pt[0].contentDocument).document,t.write(\"<!doctype html><html><body>\"),t.close(),n=un(e,t),Pt.detach()),Gt[e]=n),n}function un(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],\"display\");return n.remove(),r}x.each([\"height\",\"width\"],function(e,n){x.cssHooks[n]={get:function(e,r,i){return r?0===e.offsetWidth&&Xt.test(x.css(e,\"display\"))?x.swap(e,Qt,function(){return sn(e,n,i)}):sn(e,n,i):t},set:function(e,t,r){var i=r&&Rt(e);return on(e,t,r?an(e,n,r,x.support.boxSizing&&\"border-box\"===x.css(e,\"boxSizing\",!1,i),i):0)}}}),x.support.opacity||(x.cssHooks.opacity={get:function(e,t){return It.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||\"\")?.01*parseFloat(RegExp.$1)+\"\":t?\"1\":\"\"},set:function(e,t){var n=e.style,r=e.currentStyle,i=x.isNumeric(t)?\"alpha(opacity=\"+100*t+\")\":\"\",o=r&&r.filter||n.filter||\"\";n.zoom=1,(t>=1||\"\"===t)&&\"\"===x.trim(o.replace($t,\"\"))&&n.removeAttribute&&(n.removeAttribute(\"filter\"),\"\"===t||r&&!r.filter)||(n.filter=$t.test(o)?o.replace($t,i):o+\" \"+i)}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,n){return n?x.swap(e,{display:\"inline-block\"},Wt,[e,\"marginRight\"]):t}}),!x.support.pixelPosition&&x.fn.position&&x.each([\"top\",\"left\"],function(e,n){x.cssHooks[n]={get:function(e,r){return r?(r=Wt(e,n),Yt.test(r)?x(e).position()[n]+\"px\":r):t}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight||!x.support.reliableHiddenOffsets&&\"none\"===(e.style&&e.style.display||x.css(e,\"display\"))},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:\"\",padding:\"\",border:\"Width\"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o=\"string\"==typeof n?n.split(\" \"):[n];for(;4>r;r++)i[e+Zt[r]+t]=o[r]||o[r-2]||o[0];return i}},Ut.test(e)||(x.cssHooks[e+t].set=on)});var cn=/%20/g,pn=/\\[\\]$/,fn=/\\r?\\n/g,dn=/^(?:submit|button|image|reset|file)$/i,hn=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,\"elements\");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(\":disabled\")&&hn.test(this.nodeName)&&!dn.test(e)&&(this.checked||!Ct.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace(fn,\"\\r\\n\")}}):{name:t.name,value:n.replace(fn,\"\\r\\n\")}}).get()}}),x.param=function(e,n){var r,i=[],o=function(e,t){t=x.isFunction(t)?t():null==t?\"\":t,i[i.length]=encodeURIComponent(e)+\"=\"+encodeURIComponent(t)};if(n===t&&(n=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){o(this.name,this.value)});else for(r in e)gn(r,e[r],n,o);return i.join(\"&\").replace(cn,\"+\")};function gn(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||pn.test(e)?r(e,i):gn(e+\"[\"+(\"object\"==typeof i?t:\"\")+\"]\",i,n,r)});else if(n||\"object\"!==x.type(t))r(e,t);else for(i in t)gn(e+\"[\"+i+\"]\",t[i],n,r)}x.each(\"blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu\".split(\" \"),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,\"**\"):this.off(t,e||\"**\",n)}});var mn,yn,vn=x.now(),bn=/\\?/,xn=/#.*$/,wn=/([?&])_=[^&]*/,Tn=/^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/gm,Cn=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Nn=/^(?:GET|HEAD)$/,kn=/^\\/\\//,En=/^([\\w.+-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,Sn=x.fn.load,An={},jn={},Dn=\"*/\".concat(\"*\");try{yn=o.href}catch(Ln){yn=a.createElement(\"a\"),yn.href=\"\",yn=yn.href}mn=En.exec(yn.toLowerCase())||[];function Hn(e){return function(t,n){\"string\"!=typeof t&&(n=t,t=\"*\");var r,i=0,o=t.toLowerCase().match(T)||[];if(x.isFunction(n))while(r=o[i++])\"+\"===r[0]?(r=r.slice(1)||\"*\",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function qn(e,n,r,i){var o={},a=e===jn;function s(l){var u;return o[l]=!0,x.each(e[l]||[],function(e,l){var c=l(n,r,i);return\"string\"!=typeof c||a||o[c]?a?!(u=c):t:(n.dataTypes.unshift(c),s(c),!1)}),u}return s(n.dataTypes[0])||!o[\"*\"]&&s(\"*\")}function _n(e,n){var r,i,o=x.ajaxSettings.flatOptions||{};for(i in n)n[i]!==t&&((o[i]?e:r||(r={}))[i]=n[i]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,n,r){if(\"string\"!=typeof e&&Sn)return Sn.apply(this,arguments);var i,o,a,s=this,l=e.indexOf(\" \");return l>=0&&(i=e.slice(l,e.length),e=e.slice(0,l)),x.isFunction(n)?(r=n,n=t):n&&\"object\"==typeof n&&(a=\"POST\"),s.length>0&&x.ajax({url:e,type:a,dataType:\"html\",data:n}).done(function(e){o=arguments,s.html(i?x(\"<div>\").append(x.parseHTML(e)).find(i):e)}).complete(r&&function(e,t){s.each(r,o||[e.responseText,t,e])}),this},x.each([\"ajaxStart\",\"ajaxStop\",\"ajaxComplete\",\"ajaxError\",\"ajaxSuccess\",\"ajaxSend\"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:yn,type:\"GET\",isLocal:Cn.test(mn[1]),global:!0,processData:!0,async:!0,contentType:\"application/x-www-form-urlencoded; charset=UTF-8\",accepts:{\"*\":Dn,text:\"text/plain\",html:\"text/html\",xml:\"application/xml, text/xml\",json:\"application/json, text/javascript\"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:\"responseXML\",text:\"responseText\",json:\"responseJSON\"},converters:{\"* text\":String,\"text html\":!0,\"text json\":x.parseJSON,\"text xml\":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?_n(_n(e,x.ajaxSettings),t):_n(x.ajaxSettings,e)},ajaxPrefilter:Hn(An),ajaxTransport:Hn(jn),ajax:function(e,n){\"object\"==typeof e&&(n=e,e=t),n=n||{};var r,i,o,a,s,l,u,c,p=x.ajaxSetup({},n),f=p.context||p,d=p.context&&(f.nodeType||f.jquery)?x(f):x.event,h=x.Deferred(),g=x.Callbacks(\"once memory\"),m=p.statusCode||{},y={},v={},b=0,w=\"canceled\",C={readyState:0,getResponseHeader:function(e){var t;if(2===b){if(!c){c={};while(t=Tn.exec(a))c[t[1].toLowerCase()]=t[2]}t=c[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===b?a:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return b||(e=v[n]=v[n]||e,y[e]=t),this},overrideMimeType:function(e){return b||(p.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>b)for(t in e)m[t]=[m[t],e[t]];else C.always(e[C.status]);return this},abort:function(e){var t=e||w;return u&&u.abort(t),k(0,t),this}};if(h.promise(C).complete=g.add,C.success=C.done,C.error=C.fail,p.url=((e||p.url||yn)+\"\").replace(xn,\"\").replace(kn,mn[1]+\"//\"),p.type=n.method||n.type||p.method||p.type,p.dataTypes=x.trim(p.dataType||\"*\").toLowerCase().match(T)||[\"\"],null==p.crossDomain&&(r=En.exec(p.url.toLowerCase()),p.crossDomain=!(!r||r[1]===mn[1]&&r[2]===mn[2]&&(r[3]||(\"http:\"===r[1]?\"80\":\"443\"))===(mn[3]||(\"http:\"===mn[1]?\"80\":\"443\")))),p.data&&p.processData&&\"string\"!=typeof p.data&&(p.data=x.param(p.data,p.traditional)),qn(An,p,n,C),2===b)return C;l=p.global,l&&0===x.active++&&x.event.trigger(\"ajaxStart\"),p.type=p.type.toUpperCase(),p.hasContent=!Nn.test(p.type),o=p.url,p.hasContent||(p.data&&(o=p.url+=(bn.test(o)?\"&\":\"?\")+p.data,delete p.data),p.cache===!1&&(p.url=wn.test(o)?o.replace(wn,\"$1_=\"+vn++):o+(bn.test(o)?\"&\":\"?\")+\"_=\"+vn++)),p.ifModified&&(x.lastModified[o]&&C.setRequestHeader(\"If-Modified-Since\",x.lastModified[o]),x.etag[o]&&C.setRequestHeader(\"If-None-Match\",x.etag[o])),(p.data&&p.hasContent&&p.contentType!==!1||n.contentType)&&C.setRequestHeader(\"Content-Type\",p.contentType),C.setRequestHeader(\"Accept\",p.dataTypes[0]&&p.accepts[p.dataTypes[0]]?p.accepts[p.dataTypes[0]]+(\"*\"!==p.dataTypes[0]?\", \"+Dn+\"; q=0.01\":\"\"):p.accepts[\"*\"]);for(i in p.headers)C.setRequestHeader(i,p.headers[i]);if(p.beforeSend&&(p.beforeSend.call(f,C,p)===!1||2===b))return C.abort();w=\"abort\";for(i in{success:1,error:1,complete:1})C[i](p[i]);if(u=qn(jn,p,n,C)){C.readyState=1,l&&d.trigger(\"ajaxSend\",[C,p]),p.async&&p.timeout>0&&(s=setTimeout(function(){C.abort(\"timeout\")},p.timeout));try{b=1,u.send(y,k)}catch(N){if(!(2>b))throw N;k(-1,N)}}else k(-1,\"No Transport\");function k(e,n,r,i){var c,y,v,w,T,N=n;2!==b&&(b=2,s&&clearTimeout(s),u=t,a=i||\"\",C.readyState=e>0?4:0,c=e>=200&&300>e||304===e,r&&(w=Mn(p,C,r)),w=On(p,w,C,c),c?(p.ifModified&&(T=C.getResponseHeader(\"Last-Modified\"),T&&(x.lastModified[o]=T),T=C.getResponseHeader(\"etag\"),T&&(x.etag[o]=T)),204===e||\"HEAD\"===p.type?N=\"nocontent\":304===e?N=\"notmodified\":(N=w.state,y=w.data,v=w.error,c=!v)):(v=N,(e||!N)&&(N=\"error\",0>e&&(e=0))),C.status=e,C.statusText=(n||N)+\"\",c?h.resolveWith(f,[y,N,C]):h.rejectWith(f,[C,N,v]),C.statusCode(m),m=t,l&&d.trigger(c?\"ajaxSuccess\":\"ajaxError\",[C,p,c?y:v]),g.fireWith(f,[C,N]),l&&(d.trigger(\"ajaxComplete\",[C,p]),--x.active||x.event.trigger(\"ajaxStop\")))}return C},getJSON:function(e,t,n){return x.get(e,t,n,\"json\")},getScript:function(e,n){return x.get(e,t,n,\"script\")}}),x.each([\"get\",\"post\"],function(e,n){x[n]=function(e,r,i,o){return x.isFunction(r)&&(o=o||i,i=r,r=t),x.ajax({url:e,type:n,dataType:o,data:r,success:i})}});function Mn(e,n,r){var i,o,a,s,l=e.contents,u=e.dataTypes;while(\"*\"===u[0])u.shift(),o===t&&(o=e.mimeType||n.getResponseHeader(\"Content-Type\"));if(o)for(s in l)if(l[s]&&l[s].test(o)){u.unshift(s);break}if(u[0]in r)a=u[0];else{for(s in r){if(!u[0]||e.converters[s+\" \"+u[0]]){a=s;break}i||(i=s)}a=a||i}return a?(a!==u[0]&&u.unshift(a),r[a]):t}function On(e,t,n,r){var i,o,a,s,l,u={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)u[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!l&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),l=o,o=c.shift())if(\"*\"===o)o=l;else if(\"*\"!==l&&l!==o){if(a=u[l+\" \"+o]||u[\"* \"+o],!a)for(i in u)if(s=i.split(\" \"),s[1]===o&&(a=u[l+\" \"+s[0]]||u[\"* \"+s[0]])){a===!0?a=u[i]:u[i]!==!0&&(o=s[0],c.unshift(s[1]));break}if(a!==!0)if(a&&e[\"throws\"])t=a(t);else try{t=a(t)}catch(p){return{state:\"parsererror\",error:a?p:\"No conversion from \"+l+\" to \"+o}}}return{state:\"success\",data:t}}x.ajaxSetup({accepts:{script:\"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"},contents:{script:/(?:java|ecma)script/},converters:{\"text script\":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter(\"script\",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type=\"GET\",e.global=!1)}),x.ajaxTransport(\"script\",function(e){if(e.crossDomain){var n,r=a.head||x(\"head\")[0]||a.documentElement;return{send:function(t,i){n=a.createElement(\"script\"),n.async=!0,e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,t){(t||!n.readyState||/loaded|complete/.test(n.readyState))&&(n.onload=n.onreadystatechange=null,n.parentNode&&n.parentNode.removeChild(n),n=null,t||i(200,\"success\"))},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(t,!0)}}}});var Fn=[],Bn=/(=)\\?(?=&|$)|\\?\\?/;x.ajaxSetup({jsonp:\"callback\",jsonpCallback:function(){var e=Fn.pop()||x.expando+\"_\"+vn++;return this[e]=!0,e}}),x.ajaxPrefilter(\"json jsonp\",function(n,r,i){var o,a,s,l=n.jsonp!==!1&&(Bn.test(n.url)?\"url\":\"string\"==typeof n.data&&!(n.contentType||\"\").indexOf(\"application/x-www-form-urlencoded\")&&Bn.test(n.data)&&\"data\");return l||\"jsonp\"===n.dataTypes[0]?(o=n.jsonpCallback=x.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,l?n[l]=n[l].replace(Bn,\"$1\"+o):n.jsonp!==!1&&(n.url+=(bn.test(n.url)?\"&\":\"?\")+n.jsonp+\"=\"+o),n.converters[\"script json\"]=function(){return s||x.error(o+\" was not called\"),s[0]},n.dataTypes[0]=\"json\",a=e[o],e[o]=function(){s=arguments},i.always(function(){e[o]=a,n[o]&&(n.jsonpCallback=r.jsonpCallback,Fn.push(o)),s&&x.isFunction(a)&&a(s[0]),s=a=t}),\"script\"):t});var Pn,Rn,Wn=0,$n=e.ActiveXObject&&function(){var e;for(e in Pn)Pn[e](t,!0)};function In(){try{return new e.XMLHttpRequest}catch(t){}}function zn(){try{return new e.ActiveXObject(\"Microsoft.XMLHTTP\")}catch(t){}}x.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&In()||zn()}:In,Rn=x.ajaxSettings.xhr(),x.support.cors=!!Rn&&\"withCredentials\"in Rn,Rn=x.support.ajax=!!Rn,Rn&&x.ajaxTransport(function(n){if(!n.crossDomain||x.support.cors){var r;return{send:function(i,o){var a,s,l=n.xhr();if(n.username?l.open(n.type,n.url,n.async,n.username,n.password):l.open(n.type,n.url,n.async),n.xhrFields)for(s in n.xhrFields)l[s]=n.xhrFields[s];n.mimeType&&l.overrideMimeType&&l.overrideMimeType(n.mimeType),n.crossDomain||i[\"X-Requested-With\"]||(i[\"X-Requested-With\"]=\"XMLHttpRequest\");try{for(s in i)l.setRequestHeader(s,i[s])}catch(u){}l.send(n.hasContent&&n.data||null),r=function(e,i){var s,u,c,p;try{if(r&&(i||4===l.readyState))if(r=t,a&&(l.onreadystatechange=x.noop,$n&&delete Pn[a]),i)4!==l.readyState&&l.abort();else{p={},s=l.status,u=l.getAllResponseHeaders(),\"string\"==typeof l.responseText&&(p.text=l.responseText);try{c=l.statusText}catch(f){c=\"\"}s||!n.isLocal||n.crossDomain?1223===s&&(s=204):s=p.text?200:404}}catch(d){i||o(-1,d)}p&&o(s,c,p,u)},n.async?4===l.readyState?setTimeout(r):(a=++Wn,$n&&(Pn||(Pn={},x(e).unload($n)),Pn[a]=r),l.onreadystatechange=r):r()},abort:function(){r&&r(t,!0)}}}});var Xn,Un,Vn=/^(?:toggle|show|hide)$/,Yn=RegExp(\"^(?:([+-])=|)(\"+w+\")([a-z%]*)$\",\"i\"),Jn=/queueHooks$/,Gn=[nr],Qn={\"*\":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Yn.exec(t),o=i&&i[3]||(x.cssNumber[e]?\"\":\"px\"),a=(x.cssNumber[e]||\"px\"!==o&&+r)&&Yn.exec(x.css(n.elem,e)),s=1,l=20;if(a&&a[3]!==o){o=o||a[3],i=i||[],a=+r||1;do s=s||\".5\",a/=s,x.style(n.elem,e,a+o);while(s!==(s=n.cur()/r)&&1!==s&&--l)}return i&&(a=n.start=+a||+r||0,n.unit=o,n.end=i[1]?a+(i[1]+1)*i[2]:+i[2]),n}]};function Kn(){return setTimeout(function(){Xn=t}),Xn=x.now()}function Zn(e,t,n){var r,i=(Qn[t]||[]).concat(Qn[\"*\"]),o=0,a=i.length;for(;a>o;o++)if(r=i[o].call(n,t,e))return r}function er(e,t,n){var r,i,o=0,a=Gn.length,s=x.Deferred().always(function(){delete l.elem}),l=function(){if(i)return!1;var t=Xn||Kn(),n=Math.max(0,u.startTime+u.duration-t),r=n/u.duration||0,o=1-r,a=0,l=u.tweens.length;for(;l>a;a++)u.tweens[a].run(o);return s.notifyWith(e,[u,o,n]),1>o&&l?n:(s.resolveWith(e,[u]),!1)},u=s.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:Xn||Kn(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,u.opts,t,n,u.opts.specialEasing[t]||u.opts.easing);return u.tweens.push(r),r},stop:function(t){var n=0,r=t?u.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)u.tweens[n].run(1);return t?s.resolveWith(e,[u,t]):s.rejectWith(e,[u,t]),this}}),c=u.props;for(tr(c,u.opts.specialEasing);a>o;o++)if(r=Gn[o].call(u,e,c,u.opts))return r;return x.map(c,Zn,u),x.isFunction(u.opts.start)&&u.opts.start.call(e,u),x.fx.timer(x.extend(l,{elem:e,anim:u,queue:u.opts.queue})),u.progress(u.opts.progress).done(u.opts.done,u.opts.complete).fail(u.opts.fail).always(u.opts.always)}function tr(e,t){var n,r,i,o,a;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),a=x.cssHooks[r],a&&\"expand\"in a){o=a.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(er,{tweener:function(e,t){x.isFunction(e)?(t=e,e=[\"*\"]):e=e.split(\" \");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Qn[n]=Qn[n]||[],Qn[n].unshift(t)},prefilter:function(e,t){t?Gn.unshift(e):Gn.push(e)}});function nr(e,t,n){var r,i,o,a,s,l,u=this,c={},p=e.style,f=e.nodeType&&nn(e),d=x._data(e,\"fxshow\");n.queue||(s=x._queueHooks(e,\"fx\"),null==s.unqueued&&(s.unqueued=0,l=s.empty.fire,s.empty.fire=function(){s.unqueued||l()}),s.unqueued++,u.always(function(){u.always(function(){s.unqueued--,x.queue(e,\"fx\").length||s.empty.fire()})})),1===e.nodeType&&(\"height\"in t||\"width\"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],\"inline\"===x.css(e,\"display\")&&\"none\"===x.css(e,\"float\")&&(x.support.inlineBlockNeedsLayout&&\"inline\"!==ln(e.nodeName)?p.zoom=1:p.display=\"inline-block\")),n.overflow&&(p.overflow=\"hidden\",x.support.shrinkWrapBlocks||u.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],Vn.exec(i)){if(delete t[r],o=o||\"toggle\"===i,i===(f?\"hide\":\"show\"))continue;c[r]=d&&d[r]||x.style(e,r)}if(!x.isEmptyObject(c)){d?\"hidden\"in d&&(f=d.hidden):d=x._data(e,\"fxshow\",{}),o&&(d.hidden=!f),f?x(e).show():u.done(function(){x(e).hide()}),u.done(function(){var t;x._removeData(e,\"fxshow\");for(t in c)x.style(e,t,c[t])});for(r in c)a=Zn(f?d[r]:0,r,u),r in d||(d[r]=a.start,f&&(a.end=a.start,a.start=\"width\"===r||\"height\"===r?1:0))}}function rr(e,t,n,r,i){return new rr.prototype.init(e,t,n,r,i)}x.Tween=rr,rr.prototype={constructor:rr,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||\"swing\",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?\"\":\"px\")},cur:function(){var e=rr.propHooks[this.prop];return e&&e.get?e.get(this):rr.propHooks._default.get(this)},run:function(e){var t,n=rr.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):rr.propHooks._default.set(this),this}},rr.prototype.init.prototype=rr.prototype,rr.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,\"\"),t&&\"auto\"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},rr.propHooks.scrollTop=rr.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each([\"toggle\",\"show\",\"hide\"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||\"boolean\"==typeof e?n.apply(this,arguments):this.animate(ir(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(nn).css(\"opacity\",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),a=function(){var t=er(this,x.extend({},e),o);(i||x._data(this,\"finish\"))&&t.stop(!0)};return a.finish=a,i||o.queue===!1?this.each(a):this.queue(o.queue,a)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return\"string\"!=typeof e&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||\"fx\",[]),this.each(function(){var t=!0,n=null!=e&&e+\"queueHooks\",o=x.timers,a=x._data(this);if(n)a[n]&&a[n].stop&&i(a[n]);else for(n in a)a[n]&&a[n].stop&&Jn.test(n)&&i(a[n]);for(n=o.length;n--;)o[n].elem!==this||null!=e&&o[n].queue!==e||(o[n].anim.stop(r),t=!1,o.splice(n,1));(t||!r)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||\"fx\"),this.each(function(){var t,n=x._data(this),r=n[e+\"queue\"],i=n[e+\"queueHooks\"],o=x.timers,a=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;a>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function ir(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=Zt[i],r[\"margin\"+n]=r[\"padding\"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:ir(\"show\"),slideUp:ir(\"hide\"),slideToggle:ir(\"toggle\"),fadeIn:{opacity:\"show\"},fadeOut:{opacity:\"hide\"},fadeToggle:{opacity:\"toggle\"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&\"object\"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:\"number\"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue=\"fx\"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=rr.prototype.init,x.fx.tick=function(){var e,n=x.timers,r=0;for(Xn=x.now();n.length>r;r++)e=n[r],e()||n[r]!==e||n.splice(r--,1);n.length||x.fx.stop(),Xn=t},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){Un||(Un=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(Un),Un=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){x.offset.setOffset(this,e,t)});var n,r,o={top:0,left:0},a=this[0],s=a&&a.ownerDocument;if(s)return n=s.documentElement,x.contains(n,a)?(typeof a.getBoundingClientRect!==i&&(o=a.getBoundingClientRect()),r=or(s),{top:o.top+(r.pageYOffset||n.scrollTop)-(n.clientTop||0),left:o.left+(r.pageXOffset||n.scrollLeft)-(n.clientLeft||0)}):o},x.offset={setOffset:function(e,t,n){var r=x.css(e,\"position\");\"static\"===r&&(e.style.position=\"relative\");var i=x(e),o=i.offset(),a=x.css(e,\"top\"),s=x.css(e,\"left\"),l=(\"absolute\"===r||\"fixed\"===r)&&x.inArray(\"auto\",[a,s])>-1,u={},c={},p,f;l?(c=i.position(),p=c.top,f=c.left):(p=parseFloat(a)||0,f=parseFloat(s)||0),x.isFunction(t)&&(t=t.call(e,n,o)),null!=t.top&&(u.top=t.top-o.top+p),null!=t.left&&(u.left=t.left-o.left+f),\"using\"in t?t.using.call(e,u):i.css(u)}},x.fn.extend({position:function(){if(this[0]){var e,t,n={top:0,left:0},r=this[0];return\"fixed\"===x.css(r,\"position\")?t=r.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],\"html\")||(n=e.offset()),n.top+=x.css(e[0],\"borderTopWidth\",!0),n.left+=x.css(e[0],\"borderLeftWidth\",!0)),{top:t.top-n.top-x.css(r,\"marginTop\",!0),left:t.left-n.left-x.css(r,\"marginLeft\",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,\"html\")&&\"static\"===x.css(e,\"position\"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:\"pageXOffset\",scrollTop:\"pageYOffset\"},function(e,n){var r=/Y/.test(n);x.fn[e]=function(i){return x.access(this,function(e,i,o){var a=or(e);return o===t?a?n in a?a[n]:a.document.documentElement[i]:e[i]:(a?a.scrollTo(r?x(a).scrollLeft():o,r?o:x(a).scrollTop()):e[i]=o,t)},e,i,arguments.length,null)}});function or(e){return x.isWindow(e)?e:9===e.nodeType?e.defaultView||e.parentWindow:!1}x.each({Height:\"height\",Width:\"width\"},function(e,n){x.each({padding:\"inner\"+e,content:n,\"\":\"outer\"+e},function(r,i){x.fn[i]=function(i,o){var a=arguments.length&&(r||\"boolean\"!=typeof i),s=r||(i===!0||o===!0?\"margin\":\"border\");return x.access(this,function(n,r,i){var o;return x.isWindow(n)?n.document.documentElement[\"client\"+e]:9===n.nodeType?(o=n.documentElement,Math.max(n.body[\"scroll\"+e],o[\"scroll\"+e],n.body[\"offset\"+e],o[\"offset\"+e],o[\"client\"+e])):i===t?x.css(n,r,s):x.style(n,r,i,s)},n,a?i:t,a,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,\"object\"==typeof module&&module&&\"object\"==typeof module.exports?module.exports=x:(e.jQuery=e.$=x,\"function\"==typeof define&&define.amd&&define(\"jquery\",[],function(){return x}))})(window);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/jquery.nicescroll.js",
    "content": "/* jquery.nicescroll 3.5.0 InuYaksa*2013 MIT http://areaaperta.com/nicescroll */(function(e){var z=!1,E=!1,L=5E3,M=2E3,y=0,N=function(){var e=document.getElementsByTagName(\"script\"),e=e[e.length-1].src.split(\"?\")[0];return 0<e.split(\"/\").length?e.split(\"/\").slice(0,-1).join(\"/\")+\"/\":\"\"}(),H=[\"ms\",\"moz\",\"webkit\",\"o\"],v=window.requestAnimationFrame||!1,w=window.cancelAnimationFrame||!1;if(!v)for(var O in H){var F=H[O];v||(v=window[F+\"RequestAnimationFrame\"]);w||(w=window[F+\"CancelAnimationFrame\"]||window[F+\"CancelRequestAnimationFrame\"])}var A=window.MutationObserver||window.WebKitMutationObserver||\n    !1,I={zindex:\"auto\",cursoropacitymin:0,cursoropacitymax:1,cursorcolor:\"#424242\",cursorwidth:\"5px\",cursorborder:\"1px solid #fff\",cursorborderradius:\"5px\",scrollspeed:60,mousescrollstep:24,touchbehavior:!1,hwacceleration:!0,usetransition:!0,boxzoom:!1,dblclickzoom:!0,gesturezoom:!0,grabcursorenabled:!0,autohidemode:!0,background:\"\",iframeautoresize:!0,cursorminheight:32,preservenativescrolling:!0,railoffset:!1,bouncescroll:!0,spacebarenabled:!0,railpadding:{top:0,right:0,left:0,bottom:0},disableoutline:!0,\n    horizrailenabled:!0,railalign:\"right\",railvalign:\"bottom\",enabletranslate3d:!0,enablemousewheel:!0,enablekeyboard:!0,smoothscroll:!0,sensitiverail:!0,enablemouselockapi:!0,cursorfixedheight:!1,directionlockdeadzone:6,hidecursordelay:400,nativeparentscrolling:!0,enablescrollonselection:!0,overflowx:!0,overflowy:!0,cursordragspeed:0.3,rtlmode:!1,cursordragontouch:!1,oneaxismousemode:\"auto\"},G=!1,P=function(){if(G)return G;var e=document.createElement(\"DIV\"),c={haspointerlock:\"pointerLockElement\"in document||\n    \"mozPointerLockElement\"in document||\"webkitPointerLockElement\"in document};c.isopera=\"opera\"in window;c.isopera12=c.isopera&&\"getUserMedia\"in navigator;c.isoperamini=\"[object OperaMini]\"===Object.prototype.toString.call(window.operamini);c.isie=\"all\"in document&&\"attachEvent\"in e&&!c.isopera;c.isieold=c.isie&&!(\"msInterpolationMode\"in e.style);c.isie7=c.isie&&!c.isieold&&(!(\"documentMode\"in document)||7==document.documentMode);c.isie8=c.isie&&\"documentMode\"in document&&8==document.documentMode;c.isie9=\n    c.isie&&\"performance\"in window&&9<=document.documentMode;c.isie10=c.isie&&\"performance\"in window&&10<=document.documentMode;c.isie9mobile=/iemobile.9/i.test(navigator.userAgent);c.isie9mobile&&(c.isie9=!1);c.isie7mobile=!c.isie9mobile&&c.isie7&&/iemobile/i.test(navigator.userAgent);c.ismozilla=\"MozAppearance\"in e.style;c.iswebkit=\"WebkitAppearance\"in e.style;c.ischrome=\"chrome\"in window;c.ischrome22=c.ischrome&&c.haspointerlock;c.ischrome26=c.ischrome&&\"transition\"in e.style;c.cantouch=\"ontouchstart\"in\n    document.documentElement||\"ontouchstart\"in window;c.hasmstouch=window.navigator.msPointerEnabled||!1;c.ismac=/^mac$/i.test(navigator.platform);c.isios=c.cantouch&&/iphone|ipad|ipod/i.test(navigator.platform);c.isios4=c.isios&&!(\"seal\"in Object);c.isandroid=/android/i.test(navigator.userAgent);c.trstyle=!1;c.hastransform=!1;c.hastranslate3d=!1;c.transitionstyle=!1;c.hastransition=!1;c.transitionend=!1;for(var k=[\"transform\",\"msTransform\",\"webkitTransform\",\"MozTransform\",\"OTransform\"],l=0;l<k.length;l++)if(\"undefined\"!=\n    typeof e.style[k[l]]){c.trstyle=k[l];break}c.hastransform=!1!=c.trstyle;c.hastransform&&(e.style[c.trstyle]=\"translate3d(1px,2px,3px)\",c.hastranslate3d=/translate3d/.test(e.style[c.trstyle]));c.transitionstyle=!1;c.prefixstyle=\"\";c.transitionend=!1;for(var k=\"transition webkitTransition MozTransition OTransition OTransition msTransition KhtmlTransition\".split(\" \"),q=\" -webkit- -moz- -o- -o -ms- -khtml-\".split(\" \"),t=\"transitionend webkitTransitionEnd transitionend otransitionend oTransitionEnd msTransitionEnd KhtmlTransitionEnd\".split(\" \"),\n                                                                                                                                                                                                                                                                     l=0;l<k.length;l++)if(k[l]in e.style){c.transitionstyle=k[l];c.prefixstyle=q[l];c.transitionend=t[l];break}c.ischrome26&&(c.prefixstyle=q[1]);c.hastransition=c.transitionstyle;a:{k=[\"-moz-grab\",\"-webkit-grab\",\"grab\"];if(c.ischrome&&!c.ischrome22||c.isie)k=[];for(l=0;l<k.length;l++)if(q=k[l],e.style.cursor=q,e.style.cursor==q){k=q;break a}k=\"url(http://www.google.com/intl/en_ALL/mapfiles/openhand.cur),n-resize\"}c.cursorgrabvalue=k;c.hasmousecapture=\"setCapture\"in e;c.hasMutationObserver=!1!==A;return G=\n    c},Q=function(h,c){function k(){var d=b.win;if(\"zIndex\"in d)return d.zIndex();for(;0<d.length&&9!=d[0].nodeType;){var c=d.css(\"zIndex\");if(!isNaN(c)&&0!=c)return parseInt(c);d=d.parent()}return!1}function l(d,c,f){c=d.css(c);d=parseFloat(c);return isNaN(d)?(d=u[c]||0,f=3==d?f?b.win.outerHeight()-b.win.innerHeight():b.win.outerWidth()-b.win.innerWidth():1,b.isie8&&d&&(d+=1),f?d:0):d}function q(d,c,f,g){b._bind(d,c,function(b){b=b?b:window.event;var g={original:b,target:b.target||b.srcElement,type:\"wheel\",\n    deltaMode:\"MozMousePixelScroll\"==b.type?0:1,deltaX:0,deltaZ:0,preventDefault:function(){b.preventDefault?b.preventDefault():b.returnValue=!1;return!1},stopImmediatePropagation:function(){b.stopImmediatePropagation?b.stopImmediatePropagation():b.cancelBubble=!0}};\"mousewheel\"==c?(g.deltaY=-0.025*b.wheelDelta,b.wheelDeltaX&&(g.deltaX=-0.025*b.wheelDeltaX)):g.deltaY=b.detail;return f.call(d,g)},g)}function t(d,c,f){var g,e;0==d.deltaMode?(g=-Math.floor(d.deltaX*(b.opt.mousescrollstep/54)),e=-Math.floor(d.deltaY*\n    (b.opt.mousescrollstep/54))):1==d.deltaMode&&(g=-Math.floor(d.deltaX*b.opt.mousescrollstep),e=-Math.floor(d.deltaY*b.opt.mousescrollstep));c&&(b.opt.oneaxismousemode&&0==g&&e)&&(g=e,e=0);g&&(b.scrollmom&&b.scrollmom.stop(),b.lastdeltax+=g,b.debounced(\"mousewheelx\",function(){var d=b.lastdeltax;b.lastdeltax=0;b.rail.drag||b.doScrollLeftBy(d)},120));if(e){if(b.opt.nativeparentscrolling&&f&&!b.ispage&&!b.zoomactive)if(0>e){if(b.getScrollTop()>=b.page.maxh)return!0}else if(0>=b.getScrollTop())return!0;\n    b.scrollmom&&b.scrollmom.stop();b.lastdeltay+=e;b.debounced(\"mousewheely\",function(){var d=b.lastdeltay;b.lastdeltay=0;b.rail.drag||b.doScrollBy(d)},120)}d.stopImmediatePropagation();return d.preventDefault()}var b=this;this.version=\"3.5.0\";this.name=\"nicescroll\";this.me=c;this.opt={doc:e(\"body\"),win:!1};e.extend(this.opt,I);this.opt.snapbackspeed=80;if(h)for(var p in b.opt)\"undefined\"!=typeof h[p]&&(b.opt[p]=h[p]);this.iddoc=(this.doc=b.opt.doc)&&this.doc[0]?this.doc[0].id||\"\":\"\";this.ispage=/BODY|HTML/.test(b.opt.win?\n    b.opt.win[0].nodeName:this.doc[0].nodeName);this.haswrapper=!1!==b.opt.win;this.win=b.opt.win||(this.ispage?e(window):this.doc);this.docscroll=this.ispage&&!this.haswrapper?e(window):this.win;this.body=e(\"body\");this.iframe=this.isfixed=this.viewport=!1;this.isiframe=\"IFRAME\"==this.doc[0].nodeName&&\"IFRAME\"==this.win[0].nodeName;this.istextarea=\"TEXTAREA\"==this.win[0].nodeName;this.forcescreen=!1;this.canshowonmouseevent=\"scroll\"!=b.opt.autohidemode;this.page=this.view=this.onzoomout=this.onzoomin=\n    this.onscrollcancel=this.onscrollend=this.onscrollstart=this.onclick=this.ongesturezoom=this.onkeypress=this.onmousewheel=this.onmousemove=this.onmouseup=this.onmousedown=!1;this.scroll={x:0,y:0};this.scrollratio={x:0,y:0};this.cursorheight=20;this.scrollvaluemax=0;this.observerremover=this.observer=this.scrollmom=this.scrollrunning=this.checkrtlmode=!1;do this.id=\"ascrail\"+M++;while(document.getElementById(this.id));this.hasmousefocus=this.hasfocus=this.zoomactive=this.zoom=this.selectiondrag=this.cursorfreezed=\n    this.cursor=this.rail=!1;this.visibility=!0;this.hidden=this.locked=!1;this.cursoractive=!0;this.overflowx=b.opt.overflowx;this.overflowy=b.opt.overflowy;this.nativescrollingarea=!1;this.checkarea=0;this.events=[];this.saved={};this.delaylist={};this.synclist={};this.lastdeltay=this.lastdeltax=0;this.detected=P();var g=e.extend({},this.detected);this.ishwscroll=(this.canhwscroll=g.hastransform&&b.opt.hwacceleration)&&b.haswrapper;this.istouchcapable=!1;g.cantouch&&(g.ischrome&&!g.isios&&!g.isandroid)&&\n(this.istouchcapable=!0,g.cantouch=!1);g.cantouch&&(g.ismozilla&&!g.isios&&!g.isandroid)&&(this.istouchcapable=!0,g.cantouch=!1);b.opt.enablemouselockapi||(g.hasmousecapture=!1,g.haspointerlock=!1);this.delayed=function(d,c,f,g){var e=b.delaylist[d],k=(new Date).getTime();if(!g&&e&&e.tt)return!1;e&&e.tt&&clearTimeout(e.tt);if(e&&e.last+f>k&&!e.tt)b.delaylist[d]={last:k+f,tt:setTimeout(function(){b.delaylist[d].tt=0;c.call()},f)};else if(!e||!e.tt)b.delaylist[d]={last:k,tt:0},setTimeout(function(){c.call()},\n    0)};this.debounced=function(d,c,f){var g=b.delaylist[d];(new Date).getTime();b.delaylist[d]=c;g||setTimeout(function(){var c=b.delaylist[d];b.delaylist[d]=!1;c.call()},f)};this.synched=function(d,c){b.synclist[d]=c;(function(){b.onsync||(v(function(){b.onsync=!1;for(d in b.synclist){var c=b.synclist[d];c&&c.call(b);b.synclist[d]=!1}}),b.onsync=!0)})();return d};this.unsynched=function(d){b.synclist[d]&&(b.synclist[d]=!1)};this.css=function(d,c){for(var f in c)b.saved.css.push([d,f,d.css(f)]),d.css(f,\n    c[f])};this.scrollTop=function(d){return\"undefined\"==typeof d?b.getScrollTop():b.setScrollTop(d)};this.scrollLeft=function(d){return\"undefined\"==typeof d?b.getScrollLeft():b.setScrollLeft(d)};BezierClass=function(b,c,f,g,e,k,l){this.st=b;this.ed=c;this.spd=f;this.p1=g||0;this.p2=e||1;this.p3=k||0;this.p4=l||1;this.ts=(new Date).getTime();this.df=this.ed-this.st};BezierClass.prototype={B2:function(b){return 3*b*b*(1-b)},B3:function(b){return 3*b*(1-b)*(1-b)},B4:function(b){return(1-b)*(1-b)*(1-b)},\n    getNow:function(){var b=1-((new Date).getTime()-this.ts)/this.spd,c=this.B2(b)+this.B3(b)+this.B4(b);return 0>b?this.ed:this.st+Math.round(this.df*c)},update:function(b,c){this.st=this.getNow();this.ed=b;this.spd=c;this.ts=(new Date).getTime();this.df=this.ed-this.st;return this}};if(this.ishwscroll){this.doc.translate={x:0,y:0,tx:\"0px\",ty:\"0px\"};g.hastranslate3d&&g.isios&&this.doc.css(\"-webkit-backface-visibility\",\"hidden\");var s=function(){var d=b.doc.css(g.trstyle);return d&&\"matrix\"==d.substr(0,\n    6)?d.replace(/^.*\\((.*)\\)$/g,\"$1\").replace(/px/g,\"\").split(/, +/):!1};this.getScrollTop=function(d){if(!d){if(d=s())return 16==d.length?-d[13]:-d[5];if(b.timerscroll&&b.timerscroll.bz)return b.timerscroll.bz.getNow()}return b.doc.translate.y};this.getScrollLeft=function(d){if(!d){if(d=s())return 16==d.length?-d[12]:-d[4];if(b.timerscroll&&b.timerscroll.bh)return b.timerscroll.bh.getNow()}return b.doc.translate.x};this.notifyScrollEvent=document.createEvent?function(b){var c=document.createEvent(\"UIEvents\");\n    c.initUIEvent(\"scroll\",!1,!0,window,1);b.dispatchEvent(c)}:document.fireEvent?function(b){var c=document.createEventObject();b.fireEvent(\"onscroll\");c.cancelBubble=!0}:function(b,c){};g.hastranslate3d&&b.opt.enabletranslate3d?(this.setScrollTop=function(d,c){b.doc.translate.y=d;b.doc.translate.ty=-1*d+\"px\";b.doc.css(g.trstyle,\"translate3d(\"+b.doc.translate.tx+\",\"+b.doc.translate.ty+\",0px)\");c||b.notifyScrollEvent(b.win[0])},this.setScrollLeft=function(d,c){b.doc.translate.x=d;b.doc.translate.tx=-1*\n    d+\"px\";b.doc.css(g.trstyle,\"translate3d(\"+b.doc.translate.tx+\",\"+b.doc.translate.ty+\",0px)\");c||b.notifyScrollEvent(b.win[0])}):(this.setScrollTop=function(d,c){b.doc.translate.y=d;b.doc.translate.ty=-1*d+\"px\";b.doc.css(g.trstyle,\"translate(\"+b.doc.translate.tx+\",\"+b.doc.translate.ty+\")\");c||b.notifyScrollEvent(b.win[0])},this.setScrollLeft=function(d,c){b.doc.translate.x=d;b.doc.translate.tx=-1*d+\"px\";b.doc.css(g.trstyle,\"translate(\"+b.doc.translate.tx+\",\"+b.doc.translate.ty+\")\");c||b.notifyScrollEvent(b.win[0])})}else this.getScrollTop=\n    function(){return b.docscroll.scrollTop()},this.setScrollTop=function(d){return b.docscroll.scrollTop(d)},this.getScrollLeft=function(){return b.docscroll.scrollLeft()},this.setScrollLeft=function(d){return b.docscroll.scrollLeft(d)};this.getTarget=function(b){return!b?!1:b.target?b.target:b.srcElement?b.srcElement:!1};this.hasParent=function(b,c){if(!b)return!1;for(var f=b.target||b.srcElement||b||!1;f&&f.id!=c;)f=f.parentNode||!1;return!1!==f};var u={thin:1,medium:3,thick:5};this.getOffset=function(){if(b.isfixed)return{top:parseFloat(b.win.css(\"top\")),\n    left:parseFloat(b.win.css(\"left\"))};if(!b.viewport)return b.win.offset();var d=b.win.offset(),c=b.viewport.offset();return{top:d.top-c.top+b.viewport.scrollTop(),left:d.left-c.left+b.viewport.scrollLeft()}};this.updateScrollBar=function(d){if(b.ishwscroll)b.rail.css({height:b.win.innerHeight()}),b.railh&&b.railh.css({width:b.win.innerWidth()});else{var c=b.getOffset(),f=c.top,g=c.left,f=f+l(b.win,\"border-top-width\",!0);b.win.outerWidth();b.win.innerWidth();var g=g+(b.rail.align?b.win.outerWidth()-\n    l(b.win,\"border-right-width\")-b.rail.width:l(b.win,\"border-left-width\")),e=b.opt.railoffset;e&&(e.top&&(f+=e.top),b.rail.align&&e.left&&(g+=e.left));b.locked||b.rail.css({top:f,left:g,height:d?d.h:b.win.innerHeight()});b.zoom&&b.zoom.css({top:f+1,left:1==b.rail.align?g-20:g+b.rail.width+4});b.railh&&!b.locked&&(f=c.top,g=c.left,d=b.railh.align?f+l(b.win,\"border-top-width\",!0)+b.win.innerHeight()-b.railh.height:f+l(b.win,\"border-top-width\",!0),g+=l(b.win,\"border-left-width\"),b.railh.css({top:d,left:g,\n    width:b.railh.width}))}};this.doRailClick=function(d,c,f){var g;b.locked||(b.cancelEvent(d),c?(c=f?b.doScrollLeft:b.doScrollTop,g=f?(d.pageX-b.railh.offset().left-b.cursorwidth/2)*b.scrollratio.x:(d.pageY-b.rail.offset().top-b.cursorheight/2)*b.scrollratio.y,c(g)):(c=f?b.doScrollLeftBy:b.doScrollBy,g=f?b.scroll.x:b.scroll.y,d=f?d.pageX-b.railh.offset().left:d.pageY-b.rail.offset().top,f=f?b.view.w:b.view.h,g>=d?c(f):c(-f)))};b.hasanimationframe=v;b.hascancelanimationframe=w;b.hasanimationframe?b.hascancelanimationframe||\n    (w=function(){b.cancelAnimationFrame=!0}):(v=function(b){return setTimeout(b,15-Math.floor(+new Date/1E3)%16)},w=clearInterval);this.init=function(){b.saved.css=[];if(g.isie7mobile||g.isoperamini)return!0;g.hasmstouch&&b.css(b.ispage?e(\"html\"):b.win,{\"-ms-touch-action\":\"none\"});b.zindex=\"auto\";b.zindex=!b.ispage&&\"auto\"==b.opt.zindex?k()||\"auto\":b.opt.zindex;!b.ispage&&\"auto\"!=b.zindex&&b.zindex>y&&(y=b.zindex);b.isie&&(0==b.zindex&&\"auto\"==b.opt.zindex)&&(b.zindex=\"auto\");if(!b.ispage||!g.cantouch&&\n    !g.isieold&&!g.isie9mobile){var d=b.docscroll;b.ispage&&(d=b.haswrapper?b.win:b.doc);g.isie9mobile||b.css(d,{\"overflow-y\":\"hidden\"});b.ispage&&g.isie7&&(\"BODY\"==b.doc[0].nodeName?b.css(e(\"html\"),{\"overflow-y\":\"hidden\"}):\"HTML\"==b.doc[0].nodeName&&b.css(e(\"body\"),{\"overflow-y\":\"hidden\"}));g.isios&&(!b.ispage&&!b.haswrapper)&&b.css(e(\"body\"),{\"-webkit-overflow-scrolling\":\"touch\"});var c=e(document.createElement(\"div\"));c.css({position:\"relative\",top:0,\"float\":\"right\",width:b.opt.cursorwidth,height:\"0px\",\n    \"background-color\":b.opt.cursorcolor,border:b.opt.cursorborder,\"background-clip\":\"padding-box\",\"-webkit-border-radius\":b.opt.cursorborderradius,\"-moz-border-radius\":b.opt.cursorborderradius,\"border-radius\":b.opt.cursorborderradius});c.hborder=parseFloat(c.outerHeight()-c.innerHeight());b.cursor=c;var f=e(document.createElement(\"div\"));f.attr(\"id\",b.id);f.addClass(\"nicescroll-rails\");var l,h,x=[\"left\",\"right\"],q;for(q in x)h=x[q],(l=b.opt.railpadding[h])?f.css(\"padding-\"+h,l+\"px\"):b.opt.railpadding[h]=\n    0;f.append(c);f.width=Math.max(parseFloat(b.opt.cursorwidth),c.outerWidth())+b.opt.railpadding.left+b.opt.railpadding.right;f.css({width:f.width+\"px\",zIndex:b.zindex,background:b.opt.background,cursor:\"default\"});f.visibility=!0;f.scrollable=!0;f.align=\"left\"==b.opt.railalign?0:1;b.rail=f;c=b.rail.drag=!1;b.opt.boxzoom&&(!b.ispage&&!g.isieold)&&(c=document.createElement(\"div\"),b.bind(c,\"click\",b.doZoom),b.zoom=e(c),b.zoom.css({cursor:\"pointer\",\"z-index\":b.zindex,backgroundImage:\"url(\"+N+\"zoomico.png)\",\n    height:18,width:18,backgroundPosition:\"0px 0px\"}),b.opt.dblclickzoom&&b.bind(b.win,\"dblclick\",b.doZoom),g.cantouch&&b.opt.gesturezoom&&(b.ongesturezoom=function(d){1.5<d.scale&&b.doZoomIn(d);0.8>d.scale&&b.doZoomOut(d);return b.cancelEvent(d)},b.bind(b.win,\"gestureend\",b.ongesturezoom)));b.railh=!1;if(b.opt.horizrailenabled){b.css(d,{\"overflow-x\":\"hidden\"});c=e(document.createElement(\"div\"));c.css({position:\"relative\",top:0,height:b.opt.cursorwidth,width:\"0px\",\"background-color\":b.opt.cursorcolor,\n    border:b.opt.cursorborder,\"background-clip\":\"padding-box\",\"-webkit-border-radius\":b.opt.cursorborderradius,\"-moz-border-radius\":b.opt.cursorborderradius,\"border-radius\":b.opt.cursorborderradius});c.wborder=parseFloat(c.outerWidth()-c.innerWidth());b.cursorh=c;var m=e(document.createElement(\"div\"));m.attr(\"id\",b.id+\"-hr\");m.addClass(\"nicescroll-rails\");m.height=Math.max(parseFloat(b.opt.cursorwidth),c.outerHeight());m.css({height:m.height+\"px\",zIndex:b.zindex,background:b.opt.background});m.append(c);\n    m.visibility=!0;m.scrollable=!0;m.align=\"top\"==b.opt.railvalign?0:1;b.railh=m;b.railh.drag=!1}b.ispage?(f.css({position:\"fixed\",top:\"0px\",height:\"100%\"}),f.align?f.css({right:\"0px\"}):f.css({left:\"0px\"}),b.body.append(f),b.railh&&(m.css({position:\"fixed\",left:\"0px\",width:\"100%\"}),m.align?m.css({bottom:\"0px\"}):m.css({top:\"0px\"}),b.body.append(m))):(b.ishwscroll?(\"static\"==b.win.css(\"position\")&&b.css(b.win,{position:\"relative\"}),d=\"HTML\"==b.win[0].nodeName?b.body:b.win,b.zoom&&(b.zoom.css({position:\"absolute\",\n    top:1,right:0,\"margin-right\":f.width+4}),d.append(b.zoom)),f.css({position:\"absolute\",top:0}),f.align?f.css({right:0}):f.css({left:0}),d.append(f),m&&(m.css({position:\"absolute\",left:0,bottom:0}),m.align?m.css({bottom:0}):m.css({top:0}),d.append(m))):(b.isfixed=\"fixed\"==b.win.css(\"position\"),d=b.isfixed?\"fixed\":\"absolute\",b.isfixed||(b.viewport=b.getViewport(b.win[0])),b.viewport&&(b.body=b.viewport,!1==/fixed|relative|absolute/.test(b.viewport.css(\"position\"))&&b.css(b.viewport,{position:\"relative\"})),\n    f.css({position:d}),b.zoom&&b.zoom.css({position:d}),b.updateScrollBar(),b.body.append(f),b.zoom&&b.body.append(b.zoom),b.railh&&(m.css({position:d}),b.body.append(m))),g.isios&&b.css(b.win,{\"-webkit-tap-highlight-color\":\"rgba(0,0,0,0)\",\"-webkit-touch-callout\":\"none\"}),g.isie&&b.opt.disableoutline&&b.win.attr(\"hideFocus\",\"true\"),g.iswebkit&&b.opt.disableoutline&&b.win.css({outline:\"none\"}));!1===b.opt.autohidemode?(b.autohidedom=!1,b.rail.css({opacity:b.opt.cursoropacitymax}),b.railh&&b.railh.css({opacity:b.opt.cursoropacitymax})):\n    !0===b.opt.autohidemode||\"leave\"===b.opt.autohidemode?(b.autohidedom=e().add(b.rail),g.isie8&&(b.autohidedom=b.autohidedom.add(b.cursor)),b.railh&&(b.autohidedom=b.autohidedom.add(b.railh)),b.railh&&g.isie8&&(b.autohidedom=b.autohidedom.add(b.cursorh))):\"scroll\"==b.opt.autohidemode?(b.autohidedom=e().add(b.rail),b.railh&&(b.autohidedom=b.autohidedom.add(b.railh))):\"cursor\"==b.opt.autohidemode?(b.autohidedom=e().add(b.cursor),b.railh&&(b.autohidedom=b.autohidedom.add(b.cursorh))):\"hidden\"==b.opt.autohidemode&&\n        (b.autohidedom=!1,b.hide(),b.locked=!1);if(g.isie9mobile)b.scrollmom=new J(b),b.onmangotouch=function(d){d=b.getScrollTop();var c=b.getScrollLeft();if(d==b.scrollmom.lastscrolly&&c==b.scrollmom.lastscrollx)return!0;var f=d-b.mangotouch.sy,g=c-b.mangotouch.sx;if(0!=Math.round(Math.sqrt(Math.pow(g,2)+Math.pow(f,2)))){var n=0>f?-1:1,e=0>g?-1:1,k=+new Date;b.mangotouch.lazy&&clearTimeout(b.mangotouch.lazy);80<k-b.mangotouch.tm||b.mangotouch.dry!=n||b.mangotouch.drx!=e?(b.scrollmom.stop(),b.scrollmom.reset(c,\n    d),b.mangotouch.sy=d,b.mangotouch.ly=d,b.mangotouch.sx=c,b.mangotouch.lx=c,b.mangotouch.dry=n,b.mangotouch.drx=e,b.mangotouch.tm=k):(b.scrollmom.stop(),b.scrollmom.update(b.mangotouch.sx-g,b.mangotouch.sy-f),b.mangotouch.tm=k,f=Math.max(Math.abs(b.mangotouch.ly-d),Math.abs(b.mangotouch.lx-c)),b.mangotouch.ly=d,b.mangotouch.lx=c,2<f&&(b.mangotouch.lazy=setTimeout(function(){b.mangotouch.lazy=!1;b.mangotouch.dry=0;b.mangotouch.drx=0;b.mangotouch.tm=0;b.scrollmom.doMomentum(30)},100)))}},f=b.getScrollTop(),\n    m=b.getScrollLeft(),b.mangotouch={sy:f,ly:f,dry:0,sx:m,lx:m,drx:0,lazy:!1,tm:0},b.bind(b.docscroll,\"scroll\",b.onmangotouch);else{if(g.cantouch||b.istouchcapable||b.opt.touchbehavior||g.hasmstouch){b.scrollmom=new J(b);b.ontouchstart=function(d){if(d.pointerType&&2!=d.pointerType)return!1;if(!b.locked){if(g.hasmstouch)for(var c=d.target?d.target:!1;c;){var f=e(c).getNiceScroll();if(0<f.length&&f[0].me==b.me)break;if(0<f.length)return!1;if(\"DIV\"==c.nodeName&&c.id==b.id)break;c=c.parentNode?c.parentNode:\n    !1}b.cancelScroll();if((c=b.getTarget(d))&&/INPUT/i.test(c.nodeName)&&/range/i.test(c.type))return b.stopPropagation(d);!(\"clientX\"in d)&&\"changedTouches\"in d&&(d.clientX=d.changedTouches[0].clientX,d.clientY=d.changedTouches[0].clientY);b.forcescreen&&(f=d,d={original:d.original?d.original:d},d.clientX=f.screenX,d.clientY=f.screenY);b.rail.drag={x:d.clientX,y:d.clientY,sx:b.scroll.x,sy:b.scroll.y,st:b.getScrollTop(),sl:b.getScrollLeft(),pt:2,dl:!1};if(b.ispage||!b.opt.directionlockdeadzone)b.rail.drag.dl=\n    \"f\";else{var f=e(window).width(),n=e(window).height(),k=Math.max(document.body.scrollWidth,document.documentElement.scrollWidth),l=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight),n=Math.max(0,l-n),f=Math.max(0,k-f);b.rail.drag.ck=!b.rail.scrollable&&b.railh.scrollable?0<n?\"v\":!1:b.rail.scrollable&&!b.railh.scrollable?0<f?\"h\":!1:!1;b.rail.drag.ck||(b.rail.drag.dl=\"f\")}b.opt.touchbehavior&&(b.isiframe&&g.isie)&&(f=b.win.position(),b.rail.drag.x+=f.left,b.rail.drag.y+=f.top);\n    b.hasmoving=!1;b.lastmouseup=!1;b.scrollmom.reset(d.clientX,d.clientY);if(!g.cantouch&&!this.istouchcapable&&!g.hasmstouch){if(!c||!/INPUT|SELECT|TEXTAREA/i.test(c.nodeName))return!b.ispage&&g.hasmousecapture&&c.setCapture(),b.opt.touchbehavior?b.cancelEvent(d):b.stopPropagation(d);/SUBMIT|CANCEL|BUTTON/i.test(e(c).attr(\"type\"))&&(pc={tg:c,click:!1},b.preventclick=pc)}}};b.ontouchend=function(d){if(d.pointerType&&2!=d.pointerType)return!1;if(b.rail.drag&&2==b.rail.drag.pt&&(b.scrollmom.doMomentum(),\n    b.rail.drag=!1,b.hasmoving&&(b.hasmoving=!1,b.lastmouseup=!0,b.hideCursor(),g.hasmousecapture&&document.releaseCapture(),!g.cantouch)))return b.cancelEvent(d)};var t=b.opt.touchbehavior&&b.isiframe&&!g.hasmousecapture;b.ontouchmove=function(d,c){if(d.pointerType&&2!=d.pointerType)return!1;if(b.rail.drag&&2==b.rail.drag.pt){if(g.cantouch&&\"undefined\"==typeof d.original)return!0;b.hasmoving=!0;b.preventclick&&!b.preventclick.click&&(b.preventclick.click=b.preventclick.tg.onclick||!1,b.preventclick.tg.onclick=\n    b.onpreventclick);d=e.extend({original:d},d);\"changedTouches\"in d&&(d.clientX=d.changedTouches[0].clientX,d.clientY=d.changedTouches[0].clientY);if(b.forcescreen){var f=d;d={original:d.original?d.original:d};d.clientX=f.screenX;d.clientY=f.screenY}f=ofy=0;if(t&&!c){var n=b.win.position(),f=-n.left;ofy=-n.top}var k=d.clientY+ofy,n=k-b.rail.drag.y,l=d.clientX+f,h=l-b.rail.drag.x,r=b.rail.drag.st-n;b.ishwscroll&&b.opt.bouncescroll?0>r?r=Math.round(r/2):r>b.page.maxh&&(r=b.page.maxh+Math.round((r-b.page.maxh)/\n    2)):(0>r&&(k=r=0),r>b.page.maxh&&(r=b.page.maxh,k=0));if(b.railh&&b.railh.scrollable){var m=b.rail.drag.sl-h;b.ishwscroll&&b.opt.bouncescroll?0>m?m=Math.round(m/2):m>b.page.maxw&&(m=b.page.maxw+Math.round((m-b.page.maxw)/2)):(0>m&&(l=m=0),m>b.page.maxw&&(m=b.page.maxw,l=0))}f=!1;if(b.rail.drag.dl)f=!0,\"v\"==b.rail.drag.dl?m=b.rail.drag.sl:\"h\"==b.rail.drag.dl&&(r=b.rail.drag.st);else{var n=Math.abs(n),h=Math.abs(h),x=b.opt.directionlockdeadzone;if(\"v\"==b.rail.drag.ck){if(n>x&&h<=0.3*n)return b.rail.drag=\n    !1,!0;h>x&&(b.rail.drag.dl=\"f\",e(\"body\").scrollTop(e(\"body\").scrollTop()))}else if(\"h\"==b.rail.drag.ck){if(h>x&&n<=0.3*h)return b.rail.drag=!1,!0;n>x&&(b.rail.drag.dl=\"f\",e(\"body\").scrollLeft(e(\"body\").scrollLeft()))}}b.synched(\"touchmove\",function(){b.rail.drag&&2==b.rail.drag.pt&&(b.prepareTransition&&b.prepareTransition(0),b.rail.scrollable&&b.setScrollTop(r),b.scrollmom.update(l,k),b.railh&&b.railh.scrollable?(b.setScrollLeft(m),b.showCursor(r,m)):b.showCursor(r),g.isie10&&document.selection.clear())});\n    g.ischrome&&b.istouchcapable&&(f=!1);if(f)return b.cancelEvent(d)}}}b.onmousedown=function(d,c){if(!(b.rail.drag&&1!=b.rail.drag.pt)){if(b.locked)return b.cancelEvent(d);b.cancelScroll();b.rail.drag={x:d.clientX,y:d.clientY,sx:b.scroll.x,sy:b.scroll.y,pt:1,hr:!!c};var f=b.getTarget(d);!b.ispage&&g.hasmousecapture&&f.setCapture();b.isiframe&&!g.hasmousecapture&&(b.saved.csspointerevents=b.doc.css(\"pointer-events\"),b.css(b.doc,{\"pointer-events\":\"none\"}));return b.cancelEvent(d)}};b.onmouseup=function(d){if(b.rail.drag&&\n    (g.hasmousecapture&&document.releaseCapture(),b.isiframe&&!g.hasmousecapture&&b.doc.css(\"pointer-events\",b.saved.csspointerevents),1==b.rail.drag.pt))return b.rail.drag=!1,b.cancelEvent(d)};b.onmousemove=function(d){if(b.rail.drag&&1==b.rail.drag.pt){if(g.ischrome&&0==d.which)return b.onmouseup(d);b.cursorfreezed=!0;if(b.rail.drag.hr){b.scroll.x=b.rail.drag.sx+(d.clientX-b.rail.drag.x);0>b.scroll.x&&(b.scroll.x=0);var c=b.scrollvaluemaxw;b.scroll.x>c&&(b.scroll.x=c)}else b.scroll.y=b.rail.drag.sy+\n    (d.clientY-b.rail.drag.y),0>b.scroll.y&&(b.scroll.y=0),c=b.scrollvaluemax,b.scroll.y>c&&(b.scroll.y=c);b.synched(\"mousemove\",function(){b.rail.drag&&1==b.rail.drag.pt&&(b.showCursor(),b.rail.drag.hr?b.doScrollLeft(Math.round(b.scroll.x*b.scrollratio.x),b.opt.cursordragspeed):b.doScrollTop(Math.round(b.scroll.y*b.scrollratio.y),b.opt.cursordragspeed))});return b.cancelEvent(d)}};if(g.cantouch||b.opt.touchbehavior)b.onpreventclick=function(d){if(b.preventclick)return b.preventclick.tg.onclick=b.preventclick.click,\n    b.preventclick=!1,b.cancelEvent(d)},b.bind(b.win,\"mousedown\",b.ontouchstart),b.onclick=g.isios?!1:function(d){return b.lastmouseup?(b.lastmouseup=!1,b.cancelEvent(d)):!0},b.opt.grabcursorenabled&&g.cursorgrabvalue&&(b.css(b.ispage?b.doc:b.win,{cursor:g.cursorgrabvalue}),b.css(b.rail,{cursor:g.cursorgrabvalue}));else{var p=function(d){if(b.selectiondrag){if(d){var c=b.win.outerHeight();d=d.pageY-b.selectiondrag.top;0<d&&d<c&&(d=0);d>=c&&(d-=c);b.selectiondrag.df=d}0!=b.selectiondrag.df&&(b.doScrollBy(2*\n    -Math.floor(b.selectiondrag.df/6)),b.debounced(\"doselectionscroll\",function(){p()},50))}};b.hasTextSelected=\"getSelection\"in document?function(){return 0<document.getSelection().rangeCount}:\"selection\"in document?function(){return\"None\"!=document.selection.type}:function(){return!1};b.onselectionstart=function(d){b.ispage||(b.selectiondrag=b.win.offset())};b.onselectionend=function(d){b.selectiondrag=!1};b.onselectiondrag=function(d){b.selectiondrag&&b.hasTextSelected()&&b.debounced(\"selectionscroll\",\n    function(){p(d)},250)}}g.hasmstouch&&(b.css(b.rail,{\"-ms-touch-action\":\"none\"}),b.css(b.cursor,{\"-ms-touch-action\":\"none\"}),b.bind(b.win,\"MSPointerDown\",b.ontouchstart),b.bind(document,\"MSPointerUp\",b.ontouchend),b.bind(document,\"MSPointerMove\",b.ontouchmove),b.bind(b.cursor,\"MSGestureHold\",function(b){b.preventDefault()}),b.bind(b.cursor,\"contextmenu\",function(b){b.preventDefault()}));this.istouchcapable&&(b.bind(b.win,\"touchstart\",b.ontouchstart),b.bind(document,\"touchend\",b.ontouchend),b.bind(document,\n    \"touchcancel\",b.ontouchend),b.bind(document,\"touchmove\",b.ontouchmove));b.bind(b.cursor,\"mousedown\",b.onmousedown);b.bind(b.cursor,\"mouseup\",b.onmouseup);b.railh&&(b.bind(b.cursorh,\"mousedown\",function(d){b.onmousedown(d,!0)}),b.bind(b.cursorh,\"mouseup\",function(d){if(!(b.rail.drag&&2==b.rail.drag.pt))return b.rail.drag=!1,b.hasmoving=!1,b.hideCursor(),g.hasmousecapture&&document.releaseCapture(),b.cancelEvent(d)}));if(b.opt.cursordragontouch||!g.cantouch&&!b.opt.touchbehavior)b.rail.css({cursor:\"default\"}),\n    b.railh&&b.railh.css({cursor:\"default\"}),b.jqbind(b.rail,\"mouseenter\",function(){b.canshowonmouseevent&&b.showCursor();b.rail.active=!0}),b.jqbind(b.rail,\"mouseleave\",function(){b.rail.active=!1;b.rail.drag||b.hideCursor()}),b.opt.sensitiverail&&(b.bind(b.rail,\"click\",function(d){b.doRailClick(d,!1,!1)}),b.bind(b.rail,\"dblclick\",function(d){b.doRailClick(d,!0,!1)}),b.bind(b.cursor,\"click\",function(d){b.cancelEvent(d)}),b.bind(b.cursor,\"dblclick\",function(d){b.cancelEvent(d)})),b.railh&&(b.jqbind(b.railh,\n    \"mouseenter\",function(){b.canshowonmouseevent&&b.showCursor();b.rail.active=!0}),b.jqbind(b.railh,\"mouseleave\",function(){b.rail.active=!1;b.rail.drag||b.hideCursor()}),b.opt.sensitiverail&&(b.bind(b.railh,\"click\",function(d){b.doRailClick(d,!1,!0)}),b.bind(b.railh,\"dblclick\",function(d){b.doRailClick(d,!0,!0)}),b.bind(b.cursorh,\"click\",function(d){b.cancelEvent(d)}),b.bind(b.cursorh,\"dblclick\",function(d){b.cancelEvent(d)})));!g.cantouch&&!b.opt.touchbehavior?(b.bind(g.hasmousecapture?b.win:document,\n    \"mouseup\",b.onmouseup),b.bind(document,\"mousemove\",b.onmousemove),b.onclick&&b.bind(document,\"click\",b.onclick),!b.ispage&&b.opt.enablescrollonselection&&(b.bind(b.win[0],\"mousedown\",b.onselectionstart),b.bind(document,\"mouseup\",b.onselectionend),b.bind(b.cursor,\"mouseup\",b.onselectionend),b.cursorh&&b.bind(b.cursorh,\"mouseup\",b.onselectionend),b.bind(document,\"mousemove\",b.onselectiondrag)),b.zoom&&(b.jqbind(b.zoom,\"mouseenter\",function(){b.canshowonmouseevent&&b.showCursor();b.rail.active=!0}),\n    b.jqbind(b.zoom,\"mouseleave\",function(){b.rail.active=!1;b.rail.drag||b.hideCursor()}))):(b.bind(g.hasmousecapture?b.win:document,\"mouseup\",b.ontouchend),b.bind(document,\"mousemove\",b.ontouchmove),b.onclick&&b.bind(document,\"click\",b.onclick),b.opt.cursordragontouch&&(b.bind(b.cursor,\"mousedown\",b.onmousedown),b.bind(b.cursor,\"mousemove\",b.onmousemove),b.cursorh&&b.bind(b.cursorh,\"mousedown\",function(d){b.onmousedown(d,!0)}),b.cursorh&&b.bind(b.cursorh,\"mousemove\",b.onmousemove)));b.opt.enablemousewheel&&\n(b.isiframe||b.bind(g.isie&&b.ispage?document:b.win,\"mousewheel\",b.onmousewheel),b.bind(b.rail,\"mousewheel\",b.onmousewheel),b.railh&&b.bind(b.railh,\"mousewheel\",b.onmousewheelhr));!b.ispage&&(!g.cantouch&&!/HTML|BODY/.test(b.win[0].nodeName))&&(b.win.attr(\"tabindex\")||b.win.attr({tabindex:L++}),b.jqbind(b.win,\"focus\",function(d){z=b.getTarget(d).id||!0;b.hasfocus=!0;b.canshowonmouseevent&&b.noticeCursor()}),b.jqbind(b.win,\"blur\",function(d){z=!1;b.hasfocus=!1}),b.jqbind(b.win,\"mouseenter\",function(d){E=\n    b.getTarget(d).id||!0;b.hasmousefocus=!0;b.canshowonmouseevent&&b.noticeCursor()}),b.jqbind(b.win,\"mouseleave\",function(){E=!1;b.hasmousefocus=!1;b.rail.drag||b.hideCursor()}))}b.onkeypress=function(d){if(b.locked&&0==b.page.maxh)return!0;d=d?d:window.e;var c=b.getTarget(d);if(c&&/INPUT|TEXTAREA|SELECT|OPTION/.test(c.nodeName)&&(!c.getAttribute(\"type\")&&!c.type||!/submit|button|cancel/i.tp))return!0;if(b.hasfocus||b.hasmousefocus&&!z||b.ispage&&!z&&!E){c=d.keyCode;if(b.locked&&27!=c)return b.cancelEvent(d);\n    var f=d.ctrlKey||!1,n=d.shiftKey||!1,g=!1;switch(c){case 38:case 63233:b.doScrollBy(72);g=!0;break;case 40:case 63235:b.doScrollBy(-72);g=!0;break;case 37:case 63232:b.railh&&(f?b.doScrollLeft(0):b.doScrollLeftBy(72),g=!0);break;case 39:case 63234:b.railh&&(f?b.doScrollLeft(b.page.maxw):b.doScrollLeftBy(-72),g=!0);break;case 33:case 63276:b.doScrollBy(b.view.h);g=!0;break;case 34:case 63277:b.doScrollBy(-b.view.h);g=!0;break;case 36:case 63273:b.railh&&f?b.doScrollPos(0,0):b.doScrollTo(0);g=!0;break;\n        case 35:case 63275:b.railh&&f?b.doScrollPos(b.page.maxw,b.page.maxh):b.doScrollTo(b.page.maxh);g=!0;break;case 32:b.opt.spacebarenabled&&(n?b.doScrollBy(b.view.h):b.doScrollBy(-b.view.h),g=!0);break;case 27:b.zoomactive&&(b.doZoom(),g=!0)}if(g)return b.cancelEvent(d)}};b.opt.enablekeyboard&&b.bind(document,g.isopera&&!g.isopera12?\"keypress\":\"keydown\",b.onkeypress);b.bind(window,\"resize\",b.lazyResize);b.bind(window,\"orientationchange\",b.lazyResize);b.bind(window,\"load\",b.lazyResize);if(g.ischrome&&\n    !b.ispage&&!b.haswrapper){var s=b.win.attr(\"style\"),f=parseFloat(b.win.css(\"width\"))+1;b.win.css(\"width\",f);b.synched(\"chromefix\",function(){b.win.attr(\"style\",s)})}b.onAttributeChange=function(d){b.lazyResize(250)};!b.ispage&&!b.haswrapper&&(!1!==A?(b.observer=new A(function(d){d.forEach(b.onAttributeChange)}),b.observer.observe(b.win[0],{childList:!0,characterData:!1,attributes:!0,subtree:!1}),b.observerremover=new A(function(d){d.forEach(function(d){if(0<d.removedNodes.length)for(var c in d.removedNodes)if(d.removedNodes[c]==\n    b.win[0])return b.remove()})}),b.observerremover.observe(b.win[0].parentNode,{childList:!0,characterData:!1,attributes:!1,subtree:!1})):(b.bind(b.win,g.isie&&!g.isie9?\"propertychange\":\"DOMAttrModified\",b.onAttributeChange),g.isie9&&b.win[0].attachEvent(\"onpropertychange\",b.onAttributeChange),b.bind(b.win,\"DOMNodeRemoved\",function(d){d.target==b.win[0]&&b.remove()})));!b.ispage&&b.opt.boxzoom&&b.bind(window,\"resize\",b.resizeZoom);b.istextarea&&b.bind(b.win,\"mouseup\",b.lazyResize);b.checkrtlmode=!0;\n    b.lazyResize(30)}if(\"IFRAME\"==this.doc[0].nodeName){var K=function(d){b.iframexd=!1;try{var c=\"contentDocument\"in this?this.contentDocument:this.contentWindow.document}catch(f){b.iframexd=!0,c=!1}if(b.iframexd)return\"console\"in window&&console.log(\"NiceScroll error: policy restriced iframe\"),!0;b.forcescreen=!0;b.isiframe&&(b.iframe={doc:e(c),html:b.doc.contents().find(\"html\")[0],body:b.doc.contents().find(\"body\")[0]},b.getContentSize=function(){return{w:Math.max(b.iframe.html.scrollWidth,b.iframe.body.scrollWidth),\n    h:Math.max(b.iframe.html.scrollHeight,b.iframe.body.scrollHeight)}},b.docscroll=e(b.iframe.body));!g.isios&&(b.opt.iframeautoresize&&!b.isiframe)&&(b.win.scrollTop(0),b.doc.height(\"\"),d=Math.max(c.getElementsByTagName(\"html\")[0].scrollHeight,c.body.scrollHeight),b.doc.height(d));b.lazyResize(30);g.isie7&&b.css(e(b.iframe.html),{\"overflow-y\":\"hidden\"});b.css(e(b.iframe.body),{\"overflow-y\":\"hidden\"});g.isios&&b.haswrapper&&b.css(e(c.body),{\"-webkit-transform\":\"translate3d(0,0,0)\"});\"contentWindow\"in\n    this?b.bind(this.contentWindow,\"scroll\",b.onscroll):b.bind(c,\"scroll\",b.onscroll);b.opt.enablemousewheel&&b.bind(c,\"mousewheel\",b.onmousewheel);b.opt.enablekeyboard&&b.bind(c,g.isopera?\"keypress\":\"keydown\",b.onkeypress);if(g.cantouch||b.opt.touchbehavior)b.bind(c,\"mousedown\",b.ontouchstart),b.bind(c,\"mousemove\",function(d){b.ontouchmove(d,!0)}),b.opt.grabcursorenabled&&g.cursorgrabvalue&&b.css(e(c.body),{cursor:g.cursorgrabvalue});b.bind(c,\"mouseup\",b.ontouchend);b.zoom&&(b.opt.dblclickzoom&&b.bind(c,\n    \"dblclick\",b.doZoom),b.ongesturezoom&&b.bind(c,\"gestureend\",b.ongesturezoom))};this.doc[0].readyState&&\"complete\"==this.doc[0].readyState&&setTimeout(function(){K.call(b.doc[0],!1)},500);b.bind(this.doc,\"load\",K)}};this.showCursor=function(d,c){b.cursortimeout&&(clearTimeout(b.cursortimeout),b.cursortimeout=0);if(b.rail){b.autohidedom&&(b.autohidedom.stop().css({opacity:b.opt.cursoropacitymax}),b.cursoractive=!0);if(!b.rail.drag||1!=b.rail.drag.pt)\"undefined\"!=typeof d&&!1!==d&&(b.scroll.y=Math.round(1*\n    d/b.scrollratio.y)),\"undefined\"!=typeof c&&(b.scroll.x=Math.round(1*c/b.scrollratio.x));b.cursor.css({height:b.cursorheight,top:b.scroll.y});b.cursorh&&(!b.rail.align&&b.rail.visibility?b.cursorh.css({width:b.cursorwidth,left:b.scroll.x+b.rail.width}):b.cursorh.css({width:b.cursorwidth,left:b.scroll.x}),b.cursoractive=!0);b.zoom&&b.zoom.stop().css({opacity:b.opt.cursoropacitymax})}};this.hideCursor=function(d){!b.cursortimeout&&(b.rail&&b.autohidedom&&!(b.hasmousefocus&&\"leave\"==b.opt.autohidemode))&&\n(b.cursortimeout=setTimeout(function(){if(!b.rail.active||!b.showonmouseevent)b.autohidedom.stop().animate({opacity:b.opt.cursoropacitymin}),b.zoom&&b.zoom.stop().animate({opacity:b.opt.cursoropacitymin}),b.cursoractive=!1;b.cursortimeout=0},d||b.opt.hidecursordelay))};this.noticeCursor=function(d,c,f){b.showCursor(c,f);b.rail.active||b.hideCursor(d)};this.getContentSize=b.ispage?function(){return{w:Math.max(document.body.scrollWidth,document.documentElement.scrollWidth),h:Math.max(document.body.scrollHeight,\n    document.documentElement.scrollHeight)}}:b.haswrapper?function(){return{w:b.doc.outerWidth()+parseInt(b.win.css(\"paddingLeft\"))+parseInt(b.win.css(\"paddingRight\")),h:b.doc.outerHeight()+parseInt(b.win.css(\"paddingTop\"))+parseInt(b.win.css(\"paddingBottom\"))}}:function(){return{w:b.docscroll[0].scrollWidth,h:b.docscroll[0].scrollHeight}};this.onResize=function(d,c){if(!b.win)return!1;if(!b.haswrapper&&!b.ispage){if(\"none\"==b.win.css(\"display\"))return b.visibility&&b.hideRail().hideRailHr(),!1;!b.hidden&&\n    !b.visibility&&b.showRail().showRailHr()}var f=b.page.maxh,g=b.page.maxw,e=b.view.w;b.view={w:b.ispage?b.win.width():parseInt(b.win[0].clientWidth),h:b.ispage?b.win.height():parseInt(b.win[0].clientHeight)};b.page=c?c:b.getContentSize();b.page.maxh=Math.max(0,b.page.h-b.view.h);b.page.maxw=Math.max(0,b.page.w-b.view.w);if(b.page.maxh==f&&b.page.maxw==g&&b.view.w==e){if(b.ispage)return b;f=b.win.offset();if(b.lastposition&&(g=b.lastposition,g.top==f.top&&g.left==f.left))return b;b.lastposition=f}0==\n    b.page.maxh?(b.hideRail(),b.scrollvaluemax=0,b.scroll.y=0,b.scrollratio.y=0,b.cursorheight=0,b.setScrollTop(0),b.rail.scrollable=!1):b.rail.scrollable=!0;0==b.page.maxw?(b.hideRailHr(),b.scrollvaluemaxw=0,b.scroll.x=0,b.scrollratio.x=0,b.cursorwidth=0,b.setScrollLeft(0),b.railh.scrollable=!1):b.railh.scrollable=!0;b.locked=0==b.page.maxh&&0==b.page.maxw;if(b.locked)return b.ispage||b.updateScrollBar(b.view),!1;!b.hidden&&!b.visibility?b.showRail().showRailHr():!b.hidden&&!b.railh.visibility&&b.showRailHr();\n    b.istextarea&&(b.win.css(\"resize\")&&\"none\"!=b.win.css(\"resize\"))&&(b.view.h-=20);b.cursorheight=Math.min(b.view.h,Math.round(b.view.h*(b.view.h/b.page.h)));b.cursorheight=b.opt.cursorfixedheight?b.opt.cursorfixedheight:Math.max(b.opt.cursorminheight,b.cursorheight);b.cursorwidth=Math.min(b.view.w,Math.round(b.view.w*(b.view.w/b.page.w)));b.cursorwidth=b.opt.cursorfixedheight?b.opt.cursorfixedheight:Math.max(b.opt.cursorminheight,b.cursorwidth);b.scrollvaluemax=b.view.h-b.cursorheight-b.cursor.hborder;\n    b.railh&&(b.railh.width=0<b.page.maxh?b.view.w-b.rail.width:b.view.w,b.scrollvaluemaxw=b.railh.width-b.cursorwidth-b.cursorh.wborder);b.checkrtlmode&&b.railh&&(b.checkrtlmode=!1,b.opt.rtlmode&&0==b.scroll.x&&b.setScrollLeft(b.page.maxw));b.ispage||b.updateScrollBar(b.view);b.scrollratio={x:b.page.maxw/b.scrollvaluemaxw,y:b.page.maxh/b.scrollvaluemax};b.getScrollTop()>b.page.maxh?b.doScrollTop(b.page.maxh):(b.scroll.y=Math.round(b.getScrollTop()*(1/b.scrollratio.y)),b.scroll.x=Math.round(b.getScrollLeft()*\n        (1/b.scrollratio.x)),b.cursoractive&&b.noticeCursor());b.scroll.y&&0==b.getScrollTop()&&b.doScrollTo(Math.floor(b.scroll.y*b.scrollratio.y));return b};this.resize=b.onResize;this.lazyResize=function(d){d=isNaN(d)?30:d;b.delayed(\"resize\",b.resize,d);return b};this._bind=function(d,c,f,g){b.events.push({e:d,n:c,f:f,b:g,q:!1});d.addEventListener?d.addEventListener(c,f,g||!1):d.attachEvent?d.attachEvent(\"on\"+c,f):d[\"on\"+c]=f};this.jqbind=function(d,c,f){b.events.push({e:d,n:c,f:f,q:!0});e(d).bind(c,f)};\n    this.bind=function(d,c,f,e){var k=\"jquery\"in d?d[0]:d;\"mousewheel\"==c?\"onwheel\"in b.win?b._bind(k,\"wheel\",f,e||!1):(d=\"undefined\"!=typeof document.onmousewheel?\"mousewheel\":\"DOMMouseScroll\",q(k,d,f,e||!1),\"DOMMouseScroll\"==d&&q(k,\"MozMousePixelScroll\",f,e||!1)):k.addEventListener?(g.cantouch&&/mouseup|mousedown|mousemove/.test(c)&&b._bind(k,\"mousedown\"==c?\"touchstart\":\"mouseup\"==c?\"touchend\":\"touchmove\",function(b){if(b.touches){if(2>b.touches.length){var d=b.touches.length?b.touches[0]:b;d.original=\n        b;f.call(this,d)}}else b.changedTouches&&(d=b.changedTouches[0],d.original=b,f.call(this,d))},e||!1),b._bind(k,c,f,e||!1),g.cantouch&&\"mouseup\"==c&&b._bind(k,\"touchcancel\",f,e||!1)):b._bind(k,c,function(d){if((d=d||window.event||!1)&&d.srcElement)d.target=d.srcElement;\"pageY\"in d||(d.pageX=d.clientX+document.documentElement.scrollLeft,d.pageY=d.clientY+document.documentElement.scrollTop);return!1===f.call(k,d)||!1===e?b.cancelEvent(d):!0})};this._unbind=function(b,c,f,g){b.removeEventListener?b.removeEventListener(c,\n        f,g):b.detachEvent?b.detachEvent(\"on\"+c,f):b[\"on\"+c]=!1};this.unbindAll=function(){for(var d=0;d<b.events.length;d++){var c=b.events[d];c.q?c.e.unbind(c.n,c.f):b._unbind(c.e,c.n,c.f,c.b)}};this.cancelEvent=function(b){b=b.original?b.original:b?b:window.event||!1;if(!b)return!1;b.preventDefault&&b.preventDefault();b.stopPropagation&&b.stopPropagation();b.preventManipulation&&b.preventManipulation();b.cancelBubble=!0;b.cancel=!0;return b.returnValue=!1};this.stopPropagation=function(b){b=b.original?\n        b.original:b?b:window.event||!1;if(!b)return!1;if(b.stopPropagation)return b.stopPropagation();b.cancelBubble&&(b.cancelBubble=!0);return!1};this.showRail=function(){if(0!=b.page.maxh&&(b.ispage||\"none\"!=b.win.css(\"display\")))b.visibility=!0,b.rail.visibility=!0,b.rail.css(\"display\",\"block\");return b};this.showRailHr=function(){if(!b.railh)return b;if(0!=b.page.maxw&&(b.ispage||\"none\"!=b.win.css(\"display\")))b.railh.visibility=!0,b.railh.css(\"display\",\"block\");return b};this.hideRail=function(){b.visibility=\n        !1;b.rail.visibility=!1;b.rail.css(\"display\",\"none\");return b};this.hideRailHr=function(){if(!b.railh)return b;b.railh.visibility=!1;b.railh.css(\"display\",\"none\");return b};this.show=function(){b.hidden=!1;b.locked=!1;return b.showRail().showRailHr()};this.hide=function(){b.hidden=!0;b.locked=!0;return b.hideRail().hideRailHr()};this.toggle=function(){return b.hidden?b.show():b.hide()};this.remove=function(){b.stop();b.cursortimeout&&clearTimeout(b.cursortimeout);b.doZoomOut();b.unbindAll();g.isie9&&\n    b.win[0].detachEvent(\"onpropertychange\",b.onAttributeChange);!1!==b.observer&&b.observer.disconnect();!1!==b.observerremover&&b.observerremover.disconnect();b.events=null;b.cursor&&b.cursor.remove();b.cursorh&&b.cursorh.remove();b.rail&&b.rail.remove();b.railh&&b.railh.remove();b.zoom&&b.zoom.remove();for(var d=0;d<b.saved.css.length;d++){var c=b.saved.css[d];c[0].css(c[1],\"undefined\"==typeof c[2]?\"\":c[2])}b.saved=!1;b.me.data(\"__nicescroll\",\"\");var f=e.nicescroll;f.each(function(d){if(this&&this.id===\n        b.id){delete f[d];for(var c=++d;c<f.length;c++,d++)f[d]=f[c];f.length--;f.length&&delete f[f.length]}});for(var k in b)b[k]=null,delete b[k];b=null};this.scrollstart=function(d){this.onscrollstart=d;return b};this.scrollend=function(d){this.onscrollend=d;return b};this.scrollcancel=function(d){this.onscrollcancel=d;return b};this.zoomin=function(d){this.onzoomin=d;return b};this.zoomout=function(d){this.onzoomout=d;return b};this.isScrollable=function(b){b=b.target?b.target:b;if(\"OPTION\"==b.nodeName)return!0;\n        for(;b&&1==b.nodeType&&!/BODY|HTML/.test(b.nodeName);){var c=e(b),c=c.css(\"overflowY\")||c.css(\"overflowX\")||c.css(\"overflow\")||\"\";if(/scroll|auto/.test(c))return b.clientHeight!=b.scrollHeight;b=b.parentNode?b.parentNode:!1}return!1};this.getViewport=function(b){for(b=b&&b.parentNode?b.parentNode:!1;b&&1==b.nodeType&&!/BODY|HTML/.test(b.nodeName);){var c=e(b);if(/fixed|absolute/.test(c.css(\"position\")))return c;var f=c.css(\"overflowY\")||c.css(\"overflowX\")||c.css(\"overflow\")||\"\";if(/scroll|auto/.test(f)&&\n        b.clientHeight!=b.scrollHeight||0<c.getNiceScroll().length)return c;b=b.parentNode?b.parentNode:!1}return!1};this.onmousewheel=function(d){if(b.locked)return b.debounced(\"checkunlock\",b.resize,250),!0;if(b.rail.drag)return b.cancelEvent(d);\"auto\"==b.opt.oneaxismousemode&&0!=d.deltaX&&(b.opt.oneaxismousemode=!1);if(b.opt.oneaxismousemode&&0==d.deltaX&&!b.rail.scrollable)return b.railh&&b.railh.scrollable?b.onmousewheelhr(d):!0;var c=+new Date,f=!1;b.opt.preservenativescrolling&&b.checkarea+600<c&&\n    (b.nativescrollingarea=b.isScrollable(d),f=!0);b.checkarea=c;if(b.nativescrollingarea)return!0;if(d=t(d,!1,f))b.checkarea=0;return d};this.onmousewheelhr=function(d){if(b.locked||!b.railh.scrollable)return!0;if(b.rail.drag)return b.cancelEvent(d);var c=+new Date,f=!1;b.opt.preservenativescrolling&&b.checkarea+600<c&&(b.nativescrollingarea=b.isScrollable(d),f=!0);b.checkarea=c;return b.nativescrollingarea?!0:b.locked?b.cancelEvent(d):t(d,!0,f)};this.stop=function(){b.cancelScroll();b.scrollmon&&b.scrollmon.stop();\n        b.cursorfreezed=!1;b.scroll.y=Math.round(b.getScrollTop()*(1/b.scrollratio.y));b.noticeCursor();return b};this.getTransitionSpeed=function(d){var c=Math.round(10*b.opt.scrollspeed);d=Math.min(c,Math.round(d/20*b.opt.scrollspeed));return 20<d?d:0};b.opt.smoothscroll?b.ishwscroll&&g.hastransition&&b.opt.usetransition?(this.prepareTransition=function(d,c){var f=c?20<d?d:0:b.getTransitionSpeed(d),e=f?g.prefixstyle+\"transform \"+f+\"ms ease-out\":\"\";if(!b.lasttransitionstyle||b.lasttransitionstyle!=e)b.lasttransitionstyle=\n        e,b.doc.css(g.transitionstyle,e);return f},this.doScrollLeft=function(c,g){var f=b.scrollrunning?b.newscrolly:b.getScrollTop();b.doScrollPos(c,f,g)},this.doScrollTop=function(c,g){var f=b.scrollrunning?b.newscrollx:b.getScrollLeft();b.doScrollPos(f,c,g)},this.doScrollPos=function(c,e,f){var k=b.getScrollTop(),l=b.getScrollLeft();(0>(b.newscrolly-k)*(e-k)||0>(b.newscrollx-l)*(c-l))&&b.cancelScroll();!1==b.opt.bouncescroll&&(0>e?e=0:e>b.page.maxh&&(e=b.page.maxh),0>c?c=0:c>b.page.maxw&&(c=b.page.maxw));\n        if(b.scrollrunning&&c==b.newscrollx&&e==b.newscrolly)return!1;b.newscrolly=e;b.newscrollx=c;b.newscrollspeed=f||!1;if(b.timer)return!1;b.timer=setTimeout(function(){var f=b.getScrollTop(),k=b.getScrollLeft(),l,h;l=c-k;h=e-f;l=Math.round(Math.sqrt(Math.pow(l,2)+Math.pow(h,2)));l=b.newscrollspeed&&1<b.newscrollspeed?b.newscrollspeed:b.getTransitionSpeed(l);b.newscrollspeed&&1>=b.newscrollspeed&&(l*=b.newscrollspeed);b.prepareTransition(l,!0);b.timerscroll&&b.timerscroll.tm&&clearInterval(b.timerscroll.tm);\n            0<l&&(!b.scrollrunning&&b.onscrollstart&&b.onscrollstart.call(b,{type:\"scrollstart\",current:{x:k,y:f},request:{x:c,y:e},end:{x:b.newscrollx,y:b.newscrolly},speed:l}),g.transitionend?b.scrollendtrapped||(b.scrollendtrapped=!0,b.bind(b.doc,g.transitionend,b.onScrollEnd,!1)):(b.scrollendtrapped&&clearTimeout(b.scrollendtrapped),b.scrollendtrapped=setTimeout(b.onScrollEnd,l)),b.timerscroll={bz:new BezierClass(f,b.newscrolly,l,0,0,0.58,1),bh:new BezierClass(k,b.newscrollx,l,0,0,0.58,1)},b.cursorfreezed||\n                (b.timerscroll.tm=setInterval(function(){b.showCursor(b.getScrollTop(),b.getScrollLeft())},60)));b.synched(\"doScroll-set\",function(){b.timer=0;b.scrollendtrapped&&(b.scrollrunning=!0);b.setScrollTop(b.newscrolly);b.setScrollLeft(b.newscrollx);if(!b.scrollendtrapped)b.onScrollEnd()})},50)},this.cancelScroll=function(){if(!b.scrollendtrapped)return!0;var c=b.getScrollTop(),e=b.getScrollLeft();b.scrollrunning=!1;g.transitionend||clearTimeout(g.transitionend);b.scrollendtrapped=!1;b._unbind(b.doc,g.transitionend,\n        b.onScrollEnd);b.prepareTransition(0);b.setScrollTop(c);b.railh&&b.setScrollLeft(e);b.timerscroll&&b.timerscroll.tm&&clearInterval(b.timerscroll.tm);b.timerscroll=!1;b.cursorfreezed=!1;b.showCursor(c,e);return b},this.onScrollEnd=function(){b.scrollendtrapped&&b._unbind(b.doc,g.transitionend,b.onScrollEnd);b.scrollendtrapped=!1;b.prepareTransition(0);b.timerscroll&&b.timerscroll.tm&&clearInterval(b.timerscroll.tm);b.timerscroll=!1;var c=b.getScrollTop(),e=b.getScrollLeft();b.setScrollTop(c);b.railh&&\n    b.setScrollLeft(e);b.noticeCursor(!1,c,e);b.cursorfreezed=!1;0>c?c=0:c>b.page.maxh&&(c=b.page.maxh);0>e?e=0:e>b.page.maxw&&(e=b.page.maxw);if(c!=b.newscrolly||e!=b.newscrollx)return b.doScrollPos(e,c,b.opt.snapbackspeed);b.onscrollend&&b.scrollrunning&&b.onscrollend.call(b,{type:\"scrollend\",current:{x:e,y:c},end:{x:b.newscrollx,y:b.newscrolly}});b.scrollrunning=!1}):(this.doScrollLeft=function(c,g){var f=b.scrollrunning?b.newscrolly:b.getScrollTop();b.doScrollPos(c,f,g)},this.doScrollTop=function(c,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          g){var f=b.scrollrunning?b.newscrollx:b.getScrollLeft();b.doScrollPos(f,c,g)},this.doScrollPos=function(c,g,f){function e(){if(b.cancelAnimationFrame)return!0;b.scrollrunning=!0;if(p=1-p)return b.timer=v(e)||1;var c=0,d=sy=b.getScrollTop();if(b.dst.ay){var d=b.bzscroll?b.dst.py+b.bzscroll.getNow()*b.dst.ay:b.newscrolly,f=d-sy;if(0>f&&d<b.newscrolly||0<f&&d>b.newscrolly)d=b.newscrolly;b.setScrollTop(d);d==b.newscrolly&&(c=1)}else c=1;var g=sx=b.getScrollLeft();if(b.dst.ax){g=b.bzscroll?b.dst.px+b.bzscroll.getNow()*\n        b.dst.ax:b.newscrollx;f=g-sx;if(0>f&&g<b.newscrollx||0<f&&g>b.newscrollx)g=b.newscrollx;b.setScrollLeft(g);g==b.newscrollx&&(c+=1)}else c+=1;2==c?(b.timer=0,b.cursorfreezed=!1,b.bzscroll=!1,b.scrollrunning=!1,0>d?d=0:d>b.page.maxh&&(d=b.page.maxh),0>g?g=0:g>b.page.maxw&&(g=b.page.maxw),g!=b.newscrollx||d!=b.newscrolly?b.doScrollPos(g,d):b.onscrollend&&b.onscrollend.call(b,{type:\"scrollend\",current:{x:sx,y:sy},end:{x:b.newscrollx,y:b.newscrolly}})):b.timer=v(e)||1}g=\"undefined\"==typeof g||!1===g?b.getScrollTop(!0):\n        g;if(b.timer&&b.newscrolly==g&&b.newscrollx==c)return!0;b.timer&&w(b.timer);b.timer=0;var k=b.getScrollTop(),l=b.getScrollLeft();(0>(b.newscrolly-k)*(g-k)||0>(b.newscrollx-l)*(c-l))&&b.cancelScroll();b.newscrolly=g;b.newscrollx=c;if(!b.bouncescroll||!b.rail.visibility)0>b.newscrolly?b.newscrolly=0:b.newscrolly>b.page.maxh&&(b.newscrolly=b.page.maxh);if(!b.bouncescroll||!b.railh.visibility)0>b.newscrollx?b.newscrollx=0:b.newscrollx>b.page.maxw&&(b.newscrollx=b.page.maxw);b.dst={};b.dst.x=c-l;b.dst.y=\n        g-k;b.dst.px=l;b.dst.py=k;var h=Math.round(Math.sqrt(Math.pow(b.dst.x,2)+Math.pow(b.dst.y,2)));b.dst.ax=b.dst.x/h;b.dst.ay=b.dst.y/h;var m=0,q=h;0==b.dst.x?(m=k,q=g,b.dst.ay=1,b.dst.py=0):0==b.dst.y&&(m=l,q=c,b.dst.ax=1,b.dst.px=0);h=b.getTransitionSpeed(h);f&&1>=f&&(h*=f);b.bzscroll=0<h?b.bzscroll?b.bzscroll.update(q,h):new BezierClass(m,q,h,0,1,0,1):!1;if(!b.timer){(k==b.page.maxh&&g>=b.page.maxh||l==b.page.maxw&&c>=b.page.maxw)&&b.checkContentSize();var p=1;b.cancelAnimationFrame=!1;b.timer=1;\n        b.onscrollstart&&!b.scrollrunning&&b.onscrollstart.call(b,{type:\"scrollstart\",current:{x:l,y:k},request:{x:c,y:g},end:{x:b.newscrollx,y:b.newscrolly},speed:h});e();(k==b.page.maxh&&g>=k||l==b.page.maxw&&c>=l)&&b.checkContentSize();b.noticeCursor()}},this.cancelScroll=function(){b.timer&&w(b.timer);b.timer=0;b.bzscroll=!1;b.scrollrunning=!1;return b}):(this.doScrollLeft=function(c,g){var f=b.getScrollTop();b.doScrollPos(c,f,g)},this.doScrollTop=function(c,g){var f=b.getScrollLeft();b.doScrollPos(f,\n        c,g)},this.doScrollPos=function(c,g,f){var e=c>b.page.maxw?b.page.maxw:c;0>e&&(e=0);var k=g>b.page.maxh?b.page.maxh:g;0>k&&(k=0);b.synched(\"scroll\",function(){b.setScrollTop(k);b.setScrollLeft(e)})},this.cancelScroll=function(){});this.doScrollBy=function(c,g){var f=0,f=g?Math.floor((b.scroll.y-c)*b.scrollratio.y):(b.timer?b.newscrolly:b.getScrollTop(!0))-c;if(b.bouncescroll){var e=Math.round(b.view.h/2);f<-e?f=-e:f>b.page.maxh+e&&(f=b.page.maxh+e)}b.cursorfreezed=!1;py=b.getScrollTop(!0);if(0>f&&\n        0>=py)return b.noticeCursor();if(f>b.page.maxh&&py>=b.page.maxh)return b.checkContentSize(),b.noticeCursor();b.doScrollTop(f)};this.doScrollLeftBy=function(c,g){var f=0,f=g?Math.floor((b.scroll.x-c)*b.scrollratio.x):(b.timer?b.newscrollx:b.getScrollLeft(!0))-c;if(b.bouncescroll){var e=Math.round(b.view.w/2);f<-e?f=-e:f>b.page.maxw+e&&(f=b.page.maxw+e)}b.cursorfreezed=!1;px=b.getScrollLeft(!0);if(0>f&&0>=px||f>b.page.maxw&&px>=b.page.maxw)return b.noticeCursor();b.doScrollLeft(f)};this.doScrollTo=\n        function(c,g){g&&Math.round(c*b.scrollratio.y);b.cursorfreezed=!1;b.doScrollTop(c)};this.checkContentSize=function(){var c=b.getContentSize();(c.h!=b.page.h||c.w!=b.page.w)&&b.resize(!1,c)};b.onscroll=function(c){b.rail.drag||b.cursorfreezed||b.synched(\"scroll\",function(){b.scroll.y=Math.round(b.getScrollTop()*(1/b.scrollratio.y));b.railh&&(b.scroll.x=Math.round(b.getScrollLeft()*(1/b.scrollratio.x)));b.noticeCursor()})};b.bind(b.docscroll,\"scroll\",b.onscroll);this.doZoomIn=function(c){if(!b.zoomactive){b.zoomactive=\n        !0;b.zoomrestore={style:{}};var k=\"position top left zIndex backgroundColor marginTop marginBottom marginLeft marginRight\".split(\" \"),f=b.win[0].style,l;for(l in k){var h=k[l];b.zoomrestore.style[h]=\"undefined\"!=typeof f[h]?f[h]:\"\"}b.zoomrestore.style.width=b.win.css(\"width\");b.zoomrestore.style.height=b.win.css(\"height\");b.zoomrestore.padding={w:b.win.outerWidth()-b.win.width(),h:b.win.outerHeight()-b.win.height()};g.isios4&&(b.zoomrestore.scrollTop=e(window).scrollTop(),e(window).scrollTop(0));\n        b.win.css({position:g.isios4?\"absolute\":\"fixed\",top:0,left:0,\"z-index\":y+100,margin:\"0px\"});k=b.win.css(\"backgroundColor\");(\"\"==k||/transparent|rgba\\(0, 0, 0, 0\\)|rgba\\(0,0,0,0\\)/.test(k))&&b.win.css(\"backgroundColor\",\"#fff\");b.rail.css({\"z-index\":y+101});b.zoom.css({\"z-index\":y+102});b.zoom.css(\"backgroundPosition\",\"0px -18px\");b.resizeZoom();b.onzoomin&&b.onzoomin.call(b);return b.cancelEvent(c)}};this.doZoomOut=function(c){if(b.zoomactive)return b.zoomactive=!1,b.win.css(\"margin\",\"\"),b.win.css(b.zoomrestore.style),\n        g.isios4&&e(window).scrollTop(b.zoomrestore.scrollTop),b.rail.css({\"z-index\":b.zindex}),b.zoom.css({\"z-index\":b.zindex}),b.zoomrestore=!1,b.zoom.css(\"backgroundPosition\",\"0px 0px\"),b.onResize(),b.onzoomout&&b.onzoomout.call(b),b.cancelEvent(c)};this.doZoom=function(c){return b.zoomactive?b.doZoomOut(c):b.doZoomIn(c)};this.resizeZoom=function(){if(b.zoomactive){var c=b.getScrollTop();b.win.css({width:e(window).width()-b.zoomrestore.padding.w+\"px\",height:e(window).height()-b.zoomrestore.padding.h+\"px\"});\n        b.onResize();b.setScrollTop(Math.min(b.page.maxh,c))}};this.init();e.nicescroll.push(this)},J=function(e){var c=this;this.nc=e;this.steptime=this.lasttime=this.speedy=this.speedx=this.lasty=this.lastx=0;this.snapy=this.snapx=!1;this.demuly=this.demulx=0;this.lastscrolly=this.lastscrollx=-1;this.timer=this.chky=this.chkx=0;this.time=function(){return+new Date};this.reset=function(e,l){c.stop();var h=c.time();c.steptime=0;c.lasttime=h;c.speedx=0;c.speedy=0;c.lastx=e;c.lasty=l;c.lastscrollx=-1;c.lastscrolly=\n    -1};this.update=function(e,l){var h=c.time();c.steptime=h-c.lasttime;c.lasttime=h;var h=l-c.lasty,t=e-c.lastx,b=c.nc.getScrollTop(),p=c.nc.getScrollLeft(),b=b+h,p=p+t;c.snapx=0>p||p>c.nc.page.maxw;c.snapy=0>b||b>c.nc.page.maxh;c.speedx=t;c.speedy=h;c.lastx=e;c.lasty=l};this.stop=function(){c.nc.unsynched(\"domomentum2d\");c.timer&&clearTimeout(c.timer);c.timer=0;c.lastscrollx=-1;c.lastscrolly=-1};this.doSnapy=function(e,l){var h=!1;0>l?(l=0,h=!0):l>c.nc.page.maxh&&(l=c.nc.page.maxh,h=!0);0>e?(e=0,h=\n    !0):e>c.nc.page.maxw&&(e=c.nc.page.maxw,h=!0);h&&c.nc.doScrollPos(e,l,c.nc.opt.snapbackspeed)};this.doMomentum=function(e){var l=c.time(),h=e?l+e:c.lasttime;e=c.nc.getScrollLeft();var t=c.nc.getScrollTop(),b=c.nc.page.maxh,p=c.nc.page.maxw;c.speedx=0<p?Math.min(60,c.speedx):0;c.speedy=0<b?Math.min(60,c.speedy):0;h=h&&60>=l-h;if(0>t||t>b||0>e||e>p)h=!1;e=c.speedx&&h?c.speedx:!1;if(c.speedy&&h&&c.speedy||e){var g=Math.max(16,c.steptime);50<g&&(e=g/50,c.speedx*=e,c.speedy*=e,g=50);c.demulxy=0;c.lastscrollx=\n    c.nc.getScrollLeft();c.chkx=c.lastscrollx;c.lastscrolly=c.nc.getScrollTop();c.chky=c.lastscrolly;var s=c.lastscrollx,u=c.lastscrolly,d=function(){var e=600<c.time()-l?0.04:0.02;if(c.speedx&&(s=Math.floor(c.lastscrollx-c.speedx*(1-c.demulxy)),c.lastscrollx=s,0>s||s>p))e=0.1;if(c.speedy&&(u=Math.floor(c.lastscrolly-c.speedy*(1-c.demulxy)),c.lastscrolly=u,0>u||u>b))e=0.1;c.demulxy=Math.min(1,c.demulxy+e);c.nc.synched(\"domomentum2d\",function(){c.speedx&&(c.nc.getScrollLeft()!=c.chkx&&c.stop(),c.chkx=\n    s,c.nc.setScrollLeft(s));c.speedy&&(c.nc.getScrollTop()!=c.chky&&c.stop(),c.chky=u,c.nc.setScrollTop(u));c.timer||(c.nc.hideCursor(),c.doSnapy(s,u))});1>c.demulxy?c.timer=setTimeout(d,g):(c.stop(),c.nc.hideCursor(),c.doSnapy(s,u))};d()}else c.doSnapy(c.nc.getScrollLeft(),c.nc.getScrollTop())}},B=e.fn.scrollTop;e.cssHooks.pageYOffset={get:function(h,c,k){return(c=e.data(h,\"__nicescroll\")||!1)&&c.ishwscroll?c.getScrollTop():B.call(h)},set:function(h,c){var k=e.data(h,\"__nicescroll\")||!1;k&&k.ishwscroll?\n    k.setScrollTop(parseInt(c)):B.call(h,c);return this}};e.fn.scrollTop=function(h){if(\"undefined\"==typeof h){var c=this[0]?e.data(this[0],\"__nicescroll\")||!1:!1;return c&&c.ishwscroll?c.getScrollTop():B.call(this)}return this.each(function(){var c=e.data(this,\"__nicescroll\")||!1;c&&c.ishwscroll?c.setScrollTop(parseInt(h)):B.call(e(this),h)})};var C=e.fn.scrollLeft;e.cssHooks.pageXOffset={get:function(h,c,k){return(c=e.data(h,\"__nicescroll\")||!1)&&c.ishwscroll?c.getScrollLeft():C.call(h)},set:function(h,\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            c){var k=e.data(h,\"__nicescroll\")||!1;k&&k.ishwscroll?k.setScrollLeft(parseInt(c)):C.call(h,c);return this}};e.fn.scrollLeft=function(h){if(\"undefined\"==typeof h){var c=this[0]?e.data(this[0],\"__nicescroll\")||!1:!1;return c&&c.ishwscroll?c.getScrollLeft():C.call(this)}return this.each(function(){var c=e.data(this,\"__nicescroll\")||!1;c&&c.ishwscroll?c.setScrollLeft(parseInt(h)):C.call(e(this),h)})};var D=function(h){var c=this;this.length=0;this.name=\"nicescrollarray\";this.each=function(e){for(var h=\n    0,k=0;h<c.length;h++)e.call(c[h],k++);return c};this.push=function(e){c[c.length]=e;c.length++};this.eq=function(e){return c[e]};if(h)for(a=0;a<h.length;a++){var k=e.data(h[a],\"__nicescroll\")||!1;k&&(this[this.length]=k,this.length++)}return this};(function(e,c,k){for(var l=0;l<c.length;l++)k(e,c[l])})(D.prototype,\"show hide toggle onResize resize remove stop doScrollPos\".split(\" \"),function(e,c){e[c]=function(){var e=arguments;return this.each(function(){this[c].apply(this,e)})}});e.fn.getNiceScroll=\n    function(h){return\"undefined\"==typeof h?new D(this):this[h]&&e.data(this[h],\"__nicescroll\")||!1};e.extend(e.expr[\":\"],{nicescroll:function(h){return e.data(h,\"__nicescroll\")?!0:!1}});e.fn.niceScroll=function(h,c){\"undefined\"==typeof c&&(\"object\"==typeof h&&!(\"jquery\"in h))&&(c=h,h=!1);var k=new D;\"undefined\"==typeof c&&(c={});h&&(c.doc=e(h),c.win=e(this));var l=!(\"doc\"in c);!l&&!(\"win\"in c)&&(c.win=e(this));this.each(function(){var h=e(this).data(\"__nicescroll\")||!1;h||(c.doc=l?e(this):c.doc,h=new Q(c,\n    e(this)),e(this).data(\"__nicescroll\",h));k.push(h)});return 1==k.length?k[0]:k};window.NiceScroll={getjQuery:function(){return e}};e.nicescroll||(e.nicescroll=new D,e.nicescroll.options=I)})(jQuery);\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/jquery.sparkline.js",
    "content": "/**\n*\n* jquery.sparkline.js\n*\n* v2.1.2\n* (c) Splunk, Inc\n* Contact: Gareth Watts (gareth@splunk.com)\n* http://omnipotent.net/jquery.sparkline/\n*\n* Generates inline sparkline charts from data supplied either to the method\n* or inline in HTML\n*\n* Compatible with Internet Explorer 6.0+ and modern browsers equipped with the canvas tag\n* (Firefox 2.0+, Safari, Opera, etc)\n*\n* License: New BSD License\n*\n* Copyright (c) 2012, Splunk Inc.\n* All rights reserved.\n*\n* Redistribution and use in source and binary forms, with or without modification,\n* are permitted provided that the following conditions are met:\n*\n*     * Redistributions of source code must retain the above copyright notice,\n*       this list of conditions and the following disclaimer.\n*     * Redistributions in binary form must reproduce the above copyright notice,\n*       this list of conditions and the following disclaimer in the documentation\n*       and/or other materials provided with the distribution.\n*     * Neither the name of Splunk Inc nor the names of its contributors may\n*       be used to endorse or promote products derived from this software without\n*       specific prior written permission.\n*\n* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY\n* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT\n* SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT\n* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*\n*\n* Usage:\n*  $(selector).sparkline(values, options)\n*\n* If values is undefined or set to 'html' then the data values are read from the specified tag:\n*   <p>Sparkline: <span class=\"sparkline\">1,4,6,6,8,5,3,5</span></p>\n*   $('.sparkline').sparkline();\n* There must be no spaces in the enclosed data set\n*\n* Otherwise values must be an array of numbers or null values\n*    <p>Sparkline: <span id=\"sparkline1\">This text replaced if the browser is compatible</span></p>\n*    $('#sparkline1').sparkline([1,4,6,6,8,5,3,5])\n*    $('#sparkline2').sparkline([1,4,6,null,null,5,3,5])\n*\n* Values can also be specified in an HTML comment, or as a values attribute:\n*    <p>Sparkline: <span class=\"sparkline\"><!--1,4,6,6,8,5,3,5 --></span></p>\n*    <p>Sparkline: <span class=\"sparkline\" values=\"1,4,6,6,8,5,3,5\"></span></p>\n*    $('.sparkline').sparkline();\n*\n* For line charts, x values can also be specified:\n*   <p>Sparkline: <span class=\"sparkline\">1:1,2.7:4,3.4:6,5:6,6:8,8.7:5,9:3,10:5</span></p>\n*    $('#sparkline1').sparkline([ [1,1], [2.7,4], [3.4,6], [5,6], [6,8], [8.7,5], [9,3], [10,5] ])\n*\n* By default, options should be passed in as teh second argument to the sparkline function:\n*   $('.sparkline').sparkline([1,2,3,4], {type: 'bar'})\n*\n* Options can also be set by passing them on the tag itself.  This feature is disabled by default though\n* as there's a slight performance overhead:\n*   $('.sparkline').sparkline([1,2,3,4], {enableTagOptions: true})\n*   <p>Sparkline: <span class=\"sparkline\" sparkType=\"bar\" sparkBarColor=\"red\">loading</span></p>\n* Prefix all options supplied as tag attribute with \"spark\" (configurable by setting tagOptionPrefix)\n*\n* Supported options:\n*   lineColor - Color of the line used for the chart\n*   fillColor - Color used to fill in the chart - Set to '' or false for a transparent chart\n*   width - Width of the chart - Defaults to 3 times the number of values in pixels\n*   height - Height of the chart - Defaults to the height of the containing element\n*   chartRangeMin - Specify the minimum value to use for the Y range of the chart - Defaults to the minimum value supplied\n*   chartRangeMax - Specify the maximum value to use for the Y range of the chart - Defaults to the maximum value supplied\n*   chartRangeClip - Clip out of range values to the max/min specified by chartRangeMin and chartRangeMax\n*   chartRangeMinX - Specify the minimum value to use for the X range of the chart - Defaults to the minimum value supplied\n*   chartRangeMaxX - Specify the maximum value to use for the X range of the chart - Defaults to the maximum value supplied\n*   composite - If true then don't erase any existing chart attached to the tag, but draw\n*           another chart over the top - Note that width and height are ignored if an\n*           existing chart is detected.\n*   tagValuesAttribute - Name of tag attribute to check for data values - Defaults to 'values'\n*   enableTagOptions - Whether to check tags for sparkline options\n*   tagOptionPrefix - Prefix used for options supplied as tag attributes - Defaults to 'spark'\n*   disableHiddenCheck - If set to true, then the plugin will assume that charts will never be drawn into a\n*           hidden dom element, avoding a browser reflow\n*   disableInteraction - If set to true then all mouseover/click interaction behaviour will be disabled,\n*       making the plugin perform much like it did in 1.x\n*   disableTooltips - If set to true then tooltips will be disabled - Defaults to false (tooltips enabled)\n*   disableHighlight - If set to true then highlighting of selected chart elements on mouseover will be disabled\n*       defaults to false (highlights enabled)\n*   highlightLighten - Factor to lighten/darken highlighted chart values by - Defaults to 1.4 for a 40% increase\n*   tooltipContainer - Specify which DOM element the tooltip should be rendered into - defaults to document.body\n*   tooltipClassname - Optional CSS classname to apply to tooltips - If not specified then a default style will be applied\n*   tooltipOffsetX - How many pixels away from the mouse pointer to render the tooltip on the X axis\n*   tooltipOffsetY - How many pixels away from the mouse pointer to render the tooltip on the r axis\n*   tooltipFormatter  - Optional callback that allows you to override the HTML displayed in the tooltip\n*       callback is given arguments of (sparkline, options, fields)\n*   tooltipChartTitle - If specified then the tooltip uses the string specified by this setting as a title\n*   tooltipFormat - A format string or SPFormat object  (or an array thereof for multiple entries)\n*       to control the format of the tooltip\n*   tooltipPrefix - A string to prepend to each field displayed in a tooltip\n*   tooltipSuffix - A string to append to each field displayed in a tooltip\n*   tooltipSkipNull - If true then null values will not have a tooltip displayed (defaults to true)\n*   tooltipValueLookups - An object or range map to map field values to tooltip strings\n*       (eg. to map -1 to \"Lost\", 0 to \"Draw\", and 1 to \"Win\")\n*   numberFormatter - Optional callback for formatting numbers in tooltips\n*   numberDigitGroupSep - Character to use for group separator in numbers \"1,234\" - Defaults to \",\"\n*   numberDecimalMark - Character to use for the decimal point when formatting numbers - Defaults to \".\"\n*   numberDigitGroupCount - Number of digits between group separator - Defaults to 3\n*\n* There are 7 types of sparkline, selected by supplying a \"type\" option of 'line' (default),\n* 'bar', 'tristate', 'bullet', 'discrete', 'pie' or 'box'\n*    line - Line chart.  Options:\n*       spotColor - Set to '' to not end each line in a circular spot\n*       minSpotColor - If set, color of spot at minimum value\n*       maxSpotColor - If set, color of spot at maximum value\n*       spotRadius - Radius in pixels\n*       lineWidth - Width of line in pixels\n*       normalRangeMin\n*       normalRangeMax - If set draws a filled horizontal bar between these two values marking the \"normal\"\n*                      or expected range of values\n*       normalRangeColor - Color to use for the above bar\n*       drawNormalOnTop - Draw the normal range above the chart fill color if true\n*       defaultPixelsPerValue - Defaults to 3 pixels of width for each value in the chart\n*       highlightSpotColor - The color to use for drawing a highlight spot on mouseover - Set to null to disable\n*       highlightLineColor - The color to use for drawing a highlight line on mouseover - Set to null to disable\n*       valueSpots - Specify which points to draw spots on, and in which color.  Accepts a range map\n*\n*   bar - Bar chart.  Options:\n*       barColor - Color of bars for postive values\n*       negBarColor - Color of bars for negative values\n*       zeroColor - Color of bars with zero values\n*       nullColor - Color of bars with null values - Defaults to omitting the bar entirely\n*       barWidth - Width of bars in pixels\n*       colorMap - Optional mappnig of values to colors to override the *BarColor values above\n*                  can be an Array of values to control the color of individual bars or a range map\n*                  to specify colors for individual ranges of values\n*       barSpacing - Gap between bars in pixels\n*       zeroAxis - Centers the y-axis around zero if true\n*\n*   tristate - Charts values of win (>0), lose (<0) or draw (=0)\n*       posBarColor - Color of win values\n*       negBarColor - Color of lose values\n*       zeroBarColor - Color of draw values\n*       barWidth - Width of bars in pixels\n*       barSpacing - Gap between bars in pixels\n*       colorMap - Optional mappnig of values to colors to override the *BarColor values above\n*                  can be an Array of values to control the color of individual bars or a range map\n*                  to specify colors for individual ranges of values\n*\n*   discrete - Options:\n*       lineHeight - Height of each line in pixels - Defaults to 30% of the graph height\n*       thesholdValue - Values less than this value will be drawn using thresholdColor instead of lineColor\n*       thresholdColor\n*\n*   bullet - Values for bullet graphs msut be in the order: target, performance, range1, range2, range3, ...\n*       options:\n*       targetColor - The color of the vertical target marker\n*       targetWidth - The width of the target marker in pixels\n*       performanceColor - The color of the performance measure horizontal bar\n*       rangeColors - Colors to use for each qualitative range background color\n*\n*   pie - Pie chart. Options:\n*       sliceColors - An array of colors to use for pie slices\n*       offset - Angle in degrees to offset the first slice - Try -90 or +90\n*       borderWidth - Width of border to draw around the pie chart, in pixels - Defaults to 0 (no border)\n*       borderColor - Color to use for the pie chart border - Defaults to #000\n*\n*   box - Box plot. Options:\n*       raw - Set to true to supply pre-computed plot points as values\n*             values should be: low_outlier, low_whisker, q1, median, q3, high_whisker, high_outlier\n*             When set to false you can supply any number of values and the box plot will\n*             be computed for you.  Default is false.\n*       showOutliers - Set to true (default) to display outliers as circles\n*       outlierIQR - Interquartile range used to determine outliers.  Default 1.5\n*       boxLineColor - Outline color of the box\n*       boxFillColor - Fill color for the box\n*       whiskerColor - Line color used for whiskers\n*       outlierLineColor - Outline color of outlier circles\n*       outlierFillColor - Fill color of the outlier circles\n*       spotRadius - Radius of outlier circles\n*       medianColor - Line color of the median line\n*       target - Draw a target cross hair at the supplied value (default undefined)\n*\n*\n*\n*   Examples:\n*   $('#sparkline1').sparkline(myvalues, { lineColor: '#f00', fillColor: false });\n*   $('.barsparks').sparkline('html', { type:'bar', height:'40px', barWidth:5 });\n*   $('#tristate').sparkline([1,1,-1,1,0,0,-1], { type:'tristate' }):\n*   $('#discrete').sparkline([1,3,4,5,5,3,4,5], { type:'discrete' });\n*   $('#bullet').sparkline([10,12,12,9,7], { type:'bullet' });\n*   $('#pie').sparkline([1,1,2], { type:'pie' });\n*/\n\n/*jslint regexp: true, browser: true, jquery: true, white: true, nomen: false, plusplus: false, maxerr: 500, indent: 4 */\n\n(function(document, Math, undefined) { // performance/minified-size optimization\n(function(factory) {\n    if(typeof define === 'function' && define.amd) {\n        define(['jquery'], factory);\n    } else if (jQuery && !jQuery.fn.sparkline) {\n        factory(jQuery);\n    }\n}\n(function($) {\n    'use strict';\n\n    var UNSET_OPTION = {},\n        getDefaults, createClass, SPFormat, clipval, quartile, normalizeValue, normalizeValues,\n        remove, isNumber, all, sum, addCSS, ensureArray, formatNumber, RangeMap,\n        MouseHandler, Tooltip, barHighlightMixin,\n        line, bar, tristate, discrete, bullet, pie, box, defaultStyles, initStyles,\n        VShape, VCanvas_base, VCanvas_canvas, VCanvas_vml, pending, shapeCount = 0;\n\n    /**\n     * Default configuration settings\n     */\n    getDefaults = function () {\n        return {\n            // Settings common to most/all chart types\n            common: {\n                type: 'line',\n                lineColor: '#00f',\n                fillColor: '#cdf',\n                defaultPixelsPerValue: 3,\n                width: 'auto',\n                height: 'auto',\n                composite: false,\n                tagValuesAttribute: 'values',\n                tagOptionsPrefix: 'spark',\n                enableTagOptions: false,\n                enableHighlight: true,\n                highlightLighten: 1.4,\n                tooltipSkipNull: true,\n                tooltipPrefix: '',\n                tooltipSuffix: '',\n                disableHiddenCheck: false,\n                numberFormatter: false,\n                numberDigitGroupCount: 3,\n                numberDigitGroupSep: ',',\n                numberDecimalMark: '.',\n                disableTooltips: false,\n                disableInteraction: false\n            },\n            // Defaults for line charts\n            line: {\n                spotColor: '#f80',\n                highlightSpotColor: '#5f5',\n                highlightLineColor: '#f22',\n                spotRadius: 1.5,\n                minSpotColor: '#f80',\n                maxSpotColor: '#f80',\n                lineWidth: 1,\n                normalRangeMin: undefined,\n                normalRangeMax: undefined,\n                normalRangeColor: '#ccc',\n                drawNormalOnTop: false,\n                chartRangeMin: undefined,\n                chartRangeMax: undefined,\n                chartRangeMinX: undefined,\n                chartRangeMaxX: undefined,\n                tooltipFormat: new SPFormat('<span style=\"color: {{color}}\">&#9679;</span> {{prefix}}{{y}}{{suffix}}')\n            },\n            // Defaults for bar charts\n            bar: {\n                barColor: '#3366cc',\n                negBarColor: '#f44',\n                stackedBarColor: ['#3366cc', '#dc3912', '#ff9900', '#109618', '#66aa00',\n                    '#dd4477', '#0099c6', '#990099'],\n                zeroColor: undefined,\n                nullColor: undefined,\n                zeroAxis: true,\n                barWidth: 4,\n                barSpacing: 1,\n                chartRangeMax: undefined,\n                chartRangeMin: undefined,\n                chartRangeClip: false,\n                colorMap: undefined,\n                tooltipFormat: new SPFormat('<span style=\"color: {{color}}\">&#9679;</span> {{prefix}}{{value}}{{suffix}}')\n            },\n            // Defaults for tristate charts\n            tristate: {\n                barWidth: 4,\n                barSpacing: 1,\n                posBarColor: '#6f6',\n                negBarColor: '#f44',\n                zeroBarColor: '#999',\n                colorMap: {},\n                tooltipFormat: new SPFormat('<span style=\"color: {{color}}\">&#9679;</span> {{value:map}}'),\n                tooltipValueLookups: { map: { '-1': 'Loss', '0': 'Draw', '1': 'Win' } }\n            },\n            // Defaults for discrete charts\n            discrete: {\n                lineHeight: 'auto',\n                thresholdColor: undefined,\n                thresholdValue: 0,\n                chartRangeMax: undefined,\n                chartRangeMin: undefined,\n                chartRangeClip: false,\n                tooltipFormat: new SPFormat('{{prefix}}{{value}}{{suffix}}')\n            },\n            // Defaults for bullet charts\n            bullet: {\n                targetColor: '#f33',\n                targetWidth: 3, // width of the target bar in pixels\n                performanceColor: '#33f',\n                rangeColors: ['#d3dafe', '#a8b6ff', '#7f94ff'],\n                base: undefined, // set this to a number to change the base start number\n                tooltipFormat: new SPFormat('{{fieldkey:fields}} - {{value}}'),\n                tooltipValueLookups: { fields: {r: 'Range', p: 'Performance', t: 'Target'} }\n            },\n            // Defaults for pie charts\n            pie: {\n                offset: 0,\n                sliceColors: ['#3366cc', '#dc3912', '#ff9900', '#109618', '#66aa00',\n                    '#dd4477', '#0099c6', '#990099'],\n                borderWidth: 0,\n                borderColor: '#000',\n                tooltipFormat: new SPFormat('<span style=\"color: {{color}}\">&#9679;</span> {{value}} ({{percent.1}}%)')\n            },\n            // Defaults for box plots\n            box: {\n                raw: false,\n                boxLineColor: '#000',\n                boxFillColor: '#cdf',\n                whiskerColor: '#000',\n                outlierLineColor: '#333',\n                outlierFillColor: '#fff',\n                medianColor: '#f00',\n                showOutliers: true,\n                outlierIQR: 1.5,\n                spotRadius: 1.5,\n                target: undefined,\n                targetColor: '#4a2',\n                chartRangeMax: undefined,\n                chartRangeMin: undefined,\n                tooltipFormat: new SPFormat('{{field:fields}}: {{value}}'),\n                tooltipFormatFieldlistKey: 'field',\n                tooltipValueLookups: { fields: { lq: 'Lower Quartile', med: 'Median',\n                    uq: 'Upper Quartile', lo: 'Left Outlier', ro: 'Right Outlier',\n                    lw: 'Left Whisker', rw: 'Right Whisker'} }\n            }\n        };\n    };\n\n    // You can have tooltips use a css class other than jqstooltip by specifying tooltipClassname\n    // tooltip modified by westilian:jaman\n    defaultStyles = '.jqstooltip { ' +\n            'position: absolute;' +\n            'left: 0px;' +\n            'top: 0px;' +\n            'display: block;' +\n            'visibility: hidden;' +\n            'background: rgb(0, 0, 0) transparent;' +\n            'background-color: rgba(0,0,0,0.6);' +\n            'filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);' +\n            '-ms-filter: \"progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)\";' +\n            'color: white;' +\n            'font: 10px arial, san serif;' +\n            'text-align: left;' +\n            'white-space: nowrap;' +\n            \n            'border: 1px solid white;' +\n            'z-index: 10000;' +\n            '}' +\n            '.jqsfield { ' +\n            'color: white;' +\n            'padding: 5px 5px 8px 5px;' +\n            'font: 10px arial, san serif;' +\n            'text-align: left;' +\n            '}';\n\n    /**\n     * Utilities\n     */\n\n    createClass = function (/* [baseclass, [mixin, ...]], definition */) {\n        var Class, args;\n        Class = function () {\n            this.init.apply(this, arguments);\n        };\n        if (arguments.length > 1) {\n            if (arguments[0]) {\n                Class.prototype = $.extend(new arguments[0](), arguments[arguments.length - 1]);\n                Class._super = arguments[0].prototype;\n            } else {\n                Class.prototype = arguments[arguments.length - 1];\n            }\n            if (arguments.length > 2) {\n                args = Array.prototype.slice.call(arguments, 1, -1);\n                args.unshift(Class.prototype);\n                $.extend.apply($, args);\n            }\n        } else {\n            Class.prototype = arguments[0];\n        }\n        Class.prototype.cls = Class;\n        return Class;\n    };\n\n    /**\n     * Wraps a format string for tooltips\n     * {{x}}\n     * {{x.2}\n     * {{x:months}}\n     */\n    $.SPFormatClass = SPFormat = createClass({\n        fre: /\\{\\{([\\w.]+?)(:(.+?))?\\}\\}/g,\n        precre: /(\\w+)\\.(\\d+)/,\n\n        init: function (format, fclass) {\n            this.format = format;\n            this.fclass = fclass;\n        },\n\n        render: function (fieldset, lookups, options) {\n            var self = this,\n                fields = fieldset,\n                match, token, lookupkey, fieldvalue, prec;\n            return this.format.replace(this.fre, function () {\n                var lookup;\n                token = arguments[1];\n                lookupkey = arguments[3];\n                match = self.precre.exec(token);\n                if (match) {\n                    prec = match[2];\n                    token = match[1];\n                } else {\n                    prec = false;\n                }\n                fieldvalue = fields[token];\n                if (fieldvalue === undefined) {\n                    return '';\n                }\n                if (lookupkey && lookups && lookups[lookupkey]) {\n                    lookup = lookups[lookupkey];\n                    if (lookup.get) { // RangeMap\n                        return lookups[lookupkey].get(fieldvalue) || fieldvalue;\n                    } else {\n                        return lookups[lookupkey][fieldvalue] || fieldvalue;\n                    }\n                }\n                if (isNumber(fieldvalue)) {\n                    if (options.get('numberFormatter')) {\n                        fieldvalue = options.get('numberFormatter')(fieldvalue);\n                    } else {\n                        fieldvalue = formatNumber(fieldvalue, prec,\n                            options.get('numberDigitGroupCount'),\n                            options.get('numberDigitGroupSep'),\n                            options.get('numberDecimalMark'));\n                    }\n                }\n                return fieldvalue;\n            });\n        }\n    });\n\n    // convience method to avoid needing the new operator\n    $.spformat = function(format, fclass) {\n        return new SPFormat(format, fclass);\n    };\n\n    clipval = function (val, min, max) {\n        if (val < min) {\n            return min;\n        }\n        if (val > max) {\n            return max;\n        }\n        return val;\n    };\n\n    quartile = function (values, q) {\n        var vl;\n        if (q === 2) {\n            vl = Math.floor(values.length / 2);\n            return values.length % 2 ? values[vl] : (values[vl-1] + values[vl]) / 2;\n        } else {\n            if (values.length % 2 ) { // odd\n                vl = (values.length * q + q) / 4;\n                return vl % 1 ? (values[Math.floor(vl)] + values[Math.floor(vl) - 1]) / 2 : values[vl-1];\n            } else { //even\n                vl = (values.length * q + 2) / 4;\n                return vl % 1 ? (values[Math.floor(vl)] + values[Math.floor(vl) - 1]) / 2 :  values[vl-1];\n\n            }\n        }\n    };\n\n    normalizeValue = function (val) {\n        var nf;\n        switch (val) {\n            case 'undefined':\n                val = undefined;\n                break;\n            case 'null':\n                val = null;\n                break;\n            case 'true':\n                val = true;\n                break;\n            case 'false':\n                val = false;\n                break;\n            default:\n                nf = parseFloat(val);\n                if (val == nf) {\n                    val = nf;\n                }\n        }\n        return val;\n    };\n\n    normalizeValues = function (vals) {\n        var i, result = [];\n        for (i = vals.length; i--;) {\n            result[i] = normalizeValue(vals[i]);\n        }\n        return result;\n    };\n\n    remove = function (vals, filter) {\n        var i, vl, result = [];\n        for (i = 0, vl = vals.length; i < vl; i++) {\n            if (vals[i] !== filter) {\n                result.push(vals[i]);\n            }\n        }\n        return result;\n    };\n\n    isNumber = function (num) {\n        return !isNaN(parseFloat(num)) && isFinite(num);\n    };\n\n    formatNumber = function (num, prec, groupsize, groupsep, decsep) {\n        var p, i;\n        num = (prec === false ? parseFloat(num).toString() : num.toFixed(prec)).split('');\n        p = (p = $.inArray('.', num)) < 0 ? num.length : p;\n        if (p < num.length) {\n            num[p] = decsep;\n        }\n        for (i = p - groupsize; i > 0; i -= groupsize) {\n            num.splice(i, 0, groupsep);\n        }\n        return num.join('');\n    };\n\n    // determine if all values of an array match a value\n    // returns true if the array is empty\n    all = function (val, arr, ignoreNull) {\n        var i;\n        for (i = arr.length; i--; ) {\n            if (ignoreNull && arr[i] === null) continue;\n            if (arr[i] !== val) {\n                return false;\n            }\n        }\n        return true;\n    };\n\n    // sums the numeric values in an array, ignoring other values\n    sum = function (vals) {\n        var total = 0, i;\n        for (i = vals.length; i--;) {\n            total += typeof vals[i] === 'number' ? vals[i] : 0;\n        }\n        return total;\n    };\n\n    ensureArray = function (val) {\n        return $.isArray(val) ? val : [val];\n    };\n\n    // http://paulirish.com/2008/bookmarklet-inject-new-css-rules/\n    addCSS = function(css) {\n        var tag;\n        //if ('\\v' == 'v') /* ie only */ {\n        if (document.createStyleSheet) {\n            document.createStyleSheet().cssText = css;\n        } else {\n            tag = document.createElement('style');\n            tag.type = 'text/css';\n            document.getElementsByTagName('head')[0].appendChild(tag);\n            tag[(typeof document.body.style.WebkitAppearance == 'string') /* webkit only */ ? 'innerText' : 'innerHTML'] = css;\n        }\n    };\n\n    // Provide a cross-browser interface to a few simple drawing primitives\n    $.fn.simpledraw = function (width, height, useExisting, interact) {\n        var target, mhandler;\n        if (useExisting && (target = this.data('_jqs_vcanvas'))) {\n            return target;\n        }\n\n        if ($.fn.sparkline.canvas === false) {\n            // We've already determined that neither Canvas nor VML are available\n            return false;\n\n        } else if ($.fn.sparkline.canvas === undefined) {\n            // No function defined yet -- need to see if we support Canvas or VML\n            var el = document.createElement('canvas');\n            if (!!(el.getContext && el.getContext('2d'))) {\n                // Canvas is available\n                $.fn.sparkline.canvas = function(width, height, target, interact) {\n                    return new VCanvas_canvas(width, height, target, interact);\n                };\n            } else if (document.namespaces && !document.namespaces.v) {\n                // VML is available\n                document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML');\n                $.fn.sparkline.canvas = function(width, height, target, interact) {\n                    return new VCanvas_vml(width, height, target);\n                };\n            } else {\n                // Neither Canvas nor VML are available\n                $.fn.sparkline.canvas = false;\n                return false;\n            }\n        }\n\n        if (width === undefined) {\n            width = $(this).innerWidth();\n        }\n        if (height === undefined) {\n            height = $(this).innerHeight();\n        }\n\n        target = $.fn.sparkline.canvas(width, height, this, interact);\n\n        mhandler = $(this).data('_jqs_mhandler');\n        if (mhandler) {\n            mhandler.registerCanvas(target);\n        }\n        return target;\n    };\n\n    $.fn.cleardraw = function () {\n        var target = this.data('_jqs_vcanvas');\n        if (target) {\n            target.reset();\n        }\n    };\n\n    $.RangeMapClass = RangeMap = createClass({\n        init: function (map) {\n            var key, range, rangelist = [];\n            for (key in map) {\n                if (map.hasOwnProperty(key) && typeof key === 'string' && key.indexOf(':') > -1) {\n                    range = key.split(':');\n                    range[0] = range[0].length === 0 ? -Infinity : parseFloat(range[0]);\n                    range[1] = range[1].length === 0 ? Infinity : parseFloat(range[1]);\n                    range[2] = map[key];\n                    rangelist.push(range);\n                }\n            }\n            this.map = map;\n            this.rangelist = rangelist || false;\n        },\n\n        get: function (value) {\n            var rangelist = this.rangelist,\n                i, range, result;\n            if ((result = this.map[value]) !== undefined) {\n                return result;\n            }\n            if (rangelist) {\n                for (i = rangelist.length; i--;) {\n                    range = rangelist[i];\n                    if (range[0] <= value && range[1] >= value) {\n                        return range[2];\n                    }\n                }\n            }\n            return undefined;\n        }\n    });\n\n    // Convenience function\n    $.range_map = function(map) {\n        return new RangeMap(map);\n    };\n\n    MouseHandler = createClass({\n        init: function (el, options) {\n            var $el = $(el);\n            this.$el = $el;\n            this.options = options;\n            this.currentPageX = 0;\n            this.currentPageY = 0;\n            this.el = el;\n            this.splist = [];\n            this.tooltip = null;\n            this.over = false;\n            this.displayTooltips = !options.get('disableTooltips');\n            this.highlightEnabled = !options.get('disableHighlight');\n        },\n\n        registerSparkline: function (sp) {\n            this.splist.push(sp);\n            if (this.over) {\n                this.updateDisplay();\n            }\n        },\n\n        registerCanvas: function (canvas) {\n            var $canvas = $(canvas.canvas);\n            this.canvas = canvas;\n            this.$canvas = $canvas;\n            $canvas.mouseenter($.proxy(this.mouseenter, this));\n            $canvas.mouseleave($.proxy(this.mouseleave, this));\n            $canvas.click($.proxy(this.mouseclick, this));\n        },\n\n        reset: function (removeTooltip) {\n            this.splist = [];\n            if (this.tooltip && removeTooltip) {\n                this.tooltip.remove();\n                this.tooltip = undefined;\n            }\n        },\n\n        mouseclick: function (e) {\n            var clickEvent = $.Event('sparklineClick');\n            clickEvent.originalEvent = e;\n            clickEvent.sparklines = this.splist;\n            this.$el.trigger(clickEvent);\n        },\n\n        mouseenter: function (e) {\n            $(document.body).unbind('mousemove.jqs');\n            $(document.body).bind('mousemove.jqs', $.proxy(this.mousemove, this));\n            this.over = true;\n            this.currentPageX = e.pageX;\n            this.currentPageY = e.pageY;\n            this.currentEl = e.target;\n            if (!this.tooltip && this.displayTooltips) {\n                this.tooltip = new Tooltip(this.options);\n                this.tooltip.updatePosition(e.pageX, e.pageY);\n            }\n            this.updateDisplay();\n        },\n\n        mouseleave: function () {\n            $(document.body).unbind('mousemove.jqs');\n            var splist = this.splist,\n                 spcount = splist.length,\n                 needsRefresh = false,\n                 sp, i;\n            this.over = false;\n            this.currentEl = null;\n\n            if (this.tooltip) {\n                this.tooltip.remove();\n                this.tooltip = null;\n            }\n\n            for (i = 0; i < spcount; i++) {\n                sp = splist[i];\n                if (sp.clearRegionHighlight()) {\n                    needsRefresh = true;\n                }\n            }\n\n            if (needsRefresh) {\n                this.canvas.render();\n            }\n        },\n\n        mousemove: function (e) {\n            this.currentPageX = e.pageX;\n            this.currentPageY = e.pageY;\n            this.currentEl = e.target;\n            if (this.tooltip) {\n                this.tooltip.updatePosition(e.pageX, e.pageY);\n            }\n            this.updateDisplay();\n        },\n\n        updateDisplay: function () {\n            var splist = this.splist,\n                 spcount = splist.length,\n                 needsRefresh = false,\n                 offset = this.$canvas.offset(),\n                 localX = this.currentPageX - offset.left,\n                 localY = this.currentPageY - offset.top,\n                 tooltiphtml, sp, i, result, changeEvent;\n            if (!this.over) {\n                return;\n            }\n            for (i = 0; i < spcount; i++) {\n                sp = splist[i];\n                result = sp.setRegionHighlight(this.currentEl, localX, localY);\n                if (result) {\n                    needsRefresh = true;\n                }\n            }\n            if (needsRefresh) {\n                changeEvent = $.Event('sparklineRegionChange');\n                changeEvent.sparklines = this.splist;\n                this.$el.trigger(changeEvent);\n                if (this.tooltip) {\n                    tooltiphtml = '';\n                    for (i = 0; i < spcount; i++) {\n                        sp = splist[i];\n                        tooltiphtml += sp.getCurrentRegionTooltip();\n                    }\n                    this.tooltip.setContent(tooltiphtml);\n                }\n                if (!this.disableHighlight) {\n                    this.canvas.render();\n                }\n            }\n            if (result === null) {\n                this.mouseleave();\n            }\n        }\n    });\n\n\n    Tooltip = createClass({\n        sizeStyle: 'position: static !important;' +\n            'display: block !important;' +\n            'visibility: hidden !important;' +\n            'float: left !important;',\n\n        init: function (options) {\n            var tooltipClassname = options.get('tooltipClassname', 'jqstooltip'),\n                sizetipStyle = this.sizeStyle,\n                offset;\n            this.container = options.get('tooltipContainer') || document.body;\n            this.tooltipOffsetX = options.get('tooltipOffsetX', 10);\n            this.tooltipOffsetY = options.get('tooltipOffsetY', 12);\n            // remove any previous lingering tooltip\n            $('#jqssizetip').remove();\n            $('#jqstooltip').remove();\n            this.sizetip = $('<div/>', {\n                id: 'jqssizetip',\n                style: sizetipStyle,\n                'class': tooltipClassname\n            });\n            this.tooltip = $('<div/>', {\n                id: 'jqstooltip',\n                'class': tooltipClassname\n            }).appendTo(this.container);\n            // account for the container's location\n            offset = this.tooltip.offset();\n            this.offsetLeft = offset.left;\n            this.offsetTop = offset.top;\n            this.hidden = true;\n            $(window).unbind('resize.jqs scroll.jqs');\n            $(window).bind('resize.jqs scroll.jqs', $.proxy(this.updateWindowDims, this));\n            this.updateWindowDims();\n        },\n\n        updateWindowDims: function () {\n            this.scrollTop = $(window).scrollTop();\n            this.scrollLeft = $(window).scrollLeft();\n            this.scrollRight = this.scrollLeft + $(window).width();\n            this.updatePosition();\n        },\n\n        getSize: function (content) {\n            this.sizetip.html(content).appendTo(this.container);\n            this.width = this.sizetip.width() + 1;\n            this.height = this.sizetip.height();\n            this.sizetip.remove();\n        },\n\n        setContent: function (content) {\n            if (!content) {\n                this.tooltip.css('visibility', 'hidden');\n                this.hidden = true;\n                return;\n            }\n            this.getSize(content);\n            this.tooltip.html(content)\n                .css({\n                    'width': this.width,\n                    'height': this.height,\n                    'visibility': 'visible'\n                });\n            if (this.hidden) {\n                this.hidden = false;\n                this.updatePosition();\n            }\n        },\n\n        updatePosition: function (x, y) {\n            if (x === undefined) {\n                if (this.mousex === undefined) {\n                    return;\n                }\n                x = this.mousex - this.offsetLeft;\n                y = this.mousey - this.offsetTop;\n\n            } else {\n                this.mousex = x = x - this.offsetLeft;\n                this.mousey = y = y - this.offsetTop;\n            }\n            if (!this.height || !this.width || this.hidden) {\n                return;\n            }\n\n            y -= this.height + this.tooltipOffsetY;\n            x += this.tooltipOffsetX;\n\n            if (y < this.scrollTop) {\n                y = this.scrollTop;\n            }\n            if (x < this.scrollLeft) {\n                x = this.scrollLeft;\n            } else if (x + this.width > this.scrollRight) {\n                x = this.scrollRight - this.width;\n            }\n\n            this.tooltip.css({\n                'left': x,\n                'top': y\n            });\n        },\n\n        remove: function () {\n            this.tooltip.remove();\n            this.sizetip.remove();\n            this.sizetip = this.tooltip = undefined;\n            $(window).unbind('resize.jqs scroll.jqs');\n        }\n    });\n\n    initStyles = function() {\n        addCSS(defaultStyles);\n    };\n\n    $(initStyles);\n\n    pending = [];\n    $.fn.sparkline = function (userValues, userOptions) {\n        return this.each(function () {\n            var options = new $.fn.sparkline.options(this, userOptions),\n                 $this = $(this),\n                 render, i;\n            render = function () {\n                var values, width, height, tmp, mhandler, sp, vals;\n                if (userValues === 'html' || userValues === undefined) {\n                    vals = this.getAttribute(options.get('tagValuesAttribute'));\n                    if (vals === undefined || vals === null) {\n                        vals = $this.html();\n                    }\n                    values = vals.replace(/(^\\s*<!--)|(-->\\s*$)|\\s+/g, '').split(',');\n                } else {\n                    values = userValues;\n                }\n\n                width = options.get('width') === 'auto' ? values.length * options.get('defaultPixelsPerValue') : options.get('width');\n                if (options.get('height') === 'auto') {\n                    if (!options.get('composite') || !$.data(this, '_jqs_vcanvas')) {\n                        // must be a better way to get the line height\n                        tmp = document.createElement('span');\n                        tmp.innerHTML = 'a';\n                        $this.html(tmp);\n                        height = $(tmp).innerHeight() || $(tmp).height();\n                        $(tmp).remove();\n                        tmp = null;\n                    }\n                } else {\n                    height = options.get('height');\n                }\n\n                if (!options.get('disableInteraction')) {\n                    mhandler = $.data(this, '_jqs_mhandler');\n                    if (!mhandler) {\n                        mhandler = new MouseHandler(this, options);\n                        $.data(this, '_jqs_mhandler', mhandler);\n                    } else if (!options.get('composite')) {\n                        mhandler.reset();\n                    }\n                } else {\n                    mhandler = false;\n                }\n\n                if (options.get('composite') && !$.data(this, '_jqs_vcanvas')) {\n                    if (!$.data(this, '_jqs_errnotify')) {\n                        alert('Attempted to attach a composite sparkline to an element with no existing sparkline');\n                        $.data(this, '_jqs_errnotify', true);\n                    }\n                    return;\n                }\n\n                sp = new $.fn.sparkline[options.get('type')](this, values, options, width, height);\n\n                sp.render();\n\n                if (mhandler) {\n                    mhandler.registerSparkline(sp);\n                }\n            };\n            if (($(this).html() && !options.get('disableHiddenCheck') && $(this).is(':hidden')) || !$(this).parents('body').length) {\n                if (!options.get('composite') && $.data(this, '_jqs_pending')) {\n                    // remove any existing references to the element\n                    for (i = pending.length; i; i--) {\n                        if (pending[i - 1][0] == this) {\n                            pending.splice(i - 1, 1);\n                        }\n                    }\n                }\n                pending.push([this, render]);\n                $.data(this, '_jqs_pending', true);\n            } else {\n                render.call(this);\n            }\n        });\n    };\n\n    $.fn.sparkline.defaults = getDefaults();\n\n\n    $.sparkline_display_visible = function () {\n        var el, i, pl;\n        var done = [];\n        for (i = 0, pl = pending.length; i < pl; i++) {\n            el = pending[i][0];\n            if ($(el).is(':visible') && !$(el).parents().is(':hidden')) {\n                pending[i][1].call(el);\n                $.data(pending[i][0], '_jqs_pending', false);\n                done.push(i);\n            } else if (!$(el).closest('html').length && !$.data(el, '_jqs_pending')) {\n                // element has been inserted and removed from the DOM\n                // If it was not yet inserted into the dom then the .data request\n                // will return true.\n                // removing from the dom causes the data to be removed.\n                $.data(pending[i][0], '_jqs_pending', false);\n                done.push(i);\n            }\n        }\n        for (i = done.length; i; i--) {\n            pending.splice(done[i - 1], 1);\n        }\n    };\n\n\n    /**\n     * User option handler\n     */\n    $.fn.sparkline.options = createClass({\n        init: function (tag, userOptions) {\n            var extendedOptions, defaults, base, tagOptionType;\n            this.userOptions = userOptions = userOptions || {};\n            this.tag = tag;\n            this.tagValCache = {};\n            defaults = $.fn.sparkline.defaults;\n            base = defaults.common;\n            this.tagOptionsPrefix = userOptions.enableTagOptions && (userOptions.tagOptionsPrefix || base.tagOptionsPrefix);\n\n            tagOptionType = this.getTagSetting('type');\n            if (tagOptionType === UNSET_OPTION) {\n                extendedOptions = defaults[userOptions.type || base.type];\n            } else {\n                extendedOptions = defaults[tagOptionType];\n            }\n            this.mergedOptions = $.extend({}, base, extendedOptions, userOptions);\n        },\n\n\n        getTagSetting: function (key) {\n            var prefix = this.tagOptionsPrefix,\n                val, i, pairs, keyval;\n            if (prefix === false || prefix === undefined) {\n                return UNSET_OPTION;\n            }\n            if (this.tagValCache.hasOwnProperty(key)) {\n                val = this.tagValCache.key;\n            } else {\n                val = this.tag.getAttribute(prefix + key);\n                if (val === undefined || val === null) {\n                    val = UNSET_OPTION;\n                } else if (val.substr(0, 1) === '[') {\n                    val = val.substr(1, val.length - 2).split(',');\n                    for (i = val.length; i--;) {\n                        val[i] = normalizeValue(val[i].replace(/(^\\s*)|(\\s*$)/g, ''));\n                    }\n                } else if (val.substr(0, 1) === '{') {\n                    pairs = val.substr(1, val.length - 2).split(',');\n                    val = {};\n                    for (i = pairs.length; i--;) {\n                        keyval = pairs[i].split(':', 2);\n                        val[keyval[0].replace(/(^\\s*)|(\\s*$)/g, '')] = normalizeValue(keyval[1].replace(/(^\\s*)|(\\s*$)/g, ''));\n                    }\n                } else {\n                    val = normalizeValue(val);\n                }\n                this.tagValCache.key = val;\n            }\n            return val;\n        },\n\n        get: function (key, defaultval) {\n            var tagOption = this.getTagSetting(key),\n                result;\n            if (tagOption !== UNSET_OPTION) {\n                return tagOption;\n            }\n            return (result = this.mergedOptions[key]) === undefined ? defaultval : result;\n        }\n    });\n\n\n    $.fn.sparkline._base = createClass({\n        disabled: false,\n\n        init: function (el, values, options, width, height) {\n            this.el = el;\n            this.$el = $(el);\n            this.values = values;\n            this.options = options;\n            this.width = width;\n            this.height = height;\n            this.currentRegion = undefined;\n        },\n\n        /**\n         * Setup the canvas\n         */\n        initTarget: function () {\n            var interactive = !this.options.get('disableInteraction');\n            if (!(this.target = this.$el.simpledraw(this.width, this.height, this.options.get('composite'), interactive))) {\n                this.disabled = true;\n            } else {\n                this.canvasWidth = this.target.pixelWidth;\n                this.canvasHeight = this.target.pixelHeight;\n            }\n        },\n\n        /**\n         * Actually render the chart to the canvas\n         */\n        render: function () {\n            if (this.disabled) {\n                this.el.innerHTML = '';\n                return false;\n            }\n            return true;\n        },\n\n        /**\n         * Return a region id for a given x/y co-ordinate\n         */\n        getRegion: function (x, y) {\n        },\n\n        /**\n         * Highlight an item based on the moused-over x,y co-ordinate\n         */\n        setRegionHighlight: function (el, x, y) {\n            var currentRegion = this.currentRegion,\n                highlightEnabled = !this.options.get('disableHighlight'),\n                newRegion;\n            if (x > this.canvasWidth || y > this.canvasHeight || x < 0 || y < 0) {\n                return null;\n            }\n            newRegion = this.getRegion(el, x, y);\n            if (currentRegion !== newRegion) {\n                if (currentRegion !== undefined && highlightEnabled) {\n                    this.removeHighlight();\n                }\n                this.currentRegion = newRegion;\n                if (newRegion !== undefined && highlightEnabled) {\n                    this.renderHighlight();\n                }\n                return true;\n            }\n            return false;\n        },\n\n        /**\n         * Reset any currently highlighted item\n         */\n        clearRegionHighlight: function () {\n            if (this.currentRegion !== undefined) {\n                this.removeHighlight();\n                this.currentRegion = undefined;\n                return true;\n            }\n            return false;\n        },\n\n        renderHighlight: function () {\n            this.changeHighlight(true);\n        },\n\n        removeHighlight: function () {\n            this.changeHighlight(false);\n        },\n\n        changeHighlight: function (highlight)  {},\n\n        /**\n         * Fetch the HTML to display as a tooltip\n         */\n        getCurrentRegionTooltip: function () {\n            var options = this.options,\n                header = '',\n                entries = [],\n                fields, formats, formatlen, fclass, text, i,\n                showFields, showFieldsKey, newFields, fv,\n                formatter, format, fieldlen, j;\n            if (this.currentRegion === undefined) {\n                return '';\n            }\n            fields = this.getCurrentRegionFields();\n            formatter = options.get('tooltipFormatter');\n            if (formatter) {\n                return formatter(this, options, fields);\n            }\n            if (options.get('tooltipChartTitle')) {\n                header += '<div class=\"jqs jqstitle\">' + options.get('tooltipChartTitle') + '</div>\\n';\n            }\n            formats = this.options.get('tooltipFormat');\n            if (!formats) {\n                return '';\n            }\n            if (!$.isArray(formats)) {\n                formats = [formats];\n            }\n            if (!$.isArray(fields)) {\n                fields = [fields];\n            }\n            showFields = this.options.get('tooltipFormatFieldlist');\n            showFieldsKey = this.options.get('tooltipFormatFieldlistKey');\n            if (showFields && showFieldsKey) {\n                // user-selected ordering of fields\n                newFields = [];\n                for (i = fields.length; i--;) {\n                    fv = fields[i][showFieldsKey];\n                    if ((j = $.inArray(fv, showFields)) != -1) {\n                        newFields[j] = fields[i];\n                    }\n                }\n                fields = newFields;\n            }\n            formatlen = formats.length;\n            fieldlen = fields.length;\n            for (i = 0; i < formatlen; i++) {\n                format = formats[i];\n                if (typeof format === 'string') {\n                    format = new SPFormat(format);\n                }\n                fclass = format.fclass || 'jqsfield';\n                for (j = 0; j < fieldlen; j++) {\n                    if (!fields[j].isNull || !options.get('tooltipSkipNull')) {\n                        $.extend(fields[j], {\n                            prefix: options.get('tooltipPrefix'),\n                            suffix: options.get('tooltipSuffix')\n                        });\n                        text = format.render(fields[j], options.get('tooltipValueLookups'), options);\n                        entries.push('<div class=\"' + fclass + '\">' + text + '</div>');\n                    }\n                }\n            }\n            if (entries.length) {\n                return header + entries.join('\\n');\n            }\n            return '';\n        },\n\n        getCurrentRegionFields: function () {},\n\n        calcHighlightColor: function (color, options) {\n            var highlightColor = options.get('highlightColor'),\n                lighten = options.get('highlightLighten'),\n                parse, mult, rgbnew, i;\n            if (highlightColor) {\n                return highlightColor;\n            }\n            if (lighten) {\n                // extract RGB values\n                parse = /^#([0-9a-f])([0-9a-f])([0-9a-f])$/i.exec(color) || /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i.exec(color);\n                if (parse) {\n                    rgbnew = [];\n                    mult = color.length === 4 ? 16 : 1;\n                    for (i = 0; i < 3; i++) {\n                        rgbnew[i] = clipval(Math.round(parseInt(parse[i + 1], 16) * mult * lighten), 0, 255);\n                    }\n                    return 'rgb(' + rgbnew.join(',') + ')';\n                }\n\n            }\n            return color;\n        }\n\n    });\n\n    barHighlightMixin = {\n        changeHighlight: function (highlight) {\n            var currentRegion = this.currentRegion,\n                target = this.target,\n                shapeids = this.regionShapes[currentRegion],\n                newShapes;\n            // will be null if the region value was null\n            if (shapeids) {\n                newShapes = this.renderRegion(currentRegion, highlight);\n                if ($.isArray(newShapes) || $.isArray(shapeids)) {\n                    target.replaceWithShapes(shapeids, newShapes);\n                    this.regionShapes[currentRegion] = $.map(newShapes, function (newShape) {\n                        return newShape.id;\n                    });\n                } else {\n                    target.replaceWithShape(shapeids, newShapes);\n                    this.regionShapes[currentRegion] = newShapes.id;\n                }\n            }\n        },\n\n        render: function () {\n            var values = this.values,\n                target = this.target,\n                regionShapes = this.regionShapes,\n                shapes, ids, i, j;\n\n            if (!this.cls._super.render.call(this)) {\n                return;\n            }\n            for (i = values.length; i--;) {\n                shapes = this.renderRegion(i);\n                if (shapes) {\n                    if ($.isArray(shapes)) {\n                        ids = [];\n                        for (j = shapes.length; j--;) {\n                            shapes[j].append();\n                            ids.push(shapes[j].id);\n                        }\n                        regionShapes[i] = ids;\n                    } else {\n                        shapes.append();\n                        regionShapes[i] = shapes.id; // store just the shapeid\n                    }\n                } else {\n                    // null value\n                    regionShapes[i] = null;\n                }\n            }\n            target.render();\n        }\n    };\n\n    /**\n     * Line charts\n     */\n    $.fn.sparkline.line = line = createClass($.fn.sparkline._base, {\n        type: 'line',\n\n        init: function (el, values, options, width, height) {\n            line._super.init.call(this, el, values, options, width, height);\n            this.vertices = [];\n            this.regionMap = [];\n            this.xvalues = [];\n            this.yvalues = [];\n            this.yminmax = [];\n            this.hightlightSpotId = null;\n            this.lastShapeId = null;\n            this.initTarget();\n        },\n\n        getRegion: function (el, x, y) {\n            var i,\n                regionMap = this.regionMap; // maps regions to value positions\n            for (i = regionMap.length; i--;) {\n                if (regionMap[i] !== null && x >= regionMap[i][0] && x <= regionMap[i][1]) {\n                    return regionMap[i][2];\n                }\n            }\n            return undefined;\n        },\n\n        getCurrentRegionFields: function () {\n            var currentRegion = this.currentRegion;\n            return {\n                isNull: this.yvalues[currentRegion] === null,\n                x: this.xvalues[currentRegion],\n                y: this.yvalues[currentRegion],\n                color: this.options.get('lineColor'),\n                fillColor: this.options.get('fillColor'),\n                offset: currentRegion\n            };\n        },\n\n        renderHighlight: function () {\n            var currentRegion = this.currentRegion,\n                target = this.target,\n                vertex = this.vertices[currentRegion],\n                options = this.options,\n                spotRadius = options.get('spotRadius'),\n                highlightSpotColor = options.get('highlightSpotColor'),\n                highlightLineColor = options.get('highlightLineColor'),\n                highlightSpot, highlightLine;\n\n            if (!vertex) {\n                return;\n            }\n            if (spotRadius && highlightSpotColor) {\n                highlightSpot = target.drawCircle(vertex[0], vertex[1],\n                    spotRadius, undefined, highlightSpotColor);\n                this.highlightSpotId = highlightSpot.id;\n                target.insertAfterShape(this.lastShapeId, highlightSpot);\n            }\n            if (highlightLineColor) {\n                highlightLine = target.drawLine(vertex[0], this.canvasTop, vertex[0],\n                    this.canvasTop + this.canvasHeight, highlightLineColor);\n                this.highlightLineId = highlightLine.id;\n                target.insertAfterShape(this.lastShapeId, highlightLine);\n            }\n        },\n\n        removeHighlight: function () {\n            var target = this.target;\n            if (this.highlightSpotId) {\n                target.removeShapeId(this.highlightSpotId);\n                this.highlightSpotId = null;\n            }\n            if (this.highlightLineId) {\n                target.removeShapeId(this.highlightLineId);\n                this.highlightLineId = null;\n            }\n        },\n\n        scanValues: function () {\n            var values = this.values,\n                valcount = values.length,\n                xvalues = this.xvalues,\n                yvalues = this.yvalues,\n                yminmax = this.yminmax,\n                i, val, isStr, isArray, sp;\n            for (i = 0; i < valcount; i++) {\n                val = values[i];\n                isStr = typeof(values[i]) === 'string';\n                isArray = typeof(values[i]) === 'object' && values[i] instanceof Array;\n                sp = isStr && values[i].split(':');\n                if (isStr && sp.length === 2) { // x:y\n                    xvalues.push(Number(sp[0]));\n                    yvalues.push(Number(sp[1]));\n                    yminmax.push(Number(sp[1]));\n                } else if (isArray) {\n                    xvalues.push(val[0]);\n                    yvalues.push(val[1]);\n                    yminmax.push(val[1]);\n                } else {\n                    xvalues.push(i);\n                    if (values[i] === null || values[i] === 'null') {\n                        yvalues.push(null);\n                    } else {\n                        yvalues.push(Number(val));\n                        yminmax.push(Number(val));\n                    }\n                }\n            }\n            if (this.options.get('xvalues')) {\n                xvalues = this.options.get('xvalues');\n            }\n\n            this.maxy = this.maxyorg = Math.max.apply(Math, yminmax);\n            this.miny = this.minyorg = Math.min.apply(Math, yminmax);\n\n            this.maxx = Math.max.apply(Math, xvalues);\n            this.minx = Math.min.apply(Math, xvalues);\n\n            this.xvalues = xvalues;\n            this.yvalues = yvalues;\n            this.yminmax = yminmax;\n\n        },\n\n        processRangeOptions: function () {\n            var options = this.options,\n                normalRangeMin = options.get('normalRangeMin'),\n                normalRangeMax = options.get('normalRangeMax');\n\n            if (normalRangeMin !== undefined) {\n                if (normalRangeMin < this.miny) {\n                    this.miny = normalRangeMin;\n                }\n                if (normalRangeMax > this.maxy) {\n                    this.maxy = normalRangeMax;\n                }\n            }\n            if (options.get('chartRangeMin') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMin') < this.miny)) {\n                this.miny = options.get('chartRangeMin');\n            }\n            if (options.get('chartRangeMax') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMax') > this.maxy)) {\n                this.maxy = options.get('chartRangeMax');\n            }\n            if (options.get('chartRangeMinX') !== undefined && (options.get('chartRangeClipX') || options.get('chartRangeMinX') < this.minx)) {\n                this.minx = options.get('chartRangeMinX');\n            }\n            if (options.get('chartRangeMaxX') !== undefined && (options.get('chartRangeClipX') || options.get('chartRangeMaxX') > this.maxx)) {\n                this.maxx = options.get('chartRangeMaxX');\n            }\n\n        },\n\n        drawNormalRange: function (canvasLeft, canvasTop, canvasHeight, canvasWidth, rangey) {\n            var normalRangeMin = this.options.get('normalRangeMin'),\n                normalRangeMax = this.options.get('normalRangeMax'),\n                ytop = canvasTop + Math.round(canvasHeight - (canvasHeight * ((normalRangeMax - this.miny) / rangey))),\n                height = Math.round((canvasHeight * (normalRangeMax - normalRangeMin)) / rangey);\n            this.target.drawRect(canvasLeft, ytop, canvasWidth, height, undefined, this.options.get('normalRangeColor')).append();\n        },\n\n        render: function () {\n            var options = this.options,\n                target = this.target,\n                canvasWidth = this.canvasWidth,\n                canvasHeight = this.canvasHeight,\n                vertices = this.vertices,\n                spotRadius = options.get('spotRadius'),\n                regionMap = this.regionMap,\n                rangex, rangey, yvallast,\n                canvasTop, canvasLeft,\n                vertex, path, paths, x, y, xnext, xpos, xposnext,\n                last, next, yvalcount, lineShapes, fillShapes, plen,\n                valueSpots, hlSpotsEnabled, color, xvalues, yvalues, i;\n\n            if (!line._super.render.call(this)) {\n                return;\n            }\n\n            this.scanValues();\n            this.processRangeOptions();\n\n            xvalues = this.xvalues;\n            yvalues = this.yvalues;\n\n            if (!this.yminmax.length || this.yvalues.length < 2) {\n                // empty or all null valuess\n                return;\n            }\n\n            canvasTop = canvasLeft = 0;\n\n            rangex = this.maxx - this.minx === 0 ? 1 : this.maxx - this.minx;\n            rangey = this.maxy - this.miny === 0 ? 1 : this.maxy - this.miny;\n            yvallast = this.yvalues.length - 1;\n\n            if (spotRadius && (canvasWidth < (spotRadius * 4) || canvasHeight < (spotRadius * 4))) {\n                spotRadius = 0;\n            }\n            if (spotRadius) {\n                // adjust the canvas size as required so that spots will fit\n                hlSpotsEnabled = options.get('highlightSpotColor') &&  !options.get('disableInteraction');\n                if (hlSpotsEnabled || options.get('minSpotColor') || (options.get('spotColor') && yvalues[yvallast] === this.miny)) {\n                    canvasHeight -= Math.ceil(spotRadius);\n                }\n                if (hlSpotsEnabled || options.get('maxSpotColor') || (options.get('spotColor') && yvalues[yvallast] === this.maxy)) {\n                    canvasHeight -= Math.ceil(spotRadius);\n                    canvasTop += Math.ceil(spotRadius);\n                }\n                if (hlSpotsEnabled ||\n                     ((options.get('minSpotColor') || options.get('maxSpotColor')) && (yvalues[0] === this.miny || yvalues[0] === this.maxy))) {\n                    canvasLeft += Math.ceil(spotRadius);\n                    canvasWidth -= Math.ceil(spotRadius);\n                }\n                if (hlSpotsEnabled || options.get('spotColor') ||\n                    (options.get('minSpotColor') || options.get('maxSpotColor') &&\n                        (yvalues[yvallast] === this.miny || yvalues[yvallast] === this.maxy))) {\n                    canvasWidth -= Math.ceil(spotRadius);\n                }\n            }\n\n\n            canvasHeight--;\n\n            if (options.get('normalRangeMin') !== undefined && !options.get('drawNormalOnTop')) {\n                this.drawNormalRange(canvasLeft, canvasTop, canvasHeight, canvasWidth, rangey);\n            }\n\n            path = [];\n            paths = [path];\n            last = next = null;\n            yvalcount = yvalues.length;\n            for (i = 0; i < yvalcount; i++) {\n                x = xvalues[i];\n                xnext = xvalues[i + 1];\n                y = yvalues[i];\n                xpos = canvasLeft + Math.round((x - this.minx) * (canvasWidth / rangex));\n                xposnext = i < yvalcount - 1 ? canvasLeft + Math.round((xnext - this.minx) * (canvasWidth / rangex)) : canvasWidth;\n                next = xpos + ((xposnext - xpos) / 2);\n                regionMap[i] = [last || 0, next, i];\n                last = next;\n                if (y === null) {\n                    if (i) {\n                        if (yvalues[i - 1] !== null) {\n                            path = [];\n                            paths.push(path);\n                        }\n                        vertices.push(null);\n                    }\n                } else {\n                    if (y < this.miny) {\n                        y = this.miny;\n                    }\n                    if (y > this.maxy) {\n                        y = this.maxy;\n                    }\n                    if (!path.length) {\n                        // previous value was null\n                        path.push([xpos, canvasTop + canvasHeight]);\n                    }\n                    vertex = [xpos, canvasTop + Math.round(canvasHeight - (canvasHeight * ((y - this.miny) / rangey)))];\n                    path.push(vertex);\n                    vertices.push(vertex);\n                }\n            }\n\n            lineShapes = [];\n            fillShapes = [];\n            plen = paths.length;\n            for (i = 0; i < plen; i++) {\n                path = paths[i];\n                if (path.length) {\n                    if (options.get('fillColor')) {\n                        path.push([path[path.length - 1][0], (canvasTop + canvasHeight)]);\n                        fillShapes.push(path.slice(0));\n                        path.pop();\n                    }\n                    // if there's only a single point in this path, then we want to display it\n                    // as a vertical line which means we keep path[0]  as is\n                    if (path.length > 2) {\n                        // else we want the first value\n                        path[0] = [path[0][0], path[1][1]];\n                    }\n                    lineShapes.push(path);\n                }\n            }\n\n            // draw the fill first, then optionally the normal range, then the line on top of that\n            plen = fillShapes.length;\n            for (i = 0; i < plen; i++) {\n                target.drawShape(fillShapes[i],\n                    options.get('fillColor'), options.get('fillColor')).append();\n            }\n\n            if (options.get('normalRangeMin') !== undefined && options.get('drawNormalOnTop')) {\n                this.drawNormalRange(canvasLeft, canvasTop, canvasHeight, canvasWidth, rangey);\n            }\n\n            plen = lineShapes.length;\n            for (i = 0; i < plen; i++) {\n                target.drawShape(lineShapes[i], options.get('lineColor'), undefined,\n                    options.get('lineWidth')).append();\n            }\n\n            if (spotRadius && options.get('valueSpots')) {\n                valueSpots = options.get('valueSpots');\n                if (valueSpots.get === undefined) {\n                    valueSpots = new RangeMap(valueSpots);\n                }\n                for (i = 0; i < yvalcount; i++) {\n                    color = valueSpots.get(yvalues[i]);\n                    if (color) {\n                        target.drawCircle(canvasLeft + Math.round((xvalues[i] - this.minx) * (canvasWidth / rangex)),\n                            canvasTop + Math.round(canvasHeight - (canvasHeight * ((yvalues[i] - this.miny) / rangey))),\n                            spotRadius, undefined,\n                            color).append();\n                    }\n                }\n\n            }\n            if (spotRadius && options.get('spotColor') && yvalues[yvallast] !== null) {\n                target.drawCircle(canvasLeft + Math.round((xvalues[xvalues.length - 1] - this.minx) * (canvasWidth / rangex)),\n                    canvasTop + Math.round(canvasHeight - (canvasHeight * ((yvalues[yvallast] - this.miny) / rangey))),\n                    spotRadius, undefined,\n                    options.get('spotColor')).append();\n            }\n            if (this.maxy !== this.minyorg) {\n                if (spotRadius && options.get('minSpotColor')) {\n                    x = xvalues[$.inArray(this.minyorg, yvalues)];\n                    target.drawCircle(canvasLeft + Math.round((x - this.minx) * (canvasWidth / rangex)),\n                        canvasTop + Math.round(canvasHeight - (canvasHeight * ((this.minyorg - this.miny) / rangey))),\n                        spotRadius, undefined,\n                        options.get('minSpotColor')).append();\n                }\n                if (spotRadius && options.get('maxSpotColor')) {\n                    x = xvalues[$.inArray(this.maxyorg, yvalues)];\n                    target.drawCircle(canvasLeft + Math.round((x - this.minx) * (canvasWidth / rangex)),\n                        canvasTop + Math.round(canvasHeight - (canvasHeight * ((this.maxyorg - this.miny) / rangey))),\n                        spotRadius, undefined,\n                        options.get('maxSpotColor')).append();\n                }\n            }\n\n            this.lastShapeId = target.getLastShapeId();\n            this.canvasTop = canvasTop;\n            target.render();\n        }\n    });\n\n    /**\n     * Bar charts\n     */\n    $.fn.sparkline.bar = bar = createClass($.fn.sparkline._base, barHighlightMixin, {\n        type: 'bar',\n\n        init: function (el, values, options, width, height) {\n            var barWidth = parseInt(options.get('barWidth'), 10),\n                barSpacing = parseInt(options.get('barSpacing'), 10),\n                chartRangeMin = options.get('chartRangeMin'),\n                chartRangeMax = options.get('chartRangeMax'),\n                chartRangeClip = options.get('chartRangeClip'),\n                stackMin = Infinity,\n                stackMax = -Infinity,\n                isStackString, groupMin, groupMax, stackRanges,\n                numValues, i, vlen, range, zeroAxis, xaxisOffset, min, max, clipMin, clipMax,\n                stacked, vlist, j, slen, svals, val, yoffset, yMaxCalc, canvasHeightEf;\n            bar._super.init.call(this, el, values, options, width, height);\n\n            // scan values to determine whether to stack bars\n            for (i = 0, vlen = values.length; i < vlen; i++) {\n                val = values[i];\n                isStackString = typeof(val) === 'string' && val.indexOf(':') > -1;\n                if (isStackString || $.isArray(val)) {\n                    stacked = true;\n                    if (isStackString) {\n                        val = values[i] = normalizeValues(val.split(':'));\n                    }\n                    val = remove(val, null); // min/max will treat null as zero\n                    groupMin = Math.min.apply(Math, val);\n                    groupMax = Math.max.apply(Math, val);\n                    if (groupMin < stackMin) {\n                        stackMin = groupMin;\n                    }\n                    if (groupMax > stackMax) {\n                        stackMax = groupMax;\n                    }\n                }\n            }\n\n            this.stacked = stacked;\n            this.regionShapes = {};\n            this.barWidth = barWidth;\n            this.barSpacing = barSpacing;\n            this.totalBarWidth = barWidth + barSpacing;\n            this.width = width = (values.length * barWidth) + ((values.length - 1) * barSpacing);\n\n            this.initTarget();\n\n            if (chartRangeClip) {\n                clipMin = chartRangeMin === undefined ? -Infinity : chartRangeMin;\n                clipMax = chartRangeMax === undefined ? Infinity : chartRangeMax;\n            }\n\n            numValues = [];\n            stackRanges = stacked ? [] : numValues;\n            var stackTotals = [];\n            var stackRangesNeg = [];\n            for (i = 0, vlen = values.length; i < vlen; i++) {\n                if (stacked) {\n                    vlist = values[i];\n                    values[i] = svals = [];\n                    stackTotals[i] = 0;\n                    stackRanges[i] = stackRangesNeg[i] = 0;\n                    for (j = 0, slen = vlist.length; j < slen; j++) {\n                        val = svals[j] = chartRangeClip ? clipval(vlist[j], clipMin, clipMax) : vlist[j];\n                        if (val !== null) {\n                            if (val > 0) {\n                                stackTotals[i] += val;\n                            }\n                            if (stackMin < 0 && stackMax > 0) {\n                                if (val < 0) {\n                                    stackRangesNeg[i] += Math.abs(val);\n                                } else {\n                                    stackRanges[i] += val;\n                                }\n                            } else {\n                                stackRanges[i] += Math.abs(val - (val < 0 ? stackMax : stackMin));\n                            }\n                            numValues.push(val);\n                        }\n                    }\n                } else {\n                    val = chartRangeClip ? clipval(values[i], clipMin, clipMax) : values[i];\n                    val = values[i] = normalizeValue(val);\n                    if (val !== null) {\n                        numValues.push(val);\n                    }\n                }\n            }\n            this.max = max = Math.max.apply(Math, numValues);\n            this.min = min = Math.min.apply(Math, numValues);\n            this.stackMax = stackMax = stacked ? Math.max.apply(Math, stackTotals) : max;\n            this.stackMin = stackMin = stacked ? Math.min.apply(Math, numValues) : min;\n\n            if (options.get('chartRangeMin') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMin') < min)) {\n                min = options.get('chartRangeMin');\n            }\n            if (options.get('chartRangeMax') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMax') > max)) {\n                max = options.get('chartRangeMax');\n            }\n\n            this.zeroAxis = zeroAxis = options.get('zeroAxis', true);\n            if (min <= 0 && max >= 0 && zeroAxis) {\n                xaxisOffset = 0;\n            } else if (zeroAxis == false) {\n                xaxisOffset = min;\n            } else if (min > 0) {\n                xaxisOffset = min;\n            } else {\n                xaxisOffset = max;\n            }\n            this.xaxisOffset = xaxisOffset;\n\n            range = stacked ? (Math.max.apply(Math, stackRanges) + Math.max.apply(Math, stackRangesNeg)) : max - min;\n\n            // as we plot zero/min values a single pixel line, we add a pixel to all other\n            // values - Reduce the effective canvas size to suit\n            this.canvasHeightEf = (zeroAxis && min < 0) ? this.canvasHeight - 2 : this.canvasHeight - 1;\n\n            if (min < xaxisOffset) {\n                yMaxCalc = (stacked && max >= 0) ? stackMax : max;\n                yoffset = (yMaxCalc - xaxisOffset) / range * this.canvasHeight;\n                if (yoffset !== Math.ceil(yoffset)) {\n                    this.canvasHeightEf -= 2;\n                    yoffset = Math.ceil(yoffset);\n                }\n            } else {\n                yoffset = this.canvasHeight;\n            }\n            this.yoffset = yoffset;\n\n            if ($.isArray(options.get('colorMap'))) {\n                this.colorMapByIndex = options.get('colorMap');\n                this.colorMapByValue = null;\n            } else {\n                this.colorMapByIndex = null;\n                this.colorMapByValue = options.get('colorMap');\n                if (this.colorMapByValue && this.colorMapByValue.get === undefined) {\n                    this.colorMapByValue = new RangeMap(this.colorMapByValue);\n                }\n            }\n\n            this.range = range;\n        },\n\n        getRegion: function (el, x, y) {\n            var result = Math.floor(x / this.totalBarWidth);\n            return (result < 0 || result >= this.values.length) ? undefined : result;\n        },\n\n        getCurrentRegionFields: function () {\n            var currentRegion = this.currentRegion,\n                values = ensureArray(this.values[currentRegion]),\n                result = [],\n                value, i;\n            for (i = values.length; i--;) {\n                value = values[i];\n                result.push({\n                    isNull: value === null,\n                    value: value,\n                    color: this.calcColor(i, value, currentRegion),\n                    offset: currentRegion\n                });\n            }\n            return result;\n        },\n\n        calcColor: function (stacknum, value, valuenum) {\n            var colorMapByIndex = this.colorMapByIndex,\n                colorMapByValue = this.colorMapByValue,\n                options = this.options,\n                color, newColor;\n            if (this.stacked) {\n                color = options.get('stackedBarColor');\n            } else {\n                color = (value < 0) ? options.get('negBarColor') : options.get('barColor');\n            }\n            if (value === 0 && options.get('zeroColor') !== undefined) {\n                color = options.get('zeroColor');\n            }\n            if (colorMapByValue && (newColor = colorMapByValue.get(value))) {\n                color = newColor;\n            } else if (colorMapByIndex && colorMapByIndex.length > valuenum) {\n                color = colorMapByIndex[valuenum];\n            }\n            return $.isArray(color) ? color[stacknum % color.length] : color;\n        },\n\n        /**\n         * Render bar(s) for a region\n         */\n        renderRegion: function (valuenum, highlight) {\n            var vals = this.values[valuenum],\n                options = this.options,\n                xaxisOffset = this.xaxisOffset,\n                result = [],\n                range = this.range,\n                stacked = this.stacked,\n                target = this.target,\n                x = valuenum * this.totalBarWidth,\n                canvasHeightEf = this.canvasHeightEf,\n                yoffset = this.yoffset,\n                y, height, color, isNull, yoffsetNeg, i, valcount, val, minPlotted, allMin;\n\n            vals = $.isArray(vals) ? vals : [vals];\n            valcount = vals.length;\n            val = vals[0];\n            isNull = all(null, vals);\n            allMin = all(xaxisOffset, vals, true);\n\n            if (isNull) {\n                if (options.get('nullColor')) {\n                    color = highlight ? options.get('nullColor') : this.calcHighlightColor(options.get('nullColor'), options);\n                    y = (yoffset > 0) ? yoffset - 1 : yoffset;\n                    return target.drawRect(x, y, this.barWidth - 1, 0, color, color);\n                } else {\n                    return undefined;\n                }\n            }\n            yoffsetNeg = yoffset;\n            for (i = 0; i < valcount; i++) {\n                val = vals[i];\n\n                if (stacked && val === xaxisOffset) {\n                    if (!allMin || minPlotted) {\n                        continue;\n                    }\n                    minPlotted = true;\n                }\n\n                if (range > 0) {\n                    height = Math.floor(canvasHeightEf * ((Math.abs(val - xaxisOffset) / range))) + 1;\n                } else {\n                    height = 1;\n                }\n                if (val < xaxisOffset || (val === xaxisOffset && yoffset === 0)) {\n                    y = yoffsetNeg;\n                    yoffsetNeg += height;\n                } else {\n                    y = yoffset - height;\n                    yoffset -= height;\n                }\n                color = this.calcColor(i, val, valuenum);\n                if (highlight) {\n                    color = this.calcHighlightColor(color, options);\n                }\n                result.push(target.drawRect(x, y, this.barWidth - 1, height - 1, color, color));\n            }\n            if (result.length === 1) {\n                return result[0];\n            }\n            return result;\n        }\n    });\n\n    /**\n     * Tristate charts\n     */\n    $.fn.sparkline.tristate = tristate = createClass($.fn.sparkline._base, barHighlightMixin, {\n        type: 'tristate',\n\n        init: function (el, values, options, width, height) {\n            var barWidth = parseInt(options.get('barWidth'), 10),\n                barSpacing = parseInt(options.get('barSpacing'), 10);\n            tristate._super.init.call(this, el, values, options, width, height);\n\n            this.regionShapes = {};\n            this.barWidth = barWidth;\n            this.barSpacing = barSpacing;\n            this.totalBarWidth = barWidth + barSpacing;\n            this.values = $.map(values, Number);\n            this.width = width = (values.length * barWidth) + ((values.length - 1) * barSpacing);\n\n            if ($.isArray(options.get('colorMap'))) {\n                this.colorMapByIndex = options.get('colorMap');\n                this.colorMapByValue = null;\n            } else {\n                this.colorMapByIndex = null;\n                this.colorMapByValue = options.get('colorMap');\n                if (this.colorMapByValue && this.colorMapByValue.get === undefined) {\n                    this.colorMapByValue = new RangeMap(this.colorMapByValue);\n                }\n            }\n            this.initTarget();\n        },\n\n        getRegion: function (el, x, y) {\n            return Math.floor(x / this.totalBarWidth);\n        },\n\n        getCurrentRegionFields: function () {\n            var currentRegion = this.currentRegion;\n            return {\n                isNull: this.values[currentRegion] === undefined,\n                value: this.values[currentRegion],\n                color: this.calcColor(this.values[currentRegion], currentRegion),\n                offset: currentRegion\n            };\n        },\n\n        calcColor: function (value, valuenum) {\n            var values = this.values,\n                options = this.options,\n                colorMapByIndex = this.colorMapByIndex,\n                colorMapByValue = this.colorMapByValue,\n                color, newColor;\n\n            if (colorMapByValue && (newColor = colorMapByValue.get(value))) {\n                color = newColor;\n            } else if (colorMapByIndex && colorMapByIndex.length > valuenum) {\n                color = colorMapByIndex[valuenum];\n            } else if (values[valuenum] < 0) {\n                color = options.get('negBarColor');\n            } else if (values[valuenum] > 0) {\n                color = options.get('posBarColor');\n            } else {\n                color = options.get('zeroBarColor');\n            }\n            return color;\n        },\n\n        renderRegion: function (valuenum, highlight) {\n            var values = this.values,\n                options = this.options,\n                target = this.target,\n                canvasHeight, height, halfHeight,\n                x, y, color;\n\n            canvasHeight = target.pixelHeight;\n            halfHeight = Math.round(canvasHeight / 2);\n\n            x = valuenum * this.totalBarWidth;\n            if (values[valuenum] < 0) {\n                y = halfHeight;\n                height = halfHeight - 1;\n            } else if (values[valuenum] > 0) {\n                y = 0;\n                height = halfHeight - 1;\n            } else {\n                y = halfHeight - 1;\n                height = 2;\n            }\n            color = this.calcColor(values[valuenum], valuenum);\n            if (color === null) {\n                return;\n            }\n            if (highlight) {\n                color = this.calcHighlightColor(color, options);\n            }\n            return target.drawRect(x, y, this.barWidth - 1, height - 1, color, color);\n        }\n    });\n\n    /**\n     * Discrete charts\n     */\n    $.fn.sparkline.discrete = discrete = createClass($.fn.sparkline._base, barHighlightMixin, {\n        type: 'discrete',\n\n        init: function (el, values, options, width, height) {\n            discrete._super.init.call(this, el, values, options, width, height);\n\n            this.regionShapes = {};\n            this.values = values = $.map(values, Number);\n            this.min = Math.min.apply(Math, values);\n            this.max = Math.max.apply(Math, values);\n            this.range = this.max - this.min;\n            this.width = width = options.get('width') === 'auto' ? values.length * 2 : this.width;\n            this.interval = Math.floor(width / values.length);\n            this.itemWidth = width / values.length;\n            if (options.get('chartRangeMin') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMin') < this.min)) {\n                this.min = options.get('chartRangeMin');\n            }\n            if (options.get('chartRangeMax') !== undefined && (options.get('chartRangeClip') || options.get('chartRangeMax') > this.max)) {\n                this.max = options.get('chartRangeMax');\n            }\n            this.initTarget();\n            if (this.target) {\n                this.lineHeight = options.get('lineHeight') === 'auto' ? Math.round(this.canvasHeight * 0.3) : options.get('lineHeight');\n            }\n        },\n\n        getRegion: function (el, x, y) {\n            return Math.floor(x / this.itemWidth);\n        },\n\n        getCurrentRegionFields: function () {\n            var currentRegion = this.currentRegion;\n            return {\n                isNull: this.values[currentRegion] === undefined,\n                value: this.values[currentRegion],\n                offset: currentRegion\n            };\n        },\n\n        renderRegion: function (valuenum, highlight) {\n            var values = this.values,\n                options = this.options,\n                min = this.min,\n                max = this.max,\n                range = this.range,\n                interval = this.interval,\n                target = this.target,\n                canvasHeight = this.canvasHeight,\n                lineHeight = this.lineHeight,\n                pheight = canvasHeight - lineHeight,\n                ytop, val, color, x;\n\n            val = clipval(values[valuenum], min, max);\n            x = valuenum * interval;\n            ytop = Math.round(pheight - pheight * ((val - min) / range));\n            color = (options.get('thresholdColor') && val < options.get('thresholdValue')) ? options.get('thresholdColor') : options.get('lineColor');\n            if (highlight) {\n                color = this.calcHighlightColor(color, options);\n            }\n            return target.drawLine(x, ytop, x, ytop + lineHeight, color);\n        }\n    });\n\n    /**\n     * Bullet charts\n     */\n    $.fn.sparkline.bullet = bullet = createClass($.fn.sparkline._base, {\n        type: 'bullet',\n\n        init: function (el, values, options, width, height) {\n            var min, max, vals;\n            bullet._super.init.call(this, el, values, options, width, height);\n\n            // values: target, performance, range1, range2, range3\n            this.values = values = normalizeValues(values);\n            // target or performance could be null\n            vals = values.slice();\n            vals[0] = vals[0] === null ? vals[2] : vals[0];\n            vals[1] = values[1] === null ? vals[2] : vals[1];\n            min = Math.min.apply(Math, values);\n            max = Math.max.apply(Math, values);\n            if (options.get('base') === undefined) {\n                min = min < 0 ? min : 0;\n            } else {\n                min = options.get('base');\n            }\n            this.min = min;\n            this.max = max;\n            this.range = max - min;\n            this.shapes = {};\n            this.valueShapes = {};\n            this.regiondata = {};\n            this.width = width = options.get('width') === 'auto' ? '4.0em' : width;\n            this.target = this.$el.simpledraw(width, height, options.get('composite'));\n            if (!values.length) {\n                this.disabled = true;\n            }\n            this.initTarget();\n        },\n\n        getRegion: function (el, x, y) {\n            var shapeid = this.target.getShapeAt(el, x, y);\n            return (shapeid !== undefined && this.shapes[shapeid] !== undefined) ? this.shapes[shapeid] : undefined;\n        },\n\n        getCurrentRegionFields: function () {\n            var currentRegion = this.currentRegion;\n            return {\n                fieldkey: currentRegion.substr(0, 1),\n                value: this.values[currentRegion.substr(1)],\n                region: currentRegion\n            };\n        },\n\n        changeHighlight: function (highlight) {\n            var currentRegion = this.currentRegion,\n                shapeid = this.valueShapes[currentRegion],\n                shape;\n            delete this.shapes[shapeid];\n            switch (currentRegion.substr(0, 1)) {\n                case 'r':\n                    shape = this.renderRange(currentRegion.substr(1), highlight);\n                    break;\n                case 'p':\n                    shape = this.renderPerformance(highlight);\n                    break;\n                case 't':\n                    shape = this.renderTarget(highlight);\n                    break;\n            }\n            this.valueShapes[currentRegion] = shape.id;\n            this.shapes[shape.id] = currentRegion;\n            this.target.replaceWithShape(shapeid, shape);\n        },\n\n        renderRange: function (rn, highlight) {\n            var rangeval = this.values[rn],\n                rangewidth = Math.round(this.canvasWidth * ((rangeval - this.min) / this.range)),\n                color = this.options.get('rangeColors')[rn - 2];\n            if (highlight) {\n                color = this.calcHighlightColor(color, this.options);\n            }\n            return this.target.drawRect(0, 0, rangewidth - 1, this.canvasHeight - 1, color, color);\n        },\n\n        renderPerformance: function (highlight) {\n            var perfval = this.values[1],\n                perfwidth = Math.round(this.canvasWidth * ((perfval - this.min) / this.range)),\n                color = this.options.get('performanceColor');\n            if (highlight) {\n                color = this.calcHighlightColor(color, this.options);\n            }\n            return this.target.drawRect(0, Math.round(this.canvasHeight * 0.3), perfwidth - 1,\n                Math.round(this.canvasHeight * 0.4) - 1, color, color);\n        },\n\n        renderTarget: function (highlight) {\n            var targetval = this.values[0],\n                x = Math.round(this.canvasWidth * ((targetval - this.min) / this.range) - (this.options.get('targetWidth') / 2)),\n                targettop = Math.round(this.canvasHeight * 0.10),\n                targetheight = this.canvasHeight - (targettop * 2),\n                color = this.options.get('targetColor');\n            if (highlight) {\n                color = this.calcHighlightColor(color, this.options);\n            }\n            return this.target.drawRect(x, targettop, this.options.get('targetWidth') - 1, targetheight - 1, color, color);\n        },\n\n        render: function () {\n            var vlen = this.values.length,\n                target = this.target,\n                i, shape;\n            if (!bullet._super.render.call(this)) {\n                return;\n            }\n            for (i = 2; i < vlen; i++) {\n                shape = this.renderRange(i).append();\n                this.shapes[shape.id] = 'r' + i;\n                this.valueShapes['r' + i] = shape.id;\n            }\n            if (this.values[1] !== null) {\n                shape = this.renderPerformance().append();\n                this.shapes[shape.id] = 'p1';\n                this.valueShapes.p1 = shape.id;\n            }\n            if (this.values[0] !== null) {\n                shape = this.renderTarget().append();\n                this.shapes[shape.id] = 't0';\n                this.valueShapes.t0 = shape.id;\n            }\n            target.render();\n        }\n    });\n\n    /**\n     * Pie charts\n     */\n    $.fn.sparkline.pie = pie = createClass($.fn.sparkline._base, {\n        type: 'pie',\n\n        init: function (el, values, options, width, height) {\n            var total = 0, i;\n\n            pie._super.init.call(this, el, values, options, width, height);\n\n            this.shapes = {}; // map shape ids to value offsets\n            this.valueShapes = {}; // maps value offsets to shape ids\n            this.values = values = $.map(values, Number);\n\n            if (options.get('width') === 'auto') {\n                this.width = this.height;\n            }\n\n            if (values.length > 0) {\n                for (i = values.length; i--;) {\n                    total += values[i];\n                }\n            }\n            this.total = total;\n            this.initTarget();\n            this.radius = Math.floor(Math.min(this.canvasWidth, this.canvasHeight) / 2);\n        },\n\n        getRegion: function (el, x, y) {\n            var shapeid = this.target.getShapeAt(el, x, y);\n            return (shapeid !== undefined && this.shapes[shapeid] !== undefined) ? this.shapes[shapeid] : undefined;\n        },\n\n        getCurrentRegionFields: function () {\n            var currentRegion = this.currentRegion;\n            return {\n                isNull: this.values[currentRegion] === undefined,\n                value: this.values[currentRegion],\n                percent: this.values[currentRegion] / this.total * 100,\n                color: this.options.get('sliceColors')[currentRegion % this.options.get('sliceColors').length],\n                offset: currentRegion\n            };\n        },\n\n        changeHighlight: function (highlight) {\n            var currentRegion = this.currentRegion,\n                 newslice = this.renderSlice(currentRegion, highlight),\n                 shapeid = this.valueShapes[currentRegion];\n            delete this.shapes[shapeid];\n            this.target.replaceWithShape(shapeid, newslice);\n            this.valueShapes[currentRegion] = newslice.id;\n            this.shapes[newslice.id] = currentRegion;\n        },\n\n        renderSlice: function (valuenum, highlight) {\n            var target = this.target,\n                options = this.options,\n                radius = this.radius,\n                borderWidth = options.get('borderWidth'),\n                offset = options.get('offset'),\n                circle = 2 * Math.PI,\n                values = this.values,\n                total = this.total,\n                next = offset ? (2*Math.PI)*(offset/360) : 0,\n                start, end, i, vlen, color;\n\n            vlen = values.length;\n            for (i = 0; i < vlen; i++) {\n                start = next;\n                end = next;\n                if (total > 0) {  // avoid divide by zero\n                    end = next + (circle * (values[i] / total));\n                }\n                if (valuenum === i) {\n                    color = options.get('sliceColors')[i % options.get('sliceColors').length];\n                    if (highlight) {\n                        color = this.calcHighlightColor(color, options);\n                    }\n\n                    return target.drawPieSlice(radius, radius, radius - borderWidth, start, end, undefined, color);\n                }\n                next = end;\n            }\n        },\n\n        render: function () {\n            var target = this.target,\n                values = this.values,\n                options = this.options,\n                radius = this.radius,\n                borderWidth = options.get('borderWidth'),\n                shape, i;\n\n            if (!pie._super.render.call(this)) {\n                return;\n            }\n            if (borderWidth) {\n                target.drawCircle(radius, radius, Math.floor(radius - (borderWidth / 2)),\n                    options.get('borderColor'), undefined, borderWidth).append();\n            }\n            for (i = values.length; i--;) {\n                if (values[i]) { // don't render zero values\n                    shape = this.renderSlice(i).append();\n                    this.valueShapes[i] = shape.id; // store just the shapeid\n                    this.shapes[shape.id] = i;\n                }\n            }\n            target.render();\n        }\n    });\n\n    /**\n     * Box plots\n     */\n    $.fn.sparkline.box = box = createClass($.fn.sparkline._base, {\n        type: 'box',\n\n        init: function (el, values, options, width, height) {\n            box._super.init.call(this, el, values, options, width, height);\n            this.values = $.map(values, Number);\n            this.width = options.get('width') === 'auto' ? '4.0em' : width;\n            this.initTarget();\n            if (!this.values.length) {\n                this.disabled = 1;\n            }\n        },\n\n        /**\n         * Simulate a single region\n         */\n        getRegion: function () {\n            return 1;\n        },\n\n        getCurrentRegionFields: function () {\n            var result = [\n                { field: 'lq', value: this.quartiles[0] },\n                { field: 'med', value: this.quartiles[1] },\n                { field: 'uq', value: this.quartiles[2] }\n            ];\n            if (this.loutlier !== undefined) {\n                result.push({ field: 'lo', value: this.loutlier});\n            }\n            if (this.routlier !== undefined) {\n                result.push({ field: 'ro', value: this.routlier});\n            }\n            if (this.lwhisker !== undefined) {\n                result.push({ field: 'lw', value: this.lwhisker});\n            }\n            if (this.rwhisker !== undefined) {\n                result.push({ field: 'rw', value: this.rwhisker});\n            }\n            return result;\n        },\n\n        render: function () {\n            var target = this.target,\n                values = this.values,\n                vlen = values.length,\n                options = this.options,\n                canvasWidth = this.canvasWidth,\n                canvasHeight = this.canvasHeight,\n                minValue = options.get('chartRangeMin') === undefined ? Math.min.apply(Math, values) : options.get('chartRangeMin'),\n                maxValue = options.get('chartRangeMax') === undefined ? Math.max.apply(Math, values) : options.get('chartRangeMax'),\n                canvasLeft = 0,\n                lwhisker, loutlier, iqr, q1, q2, q3, rwhisker, routlier, i,\n                size, unitSize;\n\n            if (!box._super.render.call(this)) {\n                return;\n            }\n\n            if (options.get('raw')) {\n                if (options.get('showOutliers') && values.length > 5) {\n                    loutlier = values[0];\n                    lwhisker = values[1];\n                    q1 = values[2];\n                    q2 = values[3];\n                    q3 = values[4];\n                    rwhisker = values[5];\n                    routlier = values[6];\n                } else {\n                    lwhisker = values[0];\n                    q1 = values[1];\n                    q2 = values[2];\n                    q3 = values[3];\n                    rwhisker = values[4];\n                }\n            } else {\n                values.sort(function (a, b) { return a - b; });\n                q1 = quartile(values, 1);\n                q2 = quartile(values, 2);\n                q3 = quartile(values, 3);\n                iqr = q3 - q1;\n                if (options.get('showOutliers')) {\n                    lwhisker = rwhisker = undefined;\n                    for (i = 0; i < vlen; i++) {\n                        if (lwhisker === undefined && values[i] > q1 - (iqr * options.get('outlierIQR'))) {\n                            lwhisker = values[i];\n                        }\n                        if (values[i] < q3 + (iqr * options.get('outlierIQR'))) {\n                            rwhisker = values[i];\n                        }\n                    }\n                    loutlier = values[0];\n                    routlier = values[vlen - 1];\n                } else {\n                    lwhisker = values[0];\n                    rwhisker = values[vlen - 1];\n                }\n            }\n            this.quartiles = [q1, q2, q3];\n            this.lwhisker = lwhisker;\n            this.rwhisker = rwhisker;\n            this.loutlier = loutlier;\n            this.routlier = routlier;\n\n            unitSize = canvasWidth / (maxValue - minValue + 1);\n            if (options.get('showOutliers')) {\n                canvasLeft = Math.ceil(options.get('spotRadius'));\n                canvasWidth -= 2 * Math.ceil(options.get('spotRadius'));\n                unitSize = canvasWidth / (maxValue - minValue + 1);\n                if (loutlier < lwhisker) {\n                    target.drawCircle((loutlier - minValue) * unitSize + canvasLeft,\n                        canvasHeight / 2,\n                        options.get('spotRadius'),\n                        options.get('outlierLineColor'),\n                        options.get('outlierFillColor')).append();\n                }\n                if (routlier > rwhisker) {\n                    target.drawCircle((routlier - minValue) * unitSize + canvasLeft,\n                        canvasHeight / 2,\n                        options.get('spotRadius'),\n                        options.get('outlierLineColor'),\n                        options.get('outlierFillColor')).append();\n                }\n            }\n\n            // box\n            target.drawRect(\n                Math.round((q1 - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight * 0.1),\n                Math.round((q3 - q1) * unitSize),\n                Math.round(canvasHeight * 0.8),\n                options.get('boxLineColor'),\n                options.get('boxFillColor')).append();\n            // left whisker\n            target.drawLine(\n                Math.round((lwhisker - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight / 2),\n                Math.round((q1 - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight / 2),\n                options.get('lineColor')).append();\n            target.drawLine(\n                Math.round((lwhisker - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight / 4),\n                Math.round((lwhisker - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight - canvasHeight / 4),\n                options.get('whiskerColor')).append();\n            // right whisker\n            target.drawLine(Math.round((rwhisker - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight / 2),\n                Math.round((q3 - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight / 2),\n                options.get('lineColor')).append();\n            target.drawLine(\n                Math.round((rwhisker - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight / 4),\n                Math.round((rwhisker - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight - canvasHeight / 4),\n                options.get('whiskerColor')).append();\n            // median line\n            target.drawLine(\n                Math.round((q2 - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight * 0.1),\n                Math.round((q2 - minValue) * unitSize + canvasLeft),\n                Math.round(canvasHeight * 0.9),\n                options.get('medianColor')).append();\n            if (options.get('target')) {\n                size = Math.ceil(options.get('spotRadius'));\n                target.drawLine(\n                    Math.round((options.get('target') - minValue) * unitSize + canvasLeft),\n                    Math.round((canvasHeight / 2) - size),\n                    Math.round((options.get('target') - minValue) * unitSize + canvasLeft),\n                    Math.round((canvasHeight / 2) + size),\n                    options.get('targetColor')).append();\n                target.drawLine(\n                    Math.round((options.get('target') - minValue) * unitSize + canvasLeft - size),\n                    Math.round(canvasHeight / 2),\n                    Math.round((options.get('target') - minValue) * unitSize + canvasLeft + size),\n                    Math.round(canvasHeight / 2),\n                    options.get('targetColor')).append();\n            }\n            target.render();\n        }\n    });\n\n    // Setup a very simple \"virtual canvas\" to make drawing the few shapes we need easier\n    // This is accessible as $(foo).simpledraw()\n\n    VShape = createClass({\n        init: function (target, id, type, args) {\n            this.target = target;\n            this.id = id;\n            this.type = type;\n            this.args = args;\n        },\n        append: function () {\n            this.target.appendShape(this);\n            return this;\n        }\n    });\n\n    VCanvas_base = createClass({\n        _pxregex: /(\\d+)(px)?\\s*$/i,\n\n        init: function (width, height, target) {\n            if (!width) {\n                return;\n            }\n            this.width = width;\n            this.height = height;\n            this.target = target;\n            this.lastShapeId = null;\n            if (target[0]) {\n                target = target[0];\n            }\n            $.data(target, '_jqs_vcanvas', this);\n        },\n\n        drawLine: function (x1, y1, x2, y2, lineColor, lineWidth) {\n            return this.drawShape([[x1, y1], [x2, y2]], lineColor, lineWidth);\n        },\n\n        drawShape: function (path, lineColor, fillColor, lineWidth) {\n            return this._genShape('Shape', [path, lineColor, fillColor, lineWidth]);\n        },\n\n        drawCircle: function (x, y, radius, lineColor, fillColor, lineWidth) {\n            return this._genShape('Circle', [x, y, radius, lineColor, fillColor, lineWidth]);\n        },\n\n        drawPieSlice: function (x, y, radius, startAngle, endAngle, lineColor, fillColor) {\n            return this._genShape('PieSlice', [x, y, radius, startAngle, endAngle, lineColor, fillColor]);\n        },\n\n        drawRect: function (x, y, width, height, lineColor, fillColor) {\n            return this._genShape('Rect', [x, y, width, height, lineColor, fillColor]);\n        },\n\n        getElement: function () {\n            return this.canvas;\n        },\n\n        /**\n         * Return the most recently inserted shape id\n         */\n        getLastShapeId: function () {\n            return this.lastShapeId;\n        },\n\n        /**\n         * Clear and reset the canvas\n         */\n        reset: function () {\n            alert('reset not implemented');\n        },\n\n        _insert: function (el, target) {\n            $(target).html(el);\n        },\n\n        /**\n         * Calculate the pixel dimensions of the canvas\n         */\n        _calculatePixelDims: function (width, height, canvas) {\n            // XXX This should probably be a configurable option\n            var match;\n            match = this._pxregex.exec(height);\n            if (match) {\n                this.pixelHeight = match[1];\n            } else {\n                this.pixelHeight = $(canvas).height();\n            }\n            match = this._pxregex.exec(width);\n            if (match) {\n                this.pixelWidth = match[1];\n            } else {\n                this.pixelWidth = $(canvas).width();\n            }\n        },\n\n        /**\n         * Generate a shape object and id for later rendering\n         */\n        _genShape: function (shapetype, shapeargs) {\n            var id = shapeCount++;\n            shapeargs.unshift(id);\n            return new VShape(this, id, shapetype, shapeargs);\n        },\n\n        /**\n         * Add a shape to the end of the render queue\n         */\n        appendShape: function (shape) {\n            alert('appendShape not implemented');\n        },\n\n        /**\n         * Replace one shape with another\n         */\n        replaceWithShape: function (shapeid, shape) {\n            alert('replaceWithShape not implemented');\n        },\n\n        /**\n         * Insert one shape after another in the render queue\n         */\n        insertAfterShape: function (shapeid, shape) {\n            alert('insertAfterShape not implemented');\n        },\n\n        /**\n         * Remove a shape from the queue\n         */\n        removeShapeId: function (shapeid) {\n            alert('removeShapeId not implemented');\n        },\n\n        /**\n         * Find a shape at the specified x/y co-ordinates\n         */\n        getShapeAt: function (el, x, y) {\n            alert('getShapeAt not implemented');\n        },\n\n        /**\n         * Render all queued shapes onto the canvas\n         */\n        render: function () {\n            alert('render not implemented');\n        }\n    });\n\n    VCanvas_canvas = createClass(VCanvas_base, {\n        init: function (width, height, target, interact) {\n            VCanvas_canvas._super.init.call(this, width, height, target);\n            this.canvas = document.createElement('canvas');\n            if (target[0]) {\n                target = target[0];\n            }\n            $.data(target, '_jqs_vcanvas', this);\n            $(this.canvas).css({ display: 'inline-block', width: width, height: height, verticalAlign: 'top' });\n            this._insert(this.canvas, target);\n            this._calculatePixelDims(width, height, this.canvas);\n            this.canvas.width = this.pixelWidth;\n            this.canvas.height = this.pixelHeight;\n            this.interact = interact;\n            this.shapes = {};\n            this.shapeseq = [];\n            this.currentTargetShapeId = undefined;\n            $(this.canvas).css({width: this.pixelWidth, height: this.pixelHeight});\n        },\n\n        _getContext: function (lineColor, fillColor, lineWidth) {\n            var context = this.canvas.getContext('2d');\n            if (lineColor !== undefined) {\n                context.strokeStyle = lineColor;\n            }\n            context.lineWidth = lineWidth === undefined ? 1 : lineWidth;\n            if (fillColor !== undefined) {\n                context.fillStyle = fillColor;\n            }\n            return context;\n        },\n\n        reset: function () {\n            var context = this._getContext();\n            context.clearRect(0, 0, this.pixelWidth, this.pixelHeight);\n            this.shapes = {};\n            this.shapeseq = [];\n            this.currentTargetShapeId = undefined;\n        },\n\n        _drawShape: function (shapeid, path, lineColor, fillColor, lineWidth) {\n            var context = this._getContext(lineColor, fillColor, lineWidth),\n                i, plen;\n            context.beginPath();\n            context.moveTo(path[0][0] + 0.5, path[0][1] + 0.5);\n            for (i = 1, plen = path.length; i < plen; i++) {\n                context.lineTo(path[i][0] + 0.5, path[i][1] + 0.5); // the 0.5 offset gives us crisp pixel-width lines\n            }\n            if (lineColor !== undefined) {\n                context.stroke();\n            }\n            if (fillColor !== undefined) {\n                context.fill();\n            }\n            if (this.targetX !== undefined && this.targetY !== undefined &&\n                context.isPointInPath(this.targetX, this.targetY)) {\n                this.currentTargetShapeId = shapeid;\n            }\n        },\n\n        _drawCircle: function (shapeid, x, y, radius, lineColor, fillColor, lineWidth) {\n            var context = this._getContext(lineColor, fillColor, lineWidth);\n            context.beginPath();\n            context.arc(x, y, radius, 0, 2 * Math.PI, false);\n            if (this.targetX !== undefined && this.targetY !== undefined &&\n                context.isPointInPath(this.targetX, this.targetY)) {\n                this.currentTargetShapeId = shapeid;\n            }\n            if (lineColor !== undefined) {\n                context.stroke();\n            }\n            if (fillColor !== undefined) {\n                context.fill();\n            }\n        },\n\n        _drawPieSlice: function (shapeid, x, y, radius, startAngle, endAngle, lineColor, fillColor) {\n            var context = this._getContext(lineColor, fillColor);\n            context.beginPath();\n            context.moveTo(x, y);\n            context.arc(x, y, radius, startAngle, endAngle, false);\n            context.lineTo(x, y);\n            context.closePath();\n            if (lineColor !== undefined) {\n                context.stroke();\n            }\n            if (fillColor) {\n                context.fill();\n            }\n            if (this.targetX !== undefined && this.targetY !== undefined &&\n                context.isPointInPath(this.targetX, this.targetY)) {\n                this.currentTargetShapeId = shapeid;\n            }\n        },\n\n        _drawRect: function (shapeid, x, y, width, height, lineColor, fillColor) {\n            return this._drawShape(shapeid, [[x, y], [x + width, y], [x + width, y + height], [x, y + height], [x, y]], lineColor, fillColor);\n        },\n\n        appendShape: function (shape) {\n            this.shapes[shape.id] = shape;\n            this.shapeseq.push(shape.id);\n            this.lastShapeId = shape.id;\n            return shape.id;\n        },\n\n        replaceWithShape: function (shapeid, shape) {\n            var shapeseq = this.shapeseq,\n                i;\n            this.shapes[shape.id] = shape;\n            for (i = shapeseq.length; i--;) {\n                if (shapeseq[i] == shapeid) {\n                    shapeseq[i] = shape.id;\n                }\n            }\n            delete this.shapes[shapeid];\n        },\n\n        replaceWithShapes: function (shapeids, shapes) {\n            var shapeseq = this.shapeseq,\n                shapemap = {},\n                sid, i, first;\n\n            for (i = shapeids.length; i--;) {\n                shapemap[shapeids[i]] = true;\n            }\n            for (i = shapeseq.length; i--;) {\n                sid = shapeseq[i];\n                if (shapemap[sid]) {\n                    shapeseq.splice(i, 1);\n                    delete this.shapes[sid];\n                    first = i;\n                }\n            }\n            for (i = shapes.length; i--;) {\n                shapeseq.splice(first, 0, shapes[i].id);\n                this.shapes[shapes[i].id] = shapes[i];\n            }\n\n        },\n\n        insertAfterShape: function (shapeid, shape) {\n            var shapeseq = this.shapeseq,\n                i;\n            for (i = shapeseq.length; i--;) {\n                if (shapeseq[i] === shapeid) {\n                    shapeseq.splice(i + 1, 0, shape.id);\n                    this.shapes[shape.id] = shape;\n                    return;\n                }\n            }\n        },\n\n        removeShapeId: function (shapeid) {\n            var shapeseq = this.shapeseq,\n                i;\n            for (i = shapeseq.length; i--;) {\n                if (shapeseq[i] === shapeid) {\n                    shapeseq.splice(i, 1);\n                    break;\n                }\n            }\n            delete this.shapes[shapeid];\n        },\n\n        getShapeAt: function (el, x, y) {\n            this.targetX = x;\n            this.targetY = y;\n            this.render();\n            return this.currentTargetShapeId;\n        },\n\n        render: function () {\n            var shapeseq = this.shapeseq,\n                shapes = this.shapes,\n                shapeCount = shapeseq.length,\n                context = this._getContext(),\n                shapeid, shape, i;\n            context.clearRect(0, 0, this.pixelWidth, this.pixelHeight);\n            for (i = 0; i < shapeCount; i++) {\n                shapeid = shapeseq[i];\n                shape = shapes[shapeid];\n                this['_draw' + shape.type].apply(this, shape.args);\n            }\n            if (!this.interact) {\n                // not interactive so no need to keep the shapes array\n                this.shapes = {};\n                this.shapeseq = [];\n            }\n        }\n\n    });\n\n    VCanvas_vml = createClass(VCanvas_base, {\n        init: function (width, height, target) {\n            var groupel;\n            VCanvas_vml._super.init.call(this, width, height, target);\n            if (target[0]) {\n                target = target[0];\n            }\n            $.data(target, '_jqs_vcanvas', this);\n            this.canvas = document.createElement('span');\n            $(this.canvas).css({ display: 'inline-block', position: 'relative', overflow: 'hidden', width: width, height: height, margin: '0px', padding: '0px', verticalAlign: 'top'});\n            this._insert(this.canvas, target);\n            this._calculatePixelDims(width, height, this.canvas);\n            this.canvas.width = this.pixelWidth;\n            this.canvas.height = this.pixelHeight;\n            groupel = '<v:group coordorigin=\"0 0\" coordsize=\"' + this.pixelWidth + ' ' + this.pixelHeight + '\"' +\n                    ' style=\"position:absolute;top:0;left:0;width:' + this.pixelWidth + 'px;height=' + this.pixelHeight + 'px;\"></v:group>';\n            this.canvas.insertAdjacentHTML('beforeEnd', groupel);\n            this.group = $(this.canvas).children()[0];\n            this.rendered = false;\n            this.prerender = '';\n        },\n\n        _drawShape: function (shapeid, path, lineColor, fillColor, lineWidth) {\n            var vpath = [],\n                initial, stroke, fill, closed, vel, plen, i;\n            for (i = 0, plen = path.length; i < plen; i++) {\n                vpath[i] = '' + (path[i][0]) + ',' + (path[i][1]);\n            }\n            initial = vpath.splice(0, 1);\n            lineWidth = lineWidth === undefined ? 1 : lineWidth;\n            stroke = lineColor === undefined ? ' stroked=\"false\" ' : ' strokeWeight=\"' + lineWidth + 'px\" strokeColor=\"' + lineColor + '\" ';\n            fill = fillColor === undefined ? ' filled=\"false\"' : ' fillColor=\"' + fillColor + '\" filled=\"true\" ';\n            closed = vpath[0] === vpath[vpath.length - 1] ? 'x ' : '';\n            vel = '<v:shape coordorigin=\"0 0\" coordsize=\"' + this.pixelWidth + ' ' + this.pixelHeight + '\" ' +\n                 ' id=\"jqsshape' + shapeid + '\" ' +\n                 stroke +\n                 fill +\n                ' style=\"position:absolute;left:0px;top:0px;height:' + this.pixelHeight + 'px;width:' + this.pixelWidth + 'px;padding:0px;margin:0px;\" ' +\n                ' path=\"m ' + initial + ' l ' + vpath.join(', ') + ' ' + closed + 'e\">' +\n                ' </v:shape>';\n            return vel;\n        },\n\n        _drawCircle: function (shapeid, x, y, radius, lineColor, fillColor, lineWidth) {\n            var stroke, fill, vel;\n            x -= radius;\n            y -= radius;\n            stroke = lineColor === undefined ? ' stroked=\"false\" ' : ' strokeWeight=\"' + lineWidth + 'px\" strokeColor=\"' + lineColor + '\" ';\n            fill = fillColor === undefined ? ' filled=\"false\"' : ' fillColor=\"' + fillColor + '\" filled=\"true\" ';\n            vel = '<v:oval ' +\n                 ' id=\"jqsshape' + shapeid + '\" ' +\n                stroke +\n                fill +\n                ' style=\"position:absolute;top:' + y + 'px; left:' + x + 'px; width:' + (radius * 2) + 'px; height:' + (radius * 2) + 'px\"></v:oval>';\n            return vel;\n\n        },\n\n        _drawPieSlice: function (shapeid, x, y, radius, startAngle, endAngle, lineColor, fillColor) {\n            var vpath, startx, starty, endx, endy, stroke, fill, vel;\n            if (startAngle === endAngle) {\n                return '';  // VML seems to have problem when start angle equals end angle.\n            }\n            if ((endAngle - startAngle) === (2 * Math.PI)) {\n                startAngle = 0.0;  // VML seems to have a problem when drawing a full circle that doesn't start 0\n                endAngle = (2 * Math.PI);\n            }\n\n            startx = x + Math.round(Math.cos(startAngle) * radius);\n            starty = y + Math.round(Math.sin(startAngle) * radius);\n            endx = x + Math.round(Math.cos(endAngle) * radius);\n            endy = y + Math.round(Math.sin(endAngle) * radius);\n\n            if (startx === endx && starty === endy) {\n                if ((endAngle - startAngle) < Math.PI) {\n                    // Prevent very small slices from being mistaken as a whole pie\n                    return '';\n                }\n                // essentially going to be the entire circle, so ignore startAngle\n                startx = endx = x + radius;\n                starty = endy = y;\n            }\n\n            if (startx === endx && starty === endy && (endAngle - startAngle) < Math.PI) {\n                return '';\n            }\n\n            vpath = [x - radius, y - radius, x + radius, y + radius, startx, starty, endx, endy];\n            stroke = lineColor === undefined ? ' stroked=\"false\" ' : ' strokeWeight=\"1px\" strokeColor=\"' + lineColor + '\" ';\n            fill = fillColor === undefined ? ' filled=\"false\"' : ' fillColor=\"' + fillColor + '\" filled=\"true\" ';\n            vel = '<v:shape coordorigin=\"0 0\" coordsize=\"' + this.pixelWidth + ' ' + this.pixelHeight + '\" ' +\n                 ' id=\"jqsshape' + shapeid + '\" ' +\n                 stroke +\n                 fill +\n                ' style=\"position:absolute;left:0px;top:0px;height:' + this.pixelHeight + 'px;width:' + this.pixelWidth + 'px;padding:0px;margin:0px;\" ' +\n                ' path=\"m ' + x + ',' + y + ' wa ' + vpath.join(', ') + ' x e\">' +\n                ' </v:shape>';\n            return vel;\n        },\n\n        _drawRect: function (shapeid, x, y, width, height, lineColor, fillColor) {\n            return this._drawShape(shapeid, [[x, y], [x, y + height], [x + width, y + height], [x + width, y], [x, y]], lineColor, fillColor);\n        },\n\n        reset: function () {\n            this.group.innerHTML = '';\n        },\n\n        appendShape: function (shape) {\n            var vel = this['_draw' + shape.type].apply(this, shape.args);\n            if (this.rendered) {\n                this.group.insertAdjacentHTML('beforeEnd', vel);\n            } else {\n                this.prerender += vel;\n            }\n            this.lastShapeId = shape.id;\n            return shape.id;\n        },\n\n        replaceWithShape: function (shapeid, shape) {\n            var existing = $('#jqsshape' + shapeid),\n                vel = this['_draw' + shape.type].apply(this, shape.args);\n            existing[0].outerHTML = vel;\n        },\n\n        replaceWithShapes: function (shapeids, shapes) {\n            // replace the first shapeid with all the new shapes then toast the remaining old shapes\n            var existing = $('#jqsshape' + shapeids[0]),\n                replace = '',\n                slen = shapes.length,\n                i;\n            for (i = 0; i < slen; i++) {\n                replace += this['_draw' + shapes[i].type].apply(this, shapes[i].args);\n            }\n            existing[0].outerHTML = replace;\n            for (i = 1; i < shapeids.length; i++) {\n                $('#jqsshape' + shapeids[i]).remove();\n            }\n        },\n\n        insertAfterShape: function (shapeid, shape) {\n            var existing = $('#jqsshape' + shapeid),\n                 vel = this['_draw' + shape.type].apply(this, shape.args);\n            existing[0].insertAdjacentHTML('afterEnd', vel);\n        },\n\n        removeShapeId: function (shapeid) {\n            var existing = $('#jqsshape' + shapeid);\n            this.group.removeChild(existing[0]);\n        },\n\n        getShapeAt: function (el, x, y) {\n            var shapeid = el.id.substr(8);\n            return shapeid;\n        },\n\n        render: function () {\n            if (!this.rendered) {\n                // batch the intial render into a single repaint\n                this.group.innerHTML = this.prerender;\n                this.rendered = true;\n            }\n        }\n    });\n\n}))}(document, Math));\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/owl.carousel.js",
    "content": "/*\n *\tjQuery OwlCarousel v1.21\n *\n *\tCopyright (c) 2013 Bartosz Wojciechowski\n *\thttp://www.owlgraphic.com/owlcarousel\n *\n *\tLicensed under MIT\n *\n */\n\n\n// Object.create function\nif ( typeof Object.create !== \"function\" ) {\n\tObject.create = function( obj ) {\n\t\tfunction F() {};\n\t\tF.prototype = obj;\n\t\treturn new F();\n\t};\n}\n(function( $, window, document, undefined ) {\n\n\tvar Carousel = {\n\t\tinit :function(options, el){\n\t\t\tvar base = this;\n\t\t\tbase.options = $.extend({}, $.fn.owlCarousel.options, options);\n\t\t\tvar elem = el;\n\t\t\tvar $elem = $(el);\n\t\t\tbase.$elem = $elem;\n\t\t\tbase.loadContent()\n\t\t},\n\n\t\tloadContent : function(){\n\t\t\tvar base = this;\n\n\t\t\tif (typeof base.options.beforeInit === \"function\") {\n\t\t\t\tbase.options.beforeInit.apply(this,[base.$elem]);\n\t\t\t}\n\n\t\t\tif (typeof base.options.jsonPath === \"string\") {\n\t\t\t\tvar url = base.options.jsonPath;\n\n\t\t\t\tfunction getData(data) {\n\t\t\t\t\tif (typeof base.options.jsonSuccess === \"function\") {\n\t\t\t\t\t\tbase.options.jsonSuccess.apply(this,[data]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar content = \"\";\n\t\t\t\t\t\tfor(var i in data[\"owl\"]){\n\t\t\t\t\t\t\tcontent += data[\"owl\"][i][\"item\"];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbase.$elem.html(content);\n\t\t\t\t\t}\n\t\t\t\t\tbase.logIn();\n\t\t\t\t}\n\t\t\t\t$.getJSON(url,getData);\n\t\t\t} else {\n\t\t\t\tbase.logIn();\n\t\t\t}\n\t\t},\n\n\t\tlogIn : function(){\n\t\t\tvar base = this;\n\n\t\t\tbase.baseClass();\n\n\t\t\tbase.$elem\n\t\t\t.css({opacity: 0})\n\n\t\t\tbase.checkTouch();\n\t\t\tbase.support3d();\n\n\t\t\tbase.wrapperWidth = 0;\n\t\t\tbase.currentSlide = 0; //Starting Position\n\n\t\t\tbase.userItems = base.$elem.children();\n\t\t\tbase.itemsAmount = base.userItems.length;\n\t\t\tbase.wrapItems();\n\n\t\t\tbase.owlItems = base.$elem.find(\".owl-item\");\n\t\t\tbase.owlWrapper = base.$elem.find(\".owl-wrapper\");\n\n\t\t\tbase.orignalItems = base.options.items;\n\t\t\tbase.playDirection = \"next\";\n\n\t\t\tbase.checkVisible;\n\n\t\t\t//setTimeout(function(){\n\t\t\tbase.onStartup();\n\t\t\t//},0);\n\t\t\tbase.customEvents();\n\n\t\t},\n\n\t\tonStartup : function(){\n\t\t\tvar base = this;\n\t\t\tbase.updateItems();\n\t\t\tbase.calculateAll();\n\t\t\tbase.buildControls();\n\t\t\tbase.updateControls();\n\t\t\tbase.response();\n\t\t\tbase.moveEvents();\n\t\t\tbase.stopOnHover();\n\t\t\tif(base.options.autoPlay === true){\n\t\t\t\tbase.options.autoPlay = 5000;\n\t\t\t}\n\t\t\tbase.play();\n\t\t\tbase.$elem.find(\".owl-wrapper\").css(\"display\",\"block\")\n\n\t\t\tif(!base.$elem.is(\":visible\")){\n\t\t\t\tbase.watchVisibility();\n\t\t\t} else {\n\t\t\t\tsetTimeout(function(){\n\t\t\t\t\tbase.$elem.animate({opacity: 1},200);\n\t\t\t\t},10);\n\t\t\t}\n\t\t\tbase.onstartup = false;\n\t\t\tbase.eachMoveUpdate();\n\t\t\tif (typeof base.options.afterInit === \"function\") {\n\t\t\t\tbase.options.afterInit.apply(this,[base.$elem]);\n\t\t\t}\n\t\t},\n\n\t\teachMoveUpdate : function(){\n\t\t\tvar base = this;\n\t\t\tbase.lazyLoad();\n\t\t\tbase.autoHeight();\n\t\t\tif(base.options.singleItem === true){\n\t\t\t\tbase.addActiveClass();\n\t\t\t}\n\t\t\tif (typeof base.options.afterAction === \"function\") {\n\t\t\t\tbase.options.afterAction.apply(this);\n\t\t\t}\n\t\t},\n\n\t\tupdateVars : function(){\n\t\t\tvar base = this;\n\t\t\tbase.watchVisibility();\n\t\t\tbase.updateItems();\n\t\t\tbase.calculateAll();\n\t\t\tbase.updatePosition();\n\t\t\tbase.updateControls();\n\t\t\tbase.eachMoveUpdate();\n\t\t},\n\n\t\treload : function(elements){\n\t\t\tvar base = this;\n\t\t\tsetTimeout(function(){\n\t\t\t\tbase.updateVars();\n\t\t\t},0)\n\t\t},\n\n\t\twatchVisibility : function(){\n\t\t\tvar base = this;\n\t\t\tclearInterval(base.checkVisible);\n\t\t\tif(!base.$elem.is(\":visible\")){\n\t\t\t\tbase.$elem.css({opacity: 0});\n\t\t\t\tclearInterval(base.autoPlaySpeed);\n\t\t\t} else {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tbase.checkVisible = setInterval(function(){\n\t\t\t\tif (base.$elem.is(\":visible\")) {\n\t\t\t\t\tbase.reload();\n\t\t\t\t\tbase.$elem.animate({opacity: 1},200);\n\t\t\t\t\tclearInterval(base.checkVisible);\n\t\t\t\t}\n\t\t\t}, 500);\n\t\t},\n\n\t\twrapItems : function(){\n\t\t\tvar base = this;\n\t\t\tbase.userItems.wrapAll(\"<div class=\\\"owl-wrapper\\\">\").wrap(\"<div class=\\\"owl-item\\\"></div>\");\n\t\t\tbase.$elem.find(\".owl-wrapper\").wrap(\"<div class=\\\"owl-wrapper-outer\\\">\");\n\t\t\tbase.wrapperOuter = base.$elem.find(\".owl-wrapper-outer\");\n\t\t\tbase.$elem.css(\"display\",\"block\");\n\t\t},\n\n\t\tbaseClass : function(){\n\t\t\tvar base = this;\n\t\t\tvar hasBaseClass = base.$elem.hasClass(base.options.baseClass);\n\t\t\tvar hasThemeClass = base.$elem.hasClass(base.options.theme);\n\n\t\t\tif(!hasBaseClass){\n\t\t\t\tbase.$elem.addClass(base.options.baseClass);\n\t\t\t}\n\n\t\t\tif(!hasThemeClass){\n\t\t\t\tbase.$elem.addClass(base.options.theme);\n\t\t\t}\n\t\t},\n\n\t\tupdateItems : function(){\n\t\t\tvar base = this;\n\n\t\t\tif(base.options.responsive === false){\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif(base.options.singleItem === true){\n\t\t\t\tbase.options.items = base.orignalItems = 1;\n\t\t\t\tbase.options.itemsDesktop = false;\n\t\t\t\tbase.options.itemsDesktopSmall = false;\n\t\t\t\tbase.options.itemsTablet = false;\n\t\t\t\tbase.options.itemsMobile = false;\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tvar width = $(window).width();\n\n\t\t\tif(width > (base.options.itemsDesktop[0] || base.orignalItems) ){\n\t\t\t\t base.options.items = base.orignalItems\n\t\t\t}\n\n\t\t\tif(width <= base.options.itemsDesktop[0] && base.options.itemsDesktop !== false){\n\t\t\t\tbase.options.items = base.options.itemsDesktop[1];\n\t\t\t}\n\n\t\t\tif(width <= base.options.itemsDesktopSmall[0] && base.options.itemsDesktopSmall !== false){\n\t\t\t\tbase.options.items = base.options.itemsDesktopSmall[1];\n\t\t\t}\n\n\t\t\tif(width <= base.options.itemsTablet[0]  && base.options.itemsTablet !== false){\n\t\t\t\tbase.options.items = base.options.itemsTablet[1];\n\t\t\t}\n\n\t\t\tif(width <= base.options.itemsMobile[0] && base.options.itemsMobile !== false){\n\t\t\t\tbase.options.items = base.options.itemsMobile[1];\n\t\t\t}\n\n\t\t\t//if number of items is less than declared\n\t\t\tif(base.options.items > base.itemsAmount){\n\t\t\t\tbase.options.items = base.itemsAmount;\n\t\t\t}\n\t\t},\n\n\t\tresponse : function(){\n\t\t\tvar base = this,\n\t\t\t\tsmallDelay;\n\t\t\tif(base.options.responsive !== true){\n\t\t\t\treturn false\n\t\t\t}\n\t\t\t$(window).resize(function(){\n\t\t\t\tif(base.options.autoPlay !== false){\n\t\t\t\t\tclearInterval(base.autoPlaySpeed);\n\t\t\t\t}\n\t\t\t\tclearTimeout(smallDelay)\n\t\t\t\tsmallDelay = setTimeout(function(){\n\t\t\t\t\tbase.updateVars();\n\t\t\t\t},base.options.responsiveRefreshRate);\n\t\t\t})\n\t\t},\n\n\t\tupdatePosition : function(){\n\t\t\tvar base = this;\n\n\t\t\tif(base.support3d === true){\n\t\t\t\tif(base.positionsInArray[base.currentSlide] > base.maximumPixels){\n\t\t\t\t\tbase.transition3d(base.positionsInArray[base.currentSlide]);\n\t\t\t\t} else {\n\t\t\t\t\tbase.transition3d(0);\n\t\t\t\t\tbase.currentSlide = 0;\n\t\t\t\t}\n\t\t\t} else{\n\t\t\t\tif(base.positionsInArray[base.currentSlide] > base.maximumPixels){\n\t\t\t\t\tbase.css2slide(base.positionsInArray[base.currentSlide]);\n\t\t\t\t} else {\n\t\t\t\t\tbase.css2slide(0);\n\t\t\t\t\tbase.currentSlide = 0;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(base.options.autoPlay !== false){\n\t\t\t\tbase.checkAp();\n\t\t\t}\n\t\t},\n\n\t\tappendItemsSizes : function(){\n\t\t\tvar base = this;\n\n\t\t\tvar roundPages = 0;\n\t\t\tvar lastItem = base.itemsAmount - base.options.items;\n\n\t\t\tbase.owlItems.each(function(index){\n\t\t\t\t$(this)\n\t\t\t\t.css({\"width\": base.itemWidth})\n\t\t\t\t.data(\"owl-item\",Number(index));\n\n\t\t\t\tif(index % base.options.items === 0 || index === lastItem){\n\t\t\t\t\tif(!(index > lastItem)){\n\t\t\t\t\t\troundPages +=1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$(this).data(\"owl-roundPages\",roundPages);\n\t\t\t});\n\t\t},\n\n\t\tappendWrapperSizes : function(){\n\t\t\tvar base = this;\n\t\t\tvar width = 0;\n\n\t\t\tvar width = base.owlItems.length * base.itemWidth;\n\n\t\t\tbase.owlWrapper.css({\n\t\t\t\t\"width\": width*2,\n\t\t\t\t\"left\": 0\n\t\t\t});\n\t\t\tbase.appendItemsSizes();\n\t\t},\n\n\t\tcalculateAll : function(){\n\t\t\tvar base = this;\n\t\t\tbase.calculateWidth();\n\t\t\tbase.appendWrapperSizes();\n\t\t\tbase.loops();\n\t\t\tbase.max();\n\t\t},\n\n\t\tcalculateWidth : function(){\n\t\t\tvar base = this;\n\t\t\tbase.itemWidth = Math.round(base.$elem.width()/base.options.items)\n\t\t},\n\n\t\tmax : function(){\n\t\t\tvar base = this;\n\t\t\tbase.maximumSlide = base.itemsAmount - base.options.items;\n\t\t\tvar maximum = (base.itemsAmount * base.itemWidth) - base.options.items * base.itemWidth;\n\t\t\t\tmaximum = maximum * -1\n\t\t\tbase.maximumPixels = maximum;\n\t\t\treturn maximum;\n\t\t},\n\n\t\tmin : function(){\n\t\t\treturn 0;\n\t\t},\n\n\t\tloops : function(){\n\t\t\tvar base = this;\n\n\t\t\tbase.positionsInArray = [0];\n\t\t\tvar elWidth = 0;\n\n\t\t\tfor(var i = 0; i<base.itemsAmount; i++){\n\t\t\t\telWidth += base.itemWidth;\n\t\t\t\tbase.positionsInArray.push(-elWidth)\n\t\t\t}\n\t\t},\n\n\t\tbuildControls : function(){\n\t\t\tvar base = this;\n\t\t\tif(base.options.navigation === true || base.options.pagination === true){\n\t\t\t\tbase.owlControls = $(\"<div class=\\\"owl-controls\\\"/>\").toggleClass(\"clickable\", !base.isTouch).appendTo(base.$elem);\n\t\t\t}\n\t\t\tif(base.options.pagination === true){\n\t\t\t\tbase.buildPagination();\n\t\t\t}\n\t\t\tif(base.options.navigation === true){\n\t\t\t\tbase.buildButtons();\n\t\t\t}\n\t\t},\n\n\t\tbuildButtons : function(){\n\t\t\tvar base = this;\n\t\t\tvar buttonsWrapper = $(\"<div class=\\\"owl-buttons\\\"/>\")\n\t\t\tbase.owlControls.append(buttonsWrapper);\n\n\t\t\tbase.buttonPrev = $(\"<div/>\",{\n\t\t\t\t\"class\" : \"owl-prev\",\n\t\t\t\t\"html\" : base.options.navigationText[0] || \"\"\n\t\t\t\t});\n\n\t\t\tbase.buttonNext = $(\"<div/>\",{\n\t\t\t\t\"class\" : \"owl-next\",\n\t\t\t\t\"html\" : base.options.navigationText[1] || \"\"\n\t\t\t\t});\n\n\t\t\tbuttonsWrapper\n\t\t\t.append(base.buttonPrev)\n\t\t\t.append(base.buttonNext);\n\n\t\t\tbuttonsWrapper.on(base.getEvent(), \"div[class^=\\\"owl\\\"]\", function(event){\n\t\t\t\tevent.preventDefault();\n\t\t\t\tif($(this).hasClass(\"owl-next\")){\n\t\t\t\t\tbase.next();\n\t\t\t\t} else{\n\t\t\t\t\tbase.prev();\n\t\t\t\t}\n\t\t\t})\n\t\t},\n\n\t\tgetEvent : function(){\n\t\t\tvar base = this;\n\t\t\tif (base.isTouch === true){\n\t\t\t\treturn \"touchend.owlControls\";\n\t\t\t} else {\n\t\t\t\treturn \"click.owlControls\";\n\t\t\t}\n\t\t},\n\n\t\tbuildPagination : function(){\n\t\t\tvar base = this;\n\n\t\t\tbase.paginationWrapper = $(\"<div class=\\\"owl-pagination\\\"/>\");\n\t\t\tbase.owlControls.append(base.paginationWrapper);\n\n\t\t\tbase.paginationWrapper.on(base.getEvent(), \".owl-page\", function(event){\n\t\t\t\tevent.preventDefault();\n\t\t\t\tif(Number($(this).data(\"owl-page\")) !== base.currentSlide){\n\t\t\t\t\tbase.goTo( Number($(this).data(\"owl-page\")), true);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\tupdatePagination : function(){\n\t\t\tvar base = this;\n\t\t\tif(base.options.pagination === false){\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tbase.paginationWrapper.html(\"\");\n\n\t\t\tvar counter = 0;\n\t\t\tvar lastPage = base.itemsAmount - base.itemsAmount % base.options.items;\n\n\t\t\tfor(var i = 0; i<base.itemsAmount; i++){\n\t\t\t\tif(i % base.options.items === 0){\n\t\t\t\t\tcounter +=1;\n\t\t\t\t\tif(lastPage === i){\n\t\t\t\t\t\tvar lastItem = base.itemsAmount - base.options.items;\n\t\t\t\t\t}\n\t\t\t\t\tvar paginationButton = $(\"<div/>\",{\n\t\t\t\t\t\t\"class\" : \"owl-page\"\n\t\t\t\t\t\t});\n\t\t\t\t\tvar paginationButtonInner = $(\"<span></span>\",{\n\t\t\t\t\t\t\"text\": base.options.paginationNumbers === true ? counter : \"\",\n\t\t\t\t\t\t\"class\": base.options.paginationNumbers === true ? \"owl-numbers\" : \"\"\n\t\t\t\t\t});\n\t\t\t\t\tpaginationButton.append(paginationButtonInner);\n\n\t\t\t\t\tpaginationButton.data(\"owl-page\",lastPage === i ? lastItem : i);\n\t\t\t\t\tpaginationButton.data(\"owl-roundPages\",counter);\n\n\t\t\t\t\tbase.paginationWrapper.append(paginationButton);\n\t\t\t\t}\n\t\t\t}\n\t\t\tbase.checkPagination();\n\t\t},\n\t\tcheckPagination : function(){\n\t\t\tvar base = this;\n\n\t\t\tbase.paginationWrapper.find(\".owl-page\").each(function(i,v){\n\t\t\t\tif($(this).data(\"owl-roundPages\") === $(base.owlItems[base.currentSlide]).data(\"owl-roundPages\") ){\n\t\t\t\t\tbase.paginationWrapper\n\t\t\t\t\t\t.find(\".owl-page\")\n\t\t\t\t\t\t.removeClass(\"active\");\n\t\t\t\t\t$(this).addClass(\"active\");\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\tcheckNavigation : function(){\n\t\t\tvar base = this;\n\n\t\t\tif(base.options.navigation === false){\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif(base.options.goToFirstNav === false){\n\t\t\t\tif(base.currentSlide === 0 && base.maximumSlide === 0){\n\t\t\t\t\tbase.buttonPrev.addClass(\"disabled\");\n\t\t\t\t\tbase.buttonNext.addClass(\"disabled\");\n\t\t\t\t} else if(base.currentSlide === 0 && base.maximumSlide !== 0){\n\t\t\t\t\tbase.buttonPrev.addClass(\"disabled\");\n\t\t\t\t\tbase.buttonNext.removeClass(\"disabled\");\n\t\t\t\t} else if (base.currentSlide === base.maximumSlide){\n\t\t\t\t\tbase.buttonPrev.removeClass(\"disabled\");\n\t\t\t\t\tbase.buttonNext.addClass(\"disabled\");\n\t\t\t\t} else if(base.currentSlide !== 0 && base.currentSlide !== base.maximumSlide){\n\t\t\t\t\tbase.buttonPrev.removeClass(\"disabled\");\n\t\t\t\t\tbase.buttonNext.removeClass(\"disabled\");\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tupdateControls : function(){\n\t\t\tvar base = this;\n\t\t\tbase.updatePagination();\n\t\t\tbase.checkNavigation();\n\t\t\tif(base.owlControls){\n\t\t\t\tif(base.options.items === base.itemsAmount){\n\t\t\t\t\tbase.owlControls.hide();\n\t\t\t\t} else {\n\t\t\t\t\tbase.owlControls.show();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tdestroyControls : function(){\n\t\t\tvar base = this;\n\t\t\tif(base.owlControls){\n\t\t\t\tbase.owlControls.remove();\n\t\t\t}\n\t\t},\n\n\t\tnext : function(speed){\n\t\t\tvar base = this;\n\t\t\tbase.currentSlide += base.options.scrollPerPage === true ? base.options.items : 1;\n\t\t\tif(base.currentSlide > base.maximumSlide + (base.options.scrollPerPage == true ? (base.options.items - 1) : 0)){\n\t\t\t\tif(base.options.goToFirstNav === true){\n\t\t\t\t\tbase.currentSlide = 0;\n\t\t\t\t\tspeed = \"goToFirst\";\n\t\t\t\t} else {\n\t\t\t\t\tbase.currentSlide = base.maximumSlide;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbase.goTo(base.currentSlide,speed);\n\t\t},\n\n\t\tprev : function(speed){\n\t\t\tvar base = this;\n\t\t\tif(base.options.scrollPerPage === true && base.currentSlide > 0 && base.currentSlide < base.options.items){\n\t\t\t\tbase.currentSlide = 0\n\t\t\t} else {\n\t\t\tbase.currentSlide -= base.options.scrollPerPage === true ? base.options.items : 1;\n\t\t\t}\n\t\t\tif(base.currentSlide < 0){\n\t\t\t\tif(base.options.goToFirstNav === true){\n\t\t\t\t\tbase.currentSlide = base.maximumSlide;\n\t\t\t\t\tspeed = \"goToFirst\"\n\t\t\t\t} else {\n\t\t\t\t\tbase.currentSlide =0;\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbase.goTo(base.currentSlide,speed);\n\t\t},\n\n\t\tgoTo : function(position,pagination){\n\t\t\tvar base = this;\n\n\t\t\tif(typeof base.options.beforeMove === \"function\") {\n\t\t\t\tbase.options.beforeMove.apply(this);\n\t\t\t}\n\t\t\tif(position >= base.maximumSlide){\n\t\t\t\tposition = base.maximumSlide;\n\t\t\t}\n\t\t\telse if( position <= 0 ){\n\t\t\t\tposition = 0;\n\t\t\t}\n\t\t\tbase.currentSlide = position;\n\n\t\t\tvar goToPixel = base.positionsInArray[position];\n\n\t\t\tif(base.support3d === true){\n\t\t\t\tbase.isCss3Finish = false;\n\n\t\t\t\tif(pagination === true){\n\t\t\t\t\tbase.swapTransitionSpeed(\"paginationSpeed\");\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tbase.isCss3Finish = true;\n\t\t\t\t\t}, base.options.paginationSpeed);\n\n\t\t\t\t} else if(pagination === \"goToFirst\" ){\n\t\t\t\t\tbase.swapTransitionSpeed(base.options.goToFirstSpeed);\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tbase.isCss3Finish = true;\n\t\t\t\t\t}, base.options.goToFirstSpeed);\n\n\t\t\t\t} else {\n\t\t\t\t\tbase.swapTransitionSpeed(\"slideSpeed\");\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tbase.isCss3Finish = true;\n\t\t\t\t\t}, base.options.slideSpeed);\n\t\t\t\t}\n\t\t\t\tbase.transition3d(goToPixel);\n\t\t\t} else {\n\t\t\t\tif(pagination === true){\n\t\t\t\t\tbase.css2slide(goToPixel, base.options.paginationSpeed);\n\t\t\t\t} else if(pagination === \"goToFirst\" ){\n\t\t\t\t\tbase.css2slide(goToPixel, base.options.goToFirstSpeed);\n\t\t\t\t} else {\n\t\t\t\t\tbase.css2slide(goToPixel, base.options.slideSpeed);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(base.options.pagination === true){\n\t\t\t\tbase.checkPagination();\n\t\t\t}\n\t\t\tif(base.options.navigation === true){\n\t\t\t\tbase.checkNavigation();\n\t\t\t}\n\t\t\tif(base.options.autoPlay !== false){\n\t\t\t\tbase.checkAp();\n\t\t\t}\n\t\t\tbase.eachMoveUpdate();\n\t\t\tif(typeof base.options.afterMove === \"function\") {\n\t\t\t\tbase.options.afterMove.apply(this);\n\t\t\t}\n\t\t},\n\n\t\tstop: function(){\n\t\t\tvar base = this;\n\t\t\tbase.apStatus = \"stop\";\n\t\t\tclearInterval(base.autoPlaySpeed);\n\t\t},\n\n\t\tcheckAp : function(){\n\t\t\tvar base = this;\n\t\t\tif(base.apStatus !== \"stop\"){\n\t\t\t\tbase.play();\n\t\t\t}\n\t\t},\n\n\t\tplay : function(){\n\t\t\tvar base = this;\n\t\t\tbase.apStatus = \"play\";\n\t\t\tif(base.options.autoPlay === false){\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tclearInterval(base.autoPlaySpeed);\n\t\t\tbase.autoPlaySpeed = setInterval(function(){\n\t\t\t\tif(base.currentSlide < base.maximumSlide && base.playDirection === \"next\"){\n\t\t\t\t\tbase.next(true);\n\t\t\t\t} else if(base.currentSlide === base.maximumSlide){\n\t\t\t\t\tif(base.options.goToFirst === true){\n\t\t\t\t\t\tbase.goTo(0,\"goToFirst\");\n\t\t\t\t\t} else{\n\t\t\t\t\t\tbase.playDirection = \"prev\";\n\t\t\t\t\t\tbase.prev(true);\n\t\t\t\t\t}\n\t\t\t\t} else if(base.playDirection === \"prev\" && base.currentSlide > 0){\n\t\t\t\t\tbase.prev(true);\n\t\t\t\t} else if(base.playDirection === \"prev\" && base.currentSlide === 0){\n\t\t\t\t\tbase.playDirection = \"next\";\n\t\t\t\t\tbase.next(true);\n\t\t\t\t}\n\t\t\t},base.options.autoPlay);\n\t\t},\n\n\t\tswapTransitionSpeed : function(action){\n\t\t\tvar base = this;\n\t\t\tif(action === \"slideSpeed\"){\n\t\t\t\tbase.owlWrapper.css(base.addTransition(base.options.slideSpeed));\n\t\t\t} else if(action === \"paginationSpeed\" ){\n\t\t\t\tbase.owlWrapper.css(base.addTransition(base.options.paginationSpeed));\n\t\t\t} else if(typeof action !== \"string\"){\n\t\t\t\tbase.owlWrapper.css(base.addTransition(action));\n\t\t\t}\n\t\t},\n\n\t\taddTransition : function(speed){\n\t\t\tvar base = this;\n\t\t\treturn {\n\t\t\t\t\"-webkit-transition\": \"all \"+ speed +\"ms ease\",\n\t\t\t\t\"-moz-transition\": \"all \"+ speed +\"ms ease\",\n\t\t\t\t\"-o-transition\": \"all \"+ speed +\"ms ease\",\n\t\t\t\t\"transition\": \"all \"+ speed +\"ms ease\"\n\t\t\t};\n\t\t},\n\n\t\tremoveTransition : function(){\n\t\t\treturn {\n\t\t\t\t\"-webkit-transition\": \"\",\n\t\t\t\t\"-moz-transition\": \"\",\n\t\t\t\t\"-o-transition\": \"\",\n\t\t\t\t\"transition\": \"\"\n\t\t\t};\n\t\t},\n\n\t\tdoTranslate : function(pixels){\n\t\t\treturn {\n\t\t\t\t\"-webkit-transform\": \"translate3d(\"+pixels+\"px, 0px, 0px)\",\n\t\t\t\t\"-moz-transform\": \"translate3d(\"+pixels+\"px, 0px, 0px)\",\n\t\t\t\t\"-o-transform\": \"translate3d(\"+pixels+\"px, 0px, 0px)\",\n\t\t\t\t\"-ms-transform\": \"translate3d(\"+pixels+\"px, 0px, 0px)\",\n\t\t\t\t\"transform\": \"translate3d(\"+pixels+\"px, 0px,0px)\"\n\t\t\t};\n\t\t},\n\n\t\ttransition3d : function(value){\n\t\t\tvar base = this;\n\t\t\tbase.owlWrapper.css(base.doTranslate(value));\n\t\t},\n\n\t\tcss2move : function(value){\n\t\t\tvar base = this;\n\t\t\tbase.owlWrapper.css({\"left\" : value})\n\t\t},\n\n\t\tcss2slide : function(value,speed){\n\t\t\tvar base = this;\n\n\t\t\tbase.isCssFinish = false;\n\t\t\tbase.owlWrapper.stop(true,true).animate({\n\t\t\t\t\"left\" : value\n\t\t\t}, {\n\t\t\t\tduration : speed || base.options.slideSpeed ,\n\t\t\t\tcomplete : function(){\n\t\t\t\t\tbase.isCssFinish = true;\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\tsupport3d : function(){\n\t\t\t\tvar base = this;\n\n\t\t\t\tvar sTranslate3D = \"translate3d(0px, 0px, 0px)\";\n\t\t\t\t var eTemp = document.createElement(\"div\");\n\t\t\t\teTemp.style.cssText = \"  -moz-transform:\"    + sTranslate3D +\n\t\t\t\t\t\t\t\t\t  \"; -ms-transform:\"     + sTranslate3D +\n\t\t\t\t\t\t\t\t\t  \"; -o-transform:\"      + sTranslate3D +\n\t\t\t\t\t\t\t\t\t  \"; -webkit-transform:\" + sTranslate3D +\n\t\t\t\t\t\t\t\t\t  \"; transform:\"         + sTranslate3D;\n\t\t\t\tvar rxTranslate = /translate3d\\(0px, 0px, 0px\\)/g;\n\t\t\t\tvar asSupport = eTemp.style.cssText.match(rxTranslate);\n\t\t\t\tvar bHasSupport = (asSupport !== null && asSupport.length === 1);\n\t\t\t\tbase.support3d = bHasSupport\n\t\t\t\treturn bHasSupport;\n\t\t},\n\n\t\tcheckTouch : function(){\n\t\t\tvar base = this;\n\t\t\tbase.isTouch = (\"ontouchstart\" in document.documentElement);\n\t\t},\n\n\t\tmoveEvents : function(){\n\t\t\tvar base = this;\n\t\t\tif(base.options.mouseDraggable || base.isTouch === true){\n\t\t\t\tbase.eventTypes();\n\t\t\t\tbase.gestures();\n\t\t\t\tbase.disabledEvents();\n\t\t\t}\n\t\t},\n\n\t\teventTypes : function(){\n\t\tvar base = this;\n\t\tvar types;\n\n\t\tbase.ev_types = {};\n\n\t\tif(base.isTouch) {\n\t\ttypes = [\n\t\t\t\"touchstart.owl\",\n\t\t\t\"touchmove.owl\",\n\t\t\t\"touchend.owl\"\n\t\t\t];\n\t\t} else{\n\t\ttypes = [\n\t\t\t\"mousedown.owl\",\n\t\t\t\"mousemove.owl\",\n\t\t\t\"mouseup.owl\"\n\t\t\t];\n\t\t}\n\t\tbase.ev_types[\"start\"] = types[0];\n\t\tbase.ev_types[\"move\"] = types[1];\n\t\tbase.ev_types[\"end\"] = types[2];\n\t\t},\n\n\t\tdisabledEvents :  function(){\n\t\t\tvar base = this;\n\t\t\tif(base.isTouch !== true){\n\t\t\t\tbase.$elem.on(\"dragstart.owl\",\"img\", function(event) { event.preventDefault();});\n\t\t\t\tbase.$elem.bind(\"mousedown.disableTextSelect\", function() {return false;});\n\t\t\t}\n\t\t},\n\n\t\tgestures : function(){\n\t\t\tvar base = this;\n\n\t\t\tvar locals = {\n\t\t\t\toffsetX : 0,\n\t\t\t\toffsetY : 0,\n\t\t\t\tbaseElWidth : 0,\n\t\t\t\trelativePos : 0,\n\t\t\t\tposition: null,\n\t\t\t\tminSwipe : null,\n\t\t\t\tmaxSwipe: null,\n\t\t\t\tsliding : null,\n\t\t\t\ttargetElement : null\n\t\t\t}\n\n\t\t\tbase.isCssFinish = true;\n\n\t\t\tfunction getTouches(event){\n\t\t\t\tif(base.isTouch === true){\n\t\t\t\t\treturn {\n\t\t\t\t\t\tx : event.touches[0].pageX,\n\t\t\t\t\t\ty : event.touches[0].pageY\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif(event.pageX !== undefined){\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tx : event.pageX,\n\t\t\t\t\t\t\ty : event.pageY\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\tx : event.clientX,\n\t\t\t\t\t\t\ty : event.clientY\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfunction swapEvents(type){\n\t\t\t\tif(type === \"on\"){\n\t\t\t\t\t$(document).on(base.ev_types[\"move\"], dragMove);\n\t\t\t\t\t$(document).on(base.ev_types[\"end\"], dragEnd);\n\t\t\t\t} else if(type === \"off\"){\n\t\t\t\t\t$(document).off(base.ev_types[\"move\"]);\n\t\t\t\t\t$(document).off(base.ev_types[\"end\"]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tfunction dragStart(event) {\n\t\t\t\tvar event = event.originalEvent || event || window.event;\n\n\t\t\t\tif(base.isCssFinish === false){\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif(base.isCss3Finish === false){\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tif(base.options.autoPlay !== false){\n\t\t\t\t\tclearInterval(base.autoPlaySpeed);\n\t\t\t\t}\n\n\t\t\t\tif(base.isTouch !== true && !base.owlWrapper.hasClass(\"grabbing\")){\n\t\t\t\t\tbase.owlWrapper.addClass(\"grabbing\")\n\t\t\t\t}\n\n\t\t\t\tbase.newPosX = 0;\n\t\t\t\tbase.newRelativeX = 0;\n\n\t\t\t\t$(this).css(base.removeTransition());\n\n\t\t\t\tvar position = $(this).position();\n\t\t\t\tlocals.relativePos = position.left;\n\t\t\t\t\n\t\t\t\tlocals.offsetX = getTouches(event).x - position.left;\n\t\t\t\tlocals.offsetY = getTouches(event).y - position.top;\n\n\t\t\t\tswapEvents(\"on\");\n\n\t\t\t\tlocals.sliding = false;\n\t\t\t\tlocals.targetElement = event.target || event.srcElement;\n\t\t\t}\n\n\t\t\tfunction dragMove(event){\n\t\t\t\tvar event = event.originalEvent || event || window.event;\n\n\t\t\t\tbase.newPosX = getTouches(event).x- locals.offsetX;\n\t\t\t\tbase.newPosY = getTouches(event).y - locals.offsetY;\n\t\t\t\tbase.newRelativeX = base.newPosX - locals.relativePos;\n\n\t\t\t\tif(base.newRelativeX > 8 || base.newRelativeX < -8 && base.isTouch === true){\n\t\t\t\t\tevent.preventDefault ? event.preventDefault() : event.returnValue = false;\n\t\t\t\t\tlocals.sliding = true;\n\t\t\t\t}\n\n\t\t\t\tif((base.newPosY > 10 || base.newPosY < -10) && locals.sliding === false){\n\t\t\t\t\t $(document).off(\"touchmove.owl\");\n\t\t\t\t}\n\n\t\t\t\tvar minSwipe = function(){\n\t\t\t\t\treturn  base.newRelativeX / 5;\n\t\t\t\t}\n\t\t\t\tvar maxSwipe = function(){\n\t\t\t\t\treturn  base.maximumPixels + base.newRelativeX / 5;\n\t\t\t\t}\n\n\t\t\t\tbase.newPosX = Math.max(Math.min( base.newPosX, minSwipe() ), maxSwipe() );\n\t\t\t\tif(base.support3d === true){\n\t\t\t\t\tbase.transition3d(base.newPosX);\n\t\t\t\t} else {\n\t\t\t\t\tbase.css2move(base.newPosX);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar dragEnd = function(event){\n\t\t\t\tvar event = event.originalEvent || event || window.event;\n\t\t\t\tevent.target = event.target || event.srcElement;\n\n\t\t\t\tif(base.isTouch !== true){\n\t\t\t\t\tbase.owlWrapper.removeClass(\"grabbing\");\n\t\t\t\t}\n\n\t\t\t\tswapEvents(\"off\");\n\n\t\t\t\tif(base.newPosX !== 0){\n\t\t\t\t\tvar newPosition = base.getNewPosition();\n\t\t\t\t\tbase.goTo(newPosition);\n\t\t\t\t\tif(locals.targetElement === event.target && base.isTouch !== true){\n\t\t\t\t\t\t$(event.target).on(\"click.disable\", function(ev){\n\t\t\t\t\t\t\tev.stopImmediatePropagation()\n\t\t\t\t\t\t\tev.stopPropagation();\n\t\t\t\t\t\t\tev.preventDefault();\n\t\t\t\t\t\t\t$(event.target).off(\"click.disable\");\n\t\t\t\t\t\t});\n\t\t\t\t\tvar handlers = $._data(event.target, \"events\")[\"click\"];\n\t\t\t\t\tvar owlStopEvent = handlers.pop();\n\t\t\t\t\thandlers.splice(0, 0, owlStopEvent);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tbase.$elem.on(base.ev_types[\"start\"], \".owl-wrapper\", dragStart); \n\t\t},\n\n\t\tclearEvents : function(){\n\t\t\tvar base = this;\n\t\t\tbase.$elem.off(\".owl\");\n\t\t\t$(document).off(\".owl\");\n\t\t},\n\n\t\tgetNewPosition : function(){\n\t\t\tvar base = this,\n\t\t\t\tnewPosition;\n\n\t\t\tvar newPosition = base.improveClosest();\n\n\t\t\tif(newPosition>base.maximumSlide){\n\t\t\t\tbase.currentSlide = base.maximumSlide;\n\t\t\t\tnewPosition  = base.maximumSlide;\n\t\t\t} else if( base.newPosX >=0 ){\n\t\t\t\tnewPosition = 0;\n\t\t\t\tbase.currentSlide = 0;\n\t\t\t}\n\t\t\treturn newPosition;\n\t\t},\n\n\t\timproveClosest : function(){\n\t\t\tvar base = this;\n\t\t\tvar array = base.positionsInArray;\n\t\t\tvar goal = base.newPosX;\n\t\t\tvar closest = null;\n\t\t\t$.each(array, function(i,v){\n\t\t\t\tif( goal - (base.itemWidth/20) > array[i+1] && goal - (base.itemWidth/20)< v && base.moveDirection() === \"left\") {\n\t\t\t\t\tclosest = v;\n\t\t\t\t\tbase.currentSlide = i;\n\t\t\t\t} \n\t\t\t\telse if (goal + (base.itemWidth/20) < v && goal + (base.itemWidth/20) > array[i+1] && base.moveDirection() === \"right\"){\n\t\t\t\t\tclosest = array[i+1];\n\t\t\t\t\tbase.currentSlide = i+1;\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn base.currentSlide;\n\t\t},\n\n\t\tmoveDirection : function(){\n\t\t\tvar base = this,\n\t\t\t\tdirection;\n\t\t\tif(base.newRelativeX < 0 ){\n\t\t\t\tdirection = \"right\"\n\t\t\t\tbase.playDirection = \"next\"\n\t\t\t} else {\n\t\t\t\tdirection = \"left\"\n\t\t\t\tbase.playDirection = \"prev\"\n\t\t\t}\n\t\t\treturn direction\n\t\t},\n\n\t\tcustomEvents : function(){\n\t\t\tvar base = this;\n\t\t\tbase.$elem.on(\"owl.next\",function(){\n\t\t\t\tbase.next();\n\t\t\t});\n\t\t\tbase.$elem.on(\"owl.prev\",function(){\n\t\t\t\tbase.prev();\n\t\t\t});\n\t\t\tbase.$elem.on(\"owl.play\",function(event,speed){\n\t\t\t\tbase.options.autoPlay = speed;\n\t\t\t\tbase.play();\n\t\t\t\tbase.hoverStatus = \"play\";\n\t\t\t});\n\t\t\tbase.$elem.on(\"owl.stop\",function(){\n\t\t\t\tbase.stop();\n\t\t\t\tbase.hoverStatus = \"stop\";\n\t\t\t});\n\t\t},\n\t\t\n\t\tstopOnHover : function(){\n\t\t\tvar base = this;\n\t\t\tif(base.options.stopOnHover === true && base.isTouch === false && base.options.autoPlay !== false){\n\t\t\t\tbase.$elem.on(\"mouseover\", function(){\n\t\t\t\t\tbase.stop();\n\t\t\t\t});\n\t\t\t\tbase.$elem.on(\"mouseout\", function(){\n\t\t\t\t\tif(base.hoverStatus !== \"stop\"){\n\t\t\t\t\t\tbase.play();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\tlazyLoad : function(){\n\t\t\tvar base = this;\n\n\t\t\tif(base.options.lazyLoad === false){\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor(var i=0; i<base.itemsAmount; i++){\n\t\t\t\tvar item = $(base.owlItems[i]),\n\t\t\t\t\titemNumber = item.data(\"owl-item\"),\n\t\t\t\t\tlazyImg = item.find(\".lazyOwl\"),\n\t\t\t\t\tfollow;\n\n\t\t\t\tif(item.data(\"owl-loaded\") === undefined){\n\t\t\t\t\tlazyImg.hide();\n\t\t\t\t\titem.addClass(\"loading\").data(\"owl-loaded\",\"checked\");\n\t\t\t\t} else if(item.data(\"owl-loaded\") === \"loaded\"){\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif(base.options.lazyFollow === true){\n\t\t\t\t\tfollow = itemNumber >= base.currentSlide;\n\t\t\t\t}else {\n\t\t\t\t\tfollow = true;\n\t\t\t\t}\n\n\t\t\t\tif(follow && itemNumber < base.currentSlide + base.options.items){\n\t\t\t\t\titem.data(\"owl-loaded\", \"loaded\");\n\n\t\t\t\t\tvar link = lazyImg.data(\"src\");\n\t\t\t\t\tif(link){\n\t\t\t\t\t\tlazyImg[0].src = link;\n\t\t\t\t\t\tlazyImg.removeAttr(\"data-src\");\n\t\t\t\t\t}\n\n\t\t\t\t\tlazyImg.fadeIn(200);\n\t\t\t\t\titem.removeClass(\"loading\");\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tautoHeight : function(){\n\t\t\tvar base = this;\n\t\t\tif(base.options.autoHeight === true){\n\t\t\t\tvar itemHeight = $(base.owlItems[base.currentSlide]).css(\"height\");\n\t\t\t\tbase.wrapperOuter.css(\"height\",itemHeight);\n\n\t\t\t\tsetTimeout(function(){\n\t\t\t\t\tif(itemHeight !== $(base.owlItems[base.currentSlide]).css(\"height\")){\n\t\t\t\t\t\tbase.wrapperOuter.css(\"height\",itemHeight);\n\t\t\t\t\t}\n\t\t\t\t},400);\n\n\t\t\t\tsetTimeout(function(){\n\t\t\t\t\tif(!base.wrapperOuter.hasClass(\"autoHeight\")){\n\t\t\t\t\t\tbase.wrapperOuter.addClass(\"autoHeight\");\n\t\t\t\t\t}\n\t\t\t\t},0);\n\t\t\t}\n\t\t},\n\t\taddActiveClass : function(){\n\t\t\tvar base = this;\n\t\t\t$(base.owlItems).removeClass('active');\n\t\t\t$(base.owlItems[base.currentSlide]).addClass('active');\n\t\t}\n\n\t};\n\n\n\t$.fn.owlCarousel = function( options ){\n\t\treturn this.each(function() {\n\t\t\tvar carousel = Object.create( Carousel );\n\t\t\tcarousel.init( options, this );\n\t\t\t$.data( this, \"owlCarousel\", carousel );\n\t\t});\n\t};\n\n\t$.fn.owlCarousel.options = {\n\n\t\titems : 5,\n\t\titemsDesktop : [1199,4],\n\t\titemsDesktopSmall : [979,3],\n\t\titemsTablet: [768,2],\n\t\titemsMobile : [479,1],\n\t\tsingleItem:false,\n\n\t\tslideSpeed : 200,\n\t\tpaginationSpeed : 800,\n\n\t\tautoPlay : false,\n\t\tstopOnHover : false,\n\t\tgoToFirst : true,\n\t\tgoToFirstSpeed : 1000,\n\n\t\tnavigation : false,\n\t\tnavigationText : [\"prev\",\"next\"],\n\t\tgoToFirstNav : true,\n\t\tscrollPerPage : false,\n\n\t\tpagination : true,\n\t\tpaginationNumbers: false,\n\n\t\tresponsive: true,\n\t\tresponsiveRefreshRate : 200,\n\n\t\tbaseClass : \"owl-carousel\",\n\t\ttheme : \"owl-theme\",\n\n\t\tlazyLoad : false,\n\t\tlazyFollow : true,\n\n\t\tautoHeight : false,\n\n\t\tjsonPath : false,\n\t\tjsonSuccess : false,\n\n\t\tmouseDraggable : true,\n\n\t\tbeforeInit : false,\n\t\tafterInit : false,\n\t\tbeforeMove: false,\n\t\tafterMove: false,\n\t\tafterAction : false\n\t};\n})( jQuery, window, document );"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/flatlab/js/sparkline-chart.js",
    "content": "var Script = function () {\n\n    $(\".sparkline\").each(function(){\n        var $data = $(this).data();\n\n        $data.valueSpots = {'0:': $data.spotColor};\n\n        $(this).sparkline( $data.data || \"html\", $data,\n        {\n            tooltipFormat: '<span style=\"display:block; padding:0px 10px 12px 0px;\">' +\n            '<span style=\"color: {{color}}\">&#9679;</span> {{offset:names}} ({{percent.1}}%)</span>'\n        });\n\n\n\n\n    });\n\n//sparkline chart\n\n    $(\"#barchart\").sparkline([5,3,6,7,5,6,4,2,3,4,6,8,9,10,8,6,5,7,6,5,4,7,4], {\n        type: 'bar',\n        height: '65',\n        barWidth: 8,\n        barSpacing: 5,\n        barColor: '#fff'\n//        tooltipFormat: '<span style=\"display:block; padding:0px 10px 12px 0px;\">' +\n//            '<span style=\"color: {{color}}\">&#9679;</span> {{offset:names}} ({{percent.1}}%)</span>'\n\n    });\n\n\n    $(\"#linechart\").sparkline([1,5,3,7,9,3,6,4,7,9,7,6,2], {\n        type: 'line',\n        width: '300',\n        height: '75',\n        fillColor: '',\n        lineColor: '#fff',\n        lineWidth: 2,\n        spotColor: '#fff',\n        minSpotColor: '#fff',\n        maxSpotColor: '#fff',\n        highlightSpotColor: '#fff',\n        highlightLineColor: '#ffffff',\n        spotRadius: 4,\n        highlightLineColor: '#ffffff'\n//        tooltipFormat: '<span style=\"display:block; padding:0px 10px 12px 0px;\">' +\n//            '<span style=\"color: {{color}}\">&#9679;</span> {{offset:names}} ({{percent.1}}%)</span>'\n\n\n\n    });\n\n    $(\"#pie-chart\").sparkline([2,1,1,1], {\n        type: 'pie',\n        width: '100',\n        height: '100',\n        borderColor: '#00bf00',\n        sliceColors: ['#41CAC0', '#A8D76F', '#F8D347', '#EF6F66']\n//        tooltipFormat: '<span style=\"display:block; padding:0px 10px 12px 0px;\">' +\n//            '<span style=\"color: {{color}}\">&#9679;</span> {{offset:names}} ({{percent.1}}%)</span>'\n    });\n\n    //work progress bar\n\n    $(\"#work-progress1\").sparkline([5,6,7,5,9,6,4], {\n        type: 'bar',\n        height: '20',\n        barWidth: 5,\n        barSpacing: 2,\n        barColor: '#5fbf00'\n//        tooltipFormat: '<span style=\"display:block; padding:0px 10px 12px 0px;\">' +\n//            '<span style=\"color: {{color}}\">&#9679;</span> {{offset:names}} ({{percent.1}}%)</span>'\n    });\n\n    $(\"#work-progress2\").sparkline([3,2,5,8,4,7,5], {\n        type: 'bar',\n        height: '22',\n        barWidth: 5,\n        barSpacing: 2,\n        barColor: '#58c9f1'\n//        tooltipFormat: '<span style=\"display:block; padding:0px 10px 12px 0px;\">' +\n//            '<span style=\"color: {{color}}\">&#9679;</span> {{offset:names}} ({{percent.1}}%)</span>'\n    });\n\n    $(\"#work-progress3\").sparkline([1,6,9,3,4,8,5], {\n        type: 'bar',\n        height: '22',\n        barWidth: 5,\n        barSpacing: 2,\n        barColor: '#8075c4'\n//        tooltipFormat: '<span style=\"display:block; padding:0px 10px 12px 0px;\">' +\n//            '<span style=\"color: {{color}}\">&#9679;</span> {{offset:names}} ({{percent.1}}%)</span>'\n    });\n\n    $(\"#work-progress4\").sparkline([9,4,9,6,7,4,3], {\n        type: 'bar',\n        height: '22',\n        barWidth: 5,\n        barSpacing: 2,\n        barColor: '#ff6c60'\n//        tooltipFormat: '<span style=\"display:block; padding:0px 10px 12px 0px;\">' +\n//            '<span style=\"color: {{color}}\">&#9679;</span> {{offset:names}} ({{percent.1}}%)</span>'\n    });\n\n    $(\"#work-progress5\").sparkline([6,8,5,7,6,8,3], {\n        type: 'bar',\n        height: '22',\n        barWidth: 5,\n        barSpacing: 2,\n        barColor: '#41cac0'\n//        tooltipFormat: '<span style=\"display:block; padding:0px 10px 12px 0px;\">' +\n//            '<span style=\"color: {{color}}\">&#9679;</span> {{offset:names}} ({{percent.1}}%)</span>'\n    });\n\n    $(\"#pie-chart2\").sparkline([2,1,1,1], {\n        type: 'pie',\n        width: '250',\n        height: '125',\n        sliceColors: ['#41CAC0', '#A8D76F', '#F8D347', '#EF6F66']\n//        tooltipFormat: '<span style=\"display:block; padding:0px 10px 12px 0px;\">' +\n//    '<span style=\"color: {{color}}\">&#9679;</span> {{offset:names}} ({{percent.1}}%)</span>'});\n\n    });\n\n}();"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/gt.js",
    "content": "/* initGeetest 1.0.0\n * 用于加载id对应的验证码库，并支持宕机模式\n * 暴露 initGeetest 进行验证码的初始化\n * 一般不需要用户进行修改\n */\n(function (global, factory) {\n    \"use strict\";\n    if (typeof module === \"object\" && typeof module.exports === \"object\") {\n        // CommonJS\n        module.exports = global.document ?\n            factory(global, true) :\n            function (w) {\n                if (!w.document) {\n                    throw new Error(\"Geetest requires a window with a document\");\n                }\n                return factory(w);\n            };\n    } else {\n        factory(global);\n    }\n})(typeof window !== \"undefined\" ? window : this, function (window, noGlobal) {\n    \"use strict\";\n    if (typeof window === 'undefined') {\n        throw new Error('Geetest requires browser environment');\n    }\n    var document = window.document;\n    var Math = window.Math;\n    var head = document.getElementsByTagName(\"head\")[0];\n\n    function _Object(obj) {\n        this._obj = obj;\n    }\n\n    _Object.prototype = {\n        _each: function (process) {\n            var _obj = this._obj;\n            for (var k in _obj) {\n                if (_obj.hasOwnProperty(k)) {\n                    process(k, _obj[k]);\n                }\n            }\n            return this;\n        }\n    };\n    function Config(config) {\n        var self = this;\n        new _Object(config)._each(function (key, value) {\n            self[key] = value;\n        });\n    }\n\n    Config.prototype = {\n        api_server: 'api.geetest.com',\n        protocol: 'http://',\n        type_path: '/gettype.php',\n        fallback_config: {\n            slide: {\n                static_servers: [\"static.geetest.com\", \"dn-staticdown.qbox.me\"],\n                type: 'slide',\n                slide: '/static/js/geetest.0.0.0.js'\n            },\n            fullpage: {\n                static_servers: [\"static.geetest.com\", \"dn-staticdown.qbox.me\"],\n                type: 'fullpage',\n                fullpage: '/static/js/fullpage.0.0.0.js'\n            }\n        },\n        _get_fallback_config: function () {\n            var self = this;\n            if (isString(self.type)) {\n                return self.fallback_config[self.type];\n            } else if (self.new_captcha) {\n                return self.fallback_config.fullpage;\n            } else {\n                return self.fallback_config.slide;\n            }\n        },\n        _extend: function (obj) {\n            var self = this;\n            new _Object(obj)._each(function (key, value) {\n                self[key] = value;\n            })\n        }\n    };\n    var isNumber = function (value) {\n        return (typeof value === 'number');\n    };\n    var isString = function (value) {\n        return (typeof value === 'string');\n    };\n    var isBoolean = function (value) {\n        return (typeof value === 'boolean');\n    };\n    var isObject = function (value) {\n        return (typeof value === 'object' && value !== null);\n    };\n    var isFunction = function (value) {\n        return (typeof value === 'function');\n    };\n    var callbacks = {};\n    var status = {};\n    var random = function () {\n        return parseInt(Math.random() * 10000) + (new Date()).valueOf();\n    };\n    var loadScript = function (url, cb) {\n        var script = document.createElement(\"script\");\n        script.charset = \"UTF-8\";\n        script.async = true;\n        script.onerror = function () {\n            cb(true);\n        };\n        var loaded = false;\n        script.onload = script.onreadystatechange = function () {\n            if (!loaded &&\n                (!script.readyState ||\n                \"loaded\" === script.readyState ||\n                \"complete\" === script.readyState)) {\n\n                loaded = true;\n                setTimeout(function () {\n                    cb(false);\n                }, 0);\n            }\n        };\n        script.src = url;\n        head.appendChild(script);\n    };\n    var normalizeDomain = function (domain) {\n        return domain.replace(/^https?:\\/\\/|\\/$/g, '');\n    };\n    var normalizePath = function (path) {\n        path = path.replace(/\\/+/g, '/');\n        if (path.indexOf('/') !== 0) {\n            path = '/' + path;\n        }\n        return path;\n    };\n    var normalizeQuery = function (query) {\n        if (!query) {\n            return '';\n        }\n        var q = '?';\n        new _Object(query)._each(function (key, value) {\n            if (isString(value) || isNumber(value) || isBoolean(value)) {\n                q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';\n            }\n        });\n        if (q === '?') {\n            q = '';\n        }\n        return q.replace(/&$/, '');\n    };\n    var makeURL = function (protocol, domain, path, query) {\n        domain = normalizeDomain(domain);\n\n        var url = normalizePath(path) + normalizeQuery(query);\n        if (domain) {\n            url = protocol + domain + url;\n        }\n\n        return url;\n    };\n    var load = function (protocol, domains, path, query, cb) {\n        var tryRequest = function (at) {\n\n            var url = makeURL(protocol, domains[at], path, query);\n            loadScript(url, function (err) {\n                if (err) {\n                    if (at >= domains.length - 1) {\n                        cb(true);\n                    } else {\n                        tryRequest(at + 1);\n                    }\n                } else {\n                    cb(false);\n                }\n            });\n        };\n        tryRequest(0);\n    };\n    var jsonp = function (domains, path, config, callback) {\n        if (isObject(config.getLib)) {\n            config._extend(config.getLib);\n            callback(config);\n            return;\n        }\n        if (config.offline) {\n            callback(config._get_fallback_config());\n            return;\n        }\n        var cb = \"geetest_\" + random();\n        window[cb] = function (data) {\n            if (data.status === 'success') {\n                callback(data.data);\n            } else if (!data.status) {\n                callback(data);\n            } else {\n                callback(config._get_fallback_config());\n            }\n            window[cb] = undefined;\n            try {\n                delete window[cb];\n            } catch (e) {\n            }\n        };\n        load(config.protocol, domains, path, {\n            gt: config.gt,\n            callback: cb\n        }, function (err) {\n            if (err) {\n                callback(config._get_fallback_config());\n            }\n        });\n    };\n    var throwError = function (errorType, config) {\n        var errors = {\n            networkError: '网络错误'\n        };\n        if (typeof config.onError === 'function') {\n            config.onError(errors[errorType]);\n        } else {\n            throw new Error(errors[errorType]);\n        }\n    };\n    var detect = function () {\n        return !!window.Geetest;\n    };\n    if (detect()) {\n        status.slide = \"loaded\";\n    }\n    var initGeetest = function (userConfig, callback) {\n        var config = new Config(userConfig);\n        if (userConfig.https) {\n            config.protocol = 'https://';\n        } else if (!userConfig.protocol) {\n            config.protocol = window.location.protocol + '//';\n        }\n        jsonp([config.api_server || config.apiserver], config.type_path, config, function (newConfig) {\n            var type = newConfig.type;\n            var init = function () {\n                config._extend(newConfig);\n                callback(new window.Geetest(config));\n            };\n            callbacks[type] = callbacks[type] || [];\n            var s = status[type] || 'init';\n            if (s === 'init') {\n                status[type] = 'loading';\n                callbacks[type].push(init);\n                load(config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) {\n                    if (err) {\n                        status[type] = 'fail';\n                        throwError('networkError', config);\n                    } else {\n                        status[type] = 'loaded';\n                        var cbs = callbacks[type];\n                        for (var i = 0, len = cbs.length; i < len; i = i + 1) {\n                            var cb = cbs[i];\n                            if (isFunction(cb)) {\n                                cb();\n                            }\n                        }\n                        callbacks[type] = [];\n                    }\n                });\n            } else if (s === \"loaded\") {\n                init();\n            } else if (s === \"fail\") {\n                throwError('networkError', config);\n            } else if (s === \"loading\") {\n                callbacks[type].push(init);\n            }\n        });\n    };\n    window.initGeetest = initGeetest;\n    return initGeetest;\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/html5shiv.js",
    "content": "/*\n HTML5 Shiv v3.7.0 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed\n*/\n(function(l,f){function m(){var a=e.elements;return\"string\"==typeof a?a.split(\" \"):a}function i(a){var b=n[a[o]];b||(b={},h++,a[o]=h,n[h]=b);return b}function p(a,b,c){b||(b=f);if(g)return b.createElement(a);c||(c=i(b));b=c.cache[a]?c.cache[a].cloneNode():r.test(a)?(c.cache[a]=c.createElem(a)).cloneNode():c.createElem(a);return b.canHaveChildren&&!s.test(a)?c.frag.appendChild(b):b}function t(a,b){if(!b.cache)b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag();\na.createElement=function(c){return!e.shivMethods?b.createElem(c):p(c,a,b)};a.createDocumentFragment=Function(\"h,f\",\"return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&(\"+m().join().replace(/[\\w\\-]+/g,function(a){b.createElem(a);b.frag.createElement(a);return'c(\"'+a+'\")'})+\");return n}\")(e,b.frag)}function q(a){a||(a=f);var b=i(a);if(e.shivCSS&&!j&&!b.hasCSS){var c,d=a;c=d.createElement(\"p\");d=d.getElementsByTagName(\"head\")[0]||d.documentElement;c.innerHTML=\"x<style>article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}</style>\";\nc=d.insertBefore(c.lastChild,d.firstChild);b.hasCSS=!!c}g||t(a,b);return a}var k=l.html5||{},s=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,r=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,j,o=\"_html5shiv\",h=0,n={},g;(function(){try{var a=f.createElement(\"a\");a.innerHTML=\"<xyz></xyz>\";j=\"hidden\"in a;var b;if(!(b=1==a.childNodes.length)){f.createElement(\"a\");var c=f.createDocumentFragment();b=\"undefined\"==typeof c.cloneNode||\n\"undefined\"==typeof c.createDocumentFragment||\"undefined\"==typeof c.createElement}g=b}catch(d){g=j=!0}})();var e={elements:k.elements||\"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output progress section summary template time video\",version:\"3.7.0\",shivCSS:!1!==k.shivCSS,supportsUnknownElements:g,shivMethods:!1!==k.shivMethods,type:\"default\",shivDocument:q,createElement:p,createDocumentFragment:function(a,b){a||(a=f);\nif(g)return a.createDocumentFragment();for(var b=b||i(a),c=b.frag.cloneNode(),d=0,e=m(),h=e.length;d<h;d++)c.createElement(e[d]);return c}};l.html5=e;q(f)})(this,document);\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/jQuery.print.js",
    "content": "/* @license \n * jQuery.print, version 1.5.1\n *  (c) Sathvik Ponangi, Doers' Guild\n * Licence: CC-By (http://creativecommons.org/licenses/by/3.0/)\n *--------------------------------------------------------------------------*/\n(function ($) {\n    \"use strict\";\n    // A nice closure for our definitions\n    function getjQueryObject(string) {\n        // Make string a vaild jQuery thing\n        var jqObj = $(\"\");\n        try {\n            jqObj = $(string)\n                .clone();\n        } catch (e) {\n            jqObj = $(\"<span />\")\n                .html(string);\n        }\n        return jqObj;\n    }\n\n    function printFrame(frameWindow, content, options) {\n        // Print the selected window/iframe\n        var def = $.Deferred();\n        try {\n            frameWindow = frameWindow.contentWindow || frameWindow.contentDocument || frameWindow;\n            var wdoc = frameWindow.document || frameWindow.contentDocument || frameWindow;\n            if(options.doctype) {\n                wdoc.write(options.doctype);\n            }\n            wdoc.write(content);\n            wdoc.close();\n            var printed = false;\n            var callPrint = function () {\n                if(printed) {\n                    return;\n                }\n                // Fix for IE : Allow it to render the iframe\n                frameWindow.focus();\n                try {\n                    // Fix for IE11 - printng the whole page instead of the iframe content\n                    if (!frameWindow.document.execCommand('print', false, null)) {\n                        // document.execCommand returns false if it failed -http://stackoverflow.com/a/21336448/937891\n                        frameWindow.print();\n                    }\n                    // focus body as it is losing focus in iPad and content not getting printed\n                    $('body').focus();\n                } catch (e) {\n                    frameWindow.print();\n                }\n                frameWindow.close();\n                printed = true;\n                def.resolve();\n            }\n            // Print once the frame window loads - seems to work for the new-window option but unreliable for the iframe\n            $(frameWindow).on(\"load\", callPrint);\n            // Fallback to printing directly if the frame doesn't fire the load event for whatever reason\n            setTimeout(callPrint, options.timeout);\n        } catch (err) {\n            def.reject(err);\n        }\n        return def;\n    }\n\n    function printContentInIFrame(content, options) {\n        var $iframe = $(options.iframe + \"\");\n        var iframeCount = $iframe.length;\n        if (iframeCount === 0) {\n            // Create a new iFrame if none is given\n            $iframe = $('<iframe height=\"0\" width=\"0\" border=\"0\" wmode=\"Opaque\"/>')\n                .prependTo('body')\n                .css({\n                    \"position\": \"absolute\",\n                    \"top\": -999,\n                    \"left\": -999\n                });\n        }\n        var frameWindow = $iframe.get(0);\n        return printFrame(frameWindow, content, options)\n            .done(function () {\n                // Success\n                setTimeout(function () {\n                    // Wait for IE\n                    if (iframeCount === 0) {\n                        // Destroy the iframe if created here\n                        $iframe.remove();\n                    }\n                }, 1000);\n            })\n            .fail(function (err) {\n                // Use the pop-up method if iframe fails for some reason\n                console.error(\"Failed to print from iframe\", err);\n                printContentInNewWindow(content, options);\n            })\n            .always(function () {\n                try {\n                    options.deferred.resolve();\n                } catch (err) {\n                    console.warn('Error notifying deferred', err);\n                }\n            });\n    }\n\n    function printContentInNewWindow(content, options) {\n        // Open a new window and print selected content\n        var frameWindow = window.open();\n        return printFrame(frameWindow, content, options)\n            .always(function () {\n                try {\n                    options.deferred.resolve();\n                } catch (err) {\n                    console.warn('Error notifying deferred', err);\n                }\n            });\n    }\n\n    function isNode(o) {\n        /* http://stackoverflow.com/a/384380/937891 */\n        return !!(typeof Node === \"object\" ? o instanceof Node : o && typeof o === \"object\" && typeof o.nodeType === \"number\" && typeof o.nodeName === \"string\");\n    }\n    $.print = $.fn.print = function () {\n        // Print a given set of elements\n        var options, $this, self = this;\n        // console.log(\"Printing\", this, arguments);\n        if (self instanceof $) {\n            // Get the node if it is a jQuery object\n            self = self.get(0);\n        }\n        if (isNode(self)) {\n            // If `this` is a HTML element, i.e. for\n            // $(selector).print()\n            $this = $(self);\n            if (arguments.length > 0) {\n                options = arguments[0];\n            }\n        } else {\n            if (arguments.length > 0) {\n                // $.print(selector,options)\n                $this = $(arguments[0]);\n                if (isNode($this[0])) {\n                    if (arguments.length > 1) {\n                        options = arguments[1];\n                    }\n                } else {\n                    // $.print(options)\n                    options = arguments[0];\n                    $this = $(\"html\");\n                }\n            } else {\n                // $.print()\n                $this = $(\"html\");\n            }\n        }\n        // Default options\n        var defaults = {\n            globalStyles: true,\n            mediaPrint: false,\n            stylesheet: null,\n            noPrintSelector: \".no-print\",\n            iframe: true,\n            append: null,\n            prepend: null,\n            manuallyCopyFormValues: true,\n            deferred: $.Deferred(),\n            timeout: 750,\n            title: null,\n            doctype: '<!doctype html>'\n        };\n        // Merge with user-options\n        options = $.extend({}, defaults, (options || {}));\n        var $styles = $(\"\");\n        if (options.globalStyles) {\n            // Apply the stlyes from the current sheet to the printed page\n            $styles = $(\"style, link, meta, base, title\");\n        } else if (options.mediaPrint) {\n            // Apply the media-print stylesheet\n            $styles = $(\"link[media=print]\");\n        }\n        if (options.stylesheet) {\n            // Add a custom stylesheet if given\n            $styles = $.merge($styles, $('<link rel=\"stylesheet\" href=\"' + options.stylesheet + '\">'));\n        }\n        // Create a copy of the element to print\n        var copy = $this.clone();\n        // Wrap it in a span to get the HTML markup string\n        copy = $(\"<span/>\")\n            .append(copy);\n        // Remove unwanted elements\n        copy.find(options.noPrintSelector)\n            .remove();\n        // Add in the styles\n        copy.append($styles.clone());\n        // Update title\n        if (options.title) {\n            var title = $(\"title\", copy);\n            if (title.length === 0) {\n                title = $(\"<title />\");\n                copy.append(title);                \n            }\n            title.text(options.title);            \n        }\n        // Appedned content\n        copy.append(getjQueryObject(options.append));\n        // Prepended content\n        copy.prepend(getjQueryObject(options.prepend));\n        if (options.manuallyCopyFormValues) {\n            // Manually copy form values into the HTML for printing user-modified input fields\n            // http://stackoverflow.com/a/26707753\n            copy.find(\"input\")\n                .each(function () {\n                    var $field = $(this);\n                    if ($field.is(\"[type='radio']\") || $field.is(\"[type='checkbox']\")) {\n                        if ($field.prop(\"checked\")) {\n                            $field.attr(\"checked\", \"checked\");\n                        }\n                    } else {\n                        $field.attr(\"value\", $field.val());\n                    }\n                });\n            copy.find(\"select\").each(function () {\n                var $field = $(this);\n                $field.find(\":selected\").attr(\"selected\", \"selected\");\n            });\n            copy.find(\"textarea\").each(function () {\n                // Fix for https://github.com/DoersGuild/jQuery.print/issues/18#issuecomment-96451589\n                var $field = $(this);\n                $field.text($field.val());\n            });\n        }\n        // Get the HTML markup string\n        var content = copy.html();\n        // Notify with generated markup & cloned elements - useful for logging, etc\n        try {\n            options.deferred.notify('generated_markup', content, copy);\n        } catch (err) {\n            console.warn('Error notifying deferred', err);\n        }\n        // Destroy the copy\n        copy.remove();\n        if (options.iframe) {\n            // Use an iframe for printing\n            try {\n                printContentInIFrame(content, options);\n            } catch (e) {\n                // Use the pop-up method if iframe fails for some reason\n                console.error(\"Failed to print from iframe\", e.stack, e.message);\n                printContentInNewWindow(content, options);\n            }\n        } else {\n            // Use a new window for printing\n            printContentInNewWindow(content, options);\n        }\n        return this;\n    };\n})(jQuery);\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/jquery/1.9.1/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v1.9.1\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2013-2-4\n */\n(function( window, undefined ) {\n\n// Can't do this because several apps including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n// Support: Firefox 18+\n//\"use strict\";\nvar\n\t// The deferred used on DOM ready\n\treadyList,\n\n\t// A central reference to the root jQuery(document)\n\trootjQuery,\n\n\t// Support: IE<9\n\t// For `typeof node.method` instead of `node.method !== undefined`\n\tcore_strundefined = typeof undefined,\n\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\tlocation = window.location,\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$,\n\n\t// [[Class]] -> type pairs\n\tclass2type = {},\n\n\t// List of deleted data cache ids, so we can reuse them\n\tcore_deletedIds = [],\n\n\tcore_version = \"1.9.1\",\n\n\t// Save a reference to some core methods\n\tcore_concat = core_deletedIds.concat,\n\tcore_push = core_deletedIds.push,\n\tcore_slice = core_deletedIds.slice,\n\tcore_indexOf = core_deletedIds.indexOf,\n\tcore_toString = class2type.toString,\n\tcore_hasOwn = class2type.hasOwnProperty,\n\tcore_trim = core_version.trim,\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n\t},\n\n\t// Used for matching numbers\n\tcore_pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,\n\n\t// Used for splitting on whitespace\n\tcore_rnotwhite = /\\S+/g,\n\n\t// Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE)\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\t// Match a standalone tag\n\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\n\n\t// JSON RegExp\n\trvalidchars = /^[\\],:{}\\s]*$/,\n\trvalidbraces = /(?:^|:|,)(?:\\s*\\[)+/g,\n\trvalidescape = /\\\\(?:[\"\\\\\\/bfnrt]|u[\\da-fA-F]{4})/g,\n\trvalidtokens = /\"[^\"\\\\\\r\\n]*\"|true|false|null|-?(?:\\d+\\.|)\\d+(?:[eE][+-]?\\d+|)/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t},\n\n\t// The ready event handler\n\tcompleted = function( event ) {\n\n\t\t// readyState === \"complete\" is good enough for us to call the dom ready in oldIE\n\t\tif ( document.addEventListener || event.type === \"load\" || document.readyState === \"complete\" ) {\n\t\t\tdetach();\n\t\t\tjQuery.ready();\n\t\t}\n\t},\n\t// Clean-up method for dom ready events\n\tdetach = function() {\n\t\tif ( document.addEventListener ) {\n\t\t\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\t\t\twindow.removeEventListener( \"load\", completed, false );\n\n\t\t} else {\n\t\t\tdocument.detachEvent( \"onreadystatechange\", completed );\n\t\t\twindow.detachEvent( \"onload\", completed );\n\t\t}\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: core_version,\n\n\tconstructor: jQuery,\n\tinit: function( selector, context, rootjQuery ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector.charAt(0) === \"<\" && selector.charAt( selector.length - 1 ) === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// scripts is true for back-compat\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE and Opera return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id !== match[2] ) {\n\t\t\t\t\t\t\treturn rootjQuery.find( selector );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Otherwise, we inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn rootjQuery.ready( selector );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t},\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\t// The number of elements contained in the matched element set\n\tsize: function() {\n\t\treturn this.length;\n\t},\n\n\ttoArray: function() {\n\t\treturn core_slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num == null ?\n\n\t\t\t// Return a 'clean' array\n\t\t\tthis.toArray() :\n\n\t\t\t// Return just the object\n\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tready: function( fn ) {\n\t\t// Add the callback\n\t\tjQuery.ready.promise().done( fn );\n\n\t\treturn this;\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( core_slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: core_push,\n\tsort: [].sort,\n\tsplice: [].splice\n};\n\n// Give the init function the jQuery prototype for later instantiation\njQuery.fn.init.prototype = jQuery.fn;\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar src, copyIsArray, copy, name, options, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\t\ttarget = arguments[1] || {};\n\t\t// skip the boolean and the target\n\t\ti = 2;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// extend jQuery itself if only one argument is passed\n\tif ( length === i ) {\n\t\ttarget = this;\n\t\t--i;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\tnoConflict: function( deep ) {\n\t\tif ( window.$ === jQuery ) {\n\t\t\twindow.$ = _$;\n\t\t}\n\n\t\tif ( deep && window.jQuery === jQuery ) {\n\t\t\twindow.jQuery = _jQuery;\n\t\t}\n\n\t\treturn jQuery;\n\t},\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).\n\t\tif ( !document.body ) {\n\t\t\treturn setTimeout( jQuery.ready );\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.trigger ) {\n\t\t\tjQuery( document ).trigger(\"ready\").off(\"ready\");\n\t\t}\n\t},\n\n\t// See test/unit/core.js for details concerning isFunction.\n\t// Since version 1.3, DOM methods and functions like alert\n\t// aren't supported. They return false on IE (#2968).\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray || function( obj ) {\n\t\treturn jQuery.type(obj) === \"array\";\n\t},\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj == obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn String( obj );\n\t\t}\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ core_toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Must be an Object.\n\t\t// Because of IE, we also have to check the presence of the constructor property.\n\t\t// Make sure that DOM nodes and window objects don't pass through, as well\n\t\tif ( !obj || jQuery.type(obj) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\ttry {\n\t\t\t// Not own constructor property must be Object\n\t\t\tif ( obj.constructor &&\n\t\t\t\t!core_hasOwn.call(obj, \"constructor\") &&\n\t\t\t\t!core_hasOwn.call(obj.constructor.prototype, \"isPrototypeOf\") ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} catch ( e ) {\n\t\t\t// IE8,9 Will throw exceptions on certain host objects #9897\n\t\t\treturn false;\n\t\t}\n\n\t\t// Own properties are enumerated firstly, so to speed up,\n\t\t// if last one is own, then all properties are own.\n\n\t\tvar key;\n\t\tfor ( key in obj ) {}\n\n\t\treturn key === undefined || core_hasOwn.call( obj, key );\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\t// data: string of html\n\t// context (optional): If specified, the fragment will be created in this context, defaults to document\n\t// keepScripts (optional): If true, will include scripts passed in the html string\n\tparseHTML: function( data, context, keepScripts ) {\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\t\tif ( typeof context === \"boolean\" ) {\n\t\t\tkeepScripts = context;\n\t\t\tcontext = false;\n\t\t}\n\t\tcontext = context || document;\n\n\t\tvar parsed = rsingleTag.exec( data ),\n\t\t\tscripts = !keepScripts && [];\n\n\t\t// Single tag\n\t\tif ( parsed ) {\n\t\t\treturn [ context.createElement( parsed[1] ) ];\n\t\t}\n\n\t\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n\t\tif ( scripts ) {\n\t\t\tjQuery( scripts ).remove();\n\t\t}\n\t\treturn jQuery.merge( [], parsed.childNodes );\n\t},\n\n\tparseJSON: function( data ) {\n\t\t// Attempt to parse using the native JSON parser first\n\t\tif ( window.JSON && window.JSON.parse ) {\n\t\t\treturn window.JSON.parse( data );\n\t\t}\n\n\t\tif ( data === null ) {\n\t\t\treturn data;\n\t\t}\n\n\t\tif ( typeof data === \"string\" ) {\n\n\t\t\t// Make sure leading/trailing whitespace is removed (IE can't handle it)\n\t\t\tdata = jQuery.trim( data );\n\n\t\t\tif ( data ) {\n\t\t\t\t// Make sure the incoming data is actual JSON\n\t\t\t\t// Logic borrowed from http://json.org/json2.js\n\t\t\t\tif ( rvalidchars.test( data.replace( rvalidescape, \"@\" )\n\t\t\t\t\t.replace( rvalidtokens, \"]\" )\n\t\t\t\t\t.replace( rvalidbraces, \"\")) ) {\n\n\t\t\t\t\treturn ( new Function( \"return \" + data ) )();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tjQuery.error( \"Invalid JSON: \" + data );\n\t},\n\n\t// Cross-browser xml parsing\n\tparseXML: function( data ) {\n\t\tvar xml, tmp;\n\t\tif ( !data || typeof data !== \"string\" ) {\n\t\t\treturn null;\n\t\t}\n\t\ttry {\n\t\t\tif ( window.DOMParser ) { // Standard\n\t\t\t\ttmp = new DOMParser();\n\t\t\t\txml = tmp.parseFromString( data , \"text/xml\" );\n\t\t\t} else { // IE\n\t\t\t\txml = new ActiveXObject( \"Microsoft.XMLDOM\" );\n\t\t\t\txml.async = \"false\";\n\t\t\t\txml.loadXML( data );\n\t\t\t}\n\t\t} catch( e ) {\n\t\t\txml = undefined;\n\t\t}\n\t\tif ( !xml || !xml.documentElement || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\t\tjQuery.error( \"Invalid XML: \" + data );\n\t\t}\n\t\treturn xml;\n\t},\n\n\tnoop: function() {},\n\n\t// Evaluates a script in a global context\n\t// Workarounds based on findings by Jim Driscoll\n\t// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context\n\tglobalEval: function( data ) {\n\t\tif ( data && jQuery.trim( data ) ) {\n\t\t\t// We use execScript on Internet Explorer\n\t\t\t// We use an anonymous function so that context is window\n\t\t\t// rather than jQuery in Firefox\n\t\t\t( window.execScript || function( data ) {\n\t\t\t\twindow[ \"eval\" ].call( window, data );\n\t\t\t} )( data );\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Use native String.trim function wherever possible\n\ttrim: core_trim && !core_trim.call(\"\\uFEFF\\xA0\") ?\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\tcore_trim.call( text );\n\t\t} :\n\n\t\t// Otherwise use our own trimming functionality\n\t\tfunction( text ) {\n\t\t\treturn text == null ?\n\t\t\t\t\"\" :\n\t\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tcore_push.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\tvar len;\n\n\t\tif ( arr ) {\n\t\t\tif ( core_indexOf ) {\n\t\t\t\treturn core_indexOf.call( arr, elem, i );\n\t\t\t}\n\n\t\t\tlen = arr.length;\n\t\t\ti = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t// Skip accessing in sparse arrays\n\t\t\t\tif ( i in arr && arr[ i ] === elem ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn -1;\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar l = second.length,\n\t\t\ti = first.length,\n\t\t\tj = 0;\n\n\t\tif ( typeof l === \"number\" ) {\n\t\t\tfor ( ; j < l; j++ ) {\n\t\t\t\tfirst[ i++ ] = second[ j ];\n\t\t\t}\n\t\t} else {\n\t\t\twhile ( second[j] !== undefined ) {\n\t\t\t\tfirst[ i++ ] = second[ j++ ];\n\t\t\t}\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, inv ) {\n\t\tvar retVal,\n\t\t\tret = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length;\n\t\tinv = !!inv;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tretVal = !!callback( elems[ i ], i );\n\t\t\tif ( inv !== retVal ) {\n\t\t\t\tret.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret[ ret.length ] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn core_concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar args, proxy, tmp;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = core_slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\t// Multifunctional method to get and set values of a collection\n\t// The value/s can optionally be executed if it's a function\n\taccess: function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\t\tvar i = 0,\n\t\t\tlength = elems.length,\n\t\t\tbulk = key == null;\n\n\t\t// Sets many values\n\t\tif ( jQuery.type( key ) === \"object\" ) {\n\t\t\tchainable = true;\n\t\t\tfor ( i in key ) {\n\t\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t\t}\n\n\t\t// Sets one value\n\t\t} else if ( value !== undefined ) {\n\t\t\tchainable = true;\n\n\t\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\t\traw = true;\n\t\t\t}\n\n\t\t\tif ( bulk ) {\n\t\t\t\t// Bulk operations run against the entire set\n\t\t\t\tif ( raw ) {\n\t\t\t\t\tfn.call( elems, value );\n\t\t\t\t\tfn = null;\n\n\t\t\t\t// ...except when executing function values\n\t\t\t\t} else {\n\t\t\t\t\tbulk = fn;\n\t\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( fn ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn chainable ?\n\t\t\telems :\n\n\t\t\t// Gets\n\t\t\tbulk ?\n\t\t\t\tfn.call( elems ) :\n\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n\t},\n\n\tnow: function() {\n\t\treturn ( new Date() ).getTime();\n\t}\n});\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// we once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t// Standards-based browsers support DOMContentLoaded\n\t\t} else if ( document.addEventListener ) {\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\n\t\t// If IE event model is used\n\t\t} else {\n\t\t\t// Ensure firing before onload, maybe late but safe also for iframes\n\t\t\tdocument.attachEvent( \"onreadystatechange\", completed );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.attachEvent( \"onload\", completed );\n\n\t\t\t// If IE and not a frame\n\t\t\t// continually check to see if the document is ready\n\t\t\tvar top = false;\n\n\t\t\ttry {\n\t\t\t\ttop = window.frameElement == null && document.documentElement;\n\t\t\t} catch(e) {}\n\n\t\t\tif ( top && top.doScroll ) {\n\t\t\t\t(function doScrollCheck() {\n\t\t\t\t\tif ( !jQuery.isReady ) {\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Use the trick by Diego Perini\n\t\t\t\t\t\t\t// http://javascript.nwbox.com/IEContentLoaded/\n\t\t\t\t\t\t\ttop.doScroll(\"left\");\n\t\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t\treturn setTimeout( doScrollCheck, 50 );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// detach all dom ready events\n\t\t\t\t\t\tdetach();\n\n\t\t\t\t\t\t// and execute any waiting functions\n\t\t\t\t\t\tjQuery.ready();\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t}\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\tvar length = obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || type !== \"function\" &&\n\t\t( length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj );\n}\n\n// All jQuery objects should point back to these\nrootjQuery = jQuery(document);\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\t\t// Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\targs = args || [];\n\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar action = tuple[ 0 ],\n\t\t\t\t\t\t\t\tfn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ action + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = core_slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;\n\t\t\t\t\tif( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// if we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\njQuery.support = (function() {\n\n\tvar support, all, a,\n\t\tinput, select, fragment,\n\t\topt, eventName, isSupported, i,\n\t\tdiv = document.createElement(\"div\");\n\n\t// Setup\n\tdiv.setAttribute( \"className\", \"t\" );\n\tdiv.innerHTML = \"  <link/><table></table><a href='/a'>a</a><input type='checkbox'/>\";\n\n\t// Support tests won't run in some limited or non-browser environments\n\tall = div.getElementsByTagName(\"*\");\n\ta = div.getElementsByTagName(\"a\")[ 0 ];\n\tif ( !all || !a || !all.length ) {\n\t\treturn {};\n\t}\n\n\t// First batch of tests\n\tselect = document.createElement(\"select\");\n\topt = select.appendChild( document.createElement(\"option\") );\n\tinput = div.getElementsByTagName(\"input\")[ 0 ];\n\n\ta.style.cssText = \"top:1px;float:left;opacity:.5\";\n\tsupport = {\n\t\t// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)\n\t\tgetSetAttribute: div.className !== \"t\",\n\n\t\t// IE strips leading whitespace when .innerHTML is used\n\t\tleadingWhitespace: div.firstChild.nodeType === 3,\n\n\t\t// Make sure that tbody elements aren't automatically inserted\n\t\t// IE will insert them into empty tables\n\t\ttbody: !div.getElementsByTagName(\"tbody\").length,\n\n\t\t// Make sure that link elements get serialized correctly by innerHTML\n\t\t// This requires a wrapper element in IE\n\t\thtmlSerialize: !!div.getElementsByTagName(\"link\").length,\n\n\t\t// Get the style information from getAttribute\n\t\t// (IE uses .cssText instead)\n\t\tstyle: /top/.test( a.getAttribute(\"style\") ),\n\n\t\t// Make sure that URLs aren't manipulated\n\t\t// (IE normalizes it by default)\n\t\threfNormalized: a.getAttribute(\"href\") === \"/a\",\n\n\t\t// Make sure that element opacity exists\n\t\t// (IE uses filter instead)\n\t\t// Use a regex to work around a WebKit issue. See #5145\n\t\topacity: /^0.5/.test( a.style.opacity ),\n\n\t\t// Verify style float existence\n\t\t// (IE uses styleFloat instead of cssFloat)\n\t\tcssFloat: !!a.style.cssFloat,\n\n\t\t// Check the default checkbox/radio value (\"\" on WebKit; \"on\" elsewhere)\n\t\tcheckOn: !!input.value,\n\n\t\t// Make sure that a selected-by-default option has a working selected property.\n\t\t// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)\n\t\toptSelected: opt.selected,\n\n\t\t// Tests for enctype support on a form (#6743)\n\t\tenctype: !!document.createElement(\"form\").enctype,\n\n\t\t// Makes sure cloning an html5 element does not cause problems\n\t\t// Where outerHTML is undefined, this still works\n\t\thtml5Clone: document.createElement(\"nav\").cloneNode( true ).outerHTML !== \"<:nav></:nav>\",\n\n\t\t// jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode\n\t\tboxModel: document.compatMode === \"CSS1Compat\",\n\n\t\t// Will be defined later\n\t\tdeleteExpando: true,\n\t\tnoCloneEvent: true,\n\t\tinlineBlockNeedsLayout: false,\n\t\tshrinkWrapBlocks: false,\n\t\treliableMarginRight: true,\n\t\tboxSizingReliable: true,\n\t\tpixelPosition: false\n\t};\n\n\t// Make sure checked status is properly cloned\n\tinput.checked = true;\n\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n\n\t// Make sure that the options inside disabled selects aren't marked as disabled\n\t// (WebKit marks them as disabled)\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE<9\n\ttry {\n\t\tdelete div.test;\n\t} catch( e ) {\n\t\tsupport.deleteExpando = false;\n\t}\n\n\t// Check if we can trust getAttribute(\"value\")\n\tinput = document.createElement(\"input\");\n\tinput.setAttribute( \"value\", \"\" );\n\tsupport.input = input.getAttribute( \"value\" ) === \"\";\n\n\t// Check if an input maintains its value after becoming a radio\n\tinput.value = \"t\";\n\tinput.setAttribute( \"type\", \"radio\" );\n\tsupport.radioValue = input.value === \"t\";\n\n\t// #11217 - WebKit loses check when the name is after the checked attribute\n\tinput.setAttribute( \"checked\", \"t\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tfragment = document.createDocumentFragment();\n\tfragment.appendChild( input );\n\n\t// Check if a disconnected checkbox will retain its checked\n\t// value of true after appended to the DOM (IE6/7)\n\tsupport.appendChecked = input.checked;\n\n\t// WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<9\n\t// Opera does not clone events (and typeof div.attachEvent === undefined).\n\t// IE9-10 clones events bound via attachEvent, but they don't trigger with .click()\n\tif ( div.attachEvent ) {\n\t\tdiv.attachEvent( \"onclick\", function() {\n\t\t\tsupport.noCloneEvent = false;\n\t\t});\n\n\t\tdiv.cloneNode( true ).click();\n\t}\n\n\t// Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event)\n\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php\n\tfor ( i in { submit: true, change: true, focusin: true }) {\n\t\tdiv.setAttribute( eventName = \"on\" + i, \"t\" );\n\n\t\tsupport[ i + \"Bubbles\" ] = eventName in window || div.attributes[ eventName ].expando === false;\n\t}\n\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\t// Run tests that need a body at doc ready\n\tjQuery(function() {\n\t\tvar container, marginDiv, tds,\n\t\t\tdivReset = \"padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;\",\n\t\t\tbody = document.getElementsByTagName(\"body\")[0];\n\n\t\tif ( !body ) {\n\t\t\t// Return for frameset docs that don't have a body\n\t\t\treturn;\n\t\t}\n\n\t\tcontainer = document.createElement(\"div\");\n\t\tcontainer.style.cssText = \"border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px\";\n\n\t\tbody.appendChild( container ).appendChild( div );\n\n\t\t// Support: IE8\n\t\t// Check if table cells still have offsetWidth/Height when they are set\n\t\t// to display:none and there are still other visible table cells in a\n\t\t// table row; if so, offsetWidth/Height are not reliable for use when\n\t\t// determining if an element has been hidden directly using\n\t\t// display:none (it is still safe to use offsets if a parent element is\n\t\t// hidden; don safety goggles and see bug #4512 for more information).\n\t\tdiv.innerHTML = \"<table><tr><td></td><td>t</td></tr></table>\";\n\t\ttds = div.getElementsByTagName(\"td\");\n\t\ttds[ 0 ].style.cssText = \"padding:0;margin:0;border:0;display:none\";\n\t\tisSupported = ( tds[ 0 ].offsetHeight === 0 );\n\n\t\ttds[ 0 ].style.display = \"\";\n\t\ttds[ 1 ].style.display = \"none\";\n\n\t\t// Support: IE8\n\t\t// Check if empty table cells still have offsetWidth/Height\n\t\tsupport.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );\n\n\t\t// Check box-sizing and margin behavior\n\t\tdiv.innerHTML = \"\";\n\t\tdiv.style.cssText = \"box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;\";\n\t\tsupport.boxSizing = ( div.offsetWidth === 4 );\n\t\tsupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 );\n\n\t\t// Use window.getComputedStyle because jsdom on node.js will break without it.\n\t\tif ( window.getComputedStyle ) {\n\t\t\tsupport.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== \"1%\";\n\t\t\tsupport.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: \"4px\" } ).width === \"4px\";\n\n\t\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t\t// gets computed margin-right based on width of container. (#3333)\n\t\t\t// Fails in WebKit before Feb 2011 nightlies\n\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\tmarginDiv = div.appendChild( document.createElement(\"div\") );\n\t\t\tmarginDiv.style.cssText = div.style.cssText = divReset;\n\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\tdiv.style.width = \"1px\";\n\n\t\t\tsupport.reliableMarginRight =\n\t\t\t\t!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );\n\t\t}\n\n\t\tif ( typeof div.style.zoom !== core_strundefined ) {\n\t\t\t// Support: IE<8\n\t\t\t// Check if natively block-level elements act like inline-block\n\t\t\t// elements when setting their display to 'inline' and giving\n\t\t\t// them layout\n\t\t\tdiv.innerHTML = \"\";\n\t\t\tdiv.style.cssText = divReset + \"width:1px;padding:1px;display:inline;zoom:1\";\n\t\t\tsupport.inlineBlockNeedsLayout = ( div.offsetWidth === 3 );\n\n\t\t\t// Support: IE6\n\t\t\t// Check if elements with layout shrink-wrap their children\n\t\t\tdiv.style.display = \"block\";\n\t\t\tdiv.innerHTML = \"<div></div>\";\n\t\t\tdiv.firstChild.style.width = \"5px\";\n\t\t\tsupport.shrinkWrapBlocks = ( div.offsetWidth !== 3 );\n\n\t\t\tif ( support.inlineBlockNeedsLayout ) {\n\t\t\t\t// Prevent IE 6 from affecting layout for positioned elements #11048\n\t\t\t\t// Prevent IE from shrinking the body in IE 7 mode #12869\n\t\t\t\t// Support: IE<8\n\t\t\t\tbody.style.zoom = 1;\n\t\t\t}\n\t\t}\n\n\t\tbody.removeChild( container );\n\n\t\t// Null elements to avoid leaks in IE\n\t\tcontainer = div = tds = marginDiv = null;\n\t});\n\n\t// Null elements to avoid leaks in IE\n\tall = select = fragment = opt = a = input = null;\n\n\treturn support;\n})();\n\nvar rbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction internalData( elem, name, data, pvt /* Internal Use Only */ ){\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar thisCache, ret,\n\t\tinternalKey = jQuery.expando,\n\t\tgetByName = typeof name === \"string\",\n\n\t\t// We have to handle DOM nodes and JS objects differently because IE6-7\n\t\t// can't GC object references properly across the DOM-JS boundary\n\t\tisNode = elem.nodeType,\n\n\t\t// Only DOM nodes need the global jQuery cache; JS object data is\n\t\t// attached directly to the object so GC can occur automatically\n\t\tcache = isNode ? jQuery.cache : elem,\n\n\t\t// Only defining an ID for JS objects if its cache already exists allows\n\t\t// the code to shortcut on the same path as a DOM node with no cache\n\t\tid = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;\n\n\t// Avoid doing any more work than we need to when trying to get data on an\n\t// object that has no data at all\n\tif ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) {\n\t\treturn;\n\t}\n\n\tif ( !id ) {\n\t\t// Only DOM nodes need a new unique ID for each element since their data\n\t\t// ends up in the global cache\n\t\tif ( isNode ) {\n\t\t\telem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++;\n\t\t} else {\n\t\t\tid = internalKey;\n\t\t}\n\t}\n\n\tif ( !cache[ id ] ) {\n\t\tcache[ id ] = {};\n\n\t\t// Avoids exposing jQuery metadata on plain JS objects when the object\n\t\t// is serialized using JSON.stringify\n\t\tif ( !isNode ) {\n\t\t\tcache[ id ].toJSON = jQuery.noop;\n\t\t}\n\t}\n\n\t// An object can be passed to jQuery.data instead of a key/value pair; this gets\n\t// shallow copied over onto the existing cache\n\tif ( typeof name === \"object\" || typeof name === \"function\" ) {\n\t\tif ( pvt ) {\n\t\t\tcache[ id ] = jQuery.extend( cache[ id ], name );\n\t\t} else {\n\t\t\tcache[ id ].data = jQuery.extend( cache[ id ].data, name );\n\t\t}\n\t}\n\n\tthisCache = cache[ id ];\n\n\t// jQuery data() is stored in a separate object inside the object's internal data\n\t// cache in order to avoid key collisions between internal data and user-defined\n\t// data.\n\tif ( !pvt ) {\n\t\tif ( !thisCache.data ) {\n\t\t\tthisCache.data = {};\n\t\t}\n\n\t\tthisCache = thisCache.data;\n\t}\n\n\tif ( data !== undefined ) {\n\t\tthisCache[ jQuery.camelCase( name ) ] = data;\n\t}\n\n\t// Check for both converted-to-camel and non-converted data property names\n\t// If a data property was specified\n\tif ( getByName ) {\n\n\t\t// First Try to find as-is property data\n\t\tret = thisCache[ name ];\n\n\t\t// Test for null|undefined property data\n\t\tif ( ret == null ) {\n\n\t\t\t// Try to find the camelCased property\n\t\t\tret = thisCache[ jQuery.camelCase( name ) ];\n\t\t}\n\t} else {\n\t\tret = thisCache;\n\t}\n\n\treturn ret;\n}\n\nfunction internalRemoveData( elem, name, pvt ) {\n\tif ( !jQuery.acceptData( elem ) ) {\n\t\treturn;\n\t}\n\n\tvar i, l, thisCache,\n\t\tisNode = elem.nodeType,\n\n\t\t// See jQuery.data for more information\n\t\tcache = isNode ? jQuery.cache : elem,\n\t\tid = isNode ? elem[ jQuery.expando ] : jQuery.expando;\n\n\t// If there is already no cache entry for this object, there is no\n\t// purpose in continuing\n\tif ( !cache[ id ] ) {\n\t\treturn;\n\t}\n\n\tif ( name ) {\n\n\t\tthisCache = pvt ? cache[ id ] : cache[ id ].data;\n\n\t\tif ( thisCache ) {\n\n\t\t\t// Support array or space separated string names for data keys\n\t\t\tif ( !jQuery.isArray( name ) ) {\n\n\t\t\t\t// try the string as a key before any manipulation\n\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\tname = [ name ];\n\t\t\t\t} else {\n\n\t\t\t\t\t// split the camel cased version by spaces unless a key with the spaces exists\n\t\t\t\t\tname = jQuery.camelCase( name );\n\t\t\t\t\tif ( name in thisCache ) {\n\t\t\t\t\t\tname = [ name ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tname = name.split(\" \");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = name.concat( jQuery.map( name, jQuery.camelCase ) );\n\t\t\t}\n\n\t\t\tfor ( i = 0, l = name.length; i < l; i++ ) {\n\t\t\t\tdelete thisCache[ name[i] ];\n\t\t\t}\n\n\t\t\t// If there is no data left in the cache, we want to continue\n\t\t\t// and let the cache object itself get destroyed\n\t\t\tif ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\t// See jQuery.data for more information\n\tif ( !pvt ) {\n\t\tdelete cache[ id ].data;\n\n\t\t// Don't destroy the parent cache unless the internal data object\n\t\t// had been the only thing left in it\n\t\tif ( !isEmptyDataObject( cache[ id ] ) ) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\t// Destroy the cache\n\tif ( isNode ) {\n\t\tjQuery.cleanData( [ elem ], true );\n\n\t// Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)\n\t} else if ( jQuery.support.deleteExpando || cache != cache.window ) {\n\t\tdelete cache[ id ];\n\n\t// When all else fails, null\n\t} else {\n\t\tcache[ id ] = null;\n\t}\n}\n\njQuery.extend({\n\tcache: {},\n\n\t// Unique for each copy of jQuery on the page\n\t// Non-digits removed to match rinlinejQuery\n\texpando: \"jQuery\" + ( core_version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// The following elements throw uncatchable exceptions if you\n\t// attempt to add expando properties to them.\n\tnoData: {\n\t\t\"embed\": true,\n\t\t// Ban all objects except for Flash (which handle expandos)\n\t\t\"object\": \"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\",\n\t\t\"applet\": true\n\t},\n\n\thasData: function( elem ) {\n\t\telem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];\n\t\treturn !!elem && !isEmptyDataObject( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name );\n\t},\n\n\t// For internal use only.\n\t_data: function( elem, name, data ) {\n\t\treturn internalData( elem, name, data, true );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\treturn internalRemoveData( elem, name, true );\n\t},\n\n\t// A method for determining if a DOM node can handle the data expando\n\tacceptData: function( elem ) {\n\t\t// Do not set data on non-element because it will not be cleared (#8335).\n\t\tif ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tvar noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ];\n\n\t\t// nodes accept data unless otherwise specified; rejection can be conditional\n\t\treturn !noData || noData !== true && elem.getAttribute(\"classid\") === noData;\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar attrs, name,\n\t\t\telem = this[0],\n\t\t\ti = 0,\n\t\t\tdata = null;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = jQuery.data( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !jQuery._data( elem, \"parsedAttrs\" ) ) {\n\t\t\t\t\tattrs = elem.attributes;\n\t\t\t\t\tfor ( ; i < attrs.length; i++ ) {\n\t\t\t\t\t\tname = attrs[i].name;\n\n\t\t\t\t\t\tif ( !name.indexOf( \"data-\" ) ) {\n\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\n\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tjQuery._data( elem, \"parsedAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tjQuery.data( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn jQuery.access( this, function( value ) {\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\t// Try to fetch any internally stored data first\n\t\t\t\treturn elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null;\n\t\t\t}\n\n\t\t\tthis.each(function() {\n\t\t\t\tjQuery.data( this, key, value );\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeData( this, key );\n\t\t});\n\t}\n});\n\nfunction dataAttr( elem, key, data ) {\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\n\t\tvar name = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tjQuery.data( elem, key, data );\n\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\n\treturn data;\n}\n\n// checks a cache object for emptiness\nfunction isEmptyDataObject( obj ) {\n\tvar name;\n\tfor ( name in obj ) {\n\n\t\t// if the public data object is empty, the private is still empty\n\t\tif ( name === \"data\" && jQuery.isEmptyObject( obj[name] ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( name !== \"toJSON\" ) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = jQuery._data( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray(data) ) {\n\t\t\t\t\tqueue = jQuery._data( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\thooks.cur = fn;\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// not intended for public consumption - generates a queueHooks object, or returns the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn jQuery._data( elem, key ) || jQuery._data( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tjQuery._removeData( elem, type + \"queue\" );\n\t\t\t\tjQuery._removeData( elem, key );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\t// Based off of the plugin by Clint Helfers, with permission.\n\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n\tdelay: function( time, type ) {\n\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\t\ttype = type || \"fx\";\n\n\t\treturn this.queue( type, function( next, hooks ) {\n\t\t\tvar timeout = setTimeout( next, time );\n\t\t\thooks.stop = function() {\n\t\t\t\tclearTimeout( timeout );\n\t\t\t};\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile( i-- ) {\n\t\t\ttmp = jQuery._data( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar nodeHook, boolHook,\n\trclass = /[\\t\\r\\n]/g,\n\trreturn = /\\r/g,\n\trfocusable = /^(?:input|select|textarea|button|object)$/i,\n\trclickable = /^(?:a|area)$/i,\n\trboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i,\n\truseDefault = /^(?:checked|selected)$/i,\n\tgetSetAttribute = jQuery.support.getSetAttribute,\n\tgetSetInput = jQuery.support.input;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t},\n\n\tprop: function( name, value ) {\n\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\tname = jQuery.propFix[ name ] || name;\n\t\treturn this.each(function() {\n\t\t\t// try/catch handles cases where IE balks (such as removing a property on window)\n\t\t\ttry {\n\t\t\t\tthis[ name ] = undefined;\n\t\t\t\tdelete this[ name ];\n\t\t\t} catch( e ) {}\n\t\t});\n\t},\n\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( core_rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telem.className = jQuery.trim( cur );\n\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j,\n\t\t\ti = 0,\n\t\t\tlen = this.length,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( core_rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telem.className = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value,\n\t\t\tisBool = typeof stateVal === \"boolean\";\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tstate = stateVal,\n\t\t\t\t\tclassNames = value.match( core_rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// check each className given, space separated list\n\t\t\t\t\tstate = isBool ? state : !self.hasClass( className );\n\t\t\t\t\tself[ state ? \"addClass\" : \"removeClass\" ]( className );\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( type === core_strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tjQuery._data( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed \"false\",\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : jQuery._data( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t},\n\n\tval: function( value ) {\n\t\tvar ret, hooks, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val,\n\t\t\t\tself = jQuery(this);\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, self.val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map(val, function ( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n\t\t\t\t// uses .value. See #6932\n\t\t\t\tvar val = elem.attributes.value;\n\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// oldIE doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( jQuery.support.optDisabled ? !option.disabled : option.getAttribute(\"disabled\") === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar values = jQuery.makeArray( value );\n\n\t\t\t\tjQuery(elem).find(\"option\").each(function() {\n\t\t\t\t\tthis.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;\n\t\t\t\t});\n\n\t\t\t\tif ( !values.length ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t},\n\n\tattr: function( elem, name, value ) {\n\t\tvar hooks, notxml, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === core_strundefined ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( notxml ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && notxml && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && notxml && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\n\t\t\t// In IE9+, Flash objects don't have .getAttribute (#12945)\n\t\t\t// Support: IE9+\n\t\t\tif ( typeof elem.getAttribute !== core_strundefined ) {\n\t\t\t\tret =  elem.getAttribute( name );\n\t\t\t}\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( core_rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( (name = attrNames[i++]) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( rboolean.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false for boolean attributes\n\t\t\t\t\t// Also clear defaultChecked/defaultSelected (if appropriate) for IE<8\n\t\t\t\t\tif ( !getSetAttribute && ruseDefault.test( name ) ) {\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] =\n\t\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t\t}\n\n\t\t\t\t// See #9699 for explanation of this approach (setting first, then removal)\n\t\t\t\t} else {\n\t\t\t\t\tjQuery.attr( elem, name, \"\" );\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( getSetAttribute ? name : propName );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !jQuery.support.radioValue && value === \"radio\" && jQuery.nodeName(elem, \"input\") ) {\n\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n\t\t\t\t\t// Reset value to default in case type is set after value during creation\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\ttabindex: \"tabIndex\",\n\t\treadonly: \"readOnly\",\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\",\n\t\tmaxlength: \"maxLength\",\n\t\tcellspacing: \"cellSpacing\",\n\t\tcellpadding: \"cellPadding\",\n\t\trowspan: \"rowSpan\",\n\t\tcolspan: \"colSpan\",\n\t\tusemap: \"useMap\",\n\t\tframeborder: \"frameBorder\",\n\t\tcontenteditable: \"contentEditable\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn ( elem[ name ] = value );\n\t\t\t}\n\n\t\t} else {\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\treturn elem[ name ];\n\t\t\t}\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\t// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set\n\t\t\t\t// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\tvar attributeNode = elem.getAttributeNode(\"tabindex\");\n\n\t\t\t\treturn attributeNode && attributeNode.specified ?\n\t\t\t\t\tparseInt( attributeNode.value, 10 ) :\n\t\t\t\t\trfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?\n\t\t\t\t\t\t0 :\n\t\t\t\t\t\tundefined;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hook for boolean attributes\nboolHook = {\n\tget: function( elem, name ) {\n\t\tvar\n\t\t\t// Use .prop to determine if this attribute is understood as boolean\n\t\t\tprop = jQuery.prop( elem, name ),\n\n\t\t\t// Fetch it accordingly\n\t\t\tattr = typeof prop === \"boolean\" && elem.getAttribute( name ),\n\t\t\tdetail = typeof prop === \"boolean\" ?\n\n\t\t\t\tgetSetInput && getSetAttribute ?\n\t\t\t\t\tattr != null :\n\t\t\t\t\t// oldIE fabricates an empty string for missing boolean attributes\n\t\t\t\t\t// and conflates checked/selected into attroperties\n\t\t\t\t\truseDefault.test( name ) ?\n\t\t\t\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] :\n\t\t\t\t\t\t!!attr :\n\n\t\t\t\t// fetch an attribute node for properties not recognized as boolean\n\t\t\t\telem.getAttributeNode( name );\n\n\t\treturn detail && detail.value !== false ?\n\t\t\tname.toLowerCase() :\n\t\t\tundefined;\n\t},\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {\n\t\t\t// IE<8 needs the *property* name\n\t\t\telem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );\n\n\t\t// Use defaultChecked and defaultSelected for oldIE\n\t\t} else {\n\t\t\telem[ jQuery.camelCase( \"default-\" + name ) ] = elem[ name ] = true;\n\t\t}\n\n\t\treturn name;\n\t}\n};\n\n// fix oldIE value attroperty\nif ( !getSetInput || !getSetAttribute ) {\n\tjQuery.attrHooks.value = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\treturn jQuery.nodeName( elem, \"input\" ) ?\n\n\t\t\t\t// Ignore the value *property* by using defaultValue\n\t\t\t\telem.defaultValue :\n\n\t\t\t\tret && ret.specified ? ret.value : undefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\tif ( jQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t// Does not return so that setAttribute is also used\n\t\t\t\telem.defaultValue = value;\n\t\t\t} else {\n\t\t\t\t// Use nodeHook if defined (#1954); otherwise setAttribute is fine\n\t\t\t\treturn nodeHook && nodeHook.set( elem, value, name );\n\t\t\t}\n\t\t}\n\t};\n}\n\n// IE6/7 do not support getting/setting some attributes with get/setAttribute\nif ( !getSetAttribute ) {\n\n\t// Use this for any attribute in IE6/7\n\t// This fixes almost every IE6/7 issue\n\tnodeHook = jQuery.valHooks.button = {\n\t\tget: function( elem, name ) {\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\treturn ret && ( name === \"id\" || name === \"name\" || name === \"coords\" ? ret.value !== \"\" : ret.specified ) ?\n\t\t\t\tret.value :\n\t\t\t\tundefined;\n\t\t},\n\t\tset: function( elem, value, name ) {\n\t\t\t// Set the existing or create a new attribute node\n\t\t\tvar ret = elem.getAttributeNode( name );\n\t\t\tif ( !ret ) {\n\t\t\t\telem.setAttributeNode(\n\t\t\t\t\t(ret = elem.ownerDocument.createAttribute( name ))\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tret.value = value += \"\";\n\n\t\t\t// Break association with cloned elements by also using setAttribute (#9646)\n\t\t\treturn name === \"value\" || value === elem.getAttribute( name ) ?\n\t\t\t\tvalue :\n\t\t\t\tundefined;\n\t\t}\n\t};\n\n\t// Set contenteditable to false on removals(#10429)\n\t// Setting to empty string throws an error as an invalid value\n\tjQuery.attrHooks.contenteditable = {\n\t\tget: nodeHook.get,\n\t\tset: function( elem, value, name ) {\n\t\t\tnodeHook.set( elem, value === \"\" ? false : value, name );\n\t\t}\n\t};\n\n\t// Set width and height to auto instead of 0 on empty string( Bug #8150 )\n\t// This is for removals\n\tjQuery.each([ \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\telem.setAttribute( name, \"auto\" );\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n\n// Some attributes require a special call on IE\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !jQuery.support.hrefNormalized ) {\n\tjQuery.each([ \"href\", \"src\", \"width\", \"height\" ], function( i, name ) {\n\t\tjQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar ret = elem.getAttribute( name, 2 );\n\t\t\t\treturn ret == null ? undefined : ret;\n\t\t\t}\n\t\t});\n\t});\n\n\t// href/src property should get the full normalized URL (#10299/#12915)\n\tjQuery.each([ \"href\", \"src\" ], function( i, name ) {\n\t\tjQuery.propHooks[ name ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.getAttribute( name, 4 );\n\t\t\t}\n\t\t};\n\t});\n}\n\nif ( !jQuery.support.style ) {\n\tjQuery.attrHooks.style = {\n\t\tget: function( elem ) {\n\t\t\t// Return undefined in the case of empty string\n\t\t\t// Note: IE uppercases css property names, but if we were to .toLowerCase()\n\t\t\t// .cssText, that would destroy case senstitivity in URL's, like in \"background\"\n\t\t\treturn elem.style.cssText || undefined;\n\t\t},\n\t\tset: function( elem, value ) {\n\t\t\treturn ( elem.style.cssText = value + \"\" );\n\t\t}\n\t};\n}\n\n// Safari mis-reports the default selected property of an option\n// Accessing the parent's selectedIndex property fixes it\nif ( !jQuery.support.optSelected ) {\n\tjQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\t// Make sure that it also works with optgroups, see #5701\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t});\n}\n\n// IE6/7 call enctype encoding\nif ( !jQuery.support.enctype ) {\n\tjQuery.propFix.enctype = \"encoding\";\n}\n\n// Radios and checkboxes getter/setter\nif ( !jQuery.support.checkOn ) {\n\tjQuery.each([ \"radio\", \"checkbox\" ], function() {\n\t\tjQuery.valHooks[ this ] = {\n\t\t\tget: function( elem ) {\n\t\t\t\t// Handle the case where in Webkit \"\" is returned instead of \"on\" if a value isn't specified\n\t\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t\t}\n\t\t};\n\t});\n}\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t});\n});\nvar rformElems = /^(?:input|select|textarea)$/i,\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\t\tvar tmp, events, t, handleObjIn,\n\t\t\tspecial, eventHandle, handleObj,\n\t\t\thandlers, type, namespaces, origType,\n\t\t\telemData = jQuery._data( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?\n\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n\t\t\t\t\tundefined;\n\t\t\t};\n\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n\t\t\teventHandle.elem = elem;\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\t// jQuery(...).bind(\"mouseover mouseout\", fn);\n\t\ttypes = ( types || \"\" ).match( core_rnotwhite ) || [\"\"];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener/attachEvent if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\t// Bind the global event handler to the element\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\n\t\t\t\t\t} else if ( elem.attachEvent ) {\n\t\t\t\t\t\telem.attachEvent( \"on\" + type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t\t// Nullify elem to prevent memory leaks in IE\n\t\telem = null;\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\t\tvar j, handleObj, tmp,\n\t\t\torigCount, t, events,\n\t\t\tspecial, handlers, type,\n\t\t\tnamespaces, origType,\n\t\t\telemData = jQuery.hasData( elem ) && jQuery._data( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( core_rnotwhite ) || [\"\"];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\n\t\t\t// removeData also checks for emptiness and clears the expando if empty\n\t\t\t// so use it instead of delete\n\t\t\tjQuery._removeData( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\t\tvar handle, ontype, cur,\n\t\t\tbubbleType, special, tmp, i,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = core_hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = core_hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\tevent.isTrigger = true;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( jQuery._data( cur, \"events\" ) || {} )[ event.type ] && jQuery._data( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&\n\t\t\t\t!(type === \"click\" && jQuery.nodeName( elem, \"a\" )) && jQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Can't use an .isFunction() check here because IE6/7 fails that test.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\ttry {\n\t\t\t\t\t\telem[ type ]();\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// IE<9 dies on focus/blur to hidden element (#1486,#12518)\n\t\t\t\t\t\t// only reproducible on winXP IE8 native, not IE9 in IE8 mode\n\t\t\t\t\t}\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, ret, handleObj, matched, j,\n\t\t\thandlerQueue = [],\n\t\t\targs = core_slice.call( arguments ),\n\t\t\thandlers = ( jQuery._data( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or\n\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar sel, handleObj, matches, i,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur != this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== \"click\") ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// Fix target property (#1925)\n\t\tif ( !event.target ) {\n\t\t\tevent.target = originalEvent.srcElement || document;\n\t\t}\n\n\t\t// Support: Chrome 23+, Safari?\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\t// Support: IE<9\n\t\t// For mouse/key events, metaKey==false if it's undefined (#3368, #11328)\n\t\tevent.metaKey = !!event.metaKey;\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar body, eventDoc, doc,\n\t\t\t\tbutton = original.button,\n\t\t\t\tfromElement = original.fromElement;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add relatedTarget, if necessary\n\t\t\tif ( !event.relatedTarget && fromElement ) {\n\t\t\t\tevent.relatedTarget = fromElement === event.target ? original.toElement : fromElement;\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( jQuery.nodeName( this, \"input\" ) && this.type === \"checkbox\" && this.click ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== document.activeElement && this.focus ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tthis.focus();\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t// Support: IE<9\n\t\t\t\t\t\t// If we error on focus to hidden element (#1486, #12518),\n\t\t\t\t\t\t// let .trigger() run the handlers\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === document.activeElement && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Even when returnValue equals to undefined Firefox will still show alert\n\t\t\t\tif ( event.result !== undefined ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{ type: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = document.removeEventListener ?\n\tfunction( elem, type, handle ) {\n\t\tif ( elem.removeEventListener ) {\n\t\t\telem.removeEventListener( type, handle, false );\n\t\t}\n\t} :\n\tfunction( elem, type, handle ) {\n\t\tvar name = \"on\" + type;\n\n\t\tif ( elem.detachEvent ) {\n\n\t\t\t// #8545, #7054, preventing memory leaks for custom events in IE6-8\n\t\t\t// detachEvent needed property on element, by name of that event, to properly expose it to GC\n\t\t\tif ( typeof elem[ name ] === core_strundefined ) {\n\t\t\t\telem[ name ] = null;\n\t\t\t}\n\n\t\t\telem.detachEvent( name, handle );\n\t\t}\n\t};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false ||\n\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If preventDefault exists, run it on the original event\n\t\tif ( e.preventDefault ) {\n\t\t\te.preventDefault();\n\n\t\t// Support: IE\n\t\t// Otherwise set the returnValue property of the original event to false\n\t\t} else {\n\t\t\te.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\t\tif ( !e ) {\n\t\t\treturn;\n\t\t}\n\t\t// If stopPropagation exists, run it on the original event\n\t\tif ( e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\n\t\t// Support: IE\n\t\t// Set the cancelBubble property of the original event to true\n\t\te.cancelBubble = true;\n\t},\n\tstopImmediatePropagation: function() {\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// IE submit delegation\nif ( !jQuery.support.submitBubbles ) {\n\n\tjQuery.event.special.submit = {\n\t\tsetup: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Lazy-add a submit handler when a descendant form may potentially be submitted\n\t\t\tjQuery.event.add( this, \"click._submit keypress._submit\", function( e ) {\n\t\t\t\t// Node name check avoids a VML-related crash in IE (#9807)\n\t\t\t\tvar elem = e.target,\n\t\t\t\t\tform = jQuery.nodeName( elem, \"input\" ) || jQuery.nodeName( elem, \"button\" ) ? elem.form : undefined;\n\t\t\t\tif ( form && !jQuery._data( form, \"submitBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( form, \"submit._submit\", function( event ) {\n\t\t\t\t\t\tevent._submit_bubble = true;\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( form, \"submitBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t\t// return undefined since we don't need an event listener\n\t\t},\n\n\t\tpostDispatch: function( event ) {\n\t\t\t// If form was submitted by the user, bubble the event up the tree\n\t\t\tif ( event._submit_bubble ) {\n\t\t\t\tdelete event._submit_bubble;\n\t\t\t\tif ( this.parentNode && !event.isTrigger ) {\n\t\t\t\t\tjQuery.event.simulate( \"submit\", this.parentNode, event, true );\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\t// Only need this for delegated form submit events\n\t\t\tif ( jQuery.nodeName( this, \"form\" ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Remove delegated handlers; cleanData eventually reaps submit handlers attached above\n\t\t\tjQuery.event.remove( this, \"._submit\" );\n\t\t}\n\t};\n}\n\n// IE change delegation and checkbox/radio fix\nif ( !jQuery.support.changeBubbles ) {\n\n\tjQuery.event.special.change = {\n\n\t\tsetup: function() {\n\n\t\t\tif ( rformElems.test( this.nodeName ) ) {\n\t\t\t\t// IE doesn't fire change on a check/radio until blur; trigger it on click\n\t\t\t\t// after a propertychange. Eat the blur-change in special.change.handle.\n\t\t\t\t// This still fires onchange a second time for check/radio after blur.\n\t\t\t\tif ( this.type === \"checkbox\" || this.type === \"radio\" ) {\n\t\t\t\t\tjQuery.event.add( this, \"propertychange._change\", function( event ) {\n\t\t\t\t\t\tif ( event.originalEvent.propertyName === \"checked\" ) {\n\t\t\t\t\t\t\tthis._just_changed = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery.event.add( this, \"click._change\", function( event ) {\n\t\t\t\t\t\tif ( this._just_changed && !event.isTrigger ) {\n\t\t\t\t\t\t\tthis._just_changed = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// Allow triggered, simulated change events (#11500)\n\t\t\t\t\t\tjQuery.event.simulate( \"change\", this, event, true );\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\t// Delegated event; lazy-add a change handler on descendant inputs\n\t\t\tjQuery.event.add( this, \"beforeactivate._change\", function( e ) {\n\t\t\t\tvar elem = e.target;\n\n\t\t\t\tif ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, \"changeBubbles\" ) ) {\n\t\t\t\t\tjQuery.event.add( elem, \"change._change\", function( event ) {\n\t\t\t\t\t\tif ( this.parentNode && !event.isSimulated && !event.isTrigger ) {\n\t\t\t\t\t\t\tjQuery.event.simulate( \"change\", this.parentNode, event, true );\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tjQuery._data( elem, \"changeBubbles\", true );\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\t\thandle: function( event ) {\n\t\t\tvar elem = event.target;\n\n\t\t\t// Swallow native change events from checkbox/radio, we already triggered them above\n\t\t\tif ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== \"radio\" && elem.type !== \"checkbox\") ) {\n\t\t\t\treturn event.handleObj.handler.apply( this, arguments );\n\t\t\t}\n\t\t},\n\n\t\tteardown: function() {\n\t\t\tjQuery.event.remove( this, \"._change\" );\n\n\t\t\treturn !rformElems.test( this.nodeName );\n\t\t}\n\t};\n}\n\n// Create \"bubbling\" focus and blur events\nif ( !jQuery.support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler while someone wants focusin/focusout\n\t\tvar attaches = 0,\n\t\t\thandler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tif ( attaches++ === 0 ) {\n\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tif ( --attaches === 0 ) {\n\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar type, origFn;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n/*!\n * Sizzle CSS Selector Engine\n * Copyright 2012 jQuery Foundation and other contributors\n * Released under the MIT license\n * http://sizzlejs.com/\n */\n(function( window, undefined ) {\n\nvar i,\n\tcachedruns,\n\tExpr,\n\tgetText,\n\tisXML,\n\tcompile,\n\thasDuplicate,\n\toutermostContext,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsXML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\tsortOrder,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + -(new Date()),\n\tpreferredDoc = window.document,\n\tsupport = {},\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\n\t// General-purpose constants\n\tstrundefined = typeof undefined,\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Array methods\n\tarr = [],\n\tpop = arr.pop,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf if we can't use a native one\n\tindexOf = arr.indexOf || function( elem ) {\n\t\tvar i = 0,\n\t\t\tlen = this.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( this[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n\toperators = \"([*^$|!~]?=)\",\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")\" + whitespace +\n\t\t\"*(?:\" + operators + whitespace + \"*(?:(['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(\" + identifier + \")|)|)\" + whitespace + \"*\\\\]\",\n\n\t// Prefer arguments quoted,\n\t//   then not containing pseudos/brackets,\n\t//   then attribute selectors/non-parenthetical expressions,\n\t//   then anything else\n\t// These preferences are here to reduce the number of selectors\n\t//   needing tokenize in the PSEUDO preFilter\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\(((['\\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes.replace( 3, 8 ) + \")*)|.*)\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([\\\\x20\\\\t\\\\r\\\\n\\\\f>+~])\" + whitespace + \"*\" ),\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"NAME\": new RegExp( \"^\\\\[name=['\\\"]?(\" + characterEncoding + \")['\\\"]?\\\\]\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trsibling = /[\\x20\\t\\r\\n\\f]*[+~]/,\n\n\trnative = /^[^{]+\\{\\s*\\[native code/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trescape = /'|\\\\/g,\n\trattributeQuotes = /\\=[\\x20\\t\\r\\n\\f]*([^'\"\\]]*)[\\x20\\t\\r\\n\\f]*\\]/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = /\\\\([\\da-fA-F]{1,6}[\\x20\\t\\r\\n\\f]?|.)/g,\n\tfunescape = function( _, escaped ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\treturn high !== high ?\n\t\t\tescaped :\n\t\t\t// BMP codepoint\n\t\t\thigh < 0 ?\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t};\n\n// Use a stripped-down slice if we can't use a native one\ntry {\n\tslice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType;\n} catch ( e ) {\n\tslice = function( i ) {\n\t\tvar elem,\n\t\t\tresults = [];\n\t\twhile ( (elem = this[i++]) ) {\n\t\t\tresults.push( elem );\n\t\t}\n\t\treturn results;\n\t};\n}\n\n/**\n * For feature detection\n * @param {Function} fn The function to test for native support\n */\nfunction isNative( fn ) {\n\treturn rnative.test( fn + \"\" );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar cache,\n\t\tkeys = [];\n\n\treturn (cache = function( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key += \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key ] = value);\n\t});\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\n\tif ( !selector || typeof selector !== \"string\" ) {\n\t\treturn results;\n\t}\n\n\tif ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {\n\t\treturn [];\n\t}\n\n\tif ( !documentIsXML && !seed ) {\n\n\t\t// Shortcuts\n\t\tif ( (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, slice.call(context.getElementsByTagName( selector ), 0) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, slice.call(context.getElementsByClassName( m ), 0) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && !rbuggyQSA.test(selector) ) {\n\t\t\told = true;\n\t\t\tnid = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType === 9 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && context.parentNode || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results, slice.call( newContext.querySelectorAll(\n\t\t\t\t\t\tnewSelector\n\t\t\t\t\t), 0 ) );\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Detect xml\n * @param {Element|Object} elem An element or a document\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar doc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\n\t// Support tests\n\tdocumentIsXML = isXML( doc );\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.tagNameNoComments = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Check if attributes should be retrieved by attribute nodes\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.innerHTML = \"<select></select>\";\n\t\tvar type = typeof div.lastChild.getAttribute(\"multiple\");\n\t\t// IE8 returns a string for some attributes even when not present\n\t\treturn type !== \"boolean\" && type !== \"string\";\n\t});\n\n\t// Check if getElementsByClassName can be trusted\n\tsupport.getByClassName = assert(function( div ) {\n\t\t// Opera can't find a second classname (in 9.6)\n\t\tdiv.innerHTML = \"<div class='hidden e'></div><div class='hidden'></div>\";\n\t\tif ( !div.getElementsByClassName || !div.getElementsByClassName(\"e\").length ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Safari 3.2 caches class attributes and doesn't catch changes\n\t\tdiv.lastChild.className = \"e\";\n\t\treturn div.getElementsByClassName(\"e\").length === 2;\n\t});\n\n\t// Check if getElementById returns elements by name\n\t// Check if getElementsByName privileges form controls or returns elements by ID\n\tsupport.getByName = assert(function( div ) {\n\t\t// Inject content\n\t\tdiv.id = expando + 0;\n\t\tdiv.innerHTML = \"<a name='\" + expando + \"'></a><div name='\" + expando + \"'></div>\";\n\t\tdocElem.insertBefore( div, docElem.firstChild );\n\n\t\t// Test\n\t\tvar pass = doc.getElementsByName &&\n\t\t\t// buggy browsers will return fewer than the correct 2\n\t\t\tdoc.getElementsByName( expando ).length === 2 +\n\t\t\t// buggy browsers will return more than the correct 0\n\t\t\tdoc.getElementsByName( expando + 0 ).length;\n\t\tsupport.getIdNotName = !doc.getElementById( expando );\n\n\t\t// Cleanup\n\t\tdocElem.removeChild( div );\n\n\t\treturn pass;\n\t});\n\n\t// IE6/7 return modified attributes\n\tExpr.attrHandle = assert(function( div ) {\n\t\tdiv.innerHTML = \"<a href='#'></a>\";\n\t\treturn div.firstChild && typeof div.firstChild.getAttribute !== strundefined &&\n\t\t\tdiv.firstChild.getAttribute(\"href\") === \"#\";\n\t}) ?\n\t\t{} :\n\t\t{\n\t\t\t\"href\": function( elem ) {\n\t\t\t\treturn elem.getAttribute( \"href\", 2 );\n\t\t\t},\n\t\t\t\"type\": function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"type\");\n\t\t\t}\n\t\t};\n\n\t// ID find and filter\n\tif ( support.getIdNotName ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== strundefined && !documentIsXML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [m] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== strundefined && !documentIsXML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\n\t\t\t\treturn m ?\n\t\t\t\t\tm.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode(\"id\").value === id ?\n\t\t\t\t\t\t[m] :\n\t\t\t\t\t\tundefined :\n\t\t\t\t\t[];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.tagNameNoComments ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== strundefined ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\t\t\t}\n\t\t} :\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Name\n\tExpr.find[\"NAME\"] = support.getByName && function( tag, context ) {\n\t\tif ( typeof context.getElementsByName !== strundefined ) {\n\t\t\treturn context.getElementsByName( name );\n\t\t}\n\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21),\n\t// no need to also add to buggyMatches since matches checks buggyQSA\n\t// A support test would require too much code (would include document ready)\n\trbuggyQSA = [ \":focus\" ];\n\n\tif ( (support.qsa = isNative(doc.querySelectorAll)) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explictly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdiv.innerHTML = \"<select><option selected=''></option></select>\";\n\n\t\t\t// IE8 - Some boolean attributes are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:checked|disabled|ismap|multiple|readonly|selected|value)\" );\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\n\t\t\t// Opera 10-12/IE8 - ^= $= *= and empty values\n\t\t\t// Should not select anything\n\t\t\tdiv.innerHTML = \"<input type='hidden' i=''/>\";\n\t\t\tif ( div.querySelectorAll(\"[i^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:\\\"\\\"|'')\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = new RegExp( rbuggyMatches.join(\"|\") );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = isNative(docElem.contains) || docElem.compareDocumentPosition ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t// Document order sorting\n\tsortOrder = docElem.compareDocumentPosition ?\n\tfunction( a, b ) {\n\t\tvar compare;\n\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tif ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) {\n\t\t\tif ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) {\n\t\t\t\tif ( a === doc || contains( preferredDoc, a ) ) {\n\t\t\t\t\treturn -1;\n\t\t\t\t}\n\t\t\t\tif ( b === doc || contains( preferredDoc, b ) ) {\n\t\t\t\t\treturn 1;\n\t\t\t\t}\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn compare & 4 ? -1 : 1;\n\t\t}\n\n\t\treturn a.compareDocumentPosition ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\t} else if ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\t// Always assume the presence of duplicates if sort doesn't\n\t// pass them to our comparison function (as in Google Chrome).\n\thasDuplicate = false;\n\t[0, 0].sort( sortOrder );\n\tsupport.detectDuplicates = hasDuplicate;\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\t// rbuggyQSA always contains :focus, so no need for an existence check\n\tif ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) {\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch(e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [elem] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\tvar val;\n\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tif ( !documentIsXML ) {\n\t\tname = name.toLowerCase();\n\t}\n\tif ( (val = Expr.attrHandle[ name ]) ) {\n\t\treturn val( elem );\n\t}\n\tif ( documentIsXML || support.attributes ) {\n\t\treturn elem.getAttribute( name );\n\t}\n\treturn ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ?\n\t\tname :\n\t\tval && val.specified ? val.value : null;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n// Document sorting and removing duplicates\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\ti = 1,\n\t\tj = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\tfor ( ; (elem = results[i]); i++ ) {\n\t\t\tif ( elem === results[ i - 1 ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\treturn results;\n};\n\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n// Returns a function to use in pseudos for input types\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n// Returns a function to use in pseudos for buttons\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n// Returns a function to use in pseudos for positionals\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\tfor ( ; (node = elem[i]); i++ ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (see #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[5] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[4] ) {\n\t\t\t\tmatch[2] = match[4];\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeName ) {\n\t\t\tif ( nodeName === \"*\" ) {\n\t\t\t\treturn function() { return true; };\n\t\t\t}\n\n\t\t\tnodeName = nodeName.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute(\"class\")) || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf.call( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifider\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsXML ?\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\") :\n\t\t\t\t\t\telem.lang) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\n\t\t\t//   not comment, processing instructions, or others\n\t\t\t// Thanks to Diego Perini for the nodeName shortcut\n\t\t\t//   Greater than \"@\" means alpha characters (specifically not starting with \"#\" or \"?\")\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeName > \"@\" || elem.nodeType === 3 || elem.nodeType === 4 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\t// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)\n\t\t\t// use getAttribute instead to test this case\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === elem.type );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\nfunction tokenize( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( tokens = [] );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push( {\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t} );\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push( {\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t} );\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n}\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar data, cache, outerCache,\n\t\t\t\tdirkey = dirruns + \" \" + doneName;\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {\n\t\t\t\t\t\t\tif ( (data = cache[1]) === true || data === cachedruns ) {\n\t\t\t\t\t\t\t\treturn data === true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tcache = outerCache[ dir ] = [ dirkey ];\n\t\t\t\t\t\t\tcache[1] = matcher( elem, context, xml ) || cachedruns;\n\t\t\t\t\t\t\tif ( cache[1] === true ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf.call( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\treturn ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\t// A counter to specify which element is currently being matched\n\tvar matcherCachedRuns = 0,\n\t\tbySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, expandContext ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tsetMatched = [],\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\toutermost = expandContext != null,\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", expandContext && context.parentNode || context ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t\tcachedruns = matcherCachedRuns;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t\tcachedruns = ++matcherCachedRuns;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !group ) {\n\t\t\tgroup = tokenize( selector );\n\t\t}\n\t\ti = group.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( group[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\t}\n\treturn cached;\n};\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction select( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tmatch = tokenize( selector );\n\n\tif ( !seed ) {\n\t\t// Try to minimize operations if there is only one group\n\t\tif ( match.length === 1 ) {\n\n\t\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\t\ttokens = match[0] = match[0].slice( 0 );\n\t\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\t\tcontext.nodeType === 9 && !documentIsXML &&\n\t\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\t\tcontext = Expr.find[\"ID\"]( token.matches[0].replace( runescape, funescape ), context )[0];\n\t\t\t\tif ( !context ) {\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\n\t\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t\t}\n\n\t\t\t// Fetch a seed set for right-to-left matching\n\t\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\ttoken = tokens[i];\n\n\t\t\t\t// Abort if we hit a combinator\n\t\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\t\tif ( (seed = find(\n\t\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\t\trsibling.test( tokens[0].type ) && context.parentNode || context\n\t\t\t\t\t)) ) {\n\n\t\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\t\tpush.apply( results, slice.call( seed, 0 ) );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\tcompile( selector, match )(\n\t\tseed,\n\t\tcontext,\n\t\tdocumentIsXML,\n\t\tresults,\n\t\trsibling.test( selector )\n\t);\n\treturn results;\n}\n\n// Deprecated\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nExpr.filters = setFilters.prototype = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\n// Initialize with the default document\nsetDocument();\n\n// Override sizzle attribute retrieval\nSizzle.attr = jQuery.attr;\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n})( window );\nvar runtil = /Until$/,\n\trparentsprev = /^(?:parents|prev(?:Until|All))/,\n\tisSimple = /^.[^:#\\[\\.,]*$/,\n\trneedsContext = jQuery.expr.match.needsContext,\n\t// methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i, ret, self,\n\t\t\tlen = this.length;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\tself = this;\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tret = [];\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, this[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = ( this.selector ? this.selector + \" \" : \"\" ) + selector;\n\t\treturn ret;\n\t},\n\n\thas: function( target ) {\n\t\tvar i,\n\t\t\ttargets = jQuery( target, this ),\n\t\t\tlen = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, false) );\n\t},\n\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector, true) );\n\t},\n\n\tis: function( selector ) {\n\t\treturn !!selector && (\n\t\t\ttypeof selector === \"string\" ?\n\t\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\t\trneedsContext.test( selector ) ?\n\t\t\t\t\tjQuery( selector, this.context ).index( this[0] ) >= 0 :\n\t\t\t\t\tjQuery.filter( selector, this ).length > 0 :\n\t\t\t\tthis.filter( selector ).length > 0 );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tret = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tcur = this[i];\n\n\t\t\twhile ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) {\n\t\t\t\tif ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {\n\t\t\t\t\tret.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret );\n\t},\n\n\t// Determine the position of an element within\n\t// the matched set of elements\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn jQuery.inArray( this[0], jQuery( elem ) );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn jQuery.inArray(\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[0] : elem, this );\n\t},\n\n\tadd: function( selector, context ) {\n\t\tvar set = typeof selector === \"string\" ?\n\t\t\t\tjQuery( selector, context ) :\n\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n\t\t\tall = jQuery.merge( this.get(), set );\n\n\t\treturn this.pushStack( jQuery.unique(all) );\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\nfunction sibling( cur, dir ) {\n\tdo {\n\t\tcur = cur[ dir ];\n\t} while ( cur && cur.nodeType !== 1 );\n\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn jQuery.nodeName( elem, \"iframe\" ) ?\n\t\t\telem.contentDocument || elem.contentWindow.document :\n\t\t\tjQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar ret = jQuery.map( this, fn, until );\n\n\t\tif ( !runtil.test( name ) ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tret = jQuery.filter( selector, ret );\n\t\t}\n\n\t\tret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;\n\n\t\tif ( this.length > 1 && rparentsprev.test( name ) ) {\n\t\t\tret = ret.reverse();\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\njQuery.extend({\n\tfilter: function( expr, elems, not ) {\n\t\tif ( not ) {\n\t\t\texpr = \":not(\" + expr + \")\";\n\t\t}\n\n\t\treturn elems.length === 1 ?\n\t\t\tjQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :\n\t\t\tjQuery.find.matches(expr, elems);\n\t},\n\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\tcur = elem[ dir ];\n\n\t\twhile ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {\n\t\t\tif ( cur.nodeType === 1 ) {\n\t\t\t\tmatched.push( cur );\n\t\t\t}\n\t\t\tcur = cur[dir];\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar r = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tr.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn r;\n\t}\n});\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, keep ) {\n\n\t// Can't pass null or undefined to indexOf in Firefox 4\n\t// Set to 0 to skip string check\n\tqualifier = qualifier || 0;\n\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep(elements, function( elem, i ) {\n\t\t\tvar retVal = !!qualifier.call( elem, i, elem );\n\t\t\treturn retVal === keep;\n\t\t});\n\n\t} else if ( qualifier.nodeType ) {\n\t\treturn jQuery.grep(elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) === keep;\n\t\t});\n\n\t} else if ( typeof qualifier === \"string\" ) {\n\t\tvar filtered = jQuery.grep(elements, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t});\n\n\t\tif ( isSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter(qualifier, filtered, !keep);\n\t\t} else {\n\t\t\tqualifier = jQuery.filter( qualifier, filtered );\n\t\t}\n\t}\n\n\treturn jQuery.grep(elements, function( elem ) {\n\t\treturn ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep;\n\t});\n}\nfunction createSafeFragment( document ) {\n\tvar list = nodeNames.split( \"|\" ),\n\t\tsafeFrag = document.createDocumentFragment();\n\n\tif ( safeFrag.createElement ) {\n\t\twhile ( list.length ) {\n\t\t\tsafeFrag.createElement(\n\t\t\t\tlist.pop()\n\t\t\t);\n\t\t}\n\t}\n\treturn safeFrag;\n}\n\nvar nodeNames = \"abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|\" +\n\t\t\"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video\",\n\trinlinejQuery = / jQuery\\d+=\"(?:null|\\d+)\"/g,\n\trnoshimcache = new RegExp(\"<(?:\" + nodeNames + \")[\\\\s/>]\", \"i\"),\n\trleadingWhitespace = /^\\s+/,\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trtbody = /<tbody/i,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\tmanipulation_rcheckableType = /^(?:checkbox|radio)$/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\t\tlegend: [ 1, \"<fieldset>\", \"</fieldset>\" ],\n\t\tarea: [ 1, \"<map>\", \"</map>\" ],\n\t\tparam: [ 1, \"<object>\", \"</object>\" ],\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\tcol: [ 2, \"<table><tbody></tbody><colgroup>\", \"</colgroup></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,\n\t\t// unless wrapped in a div with non-breaking characters in front of it.\n\t\t_default: jQuery.support.htmlSerialize ? [ 0, \"\", \"\" ] : [ 1, \"X<div>\", \"</div>\"  ]\n\t},\n\tsafeFragment = createSafeFragment( document ),\n\tfragmentDiv = safeFragment.appendChild( document.createElement(\"div\") );\n\nwrapMap.optgroup = wrapMap.option;\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );\n\t\t}, null, value, arguments.length );\n\t},\n\n\twrapAll: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[0] ) {\n\t\t\t// The elements to wrap the target around\n\t\t\tvar wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);\n\n\t\t\tif ( this[0].parentNode ) {\n\t\t\t\twrap.insertBefore( this[0] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstChild && elem.firstChild.nodeType === 1 ) {\n\t\t\t\t\telem = elem.firstChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function(i) {\n\t\t\t\tjQuery(this).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function(i) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tthis.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip(arguments, true, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tthis.insertBefore( elem, this.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, false, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, false, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\t// keepData is for internal use only--do not document\n\tremove: function( selector, keepData ) {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) {\n\t\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t\t}\n\n\t\t\t\tif ( elem.parentNode ) {\n\t\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t}\n\n\t\t\t// Remove any remaining nodes\n\t\t\twhile ( elem.firstChild ) {\n\t\t\t\telem.removeChild( elem.firstChild );\n\t\t\t}\n\n\t\t\t// If this is a select, ensure that it displays empty (#12336)\n\t\t\t// Support: IE<9\n\t\t\tif ( elem.options && jQuery.nodeName( elem, \"select\" ) ) {\n\t\t\t\telem.options.length = 0;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function () {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn jQuery.access( this, function( value ) {\n\t\t\tvar elem = this[0] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined ) {\n\t\t\t\treturn elem.nodeType === 1 ?\n\t\t\t\t\telem.innerHTML.replace( rinlinejQuery, \"\" ) :\n\t\t\t\t\tundefined;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t( jQuery.support.htmlSerialize || !rnoshimcache.test( value )  ) &&\n\t\t\t\t( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [\"\", \"\"] )[1].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor (; i < l; i++ ) {\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\telem = this[i] || {};\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function( value ) {\n\t\tvar isFunc = jQuery.isFunction( value );\n\n\t\t// Make sure that the elements are removed from the DOM before they are inserted\n\t\t// this can help fix replacing a parent with child elements\n\t\tif ( !isFunc && typeof value !== \"string\" ) {\n\t\t\tvalue = jQuery( value ).not( this ).detach();\n\t\t}\n\n\t\treturn this.domManip( [ value ], true, function( elem ) {\n\t\t\tvar next = this.nextSibling,\n\t\t\t\tparent = this.parentNode;\n\n\t\t\tif ( parent ) {\n\t\t\t\tjQuery( this ).remove();\n\t\t\t\tparent.insertBefore( elem, next );\n\t\t\t}\n\t\t});\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, table, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = core_concat.apply( [], args );\n\n\t\tvar first, node, hasScripts,\n\t\t\tscripts, doc, fragment,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[0],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction || !( l <= 1 || typeof value !== \"string\" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[0] = value.call( this, index, table ? self.html() : undefined );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, table, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\ttable = table && jQuery.nodeName( first, \"tr\" );\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call(\n\t\t\t\t\t\ttable && jQuery.nodeName( this[i], \"table\" ) ?\n\t\t\t\t\t\t\tfindOrAppend( this[i], \"tbody\" ) :\n\t\t\t\t\t\t\tthis[i],\n\t\t\t\t\t\tnode,\n\t\t\t\t\t\ti\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!jQuery._data( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Hope ajax is available...\n\t\t\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\t\t\turl: node.src,\n\t\t\t\t\t\t\t\t\ttype: \"GET\",\n\t\t\t\t\t\t\t\t\tdataType: \"script\",\n\t\t\t\t\t\t\t\t\tasync: false,\n\t\t\t\t\t\t\t\t\tglobal: false,\n\t\t\t\t\t\t\t\t\t\"throws\": true\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( ( node.text || node.textContent || node.innerHTML || \"\" ).replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Fix #11809: Avoid leaking memory\n\t\t\t\tfragment = first = null;\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\nfunction findOrAppend( elem, tag ) {\n\treturn elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) );\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\tvar attr = elem.getAttributeNode(\"type\");\n\telem.type = ( attr && attr.specified ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\tif ( match ) {\n\t\telem.type = match[1];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar elem,\n\t\ti = 0;\n\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\tjQuery._data( elem, \"globalEval\", !refElements || jQuery._data( refElements[i], \"globalEval\" ) );\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\n\tif ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {\n\t\treturn;\n\t}\n\n\tvar type, i, l,\n\t\toldData = jQuery._data( src ),\n\t\tcurData = jQuery._data( dest, oldData ),\n\t\tevents = oldData.events;\n\n\tif ( events ) {\n\t\tdelete curData.handle;\n\t\tcurData.events = {};\n\n\t\tfor ( type in events ) {\n\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t}\n\t\t}\n\t}\n\n\t// make the cloned public data object a copy from the original\n\tif ( curData.data ) {\n\t\tcurData.data = jQuery.extend( {}, curData.data );\n\t}\n}\n\nfunction fixCloneNodeIssues( src, dest ) {\n\tvar nodeName, e, data;\n\n\t// We do not need to do anything for non-Elements\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\tnodeName = dest.nodeName.toLowerCase();\n\n\t// IE6-8 copies events bound via attachEvent when using cloneNode.\n\tif ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) {\n\t\tdata = jQuery._data( dest );\n\n\t\tfor ( e in data.events ) {\n\t\t\tjQuery.removeEvent( dest, e, data.handle );\n\t\t}\n\n\t\t// Event data gets referenced instead of copied if the expando gets copied too\n\t\tdest.removeAttribute( jQuery.expando );\n\t}\n\n\t// IE blanks contents when cloning scripts, and tries to evaluate newly-set text\n\tif ( nodeName === \"script\" && dest.text !== src.text ) {\n\t\tdisableScript( dest ).text = src.text;\n\t\trestoreScript( dest );\n\n\t// IE6-10 improperly clones children of object elements using classid.\n\t// IE10 throws NoModificationAllowedError if parent is null, #12132.\n\t} else if ( nodeName === \"object\" ) {\n\t\tif ( dest.parentNode ) {\n\t\t\tdest.outerHTML = src.outerHTML;\n\t\t}\n\n\t\t// This path appears unavoidable for IE9. When cloning an object\n\t\t// element in IE9, the outerHTML strategy above is not sufficient.\n\t\t// If the src has innerHTML and the destination does not,\n\t\t// copy the src.innerHTML into the dest.innerHTML. #10324\n\t\tif ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {\n\t\t\tdest.innerHTML = src.innerHTML;\n\t\t}\n\n\t} else if ( nodeName === \"input\" && manipulation_rcheckableType.test( src.type ) ) {\n\t\t// IE6-8 fails to persist the checked state of a cloned checkbox\n\t\t// or radio button. Worse, IE6-7 fail to give the cloned element\n\t\t// a checked appearance if the defaultChecked value isn't also set\n\n\t\tdest.defaultChecked = dest.checked = src.checked;\n\n\t\t// IE6-7 get confused and end up setting the value of a cloned\n\t\t// checkbox/radio button to an empty string instead of \"on\"\n\t\tif ( dest.value !== src.value ) {\n\t\t\tdest.value = src.value;\n\t\t}\n\n\t// IE6-8 fails to return the selected option to the default selected\n\t// state when cloning options\n\t} else if ( nodeName === \"option\" ) {\n\t\tdest.defaultSelected = dest.selected = src.defaultSelected;\n\n\t// IE6-8 fails to set the defaultValue to the correct value when\n\t// cloning other types of input fields\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\ti = 0,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone(true);\n\t\t\tjQuery( insert[i] )[ original ]( elems );\n\n\t\t\t// Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()\n\t\t\tcore_push.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\nfunction getAll( context, tag ) {\n\tvar elems, elem,\n\t\ti = 0,\n\t\tfound = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\ttypeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\tundefined;\n\n\tif ( !found ) {\n\t\tfor ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !tag || jQuery.nodeName( elem, tag ) ) {\n\t\t\t\tfound.push( elem );\n\t\t\t} else {\n\t\t\t\tjQuery.merge( found, getAll( elem, tag ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], found ) :\n\t\tfound;\n}\n\n// Used in buildFragment, fixes the defaultChecked property\nfunction fixDefaultChecked( elem ) {\n\tif ( manipulation_rcheckableType.test( elem.type ) ) {\n\t\telem.defaultChecked = elem.checked;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar destElements, node, clone, i, srcElements,\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\tif ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( \"<\" + elem.nodeName + \">\" ) ) {\n\t\t\tclone = elem.cloneNode( true );\n\n\t\t// IE<=8 does not properly clone detached, unknown element nodes\n\t\t} else {\n\t\t\tfragmentDiv.innerHTML = elem.outerHTML;\n\t\t\tfragmentDiv.removeChild( clone = fragmentDiv.firstChild );\n\t\t}\n\n\t\tif ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&\n\t\t\t\t(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\t// Fix all IE cloning issues\n\t\t\tfor ( i = 0; (node = srcElements[i]) != null; ++i ) {\n\t\t\t\t// Ensure that the destination node is not null; Fixes #9587\n\t\t\t\tif ( destElements[i] ) {\n\t\t\t\t\tfixCloneNodeIssues( node, destElements[i] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0; (node = srcElements[i]) != null; i++ ) {\n\t\t\t\t\tcloneCopyEvent( node, destElements[i] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\tdestElements = srcElements = node = null;\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar j, elem, contains,\n\t\t\ttmp, tag, tbody, wrap,\n\t\t\tl = elems.length,\n\n\t\t\t// Ensure a safe fragment\n\t\t\tsafe = createSafeFragment( context ),\n\n\t\t\tnodes = [],\n\t\t\ti = 0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || safe.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [\"\", \"\"] )[1].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\n\t\t\t\t\ttmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[2];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[0];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Manually add leading whitespace removed by IE\n\t\t\t\t\tif ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {\n\t\t\t\t\t\tnodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove IE's autoinserted <tbody> from table fragments\n\t\t\t\t\tif ( !jQuery.support.tbody ) {\n\n\t\t\t\t\t\t// String was a <table>, *may* have spurious <tbody>\n\t\t\t\t\t\telem = tag === \"table\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\ttmp.firstChild :\n\n\t\t\t\t\t\t\t// String was a bare <thead> or <tfoot>\n\t\t\t\t\t\t\twrap[1] === \"<table>\" && !rtbody.test( elem ) ?\n\t\t\t\t\t\t\t\ttmp :\n\t\t\t\t\t\t\t\t0;\n\n\t\t\t\t\t\tj = elem && elem.childNodes.length;\n\t\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\t\tif ( jQuery.nodeName( (tbody = elem.childNodes[j]), \"tbody\" ) && !tbody.childNodes.length ) {\n\t\t\t\t\t\t\t\telem.removeChild( tbody );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Fix #12392 for WebKit and IE > 9\n\t\t\t\t\ttmp.textContent = \"\";\n\n\t\t\t\t\t// Fix #12392 for oldIE\n\t\t\t\t\twhile ( tmp.firstChild ) {\n\t\t\t\t\t\ttmp.removeChild( tmp.firstChild );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remember the top-level container for proper cleanup\n\t\t\t\t\ttmp = safe.lastChild;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Fix #11356: Clear elements from fragment\n\t\tif ( tmp ) {\n\t\t\tsafe.removeChild( tmp );\n\t\t}\n\n\t\t// Reset defaultChecked for any radios and checkboxes\n\t\t// about to be appended to the DOM in IE 6/7 (#8060)\n\t\tif ( !jQuery.support.appendChecked ) {\n\t\t\tjQuery.grep( getAll( nodes, \"input\" ), fixDefaultChecked );\n\t\t}\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( safe.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttmp = null;\n\n\t\treturn safe;\n\t},\n\n\tcleanData: function( elems, /* internal */ acceptData ) {\n\t\tvar elem, type, id, data,\n\t\t\ti = 0,\n\t\t\tinternalKey = jQuery.expando,\n\t\t\tcache = jQuery.cache,\n\t\t\tdeleteExpando = jQuery.support.deleteExpando,\n\t\t\tspecial = jQuery.event.special;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\n\t\t\tif ( acceptData || jQuery.acceptData( elem ) ) {\n\n\t\t\t\tid = elem[ internalKey ];\n\t\t\t\tdata = id && cache[ id ];\n\n\t\t\t\tif ( data ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove cache only if it was not already removed by jQuery.event.remove\n\t\t\t\t\tif ( cache[ id ] ) {\n\n\t\t\t\t\t\tdelete cache[ id ];\n\n\t\t\t\t\t\t// IE does not allow us to delete expando properties from nodes,\n\t\t\t\t\t\t// nor does it have a removeAttribute function on Document nodes;\n\t\t\t\t\t\t// we must handle all of these cases\n\t\t\t\t\t\tif ( deleteExpando ) {\n\t\t\t\t\t\t\tdelete elem[ internalKey ];\n\n\t\t\t\t\t\t} else if ( typeof elem.removeAttribute !== core_strundefined ) {\n\t\t\t\t\t\t\telem.removeAttribute( internalKey );\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\telem[ internalKey ] = null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcore_deletedIds.push( id );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\nvar iframe, getStyles, curCSS,\n\tralpha = /alpha\\([^)]*\\)/i,\n\tropacity = /opacity\\s*=\\s*([^)]*)/,\n\trposition = /^(top|right|bottom|left)$/,\n\t// swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trmargin = /^margin/,\n\trnumsplit = new RegExp( \"^(\" + core_pnum + \")(.*)$\", \"i\" ),\n\trnumnonpx = new RegExp( \"^(\" + core_pnum + \")(?!px)[a-z%]+$\", \"i\" ),\n\trrelNum = new RegExp( \"^([+-])=(\" + core_pnum + \")\", \"i\" ),\n\telemdisplay = { BODY: \"block\" },\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: 0,\n\t\tfontWeight: 400\n\t},\n\n\tcssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ],\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ];\n\n// return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// check for vendor prefixed names\n\tvar capName = name.charAt(0).toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction isHidden( elem, el ) {\n\t// isHidden might be called from jQuery#filter function;\n\t// in that case, element will be second argument\n\telem = el || elem;\n\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = jQuery._data( elem, \"olddisplay\", css_defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\n\t\t\tif ( !values[ index ] ) {\n\t\t\t\thidden = isHidden( elem );\n\n\t\t\t\tif ( display && display !== \"none\" || !hidden ) {\n\t\t\t\t\tjQuery._data( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn jQuery.access( this, function( elem, name, value ) {\n\t\t\tvar len, styles,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tvar bool = typeof state === \"boolean\";\n\n\t\treturn this.each(function() {\n\t\t\tif ( bool ? state : isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Exclude the following css properties to add px\n\tcssNumber: {\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t// normalize float css property\n\t\t\"float\": jQuery.support.cssFloat ? \"cssFloat\" : \"styleFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that NaN and null values aren't set. See: #7116\n\t\t\tif ( value == null || type === \"number\" && isNaN( value ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Fixes #8908, it can be done more correctly by specifing setters in cssHooks,\n\t\t\t// but it would mean to define eight (for every problematic property) identical functions\n\t\t\tif ( !jQuery.support.clearCloneStyle && value === \"\" && name.indexOf(\"background\") === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\n\t\t\t\t// Wrapped to prevent IE from throwing errors when 'invalid' values are provided\n\t\t\t\t// Fixes bug #5509\n\t\t\t\ttry {\n\t\t\t\t\tstyle[ name ] = value;\n\t\t\t\t} catch(e) {}\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar num, val, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// gets hook for the prefixed version\n\t\t// followed by the unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t//convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Return, converting to number if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t},\n\n\t// A method for quickly swapping in/out CSS properties to get correct calculations\n\tswap: function( elem, options, callback, args ) {\n\t\tvar ret, name,\n\t\t\told = {};\n\n\t\t// Remember the old values, and insert the new ones\n\t\tfor ( name in options ) {\n\t\t\told[ name ] = elem.style[ name ];\n\t\t\telem.style[ name ] = options[ name ];\n\t\t}\n\n\t\tret = callback.apply( elem, args || [] );\n\n\t\t// Revert the old values\n\t\tfor ( name in options ) {\n\t\t\telem.style[ name ] = old[ name ];\n\t\t}\n\n\t\treturn ret;\n\t}\n});\n\n// NOTE: we've included the \"window\" in window.getComputedStyle\n// because jsdom on node.js will break without it.\nif ( window.getComputedStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n\n\tcurCSS = function( elem, name, _computed ) {\n\t\tvar width, minWidth, maxWidth,\n\t\t\tcomputed = _computed || getStyles( elem ),\n\n\t\t\t// getPropertyValue is only needed for .css('filter') in IE9, see #12537\n\t\t\tret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,\n\t\t\tstyle = elem.style;\n\n\t\tif ( computed ) {\n\n\t\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\tret = jQuery.style( elem, name );\n\t\t\t}\n\n\t\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t\t// Chrome < 17 and Safari 5.0 uses \"computed value\" instead of \"used value\" for margin-right\n\t\t\t// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t\t// Remember the original values\n\t\t\t\twidth = style.width;\n\t\t\t\tminWidth = style.minWidth;\n\t\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t\t// Put in the new values to get a computed value out\n\t\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\t\tret = computed.width;\n\n\t\t\t\t// Revert the changed values\n\t\t\t\tstyle.width = width;\n\t\t\t\tstyle.minWidth = minWidth;\n\t\t\t\tstyle.maxWidth = maxWidth;\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t};\n} else if ( document.documentElement.currentStyle ) {\n\tgetStyles = function( elem ) {\n\t\treturn elem.currentStyle;\n\t};\n\n\tcurCSS = function( elem, name, _computed ) {\n\t\tvar left, rs, rsLeft,\n\t\t\tcomputed = _computed || getStyles( elem ),\n\t\t\tret = computed ? computed[ name ] : undefined,\n\t\t\tstyle = elem.style;\n\n\t\t// Avoid setting ret to empty string here\n\t\t// so we don't default to auto\n\t\tif ( ret == null && style && style[ name ] ) {\n\t\t\tret = style[ name ];\n\t\t}\n\n\t\t// From the awesome hack by Dean Edwards\n\t\t// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291\n\n\t\t// If we're not dealing with a regular pixel number\n\t\t// but a number that has a weird ending, we need to convert it to pixels\n\t\t// but not position css attributes, as those are proportional to the parent element instead\n\t\t// and we can't measure the parent instead because it might trigger a \"stacking dolls\" problem\n\t\tif ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\tleft = style.left;\n\t\t\trs = elem.runtimeStyle;\n\t\t\trsLeft = rs && rs.left;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = elem.currentStyle.left;\n\t\t\t}\n\t\t\tstyle.left = name === \"fontSize\" ? \"1em\" : ret;\n\t\t\tret = style.pixelLeft + \"px\";\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.left = left;\n\t\t\tif ( rsLeft ) {\n\t\t\t\trs.left = rsLeft;\n\t\t\t}\n\t\t}\n\n\t\treturn ret === \"\" ? \"auto\" : ret;\n\t};\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// at this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\t\t\t// at this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// at this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = jQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// we need the check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\n// Try to determine the default display value of an element\nfunction css_defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = ( iframe ||\n\t\t\t\tjQuery(\"<iframe frameborder='0' width='0' height='0'/>\")\n\t\t\t\t.css( \"cssText\", \"display:block !important\" )\n\t\t\t).appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;\n\t\t\tdoc.write(\"<!doctype html><html><body>\");\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\n\n// Called ONLY from within css_defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\t\tdisplay = jQuery.css( elem[0], \"display\" );\n\telem.remove();\n\treturn display;\n}\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\t\t\t\t// certain elements can have dimension info if we invisibly show them\n\t\t\t\t// however, it must have a current display style that would benefit from this\n\t\t\t\treturn elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, \"display\" ) ) ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tjQuery.support.boxSizing && jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\nif ( !jQuery.support.opacity ) {\n\tjQuery.cssHooks.opacity = {\n\t\tget: function( elem, computed ) {\n\t\t\t// IE uses filters for opacity\n\t\t\treturn ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || \"\" ) ?\n\t\t\t\t( 0.01 * parseFloat( RegExp.$1 ) ) + \"\" :\n\t\t\t\tcomputed ? \"1\" : \"\";\n\t\t},\n\n\t\tset: function( elem, value ) {\n\t\t\tvar style = elem.style,\n\t\t\t\tcurrentStyle = elem.currentStyle,\n\t\t\t\topacity = jQuery.isNumeric( value ) ? \"alpha(opacity=\" + value * 100 + \")\" : \"\",\n\t\t\t\tfilter = currentStyle && currentStyle.filter || style.filter || \"\";\n\n\t\t\t// IE has trouble with opacity if it does not have layout\n\t\t\t// Force it by setting the zoom level\n\t\t\tstyle.zoom = 1;\n\n\t\t\t// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652\n\t\t\t// if value === \"\", then remove inline opacity #12685\n\t\t\tif ( ( value >= 1 || value === \"\" ) &&\n\t\t\t\t\tjQuery.trim( filter.replace( ralpha, \"\" ) ) === \"\" &&\n\t\t\t\t\tstyle.removeAttribute ) {\n\n\t\t\t\t// Setting style.filter to null, \"\" & \" \" still leave \"filter:\" in the cssText\n\t\t\t\t// if \"filter:\" is present at all, clearType is disabled, we want to avoid this\n\t\t\t\t// style.removeAttribute is IE Only, but so apparently is this code path...\n\t\t\t\tstyle.removeAttribute( \"filter\" );\n\n\t\t\t\t// if there is no filter style applied in a css rule or unset inline opacity, we are done\n\t\t\t\tif ( value === \"\" || currentStyle && !currentStyle.filter ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// otherwise, set new filter values\n\t\t\tstyle.filter = ralpha.test( filter ) ?\n\t\t\t\tfilter.replace( ralpha, opacity ) :\n\t\t\t\tfilter + \" \" + opacity;\n\t\t}\n\t};\n}\n\n// These hooks cannot be added until DOM ready because the support test\n// for it is not run until after DOM ready\njQuery(function() {\n\tif ( !jQuery.support.reliableMarginRight ) {\n\t\tjQuery.cssHooks.marginRight = {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\t\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t\t// Work around by temporarily setting element display to inline-block\n\t\t\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n\n\t// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n\t// getComputedStyle returns percent when specified for top/left/bottom/right\n\t// rather than make the css module depend on the offset module, we just check for it here\n\tif ( !jQuery.support.pixelPosition && jQuery.fn.position ) {\n\t\tjQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\t\t\tjQuery.cssHooks[ prop ] = {\n\t\t\t\tget: function( elem, computed ) {\n\t\t\t\t\tif ( computed ) {\n\t\t\t\t\t\tcomputed = curCSS( elem, prop );\n\t\t\t\t\t\t// if curCSS returns percentage, fallback to offset\n\t\t\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\t\t\tcomputed;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t});\n\t}\n\n});\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.hidden = function( elem ) {\n\t\t// Support: Opera <= 12.12\n\t\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\t\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||\n\t\t\t(!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || jQuery.css( elem, \"display\" )) === \"none\");\n\t};\n\n\tjQuery.expr.filters.visible = function( elem ) {\n\t\treturn !jQuery.expr.filters.hidden( elem );\n\t};\n}\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function(){\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t})\n\t\t.filter(function(){\n\t\t\tvar type = this.type;\n\t\t\t// Use .is(\":disabled\") so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !manipulation_rcheckableType.test( type ) );\n\t\t})\n\t\t.map(function( i, elem ){\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ){\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n//Serialize an array of form elements or a set of\n//key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.hover = function( fnOver, fnOut ) {\n\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n};\nvar\n\t// Document location\n\tajaxLocParts,\n\tajaxLocation,\n\tajax_nonce = jQuery.now(),\n\n\tajax_rquery = /\\?/,\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)\\r?$/mg, // IE leaves an \\r character at EOL\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t// Keep a copy of the old load method\n\t_load = jQuery.fn.load,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat(\"*\");\n\n// #8138, IE may throw an exception when accessing\n// a field from window.location if document.domain has been set\ntry {\n\tajaxLocation = location.href;\n} catch( e ) {\n\t// Use the href attribute of an A element\n\t// since IE will modify it given document.location\n\tajaxLocation = document.createElement( \"a\" );\n\tajaxLocation.href = \"\";\n\tajaxLocation = ajaxLocation.href;\n}\n\n// Segment location into parts\najaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[0] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif( typeof dataTypeOrTransport === \"string\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t});\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar deep, key,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, response, type,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = url.slice( off, url.length );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ){\n\tjQuery.fn[ type ] = function( fn ){\n\t\treturn this.on( type, fn );\n\t};\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t});\n\t};\n});\n\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": window.String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar // Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers as string\n\t\t\tresponseHeadersString,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\ttransport,\n\t\t\t// Response headers\n\t\t\tresponseHeaders,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" ).replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( core_rnotwhite ) || [\"\"];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? 80 : 443 ) ) !=\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? 80 : 443 ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\tfireGlobals = s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger(\"ajaxStart\");\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + ajax_nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( ajax_rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + ajax_nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\tjqXHR.abort(\"timeout\");\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( status >= 200 && status < 300 || status === 304 ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 ) {\n\t\t\t\t\tisSuccess = true;\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tisSuccess = true;\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tisSuccess = ajaxConvert( s, response );\n\t\t\t\t\tstatusText = isSuccess.state;\n\t\t\t\t\tsuccess = isSuccess.data;\n\t\t\t\t\terror = isSuccess.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// We extract error from statusText\n\t\t\t\t// then normalize statusText and status for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t}\n});\n\n/* Handles responses to an ajax request:\n * - sets all responseXXX fields accordingly\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\tvar firstDataType, ct, finalDataType, type,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes,\n\t\tresponseFields = s.responseFields;\n\n\t// Fill responseXXX fields\n\tfor ( type in responseFields ) {\n\t\tif ( type in responses ) {\n\t\t\tjqXHR[ responseFields[type] ] = responses[ type ];\n\t\t}\n\t}\n\n\t// Remove auto dataType and get content-type in the process\n\twhile( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n// Chain conversions given the request and the original response\nfunction ajaxConvert( s, response ) {\n\tvar conv2, current, conv, tmp,\n\t\tconverters = {},\n\t\ti = 0,\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice(),\n\t\tprev = dataTypes[ 0 ];\n\n\t// Apply the dataFilter if provided\n\tif ( s.dataFilter ) {\n\t\tresponse = s.dataFilter( response, s.dataType );\n\t}\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\t// Convert to each sequential dataType, tolerating list modification\n\tfor ( ; (current = dataTypes[++i]); ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\tif ( current !== \"*\" ) {\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\tif ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split(\" \");\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.splice( i--, 0, current );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[\"throws\"] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Update prev for next iteration\n\t\t\tprev = current;\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and global\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t\ts.global = false;\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function(s) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\n\t\tvar script,\n\t\t\thead = document.head || jQuery(\"head\")[0] || document.documentElement;\n\n\t\treturn {\n\n\t\t\tsend: function( _, callback ) {\n\n\t\t\t\tscript = document.createElement(\"script\");\n\n\t\t\t\tscript.async = true;\n\n\t\t\t\tif ( s.scriptCharset ) {\n\t\t\t\t\tscript.charset = s.scriptCharset;\n\t\t\t\t}\n\n\t\t\t\tscript.src = s.url;\n\n\t\t\t\t// Attach handlers for all browsers\n\t\t\t\tscript.onload = script.onreadystatechange = function( _, isAbort ) {\n\n\t\t\t\t\tif ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {\n\n\t\t\t\t\t\t// Handle memory leak in IE\n\t\t\t\t\t\tscript.onload = script.onreadystatechange = null;\n\n\t\t\t\t\t\t// Remove the script\n\t\t\t\t\t\tif ( script.parentNode ) {\n\t\t\t\t\t\t\tscript.parentNode.removeChild( script );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Dereference the script\n\t\t\t\t\t\tscript = null;\n\n\t\t\t\t\t\t// Callback if not abort\n\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\tcallback( 200, \"success\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\t// Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\thead.insertBefore( script, head.firstChild );\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( script ) {\n\t\t\t\t\tscript.onload( undefined, true );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( ajax_nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( ajax_rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\nvar xhrCallbacks, xhrSupported,\n\txhrId = 0,\n\t// #5280: Internet Explorer will keep connections alive if we don't abort on unload\n\txhrOnUnloadAbort = window.ActiveXObject && function() {\n\t\t// Abort all pending requests\n\t\tvar key;\n\t\tfor ( key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]( undefined, true );\n\t\t}\n\t};\n\n// Functions to create xhrs\nfunction createStandardXHR() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch( e ) {}\n}\n\nfunction createActiveXHR() {\n\ttry {\n\t\treturn new window.ActiveXObject(\"Microsoft.XMLHTTP\");\n\t} catch( e ) {}\n}\n\n// Create the request object\n// (This is still attached to ajaxSettings for backward compatibility)\njQuery.ajaxSettings.xhr = window.ActiveXObject ?\n\t/* Microsoft failed to properly\n\t * implement the XMLHttpRequest in IE7 (can't request local files),\n\t * so we use the ActiveXObject when it is available\n\t * Additionally XMLHttpRequest can be disabled in IE7/IE8 so\n\t * we need a fallback.\n\t */\n\tfunction() {\n\t\treturn !this.isLocal && createStandardXHR() || createActiveXHR();\n\t} :\n\t// For all other browsers, use the standard XMLHttpRequest object\n\tcreateStandardXHR;\n\n// Determine support properties\nxhrSupported = jQuery.ajaxSettings.xhr();\njQuery.support.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nxhrSupported = jQuery.support.ajax = !!xhrSupported;\n\n// Create transport if the browser can provide an xhr\nif ( xhrSupported ) {\n\n\tjQuery.ajaxTransport(function( s ) {\n\t\t// Cross domain only allowed if supported through XMLHttpRequest\n\t\tif ( !s.crossDomain || jQuery.support.cors ) {\n\n\t\t\tvar callback;\n\n\t\t\treturn {\n\t\t\t\tsend: function( headers, complete ) {\n\n\t\t\t\t\t// Get a new xhr\n\t\t\t\t\tvar handle, i,\n\t\t\t\t\t\txhr = s.xhr();\n\n\t\t\t\t\t// Open the socket\n\t\t\t\t\t// Passing null username, generates a login popup on Opera (#2865)\n\t\t\t\t\tif ( s.username ) {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async, s.username, s.password );\n\t\t\t\t\t} else {\n\t\t\t\t\t\txhr.open( s.type, s.url, s.async );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Apply custom fields if provided\n\t\t\t\t\tif ( s.xhrFields ) {\n\t\t\t\t\t\tfor ( i in s.xhrFields ) {\n\t\t\t\t\t\t\txhr[ i ] = s.xhrFields[ i ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Override mime type if needed\n\t\t\t\t\tif ( s.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\t\txhr.overrideMimeType( s.mimeType );\n\t\t\t\t\t}\n\n\t\t\t\t\t// X-Requested-With header\n\t\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\t\tif ( !s.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Need an extra try/catch for cross domain requests in Firefox 3\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch( err ) {}\n\n\t\t\t\t\t// Do send the request\n\t\t\t\t\t// This may raise an exception which is actually\n\t\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n\t\t\t\t\txhr.send( ( s.hasContent && s.data ) || null );\n\n\t\t\t\t\t// Listener\n\t\t\t\t\tcallback = function( _, isAbort ) {\n\t\t\t\t\t\tvar status, responseHeaders, statusText, responses;\n\n\t\t\t\t\t\t// Firefox throws exceptions when accessing properties\n\t\t\t\t\t\t// of an xhr when a network error occurred\n\t\t\t\t\t\t// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)\n\t\t\t\t\t\ttry {\n\n\t\t\t\t\t\t\t// Was never called and is aborted or complete\n\t\t\t\t\t\t\tif ( callback && ( isAbort || xhr.readyState === 4 ) ) {\n\n\t\t\t\t\t\t\t\t// Only called once\n\t\t\t\t\t\t\t\tcallback = undefined;\n\n\t\t\t\t\t\t\t\t// Do not keep as active anymore\n\t\t\t\t\t\t\t\tif ( handle ) {\n\t\t\t\t\t\t\t\t\txhr.onreadystatechange = jQuery.noop;\n\t\t\t\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t\t\t\tdelete xhrCallbacks[ handle ];\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// If it's an abort\n\t\t\t\t\t\t\t\tif ( isAbort ) {\n\t\t\t\t\t\t\t\t\t// Abort it manually if needed\n\t\t\t\t\t\t\t\t\tif ( xhr.readyState !== 4 ) {\n\t\t\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tresponses = {};\n\t\t\t\t\t\t\t\t\tstatus = xhr.status;\n\t\t\t\t\t\t\t\t\tresponseHeaders = xhr.getAllResponseHeaders();\n\n\t\t\t\t\t\t\t\t\t// When requesting binary data, IE6-9 will throw an exception\n\t\t\t\t\t\t\t\t\t// on any attempt to access responseText (#11426)\n\t\t\t\t\t\t\t\t\tif ( typeof xhr.responseText === \"string\" ) {\n\t\t\t\t\t\t\t\t\t\tresponses.text = xhr.responseText;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Firefox throws an exception when accessing\n\t\t\t\t\t\t\t\t\t// statusText for faulty cross-domain requests\n\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\tstatusText = xhr.statusText;\n\t\t\t\t\t\t\t\t\t} catch( e ) {\n\t\t\t\t\t\t\t\t\t\t// We normalize with Webkit giving an empty statusText\n\t\t\t\t\t\t\t\t\t\tstatusText = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Filter status for non standard behaviors\n\n\t\t\t\t\t\t\t\t\t// If the request is local and we have data: assume a success\n\t\t\t\t\t\t\t\t\t// (success with no data won't get notified, that's the best we\n\t\t\t\t\t\t\t\t\t// can do given current implementations)\n\t\t\t\t\t\t\t\t\tif ( !status && s.isLocal && !s.crossDomain ) {\n\t\t\t\t\t\t\t\t\t\tstatus = responses.text ? 200 : 404;\n\t\t\t\t\t\t\t\t\t// IE - #1450: sometimes returns 1223 when it should be 204\n\t\t\t\t\t\t\t\t\t} else if ( status === 1223 ) {\n\t\t\t\t\t\t\t\t\t\tstatus = 204;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch( firefoxAccessException ) {\n\t\t\t\t\t\t\tif ( !isAbort ) {\n\t\t\t\t\t\t\t\tcomplete( -1, firefoxAccessException );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Call complete if needed\n\t\t\t\t\t\tif ( responses ) {\n\t\t\t\t\t\t\tcomplete( status, statusText, responses, responseHeaders );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( !s.async ) {\n\t\t\t\t\t\t// if we're in sync mode we fire the callback\n\t\t\t\t\t\tcallback();\n\t\t\t\t\t} else if ( xhr.readyState === 4 ) {\n\t\t\t\t\t\t// (IE6 & IE7) if it's in cache and has been\n\t\t\t\t\t\t// retrieved directly we need to fire the callback\n\t\t\t\t\t\tsetTimeout( callback );\n\t\t\t\t\t} else {\n\t\t\t\t\t\thandle = ++xhrId;\n\t\t\t\t\t\tif ( xhrOnUnloadAbort ) {\n\t\t\t\t\t\t\t// Create the active xhrs callbacks list if needed\n\t\t\t\t\t\t\t// and attach the unload handler\n\t\t\t\t\t\t\tif ( !xhrCallbacks ) {\n\t\t\t\t\t\t\t\txhrCallbacks = {};\n\t\t\t\t\t\t\t\tjQuery( window ).unload( xhrOnUnloadAbort );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// Add to list of active xhrs callbacks\n\t\t\t\t\t\t\txhrCallbacks[ handle ] = callback;\n\t\t\t\t\t\t}\n\t\t\t\t\t\txhr.onreadystatechange = callback;\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\tabort: function() {\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tcallback( undefined, true );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t});\n}\nvar fxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + core_pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [function( prop, value ) {\n\t\t\tvar end, unit,\n\t\t\t\ttween = this.createTween( prop, value ),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tstart = +target || 0,\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( parts ) {\n\t\t\t\tend = +parts[2];\n\t\t\t\tunit = parts[3] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\n\t\t\t\t// We need to compute starting value\n\t\t\t\tif ( unit !== \"px\" && start ) {\n\t\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\t\t// Prefer the current property, because this process will be trivial if it uses the same units\n\t\t\t\t\t// Fallback to end or a simple constant\n\t\t\t\t\tstart = jQuery.css( tween.elem, prop, true ) || end || 1;\n\n\t\t\t\t\tdo {\n\t\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*\n\t\t\t\t\t\t// Use a string for doubling factor so we don't accidentally see scale as unchanged below\n\t\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t\t// Adjust and apply\n\t\t\t\t\t\tstart = start / scale;\n\t\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t\t\t\t// And breaking the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t\t}\n\n\t\t\t\ttween.unit = unit;\n\t\t\t\ttween.start = start;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end;\n\t\t\t}\n\t\t\treturn tween;\n\t\t}]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t});\n\treturn ( fxNow = jQuery.now() );\n}\n\nfunction createTweens( animation, props ) {\n\tjQuery.each( props, function( prop, value ) {\n\t\tvar collection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\t\tindex = 0,\n\t\t\tlength = collection.length;\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tif ( collection[ index ].call( animation, prop, value ) ) {\n\n\t\t\t\t// we're done with this property\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\t// archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// if we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// resolve when we played the last frame\n\t\t\t\t// otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tcreateTweens( animation, props );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar value, name, index, easing, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// not quite $.extend, this wont overwrite keys already present.\n\t\t\t// also - reusing 'index' from above because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/*jshint validthis:true */\n\tvar prop, index, length,\n\t\tvalue, dataShow, toggle,\n\t\ttween, hooks, oldfire,\n\t\tanim = this,\n\t\tstyle = elem.style,\n\t\torig = {},\n\t\thandled = [],\n\t\thidden = elem.nodeType && isHidden( elem );\n\n\t// handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// doing this makes sure that the complete handler will be called\n\t\t\t// before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE does not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tif ( jQuery.css( elem, \"display\" ) === \"inline\" &&\n\t\t\t\tjQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t// inline-level elements accept inline-block;\n\t\t\t// block-level elements need to be inline with layout\n\t\t\tif ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === \"inline\" ) {\n\t\t\t\tstyle.display = \"inline-block\";\n\n\t\t\t} else {\n\t\t\t\tstyle.zoom = 1;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tif ( !jQuery.support.shrinkWrapBlocks ) {\n\t\t\tanim.always(function() {\n\t\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t\t});\n\t\t}\n\t}\n\n\n\t// show/hide pass\n\tfor ( index in props ) {\n\t\tvalue = props[ index ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ index ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\thandled.push( index );\n\t\t}\n\t}\n\n\tlength = handled.length;\n\tif ( length ) {\n\t\tdataShow = jQuery._data( elem, \"fxshow\" ) || jQuery._data( elem, \"fxshow\", {} );\n\t\tif ( \"hidden\" in dataShow ) {\n\t\t\thidden = dataShow.hidden;\n\t\t}\n\n\t\t// store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\t\t\tjQuery._removeData( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( index = 0 ; index < length ; index++ ) {\n\t\t\tprop = handled[ index ];\n\t\t\ttween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 );\n\t\t\torig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails\n\t\t\t// so, simple values such as \"10px\" are parsed to Float.\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// use step hook for back compat - use cssHook if its there - use .style if its\n\t\t\t// available and use plain properties where available\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Remove in 2.0 - this supports IE8's panic based approach\n// to setting things on disconnected nodes\n\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\t\t\t\tdoAnimation.finish = function() {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t};\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || jQuery._data( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = jQuery._data( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// start the next in the queue if the last step wasn't forced\n\t\t\t// timers currently will call their complete callbacks, which will dequeue\n\t\t\t// but only if they were gotoEnd\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\tdata = jQuery._data( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.cur && hooks.cur.finish ) {\n\t\t\t\thooks.cur.finish.call( this );\n\t\t\t}\n\n\t\t\t// look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\tattrs = { height: type },\n\t\ti = 0;\n\n\t// if we include width, step value is 1 to do all cssExpand values,\n\t// if we don't include width, step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth? 1 : 0;\n\tfor( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p*Math.PI ) / 2;\n\t}\n};\n\njQuery.timers = [];\njQuery.fx = Tween.prototype.init;\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ttimers = jQuery.timers,\n\t\ti = 0;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tif ( timer() && jQuery.timers.push( timer ) ) {\n\t\tjQuery.fx.start();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\nif ( jQuery.expr && jQuery.expr.filters ) {\n\tjQuery.expr.filters.animated = function( elem ) {\n\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\t\treturn elem === fn.elem;\n\t\t}).length;\n\t};\n}\njQuery.fn.offset = function( options ) {\n\tif ( arguments.length ) {\n\t\treturn options === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function( i ) {\n\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t});\n\t}\n\n\tvar docElem, win,\n\t\tbox = { top: 0, left: 0 },\n\t\telem = this[ 0 ],\n\t\tdoc = elem && elem.ownerDocument;\n\n\tif ( !doc ) {\n\t\treturn;\n\t}\n\n\tdocElem = doc.documentElement;\n\n\t// Make sure it's not a disconnected DOM node\n\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\treturn box;\n\t}\n\n\t// If we don't have gBCR, just use 0,0 rather than error\n\t// BlackBerry 5, iOS 3 (original iPhone)\n\tif ( typeof elem.getBoundingClientRect !== core_strundefined ) {\n\t\tbox = elem.getBoundingClientRect();\n\t}\n\twin = getWindow( doc );\n\treturn {\n\t\ttop: box.top  + ( win.pageYOffset || docElem.scrollTop )  - ( docElem.clientTop  || 0 ),\n\t\tleft: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )\n\t};\n};\n\njQuery.offset = {\n\n\tsetOffset: function( elem, options, i ) {\n\t\tvar position = jQuery.css( elem, \"position\" );\n\n\t\t// set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tvar curElem = jQuery( elem ),\n\t\t\tcurOffset = curElem.offset(),\n\t\t\tcurCSSTop = jQuery.css( elem, \"top\" ),\n\t\t\tcurCSSLeft = jQuery.css( elem, \"left\" ),\n\t\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) && jQuery.inArray(\"auto\", [curCSSTop, curCSSLeft]) > -1,\n\t\t\tprops = {}, curPosition = {}, curTop, curLeft;\n\n\t\t// need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\n\njQuery.fn.extend({\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\tparentOffset = { top: 0, left: 0 },\n\t\t\telem = this[ 0 ];\n\n\t\t// fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// we assume that getBoundingClientRect is available when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top  += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\t// note: when an element has margin: auto the offsetLeft and marginLeft\n\t\t// are the same in Safari causing offset.left to incorrectly be 0\n\t\treturn {\n\t\t\ttop:  offset.top  - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true)\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || document.documentElement;\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\") === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\t\t\treturn offsetParent || document.documentElement;\n\t\t});\n\t}\n});\n\n\n// Create scrollLeft and scrollTop methods\njQuery.each( {scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\"}, function( method, prop ) {\n\tvar top = /Y/.test( prop );\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn jQuery.access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? (prop in win) ? win[ prop ] :\n\t\t\t\t\twin.document.documentElement[ method ] :\n\t\t\t\t\telem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : jQuery( win ).scrollLeft(),\n\t\t\t\t\ttop ? val : jQuery( win ).scrollTop()\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ?\n\t\telem :\n\t\telem.nodeType === 9 ?\n\t\t\telem.defaultView || elem.parentWindow :\n\t\t\tfalse;\n}\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn jQuery.access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest\n\t\t\t\t\t// unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n// Limit scope pollution from any deprecated API\n// (function() {\n\n// })();\n// Expose jQuery to the global object\nwindow.jQuery = window.$ = jQuery;\n\n// Expose jQuery as an AMD module, but only for AMD loaders that\n// understand the issues with loading multiple versions of jQuery\n// in a page that all might call define(). The loader will indicate\n// they have special allowances for multiple jQuery versions by\n// specifying define.amd.jQuery = true. Register as a named module,\n// since jQuery can be concatenated with other files that may use define,\n// but not use a proper concatenation script that understands anonymous\n// AMD modules. A named AMD is safest and most robust way to register.\n// Lowercase jquery is used because AMD module names are derived from\n// file names, and jQuery is normally delivered in a lowercase file name.\n// Do this after creating the global so that if an AMD module wants to call\n// noConflict to hide this version of jQuery, it will work.\nif ( typeof define === \"function\" && define.amd && define.amd.jQuery ) {\n\tdefine( \"jquery\", [], function () { return jQuery; } );\n}\n\n})( window );\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/jquery.contextmenu/jquery.contextmenu.r2.js",
    "content": "/*\n * ContextMenu - jQuery plugin for right-click context menus\n *\n * Author: Chris Domigan\n * Contributors: Dan G. Switzer, II\n * Parts of this plugin are inspired by Joern Zaefferer's Tooltip plugin\n *\n * Dual licensed under the MIT and GPL licenses:\n *   http://www.opensource.org/licenses/mit-license.php\n *   http://www.gnu.org/licenses/gpl.html\n *\n * Version: r2\n * Date: 16 July 2007\n *\n * For documentation visit http://www.trendskitchens.co.nz/jquery/contextmenu/\n *\n */\n\n(function($) {\n\n \tvar menu, shadow, trigger, content, hash, currentTarget;\n  var defaults = {\n    menuStyle: {\n      listStyle: 'none',\n      padding: '1px',\n      margin: '0px',\n      backgroundColor: '#fff',\n      border: '1px solid #999',\n      width: '100px'\n    },\n    itemStyle: {\n      margin: '0px',\n      color: '#000',\n      display: 'block',\n      cursor: 'default',\n      padding: '3px',\n      border: '1px solid #fff',\n      backgroundColor: 'transparent'\n    },\n    itemHoverStyle: {\n      border: '1px solid #0a246a',\n      backgroundColor: '#b6bdd2'\n    },\n    eventPosX: 'pageX',\n    eventPosY: 'pageY',\n    shadow : true,\n    onContextMenu: null,\n    onShowMenu: null\n \t};\n\n  $.fn.contextMenu = function(id, options) {\n    if (!menu) {                                      // Create singleton menu\n      menu = $('<div id=\"jqContextMenu\"></div>')\n               .hide()\n               .css({position:'absolute', zIndex:'500'})\n               .appendTo('body')\n               .bind('click', function(e) {\n                 e.stopPropagation();\n               });\n    }\n    if (!shadow) {\n      shadow = $('<div></div>')\n                 .css({backgroundColor:'#000',position:'absolute',opacity:0.2,zIndex:499})\n                 .appendTo('body')\n                 .hide();\n    }\n    hash = hash || [];\n    hash.push({\n      id : id,\n      menuStyle: $.extend({}, defaults.menuStyle, options.menuStyle || {}),\n      itemStyle: $.extend({}, defaults.itemStyle, options.itemStyle || {}),\n      itemHoverStyle: $.extend({}, defaults.itemHoverStyle, options.itemHoverStyle || {}),\n      bindings: options.bindings || {},\n      shadow: options.shadow || options.shadow === false ? options.shadow : defaults.shadow,\n      onContextMenu: options.onContextMenu || defaults.onContextMenu,\n      onShowMenu: options.onShowMenu || defaults.onShowMenu,\n      eventPosX: options.eventPosX || defaults.eventPosX,\n      eventPosY: options.eventPosY || defaults.eventPosY\n    });\n\n    var index = hash.length - 1;\n    $(this).bind('contextmenu', function(e) {\n      // Check if onContextMenu() defined\n      var bShowContext = (!!hash[index].onContextMenu) ? hash[index].onContextMenu(e) : true;\n      if (bShowContext) display(index, this, e, options);\n      return false;\n    });\n    return this;\n  };\n\n  function display(index, trigger, e, options) {\n    var cur = hash[index];\n    content = $('#'+cur.id).find('ul:first').clone(true);\n    content.css(cur.menuStyle).find('li').css(cur.itemStyle).hover(\n      function() {\n        $(this).css(cur.itemHoverStyle);\n      },\n      function(){\n        $(this).css(cur.itemStyle);\n      }\n    ).find('img').css({verticalAlign:'middle',paddingRight:'2px'});\n\n    // Send the content to the menu\n    menu.html(content);\n\n    // if there's an onShowMenu, run it now -- must run after content has been added\n\t\t// if you try to alter the content variable before the menu.html(), IE6 has issues\n\t\t// updating the content\n    if (!!cur.onShowMenu) menu = cur.onShowMenu(e, menu);\n\n    $.each(cur.bindings, function(id, func) {\n      $('#'+id, menu).bind('click', function(e) {\n        hide();\n        func(trigger, currentTarget);\n      });\n    });\n\n    menu.css({'left':e[cur.eventPosX],'top':e[cur.eventPosY]}).show();\n    if (cur.shadow) shadow.css({width:menu.width(),height:menu.height(),left:e.pageX+2,top:e.pageY+2}).show();\n    $(document).one('click', hide);\n  }\n\n  function hide() {\n    menu.hide();\n    shadow.hide();\n  }\n\n  // Apply defaults\n  $.contextMenu = {\n    defaults : function(userDefaults) {\n      $.each(userDefaults, function(i, val) {\n        if (typeof val == 'object' && defaults[i]) {\n          $.extend(defaults[i], val);\n        }\n        else defaults[i] = val;\n      });\n    }\n  };\n\n})(jQuery);\n\n$(function() {\n  $('div.contextMenu').hide();\n});"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/jquery.validation/1.14.0/additional-methods.js",
    "content": "/*!\n * jQuery Validation Plugin v1.14.0\n *\n * http://jqueryvalidation.org/\n *\n * Copyright (c) 2015 Jörn Zaefferer\n * Released under the MIT license\n */\n(function( factory ) {\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\tdefine( [\"jquery\", \"./jquery.validate\"], factory );\n\t} else {\n\t\tfactory( jQuery );\n\t}\n}(function( $ ) {\n\n(function() {\n\n\tfunction stripHtml(value) {\n\t\t// remove html tags and space chars\n\t\treturn value.replace(/<.[^<>]*?>/g, \" \").replace(/&nbsp;|&#160;/gi, \" \")\n\t\t// remove punctuation\n\t\t.replace(/[.(),;:!?%#$'\\\"_+=\\/\\-“”’]*/g, \"\");\n\t}\n\n\t$.validator.addMethod(\"maxWords\", function(value, element, params) {\n\t\treturn this.optional(element) || stripHtml(value).match(/\\b\\w+\\b/g).length <= params;\n\t}, $.validator.format(\"Please enter {0} words or less.\"));\n\n\t$.validator.addMethod(\"minWords\", function(value, element, params) {\n\t\treturn this.optional(element) || stripHtml(value).match(/\\b\\w+\\b/g).length >= params;\n\t}, $.validator.format(\"Please enter at least {0} words.\"));\n\n\t$.validator.addMethod(\"rangeWords\", function(value, element, params) {\n\t\tvar valueStripped = stripHtml(value),\n\t\t\tregex = /\\b\\w+\\b/g;\n\t\treturn this.optional(element) || valueStripped.match(regex).length >= params[0] && valueStripped.match(regex).length <= params[1];\n\t}, $.validator.format(\"Please enter between {0} and {1} words.\"));\n\n}());\n\n// Accept a value from a file input based on a required mimetype\n$.validator.addMethod(\"accept\", function(value, element, param) {\n\t// Split mime on commas in case we have multiple types we can accept\n\tvar typeParam = typeof param === \"string\" ? param.replace(/\\s/g, \"\").replace(/,/g, \"|\") : \"image/*\",\n\toptionalValue = this.optional(element),\n\ti, file;\n\n\t// Element is optional\n\tif (optionalValue) {\n\t\treturn optionalValue;\n\t}\n\n\tif ($(element).attr(\"type\") === \"file\") {\n\t\t// If we are using a wildcard, make it regex friendly\n\t\ttypeParam = typeParam.replace(/\\*/g, \".*\");\n\n\t\t// Check if the element has a FileList before checking each file\n\t\tif (element.files && element.files.length) {\n\t\t\tfor (i = 0; i < element.files.length; i++) {\n\t\t\t\tfile = element.files[i];\n\n\t\t\t\t// Grab the mimetype from the loaded file, verify it matches\n\t\t\t\tif (!file.type.match(new RegExp( \"\\\\.?(\" + typeParam + \")$\", \"i\"))) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Either return true because we've validated each file, or because the\n\t// browser does not support element.files and the FileList feature\n\treturn true;\n}, $.validator.format(\"Please enter a value with a valid mimetype.\"));\n\n$.validator.addMethod(\"alphanumeric\", function(value, element) {\n\treturn this.optional(element) || /^\\w+$/i.test(value);\n}, \"Letters, numbers, and underscores only please\");\n\n/*\n * Dutch bank account numbers (not 'giro' numbers) have 9 digits\n * and pass the '11 check'.\n * We accept the notation with spaces, as that is common.\n * acceptable: 123456789 or 12 34 56 789\n */\n$.validator.addMethod(\"bankaccountNL\", function(value, element) {\n\tif (this.optional(element)) {\n\t\treturn true;\n\t}\n\tif (!(/^[0-9]{9}|([0-9]{2} ){3}[0-9]{3}$/.test(value))) {\n\t\treturn false;\n\t}\n\t// now '11 check'\n\tvar account = value.replace(/ /g, \"\"), // remove spaces\n\t\tsum = 0,\n\t\tlen = account.length,\n\t\tpos, factor, digit;\n\tfor ( pos = 0; pos < len; pos++ ) {\n\t\tfactor = len - pos;\n\t\tdigit = account.substring(pos, pos + 1);\n\t\tsum = sum + factor * digit;\n\t}\n\treturn sum % 11 === 0;\n}, \"Please specify a valid bank account number\");\n\n$.validator.addMethod(\"bankorgiroaccountNL\", function(value, element) {\n\treturn this.optional(element) ||\n\t\t\t($.validator.methods.bankaccountNL.call(this, value, element)) ||\n\t\t\t($.validator.methods.giroaccountNL.call(this, value, element));\n}, \"Please specify a valid bank or giro account number\");\n\n/**\n * BIC is the business identifier code (ISO 9362). This BIC check is not a guarantee for authenticity.\n *\n * BIC pattern: BBBBCCLLbbb (8 or 11 characters long; bbb is optional)\n *\n * BIC definition in detail:\n * - First 4 characters - bank code (only letters)\n * - Next 2 characters - ISO 3166-1 alpha-2 country code (only letters)\n * - Next 2 characters - location code (letters and digits)\n *   a. shall not start with '0' or '1'\n *   b. second character must be a letter ('O' is not allowed) or one of the following digits ('0' for test (therefore not allowed), '1' for passive participant and '2' for active participant)\n * - Last 3 characters - branch code, optional (shall not start with 'X' except in case of 'XXX' for primary office) (letters and digits)\n */\n$.validator.addMethod(\"bic\", function(value, element) {\n    return this.optional( element ) || /^([A-Z]{6}[A-Z2-9][A-NP-Z1-2])(X{3}|[A-WY-Z0-9][A-Z0-9]{2})?$/.test( value );\n}, \"Please specify a valid BIC code\");\n\n/*\n * Código de identificación fiscal ( CIF ) is the tax identification code for Spanish legal entities\n * Further rules can be found in Spanish on http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal\n */\n$.validator.addMethod( \"cifES\", function( value ) {\n\t\"use strict\";\n\n\tvar num = [],\n\t\tcontrolDigit, sum, i, count, tmp, secondDigit;\n\n\tvalue = value.toUpperCase();\n\n\t// Quick format test\n\tif ( !value.match( \"((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)\" ) ) {\n\t\treturn false;\n\t}\n\n\tfor ( i = 0; i < 9; i++ ) {\n\t\tnum[ i ] = parseInt( value.charAt( i ), 10 );\n\t}\n\n\t// Algorithm for checking CIF codes\n\tsum = num[ 2 ] + num[ 4 ] + num[ 6 ];\n\tfor ( count = 1; count < 8; count += 2 ) {\n\t\ttmp = ( 2 * num[ count ] ).toString();\n\t\tsecondDigit = tmp.charAt( 1 );\n\n\t\tsum += parseInt( tmp.charAt( 0 ), 10 ) + ( secondDigit === \"\" ? 0 : parseInt( secondDigit, 10 ) );\n\t}\n\n\t/* The first (position 1) is a letter following the following criteria:\n\t *\tA. Corporations\n\t *\tB. LLCs\n\t *\tC. General partnerships\n\t *\tD. Companies limited partnerships\n\t *\tE. Communities of goods\n\t *\tF. Cooperative Societies\n\t *\tG. Associations\n\t *\tH. Communities of homeowners in horizontal property regime\n\t *\tJ. Civil Societies\n\t *\tK. Old format\n\t *\tL. Old format\n\t *\tM. Old format\n\t *\tN. Nonresident entities\n\t *\tP. Local authorities\n\t *\tQ. Autonomous bodies, state or not, and the like, and congregations and religious institutions\n\t *\tR. Congregations and religious institutions (since 2008 ORDER EHA/451/2008)\n\t *\tS. Organs of State Administration and regions\n\t *\tV. Agrarian Transformation\n\t *\tW. Permanent establishments of non-resident in Spain\n\t */\n\tif ( /^[ABCDEFGHJNPQRSUVW]{1}/.test( value ) ) {\n\t\tsum += \"\";\n\t\tcontrolDigit = 10 - parseInt( sum.charAt( sum.length - 1 ), 10 );\n\t\tvalue += controlDigit;\n\t\treturn ( num[ 8 ].toString() === String.fromCharCode( 64 + controlDigit ) || num[ 8 ].toString() === value.charAt( value.length - 1 ) );\n\t}\n\n\treturn false;\n\n}, \"Please specify a valid CIF number.\" );\n\n/*\n * Brazillian CPF number (Cadastrado de Pessoas Físicas) is the equivalent of a Brazilian tax registration number.\n * CPF numbers have 11 digits in total: 9 numbers followed by 2 check numbers that are being used for validation.\n */\n$.validator.addMethod(\"cpfBR\", function(value) {\n\t// Removing special characters from value\n\tvalue = value.replace(/([~!@#$%^&*()_+=`{}\\[\\]\\-|\\\\:;'<>,.\\/? ])+/g, \"\");\n\n\t// Checking value to have 11 digits only\n\tif (value.length !== 11) {\n\t\treturn false;\n\t}\n\n\tvar sum = 0,\n\t\tfirstCN, secondCN, checkResult, i;\n\n\tfirstCN = parseInt(value.substring(9, 10), 10);\n\tsecondCN = parseInt(value.substring(10, 11), 10);\n\n\tcheckResult = function(sum, cn) {\n\t\tvar result = (sum * 10) % 11;\n\t\tif ((result === 10) || (result === 11)) {result = 0;}\n\t\treturn (result === cn);\n\t};\n\n\t// Checking for dump data\n\tif (value === \"\" ||\n\t\tvalue === \"00000000000\" ||\n\t\tvalue === \"11111111111\" ||\n\t\tvalue === \"22222222222\" ||\n\t\tvalue === \"33333333333\" ||\n\t\tvalue === \"44444444444\" ||\n\t\tvalue === \"55555555555\" ||\n\t\tvalue === \"66666666666\" ||\n\t\tvalue === \"77777777777\" ||\n\t\tvalue === \"88888888888\" ||\n\t\tvalue === \"99999999999\"\n\t) {\n\t\treturn false;\n\t}\n\n\t// Step 1 - using first Check Number:\n\tfor ( i = 1; i <= 9; i++ ) {\n\t\tsum = sum + parseInt(value.substring(i - 1, i), 10) * (11 - i);\n\t}\n\n\t// If first Check Number (CN) is valid, move to Step 2 - using second Check Number:\n\tif ( checkResult(sum, firstCN) ) {\n\t\tsum = 0;\n\t\tfor ( i = 1; i <= 10; i++ ) {\n\t\t\tsum = sum + parseInt(value.substring(i - 1, i), 10) * (12 - i);\n\t\t}\n\t\treturn checkResult(sum, secondCN);\n\t}\n\treturn false;\n\n}, \"Please specify a valid CPF number\");\n\n/* NOTICE: Modified version of Castle.Components.Validator.CreditCardValidator\n * Redistributed under the the Apache License 2.0 at http://www.apache.org/licenses/LICENSE-2.0\n * Valid Types: mastercard, visa, amex, dinersclub, enroute, discover, jcb, unknown, all (overrides all other settings)\n */\n$.validator.addMethod(\"creditcardtypes\", function(value, element, param) {\n\tif (/[^0-9\\-]+/.test(value)) {\n\t\treturn false;\n\t}\n\n\tvalue = value.replace(/\\D/g, \"\");\n\n\tvar validTypes = 0x0000;\n\n\tif (param.mastercard) {\n\t\tvalidTypes |= 0x0001;\n\t}\n\tif (param.visa) {\n\t\tvalidTypes |= 0x0002;\n\t}\n\tif (param.amex) {\n\t\tvalidTypes |= 0x0004;\n\t}\n\tif (param.dinersclub) {\n\t\tvalidTypes |= 0x0008;\n\t}\n\tif (param.enroute) {\n\t\tvalidTypes |= 0x0010;\n\t}\n\tif (param.discover) {\n\t\tvalidTypes |= 0x0020;\n\t}\n\tif (param.jcb) {\n\t\tvalidTypes |= 0x0040;\n\t}\n\tif (param.unknown) {\n\t\tvalidTypes |= 0x0080;\n\t}\n\tif (param.all) {\n\t\tvalidTypes = 0x0001 | 0x0002 | 0x0004 | 0x0008 | 0x0010 | 0x0020 | 0x0040 | 0x0080;\n\t}\n\tif (validTypes & 0x0001 && /^(5[12345])/.test(value)) { //mastercard\n\t\treturn value.length === 16;\n\t}\n\tif (validTypes & 0x0002 && /^(4)/.test(value)) { //visa\n\t\treturn value.length === 16;\n\t}\n\tif (validTypes & 0x0004 && /^(3[47])/.test(value)) { //amex\n\t\treturn value.length === 15;\n\t}\n\tif (validTypes & 0x0008 && /^(3(0[012345]|[68]))/.test(value)) { //dinersclub\n\t\treturn value.length === 14;\n\t}\n\tif (validTypes & 0x0010 && /^(2(014|149))/.test(value)) { //enroute\n\t\treturn value.length === 15;\n\t}\n\tif (validTypes & 0x0020 && /^(6011)/.test(value)) { //discover\n\t\treturn value.length === 16;\n\t}\n\tif (validTypes & 0x0040 && /^(3)/.test(value)) { //jcb\n\t\treturn value.length === 16;\n\t}\n\tif (validTypes & 0x0040 && /^(2131|1800)/.test(value)) { //jcb\n\t\treturn value.length === 15;\n\t}\n\tif (validTypes & 0x0080) { //unknown\n\t\treturn true;\n\t}\n\treturn false;\n}, \"Please enter a valid credit card number.\");\n\n/**\n * Validates currencies with any given symbols by @jameslouiz\n * Symbols can be optional or required. Symbols required by default\n *\n * Usage examples:\n *  currency: [\"£\", false] - Use false for soft currency validation\n *  currency: [\"$\", false]\n *  currency: [\"RM\", false] - also works with text based symbols such as \"RM\" - Malaysia Ringgit etc\n *\n *  <input class=\"currencyInput\" name=\"currencyInput\">\n *\n * Soft symbol checking\n *  currencyInput: {\n *     currency: [\"$\", false]\n *  }\n *\n * Strict symbol checking (default)\n *  currencyInput: {\n *     currency: \"$\"\n *     //OR\n *     currency: [\"$\", true]\n *  }\n *\n * Multiple Symbols\n *  currencyInput: {\n *     currency: \"$,£,¢\"\n *  }\n */\n$.validator.addMethod(\"currency\", function(value, element, param) {\n    var isParamString = typeof param === \"string\",\n        symbol = isParamString ? param : param[0],\n        soft = isParamString ? true : param[1],\n        regex;\n\n    symbol = symbol.replace(/,/g, \"\");\n    symbol = soft ? symbol + \"]\" : symbol + \"]?\";\n    regex = \"^[\" + symbol + \"([1-9]{1}[0-9]{0,2}(\\\\,[0-9]{3})*(\\\\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\\\\.[0-9]{0,2})?|0(\\\\.[0-9]{0,2})?|(\\\\.[0-9]{1,2})?)$\";\n    regex = new RegExp(regex);\n    return this.optional(element) || regex.test(value);\n\n}, \"Please specify a valid currency\");\n\n$.validator.addMethod(\"dateFA\", function(value, element) {\n\treturn this.optional(element) || /^[1-4]\\d{3}\\/((0?[1-6]\\/((3[0-1])|([1-2][0-9])|(0?[1-9])))|((1[0-2]|(0?[7-9]))\\/(30|([1-2][0-9])|(0?[1-9]))))$/.test(value);\n}, $.validator.messages.date);\n\n/**\n * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.\n *\n * @example $.validator.methods.date(\"01/01/1900\")\n * @result true\n *\n * @example $.validator.methods.date(\"01/13/1990\")\n * @result false\n *\n * @example $.validator.methods.date(\"01.01.1900\")\n * @result false\n *\n * @example <input name=\"pippo\" class=\"{dateITA:true}\" />\n * @desc Declares an optional input element whose value must be a valid date.\n *\n * @name $.validator.methods.dateITA\n * @type Boolean\n * @cat Plugins/Validate/Methods\n */\n$.validator.addMethod(\"dateITA\", function(value, element) {\n\tvar check = false,\n\t\tre = /^\\d{1,2}\\/\\d{1,2}\\/\\d{4}$/,\n\t\tadata, gg, mm, aaaa, xdata;\n\tif ( re.test(value)) {\n\t\tadata = value.split(\"/\");\n\t\tgg = parseInt(adata[0], 10);\n\t\tmm = parseInt(adata[1], 10);\n\t\taaaa = parseInt(adata[2], 10);\n\t\txdata = new Date(Date.UTC(aaaa, mm - 1, gg, 12, 0, 0, 0));\n\t\tif ( ( xdata.getUTCFullYear() === aaaa ) && ( xdata.getUTCMonth () === mm - 1 ) && ( xdata.getUTCDate() === gg ) ) {\n\t\t\tcheck = true;\n\t\t} else {\n\t\t\tcheck = false;\n\t\t}\n\t} else {\n\t\tcheck = false;\n\t}\n\treturn this.optional(element) || check;\n}, $.validator.messages.date);\n\n$.validator.addMethod(\"dateNL\", function(value, element) {\n\treturn this.optional(element) || /^(0?[1-9]|[12]\\d|3[01])[\\.\\/\\-](0?[1-9]|1[012])[\\.\\/\\-]([12]\\d)?(\\d\\d)$/.test(value);\n}, $.validator.messages.date);\n\n// Older \"accept\" file extension method. Old docs: http://docs.jquery.com/Plugins/Validation/Methods/accept\n$.validator.addMethod(\"extension\", function(value, element, param) {\n\tparam = typeof param === \"string\" ? param.replace(/,/g, \"|\") : \"png|jpe?g|gif\";\n\treturn this.optional(element) || value.match(new RegExp(\"\\\\.(\" + param + \")$\", \"i\"));\n}, $.validator.format(\"Please enter a value with a valid extension.\"));\n\n/**\n * Dutch giro account numbers (not bank numbers) have max 7 digits\n */\n$.validator.addMethod(\"giroaccountNL\", function(value, element) {\n\treturn this.optional(element) || /^[0-9]{1,7}$/.test(value);\n}, \"Please specify a valid giro account number\");\n\n/**\n * IBAN is the international bank account number.\n * It has a country - specific format, that is checked here too\n */\n$.validator.addMethod(\"iban\", function(value, element) {\n\t// some quick simple tests to prevent needless work\n\tif (this.optional(element)) {\n\t\treturn true;\n\t}\n\n\t// remove spaces and to upper case\n\tvar iban = value.replace(/ /g, \"\").toUpperCase(),\n\t\tibancheckdigits = \"\",\n\t\tleadingZeroes = true,\n\t\tcRest = \"\",\n\t\tcOperator = \"\",\n\t\tcountrycode, ibancheck, charAt, cChar, bbanpattern, bbancountrypatterns, ibanregexp, i, p;\n\n\t// check the country code and find the country specific format\n\tcountrycode = iban.substring(0, 2);\n\tbbancountrypatterns = {\n\t\t\"AL\": \"\\\\d{8}[\\\\dA-Z]{16}\",\n\t\t\"AD\": \"\\\\d{8}[\\\\dA-Z]{12}\",\n\t\t\"AT\": \"\\\\d{16}\",\n\t\t\"AZ\": \"[\\\\dA-Z]{4}\\\\d{20}\",\n\t\t\"BE\": \"\\\\d{12}\",\n\t\t\"BH\": \"[A-Z]{4}[\\\\dA-Z]{14}\",\n\t\t\"BA\": \"\\\\d{16}\",\n\t\t\"BR\": \"\\\\d{23}[A-Z][\\\\dA-Z]\",\n\t\t\"BG\": \"[A-Z]{4}\\\\d{6}[\\\\dA-Z]{8}\",\n\t\t\"CR\": \"\\\\d{17}\",\n\t\t\"HR\": \"\\\\d{17}\",\n\t\t\"CY\": \"\\\\d{8}[\\\\dA-Z]{16}\",\n\t\t\"CZ\": \"\\\\d{20}\",\n\t\t\"DK\": \"\\\\d{14}\",\n\t\t\"DO\": \"[A-Z]{4}\\\\d{20}\",\n\t\t\"EE\": \"\\\\d{16}\",\n\t\t\"FO\": \"\\\\d{14}\",\n\t\t\"FI\": \"\\\\d{14}\",\n\t\t\"FR\": \"\\\\d{10}[\\\\dA-Z]{11}\\\\d{2}\",\n\t\t\"GE\": \"[\\\\dA-Z]{2}\\\\d{16}\",\n\t\t\"DE\": \"\\\\d{18}\",\n\t\t\"GI\": \"[A-Z]{4}[\\\\dA-Z]{15}\",\n\t\t\"GR\": \"\\\\d{7}[\\\\dA-Z]{16}\",\n\t\t\"GL\": \"\\\\d{14}\",\n\t\t\"GT\": \"[\\\\dA-Z]{4}[\\\\dA-Z]{20}\",\n\t\t\"HU\": \"\\\\d{24}\",\n\t\t\"IS\": \"\\\\d{22}\",\n\t\t\"IE\": \"[\\\\dA-Z]{4}\\\\d{14}\",\n\t\t\"IL\": \"\\\\d{19}\",\n\t\t\"IT\": \"[A-Z]\\\\d{10}[\\\\dA-Z]{12}\",\n\t\t\"KZ\": \"\\\\d{3}[\\\\dA-Z]{13}\",\n\t\t\"KW\": \"[A-Z]{4}[\\\\dA-Z]{22}\",\n\t\t\"LV\": \"[A-Z]{4}[\\\\dA-Z]{13}\",\n\t\t\"LB\": \"\\\\d{4}[\\\\dA-Z]{20}\",\n\t\t\"LI\": \"\\\\d{5}[\\\\dA-Z]{12}\",\n\t\t\"LT\": \"\\\\d{16}\",\n\t\t\"LU\": \"\\\\d{3}[\\\\dA-Z]{13}\",\n\t\t\"MK\": \"\\\\d{3}[\\\\dA-Z]{10}\\\\d{2}\",\n\t\t\"MT\": \"[A-Z]{4}\\\\d{5}[\\\\dA-Z]{18}\",\n\t\t\"MR\": \"\\\\d{23}\",\n\t\t\"MU\": \"[A-Z]{4}\\\\d{19}[A-Z]{3}\",\n\t\t\"MC\": \"\\\\d{10}[\\\\dA-Z]{11}\\\\d{2}\",\n\t\t\"MD\": \"[\\\\dA-Z]{2}\\\\d{18}\",\n\t\t\"ME\": \"\\\\d{18}\",\n\t\t\"NL\": \"[A-Z]{4}\\\\d{10}\",\n\t\t\"NO\": \"\\\\d{11}\",\n\t\t\"PK\": \"[\\\\dA-Z]{4}\\\\d{16}\",\n\t\t\"PS\": \"[\\\\dA-Z]{4}\\\\d{21}\",\n\t\t\"PL\": \"\\\\d{24}\",\n\t\t\"PT\": \"\\\\d{21}\",\n\t\t\"RO\": \"[A-Z]{4}[\\\\dA-Z]{16}\",\n\t\t\"SM\": \"[A-Z]\\\\d{10}[\\\\dA-Z]{12}\",\n\t\t\"SA\": \"\\\\d{2}[\\\\dA-Z]{18}\",\n\t\t\"RS\": \"\\\\d{18}\",\n\t\t\"SK\": \"\\\\d{20}\",\n\t\t\"SI\": \"\\\\d{15}\",\n\t\t\"ES\": \"\\\\d{20}\",\n\t\t\"SE\": \"\\\\d{20}\",\n\t\t\"CH\": \"\\\\d{5}[\\\\dA-Z]{12}\",\n\t\t\"TN\": \"\\\\d{20}\",\n\t\t\"TR\": \"\\\\d{5}[\\\\dA-Z]{17}\",\n\t\t\"AE\": \"\\\\d{3}\\\\d{16}\",\n\t\t\"GB\": \"[A-Z]{4}\\\\d{14}\",\n\t\t\"VG\": \"[\\\\dA-Z]{4}\\\\d{16}\"\n\t};\n\n\tbbanpattern = bbancountrypatterns[countrycode];\n\t// As new countries will start using IBAN in the\n\t// future, we only check if the countrycode is known.\n\t// This prevents false negatives, while almost all\n\t// false positives introduced by this, will be caught\n\t// by the checksum validation below anyway.\n\t// Strict checking should return FALSE for unknown\n\t// countries.\n\tif (typeof bbanpattern !== \"undefined\") {\n\t\tibanregexp = new RegExp(\"^[A-Z]{2}\\\\d{2}\" + bbanpattern + \"$\", \"\");\n\t\tif (!(ibanregexp.test(iban))) {\n\t\t\treturn false; // invalid country specific format\n\t\t}\n\t}\n\n\t// now check the checksum, first convert to digits\n\tibancheck = iban.substring(4, iban.length) + iban.substring(0, 4);\n\tfor (i = 0; i < ibancheck.length; i++) {\n\t\tcharAt = ibancheck.charAt(i);\n\t\tif (charAt !== \"0\") {\n\t\t\tleadingZeroes = false;\n\t\t}\n\t\tif (!leadingZeroes) {\n\t\t\tibancheckdigits += \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\".indexOf(charAt);\n\t\t}\n\t}\n\n\t// calculate the result of: ibancheckdigits % 97\n\tfor (p = 0; p < ibancheckdigits.length; p++) {\n\t\tcChar = ibancheckdigits.charAt(p);\n\t\tcOperator = \"\" + cRest + \"\" + cChar;\n\t\tcRest = cOperator % 97;\n\t}\n\treturn cRest === 1;\n}, \"Please specify a valid IBAN\");\n\n$.validator.addMethod(\"integer\", function(value, element) {\n\treturn this.optional(element) || /^-?\\d+$/.test(value);\n}, \"A positive or negative non-decimal number please\");\n\n$.validator.addMethod(\"ipv4\", function(value, element) {\n\treturn this.optional(element) || /^(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$/i.test(value);\n}, \"Please enter a valid IP v4 address.\");\n\n$.validator.addMethod(\"ipv6\", function(value, element) {\n\treturn this.optional(element) || /^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$/i.test(value);\n}, \"Please enter a valid IP v6 address.\");\n\n$.validator.addMethod(\"lettersonly\", function(value, element) {\n\treturn this.optional(element) || /^[a-z]+$/i.test(value);\n}, \"Letters only please\");\n\n$.validator.addMethod(\"letterswithbasicpunc\", function(value, element) {\n\treturn this.optional(element) || /^[a-z\\-.,()'\"\\s]+$/i.test(value);\n}, \"Letters or punctuation only please\");\n\n$.validator.addMethod(\"mobileNL\", function(value, element) {\n\treturn this.optional(element) || /^((\\+|00(\\s|\\s?\\-\\s?)?)31(\\s|\\s?\\-\\s?)?(\\(0\\)[\\-\\s]?)?|0)6((\\s|\\s?\\-\\s?)?[0-9]){8}$/.test(value);\n}, \"Please specify a valid mobile number\");\n\n/* For UK phone functions, do the following server side processing:\n * Compare original input with this RegEx pattern:\n * ^\\(?(?:(?:00\\)?[\\s\\-]?\\(?|\\+)(44)\\)?[\\s\\-]?\\(?(?:0\\)?[\\s\\-]?\\(?)?|0)([1-9]\\d{1,4}\\)?[\\s\\d\\-]+)$\n * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'\n * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.\n * A number of very detailed GB telephone number RegEx patterns can also be found at:\n * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers\n */\n$.validator.addMethod(\"mobileUK\", function(phone_number, element) {\n\tphone_number = phone_number.replace(/\\(|\\)|\\s+|-/g, \"\");\n\treturn this.optional(element) || phone_number.length > 9 &&\n\t\tphone_number.match(/^(?:(?:(?:00\\s?|\\+)44\\s?|0)7(?:[1345789]\\d{2}|624)\\s?\\d{3}\\s?\\d{3})$/);\n}, \"Please specify a valid mobile number\");\n\n/*\n * The número de identidad de extranjero ( NIE )is a code used to identify the non-nationals in Spain\n */\n$.validator.addMethod( \"nieES\", function( value ) {\n\t\"use strict\";\n\n\tvalue = value.toUpperCase();\n\n\t// Basic format test\n\tif ( !value.match( \"((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)\" ) ) {\n\t\treturn false;\n\t}\n\n\t// Test NIE\n\t//T\n\tif ( /^[T]{1}/.test( value ) ) {\n\t\treturn ( value[ 8 ] === /^[T]{1}[A-Z0-9]{8}$/.test( value ) );\n\t}\n\n\t//XYZ\n\tif ( /^[XYZ]{1}/.test( value ) ) {\n\t\treturn (\n\t\t\tvalue[ 8 ] === \"TRWAGMYFPDXBNJZSQVHLCKE\".charAt(\n\t\t\t\tvalue.replace( \"X\", \"0\" )\n\t\t\t\t\t.replace( \"Y\", \"1\" )\n\t\t\t\t\t.replace( \"Z\", \"2\" )\n\t\t\t\t\t.substring( 0, 8 ) % 23\n\t\t\t)\n\t\t);\n\t}\n\n\treturn false;\n\n}, \"Please specify a valid NIE number.\" );\n\n/*\n * The Número de Identificación Fiscal ( NIF ) is the way tax identification used in Spain for individuals\n */\n$.validator.addMethod( \"nifES\", function( value ) {\n\t\"use strict\";\n\n\tvalue = value.toUpperCase();\n\n\t// Basic format test\n\tif ( !value.match(\"((^[A-Z]{1}[0-9]{7}[A-Z0-9]{1}$|^[T]{1}[A-Z0-9]{8}$)|^[0-9]{8}[A-Z]{1}$)\") ) {\n\t\treturn false;\n\t}\n\n\t// Test NIF\n\tif ( /^[0-9]{8}[A-Z]{1}$/.test( value ) ) {\n\t\treturn ( \"TRWAGMYFPDXBNJZSQVHLCKE\".charAt( value.substring( 8, 0 ) % 23 ) === value.charAt( 8 ) );\n\t}\n\t// Test specials NIF (starts with K, L or M)\n\tif ( /^[KLM]{1}/.test( value ) ) {\n\t\treturn ( value[ 8 ] === String.fromCharCode( 64 ) );\n\t}\n\n\treturn false;\n\n}, \"Please specify a valid NIF number.\" );\n\njQuery.validator.addMethod( \"notEqualTo\", function( value, element, param ) {\n\treturn this.optional(element) || !$.validator.methods.equalTo.call( this, value, element, param );\n}, \"Please enter a different value, values must not be the same.\" );\n\n$.validator.addMethod(\"nowhitespace\", function(value, element) {\n\treturn this.optional(element) || /^\\S+$/i.test(value);\n}, \"No white space please\");\n\n/**\n* Return true if the field value matches the given format RegExp\n*\n* @example $.validator.methods.pattern(\"AR1004\",element,/^AR\\d{4}$/)\n* @result true\n*\n* @example $.validator.methods.pattern(\"BR1004\",element,/^AR\\d{4}$/)\n* @result false\n*\n* @name $.validator.methods.pattern\n* @type Boolean\n* @cat Plugins/Validate/Methods\n*/\n$.validator.addMethod(\"pattern\", function(value, element, param) {\n\tif (this.optional(element)) {\n\t\treturn true;\n\t}\n\tif (typeof param === \"string\") {\n\t\tparam = new RegExp(\"^(?:\" + param + \")$\");\n\t}\n\treturn param.test(value);\n}, \"Invalid format.\");\n\n/**\n * Dutch phone numbers have 10 digits (or 11 and start with +31).\n */\n$.validator.addMethod(\"phoneNL\", function(value, element) {\n\treturn this.optional(element) || /^((\\+|00(\\s|\\s?\\-\\s?)?)31(\\s|\\s?\\-\\s?)?(\\(0\\)[\\-\\s]?)?|0)[1-9]((\\s|\\s?\\-\\s?)?[0-9]){8}$/.test(value);\n}, \"Please specify a valid phone number.\");\n\n/* For UK phone functions, do the following server side processing:\n * Compare original input with this RegEx pattern:\n * ^\\(?(?:(?:00\\)?[\\s\\-]?\\(?|\\+)(44)\\)?[\\s\\-]?\\(?(?:0\\)?[\\s\\-]?\\(?)?|0)([1-9]\\d{1,4}\\)?[\\s\\d\\-]+)$\n * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'\n * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.\n * A number of very detailed GB telephone number RegEx patterns can also be found at:\n * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers\n */\n$.validator.addMethod(\"phoneUK\", function(phone_number, element) {\n\tphone_number = phone_number.replace(/\\(|\\)|\\s+|-/g, \"\");\n\treturn this.optional(element) || phone_number.length > 9 &&\n\t\tphone_number.match(/^(?:(?:(?:00\\s?|\\+)44\\s?)|(?:\\(?0))(?:\\d{2}\\)?\\s?\\d{4}\\s?\\d{4}|\\d{3}\\)?\\s?\\d{3}\\s?\\d{3,4}|\\d{4}\\)?\\s?(?:\\d{5}|\\d{3}\\s?\\d{3})|\\d{5}\\)?\\s?\\d{4,5})$/);\n}, \"Please specify a valid phone number\");\n\n/**\n * matches US phone number format\n *\n * where the area code may not start with 1 and the prefix may not start with 1\n * allows '-' or ' ' as a separator and allows parens around area code\n * some people may want to put a '1' in front of their number\n *\n * 1(212)-999-2345 or\n * 212 999 2344 or\n * 212-999-0983\n *\n * but not\n * 111-123-5434\n * and not\n * 212 123 4567\n */\n$.validator.addMethod(\"phoneUS\", function(phone_number, element) {\n\tphone_number = phone_number.replace(/\\s+/g, \"\");\n\treturn this.optional(element) || phone_number.length > 9 &&\n\t\tphone_number.match(/^(\\+?1-?)?(\\([2-9]([02-9]\\d|1[02-9])\\)|[2-9]([02-9]\\d|1[02-9]))-?[2-9]([02-9]\\d|1[02-9])-?\\d{4}$/);\n}, \"Please specify a valid phone number\");\n\n/* For UK phone functions, do the following server side processing:\n * Compare original input with this RegEx pattern:\n * ^\\(?(?:(?:00\\)?[\\s\\-]?\\(?|\\+)(44)\\)?[\\s\\-]?\\(?(?:0\\)?[\\s\\-]?\\(?)?|0)([1-9]\\d{1,4}\\)?[\\s\\d\\-]+)$\n * Extract $1 and set $prefix to '+44<space>' if $1 is '44', otherwise set $prefix to '0'\n * Extract $2 and remove hyphens, spaces and parentheses. Phone number is combined $prefix and $2.\n * A number of very detailed GB telephone number RegEx patterns can also be found at:\n * http://www.aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers\n */\n//Matches UK landline + mobile, accepting only 01-3 for landline or 07 for mobile to exclude many premium numbers\n$.validator.addMethod(\"phonesUK\", function(phone_number, element) {\n\tphone_number = phone_number.replace(/\\(|\\)|\\s+|-/g, \"\");\n\treturn this.optional(element) || phone_number.length > 9 &&\n\t\tphone_number.match(/^(?:(?:(?:00\\s?|\\+)44\\s?|0)(?:1\\d{8,9}|[23]\\d{9}|7(?:[1345789]\\d{8}|624\\d{6})))$/);\n}, \"Please specify a valid uk phone number\");\n\n/**\n * Matches a valid Canadian Postal Code\n *\n * @example jQuery.validator.methods.postalCodeCA( \"H0H 0H0\", element )\n * @result true\n *\n * @example jQuery.validator.methods.postalCodeCA( \"H0H0H0\", element )\n * @result false\n *\n * @name jQuery.validator.methods.postalCodeCA\n * @type Boolean\n * @cat Plugins/Validate/Methods\n */\n$.validator.addMethod( \"postalCodeCA\", function( value, element ) {\n\treturn this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\\d[A-Z] \\d[A-Z]\\d$/.test( value );\n}, \"Please specify a valid postal code\" );\n\n/*\n* Valida CEPs do brasileiros:\n*\n* Formatos aceitos:\n* 99999-999\n* 99.999-999\n* 99999999\n*/\n$.validator.addMethod(\"postalcodeBR\", function(cep_value, element) {\n\treturn this.optional(element) || /^\\d{2}.\\d{3}-\\d{3}?$|^\\d{5}-?\\d{3}?$/.test( cep_value );\n}, \"Informe um CEP válido.\");\n\n/* Matches Italian postcode (CAP) */\n$.validator.addMethod(\"postalcodeIT\", function(value, element) {\n\treturn this.optional(element) || /^\\d{5}$/.test(value);\n}, \"Please specify a valid postal code\");\n\n$.validator.addMethod(\"postalcodeNL\", function(value, element) {\n\treturn this.optional(element) || /^[1-9][0-9]{3}\\s?[a-zA-Z]{2}$/.test(value);\n}, \"Please specify a valid postal code\");\n\n// Matches UK postcode. Does not match to UK Channel Islands that have their own postcodes (non standard UK)\n$.validator.addMethod(\"postcodeUK\", function(value, element) {\n\treturn this.optional(element) || /^((([A-PR-UWYZ][0-9])|([A-PR-UWYZ][0-9][0-9])|([A-PR-UWYZ][A-HK-Y][0-9])|([A-PR-UWYZ][A-HK-Y][0-9][0-9])|([A-PR-UWYZ][0-9][A-HJKSTUW])|([A-PR-UWYZ][A-HK-Y][0-9][ABEHMNPRVWXY]))\\s?([0-9][ABD-HJLNP-UW-Z]{2})|(GIR)\\s?(0AA))$/i.test(value);\n}, \"Please specify a valid UK postcode\");\n\n/*\n * Lets you say \"at least X inputs that match selector Y must be filled.\"\n *\n * The end result is that neither of these inputs:\n *\n *\t<input class=\"productinfo\" name=\"partnumber\">\n *\t<input class=\"productinfo\" name=\"description\">\n *\n *\t...will validate unless at least one of them is filled.\n *\n * partnumber:\t{require_from_group: [1,\".productinfo\"]},\n * description: {require_from_group: [1,\".productinfo\"]}\n *\n * options[0]: number of fields that must be filled in the group\n * options[1]: CSS selector that defines the group of conditionally required fields\n */\n$.validator.addMethod(\"require_from_group\", function(value, element, options) {\n\tvar $fields = $(options[1], element.form),\n\t\t$fieldsFirst = $fields.eq(0),\n\t\tvalidator = $fieldsFirst.data(\"valid_req_grp\") ? $fieldsFirst.data(\"valid_req_grp\") : $.extend({}, this),\n\t\tisValid = $fields.filter(function() {\n\t\t\treturn validator.elementValue(this);\n\t\t}).length >= options[0];\n\n\t// Store the cloned validator for future validation\n\t$fieldsFirst.data(\"valid_req_grp\", validator);\n\n\t// If element isn't being validated, run each require_from_group field's validation rules\n\tif (!$(element).data(\"being_validated\")) {\n\t\t$fields.data(\"being_validated\", true);\n\t\t$fields.each(function() {\n\t\t\tvalidator.element(this);\n\t\t});\n\t\t$fields.data(\"being_validated\", false);\n\t}\n\treturn isValid;\n}, $.validator.format(\"Please fill at least {0} of these fields.\"));\n\n/*\n * Lets you say \"either at least X inputs that match selector Y must be filled,\n * OR they must all be skipped (left blank).\"\n *\n * The end result, is that none of these inputs:\n *\n *\t<input class=\"productinfo\" name=\"partnumber\">\n *\t<input class=\"productinfo\" name=\"description\">\n *\t<input class=\"productinfo\" name=\"color\">\n *\n *\t...will validate unless either at least two of them are filled,\n *\tOR none of them are.\n *\n * partnumber:\t{skip_or_fill_minimum: [2,\".productinfo\"]},\n * description: {skip_or_fill_minimum: [2,\".productinfo\"]},\n * color:\t\t{skip_or_fill_minimum: [2,\".productinfo\"]}\n *\n * options[0]: number of fields that must be filled in the group\n * options[1]: CSS selector that defines the group of conditionally required fields\n *\n */\n$.validator.addMethod(\"skip_or_fill_minimum\", function(value, element, options) {\n\tvar $fields = $(options[1], element.form),\n\t\t$fieldsFirst = $fields.eq(0),\n\t\tvalidator = $fieldsFirst.data(\"valid_skip\") ? $fieldsFirst.data(\"valid_skip\") : $.extend({}, this),\n\t\tnumberFilled = $fields.filter(function() {\n\t\t\treturn validator.elementValue(this);\n\t\t}).length,\n\t\tisValid = numberFilled === 0 || numberFilled >= options[0];\n\n\t// Store the cloned validator for future validation\n\t$fieldsFirst.data(\"valid_skip\", validator);\n\n\t// If element isn't being validated, run each skip_or_fill_minimum field's validation rules\n\tif (!$(element).data(\"being_validated\")) {\n\t\t$fields.data(\"being_validated\", true);\n\t\t$fields.each(function() {\n\t\t\tvalidator.element(this);\n\t\t});\n\t\t$fields.data(\"being_validated\", false);\n\t}\n\treturn isValid;\n}, $.validator.format(\"Please either skip these fields or fill at least {0} of them.\"));\n\n/* Validates US States and/or Territories by @jdforsythe\n * Can be case insensitive or require capitalization - default is case insensitive\n * Can include US Territories or not - default does not\n * Can include US Military postal abbreviations (AA, AE, AP) - default does not\n *\n * Note: \"States\" always includes DC (District of Colombia)\n *\n * Usage examples:\n *\n *  This is the default - case insensitive, no territories, no military zones\n *  stateInput: {\n *     caseSensitive: false,\n *     includeTerritories: false,\n *     includeMilitary: false\n *  }\n *\n *  Only allow capital letters, no territories, no military zones\n *  stateInput: {\n *     caseSensitive: false\n *  }\n *\n *  Case insensitive, include territories but not military zones\n *  stateInput: {\n *     includeTerritories: true\n *  }\n *\n *  Only allow capital letters, include territories and military zones\n *  stateInput: {\n *     caseSensitive: true,\n *     includeTerritories: true,\n *     includeMilitary: true\n *  }\n *\n *\n *\n */\n\n$.validator.addMethod(\"stateUS\", function(value, element, options) {\n\tvar isDefault = typeof options === \"undefined\",\n\t\tcaseSensitive = ( isDefault || typeof options.caseSensitive === \"undefined\" ) ? false : options.caseSensitive,\n\t\tincludeTerritories = ( isDefault || typeof options.includeTerritories === \"undefined\" ) ? false : options.includeTerritories,\n\t\tincludeMilitary = ( isDefault || typeof options.includeMilitary === \"undefined\" ) ? false : options.includeMilitary,\n\t\tregex;\n\n\tif (!includeTerritories && !includeMilitary) {\n\t\tregex = \"^(A[KLRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$\";\n\t} else if (includeTerritories && includeMilitary) {\n\t\tregex = \"^(A[AEKLPRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$\";\n\t} else if (includeTerritories) {\n\t\tregex = \"^(A[KLRSZ]|C[AOT]|D[CE]|FL|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEINOPST]|N[CDEHJMVY]|O[HKR]|P[AR]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY])$\";\n\t} else {\n\t\tregex = \"^(A[AEKLPRZ]|C[AOT]|D[CE]|FL|GA|HI|I[ADLN]|K[SY]|LA|M[ADEINOST]|N[CDEHJMVY]|O[HKR]|PA|RI|S[CD]|T[NX]|UT|V[AT]|W[AIVY])$\";\n\t}\n\n\tregex = caseSensitive ? new RegExp(regex) : new RegExp(regex, \"i\");\n\treturn this.optional(element) || regex.test(value);\n},\n\"Please specify a valid state\");\n\n// TODO check if value starts with <, otherwise don't try stripping anything\n$.validator.addMethod(\"strippedminlength\", function(value, element, param) {\n\treturn $(value).text().length >= param;\n}, $.validator.format(\"Please enter at least {0} characters\"));\n\n$.validator.addMethod(\"time\", function(value, element) {\n\treturn this.optional(element) || /^([01]\\d|2[0-3]|[0-9])(:[0-5]\\d){1,2}$/.test(value);\n}, \"Please enter a valid time, between 00:00 and 23:59\");\n\n$.validator.addMethod(\"time12h\", function(value, element) {\n\treturn this.optional(element) || /^((0?[1-9]|1[012])(:[0-5]\\d){1,2}(\\ ?[AP]M))$/i.test(value);\n}, \"Please enter a valid time in 12-hour am/pm format\");\n\n// same as url, but TLD is optional\n$.validator.addMethod(\"url2\", function(value, element) {\n\treturn this.optional(element) || /^(https?|ftp):\\/\\/(((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:)*@)?(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5]))|((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)*(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?)(:\\d*)?)(\\/((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)+(\\/(([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)*)*)?)?(\\?((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|[\\uE000-\\uF8FF]|\\/|\\?)*)?(#((([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(%[\\da-f]{2})|[!\\$&'\\(\\)\\*\\+,;=]|:|@)|\\/|\\?)*)?$/i.test(value);\n}, $.validator.messages.url);\n\n/**\n * Return true, if the value is a valid vehicle identification number (VIN).\n *\n * Works with all kind of text inputs.\n *\n * @example <input type=\"text\" size=\"20\" name=\"VehicleID\" class=\"{required:true,vinUS:true}\" />\n * @desc Declares a required input element whose value must be a valid vehicle identification number.\n *\n * @name $.validator.methods.vinUS\n * @type Boolean\n * @cat Plugins/Validate/Methods\n */\n$.validator.addMethod(\"vinUS\", function(v) {\n\tif (v.length !== 17) {\n\t\treturn false;\n\t}\n\n\tvar LL = [ \"A\", \"B\", \"C\", \"D\", \"E\", \"F\", \"G\", \"H\", \"J\", \"K\", \"L\", \"M\", \"N\", \"P\", \"R\", \"S\", \"T\", \"U\", \"V\", \"W\", \"X\", \"Y\", \"Z\" ],\n\t\tVL = [ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 7, 9, 2, 3, 4, 5, 6, 7, 8, 9 ],\n\t\tFL = [ 8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2 ],\n\t\trs = 0,\n\t\ti, n, d, f, cd, cdv;\n\n\tfor (i = 0; i < 17; i++) {\n\t\tf = FL[i];\n\t\td = v.slice(i, i + 1);\n\t\tif (i === 8) {\n\t\t\tcdv = d;\n\t\t}\n\t\tif (!isNaN(d)) {\n\t\t\td *= f;\n\t\t} else {\n\t\t\tfor (n = 0; n < LL.length; n++) {\n\t\t\t\tif (d.toUpperCase() === LL[n]) {\n\t\t\t\t\td = VL[n];\n\t\t\t\t\td *= f;\n\t\t\t\t\tif (isNaN(cdv) && n === 8) {\n\t\t\t\t\t\tcdv = LL[n];\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\trs += d;\n\t}\n\tcd = rs % 11;\n\tif (cd === 10) {\n\t\tcd = \"X\";\n\t}\n\tif (cd === cdv) {\n\t\treturn true;\n\t}\n\treturn false;\n}, \"The specified vehicle identification number (VIN) is invalid.\");\n\n$.validator.addMethod(\"zipcodeUS\", function(value, element) {\n\treturn this.optional(element) || /^\\d{5}(-\\d{4})?$/.test(value);\n}, \"The specified US ZIP Code is invalid\");\n\n$.validator.addMethod(\"ziprange\", function(value, element) {\n\treturn this.optional(element) || /^90[2-5]\\d\\{2\\}-\\d{4}$/.test(value);\n}, \"Your ZIP-code must be in the range 902xx-xxxx to 905xx-xxxx\");\n\n}));"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/jquery.validation/1.14.0/jquery.validate.js",
    "content": "/*!\n * jQuery Validation Plugin v1.14.0\n *\n * http://jqueryvalidation.org/\n *\n * Copyright (c) 2015 Jörn Zaefferer\n * Released under the MIT license\n */\n(function( factory ) {\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\tdefine( [\"jquery\"], factory );\n\t} else {\n\t\tfactory( jQuery );\n\t}\n}(function( $ ) {\n\n$.extend($.fn, {\n\t// http://jqueryvalidation.org/validate/\n\tvalidate: function( options ) {\n\n\t\t// if nothing is selected, return nothing; can't chain anyway\n\t\tif ( !this.length ) {\n\t\t\tif ( options && options.debug && window.console ) {\n\t\t\t\tconsole.warn( \"Nothing selected, can't validate, returning nothing.\" );\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// check if a validator for this form was already created\n\t\tvar validator = $.data( this[ 0 ], \"validator\" );\n\t\tif ( validator ) {\n\t\t\treturn validator;\n\t\t}\n\n\t\t// Add novalidate tag if HTML5.\n\t\tthis.attr( \"novalidate\", \"novalidate\" );\n\n\t\tvalidator = new $.validator( options, this[ 0 ] );\n\t\t$.data( this[ 0 ], \"validator\", validator );\n\n\t\tif ( validator.settings.onsubmit ) {\n\n\t\t\tthis.on( \"click.validate\", \":submit\", function( event ) {\n\t\t\t\tif ( validator.settings.submitHandler ) {\n\t\t\t\t\tvalidator.submitButton = event.target;\n\t\t\t\t}\n\n\t\t\t\t// allow suppressing validation by adding a cancel class to the submit button\n\t\t\t\tif ( $( this ).hasClass( \"cancel\" ) ) {\n\t\t\t\t\tvalidator.cancelSubmit = true;\n\t\t\t\t}\n\n\t\t\t\t// allow suppressing validation by adding the html5 formnovalidate attribute to the submit button\n\t\t\t\tif ( $( this ).attr( \"formnovalidate\" ) !== undefined ) {\n\t\t\t\t\tvalidator.cancelSubmit = true;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// validate the form on submit\n\t\t\tthis.on( \"submit.validate\", function( event ) {\n\t\t\t\tif ( validator.settings.debug ) {\n\t\t\t\t\t// prevent form submit to be able to see console output\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t\tfunction handle() {\n\t\t\t\t\tvar hidden, result;\n\t\t\t\t\tif ( validator.settings.submitHandler ) {\n\t\t\t\t\t\tif ( validator.submitButton ) {\n\t\t\t\t\t\t\t// insert a hidden input as a replacement for the missing submit button\n\t\t\t\t\t\t\thidden = $( \"<input type='hidden'/>\" )\n\t\t\t\t\t\t\t\t.attr( \"name\", validator.submitButton.name )\n\t\t\t\t\t\t\t\t.val( $( validator.submitButton ).val() )\n\t\t\t\t\t\t\t\t.appendTo( validator.currentForm );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tresult = validator.settings.submitHandler.call( validator, validator.currentForm, event );\n\t\t\t\t\t\tif ( validator.submitButton ) {\n\t\t\t\t\t\t\t// and clean up afterwards; thanks to no-block-scope, hidden can be referenced\n\t\t\t\t\t\t\thidden.remove();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( result !== undefined ) {\n\t\t\t\t\t\t\treturn result;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\t// prevent submit for invalid forms or custom submit handlers\n\t\t\t\tif ( validator.cancelSubmit ) {\n\t\t\t\t\tvalidator.cancelSubmit = false;\n\t\t\t\t\treturn handle();\n\t\t\t\t}\n\t\t\t\tif ( validator.form() ) {\n\t\t\t\t\tif ( validator.pendingRequest ) {\n\t\t\t\t\t\tvalidator.formSubmitted = true;\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn handle();\n\t\t\t\t} else {\n\t\t\t\t\tvalidator.focusInvalid();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\treturn validator;\n\t},\n\t// http://jqueryvalidation.org/valid/\n\tvalid: function() {\n\t\tvar valid, validator, errorList;\n\n\t\tif ( $( this[ 0 ] ).is( \"form\" ) ) {\n\t\t\tvalid = this.validate().form();\n\t\t} else {\n\t\t\terrorList = [];\n\t\t\tvalid = true;\n\t\t\tvalidator = $( this[ 0 ].form ).validate();\n\t\t\tthis.each( function() {\n\t\t\t\tvalid = validator.element( this ) && valid;\n\t\t\t\terrorList = errorList.concat( validator.errorList );\n\t\t\t});\n\t\t\tvalidator.errorList = errorList;\n\t\t}\n\t\treturn valid;\n\t},\n\n\t// http://jqueryvalidation.org/rules/\n\trules: function( command, argument ) {\n\t\tvar element = this[ 0 ],\n\t\t\tsettings, staticRules, existingRules, data, param, filtered;\n\n\t\tif ( command ) {\n\t\t\tsettings = $.data( element.form, \"validator\" ).settings;\n\t\t\tstaticRules = settings.rules;\n\t\t\texistingRules = $.validator.staticRules( element );\n\t\t\tswitch ( command ) {\n\t\t\tcase \"add\":\n\t\t\t\t$.extend( existingRules, $.validator.normalizeRule( argument ) );\n\t\t\t\t// remove messages from rules, but allow them to be set separately\n\t\t\t\tdelete existingRules.messages;\n\t\t\t\tstaticRules[ element.name ] = existingRules;\n\t\t\t\tif ( argument.messages ) {\n\t\t\t\t\tsettings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"remove\":\n\t\t\t\tif ( !argument ) {\n\t\t\t\t\tdelete staticRules[ element.name ];\n\t\t\t\t\treturn existingRules;\n\t\t\t\t}\n\t\t\t\tfiltered = {};\n\t\t\t\t$.each( argument.split( /\\s/ ), function( index, method ) {\n\t\t\t\t\tfiltered[ method ] = existingRules[ method ];\n\t\t\t\t\tdelete existingRules[ method ];\n\t\t\t\t\tif ( method === \"required\" ) {\n\t\t\t\t\t\t$( element ).removeAttr( \"aria-required\" );\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\treturn filtered;\n\t\t\t}\n\t\t}\n\n\t\tdata = $.validator.normalizeRules(\n\t\t$.extend(\n\t\t\t{},\n\t\t\t$.validator.classRules( element ),\n\t\t\t$.validator.attributeRules( element ),\n\t\t\t$.validator.dataRules( element ),\n\t\t\t$.validator.staticRules( element )\n\t\t), element );\n\n\t\t// make sure required is at front\n\t\tif ( data.required ) {\n\t\t\tparam = data.required;\n\t\t\tdelete data.required;\n\t\t\tdata = $.extend( { required: param }, data );\n\t\t\t$( element ).attr( \"aria-required\", \"true\" );\n\t\t}\n\n\t\t// make sure remote is at back\n\t\tif ( data.remote ) {\n\t\t\tparam = data.remote;\n\t\t\tdelete data.remote;\n\t\t\tdata = $.extend( data, { remote: param });\n\t\t}\n\n\t\treturn data;\n\t}\n});\n\n// Custom selectors\n$.extend( $.expr[ \":\" ], {\n\t// http://jqueryvalidation.org/blank-selector/\n\tblank: function( a ) {\n\t\treturn !$.trim( \"\" + $( a ).val() );\n\t},\n\t// http://jqueryvalidation.org/filled-selector/\n\tfilled: function( a ) {\n\t\treturn !!$.trim( \"\" + $( a ).val() );\n\t},\n\t// http://jqueryvalidation.org/unchecked-selector/\n\tunchecked: function( a ) {\n\t\treturn !$( a ).prop( \"checked\" );\n\t}\n});\n\n// constructor for validator\n$.validator = function( options, form ) {\n\tthis.settings = $.extend( true, {}, $.validator.defaults, options );\n\tthis.currentForm = form;\n\tthis.init();\n};\n\n// http://jqueryvalidation.org/jQuery.validator.format/\n$.validator.format = function( source, params ) {\n\tif ( arguments.length === 1 ) {\n\t\treturn function() {\n\t\t\tvar args = $.makeArray( arguments );\n\t\t\targs.unshift( source );\n\t\t\treturn $.validator.format.apply( this, args );\n\t\t};\n\t}\n\tif ( arguments.length > 2 && params.constructor !== Array  ) {\n\t\tparams = $.makeArray( arguments ).slice( 1 );\n\t}\n\tif ( params.constructor !== Array ) {\n\t\tparams = [ params ];\n\t}\n\t$.each( params, function( i, n ) {\n\t\tsource = source.replace( new RegExp( \"\\\\{\" + i + \"\\\\}\", \"g\" ), function() {\n\t\t\treturn n;\n\t\t});\n\t});\n\treturn source;\n};\n\n$.extend( $.validator, {\n\n\tdefaults: {\n\t\tmessages: {},\n\t\tgroups: {},\n\t\trules: {},\n\t\terrorClass: \"error\",\n\t\tvalidClass: \"valid\",\n\t\terrorElement: \"label\",\n\t\tfocusCleanup: false,\n\t\tfocusInvalid: true,\n\t\terrorContainer: $( [] ),\n\t\terrorLabelContainer: $( [] ),\n\t\tonsubmit: true,\n\t\tignore: \":hidden\",\n\t\tignoreTitle: false,\n\t\tonfocusin: function( element ) {\n\t\t\tthis.lastActive = element;\n\n\t\t\t// Hide error label and remove error class on focus if enabled\n\t\t\tif ( this.settings.focusCleanup ) {\n\t\t\t\tif ( this.settings.unhighlight ) {\n\t\t\t\t\tthis.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );\n\t\t\t\t}\n\t\t\t\tthis.hideThese( this.errorsFor( element ) );\n\t\t\t}\n\t\t},\n\t\tonfocusout: function( element ) {\n\t\t\tif ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {\n\t\t\t\tthis.element( element );\n\t\t\t}\n\t\t},\n\t\tonkeyup: function( element, event ) {\n\t\t\t// Avoid revalidate the field when pressing one of the following keys\n\t\t\t// Shift       => 16\n\t\t\t// Ctrl        => 17\n\t\t\t// Alt         => 18\n\t\t\t// Caps lock   => 20\n\t\t\t// End         => 35\n\t\t\t// Home        => 36\n\t\t\t// Left arrow  => 37\n\t\t\t// Up arrow    => 38\n\t\t\t// Right arrow => 39\n\t\t\t// Down arrow  => 40\n\t\t\t// Insert      => 45\n\t\t\t// Num lock    => 144\n\t\t\t// AltGr key   => 225\n\t\t\tvar excludedKeys = [\n\t\t\t\t16, 17, 18, 20, 35, 36, 37,\n\t\t\t\t38, 39, 40, 45, 144, 225\n\t\t\t];\n\n\t\t\tif ( event.which === 9 && this.elementValue( element ) === \"\" || $.inArray( event.keyCode, excludedKeys ) !== -1 ) {\n\t\t\t\treturn;\n\t\t\t} else if ( element.name in this.submitted || element === this.lastElement ) {\n\t\t\t\tthis.element( element );\n\t\t\t}\n\t\t},\n\t\tonclick: function( element ) {\n\t\t\t// click on selects, radiobuttons and checkboxes\n\t\t\tif ( element.name in this.submitted ) {\n\t\t\t\tthis.element( element );\n\n\t\t\t// or option elements, check parent select in that case\n\t\t\t} else if ( element.parentNode.name in this.submitted ) {\n\t\t\t\tthis.element( element.parentNode );\n\t\t\t}\n\t\t},\n\t\thighlight: function( element, errorClass, validClass ) {\n\t\t\tif ( element.type === \"radio\" ) {\n\t\t\t\tthis.findByName( element.name ).addClass( errorClass ).removeClass( validClass );\n\t\t\t} else {\n\t\t\t\t$( element ).addClass( errorClass ).removeClass( validClass );\n\t\t\t}\n\t\t},\n\t\tunhighlight: function( element, errorClass, validClass ) {\n\t\t\tif ( element.type === \"radio\" ) {\n\t\t\t\tthis.findByName( element.name ).removeClass( errorClass ).addClass( validClass );\n\t\t\t} else {\n\t\t\t\t$( element ).removeClass( errorClass ).addClass( validClass );\n\t\t\t}\n\t\t}\n\t},\n\n\t// http://jqueryvalidation.org/jQuery.validator.setDefaults/\n\tsetDefaults: function( settings ) {\n\t\t$.extend( $.validator.defaults, settings );\n\t},\n\n\tmessages: {\n\t\trequired: \"This field is required.\",\n\t\tremote: \"Please fix this field.\",\n\t\temail: \"Please enter a valid email address.\",\n\t\turl: \"Please enter a valid URL.\",\n\t\tdate: \"Please enter a valid date.\",\n\t\tdateISO: \"Please enter a valid date ( ISO ).\",\n\t\tnumber: \"Please enter a valid number.\",\n\t\tdigits: \"Please enter only digits.\",\n\t\tcreditcard: \"Please enter a valid credit card number.\",\n\t\tequalTo: \"Please enter the same value again.\",\n\t\tmaxlength: $.validator.format( \"Please enter no more than {0} characters.\" ),\n\t\tminlength: $.validator.format( \"Please enter at least {0} characters.\" ),\n\t\trangelength: $.validator.format( \"Please enter a value between {0} and {1} characters long.\" ),\n\t\trange: $.validator.format( \"Please enter a value between {0} and {1}.\" ),\n\t\tmax: $.validator.format( \"Please enter a value less than or equal to {0}.\" ),\n\t\tmin: $.validator.format( \"Please enter a value greater than or equal to {0}.\" )\n\t},\n\n\tautoCreateRanges: false,\n\n\tprototype: {\n\n\t\tinit: function() {\n\t\t\tthis.labelContainer = $( this.settings.errorLabelContainer );\n\t\t\tthis.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );\n\t\t\tthis.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );\n\t\t\tthis.submitted = {};\n\t\t\tthis.valueCache = {};\n\t\t\tthis.pendingRequest = 0;\n\t\t\tthis.pending = {};\n\t\t\tthis.invalid = {};\n\t\t\tthis.reset();\n\n\t\t\tvar groups = ( this.groups = {} ),\n\t\t\t\trules;\n\t\t\t$.each( this.settings.groups, function( key, value ) {\n\t\t\t\tif ( typeof value === \"string\" ) {\n\t\t\t\t\tvalue = value.split( /\\s/ );\n\t\t\t\t}\n\t\t\t\t$.each( value, function( index, name ) {\n\t\t\t\t\tgroups[ name ] = key;\n\t\t\t\t});\n\t\t\t});\n\t\t\trules = this.settings.rules;\n\t\t\t$.each( rules, function( key, value ) {\n\t\t\t\trules[ key ] = $.validator.normalizeRule( value );\n\t\t\t});\n\n\t\t\tfunction delegate( event ) {\n\t\t\t\tvar validator = $.data( this.form, \"validator\" ),\n\t\t\t\t\teventType = \"on\" + event.type.replace( /^validate/, \"\" ),\n\t\t\t\t\tsettings = validator.settings;\n\t\t\t\tif ( settings[ eventType ] && !$( this ).is( settings.ignore ) ) {\n\t\t\t\t\tsettings[ eventType ].call( validator, this, event );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$( this.currentForm )\n\t\t\t\t.on( \"focusin.validate focusout.validate keyup.validate\",\n\t\t\t\t\t\":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], \" +\n\t\t\t\t\t\"[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], \" +\n\t\t\t\t\t\"[type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], \" +\n\t\t\t\t\t\"[type='radio'], [type='checkbox']\", delegate)\n\t\t\t\t// Support: Chrome, oldIE\n\t\t\t\t// \"select\" is provided as event.target when clicking a option\n\t\t\t\t.on(\"click.validate\", \"select, option, [type='radio'], [type='checkbox']\", delegate);\n\n\t\t\tif ( this.settings.invalidHandler ) {\n\t\t\t\t$( this.currentForm ).on( \"invalid-form.validate\", this.settings.invalidHandler );\n\t\t\t}\n\n\t\t\t// Add aria-required to any Static/Data/Class required fields before first validation\n\t\t\t// Screen readers require this attribute to be present before the initial submission http://www.w3.org/TR/WCAG-TECHS/ARIA2.html\n\t\t\t$( this.currentForm ).find( \"[required], [data-rule-required], .required\" ).attr( \"aria-required\", \"true\" );\n\t\t},\n\n\t\t// http://jqueryvalidation.org/Validator.form/\n\t\tform: function() {\n\t\t\tthis.checkForm();\n\t\t\t$.extend( this.submitted, this.errorMap );\n\t\t\tthis.invalid = $.extend({}, this.errorMap );\n\t\t\tif ( !this.valid() ) {\n\t\t\t\t$( this.currentForm ).triggerHandler( \"invalid-form\", [ this ]);\n\t\t\t}\n\t\t\tthis.showErrors();\n\t\t\treturn this.valid();\n\t\t},\n\n\t\tcheckForm: function() {\n\t\t\tthis.prepareForm();\n\t\t\tfor ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {\n\t\t\t\tthis.check( elements[ i ] );\n\t\t\t}\n\t\t\treturn this.valid();\n\t\t},\n\n\t\t// http://jqueryvalidation.org/Validator.element/\n\t\telement: function( element ) {\n\t\t\tvar cleanElement = this.clean( element ),\n\t\t\t\tcheckElement = this.validationTargetFor( cleanElement ),\n\t\t\t\tresult = true;\n\n\t\t\tthis.lastElement = checkElement;\n\n\t\t\tif ( checkElement === undefined ) {\n\t\t\t\tdelete this.invalid[ cleanElement.name ];\n\t\t\t} else {\n\t\t\t\tthis.prepareElement( checkElement );\n\t\t\t\tthis.currentElements = $( checkElement );\n\n\t\t\t\tresult = this.check( checkElement ) !== false;\n\t\t\t\tif ( result ) {\n\t\t\t\t\tdelete this.invalid[ checkElement.name ];\n\t\t\t\t} else {\n\t\t\t\t\tthis.invalid[ checkElement.name ] = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Add aria-invalid status for screen readers\n\t\t\t$( element ).attr( \"aria-invalid\", !result );\n\n\t\t\tif ( !this.numberOfInvalids() ) {\n\t\t\t\t// Hide error containers on last error\n\t\t\t\tthis.toHide = this.toHide.add( this.containers );\n\t\t\t}\n\t\t\tthis.showErrors();\n\t\t\treturn result;\n\t\t},\n\n\t\t// http://jqueryvalidation.org/Validator.showErrors/\n\t\tshowErrors: function( errors ) {\n\t\t\tif ( errors ) {\n\t\t\t\t// add items to error list and map\n\t\t\t\t$.extend( this.errorMap, errors );\n\t\t\t\tthis.errorList = [];\n\t\t\t\tfor ( var name in errors ) {\n\t\t\t\t\tthis.errorList.push({\n\t\t\t\t\t\tmessage: errors[ name ],\n\t\t\t\t\t\telement: this.findByName( name )[ 0 ]\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// remove items from success list\n\t\t\t\tthis.successList = $.grep( this.successList, function( element ) {\n\t\t\t\t\treturn !( element.name in errors );\n\t\t\t\t});\n\t\t\t}\n\t\t\tif ( this.settings.showErrors ) {\n\t\t\t\tthis.settings.showErrors.call( this, this.errorMap, this.errorList );\n\t\t\t} else {\n\t\t\t\tthis.defaultShowErrors();\n\t\t\t}\n\t\t},\n\n\t\t// http://jqueryvalidation.org/Validator.resetForm/\n\t\tresetForm: function() {\n\t\t\tif ( $.fn.resetForm ) {\n\t\t\t\t$( this.currentForm ).resetForm();\n\t\t\t}\n\t\t\tthis.submitted = {};\n\t\t\tthis.lastElement = null;\n\t\t\tthis.prepareForm();\n\t\t\tthis.hideErrors();\n\t\t\tvar i, elements = this.elements()\n\t\t\t\t.removeData( \"previousValue\" )\n\t\t\t\t.removeAttr( \"aria-invalid\" );\n\n\t\t\tif ( this.settings.unhighlight ) {\n\t\t\t\tfor ( i = 0; elements[ i ]; i++ ) {\n\t\t\t\t\tthis.settings.unhighlight.call( this, elements[ i ],\n\t\t\t\t\t\tthis.settings.errorClass, \"\" );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\telements.removeClass( this.settings.errorClass );\n\t\t\t}\n\t\t},\n\n\t\tnumberOfInvalids: function() {\n\t\t\treturn this.objectLength( this.invalid );\n\t\t},\n\n\t\tobjectLength: function( obj ) {\n\t\t\t/* jshint unused: false */\n\t\t\tvar count = 0,\n\t\t\t\ti;\n\t\t\tfor ( i in obj ) {\n\t\t\t\tcount++;\n\t\t\t}\n\t\t\treturn count;\n\t\t},\n\n\t\thideErrors: function() {\n\t\t\tthis.hideThese( this.toHide );\n\t\t},\n\n\t\thideThese: function( errors ) {\n\t\t\terrors.not( this.containers ).text( \"\" );\n\t\t\tthis.addWrapper( errors ).hide();\n\t\t},\n\n\t\tvalid: function() {\n\t\t\treturn this.size() === 0;\n\t\t},\n\n\t\tsize: function() {\n\t\t\treturn this.errorList.length;\n\t\t},\n\n\t\tfocusInvalid: function() {\n\t\t\tif ( this.settings.focusInvalid ) {\n\t\t\t\ttry {\n\t\t\t\t\t$( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [])\n\t\t\t\t\t.filter( \":visible\" )\n\t\t\t\t\t.focus()\n\t\t\t\t\t// manually trigger focusin event; without it, focusin handler isn't called, findLastActive won't have anything to find\n\t\t\t\t\t.trigger( \"focusin\" );\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\t// ignore IE throwing errors when focusing hidden elements\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\tfindLastActive: function() {\n\t\t\tvar lastActive = this.lastActive;\n\t\t\treturn lastActive && $.grep( this.errorList, function( n ) {\n\t\t\t\treturn n.element.name === lastActive.name;\n\t\t\t}).length === 1 && lastActive;\n\t\t},\n\n\t\telements: function() {\n\t\t\tvar validator = this,\n\t\t\t\trulesCache = {};\n\n\t\t\t// select all valid inputs inside the form (no submit or reset buttons)\n\t\t\treturn $( this.currentForm )\n\t\t\t.find( \"input, select, textarea\" )\n\t\t\t.not( \":submit, :reset, :image, :disabled\" )\n\t\t\t.not( this.settings.ignore )\n\t\t\t.filter( function() {\n\t\t\t\tif ( !this.name && validator.settings.debug && window.console ) {\n\t\t\t\t\tconsole.error( \"%o has no name assigned\", this );\n\t\t\t\t}\n\n\t\t\t\t// select only the first element for each name, and only those with rules specified\n\t\t\t\tif ( this.name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\trulesCache[ this.name ] = true;\n\t\t\t\treturn true;\n\t\t\t});\n\t\t},\n\n\t\tclean: function( selector ) {\n\t\t\treturn $( selector )[ 0 ];\n\t\t},\n\n\t\terrors: function() {\n\t\t\tvar errorClass = this.settings.errorClass.split( \" \" ).join( \".\" );\n\t\t\treturn $( this.settings.errorElement + \".\" + errorClass, this.errorContext );\n\t\t},\n\n\t\treset: function() {\n\t\t\tthis.successList = [];\n\t\t\tthis.errorList = [];\n\t\t\tthis.errorMap = {};\n\t\t\tthis.toShow = $( [] );\n\t\t\tthis.toHide = $( [] );\n\t\t\tthis.currentElements = $( [] );\n\t\t},\n\n\t\tprepareForm: function() {\n\t\t\tthis.reset();\n\t\t\tthis.toHide = this.errors().add( this.containers );\n\t\t},\n\n\t\tprepareElement: function( element ) {\n\t\t\tthis.reset();\n\t\t\tthis.toHide = this.errorsFor( element );\n\t\t},\n\n\t\telementValue: function( element ) {\n\t\t\tvar val,\n\t\t\t\t$element = $( element ),\n\t\t\t\ttype = element.type;\n\n\t\t\tif ( type === \"radio\" || type === \"checkbox\" ) {\n\t\t\t\treturn this.findByName( element.name ).filter(\":checked\").val();\n\t\t\t} else if ( type === \"number\" && typeof element.validity !== \"undefined\" ) {\n\t\t\t\treturn element.validity.badInput ? false : $element.val();\n\t\t\t}\n\n\t\t\tval = $element.val();\n\t\t\tif ( typeof val === \"string\" ) {\n\t\t\t\treturn val.replace(/\\r/g, \"\" );\n\t\t\t}\n\t\t\treturn val;\n\t\t},\n\n\t\tcheck: function( element ) {\n\t\t\telement = this.validationTargetFor( this.clean( element ) );\n\n\t\t\tvar rules = $( element ).rules(),\n\t\t\t\trulesCount = $.map( rules, function( n, i ) {\n\t\t\t\t\treturn i;\n\t\t\t\t}).length,\n\t\t\t\tdependencyMismatch = false,\n\t\t\t\tval = this.elementValue( element ),\n\t\t\t\tresult, method, rule;\n\n\t\t\tfor ( method in rules ) {\n\t\t\t\trule = { method: method, parameters: rules[ method ] };\n\t\t\t\ttry {\n\n\t\t\t\t\tresult = $.validator.methods[ method ].call( this, val, element, rule.parameters );\n\n\t\t\t\t\t// if a method indicates that the field is optional and therefore valid,\n\t\t\t\t\t// don't mark it as valid when there are no other rules\n\t\t\t\t\tif ( result === \"dependency-mismatch\" && rulesCount === 1 ) {\n\t\t\t\t\t\tdependencyMismatch = true;\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tdependencyMismatch = false;\n\n\t\t\t\t\tif ( result === \"pending\" ) {\n\t\t\t\t\t\tthis.toHide = this.toHide.not( this.errorsFor( element ) );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !result ) {\n\t\t\t\t\t\tthis.formatAndAdd( element, rule );\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\tif ( this.settings.debug && window.console ) {\n\t\t\t\t\t\tconsole.log( \"Exception occurred when checking element \" + element.id + \", check the '\" + rule.method + \"' method.\", e );\n\t\t\t\t\t}\n\t\t\t\t\tif ( e instanceof TypeError ) {\n\t\t\t\t\t\te.message += \".  Exception occurred when checking element \" + element.id + \", check the '\" + rule.method + \"' method.\";\n\t\t\t\t\t}\n\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( dependencyMismatch ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( this.objectLength( rules ) ) {\n\t\t\t\tthis.successList.push( element );\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t// return the custom message for the given element and validation method\n\t\t// specified in the element's HTML5 data attribute\n\t\t// return the generic message if present and no method specific message is present\n\t\tcustomDataMessage: function( element, method ) {\n\t\t\treturn $( element ).data( \"msg\" + method.charAt( 0 ).toUpperCase() +\n\t\t\t\tmethod.substring( 1 ).toLowerCase() ) || $( element ).data( \"msg\" );\n\t\t},\n\n\t\t// return the custom message for the given element name and validation method\n\t\tcustomMessage: function( name, method ) {\n\t\t\tvar m = this.settings.messages[ name ];\n\t\t\treturn m && ( m.constructor === String ? m : m[ method ]);\n\t\t},\n\n\t\t// return the first defined argument, allowing empty strings\n\t\tfindDefined: function() {\n\t\t\tfor ( var i = 0; i < arguments.length; i++) {\n\t\t\t\tif ( arguments[ i ] !== undefined ) {\n\t\t\t\t\treturn arguments[ i ];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t},\n\n\t\tdefaultMessage: function( element, method ) {\n\t\t\treturn this.findDefined(\n\t\t\t\tthis.customMessage( element.name, method ),\n\t\t\t\tthis.customDataMessage( element, method ),\n\t\t\t\t// title is never undefined, so handle empty string as undefined\n\t\t\t\t!this.settings.ignoreTitle && element.title || undefined,\n\t\t\t\t$.validator.messages[ method ],\n\t\t\t\t\"<strong>Warning: No message defined for \" + element.name + \"</strong>\"\n\t\t\t);\n\t\t},\n\n\t\tformatAndAdd: function( element, rule ) {\n\t\t\tvar message = this.defaultMessage( element, rule.method ),\n\t\t\t\ttheregex = /\\$?\\{(\\d+)\\}/g;\n\t\t\tif ( typeof message === \"function\" ) {\n\t\t\t\tmessage = message.call( this, rule.parameters, element );\n\t\t\t} else if ( theregex.test( message ) ) {\n\t\t\t\tmessage = $.validator.format( message.replace( theregex, \"{$1}\" ), rule.parameters );\n\t\t\t}\n\t\t\tthis.errorList.push({\n\t\t\t\tmessage: message,\n\t\t\t\telement: element,\n\t\t\t\tmethod: rule.method\n\t\t\t});\n\n\t\t\tthis.errorMap[ element.name ] = message;\n\t\t\tthis.submitted[ element.name ] = message;\n\t\t},\n\n\t\taddWrapper: function( toToggle ) {\n\t\t\tif ( this.settings.wrapper ) {\n\t\t\t\ttoToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );\n\t\t\t}\n\t\t\treturn toToggle;\n\t\t},\n\n\t\tdefaultShowErrors: function() {\n\t\t\tvar i, elements, error;\n\t\t\tfor ( i = 0; this.errorList[ i ]; i++ ) {\n\t\t\t\terror = this.errorList[ i ];\n\t\t\t\tif ( this.settings.highlight ) {\n\t\t\t\t\tthis.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );\n\t\t\t\t}\n\t\t\t\tthis.showLabel( error.element, error.message );\n\t\t\t}\n\t\t\tif ( this.errorList.length ) {\n\t\t\t\tthis.toShow = this.toShow.add( this.containers );\n\t\t\t}\n\t\t\tif ( this.settings.success ) {\n\t\t\t\tfor ( i = 0; this.successList[ i ]; i++ ) {\n\t\t\t\t\tthis.showLabel( this.successList[ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( this.settings.unhighlight ) {\n\t\t\t\tfor ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {\n\t\t\t\t\tthis.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.toHide = this.toHide.not( this.toShow );\n\t\t\tthis.hideErrors();\n\t\t\tthis.addWrapper( this.toShow ).show();\n\t\t},\n\n\t\tvalidElements: function() {\n\t\t\treturn this.currentElements.not( this.invalidElements() );\n\t\t},\n\n\t\tinvalidElements: function() {\n\t\t\treturn $( this.errorList ).map(function() {\n\t\t\t\treturn this.element;\n\t\t\t});\n\t\t},\n\n\t\tshowLabel: function( element, message ) {\n\t\t\tvar place, group, errorID,\n\t\t\t\terror = this.errorsFor( element ),\n\t\t\t\telementID = this.idOrName( element ),\n\t\t\t\tdescribedBy = $( element ).attr( \"aria-describedby\" );\n\t\t\tif ( error.length ) {\n\t\t\t\t// refresh error/success class\n\t\t\t\terror.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );\n\t\t\t\t// replace message on existing label\n\t\t\t\terror.html( message );\n\t\t\t} else {\n\t\t\t\t// create error element\n\t\t\t\terror = $( \"<\" + this.settings.errorElement + \">\" )\n\t\t\t\t\t.attr( \"id\", elementID + \"-error\" )\n\t\t\t\t\t.addClass( this.settings.errorClass )\n\t\t\t\t\t.html( message || \"\" );\n\n\t\t\t\t// Maintain reference to the element to be placed into the DOM\n\t\t\t\tplace = error;\n\t\t\t\tif ( this.settings.wrapper ) {\n\t\t\t\t\t// make sure the element is visible, even in IE\n\t\t\t\t\t// actually showing the wrapped element is handled elsewhere\n\t\t\t\t\tplace = error.hide().show().wrap( \"<\" + this.settings.wrapper + \"/>\" ).parent();\n\t\t\t\t}\n\t\t\t\tif ( this.labelContainer.length ) {\n\t\t\t\t\tthis.labelContainer.append( place );\n\t\t\t\t} else if ( this.settings.errorPlacement ) {\n\t\t\t\t\tthis.settings.errorPlacement( place, $( element ) );\n\t\t\t\t} else {\n\t\t\t\t\tplace.insertAfter( element );\n\t\t\t\t}\n\n\t\t\t\t// Link error back to the element\n\t\t\t\tif ( error.is( \"label\" ) ) {\n\t\t\t\t\t// If the error is a label, then associate using 'for'\n\t\t\t\t\terror.attr( \"for\", elementID );\n\t\t\t\t} else if ( error.parents( \"label[for='\" + elementID + \"']\" ).length === 0 ) {\n\t\t\t\t\t// If the element is not a child of an associated label, then it's necessary\n\t\t\t\t\t// to explicitly apply aria-describedby\n\n\t\t\t\t\terrorID = error.attr( \"id\" ).replace( /(:|\\.|\\[|\\]|\\$)/g, \"\\\\$1\");\n\t\t\t\t\t// Respect existing non-error aria-describedby\n\t\t\t\t\tif ( !describedBy ) {\n\t\t\t\t\t\tdescribedBy = errorID;\n\t\t\t\t\t} else if ( !describedBy.match( new RegExp( \"\\\\b\" + errorID + \"\\\\b\" ) ) ) {\n\t\t\t\t\t\t// Add to end of list if not already present\n\t\t\t\t\t\tdescribedBy += \" \" + errorID;\n\t\t\t\t\t}\n\t\t\t\t\t$( element ).attr( \"aria-describedby\", describedBy );\n\n\t\t\t\t\t// If this element is grouped, then assign to all elements in the same group\n\t\t\t\t\tgroup = this.groups[ element.name ];\n\t\t\t\t\tif ( group ) {\n\t\t\t\t\t\t$.each( this.groups, function( name, testgroup ) {\n\t\t\t\t\t\t\tif ( testgroup === group ) {\n\t\t\t\t\t\t\t\t$( \"[name='\" + name + \"']\", this.currentForm )\n\t\t\t\t\t\t\t\t\t.attr( \"aria-describedby\", error.attr( \"id\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( !message && this.settings.success ) {\n\t\t\t\terror.text( \"\" );\n\t\t\t\tif ( typeof this.settings.success === \"string\" ) {\n\t\t\t\t\terror.addClass( this.settings.success );\n\t\t\t\t} else {\n\t\t\t\t\tthis.settings.success( error, element );\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.toShow = this.toShow.add( error );\n\t\t},\n\n\t\terrorsFor: function( element ) {\n\t\t\tvar name = this.idOrName( element ),\n\t\t\t\tdescriber = $( element ).attr( \"aria-describedby\" ),\n\t\t\t\tselector = \"label[for='\" + name + \"'], label[for='\" + name + \"'] *\";\n\n\t\t\t// aria-describedby should directly reference the error element\n\t\t\tif ( describer ) {\n\t\t\t\tselector = selector + \", #\" + describer.replace( /\\s+/g, \", #\" );\n\t\t\t}\n\t\t\treturn this\n\t\t\t\t.errors()\n\t\t\t\t.filter( selector );\n\t\t},\n\n\t\tidOrName: function( element ) {\n\t\t\treturn this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );\n\t\t},\n\n\t\tvalidationTargetFor: function( element ) {\n\n\t\t\t// If radio/checkbox, validate first element in group instead\n\t\t\tif ( this.checkable( element ) ) {\n\t\t\t\telement = this.findByName( element.name );\n\t\t\t}\n\n\t\t\t// Always apply ignore filter\n\t\t\treturn $( element ).not( this.settings.ignore )[ 0 ];\n\t\t},\n\n\t\tcheckable: function( element ) {\n\t\t\treturn ( /radio|checkbox/i ).test( element.type );\n\t\t},\n\n\t\tfindByName: function( name ) {\n\t\t\treturn $( this.currentForm ).find( \"[name='\" + name + \"']\" );\n\t\t},\n\n\t\tgetLength: function( value, element ) {\n\t\t\tswitch ( element.nodeName.toLowerCase() ) {\n\t\t\tcase \"select\":\n\t\t\t\treturn $( \"option:selected\", element ).length;\n\t\t\tcase \"input\":\n\t\t\t\tif ( this.checkable( element ) ) {\n\t\t\t\t\treturn this.findByName( element.name ).filter( \":checked\" ).length;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn value.length;\n\t\t},\n\n\t\tdepend: function( param, element ) {\n\t\t\treturn this.dependTypes[typeof param] ? this.dependTypes[typeof param]( param, element ) : true;\n\t\t},\n\n\t\tdependTypes: {\n\t\t\t\"boolean\": function( param ) {\n\t\t\t\treturn param;\n\t\t\t},\n\t\t\t\"string\": function( param, element ) {\n\t\t\t\treturn !!$( param, element.form ).length;\n\t\t\t},\n\t\t\t\"function\": function( param, element ) {\n\t\t\t\treturn param( element );\n\t\t\t}\n\t\t},\n\n\t\toptional: function( element ) {\n\t\t\tvar val = this.elementValue( element );\n\t\t\treturn !$.validator.methods.required.call( this, val, element ) && \"dependency-mismatch\";\n\t\t},\n\n\t\tstartRequest: function( element ) {\n\t\t\tif ( !this.pending[ element.name ] ) {\n\t\t\t\tthis.pendingRequest++;\n\t\t\t\tthis.pending[ element.name ] = true;\n\t\t\t}\n\t\t},\n\n\t\tstopRequest: function( element, valid ) {\n\t\t\tthis.pendingRequest--;\n\t\t\t// sometimes synchronization fails, make sure pendingRequest is never < 0\n\t\t\tif ( this.pendingRequest < 0 ) {\n\t\t\t\tthis.pendingRequest = 0;\n\t\t\t}\n\t\t\tdelete this.pending[ element.name ];\n\t\t\tif ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {\n\t\t\t\t$( this.currentForm ).submit();\n\t\t\t\tthis.formSubmitted = false;\n\t\t\t} else if (!valid && this.pendingRequest === 0 && this.formSubmitted ) {\n\t\t\t\t$( this.currentForm ).triggerHandler( \"invalid-form\", [ this ]);\n\t\t\t\tthis.formSubmitted = false;\n\t\t\t}\n\t\t},\n\n\t\tpreviousValue: function( element ) {\n\t\t\treturn $.data( element, \"previousValue\" ) || $.data( element, \"previousValue\", {\n\t\t\t\told: null,\n\t\t\t\tvalid: true,\n\t\t\t\tmessage: this.defaultMessage( element, \"remote\" )\n\t\t\t});\n\t\t},\n\n\t\t// cleans up all forms and elements, removes validator-specific events\n\t\tdestroy: function() {\n\t\t\tthis.resetForm();\n\n\t\t\t$( this.currentForm )\n\t\t\t\t.off( \".validate\" )\n\t\t\t\t.removeData( \"validator\" );\n\t\t}\n\n\t},\n\n\tclassRuleSettings: {\n\t\trequired: { required: true },\n\t\temail: { email: true },\n\t\turl: { url: true },\n\t\tdate: { date: true },\n\t\tdateISO: { dateISO: true },\n\t\tnumber: { number: true },\n\t\tdigits: { digits: true },\n\t\tcreditcard: { creditcard: true }\n\t},\n\n\taddClassRules: function( className, rules ) {\n\t\tif ( className.constructor === String ) {\n\t\t\tthis.classRuleSettings[ className ] = rules;\n\t\t} else {\n\t\t\t$.extend( this.classRuleSettings, className );\n\t\t}\n\t},\n\n\tclassRules: function( element ) {\n\t\tvar rules = {},\n\t\t\tclasses = $( element ).attr( \"class\" );\n\n\t\tif ( classes ) {\n\t\t\t$.each( classes.split( \" \" ), function() {\n\t\t\t\tif ( this in $.validator.classRuleSettings ) {\n\t\t\t\t\t$.extend( rules, $.validator.classRuleSettings[ this ]);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\treturn rules;\n\t},\n\n\tnormalizeAttributeRule: function( rules, type, method, value ) {\n\n\t\t// convert the value to a number for number inputs, and for text for backwards compability\n\t\t// allows type=\"date\" and others to be compared as strings\n\t\tif ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {\n\t\t\tvalue = Number( value );\n\n\t\t\t// Support Opera Mini, which returns NaN for undefined minlength\n\t\t\tif ( isNaN( value ) ) {\n\t\t\t\tvalue = undefined;\n\t\t\t}\n\t\t}\n\n\t\tif ( value || value === 0 ) {\n\t\t\trules[ method ] = value;\n\t\t} else if ( type === method && type !== \"range\" ) {\n\n\t\t\t// exception: the jquery validate 'range' method\n\t\t\t// does not test for the html5 'range' type\n\t\t\trules[ method ] = true;\n\t\t}\n\t},\n\n\tattributeRules: function( element ) {\n\t\tvar rules = {},\n\t\t\t$element = $( element ),\n\t\t\ttype = element.getAttribute( \"type\" ),\n\t\t\tmethod, value;\n\n\t\tfor ( method in $.validator.methods ) {\n\n\t\t\t// support for <input required> in both html5 and older browsers\n\t\t\tif ( method === \"required\" ) {\n\t\t\t\tvalue = element.getAttribute( method );\n\n\t\t\t\t// Some browsers return an empty string for the required attribute\n\t\t\t\t// and non-HTML5 browsers might have required=\"\" markup\n\t\t\t\tif ( value === \"\" ) {\n\t\t\t\t\tvalue = true;\n\t\t\t\t}\n\n\t\t\t\t// force non-HTML5 browsers to return bool\n\t\t\t\tvalue = !!value;\n\t\t\t} else {\n\t\t\t\tvalue = $element.attr( method );\n\t\t\t}\n\n\t\t\tthis.normalizeAttributeRule( rules, type, method, value );\n\t\t}\n\n\t\t// maxlength may be returned as -1, 2147483647 ( IE ) and 524288 ( safari ) for text inputs\n\t\tif ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {\n\t\t\tdelete rules.maxlength;\n\t\t}\n\n\t\treturn rules;\n\t},\n\n\tdataRules: function( element ) {\n\t\tvar rules = {},\n\t\t\t$element = $( element ),\n\t\t\ttype = element.getAttribute( \"type\" ),\n\t\t\tmethod, value;\n\n\t\tfor ( method in $.validator.methods ) {\n\t\t\tvalue = $element.data( \"rule\" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );\n\t\t\tthis.normalizeAttributeRule( rules, type, method, value );\n\t\t}\n\t\treturn rules;\n\t},\n\n\tstaticRules: function( element ) {\n\t\tvar rules = {},\n\t\t\tvalidator = $.data( element.form, \"validator\" );\n\n\t\tif ( validator.settings.rules ) {\n\t\t\trules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};\n\t\t}\n\t\treturn rules;\n\t},\n\n\tnormalizeRules: function( rules, element ) {\n\t\t// handle dependency check\n\t\t$.each( rules, function( prop, val ) {\n\t\t\t// ignore rule when param is explicitly false, eg. required:false\n\t\t\tif ( val === false ) {\n\t\t\t\tdelete rules[ prop ];\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ( val.param || val.depends ) {\n\t\t\t\tvar keepRule = true;\n\t\t\t\tswitch ( typeof val.depends ) {\n\t\t\t\tcase \"string\":\n\t\t\t\t\tkeepRule = !!$( val.depends, element.form ).length;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"function\":\n\t\t\t\t\tkeepRule = val.depends.call( element, element );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif ( keepRule ) {\n\t\t\t\t\trules[ prop ] = val.param !== undefined ? val.param : true;\n\t\t\t\t} else {\n\t\t\t\t\tdelete rules[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\t// evaluate parameters\n\t\t$.each( rules, function( rule, parameter ) {\n\t\t\trules[ rule ] = $.isFunction( parameter ) ? parameter( element ) : parameter;\n\t\t});\n\n\t\t// clean number parameters\n\t\t$.each([ \"minlength\", \"maxlength\" ], function() {\n\t\t\tif ( rules[ this ] ) {\n\t\t\t\trules[ this ] = Number( rules[ this ] );\n\t\t\t}\n\t\t});\n\t\t$.each([ \"rangelength\", \"range\" ], function() {\n\t\t\tvar parts;\n\t\t\tif ( rules[ this ] ) {\n\t\t\t\tif ( $.isArray( rules[ this ] ) ) {\n\t\t\t\t\trules[ this ] = [ Number( rules[ this ][ 0 ]), Number( rules[ this ][ 1 ] ) ];\n\t\t\t\t} else if ( typeof rules[ this ] === \"string\" ) {\n\t\t\t\t\tparts = rules[ this ].replace(/[\\[\\]]/g, \"\" ).split( /[\\s,]+/ );\n\t\t\t\t\trules[ this ] = [ Number( parts[ 0 ]), Number( parts[ 1 ] ) ];\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\n\t\tif ( $.validator.autoCreateRanges ) {\n\t\t\t// auto-create ranges\n\t\t\tif ( rules.min != null && rules.max != null ) {\n\t\t\t\trules.range = [ rules.min, rules.max ];\n\t\t\t\tdelete rules.min;\n\t\t\t\tdelete rules.max;\n\t\t\t}\n\t\t\tif ( rules.minlength != null && rules.maxlength != null ) {\n\t\t\t\trules.rangelength = [ rules.minlength, rules.maxlength ];\n\t\t\t\tdelete rules.minlength;\n\t\t\t\tdelete rules.maxlength;\n\t\t\t}\n\t\t}\n\n\t\treturn rules;\n\t},\n\n\t// Converts a simple string to a {string: true} rule, e.g., \"required\" to {required:true}\n\tnormalizeRule: function( data ) {\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tvar transformed = {};\n\t\t\t$.each( data.split( /\\s/ ), function() {\n\t\t\t\ttransformed[ this ] = true;\n\t\t\t});\n\t\t\tdata = transformed;\n\t\t}\n\t\treturn data;\n\t},\n\n\t// http://jqueryvalidation.org/jQuery.validator.addMethod/\n\taddMethod: function( name, method, message ) {\n\t\t$.validator.methods[ name ] = method;\n\t\t$.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];\n\t\tif ( method.length < 3 ) {\n\t\t\t$.validator.addClassRules( name, $.validator.normalizeRule( name ) );\n\t\t}\n\t},\n\n\tmethods: {\n\n\t\t// http://jqueryvalidation.org/required-method/\n\t\trequired: function( value, element, param ) {\n\t\t\t// check if dependency is met\n\t\t\tif ( !this.depend( param, element ) ) {\n\t\t\t\treturn \"dependency-mismatch\";\n\t\t\t}\n\t\t\tif ( element.nodeName.toLowerCase() === \"select\" ) {\n\t\t\t\t// could be an array for select-multiple or a string, both are fine this way\n\t\t\t\tvar val = $( element ).val();\n\t\t\t\treturn val && val.length > 0;\n\t\t\t}\n\t\t\tif ( this.checkable( element ) ) {\n\t\t\t\treturn this.getLength( value, element ) > 0;\n\t\t\t}\n\t\t\treturn value.length > 0;\n\t\t},\n\n\t\t// http://jqueryvalidation.org/email-method/\n\t\temail: function( value, element ) {\n\t\t\t// From https://html.spec.whatwg.org/multipage/forms.html#valid-e-mail-address\n\t\t\t// Retrieved 2014-01-14\n\t\t\t// If you have a problem with this implementation, report a bug against the above spec\n\t\t\t// Or use custom methods to implement your own email validation\n\t\t\treturn this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );\n\t\t},\n\n\t\t// http://jqueryvalidation.org/url-method/\n\t\turl: function( value, element ) {\n\n\t\t\t// Copyright (c) 2010-2013 Diego Perini, MIT licensed\n\t\t\t// https://gist.github.com/dperini/729294\n\t\t\t// see also https://mathiasbynens.be/demo/url-regex\n\t\t\t// modified to allow protocol-relative URLs\n\t\t\treturn this.optional( element ) || /^(?:(?:(?:https?|ftp):)?\\/\\/)(?:\\S+(?::\\S*)?@)?(?:(?!(?:10|127)(?:\\.\\d{1,3}){3})(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})).?)(?::\\d{2,5})?(?:[/?#]\\S*)?$/i.test( value );\n\t\t},\n\n\t\t// http://jqueryvalidation.org/date-method/\n\t\tdate: function( value, element ) {\n\t\t\treturn this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );\n\t\t},\n\n\t\t// http://jqueryvalidation.org/dateISO-method/\n\t\tdateISO: function( value, element ) {\n\t\t\treturn this.optional( element ) || /^\\d{4}[\\/\\-](0?[1-9]|1[012])[\\/\\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );\n\t\t},\n\n\t\t// http://jqueryvalidation.org/number-method/\n\t\tnumber: function( value, element ) {\n\t\t\treturn this.optional( element ) || /^(?:-?\\d+|-?\\d{1,3}(?:,\\d{3})+)?(?:\\.\\d+)?$/.test( value );\n\t\t},\n\n\t\t// http://jqueryvalidation.org/digits-method/\n\t\tdigits: function( value, element ) {\n\t\t\treturn this.optional( element ) || /^\\d+$/.test( value );\n\t\t},\n\n\t\t// http://jqueryvalidation.org/creditcard-method/\n\t\t// based on http://en.wikipedia.org/wiki/Luhn_algorithm\n\t\tcreditcard: function( value, element ) {\n\t\t\tif ( this.optional( element ) ) {\n\t\t\t\treturn \"dependency-mismatch\";\n\t\t\t}\n\t\t\t// accept only spaces, digits and dashes\n\t\t\tif ( /[^0-9 \\-]+/.test( value ) ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar nCheck = 0,\n\t\t\t\tnDigit = 0,\n\t\t\t\tbEven = false,\n\t\t\t\tn, cDigit;\n\n\t\t\tvalue = value.replace( /\\D/g, \"\" );\n\n\t\t\t// Basing min and max length on\n\t\t\t// http://developer.ean.com/general_info/Valid_Credit_Card_Types\n\t\t\tif ( value.length < 13 || value.length > 19 ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor ( n = value.length - 1; n >= 0; n--) {\n\t\t\t\tcDigit = value.charAt( n );\n\t\t\t\tnDigit = parseInt( cDigit, 10 );\n\t\t\t\tif ( bEven ) {\n\t\t\t\t\tif ( ( nDigit *= 2 ) > 9 ) {\n\t\t\t\t\t\tnDigit -= 9;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnCheck += nDigit;\n\t\t\t\tbEven = !bEven;\n\t\t\t}\n\n\t\t\treturn ( nCheck % 10 ) === 0;\n\t\t},\n\n\t\t// http://jqueryvalidation.org/minlength-method/\n\t\tminlength: function( value, element, param ) {\n\t\t\tvar length = $.isArray( value ) ? value.length : this.getLength( value, element );\n\t\t\treturn this.optional( element ) || length >= param;\n\t\t},\n\n\t\t// http://jqueryvalidation.org/maxlength-method/\n\t\tmaxlength: function( value, element, param ) {\n\t\t\tvar length = $.isArray( value ) ? value.length : this.getLength( value, element );\n\t\t\treturn this.optional( element ) || length <= param;\n\t\t},\n\n\t\t// http://jqueryvalidation.org/rangelength-method/\n\t\trangelength: function( value, element, param ) {\n\t\t\tvar length = $.isArray( value ) ? value.length : this.getLength( value, element );\n\t\t\treturn this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );\n\t\t},\n\n\t\t// http://jqueryvalidation.org/min-method/\n\t\tmin: function( value, element, param ) {\n\t\t\treturn this.optional( element ) || value >= param;\n\t\t},\n\n\t\t// http://jqueryvalidation.org/max-method/\n\t\tmax: function( value, element, param ) {\n\t\t\treturn this.optional( element ) || value <= param;\n\t\t},\n\n\t\t// http://jqueryvalidation.org/range-method/\n\t\trange: function( value, element, param ) {\n\t\t\treturn this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );\n\t\t},\n\n\t\t// http://jqueryvalidation.org/equalTo-method/\n\t\tequalTo: function( value, element, param ) {\n\t\t\t// bind to the blur event of the target in order to revalidate whenever the target field is updated\n\t\t\t// TODO find a way to bind the event just once, avoiding the unbind-rebind overhead\n\t\t\tvar target = $( param );\n\t\t\tif ( this.settings.onfocusout ) {\n\t\t\t\ttarget.off( \".validate-equalTo\" ).on( \"blur.validate-equalTo\", function() {\n\t\t\t\t\t$( element ).valid();\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn value === target.val();\n\t\t},\n\n\t\t// http://jqueryvalidation.org/remote-method/\n\t\tremote: function( value, element, param ) {\n\t\t\tif ( this.optional( element ) ) {\n\t\t\t\treturn \"dependency-mismatch\";\n\t\t\t}\n\n\t\t\tvar previous = this.previousValue( element ),\n\t\t\t\tvalidator, data;\n\n\t\t\tif (!this.settings.messages[ element.name ] ) {\n\t\t\t\tthis.settings.messages[ element.name ] = {};\n\t\t\t}\n\t\t\tprevious.originalMessage = this.settings.messages[ element.name ].remote;\n\t\t\tthis.settings.messages[ element.name ].remote = previous.message;\n\n\t\t\tparam = typeof param === \"string\" && { url: param } || param;\n\n\t\t\tif ( previous.old === value ) {\n\t\t\t\treturn previous.valid;\n\t\t\t}\n\n\t\t\tprevious.old = value;\n\t\t\tvalidator = this;\n\t\t\tthis.startRequest( element );\n\t\t\tdata = {};\n\t\t\tdata[ element.name ] = value;\n\t\t\t$.ajax( $.extend( true, {\n\t\t\t\tmode: \"abort\",\n\t\t\t\tport: \"validate\" + element.name,\n\t\t\t\tdataType: \"json\",\n\t\t\t\tdata: data,\n\t\t\t\tcontext: validator.currentForm,\n\t\t\t\tsuccess: function( response ) {\n\t\t\t\t\tvar valid = response === true || response === \"true\",\n\t\t\t\t\t\terrors, message, submitted;\n\n\t\t\t\t\tvalidator.settings.messages[ element.name ].remote = previous.originalMessage;\n\t\t\t\t\tif ( valid ) {\n\t\t\t\t\t\tsubmitted = validator.formSubmitted;\n\t\t\t\t\t\tvalidator.prepareElement( element );\n\t\t\t\t\t\tvalidator.formSubmitted = submitted;\n\t\t\t\t\t\tvalidator.successList.push( element );\n\t\t\t\t\t\tdelete validator.invalid[ element.name ];\n\t\t\t\t\t\tvalidator.showErrors();\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrors = {};\n\t\t\t\t\t\tmessage = response || validator.defaultMessage( element, \"remote\" );\n\t\t\t\t\t\terrors[ element.name ] = previous.message = $.isFunction( message ) ? message( value ) : message;\n\t\t\t\t\t\tvalidator.invalid[ element.name ] = true;\n\t\t\t\t\t\tvalidator.showErrors( errors );\n\t\t\t\t\t}\n\t\t\t\t\tprevious.valid = valid;\n\t\t\t\t\tvalidator.stopRequest( element, valid );\n\t\t\t\t}\n\t\t\t}, param ) );\n\t\t\treturn \"pending\";\n\t\t}\n\t}\n\n});\n\n// ajax mode: abort\n// usage: $.ajax({ mode: \"abort\"[, port: \"uniqueport\"]});\n// if mode:\"abort\" is used, the previous request on that port (port can be undefined) is aborted via XMLHttpRequest.abort()\n\nvar pendingRequests = {},\n\tajax;\n// Use a prefilter if available (1.5+)\nif ( $.ajaxPrefilter ) {\n\t$.ajaxPrefilter(function( settings, _, xhr ) {\n\t\tvar port = settings.port;\n\t\tif ( settings.mode === \"abort\" ) {\n\t\t\tif ( pendingRequests[port] ) {\n\t\t\t\tpendingRequests[port].abort();\n\t\t\t}\n\t\t\tpendingRequests[port] = xhr;\n\t\t}\n\t});\n} else {\n\t// Proxy ajax\n\tajax = $.ajax;\n\t$.ajax = function( settings ) {\n\t\tvar mode = ( \"mode\" in settings ? settings : $.ajaxSettings ).mode,\n\t\t\tport = ( \"port\" in settings ? settings : $.ajaxSettings ).port;\n\t\tif ( mode === \"abort\" ) {\n\t\t\tif ( pendingRequests[port] ) {\n\t\t\t\tpendingRequests[port].abort();\n\t\t\t}\n\t\t\tpendingRequests[port] = ajax.apply(this, arguments);\n\t\t\treturn pendingRequests[port];\n\t\t}\n\t\treturn ajax.apply(this, arguments);\n\t};\n}\n\n}));"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/jquery.validation/1.14.0/messages_zh.js",
    "content": "(function( factory ) {\n\tif ( typeof define === \"function\" && define.amd ) {\n\t\tdefine( [\"jquery\", \"../jquery.validate\"], factory );\n\t} else {\n\t\tfactory( jQuery );\n\t}\n}(function( $ ) {\n\n/*\n * Translated default messages for the jQuery validation plugin.\n * Locale: ZH (Chinese, 中文 (Zhōngwén), 汉语, 漢語)\n */\n$.extend($.validator.messages, {\n\trequired: \"这是必填字段\",\n\tremote: \"请修正此字段\",\n\temail: \"请输入有效的电子邮件地址\",\n\turl: \"请输入有效的网址\",\n\tdate: \"请输入有效的日期\",\n\tdateISO: \"请输入有效的日期 (YYYY-MM-DD)\",\n\tnumber: \"请输入有效的数字\",\n\tdigits: \"只能输入数字\",\n\tcreditcard: \"请输入有效的信用卡号码\",\n\tequalTo: \"你的输入不相同\",\n\textension: \"请输入有效的后缀\",\n\tmaxlength: $.validator.format(\"最多可以输入 {0} 个字符\"),\n\tminlength: $.validator.format(\"最少要输入 {0} 个字符\"),\n\trangelength: $.validator.format(\"请输入长度在 {0} 到 {1} 之间的字符串\"),\n\trange: $.validator.format(\"请输入范围在 {0} 到 {1} 之间的数值\"),\n\tmax: $.validator.format(\"请输入不大于 {0} 的数值\"),\n\tmin: $.validator.format(\"请输入不小于 {0} 的数值\")\n});\n\n}));"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/jquery.validation/1.14.0/validate-methods.js",
    "content": "/*****************************************************************\n * jQuery Validate扩展验证方法  (linjq)    \n * Modified by guojunhui\n * Date modified:01/01/2017  \n*****************************************************************/\n$(function(){\n    // 判断整数value是否等于0 \n    jQuery.validator.addMethod(\"isIntEqZero\", function(value, element) { \n         value=parseInt(value);      \n         return this.optional(element) || value==0;       \n    }, \"整数必须为0\"); \n      \n    // 判断整数value是否大于0\n    jQuery.validator.addMethod(\"isIntGtZero\", function(value, element) { \n         value=parseInt(value);      \n         return this.optional(element) || value>0;       \n    }, \"整数必须大于0\"); \n      \n    // 判断整数value是否大于或等于0\n    jQuery.validator.addMethod(\"isIntGteZero\", function(value, element) { \n         value=parseInt(value);      \n         return this.optional(element) || value>=0;       \n    }, \"整数必须大于或等于0\");   \n    \n    // 判断整数value是否不等于0 \n    jQuery.validator.addMethod(\"isIntNEqZero\", function(value, element) { \n         value=parseInt(value);      \n         return this.optional(element) || value!=0;       \n    }, \"整数必须不等于0\");  \n    \n    // 判断整数value是否小于0 \n    jQuery.validator.addMethod(\"isIntLtZero\", function(value, element) { \n         value=parseInt(value);      \n         return this.optional(element) || value<0;       \n    }, \"整数必须小于0\");  \n    \n    // 判断整数value是否小于或等于0 \n    jQuery.validator.addMethod(\"isIntLteZero\", function(value, element) { \n         value=parseInt(value);      \n         return this.optional(element) || value<=0;       \n    }, \"整数必须小于或等于0\");  \n    \n    // 判断浮点数value是否等于0 \n    jQuery.validator.addMethod(\"isFloatEqZero\", function(value, element) { \n         value=parseFloat(value);      \n         return this.optional(element) || value==0;       \n    }, \"浮点数必须为0\"); \n      \n    // 判断浮点数value是否大于0\n    jQuery.validator.addMethod(\"isFloatGtZero\", function(value, element) { \n         value=parseFloat(value);      \n         return this.optional(element) || value>0;       \n    }, \"浮点数必须大于0\"); \n      \n    // 判断浮点数value是否大于或等于0\n    jQuery.validator.addMethod(\"isFloatGteZero\", function(value, element) { \n         value=parseFloat(value);      \n         return this.optional(element) || value>=0;       \n    }, \"浮点数必须大于或等于0\");   \n    \n    // 判断浮点数value是否不等于0 \n    jQuery.validator.addMethod(\"isFloatNEqZero\", function(value, element) { \n         value=parseFloat(value);      \n         return this.optional(element) || value!=0;       \n    }, \"浮点数必须不等于0\");  \n    \n    // 判断浮点数value是否小于0 \n    jQuery.validator.addMethod(\"isFloatLtZero\", function(value, element) { \n         value=parseFloat(value);      \n         return this.optional(element) || value<0;       \n    }, \"浮点数必须小于0\");  \n    \n    // 判断浮点数value是否小于或等于0 \n    jQuery.validator.addMethod(\"isFloatLteZero\", function(value, element) { \n         value=parseFloat(value);      \n         return this.optional(element) || value<=0;       \n    }, \"浮点数必须小于或等于0\");  \n    \n    // 判断浮点型  \n    jQuery.validator.addMethod(\"isFloat\", function(value, element) {       \n         return this.optional(element) || /^[-\\+]?\\d+(\\.\\d+)?$/.test(value);       \n    }, \"只能包含数字、小数点等字符\"); \n     \n    // 匹配integer\n    jQuery.validator.addMethod(\"isInteger\", function(value, element) {       \n         return this.optional(element) || (/^[-\\+]?\\d+$/.test(value) && parseInt(value)>=0);       \n    }, \"匹配integer\");  \n     \n    // 判断数值类型，包括整数和浮点数\n    jQuery.validator.addMethod(\"isNumber\", function(value, element) {       \n         return this.optional(element) || /^[-\\+]?\\d+$/.test(value) || /^[-\\+]?\\d+(\\.\\d+)?$/.test(value);       \n    }, \"匹配数值类型，包括整数和浮点数\");  \n    \n    // 只能输入[0-9]数字\n    jQuery.validator.addMethod(\"isDigits\", function(value, element) {       \n         return this.optional(element) || /^\\d+$/.test(value);       \n    }, \"只能输入0-9数字\");  \n    \n    // 判断中文字符 \n    jQuery.validator.addMethod(\"isChinese\", function(value, element) {       \n         return this.optional(element) || /^[\\u0391-\\uFFE5]+$/.test(value);       \n    }, \"只能包含中文字符。\");   \n \n    // 判断英文字符 \n    jQuery.validator.addMethod(\"isEnglish\", function(value, element) {       \n         return this.optional(element) || /^[A-Za-z]+$/.test(value);       \n    }, \"只能包含英文字符。\");   \n \n     // 手机号码验证    \n    jQuery.validator.addMethod(\"isMobile\", function(value, element) {    \n      var length = value.length;    \n      return this.optional(element) || (length == 11 && /^(((13[0-9]{1})|(15[0-35-9]{1})|(17[0-9]{1})|(18[0-9]{1}))+\\d{8})$/.test(value));    \n    }, \"手机号码格式不正确。\");\n\n    // 电话号码验证    \n    jQuery.validator.addMethod(\"isPhone\", function(value, element) {    \n      var tel = /^(\\d{3,4}-?)?\\d{7,9}$/g;    \n      return this.optional(element) || (tel.test(value));    \n    }, \"电话号码格式不正确\");\n\n    // 联系电话(手机/电话皆可)验证   \n    jQuery.validator.addMethod(\"isTel\", function(value,element) {   \n        var length = value.length;   \n        var mobile = /^(((13[0-9]{1})|(15[0-35-9]{1})|(17[0-9]{1})|(18[0-9]{1}))+\\d{8})$/;\n        var tel = /^(\\d{3,4}-?)?\\d{7,9}$/g;       \n        return this.optional(element) || tel.test(value) || (length==11 && mobile.test(value));   \n    }, \"请输入正确手机号码或电话号码\"); \n \n     // 匹配qq      \n    jQuery.validator.addMethod(\"isQq\", function(value, element) {       \n         return this.optional(element) || /^[1-9]\\d{4,12}$/;       \n    }, \"QQ号码不合法\");   \n \n     // 邮政编码验证    \n    jQuery.validator.addMethod(\"isZipCode\", function(value, element) {    \n      var zip = /^[0-9]{6}$/;    \n      return this.optional(element) || (zip.test(value));    \n    }, \"邮政编码不正确\");  \n    \n    // 匹配密码，以字母开头，长度在6-16之间，只能包含字符、数字和下划线。      \n    jQuery.validator.addMethod(\"isPwd\", function(value, element) {       \n         return this.optional(element) || /^[a-zA-Z]\\\\w{6,16}$/.test(value);       \n    }, \"以字母开头，长度在6-12之间，只能包含字符、数字和下划线。\");  \n    \n    // 身份证号码验证\n    jQuery.validator.addMethod(\"isIdCardNo\", function(value, element) { \n      //var idCard = /^(\\d{6})()?(\\d{4})(\\d{2})(\\d{2})(\\d{3})(\\w)$/;   \n      return this.optional(element) || isIdCardNo(value);    \n    }, \"身份证号码不正确\"); \n\n    // IP地址验证   \n    jQuery.validator.addMethod(\"ip\", function(value, element) {    \n      return this.optional(element) || /^(([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5])))\\.)(([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5])))\\.){2}([1-9]|([1-9]\\d)|(1\\d\\d)|(2([0-4]\\d|5[0-5])))$/.test(value);    \n    }, \"请填写正确的IP地址\");\n   \n    // 字符验证，只能包含中文、英文、数字、下划线等字符。    \n    jQuery.validator.addMethod(\"stringCheck\", function(value, element) {       \n         return this.optional(element) || /^[a-zA-Z0-9\\u4e00-\\u9fa5-_]+$/.test(value);       \n    }, \"只能包含中文、英文、数字、下划线等字符\");   \n   \n    // 匹配english  \n    jQuery.validator.addMethod(\"isEnglish\", function(value, element) {       \n         return this.optional(element) || /^[A-Za-z]+$/.test(value);       \n    }, \"必须输入英文\");   \n    \n    // 匹配汉字  \n    jQuery.validator.addMethod(\"isChinese\", function(value, element) {       \n         return this.optional(element) || /^[\\u4e00-\\u9fa5]+$/.test(value);       \n    }, \"只能输入汉字\");   \n    \n    // 匹配中文(包括汉字和字符) \n    jQuery.validator.addMethod(\"isChineseChar\", function(value, element) {       \n         return this.optional(element) || /^[\\u0391-\\uFFE5]+$/.test(value);       \n    }, \"匹配中文(包括汉字和字符) \"); \n      \n    // 判断是否为合法字符(a-zA-Z0-9-_)\n    jQuery.validator.addMethod(\"isRightfulString\", function(value, element) {       \n         return this.optional(element) || /^[A-Za-z0-9_-]+$/.test(value);       \n    }, \"判断是否为合法字符(a-zA-Z0-9-_)\");   \n    \n    // 判断是否包含中英文特殊字符，除英文\"-_\"字符外\n    jQuery.validator.addMethod(\"isContainsSpecialChar\", function(value, element) {  \n         var reg = RegExp(/[(\\ )(\\`)(\\~)(\\!)(\\@)(\\#)(\\$)(\\%)(\\^)(\\&)(\\*)(\\()(\\))(\\+)(\\=)(\\|)(\\{)(\\})(\\')(\\:)(\\;)(\\')(',)(\\[)(\\])(\\.)(\\<)(\\>)(\\/)(\\?)(\\~)(\\！)(\\@)(\\#)(\\￥)(\\%)(\\…)(\\&)(\\*)(\\（)(\\）)(\\—)(\\+)(\\|)(\\{)(\\})(\\【)(\\】)(\\‘)(\\；)(\\：)(\\”)(\\“)(\\’)(\\。)(\\，)(\\、)(\\？)]+/);   \n         return this.optional(element) || !reg.test(value);       \n    }, \"含有中英文特殊字符\");\n\t\n\t//车牌号校验\n\tjQuery.validator.addMethod(\"isPlateNo\", function(value, element) {\n\t\tvar reg = /^[\\u4e00-\\u9fa5]{1}[A-Z]{1}[A-Z_0-9]{5}$/;\n\t\treturn this.optional(element) || (tel.test(value)); \n\t},\"请输入正确车牌号\");\n});\n//身份证号码的验证规则\nfunction isIdCardNo(num){ \n　   //if (isNaN(num)) {alert(\"输入的不是数字！\"); return false;} \n　　 var len = num.length, re; \n　　 if (len == 15) \n　　 re = new RegExp(/^(\\d{6})()?(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\w)$/); \n　　 else if (len == 18) \n　　 re = new RegExp(/^(\\d{6})()?(\\d{4})(\\d{2})(\\d{2})(\\d{3})(\\w)$/); \n　　 else {\n\t\t//alert(\"输入的数字位数不对。\"); \n\t\treturn false;\n\t} \n　　 var a = num.match(re); \n　　 if (a != null) \n　　 { \n　　 if (len==15) \n　　 { \n　　 var D = new Date(\"19\"+a[3]+\"/\"+a[4]+\"/\"+a[5]); \n　　 var B = D.getYear()==a[3]&&(D.getMonth()+1)==a[4]&&D.getDate()==a[5]; \n　　 } \n　　 else \n　　 { \n　　 var D = new Date(a[3]+\"/\"+a[4]+\"/\"+a[5]); \n　　 var B = D.getFullYear()==a[3]&&(D.getMonth()+1)==a[4]&&D.getDate()==a[5]; \n　　 } \n　　 if (!B) {\n\t\t//alert(\"输入的身份证号 \"+ a[0] +\" 里出生日期不对。\"); \n\t\treturn false;\n\t} \n　　 } \n　　 if(!re.test(num)){\n\t\t//alert(\"身份证最后一位只能是数字和字母。\");\n\t\treturn false;\n\t}\n　　 return true; \n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/jselect-1.0.js",
    "content": "/*!\n * js模拟系统select v1.0\n * http://www.cnblogs.com/typeof/ \n * \n * 主流浏览器对html的select元素渲染都不一样，IE系列(6, 7, 8)也不一样，\n * firefox，chrome，safari，opera 渲染和事件处理也稍有差异\n * 该脚本解决了在不同浏览器下渲染和事件响应不一致的问题，对系统select是完全\n * 意义上的替换。v1.0版本只支持单个select选择即不支持二级或者三级联动且不支持系统select的onchange事件。\n * 该版本支持模拟select选择的数据和系统select选中数据的同步，不影响form表单的提交 \n *\n * 如果page上select有的不想通过该脚本替换，只想维持系统select，可以在相应的select元素添加自定义属性data-enabled=\"true\"，\n * 否则可以在想要通过该脚本替换的select元素上添加自定义属性data-enabled=\"false\"或者不加，会默认为这个select需要\n * 通过该脚本进行替换\n *\n * 日期：2012-11-07 15:38\n */\n(function(squid) {\n    function JSelect() {\n        this.init()\n    } \n\n    JSelect.prototype = {\n        constructor: JSelect,\n        init: function(context) {\n            //获取指定上下文所有select元素\n            var elems = squid.getElementsByTagName('select', context)\n            this.globalEvent()\n            this.initView(elems)\n        },\n        initView: function(elems) {\n            var i = 0,\n                elem,\n                length = elems.length,\n                enabled;\n\n            for(; i < length; i++) {\n                elem = elems[i]\n                enabled = elem.getAttribute('data-enabled')\n                //使用系统select\n                if(!enabled || enabled === 'true')\n                    continue\n                if(squid.isVisible(elem))\n                    elem.style.display = 'none'\n                \n                this.create(elem)\n            }\n        },\n        create: function(elem) {\n            var data = [],\n                i = 0,\n                length,\n                option,\n                options,\n                value,\n                text,\n                obj,\n                lis,\n                ul,\n                _default,\n                icon,\n                selectedText,\n                selectedValue,\n                div,\n                wrapper,\n                position,\n                left,\n                top,\n                cssText; \n\n            options = elem.getElementsByTagName('option') \n            length = options.length\n            for(; i < length; i++) {\n                option = options[i]\n                value = option.value\n                text = option.innerText || option.textContent\n                \n                obj = {\n                    value: value, \n                    text: text\n                }\n                if(option.selected) {\n                   selectedValue = value\n                   selectedText = text  \n                   obj['selected'] = true \n                }\n                data.push(obj)\n            }\n\n            lis = this.render(this.tmpl, data)\n            ul = '<ul class=\"select-item\">' + lis + '</ul>'\n            //\n            div = document.createElement('span')\n            div.style.display = 'none'\n            div.className = 'select-wrapper'\n            //已选元素\n            _default = document.createElement('span')\n            _default.className = 'select-default unselectable'\n            _default.unselectable = 'on'\n            //让div元素能够获取焦点\n            _default.setAttribute('tabindex', '1')\n            _default.setAttribute('data-value', selectedValue)\n            _default.setAttribute('hidefocus', true)\n            _default.innerHTML = selectedText \n            div.appendChild(_default) \n            //选择icon\n            icon = document.createElement('i')\n            icon.className = 'select-icon' \n            div.appendChild(icon)\n            //下拉列表\n            wrapper = document.createElement('span')\n            wrapper.className = 'select-list hide'\n            wrapper.innerHTML = ul\n            //生成新的元素\n            div.appendChild(wrapper)\n            //插入到select元素后面\n            elem.parentNode.insertBefore(div, null)\n            //获取select元素left top值\n            //先设置select显示，取完left, top值后重新隐藏\n            elem.style.display = 'block'\n            //事件绑定\n            this.sysEvent(div)\n            position = squid.position(elem)\n            elem.style.display = 'none'\n            left = position.left\n            top = position.top\n            cssText = ' display: inline-block;'\n            div.style.cssText = cssText\n        },\n        globalEvent: function() {\n            //document 添加click事件，用户处理每个jselect元素展开关闭\n            var target,\n                className,\n                elem,\n                wrapper,\n                status,\n                that = this;\n\n\n            squid.on(document, 'click', function(event) {\n                target = event.target, \n                className = target.className;\n\n                switch(className) {\n                    case 'select-icon':\n                    case 'select-default unselectable':\n                        elem = target.tagName.toLowerCase() === 'span' ? target : target.previousSibling\n                        wrapper = elem.nextSibling.nextSibling\n                         \n                        //firefox 鼠标右键会触发click事件\n                        //鼠标左键点击执行\n                        if(event.button === 0) {\n                            //初始化选中元素\n                            that.initSelected(elem)\n                            if(squid.isHidden(wrapper)) {\n                                status = 'inline-block'\n                                //关闭所有展开jselect\n                                that.closeSelect() \n                            }else{\n                                status = 'none' \n                            }\n                            wrapper.style.display = status \n                            elem.focus() \n                        }else if(event.button === 2){\n                            wrapper.style.display = 'none' \n                        }\n                        that.zIndex(wrapper)\n                        break\n                    case 'select-option':\n                    case 'select-option selected':\n                        if(event.button === 0) {\n                            that.fireSelected(target, target.parentNode.parentNode.previousSibling.previousSibling)\n                            wrapper.style.display = 'none' \n                        }\n                        break\n                    default:\n                        while(target && target.nodeType !== 9) {\n                            if(target.nodeType === 1) {\n                                if(target.className === 'select-wrapper') {\n                                    return\n                                } \n                            }\n                            target = target.parentNode\n                        }\n                        that.closeSelect()\n                        break\n                } \n            })\n        },\n        sysEvent: function(elem) {\n            var stand = elem.firstChild,\n                dropdown = elem.lastChild,\n                target,\n                //firefox = 'MozBinding' in document.documentElement.style,\n                chrome = /chrome/i.test(navigator.userAgent),\n                keyup = chrome ? 'keypress' : 'keyup',\n                that = this;\n\n            squid.on(elem, 'mouseover', function(event) {\n                if(!that.doScrolling) {\n                    target = event.target\n                    that.activate(target)  \n                }\n            })\n\n            squid.on(elem, 'mouseout', function(event) {\n                if(!that.doScrolling) {\n                    target = event.target \n                    that.deactivate(target)\n                }\n            })\n\n            squid.on(stand, 'keydown', function(event) {\n               var keyCode = event.keyCode;\n\n               switch(keyCode) {\n                   //回车选中\n                   case 13:\n                        that.enter(dropdown) \n                        break\n                   //向上键\n                   case 38:\n                       that.doScrolling = true\n                       that.up(dropdown) \n                       break\n                   //向下键\n                   case 40:\n                       that.doScrolling = true\n                       that.down(dropdown) \n                       break\n                   default:\n                       break\n               } \n            })\n\n            squid.on(stand, keyup, function(event) {\n               var keyCode = event.keyCode;\n\n               switch(keyCode) {\n                   //回车选中\n                   case 13:\n                        that.doScrolling = false\n                        break\n                   //向上键\n                   case 38:\n                        that.doScrolling = false\n                        break\n                   //向下键\n                   case 40:\n                       that.doScrolling = false\n                       break\n                   default:\n                       break\n               }  \n            })\n        },\n        zIndex: function(elem) {\n            var index = 10,\n                cur = elem.parentNode.parentNode,\n                next = squid.next(cur);\n            \n            if(next) {\n                cur.style.zIndex = index\n                next.style.zIndex = --index\n            }\n        },\n        initSelected: function(elem) {\n            var curText = elem.innerText || elem.textContent,\n                curValue = elem.getAttribute('data-value'),\n                wrapper = elem.nextSibling.nextSibling,\n                n = wrapper.firstChild.firstChild,\n                text,\n                value,\n                dir,\n                min = 0,\n                max,\n                hidden = false;\n\n            for(; n; n = n.nextSibling) {\n                text = n.innerText || n.textContent \n                value = n.getAttribute('data-value')\n                if(curText === text && curValue === value) {\n                    //显示已选中元素\n                    if(squid.isHidden(wrapper)) {\n                        wrapper.style.display = 'block'\n                        hidden = true\n                    }\n                    max = wrapper.scrollHeight\n                    if(n.offsetTop > (max / 2)) {\n                        if(wrapper.clientHeight + wrapper.scrollTop === max) \n                            dir = 'up'\n                        else\n                            dir = 'down'\n                    }else{\n                        if(wrapper.scrollTop === min)\n                            dir = 'down'\n                        else\n                            dir = 'up'\n                    }\n                    this.inView(n, wrapper, dir) \n                    if(hidden)\n                        wrapper.style.display = 'none'\n                    this.activate(n)\n                    break\n                }\n            } \n        },\n        activate: function(elem) {\n            var tagName = (elem.tagName || '').toLowerCase(),\n                    className = elem.className,\n                    parent = elem.parentNode,\n                    first = parent.firstChild,\n                    last = parent.lastChild;\n\n            switch(tagName) {\n                case 'li':\n                    //li.select-option 元素\n                    if(!~className.indexOf('selected') && (elem !== first || elem !== last)) {\n                        this.deactivate(elem)\n                        elem.className = className + ' selected'\n                    }\n                    break\n                default:\n                    break\n            } \n        },\n        deactivate: function(elem) {\n             var tagName = (elem.tagName || '').toLowerCase(),\n                 className = (' ' + elem.className + ' ').replace(/[\\n\\r\\t]/, '');\n\n            switch(tagName) {\n                case 'li':\n                    //li.select-option 元素\n                    var i = 0,\n                        lis = squid.siblings(elem),\n                        length = lis.length,\n                        cur;\n\n                    for(; i < length; i++) {\n                        cur = lis[i] \n                        cur.className = squid.trim(className.replace(' selected ', ''))\n                    }\n                    break\n                default:\n                    break\n            }\n        },\n        fireSelected: function(elem, s) {\n            var text = elem.innerText || elem.textContent,\n                value = elem.getAttribute('data-value'),\n                r;\n\n            s.setAttribute('data-value', value) \n            if(s.innerText) \n                s.innerText = text\n            else\n                s.textContent = text\n\n            //触发系统select选中，用于form表单提交\n            r = s.parentNode.previousSibling.previousSibling\n            r.value = value \n            r.setAttribute('data-text', text)\n        },\n        closeSelect: function() {\n            var elems = squid.getElementsByClassName('select-list'),\n                i = 0,\n                length = elems.length,\n                elem;  \n\n            for(; i < length; i++) {\n                elem = elems[i] \n                if(squid.isVisible(elem))\n                    elem.style.display = 'none'\n            }\n        },\n        up: function(elem) {\n            var ul = elem.firstChild,\n                lis = ul.childNodes,\n                li = this.getSelectedIndex(lis),\n                cur,\n                i = li.index;\n            \n            if(i > 0) {\n                i-- \n                cur = lis[i]\n                //判断元素是否in view\n                this.inView(cur, elem, 'up')\n                this.activate(cur) \n                this.fireSelected(cur, elem.previousSibling.previousSibling) \n            }\n        },\n        down: function(elem) {\n            var ul = elem.firstChild,\n                lis = ul.childNodes,\n                li = this.getSelectedIndex(lis),\n                cur,\n                i = li.index;\n\n            if(i < lis.length - 1) {\n                 i++ \n                 cur = lis[i]\n                 //判断元素是否in view\n                 this.inView(cur, elem, 'down') \n                 this.activate(cur)\n                 this.fireSelected(cur, elem.previousSibling.previousSibling)\n            } \n        },\n        enter: function(elem) {\n            var ul = elem.firstChild,\n                lis = ul.childNodes,\n                li,\n                i,\n                cur;\n\n            li = this.getSelectedIndex(lis)\n            i = li.index\n            cur = lis[i] \n            this.fireSelected(cur, elem.previousSibling.previousSibling) \n            this.closeSelect()\n        },\n        getSelectedIndex: function(elems) {\n            var i = 0,\n                length = elems.length,\n                elem;\n            \n            for(; i < length; i++) {\n                elem = elems[i]\n                if(~elem.className.indexOf('selected')) {\n                    return {\n                        index: i\n                    } \n                }\n            }\n\n            return {\n                index: -1\n            }\n        },\n        inView: function(elem, wrapper, dir) {\n            var scrollTop = wrapper.scrollTop,\n                offsetTop = elem.offsetTop,\n                top;\n\n            if(dir === 'up') {\n                if(offsetTop === 0) {\n                    wrapper.scrollTop = offsetTop;\n                }else if(offsetTop < scrollTop) {\n                    top = offsetTop - scrollTop\n                    this.scrollInView(wrapper, top) \n                }\n            }else{\n                var clientHeight = wrapper.clientHeight;\n                \n                if(offsetTop + elem.offsetHeight === wrapper.scrollHeight) {\n                    wrapper.scrollTop = wrapper.scrollHeight - wrapper.clientHeight \n                }else if(offsetTop + elem.offsetHeight > clientHeight + scrollTop) {\n                    top = (offsetTop + elem.offsetHeight) - (scrollTop + clientHeight)\n                    this.scrollInView(wrapper, top) \n                }\n            }\n        },\n        scrollInView: function(elem, top) {\n            setTimeout(function() {\n                elem.scrollTop += top\n            }, 10)\n        },\n        doScrolling: false,\n        render: function(tmpl, data) {\n            var i = 0,\n                cur,\n                length = data.length,\n                prop,\n                value,\n                item,\n                r = [];\n\n            for(; i < length; i++) {\n               cur = data[i]\n               item = tmpl.replace(/\\{\\{\\w+\\}\\}/g, function(a) {\n                   prop = a.replace(/[\\{\\}]+/g, '')\n                   value = cur[prop] || ''\n                   if(prop === 'class') {\n                        value += 'select-option'\n                        if(cur.selected) {\n                            value += ' selected' \n                        }\n                   }\n                        \n                   return value\n               })\n               r.push(item)\n            }\n\n            return r.join('')\n        },\n        tmpl: '<li class=\"{{class}}\" data-value=\"{{value}}\">{{text}}</li>'\n    }\n\n    squid.swing.jselect = function() {\n        return new JSelect() \n    }\n})(squid);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/kindeditor.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2017 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @website http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n* @version 4.1.12 (2017-04-12)\n*******************************************************************************/\n(function (window, undefined) {\n\tif (window.KindEditor) {\n\t\treturn;\n\t}\n\n\nif (!window.console) {\n\twindow.console = {};\n}\nif (!console.log) {\n\tconsole.log = function () {};\n}\nvar _VERSION = '4.1.12 (2017-04-12)',\n\t_ua = navigator.userAgent.toLowerCase(),\n\t_IE = _ua.indexOf('msie') > -1 && _ua.indexOf('opera') == -1,\n\t_NEWIE = _ua.indexOf('msie') == -1 && _ua.indexOf('trident') > -1,\n\t_GECKO = _ua.indexOf('gecko') > -1 && _ua.indexOf('khtml') == -1,\n\t_WEBKIT = _ua.indexOf('applewebkit') > -1,\n\t_OPERA = _ua.indexOf('opera') > -1,\n\t_MOBILE = _ua.indexOf('mobile') > -1,\n\t_IOS = /ipad|iphone|ipod/.test(_ua),\n\t_QUIRKS = document.compatMode != 'CSS1Compat',\n\t_IERANGE = !window.getSelection,\n\t_matches = /(?:msie|firefox|webkit|opera)[\\/:\\s](\\d+)/.exec(_ua),\n\t_V = _matches ? _matches[1] : '0',\n\t_TIME = new Date().getTime();\nfunction _isArray(val) {\n\tif (!val) {\n\t\treturn false;\n\t}\n\treturn Object.prototype.toString.call(val) === '[object Array]';\n}\nfunction _isFunction(val) {\n\tif (!val) {\n\t\treturn false;\n\t}\n\treturn Object.prototype.toString.call(val) === '[object Function]';\n}\nfunction _inArray(val, arr) {\n\tfor (var i = 0, len = arr.length; i < len; i++) {\n\t\tif (val === arr[i]) {\n\t\t\treturn i;\n\t\t}\n\t}\n\treturn -1;\n}\nfunction _each(obj, fn) {\n\tif (_isArray(obj)) {\n\t\tfor (var i = 0, len = obj.length; i < len; i++) {\n\t\t\tif (fn.call(obj[i], i, obj[i]) === false) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else {\n\t\tfor (var key in obj) {\n\t\t\tif (obj.hasOwnProperty(key)) {\n\t\t\t\tif (fn.call(obj[key], key, obj[key]) === false) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\nfunction _trim(str) {\n\treturn str.replace(/(?:^[ \\t\\n\\r]+)|(?:[ \\t\\n\\r]+$)/g, '');\n}\nfunction _inString(val, str, delimiter) {\n\tdelimiter = delimiter === undefined ? ',' : delimiter;\n\treturn (delimiter + str + delimiter).indexOf(delimiter + val + delimiter) >= 0;\n}\nfunction _addUnit(val, unit) {\n\tunit = unit || 'px';\n\treturn val && /^-?\\d+(?:\\.\\d+)?$/.test(val) ? val + unit : val;\n}\nfunction _removeUnit(val) {\n\tvar match;\n\treturn val && (match = /(\\d+)/.exec(val)) ? parseInt(match[1], 10) : 0;\n}\nfunction _escape(val) {\n\treturn val.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');\n}\nfunction _unescape(val) {\n\treturn val.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '\"').replace(/&amp;/g, '&');\n}\nfunction _toCamel(str) {\n\tvar arr = str.split('-');\n\tstr = '';\n\t_each(arr, function(key, val) {\n\t\tstr += (key > 0) ? val.charAt(0).toUpperCase() + val.substr(1) : val;\n\t});\n\treturn str;\n}\nfunction _toHex(val) {\n\tfunction hex(d) {\n\t\tvar s = parseInt(d, 10).toString(16).toUpperCase();\n\t\treturn s.length > 1 ? s : '0' + s;\n\t}\n\treturn val.replace(/rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)/ig,\n\t\tfunction($0, $1, $2, $3) {\n\t\t\treturn '#' + hex($1) + hex($2) + hex($3);\n\t\t}\n\t);\n}\nfunction _toMap(val, delimiter) {\n\tdelimiter = delimiter === undefined ? ',' : delimiter;\n\tvar map = {}, arr = _isArray(val) ? val : val.split(delimiter), match;\n\t_each(arr, function(key, val) {\n\t\tif ((match = /^(\\d+)\\.\\.(\\d+)$/.exec(val))) {\n\t\t\tfor (var i = parseInt(match[1], 10); i <= parseInt(match[2], 10); i++) {\n\t\t\t\tmap[i.toString()] = true;\n\t\t\t}\n\t\t} else {\n\t\t\tmap[val] = true;\n\t\t}\n\t});\n\treturn map;\n}\nfunction _toArray(obj, offset) {\n\treturn Array.prototype.slice.call(obj, offset || 0);\n}\nfunction _undef(val, defaultVal) {\n\treturn val === undefined ? defaultVal : val;\n}\nfunction _invalidUrl(url) {\n\treturn !url || /[<>\"]/.test(url);\n}\nfunction _addParam(url, param) {\n\treturn url.indexOf('?') >= 0 ? url + '&' + param : url + '?' + param;\n}\nfunction _extend(child, parent, proto) {\n\tif (!proto) {\n\t\tproto = parent;\n\t\tparent = null;\n\t}\n\tvar childProto;\n\tif (parent) {\n\t\tvar fn = function () {};\n\t\tfn.prototype = parent.prototype;\n\t\tchildProto = new fn();\n\t\t_each(proto, function(key, val) {\n\t\t\tchildProto[key] = val;\n\t\t});\n\t} else {\n\t\tchildProto = proto;\n\t}\n\tchildProto.constructor = child;\n\tchild.prototype = childProto;\n\tchild.parent = parent ? parent.prototype : null;\n}\n\n\nfunction _json(text) {\n\tvar match;\n\tif ((match = /\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\]/.exec(text))) {\n\t\ttext = match[0];\n\t}\n\tvar cx = /[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;\n\tcx.lastIndex = 0;\n\tif (cx.test(text)) {\n\t\ttext = text.replace(cx, function (a) {\n\t\t\treturn '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);\n\t\t});\n\t}\n\tif (/^[\\],:{}\\s]*$/.\n\ttest(text.replace(/\\\\(?:[\"\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').\n\treplace(/\"[^\"\\\\\\n\\r]*\"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']').\n\treplace(/(?:^|:|,)(?:\\s*\\[)+/g, ''))) {\n\t\treturn eval('(' + text + ')');\n\t}\n\tthrow 'JSON parse error';\n}\nvar _round = Math.round;\nvar K = {\n\tDEBUG : false,\n\tVERSION : _VERSION,\n\tIE : _IE,\n\tGECKO : _GECKO,\n\tWEBKIT : _WEBKIT,\n\tOPERA : _OPERA,\n\tV : _V,\n\tTIME : _TIME,\n\teach : _each,\n\tisArray : _isArray,\n\tisFunction : _isFunction,\n\tinArray : _inArray,\n\tinString : _inString,\n\ttrim : _trim,\n\taddUnit : _addUnit,\n\tremoveUnit : _removeUnit,\n\tescape : _escape,\n\tunescape : _unescape,\n\ttoCamel : _toCamel,\n\ttoHex : _toHex,\n\ttoMap : _toMap,\n\ttoArray : _toArray,\n\tundef : _undef,\n\tinvalidUrl : _invalidUrl,\n\taddParam : _addParam,\n\textend : _extend,\n\tjson : _json\n};\nvar _INLINE_TAG_MAP = _toMap('a,abbr,acronym,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,img,input,ins,kbd,label,map,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'),\n\t_BLOCK_TAG_MAP = _toMap('address,applet,blockquote,body,center,dd,dir,div,dl,dt,fieldset,form,frameset,h1,h2,h3,h4,h5,h6,head,hr,html,iframe,ins,isindex,li,map,menu,meta,noframes,noscript,object,ol,p,pre,script,style,table,tbody,td,tfoot,th,thead,title,tr,ul'),\n\t_SINGLE_TAG_MAP = _toMap('area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed'),\n\t_STYLE_TAG_MAP = _toMap('b,basefont,big,del,em,font,i,s,small,span,strike,strong,sub,sup,u'),\n\t_CONTROL_TAG_MAP = _toMap('img,table,input,textarea,button'),\n\t_PRE_TAG_MAP = _toMap('pre,style,script'),\n\t_NOSPLIT_TAG_MAP = _toMap('html,head,body,td,tr,table,ol,ul,li'),\n\t_AUTOCLOSE_TAG_MAP = _toMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'),\n\t_FILL_ATTR_MAP = _toMap('checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'),\n\t_VALUE_TAG_MAP = _toMap('input,button,textarea,select');\n\n\nfunction _getBasePath() {\n\tvar els = document.getElementsByTagName('script'), src;\n\tfor (var i = 0, len = els.length; i < len; i++) {\n\t\tsrc = els[i].src || '';\n\t\tif (/kindeditor[\\w\\-\\.]*\\.js/.test(src)) {\n\t\t\treturn src.substring(0, src.lastIndexOf('/') + 1);\n\t\t}\n\t}\n\treturn '';\n}\nK.basePath = _getBasePath();\nK.options = {\n\tdesignMode : true,\n\tfullscreenMode : false,\n\tfilterMode : true,\n\twellFormatMode : true,\n\tshadowMode : true,\n\tloadStyleMode : true,\n\tbasePath : K.basePath,\n\tthemesPath : K.basePath + 'themes/',\n\tlangPath : K.basePath + 'lang/',\n\tpluginsPath : K.basePath + 'plugins/',\n\tthemeType : 'default',\n\tlangType : 'zh-CN',\n\turlType : '',\n\tnewlineTag : 'p',\n\tresizeType : 2,\n\tsyncType : 'form',\n\tpasteType : 2,\n\tdialogAlignType : 'page',\n\tuseContextmenu : true,\n\tfullscreenShortcut : false,\n\tbodyClass : 'ke-content',\n\tindentChar : '\\t',\n\tcssPath : '',\n\tcssData : '',\n\tminWidth : 650,\n\tminHeight : 100,\n\tminChangeSize : 50,\n\tzIndex : 811213,\n\titems : [\n\t\t'source', '|', 'undo', 'redo', '|', 'preview', 'print', 'template', 'code', 'cut', 'copy', 'paste',\n\t\t'plainpaste', 'wordpaste', '|', 'justifyleft', 'justifycenter', 'justifyright',\n\t\t'justifyfull', 'insertorderedlist', 'insertunorderedlist', 'indent', 'outdent', 'subscript',\n\t\t'superscript', 'clearhtml', 'quickformat', 'selectall', '|', 'fullscreen', '/',\n\t\t'formatblock', 'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold',\n\t\t'italic', 'underline', 'strikethrough', 'lineheight', 'removeformat', '|', 'image', 'multiimage',\n\t\t'flash', 'media',/* 'insertfile',*/ 'table', 'hr', 'emoticons', 'baidumap', 'pagebreak',\n\t\t'anchor', 'link', 'unlink', '|', 'about'\n\t],\n\tnoDisableItems : ['source', 'fullscreen'],\n\tcolorTable : [\n\t\t['#E53333', '#E56600', '#FF9900', '#64451D', '#DFC5A4', '#FFE500'],\n\t\t['#009900', '#006600', '#99BB00', '#B8D100', '#60D978', '#00D5FF'],\n\t\t['#337FE5', '#003399', '#4C33E5', '#9933E5', '#CC33E5', '#EE33EE'],\n\t\t['#FFFFFF', '#CCCCCC', '#999999', '#666666', '#333333', '#000000']\n\t],\n\tfontSizeTable : ['9px', '10px', '12px', '14px', '16px', '18px', '24px', '32px'],\n\thtmlTags : {\n\t\tfont : ['id', 'class', 'color', 'size', 'face', '.background-color'],\n\t\tspan : [\n\t\t\t'id', 'class', '.color', '.background-color', '.font-size', '.font-family', '.background',\n\t\t\t'.font-weight', '.font-style', '.text-decoration', '.vertical-align', '.line-height'\n\t\t],\n\t\tdiv : [\n\t\t\t'id', 'class', 'align', '.border', '.margin', '.padding', '.text-align', '.color',\n\t\t\t'.background-color', '.font-size', '.font-family', '.font-weight', '.background',\n\t\t\t'.font-style', '.text-decoration', '.vertical-align', '.margin-left'\n\t\t],\n\t\ttable: [\n\t\t\t'id', 'class', 'border', 'cellspacing', 'cellpadding', 'width', 'height', 'align', 'bordercolor',\n\t\t\t'.padding', '.margin', '.border', 'bgcolor', '.text-align', '.color', '.background-color',\n\t\t\t'.font-size', '.font-family', '.font-weight', '.font-style', '.text-decoration', '.background',\n\t\t\t'.width', '.height', '.border-collapse'\n\t\t],\n\t\t'td,th': [\n\t\t\t'id', 'class', 'align', 'valign', 'width', 'height', 'colspan', 'rowspan', 'bgcolor',\n\t\t\t'.text-align', '.color', '.background-color', '.font-size', '.font-family', '.font-weight',\n\t\t\t'.font-style', '.text-decoration', '.vertical-align', '.background', '.border'\n\t\t],\n\t\ta : ['id', 'class', 'href', 'target', 'name'],\n\t\tembed : ['id', 'class', 'src', 'width', 'height', 'type', 'loop', 'autostart', 'quality', '.width', '.height', 'align', 'allowscriptaccess', 'wmode'],\n\t\timg : ['id', 'class', 'src', 'width', 'height', 'border', 'alt', 'title', 'align', '.width', '.height', '.border'],\n\t\t'p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6' : [\n\t\t\t'id', 'class', 'align', '.text-align', '.color', '.background-color', '.font-size', '.font-family', '.background',\n\t\t\t'.font-weight', '.font-style', '.text-decoration', '.vertical-align', '.text-indent', '.margin-left'\n\t\t],\n\t\tpre : ['id', 'class'],\n\t\thr : ['id', 'class', '.page-break-after'],\n\t\t'br,tbody,tr,strong,b,sub,sup,em,i,u,strike,s,del' : ['id', 'class'],\n\t\tiframe : ['id', 'class', 'src', 'frameborder', 'width', 'height', '.width', '.height']\n\t},\n\tlayout : '<div class=\"container\"><div class=\"toolbar\"></div><div class=\"edit\"></div><div class=\"statusbar\"></div></div>'\n};\n\n\nvar _useCapture = false;\n\n\nvar _INPUT_KEY_MAP = _toMap('8,9,13,32,46,48..57,59,61,65..90,106,109..111,188,190..192,219..222');\n\nvar _CURSORMOVE_KEY_MAP = _toMap('33..40');\n\nvar _CHANGE_KEY_MAP = {};\n_each(_INPUT_KEY_MAP, function(key, val) {\n\t_CHANGE_KEY_MAP[key] = val;\n});\n_each(_CURSORMOVE_KEY_MAP, function(key, val) {\n\t_CHANGE_KEY_MAP[key] = val;\n});\n\n\nfunction _bindEvent(el, type, fn) {\n\tif (el.addEventListener){\n\t\tel.addEventListener(type, fn, _useCapture);\n\t} else if (el.attachEvent){\n\t\tel.attachEvent('on' + type, fn);\n\t}\n}\n\nfunction _unbindEvent(el, type, fn) {\n\tif (el.removeEventListener){\n\t\tel.removeEventListener(type, fn, _useCapture);\n\t} else if (el.detachEvent){\n\t\tel.detachEvent('on' + type, fn);\n\t}\n}\nvar _EVENT_PROPS = ('altKey,attrChange,attrName,bubbles,button,cancelable,charCode,clientX,clientY,ctrlKey,currentTarget,' +\n\t'data,detail,eventPhase,fromElement,handler,keyCode,metaKey,newValue,offsetX,offsetY,originalTarget,pageX,' +\n\t'pageY,prevValue,relatedNode,relatedTarget,screenX,screenY,shiftKey,srcElement,target,toElement,view,wheelDelta,which').split(',');\n\n\nfunction KEvent(el, event) {\n\tthis.init(el, event);\n}\n_extend(KEvent, {\n\tinit : function(el, event) {\n\t\tvar self = this, doc = el.ownerDocument || el.document || el;\n\t\tself.event = event;\n\t\t_each(_EVENT_PROPS, function(key, val) {\n\t\t\tself[val] = event[val];\n\t\t});\n\t\tif (!self.target) {\n\t\t\tself.target = self.srcElement || doc;\n\t\t}\n\t\tif (self.target.nodeType === 3) {\n\t\t\tself.target = self.target.parentNode;\n\t\t}\n\t\tif (!self.relatedTarget && self.fromElement) {\n\t\t\tself.relatedTarget = self.fromElement === self.target ? self.toElement : self.fromElement;\n\t\t}\n\t\tif (self.pageX == null && self.clientX != null) {\n\t\t\tvar d = doc.documentElement, body = doc.body;\n\t\t\tself.pageX = self.clientX + (d && d.scrollLeft || body && body.scrollLeft || 0) - (d && d.clientLeft || body && body.clientLeft || 0);\n\t\t\tself.pageY = self.clientY + (d && d.scrollTop  || body && body.scrollTop  || 0) - (d && d.clientTop  || body && body.clientTop  || 0);\n\t\t}\n\t\tif (!self.which && ((self.charCode || self.charCode === 0) ? self.charCode : self.keyCode)) {\n\t\t\tself.which = self.charCode || self.keyCode;\n\t\t}\n\t\tif (!self.metaKey && self.ctrlKey) {\n\t\t\tself.metaKey = self.ctrlKey;\n\t\t}\n\t\tif (!self.which && self.button !== undefined) {\n\t\t\tself.which = (self.button & 1 ? 1 : (self.button & 2 ? 3 : (self.button & 4 ? 2 : 0)));\n\t\t}\n\t\tswitch (self.which) {\n\t\tcase 186 :\n\t\t\tself.which = 59;\n\t\t\tbreak;\n\t\tcase 187 :\n\t\tcase 107 :\n\t\tcase 43 :\n\t\t\tself.which = 61;\n\t\t\tbreak;\n\t\tcase 189 :\n\t\tcase 45 :\n\t\t\tself.which = 109;\n\t\t\tbreak;\n\t\tcase 42 :\n\t\t\tself.which = 106;\n\t\t\tbreak;\n\t\tcase 47 :\n\t\t\tself.which = 111;\n\t\t\tbreak;\n\t\tcase 78 :\n\t\t\tself.which = 110;\n\t\t\tbreak;\n\t\t}\n\t\tif (self.which >= 96 && self.which <= 105) {\n\t\t\tself.which -= 48;\n\t\t}\n\t},\n\tpreventDefault : function() {\n\t\tvar ev = this.event;\n\t\tif (ev.preventDefault) {\n\t\t\tev.preventDefault();\n\t\t} else {\n\t\t\tev.returnValue = false;\n\t\t}\n\t},\n\tstopPropagation : function() {\n\t\tvar ev = this.event;\n\t\tif (ev.stopPropagation) {\n\t\t\tev.stopPropagation();\n\t\t} else {\n\t\t\tev.cancelBubble = true;\n\t\t}\n\t},\n\tstop : function() {\n\t\tthis.preventDefault();\n\t\tthis.stopPropagation();\n\t}\n});\nvar _eventExpendo = 'kindeditor_' + _TIME, _eventId = 0, _eventData = {};\nfunction _getId(el) {\n\treturn el[_eventExpendo] || null;\n}\nfunction _setId(el) {\n\tel[_eventExpendo] = ++_eventId;\n\treturn _eventId;\n}\nfunction _removeId(el) {\n\ttry {\n\t\tdelete el[_eventExpendo];\n\t} catch(e) {\n\t\tif (el.removeAttribute) {\n\t\t\tel.removeAttribute(_eventExpendo);\n\t\t}\n\t}\n}\nfunction _bind(el, type, fn) {\n\tif (type.indexOf(',') >= 0) {\n\t\t_each(type.split(','), function() {\n\t\t\t_bind(el, this, fn);\n\t\t});\n\t\treturn;\n\t}\n\tvar id = _getId(el);\n\tif (!id) {\n\t\tid = _setId(el);\n\t}\n\tif (_eventData[id] === undefined) {\n\t\t_eventData[id] = {};\n\t}\n\tvar events = _eventData[id][type];\n\tif (events && events.length > 0) {\n\t\t_unbindEvent(el, type, events[0]);\n\t} else {\n\t\t_eventData[id][type] = [];\n\t\t_eventData[id].el = el;\n\t}\n\tevents = _eventData[id][type];\n\tif (events.length === 0) {\n\t\tevents[0] = function(e) {\n\t\t\tvar kevent = e ? new KEvent(el, e) : undefined;\n\t\t\t_each(events, function(i, event) {\n\t\t\t\tif (i > 0 && event) {\n\t\t\t\t\tevent.call(el, kevent);\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\t}\n\tif (_inArray(fn, events) < 0) {\n\t\tevents.push(fn);\n\t}\n\t_bindEvent(el, type, events[0]);\n}\nfunction _unbind(el, type, fn) {\n\tif (type && type.indexOf(',') >= 0) {\n\t\t_each(type.split(','), function() {\n\t\t\t_unbind(el, this, fn);\n\t\t});\n\t\treturn;\n\t}\n\tvar id = _getId(el);\n\tif (!id) {\n\t\treturn;\n\t}\n\tif (type === undefined) {\n\t\tif (id in _eventData) {\n\t\t\t_each(_eventData[id], function(key, events) {\n\t\t\t\tif (key != 'el' && events.length > 0) {\n\t\t\t\t\t_unbindEvent(el, key, events[0]);\n\t\t\t\t}\n\t\t\t});\n\t\t\tdelete _eventData[id];\n\t\t\t_removeId(el);\n\t\t}\n\t\treturn;\n\t}\n\tif (!_eventData[id]) {\n\t\treturn;\n\t}\n\tvar events = _eventData[id][type];\n\tif (events && events.length > 0) {\n\t\tif (fn === undefined) {\n\t\t\t_unbindEvent(el, type, events[0]);\n\t\t\tdelete _eventData[id][type];\n\t\t} else {\n\t\t\t_each(events, function(i, event) {\n\t\t\t\tif (i > 0 && event === fn) {\n\t\t\t\t\tevents.splice(i, 1);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (events.length == 1) {\n\t\t\t\t_unbindEvent(el, type, events[0]);\n\t\t\t\tdelete _eventData[id][type];\n\t\t\t}\n\t\t}\n\t\tvar count = 0;\n\t\t_each(_eventData[id], function() {\n\t\t\tcount++;\n\t\t});\n\t\tif (count < 2) {\n\t\t\tdelete _eventData[id];\n\t\t\t_removeId(el);\n\t\t}\n\t}\n}\nfunction _fire(el, type) {\n\tif (type.indexOf(',') >= 0) {\n\t\t_each(type.split(','), function() {\n\t\t\t_fire(el, this);\n\t\t});\n\t\treturn;\n\t}\n\tvar id = _getId(el);\n\tif (!id) {\n\t\treturn;\n\t}\n\tvar events = _eventData[id][type];\n\tif (_eventData[id] && events && events.length > 0) {\n\t\tevents[0]();\n\t}\n}\nfunction _ctrl(el, key, fn) {\n\tvar self = this;\n\tkey = /^\\d{2,}$/.test(key) ? key : key.toUpperCase().charCodeAt(0);\n\t_bind(el, 'keydown', function(e) {\n\t\tif (e.ctrlKey && e.which == key && !e.shiftKey && !e.altKey) {\n\t\t\tfn.call(el);\n\t\t\te.stop();\n\t\t}\n\t});\n}\nvar _readyFinished = false;\nfunction _ready(fn) {\n\tif (_readyFinished) {\n\t\tfn(KindEditor);\n\t\treturn;\n\t}\n\tvar loaded = false;\n\tfunction readyFunc() {\n\t\tif (!loaded) {\n\t\t\tloaded = true;\n\t\t\tfn(KindEditor);\n\t\t\t_readyFinished = true;\n\t\t}\n\t}\n\tfunction ieReadyFunc() {\n\t\tif (!loaded) {\n\t\t\ttry {\n\t\t\t\tdocument.documentElement.doScroll('left');\n\t\t\t} catch(e) {\n\t\t\t\tsetTimeout(ieReadyFunc, 100);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\treadyFunc();\n\t\t}\n\t}\n\tfunction ieReadyStateFunc() {\n\t\tif (document.readyState === 'complete') {\n\t\t\treadyFunc();\n\t\t}\n\t}\n\tif (document.addEventListener) {\n\t\t_bind(document, 'DOMContentLoaded', readyFunc);\n\t} else if (document.attachEvent) {\n\t\t_bind(document, 'readystatechange', ieReadyStateFunc);\n\t\tvar toplevel = false;\n\t\ttry {\n\t\t\ttoplevel = window.frameElement == null;\n\t\t} catch(e) {}\n\t\tif (document.documentElement.doScroll && toplevel) {\n\t\t\tieReadyFunc();\n\t\t}\n\t}\n\t_bind(window, 'load', readyFunc);\n}\nif (window.attachEvent) {\n\twindow.attachEvent('onunload', function() {\n\t\t_each(_eventData, function(key, events) {\n\t\t\tif (events.el) {\n\t\t\t\t_unbind(events.el);\n\t\t\t}\n\t\t});\n\t});\n}\nK.ctrl = _ctrl;\nK.ready = _ready;\n\nfunction _getCssList(css) {\n\tcss = css.replace(/&quot;/g, '\"');\n\tvar list = {},\n\t\treg = /\\s*([\\w\\-]+)\\s*:([^;]*)(;|$)/g,\n\t\tmatch;\n\twhile ((match = reg.exec(css))) {\n\t\tvar key = _trim(match[1].toLowerCase()),\n\t\t\tval = _trim(_toHex(match[2]));\n\t\tlist[key] = val;\n\t}\n\treturn list;\n}\nfunction _getAttrList(tag) {\n\tvar list = {},\n\t\treg = /\\s+(?:([\\w\\-:]+)|(?:([\\w\\-:]+)=([^\\s\"'<>]+))|(?:([\\w\\-:\"]+)=\"([^\"]*)\")|(?:([\\w\\-:\"]+)='([^']*)'))(?=(?:\\s|\\/|>)+)/g,\n\t\tmatch;\n\twhile ((match = reg.exec(tag))) {\n\t\tvar key = (match[1] || match[2] || match[4] || match[6]).toLowerCase(),\n\t\t\tval = (match[2] ? match[3] : (match[4] ? match[5] : match[7])) || '';\n\t\tlist[key] = val;\n\t}\n\treturn list;\n}\nfunction _addClassToTag(tag, className) {\n\tif (/\\s+class\\s*=/.test(tag)) {\n\t\ttag = tag.replace(/(\\s+class=[\"']?)([^\"']*)([\"']?[\\s>])/, function($0, $1, $2, $3) {\n\t\t\tif ((' ' + $2 + ' ').indexOf(' ' + className + ' ') < 0) {\n\t\t\t\treturn $2 === '' ? $1 + className + $3 : $1 + $2 + ' ' + className + $3;\n\t\t\t} else {\n\t\t\t\treturn $0;\n\t\t\t}\n\t\t});\n\t} else {\n\t\ttag = tag.substr(0, tag.length - 1) + ' class=\"' + className + '\">';\n\t}\n\treturn tag;\n}\nfunction _formatCss(css) {\n\tvar str = '';\n\t_each(_getCssList(css), function(key, val) {\n\t\tstr += key + ':' + val + ';';\n\t});\n\treturn str;\n}\nfunction _formatUrl(url, mode, host, pathname) {\n\tmode = _undef(mode, '').toLowerCase();\n\tif (url.substr(0, 5) != 'data:') {\n\t\turl = url.replace(/([^:])\\/\\//g, '$1/');\n\t}\n\tif (_inArray(mode, ['absolute', 'relative', 'domain']) < 0) {\n\t\treturn url;\n\t}\n\thost = host || location.protocol + '//' + location.host;\n\tif (pathname === undefined) {\n\t\tvar m = location.pathname.match(/^(\\/.*)\\//);\n\t\tpathname = m ? m[1] : '';\n\t}\n\tvar match;\n\tif ((match = /^(\\w+:\\/\\/[^\\/]*)/.exec(url))) {\n\t\tif (match[1] !== host) {\n\t\t\treturn url;\n\t\t}\n\t} else if (/^\\w+:/.test(url)) {\n\t\treturn url;\n\t}\n\tfunction getRealPath(path) {\n\t\tvar parts = path.split('/'), paths = [];\n\t\tfor (var i = 0, len = parts.length; i < len; i++) {\n\t\t\tvar part = parts[i];\n\t\t\tif (part == '..') {\n\t\t\t\tif (paths.length > 0) {\n\t\t\t\t\tpaths.pop();\n\t\t\t\t}\n\t\t\t} else if (part !== '' && part != '.') {\n\t\t\t\tpaths.push(part);\n\t\t\t}\n\t\t}\n\t\treturn '/' + paths.join('/');\n\t}\n\tif (/^\\//.test(url)) {\n\t\turl = host + getRealPath(url.substr(1));\n\t} else if (!/^\\w+:\\/\\//.test(url)) {\n\t\turl = host + getRealPath(pathname + '/' + url);\n\t}\n\tfunction getRelativePath(path, depth) {\n\t\tif (url.substr(0, path.length) === path) {\n\t\t\tvar arr = [];\n\t\t\tfor (var i = 0; i < depth; i++) {\n\t\t\t\tarr.push('..');\n\t\t\t}\n\t\t\tvar prefix = '.';\n\t\t\tif (arr.length > 0) {\n\t\t\t\tprefix += '/' + arr.join('/');\n\t\t\t}\n\t\t\tif (pathname == '/') {\n\t\t\t\tprefix += '/';\n\t\t\t}\n\t\t\treturn prefix + url.substr(path.length);\n\t\t} else {\n\t\t\tif ((match = /^(.*)\\//.exec(path))) {\n\t\t\t\treturn getRelativePath(match[1], ++depth);\n\t\t\t}\n\t\t}\n\t}\n\tif (mode === 'relative') {\n\t\turl = getRelativePath(host + pathname, 0).substr(2);\n\t} else if (mode === 'absolute') {\n\t\tif (url.substr(0, host.length) === host) {\n\t\t\turl = url.substr(host.length);\n\t\t}\n\t}\n\treturn url;\n}\nfunction _formatHtml(html, htmlTags, urlType, wellFormatted, indentChar) {\n\tif (html == null) {\n\t\thtml = '';\n\t}\n\turlType = urlType || '';\n\twellFormatted = _undef(wellFormatted, false);\n\tindentChar = _undef(indentChar, '\\t');\n\tvar fontSizeList = 'xx-small,x-small,small,medium,large,x-large,xx-large'.split(',');\n\thtml = html.replace(/(<(?:pre|pre\\s[^>]*)>)([\\s\\S]*?)(<\\/pre>)/ig, function($0, $1, $2, $3) {\n\t\treturn $1 + $2.replace(/<(?:br|br\\s[^>]*)>/ig, '\\n') + $3;\n\t});\n\thtml = html.replace(/<(?:br|br\\s[^>]*)\\s*\\/?>\\s*<\\/p>/ig, '</p>');\n\thtml = html.replace(/(<(?:p|p\\s[^>]*)>)\\s*(<\\/p>)/ig, '$1<br />$2');\n\thtml = html.replace(/\\u200B/g, '');\n\thtml = html.replace(/\\u00A9/g, '&copy;');\n\thtml = html.replace(/\\u00AE/g, '&reg;');\n\thtml = html.replace(/\\u2003/g, '&emsp;');\n\thtml = html.replace(/\\u3000/g, '&emsp;');\n\thtml = html.replace(/<[^>]+/g, function($0) {\n\t\treturn $0.replace(/\\s+/g, ' ');\n\t});\n\tvar htmlTagMap = {};\n\tif (htmlTags) {\n\t\t_each(htmlTags, function(key, val) {\n\t\t\tvar arr = key.split(',');\n\t\t\tfor (var i = 0, len = arr.length; i < len; i++) {\n\t\t\t\thtmlTagMap[arr[i]] = _toMap(val);\n\t\t\t}\n\t\t});\n\t\tif (!htmlTagMap.script) {\n\t\t\thtml = html.replace(/(<(?:script|script\\s[^>]*)>)([\\s\\S]*?)(<\\/script>)/ig, '');\n\t\t}\n\t\tif (!htmlTagMap.style) {\n\t\t\thtml = html.replace(/(<(?:style|style\\s[^>]*)>)([\\s\\S]*?)(<\\/style>)/ig, '');\n\t\t}\n\t}\n\tvar re = /(\\s*)<(\\/)?([\\w\\-:]+)((?:\\s+|(?:\\s+[\\w\\-:]+)|(?:\\s+[\\w\\-:]+=[^\\s\"'<>]+)|(?:\\s+[\\w\\-:\"]+=\"[^\"]*\")|(?:\\s+[\\w\\-:\"]+='[^']*'))*)(\\/)?>(\\s*)/g;\n\tvar tagStack = [];\n\thtml = html.replace(re, function($0, $1, $2, $3, $4, $5, $6) {\n\t\tvar full = $0,\n\t\t\tstartNewline = $1 || '',\n\t\t\tstartSlash = $2 || '',\n\t\t\ttagName = $3.toLowerCase(),\n\t\t\tattr = $4 || '',\n\t\t\tendSlash = $5 ? ' ' + $5 : '',\n\t\t\tendNewline = $6 || '';\n\t\tif (htmlTags && !htmlTagMap[tagName]) {\n\t\t\treturn '';\n\t\t}\n\t\tif (endSlash === '' && _SINGLE_TAG_MAP[tagName]) {\n\t\t\tendSlash = ' /';\n\t\t}\n\t\tif (_INLINE_TAG_MAP[tagName]) {\n\t\t\tif (startNewline) {\n\t\t\t\tstartNewline = ' ';\n\t\t\t}\n\t\t\tif (endNewline) {\n\t\t\t\tendNewline = ' ';\n\t\t\t}\n\t\t}\n\t\tif (_PRE_TAG_MAP[tagName]) {\n\t\t\tif (startSlash) {\n\t\t\t\tendNewline = '\\n';\n\t\t\t} else {\n\t\t\t\tstartNewline = '\\n';\n\t\t\t}\n\t\t}\n\t\tif (wellFormatted && tagName == 'br') {\n\t\t\tendNewline = '\\n';\n\t\t}\n\t\tif (_BLOCK_TAG_MAP[tagName] && !_PRE_TAG_MAP[tagName]) {\n\t\t\tif (wellFormatted) {\n\t\t\t\tif (startSlash && tagStack.length > 0 && tagStack[tagStack.length - 1] === tagName) {\n\t\t\t\t\ttagStack.pop();\n\t\t\t\t} else {\n\t\t\t\t\ttagStack.push(tagName);\n\t\t\t\t}\n\t\t\t\tstartNewline = '\\n';\n\t\t\t\tendNewline = '\\n';\n\t\t\t\tfor (var i = 0, len = startSlash ? tagStack.length : tagStack.length - 1; i < len; i++) {\n\t\t\t\t\tstartNewline += indentChar;\n\t\t\t\t\tif (!startSlash) {\n\t\t\t\t\t\tendNewline += indentChar;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (endSlash) {\n\t\t\t\t\ttagStack.pop();\n\t\t\t\t} else if (!startSlash) {\n\t\t\t\t\tendNewline += indentChar;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tstartNewline = endNewline = '';\n\t\t\t}\n\t\t}\n\t\tif (attr !== '') {\n\t\t\tvar attrMap = _getAttrList(full);\n\t\t\tif (tagName === 'font') {\n\t\t\t\tvar fontStyleMap = {}, fontStyle = '';\n\t\t\t\t_each(attrMap, function(key, val) {\n\t\t\t\t\tif (key === 'color') {\n\t\t\t\t\t\tfontStyleMap.color = val;\n\t\t\t\t\t\tdelete attrMap[key];\n\t\t\t\t\t}\n\t\t\t\t\tif (key === 'size') {\n\t\t\t\t\t\tfontStyleMap['font-size'] = fontSizeList[parseInt(val, 10) - 1] || '';\n\t\t\t\t\t\tdelete attrMap[key];\n\t\t\t\t\t}\n\t\t\t\t\tif (key === 'face') {\n\t\t\t\t\t\tfontStyleMap['font-family'] = val;\n\t\t\t\t\t\tdelete attrMap[key];\n\t\t\t\t\t}\n\t\t\t\t\tif (key === 'style') {\n\t\t\t\t\t\tfontStyle = val;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (fontStyle && !/;$/.test(fontStyle)) {\n\t\t\t\t\tfontStyle += ';';\n\t\t\t\t}\n\t\t\t\t_each(fontStyleMap, function(key, val) {\n\t\t\t\t\tif (val === '') {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (/\\s/.test(val)) {\n\t\t\t\t\t\tval = \"'\" + val + \"'\";\n\t\t\t\t\t}\n\t\t\t\t\tfontStyle += key + ':' + val + ';';\n\t\t\t\t});\n\t\t\t\tattrMap.style = fontStyle;\n\t\t\t}\n\t\t\t_each(attrMap, function(key, val) {\n\t\t\t\tif (_FILL_ATTR_MAP[key]) {\n\t\t\t\t\tattrMap[key] = key;\n\t\t\t\t}\n\t\t\t\tif (_inArray(key, ['src', 'href']) >= 0) {\n\t\t\t\t\tattrMap[key] = _formatUrl(val, urlType);\n\t\t\t\t}\n\t\t\t\tif (htmlTags && key !== 'style' && !htmlTagMap[tagName]['*'] && !htmlTagMap[tagName][key] ||\n\t\t\t\t\ttagName === 'body' && key === 'contenteditable' ||\n\t\t\t\t\t/^kindeditor_\\d+$/.test(key)) {\n\t\t\t\t\tdelete attrMap[key];\n\t\t\t\t}\n\t\t\t\tif (key === 'style' && val !== '') {\n\t\t\t\t\tvar styleMap = _getCssList(val);\n\t\t\t\t\t_each(styleMap, function(k, v) {\n\t\t\t\t\t\tif (htmlTags && !htmlTagMap[tagName].style && !htmlTagMap[tagName]['.' + k]) {\n\t\t\t\t\t\t\tdelete styleMap[k];\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tvar style = '';\n\t\t\t\t\t_each(styleMap, function(k, v) {\n\t\t\t\t\t\tstyle += k + ':' + v + ';';\n\t\t\t\t\t});\n\t\t\t\t\tattrMap.style = style;\n\t\t\t\t}\n\t\t\t});\n\t\t\tattr = '';\n\t\t\t_each(attrMap, function(key, val) {\n\t\t\t\tif (key === 'style' && val === '') {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tval = val.replace(/\"/g, '&quot;');\n\t\t\t\tattr += ' ' + key + '=\"' + val + '\"';\n\t\t\t});\n\t\t}\n\t\tif (tagName === 'font') {\n\t\t\ttagName = 'span';\n\t\t}\n\t\treturn startNewline + '<' + startSlash + tagName + attr + endSlash + '>' + endNewline;\n\t});\n\thtml = html.replace(/(<(?:pre|pre\\s[^>]*)>)([\\s\\S]*?)(<\\/pre>)/ig, function($0, $1, $2, $3) {\n\t\treturn $1 + $2.replace(/\\n/g, '<span id=\"__kindeditor_pre_newline__\">\\n') + $3;\n\t});\n\thtml = html.replace(/\\n\\s*\\n/g, '\\n');\n\thtml = html.replace(/<span id=\"__kindeditor_pre_newline__\">\\n/g, '\\n');\n\treturn _trim(html);\n}\n\nfunction _clearMsWord(html, htmlTags) {\n\thtml = html.replace(/<meta[\\s\\S]*?>/ig, '')\n\t\t.replace(/<![\\s\\S]*?>/ig, '')\n\t\t.replace(/<style[^>]*>[\\s\\S]*?<\\/style>/ig, '')\n\t\t.replace(/<script[^>]*>[\\s\\S]*?<\\/script>/ig, '')\n\t\t.replace(/<w:[^>]+>[\\s\\S]*?<\\/w:[^>]+>/ig, '')\n\t\t.replace(/<o:[^>]+>[\\s\\S]*?<\\/o:[^>]+>/ig, '')\n\t\t.replace(/<xml>[\\s\\S]*?<\\/xml>/ig, '')\n\t\t.replace(/<(?:table|td)[^>]*>/ig, function(full) {\n\t\t\treturn full.replace(/border-bottom:([#\\w\\s]+)/ig, 'border:$1');\n\t\t});\n\treturn _formatHtml(html, htmlTags);\n}\n\nfunction _mediaType(src) {\n\tif (/\\.(rm|rmvb)(\\?|$)/i.test(src)) {\n\t\treturn 'audio/x-pn-realaudio-plugin';\n\t}\n\tif (/\\.(swf|flv)(\\?|$)/i.test(src)) {\n\t\treturn 'application/x-shockwave-flash';\n\t}\n\treturn 'video/x-ms-asf-plugin';\n}\n\nfunction _mediaClass(type) {\n\tif (/realaudio/i.test(type)) {\n\t\treturn 'ke-rm';\n\t}\n\tif (/flash/i.test(type)) {\n\t\treturn 'ke-flash';\n\t}\n\treturn 'ke-media';\n}\nfunction _mediaAttrs(srcTag) {\n\treturn _getAttrList(unescape(srcTag));\n}\nfunction _mediaEmbed(attrs) {\n\tvar html = '<embed ';\n\t_each(attrs, function(key, val) {\n\t\thtml += key + '=\"' + val + '\" ';\n\t});\n\thtml += '/>';\n\treturn html;\n}\nfunction _mediaImg(blankPath, attrs) {\n\tvar width = attrs.width,\n\t\theight = attrs.height,\n\t\ttype = attrs.type || _mediaType(attrs.src),\n\t\tsrcTag = _mediaEmbed(attrs),\n\t\tstyle = '';\n\tif (/\\D/.test(width)) {\n\t\tstyle += 'width:' + width + ';';\n\t} else if (width > 0) {\n\t\tstyle += 'width:' + width + 'px;';\n\t}\n\tif (/\\D/.test(height)) {\n\t\tstyle += 'height:' + height + ';';\n\t} else if (height > 0) {\n\t\tstyle += 'height:' + height + 'px;';\n\t}\n\tvar html = '<img class=\"' + _mediaClass(type) + '\" src=\"' + blankPath + '\" ';\n\tif (style !== '') {\n\t\thtml += 'style=\"' + style + '\" ';\n\t}\n\thtml += 'data-ke-tag=\"' + escape(srcTag) + '\" alt=\"\" />';\n\treturn html;\n}\n\n\n\n\nfunction _tmpl(str, data) {\n\tvar fn = new Function(\"obj\",\n\t\t\"var p=[],print=function(){p.push.apply(p,arguments);};\" +\n\t\t\"with(obj){p.push('\" +\n\t\tstr.replace(/[\\r\\t\\n]/g, \" \")\n\t\t\t.split(\"<%\").join(\"\\t\")\n\t\t\t.replace(/((^|%>)[^\\t]*)'/g, \"$1\\r\")\n\t\t\t.replace(/\\t=(.*?)%>/g, \"',$1,'\")\n\t\t\t.split(\"\\t\").join(\"');\")\n\t\t\t.split(\"%>\").join(\"p.push('\")\n\t\t\t.split(\"\\r\").join(\"\\\\'\") + \"');}return p.join('');\");\n\treturn data ? fn(data) : fn;\n}\nK.formatUrl = _formatUrl;\nK.formatHtml = _formatHtml;\nK.getCssList = _getCssList;\nK.getAttrList = _getAttrList;\nK.mediaType = _mediaType;\nK.mediaAttrs = _mediaAttrs;\nK.mediaEmbed = _mediaEmbed;\nK.mediaImg = _mediaImg;\nK.clearMsWord = _clearMsWord;\nK.tmpl = _tmpl;\n\n\nfunction _contains(nodeA, nodeB) {\n\tif (nodeA.nodeType == 9 && nodeB.nodeType != 9) {\n\t\treturn true;\n\t}\n\twhile ((nodeB = nodeB.parentNode)) {\n\t\tif (nodeB == nodeA) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\nvar _getSetAttrDiv = document.createElement('div');\n_getSetAttrDiv.setAttribute('className', 't');\nvar _GET_SET_ATTRIBUTE = _getSetAttrDiv.className !== 't';\nfunction _getAttr(el, key) {\n\tkey = key.toLowerCase();\n\tvar val = null;\n\tif (!_GET_SET_ATTRIBUTE && el.nodeName.toLowerCase() != 'script') {\n\t\tvar div = el.ownerDocument.createElement('div');\n\t\tdiv.appendChild(el.cloneNode(false));\n\t\tvar list = _getAttrList(_unescape(div.innerHTML));\n\t\tif (key in list) {\n\t\t\tval = list[key];\n\t\t}\n\t} else {\n\t\ttry {\n\t\t\tval = el.getAttribute(key, 2);\n\t\t} catch(e) {\n\t\t\tval = el.getAttribute(key, 1);\n\t\t}\n\t}\n\tif (key === 'style' && val !== null) {\n\t\tval = _formatCss(val);\n\t}\n\treturn val;\n}\nfunction _queryAll(expr, root) {\n\tvar exprList = expr.split(',');\n\tif (exprList.length > 1) {\n\t\tvar mergedResults = [];\n\t\t_each(exprList, function() {\n\t\t\t_each(_queryAll(this, root), function() {\n\t\t\t\tif (_inArray(this, mergedResults) < 0) {\n\t\t\t\t\tmergedResults.push(this);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\treturn mergedResults;\n\t}\n\troot = root || document;\n\tfunction escape(str) {\n\t\tif (typeof str != 'string') {\n\t\t\treturn str;\n\t\t}\n\t\treturn str.replace(/([^\\w\\-])/g, '\\\\$1');\n\t}\n\tfunction stripslashes(str) {\n\t\treturn str.replace(/\\\\/g, '');\n\t}\n\tfunction cmpTag(tagA, tagB) {\n\t\treturn tagA === '*' || tagA.toLowerCase() === escape(tagB.toLowerCase());\n\t}\n\tfunction byId(id, tag, root) {\n\t\tvar arr = [],\n\t\t\tdoc = root.ownerDocument || root,\n\t\t\tel = doc.getElementById(stripslashes(id));\n\t\tif (el) {\n\t\t\tif (cmpTag(tag, el.nodeName) && _contains(root, el)) {\n\t\t\t\tarr.push(el);\n\t\t\t}\n\t\t}\n\t\treturn arr;\n\t}\n\tfunction byClass(className, tag, root) {\n\t\tvar doc = root.ownerDocument || root, arr = [], els, i, len, el;\n\t\tif (root.getElementsByClassName) {\n\t\t\tels = root.getElementsByClassName(stripslashes(className));\n\t\t\tfor (i = 0, len = els.length; i < len; i++) {\n\t\t\t\tel = els[i];\n\t\t\t\tif (cmpTag(tag, el.nodeName)) {\n\t\t\t\t\tarr.push(el);\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (doc.querySelectorAll) {\n\t\t\tels = doc.querySelectorAll((root.nodeName !== '#document' ? root.nodeName + ' ' : '') + tag + '.' + className);\n\t\t\tfor (i = 0, len = els.length; i < len; i++) {\n\t\t\t\tel = els[i];\n\t\t\t\tif (_contains(root, el)) {\n\t\t\t\t\tarr.push(el);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tels = root.getElementsByTagName(tag);\n\t\t\tclassName = ' ' + className + ' ';\n\t\t\tfor (i = 0, len = els.length; i < len; i++) {\n\t\t\t\tel = els[i];\n\t\t\t\tif (el.nodeType == 1) {\n\t\t\t\t\tvar cls = el.className;\n\t\t\t\t\tif (cls && (' ' + cls + ' ').indexOf(className) > -1) {\n\t\t\t\t\t\tarr.push(el);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn arr;\n\t}\n\tfunction byName(name, tag, root) {\n\t\tvar arr = [], doc = root.ownerDocument || root,\n\t\t\tels = doc.getElementsByName(stripslashes(name)), el;\n\t\tfor (var i = 0, len = els.length; i < len; i++) {\n\t\t\tel = els[i];\n\t\t\tif (cmpTag(tag, el.nodeName) && _contains(root, el)) {\n\t\t\t\tif (el.getAttribute('name') !== null) {\n\t\t\t\t\tarr.push(el);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn arr;\n\t}\n\tfunction byAttr(key, val, tag, root) {\n\t\tvar arr = [], els = root.getElementsByTagName(tag), el;\n\t\tfor (var i = 0, len = els.length; i < len; i++) {\n\t\t\tel = els[i];\n\t\t\tif (el.nodeType == 1) {\n\t\t\t\tif (val === null) {\n\t\t\t\t\tif (_getAttr(el, key) !== null) {\n\t\t\t\t\t\tarr.push(el);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (val === escape(_getAttr(el, key))) {\n\t\t\t\t\t\tarr.push(el);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn arr;\n\t}\n\tfunction select(expr, root) {\n\t\tvar arr = [], matches;\n\t\tmatches = /^((?:\\\\.|[^.#\\s\\[<>])+)/.exec(expr);\n\t\tvar tag = matches ? matches[1] : '*';\n\t\tif ((matches = /#((?:[\\w\\-]|\\\\.)+)$/.exec(expr))) {\n\t\t\tarr = byId(matches[1], tag, root);\n\t\t} else if ((matches = /\\.((?:[\\w\\-]|\\\\.)+)$/.exec(expr))) {\n\t\t\tarr = byClass(matches[1], tag, root);\n\t\t} else if ((matches = /\\[((?:[\\w\\-]|\\\\.)+)\\]/.exec(expr))) {\n\t\t\tarr = byAttr(matches[1].toLowerCase(), null, tag, root);\n\t\t} else if ((matches = /\\[((?:[\\w\\-]|\\\\.)+)\\s*=\\s*['\"]?((?:\\\\.|[^'\"]+)+)['\"]?\\]/.exec(expr))) {\n\t\t\tvar key = matches[1].toLowerCase(), val = matches[2];\n\t\t\tif (key === 'id') {\n\t\t\t\tarr = byId(val, tag, root);\n\t\t\t} else if (key === 'class') {\n\t\t\t\tarr = byClass(val, tag, root);\n\t\t\t} else if (key === 'name') {\n\t\t\t\tarr = byName(val, tag, root);\n\t\t\t} else {\n\t\t\t\tarr = byAttr(key, val, tag, root);\n\t\t\t}\n\t\t} else {\n\t\t\tvar els = root.getElementsByTagName(tag), el;\n\t\t\tfor (var i = 0, len = els.length; i < len; i++) {\n\t\t\t\tel = els[i];\n\t\t\t\tif (el.nodeType == 1) {\n\t\t\t\t\tarr.push(el);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn arr;\n\t}\n\tvar parts = [], arr, re = /((?:\\\\.|[^\\s>])+|[\\s>])/g;\n\twhile ((arr = re.exec(expr))) {\n\t\tif (arr[1] !== ' ') {\n\t\t\tparts.push(arr[1]);\n\t\t}\n\t}\n\tvar results = [];\n\tif (parts.length == 1) {\n\t\treturn select(parts[0], root);\n\t}\n\tvar isChild = false, part, els, subResults, val, v, i, j, k, length, len, l;\n\tfor (i = 0, lenth = parts.length; i < lenth; i++) {\n\t\tpart = parts[i];\n\t\tif (part === '>') {\n\t\t\tisChild = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (i > 0) {\n\t\t\tels = [];\n\t\t\tfor (j = 0, len = results.length; j < len; j++) {\n\t\t\t\tval = results[j];\n\t\t\t\tsubResults = select(part, val);\n\t\t\t\tfor (k = 0, l = subResults.length; k < l; k++) {\n\t\t\t\t\tv = subResults[k];\n\t\t\t\t\tif (isChild) {\n\t\t\t\t\t\tif (val === v.parentNode) {\n\t\t\t\t\t\t\tels.push(v);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tels.push(v);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tresults = els;\n\t\t} else {\n\t\t\tresults = select(part, root);\n\t\t}\n\t\tif (results.length === 0) {\n\t\t\treturn [];\n\t\t}\n\t}\n\treturn results;\n}\nfunction _query(expr, root) {\n\tvar arr = _queryAll(expr, root);\n\treturn arr.length > 0 ? arr[0] : null;\n}\nK.query = _query;\nK.queryAll = _queryAll;\n\n\nfunction _get(val) {\n\treturn K(val)[0];\n}\nfunction _getDoc(node) {\n\tif (!node) {\n\t\treturn document;\n\t}\n\treturn node.ownerDocument || node.document || node;\n}\nfunction _getWin(node) {\n\tif (!node) {\n\t\treturn window;\n\t}\n\tvar doc = _getDoc(node);\n\treturn doc.parentWindow || doc.defaultView;\n}\nfunction _setHtml(el, html) {\n\tif (el.nodeType != 1) {\n\t\treturn;\n\t}\n\tvar doc = _getDoc(el);\n\ttry {\n\t\tel.innerHTML = '<img id=\"__kindeditor_temp_tag__\" width=\"0\" height=\"0\" style=\"display:none;\" />' + html;\n\t\tvar temp = doc.getElementById('__kindeditor_temp_tag__');\n\t\ttemp.parentNode.removeChild(temp);\n\t} catch(e) {\n\t\tK(el).empty();\n\t\tK('@' + html, doc).each(function() {\n\t\t\tel.appendChild(this);\n\t\t});\n\t}\n}\nfunction _hasClass(el, cls) {\n\treturn _inString(cls, el.className, ' ');\n}\nfunction _setAttr(el, key, val) {\n\tif (_IE && _V < 8 && key.toLowerCase() == 'class') {\n\t\tkey = 'className';\n\t}\n\tel.setAttribute(key, '' + val);\n}\nfunction _removeAttr(el, key) {\n\tif (_IE && _V < 8 && key.toLowerCase() == 'class') {\n\t\tkey = 'className';\n\t}\n\t_setAttr(el, key, '');\n\tel.removeAttribute(key);\n}\nfunction _getNodeName(node) {\n\tif (!node || !node.nodeName) {\n\t\treturn '';\n\t}\n\treturn node.nodeName.toLowerCase();\n}\nfunction _computedCss(el, key) {\n\tvar self = this, win = _getWin(el), camelKey = _toCamel(key), val = '';\n\tif (win.getComputedStyle) {\n\t\tvar style = win.getComputedStyle(el, null);\n\t\tval = style[camelKey] || style.getPropertyValue(key) || el.style[camelKey];\n\t} else if (el.currentStyle) {\n\t\tval = el.currentStyle[camelKey] || el.style[camelKey];\n\t}\n\treturn val;\n}\nfunction _hasVal(node) {\n\treturn !!_VALUE_TAG_MAP[_getNodeName(node)];\n}\nfunction _docElement(doc) {\n\tdoc = doc || document;\n\treturn _QUIRKS ? doc.body : doc.documentElement;\n}\nfunction _docHeight(doc) {\n\tvar el = _docElement(doc);\n\treturn Math.max(el.scrollHeight, el.clientHeight);\n}\nfunction _docWidth(doc) {\n\tvar el = _docElement(doc);\n\treturn Math.max(el.scrollWidth, el.clientWidth);\n}\nfunction _getScrollPos(doc) {\n\tdoc = doc || document;\n\tvar x, y;\n\tif (_IE || _NEWIE || _OPERA) {\n\t\tx = _docElement(doc).scrollLeft;\n\t\ty = _docElement(doc).scrollTop;\n\t} else {\n\t\tx = _getWin(doc).scrollX;\n\t\ty = _getWin(doc).scrollY;\n\t}\n\treturn {x : x, y : y};\n}\n\n\nfunction KNode(node) {\n\tthis.init(node);\n}\n_extend(KNode, {\n\tinit : function(node) {\n\t\tvar self = this;\n\t\tnode = _isArray(node) ? node : [node];\n\t\tvar length = 0;\n\t\tfor (var i = 0, len = node.length; i < len; i++) {\n\t\t\tif (node[i]) {\n\t\t\t\tself[i] = node[i].constructor === KNode ? node[i][0] : node[i];\n\t\t\t\tlength++;\n\t\t\t}\n\t\t}\n\t\tself.length = length;\n\t\tself.doc = _getDoc(self[0]);\n\t\tself.name = _getNodeName(self[0]);\n\t\tself.type = self.length > 0 ? self[0].nodeType : null;\n\t\tself.win = _getWin(self[0]);\n\t},\n\teach : function(fn) {\n\t\tvar self = this;\n\t\tfor (var i = 0; i < self.length; i++) {\n\t\t\tif (fn.call(self[i], i, self[i]) === false) {\n\t\t\t\treturn self;\n\t\t\t}\n\t\t}\n\t\treturn self;\n\t},\n\tbind : function(type, fn) {\n\t\tthis.each(function() {\n\t\t\t_bind(this, type, fn);\n\t\t});\n\t\treturn this;\n\t},\n\tunbind : function(type, fn) {\n\t\tthis.each(function() {\n\t\t\t_unbind(this, type, fn);\n\t\t});\n\t\treturn this;\n\t},\n\tfire : function(type) {\n\t\tif (this.length < 1) {\n\t\t\treturn this;\n\t\t}\n\t\t_fire(this[0], type);\n\t\treturn this;\n\t},\n\thasAttr : function(key) {\n\t\tif (this.length < 1) {\n\t\t\treturn false;\n\t\t}\n\t\treturn !!_getAttr(this[0], key);\n\t},\n\tattr : function(key, val) {\n\t\tvar self = this;\n\t\tif (key === undefined) {\n\t\t\treturn _getAttrList(self.outer());\n\t\t}\n\t\tif (typeof key === 'object') {\n\t\t\t_each(key, function(k, v) {\n\t\t\t\tself.attr(k, v);\n\t\t\t});\n\t\t\treturn self;\n\t\t}\n\t\tif (val === undefined) {\n\t\t\tval = self.length < 1 ? null : _getAttr(self[0], key);\n\t\t\treturn val === null ? '' : val;\n\t\t}\n\t\tself.each(function() {\n\t\t\t_setAttr(this, key, val);\n\t\t});\n\t\treturn self;\n\t},\n\tremoveAttr : function(key) {\n\t\tthis.each(function() {\n\t\t\t_removeAttr(this, key);\n\t\t});\n\t\treturn this;\n\t},\n\tget : function(i) {\n\t\tif (this.length < 1) {\n\t\t\treturn null;\n\t\t}\n\t\treturn this[i || 0];\n\t},\n\teq : function(i) {\n\t\tif (this.length < 1) {\n\t\t\treturn null;\n\t\t}\n\t\treturn this[i] ? new KNode(this[i]) : null;\n\t},\n\thasClass : function(cls) {\n\t\tif (this.length < 1) {\n\t\t\treturn false;\n\t\t}\n\t\treturn _hasClass(this[0], cls);\n\t},\n\taddClass : function(cls) {\n\t\tthis.each(function() {\n\t\t\tif (!_hasClass(this, cls)) {\n\t\t\t\tthis.className = _trim(this.className + ' ' + cls);\n\t\t\t}\n\t\t});\n\t\treturn this;\n\t},\n\tremoveClass : function(cls) {\n\t\tthis.each(function() {\n\t\t\tif (_hasClass(this, cls)) {\n\t\t\t\tthis.className = _trim(this.className.replace(new RegExp('(^|\\\\s)' + cls + '(\\\\s|$)'), ' '));\n\t\t\t}\n\t\t});\n\t\treturn this;\n\t},\n\thtml : function(val) {\n\t\tvar self = this;\n\t\tif (val === undefined) {\n\t\t\tif (self.length < 1 || self.type != 1) {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\treturn _formatHtml(self[0].innerHTML);\n\t\t}\n\t\tself.each(function() {\n\t\t\t_setHtml(this, val);\n\t\t});\n\t\treturn self;\n\t},\n\ttext : function() {\n\t\tvar self = this;\n\t\tif (self.length < 1) {\n\t\t\treturn '';\n\t\t}\n\t\treturn _IE ? self[0].innerText : self[0].textContent;\n\t},\n\thasVal : function() {\n\t\tif (this.length < 1) {\n\t\t\treturn false;\n\t\t}\n\t\treturn _hasVal(this[0]);\n\t},\n\tval : function(val) {\n\t\tvar self = this;\n\t\tif (val === undefined) {\n\t\t\tif (self.length < 1) {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\treturn self.hasVal() ? self[0].value : self.attr('value');\n\t\t} else {\n\t\t\tself.each(function() {\n\t\t\t\tif (_hasVal(this)) {\n\t\t\t\t\tthis.value = val;\n\t\t\t\t} else {\n\t\t\t\t\t_setAttr(this, 'value' , val);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn self;\n\t\t}\n\t},\n\tcss : function(key, val) {\n\t\tvar self = this;\n\t\tif (key === undefined) {\n\t\t\treturn _getCssList(self.attr('style'));\n\t\t}\n\t\tif (typeof key === 'object') {\n\t\t\t_each(key, function(k, v) {\n\t\t\t\tself.css(k, v);\n\t\t\t});\n\t\t\treturn self;\n\t\t}\n\t\tif (val === undefined) {\n\t\t\tif (self.length < 1) {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\treturn self[0].style[_toCamel(key)] || _computedCss(self[0], key) || '';\n\t\t}\n\t\tself.each(function() {\n\t\t\tthis.style[_toCamel(key)] = val;\n\t\t});\n\t\treturn self;\n\t},\n\twidth : function(val) {\n\t\tvar self = this;\n\t\tif (val === undefined) {\n\t\t\tif (self.length < 1) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn self[0].offsetWidth;\n\t\t}\n\t\treturn self.css('width', _addUnit(val));\n\t},\n\theight : function(val) {\n\t\tvar self = this;\n\t\tif (val === undefined) {\n\t\t\tif (self.length < 1) {\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t\treturn self[0].offsetHeight;\n\t\t}\n\t\treturn self.css('height', _addUnit(val));\n\t},\n\topacity : function(val) {\n\t\tthis.each(function() {\n\t\t\tif (this.style.opacity === undefined) {\n\t\t\t\tthis.style.filter = val == 1 ? '' : 'alpha(opacity=' + (val * 100) + ')';\n\t\t\t} else {\n\t\t\t\tthis.style.opacity = val == 1 ? '' : val;\n\t\t\t}\n\t\t});\n\t\treturn this;\n\t},\n\tdata : function(key, val) {\n\t\tvar self = this;\n\t\tkey = 'kindeditor_data_' + key;\n\t\tif (val === undefined) {\n\t\t\tif (self.length < 1) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\treturn self[0][key];\n\t\t}\n\t\tthis.each(function() {\n\t\t\tthis[key] = val;\n\t\t});\n\t\treturn self;\n\t},\n\tpos : function() {\n\t\tvar self = this, node = self[0], x = 0, y = 0;\n\t\tif (node) {\n\t\t\tif (node.getBoundingClientRect) {\n\t\t\t\tvar box = node.getBoundingClientRect(),\n\t\t\t\t\tpos = _getScrollPos(self.doc);\n\t\t\t\tx = box.left + pos.x;\n\t\t\t\ty = box.top + pos.y;\n\t\t\t} else {\n\t\t\t\twhile (node) {\n\t\t\t\t\tx += node.offsetLeft;\n\t\t\t\t\ty += node.offsetTop;\n\t\t\t\t\tnode = node.offsetParent;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn {x : _round(x), y : _round(y)};\n\t},\n\tclone : function(bool) {\n\t\tif (this.length < 1) {\n\t\t\treturn new KNode([]);\n\t\t}\n\t\treturn new KNode(this[0].cloneNode(bool));\n\t},\n\tappend : function(expr) {\n\t\tthis.each(function() {\n\t\t\tif (this.appendChild) {\n\t\t\t\tthis.appendChild(_get(expr));\n\t\t\t}\n\t\t});\n\t\treturn this;\n\t},\n\tappendTo : function(expr) {\n\t\tthis.each(function() {\n\t\t\t_get(expr).appendChild(this);\n\t\t});\n\t\treturn this;\n\t},\n\tbefore : function(expr) {\n\t\tthis.each(function() {\n\t\t\tthis.parentNode.insertBefore(_get(expr), this);\n\t\t});\n\t\treturn this;\n\t},\n\tafter : function(expr) {\n\t\tthis.each(function() {\n\t\t\tif (this.nextSibling) {\n\t\t\t\tthis.parentNode.insertBefore(_get(expr), this.nextSibling);\n\t\t\t} else {\n\t\t\t\tthis.parentNode.appendChild(_get(expr));\n\t\t\t}\n\t\t});\n\t\treturn this;\n\t},\n\treplaceWith : function(expr) {\n\t\tvar nodes = [];\n\t\tthis.each(function(i, node) {\n\t\t\t_unbind(node);\n\t\t\tvar newNode = _get(expr);\n\t\t\tnode.parentNode.replaceChild(newNode, node);\n\t\t\tnodes.push(newNode);\n\t\t});\n\t\treturn K(nodes);\n\t},\n\tempty : function() {\n\t\tvar self = this;\n\t\tself.each(function(i, node) {\n\t\t\tvar child = node.firstChild;\n\t\t\twhile (child) {\n\t\t\t\tif (!node.parentNode) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tvar next = child.nextSibling;\n\t\t\t\tchild.parentNode.removeChild(child);\n\t\t\t\tchild = next;\n\t\t\t}\n\t\t});\n\t\treturn self;\n\t},\n\tremove : function(keepChilds) {\n\t\tvar self = this;\n\t\tself.each(function(i, node) {\n\t\t\tif (!node.parentNode) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t_unbind(node);\n\t\t\tif (keepChilds) {\n\t\t\t\tvar child = node.firstChild;\n\t\t\t\twhile (child) {\n\t\t\t\t\tvar next = child.nextSibling;\n\t\t\t\t\tnode.parentNode.insertBefore(child, node);\n\t\t\t\t\tchild = next;\n\t\t\t\t}\n\t\t\t}\n\t\t\tnode.parentNode.removeChild(node);\n\t\t\tdelete self[i];\n\t\t});\n\t\tself.length = 0;\n\t\treturn self;\n\t},\n\tshow : function(val) {\n\t\tvar self = this;\n\t\tif (val === undefined) {\n\t\t\tval = self._originDisplay || '';\n\t\t}\n\t\tif (self.css('display') != 'none') {\n\t\t\treturn self;\n\t\t}\n\t\treturn self.css('display', val);\n\t},\n\thide : function() {\n\t\tvar self = this;\n\t\tif (self.length < 1) {\n\t\t\treturn self;\n\t\t}\n\t\tself._originDisplay = self[0].style.display;\n\t\treturn self.css('display', 'none');\n\t},\n\touter : function() {\n\t\tvar self = this;\n\t\tif (self.length < 1) {\n\t\t\treturn '';\n\t\t}\n\t\tvar div = self.doc.createElement('div'), html;\n\t\tdiv.appendChild(self[0].cloneNode(true));\n\t\thtml = _formatHtml(div.innerHTML);\n\t\tdiv = null;\n\t\treturn html;\n\t},\n\tisSingle : function() {\n\t\treturn !!_SINGLE_TAG_MAP[this.name];\n\t},\n\tisInline : function() {\n\t\treturn !!_INLINE_TAG_MAP[this.name];\n\t},\n\tisBlock : function() {\n\t\treturn !!_BLOCK_TAG_MAP[this.name];\n\t},\n\tisStyle : function() {\n\t\treturn !!_STYLE_TAG_MAP[this.name];\n\t},\n\tisControl : function() {\n\t\treturn !!_CONTROL_TAG_MAP[this.name];\n\t},\n\tcontains : function(otherNode) {\n\t\tif (this.length < 1) {\n\t\t\treturn false;\n\t\t}\n\t\treturn _contains(this[0], _get(otherNode));\n\t},\n\tparent : function() {\n\t\tif (this.length < 1) {\n\t\t\treturn null;\n\t\t}\n\t\tvar node = this[0].parentNode;\n\t\treturn node ? new KNode(node) : null;\n\t},\n\tchildren : function() {\n\t\tif (this.length < 1) {\n\t\t\treturn new KNode([]);\n\t\t}\n\t\tvar list = [], child = this[0].firstChild;\n\t\twhile (child) {\n\t\t\tif (child.nodeType != 3 || _trim(child.nodeValue) !== '') {\n\t\t\t\tlist.push(child);\n\t\t\t}\n\t\t\tchild = child.nextSibling;\n\t\t}\n\t\treturn new KNode(list);\n\t},\n\tfirst : function() {\n\t\tvar list = this.children();\n\t\treturn list.length > 0 ? list.eq(0) : null;\n\t},\n\tlast : function() {\n\t\tvar list = this.children();\n\t\treturn list.length > 0 ? list.eq(list.length - 1) : null;\n\t},\n\tindex : function() {\n\t\tif (this.length < 1) {\n\t\t\treturn -1;\n\t\t}\n\t\tvar i = -1, sibling = this[0];\n\t\twhile (sibling) {\n\t\t\ti++;\n\t\t\tsibling = sibling.previousSibling;\n\t\t}\n\t\treturn i;\n\t},\n\tprev : function() {\n\t\tif (this.length < 1) {\n\t\t\treturn null;\n\t\t}\n\t\tvar node = this[0].previousSibling;\n\t\treturn node ? new KNode(node) : null;\n\t},\n\tnext : function() {\n\t\tif (this.length < 1) {\n\t\t\treturn null;\n\t\t}\n\t\tvar node = this[0].nextSibling;\n\t\treturn node ? new KNode(node) : null;\n\t},\n\tscan : function(fn, order) {\n\t\tif (this.length < 1) {\n\t\t\treturn;\n\t\t}\n\t\torder = (order === undefined) ? true : order;\n\t\tfunction walk(node) {\n\t\t\tvar n = order ? node.firstChild : node.lastChild;\n\t\t\twhile (n) {\n\t\t\t\tvar next = order ? n.nextSibling : n.previousSibling;\n\t\t\t\tif (fn(n) === false) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (walk(n) === false) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tn = next;\n\t\t\t}\n\t\t}\n\t\twalk(this[0]);\n\t\treturn this;\n\t}\n});\n_each(('blur,focus,focusin,focusout,load,resize,scroll,unload,click,dblclick,' +\n\t'mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,' +\n\t'change,select,submit,keydown,keypress,keyup,error,contextmenu').split(','), function(i, type) {\n\tKNode.prototype[type] = function(fn) {\n\t\treturn fn ? this.bind(type, fn) : this.fire(type);\n\t};\n});\nvar _K = K;\nK = function(expr, root) {\n\tif (expr === undefined || expr === null) {\n\t\treturn;\n\t}\n\tfunction newNode(node) {\n\t\tif (!node[0]) {\n\t\t\tnode = [];\n\t\t}\n\t\treturn new KNode(node);\n\t}\n\tif (typeof expr === 'string') {\n\t\tif (root) {\n\t\t\troot = _get(root);\n\t\t}\n\t\tvar length = expr.length;\n\t\tif (expr.charAt(0) === '@') {\n\t\t\texpr = expr.substr(1);\n\t\t}\n\t\tif (expr.length !== length || /<.+>/.test(expr)) {\n\t\t\tvar doc = root ? root.ownerDocument || root : document,\n\t\t\t\tdiv = doc.createElement('div'), list = [];\n\t\t\tdiv.innerHTML = '<img id=\"__kindeditor_temp_tag__\" width=\"0\" height=\"0\" style=\"display:none;\" />' + expr;\n\t\t\tfor (var i = 0, len = div.childNodes.length; i < len; i++) {\n\t\t\t\tvar child = div.childNodes[i];\n\t\t\t\tif (child.id == '__kindeditor_temp_tag__') {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tlist.push(child);\n\t\t\t}\n\t\t\treturn newNode(list);\n\t\t}\n\t\treturn newNode(_queryAll(expr, root));\n\t}\n\tif (expr && expr.constructor === KNode) {\n\t\treturn expr;\n\t}\n\tif (expr.toArray) {\n\t\texpr = expr.toArray();\n\t}\n\tif (_isArray(expr)) {\n\t\treturn newNode(expr);\n\t}\n\treturn newNode(_toArray(arguments));\n};\n_each(_K, function(key, val) {\n\tK[key] = val;\n});\nK.NodeClass = KNode;\nwindow.KindEditor = K;\n\n\nvar _START_TO_START = 0,\n\t_START_TO_END = 1,\n\t_END_TO_END = 2,\n\t_END_TO_START = 3,\n\t_BOOKMARK_ID = 0;\nfunction _updateCollapsed(range) {\n\trange.collapsed = (range.startContainer === range.endContainer && range.startOffset === range.endOffset);\n\treturn range;\n}\nfunction _copyAndDelete(range, isCopy, isDelete) {\n\tvar doc = range.doc, nodeList = [];\n\tfunction splitTextNode(node, startOffset, endOffset) {\n\t\tvar length = node.nodeValue.length, centerNode;\n\t\tif (isCopy) {\n\t\t\tvar cloneNode = node.cloneNode(true);\n\t\t\tif (startOffset > 0) {\n\t\t\t\tcenterNode = cloneNode.splitText(startOffset);\n\t\t\t} else {\n\t\t\t\tcenterNode = cloneNode;\n\t\t\t}\n\t\t\tif (endOffset < length) {\n\t\t\t\tcenterNode.splitText(endOffset - startOffset);\n\t\t\t}\n\t\t}\n\t\tif (isDelete) {\n\t\t\tvar center = node;\n\t\t\tif (startOffset > 0) {\n\t\t\t\tcenter = node.splitText(startOffset);\n\t\t\t\trange.setStart(node, startOffset);\n\t\t\t}\n\t\t\tif (endOffset < length) {\n\t\t\t\tvar right = center.splitText(endOffset - startOffset);\n\t\t\t\trange.setEnd(right, 0);\n\t\t\t}\n\t\t\tnodeList.push(center);\n\t\t}\n\t\treturn centerNode;\n\t}\n\tfunction removeNodes() {\n\t\tif (isDelete) {\n\t\t\trange.up().collapse(true);\n\t\t}\n\t\tfor (var i = 0, len = nodeList.length; i < len; i++) {\n\t\t\tvar node = nodeList[i];\n\t\t\tif (node.parentNode) {\n\t\t\t\tnode.parentNode.removeChild(node);\n\t\t\t}\n\t\t}\n\t}\n\tvar copyRange = range.cloneRange().down();\n\tvar start = -1, incStart = -1, incEnd = -1, end = -1,\n\t\tancestor = range.commonAncestor(), frag = doc.createDocumentFragment();\n\tif (ancestor.nodeType == 3) {\n\t\tvar textNode = splitTextNode(ancestor, range.startOffset, range.endOffset);\n\t\tif (isCopy) {\n\t\t\tfrag.appendChild(textNode);\n\t\t}\n\t\tremoveNodes();\n\t\treturn isCopy ? frag : range;\n\t}\n\tfunction extractNodes(parent, frag) {\n\t\tvar node = parent.firstChild, nextNode;\n\t\twhile (node) {\n\t\t\tvar testRange = new KRange(doc).selectNode(node);\n\t\t\tstart = testRange.compareBoundaryPoints(_START_TO_END, range);\n\t\t\tif (start >= 0 && incStart <= 0) {\n\t\t\t\tincStart = testRange.compareBoundaryPoints(_START_TO_START, range);\n\t\t\t}\n\t\t\tif (incStart >= 0 && incEnd <= 0) {\n\t\t\t\tincEnd = testRange.compareBoundaryPoints(_END_TO_END, range);\n\t\t\t}\n\t\t\tif (incEnd >= 0 && end <= 0) {\n\t\t\t\tend = testRange.compareBoundaryPoints(_END_TO_START, range);\n\t\t\t}\n\t\t\tif (end >= 0) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tnextNode = node.nextSibling;\n\t\t\tif (start > 0) {\n\t\t\t\tif (node.nodeType == 1) {\n\t\t\t\t\tif (incStart >= 0 && incEnd <= 0) {\n\t\t\t\t\t\tif (isCopy) {\n\t\t\t\t\t\t\tfrag.appendChild(node.cloneNode(true));\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isDelete) {\n\t\t\t\t\t\t\tnodeList.push(node);\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar childFlag;\n\t\t\t\t\t\tif (isCopy) {\n\t\t\t\t\t\t\tchildFlag = node.cloneNode(false);\n\t\t\t\t\t\t\tfrag.appendChild(childFlag);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (extractNodes(node, childFlag) === false) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (node.nodeType == 3) {\n\t\t\t\t\tvar textNode;\n\t\t\t\t\tif (node == copyRange.startContainer) {\n\t\t\t\t\t\ttextNode = splitTextNode(node, copyRange.startOffset, node.nodeValue.length);\n\t\t\t\t\t} else if (node == copyRange.endContainer) {\n\t\t\t\t\t\ttextNode = splitTextNode(node, 0, copyRange.endOffset);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttextNode = splitTextNode(node, 0, node.nodeValue.length);\n\t\t\t\t\t}\n\t\t\t\t\tif (isCopy) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tfrag.appendChild(textNode);\n\t\t\t\t\t\t} catch(e) {}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tnode = nextNode;\n\t\t}\n\t}\n\textractNodes(ancestor, frag);\n\tif (isDelete) {\n\t\trange.up().collapse(true);\n\t}\n\tfor (var i = 0, len = nodeList.length; i < len; i++) {\n\t\tvar node = nodeList[i];\n\t\tif (node.parentNode) {\n\t\t\tnode.parentNode.removeChild(node);\n\t\t}\n\t}\n\treturn isCopy ? frag : range;\n}\n\nfunction _moveToElementText(range, el) {\n\tvar node = el;\n\twhile (node) {\n\t\tvar knode = K(node);\n\t\tif (knode.name == 'marquee' || knode.name == 'select') {\n\t\t\treturn;\n\t\t}\n\t\tnode = node.parentNode;\n\t}\n\ttry {\n\t\trange.moveToElementText(el);\n\t} catch(e) {}\n}\n\nfunction _getStartEnd(rng, isStart) {\n\tvar doc = rng.parentElement().ownerDocument,\n\t\tpointRange = rng.duplicate();\n\tpointRange.collapse(isStart);\n\tvar parent = pointRange.parentElement(),\n\t\tnodes = parent.childNodes;\n\tif (nodes.length === 0) {\n\t\treturn {node: parent.parentNode, offset: K(parent).index()};\n\t}\n\tvar startNode = doc, startPos = 0, cmp = -1;\n\tvar testRange = rng.duplicate();\n\t_moveToElementText(testRange, parent);\n\tfor (var i = 0, len = nodes.length; i < len; i++) {\n\t\tvar node = nodes[i];\n\t\tcmp = testRange.compareEndPoints('StartToStart', pointRange);\n\t\tif (cmp === 0) {\n\t\t\treturn {node: node.parentNode, offset: i};\n\t\t}\n\t\tif (node.nodeType == 1) {\n\t\t\tvar nodeRange = rng.duplicate(), dummy, knode = K(node), newNode = node;\n\t\t\tif (knode.isControl()) {\n\t\t\t\tdummy = doc.createElement('span');\n\t\t\t\tknode.after(dummy);\n\t\t\t\tnewNode = dummy;\n\t\t\t\tstartPos += knode.text().replace(/\\r\\n|\\n|\\r/g, '').length;\n\t\t\t}\n\t\t\t_moveToElementText(nodeRange, newNode);\n\t\t\ttestRange.setEndPoint('StartToEnd', nodeRange);\n\t\t\tif (cmp > 0) {\n\t\t\t\tstartPos += nodeRange.text.replace(/\\r\\n|\\n|\\r/g, '').length;\n\t\t\t} else {\n\t\t\t\tstartPos = 0;\n\t\t\t}\n\t\t\tif (dummy) {\n\t\t\t\tK(dummy).remove();\n\t\t\t}\n\t\t} else if (node.nodeType == 3) {\n\t\t\ttestRange.moveStart('character', node.nodeValue.length);\n\t\t\tstartPos += node.nodeValue.length;\n\t\t}\n\t\tif (cmp < 0) {\n\t\t\tstartNode = node;\n\t\t}\n\t}\n\tif (cmp < 0 && startNode.nodeType == 1) {\n\t\treturn {node: parent, offset: K(parent.lastChild).index() + 1};\n\t}\n\tif (cmp > 0) {\n\t\twhile (startNode.nextSibling && startNode.nodeType == 1) {\n\t\t\tstartNode = startNode.nextSibling;\n\t\t}\n\t}\n\ttestRange = rng.duplicate();\n\t_moveToElementText(testRange, parent);\n\ttestRange.setEndPoint('StartToEnd', pointRange);\n\tstartPos -= testRange.text.replace(/\\r\\n|\\n|\\r/g, '').length;\n\tif (cmp > 0 && startNode.nodeType == 3) {\n\t\tvar prevNode = startNode.previousSibling;\n\t\twhile (prevNode && prevNode.nodeType == 3) {\n\t\t\tstartPos -= prevNode.nodeValue.length;\n\t\t\tprevNode = prevNode.previousSibling;\n\t\t}\n\t}\n\treturn {node: startNode, offset: startPos};\n}\n\nfunction _getEndRange(node, offset) {\n\tvar doc = node.ownerDocument || node,\n\t\trange = doc.body.createTextRange();\n\tif (doc == node) {\n\t\trange.collapse(true);\n\t\treturn range;\n\t}\n\tif (node.nodeType == 1 && node.childNodes.length > 0) {\n\t\tvar children = node.childNodes, isStart, child;\n\t\tif (offset === 0) {\n\t\t\tchild = children[0];\n\t\t\tisStart = true;\n\t\t} else {\n\t\t\tchild = children[offset - 1];\n\t\t\tisStart = false;\n\t\t}\n\t\tif (!child) {\n\t\t\treturn range;\n\t\t}\n\t\tif (K(child).name === 'head') {\n\t\t\tif (offset === 1) {\n\t\t\t\tisStart = true;\n\t\t\t}\n\t\t\tif (offset === 2) {\n\t\t\t\tisStart = false;\n\t\t\t}\n\t\t\trange.collapse(isStart);\n\t\t\treturn range;\n\t\t}\n\t\tif (child.nodeType == 1) {\n\t\t\tvar kchild = K(child), span;\n\t\t\tif (kchild.isControl()) {\n\t\t\t\tspan = doc.createElement('span');\n\t\t\t\tif (isStart) {\n\t\t\t\t\tkchild.before(span);\n\t\t\t\t} else {\n\t\t\t\t\tkchild.after(span);\n\t\t\t\t}\n\t\t\t\tchild = span;\n\t\t\t}\n\t\t\t_moveToElementText(range, child);\n\t\t\trange.collapse(isStart);\n\t\t\tif (span) {\n\t\t\t\tK(span).remove();\n\t\t\t}\n\t\t\treturn range;\n\t\t}\n\t\tnode = child;\n\t\toffset = isStart ? 0 : child.nodeValue.length;\n\t}\n\tvar dummy = doc.createElement('span');\n\tK(node).before(dummy);\n\t_moveToElementText(range, dummy);\n\trange.moveStart('character', offset);\n\tK(dummy).remove();\n\treturn range;\n}\n\nfunction _toRange(rng) {\n\tvar doc, range;\n\tfunction tr2td(start) {\n\t\tif (K(start.node).name == 'tr') {\n\t\t\tstart.node = start.node.cells[start.offset];\n\t\t\tstart.offset = 0;\n\t\t}\n\t}\n\tif (_IERANGE) {\n\t\tif (rng.item) {\n\t\t\tdoc = _getDoc(rng.item(0));\n\t\t\trange = new KRange(doc);\n\t\t\trange.selectNode(rng.item(0));\n\t\t\treturn range;\n\t\t}\n\t\tdoc = rng.parentElement().ownerDocument;\n\t\tvar start = _getStartEnd(rng, true),\n\t\t\tend = _getStartEnd(rng, false);\n\t\ttr2td(start);\n\t\ttr2td(end);\n\t\trange = new KRange(doc);\n\t\trange.setStart(start.node, start.offset);\n\t\trange.setEnd(end.node, end.offset);\n\t\treturn range;\n\t}\n\tvar startContainer = rng.startContainer;\n\tdoc = startContainer.ownerDocument || startContainer;\n\trange = new KRange(doc);\n\trange.setStart(startContainer, rng.startOffset);\n\trange.setEnd(rng.endContainer, rng.endOffset);\n\treturn range;\n}\n\n\nfunction KRange(doc) {\n\tthis.init(doc);\n}\n_extend(KRange, {\n\tinit : function(doc) {\n\t\tvar self = this;\n\t\tself.startContainer = doc;\n\t\tself.startOffset = 0;\n\t\tself.endContainer = doc;\n\t\tself.endOffset = 0;\n\t\tself.collapsed = true;\n\t\tself.doc = doc;\n\t},\n\tcommonAncestor : function() {\n\t\tfunction getParents(node) {\n\t\t\tvar parents = [];\n\t\t\twhile (node) {\n\t\t\t\tparents.push(node);\n\t\t\t\tnode = node.parentNode;\n\t\t\t}\n\t\t\treturn parents;\n\t\t}\n\t\tvar parentsA = getParents(this.startContainer),\n\t\t\tparentsB = getParents(this.endContainer),\n\t\t\ti = 0, lenA = parentsA.length, lenB = parentsB.length, parentA, parentB;\n\t\twhile (++i) {\n\t\t\tparentA = parentsA[lenA - i];\n\t\t\tparentB = parentsB[lenB - i];\n\t\t\tif (!parentA || !parentB || parentA !== parentB) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\treturn parentsA[lenA - i + 1];\n\t},\n\tsetStart : function(node, offset) {\n\t\tvar self = this, doc = self.doc;\n\t\tself.startContainer = node;\n\t\tself.startOffset = offset;\n\t\tif (self.endContainer === doc) {\n\t\t\tself.endContainer = node;\n\t\t\tself.endOffset = offset;\n\t\t}\n\t\treturn _updateCollapsed(this);\n\t},\n\tsetEnd : function(node, offset) {\n\t\tvar self = this, doc = self.doc;\n\t\tself.endContainer = node;\n\t\tself.endOffset = offset;\n\t\tif (self.startContainer === doc) {\n\t\t\tself.startContainer = node;\n\t\t\tself.startOffset = offset;\n\t\t}\n\t\treturn _updateCollapsed(this);\n\t},\n\tsetStartBefore : function(node) {\n\t\treturn this.setStart(node.parentNode || this.doc, K(node).index());\n\t},\n\tsetStartAfter : function(node) {\n\t\treturn this.setStart(node.parentNode || this.doc, K(node).index() + 1);\n\t},\n\tsetEndBefore : function(node) {\n\t\treturn this.setEnd(node.parentNode || this.doc, K(node).index());\n\t},\n\tsetEndAfter : function(node) {\n\t\treturn this.setEnd(node.parentNode || this.doc, K(node).index() + 1);\n\t},\n\tselectNode : function(node) {\n\t\treturn this.setStartBefore(node).setEndAfter(node);\n\t},\n\tselectNodeContents : function(node) {\n\t\tvar knode = K(node);\n\t\tif (knode.type == 3 || knode.isSingle()) {\n\t\t\treturn this.selectNode(node);\n\t\t}\n\t\tvar children = knode.children();\n\t\tif (children.length > 0) {\n\t\t\treturn this.setStartBefore(children[0]).setEndAfter(children[children.length - 1]);\n\t\t}\n\t\treturn this.setStart(node, 0).setEnd(node, 0);\n\t},\n\tcollapse : function(toStart) {\n\t\tif (toStart) {\n\t\t\treturn this.setEnd(this.startContainer, this.startOffset);\n\t\t}\n\t\treturn this.setStart(this.endContainer, this.endOffset);\n\t},\n\tcompareBoundaryPoints : function(how, range) {\n\t\tvar rangeA = this.get(), rangeB = range.get();\n\t\tif (_IERANGE) {\n\t\t\tvar arr = {};\n\t\t\tarr[_START_TO_START] = 'StartToStart';\n\t\t\tarr[_START_TO_END] = 'EndToStart';\n\t\t\tarr[_END_TO_END] = 'EndToEnd';\n\t\t\tarr[_END_TO_START] = 'StartToEnd';\n\t\t\tvar cmp = rangeA.compareEndPoints(arr[how], rangeB);\n\t\t\tif (cmp !== 0) {\n\t\t\t\treturn cmp;\n\t\t\t}\n\t\t\tvar nodeA, nodeB, nodeC, posA, posB;\n\t\t\tif (how === _START_TO_START || how === _END_TO_START) {\n\t\t\t\tnodeA = this.startContainer;\n\t\t\t\tposA = this.startOffset;\n\t\t\t}\n\t\t\tif (how === _START_TO_END || how === _END_TO_END) {\n\t\t\t\tnodeA = this.endContainer;\n\t\t\t\tposA = this.endOffset;\n\t\t\t}\n\t\t\tif (how === _START_TO_START || how === _START_TO_END) {\n\t\t\t\tnodeB = range.startContainer;\n\t\t\t\tposB = range.startOffset;\n\t\t\t}\n\t\t\tif (how === _END_TO_END || how === _END_TO_START) {\n\t\t\t\tnodeB = range.endContainer;\n\t\t\t\tposB = range.endOffset;\n\t\t\t}\n\t\t\tif (nodeA === nodeB) {\n\t\t\t\tvar diff = posA - posB;\n\t\t\t\treturn diff > 0 ? 1 : (diff < 0 ? -1 : 0);\n\t\t\t}\n\t\t\tnodeC = nodeB;\n\t\t\twhile (nodeC && nodeC.parentNode !== nodeA) {\n\t\t\t\tnodeC = nodeC.parentNode;\n\t\t\t}\n\t\t\tif (nodeC) {\n\t\t\t\treturn K(nodeC).index() >= posA ? -1 : 1;\n\t\t\t}\n\t\t\tnodeC = nodeA;\n\t\t\twhile (nodeC && nodeC.parentNode !== nodeB) {\n\t\t\t\tnodeC = nodeC.parentNode;\n\t\t\t}\n\t\t\tif (nodeC) {\n\t\t\t\treturn K(nodeC).index() >= posB ? 1 : -1;\n\t\t\t}\n\t\t\tnodeC = K(nodeB).next();\n\t\t\tif (nodeC && nodeC.contains(nodeA)) {\n\t\t\t\treturn 1;\n\t\t\t}\n\t\t\tnodeC = K(nodeA).next();\n\t\t\tif (nodeC && nodeC.contains(nodeB)) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t} else {\n\t\t\treturn rangeA.compareBoundaryPoints(how, rangeB);\n\t\t}\n\t},\n\tcloneRange : function() {\n\t\treturn new KRange(this.doc).setStart(this.startContainer, this.startOffset).setEnd(this.endContainer, this.endOffset);\n\t},\n\ttoString : function() {\n\t\tvar rng = this.get(), str = _IERANGE ? rng.text : rng.toString();\n\t\treturn str.replace(/\\r\\n|\\n|\\r/g, '');\n\t},\n\tcloneContents : function() {\n\t\treturn _copyAndDelete(this, true, false);\n\t},\n\tdeleteContents : function() {\n\t\treturn _copyAndDelete(this, false, true);\n\t},\n\textractContents : function() {\n\t\treturn _copyAndDelete(this, true, true);\n\t},\n\tinsertNode : function(node) {\n\t\tvar self = this,\n\t\t\tsc = self.startContainer, so = self.startOffset,\n\t\t\tec = self.endContainer, eo = self.endOffset,\n\t\t\tfirstChild, lastChild, c, nodeCount = 1;\n\t\tif (node.nodeName.toLowerCase() === '#document-fragment') {\n\t\t\tfirstChild = node.firstChild;\n\t\t\tlastChild = node.lastChild;\n\t\t\tnodeCount = node.childNodes.length;\n\t\t}\n\t\tif (sc.nodeType == 1) {\n\t\t\tc = sc.childNodes[so];\n\t\t\tif (c) {\n\t\t\t\tsc.insertBefore(node, c);\n\t\t\t\tif (sc === ec) {\n\t\t\t\t\teo += nodeCount;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsc.appendChild(node);\n\t\t\t}\n\t\t} else if (sc.nodeType == 3) {\n\t\t\tif (so === 0) {\n\t\t\t\tsc.parentNode.insertBefore(node, sc);\n\t\t\t\tif (sc.parentNode === ec) {\n\t\t\t\t\teo += nodeCount;\n\t\t\t\t}\n\t\t\t} else if (so >= sc.nodeValue.length) {\n\t\t\t\tif (sc.nextSibling) {\n\t\t\t\t\tsc.parentNode.insertBefore(node, sc.nextSibling);\n\t\t\t\t} else {\n\t\t\t\t\tsc.parentNode.appendChild(node);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (so > 0) {\n\t\t\t\t\tc = sc.splitText(so);\n\t\t\t\t} else {\n\t\t\t\t\tc = sc;\n\t\t\t\t}\n\t\t\t\tsc.parentNode.insertBefore(node, c);\n\t\t\t\tif (sc === ec) {\n\t\t\t\t\tec = c;\n\t\t\t\t\teo -= so;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (firstChild) {\n\t\t\tself.setStartBefore(firstChild).setEndAfter(lastChild);\n\t\t} else {\n\t\t\tself.selectNode(node);\n\t\t}\n\t\tif (self.compareBoundaryPoints(_END_TO_END, self.cloneRange().setEnd(ec, eo)) >= 1) {\n\t\t\treturn self;\n\t\t}\n\t\treturn self.setEnd(ec, eo);\n\t},\n\tsurroundContents : function(node) {\n\t\tnode.appendChild(this.extractContents());\n\t\treturn this.insertNode(node).selectNode(node);\n\t},\n\tisControl : function() {\n\t\tvar self = this,\n\t\t\tsc = self.startContainer, so = self.startOffset,\n\t\t\tec = self.endContainer, eo = self.endOffset, rng;\n\t\treturn sc.nodeType == 1 && sc === ec && so + 1 === eo && K(sc.childNodes[so]).isControl();\n\t},\n\tget : function(hasControlRange) {\n\t\tvar self = this, doc = self.doc, node, rng;\n\t\tif (!_IERANGE) {\n\t\t\trng = doc.createRange();\n\t\t\ttry {\n\t\t\t\trng.setStart(self.startContainer, self.startOffset);\n\t\t\t\trng.setEnd(self.endContainer, self.endOffset);\n\t\t\t} catch (e) {}\n\t\t\treturn rng;\n\t\t}\n\t\tif (hasControlRange && self.isControl()) {\n\t\t\trng = doc.body.createControlRange();\n\t\t\trng.addElement(self.startContainer.childNodes[self.startOffset]);\n\t\t\treturn rng;\n\t\t}\n\t\tvar range = self.cloneRange().down();\n\t\trng = doc.body.createTextRange();\n\t\trng.setEndPoint('StartToStart', _getEndRange(range.startContainer, range.startOffset));\n\t\trng.setEndPoint('EndToStart', _getEndRange(range.endContainer, range.endOffset));\n\t\treturn rng;\n\t},\n\thtml : function() {\n\t\treturn K(this.cloneContents()).outer();\n\t},\n\tdown : function() {\n\t\tvar self = this;\n\t\tfunction downPos(node, pos, isStart) {\n\t\t\tif (node.nodeType != 1) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar children = K(node).children();\n\t\t\tif (children.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar left, right, child, offset;\n\t\t\tif (pos > 0) {\n\t\t\t\tleft = children.eq(pos - 1);\n\t\t\t}\n\t\t\tif (pos < children.length) {\n\t\t\t\tright = children.eq(pos);\n\t\t\t}\n\t\t\tif (left && left.type == 3) {\n\t\t\t\tchild = left[0];\n\t\t\t\toffset = child.nodeValue.length;\n\t\t\t}\n\t\t\tif (right && right.type == 3) {\n\t\t\t\tchild = right[0];\n\t\t\t\toffset = 0;\n\t\t\t}\n\t\t\tif (!child) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (isStart) {\n\t\t\t\tself.setStart(child, offset);\n\t\t\t} else {\n\t\t\t\tself.setEnd(child, offset);\n\t\t\t}\n\t\t}\n\t\tdownPos(self.startContainer, self.startOffset, true);\n\t\tdownPos(self.endContainer, self.endOffset, false);\n\t\treturn self;\n\t},\n\tup : function() {\n\t\tvar self = this;\n\t\tfunction upPos(node, pos, isStart) {\n\t\t\tif (node.nodeType != 3) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (pos === 0) {\n\t\t\t\tif (isStart) {\n\t\t\t\t\tself.setStartBefore(node);\n\t\t\t\t} else {\n\t\t\t\t\tself.setEndBefore(node);\n\t\t\t\t}\n\t\t\t} else if (pos == node.nodeValue.length) {\n\t\t\t\tif (isStart) {\n\t\t\t\t\tself.setStartAfter(node);\n\t\t\t\t} else {\n\t\t\t\t\tself.setEndAfter(node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tupPos(self.startContainer, self.startOffset, true);\n\t\tupPos(self.endContainer, self.endOffset, false);\n\t\treturn self;\n\t},\n\tenlarge : function(toBlock) {\n\t\tvar self = this;\n\t\tself.up();\n\t\tfunction enlargePos(node, pos, isStart) {\n\t\t\tvar knode = K(node), parent;\n\t\t\tif (knode.type == 3 || _NOSPLIT_TAG_MAP[knode.name] || !toBlock && knode.isBlock()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (pos === 0) {\n\t\t\t\twhile (!knode.prev()) {\n\t\t\t\t\tparent = knode.parent();\n\t\t\t\t\tif (!parent || _NOSPLIT_TAG_MAP[parent.name] || !toBlock && parent.isBlock()) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tknode = parent;\n\t\t\t\t}\n\t\t\t\tif (isStart) {\n\t\t\t\t\tself.setStartBefore(knode[0]);\n\t\t\t\t} else {\n\t\t\t\t\tself.setEndBefore(knode[0]);\n\t\t\t\t}\n\t\t\t} else if (pos == knode.children().length) {\n\t\t\t\twhile (!knode.next()) {\n\t\t\t\t\tparent = knode.parent();\n\t\t\t\t\tif (!parent || _NOSPLIT_TAG_MAP[parent.name] || !toBlock && parent.isBlock()) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tknode = parent;\n\t\t\t\t}\n\t\t\t\tif (isStart) {\n\t\t\t\t\tself.setStartAfter(knode[0]);\n\t\t\t\t} else {\n\t\t\t\t\tself.setEndAfter(knode[0]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tenlargePos(self.startContainer, self.startOffset, true);\n\t\tenlargePos(self.endContainer, self.endOffset, false);\n\t\treturn self;\n\t},\n\tshrink : function() {\n\t\tvar self = this, child, collapsed = self.collapsed;\n\t\twhile (self.startContainer.nodeType == 1 && (child = self.startContainer.childNodes[self.startOffset]) && child.nodeType == 1 && !K(child).isSingle()) {\n\t\t\tself.setStart(child, 0);\n\t\t}\n\t\tif (collapsed) {\n\t\t\treturn self.collapse(collapsed);\n\t\t}\n\t\twhile (self.endContainer.nodeType == 1 && self.endOffset > 0 && (child = self.endContainer.childNodes[self.endOffset - 1]) && child.nodeType == 1 && !K(child).isSingle()) {\n\t\t\tself.setEnd(child, child.childNodes.length);\n\t\t}\n\t\treturn self;\n\t},\n\tcreateBookmark : function(serialize) {\n\t\tvar self = this, doc = self.doc, endNode,\n\t\t\tstartNode = K('<span style=\"display:none;\"></span>', doc)[0];\n\t\tstartNode.id = '__kindeditor_bookmark_start_' + (_BOOKMARK_ID++) + '__';\n\t\tif (!self.collapsed) {\n\t\t\tendNode = startNode.cloneNode(true);\n\t\t\tendNode.id = '__kindeditor_bookmark_end_' + (_BOOKMARK_ID++) + '__';\n\t\t}\n\t\tif (endNode) {\n\t\t\tself.cloneRange().collapse(false).insertNode(endNode).setEndBefore(endNode);\n\t\t}\n\t\tself.insertNode(startNode).setStartAfter(startNode);\n\t\treturn {\n\t\t\tstart : serialize ? '#' + startNode.id : startNode,\n\t\t\tend : endNode ? (serialize ? '#' + endNode.id : endNode) : null\n\t\t};\n\t},\n\tmoveToBookmark : function(bookmark) {\n\t\tvar self = this, doc = self.doc,\n\t\t\tstart = K(bookmark.start, doc), end = bookmark.end ? K(bookmark.end, doc) : null;\n\t\tif (!start || start.length < 1) {\n\t\t\treturn self;\n\t\t}\n\t\tself.setStartBefore(start[0]);\n\t\tstart.remove();\n\t\tif (end && end.length > 0) {\n\t\t\tself.setEndBefore(end[0]);\n\t\t\tend.remove();\n\t\t} else {\n\t\t\tself.collapse(true);\n\t\t}\n\t\treturn self;\n\t},\n\tdump : function() {\n\t\tconsole.log('--------------------');\n\t\tconsole.log(this.startContainer.nodeType == 3 ? this.startContainer.nodeValue : this.startContainer, this.startOffset);\n\t\tconsole.log(this.endContainer.nodeType == 3 ? this.endContainer.nodeValue : this.endContainer, this.endOffset);\n\t}\n});\nfunction _range(mixed) {\n\tif (!mixed.nodeName) {\n\t\treturn mixed.constructor === KRange ? mixed : _toRange(mixed);\n\t}\n\treturn new KRange(mixed);\n}\nK.RangeClass = KRange;\nK.range = _range;\nK.START_TO_START = _START_TO_START;\nK.START_TO_END = _START_TO_END;\nK.END_TO_END = _END_TO_END;\nK.END_TO_START = _END_TO_START;\n\n\n\nfunction _nativeCommand(doc, key, val) {\n\ttry {\n\t\tdoc.execCommand(key, false, val);\n\t} catch(e) {}\n}\n\nfunction _nativeCommandValue(doc, key) {\n\tvar val = '';\n\ttry {\n\t\tval = doc.queryCommandValue(key);\n\t} catch (e) {}\n\tif (typeof val !== 'string') {\n\t\tval = '';\n\t}\n\treturn val;\n}\n\nfunction _getSel(doc) {\n\tvar win = _getWin(doc);\n\treturn _IERANGE ? doc.selection : win.getSelection();\n}\n\nfunction _getRng(doc) {\n\tvar sel = _getSel(doc), rng;\n\ttry {\n\t\tif (sel.rangeCount > 0) {\n\t\t\trng = sel.getRangeAt(0);\n\t\t} else {\n\t\t\trng = sel.createRange();\n\t\t}\n\t} catch(e) {}\n\tif (_IERANGE && (!rng || (!rng.item && rng.parentElement().ownerDocument !== doc))) {\n\t\treturn null;\n\t}\n\treturn rng;\n}\n\nfunction _singleKeyMap(map) {\n\tvar newMap = {}, arr, v;\n\t_each(map, function(key, val) {\n\t\tarr = key.split(',');\n\t\tfor (var i = 0, len = arr.length; i < len; i++) {\n\t\t\tv = arr[i];\n\t\t\tnewMap[v] = val;\n\t\t}\n\t});\n\treturn newMap;\n}\n\nfunction _hasAttrOrCss(knode, map) {\n\treturn _hasAttrOrCssByKey(knode, map, '*') || _hasAttrOrCssByKey(knode, map);\n}\nfunction _hasAttrOrCssByKey(knode, map, mapKey) {\n\tmapKey = mapKey || knode.name;\n\tif (knode.type !== 1) {\n\t\treturn false;\n\t}\n\tvar newMap = _singleKeyMap(map);\n\tif (!newMap[mapKey]) {\n\t\treturn false;\n\t}\n\tvar arr = newMap[mapKey].split(',');\n\tfor (var i = 0, len = arr.length; i < len; i++) {\n\t\tvar key = arr[i];\n\t\tif (key === '*') {\n\t\t\treturn true;\n\t\t}\n\t\tvar match = /^(\\.?)([^=]+)(?:=([^=]*))?$/.exec(key);\n\t\tvar method = match[1] ? 'css' : 'attr';\n\t\tkey = match[2];\n\t\tvar val = match[3] || '';\n\t\tif (val === '' && knode[method](key) !== '') {\n\t\t\treturn true;\n\t\t}\n\t\tif (val !== '' && knode[method](key) === val) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction _removeAttrOrCss(knode, map) {\n\tif (knode.type != 1) {\n\t\treturn;\n\t}\n\t_removeAttrOrCssByKey(knode, map, '*');\n\t_removeAttrOrCssByKey(knode, map);\n}\nfunction _removeAttrOrCssByKey(knode, map, mapKey) {\n\tmapKey = mapKey || knode.name;\n\tif (knode.type !== 1) {\n\t\treturn;\n\t}\n\tvar newMap = _singleKeyMap(map);\n\tif (!newMap[mapKey]) {\n\t\treturn;\n\t}\n\tvar arr = newMap[mapKey].split(','), allFlag = false;\n\tfor (var i = 0, len = arr.length; i < len; i++) {\n\t\tvar key = arr[i];\n\t\tif (key === '*') {\n\t\t\tallFlag = true;\n\t\t\tbreak;\n\t\t}\n\t\tvar match = /^(\\.?)([^=]+)(?:=([^=]*))?$/.exec(key);\n\t\tkey = match[2];\n\t\tif (match[1]) {\n\t\t\tkey = _toCamel(key);\n\t\t\tif (knode[0].style[key]) {\n\t\t\t\tknode[0].style[key] = '';\n\t\t\t}\n\t\t} else {\n\t\t\tknode.removeAttr(key);\n\t\t}\n\t}\n\tif (allFlag) {\n\t\tknode.remove(true);\n\t}\n}\n\nfunction _getInnerNode(knode) {\n\tvar inner = knode;\n\twhile (inner.first()) {\n\t\tinner = inner.first();\n\t}\n\treturn inner;\n}\n\nfunction _isEmptyNode(knode) {\n\tif (knode.type != 1 || knode.isSingle()) {\n\t\treturn false;\n\t}\n\treturn knode.html().replace(/<[^>]+>/g, '') === '';\n}\n\n\n\n\nfunction _mergeWrapper(a, b) {\n\ta = a.clone(true);\n\tvar lastA = _getInnerNode(a), childA = a, merged = false;\n\twhile (b) {\n\t\twhile (childA) {\n\t\t\tif (childA.name === b.name) {\n\t\t\t\t_mergeAttrs(childA, b.attr(), b.css());\n\t\t\t\tmerged = true;\n\t\t\t}\n\t\t\tchildA = childA.first();\n\t\t}\n\t\tif (!merged) {\n\t\t\tlastA.append(b.clone(false));\n\t\t}\n\t\tmerged = false;\n\t\tb = b.first();\n\t}\n\treturn a;\n}\n\nfunction _wrapNode(knode, wrapper) {\n\twrapper = wrapper.clone(true);\n\tif (knode.type == 3) {\n\t\t_getInnerNode(wrapper).append(knode.clone(false));\n\t\tknode.replaceWith(wrapper);\n\t\treturn wrapper;\n\t}\n\tvar nodeWrapper = knode, child;\n\twhile ((child = knode.first()) && child.children().length == 1) {\n\t\tknode = child;\n\t}\n\tchild = knode.first();\n\tvar frag = knode.doc.createDocumentFragment();\n\twhile (child) {\n\t\tfrag.appendChild(child[0]);\n\t\tchild = child.next();\n\t}\n\twrapper = _mergeWrapper(nodeWrapper, wrapper);\n\tif (frag.firstChild) {\n\t\t_getInnerNode(wrapper).append(frag);\n\t}\n\tnodeWrapper.replaceWith(wrapper);\n\treturn wrapper;\n}\n\nfunction _mergeAttrs(knode, attrs, styles) {\n\t_each(attrs, function(key, val) {\n\t\tif (key !== 'style') {\n\t\t\tknode.attr(key, val);\n\t\t}\n\t});\n\t_each(styles, function(key, val) {\n\t\tknode.css(key, val);\n\t});\n}\n\nfunction _inPreElement(knode) {\n\twhile (knode && knode.name != 'body') {\n\t\tif (_PRE_TAG_MAP[knode.name] || knode.name == 'div' && knode.hasClass('ke-script')) {\n\t\t\treturn true;\n\t\t}\n\t\tknode = knode.parent();\n\t}\n\treturn false;\n}\n\nfunction KCmd(range) {\n\tthis.init(range);\n}\n_extend(KCmd, {\n\tinit : function(range) {\n\t\tvar self = this, doc = range.doc;\n\t\tself.doc = doc;\n\t\tself.win = _getWin(doc);\n\t\tself.sel = _getSel(doc);\n\t\tself.range = range;\n\t},\n\tselection : function(forceReset) {\n\t\tvar self = this, doc = self.doc, rng = _getRng(doc);\n\t\tself.sel = _getSel(doc);\n\t\tif (rng) {\n\t\t\tself.range = _range(rng);\n\t\t\tif (K(self.range.startContainer).name == 'html') {\n\t\t\t\tself.range.selectNodeContents(doc.body).collapse(false);\n\t\t\t}\n\t\t\treturn self;\n\t\t}\n\t\tif (forceReset) {\n\t\t\tself.range.selectNodeContents(doc.body).collapse(false);\n\t\t}\n\t\treturn self;\n\t},\n\tselect : function(hasDummy) {\n\t\thasDummy = _undef(hasDummy, true);\n\t\tvar self = this, sel = self.sel, range = self.range.cloneRange().shrink(),\n\t\t\tsc = range.startContainer, so = range.startOffset,\n\t\t\tec = range.endContainer, eo = range.endOffset,\n\t\t\tdoc = _getDoc(sc), win = self.win, rng, hasU200b = false;\n\t\tif (hasDummy && sc.nodeType == 1 && range.collapsed) {\n\t\t\tif (_IERANGE) {\n\t\t\t\tvar dummy = K('<span>&nbsp;</span>', doc);\n\t\t\t\trange.insertNode(dummy[0]);\n\t\t\t\trng = doc.body.createTextRange();\n\t\t\t\ttry {\n\t\t\t\t\trng.moveToElementText(dummy[0]);\n\t\t\t\t} catch(ex) {}\n\t\t\t\trng.collapse(false);\n\t\t\t\trng.select();\n\t\t\t\tdummy.remove();\n\t\t\t\twin.focus();\n\t\t\t\treturn self;\n\t\t\t}\n\t\t\tif (_WEBKIT) {\n\t\t\t\tvar children = sc.childNodes;\n\t\t\t\tif (K(sc).isInline() || so > 0 && K(children[so - 1]).isInline() || children[so] && K(children[so]).isInline()) {\n\t\t\t\t\trange.insertNode(doc.createTextNode('\\u200B'));\n\t\t\t\t\thasU200b = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (_IERANGE) {\n\t\t\ttry {\n\t\t\t\trng = range.get(true);\n\t\t\t\trng.select();\n\t\t\t} catch(e) {}\n\t\t} else {\n\t\t\tif (hasU200b) {\n\t\t\t\trange.collapse(false);\n\t\t\t}\n\t\t\trng = range.get(true);\n\t\t\tsel.removeAllRanges();\n\t\t\tsel.addRange(rng);\n\t\t\tif (doc !== document) {\n\t\t\t\tvar pos = K(rng.endContainer).pos();\n\t\t\t\twin.scrollTo(pos.x, pos.y);\n\t\t\t}\n\t\t}\n\t\twin.focus();\n\t\treturn self;\n\t},\n\twrap : function(val) {\n\t\tvar self = this, doc = self.doc, range = self.range, wrapper;\n\t\twrapper = K(val, doc);\n\t\tif (range.collapsed) {\n\t\t\trange.shrink();\n\t\t\trange.insertNode(wrapper[0]).selectNodeContents(wrapper[0]);\n\t\t\treturn self;\n\t\t}\n\t\tif (wrapper.isBlock()) {\n\t\t\tvar copyWrapper = wrapper.clone(true), child = copyWrapper;\n\t\t\twhile (child.first()) {\n\t\t\t\tchild = child.first();\n\t\t\t}\n\t\t\tchild.append(range.extractContents());\n\t\t\trange.insertNode(copyWrapper[0]).selectNode(copyWrapper[0]);\n\t\t\treturn self;\n\t\t}\n\t\trange.enlarge();\n\t\tvar bookmark = range.createBookmark(), ancestor = range.commonAncestor(), isStart = false;\n\t\tK(ancestor).scan(function(node) {\n\t\t\tif (!isStart && node == bookmark.start) {\n\t\t\t\tisStart = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (isStart) {\n\t\t\t\tif (node == bookmark.end) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tvar knode = K(node);\n\t\t\t\tif (_inPreElement(knode)) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (knode.type == 3 && _trim(node.nodeValue).length > 0) {\n\t\t\t\t\tvar parent;\n\t\t\t\t\twhile ((parent = knode.parent()) && parent.isStyle() && parent.children().length == 1) {\n\t\t\t\t\t\tknode = parent;\n\t\t\t\t\t}\n\t\t\t\t\t_wrapNode(knode, wrapper);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\trange.moveToBookmark(bookmark);\n\t\treturn self;\n\t},\n\tsplit : function(isStart, map) {\n\t\tvar range = this.range, doc = range.doc;\n\t\tvar tempRange = range.cloneRange().collapse(isStart);\n\t\tvar node = tempRange.startContainer, pos = tempRange.startOffset,\n\t\t\tparent = node.nodeType == 3 ? node.parentNode : node,\n\t\t\tneedSplit = false, knode;\n\t\twhile (parent && parent.parentNode) {\n\t\t\tknode = K(parent);\n\t\t\tif (map) {\n\t\t\t\tif (!knode.isStyle()) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!_hasAttrOrCss(knode, map)) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (_NOSPLIT_TAG_MAP[knode.name]) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tneedSplit = true;\n\t\t\tparent = parent.parentNode;\n\t\t}\n\t\tif (needSplit) {\n\t\t\tvar dummy = doc.createElement('span');\n\t\t\trange.cloneRange().collapse(!isStart).insertNode(dummy);\n\t\t\tif (isStart) {\n\t\t\t\ttempRange.setStartBefore(parent.firstChild).setEnd(node, pos);\n\t\t\t} else {\n\t\t\t\ttempRange.setStart(node, pos).setEndAfter(parent.lastChild);\n\t\t\t}\n\t\t\tvar frag = tempRange.extractContents(),\n\t\t\t\tfirst = frag.firstChild, last = frag.lastChild;\n\t\t\tif (isStart) {\n\t\t\t\ttempRange.insertNode(frag);\n\t\t\t\trange.setStartAfter(last).setEndBefore(dummy);\n\t\t\t} else {\n\t\t\t\tparent.appendChild(frag);\n\t\t\t\trange.setStartBefore(dummy).setEndBefore(first);\n\t\t\t}\n\t\t\tvar dummyParent = dummy.parentNode;\n\t\t\tif (dummyParent == range.endContainer) {\n\t\t\t\tvar prev = K(dummy).prev(), next = K(dummy).next();\n\t\t\t\tif (prev && next && prev.type == 3 && next.type == 3) {\n\t\t\t\t\trange.setEnd(prev[0], prev[0].nodeValue.length);\n\t\t\t\t} else if (!isStart) {\n\t\t\t\t\trange.setEnd(range.endContainer, range.endOffset - 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdummyParent.removeChild(dummy);\n\t\t}\n\t\treturn this;\n\t},\n\tremove : function(map) {\n\t\tvar self = this, doc = self.doc, range = self.range;\n\t\trange.enlarge();\n\t\tif (range.startOffset === 0) {\n\t\t\tvar ksc = K(range.startContainer), parent;\n\t\t\twhile ((parent = ksc.parent()) && parent.isStyle() && parent.children().length == 1) {\n\t\t\t\tksc = parent;\n\t\t\t}\n\t\t\trange.setStart(ksc[0], 0);\n\t\t\tksc = K(range.startContainer);\n\t\t\tif (ksc.isBlock()) {\n\t\t\t\t_removeAttrOrCss(ksc, map);\n\t\t\t}\n\t\t\tvar kscp = ksc.parent();\n\t\t\tif (kscp && kscp.isBlock()) {\n\t\t\t\t_removeAttrOrCss(kscp, map);\n\t\t\t}\n\t\t}\n\t\tvar sc, so;\n\t\tif (range.collapsed) {\n\t\t\tself.split(true, map);\n\t\t\tsc = range.startContainer;\n\t\t\tso = range.startOffset;\n\t\t\tif (so > 0) {\n\t\t\t\tvar sb = K(sc.childNodes[so - 1]);\n\t\t\t\tif (sb && _isEmptyNode(sb)) {\n\t\t\t\t\tsb.remove();\n\t\t\t\t\trange.setStart(sc, so - 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar sa = K(sc.childNodes[so]);\n\t\t\tif (sa && _isEmptyNode(sa)) {\n\t\t\t\tsa.remove();\n\t\t\t}\n\t\t\tif (_isEmptyNode(sc)) {\n\t\t\t\trange.startBefore(sc);\n\t\t\t\tsc.remove();\n\t\t\t}\n\t\t\trange.collapse(true);\n\t\t\treturn self;\n\t\t}\n\t\tself.split(true, map);\n\t\tself.split(false, map);\n\t\tvar startDummy = doc.createElement('span'), endDummy = doc.createElement('span');\n\t\trange.cloneRange().collapse(false).insertNode(endDummy);\n\t\trange.cloneRange().collapse(true).insertNode(startDummy);\n\t\tvar nodeList = [], cmpStart = false;\n\t\tK(range.commonAncestor()).scan(function(node) {\n\t\t\tif (!cmpStart && node == startDummy) {\n\t\t\t\tcmpStart = true;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (node == endDummy) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (cmpStart) {\n\t\t\t\tnodeList.push(node);\n\t\t\t}\n\t\t});\n\t\tK(startDummy).remove();\n\t\tK(endDummy).remove();\n\t\tsc = range.startContainer;\n\t\tso = range.startOffset;\n\t\tvar ec = range.endContainer, eo = range.endOffset;\n\t\tif (so > 0) {\n\t\t\tvar startBefore = K(sc.childNodes[so - 1]);\n\t\t\tif (startBefore && _isEmptyNode(startBefore)) {\n\t\t\t\tstartBefore.remove();\n\t\t\t\trange.setStart(sc, so - 1);\n\t\t\t\tif (sc == ec) {\n\t\t\t\t\trange.setEnd(ec, eo - 1);\n\t\t\t\t}\n\t\t\t}\n\t\t\tvar startAfter = K(sc.childNodes[so]);\n\t\t\tif (startAfter && _isEmptyNode(startAfter)) {\n\t\t\t\tstartAfter.remove();\n\t\t\t\tif (sc == ec) {\n\t\t\t\t\trange.setEnd(ec, eo - 1);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tvar endAfter = K(ec.childNodes[range.endOffset]);\n\t\tif (endAfter && _isEmptyNode(endAfter)) {\n\t\t\tendAfter.remove();\n\t\t}\n\t\tvar bookmark = range.createBookmark(true);\n\t\t_each(nodeList, function(i, node) {\n\t\t\t_removeAttrOrCss(K(node), map);\n\t\t});\n\t\trange.moveToBookmark(bookmark);\n\t\treturn self;\n\t},\n\tcommonNode : function(map) {\n\t\tvar range = this.range;\n\t\tvar ec = range.endContainer, eo = range.endOffset,\n\t\t\tnode = (ec.nodeType == 3 || eo === 0) ? ec : ec.childNodes[eo - 1];\n\t\tfunction find(node) {\n\t\t\tvar child = node, parent = node;\n\t\t\twhile (parent) {\n\t\t\t\tif (_hasAttrOrCss(K(parent), map)) {\n\t\t\t\t\treturn K(parent);\n\t\t\t\t}\n\t\t\t\tparent = parent.parentNode;\n\t\t\t}\n\t\t\twhile (child && (child = child.lastChild)) {\n\t\t\t\tif (_hasAttrOrCss(K(child), map)) {\n\t\t\t\t\treturn K(child);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\tvar cNode = find(node);\n\t\tif (cNode) {\n\t\t\treturn cNode;\n\t\t}\n\t\tif (node.nodeType == 1 || (ec.nodeType == 3 && eo === 0)) {\n\t\t\tvar prev = K(node).prev();\n\t\t\tif (prev) {\n\t\t\t\treturn find(prev);\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t},\n\tcommonAncestor : function(tagName) {\n\t\tvar range = this.range,\n\t\t\tsc = range.startContainer, so = range.startOffset,\n\t\t\tec = range.endContainer, eo = range.endOffset,\n\t\t\tstartNode = (sc.nodeType == 3 || so === 0) ? sc : sc.childNodes[so - 1],\n\t\t\tendNode = (ec.nodeType == 3 || eo === 0) ? ec : ec.childNodes[eo - 1];\n\t\tfunction find(node) {\n\t\t\twhile (node) {\n\t\t\t\tif (node.nodeType == 1) {\n\t\t\t\t\tif (node.tagName.toLowerCase() === tagName) {\n\t\t\t\t\t\treturn node;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tnode = node.parentNode;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t\tvar start = find(startNode), end = find(endNode);\n\t\tif (start && end && start === end) {\n\t\t\treturn K(start);\n\t\t}\n\t\treturn null;\n\t},\n\tstate : function(key) {\n\t\tvar self = this, doc = self.doc, bool = false;\n\t\ttry {\n\t\t\tbool = doc.queryCommandState(key);\n\t\t} catch (e) {}\n\t\treturn bool;\n\t},\n\tval : function(key) {\n\t\tvar self = this, doc = self.doc, range = self.range;\n\t\tfunction lc(val) {\n\t\t\treturn val.toLowerCase();\n\t\t}\n\t\tkey = lc(key);\n\t\tvar val = '', knode;\n\t\tif (key === 'fontfamily' || key === 'fontname') {\n\t\t\tval = _nativeCommandValue(doc, 'fontname');\n\t\t\tval = val.replace(/['\"]/g, '');\n\t\t\treturn lc(val);\n\t\t}\n\t\tif (key === 'formatblock') {\n\t\t\tval = _nativeCommandValue(doc, key);\n\t\t\tif (val === '') {\n\t\t\t\tknode = self.commonNode({'h1,h2,h3,h4,h5,h6,p,div,pre,address' : '*'});\n\t\t\t\tif (knode) {\n\t\t\t\t\tval = knode.name;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (val === 'Normal') {\n\t\t\t\tval = 'p';\n\t\t\t}\n\t\t\treturn lc(val);\n\t\t}\n\t\tif (key === 'fontsize') {\n\t\t\tknode = self.commonNode({'*' : '.font-size'});\n\t\t\tif (knode) {\n\t\t\t\tval = knode.css('font-size');\n\t\t\t}\n\t\t\treturn lc(val);\n\t\t}\n\t\tif (key === 'forecolor') {\n\t\t\tknode = self.commonNode({'*' : '.color'});\n\t\t\tif (knode) {\n\t\t\t\tval = knode.css('color');\n\t\t\t}\n\t\t\tval = _toHex(val);\n\t\t\tif (val === '') {\n\t\t\t\tval = 'default';\n\t\t\t}\n\t\t\treturn lc(val);\n\t\t}\n\t\tif (key === 'hilitecolor') {\n\t\t\tknode = self.commonNode({'*' : '.background-color'});\n\t\t\tif (knode) {\n\t\t\t\tval = knode.css('background-color');\n\t\t\t}\n\t\t\tval = _toHex(val);\n\t\t\tif (val === '') {\n\t\t\t\tval = 'default';\n\t\t\t}\n\t\t\treturn lc(val);\n\t\t}\n\t\treturn val;\n\t},\n\ttoggle : function(wrapper, map) {\n\t\tvar self = this;\n\t\tif (self.commonNode(map)) {\n\t\t\tself.remove(map);\n\t\t} else {\n\t\t\tself.wrap(wrapper);\n\t\t}\n\t\treturn self.select();\n\t},\n\tbold : function() {\n\t\treturn this.toggle('<strong></strong>', {\n\t\t\tspan : '.font-weight=bold',\n\t\t\tstrong : '*',\n\t\t\tb : '*'\n\t\t});\n\t},\n\titalic : function() {\n\t\treturn this.toggle('<em></em>', {\n\t\t\tspan : '.font-style=italic',\n\t\t\tem : '*',\n\t\t\ti : '*'\n\t\t});\n\t},\n\tunderline : function() {\n\t\treturn this.toggle('<u></u>', {\n\t\t\tspan : '.text-decoration=underline',\n\t\t\tu : '*'\n\t\t});\n\t},\n\tstrikethrough : function() {\n\t\treturn this.toggle('<s></s>', {\n\t\t\tspan : '.text-decoration=line-through',\n\t\t\ts : '*'\n\t\t});\n\t},\n\tforecolor : function(val) {\n\t\treturn this.wrap('<span style=\"color:' + val + ';\"></span>').select();\n\t},\n\thilitecolor : function(val) {\n\t\treturn this.wrap('<span style=\"background-color:' + val + ';\"></span>').select();\n\t},\n\tfontsize : function(val) {\n\t\treturn this.wrap('<span style=\"font-size:' + val + ';\"></span>').select();\n\t},\n\tfontname : function(val) {\n\t\treturn this.fontfamily(val);\n\t},\n\tfontfamily : function(val) {\n\t\treturn this.wrap('<span style=\"font-family:' + val + ';\"></span>').select();\n\t},\n\tremoveformat : function() {\n\t\tvar map = {\n\t\t\t'*' : '.font-weight,.font-style,.text-decoration,.color,.background-color,.font-size,.font-family,.text-indent'\n\t\t},\n\t\ttags = _STYLE_TAG_MAP;\n\t\t_each(tags, function(key, val) {\n\t\t\tmap[key] = '*';\n\t\t});\n\t\tthis.remove(map);\n\t\treturn this.select();\n\t},\n\tinserthtml : function(val, quickMode) {\n\t\tvar self = this, range = self.range;\n\t\tif (val === '') {\n\t\t\treturn self;\n\t\t}\n\t\tfunction pasteHtml(range, val) {\n\t\t\tval = '<img id=\"__kindeditor_temp_tag__\" width=\"0\" height=\"0\" style=\"display:none;\" />' + val;\n\t\t\tvar rng = range.get();\n\t\t\tif (rng.item) {\n\t\t\t\trng.item(0).outerHTML = val;\n\t\t\t} else {\n\t\t\t\trng.pasteHTML(val);\n\t\t\t}\n\t\t\tvar temp = range.doc.getElementById('__kindeditor_temp_tag__');\n\t\t\ttemp.parentNode.removeChild(temp);\n\t\t\tvar newRange = _toRange(rng);\n\t\t\trange.setEnd(newRange.endContainer, newRange.endOffset);\n\t\t\trange.collapse(false);\n\t\t\tself.select(false);\n\t\t}\n\t\tfunction insertHtml(range, val) {\n\t\t\tvar doc = range.doc,\n\t\t\t\tfrag = doc.createDocumentFragment();\n\t\t\tK('@' + val, doc).each(function() {\n\t\t\t\tfrag.appendChild(this);\n\t\t\t});\n\t\t\trange.deleteContents();\n\t\t\trange.insertNode(frag);\n\t\t\trange.collapse(false);\n\t\t\tself.select(false);\n\t\t}\n\t\tif (_IERANGE && quickMode) {\n\t\t\ttry {\n\t\t\t\tpasteHtml(range, val);\n\t\t\t} catch(e) {\n\t\t\t\tinsertHtml(range, val);\n\t\t\t}\n\t\t\treturn self;\n\t\t}\n\t\tinsertHtml(range, val);\n\t\treturn self;\n\t},\n\thr : function() {\n\t\treturn this.inserthtml('<hr />');\n\t},\n\tprint : function() {\n\t\tthis.win.print();\n\t\treturn this;\n\t},\n\tinsertimage : function(url, title, width, height, border, align) {\n\t\ttitle = _undef(title, '');\n\t\tborder = _undef(border, 0);\n\t\tvar html = '<img src=\"' + _escape(url) + '\" data-ke-src=\"' + _escape(url) + '\" ';\n\t\tif (width) {\n\t\t\thtml += 'width=\"' + _escape(width) + '\" ';\n\t\t}\n\t\tif (height) {\n\t\t\thtml += 'height=\"' + _escape(height) + '\" ';\n\t\t}\n\t\tif (title) {\n\t\t\thtml += 'title=\"' + _escape(title) + '\" ';\n\t\t}\n\t\tif (align) {\n\t\t\thtml += 'align=\"' + _escape(align) + '\" ';\n\t\t}\n\t\thtml += 'alt=\"' + _escape(title) + '\" ';\n\t\thtml += '/>';\n\t\treturn this.inserthtml(html);\n\t},\n\tcreatelink : function(url, type) {\n\t\tvar self = this, doc = self.doc, range = self.range;\n\t\tself.select();\n\t\tvar a = self.commonNode({ a : '*' });\n\t\tif (a && !range.isControl()) {\n\t\t\trange.selectNode(a.get());\n\t\t\tself.select();\n\t\t}\n\t\tvar html = '<a href=\"' + _escape(url) + '\" data-ke-src=\"' + _escape(url) + '\" ';\n\t\tif (type) {\n\t\t\thtml += ' target=\"' + _escape(type) + '\"';\n\t\t}\n\t\tif (range.collapsed) {\n\t\t\thtml += '>' + _escape(url) + '</a>';\n\t\t\treturn self.inserthtml(html);\n\t\t}\n\t\tif (range.isControl()) {\n\t\t\tvar node = K(range.startContainer.childNodes[range.startOffset]);\n\t\t\thtml += '></a>';\n\t\t\tnode.after(K(html, doc));\n\t\t\tnode.next().append(node);\n\t\t\trange.selectNode(node[0]);\n\t\t\treturn self.select();\n\t\t}\n\t\tfunction setAttr(node, url, type) {\n\t\t\tK(node).attr('href', url).attr('data-ke-src', url);\n\t\t\tif (type) {\n\t\t\t\tK(node).attr('target', type);\n\t\t\t} else {\n\t\t\t\tK(node).removeAttr('target');\n\t\t\t}\n\t\t}\n\t\tvar sc = range.startContainer, so = range.startOffset,\n\t\t\tec = range.endContainer, eo = range.endOffset;\n\t\tif (sc.nodeType == 1 && sc === ec && so + 1 === eo) {\n\t\t\tvar child = sc.childNodes[so];\n\t\t\tif (child.nodeName.toLowerCase() == 'a') {\n\t\t\t\tsetAttr(child, url, type);\n\t\t\t\treturn self;\n\t\t\t}\n\t\t}\n\t\t_nativeCommand(doc, 'createlink', '__kindeditor_temp_url__');\n\t\tK('a[href=\"__kindeditor_temp_url__\"]', doc).each(function() {\n\t\t\tsetAttr(this, url, type);\n\t\t});\n\t\treturn self;\n\t},\n\tunlink : function() {\n\t\tvar self = this, doc = self.doc, range = self.range;\n\t\tself.select();\n\t\tif (range.collapsed) {\n\t\t\tvar a = self.commonNode({ a : '*' });\n\t\t\tif (a) {\n\t\t\t\trange.selectNode(a.get());\n\t\t\t\tself.select();\n\t\t\t}\n\t\t\t_nativeCommand(doc, 'unlink', null);\n\t\t\tif (_WEBKIT && K(range.startContainer).name === 'img') {\n\t\t\t\tvar parent = K(range.startContainer).parent();\n\t\t\t\tif (parent.name === 'a') {\n\t\t\t\t\tparent.remove(true);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t_nativeCommand(doc, 'unlink', null);\n\t\t}\n\t\treturn self;\n\t}\n});\n_each(('formatblock,selectall,justifyleft,justifycenter,justifyright,justifyfull,insertorderedlist,' +\n\t'insertunorderedlist,indent,outdent,subscript,superscript').split(','), function(i, name) {\n\tKCmd.prototype[name] = function(val) {\n\t\tvar self = this;\n\t\tself.select();\n\t\t_nativeCommand(self.doc, name, val);\n\t\tif (_IERANGE && _inArray(name, 'justifyleft,justifycenter,justifyright,justifyfull'.split(',')) >= 0) {\n\t\t\tself.selection();\n\t\t}\n\t\tif (!_IERANGE || _inArray(name, 'formatblock,selectall,insertorderedlist,insertunorderedlist'.split(',')) >= 0) {\n\t\t\tself.selection();\n\t\t}\n\t\treturn self;\n\t};\n});\n_each('cut,copy,paste'.split(','), function(i, name) {\n\tKCmd.prototype[name] = function() {\n\t\tvar self = this;\n\t\tif (!self.doc.queryCommandSupported(name)) {\n\t\t\tthrow 'not supported';\n\t\t}\n\t\tself.select();\n\t\t_nativeCommand(self.doc, name, null);\n\t\treturn self;\n\t};\n});\nfunction _cmd(mixed) {\n\tif (mixed.nodeName) {\n\t\tvar doc = _getDoc(mixed);\n\t\tmixed = _range(doc).selectNodeContents(doc.body).collapse(false);\n\t}\n\treturn new KCmd(mixed);\n}\nK.CmdClass = KCmd;\nK.cmd = _cmd;\n\n\nfunction _drag(options) {\n\tvar moveEl = options.moveEl,\n\t\tmoveFn = options.moveFn,\n\t\tclickEl = options.clickEl || moveEl,\n\t\tbeforeDrag = options.beforeDrag,\n\t\tiframeFix = options.iframeFix === undefined ? true : options.iframeFix;\n\tvar docs = [document];\n\tif (iframeFix) {\n\t\tK('iframe').each(function() {\n\t\t\tvar src = _formatUrl(this.src || '', 'absolute');\n\t\t\tif (/^https?:\\/\\//.test(src)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar doc;\n\t\t\ttry {\n\t\t\t\tdoc = _iframeDoc(this);\n\t\t\t} catch(e) {}\n\t\t\tif (doc) {\n\t\t\t\tvar pos = K(this).pos();\n\t\t\t\tK(doc).data('pos-x', pos.x);\n\t\t\t\tK(doc).data('pos-y', pos.y);\n\t\t\t\tdocs.push(doc);\n\t\t\t}\n\t\t});\n\t}\n\tclickEl.mousedown(function(e) {\n\t\tif(e.button !== 0 && e.button !== 1) {\n\t\t\treturn;\n\t\t}\n\t\te.stopPropagation();\n\t\tvar self = clickEl.get(),\n\t\t\tx = _removeUnit(moveEl.css('left')),\n\t\t\ty = _removeUnit(moveEl.css('top')),\n\t\t\twidth = moveEl.width(),\n\t\t\theight = moveEl.height(),\n\t\t\tpageX = e.pageX,\n\t\t\tpageY = e.pageY;\n\t\tif (beforeDrag) {\n\t\t\tbeforeDrag();\n\t\t}\n\t\tfunction moveListener(e) {\n\t\t\te.preventDefault();\n\t\t\tvar kdoc = K(_getDoc(e.target));\n\t\t\tvar diffX = _round((kdoc.data('pos-x') || 0) + e.pageX - pageX);\n\t\t\tvar diffY = _round((kdoc.data('pos-y') || 0) + e.pageY - pageY);\n\t\t\tmoveFn.call(clickEl, x, y, width, height, diffX, diffY);\n\t\t}\n\t\tfunction selectListener(e) {\n\t\t\te.preventDefault();\n\t\t}\n\t\tfunction upListener(e) {\n\t\t\te.preventDefault();\n\t\t\tK(docs).unbind('mousemove', moveListener)\n\t\t\t\t.unbind('mouseup', upListener)\n\t\t\t\t.unbind('selectstart', selectListener);\n\t\t\tif (self.releaseCapture) {\n\t\t\t\tself.releaseCapture();\n\t\t\t}\n\t\t}\n\t\tK(docs).mousemove(moveListener)\n\t\t\t.mouseup(upListener)\n\t\t\t.bind('selectstart', selectListener);\n\t\tif (self.setCapture) {\n\t\t\tself.setCapture();\n\t\t}\n\t});\n}\n\n\nfunction KWidget(options) {\n\tthis.init(options);\n}\n_extend(KWidget, {\n\tinit : function(options) {\n\t\tvar self = this;\n\t\tself.name = options.name || '';\n\t\tself.doc = options.doc || document;\n\t\tself.win = _getWin(self.doc);\n\t\tself.x = _addUnit(options.x);\n\t\tself.y = _addUnit(options.y);\n\t\tself.z = options.z;\n\t\tself.width = _addUnit(options.width);\n\t\tself.height = _addUnit(options.height);\n\t\tself.div = K('<div style=\"display:block;\"></div>');\n\t\tself.options = options;\n\t\tself._alignEl = options.alignEl;\n\t\tif (self.width) {\n\t\t\tself.div.css('width', self.width);\n\t\t}\n\t\tif (self.height) {\n\t\t\tself.div.css('height', self.height);\n\t\t}\n\t\tif (self.z) {\n\t\t\tself.div.css({\n\t\t\t\tposition : 'absolute',\n\t\t\t\tleft : self.x,\n\t\t\t\ttop : self.y,\n\t\t\t\t'z-index' : self.z\n\t\t\t});\n\t\t}\n\t\tif (self.z && (self.x === undefined || self.y === undefined)) {\n\t\t\tself.autoPos(self.width, self.height);\n\t\t}\n\t\tif (options.cls) {\n\t\t\tself.div.addClass(options.cls);\n\t\t}\n\t\tif (options.shadowMode) {\n\t\t\tself.div.addClass('ke-shadow');\n\t\t}\n\t\tif (options.css) {\n\t\t\tself.div.css(options.css);\n\t\t}\n\t\tif (options.src) {\n\t\t\tK(options.src).replaceWith(self.div);\n\t\t} else {\n\t\t\tK(self.doc.body).append(self.div);\n\t\t}\n\t\tif (options.html) {\n\t\t\tself.div.html(options.html);\n\t\t}\n\t\tif (options.autoScroll) {\n\t\t\tif (_IE && _V < 7 || _QUIRKS) {\n\t\t\t\tvar scrollPos = _getScrollPos();\n\t\t\t\tK(self.win).bind('scroll', function(e) {\n\t\t\t\t\tvar pos = _getScrollPos(),\n\t\t\t\t\t\tdiffX = pos.x - scrollPos.x,\n\t\t\t\t\t\tdiffY = pos.y - scrollPos.y;\n\t\t\t\t\tself.pos(_removeUnit(self.x) + diffX, _removeUnit(self.y) + diffY, false);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tself.div.css('position', 'fixed');\n\t\t\t}\n\t\t}\n\t},\n\tpos : function(x, y, updateProp) {\n\t\tvar self = this;\n\t\tupdateProp = _undef(updateProp, true);\n\t\tif (x !== null) {\n\t\t\tx = x < 0 ? 0 : _addUnit(x);\n\t\t\tself.div.css('left', x);\n\t\t\tif (updateProp) {\n\t\t\t\tself.x = x;\n\t\t\t}\n\t\t}\n\t\tif (y !== null) {\n\t\t\ty = y < 0 ? 0 : _addUnit(y);\n\t\t\tself.div.css('top', y);\n\t\t\tif (updateProp) {\n\t\t\t\tself.y = y;\n\t\t\t}\n\t\t}\n\t\treturn self;\n\t},\n\tautoPos : function(width, height) {\n\t\tvar x, y, self = this,\n\t\t\tw = _removeUnit(width) || 0,\n\t\t\th = _removeUnit(height) || 0,\n\t\t\tscrollPos = _getScrollPos();\n\t\tif (self._alignEl) {\n\t\t\tvar knode = K(self._alignEl),\n\t\t\t\tpos = knode.pos(),\n\t\t\t\tdiffX = _round(knode[0].clientWidth / 2 - w / 2),\n\t\t\t\tdiffY = _round(knode[0].clientHeight / 2 - h / 2);\n\t\t\tx = diffX < 0 ? pos.x : pos.x + diffX;\n\t\t\ty = diffY < 0 ? pos.y : pos.y + diffY;\n\t\t} else {\n\t\t\tvar docEl = _docElement(self.doc);\n\t\t\tx = _round(scrollPos.x + (docEl.clientWidth - w) / 2);\n\t\t\ty = _round(scrollPos.y + (docEl.clientHeight - h) / 2);\n\t\t}\n\t\tif (!(_IE && _V < 7 || _QUIRKS)) {\n\t\t\tx -= scrollPos.x;\n\t\t\ty -= scrollPos.y;\n\t\t}\n\t\treturn self.pos(x, y);\n\t},\n\tremove : function() {\n\t\tvar self = this;\n\t\tif (_IE && _V < 7 || _QUIRKS) {\n\t\t\tK(self.win).unbind('scroll');\n\t\t}\n\t\tself.div.remove();\n\t\t_each(self, function(i) {\n\t\t\tself[i] = null;\n\t\t});\n\t\treturn this;\n\t},\n\tshow : function() {\n\t\tthis.div.show();\n\t\treturn this;\n\t},\n\thide : function() {\n\t\tthis.div.hide();\n\t\treturn this;\n\t},\n\tdraggable : function(options) {\n\t\tvar self = this;\n\t\toptions = options || {};\n\t\toptions.moveEl = self.div;\n\t\toptions.moveFn = function(x, y, width, height, diffX, diffY) {\n\t\t\tif ((x = x + diffX) < 0) {\n\t\t\t\tx = 0;\n\t\t\t}\n\t\t\tif ((y = y + diffY) < 0) {\n\t\t\t\ty = 0;\n\t\t\t}\n\t\t\tself.pos(x, y);\n\t\t};\n\t\t_drag(options);\n\t\treturn self;\n\t}\n});\nfunction _widget(options) {\n\treturn new KWidget(options);\n}\nK.WidgetClass = KWidget;\nK.widget = _widget;\n\n\nfunction _iframeDoc(iframe) {\n\tiframe = _get(iframe);\n\treturn iframe.contentDocument || iframe.contentWindow.document;\n}\nvar html, _direction = '';\nif ((html = document.getElementsByTagName('html'))) {\n\t_direction = html[0].dir;\n}\nfunction _getInitHtml(themesPath, bodyClass, cssPath, cssData) {\n\tvar arr = [\n\t\t(_direction === '' ? '<html>' : '<html dir=\"' + _direction + '\">'),\n\t\t'<head><meta charset=\"utf-8\" /><title></title>',\n\t\t'<style>',\n\t\t'html {margin:0;padding:0;}',\n\t\t'body {margin:0;padding:5px;}',\n\t\t'body, td {font:12px/1.5 \"sans serif\",tahoma,verdana,helvetica;}',\n\t\t'body, p, div {word-wrap: break-word;}',\n\t\t'p {margin:5px 0;}',\n\t\t'table {border-collapse:collapse;}',\n\t\t'img {border:0;}',\n\t\t'noscript {display:none;}',\n\t\t'table.ke-zeroborder td {border:1px dotted #AAA;}',\n\t\t'img.ke-flash {',\n\t\t'\tborder:1px solid #AAA;',\n\t\t'\tbackground-image:url(' + themesPath + 'common/flash.gif);',\n\t\t'\tbackground-position:center center;',\n\t\t'\tbackground-repeat:no-repeat;',\n\t\t'\twidth:100px;',\n\t\t'\theight:100px;',\n\t\t'}',\n\t\t'img.ke-rm {',\n\t\t'\tborder:1px solid #AAA;',\n\t\t'\tbackground-image:url(' + themesPath + 'common/rm.gif);',\n\t\t'\tbackground-position:center center;',\n\t\t'\tbackground-repeat:no-repeat;',\n\t\t'\twidth:100px;',\n\t\t'\theight:100px;',\n\t\t'}',\n\t\t'img.ke-media {',\n\t\t'\tborder:1px solid #AAA;',\n\t\t'\tbackground-image:url(' + themesPath + 'common/media.gif);',\n\t\t'\tbackground-position:center center;',\n\t\t'\tbackground-repeat:no-repeat;',\n\t\t'\twidth:100px;',\n\t\t'\theight:100px;',\n\t\t'}',\n\t\t'img.ke-anchor {',\n\t\t'\tborder:1px dashed #666;',\n\t\t'\twidth:16px;',\n\t\t'\theight:16px;',\n\t\t'}',\n\t\t'.ke-script, .ke-noscript, .ke-display-none {',\n\t\t'\tdisplay:none;',\n\t\t'\tfont-size:0;',\n\t\t'\twidth:0;',\n\t\t'\theight:0;',\n\t\t'}',\n\t\t'.ke-pagebreak {',\n\t\t'\tborder:1px dotted #AAA;',\n\t\t'\tfont-size:0;',\n\t\t'\theight:2px;',\n\t\t'}',\n\t\t'</style>'\n\t];\n\tif (!_isArray(cssPath)) {\n\t\tcssPath = [cssPath];\n\t}\n\t_each(cssPath, function(i, path) {\n\t\tif (path) {\n\t\t\tarr.push('<link href=\"' + path + '\" rel=\"stylesheet\" />');\n\t\t}\n\t});\n\tif (cssData) {\n\t\tarr.push('<style>' + cssData + '</style>');\n\t}\n\tarr.push('</head><body ' + (bodyClass ? 'class=\"' + bodyClass + '\"' : '') + '></body></html>');\n\treturn arr.join('\\n');\n}\nfunction _elementVal(knode, val) {\n\tif (knode.hasVal()) {\n\t\tif (val === undefined) {\n\t\t\tvar html = knode.val();\n\t\t\thtml = html.replace(/(<(?:p|p\\s[^>]*)>) *(<\\/p>)/ig, '');\n\t\t\treturn html;\n\t\t}\n\t\treturn knode.val(val);\n\t}\n\treturn knode.html(val);\n}\n\n\nfunction KEdit(options) {\n\tthis.init(options);\n}\n_extend(KEdit, KWidget, {\n\tinit : function(options) {\n\t\tvar self = this;\n\t\tKEdit.parent.init.call(self, options);\n\t\tself.srcElement = K(options.srcElement);\n\t\tself.div.addClass('ke-edit');\n\t\tself.designMode = _undef(options.designMode, true);\n\t\tself.beforeGetHtml = options.beforeGetHtml;\n\t\tself.beforeSetHtml = options.beforeSetHtml;\n\t\tself.afterSetHtml = options.afterSetHtml;\n\t\tvar themesPath = _undef(options.themesPath, ''),\n\t\t\tbodyClass = options.bodyClass,\n\t\t\tcssPath = options.cssPath,\n\t\t\tcssData = options.cssData,\n\t\t\tisDocumentDomain = location.protocol != 'res:' && location.host.replace(/:\\d+/, '') !== document.domain,\n\t\t\tsrcScript = ('document.open();' +\n\t\t\t\t(isDocumentDomain ? 'document.domain=\"' + document.domain + '\";' : '') +\n\t\t\t\t'document.close();'),\n\t\t\tiframeSrc = _IE ? ' src=\"javascript:void(function(){' + encodeURIComponent(srcScript) + '}())\"' : '';\n\t\tself.iframe = K('<iframe class=\"ke-edit-iframe\" hidefocus=\"true\" frameborder=\"0\"' + iframeSrc + '></iframe>').css('width', '100%');\n\t\tself.textarea = K('<textarea class=\"ke-edit-textarea\" hidefocus=\"true\"></textarea>').css('width', '100%');\n\t\tself.tabIndex = isNaN(parseInt(options.tabIndex, 10)) ? self.srcElement.attr('tabindex') : parseInt(options.tabIndex, 10);\n\t\tself.iframe.attr('tabindex', self.tabIndex);\n\t\tself.textarea.attr('tabindex', self.tabIndex);\n\t\tif (self.width) {\n\t\t\tself.setWidth(self.width);\n\t\t}\n\t\tif (self.height) {\n\t\t\tself.setHeight(self.height);\n\t\t}\n\t\tif (self.designMode) {\n\t\t\tself.textarea.hide();\n\t\t} else {\n\t\t\tself.iframe.hide();\n\t\t}\n\t\tfunction ready() {\n\t\t\tvar doc = _iframeDoc(self.iframe);\n\t\t\tdoc.open();\n\t\t\tif (isDocumentDomain) {\n\t\t\t\tdoc.domain = document.domain;\n\t\t\t}\n\t\t\tdoc.write(_getInitHtml(themesPath, bodyClass, cssPath, cssData));\n\t\t\tdoc.close();\n\t\t\tself.win = self.iframe[0].contentWindow;\n\t\t\tself.doc = doc;\n\t\t\tvar cmd = _cmd(doc);\n\t\t\tself.afterChange(function(e) {\n\t\t\t\tcmd.selection();\n\t\t\t});\n\t\t\tif (_WEBKIT) {\n\t\t\t\tK(doc).click(function(e) {\n\t\t\t\t\tif (K(e.target).name === 'img') {\n\t\t\t\t\t\tcmd.selection(true);\n\t\t\t\t\t\tcmd.range.selectNode(e.target);\n\t\t\t\t\t\tcmd.select();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (_IE) {\n\t\t\t\tself._mousedownHandler = function() {\n\t\t\t\t\tvar newRange = cmd.range.cloneRange();\n\t\t\t\t\tnewRange.shrink();\n\t\t\t\t\tif (newRange.isControl()) {\n\t\t\t\t\t\tself.blur();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tK(document).mousedown(self._mousedownHandler);\n\t\t\t\tK(doc).keydown(function(e) {\n\t\t\t\t\tif (e.which == 8) {\n\t\t\t\t\t\tcmd.selection();\n\t\t\t\t\t\tvar rng = cmd.range;\n\t\t\t\t\t\tif (rng.isControl()) {\n\t\t\t\t\t\t\trng.collapse(true);\n\t\t\t\t\t\t\tK(rng.startContainer.childNodes[rng.startOffset]).remove();\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tself.cmd = cmd;\n\t\t\tself.html(_elementVal(self.srcElement));\n\t\t\tif (_IE) {\n\t\t\t\tdoc.body.disabled = true;\n\t\t\t\tdoc.body.contentEditable = true;\n\t\t\t\tdoc.body.removeAttribute('disabled');\n\t\t\t} else {\n\t\t\t\tdoc.designMode = 'on';\n\t\t\t}\n\t\t\tif (options.afterCreate) {\n\t\t\t\toptions.afterCreate.call(self);\n\t\t\t}\n\t\t}\n\t\tif (isDocumentDomain) {\n\t\t\tself.iframe.bind('load', function(e) {\n\t\t\t\tself.iframe.unbind('load');\n\t\t\t\tif (_IE) {\n\t\t\t\t\tready();\n\t\t\t\t} else {\n\t\t\t\t\tsetTimeout(ready, 0);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tself.div.append(self.iframe);\n\t\tself.div.append(self.textarea);\n\t\tself.srcElement.hide();\n\t\t!isDocumentDomain && ready();\n\t},\n\tsetWidth : function(val) {\n\t\tvar self = this;\n\t\tval = _addUnit(val);\n\t\tself.width = val;\n\t\tself.div.css('width', val);\n\t\treturn self;\n\t},\n\tsetHeight : function(val) {\n\t\tvar self = this;\n\t\tval = _addUnit(val);\n\t\tself.height = val;\n\t\tself.div.css('height', val);\n\t\tself.iframe.css('height', val);\n\t\tif ((_IE && _V < 8) || _QUIRKS) {\n\t\t\tval = _addUnit(_removeUnit(val) - 2);\n\t\t}\n\t\tself.textarea.css('height', val);\n\t\treturn self;\n\t},\n\tremove : function() {\n\t\tvar self = this, doc = self.doc;\n\t\tK(doc.body).unbind();\n\t\tK(doc).unbind();\n\t\tK(self.win).unbind();\n\t\tif (self._mousedownHandler) {\n\t\t\tK(document).unbind('mousedown', self._mousedownHandler);\n\t\t}\n\t\t_elementVal(self.srcElement, self.html());\n\t\tself.srcElement.show();\n\t\tself.iframe.unbind();\n\t\tself.textarea.unbind();\n\t\tKEdit.parent.remove.call(self);\n\t},\n\thtml : function(val, isFull) {\n\t\tvar self = this, doc = self.doc;\n\t\tif (self.designMode) {\n\t\t\tvar body = doc.body;\n\t\t\tif (val === undefined) {\n\t\t\t\tif (isFull) {\n\t\t\t\t\tval = '<!doctype html><html>' + body.parentNode.innerHTML + '</html>';\n\t\t\t\t} else {\n\t\t\t\t\tval = body.innerHTML;\n\t\t\t\t}\n\t\t\t\tif (self.beforeGetHtml) {\n\t\t\t\t\tval = self.beforeGetHtml(val);\n\t\t\t\t}\n\t\t\t\tif (_GECKO && val == '<br />') {\n\t\t\t\t\tval = '';\n\t\t\t\t}\n\t\t\t\treturn val;\n\t\t\t}\n\t\t\tif (self.beforeSetHtml) {\n\t\t\t\tval = self.beforeSetHtml(val);\n\t\t\t}\n\t\t\tif (_IE && _V >= 9) {\n\t\t\t\tval = val.replace(/(<.*?checked=\")checked(\".*>)/ig, '$1$2');\n\t\t\t}\n\t\t\tK(body).html(val);\n\t\t\tif (self.afterSetHtml) {\n\t\t\t\tself.afterSetHtml();\n\t\t\t}\n\t\t\treturn self;\n\t\t}\n\t\tif (val === undefined) {\n\t\t\treturn self.textarea.val();\n\t\t}\n\t\tself.textarea.val(val);\n\t\treturn self;\n\t},\n\tdesign : function(bool) {\n\t\tvar self = this, val;\n\t\tif (bool === undefined ? !self.designMode : bool) {\n\t\t\tif (!self.designMode) {\n\t\t\t\tval = self.html();\n\t\t\t\tself.designMode = true;\n\t\t\t\tself.textarea.hide();\n\t\t\t\tself.html(val);\n\t\t\t\tvar iframe = self.iframe;\n\t\t\t\tvar height = _removeUnit(self.height);\n\t\t\t\tiframe.height(height - 2);\n\t\t\t\tiframe.show();\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tiframe.height(height);\n\t\t\t\t}, 0);\n\t\t\t}\n\t\t} else {\n\t\t\tif (self.designMode) {\n\t\t\t\tval = self.html();\n\t\t\t\tself.designMode = false;\n\t\t\t\tself.html(val);\n\t\t\t\tself.iframe.hide();\n\t\t\t\tself.textarea.show();\n\t\t\t}\n\t\t}\n\t\treturn self.focus();\n\t},\n\tfocus : function() {\n\t\tvar self = this;\n\t\tself.designMode ? self.win.focus() : self.textarea[0].focus();\n\t\treturn self;\n\t},\n\tblur : function() {\n\t\tvar self = this;\n\t\tif (_IE) {\n\t\t\tvar input = K('<input type=\"text\" style=\"float:left;width:0;height:0;padding:0;margin:0;border:0;\" value=\"\" />', self.div);\n\t\t\tself.div.append(input);\n\t\t\tinput[0].focus();\n\t\t\tinput.remove();\n\t\t} else {\n\t\t\tself.designMode ? self.win.blur() : self.textarea[0].blur();\n\t\t}\n\t\treturn self;\n\t},\n\tafterChange : function(fn) {\n\t\tvar self = this, doc = self.doc, body = doc.body;\n\t\tK(doc).keyup(function(e) {\n\t\t\tif (!e.ctrlKey && !e.altKey && _CHANGE_KEY_MAP[e.which]) {\n\t\t\t\tfn(e);\n\t\t\t}\n\t\t});\n\t\tK(doc).mouseup(fn).contextmenu(fn);\n\t\tK(self.win).blur(fn);\n\t\tfunction timeoutHandler(e) {\n\t\t\tsetTimeout(function() {\n\t\t\t\tfn(e);\n\t\t\t}, 1);\n\t\t}\n\t\tK(body).bind('paste', timeoutHandler);\n\t\tK(body).bind('cut', timeoutHandler);\n\t\treturn self;\n\t}\n});\nfunction _edit(options) {\n\treturn new KEdit(options);\n}\nK.EditClass = KEdit;\nK.edit = _edit;\nK.iframeDoc = _iframeDoc;\n\n\nfunction _selectToolbar(name, fn) {\n\tvar self = this,\n\t\tknode = self.get(name);\n\tif (knode) {\n\t\tif (knode.hasClass('ke-disabled')) {\n\t\t\treturn;\n\t\t}\n\t\tfn(knode);\n\t}\n}\n\n\nfunction KToolbar(options) {\n\tthis.init(options);\n}\n_extend(KToolbar, KWidget, {\n\tinit : function(options) {\n\t\tvar self = this;\n\t\tKToolbar.parent.init.call(self, options);\n\t\tself.disableMode = _undef(options.disableMode, false);\n\t\tself.noDisableItemMap = _toMap(_undef(options.noDisableItems, []));\n\t\tself._itemMap = {};\n\t\tself.div.addClass('ke-toolbar').bind('contextmenu,mousedown,mousemove', function(e) {\n\t\t\te.preventDefault();\n\t\t}).attr('unselectable', 'on');\n\t\tfunction find(target) {\n\t\t\tvar knode = K(target);\n\t\t\tif (knode.hasClass('ke-outline')) {\n\t\t\t\treturn knode;\n\t\t\t}\n\t\t\tif (knode.hasClass('ke-toolbar-icon')) {\n\t\t\t\treturn knode.parent();\n\t\t\t}\n\t\t}\n\t\tfunction hover(e, method) {\n\t\t\tvar knode = find(e.target);\n\t\t\tif (knode) {\n\t\t\t\tif (knode.hasClass('ke-disabled')) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (knode.hasClass('ke-selected')) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tknode[method]('ke-on');\n\t\t\t}\n\t\t}\n\t\tself.div.mouseover(function(e) {\n\t\t\thover(e, 'addClass');\n\t\t})\n\t\t.mouseout(function(e) {\n\t\t\thover(e, 'removeClass');\n\t\t})\n\t\t.click(function(e) {\n\t\t\tvar knode = find(e.target);\n\t\t\tif (knode) {\n\t\t\t\tif (knode.hasClass('ke-disabled')) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tself.options.click.call(this, e, knode.attr('data-name'));\n\t\t\t}\n\t\t});\n\t},\n\tget : function(name) {\n\t\tif (this._itemMap[name]) {\n\t\t\treturn this._itemMap[name];\n\t\t}\n\t\treturn (this._itemMap[name] = K('span.ke-icon-' + name, this.div).parent());\n\t},\n\tselect : function(name) {\n\t\t_selectToolbar.call(this, name, function(knode) {\n\t\t\tknode.addClass('ke-selected');\n\t\t});\n\t\treturn self;\n\t},\n\tunselect : function(name) {\n\t\t_selectToolbar.call(this, name, function(knode) {\n\t\t\tknode.removeClass('ke-selected').removeClass('ke-on');\n\t\t});\n\t\treturn self;\n\t},\n\tenable : function(name) {\n\t\tvar self = this,\n\t\t\tknode = name.get ? name : self.get(name);\n\t\tif (knode) {\n\t\t\tknode.removeClass('ke-disabled');\n\t\t\tknode.opacity(1);\n\t\t}\n\t\treturn self;\n\t},\n\tdisable : function(name) {\n\t\tvar self = this,\n\t\t\tknode = name.get ? name : self.get(name);\n\t\tif (knode) {\n\t\t\tknode.removeClass('ke-selected').addClass('ke-disabled');\n\t\t\tknode.opacity(0.5);\n\t\t}\n\t\treturn self;\n\t},\n\tdisableAll : function(bool, noDisableItems) {\n\t\tvar self = this, map = self.noDisableItemMap, item;\n\t\tif (noDisableItems) {\n\t\t\tmap = _toMap(noDisableItems);\n\t\t}\n\t\tif (bool === undefined ? !self.disableMode : bool) {\n\t\t\tK('span.ke-outline', self.div).each(function() {\n\t\t\t\tvar knode = K(this),\n\t\t\t\t\tname = knode[0].getAttribute('data-name', 2);\n\t\t\t\tif (!map[name]) {\n\t\t\t\t\tself.disable(knode);\n\t\t\t\t}\n\t\t\t});\n\t\t\tself.disableMode = true;\n\t\t} else {\n\t\t\tK('span.ke-outline', self.div).each(function() {\n\t\t\t\tvar knode = K(this),\n\t\t\t\t\tname = knode[0].getAttribute('data-name', 2);\n\t\t\t\tif (!map[name]) {\n\t\t\t\t\tself.enable(knode);\n\t\t\t\t}\n\t\t\t});\n\t\t\tself.disableMode = false;\n\t\t}\n\t\treturn self;\n\t}\n});\nfunction _toolbar(options) {\n\treturn new KToolbar(options);\n}\nK.ToolbarClass = KToolbar;\nK.toolbar = _toolbar;\n\n\n\nfunction KMenu(options) {\n\tthis.init(options);\n}\n_extend(KMenu, KWidget, {\n\tinit : function(options) {\n\t\tvar self = this;\n\t\toptions.z = options.z || 811213;\n\t\tKMenu.parent.init.call(self, options);\n\t\tself.centerLineMode = _undef(options.centerLineMode, true);\n\t\tself.div.addClass('ke-menu').bind('click,mousedown', function(e){\n\t\t\te.stopPropagation();\n\t\t}).attr('unselectable', 'on');\n\t},\n\taddItem : function(item) {\n\t\tvar self = this;\n\t\tif (item.title === '-') {\n\t\t\tself.div.append(K('<div class=\"ke-menu-separator\"></div>'));\n\t\t\treturn;\n\t\t}\n\t\tvar itemDiv = K('<div class=\"ke-menu-item\" unselectable=\"on\"></div>'),\n\t\t\tleftDiv = K('<div class=\"ke-inline-block ke-menu-item-left\"></div>'),\n\t\t\trightDiv = K('<div class=\"ke-inline-block ke-menu-item-right\"></div>'),\n\t\t\theight = _addUnit(item.height),\n\t\t\ticonClass = _undef(item.iconClass, '');\n\t\tself.div.append(itemDiv);\n\t\tif (height) {\n\t\t\titemDiv.css('height', height);\n\t\t\trightDiv.css('line-height', height);\n\t\t}\n\t\tvar centerDiv;\n\t\tif (self.centerLineMode) {\n\t\t\tcenterDiv = K('<div class=\"ke-inline-block ke-menu-item-center\"></div>');\n\t\t\tif (height) {\n\t\t\t\tcenterDiv.css('height', height);\n\t\t\t}\n\t\t}\n\t\titemDiv.mouseover(function(e) {\n\t\t\tK(this).addClass('ke-menu-item-on');\n\t\t\tif (centerDiv) {\n\t\t\t\tcenterDiv.addClass('ke-menu-item-center-on');\n\t\t\t}\n\t\t})\n\t\t.mouseout(function(e) {\n\t\t\tK(this).removeClass('ke-menu-item-on');\n\t\t\tif (centerDiv) {\n\t\t\t\tcenterDiv.removeClass('ke-menu-item-center-on');\n\t\t\t}\n\t\t})\n\t\t.click(function(e) {\n\t\t\titem.click.call(K(this));\n\t\t\te.stopPropagation();\n\t\t})\n\t\t.append(leftDiv);\n\t\tif (centerDiv) {\n\t\t\titemDiv.append(centerDiv);\n\t\t}\n\t\titemDiv.append(rightDiv);\n\t\tif (item.checked) {\n\t\t\ticonClass = 'ke-icon-checked';\n\t\t}\n\t\tif (iconClass !== '') {\n\t\t\tleftDiv.html('<span class=\"ke-inline-block ke-toolbar-icon ke-toolbar-icon-url ' + iconClass + '\"></span>');\n\t\t}\n\t\trightDiv.html(item.title);\n\t\treturn self;\n\t},\n\tremove : function() {\n\t\tvar self = this;\n\t\tif (self.options.beforeRemove) {\n\t\t\tself.options.beforeRemove.call(self);\n\t\t}\n\t\tK('.ke-menu-item', self.div[0]).unbind();\n\t\tKMenu.parent.remove.call(self);\n\t\treturn self;\n\t}\n});\nfunction _menu(options) {\n\treturn new KMenu(options);\n}\nK.MenuClass = KMenu;\nK.menu = _menu;\n\n\n\nfunction KColorPicker(options) {\n\tthis.init(options);\n}\n_extend(KColorPicker, KWidget, {\n\tinit : function(options) {\n\t\tvar self = this;\n\t\toptions.z = options.z || 811213;\n\t\tKColorPicker.parent.init.call(self, options);\n\t\tvar colors = options.colors || [\n\t\t\t['#E53333', '#E56600', '#FF9900', '#64451D', '#DFC5A4', '#FFE500'],\n\t\t\t['#009900', '#006600', '#99BB00', '#B8D100', '#60D978', '#00D5FF'],\n\t\t\t['#337FE5', '#003399', '#4C33E5', '#9933E5', '#CC33E5', '#EE33EE'],\n\t\t\t['#FFFFFF', '#CCCCCC', '#999999', '#666666', '#333333', '#000000']\n\t\t];\n\t\tself.selectedColor = (options.selectedColor || '').toLowerCase();\n\t\tself._cells = [];\n\t\tself.div.addClass('ke-colorpicker').bind('click,mousedown', function(e){\n\t\t\te.stopPropagation();\n\t\t}).attr('unselectable', 'on');\n\t\tvar table = self.doc.createElement('table');\n\t\tself.div.append(table);\n\t\ttable.className = 'ke-colorpicker-table';\n\t\ttable.cellPadding = 0;\n\t\ttable.cellSpacing = 0;\n\t\ttable.border = 0;\n\t\tvar row = table.insertRow(0), cell = row.insertCell(0);\n\t\tcell.colSpan = colors[0].length;\n\t\tself._addAttr(cell, '', 'ke-colorpicker-cell-top');\n\t\tfor (var i = 0; i < colors.length; i++) {\n\t\t\trow = table.insertRow(i + 1);\n\t\t\tfor (var j = 0; j < colors[i].length; j++) {\n\t\t\t\tcell = row.insertCell(j);\n\t\t\t\tself._addAttr(cell, colors[i][j], 'ke-colorpicker-cell');\n\t\t\t}\n\t\t}\n\t},\n\t_addAttr : function(cell, color, cls) {\n\t\tvar self = this;\n\t\tcell = K(cell).addClass(cls);\n\t\tif (self.selectedColor === color.toLowerCase()) {\n\t\t\tcell.addClass('ke-colorpicker-cell-selected');\n\t\t}\n\t\tcell.attr('title', color || self.options.noColor);\n\t\tcell.mouseover(function(e) {\n\t\t\tK(this).addClass('ke-colorpicker-cell-on');\n\t\t});\n\t\tcell.mouseout(function(e) {\n\t\t\tK(this).removeClass('ke-colorpicker-cell-on');\n\t\t});\n\t\tcell.click(function(e) {\n\t\t\te.stop();\n\t\t\tself.options.click.call(K(this), color);\n\t\t});\n\t\tif (color) {\n\t\t\tcell.append(K('<div class=\"ke-colorpicker-cell-color\" unselectable=\"on\"></div>').css('background-color', color));\n\t\t} else {\n\t\t\tcell.html(self.options.noColor);\n\t\t}\n\t\tK(cell).attr('unselectable', 'on');\n\t\tself._cells.push(cell);\n\t},\n\tremove : function() {\n\t\tvar self = this;\n\t\t_each(self._cells, function() {\n\t\t\tthis.unbind();\n\t\t});\n\t\tKColorPicker.parent.remove.call(self);\n\t\treturn self;\n\t}\n});\nfunction _colorpicker(options) {\n\treturn new KColorPicker(options);\n}\nK.ColorPickerClass = KColorPicker;\nK.colorpicker = _colorpicker;\n\n\nfunction KUploadButton(options) {\n\tthis.init(options);\n}\n_extend(KUploadButton, {\n\tinit : function(options) {\n\t\tvar self = this,\n\t\t\tbutton = K(options.button),\n\t\t\tfieldName = options.fieldName || 'file',\n\t\t\turl = options.url || '',\n\t\t\ttitle = button.val(),\n\t\t\textraParams = options.extraParams || {},\n\t\t\tcls = button[0].className || '',\n\t\t\ttarget = options.target || 'kindeditor_upload_iframe_' + new Date().getTime();\n\t\toptions.afterError = options.afterError || function(str) {\n\t\t\talert(str);\n\t\t};\n\t\tvar hiddenElements = [];\n\t\tfor(var k in extraParams){\n\t\t\thiddenElements.push('<input type=\"hidden\" name=\"' + k + '\" value=\"' + extraParams[k] + '\" />');\n\t\t}\n\t\tvar html = [\n\t\t\t'<div class=\"ke-inline-block ' + cls + '\">',\n\t\t\t(options.target ? '' : '<iframe name=\"' + target + '\" style=\"display:none;\"></iframe>'),\n\t\t\t(options.form ? '<div class=\"ke-upload-area\">' : '<form class=\"ke-upload-area ke-form\" method=\"post\" enctype=\"multipart/form-data\" target=\"' + target + '\" action=\"' + url + '\">'),\n\t\t\t'<span class=\"ke-button-common\">',\n\t\t\thiddenElements.join(''),\n\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" value=\"' + title + '\" />',\n\t\t\t'</span>',\n\t\t\t'<input type=\"file\" class=\"ke-upload-file\" name=\"' + fieldName + '\" tabindex=\"-1\" />',\n\t\t\t(options.form ? '</div>' : '</form>'),\n\t\t\t'</div>'].join('');\n\t\tvar div = K(html, button.doc);\n\t\tbutton.hide();\n\t\tbutton.before(div);\n\t\tself.div = div;\n\t\tself.button = button;\n\t\tself.iframe = options.target ? K('iframe[name=\"' + target + '\"]') : K('iframe', div);\n\t\tself.form = options.form ? K(options.form) : K('form', div);\n\t\tself.fileBox = K('.ke-upload-file', div);\n\t\tvar width = options.width || K('.ke-button-common', div).width();\n\t\tK('.ke-upload-area', div).width(width);\n\t\tself.options = options;\n\t},\n\tsubmit : function() {\n\t\tvar self = this,\n\t\t\tiframe = self.iframe;\n\t\tiframe.bind('load', function() {\n\t\t\tiframe.unbind();\n\t\t\tvar tempForm = document.createElement('form');\n\t\t\tself.fileBox.before(tempForm);\n\t\t\tK(tempForm).append(self.fileBox);\n\t\t\ttempForm.reset();\n\t\t\tK(tempForm).remove(true);\n\t\t\tvar doc = K.iframeDoc(iframe),\n\t\t\t\tpre = doc.getElementsByTagName('pre')[0],\n\t\t\t\tstr = '', data;\n\t\t\tif (pre) {\n\t\t\t\tstr = pre.innerHTML;\n\t\t\t} else {\n\t\t\t\tstr = doc.body.innerHTML;\n\t\t\t}\n\t\t\tstr = _unescape(str);\n\t\t\tiframe[0].src = 'javascript:false';\n\t\t\ttry {\n\t\t\t\tdata = K.json(str);\n\t\t\t} catch (e) {\n\t\t\t\tself.options.afterError.call(self, '<!doctype html><html>' + doc.body.parentNode.innerHTML + '</html>');\n\t\t\t}\n\t\t\tif (data) {\n\t\t\t\tself.options.afterUpload.call(self, data);\n\t\t\t}\n\t\t});\n\t\tself.form[0].submit();\n\t\treturn self;\n\t},\n\tremove : function() {\n\t\tvar self = this;\n\t\tif (self.fileBox) {\n\t\t\tself.fileBox.unbind();\n\t\t}\n\t\tself.iframe.remove();\n\t\tself.div.remove();\n\t\tself.button.show();\n\t\treturn self;\n\t}\n});\nfunction _uploadbutton(options) {\n\treturn new KUploadButton(options);\n}\nK.UploadButtonClass = KUploadButton;\nK.uploadbutton = _uploadbutton;\n\n\nfunction _createButton(arg) {\n\targ = arg || {};\n\tvar name = arg.name || '',\n\t\tspan = K('<span class=\"ke-button-common ke-button-outer\" title=\"' + name + '\"></span>'),\n\t\tbtn = K('<input class=\"ke-button-common ke-button\" type=\"button\" value=\"' + name + '\" />');\n\tif (arg.click) {\n\t\tbtn.click(arg.click);\n\t}\n\tspan.append(btn);\n\treturn span;\n}\n\n\nfunction KDialog(options) {\n\tthis.init(options);\n}\n_extend(KDialog, KWidget, {\n\tinit : function(options) {\n\t\tvar self = this;\n\t\tvar shadowMode = _undef(options.shadowMode, true);\n\t\toptions.z = options.z || 811213;\n\t\toptions.shadowMode = false;\n\t\toptions.autoScroll = _undef(options.autoScroll, true);\n\t\tKDialog.parent.init.call(self, options);\n\t\tvar title = options.title,\n\t\t\tbody = K(options.body, self.doc),\n\t\t\tpreviewBtn = options.previewBtn,\n\t\t\tyesBtn = options.yesBtn,\n\t\t\tnoBtn = options.noBtn,\n\t\t\tcloseBtn = options.closeBtn,\n\t\t\tshowMask = _undef(options.showMask, true);\n\t\tself.div.addClass('ke-dialog').bind('click,mousedown', function(e){\n\t\t\te.stopPropagation();\n\t\t});\n\t\tvar contentDiv = K('<div class=\"ke-dialog-content\"></div>').appendTo(self.div);\n\t\tif (_IE && _V < 7) {\n\t\t\tself.iframeMask = K('<iframe src=\"about:blank\" class=\"ke-dialog-shadow\"></iframe>').appendTo(self.div);\n\t\t} else if (shadowMode) {\n\t\t\tK('<div class=\"ke-dialog-shadow\"></div>').appendTo(self.div);\n\t\t}\n\t\tvar headerDiv = K('<div class=\"ke-dialog-header\"></div>');\n\t\tcontentDiv.append(headerDiv);\n\t\theaderDiv.html(title);\n\t\tself.closeIcon = K('<span class=\"ke-dialog-icon-close\" title=\"' + closeBtn.name + '\"></span>').click(closeBtn.click);\n\t\theaderDiv.append(self.closeIcon);\n\t\tself.draggable({\n\t\t\tclickEl : headerDiv,\n\t\t\tbeforeDrag : options.beforeDrag\n\t\t});\n\t\tvar bodyDiv = K('<div class=\"ke-dialog-body\"></div>');\n\t\tcontentDiv.append(bodyDiv);\n\t\tbodyDiv.append(body);\n\t\tvar footerDiv = K('<div class=\"ke-dialog-footer\"></div>');\n\t\tif (previewBtn || yesBtn || noBtn) {\n\t\t\tcontentDiv.append(footerDiv);\n\t\t}\n\t\t_each([\n\t\t\t{ btn : previewBtn, name : 'preview' },\n\t\t\t{ btn : yesBtn, name : 'yes' },\n\t\t\t{ btn : noBtn, name : 'no' }\n\t\t], function() {\n\t\t\tif (this.btn) {\n\t\t\t\tvar button = _createButton(this.btn);\n\t\t\t\tbutton.addClass('ke-dialog-' + this.name);\n\t\t\t\tfooterDiv.append(button);\n\t\t\t}\n\t\t});\n\t\tif (self.height) {\n\t\t\tbodyDiv.height(_removeUnit(self.height) - headerDiv.height() - footerDiv.height());\n\t\t}\n\t\tself.div.width(self.div.width());\n\t\tself.div.height(self.div.height());\n\t\tself.mask = null;\n\t\tif (showMask) {\n\t\t\tvar docEl = _docElement(self.doc),\n\t\t\t\tdocWidth = Math.max(docEl.scrollWidth, docEl.clientWidth),\n\t\t\t\tdocHeight = Math.max(docEl.scrollHeight, docEl.clientHeight);\n\t\t\tself.mask = _widget({\n\t\t\t\tx : 0,\n\t\t\t\ty : 0,\n\t\t\t\tz : self.z - 1,\n\t\t\t\tcls : 'ke-dialog-mask',\n\t\t\t\twidth : docWidth,\n\t\t\t\theight : docHeight\n\t\t\t});\n\t\t}\n\t\tself.autoPos(self.div.width(), self.div.height());\n\t\tself.footerDiv = footerDiv;\n\t\tself.bodyDiv = bodyDiv;\n\t\tself.headerDiv = headerDiv;\n\t\tself.isLoading = false;\n\t},\n\tsetMaskIndex : function(z) {\n\t\tvar self = this;\n\t\tself.mask.div.css('z-index', z);\n\t},\n\tshowLoading : function(msg) {\n\t\tmsg = _undef(msg, '');\n\t\tvar self = this, body = self.bodyDiv;\n\t\tself.loading = K('<div class=\"ke-dialog-loading\"><div class=\"ke-inline-block ke-dialog-loading-content\" style=\"margin-top:' + Math.round(body.height() / 3) + 'px;\">' + msg + '</div></div>')\n\t\t\t.width(body.width()).height(body.height())\n\t\t\t.css('top', self.headerDiv.height() + 'px');\n\t\tbody.css('visibility', 'hidden').after(self.loading);\n\t\tself.isLoading = true;\n\t\treturn self;\n\t},\n\thideLoading : function() {\n\t\tthis.loading && this.loading.remove();\n\t\tthis.bodyDiv.css('visibility', 'visible');\n\t\tthis.isLoading = false;\n\t\treturn this;\n\t},\n\tremove : function() {\n\t\tvar self = this;\n\t\tif (self.options.beforeRemove) {\n\t\t\tself.options.beforeRemove.call(self);\n\t\t}\n\t\tself.mask && self.mask.remove();\n\t\tself.iframeMask && self.iframeMask.remove();\n\t\tself.closeIcon.unbind();\n\t\tK('input', self.div).unbind();\n\t\tK('button', self.div).unbind();\n\t\tself.footerDiv.unbind();\n\t\tself.bodyDiv.unbind();\n\t\tself.headerDiv.unbind();\n\t\tK('iframe', self.div).each(function() {\n\t\t\tK(this).remove();\n\t\t});\n\t\tKDialog.parent.remove.call(self);\n\t\treturn self;\n\t}\n});\nfunction _dialog(options) {\n\treturn new KDialog(options);\n}\nK.DialogClass = KDialog;\nK.dialog = _dialog;\n\n\nfunction _tabs(options) {\n\tvar self = _widget(options),\n\t\tremove = self.remove,\n\t\tafterSelect = options.afterSelect,\n\t\tdiv = self.div,\n\t\tliList = [];\n\tdiv.addClass('ke-tabs')\n\t\t.bind('contextmenu,mousedown,mousemove', function(e) {\n\t\t\te.preventDefault();\n\t\t});\n\tvar ul = K('<ul class=\"ke-tabs-ul ke-clearfix\"></ul>');\n\tdiv.append(ul);\n\tself.add = function(tab) {\n\t\tvar li = K('<li class=\"ke-tabs-li\">' + tab.title + '</li>');\n\t\tli.data('tab', tab);\n\t\tliList.push(li);\n\t\tul.append(li);\n\t};\n\tself.selectedIndex = 0;\n\tself.select = function(index) {\n\t\tself.selectedIndex = index;\n\t\t_each(liList, function(i, li) {\n\t\t\tli.unbind();\n\t\t\tif (i === index) {\n\t\t\t\tli.addClass('ke-tabs-li-selected');\n\t\t\t\tK(li.data('tab').panel).show('');\n\t\t\t} else {\n\t\t\t\tli.removeClass('ke-tabs-li-selected').removeClass('ke-tabs-li-on')\n\t\t\t\t.mouseover(function() {\n\t\t\t\t\tK(this).addClass('ke-tabs-li-on');\n\t\t\t\t})\n\t\t\t\t.mouseout(function() {\n\t\t\t\t\tK(this).removeClass('ke-tabs-li-on');\n\t\t\t\t})\n\t\t\t\t.click(function() {\n\t\t\t\t\tself.select(i);\n\t\t\t\t});\n\t\t\t\tK(li.data('tab').panel).hide();\n\t\t\t}\n\t\t});\n\t\tif (afterSelect) {\n\t\t\tafterSelect.call(self, index);\n\t\t}\n\t};\n\tself.remove = function() {\n\t\t_each(liList, function() {\n\t\t\tthis.remove();\n\t\t});\n\t\tul.remove();\n\t\tremove.call(self);\n\t};\n\treturn self;\n}\nK.tabs = _tabs;\n\n\nfunction _loadScript(url, fn) {\n\tvar head = document.getElementsByTagName('head')[0] || (_QUIRKS ? document.body : document.documentElement),\n\t\tscript = document.createElement('script');\n\thead.appendChild(script);\n\tscript.src = url;\n\tscript.charset = 'utf-8';\n\tscript.onload = script.onreadystatechange = function() {\n\t\tif (!this.readyState || this.readyState === 'loaded') {\n\t\t\tif (fn) {\n\t\t\t\tfn();\n\t\t\t}\n\t\t\tscript.onload = script.onreadystatechange = null;\n\t\t\thead.removeChild(script);\n\t\t}\n\t};\n}\n\n\nfunction _chopQuery(url) {\n\tvar index = url.indexOf('?');\n\treturn index > 0 ? url.substr(0, index) : url;\n}\nfunction _loadStyle(url) {\n\tvar head = document.getElementsByTagName('head')[0] || (_QUIRKS ? document.body : document.documentElement),\n\t\tlink = document.createElement('link'),\n\t\tabsoluteUrl = _chopQuery(_formatUrl(url, 'absolute'));\n\tvar links = K('link[rel=\"stylesheet\"]', head);\n\tfor (var i = 0, len = links.length; i < len; i++) {\n\t\tif (_chopQuery(_formatUrl(links[i].href, 'absolute')) === absoluteUrl) {\n\t\t\treturn;\n\t\t}\n\t}\n\thead.appendChild(link);\n\tlink.href = url;\n\tlink.rel = 'stylesheet';\n}\nfunction _ajax(url, fn, method, param, dataType) {\n\tmethod = method || 'GET';\n\tdataType = dataType || 'json';\n\tvar xhr = window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');\n\txhr.open(method, url, true);\n\txhr.onreadystatechange = function () {\n\t\tif (xhr.readyState == 4 && xhr.status == 200) {\n\t\t\tif (fn) {\n\t\t\t\tvar data = _trim(xhr.responseText);\n\t\t\t\tif (dataType == 'json') {\n\t\t\t\t\tdata = _json(data);\n\t\t\t\t}\n\t\t\t\tfn(data);\n\t\t\t}\n\t\t}\n\t};\n\tif (method == 'POST') {\n\t\tvar params = [];\n\t\t_each(param, function(key, val) {\n\t\t\tparams.push(encodeURIComponent(key) + '=' + encodeURIComponent(val));\n\t\t});\n\t\ttry {\n\t\t\txhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');\n\t\t} catch (e) {}\n\t\txhr.send(params.join('&'));\n\t} else {\n\t\txhr.send(null);\n\t}\n}\nK.loadScript = _loadScript;\nK.loadStyle = _loadStyle;\nK.ajax = _ajax;\n\n\nvar _plugins = {};\nfunction _plugin(name, fn) {\n\tif (name === undefined) {\n\t\treturn _plugins;\n\t}\n\tif (!fn) {\n\t\treturn _plugins[name];\n\t}\n\t_plugins[name] = fn;\n}\nvar _language = {};\nfunction _parseLangKey(key) {\n\tvar match, ns = 'core';\n\tif ((match = /^(\\w+)\\.(\\w+)$/.exec(key))) {\n\t\tns = match[1];\n\t\tkey = match[2];\n\t}\n\treturn { ns : ns, key : key };\n}\nfunction _lang(mixed, langType) {\n\tlangType = langType === undefined ? K.options.langType : langType;\n\tif (typeof mixed === 'string') {\n\t\tif (!_language[langType]) {\n\t\t\treturn 'no language';\n\t\t}\n\t\tvar pos = mixed.length - 1;\n\t\tif (mixed.substr(pos) === '.') {\n\t\t\treturn _language[langType][mixed.substr(0, pos)];\n\t\t}\n\t\tvar obj = _parseLangKey(mixed);\n\t\treturn _language[langType][obj.ns][obj.key];\n\t}\n\t_each(mixed, function(key, val) {\n\t\tvar obj = _parseLangKey(key);\n\t\tif (!_language[langType]) {\n\t\t\t_language[langType] = {};\n\t\t}\n\t\tif (!_language[langType][obj.ns]) {\n\t\t\t_language[langType][obj.ns] = {};\n\t\t}\n\t\t_language[langType][obj.ns][obj.key] = val;\n\t});\n}\n\n\nfunction _getImageFromRange(range, fn) {\n\tif (range.collapsed) {\n\t\treturn;\n\t}\n\trange = range.cloneRange().up();\n\tvar sc = range.startContainer, so = range.startOffset;\n\tif (!_WEBKIT && !range.isControl()) {\n\t\treturn;\n\t}\n\tvar img = K(sc.childNodes[so]);\n\tif (!img || img.name != 'img') {\n\t\treturn;\n\t}\n\tif (fn(img)) {\n\t\treturn img;\n\t}\n}\nfunction _bindContextmenuEvent() {\n\tvar self = this, doc = self.edit.doc;\n\tK(doc).contextmenu(function(e) {\n\t\tif (self.menu) {\n\t\t\tself.hideMenu();\n\t\t}\n\t\tif (!self.useContextmenu) {\n\t\t\te.preventDefault();\n\t\t\treturn;\n\t\t}\n\t\tif (self._contextmenus.length === 0) {\n\t\t\treturn;\n\t\t}\n\t\tvar maxWidth = 0, items = [];\n\t\t_each(self._contextmenus, function() {\n\t\t\tif (this.title == '-') {\n\t\t\t\titems.push(this);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this.cond && this.cond()) {\n\t\t\t\titems.push(this);\n\t\t\t\tif (this.width && this.width > maxWidth) {\n\t\t\t\t\tmaxWidth = this.width;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\twhile (items.length > 0 && items[0].title == '-') {\n\t\t\titems.shift();\n\t\t}\n\t\twhile (items.length > 0 && items[items.length - 1].title == '-') {\n\t\t\titems.pop();\n\t\t}\n\t\tvar prevItem = null;\n\t\t_each(items, function(i) {\n\t\t\tif (this.title == '-' && prevItem.title == '-') {\n\t\t\t\tdelete items[i];\n\t\t\t}\n\t\t\tprevItem = this;\n\t\t});\n\t\tif (items.length > 0) {\n\t\t\te.preventDefault();\n\t\t\tvar pos = K(self.edit.iframe).pos(),\n\t\t\t\tmenu = _menu({\n\t\t\t\t\tx : pos.x + e.clientX,\n\t\t\t\t\ty : pos.y + e.clientY,\n\t\t\t\t\twidth : maxWidth,\n\t\t\t\t\tcss : { visibility: 'hidden' },\n\t\t\t\t\tshadowMode : self.shadowMode\n\t\t\t\t});\n\t\t\t_each(items, function() {\n\t\t\t\tif (this.title) {\n\t\t\t\t\tmenu.addItem(this);\n\t\t\t\t}\n\t\t\t});\n\t\t\tvar docEl = _docElement(menu.doc),\n\t\t\t\tmenuHeight = menu.div.height();\n\t\t\tif (e.clientY + menuHeight >= docEl.clientHeight - 100) {\n\t\t\t\tmenu.pos(menu.x, _removeUnit(menu.y) - menuHeight);\n\t\t\t}\n\t\t\tmenu.div.css('visibility', 'visible');\n\t\t\tself.menu = menu;\n\t\t}\n\t});\n}\nfunction _bindNewlineEvent() {\n\tvar self = this, doc = self.edit.doc, newlineTag = self.newlineTag;\n\tif (_IE && newlineTag !== 'br') {\n\t\treturn;\n\t}\n\tif (_GECKO && _V < 3 && newlineTag !== 'p') {\n\t\treturn;\n\t}\n\tif (_OPERA && _V < 9) {\n\t\treturn;\n\t}\n\tvar brSkipTagMap = _toMap('h1,h2,h3,h4,h5,h6,pre,li'),\n\t\tpSkipTagMap = _toMap('p,h1,h2,h3,h4,h5,h6,pre,li,blockquote');\n\tfunction getAncestorTagName(range) {\n\t\tvar ancestor = K(range.commonAncestor());\n\t\twhile (ancestor) {\n\t\t\tif (ancestor.type == 1 && !ancestor.isStyle()) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tancestor = ancestor.parent();\n\t\t}\n\t\treturn ancestor.name;\n\t}\n\tK(doc).keydown(function(e) {\n\t\tif (e.which != 13 || e.shiftKey || e.ctrlKey || e.altKey) {\n\t\t\treturn;\n\t\t}\n\t\tself.cmd.selection();\n\t\tvar tagName = getAncestorTagName(self.cmd.range);\n\t\tif (tagName == 'marquee' || tagName == 'select') {\n\t\t\treturn;\n\t\t}\n\t\tif (newlineTag === 'br' && !brSkipTagMap[tagName]) {\n\t\t\te.preventDefault();\n\t\t\tself.insertHtml('<br />' + (_IE && _V < 9 ? '' : '\\u200B'));\n\t\t\treturn;\n\t\t}\n\t\tif (!pSkipTagMap[tagName]) {\n\t\t\t_nativeCommand(doc, 'formatblock', '<p>');\n\t\t}\n\t});\n\tK(doc).keyup(function(e) {\n\t\tif (e.which != 13 || e.shiftKey || e.ctrlKey || e.altKey) {\n\t\t\treturn;\n\t\t}\n\t\tif (newlineTag == 'br') {\n\t\t\treturn;\n\t\t}\n\t\tif (_GECKO) {\n\t\t\tvar root = self.cmd.commonAncestor('p');\n\t\t\tvar a = self.cmd.commonAncestor('a');\n\t\t\tif (a && a.text() == '') {\n\t\t\t\ta.remove(true);\n\t\t\t\tself.cmd.range.selectNodeContents(root[0]).collapse(true);\n\t\t\t\tself.cmd.select();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tself.cmd.selection();\n\t\tvar tagName = getAncestorTagName(self.cmd.range);\n\t\tif (tagName == 'marquee' || tagName == 'select') {\n\t\t\treturn;\n\t\t}\n\t\tif (!pSkipTagMap[tagName]) {\n\t\t\t_nativeCommand(doc, 'formatblock', '<p>');\n\t\t}\n\t\tvar div = self.cmd.commonAncestor('div');\n\t\tif (div) {\n\t\t\tvar p = K('<p></p>'),\n\t\t\t\tchild = div[0].firstChild;\n\t\t\twhile (child) {\n\t\t\t\tvar next = child.nextSibling;\n\t\t\t\tp.append(child);\n\t\t\t\tchild = next;\n\t\t\t}\n\t\t\tdiv.before(p);\n\t\t\tdiv.remove();\n\t\t\tself.cmd.range.selectNodeContents(p[0]);\n\t\t\tself.cmd.select();\n\t\t}\n\t});\n}\nfunction _bindTabEvent() {\n\tvar self = this, doc = self.edit.doc;\n\tK(doc).keydown(function(e) {\n\t\tif (e.which == 9) {\n\t\t\te.preventDefault();\n\t\t\tif (self.afterTab) {\n\t\t\t\tself.afterTab.call(self, e);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar cmd = self.cmd, range = cmd.range;\n\t\t\trange.shrink();\n\t\t\tif (range.collapsed && range.startContainer.nodeType == 1) {\n\t\t\t\trange.insertNode(K('@&nbsp;', doc)[0]);\n\t\t\t\tcmd.select();\n\t\t\t}\n\t\t\tself.insertHtml('&nbsp;&nbsp;&nbsp;&nbsp;');\n\t\t}\n\t});\n}\nfunction _bindFocusEvent() {\n\tvar self = this;\n\tK(self.edit.textarea[0], self.edit.win).focus(function(e) {\n\t\tif (self.afterFocus) {\n\t\t\tself.afterFocus.call(self, e);\n\t\t}\n\t}).blur(function(e) {\n\t\tif (self.afterBlur) {\n\t\t\tself.afterBlur.call(self, e);\n\t\t}\n\t});\n}\nfunction _removeBookmarkTag(html) {\n\treturn _trim(html.replace(/<span [^>]*id=\"?__kindeditor_bookmark_\\w+_\\d+__\"?[^>]*><\\/span>/ig, ''));\n}\nfunction _removeTempTag(html) {\n\treturn html.replace(/<div[^>]+class=\"?__kindeditor_paste__\"?[^>]*>[\\s\\S]*?<\\/div>/ig, '');\n}\nfunction _addBookmarkToStack(stack, bookmark) {\n\tif (stack.length === 0) {\n\t\tstack.push(bookmark);\n\t\treturn;\n\t}\n\tvar prev = stack[stack.length - 1];\n\tif (_removeBookmarkTag(bookmark.html) !== _removeBookmarkTag(prev.html)) {\n\t\tstack.push(bookmark);\n\t}\n}\n\n\n\nfunction _undoToRedo(fromStack, toStack) {\n\tvar self = this, edit = self.edit,\n\t\tbody = edit.doc.body,\n\t\trange, bookmark;\n\tif (fromStack.length === 0) {\n\t\treturn self;\n\t}\n\tif (edit.designMode) {\n\t\trange = self.cmd.range;\n\t\tbookmark = range.createBookmark(true);\n\t\tbookmark.html = body.innerHTML;\n\t} else {\n\t\tbookmark = {\n\t\t\thtml : body.innerHTML\n\t\t};\n\t}\n\t_addBookmarkToStack(toStack, bookmark);\n\tvar prev = fromStack.pop();\n\tif (_removeBookmarkTag(bookmark.html) === _removeBookmarkTag(prev.html) && fromStack.length > 0) {\n\t\tprev = fromStack.pop();\n\t}\n\tif (edit.designMode) {\n\t\tedit.html(prev.html);\n\t\tif (prev.start) {\n\t\t\trange.moveToBookmark(prev);\n\t\t\tself.select();\n\t\t}\n\t} else {\n\t\tK(body).html(_removeBookmarkTag(prev.html));\n\t}\n\treturn self;\n}\nfunction KEditor(options) {\n\tvar self = this;\n\tself.options = {};\n\tfunction setOption(key, val) {\n\t\tif (KEditor.prototype[key] === undefined) {\n\t\t\tself[key] = val;\n\t\t}\n\t\tself.options[key] = val;\n\t}\n\t_each(options, function(key, val) {\n\t\tsetOption(key, options[key]);\n\t});\n\t_each(K.options, function(key, val) {\n\t\tif (self[key] === undefined) {\n\t\t\tsetOption(key, val);\n\t\t}\n\t});\n\tvar se = K(self.srcElement || '<textarea/>');\n\tif (!self.width) {\n\t\tself.width = se[0].style.width || se.width();\n\t}\n\tif (!self.height) {\n\t\tself.height = se[0].style.height || se.height();\n\t}\n\tsetOption('width', _undef(self.width, self.minWidth));\n\tsetOption('height', _undef(self.height, self.minHeight));\n\tsetOption('width', _addUnit(self.width));\n\tsetOption('height', _addUnit(self.height));\n\tif (_MOBILE && (!_IOS || _V < 534)) {\n\t\tself.designMode = false;\n\t}\n\tself.srcElement = se;\n\tself.initContent = '';\n\tself.plugin = {};\n\tself.isCreated = false;\n\tself._handlers = {};\n\tself._contextmenus = [];\n\tself._undoStack = [];\n\tself._redoStack = [];\n\tself._firstAddBookmark = true;\n\tself.menu = self.contextmenu = null;\n\tself.dialogs = [];\n}\nKEditor.prototype = {\n\tlang : function(mixed) {\n\t\treturn _lang(mixed, this.langType);\n\t},\n\tloadPlugin : function(name, fn) {\n\t\tvar self = this;\n\t\tvar _pluginStatus = this._pluginStatus;\n\t\tif (!_pluginStatus) {\n\t\t\t_pluginStatus = this._pluginStatus = {};\n\t\t}\n\t\tif (_plugins[name]) {\n\t\t\tif (!_isFunction(_plugins[name])) {\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tself.loadPlugin(name, fn);\n\t\t\t\t}, 100);\n\t\t\t\treturn self;\n\t\t\t}\n\t\t\tif(!_pluginStatus[name]) {\n\t\t\t\t_plugins[name].call(self, KindEditor);\n\t\t\t\t_pluginStatus[name] = 'inited';\n\t\t\t}\n\t\t\tif (fn) {\n\t\t\t\tfn.call(self);\n\t\t\t}\n\t\t\treturn self;\n\t\t}\n\t\t_plugins[name] = 'loading';\n\t\t_loadScript(self.pluginsPath + name + '/' + name + '.js?ver=' + encodeURIComponent(K.DEBUG ? _TIME : _VERSION), function() {\n\t\t\tsetTimeout(function() {\n\t\t\t\tif (_plugins[name]) {\n\t\t\t\t\tself.loadPlugin(name, fn);\n\t\t\t\t}\n\t\t\t}, 0);\n\t\t});\n\t\treturn self;\n\t},\n\thandler : function(key, fn) {\n\t\tvar self = this;\n\t\tif (!self._handlers[key]) {\n\t\t\tself._handlers[key] = [];\n\t\t}\n\t\tif (_isFunction(fn)) {\n\t\t\tself._handlers[key].push(fn);\n\t\t\treturn self;\n\t\t}\n\t\t_each(self._handlers[key], function() {\n\t\t\tfn = this.call(self, fn);\n\t\t});\n\t\treturn fn;\n\t},\n\tclickToolbar : function(name, fn) {\n\t\tvar self = this, key = 'clickToolbar' + name;\n\t\tif (fn === undefined) {\n\t\t\tif (self._handlers[key]) {\n\t\t\t\treturn self.handler(key);\n\t\t\t}\n\t\t\tself.loadPlugin(name, function() {\n\t\t\t\tself.handler(key);\n\t\t\t});\n\t\t\treturn self;\n\t\t}\n\t\treturn self.handler(key, fn);\n\t},\n\tupdateState : function() {\n\t\tvar self = this;\n\t\t_each(('justifyleft,justifycenter,justifyright,justifyfull,insertorderedlist,insertunorderedlist,' +\n\t\t\t'subscript,superscript,bold,italic,underline,strikethrough').split(','), function(i, name) {\n\t\t\tself.cmd.state(name) ? self.toolbar.select(name) : self.toolbar.unselect(name);\n\t\t});\n\t\treturn self;\n\t},\n\taddContextmenu : function(item) {\n\t\tthis._contextmenus.push(item);\n\t\treturn this;\n\t},\n\tafterCreate : function(fn) {\n\t\treturn this.handler('afterCreate', fn);\n\t},\n\tbeforeRemove : function(fn) {\n\t\treturn this.handler('beforeRemove', fn);\n\t},\n\tbeforeGetHtml : function(fn) {\n\t\treturn this.handler('beforeGetHtml', fn);\n\t},\n\tbeforeSetHtml : function(fn) {\n\t\treturn this.handler('beforeSetHtml', fn);\n\t},\n\tafterSetHtml : function(fn) {\n\t\treturn this.handler('afterSetHtml', fn);\n\t},\n\tcreate : function() {\n\t\tvar self = this, fullscreenMode = self.fullscreenMode;\n\t\tif (self.isCreated) {\n\t\t\treturn self;\n\t\t}\n\t\tif (self.srcElement.data('kindeditor')) {\n\t\t\treturn self;\n\t\t}\n\t\tself.srcElement.data('kindeditor', 'true');\n\t\tif (fullscreenMode) {\n\t\t\t_docElement().style.overflow = 'hidden';\n\t\t} else {\n\t\t\t_docElement().style.overflow = '';\n\t\t}\n\t\tvar width = fullscreenMode ? _docElement().clientWidth + 'px' : self.width,\n\t\t\theight = fullscreenMode ? _docElement().clientHeight + 'px' : self.height;\n\t\tif ((_IE && _V < 8) || _QUIRKS) {\n\t\t\theight = _addUnit(_removeUnit(height) + 2);\n\t\t}\n\t\tvar container = self.container = K(self.layout);\n\t\tif (fullscreenMode) {\n\t\t\tK(document.body).append(container);\n\t\t} else {\n\t\t\tself.srcElement.before(container);\n\t\t}\n\t\tvar toolbarDiv = K('.toolbar', container),\n\t\t\teditDiv = K('.edit', container),\n\t\t\tstatusbar = self.statusbar = K('.statusbar', container);\n\t\tcontainer.removeClass('container')\n\t\t\t.addClass('ke-container ke-container-' + self.themeType).css('width', width);\n\t\tif (fullscreenMode) {\n\t\t\tcontainer.css({\n\t\t\t\tposition : 'absolute',\n\t\t\t\tleft : 0,\n\t\t\t\ttop : 0,\n\t\t\t\t'z-index' : 811211\n\t\t\t});\n\t\t\tif (!_GECKO) {\n\t\t\t\tself._scrollPos = _getScrollPos();\n\t\t\t}\n\t\t\twindow.scrollTo(0, 0);\n\t\t\tK(document.body).css({\n\t\t\t\t'height' : '1px',\n\t\t\t\t'overflow' : 'hidden'\n\t\t\t});\n\t\t\tK(document.body.parentNode).css('overflow', 'hidden');\n\t\t\tself._fullscreenExecuted = true;\n\t\t} else {\n\t\t\tif (self._fullscreenExecuted) {\n\t\t\t\tK(document.body).css({\n\t\t\t\t\t'height' : '',\n\t\t\t\t\t'overflow' : ''\n\t\t\t\t});\n\t\t\t\tK(document.body.parentNode).css('overflow', '');\n\t\t\t}\n\t\t\tif (self._scrollPos) {\n\t\t\t\twindow.scrollTo(self._scrollPos.x, self._scrollPos.y);\n\t\t\t}\n\t\t}\n\t\tvar htmlList = [];\n\t\tK.each(self.items, function(i, name) {\n\t\t\tif (name == '|') {\n\t\t\t\thtmlList.push('<span class=\"ke-inline-block ke-separator\"></span>');\n\t\t\t} else if (name == '/') {\n\t\t\t\thtmlList.push('<div class=\"ke-hr\"></div>');\n\t\t\t} else {\n\t\t\t\thtmlList.push('<span class=\"ke-outline\" data-name=\"' + name + '\" title=\"' + self.lang(name) + '\" unselectable=\"on\">');\n\t\t\t\thtmlList.push('<span class=\"ke-toolbar-icon ke-toolbar-icon-url ke-icon-' + name + '\" unselectable=\"on\"></span></span>');\n\t\t\t}\n\t\t});\n\t\tvar toolbar = self.toolbar = _toolbar({\n\t\t\tsrc : toolbarDiv,\n\t\t\thtml : htmlList.join(''),\n\t\t\tnoDisableItems : self.noDisableItems,\n\t\t\tclick : function(e, name) {\n\t\t\t\te.stop();\n\t\t\t\tif (self.menu) {\n\t\t\t\t\tvar menuName = self.menu.name;\n\t\t\t\t\tself.hideMenu();\n\t\t\t\t\tif (menuName === name) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tself.clickToolbar(name);\n\t\t\t}\n\t\t});\n\t\tvar editHeight = _removeUnit(height) - toolbar.div.height();\n\t\tvar edit = self.edit = _edit({\n\t\t\theight : editHeight > 0 && _removeUnit(height) > self.minHeight ? editHeight : self.minHeight,\n\t\t\tsrc : editDiv,\n\t\t\tsrcElement : self.srcElement,\n\t\t\tdesignMode : self.designMode,\n\t\t\tthemesPath : self.themesPath,\n\t\t\tbodyClass : self.bodyClass,\n\t\t\tcssPath : self.cssPath,\n\t\t\tcssData : self.cssData,\n\t\t\tbeforeGetHtml : function(html) {\n\t\t\t\thtml = self.beforeGetHtml(html);\n\t\t\t\thtml = _removeBookmarkTag(_removeTempTag(html));\n\t\t\t\treturn _formatHtml(html, self.filterMode ? self.htmlTags : null, self.urlType, self.wellFormatMode, self.indentChar);\n\t\t\t},\n\t\t\tbeforeSetHtml : function(html) {\n\t\t\t\thtml = _formatHtml(html, self.filterMode ? self.htmlTags : null, '', false);\n\t\t\t\treturn self.beforeSetHtml(html);\n\t\t\t},\n\t\t\tafterSetHtml : function() {\n\t\t\t\tself.edit = edit = this;\n\t\t\t\tself.afterSetHtml();\n\t\t\t},\n\t\t\tafterCreate : function() {\n\t\t\t\tself.edit = edit = this;\n\t\t\t\tself.cmd = edit.cmd;\n\t\t\t\tself._docMousedownFn = function(e) {\n\t\t\t\t\tif (self.menu) {\n\t\t\t\t\t\tself.hideMenu();\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tK(edit.doc, document).mousedown(self._docMousedownFn);\n\t\t\t\t_bindContextmenuEvent.call(self);\n\t\t\t\t_bindNewlineEvent.call(self);\n\t\t\t\t_bindTabEvent.call(self);\n\t\t\t\t_bindFocusEvent.call(self);\n\t\t\t\tedit.afterChange(function(e) {\n\t\t\t\t\tif (!edit.designMode) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tself.updateState();\n\t\t\t\t\tself.addBookmark();\n\t\t\t\t\tif (self.options.afterChange) {\n\t\t\t\t\t\tself.options.afterChange.call(self);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tedit.textarea.keyup(function(e) {\n\t\t\t\t\tif (!e.ctrlKey && !e.altKey && _INPUT_KEY_MAP[e.which]) {\n\t\t\t\t\t\tif (self.options.afterChange) {\n\t\t\t\t\t\t\tself.options.afterChange.call(self);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (self.readonlyMode) {\n\t\t\t\t\tself.readonly();\n\t\t\t\t}\n\t\t\t\tself.isCreated = true;\n\t\t\t\tif (self.initContent === '') {\n\t\t\t\t\tself.initContent = self.html();\n\t\t\t\t}\n\t\t\t\tif (self._undoStack.length > 0) {\n\t\t\t\t\tvar prev = self._undoStack.pop();\n\t\t\t\t\tif (prev.start) {\n\t\t\t\t\t\tself.html(prev.html);\n\t\t\t\t\t\tedit.cmd.range.moveToBookmark(prev);\n\t\t\t\t\t\tself.select();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tself.afterCreate();\n\t\t\t\tif (self.options.afterCreate) {\n\t\t\t\t\tself.options.afterCreate.call(self);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tstatusbar.removeClass('statusbar').addClass('ke-statusbar')\n\t\t\t.append('<span class=\"ke-inline-block ke-statusbar-center-icon\"></span>')\n\t\t\t.append('<span class=\"ke-inline-block ke-statusbar-right-icon\"></span>');\n\t\tif (self._fullscreenResizeHandler) {\n\t\t\tK(window).unbind('resize', self._fullscreenResizeHandler);\n\t\t\tself._fullscreenResizeHandler = null;\n\t\t}\n\t\tfunction initResize() {\n\t\t\tif (statusbar.height() === 0) {\n\t\t\t\tsetTimeout(initResize, 100);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tself.resize(width, height, false);\n\t\t}\n\t\tinitResize();\n\t\tif (fullscreenMode) {\n\t\t\tself._fullscreenResizeHandler = function(e) {\n\t\t\t\tif (self.isCreated) {\n\t\t\t\t\tself.resize(_docElement().clientWidth, _docElement().clientHeight, false);\n\t\t\t\t}\n\t\t\t};\n\t\t\tK(window).bind('resize', self._fullscreenResizeHandler);\n\t\t\ttoolbar.select('fullscreen');\n\t\t\tstatusbar.first().css('visibility', 'hidden');\n\t\t\tstatusbar.last().css('visibility', 'hidden');\n\t\t} else {\n\t\t\tif (_GECKO) {\n\t\t\t\tK(window).bind('scroll', function(e) {\n\t\t\t\t\tself._scrollPos = _getScrollPos();\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (self.resizeType > 0) {\n\t\t\t\t_drag({\n\t\t\t\t\tmoveEl : container,\n\t\t\t\t\tclickEl : statusbar,\n\t\t\t\t\tmoveFn : function(x, y, width, height, diffX, diffY) {\n\t\t\t\t\t\theight += diffY;\n\t\t\t\t\t\tself.resize(null, height);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tstatusbar.first().css('visibility', 'hidden');\n\t\t\t}\n\t\t\tif (self.resizeType === 2) {\n\t\t\t\t_drag({\n\t\t\t\t\tmoveEl : container,\n\t\t\t\t\tclickEl : statusbar.last(),\n\t\t\t\t\tmoveFn : function(x, y, width, height, diffX, diffY) {\n\t\t\t\t\t\twidth += diffX;\n\t\t\t\t\t\theight += diffY;\n\t\t\t\t\t\tself.resize(width, height);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tstatusbar.last().css('visibility', 'hidden');\n\t\t\t}\n\t\t}\n\t\treturn self;\n\t},\n\tremove : function() {\n\t\tvar self = this;\n\t\tif (!self.isCreated) {\n\t\t\treturn self;\n\t\t}\n\t\tself.beforeRemove();\n\t\tself.srcElement.data('kindeditor', '');\n\t\tif (self.menu) {\n\t\t\tself.hideMenu();\n\t\t}\n\t\t_each(self.dialogs, function() {\n\t\t\tself.hideDialog();\n\t\t});\n\t\tK(document).unbind('mousedown', self._docMousedownFn);\n\t\tself.toolbar.remove();\n\t\tself.edit.remove();\n\t\tself.statusbar.last().unbind();\n\t\tself.statusbar.unbind();\n\t\tself.container.remove();\n\t\tself.container = self.toolbar = self.edit = self.menu = null;\n\t\tself.dialogs = [];\n\t\tself.isCreated = false;\n\t\treturn self;\n\t},\n\tresize : function(width, height, updateProp) {\n\t\tvar self = this;\n\t\tupdateProp = _undef(updateProp, true);\n\t\tif (width) {\n\t\t\tif (!/%/.test(width)) {\n\t\t\t\twidth = _removeUnit(width);\n\t\t\t\twidth = width < self.minWidth ? self.minWidth : width;\n\t\t\t}\n\t\t\tself.container.css('width', _addUnit(width));\n\t\t\tif (updateProp) {\n\t\t\t\tself.width = _addUnit(width);\n\t\t\t}\n\t\t}\n\t\tif (height) {\n\t\t\theight = _removeUnit(height);\n\t\t\tvar editHeight = _removeUnit(height) - self.toolbar.div.height() - self.statusbar.height();\n\t\t\teditHeight = editHeight < self.minHeight ? self.minHeight : editHeight;\n\t\t\tself.edit.setHeight(editHeight);\n\t\t\tif (updateProp) {\n\t\t\t\tself.height = _addUnit(height);\n\t\t\t}\n\t\t}\n\t\treturn self;\n\t},\n\tselect : function() {\n\t\tthis.isCreated && this.cmd.select();\n\t\treturn this;\n\t},\n\thtml : function(val) {\n\t\tvar self = this;\n\t\tif (val === undefined) {\n\t\t\treturn self.isCreated ? self.edit.html() : _elementVal(self.srcElement);\n\t\t}\n\t\tself.isCreated ? self.edit.html(val) : _elementVal(self.srcElement, val);\n\t\tif (self.isCreated) {\n\t\t\tself.cmd.selection();\n\t\t}\n\t\treturn self;\n\t},\n\tfullHtml : function() {\n\t\treturn this.isCreated ? this.edit.html(undefined, true) : '';\n\t},\n\ttext : function(val) {\n\t\tvar self = this;\n\t\tif (val === undefined) {\n\t\t\treturn _trim(self.html().replace(/<(?!img|embed).*?>/ig, '').replace(/&nbsp;/ig, ' '));\n\t\t} else {\n\t\t\treturn self.html(_escape(val));\n\t\t}\n\t},\n\tisEmpty : function() {\n\t\treturn _trim(this.text().replace(/\\r\\n|\\n|\\r/, '')) === '';\n\t},\n\tisDirty : function() {\n\t\treturn _trim(this.initContent.replace(/\\r\\n|\\n|\\r|t/g, '')) !== _trim(this.html().replace(/\\r\\n|\\n|\\r|t/g, ''));\n\t},\n\tselectedHtml : function() {\n\t\tvar val = this.isCreated ? this.cmd.range.html() : '';\n\t\tval = _removeBookmarkTag(_removeTempTag(val));\n\t\treturn val;\n\t},\n\tcount : function(mode) {\n\t\tvar self = this;\n\t\tmode = (mode || 'html').toLowerCase();\n\t\tif (mode === 'html') {\n\t\t\treturn self.html().length;\n\t\t}\n\t\tif (mode === 'text') {\n\t\t\treturn self.text().replace(/<(?:img|embed).*?>/ig, 'K').replace(/\\r\\n|\\n|\\r/g, '').length;\n\t\t}\n\t\treturn 0;\n\t},\n\texec : function(key) {\n\t\tkey = key.toLowerCase();\n\t\tvar self = this, cmd = self.cmd,\n\t\t\tchangeFlag = _inArray(key, 'selectall,copy,paste,print'.split(',')) < 0;\n\t\tif (changeFlag) {\n\t\t\tself.addBookmark(false);\n\t\t}\n\t\tcmd[key].apply(cmd, _toArray(arguments, 1));\n\t\tif (changeFlag) {\n\t\t\tself.updateState();\n\t\t\tself.addBookmark(false);\n\t\t\tif (self.options.afterChange) {\n\t\t\t\tself.options.afterChange.call(self);\n\t\t\t}\n\t\t}\n\t\treturn self;\n\t},\n\tinsertHtml : function(val, quickMode) {\n\t\tif (!this.isCreated) {\n\t\t\treturn this;\n\t\t}\n\t\tval = this.beforeSetHtml(val);\n\t\tthis.exec('inserthtml', val, quickMode);\n\t\treturn this;\n\t},\n\tappendHtml : function(val) {\n\t\tthis.html(this.html() + val);\n\t\tif (this.isCreated) {\n\t\t\tvar cmd = this.cmd;\n\t\t\tcmd.range.selectNodeContents(cmd.doc.body).collapse(false);\n\t\t\tcmd.select();\n\t\t}\n\t\treturn this;\n\t},\n\tsync : function() {\n\t\t_elementVal(this.srcElement, this.html());\n\t\treturn this;\n\t},\n\tfocus : function() {\n\t\tthis.isCreated ? this.edit.focus() : this.srcElement[0].focus();\n\t\treturn this;\n\t},\n\tblur : function() {\n\t\tthis.isCreated ? this.edit.blur() : this.srcElement[0].blur();\n\t\treturn this;\n\t},\n\taddBookmark : function(checkSize) {\n\t\tcheckSize = _undef(checkSize, true);\n\t\tvar self = this, edit = self.edit,\n\t\t\tbody = edit.doc.body,\n\t\t\thtml = _removeTempTag(body.innerHTML), bookmark;\n\t\tif (checkSize && self._undoStack.length > 0) {\n\t\t\tvar prev = self._undoStack[self._undoStack.length - 1];\n\t\t\tif (Math.abs(html.length - _removeBookmarkTag(prev.html).length) < self.minChangeSize) {\n\t\t\t\treturn self;\n\t\t\t}\n\t\t}\n\t\tif (edit.designMode && !self._firstAddBookmark) {\n\t\t\tvar range = self.cmd.range;\n\t\t\tbookmark = range.createBookmark(true);\n\t\t\tbookmark.html = _removeTempTag(body.innerHTML);\n\t\t\trange.moveToBookmark(bookmark);\n\t\t} else {\n\t\t\tbookmark = {\n\t\t\t\thtml : html\n\t\t\t};\n\t\t}\n\t\tself._firstAddBookmark = false;\n\t\t_addBookmarkToStack(self._undoStack, bookmark);\n\t\treturn self;\n\t},\n\tundo : function() {\n\t\treturn _undoToRedo.call(this, this._undoStack, this._redoStack);\n\t},\n\tredo : function() {\n\t\treturn _undoToRedo.call(this, this._redoStack, this._undoStack);\n\t},\n\tfullscreen : function(bool) {\n\t\tthis.fullscreenMode = (bool === undefined ? !this.fullscreenMode : bool);\n\t\tthis.addBookmark(false);\n\t\treturn this.remove().create();\n\t},\n\treadonly : function(isReadonly) {\n\t\tisReadonly = _undef(isReadonly, true);\n\t\tvar self = this, edit = self.edit, doc = edit.doc;\n\t\tif (self.designMode) {\n\t\t\tself.toolbar.disableAll(isReadonly, []);\n\t\t} else {\n\t\t\t_each(self.noDisableItems, function() {\n\t\t\t\tself.toolbar[isReadonly ? 'disable' : 'enable'](this);\n\t\t\t});\n\t\t}\n\t\tif (_IE) {\n\t\t\tdoc.body.contentEditable = !isReadonly;\n\t\t} else {\n\t\t\tdoc.designMode = isReadonly ? 'off' : 'on';\n\t\t}\n\t\tedit.textarea[0].disabled = isReadonly;\n\t},\n\tcreateMenu : function(options) {\n\t\tvar self = this,\n\t\t\tname = options.name,\n\t\t\tknode = self.toolbar.get(name),\n\t\t\tpos = knode.pos();\n\t\toptions.x = pos.x;\n\t\toptions.y = pos.y + knode.height();\n\t\toptions.z = self.options.zIndex;\n\t\toptions.shadowMode = _undef(options.shadowMode, self.shadowMode);\n\t\tif (options.selectedColor !== undefined) {\n\t\t\toptions.cls = 'ke-colorpicker-' + self.themeType;\n\t\t\toptions.noColor = self.lang('noColor');\n\t\t\tself.menu = _colorpicker(options);\n\t\t} else {\n\t\t\toptions.cls = 'ke-menu-' + self.themeType;\n\t\t\toptions.centerLineMode = false;\n\t\t\tself.menu = _menu(options);\n\t\t}\n\t\treturn self.menu;\n\t},\n\thideMenu : function() {\n\t\tthis.menu.remove();\n\t\tthis.menu = null;\n\t\treturn this;\n\t},\n\thideContextmenu : function() {\n\t\tthis.contextmenu.remove();\n\t\tthis.contextmenu = null;\n\t\treturn this;\n\t},\n\tcreateDialog : function(options) {\n\t\tvar self = this, name = options.name;\n\t\toptions.z = self.options.zIndex;\n\t\toptions.shadowMode = _undef(options.shadowMode, self.shadowMode);\n\t\toptions.closeBtn = _undef(options.closeBtn, {\n\t\t\tname : self.lang('close'),\n\t\t\tclick : function(e) {\n\t\t\t\tself.hideDialog();\n\t\t\t\tif (_IE && self.cmd) {\n\t\t\t\t\tself.cmd.select();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\toptions.noBtn = _undef(options.noBtn, {\n\t\t\tname : self.lang(options.yesBtn ? 'no' : 'close'),\n\t\t\tclick : function(e) {\n\t\t\t\tself.hideDialog();\n\t\t\t\tif (_IE && self.cmd) {\n\t\t\t\t\tself.cmd.select();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif (self.dialogAlignType != 'page') {\n\t\t\toptions.alignEl = self.container;\n\t\t}\n\t\toptions.cls = 'ke-dialog-' + self.themeType;\n\t\tif (self.dialogs.length > 0) {\n\t\t\tvar firstDialog = self.dialogs[0],\n\t\t\t\tparentDialog = self.dialogs[self.dialogs.length - 1];\n\t\t\tfirstDialog.setMaskIndex(parentDialog.z + 2);\n\t\t\toptions.z = parentDialog.z + 3;\n\t\t\toptions.showMask = false;\n\t\t}\n\t\tvar dialog = _dialog(options);\n\t\tself.dialogs.push(dialog);\n\t\treturn dialog;\n\t},\n\thideDialog : function() {\n\t\tvar self = this;\n\t\tif (self.dialogs.length > 0) {\n\t\t\tself.dialogs.pop().remove();\n\t\t}\n\t\tif (self.dialogs.length > 0) {\n\t\t\tvar firstDialog = self.dialogs[0],\n\t\t\t\tparentDialog = self.dialogs[self.dialogs.length - 1];\n\t\t\tfirstDialog.setMaskIndex(parentDialog.z - 1);\n\t\t}\n\t\treturn self;\n\t},\n\terrorDialog : function(html) {\n\t\tvar self = this;\n\t\tvar dialog = self.createDialog({\n\t\t\twidth : 750,\n\t\t\ttitle : self.lang('uploadError'),\n\t\t\tbody : '<div style=\"padding:10px 20px;\"><iframe frameborder=\"0\" style=\"width:708px;height:400px;\"></iframe></div>'\n\t\t});\n\t\tvar iframe = K('iframe', dialog.div), doc = K.iframeDoc(iframe);\n\t\tdoc.open();\n\t\tdoc.write(html);\n\t\tdoc.close();\n\t\tK(doc.body).css('background-color', '#FFF');\n\t\tiframe[0].contentWindow.focus();\n\t\treturn self;\n\t}\n};\nfunction _editor(options) {\n\treturn new KEditor(options);\n}\nvar _instances = [];\nfunction _create(expr, options) {\n\toptions = options || {};\n\toptions.basePath = _undef(options.basePath, K.basePath);\n\toptions.themesPath = _undef(options.themesPath, options.basePath + 'themes/');\n\toptions.langPath = _undef(options.langPath, options.basePath + 'lang/');\n\toptions.pluginsPath = _undef(options.pluginsPath, options.basePath + 'plugins/');\n\tif (_undef(options.loadStyleMode, K.options.loadStyleMode)) {\n\t\tvar themeType = _undef(options.themeType, K.options.themeType);\n\t\t_loadStyle(options.themesPath + 'default/default.css');\n\t\t_loadStyle(options.themesPath + themeType + '/' + themeType + '.css');\n\t}\n\tfunction create(editor) {\n\t\t_each(_plugins, function(name, fn) {\n\t\t\tif (_isFunction(fn)) {\n\t\t\t\tfn.call(editor, KindEditor);\n\t\t\t\tif (!editor._pluginStatus) {\n\t\t\t\t\teditor._pluginStatus = {};\n\t\t\t\t}\n\t\t\t\teditor._pluginStatus[name] = 'inited';\n\t\t\t}\n\t\t});\n\t\treturn editor.create();\n\t}\n\tvar knode = K(expr);\n\tif (!knode || knode.length === 0) {\n\t\treturn;\n\t}\n\tif (knode.length > 1) {\n\t\tknode.each(function() {\n\t\t\t_create(this, options);\n\t\t});\n\t\treturn _instances[0];\n\t}\n\toptions.srcElement = knode[0];\n\tvar editor = new KEditor(options);\n\t_instances.push(editor);\n\tif (_language[editor.langType]) {\n\t\treturn create(editor);\n\t}\n\t_loadScript(editor.langPath + editor.langType + '.js?ver=' + encodeURIComponent(K.DEBUG ? _TIME : _VERSION), function() {\n\t\tcreate(editor);\n\t});\n\treturn editor;\n}\nfunction _eachEditor(expr, fn) {\n\tK(expr).each(function(i, el) {\n\t\tK.each(_instances, function(j, editor) {\n\t\t\tif (editor && editor.srcElement[0] == el) {\n\t\t\t\tfn.call(editor, j);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t});\n}\nK.remove = function(expr) {\n\t_eachEditor(expr, function(i) {\n\t\tthis.remove();\n\t\t_instances.splice(i, 1);\n\t});\n};\nK.sync = function(expr) {\n\t_eachEditor(expr, function() {\n\t\tthis.sync();\n\t});\n};\nK.html = function(expr, val) {\n\t_eachEditor(expr, function() {\n\t\tthis.html(val);\n\t});\n};\nK.insertHtml = function(expr, val) {\n\t_eachEditor(expr, function() {\n\t\tthis.insertHtml(val);\n\t});\n};\nK.appendHtml = function(expr, val) {\n\t_eachEditor(expr, function() {\n\t\tthis.appendHtml(val);\n\t});\n};\n\n\nif (_IE && _V < 7) {\n\t_nativeCommand(document, 'BackgroundImageCache', true);\n}\nK.EditorClass = KEditor;\nK.editor = _editor;\nK.create = _create;\nK.instances = _instances;\nK.plugin = _plugin;\nK.lang = _lang;\n\n\n_plugin('core', function(K) {\n\tvar self = this,\n\t\tshortcutKeys = {\n\t\t\tundo : 'Z', redo : 'Y', bold : 'B', italic : 'I', underline : 'U', print : 'P', selectall : 'A'\n\t\t};\n\tself.afterSetHtml(function() {\n\t\tif (self.options.afterChange) {\n\t\t\tself.options.afterChange.call(self);\n\t\t}\n\t});\n\tself.afterCreate(function() {\n\t\tif (self.syncType != 'form') {\n\t\t\treturn;\n\t\t}\n\t\tvar el = K(self.srcElement), hasForm = false;\n\t\twhile ((el = el.parent())) {\n\t\t\tif (el.name == 'form') {\n\t\t\t\thasForm = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (hasForm) {\n\t\t\tel.bind('submit', function(e) {\n\t\t\t\tself.sync();\n\t\t\t\tK(window).bind('unload', function() {\n\t\t\t\t\tself.edit.textarea.remove();\n\t\t\t\t});\n\t\t\t});\n\t\t\tvar resetBtn = K('[type=\"reset\"]', el);\n\t\t\tresetBtn.click(function() {\n\t\t\t\tself.html(self.initContent);\n\t\t\t\tself.cmd.selection();\n\t\t\t});\n\t\t\tself.beforeRemove(function() {\n\t\t\t\tel.unbind();\n\t\t\t\tresetBtn.unbind();\n\t\t\t});\n\t\t}\n\t});\n\tself.clickToolbar('source', function() {\n\t\tif (self.edit.designMode) {\n\t\t\tself.toolbar.disableAll(true);\n\t\t\tself.edit.design(false);\n\t\t\tself.toolbar.select('source');\n\t\t} else {\n\t\t\tself.toolbar.disableAll(false);\n\t\t\tself.edit.design(true);\n\t\t\tself.toolbar.unselect('source');\n\t\t\tif (_GECKO) {\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tself.cmd.selection();\n\t\t\t\t}, 0);\n\t\t\t} else {\n\t\t\t\tself.cmd.selection();\n\t\t\t}\n\t\t}\n\t\tself.designMode = self.edit.designMode;\n\t});\n\tself.afterCreate(function() {\n\t\tif (!self.designMode) {\n\t\t\tself.toolbar.disableAll(true).select('source');\n\t\t}\n\t});\n\tself.clickToolbar('fullscreen', function() {\n\t\tself.fullscreen();\n\t});\n\tif (self.fullscreenShortcut) {\n\t\tvar loaded = false;\n\t\tself.afterCreate(function() {\n\t\t\tK(self.edit.doc, self.edit.textarea).keyup(function(e) {\n\t\t\t\tif (e.which == 27) {\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tself.fullscreen();\n\t\t\t\t\t}, 0);\n\t\t\t\t}\n\t\t\t});\n\t\t\tif (loaded) {\n\t\t\t\tif (_IE && !self.designMode) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tself.focus();\n\t\t\t}\n\t\t\tif (!loaded) {\n\t\t\t\tloaded = true;\n\t\t\t}\n\t\t});\n\t}\n\t_each('undo,redo'.split(','), function(i, name) {\n\t\tif (shortcutKeys[name]) {\n\t\t\tself.afterCreate(function() {\n\t\t\t\t_ctrl(this.edit.doc, shortcutKeys[name], function() {\n\t\t\t\t\tself.clickToolbar(name);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\tself.clickToolbar(name, function() {\n\t\t\tself[name]();\n\t\t});\n\t});\n\tself.clickToolbar('formatblock', function() {\n\t\tvar blocks = self.lang('formatblock.formatBlock'),\n\t\t\theights = {\n\t\t\t\th1 : 28,\n\t\t\t\th2 : 24,\n\t\t\t\th3 : 18,\n\t\t\t\tH4 : 14,\n\t\t\t\tp : 12\n\t\t\t},\n\t\t\tcurVal = self.cmd.val('formatblock'),\n\t\t\tmenu = self.createMenu({\n\t\t\t\tname : 'formatblock',\n\t\t\t\twidth : self.langType == 'en' ? 200 : 150\n\t\t\t});\n\t\t_each(blocks, function(key, val) {\n\t\t\tvar style = 'font-size:' + heights[key] + 'px;';\n\t\t\tif (key.charAt(0) === 'h') {\n\t\t\t\tstyle += 'font-weight:bold;';\n\t\t\t}\n\t\t\tmenu.addItem({\n\t\t\t\ttitle : '<span style=\"' + style + '\" unselectable=\"on\">' + val + '</span>',\n\t\t\t\theight : heights[key] + 12,\n\t\t\t\tchecked : (curVal === key || curVal === val),\n\t\t\t\tclick : function() {\n\t\t\t\t\tself.select().exec('formatblock', '<' + key + '>').hideMenu();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t});\n\tself.clickToolbar('fontname', function() {\n\t\tvar curVal = self.cmd.val('fontname'),\n\t\t\tmenu = self.createMenu({\n\t\t\t\tname : 'fontname',\n\t\t\t\twidth : 150\n\t\t\t});\n\t\t_each(self.lang('fontname.fontName'), function(key, val) {\n\t\t\tmenu.addItem({\n\t\t\t\ttitle : '<span style=\"font-family: ' + key + ';\" unselectable=\"on\">' + val + '</span>',\n\t\t\t\tchecked : (curVal === key.toLowerCase() || curVal === val.toLowerCase()),\n\t\t\t\tclick : function() {\n\t\t\t\t\tself.exec('fontname', key).hideMenu();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t});\n\tself.clickToolbar('fontsize', function() {\n\t\tvar curVal = self.cmd.val('fontsize'),\n\t\t\tmenu = self.createMenu({\n\t\t\t\tname : 'fontsize',\n\t\t\t\twidth : 150\n\t\t\t});\n\t\t_each(self.fontSizeTable, function(i, val) {\n\t\t\tmenu.addItem({\n\t\t\t\ttitle : '<span style=\"font-size:' + val + ';\" unselectable=\"on\">' + val + '</span>',\n\t\t\t\theight : _removeUnit(val) + 12,\n\t\t\t\tchecked : curVal === val,\n\t\t\t\tclick : function() {\n\t\t\t\t\tself.exec('fontsize', val).hideMenu();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t});\n\t_each('forecolor,hilitecolor'.split(','), function(i, name) {\n\t\tself.clickToolbar(name, function() {\n\t\t\tself.createMenu({\n\t\t\t\tname : name,\n\t\t\t\tselectedColor : self.cmd.val(name) || 'default',\n\t\t\t\tcolors : self.colorTable,\n\t\t\t\tclick : function(color) {\n\t\t\t\t\tself.exec(name, color).hideMenu();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t});\n\t_each(('cut,copy,paste').split(','), function(i, name) {\n\t\tself.clickToolbar(name, function() {\n\t\t\tself.focus();\n\t\t\ttry {\n\t\t\t\tself.exec(name, null);\n\t\t\t} catch(e) {\n\t\t\t\talert(self.lang(name + 'Error'));\n\t\t\t}\n\t\t});\n\t});\n\tself.clickToolbar('about', function() {\n\t\tvar html = '<div style=\"margin:20px;\">' +\n\t\t\t'<div>KindEditor ' + _VERSION + '</div>' +\n\t\t\t'<div>Copyright &copy; <a href=\"http://www.kindsoft.net/\" target=\"_blank\">kindsoft.net</a> All rights reserved.</div>' +\n\t\t\t'</div>';\n\t\tself.createDialog({\n\t\t\tname : 'about',\n\t\t\twidth : 350,\n\t\t\ttitle : self.lang('about'),\n\t\t\tbody : html\n\t\t});\n\t});\n\tself.plugin.getSelectedLink = function() {\n\t\treturn self.cmd.commonAncestor('a');\n\t};\n\tself.plugin.getSelectedImage = function() {\n\t\treturn _getImageFromRange(self.edit.cmd.range, function(img) {\n\t\t\treturn !/^ke-\\w+$/i.test(img[0].className);\n\t\t});\n\t};\n\tself.plugin.getSelectedFlash = function() {\n\t\treturn _getImageFromRange(self.edit.cmd.range, function(img) {\n\t\t\treturn img[0].className == 'ke-flash';\n\t\t});\n\t};\n\tself.plugin.getSelectedMedia = function() {\n\t\treturn _getImageFromRange(self.edit.cmd.range, function(img) {\n\t\t\treturn img[0].className == 'ke-media' || img[0].className == 'ke-rm';\n\t\t});\n\t};\n\tself.plugin.getSelectedAnchor = function() {\n\t\treturn _getImageFromRange(self.edit.cmd.range, function(img) {\n\t\t\treturn img[0].className == 'ke-anchor';\n\t\t});\n\t};\n\t_each('link,image,flash,media,anchor'.split(','), function(i, name) {\n\t\tvar uName = name.charAt(0).toUpperCase() + name.substr(1);\n\t\t_each('edit,delete'.split(','), function(j, val) {\n\t\t\tself.addContextmenu({\n\t\t\t\ttitle : self.lang(val + uName),\n\t\t\t\tclick : function() {\n\t\t\t\t\tself.loadPlugin(name, function() {\n\t\t\t\t\t\tself.plugin[name][val]();\n\t\t\t\t\t\tself.hideMenu();\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t\tcond : self.plugin['getSelected' + uName],\n\t\t\t\twidth : 150,\n\t\t\t\ticonClass : val == 'edit' ? 'ke-icon-' + name : undefined\n\t\t\t});\n\t\t});\n\t\tself.addContextmenu({ title : '-' });\n\t});\n\tself.plugin.getSelectedTable = function() {\n\t\treturn self.cmd.commonAncestor('table');\n\t};\n\tself.plugin.getSelectedRow = function() {\n\t\treturn self.cmd.commonAncestor('tr');\n\t};\n\tself.plugin.getSelectedCell = function() {\n\t\treturn self.cmd.commonAncestor('td');\n\t};\n\t_each(('prop,cellprop,colinsertleft,colinsertright,rowinsertabove,rowinsertbelow,rowmerge,colmerge,' +\n\t'rowsplit,colsplit,coldelete,rowdelete,insert,delete').split(','), function(i, val) {\n\t\tvar cond = _inArray(val, ['prop', 'delete']) < 0 ? self.plugin.getSelectedCell : self.plugin.getSelectedTable;\n\t\tself.addContextmenu({\n\t\t\ttitle : self.lang('table' + val),\n\t\t\tclick : function() {\n\t\t\t\tself.loadPlugin('table', function() {\n\t\t\t\t\tself.plugin.table[val]();\n\t\t\t\t\tself.hideMenu();\n\t\t\t\t});\n\t\t\t},\n\t\t\tcond : cond,\n\t\t\twidth : 170,\n\t\t\ticonClass : 'ke-icon-table' + val\n\t\t});\n\t});\n\tself.addContextmenu({ title : '-' });\n\t_each(('selectall,justifyleft,justifycenter,justifyright,justifyfull,insertorderedlist,' +\n\t\t'insertunorderedlist,indent,outdent,subscript,superscript,hr,print,' +\n\t\t'bold,italic,underline,strikethrough,removeformat,unlink').split(','), function(i, name) {\n\t\tif (shortcutKeys[name]) {\n\t\t\tself.afterCreate(function() {\n\t\t\t\t_ctrl(this.edit.doc, shortcutKeys[name], function() {\n\t\t\t\t\tself.cmd.selection();\n\t\t\t\t\tself.clickToolbar(name);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\t\tself.clickToolbar(name, function() {\n\t\t\tself.focus().exec(name, null);\n\t\t});\n\t});\n\tself.afterCreate(function() {\n\t\tvar doc = self.edit.doc, cmd, bookmark, div,\n\t\t\tcls = '__kindeditor_paste__', pasting = false;\n\t\tfunction movePastedData() {\n\t\t\tcmd.range.moveToBookmark(bookmark);\n\t\t\tcmd.select();\n\t\t\tif (_WEBKIT) {\n\t\t\t\tK('div.' + cls, div).each(function() {\n\t\t\t\t\tK(this).after('<br />').remove(true);\n\t\t\t\t});\n\t\t\t\tK('span.Apple-style-span', div).remove(true);\n\t\t\t\tK('span.Apple-tab-span', div).remove(true);\n\t\t\t\tK('span[style]', div).each(function() {\n\t\t\t\t\tif (K(this).css('white-space') == 'nowrap') {\n\t\t\t\t\t\tK(this).remove(true);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tK('meta', div).remove();\n\t\t\t}\n\t\t\tvar html = div[0].innerHTML;\n\t\t\tdiv.remove();\n\t\t\tif (html === '') {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (_WEBKIT) {\n\t\t\t\thtml = html.replace(/(<br>)\\1/ig, '$1');\n\t\t\t}\n\t\t\tif (self.pasteType === 2) {\n\t\t\t\thtml = html.replace(/(<(?:p|p\\s[^>]*)>) *(<\\/p>)/ig, '');\n\t\t\t\tif (/schemas-microsoft-com|worddocument|mso-\\w+/i.test(html)) {\n\t\t\t\t\thtml = _clearMsWord(html, self.filterMode ? self.htmlTags : K.options.htmlTags);\n\t\t\t\t} else {\n\t\t\t\t\thtml = _formatHtml(html, self.filterMode ? self.htmlTags : null);\n\t\t\t\t\thtml = self.beforeSetHtml(html);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (self.pasteType === 1) {\n\t\t\t\thtml = html.replace(/&nbsp;/ig, ' ');\n\t\t\t\thtml = html.replace(/\\n\\s*\\n/g, '\\n');\n\t\t\t\thtml = html.replace(/<br[^>]*>/ig, '\\n');\n\t\t\t\thtml = html.replace(/<\\/p><p[^>]*>/ig, '\\n');\n\t\t\t\thtml = html.replace(/<[^>]+>/g, '');\n\t\t\t\thtml = html.replace(/ {2}/g, ' &nbsp;');\n\t\t\t\tif (self.newlineTag == 'p') {\n\t\t\t\t\tif (/\\n/.test(html)) {\n\t\t\t\t\t\thtml = html.replace(/^/, '<p>').replace(/$/, '<br /></p>').replace(/\\n/g, '<br /></p><p>');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\thtml = html.replace(/\\n/g, '<br />$&');\n\t\t\t\t}\n\t\t\t}\n\t\t\tself.insertHtml(html, true);\n\t\t}\n\t\tK(doc.body).bind('paste', function(e){\n\t\t\tif (self.pasteType === 0) {\n\t\t\t\te.stop();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (pasting) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tpasting = true;\n\t\t\tK('div.' + cls, doc).remove();\n\t\t\tcmd = self.cmd.selection();\n\t\t\tbookmark = cmd.range.createBookmark();\n\t\t\tdiv = K('<div class=\"' + cls + '\"></div>', doc).css({\n\t\t\t\tposition : 'absolute',\n\t\t\t\twidth : '1px',\n\t\t\t\theight : '1px',\n\t\t\t\toverflow : 'hidden',\n\t\t\t\tleft : '-1981px',\n\t\t\t\ttop : K(bookmark.start).pos().y + 'px',\n\t\t\t\t'white-space' : 'nowrap'\n\t\t\t});\n\t\t\tK(doc.body).append(div);\n\t\t\tif (_IE) {\n\t\t\t\tvar rng = cmd.range.get(true);\n\t\t\t\trng.moveToElementText(div[0]);\n\t\t\t\trng.select();\n\t\t\t\trng.execCommand('paste');\n\t\t\t\te.preventDefault();\n\t\t\t} else {\n\t\t\t\tcmd.range.selectNodeContents(div[0]);\n\t\t\t\tcmd.select();\n\t\t\t\tdiv[0].tabIndex = -1;\n\t\t\t\tdiv[0].focus();\n\t\t\t}\n\t\t\tsetTimeout(function() {\n\t\t\t\tmovePastedData();\n\t\t\t\tpasting = false;\n\t\t\t}, 0);\n\t\t});\n\t});\n\tself.beforeGetHtml(function(html) {\n\t\tif (_IE && _V <= 8) {\n\t\t\thtml = html.replace(/<div\\s+[^>]*data-ke-input-tag=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/div>/ig, function(full, tag) {\n\t\t\t\treturn unescape(tag);\n\t\t\t});\n\t\t\thtml = html.replace(/(<input)((?:\\s+[^>]*)?>)/ig, function($0, $1, $2) {\n\t\t\t\tif (!/\\s+type=\"[^\"]+\"/i.test($0)) {\n\t\t\t\t\treturn $1 + ' type=\"text\"' + $2;\n\t\t\t\t}\n\t\t\t\treturn $0;\n\t\t\t});\n\t\t}\n\t\treturn html.replace(/(<(?:noscript|noscript\\s[^>]*)>)([\\s\\S]*?)(<\\/noscript>)/ig, function($0, $1, $2, $3) {\n\t\t\treturn $1 + _unescape($2).replace(/\\s+/g, ' ') + $3;\n\t\t})\n\t\t.replace(/<img[^>]*class=\"?ke-(flash|rm|media)\"?[^>]*>/ig, function(full) {\n\t\t\tvar imgAttrs = _getAttrList(full);\n\t\t\tvar styles = _getCssList(imgAttrs.style || '');\n\t\t\tvar attrs = _mediaAttrs(imgAttrs['data-ke-tag']);\n\t\t\tvar width = _undef(styles.width, '');\n\t\t\tvar height = _undef(styles.height, '');\n\t\t\tif (/px/i.test(width)) {\n\t\t\t\twidth = _removeUnit(width);\n\t\t\t}\n\t\t\tif (/px/i.test(height)) {\n\t\t\t\theight = _removeUnit(height);\n\t\t\t}\n\t\t\tattrs.width = _undef(imgAttrs.width, width);\n\t\t\tattrs.height = _undef(imgAttrs.height, height);\n\t\t\treturn _mediaEmbed(attrs);\n\t\t})\n\t\t.replace(/<img[^>]*class=\"?ke-anchor\"?[^>]*>/ig, function(full) {\n\t\t\tvar imgAttrs = _getAttrList(full);\n\t\t\treturn '<a name=\"' + unescape(imgAttrs['data-ke-name']) + '\"></a>';\n\t\t})\n\t\t.replace(/<div\\s+[^>]*data-ke-script-attr=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/div>/ig, function(full, attr, code) {\n\t\t\treturn '<script' + unescape(attr) + '>' + unescape(code) + '</script>';\n\t\t})\n\t\t.replace(/<div\\s+[^>]*data-ke-noscript-attr=\"([^\"]*)\"[^>]*>([\\s\\S]*?)<\\/div>/ig, function(full, attr, code) {\n\t\t\treturn '<noscript' + unescape(attr) + '>' + unescape(code) + '</noscript>';\n\t\t})\n\t\t.replace(/(<[^>]*)data-ke-src=\"([^\"]*)\"([^>]*>)/ig, function(full, start, src, end) {\n\t\t\tfull = full.replace(/(\\s+(?:href|src)=\")[^\"]*(\")/i, function($0, $1, $2) {\n\t\t\t\treturn $1 + _unescape(src) + $2;\n\t\t\t});\n\t\t\tfull = full.replace(/\\s+data-ke-src=\"[^\"]*\"/i, '');\n\t\t\treturn full;\n\t\t})\n\t\t.replace(/(<[^>]+\\s)data-ke-(on\\w+=\"[^\"]*\"[^>]*>)/ig, function(full, start, end) {\n\t\t\treturn start + end;\n\t\t});\n\t});\n\tself.beforeSetHtml(function(html) {\n\t\tif (_IE && _V <= 8) {\n\t\t\thtml = html.replace(/<input[^>]*>|<(select|button)[^>]*>[\\s\\S]*?<\\/\\1>/ig, function(full) {\n\t\t\t\tvar attrs = _getAttrList(full);\n\t\t\t\tvar styles = _getCssList(attrs.style || '');\n\t\t\t\tif (styles.display == 'none') {\n\t\t\t\t\treturn '<div class=\"ke-display-none\" data-ke-input-tag=\"' + escape(full) + '\"></div>';\n\t\t\t\t}\n\t\t\t\treturn full;\n\t\t\t});\n\t\t}\n\t\treturn html.replace(/<embed[^>]*type=\"([^\"]+)\"[^>]*>(?:<\\/embed>)?/ig, function(full) {\n\t\t\tvar attrs = _getAttrList(full);\n\t\t\tattrs.src = _undef(attrs.src, '');\n\t\t\tattrs.width = _undef(attrs.width, 0);\n\t\t\tattrs.height = _undef(attrs.height, 0);\n\t\t\treturn _mediaImg(self.themesPath + 'common/blank.gif', attrs);\n\t\t})\n\t\t.replace(/<a[^>]*name=\"([^\"]+)\"[^>]*>(?:<\\/a>)?/ig, function(full) {\n\t\t\tvar attrs = _getAttrList(full);\n\t\t\tif (attrs.href !== undefined) {\n\t\t\t\treturn full;\n\t\t\t}\n\t\t\treturn '<img class=\"ke-anchor\" src=\"' + self.themesPath + 'common/anchor.gif\" data-ke-name=\"' + escape(attrs.name) + '\" />';\n\t\t})\n\t\t.replace(/<script([^>]*)>([\\s\\S]*?)<\\/script>/ig, function(full, attr, code) {\n\t\t\treturn '<div class=\"ke-script\" data-ke-script-attr=\"' + escape(attr) + '\">' + escape(code) + '</div>';\n\t\t})\n\t\t.replace(/<noscript([^>]*)>([\\s\\S]*?)<\\/noscript>/ig, function(full, attr, code) {\n\t\t\treturn '<div class=\"ke-noscript\" data-ke-noscript-attr=\"' + escape(attr) + '\">' + escape(code) + '</div>';\n\t\t})\n\t\t.replace(/(<[^>]*)(href|src)=\"([^\"]*)\"([^>]*>)/ig, function(full, start, key, src, end) {\n\t\t\tif (full.match(/\\sdata-ke-src=\"[^\"]*\"/i)) {\n\t\t\t\treturn full;\n\t\t\t}\n\t\t\tfull = start + key + '=\"' + src + '\"' + ' data-ke-src=\"' + _escape(src) + '\"' + end;\n\t\t\treturn full;\n\t\t})\n\t\t.replace(/(<[^>]+\\s)(on\\w+=\"[^\"]*\"[^>]*>)/ig, function(full, start, end) {\n\t\t\treturn start + 'data-ke-' + end;\n\t\t})\n\t\t.replace(/<table[^>]*\\s+border=\"0\"[^>]*>/ig, function(full) {\n\t\t\tif (full.indexOf('ke-zeroborder') >= 0) {\n\t\t\t\treturn full;\n\t\t\t}\n\t\t\treturn _addClassToTag(full, 'ke-zeroborder');\n\t\t});\n\t});\n});\n\n\n})(window);\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.lang({\n\tsource : 'HTML代码',\n\tpreview : '预览',\n\tundo : '后退(Ctrl+Z)',\n\tredo : '前进(Ctrl+Y)',\n\tcut : '剪切(Ctrl+X)',\n\tcopy : '复制(Ctrl+C)',\n\tpaste : '粘贴(Ctrl+V)',\n\tplainpaste : '粘贴为无格式文本',\n\twordpaste : '从Word粘贴',\n\tselectall : '全选(Ctrl+A)',\n\tjustifyleft : '左对齐',\n\tjustifycenter : '居中',\n\tjustifyright : '右对齐',\n\tjustifyfull : '两端对齐',\n\tinsertorderedlist : '编号',\n\tinsertunorderedlist : '项目符号',\n\tindent : '增加缩进',\n\toutdent : '减少缩进',\n\tsubscript : '下标',\n\tsuperscript : '上标',\n\tformatblock : '段落',\n\tfontname : '字体',\n\tfontsize : '文字大小',\n\tforecolor : '文字颜色',\n\thilitecolor : '文字背景',\n\tbold : '粗体(Ctrl+B)',\n\titalic : '斜体(Ctrl+I)',\n\tunderline : '下划线(Ctrl+U)',\n\tstrikethrough : '删除线',\n\tremoveformat : '删除格式',\n\timage : '图片',\n\tmultiimage : '批量图片上传',\n\tflash : 'Flash',\n\tmedia : '视音频',\n\ttable : '表格',\n\ttablecell : '单元格',\n\thr : '插入横线',\n\temoticons : '插入表情',\n\tlink : '超级链接',\n\tunlink : '取消超级链接',\n\tfullscreen : '全屏显示',\n\tabout : '关于',\n\tprint : '打印(Ctrl+P)',\n\tfilemanager : '文件空间',\n\tcode : '插入程序代码',\n\tmap : 'Google地图',\n\tbaidumap : '百度地图',\n\tlineheight : '行距',\n\tclearhtml : '清理HTML代码',\n\tpagebreak : '插入分页符',\n\tquickformat : '一键排版',\n\tinsertfile : '插入文件',\n\ttemplate : '插入模板',\n\tanchor : '锚点',\n\tyes : '确定',\n\tno : '取消',\n\tclose : '关闭',\n\teditImage : '图片属性',\n\tdeleteImage : '删除图片',\n\teditFlash : 'Flash属性',\n\tdeleteFlash : '删除Flash',\n\teditMedia : '视音频属性',\n\tdeleteMedia : '删除视音频',\n\teditLink : '超级链接属性',\n\tdeleteLink : '取消超级链接',\n\teditAnchor : '锚点属性',\n\tdeleteAnchor : '删除锚点',\n\ttableprop : '表格属性',\n\ttablecellprop : '单元格属性',\n\ttableinsert : '插入表格',\n\ttabledelete : '删除表格',\n\ttablecolinsertleft : '左侧插入列',\n\ttablecolinsertright : '右侧插入列',\n\ttablerowinsertabove : '上方插入行',\n\ttablerowinsertbelow : '下方插入行',\n\ttablerowmerge : '向下合并单元格',\n\ttablecolmerge : '向右合并单元格',\n\ttablerowsplit : '拆分行',\n\ttablecolsplit : '拆分列',\n\ttablecoldelete : '删除列',\n\ttablerowdelete : '删除行',\n\tnoColor : '无颜色',\n\tpleaseSelectFile : '请选择文件。',\n\tinvalidImg : \"请输入有效的URL地址。\\n只允许jpg,gif,bmp,png格式。\",\n\tinvalidMedia : \"请输入有效的URL地址。\\n只允许swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb格式。\",\n\tinvalidWidth : \"宽度必须为数字。\",\n\tinvalidHeight : \"高度必须为数字。\",\n\tinvalidBorder : \"边框必须为数字。\",\n\tinvalidUrl : \"请输入有效的URL地址。\",\n\tinvalidRows : '行数为必选项，只允许输入大于0的数字。',\n\tinvalidCols : '列数为必选项，只允许输入大于0的数字。',\n\tinvalidPadding : '边距必须为数字。',\n\tinvalidSpacing : '间距必须为数字。',\n\tinvalidJson : '服务器发生故障。',\n\tuploadSuccess : '上传成功。',\n\tcutError : '您的浏览器安全设置不允许使用剪切操作，请使用快捷键(Ctrl+X)来完成。',\n\tcopyError : '您的浏览器安全设置不允许使用复制操作，请使用快捷键(Ctrl+C)来完成。',\n\tpasteError : '您的浏览器安全设置不允许使用粘贴操作，请使用快捷键(Ctrl+V)来完成。',\n\tajaxLoading : '加载中，请稍候 ...',\n\tuploadLoading : '上传中，请稍候 ...',\n\tuploadError : '上传错误',\n\t'plainpaste.comment' : '请使用快捷键(Ctrl+V)把内容粘贴到下面的方框里。',\n\t'wordpaste.comment' : '请使用快捷键(Ctrl+V)把内容粘贴到下面的方框里。',\n\t'code.pleaseInput' : '请输入程序代码。',\n\t'link.url' : 'URL',\n\t'link.linkType' : '打开类型',\n\t'link.newWindow' : '新窗口',\n\t'link.selfWindow' : '当前窗口',\n\t'flash.url' : 'URL',\n\t'flash.width' : '宽度',\n\t'flash.height' : '高度',\n\t'flash.upload' : '上传',\n\t'flash.viewServer' : '文件空间',\n\t'media.url' : 'URL',\n\t'media.width' : '宽度',\n\t'media.height' : '高度',\n\t'media.autostart' : '自动播放',\n\t'media.upload' : '上传',\n\t'media.viewServer' : '文件空间',\n\t'image.remoteImage' : '网络图片',\n\t'image.localImage' : '本地上传',\n\t'image.remoteUrl' : '图片地址',\n\t'image.localUrl' : '上传文件',\n\t'image.size' : '图片大小',\n\t'image.width' : '宽',\n\t'image.height' : '高',\n\t'image.resetSize' : '重置大小',\n\t'image.align' : '对齐方式',\n\t'image.defaultAlign' : '默认方式',\n\t'image.leftAlign' : '左对齐',\n\t'image.rightAlign' : '右对齐',\n\t'image.imgTitle' : '图片说明',\n\t'image.upload' : '浏览...',\n\t'image.viewServer' : '图片空间',\n\t'multiimage.uploadDesc' : '允许用户同时上传<%=uploadLimit%>张图片，单张图片容量不超过<%=sizeLimit%>',\n\t'multiimage.startUpload' : '开始上传',\n\t'multiimage.clearAll' : '全部清空',\n\t'multiimage.insertAll' : '全部插入',\n\t'multiimage.queueLimitExceeded' : '文件数量超过限制。',\n\t'multiimage.fileExceedsSizeLimit' : '文件大小超过限制。',\n\t'multiimage.zeroByteFile' : '无法上传空文件。',\n\t'multiimage.invalidFiletype' : '文件类型不正确。',\n\t'multiimage.unknownError' : '发生异常，无法上传。',\n\t'multiimage.pending' : '等待上传',\n\t'multiimage.uploadError' : '上传失败',\n\t'filemanager.emptyFolder' : '空文件夹',\n\t'filemanager.moveup' : '移到上一级文件夹',\n\t'filemanager.viewType' : '显示方式：',\n\t'filemanager.viewImage' : '缩略图',\n\t'filemanager.listImage' : '详细信息',\n\t'filemanager.orderType' : '排序方式：',\n\t'filemanager.fileName' : '名称',\n\t'filemanager.fileSize' : '大小',\n\t'filemanager.fileType' : '类型',\n\t'insertfile.url' : 'URL',\n\t'insertfile.title' : '文件说明',\n\t'insertfile.upload' : '上传',\n\t'insertfile.viewServer' : '文件空间',\n\t'table.cells' : '单元格数',\n\t'table.rows' : '行数',\n\t'table.cols' : '列数',\n\t'table.size' : '大小',\n\t'table.width' : '宽度',\n\t'table.height' : '高度',\n\t'table.percent' : '%',\n\t'table.px' : 'px',\n\t'table.space' : '边距间距',\n\t'table.padding' : '边距',\n\t'table.spacing' : '间距',\n\t'table.align' : '对齐方式',\n\t'table.textAlign' : '水平对齐',\n\t'table.verticalAlign' : '垂直对齐',\n\t'table.alignDefault' : '默认',\n\t'table.alignLeft' : '左对齐',\n\t'table.alignCenter' : '居中',\n\t'table.alignRight' : '右对齐',\n\t'table.alignTop' : '顶部',\n\t'table.alignMiddle' : '中部',\n\t'table.alignBottom' : '底部',\n\t'table.alignBaseline' : '基线',\n\t'table.border' : '边框',\n\t'table.borderWidth' : '边框',\n\t'table.borderColor' : '颜色',\n\t'table.backgroundColor' : '背景颜色',\n\t'map.address' : '地址: ',\n\t'map.search' : '搜索',\n\t'baidumap.address' : '地址: ',\n\t'baidumap.search' : '搜索',\n\t'baidumap.insertDynamicMap' : '插入动态地图',\n\t'anchor.name' : '锚点名称',\n\t'formatblock.formatBlock' : {\n\t\th1 : '标题 1',\n\t\th2 : '标题 2',\n\t\th3 : '标题 3',\n\t\th4 : '标题 4',\n\t\tp : '正 文'\n\t},\n\t'fontname.fontName' : {\n\t\t'SimSun' : '宋体',\n\t\t'NSimSun' : '新宋体',\n\t\t'FangSong_GB2312' : '仿宋_GB2312',\n\t\t'KaiTi_GB2312' : '楷体_GB2312',\n\t\t'SimHei' : '黑体',\n\t\t'Microsoft YaHei' : '微软雅黑',\n\t\t'Arial' : 'Arial',\n\t\t'Arial Black' : 'Arial Black',\n\t\t'Times New Roman' : 'Times New Roman',\n\t\t'Courier New' : 'Courier New',\n\t\t'Tahoma' : 'Tahoma',\n\t\t'Verdana' : 'Verdana'\n\t},\n\t'lineheight.lineHeight' : [\n\t\t{'1' : '单倍行距'},\n\t\t{'1.5' : '1.5倍行距'},\n\t\t{'2' : '2倍行距'},\n\t\t{'2.5' : '2.5倍行距'},\n\t\t{'3' : '3倍行距'}\n\t],\n\t'template.selectTemplate' : '可选模板',\n\t'template.replaceContent' : '替换当前内容',\n\t'template.fileList' : {\n\t\t'1.html' : '图片和文字',\n\t\t'2.html' : '表格',\n\t\t'3.html' : '项目编号'\n\t}\n}, 'zh-CN');\nKindEditor.options.langType = 'zh-CN';\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('anchor', function(K) {\n\tvar self = this, name = 'anchor', lang = self.lang(name + '.');\n\tself.plugin.anchor = {\n\t\tedit : function() {\n\t\t\tvar html = ['<div style=\"padding:20px;\">',\n\t\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t\t'<label for=\"keName\">' + lang.name + '</label>',\n\t\t\t\t\t'<input class=\"ke-input-text\" type=\"text\" id=\"keName\" name=\"name\" value=\"\" style=\"width:100px;\" />',\n\t\t\t\t\t'</div>',\n\t\t\t\t\t'</div>'].join('');\n\t\t\tvar dialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 300,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tself.insertHtml('<a name=\"' + nameBox.val() + '\">').hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tvar div = dialog.div,\n\t\t\t\tnameBox = K('input[name=\"name\"]', div);\n\t\t\tvar img = self.plugin.getSelectedAnchor();\n\t\t\tif (img) {\n\t\t\t\tnameBox.val(unescape(img.attr('data-ke-name')));\n\t\t\t}\n\t\t\tnameBox[0].focus();\n\t\t\tnameBox[0].select();\n\t\t},\n\t\t'delete' : function() {\n\t\t\tself.plugin.getSelectedAnchor().remove();\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.anchor.edit);\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('autoheight', function(K) {\n\tvar self = this;\n\tif (!self.autoHeightMode) {\n\t\treturn;\n\t}\n\tvar minHeight;\n\tfunction hideScroll() {\n\t\tvar edit = self.edit;\n\t\tvar body = edit.doc.body;\n\t\tedit.iframe[0].scroll = 'no';\n\t\tbody.style.overflowY = 'hidden';\n\t}\n\tfunction resetHeight() {\n\t\tif(self.fullscreenMode){\n\t\t\treturn;\n\t\t}\n\t\tvar edit = self.edit;\n\t\tvar body = edit.doc.body;\n\t\tedit.iframe.height(minHeight);\n\t\tself.resize(null, Math.max((K.IE ? body.scrollHeight : body.offsetHeight) + 76, minHeight));\n\t}\n\tfunction init() {\n\t\tminHeight = K.removeUnit(self.height);\n\t\tself.edit.afterChange(resetHeight);\n\t\tif(!self.fullscreenMode){\n\t\t\thideScroll();\n\t\t}\n\t\tresetHeight();\n\t}\n\tif (self.isCreated) {\n\t\tinit();\n\t} else {\n\t\tself.afterCreate(init);\n\t}\n});\n/*\n* 如何实现真正的自动高度？\n* 修改编辑器高度之后，再次获取body内容高度时，最小值只会是当前iframe的设置高度，这样就导致高度只增不减。\n* 所以每次获取body内容高度之前，先将iframe的高度重置为最小高度，这样就能获取body的实际高度。\n* 由此就实现了真正的自动高度\n* 测试：chrome、firefox、IE9、IE8\n* */\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('baidumap', function(K) {\n\tvar self = this, name = 'baidumap', lang = self.lang(name + '.');\n\tvar mapWidth = K.undef(self.mapWidth, 558);\n\tvar mapHeight = K.undef(self.mapHeight, 360);\n\tself.clickToolbar(name, function() {\n\t\tvar html = ['<div style=\"padding:10px 20px;\">',\n\t\t\t'<div class=\"ke-header\">',\n\t\t\t'<div class=\"ke-left\">',\n\t\t\tlang.address + ' <input id=\"kindeditor_plugin_map_address\" name=\"address\" class=\"ke-input-text\" value=\"\" style=\"width:250px;\" /> ',\n\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t'<input type=\"button\" name=\"searchBtn\" class=\"ke-button-common ke-button\" value=\"' + lang.search + '\" />',\n\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-right\">',\n\t\t\t'<input type=\"checkbox\" id=\"keInsertDynamicMap\" name=\"insertDynamicMap\" value=\"1\" /> <label for=\"keInsertDynamicMap\">' + lang.insertDynamicMap + '</label>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-clearfix\"></div>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-map\" style=\"width:' + mapWidth + 'px;height:' + mapHeight + 'px;\"></div>',\n\t\t\t'</div>'].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : mapWidth + 42,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tyesBtn : {\n\t\t\t\tname : self.lang('yes'),\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tvar map = win.map;\n\t\t\t\t\tvar centerObj = map.getCenter();\n\t\t\t\t\tvar center = centerObj.lng + ',' + centerObj.lat;\n\t\t\t\t\tvar zoom = map.getZoom();\n\t\t\t\t\tvar url = [checkbox[0].checked ? self.pluginsPath + 'baidumap/index.html' : 'http://api.map.baidu.com/staticimage',\n\t\t\t\t\t\t'?center=' + encodeURIComponent(center),\n\t\t\t\t\t\t'&zoom=' + encodeURIComponent(zoom),\n\t\t\t\t\t\t'&width=' + mapWidth,\n\t\t\t\t\t\t'&height=' + mapHeight,\n\t\t\t\t\t\t'&markers=' + encodeURIComponent(center),\n\t\t\t\t\t\t'&markerStyles=' + encodeURIComponent('l,A')].join('');\n\t\t\t\t\tif (checkbox[0].checked) {\n\t\t\t\t\t\tself.insertHtml('<iframe src=\"' + url + '\" frameborder=\"0\" style=\"width:' + (mapWidth + 2) + 'px;height:' + (mapHeight + 2) + 'px;\"></iframe>');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.exec('insertimage', url);\n\t\t\t\t\t}\n\t\t\t\t\tself.hideDialog().focus();\n\t\t\t\t}\n\t\t\t},\n\t\t\tbeforeRemove : function() {\n\t\t\t\tsearchBtn.remove();\n\t\t\t\tif (doc) {\n\t\t\t\t\tdoc.write('');\n\t\t\t\t}\n\t\t\t\tiframe.remove();\n\t\t\t}\n\t\t});\n\t\tvar div = dialog.div,\n\t\t\taddressBox = K('[name=\"address\"]', div),\n\t\t\tsearchBtn = K('[name=\"searchBtn\"]', div),\n\t\t\tcheckbox = K('[name=\"insertDynamicMap\"]', dialog.div),\n\t\t\twin, doc;\n\t\tvar iframe = K('<iframe class=\"ke-textarea\" frameborder=\"0\" src=\"' + self.pluginsPath + 'baidumap/map.html\" style=\"width:' + mapWidth + 'px;height:' + mapHeight + 'px;\"></iframe>');\n\t\tfunction ready() {\n\t\t\twin = iframe[0].contentWindow;\n\t\t\tdoc = K.iframeDoc(iframe);\n\t\t}\n\t\tiframe.bind('load', function() {\n\t\t\tiframe.unbind('load');\n\t\t\tif (K.IE) {\n\t\t\t\tready();\n\t\t\t} else {\n\t\t\t\tsetTimeout(ready, 0);\n\t\t\t}\n\t\t});\n\t\tK('.ke-map', div).replaceWith(iframe);\n\t\tsearchBtn.click(function() {\n\t\t\twin.search(addressBox.val());\n\t\t});\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\n\nKindEditor.plugin('map', function(K) {\n\tvar self = this, name = 'map', lang = self.lang(name + '.');\n\tself.clickToolbar(name, function() {\n\t\tvar html = ['<div style=\"padding:10px 20px;\">',\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\tlang.address + ' <input id=\"kindeditor_plugin_map_address\" name=\"address\" class=\"ke-input-text\" value=\"\" style=\"width:250px;\" /> ',\n\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t'<input type=\"button\" name=\"searchBtn\" class=\"ke-button-common ke-button\" value=\"' + lang.search + '\" />',\n\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-map\" style=\"width:558px;height:360px;\"></div>',\n\t\t\t'</div>'].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : 600,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tyesBtn : {\n\t\t\t\tname : self.lang('yes'),\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tvar geocoder = win.geocoder,\n\t\t\t\t\t\tmap = win.map,\n\t\t\t\t\t\tcenter = map.getCenter().lat() + ',' + map.getCenter().lng(),\n\t\t\t\t\t\tzoom = map.getZoom(),\n\t\t\t\t\t\tmaptype = map.getMapTypeId(),\n\t\t\t\t\t\turl = 'http://maps.googleapis.com/maps/api/staticmap';\n\t\t\t\t\t\turl += '?center=' + encodeURIComponent(center);\n\t\t\t\t\t\turl += '&zoom=' + encodeURIComponent(zoom);\n\t\t\t\t\t\turl += '&size=558x360';\n\t\t\t\t\t\turl += '&maptype=' + encodeURIComponent(maptype);\n\t\t\t\t\t\turl += '&markers=' + encodeURIComponent(center);\n\t\t\t\t\t\turl += '&language=' + self.langType;\n\t\t\t\t\t\turl += '&sensor=false';\n\t\t\t\t\tself.exec('insertimage', url).hideDialog().focus();\n\t\t\t\t}\n\t\t\t},\n\t\t\tbeforeRemove : function() {\n\t\t\t\tsearchBtn.remove();\n\t\t\t\tif (doc) {\n\t\t\t\t\tdoc.write('');\n\t\t\t\t}\n\t\t\t\tiframe.remove();\n\t\t\t}\n\t\t});\n\t\tvar div = dialog.div,\n\t\t\taddressBox = K('[name=\"address\"]', div),\n\t\t\tsearchBtn = K('[name=\"searchBtn\"]', div),\n\t\t\twin, doc;\n\t\tvar iframeHtml = ['<!doctype html><html><head>',\n\t\t\t'<meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no\" />',\n\t\t\t'<style>',\n\t\t\t'\thtml { height: 100% }',\n\t\t\t'\tbody { height: 100%; margin: 0; padding: 0; background-color: #FFF }',\n\t\t\t'\t#map_canvas { height: 100% }',\n\t\t\t'</style>',\n\t\t\t'<script src=\"http://maps.googleapis.com/maps/api/js?sensor=false&language=' + self.langType + '\"></script>',\n\t\t\t'<script>',\n\t\t\t'var map, geocoder;',\n\t\t\t'function initialize() {',\n\t\t\t'\tvar latlng = new google.maps.LatLng(31.230393, 121.473704);',\n\t\t\t'\tvar options = {',\n\t\t\t'\t\tzoom: 11,',\n\t\t\t'\t\tcenter: latlng,',\n\t\t\t'\t\tdisableDefaultUI: true,',\n\t\t\t'\t\tpanControl: true,',\n\t\t\t'\t\tzoomControl: true,',\n\t\t\t'\t\tmapTypeControl: true,',\n\t\t\t'\t\tscaleControl: true,',\n\t\t\t'\t\tstreetViewControl: false,',\n\t\t\t'\t\toverviewMapControl: true,',\n\t\t\t'\t\tmapTypeId: google.maps.MapTypeId.ROADMAP',\n\t\t\t'\t};',\n\t\t\t'\tmap = new google.maps.Map(document.getElementById(\"map_canvas\"), options);',\n\t\t\t'\tgeocoder = new google.maps.Geocoder();',\n\t\t\t'\tgeocoder.geocode({latLng: latlng}, function(results, status) {',\n\t\t\t'\t\tif (status == google.maps.GeocoderStatus.OK) {',\n\t\t\t'\t\t\tif (results[3]) {',\n\t\t\t'\t\t\t\tparent.document.getElementById(\"kindeditor_plugin_map_address\").value = results[3].formatted_address;',\n\t\t\t'\t\t\t}',\n\t\t\t'\t\t}',\n\t\t\t'\t});',\n\t\t\t'}',\n\t\t\t'function search(address) {',\n\t\t\t'\tif (!map) return;',\n\t\t\t'\tgeocoder.geocode({address : address}, function(results, status) {',\n\t\t\t'\t\tif (status == google.maps.GeocoderStatus.OK) {',\n\t\t\t'\t\t\tmap.setZoom(11);',\n\t\t\t'\t\t\tmap.setCenter(results[0].geometry.location);',\n\t\t\t'\t\t\tvar marker = new google.maps.Marker({',\n\t\t\t'\t\t\t\tmap: map,',\n\t\t\t'\t\t\t\tposition: results[0].geometry.location',\n\t\t\t'\t\t\t});',\n\t\t\t'\t\t} else {',\n\t\t\t'\t\t\talert(\"Invalid address: \" + address);',\n\t\t\t'\t\t}',\n\t\t\t'\t});',\n\t\t\t'}',\n\t\t\t'</script>',\n\t\t\t'</head>',\n\t\t\t'<body onload=\"initialize();\">',\n\t\t\t'<div id=\"map_canvas\" style=\"width:100%; height:100%\"></div>',\n\t\t\t'</body></html>'].join('\\n');\n\t\tvar iframe = K('<iframe class=\"ke-textarea\" frameborder=\"0\" src=\"' + self.pluginsPath + 'map/map.html\" style=\"width:558px;height:360px;\"></iframe>');\n\t\tfunction ready() {\n\t\t\twin = iframe[0].contentWindow;\n\t\t\tdoc = K.iframeDoc(iframe);\n\t\t}\n\t\tiframe.bind('load', function() {\n\t\t\tiframe.unbind('load');\n\t\t\tif (K.IE) {\n\t\t\t\tready();\n\t\t\t} else {\n\t\t\t\tsetTimeout(ready, 0);\n\t\t\t}\n\t\t});\n\t\tK('.ke-map', div).replaceWith(iframe);\n\t\tsearchBtn.click(function() {\n\t\t\twin.search(addressBox.val());\n\t\t});\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('clearhtml', function(K) {\n\tvar self = this, name = 'clearhtml';\n\tself.clickToolbar(name, function() {\n\t\tself.focus();\n\t\tvar html = self.html();\n\t\thtml = html.replace(/(<script[^>]*>)([\\s\\S]*?)(<\\/script>)/ig, '');\n\t\thtml = html.replace(/(<style[^>]*>)([\\s\\S]*?)(<\\/style>)/ig, '');\n\t\thtml = K.formatHtml(html, {\n\t\t\ta : ['href', 'target'],\n\t\t\tembed : ['src', 'width', 'height', 'type', 'loop', 'autostart', 'quality', '.width', '.height', 'align', 'allowscriptaccess'],\n\t\t\timg : ['src', 'width', 'height', 'border', 'alt', 'title', '.width', '.height'],\n\t\t\ttable : ['border'],\n\t\t\t'td,th' : ['rowspan', 'colspan'],\n\t\t\t'div,hr,br,tbody,tr,p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6' : []\n\t\t});\n\t\tself.html(html);\n\t\tself.cmd.selection(true);\n\t\tself.addBookmark();\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\n\n\nKindEditor.plugin('code', function(K) {\n\tvar self = this, name = 'code';\n\tself.clickToolbar(name, function() {\n\t\tvar lang = self.lang(name + '.'),\n\t\t\thtml = ['<div style=\"padding:10px 20px;\">',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<select class=\"ke-code-type\">',\n\t\t\t\t'<option value=\"js\">JavaScript</option>',\n\t\t\t\t'<option value=\"html\">HTML</option>',\n\t\t\t\t'<option value=\"css\">CSS</option>',\n\t\t\t\t'<option value=\"php\">PHP</option>',\n\t\t\t\t'<option value=\"pl\">Perl</option>',\n\t\t\t\t'<option value=\"py\">Python</option>',\n\t\t\t\t'<option value=\"rb\">Ruby</option>',\n\t\t\t\t'<option value=\"java\">Java</option>',\n\t\t\t\t'<option value=\"vb\">ASP/VB</option>',\n\t\t\t\t'<option value=\"cpp\">C/C++</option>',\n\t\t\t\t'<option value=\"cs\">C#</option>',\n\t\t\t\t'<option value=\"xml\">XML</option>',\n\t\t\t\t'<option value=\"bsh\">Shell</option>',\n\t\t\t\t'<option value=\"\">Other</option>',\n\t\t\t\t'</select>',\n\t\t\t\t'</div>',\n\t\t\t\t'<textarea class=\"ke-textarea\" style=\"width:408px;height:260px;\"></textarea>',\n\t\t\t\t'</div>'].join(''),\n\t\t\tdialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 450,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar type = K('.ke-code-type', dialog.div).val(),\n\t\t\t\t\t\t\tcode = textarea.val(),\n\t\t\t\t\t\t\tcls = type === '' ? '' :  ' lang-' + type,\n\t\t\t\t\t\t\thtml = '<pre class=\"prettyprint' + cls + '\">\\n' + K.escape(code) + '</pre> ';\n\t\t\t\t\t\tif (K.trim(code) === '') {\n\t\t\t\t\t\t\talert(lang.pleaseInput);\n\t\t\t\t\t\t\ttextarea[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tself.insertHtml(html).hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\ttextarea = K('textarea', dialog.div);\n\t\ttextarea[0].focus();\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('emoticons', function(K) {\n\tvar self = this, name = 'emoticons',\n\t\tpath = (self.emoticonsPath || self.pluginsPath + 'emoticons/images/'),\n\t\tallowPreview = self.allowPreviewEmoticons === undefined ? true : self.allowPreviewEmoticons,\n\t\tcurrentPageNum = 1;\n\tself.clickToolbar(name, function() {\n\t\tvar rows = 5, cols = 9, total = 135, startNum = 0,\n\t\t\tcells = rows * cols, pages = Math.ceil(total / cells),\n\t\t\tcolsHalf = Math.floor(cols / 2),\n\t\t\twrapperDiv = K('<div class=\"ke-plugin-emoticons\"></div>'),\n\t\t\telements = [],\n\t\t\tmenu = self.createMenu({\n\t\t\t\tname : name,\n\t\t\t\tbeforeRemove : function() {\n\t\t\t\t\tremoveEvent();\n\t\t\t\t}\n\t\t\t});\n\t\tmenu.div.append(wrapperDiv);\n\t\tvar previewDiv, previewImg;\n\t\tif (allowPreview) {\n\t\t\tpreviewDiv = K('<div class=\"ke-preview\"></div>').css('right', 0);\n\t\t\tpreviewImg = K('<img class=\"ke-preview-img\" src=\"' + path + startNum + '.gif\" />');\n\t\t\twrapperDiv.append(previewDiv);\n\t\t\tpreviewDiv.append(previewImg);\n\t\t}\n\t\tfunction bindCellEvent(cell, j, num) {\n\t\t\tif (previewDiv) {\n\t\t\t\tcell.mouseover(function() {\n\t\t\t\t\tif (j > colsHalf) {\n\t\t\t\t\t\tpreviewDiv.css('left', 0);\n\t\t\t\t\t\tpreviewDiv.css('right', '');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpreviewDiv.css('left', '');\n\t\t\t\t\t\tpreviewDiv.css('right', 0);\n\t\t\t\t\t}\n\t\t\t\t\tpreviewImg.attr('src', path + num + '.gif');\n\t\t\t\t\tK(this).addClass('ke-on');\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tcell.mouseover(function() {\n\t\t\t\t\tK(this).addClass('ke-on');\n\t\t\t\t});\n\t\t\t}\n\t\t\tcell.mouseout(function() {\n\t\t\t\tK(this).removeClass('ke-on');\n\t\t\t});\n\t\t\tcell.click(function(e) {\n\t\t\t\tself.insertHtml('<img src=\"' + path + num + '.gif\" border=\"0\" alt=\"\" />').hideMenu().focus();\n\t\t\t\te.stop();\n\t\t\t});\n\t\t}\n\t\tfunction createEmoticonsTable(pageNum, parentDiv) {\n\t\t\tvar table = document.createElement('table');\n\t\t\tparentDiv.append(table);\n\t\t\tif (previewDiv) {\n\t\t\t\tK(table).mouseover(function() {\n\t\t\t\t\tpreviewDiv.show('block');\n\t\t\t\t});\n\t\t\t\tK(table).mouseout(function() {\n\t\t\t\t\tpreviewDiv.hide();\n\t\t\t\t});\n\t\t\t\telements.push(K(table));\n\t\t\t}\n\t\t\ttable.className = 'ke-table';\n\t\t\ttable.cellPadding = 0;\n\t\t\ttable.cellSpacing = 0;\n\t\t\ttable.border = 0;\n\t\t\tvar num = (pageNum - 1) * cells + startNum;\n\t\t\tfor (var i = 0; i < rows; i++) {\n\t\t\t\tvar row = table.insertRow(i);\n\t\t\t\tfor (var j = 0; j < cols; j++) {\n\t\t\t\t\tvar cell = K(row.insertCell(j));\n\t\t\t\t\tcell.addClass('ke-cell');\n\t\t\t\t\tbindCellEvent(cell, j, num);\n\t\t\t\t\tvar span = K('<span class=\"ke-img\"></span>')\n\t\t\t\t\t\t.css('background-position', '-' + (24 * num) + 'px 0px')\n\t\t\t\t\t\t.css('background-image', 'url(' + path + 'static.gif)');\n\t\t\t\t\tcell.append(span);\n\t\t\t\t\telements.push(cell);\n\t\t\t\t\tnum++;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn table;\n\t\t}\n\t\tvar table = createEmoticonsTable(currentPageNum, wrapperDiv);\n\t\tfunction removeEvent() {\n\t\t\tK.each(elements, function() {\n\t\t\t\tthis.unbind();\n\t\t\t});\n\t\t}\n\t\tvar pageDiv;\n\t\tfunction bindPageEvent(el, pageNum) {\n\t\t\tel.click(function(e) {\n\t\t\t\tremoveEvent();\n\t\t\t\ttable.parentNode.removeChild(table);\n\t\t\t\tpageDiv.remove();\n\t\t\t\ttable = createEmoticonsTable(pageNum, wrapperDiv);\n\t\t\t\tcreatePageTable(pageNum);\n\t\t\t\tcurrentPageNum = pageNum;\n\t\t\t\te.stop();\n\t\t\t});\n\t\t}\n\t\tfunction createPageTable(currentPageNum) {\n\t\t\tpageDiv = K('<div class=\"ke-page\"></div>');\n\t\t\twrapperDiv.append(pageDiv);\n\t\t\tfor (var pageNum = 1; pageNum <= pages; pageNum++) {\n\t\t\t\tif (currentPageNum !== pageNum) {\n\t\t\t\t\tvar a = K('<a href=\"javascript:;\">[' + pageNum + ']</a>');\n\t\t\t\t\tbindPageEvent(a, pageNum);\n\t\t\t\t\tpageDiv.append(a);\n\t\t\t\t\telements.push(a);\n\t\t\t\t} else {\n\t\t\t\t\tpageDiv.append(K('@[' + pageNum + ']'));\n\t\t\t\t}\n\t\t\t\tpageDiv.append(K('@&nbsp;'));\n\t\t\t}\n\t\t}\n\t\tcreatePageTable(currentPageNum);\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('filemanager', function(K) {\n\tvar self = this, name = 'filemanager',\n\t\tfileManagerJson = K.undef(self.fileManagerJson, self.basePath + 'php/file_manager_json.php'),\n\t\timgPath = self.pluginsPath + name + '/images/',\n\t\tlang = self.lang(name + '.');\n\tfunction makeFileTitle(filename, filesize, datetime) {\n\t\treturn filename + ' (' + Math.ceil(filesize / 1024) + 'KB, ' + datetime + ')';\n\t}\n\tfunction bindTitle(el, data) {\n\t\tif (data.is_dir) {\n\t\t\tel.attr('title', data.filename);\n\t\t} else {\n\t\t\tel.attr('title', makeFileTitle(data.filename, data.filesize, data.datetime));\n\t\t}\n\t}\n\tself.plugin.filemanagerDialog = function(options) {\n\t\tvar width = K.undef(options.width, 650),\n\t\t\theight = K.undef(options.height, 510),\n\t\t\tdirName = K.undef(options.dirName, ''),\n\t\t\tviewType = K.undef(options.viewType, 'VIEW').toUpperCase(),\n\t\t\tclickFn = options.clickFn;\n\t\tvar html = [\n\t\t\t'<div style=\"padding:10px 20px;\">',\n\t\t\t'<div class=\"ke-plugin-filemanager-header\">',\n\t\t\t'<div class=\"ke-left\">',\n\t\t\t'<img class=\"ke-inline-block\" name=\"moveupImg\" src=\"' + imgPath + 'go-up.gif\" width=\"16\" height=\"16\" border=\"0\" alt=\"\" /> ',\n\t\t\t'<a class=\"ke-inline-block\" name=\"moveupLink\" href=\"javascript:;\">' + lang.moveup + '</a>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-right\">',\n\t\t\tlang.viewType + ' <select class=\"ke-inline-block\" name=\"viewType\">',\n\t\t\t'<option value=\"VIEW\">' + lang.viewImage + '</option>',\n\t\t\t'<option value=\"LIST\">' + lang.listImage + '</option>',\n\t\t\t'</select> ',\n\t\t\tlang.orderType + ' <select class=\"ke-inline-block\" name=\"orderType\">',\n\t\t\t'<option value=\"NAME\">' + lang.fileName + '</option>',\n\t\t\t'<option value=\"SIZE\">' + lang.fileSize + '</option>',\n\t\t\t'<option value=\"TYPE\">' + lang.fileType + '</option>',\n\t\t\t'</select>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-clearfix\"></div>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-plugin-filemanager-body\"></div>',\n\t\t\t'</div>'\n\t\t].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : width,\n\t\t\theight : height,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html\n\t\t}),\n\t\tdiv = dialog.div,\n\t\tbodyDiv = K('.ke-plugin-filemanager-body', div),\n\t\tmoveupImg = K('[name=\"moveupImg\"]', div),\n\t\tmoveupLink = K('[name=\"moveupLink\"]', div),\n\t\tviewServerBtn = K('[name=\"viewServer\"]', div),\n\t\tviewTypeBox = K('[name=\"viewType\"]', div),\n\t\torderTypeBox = K('[name=\"orderType\"]', div);\n\t\tfunction reloadPage(path, order, func) {\n\t\t\tvar param = 'path=' + path + '&order=' + order + '&dir=' + dirName;\n\t\t\tdialog.showLoading(self.lang('ajaxLoading'));\n\t\t\tK.ajax(K.addParam(fileManagerJson, param + '&' + new Date().getTime()), function(data) {\n\t\t\t\tdialog.hideLoading();\n\t\t\t\tfunc(data);\n\t\t\t});\n\t\t}\n\t\tvar elList = [];\n\t\tfunction bindEvent(el, result, data, createFunc) {\n\t\t\tvar fileUrl = K.formatUrl(result.current_url + data.filename, 'absolute'),\n\t\t\t\tdirPath = encodeURIComponent(result.current_dir_path + data.filename + '/');\n\t\t\tif (data.is_dir) {\n\t\t\t\tel.click(function(e) {\n\t\t\t\t\treloadPage(dirPath, orderTypeBox.val(), createFunc);\n\t\t\t\t});\n\t\t\t} else if (data.is_photo) {\n\t\t\t\tel.click(function(e) {\n\t\t\t\t\tclickFn.call(this, fileUrl, data.filename);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tel.click(function(e) {\n\t\t\t\t\tclickFn.call(this, fileUrl, data.filename);\n\t\t\t\t});\n\t\t\t}\n\t\t\telList.push(el);\n\t\t}\n\t\tfunction createCommon(result, createFunc) {\n\t\t\tK.each(elList, function() {\n\t\t\t\tthis.unbind();\n\t\t\t});\n\t\t\tmoveupLink.unbind();\n\t\t\tviewTypeBox.unbind();\n\t\t\torderTypeBox.unbind();\n\t\t\tif (result.current_dir_path) {\n\t\t\t\tmoveupLink.click(function(e) {\n\t\t\t\t\treloadPage(result.moveup_dir_path, orderTypeBox.val(), createFunc);\n\t\t\t\t});\n\t\t\t}\n\t\t\tfunction changeFunc() {\n\t\t\t\tif (viewTypeBox.val() == 'VIEW') {\n\t\t\t\t\treloadPage(result.current_dir_path, orderTypeBox.val(), createView);\n\t\t\t\t} else {\n\t\t\t\t\treloadPage(result.current_dir_path, orderTypeBox.val(), createList);\n\t\t\t\t}\n\t\t\t}\n\t\t\tviewTypeBox.change(changeFunc);\n\t\t\torderTypeBox.change(changeFunc);\n\t\t\tbodyDiv.html('');\n\t\t}\n\t\tfunction createList(result) {\n\t\t\tcreateCommon(result, createList);\n\t\t\tvar table = document.createElement('table');\n\t\t\ttable.className = 'ke-table';\n\t\t\ttable.cellPadding = 0;\n\t\t\ttable.cellSpacing = 0;\n\t\t\ttable.border = 0;\n\t\t\tbodyDiv.append(table);\n\t\t\tvar fileList = result.file_list;\n\t\t\tfor (var i = 0, len = fileList.length; i < len; i++) {\n\t\t\t\tvar data = fileList[i], row = K(table.insertRow(i));\n\t\t\t\trow.mouseover(function(e) {\n\t\t\t\t\tK(this).addClass('ke-on');\n\t\t\t\t})\n\t\t\t\t.mouseout(function(e) {\n\t\t\t\t\tK(this).removeClass('ke-on');\n\t\t\t\t});\n\t\t\t\tvar iconUrl = imgPath + (data.is_dir ? 'folder-16.gif' : 'file-16.gif'),\n\t\t\t\t\timg = K('<img src=\"' + iconUrl + '\" width=\"16\" height=\"16\" alt=\"' + data.filename + '\" align=\"absmiddle\" />'),\n\t\t\t\t\tcell0 = K(row[0].insertCell(0)).addClass('ke-cell ke-name').append(img).append(document.createTextNode(' ' + data.filename));\n\t\t\t\tif (!data.is_dir || data.has_file) {\n\t\t\t\t\trow.css('cursor', 'pointer');\n\t\t\t\t\tcell0.attr('title', data.filename);\n\t\t\t\t\tbindEvent(cell0, result, data, createList);\n\t\t\t\t} else {\n\t\t\t\t\tcell0.attr('title', lang.emptyFolder);\n\t\t\t\t}\n\t\t\t\tK(row[0].insertCell(1)).addClass('ke-cell ke-size').html(data.is_dir ? '-' : Math.ceil(data.filesize / 1024) + 'KB');\n\t\t\t\tK(row[0].insertCell(2)).addClass('ke-cell ke-datetime').html(data.datetime);\n\t\t\t}\n\t\t}\n\t\tfunction createView(result) {\n\t\t\tcreateCommon(result, createView);\n\t\t\tvar fileList = result.file_list;\n\t\t\tfor (var i = 0, len = fileList.length; i < len; i++) {\n\t\t\t\tvar data = fileList[i],\n\t\t\t\t\tdiv = K('<div class=\"ke-inline-block ke-item\"></div>');\n\t\t\t\tbodyDiv.append(div);\n\t\t\t\tvar photoDiv = K('<div class=\"ke-inline-block ke-photo\"></div>')\n\t\t\t\t\t.mouseover(function(e) {\n\t\t\t\t\t\tK(this).addClass('ke-on');\n\t\t\t\t\t})\n\t\t\t\t\t.mouseout(function(e) {\n\t\t\t\t\t\tK(this).removeClass('ke-on');\n\t\t\t\t\t});\n\t\t\t\tdiv.append(photoDiv);\n\t\t\t\tvar fileUrl = result.current_url + data.filename,\n\t\t\t\t\ticonUrl = data.is_dir ? imgPath + 'folder-64.gif' : (data.is_photo ? fileUrl : imgPath + 'file-64.gif');\n\t\t\t\tvar img = K('<img src=\"' + iconUrl + '\" width=\"80\" height=\"80\" alt=\"' + data.filename + '\" />');\n\t\t\t\tif (!data.is_dir || data.has_file) {\n\t\t\t\t\tphotoDiv.css('cursor', 'pointer');\n\t\t\t\t\tbindTitle(photoDiv, data);\n\t\t\t\t\tbindEvent(photoDiv, result, data, createView);\n\t\t\t\t} else {\n\t\t\t\t\tphotoDiv.attr('title', lang.emptyFolder);\n\t\t\t\t}\n\t\t\t\tphotoDiv.append(img);\n\t\t\t\tdiv.append('<div class=\"ke-name\" title=\"' + data.filename + '\">' + data.filename + '</div>');\n\t\t\t}\n\t\t}\n\t\tviewTypeBox.val(viewType);\n\t\treloadPage('', orderTypeBox.val(), viewType == 'VIEW' ? createView : createList);\n\t\treturn dialog;\n\t}\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('flash', function(K) {\n\tvar self = this, name = 'flash', lang = self.lang(name + '.'),\n\t\tallowFlashUpload = K.undef(self.allowFlashUpload, true),\n\t\tallowFileManager = K.undef(self.allowFileManager, false),\n\t\tformatUploadUrl = K.undef(self.formatUploadUrl, true),\n\t\textraParams = K.undef(self.extraFileUploadParams, {}),\n\t\tfilePostName = K.undef(self.filePostName, 'imgFile'),\n\t\tuploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php');\n\tself.plugin.flash = {\n\t\tedit : function() {\n\t\t\tvar html = [\n\t\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keUrl\" style=\"width:60px;\">' + lang.url + '</label>',\n\t\t\t\t'<input class=\"ke-input-text\" type=\"text\" id=\"keUrl\" name=\"url\" value=\"\" style=\"width:250px;\" /> &nbsp;',\n\t\t\t\t/*'<input type=\"button\" style=\"display: none\" class=\"ke-upload-button\" value=\"' + lang.upload + '\" /> &nbsp;',\n\t\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" name=\"viewServer\" value=\"' + lang.viewServer + '\" />',*/\n\t\t\t\t'</span>',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keWidth\" style=\"width:60px;\">' + lang.width + '</label>',\n\t\t\t\t'<input type=\"text\" id=\"keWidth\" class=\"ke-input-text ke-input-number\" name=\"width\" value=\"550\" maxlength=\"4\" /> ',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keHeight\" style=\"width:60px;\">' + lang.height + '</label>',\n\t\t\t\t'<input type=\"text\" id=\"keHeight\" class=\"ke-input-text ke-input-number\" name=\"height\" value=\"400\" maxlength=\"4\" /> ',\n\t\t\t\t'</div>',\n\t\t\t\t'</div>'\n\t\t\t].join('');\n\t\t\tvar dialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 450,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar url = K.trim(urlBox.val()),\n\t\t\t\t\t\t\twidth = widthBox.val(),\n\t\t\t\t\t\t\theight = heightBox.val();\n\t\t\t\t\t\tif (url == 'http://' || K.invalidUrl(url)) {\n\t\t\t\t\t\t\talert(self.lang('invalidUrl'));\n\t\t\t\t\t\t\turlBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(width)) {\n\t\t\t\t\t\t\talert(self.lang('invalidWidth'));\n\t\t\t\t\t\t\twidthBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(height)) {\n\t\t\t\t\t\t\talert(self.lang('invalidHeight'));\n\t\t\t\t\t\t\theightBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar html = K.mediaImg(self.themesPath + 'common/blank.gif', {\n\t\t\t\t\t\t\t\tsrc : url,\n\t\t\t\t\t\t\t\ttype : K.mediaType('.swf'),\n\t\t\t\t\t\t\t\twidth : width,\n\t\t\t\t\t\t\t\theight : height,\n\t\t\t\t\t\t\t\tquality : 'high'\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\tself.insertHtml(html).hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\tdiv = dialog.div,\n\t\t\turlBox = K('[name=\"url\"]', div),\n\t\t\tviewServerBtn = K('[name=\"viewServer\"]', div),\n\t\t\twidthBox = K('[name=\"width\"]', div),\n\t\t\theightBox = K('[name=\"height\"]', div);\n\t\t\turlBox.val('http://');\n\t\t\tif (allowFlashUpload) {\n\t\t\t\tvar uploadbutton = K.uploadbutton({\n\t\t\t\t\tbutton : K('.ke-upload-button', div)[0],\n\t\t\t\t\tfieldName : filePostName,\n\t\t\t\t\textraParams : extraParams,\n\t\t\t\t\turl : K.addParam(uploadJson, 'dir=flash'),\n\t\t\t\t\tafterUpload : function(data) {\n\t\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\t\tif (data.error === 0) {\n\t\t\t\t\t\t\tvar url = data.url;\n\t\t\t\t\t\t\tif (formatUploadUrl) {\n\t\t\t\t\t\t\t\turl = K.formatUrl(url, 'absolute');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\turlBox.val(url);\n\t\t\t\t\t\t\tif (self.afterUpload) {\n\t\t\t\t\t\t\t\tself.afterUpload.call(self, url, data, name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\talert(self.lang('uploadSuccess'));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\talert(data.message);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tafterError : function(html) {\n\t\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\t\tself.errorDialog(html);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tuploadbutton.fileBox.change(function(e) {\n\t\t\t\t\tdialog.showLoading(self.lang('uploadLoading'));\n\t\t\t\t\tuploadbutton.submit();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tK('.ke-upload-button', div).hide();\n\t\t\t}\n\t\t\tif (allowFileManager) {\n\t\t\t\tviewServerBtn.click(function(e) {\n\t\t\t\t\tself.loadPlugin('filemanager', function() {\n\t\t\t\t\t\tself.plugin.filemanagerDialog({\n\t\t\t\t\t\t\tviewType : 'LIST',\n\t\t\t\t\t\t\tdirName : 'flash',\n\t\t\t\t\t\t\tclickFn : function(url, title) {\n\t\t\t\t\t\t\t\tif (self.dialogs.length > 1) {\n\t\t\t\t\t\t\t\t\tK('[name=\"url\"]', div).val(url);\n\t\t\t\t\t\t\t\t\tif (self.afterSelectFile) {\n\t\t\t\t\t\t\t\t\t\tself.afterSelectFile.call(self, url);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tself.hideDialog();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tviewServerBtn.hide();\n\t\t\t}\n\t\t\tvar img = self.plugin.getSelectedFlash();\n\t\t\tif (img) {\n\t\t\t\tvar attrs = K.mediaAttrs(img.attr('data-ke-tag'));\n\t\t\t\turlBox.val(attrs.src);\n\t\t\t\twidthBox.val(K.removeUnit(img.css('width')) || attrs.width || 0);\n\t\t\t\theightBox.val(K.removeUnit(img.css('height')) || attrs.height || 0);\n\t\t\t}\n\t\t\turlBox[0].focus();\n\t\t\turlBox[0].select();\n\t\t},\n\t\t'delete' : function() {\n\t\t\tself.plugin.getSelectedFlash().remove();\n\t\t\tself.addBookmark();\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.flash.edit);\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('image', function(K) {\n\tvar self = this, name = 'image',\n\t\tallowImageUpload = K.undef(self.allowImageUpload, true),\n\t\tallowImageRemote = K.undef(self.allowImageRemote, true),\n\t\tformatUploadUrl = K.undef(self.formatUploadUrl, true),\n\t\tallowFileManager = K.undef(self.allowFileManager, false),\n\t\tuploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'),\n\t\timageTabIndex = K.undef(self.imageTabIndex, 0),\n\t\timgPath = self.pluginsPath + 'image/images/',\n\t\textraParams = K.undef(self.extraFileUploadParams, {}),\n\t\tfilePostName = K.undef(self.filePostName, 'imgFile'),\n\t\tfillDescAfterUploadImage = K.undef(self.fillDescAfterUploadImage, false),\n\t\tlang = self.lang(name + '.');\n\tself.plugin.imageDialog = function(options) {\n\t\tvar imageUrl = options.imageUrl,\n\t\t\timageWidth = K.undef(options.imageWidth, ''),\n\t\t\timageHeight = K.undef(options.imageHeight, ''),\n\t\t\timageTitle = K.undef(options.imageTitle, ''),\n\t\t\timageAlign = K.undef(options.imageAlign, ''),\n\t\t\tshowRemote = K.undef(options.showRemote, true),\n\t\t\tshowLocal = K.undef(options.showLocal, true),\n\t\t\ttabIndex = K.undef(options.tabIndex, 0),\n\t\t\tclickFn = options.clickFn;\n\t\tvar target = 'kindeditor_upload_iframe_' + new Date().getTime();\n\t\tvar hiddenElements = [];\n\t\tfor(var k in extraParams){\n\t\t\thiddenElements.push('<input type=\"hidden\" name=\"' + k + '\" value=\"' + extraParams[k] + '\" />');\n\t\t}\n\t\tvar html = [\n\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t'<div class=\"tabs\"></div>',\n\t\t\t'<div class=\"tab1\" style=\"display:none;\">',\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label for=\"remoteUrl\" style=\"width:60px;\">' + lang.remoteUrl + '</label>',\n\t\t\t'<input type=\"text\" id=\"remoteUrl\" class=\"ke-input-text\" name=\"url\" value=\"\" style=\"width:250px;\" /> &nbsp;',\n\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" name=\"viewServer\" value=\"' + lang.viewServer + '\" />',\n\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label for=\"remoteWidth\" style=\"width:60px;\">' + lang.size + '</label>',\n\t\t\tlang.width + ' <input type=\"text\" id=\"remoteWidth\" class=\"ke-input-text ke-input-number\" name=\"width\" value=\"\" maxlength=\"4\" /> ',\n\t\t\tlang.height + ' <input type=\"text\" class=\"ke-input-text ke-input-number\" name=\"height\" value=\"\" maxlength=\"4\" /> ',\n\t\t\t'<img class=\"ke-refresh-btn\" src=\"' + imgPath + 'refresh.png\" width=\"16\" height=\"16\" alt=\"\" style=\"cursor:pointer;\" title=\"' + lang.resetSize + '\" />',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label style=\"width:60px;\">' + lang.align + '</label>',\n\t\t\t'<input type=\"radio\" name=\"align\" class=\"ke-inline-block\" value=\"\" checked=\"checked\" /> <img name=\"defaultImg\" src=\"' + imgPath + 'align_top.gif\" width=\"23\" height=\"25\" alt=\"\" />',\n\t\t\t' <input type=\"radio\" name=\"align\" class=\"ke-inline-block\" value=\"left\" /> <img name=\"leftImg\" src=\"' + imgPath + 'align_left.gif\" width=\"23\" height=\"25\" alt=\"\" />',\n\t\t\t' <input type=\"radio\" name=\"align\" class=\"ke-inline-block\" value=\"right\" /> <img name=\"rightImg\" src=\"' + imgPath + 'align_right.gif\" width=\"23\" height=\"25\" alt=\"\" />',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label for=\"remoteTitle\" style=\"width:60px;\">' + lang.imgTitle + '</label>',\n\t\t\t'<input type=\"text\" id=\"remoteTitle\" class=\"ke-input-text\" name=\"title\" value=\"\" style=\"width:250px;\" />',\n\t\t\t'</div>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"tab2\" style=\"display:none;\">',\n\t\t\t'<iframe name=\"' + target + '\" style=\"display:none;\"></iframe>',\n\t\t\t'<form class=\"ke-upload-area ke-form\" method=\"post\" enctype=\"multipart/form-data\" target=\"' + target + '\" action=\"' + K.addParam(uploadJson, 'dir=image') + '\">',\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\thiddenElements.join(''),\n\t\t\t'<label style=\"width:60px;\">' + lang.localUrl + '</label>',\n\t\t\t'<input type=\"text\" name=\"localUrl\" class=\"ke-input-text\" tabindex=\"-1\" style=\"width:250px;\" readonly=\"true\" /> &nbsp;',\n\t\t\t'<input type=\"button\" class=\"ke-upload-button\" value=\"' + lang.upload + '\" />',\n\t\t\t'</div>',\n\t\t\t'</form>',\n\t\t\t'</div>',\n\t\t\t'</div>'\n\t\t].join('');\n\t\tvar dialogWidth = showLocal || allowFileManager ? 450 : 400,\n\t\t\tdialogHeight = showLocal && showRemote ? 300 : 250;\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : dialogWidth,\n\t\t\theight : dialogHeight,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tyesBtn : {\n\t\t\t\tname : self.lang('yes'),\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tif (dialog.isLoading) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (showLocal && showRemote && tabs && tabs.selectedIndex === 1 || !showRemote) {\n\t\t\t\t\t\tif (uploadbutton.fileBox.val() == '') {\n\t\t\t\t\t\t\talert(self.lang('pleaseSelectFile'));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdialog.showLoading(self.lang('uploadLoading'));\n\t\t\t\t\t\tuploadbutton.submit();\n\t\t\t\t\t\tlocalUrlBox.val('');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar url = K.trim(urlBox.val()),\n\t\t\t\t\t\twidth = widthBox.val(),\n\t\t\t\t\t\theight = heightBox.val(),\n\t\t\t\t\t\ttitle = titleBox.val(),\n\t\t\t\t\t\talign = '';\n\t\t\t\t\talignBox.each(function() {\n\t\t\t\t\t\tif (this.checked) {\n\t\t\t\t\t\t\talign = this.value;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif (url == 'http://' || K.invalidUrl(url)) {\n\t\t\t\t\t\talert(self.lang('invalidUrl'));\n\t\t\t\t\t\turlBox[0].focus();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!/^\\d*$/.test(width)) {\n\t\t\t\t\t\talert(self.lang('invalidWidth'));\n\t\t\t\t\t\twidthBox[0].focus();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!/^\\d*$/.test(height)) {\n\t\t\t\t\t\talert(self.lang('invalidHeight'));\n\t\t\t\t\t\theightBox[0].focus();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tclickFn.call(self, url, title, width, height, 0, align);\n\t\t\t\t}\n\t\t\t},\n\t\t\tbeforeRemove : function() {\n\t\t\t\tviewServerBtn.unbind();\n\t\t\t\twidthBox.unbind();\n\t\t\t\theightBox.unbind();\n\t\t\t\trefreshBtn.unbind();\n\t\t\t}\n\t\t}),\n\t\tdiv = dialog.div;\n\t\tvar urlBox = K('[name=\"url\"]', div),\n\t\t\tlocalUrlBox = K('[name=\"localUrl\"]', div),\n\t\t\tviewServerBtn = K('[name=\"viewServer\"]', div),\n\t\t\twidthBox = K('.tab1 [name=\"width\"]', div),\n\t\t\theightBox = K('.tab1 [name=\"height\"]', div),\n\t\t\trefreshBtn = K('.ke-refresh-btn', div),\n\t\t\ttitleBox = K('.tab1 [name=\"title\"]', div),\n\t\t\talignBox = K('.tab1 [name=\"align\"]', div);\n\t\tvar tabs;\n\t\tif (showRemote && showLocal) {\n\t\t\ttabs = K.tabs({\n\t\t\t\tsrc : K('.tabs', div),\n\t\t\t\tafterSelect : function(i) {}\n\t\t\t});\n\t\t\ttabs.add({\n\t\t\t\ttitle : lang.remoteImage,\n\t\t\t\tpanel : K('.tab1', div)\n\t\t\t});\n\t\t\ttabs.add({\n\t\t\t\ttitle : lang.localImage,\n\t\t\t\tpanel : K('.tab2', div)\n\t\t\t});\n\t\t\ttabs.select(tabIndex);\n\t\t} else if (showRemote) {\n\t\t\tK('.tab1', div).show();\n\t\t} else if (showLocal) {\n\t\t\tK('.tab2', div).show();\n\t\t}\n\t\tvar uploadbutton = K.uploadbutton({\n\t\t\tbutton : K('.ke-upload-button', div)[0],\n\t\t\tfieldName : filePostName,\n\t\t\tform : K('.ke-form', div),\n\t\t\ttarget : target,\n\t\t\twidth: 60,\n\t\t\tafterUpload : function(data) {\n\t\t\t\tdialog.hideLoading();\n\t\t\t\tif (data.error === 0) {\n\t\t\t\t\tvar url = data.url;\n\t\t\t\t\tif (formatUploadUrl) {\n\t\t\t\t\t\turl = K.formatUrl(url, 'absolute');\n\t\t\t\t\t}\n\t\t\t\t\tif (self.afterUpload) {\n\t\t\t\t\t\tself.afterUpload.call(self, url, data, name);\n\t\t\t\t\t}\n\t\t\t\t\tif (!fillDescAfterUploadImage) {\n\t\t\t\t\t\tclickFn.call(self, url, data.title, data.width, data.height, data.border, data.align);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tK(\".ke-dialog-row #remoteUrl\", div).val(url);\n\t\t\t\t\t\tK(\".ke-tabs-li\", div)[0].click();\n\t\t\t\t\t\tK(\".ke-refresh-btn\", div).click();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\talert(data.message);\n\t\t\t\t}\n\t\t\t},\n\t\t\tafterError : function(html) {\n\t\t\t\tdialog.hideLoading();\n\t\t\t\tself.errorDialog(html);\n\t\t\t}\n\t\t});\n\t\tuploadbutton.fileBox.change(function(e) {\n\t\t\tlocalUrlBox.val(uploadbutton.fileBox.val());\n\t\t});\n\t\tif (allowFileManager) {\n\t\t\tviewServerBtn.click(function(e) {\n\t\t\t\tself.loadPlugin('filemanager', function() {\n\t\t\t\t\tself.plugin.filemanagerDialog({\n\t\t\t\t\t\tviewType : 'VIEW',\n\t\t\t\t\t\tdirName : 'image',\n\t\t\t\t\t\tclickFn : function(url, title) {\n\t\t\t\t\t\t\tif (self.dialogs.length > 1) {\n\t\t\t\t\t\t\t\tK('[name=\"url\"]', div).val(url);\n\t\t\t\t\t\t\t\tif (self.afterSelectFile) {\n\t\t\t\t\t\t\t\t\tself.afterSelectFile.call(self, url);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tself.hideDialog();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\tviewServerBtn.hide();\n\t\t}\n\t\tvar originalWidth = 0, originalHeight = 0;\n\t\tfunction setSize(width, height) {\n\t\t\twidthBox.val(width);\n\t\t\theightBox.val(height);\n\t\t\toriginalWidth = width;\n\t\t\toriginalHeight = height;\n\t\t}\n\t\trefreshBtn.click(function(e) {\n\t\t\tvar tempImg = K('<img src=\"' + urlBox.val() + '\" />', document).css({\n\t\t\t\tposition : 'absolute',\n\t\t\t\tvisibility : 'hidden',\n\t\t\t\ttop : 0,\n\t\t\t\tleft : '-1000px'\n\t\t\t});\n\t\t\ttempImg.bind('load', function() {\n\t\t\t\tsetSize(tempImg.width(), tempImg.height());\n\t\t\t\ttempImg.remove();\n\t\t\t});\n\t\t\tK(document.body).append(tempImg);\n\t\t});\n\t\twidthBox.change(function(e) {\n\t\t\tif (originalWidth > 0) {\n\t\t\t\theightBox.val(Math.round(originalHeight / originalWidth * parseInt(this.value, 10)));\n\t\t\t}\n\t\t});\n\t\theightBox.change(function(e) {\n\t\t\tif (originalHeight > 0) {\n\t\t\t\twidthBox.val(Math.round(originalWidth / originalHeight * parseInt(this.value, 10)));\n\t\t\t}\n\t\t});\n\t\turlBox.val(options.imageUrl);\n\t\tsetSize(options.imageWidth, options.imageHeight);\n\t\ttitleBox.val(options.imageTitle);\n\t\talignBox.each(function() {\n\t\t\tif (this.value === options.imageAlign) {\n\t\t\t\tthis.checked = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif (showRemote && tabIndex === 0) {\n\t\t\turlBox[0].focus();\n\t\t\turlBox[0].select();\n\t\t}\n\t\treturn dialog;\n\t};\n\tself.plugin.image = {\n\t\tedit : function() {\n\t\t\tvar img = self.plugin.getSelectedImage();\n\t\t\tself.plugin.imageDialog({\n\t\t\t\timageUrl : img ? img.attr('data-ke-src') : 'http://',\n\t\t\t\timageWidth : img ? img.width() : '',\n\t\t\t\timageHeight : img ? img.height() : '',\n\t\t\t\timageTitle : img ? img.attr('title') : '',\n\t\t\t\timageAlign : img ? img.attr('align') : '',\n\t\t\t\tshowRemote : allowImageRemote,\n\t\t\t\tshowLocal : allowImageUpload,\n\t\t\t\ttabIndex: img ? 0 : imageTabIndex,\n\t\t\t\tclickFn : function(url, title, width, height, border, align) {\n\t\t\t\t\tif (img) {\n\t\t\t\t\t\timg.attr('src', url);\n\t\t\t\t\t\timg.attr('data-ke-src', url);\n\t\t\t\t\t\timg.attr('width', width);\n\t\t\t\t\t\timg.attr('height', height);\n\t\t\t\t\t\timg.attr('title', title);\n\t\t\t\t\t\timg.attr('align', align);\n\t\t\t\t\t\timg.attr('alt', title);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.exec('insertimage', url, title, width, height, border, align);\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tself.hideDialog().focus();\n\t\t\t\t\t}, 0);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\t'delete' : function() {\n\t\t\tvar target = self.plugin.getSelectedImage();\n\t\t\tif (target.parent().name == 'a') {\n\t\t\t\ttarget = target.parent();\n\t\t\t}\n\t\t\ttarget.remove();\n\t\t\tself.addBookmark();\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.image.edit);\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('insertfile', function(K) {\n\tvar self = this, name = 'insertfile',\n\t\tallowFileUpload = K.undef(self.allowFileUpload, true),\n\t\tallowFileManager = K.undef(self.allowFileManager, false),\n\t\tformatUploadUrl = K.undef(self.formatUploadUrl, true),\n\t\tuploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'),\n\t\textraParams = K.undef(self.extraFileUploadParams, {}),\n\t\tfilePostName = K.undef(self.filePostName, 'imgFile'),\n\t\tlang = self.lang(name + '.');\n\tself.plugin.fileDialog = function(options) {\n\t\tvar fileUrl = K.undef(options.fileUrl, 'http://'),\n\t\t\tfileTitle = K.undef(options.fileTitle, ''),\n\t\t\tclickFn = options.clickFn;\n\t\tvar html = [\n\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label for=\"keUrl\" style=\"width:60px;\">' + lang.url + '</label>',\n\t\t\t'<input type=\"text\" id=\"keUrl\" name=\"url\" class=\"ke-input-text\" style=\"width:160px;\" /> &nbsp;',\n\t\t\t'<input type=\"button\" class=\"ke-upload-button\" value=\"' + lang.upload + '\" /> &nbsp;',\n\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" name=\"viewServer\" value=\"' + lang.viewServer + '\" />',\n\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label for=\"keTitle\" style=\"width:60px;\">' + lang.title + '</label>',\n\t\t\t'<input type=\"text\" id=\"keTitle\" class=\"ke-input-text\" name=\"title\" value=\"\" style=\"width:160px;\" /></div>',\n\t\t\t'</div>',\n\t\t\t'</form>',\n\t\t\t'</div>'\n\t\t\t].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : 450,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tyesBtn : {\n\t\t\t\tname : self.lang('yes'),\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tvar url = K.trim(urlBox.val()),\n\t\t\t\t\t\ttitle = titleBox.val();\n\t\t\t\t\tif (url == 'http://' || K.invalidUrl(url)) {\n\t\t\t\t\t\talert(self.lang('invalidUrl'));\n\t\t\t\t\t\turlBox[0].focus();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (K.trim(title) === '') {\n\t\t\t\t\t\ttitle = url;\n\t\t\t\t\t}\n\t\t\t\t\tclickFn.call(self, url, title);\n\t\t\t\t}\n\t\t\t}\n\t\t}),\n\t\tdiv = dialog.div;\n\t\tvar urlBox = K('[name=\"url\"]', div),\n\t\t\tviewServerBtn = K('[name=\"viewServer\"]', div),\n\t\t\ttitleBox = K('[name=\"title\"]', div);\n\t\tif (allowFileUpload) {\n\t\t\tvar uploadbutton = K.uploadbutton({\n\t\t\t\tbutton : K('.ke-upload-button', div)[0],\n\t\t\t\tfieldName : filePostName,\n\t\t\t\turl : K.addParam(uploadJson, 'dir=file'),\n\t\t\t\textraParams : extraParams,\n\t\t\t\tafterUpload : function(data) {\n\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\tif (data.error === 0) {\n\t\t\t\t\t\tvar url = data.url;\n\t\t\t\t\t\tif (formatUploadUrl) {\n\t\t\t\t\t\t\turl = K.formatUrl(url, 'absolute');\n\t\t\t\t\t\t}\n\t\t\t\t\t\turlBox.val(url);\n\t\t\t\t\t\tif (self.afterUpload) {\n\t\t\t\t\t\t\tself.afterUpload.call(self, url, data, name);\n\t\t\t\t\t\t}\n\t\t\t\t\t\talert(self.lang('uploadSuccess'));\n\t\t\t\t\t} else {\n\t\t\t\t\t\talert(data.message);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tafterError : function(html) {\n\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\tself.errorDialog(html);\n\t\t\t\t}\n\t\t\t});\n\t\t\tuploadbutton.fileBox.change(function(e) {\n\t\t\t\tdialog.showLoading(self.lang('uploadLoading'));\n\t\t\t\tuploadbutton.submit();\n\t\t\t});\n\t\t} else {\n\t\t\tK('.ke-upload-button', div).hide();\n\t\t}\n\t\tif (allowFileManager) {\n\t\t\tviewServerBtn.click(function(e) {\n\t\t\t\tself.loadPlugin('filemanager', function() {\n\t\t\t\t\tself.plugin.filemanagerDialog({\n\t\t\t\t\t\tviewType : 'LIST',\n\t\t\t\t\t\tdirName : 'file',\n\t\t\t\t\t\tclickFn : function(url, title) {\n\t\t\t\t\t\t\tif (self.dialogs.length > 1) {\n\t\t\t\t\t\t\t\tK('[name=\"url\"]', div).val(url);\n\t\t\t\t\t\t\t\tif (self.afterSelectFile) {\n\t\t\t\t\t\t\t\t\tself.afterSelectFile.call(self, url);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tself.hideDialog();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\tviewServerBtn.hide();\n\t\t}\n\t\turlBox.val(fileUrl);\n\t\ttitleBox.val(fileTitle);\n\t\turlBox[0].focus();\n\t\turlBox[0].select();\n\t};\n\tself.clickToolbar(name, function() {\n\t\tself.plugin.fileDialog({\n\t\t\tclickFn : function(url, title) {\n\t\t\t\tvar html = '<a class=\"ke-insertfile\" href=\"' + url + '\" data-ke-src=\"' + url + '\" target=\"_blank\">' + title + '</a>';\n\t\t\t\tself.insertHtml(html).hideDialog().focus();\n\t\t\t}\n\t\t});\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('lineheight', function(K) {\n\tvar self = this, name = 'lineheight', lang = self.lang(name + '.');\n\tself.clickToolbar(name, function() {\n\t\tvar curVal = '', commonNode = self.cmd.commonNode({'*' : '.line-height'});\n\t\tif (commonNode) {\n\t\t\tcurVal = commonNode.css('line-height');\n\t\t}\n\t\tvar menu = self.createMenu({\n\t\t\tname : name,\n\t\t\twidth : 150\n\t\t});\n\t\tK.each(lang.lineHeight, function(i, row) {\n\t\t\tK.each(row, function(key, val) {\n\t\t\t\tmenu.addItem({\n\t\t\t\t\ttitle : val,\n\t\t\t\t\tchecked : curVal === key,\n\t\t\t\t\tclick : function() {\n\t\t\t\t\t\tself.cmd.toggle('<span style=\"line-height:' + key + ';\"></span>', {\n\t\t\t\t\t\t\tspan : '.line-height=' + key\n\t\t\t\t\t\t});\n\t\t\t\t\t\tself.updateState();\n\t\t\t\t\t\tself.addBookmark();\n\t\t\t\t\t\tself.hideMenu();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('link', function(K) {\n\tvar self = this, name = 'link';\n\tself.plugin.link = {\n\t\tedit : function() {\n\t\t\tvar lang = self.lang(name + '.'),\n\t\t\t\thtml = '<div style=\"padding:20px;\">' +\n\t\t\t\t\t'<div class=\"ke-dialog-row\">' +\n\t\t\t\t\t'<label for=\"keUrl\" style=\"width:60px;\">' + lang.url + '</label>' +\n\t\t\t\t\t'<input class=\"ke-input-text\" type=\"text\" id=\"keUrl\" name=\"url\" value=\"\" style=\"width:260px;\" /></div>' +\n\t\t\t\t\t'<div class=\"ke-dialog-row\"\">' +\n\t\t\t\t\t'<label for=\"keType\" style=\"width:60px;\">' + lang.linkType + '</label>' +\n\t\t\t\t\t'<select id=\"keType\" name=\"type\"></select>' +\n\t\t\t\t\t'</div>' +\n\t\t\t\t\t'</div>',\n\t\t\t\tdialog = self.createDialog({\n\t\t\t\t\tname : name,\n\t\t\t\t\twidth : 450,\n\t\t\t\t\ttitle : self.lang(name),\n\t\t\t\t\tbody : html,\n\t\t\t\t\tyesBtn : {\n\t\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\t\tvar url = K.trim(urlBox.val());\n\t\t\t\t\t\t\tif (url == 'http://' || K.invalidUrl(url)) {\n\t\t\t\t\t\t\t\talert(self.lang('invalidUrl'));\n\t\t\t\t\t\t\t\turlBox[0].focus();\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tself.exec('createlink', url, typeBox.val()).hideDialog().focus();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\tdiv = dialog.div,\n\t\t\t\turlBox = K('input[name=\"url\"]', div),\n\t\t\t\ttypeBox = K('select[name=\"type\"]', div);\n\t\t\turlBox.val('http://');\n\t\t\ttypeBox[0].options[0] = new Option(lang.newWindow, '_blank');\n\t\t\ttypeBox[0].options[1] = new Option(lang.selfWindow, '');\n\t\t\tself.cmd.selection();\n\t\t\tvar a = self.plugin.getSelectedLink();\n\t\t\tif (a) {\n\t\t\t\tself.cmd.range.selectNode(a[0]);\n\t\t\t\tself.cmd.select();\n\t\t\t\turlBox.val(a.attr('data-ke-src'));\n\t\t\t\ttypeBox.val(a.attr('target'));\n\t\t\t}\n\t\t\turlBox[0].focus();\n\t\t\turlBox[0].select();\n\t\t},\n\t\t'delete' : function() {\n\t\t\tself.exec('unlink', null);\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.link.edit);\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('media', function(K) {\n\tvar self = this, name = 'media', lang = self.lang(name + '.'),\n\t\tallowMediaUpload = K.undef(self.allowMediaUpload, true),\n\t\tallowFileManager = K.undef(self.allowFileManager, false),\n\t\tformatUploadUrl = K.undef(self.formatUploadUrl, true),\n\t\textraParams = K.undef(self.extraFileUploadParams, {}),\n\t\tfilePostName = K.undef(self.filePostName, 'imgFile'),\n\t\tuploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php');\n\tself.plugin.media = {\n\t\tedit : function() {\n\t\t\tvar html = [\n\t\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keUrl\" style=\"width:60px;\">' + lang.url + '</label>',\n\t\t\t\t'<input class=\"ke-input-text\" type=\"text\" id=\"keUrl\" name=\"url\" value=\"\" style=\"width:250px;\" /> &nbsp;',\n\t\t\t\t/*'<input style=\"display: none\" type=\"button\" class=\"ke-upload-button\" value=\"' + lang.upload + '\" /> &nbsp;',\n\t\t\t\t'<span style=\"display: none\" class=\"ke-button-common ke-button-outer\">',\n\t\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" name=\"viewServer\" value=\"' + lang.viewServer + '\" />',*/\n\t\t\t\t'</span>',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keWidth\" style=\"width:60px;\">' + lang.width + '</label>',\n\t\t\t\t'<input type=\"text\" id=\"keWidth\" class=\"ke-input-text ke-input-number\" name=\"width\" value=\"550\" maxlength=\"4\" />',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keHeight\" style=\"width:60px;\">' + lang.height + '</label>',\n\t\t\t\t'<input type=\"text\" id=\"keHeight\" class=\"ke-input-text ke-input-number\" name=\"height\" value=\"400\" maxlength=\"4\" />',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keAutostart\">' + lang.autostart + '</label>',\n\t\t\t\t'<input type=\"checkbox\" id=\"keAutostart\" name=\"autostart\" value=\"\" /> ',\n\t\t\t\t'</div>',\n\t\t\t\t'</div>'\n\t\t\t].join('');\n\t\t\tvar dialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 450,\n\t\t\t\theight : 230,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar url = K.trim(urlBox.val()),\n\t\t\t\t\t\t\twidth = widthBox.val(),\n\t\t\t\t\t\t\theight = heightBox.val();\n\t\t\t\t\t\tif (url == 'http://' || K.invalidUrl(url)) {\n\t\t\t\t\t\t\talert(self.lang('invalidUrl'));\n\t\t\t\t\t\t\turlBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(width)) {\n\t\t\t\t\t\t\talert(self.lang('invalidWidth'));\n\t\t\t\t\t\t\twidthBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(height)) {\n\t\t\t\t\t\t\talert(self.lang('invalidHeight'));\n\t\t\t\t\t\t\theightBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar html = K.mediaImg(self.themesPath + 'common/blank.gif', {\n\t\t\t\t\t\t\t\tsrc : url,\n\t\t\t\t\t\t\t\ttype : K.mediaType(url),\n\t\t\t\t\t\t\t\twidth : width,\n\t\t\t\t\t\t\t\theight : height,\n\t\t\t\t\t\t\t\tautostart : autostartBox[0].checked ? 'true' : 'false',\n\t\t\t\t\t\t\t\tloop : 'true'\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\tself.insertHtml(html).hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\tdiv = dialog.div,\n\t\t\turlBox = K('[name=\"url\"]', div),\n\t\t\tviewServerBtn = K('[name=\"viewServer\"]', div),\n\t\t\twidthBox = K('[name=\"width\"]', div),\n\t\t\theightBox = K('[name=\"height\"]', div),\n\t\t\tautostartBox = K('[name=\"autostart\"]', div);\n\t\t\turlBox.val('http://');\n\t\t\tif (allowMediaUpload) {\n\t\t\t\tvar uploadbutton = K.uploadbutton({\n\t\t\t\t\tbutton : K('.ke-upload-button', div)[0],\n\t\t\t\t\tfieldName : filePostName,\n\t\t\t\t\textraParams : extraParams,\n\t\t\t\t\turl : K.addParam(uploadJson, 'dir=media'),\n\t\t\t\t\tafterUpload : function(data) {\n\t\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\t\tif (data.error === 0) {\n\t\t\t\t\t\t\tvar url = data.url;\n\t\t\t\t\t\t\tif (formatUploadUrl) {\n\t\t\t\t\t\t\t\turl = K.formatUrl(url, 'absolute');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\turlBox.val(url);\n\t\t\t\t\t\t\tif (self.afterUpload) {\n\t\t\t\t\t\t\t\tself.afterUpload.call(self, url, data, name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\talert(self.lang('uploadSuccess'));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\talert(data.message);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tafterError : function(html) {\n\t\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\t\tself.errorDialog(html);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tuploadbutton.fileBox.change(function(e) {\n\t\t\t\t\tdialog.showLoading(self.lang('uploadLoading'));\n\t\t\t\t\tuploadbutton.submit();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tK('.ke-upload-button', div).hide();\n\t\t\t}\n\t\t\tif (allowFileManager) {\n\t\t\t\tviewServerBtn.click(function(e) {\n\t\t\t\t\tself.loadPlugin('filemanager', function() {\n\t\t\t\t\t\tself.plugin.filemanagerDialog({\n\t\t\t\t\t\t\tviewType : 'LIST',\n\t\t\t\t\t\t\tdirName : 'media',\n\t\t\t\t\t\t\tclickFn : function(url, title) {\n\t\t\t\t\t\t\t\tif (self.dialogs.length > 1) {\n\t\t\t\t\t\t\t\t\tK('[name=\"url\"]', div).val(url);\n\t\t\t\t\t\t\t\t\tif (self.afterSelectFile) {\n\t\t\t\t\t\t\t\t\t\tself.afterSelectFile.call(self, url);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tself.hideDialog();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tviewServerBtn.hide();\n\t\t\t}\n\t\t\tvar img = self.plugin.getSelectedMedia();\n\t\t\tif (img) {\n\t\t\t\tvar attrs = K.mediaAttrs(img.attr('data-ke-tag'));\n\t\t\t\turlBox.val(attrs.src);\n\t\t\t\twidthBox.val(K.removeUnit(img.css('width')) || attrs.width || 0);\n\t\t\t\theightBox.val(K.removeUnit(img.css('height')) || attrs.height || 0);\n\t\t\t\tautostartBox[0].checked = (attrs.autostart === 'true');\n\t\t\t}\n\t\t\turlBox[0].focus();\n\t\t\turlBox[0].select();\n\t\t},\n\t\t'delete' : function() {\n\t\t\tself.plugin.getSelectedMedia().remove();\n\t\t\tself.addBookmark();\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.media.edit);\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n(function(K) {\nfunction KSWFUpload(options) {\n\tthis.init(options);\n}\nK.extend(KSWFUpload, {\n\tinit : function(options) {\n\t\tvar self = this;\n\t\toptions.afterError = options.afterError || function(str) {\n\t\t\talert(str);\n\t\t};\n\t\tself.options = options;\n\t\tself.progressbars = {};\n\t\tself.div = K(options.container).html([\n\t\t\t'<div class=\"ke-swfupload\">',\n\t\t\t'<div class=\"ke-swfupload-top\">',\n\t\t\t'<div class=\"ke-inline-block ke-swfupload-button\">',\n\t\t\t'<input type=\"button\" value=\"Browse\" />',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-inline-block ke-swfupload-desc\">' + options.uploadDesc + '</div>',\n\t\t\t'<span class=\"ke-button-common ke-button-outer ke-swfupload-startupload\">',\n\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" value=\"' + options.startButtonValue + '\" />',\n\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-swfupload-body\"></div>',\n\t\t\t'</div>'\n\t\t].join(''));\n\t\tself.bodyDiv = K('.ke-swfupload-body', self.div);\n\t\tfunction showError(itemDiv, msg) {\n\t\t\tK('.ke-status > div', itemDiv).hide();\n\t\t\tK('.ke-message', itemDiv).addClass('ke-error').show().html(K.escape(msg));\n\t\t}\n\t\tvar settings = {\n\t\t\tdebug : false,\n\t\t\tupload_url : options.uploadUrl,\n\t\t\tflash_url : options.flashUrl,\n\t\t\tfile_post_name : options.filePostName,\n\t\t\tbutton_placeholder : K('.ke-swfupload-button > input', self.div)[0],\n\t\t\tbutton_image_url: options.buttonImageUrl,\n\t\t\tbutton_width: options.buttonWidth,\n\t\t\tbutton_height: options.buttonHeight,\n\t\t\tbutton_cursor : SWFUpload.CURSOR.HAND,\n\t\t\tfile_types : options.fileTypes,\n\t\t\tfile_types_description : options.fileTypesDesc,\n\t\t\tfile_upload_limit : options.fileUploadLimit,\n\t\t\tfile_size_limit : options.fileSizeLimit,\n\t\t\tpost_params : options.postParams,\n\t\t\tfile_queued_handler : function(file) {\n\t\t\t\tfile.url = self.options.fileIconUrl;\n\t\t\t\tself.appendFile(file);\n\t\t\t},\n\t\t\tfile_queue_error_handler : function(file, errorCode, message) {\n\t\t\t\tvar errorName = '';\n\t\t\t\tswitch (errorCode) {\n\t\t\t\t\tcase SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:\n\t\t\t\t\t\terrorName = options.queueLimitExceeded;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:\n\t\t\t\t\t\terrorName = options.fileExceedsSizeLimit;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:\n\t\t\t\t\t\terrorName = options.zeroByteFile;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:\n\t\t\t\t\t\terrorName = options.invalidFiletype;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\terrorName = options.unknownError;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tK.DEBUG && alert(errorName);\n\t\t\t},\n\t\t\tupload_start_handler : function(file) {\n\t\t\t\tvar self = this;\n\t\t\t\tvar itemDiv = K('div[data-id=\"' + file.id + '\"]', self.bodyDiv);\n\t\t\t\tK('.ke-status > div', itemDiv).hide();\n\t\t\t\tK('.ke-progressbar', itemDiv).show();\n\t\t\t},\n\t\t\tupload_progress_handler : function(file, bytesLoaded, bytesTotal) {\n\t\t\t\tvar percent = Math.round(bytesLoaded * 100 / bytesTotal);\n\t\t\t\tvar progressbar = self.progressbars[file.id];\n\t\t\t\tprogressbar.bar.css('width', Math.round(percent * 80 / 100) + 'px');\n\t\t\t\tprogressbar.percent.html(percent + '%');\n\t\t\t},\n\t\t\tupload_error_handler : function(file, errorCode, message) {\n\t\t\t\tif (file && file.filestatus == SWFUpload.FILE_STATUS.ERROR) {\n\t\t\t\t\tvar itemDiv = K('div[data-id=\"' + file.id + '\"]', self.bodyDiv).eq(0);\n\t\t\t\t\tshowError(itemDiv, self.options.errorMessage);\n\t\t\t\t}\n\t\t\t},\n\t\t\tupload_success_handler : function(file, serverData) {\n\t\t\t\tvar itemDiv = K('div[data-id=\"' + file.id + '\"]', self.bodyDiv).eq(0);\n\t\t\t\tvar data = {};\n\t\t\t\ttry {\n\t\t\t\t\tdata = K.json(serverData);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tself.options.afterError.call(this, '<!doctype html><html>' + serverData + '</html>');\n\t\t\t\t}\n\t\t\t\tif (data.error !== 0) {\n\t\t\t\t\tshowError(itemDiv, K.DEBUG ? data.message : self.options.errorMessage);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfile.url = data.url;\n\t\t\t\tK('.ke-img', itemDiv).attr('src', file.url).attr('data-status', file.filestatus).data('data', data);\n\t\t\t\tK('.ke-status > div', itemDiv).hide();\n\t\t\t}\n\t\t};\n\t\tself.swfu = new SWFUpload(settings);\n\t\tK('.ke-swfupload-startupload input', self.div).click(function() {\n\t\t\tself.swfu.startUpload();\n\t\t});\n\t},\n\tgetUrlList : function() {\n\t\tvar list = [];\n\t\tK('.ke-img', self.bodyDiv).each(function() {\n\t\t\tvar img = K(this);\n\t\t\tvar status = img.attr('data-status');\n\t\t\tif (status == SWFUpload.FILE_STATUS.COMPLETE) {\n\t\t\t\tlist.push(img.data('data'));\n\t\t\t}\n\t\t});\n\t\treturn list;\n\t},\n\tremoveFile : function(fileId) {\n\t\tvar self = this;\n\t\tself.swfu.cancelUpload(fileId);\n\t\tvar itemDiv = K('div[data-id=\"' + fileId + '\"]', self.bodyDiv);\n\t\tK('.ke-photo', itemDiv).unbind();\n\t\tK('.ke-delete', itemDiv).unbind();\n\t\titemDiv.remove();\n\t},\n\tremoveFiles : function() {\n\t\tvar self = this;\n\t\tK('.ke-item', self.bodyDiv).each(function() {\n\t\t\tself.removeFile(K(this).attr('data-id'));\n\t\t});\n\t},\n\tappendFile : function(file) {\n\t\tvar self = this;\n\t\tvar itemDiv = K('<div class=\"ke-inline-block ke-item\" data-id=\"' + file.id + '\"></div>');\n\t\tself.bodyDiv.append(itemDiv);\n\t\tvar photoDiv = K('<div class=\"ke-inline-block ke-photo\"></div>')\n\t\t\t.mouseover(function(e) {\n\t\t\t\tK(this).addClass('ke-on');\n\t\t\t})\n\t\t\t.mouseout(function(e) {\n\t\t\t\tK(this).removeClass('ke-on');\n\t\t\t});\n\t\titemDiv.append(photoDiv);\n\t\tvar img = K('<img src=\"' + file.url + '\" class=\"ke-img\" data-status=\"' + file.filestatus + '\" width=\"80\" height=\"80\" alt=\"' + file.name + '\" />');\n\t\tphotoDiv.append(img);\n\t\tK('<span class=\"ke-delete\"></span>').appendTo(photoDiv).click(function() {\n\t\t\tself.removeFile(file.id);\n\t\t});\n\t\tvar statusDiv = K('<div class=\"ke-status\"></div>').appendTo(photoDiv);\n\t\tK(['<div class=\"ke-progressbar\">',\n\t\t\t'<div class=\"ke-progressbar-bar\"><div class=\"ke-progressbar-bar-inner\"></div></div>',\n\t\t\t'<div class=\"ke-progressbar-percent\">0%</div></div>'].join('')).hide().appendTo(statusDiv);\n\t\tK('<div class=\"ke-message\">' + self.options.pendingMessage + '</div>').appendTo(statusDiv);\n\t\titemDiv.append('<div class=\"ke-name\">' + file.name + '</div>');\n\t\tself.progressbars[file.id] = {\n\t\t\tbar : K('.ke-progressbar-bar-inner', photoDiv),\n\t\t\tpercent : K('.ke-progressbar-percent', photoDiv)\n\t\t};\n\t},\n\tremove : function() {\n\t\tthis.removeFiles();\n\t\tthis.swfu.destroy();\n\t\tthis.div.html('');\n\t}\n});\nK.swfupload = function(element, options) {\n\treturn new KSWFUpload(element, options);\n};\n})(KindEditor);\nKindEditor.plugin('multiimage', function(K) {\n\tvar self = this, name = 'multiimage',\n\t\tformatUploadUrl = K.undef(self.formatUploadUrl, true),\n\t\tuploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'),\n\t\timgPath = self.pluginsPath + 'multiimage/images/',\n\t\timageSizeLimit = K.undef(self.imageSizeLimit, '1MB'),\n\t\timageFileTypes = K.undef(self.imageFileTypes, '*.jpg;*.gif;*.png'),\n\t\timageUploadLimit = K.undef(self.imageUploadLimit, 20),\n\t\tfilePostName = K.undef(self.filePostName, 'imgFile'),\n\t\tlang = self.lang(name + '.');\n\tself.plugin.multiImageDialog = function(options) {\n\t\tvar clickFn = options.clickFn,\n\t\t\tuploadDesc = K.tmpl(lang.uploadDesc, {uploadLimit : imageUploadLimit, sizeLimit : imageSizeLimit});\n\t\tvar html = [\n\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t'<div class=\"swfupload\">',\n\t\t\t'</div>',\n\t\t\t'</div>'\n\t\t].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : 650,\n\t\t\theight : 510,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tpreviewBtn : {\n\t\t\t\tname : lang.insertAll,\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tclickFn.call(self, swfupload.getUrlList());\n\t\t\t\t}\n\t\t\t},\n\t\t\tyesBtn : {\n\t\t\t\tname : lang.clearAll,\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tswfupload.removeFiles();\n\t\t\t\t}\n\t\t\t},\n\t\t\tbeforeRemove : function() {\n\t\t\t\tif (!K.IE || K.V <= 8) {\n\t\t\t\t\tswfupload.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}),\n\t\tdiv = dialog.div;\n\t\tvar swfupload = K.swfupload({\n\t\t\tcontainer : K('.swfupload', div),\n\t\t\tbuttonImageUrl : imgPath + (self.langType == 'zh-CN' ? 'select-files-zh-CN.png' : 'select-files-en.png'),\n\t\t\tbuttonWidth : self.langType == 'zh-CN' ? 72 : 88,\n\t\t\tbuttonHeight : 23,\n\t\t\tfileIconUrl : imgPath + 'image.png',\n\t\t\tuploadDesc : uploadDesc,\n\t\t\tstartButtonValue : lang.startUpload,\n\t\t\tuploadUrl : K.addParam(uploadJson, 'dir=image'),\n\t\t\tflashUrl : imgPath + 'swfupload.swf',\n\t\t\tfilePostName : filePostName,\n\t\t\tfileTypes : '*.jpg;*.jpeg;*.gif;*.png;*.bmp',\n\t\t\tfileTypesDesc : 'Image Files',\n\t\t\tfileUploadLimit : imageUploadLimit,\n\t\t\tfileSizeLimit : imageSizeLimit,\n\t\t\tpostParams :  K.undef(self.extraFileUploadParams, {}),\n\t\t\tqueueLimitExceeded : lang.queueLimitExceeded,\n\t\t\tfileExceedsSizeLimit : lang.fileExceedsSizeLimit,\n\t\t\tzeroByteFile : lang.zeroByteFile,\n\t\t\tinvalidFiletype : lang.invalidFiletype,\n\t\t\tunknownError : lang.unknownError,\n\t\t\tpendingMessage : lang.pending,\n\t\t\terrorMessage : lang.uploadError,\n\t\t\tafterError : function(html) {\n\t\t\t\tself.errorDialog(html);\n\t\t\t}\n\t\t});\n\t\treturn dialog;\n\t};\n\tself.clickToolbar(name, function() {\n\t\tself.plugin.multiImageDialog({\n\t\t\tclickFn : function (urlList) {\n\t\t\t\tif (urlList.length === 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tK.each(urlList, function(i, data) {\n\t\t\t\t\tif (self.afterUpload) {\n\t\t\t\t\t\tself.afterUpload.call(self, data.url, data, 'multiimage');\n\t\t\t\t\t}\n\t\t\t\t\tself.exec('insertimage', data.url, data.title, data.width, data.height, data.border, data.align);\n\t\t\t\t});\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tself.hideDialog().focus();\n\t\t\t\t}, 0);\n\t\t\t}\n\t\t});\n\t});\n});\n/* ******************* */\n/* Constructor & Init  */\n/* ******************* */\n(function() {\nwindow.SWFUpload = function (settings) {\n\tthis.initSWFUpload(settings);\n};\nSWFUpload.prototype.initSWFUpload = function (settings) {\n\ttry {\n\t\tthis.customSettings = {};\n\t\tthis.settings = settings;\n\t\tthis.eventQueue = [];\n\t\tthis.movieName = \"KindEditor_SWFUpload_\" + SWFUpload.movieCount++;\n\t\tthis.movieElement = null;\n\t\tSWFUpload.instances[this.movieName] = this;\n\t\tthis.initSettings();\n\t\tthis.loadFlash();\n\t\tthis.displayDebugInfo();\n\t} catch (ex) {\n\t\tdelete SWFUpload.instances[this.movieName];\n\t\tthrow ex;\n\t}\n};\n/* *************** */\n/* Static Members  */\n/* *************** */\nSWFUpload.instances = {};\nSWFUpload.movieCount = 0;\nSWFUpload.version = \"2.2.0 2009-03-25\";\nSWFUpload.QUEUE_ERROR = {\n\tQUEUE_LIMIT_EXCEEDED\t  \t\t: -100,\n\tFILE_EXCEEDS_SIZE_LIMIT  \t\t: -110,\n\tZERO_BYTE_FILE\t\t\t  \t\t: -120,\n\tINVALID_FILETYPE\t\t  \t\t: -130\n};\nSWFUpload.UPLOAD_ERROR = {\n\tHTTP_ERROR\t\t\t\t  \t\t: -200,\n\tMISSING_UPLOAD_URL\t      \t\t: -210,\n\tIO_ERROR\t\t\t\t  \t\t: -220,\n\tSECURITY_ERROR\t\t\t  \t\t: -230,\n\tUPLOAD_LIMIT_EXCEEDED\t  \t\t: -240,\n\tUPLOAD_FAILED\t\t\t  \t\t: -250,\n\tSPECIFIED_FILE_ID_NOT_FOUND\t\t: -260,\n\tFILE_VALIDATION_FAILED\t  \t\t: -270,\n\tFILE_CANCELLED\t\t\t  \t\t: -280,\n\tUPLOAD_STOPPED\t\t\t\t\t: -290\n};\nSWFUpload.FILE_STATUS = {\n\tQUEUED\t\t : -1,\n\tIN_PROGRESS\t : -2,\n\tERROR\t\t : -3,\n\tCOMPLETE\t : -4,\n\tCANCELLED\t : -5\n};\nSWFUpload.BUTTON_ACTION = {\n\tSELECT_FILE  : -100,\n\tSELECT_FILES : -110,\n\tSTART_UPLOAD : -120\n};\nSWFUpload.CURSOR = {\n\tARROW : -1,\n\tHAND : -2\n};\nSWFUpload.WINDOW_MODE = {\n\tWINDOW : \"window\",\n\tTRANSPARENT : \"transparent\",\n\tOPAQUE : \"opaque\"\n};\nSWFUpload.completeURL = function(url) {\n\tif (typeof(url) !== \"string\" || url.match(/^https?:\\/\\//i) || url.match(/^\\//)) {\n\t\treturn url;\n\t}\n\tvar currentURL = window.location.protocol + \"//\" + window.location.hostname + (window.location.port ? \":\" + window.location.port : \"\");\n\tvar indexSlash = window.location.pathname.lastIndexOf(\"/\");\n\tvar path;\n\tif (indexSlash <= 0) {\n\t\tpath = \"/\";\n\t} else {\n\t\tpath = window.location.pathname.substr(0, indexSlash) + \"/\";\n\t}\n\treturn /*currentURL +*/ path + url;\n};\n/* ******************** */\n/* Instance Members  */\n/* ******************** */\nSWFUpload.prototype.initSettings = function () {\n\tthis.ensureDefault = function (settingName, defaultValue) {\n\t\tthis.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];\n\t};\n\tthis.ensureDefault(\"upload_url\", \"\");\n\tthis.ensureDefault(\"preserve_relative_urls\", false);\n\tthis.ensureDefault(\"file_post_name\", \"Filedata\");\n\tthis.ensureDefault(\"post_params\", {});\n\tthis.ensureDefault(\"use_query_string\", false);\n\tthis.ensureDefault(\"requeue_on_error\", false);\n\tthis.ensureDefault(\"http_success\", []);\n\tthis.ensureDefault(\"assume_success_timeout\", 0);\n\tthis.ensureDefault(\"file_types\", \"*.*\");\n\tthis.ensureDefault(\"file_types_description\", \"All Files\");\n\tthis.ensureDefault(\"file_size_limit\", 0);\n\tthis.ensureDefault(\"file_upload_limit\", 0);\n\tthis.ensureDefault(\"file_queue_limit\", 0);\n\tthis.ensureDefault(\"flash_url\", \"swfupload.swf\");\n\tthis.ensureDefault(\"prevent_swf_caching\", true);\n\tthis.ensureDefault(\"button_image_url\", \"\");\n\tthis.ensureDefault(\"button_width\", 1);\n\tthis.ensureDefault(\"button_height\", 1);\n\tthis.ensureDefault(\"button_text\", \"\");\n\tthis.ensureDefault(\"button_text_style\", \"color: #000000; font-size: 16pt;\");\n\tthis.ensureDefault(\"button_text_top_padding\", 0);\n\tthis.ensureDefault(\"button_text_left_padding\", 0);\n\tthis.ensureDefault(\"button_action\", SWFUpload.BUTTON_ACTION.SELECT_FILES);\n\tthis.ensureDefault(\"button_disabled\", false);\n\tthis.ensureDefault(\"button_placeholder_id\", \"\");\n\tthis.ensureDefault(\"button_placeholder\", null);\n\tthis.ensureDefault(\"button_cursor\", SWFUpload.CURSOR.ARROW);\n\tthis.ensureDefault(\"button_window_mode\", SWFUpload.WINDOW_MODE.WINDOW);\n\tthis.ensureDefault(\"debug\", false);\n\tthis.settings.debug_enabled = this.settings.debug;\n\tthis.settings.return_upload_start_handler = this.returnUploadStart;\n\tthis.ensureDefault(\"swfupload_loaded_handler\", null);\n\tthis.ensureDefault(\"file_dialog_start_handler\", null);\n\tthis.ensureDefault(\"file_queued_handler\", null);\n\tthis.ensureDefault(\"file_queue_error_handler\", null);\n\tthis.ensureDefault(\"file_dialog_complete_handler\", null);\n\tthis.ensureDefault(\"upload_start_handler\", null);\n\tthis.ensureDefault(\"upload_progress_handler\", null);\n\tthis.ensureDefault(\"upload_error_handler\", null);\n\tthis.ensureDefault(\"upload_success_handler\", null);\n\tthis.ensureDefault(\"upload_complete_handler\", null);\n\tthis.ensureDefault(\"debug_handler\", this.debugMessage);\n\tthis.ensureDefault(\"custom_settings\", {});\n\tthis.customSettings = this.settings.custom_settings;\n\tif (!!this.settings.prevent_swf_caching) {\n\t\tthis.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf(\"?\") < 0 ? \"?\" : \"&\") + \"preventswfcaching=\" + new Date().getTime();\n\t}\n\tif (!this.settings.preserve_relative_urls) {\n\t\tthis.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url);\n\t\tthis.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url);\n\t}\n\tdelete this.ensureDefault;\n};\nSWFUpload.prototype.loadFlash = function () {\n\tvar targetElement, tempParent;\n\tif (document.getElementById(this.movieName) !== null) {\n\t\tthrow \"ID \" + this.movieName + \" is already in use. The Flash Object could not be added\";\n\t}\n\ttargetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder;\n\tif (targetElement == undefined) {\n\t\tthrow \"Could not find the placeholder element: \" + this.settings.button_placeholder_id;\n\t}\n\ttempParent = document.createElement(\"div\");\n\ttempParent.innerHTML = this.getFlashHTML();\n\ttargetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);\n\tif (window[this.movieName] == undefined) {\n\t\twindow[this.movieName] = this.getMovieElement();\n\t}\n};\nSWFUpload.prototype.getFlashHTML = function () {\n\tvar classid = '';\n\tif (KindEditor.IE && KindEditor.V > 8) {\n\t\tclassid = ' classid = \"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\"';\n\t}\n\treturn ['<object id=\"', this.movieName, '\"' + classid + ' type=\"application/x-shockwave-flash\" data=\"', this.settings.flash_url, '\" width=\"', this.settings.button_width, '\" height=\"', this.settings.button_height, '\" class=\"swfupload\">',\n\t\t\t\t'<param name=\"wmode\" value=\"', this.settings.button_window_mode, '\" />',\n\t\t\t\t'<param name=\"movie\" value=\"', this.settings.flash_url, '\" />',\n\t\t\t\t'<param name=\"quality\" value=\"high\" />',\n\t\t\t\t'<param name=\"menu\" value=\"false\" />',\n\t\t\t\t'<param name=\"allowScriptAccess\" value=\"always\" />',\n\t\t\t\t'<param name=\"flashvars\" value=\"' + this.getFlashVars() + '\" />',\n\t\t\t\t'</object>'].join(\"\");\n};\nSWFUpload.prototype.getFlashVars = function () {\n\tvar paramString = this.buildParamString();\n\tvar httpSuccessString = this.settings.http_success.join(\",\");\n\treturn [\"movieName=\", encodeURIComponent(this.movieName),\n\t\t\t\"&amp;uploadURL=\", encodeURIComponent(this.settings.upload_url),\n\t\t\t\"&amp;useQueryString=\", encodeURIComponent(this.settings.use_query_string),\n\t\t\t\"&amp;requeueOnError=\", encodeURIComponent(this.settings.requeue_on_error),\n\t\t\t\"&amp;httpSuccess=\", encodeURIComponent(httpSuccessString),\n\t\t\t\"&amp;assumeSuccessTimeout=\", encodeURIComponent(this.settings.assume_success_timeout),\n\t\t\t\"&amp;params=\", encodeURIComponent(paramString),\n\t\t\t\"&amp;filePostName=\", encodeURIComponent(this.settings.file_post_name),\n\t\t\t\"&amp;fileTypes=\", encodeURIComponent(this.settings.file_types),\n\t\t\t\"&amp;fileTypesDescription=\", encodeURIComponent(this.settings.file_types_description),\n\t\t\t\"&amp;fileSizeLimit=\", encodeURIComponent(this.settings.file_size_limit),\n\t\t\t\"&amp;fileUploadLimit=\", encodeURIComponent(this.settings.file_upload_limit),\n\t\t\t\"&amp;fileQueueLimit=\", encodeURIComponent(this.settings.file_queue_limit),\n\t\t\t\"&amp;debugEnabled=\", encodeURIComponent(this.settings.debug_enabled),\n\t\t\t\"&amp;buttonImageURL=\", encodeURIComponent(this.settings.button_image_url),\n\t\t\t\"&amp;buttonWidth=\", encodeURIComponent(this.settings.button_width),\n\t\t\t\"&amp;buttonHeight=\", encodeURIComponent(this.settings.button_height),\n\t\t\t\"&amp;buttonText=\", encodeURIComponent(this.settings.button_text),\n\t\t\t\"&amp;buttonTextTopPadding=\", encodeURIComponent(this.settings.button_text_top_padding),\n\t\t\t\"&amp;buttonTextLeftPadding=\", encodeURIComponent(this.settings.button_text_left_padding),\n\t\t\t\"&amp;buttonTextStyle=\", encodeURIComponent(this.settings.button_text_style),\n\t\t\t\"&amp;buttonAction=\", encodeURIComponent(this.settings.button_action),\n\t\t\t\"&amp;buttonDisabled=\", encodeURIComponent(this.settings.button_disabled),\n\t\t\t\"&amp;buttonCursor=\", encodeURIComponent(this.settings.button_cursor)\n\t\t].join(\"\");\n};\nSWFUpload.prototype.getMovieElement = function () {\n\tif (this.movieElement == undefined) {\n\t\tthis.movieElement = document.getElementById(this.movieName);\n\t}\n\tif (this.movieElement === null) {\n\t\tthrow \"Could not find Flash element\";\n\t}\n\treturn this.movieElement;\n};\nSWFUpload.prototype.buildParamString = function () {\n\tvar postParams = this.settings.post_params;\n\tvar paramStringPairs = [];\n\tif (typeof(postParams) === \"object\") {\n\t\tfor (var name in postParams) {\n\t\t\tif (postParams.hasOwnProperty(name)) {\n\t\t\t\tparamStringPairs.push(encodeURIComponent(name.toString()) + \"=\" + encodeURIComponent(postParams[name].toString()));\n\t\t\t}\n\t\t}\n\t}\n\treturn paramStringPairs.join(\"&amp;\");\n};\nSWFUpload.prototype.destroy = function () {\n\ttry {\n\t\tthis.cancelUpload(null, false);\n\t\tvar movieElement = null;\n\t\tmovieElement = this.getMovieElement();\n\t\tif (movieElement && typeof(movieElement.CallFunction) === \"unknown\") {\n\t\t\tfor (var i in movieElement) {\n\t\t\t\ttry {\n\t\t\t\t\tif (typeof(movieElement[i]) === \"function\") {\n\t\t\t\t\t\tmovieElement[i] = null;\n\t\t\t\t\t}\n\t\t\t\t} catch (ex1) {}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tmovieElement.parentNode.removeChild(movieElement);\n\t\t\t} catch (ex) {}\n\t\t}\n\t\twindow[this.movieName] = null;\n\t\tSWFUpload.instances[this.movieName] = null;\n\t\tdelete SWFUpload.instances[this.movieName];\n\t\tthis.movieElement = null;\n\t\tthis.settings = null;\n\t\tthis.customSettings = null;\n\t\tthis.eventQueue = null;\n\t\tthis.movieName = null;\n\t\treturn true;\n\t} catch (ex2) {\n\t\treturn false;\n\t}\n};\nSWFUpload.prototype.displayDebugInfo = function () {\n\tthis.debug(\n\t\t[\n\t\t\t\"---SWFUpload Instance Info---\\n\",\n\t\t\t\"Version: \", SWFUpload.version, \"\\n\",\n\t\t\t\"Movie Name: \", this.movieName, \"\\n\",\n\t\t\t\"Settings:\\n\",\n\t\t\t\"\\t\", \"upload_url:               \", this.settings.upload_url, \"\\n\",\n\t\t\t\"\\t\", \"flash_url:                \", this.settings.flash_url, \"\\n\",\n\t\t\t\"\\t\", \"use_query_string:         \", this.settings.use_query_string.toString(), \"\\n\",\n\t\t\t\"\\t\", \"requeue_on_error:         \", this.settings.requeue_on_error.toString(), \"\\n\",\n\t\t\t\"\\t\", \"http_success:             \", this.settings.http_success.join(\", \"), \"\\n\",\n\t\t\t\"\\t\", \"assume_success_timeout:   \", this.settings.assume_success_timeout, \"\\n\",\n\t\t\t\"\\t\", \"file_post_name:           \", this.settings.file_post_name, \"\\n\",\n\t\t\t\"\\t\", \"post_params:              \", this.settings.post_params.toString(), \"\\n\",\n\t\t\t\"\\t\", \"file_types:               \", this.settings.file_types, \"\\n\",\n\t\t\t\"\\t\", \"file_types_description:   \", this.settings.file_types_description, \"\\n\",\n\t\t\t\"\\t\", \"file_size_limit:          \", this.settings.file_size_limit, \"\\n\",\n\t\t\t\"\\t\", \"file_upload_limit:        \", this.settings.file_upload_limit, \"\\n\",\n\t\t\t\"\\t\", \"file_queue_limit:         \", this.settings.file_queue_limit, \"\\n\",\n\t\t\t\"\\t\", \"debug:                    \", this.settings.debug.toString(), \"\\n\",\n\t\t\t\"\\t\", \"prevent_swf_caching:      \", this.settings.prevent_swf_caching.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_placeholder_id:    \", this.settings.button_placeholder_id.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_placeholder:       \", (this.settings.button_placeholder ? \"Set\" : \"Not Set\"), \"\\n\",\n\t\t\t\"\\t\", \"button_image_url:         \", this.settings.button_image_url.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_width:             \", this.settings.button_width.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_height:            \", this.settings.button_height.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_text:              \", this.settings.button_text.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_text_style:        \", this.settings.button_text_style.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_text_top_padding:  \", this.settings.button_text_top_padding.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_text_left_padding: \", this.settings.button_text_left_padding.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_action:            \", this.settings.button_action.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_disabled:          \", this.settings.button_disabled.toString(), \"\\n\",\n\t\t\t\"\\t\", \"custom_settings:          \", this.settings.custom_settings.toString(), \"\\n\",\n\t\t\t\"Event Handlers:\\n\",\n\t\t\t\"\\t\", \"swfupload_loaded_handler assigned:  \", (typeof this.settings.swfupload_loaded_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"file_dialog_start_handler assigned: \", (typeof this.settings.file_dialog_start_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"file_queued_handler assigned:       \", (typeof this.settings.file_queued_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"file_queue_error_handler assigned:  \", (typeof this.settings.file_queue_error_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"upload_start_handler assigned:      \", (typeof this.settings.upload_start_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"upload_progress_handler assigned:   \", (typeof this.settings.upload_progress_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"upload_error_handler assigned:      \", (typeof this.settings.upload_error_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"upload_success_handler assigned:    \", (typeof this.settings.upload_success_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"upload_complete_handler assigned:   \", (typeof this.settings.upload_complete_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"debug_handler assigned:             \", (typeof this.settings.debug_handler === \"function\").toString(), \"\\n\"\n\t\t].join(\"\")\n\t);\n};\n/* Note: addSetting and getSetting are no longer used by SWFUpload but are included\n\tthe maintain v2 API compatibility\n*/\nSWFUpload.prototype.addSetting = function (name, value, default_value) {\n    if (value == undefined) {\n        return (this.settings[name] = default_value);\n    } else {\n        return (this.settings[name] = value);\n\t}\n};\nSWFUpload.prototype.getSetting = function (name) {\n    if (this.settings[name] != undefined) {\n        return this.settings[name];\n\t}\n    return \"\";\n};\nSWFUpload.prototype.callFlash = function (functionName, argumentArray) {\n\targumentArray = argumentArray || [];\n\tvar movieElement = this.getMovieElement();\n\tvar returnValue, returnString;\n\ttry {\n\t\treturnString = movieElement.CallFunction('<invoke name=\"' + functionName + '\" returntype=\"javascript\">' + __flash__argumentsToXML(argumentArray, 0) + '</invoke>');\n\t\treturnValue = eval(returnString);\n\t} catch (ex) {\n\t\tthrow \"Call to \" + functionName + \" failed\";\n\t}\n\tif (returnValue != undefined && typeof returnValue.post === \"object\") {\n\t\treturnValue = this.unescapeFilePostParams(returnValue);\n\t}\n\treturn returnValue;\n};\n/* *****************************\n\t-- Flash control methods --\n\tYour UI should use these\n\tto operate SWFUpload\n   ***************************** */\nSWFUpload.prototype.selectFile = function () {\n\tthis.callFlash(\"SelectFile\");\n};\nSWFUpload.prototype.selectFiles = function () {\n\tthis.callFlash(\"SelectFiles\");\n};\nSWFUpload.prototype.startUpload = function (fileID) {\n\tthis.callFlash(\"StartUpload\", [fileID]);\n};\nSWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) {\n\tif (triggerErrorEvent !== false) {\n\t\ttriggerErrorEvent = true;\n\t}\n\tthis.callFlash(\"CancelUpload\", [fileID, triggerErrorEvent]);\n};\nSWFUpload.prototype.stopUpload = function () {\n\tthis.callFlash(\"StopUpload\");\n};\n/* ************************\n * Settings methods\n *   These methods change the SWFUpload settings.\n *   SWFUpload settings should not be changed directly on the settings object\n *   since many of the settings need to be passed to Flash in order to take\n *   effect.\n * *********************** */\nSWFUpload.prototype.getStats = function () {\n\treturn this.callFlash(\"GetStats\");\n};\nSWFUpload.prototype.setStats = function (statsObject) {\n\tthis.callFlash(\"SetStats\", [statsObject]);\n};\nSWFUpload.prototype.getFile = function (fileID) {\n\tif (typeof(fileID) === \"number\") {\n\t\treturn this.callFlash(\"GetFileByIndex\", [fileID]);\n\t} else {\n\t\treturn this.callFlash(\"GetFile\", [fileID]);\n\t}\n};\nSWFUpload.prototype.addFileParam = function (fileID, name, value) {\n\treturn this.callFlash(\"AddFileParam\", [fileID, name, value]);\n};\nSWFUpload.prototype.removeFileParam = function (fileID, name) {\n\tthis.callFlash(\"RemoveFileParam\", [fileID, name]);\n};\nSWFUpload.prototype.setUploadURL = function (url) {\n\tthis.settings.upload_url = url.toString();\n\tthis.callFlash(\"SetUploadURL\", [url]);\n};\nSWFUpload.prototype.setPostParams = function (paramsObject) {\n\tthis.settings.post_params = paramsObject;\n\tthis.callFlash(\"SetPostParams\", [paramsObject]);\n};\nSWFUpload.prototype.addPostParam = function (name, value) {\n\tthis.settings.post_params[name] = value;\n\tthis.callFlash(\"SetPostParams\", [this.settings.post_params]);\n};\nSWFUpload.prototype.removePostParam = function (name) {\n\tdelete this.settings.post_params[name];\n\tthis.callFlash(\"SetPostParams\", [this.settings.post_params]);\n};\nSWFUpload.prototype.setFileTypes = function (types, description) {\n\tthis.settings.file_types = types;\n\tthis.settings.file_types_description = description;\n\tthis.callFlash(\"SetFileTypes\", [types, description]);\n};\nSWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {\n\tthis.settings.file_size_limit = fileSizeLimit;\n\tthis.callFlash(\"SetFileSizeLimit\", [fileSizeLimit]);\n};\nSWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {\n\tthis.settings.file_upload_limit = fileUploadLimit;\n\tthis.callFlash(\"SetFileUploadLimit\", [fileUploadLimit]);\n};\nSWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {\n\tthis.settings.file_queue_limit = fileQueueLimit;\n\tthis.callFlash(\"SetFileQueueLimit\", [fileQueueLimit]);\n};\nSWFUpload.prototype.setFilePostName = function (filePostName) {\n\tthis.settings.file_post_name = filePostName;\n\tthis.callFlash(\"SetFilePostName\", [filePostName]);\n};\nSWFUpload.prototype.setUseQueryString = function (useQueryString) {\n\tthis.settings.use_query_string = useQueryString;\n\tthis.callFlash(\"SetUseQueryString\", [useQueryString]);\n};\nSWFUpload.prototype.setRequeueOnError = function (requeueOnError) {\n\tthis.settings.requeue_on_error = requeueOnError;\n\tthis.callFlash(\"SetRequeueOnError\", [requeueOnError]);\n};\nSWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {\n\tif (typeof http_status_codes === \"string\") {\n\t\thttp_status_codes = http_status_codes.replace(\" \", \"\").split(\",\");\n\t}\n\tthis.settings.http_success = http_status_codes;\n\tthis.callFlash(\"SetHTTPSuccess\", [http_status_codes]);\n};\nSWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) {\n\tthis.settings.assume_success_timeout = timeout_seconds;\n\tthis.callFlash(\"SetAssumeSuccessTimeout\", [timeout_seconds]);\n};\nSWFUpload.prototype.setDebugEnabled = function (debugEnabled) {\n\tthis.settings.debug_enabled = debugEnabled;\n\tthis.callFlash(\"SetDebugEnabled\", [debugEnabled]);\n};\nSWFUpload.prototype.setButtonImageURL = function (buttonImageURL) {\n\tif (buttonImageURL == undefined) {\n\t\tbuttonImageURL = \"\";\n\t}\n\tthis.settings.button_image_url = buttonImageURL;\n\tthis.callFlash(\"SetButtonImageURL\", [buttonImageURL]);\n};\nSWFUpload.prototype.setButtonDimensions = function (width, height) {\n\tthis.settings.button_width = width;\n\tthis.settings.button_height = height;\n\tvar movie = this.getMovieElement();\n\tif (movie != undefined) {\n\t\tmovie.style.width = width + \"px\";\n\t\tmovie.style.height = height + \"px\";\n\t}\n\tthis.callFlash(\"SetButtonDimensions\", [width, height]);\n};\nSWFUpload.prototype.setButtonText = function (html) {\n\tthis.settings.button_text = html;\n\tthis.callFlash(\"SetButtonText\", [html]);\n};\nSWFUpload.prototype.setButtonTextPadding = function (left, top) {\n\tthis.settings.button_text_top_padding = top;\n\tthis.settings.button_text_left_padding = left;\n\tthis.callFlash(\"SetButtonTextPadding\", [left, top]);\n};\nSWFUpload.prototype.setButtonTextStyle = function (css) {\n\tthis.settings.button_text_style = css;\n\tthis.callFlash(\"SetButtonTextStyle\", [css]);\n};\nSWFUpload.prototype.setButtonDisabled = function (isDisabled) {\n\tthis.settings.button_disabled = isDisabled;\n\tthis.callFlash(\"SetButtonDisabled\", [isDisabled]);\n};\nSWFUpload.prototype.setButtonAction = function (buttonAction) {\n\tthis.settings.button_action = buttonAction;\n\tthis.callFlash(\"SetButtonAction\", [buttonAction]);\n};\nSWFUpload.prototype.setButtonCursor = function (cursor) {\n\tthis.settings.button_cursor = cursor;\n\tthis.callFlash(\"SetButtonCursor\", [cursor]);\n};\n/* *******************************\n\tFlash Event Interfaces\n\tThese functions are used by Flash to trigger the various\n\tevents.\n\tAll these functions a Private.\n\tBecause the ExternalInterface library is buggy the event calls\n\tare added to a queue and the queue then executed by a setTimeout.\n\tThis ensures that events are executed in a determinate order and that\n\tthe ExternalInterface bugs are avoided.\n******************************* */\nSWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {\n\tif (argumentArray == undefined) {\n\t\targumentArray = [];\n\t} else if (!(argumentArray instanceof Array)) {\n\t\targumentArray = [argumentArray];\n\t}\n\tvar self = this;\n\tif (typeof this.settings[handlerName] === \"function\") {\n\t\tthis.eventQueue.push(function () {\n\t\t\tthis.settings[handlerName].apply(this, argumentArray);\n\t\t});\n\t\tsetTimeout(function () {\n\t\t\tself.executeNextEvent();\n\t\t}, 0);\n\t} else if (this.settings[handlerName] !== null) {\n\t\tthrow \"Event handler \" + handlerName + \" is unknown or is not a function\";\n\t}\n};\nSWFUpload.prototype.executeNextEvent = function () {\n\tvar  f = this.eventQueue ? this.eventQueue.shift() : null;\n\tif (typeof(f) === \"function\") {\n\t\tf.apply(this);\n\t}\n};\nSWFUpload.prototype.unescapeFilePostParams = function (file) {\n\tvar reg = /[$]([0-9a-f]{4})/i;\n\tvar unescapedPost = {};\n\tvar uk;\n\tif (file != undefined) {\n\t\tfor (var k in file.post) {\n\t\t\tif (file.post.hasOwnProperty(k)) {\n\t\t\t\tuk = k;\n\t\t\t\tvar match;\n\t\t\t\twhile ((match = reg.exec(uk)) !== null) {\n\t\t\t\t\tuk = uk.replace(match[0], String.fromCharCode(parseInt(\"0x\" + match[1], 16)));\n\t\t\t\t}\n\t\t\t\tunescapedPost[uk] = file.post[k];\n\t\t\t}\n\t\t}\n\t\tfile.post = unescapedPost;\n\t}\n\treturn file;\n};\nSWFUpload.prototype.testExternalInterface = function () {\n\ttry {\n\t\treturn this.callFlash(\"TestExternalInterface\");\n\t} catch (ex) {\n\t\treturn false;\n\t}\n};\nSWFUpload.prototype.flashReady = function () {\n\tvar movieElement = this.getMovieElement();\n\tif (!movieElement) {\n\t\tthis.debug(\"Flash called back ready but the flash movie can't be found.\");\n\t\treturn;\n\t}\n\tthis.cleanUp(movieElement);\n\tthis.queueEvent(\"swfupload_loaded_handler\");\n};\nSWFUpload.prototype.cleanUp = function (movieElement) {\n\ttry {\n\t\tif (this.movieElement && typeof(movieElement.CallFunction) === \"unknown\") {\n\t\t\tthis.debug(\"Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)\");\n\t\t\tfor (var key in movieElement) {\n\t\t\t\ttry {\n\t\t\t\t\tif (typeof(movieElement[key]) === \"function\") {\n\t\t\t\t\t\tmovieElement[key] = null;\n\t\t\t\t\t}\n\t\t\t\t} catch (ex) {\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch (ex1) {\n\t}\n\twindow[\"__flash__removeCallback\"] = function (instance, name) {\n\t\ttry {\n\t\t\tif (instance) {\n\t\t\t\tinstance[name] = null;\n\t\t\t}\n\t\t} catch (flashEx) {\n\t\t}\n\t};\n};\n/* This is a chance to do something before the browse window opens */\nSWFUpload.prototype.fileDialogStart = function () {\n\tthis.queueEvent(\"file_dialog_start_handler\");\n};\n/* Called when a file is successfully added to the queue. */\nSWFUpload.prototype.fileQueued = function (file) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"file_queued_handler\", file);\n};\n/* Handle errors that occur when an attempt to queue a file fails. */\nSWFUpload.prototype.fileQueueError = function (file, errorCode, message) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"file_queue_error_handler\", [file, errorCode, message]);\n};\n/* Called after the file dialog has closed and the selected files have been queued.\n\tYou could call startUpload here if you want the queued files to begin uploading immediately. */\nSWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) {\n\tthis.queueEvent(\"file_dialog_complete_handler\", [numFilesSelected, numFilesQueued, numFilesInQueue]);\n};\nSWFUpload.prototype.uploadStart = function (file) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"return_upload_start_handler\", file);\n};\nSWFUpload.prototype.returnUploadStart = function (file) {\n\tvar returnValue;\n\tif (typeof this.settings.upload_start_handler === \"function\") {\n\t\tfile = this.unescapeFilePostParams(file);\n\t\treturnValue = this.settings.upload_start_handler.call(this, file);\n\t} else if (this.settings.upload_start_handler != undefined) {\n\t\tthrow \"upload_start_handler must be a function\";\n\t}\n\tif (returnValue === undefined) {\n\t\treturnValue = true;\n\t}\n\treturnValue = !!returnValue;\n\tthis.callFlash(\"ReturnUploadStart\", [returnValue]);\n};\nSWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"upload_progress_handler\", [file, bytesComplete, bytesTotal]);\n};\nSWFUpload.prototype.uploadError = function (file, errorCode, message) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"upload_error_handler\", [file, errorCode, message]);\n};\nSWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"upload_success_handler\", [file, serverData, responseReceived]);\n};\nSWFUpload.prototype.uploadComplete = function (file) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"upload_complete_handler\", file);\n};\n/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the\n   internal debug console.  You can override this event and have messages written where you want. */\nSWFUpload.prototype.debug = function (message) {\n\tthis.queueEvent(\"debug_handler\", message);\n};\n/* **********************************\n\tDebug Console\n\tThe debug console is a self contained, in page location\n\tfor debug message to be sent.  The Debug Console adds\n\titself to the body if necessary.\n\tThe console is automatically scrolled as messages appear.\n\tIf you are using your own debug handler or when you deploy to production and\n\thave debug disabled you can remove these functions to reduce the file size\n\tand complexity.\n********************************** */\nSWFUpload.prototype.debugMessage = function (message) {\n\tif (this.settings.debug) {\n\t\tvar exceptionMessage, exceptionValues = [];\n\t\tif (typeof message === \"object\" && typeof message.name === \"string\" && typeof message.message === \"string\") {\n\t\t\tfor (var key in message) {\n\t\t\t\tif (message.hasOwnProperty(key)) {\n\t\t\t\t\texceptionValues.push(key + \": \" + message[key]);\n\t\t\t\t}\n\t\t\t}\n\t\t\texceptionMessage = exceptionValues.join(\"\\n\") || \"\";\n\t\t\texceptionValues = exceptionMessage.split(\"\\n\");\n\t\t\texceptionMessage = \"EXCEPTION: \" + exceptionValues.join(\"\\nEXCEPTION: \");\n\t\t\tSWFUpload.Console.writeLine(exceptionMessage);\n\t\t} else {\n\t\t\tSWFUpload.Console.writeLine(message);\n\t\t}\n\t}\n};\nSWFUpload.Console = {};\nSWFUpload.Console.writeLine = function (message) {\n\tvar console, documentForm;\n\ttry {\n\t\tconsole = document.getElementById(\"SWFUpload_Console\");\n\t\tif (!console) {\n\t\t\tdocumentForm = document.createElement(\"form\");\n\t\t\tdocument.getElementsByTagName(\"body\")[0].appendChild(documentForm);\n\t\t\tconsole = document.createElement(\"textarea\");\n\t\t\tconsole.id = \"SWFUpload_Console\";\n\t\t\tconsole.style.fontFamily = \"monospace\";\n\t\t\tconsole.setAttribute(\"wrap\", \"off\");\n\t\t\tconsole.wrap = \"off\";\n\t\t\tconsole.style.overflow = \"auto\";\n\t\t\tconsole.style.width = \"700px\";\n\t\t\tconsole.style.height = \"350px\";\n\t\t\tconsole.style.margin = \"5px\";\n\t\t\tdocumentForm.appendChild(console);\n\t\t}\n\t\tconsole.value += message + \"\\n\";\n\t\tconsole.scrollTop = console.scrollHeight - console.clientHeight;\n\t} catch (ex) {\n\t\talert(\"Exception: \" + ex.name + \" Message: \" + ex.message);\n\t}\n};\n})();\n(function() {\n/*\n\tQueue Plug-in\n\tFeatures:\n\t\t*Adds a cancelQueue() method for cancelling the entire queue.\n\t\t*All queued files are uploaded when startUpload() is called.\n\t\t*If false is returned from uploadComplete then the queue upload is stopped.\n\t\t If false is not returned (strict comparison) then the queue upload is continued.\n\t\t*Adds a QueueComplete event that is fired when all the queued files have finished uploading.\n\t\t Set the event handler with the queue_complete_handler setting.\n\t*/\nif (typeof(SWFUpload) === \"function\") {\n\tSWFUpload.queue = {};\n\tSWFUpload.prototype.initSettings = (function (oldInitSettings) {\n\t\treturn function () {\n\t\t\tif (typeof(oldInitSettings) === \"function\") {\n\t\t\t\toldInitSettings.call(this);\n\t\t\t}\n\t\t\tthis.queueSettings = {};\n\t\t\tthis.queueSettings.queue_cancelled_flag = false;\n\t\t\tthis.queueSettings.queue_upload_count = 0;\n\t\t\tthis.queueSettings.user_upload_complete_handler = this.settings.upload_complete_handler;\n\t\t\tthis.queueSettings.user_upload_start_handler = this.settings.upload_start_handler;\n\t\t\tthis.settings.upload_complete_handler = SWFUpload.queue.uploadCompleteHandler;\n\t\t\tthis.settings.upload_start_handler = SWFUpload.queue.uploadStartHandler;\n\t\t\tthis.settings.queue_complete_handler = this.settings.queue_complete_handler || null;\n\t\t};\n\t})(SWFUpload.prototype.initSettings);\n\tSWFUpload.prototype.startUpload = function (fileID) {\n\t\tthis.queueSettings.queue_cancelled_flag = false;\n\t\tthis.callFlash(\"StartUpload\", [fileID]);\n\t};\n\tSWFUpload.prototype.cancelQueue = function () {\n\t\tthis.queueSettings.queue_cancelled_flag = true;\n\t\tthis.stopUpload();\n\t\tvar stats = this.getStats();\n\t\twhile (stats.files_queued > 0) {\n\t\t\tthis.cancelUpload();\n\t\t\tstats = this.getStats();\n\t\t}\n\t};\n\tSWFUpload.queue.uploadStartHandler = function (file) {\n\t\tvar returnValue;\n\t\tif (typeof(this.queueSettings.user_upload_start_handler) === \"function\") {\n\t\t\treturnValue = this.queueSettings.user_upload_start_handler.call(this, file);\n\t\t}\n\t\treturnValue = (returnValue === false) ? false : true;\n\t\tthis.queueSettings.queue_cancelled_flag = !returnValue;\n\t\treturn returnValue;\n\t};\n\tSWFUpload.queue.uploadCompleteHandler = function (file) {\n\t\tvar user_upload_complete_handler = this.queueSettings.user_upload_complete_handler;\n\t\tvar continueUpload;\n\t\tif (file.filestatus === SWFUpload.FILE_STATUS.COMPLETE) {\n\t\t\tthis.queueSettings.queue_upload_count++;\n\t\t}\n\t\tif (typeof(user_upload_complete_handler) === \"function\") {\n\t\t\tcontinueUpload = (user_upload_complete_handler.call(this, file) === false) ? false : true;\n\t\t} else if (file.filestatus === SWFUpload.FILE_STATUS.QUEUED) {\n\t\t\tcontinueUpload = false;\n\t\t} else {\n\t\t\tcontinueUpload = true;\n\t\t}\n\t\tif (continueUpload) {\n\t\t\tvar stats = this.getStats();\n\t\t\tif (stats.files_queued > 0 && this.queueSettings.queue_cancelled_flag === false) {\n\t\t\t\tthis.startUpload();\n\t\t\t} else if (this.queueSettings.queue_cancelled_flag === false) {\n\t\t\t\tthis.queueEvent(\"queue_complete_handler\", [this.queueSettings.queue_upload_count]);\n\t\t\t\tthis.queueSettings.queue_upload_count = 0;\n\t\t\t} else {\n\t\t\t\tthis.queueSettings.queue_cancelled_flag = false;\n\t\t\t\tthis.queueSettings.queue_upload_count = 0;\n\t\t\t}\n\t\t}\n\t};\n}\n})();\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('pagebreak', function(K) {\n\tvar self = this;\n\tvar name = 'pagebreak';\n\tvar pagebreakHtml = K.undef(self.pagebreakHtml, '<hr style=\"page-break-after: always;\" class=\"ke-pagebreak\" />');\n\tself.clickToolbar(name, function() {\n\t\tvar cmd = self.cmd, range = cmd.range;\n\t\tself.focus();\n\t\tvar tail = self.newlineTag == 'br' || K.WEBKIT ? '' : '<span id=\"__kindeditor_tail_tag__\"></span>';\n\t\tself.insertHtml(pagebreakHtml + tail);\n\t\tif (tail !== '') {\n\t\t\tvar p = K('#__kindeditor_tail_tag__', self.edit.doc);\n\t\t\trange.selectNodeContents(p[0]);\n\t\t\tp.removeAttr('id');\n\t\t\tcmd.select();\n\t\t}\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('plainpaste', function(K) {\n\tvar self = this, name = 'plainpaste';\n\tself.clickToolbar(name, function() {\n\t\tvar lang = self.lang(name + '.'),\n\t\t\thtml = '<div style=\"padding:10px 20px;\">' +\n\t\t\t\t'<div style=\"margin-bottom:10px;\">' + lang.comment + '</div>' +\n\t\t\t\t'<textarea class=\"ke-textarea\" style=\"width:408px;height:260px;\"></textarea>' +\n\t\t\t\t'</div>',\n\t\t\tdialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 450,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar html = textarea.val();\n\t\t\t\t\t\thtml = K.escape(html);\n\t\t\t\t\t\thtml = html.replace(/ {2}/g, ' &nbsp;');\n\t\t\t\t\t\tif (self.newlineTag == 'p') {\n\t\t\t\t\t\t\thtml = html.replace(/^/, '<p>').replace(/$/, '</p>').replace(/\\n/g, '</p><p>');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thtml = html.replace(/\\n/g, '<br />$&');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tself.insertHtml(html).hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\ttextarea = K('textarea', dialog.div);\n\t\ttextarea[0].focus();\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('preview', function(K) {\n\tvar self = this, name = 'preview', undefined;\n\tself.clickToolbar(name, function() {\n\t\tvar lang = self.lang(name + '.'),\n\t\t\thtml = '<div style=\"padding:10px 20px;\">' +\n\t\t\t\t'<iframe class=\"ke-textarea\" frameborder=\"0\" style=\"width:708px;height:400px;\"></iframe>' +\n\t\t\t\t'</div>',\n\t\t\tdialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 750,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html\n\t\t\t}),\n\t\t\tiframe = K('iframe', dialog.div),\n\t\t\tdoc = K.iframeDoc(iframe);\n\t\tdoc.open();\n\t\tdoc.write(self.fullHtml());\n\t\tdoc.close();\n\t\tK(doc.body).css('background-color', '#FFF');\n\t\tiframe[0].contentWindow.focus();\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('quickformat', function(K) {\n\tvar self = this, name = 'quickformat',\n\t\tblockMap = K.toMap('blockquote,center,div,h1,h2,h3,h4,h5,h6,p');\n\tfunction getFirstChild(knode) {\n\t\tvar child = knode.first();\n\t\twhile (child && child.first()) {\n\t\t\tchild = child.first();\n\t\t}\n\t\treturn child;\n\t}\n\tself.clickToolbar(name, function() {\n\t\tself.focus();\n\t\tvar doc = self.edit.doc,\n\t\t\trange = self.cmd.range,\n\t\t\tchild = K(doc.body).first(), next,\n\t\t\tnodeList = [], subList = [],\n\t\t\tbookmark = range.createBookmark(true);\n\t\twhile(child) {\n\t\t\tnext = child.next();\n\t\t\tvar firstChild = getFirstChild(child);\n\t\t\tif (!firstChild || firstChild.name != 'img') {\n\t\t\t\tif (blockMap[child.name]) {\n\t\t\t\t\tchild.html(child.html().replace(/^(\\s|&nbsp;|　)+/ig, ''));\n\t\t\t\t\tchild.css('text-indent', '2em');\n\t\t\t\t} else {\n\t\t\t\t\tsubList.push(child);\n\t\t\t\t}\n\t\t\t\tif (!next || (blockMap[next.name] || blockMap[child.name] && !blockMap[next.name])) {\n\t\t\t\t\tif (subList.length > 0) {\n\t\t\t\t\t\tnodeList.push(subList);\n\t\t\t\t\t}\n\t\t\t\t\tsubList = [];\n\t\t\t\t}\n\t\t\t}\n\t\t\tchild = next;\n\t\t}\n\t\tK.each(nodeList, function(i, subList) {\n\t\t\tvar wrapper = K('<p style=\"text-indent:2em;\"></p>', doc);\n\t\t\tsubList[0].before(wrapper);\n\t\t\tK.each(subList, function(i, knode) {\n\t\t\t\twrapper.append(knode);\n\t\t\t});\n\t\t});\n\t\trange.moveToBookmark(bookmark);\n\t\tself.addBookmark();\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('table', function(K) {\n\tvar self = this, name = 'table', lang = self.lang(name + '.'), zeroborder = 'ke-zeroborder';\n\tfunction _setColor(box, color) {\n\t\tcolor = color.toUpperCase();\n\t\tbox.css('background-color', color);\n\t\tbox.css('color', color === '#000000' ? '#FFFFFF' : '#000000');\n\t\tbox.html(color);\n\t}\n\tvar pickerList = [];\n\tfunction _initColorPicker(dialogDiv, colorBox) {\n\t\tcolorBox.bind('click,mousedown', function(e){\n\t\t\te.stopPropagation();\n\t\t});\n\t\tfunction removePicker() {\n\t\t\tK.each(pickerList, function() {\n\t\t\t\tthis.remove();\n\t\t\t});\n\t\t\tpickerList = [];\n\t\t\tK(document).unbind('click,mousedown', removePicker);\n\t\t\tdialogDiv.unbind('click,mousedown', removePicker);\n\t\t}\n\t\tcolorBox.click(function(e) {\n\t\t\tremovePicker();\n\t\t\tvar box = K(this),\n\t\t\t\tpos = box.pos();\n\t\t\tvar picker = K.colorpicker({\n\t\t\t\tx : pos.x,\n\t\t\t\ty : pos.y + box.height(),\n\t\t\t\tz : 811214,\n\t\t\t\tselectedColor : K(this).html(),\n\t\t\t\tcolors : self.colorTable,\n\t\t\t\tnoColor : self.lang('noColor'),\n\t\t\t\tshadowMode : self.shadowMode,\n\t\t\t\tclick : function(color) {\n\t\t\t\t\t_setColor(box, color);\n\t\t\t\t\tremovePicker();\n\t\t\t\t}\n\t\t\t});\n\t\t\tpickerList.push(picker);\n\t\t\tK(document).bind('click,mousedown', removePicker);\n\t\t\tdialogDiv.bind('click,mousedown', removePicker);\n\t\t});\n\t}\n\tfunction _getCellIndex(table, row, cell) {\n\t\tvar rowSpanCount = 0;\n\t\tfor (var i = 0, len = row.cells.length; i < len; i++) {\n\t\t\tif (row.cells[i] == cell) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\trowSpanCount += row.cells[i].rowSpan - 1;\n\t\t}\n\t\treturn cell.cellIndex - rowSpanCount;\n\t}\n\tself.plugin.table = {\n\t\tprop : function(isInsert) {\n\t\t\tvar html = [\n\t\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keRows\" style=\"width:90px;\">' + lang.cells + '</label>',\n\t\t\t\tlang.rows + ' <input type=\"text\" id=\"keRows\" class=\"ke-input-text ke-input-number\" name=\"rows\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\tlang.cols + ' <input type=\"text\" class=\"ke-input-text ke-input-number\" name=\"cols\" value=\"\" maxlength=\"4\" />',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keWidth\" style=\"width:90px;\">' + lang.size + '</label>',\n\t\t\t\tlang.width + ' <input type=\"text\" id=\"keWidth\" class=\"ke-input-text ke-input-number\" name=\"width\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\t'<select name=\"widthType\">',\n\t\t\t\t'<option value=\"%\">' + lang.percent + '</option>',\n\t\t\t\t'<option value=\"px\">' + lang.px + '</option>',\n\t\t\t\t'</select> &nbsp; ',\n\t\t\t\tlang.height + ' <input type=\"text\" class=\"ke-input-text ke-input-number\" name=\"height\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\t'<select name=\"heightType\">',\n\t\t\t\t'<option value=\"%\">' + lang.percent + '</option>',\n\t\t\t\t'<option value=\"px\">' + lang.px + '</option>',\n\t\t\t\t'</select>',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"kePadding\" style=\"width:90px;\">' + lang.space + '</label>',\n\t\t\t\tlang.padding + ' <input type=\"text\" id=\"kePadding\" class=\"ke-input-text ke-input-number\" name=\"padding\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\tlang.spacing + ' <input type=\"text\" class=\"ke-input-text ke-input-number\" name=\"spacing\" value=\"\" maxlength=\"4\" />',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keAlign\" style=\"width:90px;\">' + lang.align + '</label>',\n\t\t\t\t'<select id=\"keAlign\" name=\"align\">',\n\t\t\t\t'<option value=\"\">' + lang.alignDefault + '</option>',\n\t\t\t\t'<option value=\"left\">' + lang.alignLeft + '</option>',\n\t\t\t\t'<option value=\"center\">' + lang.alignCenter + '</option>',\n\t\t\t\t'<option value=\"right\">' + lang.alignRight + '</option>',\n\t\t\t\t'</select>',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keBorder\" style=\"width:90px;\">' + lang.border + '</label>',\n\t\t\t\tlang.borderWidth + ' <input type=\"text\" id=\"keBorder\" class=\"ke-input-text ke-input-number\" name=\"border\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\tlang.borderColor + ' <span class=\"ke-inline-block ke-input-color\"></span>',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keBgColor\" style=\"width:90px;\">' + lang.backgroundColor + '</label>',\n\t\t\t\t'<span class=\"ke-inline-block ke-input-color\"></span>',\n\t\t\t\t'</div>',\n\t\t\t\t'</div>'\n\t\t\t].join('');\n\t\t\tvar bookmark = self.cmd.range.createBookmark();\n\t\t\tvar dialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 500,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tbeforeRemove : function() {\n\t\t\t\t\tcolorBox.unbind();\n\t\t\t\t},\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar rows = rowsBox.val(),\n\t\t\t\t\t\t\tcols = colsBox.val(),\n\t\t\t\t\t\t\twidth = widthBox.val(),\n\t\t\t\t\t\t\theight = heightBox.val(),\n\t\t\t\t\t\t\twidthType = widthTypeBox.val(),\n\t\t\t\t\t\t\theightType = heightTypeBox.val(),\n\t\t\t\t\t\t\tpadding = paddingBox.val(),\n\t\t\t\t\t\t\tspacing = spacingBox.val(),\n\t\t\t\t\t\t\talign = alignBox.val(),\n\t\t\t\t\t\t\tborder = borderBox.val(),\n\t\t\t\t\t\t\tborderColor = K(colorBox[0]).html() || '',\n\t\t\t\t\t\t\tbgColor = K(colorBox[1]).html() || '';\n\t\t\t\t\t\tif (rows == 0 || !/^\\d+$/.test(rows)) {\n\t\t\t\t\t\t\talert(self.lang('invalidRows'));\n\t\t\t\t\t\t\trowsBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (cols == 0 || !/^\\d+$/.test(cols)) {\n\t\t\t\t\t\t\talert(self.lang('invalidRows'));\n\t\t\t\t\t\t\tcolsBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(width)) {\n\t\t\t\t\t\t\talert(self.lang('invalidWidth'));\n\t\t\t\t\t\t\twidthBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(height)) {\n\t\t\t\t\t\t\talert(self.lang('invalidHeight'));\n\t\t\t\t\t\t\theightBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(padding)) {\n\t\t\t\t\t\t\talert(self.lang('invalidPadding'));\n\t\t\t\t\t\t\tpaddingBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(spacing)) {\n\t\t\t\t\t\t\talert(self.lang('invalidSpacing'));\n\t\t\t\t\t\t\tspacingBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(border)) {\n\t\t\t\t\t\t\talert(self.lang('invalidBorder'));\n\t\t\t\t\t\t\tborderBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (table) {\n\t\t\t\t\t\t\tif (width !== '') {\n\t\t\t\t\t\t\t\ttable.width(width + widthType);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.css('width', '');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (table[0].width !== undefined) {\n\t\t\t\t\t\t\t\ttable.removeAttr('width');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (height !== '') {\n\t\t\t\t\t\t\t\ttable.height(height + heightType);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.css('height', '');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (table[0].height !== undefined) {\n\t\t\t\t\t\t\t\ttable.removeAttr('height');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttable.css('background-color', bgColor);\n\t\t\t\t\t\t\tif (table[0].bgColor !== undefined) {\n\t\t\t\t\t\t\t\ttable.removeAttr('bgColor');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (padding !== '') {\n\t\t\t\t\t\t\t\ttable[0].cellPadding = padding;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeAttr('cellPadding');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (spacing !== '') {\n\t\t\t\t\t\t\t\ttable[0].cellSpacing = spacing;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeAttr('cellSpacing');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (align !== '') {\n\t\t\t\t\t\t\t\ttable[0].align = align;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeAttr('align');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (border !== '') {\n\t\t\t\t\t\t\t\ttable.attr('border', border);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeAttr('border');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (border === '' || border === '0') {\n\t\t\t\t\t\t\t\ttable.addClass(zeroborder);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeClass(zeroborder);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (borderColor !== '') {\n\t\t\t\t\t\t\t\ttable.attr('borderColor', borderColor);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeAttr('borderColor');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tself.hideDialog().focus();\n\t\t\t\t\t\t\tself.cmd.range.moveToBookmark(bookmark);\n\t\t\t\t\t\t\tself.cmd.select();\n\t\t\t\t\t\t\tself.addBookmark();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar style = '';\n\t\t\t\t\t\tif (width !== '') {\n\t\t\t\t\t\t\tstyle += 'width:' + width + widthType + ';';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (height !== '') {\n\t\t\t\t\t\t\tstyle += 'height:' + height + heightType + ';';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (bgColor !== '') {\n\t\t\t\t\t\t\tstyle += 'background-color:' + bgColor + ';';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar html = '<table';\n\t\t\t\t\t\tif (style !== '') {\n\t\t\t\t\t\t\thtml += ' style=\"' + style + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (padding !== '') {\n\t\t\t\t\t\t\thtml += ' cellpadding=\"' + padding + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (spacing !== '') {\n\t\t\t\t\t\t\thtml += ' cellspacing=\"' + spacing + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (align !== '') {\n\t\t\t\t\t\t\thtml += ' align=\"' + align + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (border !== '') {\n\t\t\t\t\t\t\thtml += ' border=\"' + border + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (border === '' || border === '0') {\n\t\t\t\t\t\t\thtml += ' class=\"' + zeroborder + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (borderColor !== '') {\n\t\t\t\t\t\t\thtml += ' bordercolor=\"' + borderColor + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\thtml += '>';\n\t\t\t\t\t\tfor (var i = 0; i < rows; i++) {\n\t\t\t\t\t\t\thtml += '<tr>';\n\t\t\t\t\t\t\tfor (var j = 0; j < cols; j++) {\n\t\t\t\t\t\t\t\thtml += '<td>' + (K.IE ? '&nbsp;' : '<br />') + '</td>';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\thtml += '</tr>';\n\t\t\t\t\t\t}\n\t\t\t\t\t\thtml += '</table>';\n\t\t\t\t\t\tif (!K.IE) {\n\t\t\t\t\t\t\thtml += '<br />';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tself.insertHtml(html);\n\t\t\t\t\t\tself.select().hideDialog().focus();\n\t\t\t\t\t\tself.addBookmark();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\tdiv = dialog.div,\n\t\t\trowsBox = K('[name=\"rows\"]', div).val(3),\n\t\t\tcolsBox = K('[name=\"cols\"]', div).val(2),\n\t\t\twidthBox = K('[name=\"width\"]', div).val(100),\n\t\t\theightBox = K('[name=\"height\"]', div),\n\t\t\twidthTypeBox = K('[name=\"widthType\"]', div),\n\t\t\theightTypeBox = K('[name=\"heightType\"]', div),\n\t\t\tpaddingBox = K('[name=\"padding\"]', div).val(2),\n\t\t\tspacingBox = K('[name=\"spacing\"]', div).val(0),\n\t\t\talignBox = K('[name=\"align\"]', div),\n\t\t\tborderBox = K('[name=\"border\"]', div).val(1),\n\t\t\tcolorBox = K('.ke-input-color', div);\n\t\t\t_initColorPicker(div, colorBox.eq(0));\n\t\t\t_initColorPicker(div, colorBox.eq(1));\n\t\t\t_setColor(colorBox.eq(0), '#000000');\n\t\t\t_setColor(colorBox.eq(1), '');\n\t\t\trowsBox[0].focus();\n\t\t\trowsBox[0].select();\n\t\t\tvar table;\n\t\t\tif (isInsert) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttable = self.plugin.getSelectedTable();\n\t\t\tif (table) {\n\t\t\t\trowsBox.val(table[0].rows.length);\n\t\t\t\tcolsBox.val(table[0].rows.length > 0 ? table[0].rows[0].cells.length : 0);\n\t\t\t\trowsBox.attr('disabled', true);\n\t\t\t\tcolsBox.attr('disabled', true);\n\t\t\t\tvar match,\n\t\t\t\t\ttableWidth = table[0].style.width || table[0].width,\n\t\t\t\t\ttableHeight = table[0].style.height || table[0].height;\n\t\t\t\tif (tableWidth !== undefined && (match = /^(\\d+)((?:px|%)*)$/.exec(tableWidth))) {\n\t\t\t\t\twidthBox.val(match[1]);\n\t\t\t\t\twidthTypeBox.val(match[2]);\n\t\t\t\t} else {\n\t\t\t\t\twidthBox.val('');\n\t\t\t\t}\n\t\t\t\tif (tableHeight !== undefined && (match = /^(\\d+)((?:px|%)*)$/.exec(tableHeight))) {\n\t\t\t\t\theightBox.val(match[1]);\n\t\t\t\t\theightTypeBox.val(match[2]);\n\t\t\t\t}\n\t\t\t\tpaddingBox.val(table[0].cellPadding || '');\n\t\t\t\tspacingBox.val(table[0].cellSpacing || '');\n\t\t\t\talignBox.val(table[0].align || '');\n\t\t\t\tborderBox.val(table[0].border === undefined ? '' : table[0].border);\n\t\t\t\t_setColor(colorBox.eq(0), K.toHex(table.attr('borderColor') || ''));\n\t\t\t\t_setColor(colorBox.eq(1), K.toHex(table[0].style.backgroundColor || table[0].bgColor || ''));\n\t\t\t\twidthBox[0].focus();\n\t\t\t\twidthBox[0].select();\n\t\t\t}\n\t\t},\n\t\tcellprop : function() {\n\t\t\tvar html = [\n\t\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keWidth\" style=\"width:90px;\">' + lang.size + '</label>',\n\t\t\t\tlang.width + ' <input type=\"text\" id=\"keWidth\" class=\"ke-input-text ke-input-number\" name=\"width\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\t'<select name=\"widthType\">',\n\t\t\t\t'<option value=\"%\">' + lang.percent + '</option>',\n\t\t\t\t'<option value=\"px\">' + lang.px + '</option>',\n\t\t\t\t'</select> &nbsp; ',\n\t\t\t\tlang.height + ' <input type=\"text\" class=\"ke-input-text ke-input-number\" name=\"height\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\t'<select name=\"heightType\">',\n\t\t\t\t'<option value=\"%\">' + lang.percent + '</option>',\n\t\t\t\t'<option value=\"px\">' + lang.px + '</option>',\n\t\t\t\t'</select>',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keAlign\" style=\"width:90px;\">' + lang.align + '</label>',\n\t\t\t\tlang.textAlign + ' <select id=\"keAlign\" name=\"textAlign\">',\n\t\t\t\t'<option value=\"\">' + lang.alignDefault + '</option>',\n\t\t\t\t'<option value=\"left\">' + lang.alignLeft + '</option>',\n\t\t\t\t'<option value=\"center\">' + lang.alignCenter + '</option>',\n\t\t\t\t'<option value=\"right\">' + lang.alignRight + '</option>',\n\t\t\t\t'</select> ',\n\t\t\t\tlang.verticalAlign + ' <select name=\"verticalAlign\">',\n\t\t\t\t'<option value=\"\">' + lang.alignDefault + '</option>',\n\t\t\t\t'<option value=\"top\">' + lang.alignTop + '</option>',\n\t\t\t\t'<option value=\"middle\">' + lang.alignMiddle + '</option>',\n\t\t\t\t'<option value=\"bottom\">' + lang.alignBottom + '</option>',\n\t\t\t\t'<option value=\"baseline\">' + lang.alignBaseline + '</option>',\n\t\t\t\t'</select>',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keBorder\" style=\"width:90px;\">' + lang.border + '</label>',\n\t\t\t\tlang.borderWidth + ' <input type=\"text\" id=\"keBorder\" class=\"ke-input-text ke-input-number\" name=\"border\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\tlang.borderColor + ' <span class=\"ke-inline-block ke-input-color\"></span>',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keBgColor\" style=\"width:90px;\">' + lang.backgroundColor + '</label>',\n\t\t\t\t'<span class=\"ke-inline-block ke-input-color\"></span>',\n\t\t\t\t'</div>',\n\t\t\t\t'</div>'\n\t\t\t].join('');\n\t\t\tvar bookmark = self.cmd.range.createBookmark();\n\t\t\tvar dialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 500,\n\t\t\t\ttitle : self.lang('tablecell'),\n\t\t\t\tbody : html,\n\t\t\t\tbeforeRemove : function() {\n\t\t\t\t\tcolorBox.unbind();\n\t\t\t\t},\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar width = widthBox.val(),\n\t\t\t\t\t\t\theight = heightBox.val(),\n\t\t\t\t\t\t\twidthType = widthTypeBox.val(),\n\t\t\t\t\t\t\theightType = heightTypeBox.val(),\n\t\t\t\t\t\t\tpadding = paddingBox.val(),\n\t\t\t\t\t\t\tspacing = spacingBox.val(),\n\t\t\t\t\t\t\ttextAlign = textAlignBox.val(),\n\t\t\t\t\t\t\tverticalAlign = verticalAlignBox.val(),\n\t\t\t\t\t\t\tborder = borderBox.val(),\n\t\t\t\t\t\t\tborderColor = K(colorBox[0]).html() || '',\n\t\t\t\t\t\t\tbgColor = K(colorBox[1]).html() || '';\n\t\t\t\t\t\tif (!/^\\d*$/.test(width)) {\n\t\t\t\t\t\t\talert(self.lang('invalidWidth'));\n\t\t\t\t\t\t\twidthBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(height)) {\n\t\t\t\t\t\t\talert(self.lang('invalidHeight'));\n\t\t\t\t\t\t\theightBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(border)) {\n\t\t\t\t\t\t\talert(self.lang('invalidBorder'));\n\t\t\t\t\t\t\tborderBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcell.css({\n\t\t\t\t\t\t\twidth : width !== '' ? (width + widthType) : '',\n\t\t\t\t\t\t\theight : height !== '' ? (height + heightType) : '',\n\t\t\t\t\t\t\t'background-color' : bgColor,\n\t\t\t\t\t\t\t'text-align' : textAlign,\n\t\t\t\t\t\t\t'vertical-align' : verticalAlign,\n\t\t\t\t\t\t\t'border-width' : border,\n\t\t\t\t\t\t\t'border-style' : border !== '' ? 'solid' : '',\n\t\t\t\t\t\t\t'border-color' : borderColor\n\t\t\t\t\t\t});\n\t\t\t\t\t\tself.hideDialog().focus();\n\t\t\t\t\t\tself.cmd.range.moveToBookmark(bookmark);\n\t\t\t\t\t\tself.cmd.select();\n\t\t\t\t\t\tself.addBookmark();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\tdiv = dialog.div,\n\t\t\twidthBox = K('[name=\"width\"]', div).val(100),\n\t\t\theightBox = K('[name=\"height\"]', div),\n\t\t\twidthTypeBox = K('[name=\"widthType\"]', div),\n\t\t\theightTypeBox = K('[name=\"heightType\"]', div),\n\t\t\tpaddingBox = K('[name=\"padding\"]', div).val(2),\n\t\t\tspacingBox = K('[name=\"spacing\"]', div).val(0),\n\t\t\ttextAlignBox = K('[name=\"textAlign\"]', div),\n\t\t\tverticalAlignBox = K('[name=\"verticalAlign\"]', div),\n\t\t\tborderBox = K('[name=\"border\"]', div).val(1),\n\t\t\tcolorBox = K('.ke-input-color', div);\n\t\t\t_initColorPicker(div, colorBox.eq(0));\n\t\t\t_initColorPicker(div, colorBox.eq(1));\n\t\t\t_setColor(colorBox.eq(0), '#000000');\n\t\t\t_setColor(colorBox.eq(1), '');\n\t\t\twidthBox[0].focus();\n\t\t\twidthBox[0].select();\n\t\t\tvar cell = self.plugin.getSelectedCell();\n\t\t\tvar match,\n\t\t\t\tcellWidth = cell[0].style.width || cell[0].width || '',\n\t\t\t\tcellHeight = cell[0].style.height || cell[0].height || '';\n\t\t\tif ((match = /^(\\d+)((?:px|%)*)$/.exec(cellWidth))) {\n\t\t\t\twidthBox.val(match[1]);\n\t\t\t\twidthTypeBox.val(match[2]);\n\t\t\t} else {\n\t\t\t\twidthBox.val('');\n\t\t\t}\n\t\t\tif ((match = /^(\\d+)((?:px|%)*)$/.exec(cellHeight))) {\n\t\t\t\theightBox.val(match[1]);\n\t\t\t\theightTypeBox.val(match[2]);\n\t\t\t}\n\t\t\ttextAlignBox.val(cell[0].style.textAlign || '');\n\t\t\tverticalAlignBox.val(cell[0].style.verticalAlign || '');\n\t\t\tvar border = cell[0].style.borderWidth || '';\n\t\t\tif (border) {\n\t\t\t\tborder = parseInt(border);\n\t\t\t}\n\t\t\tborderBox.val(border);\n\t\t\t_setColor(colorBox.eq(0), K.toHex(cell[0].style.borderColor || ''));\n\t\t\t_setColor(colorBox.eq(1), K.toHex(cell[0].style.backgroundColor || ''));\n\t\t\twidthBox[0].focus();\n\t\t\twidthBox[0].select();\n\t\t},\n\t\tinsert : function() {\n\t\t\tthis.prop(true);\n\t\t},\n\t\t'delete' : function() {\n\t\t\tvar table = self.plugin.getSelectedTable();\n\t\t\tself.cmd.range.setStartBefore(table[0]).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\ttable.remove();\n\t\t\tself.addBookmark();\n\t\t},\n\t\tcolinsert : function(offset) {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\tindex = cell.cellIndex + offset;\n\t\t\tindex += table.rows[0].cells.length - row.cells.length;\n\t\t\tfor (var i = 0, len = table.rows.length; i < len; i++) {\n\t\t\t\tvar newRow = table.rows[i],\n\t\t\t\t\tnewCell = newRow.insertCell(index);\n\t\t\t\tnewCell.innerHTML = K.IE ? '' : '<br />';\n\t\t\t\tindex = _getCellIndex(table, newRow, newCell);\n\t\t\t}\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\tcolinsertleft : function() {\n\t\t\tthis.colinsert(0);\n\t\t},\n\t\tcolinsertright : function() {\n\t\t\tthis.colinsert(1);\n\t\t},\n\t\trowinsert : function(offset) {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0];\n\t\t\tvar rowIndex = row.rowIndex;\n\t\t\tif (offset === 1) {\n\t\t\t\trowIndex = row.rowIndex + (cell.rowSpan - 1) + offset;\n\t\t\t}\n\t\t\tvar newRow = table.insertRow(rowIndex);\n\t\t\tfor (var i = 0, len = row.cells.length; i < len; i++) {\n\t\t\t\tif (row.cells[i].rowSpan > 1) {\n\t\t\t\t\tlen -= row.cells[i].rowSpan - 1;\n\t\t\t\t}\n\t\t\t\tvar newCell = newRow.insertCell(i);\n\t\t\t\tif (offset === 1 && row.cells[i].colSpan > 1) {\n\t\t\t\t\tnewCell.colSpan = row.cells[i].colSpan;\n\t\t\t\t}\n\t\t\t\tnewCell.innerHTML = K.IE ? '' : '<br />';\n\t\t\t}\n\t\t\tfor (var j = rowIndex; j >= 0; j--) {\n\t\t\t\tvar cells = table.rows[j].cells;\n\t\t\t\tif (cells.length > i) {\n\t\t\t\t\tfor (var k = cell.cellIndex; k >= 0; k--) {\n\t\t\t\t\t\tif (cells[k].rowSpan > 1) {\n\t\t\t\t\t\t\tcells[k].rowSpan += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\trowinsertabove : function() {\n\t\t\tthis.rowinsert(0);\n\t\t},\n\t\trowinsertbelow : function() {\n\t\t\tthis.rowinsert(1);\n\t\t},\n\t\trowmerge : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\trowIndex = row.rowIndex,\n\t\t\t\tnextRowIndex = rowIndex + cell.rowSpan,\n\t\t\t\tnextRow = table.rows[nextRowIndex];\n\t\t\tif (table.rows.length <= nextRowIndex) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar cellIndex = cell.cellIndex;\n\t\t\tif (nextRow.cells.length <= cellIndex) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar nextCell = nextRow.cells[cellIndex];\n\t\t\tif (cell.colSpan !== nextCell.colSpan) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcell.rowSpan += nextCell.rowSpan;\n\t\t\tnextRow.deleteCell(cellIndex);\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\tcolmerge : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\trowIndex = row.rowIndex,\n\t\t\t\tcellIndex = cell.cellIndex,\n\t\t\t\tnextCellIndex = cellIndex + 1;\n\t\t\tif (row.cells.length <= nextCellIndex) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar nextCell = row.cells[nextCellIndex];\n\t\t\tif (cell.rowSpan !== nextCell.rowSpan) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcell.colSpan += nextCell.colSpan;\n\t\t\trow.deleteCell(nextCellIndex);\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\trowsplit : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\trowIndex = row.rowIndex;\n\t\t\tif (cell.rowSpan === 1) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar cellIndex = _getCellIndex(table, row, cell);\n\t\t\tfor (var i = 1, len = cell.rowSpan; i < len; i++) {\n\t\t\t\tvar newRow = table.rows[rowIndex + i],\n\t\t\t\t\tnewCell = newRow.insertCell(cellIndex);\n\t\t\t\tif (cell.colSpan > 1) {\n\t\t\t\t\tnewCell.colSpan = cell.colSpan;\n\t\t\t\t}\n\t\t\t\tnewCell.innerHTML = K.IE ? '' : '<br />';\n\t\t\t\tcellIndex = _getCellIndex(table, newRow, newCell);\n\t\t\t}\n\t\t\tK(cell).removeAttr('rowSpan');\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\tcolsplit : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\tcellIndex = cell.cellIndex;\n\t\t\tif (cell.colSpan === 1) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (var i = 1, len = cell.colSpan; i < len; i++) {\n\t\t\t\tvar newCell = row.insertCell(cellIndex + i);\n\t\t\t\tif (cell.rowSpan > 1) {\n\t\t\t\t\tnewCell.rowSpan = cell.rowSpan;\n\t\t\t\t}\n\t\t\t\tnewCell.innerHTML = K.IE ? '' : '<br />';\n\t\t\t}\n\t\t\tK(cell).removeAttr('colSpan');\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\tcoldelete : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\tindex = cell.cellIndex;\n\t\t\tfor (var i = 0, len = table.rows.length; i < len; i++) {\n\t\t\t\tvar newRow = table.rows[i],\n\t\t\t\t\tnewCell = newRow.cells[index];\n\t\t\t\tif (newCell.colSpan > 1) {\n\t\t\t\t\tnewCell.colSpan -= 1;\n\t\t\t\t\tif (newCell.colSpan === 1) {\n\t\t\t\t\t\tK(newCell).removeAttr('colSpan');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnewRow.deleteCell(index);\n\t\t\t\t}\n\t\t\t\tif (newCell.rowSpan > 1) {\n\t\t\t\t\ti += newCell.rowSpan - 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (row.cells.length === 0) {\n\t\t\t\tself.cmd.range.setStartBefore(table).collapse(true);\n\t\t\t\tself.cmd.select();\n\t\t\t\tK(table).remove();\n\t\t\t} else {\n\t\t\t\tself.cmd.selection(true);\n\t\t\t}\n\t\t\tself.addBookmark();\n\t\t},\n\t\trowdelete : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\trowIndex = row.rowIndex;\n\t\t\tfor (var i = cell.rowSpan - 1; i >= 0; i--) {\n\t\t\t\ttable.deleteRow(rowIndex + i);\n\t\t\t}\n\t\t\tif (table.rows.length === 0) {\n\t\t\t\tself.cmd.range.setStartBefore(table).collapse(true);\n\t\t\t\tself.cmd.select();\n\t\t\t\tK(table).remove();\n\t\t\t} else {\n\t\t\t\tself.cmd.selection(true);\n\t\t\t}\n\t\t\tself.addBookmark();\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.table.prop);\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('template', function(K) {\n\tvar self = this, name = 'template', lang = self.lang(name + '.'),\n\t\thtmlPath = self.pluginsPath + name + '/html/';\n\tfunction getFilePath(fileName) {\n\t\treturn htmlPath + fileName + '?ver=' + encodeURIComponent(K.DEBUG ? K.TIME : K.VERSION);\n\t}\n\tself.clickToolbar(name, function() {\n\t\tvar lang = self.lang(name + '.'),\n\t\t\tarr = ['<div style=\"padding:10px 20px;\">',\n\t\t\t\t'<div class=\"ke-header\">',\n\t\t\t\t'<div class=\"ke-left\">',\n\t\t\t\tlang. selectTemplate + ' <select>'];\n\t\t\tK.each(lang.fileList, function(key, val) {\n\t\t\t\tarr.push('<option value=\"' + key + '\">' + val + '</option>');\n\t\t\t});\n\t\t\thtml = [arr.join(''),\n\t\t\t\t'</select></div>',\n\t\t\t\t'<div class=\"ke-right\">',\n\t\t\t\t'<input type=\"checkbox\" id=\"keReplaceFlag\" name=\"replaceFlag\" value=\"1\" /> <label for=\"keReplaceFlag\">' + lang.replaceContent + '</label>',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-clearfix\"></div>',\n\t\t\t\t'</div>',\n\t\t\t\t'<iframe class=\"ke-textarea\" frameborder=\"0\" style=\"width:458px;height:260px;background-color:#FFF;\"></iframe>',\n\t\t\t\t'</div>'].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : 500,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tyesBtn : {\n\t\t\t\tname : self.lang('yes'),\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tvar doc = K.iframeDoc(iframe);\n\t\t\t\t\tself[checkbox[0].checked ? 'html' : 'insertHtml'](doc.body.innerHTML).hideDialog().focus();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tvar selectBox = K('select', dialog.div),\n\t\t\tcheckbox = K('[name=\"replaceFlag\"]', dialog.div),\n\t\t\tiframe = K('iframe', dialog.div);\n\t\tcheckbox[0].checked = true;\n\t\tiframe.attr('src', getFilePath(selectBox.val()));\n\t\tselectBox.change(function() {\n\t\t\tiframe.attr('src', getFilePath(this.value));\n\t\t});\n\t});\n});\n\n/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\nKindEditor.plugin('wordpaste', function(K) {\n\tvar self = this, name = 'wordpaste';\n\tself.clickToolbar(name, function() {\n\t\tvar lang = self.lang(name + '.'),\n\t\t\thtml = '<div style=\"padding:10px 20px;\">' +\n\t\t\t\t'<div style=\"margin-bottom:10px;\">' + lang.comment + '</div>' +\n\t\t\t\t'<iframe class=\"ke-textarea\" frameborder=\"0\" style=\"width:408px;height:260px;\"></iframe>' +\n\t\t\t\t'</div>',\n\t\t\tdialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 450,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar str = doc.body.innerHTML;\n\t\t\t\t\t\tstr = K.clearMsWord(str, self.filterMode ? self.htmlTags : K.options.htmlTags);\n\t\t\t\t\t\tself.insertHtml(str).hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\tdiv = dialog.div,\n\t\t\tiframe = K('iframe', div),\n\t\t\tdoc = K.iframeDoc(iframe);\n\t\tif (!K.IE) {\n\t\t\tdoc.designMode = 'on';\n\t\t}\n\t\tdoc.open();\n\t\tdoc.write('<!doctype html><html><head><title>WordPaste</title></head>');\n\t\tdoc.write('<body style=\"background-color:#FFF;font-size:12px;margin:2px;\">');\n\t\tif (!K.IE) {\n\t\t\tdoc.write('<br />');\n\t\t}\n\t\tdoc.write('</body></html>');\n\t\tdoc.close();\n\t\tif (K.IE) {\n\t\t\tdoc.body.contentEditable = 'true';\n\t\t}\n\t\tiframe[0].contentWindow.focus();\n\t});\n});\n\n\nKindEditor.plugin('fixtoolbar', function (K) {\n    var self = this;\n    if (!self.fixToolBar) {\n        return;\n    }\n    function init() {\n        var toolbar = K('.ke-toolbar');\n        var originY = toolbar.pos().y;\n        K(window).bind('scroll', function () {\n            if (toolbar.css('position') == 'fixed') {\n                if(document.body.scrollTop - originY < 0){\n                    toolbar.css('position', 'static');\n                    toolbar.css('top', 'auto');\n                }\n            } else {\n                if (toolbar.pos().y - document.body.scrollTop < 0) {\n                    toolbar.css('position', 'fixed');\n                    toolbar.css('top', 0);\n                }\n            }\n        });\n    }\n    if (self.isCreated) {\n        init();\n    } else {\n        self.afterCreate(init);\n    }\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/lang/ar.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n* Arabic Translation By daif alotaibi (http://daif.net/)\n*******************************************************************************/\n\nKindEditor.lang({\n\tsource : 'عرض المصدر',\n\tpreview : 'معاينة الصفحة',\n\tundo : 'تراجع(Ctrl+Z)',\n\tredo : 'إعادة التراجع(Ctrl+Y)',\n\tcut : 'قص(Ctrl+X)',\n\tcopy : 'نسخ(Ctrl+C)',\n\tpaste : 'لصق(Ctrl+V)',\n\tplainpaste : 'لصق كنص عادي',\n\twordpaste : 'لصق من مايكروسفت ورد',\n\tselectall : 'تحديد الكل',\n\tjustifyleft : 'محاذاه لليسار',\n\tjustifycenter : 'محاذاه للوسط',\n\tjustifyright : 'محاذاه لليمين',\n\tjustifyfull : 'محاذاه تلقائية',\n\tinsertorderedlist : 'قائمة مرقمه',\n\tinsertunorderedlist : 'قائمة نقطية',\n\tindent : 'إزاحه النص',\n\toutdent : 'إلغاء الازاحة',\n\tsubscript : 'أسفل النص',\n\tsuperscript : 'أعلى النص',\n\tformatblock : 'Paragraph format',\n\tfontname : 'نوع الخط',\n\tfontsize : 'حجم الخط',\n\tforecolor : 'لون النص',\n\thilitecolor : 'لون خلفية النص',\n\tbold : 'عريض(Ctrl+B)',\n\titalic : 'مائل(Ctrl+I)',\n\tunderline : 'خط تحت النص(Ctrl+U)',\n\tstrikethrough : 'خط على النص',\n\tremoveformat : 'إزالة التنسيق',\n\timage : 'إدراج صورة',\n\tmultiimage : 'Multi image',\n\tflash : 'إدراج فلاش',\n\tmedia : 'إدراج وسائط متعددة',\n\ttable : 'إدراج جدول',\n\ttablecell : 'خلية',\n\thr : 'إدراج خط أفقي',\n\temoticons : 'إدراج وجه ضاحك',\n\tlink : 'رابط',\n\tunlink : 'إزالة الرابط',\n\tfullscreen : 'محرر ملئ الشاشة',\n\tabout : 'حول',\n\tprint : 'طباعة',\n\tfilemanager : 'مدير الملفات',\n\tcode : 'إدراج نص برمجي',\n\tmap : 'خرائط قووقل',\n\tbaidumap : 'خرائط قووقل',\n\tlineheight : 'إرتفاع السطر',\n\tclearhtml : 'مسح كود HTML',\n\tpagebreak : 'إدراج فاصل صفحات',\n\tquickformat : 'تنسيق سريع',\n\tinsertfile : 'إدراج ملف',\n\ttemplate : 'إدراج قالب',\n\tanchor : 'رابط',\n\tyes : 'موافق',\n\tno : 'إلغاء',\n\tclose : 'إغلاق',\n\teditImage : 'خصائص الصورة',\n\tdeleteImage : 'حذفالصورة',\n\teditFlash : 'خصائص الفلاش',\n\tdeleteFlash : 'حذف الفلاش',\n\teditMedia : 'خصائص الوسائط',\n\tdeleteMedia : 'حذف الوسائط',\n\teditLink : 'خصائص الرابط',\n\tdeleteLink : 'إزالة الرابط',\n\teditAnchor : 'Anchor properties',\n\tdeleteAnchor : 'Delete Anchor',\n\ttableprop : 'خصائص الجدول',\n\ttablecellprop : 'خصائص الخلية',\n\ttableinsert : 'إدراج جدول',\n\ttabledelete : 'حذف جدول',\n\ttablecolinsertleft : 'إدراج عمود لليسار',\n\ttablecolinsertright : 'إدراج عمود لليسار',\n\ttablerowinsertabove : 'إدراج صف للأعلى',\n\ttablerowinsertbelow : 'إدراج صف للأسفل',\n\ttablerowmerge : 'دمج للأسفل',\n\ttablecolmerge : 'دمج لليمين',\n\ttablerowsplit : 'تقسم الصف',\n\ttablecolsplit : 'تقسيم العمود',\n\ttablecoldelete : 'حذف العمود',\n\ttablerowdelete : 'حذف الصف',\n\tnoColor : 'إفتراضي',\n\tpleaseSelectFile : 'Please select file.',\n\tinvalidImg : \"الرجاء إدخال رابط صحيح.\\nالملفات المسموح بها: jpg,gif,bmp,png\",\n\tinvalidMedia : \"الرجاء إدخال رابط صحيح.\\nالملفات المسموح بها: swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb\",\n\tinvalidWidth : \"العرض يجب أن يكون رقم.\",\n\tinvalidHeight : \"الإرتفاع يجب أن يكون رقم.\",\n\tinvalidBorder : \"عرض الحد يجب أن يكون رقم.\",\n\tinvalidUrl : \"الرجاء إدخال رابط حيح.\",\n\tinvalidRows : 'صفوف غير صحيح.',\n\tinvalidCols : 'أعمدة غير صحيحة.',\n\tinvalidPadding : 'The padding must be number.',\n\tinvalidSpacing : 'The spacing must be number.',\n\tinvalidJson : 'Invalid JSON string.',\n\tuploadSuccess : 'تم رفع الملف بنجاح.',\n\tcutError : 'حاليا غير مدعومة من المتصفح, إستخدم إختصار لوحة المفاتيح (Ctrl+X).',\n\tcopyError : 'حاليا غير مدعومة من المتصفح, إستخدم إختصار لوحة المفاتيح (Ctrl+C).',\n\tpasteError : 'حاليا غير مدعومة من المتصفح, إستخدم إختصار لوحة المفاتيح (Ctrl+V).',\n\tajaxLoading : 'Loading ...',\n\tuploadLoading : 'Uploading ...',\n\tuploadError : 'Upload Error',\n\t'plainpaste.comment' : 'إستخدم إختصار لوحة المفاتيح (Ctrl+V) للصق داخل النافذة.',\n\t'wordpaste.comment' : 'إستخدم إختصار لوحة المفاتيح (Ctrl+V) للصق داخل النافذة.',\n\t'code.pleaseInput' : 'Please input code.',\n\t'link.url' : 'الرابط',\n\t'link.linkType' : 'الهدف',\n\t'link.newWindow' : 'نافذة جديدة',\n\t'link.selfWindow' : 'نفس النافذة',\n\t'flash.url' : 'الرابط',\n\t'flash.width' : 'العرض',\n\t'flash.height' : 'الإرتفاع',\n\t'flash.upload' : 'رفع',\n\t'flash.viewServer' : 'أستعراض',\n\t'media.url' : 'الرابط',\n\t'media.width' : 'العرض',\n\t'media.height' : 'الإرتفاع',\n\t'media.autostart' : 'تشغيل تلقائي',\n\t'media.upload' : 'رفع',\n\t'media.viewServer' : 'أستعراض',\n\t'image.remoteImage' : 'إدراج الرابط',\n\t'image.localImage' : 'رفع',\n\t'image.remoteUrl' : 'الرابط',\n\t'image.localUrl' : 'الملف',\n\t'image.size' : 'الحجم',\n\t'image.width' : 'العرض',\n\t'image.height' : 'الإرتفاع',\n\t'image.resetSize' : 'إستعادة الأبعاد',\n\t'image.align' : 'محاذاة',\n\t'image.defaultAlign' : 'الإفتراضي',\n\t'image.leftAlign' : 'اليسار',\n\t'image.rightAlign' : 'اليمين',\n\t'image.imgTitle' : 'العنوان',\n\t'image.upload' : 'أستعراض',\n\t'image.viewServer' : 'أستعراض',\n\t'multiimage.uploadDesc' : 'Allows users to upload <%=uploadLimit%> images, single image size not exceeding <%=sizeLimit%>',\n\t'multiimage.startUpload' : 'Start upload',\n\t'multiimage.clearAll' : 'Clear all',\n\t'multiimage.insertAll' : 'Insert all',\n\t'multiimage.queueLimitExceeded' : 'Queue limit exceeded.',\n\t'multiimage.fileExceedsSizeLimit' : 'File exceeds size limit.',\n\t'multiimage.zeroByteFile' : 'Zero byte file.',\n\t'multiimage.invalidFiletype' : 'Invalid file type.',\n\t'multiimage.unknownError' : 'Unknown upload error.',\n\t'multiimage.pending' : 'Pending ...',\n\t'multiimage.uploadError' : 'Upload error',\n\t'filemanager.emptyFolder' : 'فارغ',\n\t'filemanager.moveup' : 'المجلد الأب',\n\t'filemanager.viewType' : 'العرض: ',\n\t'filemanager.viewImage' : 'مصغرات',\n\t'filemanager.listImage' : 'قائمة',\n\t'filemanager.orderType' : 'الترتيب: ',\n\t'filemanager.fileName' : 'بالإسم',\n\t'filemanager.fileSize' : 'بالحجم',\n\t'filemanager.fileType' : 'بالنوع',\n\t'insertfile.url' : 'الرابط',\n\t'insertfile.title' : 'العنوان',\n\t'insertfile.upload' : 'رفع',\n\t'insertfile.viewServer' : 'أستعراض',\n\t'table.cells' : 'خلايا',\n\t'table.rows' : 'صفوف',\n\t'table.cols' : 'أعمدة',\n\t'table.size' : 'الأبعاد',\n\t'table.width' : 'العرض',\n\t'table.height' : 'الإرتفاع',\n\t'table.percent' : '%',\n\t'table.px' : 'px',\n\t'table.space' : 'الخارج',\n\t'table.padding' : 'الداخل',\n\t'table.spacing' : 'الفراغات',\n\t'table.align' : 'محاذاه',\n\t'table.textAlign' : 'افقى',\n\t'table.verticalAlign' : 'رأسي',\n\t'table.alignDefault' : 'إفتراضي',\n\t'table.alignLeft' : 'يسار',\n\t'table.alignCenter' : 'وسط',\n\t'table.alignRight' : 'يمين',\n\t'table.alignTop' : 'أعلى',\n\t'table.alignMiddle' : 'منتصف',\n\t'table.alignBottom' : 'أسفل',\n\t'table.alignBaseline' : 'Baseline',\n\t'table.border' : 'الحدود',\n\t'table.borderWidth' : 'العرض',\n\t'table.borderColor' : 'اللون',\n\t'table.backgroundColor' : 'الخلفية',\n\t'map.address' : 'العنوان: ',\n\t'map.search' : 'بحث',\n\t'baidumap.address' : 'العنوان: ',\n\t'baidumap.search' : 'بحث',\n\t'baidumap.insertDynamicMap' : 'Dynamic Map',\n\t'anchor.name' : 'إسم الرابط',\n\t'formatblock.formatBlock' : {\n\t\th1 : 'عنوان 1',\n\t\th2 : 'عنوان 2',\n\t\th3 : 'عنوان 3',\n\t\th4 : 'عنوان 4',\n\t\tp : 'عادي'\n\t},\n\t'fontname.fontName' : {\n\t\t'Arial' : 'Arial',\n\t\t'Arial Black' : 'Arial Black',\n\t\t'Comic Sans MS' : 'Comic Sans MS',\n\t\t'Courier New' : 'Courier New',\n\t\t'Garamond' : 'Garamond',\n\t\t'Georgia' : 'Georgia',\n\t\t'Tahoma' : 'Tahoma',\n\t\t'Times New Roman' : 'Times New Roman',\n\t\t'Trebuchet MS' : 'Trebuchet MS',\n\t\t'Verdana' : 'Verdana'\n\t},\n\t'lineheight.lineHeight' : [\n\t\t{'1' : 'إرتفاع السطر 1'},\n\t\t{'1.5' : 'إرتفاع السطر 1.5'},\n\t\t{'2' : 'إرتفاع السطر 2'},\n\t\t{'2.5' : 'إرتفاع السطر 2.5'},\n\t\t{'3' : 'إرتفاع السطر 3'}\n\t],\n\t'template.selectTemplate' : 'قالب',\n\t'template.replaceContent' : 'إستبدال المحتوى الحالي',\n\t'template.fileList' : {\n\t\t'1.html' : 'صورة ونص',\n\t\t'2.html' : 'جدول',\n\t\t'3.html' : 'قائمة'\n\t}\n}, 'ar');\n\nKindEditor.each(KindEditor.options.items, function(i, name) {\n\tif (name == 'baidumap') {\n\t\tKindEditor.options.items[i] = 'map';\n\t}\n});\nKindEditor.options.langType = 'ar';"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/lang/en.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.lang({\n\tsource : 'Source',\n\tpreview : 'Preview',\n\tundo : 'Undo(Ctrl+Z)',\n\tredo : 'Redo(Ctrl+Y)',\n\tcut : 'Cut(Ctrl+X)',\n\tcopy : 'Copy(Ctrl+C)',\n\tpaste : 'Paste(Ctrl+V)',\n\tplainpaste : 'Paste as plain text',\n\twordpaste : 'Paste from Word',\n\tselectall : 'Select all',\n\tjustifyleft : 'Align left',\n\tjustifycenter : 'Align center',\n\tjustifyright : 'Align right',\n\tjustifyfull : 'Align full',\n\tinsertorderedlist : 'Ordered list',\n\tinsertunorderedlist : 'Unordered list',\n\tindent : 'Increase indent',\n\toutdent : 'Decrease indent',\n\tsubscript : 'Subscript',\n\tsuperscript : 'Superscript',\n\tformatblock : 'Paragraph format',\n\tfontname : 'Font family',\n\tfontsize : 'Font size',\n\tforecolor : 'Text color',\n\thilitecolor : 'Highlight color',\n\tbold : 'Bold(Ctrl+B)',\n\titalic : 'Italic(Ctrl+I)',\n\tunderline : 'Underline(Ctrl+U)',\n\tstrikethrough : 'Strikethrough',\n\tremoveformat : 'Remove format',\n\timage : 'Image',\n\tmultiimage : 'Multi image',\n\tflash : 'Flash',\n\tmedia : 'Embeded media',\n\ttable : 'Table',\n\ttablecell : 'Cell',\n\thr : 'Insert horizontal line',\n\temoticons : 'Insert emoticon',\n\tlink : 'Link',\n\tunlink : 'Unlink',\n\tfullscreen : 'Toggle fullscreen mode',\n\tabout : 'About',\n\tprint : 'Print',\n\tfilemanager : 'File Manager',\n\tcode : 'Insert code',\n\tmap : 'Google Maps',\n\tbaidumap : 'Baidu Maps',\n\tlineheight : 'Line height',\n\tclearhtml : 'Clear HTML code',\n\tpagebreak : 'Insert Page Break',\n\tquickformat : 'Quick Format',\n\tinsertfile : 'Insert file',\n\ttemplate : 'Insert Template',\n\tanchor : 'Anchor',\n\tyes : 'OK',\n\tno : 'Cancel',\n\tclose : 'Close',\n\teditImage : 'Image properties',\n\tdeleteImage : 'Delete image',\n\teditFlash : 'Flash properties',\n\tdeleteFlash : 'Delete flash',\n\teditMedia : 'Media properties',\n\tdeleteMedia : 'Delete media',\n\teditLink : 'Link properties',\n\tdeleteLink : 'Unlink',\n\teditAnchor : 'Anchor properties',\n\tdeleteAnchor : 'Delete Anchor',\n\ttableprop : 'Table properties',\n\ttablecellprop : 'Cell properties',\n\ttableinsert : 'Insert table',\n\ttabledelete : 'Delete table',\n\ttablecolinsertleft : 'Insert column left',\n\ttablecolinsertright : 'Insert column right',\n\ttablerowinsertabove : 'Insert row above',\n\ttablerowinsertbelow : 'Insert row below',\n\ttablerowmerge : 'Merge down',\n\ttablecolmerge : 'Merge right',\n\ttablerowsplit : 'Split row',\n\ttablecolsplit : 'Split column',\n\ttablecoldelete : 'Delete column',\n\ttablerowdelete : 'Delete row',\n\tnoColor : 'Default',\n\tpleaseSelectFile : 'Please select file.',\n\tinvalidImg : \"Please type valid URL.\\nAllowed file extension: jpg,gif,bmp,png\",\n\tinvalidMedia : \"Please type valid URL.\\nAllowed file extension: swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb\",\n\tinvalidWidth : \"The width must be number.\",\n\tinvalidHeight : \"The height must be number.\",\n\tinvalidBorder : \"The border must be number.\",\n\tinvalidUrl : \"Please type valid URL.\",\n\tinvalidRows : 'Invalid rows.',\n\tinvalidCols : 'Invalid columns.',\n\tinvalidPadding : 'The padding must be number.',\n\tinvalidSpacing : 'The spacing must be number.',\n\tinvalidJson : 'Invalid JSON string.',\n\tuploadSuccess : 'Upload success.',\n\tcutError : 'Currently not supported by your browser, use keyboard shortcut(Ctrl+X) instead.',\n\tcopyError : 'Currently not supported by your browser, use keyboard shortcut(Ctrl+C) instead.',\n\tpasteError : 'Currently not supported by your browser, use keyboard shortcut(Ctrl+V) instead.',\n\tajaxLoading : 'Loading ...',\n\tuploadLoading : 'Uploading ...',\n\tuploadError : 'Upload Error',\n\t'plainpaste.comment' : 'Use keyboard shortcut(Ctrl+V) to paste the text into the window.',\n\t'wordpaste.comment' : 'Use keyboard shortcut(Ctrl+V) to paste the text into the window.',\n\t'code.pleaseInput' : 'Please input code.',\n\t'link.url' : 'URL',\n\t'link.linkType' : 'Target',\n\t'link.newWindow' : 'New window',\n\t'link.selfWindow' : 'Same window',\n\t'flash.url' : 'URL',\n\t'flash.width' : 'Width',\n\t'flash.height' : 'Height',\n\t'flash.upload' : 'Upload',\n\t'flash.viewServer' : 'Browse',\n\t'media.url' : 'URL',\n\t'media.width' : 'Width',\n\t'media.height' : 'Height',\n\t'media.autostart' : 'Auto start',\n\t'media.upload' : 'Upload',\n\t'media.viewServer' : 'Browse',\n\t'image.remoteImage' : 'Insert URL',\n\t'image.localImage' : 'Upload',\n\t'image.remoteUrl' : 'URL',\n\t'image.localUrl' : 'File',\n\t'image.size' : 'Size',\n\t'image.width' : 'Width',\n\t'image.height' : 'Height',\n\t'image.resetSize' : 'Reset dimensions',\n\t'image.align' : 'Align',\n\t'image.defaultAlign' : 'Default',\n\t'image.leftAlign' : 'Left',\n\t'image.rightAlign' : 'Right',\n\t'image.imgTitle' : 'Title',\n\t'image.upload' : 'Browse',\n\t'image.viewServer' : 'Browse',\n\t'multiimage.uploadDesc' : 'Allows users to upload <%=uploadLimit%> images, single image size not exceeding <%=sizeLimit%>',\n\t'multiimage.startUpload' : 'Start upload',\n\t'multiimage.clearAll' : 'Clear all',\n\t'multiimage.insertAll' : 'Insert all',\n\t'multiimage.queueLimitExceeded' : 'Queue limit exceeded.',\n\t'multiimage.fileExceedsSizeLimit' : 'File exceeds size limit.',\n\t'multiimage.zeroByteFile' : 'Zero byte file.',\n\t'multiimage.invalidFiletype' : 'Invalid file type.',\n\t'multiimage.unknownError' : 'Unknown upload error.',\n\t'multiimage.pending' : 'Pending ...',\n\t'multiimage.uploadError' : 'Upload error',\n\t'filemanager.emptyFolder' : 'Blank',\n\t'filemanager.moveup' : 'Parent folder',\n\t'filemanager.viewType' : 'Display: ',\n\t'filemanager.viewImage' : 'Thumbnails',\n\t'filemanager.listImage' : 'List',\n\t'filemanager.orderType' : 'Sorting: ',\n\t'filemanager.fileName' : 'By name',\n\t'filemanager.fileSize' : 'By size',\n\t'filemanager.fileType' : 'By type',\n\t'insertfile.url' : 'URL',\n\t'insertfile.title' : 'Title',\n\t'insertfile.upload' : 'Upload',\n\t'insertfile.viewServer' : 'Browse',\n\t'table.cells' : 'Cells',\n\t'table.rows' : 'Rows',\n\t'table.cols' : 'Columns',\n\t'table.size' : 'Dimensions',\n\t'table.width' : 'Width',\n\t'table.height' : 'Height',\n\t'table.percent' : '%',\n\t'table.px' : 'px',\n\t'table.space' : 'Space',\n\t'table.padding' : 'Padding',\n\t'table.spacing' : 'Spacing',\n\t'table.align' : 'Align',\n\t'table.textAlign' : 'Horizontal',\n\t'table.verticalAlign' : 'Vertical',\n\t'table.alignDefault' : 'Default',\n\t'table.alignLeft' : 'Left',\n\t'table.alignCenter' : 'Center',\n\t'table.alignRight' : 'Right',\n\t'table.alignTop' : 'Top',\n\t'table.alignMiddle' : 'Middle',\n\t'table.alignBottom' : 'Bottom',\n\t'table.alignBaseline' : 'Baseline',\n\t'table.border' : 'Border',\n\t'table.borderWidth' : 'Width',\n\t'table.borderColor' : 'Color',\n\t'table.backgroundColor' : 'Background',\n\t'map.address' : 'Address: ',\n\t'map.search' : 'Search',\n\t'baidumap.address' : 'Address: ',\n\t'baidumap.search' : 'Search',\n\t'baidumap.insertDynamicMap' : 'Dynamic Map',\n\t'anchor.name' : 'Anchor name',\n\t'formatblock.formatBlock' : {\n\t\th1 : 'Heading 1',\n\t\th2 : 'Heading 2',\n\t\th3 : 'Heading 3',\n\t\th4 : 'Heading 4',\n\t\tp : 'Normal'\n\t},\n\t'fontname.fontName' : {\n\t\t'Arial' : 'Arial',\n\t\t'Arial Black' : 'Arial Black',\n\t\t'Comic Sans MS' : 'Comic Sans MS',\n\t\t'Courier New' : 'Courier New',\n\t\t'Garamond' : 'Garamond',\n\t\t'Georgia' : 'Georgia',\n\t\t'Tahoma' : 'Tahoma',\n\t\t'Times New Roman' : 'Times New Roman',\n\t\t'Trebuchet MS' : 'Trebuchet MS',\n\t\t'Verdana' : 'Verdana'\n\t},\n\t'lineheight.lineHeight' : [\n\t\t{'1' : 'Line height 1'},\n\t\t{'1.5' : 'Line height 1.5'},\n\t\t{'2' : 'Line height 2'},\n\t\t{'2.5' : 'Line height 2.5'},\n\t\t{'3' : 'Line height 3'}\n\t],\n\t'template.selectTemplate' : 'Template',\n\t'template.replaceContent' : 'Replace current content',\n\t'template.fileList' : {\n\t\t'1.html' : 'Image and Text',\n\t\t'2.html' : 'Table',\n\t\t'3.html' : 'List'\n\t}\n}, 'en');\n\nKindEditor.each(KindEditor.options.items, function(i, name) {\n\tif (name == 'baidumap') {\n\t\tKindEditor.options.items[i] = 'map';\n\t}\n});\nKindEditor.options.langType = 'en';\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/lang/ko.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Composite <ukjinplant@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.lang({\n\tsource : '소스',\n\tpreview : '미리보기',\n\tundo : '작업취소(Ctrl+Z)',\n\tredo : '작업재개(Ctrl+Y)',\n\tcut : '잘라내기(Ctrl+X)',\n\tcopy : '복사(Ctrl+C)',\n\tpaste : '붙여넣기(Ctrl+V)',\n\tplainpaste : '일반 텍스트로 붙여넣기',\n\twordpaste : '워드 문서로 붙여넣기',\n\tselectall : '전체 선택',\n\tjustifyleft : '왼쪽 정렬',\n\tjustifycenter : '가운데 정렬',\n\tjustifyright : '오른쪽 정렬',\n\tjustifyfull : '양쪽 정렬',\n\tinsertorderedlist : '순서 목록',\n\tinsertunorderedlist : '비순서 목록',\n\tindent : '들여쓰기',\n\toutdent : '내어쓰기',\n\tsubscript : '아랫첨자',\n\tsuperscript : '윗첨자',\n\tformatblock : '문단 형식',\n\tfontname : '글꼴',\n\tfontsize : '글자 크기',\n\tforecolor : '글자색',\n\thilitecolor : '강조색',\n\tbold : '굵게(Ctrl+B)',\n\titalic : '이텔릭(Ctrl+I)',\n\tunderline : '빝줄(Ctrl+U)',\n\tstrikethrough : '취소선',\n\tremoveformat : '형식 제거',\n\timage : '이미지 추가',\n\tmultiimage : '여러 이미지 추가',\n\tflash : '플래시 추가',\n\tmedia : '미디어 추가',\n\ttable : '표',\n\ttablecell : '열',\n\thr : '구분선 추가',\n\temoticons : '이모티콘 추가',\n\tlink : '링크',\n\tunlink : '링크 제거',\n\tfullscreen : '전체 화면 모드',\n\tabout : '이 에디터는...',\n\tprint : '인쇄',\n\tfilemanager : '파일 관리자',\n\tcode : '코드 추가',\n\tmap : '구글 맵 추가',\n\tbaidumap : '바이두 맵 추가',\n\tlineheight : '행 간격',\n\tclearhtml : 'HTML 코드 정리',\n\tpagebreak : '페이지 구분 추가',\n\tquickformat : '빠른 형식',\n\tinsertfile : '파일 추가',\n\ttemplate : '템플릿 추가',\n\tanchor : '책갈피',\n\tyes : '확인',\n\tno : '취소',\n\tclose : '닫기',\n\teditImage : '이미지 속성',\n\tdeleteImage : '이미지 삭제',\n\teditFlash : '플래시 속성',\n\tdeleteFlash : '플래시 삭제',\n\teditMedia : '미디어 속성',\n\tdeleteMedia : '미디어 삭제',\n\teditLink : '링크 속성',\n\tdeleteLink : '링크 삭제',\n\teditAnchor : 'Anchor properties',\n\tdeleteAnchor : 'Delete Anchor',\n\ttableprop : '표 속성',\n\ttablecellprop : '열 속성',\n\ttableinsert : '표 추가',\n\ttabledelete : '표 삭제',\n\ttablecolinsertleft : '왼쪽으로 열 추가',\n\ttablecolinsertright : '오른쪽으로 열 추가',\n\ttablerowinsertabove : '위쪽으로 열 추가',\n\ttablerowinsertbelow : '아래쪽으로 열 추가',\n\ttablerowmerge : '아래로 병합',\n\ttablecolmerge : '오른쪽으로 병합',\n\ttablerowsplit : '행 나누기',\n\ttablecolsplit : '열 나누기',\n\ttablecoldelete : '열 삭제',\n\ttablerowdelete : '행 삭제',\n\tnoColor : '기본색',\n\tpleaseSelectFile : '파일 선택',\n\tinvalidImg : \"올바른 주소를 입력하세요.\\njpg,gif,bmp,png 형식이 가능합니다.\",\n\tinvalidMedia : \"올바른 주소를 입력하세요.\\nswf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb 형식이 가능합니다.\",\n\tinvalidWidth : \"넓이 값은 숫자여야 합니다.\",\n\tinvalidHeight : \"높이 값은 숫자여야 합니다.\",\n\tinvalidBorder : \"굵기 값은 숫자여야 합니다.\",\n\tinvalidUrl : \"올바른 주소를 입력하세요.\",\n\tinvalidRows : '올바른 행이 아닙니다.',\n\tinvalidCols : '올바른 열이 아닙니다.',\n\tinvalidPadding : '안쪽 여백 값은 숫자여야 합니다.',\n\tinvalidSpacing : '간격 길이 값은 숫자여야 합니다.',\n\tinvalidJson : '올바른 JSON 형식이 아닙니다.',\n\tuploadSuccess : '업로드가 완료되었습니다.',\n\tcutError : '브라우저가 잘라내기 기능을 지원하지 않습니다, 단축키로 대신 사용하세요. (Ctrl+X)',\n\tcopyError : '브라우저가 복사 기능을 지원하지 않습니다, 단축키로 대신 사용하세요. (Ctrl+X)',\n\tpasteError : '브라우저가 붙여넣기 기능을 지원하지 않습니다, 단축키로 대신 사용하세요. (Ctrl+X)',\n\tajaxLoading : '불러오는 중 ...',\n\tuploadLoading : '업로드 중 ...',\n\tuploadError : '업로드 오류',\n\t'plainpaste.comment' : '단축키(Ctrl+V)를 통하여 여기에 텍스트를 붙여넣으세요.',\n\t'wordpaste.comment' : '단축키(Ctrl+V)를 통하여 여기에 워드 텍스트를 붙여넣으세요.',\n\t'code.pleaseInput' : 'Please input code.',\n\t'link.url' : '주소',\n\t'link.linkType' : '창',\n\t'link.newWindow' : '새 창',\n\t'link.selfWindow' : '현재 창',\n\t'flash.url' : '주소',\n\t'flash.width' : '넓이',\n\t'flash.height' : '높이',\n\t'flash.upload' : '업로드',\n\t'flash.viewServer' : '찾아보기',\n\t'media.url' : '주소',\n\t'media.width' : '넓이',\n\t'media.height' : '높이',\n\t'media.autostart' : '자동 시작',\n\t'media.upload' : '업로드',\n\t'media.viewServer' : '찾아보기',\n\t'image.remoteImage' : '외부 이미지',\n\t'image.localImage' : '내부 이미지',\n\t'image.remoteUrl' : '주소',\n\t'image.localUrl' : '파일',\n\t'image.size' : '크기',\n\t'image.width' : '넓이',\n\t'image.height' : '높이',\n\t'image.resetSize' : '기본 크기로',\n\t'image.align' : '정렬',\n\t'image.defaultAlign' : '기본',\n\t'image.leftAlign' : '왼쪽',\n\t'image.rightAlign' : '오른쪽',\n\t'image.imgTitle' : '제목',\n\t'image.upload' : '찾아보기',\n\t'image.viewServer' : '찾아보기',\n\t'multiimage.uploadDesc' : '최대 이미지 개수: <%=uploadLimit%>개, 개당 이미지 크기: <%=sizeLimit%>',\n\t'multiimage.startUpload' : '업로드 시작',\n\t'multiimage.clearAll' : '모두 삭제',\n\t'multiimage.insertAll' : '모두 삽입',\n\t'multiimage.queueLimitExceeded' : '업로드 개수가 초과되었습니다.',\n\t'multiimage.fileExceedsSizeLimit' : '업로드 크기가 초과되었습니다.',\n\t'multiimage.zeroByteFile' : '파일 크기가 없습니다.',\n\t'multiimage.invalidFiletype' : '올바른 이미지가 아닙니다.',\n\t'multiimage.unknownError' : '알 수 없는 업로드 오류가 발생하였습니다.',\n\t'multiimage.pending' : '처리 중 ...',\n\t'multiimage.uploadError' : '업로드 오류',\n\t'filemanager.emptyFolder' : '빈 폴더',\n\t'filemanager.moveup' : '위로',\n\t'filemanager.viewType' : '보기 방식: ',\n\t'filemanager.viewImage' : '미리 보기',\n\t'filemanager.listImage' : '목록',\n\t'filemanager.orderType' : '정렬 방식: ',\n\t'filemanager.fileName' : '이름별',\n\t'filemanager.fileSize' : '크기별',\n\t'filemanager.fileType' : '종류별',\n\t'insertfile.url' : '주소',\n\t'insertfile.title' : '제목',\n\t'insertfile.upload' : '업로드',\n\t'insertfile.viewServer' : '찾아보기',\n\t'table.cells' : '열',\n\t'table.rows' : '행',\n\t'table.cols' : '열',\n\t'table.size' : '표 크기',\n\t'table.width' : '넓이',\n\t'table.height' : '높이',\n\t'table.percent' : '%',\n\t'table.px' : 'px',\n\t'table.space' : '간격',\n\t'table.padding' : '안쪽여백',\n\t'table.spacing' : '간격',\n\t'table.align' : '정렬',\n\t'table.textAlign' : '수직',\n\t'table.verticalAlign' : '수평',\n\t'table.alignDefault' : '기본',\n\t'table.alignLeft' : '왼쪽',\n\t'table.alignCenter' : '가운데',\n\t'table.alignRight' : '오른쪽',\n\t'table.alignTop' : '위쪽',\n\t'table.alignMiddle' : '중간',\n\t'table.alignBottom' : '아래쪽',\n\t'table.alignBaseline' : '글자기준',\n\t'table.border' : '테두리',\n\t'table.borderWidth' : '크기',\n\t'table.borderColor' : '색상',\n\t'table.backgroundColor' : '배경',\n\t'map.address' : '주소: ',\n\t'map.search' : '검색',\n\t'baidumap.address' : '주소: ',\n\t'baidumap.search' : '검색',\n\t'baidumap.insertDynamicMap' : '동적 지도',\n\t'anchor.name' : '책갈피명',\n\t'formatblock.formatBlock' : {\n\t\th1 : '제목 1',\n\t\th2 : '제목 2',\n\t\th3 : '제목 3',\n\t\th4 : '제목 4',\n\t\tp : '본문'\n\t},\n\t'fontname.fontName' : {\n\t\t'Gulim' : '굴림',\n\t\t'Dotum' : '돋움',\n\t\t'Batang' : '바탕',\n\t\t'Gungsuh' : '궁서',\n\t\t'Malgun Gothic' : '맑은 고딕',\n\t\t'Arial' : 'Arial',\n\t\t'Arial Black' : 'Arial Black',\n\t\t'Comic Sans MS' : 'Comic Sans MS',\n\t\t'Courier New' : 'Courier New',\n\t\t'Garamond' : 'Garamond',\n\t\t'Georgia' : 'Georgia',\n\t\t'Tahoma' : 'Tahoma',\n\t\t'Times New Roman' : 'Times New Roman',\n\t\t'Trebuchet MS' : 'Trebuchet MS',\n\t\t'Verdana' : 'Verdana'\n\t},\n\t'lineheight.lineHeight' : [\n\t\t{'1' : '행간 1'},\n\t\t{'1.5' : '행간 1.5'},\n\t\t{'2' : '행간 2'},\n\t\t{'2.5' : '행간 2.5'},\n\t\t{'3' : '행간 3'}\n\t],\n\t'template.selectTemplate' : '템플릿',\n\t'template.replaceContent' : '내용 바꾸기',\n\t'template.fileList' : {\n\t\t'1.html' : '이미지와 텍스트',\n\t\t'2.html' : '표',\n\t\t'3.html' : '목록'\n\t}\n}, 'ko');\n\nKindEditor.each(KindEditor.options.items, function(i, name) {\n\tif (name == 'baidumap') {\n\t\tKindEditor.options.items[i] = 'map';\n\t}\n});\nKindEditor.options.langType = 'ko';\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/lang/ru.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n* Translated to Russian by Valery Votintsev (http://codersclub.org/)\n*******************************************************************************/\n\nKindEditor.lang({\n\tsource : 'Source',\n\tpreview : 'Preview',\n\tundo : 'Отмена(Ctrl+Z)',\n\tredo : 'Повтор(Ctrl+Y)',\n\tcut : 'Вырезать(Ctrl+X)',\n\tcopy : 'Копировать(Ctrl+C)',\n\tpaste : 'Вставить(Ctrl+V)',\n\tplainpaste : 'Вставить как простой текст',\n\twordpaste : 'Вставить из Word',\n\tselectall : 'Выбрать все',\n\tjustifyleft : 'Выравнивание влево',\n\tjustifycenter : 'Выравнивание по центру',\n\tjustifyright : 'Выравнивание вправо',\n\tjustifyfull : 'Выравнивание по обеим сторонам',\n\tinsertorderedlist : 'Нумерованый список',\n\tinsertunorderedlist : 'Ненумерованый список',\n\tindent : 'Добавить отступ',\n\toutdent : 'Убрать отступ',\n\tsubscript : 'Надстрочный',\n\tsuperscript : 'Подстрочный',\n\tformatblock : 'Формат параграфа',\n\tfontname : 'Шрифт',\n\tfontsize : 'Размер',\n\tforecolor : 'Цвет текста',\n\thilitecolor : 'Цвет фона',\n\tbold : 'Жирный(Ctrl+B)',\n\titalic : 'Наклонный(Ctrl+I)',\n\tunderline : 'Подчёркнутый(Ctrl+U)',\n\tstrikethrough : 'Перечёркнутый',\n\tremoveformat : 'Удалить формат',\n\timage : 'Изображение',\n\tmultiimage : 'Мульти-загрузка',\n\tflash : 'Flash',\n\tmedia : 'Встроенные данные',\n\ttable : 'Таблица',\n\ttablecell : 'Ячейка',\n\thr : 'Горизонтальный разделитель',\n\temoticons : 'Смайл',\n\tlink : 'Ссылка',\n\tunlink : 'Убрать ссылку',\n\tfullscreen : 'На весь экран',\n\tabout : 'О программе',\n\tprint : 'Печать',\n\tfilemanager : 'Файлы',\n\tcode : 'Код',\n\tmap : 'Карта Google',\n\tbaidumap : 'Карта Baidu',\n\tlineheight : 'Межстрочный интервал',\n\tclearhtml : 'Очистить HTML код',\n\tpagebreak : 'Разрыв страницы',\n\tquickformat : 'Быстрый формат',\n\tinsertfile : 'Вставить файл',\n\ttemplate : 'Вставить шаблон',\n\tanchor : 'Якорь',\n\tyes : 'OK',\n\tno : 'Отмена',\n\tclose : 'Закрыть',\n\teditImage : 'Свойства изображения',\n\tdeleteImage : 'Удалить изображение',\n\teditFlash : 'Свойства Flash',\n\tdeleteFlash : 'Удалить Flash',\n\teditMedia : 'Свойства Media',\n\tdeleteMedia : 'Удалить Media',\n\teditLink : 'Свойства ссылки',\n\tdeleteLink : 'Удалить ссылку',\n\teditAnchor : 'Anchor properties',\n\tdeleteAnchor : 'Delete Anchor',\n\ttableprop : 'Свойства таблицы',\n\ttablecellprop : 'Свойства ячейки',\n\ttableinsert : 'Вставить таблицу',\n\ttabledelete : 'Удалить таблицу',\n\ttablecolinsertleft : 'Добавить столбец слева',\n\ttablecolinsertright : 'Добавить столбец справа',\n\ttablerowinsertabove : 'Добавить строку выше',\n\ttablerowinsertbelow : 'Добавить строку ниже',\n\ttablerowmerge : 'Объединить вниз',\n\ttablecolmerge : 'Объединить вправо',\n\ttablerowsplit : 'Разделить строку',\n\ttablecolsplit : 'Разделить столбец',\n\ttablecoldelete : 'Удалить столбец',\n\ttablerowdelete : 'Удалить строку',\n\tnoColor : 'По умолчанию',\n\tpleaseSelectFile : 'Выберите файл.',\n\tinvalidImg : \"Укажите корректный URL изображения.\\nРазрешённые форматы: jpg,gif,bmp,png\",\n\tinvalidMedia : \"Укажите корректный тип медиа-объекта.\\nРазрешённые типы: swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb\",\n\tinvalidWidth : \"Ширина должна быть числом.\",\n\tinvalidHeight : \"Высота должна быть числом.\",\n\tinvalidBorder : \"Ширина рамки должна быть числом.\",\n\tinvalidUrl : \"Укажите корректный URL.\",\n\tinvalidRows : 'Неверные строки.',\n\tinvalidCols : 'Неверные столбцы.',\n\tinvalidPadding : 'padding должен быть числом.',\n\tinvalidSpacing : 'spacing должен быть числом.',\n\tinvalidJson : 'Неверная JSON строка.',\n\tuploadSuccess : 'Загрузка завершена.',\n\tcutError : 'Данная опция не поддерживается вашим браузером, воспользуйтесь комбинацией клавиш (Ctrl+X).',\n\tcopyError : 'Данная опция не поддерживается вашим браузером, воспользуйтесь комбинацией клавиш (Ctrl+C).',\n\tpasteError : 'Данная опция не поддерживается вашим браузером, воспользуйтесь комбинацией клавиш (Ctrl+V).',\n\tajaxLoading : 'Загрузка ...',\n\tuploadLoading : 'Загрузка ...',\n\tuploadError : 'Сбой загрузки',\n\t'plainpaste.comment' : 'Для вставки скопированного текста воспользуйтесь комбинацией клавиш (Ctrl+V).',\n\t'wordpaste.comment' : 'Для вставки скопированного текста воспользуйтесь комбинацией клавиш (Ctrl+V).',\n\t'code.pleaseInput' : 'Введите код.',\n\t'link.url' : 'URL',\n\t'link.linkType' : 'Открывать ссылку',\n\t'link.newWindow' : 'в новом окне',\n\t'link.selfWindow' : 'в том же окне',\n\t'flash.url' : 'URL',\n\t'flash.width' : 'Ширина',\n\t'flash.height' : 'Высота',\n\t'flash.upload' : 'Загрузить',\n\t'flash.viewServer' : 'Выбрать',\n\t'media.url' : 'URL',\n\t'media.width' : 'Ширина',\n\t'media.height' : 'Высота',\n\t'media.autostart' : 'Автостарт',\n\t'media.upload' : 'Загрузить',\n\t'media.viewServer' : 'Выбрать',\n\t'image.remoteImage' : 'Вставить URL изображения',\n\t'image.localImage' : 'Загрузить',\n\t'image.remoteUrl' : 'URL',\n\t'image.localUrl' : 'Файл',\n\t'image.size' : 'Размер',\n\t'image.width' : 'Ширина',\n\t'image.height' : 'Высота',\n\t'image.resetSize' : 'Сбросить размеры',\n\t'image.align' : 'Выравнивание',\n\t'image.defaultAlign' : 'По умолчанию',\n\t'image.leftAlign' : 'Влево',\n\t'image.rightAlign' : 'Вправо',\n\t'image.imgTitle' : 'Название',\n\t'image.upload' : 'Загрузить',\n\t'image.viewServer' : 'Выбрать',\n\t'multiimage.uploadDesc' : 'Максимальное кол-во изображений: <%=uploadLimit%>, Максимальный размер одного изображения: <%=sizeLimit%>',\n\t'multiimage.startUpload' : 'Начать загрузку',\n\t'multiimage.clearAll' : 'Очистить все',\n\t'multiimage.insertAll' : 'Вставить все',\n\t'multiimage.queueLimitExceeded' : 'Превышен лимит очереди.',\n\t'multiimage.fileExceedsSizeLimit' : 'Превышен максимальный размер файла.',\n\t'multiimage.zeroByteFile' : 'Файл нулевой длины.',\n\t'multiimage.invalidFiletype' : 'Недопустимый тип файла.',\n\t'multiimage.unknownError' : 'Непредвиденная ошибка загрузки.',\n\t'multiimage.pending' : 'Ожидает ...',\n\t'multiimage.uploadError' : 'Ошибка загрузки',\n\t'filemanager.emptyFolder' : 'Папка пуста',\n\t'filemanager.moveup' : 'Наверх',\n\t'filemanager.viewType' : 'Тип показа: ',\n\t'filemanager.viewImage' : 'Превьюшки',\n\t'filemanager.listImage' : 'Список',\n\t'filemanager.orderType' : 'Сортировка: ',\n\t'filemanager.fileName' : 'По имени',\n\t'filemanager.fileSize' : 'По размеру',\n\t'filemanager.fileType' : 'По типу',\n\t'insertfile.url' : 'URL',\n\t'insertfile.title' : 'Название',\n\t'insertfile.upload' : 'Загрузить',\n\t'insertfile.viewServer' : 'Выбрать',\n\t'table.cells' : 'Ячейки',\n\t'table.rows' : 'Строки',\n\t'table.cols' : 'Столбцы',\n\t'table.size' : 'Размеры',\n\t'table.width' : 'Ширина',\n\t'table.height' : 'Высота',\n\t'table.percent' : '%',\n\t'table.px' : 'px',\n\t'table.space' : 'Space',\n\t'table.padding' : 'Padding',\n\t'table.spacing' : 'Spacing',\n\t'table.align' : 'Выравнивание',\n\t'table.textAlign' : 'По горизонтали',\n\t'table.verticalAlign' : 'По вертикали',\n\t'table.alignDefault' : 'По умолчанию',\n\t'table.alignLeft' : 'Влево',\n\t'table.alignCenter' : 'По центру',\n\t'table.alignRight' : 'Вправо',\n\t'table.alignTop' : 'Вверх',\n\t'table.alignMiddle' : 'Посередине',\n\t'table.alignBottom' : 'Вниз',\n\t'table.alignBaseline' : 'По базовой линии',\n\t'table.border' : 'Рамка',\n\t'table.borderWidth' : 'Ширина',\n\t'table.borderColor' : 'Цвет',\n\t'table.backgroundColor' : 'Цвет фона',\n\t'map.address' : 'Адрес: ',\n\t'map.search' : 'Поиск',\n\t'baidumap.address' : 'Адрес: ',\n\t'baidumap.search' : 'Поиск',\n\t'baidumap.insertDynamicMap' : 'Динамическая карта',\n\t'anchor.name' : 'Имя якоря',\n\t'formatblock.formatBlock' : {\n\t\th1 : 'Заголовок 1',\n\t\th2 : 'Заголовок 2',\n\t\th3 : 'Заголовок 3',\n\t\th4 : 'Заголовок 4',\n\t\tp : 'Обычный текст'\n\t},\n\t'fontname.fontName' : {\n\t\t'Arial' : 'Arial',\n\t\t'Arial Black' : 'Arial Black',\n\t\t'Comic Sans MS' : 'Comic Sans MS',\n\t\t'Courier New' : 'Courier New',\n\t\t'Garamond' : 'Garamond',\n\t\t'Georgia' : 'Georgia',\n\t\t'Tahoma' : 'Tahoma',\n\t\t'Times New Roman' : 'Times New Roman',\n\t\t'Trebuchet MS' : 'Trebuchet MS',\n\t\t'Verdana' : 'Verdana'\n\t},\n\t'lineheight.lineHeight' : [\n\t\t{'1' : '1'},\n\t\t{'1.5' : '1.5'},\n\t\t{'2' : '2'},\n\t\t{'2.5' : '2.5'},\n\t\t{'3' : '3'}\n\t],\n\t'template.selectTemplate' : 'Шаблон',\n\t'template.replaceContent' : 'Заменить текущий шаблон',\n\t'template.fileList' : {\n\t\t'1.html' : 'Текст и изображения',\n\t\t'2.html' : 'Таблица',\n\t\t'3.html' : 'Список'\n\t}\n}, 'en');\n\nKindEditor.each(KindEditor.options.items, function(i, name) {\n\tif (name == 'baidumap') {\n\t\tKindEditor.options.items[i] = 'map';\n\t}\n});\nKindEditor.options.langType = 'ru';\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/lang/zh-CN.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.lang({\n\tsource : 'HTML代码',\n\tpreview : '预览',\n\tundo : '后退(Ctrl+Z)',\n\tredo : '前进(Ctrl+Y)',\n\tcut : '剪切(Ctrl+X)',\n\tcopy : '复制(Ctrl+C)',\n\tpaste : '粘贴(Ctrl+V)',\n\tplainpaste : '粘贴为无格式文本',\n\twordpaste : '从Word粘贴',\n\tselectall : '全选(Ctrl+A)',\n\tjustifyleft : '左对齐',\n\tjustifycenter : '居中',\n\tjustifyright : '右对齐',\n\tjustifyfull : '两端对齐',\n\tinsertorderedlist : '编号',\n\tinsertunorderedlist : '项目符号',\n\tindent : '增加缩进',\n\toutdent : '减少缩进',\n\tsubscript : '下标',\n\tsuperscript : '上标',\n\tformatblock : '段落',\n\tfontname : '字体',\n\tfontsize : '文字大小',\n\tforecolor : '文字颜色',\n\thilitecolor : '文字背景',\n\tbold : '粗体(Ctrl+B)',\n\titalic : '斜体(Ctrl+I)',\n\tunderline : '下划线(Ctrl+U)',\n\tstrikethrough : '删除线',\n\tremoveformat : '删除格式',\n\timage : '图片',\n\tmultiimage : '批量图片上传',\n\tflash : 'Flash',\n\tmedia : '视音频',\n\ttable : '表格',\n\ttablecell : '单元格',\n\thr : '插入横线',\n\temoticons : '插入表情',\n\tlink : '超级链接',\n\tunlink : '取消超级链接',\n\tfullscreen : '全屏显示',\n\tabout : '关于',\n\tprint : '打印(Ctrl+P)',\n\tfilemanager : '文件空间',\n\tcode : '插入程序代码',\n\tmap : 'Google地图',\n\tbaidumap : '百度地图',\n\tlineheight : '行距',\n\tclearhtml : '清理HTML代码',\n\tpagebreak : '插入分页符',\n\tquickformat : '一键排版',\n\tinsertfile : '插入文件',\n\ttemplate : '插入模板',\n\tanchor : '锚点',\n\tyes : '确定',\n\tno : '取消',\n\tclose : '关闭',\n\teditImage : '图片属性',\n\tdeleteImage : '删除图片',\n\teditFlash : 'Flash属性',\n\tdeleteFlash : '删除Flash',\n\teditMedia : '视音频属性',\n\tdeleteMedia : '删除视音频',\n\teditLink : '超级链接属性',\n\tdeleteLink : '取消超级链接',\n\teditAnchor : '锚点属性',\n\tdeleteAnchor : '删除锚点',\n\ttableprop : '表格属性',\n\ttablecellprop : '单元格属性',\n\ttableinsert : '插入表格',\n\ttabledelete : '删除表格',\n\ttablecolinsertleft : '左侧插入列',\n\ttablecolinsertright : '右侧插入列',\n\ttablerowinsertabove : '上方插入行',\n\ttablerowinsertbelow : '下方插入行',\n\ttablerowmerge : '向下合并单元格',\n\ttablecolmerge : '向右合并单元格',\n\ttablerowsplit : '拆分行',\n\ttablecolsplit : '拆分列',\n\ttablecoldelete : '删除列',\n\ttablerowdelete : '删除行',\n\tnoColor : '无颜色',\n\tpleaseSelectFile : '请选择文件。',\n\tinvalidImg : \"请输入有效的URL地址。\\n只允许jpg,gif,bmp,png格式。\",\n\tinvalidMedia : \"请输入有效的URL地址。\\n只允许swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb格式。\",\n\tinvalidWidth : \"宽度必须为数字。\",\n\tinvalidHeight : \"高度必须为数字。\",\n\tinvalidBorder : \"边框必须为数字。\",\n\tinvalidUrl : \"请输入有效的URL地址。\",\n\tinvalidRows : '行数为必选项，只允许输入大于0的数字。',\n\tinvalidCols : '列数为必选项，只允许输入大于0的数字。',\n\tinvalidPadding : '边距必须为数字。',\n\tinvalidSpacing : '间距必须为数字。',\n\tinvalidJson : '服务器发生故障。',\n\tuploadSuccess : '上传成功。',\n\tcutError : '您的浏览器安全设置不允许使用剪切操作，请使用快捷键(Ctrl+X)来完成。',\n\tcopyError : '您的浏览器安全设置不允许使用复制操作，请使用快捷键(Ctrl+C)来完成。',\n\tpasteError : '您的浏览器安全设置不允许使用粘贴操作，请使用快捷键(Ctrl+V)来完成。',\n\tajaxLoading : '加载中，请稍候 ...',\n\tuploadLoading : '上传中，请稍候 ...',\n\tuploadError : '上传错误',\n\t'plainpaste.comment' : '请使用快捷键(Ctrl+V)把内容粘贴到下面的方框里。',\n\t'wordpaste.comment' : '请使用快捷键(Ctrl+V)把内容粘贴到下面的方框里。',\n\t'code.pleaseInput' : '请输入程序代码。',\n\t'link.url' : 'URL',\n\t'link.linkType' : '打开类型',\n\t'link.newWindow' : '新窗口',\n\t'link.selfWindow' : '当前窗口',\n\t'flash.url' : 'URL',\n\t'flash.width' : '宽度',\n\t'flash.height' : '高度',\n\t'flash.upload' : '上传',\n\t'flash.viewServer' : '文件空间',\n\t'media.url' : 'URL',\n\t'media.width' : '宽度',\n\t'media.height' : '高度',\n\t'media.autostart' : '自动播放',\n\t'media.upload' : '上传',\n\t'media.viewServer' : '文件空间',\n\t'image.remoteImage' : '网络图片',\n\t'image.localImage' : '本地上传',\n\t'image.remoteUrl' : '图片地址',\n\t'image.localUrl' : '上传文件',\n\t'image.size' : '图片大小',\n\t'image.width' : '宽',\n\t'image.height' : '高',\n\t'image.resetSize' : '重置大小',\n\t'image.align' : '对齐方式',\n\t'image.defaultAlign' : '默认方式',\n\t'image.leftAlign' : '左对齐',\n\t'image.rightAlign' : '右对齐',\n\t'image.imgTitle' : '图片说明',\n\t'image.upload' : '浏览...',\n\t'image.viewServer' : '图片空间',\n\t'multiimage.uploadDesc' : '允许用户同时上传<%=uploadLimit%>张图片，单张图片容量不超过<%=sizeLimit%>',\n\t'multiimage.startUpload' : '开始上传',\n\t'multiimage.clearAll' : '全部清空',\n\t'multiimage.insertAll' : '全部插入',\n\t'multiimage.queueLimitExceeded' : '文件数量超过限制。',\n\t'multiimage.fileExceedsSizeLimit' : '文件大小超过限制。',\n\t'multiimage.zeroByteFile' : '无法上传空文件。',\n\t'multiimage.invalidFiletype' : '文件类型不正确。',\n\t'multiimage.unknownError' : '发生异常，无法上传。',\n\t'multiimage.pending' : '等待上传',\n\t'multiimage.uploadError' : '上传失败',\n\t'filemanager.emptyFolder' : '空文件夹',\n\t'filemanager.moveup' : '移到上一级文件夹',\n\t'filemanager.viewType' : '显示方式：',\n\t'filemanager.viewImage' : '缩略图',\n\t'filemanager.listImage' : '详细信息',\n\t'filemanager.orderType' : '排序方式：',\n\t'filemanager.fileName' : '名称',\n\t'filemanager.fileSize' : '大小',\n\t'filemanager.fileType' : '类型',\n\t'insertfile.url' : 'URL',\n\t'insertfile.title' : '文件说明',\n\t'insertfile.upload' : '上传',\n\t'insertfile.viewServer' : '文件空间',\n\t'table.cells' : '单元格数',\n\t'table.rows' : '行数',\n\t'table.cols' : '列数',\n\t'table.size' : '大小',\n\t'table.width' : '宽度',\n\t'table.height' : '高度',\n\t'table.percent' : '%',\n\t'table.px' : 'px',\n\t'table.space' : '边距间距',\n\t'table.padding' : '边距',\n\t'table.spacing' : '间距',\n\t'table.align' : '对齐方式',\n\t'table.textAlign' : '水平对齐',\n\t'table.verticalAlign' : '垂直对齐',\n\t'table.alignDefault' : '默认',\n\t'table.alignLeft' : '左对齐',\n\t'table.alignCenter' : '居中',\n\t'table.alignRight' : '右对齐',\n\t'table.alignTop' : '顶部',\n\t'table.alignMiddle' : '中部',\n\t'table.alignBottom' : '底部',\n\t'table.alignBaseline' : '基线',\n\t'table.border' : '边框',\n\t'table.borderWidth' : '边框',\n\t'table.borderColor' : '颜色',\n\t'table.backgroundColor' : '背景颜色',\n\t'map.address' : '地址: ',\n\t'map.search' : '搜索',\n\t'baidumap.address' : '地址: ',\n\t'baidumap.search' : '搜索',\n\t'baidumap.insertDynamicMap' : '插入动态地图',\n\t'anchor.name' : '锚点名称',\n\t'formatblock.formatBlock' : {\n\t\th1 : '标题 1',\n\t\th2 : '标题 2',\n\t\th3 : '标题 3',\n\t\th4 : '标题 4',\n\t\tp : '正 文'\n\t},\n\t'fontname.fontName' : {\n\t\t'SimSun' : '宋体',\n\t\t'NSimSun' : '新宋体',\n\t\t'FangSong_GB2312' : '仿宋_GB2312',\n\t\t'KaiTi_GB2312' : '楷体_GB2312',\n\t\t'SimHei' : '黑体',\n\t\t'Microsoft YaHei' : '微软雅黑',\n\t\t'Arial' : 'Arial',\n\t\t'Arial Black' : 'Arial Black',\n\t\t'Times New Roman' : 'Times New Roman',\n\t\t'Courier New' : 'Courier New',\n\t\t'Tahoma' : 'Tahoma',\n\t\t'Verdana' : 'Verdana'\n\t},\n\t'lineheight.lineHeight' : [\n\t\t{'1' : '单倍行距'},\n\t\t{'1.5' : '1.5倍行距'},\n\t\t{'2' : '2倍行距'},\n\t\t{'2.5' : '2.5倍行距'},\n\t\t{'3' : '3倍行距'}\n\t],\n\t'template.selectTemplate' : '可选模板',\n\t'template.replaceContent' : '替换当前内容',\n\t'template.fileList' : {\n\t\t'1.html' : '图片和文字',\n\t\t'2.html' : '表格',\n\t\t'3.html' : '项目编号'\n\t}\n}, 'zh-CN');\n\nKindEditor.options.langType = 'zh-CN';"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/lang/zh-TW.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.lang({\n\tsource : '原始碼',\n\tpreview : '預覽',\n\tundo : '復原(Ctrl+Z)',\n\tredo : '重複(Ctrl+Y)',\n\tcut : '剪下(Ctrl+X)',\n\tcopy : '複製(Ctrl+C)',\n\tpaste : '貼上(Ctrl+V)',\n\tplainpaste : '貼為純文字格式',\n\twordpaste : '自Word貼上',\n\tselectall : '全選(Ctrl+A)',\n\tjustifyleft : '靠左對齊',\n\tjustifycenter : '置中',\n\tjustifyright : '靠右對齊',\n\tjustifyfull : '左右對齊',\n\tinsertorderedlist : '編號清單',\n\tinsertunorderedlist : '項目清單',\n\tindent : '增加縮排',\n\toutdent : '減少縮排',\n\tsubscript : '下標',\n\tsuperscript : '上標',\n\tformatblock : '標題',\n\tfontname : '字體',\n\tfontsize : '文字大小',\n\tforecolor : '文字顏色',\n\thilitecolor : '背景顏色',\n\tbold : '粗體(Ctrl+B)',\n\titalic : '斜體(Ctrl+I)',\n\tunderline : '底線(Ctrl+U)',\n\tstrikethrough : '刪除線',\n\tremoveformat : '清除格式',\n\timage : '影像',\n\tmultiimage : '批量影像上傳',\n\tflash : 'Flash',\n\tmedia : '多媒體',\n\ttable : '表格',\n\ttablecell : '儲存格',\n\thr : '插入水平線',\n\temoticons : '插入表情',\n\tlink : '超連結',\n\tunlink : '移除超連結',\n\tfullscreen : '最大化',\n\tabout : '關於',\n\tprint : '列印(Ctrl+P)',\n\tfilemanager : '瀏覽伺服器',\n\tcode : '插入程式代碼',\n\tmap : 'Google地圖',\n\tbaidumap : 'Baidu地圖',\n\tlineheight : '行距',\n\tclearhtml : '清理HTML代碼',\n\tpagebreak : '插入分頁符號',\n\tquickformat : '快速排版',\n\tinsertfile : '插入文件',\n\ttemplate : '插入樣板',\n\tanchor : '錨點',\n\tyes : '確定',\n\tno : '取消',\n\tclose : '關閉',\n\teditImage : '影像屬性',\n\tdeleteImage : '刪除影像',\n\teditFlash : 'Flash屬性',\n\tdeleteFlash : '删除Flash',\n\teditMedia : '多媒體屬性',\n\tdeleteMedia : '删除多媒體',\n\teditLink : '超連結屬性',\n\tdeleteLink : '移除超連結',\n\teditAnchor : '锚点属性',\n\tdeleteAnchor : '删除锚点',\n\ttableprop : '表格屬性',\n\ttablecellprop : '儲存格屬性',\n\ttableinsert : '插入表格',\n\ttabledelete : '刪除表格',\n\ttablecolinsertleft : '向左插入列',\n\ttablecolinsertright : '向右插入列',\n\ttablerowinsertabove : '向上插入欄',\n\ttablerowinsertbelow : '下方插入欄',\n\ttablerowmerge : '向下合併單元格',\n\ttablecolmerge : '向右合併單元格',\n\ttablerowsplit : '分割欄',\n\ttablecolsplit : '分割列',\n\ttablecoldelete : '删除列',\n\ttablerowdelete : '删除欄',\n\tnoColor : '自動',\n\tpleaseSelectFile : '請選擇文件。',\n\tinvalidImg : \"請輸入有效的URL。\\n只允許jpg,gif,bmp,png格式。\",\n\tinvalidMedia : \"請輸入有效的URL。\\n只允許swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb格式。\",\n\tinvalidWidth : \"寬度必須是數字。\",\n\tinvalidHeight : \"高度必須是數字。\",\n\tinvalidBorder : \"邊框必須是數字。\",\n\tinvalidUrl : \"請輸入有效的URL。\",\n\tinvalidRows : '欄數是必須輸入項目，只允許輸入大於0的數字。',\n\tinvalidCols : '列數是必須輸入項目，只允許輸入大於0的數字。',\n\tinvalidPadding : '內距必須是數字。',\n\tinvalidSpacing : '間距必須是數字。',\n\tinvalidJson : '伺服器發生故障。',\n\tuploadSuccess : '上傳成功。',\n\tcutError : '您的瀏覽器安全設置不允許使用剪下操作，請使用快捷鍵(Ctrl+X)完成。',\n\tcopyError : '您的瀏覽器安全設置不允許使用剪下操作，請使用快捷鍵(Ctrl+C)完成。',\n\tpasteError : '您的瀏覽器安全設置不允許使用剪下操作，請使用快捷鍵(Ctrl+V)完成。',\n\tajaxLoading : '加載中，請稍候 ...',\n\tuploadLoading : '上傳中，請稍候 ...',\n\tuploadError : '上傳錯誤',\n\t'plainpaste.comment' : '請使用快捷鍵(Ctrl+V)把內容貼到下方區域裡。',\n\t'wordpaste.comment' : '請使用快捷鍵(Ctrl+V)把內容貼到下方區域裡。',\n\t'code.pleaseInput' : 'Please input code.',\n\t'link.url' : 'URL',\n\t'link.linkType' : '打開類型',\n\t'link.newWindow' : '新窗口',\n\t'link.selfWindow' : '本頁窗口',\n\t'flash.url' : 'URL',\n\t'flash.width' : '寬度',\n\t'flash.height' : '高度',\n\t'flash.upload' : '上傳',\n\t'flash.viewServer' : '瀏覽',\n\t'media.url' : 'URL',\n\t'media.width' : '寬度',\n\t'media.height' : '高度',\n\t'media.autostart' : '自動播放',\n\t'media.upload' : '上傳',\n\t'media.viewServer' : '瀏覽',\n\t'image.remoteImage' : '網絡影像',\n\t'image.localImage' : '上傳影像',\n\t'image.remoteUrl' : '影像URL',\n\t'image.localUrl' : '影像URL',\n\t'image.size' : '影像大小',\n\t'image.width' : '寬度',\n\t'image.height' : '高度',\n\t'image.resetSize' : '原始大小',\n\t'image.align' : '對齊方式',\n\t'image.defaultAlign' : '未設定',\n\t'image.leftAlign' : '向左對齊',\n\t'image.rightAlign' : '向右對齊',\n\t'image.imgTitle' : '影像說明',\n\t'image.upload' : '瀏覽...',\n\t'image.viewServer' : '瀏覽...',\n\t'multiimage.uploadDesc' : 'Allows users to upload <%=uploadLimit%> images, single image size not exceeding <%=sizeLimit%>',\n\t'multiimage.startUpload' : 'Start upload',\n\t'multiimage.clearAll' : 'Clear all',\n\t'multiimage.insertAll' : 'Insert all',\n\t'multiimage.queueLimitExceeded' : 'Queue limit exceeded.',\n\t'multiimage.fileExceedsSizeLimit' : 'File exceeds size limit.',\n\t'multiimage.zeroByteFile' : 'Zero byte file.',\n\t'multiimage.invalidFiletype' : 'Invalid file type.',\n\t'multiimage.unknownError' : 'Unknown upload error.',\n\t'multiimage.pending' : 'Pending ...',\n\t'multiimage.uploadError' : 'Upload error',\n\t'filemanager.emptyFolder' : '空文件夾',\n\t'filemanager.moveup' : '至上一級文件夾',\n\t'filemanager.viewType' : '顯示方式：',\n\t'filemanager.viewImage' : '縮略圖',\n\t'filemanager.listImage' : '詳細信息',\n\t'filemanager.orderType' : '排序方式：',\n\t'filemanager.fileName' : '名稱',\n\t'filemanager.fileSize' : '大小',\n\t'filemanager.fileType' : '類型',\n\t'insertfile.url' : 'URL',\n\t'insertfile.title' : '文件說明',\n\t'insertfile.upload' : '上傳',\n\t'insertfile.viewServer' : '瀏覽',\n\t'table.cells' : '儲存格數',\n\t'table.rows' : '欄數',\n\t'table.cols' : '列數',\n\t'table.size' : '表格大小',\n\t'table.width' : '寬度',\n\t'table.height' : '高度',\n\t'table.percent' : '%',\n\t'table.px' : 'px',\n\t'table.space' : '內距間距',\n\t'table.padding' : '內距',\n\t'table.spacing' : '間距',\n\t'table.align' : '對齊方式',\n\t'table.textAlign' : '水平對齊',\n\t'table.verticalAlign' : '垂直對齊',\n\t'table.alignDefault' : '未設定',\n\t'table.alignLeft' : '向左對齊',\n\t'table.alignCenter' : '置中',\n\t'table.alignRight' : '向右對齊',\n\t'table.alignTop' : '靠上',\n\t'table.alignMiddle' : '置中',\n\t'table.alignBottom' : '靠下',\n\t'table.alignBaseline' : '基線',\n\t'table.border' : '表格邊框',\n\t'table.borderWidth' : '邊框',\n\t'table.borderColor' : '顏色',\n\t'table.backgroundColor' : '背景顏色',\n\t'map.address' : '住所: ',\n\t'map.search' : '尋找',\n\t'baidumap.address' : '住所: ',\n\t'baidumap.search' : '尋找',\n\t'baidumap.insertDynamicMap' : '插入動態地圖',\n\t'anchor.name' : '錨點名稱',\n\t'formatblock.formatBlock' : {\n\t\th1 : '標題 1',\n\t\th2 : '標題 2',\n\t\th3 : '標題 3',\n\t\th4 : '標題 4',\n\t\tp : '一般'\n\t},\n\t'fontname.fontName' : {\n\t\t'MingLiU' : '細明體',\n\t\t'PMingLiU' : '新細明體',\n\t\t'DFKai-SB' : '標楷體',\n\t\t'SimSun' : '宋體',\n\t\t'NSimSun' : '新宋體',\n\t\t'FangSong' : '仿宋體',\n\t\t'Arial' : 'Arial',\n\t\t'Arial Black' : 'Arial Black',\n\t\t'Times New Roman' : 'Times New Roman',\n\t\t'Courier New' : 'Courier New',\n\t\t'Tahoma' : 'Tahoma',\n\t\t'Verdana' : 'Verdana'\n\t},\n\t'lineheight.lineHeight' : [\n\t\t{'1' : '单倍行距'},\n\t\t{'1.5' : '1.5倍行距'},\n\t\t{'2' : '2倍行距'},\n\t\t{'2.5' : '2.5倍行距'},\n\t\t{'3' : '3倍行距'}\n\t],\n\t'template.selectTemplate' : '可選樣板',\n\t'template.replaceContent' : '取代當前內容',\n\t'template.fileList' : {\n\t\t'1.html' : '影像和文字',\n\t\t'2.html' : '表格',\n\t\t'3.html' : '项目清單'\n\t}\n}, 'zh-TW');\n\nKindEditor.each(KindEditor.options.items, function(i, name) {\n\tif (name == 'baidumap') {\n\t\tKindEditor.options.items[i] = 'map';\n\t}\n});\nKindEditor.options.langType = 'zh-TW';"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/anchor/anchor.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('anchor', function(K) {\n\tvar self = this, name = 'anchor', lang = self.lang(name + '.');\n\tself.plugin.anchor = {\n\t\tedit : function() {\n\t\t\tvar html = ['<div style=\"padding:20px;\">',\n\t\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t\t'<label for=\"keName\">' + lang.name + '</label>',\n\t\t\t\t\t'<input class=\"ke-input-text\" type=\"text\" id=\"keName\" name=\"name\" value=\"\" style=\"width:100px;\" />',\n\t\t\t\t\t'</div>',\n\t\t\t\t\t'</div>'].join('');\n\t\t\tvar dialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 300,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tself.insertHtml('<a name=\"' + nameBox.val() + '\">').hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tvar div = dialog.div,\n\t\t\t\tnameBox = K('input[name=\"name\"]', div);\n\t\t\tvar img = self.plugin.getSelectedAnchor();\n\t\t\tif (img) {\n\t\t\t\tnameBox.val(unescape(img.attr('data-ke-name')));\n\t\t\t}\n\t\t\tnameBox[0].focus();\n\t\t\tnameBox[0].select();\n\t\t},\n\t\t'delete' : function() {\n\t\t\tself.plugin.getSelectedAnchor().remove();\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.anchor.edit);\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/autoheight/autoheight.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('autoheight', function(K) {\n\tvar self = this;\n\n\tif (!self.autoHeightMode) {\n\t\treturn;\n\t}\n\n\tvar minHeight;\n\n\tfunction hideScroll() {\n\t\tvar edit = self.edit;\n\t\tvar body = edit.doc.body;\n\t\tedit.iframe[0].scroll = 'no';\n\t\tbody.style.overflowY = 'hidden';\n\t}\n\n\tfunction resetHeight() {\n\t\tif(self.fullscreenMode){\n\t\t\treturn;\n\t\t}\n\t\tvar edit = self.edit;\n\t\tvar body = edit.doc.body;\n\t\tedit.iframe.height(minHeight);\n\t\tself.resize(null, Math.max((K.IE ? body.scrollHeight : body.offsetHeight) + 76, minHeight));\n\t}\n\n\tfunction init() {\n\t\tminHeight = K.removeUnit(self.height);\n\n\t\tself.edit.afterChange(resetHeight);\n\t\tif(!self.fullscreenMode){\n\t\t\thideScroll();\n\t\t}\n\t\tresetHeight();\n\t}\n\n\tif (self.isCreated) {\n\t\tinit();\n\t} else {\n\t\tself.afterCreate(init);\n\t}\n});\n\n/*\n* 如何实现真正的自动高度？\n* 修改编辑器高度之后，再次获取body内容高度时，最小值只会是当前iframe的设置高度，这样就导致高度只增不减。\n* 所以每次获取body内容高度之前，先将iframe的高度重置为最小高度，这样就能获取body的实际高度。\n* 由此就实现了真正的自动高度\n* 测试：chrome、firefox、IE9、IE8\n* */\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/baidumap/baidumap.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\n// Baidu Maps: http://dev.baidu.com/wiki/map/index.php?title=%E9%A6%96%E9%A1%B5\n\nKindEditor.plugin('baidumap', function(K) {\n\tvar self = this, name = 'baidumap', lang = self.lang(name + '.');\n\tvar mapWidth = K.undef(self.mapWidth, 558);\n\tvar mapHeight = K.undef(self.mapHeight, 360);\n\tself.clickToolbar(name, function() {\n\t\tvar html = ['<div style=\"padding:10px 20px;\">',\n\t\t\t'<div class=\"ke-header\">',\n\t\t\t// left start\n\t\t\t'<div class=\"ke-left\">',\n\t\t\tlang.address + ' <input id=\"kindeditor_plugin_map_address\" name=\"address\" class=\"ke-input-text\" value=\"\" style=\"width:200px;\" /> ',\n\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t'<input type=\"button\" name=\"searchBtn\" class=\"ke-button-common ke-button\" value=\"' + lang.search + '\" />',\n\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t\t// right start\n\t\t\t'<div class=\"ke-right\">',\n\t\t\t'<input type=\"checkbox\" id=\"keInsertDynamicMap\" name=\"insertDynamicMap\" value=\"1\" /> <label for=\"keInsertDynamicMap\">' + lang.insertDynamicMap + '</label>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-clearfix\"></div>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-map\" style=\"width:' + mapWidth + 'px;height:' + mapHeight + 'px;\"></div>',\n\t\t\t'</div>'].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : mapWidth + 42,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tyesBtn : {\n\t\t\t\tname : self.lang('yes'),\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tvar map = win.map;\n\t\t\t\t\tvar centerObj = map.getCenter();\n\t\t\t\t\tvar center = centerObj.lng + ',' + centerObj.lat;\n\t\t\t\t\tvar zoom = map.getZoom();\n\t\t\t\t\tvar url = [checkbox[0].checked ? self.pluginsPath + 'baidumap/index.html' : 'http://api.map.baidu.com/staticimage',\n\t\t\t\t\t\t'?center=' + encodeURIComponent(center),\n\t\t\t\t\t\t'&zoom=' + encodeURIComponent(zoom),\n\t\t\t\t\t\t'&width=' + mapWidth,\n\t\t\t\t\t\t'&height=' + mapHeight,\n\t\t\t\t\t\t'&markers=' + encodeURIComponent(center),\n\t\t\t\t\t\t'&markerStyles=' + encodeURIComponent('l,A')].join('');\n\t\t\t\t\tif (checkbox[0].checked) {\n\t\t\t\t\t\tself.insertHtml('<iframe src=\"' + url + '\" frameborder=\"0\" style=\"width:' + (mapWidth + 2) + 'px;height:' + (mapHeight + 2) + 'px;\"></iframe>');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.exec('insertimage', url);\n\t\t\t\t\t}\n\t\t\t\t\tself.hideDialog().focus();\n\t\t\t\t}\n\t\t\t},\n\t\t\tbeforeRemove : function() {\n\t\t\t\tsearchBtn.remove();\n\t\t\t\tif (doc) {\n\t\t\t\t\tdoc.write('');\n\t\t\t\t}\n\t\t\t\tiframe.remove();\n\t\t\t}\n\t\t});\n\t\tvar div = dialog.div,\n\t\t\taddressBox = K('[name=\"address\"]', div),\n\t\t\tsearchBtn = K('[name=\"searchBtn\"]', div),\n\t\t\tcheckbox = K('[name=\"insertDynamicMap\"]', dialog.div),\n\t\t\twin, doc;\n\t\tvar iframe = K('<iframe class=\"ke-textarea\" frameborder=\"0\" src=\"' + self.pluginsPath + 'baidumap/map.html\" style=\"width:' + mapWidth + 'px;height:' + mapHeight + 'px;\"></iframe>');\n\t\tfunction ready() {\n\t\t\twin = iframe[0].contentWindow;\n\t\t\tdoc = K.iframeDoc(iframe);\n\t\t}\n\t\tiframe.bind('load', function() {\n\t\t\tiframe.unbind('load');\n\t\t\tif (K.IE) {\n\t\t\t\tready();\n\t\t\t} else {\n\t\t\t\tsetTimeout(ready, 0);\n\t\t\t}\n\t\t});\n\t\tK('.ke-map', div).replaceWith(iframe);\n\t\t// search map\n\t\tsearchBtn.click(function() {\n\t\t\twin.search(addressBox.val());\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/baidumap/index.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n<meta charset=\"utf-8\" />\n<meta name=\"keywords\" content=\"百度地图,百度地图API，百度地图自定义工具，百度地图所见即所得工具\" />\n<meta name=\"description\" content=\"百度地图API自定义地图，帮助用户在可视化操作下生成百度地图\" />\n<title>百度地图API自定义地图</title>\n<!--引用百度地图API-->\n<style type=\"text/css\">\n\thtml,body{margin:0;padding:0;}\n\t.iw_poi_title {color:#CC5522;font-size:14px;font-weight:bold;overflow:hidden;padding-right:13px;white-space:nowrap}\n\t.iw_poi_content {font:12px arial,sans-serif;overflow:visible;padding-top:4px;white-space:-moz-pre-wrap;word-wrap:break-word}\n</style>\n<script type=\"text/javascript\" src=\"http://api.map.baidu.com/api?key=&v=1.1&services=true\"></script>\n</head>\n\n<body onload=\"initMap();\">\n  <!--百度地图容器-->\n  <div style=\"width:697px;height:550px;border:#ccc solid 1px;\" id=\"dituContent\"></div>\n</body>\n<script type=\"text/javascript\">\n\tfunction getParam(name) {\n\t\treturn location.href.match(new RegExp('[?&]' + name + '=([^?&]+)', 'i')) ? decodeURIComponent(RegExp.$1) : '';\n\t}\n\tvar centerParam = getParam('center');\n\tvar zoomParam = getParam('zoom');\n\tvar widthParam = getParam('width');\n\tvar heightParam = getParam('height');\n\tvar markersParam = getParam('markers');\n\tvar markerStylesParam = getParam('markerStyles');\n\n\t//创建和初始化地图函数：\n\tfunction initMap(){\n\t\t// [FF]切换模式后报错\n\t\tif (!window.BMap) {\n\t\t\treturn;\n\t\t}\n\t\tvar dituContent = document.getElementById('dituContent');\n\t\tdituContent.style.width = widthParam + 'px';\n\t\tdituContent.style.height = heightParam + 'px';\n\n\t\tcreateMap();//创建地图\n\t\tsetMapEvent();//设置地图事件\n\t\taddMapControl();//向地图添加控件\n\n\t\t// 创建标注\n\t\tvar markersArr = markersParam.split(',');\n\t\tvar point = new BMap.Point(markersArr[0], markersArr[1]);\n\t\tvar marker = new BMap.Marker(point);\n\t\tmap.addOverlay(marker); // 将标注添加到地图中\n\t}\n\n\t//创建地图函数：\n\tfunction createMap(){\n\t\tvar map = new BMap.Map(\"dituContent\");//在百度地图容器中创建一个地图\n\t\tvar centerArr = centerParam.split(',');\n\t\tvar point = new BMap.Point(centerArr[0], centerArr[1]);//定义一个中心点坐标\n\t\tmap.centerAndZoom(point, zoomParam);//设定地图的中心点和坐标并将地图显示在地图容器中\n\t\twindow.map = map;//将map变量存储在全局\n\t}\n\n\t//地图事件设置函数：\n\tfunction setMapEvent(){\n\t\tmap.enableDragging();//启用地图拖拽事件，默认启用(可不写)\n\t\tmap.enableScrollWheelZoom();//启用地图滚轮放大缩小\n\t\tmap.enableDoubleClickZoom();//启用鼠标双击放大，默认启用(可不写)\n\t\tmap.enableKeyboard();//启用键盘上下左右键移动地图\n\t}\n\n\t//地图控件添加函数：\n\tfunction addMapControl(){\n\t\t//向地图中添加缩放控件\n\tvar ctrl_nav = new BMap.NavigationControl({anchor:BMAP_ANCHOR_TOP_LEFT,type:BMAP_NAVIGATION_CONTROL_LARGE});\n\tmap.addControl(ctrl_nav);\n\t\t//向地图中添加缩略图控件\n\tvar ctrl_ove = new BMap.OverviewMapControl({anchor:BMAP_ANCHOR_BOTTOM_RIGHT,isOpen:1});\n\tmap.addControl(ctrl_ove);\n\t\t//向地图中添加比例尺控件\n\tvar ctrl_sca = new BMap.ScaleControl({anchor:BMAP_ANCHOR_BOTTOM_LEFT});\n\tmap.addControl(ctrl_sca);\n\t}\n</script>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/baidumap/map.html",
    "content": "<!doctype html>\n<html>\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>Baidu Maps</title>\n\t\t<style>\n\t\t\thtml { height: 100% }\n\t\t\tbody { height: 100%; margin: 0; padding: 0; background-color: #FFF }\n\t\t</style>\n\t\t<script charset=\"utf-8\" src=\"http://api.map.baidu.com/api?v=1.3\"></script>\n\t\t<script>\n\t\t\tvar map, geocoder;\n\t\t\tfunction initialize() {\n\t\t\t\tmap = new BMap.Map('map_canvas');\n\t\t\t\tvar point = new BMap.Point(121.473704, 31.230393);\n\t\t\t\tmap.centerAndZoom(point, 11);\n\t\t\t\tmap.addControl(new BMap.NavigationControl());\n\t\t\t\tmap.enableScrollWheelZoom();\n\n\t\t\t\tvar gc = new BMap.Geocoder();\n\t\t\t\tgc.getLocation(point, function(rs){\n\t\t\t\t\tvar addComp = rs.addressComponents;\n\t\t\t\t\tvar address = [addComp.city].join('');\n\t\t\t\t\tparent.document.getElementById(\"kindeditor_plugin_map_address\").value = address;\n\t\t\t\t});\n\t\t\t}\n\t\t\tfunction search(address) {\n\t\t\t\tif (!map) return;\n\t\t\t\tvar local = new BMap.LocalSearch(map, {\n\t\t\t\t\trenderOptions: {\n\t\t\t\t\t\tmap: map,\n\t\t\t\t\t\tautoViewport: true,\n\t\t\t\t\t\tselectFirstResult: false\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tlocal.search(address);\n\t\t\t}\n\t\t</script>\n\t</head>\n\t<body onload=\"initialize();\">\n\t\t<div id=\"map_canvas\" style=\"width:100%; height:100%\"></div>\n\t</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/clearhtml/clearhtml.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('clearhtml', function(K) {\n\tvar self = this, name = 'clearhtml';\n\tself.clickToolbar(name, function() {\n\t\tself.focus();\n\t\tvar html = self.html();\n\t\thtml = html.replace(/(<script[^>]*>)([\\s\\S]*?)(<\\/script>)/ig, '');\n\t\thtml = html.replace(/(<style[^>]*>)([\\s\\S]*?)(<\\/style>)/ig, '');\n\t\thtml = K.formatHtml(html, {\n\t\t\ta : ['href', 'target'],\n\t\t\tembed : ['src', 'width', 'height', 'type', 'loop', 'autostart', 'quality', '.width', '.height', 'align', 'allowscriptaccess'],\n\t\t\timg : ['src', 'width', 'height', 'border', 'alt', 'title', '.width', '.height'],\n\t\t\ttable : ['border'],\n\t\t\t'td,th' : ['rowspan', 'colspan'],\n\t\t\t'div,hr,br,tbody,tr,p,ol,ul,li,blockquote,h1,h2,h3,h4,h5,h6' : []\n\t\t});\n\t\tself.html(html);\n\t\tself.cmd.selection(true);\n\t\tself.addBookmark();\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/code/code.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\n// google code prettify: http://google-code-prettify.googlecode.com/\n// http://google-code-prettify.googlecode.com/\n\nKindEditor.plugin('code', function(K) {\n\tvar self = this, name = 'code';\n\tself.clickToolbar(name, function() {\n\t\tvar lang = self.lang(name + '.'),\n\t\t\thtml = ['<div style=\"padding:10px 20px;\">',\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<select class=\"ke-code-type\">',\n\t\t\t\t'<option value=\"js\">JavaScript</option>',\n\t\t\t\t'<option value=\"html\">HTML</option>',\n\t\t\t\t'<option value=\"css\">CSS</option>',\n\t\t\t\t'<option value=\"php\">PHP</option>',\n\t\t\t\t'<option value=\"pl\">Perl</option>',\n\t\t\t\t'<option value=\"py\">Python</option>',\n\t\t\t\t'<option value=\"rb\">Ruby</option>',\n\t\t\t\t'<option value=\"java\">Java</option>',\n\t\t\t\t'<option value=\"vb\">ASP/VB</option>',\n\t\t\t\t'<option value=\"cpp\">C/C++</option>',\n\t\t\t\t'<option value=\"cs\">C#</option>',\n\t\t\t\t'<option value=\"xml\">XML</option>',\n\t\t\t\t'<option value=\"bsh\">Shell</option>',\n\t\t\t\t'<option value=\"\">Other</option>',\n\t\t\t\t'</select>',\n\t\t\t\t'</div>',\n\t\t\t\t'<textarea class=\"ke-textarea\" style=\"width:408px;height:260px;\"></textarea>',\n\t\t\t\t'</div>'].join(''),\n\t\t\tdialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 450,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar type = K('.ke-code-type', dialog.div).val(),\n\t\t\t\t\t\t\tcode = textarea.val(),\n\t\t\t\t\t\t\tcls = type === '' ? '' :  ' lang-' + type,\n\t\t\t\t\t\t\thtml = '<pre class=\"prettyprint' + cls + '\">\\n' + K.escape(code) + '</pre> ';\n\t\t\t\t\t\tif (K.trim(code) === '') {\n\t\t\t\t\t\t\ttextarea[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tself.insertHtml(html).hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\ttextarea = K('textarea', dialog.div);\n\t\ttextarea[0].focus();\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/code/prettify.css",
    "content": ".pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}\n\npre.prettyprint {\n\tborder: 0;\n\tborder-left: 3px solid rgb(204, 204, 204);\n\tmargin-left: 2em;\n\tpadding: 0.5em;\n\tfont-size: 110%;\n\tdisplay: block;\n\tfont-family: \"Consolas\", \"Monaco\", \"Bitstream Vera Sans Mono\", \"Courier New\", Courier, monospace;\n\tmargin: 1em 0px;\n\twhite-space: pre;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/code/prettify.js",
    "content": "var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;\n(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:\"0\"<=b&&b<=\"7\"?parseInt(a.substring(1),8):b===\"u\"||b===\"x\"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?\"\\\\x0\":\"\\\\x\")+a.toString(16);a=String.fromCharCode(a);if(a===\"\\\\\"||a===\"-\"||a===\"[\"||a===\"]\")a=\"\\\\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\S\\s]|[^\\\\]/g),a=\n[],b=[],o=f[0]===\"^\",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&\"-\"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=[\"[\"];o&&b.push(\"^\");b.push.apply(b,a);for(c=0;c<\nf.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push(\"-\"),b.push(e(i[1])));b.push(\"]\");return b.join(\"\")}function y(a){for(var f=a.source.match(/\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*]|\\\\u[\\dA-Fa-f]{4}|\\\\x[\\dA-Fa-f]{2}|\\\\\\d+|\\\\[^\\dux]|\\(\\?[!:=]|[()^]|[^()[\\\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j===\"(\"?++i:\"\\\\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j===\"(\"?(++i,d[i]===void 0&&(f[c]=\"(?:\")):\"\\\\\"===j.charAt(0)&&\n(j=+j.substring(1))&&j<=i&&(f[c]=\"\\\\\"+d[i]);for(i=c=0;c<b;++c)\"^\"===f[c]&&\"^\"!==f[c+1]&&(f[c]=\"\");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a===\"[\"?f[c]=h(j):a!==\"\\\\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return\"[\"+String.fromCharCode(a&-33,a|32)+\"]\"}));return f.join(\"\")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\\\u[\\da-f]{4}|\\\\x[\\da-f]{2}|\\\\[^UXux]/gi,\"\"))){s=!0;l=!1;break}}for(var r=\n{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(\"\"+g);n.push(\"(?:\"+y(g)+\")\")}return RegExp(n.join(\"|\"),l?\"gi\":\"g\")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if(\"BR\"===g||\"LI\"===g)h[s]=\"\\n\",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\\r\\n?/g,\"\\n\"):g.replace(/[\\t\\n\\r ]+/g,\" \"),h[s]=g,t[s<<1]=y,y+=g.length,\nt[s++<<1|1]=a)}}var e=/(?:^|\\s)nocode(?:\\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue(\"white-space\"));var p=l&&\"pre\"===l.substring(0,3);m(a);return{a:h.join(\"\").replace(/\\n$/,\"\"),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,\"pln\"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===\n\"string\")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b=\"pln\")}if((c=b.length>=5&&\"lang-\"===b.substring(0,5))&&!(o&&typeof o[1]===\"string\"))c=!1,b=\"src\";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),\nl=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=\"\"+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\\S\\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push([\"str\",/^(?:'''(?:[^'\\\\]|\\\\[\\S\\s]|''?(?=[^']))*(?:'''|$)|\"\"\"(?:[^\"\\\\]|\\\\[\\S\\s]|\"\"?(?=[^\"]))*(?:\"\"\"|$)|'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$))/,q,\"'\\\"\"]):a.multiLineStrings?m.push([\"str\",/^(?:'(?:[^'\\\\]|\\\\[\\S\\s])*(?:'|$)|\"(?:[^\"\\\\]|\\\\[\\S\\s])*(?:\"|$)|`(?:[^\\\\`]|\\\\[\\S\\s])*(?:`|$))/,\nq,\"'\\\"`\"]):m.push([\"str\",/^(?:'(?:[^\\n\\r'\\\\]|\\\\.)*(?:'|$)|\"(?:[^\\n\\r\"\\\\]|\\\\.)*(?:\"|$))/,q,\"\\\"'\"]);a.verbatimStrings&&e.push([\"str\",/^@\"(?:[^\"]|\"\")*(?:\"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push([\"com\",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,\"#\"]):m.push([\"com\",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\\b|[^\\n\\r]*)/,q,\"#\"]),e.push([\"str\",/^<(?:(?:(?:\\.\\.\\/)*|\\/?)(?:[\\w-]+(?:\\/[\\w-]+)+)?[\\w-]+\\.h|[a-z]\\w*)>/,q])):m.push([\"com\",/^#[^\\n\\r]*/,\nq,\"#\"]));a.cStyleComments&&(e.push([\"com\",/^\\/\\/[^\\n\\r]*/,q]),e.push([\"com\",/^\\/\\*[\\S\\s]*?(?:\\*\\/|$)/,q]));a.regexLiterals&&e.push([\"lang-regex\",/^(?:^^\\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|,|-=|->|\\/|\\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\\^=|\\^\\^|\\^\\^=|{|\\||\\|=|\\|\\||\\|\\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*(\\/(?=[^*/])(?:[^/[\\\\]|\\\\[\\S\\s]|\\[(?:[^\\\\\\]]|\\\\[\\S\\s])*(?:]|$))+\\/)/]);(h=a.types)&&e.push([\"typ\",h]);a=(\"\"+a.keywords).replace(/^ | $/g,\n\"\");a.length&&e.push([\"kwd\",RegExp(\"^(?:\"+a.replace(/[\\s,]+/g,\"|\")+\")\\\\b\"),q]);m.push([\"pln\",/^\\s+/,q,\" \\r\\n\\t\\xa0\"]);e.push([\"lit\",/^@[$_a-z][\\w$@]*/i,q],[\"typ\",/^(?:[@_]?[A-Z]+[a-z][\\w$@]*|\\w+_t\\b)/,q],[\"pln\",/^[$_a-z][\\w$@]*/i,q],[\"lit\",/^(?:0x[\\da-f]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+-]?\\d+)?)[a-z]*/i,q,\"0123456789\"],[\"pln\",/^\\\\[\\S\\s]?/,q],[\"pun\",/^.[^\\s\\w\"-$'./@\\\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if(\"BR\"===a.nodeName)h(a),\na.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}\nfor(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\\s)nocode(?:\\s|$)/,t=/\\r\\n?|\\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue(\"white-space\"));var p=l&&\"pre\"===l.substring(0,3);for(l=s.createElement(\"LI\");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute(\"value\",\nm);var r=s.createElement(\"OL\");r.className=\"linenums\";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className=\"L\"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode(\"\\xa0\")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn(\"cannot override language handler %s\",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\\s*</.test(m)?\"default-markup\":\"default-code\";return A[a]}function E(a){var m=\na.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\\bMSIE\\b/.test(navigator.userAgent),m=/\\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,\"\\r\"));i.nodeValue=\nj;var u=i.ownerDocument,v=u.createElement(\"SPAN\");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){\"console\"in window&&console.log(w&&w.stack?w.stack:w)}}var v=[\"break,continue,do,else,for,if,return,while\"],w=[[v,\"auto,case,char,consts,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile\"],\n\"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof\"],F=[w,\"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where\"],G=[w,\"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient\"],\nH=[G,\"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var\"],w=[w,\"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN\"],I=[v,\"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None\"],\nJ=[v,\"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END\"],v=[v,\"case,done,elif,esac,eval,fi,function,in,local,set,then,until\"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\\d*)/,N=/\\S/,O=u({keywords:[F,H,w,\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\"+\nI,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,[\"default-code\"]);k(x([],[[\"pln\",/^[^<?]+/],[\"dec\",/^<!\\w[^>]*(?:>|$)/],[\"com\",/^<\\!--[\\S\\s]*?(?:--\\>|$)/],[\"lang-\",/^<\\?([\\S\\s]+?)(?:\\?>|$)/],[\"lang-\",/^<%([\\S\\s]+?)(?:%>|$)/],[\"pun\",/^(?:<[%?]|[%?]>)/],[\"lang-\",/^<xmp\\b[^>]*>([\\S\\s]+?)<\\/xmp\\b[^>]*>/i],[\"lang-js\",/^<script\\b[^>]*>([\\S\\s]*?)(<\\/script\\b[^>]*>)/i],[\"lang-css\",/^<style\\b[^>]*>([\\S\\s]*?)(<\\/style\\b[^>]*>)/i],[\"lang-in.tag\",/^(<\\/?[a-z][^<>]*>)/i]]),\n[\"default-markup\",\"htm\",\"html\",\"mxml\",\"xhtml\",\"xml\",\"xsl\"]);k(x([[\"pln\",/^\\s+/,q,\" \\t\\r\\n\"],[\"atv\",/^(?:\"[^\"]*\"?|'[^']*'?)/,q,\"\\\"'\"]],[[\"tag\",/^^<\\/?[a-z](?:[\\w-.:]*\\w)?|\\/?>$/i],[\"atn\",/^(?!style[\\s=]|on)[a-z](?:[\\w:-]*\\w)?/i],[\"lang-uq.val\",/^=\\s*([^\\s\"'>]*(?:[^\\s\"'/>]|\\/(?=\\s)))/],[\"pun\",/^[/<->]+/],[\"lang-js\",/^on\\w+\\s*=\\s*\"([^\"]+)\"/i],[\"lang-js\",/^on\\w+\\s*=\\s*'([^']+)'/i],[\"lang-js\",/^on\\w+\\s*=\\s*([^\\s\"'>]+)/i],[\"lang-css\",/^style\\s*=\\s*\"([^\"]+)\"/i],[\"lang-css\",/^style\\s*=\\s*'([^']+)'/i],[\"lang-css\",\n/^style\\s*=\\s*([^\\s\"'>]+)/i]]),[\"in.tag\"]);k(x([],[[\"atv\",/^[\\S\\s]+/]]),[\"uq.val\"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),[\"c\",\"cc\",\"cpp\",\"cxx\",\"cyc\",\"m\"]);k(u({keywords:\"null,true,false\"}),[\"json\"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),[\"cs\"]);k(u({keywords:G,cStyleComments:!0}),[\"java\"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),[\"bsh\",\"csh\",\"sh\"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),\n[\"cv\",\"py\"]);k(u({keywords:\"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END\",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"perl\",\"pl\",\"pm\"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),[\"rb\"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),[\"js\"]);k(u({keywords:\"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes\",\nhashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),[\"coffee\"]);k(x([],[[\"str\",/^[\\S\\s]+/]]),[\"regex\"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement(\"PRE\");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf(\"prettyprint\")>=0){var k=k.match(g),f,b;if(b=\n!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&\"CODE\"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName===\"pre\"||o.tagName===\"code\"||o.tagName===\"xmp\")&&o.className&&o.className.indexOf(\"prettyprint\")>=0){b=!0;break}b||((b=(b=n.className.match(/\\blinenums\\b(?::(\\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,\n250):a&&a()}for(var e=[document.getElementsByTagName(\"pre\"),document.getElementsByTagName(\"code\"),document.getElementsByTagName(\"xmp\")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\\blang(?:uage)?-([\\w.]+)(?!\\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:\"atn\",PR_ATTRIB_VALUE:\"atv\",PR_COMMENT:\"com\",PR_DECLARATION:\"dec\",PR_KEYWORD:\"kwd\",PR_LITERAL:\"lit\",\nPR_NOCODE:\"nocode\",PR_PLAIN:\"pln\",PR_PUNCTUATION:\"pun\",PR_SOURCE:\"src\",PR_STRING:\"str\",PR_TAG:\"tag\",PR_TYPE:\"typ\"}})();\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/emoticons/emoticons.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('emoticons', function(K) {\n\tvar self = this, name = 'emoticons',\n\t\tpath = (self.emoticonsPath || self.pluginsPath + 'emoticons/images/'),\n\t\tallowPreview = self.allowPreviewEmoticons === undefined ? true : self.allowPreviewEmoticons,\n\t\tcurrentPageNum = 1;\n\tself.clickToolbar(name, function() {\n\t\tvar rows = 5, cols = 9, total = 135, startNum = 0,\n\t\t\tcells = rows * cols, pages = Math.ceil(total / cells),\n\t\t\tcolsHalf = Math.floor(cols / 2),\n\t\t\twrapperDiv = K('<div class=\"ke-plugin-emoticons\"></div>'),\n\t\t\telements = [],\n\t\t\tmenu = self.createMenu({\n\t\t\t\tname : name,\n\t\t\t\tbeforeRemove : function() {\n\t\t\t\t\tremoveEvent();\n\t\t\t\t}\n\t\t\t});\n\t\tmenu.div.append(wrapperDiv);\n\t\tvar previewDiv, previewImg;\n\t\tif (allowPreview) {\n\t\t\tpreviewDiv = K('<div class=\"ke-preview\"></div>').css('right', 0);\n\t\t\tpreviewImg = K('<img class=\"ke-preview-img\" src=\"' + path + startNum + '.gif\" />');\n\t\t\twrapperDiv.append(previewDiv);\n\t\t\tpreviewDiv.append(previewImg);\n\t\t}\n\t\tfunction bindCellEvent(cell, j, num) {\n\t\t\tif (previewDiv) {\n\t\t\t\tcell.mouseover(function() {\n\t\t\t\t\tif (j > colsHalf) {\n\t\t\t\t\t\tpreviewDiv.css('left', 0);\n\t\t\t\t\t\tpreviewDiv.css('right', '');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpreviewDiv.css('left', '');\n\t\t\t\t\t\tpreviewDiv.css('right', 0);\n\t\t\t\t\t}\n\t\t\t\t\tpreviewImg.attr('src', path + num + '.gif');\n\t\t\t\t\tK(this).addClass('ke-on');\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tcell.mouseover(function() {\n\t\t\t\t\tK(this).addClass('ke-on');\n\t\t\t\t});\n\t\t\t}\n\t\t\tcell.mouseout(function() {\n\t\t\t\tK(this).removeClass('ke-on');\n\t\t\t});\n\t\t\tcell.click(function(e) {\n\t\t\t\tself.insertHtml('<img src=\"' + path + num + '.gif\" border=\"0\" alt=\"\" />').hideMenu().focus();\n\t\t\t\te.stop();\n\t\t\t});\n\t\t}\n\t\tfunction createEmoticonsTable(pageNum, parentDiv) {\n\t\t\tvar table = document.createElement('table');\n\t\t\tparentDiv.append(table);\n\t\t\tif (previewDiv) {\n\t\t\t\tK(table).mouseover(function() {\n\t\t\t\t\tpreviewDiv.show('block');\n\t\t\t\t});\n\t\t\t\tK(table).mouseout(function() {\n\t\t\t\t\tpreviewDiv.hide();\n\t\t\t\t});\n\t\t\t\telements.push(K(table));\n\t\t\t}\n\t\t\ttable.className = 'ke-table';\n\t\t\ttable.cellPadding = 0;\n\t\t\ttable.cellSpacing = 0;\n\t\t\ttable.border = 0;\n\t\t\tvar num = (pageNum - 1) * cells + startNum;\n\t\t\tfor (var i = 0; i < rows; i++) {\n\t\t\t\tvar row = table.insertRow(i);\n\t\t\t\tfor (var j = 0; j < cols; j++) {\n\t\t\t\t\tvar cell = K(row.insertCell(j));\n\t\t\t\t\tcell.addClass('ke-cell');\n\t\t\t\t\tbindCellEvent(cell, j, num);\n\t\t\t\t\tvar span = K('<span class=\"ke-img\"></span>')\n\t\t\t\t\t\t.css('background-position', '-' + (24 * num) + 'px 0px')\n\t\t\t\t\t\t.css('background-image', 'url(' + path + 'static.gif)');\n\t\t\t\t\tcell.append(span);\n\t\t\t\t\telements.push(cell);\n\t\t\t\t\tnum++;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn table;\n\t\t}\n\t\tvar table = createEmoticonsTable(currentPageNum, wrapperDiv);\n\t\tfunction removeEvent() {\n\t\t\tK.each(elements, function() {\n\t\t\t\tthis.unbind();\n\t\t\t});\n\t\t}\n\t\tvar pageDiv;\n\t\tfunction bindPageEvent(el, pageNum) {\n\t\t\tel.click(function(e) {\n\t\t\t\tremoveEvent();\n\t\t\t\ttable.parentNode.removeChild(table);\n\t\t\t\tpageDiv.remove();\n\t\t\t\ttable = createEmoticonsTable(pageNum, wrapperDiv);\n\t\t\t\tcreatePageTable(pageNum);\n\t\t\t\tcurrentPageNum = pageNum;\n\t\t\t\te.stop();\n\t\t\t});\n\t\t}\n\t\tfunction createPageTable(currentPageNum) {\n\t\t\tpageDiv = K('<div class=\"ke-page\"></div>');\n\t\t\twrapperDiv.append(pageDiv);\n\t\t\tfor (var pageNum = 1; pageNum <= pages; pageNum++) {\n\t\t\t\tif (currentPageNum !== pageNum) {\n\t\t\t\t\tvar a = K('<a href=\"javascript:;\">[' + pageNum + ']</a>');\n\t\t\t\t\tbindPageEvent(a, pageNum);\n\t\t\t\t\tpageDiv.append(a);\n\t\t\t\t\telements.push(a);\n\t\t\t\t} else {\n\t\t\t\t\tpageDiv.append(K('@[' + pageNum + ']'));\n\t\t\t\t}\n\t\t\t\tpageDiv.append(K('@&nbsp;'));\n\t\t\t}\n\t\t}\n\t\tcreatePageTable(currentPageNum);\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/filemanager/filemanager.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('filemanager', function(K) {\n\tvar self = this, name = 'filemanager',\n\t\tfileManagerJson = K.undef(self.fileManagerJson, self.basePath + 'php/file_manager_json.php'),\n\t\timgPath = self.pluginsPath + name + '/images/',\n\t\tlang = self.lang(name + '.');\n\tfunction makeFileTitle(filename, filesize, datetime) {\n\t\treturn filename + ' (' + Math.ceil(filesize / 1024) + 'KB, ' + datetime + ')';\n\t}\n\tfunction bindTitle(el, data) {\n\t\tif (data.is_dir) {\n\t\t\tel.attr('title', data.filename);\n\t\t} else {\n\t\t\tel.attr('title', makeFileTitle(data.filename, data.filesize, data.datetime));\n\t\t}\n\t}\n\tself.plugin.filemanagerDialog = function(options) {\n\t\tvar width = K.undef(options.width, 650),\n\t\t\theight = K.undef(options.height, 510),\n\t\t\tdirName = K.undef(options.dirName, ''),\n\t\t\tviewType = K.undef(options.viewType, 'VIEW').toUpperCase(), // \"LIST\" or \"VIEW\"\n\t\t\tclickFn = options.clickFn;\n\t\tvar html = [\n\t\t\t'<div style=\"padding:10px 20px;\">',\n\t\t\t// header start\n\t\t\t'<div class=\"ke-plugin-filemanager-header\">',\n\t\t\t// left start\n\t\t\t'<div class=\"ke-left\">',\n\t\t\t'<img class=\"ke-inline-block\" name=\"moveupImg\" src=\"' + imgPath + 'go-up.gif\" width=\"16\" height=\"16\" border=\"0\" alt=\"\" /> ',\n\t\t\t'<a class=\"ke-inline-block\" name=\"moveupLink\" href=\"javascript:;\">' + lang.moveup + '</a>',\n\t\t\t'</div>',\n\t\t\t// right start\n\t\t\t'<div class=\"ke-right\">',\n\t\t\tlang.viewType + ' <select class=\"ke-inline-block\" name=\"viewType\">',\n\t\t\t'<option value=\"VIEW\">' + lang.viewImage + '</option>',\n\t\t\t'<option value=\"LIST\">' + lang.listImage + '</option>',\n\t\t\t'</select> ',\n\t\t\tlang.orderType + ' <select class=\"ke-inline-block\" name=\"orderType\">',\n\t\t\t'<option value=\"NAME\">' + lang.fileName + '</option>',\n\t\t\t'<option value=\"SIZE\">' + lang.fileSize + '</option>',\n\t\t\t'<option value=\"TYPE\">' + lang.fileType + '</option>',\n\t\t\t'</select>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-clearfix\"></div>',\n\t\t\t'</div>',\n\t\t\t// body start\n\t\t\t'<div class=\"ke-plugin-filemanager-body\"></div>',\n\t\t\t'</div>'\n\t\t].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : width,\n\t\t\theight : height,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html\n\t\t}),\n\t\tdiv = dialog.div,\n\t\tbodyDiv = K('.ke-plugin-filemanager-body', div),\n\t\tmoveupImg = K('[name=\"moveupImg\"]', div),\n\t\tmoveupLink = K('[name=\"moveupLink\"]', div),\n\t\tviewServerBtn = K('[name=\"viewServer\"]', div),\n\t\tviewTypeBox = K('[name=\"viewType\"]', div),\n\t\torderTypeBox = K('[name=\"orderType\"]', div);\n\t\tfunction reloadPage(path, order, func) {\n\t\t\tvar param = 'path=' + path + '&order=' + order + '&dir=' + dirName;\n\t\t\tdialog.showLoading(self.lang('ajaxLoading'));\n\t\t\tK.ajax(K.addParam(fileManagerJson, param + '&' + new Date().getTime()), function(data) {\n\t\t\t\tdialog.hideLoading();\n\t\t\t\tfunc(data);\n\t\t\t});\n\t\t}\n\t\tvar elList = [];\n\t\tfunction bindEvent(el, result, data, createFunc) {\n\t\t\tvar fileUrl = K.formatUrl(result.current_url + data.filename, 'absolute'),\n\t\t\t\tdirPath = encodeURIComponent(result.current_dir_path + data.filename + '/');\n\t\t\tif (data.is_dir) {\n\t\t\t\tel.click(function(e) {\n\t\t\t\t\treloadPage(dirPath, orderTypeBox.val(), createFunc);\n\t\t\t\t});\n\t\t\t} else if (data.is_photo) {\n\t\t\t\tel.click(function(e) {\n\t\t\t\t\tclickFn.call(this, fileUrl, data.filename);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tel.click(function(e) {\n\t\t\t\t\tclickFn.call(this, fileUrl, data.filename);\n\t\t\t\t});\n\t\t\t}\n\t\t\telList.push(el);\n\t\t}\n\t\tfunction createCommon(result, createFunc) {\n\t\t\t// remove events\n\t\t\tK.each(elList, function() {\n\t\t\t\tthis.unbind();\n\t\t\t});\n\t\t\tmoveupLink.unbind();\n\t\t\tviewTypeBox.unbind();\n\t\t\torderTypeBox.unbind();\n\t\t\t// add events\n\t\t\tif (result.current_dir_path) {\n\t\t\t\tmoveupLink.click(function(e) {\n\t\t\t\t\treloadPage(result.moveup_dir_path, orderTypeBox.val(), createFunc);\n\t\t\t\t});\n\t\t\t}\n\t\t\tfunction changeFunc() {\n\t\t\t\tif (viewTypeBox.val() == 'VIEW') {\n\t\t\t\t\treloadPage(result.current_dir_path, orderTypeBox.val(), createView);\n\t\t\t\t} else {\n\t\t\t\t\treloadPage(result.current_dir_path, orderTypeBox.val(), createList);\n\t\t\t\t}\n\t\t\t}\n\t\t\tviewTypeBox.change(changeFunc);\n\t\t\torderTypeBox.change(changeFunc);\n\t\t\tbodyDiv.html('');\n\t\t}\n\t\tfunction createList(result) {\n\t\t\tcreateCommon(result, createList);\n\t\t\tvar table = document.createElement('table');\n\t\t\ttable.className = 'ke-table';\n\t\t\ttable.cellPadding = 0;\n\t\t\ttable.cellSpacing = 0;\n\t\t\ttable.border = 0;\n\t\t\tbodyDiv.append(table);\n\t\t\tvar fileList = result.file_list;\n\t\t\tfor (var i = 0, len = fileList.length; i < len; i++) {\n\t\t\t\tvar data = fileList[i], row = K(table.insertRow(i));\n\t\t\t\trow.mouseover(function(e) {\n\t\t\t\t\tK(this).addClass('ke-on');\n\t\t\t\t})\n\t\t\t\t.mouseout(function(e) {\n\t\t\t\t\tK(this).removeClass('ke-on');\n\t\t\t\t});\n\t\t\t\tvar iconUrl = imgPath + (data.is_dir ? 'folder-16.gif' : 'file-16.gif'),\n\t\t\t\t\timg = K('<img src=\"' + iconUrl + '\" width=\"16\" height=\"16\" alt=\"' + data.filename + '\" align=\"absmiddle\" />'),\n\t\t\t\t\tcell0 = K(row[0].insertCell(0)).addClass('ke-cell ke-name').append(img).append(document.createTextNode(' ' + data.filename));\n\t\t\t\tif (!data.is_dir || data.has_file) {\n\t\t\t\t\trow.css('cursor', 'pointer');\n\t\t\t\t\tcell0.attr('title', data.filename);\n\t\t\t\t\tbindEvent(cell0, result, data, createList);\n\t\t\t\t} else {\n\t\t\t\t\tcell0.attr('title', lang.emptyFolder);\n\t\t\t\t}\n\t\t\t\tK(row[0].insertCell(1)).addClass('ke-cell ke-size').html(data.is_dir ? '-' : Math.ceil(data.filesize / 1024) + 'KB');\n\t\t\t\tK(row[0].insertCell(2)).addClass('ke-cell ke-datetime').html(data.datetime);\n\t\t\t}\n\t\t}\n\t\tfunction createView(result) {\n\t\t\tcreateCommon(result, createView);\n\t\t\tvar fileList = result.file_list;\n\t\t\tfor (var i = 0, len = fileList.length; i < len; i++) {\n\t\t\t\tvar data = fileList[i],\n\t\t\t\t\tdiv = K('<div class=\"ke-inline-block ke-item\"></div>');\n\t\t\t\tbodyDiv.append(div);\n\t\t\t\tvar photoDiv = K('<div class=\"ke-inline-block ke-photo\"></div>')\n\t\t\t\t\t.mouseover(function(e) {\n\t\t\t\t\t\tK(this).addClass('ke-on');\n\t\t\t\t\t})\n\t\t\t\t\t.mouseout(function(e) {\n\t\t\t\t\t\tK(this).removeClass('ke-on');\n\t\t\t\t\t});\n\t\t\t\tdiv.append(photoDiv);\n\t\t\t\tvar fileUrl = result.current_url + data.filename,\n\t\t\t\t\ticonUrl = data.is_dir ? imgPath + 'folder-64.gif' : (data.is_photo ? fileUrl : imgPath + 'file-64.gif');\n\t\t\t\tvar img = K('<img src=\"' + iconUrl + '\" width=\"80\" height=\"80\" alt=\"' + data.filename + '\" />');\n\t\t\t\tif (!data.is_dir || data.has_file) {\n\t\t\t\t\tphotoDiv.css('cursor', 'pointer');\n\t\t\t\t\tbindTitle(photoDiv, data);\n\t\t\t\t\tbindEvent(photoDiv, result, data, createView);\n\t\t\t\t} else {\n\t\t\t\t\tphotoDiv.attr('title', lang.emptyFolder);\n\t\t\t\t}\n\t\t\t\tphotoDiv.append(img);\n\t\t\t\tdiv.append('<div class=\"ke-name\" title=\"' + data.filename + '\">' + data.filename + '</div>');\n\t\t\t}\n\t\t}\n\t\tviewTypeBox.val(viewType);\n\t\treloadPage('', orderTypeBox.val(), viewType == 'VIEW' ? createView : createList);\n\t\treturn dialog;\n\t}\n\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/fixtoolbar/fixtoolbar.js",
    "content": "/**\n * Created by chenyihong on 14/12/4.\n */\n\nKindEditor.plugin('fixtoolbar', function (K) {\n    var self = this;\n    if (!self.fixToolBar) {\n        return;\n    }\n\n    function init() {\n        var toolbar = K('.ke-toolbar');\n        var originY = toolbar.pos().y;\n        K(window).bind('scroll', function () {\n            if (toolbar.css('position') == 'fixed') {\n                if(document.body.scrollTop - originY < 0){\n                    toolbar.css('position', 'static');\n                    toolbar.css('top', 'auto');\n                }\n            } else {\n                if (toolbar.pos().y - document.body.scrollTop < 0) {\n                    toolbar.css('position', 'fixed');\n                    toolbar.css('top', 0);\n                }\n            }\n        });\n    }\n\n    if (self.isCreated) {\n        init();\n    } else {\n        self.afterCreate(init);\n    }\n\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/flash/flash.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('flash', function(K) {\n\tvar self = this, name = 'flash', lang = self.lang(name + '.'),\n\t\tallowFlashUpload = K.undef(self.allowFlashUpload, true),\n\t\tallowFileManager = K.undef(self.allowFileManager, false),\n\t\tformatUploadUrl = K.undef(self.formatUploadUrl, true),\n\t\textraParams = K.undef(self.extraFileUploadParams, {}),\n\t\tfilePostName = K.undef(self.filePostName, 'imgFile'),\n\t\tuploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php');\n\tself.plugin.flash = {\n\t\tedit : function() {\n\t\t\tvar html = [\n\t\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t\t//url\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keUrl\" style=\"width:60px;\">' + lang.url + '</label>',\n\t\t\t\t'<input class=\"ke-input-text\" type=\"text\" id=\"keUrl\" name=\"url\" value=\"\" style=\"width:160px;\" /> &nbsp;',\n\t\t\t\t'<input type=\"button\" class=\"ke-upload-button\" value=\"' + lang.upload + '\" /> &nbsp;',\n\t\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" name=\"viewServer\" value=\"' + lang.viewServer + '\" />',\n\t\t\t\t'</span>',\n\t\t\t\t'</div>',\n\t\t\t\t//width\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keWidth\" style=\"width:60px;\">' + lang.width + '</label>',\n\t\t\t\t'<input type=\"text\" id=\"keWidth\" class=\"ke-input-text ke-input-number\" name=\"width\" value=\"550\" maxlength=\"4\" /> ',\n\t\t\t\t'</div>',\n\t\t\t\t//height\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keHeight\" style=\"width:60px;\">' + lang.height + '</label>',\n\t\t\t\t'<input type=\"text\" id=\"keHeight\" class=\"ke-input-text ke-input-number\" name=\"height\" value=\"400\" maxlength=\"4\" /> ',\n\t\t\t\t'</div>',\n\t\t\t\t'</div>'\n\t\t\t].join('');\n\t\t\tvar dialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 450,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar url = K.trim(urlBox.val()),\n\t\t\t\t\t\t\twidth = widthBox.val(),\n\t\t\t\t\t\t\theight = heightBox.val();\n\t\t\t\t\t\tif (url == 'http://' || K.invalidUrl(url)) {\n\t\t\t\t\t\t\talert(self.lang('invalidUrl'));\n\t\t\t\t\t\t\turlBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(width)) {\n\t\t\t\t\t\t\talert(self.lang('invalidWidth'));\n\t\t\t\t\t\t\twidthBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(height)) {\n\t\t\t\t\t\t\talert(self.lang('invalidHeight'));\n\t\t\t\t\t\t\theightBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar html = K.mediaImg(self.themesPath + 'common/blank.gif', {\n\t\t\t\t\t\t\t\tsrc : url,\n\t\t\t\t\t\t\t\ttype : K.mediaType('.swf'),\n\t\t\t\t\t\t\t\twidth : width,\n\t\t\t\t\t\t\t\theight : height,\n\t\t\t\t\t\t\t\tquality : 'high'\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\tself.insertHtml(html).hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\tdiv = dialog.div,\n\t\t\turlBox = K('[name=\"url\"]', div),\n\t\t\tviewServerBtn = K('[name=\"viewServer\"]', div),\n\t\t\twidthBox = K('[name=\"width\"]', div),\n\t\t\theightBox = K('[name=\"height\"]', div);\n\t\t\turlBox.val('http://');\n\n\t\t\tif (allowFlashUpload) {\n\t\t\t\tvar uploadbutton = K.uploadbutton({\n\t\t\t\t\tbutton : K('.ke-upload-button', div)[0],\n\t\t\t\t\tfieldName : filePostName,\n\t\t\t\t\textraParams : extraParams,\n\t\t\t\t\turl : K.addParam(uploadJson, 'dir=flash'),\n\t\t\t\t\tafterUpload : function(data) {\n\t\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\t\tif (data.error === 0) {\n\t\t\t\t\t\t\tvar url = data.url;\n\t\t\t\t\t\t\tif (formatUploadUrl) {\n\t\t\t\t\t\t\t\turl = K.formatUrl(url, 'absolute');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\turlBox.val(url);\n\t\t\t\t\t\t\tif (self.afterUpload) {\n\t\t\t\t\t\t\t\tself.afterUpload.call(self, url, data, name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\talert(self.lang('uploadSuccess'));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\talert(data.message);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tafterError : function(html) {\n\t\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\t\tself.errorDialog(html);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tuploadbutton.fileBox.change(function(e) {\n\t\t\t\t\tdialog.showLoading(self.lang('uploadLoading'));\n\t\t\t\t\tuploadbutton.submit();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tK('.ke-upload-button', div).hide();\n\t\t\t}\n\n\t\t\tif (allowFileManager) {\n\t\t\t\tviewServerBtn.click(function(e) {\n\t\t\t\t\tself.loadPlugin('filemanager', function() {\n\t\t\t\t\t\tself.plugin.filemanagerDialog({\n\t\t\t\t\t\t\tviewType : 'LIST',\n\t\t\t\t\t\t\tdirName : 'flash',\n\t\t\t\t\t\t\tclickFn : function(url, title) {\n\t\t\t\t\t\t\t\tif (self.dialogs.length > 1) {\n\t\t\t\t\t\t\t\t\tK('[name=\"url\"]', div).val(url);\n\t\t\t\t\t\t\t\t\tif (self.afterSelectFile) {\n\t\t\t\t\t\t\t\t\t\tself.afterSelectFile.call(self, url);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tself.hideDialog();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tviewServerBtn.hide();\n\t\t\t}\n\n\t\t\tvar img = self.plugin.getSelectedFlash();\n\t\t\tif (img) {\n\t\t\t\tvar attrs = K.mediaAttrs(img.attr('data-ke-tag'));\n\t\t\t\turlBox.val(attrs.src);\n\t\t\t\twidthBox.val(K.removeUnit(img.css('width')) || attrs.width || 0);\n\t\t\t\theightBox.val(K.removeUnit(img.css('height')) || attrs.height || 0);\n\t\t\t}\n\t\t\turlBox[0].focus();\n\t\t\turlBox[0].select();\n\t\t},\n\t\t'delete' : function() {\n\t\t\tself.plugin.getSelectedFlash().remove();\n\t\t\t// [IE] 删除图片后立即点击图片按钮出错\n\t\t\tself.addBookmark();\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.flash.edit);\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/image/image.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('image', function(K) {\n\tvar self = this, name = 'image',\n\t\tallowImageUpload = K.undef(self.allowImageUpload, true),\n\t\tallowImageRemote = K.undef(self.allowImageRemote, true),\n\t\tformatUploadUrl = K.undef(self.formatUploadUrl, true),\n\t\tallowFileManager = K.undef(self.allowFileManager, false),\n\t\tuploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'),\n\t\timageTabIndex = K.undef(self.imageTabIndex, 0),\n\t\timgPath = self.pluginsPath + 'image/images/',\n\t\textraParams = K.undef(self.extraFileUploadParams, {}),\n\t\tfilePostName = K.undef(self.filePostName, 'imgFile'),\n\t\tfillDescAfterUploadImage = K.undef(self.fillDescAfterUploadImage, false),\n\t\tlang = self.lang(name + '.');\n\n\tself.plugin.imageDialog = function(options) {\n\t\tvar imageUrl = options.imageUrl,\n\t\t\timageWidth = K.undef(options.imageWidth, ''),\n\t\t\timageHeight = K.undef(options.imageHeight, ''),\n\t\t\timageTitle = K.undef(options.imageTitle, ''),\n\t\t\timageAlign = K.undef(options.imageAlign, ''),\n\t\t\tshowRemote = K.undef(options.showRemote, true),\n\t\t\tshowLocal = K.undef(options.showLocal, true),\n\t\t\ttabIndex = K.undef(options.tabIndex, 0),\n\t\t\tclickFn = options.clickFn;\n\t\tvar target = 'kindeditor_upload_iframe_' + new Date().getTime();\n\t\tvar hiddenElements = [];\n\t\tfor(var k in extraParams){\n\t\t\thiddenElements.push('<input type=\"hidden\" name=\"' + k + '\" value=\"' + extraParams[k] + '\" />');\n\t\t}\n\t\tvar html = [\n\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t//tabs\n\t\t\t'<div class=\"tabs\"></div>',\n\t\t\t//remote image - start\n\t\t\t'<div class=\"tab1\" style=\"display:none;\">',\n\t\t\t//url\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label for=\"remoteUrl\" style=\"width:60px;\">' + lang.remoteUrl + '</label>',\n\t\t\t'<input type=\"text\" id=\"remoteUrl\" class=\"ke-input-text\" name=\"url\" value=\"\" style=\"width:200px;\" /> &nbsp;',\n\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" name=\"viewServer\" value=\"' + lang.viewServer + '\" />',\n\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t\t//size\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label for=\"remoteWidth\" style=\"width:60px;\">' + lang.size + '</label>',\n\t\t\tlang.width + ' <input type=\"text\" id=\"remoteWidth\" class=\"ke-input-text ke-input-number\" name=\"width\" value=\"\" maxlength=\"4\" /> ',\n\t\t\tlang.height + ' <input type=\"text\" class=\"ke-input-text ke-input-number\" name=\"height\" value=\"\" maxlength=\"4\" /> ',\n\t\t\t'<img class=\"ke-refresh-btn\" src=\"' + imgPath + 'refresh.png\" width=\"16\" height=\"16\" alt=\"\" style=\"cursor:pointer;\" title=\"' + lang.resetSize + '\" />',\n\t\t\t'</div>',\n\t\t\t//align\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label style=\"width:60px;\">' + lang.align + '</label>',\n\t\t\t'<input type=\"radio\" name=\"align\" class=\"ke-inline-block\" value=\"\" checked=\"checked\" /> <img name=\"defaultImg\" src=\"' + imgPath + 'align_top.gif\" width=\"23\" height=\"25\" alt=\"\" />',\n\t\t\t' <input type=\"radio\" name=\"align\" class=\"ke-inline-block\" value=\"left\" /> <img name=\"leftImg\" src=\"' + imgPath + 'align_left.gif\" width=\"23\" height=\"25\" alt=\"\" />',\n\t\t\t' <input type=\"radio\" name=\"align\" class=\"ke-inline-block\" value=\"right\" /> <img name=\"rightImg\" src=\"' + imgPath + 'align_right.gif\" width=\"23\" height=\"25\" alt=\"\" />',\n\t\t\t'</div>',\n\t\t\t//title\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label for=\"remoteTitle\" style=\"width:60px;\">' + lang.imgTitle + '</label>',\n\t\t\t'<input type=\"text\" id=\"remoteTitle\" class=\"ke-input-text\" name=\"title\" value=\"\" style=\"width:200px;\" />',\n\t\t\t'</div>',\n\t\t\t'</div>',\n\t\t\t//remote image - end\n\t\t\t//local upload - start\n\t\t\t'<div class=\"tab2\" style=\"display:none;\">',\n\t\t\t'<iframe name=\"' + target + '\" style=\"display:none;\"></iframe>',\n\t\t\t'<form class=\"ke-upload-area ke-form\" method=\"post\" enctype=\"multipart/form-data\" target=\"' + target + '\" action=\"' + K.addParam(uploadJson, 'dir=image') + '\">',\n\t\t\t//file\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\thiddenElements.join(''),\n\t\t\t'<label style=\"width:60px;\">' + lang.localUrl + '</label>',\n\t\t\t'<input type=\"text\" name=\"localUrl\" class=\"ke-input-text\" tabindex=\"-1\" style=\"width:200px;\" readonly=\"true\" /> &nbsp;',\n\t\t\t'<input type=\"button\" class=\"ke-upload-button\" value=\"' + lang.upload + '\" />',\n\t\t\t'</div>',\n\t\t\t'</form>',\n\t\t\t'</div>',\n\t\t\t//local upload - end\n\t\t\t'</div>'\n\t\t].join('');\n\t\tvar dialogWidth = showLocal || allowFileManager ? 450 : 400,\n\t\t\tdialogHeight = showLocal && showRemote ? 300 : 250;\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : dialogWidth,\n\t\t\theight : dialogHeight,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tyesBtn : {\n\t\t\t\tname : self.lang('yes'),\n\t\t\t\tclick : function(e) {\n\t\t\t\t\t// Bugfix: http://code.google.com/p/kindeditor/issues/detail?id=319\n\t\t\t\t\tif (dialog.isLoading) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// insert local image\n\t\t\t\t\tif (showLocal && showRemote && tabs && tabs.selectedIndex === 1 || !showRemote) {\n\t\t\t\t\t\tif (uploadbutton.fileBox.val() == '') {\n\t\t\t\t\t\t\talert(self.lang('pleaseSelectFile'));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdialog.showLoading(self.lang('uploadLoading'));\n\t\t\t\t\t\tuploadbutton.submit();\n\t\t\t\t\t\tlocalUrlBox.val('');\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\t// insert remote image\n\t\t\t\t\tvar url = K.trim(urlBox.val()),\n\t\t\t\t\t\twidth = widthBox.val(),\n\t\t\t\t\t\theight = heightBox.val(),\n\t\t\t\t\t\ttitle = titleBox.val(),\n\t\t\t\t\t\talign = '';\n\t\t\t\t\talignBox.each(function() {\n\t\t\t\t\t\tif (this.checked) {\n\t\t\t\t\t\t\talign = this.value;\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\tif (url == 'http://' || K.invalidUrl(url)) {\n\t\t\t\t\t\talert(self.lang('invalidUrl'));\n\t\t\t\t\t\turlBox[0].focus();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!/^\\d*$/.test(width)) {\n\t\t\t\t\t\talert(self.lang('invalidWidth'));\n\t\t\t\t\t\twidthBox[0].focus();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (!/^\\d*$/.test(height)) {\n\t\t\t\t\t\talert(self.lang('invalidHeight'));\n\t\t\t\t\t\theightBox[0].focus();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tclickFn.call(self, url, title, width, height, 0, align);\n\t\t\t\t}\n\t\t\t},\n\t\t\tbeforeRemove : function() {\n\t\t\t\tviewServerBtn.unbind();\n\t\t\t\twidthBox.unbind();\n\t\t\t\theightBox.unbind();\n\t\t\t\trefreshBtn.unbind();\n\t\t\t}\n\t\t}),\n\t\tdiv = dialog.div;\n\n\t\tvar urlBox = K('[name=\"url\"]', div),\n\t\t\tlocalUrlBox = K('[name=\"localUrl\"]', div),\n\t\t\tviewServerBtn = K('[name=\"viewServer\"]', div),\n\t\t\twidthBox = K('.tab1 [name=\"width\"]', div),\n\t\t\theightBox = K('.tab1 [name=\"height\"]', div),\n\t\t\trefreshBtn = K('.ke-refresh-btn', div),\n\t\t\ttitleBox = K('.tab1 [name=\"title\"]', div),\n\t\t\talignBox = K('.tab1 [name=\"align\"]', div);\n\n\t\tvar tabs;\n\t\tif (showRemote && showLocal) {\n\t\t\ttabs = K.tabs({\n\t\t\t\tsrc : K('.tabs', div),\n\t\t\t\tafterSelect : function(i) {}\n\t\t\t});\n\t\t\ttabs.add({\n\t\t\t\ttitle : lang.remoteImage,\n\t\t\t\tpanel : K('.tab1', div)\n\t\t\t});\n\t\t\ttabs.add({\n\t\t\t\ttitle : lang.localImage,\n\t\t\t\tpanel : K('.tab2', div)\n\t\t\t});\n\t\t\ttabs.select(tabIndex);\n\t\t} else if (showRemote) {\n\t\t\tK('.tab1', div).show();\n\t\t} else if (showLocal) {\n\t\t\tK('.tab2', div).show();\n\t\t}\n\n\t\tvar uploadbutton = K.uploadbutton({\n\t\t\tbutton : K('.ke-upload-button', div)[0],\n\t\t\tfieldName : filePostName,\n\t\t\tform : K('.ke-form', div),\n\t\t\ttarget : target,\n\t\t\twidth: 60,\n\t\t\tafterUpload : function(data) {\n\t\t\t\tdialog.hideLoading();\n\t\t\t\tif (data.error === 0) {\n\t\t\t\t\tvar url = data.url;\n\t\t\t\t\tif (formatUploadUrl) {\n\t\t\t\t\t\turl = K.formatUrl(url, 'absolute');\n\t\t\t\t\t}\n\t\t\t\t\tif (self.afterUpload) {\n\t\t\t\t\t\tself.afterUpload.call(self, url, data, name);\n\t\t\t\t\t}\n\t\t\t\t\tif (!fillDescAfterUploadImage) {\n\t\t\t\t\t\tclickFn.call(self, url, data.title, data.width, data.height, data.border, data.align);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tK(\".ke-dialog-row #remoteUrl\", div).val(url);\n\t\t\t\t\t\tK(\".ke-tabs-li\", div)[0].click();\n\t\t\t\t\t\tK(\".ke-refresh-btn\", div).click();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\talert(data.message);\n\t\t\t\t}\n\t\t\t},\n\t\t\tafterError : function(html) {\n\t\t\t\tdialog.hideLoading();\n\t\t\t\tself.errorDialog(html);\n\t\t\t}\n\t\t});\n\t\tuploadbutton.fileBox.change(function(e) {\n\t\t\tlocalUrlBox.val(uploadbutton.fileBox.val());\n\t\t});\n\t\tif (allowFileManager) {\n\t\t\tviewServerBtn.click(function(e) {\n\t\t\t\tself.loadPlugin('filemanager', function() {\n\t\t\t\t\tself.plugin.filemanagerDialog({\n\t\t\t\t\t\tviewType : 'VIEW',\n\t\t\t\t\t\tdirName : 'image',\n\t\t\t\t\t\tclickFn : function(url, title) {\n\t\t\t\t\t\t\tif (self.dialogs.length > 1) {\n\t\t\t\t\t\t\t\tK('[name=\"url\"]', div).val(url);\n\t\t\t\t\t\t\t\tif (self.afterSelectFile) {\n\t\t\t\t\t\t\t\t\tself.afterSelectFile.call(self, url);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tself.hideDialog();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\tviewServerBtn.hide();\n\t\t}\n\t\tvar originalWidth = 0, originalHeight = 0;\n\t\tfunction setSize(width, height) {\n\t\t\twidthBox.val(width);\n\t\t\theightBox.val(height);\n\t\t\toriginalWidth = width;\n\t\t\toriginalHeight = height;\n\t\t}\n\t\trefreshBtn.click(function(e) {\n\t\t\tvar tempImg = K('<img src=\"' + urlBox.val() + '\" />', document).css({\n\t\t\t\tposition : 'absolute',\n\t\t\t\tvisibility : 'hidden',\n\t\t\t\ttop : 0,\n\t\t\t\tleft : '-1000px'\n\t\t\t});\n\t\t\ttempImg.bind('load', function() {\n\t\t\t\tsetSize(tempImg.width(), tempImg.height());\n\t\t\t\ttempImg.remove();\n\t\t\t});\n\t\t\tK(document.body).append(tempImg);\n\t\t});\n\t\twidthBox.change(function(e) {\n\t\t\tif (originalWidth > 0) {\n\t\t\t\theightBox.val(Math.round(originalHeight / originalWidth * parseInt(this.value, 10)));\n\t\t\t}\n\t\t});\n\t\theightBox.change(function(e) {\n\t\t\tif (originalHeight > 0) {\n\t\t\t\twidthBox.val(Math.round(originalWidth / originalHeight * parseInt(this.value, 10)));\n\t\t\t}\n\t\t});\n\t\turlBox.val(options.imageUrl);\n\t\tsetSize(options.imageWidth, options.imageHeight);\n\t\ttitleBox.val(options.imageTitle);\n\t\talignBox.each(function() {\n\t\t\tif (this.value === options.imageAlign) {\n\t\t\t\tthis.checked = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\tif (showRemote && tabIndex === 0) {\n\t\t\turlBox[0].focus();\n\t\t\turlBox[0].select();\n\t\t}\n\t\treturn dialog;\n\t};\n\tself.plugin.image = {\n\t\tedit : function() {\n\t\t\tvar img = self.plugin.getSelectedImage();\n\t\t\tself.plugin.imageDialog({\n\t\t\t\timageUrl : img ? img.attr('data-ke-src') : 'http://',\n\t\t\t\timageWidth : img ? img.width() : '',\n\t\t\t\timageHeight : img ? img.height() : '',\n\t\t\t\timageTitle : img ? img.attr('title') : '',\n\t\t\t\timageAlign : img ? img.attr('align') : '',\n\t\t\t\tshowRemote : allowImageRemote,\n\t\t\t\tshowLocal : allowImageUpload,\n\t\t\t\ttabIndex: img ? 0 : imageTabIndex,\n\t\t\t\tclickFn : function(url, title, width, height, border, align) {\n\t\t\t\t\tif (img) {\n\t\t\t\t\t\timg.attr('src', url);\n\t\t\t\t\t\timg.attr('data-ke-src', url);\n\t\t\t\t\t\timg.attr('width', width);\n\t\t\t\t\t\timg.attr('height', height);\n\t\t\t\t\t\timg.attr('title', title);\n\t\t\t\t\t\timg.attr('align', align);\n\t\t\t\t\t\timg.attr('alt', title);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.exec('insertimage', url, title, width, height, border, align);\n\t\t\t\t\t}\n\t\t\t\t\t// Bugfix: [Firefox] 上传图片后，总是出现正在加载的样式，需要延迟执行hideDialog\n\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\tself.hideDialog().focus();\n\t\t\t\t\t}, 0);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\t'delete' : function() {\n\t\t\tvar target = self.plugin.getSelectedImage();\n\t\t\tif (target.parent().name == 'a') {\n\t\t\t\ttarget = target.parent();\n\t\t\t}\n\t\t\ttarget.remove();\n\t\t\t// [IE] 删除图片后立即点击图片按钮出错\n\t\t\tself.addBookmark();\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.image.edit);\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/insertfile/insertfile.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('insertfile', function(K) {\n\tvar self = this, name = 'insertfile',\n\t\tallowFileUpload = K.undef(self.allowFileUpload, true),\n\t\tallowFileManager = K.undef(self.allowFileManager, false),\n\t\tformatUploadUrl = K.undef(self.formatUploadUrl, true),\n\t\tuploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'),\n\t\textraParams = K.undef(self.extraFileUploadParams, {}),\n\t\tfilePostName = K.undef(self.filePostName, 'imgFile'),\n\t\tlang = self.lang(name + '.');\n\tself.plugin.fileDialog = function(options) {\n\t\tvar fileUrl = K.undef(options.fileUrl, 'http://'),\n\t\t\tfileTitle = K.undef(options.fileTitle, ''),\n\t\t\tclickFn = options.clickFn;\n\t\tvar html = [\n\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label for=\"keUrl\" style=\"width:60px;\">' + lang.url + '</label>',\n\t\t\t'<input type=\"text\" id=\"keUrl\" name=\"url\" class=\"ke-input-text\" style=\"width:160px;\" /> &nbsp;',\n\t\t\t'<input type=\"button\" class=\"ke-upload-button\" value=\"' + lang.upload + '\" /> &nbsp;',\n\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" name=\"viewServer\" value=\"' + lang.viewServer + '\" />',\n\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t\t//title\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t'<label for=\"keTitle\" style=\"width:60px;\">' + lang.title + '</label>',\n\t\t\t'<input type=\"text\" id=\"keTitle\" class=\"ke-input-text\" name=\"title\" value=\"\" style=\"width:160px;\" /></div>',\n\t\t\t'</div>',\n\t\t\t//form end\n\t\t\t'</form>',\n\t\t\t'</div>'\n\t\t\t].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : 450,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tyesBtn : {\n\t\t\t\tname : self.lang('yes'),\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tvar url = K.trim(urlBox.val()),\n\t\t\t\t\t\ttitle = titleBox.val();\n\t\t\t\t\tif (url == 'http://' || K.invalidUrl(url)) {\n\t\t\t\t\t\talert(self.lang('invalidUrl'));\n\t\t\t\t\t\turlBox[0].focus();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (K.trim(title) === '') {\n\t\t\t\t\t\ttitle = url;\n\t\t\t\t\t}\n\t\t\t\t\tclickFn.call(self, url, title);\n\t\t\t\t}\n\t\t\t}\n\t\t}),\n\t\tdiv = dialog.div;\n\n\t\tvar urlBox = K('[name=\"url\"]', div),\n\t\t\tviewServerBtn = K('[name=\"viewServer\"]', div),\n\t\t\ttitleBox = K('[name=\"title\"]', div);\n\n\t\tif (allowFileUpload) {\n\t\t\tvar uploadbutton = K.uploadbutton({\n\t\t\t\tbutton : K('.ke-upload-button', div)[0],\n\t\t\t\tfieldName : filePostName,\n\t\t\t\turl : K.addParam(uploadJson, 'dir=file'),\n\t\t\t\textraParams : extraParams,\n\t\t\t\tafterUpload : function(data) {\n\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\tif (data.error === 0) {\n\t\t\t\t\t\tvar url = data.url;\n\t\t\t\t\t\tif (formatUploadUrl) {\n\t\t\t\t\t\t\turl = K.formatUrl(url, 'absolute');\n\t\t\t\t\t\t}\n\t\t\t\t\t\turlBox.val(url);\n\t\t\t\t\t\tif (self.afterUpload) {\n\t\t\t\t\t\t\tself.afterUpload.call(self, url, data, name);\n\t\t\t\t\t\t}\n\t\t\t\t\t\talert(self.lang('uploadSuccess'));\n\t\t\t\t\t} else {\n\t\t\t\t\t\talert(data.message);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tafterError : function(html) {\n\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\tself.errorDialog(html);\n\t\t\t\t}\n\t\t\t});\n\t\t\tuploadbutton.fileBox.change(function(e) {\n\t\t\t\tdialog.showLoading(self.lang('uploadLoading'));\n\t\t\t\tuploadbutton.submit();\n\t\t\t});\n\t\t} else {\n\t\t\tK('.ke-upload-button', div).hide();\n\t\t}\n\t\tif (allowFileManager) {\n\t\t\tviewServerBtn.click(function(e) {\n\t\t\t\tself.loadPlugin('filemanager', function() {\n\t\t\t\t\tself.plugin.filemanagerDialog({\n\t\t\t\t\t\tviewType : 'LIST',\n\t\t\t\t\t\tdirName : 'file',\n\t\t\t\t\t\tclickFn : function(url, title) {\n\t\t\t\t\t\t\tif (self.dialogs.length > 1) {\n\t\t\t\t\t\t\t\tK('[name=\"url\"]', div).val(url);\n\t\t\t\t\t\t\t\tif (self.afterSelectFile) {\n\t\t\t\t\t\t\t\t\tself.afterSelectFile.call(self, url);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tself.hideDialog();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\tviewServerBtn.hide();\n\t\t}\n\t\turlBox.val(fileUrl);\n\t\ttitleBox.val(fileTitle);\n\t\turlBox[0].focus();\n\t\turlBox[0].select();\n\t};\n\tself.clickToolbar(name, function() {\n\t\tself.plugin.fileDialog({\n\t\t\tclickFn : function(url, title) {\n\t\t\t\tvar html = '<a class=\"ke-insertfile\" href=\"' + url + '\" data-ke-src=\"' + url + '\" target=\"_blank\">' + title + '</a>';\n\t\t\t\tself.insertHtml(html).hideDialog().focus();\n\t\t\t}\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/lineheight/lineheight.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('lineheight', function(K) {\n\tvar self = this, name = 'lineheight', lang = self.lang(name + '.');\n\tself.clickToolbar(name, function() {\n\t\tvar curVal = '', commonNode = self.cmd.commonNode({'*' : '.line-height'});\n\t\tif (commonNode) {\n\t\t\tcurVal = commonNode.css('line-height');\n\t\t}\n\t\tvar menu = self.createMenu({\n\t\t\tname : name,\n\t\t\twidth : 150\n\t\t});\n\t\tK.each(lang.lineHeight, function(i, row) {\n\t\t\tK.each(row, function(key, val) {\n\t\t\t\tmenu.addItem({\n\t\t\t\t\ttitle : val,\n\t\t\t\t\tchecked : curVal === key,\n\t\t\t\t\tclick : function() {\n\t\t\t\t\t\tself.cmd.toggle('<span style=\"line-height:' + key + ';\"></span>', {\n\t\t\t\t\t\t\tspan : '.line-height=' + key\n\t\t\t\t\t\t});\n\t\t\t\t\t\tself.updateState();\n\t\t\t\t\t\tself.addBookmark();\n\t\t\t\t\t\tself.hideMenu();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/link/link.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('link', function(K) {\n\tvar self = this, name = 'link';\n\tself.plugin.link = {\n\t\tedit : function() {\n\t\t\tvar lang = self.lang(name + '.'),\n\t\t\t\thtml = '<div style=\"padding:20px;\">' +\n\t\t\t\t\t//url\n\t\t\t\t\t'<div class=\"ke-dialog-row\">' +\n\t\t\t\t\t'<label for=\"keUrl\" style=\"width:60px;\">' + lang.url + '</label>' +\n\t\t\t\t\t'<input class=\"ke-input-text\" type=\"text\" id=\"keUrl\" name=\"url\" value=\"\" style=\"width:260px;\" /></div>' +\n\t\t\t\t\t//type\n\t\t\t\t\t'<div class=\"ke-dialog-row\"\">' +\n\t\t\t\t\t'<label for=\"keType\" style=\"width:60px;\">' + lang.linkType + '</label>' +\n\t\t\t\t\t'<select id=\"keType\" name=\"type\"></select>' +\n\t\t\t\t\t'</div>' +\n\t\t\t\t\t'</div>',\n\t\t\t\tdialog = self.createDialog({\n\t\t\t\t\tname : name,\n\t\t\t\t\twidth : 450,\n\t\t\t\t\ttitle : self.lang(name),\n\t\t\t\t\tbody : html,\n\t\t\t\t\tyesBtn : {\n\t\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\t\tvar url = K.trim(urlBox.val());\n\t\t\t\t\t\t\tif (url == 'http://' || K.invalidUrl(url)) {\n\t\t\t\t\t\t\t\talert(self.lang('invalidUrl'));\n\t\t\t\t\t\t\t\turlBox[0].focus();\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tself.exec('createlink', url, typeBox.val()).hideDialog().focus();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\tdiv = dialog.div,\n\t\t\t\turlBox = K('input[name=\"url\"]', div),\n\t\t\t\ttypeBox = K('select[name=\"type\"]', div);\n\t\t\turlBox.val('http://');\n\t\t\ttypeBox[0].options[0] = new Option(lang.newWindow, '_blank');\n\t\t\ttypeBox[0].options[1] = new Option(lang.selfWindow, '');\n\t\t\tself.cmd.selection();\n\t\t\tvar a = self.plugin.getSelectedLink();\n\t\t\tif (a) {\n\t\t\t\tself.cmd.range.selectNode(a[0]);\n\t\t\t\tself.cmd.select();\n\t\t\t\turlBox.val(a.attr('data-ke-src'));\n\t\t\t\ttypeBox.val(a.attr('target'));\n\t\t\t}\n\t\t\turlBox[0].focus();\n\t\t\turlBox[0].select();\n\t\t},\n\t\t'delete' : function() {\n\t\t\tself.exec('unlink', null);\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.link.edit);\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/map/map.html",
    "content": "<!doctype html>\n<html>\n\t<head>\n\t<meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no\" />\n\t<style>\n\t\thtml { height: 100% }\n\t\tbody { height: 100%; margin: 0; padding: 0; background-color: #FFF }\n\t\t#map_canvas { height: 100% }\n\t</style>\n\t<script src=\"http://maps.googleapis.com/maps/api/js?sensor=false&language=zh_CN\"></script>\n\t<script>\n\t\tvar map, geocoder;\n\t\tfunction initialize() {\n\t\t\tvar latlng = new google.maps.LatLng(-34.397, 150.644);\n\t\t\tvar options = {\n\t\t\t\tzoom: 11,\n\t\t\t\tcenter: latlng,\n\t\t\t\tdisableDefaultUI: true,\n\t\t\t\tpanControl: true,\n\t\t\t\tzoomControl: true,\n\t\t\t\tmapTypeControl: true,\n\t\t\t\tscaleControl: true,\n\t\t\t\tstreetViewControl: false,\n\t\t\t\toverviewMapControl: true,\n\t\t\t\tmapTypeId: google.maps.MapTypeId.ROADMAP\n\t\t\t};\n\t\t\tmap = new google.maps.Map(document.getElementById(\"map_canvas\"), options);\n\t\t\tgeocoder = new google.maps.Geocoder();\n\t\t\tgeocoder.geocode({latLng: latlng}, function(results, status) {\n\t\t\t\tif (status == google.maps.GeocoderStatus.OK) {\n\t\t\t\t\tif (results[3]) {\n\t\t\t\t\t\tparent.document.getElementById(\"kindeditor_plugin_map_address\").value = results[3].formatted_address;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tfunction search(address) {\n\t\t\tif (!map) return;\n\t\t\tgeocoder.geocode({address : address}, function(results, status) {\n\t\t\t\tif (status == google.maps.GeocoderStatus.OK) {\n\t\t\t\t\tmap.setZoom(11);\n\t\t\t\t\tmap.setCenter(results[0].geometry.location);\n\t\t\t\t\tvar marker = new google.maps.Marker({\n\t\t\t\t\t\tmap: map,\n\t\t\t\t\t\tposition: results[0].geometry.location\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\talert(\"Invalid address: \" + address);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t</script>\n\t</head>\n\t<body onload=\"initialize();\">\n\t\t<div id=\"map_canvas\" style=\"width:100%; height:100%\"></div>\n\t</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/map/map.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\n// Google Maps: http://code.google.com/apis/maps/index.html\n\nKindEditor.plugin('map', function(K) {\n\tvar self = this, name = 'map', lang = self.lang(name + '.');\n\tself.clickToolbar(name, function() {\n\t\tvar html = ['<div style=\"padding:10px 20px;\">',\n\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\tlang.address + ' <input id=\"kindeditor_plugin_map_address\" name=\"address\" class=\"ke-input-text\" value=\"\" style=\"width:200px;\" /> ',\n\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t'<input type=\"button\" name=\"searchBtn\" class=\"ke-button-common ke-button\" value=\"' + lang.search + '\" />',\n\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-map\" style=\"width:558px;height:360px;\"></div>',\n\t\t\t'</div>'].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : 600,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tyesBtn : {\n\t\t\t\tname : self.lang('yes'),\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tvar geocoder = win.geocoder,\n\t\t\t\t\t\tmap = win.map,\n\t\t\t\t\t\tcenter = map.getCenter().lat() + ',' + map.getCenter().lng(),\n\t\t\t\t\t\tzoom = map.getZoom(),\n\t\t\t\t\t\tmaptype = map.getMapTypeId(),\n\t\t\t\t\t\turl = 'http://maps.googleapis.com/maps/api/staticmap';\n\t\t\t\t\t\turl += '?center=' + encodeURIComponent(center);\n\t\t\t\t\t\turl += '&zoom=' + encodeURIComponent(zoom);\n\t\t\t\t\t\turl += '&size=558x360';\n\t\t\t\t\t\turl += '&maptype=' + encodeURIComponent(maptype);\n\t\t\t\t\t\turl += '&markers=' + encodeURIComponent(center);\n\t\t\t\t\t\turl += '&language=' + self.langType;\n\t\t\t\t\t\turl += '&sensor=false';\n\t\t\t\t\tself.exec('insertimage', url).hideDialog().focus();\n\t\t\t\t}\n\t\t\t},\n\t\t\tbeforeRemove : function() {\n\t\t\t\tsearchBtn.remove();\n\t\t\t\tif (doc) {\n\t\t\t\t\tdoc.write('');\n\t\t\t\t}\n\t\t\t\tiframe.remove();\n\t\t\t}\n\t\t});\n\t\tvar div = dialog.div,\n\t\t\taddressBox = K('[name=\"address\"]', div),\n\t\t\tsearchBtn = K('[name=\"searchBtn\"]', div),\n\t\t\twin, doc;\n\t\tvar iframeHtml = ['<!doctype html><html><head>',\n\t\t\t'<meta name=\"viewport\" content=\"initial-scale=1.0, user-scalable=no\" />',\n\t\t\t'<style>',\n\t\t\t'\thtml { height: 100% }',\n\t\t\t'\tbody { height: 100%; margin: 0; padding: 0; background-color: #FFF }',\n\t\t\t'\t#map_canvas { height: 100% }',\n\t\t\t'</style>',\n\t\t\t'<script src=\"http://maps.googleapis.com/maps/api/js?sensor=false&language=' + self.langType + '\"></script>',\n\t\t\t'<script>',\n\t\t\t'var map, geocoder;',\n\t\t\t'function initialize() {',\n\t\t\t'\tvar latlng = new google.maps.LatLng(31.230393, 121.473704);',\n\t\t\t'\tvar options = {',\n\t\t\t'\t\tzoom: 11,',\n\t\t\t'\t\tcenter: latlng,',\n\t\t\t'\t\tdisableDefaultUI: true,',\n\t\t\t'\t\tpanControl: true,',\n\t\t\t'\t\tzoomControl: true,',\n\t\t\t'\t\tmapTypeControl: true,',\n\t\t\t'\t\tscaleControl: true,',\n\t\t\t'\t\tstreetViewControl: false,',\n\t\t\t'\t\toverviewMapControl: true,',\n\t\t\t'\t\tmapTypeId: google.maps.MapTypeId.ROADMAP',\n\t\t\t'\t};',\n\t\t\t'\tmap = new google.maps.Map(document.getElementById(\"map_canvas\"), options);',\n\t\t\t'\tgeocoder = new google.maps.Geocoder();',\n\t\t\t'\tgeocoder.geocode({latLng: latlng}, function(results, status) {',\n\t\t\t'\t\tif (status == google.maps.GeocoderStatus.OK) {',\n\t\t\t'\t\t\tif (results[3]) {',\n\t\t\t'\t\t\t\tparent.document.getElementById(\"kindeditor_plugin_map_address\").value = results[3].formatted_address;',\n\t\t\t'\t\t\t}',\n\t\t\t'\t\t}',\n\t\t\t'\t});',\n\t\t\t'}',\n\t\t\t'function search(address) {',\n\t\t\t'\tif (!map) return;',\n\t\t\t'\tgeocoder.geocode({address : address}, function(results, status) {',\n\t\t\t'\t\tif (status == google.maps.GeocoderStatus.OK) {',\n\t\t\t'\t\t\tmap.setZoom(11);',\n\t\t\t'\t\t\tmap.setCenter(results[0].geometry.location);',\n\t\t\t'\t\t\tvar marker = new google.maps.Marker({',\n\t\t\t'\t\t\t\tmap: map,',\n\t\t\t'\t\t\t\tposition: results[0].geometry.location',\n\t\t\t'\t\t\t});',\n\t\t\t'\t\t} else {',\n\t\t\t'\t\t\talert(\"Invalid address: \" + address);',\n\t\t\t'\t\t}',\n\t\t\t'\t});',\n\t\t\t'}',\n\t\t\t'</script>',\n\t\t\t'</head>',\n\t\t\t'<body onload=\"initialize();\">',\n\t\t\t'<div id=\"map_canvas\" style=\"width:100%; height:100%\"></div>',\n\t\t\t'</body></html>'].join('\\n');\n\t\t// TODO：用doc.write(iframeHtml)方式加载时，在IE6上第一次加载报错，暂时使用src方式\n\t\tvar iframe = K('<iframe class=\"ke-textarea\" frameborder=\"0\" src=\"' + self.pluginsPath + 'map/map.html\" style=\"width:558px;height:360px;\"></iframe>');\n\t\tfunction ready() {\n\t\t\twin = iframe[0].contentWindow;\n\t\t\tdoc = K.iframeDoc(iframe);\n\t\t\t//doc.open();\n\t\t\t//doc.write(iframeHtml);\n\t\t\t//doc.close();\n\t\t}\n\t\tiframe.bind('load', function() {\n\t\t\tiframe.unbind('load');\n\t\t\tif (K.IE) {\n\t\t\t\tready();\n\t\t\t} else {\n\t\t\t\tsetTimeout(ready, 0);\n\t\t\t}\n\t\t});\n\t\tK('.ke-map', div).replaceWith(iframe);\n\t\t// search map\n\t\tsearchBtn.click(function() {\n\t\t\twin.search(addressBox.val());\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/media/media.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('media', function(K) {\n\tvar self = this, name = 'media', lang = self.lang(name + '.'),\n\t\tallowMediaUpload = K.undef(self.allowMediaUpload, true),\n\t\tallowFileManager = K.undef(self.allowFileManager, false),\n\t\tformatUploadUrl = K.undef(self.formatUploadUrl, true),\n\t\textraParams = K.undef(self.extraFileUploadParams, {}),\n\t\tfilePostName = K.undef(self.filePostName, 'imgFile'),\n\t\tuploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php');\n\tself.plugin.media = {\n\t\tedit : function() {\n\t\t\tvar html = [\n\t\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t\t//url\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keUrl\" style=\"width:60px;\">' + lang.url + '</label>',\n\t\t\t\t'<input class=\"ke-input-text\" type=\"text\" id=\"keUrl\" name=\"url\" value=\"\" style=\"width:160px;\" /> &nbsp;',\n\t\t\t\t'<input type=\"button\" class=\"ke-upload-button\" value=\"' + lang.upload + '\" /> &nbsp;',\n\t\t\t\t'<span class=\"ke-button-common ke-button-outer\">',\n\t\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" name=\"viewServer\" value=\"' + lang.viewServer + '\" />',\n\t\t\t\t'</span>',\n\t\t\t\t'</div>',\n\t\t\t\t//width\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keWidth\" style=\"width:60px;\">' + lang.width + '</label>',\n\t\t\t\t'<input type=\"text\" id=\"keWidth\" class=\"ke-input-text ke-input-number\" name=\"width\" value=\"550\" maxlength=\"4\" />',\n\t\t\t\t'</div>',\n\t\t\t\t//height\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keHeight\" style=\"width:60px;\">' + lang.height + '</label>',\n\t\t\t\t'<input type=\"text\" id=\"keHeight\" class=\"ke-input-text ke-input-number\" name=\"height\" value=\"400\" maxlength=\"4\" />',\n\t\t\t\t'</div>',\n\t\t\t\t//autostart\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keAutostart\">' + lang.autostart + '</label>',\n\t\t\t\t'<input type=\"checkbox\" id=\"keAutostart\" name=\"autostart\" value=\"\" /> ',\n\t\t\t\t'</div>',\n\t\t\t\t'</div>'\n\t\t\t].join('');\n\t\t\tvar dialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 450,\n\t\t\t\theight : 230,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar url = K.trim(urlBox.val()),\n\t\t\t\t\t\t\twidth = widthBox.val(),\n\t\t\t\t\t\t\theight = heightBox.val();\n\t\t\t\t\t\tif (url == 'http://' || K.invalidUrl(url)) {\n\t\t\t\t\t\t\talert(self.lang('invalidUrl'));\n\t\t\t\t\t\t\turlBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(width)) {\n\t\t\t\t\t\t\talert(self.lang('invalidWidth'));\n\t\t\t\t\t\t\twidthBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(height)) {\n\t\t\t\t\t\t\talert(self.lang('invalidHeight'));\n\t\t\t\t\t\t\theightBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar html = K.mediaImg(self.themesPath + 'common/blank.gif', {\n\t\t\t\t\t\t\t\tsrc : url,\n\t\t\t\t\t\t\t\ttype : K.mediaType(url),\n\t\t\t\t\t\t\t\twidth : width,\n\t\t\t\t\t\t\t\theight : height,\n\t\t\t\t\t\t\t\tautostart : autostartBox[0].checked ? 'true' : 'false',\n\t\t\t\t\t\t\t\tloop : 'true'\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\tself.insertHtml(html).hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\tdiv = dialog.div,\n\t\t\turlBox = K('[name=\"url\"]', div),\n\t\t\tviewServerBtn = K('[name=\"viewServer\"]', div),\n\t\t\twidthBox = K('[name=\"width\"]', div),\n\t\t\theightBox = K('[name=\"height\"]', div),\n\t\t\tautostartBox = K('[name=\"autostart\"]', div);\n\t\t\turlBox.val('http://');\n\n\t\t\tif (allowMediaUpload) {\n\t\t\t\tvar uploadbutton = K.uploadbutton({\n\t\t\t\t\tbutton : K('.ke-upload-button', div)[0],\n\t\t\t\t\tfieldName : filePostName,\n\t\t\t\t\textraParams : extraParams,\n\t\t\t\t\turl : K.addParam(uploadJson, 'dir=media'),\n\t\t\t\t\tafterUpload : function(data) {\n\t\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\t\tif (data.error === 0) {\n\t\t\t\t\t\t\tvar url = data.url;\n\t\t\t\t\t\t\tif (formatUploadUrl) {\n\t\t\t\t\t\t\t\turl = K.formatUrl(url, 'absolute');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\turlBox.val(url);\n\t\t\t\t\t\t\tif (self.afterUpload) {\n\t\t\t\t\t\t\t\tself.afterUpload.call(self, url, data, name);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\talert(self.lang('uploadSuccess'));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\talert(data.message);\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tafterError : function(html) {\n\t\t\t\t\t\tdialog.hideLoading();\n\t\t\t\t\t\tself.errorDialog(html);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tuploadbutton.fileBox.change(function(e) {\n\t\t\t\t\tdialog.showLoading(self.lang('uploadLoading'));\n\t\t\t\t\tuploadbutton.submit();\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tK('.ke-upload-button', div).hide();\n\t\t\t}\n\n\t\t\tif (allowFileManager) {\n\t\t\t\tviewServerBtn.click(function(e) {\n\t\t\t\t\tself.loadPlugin('filemanager', function() {\n\t\t\t\t\t\tself.plugin.filemanagerDialog({\n\t\t\t\t\t\t\tviewType : 'LIST',\n\t\t\t\t\t\t\tdirName : 'media',\n\t\t\t\t\t\t\tclickFn : function(url, title) {\n\t\t\t\t\t\t\t\tif (self.dialogs.length > 1) {\n\t\t\t\t\t\t\t\t\tK('[name=\"url\"]', div).val(url);\n\t\t\t\t\t\t\t\t\tif (self.afterSelectFile) {\n\t\t\t\t\t\t\t\t\t\tself.afterSelectFile.call(self, url);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tself.hideDialog();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tviewServerBtn.hide();\n\t\t\t}\n\n\t\t\tvar img = self.plugin.getSelectedMedia();\n\t\t\tif (img) {\n\t\t\t\tvar attrs = K.mediaAttrs(img.attr('data-ke-tag'));\n\t\t\t\turlBox.val(attrs.src);\n\t\t\t\twidthBox.val(K.removeUnit(img.css('width')) || attrs.width || 0);\n\t\t\t\theightBox.val(K.removeUnit(img.css('height')) || attrs.height || 0);\n\t\t\t\tautostartBox[0].checked = (attrs.autostart === 'true');\n\t\t\t}\n\t\t\turlBox[0].focus();\n\t\t\turlBox[0].select();\n\t\t},\n\t\t'delete' : function() {\n\t\t\tself.plugin.getSelectedMedia().remove();\n\t\t\t// [IE] 删除图片后立即点击图片按钮出错\n\t\t\tself.addBookmark();\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.media.edit);\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/multiimage/multiimage.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\n\n(function(K) {\n\nfunction KSWFUpload(options) {\n\tthis.init(options);\n}\nK.extend(KSWFUpload, {\n\tinit : function(options) {\n\t\tvar self = this;\n\t\toptions.afterError = options.afterError || function(str) {\n\t\t\talert(str);\n\t\t};\n\t\tself.options = options;\n\t\tself.progressbars = {};\n\t\t// template\n\t\tself.div = K(options.container).html([\n\t\t\t'<div class=\"ke-swfupload\">',\n\t\t\t'<div class=\"ke-swfupload-top\">',\n\t\t\t'<div class=\"ke-inline-block ke-swfupload-button\">',\n\t\t\t'<input type=\"button\" value=\"Browse\" />',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-inline-block ke-swfupload-desc\">' + options.uploadDesc + '</div>',\n\t\t\t'<span class=\"ke-button-common ke-button-outer ke-swfupload-startupload\">',\n\t\t\t'<input type=\"button\" class=\"ke-button-common ke-button\" value=\"' + options.startButtonValue + '\" />',\n\t\t\t'</span>',\n\t\t\t'</div>',\n\t\t\t'<div class=\"ke-swfupload-body\"></div>',\n\t\t\t'</div>'\n\t\t].join(''));\n\t\tself.bodyDiv = K('.ke-swfupload-body', self.div);\n\n\t\tfunction showError(itemDiv, msg) {\n\t\t\tK('.ke-status > div', itemDiv).hide();\n\t\t\tK('.ke-message', itemDiv).addClass('ke-error').show().html(K.escape(msg));\n\t\t}\n\n\t\tvar settings = {\n\t\t\tdebug : false,\n\t\t\tupload_url : options.uploadUrl,\n\t\t\tflash_url : options.flashUrl,\n\t\t\tfile_post_name : options.filePostName,\n\t\t\tbutton_placeholder : K('.ke-swfupload-button > input', self.div)[0],\n\t\t\tbutton_image_url: options.buttonImageUrl,\n\t\t\tbutton_width: options.buttonWidth,\n\t\t\tbutton_height: options.buttonHeight,\n\t\t\tbutton_cursor : SWFUpload.CURSOR.HAND,\n\t\t\tfile_types : options.fileTypes,\n\t\t\tfile_types_description : options.fileTypesDesc,\n\t\t\tfile_upload_limit : options.fileUploadLimit,\n\t\t\tfile_size_limit : options.fileSizeLimit,\n\t\t\tpost_params : options.postParams,\n\t\t\tfile_queued_handler : function(file) {\n\t\t\t\tfile.url = self.options.fileIconUrl;\n\t\t\t\tself.appendFile(file);\n\t\t\t},\n\t\t\tfile_queue_error_handler : function(file, errorCode, message) {\n\t\t\t\tvar errorName = '';\n\t\t\t\tswitch (errorCode) {\n\t\t\t\t\tcase SWFUpload.QUEUE_ERROR.QUEUE_LIMIT_EXCEEDED:\n\t\t\t\t\t\terrorName = options.queueLimitExceeded;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:\n\t\t\t\t\t\terrorName = options.fileExceedsSizeLimit;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:\n\t\t\t\t\t\terrorName = options.zeroByteFile;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:\n\t\t\t\t\t\terrorName = options.invalidFiletype;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tdefault:\n\t\t\t\t\t\terrorName = options.unknownError;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tK.DEBUG && alert(errorName);\n\t\t\t},\n\t\t\tupload_start_handler : function(file) {\n\t\t\t\tvar self = this;\n\t\t\t\tvar itemDiv = K('div[data-id=\"' + file.id + '\"]', self.bodyDiv);\n\t\t\t\tK('.ke-status > div', itemDiv).hide();\n\t\t\t\tK('.ke-progressbar', itemDiv).show();\n\t\t\t},\n\t\t\tupload_progress_handler : function(file, bytesLoaded, bytesTotal) {\n\t\t\t\tvar percent = Math.round(bytesLoaded * 100 / bytesTotal);\n\t\t\t\tvar progressbar = self.progressbars[file.id];\n\t\t\t\tprogressbar.bar.css('width', Math.round(percent * 80 / 100) + 'px');\n\t\t\t\tprogressbar.percent.html(percent + '%');\n\t\t\t},\n\t\t\tupload_error_handler : function(file, errorCode, message) {\n\t\t\t\tif (file && file.filestatus == SWFUpload.FILE_STATUS.ERROR) {\n\t\t\t\t\tvar itemDiv = K('div[data-id=\"' + file.id + '\"]', self.bodyDiv).eq(0);\n\t\t\t\t\tshowError(itemDiv, self.options.errorMessage);\n\t\t\t\t}\n\t\t\t},\n\t\t\tupload_success_handler : function(file, serverData) {\n\t\t\t\tvar itemDiv = K('div[data-id=\"' + file.id + '\"]', self.bodyDiv).eq(0);\n\t\t\t\tvar data = {};\n\t\t\t\ttry {\n\t\t\t\t\tdata = K.json(serverData);\n\t\t\t\t} catch (e) {\n\t\t\t\t\tself.options.afterError.call(this, '<!doctype html><html>' + serverData + '</html>');\n\t\t\t\t}\n\t\t\t\tif (data.error !== 0) {\n\t\t\t\t\tshowError(itemDiv, K.DEBUG ? data.message : self.options.errorMessage);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfile.url = data.url;\n\t\t\t\tK('.ke-img', itemDiv).attr('src', file.url).attr('data-status', file.filestatus).data('data', data);\n\t\t\t\tK('.ke-status > div', itemDiv).hide();\n\t\t\t}\n\t\t};\n\t\tself.swfu = new SWFUpload(settings);\n\n\t\tK('.ke-swfupload-startupload input', self.div).click(function() {\n\t\t\tself.swfu.startUpload();\n\t\t});\n\t},\n\tgetUrlList : function() {\n\t\tvar list = [];\n\t\tK('.ke-img', self.bodyDiv).each(function() {\n\t\t\tvar img = K(this);\n\t\t\tvar status = img.attr('data-status');\n\t\t\tif (status == SWFUpload.FILE_STATUS.COMPLETE) {\n\t\t\t\tlist.push(img.data('data'));\n\t\t\t}\n\t\t});\n\t\treturn list;\n\t},\n\tremoveFile : function(fileId) {\n\t\tvar self = this;\n\t\tself.swfu.cancelUpload(fileId);\n\t\tvar itemDiv = K('div[data-id=\"' + fileId + '\"]', self.bodyDiv);\n\t\tK('.ke-photo', itemDiv).unbind();\n\t\tK('.ke-delete', itemDiv).unbind();\n\t\titemDiv.remove();\n\t},\n\tremoveFiles : function() {\n\t\tvar self = this;\n\t\tK('.ke-item', self.bodyDiv).each(function() {\n\t\t\tself.removeFile(K(this).attr('data-id'));\n\t\t});\n\t},\n\tappendFile : function(file) {\n\t\tvar self = this;\n\t\tvar itemDiv = K('<div class=\"ke-inline-block ke-item\" data-id=\"' + file.id + '\"></div>');\n\t\tself.bodyDiv.append(itemDiv);\n\t\tvar photoDiv = K('<div class=\"ke-inline-block ke-photo\"></div>')\n\t\t\t.mouseover(function(e) {\n\t\t\t\tK(this).addClass('ke-on');\n\t\t\t})\n\t\t\t.mouseout(function(e) {\n\t\t\t\tK(this).removeClass('ke-on');\n\t\t\t});\n\t\titemDiv.append(photoDiv);\n\n\t\tvar img = K('<img src=\"' + file.url + '\" class=\"ke-img\" data-status=\"' + file.filestatus + '\" width=\"80\" height=\"80\" alt=\"' + file.name + '\" />');\n\t\tphotoDiv.append(img);\n\t\tK('<span class=\"ke-delete\"></span>').appendTo(photoDiv).click(function() {\n\t\t\tself.removeFile(file.id);\n\t\t});\n\t\tvar statusDiv = K('<div class=\"ke-status\"></div>').appendTo(photoDiv);\n\t\t// progressbar\n\t\tK(['<div class=\"ke-progressbar\">',\n\t\t\t'<div class=\"ke-progressbar-bar\"><div class=\"ke-progressbar-bar-inner\"></div></div>',\n\t\t\t'<div class=\"ke-progressbar-percent\">0%</div></div>'].join('')).hide().appendTo(statusDiv);\n\t\t// message\n\t\tK('<div class=\"ke-message\">' + self.options.pendingMessage + '</div>').appendTo(statusDiv);\n\n\t\titemDiv.append('<div class=\"ke-name\">' + file.name + '</div>');\n\n\t\tself.progressbars[file.id] = {\n\t\t\tbar : K('.ke-progressbar-bar-inner', photoDiv),\n\t\t\tpercent : K('.ke-progressbar-percent', photoDiv)\n\t\t};\n\t},\n\tremove : function() {\n\t\tthis.removeFiles();\n\t\tthis.swfu.destroy();\n\t\tthis.div.html('');\n\t}\n});\n\nK.swfupload = function(element, options) {\n\treturn new KSWFUpload(element, options);\n};\n\n})(KindEditor);\n\nKindEditor.plugin('multiimage', function(K) {\n\tvar self = this, name = 'multiimage',\n\t\tformatUploadUrl = K.undef(self.formatUploadUrl, true),\n\t\tuploadJson = K.undef(self.uploadJson, self.basePath + 'php/upload_json.php'),\n\t\timgPath = self.pluginsPath + 'multiimage/images/',\n\t\timageSizeLimit = K.undef(self.imageSizeLimit, '1MB'),\n\t\timageFileTypes = K.undef(self.imageFileTypes, '*.jpg;*.gif;*.png'),\n\t\timageUploadLimit = K.undef(self.imageUploadLimit, 20),\n\t\tfilePostName = K.undef(self.filePostName, 'imgFile'),\n\t\tlang = self.lang(name + '.');\n\n\tself.plugin.multiImageDialog = function(options) {\n\t\tvar clickFn = options.clickFn,\n\t\t\tuploadDesc = K.tmpl(lang.uploadDesc, {uploadLimit : imageUploadLimit, sizeLimit : imageSizeLimit});\n\t\tvar html = [\n\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t'<div class=\"swfupload\">',\n\t\t\t'</div>',\n\t\t\t'</div>'\n\t\t].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : 650,\n\t\t\theight : 510,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tpreviewBtn : {\n\t\t\t\tname : lang.insertAll,\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tclickFn.call(self, swfupload.getUrlList());\n\t\t\t\t}\n\t\t\t},\n\t\t\tyesBtn : {\n\t\t\t\tname : lang.clearAll,\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tswfupload.removeFiles();\n\t\t\t\t}\n\t\t\t},\n\t\t\tbeforeRemove : function() {\n\t\t\t\t// IE9 bugfix: https://github.com/kindsoft/kindeditor/issues/72\n\t\t\t\tif (!K.IE || K.V <= 8) {\n\t\t\t\t\tswfupload.remove();\n\t\t\t\t}\n\t\t\t}\n\t\t}),\n\t\tdiv = dialog.div;\n\n\t\tvar swfupload = K.swfupload({\n\t\t\tcontainer : K('.swfupload', div),\n\t\t\tbuttonImageUrl : imgPath + (self.langType == 'zh-CN' ? 'select-files-zh-CN.png' : 'select-files-en.png'),\n\t\t\tbuttonWidth : self.langType == 'zh-CN' ? 72 : 88,\n\t\t\tbuttonHeight : 23,\n\t\t\tfileIconUrl : imgPath + 'image.png',\n\t\t\tuploadDesc : uploadDesc,\n\t\t\tstartButtonValue : lang.startUpload,\n\t\t\tuploadUrl : K.addParam(uploadJson, 'dir=image'),\n\t\t\tflashUrl : imgPath + 'swfupload.swf',\n\t\t\tfilePostName : filePostName,\n\t\t\tfileTypes : '*.jpg;*.jpeg;*.gif;*.png;*.bmp',\n\t\t\tfileTypesDesc : 'Image Files',\n\t\t\tfileUploadLimit : imageUploadLimit,\n\t\t\tfileSizeLimit : imageSizeLimit,\n\t\t\tpostParams :  K.undef(self.extraFileUploadParams, {}),\n\t\t\tqueueLimitExceeded : lang.queueLimitExceeded,\n\t\t\tfileExceedsSizeLimit : lang.fileExceedsSizeLimit,\n\t\t\tzeroByteFile : lang.zeroByteFile,\n\t\t\tinvalidFiletype : lang.invalidFiletype,\n\t\t\tunknownError : lang.unknownError,\n\t\t\tpendingMessage : lang.pending,\n\t\t\terrorMessage : lang.uploadError,\n\t\t\tafterError : function(html) {\n\t\t\t\tself.errorDialog(html);\n\t\t\t}\n\t\t});\n\n\t\treturn dialog;\n\t};\n\tself.clickToolbar(name, function() {\n\t\tself.plugin.multiImageDialog({\n\t\t\tclickFn : function (urlList) {\n\t\t\t\tif (urlList.length === 0) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tK.each(urlList, function(i, data) {\n\t\t\t\t\tif (self.afterUpload) {\n\t\t\t\t\t\tself.afterUpload.call(self, data.url, data, 'multiimage');\n\t\t\t\t\t}\n\t\t\t\t\tself.exec('insertimage', data.url, data.title, data.width, data.height, data.border, data.align);\n\t\t\t\t});\n\t\t\t\t// Bugfix: [Firefox] 上传图片后，总是出现正在加载的样式，需要延迟执行hideDialog\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tself.hideDialog().focus();\n\t\t\t\t}, 0);\n\t\t\t}\n\t\t});\n\t});\n});\n\n\n/**\n * SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com\n *\n * mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/,  http://www.vinterwebb.se/\n *\n * SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilz閚 and Mammon Media and is released under the MIT License:\n * http://www.opensource.org/licenses/mit-license.php\n *\n * SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:\n * http://www.opensource.org/licenses/mit-license.php\n *\n */\n\n\n/* ******************* */\n/* Constructor & Init  */\n/* ******************* */\n\n(function() {\n\nwindow.SWFUpload = function (settings) {\n\tthis.initSWFUpload(settings);\n};\n\nSWFUpload.prototype.initSWFUpload = function (settings) {\n\ttry {\n\t\tthis.customSettings = {};\t// A container where developers can place their own settings associated with this instance.\n\t\tthis.settings = settings;\n\t\tthis.eventQueue = [];\n\t\tthis.movieName = \"KindEditor_SWFUpload_\" + SWFUpload.movieCount++;\n\t\tthis.movieElement = null;\n\n\n\t\t// Setup global control tracking\n\t\tSWFUpload.instances[this.movieName] = this;\n\n\t\t// Load the settings.  Load the Flash movie.\n\t\tthis.initSettings();\n\t\tthis.loadFlash();\n\t\tthis.displayDebugInfo();\n\t} catch (ex) {\n\t\tdelete SWFUpload.instances[this.movieName];\n\t\tthrow ex;\n\t}\n};\n\n/* *************** */\n/* Static Members  */\n/* *************** */\nSWFUpload.instances = {};\nSWFUpload.movieCount = 0;\nSWFUpload.version = \"2.2.0 2009-03-25\";\nSWFUpload.QUEUE_ERROR = {\n\tQUEUE_LIMIT_EXCEEDED\t  \t\t: -100,\n\tFILE_EXCEEDS_SIZE_LIMIT  \t\t: -110,\n\tZERO_BYTE_FILE\t\t\t  \t\t: -120,\n\tINVALID_FILETYPE\t\t  \t\t: -130\n};\nSWFUpload.UPLOAD_ERROR = {\n\tHTTP_ERROR\t\t\t\t  \t\t: -200,\n\tMISSING_UPLOAD_URL\t      \t\t: -210,\n\tIO_ERROR\t\t\t\t  \t\t: -220,\n\tSECURITY_ERROR\t\t\t  \t\t: -230,\n\tUPLOAD_LIMIT_EXCEEDED\t  \t\t: -240,\n\tUPLOAD_FAILED\t\t\t  \t\t: -250,\n\tSPECIFIED_FILE_ID_NOT_FOUND\t\t: -260,\n\tFILE_VALIDATION_FAILED\t  \t\t: -270,\n\tFILE_CANCELLED\t\t\t  \t\t: -280,\n\tUPLOAD_STOPPED\t\t\t\t\t: -290\n};\nSWFUpload.FILE_STATUS = {\n\tQUEUED\t\t : -1,\n\tIN_PROGRESS\t : -2,\n\tERROR\t\t : -3,\n\tCOMPLETE\t : -4,\n\tCANCELLED\t : -5\n};\nSWFUpload.BUTTON_ACTION = {\n\tSELECT_FILE  : -100,\n\tSELECT_FILES : -110,\n\tSTART_UPLOAD : -120\n};\nSWFUpload.CURSOR = {\n\tARROW : -1,\n\tHAND : -2\n};\nSWFUpload.WINDOW_MODE = {\n\tWINDOW : \"window\",\n\tTRANSPARENT : \"transparent\",\n\tOPAQUE : \"opaque\"\n};\n\n// Private: takes a URL, determines if it is relative and converts to an absolute URL\n// using the current site. Only processes the URL if it can, otherwise returns the URL untouched\nSWFUpload.completeURL = function(url) {\n\tif (typeof(url) !== \"string\" || url.match(/^https?:\\/\\//i) || url.match(/^\\//)) {\n\t\treturn url;\n\t}\n\n\tvar currentURL = window.location.protocol + \"//\" + window.location.hostname + (window.location.port ? \":\" + window.location.port : \"\");\n\n\tvar indexSlash = window.location.pathname.lastIndexOf(\"/\");\n\tvar path;\n\tif (indexSlash <= 0) {\n\t\tpath = \"/\";\n\t} else {\n\t\tpath = window.location.pathname.substr(0, indexSlash) + \"/\";\n\t}\n\n\treturn /*currentURL +*/ path + url;\n\n};\n\n\n/* ******************** */\n/* Instance Members  */\n/* ******************** */\n\n// Private: initSettings ensures that all the\n// settings are set, getting a default value if one was not assigned.\nSWFUpload.prototype.initSettings = function () {\n\tthis.ensureDefault = function (settingName, defaultValue) {\n\t\tthis.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];\n\t};\n\n\t// Upload backend settings\n\tthis.ensureDefault(\"upload_url\", \"\");\n\tthis.ensureDefault(\"preserve_relative_urls\", false);\n\tthis.ensureDefault(\"file_post_name\", \"Filedata\");\n\tthis.ensureDefault(\"post_params\", {});\n\tthis.ensureDefault(\"use_query_string\", false);\n\tthis.ensureDefault(\"requeue_on_error\", false);\n\tthis.ensureDefault(\"http_success\", []);\n\tthis.ensureDefault(\"assume_success_timeout\", 0);\n\n\t// File Settings\n\tthis.ensureDefault(\"file_types\", \"*.*\");\n\tthis.ensureDefault(\"file_types_description\", \"All Files\");\n\tthis.ensureDefault(\"file_size_limit\", 0);\t// Default zero means \"unlimited\"\n\tthis.ensureDefault(\"file_upload_limit\", 0);\n\tthis.ensureDefault(\"file_queue_limit\", 0);\n\n\t// Flash Settings\n\tthis.ensureDefault(\"flash_url\", \"swfupload.swf\");\n\tthis.ensureDefault(\"prevent_swf_caching\", true);\n\n\t// Button Settings\n\tthis.ensureDefault(\"button_image_url\", \"\");\n\tthis.ensureDefault(\"button_width\", 1);\n\tthis.ensureDefault(\"button_height\", 1);\n\tthis.ensureDefault(\"button_text\", \"\");\n\tthis.ensureDefault(\"button_text_style\", \"color: #000000; font-size: 16pt;\");\n\tthis.ensureDefault(\"button_text_top_padding\", 0);\n\tthis.ensureDefault(\"button_text_left_padding\", 0);\n\tthis.ensureDefault(\"button_action\", SWFUpload.BUTTON_ACTION.SELECT_FILES);\n\tthis.ensureDefault(\"button_disabled\", false);\n\tthis.ensureDefault(\"button_placeholder_id\", \"\");\n\tthis.ensureDefault(\"button_placeholder\", null);\n\tthis.ensureDefault(\"button_cursor\", SWFUpload.CURSOR.ARROW);\n\tthis.ensureDefault(\"button_window_mode\", SWFUpload.WINDOW_MODE.WINDOW);\n\n\t// Debug Settings\n\tthis.ensureDefault(\"debug\", false);\n\tthis.settings.debug_enabled = this.settings.debug;\t// Here to maintain v2 API\n\n\t// Event Handlers\n\tthis.settings.return_upload_start_handler = this.returnUploadStart;\n\tthis.ensureDefault(\"swfupload_loaded_handler\", null);\n\tthis.ensureDefault(\"file_dialog_start_handler\", null);\n\tthis.ensureDefault(\"file_queued_handler\", null);\n\tthis.ensureDefault(\"file_queue_error_handler\", null);\n\tthis.ensureDefault(\"file_dialog_complete_handler\", null);\n\n\tthis.ensureDefault(\"upload_start_handler\", null);\n\tthis.ensureDefault(\"upload_progress_handler\", null);\n\tthis.ensureDefault(\"upload_error_handler\", null);\n\tthis.ensureDefault(\"upload_success_handler\", null);\n\tthis.ensureDefault(\"upload_complete_handler\", null);\n\n\tthis.ensureDefault(\"debug_handler\", this.debugMessage);\n\n\tthis.ensureDefault(\"custom_settings\", {});\n\n\t// Other settings\n\tthis.customSettings = this.settings.custom_settings;\n\n\t// Update the flash url if needed\n\tif (!!this.settings.prevent_swf_caching) {\n\t\tthis.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf(\"?\") < 0 ? \"?\" : \"&\") + \"preventswfcaching=\" + new Date().getTime();\n\t}\n\n\tif (!this.settings.preserve_relative_urls) {\n\t\t//this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url);\t// Don't need to do this one since flash doesn't look at it\n\t\tthis.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url);\n\t\tthis.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url);\n\t}\n\n\tdelete this.ensureDefault;\n};\n\n// Private: loadFlash replaces the button_placeholder element with the flash movie.\nSWFUpload.prototype.loadFlash = function () {\n\tvar targetElement, tempParent;\n\n\t// Make sure an element with the ID we are going to use doesn't already exist\n\tif (document.getElementById(this.movieName) !== null) {\n\t\tthrow \"ID \" + this.movieName + \" is already in use. The Flash Object could not be added\";\n\t}\n\n\t// Get the element where we will be placing the flash movie\n\ttargetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder;\n\n\tif (targetElement == undefined) {\n\t\tthrow \"Could not find the placeholder element: \" + this.settings.button_placeholder_id;\n\t}\n\n\t// Append the container and load the flash\n\ttempParent = document.createElement(\"div\");\n\ttempParent.innerHTML = this.getFlashHTML();\t// Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)\n\ttargetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);\n\n\t// Fix IE Flash/Form bug\n\tif (window[this.movieName] == undefined) {\n\t\twindow[this.movieName] = this.getMovieElement();\n\t}\n\n};\n\n// Private: getFlashHTML generates the object tag needed to embed the flash in to the document\nSWFUpload.prototype.getFlashHTML = function () {\n\t// Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay\n\t// Fix bug for IE9\n\t// http://www.kindsoft.net/view.php?bbsid=7&postid=5825&pagenum=1\n\tvar classid = '';\n\tif (KindEditor.IE && KindEditor.V > 8) {\n\t\tclassid = ' classid = \"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\"';\n\t}\n\treturn ['<object id=\"', this.movieName, '\"' + classid + ' type=\"application/x-shockwave-flash\" data=\"', this.settings.flash_url, '\" width=\"', this.settings.button_width, '\" height=\"', this.settings.button_height, '\" class=\"swfupload\">',\n\t\t\t\t'<param name=\"wmode\" value=\"', this.settings.button_window_mode, '\" />',\n\t\t\t\t'<param name=\"movie\" value=\"', this.settings.flash_url, '\" />',\n\t\t\t\t'<param name=\"quality\" value=\"high\" />',\n\t\t\t\t'<param name=\"menu\" value=\"false\" />',\n\t\t\t\t'<param name=\"allowScriptAccess\" value=\"always\" />',\n\t\t\t\t'<param name=\"flashvars\" value=\"' + this.getFlashVars() + '\" />',\n\t\t\t\t'</object>'].join(\"\");\n};\n\n// Private: getFlashVars builds the parameter string that will be passed\n// to flash in the flashvars param.\nSWFUpload.prototype.getFlashVars = function () {\n\t// Build a string from the post param object\n\tvar paramString = this.buildParamString();\n\tvar httpSuccessString = this.settings.http_success.join(\",\");\n\n\t// Build the parameter string\n\treturn [\"movieName=\", encodeURIComponent(this.movieName),\n\t\t\t\"&amp;uploadURL=\", encodeURIComponent(this.settings.upload_url),\n\t\t\t\"&amp;useQueryString=\", encodeURIComponent(this.settings.use_query_string),\n\t\t\t\"&amp;requeueOnError=\", encodeURIComponent(this.settings.requeue_on_error),\n\t\t\t\"&amp;httpSuccess=\", encodeURIComponent(httpSuccessString),\n\t\t\t\"&amp;assumeSuccessTimeout=\", encodeURIComponent(this.settings.assume_success_timeout),\n\t\t\t\"&amp;params=\", encodeURIComponent(paramString),\n\t\t\t\"&amp;filePostName=\", encodeURIComponent(this.settings.file_post_name),\n\t\t\t\"&amp;fileTypes=\", encodeURIComponent(this.settings.file_types),\n\t\t\t\"&amp;fileTypesDescription=\", encodeURIComponent(this.settings.file_types_description),\n\t\t\t\"&amp;fileSizeLimit=\", encodeURIComponent(this.settings.file_size_limit),\n\t\t\t\"&amp;fileUploadLimit=\", encodeURIComponent(this.settings.file_upload_limit),\n\t\t\t\"&amp;fileQueueLimit=\", encodeURIComponent(this.settings.file_queue_limit),\n\t\t\t\"&amp;debugEnabled=\", encodeURIComponent(this.settings.debug_enabled),\n\t\t\t\"&amp;buttonImageURL=\", encodeURIComponent(this.settings.button_image_url),\n\t\t\t\"&amp;buttonWidth=\", encodeURIComponent(this.settings.button_width),\n\t\t\t\"&amp;buttonHeight=\", encodeURIComponent(this.settings.button_height),\n\t\t\t\"&amp;buttonText=\", encodeURIComponent(this.settings.button_text),\n\t\t\t\"&amp;buttonTextTopPadding=\", encodeURIComponent(this.settings.button_text_top_padding),\n\t\t\t\"&amp;buttonTextLeftPadding=\", encodeURIComponent(this.settings.button_text_left_padding),\n\t\t\t\"&amp;buttonTextStyle=\", encodeURIComponent(this.settings.button_text_style),\n\t\t\t\"&amp;buttonAction=\", encodeURIComponent(this.settings.button_action),\n\t\t\t\"&amp;buttonDisabled=\", encodeURIComponent(this.settings.button_disabled),\n\t\t\t\"&amp;buttonCursor=\", encodeURIComponent(this.settings.button_cursor)\n\t\t].join(\"\");\n};\n\n// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload\n// The element is cached after the first lookup\nSWFUpload.prototype.getMovieElement = function () {\n\tif (this.movieElement == undefined) {\n\t\tthis.movieElement = document.getElementById(this.movieName);\n\t}\n\n\tif (this.movieElement === null) {\n\t\tthrow \"Could not find Flash element\";\n\t}\n\n\treturn this.movieElement;\n};\n\n// Private: buildParamString takes the name/value pairs in the post_params setting object\n// and joins them up in to a string formatted \"name=value&amp;name=value\"\nSWFUpload.prototype.buildParamString = function () {\n\tvar postParams = this.settings.post_params;\n\tvar paramStringPairs = [];\n\n\tif (typeof(postParams) === \"object\") {\n\t\tfor (var name in postParams) {\n\t\t\tif (postParams.hasOwnProperty(name)) {\n\t\t\t\tparamStringPairs.push(encodeURIComponent(name.toString()) + \"=\" + encodeURIComponent(postParams[name].toString()));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn paramStringPairs.join(\"&amp;\");\n};\n\n// Public: Used to remove a SWFUpload instance from the page. This method strives to remove\n// all references to the SWF, and other objects so memory is properly freed.\n// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state.\n// Credits: Major improvements provided by steffen\nSWFUpload.prototype.destroy = function () {\n\ttry {\n\t\t// Make sure Flash is done before we try to remove it\n\t\tthis.cancelUpload(null, false);\n\n\n\t\t// Remove the SWFUpload DOM nodes\n\t\tvar movieElement = null;\n\t\tmovieElement = this.getMovieElement();\n\n\t\tif (movieElement && typeof(movieElement.CallFunction) === \"unknown\") { // We only want to do this in IE\n\t\t\t// Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround)\n\t\t\tfor (var i in movieElement) {\n\t\t\t\ttry {\n\t\t\t\t\tif (typeof(movieElement[i]) === \"function\") {\n\t\t\t\t\t\tmovieElement[i] = null;\n\t\t\t\t\t}\n\t\t\t\t} catch (ex1) {}\n\t\t\t}\n\n\t\t\t// Remove the Movie Element from the page\n\t\t\ttry {\n\t\t\t\tmovieElement.parentNode.removeChild(movieElement);\n\t\t\t} catch (ex) {}\n\t\t}\n\n\t\t// Remove IE form fix reference\n\t\twindow[this.movieName] = null;\n\n\t\t// Destroy other references\n\t\tSWFUpload.instances[this.movieName] = null;\n\t\tdelete SWFUpload.instances[this.movieName];\n\n\t\tthis.movieElement = null;\n\t\tthis.settings = null;\n\t\tthis.customSettings = null;\n\t\tthis.eventQueue = null;\n\t\tthis.movieName = null;\n\n\n\t\treturn true;\n\t} catch (ex2) {\n\t\treturn false;\n\t}\n};\n\n\n// Public: displayDebugInfo prints out settings and configuration\n// information about this SWFUpload instance.\n// This function (and any references to it) can be deleted when placing\n// SWFUpload in production.\nSWFUpload.prototype.displayDebugInfo = function () {\n\tthis.debug(\n\t\t[\n\t\t\t\"---SWFUpload Instance Info---\\n\",\n\t\t\t\"Version: \", SWFUpload.version, \"\\n\",\n\t\t\t\"Movie Name: \", this.movieName, \"\\n\",\n\t\t\t\"Settings:\\n\",\n\t\t\t\"\\t\", \"upload_url:               \", this.settings.upload_url, \"\\n\",\n\t\t\t\"\\t\", \"flash_url:                \", this.settings.flash_url, \"\\n\",\n\t\t\t\"\\t\", \"use_query_string:         \", this.settings.use_query_string.toString(), \"\\n\",\n\t\t\t\"\\t\", \"requeue_on_error:         \", this.settings.requeue_on_error.toString(), \"\\n\",\n\t\t\t\"\\t\", \"http_success:             \", this.settings.http_success.join(\", \"), \"\\n\",\n\t\t\t\"\\t\", \"assume_success_timeout:   \", this.settings.assume_success_timeout, \"\\n\",\n\t\t\t\"\\t\", \"file_post_name:           \", this.settings.file_post_name, \"\\n\",\n\t\t\t\"\\t\", \"post_params:              \", this.settings.post_params.toString(), \"\\n\",\n\t\t\t\"\\t\", \"file_types:               \", this.settings.file_types, \"\\n\",\n\t\t\t\"\\t\", \"file_types_description:   \", this.settings.file_types_description, \"\\n\",\n\t\t\t\"\\t\", \"file_size_limit:          \", this.settings.file_size_limit, \"\\n\",\n\t\t\t\"\\t\", \"file_upload_limit:        \", this.settings.file_upload_limit, \"\\n\",\n\t\t\t\"\\t\", \"file_queue_limit:         \", this.settings.file_queue_limit, \"\\n\",\n\t\t\t\"\\t\", \"debug:                    \", this.settings.debug.toString(), \"\\n\",\n\n\t\t\t\"\\t\", \"prevent_swf_caching:      \", this.settings.prevent_swf_caching.toString(), \"\\n\",\n\n\t\t\t\"\\t\", \"button_placeholder_id:    \", this.settings.button_placeholder_id.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_placeholder:       \", (this.settings.button_placeholder ? \"Set\" : \"Not Set\"), \"\\n\",\n\t\t\t\"\\t\", \"button_image_url:         \", this.settings.button_image_url.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_width:             \", this.settings.button_width.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_height:            \", this.settings.button_height.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_text:              \", this.settings.button_text.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_text_style:        \", this.settings.button_text_style.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_text_top_padding:  \", this.settings.button_text_top_padding.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_text_left_padding: \", this.settings.button_text_left_padding.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_action:            \", this.settings.button_action.toString(), \"\\n\",\n\t\t\t\"\\t\", \"button_disabled:          \", this.settings.button_disabled.toString(), \"\\n\",\n\n\t\t\t\"\\t\", \"custom_settings:          \", this.settings.custom_settings.toString(), \"\\n\",\n\t\t\t\"Event Handlers:\\n\",\n\t\t\t\"\\t\", \"swfupload_loaded_handler assigned:  \", (typeof this.settings.swfupload_loaded_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"file_dialog_start_handler assigned: \", (typeof this.settings.file_dialog_start_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"file_queued_handler assigned:       \", (typeof this.settings.file_queued_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"file_queue_error_handler assigned:  \", (typeof this.settings.file_queue_error_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"upload_start_handler assigned:      \", (typeof this.settings.upload_start_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"upload_progress_handler assigned:   \", (typeof this.settings.upload_progress_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"upload_error_handler assigned:      \", (typeof this.settings.upload_error_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"upload_success_handler assigned:    \", (typeof this.settings.upload_success_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"upload_complete_handler assigned:   \", (typeof this.settings.upload_complete_handler === \"function\").toString(), \"\\n\",\n\t\t\t\"\\t\", \"debug_handler assigned:             \", (typeof this.settings.debug_handler === \"function\").toString(), \"\\n\"\n\t\t].join(\"\")\n\t);\n};\n\n/* Note: addSetting and getSetting are no longer used by SWFUpload but are included\n\tthe maintain v2 API compatibility\n*/\n// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.\nSWFUpload.prototype.addSetting = function (name, value, default_value) {\n    if (value == undefined) {\n        return (this.settings[name] = default_value);\n    } else {\n        return (this.settings[name] = value);\n\t}\n};\n\n// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.\nSWFUpload.prototype.getSetting = function (name) {\n    if (this.settings[name] != undefined) {\n        return this.settings[name];\n\t}\n\n    return \"\";\n};\n\n\n\n// Private: callFlash handles function calls made to the Flash element.\n// Calls are made with a setTimeout for some functions to work around\n// bugs in the ExternalInterface library.\nSWFUpload.prototype.callFlash = function (functionName, argumentArray) {\n\targumentArray = argumentArray || [];\n\n\tvar movieElement = this.getMovieElement();\n\tvar returnValue, returnString;\n\n\t// Flash's method if calling ExternalInterface methods (code adapted from MooTools).\n\ttry {\n\t\treturnString = movieElement.CallFunction('<invoke name=\"' + functionName + '\" returntype=\"javascript\">' + __flash__argumentsToXML(argumentArray, 0) + '</invoke>');\n\t\treturnValue = eval(returnString);\n\t} catch (ex) {\n\t\tthrow \"Call to \" + functionName + \" failed\";\n\t}\n\n\t// Unescape file post param values\n\tif (returnValue != undefined && typeof returnValue.post === \"object\") {\n\t\treturnValue = this.unescapeFilePostParams(returnValue);\n\t}\n\n\treturn returnValue;\n};\n\n/* *****************************\n\t-- Flash control methods --\n\tYour UI should use these\n\tto operate SWFUpload\n   ***************************** */\n\n// WARNING: this function does not work in Flash Player 10\n// Public: selectFile causes a File Selection Dialog window to appear.  This\n// dialog only allows 1 file to be selected.\nSWFUpload.prototype.selectFile = function () {\n\tthis.callFlash(\"SelectFile\");\n};\n\n// WARNING: this function does not work in Flash Player 10\n// Public: selectFiles causes a File Selection Dialog window to appear/ This\n// dialog allows the user to select any number of files\n// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.\n// If the selection name length is too long the dialog will fail in an unpredictable manner.  There is no work-around\n// for this bug.\nSWFUpload.prototype.selectFiles = function () {\n\tthis.callFlash(\"SelectFiles\");\n};\n\n\n// Public: startUpload starts uploading the first file in the queue unless\n// the optional parameter 'fileID' specifies the ID\nSWFUpload.prototype.startUpload = function (fileID) {\n\tthis.callFlash(\"StartUpload\", [fileID]);\n};\n\n// Public: cancelUpload cancels any queued file.  The fileID parameter may be the file ID or index.\n// If you do not specify a fileID the current uploading file or first file in the queue is cancelled.\n// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter.\nSWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) {\n\tif (triggerErrorEvent !== false) {\n\t\ttriggerErrorEvent = true;\n\t}\n\tthis.callFlash(\"CancelUpload\", [fileID, triggerErrorEvent]);\n};\n\n// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.\n// If nothing is currently uploading then nothing happens.\nSWFUpload.prototype.stopUpload = function () {\n\tthis.callFlash(\"StopUpload\");\n};\n\n/* ************************\n * Settings methods\n *   These methods change the SWFUpload settings.\n *   SWFUpload settings should not be changed directly on the settings object\n *   since many of the settings need to be passed to Flash in order to take\n *   effect.\n * *********************** */\n\n// Public: getStats gets the file statistics object.\nSWFUpload.prototype.getStats = function () {\n\treturn this.callFlash(\"GetStats\");\n};\n\n// Public: setStats changes the SWFUpload statistics.  You shouldn't need to\n// change the statistics but you can.  Changing the statistics does not\n// affect SWFUpload accept for the successful_uploads count which is used\n// by the upload_limit setting to determine how many files the user may upload.\nSWFUpload.prototype.setStats = function (statsObject) {\n\tthis.callFlash(\"SetStats\", [statsObject]);\n};\n\n// Public: getFile retrieves a File object by ID or Index.  If the file is\n// not found then 'null' is returned.\nSWFUpload.prototype.getFile = function (fileID) {\n\tif (typeof(fileID) === \"number\") {\n\t\treturn this.callFlash(\"GetFileByIndex\", [fileID]);\n\t} else {\n\t\treturn this.callFlash(\"GetFile\", [fileID]);\n\t}\n};\n\n// Public: addFileParam sets a name/value pair that will be posted with the\n// file specified by the Files ID.  If the name already exists then the\n// exiting value will be overwritten.\nSWFUpload.prototype.addFileParam = function (fileID, name, value) {\n\treturn this.callFlash(\"AddFileParam\", [fileID, name, value]);\n};\n\n// Public: removeFileParam removes a previously set (by addFileParam) name/value\n// pair from the specified file.\nSWFUpload.prototype.removeFileParam = function (fileID, name) {\n\tthis.callFlash(\"RemoveFileParam\", [fileID, name]);\n};\n\n// Public: setUploadUrl changes the upload_url setting.\nSWFUpload.prototype.setUploadURL = function (url) {\n\tthis.settings.upload_url = url.toString();\n\tthis.callFlash(\"SetUploadURL\", [url]);\n};\n\n// Public: setPostParams changes the post_params setting\nSWFUpload.prototype.setPostParams = function (paramsObject) {\n\tthis.settings.post_params = paramsObject;\n\tthis.callFlash(\"SetPostParams\", [paramsObject]);\n};\n\n// Public: addPostParam adds post name/value pair.  Each name can have only one value.\nSWFUpload.prototype.addPostParam = function (name, value) {\n\tthis.settings.post_params[name] = value;\n\tthis.callFlash(\"SetPostParams\", [this.settings.post_params]);\n};\n\n// Public: removePostParam deletes post name/value pair.\nSWFUpload.prototype.removePostParam = function (name) {\n\tdelete this.settings.post_params[name];\n\tthis.callFlash(\"SetPostParams\", [this.settings.post_params]);\n};\n\n// Public: setFileTypes changes the file_types setting and the file_types_description setting\nSWFUpload.prototype.setFileTypes = function (types, description) {\n\tthis.settings.file_types = types;\n\tthis.settings.file_types_description = description;\n\tthis.callFlash(\"SetFileTypes\", [types, description]);\n};\n\n// Public: setFileSizeLimit changes the file_size_limit setting\nSWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {\n\tthis.settings.file_size_limit = fileSizeLimit;\n\tthis.callFlash(\"SetFileSizeLimit\", [fileSizeLimit]);\n};\n\n// Public: setFileUploadLimit changes the file_upload_limit setting\nSWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {\n\tthis.settings.file_upload_limit = fileUploadLimit;\n\tthis.callFlash(\"SetFileUploadLimit\", [fileUploadLimit]);\n};\n\n// Public: setFileQueueLimit changes the file_queue_limit setting\nSWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {\n\tthis.settings.file_queue_limit = fileQueueLimit;\n\tthis.callFlash(\"SetFileQueueLimit\", [fileQueueLimit]);\n};\n\n// Public: setFilePostName changes the file_post_name setting\nSWFUpload.prototype.setFilePostName = function (filePostName) {\n\tthis.settings.file_post_name = filePostName;\n\tthis.callFlash(\"SetFilePostName\", [filePostName]);\n};\n\n// Public: setUseQueryString changes the use_query_string setting\nSWFUpload.prototype.setUseQueryString = function (useQueryString) {\n\tthis.settings.use_query_string = useQueryString;\n\tthis.callFlash(\"SetUseQueryString\", [useQueryString]);\n};\n\n// Public: setRequeueOnError changes the requeue_on_error setting\nSWFUpload.prototype.setRequeueOnError = function (requeueOnError) {\n\tthis.settings.requeue_on_error = requeueOnError;\n\tthis.callFlash(\"SetRequeueOnError\", [requeueOnError]);\n};\n\n// Public: setHTTPSuccess changes the http_success setting\nSWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {\n\tif (typeof http_status_codes === \"string\") {\n\t\thttp_status_codes = http_status_codes.replace(\" \", \"\").split(\",\");\n\t}\n\n\tthis.settings.http_success = http_status_codes;\n\tthis.callFlash(\"SetHTTPSuccess\", [http_status_codes]);\n};\n\n// Public: setHTTPSuccess changes the http_success setting\nSWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) {\n\tthis.settings.assume_success_timeout = timeout_seconds;\n\tthis.callFlash(\"SetAssumeSuccessTimeout\", [timeout_seconds]);\n};\n\n// Public: setDebugEnabled changes the debug_enabled setting\nSWFUpload.prototype.setDebugEnabled = function (debugEnabled) {\n\tthis.settings.debug_enabled = debugEnabled;\n\tthis.callFlash(\"SetDebugEnabled\", [debugEnabled]);\n};\n\n// Public: setButtonImageURL loads a button image sprite\nSWFUpload.prototype.setButtonImageURL = function (buttonImageURL) {\n\tif (buttonImageURL == undefined) {\n\t\tbuttonImageURL = \"\";\n\t}\n\n\tthis.settings.button_image_url = buttonImageURL;\n\tthis.callFlash(\"SetButtonImageURL\", [buttonImageURL]);\n};\n\n// Public: setButtonDimensions resizes the Flash Movie and button\nSWFUpload.prototype.setButtonDimensions = function (width, height) {\n\tthis.settings.button_width = width;\n\tthis.settings.button_height = height;\n\n\tvar movie = this.getMovieElement();\n\tif (movie != undefined) {\n\t\tmovie.style.width = width + \"px\";\n\t\tmovie.style.height = height + \"px\";\n\t}\n\n\tthis.callFlash(\"SetButtonDimensions\", [width, height]);\n};\n// Public: setButtonText Changes the text overlaid on the button\nSWFUpload.prototype.setButtonText = function (html) {\n\tthis.settings.button_text = html;\n\tthis.callFlash(\"SetButtonText\", [html]);\n};\n// Public: setButtonTextPadding changes the top and left padding of the text overlay\nSWFUpload.prototype.setButtonTextPadding = function (left, top) {\n\tthis.settings.button_text_top_padding = top;\n\tthis.settings.button_text_left_padding = left;\n\tthis.callFlash(\"SetButtonTextPadding\", [left, top]);\n};\n\n// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button\nSWFUpload.prototype.setButtonTextStyle = function (css) {\n\tthis.settings.button_text_style = css;\n\tthis.callFlash(\"SetButtonTextStyle\", [css]);\n};\n// Public: setButtonDisabled disables/enables the button\nSWFUpload.prototype.setButtonDisabled = function (isDisabled) {\n\tthis.settings.button_disabled = isDisabled;\n\tthis.callFlash(\"SetButtonDisabled\", [isDisabled]);\n};\n// Public: setButtonAction sets the action that occurs when the button is clicked\nSWFUpload.prototype.setButtonAction = function (buttonAction) {\n\tthis.settings.button_action = buttonAction;\n\tthis.callFlash(\"SetButtonAction\", [buttonAction]);\n};\n\n// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button\nSWFUpload.prototype.setButtonCursor = function (cursor) {\n\tthis.settings.button_cursor = cursor;\n\tthis.callFlash(\"SetButtonCursor\", [cursor]);\n};\n\n/* *******************************\n\tFlash Event Interfaces\n\tThese functions are used by Flash to trigger the various\n\tevents.\n\n\tAll these functions a Private.\n\n\tBecause the ExternalInterface library is buggy the event calls\n\tare added to a queue and the queue then executed by a setTimeout.\n\tThis ensures that events are executed in a determinate order and that\n\tthe ExternalInterface bugs are avoided.\n******************************* */\n\nSWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {\n\t// Warning: Don't call this.debug inside here or you'll create an infinite loop\n\n\tif (argumentArray == undefined) {\n\t\targumentArray = [];\n\t} else if (!(argumentArray instanceof Array)) {\n\t\targumentArray = [argumentArray];\n\t}\n\n\tvar self = this;\n\tif (typeof this.settings[handlerName] === \"function\") {\n\t\t// Queue the event\n\t\tthis.eventQueue.push(function () {\n\t\t\tthis.settings[handlerName].apply(this, argumentArray);\n\t\t});\n\n\t\t// Execute the next queued event\n\t\tsetTimeout(function () {\n\t\t\tself.executeNextEvent();\n\t\t}, 0);\n\n\t} else if (this.settings[handlerName] !== null) {\n\t\tthrow \"Event handler \" + handlerName + \" is unknown or is not a function\";\n\t}\n};\n\n// Private: Causes the next event in the queue to be executed.  Since events are queued using a setTimeout\n// we must queue them in order to garentee that they are executed in order.\nSWFUpload.prototype.executeNextEvent = function () {\n\t// Warning: Don't call this.debug inside here or you'll create an infinite loop\n\n\tvar  f = this.eventQueue ? this.eventQueue.shift() : null;\n\tif (typeof(f) === \"function\") {\n\t\tf.apply(this);\n\t}\n};\n\n// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have\n// properties that contain characters that are not valid for JavaScript identifiers. To work around this\n// the Flash Component escapes the parameter names and we must unescape again before passing them along.\nSWFUpload.prototype.unescapeFilePostParams = function (file) {\n\tvar reg = /[$]([0-9a-f]{4})/i;\n\tvar unescapedPost = {};\n\tvar uk;\n\n\tif (file != undefined) {\n\t\tfor (var k in file.post) {\n\t\t\tif (file.post.hasOwnProperty(k)) {\n\t\t\t\tuk = k;\n\t\t\t\tvar match;\n\t\t\t\twhile ((match = reg.exec(uk)) !== null) {\n\t\t\t\t\tuk = uk.replace(match[0], String.fromCharCode(parseInt(\"0x\" + match[1], 16)));\n\t\t\t\t}\n\t\t\t\tunescapedPost[uk] = file.post[k];\n\t\t\t}\n\t\t}\n\n\t\tfile.post = unescapedPost;\n\t}\n\n\treturn file;\n};\n\n// Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working)\nSWFUpload.prototype.testExternalInterface = function () {\n\ttry {\n\t\treturn this.callFlash(\"TestExternalInterface\");\n\t} catch (ex) {\n\t\treturn false;\n\t}\n};\n\n// Private: This event is called by Flash when it has finished loading. Don't modify this.\n// Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded.\nSWFUpload.prototype.flashReady = function () {\n\t// Check that the movie element is loaded correctly with its ExternalInterface methods defined\n\tvar movieElement = this.getMovieElement();\n\n\tif (!movieElement) {\n\t\tthis.debug(\"Flash called back ready but the flash movie can't be found.\");\n\t\treturn;\n\t}\n\n\tthis.cleanUp(movieElement);\n\n\tthis.queueEvent(\"swfupload_loaded_handler\");\n};\n\n// Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE.\n// This function is called by Flash each time the ExternalInterface functions are created.\nSWFUpload.prototype.cleanUp = function (movieElement) {\n\t// Pro-actively unhook all the Flash functions\n\ttry {\n\t\tif (this.movieElement && typeof(movieElement.CallFunction) === \"unknown\") { // We only want to do this in IE\n\t\t\tthis.debug(\"Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)\");\n\t\t\tfor (var key in movieElement) {\n\t\t\t\ttry {\n\t\t\t\t\tif (typeof(movieElement[key]) === \"function\") {\n\t\t\t\t\t\tmovieElement[key] = null;\n\t\t\t\t\t}\n\t\t\t\t} catch (ex) {\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} catch (ex1) {\n\n\t}\n\n\t// Fix Flashes own cleanup code so if the SWFMovie was removed from the page\n\t// it doesn't display errors.\n\twindow[\"__flash__removeCallback\"] = function (instance, name) {\n\t\ttry {\n\t\t\tif (instance) {\n\t\t\t\tinstance[name] = null;\n\t\t\t}\n\t\t} catch (flashEx) {\n\n\t\t}\n\t};\n\n};\n\n\n/* This is a chance to do something before the browse window opens */\nSWFUpload.prototype.fileDialogStart = function () {\n\tthis.queueEvent(\"file_dialog_start_handler\");\n};\n\n\n/* Called when a file is successfully added to the queue. */\nSWFUpload.prototype.fileQueued = function (file) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"file_queued_handler\", file);\n};\n\n\n/* Handle errors that occur when an attempt to queue a file fails. */\nSWFUpload.prototype.fileQueueError = function (file, errorCode, message) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"file_queue_error_handler\", [file, errorCode, message]);\n};\n\n/* Called after the file dialog has closed and the selected files have been queued.\n\tYou could call startUpload here if you want the queued files to begin uploading immediately. */\nSWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) {\n\tthis.queueEvent(\"file_dialog_complete_handler\", [numFilesSelected, numFilesQueued, numFilesInQueue]);\n};\n\nSWFUpload.prototype.uploadStart = function (file) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"return_upload_start_handler\", file);\n};\n\nSWFUpload.prototype.returnUploadStart = function (file) {\n\tvar returnValue;\n\tif (typeof this.settings.upload_start_handler === \"function\") {\n\t\tfile = this.unescapeFilePostParams(file);\n\t\treturnValue = this.settings.upload_start_handler.call(this, file);\n\t} else if (this.settings.upload_start_handler != undefined) {\n\t\tthrow \"upload_start_handler must be a function\";\n\t}\n\n\t// Convert undefined to true so if nothing is returned from the upload_start_handler it is\n\t// interpretted as 'true'.\n\tif (returnValue === undefined) {\n\t\treturnValue = true;\n\t}\n\n\treturnValue = !!returnValue;\n\n\tthis.callFlash(\"ReturnUploadStart\", [returnValue]);\n};\n\n\n\nSWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"upload_progress_handler\", [file, bytesComplete, bytesTotal]);\n};\n\nSWFUpload.prototype.uploadError = function (file, errorCode, message) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"upload_error_handler\", [file, errorCode, message]);\n};\n\nSWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"upload_success_handler\", [file, serverData, responseReceived]);\n};\n\nSWFUpload.prototype.uploadComplete = function (file) {\n\tfile = this.unescapeFilePostParams(file);\n\tthis.queueEvent(\"upload_complete_handler\", file);\n};\n\n/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the\n   internal debug console.  You can override this event and have messages written where you want. */\nSWFUpload.prototype.debug = function (message) {\n\tthis.queueEvent(\"debug_handler\", message);\n};\n\n\n/* **********************************\n\tDebug Console\n\tThe debug console is a self contained, in page location\n\tfor debug message to be sent.  The Debug Console adds\n\titself to the body if necessary.\n\n\tThe console is automatically scrolled as messages appear.\n\n\tIf you are using your own debug handler or when you deploy to production and\n\thave debug disabled you can remove these functions to reduce the file size\n\tand complexity.\n********************************** */\n\n// Private: debugMessage is the default debug_handler.  If you want to print debug messages\n// call the debug() function.  When overriding the function your own function should\n// check to see if the debug setting is true before outputting debug information.\nSWFUpload.prototype.debugMessage = function (message) {\n\tif (this.settings.debug) {\n\t\tvar exceptionMessage, exceptionValues = [];\n\n\t\t// Check for an exception object and print it nicely\n\t\tif (typeof message === \"object\" && typeof message.name === \"string\" && typeof message.message === \"string\") {\n\t\t\tfor (var key in message) {\n\t\t\t\tif (message.hasOwnProperty(key)) {\n\t\t\t\t\texceptionValues.push(key + \": \" + message[key]);\n\t\t\t\t}\n\t\t\t}\n\t\t\texceptionMessage = exceptionValues.join(\"\\n\") || \"\";\n\t\t\texceptionValues = exceptionMessage.split(\"\\n\");\n\t\t\texceptionMessage = \"EXCEPTION: \" + exceptionValues.join(\"\\nEXCEPTION: \");\n\t\t\tSWFUpload.Console.writeLine(exceptionMessage);\n\t\t} else {\n\t\t\tSWFUpload.Console.writeLine(message);\n\t\t}\n\t}\n};\n\nSWFUpload.Console = {};\nSWFUpload.Console.writeLine = function (message) {\n\tvar console, documentForm;\n\n\ttry {\n\t\tconsole = document.getElementById(\"SWFUpload_Console\");\n\n\t\tif (!console) {\n\t\t\tdocumentForm = document.createElement(\"form\");\n\t\t\tdocument.getElementsByTagName(\"body\")[0].appendChild(documentForm);\n\n\t\t\tconsole = document.createElement(\"textarea\");\n\t\t\tconsole.id = \"SWFUpload_Console\";\n\t\t\tconsole.style.fontFamily = \"monospace\";\n\t\t\tconsole.setAttribute(\"wrap\", \"off\");\n\t\t\tconsole.wrap = \"off\";\n\t\t\tconsole.style.overflow = \"auto\";\n\t\t\tconsole.style.width = \"700px\";\n\t\t\tconsole.style.height = \"350px\";\n\t\t\tconsole.style.margin = \"5px\";\n\t\t\tdocumentForm.appendChild(console);\n\t\t}\n\n\t\tconsole.value += message + \"\\n\";\n\n\t\tconsole.scrollTop = console.scrollHeight - console.clientHeight;\n\t} catch (ex) {\n\t\talert(\"Exception: \" + ex.name + \" Message: \" + ex.message);\n\t}\n};\n\n})();\n\n(function() {\n/*\n\tQueue Plug-in\n\n\tFeatures:\n\t\t*Adds a cancelQueue() method for cancelling the entire queue.\n\t\t*All queued files are uploaded when startUpload() is called.\n\t\t*If false is returned from uploadComplete then the queue upload is stopped.\n\t\t If false is not returned (strict comparison) then the queue upload is continued.\n\t\t*Adds a QueueComplete event that is fired when all the queued files have finished uploading.\n\t\t Set the event handler with the queue_complete_handler setting.\n\n\t*/\n\nif (typeof(SWFUpload) === \"function\") {\n\tSWFUpload.queue = {};\n\n\tSWFUpload.prototype.initSettings = (function (oldInitSettings) {\n\t\treturn function () {\n\t\t\tif (typeof(oldInitSettings) === \"function\") {\n\t\t\t\toldInitSettings.call(this);\n\t\t\t}\n\n\t\t\tthis.queueSettings = {};\n\n\t\t\tthis.queueSettings.queue_cancelled_flag = false;\n\t\t\tthis.queueSettings.queue_upload_count = 0;\n\n\t\t\tthis.queueSettings.user_upload_complete_handler = this.settings.upload_complete_handler;\n\t\t\tthis.queueSettings.user_upload_start_handler = this.settings.upload_start_handler;\n\t\t\tthis.settings.upload_complete_handler = SWFUpload.queue.uploadCompleteHandler;\n\t\t\tthis.settings.upload_start_handler = SWFUpload.queue.uploadStartHandler;\n\n\t\t\tthis.settings.queue_complete_handler = this.settings.queue_complete_handler || null;\n\t\t};\n\t})(SWFUpload.prototype.initSettings);\n\n\tSWFUpload.prototype.startUpload = function (fileID) {\n\t\tthis.queueSettings.queue_cancelled_flag = false;\n\t\tthis.callFlash(\"StartUpload\", [fileID]);\n\t};\n\n\tSWFUpload.prototype.cancelQueue = function () {\n\t\tthis.queueSettings.queue_cancelled_flag = true;\n\t\tthis.stopUpload();\n\n\t\tvar stats = this.getStats();\n\t\twhile (stats.files_queued > 0) {\n\t\t\tthis.cancelUpload();\n\t\t\tstats = this.getStats();\n\t\t}\n\t};\n\n\tSWFUpload.queue.uploadStartHandler = function (file) {\n\t\tvar returnValue;\n\t\tif (typeof(this.queueSettings.user_upload_start_handler) === \"function\") {\n\t\t\treturnValue = this.queueSettings.user_upload_start_handler.call(this, file);\n\t\t}\n\n\t\t// To prevent upload a real \"FALSE\" value must be returned, otherwise default to a real \"TRUE\" value.\n\t\treturnValue = (returnValue === false) ? false : true;\n\n\t\tthis.queueSettings.queue_cancelled_flag = !returnValue;\n\n\t\treturn returnValue;\n\t};\n\n\tSWFUpload.queue.uploadCompleteHandler = function (file) {\n\t\tvar user_upload_complete_handler = this.queueSettings.user_upload_complete_handler;\n\t\tvar continueUpload;\n\n\t\tif (file.filestatus === SWFUpload.FILE_STATUS.COMPLETE) {\n\t\t\tthis.queueSettings.queue_upload_count++;\n\t\t}\n\n\t\tif (typeof(user_upload_complete_handler) === \"function\") {\n\t\t\tcontinueUpload = (user_upload_complete_handler.call(this, file) === false) ? false : true;\n\t\t} else if (file.filestatus === SWFUpload.FILE_STATUS.QUEUED) {\n\t\t\t// If the file was stopped and re-queued don't restart the upload\n\t\t\tcontinueUpload = false;\n\t\t} else {\n\t\t\tcontinueUpload = true;\n\t\t}\n\n\t\tif (continueUpload) {\n\t\t\tvar stats = this.getStats();\n\t\t\tif (stats.files_queued > 0 && this.queueSettings.queue_cancelled_flag === false) {\n\t\t\t\tthis.startUpload();\n\t\t\t} else if (this.queueSettings.queue_cancelled_flag === false) {\n\t\t\t\tthis.queueEvent(\"queue_complete_handler\", [this.queueSettings.queue_upload_count]);\n\t\t\t\tthis.queueSettings.queue_upload_count = 0;\n\t\t\t} else {\n\t\t\t\tthis.queueSettings.queue_cancelled_flag = false;\n\t\t\t\tthis.queueSettings.queue_upload_count = 0;\n\t\t\t}\n\t\t}\n\t};\n}\n\n})();\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/pagebreak/pagebreak.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('pagebreak', function(K) {\n\tvar self = this;\n\tvar name = 'pagebreak';\n\tvar pagebreakHtml = K.undef(self.pagebreakHtml, '<hr style=\"page-break-after: always;\" class=\"ke-pagebreak\" />');\n\n\tself.clickToolbar(name, function() {\n\t\tvar cmd = self.cmd, range = cmd.range;\n\t\tself.focus();\n\t\tvar tail = self.newlineTag == 'br' || K.WEBKIT ? '' : '<span id=\"__kindeditor_tail_tag__\"></span>';\n\t\tself.insertHtml(pagebreakHtml + tail);\n\t\tif (tail !== '') {\n\t\t\tvar p = K('#__kindeditor_tail_tag__', self.edit.doc);\n\t\t\trange.selectNodeContents(p[0]);\n\t\t\tp.removeAttr('id');\n\t\t\tcmd.select();\n\t\t}\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/plainpaste/plainpaste.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('plainpaste', function(K) {\n\tvar self = this, name = 'plainpaste';\n\tself.clickToolbar(name, function() {\n\t\tvar lang = self.lang(name + '.'),\n\t\t\thtml = '<div style=\"padding:10px 20px;\">' +\n\t\t\t\t'<div style=\"margin-bottom:10px;\">' + lang.comment + '</div>' +\n\t\t\t\t'<textarea class=\"ke-textarea\" style=\"width:408px;height:260px;\"></textarea>' +\n\t\t\t\t'</div>',\n\t\t\tdialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 450,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar html = textarea.val();\n\t\t\t\t\t\thtml = K.escape(html);\n\t\t\t\t\t\thtml = html.replace(/ {2}/g, ' &nbsp;');\n\t\t\t\t\t\tif (self.newlineTag == 'p') {\n\t\t\t\t\t\t\thtml = html.replace(/^/, '<p>').replace(/$/, '</p>').replace(/\\n/g, '</p><p>');\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\thtml = html.replace(/\\n/g, '<br />$&');\n\t\t\t\t\t\t}\n\t\t\t\t\t\tself.insertHtml(html).hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\ttextarea = K('textarea', dialog.div);\n\t\ttextarea[0].focus();\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/preview/preview.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('preview', function(K) {\n\tvar self = this, name = 'preview', undefined;\n\tself.clickToolbar(name, function() {\n\t\tvar lang = self.lang(name + '.'),\n\t\t\thtml = '<div style=\"padding:10px 20px;\">' +\n\t\t\t\t'<iframe class=\"ke-textarea\" frameborder=\"0\" style=\"width:708px;height:400px;\"></iframe>' +\n\t\t\t\t'</div>',\n\t\t\tdialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 750,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html\n\t\t\t}),\n\t\t\tiframe = K('iframe', dialog.div),\n\t\t\tdoc = K.iframeDoc(iframe);\n\t\tdoc.open();\n\t\tdoc.write(self.fullHtml());\n\t\tdoc.close();\n\t\tK(doc.body).css('background-color', '#FFF');\n\t\tiframe[0].contentWindow.focus();\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/quickformat/quickformat.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('quickformat', function(K) {\n\tvar self = this, name = 'quickformat',\n\t\tblockMap = K.toMap('blockquote,center,div,h1,h2,h3,h4,h5,h6,p');\n\tfunction getFirstChild(knode) {\n\t\tvar child = knode.first();\n\t\twhile (child && child.first()) {\n\t\t\tchild = child.first();\n\t\t}\n\t\treturn child;\n\t}\n\tself.clickToolbar(name, function() {\n\t\tself.focus();\n\t\tvar doc = self.edit.doc,\n\t\t\trange = self.cmd.range,\n\t\t\tchild = K(doc.body).first(), next,\n\t\t\tnodeList = [], subList = [],\n\t\t\tbookmark = range.createBookmark(true);\n\t\twhile(child) {\n\t\t\tnext = child.next();\n\t\t\tvar firstChild = getFirstChild(child);\n\t\t\tif (!firstChild || firstChild.name != 'img') {\n\t\t\t\tif (blockMap[child.name]) {\n\t\t\t\t\tchild.html(child.html().replace(/^(\\s|&nbsp;|　)+/ig, ''));\n\t\t\t\t\tchild.css('text-indent', '2em');\n\t\t\t\t} else {\n\t\t\t\t\tsubList.push(child);\n\t\t\t\t}\n\t\t\t\tif (!next || (blockMap[next.name] || blockMap[child.name] && !blockMap[next.name])) {\n\t\t\t\t\tif (subList.length > 0) {\n\t\t\t\t\t\tnodeList.push(subList);\n\t\t\t\t\t}\n\t\t\t\t\tsubList = [];\n\t\t\t\t}\n\t\t\t}\n\t\t\tchild = next;\n\t\t}\n\t\tK.each(nodeList, function(i, subList) {\n\t\t\tvar wrapper = K('<p style=\"text-indent:2em;\"></p>', doc);\n\t\t\tsubList[0].before(wrapper);\n\t\t\tK.each(subList, function(i, knode) {\n\t\t\t\twrapper.append(knode);\n\t\t\t});\n\t\t});\n\t\trange.moveToBookmark(bookmark);\n\t\tself.addBookmark();\n\t});\n});\n\n/**\n--------------------------\nabcd<br />\n1234<br />\n\nto\n\n<p style=\"text-indent:2em;\">\n\tabcd<br />\n\t1234<br />\n</p>\n\n--------------------------\n\n&nbsp; abcd<img>1233\n<p>1234</p>\n\nto\n\n<p style=\"text-indent:2em;\">abcd<img>1233</p>\n<p style=\"text-indent:2em;\">1234</p>\n\n--------------------------\n*/"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/table/table.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('table', function(K) {\n\tvar self = this, name = 'table', lang = self.lang(name + '.'), zeroborder = 'ke-zeroborder';\n\t// 设置颜色\n\tfunction _setColor(box, color) {\n\t\tcolor = color.toUpperCase();\n\t\tbox.css('background-color', color);\n\t\tbox.css('color', color === '#000000' ? '#FFFFFF' : '#000000');\n\t\tbox.html(color);\n\t}\n\t// 初始化取色器\n\tvar pickerList = [];\n\tfunction _initColorPicker(dialogDiv, colorBox) {\n\t\tcolorBox.bind('click,mousedown', function(e){\n\t\t\te.stopPropagation();\n\t\t});\n\t\tfunction removePicker() {\n\t\t\tK.each(pickerList, function() {\n\t\t\t\tthis.remove();\n\t\t\t});\n\t\t\tpickerList = [];\n\t\t\tK(document).unbind('click,mousedown', removePicker);\n\t\t\tdialogDiv.unbind('click,mousedown', removePicker);\n\t\t}\n\t\tcolorBox.click(function(e) {\n\t\t\tremovePicker();\n\t\t\tvar box = K(this),\n\t\t\t\tpos = box.pos();\n\t\t\tvar picker = K.colorpicker({\n\t\t\t\tx : pos.x,\n\t\t\t\ty : pos.y + box.height(),\n\t\t\t\tz : 811214,\n\t\t\t\tselectedColor : K(this).html(),\n\t\t\t\tcolors : self.colorTable,\n\t\t\t\tnoColor : self.lang('noColor'),\n\t\t\t\tshadowMode : self.shadowMode,\n\t\t\t\tclick : function(color) {\n\t\t\t\t\t_setColor(box, color);\n\t\t\t\t\tremovePicker();\n\t\t\t\t}\n\t\t\t});\n\t\t\tpickerList.push(picker);\n\t\t\tK(document).bind('click,mousedown', removePicker);\n\t\t\tdialogDiv.bind('click,mousedown', removePicker);\n\t\t});\n\t}\n\t// 取得下一行cell的index\n\tfunction _getCellIndex(table, row, cell) {\n\t\tvar rowSpanCount = 0;\n\t\tfor (var i = 0, len = row.cells.length; i < len; i++) {\n\t\t\tif (row.cells[i] == cell) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\trowSpanCount += row.cells[i].rowSpan - 1;\n\t\t}\n\t\treturn cell.cellIndex - rowSpanCount;\n\t}\n\tself.plugin.table = {\n\t\t//insert or modify table\n\t\tprop : function(isInsert) {\n\t\t\tvar html = [\n\t\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t\t//rows, cols\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keRows\" style=\"width:90px;\">' + lang.cells + '</label>',\n\t\t\t\tlang.rows + ' <input type=\"text\" id=\"keRows\" class=\"ke-input-text ke-input-number\" name=\"rows\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\tlang.cols + ' <input type=\"text\" class=\"ke-input-text ke-input-number\" name=\"cols\" value=\"\" maxlength=\"4\" />',\n\t\t\t\t'</div>',\n\t\t\t\t//width, height\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keWidth\" style=\"width:90px;\">' + lang.size + '</label>',\n\t\t\t\tlang.width + ' <input type=\"text\" id=\"keWidth\" class=\"ke-input-text ke-input-number\" name=\"width\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\t'<select name=\"widthType\">',\n\t\t\t\t'<option value=\"%\">' + lang.percent + '</option>',\n\t\t\t\t'<option value=\"px\">' + lang.px + '</option>',\n\t\t\t\t'</select> &nbsp; ',\n\t\t\t\tlang.height + ' <input type=\"text\" class=\"ke-input-text ke-input-number\" name=\"height\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\t'<select name=\"heightType\">',\n\t\t\t\t'<option value=\"%\">' + lang.percent + '</option>',\n\t\t\t\t'<option value=\"px\">' + lang.px + '</option>',\n\t\t\t\t'</select>',\n\t\t\t\t'</div>',\n\t\t\t\t//space, padding\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"kePadding\" style=\"width:90px;\">' + lang.space + '</label>',\n\t\t\t\tlang.padding + ' <input type=\"text\" id=\"kePadding\" class=\"ke-input-text ke-input-number\" name=\"padding\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\tlang.spacing + ' <input type=\"text\" class=\"ke-input-text ke-input-number\" name=\"spacing\" value=\"\" maxlength=\"4\" />',\n\t\t\t\t'</div>',\n\t\t\t\t//align\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keAlign\" style=\"width:90px;\">' + lang.align + '</label>',\n\t\t\t\t'<select id=\"keAlign\" name=\"align\">',\n\t\t\t\t'<option value=\"\">' + lang.alignDefault + '</option>',\n\t\t\t\t'<option value=\"left\">' + lang.alignLeft + '</option>',\n\t\t\t\t'<option value=\"center\">' + lang.alignCenter + '</option>',\n\t\t\t\t'<option value=\"right\">' + lang.alignRight + '</option>',\n\t\t\t\t'</select>',\n\t\t\t\t'</div>',\n\t\t\t\t//border\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keBorder\" style=\"width:90px;\">' + lang.border + '</label>',\n\t\t\t\tlang.borderWidth + ' <input type=\"text\" id=\"keBorder\" class=\"ke-input-text ke-input-number\" name=\"border\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\tlang.borderColor + ' <span class=\"ke-inline-block ke-input-color\"></span>',\n\t\t\t\t'</div>',\n\t\t\t\t//background color\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keBgColor\" style=\"width:90px;\">' + lang.backgroundColor + '</label>',\n\t\t\t\t'<span class=\"ke-inline-block ke-input-color\"></span>',\n\t\t\t\t'</div>',\n\t\t\t\t'</div>'\n\t\t\t].join('');\n\t\t\tvar bookmark = self.cmd.range.createBookmark();\n\t\t\tvar dialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 500,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tbeforeRemove : function() {\n\t\t\t\t\tcolorBox.unbind();\n\t\t\t\t},\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar rows = rowsBox.val(),\n\t\t\t\t\t\t\tcols = colsBox.val(),\n\t\t\t\t\t\t\twidth = widthBox.val(),\n\t\t\t\t\t\t\theight = heightBox.val(),\n\t\t\t\t\t\t\twidthType = widthTypeBox.val(),\n\t\t\t\t\t\t\theightType = heightTypeBox.val(),\n\t\t\t\t\t\t\tpadding = paddingBox.val(),\n\t\t\t\t\t\t\tspacing = spacingBox.val(),\n\t\t\t\t\t\t\talign = alignBox.val(),\n\t\t\t\t\t\t\tborder = borderBox.val(),\n\t\t\t\t\t\t\tborderColor = K(colorBox[0]).html() || '',\n\t\t\t\t\t\t\tbgColor = K(colorBox[1]).html() || '';\n\t\t\t\t\t\tif (rows == 0 || !/^\\d+$/.test(rows)) {\n\t\t\t\t\t\t\talert(self.lang('invalidRows'));\n\t\t\t\t\t\t\trowsBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (cols == 0 || !/^\\d+$/.test(cols)) {\n\t\t\t\t\t\t\talert(self.lang('invalidRows'));\n\t\t\t\t\t\t\tcolsBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(width)) {\n\t\t\t\t\t\t\talert(self.lang('invalidWidth'));\n\t\t\t\t\t\t\twidthBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(height)) {\n\t\t\t\t\t\t\talert(self.lang('invalidHeight'));\n\t\t\t\t\t\t\theightBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(padding)) {\n\t\t\t\t\t\t\talert(self.lang('invalidPadding'));\n\t\t\t\t\t\t\tpaddingBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(spacing)) {\n\t\t\t\t\t\t\talert(self.lang('invalidSpacing'));\n\t\t\t\t\t\t\tspacingBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(border)) {\n\t\t\t\t\t\t\talert(self.lang('invalidBorder'));\n\t\t\t\t\t\t\tborderBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//modify table\n\t\t\t\t\t\tif (table) {\n\t\t\t\t\t\t\tif (width !== '') {\n\t\t\t\t\t\t\t\ttable.width(width + widthType);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.css('width', '');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (table[0].width !== undefined) {\n\t\t\t\t\t\t\t\ttable.removeAttr('width');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (height !== '') {\n\t\t\t\t\t\t\t\ttable.height(height + heightType);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.css('height', '');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (table[0].height !== undefined) {\n\t\t\t\t\t\t\t\ttable.removeAttr('height');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttable.css('background-color', bgColor);\n\t\t\t\t\t\t\tif (table[0].bgColor !== undefined) {\n\t\t\t\t\t\t\t\ttable.removeAttr('bgColor');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (padding !== '') {\n\t\t\t\t\t\t\t\ttable[0].cellPadding = padding;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeAttr('cellPadding');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (spacing !== '') {\n\t\t\t\t\t\t\t\ttable[0].cellSpacing = spacing;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeAttr('cellSpacing');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (align !== '') {\n\t\t\t\t\t\t\t\ttable[0].align = align;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeAttr('align');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (border !== '') {\n\t\t\t\t\t\t\t\ttable.attr('border', border);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeAttr('border');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (border === '' || border === '0') {\n\t\t\t\t\t\t\t\ttable.addClass(zeroborder);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeClass(zeroborder);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (borderColor !== '') {\n\t\t\t\t\t\t\t\ttable.attr('borderColor', borderColor);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttable.removeAttr('borderColor');\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tself.hideDialog().focus();\n\t\t\t\t\t\t\tself.cmd.range.moveToBookmark(bookmark);\n\t\t\t\t\t\t\tself.cmd.select();\n\t\t\t\t\t\t\tself.addBookmark();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//insert new table\n\t\t\t\t\t\tvar style = '';\n\t\t\t\t\t\tif (width !== '') {\n\t\t\t\t\t\t\tstyle += 'width:' + width + widthType + ';';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (height !== '') {\n\t\t\t\t\t\t\tstyle += 'height:' + height + heightType + ';';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (bgColor !== '') {\n\t\t\t\t\t\t\tstyle += 'background-color:' + bgColor + ';';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tvar html = '<table';\n\t\t\t\t\t\tif (style !== '') {\n\t\t\t\t\t\t\thtml += ' style=\"' + style + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (padding !== '') {\n\t\t\t\t\t\t\thtml += ' cellpadding=\"' + padding + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (spacing !== '') {\n\t\t\t\t\t\t\thtml += ' cellspacing=\"' + spacing + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (align !== '') {\n\t\t\t\t\t\t\thtml += ' align=\"' + align + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (border !== '') {\n\t\t\t\t\t\t\thtml += ' border=\"' + border + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (border === '' || border === '0') {\n\t\t\t\t\t\t\thtml += ' class=\"' + zeroborder + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (borderColor !== '') {\n\t\t\t\t\t\t\thtml += ' bordercolor=\"' + borderColor + '\"';\n\t\t\t\t\t\t}\n\t\t\t\t\t\thtml += '>';\n\t\t\t\t\t\tfor (var i = 0; i < rows; i++) {\n\t\t\t\t\t\t\thtml += '<tr>';\n\t\t\t\t\t\t\tfor (var j = 0; j < cols; j++) {\n\t\t\t\t\t\t\t\thtml += '<td>' + (K.IE ? '&nbsp;' : '<br />') + '</td>';\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\thtml += '</tr>';\n\t\t\t\t\t\t}\n\t\t\t\t\t\thtml += '</table>';\n\t\t\t\t\t\tif (!K.IE) {\n\t\t\t\t\t\t\thtml += '<br />';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tself.insertHtml(html);\n\t\t\t\t\t\tself.select().hideDialog().focus();\n\t\t\t\t\t\tself.addBookmark();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\tdiv = dialog.div,\n\t\t\trowsBox = K('[name=\"rows\"]', div).val(3),\n\t\t\tcolsBox = K('[name=\"cols\"]', div).val(2),\n\t\t\twidthBox = K('[name=\"width\"]', div).val(100),\n\t\t\theightBox = K('[name=\"height\"]', div),\n\t\t\twidthTypeBox = K('[name=\"widthType\"]', div),\n\t\t\theightTypeBox = K('[name=\"heightType\"]', div),\n\t\t\tpaddingBox = K('[name=\"padding\"]', div).val(2),\n\t\t\tspacingBox = K('[name=\"spacing\"]', div).val(0),\n\t\t\talignBox = K('[name=\"align\"]', div),\n\t\t\tborderBox = K('[name=\"border\"]', div).val(1),\n\t\t\tcolorBox = K('.ke-input-color', div);\n\t\t\t_initColorPicker(div, colorBox.eq(0));\n\t\t\t_initColorPicker(div, colorBox.eq(1));\n\t\t\t_setColor(colorBox.eq(0), '#000000');\n\t\t\t_setColor(colorBox.eq(1), '');\n\t\t\t// foucs and select\n\t\t\trowsBox[0].focus();\n\t\t\trowsBox[0].select();\n\t\t\tvar table;\n\t\t\tif (isInsert) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t//get selected table node\n\t\t\ttable = self.plugin.getSelectedTable();\n\t\t\tif (table) {\n\t\t\t\trowsBox.val(table[0].rows.length);\n\t\t\t\tcolsBox.val(table[0].rows.length > 0 ? table[0].rows[0].cells.length : 0);\n\t\t\t\trowsBox.attr('disabled', true);\n\t\t\t\tcolsBox.attr('disabled', true);\n\t\t\t\tvar match,\n\t\t\t\t\ttableWidth = table[0].style.width || table[0].width,\n\t\t\t\t\ttableHeight = table[0].style.height || table[0].height;\n\t\t\t\tif (tableWidth !== undefined && (match = /^(\\d+)((?:px|%)*)$/.exec(tableWidth))) {\n\t\t\t\t\twidthBox.val(match[1]);\n\t\t\t\t\twidthTypeBox.val(match[2]);\n\t\t\t\t} else {\n\t\t\t\t\twidthBox.val('');\n\t\t\t\t}\n\t\t\t\tif (tableHeight !== undefined && (match = /^(\\d+)((?:px|%)*)$/.exec(tableHeight))) {\n\t\t\t\t\theightBox.val(match[1]);\n\t\t\t\t\theightTypeBox.val(match[2]);\n\t\t\t\t}\n\t\t\t\tpaddingBox.val(table[0].cellPadding || '');\n\t\t\t\tspacingBox.val(table[0].cellSpacing || '');\n\t\t\t\talignBox.val(table[0].align || '');\n\t\t\t\tborderBox.val(table[0].border === undefined ? '' : table[0].border);\n\t\t\t\t_setColor(colorBox.eq(0), K.toHex(table.attr('borderColor') || ''));\n\t\t\t\t_setColor(colorBox.eq(1), K.toHex(table[0].style.backgroundColor || table[0].bgColor || ''));\n\t\t\t\twidthBox[0].focus();\n\t\t\t\twidthBox[0].select();\n\t\t\t}\n\t\t},\n\t\t//modify cell\n\t\tcellprop : function() {\n\t\t\tvar html = [\n\t\t\t\t'<div style=\"padding:20px;\">',\n\t\t\t\t//width, height\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keWidth\" style=\"width:90px;\">' + lang.size + '</label>',\n\t\t\t\tlang.width + ' <input type=\"text\" id=\"keWidth\" class=\"ke-input-text ke-input-number\" name=\"width\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\t'<select name=\"widthType\">',\n\t\t\t\t'<option value=\"%\">' + lang.percent + '</option>',\n\t\t\t\t'<option value=\"px\">' + lang.px + '</option>',\n\t\t\t\t'</select> &nbsp; ',\n\t\t\t\tlang.height + ' <input type=\"text\" class=\"ke-input-text ke-input-number\" name=\"height\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\t'<select name=\"heightType\">',\n\t\t\t\t'<option value=\"%\">' + lang.percent + '</option>',\n\t\t\t\t'<option value=\"px\">' + lang.px + '</option>',\n\t\t\t\t'</select>',\n\t\t\t\t'</div>',\n\t\t\t\t//align\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keAlign\" style=\"width:90px;\">' + lang.align + '</label>',\n\t\t\t\tlang.textAlign + ' <select id=\"keAlign\" name=\"textAlign\">',\n\t\t\t\t'<option value=\"\">' + lang.alignDefault + '</option>',\n\t\t\t\t'<option value=\"left\">' + lang.alignLeft + '</option>',\n\t\t\t\t'<option value=\"center\">' + lang.alignCenter + '</option>',\n\t\t\t\t'<option value=\"right\">' + lang.alignRight + '</option>',\n\t\t\t\t'</select> ',\n\t\t\t\tlang.verticalAlign + ' <select name=\"verticalAlign\">',\n\t\t\t\t'<option value=\"\">' + lang.alignDefault + '</option>',\n\t\t\t\t'<option value=\"top\">' + lang.alignTop + '</option>',\n\t\t\t\t'<option value=\"middle\">' + lang.alignMiddle + '</option>',\n\t\t\t\t'<option value=\"bottom\">' + lang.alignBottom + '</option>',\n\t\t\t\t'<option value=\"baseline\">' + lang.alignBaseline + '</option>',\n\t\t\t\t'</select>',\n\t\t\t\t'</div>',\n\t\t\t\t//border\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keBorder\" style=\"width:90px;\">' + lang.border + '</label>',\n\t\t\t\tlang.borderWidth + ' <input type=\"text\" id=\"keBorder\" class=\"ke-input-text ke-input-number\" name=\"border\" value=\"\" maxlength=\"4\" /> &nbsp; ',\n\t\t\t\tlang.borderColor + ' <span class=\"ke-inline-block ke-input-color\"></span>',\n\t\t\t\t'</div>',\n\t\t\t\t//background color\n\t\t\t\t'<div class=\"ke-dialog-row\">',\n\t\t\t\t'<label for=\"keBgColor\" style=\"width:90px;\">' + lang.backgroundColor + '</label>',\n\t\t\t\t'<span class=\"ke-inline-block ke-input-color\"></span>',\n\t\t\t\t'</div>',\n\t\t\t\t'</div>'\n\t\t\t].join('');\n\t\t\tvar bookmark = self.cmd.range.createBookmark();\n\t\t\tvar dialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 500,\n\t\t\t\ttitle : self.lang('tablecell'),\n\t\t\t\tbody : html,\n\t\t\t\tbeforeRemove : function() {\n\t\t\t\t\tcolorBox.unbind();\n\t\t\t\t},\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar width = widthBox.val(),\n\t\t\t\t\t\t\theight = heightBox.val(),\n\t\t\t\t\t\t\twidthType = widthTypeBox.val(),\n\t\t\t\t\t\t\theightType = heightTypeBox.val(),\n\t\t\t\t\t\t\tpadding = paddingBox.val(),\n\t\t\t\t\t\t\tspacing = spacingBox.val(),\n\t\t\t\t\t\t\ttextAlign = textAlignBox.val(),\n\t\t\t\t\t\t\tverticalAlign = verticalAlignBox.val(),\n\t\t\t\t\t\t\tborder = borderBox.val(),\n\t\t\t\t\t\t\tborderColor = K(colorBox[0]).html() || '',\n\t\t\t\t\t\t\tbgColor = K(colorBox[1]).html() || '';\n\t\t\t\t\t\tif (!/^\\d*$/.test(width)) {\n\t\t\t\t\t\t\talert(self.lang('invalidWidth'));\n\t\t\t\t\t\t\twidthBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(height)) {\n\t\t\t\t\t\t\talert(self.lang('invalidHeight'));\n\t\t\t\t\t\t\theightBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (!/^\\d*$/.test(border)) {\n\t\t\t\t\t\t\talert(self.lang('invalidBorder'));\n\t\t\t\t\t\t\tborderBox[0].focus();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcell.css({\n\t\t\t\t\t\t\twidth : width !== '' ? (width + widthType) : '',\n\t\t\t\t\t\t\theight : height !== '' ? (height + heightType) : '',\n\t\t\t\t\t\t\t'background-color' : bgColor,\n\t\t\t\t\t\t\t'text-align' : textAlign,\n\t\t\t\t\t\t\t'vertical-align' : verticalAlign,\n\t\t\t\t\t\t\t'border-width' : border,\n\t\t\t\t\t\t\t'border-style' : border !== '' ? 'solid' : '',\n\t\t\t\t\t\t\t'border-color' : borderColor\n\t\t\t\t\t\t});\n\t\t\t\t\t\tself.hideDialog().focus();\n\t\t\t\t\t\tself.cmd.range.moveToBookmark(bookmark);\n\t\t\t\t\t\tself.cmd.select();\n\t\t\t\t\t\tself.addBookmark();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\tdiv = dialog.div,\n\t\t\twidthBox = K('[name=\"width\"]', div).val(100),\n\t\t\theightBox = K('[name=\"height\"]', div),\n\t\t\twidthTypeBox = K('[name=\"widthType\"]', div),\n\t\t\theightTypeBox = K('[name=\"heightType\"]', div),\n\t\t\tpaddingBox = K('[name=\"padding\"]', div).val(2),\n\t\t\tspacingBox = K('[name=\"spacing\"]', div).val(0),\n\t\t\ttextAlignBox = K('[name=\"textAlign\"]', div),\n\t\t\tverticalAlignBox = K('[name=\"verticalAlign\"]', div),\n\t\t\tborderBox = K('[name=\"border\"]', div).val(1),\n\t\t\tcolorBox = K('.ke-input-color', div);\n\t\t\t_initColorPicker(div, colorBox.eq(0));\n\t\t\t_initColorPicker(div, colorBox.eq(1));\n\t\t\t_setColor(colorBox.eq(0), '#000000');\n\t\t\t_setColor(colorBox.eq(1), '');\n\t\t\t// foucs and select\n\t\t\twidthBox[0].focus();\n\t\t\twidthBox[0].select();\n\t\t\t// get selected cell\n\t\t\tvar cell = self.plugin.getSelectedCell();\n\t\t\tvar match,\n\t\t\t\tcellWidth = cell[0].style.width || cell[0].width || '',\n\t\t\t\tcellHeight = cell[0].style.height || cell[0].height || '';\n\t\t\tif ((match = /^(\\d+)((?:px|%)*)$/.exec(cellWidth))) {\n\t\t\t\twidthBox.val(match[1]);\n\t\t\t\twidthTypeBox.val(match[2]);\n\t\t\t} else {\n\t\t\t\twidthBox.val('');\n\t\t\t}\n\t\t\tif ((match = /^(\\d+)((?:px|%)*)$/.exec(cellHeight))) {\n\t\t\t\theightBox.val(match[1]);\n\t\t\t\theightTypeBox.val(match[2]);\n\t\t\t}\n\t\t\ttextAlignBox.val(cell[0].style.textAlign || '');\n\t\t\tverticalAlignBox.val(cell[0].style.verticalAlign || '');\n\t\t\tvar border = cell[0].style.borderWidth || '';\n\t\t\tif (border) {\n\t\t\t\tborder = parseInt(border);\n\t\t\t}\n\t\t\tborderBox.val(border);\n\t\t\t_setColor(colorBox.eq(0), K.toHex(cell[0].style.borderColor || ''));\n\t\t\t_setColor(colorBox.eq(1), K.toHex(cell[0].style.backgroundColor || ''));\n\t\t\twidthBox[0].focus();\n\t\t\twidthBox[0].select();\n\t\t},\n\t\tinsert : function() {\n\t\t\tthis.prop(true);\n\t\t},\n\t\t'delete' : function() {\n\t\t\tvar table = self.plugin.getSelectedTable();\n\t\t\tself.cmd.range.setStartBefore(table[0]).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\ttable.remove();\n\t\t\tself.addBookmark();\n\t\t},\n\t\tcolinsert : function(offset) {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\tindex = cell.cellIndex + offset;\n\t\t\t// 取得第一行的index\n\t\t\tindex += table.rows[0].cells.length - row.cells.length;\n\n\t\t\tfor (var i = 0, len = table.rows.length; i < len; i++) {\n\t\t\t\tvar newRow = table.rows[i],\n\t\t\t\t\tnewCell = newRow.insertCell(index);\n\t\t\t\tnewCell.innerHTML = K.IE ? '' : '<br />';\n\t\t\t\t// 调整下一行的单元格index\n\t\t\t\tindex = _getCellIndex(table, newRow, newCell);\n\t\t\t}\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\tcolinsertleft : function() {\n\t\t\tthis.colinsert(0);\n\t\t},\n\t\tcolinsertright : function() {\n\t\t\tthis.colinsert(1);\n\t\t},\n\t\trowinsert : function(offset) {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0];\n\t\t\tvar rowIndex = row.rowIndex;\n\t\t\tif (offset === 1) {\n\t\t\t\trowIndex = row.rowIndex + (cell.rowSpan - 1) + offset;\n\t\t\t}\n\t\t\tvar newRow = table.insertRow(rowIndex);\n\n\t\t\tfor (var i = 0, len = row.cells.length; i < len; i++) {\n\t\t\t\t// 调整cell个数\n\t\t\t\tif (row.cells[i].rowSpan > 1) {\n\t\t\t\t\tlen -= row.cells[i].rowSpan - 1;\n\t\t\t\t}\n\t\t\t\tvar newCell = newRow.insertCell(i);\n\t\t\t\t// copy colspan\n\t\t\t\tif (offset === 1 && row.cells[i].colSpan > 1) {\n\t\t\t\t\tnewCell.colSpan = row.cells[i].colSpan;\n\t\t\t\t}\n\t\t\t\tnewCell.innerHTML = K.IE ? '' : '<br />';\n\t\t\t}\n\t\t\t// 调整rowspan\n\t\t\tfor (var j = rowIndex; j >= 0; j--) {\n\t\t\t\tvar cells = table.rows[j].cells;\n\t\t\t\tif (cells.length > i) {\n\t\t\t\t\tfor (var k = cell.cellIndex; k >= 0; k--) {\n\t\t\t\t\t\tif (cells[k].rowSpan > 1) {\n\t\t\t\t\t\t\tcells[k].rowSpan += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\trowinsertabove : function() {\n\t\t\tthis.rowinsert(0);\n\t\t},\n\t\trowinsertbelow : function() {\n\t\t\tthis.rowinsert(1);\n\t\t},\n\t\trowmerge : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\trowIndex = row.rowIndex, // 当前行的index\n\t\t\t\tnextRowIndex = rowIndex + cell.rowSpan, // 下一行的index\n\t\t\t\tnextRow = table.rows[nextRowIndex]; // 下一行\n\t\t\t// 最后一行不能合并\n\t\t\tif (table.rows.length <= nextRowIndex) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar cellIndex = cell.cellIndex; // 下一行单元格的index\n\t\t\tif (nextRow.cells.length <= cellIndex) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar nextCell = nextRow.cells[cellIndex]; // 下一行单元格\n\t\t\t// 上下行的colspan不一致时不能合并\n\t\t\tif (cell.colSpan !== nextCell.colSpan) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcell.rowSpan += nextCell.rowSpan;\n\t\t\tnextRow.deleteCell(cellIndex);\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\tcolmerge : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\trowIndex = row.rowIndex, // 当前行的index\n\t\t\t\tcellIndex = cell.cellIndex,\n\t\t\t\tnextCellIndex = cellIndex + 1;\n\t\t\t// 最后一列不能合并\n\t\t\tif (row.cells.length <= nextCellIndex) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar nextCell = row.cells[nextCellIndex];\n\t\t\t// 左右列的rowspan不一致时不能合并\n\t\t\tif (cell.rowSpan !== nextCell.rowSpan) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcell.colSpan += nextCell.colSpan;\n\t\t\trow.deleteCell(nextCellIndex);\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\trowsplit : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\trowIndex = row.rowIndex;\n\t\t\t// 不是可分割单元格\n\t\t\tif (cell.rowSpan === 1) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar cellIndex = _getCellIndex(table, row, cell);\n\t\t\tfor (var i = 1, len = cell.rowSpan; i < len; i++) {\n\t\t\t\tvar newRow = table.rows[rowIndex + i],\n\t\t\t\t\tnewCell = newRow.insertCell(cellIndex);\n\t\t\t\tif (cell.colSpan > 1) {\n\t\t\t\t\tnewCell.colSpan = cell.colSpan;\n\t\t\t\t}\n\t\t\t\tnewCell.innerHTML = K.IE ? '' : '<br />';\n\t\t\t\t// 调整下一行的单元格index\n\t\t\t\tcellIndex = _getCellIndex(table, newRow, newCell);\n\t\t\t}\n\t\t\tK(cell).removeAttr('rowSpan');\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\tcolsplit : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\tcellIndex = cell.cellIndex;\n\t\t\t// 不是可分割单元格\n\t\t\tif (cell.colSpan === 1) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (var i = 1, len = cell.colSpan; i < len; i++) {\n\t\t\t\tvar newCell = row.insertCell(cellIndex + i);\n\t\t\t\tif (cell.rowSpan > 1) {\n\t\t\t\t\tnewCell.rowSpan = cell.rowSpan;\n\t\t\t\t}\n\t\t\t\tnewCell.innerHTML = K.IE ? '' : '<br />';\n\t\t\t}\n\t\t\tK(cell).removeAttr('colSpan');\n\t\t\tself.cmd.range.selectNodeContents(cell).collapse(true);\n\t\t\tself.cmd.select();\n\t\t\tself.addBookmark();\n\t\t},\n\t\tcoldelete : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\tindex = cell.cellIndex;\n\t\t\tfor (var i = 0, len = table.rows.length; i < len; i++) {\n\t\t\t\tvar newRow = table.rows[i],\n\t\t\t\t\tnewCell = newRow.cells[index];\n\t\t\t\tif (newCell.colSpan > 1) {\n\t\t\t\t\tnewCell.colSpan -= 1;\n\t\t\t\t\tif (newCell.colSpan === 1) {\n\t\t\t\t\t\tK(newCell).removeAttr('colSpan');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tnewRow.deleteCell(index);\n\t\t\t\t}\n\t\t\t\t// 跳过不需要删除的行\n\t\t\t\tif (newCell.rowSpan > 1) {\n\t\t\t\t\ti += newCell.rowSpan - 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (row.cells.length === 0) {\n\t\t\t\tself.cmd.range.setStartBefore(table).collapse(true);\n\t\t\t\tself.cmd.select();\n\t\t\t\tK(table).remove();\n\t\t\t} else {\n\t\t\t\tself.cmd.selection(true);\n\t\t\t}\n\t\t\tself.addBookmark();\n\t\t},\n\t\trowdelete : function() {\n\t\t\tvar table = self.plugin.getSelectedTable()[0],\n\t\t\t\trow = self.plugin.getSelectedRow()[0],\n\t\t\t\tcell = self.plugin.getSelectedCell()[0],\n\t\t\t\trowIndex = row.rowIndex;\n\t\t\t// 从下到上删除\n\t\t\tfor (var i = cell.rowSpan - 1; i >= 0; i--) {\n\t\t\t\ttable.deleteRow(rowIndex + i);\n\t\t\t}\n\t\t\tif (table.rows.length === 0) {\n\t\t\t\tself.cmd.range.setStartBefore(table).collapse(true);\n\t\t\t\tself.cmd.select();\n\t\t\t\tK(table).remove();\n\t\t\t} else {\n\t\t\t\tself.cmd.selection(true);\n\t\t\t}\n\t\t\tself.addBookmark();\n\t\t}\n\t};\n\tself.clickToolbar(name, self.plugin.table.prop);\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/template/html/1.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<meta charset=\"utf-8\" />\n</head>\n<body>\n\t<h3>\n\t\t<img align=\"left\" height=\"100\" style=\"margin-right: 10px\" width=\"100\" />在此处输入标题\n\t</h3>\n\t<p>\n\t\t在此处输入内容\n\t</p>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/template/html/2.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<meta charset=\"utf-8\" />\n</head>\n<body>\n\t<h3>\n\t\t标题\n\t</h3>\n\t<table style=\"width:100%;\" cellpadding=\"2\" cellspacing=\"0\" border=\"1\">\n\t\t<tbody>\n\t\t\t<tr>\n\t\t\t\t<td>\n\t\t\t\t\t<h3>标题1</h3>\n\t\t\t\t</td>\n\t\t\t\t<td>\n\t\t\t\t\t<h3>标题1</h3>\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td>\n\t\t\t\t\t内容1\n\t\t\t\t</td>\n\t\t\t\t<td>\n\t\t\t\t\t内容2\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td>\n\t\t\t\t\t内容3\n\t\t\t\t</td>\n\t\t\t\t<td>\n\t\t\t\t\t内容4\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t</tbody>\n\t</table>\n\t<p>\n\t\t表格说明\n\t</p>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/template/html/3.html",
    "content": "<!doctype html>\n<html>\n<head>\n\t<meta charset=\"utf-8\" />\n</head>\n<body>\n\t<p>\n\t\t在此处输入内容\n\t</p>\n\t<ol>\n\t\t<li>\n\t\t\t描述1\n\t\t</li>\n\t\t<li>\n\t\t\t描述2\n\t\t</li>\n\t\t<li>\n\t\t\t描述3\n\t\t</li>\n\t</ol>\n\t<p>\n\t\t在此处输入内容\n\t</p>\n\t<ul>\n\t\t<li>\n\t\t\t描述1\n\t\t</li>\n\t\t<li>\n\t\t\t描述2\n\t\t</li>\n\t\t<li>\n\t\t\t描述3\n\t\t</li>\n\t</ul>\n</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/template/template.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('template', function(K) {\n\tvar self = this, name = 'template', lang = self.lang(name + '.'),\n\t\thtmlPath = self.pluginsPath + name + '/html/';\n\tfunction getFilePath(fileName) {\n\t\treturn htmlPath + fileName + '?ver=' + encodeURIComponent(K.DEBUG ? K.TIME : K.VERSION);\n\t}\n\tself.clickToolbar(name, function() {\n\t\tvar lang = self.lang(name + '.'),\n\t\t\tarr = ['<div style=\"padding:10px 20px;\">',\n\t\t\t\t'<div class=\"ke-header\">',\n\t\t\t\t// left start\n\t\t\t\t'<div class=\"ke-left\">',\n\t\t\t\tlang. selectTemplate + ' <select>'];\n\t\t\tK.each(lang.fileList, function(key, val) {\n\t\t\t\tarr.push('<option value=\"' + key + '\">' + val + '</option>');\n\t\t\t});\n\t\t\thtml = [arr.join(''),\n\t\t\t\t'</select></div>',\n\t\t\t\t// right start\n\t\t\t\t'<div class=\"ke-right\">',\n\t\t\t\t'<input type=\"checkbox\" id=\"keReplaceFlag\" name=\"replaceFlag\" value=\"1\" /> <label for=\"keReplaceFlag\">' + lang.replaceContent + '</label>',\n\t\t\t\t'</div>',\n\t\t\t\t'<div class=\"ke-clearfix\"></div>',\n\t\t\t\t'</div>',\n\t\t\t\t'<iframe class=\"ke-textarea\" frameborder=\"0\" style=\"width:458px;height:260px;background-color:#FFF;\"></iframe>',\n\t\t\t\t'</div>'].join('');\n\t\tvar dialog = self.createDialog({\n\t\t\tname : name,\n\t\t\twidth : 500,\n\t\t\ttitle : self.lang(name),\n\t\t\tbody : html,\n\t\t\tyesBtn : {\n\t\t\t\tname : self.lang('yes'),\n\t\t\t\tclick : function(e) {\n\t\t\t\t\tvar doc = K.iframeDoc(iframe);\n\t\t\t\t\tself[checkbox[0].checked ? 'html' : 'insertHtml'](doc.body.innerHTML).hideDialog().focus();\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tvar selectBox = K('select', dialog.div),\n\t\t\tcheckbox = K('[name=\"replaceFlag\"]', dialog.div),\n\t\t\tiframe = K('iframe', dialog.div);\n\t\tcheckbox[0].checked = true;\n\t\tiframe.attr('src', getFilePath(selectBox.val()));\n\t\tselectBox.change(function() {\n\t\t\tiframe.attr('src', getFilePath(this.value));\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/plugins/wordpaste/wordpaste.js",
    "content": "/*******************************************************************************\n* KindEditor - WYSIWYG HTML Editor for Internet\n* Copyright (C) 2006-2011 kindsoft.net\n*\n* @author Roddy <luolonghao@gmail.com>\n* @site http://www.kindsoft.net/\n* @licence http://www.kindsoft.net/license.php\n*******************************************************************************/\n\nKindEditor.plugin('wordpaste', function(K) {\n\tvar self = this, name = 'wordpaste';\n\tself.clickToolbar(name, function() {\n\t\tvar lang = self.lang(name + '.'),\n\t\t\thtml = '<div style=\"padding:10px 20px;\">' +\n\t\t\t\t'<div style=\"margin-bottom:10px;\">' + lang.comment + '</div>' +\n\t\t\t\t'<iframe class=\"ke-textarea\" frameborder=\"0\" style=\"width:408px;height:260px;\"></iframe>' +\n\t\t\t\t'</div>',\n\t\t\tdialog = self.createDialog({\n\t\t\t\tname : name,\n\t\t\t\twidth : 450,\n\t\t\t\ttitle : self.lang(name),\n\t\t\t\tbody : html,\n\t\t\t\tyesBtn : {\n\t\t\t\t\tname : self.lang('yes'),\n\t\t\t\t\tclick : function(e) {\n\t\t\t\t\t\tvar str = doc.body.innerHTML;\n\t\t\t\t\t\tstr = K.clearMsWord(str, self.filterMode ? self.htmlTags : K.options.htmlTags);\n\t\t\t\t\t\tself.insertHtml(str).hideDialog().focus();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}),\n\t\t\tdiv = dialog.div,\n\t\t\tiframe = K('iframe', div),\n\t\t\tdoc = K.iframeDoc(iframe);\n\t\tif (!K.IE) {\n\t\t\tdoc.designMode = 'on';\n\t\t}\n\t\tdoc.open();\n\t\tdoc.write('<!doctype html><html><head><title>WordPaste</title></head>');\n\t\tdoc.write('<body style=\"background-color:#FFF;font-size:12px;margin:2px;\">');\n\t\tif (!K.IE) {\n\t\t\tdoc.write('<br />');\n\t\t}\n\t\tdoc.write('</body></html>');\n\t\tdoc.close();\n\t\tif (K.IE) {\n\t\t\tdoc.body.contentEditable = 'true';\n\t\t}\n\t\tiframe[0].contentWindow.focus();\n\t});\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/themes/default/default.css",
    "content": "/* common */\n.ke-inline-block {\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tzoom: 1;\n\t*display: inline;\n}\n.ke-clearfix {\n\tzoom: 1;\n}\n.ke-clearfix:after {\n\tcontent: \".\";\n\tdisplay: block;\n\tclear: both;\n\tfont-size: 0;\n\theight: 0;\n\tline-height: 0;\n\tvisibility: hidden;\n}\n.ke-shadow {\n\tbox-shadow: 1px 1px 3px #A0A0A0;\n\t-moz-box-shadow: 1px 1px 3px #A0A0A0;\n\t-webkit-box-shadow: 1px 1px 3px #A0A0A0;\n\tfilter: progid:DXImageTransform.Microsoft.Shadow(color='#A0A0A0', Direction=135, Strength=3);\n\tbackground-color: #F0F0EE;\n}\n.ke-menu a,\n.ke-menu a:hover,\n.ke-dialog a,\n.ke-dialog a:hover {\n\tcolor: #337FE5;\n\ttext-decoration: none;\n}\n/* icons */\n.ke-icon-source {\n\tbackground-position: 0px 0px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-preview {\n\tbackground-position: 0px -16px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-print {\n\tbackground-position: 0px -32px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-undo {\n\tbackground-position: 0px -48px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-redo {\n\tbackground-position: 0px -64px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-cut {\n\tbackground-position: 0px -80px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-copy {\n\tbackground-position: 0px -96px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-paste {\n\tbackground-position: 0px -112px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-selectall {\n\tbackground-position: 0px -128px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-justifyleft {\n\tbackground-position: 0px -144px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-justifycenter {\n\tbackground-position: 0px -160px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-justifyright {\n\tbackground-position: 0px -176px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-justifyfull {\n\tbackground-position: 0px -192px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-insertorderedlist {\n\tbackground-position: 0px -208px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-insertunorderedlist {\n\tbackground-position: 0px -224px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-indent {\n\tbackground-position: 0px -240px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-outdent {\n\tbackground-position: 0px -256px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-subscript {\n\tbackground-position: 0px -272px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-superscript {\n\tbackground-position: 0px -288px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-date {\n\tbackground-position: 0px -304px;\n\twidth: 25px;\n\theight: 16px;\n}\n.ke-icon-time {\n\tbackground-position: 0px -320px;\n\twidth: 25px;\n\theight: 16px;\n}\n.ke-icon-formatblock {\n\tbackground-position: 0px -336px;\n\twidth: 25px;\n\theight: 16px;\n}\n.ke-icon-fontname {\n\tbackground-position: 0px -352px;\n\twidth: 21px;\n\theight: 16px;\n}\n.ke-icon-fontsize {\n\tbackground-position: 0px -368px;\n\twidth: 23px;\n\theight: 16px;\n}\n.ke-icon-forecolor {\n\tbackground-position: 0px -384px;\n\twidth: 20px;\n\theight: 16px;\n}\n.ke-icon-hilitecolor {\n\tbackground-position: 0px -400px;\n\twidth: 23px;\n\theight: 16px;\n}\n.ke-icon-bold {\n\tbackground-position: 0px -416px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-italic {\n\tbackground-position: 0px -432px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-underline {\n\tbackground-position: 0px -448px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-strikethrough {\n\tbackground-position: 0px -464px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-removeformat {\n\tbackground-position: 0px -480px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-image {\n\tbackground-position: 0px -496px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-flash {\n\tbackground-position: 0px -512px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-media {\n\tbackground-position: 0px -528px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-div {\n\tbackground-position: 0px -544px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-formula {\n\tbackground-position: 0px -576px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-hr {\n\tbackground-position: 0px -592px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-emoticons {\n\tbackground-position: 0px -608px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-link {\n\tbackground-position: 0px -624px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-unlink {\n\tbackground-position: 0px -640px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-fullscreen {\n\tbackground-position: 0px -656px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-about {\n\tbackground-position: 0px -672px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-plainpaste {\n\tbackground-position: 0px -704px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-wordpaste {\n\tbackground-position: 0px -720px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-table {\n\tbackground-position: 0px -784px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablemenu {\n\tbackground-position: 0px -768px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tableinsert {\n\tbackground-position: 0px -784px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tabledelete {\n\tbackground-position: 0px -800px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablecolinsertleft {\n\tbackground-position: 0px -816px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablecolinsertright {\n\tbackground-position: 0px -832px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablerowinsertabove {\n\tbackground-position: 0px -848px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablerowinsertbelow {\n\tbackground-position: 0px -864px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablecoldelete {\n\tbackground-position: 0px -880px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablerowdelete {\n\tbackground-position: 0px -896px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablecellprop {\n\tbackground-position: 0px -912px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tableprop {\n\tbackground-position: 0px -928px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-checked {\n\tbackground-position: 0px -944px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-code {\n\tbackground-position: 0px -960px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-map {\n\tbackground-position: 0px -976px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-baidumap {\n\tbackground-position: 0px -976px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-lineheight {\n\tbackground-position: 0px -992px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-clearhtml {\n\tbackground-position: 0px -1008px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-pagebreak {\n\tbackground-position: 0px -1024px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-insertfile {\n\tbackground-position: 0px -1040px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-quickformat {\n\tbackground-position: 0px -1056px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-template {\n\tbackground-position: 0px -1072px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablecellsplit {\n\tbackground-position: 0px -1088px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablerowmerge {\n\tbackground-position: 0px -1104px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablerowsplit {\n\tbackground-position: 0px -1120px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablecolmerge {\n\tbackground-position: 0px -1136px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-tablecolsplit {\n\tbackground-position: 0px -1152px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-anchor {\n\tbackground-position: 0px -1168px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-search {\n\tbackground-position: 0px -1184px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-new {\n\tbackground-position: 0px -1200px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-specialchar {\n\tbackground-position: 0px -1216px;\n\twidth: 16px;\n\theight: 16px;\n}\n.ke-icon-multiimage {\n\tbackground-position: 0px -1232px;\n\twidth: 16px;\n\theight: 16px;\n}\n/* container */\n.ke-container {\n\tdisplay: block;\n\tborder: 1px solid #CCCCCC;\n\tbackground-color: #FFF;\n\toverflow: hidden;\n\tmargin: 0;\n\tpadding: 0;\n}\n/* toolbar */\n.ke-toolbar {\n\tborder-bottom: 1px solid #CCC;\n\tbackground-color: #F0F0EE;\n\tpadding: 2px 5px;\n\ttext-align: left;\n\toverflow: hidden;\n\tzoom: 1;\n}\n.ke-toolbar-icon {\n\tbackground-repeat: no-repeat;\n\tfont-size: 0;\n\tline-height: 0;\n\toverflow: hidden;\n\tdisplay: block;\n}\n.ke-toolbar-icon-url {\n\tbackground-image: url(default.png);\n}\n.ke-toolbar .ke-outline {\n\tborder: 1px solid #F0F0EE;\n\tmargin: 1px;\n\tpadding: 1px 2px;\n\tfont-size: 0;\n\tline-height: 0;\n\toverflow: hidden;\n\tcursor: pointer;\n\tdisplay: block;\n\tfloat: left;\n}\n.ke-toolbar .ke-on {\n\tborder: 1px solid #5690D2;\n}\n.ke-toolbar .ke-selected {\n\tborder: 1px solid #5690D2;\n\tbackground-color: #E9EFF6;\n}\n.ke-toolbar .ke-disabled {\n\tcursor: default;\n}\n.ke-toolbar .ke-separator {\n\theight: 16px;\n\tmargin: 2px 3px;\n\tborder-left: 1px solid #A0A0A0;\n\tborder-right: 1px solid #FFFFFF;\n\tborder-top:0;\n\tborder-bottom:0;\n\twidth: 0;\n\tfont-size: 0;\n\tline-height: 0;\n\toverflow: hidden;\n\tdisplay: block;\n\tfloat: left;\n}\n.ke-toolbar .ke-hr {\n\toverflow: hidden;\n\theight: 1px;\n\tclear: both;\n}\n/* edit */\n.ke-edit {\n\tpadding: 0;\n}\n.ke-edit-iframe,\n.ke-edit-textarea {\n\tborder: 0;\n\tmargin: 0;\n\tpadding: 0;\n\toverflow: auto;\n}\n.ke-edit-textarea {\n\tfont: 12px/1.5 \"Consolas\", \"Monaco\", \"Bitstream Vera Sans Mono\", \"Courier New\", Courier, monospace;\n\tcolor: #000;\n\toverflow: auto;\n\tresize: none;\n}\n.ke-edit-textarea:focus {\n\toutline: none;\n}\n/* statusbar */\n.ke-statusbar {\n\tposition: relative;\n\tbackground-color: #F0F0EE;\n\tborder-top: 1px solid #CCCCCC;\n\tfont-size: 0;\n\tline-height: 0;\n\t*height: 12px;\n\toverflow: hidden;\n\ttext-align: center;\n\tcursor: s-resize;\n}\n.ke-statusbar-center-icon {\n\tbackground-position: -0px -754px;\n\twidth: 15px;\n\theight: 11px;\n\tbackground-image: url(default.png);\n}\n.ke-statusbar-right-icon {\n\tposition: absolute;\n\tright: 0;\n\tbottom: 0;\n\tcursor: se-resize;\n\tbackground-position: -5px -741px;\n\twidth: 11px;\n\theight: 11px;\n\tbackground-image: url(default.png);\n}\n/* menu */\n.ke-menu {\n\tborder: 1px solid #A0A0A0;\n\tbackground-color: #F1F1F1;\n\tcolor: #222222;\n\tpadding: 2px;\n\tfont-family: \"sans serif\",tahoma,verdana,helvetica;\n\tfont-size: 12px;\n\ttext-align: left;\n\toverflow: hidden;\n}\n.ke-menu-item {\n\tborder: 1px solid #F1F1F1;\n\tbackground-color: #F1F1F1;\n\tcolor: #222222;\n\theight: 24px;\n\toverflow: hidden;\n\tcursor: pointer;\n}\n.ke-menu-item-on {\n\tborder: 1px solid #5690D2;\n\tbackground-color: #E9EFF6;\n}\n.ke-menu-item-left {\n\twidth: 27px;\n\ttext-align: center;\n\toverflow: hidden;\n}\n.ke-menu-item-center {\n\twidth: 0;\n\theight: 24px;\n\tborder-left: 1px solid #E3E3E3;\n\tborder-right: 1px solid #FFFFFF;\n\tborder-top: 0;\n\tborder-bottom: 0;\n}\n.ke-menu-item-center-on {\n\tborder-left: 1px solid #E9EFF6;\n\tborder-right: 1px solid #E9EFF6;\n}\n.ke-menu-item-right {\n\tborder: 0;\n\tpadding: 0 0 0 5px;\n\tline-height: 24px;\n\ttext-align: left;\n\toverflow: hidden;\n}\n.ke-menu-separator {\n\tmargin: 2px 0;\n\theight: 0;\n\toverflow: hidden;\n\tborder-top: 1px solid #CCCCCC;\n\tborder-bottom: 1px solid #FFFFFF;\n\tborder-left: 0;\n\tborder-right: 0;\n}\n/* colorpicker */\n.ke-colorpicker {\n\tborder: 1px solid #A0A0A0;\n\tbackground-color: #F1F1F1;\n\tcolor: #222222;\n\tpadding: 2px;\n}\n.ke-colorpicker-table {\n\tborder:0;\n\tmargin:0;\n\tpadding:0;\n\tborder-collapse: separate;\n}\n.ke-colorpicker-cell {\n\tfont-size: 0;\n\tline-height: 0;\n\tborder: 1px solid #F0F0EE;\n\tcursor: pointer;\n\tmargin:3px;\n\tpadding:0;\n}\n.ke-colorpicker-cell-top {\n\tfont-family: \"sans serif\",tahoma,verdana,helvetica;\n\tfont-size: 12px;\n\tline-height: 24px;\n\tborder: 1px solid #F0F0EE;\n\tcursor: pointer;\n\tmargin:0;\n\tpadding:0;\n\ttext-align: center;\n}\n.ke-colorpicker-cell-on {\n\tborder: 1px solid #5690D2;\n}\n.ke-colorpicker-cell-selected {\n\tborder: 1px solid #2446AB;\n}\n.ke-colorpicker-cell-color {\n\twidth: 14px;\n\theight: 14px;\n\tmargin: 3px;\n\tpadding: 0;\n\tborder: 0;\n}\n/* dialog */\n.ke-dialog {\n\tposition: absolute;\n\tmargin: 0;\n\tpadding: 0;\n}\n.ke-dialog .ke-header {\n\twidth: 100%;\n\tmargin-bottom: 10px;\n}\n.ke-dialog .ke-header .ke-left {\n\tfloat: left;\n}\n.ke-dialog .ke-header .ke-right {\n\tfloat: right;\n}\n.ke-dialog .ke-header label {\n\tmargin-right: 0;\n\tcursor: pointer;\n\tfont-weight: normal;\n\tdisplay: inline;\n\tvertical-align: top;\n}\n.ke-dialog-content {\n\tbackground-color: #FFF;\n\twidth: 100%;\n\theight: 100%;\n\tcolor: #333;\n\tborder: 1px solid #A0A0A0;\n}\n.ke-dialog-shadow {\n\tposition: absolute;\n\tz-index: -1;\n\ttop: 0;\n\tleft: 0;\n\twidth: 100%;\n\theight: 100%;\n\tbox-shadow: 3px 3px 7px #999;\n\t-moz-box-shadow: 3px 3px 7px #999;\n\t-webkit-box-shadow: 3px 3px 7px #999;\n\tfilter: progid:DXImageTransform.Microsoft.Blur(PixelRadius='3', MakeShadow='true', ShadowOpacity='0.4');\n\tbackground-color: #F0F0EE;\n}\n.ke-dialog-header {\n\tborder:0;\n\tmargin:0;\n\tpadding: 0 10px;\n\tbackground: url(background.png) repeat scroll 0 0 #F0F0EE;\n\tborder-bottom: 1px solid #CFCFCF;\n\theight: 24px;\n\tfont: 12px/24px \"sans serif\",tahoma,verdana,helvetica;\n\ttext-align: left;\n\tcolor: #222;\n\tcursor: move;\n}\n.ke-dialog-icon-close {\n\tdisplay: block;\n\tbackground: url(default.png) no-repeat scroll 0px -688px;\n\twidth: 16px;\n\theight: 16px;\n\tposition: absolute;\n\tright: 6px;\n\ttop: 6px;\n\tcursor: pointer;\n}\n.ke-dialog-body {\n\tfont: 12px/1.5 \"sans serif\",tahoma,verdana,helvetica;\n\ttext-align: left;\n\toverflow: hidden;\n\twidth: 100%;\n}\n.ke-dialog-body textarea {\n\tdisplay: block;\n\toverflow: auto;\n\tpadding: 0;\n\tresize: none;\n}\n.ke-dialog-body textarea:focus,\n.ke-dialog-body input:focus,\n.ke-dialog-body select:focus {\n\toutline: none;\n}\n.ke-dialog-body label {\n\tmargin-right: 10px;\n\tcursor: pointer;\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tzoom: 1;\n\t*display: inline;\n}\n.ke-dialog-body img {\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tzoom: 1;\n\t*display: inline;\n}\n.ke-dialog-body select {\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tzoom: 1;\n\t*display: inline;\n\twidth: auto;\n}\n.ke-dialog-body .ke-textarea {\n\tdisplay: block;\n\twidth: 408px;\n\theight: 260px;\n\tfont-family: \"sans serif\",tahoma,verdana,helvetica;\n\tfont-size: 12px;\n\tborder-color: #848484 #E0E0E0 #E0E0E0 #848484;\n\tborder-style: solid;\n\tborder-width: 1px;\n}\n.ke-dialog-body .ke-form {\n\tmargin: 0;\n\tpadding: 0;\n}\n.ke-dialog-loading {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 1px;\n\tz-index: 1;\n\ttext-align: center;\n}\n.ke-dialog-loading-content {\n\tbackground: url(\"../common/loading.gif\") no-repeat;\n    color: #666;\n    font-size: 14px;\n    font-weight: bold;\n    height: 31px;\n    line-height: 31px;\n    padding-left: 36px;\n}\n.ke-dialog-row {\n\tmargin-bottom: 10px;\n}\n.ke-dialog-footer {\n\tfont: 12px/1 \"sans serif\",tahoma,verdana,helvetica;\n\ttext-align: right;\n\tpadding:0 0 5px 0;\n\tbackground-color: #FFF;\n\twidth: 100%;\n}\n.ke-dialog-preview,\n.ke-dialog-yes {\n\tmargin: 5px;\n}\n.ke-dialog-no {\n\tmargin: 5px 10px 5px 5px;\n}\n.ke-dialog-mask {\n\tbackground-color:#FFF;\n\tfilter:alpha(opacity=50);\n\topacity:0.5;\n}\n.ke-button-common {\n\tbackground: url(background.png) no-repeat;\n\tcursor: pointer;\n\theight: 23px;\n\tline-height: 23px;\n\toverflow: visible;\n\tdisplay: inline-block;\n\tvertical-align: top;\n\tcursor: pointer;\n}\n.ke-button-outer {\n\tbackground-position: 0 -25px;\n\tpadding: 0;\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tzoom: 1;\n\t*display: inline;\n}\n.ke-button {\n\tbackground-position: right -25px;\n\tpadding: 0 14px 0 12px;\n\tmargin: 0 0 0 2px;\n\tfont-family: \"sans serif\",tahoma,verdana,helvetica;\n\tborder: 0 none;\n\tcolor: #333;\n\tfont-size: 12px;\n\ttext-decoration: none;\n}\n/* inputbox */\n.ke-input-text {\n\tbackground-color:#FFFFFF;\n\tfont-family: \"sans serif\",tahoma,verdana,helvetica;\n\tfont-size: 12px;\n\tline-height: 17px;\n\theight: 17px;\n\tpadding: 2px 4px;\n\tborder-color: #848484 #E0E0E0 #E0E0E0 #848484;\n\tborder-style: solid;\n\tborder-width: 1px;\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tzoom: 1;\n\t*display: inline;\n}\n.ke-input-number {\n\twidth: 50px;\n}\n.ke-input-color {\n\tborder: 1px solid #A0A0A0;\n\tbackground-color: #FFFFFF;\n\tfont-size: 12px;\n\twidth: 60px;\n\theight: 20px;\n\tline-height: 20px;\n\tpadding-left: 5px;\n\toverflow: hidden;\n\tcursor: pointer;\n\tdisplay: -moz-inline-stack;\n\tdisplay: inline-block;\n\tvertical-align: middle;\n\tzoom: 1;\n\t*display: inline;\n}\n.ke-upload-button {\n\tposition: relative;\n}\n.ke-upload-area {\n\tposition: relative;\n\toverflow: hidden;\n\tmargin: 0;\n\tpadding: 0;\n\t*height: 25px;\n}\n.ke-upload-area .ke-upload-file {\n\tposition: absolute;\n\tfont-size: 60px;\n\ttop: 0;\n\tright: 0;\n\tpadding: 0;\n\tmargin: 0;\n\tz-index: 811212;\n\tborder: 0 none;\n\topacity: 0;\n\tfilter: alpha(opacity=0);\n}\n/* tabs */\n.ke-tabs {\n\tfont: 12px/1 \"sans serif\",tahoma,verdana,helvetica;\n\tborder-bottom:1px solid #A0A0A0;\n\tpadding-left:5px;\n\tmargin-bottom:20px;\n}\n.ke-tabs-ul  {\n\tlist-style-image:none;\n\tlist-style-position:outside;\n\tlist-style-type:none;\n\tmargin:0;\n\tpadding:0;\n}\n.ke-tabs-li {\n\tposition: relative;\n\tborder: 1px solid #A0A0A0;\n\tbackground-color: #F0F0EE;\n\tmargin: 0 2px -1px 0;\n\tpadding: 0 20px;\n\tfloat: left;\n\tline-height: 25px;\n\ttext-align: center;\n\tcolor: #555555;\n\tcursor: pointer;\n}\n.ke-tabs-li-selected {\n\tbackground-color: #FFF;\n\tborder-bottom: 1px solid #FFF;\n\tcolor: #000;\n\tcursor: default;\n}\n.ke-tabs-li-on {\n\tbackground-color: #FFF;\n\tcolor: #000;\n}\n/* progressbar */\n.ke-progressbar {\n\tposition: relative;\n\tmargin: 0;\n\tpadding: 0;\n}\n.ke-progressbar-bar {\n\tborder: 1px solid #6FA5DB;\n\twidth: 80px;\n\theight: 5px;\n\tmargin: 10px 10px 0 10px;\n\tpadding: 0;\n}\n.ke-progressbar-bar-inner {\n\twidth: 0;\n\theight: 5px;\n\tbackground-color: #6FA5DB;\n\toverflow: hidden;\n\tmargin: 0;\n\tpadding: 0;\n}\n.ke-progressbar-percent {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 40%;\n\tdisplay: none;\n}\n/* swfupload */\n.ke-swfupload-top {\n\tposition: relative;\n\tmargin-bottom: 10px;\n\t_width: 608px;\n}\n.ke-swfupload-button {\n\theight: 23px;\n\tline-height: 23px;\n}\n.ke-swfupload-desc {\n\tpadding: 0 10px;\n\theight: 23px;\n\tline-height: 23px;\n}\n.ke-swfupload-startupload {\n\tposition: absolute;\n\ttop: 0;\n\tright: 0;\n}\n.ke-swfupload-body {\n\toverflow: scroll;\n\tbackground-color:#FFFFFF;\n\tborder-color: #848484 #E0E0E0 #E0E0E0 #848484;\n\tborder-style: solid;\n\tborder-width: 1px;\n\twidth: auto;\n\theight: 370px;\n\tpadding: 5px;\n}\n.ke-swfupload-body .ke-item {\n\twidth: 100px;\n\tmargin: 5px;\n}\n.ke-swfupload-body .ke-photo {\n\tposition: relative;\n\tborder: 1px solid #DDDDDD;\n\tbackground-color:#FFFFFF;\n\tpadding: 10px;\n}\n.ke-swfupload-body .ke-delete {\n\tdisplay: block;\n\tbackground: url(default.png) no-repeat scroll 0px -688px;\n\twidth: 16px;\n\theight: 16px;\n\tposition: absolute;\n\tright: 0;\n\ttop: 0;\n\tcursor: pointer;\n}\n.ke-swfupload-body .ke-status  {\n\tposition: absolute;\n\tleft: 0;\n\tbottom: 5px;\n\twidth: 100px;\n\theight: 17px;\n}\n.ke-swfupload-body .ke-message  {\n\twidth: 100px;\n\ttext-align: center;\n\toverflow: hidden;\n\theight:17px;\n}\n.ke-swfupload-body .ke-error  {\n\tcolor: red;\n}\n.ke-swfupload-body .ke-name {\n\twidth: 100px;\n\ttext-align: center;\n\toverflow: hidden;\n\theight:16px;\n}\n.ke-swfupload-body .ke-on {\n\tborder: 1px solid #5690D2;\n\tbackground-color: #E9EFF6;\n}\n\n/* emoticons */\n.ke-plugin-emoticons {\n\tposition: relative;\n}\n.ke-plugin-emoticons .ke-preview {\n\tposition: absolute;\n\ttext-align: center;\n\tmargin: 2px;\n\tpadding: 10px;\n\ttop: 0;\n\tborder: 1px solid #A0A0A0;\n\tbackground-color: #FFFFFF;\n\tdisplay: none;\n}\n.ke-plugin-emoticons .ke-preview-img {\n\tborder:0;\n\tmargin:0;\n\tpadding:0;\n}\n.ke-plugin-emoticons .ke-table {\n\tborder:0;\n\tmargin:0;\n\tpadding:0;\n\tborder-collapse:separate;\n}\n.ke-plugin-emoticons .ke-cell {\n\tmargin:0;\n\tpadding:1px;\n\tborder:1px solid #F0F0EE;\n\tcursor:pointer;\n}\n.ke-plugin-emoticons .ke-on {\n\tborder: 1px solid #5690D2;\n\tbackground-color: #E9EFF6;\n}\n.ke-plugin-emoticons .ke-img {\n\tdisplay:block;\n\tbackground-repeat:no-repeat;\n\toverflow:hidden;\n\tmargin:2px;\n\twidth:24px;\n\theight:24px;\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n}\n.ke-plugin-emoticons .ke-page {\n\ttext-align: right;\n\tmargin: 5px;\n\tpadding: 0;\n\tborder: 0;\n\tfont: 12px/1 \"sans serif\",tahoma,verdana,helvetica;\n\tcolor: #333;\n\ttext-decoration: none;\n}\n.ke-plugin-plainpaste-textarea,\n.ke-plugin-wordpaste-iframe {\n\tdisplay: block;\n\twidth: 408px;\n\theight: 260px;\n\tfont-family: \"sans serif\",tahoma,verdana,helvetica;\n\tfont-size: 12px;\n\tborder-color: #848484 #E0E0E0 #E0E0E0 #848484;\n\tborder-style: solid;\n\tborder-width: 1px;\n}\n/* filemanager */\n.ke-plugin-filemanager-header {\n\twidth: 100%;\n\tmargin-bottom: 10px;\n}\n.ke-plugin-filemanager-header .ke-left {\n\tfloat: left;\n}\n.ke-plugin-filemanager-header .ke-right {\n\tfloat: right;\n}\n.ke-plugin-filemanager-body {\n\toverflow: scroll;\n\tbackground-color:#FFFFFF;\n\tborder-color: #848484 #E0E0E0 #E0E0E0 #848484;\n\tborder-style: solid;\n\tborder-width: 1px;\n\twidth: auto;\n\theight: 370px;\n\tpadding: 5px;\n}\n.ke-plugin-filemanager-body .ke-item {\n\twidth: 100px;\n\tmargin: 5px;\n}\n.ke-plugin-filemanager-body .ke-photo {\n\tborder: 1px solid #DDDDDD;\n\tbackground-color:#FFFFFF;\n\tpadding: 10px;\n}\n.ke-plugin-filemanager-body .ke-name {\n\twidth: 100px;\n\ttext-align: center;\n\toverflow: hidden;\n\theight:16px;\n}\n.ke-plugin-filemanager-body .ke-on {\n\tborder: 1px solid #5690D2;\n\tbackground-color: #E9EFF6;\n}\n.ke-plugin-filemanager-body .ke-table {\n\twidth: 95%;\n\tborder: 0;\n\tmargin: 0;\n\tpadding: 0;\n\tborder-collapse: separate;\n}\n.ke-plugin-filemanager-body .ke-table .ke-cell {\n\tmargin: 0;\n\tpadding: 0;\n\tborder: 0;\n}\n.ke-plugin-filemanager-body .ke-table .ke-name {\n\twidth: 55%;\n\ttext-align: left;\n}\n.ke-plugin-filemanager-body .ke-table .ke-size {\n\twidth: 15%;\n\ttext-align: left;\n}\n.ke-plugin-filemanager-body .ke-table .ke-datetime {\n\twidth: 30%;\n\ttext-align: center;\n}\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/themes/qq/qq.css",
    "content": "/* container */\n.ke-container-qq {\n\tdisplay: block;\n\tborder: 1px solid #c3c3c3;\n\tbackground-color: #FFF;\n\toverflow: hidden;\n\tmargin: 0;\n\tpadding: 0;\n}\n/* toolbar */\n.ke-container-qq .ke-toolbar {\n\tborder-bottom: 1px solid #c3c3c3;\n\tbackground-color: #FFFFFF;\n\tpadding: 2px 5px;\n\ttext-align: left;\n\toverflow: hidden;\n\tzoom: 1;\n}\n.ke-toolbar-icon-url {\n\tbackground-image: url(editor.gif);\n\twidth:18px;\n\t*xwidth:20px;\n\theight:18px;\n\t*xheight:20px;\n}\n.ke-icon-checked{\n\tbackground-image: url(../default/default.png);\n\twidth:16px;\n\theight:16px;\n}\n.ke-container-qq .ke-icon-bold{\n\tbackground-position: 4px 1px;\n}\n.ke-container-qq .ke-icon-italic{\n\tbackground-position: -27px 1px;\n}\n.ke-container-qq .ke-icon-italic{\n\tbackground-position: -28px 1px;\n}\n.ke-container-qq .ke-icon-underline{\n\tbackground-position: -60px 1px;\n}\n.ke-container-qq .ke-icon-fontname{\n\tbackground-position: -95px 1px;\n}\n.ke-container-qq .ke-icon-fontsize{\n\tbackground-position: -128px 1px;\n}\n.ke-container-qq .ke-icon-forecolor{\n\tbackground-position: -159px 1px;\n}\n.ke-container-qq .ke-icon-hilitecolor{\n\tbackground-position: -190px 1px;\n}\n.ke-container-qq .ke-icon-plug-align{\n\tbackground-position: -223px 1px;\n}\n.plug-align-justifyleft{\n\tbackground-position: -350px 1px;\n}\n.plug-align-justifycenter{\n\tbackground-position: -382px 1px;\n}\n.plug-align-justifyright{\n\tbackground-position: -414px 1px;\n}\n.plug-order-insertorderedlist{\n\tbackground-position: -446px 1px;\n}\n.plug-order-insertunorderedlist{\n\tbackground-position: -477px 1px;\n}\n.plug-indent-indent{\n\tbackground-position: -513px 1px;\n}\n.plug-indent-outdent{\n\tbackground-position: -545px 1px;\n}\n.ke-container-qq .ke-icon-plug-order{\n\tbackground-position: -255px 1px;\n}\n.ke-container-qq .ke-icon-plug-indent{\n\tbackground-position: -287px 1px;\n}\n.ke-container-qq .ke-icon-link{\n\tbackground-position: -319px 1px;\n}\n\n.ke-container-qq .ke-toolbar .ke-outline {\n\tcursor: default;\n\tpadding:0px;\n\tborder:1px solid #fff;\n}\n.ke-container-qq .ke-toolbar .ke-on {\n\tborder-left:1px solid white;\n\tborder-top:1px solid white;\n\tborder-right:1px solid gray;\n\tborder-bottom:1px solid gray;\n\tbackground-color: #FFFFFF;\n}\n.ke-container-qq .ke-toolbar .ke-selected {\n\tborder-left:1px solid gray;\n\tborder-top:1px solid gray;\n\tborder-right:1px solid white;\n\tborder-bottom:1px solid white;\n\tbackground-color: #FFFFFF;\n}\n.ke-container-qq .ke-toolbar  .ke-disabled {\n\tcursor: default;\n}\n\n.ke-colorpicker-qq{\n\tbackground:#fff;\n}\n/* statusbar */\n.ke-container-qq .ke-statusbar {\n\tdisplay:none;\n}\n/* menu */\n.ke-menu-qq {\n\tborder:1px solid #a6a6a6;\n\tposition:absolute;\n\tbackground:#fff;\n\t-moz-box-shadow:2px 2px 4px #DDDDDD;\n\tz-index:999;\n\tleft:-400px;\n\ttop:-386px;\n\tright:218px;\n\twidth:130px;\n}\n.ke-menu-qq .ke-menu-item {\n\tpadding:0px;\n\tbackground:#fff;\n}\n.ke-menu-qq .ke-menu-item-on {\n\tborder:1px solid #000080;background:#FFEEC2;color:#036;\n}\n.ke-menu-qq .ke-toolbar .ke-selected {\n\tborder:1px solid #9a9afb;\n}\n.ke-menu-qq .ke-menu-item-left{\n\twidth:auto;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/kindeditor/themes/simple/simple.css",
    "content": "/* container */\n.ke-container-simple {\n\tdisplay: block;\n\tborder: 1px solid #CCC;\n\tbackground-color: #FFF;\n\toverflow: hidden;\n}\n/* toolbar */\n.ke-container-simple .ke-toolbar {\n\tborder-bottom: 1px solid #CCC;\n\tbackground-color: #FFF;\n\tpadding: 2px 5px;\n\toverflow: hidden;\n}\n.ke-container-simple .ke-toolbar .ke-outline {\n\tborder: 1px solid #FFF;\n\tbackground-color: transparent;\n\tmargin: 1px;\n\tpadding: 1px 2px;\n\tfont-size: 0;\n\tline-height: 0;\n\toverflow: hidden;\n\tcursor: pointer;\n}\n.ke-container-simple .ke-toolbar .ke-on {\n\tborder: 1px solid #5690D2;\n}\n.ke-container-simple .ke-toolbar .ke-selected {\n\tborder: 1px solid #5690D2;\n\tbackground-color: #E9EFF6;\n}\n.ke-container-simple .ke-toolbar  .ke-disabled {\n\tcursor: default;\n}\n/* statusbar */\n.ke-container-simple .ke-statusbar {\n\tposition: relative;\n\tbackground-color: #FFF;\n\tborder-top: 1px solid #CCCCCC;\n\tfont-size: 0;\n\tline-height: 0;\n\t*height: 12px;\n\toverflow: hidden;\n\ttext-align: center;\n\tcursor: s-resize;\n}\n/* menu */\n.ke-menu-simple {\n\tborder: 1px solid #A0A0A0;\n\tbackground-color: #FFF;\n\tcolor: #222222;\n\tpadding: 2px;\n\tfont-family: \"sans serif\",tahoma,verdana,helvetica;\n\tfont-size: 12px;\n\ttext-align: left;\n\toverflow: hidden;\n}\n.ke-menu-simple .ke-menu-item {\n\tborder: 1px solid #FFF;\n\tbackground-color: #FFF;\n\tcolor: #222222;\n\theight: 24px;\n\toverflow: hidden;\n\tcursor: pointer;\n}\n.ke-menu-simple .ke-menu-item-on {\n\tborder: 1px solid #5690D2;\n\tbackground-color: #FFF;\n}\n/* colorpicker */\n.ke-colorpicker-simple {\n\tborder: 1px solid #A0A0A0;\n\tbackground-color: #FEFEFE;\n\tcolor: #222222;\n\tpadding: 2px;\n}\n.ke-colorpicker-simple .ke-colorpicker-cell {\n\tfont-size: 0;\n\tline-height: 0;\n\tborder: 1px solid #FEFEFE;\n\tcursor: pointer;\n\tmargin:3px;\n\tpadding:0;\n}\n.ke-colorpicker-simple .ke-colorpicker-cell-top {\n\tfont-family: \"sans serif\",tahoma,verdana,helvetica;\n\tfont-size: 12px;\n\tline-height: 24px;\n\tborder: 1px solid #FEFEFE;\n\tcursor: pointer;\n\tmargin:0;\n\tpadding:0;\n\ttext-align: center;\n}\n.ke-colorpicker-simple .ke-colorpicker-cell-on {\n\tborder: 1px solid #5690D2;\n}\n.ke-colorpicker-simple .ke-colorpicker-cell-selected {\n\tborder: 1px solid #2446AB;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/layer/2.4/layer.js",
    "content": "/*! layer-v2.4 弹层组件 License LGPL  http://layer.layui.com/ By 贤心 */\n;!function(a,b){\"use strict\";var c,d,e={getPath:function(){var a=document.scripts,b=a[a.length-1],c=b.src;if(!b.getAttribute(\"merge\"))return c.substring(0,c.lastIndexOf(\"/\")+1)}(),enter:function(a){13===a.keyCode&&a.preventDefault()},config:{},end:{},btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],type:[\"dialog\",\"page\",\"iframe\",\"loading\",\"tips\"]},f={v:\"2.4\",ie6:!!a.ActiveXObject&&!a.XMLHttpRequest,index:0,path:e.getPath,config:function(a,b){var d=0;return a=a||{},f.cache=e.config=c.extend(e.config,a),f.path=e.config.path||f.path,\"string\"==typeof a.extend&&(a.extend=[a.extend]),f.use(\"skin/layer.css\",a.extend&&a.extend.length>0?function g(){var c=a.extend;f.use(c[c[d]?d:d-1],d<c.length?function(){return++d,g}():b)}():b),this},use:function(a,b,d){var e=c(\"head\")[0],a=a.replace(/\\s/g,\"\"),g=/\\.css$/.test(a),h=document.createElement(g?\"link\":\"script\"),i=\"layui_layer_\"+a.replace(/\\.|\\//g,\"\");return f.path?(g&&(h.rel=\"stylesheet\"),h[g?\"href\":\"src\"]=/^http:\\/\\//.test(a)?a:f.path+a,h.id=i,c(\"#\"+i)[0]||e.appendChild(h),function j(){(g?1989===parseInt(c(\"#\"+i).css(\"width\")):f[d||i])?function(){b&&b();try{g||e.removeChild(h)}catch(a){}}():setTimeout(j,100)}(),this):void 0},ready:function(a,b){var d=\"function\"==typeof a;return d&&(b=a),f.config(c.extend(e.config,function(){return d?{}:{path:a}}()),b),this},alert:function(a,b,d){var e=\"function\"==typeof b;return e&&(d=b),f.open(c.extend({content:a,yes:d},e?{}:b))},confirm:function(a,b,d,g){var h=\"function\"==typeof b;return h&&(g=d,d=b),f.open(c.extend({content:a,btn:e.btn,yes:d,btn2:g},h?{}:b))},msg:function(a,d,g){var i=\"function\"==typeof d,j=e.config.skin,k=(j?j+\" \"+j+\"-msg\":\"\")||\"layui-layer-msg\",l=h.anim.length-1;return i&&(g=d),f.open(c.extend({content:a,time:3e3,shade:!1,skin:k,title:!1,closeBtn:!1,btn:!1,end:g},i&&!e.config.skin?{skin:k+\" layui-layer-hui\",shift:l}:function(){return d=d||{},(-1===d.icon||d.icon===b&&!e.config.skin)&&(d.skin=k+\" \"+(d.skin||\"layui-layer-hui\")),d}()))},load:function(a,b){return f.open(c.extend({type:3,icon:a||0,shade:.01},b))},tips:function(a,b,d){return f.open(c.extend({type:4,content:[a,b],closeBtn:!1,time:3e3,shade:!1,fix:!1,maxWidth:210},d))}},g=function(a){var b=this;b.index=++f.index,b.config=c.extend({},b.config,e.config,a),b.creat()};g.pt=g.prototype;var h=[\"layui-layer\",\".layui-layer-title\",\".layui-layer-main\",\".layui-layer-dialog\",\"layui-layer-iframe\",\"layui-layer-content\",\"layui-layer-btn\",\"layui-layer-close\"];h.anim=[\"layer-anim\",\"layer-anim-01\",\"layer-anim-02\",\"layer-anim-03\",\"layer-anim-04\",\"layer-anim-05\",\"layer-anim-06\"],g.pt.config={type:0,shade:.3,fix:!0,move:h[1],title:\"&#x4FE1;&#x606F;\",offset:\"auto\",area:\"auto\",closeBtn:1,time:0,zIndex:19891014,maxWidth:360,shift:0,icon:-1,scrollbar:!0,tips:2},g.pt.vessel=function(a,b){var c=this,d=c.index,f=c.config,g=f.zIndex+d,i=\"object\"==typeof f.title,j=f.maxmin&&(1===f.type||2===f.type),k=f.title?'<div class=\"layui-layer-title\" style=\"'+(i?f.title[1]:\"\")+'\">'+(i?f.title[0]:f.title)+\"</div>\":\"\";return f.zIndex=g,b([f.shade?'<div class=\"layui-layer-shade\" id=\"layui-layer-shade'+d+'\" times=\"'+d+'\" style=\"'+(\"z-index:\"+(g-1)+\"; background-color:\"+(f.shade[1]||\"#000\")+\"; opacity:\"+(f.shade[0]||f.shade)+\"; filter:alpha(opacity=\"+(100*f.shade[0]||100*f.shade)+\");\")+'\"></div>':\"\",'<div class=\"'+h[0]+(\" layui-layer-\"+e.type[f.type])+(0!=f.type&&2!=f.type||f.shade?\"\":\" layui-layer-border\")+\" \"+(f.skin||\"\")+'\" id=\"'+h[0]+d+'\" type=\"'+e.type[f.type]+'\" times=\"'+d+'\" showtime=\"'+f.time+'\" conType=\"'+(a?\"object\":\"string\")+'\" style=\"z-index: '+g+\"; width:\"+f.area[0]+\";height:\"+f.area[1]+(f.fix?\"\":\";position:absolute;\")+'\">'+(a&&2!=f.type?\"\":k)+'<div id=\"'+(f.id||\"\")+'\" class=\"layui-layer-content'+(0==f.type&&-1!==f.icon?\" layui-layer-padding\":\"\")+(3==f.type?\" layui-layer-loading\"+f.icon:\"\")+'\">'+(0==f.type&&-1!==f.icon?'<i class=\"layui-layer-ico layui-layer-ico'+f.icon+'\"></i>':\"\")+(1==f.type&&a?\"\":f.content||\"\")+'</div><span class=\"layui-layer-setwin\">'+function(){var a=j?'<a class=\"layui-layer-min\" href=\"javascript:;\"><cite></cite></a><a class=\"layui-layer-ico layui-layer-max\" href=\"javascript:;\"></a>':\"\";return f.closeBtn&&(a+='<a class=\"layui-layer-ico '+h[7]+\" \"+h[7]+(f.title?f.closeBtn:4==f.type?\"1\":\"2\")+'\" href=\"javascript:;\"></a>'),a}()+\"</span>\"+(f.btn?function(){var a=\"\";\"string\"==typeof f.btn&&(f.btn=[f.btn]);for(var b=0,c=f.btn.length;c>b;b++)a+='<a class=\"'+h[6]+b+'\">'+f.btn[b]+\"</a>\";return'<div class=\"'+h[6]+'\">'+a+\"</div>\"}():\"\")+\"</div>\"],k),c},g.pt.creat=function(){var a=this,b=a.config,g=a.index,i=b.content,j=\"object\"==typeof i;if(!c(\"#\"+b.id)[0]){switch(\"string\"==typeof b.area&&(b.area=\"auto\"===b.area?[\"\",\"\"]:[b.area,\"\"]),b.type){case 0:b.btn=\"btn\"in b?b.btn:e.btn[0],f.closeAll(\"dialog\");break;case 2:var i=b.content=j?b.content:[b.content||\"http://layer.layui.com\",\"auto\"];b.content='<iframe scrolling=\"'+(b.content[1]||\"auto\")+'\" allowtransparency=\"true\" id=\"'+h[4]+g+'\" name=\"'+h[4]+g+'\" onload=\"this.className=\\'\\';\" class=\"layui-layer-load\" frameborder=\"0\" src=\"'+b.content[0]+'\"></iframe>';break;case 3:b.title=!1,b.closeBtn=!1,-1===b.icon&&0===b.icon,f.closeAll(\"loading\");break;case 4:j||(b.content=[b.content,\"body\"]),b.follow=b.content[1],b.content=b.content[0]+'<i class=\"layui-layer-TipsG\"></i>',b.title=!1,b.tips=\"object\"==typeof b.tips?b.tips:[b.tips,!0],b.tipsMore||f.closeAll(\"tips\")}a.vessel(j,function(d,e){c(\"body\").append(d[0]),j?function(){2==b.type||4==b.type?function(){c(\"body\").append(d[1])}():function(){i.parents(\".\"+h[0])[0]||(i.show().addClass(\"layui-layer-wrap\").wrap(d[1]),c(\"#\"+h[0]+g).find(\".\"+h[5]).before(e))}()}():c(\"body\").append(d[1]),a.layero=c(\"#\"+h[0]+g),b.scrollbar||h.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",g)}).auto(g),2==b.type&&f.ie6&&a.layero.find(\"iframe\").attr(\"src\",i[0]),c(document).off(\"keydown\",e.enter).on(\"keydown\",e.enter),a.layero.on(\"keydown\",function(a){c(document).off(\"keydown\",e.enter)}),4==b.type?a.tips():a.offset(),b.fix&&d.on(\"resize\",function(){a.offset(),(/^\\d+%$/.test(b.area[0])||/^\\d+%$/.test(b.area[1]))&&a.auto(g),4==b.type&&a.tips()}),b.time<=0||setTimeout(function(){f.close(a.index)},b.time),a.move().callback(),h.anim[b.shift]&&a.layero.addClass(h.anim[b.shift])}},g.pt.auto=function(a){function b(a){a=g.find(a),a.height(i[1]-j-k-2*(0|parseFloat(a.css(\"padding\"))))}var e=this,f=e.config,g=c(\"#\"+h[0]+a);\"\"===f.area[0]&&f.maxWidth>0&&(/MSIE 7/.test(navigator.userAgent)&&f.btn&&g.width(g.innerWidth()),g.outerWidth()>f.maxWidth&&g.width(f.maxWidth));var i=[g.innerWidth(),g.innerHeight()],j=g.find(h[1]).outerHeight()||0,k=g.find(\".\"+h[6]).outerHeight()||0;switch(f.type){case 2:b(\"iframe\");break;default:\"\"===f.area[1]?f.fix&&i[1]>=d.height()&&(i[1]=d.height(),b(\".\"+h[5])):b(\".\"+h[5])}return e},g.pt.offset=function(){var a=this,b=a.config,c=a.layero,e=[c.outerWidth(),c.outerHeight()],f=\"object\"==typeof b.offset;a.offsetTop=(d.height()-e[1])/2,a.offsetLeft=(d.width()-e[0])/2,f?(a.offsetTop=b.offset[0],a.offsetLeft=b.offset[1]||a.offsetLeft):\"auto\"!==b.offset&&(a.offsetTop=b.offset,\"rb\"===b.offset&&(a.offsetTop=d.height()-e[1],a.offsetLeft=d.width()-e[0])),b.fix||(a.offsetTop=/%$/.test(a.offsetTop)?d.height()*parseFloat(a.offsetTop)/100:parseFloat(a.offsetTop),a.offsetLeft=/%$/.test(a.offsetLeft)?d.width()*parseFloat(a.offsetLeft)/100:parseFloat(a.offsetLeft),a.offsetTop+=d.scrollTop(),a.offsetLeft+=d.scrollLeft()),c.css({top:a.offsetTop,left:a.offsetLeft})},g.pt.tips=function(){var a=this,b=a.config,e=a.layero,f=[e.outerWidth(),e.outerHeight()],g=c(b.follow);g[0]||(g=c(\"body\"));var i={width:g.outerWidth(),height:g.outerHeight(),top:g.offset().top,left:g.offset().left},j=e.find(\".layui-layer-TipsG\"),k=b.tips[0];b.tips[1]||j.remove(),i.autoLeft=function(){i.left+f[0]-d.width()>0?(i.tipLeft=i.left+i.width-f[0],j.css({right:12,left:\"auto\"})):i.tipLeft=i.left},i.where=[function(){i.autoLeft(),i.tipTop=i.top-f[1]-10,j.removeClass(\"layui-layer-TipsB\").addClass(\"layui-layer-TipsT\").css(\"border-right-color\",b.tips[1])},function(){i.tipLeft=i.left+i.width+10,i.tipTop=i.top,j.removeClass(\"layui-layer-TipsL\").addClass(\"layui-layer-TipsR\").css(\"border-bottom-color\",b.tips[1])},function(){i.autoLeft(),i.tipTop=i.top+i.height+10,j.removeClass(\"layui-layer-TipsT\").addClass(\"layui-layer-TipsB\").css(\"border-right-color\",b.tips[1])},function(){i.tipLeft=i.left-f[0]-10,i.tipTop=i.top,j.removeClass(\"layui-layer-TipsR\").addClass(\"layui-layer-TipsL\").css(\"border-bottom-color\",b.tips[1])}],i.where[k-1](),1===k?i.top-(d.scrollTop()+f[1]+16)<0&&i.where[2]():2===k?d.width()-(i.left+i.width+f[0]+16)>0||i.where[3]():3===k?i.top-d.scrollTop()+i.height+f[1]+16-d.height()>0&&i.where[0]():4===k&&f[0]+16-i.left>0&&i.where[1](),e.find(\".\"+h[5]).css({\"background-color\":b.tips[1],\"padding-right\":b.closeBtn?\"30px\":\"\"}),e.css({left:i.tipLeft-(b.fix?d.scrollLeft():0),top:i.tipTop-(b.fix?d.scrollTop():0)})},g.pt.move=function(){var a=this,b=a.config,e={setY:0,moveLayer:function(){var a=e.layero,b=parseInt(a.css(\"margin-left\")),c=parseInt(e.move.css(\"left\"));0===b||(c-=b),\"fixed\"!==a.css(\"position\")&&(c-=a.parent().offset().left,e.setY=0),a.css({left:c,top:parseInt(e.move.css(\"top\"))-e.setY})}},f=a.layero.find(b.move);return b.move&&f.attr(\"move\",\"ok\"),f.css({cursor:b.move?\"move\":\"auto\"}),c(b.move).on(\"mousedown\",function(a){if(a.preventDefault(),\"ok\"===c(this).attr(\"move\")){e.ismove=!0,e.layero=c(this).parents(\".\"+h[0]);var f=e.layero.offset().left,g=e.layero.offset().top,i=e.layero.outerWidth()-6,j=e.layero.outerHeight()-6;c(\"#layui-layer-moves\")[0]||c(\"body\").append('<div id=\"layui-layer-moves\" class=\"layui-layer-moves\" style=\"left:'+f+\"px; top:\"+g+\"px; width:\"+i+\"px; height:\"+j+'px; z-index:2147483584\"></div>'),e.move=c(\"#layui-layer-moves\"),b.moveType&&e.move.css({visibility:\"hidden\"}),e.moveX=a.pageX-e.move.position().left,e.moveY=a.pageY-e.move.position().top,\"fixed\"!==e.layero.css(\"position\")||(e.setY=d.scrollTop())}}),c(document).mousemove(function(a){if(e.ismove){var c=a.pageX-e.moveX,f=a.pageY-e.moveY;if(a.preventDefault(),!b.moveOut){e.setY=d.scrollTop();var g=d.width()-e.move.outerWidth(),h=e.setY;0>c&&(c=0),c>g&&(c=g),h>f&&(f=h),f>d.height()-e.move.outerHeight()+e.setY&&(f=d.height()-e.move.outerHeight()+e.setY)}e.move.css({left:c,top:f}),b.moveType&&e.moveLayer(),c=f=g=h=null}}).mouseup(function(){try{e.ismove&&(e.moveLayer(),e.move.remove(),b.moveEnd&&b.moveEnd()),e.ismove=!1}catch(a){e.ismove=!1}}),a},g.pt.callback=function(){function a(){var a=g.cancel&&g.cancel(b.index,d);a===!1||f.close(b.index)}var b=this,d=b.layero,g=b.config;b.openLayer(),g.success&&(2==g.type?d.find(\"iframe\").on(\"load\",function(){g.success(d,b.index)}):g.success(d,b.index)),f.ie6&&b.IE6(d),d.find(\".\"+h[6]).children(\"a\").on(\"click\",function(){var a=c(this).index();if(0===a)g.yes?g.yes(b.index,d):g.btn1?g.btn1(b.index,d):f.close(b.index);else{var e=g[\"btn\"+(a+1)]&&g[\"btn\"+(a+1)](b.index,d);e===!1||f.close(b.index)}}),d.find(\".\"+h[7]).on(\"click\",a),g.shadeClose&&c(\"#layui-layer-shade\"+b.index).on(\"click\",function(){f.close(b.index)}),d.find(\".layui-layer-min\").on(\"click\",function(){var a=g.min&&g.min(d);a===!1||f.min(b.index,g)}),d.find(\".layui-layer-max\").on(\"click\",function(){c(this).hasClass(\"layui-layer-maxmin\")?(f.restore(b.index),g.restore&&g.restore(d)):(f.full(b.index,g),setTimeout(function(){g.full&&g.full(d)},100))}),g.end&&(e.end[b.index]=g.end)},e.reselect=function(){c.each(c(\"select\"),function(a,b){var d=c(this);d.parents(\".\"+h[0])[0]||1==d.attr(\"layer\")&&c(\".\"+h[0]).length<1&&d.removeAttr(\"layer\").show(),d=null})},g.pt.IE6=function(a){function b(){a.css({top:f+(e.config.fix?d.scrollTop():0)})}var e=this,f=a.offset().top;b(),d.scroll(b),c(\"select\").each(function(a,b){var d=c(this);d.parents(\".\"+h[0])[0]||\"none\"===d.css(\"display\")||d.attr({layer:\"1\"}).hide(),d=null})},g.pt.openLayer=function(){var a=this;f.zIndex=a.config.zIndex,f.setTop=function(a){var b=function(){f.zIndex++,a.css(\"z-index\",f.zIndex+1)};return f.zIndex=parseInt(a[0].style.zIndex),a.on(\"mousedown\",b),f.zIndex}},e.record=function(a){var b=[a.width(),a.height(),a.position().top,a.position().left+parseFloat(a.css(\"margin-left\"))];a.find(\".layui-layer-max\").addClass(\"layui-layer-maxmin\"),a.attr({area:b})},e.rescollbar=function(a){h.html.attr(\"layer-full\")==a&&(h.html[0].style.removeProperty?h.html[0].style.removeProperty(\"overflow\"):h.html[0].style.removeAttribute(\"overflow\"),h.html.removeAttr(\"layer-full\"))},a.layer=f,f.getChildFrame=function(a,b){return b=b||c(\".\"+h[4]).attr(\"times\"),c(\"#\"+h[0]+b).find(\"iframe\").contents().find(a)},f.getFrameIndex=function(a){return c(\"#\"+a).parents(\".\"+h[4]).attr(\"times\")},f.iframeAuto=function(a){if(a){var b=f.getChildFrame(\"html\",a).outerHeight(),d=c(\"#\"+h[0]+a),e=d.find(h[1]).outerHeight()||0,g=d.find(\".\"+h[6]).outerHeight()||0;d.css({height:b+e+g}),d.find(\"iframe\").css({height:b})}},f.iframeSrc=function(a,b){c(\"#\"+h[0]+a).find(\"iframe\").attr(\"src\",b)},f.style=function(a,b){var d=c(\"#\"+h[0]+a),f=d.attr(\"type\"),g=d.find(h[1]).outerHeight()||0,i=d.find(\".\"+h[6]).outerHeight()||0;(f===e.type[1]||f===e.type[2])&&(d.css(b),f===e.type[2]&&d.find(\"iframe\").css({height:parseFloat(b.height)-g-i}))},f.min=function(a,b){var d=c(\"#\"+h[0]+a),g=d.find(h[1]).outerHeight()||0;e.record(d),f.style(a,{width:180,height:g,overflow:\"hidden\"}),d.find(\".layui-layer-min\").hide(),\"page\"===d.attr(\"type\")&&d.find(h[4]).hide(),e.rescollbar(a)},f.restore=function(a){var b=c(\"#\"+h[0]+a),d=b.attr(\"area\").split(\",\");b.attr(\"type\");f.style(a,{width:parseFloat(d[0]),height:parseFloat(d[1]),top:parseFloat(d[2]),left:parseFloat(d[3]),overflow:\"visible\"}),b.find(\".layui-layer-max\").removeClass(\"layui-layer-maxmin\"),b.find(\".layui-layer-min\").show(),\"page\"===b.attr(\"type\")&&b.find(h[4]).show(),e.rescollbar(a)},f.full=function(a){var b,g=c(\"#\"+h[0]+a);e.record(g),h.html.attr(\"layer-full\")||h.html.css(\"overflow\",\"hidden\").attr(\"layer-full\",a),clearTimeout(b),b=setTimeout(function(){var b=\"fixed\"===g.css(\"position\");f.style(a,{top:b?0:d.scrollTop(),left:b?0:d.scrollLeft(),width:d.width(),height:d.height()}),g.find(\".layui-layer-min\").hide()},100)},f.title=function(a,b){var d=c(\"#\"+h[0]+(b||f.index)).find(h[1]);d.html(a)},f.close=function(a){var b=c(\"#\"+h[0]+a),d=b.attr(\"type\");if(b[0]){if(d===e.type[1]&&\"object\"===b.attr(\"conType\")){b.children(\":not(.\"+h[5]+\")\").remove();for(var g=0;2>g;g++)b.find(\".layui-layer-wrap\").unwrap().hide()}else{if(d===e.type[2])try{var i=c(\"#\"+h[4]+a)[0];i.contentWindow.document.write(\"\"),i.contentWindow.close(),b.find(\".\"+h[5])[0].removeChild(i)}catch(j){}b[0].innerHTML=\"\",b.remove()}c(\"#layui-layer-moves, #layui-layer-shade\"+a).remove(),f.ie6&&e.reselect(),e.rescollbar(a),c(document).off(\"keydown\",e.enter),\"function\"==typeof e.end[a]&&e.end[a](),delete e.end[a]}},f.closeAll=function(a){c.each(c(\".\"+h[0]),function(){var b=c(this),d=a?b.attr(\"type\")===a:1;d&&f.close(b.attr(\"times\")),d=null})};var i=f.cache||{},j=function(a){return i.skin?\" \"+i.skin+\" \"+i.skin+\"-\"+a:\"\"};f.prompt=function(a,b){a=a||{},\"function\"==typeof a&&(b=a);var d,e=2==a.formType?'<textarea class=\"layui-layer-input\">'+(a.value||\"\")+\"</textarea>\":function(){return'<input type=\"'+(1==a.formType?\"password\":\"text\")+'\" class=\"layui-layer-input\" value=\"'+(a.value||\"\")+'\">'}();return f.open(c.extend({btn:[\"&#x786E;&#x5B9A;\",\"&#x53D6;&#x6D88;\"],content:e,skin:\"layui-layer-prompt\"+j(\"prompt\"),success:function(a){d=a.find(\".layui-layer-input\"),d.focus()},yes:function(c){var e=d.val();\"\"===e?d.focus():e.length>(a.maxlength||500)?f.tips(\"&#x6700;&#x591A;&#x8F93;&#x5165;\"+(a.maxlength||500)+\"&#x4E2A;&#x5B57;&#x6570;\",d,{tips:1}):b&&b(e,c,d)}},a))},f.tab=function(a){a=a||{};var b=a.tab||{};return f.open(c.extend({type:1,skin:\"layui-layer-tab\"+j(\"tab\"),title:function(){var a=b.length,c=1,d=\"\";if(a>0)for(d='<span class=\"layui-layer-tabnow\">'+b[0].title+\"</span>\";a>c;c++)d+=\"<span>\"+b[c].title+\"</span>\";return d}(),content:'<ul class=\"layui-layer-tabmain\">'+function(){var a=b.length,c=1,d=\"\";if(a>0)for(d='<li class=\"layui-layer-tabli xubox_tab_layer\">'+(b[0].content||\"no content\")+\"</li>\";a>c;c++)d+='<li class=\"layui-layer-tabli\">'+(b[c].content||\"no  content\")+\"</li>\";return d}()+\"</ul>\",success:function(b){var d=b.find(\".layui-layer-title\").children(),e=b.find(\".layui-layer-tabmain\").children();d.on(\"mousedown\",function(b){b.stopPropagation?b.stopPropagation():b.cancelBubble=!0;var d=c(this),f=d.index();d.addClass(\"layui-layer-tabnow\").siblings().removeClass(\"layui-layer-tabnow\"),e.eq(f).show().siblings().hide(),\"function\"==typeof a.change&&a.change(f)})}},a))},f.photos=function(b,d,e){function g(a,b,c){var d=new Image;return d.src=a,d.complete?b(d):(d.onload=function(){d.onload=null,b(d)},void(d.onerror=function(a){d.onerror=null,c(a)}))}var h={};if(b=b||{},b.photos){var i=b.photos.constructor===Object,k=i?b.photos:{},l=k.data||[],m=k.start||0;if(h.imgIndex=(0|m)+1,b.img=b.img||\"img\",i){if(0===l.length)return f.msg(\"&#x6CA1;&#x6709;&#x56FE;&#x7247;\")}else{var n=c(b.photos),o=function(){l=[],n.find(b.img).each(function(a){var b=c(this);b.attr(\"layer-index\",a),l.push({alt:b.attr(\"alt\"),pid:b.attr(\"layer-pid\"),src:b.attr(\"layer-src\")||b.attr(\"src\"),thumb:b.attr(\"src\")})})};if(o(),0===l.length)return;if(d||n.on(\"click\",b.img,function(){var a=c(this),d=a.attr(\"layer-index\");f.photos(c.extend(b,{photos:{start:d,data:l,tab:b.tab},full:b.full}),!0),o()}),!d)return}h.imgprev=function(a){h.imgIndex--,h.imgIndex<1&&(h.imgIndex=l.length),h.tabimg(a)},h.imgnext=function(a,b){h.imgIndex++,h.imgIndex>l.length&&(h.imgIndex=1,b)||h.tabimg(a)},h.keyup=function(a){if(!h.end){var b=a.keyCode;a.preventDefault(),37===b?h.imgprev(!0):39===b?h.imgnext(!0):27===b&&f.close(h.index)}},h.tabimg=function(a){l.length<=1||(k.start=h.imgIndex-1,f.close(h.index),f.photos(b,!0,a))},h.event=function(){h.bigimg.hover(function(){h.imgsee.show()},function(){h.imgsee.hide()}),h.bigimg.find(\".layui-layer-imgprev\").on(\"click\",function(a){a.preventDefault(),h.imgprev()}),h.bigimg.find(\".layui-layer-imgnext\").on(\"click\",function(a){a.preventDefault(),h.imgnext()}),c(document).on(\"keyup\",h.keyup)},h.loadi=f.load(1,{shade:\"shade\"in b?!1:.9,scrollbar:!1}),g(l[m].src,function(d){f.close(h.loadi),h.index=f.open(c.extend({type:1,area:function(){var e=[d.width,d.height],f=[c(a).width()-50,c(a).height()-50];return!b.full&&e[0]>f[0]&&(e[0]=f[0],e[1]=e[0]*d.height/d.width),[e[0]+\"px\",e[1]+\"px\"]}(),title:!1,shade:.9,shadeClose:!0,closeBtn:!1,move:\".layui-layer-phimg img\",moveType:1,scrollbar:!1,moveOut:!0,shift:5*Math.random()|0,skin:\"layui-layer-photos\"+j(\"photos\"),content:'<div class=\"layui-layer-phimg\"><img src=\"'+l[m].src+'\" alt=\"'+(l[m].alt||\"\")+'\" layer-pid=\"'+l[m].pid+'\"><div class=\"layui-layer-imgsee\">'+(l.length>1?'<span class=\"layui-layer-imguide\"><a href=\"javascript:;\" class=\"layui-layer-iconext layui-layer-imgprev\"></a><a href=\"javascript:;\" class=\"layui-layer-iconext layui-layer-imgnext\"></a></span>':\"\")+'<div class=\"layui-layer-imgbar\" style=\"display:'+(e?\"block\":\"\")+'\"><span class=\"layui-layer-imgtit\"><a href=\"javascript:;\">'+(l[m].alt||\"\")+\"</a><em>\"+h.imgIndex+\"/\"+l.length+\"</em></span></div></div></div>\",success:function(a,c){h.bigimg=a.find(\".layui-layer-phimg\"),h.imgsee=a.find(\".layui-layer-imguide,.layui-layer-imgbar\"),h.event(a),b.tab&&b.tab(l[m],a)},end:function(){h.end=!0,c(document).off(\"keyup\",h.keyup)}},b))},function(){f.close(h.loadi),f.msg(\"&#x5F53;&#x524D;&#x56FE;&#x7247;&#x5730;&#x5740;&#x5F02;&#x5E38;<br>&#x662F;&#x5426;&#x7EE7;&#x7EED;&#x67E5;&#x770B;&#x4E0B;&#x4E00;&#x5F20;&#xFF1F;\",{time:3e4,btn:[\"&#x4E0B;&#x4E00;&#x5F20;\",\"&#x4E0D;&#x770B;&#x4E86;\"],yes:function(){l.length>1&&h.imgnext(!0,!0)}})})}},e.run=function(){c=jQuery,d=c(a),h.html=c(\"html\"),f.open=function(a){var b=new g(a);return b.index}},\"function\"==typeof define?define(function(){return e.run(),f}):function(){e.run(),f.use(\"skin/layer.css\")}()}(window);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/layer/2.4/skin/layer.css",
    "content": "/*!\n \n @Name: layer's style\n @Author: 贤心\n @Blog： sentsin.com\n \n */.layui-layer-imgbar,.layui-layer-imgtit a,.layui-layer-tab .layui-layer-title span,.layui-layer-title{text-overflow:ellipsis;white-space:nowrap}*html{background-image:url(about:blank);background-attachment:fixed}html #layui_layer_skinlayercss{display:none;position:absolute;width:1989px}.layui-layer,.layui-layer-shade{position:fixed;_position:absolute;pointer-events:auto}.layui-layer-shade{top:0;left:0;width:100%;height:100%;_height:expression(document.body.offsetHeight+\"px\")}.layui-layer{-webkit-overflow-scrolling:touch;top:150px;left:0;margin:0;padding:0;background-color:#fff;-webkit-background-clip:content;box-shadow:1px 1px 50px rgba(0,0,0,.3);border-radius:2px;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation-duration:.3s;animation-duration:.3s}.layui-layer-close{position:absolute}.layui-layer-content{position:relative}.layui-layer-border{border:1px solid #B2B2B2;border:1px solid rgba(0,0,0,.3);box-shadow:1px 1px 5px rgba(0,0,0,.2)}.layui-layer-moves{position:absolute;border:3px solid #666;border:3px solid rgba(0,0,0,.5);cursor:move;background-color:#fff;background-color:rgba(255,255,255,.3);filter:alpha(opacity=50)}.layui-layer-load{background:url(default/loading-0.gif) center center no-repeat #fff}.layui-layer-ico{background:url(default/icon.png) no-repeat}.layui-layer-btn a,.layui-layer-dialog .layui-layer-ico,.layui-layer-setwin a{display:inline-block;*display:inline;*zoom:1;vertical-align:top}@-webkit-keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceIn{0%{opacity:0;-webkit-transform:scale(.5);-ms-transform:scale(.5);transform:scale(.5)}100%{opacity:1;-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceOut{100%{opacity:0;-webkit-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.03);transform:scale(1.03)}0%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes bounceOut{100%{opacity:0;-webkit-transform:scale(.7);-ms-transform:scale(.7);transform:scale(.7)}30%{-webkit-transform:scale(1.03);-ms-transform:scale(1.03);transform:scale(1.03)}0%{-webkit-transform:scale(1);-ms-transform:scale(1);transform:scale(1)}}.layer-anim-close{-webkit-animation-name:bounceOut;animation-name:bounceOut;-webkit-animation-duration:.2s;animation-duration:.2s}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale(.1) translateY(-2000px);-ms-transform:scale(.1) translateY(-2000px);transform:scale(.1) translateY(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateY(60px);-ms-transform:scale(.475) translateY(60px);transform:scale(.475) translateY(60px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-01{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);transform:translateY(0)}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translateY(2000px);-ms-transform:translateY(2000px);transform:translateY(2000px)}100%{opacity:1;-webkit-transform:translateY(0);-ms-transform:translateY(0);transform:translateY(0)}}.layer-anim-02{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale(.1) translateX(-2000px);-ms-transform:scale(.1) translateX(-2000px);transform:scale(.1) translateX(-2000px);-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}60%{opacity:1;-webkit-transform:scale(.475) translateX(48px);-ms-transform:scale(.475) translateX(48px);transform:scale(.475) translateX(48px);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}}.layer-anim-03{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translateX(-100%) rotate(-120deg);-ms-transform:translateX(-100%) rotate(-120deg);transform:translateX(-100%) rotate(-120deg)}100%{opacity:1;-webkit-transform:translateX(0) rotate(0);-ms-transform:translateX(0) rotate(0);transform:translateX(0) rotate(0)}}.layer-anim-04{-webkit-animation-name:rollIn;animation-name:rollIn}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layer-anim-05{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes shake{0%,100%{-webkit-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);transform:translateX(10px)}}@keyframes shake{0%,100%{-webkit-transform:translateX(0);-ms-transform:translateX(0);transform:translateX(0)}10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px);-ms-transform:translateX(-10px);transform:translateX(-10px)}20%,40%,60%,80%{-webkit-transform:translateX(10px);-ms-transform:translateX(10px);transform:translateX(10px)}}.layer-anim-06{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.layui-layer-title{padding:0 80px 0 20px;height:42px;line-height:42px;border-bottom:1px solid #eee;font-size:14px;color:#333;overflow:hidden;background-color:#F8F8F8;border-radius:2px 2px 0 0}.layui-layer-setwin{position:absolute;right:15px;*right:0;top:15px;font-size:0;line-height:initial}.layui-layer-setwin a{position:relative;width:16px;height:16px;margin-left:10px;font-size:12px;_overflow:hidden}.layui-layer-setwin .layui-layer-min cite{position:absolute;width:14px;height:2px;left:0;top:50%;margin-top:-1px;background-color:#2E2D3C;cursor:pointer;_overflow:hidden}.layui-layer-setwin .layui-layer-min:hover cite{background-color:#2D93CA}.layui-layer-setwin .layui-layer-max{background-position:-32px -40px}.layui-layer-setwin .layui-layer-max:hover{background-position:-16px -40px}.layui-layer-setwin .layui-layer-maxmin{background-position:-65px -40px}.layui-layer-setwin .layui-layer-maxmin:hover{background-position:-49px -40px}.layui-layer-setwin .layui-layer-close1{background-position:0 -40px;cursor:pointer}.layui-layer-setwin .layui-layer-close1:hover{opacity:.7}.layui-layer-setwin .layui-layer-close2{position:absolute;right:-28px;top:-28px;width:30px;height:30px;margin-left:0;background-position:-149px -31px;*right:-18px;_display:none}.layui-layer-setwin .layui-layer-close2:hover{background-position:-180px -31px}.layui-layer-btn{text-align:right;padding:0 10px 12px;pointer-events:auto}.layui-layer-btn a{height:28px;line-height:28px;margin:0 6px;padding:0 15px;border:1px solid #dedede;background-color:#f1f1f1;color:#333;border-radius:2px;font-weight:400;cursor:pointer;text-decoration:none}.layui-layer-btn a:hover{opacity:.9;text-decoration:none}.layui-layer-btn a:active{opacity:.7}.layui-layer-btn .layui-layer-btn0{border-color:#4898d5;background-color:#2e8ded;color:#fff}.layui-layer-dialog{min-width:260px}.layui-layer-dialog .layui-layer-content{position:relative;padding:20px;line-height:24px;word-break:break-all;overflow:hidden;font-size:14px;overflow-x:hidden;overflow-y:auto}.layui-layer-dialog .layui-layer-content .layui-layer-ico{position:absolute;top:16px;left:15px;_left:-40px;width:30px;height:30px}.layui-layer-ico1{background-position:-30px 0}.layui-layer-ico2{background-position:-60px 0}.layui-layer-ico3{background-position:-90px 0}.layui-layer-ico4{background-position:-120px 0}.layui-layer-ico5{background-position:-150px 0}.layui-layer-ico6{background-position:-180px 0}.layui-layer-rim{border:6px solid #8D8D8D;border:6px solid rgba(0,0,0,.3);border-radius:5px;box-shadow:none}.layui-layer-msg{min-width:180px;border:1px solid #D3D4D3;box-shadow:none}.layui-layer-hui{min-width:100px;background-color:#000;filter:alpha(opacity=60);background-color:rgba(0,0,0,.6);color:#fff;border:none}.layui-layer-hui .layui-layer-content{padding:12px 25px;text-align:center}.layui-layer-dialog .layui-layer-padding{padding:20px 20px 20px 55px;text-align:left}.layui-layer-page .layui-layer-content{position:relative;overflow:auto}.layui-layer-iframe .layui-layer-btn,.layui-layer-page .layui-layer-btn{padding-top:10px}.layui-layer-nobg{background:0 0}.layui-layer-iframe .layui-layer-content{overflow:hidden}.layui-layer-iframe iframe{display:block;width:100%}.layui-layer-loading{border-radius:100%;background:0 0;box-shadow:none;border:none}.layui-layer-loading .layui-layer-content{width:60px;height:24px;background:url(default/loading-0.gif) no-repeat}.layui-layer-loading .layui-layer-loading1{width:37px;height:37px;background:url(default/loading-1.gif) no-repeat}.layui-layer-ico16,.layui-layer-loading .layui-layer-loading2{width:32px;height:32px;background:url(default/loading-2.gif) no-repeat}.layui-layer-tips{background:0 0;box-shadow:none;border:none}.layui-layer-tips .layui-layer-content{position:relative;line-height:22px;min-width:12px;padding:5px 10px;font-size:12px;_float:left;border-radius:3px;box-shadow:1px 1px 3px rgba(0,0,0,.3);background-color:#F90;color:#fff}.layui-layer-tips .layui-layer-close{right:-2px;top:-1px}.layui-layer-tips i.layui-layer-TipsG{position:absolute;width:0;height:0;border-width:8px;border-color:transparent;border-style:dashed;*overflow:hidden}.layui-layer-tips i.layui-layer-TipsB,.layui-layer-tips i.layui-layer-TipsT{left:5px;border-right-style:solid;border-right-color:#F90}.layui-layer-tips i.layui-layer-TipsT{bottom:-8px}.layui-layer-tips i.layui-layer-TipsB{top:-8px}.layui-layer-tips i.layui-layer-TipsL,.layui-layer-tips i.layui-layer-TipsR{top:1px;border-bottom-style:solid;border-bottom-color:#F90}.layui-layer-tips i.layui-layer-TipsR{left:-8px}.layui-layer-tips i.layui-layer-TipsL{right:-8px}.layui-layer-lan[type=dialog]{min-width:280px}.layui-layer-lan .layui-layer-title{background:#4476A7;color:#fff;border:none}.layui-layer-lan .layui-layer-btn{padding:10px;text-align:right;border-top:1px solid #E9E7E7}.layui-layer-lan .layui-layer-btn a{background:#BBB5B5;border:none}.layui-layer-lan .layui-layer-btn .layui-layer-btn1{background:#C9C5C5}.layui-layer-molv .layui-layer-title{background:#009f95;color:#fff;border:none}.layui-layer-molv .layui-layer-btn a{background:#009f95}.layui-layer-molv .layui-layer-btn .layui-layer-btn1{background:#92B8B1}.layui-layer-iconext{background:url(default/icon-ext.png) no-repeat}.layui-layer-prompt .layui-layer-input{display:block;width:220px;height:30px;margin:0 auto;line-height:30px;padding:0 5px;border:1px solid #ccc;box-shadow:1px 1px 5px rgba(0,0,0,.1) inset;color:#333}.layui-layer-prompt textarea.layui-layer-input{width:300px;height:100px;line-height:20px}.layui-layer-tab{box-shadow:1px 1px 50px rgba(0,0,0,.4)}.layui-layer-tab .layui-layer-title{padding-left:0;border-bottom:1px solid #ccc;background-color:#eee;overflow:visible}.layui-layer-tab .layui-layer-title span{position:relative;float:left;min-width:80px;max-width:260px;padding:0 20px;text-align:center;cursor:default;overflow:hidden}.layui-layer-tab .layui-layer-title span.layui-layer-tabnow{height:43px;border-left:1px solid #ccc;border-right:1px solid #ccc;background-color:#fff;z-index:10}.layui-layer-tab .layui-layer-title span:first-child{border-left:none}.layui-layer-tabmain{line-height:24px;clear:both}.layui-layer-tabmain .layui-layer-tabli{display:none}.layui-layer-tabmain .layui-layer-tabli.xubox_tab_layer{display:block}.xubox_tabclose{position:absolute;right:10px;top:5px;cursor:pointer}.layui-layer-photos{-webkit-animation-duration:1s;animation-duration:1s}.layui-layer-photos .layui-layer-content{overflow:hidden;text-align:center}.layui-layer-photos .layui-layer-phimg img{position:relative;width:100%;display:inline-block;*display:inline;*zoom:1;vertical-align:top}.layui-layer-imgbar,.layui-layer-imguide{display:none}.layui-layer-imgnext,.layui-layer-imgprev{position:absolute;top:50%;width:27px;_width:44px;height:44px;margin-top:-22px;outline:0;blr:expression(this.onFocus=this.blur())}.layui-layer-imgprev{left:10px;background-position:-5px -5px;_background-position:-70px -5px}.layui-layer-imgprev:hover{background-position:-33px -5px;_background-position:-120px -5px}.layui-layer-imgnext{right:10px;_right:8px;background-position:-5px -50px;_background-position:-70px -50px}.layui-layer-imgnext:hover{background-position:-33px -50px;_background-position:-120px -50px}.layui-layer-imgbar{position:absolute;left:0;bottom:0;width:100%;height:32px;line-height:32px;background-color:rgba(0,0,0,.8);background-color:#000\\9;filter:Alpha(opacity=80);color:#fff;overflow:hidden;font-size:0}.layui-layer-imgtit *{display:inline-block;*display:inline;*zoom:1;vertical-align:top;font-size:12px}.layui-layer-imgtit a{max-width:65%;overflow:hidden;color:#fff}.layui-layer-imgtit a:hover{color:#fff;text-decoration:underline}.layui-layer-imgtit em{padding-left:10px;font-style:normal}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/laypage/1.2/laypage.js",
    "content": "﻿/*! layPage v1.2 - 分页插件 By 贤心 http://sentsin.com/layui/laypage MIT License */\n;!function(){\"use strict\";function a(d){var e=\"laypagecss\";a.dir=\"dir\"in a?a.dir:f.getpath+\"/skin/laypage.css\",new f(d),a.dir&&!b[c](e)&&f.use(a.dir,e)}var b,c,d,e,f;a.v=\"1.2\",b=document,c=\"getElementById\",d=\"getElementsByTagName\",e=0,f=function(a){var b=this,c=b.config=a||{};c.item=e++,b.render(!0)},f.on=function(a,b,c){return a.attachEvent?a.attachEvent(\"on\"+b,function(){c.call(a,window.even)}):a.addEventListener(b,c,!1),f},f.getpath=function(){var a=document.scripts,b=a[a.length-1].src;return b.substring(0,b.lastIndexOf(\"/\")+1)}(),f.use=function(c,e){var f=b.createElement(\"link\");f.type=\"text/css\",f.rel=\"stylesheet\",f.href=a.dir,e&&(f.id=e),b[d](\"head\")[0].appendChild(f),f=null},f.prototype.type=function(){var a=this.config;return\"object\"==typeof a.cont?void 0===a.cont.length?2:3:void 0},f.prototype.view=function(){var b=this,c=b.config,d=[],e={};c.pages=0|c.pages,c.curr=0|c.curr||1,c.groups=\"groups\"in c?0|c.groups:5,c.first=\"first\"in c?c.first:1,c.last=\"last\"in c?c.last:c.pages,c.prev=\"prev\"in c?c.prev:\"上一页\",c.next=\"next\"in c?c.next:\"下一页\",c.groups>c.pages&&(c.groups=c.pages),e.index=Math.ceil((c.curr+(c.groups>1&&c.groups!==c.pages?1:0))/(0===c.groups?1:c.groups)),c.curr>1&&c.prev&&d.push('<a href=\"javascript:;\" class=\"laypage_prev\" data-page=\"'+(c.curr-1)+'\">'+c.prev+\"</a>\"),e.index>1&&c.first&&0!==c.groups&&d.push('<a href=\"javascript:;\" class=\"laypage_first\" data-page=\"1\"  title=\"首页\">'+c.first+\"</a><span>…</span>\"),e.poor=Math.floor((c.groups-1)/2),e.start=e.index>1?c.curr-e.poor:1,e.end=e.index>1?function(){var a=c.curr+(c.groups-e.poor-1);return a>c.pages?c.pages:a}():c.groups,e.end-e.start<c.groups-1&&(e.start=e.end-c.groups+1);for(;e.start<=e.end;e.start++)e.start===c.curr?d.push('<span class=\"laypage_curr\" '+(/^#/.test(c.skin)?'style=\"background-color:'+c.skin+'\"':\"\")+\">\"+e.start+\"</span>\"):d.push('<a href=\"javascript:;\" data-page=\"'+e.start+'\">'+e.start+\"</a>\");return c.pages>c.groups&&e.end<c.pages&&c.last&&0!==c.groups&&d.push('<span>…</span><a href=\"javascript:;\" class=\"laypage_last\" title=\"尾页\"  data-page=\"'+c.pages+'\">'+c.last+\"</a>\"),e.flow=!c.prev&&0===c.groups,(c.curr!==c.pages&&c.next||e.flow)&&d.push(function(){return e.flow&&c.curr===c.pages?'<span class=\"page_nomore\" title=\"已没有更多\">'+c.next+\"</span>\":'<a href=\"javascript:;\" class=\"laypage_next\" data-page=\"'+(c.curr+1)+'\">'+c.next+\"</a>\"}()),'<div name=\"laypage'+a.v+'\" class=\"laypage_main laypageskin_'+(c.skin?function(a){return/^#/.test(a)?\"molv\":a}(c.skin):\"default\")+'\" id=\"laypage_'+b.config.item+'\">'+d.join(\"\")+function(){return c.skip?'<span class=\"laypage_total\"><label>到第</label><input type=\"number\" min=\"1\" onkeyup=\"this.value=this.value.replace(/\\\\D/, \\'\\');\" class=\"laypage_skip\"><label>页</label><button type=\"button\" class=\"laypage_btn\">确定</button></span>':\"\"}()+\"</div>\"},f.prototype.jump=function(a){var i,j,b=this,c=b.config,e=a.children,g=a[d](\"button\")[0],h=a[d](\"input\")[0];for(i=0,j=e.length;j>i;i++)\"a\"===e[i].nodeName.toLowerCase()&&f.on(e[i],\"click\",function(){var a=0|this.getAttribute(\"data-page\");c.curr=a,b.render()});g&&f.on(g,\"click\",function(){var a=0|h.value.replace(/\\s|\\D/g,\"\");a&&a<=c.pages&&(c.curr=a,b.render())})},f.prototype.render=function(a){var d=this,e=d.config,f=d.type(),g=d.view();2===f?e.cont.innerHTML=g:3===f?e.cont.html(g):b[c](e.cont).innerHTML=g,e.jump&&e.jump(e,a),d.jump(b[c](\"laypage_\"+e.item)),e.hash&&!a&&(location.hash=\"!\"+e.hash+\"=\"+e.curr)},\"function\"==typeof define?define(function(){return a}):\"undefined\"!=typeof exports?module.exports=a:window.laypage=a}();"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/laypage/1.2/skin/laypage.css",
    "content": "/*!\n laypage默认样式\n*/\n.laypage_main{font-size:0; clear:both; color:#666}\n.laypage_main *{display:inline-block; vertical-align: top; font-size:12px}\n.laypage_main a{height:26px; line-height:26px; text-decoration:none; color:#666}\n.laypage_main a, .laypage_main span{margin:0 3px 6px; padding:0 10px}\n.laypage_main span{height:26px; line-height:26px}\n.laypage_main input, .laypage_main button{ border:1px solid #ccc; background-color:#fff}\n.laypage_main input{width:40px; height:26px; line-height:26px; margin:0 5px; padding:0 5px}\n.laypage_main button{height:28px; line-height:28px; margin-left:5px; padding:0 10px; color:#666}\n\n/* 默认皮肤 */\n.laypageskin_default a{border:1px solid #ddd; background-color:#fff}\n.laypageskin_default a:hover{ background-color:#5a98de; border-color:#5a98de; color:#fff}\n.laypageskin_default span{height:28px; line-height:28px; color:#999}\n.laypageskin_default .laypage_curr{font-weight:700; color:#666}\n\n/* 一般用于信息流加载 */\n.laypageskin_flow{text-align:center}\n.laypageskin_flow .page_nomore{color:#999}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/lightbox2/2.8.1/css/lightbox.css",
    "content": "﻿body:after{content:url(../images/close.png) url(../images/loading.gif) url(../images/prev.png) url(../images/next.png);display:none}\n.lightboxOverlay{position:absolute;top:0;left:0;z-index:9999;background-color:black;filter:alpha(opacity=80);opacity:.8;display:none}\n.lightbox{position:absolute;left:0;width:100%;z-index:10000;text-align:center;line-height:0;font-weight:normal}\n.lightbox .lb-image{display:block;height:auto;max-width:inherit;-webkit-border-radius:3px;-moz-border-radius:3px;-ms-border-radius:3px;-o-border-radius:3px;border-radius:3px}\n.lightbox a img{border:0}\n.lb-outerContainer{position:relative;background-color:white;*zoom:1;width:250px;height:250px;margin:0 auto;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px}\n.lb-outerContainer:after{content:\"\";display:table;clear:both}\n.lb-container{padding:4px}\n.lb-loader{position:absolute;top:43%;left:0;height:25%;width:100%;text-align:center;line-height:0}\n.lb-cancel{display:block;width:32px;height:32px;margin:0 auto;background:url(../images/loading.gif) no-repeat}\n.lb-nav{position:absolute;top:0;left:0;height:100%;width:100%;z-index:10}\n.lb-container>.nav{left:0}\n.lb-nav a{outline:0;background-image:url('data:image/gif;base64,R0lGODlhAQABAPAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==')}\n.lb-prev,.lb-next{height:100%;cursor:pointer;display:block}\n.lb-nav a.lb-prev{width:34%;left:0;float:left;background:url(../images/prev.png) left 48% no-repeat;filter:alpha(opacity=0);opacity:0;-webkit-transition:opacity .6s;-moz-transition:opacity .6s;-o-transition:opacity .6s;transition:opacity .6s}\n.lb-nav a.lb-prev:hover{filter:alpha(opacity=100);opacity:1}\n.lb-nav a.lb-next{width:64%;right:0;float:right;background:url(../images/next.png) right 48% no-repeat;filter:alpha(opacity=0);opacity:0;-webkit-transition:opacity .6s;-moz-transition:opacity .6s;-o-transition:opacity .6s;transition:opacity .6s}\n.lb-nav a.lb-next:hover{filter:alpha(opacity=100);opacity:1}\n.lb-dataContainer{margin:0 auto;padding-top:5px;*zoom:1;width:100%;-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px}\n.lb-dataContainer:after{content:\"\";display:table;clear:both}\n.lb-data{padding:0 4px;color:#ccc}\n.lb-data .lb-details{width:85%;float:left;text-align:left;line-height:1.1em}\n.lb-data .lb-caption{font-size:13px;font-weight:bold;line-height:1em}\n.lb-data .lb-number{display:block;clear:left;padding-bottom:1em;font-size:12px;color:#999}\n.lb-data .lb-close{display:block;float:right;width:30px;height:30px;background:url(../images/close.png) top right no-repeat;text-align:right;outline:0;filter:alpha(opacity=70);opacity:.7;-webkit-transition:opacity .2s;-moz-transition:opacity .2s;-o-transition:opacity .2s;transition:opacity .2s}\n.lb-data .lb-close:hover{cursor:pointer;filter:alpha(opacity=100);opacity:1}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/lightbox2/2.8.1/examples.html",
    "content": "<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<title>Lightbox Example</title>\n<link rel=\"stylesheet\" href=\"css/lightbox.css\">\n</head>\n<body>\n<section>\n\t<h3>Two Individual Images</h3>\n\t<div> <a class=\"example-image-link\" href=\"http://lokeshdhakar.com/projects/lightbox2/images/image-1.jpg\" data-lightbox=\"example-1\" data-title=\"图片标题\"><img class=\"example-image\" src=\"http://lokeshdhakar.com/projects/lightbox2/images/thumb-1.jpg\" alt=\"image-1\" /></a> <a class=\"example-image-link\" href=\"http://lokeshdhakar.com/projects/lightbox2/images/image-2.jpg\" data-lightbox=\"example-2\" data-title=\"图片标题\"><img class=\"example-image\" src=\"http://lokeshdhakar.com/projects/lightbox2/images/thumb-2.jpg\" alt=\"image-1\"/></a> </div>\n\t<hr />\n\t<h3>A Four Image Set</h3>\n\t<div> <a class=\"example-image-link\" href=\"http://lokeshdhakar.com/projects/lightbox2/images/image-3.jpg\" data-lightbox=\"example-set\" data-title=\"图片标题\"><img class=\"example-image\" src=\"http://lokeshdhakar.com/projects/lightbox2/images/thumb-3.jpg\" alt=\"\"/></a> <a class=\"example-image-link\" href=\"http://lokeshdhakar.com/projects/lightbox2/images/image-4.jpg\" data-lightbox=\"example-set\" data-title=\"图片标题\"><img class=\"example-image\" src=\"http://lokeshdhakar.com/projects/lightbox2/images/thumb-4.jpg\" alt=\"\" /></a> <a class=\"example-image-link\" href=\"http://lokeshdhakar.com/projects/lightbox2/images/image-5.jpg\" data-lightbox=\"example-set\" data-title=\"图片标题\"><img class=\"example-image\" src=\"http://lokeshdhakar.com/projects/lightbox2/images/thumb-5.jpg\" alt=\"\" /></a> <a class=\"example-image-link\" href=\"http://lokeshdhakar.com/projects/lightbox2/images/image-6.jpg\" data-lightbox=\"example-set\" data-title=\"图片标题\"><img class=\"example-image\" src=\"http://lokeshdhakar.com/projects/lightbox2/images/thumb-6.jpg\" alt=\"\" /></a> </div>\n</section>\n<script src=\"js/lightbox-plus-jquery.min.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/lightbox2/2.8.1/js/lightbox-plus-jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v2.1.4\n * http://jquery.com/\n *\n * Includes Sizzle.js\n * http://sizzlejs.com/\n *\n * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2015-04-28T16:01Z\n */\n\n(function( global, factory ) {\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n}(typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Support: Firefox 18+\n// Can't be in strict mode, several libs including ASP.NET trace\n// the stack via arguments.caller.callee and Firefox dies if\n// you try to trace through \"use strict\" call chains. (#13335)\n//\n\nvar arr = [];\n\nvar slice = arr.slice;\n\nvar concat = arr.concat;\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar support = {};\n\n\n\nvar\n\t// Use the correct document accordingly with window argument (sandbox)\n\tdocument = window.document,\n\n\tversion = \"2.1.4\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android<4.1\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([\\da-z])/gi,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn = jQuery.prototype = {\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// Start with an empty selector\n\tselector: \"\",\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\t\treturn num != null ?\n\n\t\t\t// Return just the one element from the set\n\t\t\t( num < 0 ? this[ num + this.length ] : this[ num ] ) :\n\n\t\t\t// Return all the elements in a clean array\n\t\t\tslice.call( this );\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\t\tret.context = this.context;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\t// (You can seed the arguments with an array of args, but this is\n\t// only used internally.)\n\teach: function( callback, args ) {\n\t\treturn jQuery.each( this, callback, args );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t}));\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor(null);\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[0] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction(target) ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\t\t// Only deal with non-null/undefined values\n\t\tif ( (options = arguments[ i ]) != null ) {\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend({\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type(obj) === \"function\";\n\t},\n\n\tisArray: Array.isArray,\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\t\t// parseFloat NaNs numeric-cast false positives (null|true|false|\"\")\n\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t// subtraction forces infinities to NaN\n\t\t// adding 1 corrects loss of precision from parseFloat (#15100)\n\t\treturn !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\t// Not plain objects:\n\t\t// - Any object or value whose internal [[Class]] property is not \"[object Object]\"\n\t\t// - DOM nodes\n\t\t// - window\n\t\tif ( jQuery.type( obj ) !== \"object\" || obj.nodeType || jQuery.isWindow( obj ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( obj.constructor &&\n\t\t\t\t!hasOwn.call( obj.constructor.prototype, \"isPrototypeOf\" ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// If the function hasn't returned already, we're confident that\n\t\t// |obj| is a plain object, created by {} or constructed with new Object\n\t\treturn true;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\t\tvar name;\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\t\t// Support: Android<4.0, iOS<6 (functionish RegExp)\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ toString.call(obj) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code ) {\n\t\tvar script,\n\t\t\tindirect = eval;\n\n\t\tcode = jQuery.trim( code );\n\n\t\tif ( code ) {\n\t\t\t// If the code includes a valid, prologue position\n\t\t\t// strict mode pragma, execute code by injecting a\n\t\t\t// script tag into the document.\n\t\t\tif ( code.indexOf(\"use strict\") === 1 ) {\n\t\t\t\tscript = document.createElement(\"script\");\n\t\t\t\tscript.text = code;\n\t\t\t\tdocument.head.appendChild( script ).parentNode.removeChild( script );\n\t\t\t} else {\n\t\t\t// Otherwise, avoid the DOM node creation, insertion\n\t\t\t// and removal by using an indirect global eval\n\t\t\t\tindirect( code );\n\t\t\t}\n\t\t}\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Support: IE9-11+\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\t// args is for internal usage only\n\teach: function( obj, callback, args ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = obj.length,\n\t\t\tisArray = isArraylike( obj );\n\n\t\tif ( args ) {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// A special, fast, case for the most common use of each\n\t\t} else {\n\t\t\tif ( isArray ) {\n\t\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( i in obj ) {\n\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n\n\t\t\t\t\tif ( value === false ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android<4.1\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArraylike( Object(arr) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar value,\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tisArray = isArraylike( elems ),\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArray ) {\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar tmp, args, proxy;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\tnow: Date.now,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n});\n\n// Populate the class2type map\njQuery.each(\"Boolean Number String Function Array Date RegExp Object Error\".split(\" \"), function(i, name) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n});\n\nfunction isArraylike( obj ) {\n\n\t// Support: iOS 8.2 (not reproducible in simulator)\n\t// `in` check used to prevent JIT error (gh-2145)\n\t// hasOwn isn't used here due to false negatives\n\t// regarding Nodelist length in IE\n\tvar length = \"length\" in obj && obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\tif ( obj.nodeType === 1 && length ) {\n\t\treturn true;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.2.0-pre\n * http://sizzlejs.com/\n *\n * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2014-12-16\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// General-purpose constants\n\tMAX_NEGATIVE = 1 << 31,\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// http://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\t// http://www.w3.org/TR/css3-syntax/#characters\n\tcharacterEncoding = \"(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+\",\n\n\t// Loosely modeled on CSS identifier characters\n\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = characterEncoding.replace( \"w\", \"w#\" ),\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + characterEncoding + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + characterEncoding + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + characterEncoding + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + characterEncoding + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + characterEncoding.replace( \"w\", \"w*\" ) + \")\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\trescape = /'|\\\\/g,\n\n\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t};\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar match, elem, m, nodeType,\n\t\t// QSA vars\n\t\ti, groups, old, nid, newContext, newSelector;\n\n\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\n\tcontext = context || document;\n\tresults = results || [];\n\tnodeType = context.nodeType;\n\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\tif ( !seed && documentIsHTML ) {\n\n\t\t// Try to shortcut find operations when possible (e.g., not under DocumentFragment)\n\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\t\t\t// Speed-up: Sizzle(\"#ID\")\n\t\t\tif ( (m = match[1]) ) {\n\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\telem = context.getElementById( m );\n\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t\t// nodes that are no longer in the document (jQuery #6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n\t\t\t\t\t\t// by name instead of ID\n\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Context is not a document\n\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Speed-up: Sizzle(\"TAG\")\n\t\t\t} else if ( match[2] ) {\n\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\treturn results;\n\n\t\t\t// Speed-up: Sizzle(\".CLASS\")\n\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName ) {\n\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\treturn results;\n\t\t\t}\n\t\t}\n\n\t\t// QSA path\n\t\tif ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\t\t\tnid = old = expando;\n\t\t\tnewContext = context;\n\t\t\tnewSelector = nodeType !== 1 && selector;\n\n\t\t\t// qSA works strangely on Element-rooted queries\n\t\t\t// We can work around this by specifying an extra ID on the root\n\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n\t\t\t// IE 8 doesn't work on object elements\n\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== \"object\" ) {\n\t\t\t\tgroups = tokenize( selector );\n\n\t\t\t\tif ( (old = context.getAttribute(\"id\")) ) {\n\t\t\t\t\tnid = old.replace( rescape, \"\\\\$&\" );\n\t\t\t\t} else {\n\t\t\t\t\tcontext.setAttribute( \"id\", nid );\n\t\t\t\t}\n\t\t\t\tnid = \"[id='\" + nid + \"'] \";\n\n\t\t\t\ti = groups.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n\t\t\t\t}\n\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;\n\t\t\t\tnewSelector = groups.join(\",\");\n\t\t\t}\n\n\t\t\tif ( newSelector ) {\n\t\t\t\ttry {\n\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t);\n\t\t\t\t\treturn results;\n\t\t\t\t} catch(qsaError) {\n\t\t\t\t} finally {\n\t\t\t\t\tif ( !old ) {\n\t\t\t\t\t\tcontext.removeAttribute(\"id\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created div and expects a boolean result\n */\nfunction assert( fn ) {\n\tvar div = document.createElement(\"div\");\n\n\ttry {\n\t\treturn !!fn( div );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( div.parentNode ) {\n\t\t\tdiv.parentNode.removeChild( div );\n\t\t}\n\t\t// release memory in IE\n\t\tdiv = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = attrs.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\t( ~b.sourceIndex || MAX_NEGATIVE ) -\n\t\t\t( ~a.sourceIndex || MAX_NEGATIVE );\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, parent,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// If no document and documentElement is available, return\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Set our document\n\tdocument = doc;\n\tdocElem = doc.documentElement;\n\tparent = doc.defaultView;\n\n\t// Support: IE>8\n\t// If iframe document is assigned to \"document\" variable and if iframe has been reloaded,\n\t// IE will throw \"permission denied\" error when accessing \"document\" variable, see jQuery #13936\n\t// IE6-8 do not support the defaultView property so parent will be undefined\n\tif ( parent && parent !== parent.top ) {\n\t\t// IE11 does not have attachEvent, so all must suffer\n\t\tif ( parent.addEventListener ) {\n\t\t\tparent.addEventListener( \"unload\", unloadHandler, false );\n\t\t} else if ( parent.attachEvent ) {\n\t\t\tparent.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Support tests\n\t---------------------------------------------------------------------- */\n\tdocumentIsHTML = !isXML( doc );\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( div ) {\n\t\tdiv.className = \"i\";\n\t\treturn !div.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( div ) {\n\t\tdiv.appendChild( doc.createComment(\"\") );\n\t\treturn !div.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( doc.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( div ) {\n\t\tdocElem.appendChild( div ).id = expando;\n\t\treturn !doc.getElementsByName || !doc.getElementsByName( expando ).length;\n\t});\n\n\t// ID find and filter\n\tif ( support.getById ) {\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar m = context.getElementById( id );\n\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n\t\t\t\t// nodes that are no longer in the document #6963\n\t\t\t\treturn m && m.parentNode ? [ m ] : [];\n\t\t\t}\n\t\t};\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t} else {\n\t\t// Support: IE6/7\n\t\t// getElementById is not reliable as a find shortcut\n\t\tdelete Expr.find[\"ID\"];\n\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" && elem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See http://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( div ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// http://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( div ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\f]' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( div.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !div.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+\n\t\t\tif ( !div.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibing-combinator selector` fails\n\t\t\tif ( !div.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( div ) {\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = doc.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tdiv.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( div.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !div.querySelectorAll(\":enabled\").length ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tdiv.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( div ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( div, \"div\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( div, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully does not implement inclusive descendent\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === doc ? -1 :\n\t\t\t\tb === doc ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn doc;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n\t\t\t\t\t\t\tdiff = cache[1];\n\n\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": function( elem ) {\n\t\t\treturn elem.disabled === false;\n\t\t},\n\n\t\t\"disabled\": function( elem ) {\n\t\t\treturn elem.disabled === true;\n\t\t},\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tcheckNonElements = base && dir === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from dir caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\t\t\t\t\t\tif ( (oldCache = outerCache[ dir ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\touterCache[ dir ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context !== document && context;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be \"00\" below\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\tmatchedCount += i;\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is no seed and only one group\n\tif ( match.length === 1 ) {\n\n\t\t// Take a shortcut and set the context if the root selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\n\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\trsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( div1 ) {\n\t// Should return 1, but returns 4 (following)\n\treturn div1.compareDocumentPosition( document.createElement(\"div\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( div ) {\n\tdiv.innerHTML = \"<a href='#'></a>\";\n\treturn div.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( div ) {\n\tdiv.innerHTML = \"<input/>\";\n\tdiv.firstChild.setAttribute( \"value\", \"\" );\n\treturn div.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( div ) {\n\treturn div.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\njQuery.expr[\":\"] = jQuery.expr.pseudos;\njQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\n\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\nvar rsingleTag = (/^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/);\n\n\n\nvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\t/* jshint -W018 */\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t});\n\n\t}\n\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t});\n\n\t}\n\n\tif ( typeof qualifier === \"string\" ) {\n\t\tif ( risSimple.test( qualifier ) ) {\n\t\t\treturn jQuery.filter( qualifier, elements, not );\n\t\t}\n\n\t\tqualifier = jQuery.filter( qualifier, elements );\n\t}\n\n\treturn jQuery.grep( elements, function( elem ) {\n\t\treturn ( indexOf.call( qualifier, elem ) >= 0 ) !== not;\n\t});\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\treturn elems.length === 1 && elem.nodeType === 1 ?\n\t\tjQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :\n\t\tjQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\t\treturn elem.nodeType === 1;\n\t\t}));\n};\n\njQuery.fn.extend({\n\tfind: function( selector ) {\n\t\tvar i,\n\t\t\tlen = this.length,\n\t\t\tret = [],\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}) );\n\t\t}\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n\t\tret.selector = this.selector ? this.selector + \" \" + selector : selector;\n\t\treturn ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], false) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow(this, selector || [], true) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n});\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n\n\tinit = jQuery.fn.init = function( selector, context ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[0] === \"<\" && selector[ selector.length - 1 ] === \">\" && selector.length >= 3 ) {\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && (match[1] || !context) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[1] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n\n\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[1],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[2] );\n\n\t\t\t\t\t// Support: Blackberry 4.6\n\t\t\t\t\t// gEBID returns nodes no longer in the document (#6963)\n\t\t\t\t\tif ( elem && elem.parentNode ) {\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t\tthis[0] = elem;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.context = document;\n\t\t\t\t\tthis.selector = selector;\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || rootjQuery ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis.context = this[0] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn typeof rootjQuery.ready !== \"undefined\" ?\n\t\t\t\trootjQuery.ready( selector ) :\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\tif ( selector.selector !== undefined ) {\n\t\t\tthis.selector = selector.selector;\n\t\t\tthis.context = selector.context;\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\t// Methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.extend({\n\tdir: function( elem, dir, until ) {\n\t\tvar matched = [],\n\t\t\ttruncate = until !== undefined;\n\n\t\twhile ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tmatched.push( elem );\n\t\t\t}\n\t\t}\n\t\treturn matched;\n\t},\n\n\tsibling: function( n, elem ) {\n\t\tvar matched = [];\n\n\t\tfor ( ; n; n = n.nextSibling ) {\n\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\t\tmatched.push( n );\n\t\t\t}\n\t\t}\n\n\t\treturn matched;\n\t}\n});\n\njQuery.fn.extend({\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter(function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\tpos = rneedsContext.test( selectors ) || typeof selectors !== \"string\" ?\n\t\t\t\tjQuery( selectors, context || this.context ) :\n\t\t\t\t0;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tfor ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {\n\t\t\t\t// Always skip document fragments\n\t\t\t\tif ( cur.nodeType < 11 && (pos ?\n\t\t\t\t\tpos.index(cur) > -1 :\n\n\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\tjQuery.find.matchesSelector(cur, selectors)) ) {\n\n\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// Index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.unique(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter(selector)\n\t\t);\n\t}\n});\n\nfunction sibling( cur, dir ) {\n\twhile ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each({\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn jQuery.dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn jQuery.dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn jQuery.sibling( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn elem.contentDocument || jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.unique( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n});\nvar rnotwhite = (/\\S+/g);\n\n\n\n// String to Object options format cache\nvar optionsCache = {};\n\n// Convert String-formatted options into Object-formatted ones and store in cache\nfunction createOptions( options ) {\n\tvar object = optionsCache[ options ] = {};\n\tjQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t});\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\t( optionsCache[ options ] || createOptions( options ) ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Last fire value (for non-forgettable lists)\n\t\tmemory,\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\t\t// Flag to know if list is currently firing\n\t\tfiring,\n\t\t// First callback to fire (used internally by add and fireWith)\n\t\tfiringStart,\n\t\t// End of the loop when firing\n\t\tfiringLength,\n\t\t// Index of currently firing callback (modified by remove if needed)\n\t\tfiringIndex,\n\t\t// Actual callback list\n\t\tlist = [],\n\t\t// Stack of fire calls for repeatable lists\n\t\tstack = !options.once && [],\n\t\t// Fire callbacks\n\t\tfire = function( data ) {\n\t\t\tmemory = options.memory && data;\n\t\t\tfired = true;\n\t\t\tfiringIndex = firingStart || 0;\n\t\t\tfiringStart = 0;\n\t\t\tfiringLength = list.length;\n\t\t\tfiring = true;\n\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n\t\t\t\t\tmemory = false; // To prevent further calls using add\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfiring = false;\n\t\t\tif ( list ) {\n\t\t\t\tif ( stack ) {\n\t\t\t\t\tif ( stack.length ) {\n\t\t\t\t\t\tfire( stack.shift() );\n\t\t\t\t\t}\n\t\t\t\t} else if ( memory ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t} else {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t// Actual Callbacks object\n\t\tself = {\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\t// First, we save the current length\n\t\t\t\t\tvar start = list.length;\n\t\t\t\t\t(function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n\t\t\t\t\t\t\tif ( type === \"function\" ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== \"string\" ) {\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t})( arguments );\n\t\t\t\t\t// Do we need to add the callbacks to the\n\t\t\t\t\t// current firing batch?\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tfiringLength = list.length;\n\t\t\t\t\t// With memory, if we're not firing then\n\t\t\t\t\t// we should call right away\n\t\t\t\t\t} else if ( memory ) {\n\t\t\t\t\t\tfiringStart = start;\n\t\t\t\t\t\tfire( memory );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\t\tvar index;\n\t\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\t\tlist.splice( index, 1 );\n\t\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n\t\t\t\t\t\t\t\t\tfiringLength--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n\t\t\t},\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tlist = [];\n\t\t\t\tfiringLength = 0;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Have the list do nothing anymore\n\t\t\tdisable: function() {\n\t\t\t\tlist = stack = memory = undefined;\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it disabled?\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\t\t\t// Lock the list in its current state\n\t\t\tlock: function() {\n\t\t\t\tstack = undefined;\n\t\t\t\tif ( !memory ) {\n\t\t\t\t\tself.disable();\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Is it locked?\n\t\t\tlocked: function() {\n\t\t\t\treturn !stack;\n\t\t\t},\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( list && ( !fired || stack ) ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tif ( firing ) {\n\t\t\t\t\t\tstack.push( args );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfire( args );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\njQuery.extend({\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\t\t\t\t// action, add listener, listener list, final state\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks(\"once memory\"), \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks(\"once memory\"), \"rejected\" ],\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks(\"memory\") ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t}).promise();\n\t\t\t\t},\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Keep pipe for back-compat\n\t\tpromise.pipe = promise.then;\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 3 ];\n\n\t\t\t// promise[ done | fail | progress ] = list.add\n\t\t\tpromise[ tuple[1] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(function() {\n\t\t\t\t\t// state = [ resolved | rejected ]\n\t\t\t\t\tstate = stateString;\n\n\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n\t\t\t}\n\n\t\t\t// deferred[ resolve | reject | notify ]\n\t\t\tdeferred[ tuple[0] ] = function() {\n\t\t\t\tdeferred[ tuple[0] + \"With\" ]( this === deferred ? promise : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\t\t\tdeferred[ tuple[0] + \"With\" ] = list.fireWith;\n\t\t});\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( subordinate /* , ..., subordinateN */ ) {\n\t\tvar i = 0,\n\t\t\tresolveValues = slice.call( arguments ),\n\t\t\tlength = resolveValues.length,\n\n\t\t\t// the count of uncompleted subordinates\n\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n\n\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n\n\t\t\t// Update function for both resolve and progress values\n\t\t\tupdateFunc = function( i, contexts, values ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tcontexts[ i ] = this;\n\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( values === progressValues ) {\n\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n\t\t\t\t\t} else if ( !( --remaining ) ) {\n\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t},\n\n\t\t\tprogressValues, progressContexts, resolveContexts;\n\n\t\t// Add listeners to Deferred subordinates; treat others as resolved\n\t\tif ( length > 1 ) {\n\t\t\tprogressValues = new Array( length );\n\t\t\tprogressContexts = new Array( length );\n\t\t\tresolveContexts = new Array( length );\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n\t\t\t\t\tresolveValues[ i ].promise()\n\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n\t\t\t\t\t\t.fail( deferred.reject )\n\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n\t\t\t\t} else {\n\t\t\t\t\t--remaining;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// If we're not waiting on anything, resolve the master\n\t\tif ( !remaining ) {\n\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n\t\t}\n\n\t\treturn deferred.promise();\n\t}\n});\n\n\n// The deferred used on DOM ready\nvar readyList;\n\njQuery.fn.ready = function( fn ) {\n\t// Add the callback\n\tjQuery.ready.promise().done( fn );\n\n\treturn this;\n};\n\njQuery.extend({\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\n\t\t// Trigger any bound ready events\n\t\tif ( jQuery.fn.triggerHandler ) {\n\t\t\tjQuery( document ).triggerHandler( \"ready\" );\n\t\t\tjQuery( document ).off( \"ready\" );\n\t\t}\n\t}\n});\n\n/**\n * The ready event handler and self cleanup method\n */\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed, false );\n\twindow.removeEventListener( \"load\", completed, false );\n\tjQuery.ready();\n}\n\njQuery.ready.promise = function( obj ) {\n\tif ( !readyList ) {\n\n\t\treadyList = jQuery.Deferred();\n\n\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n\t\t// We once tried to use readyState \"interactive\" here, but it caused issues like the one\n\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n\t\tif ( document.readyState === \"complete\" ) {\n\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\t\t\tsetTimeout( jQuery.ready );\n\n\t\t} else {\n\n\t\t\t// Use the handy event callback\n\t\t\tdocument.addEventListener( \"DOMContentLoaded\", completed, false );\n\n\t\t\t// A fallback to window.onload, that will always work\n\t\t\twindow.addEventListener( \"load\", completed, false );\n\t\t}\n\t}\n\treturn readyList.promise( obj );\n};\n\n// Kick off the DOM ready check even if the user does not\njQuery.ready.promise();\n\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( jQuery.type( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn chainable ?\n\t\telems :\n\n\t\t// Gets\n\t\tbulk ?\n\t\t\tfn.call( elems ) :\n\t\t\tlen ? fn( elems[0], key ) : emptyGet;\n};\n\n\n/**\n * Determines whether an object can have data\n */\njQuery.acceptData = function( owner ) {\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\t/* jshint -W018 */\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\nfunction Data() {\n\t// Support: Android<4,\n\t// Old WebKit does not have Object.preventExtensions/freeze method,\n\t// return new empty object instead with no [[set]] accessor\n\tObject.defineProperty( this.cache = {}, 0, {\n\t\tget: function() {\n\t\t\treturn {};\n\t\t}\n\t});\n\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\nData.accepts = jQuery.acceptData;\n\nData.prototype = {\n\tkey: function( owner ) {\n\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t// but we should not, see #8335.\n\t\t// Always return the key for a frozen object.\n\t\tif ( !Data.accepts( owner ) ) {\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar descriptor = {},\n\t\t\t// Check if the owner object already has a cache key\n\t\t\tunlock = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !unlock ) {\n\t\t\tunlock = Data.uid++;\n\n\t\t\t// Secure it in a non-enumerable, non-writable property\n\t\t\ttry {\n\t\t\t\tdescriptor[ this.expando ] = { value: unlock };\n\t\t\t\tObject.defineProperties( owner, descriptor );\n\n\t\t\t// Support: Android<4\n\t\t\t// Fallback to a less secure definition\n\t\t\t} catch ( e ) {\n\t\t\t\tdescriptor[ this.expando ] = unlock;\n\t\t\t\tjQuery.extend( owner, descriptor );\n\t\t\t}\n\t\t}\n\n\t\t// Ensure the cache object\n\t\tif ( !this.cache[ unlock ] ) {\n\t\t\tthis.cache[ unlock ] = {};\n\t\t}\n\n\t\treturn unlock;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\t// There may be an unlock assigned to this node,\n\t\t\t// if there is no entry for this \"owner\", create one inline\n\t\t\t// and set the unlock as though an owner entry had always existed\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\t// Handle: [ owner, key, value ] args\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ data ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\t\t\t// Fresh assignments by object are shallow copied\n\t\t\tif ( jQuery.isEmptyObject( cache ) ) {\n\t\t\t\tjQuery.extend( this.cache[ unlock ], data );\n\t\t\t// Otherwise, copy the properties one-by-one to the cache object\n\t\t\t} else {\n\t\t\t\tfor ( prop in data ) {\n\t\t\t\t\tcache[ prop ] = data[ prop ];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\t// Either a valid cache is found, or will be created.\n\t\t// New caches will be created and the unlock returned,\n\t\t// allowing direct access to the newly created\n\t\t// empty data object. A valid owner object must be provided.\n\t\tvar cache = this.cache[ this.key( owner ) ];\n\n\t\treturn key === undefined ?\n\t\t\tcache : cache[ key ];\n\t},\n\taccess: function( owner, key, value ) {\n\t\tvar stored;\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t((key && typeof key === \"string\") && value === undefined) ) {\n\n\t\t\tstored = this.get( owner, key );\n\n\t\t\treturn stored !== undefined ?\n\t\t\t\tstored : this.get( owner, jQuery.camelCase(key) );\n\t\t}\n\n\t\t// [*]When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i, name, camel,\n\t\t\tunlock = this.key( owner ),\n\t\t\tcache = this.cache[ unlock ];\n\n\t\tif ( key === undefined ) {\n\t\t\tthis.cache[ unlock ] = {};\n\n\t\t} else {\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( jQuery.isArray( key ) ) {\n\t\t\t\t// If \"name\" is an array of keys...\n\t\t\t\t// When data is initially created, via (\"key\", \"val\") signature,\n\t\t\t\t// keys will be converted to camelCase.\n\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n\t\t\t\t// both plain key and camelCase key. #12786\n\t\t\t\t// This will only penalize the array argument path.\n\t\t\t\tname = key.concat( key.map( jQuery.camelCase ) );\n\t\t\t} else {\n\t\t\t\tcamel = jQuery.camelCase( key );\n\t\t\t\t// Try the string as a key before any manipulation\n\t\t\t\tif ( key in cache ) {\n\t\t\t\t\tname = [ key, camel ];\n\t\t\t\t} else {\n\t\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\t\tname = camel;\n\t\t\t\t\tname = name in cache ?\n\t\t\t\t\t\t[ name ] : ( name.match( rnotwhite ) || [] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ti = name.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ name[ i ] ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\treturn !jQuery.isEmptyObject(\n\t\t\tthis.cache[ owner[ this.expando ] ] || {}\n\t\t);\n\t},\n\tdiscard: function( owner ) {\n\t\tif ( owner[ this.expando ] ) {\n\t\t\tdelete this.cache[ owner[ this.expando ] ];\n\t\t}\n\t}\n};\nvar data_priv = new Data();\n\nvar data_user = new Data();\n\n\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /([A-Z])/g;\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$1\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = data === \"true\" ? true :\n\t\t\t\t\tdata === \"false\" ? false :\n\t\t\t\t\tdata === \"null\" ? null :\n\t\t\t\t\t// Only convert to a number if it doesn't change the string\n\t\t\t\t\t+data + \"\" === data ? +data :\n\t\t\t\t\trbrace.test( data ) ? jQuery.parseJSON( data ) :\n\t\t\t\t\tdata;\n\t\t\t} catch( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdata_user.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend({\n\thasData: function( elem ) {\n\t\treturn data_user.hasData( elem ) || data_priv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn data_user.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdata_user.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to data_priv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn data_priv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdata_priv.remove( elem, name );\n\t}\n});\n\njQuery.fn.extend({\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = data_user.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !data_priv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE11+\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdata_priv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each(function() {\n\t\t\t\tdata_user.set( this, key );\n\t\t\t});\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data,\n\t\t\t\tcamelKey = jQuery.camelCase( key );\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key as-is\n\t\t\t\tdata = data_user.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// with the key camelized\n\t\t\t\tdata = data_user.get( elem, camelKey );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, camelKey, undefined );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each(function() {\n\t\t\t\t// First, attempt to store a copy or reference of any\n\t\t\t\t// data that might've been store with a camelCased key.\n\t\t\t\tvar data = data_user.get( this, camelKey );\n\n\t\t\t\t// For HTML5 data-* attribute interop, we have to\n\t\t\t\t// store property names with dashes in a camelCase form.\n\t\t\t\t// This might not apply to all properties...*\n\t\t\t\tdata_user.set( this, camelKey, value );\n\n\t\t\t\t// *... In the case of properties that might _actually_\n\t\t\t\t// have dashes, we need to also store a copy of that\n\t\t\t\t// unchanged property.\n\t\t\t\tif ( key.indexOf(\"-\") !== -1 && data !== undefined ) {\n\t\t\t\t\tdata_user.set( this, key, value );\n\t\t\t\t}\n\t\t\t});\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each(function() {\n\t\t\tdata_user.remove( this, key );\n\t\t});\n\t}\n});\n\n\njQuery.extend({\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = data_priv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n\t\t\t\t\tqueue = data_priv.access( elem, type, jQuery.makeArray(data) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// Clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// Not public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn data_priv.get( elem, key ) || data_priv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks(\"once memory\").add(function() {\n\t\t\t\tdata_priv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t})\n\t\t});\n\t}\n});\n\njQuery.fn.extend({\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[0], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each(function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[0] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t});\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t});\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = data_priv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n});\nvar pnum = (/[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/).source;\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHidden = function( elem, el ) {\n\t\t// isHidden might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\t\treturn jQuery.css( elem, \"display\" ) === \"none\" || !jQuery.contains( elem.ownerDocument, elem );\n\t};\n\nvar rcheckableType = (/^(?:checkbox|radio)$/i);\n\n\n\n(function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Safari<=5.1\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Safari<=5.1, Android<4.2\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE<=11+\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n})();\nvar strundefined = typeof undefined;\n\n\n\nsupport.focusinBubbles = \"onfocusin\" in window;\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,\n\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !(events = elemData.events) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !(eventHandle = elemData.handle) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== strundefined && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend({\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join(\".\")\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !(handlers = events[ type ]) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = data_priv.hasData( elem ) && data_priv.get( elem );\n\n\t\tif ( !elemData || !(events = elemData.events) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnotwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n\t\t\ttype = origType = tmp[1];\n\t\t\tnamespaces = ( tmp[2] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[2] && new RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector || selector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdelete elemData.handle;\n\t\t\tdata_priv.remove( elem, \"events\" );\n\t\t}\n\t},\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split(\".\") : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf(\".\") >= 0 ) {\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split(\".\");\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf(\":\") < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join(\".\");\n\t\tevent.namespace_re = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join(\"\\\\.(?:.*\\\\.|)\") + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( data_priv.get( cur, \"events\" ) || {} )[ event.type ] && data_priv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && jQuery.acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&\n\t\t\t\tjQuery.acceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\tdispatch: function( event ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tevent = jQuery.event.fix( event );\n\n\t\tvar i, j, ret, matched, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\targs = slice.call( arguments ),\n\t\t\thandlers = ( data_priv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[0] = event;\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or 2) have namespace(s)\n\t\t\t\t// a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n\t\t\t\t\t\t\t.apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, matches, sel, handleObj,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\t// Black-hole SVG <use> instance trees (#13180)\n\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== \"click\") ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.disabled !== true || event.type !== \"click\" ) {\n\t\t\t\t\tmatches = [];\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matches[ sel ] ) {\n\t\t\t\t\t\t\tmatches.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matches.length ) {\n\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\t// Includes some event props shared by KeyEvent and MouseEvent\n\tprops: \"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which\".split(\" \"),\n\n\tfixHooks: {},\n\n\tkeyHooks: {\n\t\tprops: \"char charCode key keyCode\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\n\t\t\t// Add which for key events\n\t\t\tif ( event.which == null ) {\n\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tmouseHooks: {\n\t\tprops: \"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement\".split(\" \"),\n\t\tfilter: function( event, original ) {\n\t\t\tvar eventDoc, doc, body,\n\t\t\t\tbutton = original.button;\n\n\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n\t\t\tif ( event.pageX == null && original.clientX != null ) {\n\t\t\t\teventDoc = event.target.ownerDocument || document;\n\t\t\t\tdoc = eventDoc.documentElement;\n\t\t\t\tbody = eventDoc.body;\n\n\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n\t\t\t}\n\n\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\t\t// Note: button is not normalized, so don't use it\n\t\t\tif ( !event.which && button !== undefined ) {\n\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n\t\t\t}\n\n\t\t\treturn event;\n\t\t}\n\t},\n\n\tfix: function( event ) {\n\t\tif ( event[ jQuery.expando ] ) {\n\t\t\treturn event;\n\t\t}\n\n\t\t// Create a writable copy of the event object and normalize some properties\n\t\tvar i, prop, copy,\n\t\t\ttype = event.type,\n\t\t\toriginalEvent = event,\n\t\t\tfixHook = this.fixHooks[ type ];\n\n\t\tif ( !fixHook ) {\n\t\t\tthis.fixHooks[ type ] = fixHook =\n\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n\t\t\t\t{};\n\t\t}\n\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n\n\t\tevent = new jQuery.Event( originalEvent );\n\n\t\ti = copy.length;\n\t\twhile ( i-- ) {\n\t\t\tprop = copy[ i ];\n\t\t\tevent[ prop ] = originalEvent[ prop ];\n\t\t}\n\n\t\t// Support: Cordova 2.5 (WebKit) (#13255)\n\t\t// All events should have a target; Cordova deviceready doesn't\n\t\tif ( !event.target ) {\n\t\t\tevent.target = document;\n\t\t}\n\n\t\t// Support: Safari 6.0+, Chrome<28\n\t\t// Target should not be a text node (#504, #13143)\n\t\tif ( event.target.nodeType === 3 ) {\n\t\t\tevent.target = event.target.parentNode;\n\t\t}\n\n\t\treturn fixHook.filter ? fixHook.filter( event, originalEvent ) : event;\n\t},\n\n\tspecial: {\n\t\tload: {\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\tthis.focus();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this.type === \"checkbox\" && this.click && jQuery.nodeName( this, \"input\" ) ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tsimulate: function( type, elem, event, bubble ) {\n\t\t// Piggyback on a donor event to simulate a different one.\n\t\t// Fake originalEvent to avoid donor's stopPropagation, but if the\n\t\t// simulated event prevents default then we do the same on the donor.\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true,\n\t\t\t\toriginalEvent: {}\n\t\t\t}\n\t\t);\n\t\tif ( bubble ) {\n\t\t\tjQuery.event.trigger( e, null, elem );\n\t\t} else {\n\t\t\tjQuery.event.dispatch.call( elem, e );\n\t\t}\n\t\tif ( e.isDefaultPrevented() ) {\n\t\t\tevent.preventDefault();\n\t\t}\n\t}\n};\n\njQuery.removeEvent = function( elem, type, handle ) {\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle, false );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\t// Allow instantiation without the 'new' keyword\n\tif ( !(this instanceof jQuery.Event) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\t\t\t\t// Support: Android<4.0\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && e.preventDefault ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopPropagation ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && e.stopImmediatePropagation ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// Support: Chrome 15+\njQuery.each({\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mousenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n});\n\n// Support: Firefox, Chrome, Safari\n// Create \"bubbling\" focus and blur events\nif ( !support.focusinBubbles ) {\n\tjQuery.each({ focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n\t\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = data_priv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdata_priv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = data_priv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdata_priv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdata_priv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t});\n}\n\njQuery.fn.extend({\n\n\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n\t\tvar origFn, type;\n\n\t\t// Types can be a map of types/handlers\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-Object, selector, data )\n\t\t\tif ( typeof selector !== \"string\" ) {\n\t\t\t\t// ( types-Object, data )\n\t\t\t\tdata = data || selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( data == null && fn == null ) {\n\t\t\t// ( types, fn )\n\t\t\tfn = selector;\n\t\t\tdata = selector = undefined;\n\t\t} else if ( fn == null ) {\n\t\t\tif ( typeof selector === \"string\" ) {\n\t\t\t\t// ( types, selector, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = undefined;\n\t\t\t} else {\n\t\t\t\t// ( types, data, fn )\n\t\t\t\tfn = data;\n\t\t\t\tdata = selector;\n\t\t\t\tselector = undefined;\n\t\t\t}\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t} else if ( !fn ) {\n\t\t\treturn this;\n\t\t}\n\n\t\tif ( one === 1 ) {\n\t\t\torigFn = fn;\n\t\t\tfn = function( event ) {\n\t\t\t\t// Can use an empty set, since event contains the info\n\t\t\t\tjQuery().off( event );\n\t\t\t\treturn origFn.apply( this, arguments );\n\t\t\t};\n\t\t\t// Use same guid so caller can remove using origFn\n\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.add( this, types, fn, data, selector );\n\t\t});\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn this.on( types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ? handleObj.origType + \".\" + handleObj.namespace : handleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t});\n\t},\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t});\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[0];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n});\n\n\nvar\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n\trtagName = /<([\\w:]+)/,\n\trhtml = /<|&#?\\w+;/,\n\trnoInnerhtml = /<(?:script|style|link)/i,\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptType = /^$|\\/(?:java|ecma)script/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n\n\t// We have to close these tags to support XHTML (#13200)\n\twrapMap = {\n\n\t\t// Support: IE9\n\t\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t\tthead: [ 1, \"<table>\", \"</table>\" ],\n\t\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\t\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\t\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t\t_default: [ 0, \"\", \"\" ]\n\t};\n\n// Support: IE9\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n// Support: 1.x compatibility\n// Manipulating tables requires a tbody\nfunction manipulationTarget( elem, content ) {\n\treturn jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ?\n\n\t\telem.getElementsByTagName(\"tbody\")[0] ||\n\t\t\telem.appendChild( elem.ownerDocument.createElement(\"tbody\") ) :\n\t\telem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = (elem.getAttribute(\"type\") !== null) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\tif ( match ) {\n\t\telem.type = match[ 1 ];\n\t} else {\n\t\telem.removeAttribute(\"type\");\n\t}\n\n\treturn elem;\n}\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdata_priv.set(\n\t\t\telems[ i ], \"globalEval\", !refElements || data_priv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( data_priv.hasData( src ) ) {\n\t\tpdataOld = data_priv.access( src );\n\t\tpdataCur = data_priv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( data_user.hasData( src ) ) {\n\t\tudataOld = data_user.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdata_user.set( dest, udataCur );\n\t}\n}\n\nfunction getAll( context, tag ) {\n\tvar ret = context.getElementsByTagName ? context.getElementsByTagName( tag || \"*\" ) :\n\t\t\tcontext.querySelectorAll ? context.querySelectorAll( tag || \"*\" ) :\n\t\t\t[];\n\n\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n\t\tjQuery.merge( [ context ], ret ) :\n\t\tret;\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\njQuery.extend({\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tbuildFragment: function( elems, context, scripts, selection ) {\n\t\tvar elem, tmp, tag, wrap, contains, j,\n\t\t\tfragment = context.createDocumentFragment(),\n\t\t\tnodes = [],\n\t\t\ti = 0,\n\t\t\tl = elems.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\telem = elems[ i ];\n\n\t\t\tif ( elem || elem === 0 ) {\n\n\t\t\t\t// Add nodes directly\n\t\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\t\t\t\t\t// Support: QtWebKit, PhantomJS\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t\t// Convert non-html into a text node\n\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t\t// Convert html into DOM nodes\n\t\t\t\t} else {\n\t\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement(\"div\") );\n\n\t\t\t\t\t// Deserialize a standard representation\n\t\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\t\ttmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, \"<$1></$2>\" ) + wrap[ 2 ];\n\n\t\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\t\tj = wrap[ 0 ];\n\t\t\t\t\twhile ( j-- ) {\n\t\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: QtWebKit, PhantomJS\n\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t\t// Remember the top-level container\n\t\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\t\ttmp.textContent = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Remove wrapper from fragment\n\t\tfragment.textContent = \"\";\n\n\t\ti = 0;\n\t\twhile ( (elem = nodes[ i++ ]) ) {\n\n\t\t\t// #4087 - If origin and destination elements are the same, and this is\n\t\t\t// that element, do not do anything\n\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t\t// Append to fragment\n\t\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t\t// Preserve script evaluation history\n\t\t\tif ( contains ) {\n\t\t\t\tsetGlobalEval( tmp );\n\t\t\t}\n\n\t\t\t// Capture executables\n\t\t\tif ( scripts ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n\t\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\t\tscripts.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn fragment;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type, key,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[ i ]) !== undefined; i++ ) {\n\t\t\tif ( jQuery.acceptData( elem ) ) {\n\t\t\t\tkey = elem[ data_priv.expando ];\n\n\t\t\t\tif ( key && (data = data_priv.cache[ key ]) ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( data_priv.cache[ key ] ) {\n\t\t\t\t\t\t// Discard any remaining `private` data\n\t\t\t\t\t\tdelete data_priv.cache[ key ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Discard any remaining `user` data\n\t\t\tdelete data_user.cache[ elem[ data_user.expando ] ];\n\t\t}\n\t}\n});\n\njQuery.fn.extend({\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each(function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t});\n\t},\n\n\tprepend: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t});\n\t},\n\n\tbefore: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t});\n\t},\n\n\tafter: function() {\n\t\treturn this.domManip( arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t});\n\t},\n\n\tremove: function( selector, keepData /* Internal Use Only */ ) {\n\t\tvar elem,\n\t\t\telems = selector ? jQuery.filter( selector, this ) : this,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n\t\t\t\tjQuery.cleanData( getAll( elem ) );\n\t\t\t}\n\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\t\t\tsetGlobalEval( getAll( elem, \"script\" ) );\n\t\t\t\t}\n\t\t\t\telem.parentNode.removeChild( elem );\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map(function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t});\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = value.replace( rxhtmlTag, \"<$1></$2>\" );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar arg = arguments[ 0 ];\n\n\t\t// Make the changes, replacing each context element with the new content\n\t\tthis.domManip( arguments, function( elem ) {\n\t\t\targ = this.parentNode;\n\n\t\t\tjQuery.cleanData( getAll( this ) );\n\n\t\t\tif ( arg ) {\n\t\t\t\targ.replaceChild( elem, this );\n\t\t\t}\n\t\t});\n\n\t\t// Force removal if there was no new content (e.g., from empty arguments)\n\t\treturn arg && (arg.length || arg.nodeType) ? this : this.remove();\n\t},\n\n\tdetach: function( selector ) {\n\t\treturn this.remove( selector, true );\n\t},\n\n\tdomManip: function( args, callback ) {\n\n\t\t// Flatten any nested arrays\n\t\targs = concat.apply( [], args );\n\n\t\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tset = this,\n\t\t\tiNoClone = l - 1,\n\t\t\tvalue = args[ 0 ],\n\t\t\tisFunction = jQuery.isFunction( value );\n\n\t\t// We can't cloneNode fragments that contain checked, in WebKit\n\t\tif ( isFunction ||\n\t\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\t\treturn this.each(function( index ) {\n\t\t\t\tvar self = set.eq( index );\n\t\t\t\tif ( isFunction ) {\n\t\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t\t}\n\t\t\t\tself.domManip( args, callback );\n\t\t\t});\n\t\t}\n\n\t\tif ( l ) {\n\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );\n\t\t\tfirst = fragment.firstChild;\n\n\t\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\t\tfragment = first;\n\t\t\t}\n\n\t\t\tif ( first ) {\n\t\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\t\thasScripts = scripts.length;\n\n\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tnode = fragment;\n\n\t\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\t\t\t// Support: QtWebKit\n\t\t\t\t\t\t\t// jQuery.merge because push.apply(_, arraylike) throws\n\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcallback.call( this[ i ], node, i );\n\t\t\t\t}\n\n\t\t\t\tif ( hasScripts ) {\n\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t\t// Reenable scripts\n\t\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t\t!data_priv.access( node, \"globalEval\" ) && jQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\t\tif ( node.src ) {\n\t\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.globalEval( node.textContent.replace( rcleanScript, \"\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t}\n});\n\njQuery.each({\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: QtWebKit\n\t\t\t// .get() because push.apply(_, arraylike) throws\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n});\n\n\nvar iframe,\n\telemdisplay = {};\n\n/**\n * Retrieve the actual display of a element\n * @param {String} name nodeName of the element\n * @param {Object} doc Document object\n */\n// Called only from within defaultDisplay\nfunction actualDisplay( name, doc ) {\n\tvar style,\n\t\telem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n\n\t\t// getDefaultComputedStyle might be reliably used only on attached element\n\t\tdisplay = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?\n\n\t\t\t// Use of this method is a temporary fix (more like optimization) until something better comes along,\n\t\t\t// since it was removed from specification and supported only in FF\n\t\t\tstyle.display : jQuery.css( elem[ 0 ], \"display\" );\n\n\t// We don't have any data stored on the element,\n\t// so use \"detach\" method as fast way to get rid of the element\n\telem.detach();\n\n\treturn display;\n}\n\n/**\n * Try to determine the default display value of an element\n * @param {String} nodeName\n */\nfunction defaultDisplay( nodeName ) {\n\tvar doc = document,\n\t\tdisplay = elemdisplay[ nodeName ];\n\n\tif ( !display ) {\n\t\tdisplay = actualDisplay( nodeName, doc );\n\n\t\t// If the simple way fails, read from inside an iframe\n\t\tif ( display === \"none\" || !display ) {\n\n\t\t\t// Use the already-created iframe if possible\n\t\t\tiframe = (iframe || jQuery( \"<iframe frameborder='0' width='0' height='0'/>\" )).appendTo( doc.documentElement );\n\n\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse\n\t\t\tdoc = iframe[ 0 ].contentDocument;\n\n\t\t\t// Support: IE\n\t\t\tdoc.write();\n\t\t\tdoc.close();\n\n\t\t\tdisplay = actualDisplay( nodeName, doc );\n\t\t\tiframe.detach();\n\t\t}\n\n\t\t// Store the correct default display\n\t\telemdisplay[ nodeName ] = display;\n\t}\n\n\treturn display;\n}\nvar rmargin = (/^margin/);\n\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar getStyles = function( elem ) {\n\t\t// Support: IE<=11+, Firefox<=30+ (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tif ( elem.ownerDocument.defaultView.opener ) {\n\t\t\treturn elem.ownerDocument.defaultView.getComputedStyle( elem, null );\n\t\t}\n\n\t\treturn window.getComputedStyle( elem, null );\n\t};\n\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// Support: IE9\n\t// getPropertyValue is only needed for .css('filter') (#12537)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\t}\n\n\tif ( computed ) {\n\n\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// Support: iOS < 6\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// iOS < 6 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\t\t// Support: IE\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn (this.get = hookFn).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\n(function() {\n\tvar pixelPositionVal, boxSizingReliableVal,\n\t\tdocElem = document.documentElement,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE9-11+\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tcontainer.style.cssText = \"border:0;width:0;height:0;top:0;left:-9999px;margin-top:1px;\" +\n\t\t\"position:absolute\";\n\tcontainer.appendChild( div );\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computePixelPositionAndBoxSizingReliable() {\n\t\tdiv.style.cssText =\n\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t// Vendor-prefix box-sizing\n\t\t\t\"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;\" +\n\t\t\t\"box-sizing:border-box;display:block;margin-top:1%;top:1%;\" +\n\t\t\t\"border:1px;padding:1px;width:4px;position:absolute\";\n\t\tdiv.innerHTML = \"\";\n\t\tdocElem.appendChild( container );\n\n\t\tvar divStyle = window.getComputedStyle( div, null );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\t\tboxSizingReliableVal = divStyle.width === \"4px\";\n\n\t\tdocElem.removeChild( container );\n\t}\n\n\t// Support: node.js jsdom\n\t// Don't assume that getComputedStyle is a property of the global object\n\tif ( window.getComputedStyle ) {\n\t\tjQuery.extend( support, {\n\t\t\tpixelPosition: function() {\n\n\t\t\t\t// This test is executed only once but we still do memoizing\n\t\t\t\t// since we can use the boxSizingReliable pre-computing.\n\t\t\t\t// No need to check if the test was already performed, though.\n\t\t\t\tcomputePixelPositionAndBoxSizingReliable();\n\t\t\t\treturn pixelPositionVal;\n\t\t\t},\n\t\t\tboxSizingReliable: function() {\n\t\t\t\tif ( boxSizingReliableVal == null ) {\n\t\t\t\t\tcomputePixelPositionAndBoxSizingReliable();\n\t\t\t\t}\n\t\t\t\treturn boxSizingReliableVal;\n\t\t\t},\n\t\t\treliableMarginRight: function() {\n\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Check if div with explicit width and no margin-right incorrectly\n\t\t\t\t// gets computed margin-right based on width of container. (#3333)\n\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n\t\t\t\t// This support function is only executed once so no memoizing is needed.\n\t\t\t\tvar ret,\n\t\t\t\t\tmarginDiv = div.appendChild( document.createElement( \"div\" ) );\n\n\t\t\t\t// Reset CSS: box-sizing; display; margin; border; padding\n\t\t\t\tmarginDiv.style.cssText = div.style.cssText =\n\t\t\t\t\t// Support: Firefox<29, Android 2.3\n\t\t\t\t\t// Vendor-prefix box-sizing\n\t\t\t\t\t\"-webkit-box-sizing:content-box;-moz-box-sizing:content-box;\" +\n\t\t\t\t\t\"box-sizing:content-box;display:block;margin:0;border:0;padding:0\";\n\t\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = \"0\";\n\t\t\t\tdiv.style.width = \"1px\";\n\t\t\t\tdocElem.appendChild( container );\n\n\t\t\t\tret = !parseFloat( window.getComputedStyle( marginDiv, null ).marginRight );\n\n\t\t\t\tdocElem.removeChild( container );\n\t\t\t\tdiv.removeChild( marginDiv );\n\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t});\n\t}\n})();\n\n\n// A method for quickly swapping in/out CSS properties to get correct calculations.\njQuery.swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\nvar\n\t// Swappable if display is none or starts with table except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\trnumsplit = new RegExp( \"^(\" + pnum + \")(.*)$\", \"i\" ),\n\trrelNum = new RegExp( \"^([+-])=(\" + pnum + \")\", \"i\" ),\n\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t},\n\n\tcssPrefixes = [ \"Webkit\", \"O\", \"Moz\", \"ms\" ];\n\n// Return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( style, name ) {\n\n\t// Shortcut for names that are not vendor prefixed\n\tif ( name in style ) {\n\t\treturn name;\n\t}\n\n\t// Check for vendor prefixed names\n\tvar capName = name[0].toUpperCase() + name.slice(1),\n\t\torigName = name,\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in style ) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn origName;\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\tvar matches = rnumsplit.exec( value );\n\treturn matches ?\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i = extra === ( isBorderBox ? \"border\" : \"content\" ) ?\n\t\t// If we already have the right measurement, avoid augmentation\n\t\t4 :\n\t\t// Otherwise initialize for horizontal or vertical properties\n\t\tname === \"width\" ? 1 : 0,\n\n\t\tval = 0;\n\n\tfor ( ; i < 4; i += 2 ) {\n\t\t// Both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// At this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\t\t\t// At this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// At this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar valueIsBorderBox = true,\n\t\tval = name === \"width\" ? elem.offsetWidth : elem.offsetHeight,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// Some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test(val) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// Check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox &&\n\t\t\t( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// Use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem, hidden,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tvalues[ index ] = data_priv.get( elem, \"olddisplay\" );\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\t\t\t// Reset the inline display of this element to learn if it is\n\t\t\t// being hidden by cascaded rules or not\n\t\t\tif ( !values[ index ] && display === \"none\" ) {\n\t\t\t\telem.style.display = \"\";\n\t\t\t}\n\n\t\t\t// Set elements which have been overridden with display: none\n\t\t\t// in a stylesheet to whatever the default browser style is\n\t\t\t// for such an element\n\t\t\tif ( elem.style.display === \"\" && isHidden( elem ) ) {\n\t\t\t\tvalues[ index ] = data_priv.access( elem, \"olddisplay\", defaultDisplay(elem.nodeName) );\n\t\t\t}\n\t\t} else {\n\t\t\thidden = isHidden( elem );\n\n\t\t\tif ( display !== \"none\" || !hidden ) {\n\t\t\t\tdata_priv.set( elem, \"olddisplay\", hidden ? display : jQuery.css( elem, \"display\" ) );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of most of the elements in a second loop\n\t// to avoid the constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\t\tif ( !show || elem.style.display === \"none\" || elem.style.display === \"\" ) {\n\t\t\telem.style.display = show ? values[ index ] || \"\" : \"none\";\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.extend({\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t\"float\": \"cssFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n\n\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && (ret = rrelNum.exec( value )) ) {\n\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number, add 'px' to the (except for certain CSS properties)\n\t\t\tif ( type === \"number\" && !jQuery.cssNumber[ origName ] ) {\n\t\t\t\tvalue += \"px\";\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// background-* props affect original clone's values\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !(\"set\" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n\t\t\t\tstyle[ name ] = value;\n\t\t\t}\n\n\t\t} else {\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n\n\t\t// Try prefixed name followed by the unprefixed name\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t// Convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t}\n});\n\njQuery.each([ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) && elem.offsetWidth === 0 ?\n\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t}) :\n\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar styles = extra && getStyles( elem );\n\t\t\treturn setPositiveNumber( elem, value, extra ?\n\t\t\t\taugmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t) : 0\n\t\t\t);\n\t\t}\n\t};\n});\n\n// Support: Android 2.3\njQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn jQuery.swap( elem, { \"display\": \"inline-block\" },\n\t\t\t\tcurCSS, [ elem, \"marginRight\" ] );\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each({\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// Assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split(\" \") : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n});\n\njQuery.fn.extend({\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t},\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( isHidden( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t});\n\t}\n});\n\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || \"swing\";\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\tif ( tween.elem[ tween.prop ] != null &&\n\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// Passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails.\n\t\t\t// Simple values such as \"10px\" are parsed to Float;\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as-is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\t\t\t// Use step hook for back compat.\n\t\t\t// Use cssHook if its there.\n\t\t\t// Use .style if available and use plain properties where available.\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE9\n// Panic based approach to setting things on disconnected nodes\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t}\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back Compat <1.8 extension point\njQuery.fx.step = {};\n\n\n\n\nvar\n\tfxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trfxnum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" ),\n\trrun = /queueHooks$/,\n\tanimationPrefilters = [ defaultPrefilter ],\n\ttweeners = {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value ),\n\t\t\t\ttarget = tween.cur(),\n\t\t\t\tparts = rfxnum.exec( value ),\n\t\t\t\tunit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t\t\t// Starting value computation is required for potential unit mismatches\n\t\t\t\tstart = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +target ) &&\n\t\t\t\t\trfxnum.exec( jQuery.css( tween.elem, prop ) ),\n\t\t\t\tscale = 1,\n\t\t\t\tmaxIterations = 20;\n\n\t\t\tif ( start && start[ 3 ] !== unit ) {\n\t\t\t\t// Trust units reported by jQuery.css\n\t\t\t\tunit = unit || start[ 3 ];\n\n\t\t\t\t// Make sure we update the tween properties later on\n\t\t\t\tparts = parts || [];\n\n\t\t\t\t// Iteratively approximate from a nonzero starting point\n\t\t\t\tstart = +target || 1;\n\n\t\t\t\tdo {\n\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*.\n\t\t\t\t\t// Use string for doubling so we don't accidentally see scale as unchanged below\n\t\t\t\t\tscale = scale || \".5\";\n\n\t\t\t\t\t// Adjust and apply\n\t\t\t\t\tstart = start / scale;\n\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n\n\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur(),\n\t\t\t\t// break the loop if scale is unchanged or perfect, or if we've just had enough\n\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n\t\t\t}\n\n\t\t\t// Update tween properties\n\t\t\tif ( parts ) {\n\t\t\t\tstart = tween.start = +start || +target || 0;\n\t\t\t\ttween.unit = unit;\n\t\t\t\t// If a +=/-= token was provided, we're doing a relative animation\n\t\t\t\ttween.end = parts[ 1 ] ?\n\t\t\t\t\tstart + ( parts[ 1 ] + 1 ) * parts[ 2 ] :\n\t\t\t\t\t+parts[ 2 ];\n\t\t\t}\n\n\t\t\treturn tween;\n\t\t} ]\n\t};\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\tsetTimeout(function() {\n\t\tfxNow = undefined;\n\t});\n\treturn ( fxNow = jQuery.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\ti = 0,\n\t\tattrs = { height: type };\n\n\t// If we include width, step value is 1 to do all cssExpand values,\n\t// otherwise step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4 ; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( tweeners[ prop ] || [] ).concat( tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( (tween = collection[ index ].call( animation, prop, value )) ) {\n\n\t\t\t// We're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\t/* jshint validthis: true */\n\tvar prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHidden( elem ),\n\t\tdataShow = data_priv.get( elem, \"fxshow\" );\n\n\t// Handle queue: false promises\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always(function() {\n\t\t\t// Ensure the complete handler is called before this completes\n\t\t\tanim.always(function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t// Height/width overflow pass\n\tif ( elem.nodeType === 1 && ( \"height\" in props || \"width\" in props ) ) {\n\t\t// Make sure that nothing sneaks out\n\t\t// Record all 3 overflow attributes because IE9-10 do not\n\t\t// change the overflow attribute when overflowX and\n\t\t// overflowY are set to the same value\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Set display property to inline-block for height/width\n\t\t// animations on inline elements that are having width/height animated\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\n\t\t// Test default display if display is currently \"none\"\n\t\tcheckDisplay = display === \"none\" ?\n\t\t\tdata_priv.get( elem, \"olddisplay\" ) || defaultDisplay( elem.nodeName ) : display;\n\n\t\tif ( checkDisplay === \"inline\" && jQuery.css( elem, \"float\" ) === \"none\" ) {\n\t\t\tstyle.display = \"inline-block\";\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always(function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t});\n\t}\n\n\t// show/hide pass\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.exec( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\n\t\t// Any non-fx value stops us from restoring the original display value\n\t\t} else {\n\t\t\tdisplay = undefined;\n\t\t}\n\t}\n\n\tif ( !jQuery.isEmptyObject( orig ) ) {\n\t\tif ( dataShow ) {\n\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\thidden = dataShow.hidden;\n\t\t\t}\n\t\t} else {\n\t\t\tdataShow = data_priv.access( elem, \"fxshow\", {} );\n\t\t}\n\n\t\t// Store state if its toggle - enables .stop().toggle() to \"reverse\"\n\t\tif ( toggle ) {\n\t\t\tdataShow.hidden = !hidden;\n\t\t}\n\t\tif ( hidden ) {\n\t\t\tjQuery( elem ).show();\n\t\t} else {\n\t\t\tanim.done(function() {\n\t\t\t\tjQuery( elem ).hide();\n\t\t\t});\n\t\t}\n\t\tanim.done(function() {\n\t\t\tvar prop;\n\n\t\t\tdata_priv.remove( elem, \"fxshow\" );\n\t\t\tfor ( prop in orig ) {\n\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t}\n\t\t});\n\t\tfor ( prop in orig ) {\n\t\t\ttween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\n\t\t\tif ( !( prop in dataShow ) ) {\n\t\t\t\tdataShow[ prop ] = tween.start;\n\t\t\t\tif ( hidden ) {\n\t\t\t\t\ttween.end = tween.start;\n\t\t\t\t\ttween.start = prop === \"width\" || prop === \"height\" ? 1 : 0;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t// If this is a noop like .hide().hide(), restore an overwritten display value\n\t} else if ( (display === \"none\" ? defaultDisplay( elem.nodeName ) : display) === \"inline\" ) {\n\t\tstyle.display = display;\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// Not quite $.extend, this won't overwrite existing keys.\n\t\t\t// Reusing 'index' because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = animationPrefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\t\t\t// Don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t}),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\t\t\t\t// Support: Android 2.3\n\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise({\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\t\t\t\t\t// If we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length ; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// Resolve when we played the last frame; otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t}),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length ; index++ ) {\n\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t})\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.split(\" \");\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length ; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n\t\t\ttweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tanimationPrefilters.unshift( callback );\n\t\t} else {\n\t\t\tanimationPrefilters.push( callback );\n\t\t}\n\t}\n});\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === \"number\" ? opt.duration :\n\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n\n\t// Normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend({\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// Show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHidden ).css( \"opacity\", 0 ).show()\n\n\t\t\t// Animate to the value specified\n\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || data_priv.get( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = data_priv.get( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Start the next in the queue if the last step wasn't forced.\n\t\t\t// Timers currently will call their complete callbacks, which\n\t\t\t// will dequeue but only if they were gotoEnd.\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t});\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar index,\n\t\t\t\tdata = data_priv.get( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// Enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// Empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// Look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t});\n\t}\n});\n\njQuery.each([ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n});\n\n// Generate shortcuts for custom animations\njQuery.each({\n\tslideDown: genFx(\"show\"),\n\tslideUp: genFx(\"hide\"),\n\tslideToggle: genFx(\"toggle\"),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n});\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ti = 0,\n\t\ttimers = jQuery.timers;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tif ( timer() ) {\n\t\tjQuery.fx.start();\n\t} else {\n\t\tjQuery.timers.pop();\n\t}\n};\n\njQuery.fx.interval = 13;\n\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tclearInterval( timerId );\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\tclearTimeout( timeout );\n\t\t};\n\t});\n};\n\n\n(function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: iOS<=5.1, Android<=4.2+\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE<=11+\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: Android<=2.3\n\t// Options inside disabled selects are incorrectly marked as disabled\n\tselect.disabled = true;\n\tsupport.optDisabled = !opt.disabled;\n\n\t// Support: IE<=11+\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n})();\n\n\nvar nodeHook, boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\n\njQuery.fn.extend({\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tattr: function( elem, name, value ) {\n\t\tvar hooks, ret,\n\t\t\tnType = elem.nodeType;\n\n\t\t// don't get/set attributes on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === strundefined ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// All attributes are lowercase\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\tname = name.toLowerCase();\n\t\t\thooks = jQuery.attrHooks[ name ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\n\t\t\t} else if ( hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n\t\t\t\treturn ret;\n\n\t\t\t} else {\n\t\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t} else if ( hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n\t\t\treturn ret;\n\n\t\t} else {\n\t\t\tret = jQuery.find.attr( elem, name );\n\n\t\t\t// Non-existent attributes return null, we normalize to undefined\n\t\t\treturn ret == null ?\n\t\t\t\tundefined :\n\t\t\t\tret;\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name, propName,\n\t\t\ti = 0,\n\t\t\tattrNames = value && value.match( rnotwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( (name = attrNames[i++]) ) {\n\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n\n\t\t\t\t// Boolean attributes get special treatment (#10870)\n\t\t\t\tif ( jQuery.expr.match.bool.test( name ) ) {\n\t\t\t\t\t// Set corresponding property to false\n\t\t\t\t\telem[ propName ] = false;\n\t\t\t\t}\n\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tjQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle;\n\t\tif ( !isXML ) {\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ name ];\n\t\t\tattrHandle[ name ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tname.toLowerCase() :\n\t\t\t\tnull;\n\t\t\tattrHandle[ name ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n});\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i;\n\njQuery.fn.extend({\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\treturn this.each(function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t},\n\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks, notxml,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n\n\t\tif ( notxml ) {\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\treturn hooks && \"set\" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?\n\t\t\t\tret :\n\t\t\t\t( elem[ name ] = value );\n\n\t\t} else {\n\t\t\treturn hooks && \"get\" in hooks && (ret = hooks.get( elem, name )) !== null ?\n\t\t\t\tret :\n\t\t\t\telem[ name ];\n\t\t}\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\t\t\t\treturn elem.hasAttribute( \"tabindex\" ) || rfocusable.test( elem.nodeName ) || elem.href ?\n\t\t\t\t\telem.tabIndex :\n\t\t\t\t\t-1;\n\t\t\t}\n\t\t}\n\t}\n});\n\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t}\n\t};\n}\n\njQuery.each([\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n});\n\n\n\n\nvar rclass = /[\\t\\r\\n\\f]/g;\n\njQuery.fn.extend({\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\tproceed = typeof value === \"string\" && value,\n\t\t\ti = 0,\n\t\t\tlen = this.length;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\n\t\tif ( proceed ) {\n\t\t\t// The disjunction here is for better compressibility (see removeClass)\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\" \"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = jQuery.trim( cur );\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, clazz, j, finalValue,\n\t\t\tproceed = arguments.length === 0 || typeof value === \"string\" && value,\n\t\t\ti = 0,\n\t\t\tlen = this.length;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n\t\t\t});\n\t\t}\n\t\tif ( proceed ) {\n\t\t\tclasses = ( value || \"\" ).match( rnotwhite ) || [];\n\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\telem = this[ i ];\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n\t\t\t\t\t( \" \" + elem.className + \" \" ).replace( rclass, \" \" ) :\n\t\t\t\t\t\"\"\n\t\t\t\t);\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) >= 0 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = value ? jQuery.trim( cur ) : \"\";\n\t\t\t\t\tif ( elem.className !== finalValue ) {\n\t\t\t\t\t\telem.className = finalValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value;\n\n\t\tif ( typeof stateVal === \"boolean\" && type === \"string\" ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tif ( type === \"string\" ) {\n\t\t\t\t// Toggle individual class names\n\t\t\t\tvar className,\n\t\t\t\t\ti = 0,\n\t\t\t\t\tself = jQuery( this ),\n\t\t\t\t\tclassNames = value.match( rnotwhite ) || [];\n\n\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( type === strundefined || type === \"boolean\" ) {\n\t\t\t\tif ( this.className ) {\n\t\t\t\t\t// store className if set\n\t\t\t\t\tdata_priv.set( this, \"__className__\", this.className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tthis.className = this.className || value === false ? \"\" : data_priv.get( this, \"__className__\" ) || \"\";\n\t\t\t}\n\t\t});\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className = \" \" + selector + \" \",\n\t\t\ti = 0,\n\t\t\tl = this.length;\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( this[i].nodeType === 1 && (\" \" + this[i].className + \" \").replace(rclass, \" \").indexOf( className ) >= 0 ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n});\n\n\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend({\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[0];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks && \"get\" in hooks && (ret = hooks.get( elem, \"value\" )) !== undefined ) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\treturn typeof ret === \"string\" ?\n\t\t\t\t\t// Handle most common string cases\n\t\t\t\t\tret.replace(rreturn, \"\") :\n\t\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\t\tret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each(function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t});\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !(\"set\" in hooks) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t});\n\t}\n});\n\njQuery.extend({\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\t\t\t\t\t// Support: IE10-11+\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\tjQuery.trim( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\" || index < 0,\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length,\n\t\t\t\t\ti = index < 0 ?\n\t\t\t\t\t\tmax :\n\t\t\t\t\t\tone ? index : 0;\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// IE6-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t( support.optDisabled ? !option.disabled : option.getAttribute( \"disabled\" ) === null ) &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\t\t\t\t\tif ( (option.selected = jQuery.inArray( option.value, values ) >= 0) ) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t}\n});\n\n// Radios and checkboxes getter/setter\njQuery.each([ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute(\"value\") === null ? \"on\" : elem.value;\n\t\t};\n\t}\n});\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\njQuery.each( (\"blur focus focusin focusout load resize scroll unload click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup error contextmenu\").split(\" \"), function( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n});\n\njQuery.fn.extend({\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t},\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ? this.off( selector, \"**\" ) : this.off( types, selector || \"**\", fn );\n\t}\n});\n\n\nvar nonce = jQuery.now();\n\nvar rquery = (/\\?/);\n\n\n\n// Support: Android 2.3\n// Workaround failure to string-cast null input\njQuery.parseJSON = function( data ) {\n\treturn JSON.parse( data + \"\" );\n};\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml, tmp;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\n\t// Support: IE9\n\ttry {\n\t\ttmp = new DOMParser();\n\t\txml = tmp.parseFromString( data, \"text/xml\" );\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\n\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\trhash = /#.*$/,\n\trts = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\trurl = /^([\\w.+-]+:)(?:\\/\\/(?:[^\\/?#]*@|)([^\\/?#:]*)(?::(\\d+)|)|)/,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat( \"*\" ),\n\n\t// Document location\n\tajaxLocation = window.location.href,\n\n\t// Segment location into parts\n\tajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[0] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t});\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader(\"Content-Type\");\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[0] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s[ \"throws\" ] ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn { state: \"parsererror\", error: conv ? e : \"No conversion from \" + prev + \" to \" + current };\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend({\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: ajaxLocation,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /xml/,\n\t\t\thtml: /html/,\n\t\t\tjson: /json/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": jQuery.parseJSON,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar transport,\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\t\t\t// Cross-domain detection vars\n\t\t\tparts,\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\t\t\t// Loop variable\n\t\t\ti,\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\tjQuery.event,\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks(\"once memory\"),\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\t\t\t// The jqXHR state\n\t\t\tstate = 0,\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( state === 2 ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tvar lname = name.toLowerCase();\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( !state ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n\t\tjqXHR.success = jqXHR.done;\n\t\tjqXHR.error = jqXHR.fail;\n\n\t\t// Remove hash character (#7531: and string promotion)\n\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || ajaxLocation ) + \"\" ).replace( rhash, \"\" )\n\t\t\t.replace( rprotocol, ajaxLocParts[ 1 ] + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = jQuery.trim( s.dataType || \"*\" ).toLowerCase().match( rnotwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n\t\tif ( s.crossDomain == null ) {\n\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n\t\t\ts.crossDomain = !!( parts &&\n\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) !==\n\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === \"http:\" ? \"80\" : \"443\" ) ) )\n\t\t\t);\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( state === 2 ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger(\"ajaxStart\");\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\tcacheURL = s.url;\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL = ( s.url += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data );\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add anti-cache in url if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\ts.url = rts.test( cacheURL ) ?\n\n\t\t\t\t\t// If there is already a '_' parameter, set its value\n\t\t\t\t\tcacheURL.replace( rts, \"$1_=\" + nonce++ ) :\n\n\t\t\t\t\t// Otherwise add one to the end\n\t\t\t\t\tcacheURL + ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + nonce++;\n\t\t\t}\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// Aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n\t\t\tjqXHR[ i ]( s[ i ] );\n\t\t}\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = setTimeout(function() {\n\t\t\t\t\tjqXHR.abort(\"timeout\");\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tstate = 1;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\t\t\t\t// Propagate exception as error if not done\n\t\t\t\tif ( state < 2 ) {\n\t\t\t\t\tdone( -1, e );\n\t\t\t\t// Simply rethrow otherwise\n\t\t\t\t} else {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Called once\n\t\t\tif ( state === 2 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// State is \"done\" now\n\t\t\tstate = 2;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\tclearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"Last-Modified\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader(\"etag\");\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Extract error from statusText and normalize for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n});\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\t\t// Shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\treturn jQuery.ajax({\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t});\n\t};\n});\n\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax({\n\t\turl: url,\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tasync: false,\n\t\tglobal: false,\n\t\t\"throws\": true\n\t});\n};\n\n\njQuery.fn.extend({\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapAll( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\tif ( this[ 0 ] ) {\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map(function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t}).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each(function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call(this, i) );\n\t\t\t});\n\t\t}\n\n\t\treturn this.each(function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t});\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each(function( i ) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n\t\t});\n\t},\n\n\tunwrap: function() {\n\t\treturn this.parent().each(function() {\n\t\t\tif ( !jQuery.nodeName( this, \"body\" ) ) {\n\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t\t}\n\t\t}).end();\n\t}\n});\n\n\njQuery.expr.filters.hidden = function( elem ) {\n\t// Support: Opera <= 12.12\n\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0;\n};\njQuery.expr.filters.visible = function( elem ) {\n\treturn !jQuery.expr.filters.hidden( elem );\n};\n\n\n\n\nvar r20 = /%20/g,\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams( prefix + \"[\" + ( typeof v === \"object\" ? i : \"\" ) + \"]\", v, traditional, add );\n\t\t\t}\n\t\t});\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, value ) {\n\t\t\t// If value is a function, invoke it and return its value\n\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? \"\" : value );\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" + encodeURIComponent( value );\n\t\t};\n\n\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n\tif ( traditional === undefined ) {\n\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n\t}\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t});\n\n\t} else {\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" ).replace( r20, \"+\" );\n};\n\njQuery.fn.extend({\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map(function() {\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t})\n\t\t.filter(function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t})\n\t\t.map(function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\treturn val == null ?\n\t\t\t\tnull :\n\t\t\t\tjQuery.isArray( val ) ?\n\t\t\t\t\tjQuery.map( val, function( val ) {\n\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t\t}) :\n\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t}).get();\n\t}\n});\n\n\njQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new XMLHttpRequest();\n\t} catch( e ) {}\n};\n\nvar xhrId = 0,\n\txhrCallbacks = {},\n\txhrSuccessStatus = {\n\t\t// file protocol always yields status code 0, assume 200\n\t\t0: 200,\n\t\t// Support: IE9\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\n// Support: IE9\n// Open requests must be manually aborted on unload (#5280)\n// See https://support.microsoft.com/kb/2856746 for more info\nif ( window.attachEvent ) {\n\twindow.attachEvent( \"onunload\", function() {\n\t\tfor ( var key in xhrCallbacks ) {\n\t\t\txhrCallbacks[ key ]();\n\t\t}\n\t});\n}\n\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nsupport.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport(function( options ) {\n\tvar callback;\n\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i,\n\t\t\t\t\txhr = options.xhr(),\n\t\t\t\t\tid = ++xhrId;\n\n\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[\"X-Requested-With\"] ) {\n\t\t\t\t\theaders[\"X-Requested-With\"] = \"XMLHttpRequest\";\n\t\t\t\t}\n\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n\t\t\t\t\t\t\tcallback = xhr.onload = xhr.onerror = null;\n\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\t// file: protocol always yields status 0; see #8605, #14207\n\t\t\t\t\t\t\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\t\t\t\t\t\t\t\t\t// Support: IE9\n\t\t\t\t\t\t\t\t\t// Accessing binary-data responseText throws an exception\n\t\t\t\t\t\t\t\t\t// (#11426)\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText === \"string\" ? {\n\t\t\t\t\t\t\t\t\t\ttext: xhr.responseText\n\t\t\t\t\t\t\t\t\t} : undefined,\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\txhr.onerror = callback(\"error\");\n\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = xhrCallbacks[ id ] = callback(\"abort\");\n\n\t\t\t\ttry {\n\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\n// Install script dataType\njQuery.ajaxSetup({\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /(?:java|ecma)script/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n});\n\n// Handle cache's special case and crossDomain\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t}\n});\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery(\"<script>\").prop({\n\t\t\t\t\tasync: true,\n\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\tsrc: s.url\n\t\t\t\t}).on(\n\t\t\t\t\t\"load error\",\n\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n});\n\n\n\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup({\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n});\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" && !( s.contentType || \"\" ).indexOf(\"application/x-www-form-urlencoded\") && rjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[\"script json\"] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always(function() {\n\t\t\t// Restore preexisting value\n\t\t\twindow[ callbackName ] = overwritten;\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\t\t\t\t// make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t});\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n});\n\n\n\n\n// data: string of html\n// context (optional): If specified, the fragment will be created in this context, defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\tcontext = context || document;\n\n\tvar parsed = rsingleTag.exec( data ),\n\t\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[1] ) ];\n\t}\n\n\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n// Keep a copy of the old load method\nvar _load = jQuery.fn.load;\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tif ( typeof url !== \"string\" && _load ) {\n\t\treturn _load.apply( this, arguments );\n\t}\n\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf(\" \");\n\n\tif ( off >= 0 ) {\n\t\tselector = jQuery.trim( url.slice( off ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax({\n\t\t\turl: url,\n\n\t\t\t// if \"type\" variable is undefined, then \"GET\" method will be used\n\t\t\ttype: type,\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t}).done(function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery(\"<div>\").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t}).complete( callback && function( jqXHR, status ) {\n\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t});\n\t}\n\n\treturn this;\n};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [ \"ajaxStart\", \"ajaxStop\", \"ajaxComplete\", \"ajaxError\", \"ajaxSuccess\", \"ajaxSend\" ], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n});\n\n\n\n\njQuery.expr.filters.animated = function( elem ) {\n\treturn jQuery.grep(jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t}).length;\n};\n\n\n\n\nvar docElem = window.document.documentElement;\n\n/**\n * Gets a window from an element\n */\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;\n}\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// Set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t( curCSSTop + curCSSLeft ).indexOf(\"auto\") > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\t\t\toptions = options.call( elem, i, curOffset );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend({\n\toffset: function( options ) {\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each(function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t});\n\t\t}\n\n\t\tvar docElem, win,\n\t\t\telem = this[ 0 ],\n\t\t\tbox = { top: 0, left: 0 },\n\t\t\tdoc = elem && elem.ownerDocument;\n\n\t\tif ( !doc ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdocElem = doc.documentElement;\n\n\t\t// Make sure it's not a disconnected DOM node\n\t\tif ( !jQuery.contains( docElem, elem ) ) {\n\t\t\treturn box;\n\t\t}\n\n\t\t// Support: BlackBerry 5, iOS 3 (original iPhone)\n\t\t// If we don't have gBCR, just use 0,0 rather than error\n\t\tif ( typeof elem.getBoundingClientRect !== strundefined ) {\n\t\t\tbox = elem.getBoundingClientRect();\n\t\t}\n\t\twin = getWindow( doc );\n\t\treturn {\n\t\t\ttop: box.top + win.pageYOffset - docElem.clientTop,\n\t\t\tleft: box.left + win.pageXOffset - docElem.clientLeft\n\t\t};\n\t},\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\t\t\t// Assume getBoundingClientRect is there when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset.top += jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true );\n\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true );\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\toffsetParent: function() {\n\t\treturn this.map(function() {\n\t\t\tvar offsetParent = this.offsetParent || docElem;\n\n\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, \"html\" ) && jQuery.css( offsetParent, \"position\" ) === \"static\" ) ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || docElem;\n\t\t});\n\t}\n});\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : window.pageXOffset,\n\t\t\t\t\ttop ? val : window.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length, null );\n\t};\n});\n\n// Support: Safari<7+, Chrome<37+\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n});\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name }, function( defaultExtra, funcName ) {\n\t\t// Margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n\t\t\t\t\t// isn't a whole lot we can do. See pull request at this URL for discussion:\n\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n\t\t\t\t\treturn elem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n\t\t};\n\t});\n});\n\n\n// The number of elements contained in the matched element set\njQuery.fn.size = function() {\n\treturn this.length;\n};\n\njQuery.fn.andSelf = jQuery.fn.addBack;\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t});\n}\n\n\n\n\nvar\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( typeof noGlobal === strundefined ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\nreturn jQuery;\n\n}));\n\n/*!\n * Lightbox v2.8.1\n * by Lokesh Dhakar\n *\n * More info:\n * http://lokeshdhakar.com/projects/lightbox2/\n *\n * Copyright 2007, 2015 Lokesh Dhakar\n * Released under the MIT license\n * https://github.com/lokesh/lightbox2/blob/master/LICENSE\n */\n\n// Uses Node, AMD or browser globals to create a module.\n(function (root, factory) {\n    if (typeof define === 'function' && define.amd) {\n        // AMD. Register as an anonymous module.\n        define(['jquery'], factory);\n    } else if (typeof exports === 'object') {\n        // Node. Does not work with strict CommonJS, but\n        // only CommonJS-like environments that support module.exports,\n        // like Node.\n        module.exports = factory(require('jquery'));\n    } else {\n        // Browser globals (root is window)\n        root.lightbox = factory(root.jQuery);\n    }\n}(this, function ($) {\n\n  function Lightbox(options) {\n    this.album = [];\n    this.currentImageIndex = void 0;\n    this.init();\n\n    // options\n    this.options = $.extend({}, this.constructor.defaults);\n    this.option(options);\n  }\n\n  // Descriptions of all options available on the mapper site:\n  // http://lokeshdhakar.com/projects/lightbox2/index.html#options\n  Lightbox.defaults = {\n    albumLabel: 'Image %1 of %2',\n    alwaysShowNavOnTouchDevices: false,\n    fadeDuration: 500,\n    fitImagesInViewport: true,\n    // maxWidth: 800,\n    // maxHeight: 600,\n    positionFromTop: 50,\n    resizeDuration: 700,\n    showImageNumberLabel: true,\n    wrapAround: false\n  };\n\n  Lightbox.prototype.option = function(options) {\n    $.extend(this.options, options);\n  };\n\n  Lightbox.prototype.imageCountLabel = function(currentImageNum, totalImages) {\n    return this.options.albumLabel.replace(/%1/g, currentImageNum).replace(/%2/g, totalImages);\n  };\n\n  Lightbox.prototype.init = function() {\n    this.enable();\n    this.build();\n  };\n\n  // Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes\n  // that contain 'lightbox'. When these are clicked, start lightbox.\n  Lightbox.prototype.enable = function() {\n    var self = this;\n    $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) {\n      self.start($(event.currentTarget));\n      return false;\n    });\n  };\n\n  // Build html for the lightbox and the overlay.\n  // Attach event handlers to the new DOM elements. click click click\n  Lightbox.prototype.build = function() {\n    var self = this;\n    $('<div id=\"lightboxOverlay\" class=\"lightboxOverlay\"></div><div id=\"lightbox\" class=\"lightbox\"><div class=\"lb-outerContainer\"><div class=\"lb-container\"><img class=\"lb-image\" src=\"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\" /><div class=\"lb-nav\"><a class=\"lb-prev\" href=\"\" ></a><a class=\"lb-next\" href=\"\" ></a></div><div class=\"lb-loader\"><a class=\"lb-cancel\"></a></div></div></div><div class=\"lb-dataContainer\"><div class=\"lb-data\"><div class=\"lb-details\"><span class=\"lb-caption\"></span><span class=\"lb-number\"></span></div><div class=\"lb-closeContainer\"><a class=\"lb-close\"></a></div></div></div></div>').appendTo($('body'));\n\n    // Cache jQuery objects\n    this.$lightbox       = $('#lightbox');\n    this.$overlay        = $('#lightboxOverlay');\n    this.$outerContainer = this.$lightbox.find('.lb-outerContainer');\n    this.$container      = this.$lightbox.find('.lb-container');\n\n    // Store css values for future lookup\n    this.containerTopPadding = parseInt(this.$container.css('padding-top'), 10);\n    this.containerRightPadding = parseInt(this.$container.css('padding-right'), 10);\n    this.containerBottomPadding = parseInt(this.$container.css('padding-bottom'), 10);\n    this.containerLeftPadding = parseInt(this.$container.css('padding-left'), 10);\n\n    // Attach event handlers to the newly minted DOM elements\n    this.$overlay.hide().on('click', function() {\n      self.end();\n      return false;\n    });\n\n    this.$lightbox.hide().on('click', function(event) {\n      if ($(event.target).attr('id') === 'lightbox') {\n        self.end();\n      }\n      return false;\n    });\n\n    this.$outerContainer.on('click', function(event) {\n      if ($(event.target).attr('id') === 'lightbox') {\n        self.end();\n      }\n      return false;\n    });\n\n    this.$lightbox.find('.lb-prev').on('click', function() {\n      if (self.currentImageIndex === 0) {\n        self.changeImage(self.album.length - 1);\n      } else {\n        self.changeImage(self.currentImageIndex - 1);\n      }\n      return false;\n    });\n\n    this.$lightbox.find('.lb-next').on('click', function() {\n      if (self.currentImageIndex === self.album.length - 1) {\n        self.changeImage(0);\n      } else {\n        self.changeImage(self.currentImageIndex + 1);\n      }\n      return false;\n    });\n\n    this.$lightbox.find('.lb-loader, .lb-close').on('click', function() {\n      self.end();\n      return false;\n    });\n  };\n\n  // Show overlay and lightbox. If the image is part of a set, add siblings to album array.\n  Lightbox.prototype.start = function($link) {\n    var self    = this;\n    var $window = $(window);\n\n    $window.on('resize', $.proxy(this.sizeOverlay, this));\n\n    $('select, object, embed').css({\n      visibility: 'hidden'\n    });\n\n    this.sizeOverlay();\n\n    this.album = [];\n    var imageNumber = 0;\n\n    function addToAlbum($link) {\n      self.album.push({\n        link: $link.attr('href'),\n        title: $link.attr('data-title') || $link.attr('title')\n      });\n    }\n\n    // Support both data-lightbox attribute and rel attribute implementations\n    var dataLightboxValue = $link.attr('data-lightbox');\n    var $links;\n\n    if (dataLightboxValue) {\n      $links = $($link.prop('tagName') + '[data-lightbox=\"' + dataLightboxValue + '\"]');\n      for (var i = 0; i < $links.length; i = ++i) {\n        addToAlbum($($links[i]));\n        if ($links[i] === $link[0]) {\n          imageNumber = i;\n        }\n      }\n    } else {\n      if ($link.attr('rel') === 'lightbox') {\n        // If image is not part of a set\n        addToAlbum($link);\n      } else {\n        // If image is part of a set\n        $links = $($link.prop('tagName') + '[rel=\"' + $link.attr('rel') + '\"]');\n        for (var j = 0; j < $links.length; j = ++j) {\n          addToAlbum($($links[j]));\n          if ($links[j] === $link[0]) {\n            imageNumber = j;\n          }\n        }\n      }\n    }\n\n    // Position Lightbox\n    var top  = $window.scrollTop() + this.options.positionFromTop;\n    var left = $window.scrollLeft();\n    this.$lightbox.css({\n      top: top + 'px',\n      left: left + 'px'\n    }).fadeIn(this.options.fadeDuration);\n\n    this.changeImage(imageNumber);\n  };\n\n  // Hide most UI elements in preparation for the animated resizing of the lightbox.\n  Lightbox.prototype.changeImage = function(imageNumber) {\n    var self = this;\n\n    this.disableKeyboardNav();\n    var $image = this.$lightbox.find('.lb-image');\n\n    this.$overlay.fadeIn(this.options.fadeDuration);\n\n    $('.lb-loader').fadeIn('slow');\n    this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();\n\n    this.$outerContainer.addClass('animating');\n\n    // When image to show is preloaded, we send the width and height to sizeContainer()\n    var preloader = new Image();\n    preloader.onload = function() {\n      var $preloader;\n      var imageHeight;\n      var imageWidth;\n      var maxImageHeight;\n      var maxImageWidth;\n      var windowHeight;\n      var windowWidth;\n\n      $image.attr('src', self.album[imageNumber].link);\n\n      $preloader = $(preloader);\n\n      $image.width(preloader.width);\n      $image.height(preloader.height);\n\n      if (self.options.fitImagesInViewport) {\n        // Fit image inside the viewport.\n        // Take into account the border around the image and an additional 10px gutter on each side.\n\n        windowWidth    = $(window).width();\n        windowHeight   = $(window).height();\n        maxImageWidth  = windowWidth - self.containerLeftPadding - self.containerRightPadding - 20;\n        maxImageHeight = windowHeight - self.containerTopPadding - self.containerBottomPadding - 120;\n\n        // Check if image size is larger then maxWidth|maxHeight in settings\n        if (self.options.maxWidth && self.options.maxWidth < maxImageWidth) {\n          maxImageWidth = self.options.maxWidth;\n        }\n        if (self.options.maxHeight && self.options.maxHeight < maxImageWidth) {\n          maxImageHeight = self.options.maxHeight;\n        }\n\n        // Is there a fitting issue?\n        if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) {\n          if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) {\n            imageWidth  = maxImageWidth;\n            imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10);\n            $image.width(imageWidth);\n            $image.height(imageHeight);\n          } else {\n            imageHeight = maxImageHeight;\n            imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10);\n            $image.width(imageWidth);\n            $image.height(imageHeight);\n          }\n        }\n      }\n      self.sizeContainer($image.width(), $image.height());\n    };\n\n    preloader.src          = this.album[imageNumber].link;\n    this.currentImageIndex = imageNumber;\n  };\n\n  // Stretch overlay to fit the viewport\n  Lightbox.prototype.sizeOverlay = function() {\n    this.$overlay\n      .width($(window).width())\n      .height($(document).height());\n  };\n\n  // Animate the size of the lightbox to fit the image we are showing\n  Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) {\n    var self = this;\n\n    var oldWidth  = this.$outerContainer.outerWidth();\n    var oldHeight = this.$outerContainer.outerHeight();\n    var newWidth  = imageWidth + this.containerLeftPadding + this.containerRightPadding;\n    var newHeight = imageHeight + this.containerTopPadding + this.containerBottomPadding;\n\n    function postResize() {\n      self.$lightbox.find('.lb-dataContainer').width(newWidth);\n      self.$lightbox.find('.lb-prevLink').height(newHeight);\n      self.$lightbox.find('.lb-nextLink').height(newHeight);\n      self.showImage();\n    }\n\n    if (oldWidth !== newWidth || oldHeight !== newHeight) {\n      this.$outerContainer.animate({\n        width: newWidth,\n        height: newHeight\n      }, this.options.resizeDuration, 'swing', function() {\n        postResize();\n      });\n    } else {\n      postResize();\n    }\n  };\n\n  // Display the image and its details and begin preload neighboring images.\n  Lightbox.prototype.showImage = function() {\n    this.$lightbox.find('.lb-loader').stop(true).hide();\n    this.$lightbox.find('.lb-image').fadeIn('slow');\n\n    this.updateNav();\n    this.updateDetails();\n    this.preloadNeighboringImages();\n    this.enableKeyboardNav();\n  };\n\n  // Display previous and next navigation if appropriate.\n  Lightbox.prototype.updateNav = function() {\n    // Check to see if the browser supports touch events. If so, we take the conservative approach\n    // and assume that mouse hover events are not supported and always show prev/next navigation\n    // arrows in image sets.\n    var alwaysShowNav = false;\n    try {\n      document.createEvent('TouchEvent');\n      alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false;\n    } catch (e) {}\n\n    this.$lightbox.find('.lb-nav').show();\n\n    if (this.album.length > 1) {\n      if (this.options.wrapAround) {\n        if (alwaysShowNav) {\n          this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1');\n        }\n        this.$lightbox.find('.lb-prev, .lb-next').show();\n      } else {\n        if (this.currentImageIndex > 0) {\n          this.$lightbox.find('.lb-prev').show();\n          if (alwaysShowNav) {\n            this.$lightbox.find('.lb-prev').css('opacity', '1');\n          }\n        }\n        if (this.currentImageIndex < this.album.length - 1) {\n          this.$lightbox.find('.lb-next').show();\n          if (alwaysShowNav) {\n            this.$lightbox.find('.lb-next').css('opacity', '1');\n          }\n        }\n      }\n    }\n  };\n\n  // Display caption, image number, and closing button.\n  Lightbox.prototype.updateDetails = function() {\n    var self = this;\n\n    // Enable anchor clicks in the injected caption html.\n    // Thanks Nate Wright for the fix. @https://github.com/NateWr\n    if (typeof this.album[this.currentImageIndex].title !== 'undefined' &&\n      this.album[this.currentImageIndex].title !== '') {\n      this.$lightbox.find('.lb-caption')\n        .html(this.album[this.currentImageIndex].title)\n        .fadeIn('fast')\n        .find('a').on('click', function(event) {\n          if ($(this).attr('target') !== undefined) {\n            window.open($(this).attr('href'), $(this).attr('target'));\n          } else {\n            location.href = $(this).attr('href');\n          }\n        });\n    }\n\n    if (this.album.length > 1 && this.options.showImageNumberLabel) {\n      var labelText = this.imageCountLabel(this.currentImageIndex + 1, this.album.length);\n      this.$lightbox.find('.lb-number').text(labelText).fadeIn('fast');\n    } else {\n      this.$lightbox.find('.lb-number').hide();\n    }\n\n    this.$outerContainer.removeClass('animating');\n\n    this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() {\n      return self.sizeOverlay();\n    });\n  };\n\n  // Preload previous and next images in set.\n  Lightbox.prototype.preloadNeighboringImages = function() {\n    if (this.album.length > this.currentImageIndex + 1) {\n      var preloadNext = new Image();\n      preloadNext.src = this.album[this.currentImageIndex + 1].link;\n    }\n    if (this.currentImageIndex > 0) {\n      var preloadPrev = new Image();\n      preloadPrev.src = this.album[this.currentImageIndex - 1].link;\n    }\n  };\n\n  Lightbox.prototype.enableKeyboardNav = function() {\n    $(document).on('keyup.keyboard', $.proxy(this.keyboardAction, this));\n  };\n\n  Lightbox.prototype.disableKeyboardNav = function() {\n    $(document).off('.keyboard');\n  };\n\n  Lightbox.prototype.keyboardAction = function(event) {\n    var KEYCODE_ESC        = 27;\n    var KEYCODE_LEFTARROW  = 37;\n    var KEYCODE_RIGHTARROW = 39;\n\n    var keycode = event.keyCode;\n    var key     = String.fromCharCode(keycode).toLowerCase();\n    if (keycode === KEYCODE_ESC || key.match(/x|o|c/)) {\n      this.end();\n    } else if (key === 'p' || keycode === KEYCODE_LEFTARROW) {\n      if (this.currentImageIndex !== 0) {\n        this.changeImage(this.currentImageIndex - 1);\n      } else if (this.options.wrapAround && this.album.length > 1) {\n        this.changeImage(this.album.length - 1);\n      }\n    } else if (key === 'n' || keycode === KEYCODE_RIGHTARROW) {\n      if (this.currentImageIndex !== this.album.length - 1) {\n        this.changeImage(this.currentImageIndex + 1);\n      } else if (this.options.wrapAround && this.album.length > 1) {\n        this.changeImage(0);\n      }\n    }\n  };\n\n  // Closing time. :-(\n  Lightbox.prototype.end = function() {\n    this.disableKeyboardNav();\n    $(window).off('resize', this.sizeOverlay);\n    this.$lightbox.fadeOut(this.options.fadeDuration);\n    this.$overlay.fadeOut(this.options.fadeDuration);\n    $('select, object, embed').css({\n      visibility: 'visible'\n    });\n  };\n\n  return new Lightbox();\n}));\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/lightbox2/2.8.1/js/lightbox.js",
    "content": "/*!\n * Lightbox v2.8.1\n * by Lokesh Dhakar\n *\n * More info:\n * http://lokeshdhakar.com/projects/lightbox2/\n *\n * Copyright 2007, 2015 Lokesh Dhakar\n * Released under the MIT license\n * https://github.com/lokesh/lightbox2/blob/master/LICENSE\n */\n\n// Uses Node, AMD or browser globals to create a module.\n(function (root, factory) {\n    if (typeof define === 'function' && define.amd) {\n        // AMD. Register as an anonymous module.\n        define(['jquery'], factory);\n    } else if (typeof exports === 'object') {\n        // Node. Does not work with strict CommonJS, but\n        // only CommonJS-like environments that support module.exports,\n        // like Node.\n        module.exports = factory(require('jquery'));\n    } else {\n        // Browser globals (root is window)\n        root.lightbox = factory(root.jQuery);\n    }\n}(this, function ($) {\n\n  function Lightbox(options) {\n    this.album = [];\n    this.currentImageIndex = void 0;\n    this.init();\n\n    // options\n    this.options = $.extend({}, this.constructor.defaults);\n    this.option(options);\n  }\n\n  // Descriptions of all options available on the mapper site:\n  // http://lokeshdhakar.com/projects/lightbox2/index.html#options\n  Lightbox.defaults = {\n    albumLabel: 'Image %1 of %2',\n    alwaysShowNavOnTouchDevices: false,\n    fadeDuration: 500,\n    fitImagesInViewport: true,\n    // maxWidth: 800,\n    // maxHeight: 600,\n    positionFromTop: 50,\n    resizeDuration: 700,\n    showImageNumberLabel: true,\n    wrapAround: false\n  };\n\n  Lightbox.prototype.option = function(options) {\n    $.extend(this.options, options);\n  };\n\n  Lightbox.prototype.imageCountLabel = function(currentImageNum, totalImages) {\n    return this.options.albumLabel.replace(/%1/g, currentImageNum).replace(/%2/g, totalImages);\n  };\n\n  Lightbox.prototype.init = function() {\n    this.enable();\n    this.build();\n  };\n\n  // Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes\n  // that contain 'lightbox'. When these are clicked, start lightbox.\n  Lightbox.prototype.enable = function() {\n    var self = this;\n    $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) {\n      self.start($(event.currentTarget));\n      return false;\n    });\n  };\n\n  // Build html for the lightbox and the overlay.\n  // Attach event handlers to the new DOM elements. click click click\n  Lightbox.prototype.build = function() {\n    var self = this;\n    $('<div id=\"lightboxOverlay\" class=\"lightboxOverlay\"></div><div id=\"lightbox\" class=\"lightbox\"><div class=\"lb-outerContainer\"><div class=\"lb-container\"><img class=\"lb-image\" src=\"data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==\" /><div class=\"lb-nav\"><a class=\"lb-prev\" href=\"\" ></a><a class=\"lb-next\" href=\"\" ></a></div><div class=\"lb-loader\"><a class=\"lb-cancel\"></a></div></div></div><div class=\"lb-dataContainer\"><div class=\"lb-data\"><div class=\"lb-details\"><span class=\"lb-caption\"></span><span class=\"lb-number\"></span></div><div class=\"lb-closeContainer\"><a class=\"lb-close\"></a></div></div></div></div>').appendTo($('body'));\n\n    // Cache jQuery objects\n    this.$lightbox       = $('#lightbox');\n    this.$overlay        = $('#lightboxOverlay');\n    this.$outerContainer = this.$lightbox.find('.lb-outerContainer');\n    this.$container      = this.$lightbox.find('.lb-container');\n\n    // Store css values for future lookup\n    this.containerTopPadding = parseInt(this.$container.css('padding-top'), 10);\n    this.containerRightPadding = parseInt(this.$container.css('padding-right'), 10);\n    this.containerBottomPadding = parseInt(this.$container.css('padding-bottom'), 10);\n    this.containerLeftPadding = parseInt(this.$container.css('padding-left'), 10);\n\n    // Attach event handlers to the newly minted DOM elements\n    this.$overlay.hide().on('click', function() {\n      self.end();\n      return false;\n    });\n\n    this.$lightbox.hide().on('click', function(event) {\n      if ($(event.target).attr('id') === 'lightbox') {\n        self.end();\n      }\n      return false;\n    });\n\n    this.$outerContainer.on('click', function(event) {\n      if ($(event.target).attr('id') === 'lightbox') {\n        self.end();\n      }\n      return false;\n    });\n\n    this.$lightbox.find('.lb-prev').on('click', function() {\n      if (self.currentImageIndex === 0) {\n        self.changeImage(self.album.length - 1);\n      } else {\n        self.changeImage(self.currentImageIndex - 1);\n      }\n      return false;\n    });\n\n    this.$lightbox.find('.lb-next').on('click', function() {\n      if (self.currentImageIndex === self.album.length - 1) {\n        self.changeImage(0);\n      } else {\n        self.changeImage(self.currentImageIndex + 1);\n      }\n      return false;\n    });\n\n    this.$lightbox.find('.lb-loader, .lb-close').on('click', function() {\n      self.end();\n      return false;\n    });\n  };\n\n  // Show overlay and lightbox. If the image is part of a set, add siblings to album array.\n  Lightbox.prototype.start = function($link) {\n    var self    = this;\n    var $window = $(window);\n\n    $window.on('resize', $.proxy(this.sizeOverlay, this));\n\n    $('select, object, embed').css({\n      visibility: 'hidden'\n    });\n\n    this.sizeOverlay();\n\n    this.album = [];\n    var imageNumber = 0;\n\n    function addToAlbum($link) {\n      self.album.push({\n        link: $link.attr('href'),\n        title: $link.attr('data-title') || $link.attr('title')\n      });\n    }\n\n    // Support both data-lightbox attribute and rel attribute implementations\n    var dataLightboxValue = $link.attr('data-lightbox');\n    var $links;\n\n    if (dataLightboxValue) {\n      $links = $($link.prop('tagName') + '[data-lightbox=\"' + dataLightboxValue + '\"]');\n      for (var i = 0; i < $links.length; i = ++i) {\n        addToAlbum($($links[i]));\n        if ($links[i] === $link[0]) {\n          imageNumber = i;\n        }\n      }\n    } else {\n      if ($link.attr('rel') === 'lightbox') {\n        // If image is not part of a set\n        addToAlbum($link);\n      } else {\n        // If image is part of a set\n        $links = $($link.prop('tagName') + '[rel=\"' + $link.attr('rel') + '\"]');\n        for (var j = 0; j < $links.length; j = ++j) {\n          addToAlbum($($links[j]));\n          if ($links[j] === $link[0]) {\n            imageNumber = j;\n          }\n        }\n      }\n    }\n\n    // Position Lightbox\n    var top  = $window.scrollTop() + this.options.positionFromTop;\n    var left = $window.scrollLeft();\n    this.$lightbox.css({\n      top: top + 'px',\n      left: left + 'px'\n    }).fadeIn(this.options.fadeDuration);\n\n    this.changeImage(imageNumber);\n  };\n\n  // Hide most UI elements in preparation for the animated resizing of the lightbox.\n  Lightbox.prototype.changeImage = function(imageNumber) {\n    var self = this;\n\n    this.disableKeyboardNav();\n    var $image = this.$lightbox.find('.lb-image');\n\n    this.$overlay.fadeIn(this.options.fadeDuration);\n\n    $('.lb-loader').fadeIn('slow');\n    this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();\n\n    this.$outerContainer.addClass('animating');\n\n    // When image to show is preloaded, we send the width and height to sizeContainer()\n    var preloader = new Image();\n    preloader.onload = function() {\n      var $preloader;\n      var imageHeight;\n      var imageWidth;\n      var maxImageHeight;\n      var maxImageWidth;\n      var windowHeight;\n      var windowWidth;\n\n      $image.attr('src', self.album[imageNumber].link);\n\n      $preloader = $(preloader);\n\n      $image.width(preloader.width);\n      $image.height(preloader.height);\n\n      if (self.options.fitImagesInViewport) {\n        // Fit image inside the viewport.\n        // Take into account the border around the image and an additional 10px gutter on each side.\n\n        windowWidth    = $(window).width();\n        windowHeight   = $(window).height();\n        maxImageWidth  = windowWidth - self.containerLeftPadding - self.containerRightPadding - 20;\n        maxImageHeight = windowHeight - self.containerTopPadding - self.containerBottomPadding - 120;\n\n        // Check if image size is larger then maxWidth|maxHeight in settings\n        if (self.options.maxWidth && self.options.maxWidth < maxImageWidth) {\n          maxImageWidth = self.options.maxWidth;\n        }\n        if (self.options.maxHeight && self.options.maxHeight < maxImageWidth) {\n          maxImageHeight = self.options.maxHeight;\n        }\n\n        // Is there a fitting issue?\n        if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) {\n          if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) {\n            imageWidth  = maxImageWidth;\n            imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10);\n            $image.width(imageWidth);\n            $image.height(imageHeight);\n          } else {\n            imageHeight = maxImageHeight;\n            imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10);\n            $image.width(imageWidth);\n            $image.height(imageHeight);\n          }\n        }\n      }\n      self.sizeContainer($image.width(), $image.height());\n    };\n\n    preloader.src          = this.album[imageNumber].link;\n    this.currentImageIndex = imageNumber;\n  };\n\n  // Stretch overlay to fit the viewport\n  Lightbox.prototype.sizeOverlay = function() {\n    this.$overlay\n      .width($(window).width())\n      .height($(document).height());\n  };\n\n  // Animate the size of the lightbox to fit the image we are showing\n  Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) {\n    var self = this;\n\n    var oldWidth  = this.$outerContainer.outerWidth();\n    var oldHeight = this.$outerContainer.outerHeight();\n    var newWidth  = imageWidth + this.containerLeftPadding + this.containerRightPadding;\n    var newHeight = imageHeight + this.containerTopPadding + this.containerBottomPadding;\n\n    function postResize() {\n      self.$lightbox.find('.lb-dataContainer').width(newWidth);\n      self.$lightbox.find('.lb-prevLink').height(newHeight);\n      self.$lightbox.find('.lb-nextLink').height(newHeight);\n      self.showImage();\n    }\n\n    if (oldWidth !== newWidth || oldHeight !== newHeight) {\n      this.$outerContainer.animate({\n        width: newWidth,\n        height: newHeight\n      }, this.options.resizeDuration, 'swing', function() {\n        postResize();\n      });\n    } else {\n      postResize();\n    }\n  };\n\n  // Display the image and its details and begin preload neighboring images.\n  Lightbox.prototype.showImage = function() {\n    this.$lightbox.find('.lb-loader').stop(true).hide();\n    this.$lightbox.find('.lb-image').fadeIn('slow');\n\n    this.updateNav();\n    this.updateDetails();\n    this.preloadNeighboringImages();\n    this.enableKeyboardNav();\n  };\n\n  // Display previous and next navigation if appropriate.\n  Lightbox.prototype.updateNav = function() {\n    // Check to see if the browser supports touch events. If so, we take the conservative approach\n    // and assume that mouse hover events are not supported and always show prev/next navigation\n    // arrows in image sets.\n    var alwaysShowNav = false;\n    try {\n      document.createEvent('TouchEvent');\n      alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false;\n    } catch (e) {}\n\n    this.$lightbox.find('.lb-nav').show();\n\n    if (this.album.length > 1) {\n      if (this.options.wrapAround) {\n        if (alwaysShowNav) {\n          this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1');\n        }\n        this.$lightbox.find('.lb-prev, .lb-next').show();\n      } else {\n        if (this.currentImageIndex > 0) {\n          this.$lightbox.find('.lb-prev').show();\n          if (alwaysShowNav) {\n            this.$lightbox.find('.lb-prev').css('opacity', '1');\n          }\n        }\n        if (this.currentImageIndex < this.album.length - 1) {\n          this.$lightbox.find('.lb-next').show();\n          if (alwaysShowNav) {\n            this.$lightbox.find('.lb-next').css('opacity', '1');\n          }\n        }\n      }\n    }\n  };\n\n  // Display caption, image number, and closing button.\n  Lightbox.prototype.updateDetails = function() {\n    var self = this;\n\n    // Enable anchor clicks in the injected caption html.\n    // Thanks Nate Wright for the fix. @https://github.com/NateWr\n    if (typeof this.album[this.currentImageIndex].title !== 'undefined' &&\n      this.album[this.currentImageIndex].title !== '') {\n      this.$lightbox.find('.lb-caption')\n        .html(this.album[this.currentImageIndex].title)\n        .fadeIn('fast')\n        .find('a').on('click', function(event) {\n          if ($(this).attr('target') !== undefined) {\n            window.open($(this).attr('href'), $(this).attr('target'));\n          } else {\n            location.href = $(this).attr('href');\n          }\n        });\n    }\n\n    if (this.album.length > 1 && this.options.showImageNumberLabel) {\n      var labelText = this.imageCountLabel(this.currentImageIndex + 1, this.album.length);\n      this.$lightbox.find('.lb-number').text(labelText).fadeIn('fast');\n    } else {\n      this.$lightbox.find('.lb-number').hide();\n    }\n\n    this.$outerContainer.removeClass('animating');\n\n    this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() {\n      return self.sizeOverlay();\n    });\n  };\n\n  // Preload previous and next images in set.\n  Lightbox.prototype.preloadNeighboringImages = function() {\n    if (this.album.length > this.currentImageIndex + 1) {\n      var preloadNext = new Image();\n      preloadNext.src = this.album[this.currentImageIndex + 1].link;\n    }\n    if (this.currentImageIndex > 0) {\n      var preloadPrev = new Image();\n      preloadPrev.src = this.album[this.currentImageIndex - 1].link;\n    }\n  };\n\n  Lightbox.prototype.enableKeyboardNav = function() {\n    $(document).on('keyup.keyboard', $.proxy(this.keyboardAction, this));\n  };\n\n  Lightbox.prototype.disableKeyboardNav = function() {\n    $(document).off('.keyboard');\n  };\n\n  Lightbox.prototype.keyboardAction = function(event) {\n    var KEYCODE_ESC        = 27;\n    var KEYCODE_LEFTARROW  = 37;\n    var KEYCODE_RIGHTARROW = 39;\n\n    var keycode = event.keyCode;\n    var key     = String.fromCharCode(keycode).toLowerCase();\n    if (keycode === KEYCODE_ESC || key.match(/x|o|c/)) {\n      this.end();\n    } else if (key === 'p' || keycode === KEYCODE_LEFTARROW) {\n      if (this.currentImageIndex !== 0) {\n        this.changeImage(this.currentImageIndex - 1);\n      } else if (this.options.wrapAround && this.album.length > 1) {\n        this.changeImage(this.album.length - 1);\n      }\n    } else if (key === 'n' || keycode === KEYCODE_RIGHTARROW) {\n      if (this.currentImageIndex !== this.album.length - 1) {\n        this.changeImage(this.currentImageIndex + 1);\n      } else if (this.options.wrapAround && this.album.length > 1) {\n        this.changeImage(0);\n      }\n    }\n  };\n\n  // Closing time. :-(\n  Lightbox.prototype.end = function() {\n    this.disableKeyboardNav();\n    $(window).off('resize', this.sizeOverlay);\n    this.$lightbox.fadeOut(this.options.fadeDuration);\n    this.$overlay.fadeOut(this.options.fadeDuration);\n    $('select, object, embed').css({\n      visibility: 'visible'\n    });\n  };\n\n  return new Lightbox();\n}));\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/login/font-awesome.css",
    "content": "/*!\n *  Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome\n *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)\n */\n/* FONT PATH\n * -------------------------- */\n@font-face {\n  font-family: 'FontAwesome';\n  src: url('../fonts/fontawesome-webfont.eot?v=4.0.3');\n  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'), \n       url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'), \n       url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'), \n       url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');\n  font-weight: normal;\n  font-style: normal;\n}\n.box1 {\n\tdisplay: inline-block;\n\twidth: 15%;\n\tpadding:5px .5em;\n\tbackground:rgba(238, 238, 238, 0.26);\n\tmargin: .5em 1% .5em 0;\n\ttext-align: left;\n\t-moz-box-sizing: border-box;\n\t-webkit-box-sizing: border-box;\n\tbox-sizing: border-box;\n\tfont-size:13px;\n}\n.fontawesome-icon-list a i {\n    margin-right:10px;\n    font-size:25px;\n    color:#757575;\n}\n.margin-top{\n\tmargin-top:20px;\n}\n.fa {\n  display: inline-block;\n  font-family: FontAwesome;\n  font-style: normal;\n  font-weight: normal;\n  line-height: 1;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n/* makes the font 33% larger relative to the icon container */\n.fa-lg {\n  font-size: 1.3333333333333333em;\n  line-height: 0.75em;\n  vertical-align: -15%;\n}\n.fa-2x {\n  font-size: 2em;\n}\n.fa-3x {\n  font-size: 3em;\n}\n.fa-4x {\n  font-size: 4em;\n}\n.fa-5x {\n  font-size: 5em;\n}\n.fa-fw {\n  width: 1.2857142857142858em;\n  text-align: center;\n}\n.fa-ul {\n  padding-left: 0;\n  margin-left: 2.142857142857143em;\n  list-style-type: none;\n}\n.fa-ul > li {\n  position: relative;\n}\n.fa-li {\n  position: absolute;\n  left: -2.142857142857143em;\n  width: 2.142857142857143em;\n  top: 0.14285714285714285em;\n  text-align: center;\n}\n.fa-li.fa-lg {\n  left: -1.8571428571428572em;\n}\n.fa-border {\n  padding: .2em .25em .15em;\n  border: solid 0.08em #eeeeee;\n  border-radius: .1em;\n}\n.pull-right {\n  float: right;\n}\n.pull-left {\n  float: left;\n}\n.fa.pull-left {\n  margin-right: .3em;\n}\n.fa.pull-right {\n  margin-left: .3em;\n}\n.fa-spin {\n  -webkit-animation: spin 2s infinite linear;\n  -moz-animation: spin 2s infinite linear;\n  -o-animation: spin 2s infinite linear;\n  animation: spin 2s infinite linear;\n}\n@-moz-keyframes spin {\n  0% {\n    -moz-transform: rotate(0deg);\n  }\n  100% {\n    -moz-transform: rotate(359deg);\n  }\n}\n@-webkit-keyframes spin {\n  0% {\n    -webkit-transform: rotate(0deg);\n  }\n  100% {\n    -webkit-transform: rotate(359deg);\n  }\n}\n@-o-keyframes spin {\n  0% {\n    -o-transform: rotate(0deg);\n  }\n  100% {\n    -o-transform: rotate(359deg);\n  }\n}\n@-ms-keyframes spin {\n  0% {\n    -ms-transform: rotate(0deg);\n  }\n  100% {\n    -ms-transform: rotate(359deg);\n  }\n}\n@keyframes spin {\n  0% {\n    transform: rotate(0deg);\n  }\n  100% {\n    transform: rotate(359deg);\n  }\n}\n.fa-rotate-90 {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1);\n  -webkit-transform: rotate(90deg);\n  -moz-transform: rotate(90deg);\n  -ms-transform: rotate(90deg);\n  -o-transform: rotate(90deg);\n  transform: rotate(90deg);\n}\n.fa-rotate-180 {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2);\n  -webkit-transform: rotate(180deg);\n  -moz-transform: rotate(180deg);\n  -ms-transform: rotate(180deg);\n  -o-transform: rotate(180deg);\n  transform: rotate(180deg);\n}\n.fa-rotate-270 {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);\n  -webkit-transform: rotate(270deg);\n  -moz-transform: rotate(270deg);\n  -ms-transform: rotate(270deg);\n  -o-transform: rotate(270deg);\n  transform: rotate(270deg);\n}\n.fa-flip-horizontal {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);\n  -webkit-transform: scale(-1, 1);\n  -moz-transform: scale(-1, 1);\n  -ms-transform: scale(-1, 1);\n  -o-transform: scale(-1, 1);\n  transform: scale(-1, 1);\n}\n.fa-flip-vertical {\n  filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);\n  -webkit-transform: scale(1, -1);\n  -moz-transform: scale(1, -1);\n  -ms-transform: scale(1, -1);\n  -o-transform: scale(1, -1);\n  transform: scale(1, -1);\n}\n.fa-stack {\n  position: relative;\n  display: inline-block;\n  width: 2em;\n  height: 2em;\n  line-height: 2em;\n  vertical-align: middle;\n}\n.fa-stack-1x,\n.fa-stack-2x {\n  position: absolute;\n  left: 0;\n  width: 100%;\n  text-align: center;\n}\n.fa-stack-1x {\n  line-height: inherit;\n}\n.fa-stack-2x {\n  font-size: 2em;\n}\n.fa-inverse {\n  color: #ffffff;\n}\n/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen\n   readers do not read off random characters that represent icons */\n.fa-glass:before {\n  content: \"\\f000\";\n}\n.fa-music:before {\n  content: \"\\f001\";\n}\n.fa-search:before {\n  content: \"\\f002\";\n}\n.fa-envelope-o:before {\n  content: \"\\f003\";\n}\n.fa-heart:before {\n  content: \"\\f004\";\n}\n.fa-star:before {\n  content: \"\\f005\";\n}\n.fa-star-o:before {\n  content: \"\\f006\";\n}\n.fa-user:before {\n  content: \"\\f007\";\n}\n.fa-film:before {\n  content: \"\\f008\";\n}\n.fa-th-large:before {\n  content: \"\\f009\";\n}\n.fa-th:before {\n  content: \"\\f00a\";\n}\n.fa-th-list:before {\n  content: \"\\f00b\";\n}\n.fa-check:before {\n  content: \"\\f00c\";\n}\n.fa-times:before {\n  content: \"\\f00d\";\n}\n.fa-search-plus:before {\n  content: \"\\f00e\";\n}\n.fa-search-minus:before {\n  content: \"\\f010\";\n}\n.fa-power-off:before {\n  content: \"\\f011\" !important;\n}\n.pull-left1:before{\n\tcontent:\"\\f0e7\";\n}\n.fa-signal:before {\n  content: \"\\f012\";\n}\n.fa-gear:before,\n.fa-cog:before {\n  content: \"\\f013\";\n}\n.fa-trash-o:before {\n  content: \"\\f014\";\n}\n.fa-home:before {\n  content: \"\\f015\";\n}\n.fa-file-o:before {\n  content: \"\\f016\";\n}\n.fa-clock-o:before {\n  content: \"\\f017\";\n}\n.fa-road:before {\n  content: \"\\f018\";\n}\n.fa-download:before {\n  content: \"\\f019\";\n}\n.fa-arrow-circle-o-down:before {\n  content: \"\\f01a\";\n}\n.fa-arrow-circle-o-up:before {\n  content: \"\\f01b\";\n}\n.fa-inbox:before {\n  content: \"\\f01c\";\n}\n.fa-play-circle-o:before {\n  content: \"\\f01d\";\n}\n.fa-rotate-right:before,\n.fa-repeat:before {\n  content: \"\\f01e\";\n}\n.fa-refresh:before {\n  content: \"\\f021\";\n}\n.fa-list-alt:before {\n  content: \"\\f022\";\n}\n.fa-lock:before {\n  content: \"\\f023\";\n}\n.fa-flag:before {\n  content: \"\\f024\";\n}\n.fa-headphones:before {\n  content: \"\\f025\";\n}\n.fa-volume-off:before {\n  content: \"\\f026\";\n}\n.fa-volume-down:before {\n  content: \"\\f027\";\n}\n.fa-volume-up:before {\n  content: \"\\f028\";\n}\n.fa-qrcode:before {\n  content: \"\\f029\";\n}\n.fa-barcode:before {\n  content: \"\\f02a\";\n}\n.fa-tag:before {\n  content: \"\\f02b\";\n}\n.fa-tags:before {\n  content: \"\\f02c\";\n}\n.fa-book:before {\n  content: \"\\f02d\";\n}\n.fa-bookmark:before {\n  content: \"\\f02e\";\n}\n.fa-print:before {\n  content: \"\\f02f\";\n}\n.fa-camera:before {\n  content: \"\\f030\";\n}\n.fa-font:before {\n  content: \"\\f031\";\n}\n.fa-bold:before {\n  content: \"\\f032\";\n}\n.fa-italic:before {\n  content: \"\\f033\";\n}\n.fa-text-height:before {\n  content: \"\\f034\";\n}\n.fa-text-width:before {\n  content: \"\\f035\";\n}\n.fa-align-left:before {\n  content: \"\\f036\";\n}\n.fa-align-center:before {\n  content: \"\\f037\";\n}\n.fa-align-right:before {\n  content: \"\\f038\";\n}\n.fa-align-justify:before {\n  content: \"\\f039\";\n}\n.fa-list:before {\n  content: \"\\f03a\";\n}\n.fa-dedent:before,\n.fa-outdent:before {\n  content: \"\\f03b\";\n}\n.fa-indent:before {\n  content: \"\\f03c\";\n}\n.fa-video-camera:before {\n  content: \"\\f03d\";\n}\n.fa-picture-o:before {\n  content: \"\\f03e\";\n}\n.fa-pencil:before {\n  content: \"\\f040\";\n}\n.fa-map-marker:before {\n  content: \"\\f041\";\n}\n.fa-adjust:before {\n  content: \"\\f042\";\n}\n.fa-tint:before {\n  content: \"\\f043\";\n}\n.fa-edit:before,\n.fa-pencil-square-o:before {\n  content: \"\\f044\";\n}\n.fa-share-square-o:before {\n  content: \"\\f045\";\n}\n.fa-check-square-o:before {\n  content: \"\\f046\";\n}\n.fa-arrows:before {\n  content: \"\\f047\";\n}\n.fa-step-backward:before {\n  content: \"\\f048\";\n}\n.fa-fast-backward:before {\n  content: \"\\f049\";\n}\n.fa-backward:before {\n  content: \"\\f04a\";\n}\n.fa-play:before {\n  content: \"\\f04b\";\n}\n.fa-pause:before {\n  content: \"\\f04c\";\n}\n.fa-stop:before {\n  content: \"\\f04d\";\n}\n.fa-forward:before {\n  content: \"\\f04e\";\n}\n.fa-fast-forward:before {\n  content: \"\\f050\";\n}\n.fa-step-forward:before {\n  content: \"\\f051\";\n}\n.fa-eject:before {\n  content: \"\\f052\";\n}\n.fa-chevron-left:before {\n  content: \"\\f053\";\n}\n.fa-chevron-right:before {\n  content: \"\\f054\";\n}\n.fa-plus-circle:before {\n  content: \"\\f055\";\n}\n.fa-minus-circle:before {\n  content: \"\\f056\";\n}\n.fa-times-circle:before {\n  content: \"\\f057\";\n}\n.fa-check-circle:before {\n  content: \"\\f058\";\n}\n.fa-question-circle:before {\n  content: \"\\f059\";\n}\n.fa-info-circle:before {\n  content: \"\\f05a\";\n}\n.fa-crosshairs:before {\n  content: \"\\f05b\";\n}\n.fa-times-circle-o:before {\n  content: \"\\f05c\";\n}\n.fa-check-circle-o:before {\n  content: \"\\f05d\";\n}\n.fa-ban:before {\n  content: \"\\f05e\";\n}\n.fa-arrow-left:before {\n  content: \"\\f060\";\n}\n.fa-arrow-right:before {\n  content: \"\\f061\";\n}\n.fa-arrow-up:before {\n  content: \"\\f062\";\n}\n.fa-arrow-down:before {\n  content: \"\\f063\";\n}\n.fa-mail-forward:before,\n.fa-share:before {\n  content: \"\\f064\";\n}\n.fa-expand:before {\n  content: \"\\f065\";\n}\n.fa-compress:before {\n  content: \"\\f066\";\n}\n.fa-plus:before {\n  content: \"\\f067\";\n}\n.fa-minus:before {\n  content: \"\\f068\";\n}\n.fa-asterisk:before {\n  content: \"\\f069\";\n}\n.fa-exclamation-circle:before {\n  content: \"\\f06a\";\n}\n.fa-gift:before {\n  content: \"\\f06b\";\n}\n.fa-leaf:before {\n  content: \"\\f06c\";\n}\n.fa-fire:before {\n  content: \"\\f06d\";\n}\n.fa-eye:before {\n  content: \"\\f06e\";\n}\n.fa-eye-slash:before {\n  content: \"\\f070\";\n}\n.fa-warning:before,\n.fa-exclamation-triangle:before {\n  content: \"\\f071\";\n}\n.fa-plane:before {\n  content: \"\\f072\";\n}\n.fa-calendar:before {\n  content: \"\\f073\";\n}\n.fa-random:before {\n  content: \"\\f074\";\n}\n.fa-comment:before {\n  content: \"\\f075\";\n}\n.fa-magnet:before {\n  content: \"\\f076\";\n}\n.fa-chevron-up:before {\n  content: \"\\f077\";\n}\n.fa-chevron-down:before {\n  content: \"\\f078\";\n}\n.fa-retweet:before {\n  content: \"\\f079\";\n}\n.fa-shopping-cart:before {\n  content: \"\\f07a\";\n}\n.fa-folder:before {\n  content: \"\\f07b\";\n}\n.fa-folder-open:before {\n  content: \"\\f07c\";\n}\n.fa-arrows-v:before {\n  content: \"\\f07d\";\n}\n.fa-arrows-h:before {\n  content: \"\\f07e\";\n}\n.fa-twitter-square:before {\n  content: \"\\f081\";\n}\n.fa-facebook-square:before {\n  content: \"\\f082\";\n}\n.fa-camera-retro:before {\n  content: \"\\f083\";\n}\n.fa-key:before {\n  content: \"\\f084\";\n}\n.fa-gears:before,\n.fa-cogs:before {\n  content: \"\\f085\";\n}\n.fa-comments:before {\n  content: \"\\f086\";\n}\n.fa-thumbs-o-up:before {\n  content: \"\\f087\";\n}\n.fa-thumbs-o-down:before {\n  content: \"\\f088\";\n}\n.fa-star-half:before {\n  content: \"\\f089\";\n}\n.fa-heart-o:before {\n  content: \"\\f08a\";\n}\n.fa-sign-out:before {\n  content: \"\\f08b\";\n}\n.fa-linkedin-square:before {\n  content: \"\\f08c\";\n}\n.fa-thumb-tack:before {\n  content: \"\\f08d\";\n}\n.fa-external-link:before {\n  content: \"\\f08e\";\n}\n.fa-sign-in:before {\n  content: \"\\f090\";\n}\n.fa-trophy:before {\n  content: \"\\f091\";\n}\n.fa-github-square:before {\n  content: \"\\f092\";\n}\n.fa-upload:before {\n  content: \"\\f093\";\n}\n.fa-lemon-o:before {\n  content: \"\\f094\";\n}\n.fa-phone:before {\n  content: \"\\f095\";\n}\n.fa-square-o:before {\n  content: \"\\f096\";\n}\n.fa-bookmark-o:before {\n  content: \"\\f097\";\n}\n.fa-phone-square:before {\n  content: \"\\f098\";\n}\n.fa-twitter:before {\n  content: \"\\f099\";\n}\n.fa-facebook:before {\n  content: \"\\f09a\";\n}\n.fa-github:before {\n  content: \"\\f09b\";\n}\n.fa-unlock:before {\n  content: \"\\f09c\";\n}\n.fa-credit-card:before {\n  content: \"\\f09d\";\n}\n.fa-rss:before {\n  content: \"\\f09e\";\n}\n.fa-hdd-o:before {\n  content: \"\\f0a0\";\n}\n.fa-bullhorn:before {\n  content: \"\\f0a1\";\n}\n.fa-bell:before {\n  content: \"\\f0f3\";\n}\n.fa-certificate:before {\n  content: \"\\f0a3\";\n}\n.fa-hand-o-right:before {\n  content: \"\\f0a4\";\n}\n.fa-hand-o-left:before {\n  content: \"\\f0a5\";\n}\n.fa-hand-o-up:before {\n  content: \"\\f0a6\";\n}\n.fa-hand-o-down:before {\n  content: \"\\f0a7\";\n}\n.fa-arrow-circle-left:before {\n  content: \"\\f0a8\";\n}\n.fa-arrow-circle-right:before {\n  content: \"\\f0a9\";\n}\n.fa-arrow-circle-up:before {\n  content: \"\\f0aa\";\n}\n.fa-arrow-circle-down:before {\n  content: \"\\f0ab\";\n}\n.fa-globe:before {\n  content: \"\\f0ac\";\n}\n.fa-wrench:before {\n  content: \"\\f0ad\";\n}\n.fa-tasks:before {\n  content: \"\\f0ae\";\n}\n.fa-filter:before {\n  content: \"\\f0b0\";\n}\n.fa-briefcase:before {\n  content: \"\\f0b1\";\n}\n.fa-arrows-alt:before {\n  content: \"\\f0b2\";\n}\n.fa-group:before,\n.fa-users:before {\n  content: \"\\f0c0\";\n}\n.fa-chain:before,\n.fa-link:before {\n  content: \"\\f0c1\";\n}\n.fa-cloud:before {\n  content: \"\\f0c2\";\n}\n.fa-flask:before {\n  content: \"\\f0c3\";\n}\n.fa-cut:before,\n.fa-scissors:before {\n  content: \"\\f0c4\";\n}\n.fa-copy:before,\n.fa-files-o:before {\n  content: \"\\f0c5\";\n}\n.fa-paperclip:before {\n  content: \"\\f0c6\";\n}\n.fa-save:before,\n.fa-floppy-o:before {\n  content: \"\\f0c7\";\n}\n.fa-square:before {\n  content: \"\\f0c8\";\n}\n.fa-bars:before {\n  content: \"\\f0c9\";\n}\n.fa-list-ul:before {\n  content: \"\\f0ca\";\n}\n.fa-list-ol:before {\n  content: \"\\f0cb\";\n}\n.fa-strikethrough:before {\n  content: \"\\f0cc\";\n}\n.fa-underline:before {\n  content: \"\\f0cd\";\n}\n.fa-table:before {\n  content: \"\\f0ce\";\n}\n.fa-magic:before {\n  content: \"\\f0d0\";\n}\n.fa-truck:before {\n  content: \"\\f0d1\";\n}\n.fa-pinterest:before {\n  content: \"\\f0d2\";\n}\n.fa-pinterest-square:before {\n  content: \"\\f0d3\";\n}\n.fa-google-plus-square:before {\n  content: \"\\f0d4\";\n}\n.fa-google-plus:before {\n  content: \"\\f0d5\";\n}\n.fa-money:before {\n  content: \"\\f156\";\n}\n.fa-caret-down:before {\n  content: \"\\f0d7\";\n}\n.fa-caret-up:before {\n  content: \"\\f0d8\";\n}\n.fa-caret-left:before {\n  content: \"\\f0d9\";\n}\n.fa-caret-right:before {\n  content: \"\\f0da\";\n}\n.fa-columns:before {\n  content: \"\\f0db\";\n}\n.fa-unsorted:before,\n.fa-sort:before {\n  content: \"\\f0dc\";\n}\n.fa-sort-down:before,\n.fa-sort-asc:before {\n  content: \"\\f0dd\";\n}\n.fa-sort-up:before,\n.fa-sort-desc:before {\n  content: \"\\f0de\";\n}\n.fa-envelope:before {\n  content: \"\\f0e0\";\n}\n.fa-linkedin:before {\n  content: \"\\f0e1\";\n}\n.fa-rotate-left:before,\n.fa-undo:before {\n  content: \"\\f0e2\";\n}\n.fa-legal:before,\n.fa-gavel:before {\n  content: \"\\f0e3\";\n}\n.fa-dashboard:before,\n.fa-tachometer:before {\n  content: \"\\f0e4\";\n}\n.fa-comment-o:before {\n  content: \"\\f0e5\";\n}\n.fa-comments-o:before {\n  content: \"\\f0e6\";\n}\n.fa-flash:before,\n.fa-bolt:before {\n  content: \"\\f0e7\";\n}\n.fa-sitemap:before {\n  content: \"\\f0e8\";\n}\n.fa-umbrella:before {\n  content: \"\\f0e9\";\n}\n.fa-paste:before,\n.fa-clipboard:before {\n  content: \"\\f0ea\";\n}\n.fa-lightbulb-o:before {\n  content: \"\\f0eb\";\n}\n.fa-exchange:before {\n  content: \"\\f0ec\";\n}\n.fa-cloud-download:before {\n  content: \"\\f0ed\";\n}\n.fa-cloud-upload:before {\n  content: \"\\f0ee\";\n}\n.fa-user-md:before {\n  content: \"\\f0f0\";\n}\n.fa-stethoscope:before {\n  content: \"\\f0f1\";\n}\n.fa-suitcase:before {\n  content: \"\\f0f2\";\n}\n.fa-bell-o:before {\n  content: \"\\f0a2\";\n}\n.fa-coffee:before {\n  content: \"\\f0f4\";\n}\n.fa-cutlery:before {\n  content: \"\\f0f5\";\n}\n.fa-file-text-o:before {\n  content: \"\\f0f6\";\n}\n.fa-building-o:before {\n  content: \"\\f0f7\";\n}\n.fa-hospital-o:before {\n  content: \"\\f0f8\";\n}\n.fa-ambulance:before {\n  content: \"\\f0f9\";\n}\n.fa-medkit:before {\n  content: \"\\f0fa\";\n}\n.fa-fighter-jet:before {\n  content: \"\\f0fb\";\n}\n.fa-beer:before {\n  content: \"\\f0fc\";\n}\n.fa-h-square:before {\n  content: \"\\f0fd\";\n}\n.fa-plus-square:before {\n  content: \"\\f0fe\";\n}\n.fa-angle-double-left:before {\n  content: \"\\f100\";\n}\n.fa-angle-double-right:before {\n  content: \"\\f101\";\n}\n.fa-angle-double-up:before {\n  content: \"\\f102\";\n}\n.fa-angle-double-down:before {\n  content: \"\\f103\";\n}\n.fa-angle-left:before {\n  content: \"\\f104\";\n}\n.fa-angle-right:before {\n  content: \"\\f105\";\n}\n.fa-angle-up:before {\n  content: \"\\f106\";\n}\n.fa-angle-down:before {\n  content: \"\\f107\";\n}\n.fa-desktop:before {\n  content: \"\\f108\";\n}\n.fa-laptop:before {\n  content: \"\\f109\";\n}\n.fa-tablet:before {\n  content: \"\\f10a\";\n}\n.fa-mobile-phone:before,\n.fa-mobile:before {\n  content: \"\\f10b\";\n}\n.fa-circle-o:before {\n  content: \"\\f10c\";\n}\n.fa-quote-left:before {\n  content: \"\\f10d\";\n}\n.fa-quote-right:before {\n  content: \"\\f10e\";\n}\n.fa-spinner:before {\n  content: \"\\f110\";\n}\n.fa-circle:before {\n  content: \"\\f111\";\n}\n.fa-mail-reply:before,\n.fa-reply:before {\n  content: \"\\f112\";\n}\n.fa-github-alt:before {\n  content: \"\\f113\";\n}\n.fa-folder-o:before {\n  content: \"\\f114\";\n}\n.fa-folder-open-o:before {\n  content: \"\\f115\";\n}\n.fa-smile-o:before {\n  content: \"\\f118\";\n}\n.fa-frown-o:before {\n  content: \"\\f119\";\n}\n.fa-meh-o:before {\n  content: \"\\f11a\";\n}\n.fa-gamepad:before {\n  content: \"\\f11b\";\n}\n.fa-keyboard-o:before {\n  content: \"\\f11c\";\n}\n.fa-flag-o:before {\n  content: \"\\f11d\";\n}\n.fa-flag-checkered:before {\n  content: \"\\f11e\";\n}\n.fa-terminal:before {\n  content: \"\\f120\";\n}\n.fa-code:before {\n  content: \"\\f121\";\n}\n.fa-reply-all:before {\n  content: \"\\f122\";\n}\n.fa-mail-reply-all:before {\n  content: \"\\f122\";\n}\n.fa-star-half-empty:before,\n.fa-star-half-full:before,\n.fa-star-half-o:before {\n  content: \"\\f123\";\n}\n.fa-location-arrow:before {\n  content: \"\\f124\";\n}\n.fa-crop:before {\n  content: \"\\f125\";\n}\n.fa-code-fork:before {\n  content: \"\\f126\";\n}\n.fa-unlink:before,\n.fa-chain-broken:before {\n  content: \"\\f127\";\n}\n.fa-question:before {\n  content: \"\\f128\";\n}\n.fa-info:before {\n  content: \"\\f129\";\n}\n.fa-exclamation:before {\n  content: \"\\f12a\";\n}\n.fa-superscript:before {\n  content: \"\\f12b\";\n}\n.fa-subscript:before {\n  content: \"\\f12c\";\n}\n.fa-eraser:before {\n  content: \"\\f12d\";\n}\n.fa-puzzle-piece:before {\n  content: \"\\f12e\";\n}\n.fa-microphone:before {\n  content: \"\\f130\";\n}\n.fa-microphone-slash:before {\n  content: \"\\f131\";\n}\n.fa-shield:before {\n  content: \"\\f132\";\n}\n.fa-calendar-o:before {\n  content: \"\\f133\";\n}\n.fa-fire-extinguisher:before {\n  content: \"\\f134\";\n}\n.fa-rocket:before {\n  content: \"\\f135\";\n}\n.fa-maxcdn:before {\n  content: \"\\f136\";\n}\n.fa-chevron-circle-left:before {\n  content: \"\\f137\";\n}\n.fa-chevron-circle-right:before {\n  content: \"\\f138\";\n}\n.fa-chevron-circle-up:before {\n  content: \"\\f139\";\n}\n.fa-chevron-circle-down:before {\n  content: \"\\f13a\";\n}\n.fa-html5:before {\n  content: \"\\f13b\";\n}\n.fa-css3:before {\n  content: \"\\f13c\";\n}\n.fa-anchor:before {\n  content: \"\\f13d\";\n}\n.fa-unlock-alt:before {\n  content: \"\\f13e\";\n}\n.fa-bullseye:before {\n  content: \"\\f140\";\n}\n.fa-ellipsis-h:before {\n  content: \"\\f141\";\n}\n.fa-ellipsis-v:before {\n  content: \"\\f142\";\n}\n.fa-rss-square:before {\n  content: \"\\f143\";\n}\n.fa-play-circle:before {\n  content: \"\\f144\";\n}\n.fa-ticket:before {\n  content:\"\\f080\";\n}\n.fa-minus-square:before {\n  content: \"\\f146\";\n}\n.fa-minus-square-o:before {\n  content: \"\\f147\";\n}\n.fa-level-up:before {\n  content: \"\\f148\";\n}\n.fa-level-down:before {\n  content: \"\\f149\";\n}\n.fa-check-square:before {\n  content: \"\\f14a\";\n}\n.fa-pencil-square:before {\n  content: \"\\f14b\";\n}\n.fa-external-link-square:before {\n  content: \"\\f14c\";\n}\n.fa-share-square:before {\n  content: \"\\f14d\";\n}\n.fa-compass:before {\n  content: \"\\f14e\";\n}\n.fa-toggle-down:before,\n.fa-caret-square-o-down:before {\n  content: \"\\f150\";\n}\n.fa-toggle-up:before,\n.fa-caret-square-o-up:before {\n  content: \"\\f151\";\n}\n.fa-toggle-right:before,\n.fa-caret-square-o-right:before {\n  content: \"\\f152\";\n}\n.fa-euro:before,\n.fa-eur:before {\n  content: \"\\f153\";\n}\n.fa-gbp:before {\n  content: \"\\f154\";\n}\n.fa-dollar:before,\n.fa-usd:before {\n  content: \"\\f155\";\n}\n.fa-rupee:before,\n.fa-inr:before {\n  content: \"\\f156\";\n}\n.fa-cny:before,\n.fa-rmb:before,\n.fa-yen:before,\n.fa-jpy:before {\n  content: \"\\f157\";\n}\n.fa-ruble:before,\n.fa-rouble:before,\n.fa-rub:before {\n  content: \"\\f158\";\n}\n.fa-won:before,\n.fa-krw:before {\n  content: \"\\f159\";\n}\n.fa-bitcoin:before,\n.fa-btc:before {\n  content: \"\\f15a\";\n}\n.fa-file:before {\n  content: \"\\f15b\";\n}\n.fa-file-text:before {\n  content: \"\\f15c\";\n}\n.fa-sort-alpha-asc:before {\n  content: \"\\f15d\";\n}\n.fa-sort-alpha-desc:before {\n  content: \"\\f15e\";\n}\n.fa-sort-amount-asc:before {\n  content: \"\\f160\";\n}\n.fa-sort-amount-desc:before {\n  content: \"\\f161\";\n}\n.fa-sort-numeric-asc:before {\n  content: \"\\f162\";\n}\n.fa-sort-numeric-desc:before {\n  content: \"\\f163\";\n}\n.fa-thumbs-up:before {\n  content: \"\\f164\";\n}\n.fa-thumbs-down:before {\n  content: \"\\f165\";\n}\n.fa-youtube-square:before {\n  content: \"\\f166\";\n}\n.fa-youtube:before {\n  content: \"\\f167\";\n}\n.fa-xing:before {\n  content: \"\\f168\";\n}\n.fa-xing-square:before {\n  content: \"\\f169\";\n}\n.fa-youtube-play:before {\n  content: \"\\f16a\";\n}\n.fa-dropbox:before {\n  content: \"\\f16b\";\n}\n.fa-stack-overflow:before {\n  content: \"\\f16c\";\n}\n.fa-instagram:before {\n  content: \"\\f16d\";\n}\n.fa-flickr:before {\n  content: \"\\f16e\";\n}\n.fa-adn:before {\n  content: \"\\f170\";\n}\n.fa-bitbucket:before {\n  content: \"\\f171\";\n}\n.fa-bitbucket-square:before {\n  content: \"\\f172\";\n}\n.fa-tumblr:before {\n  content: \"\\f173\";\n}\n.fa-tumblr-square:before {\n  content: \"\\f174\";\n}\n.fa-long-arrow-down:before {\n  content: \"\\f175\";\n}\n.fa-long-arrow-up:before {\n  content: \"\\f176\";\n}\n.fa-long-arrow-left:before {\n  content: \"\\f177\";\n}\n.fa-long-arrow-right:before {\n  content: \"\\f178\";\n}\n.fa-apple:before {\n  content: \"\\f179\";\n}\n.fa-windows:before {\n  content: \"\\f17a\";\n}\n.fa-android:before {\n  content: \"\\f17b\";\n}\n.fa-linux:before {\n  content: \"\\f17c\";\n}\n.fa-dribbble:before {\n  content: \"\\f17d\";\n}\n.fa-skype:before {\n  content: \"\\f17e\";\n}\n.fa-foursquare:before {\n  content: \"\\f180\";\n}\n.fa-trello:before {\n  content: \"\\f181\";\n}\n.fa-female:before {\n  content: \"\\f182\";\n}\n.fa-male:before {\n  content: \"\\f183\";\n}\n.fa-gittip:before {\n  content: \"\\f184\";\n}\n.fa-sun-o:before {\n  content: \"\\f185\";\n}\n.fa-moon-o:before {\n  content: \"\\f186\";\n}\n.fa-archive:before {\n  content: \"\\f187\";\n}\n.fa-bug:before {\n  content: \"\\f188\";\n}\n.fa-vk:before {\n  content: \"\\f189\";\n}\n.fa-weibo:before {\n  content: \"\\f18a\";\n}\n.fa-renren:before {\n  content: \"\\f18b\";\n}\n.fa-pagelines:before {\n  content: \"\\f18c\";\n}\n.fa-stack-exchange:before {\n  content: \"\\f18d\";\n}\n.fa-arrow-circle-o-right:before {\n  content: \"\\f18e\";\n}\n.fa-arrow-circle-o-left:before {\n  content: \"\\f190\";\n}\n.fa-toggle-left:before,\n.fa-caret-square-o-left:before {\n  content: \"\\f191\";\n}\n.fa-dot-circle-o:before {\n  content: \"\\f192\";\n}\n.fa-wheelchair:before {\n  content: \"\\f193\";\n}\n.fa-vimeo-square:before {\n  content: \"\\f194\";\n}\n.fa-turkish-lira:before,\n.fa-try:before {\n  content: \"\\f195\";\n}\n.fa-plus-square-o:before {\n  content: \"\\f196\";\n}\n.fa-bar-chart:before {\n    content: \"\\f080\";\n}\n.fa-send-o:before, .fa-paper-plane-o:before {\n    content: \"\\f1d9\";\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/login/style.css",
    "content": "/*--\nAuthor: W3layouts\nAuthor URL: http://w3layouts.com\nLicense: Creative Commons Attribution 3.0 Unported\nLicense URL: http://creativecommons.org/licenses/by/3.0/\n--*/\n/* reset */\nhtml,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,dl,dt,dd,ol,nav ul,nav li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline;}\narticle, aside, details, figcaption, figure,footer, header, hgroup, menu, nav, section {display: block;}\nol,ul{list-style:none;margin:0px;padding:0px;}\nblockquote,q{quotes:none;}\nblockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}\ntable{border-collapse:collapse;border-spacing:0;}\n/* start editing from here */\na{text-decoration:none;}\n.txt-rt{text-align:right;}/* text align right */\n.txt-lt{text-align:left;}/* text align left */\n.txt-center{text-align:center;}/* text align center */\n.float-rt{float:right;}/* float right */\n.float-lt{float:left;}/* float left */\n.clear{clear:both;}/* clear float */\n.pos-relative{position:relative;}/* Position Relative */\n.pos-absolute{position:absolute;}/* Position Absolute */\n.vertical-base{\tvertical-align:baseline;}/* vertical align baseline */\n.vertical-top{\tvertical-align:top;}/* vertical align top */\nnav.vertical ul li{\tdisplay:block;}/* vertical menu */\nnav.horizontal ul li{\tdisplay: inline-block;}/* horizontal menu */\nimg{max-width:100%;}\n/*end reset*/\nbody {\n\ttext-align: center;\n\tfont-family: 'Oleo Script', cursive;\n}\n\n/*--header--*/\n.center-container {\n\tpadding: 0em;\n\tbackground: rgba(19, 19, 19, 0.42)\n}\n.header-w3l {\n\tpadding-top: 13em;\n}\n.header-w3l h1{\n\tfont-size:3em;\n\tcolor:white;\n\tletter-spacing: 4px;\n\tfont-weight: 500;\n\ttext-transform: uppercase;\n}\n/*--//header--*/\n\n/*--main--*/\n.main-content-agile {\n\tmargin: 4em 0em 3em;\n}\n.wthree-pro h2 {\n\tfont-size: 1.5em;\n\tcolor: #fff;\n\tletter-spacing: 1px;\n\tmargin-top: 0.3em;\n\tmargin-bottom: 2em;\n\tfont-weight: 400;\n}\n.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\toutline: none;\n\tfont-size: 1em;\n\tpadding: 1em 3em 1em 1em;\n\tborder: none;\n\tmargin-bottom: 0.3em;\n\tbackground: none;\n\tborder: 1px solid #eee;\n\twidth: 82%;\n\tcolor: #fff;\n\tfont-weight: 400;\n\tfont-family: '黑体';\n\tletter-spacing: 1px;\n}\n.sub-main-w3 {\n\tposition: relative;\n\twidth: 23%;\n\tmargin: 0 auto;\n}\n.sub-w3l h6 a {\n\tfont-size: 1em;\n\tcolor: #fff;\n\tletter-spacing: 2px;\n\ttext-align: right;\n\tdisplay: inherit;\n}\n.sub-w3l {\n\tmargin-top: 2em;\n}\n.right-w3l {\n\tmargin-top: 3em;\n}\nspan.icon1, span.icon2 {\n\tcolor: #fff;\n\tfont-size: 1.1em;\n\tposition: absolute;\n}\nspan.icon1 {\n\ttop: 27%;\n}\nspan.icon2 {\n\ttop: 49%;\n}\nspan.icon1, span.icon2{\n\tright:5%;\n}\n.sub-main-w3 input[type=\"button\"] {\n\tcolor: white;\n\tbackground: #2baf2b;\n\tborder: none;\n\tpadding: 8px 0px;\n\toutline: none;\n\twidth: 100%;\n\tfont-size: 1.1em;\n\tcursor: pointer;\n\tletter-spacing: 2px;\n\tfont-weight: 400;\n\tfont-family: '黑体';\n\ttransition: 0.5s all;\n\t-webkit-transition: 0.5s all;\n\t-o-transition: 0.5s all;\n\t-moz-transition: 0.5s all;\n\t-ms-transition: 0.5s all;\n}\n.sub-main-w3 input[type=\"button\"]:hover {\n\tbackground: #fff;\n\tcolor: black;\n\ttransition:0.5s all;\n\t-webkit-transition:0.5s all;\n\t-o-transition:0.5s all;\n\t-moz-transition:0.5s all;\n\t-ms-transition:0.5s all;\n}\n/*--//main--*/\n\n/*--footer--*/\n.footer {\n\tpadding: 6em 0 3em;\n}\n.footer p {\n\tfont-size: 1em;\n\tcolor: white;\n\tletter-spacing: 2px;\n}\n.footer p a {\n\tcolor: #2baf2b;\n}\n.footer p a:hover {\n\ttext-decoration:underline;\n}\n/*--//footer--*/\n\n/*--responsive--*/\n\n@media(max-width: 1680px){\n\n}\n@media(max-width: 1600px){\n\n}\n@media(max-width: 1440px){\n\t.sub-main-w3 {\n\t\twidth: 26%;\n\t}\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\twidth: 81%;\n\t}\n}\n@media(max-width: 1366px){\n\t.header-w3l h1 {\n\t\tfont-size: 2.9em;\n\t}\n\t.main-content-agile {\n\t\tmargin: 6em 0em 3em;\n\t}\n}\n@media(max-width: 1280px){\n\t.header-w3l h1 {\n\t\tfont-size: 2.8em;\n\t}\n\t.sub-main-w3 {\n\t\twidth: 28%;\n\t}\n}\n@media(max-width: 1080px){\n\t.header-w3l h1 {\n\t\tfont-size: 2.7em;\n\t}\n\t.wthree-pro h2 {\n\t\tfont-size: 1.3em;\n\t\tmargin-bottom: 1.5em;\n\t}\n\t.sub-main-w3 {\n\t\twidth: 31%;\n\t}\n\t.footer {\n\t\tpadding: 5em 0 2em;\n\t}\n\tspan.icon1 {\n\t\ttop: 22%;\n\t}\n\tspan.icon2 {\n\t\ttop: 46%;\n\t}\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\twidth: 80%;\n\t}\n\t.sub-main-w3 input[type=\"button\"] {\n\t\tfont-size: 1em;\n\t}\n}\n@media(max-width: 1050px){\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\twidth: 79%;\n\t}\n}\n@media(max-width: 1024px){\n\t.header-w3l {\n\t\tpadding-top: 1.35em;\n\t}\n\t.header-w3l h1 {\n\t\tfont-size: 2.6em;\n\t}\n\t.sub-main-w3 {\n\t\twidth: 33%;\n\t}\n\t.footer {\n\t\tpadding: 4em 0 2em;\n\t}\n\t.right-w3l {\n\t\tmargin-top: 2.5em;\n\t}\n\t.main-content-agile {\n\t\tmargin: 5.75em 0em 3em;\n\t}\n\tspan.icon2 {\n\t\ttop: 47%;\n\t}\n\tspan.icon1 {\n\t\ttop: 23%;\n\t}\n\tspan.icon1, span.icon2 {\n\t\tright: 6.5%;\n\t}\n}\n@media(max-width: 991px){\n\t.header-w3l h1 {\n\t\tfont-size: 2.55em;\n\t}\n\t.main-content-agile {\n\t\tmargin: 4em 0em 2em;\n\t}\n\t.footer {\n\t\tpadding: 3em 0 1.5em;\n\t}\n\t.right-w3l {\n\t\tmargin-top: 2.25em;\n\t}\n\tspan.icon2 {\n\t\ttop: 48%;\n\t}\n}\n@media(max-width: 900px){\n\n}\n@media(max-width: 800px){\n\t.header-w3l h1 {\n\t\tfont-size: 2.4em;\n\t\tletter-spacing: 3px;\n\t}\n\t.sub-main-w3 {\n\t\twidth: 39%;\n\t}\n}\n@media(max-width: 768px){\n\t.header-w3l {\n\t\tpadding-top: 2em;\n\t}\n\t.wthree-pro h2 {\n\t\tfont-size: 1.25em;\n\t\tmargin-bottom: 2em;\n\t}\n\t.sub-main-w3 {\n\t\twidth: 41%;\n\t}\n\t.right-w3l {\n\t\tmargin-top: 3em;\n\t}\n\t.main-content-agile {\n\t\tmargin: 8em 0em 4em;\n\t}\n\t.footer {\n\t\tpadding: 6.3em 0 10em;\n\t}\n}\n@media(max-width: 736px){\n\t.header-w3l {\n\t\tpadding-top: 1.35em;\n\t}\n\t.wthree-pro h2 {\n\t\tmargin-bottom: 1.5em;\n\t}\n\t.main-content-agile {\n\t\tmargin: 4em 0em 2em;\n\t}\n\t.right-w3l {\n\t\tmargin-top: 2.25em;\n\t}\n\t.footer {\n\t\tpadding: 3em 0 1.8em;\n\t}\n\t.footer p {\n\t\tfont-size: 0.95em;\n\t}\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\twidth: 78%;\n\t}\n}\n@media(max-width: 667px){\n\t.header-w3l h1 {\n\t\tfont-size: 2.25em;\n\t}\n\t.wthree-pro h2 {\n\t\tfont-size: 1.2em;\n\t}\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\tpadding: 0.9em 3em 0.9em 0.9em;\n\t}\n\t.main-content-agile {\n\t\tmargin: 4.4em 0em 2em;\n\t}\n\t.footer {\n\t\tpadding: 3.2em 0 2em;\n\t}\n\t.sub-main-w3 {\n\t\twidth: 45%;\n\t}\n\tspan.icon1, span.icon2 {\n\t\tright: 7%;\n\t\ttop: 21.5%;\n\t}\n\tspan.icon2 {\n\t\ttop: 46.5%;\n\t}\n}\n@media(max-width: 640px){\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\twidth: 77%;\n\t}\n}\n@media(max-width: 600px){\n\t.sub-main-w3 {\n\t\twidth: 50%;\n\t}\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\twidth: 78%;\n\t}\n}\n@media(max-width: 568px){\n\t.header-w3l h1 {\n\t\tfont-size: 2.1em;\n\t}\n\t.sub-main-w3 {\n\t\twidth: 51%;\n\t}\n}\n@media(max-width: 480px){\n\t.header-w3l h1 {\n\t\tfont-size: 2em;\n\t}\n\t.wthree-pro h2 {\n\t\tfont-size: 1.15em;\n\t}\n\t.sub-main-w3 {\n\t\twidth: 58%;\n\t}\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\twidth: 76%;\n\t}\n\t.footer p {\n\t\tline-height: 2;\n\t}\n}\n@media(max-width: 414px){\n\t.header-w3l h1 {\n\t\tfont-size: 1.8em;\n\t}\n\t.wthree-pro h2 {\n\t\tfont-size: 1.1em;\n\t}\n\t.sub-main-w3 {\n\t\twidth: 62%;\n\t}\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\twidth: 74%;\n\t}\n\t.footer {\n\t\tpadding: 4.95em 0 3.2em;\n\t}\n}\n@media(max-width: 384px){\n\t.header-w3l h1 {\n\t\tfont-size: 1.6em;\n\t\tletter-spacing: 2px;\n\t}\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\tpadding: 0.8em 3em 0.8em 0.9em;\n\t}\n\t.sub-main-w3 {\n\t\twidth: 70%;\n\t}\n\t.sub-main-w3 input[type=\"button\"] {\n\t\tletter-spacing: 1px\n\t}\n\t.footer {\n\t\tpadding: 3em 0 1.6em;\n\t}\n\t.footer p {\n\t\tfont-size: 0.9em;\n\t}\n}\n@media(max-width: 375px){\n\t.footer {\n\t\tpadding: 3.2em 0 1.6em;\n\t}\n}\n@media(max-width: 320px){\n\t.header-w3l h1 {\n\t\tfont-size: 1.45em;\n\t}\n\t.wthree-pro h2 {\n\t\tfont-size: 1em;\n\t}\n\t.sub-main-w3 input[type=\"text\"], .sub-main-w3 input[type=\"password\"] {\n\t\tfont-size: 0.9em;\n\t}\n\t.main-content-agile {\n\t\tmargin: 2.5em 0em 1em;\n\t}\n\t.sub-w3l h6 a {\n\t\tfont-size: 0.9em;\n\t}\n\t.sub-main-w3 input[type=\"button\"] {\n\t\tpadding: 7px 0px;\n\t\twidth: 42%;\n\t}\n\t.right-w3l {\n\t\tmargin-top: 2em;\n\t}\n\t.footer p {\n\t\tfont-size: 0.85em;\n\t\tletter-spacing: 1px;\n\t}\n\t.footer {\n\t\tpadding: 2.2em 0 1.4em;\n\t}\n}\n/*--//responsive--*/\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/nprogress/0.2.0/nprogress.css",
    "content": "/* Make clicks pass-through */\n#nprogress {\n  pointer-events: none;\n}\n\n#nprogress .bar {\n  background: #29d;\n\n  position: fixed;\n  z-index: 1031;\n  top: 0;\n  left: 0;\n\n  width: 100%;\n  height: 2px;\n}\n\n/* Fancy blur effect */\n#nprogress .peg {\n  display: block;\n  position: absolute;\n  right: 0px;\n  width: 100px;\n  height: 100%;\n  box-shadow: 0 0 10px #29d, 0 0 5px #29d;\n  opacity: 1.0;\n\n  -webkit-transform: rotate(3deg) translate(0px, -4px);\n      -ms-transform: rotate(3deg) translate(0px, -4px);\n          transform: rotate(3deg) translate(0px, -4px);\n}\n\n/* Remove these to get rid of the spinner */\n#nprogress .spinner {\n  display: block;\n  position: fixed;\n  z-index: 1031;\n  top: 15px;\n  right: 15px;\n}\n\n#nprogress .spinner-icon {\n  width: 18px;\n  height: 18px;\n  box-sizing: border-box;\n\n  border: solid 2px transparent;\n  border-top-color: #29d;\n  border-left-color: #29d;\n  border-radius: 50%;\n\n  -webkit-animation: nprogress-spinner 400ms linear infinite;\n          animation: nprogress-spinner 400ms linear infinite;\n}\n\n.nprogress-custom-parent {\n  overflow: hidden;\n  position: relative;\n}\n\n.nprogress-custom-parent #nprogress .spinner,\n.nprogress-custom-parent #nprogress .bar {\n  position: absolute;\n}\n\n@-webkit-keyframes nprogress-spinner {\n  0%   { -webkit-transform: rotate(0deg); }\n  100% { -webkit-transform: rotate(360deg); }\n}\n@keyframes nprogress-spinner {\n  0%   { transform: rotate(0deg); }\n  100% { transform: rotate(360deg); }\n}\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/nprogress/0.2.0/nprogress.js",
    "content": "/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress\n * @license MIT */\n\n;(function(root, factory) {\n\n  if (typeof define === 'function' && define.amd) {\n    define(factory);\n  } else if (typeof exports === 'object') {\n    module.exports = factory();\n  } else {\n    root.NProgress = factory();\n  }\n\n})(this, function() {\n  var NProgress = {};\n\n  NProgress.version = '0.2.0';\n\n  var Settings = NProgress.settings = {\n    minimum: 0.08,\n    easing: 'ease',\n    positionUsing: '',\n    speed: 200,\n    trickle: true,\n    trickleRate: 0.02,\n    trickleSpeed: 800,\n    showSpinner: true,\n    barSelector: '[role=\"bar\"]',\n    spinnerSelector: '[role=\"spinner\"]',\n    parent: 'body',\n    template: '<div class=\"bar\" role=\"bar\"><div class=\"peg\"></div></div><div class=\"spinner\" role=\"spinner\"><div class=\"spinner-icon\"></div></div>'\n  };\n\n  /**\n   * Updates configuration.\n   *\n   *     NProgress.configure({\n   *       minimum: 0.1\n   *     });\n   */\n  NProgress.configure = function(options) {\n    var key, value;\n    for (key in options) {\n      value = options[key];\n      if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;\n    }\n\n    return this;\n  };\n\n  /**\n   * Last number.\n   */\n\n  NProgress.status = null;\n\n  /**\n   * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.\n   *\n   *     NProgress.set(0.4);\n   *     NProgress.set(1.0);\n   */\n\n  NProgress.set = function(n) {\n    var started = NProgress.isStarted();\n\n    n = clamp(n, Settings.minimum, 1);\n    NProgress.status = (n === 1 ? null : n);\n\n    var progress = NProgress.render(!started),\n        bar      = progress.querySelector(Settings.barSelector),\n        speed    = Settings.speed,\n        ease     = Settings.easing;\n\n    progress.offsetWidth; /* Repaint */\n\n    queue(function(next) {\n      // Set positionUsing if it hasn't already been set\n      if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();\n\n      // Add transition\n      css(bar, barPositionCSS(n, speed, ease));\n\n      if (n === 1) {\n        // Fade out\n        css(progress, { \n          transition: 'none', \n          opacity: 1 \n        });\n        progress.offsetWidth; /* Repaint */\n\n        setTimeout(function() {\n          css(progress, { \n            transition: 'all ' + speed + 'ms linear', \n            opacity: 0 \n          });\n          setTimeout(function() {\n            NProgress.remove();\n            next();\n          }, speed);\n        }, speed);\n      } else {\n        setTimeout(next, speed);\n      }\n    });\n\n    return this;\n  };\n\n  NProgress.isStarted = function() {\n    return typeof NProgress.status === 'number';\n  };\n\n  /**\n   * Shows the progress bar.\n   * This is the same as setting the status to 0%, except that it doesn't go backwards.\n   *\n   *     NProgress.start();\n   *\n   */\n  NProgress.start = function() {\n    if (!NProgress.status) NProgress.set(0);\n\n    var work = function() {\n      setTimeout(function() {\n        if (!NProgress.status) return;\n        NProgress.trickle();\n        work();\n      }, Settings.trickleSpeed);\n    };\n\n    if (Settings.trickle) work();\n\n    return this;\n  };\n\n  /**\n   * Hides the progress bar.\n   * This is the *sort of* the same as setting the status to 100%, with the\n   * difference being `done()` makes some placebo effect of some realistic motion.\n   *\n   *     NProgress.done();\n   *\n   * If `true` is passed, it will show the progress bar even if its hidden.\n   *\n   *     NProgress.done(true);\n   */\n\n  NProgress.done = function(force) {\n    if (!force && !NProgress.status) return this;\n\n    return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);\n  };\n\n  /**\n   * Increments by a random amount.\n   */\n\n  NProgress.inc = function(amount) {\n    var n = NProgress.status;\n\n    if (!n) {\n      return NProgress.start();\n    } else {\n      if (typeof amount !== 'number') {\n        amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);\n      }\n\n      n = clamp(n + amount, 0, 0.994);\n      return NProgress.set(n);\n    }\n  };\n\n  NProgress.trickle = function() {\n    return NProgress.inc(Math.random() * Settings.trickleRate);\n  };\n\n  /**\n   * Waits for all supplied jQuery promises and\n   * increases the progress as the promises resolve.\n   *\n   * @param $promise jQUery Promise\n   */\n  (function() {\n    var initial = 0, current = 0;\n\n    NProgress.promise = function($promise) {\n      if (!$promise || $promise.state() === \"resolved\") {\n        return this;\n      }\n\n      if (current === 0) {\n        NProgress.start();\n      }\n\n      initial++;\n      current++;\n\n      $promise.always(function() {\n        current--;\n        if (current === 0) {\n            initial = 0;\n            NProgress.done();\n        } else {\n            NProgress.set((initial - current) / initial);\n        }\n      });\n\n      return this;\n    };\n\n  })();\n\n  /**\n   * (Internal) renders the progress bar markup based on the `template`\n   * setting.\n   */\n\n  NProgress.render = function(fromStart) {\n    if (NProgress.isRendered()) return document.getElementById('nprogress');\n\n    addClass(document.documentElement, 'nprogress-busy');\n    \n    var progress = document.createElement('div');\n    progress.id = 'nprogress';\n    progress.innerHTML = Settings.template;\n\n    var bar      = progress.querySelector(Settings.barSelector),\n        perc     = fromStart ? '-100' : toBarPerc(NProgress.status || 0),\n        parent   = document.querySelector(Settings.parent),\n        spinner;\n    \n    css(bar, {\n      transition: 'all 0 linear',\n      transform: 'translate3d(' + perc + '%,0,0)'\n    });\n\n    if (!Settings.showSpinner) {\n      spinner = progress.querySelector(Settings.spinnerSelector);\n      spinner && removeElement(spinner);\n    }\n\n    if (parent != document.body) {\n      addClass(parent, 'nprogress-custom-parent');\n    }\n\n    parent.appendChild(progress);\n    return progress;\n  };\n\n  /**\n   * Removes the element. Opposite of render().\n   */\n\n  NProgress.remove = function() {\n    removeClass(document.documentElement, 'nprogress-busy');\n    removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent');\n    var progress = document.getElementById('nprogress');\n    progress && removeElement(progress);\n  };\n\n  /**\n   * Checks if the progress bar is rendered.\n   */\n\n  NProgress.isRendered = function() {\n    return !!document.getElementById('nprogress');\n  };\n\n  /**\n   * Determine which positioning CSS rule to use.\n   */\n\n  NProgress.getPositioningCSS = function() {\n    // Sniff on document.body.style\n    var bodyStyle = document.body.style;\n\n    // Sniff prefixes\n    var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :\n                       ('MozTransform' in bodyStyle) ? 'Moz' :\n                       ('msTransform' in bodyStyle) ? 'ms' :\n                       ('OTransform' in bodyStyle) ? 'O' : '';\n\n    if (vendorPrefix + 'Perspective' in bodyStyle) {\n      // Modern browsers with 3D support, e.g. Webkit, IE10\n      return 'translate3d';\n    } else if (vendorPrefix + 'Transform' in bodyStyle) {\n      // Browsers without 3D support, e.g. IE9\n      return 'translate';\n    } else {\n      // Browsers without translate() support, e.g. IE7-8\n      return 'margin';\n    }\n  };\n\n  /**\n   * Helpers\n   */\n\n  function clamp(n, min, max) {\n    if (n < min) return min;\n    if (n > max) return max;\n    return n;\n  }\n\n  /**\n   * (Internal) converts a percentage (`0..1`) to a bar translateX\n   * percentage (`-100%..0%`).\n   */\n\n  function toBarPerc(n) {\n    return (-1 + n) * 100;\n  }\n\n\n  /**\n   * (Internal) returns the correct CSS for changing the bar's\n   * position given an n percentage, and speed and ease from Settings\n   */\n\n  function barPositionCSS(n, speed, ease) {\n    var barCSS;\n\n    if (Settings.positionUsing === 'translate3d') {\n      barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };\n    } else if (Settings.positionUsing === 'translate') {\n      barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };\n    } else {\n      barCSS = { 'margin-left': toBarPerc(n)+'%' };\n    }\n\n    barCSS.transition = 'all '+speed+'ms '+ease;\n\n    return barCSS;\n  }\n\n  /**\n   * (Internal) Queues a function to be executed.\n   */\n\n  var queue = (function() {\n    var pending = [];\n    \n    function next() {\n      var fn = pending.shift();\n      if (fn) {\n        fn(next);\n      }\n    }\n\n    return function(fn) {\n      pending.push(fn);\n      if (pending.length == 1) next();\n    };\n  })();\n\n  /**\n   * (Internal) Applies css properties to an element, similar to the jQuery \n   * css method.\n   *\n   * While this helper does assist with vendor prefixed property names, it \n   * does not perform any manipulation of values prior to setting styles.\n   */\n\n  var css = (function() {\n    var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],\n        cssProps    = {};\n\n    function camelCase(string) {\n      return string.replace(/^-ms-/, 'ms-').replace(/-([\\da-z])/gi, function(match, letter) {\n        return letter.toUpperCase();\n      });\n    }\n\n    function getVendorProp(name) {\n      var style = document.body.style;\n      if (name in style) return name;\n\n      var i = cssPrefixes.length,\n          capName = name.charAt(0).toUpperCase() + name.slice(1),\n          vendorName;\n      while (i--) {\n        vendorName = cssPrefixes[i] + capName;\n        if (vendorName in style) return vendorName;\n      }\n\n      return name;\n    }\n\n    function getStyleProp(name) {\n      name = camelCase(name);\n      return cssProps[name] || (cssProps[name] = getVendorProp(name));\n    }\n\n    function applyCss(element, prop, value) {\n      prop = getStyleProp(prop);\n      element.style[prop] = value;\n    }\n\n    return function(element, properties) {\n      var args = arguments,\n          prop, \n          value;\n\n      if (args.length == 2) {\n        for (prop in properties) {\n          value = properties[prop];\n          if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);\n        }\n      } else {\n        applyCss(element, args[1], args[2]);\n      }\n    }\n  })();\n\n  /**\n   * (Internal) Determines if an element or space separated list of class names contains a class name.\n   */\n\n  function hasClass(element, name) {\n    var list = typeof element == 'string' ? element : classList(element);\n    return list.indexOf(' ' + name + ' ') >= 0;\n  }\n\n  /**\n   * (Internal) Adds a class to an element.\n   */\n\n  function addClass(element, name) {\n    var oldList = classList(element),\n        newList = oldList + name;\n\n    if (hasClass(oldList, name)) return; \n\n    // Trim the opening space.\n    element.className = newList.substring(1);\n  }\n\n  /**\n   * (Internal) Removes a class from an element.\n   */\n\n  function removeClass(element, name) {\n    var oldList = classList(element),\n        newList;\n\n    if (!hasClass(element, name)) return;\n\n    // Replace the class name.\n    newList = oldList.replace(' ' + name + ' ', ' ');\n\n    // Trim the opening and closing spaces.\n    element.className = newList.substring(1, newList.length - 1);\n  }\n\n  /**\n   * (Internal) Gets a space separated list of the class names on the element. \n   * The list is wrapped with a single space on each end to facilitate finding \n   * matches within the list.\n   */\n\n  function classList(element) {\n    return (' ' + (element.className || '') + ' ').replace(/\\s+/gi, ' ');\n  }\n\n  /**\n   * (Internal) Removes an element from the DOM.\n   */\n\n  function removeElement(element) {\n    element && element.parentNode && element.parentNode.removeChild(element);\n  }\n\n  return NProgress;\n});\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/province/distpicker.data.js",
    "content": "/*!\n * Distpicker v1.0.4\n * https://github.com/fengyuanchen/distpicker\n *\n * Copyright (c) 2014-2016 Fengyuan Chen\n * Released under the MIT license\n *\n * Date: 2016-06-01T15:05:52.606Z\n */\n\n(function (factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as anonymous module.\n    define('ChineseDistricts', [], factory);\n  } else {\n    // Browser globals.\n    factory();\n  }\n})(function () {\n\n  var ChineseDistricts = {\n    86: {\n      110000: '北京市',\n      120000: '天津市',\n      130000: '河北省',\n      140000: '山西省',\n      150000: '内蒙古自治区',\n      210000: '辽宁省',\n      220000: '吉林省',\n      230000: '黑龙江省',\n      310000: '上海市',\n      320000: '江苏省',\n      330000: '浙江省',\n      340000: '安徽省',\n      350000: '福建省',\n      360000: '江西省',\n      370000: '山东省',\n      410000: '河南省',\n      420000: '湖北省',\n      430000: '湖南省',\n      440000: '广东省',\n      450000: '广西壮族自治区',\n      460000: '海南省',\n      500000: '重庆市',\n      510000: '四川省',\n      520000: '贵州省',\n      530000: '云南省',\n      540000: '西藏自治区',\n      610000: '陕西省',\n      620000: '甘肃省',\n      630000: '青海省',\n      640000: '宁夏回族自治区',\n      650000: '新疆维吾尔自治区',\n      710000: '台湾省',\n      810000: '香港特别行政区',\n      820000: '澳门特别行政区'\n    },\n    110000: {\n      110100: '北京市市辖区'\n    },\n    110100: {\n      110101: '东城区',\n      110102: '西城区',\n      110105: '朝阳区',\n      110106: '丰台区',\n      110107: '石景山区',\n      110108: '海淀区',\n      110109: '门头沟区',\n      110111: '房山区',\n      110112: '通州区',\n      110113: '顺义区',\n      110114: '昌平区',\n      110115: '大兴区',\n      110116: '怀柔区',\n      110117: '平谷区',\n      110118: '密云区',\n      110119: '延庆区'\n    },\n    120000: {\n      120100: '天津市市辖区',\n      120200: '天津市郊县'\n    },\n    120100: {\n      120101: '和平区',\n      120102: '河东区',\n      120103: '河西区',\n      120104: '南开区',\n      120105: '河北区',\n      120106: '红桥区',\n      120110: '东丽区',\n      120111: '西青区',\n      120112: '津南区',\n      120113: '北辰区',\n      120114: '武清区',\n      120115: '宝坻区',\n      120116: '滨海新区',\n      120117: '宁河区',\n      120118: '静海区',\n      120225: '蓟县'\n    },\n    130000: {\n      130100: '石家庄市',\n      130200: '唐山市',\n      130300: '秦皇岛市',\n      130400: '邯郸市',\n      130500: '邢台市',\n      130600: '保定市',\n      130700: '张家口市',\n      130800: '承德市',\n      130900: '沧州市',\n      131000: '廊坊市',\n      131100: '衡水市'\n    },\n    130100: {\n      130102: '长安区',\n      130104: '桥西区',\n      130105: '新华区',\n      130107: '井陉矿区',\n      130108: '裕华区',\n      130109: '藁城区',\n      130110: '鹿泉区',\n      130111: '栾城区',\n      130121: '井陉县',\n      130123: '正定县',\n      130125: '行唐县',\n      130126: '灵寿县',\n      130127: '高邑县',\n      130128: '深泽县',\n      130129: '赞皇县',\n      130130: '无极县',\n      130131: '平山县',\n      130132: '元氏县',\n      130133: '赵县',\n      130181: '辛集市',\n      130183: '晋州市',\n      130184: '新乐市'\n    },\n    130200: {\n      130202: '路南区',\n      130203: '路北区',\n      130204: '古冶区',\n      130205: '开平区',\n      130207: '丰南区',\n      130208: '丰润区',\n      130209: '曹妃甸区',\n      130223: '滦县',\n      130224: '滦南县',\n      130225: '乐亭县',\n      130227: '迁西县',\n      130229: '玉田县',\n      130281: '遵化市',\n      130283: '迁安市'\n    },\n    130300: {\n      130302: '海港区',\n      130303: '山海关区',\n      130304: '北戴河区',\n      130306: '抚宁区',\n      130321: '青龙满族自治县',\n      130322: '昌黎县',\n      130324: '卢龙县'\n    },\n    130400: {\n      130402: '邯山区',\n      130403: '丛台区',\n      130404: '复兴区',\n      130406: '峰峰矿区',\n      130421: '邯郸县',\n      130423: '临漳县',\n      130424: '成安县',\n      130425: '大名县',\n      130426: '涉县',\n      130427: '磁县',\n      130428: '肥乡县',\n      130429: '永年县',\n      130430: '邱县',\n      130431: '鸡泽县',\n      130432: '广平县',\n      130433: '馆陶县',\n      130434: '魏县',\n      130435: '曲周县',\n      130481: '武安市'\n    },\n    130500: {\n      130502: '桥东区',\n      130503: '桥西区',\n      130521: '邢台县',\n      130522: '临城县',\n      130523: '内丘县',\n      130524: '柏乡县',\n      130525: '隆尧县',\n      130526: '任县',\n      130527: '南和县',\n      130528: '宁晋县',\n      130529: '巨鹿县',\n      130530: '新河县',\n      130531: '广宗县',\n      130532: '平乡县',\n      130533: '威县',\n      130534: '清河县',\n      130535: '临西县',\n      130581: '南宫市',\n      130582: '沙河市'\n    },\n    130600: {\n      130602: '竞秀区',\n      130606: '莲池区',\n      130607: '满城区',\n      130608: '清苑区',\n      130609: '徐水区',\n      130623: '涞水县',\n      130624: '阜平县',\n      130626: '定兴县',\n      130627: '唐县',\n      130628: '高阳县',\n      130629: '容城县',\n      130630: '涞源县',\n      130631: '望都县',\n      130632: '安新县',\n      130633: '易县',\n      130634: '曲阳县',\n      130635: '蠡县',\n      130636: '顺平县',\n      130637: '博野县',\n      130638: '雄县',\n      130681: '涿州市',\n      130682: '定州市',\n      130683: '安国市',\n      130684: '高碑店市'\n    },\n    130700: {\n      130702: '桥东区',\n      130703: '桥西区',\n      130705: '宣化区',\n      130706: '下花园区',\n      130721: '宣化县',\n      130722: '张北县',\n      130723: '康保县',\n      130724: '沽源县',\n      130725: '尚义县',\n      130726: '蔚县',\n      130727: '阳原县',\n      130728: '怀安县',\n      130729: '万全县',\n      130730: '怀来县',\n      130731: '涿鹿县',\n      130732: '赤城县',\n      130733: '崇礼县'\n    },\n    130800: {\n      130802: '双桥区',\n      130803: '双滦区',\n      130804: '鹰手营子矿区',\n      130821: '承德县',\n      130822: '兴隆县',\n      130823: '平泉县',\n      130824: '滦平县',\n      130825: '隆化县',\n      130826: '丰宁满族自治县',\n      130827: '宽城满族自治县',\n      130828: '围场满族蒙古族自治县'\n    },\n    130900: {\n      130902: '新华区',\n      130903: '运河区',\n      130921: '沧县',\n      130922: '青县',\n      130923: '东光县',\n      130924: '海兴县',\n      130925: '盐山县',\n      130926: '肃宁县',\n      130927: '南皮县',\n      130928: '吴桥县',\n      130929: '献县',\n      130930: '孟村回族自治县',\n      130981: '泊头市',\n      130982: '任丘市',\n      130983: '黄骅市',\n      130984: '河间市'\n    },\n    131000: {\n      131002: '安次区',\n      131003: '广阳区',\n      131022: '固安县',\n      131023: '永清县',\n      131024: '香河县',\n      131025: '大城县',\n      131026: '文安县',\n      131028: '大厂回族自治县',\n      131081: '霸州市',\n      131082: '三河市'\n    },\n    131100: {\n      131102: '桃城区',\n      131121: '枣强县',\n      131122: '武邑县',\n      131123: '武强县',\n      131124: '饶阳县',\n      131125: '安平县',\n      131126: '故城县',\n      131127: '景县',\n      131128: '阜城县',\n      131181: '冀州市',\n      131182: '深州市'\n    },\n    140000: {\n      140100: '太原市',\n      140200: '大同市',\n      140300: '阳泉市',\n      140400: '长治市',\n      140500: '晋城市',\n      140600: '朔州市',\n      140700: '晋中市',\n      140800: '运城市',\n      140900: '忻州市',\n      141000: '临汾市',\n      141100: '吕梁市'\n    },\n    140100: {\n      140105: '小店区',\n      140106: '迎泽区',\n      140107: '杏花岭区',\n      140108: '尖草坪区',\n      140109: '万柏林区',\n      140110: '晋源区',\n      140121: '清徐县',\n      140122: '阳曲县',\n      140123: '娄烦县',\n      140181: '古交市'\n    },\n    140200: {\n      140202: '城区',\n      140203: '矿区',\n      140211: '南郊区',\n      140212: '新荣区',\n      140221: '阳高县',\n      140222: '天镇县',\n      140223: '广灵县',\n      140224: '灵丘县',\n      140225: '浑源县',\n      140226: '左云县',\n      140227: '大同县'\n    },\n    140300: {\n      140302: '城区',\n      140303: '矿区',\n      140311: '郊区',\n      140321: '平定县',\n      140322: '盂县'\n    },\n    140400: {\n      140402: '城区',\n      140411: '郊区',\n      140421: '长治县',\n      140423: '襄垣县',\n      140424: '屯留县',\n      140425: '平顺县',\n      140426: '黎城县',\n      140427: '壶关县',\n      140428: '长子县',\n      140429: '武乡县',\n      140430: '沁县',\n      140431: '沁源县',\n      140481: '潞城市'\n    },\n    140500: {\n      140502: '城区',\n      140521: '沁水县',\n      140522: '阳城县',\n      140524: '陵川县',\n      140525: '泽州县',\n      140581: '高平市'\n    },\n    140600: {\n      140602: '朔城区',\n      140603: '平鲁区',\n      140621: '山阴县',\n      140622: '应县',\n      140623: '右玉县',\n      140624: '怀仁县'\n    },\n    140700: {\n      140702: '榆次区',\n      140721: '榆社县',\n      140722: '左权县',\n      140723: '和顺县',\n      140724: '昔阳县',\n      140725: '寿阳县',\n      140726: '太谷县',\n      140727: '祁县',\n      140728: '平遥县',\n      140729: '灵石县',\n      140781: '介休市'\n    },\n    140800: {\n      140802: '盐湖区',\n      140821: '临猗县',\n      140822: '万荣县',\n      140823: '闻喜县',\n      140824: '稷山县',\n      140825: '新绛县',\n      140826: '绛县',\n      140827: '垣曲县',\n      140828: '夏县',\n      140829: '平陆县',\n      140830: '芮城县',\n      140881: '永济市',\n      140882: '河津市'\n    },\n    140900: {\n      140902: '忻府区',\n      140921: '定襄县',\n      140922: '五台县',\n      140923: '代县',\n      140924: '繁峙县',\n      140925: '宁武县',\n      140926: '静乐县',\n      140927: '神池县',\n      140928: '五寨县',\n      140929: '岢岚县',\n      140930: '河曲县',\n      140931: '保德县',\n      140932: '偏关县',\n      140981: '原平市'\n    },\n    141000: {\n      141002: '尧都区',\n      141021: '曲沃县',\n      141022: '翼城县',\n      141023: '襄汾县',\n      141024: '洪洞县',\n      141025: '古县',\n      141026: '安泽县',\n      141027: '浮山县',\n      141028: '吉县',\n      141029: '乡宁县',\n      141030: '大宁县',\n      141031: '隰县',\n      141032: '永和县',\n      141033: '蒲县',\n      141034: '汾西县',\n      141081: '侯马市',\n      141082: '霍州市'\n    },\n    141100: {\n      141102: '离石区',\n      141121: '文水县',\n      141122: '交城县',\n      141123: '兴县',\n      141124: '临县',\n      141125: '柳林县',\n      141126: '石楼县',\n      141127: '岚县',\n      141128: '方山县',\n      141129: '中阳县',\n      141130: '交口县',\n      141181: '孝义市',\n      141182: '汾阳市'\n    },\n    150000: {\n      150100: '呼和浩特市',\n      150200: '包头市',\n      150300: '乌海市',\n      150400: '赤峰市',\n      150500: '通辽市',\n      150600: '鄂尔多斯市',\n      150700: '呼伦贝尔市',\n      150800: '巴彦淖尔市',\n      150900: '乌兰察布市',\n      152200: '兴安盟',\n      152500: '锡林郭勒盟',\n      152900: '阿拉善盟'\n    },\n    150100: {\n      150102: '新城区',\n      150103: '回民区',\n      150104: '玉泉区',\n      150105: '赛罕区',\n      150121: '土默特左旗',\n      150122: '托克托县',\n      150123: '和林格尔县',\n      150124: '清水河县',\n      150125: '武川县'\n    },\n    150200: {\n      150202: '东河区',\n      150203: '昆都仑区',\n      150204: '青山区',\n      150205: '石拐区',\n      150206: '白云鄂博矿区',\n      150207: '九原区',\n      150221: '土默特右旗',\n      150222: '固阳县',\n      150223: '达尔罕茂明安联合旗'\n    },\n    150300: {\n      150302: '海勃湾区',\n      150303: '海南区',\n      150304: '乌达区'\n    },\n    150400: {\n      150402: '红山区',\n      150403: '元宝山区',\n      150404: '松山区',\n      150421: '阿鲁科尔沁旗',\n      150422: '巴林左旗',\n      150423: '巴林右旗',\n      150424: '林西县',\n      150425: '克什克腾旗',\n      150426: '翁牛特旗',\n      150428: '喀喇沁旗',\n      150429: '宁城县',\n      150430: '敖汉旗'\n    },\n    150500: {\n      150502: '科尔沁区',\n      150521: '科尔沁左翼中旗',\n      150522: '科尔沁左翼后旗',\n      150523: '开鲁县',\n      150524: '库伦旗',\n      150525: '奈曼旗',\n      150526: '扎鲁特旗',\n      150581: '霍林郭勒市'\n    },\n    150600: {\n      150602: '东胜区',\n      150621: '达拉特旗',\n      150622: '准格尔旗',\n      150623: '鄂托克前旗',\n      150624: '鄂托克旗',\n      150625: '杭锦旗',\n      150626: '乌审旗',\n      150627: '伊金霍洛旗'\n    },\n    150700: {\n      150702: '海拉尔区',\n      150703: '扎赉诺尔区',\n      150721: '阿荣旗',\n      150722: '莫力达瓦达斡尔族自治旗',\n      150723: '鄂伦春自治旗',\n      150724: '鄂温克族自治旗',\n      150725: '陈巴尔虎旗',\n      150726: '新巴尔虎左旗',\n      150727: '新巴尔虎右旗',\n      150781: '满洲里市',\n      150782: '牙克石市',\n      150783: '扎兰屯市',\n      150784: '额尔古纳市',\n      150785: '根河市'\n    },\n    150800: {\n      150802: '临河区',\n      150821: '五原县',\n      150822: '磴口县',\n      150823: '乌拉特前旗',\n      150824: '乌拉特中旗',\n      150825: '乌拉特后旗',\n      150826: '杭锦后旗'\n    },\n    150900: {\n      150902: '集宁区',\n      150921: '卓资县',\n      150922: '化德县',\n      150923: '商都县',\n      150924: '兴和县',\n      150925: '凉城县',\n      150926: '察哈尔右翼前旗',\n      150927: '察哈尔右翼中旗',\n      150928: '察哈尔右翼后旗',\n      150929: '四子王旗',\n      150981: '丰镇市'\n    },\n    152200: {\n      152201: '乌兰浩特市',\n      152202: '阿尔山市',\n      152221: '科尔沁右翼前旗',\n      152222: '科尔沁右翼中旗',\n      152223: '扎赉特旗',\n      152224: '突泉县'\n    },\n    152500: {\n      152501: '二连浩特市',\n      152502: '锡林浩特市',\n      152522: '阿巴嘎旗',\n      152523: '苏尼特左旗',\n      152524: '苏尼特右旗',\n      152525: '东乌珠穆沁旗',\n      152526: '西乌珠穆沁旗',\n      152527: '太仆寺旗',\n      152528: '镶黄旗',\n      152529: '正镶白旗',\n      152530: '正蓝旗',\n      152531: '多伦县'\n    },\n    152900: {\n      152921: '阿拉善左旗',\n      152922: '阿拉善右旗',\n      152923: '额济纳旗'\n    },\n    210000: {\n      210100: '沈阳市',\n      210200: '大连市',\n      210300: '鞍山市',\n      210400: '抚顺市',\n      210500: '本溪市',\n      210600: '丹东市',\n      210700: '锦州市',\n      210800: '营口市',\n      210900: '阜新市',\n      211000: '辽阳市',\n      211100: '盘锦市',\n      211200: '铁岭市',\n      211300: '朝阳市',\n      211400: '葫芦岛市'\n    },\n    210100: {\n      210102: '和平区',\n      210103: '沈河区',\n      210104: '大东区',\n      210105: '皇姑区',\n      210106: '铁西区',\n      210111: '苏家屯区',\n      210112: '浑南区',\n      210113: '沈北新区',\n      210114: '于洪区',\n      210122: '辽中县',\n      210123: '康平县',\n      210124: '法库县',\n      210181: '新民市'\n    },\n    210200: {\n      210202: '中山区',\n      210203: '西岗区',\n      210204: '沙河口区',\n      210211: '甘井子区',\n      210212: '旅顺口区',\n      210213: '金州区',\n      210214: '普兰店区',\n      210224: '长海县',\n      210281: '瓦房店市',\n      210283: '庄河市'\n    },\n    210300: {\n      210302: '铁东区',\n      210303: '铁西区',\n      210304: '立山区',\n      210311: '千山区',\n      210321: '台安县',\n      210323: '岫岩满族自治县',\n      210381: '海城市'\n    },\n    210400: {\n      210402: '新抚区',\n      210403: '东洲区',\n      210404: '望花区',\n      210411: '顺城区',\n      210421: '抚顺县',\n      210422: '新宾满族自治县',\n      210423: '清原满族自治县'\n    },\n    210500: {\n      210502: '平山区',\n      210503: '溪湖区',\n      210504: '明山区',\n      210505: '南芬区',\n      210521: '本溪满族自治县',\n      210522: '桓仁满族自治县'\n    },\n    210600: {\n      210602: '元宝区',\n      210603: '振兴区',\n      210604: '振安区',\n      210624: '宽甸满族自治县',\n      210681: '东港市',\n      210682: '凤城市'\n    },\n    210700: {\n      210702: '古塔区',\n      210703: '凌河区',\n      210711: '太和区',\n      210726: '黑山县',\n      210727: '义县',\n      210781: '凌海市',\n      210782: '北镇市'\n    },\n    210800: {\n      210802: '站前区',\n      210803: '西市区',\n      210804: '鲅鱼圈区',\n      210811: '老边区',\n      210881: '盖州市',\n      210882: '大石桥市'\n    },\n    210900: {\n      210902: '海州区',\n      210903: '新邱区',\n      210904: '太平区',\n      210905: '清河门区',\n      210911: '细河区',\n      210921: '阜新蒙古族自治县',\n      210922: '彰武县'\n    },\n    211000: {\n      211002: '白塔区',\n      211003: '文圣区',\n      211004: '宏伟区',\n      211005: '弓长岭区',\n      211011: '太子河区',\n      211021: '辽阳县',\n      211081: '灯塔市'\n    },\n    211100: {\n      211102: '双台子区',\n      211103: '兴隆台区',\n      211121: '大洼县',\n      211122: '盘山县'\n    },\n    211200: {\n      211202: '银州区',\n      211204: '清河区',\n      211221: '铁岭县',\n      211223: '西丰县',\n      211224: '昌图县',\n      211281: '调兵山市',\n      211282: '开原市'\n    },\n    211300: {\n      211302: '双塔区',\n      211303: '龙城区',\n      211321: '朝阳县',\n      211322: '建平县',\n      211324: '喀喇沁左翼蒙古族自治县',\n      211381: '北票市',\n      211382: '凌源市'\n    },\n    211400: {\n      211402: '连山区',\n      211403: '龙港区',\n      211404: '南票区',\n      211421: '绥中县',\n      211422: '建昌县',\n      211481: '兴城市'\n    },\n    220000: {\n      220100: '长春市',\n      220200: '吉林市',\n      220300: '四平市',\n      220400: '辽源市',\n      220500: '通化市',\n      220600: '白山市',\n      220700: '松原市',\n      220800: '白城市',\n      222400: '延边朝鲜族自治州'\n    },\n    220100: {\n      220102: '南关区',\n      220103: '宽城区',\n      220104: '朝阳区',\n      220105: '二道区',\n      220106: '绿园区',\n      220112: '双阳区',\n      220113: '九台区',\n      220122: '农安县',\n      220182: '榆树市',\n      220183: '德惠市'\n    },\n    220200: {\n      220202: '昌邑区',\n      220203: '龙潭区',\n      220204: '船营区',\n      220211: '丰满区',\n      220221: '永吉县',\n      220281: '蛟河市',\n      220282: '桦甸市',\n      220283: '舒兰市',\n      220284: '磐石市'\n    },\n    220300: {\n      220302: '铁西区',\n      220303: '铁东区',\n      220322: '梨树县',\n      220323: '伊通满族自治县',\n      220381: '公主岭市',\n      220382: '双辽市'\n    },\n    220400: {\n      220402: '龙山区',\n      220403: '西安区',\n      220421: '东丰县',\n      220422: '东辽县'\n    },\n    220500: {\n      220502: '东昌区',\n      220503: '二道江区',\n      220521: '通化县',\n      220523: '辉南县',\n      220524: '柳河县',\n      220581: '梅河口市',\n      220582: '集安市'\n    },\n    220600: {\n      220602: '浑江区',\n      220605: '江源区',\n      220621: '抚松县',\n      220622: '靖宇县',\n      220623: '长白朝鲜族自治县',\n      220681: '临江市'\n    },\n    220700: {\n      220702: '宁江区',\n      220721: '前郭尔罗斯蒙古族自治县',\n      220722: '长岭县',\n      220723: '乾安县',\n      220781: '扶余市'\n    },\n    220800: {\n      220802: '洮北区',\n      220821: '镇赉县',\n      220822: '通榆县',\n      220881: '洮南市',\n      220882: '大安市'\n    },\n    222400: {\n      222401: '延吉市',\n      222402: '图们市',\n      222403: '敦化市',\n      222404: '珲春市',\n      222405: '龙井市',\n      222406: '和龙市',\n      222424: '汪清县',\n      222426: '安图县'\n    },\n    230000: {\n      230100: '哈尔滨市',\n      230200: '齐齐哈尔市',\n      230300: '鸡西市',\n      230400: '鹤岗市',\n      230500: '双鸭山市',\n      230600: '大庆市',\n      230700: '伊春市',\n      230800: '佳木斯市',\n      230900: '七台河市',\n      231000: '牡丹江市',\n      231100: '黑河市',\n      231200: '绥化市',\n      232700: '大兴安岭地区'\n    },\n    230100: {\n      230102: '道里区',\n      230103: '南岗区',\n      230104: '道外区',\n      230108: '平房区',\n      230109: '松北区',\n      230110: '香坊区',\n      230111: '呼兰区',\n      230112: '阿城区',\n      230113: '双城区',\n      230123: '依兰县',\n      230124: '方正县',\n      230125: '宾县',\n      230126: '巴彦县',\n      230127: '木兰县',\n      230128: '通河县',\n      230129: '延寿县',\n      230183: '尚志市',\n      230184: '五常市'\n    },\n    230200: {\n      230202: '龙沙区',\n      230203: '建华区',\n      230204: '铁锋区',\n      230205: '昂昂溪区',\n      230206: '富拉尔基区',\n      230207: '碾子山区',\n      230208: '梅里斯达斡尔族区',\n      230221: '龙江县',\n      230223: '依安县',\n      230224: '泰来县',\n      230225: '甘南县',\n      230227: '富裕县',\n      230229: '克山县',\n      230230: '克东县',\n      230231: '拜泉县',\n      230281: '讷河市'\n    },\n    230300: {\n      230302: '鸡冠区',\n      230303: '恒山区',\n      230304: '滴道区',\n      230305: '梨树区',\n      230306: '城子河区',\n      230307: '麻山区',\n      230321: '鸡东县',\n      230381: '虎林市',\n      230382: '密山市'\n    },\n    230400: {\n      230402: '向阳区',\n      230403: '工农区',\n      230404: '南山区',\n      230405: '兴安区',\n      230406: '东山区',\n      230407: '兴山区',\n      230421: '萝北县',\n      230422: '绥滨县'\n    },\n    230500: {\n      230502: '尖山区',\n      230503: '岭东区',\n      230505: '四方台区',\n      230506: '宝山区',\n      230521: '集贤县',\n      230522: '友谊县',\n      230523: '宝清县',\n      230524: '饶河县'\n    },\n    230600: {\n      230602: '萨尔图区',\n      230603: '龙凤区',\n      230604: '让胡路区',\n      230605: '红岗区',\n      230606: '大同区',\n      230621: '肇州县',\n      230622: '肇源县',\n      230623: '林甸县',\n      230624: '杜尔伯特蒙古族自治县'\n    },\n    230700: {\n      230702: '伊春区',\n      230703: '南岔区',\n      230704: '友好区',\n      230705: '西林区',\n      230706: '翠峦区',\n      230707: '新青区',\n      230708: '美溪区',\n      230709: '金山屯区',\n      230710: '五营区',\n      230711: '乌马河区',\n      230712: '汤旺河区',\n      230713: '带岭区',\n      230714: '乌伊岭区',\n      230715: '红星区',\n      230716: '上甘岭区',\n      230722: '嘉荫县',\n      230781: '铁力市'\n    },\n    230800: {\n      230803: '向阳区',\n      230804: '前进区',\n      230805: '东风区',\n      230811: '郊区',\n      230822: '桦南县',\n      230826: '桦川县',\n      230828: '汤原县',\n      230833: '抚远市',\n      230881: '同江市',\n      230882: '富锦市'\n    },\n    230900: {\n      230902: '新兴区',\n      230903: '桃山区',\n      230904: '茄子河区',\n      230921: '勃利县'\n    },\n    231000: {\n      231002: '东安区',\n      231003: '阳明区',\n      231004: '爱民区',\n      231005: '西安区',\n      231025: '林口县',\n      231081: '绥芬河市',\n      231083: '海林市',\n      231084: '宁安市',\n      231085: '穆棱市',\n      231086: '东宁市'\n    },\n    231100: {\n      231102: '爱辉区',\n      231121: '嫩江县',\n      231123: '逊克县',\n      231124: '孙吴县',\n      231181: '北安市',\n      231182: '五大连池市'\n    },\n    231200: {\n      231202: '北林区',\n      231221: '望奎县',\n      231222: '兰西县',\n      231223: '青冈县',\n      231224: '庆安县',\n      231225: '明水县',\n      231226: '绥棱县',\n      231281: '安达市',\n      231282: '肇东市',\n      231283: '海伦市'\n    },\n    232700: {\n      232701: '加格达奇区',\n      232721: '呼玛县',\n      232722: '塔河县',\n      232723: '漠河县'\n    },\n    310000: {\n      310100: '上海市市辖区',\n      310200: '上海市郊县'\n    },\n    310100: {\n      310101: '黄浦区',\n      310104: '徐汇区',\n      310105: '长宁区',\n      310106: '静安区',\n      310107: '普陀区',\n      310109: '虹口区',\n      310110: '杨浦区',\n      310112: '闵行区',\n      310113: '宝山区',\n      310114: '嘉定区',\n      310115: '浦东新区',\n      310116: '金山区',\n      310117: '松江区',\n      310118: '青浦区',\n      310120: '奉贤区',\n      310230: '崇明县'\n    },\n    320000: {\n      320100: '南京市',\n      320200: '无锡市',\n      320300: '徐州市',\n      320400: '常州市',\n      320500: '苏州市',\n      320600: '南通市',\n      320700: '连云港市',\n      320800: '淮安市',\n      320900: '盐城市',\n      321000: '扬州市',\n      321100: '镇江市',\n      321200: '泰州市',\n      321300: '宿迁市'\n    },\n    320100: {\n      320102: '玄武区',\n      320104: '秦淮区',\n      320105: '建邺区',\n      320106: '鼓楼区',\n      320111: '浦口区',\n      320113: '栖霞区',\n      320114: '雨花台区',\n      320115: '江宁区',\n      320116: '六合区',\n      320117: '溧水区',\n      320118: '高淳区'\n    },\n    320200: {\n      320205: '锡山区',\n      320206: '惠山区',\n      320211: '滨湖区',\n      320213: '梁溪区',\n      320214: '新吴区',\n      320281: '江阴市',\n      320282: '宜兴市'\n    },\n    320300: {\n      320302: '鼓楼区',\n      320303: '云龙区',\n      320305: '贾汪区',\n      320311: '泉山区',\n      320312: '铜山区',\n      320321: '丰县',\n      320322: '沛县',\n      320324: '睢宁县',\n      320381: '新沂市',\n      320382: '邳州市'\n    },\n    320400: {\n      320402: '天宁区',\n      320404: '钟楼区',\n      320411: '新北区',\n      320412: '武进区',\n      320413: '金坛区',\n      320481: '溧阳市'\n    },\n    320500: {\n      320505: '虎丘区',\n      320506: '吴中区',\n      320507: '相城区',\n      320508: '姑苏区',\n      320509: '吴江区',\n      320581: '常熟市',\n      320582: '张家港市',\n      320583: '昆山市',\n      320585: '太仓市'\n    },\n    320600: {\n      320602: '崇川区',\n      320611: '港闸区',\n      320612: '通州区',\n      320621: '海安县',\n      320623: '如东县',\n      320681: '启东市',\n      320682: '如皋市',\n      320684: '海门市'\n    },\n    320700: {\n      320703: '连云区',\n      320706: '海州区',\n      320707: '赣榆区',\n      320722: '东海县',\n      320723: '灌云县',\n      320724: '灌南县'\n    },\n    320800: {\n      320802: '清河区',\n      320803: '淮安区',\n      320804: '淮阴区',\n      320811: '清浦区',\n      320826: '涟水县',\n      320829: '洪泽县',\n      320830: '盱眙县',\n      320831: '金湖县'\n    },\n    320900: {\n      320902: '亭湖区',\n      320903: '盐都区',\n      320904: '大丰区',\n      320921: '响水县',\n      320922: '滨海县',\n      320923: '阜宁县',\n      320924: '射阳县',\n      320925: '建湖县',\n      320981: '东台市'\n    },\n    321000: {\n      321002: '广陵区',\n      321003: '邗江区',\n      321012: '江都区',\n      321023: '宝应县',\n      321081: '仪征市',\n      321084: '高邮市'\n    },\n    321100: {\n      321102: '京口区',\n      321111: '润州区',\n      321112: '丹徒区',\n      321181: '丹阳市',\n      321182: '扬中市',\n      321183: '句容市'\n    },\n    321200: {\n      321202: '海陵区',\n      321203: '高港区',\n      321204: '姜堰区',\n      321281: '兴化市',\n      321282: '靖江市',\n      321283: '泰兴市'\n    },\n    321300: {\n      321302: '宿城区',\n      321311: '宿豫区',\n      321322: '沭阳县',\n      321323: '泗阳县',\n      321324: '泗洪县'\n    },\n    330000: {\n      330100: '杭州市',\n      330200: '宁波市',\n      330300: '温州市',\n      330400: '嘉兴市',\n      330500: '湖州市',\n      330600: '绍兴市',\n      330700: '金华市',\n      330800: '衢州市',\n      330900: '舟山市',\n      331000: '台州市',\n      331100: '丽水市'\n    },\n    330100: {\n      330102: '上城区',\n      330103: '下城区',\n      330104: '江干区',\n      330105: '拱墅区',\n      330106: '西湖区',\n      330108: '滨江区',\n      330109: '萧山区',\n      330110: '余杭区',\n      330111: '富阳区',\n      330122: '桐庐县',\n      330127: '淳安县',\n      330182: '建德市',\n      330185: '临安市'\n    },\n    330200: {\n      330203: '海曙区',\n      330204: '江东区',\n      330205: '江北区',\n      330206: '北仑区',\n      330211: '镇海区',\n      330212: '鄞州区',\n      330225: '象山县',\n      330226: '宁海县',\n      330281: '余姚市',\n      330282: '慈溪市',\n      330283: '奉化市'\n    },\n    330300: {\n      330302: '鹿城区',\n      330303: '龙湾区',\n      330304: '瓯海区',\n      330305: '洞头区',\n      330324: '永嘉县',\n      330326: '平阳县',\n      330327: '苍南县',\n      330328: '文成县',\n      330329: '泰顺县',\n      330381: '瑞安市',\n      330382: '乐清市'\n    },\n    330400: {\n      330402: '南湖区',\n      330411: '秀洲区',\n      330421: '嘉善县',\n      330424: '海盐县',\n      330481: '海宁市',\n      330482: '平湖市',\n      330483: '桐乡市'\n    },\n    330500: {\n      330502: '吴兴区',\n      330503: '南浔区',\n      330521: '德清县',\n      330522: '长兴县',\n      330523: '安吉县'\n    },\n    330600: {\n      330602: '越城区',\n      330603: '柯桥区',\n      330604: '上虞区',\n      330624: '新昌县',\n      330681: '诸暨市',\n      330683: '嵊州市'\n    },\n    330700: {\n      330702: '婺城区',\n      330703: '金东区',\n      330723: '武义县',\n      330726: '浦江县',\n      330727: '磐安县',\n      330781: '兰溪市',\n      330782: '义乌市',\n      330783: '东阳市',\n      330784: '永康市'\n    },\n    330800: {\n      330802: '柯城区',\n      330803: '衢江区',\n      330822: '常山县',\n      330824: '开化县',\n      330825: '龙游县',\n      330881: '江山市'\n    },\n    330900: {\n      330902: '定海区',\n      330903: '普陀区',\n      330921: '岱山县',\n      330922: '嵊泗县'\n    },\n    331000: {\n      331002: '椒江区',\n      331003: '黄岩区',\n      331004: '路桥区',\n      331021: '玉环县',\n      331022: '三门县',\n      331023: '天台县',\n      331024: '仙居县',\n      331081: '温岭市',\n      331082: '临海市'\n    },\n    331100: {\n      331102: '莲都区',\n      331121: '青田县',\n      331122: '缙云县',\n      331123: '遂昌县',\n      331124: '松阳县',\n      331125: '云和县',\n      331126: '庆元县',\n      331127: '景宁畲族自治县',\n      331181: '龙泉市'\n    },\n    340000: {\n      340100: '合肥市',\n      340200: '芜湖市',\n      340300: '蚌埠市',\n      340400: '淮南市',\n      340500: '马鞍山市',\n      340600: '淮北市',\n      340700: '铜陵市',\n      340800: '安庆市',\n      341000: '黄山市',\n      341100: '滁州市',\n      341200: '阜阳市',\n      341300: '宿州市',\n      341500: '六安市',\n      341600: '亳州市',\n      341700: '池州市',\n      341800: '宣城市'\n    },\n    340100: {\n      340102: '瑶海区',\n      340103: '庐阳区',\n      340104: '蜀山区',\n      340111: '包河区',\n      340121: '长丰县',\n      340122: '肥东县',\n      340123: '肥西县',\n      340124: '庐江县',\n      340181: '巢湖市'\n    },\n    340200: {\n      340202: '镜湖区',\n      340203: '弋江区',\n      340207: '鸠江区',\n      340208: '三山区',\n      340221: '芜湖县',\n      340222: '繁昌县',\n      340223: '南陵县',\n      340225: '无为县'\n    },\n    340300: {\n      340302: '龙子湖区',\n      340303: '蚌山区',\n      340304: '禹会区',\n      340311: '淮上区',\n      340321: '怀远县',\n      340322: '五河县',\n      340323: '固镇县'\n    },\n    340400: {\n      340402: '大通区',\n      340403: '田家庵区',\n      340404: '谢家集区',\n      340405: '八公山区',\n      340406: '潘集区',\n      340421: '凤台县',\n      340422: '寿县'\n    },\n    340500: {\n      340503: '花山区',\n      340504: '雨山区',\n      340506: '博望区',\n      340521: '当涂县',\n      340522: '含山县',\n      340523: '和县'\n    },\n    340600: {\n      340602: '杜集区',\n      340603: '相山区',\n      340604: '烈山区',\n      340621: '濉溪县'\n    },\n    340700: {\n      340705: '铜官区',\n      340706: '义安区',\n      340711: '郊区',\n      340722: '枞阳县'\n    },\n    340800: {\n      340802: '迎江区',\n      340803: '大观区',\n      340811: '宜秀区',\n      340822: '怀宁县',\n      340824: '潜山县',\n      340825: '太湖县',\n      340826: '宿松县',\n      340827: '望江县',\n      340828: '岳西县',\n      340881: '桐城市'\n    },\n    341000: {\n      341002: '屯溪区',\n      341003: '黄山区',\n      341004: '徽州区',\n      341021: '歙县',\n      341022: '休宁县',\n      341023: '黟县',\n      341024: '祁门县'\n    },\n    341100: {\n      341102: '琅琊区',\n      341103: '南谯区',\n      341122: '来安县',\n      341124: '全椒县',\n      341125: '定远县',\n      341126: '凤阳县',\n      341181: '天长市',\n      341182: '明光市'\n    },\n    341200: {\n      341202: '颍州区',\n      341203: '颍东区',\n      341204: '颍泉区',\n      341221: '临泉县',\n      341222: '太和县',\n      341225: '阜南县',\n      341226: '颍上县',\n      341282: '界首市'\n    },\n    341300: {\n      341302: '埇桥区',\n      341321: '砀山县',\n      341322: '萧县',\n      341323: '灵璧县',\n      341324: '泗县'\n    },\n    341500: {\n      341502: '金安区',\n      341503: '裕安区',\n      341504: '叶集区',\n      341522: '霍邱县',\n      341523: '舒城县',\n      341524: '金寨县',\n      341525: '霍山县'\n    },\n    341600: {\n      341602: '谯城区',\n      341621: '涡阳县',\n      341622: '蒙城县',\n      341623: '利辛县'\n    },\n    341700: {\n      341702: '贵池区',\n      341721: '东至县',\n      341722: '石台县',\n      341723: '青阳县'\n    },\n    341800: {\n      341802: '宣州区',\n      341821: '郎溪县',\n      341822: '广德县',\n      341823: '泾县',\n      341824: '绩溪县',\n      341825: '旌德县',\n      341881: '宁国市'\n    },\n    350000: {\n      350100: '福州市',\n      350200: '厦门市',\n      350300: '莆田市',\n      350400: '三明市',\n      350500: '泉州市',\n      350600: '漳州市',\n      350700: '南平市',\n      350800: '龙岩市',\n      350900: '宁德市'\n    },\n    350100: {\n      350102: '鼓楼区',\n      350103: '台江区',\n      350104: '仓山区',\n      350105: '马尾区',\n      350111: '晋安区',\n      350121: '闽侯县',\n      350122: '连江县',\n      350123: '罗源县',\n      350124: '闽清县',\n      350125: '永泰县',\n      350128: '平潭县',\n      350181: '福清市',\n      350182: '长乐市'\n    },\n    350200: {\n      350203: '思明区',\n      350205: '海沧区',\n      350206: '湖里区',\n      350211: '集美区',\n      350212: '同安区',\n      350213: '翔安区'\n    },\n    350300: {\n      350302: '城厢区',\n      350303: '涵江区',\n      350304: '荔城区',\n      350305: '秀屿区',\n      350322: '仙游县'\n    },\n    350400: {\n      350402: '梅列区',\n      350403: '三元区',\n      350421: '明溪县',\n      350423: '清流县',\n      350424: '宁化县',\n      350425: '大田县',\n      350426: '尤溪县',\n      350427: '沙县',\n      350428: '将乐县',\n      350429: '泰宁县',\n      350430: '建宁县',\n      350481: '永安市'\n    },\n    350500: {\n      350502: '鲤城区',\n      350503: '丰泽区',\n      350504: '洛江区',\n      350505: '泉港区',\n      350521: '惠安县',\n      350524: '安溪县',\n      350525: '永春县',\n      350526: '德化县',\n      350527: '金门县',\n      350581: '石狮市',\n      350582: '晋江市',\n      350583: '南安市'\n    },\n    350600: {\n      350602: '芗城区',\n      350603: '龙文区',\n      350622: '云霄县',\n      350623: '漳浦县',\n      350624: '诏安县',\n      350625: '长泰县',\n      350626: '东山县',\n      350627: '南靖县',\n      350628: '平和县',\n      350629: '华安县',\n      350681: '龙海市'\n    },\n    350700: {\n      350702: '延平区',\n      350703: '建阳区',\n      350721: '顺昌县',\n      350722: '浦城县',\n      350723: '光泽县',\n      350724: '松溪县',\n      350725: '政和县',\n      350781: '邵武市',\n      350782: '武夷山市',\n      350783: '建瓯市'\n    },\n    350800: {\n      350802: '新罗区',\n      350803: '永定区',\n      350821: '长汀县',\n      350823: '上杭县',\n      350824: '武平县',\n      350825: '连城县',\n      350881: '漳平市'\n    },\n    350900: {\n      350902: '蕉城区',\n      350921: '霞浦县',\n      350922: '古田县',\n      350923: '屏南县',\n      350924: '寿宁县',\n      350925: '周宁县',\n      350926: '柘荣县',\n      350981: '福安市',\n      350982: '福鼎市'\n    },\n    360000: {\n      360100: '南昌市',\n      360200: '景德镇市',\n      360300: '萍乡市',\n      360400: '九江市',\n      360500: '新余市',\n      360600: '鹰潭市',\n      360700: '赣州市',\n      360800: '吉安市',\n      360900: '宜春市',\n      361000: '抚州市',\n      361100: '上饶市'\n    },\n    360100: {\n      360102: '东湖区',\n      360103: '西湖区',\n      360104: '青云谱区',\n      360105: '湾里区',\n      360111: '青山湖区',\n      360112: '新建区',\n      360121: '南昌县',\n      360123: '安义县',\n      360124: '进贤县'\n    },\n    360200: {\n      360202: '昌江区',\n      360203: '珠山区',\n      360222: '浮梁县',\n      360281: '乐平市'\n    },\n    360300: {\n      360302: '安源区',\n      360313: '湘东区',\n      360321: '莲花县',\n      360322: '上栗县',\n      360323: '芦溪县'\n    },\n    360400: {\n      360402: '庐山区',\n      360403: '浔阳区',\n      360421: '九江县',\n      360423: '武宁县',\n      360424: '修水县',\n      360425: '永修县',\n      360426: '德安县',\n      360427: '星子县',\n      360428: '都昌县',\n      360429: '湖口县',\n      360430: '彭泽县',\n      360481: '瑞昌市',\n      360482: '共青城市'\n    },\n    360500: {\n      360502: '渝水区',\n      360521: '分宜县'\n    },\n    360600: {\n      360602: '月湖区',\n      360622: '余江县',\n      360681: '贵溪市'\n    },\n    360700: {\n      360702: '章贡区',\n      360703: '南康区',\n      360721: '赣县',\n      360722: '信丰县',\n      360723: '大余县',\n      360724: '上犹县',\n      360725: '崇义县',\n      360726: '安远县',\n      360727: '龙南县',\n      360728: '定南县',\n      360729: '全南县',\n      360730: '宁都县',\n      360731: '于都县',\n      360732: '兴国县',\n      360733: '会昌县',\n      360734: '寻乌县',\n      360735: '石城县',\n      360781: '瑞金市'\n    },\n    360800: {\n      360802: '吉州区',\n      360803: '青原区',\n      360821: '吉安县',\n      360822: '吉水县',\n      360823: '峡江县',\n      360824: '新干县',\n      360825: '永丰县',\n      360826: '泰和县',\n      360827: '遂川县',\n      360828: '万安县',\n      360829: '安福县',\n      360830: '永新县',\n      360881: '井冈山市'\n    },\n    360900: {\n      360902: '袁州区',\n      360921: '奉新县',\n      360922: '万载县',\n      360923: '上高县',\n      360924: '宜丰县',\n      360925: '靖安县',\n      360926: '铜鼓县',\n      360981: '丰城市',\n      360982: '樟树市',\n      360983: '高安市'\n    },\n    361000: {\n      361002: '临川区',\n      361021: '南城县',\n      361022: '黎川县',\n      361023: '南丰县',\n      361024: '崇仁县',\n      361025: '乐安县',\n      361026: '宜黄县',\n      361027: '金溪县',\n      361028: '资溪县',\n      361029: '东乡县',\n      361030: '广昌县'\n    },\n    361100: {\n      361102: '信州区',\n      361103: '广丰区',\n      361121: '上饶县',\n      361123: '玉山县',\n      361124: '铅山县',\n      361125: '横峰县',\n      361126: '弋阳县',\n      361127: '余干县',\n      361128: '鄱阳县',\n      361129: '万年县',\n      361130: '婺源县',\n      361181: '德兴市'\n    },\n    370000: {\n      370100: '济南市',\n      370200: '青岛市',\n      370300: '淄博市',\n      370400: '枣庄市',\n      370500: '东营市',\n      370600: '烟台市',\n      370700: '潍坊市',\n      370800: '济宁市',\n      370900: '泰安市',\n      371000: '威海市',\n      371100: '日照市',\n      371200: '莱芜市',\n      371300: '临沂市',\n      371400: '德州市',\n      371500: '聊城市',\n      371600: '滨州市',\n      371700: '菏泽市'\n    },\n    370100: {\n      370102: '历下区',\n      370103: '市中区',\n      370104: '槐荫区',\n      370105: '天桥区',\n      370112: '历城区',\n      370113: '长清区',\n      370124: '平阴县',\n      370125: '济阳县',\n      370126: '商河县',\n      370181: '章丘市'\n    },\n    370200: {\n      370202: '市南区',\n      370203: '市北区',\n      370211: '黄岛区',\n      370212: '崂山区',\n      370213: '李沧区',\n      370214: '城阳区',\n      370281: '胶州市',\n      370282: '即墨市',\n      370283: '平度市',\n      370285: '莱西市'\n    },\n    370300: {\n      370302: '淄川区',\n      370303: '张店区',\n      370304: '博山区',\n      370305: '临淄区',\n      370306: '周村区',\n      370321: '桓台县',\n      370322: '高青县',\n      370323: '沂源县'\n    },\n    370400: {\n      370402: '市中区',\n      370403: '薛城区',\n      370404: '峄城区',\n      370405: '台儿庄区',\n      370406: '山亭区',\n      370481: '滕州市'\n    },\n    370500: {\n      370502: '东营区',\n      370503: '河口区',\n      370521: '垦利县',\n      370522: '利津县',\n      370523: '广饶县'\n    },\n    370600: {\n      370602: '芝罘区',\n      370611: '福山区',\n      370612: '牟平区',\n      370613: '莱山区',\n      370634: '长岛县',\n      370681: '龙口市',\n      370682: '莱阳市',\n      370683: '莱州市',\n      370684: '蓬莱市',\n      370685: '招远市',\n      370686: '栖霞市',\n      370687: '海阳市'\n    },\n    370700: {\n      370702: '潍城区',\n      370703: '寒亭区',\n      370704: '坊子区',\n      370705: '奎文区',\n      370724: '临朐县',\n      370725: '昌乐县',\n      370781: '青州市',\n      370782: '诸城市',\n      370783: '寿光市',\n      370784: '安丘市',\n      370785: '高密市',\n      370786: '昌邑市'\n    },\n    370800: {\n      370811: '任城区',\n      370812: '兖州区',\n      370826: '微山县',\n      370827: '鱼台县',\n      370828: '金乡县',\n      370829: '嘉祥县',\n      370830: '汶上县',\n      370831: '泗水县',\n      370832: '梁山县',\n      370881: '曲阜市',\n      370883: '邹城市'\n    },\n    370900: {\n      370902: '泰山区',\n      370911: '岱岳区',\n      370921: '宁阳县',\n      370923: '东平县',\n      370982: '新泰市',\n      370983: '肥城市'\n    },\n    371000: {\n      371002: '环翠区',\n      371003: '文登区',\n      371082: '荣成市',\n      371083: '乳山市'\n    },\n    371100: {\n      371102: '东港区',\n      371103: '岚山区',\n      371121: '五莲县',\n      371122: '莒县'\n    },\n    371200: {\n      371202: '莱城区',\n      371203: '钢城区'\n    },\n    371300: {\n      371302: '兰山区',\n      371311: '罗庄区',\n      371312: '河东区',\n      371321: '沂南县',\n      371322: '郯城县',\n      371323: '沂水县',\n      371324: '兰陵县',\n      371325: '费县',\n      371326: '平邑县',\n      371327: '莒南县',\n      371328: '蒙阴县',\n      371329: '临沭县'\n    },\n    371400: {\n      371402: '德城区',\n      371403: '陵城区',\n      371422: '宁津县',\n      371423: '庆云县',\n      371424: '临邑县',\n      371425: '齐河县',\n      371426: '平原县',\n      371427: '夏津县',\n      371428: '武城县',\n      371481: '乐陵市',\n      371482: '禹城市'\n    },\n    371500: {\n      371502: '东昌府区',\n      371521: '阳谷县',\n      371522: '莘县',\n      371523: '茌平县',\n      371524: '东阿县',\n      371525: '冠县',\n      371526: '高唐县',\n      371581: '临清市'\n    },\n    371600: {\n      371602: '滨城区',\n      371603: '沾化区',\n      371621: '惠民县',\n      371622: '阳信县',\n      371623: '无棣县',\n      371625: '博兴县',\n      371626: '邹平县'\n    },\n    371700: {\n      371702: '牡丹区',\n      371721: '曹县',\n      371722: '单县',\n      371723: '成武县',\n      371724: '巨野县',\n      371725: '郓城县',\n      371726: '鄄城县',\n      371727: '定陶县',\n      371728: '东明县'\n    },\n    410000: {\n      410100: '郑州市',\n      410200: '开封市',\n      410300: '洛阳市',\n      410400: '平顶山市',\n      410500: '安阳市',\n      410600: '鹤壁市',\n      410700: '新乡市',\n      410800: '焦作市',\n      410900: '濮阳市',\n      411000: '许昌市',\n      411100: '漯河市',\n      411200: '三门峡市',\n      411300: '南阳市',\n      411400: '商丘市',\n      411500: '信阳市',\n      411600: '周口市',\n      411700: '驻马店市',\n      419001: '济源市'\n    },\n    410100: {\n      410102: '中原区',\n      410103: '二七区',\n      410104: '管城回族区',\n      410105: '金水区',\n      410106: '上街区',\n      410108: '惠济区',\n      410122: '中牟县',\n      410181: '巩义市',\n      410182: '荥阳市',\n      410183: '新密市',\n      410184: '新郑市',\n      410185: '登封市'\n    },\n    410200: {\n      410202: '龙亭区',\n      410203: '顺河回族区',\n      410204: '鼓楼区',\n      410205: '禹王台区',\n      410212: '祥符区',\n      410221: '杞县',\n      410222: '通许县',\n      410223: '尉氏县',\n      410225: '兰考县'\n    },\n    410300: {\n      410302: '老城区',\n      410303: '西工区',\n      410304: '瀍河回族区',\n      410305: '涧西区',\n      410306: '吉利区',\n      410311: '洛龙区',\n      410322: '孟津县',\n      410323: '新安县',\n      410324: '栾川县',\n      410325: '嵩县',\n      410326: '汝阳县',\n      410327: '宜阳县',\n      410328: '洛宁县',\n      410329: '伊川县',\n      410381: '偃师市'\n    },\n    410400: {\n      410402: '新华区',\n      410403: '卫东区',\n      410404: '石龙区',\n      410411: '湛河区',\n      410421: '宝丰县',\n      410422: '叶县',\n      410423: '鲁山县',\n      410425: '郏县',\n      410481: '舞钢市',\n      410482: '汝州市'\n    },\n    410500: {\n      410502: '文峰区',\n      410503: '北关区',\n      410505: '殷都区',\n      410506: '龙安区',\n      410522: '安阳县',\n      410523: '汤阴县',\n      410526: '滑县',\n      410527: '内黄县',\n      410581: '林州市'\n    },\n    410600: {\n      410602: '鹤山区',\n      410603: '山城区',\n      410611: '淇滨区',\n      410621: '浚县',\n      410622: '淇县'\n    },\n    410700: {\n      410702: '红旗区',\n      410703: '卫滨区',\n      410704: '凤泉区',\n      410711: '牧野区',\n      410721: '新乡县',\n      410724: '获嘉县',\n      410725: '原阳县',\n      410726: '延津县',\n      410727: '封丘县',\n      410728: '长垣县',\n      410781: '卫辉市',\n      410782: '辉县市'\n    },\n    410800: {\n      410802: '解放区',\n      410803: '中站区',\n      410804: '马村区',\n      410811: '山阳区',\n      410821: '修武县',\n      410822: '博爱县',\n      410823: '武陟县',\n      410825: '温县',\n      410882: '沁阳市',\n      410883: '孟州市'\n    },\n    410900: {\n      410902: '华龙区',\n      410922: '清丰县',\n      410923: '南乐县',\n      410926: '范县',\n      410927: '台前县',\n      410928: '濮阳县'\n    },\n    411000: {\n      411002: '魏都区',\n      411023: '许昌县',\n      411024: '鄢陵县',\n      411025: '襄城县',\n      411081: '禹州市',\n      411082: '长葛市'\n    },\n    411100: {\n      411102: '源汇区',\n      411103: '郾城区',\n      411104: '召陵区',\n      411121: '舞阳县',\n      411122: '临颍县'\n    },\n    411200: {\n      411202: '湖滨区',\n      411203: '陕州区',\n      411221: '渑池县',\n      411224: '卢氏县',\n      411281: '义马市',\n      411282: '灵宝市'\n    },\n    411300: {\n      411302: '宛城区',\n      411303: '卧龙区',\n      411321: '南召县',\n      411322: '方城县',\n      411323: '西峡县',\n      411324: '镇平县',\n      411325: '内乡县',\n      411326: '淅川县',\n      411327: '社旗县',\n      411328: '唐河县',\n      411329: '新野县',\n      411330: '桐柏县',\n      411381: '邓州市'\n    },\n    411400: {\n      411402: '梁园区',\n      411403: '睢阳区',\n      411421: '民权县',\n      411422: '睢县',\n      411423: '宁陵县',\n      411424: '柘城县',\n      411425: '虞城县',\n      411426: '夏邑县',\n      411481: '永城市'\n    },\n    411500: {\n      411502: '浉河区',\n      411503: '平桥区',\n      411521: '罗山县',\n      411522: '光山县',\n      411523: '新县',\n      411524: '商城县',\n      411525: '固始县',\n      411526: '潢川县',\n      411527: '淮滨县',\n      411528: '息县'\n    },\n    411600: {\n      411602: '川汇区',\n      411621: '扶沟县',\n      411622: '西华县',\n      411623: '商水县',\n      411624: '沈丘县',\n      411625: '郸城县',\n      411626: '淮阳县',\n      411627: '太康县',\n      411628: '鹿邑县',\n      411681: '项城市'\n    },\n    411700: {\n      411702: '驿城区',\n      411721: '西平县',\n      411722: '上蔡县',\n      411723: '平舆县',\n      411724: '正阳县',\n      411725: '确山县',\n      411726: '泌阳县',\n      411727: '汝南县',\n      411728: '遂平县',\n      411729: '新蔡县'\n    },\n    420000: {\n      420100: '武汉市',\n      420200: '黄石市',\n      420300: '十堰市',\n      420500: '宜昌市',\n      420600: '襄阳市',\n      420700: '鄂州市',\n      420800: '荆门市',\n      420900: '孝感市',\n      421000: '荆州市',\n      421100: '黄冈市',\n      421200: '咸宁市',\n      421300: '随州市',\n      422800: '恩施土家族苗族自治州',\n      429004: '仙桃市',\n      429005: '潜江市',\n      429006: '天门市',\n      429021: '神农架林区'\n    },\n    420100: {\n      420102: '江岸区',\n      420103: '江汉区',\n      420104: '硚口区',\n      420105: '汉阳区',\n      420106: '武昌区',\n      420107: '青山区',\n      420111: '洪山区',\n      420112: '东西湖区',\n      420113: '汉南区',\n      420114: '蔡甸区',\n      420115: '江夏区',\n      420116: '黄陂区',\n      420117: '新洲区'\n    },\n    420200: {\n      420202: '黄石港区',\n      420203: '西塞山区',\n      420204: '下陆区',\n      420205: '铁山区',\n      420222: '阳新县',\n      420281: '大冶市'\n    },\n    420300: {\n      420302: '茅箭区',\n      420303: '张湾区',\n      420304: '郧阳区',\n      420322: '郧西县',\n      420323: '竹山县',\n      420324: '竹溪县',\n      420325: '房县',\n      420381: '丹江口市'\n    },\n    420500: {\n      420502: '西陵区',\n      420503: '伍家岗区',\n      420504: '点军区',\n      420505: '猇亭区',\n      420506: '夷陵区',\n      420525: '远安县',\n      420526: '兴山县',\n      420527: '秭归县',\n      420528: '长阳土家族自治县',\n      420529: '五峰土家族自治县',\n      420581: '宜都市',\n      420582: '当阳市',\n      420583: '枝江市'\n    },\n    420600: {\n      420602: '襄城区',\n      420606: '樊城区',\n      420607: '襄州区',\n      420624: '南漳县',\n      420625: '谷城县',\n      420626: '保康县',\n      420682: '老河口市',\n      420683: '枣阳市',\n      420684: '宜城市'\n    },\n    420700: {\n      420702: '梁子湖区',\n      420703: '华容区',\n      420704: '鄂城区'\n    },\n    420800: {\n      420802: '东宝区',\n      420804: '掇刀区',\n      420821: '京山县',\n      420822: '沙洋县',\n      420881: '钟祥市'\n    },\n    420900: {\n      420902: '孝南区',\n      420921: '孝昌县',\n      420922: '大悟县',\n      420923: '云梦县',\n      420981: '应城市',\n      420982: '安陆市',\n      420984: '汉川市'\n    },\n    421000: {\n      421002: '沙市区',\n      421003: '荆州区',\n      421022: '公安县',\n      421023: '监利县',\n      421024: '江陵县',\n      421081: '石首市',\n      421083: '洪湖市',\n      421087: '松滋市'\n    },\n    421100: {\n      421102: '黄州区',\n      421121: '团风县',\n      421122: '红安县',\n      421123: '罗田县',\n      421124: '英山县',\n      421125: '浠水县',\n      421126: '蕲春县',\n      421127: '黄梅县',\n      421181: '麻城市',\n      421182: '武穴市'\n    },\n    421200: {\n      421202: '咸安区',\n      421221: '嘉鱼县',\n      421222: '通城县',\n      421223: '崇阳县',\n      421224: '通山县',\n      421281: '赤壁市'\n    },\n    421300: {\n      421303: '曾都区',\n      421321: '随县',\n      421381: '广水市'\n    },\n    422800: {\n      422801: '恩施市',\n      422802: '利川市',\n      422822: '建始县',\n      422823: '巴东县',\n      422825: '宣恩县',\n      422826: '咸丰县',\n      422827: '来凤县',\n      422828: '鹤峰县'\n    },\n    430000: {\n      430100: '长沙市',\n      430200: '株洲市',\n      430300: '湘潭市',\n      430400: '衡阳市',\n      430500: '邵阳市',\n      430600: '岳阳市',\n      430700: '常德市',\n      430800: '张家界市',\n      430900: '益阳市',\n      431000: '郴州市',\n      431100: '永州市',\n      431200: '怀化市',\n      431300: '娄底市',\n      433100: '湘西土家族苗族自治州'\n    },\n    430100: {\n      430102: '芙蓉区',\n      430103: '天心区',\n      430104: '岳麓区',\n      430105: '开福区',\n      430111: '雨花区',\n      430112: '望城区',\n      430121: '长沙县',\n      430124: '宁乡县',\n      430181: '浏阳市'\n    },\n    430200: {\n      430202: '荷塘区',\n      430203: '芦淞区',\n      430204: '石峰区',\n      430211: '天元区',\n      430221: '株洲县',\n      430223: '攸县',\n      430224: '茶陵县',\n      430225: '炎陵县',\n      430281: '醴陵市'\n    },\n    430300: {\n      430302: '雨湖区',\n      430304: '岳塘区',\n      430321: '湘潭县',\n      430381: '湘乡市',\n      430382: '韶山市'\n    },\n    430400: {\n      430405: '珠晖区',\n      430406: '雁峰区',\n      430407: '石鼓区',\n      430408: '蒸湘区',\n      430412: '南岳区',\n      430421: '衡阳县',\n      430422: '衡南县',\n      430423: '衡山县',\n      430424: '衡东县',\n      430426: '祁东县',\n      430481: '耒阳市',\n      430482: '常宁市'\n    },\n    430500: {\n      430502: '双清区',\n      430503: '大祥区',\n      430511: '北塔区',\n      430521: '邵东县',\n      430522: '新邵县',\n      430523: '邵阳县',\n      430524: '隆回县',\n      430525: '洞口县',\n      430527: '绥宁县',\n      430528: '新宁县',\n      430529: '城步苗族自治县',\n      430581: '武冈市'\n    },\n    430600: {\n      430602: '岳阳楼区',\n      430603: '云溪区',\n      430611: '君山区',\n      430621: '岳阳县',\n      430623: '华容县',\n      430624: '湘阴县',\n      430626: '平江县',\n      430681: '汨罗市',\n      430682: '临湘市'\n    },\n    430700: {\n      430702: '武陵区',\n      430703: '鼎城区',\n      430721: '安乡县',\n      430722: '汉寿县',\n      430723: '澧县',\n      430724: '临澧县',\n      430725: '桃源县',\n      430726: '石门县',\n      430781: '津市市'\n    },\n    430800: {\n      430802: '永定区',\n      430811: '武陵源区',\n      430821: '慈利县',\n      430822: '桑植县'\n    },\n    430900: {\n      430902: '资阳区',\n      430903: '赫山区',\n      430921: '南县',\n      430922: '桃江县',\n      430923: '安化县',\n      430981: '沅江市'\n    },\n    431000: {\n      431002: '北湖区',\n      431003: '苏仙区',\n      431021: '桂阳县',\n      431022: '宜章县',\n      431023: '永兴县',\n      431024: '嘉禾县',\n      431025: '临武县',\n      431026: '汝城县',\n      431027: '桂东县',\n      431028: '安仁县',\n      431081: '资兴市'\n    },\n    431100: {\n      431102: '零陵区',\n      431103: '冷水滩区',\n      431121: '祁阳县',\n      431122: '东安县',\n      431123: '双牌县',\n      431124: '道县',\n      431125: '江永县',\n      431126: '宁远县',\n      431127: '蓝山县',\n      431128: '新田县',\n      431129: '江华瑶族自治县'\n    },\n    431200: {\n      431202: '鹤城区',\n      431221: '中方县',\n      431222: '沅陵县',\n      431223: '辰溪县',\n      431224: '溆浦县',\n      431225: '会同县',\n      431226: '麻阳苗族自治县',\n      431227: '新晃侗族自治县',\n      431228: '芷江侗族自治县',\n      431229: '靖州苗族侗族自治县',\n      431230: '通道侗族自治县',\n      431281: '洪江市'\n    },\n    431300: {\n      431302: '娄星区',\n      431321: '双峰县',\n      431322: '新化县',\n      431381: '冷水江市',\n      431382: '涟源市'\n    },\n    433100: {\n      433101: '吉首市',\n      433122: '泸溪县',\n      433123: '凤凰县',\n      433124: '花垣县',\n      433125: '保靖县',\n      433126: '古丈县',\n      433127: '永顺县',\n      433130: '龙山县'\n    },\n    440000: {\n      440100: '广州市',\n      440200: '韶关市',\n      440300: '深圳市',\n      440400: '珠海市',\n      440500: '汕头市',\n      440600: '佛山市',\n      440700: '江门市',\n      440800: '湛江市',\n      440900: '茂名市',\n      441200: '肇庆市',\n      441300: '惠州市',\n      441400: '梅州市',\n      441500: '汕尾市',\n      441600: '河源市',\n      441700: '阳江市',\n      441800: '清远市',\n      441900: '东莞市',\n      442000: '中山市',\n      445100: '潮州市',\n      445200: '揭阳市',\n      445300: '云浮市'\n    },\n    440100: {\n      440103: '荔湾区',\n      440104: '越秀区',\n      440105: '海珠区',\n      440106: '天河区',\n      440111: '白云区',\n      440112: '黄埔区',\n      440113: '番禺区',\n      440114: '花都区',\n      440115: '南沙区',\n      440117: '从化区',\n      440118: '增城区'\n    },\n    440200: {\n      440203: '武江区',\n      440204: '浈江区',\n      440205: '曲江区',\n      440222: '始兴县',\n      440224: '仁化县',\n      440229: '翁源县',\n      440232: '乳源瑶族自治县',\n      440233: '新丰县',\n      440281: '乐昌市',\n      440282: '南雄市'\n    },\n    440300: {\n      440303: '罗湖区',\n      440304: '福田区',\n      440305: '南山区',\n      440306: '宝安区',\n      440307: '龙岗区',\n      440308: '盐田区'\n    },\n    440400: {\n      440402: '香洲区',\n      440403: '斗门区',\n      440404: '金湾区'\n    },\n    440500: {\n      440507: '龙湖区',\n      440511: '金平区',\n      440512: '濠江区',\n      440513: '潮阳区',\n      440514: '潮南区',\n      440515: '澄海区',\n      440523: '南澳县'\n    },\n    440600: {\n      440604: '禅城区',\n      440605: '南海区',\n      440606: '顺德区',\n      440607: '三水区',\n      440608: '高明区'\n    },\n    440700: {\n      440703: '蓬江区',\n      440704: '江海区',\n      440705: '新会区',\n      440781: '台山市',\n      440783: '开平市',\n      440784: '鹤山市',\n      440785: '恩平市'\n    },\n    440800: {\n      440802: '赤坎区',\n      440803: '霞山区',\n      440804: '坡头区',\n      440811: '麻章区',\n      440823: '遂溪县',\n      440825: '徐闻县',\n      440881: '廉江市',\n      440882: '雷州市',\n      440883: '吴川市'\n    },\n    440900: {\n      440902: '茂南区',\n      440904: '电白区',\n      440981: '高州市',\n      440982: '化州市',\n      440983: '信宜市'\n    },\n    441200: {\n      441202: '端州区',\n      441203: '鼎湖区',\n      441204: '高要区',\n      441223: '广宁县',\n      441224: '怀集县',\n      441225: '封开县',\n      441226: '德庆县',\n      441284: '四会市'\n    },\n    441300: {\n      441302: '惠城区',\n      441303: '惠阳区',\n      441322: '博罗县',\n      441323: '惠东县',\n      441324: '龙门县'\n    },\n    441400: {\n      441402: '梅江区',\n      441403: '梅县区',\n      441422: '大埔县',\n      441423: '丰顺县',\n      441424: '五华县',\n      441426: '平远县',\n      441427: '蕉岭县',\n      441481: '兴宁市'\n    },\n    441500: {\n      441502: '城区',\n      441521: '海丰县',\n      441523: '陆河县',\n      441581: '陆丰市'\n    },\n    441600: {\n      441602: '源城区',\n      441621: '紫金县',\n      441622: '龙川县',\n      441623: '连平县',\n      441624: '和平县',\n      441625: '东源县'\n    },\n    441700: {\n      441702: '江城区',\n      441704: '阳东区',\n      441721: '阳西县',\n      441781: '阳春市'\n    },\n    441800: {\n      441802: '清城区',\n      441803: '清新区',\n      441821: '佛冈县',\n      441823: '阳山县',\n      441825: '连山壮族瑶族自治县',\n      441826: '连南瑶族自治县',\n      441881: '英德市',\n      441882: '连州市'\n    },\n    441900: {\n      441900: '三元里'\n    },\n    442000: {\n      442000: '湖滨北路'\n    },\n    445100: {\n      445102: '湘桥区',\n      445103: '潮安区',\n      445122: '饶平县'\n    },\n    445200: {\n      445202: '榕城区',\n      445203: '揭东区',\n      445222: '揭西县',\n      445224: '惠来县',\n      445281: '普宁市'\n    },\n    445300: {\n      445302: '云城区',\n      445303: '云安区',\n      445321: '新兴县',\n      445322: '郁南县',\n      445381: '罗定市'\n    },\n    450000: {\n      450100: '南宁市',\n      450200: '柳州市',\n      450300: '桂林市',\n      450400: '梧州市',\n      450500: '北海市',\n      450600: '防城港市',\n      450700: '钦州市',\n      450800: '贵港市',\n      450900: '玉林市',\n      451000: '百色市',\n      451100: '贺州市',\n      451200: '河池市',\n      451300: '来宾市',\n      451400: '崇左市'\n    },\n    450100: {\n      450102: '兴宁区',\n      450103: '青秀区',\n      450105: '江南区',\n      450107: '西乡塘区',\n      450108: '良庆区',\n      450109: '邕宁区',\n      450110: '武鸣区',\n      450123: '隆安县',\n      450124: '马山县',\n      450125: '上林县',\n      450126: '宾阳县',\n      450127: '横县'\n    },\n    450200: {\n      450202: '城中区',\n      450203: '鱼峰区',\n      450204: '柳南区',\n      450205: '柳北区',\n      450221: '柳江县',\n      450222: '柳城县',\n      450223: '鹿寨县',\n      450224: '融安县',\n      450225: '融水苗族自治县',\n      450226: '三江侗族自治县'\n    },\n    450300: {\n      450302: '秀峰区',\n      450303: '叠彩区',\n      450304: '象山区',\n      450305: '七星区',\n      450311: '雁山区',\n      450312: '临桂区',\n      450321: '阳朔县',\n      450323: '灵川县',\n      450324: '全州县',\n      450325: '兴安县',\n      450326: '永福县',\n      450327: '灌阳县',\n      450328: '龙胜各族自治县',\n      450329: '资源县',\n      450330: '平乐县',\n      450331: '荔浦县',\n      450332: '恭城瑶族自治县'\n    },\n    450400: {\n      450403: '万秀区',\n      450405: '长洲区',\n      450406: '龙圩区',\n      450421: '苍梧县',\n      450422: '藤县',\n      450423: '蒙山县',\n      450481: '岑溪市'\n    },\n    450500: {\n      450502: '海城区',\n      450503: '银海区',\n      450512: '铁山港区',\n      450521: '合浦县'\n    },\n    450600: {\n      450602: '港口区',\n      450603: '防城区',\n      450621: '上思县',\n      450681: '东兴市'\n    },\n    450700: {\n      450702: '钦南区',\n      450703: '钦北区',\n      450721: '灵山县',\n      450722: '浦北县'\n    },\n    450800: {\n      450802: '港北区',\n      450803: '港南区',\n      450804: '覃塘区',\n      450821: '平南县',\n      450881: '桂平市'\n    },\n    450900: {\n      450902: '玉州区',\n      450903: '福绵区',\n      450921: '容县',\n      450922: '陆川县',\n      450923: '博白县',\n      450924: '兴业县',\n      450981: '北流市'\n    },\n    451000: {\n      451002: '右江区',\n      451021: '田阳县',\n      451022: '田东县',\n      451023: '平果县',\n      451024: '德保县',\n      451026: '那坡县',\n      451027: '凌云县',\n      451028: '乐业县',\n      451029: '田林县',\n      451030: '西林县',\n      451031: '隆林各族自治县',\n      451081: '靖西市'\n    },\n    451100: {\n      451102: '八步区',\n      451121: '昭平县',\n      451122: '钟山县',\n      451123: '富川瑶族自治县'\n    },\n    451200: {\n      451202: '金城江区',\n      451221: '南丹县',\n      451222: '天峨县',\n      451223: '凤山县',\n      451224: '东兰县',\n      451225: '罗城仫佬族自治县',\n      451226: '环江毛南族自治县',\n      451227: '巴马瑶族自治县',\n      451228: '都安瑶族自治县',\n      451229: '大化瑶族自治县',\n      451281: '宜州市'\n    },\n    451300: {\n      451302: '兴宾区',\n      451321: '忻城县',\n      451322: '象州县',\n      451323: '武宣县',\n      451324: '金秀瑶族自治县',\n      451381: '合山市'\n    },\n    451400: {\n      451402: '江州区',\n      451421: '扶绥县',\n      451422: '宁明县',\n      451423: '龙州县',\n      451424: '大新县',\n      451425: '天等县',\n      451481: '凭祥市'\n    },\n    460000: {\n      460100: '海口市',\n      460200: '三亚市',\n      460300: '三沙市',\n      460400: '儋州市',\n      469001: '五指山市',\n      469002: '琼海市',\n      469005: '文昌市',\n      469006: '万宁市',\n      469007: '东方市',\n      469021: '定安县',\n      469022: '屯昌县',\n      469023: '澄迈县',\n      469024: '临高县',\n      469025: '白沙黎族自治县',\n      469026: '昌江黎族自治县',\n      469027: '乐东黎族自治县',\n      469028: '陵水黎族自治县',\n      469029: '保亭黎族苗族自治县',\n      469030: '琼中黎族苗族自治县'\n    },\n    460100: {\n      460105: '秀英区',\n      460106: '龙华区',\n      460107: '琼山区',\n      460108: '美兰区'\n    },\n    460200: {\n      460200: '三亚湾',\n      460202: '海棠区',\n      460203: '吉阳区',\n      460204: '天涯区',\n      460205: '崖州区'\n    },\n    460300: {\n      460321: '西沙群岛',\n      460322: '南沙群岛',\n      460323: '中沙群岛的岛礁及其海域'\n    },\n    500000: {\n      500100: '重庆市市辖区',\n      500200: '重庆市郊县'\n    },\n    500100: {\n      500101: '万州区',\n      500102: '涪陵区',\n      500103: '渝中区',\n      500104: '大渡口区',\n      500105: '江北区',\n      500106: '沙坪坝区',\n      500107: '九龙坡区',\n      500108: '南岸区',\n      500109: '北碚区',\n      500110: '綦江区',\n      500111: '大足区',\n      500112: '渝北区',\n      500113: '巴南区',\n      500114: '黔江区',\n      500115: '长寿区',\n      500116: '江津区',\n      500117: '合川区',\n      500118: '永川区',\n      500119: '南川区',\n      500120: '璧山区',\n      500151: '铜梁区',\n      500152: '潼南区',\n      500153: '荣昌区',\n      500228: '梁平县',\n      500229: '城口县',\n      500230: '丰都县',\n      500231: '垫江县',\n      500232: '武隆县',\n      500233: '忠县',\n      500234: '开县',\n      500235: '云阳县',\n      500236: '奉节县',\n      500237: '巫山县',\n      500238: '巫溪县',\n      500240: '石柱土家族自治县',\n      500241: '秀山土家族苗族自治县',\n      500242: '酉阳土家族苗族自治县',\n      500243: '彭水苗族土家族自治县'\n    },\n    510000: {\n      510100: '成都市',\n      510300: '自贡市',\n      510400: '攀枝花市',\n      510500: '泸州市',\n      510600: '德阳市',\n      510700: '绵阳市',\n      510800: '广元市',\n      510900: '遂宁市',\n      511000: '内江市',\n      511100: '乐山市',\n      511300: '南充市',\n      511400: '眉山市',\n      511500: '宜宾市',\n      511600: '广安市',\n      511700: '达州市',\n      511800: '雅安市',\n      511900: '巴中市',\n      512000: '资阳市',\n      513200: '阿坝藏族羌族自治州',\n      513300: '甘孜藏族自治州',\n      513400: '凉山彝族自治州'\n    },\n    510100: {\n      510104: '锦江区',\n      510105: '青羊区',\n      510106: '金牛区',\n      510107: '武侯区',\n      510108: '成华区',\n      510112: '龙泉驿区',\n      510113: '青白江区',\n      510114: '新都区',\n      510115: '温江区',\n      510116: '双流区',\n      510121: '金堂县',\n      510124: '郫县',\n      510129: '大邑县',\n      510131: '蒲江县',\n      510132: '新津县',\n      510181: '都江堰市',\n      510182: '彭州市',\n      510183: '邛崃市',\n      510184: '崇州市'\n    },\n    510300: {\n      510302: '自流井区',\n      510303: '贡井区',\n      510304: '大安区',\n      510311: '沿滩区',\n      510321: '荣县',\n      510322: '富顺县'\n    },\n    510400: {\n      510402: '东区',\n      510403: '西区',\n      510411: '仁和区',\n      510421: '米易县',\n      510422: '盐边县'\n    },\n    510500: {\n      510502: '江阳区',\n      510503: '纳溪区',\n      510504: '龙马潭区',\n      510521: '泸县',\n      510522: '合江县',\n      510524: '叙永县',\n      510525: '古蔺县'\n    },\n    510600: {\n      510603: '旌阳区',\n      510623: '中江县',\n      510626: '罗江县',\n      510681: '广汉市',\n      510682: '什邡市',\n      510683: '绵竹市'\n    },\n    510700: {\n      510703: '涪城区',\n      510704: '游仙区',\n      510722: '三台县',\n      510723: '盐亭县',\n      510724: '安县',\n      510725: '梓潼县',\n      510726: '北川羌族自治县',\n      510727: '平武县',\n      510781: '江油市'\n    },\n    510800: {\n      510802: '利州区',\n      510811: '昭化区',\n      510812: '朝天区',\n      510821: '旺苍县',\n      510822: '青川县',\n      510823: '剑阁县',\n      510824: '苍溪县'\n    },\n    510900: {\n      510903: '船山区',\n      510904: '安居区',\n      510921: '蓬溪县',\n      510922: '射洪县',\n      510923: '大英县'\n    },\n    511000: {\n      511002: '市中区',\n      511011: '东兴区',\n      511024: '威远县',\n      511025: '资中县',\n      511028: '隆昌县'\n    },\n    511100: {\n      511102: '市中区',\n      511111: '沙湾区',\n      511112: '五通桥区',\n      511113: '金口河区',\n      511123: '犍为县',\n      511124: '井研县',\n      511126: '夹江县',\n      511129: '沐川县',\n      511132: '峨边彝族自治县',\n      511133: '马边彝族自治县',\n      511181: '峨眉山市'\n    },\n    511300: {\n      511302: '顺庆区',\n      511303: '高坪区',\n      511304: '嘉陵区',\n      511321: '南部县',\n      511322: '营山县',\n      511323: '蓬安县',\n      511324: '仪陇县',\n      511325: '西充县',\n      511381: '阆中市'\n    },\n    511400: {\n      511402: '东坡区',\n      511403: '彭山区',\n      511421: '仁寿县',\n      511423: '洪雅县',\n      511424: '丹棱县',\n      511425: '青神县'\n    },\n    511500: {\n      511502: '翠屏区',\n      511503: '南溪区',\n      511521: '宜宾县',\n      511523: '江安县',\n      511524: '长宁县',\n      511525: '高县',\n      511526: '珙县',\n      511527: '筠连县',\n      511528: '兴文县',\n      511529: '屏山县'\n    },\n    511600: {\n      511602: '广安区',\n      511603: '前锋区',\n      511621: '岳池县',\n      511622: '武胜县',\n      511623: '邻水县',\n      511681: '华蓥市'\n    },\n    511700: {\n      511702: '通川区',\n      511703: '达川区',\n      511722: '宣汉县',\n      511723: '开江县',\n      511724: '大竹县',\n      511725: '渠县',\n      511781: '万源市'\n    },\n    511800: {\n      511802: '雨城区',\n      511803: '名山区',\n      511822: '荥经县',\n      511823: '汉源县',\n      511824: '石棉县',\n      511825: '天全县',\n      511826: '芦山县',\n      511827: '宝兴县'\n    },\n    511900: {\n      511902: '巴州区',\n      511903: '恩阳区',\n      511921: '通江县',\n      511922: '南江县',\n      511923: '平昌县'\n    },\n    512000: {\n      512002: '雁江区',\n      512021: '安岳县',\n      512022: '乐至县',\n      512081: '简阳市'\n    },\n    513200: {\n      513201: '马尔康市',\n      513221: '汶川县',\n      513222: '理县',\n      513223: '茂县',\n      513224: '松潘县',\n      513225: '九寨沟县',\n      513226: '金川县',\n      513227: '小金县',\n      513228: '黑水县',\n      513230: '壤塘县',\n      513231: '阿坝县',\n      513232: '若尔盖县',\n      513233: '红原县'\n    },\n    513300: {\n      513301: '康定市',\n      513322: '泸定县',\n      513323: '丹巴县',\n      513324: '九龙县',\n      513325: '雅江县',\n      513326: '道孚县',\n      513327: '炉霍县',\n      513328: '甘孜县',\n      513329: '新龙县',\n      513330: '德格县',\n      513331: '白玉县',\n      513332: '石渠县',\n      513333: '色达县',\n      513334: '理塘县',\n      513335: '巴塘县',\n      513336: '乡城县',\n      513337: '稻城县',\n      513338: '得荣县'\n    },\n    513400: {\n      513401: '西昌市',\n      513422: '木里藏族自治县',\n      513423: '盐源县',\n      513424: '德昌县',\n      513425: '会理县',\n      513426: '会东县',\n      513427: '宁南县',\n      513428: '普格县',\n      513429: '布拖县',\n      513430: '金阳县',\n      513431: '昭觉县',\n      513432: '喜德县',\n      513433: '冕宁县',\n      513434: '越西县',\n      513435: '甘洛县',\n      513436: '美姑县',\n      513437: '雷波县'\n    },\n    520000: {\n      520100: '贵阳市',\n      520200: '六盘水市',\n      520300: '遵义市',\n      520400: '安顺市',\n      520500: '毕节市',\n      520600: '铜仁市',\n      522300: '黔西南布依族苗族自治州',\n      522600: '黔东南苗族侗族自治州',\n      522700: '黔南布依族苗族自治州'\n    },\n    520100: {\n      520102: '南明区',\n      520103: '云岩区',\n      520111: '花溪区',\n      520112: '乌当区',\n      520113: '白云区',\n      520115: '观山湖区',\n      520121: '开阳县',\n      520122: '息烽县',\n      520123: '修文县',\n      520181: '清镇市'\n    },\n    520200: {\n      520201: '钟山区',\n      520203: '六枝特区',\n      520221: '水城县',\n      520222: '盘县'\n    },\n    520300: {\n      520302: '红花岗区',\n      520303: '汇川区',\n      520321: '遵义县',\n      520322: '桐梓县',\n      520323: '绥阳县',\n      520324: '正安县',\n      520325: '道真仡佬族苗族自治县',\n      520326: '务川仡佬族苗族自治县',\n      520327: '凤冈县',\n      520328: '湄潭县',\n      520329: '余庆县',\n      520330: '习水县',\n      520381: '赤水市',\n      520382: '仁怀市'\n    },\n    520400: {\n      520402: '西秀区',\n      520403: '平坝区',\n      520422: '普定县',\n      520423: '镇宁布依族苗族自治县',\n      520424: '关岭布依族苗族自治县',\n      520425: '紫云苗族布依族自治县'\n    },\n    520500: {\n      520502: '七星关区',\n      520521: '大方县',\n      520522: '黔西县',\n      520523: '金沙县',\n      520524: '织金县',\n      520525: '纳雍县',\n      520526: '威宁彝族回族苗族自治县',\n      520527: '赫章县'\n    },\n    520600: {\n      520602: '碧江区',\n      520603: '万山区',\n      520621: '江口县',\n      520622: '玉屏侗族自治县',\n      520623: '石阡县',\n      520624: '思南县',\n      520625: '印江土家族苗族自治县',\n      520626: '德江县',\n      520627: '沿河土家族自治县',\n      520628: '松桃苗族自治县'\n    },\n    522300: {\n      522301: '兴义市',\n      522322: '兴仁县',\n      522323: '普安县',\n      522324: '晴隆县',\n      522325: '贞丰县',\n      522326: '望谟县',\n      522327: '册亨县',\n      522328: '安龙县'\n    },\n    522600: {\n      522601: '凯里市',\n      522622: '黄平县',\n      522623: '施秉县',\n      522624: '三穗县',\n      522625: '镇远县',\n      522626: '岑巩县',\n      522627: '天柱县',\n      522628: '锦屏县',\n      522629: '剑河县',\n      522630: '台江县',\n      522631: '黎平县',\n      522632: '榕江县',\n      522633: '从江县',\n      522634: '雷山县',\n      522635: '麻江县',\n      522636: '丹寨县'\n    },\n    522700: {\n      522701: '都匀市',\n      522702: '福泉市',\n      522722: '荔波县',\n      522723: '贵定县',\n      522725: '瓮安县',\n      522726: '独山县',\n      522727: '平塘县',\n      522728: '罗甸县',\n      522729: '长顺县',\n      522730: '龙里县',\n      522731: '惠水县',\n      522732: '三都水族自治县'\n    },\n    530000: {\n      530100: '昆明市',\n      530300: '曲靖市',\n      530400: '玉溪市',\n      530500: '保山市',\n      530600: '昭通市',\n      530700: '丽江市',\n      530800: '普洱市',\n      530900: '临沧市',\n      532300: '楚雄彝族自治州',\n      532500: '红河哈尼族彝族自治州',\n      532600: '文山壮族苗族自治州',\n      532800: '西双版纳傣族自治州',\n      532900: '大理白族自治州',\n      533100: '德宏傣族景颇族自治州',\n      533300: '怒江傈僳族自治州',\n      533400: '迪庆藏族自治州'\n    },\n    530100: {\n      530102: '五华区',\n      530103: '盘龙区',\n      530111: '官渡区',\n      530112: '西山区',\n      530113: '东川区',\n      530114: '呈贡区',\n      530122: '晋宁县',\n      530124: '富民县',\n      530125: '宜良县',\n      530126: '石林彝族自治县',\n      530127: '嵩明县',\n      530128: '禄劝彝族苗族自治县',\n      530129: '寻甸回族彝族自治县',\n      530181: '安宁市'\n    },\n    530300: {\n      530302: '麒麟区',\n      530321: '马龙县',\n      530322: '陆良县',\n      530323: '师宗县',\n      530324: '罗平县',\n      530325: '富源县',\n      530326: '会泽县',\n      530328: '沾益县',\n      530381: '宣威市'\n    },\n    530400: {\n      530402: '红塔区',\n      530403: '江川区',\n      530422: '澄江县',\n      530423: '通海县',\n      530424: '华宁县',\n      530425: '易门县',\n      530426: '峨山彝族自治县',\n      530427: '新平彝族傣族自治县',\n      530428: '元江哈尼族彝族傣族自治县'\n    },\n    530500: {\n      530502: '隆阳区',\n      530521: '施甸县',\n      530523: '龙陵县',\n      530524: '昌宁县',\n      530581: '腾冲市'\n    },\n    530600: {\n      530602: '昭阳区',\n      530621: '鲁甸县',\n      530622: '巧家县',\n      530623: '盐津县',\n      530624: '大关县',\n      530625: '永善县',\n      530626: '绥江县',\n      530627: '镇雄县',\n      530628: '彝良县',\n      530629: '威信县',\n      530630: '水富县'\n    },\n    530700: {\n      530702: '古城区',\n      530721: '玉龙纳西族自治县',\n      530722: '永胜县',\n      530723: '华坪县',\n      530724: '宁蒗彝族自治县'\n    },\n    530800: {\n      530802: '思茅区',\n      530821: '宁洱哈尼族彝族自治县',\n      530822: '墨江哈尼族自治县',\n      530823: '景东彝族自治县',\n      530824: '景谷傣族彝族自治县',\n      530825: '镇沅彝族哈尼族拉祜族自治县',\n      530826: '江城哈尼族彝族自治县',\n      530827: '孟连傣族拉祜族佤族自治县',\n      530828: '澜沧拉祜族自治县',\n      530829: '西盟佤族自治县'\n    },\n    530900: {\n      530902: '临翔区',\n      530921: '凤庆县',\n      530922: '云县',\n      530923: '永德县',\n      530924: '镇康县',\n      530925: '双江拉祜族佤族布朗族傣族自治县',\n      530926: '耿马傣族佤族自治县',\n      530927: '沧源佤族自治县'\n    },\n    532300: {\n      532301: '楚雄市',\n      532322: '双柏县',\n      532323: '牟定县',\n      532324: '南华县',\n      532325: '姚安县',\n      532326: '大姚县',\n      532327: '永仁县',\n      532328: '元谋县',\n      532329: '武定县',\n      532331: '禄丰县'\n    },\n    532500: {\n      532501: '个旧市',\n      532502: '开远市',\n      532503: '蒙自市',\n      532504: '弥勒市',\n      532523: '屏边苗族自治县',\n      532524: '建水县',\n      532525: '石屏县',\n      532527: '泸西县',\n      532528: '元阳县',\n      532529: '红河县',\n      532530: '金平苗族瑶族傣族自治县',\n      532531: '绿春县',\n      532532: '河口瑶族自治县'\n    },\n    532600: {\n      532601: '文山市',\n      532622: '砚山县',\n      532623: '西畴县',\n      532624: '麻栗坡县',\n      532625: '马关县',\n      532626: '丘北县',\n      532627: '广南县',\n      532628: '富宁县'\n    },\n    532800: {\n      532801: '景洪市',\n      532822: '勐海县',\n      532823: '勐腊县'\n    },\n    532900: {\n      532901: '大理市',\n      532922: '漾濞彝族自治县',\n      532923: '祥云县',\n      532924: '宾川县',\n      532925: '弥渡县',\n      532926: '南涧彝族自治县',\n      532927: '巍山彝族回族自治县',\n      532928: '永平县',\n      532929: '云龙县',\n      532930: '洱源县',\n      532931: '剑川县',\n      532932: '鹤庆县'\n    },\n    533100: {\n      533102: '瑞丽市',\n      533103: '芒市',\n      533122: '梁河县',\n      533123: '盈江县',\n      533124: '陇川县'\n    },\n    533300: {\n      533321: '泸水县',\n      533323: '福贡县',\n      533324: '贡山独龙族怒族自治县',\n      533325: '兰坪白族普米族自治县'\n    },\n    533400: {\n      533401: '香格里拉市',\n      533422: '德钦县',\n      533423: '维西傈僳族自治县'\n    },\n    540000: {\n      540100: '拉萨市',\n      540200: '日喀则市',\n      540300: '昌都市',\n      540400: '林芝市',\n      542200: '山南地区',\n      542400: '那曲地区',\n      542500: '阿里地区'\n    },\n    540100: {\n      540102: '城关区',\n      540103: '堆龙德庆区',\n      540121: '林周县',\n      540122: '当雄县',\n      540123: '尼木县',\n      540124: '曲水县',\n      540126: '达孜县',\n      540127: '墨竹工卡县'\n    },\n    540200: {\n      540202: '桑珠孜区',\n      540221: '南木林县',\n      540222: '江孜县',\n      540223: '定日县',\n      540224: '萨迦县',\n      540225: '拉孜县',\n      540226: '昂仁县',\n      540227: '谢通门县',\n      540228: '白朗县',\n      540229: '仁布县',\n      540230: '康马县',\n      540231: '定结县',\n      540232: '仲巴县',\n      540233: '亚东县',\n      540234: '吉隆县',\n      540235: '聂拉木县',\n      540236: '萨嘎县',\n      540237: '岗巴县'\n    },\n    540300: {\n      540302: '卡若区',\n      540321: '江达县',\n      540322: '贡觉县',\n      540323: '类乌齐县',\n      540324: '丁青县',\n      540325: '察雅县',\n      540326: '八宿县',\n      540327: '左贡县',\n      540328: '芒康县',\n      540329: '洛隆县',\n      540330: '边坝县'\n    },\n    540400: {\n      540402: '巴宜区',\n      540421: '工布江达县',\n      540422: '米林县',\n      540423: '墨脱县',\n      540424: '波密县',\n      540425: '察隅县',\n      540426: '朗县'\n    },\n    542200: {\n      542221: '乃东县',\n      542222: '扎囊县',\n      542223: '贡嘎县',\n      542224: '桑日县',\n      542225: '琼结县',\n      542226: '曲松县',\n      542227: '措美县',\n      542228: '洛扎县',\n      542229: '加查县',\n      542231: '隆子县',\n      542232: '错那县',\n      542233: '浪卡子县'\n    },\n    542400: {\n      542421: '那曲县',\n      542422: '嘉黎县',\n      542423: '比如县',\n      542424: '聂荣县',\n      542425: '安多县',\n      542426: '申扎县',\n      542427: '索县',\n      542428: '班戈县',\n      542429: '巴青县',\n      542430: '尼玛县',\n      542431: '双湖县'\n    },\n    542500: {\n      542521: '普兰县',\n      542522: '札达县',\n      542523: '噶尔县',\n      542524: '日土县',\n      542525: '革吉县',\n      542526: '改则县',\n      542527: '措勤县'\n    },\n    610000: {\n      610100: '西安市',\n      610200: '铜川市',\n      610300: '宝鸡市',\n      610400: '咸阳市',\n      610500: '渭南市',\n      610600: '延安市',\n      610700: '汉中市',\n      610800: '榆林市',\n      610900: '安康市',\n      611000: '商洛市'\n    },\n    610100: {\n      610102: '新城区',\n      610103: '碑林区',\n      610104: '莲湖区',\n      610111: '灞桥区',\n      610112: '未央区',\n      610113: '雁塔区',\n      610114: '阎良区',\n      610115: '临潼区',\n      610116: '长安区',\n      610117: '高陵区',\n      610122: '蓝田县',\n      610124: '周至县',\n      610125: '户县'\n    },\n    610200: {\n      610202: '王益区',\n      610203: '印台区',\n      610204: '耀州区',\n      610222: '宜君县'\n    },\n    610300: {\n      610302: '渭滨区',\n      610303: '金台区',\n      610304: '陈仓区',\n      610322: '凤翔县',\n      610323: '岐山县',\n      610324: '扶风县',\n      610326: '眉县',\n      610327: '陇县',\n      610328: '千阳县',\n      610329: '麟游县',\n      610330: '凤县',\n      610331: '太白县'\n    },\n    610400: {\n      610402: '秦都区',\n      610403: '杨陵区',\n      610404: '渭城区',\n      610422: '三原县',\n      610423: '泾阳县',\n      610424: '乾县',\n      610425: '礼泉县',\n      610426: '永寿县',\n      610427: '彬县',\n      610428: '长武县',\n      610429: '旬邑县',\n      610430: '淳化县',\n      610431: '武功县',\n      610481: '兴平市'\n    },\n    610500: {\n      610502: '临渭区',\n      610503: '华州区',\n      610522: '潼关县',\n      610523: '大荔县',\n      610524: '合阳县',\n      610525: '澄城县',\n      610526: '蒲城县',\n      610527: '白水县',\n      610528: '富平县',\n      610581: '韩城市',\n      610582: '华阴市'\n    },\n    610600: {\n      610602: '宝塔区',\n      610621: '延长县',\n      610622: '延川县',\n      610623: '子长县',\n      610624: '安塞县',\n      610625: '志丹县',\n      610626: '吴起县',\n      610627: '甘泉县',\n      610628: '富县',\n      610629: '洛川县',\n      610630: '宜川县',\n      610631: '黄龙县',\n      610632: '黄陵县'\n    },\n    610700: {\n      610702: '汉台区',\n      610721: '南郑县',\n      610722: '城固县',\n      610723: '洋县',\n      610724: '西乡县',\n      610725: '勉县',\n      610726: '宁强县',\n      610727: '略阳县',\n      610728: '镇巴县',\n      610729: '留坝县',\n      610730: '佛坪县'\n    },\n    610800: {\n      610802: '榆阳区',\n      610803: '横山区',\n      610821: '神木县',\n      610822: '府谷县',\n      610824: '靖边县',\n      610825: '定边县',\n      610826: '绥德县',\n      610827: '米脂县',\n      610828: '佳县',\n      610829: '吴堡县',\n      610830: '清涧县',\n      610831: '子洲县'\n    },\n    610900: {\n      610902: '汉滨区',\n      610921: '汉阴县',\n      610922: '石泉县',\n      610923: '宁陕县',\n      610924: '紫阳县',\n      610925: '岚皋县',\n      610926: '平利县',\n      610927: '镇坪县',\n      610928: '旬阳县',\n      610929: '白河县'\n    },\n    611000: {\n      611002: '商州区',\n      611021: '洛南县',\n      611022: '丹凤县',\n      611023: '商南县',\n      611024: '山阳县',\n      611025: '镇安县',\n      611026: '柞水县'\n    },\n    620000: {\n      620100: '兰州市',\n      620200: '嘉峪关市',\n      620300: '金昌市',\n      620400: '白银市',\n      620500: '天水市',\n      620600: '武威市',\n      620700: '张掖市',\n      620800: '平凉市',\n      620900: '酒泉市',\n      621000: '庆阳市',\n      621100: '定西市',\n      621200: '陇南市',\n      622900: '临夏回族自治州',\n      623000: '甘南藏族自治州'\n    },\n    620100: {\n      620102: '城关区',\n      620103: '七里河区',\n      620104: '西固区',\n      620105: '安宁区',\n      620111: '红古区',\n      620121: '永登县',\n      620122: '皋兰县',\n      620123: '榆中县'\n    },\n    620300: {\n      620302: '金川区',\n      620321: '永昌县'\n    },\n    620400: {\n      620402: '白银区',\n      620403: '平川区',\n      620421: '靖远县',\n      620422: '会宁县',\n      620423: '景泰县'\n    },\n    620500: {\n      620502: '秦州区',\n      620503: '麦积区',\n      620521: '清水县',\n      620522: '秦安县',\n      620523: '甘谷县',\n      620524: '武山县',\n      620525: '张家川回族自治县'\n    },\n    620600: {\n      620602: '凉州区',\n      620621: '民勤县',\n      620622: '古浪县',\n      620623: '天祝藏族自治县'\n    },\n    620700: {\n      620702: '甘州区',\n      620721: '肃南裕固族自治县',\n      620722: '民乐县',\n      620723: '临泽县',\n      620724: '高台县',\n      620725: '山丹县'\n    },\n    620800: {\n      620802: '崆峒区',\n      620821: '泾川县',\n      620822: '灵台县',\n      620823: '崇信县',\n      620824: '华亭县',\n      620825: '庄浪县',\n      620826: '静宁县'\n    },\n    620900: {\n      620902: '肃州区',\n      620921: '金塔县',\n      620922: '瓜州县',\n      620923: '肃北蒙古族自治县',\n      620924: '阿克塞哈萨克族自治县',\n      620981: '玉门市',\n      620982: '敦煌市'\n    },\n    621000: {\n      621002: '西峰区',\n      621021: '庆城县',\n      621022: '环县',\n      621023: '华池县',\n      621024: '合水县',\n      621025: '正宁县',\n      621026: '宁县',\n      621027: '镇原县'\n    },\n    621100: {\n      621102: '安定区',\n      621121: '通渭县',\n      621122: '陇西县',\n      621123: '渭源县',\n      621124: '临洮县',\n      621125: '漳县',\n      621126: '岷县'\n    },\n    621200: {\n      621202: '武都区',\n      621221: '成县',\n      621222: '文县',\n      621223: '宕昌县',\n      621224: '康县',\n      621225: '西和县',\n      621226: '礼县',\n      621227: '徽县',\n      621228: '两当县'\n    },\n    622900: {\n      622901: '临夏市',\n      622921: '临夏县',\n      622922: '康乐县',\n      622923: '永靖县',\n      622924: '广河县',\n      622925: '和政县',\n      622926: '东乡族自治县',\n      622927: '积石山保安族东乡族撒拉族自治县'\n    },\n    623000: {\n      623001: '合作市',\n      623021: '临潭县',\n      623022: '卓尼县',\n      623023: '舟曲县',\n      623024: '迭部县',\n      623025: '玛曲县',\n      623026: '碌曲县',\n      623027: '夏河县'\n    },\n    630000: {\n      630100: '西宁市',\n      630200: '海东市',\n      632200: '海北藏族自治州',\n      632300: '黄南藏族自治州',\n      632500: '海南藏族自治州',\n      632600: '果洛藏族自治州',\n      632700: '玉树藏族自治州',\n      632800: '海西蒙古族藏族自治州'\n    },\n    630100: {\n      630102: '城东区',\n      630103: '城中区',\n      630104: '城西区',\n      630105: '城北区',\n      630121: '大通回族土族自治县',\n      630122: '湟中县',\n      630123: '湟源县'\n    },\n    630200: {\n      630202: '乐都区',\n      630203: '平安区',\n      630222: '民和回族土族自治县',\n      630223: '互助土族自治县',\n      630224: '化隆回族自治县',\n      630225: '循化撒拉族自治县'\n    },\n    632200: {\n      632221: '门源回族自治县',\n      632222: '祁连县',\n      632223: '海晏县',\n      632224: '刚察县'\n    },\n    632300: {\n      632321: '同仁县',\n      632322: '尖扎县',\n      632323: '泽库县',\n      632324: '河南蒙古族自治县'\n    },\n    632500: {\n      632521: '共和县',\n      632522: '同德县',\n      632523: '贵德县',\n      632524: '兴海县',\n      632525: '贵南县'\n    },\n    632600: {\n      632621: '玛沁县',\n      632622: '班玛县',\n      632623: '甘德县',\n      632624: '达日县',\n      632625: '久治县',\n      632626: '玛多县'\n    },\n    632700: {\n      632701: '玉树市',\n      632722: '杂多县',\n      632723: '称多县',\n      632724: '治多县',\n      632725: '囊谦县',\n      632726: '曲麻莱县'\n    },\n    632800: {\n      632801: '格尔木市',\n      632802: '德令哈市',\n      632821: '乌兰县',\n      632822: '都兰县',\n      632823: '天峻县',\n      632825: '海西蒙古族藏族自治州直辖'\n    },\n    640000: {\n      640100: '银川市',\n      640200: '石嘴山市',\n      640300: '吴忠市',\n      640400: '固原市',\n      640500: '中卫市'\n    },\n    640100: {\n      640104: '兴庆区',\n      640105: '西夏区',\n      640106: '金凤区',\n      640121: '永宁县',\n      640122: '贺兰县',\n      640181: '灵武市'\n    },\n    640200: {\n      640202: '大武口区',\n      640205: '惠农区',\n      640221: '平罗县'\n    },\n    640300: {\n      640302: '利通区',\n      640303: '红寺堡区',\n      640323: '盐池县',\n      640324: '同心县',\n      640381: '青铜峡市'\n    },\n    640400: {\n      640402: '原州区',\n      640422: '西吉县',\n      640423: '隆德县',\n      640424: '泾源县',\n      640425: '彭阳县'\n    },\n    640500: {\n      640502: '沙坡头区',\n      640521: '中宁县',\n      640522: '海原县'\n    },\n    650000: {\n      650100: '乌鲁木齐市',\n      650200: '克拉玛依市',\n      650400: '吐鲁番市',\n      652200: '哈密地区',\n      652300: '昌吉回族自治州',\n      652700: '博尔塔拉蒙古自治州',\n      652800: '巴音郭楞蒙古自治州',\n      652900: '阿克苏地区',\n      653000: '克孜勒苏柯尔克孜自治州',\n      653100: '喀什地区',\n      653200: '和田地区',\n      654000: '伊犁哈萨克自治州',\n      654200: '塔城地区',\n      654300: '阿勒泰地区',\n      659001: '石河子市',\n      659002: '阿拉尔市',\n      659003: '图木舒克市',\n      659004: '五家渠市',\n      659005: '北屯市',\n      659006: '铁门关市',\n      659007: '双河市',\n      659008: '可克达拉市'\n    },\n    650100: {\n      650102: '天山区',\n      650103: '沙依巴克区',\n      650104: '新市区',\n      650105: '水磨沟区',\n      650106: '头屯河区',\n      650107: '达坂城区',\n      650109: '米东区',\n      650121: '乌鲁木齐县'\n    },\n    650200: {\n      650202: '独山子区',\n      650203: '克拉玛依区',\n      650204: '白碱滩区',\n      650205: '乌尔禾区'\n    },\n    650400: {\n      650402: '高昌区',\n      650421: '鄯善县',\n      650422: '托克逊县'\n    },\n    652200: {\n      652201: '哈密市',\n      652222: '巴里坤哈萨克自治县',\n      652223: '伊吾县'\n    },\n    652300: {\n      652301: '昌吉市',\n      652302: '阜康市',\n      652323: '呼图壁县',\n      652324: '玛纳斯县',\n      652325: '奇台县',\n      652327: '吉木萨尔县',\n      652328: '木垒哈萨克自治县'\n    },\n    652700: {\n      652701: '博乐市',\n      652702: '阿拉山口市',\n      652722: '精河县',\n      652723: '温泉县'\n    },\n    652800: {\n      652801: '库尔勒市',\n      652822: '轮台县',\n      652823: '尉犁县',\n      652824: '若羌县',\n      652825: '且末县',\n      652826: '焉耆回族自治县',\n      652827: '和静县',\n      652828: '和硕县',\n      652829: '博湖县'\n    },\n    652900: {\n      652901: '阿克苏市',\n      652922: '温宿县',\n      652923: '库车县',\n      652924: '沙雅县',\n      652925: '新和县',\n      652926: '拜城县',\n      652927: '乌什县',\n      652928: '阿瓦提县',\n      652929: '柯坪县'\n    },\n    653000: {\n      653001: '阿图什市',\n      653022: '阿克陶县',\n      653023: '阿合奇县',\n      653024: '乌恰县'\n    },\n    653100: {\n      653101: '喀什市',\n      653121: '疏附县',\n      653122: '疏勒县',\n      653123: '英吉沙县',\n      653124: '泽普县',\n      653125: '莎车县',\n      653126: '叶城县',\n      653127: '麦盖提县',\n      653128: '岳普湖县',\n      653129: '伽师县',\n      653130: '巴楚县',\n      653131: '塔什库尔干塔吉克自治县'\n    },\n    653200: {\n      653201: '和田市',\n      653221: '和田县',\n      653222: '墨玉县',\n      653223: '皮山县',\n      653224: '洛浦县',\n      653225: '策勒县',\n      653226: '于田县',\n      653227: '民丰县'\n    },\n    654000: {\n      654002: '伊宁市',\n      654003: '奎屯市',\n      654004: '霍尔果斯市',\n      654021: '伊宁县',\n      654022: '察布查尔锡伯自治县',\n      654023: '霍城县',\n      654024: '巩留县',\n      654025: '新源县',\n      654026: '昭苏县',\n      654027: '特克斯县',\n      654028: '尼勒克县'\n    },\n    654200: {\n      654201: '塔城市',\n      654202: '乌苏市',\n      654221: '额敏县',\n      654223: '沙湾县',\n      654224: '托里县',\n      654225: '裕民县',\n      654226: '和布克赛尔蒙古自治县'\n    },\n    654300: {\n      654301: '阿勒泰市',\n      654321: '布尔津县',\n      654322: '富蕴县',\n      654323: '福海县',\n      654324: '哈巴河县',\n      654325: '青河县',\n      654326: '吉木乃县'\n    },\n    810000: {\n      810001: '中西区',\n      810002: '湾仔区',\n      810003: '东区',\n      810004: '南区',\n      810005: '油尖旺区',\n      810006: '深水埗区',\n      810007: '九龙城区',\n      810008: '黄大仙区',\n      810009: '观塘区',\n      810010: '荃湾区',\n      810011: '屯门区',\n      810012: '元朗区',\n      810013: '北区',\n      810014: '大埔区',\n      810015: '西贡区',\n      810016: '沙田区',\n      810017: '葵青区',\n      810018: '离岛区'\n    },\n    820000: {\n      820001: '花地玛堂区',\n      820002: '花王堂区',\n      820003: '望德堂区',\n      820004: '大堂区',\n      820005: '风顺堂区',\n      820006: '嘉模堂区',\n      820007: '路凼填海区',\n      820008: '圣方济各堂区'\n    }\n  };\n\n  if (typeof window !== 'undefined') {\n    window.ChineseDistricts = ChineseDistricts;\n  }\n\n  return ChineseDistricts;\n\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/province/distpicker.js",
    "content": "/*!\n * Distpicker v1.0.4\n * https://github.com/fengyuanchen/distpicker\n *\n * Copyright (c) 2014-2016 Fengyuan Chen\n * Released under the MIT license\n *\n * Date: 2016-06-01T15:05:52.606Z\n */\n\n(function (factory) {\n  if (typeof define === 'function' && define.amd) {\n    // AMD. Register as anonymous module.\n    define(['jquery', 'ChineseDistricts'], factory);\n  } else if (typeof exports === 'object') {\n    // Node / CommonJS\n    factory(require('jquery'), require('ChineseDistricts'));\n  } else {\n    // Browser globals.\n    factory(jQuery, ChineseDistricts);\n  }\n})(function ($, ChineseDistricts) {\n\n  'use strict';\n\n  if (typeof ChineseDistricts === 'undefined') {\n    throw new Error('The file \"distpicker.data.js\" must be included first!');\n  }\n\n  var NAMESPACE = 'distpicker';\n  var EVENT_CHANGE = 'change.' + NAMESPACE;\n  var PROVINCE = 'province';\n  var CIRY = 'city';\n  var DISTRICT = 'district';\n\n  function Distpicker(element, options) {\n    this.$element = $(element);\n    this.options = $.extend({}, Distpicker.DEFAULTS, $.isPlainObject(options) && options);\n    this.placeholders = $.extend({}, Distpicker.DEFAULTS);\n    this.active = false;\n    this.init();\n  }\n\n  Distpicker.prototype = {\n    constructor: Distpicker,\n\n    init: function () {\n      var options = this.options;\n      var $select = this.$element.find('select');\n      var length = $select.length;\n      var data = {};\n\n      $select.each(function () {\n        $.extend(data, $(this).data());\n      });\n\n      $.each([PROVINCE, CIRY, DISTRICT], $.proxy(function (i, type) {\n        if (data[type]) {\n          options[type] = data[type];\n          this['$' + type] = $select.filter('[data-' + type + ']');\n        } else {\n          this['$' + type] = length > i ? $select.eq(i) : null;\n        }\n      }, this));\n\n      this.bind();\n\n      // Reset all the selects (after event binding)\n      this.reset();\n\n      this.active = true;\n    },\n\n    bind: function () {\n      if (this.$province) {\n        this.$province.on(EVENT_CHANGE, (this._changeProvince = $.proxy(function () {\n          this.output(CIRY);\n          this.output(DISTRICT);\n        }, this)));\n      }\n\n      if (this.$city) {\n        this.$city.on(EVENT_CHANGE, (this._changeCity = $.proxy(function () {\n          this.output(DISTRICT);\n        }, this)));\n      }\n    },\n\n    unbind: function () {\n      if (this.$province) {\n        this.$province.off(EVENT_CHANGE, this._changeProvince);\n      }\n\n      if (this.$city) {\n        this.$city.off(EVENT_CHANGE, this._changeCity);\n      }\n    },\n\n    output: function (type) {\n      var options = this.options;\n      var placeholders = this.placeholders;\n      var $select = this['$' + type];\n      var districts = {};\n      var data = [];\n      var code;\n      var matched;\n      var value;\n\n      if (!$select || !$select.length) {\n        return;\n      }\n\n      value = options[type];\n\n      code = (\n        type === PROVINCE ? 86 :\n        type === CIRY ? this.$province && this.$province.find(':selected').data('code') :\n        type === DISTRICT ? this.$city && this.$city.find(':selected').data('code') : code\n      );\n\n      districts = $.isNumeric(code) ? ChineseDistricts[code] : null;\n\n      if ($.isPlainObject(districts)) {\n        $.each(districts, function (code, address) {\n          var selected = address === value;\n\n          if (selected) {\n            matched = true;\n          }\n\n          data.push({\n            code: code,\n            address: address,\n            selected: selected\n          });\n        });\n      }\n\n      if (!matched) {\n        if (data.length && (options.autoSelect || options.autoselect)) {\n          data[0].selected = true;\n        }\n\n        // Save the unmatched value as a placeholder at the first output\n        if (!this.active && value) {\n          placeholders[type] = value;\n        }\n      }\n\n      // Add placeholder option\n      if (options.placeholder) {\n        data.unshift({\n          code: '',\n          address: placeholders[type],\n          selected: false\n        });\n      }\n\n      $select.html(this.getList(data));\n    },\n\n    getList: function (data) {\n      var list = [];\n\n      $.each(data, function (i, n) {\n        list.push(\n          '<option' +\n          ' value=\"' + (n.address && n.code ? n.address : '') + '\"' +\n          ' data-code=\"' + (n.code || '') + '\"' +\n          (n.selected ? ' selected' : '') +\n          '>' +\n            (n.address || '') +\n          '</option>'\n        );\n      });\n\n      return list.join('');\n    },\n\n    reset: function (deep) {\n      if (!deep) {\n        this.output(PROVINCE);\n        this.output(CIRY);\n        this.output(DISTRICT);\n      } else if (this.$province) {\n        this.$province.find(':first').prop('selected', true).trigger(EVENT_CHANGE);\n      }\n    },\n\n    destroy: function () {\n      this.unbind();\n      this.$element.removeData(NAMESPACE);\n    }\n  };\n\n  Distpicker.DEFAULTS = {\n    autoSelect: true,\n    placeholder: true,\n    province: '—— 省 ——',\n    city: '—— 市 ——',\n    district: '—— 区 ——'\n  };\n\n  Distpicker.setDefaults = function (options) {\n    $.extend(Distpicker.DEFAULTS, options);\n  };\n\n  // Save the other distpicker\n  Distpicker.other = $.fn.distpicker;\n\n  // Register as jQuery plugin\n  $.fn.distpicker = function (option) {\n    var args = [].slice.call(arguments, 1);\n\n    return this.each(function () {\n      var $this = $(this);\n      var data = $this.data(NAMESPACE);\n      var options;\n      var fn;\n\n      if (!data) {\n        if (/destroy/.test(option)) {\n          return;\n        }\n\n        options = $.extend({}, $this.data(), $.isPlainObject(option) && option);\n        $this.data(NAMESPACE, (data = new Distpicker(this, options)));\n      }\n\n      if (typeof option === 'string' && $.isFunction(fn = data[option])) {\n        fn.apply(data, args);\n      }\n    });\n  };\n\n  $.fn.distpicker.Constructor = Distpicker;\n  $.fn.distpicker.setDefaults = Distpicker.setDefaults;\n\n  // No conflict\n  $.fn.distpicker.noConflict = function () {\n    $.fn.distpicker = Distpicker.other;\n    return this;\n  };\n\n  $(function () {\n    $('[data-toggle=\"distpicker\"]').distpicker();\n  });\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/squid.js",
    "content": "/*!\n * Squid 总结、积累、收集的一些基础方法\n * http://www.cnblogs.com/typeof/\n *\n * 所有plugins、swing所做的扩展都是基于Squid对象\n */\n(function(window) {\n    //定义squid\n    var Squid = function() {},\n        slice = Array.prototype.slice,\n        splice = Array.prototype.splice,\n        trim = String.prototype.trim;\n\n    //浅度拷贝\n    Squid.extend = function() {\n        var target = arguments[0],\n            i = 1,\n            length = arguments.length,\n            options,\n            prop;\n\n        if(typeof target !== 'object') {\n            target = {};\n        }\n\n        if(length === i) {\n            target = this;\n            --i;\n        }\n\n        for(; i < length; i++) {\n            if((options = arguments[i]) != null) {\n                for(prop in options) {\n                    target[prop] = options[prop];\n                }\n            }\n        }\n\n        return target;\n    };\n\n    //DOM 方法\n    Squid.extend({\n        getElementById: function(id) {\n            var elem = document.getElementById(id);\n            \n            if(elem && elem.parentNode) {\n                if(elem.id !== id) {\n                    elem = null;\n                    var elems = document.getElementsByTagName(id),\n                        i = 0,\n                        length = elems.length,\n                        cur;\n\n                    for(; i < length; i++) {\n                        cur = elems[i];\n                        if(cur.id === id) {\n                            elem = cur;\n                            break;\n                        }\n                    }\n                }\n                \n                return elem;\n            } \n        },\n        getElementsByTagName: function(tagName, context) {\n            context = context || document;\n\n            var elems = context.getElementsByTagName(tagName),\n                r = [];\n            \n            try {\n                r = slice.call(elems, 0);\n            }catch(e) {\n                var i = 0,\n                    length = elems.length,\n                    elem;\n\n                for(; i < length; i++) {\n                    elem = elems[i];\n                    r.push(elem);\n                }\n            }\n\n            return r;\n        },\n        getElementsByClassName: function(className, context) {\n            //执行上下文，默认为document\n            context = context || document; \n\n            var r = [];\n\n            if(context.getElementsByClassName) {\n                var elems = context.getElementsByClassName(className);\t\t\t\t\n                r = slice.call(elems, 0);\n            }else{\n                var elems,\n                    elem,\n                    i = 0,\n                    length;\n\n                elems = context.getElementsByTagName('*');\t\t\n                length = elems.length;\n                for(; i < length; i++) {\n                    elem = elems[i];\n                    if(elem.className && (\" \" + elem.className + \" \").replace(/[\\t\\n\\r]/g, \" \").indexOf(className) >= 0) {\n                        r.push(elem);\t\n                    }\n                }\n            }\n\n            return r;    \n        },\n        children: function(elem) {\n\n        },\n        first: function(elem) {\n            return this.sibling(elem.firstChild)[0];\t\n        },\n        next: function(elem) {\n            return this.nth(elem, 2, 'nextSibling');\n        },\n        siblings: function(elem) {\n            return this.sibling(elem.parentNode.firstChild, elem); \n        },\n        nth: function(cur, r, dir) {\n            r = r || 1;\n            var i = 0;\n\n            for(; cur; cur = cur[dir]) {\n                if(cur.nodeType === 1 && ++i === r) {\n                    break; \n                }\n            }\n\n            return cur;\n        },\n        sibling: function(n, elem) {\n            var r = [];\n\n            for(; n; n = n.nextSibling) {\n                if(n.nodeType === 1 && n !== elem) {\n                    r.push(n);\t\n                }\t\n            }\n\n            return r;\n        },\n        isVisible: function(elem) {\n            return !this.isHidden(elem); \n        },\n        isHidden: function(elem) {\n            if(elem) {\n                var width = elem.offsetWidth,\n                    height = elem.offsetHeight;\n\n                return (width === 0 && height === 0) || elem.style.display === 'none'\n            } \n        },\n        getOffset: function(elem) {\n            var body = document.body,\n                docElem = document.documentElement;\n\n            if('getBoundingClientRect' in document.documentElement) {\n                var box;\n\n                try {\n                    box = elem.getBoundingClientRect()\n                }catch(e) {}\n\n                if(!box || !elem.parentNode) {\n                    return box ? {top: box.top, left: box.left} : {top: 0, left: 0}\n                }\n\n                var win = window,\n                    clientTop = docElem.clientTop || body.clientTop || 0,\n                    clientLeft = docElem.clientLeft || body.clientLeft || 0,\n                    scrollTop = win.pageYOffset || docElem.scrollTop || body.scrollTop,\n                    scrollLeft = win.pageXOffset || docElem.scrollLeft || body.scrollLeft,\n                    top = box.top + scrollTop - clientTop,\n                    left = box.left + scrollLeft - clientLeft; \n\n                return {top: top, left: left}\n            }else{\n                var offsetParent = elem.offsetParent,\n                    top = elem.offsetTop,\n                    left = elem.offsetLeft;\n\n                while((elem = elem.parentNode) && elem !== body && elem !== docElem) {\n                    if(elem === offsetParent) {\n                        top = elem.offsetTop\n                        left = elem.offsetLeft\n\n                        offsetParent = elem.offsetParent\n                    }\n                }\n\n                return {top: top, left: left}\n            }\n        },\n        position: function(elem) {\n            if(!elem) {\n                return null; \n            }\n\n            var offsetParent = elem.offsetParent,\n                offset = this.getOffset(elem),\n                parentOffset = this.getOffset(offsetParent);\n\n            return {\n                top: offset.top - parentOffset.top,\n                left: offset.left - parentOffset.left\n            };\n        }\n    });\n    \n    //全局缓存对象\n    var cache = {};\n\n    Squid.extend({\n        guid: 1,\n        uuid: 0,\n        expando: 'squid' + (Math.random() + '').replace(/\\D/g, ''),\n        data: function(elem, name) {\n            var internalKey = squid.expando,\n                id,\n                thisCache,\n                r;\n\n            id = elem[squid.expando];\n            if(!id) {\n                elem[squid.expando] = id = ++squid.uuid;\n            }\n            if(!cache[id]) {\n                cache[id] = {};\n            }\n\n            if(typeof name === 'object' || typeof name === 'function') {\n                cache[id][internalKey] = name;\n            }\n\n            thisCache = cache[id];\n\n            if(!thisCache[internalKey]) {\n                thisCache[internalKey] = {};\n            }\n            thisCache = thisCache[internalKey];\n\n            if(name === 'events' && !thisCache[name]) {\n                return thisCache[internalKey] && thisCache[internalKey].events;\n            }\n\n            if(typeof name === 'string') {\n                r = thisCache[name];\n            }else{\n                r = thisCache;\n            }\n\n            return r;\t\t\t\n        },\n        removeData: function(elem, name) {\n            var internalKey = squid.expando,\n                id = elem[squid.expando],\n                internalCache;\n\n            if(!cache[id]) {\n                return;\n            }\n            try{\n                delete cache[id];\n            }catch(e) {\n                cache[id] = null;\n            }\n            if(elem.removeAttribute) {\n                elem.removeAttribute(squid.expando);\n            }else{\n                elem[squid.expando] = null;\n            }\n        }\n    });\n\n    //事件处理\n    Squid.event = {\n        add: function(elem, type, handler) {\n            var elemData,\n            events,\n            eventHandler,\n            handleObj,\n            handlers;\n\n            if(elem.nodeType === 3 || elem.nodeType === 8) {\n                return;\n            }\n            if(!handler) {\n                return;\n            }\n            if(!handler.guid) {\n                handler.guid = squid.guid++;\n            }\n\n            elemData = squid.data(elem);\n            if(!elemData) {\n                return;\n            }\n\n            events = elemData.events;\n            eventHandler = elemData.handle;\n            if(!events) {\n                elemData.events = events = {};\n            }\n\n            if(!eventHandler) {\n                elemData.handle = eventHandler = function(event) {\n                    return squid.event.handle.apply(eventHandler.elem, arguments); \n                };\n                eventHandler.elem = elem;\n            }\n            \n            handleObj = {\n                handler: handler\n            };\n            handleObj.type = type;\n            if(!handleObj.guid) {\n                handleObj.guid = handler.guid;\n            }\n            handlers = events[type];\n            if(!handlers) {\n                handlers = events[type] = [];\n                if(elem.addEventListener) {\n                    elem.addEventListener(type, eventHandler, false);\n                }else if(elem.attachEvent){\n                    elem.attachEvent('on' + type, eventHandler);\n                }\n            }\n\n            handlers.push(handleObj);\n        },\n        remove: function(elem, type, handler) {\n            var elemData,\n                events,\n                eventType,\n                i = 0,\n                handleObj;\n                \n            if(elem.nodeType === 3 || elem.nodeType === 8) {\n                return;\n            }\t\n            \n            elemData = squid.data(elem);\n            events = elemData.events;\n            if(!events) {\n                return;\n            }\n            eventType = events[type] || [];\n            if(!handler) {\n                for(; i < eventType.length; i++) {\n                    handleObj = eventType[i];\n                    squid.event.remove(elem, type, handleObj.handler);\n                    eventType.splice(i--, 1);\n                }\n            }\n        \n            if(eventType.length === 0) {\n                if(elem.removeEventListener) {\n                    elem.removeEventListener(type, elemData.handle, false);\n                }else if(elem.detachEvent) {\n                    elem.detachEvent('on' + type, elemData.handle);\n                }\n            }\n            \n            squid.removeData(elem);\n        },\n        handle: function(event) {\n            var i = 0,\n                length,\n                handlers,\n                handleObj,\n                args = Array.prototype.slice.call(arguments, 0);\n\n            event = squid.event.fix(event);\n            handlers = ((squid.data(this, 'events') || {})[event.type] || []).slice(0);\n\n            args[0] = event;\n\n            length = handlers.length;\n            for(; i < length; i++) {\n                handleObj = handlers[i];\n                event.handler = handleObj.handler;\n                event.handleObj = handleObj;\n\n                handleObj.handler.apply(this, args);\n            }\n        },\n        fix: function(event) {\n            if(!event.target) {\n                event.target = event.srcElement || document;\n            }\n\n            if(event.target.nodeType === 3) {\n                event.target = event.target.parentNode;\n            }\n            \n            if(!event.relateTarget && event.fromElement) {\n                event.relateTarget = event.fromElement === event.target ? event.toElement : event.fromElement;\n            }\n\n            if(!event.preventDefault) {\n                event.preventDefault = function() {\n                    event.returnValue = false;\n                };\n            }\n\n            if(!event.stopPropagation) {\n                event.stopPropagation = function() {\n                    event.cancelBubble = true;\n                };\n            }\n            \n            if(event.pageX == null) {\n                var eventDoc = event.target.ownerDocument || document,\n                    doc = eventDoc.documentElment,\n                    body = eventDoc.body;\n                \n                event.pageX = event.clientX + (doc && document.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);\n                event.pageY = event.clientY + (doc && document.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);\n            }\n\n            return event;\n        }\n    };\n\n    //事件处理\n    Squid.extend({\n        on: function(elem, type, handler) {\n            return this.event.add(elem, type, handler);\t\n        },\n        off: function(elem, type, handler) {\n            return this.event.remove(elem, type, handler);\n        },\n        //把函数放到特定上下文执行\n        proxy: function(fn, context) {\n            var slice = Array.prototype.slice,\n                args = slice.call(arguments, 2),\n            proxy = function() {\n                return fn.apply(context, args.concat(slice.call(arguments))); \n            };\n\n            proxy.guid = fn.guid = fn.guid || proxy.guid || squid.guid++;\n\n            return proxy;\n        }\n    });\n\n    var fnThrottleId = 0;\n    //工具函数\n    Squid.extend({\n        trim: trim ? function(text) {\n            return trim.call(text);\n        } : function(text) {\n            return text.toString().replace(/^\\s+/, '').replace(/\\s+$/, '');\n        },\n        throttle: function(fn, delay, context) {\n            delay = delay || 100;\n            context  = context || null;  \n            \n            return function() {\n                var args = arguments;\n                \n                clearTimeout(fnThrottleId);\n                fnThrottleId = setTimeout(function() {\n                    fn.apply(context, args);\n                }, delay);\n            };\n        },\n        isEmpty: function(obj) {\n            for(var prop in obj) {\n                return false; \n            }\n            \n            return true;\n        }\n    });\n\n    //基于Squid扩展的插件\n    Squid.plugin = function() {};\n    //解决浏览器对默认组件渲染不一样\n    Squid.swing = function() {};    \n    window.squid = Squid;\n})(window);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/swfobject.js",
    "content": "/*\tSWFObject v2.2 <http://code.google.com/p/swfobject/> \n\tis released under the MIT License <http://www.opensource.org/licenses/mit-license.php> \n*/\nvar swfobject=function(){var D=\"undefined\",r=\"object\",S=\"Shockwave Flash\",W=\"ShockwaveFlash.ShockwaveFlash\",q=\"application/x-shockwave-flash\",R=\"SWFObjectExprInst\",x=\"onreadystatechange\",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\\/(\\d+(\\.\\d+)?).*$/,\"$1\")):false,X=!+\"\\v1\",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\\s+(\\S+\\s+\\S+$)/,\"$1\");ag[0]=parseInt(ab.replace(/^(.*)\\..*$/,\"$1\"),10);ag[1]=parseInt(ab.replace(/^.*\\.(.*)\\s.*$/,\"$1\"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,\"$1\"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable(\"$version\");if(ab){X=true;ab=ab.split(\" \")[1].split(\",\");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState==\"complete\")||(typeof j.readyState==D&&(j.getElementsByTagName(\"body\")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener(\"DOMContentLoaded\",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState==\"complete\"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll(\"left\")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName(\"body\")[0].appendChild(C(\"span\"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener(\"load\",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener(\"load\",Y,false)}else{if(typeof O.attachEvent!=D){i(O,\"onload\",Y)}else{if(typeof O.onload==\"function\"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName(\"body\")[0];var aa=C(r);aa.setAttribute(\"type\",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable(\"$version\");if(ab){ab=ab.split(\" \")[1].split(\",\");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute(\"width\")||\"0\";ai.height=ae.getAttribute(\"height\")||\"0\";if(ae.getAttribute(\"class\")){ai.styleclass=ae.getAttribute(\"class\")}if(ae.getAttribute(\"align\")){ai.align=ae.getAttribute(\"align\")}var ah={};var X=ae.getElementsByTagName(\"param\");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute(\"name\").toLowerCase()!=\"movie\"){ah[X[ad].getAttribute(\"name\")]=X[ad].getAttribute(\"value\")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName==\"OBJECT\"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F(\"6.0.65\")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName==\"OBJECT\"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width=\"310\"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height=\"137\"}j.title=j.title.slice(0,47)+\" - Flash Player Installation\";var ad=M.ie&&M.win?\"ActiveX\":\"PlugIn\",ac=\"MMredirectURL=\"+O.location.toString().replace(/&/g,\"%26\")+\"&MMplayerType=\"+ad+\"&MMdoctitle=\"+j.title;if(typeof ab.flashvars!=D){ab.flashvars+=\"&\"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C(\"div\");X+=\"SWFObjectNew\";Y.setAttribute(\"id\",X);ae.parentNode.insertBefore(Y,ae);ae.style.display=\"none\";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C(\"div\");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display=\"none\";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C(\"div\");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName==\"PARAM\")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah=\"\";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()==\"data\"){ag.movie=ai[ae]}else{if(ae.toLowerCase()==\"styleclass\"){ah+=' class=\"'+ai[ae]+'\"'}else{if(ae.toLowerCase()!=\"classid\"){ah+=\" \"+ae+'=\"'+ai[ae]+'\"'}}}}}var af=\"\";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name=\"'+ad+'\" value=\"'+ag[ad]+'\" />'}}aa.outerHTML='<object classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\"'+ah+\">\"+af+\"</object>\";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute(\"type\",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()==\"styleclass\"){Z.setAttribute(\"class\",ai[ac])}else{if(ac.toLowerCase()!=\"classid\"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!=\"movie\"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C(\"param\");aa.setAttribute(\"name\",X);aa.setAttribute(\"value\",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName==\"OBJECT\"){if(M.ie&&M.win){X.style.display=\"none\";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]==\"function\"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(\".\");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName(\"head\")[0];if(!aa){return}var X=(ad&&typeof ad==\"string\")?ad:\"screen\";if(ab){n=null;G=null}if(!n||G!=X){var Z=C(\"style\");Z.setAttribute(\"type\",\"text/css\");Z.setAttribute(\"media\",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+\" {\"+Y+\"}\"))}}}function w(Z,X){if(!m){return}var Y=X?\"visible\":\"hidden\";if(J&&c(Z)){c(Z).style.visibility=Y}else{v(\"#\"+Z,\"visibility:\"+Y)}}function L(Y){var Z=/[\\\\\\\"<>\\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent(\"onunload\",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+=\"\";ag+=\"\";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+=\"&\"+ai+\"=\"+Z[ai]}else{am.flashvars=ai+\"=\"+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\\?/.test(Z)){Z=Z.split(\"?\")[1]}if(aa==null){return L(Z)}var Y=Z.split(\"&\");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf(\"=\"))==aa){return L(Y[X].substring((Y[X].indexOf(\"=\")+1)))}}}return\"\"},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display=\"block\"}}if(E){E(B)}}a=false}}}}();"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/README.md",
    "content": "目录说明\n========================\n\n```bash\n├── Uploader.swf                      # SWF文件，当使用Flash运行时需要引入。\n├\n├── webuploader.js                    # 完全版本。\n├── webuploader.min.js                # min版本\n├\n├── webuploader.flashonly.js          # 只有Flash实现的版本。\n├── webuploader.flashonly.min.js      # min版本\n├\n├── webuploader.html5only.js          # 只有Html5实现的版本。\n├── webuploader.html5only.min.js      # min版本\n├\n├── webuploader.noimage.js            # 去除图片处理的版本，包括HTML5和FLASH.\n├── webuploader.noimage.min.js        # min版本\n├\n├── webuploader.custom.js             # 自定义打包方案，请查看 Gruntfile.js，满足移动端使用。\n└── webuploader.custom.min.js         # min版本\n```\n\n## 示例\n\n请把整个 Git 包下载下来放在 php 服务器下，因为默认提供的文件接受是用 php 编写的，打开 examples 页面便能查看示例效果。"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/cropper/cropper.js",
    "content": "/*!\n * Cropper v0.3.2\n * https://github.com/fengyuanchen/cropper\n *\n * Copyright 2014 Fengyuan Chen\n * Released under the MIT license\n */\n\n(function(factory) {\n    if (typeof define === \"function\" && define.amd) {\n        // AMD. Register as anonymous module.\n        define([\"jquery\"], factory);\n    } else {\n        // Browser globals.\n        factory(jQuery);\n    }\n}(function($) {\n\n    \"use strict\";\n\n    var $window = $(window),\n        Cropper = function(element, options) {\n            options = $.isPlainObject(options) ? options : {};\n            this.$image = $(element);\n            this.defaults = $.extend({}, Cropper.defaults, this.$image.data(), options);\n            this.init();\n        };\n\n    Cropper.prototype = {\n        construstor: Cropper,\n\n        init: function() {\n            this.setAspectRatio(this.defaults.aspectRatio);\n            this.render();\n        },\n\n        render: function(callback) {\n            var that = this,\n                $image = this.$image,\n                $clone,\n                src;\n\n            if (this.active) {\n                return;\n            }\n\n            if (this.$clone) {\n                this.$clone.remove(); // Remove the old clone\n            }\n\n            src = $image.attr(\"src\"); // Don't use \"prop\"\n            $clone = $('<img src=\"' + src + '\">');\n\n            $clone.on(\"load\", function() {\n                var image;\n\n                $clone.off(\"load\");\n\n                if (this.naturalWidth && this.naturalHeight) {\n                    image = {\n                        naturalHeight: this.naturalHeight,\n                        naturalWidth: this.naturalWidth\n                    };\n                } else {\n                    Cropper.fn.size($clone, {\n                        height: \"auto\",\n                        width: \"auto\"\n                    });\n\n                    image = Cropper.fn.size($clone);\n                    image = {\n                        naturalHeight: image.height,\n                        naturalWidth: image.width\n                    };\n                }\n\n                Cropper.fn.size($clone, {\n                    height: \"100%\",\n                    width: \"100%\"\n                });\n\n                image.aspectRatio = image.naturalWidth / image.naturalHeight;\n                that.src = src;\n                that.image = image;\n                that.active = true;\n                that.createCropper();\n            });\n\n            if ($.isFunction(callback)) {\n                $image.on(\"ready.cropper\", callback);\n            }\n\n            this.$clone = $clone;\n            $image.after($clone);\n        },\n\n        unrender: function() {\n            if (this.active) {\n                this.active = false;\n                this.removeCropper();\n                this.src = \"\";\n                this.image = null;\n                this.cropper = null;\n                this.dragger = null;\n            }\n        },\n\n        rerender: function() {\n            this.unrender();\n            this.render();\n        },\n\n        resize: function() {\n            clearTimeout(this.resizing);\n            this.resizing = setTimeout($.proxy(this.rerender, this), 200);\n        },\n\n        createCropper: function() {\n            this.$cropper = $(Cropper.template);\n            this.$dragger = this.$cropper.find(\".cropper-dragger\");\n            Cropper.fn.toggle(this.$image);\n            this.$image.after(this.$cropper);\n            this.$cropper.prepend(this.$clone);\n\n            if (!this.defaults.modal) {\n                Cropper.fn.toggle(this.$cropper.find(\".cropper-modal\"));\n            }\n\n            this.setPreview();\n            this.addListener();\n        },\n\n        removeCropper: function() {\n            this.removeListener();\n            this.$preview = null;\n            this.$clone.remove();\n            this.$clone = null;\n            this.$dragger = null;\n            this.$cropper.remove();\n            this.$cropper = null;\n            Cropper.fn.toggle(this.$image);\n        },\n\n        addListener: function() {\n            this.$cropper.bind(\"mousedown touchstart\", $.proxy(this.dragstart, this));\n            this.$cropper.bind(\"mousemove touchmove\", $.proxy(this.dragmove, this));\n            this.$cropper.bind(\"mouseup mouseleave touchend touchleave\", $.proxy(this.dragend, this));\n            $window.on(\"resize\", $.proxy(this.resize, this));\n        },\n\n        removeListener: function() {\n            this.$cropper.unbind(\"mousedown touchstart\", this.dragstart);\n            this.$cropper.unbind(\"mousemove touchmove\", this.dragmove);\n            this.$cropper.unbind(\"mouseup mouseleave touchend touchleave\", this.dragend);\n            $window.off(\"resize\", this.resize);\n        },\n\n        setPreview: function() {\n            var preview = this.defaults.preview;\n\n            this.$preview = this.$cropper.find(\".cropper-preview\");\n\n            if (typeof preview === \"string\" && preview.length > 0) {\n                this.$preview = this.$preview.add(preview);\n            }\n\n            this.$preview.html('<img src=\"' + this.src + '\">');\n            this.setCropper();\n        },\n\n        setCropper: function() {\n            var $container = this.$image.parent(),\n                container = Cropper.fn.size($container),\n                image = this.image,\n                cropper;\n\n            if (((image.naturalWidth * container.height / image.naturalHeight) - container.width) >= 0) {\n                cropper = {\n                    height: container.width / image.aspectRatio,\n                    width: container.width,\n                    left: 0\n                };\n\n                cropper.top = (container.height - cropper.height) / 2;\n            } else {\n                cropper = {\n                    height: container.height,\n                    width: container.height * image.aspectRatio,\n                    top: 0\n                };\n\n                cropper.left = (container.width - cropper.width) / 2;\n            }\n\n            $.each(cropper, function(i, n) {\n                cropper[i] = Math.round(n);\n            });\n\n            image.height = cropper.height;\n            image.width = cropper.width;\n            image.ratio = image.width / image.naturalWidth;\n\n            Cropper.fn.position($container);\n            this.$cropper.css({\n                height: cropper.height,\n                left: cropper.left,\n                top: cropper.top,\n                width: cropper.width\n            });\n\n            this.cropper = cropper;\n            this.setDragger();\n        },\n\n        setDragger: function() {\n            var cropper = this.cropper,\n                // If not set, use the original aspect ratio of the image.\n                aspectRatio = this.defaults.aspectRatio || this.image.aspectRatio,\n                dragger;\n\n            if (((cropper.height * aspectRatio) - cropper.width) >= 0) {\n                dragger = {\n                    height: cropper.width / aspectRatio,\n                    width: cropper.width,\n                    left: 0,\n                    top: (cropper.height - (cropper.width / aspectRatio)) / 2,\n                    maxWidth: cropper.width,\n                    maxHeight: cropper.width / aspectRatio\n                };\n            } else {\n                dragger = {\n                    height: cropper.height,\n                    width: cropper.height * aspectRatio,\n                    left: (cropper.width - (cropper.height * aspectRatio)) / 2,\n                    top: 0,\n                    maxHeight: cropper.height,\n                    maxWidth: cropper.height * aspectRatio\n                };\n            }\n\n            dragger.height *= 0.8;\n            dragger.width *= 0.8;\n\n            dragger.left = (cropper.width - dragger.width) / 2;\n            dragger.top = (cropper.height - dragger.height) / 2;\n\n            this.dragger = Cropper.fn.round(dragger);\n            this.setData(this.defaults.data);\n            this.$image.trigger(\"ready.cropper\").off(\"ready.cropper\");\n        },\n\n        resetDragger: function() {\n            var dragger = this.dragger,\n                cropper = this.cropper;\n\n            dragger.width = dragger.width > dragger.maxWidth ? dragger.maxWidth : Math.abs(dragger.width);\n            dragger.height = dragger.height > dragger.maxHeight ? dragger.maxHeight : Math.abs(dragger.height);\n\n            dragger.maxLeft = cropper.width - dragger.width;\n            dragger.maxTop = cropper.height - dragger.height;\n\n            dragger.left = dragger.left < 0 ? 0 : dragger.left > dragger.maxLeft ? dragger.maxLeft : dragger.left;\n            dragger.top = dragger.top < 0 ? 0 : dragger.top > dragger.maxTop ? dragger.maxTop : dragger.top;\n\n            dragger = Cropper.fn.round(dragger);\n\n            this.$dragger.css({\n                height: dragger.height,\n                left: dragger.left,\n                top: dragger.top,\n                width: dragger.width\n            });\n\n            this.dragger = dragger;\n            this.preview();\n            this.output();\n        },\n\n        dragging: function() {\n            var direction = this.direction,\n                dragger = this.dragger,\n                aspectRatio = this.defaults.aspectRatio,\n                range = {\n                    x: this.endX - this.startX,\n                    y: this.endY - this.startY\n                };\n\n            if (aspectRatio) {\n                range.X = range.y * aspectRatio;\n                range.Y = range.x / aspectRatio;\n            }\n\n            switch (direction) {\n\n                // dragging\n                case \"e\":\n                    dragger.width += range.x;\n\n                    if (aspectRatio) {\n                        dragger.height = dragger.width / aspectRatio;\n                        dragger.top -= range.Y / 2;\n                    }\n\n                    if (dragger.width < 0) {\n                        this.direction = \"w\";\n                        dragger.width = 0;\n                    }\n\n                    break;\n\n                case \"n\":\n                    dragger.height -= range.y;\n                    dragger.top += range.y;\n\n                    if (aspectRatio) {\n                        dragger.width = dragger.height * aspectRatio;\n                        dragger.left += range.X / 2;\n                    }\n\n                    if (dragger.height < 0) {\n                        this.direction = \"s\";\n                        dragger.height = 0;\n                    }\n\n                    break;\n\n                case \"w\":\n                    dragger.width -= range.x;\n                    dragger.left += range.x;\n\n                    if (aspectRatio) {\n                        dragger.height = dragger.width / aspectRatio;\n                        dragger.top += range.Y / 2;\n                    }\n\n                    if (dragger.width < 0) {\n                        this.direction = \"e\";\n                        dragger.width = 0;\n                    }\n\n                    break;\n\n                case \"s\":\n                    dragger.height += range.y;\n\n                    if (aspectRatio) {\n                        dragger.width = dragger.height * aspectRatio;\n                        dragger.left -= range.X / 2;\n                    }\n\n                    if (dragger.height < 0) {\n                        this.direction = \"n\";\n                        dragger.height = 0;\n                    }\n\n                    break;\n\n                case \"ne\":\n                    dragger.height -= range.y;\n                    dragger.top += range.y;\n\n                    if (aspectRatio) {\n                        dragger.width = dragger.height * aspectRatio;\n                    } else {\n                        dragger.width += range.x;\n                    }\n\n                    if (dragger.height < 0) {\n                        this.direction = \"sw\";\n                        dragger.height = 0;\n                        dragger.width = 0;\n                    }\n\n                    break;\n\n                case \"nw\":\n                    dragger.height -= range.y;\n                    dragger.top += range.y;\n\n                    if (aspectRatio) {\n                        dragger.width = dragger.height * aspectRatio;\n                        dragger.left += range.X;\n                    } else {\n                        dragger.width -= range.x;\n                        dragger.left += range.x;\n                    }\n\n                    if (dragger.height < 0) {\n                        this.direction = \"se\";\n                        dragger.height = 0;\n                        dragger.width = 0;\n                    }\n\n                    break;\n\n                case \"sw\":\n                    dragger.width -= range.x;\n                    dragger.left += range.x;\n\n                    if (aspectRatio) {\n                        dragger.height = dragger.width / aspectRatio;\n                    } else {\n                        dragger.height += range.y;\n                    }\n\n                    if (dragger.width < 0) {\n                        this.direction = \"ne\";\n                        dragger.height = 0;\n                        dragger.width = 0;\n                    }\n\n                    break;\n\n                case \"se\":\n                    dragger.width += range.x;\n\n                    if (aspectRatio) {\n                        dragger.height = dragger.width / aspectRatio;\n                    } else {\n                        dragger.height += range.y;\n                    }\n\n                    if (dragger.width < 0) {\n                        this.direction = \"nw\";\n                        dragger.height = 0;\n                        dragger.width = 0;\n                    }\n\n                    break;\n\n                // moving\n                default:\n                    dragger.left += range.x;\n                    dragger.top += range.y;\n            }\n\n            this.resetDragger();\n            this.startX = this.endX;\n            this.startY = this.endY;\n        },\n\n        output: function() {\n            this.defaults.done(this.getData());\n        },\n\n        preview: function() {\n            var that = this,\n                cropper = that.cropper,\n                dragger = that.dragger;\n\n            this.$preview.each(function() {\n                var $this = $(this),\n                    ratio = $this.outerWidth() / dragger.width,\n                    styles = {\n                        height: cropper.height,\n                        marginLeft: - dragger.left,\n                        marginTop: - dragger.top,\n                        width: cropper.width\n                    };\n\n                $this.css({overflow: \"hidden\"});\n                $this.find(\"img\").css(Cropper.fn.round(styles, function(n) {\n                    return n * ratio;\n                }));\n            });\n        },\n\n        // Public methods\n\n        enable: function(callback) {\n            this.render(callback);\n        },\n\n        disable: function() {\n            this.unrender();\n        },\n\n        setAspectRatio: function(aspectRatio) {\n            if (aspectRatio === \"auto\" || ($.isNumeric(aspectRatio) && aspectRatio > 0)) {\n                this.defaults.aspectRatio = aspectRatio === \"auto\" ? NaN : aspectRatio;\n\n                if (this.active) {\n                    this.setDragger();\n                }\n            }\n        },\n\n        setData: function(data) {\n            var cropper = this.cropper,\n                dragger = this.dragger,\n                aspectRatio = this.defaults.aspectRatio,\n                isNumber = function(n) {\n                    return typeof n === \"number\";\n                };\n\n            if (!this.active) {\n                return;\n            }\n\n            if ($.isPlainObject(data) && !$.isEmptyObject(data)) {\n                data = Cropper.fn.transformData(data, this.image.ratio);\n\n                if (isNumber(data.x1) && data.x1 <= cropper.width) {\n                    dragger.left = data.x1;\n                }\n\n                if (isNumber(data.y1) && data.y1 <= cropper.height) {\n                    dragger.top = data.y1;\n                }\n\n                if (aspectRatio){\n                    if (isNumber(data.width) && data.width <= cropper.width) {\n                        dragger.width = data.width;\n                        dragger.height = dragger.width / aspectRatio;\n                    } else if (isNumber(data.height) && data.height <= cropper.height) {\n                        dragger.height = data.height;\n                        dragger.width = dragger.height * aspectRatio;\n                    } else if (isNumber(data.x2) && data.x2 <= cropper.width) {\n                        dragger.width = data.x2 - dragger.left;\n                        dragger.height = dragger.width / aspectRatio;\n                    } else if (isNumber(data.y2) && data.y2 <= cropper.height) {\n                        dragger.height = data.y2 - dragger.top;\n                        dragger.width = dragger.height * aspectRatio;\n                    }\n                } else {\n                    if (isNumber(data.width) && data.width <= cropper.width) {\n                        dragger.width = data.width;\n                    } else if (isNumber(data.x2) && data.x2 <= cropper.width) {\n                        dragger.width = data.x2 - dragger.left;\n                    }\n\n                    if (isNumber(data.height) && data.height <= cropper.height) {\n                        dragger.height = data.height;\n                    } else if (isNumber(data.y2) && data.height <= cropper.height) {\n                        dragger.height = data.y2 - dragger.top;\n                    }\n                }\n            }\n\n            this.dragger = dragger;\n            this.resetDragger();\n        },\n\n        getData: function() {\n            var dragger = this.dragger,\n                data = {};\n\n            if (this.active) {\n                data = {\n                    x1: dragger.left,\n                    y1: dragger.top,\n                    width: dragger.width,\n                    height: dragger.height,\n                    x2: dragger.left + dragger.width,\n                    y2: dragger.top + dragger.height\n                };\n\n                data = Cropper.fn.transformData(data, (1 / this.image.ratio));\n            }\n\n            return data;\n        },\n\n        setImgSrc: function(src) {\n            if (typeof src === \"string\" && src.length > 0 && src !== this.src) {\n                this.$image.attr(\"src\", src);\n                this.rerender();\n            }\n        },\n\n        getImgInfo: function() {\n            return this.image || {};\n        },\n\n        // Public events\n\n        dragstart: function(event) {\n            var touches = Cropper.fn.getOriginalEvent(event).touches,\n                e = event,\n                touching,\n                direction;\n\n            if (touches && touches.length === 1) {\n                e = touches[0];\n                this.touchId = e.identifier;\n                touching = true;\n            }\n\n            direction = $(e.target).data().direction;\n\n            if (Cropper.fn.isDirection(direction)) {\n                this.startX = e.pageX;\n                this.startY = e.pageY;\n                this.direction = direction;\n                this.$image.trigger(\"dragstart\");\n                touching && event.preventDefault();\n            }\n        },\n\n        dragmove: function(event) {\n            var touches = Cropper.fn.getOriginalEvent(event).changedTouches,\n                e = event,\n                touching;\n\n            if (touches && touches.length === 1) {\n                e = touches[0];\n                touching = true;\n\n                if (e.identifier !== this.touchId) {\n                    return;\n                }\n            }\n\n            if (this.direction) {\n                this.$image.trigger(\"dragmove\");\n                touching && event.preventDefault();\n                this.endX = e.pageX;\n                this.endY = e.pageY;\n                this.dragging();\n            }\n        },\n\n        dragend: function(event) {\n            var touches = Cropper.fn.getOriginalEvent(event).changedTouches,\n                e = event,\n                touching;\n\n            if (touches && touches.length === 1) {\n                e = touches[0];\n                touching = true;\n\n                if (e.identifier !== this.touchId) {\n                    return;\n                }\n            }\n\n            if (this.direction) {\n                this.direction = \"\";\n                this.$image.trigger(\"dragend\");\n                touching && event.preventDefault();\n            }\n        }\n    };\n\n    // Common methods\n    Cropper.fn = {\n        toggle: function($e) {\n            $e.toggleClass(\"cropper-hidden\");\n        },\n\n        position: function($e, option) {\n            var position = $e.css(\"position\");\n\n            if (position === \"static\") {\n                $e.css(\"position\", option || \"relative\");\n            }\n        },\n\n        size: function($e, options) {\n            if ($.isPlainObject(options)) {\n                $e.css(options);\n            } else {\n                return {\n                    height: $e.height(),\n                    width: $e.width()\n                };\n            }\n        },\n\n        round: function(data, fn) {\n            var value,\n                i;\n\n            for (i in data) {\n                value = data[i];\n\n                if (data.hasOwnProperty(i) && typeof value === \"number\") {\n                    data[i] = Math.round($.isFunction(fn) ? fn(value) : value);\n                }\n            }\n\n            return data;\n        },\n\n        transformData: function(data, ratio) {\n            var that = this,\n                result = {};\n\n            $.each(data, function(i, n) {\n                if (that.isDataOption(i) && $.isNumeric(n) && n >= 0) {\n                    result[i] = Math.round(n * ratio);\n                }\n            });\n\n            return result;\n        },\n\n        getOriginalEvent: function(event) {\n            if (event && typeof event.originalEvent !== \"undefined\") {\n               event = event.originalEvent;\n            }\n\n            return event;\n        },\n\n        isDataOption: function(s) {\n            return /^(x1|y1|x2|y2|width|height)$/i.test(s);\n        },\n\n        isDirection: function(s) {\n            return /^(\\*|e|n|w|s|ne|nw|sw|se)$/i.test(s);\n        }\n    };\n\n    Cropper.template = [\n        '<div class=\"cropper-container\">',\n            '<div class=\"cropper-modal\"></div>',\n            '<div class=\"cropper-dragger\">',\n                '<span class=\"cropper-preview\"></span>',\n                '<span class=\"cropper-dashed dashed-h\"></span>',\n                '<span class=\"cropper-dashed dashed-v\"></span>',\n                '<span class=\"cropper-face\" data-direction=\"*\"></span>',\n                '<span class=\"cropper-line line-e\" data-direction=\"e\"></span>',\n                '<span class=\"cropper-line line-n\" data-direction=\"n\"></span>',\n                '<span class=\"cropper-line line-w\" data-direction=\"w\"></span>',\n                '<span class=\"cropper-line line-s\" data-direction=\"s\"></span>',\n                '<span class=\"cropper-point point-e\" data-direction=\"e\"></span>',\n                '<span class=\"cropper-point point-n\" data-direction=\"n\"></span>',\n                '<span class=\"cropper-point point-w\" data-direction=\"w\"></span>',\n                '<span class=\"cropper-point point-s\" data-direction=\"s\"></span>',\n                '<span class=\"cropper-point point-ne\" data-direction=\"ne\"></span>',\n                '<span class=\"cropper-point point-nw\" data-direction=\"nw\"></span>',\n                '<span class=\"cropper-point point-sw\" data-direction=\"sw\"></span>',\n                '<span class=\"cropper-point point-se\" data-direction=\"se\"></span>',\n            '</div>',\n        '</div>'\n    ].join(\"\");\n\n    Cropper.defaults = {\n        aspectRatio: \"auto\",\n        data: {},\n        done: function(/* data */) {},\n        modal: true,\n        preview: \"\"\n    };\n\n    Cropper.setDefaults = function(options) {\n        $.extend(Cropper.defaults, options);\n    };\n\n    // Register as jQuery plugin\n    $.fn.cropper = function(options, settings) {\n        var result = this;\n\n        this.each(function() {\n            var $this = $(this),\n                data = $this.data(\"cropper\");\n\n            if (!data) {\n                data = new Cropper(this, options);\n                $this.data(\"cropper\", data);\n            }\n\n            if (typeof options === \"string\" && $.isFunction(data[options])) {\n                result = data[options](settings);\n            }\n        });\n\n        return (typeof result !== \"undefined\" ? result : this);\n    };\n\n    $.fn.cropper.Constructor = Cropper;\n    $.fn.cropper.setDefaults = Cropper.setDefaults;\n\n    $(function() {\n        $(\"img[cropper]\").cropper();\n    });\n}));\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/cropper/index.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<title>WebUploader演示 - 带裁剪功能</title>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"../webuploader.css\" />\n</head>\n<body>\n<div id=\"wrapper\">\n\t<div class=\"uploader-container\">\n\t\t<div id=\"filePicker\">选择文件</div>\n\t</div>\n\t\n\t<!-- Croper container -->\n\t<div class=\"cropper-wraper webuploader-element-invisible\">\n\t\t<div class=\"img-container\"> <img src=\"\" alt=\"\" /> </div>\n\t\t<div class=\"upload-btn\">上传所选区域</div>\n\t\t<div class=\"img-preview\"></div>\n\t</div>\n</div>\n<script type=\"text/javascript\" src=\"../../../jquery/1.9.1/jquery.min.js\"></script> \n<script type=\"text/javascript\" src=\"../webuploader.min.js\"></script> \n<script type=\"text/javascript\" src=\"cropper.js\"></script> \n<script type=\"text/javascript\" src=\"uploader.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/cropper/uploader.js",
    "content": "(function( factory ) {\n    if ( !window.jQuery ) {\n        alert('jQuery is required.')\n    }\n\n    jQuery(function() {\n        factory.call( null, jQuery );\n    });\n})(function( $ ) {\n\nvar Uploader = (function() {\n\n    // -------setting-------\n    // 如果使用原始大小，超大的图片可能会出现 Croper UI 卡顿，所以这里建议先缩小后再crop.\n    var FRAME_WIDTH = 1600;\n\n\n    var _ = WebUploader;\n    var Uploader = _.Uploader;\n    var uploaderContainer = $('.uploader-container');\n    var uploader, file;\n\n    if ( !Uploader.support() ) {\n        alert( 'Web Uploader 不支持您的浏览器！');\n        throw new Error( 'WebUploader does not support the browser you are using.' );\n    }\n\n    // hook,\n    // 在文件开始上传前进行裁剪。\n    Uploader.register({\n        'before-send-file': 'cropImage'\n    }, {\n\n        cropImage: function( file ) {\n\n            var data = file._cropData,\n                image, deferred;\n\n            file = this.request( 'get-file', file );\n            deferred = _.Deferred();\n\n            image = new _.Lib.Image();\n\n            deferred.always(function() {\n                image.destroy();\n                image = null;\n            });\n            image.once( 'error', deferred.reject );\n            image.once( 'load', function() {\n                image.crop( data.x, data.y, data.width, data.height, data.scale );\n            });\n\n            image.once( 'complete', function() {\n                var blob, size;\n\n                // 移动端 UC / qq 浏览器的无图模式下\n                // ctx.getImageData 处理大图的时候会报 Exception\n                // INDEX_SIZE_ERR: DOM Exception 1\n                try {\n                    blob = image.getAsBlob();\n                    size = file.size;\n                    file.source = blob;\n                    file.size = blob.size;\n\n                    file.trigger( 'resize', blob.size, size );\n\n                    deferred.resolve();\n                } catch ( e ) {\n                    console.log( e );\n                    // 出错了直接继续，让其上传原始图片\n                    deferred.resolve();\n                }\n            });\n\n            file._info && image.info( file._info );\n            file._meta && image.meta( file._meta );\n            image.loadFromBlob( file.source );\n            return deferred.promise();\n        }\n    });\n\n    return {\n        init: function( selectCb ) {\n            uploader = new Uploader({\n                pick: {\n                    id: '#filePicker',\n                    multiple: false\n                },\n\n                // 设置用什么方式去生成缩略图。\n                thumb: {\n                    quality: 70,\n\n                    // 不允许放大\n                    allowMagnify: false,\n\n                    // 是否采用裁剪模式。如果采用这样可以避免空白内容。\n                    crop: false\n                },\n\n                // 禁掉分块传输，默认是开起的。\n                chunked: false,\n\n                // 禁掉上传前压缩功能，因为会手动裁剪。\n                compress: false,\n\n                // fileSingleSizeLimit: 2 * 1024 * 1024,\n\n                server: '../server/fileupload.php',\n                swf: '../Uploader.swf',\n                fileNumLimit: 1,\n                onError: function() {\n                    var args = [].slice.call(arguments, 0);\n                    alert(args.join('\\n'));\n                }\n            });\n\n            uploader.on('fileQueued', function( _file ) {\n                file = _file;\n\n                uploader.makeThumb( file, function( error, src ) {\n\n                    if ( error ) {\n                        alert('不能预览');\n                        return;\n                    }\n\n                    selectCb( src );\n\n                }, FRAME_WIDTH, 1 );   // 注意这里的 height 值是 1，被当成了 100% 使用。\n            });\n        },\n\n        crop: function( data ) {\n\n            var scale = Croper.getImageSize().width / file._info.width;\n            data.scale = scale;\n\n            file._cropData = {\n                x: data.x1,\n                y: data.y1,\n                width: data.width,\n                height: data.height,\n                scale: data.scale\n            };\n        },\n\n        upload: function() {\n            uploader.upload();\n        }\n    }\n})();\n\n\nvar Croper = (function() {\n    var container = $('.cropper-wraper');\n    var $image = container.find('.img-container img');\n    var btn = $('.upload-btn');\n    var isBase64Supported, callback;\n\n    $image.cropper({\n        aspectRatio: 16 / 9,\n        preview: \".img-preview\",\n        done: function(data) {\n            // console.log(data);\n        }\n    });\n\n    function srcWrap( src, cb ) {\n\n        // we need to check this at the first time.\n        if (typeof isBase64Supported === 'undefined') {\n            (function() {\n                var data = new Image();\n                var support = true;\n                data.onload = data.onerror = function() {\n                    if( this.width != 1 || this.height != 1 ) {\n                        support = false;\n                    }\n                }\n                data.src = src;\n                isBase64Supported = support;\n            })();\n        }\n\n        if ( isBase64Supported ) {\n            cb( src );\n        } else {\n            // otherwise we need server support.\n            // convert base64 to a file.\n            $.ajax('../server/preview.php', {\n                method: 'POST',\n                data: src,\n                dataType:'json'\n            }).done(function( response ) {\n                if (response.result) {\n                    cb( response.result );\n                } else {\n                    alert(\"预览出错\");\n                }\n            });\n        }\n    }\n\n    btn.on('click', function() {\n        callback && callback($image.cropper(\"getData\"));\n        return false;\n    });\n\n    return {\n        setSource: function( src ) {\n\n            // 处理 base64 不支持的情况。\n            // 一般出现在 ie6-ie8\n            srcWrap( src, function( src ) {\n                $image.cropper(\"setImgSrc\", src);\n            });\n\n            container.removeClass('webuploader-element-invisible');\n\n            return this;\n        },\n\n        getImageSize: function() {\n            var img = $image.get(0);\n            return {\n                width: img.naturalWidth,\n                height: img.naturalHeight\n            }\n        },\n\n        setCallback: function( cb ) {\n            callback = cb;\n            return this;\n        },\n\n        disable: function() {\n            $image.cropper(\"disable\");\n            return this;\n        },\n\n        enable: function() {\n            $image.cropper(\"enable\");\n            return this;\n        }\n    }\n\n})();\n\n\n\nvar container = $('.uploader-container');\n\nUploader.init(function( src ) {\n\n    Croper.setSource( src );\n\n    // 隐藏选择按钮。\n    container.addClass('webuploader-element-invisible');\n\n    // 当用户选择上传的时候，开始上传。\n    Croper.setCallback(function( data ) {\n        Uploader.crop(data);\n        Uploader.upload();\n    });\n});\n\n});"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/image-upload/index.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<title>WebUploader演示</title>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"../webuploader.css\" />\n</head>\n<body>\n<div class=\"uploader-list-container\">\n\t<div class=\"queueList\">\n\t\t<div id=\"dndArea\" class=\"placeholder\">\n\t\t\t<div id=\"filePicker-2\"></div>\n\t\t\t<p>或将照片拖到这里，单次最多可选300张</p>\n\t\t</div>\n\t</div>\n\t<div class=\"statusBar\" style=\"display:none;\">\n\t\t<div class=\"progress\"> <span class=\"text\">0%</span> <span class=\"percentage\"></span> </div>\n\t\t<div class=\"info\"></div>\n\t\t<div class=\"btns\">\n\t\t\t<div id=\"filePicker2\"></div>\n\t\t\t<div class=\"uploadBtn\">开始上传</div>\n\t\t</div>\n\t</div>\n</div>\n<script type=\"text/javascript\" src=\"../../../jquery/1.9.1/jquery.min.js\"></script> \n<script type=\"text/javascript\" src=\"../webuploader.min.js\"></script> \n<script type=\"text/javascript\" src=\"upload.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/image-upload/upload.js",
    "content": "(function( $ ){\n    // 当domReady的时候开始初始化\n    $(function() {\n        var $wrap = $('.uploader-list-container'),\n\n            // 图片容器\n            $queue = $( '<ul class=\"filelist\"></ul>' )\n                .appendTo( $wrap.find( '.queueList' ) ),\n\n            // 状态栏，包括进度和控制按钮\n            $statusBar = $wrap.find( '.statusBar' ),\n\n            // 文件总体选择信息。\n            $info = $statusBar.find( '.info' ),\n\n            // 上传按钮\n            $upload = $wrap.find( '.uploadBtn' ),\n\n            // 没选择文件之前的内容。\n            $placeHolder = $wrap.find( '.placeholder' ),\n\n            $progress = $statusBar.find( '.progress' ).hide(),\n\n            // 添加的文件数量\n            fileCount = 0,\n\n            // 添加的文件总大小\n            fileSize = 0,\n\n            // 优化retina, 在retina下这个值是2\n            ratio = window.devicePixelRatio || 1,\n\n            // 缩略图大小\n            thumbnailWidth = 110 * ratio,\n            thumbnailHeight = 110 * ratio,\n\n            // 可能有pedding, ready, uploading, confirm, done.\n            state = 'pedding',\n\n            // 所有文件的进度信息，key为file id\n            percentages = {},\n            // 判断浏览器是否支持图片的base64\n            isSupportBase64 = ( function() {\n                var data = new Image();\n                var support = true;\n                data.onload = data.onerror = function() {\n                    if( this.width != 1 || this.height != 1 ) {\n                        support = false;\n                    }\n                }\n                data.src = \"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==\";\n                return support;\n            } )(),\n\n            // 检测是否已经安装flash，检测flash的版本\n            flashVersion = ( function() {\n                var version;\n\n                try {\n                    version = navigator.plugins[ 'Shockwave Flash' ];\n                    version = version.description;\n                } catch ( ex ) {\n                    try {\n                        version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                                .GetVariable('$version');\n                    } catch ( ex2 ) {\n                        version = '0.0';\n                    }\n                }\n                version = version.match( /\\d+/g );\n                return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n            } )(),\n\n            supportTransition = (function(){\n                var s = document.createElement('p').style,\n                    r = 'transition' in s ||\n                            'WebkitTransition' in s ||\n                            'MozTransition' in s ||\n                            'msTransition' in s ||\n                            'OTransition' in s;\n                s = null;\n                return r;\n            })(),\n\n            // WebUploader实例\n            uploader;\n\n        if ( !WebUploader.Uploader.support('flash') && WebUploader.browser.ie ) {\n\n            // flash 安装了但是版本过低。\n            if (flashVersion) {\n                (function(container) {\n                    window['expressinstallcallback'] = function( state ) {\n                        switch(state) {\n                            case 'Download.Cancelled':\n                                alert('您取消了更新！')\n                                break;\n\n                            case 'Download.Failed':\n                                alert('安装失败')\n                                break;\n\n                            default:\n                                alert('安装已成功，请刷新！');\n                                break;\n                        }\n                        delete window['expressinstallcallback'];\n                    };\n\n                    var swf = 'expressInstall.swf';\n                    // insert flash object\n                    var html = '<object type=\"application/' +\n                            'x-shockwave-flash\" data=\"' +  swf + '\" ';\n\n                    if (WebUploader.browser.ie) {\n                        html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                    }\n\n                    html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                        '<param name=\"movie\" value=\"' + swf + '\" />' +\n                        '<param name=\"wmode\" value=\"transparent\" />' +\n                        '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                    '</object>';\n\n                    container.html(html);\n\n                })($wrap);\n\n            // 压根就没有安转。\n            } else {\n                $wrap.html('<a href=\"http://www.adobe.com/go/getflashplayer\" target=\"_blank\" border=\"0\"><img alt=\"get flash player\" src=\"http://www.adobe.com/macromedia/style_guide/images/160x41_Get_Flash_Player.jpg\" /></a>');\n            }\n\n            return;\n        } else if (!WebUploader.Uploader.support()) {\n            alert( 'Web Uploader 不支持您的浏览器！');\n            return;\n        }\n\n        // 实例化\n        uploader = WebUploader.create({\n            pick: {\n                id: '#filePicker-2',\n                label: '点击选择图片'\n            },\n            formData: {\n                uid: 123\n            },\n            dnd: '#dndArea',\n            paste: '#uploader',\n            swf: '../Uploader.swf',\n            chunked: false,\n            chunkSize: 512 * 1024,\n            server: '../server/fileupload.php',\n            // runtimeOrder: 'flash',\n\n            // accept: {\n            //     title: 'Images',\n            //     extensions: 'gif,jpg,jpeg,bmp,png',\n            //     mimeTypes: 'image/*'\n            // },\n\n            // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候，把图片打开。\n            disableGlobalDnd: true,\n            fileNumLimit: 300,\n            fileSizeLimit: 200 * 1024 * 1024,    // 200 M\n            fileSingleSizeLimit: 50 * 1024 * 1024    // 50 M\n        });\n\n        // 拖拽时不接受 js, txt 文件。\n        uploader.on( 'dndAccept', function( items ) {\n            var denied = false,\n                len = items.length,\n                i = 0,\n                // 修改js类型\n                unAllowed = 'text/plain;application/javascript ';\n\n            for ( ; i < len; i++ ) {\n                // 如果在列表里面\n                if ( ~unAllowed.indexOf( items[ i ].type ) ) {\n                    denied = true;\n                    break;\n                }\n            }\n\n            return !denied;\n        });\n\n        uploader.on('dialogOpen', function() {\n            console.log('here');\n        });\n\n        // uploader.on('filesQueued', function() {\n        //     uploader.sort(function( a, b ) {\n        //         if ( a.name < b.name )\n        //           return -1;\n        //         if ( a.name > b.name )\n        //           return 1;\n        //         return 0;\n        //     });\n        // });\n\n        // 添加“添加文件”的按钮，\n        uploader.addButton({\n            id: '#filePicker2',\n            label: '继续添加'\n        });\n\n        uploader.on('ready', function() {\n            window.uploader = uploader;\n        });\n\n        // 当有文件添加进来时执行，负责view的创建\n        function addFile( file ) {\n            var $li = $( '<li id=\"' + file.id + '\">' +\n                    '<p class=\"title\">' + file.name + '</p>' +\n                    '<p class=\"imgWrap\"></p>'+\n                    '<p class=\"progress\"><span></span></p>' +\n                    '</li>' ),\n\n                $btns = $('<div class=\"file-panel\">' +\n                    '<span class=\"cancel\">删除</span>' +\n                    '<span class=\"rotateRight\">向右旋转</span>' +\n                    '<span class=\"rotateLeft\">向左旋转</span></div>').appendTo( $li ),\n                $prgress = $li.find('p.progress span'),\n                $wrap = $li.find( 'p.imgWrap' ),\n                $info = $('<p class=\"error\"></p>'),\n\n                showError = function( code ) {\n                    switch( code ) {\n                        case 'exceed_size':\n                            text = '文件大小超出';\n                            break;\n\n                        case 'interrupt':\n                            text = '上传暂停';\n                            break;\n\n                        default:\n                            text = '上传失败，请重试';\n                            break;\n                    }\n\n                    $info.text( text ).appendTo( $li );\n                };\n\n            if ( file.getStatus() === 'invalid' ) {\n                showError( file.statusText );\n            } else {\n                // @todo lazyload\n                $wrap.text( '预览中' );\n                uploader.makeThumb( file, function( error, src ) {\n                    var img;\n\n                    if ( error ) {\n                        $wrap.text( '不能预览' );\n                        return;\n                    }\n\n                    if( isSupportBase64 ) {\n                        img = $('<img src=\"'+src+'\">');\n                        $wrap.empty().append( img );\n                    } else {\n                        $.ajax('../server/preview.php', {\n                            method: 'POST',\n                            data: src,\n                            dataType:'json'\n                        }).done(function( response ) {\n                            if (response.result) {\n                                img = $('<img src=\"'+response.result+'\">');\n                                $wrap.empty().append( img );\n                            } else {\n                                $wrap.text(\"预览出错\");\n                            }\n                        });\n                    }\n                }, thumbnailWidth, thumbnailHeight );\n\n                percentages[ file.id ] = [ file.size, 0 ];\n                file.rotation = 0;\n            }\n\n            file.on('statuschange', function( cur, prev ) {\n                if ( prev === 'progress' ) {\n                    $prgress.hide().width(0);\n                } else if ( prev === 'queued' ) {\n                    $li.off( 'mouseenter mouseleave' );\n                    $btns.remove();\n                }\n\n                // 成功\n                if ( cur === 'error' || cur === 'invalid' ) {\n                    console.log( file.statusText );\n                    showError( file.statusText );\n                    percentages[ file.id ][ 1 ] = 1;\n                } else if ( cur === 'interrupt' ) {\n                    showError( 'interrupt' );\n                } else if ( cur === 'queued' ) {\n                    percentages[ file.id ][ 1 ] = 0;\n                } else if ( cur === 'progress' ) {\n                    $info.remove();\n                    $prgress.css('display', 'block');\n                } else if ( cur === 'complete' ) {\n                    $li.append( '<span class=\"success\"></span>' );\n                }\n\n                $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur );\n            });\n\n            $li.on( 'mouseenter', function() {\n                $btns.stop().animate({height: 30});\n            });\n\n            $li.on( 'mouseleave', function() {\n                $btns.stop().animate({height: 0});\n            });\n\n            $btns.on( 'click', 'span', function() {\n                var index = $(this).index(),\n                    deg;\n\n                switch ( index ) {\n                    case 0:\n                        uploader.removeFile( file );\n                        return;\n\n                    case 1:\n                        file.rotation += 90;\n                        break;\n\n                    case 2:\n                        file.rotation -= 90;\n                        break;\n                }\n\n                if ( supportTransition ) {\n                    deg = 'rotate(' + file.rotation + 'deg)';\n                    $wrap.css({\n                        '-webkit-transform': deg,\n                        '-mos-transform': deg,\n                        '-o-transform': deg,\n                        'transform': deg\n                    });\n                } else {\n                    $wrap.css( 'filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')');\n                    // use jquery animate to rotation\n                    // $({\n                    //     rotation: rotation\n                    // }).animate({\n                    //     rotation: file.rotation\n                    // }, {\n                    //     easing: 'linear',\n                    //     step: function( now ) {\n                    //         now = now * Math.PI / 180;\n\n                    //         var cos = Math.cos( now ),\n                    //             sin = Math.sin( now );\n\n                    //         $wrap.css( 'filter', \"progid:DXImageTransform.Microsoft.Matrix(M11=\" + cos + \",M12=\" + (-sin) + \",M21=\" + sin + \",M22=\" + cos + \",SizingMethod='auto expand')\");\n                    //     }\n                    // });\n                }\n\n\n            });\n\n            $li.appendTo( $queue );\n        }\n\n        // 负责view的销毁\n        function removeFile( file ) {\n            var $li = $('#'+file.id);\n\n            delete percentages[ file.id ];\n            updateTotalProgress();\n            $li.off().find('.file-panel').off().end().remove();\n        }\n\n        function updateTotalProgress() {\n            var loaded = 0,\n                total = 0,\n                spans = $progress.children(),\n                percent;\n\n            $.each( percentages, function( k, v ) {\n                total += v[ 0 ];\n                loaded += v[ 0 ] * v[ 1 ];\n            } );\n\n            percent = total ? loaded / total : 0;\n\n\n            spans.eq( 0 ).text( Math.round( percent * 100 ) + '%' );\n            spans.eq( 1 ).css( 'width', Math.round( percent * 100 ) + '%' );\n            updateStatus();\n        }\n\n        function updateStatus() {\n            var text = '', stats;\n\n            if ( state === 'ready' ) {\n                text = '选中' + fileCount + '张图片，共' +\n                        WebUploader.formatSize( fileSize ) + '。';\n            } else if ( state === 'confirm' ) {\n                stats = uploader.getStats();\n                if ( stats.uploadFailNum ) {\n                    text = '已成功上传' + stats.successNum+ '张照片至XX相册，'+\n                        stats.uploadFailNum + '张照片上传失败，<a class=\"retry\" href=\"#\">重新上传</a>失败图片或<a class=\"ignore\" href=\"#\">忽略</a>'\n                }\n\n            } else {\n                stats = uploader.getStats();\n                text = '共' + fileCount + '张（' +\n                        WebUploader.formatSize( fileSize )  +\n                        '），已上传' + stats.successNum + '张';\n\n                if ( stats.uploadFailNum ) {\n                    text += '，失败' + stats.uploadFailNum + '张';\n                }\n            }\n\n            $info.html( text );\n        }\n\n        function setState( val ) {\n            var file, stats;\n\n            if ( val === state ) {\n                return;\n            }\n\n            $upload.removeClass( 'state-' + state );\n            $upload.addClass( 'state-' + val );\n            state = val;\n\n            switch ( state ) {\n                case 'pedding':\n                    $placeHolder.removeClass( 'element-invisible' );\n                    $queue.hide();\n                    $statusBar.addClass( 'element-invisible' );\n                    uploader.refresh();\n                    break;\n\n                case 'ready':\n                    $placeHolder.addClass( 'element-invisible' );\n                    $( '#filePicker2' ).removeClass( 'element-invisible');\n                    $queue.show();\n                    $statusBar.removeClass('element-invisible');\n                    uploader.refresh();\n                    break;\n\n                case 'uploading':\n                    $( '#filePicker2' ).addClass( 'element-invisible' );\n                    $progress.show();\n                    $upload.text( '暂停上传' );\n                    break;\n\n                case 'paused':\n                    $progress.show();\n                    $upload.text( '继续上传' );\n                    break;\n\n                case 'confirm':\n                    $progress.hide();\n                    $( '#filePicker2' ).removeClass( 'element-invisible' );\n                    $upload.text( '开始上传' );\n\n                    stats = uploader.getStats();\n                    if ( stats.successNum && !stats.uploadFailNum ) {\n                        setState( 'finish' );\n                        return;\n                    }\n                    break;\n                case 'finish':\n                    stats = uploader.getStats();\n                    if ( stats.successNum ) {\n                        alert( '上传成功' );\n                    } else {\n                        // 没有成功的图片，重设\n                        state = 'done';\n                        location.reload();\n                    }\n                    break;\n            }\n\n            updateStatus();\n        }\n\n        uploader.onUploadProgress = function( file, percentage ) {\n            var $li = $('#'+file.id),\n                $percent = $li.find('.progress span');\n\n            $percent.css( 'width', percentage * 100 + '%' );\n            percentages[ file.id ][ 1 ] = percentage;\n            updateTotalProgress();\n        };\n\n        uploader.onFileQueued = function( file ) {\n            fileCount++;\n            fileSize += file.size;\n\n            if ( fileCount === 1 ) {\n                $placeHolder.addClass( 'element-invisible' );\n                $statusBar.show();\n            }\n\n            addFile( file );\n            setState( 'ready' );\n            updateTotalProgress();\n        };\n\n        uploader.onFileDequeued = function( file ) {\n            fileCount--;\n            fileSize -= file.size;\n\n            if ( !fileCount ) {\n                setState( 'pedding' );\n            }\n\n            removeFile( file );\n            updateTotalProgress();\n\n        };\n\n        uploader.on( 'all', function( type ) {\n            var stats;\n            switch( type ) {\n                case 'uploadFinished':\n                    setState( 'confirm' );\n                    break;\n\n                case 'startUpload':\n                    setState( 'uploading' );\n                    break;\n\n                case 'stopUpload':\n                    setState( 'paused' );\n                    break;\n\n            }\n        });\n\n        uploader.onError = function( code ) {\n            alert( 'Eroor: ' + code );\n        };\n\n        $upload.on('click', function() {\n            if ( $(this).hasClass( 'disabled' ) ) {\n                return false;\n            }\n\n            if ( state === 'ready' ) {\n                uploader.upload();\n            } else if ( state === 'paused' ) {\n                uploader.upload();\n            } else if ( state === 'uploading' ) {\n                uploader.stop();\n            }\n        });\n\n        $info.on( 'click', '.retry', function() {\n            uploader.retry();\n        } );\n\n        $info.on( 'click', '.ignore', function() {\n            alert( 'todo' );\n        } );\n\n        $upload.addClass( 'state-' + state );\n        updateTotalProgress();\n    });\n\n})( jQuery );"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/md5-demo/index.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<head>\n<meta charset=\"utf-8\">\n<title>WebUploader演示 - 带裁剪功能</title>\n<link rel=\"stylesheet\" type=\"text/css\" href=\"../webuploader.css\" />\n</head>\n<body>\n<div id=\"wrapper\">\n\t<div class=\"uploader-container\">\n\t\t<div id=\"filePicker\">html5版本</div>\n\t\t<div id=\"filePicker2\">flash版本</div>\n\t</div>\n\t<div id=\"log\"> <strong>console 会影响 md5 时间的计算，所以在测试 md5 速度的时候，把 console 关了</strong> </div>\n</div>\n<script type=\"text/javascript\" src=\"../../../jquery/1.9.1/jquery.min.js\"></script> \n<script type=\"text/javascript\" src=\"../webuploader.min.js\"></script> \n<script type=\"text/javascript\" src=\"script.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/md5-demo/script.js",
    "content": "(function($) {\n    $(function() {\n        var log = (function() {\n            var dom = $('#log');\n\n            return function( str ) {\n                dom.append('<p>' + str + '</p>')\n            }\n        })();\n\n        WebUploader.create({\n            pick: '#filePicker'\n        }).on('fileQueued', function( file ) {\n            var start =  +new Date();\n\n            // 返回的是 promise 对象\n            this.md5File(file, 0, 1 * 1024 * 1024)\n\n                // 可以用来监听进度\n                .progress(function(percentage) {\n                    // console.log('Percentage:', percentage);\n                })\n\n                // 处理完成后触发\n                .then(function(ret) {\n                    // console.log('md5:', ret);\n                    \n                    var end = +new Date();\n                    log('HTML5: md5 ' + file.name + ' cost ' + (end - start) + 'ms get value: ' + ret);\n                });\n        });\n\n        WebUploader.create({\n            pick: '#filePicker2',\n            swf: '../Uploader.swf',\n            runtimeOrder: 'flash'\n        }).on('fileQueued', function( file ) {\n            var start =  +new Date();\n\n            // 返回的是 promise 对象\n            this.md5File(file, 0, 1 * 1024 * 1024)\n\n                // 可以用来监听进度\n                .progress(function(percentage) {\n                    // console.log('Percentage:', percentage);\n                })\n\n                // 处理完成后触发\n                .then(function(ret) {\n                    // console.log('md5:', ret);\n                    \n                    var end = +new Date();\n                    log('Flash: md5 ' + file.name + ' cost ' + (end - start) + 'ms get value: ' + ret);\n                });\n        });\n    });\n})(jQuery);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/requirejs/app.js",
    "content": "requirejs.config({\n    baseUrl: '../../dist',\n    paths: {\n        jquery: '../examples/image-upload/jquery'\n    }\n});\n\nrequire([ 'webuploader.flashonly' ], function( WebUploader ) {\n    // 当domReady的时候开始初始化\n    $(function() {\n        var $wrap = $('#uploader'),\n\n            // 图片容器\n            $queue = $( '<ul class=\"filelist\"></ul>' )\n                .appendTo( $wrap.find( '.queueList' ) ),\n\n            // 状态栏，包括进度和控制按钮\n            $statusBar = $wrap.find( '.statusBar' ),\n\n            // 文件总体选择信息。\n            $info = $statusBar.find( '.info' ),\n\n            // 上传按钮\n            $upload = $wrap.find( '.uploadBtn' ),\n\n            // 没选择文件之前的内容。\n            $placeHolder = $wrap.find( '.placeholder' ),\n\n            $progress = $statusBar.find( '.progress' ).hide(),\n\n            // 添加的文件数量\n            fileCount = 0,\n\n            // 添加的文件总大小\n            fileSize = 0,\n\n            // 优化retina, 在retina下这个值是2\n            ratio = window.devicePixelRatio || 1,\n\n            // 缩略图大小\n            thumbnailWidth = 110 * ratio,\n            thumbnailHeight = 110 * ratio,\n\n            // 可能有pedding, ready, uploading, confirm, done.\n            state = 'pedding',\n\n            // 所有文件的进度信息，key为file id\n            percentages = {},\n\n            supportTransition = (function(){\n                var s = document.createElement('p').style,\n                    r = 'transition' in s ||\n                          'WebkitTransition' in s ||\n                          'MozTransition' in s ||\n                          'msTransition' in s ||\n                          'OTransition' in s;\n                s = null;\n                return r;\n            })(),\n\n            // WebUploader实例\n            uploader;\n\n        // 实例化\n        uploader = WebUploader.create({\n            pick: {\n                id: '#filePicker',\n                label: '点击选择图片'\n            },\n            dnd: '#dndArea',\n            paste: '#uploader',\n            swf: '../../dist/Uploader.swf',\n            chunked: true,\n            // runtimeOrder: 'flash',\n            sendAsBinary: true,\n            server: '../../server/fileupload.php',\n            // server: 'http://liaoxuezhi.fe.baidu.com/webupload/fileupload.php',\n            // server: 'http://www.2betop.net/fileupload.php',\n            fileNumLimit: 300,\n            fileSizeLimit: 200 * 1024 * 1024,    // 200 M\n            fileSingleSizeLimit: 50 * 1024 * 1024    // 50 M\n        });\n\n        // 添加“添加文件”的按钮，\n        uploader.addButton({\n            id: '#filePicker2',\n            label: '继续添加'\n        });\n\n        // 当有文件添加进来时执行，负责view的创建\n        function addFile( file ) {\n            var $li = $( '<li id=\"' + file.id + '\">' +\n                    '<p class=\"title\">' + file.name + '</p>' +\n                    '<p class=\"imgWrap\"></p>'+\n                    '<p class=\"progress\"><span></span></p>' +\n                    '</li>' ),\n\n                $btns = $('<div class=\"file-panel\">' +\n                    '<span class=\"cancel\">删除</span>' +\n                    '<span class=\"rotateRight\">向右旋转</span>' +\n                    '<span class=\"rotateLeft\">向左旋转</span></div>').appendTo( $li ),\n                $prgress = $li.find('p.progress span'),\n                $wrap = $li.find( 'p.imgWrap' ),\n                $info = $('<p class=\"error\"></p>'),\n\n                showError = function( code ) {\n                    switch( code ) {\n                        case 'exceed_size':\n                            text = '文件大小超出';\n                            break;\n\n                        case 'interrupt':\n                            text = '上传暂停';\n                            break;\n\n                        default:\n                            text = '上传失败，请重试';\n                            break;\n                    }\n\n                    $info.text( text ).appendTo( $li );\n                };\n\n            if ( file.getStatus() === 'invalid' ) {\n                showError( file.statusText );\n            } else {\n                // @todo lazyload\n                $wrap.text( '预览中' );\n                uploader.makeThumb( file, function( error, src ) {\n                    if ( error ) {\n                        $wrap.text( '不能预览' );\n                        return;\n                    }\n\n                    var img = $('<img src=\"'+src+'\">');\n                    $wrap.empty().append( img );\n                }, thumbnailWidth, thumbnailHeight );\n\n                percentages[ file.id ] = [ file.size, 0 ];\n                file.rotation = 0;\n            }\n\n            file.on('statuschange', function( cur, prev ) {\n                if ( prev === 'progress' ) {\n                    $prgress.hide().width(0);\n                } else if ( prev === 'queued' ) {\n                    $li.off( 'mouseenter mouseleave' );\n                    $btns.remove();\n                }\n\n                // 成功\n                if ( cur === 'error' || cur === 'invalid' ) {\n                    console.log( file.statusText );\n                    showError( file.statusText );\n                    percentages[ file.id ][ 1 ] = 1;\n                } else if ( cur === 'interrupt' ) {\n                    showError( 'interrupt' );\n                } else if ( cur === 'queued' ) {\n                    percentages[ file.id ][ 1 ] = 0;\n                } else if ( cur === 'progress' ) {\n                    $info.remove();\n                    $prgress.css('display', 'block');\n                } else if ( cur === 'complete' ) {\n                    $li.append( '<span class=\"success\"></span>' );\n                }\n\n                $li.removeClass( 'state-' + prev ).addClass( 'state-' + cur );\n            });\n\n            $li.on( 'mouseenter', function() {\n                $btns.stop().animate({height: 30});\n            });\n\n            $li.on( 'mouseleave', function() {\n                $btns.stop().animate({height: 0});\n            });\n\n            $btns.on( 'click', 'span', function() {\n                var index = $(this).index(),\n                    deg;\n\n                switch ( index ) {\n                    case 0:\n                        uploader.removeFile( file );\n                        return;\n\n                    case 1:\n                        file.rotation += 90;\n                        break;\n\n                    case 2:\n                        file.rotation -= 90;\n                        break;\n                }\n\n                if ( supportTransition ) {\n                    deg = 'rotate(' + file.rotation + 'deg)';\n                    $wrap.css({\n                        '-webkit-transform': deg,\n                        '-mos-transform': deg,\n                        '-o-transform': deg,\n                        'transform': deg\n                    });\n                } else {\n                    $wrap.css( 'filter', 'progid:DXImageTransform.Microsoft.BasicImage(rotation='+ (~~((file.rotation/90)%4 + 4)%4) +')');\n                    // use jquery animate to rotation\n                    // $({\n                    //     rotation: rotation\n                    // }).animate({\n                    //     rotation: file.rotation\n                    // }, {\n                    //     easing: 'linear',\n                    //     step: function( now ) {\n                    //         now = now * Math.PI / 180;\n\n                    //         var cos = Math.cos( now ),\n                    //             sin = Math.sin( now );\n\n                    //         $wrap.css( 'filter', \"progid:DXImageTransform.Microsoft.Matrix(M11=\" + cos + \",M12=\" + (-sin) + \",M21=\" + sin + \",M22=\" + cos + \",SizingMethod='auto expand')\");\n                    //     }\n                    // });\n                }\n\n\n            });\n\n            $li.appendTo( $queue );\n        }\n\n        // 负责view的销毁\n        function removeFile( file ) {\n            var $li = $('#'+file.id);\n\n            delete percentages[ file.id ];\n            updateTotalProgress();\n            $li.off().find('.file-panel').off().end().remove();\n        }\n\n        function updateTotalProgress() {\n            var loaded = 0,\n                total = 0,\n                spans = $progress.children(),\n                percent;\n\n            $.each( percentages, function( k, v ) {\n                total += v[ 0 ];\n                loaded += v[ 0 ] * v[ 1 ];\n            } );\n\n            percent = total ? loaded / total : 0;\n\n            spans.eq( 0 ).text( Math.round( percent * 100 ) + '%' );\n            spans.eq( 1 ).css( 'width', Math.round( percent * 100 ) + '%' );\n            updateStatus();\n        }\n\n        function updateStatus() {\n            var text = '', stats;\n\n            if ( state === 'ready' ) {\n                text = '选中' + fileCount + '张图片，共' +\n                        WebUploader.formatSize( fileSize ) + '。';\n            } else if ( state === 'confirm' ) {\n                stats = uploader.getStats();\n                if ( stats.uploadFailNum ) {\n                    text = '已成功上传' + stats.successNum+ '张照片至XX相册，'+\n                        stats.uploadFailNum + '张照片上传失败，<a class=\"retry\" href=\"#\">重新上传</a>失败图片或<a class=\"ignore\" href=\"#\">忽略</a>'\n                }\n\n            } else {\n                stats = uploader.getStats();\n                text = '共' + fileCount + '张（' +\n                        WebUploader.formatSize( fileSize )  +\n                        '），已上传' + stats.successNum + '张';\n\n                if ( stats.uploadFailNum ) {\n                    text += '，失败' + stats.uploadFailNum + '张';\n                }\n            }\n\n            $info.html( text );\n        }\n\n        function setState( val ) {\n            var file, stats;\n\n            if ( val === state ) {\n                return;\n            }\n\n            $upload.removeClass( 'state-' + state );\n            $upload.addClass( 'state-' + val );\n            state = val;\n\n            switch ( state ) {\n                case 'pedding':\n                    $placeHolder.removeClass( 'element-invisible' );\n                    $queue.hide();\n                    $statusBar.addClass( 'element-invisible' );\n                    uploader.refresh();\n                    break;\n\n                case 'ready':\n                    $placeHolder.addClass( 'element-invisible' );\n                    $( '#filePicker2' ).removeClass( 'element-invisible');\n                    $queue.show();\n                    $statusBar.removeClass('element-invisible');\n                    uploader.refresh();\n                    break;\n\n                case 'uploading':\n                    $( '#filePicker2' ).addClass( 'element-invisible' );\n                    $progress.show();\n                    $upload.text( '暂停上传' );\n                    break;\n\n                case 'paused':\n                    $progress.show();\n                    $upload.text( '继续上传' );\n                    break;\n\n                case 'confirm':\n                    $progress.hide();\n                    $upload.text( '开始上传' ).addClass( 'disabled' );\n\n                    stats = uploader.getStats();\n                    if ( stats.successNum && !stats.uploadFailNum ) {\n                        setState( 'finish' );\n                        return;\n                    }\n                    break;\n                case 'finish':\n                    stats = uploader.getStats();\n                    if ( stats.successNum ) {\n                        alert( '上传成功' );\n                    } else {\n                        // 没有成功的图片，重设\n                        state = 'done';\n                        location.reload();\n                    }\n                    break;\n            }\n\n            updateStatus();\n        }\n\n        uploader.onUploadProgress = function( file, percentage ) {\n            var $li = $('#'+file.id),\n                $percent = $li.find('.progress span');\n\n            $percent.css( 'width', percentage * 100 + '%' );\n            percentages[ file.id ][ 1 ] = percentage;\n            updateTotalProgress();\n        };\n\n        uploader.onFileQueued = function( file ) {\n            fileCount++;\n            fileSize += file.size;\n\n            if ( fileCount === 1 ) {\n                $placeHolder.addClass( 'element-invisible' );\n                $statusBar.show();\n            }\n\n            addFile( file );\n            setState( 'ready' );\n            updateTotalProgress();\n        };\n\n        uploader.onFileDequeued = function( file ) {\n            fileCount--;\n            fileSize -= file.size;\n\n            if ( !fileCount ) {\n                setState( 'pedding' );\n            }\n\n            removeFile( file );\n            updateTotalProgress();\n\n        };\n\n        uploader.on( 'all', function( type ) {\n            var stats;\n            switch( type ) {\n                case 'uploadFinished':\n                    setState( 'confirm' );\n                    break;\n\n                case 'startUpload':\n                    setState( 'uploading' );\n                    break;\n\n                case 'stopUpload':\n                    setState( 'paused' );\n                    break;\n\n            }\n        });\n\n        uploader.onError = function( code ) {\n            alert( 'Eroor: ' + code );\n        };\n\n        $upload.on('click', function() {\n            if ( $(this).hasClass( 'disabled' ) ) {\n                return false;\n            }\n\n            if ( state === 'ready' ) {\n                uploader.upload();\n            } else if ( state === 'paused' ) {\n                uploader.upload();\n            } else if ( state === 'uploading' ) {\n                uploader.stop();\n            }\n        });\n\n        $info.on( 'click', '.retry', function() {\n            uploader.retry();\n        } );\n\n        $info.on( 'click', '.ignore', function() {\n            alert( 'todo' );\n        } );\n\n        $upload.addClass( 'state-' + state );\n        updateTotalProgress();\n    });\n});"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/requirejs/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title>WebUploader演示</title>\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../../css/webuploader.css\" />\n    <link rel=\"stylesheet\" type=\"text/css\" href=\"../../examples/image-upload/style.css\" />\n</head>\n\n\n<body>\n    <div id=\"wrapper\">\n        <div id=\"container\">\n            <!--头部，相册选择和格式选择-->\n\n            <div id=\"uploader\">\n                <div class=\"queueList\">\n                    <div id=\"dndArea\" class=\"placeholder\">\n                        <div id=\"filePicker\"></div>\n                        <p>或将照片拖到这里，单次最多可选300张</p>\n                    </div>\n                </div>\n                <div class=\"statusBar\" style=\"display:none;\">\n                    <div class=\"progress\">\n                        <span class=\"text\">0%</span>\n                        <span class=\"percentage\"></span>\n                    </div><div class=\"info\"></div>\n                    <div class=\"btns\">\n                        <div id=\"filePicker2\"></div><div class=\"uploadBtn\">开始上传</div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n    <script src=\"./require.js\" data-main=\"app.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/requirejs/require.js",
    "content": "/*\n RequireJS 2.1.10 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.\n Available via the MIT or new BSD license.\n see: http://github.com/jrburke/requirejs for details\n*/\nvar requirejs,require,define;\n(function(ca){function G(b){return\"[object Function]\"===N.call(b)}function H(b){return\"[object Array]\"===N.call(b)}function v(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function U(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function s(b,c){return ga.call(b,c)}function j(b,c){return s(b,c)&&b[c]}function B(b,c){for(var d in b)if(s(b,d)&&c(b[d],d))break}function V(b,c,d,g){c&&B(c,function(c,h){if(d||!s(b,h))g&&\"object\"===typeof c&&c&&!H(c)&&!G(c)&&!(c instanceof\nRegExp)?(b[h]||(b[h]={}),V(b[h],c,d,g)):b[h]=c});return b}function t(b,c){return function(){return c.apply(b,arguments)}}function da(b){throw b;}function ea(b){if(!b)return b;var c=ca;v(b.split(\".\"),function(b){c=c[b]});return c}function C(b,c,d,g){c=Error(c+\"\\nhttp://requirejs.org/docs/errors.html#\"+b);c.requireType=b;c.requireModules=g;d&&(c.originalError=d);return c}function ha(b){function c(a,e,b){var f,n,c,d,g,h,i,I=e&&e.split(\"/\");n=I;var m=l.map,k=m&&m[\"*\"];if(a&&\".\"===a.charAt(0))if(e){n=\nI.slice(0,I.length-1);a=a.split(\"/\");e=a.length-1;l.nodeIdCompat&&R.test(a[e])&&(a[e]=a[e].replace(R,\"\"));n=a=n.concat(a);d=n.length;for(e=0;e<d;e++)if(c=n[e],\".\"===c)n.splice(e,1),e-=1;else if(\"..\"===c)if(1===e&&(\"..\"===n[2]||\"..\"===n[0]))break;else 0<e&&(n.splice(e-1,2),e-=2);a=a.join(\"/\")}else 0===a.indexOf(\"./\")&&(a=a.substring(2));if(b&&m&&(I||k)){n=a.split(\"/\");e=n.length;a:for(;0<e;e-=1){d=n.slice(0,e).join(\"/\");if(I)for(c=I.length;0<c;c-=1)if(b=j(m,I.slice(0,c).join(\"/\")))if(b=j(b,d)){f=b;\ng=e;break a}!h&&(k&&j(k,d))&&(h=j(k,d),i=e)}!f&&h&&(f=h,g=i);f&&(n.splice(0,g,f),a=n.join(\"/\"))}return(f=j(l.pkgs,a))?f:a}function d(a){z&&v(document.getElementsByTagName(\"script\"),function(e){if(e.getAttribute(\"data-requiremodule\")===a&&e.getAttribute(\"data-requirecontext\")===i.contextName)return e.parentNode.removeChild(e),!0})}function g(a){var e=j(l.paths,a);if(e&&H(e)&&1<e.length)return e.shift(),i.require.undef(a),i.require([a]),!0}function u(a){var e,b=a?a.indexOf(\"!\"):-1;-1<b&&(e=a.substring(0,\nb),a=a.substring(b+1,a.length));return[e,a]}function m(a,e,b,f){var n,d,g=null,h=e?e.name:null,l=a,m=!0,k=\"\";a||(m=!1,a=\"_@r\"+(N+=1));a=u(a);g=a[0];a=a[1];g&&(g=c(g,h,f),d=j(p,g));a&&(g?k=d&&d.normalize?d.normalize(a,function(a){return c(a,h,f)}):c(a,h,f):(k=c(a,h,f),a=u(k),g=a[0],k=a[1],b=!0,n=i.nameToUrl(k)));b=g&&!d&&!b?\"_unnormalized\"+(Q+=1):\"\";return{prefix:g,name:k,parentMap:e,unnormalized:!!b,url:n,originalName:l,isDefine:m,id:(g?g+\"!\"+k:k)+b}}function q(a){var e=a.id,b=j(k,e);b||(b=k[e]=new i.Module(a));\nreturn b}function r(a,e,b){var f=a.id,n=j(k,f);if(s(p,f)&&(!n||n.defineEmitComplete))\"defined\"===e&&b(p[f]);else if(n=q(a),n.error&&\"error\"===e)b(n.error);else n.on(e,b)}function w(a,e){var b=a.requireModules,f=!1;if(e)e(a);else if(v(b,function(e){if(e=j(k,e))e.error=a,e.events.error&&(f=!0,e.emit(\"error\",a))}),!f)h.onError(a)}function x(){S.length&&(ia.apply(A,[A.length,0].concat(S)),S=[])}function y(a){delete k[a];delete W[a]}function F(a,e,b){var f=a.map.id;a.error?a.emit(\"error\",a.error):(e[f]=\n!0,v(a.depMaps,function(f,c){var d=f.id,g=j(k,d);g&&(!a.depMatched[c]&&!b[d])&&(j(e,d)?(a.defineDep(c,p[d]),a.check()):F(g,e,b))}),b[f]=!0)}function D(){var a,e,b=(a=1E3*l.waitSeconds)&&i.startTime+a<(new Date).getTime(),f=[],c=[],h=!1,k=!0;if(!X){X=!0;B(W,function(a){var i=a.map,m=i.id;if(a.enabled&&(i.isDefine||c.push(a),!a.error))if(!a.inited&&b)g(m)?h=e=!0:(f.push(m),d(m));else if(!a.inited&&(a.fetched&&i.isDefine)&&(h=!0,!i.prefix))return k=!1});if(b&&f.length)return a=C(\"timeout\",\"Load timeout for modules: \"+\nf,null,f),a.contextName=i.contextName,w(a);k&&v(c,function(a){F(a,{},{})});if((!b||e)&&h)if((z||fa)&&!Y)Y=setTimeout(function(){Y=0;D()},50);X=!1}}function E(a){s(p,a[0])||q(m(a[0],null,!0)).init(a[1],a[2])}function L(a){var a=a.currentTarget||a.srcElement,e=i.onScriptLoad;a.detachEvent&&!Z?a.detachEvent(\"onreadystatechange\",e):a.removeEventListener(\"load\",e,!1);e=i.onScriptError;(!a.detachEvent||Z)&&a.removeEventListener(\"error\",e,!1);return{node:a,id:a&&a.getAttribute(\"data-requiremodule\")}}function M(){var a;\nfor(x();A.length;){a=A.shift();if(null===a[0])return w(C(\"mismatch\",\"Mismatched anonymous define() module: \"+a[a.length-1]));E(a)}}var X,$,i,K,Y,l={waitSeconds:7,baseUrl:\"./\",paths:{},bundles:{},pkgs:{},shim:{},config:{}},k={},W={},aa={},A=[],p={},T={},ba={},N=1,Q=1;K={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?a.exports:a.exports=p[a.map.id]={}},module:function(a){return a.module?a.module:\na.module={id:a.map.id,uri:a.map.url,config:function(){return j(l.config,a.map.id)||{}},exports:K.exports(a)}}};$=function(a){this.events=j(aa,a.id)||{};this.map=a;this.shim=j(l.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};$.prototype={init:function(a,e,b,f){f=f||{};if(!this.inited){this.factory=e;if(b)this.on(\"error\",b);else this.events.error&&(b=t(this,function(a){this.emit(\"error\",a)}));this.depMaps=a&&a.slice(0);this.errback=b;this.inited=\n!0;this.ignore=f.ignore;f.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,e){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=e)},fetch:function(){if(!this.fetched){this.fetched=!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],t(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=\nthis.map.url;T[a]||(T[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,e,b=this.map.id;e=this.depExports;var f=this.exports,c=this.factory;if(this.inited)if(this.error)this.emit(\"error\",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(G(c)){if(this.events.error&&this.map.isDefine||h.onError!==da)try{f=i.execCb(b,c,e,f)}catch(d){a=d}else f=i.execCb(b,c,e,f);this.map.isDefine&&void 0===f&&((e=this.module)?f=e.exports:this.usingExports&&\n(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?\"define\":\"require\",w(this.error=a)}else f=c;this.exports=f;if(this.map.isDefine&&!this.ignore&&(p[b]=f,h.onResourceLoad))h.onResourceLoad(i,this.map,this.depMaps);y(b);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit(\"defined\",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=\nthis.map,b=a.id,d=m(a.prefix);this.depMaps.push(d);r(d,\"defined\",t(this,function(f){var d,g;g=j(ba,this.map.id);var J=this.map.name,u=this.map.parentMap?this.map.parentMap.name:null,p=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(J=f.normalize(J,function(a){return c(a,u,!0)})||\"\"),f=m(a.prefix+\"!\"+J,this.map.parentMap),r(f,\"defined\",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),g=j(k,f.id)){this.depMaps.push(f);\nif(this.events.error)g.on(\"error\",t(this,function(a){this.emit(\"error\",a)}));g.enable()}}else g?(this.map.url=i.nameToUrl(g),this.load()):(d=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),d.error=t(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(k,function(a){0===a.map.id.indexOf(b+\"_unnormalized\")&&y(a.map.id)});w(a)}),d.fromText=t(this,function(f,c){var g=a.name,J=m(g),k=O;c&&(f=c);k&&(O=!1);q(J);s(l.config,b)&&(l.config[g]=l.config[b]);try{h.exec(f)}catch(j){return w(C(\"fromtexteval\",\n\"fromText eval for \"+b+\" failed: \"+j,j,[b]))}k&&(O=!0);this.depMaps.push(J);i.completeLoad(g);p([g],d)}),f.load(a.name,p,d,l))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){W[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,t(this,function(a,b){var c,f;if(\"string\"===typeof a){a=m(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=j(K,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;r(a,\"defined\",t(this,function(a){this.defineDep(b,\na);this.check()}));this.errback&&r(a,\"error\",t(this,this.errback))}c=a.id;f=k[c];!s(K,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,t(this,function(a){var b=j(k,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});\"error\"===a&&delete this.events[a]}};i={config:l,contextName:b,registry:k,defined:p,urlFetched:T,defQueue:A,Module:$,makeModuleMap:m,\nnextTick:h.nextTick,onError:w,configure:function(a){a.baseUrl&&\"/\"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+=\"/\");var b=l.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(l[b]||(l[b]={}),V(l[b],a,!0,!0)):l[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(ba[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),l.shim=b);a.packages&&v(a.packages,function(a){var b,\na=\"string\"===typeof a?{name:a}:a;b=a.name;a.location&&(l.paths[b]=a.location);l.pkgs[b]=a.name+\"/\"+(a.main||\"main\").replace(ja,\"\").replace(R,\"\")});B(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=m(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ca,arguments));return b||a.exports&&ea(a.exports)}},makeRequire:function(a,e){function g(f,c,d){var j,l;e.enableBuildCallback&&(c&&G(c))&&(c.__requireJsBuild=\n!0);if(\"string\"===typeof f){if(G(c))return w(C(\"requireargs\",\"Invalid require call\"),d);if(a&&s(K,f))return K[f](k[a.id]);if(h.get)return h.get(i,f,a,g);j=m(f,a,!1,!0);j=j.id;return!s(p,j)?w(C(\"notloaded\",'Module name \"'+j+'\" has not been loaded yet for context: '+b+(a?\"\":\". Use require([])\"))):p[j]}M();i.nextTick(function(){M();l=q(m(null,a));l.skipMap=e.skipMap;l.init(f,c,d,{enabled:!0});D()});return g}e=e||{};V(g,{isBrowser:z,toUrl:function(b){var e,d=b.lastIndexOf(\".\"),g=b.split(\"/\")[0];if(-1!==\nd&&(!(\".\"===g||\"..\"===g)||1<d))e=b.substring(d,b.length),b=b.substring(0,d);return i.nameToUrl(c(b,a&&a.id,!0),e,!0)},defined:function(b){return s(p,m(b,a,!1,!0).id)},specified:function(b){b=m(b,a,!1,!0).id;return s(p,b)||s(k,b)}});a||(g.undef=function(b){x();var c=m(b,a,!0),e=j(k,b);d(b);delete p[b];delete T[c.url];delete aa[b];U(A,function(a,c){a[0]===b&&A.splice(c,1)});e&&(e.events.defined&&(aa[b]=e.events),y(b))});return g},enable:function(a){j(k,a.id)&&q(a).enable()},completeLoad:function(a){var b,\nc,f=j(l.shim,a)||{},d=f.exports;for(x();A.length;){c=A.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);E(c)}c=j(k,a);if(!b&&!s(p,a)&&c&&!c.inited){if(l.enforceDefine&&(!d||!ea(d)))return g(a)?void 0:w(C(\"nodefine\",\"No define call for \"+a,null,[a]));E([a,f.deps||[],f.exportsFn])}D()},nameToUrl:function(a,b,c){var f,d,g;(f=j(l.pkgs,a))&&(a=f);if(f=j(ba,a))return i.nameToUrl(f,b,c);if(h.jsExtRegExp.test(a))f=a+(b||\"\");else{f=l.paths;a=a.split(\"/\");for(d=a.length;0<d;d-=1)if(g=a.slice(0,\nd).join(\"/\"),g=j(f,g)){H(g)&&(g=g[0]);a.splice(0,d,g);break}f=a.join(\"/\");f+=b||(/^data\\:|\\?/.test(f)||c?\"\":\".js\");f=(\"/\"===f.charAt(0)||f.match(/^[\\w\\+\\.\\-]+:/)?\"\":l.baseUrl)+f}return l.urlArgs?f+((-1===f.indexOf(\"?\")?\"?\":\"&\")+l.urlArgs):f},load:function(a,b){h.load(i,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if(\"load\"===a.type||ka.test((a.currentTarget||a.srcElement).readyState))P=null,a=L(a),i.completeLoad(a.id)},onScriptError:function(a){var b=L(a);if(!g(b.id))return w(C(\"scripterror\",\n\"Script error for: \"+b.id,a,[b.id]))}};i.require=i.makeRequire();return i}var h,x,y,D,L,E,P,M,q,Q,la=/(\\/\\*([\\s\\S]*?)\\*\\/|([^:]|^)\\/\\/(.*)$)/mg,ma=/[^.]\\s*require\\s*\\(\\s*[\"']([^'\"\\s]+)[\"']\\s*\\)/g,R=/\\.js$/,ja=/^\\.\\//;x=Object.prototype;var N=x.toString,ga=x.hasOwnProperty,ia=Array.prototype.splice,z=!!(\"undefined\"!==typeof window&&\"undefined\"!==typeof navigator&&window.document),fa=!z&&\"undefined\"!==typeof importScripts,ka=z&&\"PLAYSTATION 3\"===navigator.platform?/^complete$/:/^(complete|loaded)$/,\nZ=\"undefined\"!==typeof opera&&\"[object Opera]\"===opera.toString(),F={},r={},S=[],O=!1;if(\"undefined\"===typeof define){if(\"undefined\"!==typeof requirejs){if(G(requirejs))return;r=requirejs;requirejs=void 0}\"undefined\"!==typeof require&&!G(require)&&(r=require,require=void 0);h=requirejs=function(b,c,d,g){var u,m=\"_\";!H(b)&&\"string\"!==typeof b&&(u=b,H(c)?(b=c,c=d,d=g):b=[]);u&&u.context&&(m=u.context);(g=j(F,m))||(g=F[m]=h.s.newContext(m));u&&g.configure(u);return g.require(b,c,d)};h.config=function(b){return h(b)};\nh.nextTick=\"undefined\"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=h);h.version=\"2.1.10\";h.jsExtRegExp=/^\\/|:|\\?|\\.js$/;h.isBrowser=z;x=h.s={contexts:F,newContext:ha};h({});v([\"toUrl\",\"undef\",\"defined\",\"specified\"],function(b){h[b]=function(){var c=F._;return c.require[b].apply(c,arguments)}});if(z&&(y=x.head=document.getElementsByTagName(\"head\")[0],D=document.getElementsByTagName(\"base\")[0]))y=x.head=D.parentNode;h.onError=da;h.createNode=function(b){var c=\nb.xhtml?document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"html:script\"):document.createElement(\"script\");c.type=b.scriptType||\"text/javascript\";c.charset=\"utf-8\";c.async=!0;return c};h.load=function(b,c,d){var g=b&&b.config||{};if(z)return g=h.createNode(g,c,d),g.setAttribute(\"data-requirecontext\",b.contextName),g.setAttribute(\"data-requiremodule\",c),g.attachEvent&&!(g.attachEvent.toString&&0>g.attachEvent.toString().indexOf(\"[native code\"))&&!Z?(O=!0,g.attachEvent(\"onreadystatechange\",b.onScriptLoad)):\n(g.addEventListener(\"load\",b.onScriptLoad,!1),g.addEventListener(\"error\",b.onScriptError,!1)),g.src=d,M=g,D?y.insertBefore(g,D):y.appendChild(g),M=null,g;if(fa)try{importScripts(d),b.completeLoad(c)}catch(j){b.onError(C(\"importscripts\",\"importScripts failed for \"+c+\" at \"+d,j,[c]))}};z&&!r.skipDataMain&&U(document.getElementsByTagName(\"script\"),function(b){y||(y=b.parentNode);if(L=b.getAttribute(\"data-main\"))return q=L,r.baseUrl||(E=q.split(\"/\"),q=E.pop(),Q=E.length?E.join(\"/\")+\"/\":\"./\",r.baseUrl=\nQ),q=q.replace(R,\"\"),h.jsExtRegExp.test(q)&&(q=L),r.deps=r.deps?r.deps.concat(q):[q],!0});define=function(b,c,d){var g,h;\"string\"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(la,\"\").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?[\"require\"]:[\"require\",\"exports\",\"module\"]).concat(c)));if(O){if(!(g=M))P&&\"interactive\"===P.readyState||U(document.getElementsByTagName(\"script\"),function(b){if(\"interactive\"===b.readyState)return P=b}),g=P;g&&(b||\n(b=g.getAttribute(\"data-requiremodule\")),h=F[g.getAttribute(\"data-requirecontext\")])}(h?h.defQueue:S).push([b,c,d])};define.amd={jQuery:!0};h.exec=function(b){return eval(b)};h(r)}})(this);\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/server/crossdomain.xml",
    "content": "<?xml version=\"1.0\" ?>\n<cross-domain-policy>\n<allow-access-from domain=\"*\" />\n</cross-domain-policy>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/server/fileupload.php",
    "content": "<?php\n/**\n * upload.php\n *\n * Copyright 2013, Moxiecode Systems AB\n * Released under GPL License.\n *\n * License: http://www.plupload.com/license\n * Contributing: http://www.plupload.com/contributing\n */\n\n#!! 注意\n#!! 此文件只是个示例，不要用于真正的产品之中。\n#!! 不保证代码安全性。\n\n#!! IMPORTANT:\n#!! this file is just an example, it doesn't incorporate any security checks and\n#!! is not recommended to be used in production environment as it is. Be sure to\n#!! revise it and customize to your needs.\n\n\n// Make sure file is not cached (as it happens for example on iOS devices)\nheader(\"Expires: Mon, 26 Jul 1997 05:00:00 GMT\");\nheader(\"Last-Modified: \" . gmdate(\"D, d M Y H:i:s\") . \" GMT\");\nheader(\"Cache-Control: no-store, no-cache, must-revalidate\");\nheader(\"Cache-Control: post-check=0, pre-check=0\", false);\nheader(\"Pragma: no-cache\");\n\n\n// Support CORS\n// header(\"Access-Control-Allow-Origin: *\");\n// other CORS headers if any...\nif ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {\n    exit; // finish preflight CORS requests here\n}\n\n\nif ( !empty($_REQUEST[ 'debug' ]) ) {\n    $random = rand(0, intval($_REQUEST[ 'debug' ]) );\n    if ( $random === 0 ) {\n        header(\"HTTP/1.0 500 Internal Server Error\");\n        exit;\n    }\n}\n\n// header(\"HTTP/1.0 500 Internal Server Error\");\n// exit;\n\n\n// 5 minutes execution time\n@set_time_limit(5 * 60);\n\n// Uncomment this one to fake upload time\n// usleep(5000);\n\n// Settings\n// $targetDir = ini_get(\"upload_tmp_dir\") . DIRECTORY_SEPARATOR . \"plupload\";\n$targetDir = 'upload_tmp';\n$uploadDir = 'upload';\n\n$cleanupTargetDir = true; // Remove old files\n$maxFileAge = 5 * 3600; // Temp file age in seconds\n\n\n// Create target dir\nif (!file_exists($targetDir)) {\n    @mkdir($targetDir);\n}\n\n// Create target dir\nif (!file_exists($uploadDir)) {\n    @mkdir($uploadDir);\n}\n\n// Get a file name\nif (isset($_REQUEST[\"name\"])) {\n    $fileName = $_REQUEST[\"name\"];\n} elseif (!empty($_FILES)) {\n    $fileName = $_FILES[\"file\"][\"name\"];\n} else {\n    $fileName = uniqid(\"file_\");\n}\n\n$filePath = $targetDir . DIRECTORY_SEPARATOR . $fileName;\n$uploadPath = $uploadDir . DIRECTORY_SEPARATOR . $fileName;\n\n// Chunking might be enabled\n$chunk = isset($_REQUEST[\"chunk\"]) ? intval($_REQUEST[\"chunk\"]) : 0;\n$chunks = isset($_REQUEST[\"chunks\"]) ? intval($_REQUEST[\"chunks\"]) : 1;\n\n\n// Remove old temp files\nif ($cleanupTargetDir) {\n    if (!is_dir($targetDir) || !$dir = opendir($targetDir)) {\n        die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 100, \"message\": \"Failed to open temp directory.\"}, \"id\" : \"id\"}');\n    }\n\n    while (($file = readdir($dir)) !== false) {\n        $tmpfilePath = $targetDir . DIRECTORY_SEPARATOR . $file;\n\n        // If temp file is current file proceed to the next\n        if ($tmpfilePath == \"{$filePath}_{$chunk}.part\" || $tmpfilePath == \"{$filePath}_{$chunk}.parttmp\") {\n            continue;\n        }\n\n        // Remove temp file if it is older than the max age and is not the current file\n        if (preg_match('/\\.(part|parttmp)$/', $file) && (@filemtime($tmpfilePath) < time() - $maxFileAge)) {\n            @unlink($tmpfilePath);\n        }\n    }\n    closedir($dir);\n}\n\n\n// Open temp file\nif (!$out = @fopen(\"{$filePath}_{$chunk}.parttmp\", \"wb\")) {\n    die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 102, \"message\": \"Failed to open output stream.\"}, \"id\" : \"id\"}');\n}\n\nif (!empty($_FILES)) {\n    if ($_FILES[\"file\"][\"error\"] || !is_uploaded_file($_FILES[\"file\"][\"tmp_name\"])) {\n        die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 103, \"message\": \"Failed to move uploaded file.\"}, \"id\" : \"id\"}');\n    }\n\n    // Read binary input stream and append it to temp file\n    if (!$in = @fopen($_FILES[\"file\"][\"tmp_name\"], \"rb\")) {\n        die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 101, \"message\": \"Failed to open input stream.\"}, \"id\" : \"id\"}');\n    }\n} else {\n    if (!$in = @fopen(\"php://input\", \"rb\")) {\n        die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 101, \"message\": \"Failed to open input stream.\"}, \"id\" : \"id\"}');\n    }\n}\n\nwhile ($buff = fread($in, 4096)) {\n    fwrite($out, $buff);\n}\n\n@fclose($out);\n@fclose($in);\n\nrename(\"{$filePath}_{$chunk}.parttmp\", \"{$filePath}_{$chunk}.part\");\n\n$index = 0;\n$done = true;\nfor( $index = 0; $index < $chunks; $index++ ) {\n    if ( !file_exists(\"{$filePath}_{$index}.part\") ) {\n        $done = false;\n        break;\n    }\n}\nif ( $done ) {\n    if (!$out = @fopen($uploadPath, \"wb\")) {\n        die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 102, \"message\": \"Failed to open output stream.\"}, \"id\" : \"id\"}');\n    }\n\n    if ( flock($out, LOCK_EX) ) {\n        for( $index = 0; $index < $chunks; $index++ ) {\n            if (!$in = @fopen(\"{$filePath}_{$index}.part\", \"rb\")) {\n                break;\n            }\n\n            while ($buff = fread($in, 4096)) {\n                fwrite($out, $buff);\n            }\n\n            @fclose($in);\n            @unlink(\"{$filePath}_{$index}.part\");\n        }\n\n        flock($out, LOCK_UN);\n    }\n    @fclose($out);\n}\n\n// Return Success JSON-RPC response\ndie('{\"jsonrpc\" : \"2.0\", \"result\" : null, \"id\" : \"id\"}');"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/server/fileupload2.php",
    "content": "<?php\n/**\n * upload.php\n *\n * Copyright 2013, Moxiecode Systems AB\n * Released under GPL License.\n *\n * License: http://www.plupload.com/license\n * Contributing: http://www.plupload.com/contributing\n */\n\n#!! IMPORTANT:\n#!! this file is just an example, it doesn't incorporate any security checks and\n#!! is not recommended to be used in production environment as it is. Be sure to\n#!! revise it and customize to your needs.\n\n\n// Make sure file is not cached (as it happens for example on iOS devices)\nheader(\"Expires: Mon, 26 Jul 1997 05:00:00 GMT\");\nheader(\"Last-Modified: \" . gmdate(\"D, d M Y H:i:s\") . \" GMT\");\nheader(\"Cache-Control: no-store, no-cache, must-revalidate\");\nheader(\"Cache-Control: post-check=0, pre-check=0\", false);\nheader(\"Pragma: no-cache\");\n\n// header(\"HTTP/1.0 500 Internal Server Error\");\n\n// echo mymd5('upload/C程序设计语言.pdf'); die;\n// Support CORS\n// header(\"Access-Control-Allow-Origin: *\");\n// other CORS headers if any...\nif ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {\n    exit; // finish preflight CORS requests here\n}\n\n\nif ( !empty($_REQUEST[ 'debug' ]) ) {\n    $random = rand(0, intval($_REQUEST[ 'debug' ]) );\n    if ( $random === 0 ) {\n        header(\"HTTP/1.0 500 Internal Server Error\");\n        exit;\n    }\n}\n\n\n// 5 minutes execution time\n@set_time_limit(5 * 60);\n\n// Uncomment this one to fake upload time\n// usleep(5000);\n\n// Settings\n// $targetDir = ini_get(\"upload_tmp_dir\") . DIRECTORY_SEPARATOR . \"plupload\";\n$targetDir = 'upload_tmp';\n$uploadDir = 'upload';\n\n$cleanupTargetDir = true; // Remove old files\n$maxFileAge = 5 * 3600; // Temp file age in seconds\n\n\n// Create target dir\nif (!file_exists($targetDir)) {\n    @mkdir($targetDir);\n}\n\n// Create target dir\nif (!file_exists($uploadDir)) {\n    @mkdir($uploadDir);\n}\n\n// Get a file name\nif (isset($_REQUEST[\"name\"])) {\n    $fileName = $_REQUEST[\"name\"];\n} elseif (!empty($_FILES)) {\n    $fileName = $_FILES[\"file\"][\"name\"];\n} else {\n    $fileName = uniqid(\"file_\");\n}\n\n$md5File = @file('md5list2.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);\n$md5File = $md5File ? $md5File : array();\n\nif (isset($_REQUEST[\"md5\"]) && array_search($_REQUEST[\"md5\"], $md5File ) !== FALSE ) {\n    die('{\"jsonrpc\" : \"2.0\", \"result\" : null, \"id\" : \"id\", \"exist\": 1}');\n}\n\n$filePath = $targetDir . DIRECTORY_SEPARATOR . $fileName;\n$uploadPath = $uploadDir . DIRECTORY_SEPARATOR . $fileName;\n\n// Chunking might be enabled\n$chunk = isset($_REQUEST[\"chunk\"]) ? intval($_REQUEST[\"chunk\"]) : 0;\n$chunks = isset($_REQUEST[\"chunks\"]) ? intval($_REQUEST[\"chunks\"]) : 0;\n\n\n// Remove old temp files\nif ($cleanupTargetDir) {\n    if (!is_dir($targetDir) || !$dir = opendir($targetDir)) {\n        die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 100, \"message\": \"Failed to open temp directory.\"}, \"id\" : \"id\"}');\n    }\n\n    while (($file = readdir($dir)) !== false) {\n        $tmpfilePath = $targetDir . DIRECTORY_SEPARATOR . $file;\n\n        // If temp file is current file proceed to the next\n        if ($tmpfilePath == \"{$filePath}.part\") {\n            continue;\n        }\n\n        // Remove temp file if it is older than the max age and is not the current file\n        if (preg_match('/\\.part$/', $file) && (filemtime($tmpfilePath) < time() - $maxFileAge)) {\n            @unlink($tmpfilePath);\n        }\n    }\n    closedir($dir);\n}\n\n\n// Open temp file\nif (!$out = @fopen(\"{$filePath}.part\", $chunks ? \"ab\" : \"wb\")) {\n    die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 102, \"message\": \"Failed to open output stream.\"}, \"id\" : \"id\"}');\n}\n\nif (!empty($_FILES)) {\n    if ($_FILES[\"file\"][\"error\"] || !is_uploaded_file($_FILES[\"file\"][\"tmp_name\"])) {\n        die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 103, \"message\": \"Failed to move uploaded file.\"}, \"id\" : \"id\"}');\n    }\n\n    // Read binary input stream and append it to temp file\n    if (!$in = @fopen($_FILES[\"file\"][\"tmp_name\"], \"rb\")) {\n        die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 101, \"message\": \"Failed to open input stream.\"}, \"id\" : \"id\"}');\n    }\n} else {\n    if (!$in = @fopen(\"php://input\", \"rb\")) {\n        die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 101, \"message\": \"Failed to open input stream.\"}, \"id\" : \"id\"}');\n    }\n}\n\nwhile ($buff = fread($in, 4096)) {\n    fwrite($out, $buff);\n}\n\n@fclose($out);\n@fclose($in);\n\n// Check if file has been uploaded\nif (!$chunks || $chunk == $chunks - 1) {\n    // Strip the temp .part suffix off\n    rename(\"{$filePath}.part\", $filePath);\n\n    rename($filePath, $uploadPath);\n    array_push($md5File, mymd5($uploadPath));\n    $md5File = array_unique($md5File);\n    file_put_contents('md5list2.txt', join($md5File, \"\\n\"));\n}\n\nfunction mymd5( $file ) {\n    $fragment = 65536;\n\n    $rh = fopen($file, 'rb');\n    $size = filesize($file);\n\n    $part1 = fread( $rh, $fragment );\n    fseek($rh, $size-$fragment);\n    $part2 = fread( $rh, $fragment);\n    fclose($rh);\n\n    return md5( $part1.$part2 );\n}\n\n\n\n// Return Success JSON-RPC response\ndie('{\"jsonrpc\" : \"2.0\", \"result\" : null, \"id\" : \"id\"}');"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/server/preview.php",
    "content": "<?php\n/**\n * 此页面用来协助 IE6/7 预览图片，因为 IE 6/7 不支持 base64\n */\n\n$DIR = 'preview';\n// Create target dir\nif (!file_exists($DIR)) {\n    @mkdir($DIR);\n}\n\n$cleanupTargetDir = true; // Remove old files\n$maxFileAge = 5 * 3600; // Temp file age in seconds\n\nif ($cleanupTargetDir) {\n    if (!is_dir($DIR) || !$dir = opendir($DIR)) {\n        die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 100, \"message\": \"Failed to open temp directory.\"}, \"id\" : \"id\"}');\n    }\n\n    while (($file = readdir($dir)) !== false) {\n        $tmpfilePath = $DIR . DIRECTORY_SEPARATOR . $file;\n\n        // Remove temp file if it is older than the max age and is not the current file\n        if (@filemtime($tmpfilePath) < time() - $maxFileAge) {\n            @unlink($tmpfilePath);\n        }\n    }\n    closedir($dir);\n}\n\n$src = file_get_contents('php://input');\n\nif (preg_match(\"#^data:image/(\\w+);base64,(.*)$#\", $src, $matches)) {\n\n    $previewUrl = sprintf(\n        \"%s://%s%s\",\n        isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http',\n        $_SERVER['HTTP_HOST'],\n        $_SERVER['REQUEST_URI']\n    );\n    $previewUrl = str_replace(\"preview.php\", \"\", $previewUrl);\n\n\n    $base64 = $matches[2];\n    $type = $matches[1];\n    if ($type === 'jpeg') {\n        $type = 'jpg';\n    }\n\n    $filename = md5($base64).\".$type\";\n    $filePath = $DIR.DIRECTORY_SEPARATOR.$filename;\n\n    if (file_exists($filePath)) {\n        die('{\"jsonrpc\" : \"2.0\", \"result\" : \"'.$previewUrl.'preview/'.$filename.'\", \"id\" : \"id\"}');\n    } else {\n        $data = base64_decode($base64);\n        file_put_contents($filePath, $data);\n        die('{\"jsonrpc\" : \"2.0\", \"result\" : \"'.$previewUrl.'preview/'.$filename.'\", \"id\" : \"id\"}');\n    }\n\n} else {\n    die('{\"jsonrpc\" : \"2.0\", \"error\" : {\"code\": 100, \"message\": \"un recoginized source\"}}');\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/webuploader.css",
    "content": ".webuploader-container{position: relative; display:inline-block; vertical-align:top}\n.webuploader-element-invisible{position: absolute !important;clip: rect(1px 1px 1px 1px);/* IE6, IE7*/clip: rect(1px,1px,1px,1px)}\n.webuploader-pick{position: relative;display: inline-block;cursor: pointer;background:#3bb4f2;padding:4px 12px;color: #fff;text-align: center;border-radius: 3px;overflow: hidden}\n.webuploader-pick-hover{background: #00a2d4}\n.webuploader-pick-disable{opacity: 0.6;pointer-events:none}\n.uploader-list{width: 100%;overflow: hidden}\n.btn-uploadstar{vertical-align:top}\n.file-item{float: left;position: relative;margin: 0 20px 20px 0;padding: 4px}\n.file-item .error{position: absolute;top: 4px;left: 4px;right: 4px;background: red;color: white;text-align: center;height: 20px;font-size: 14px;line-height: 23px}\n.file-item .info{position: absolute;left: 4px;bottom: 4px;right: 4px;height: 20px;line-height: 20px;text-indent: 5px;background: rgba(0, 0, 0, 0.6);color: white;overflow: hidden;white-space: nowrap;text-overflow : ellipsis;font-size: 12px;z-index: 10}\n.upload-state-done:after{content:\"\\f00c\";font-family: FontAwesome;font-style: normal;font-weight: normal;line-height: 1;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;font-size: 32px;position: absolute;bottom: 0;right: 4px;color: #4cae4c;z-index: 99}\n.cropper-container{position: relative; overflow: hidden; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; background-color: #fff; -webkit-tap-highlight-color: transparent; -webkit-touch-callout: none;}\n.cropper-container .cropper-modal{position: absolute; top: 0; right: 0; bottom: 0; left: 0; background: #000; filter: alpha(opacity=50); opacity: .5;}\n.cropper-container .cropper-dragger{position: absolute; top: 10%; left: 10%; width: 80%; height: 80%;}\n.cropper-container .cropper-preview{display: block; width: 100%; height: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; overflow: hidden; border-color: #69f; border-color: rgba(51, 102, 255, .75); border-style: solid; border-width: 1px;}\n.cropper-container .cropper-dashed{position: absolute; display: block; filter: alpha(opacity=50); border: 0 dashed #fff; opacity: .5;}\n.cropper-container .dashed-h{top: 33.3%; left: 0; width: 100%; height: 33.3%; border-top-width: 1px; border-bottom-width: 1px;}\n.cropper-container .dashed-v{top: 0; left: 33.3%; width: 33.3%; height: 100%; border-right-width: 1px; border-left-width: 1px;}\n.cropper-container .cropper-face,\n.cropper-container .cropper-line,\n.cropper-container .cropper-point{position: absolute; display: block; width: 100%; height: 100%; filter: alpha(opacity=10); opacity: .1;}\n.cropper-container .cropper-face{top: 0; left: 0; cursor: move; background-color: #fff;}\n.cropper-container .cropper-line{background-color: #69f;}\n.cropper-container .line-e{top: 0; right: -2px; width: 5px; cursor: e-resize;}\n.cropper-container .line-n{top: -2px; left: 0; height: 5px; cursor: n-resize;}\n.cropper-container .line-w{top: 0; left: -2px; width: 5px; cursor: w-resize;}\n.cropper-container .line-s{bottom: -2px; left: 0; height: 5px; cursor: s-resize;}\n.cropper-container .cropper-point{width: 5px; height: 5px; background-color: #69f; filter: alpha(opacity=75); opacity: .75;}\n.cropper-container .point-e{top: 49%; right: -2px; cursor: e-resize;}\n.cropper-container .point-n{top: -2px; left: 49%; cursor: n-resize;}\n.cropper-container .point-w{top: 49%; left: -2px; cursor: w-resize;}\n.cropper-container .point-s{bottom: -2px; left: 49%; cursor: s-resize;}\n.cropper-container .point-ne{top: -2px; right: -2px; cursor: ne-resize;}\n.cropper-container .point-nw{top: -2px; left: -2px; cursor: nw-resize;}\n.cropper-container .point-sw{bottom: -2px; left: -2px; cursor: sw-resize;}\n.cropper-container .point-se{right: -2px; bottom: -2px; width: 20px; height: 20px; cursor: se-resize; filter: alpha(opacity=100); opacity: 1;}\n.cropper-container .point-se:before{position: absolute; right: -50%; bottom: -50%; display: block; width: 200%; height: 200%; content: \" \"; background-color: #69f; filter: alpha(opacity=0); opacity: 0;}\n@media (min-width: 768px){.cropper-container .point-se{width: 15px; height: 15px;}}\n@media (min-width: 992px){.cropper-container .point-se{width: 10px; height: 10px;}}\n@media (min-width: 1200px){.cropper-container .point-se{width: 5px; height: 5px; filter: alpha(opacity=75); opacity: .75;}}\n.cropper-hidden{display: none !important;}\n.img-preview{width: 160px; height: 90px; margin-top: 1em; border: 1px solid #ccc;}\n\n\n.uploader-list-container{color: #838383; font-size: 12px; margin-top: 10px; background-color: #FFF; border:solid 1px #ddd}\n.uploader-list-container .queueList{margin: 20px;}\n.element-invisible{position: absolute !important; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px,1px,1px,1px);}\n.uploader-list-container .placeholder{border: 3px dashed #e6e6e6; min-height: 238px; padding-top: 158px; text-align: center; background: url(images/image.png) center 93px no-repeat; color: #cccccc; font-size: 18px; position: relative;}\n.uploader-list-container .placeholder .webuploader-pick{font-size: 18px; background: #00b7ee; border-radius: 3px; line-height: 44px; padding: 0 30px; color: #fff; display: inline-block; margin: 20px auto; cursor: pointer; box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);}\n.uploader-list-container .placeholder .webuploader-pick-hover{background: #00a2d4;}\n.uploader-list-container .placeholder .flashTip{color: #666666; font-size: 12px; position: absolute; width: 100%; text-align: center; bottom: 20px;}\n.uploader-list-container .placeholder .flashTip a{color: #0785d1; text-decoration: none;}\n.uploader-list-container .placeholder .flashTip a:hover{text-decoration: underline;}\n.uploader-list-container .placeholder.webuploader-dnd-over{border-color: #999999;}\n.uploader-list-container .placeholder.webuploader-dnd-over.webuploader-dnd-denied{border-color: red;}\n.uploader-list-container .filelist{list-style: none; margin: 0; padding: 0;}\n.uploader-list-container .filelist:after{content: ''; display: block; width: 0; height: 0; overflow: hidden; clear: both;}\n.uploader-list-container .filelist li{width: 110px; height: 110px; background: url(images/bg.png) no-repeat; text-align: center; margin: 0 8px 20px 0; position: relative; display: inline; float: left; overflow: hidden; font-size: 12px;}\n.uploader-list-container .filelist li p.log{position: relative; top: -45px;}\n.uploader-list-container .filelist li p.title{position: absolute; top: 0; left: 0; width: 100%; overflow: hidden; white-space: nowrap; text-overflow : ellipsis; top: 5px; text-indent: 5px; text-align: left;}\n.uploader-list-container .filelist li p.progress{position: absolute; width: 100%; bottom: 0; left: 0; height: 8px; overflow: hidden; z-index: 50;}\n.uploader-list-container .filelist li p.progress span{display: none; overflow: hidden; width: 0; height: 100%; background: #1483d8 url(images/progress.png) repeat-x; -webit-transition: width 200ms linear; -moz-transition: width 200ms linear; -o-transition: width 200ms linear; -ms-transition: width 200ms linear; transition: width 200ms linear; -webkit-animation: progressmove 2s linear infinite; -moz-animation: progressmove 2s linear infinite; -o-animation: progressmove 2s linear infinite; -ms-animation: progressmove 2s linear infinite; animation: progressmove 2s linear infinite; -webkit-transform: translateZ(0);}\n@-webkit-keyframes progressmove{0%{background-position: 0 0;} 100%{background-position: 17px 0;}}\n@-moz-keyframes progressmove{0%{background-position: 0 0;} 100%{background-position: 17px 0;}}\n@keyframes progressmove{0%{background-position: 0 0;} 100%{background-position: 17px 0;}}\n.uploader-list-container .filelist li p.imgWrap{position: relative; z-index: 2; line-height: 110px; vertical-align: middle; overflow: hidden; width: 110px; height: 110px; -webkit-transform-origin: 50% 50%; -moz-transform-origin: 50% 50%; -o-transform-origin: 50% 50%; -ms-transform-origin: 50% 50%; transform-origin: 50% 50%; -webit-transition: 200ms ease-out; -moz-transition: 200ms ease-out; -o-transition: 200ms ease-out; -ms-transition: 200ms ease-out; transition: 200ms ease-out;}\n.uploader-list-container .filelist li img{width: 100%;}\n.uploader-list-container .filelist li p.error{background: #f43838; color: #fff; position: absolute; bottom: 0; left: 0; height: 28px; line-height: 28px; width: 100%; z-index: 100;}\n.uploader-list-container .filelist li .success{display: block; position: absolute; left: 0; bottom: 0; height: 40px; width: 100%; z-index: 200; background: url(images/success.png) no-repeat right bottom;}\n.uploader-list-container .filelist div.file-panel{position: absolute; height: 0; filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0,startColorstr='#80000000', endColorstr='#80000000')\\0; background: rgba( 0, 0, 0, 0.5 ); width: 100%; top: 0; left: 0; overflow: hidden; z-index: 300;}\n.uploader-list-container .filelist div.file-panel span{width: 24px; height: 24px; display: inline; float: right; text-indent: -9999px; overflow: hidden; background: url(images/icons.png) no-repeat; margin: 5px 1px 1px; cursor: pointer;}\n.uploader-list-container .filelist div.file-panel span.rotateLeft{background-position: 0 -24px;}\n.uploader-list-container .filelist div.file-panel span.rotateLeft:hover{background-position: 0 0;}\n.uploader-list-container .filelist div.file-panel span.rotateRight{background-position: -24px -24px;}\n.uploader-list-container .filelist div.file-panel span.rotateRight:hover{background-position: -24px 0;}\n.uploader-list-container .filelist div.file-panel span.cancel{background-position: -48px -24px;}\n.uploader-list-container .filelist div.file-panel span.cancel:hover{background-position: -48px 0;}\n.uploader-list-container .statusBar{height: 63px; border-top: 1px solid #dadada; padding: 0 20px; line-height: 63px; vertical-align: middle; position: relative;}\n.uploader-list-container .statusBar .progress{border: 1px solid #1483d8; width: 198px; background: #fff; height: 18px; position: relative; display: inline-block; text-align: center; line-height: 20px; color: #6dbfff; position: relative; margin-right: 10px;}\n.uploader-list-container .statusBar .progress span.percentage{width: 0; height: 100%; left: 0; top: 0; background: #1483d8; position: absolute;}\n.uploader-list-container .statusBar .progress span.text{position: relative; z-index: 10;}\n.uploader-list-container .statusBar .info{display: inline-block; font-size: 14px; color: #666666;}\n.uploader-list-container .statusBar .btns{position: absolute; top: 10px; right: 20px; line-height: 40px;}\n#filePicker{display: inline-block; float: left;}\n.uploader-list-container .statusBar .btns .webuploader-pick,\n.uploader-list-container .statusBar .btns .uploadBtn,\n.uploader-list-container .statusBar .btns .uploadBtn.state-uploading,\n.uploader-list-container .statusBar .btns .uploadBtn.state-paused{background: #ffffff; border: 1px solid #cfcfcf; color: #565656; padding: 0 18px; display: inline-block; border-radius: 3px; margin-left: 10px; cursor: pointer; font-size: 14px; float: left;}\n.uploader-list-container .statusBar .btns .webuploader-pick-hover,\n.uploader-list-container .statusBar .btns .uploadBtn:hover,\n.uploader-list-container .statusBar .btns .uploadBtn.state-uploading:hover,\n.uploader-list-container .statusBar .btns .uploadBtn.state-paused:hover{background: #f0f0f0;}\n.uploader-list-container .statusBar .btns .uploadBtn{background: #00b7ee; color: #fff; border-color: transparent;}\n.uploader-list-container .statusBar .btns .uploadBtn:hover{background: #00a2d4;}\n.uploader-list-container .statusBar .btns .uploadBtn.disabled{pointer-events: none; opacity: 0.6;}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/webuploader.custom.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n    \n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n    \n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * 直接来源于jquery的代码。\n     * @fileOverview Promise/A+\n     * @beta\n     */\n    define('promise-builtin',[\n        'dollar'\n    ], function( $ ) {\n    \n        var api;\n    \n        // 简单版Callbacks, 默认memory，可选once.\n        function Callbacks( once ) {\n            var list = [],\n                stack = !once && [],\n                fire = function( data ) {\n                    memory = data;\n                    fired = true;\n                    firingIndex = firingStart || 0;\n                    firingStart = 0;\n                    firingLength = list.length;\n                    firing = true;\n    \n                    for ( ; list && firingIndex < firingLength; firingIndex++ ) {\n                        list[ firingIndex ].apply( data[ 0 ], data[ 1 ] );\n                    }\n                    firing = false;\n    \n                    if ( list ) {\n                        if ( stack ) {\n                            stack.length && fire( stack.shift() );\n                        }  else {\n                            list = [];\n                        }\n                    }\n                },\n                self = {\n                    add: function() {\n                        if ( list ) {\n                            var start = list.length;\n                            (function add ( args ) {\n                                $.each( args, function( _, arg ) {\n                                    var type = $.type( arg );\n                                    if ( type === 'function' ) {\n                                        list.push( arg );\n                                    } else if ( arg && arg.length &&\n                                            type !== 'string' ) {\n    \n                                        add( arg );\n                                    }\n                                });\n                            })( arguments );\n    \n                            if ( firing ) {\n                                firingLength = list.length;\n                            } else if ( memory ) {\n                                firingStart = start;\n                                fire( memory );\n                            }\n                        }\n                        return this;\n                    },\n    \n                    disable: function() {\n                        list = stack = memory = undefined;\n                        return this;\n                    },\n    \n                    // Lock the list in its current state\n                    lock: function() {\n                        stack = undefined;\n                        if ( !memory ) {\n                            self.disable();\n                        }\n                        return this;\n                    },\n    \n                    fireWith: function( context, args ) {\n                        if ( list && (!fired || stack) ) {\n                            args = args || [];\n                            args = [ context, args.slice ? args.slice() : args ];\n                            if ( firing ) {\n                                stack.push( args );\n                            } else {\n                                fire( args );\n                            }\n                        }\n                        return this;\n                    },\n    \n                    fire: function() {\n                        self.fireWith( this, arguments );\n                        return this;\n                    }\n                },\n    \n                fired, firing, firingStart, firingLength, firingIndex, memory;\n    \n            return self;\n        }\n    \n        function Deferred( func ) {\n            var tuples = [\n                    // action, add listener, listener list, final state\n                    [ 'resolve', 'done', Callbacks( true ), 'resolved' ],\n                    [ 'reject', 'fail', Callbacks( true ), 'rejected' ],\n                    [ 'notify', 'progress', Callbacks() ]\n                ],\n                state = 'pending',\n                promise = {\n                    state: function() {\n                        return state;\n                    },\n                    always: function() {\n                        deferred.done( arguments ).fail( arguments );\n                        return this;\n                    },\n                    then: function( /* fnDone, fnFail, fnProgress */ ) {\n                        var fns = arguments;\n                        return Deferred(function( newDefer ) {\n                            $.each( tuples, function( i, tuple ) {\n                                var action = tuple[ 0 ],\n                                    fn = $.isFunction( fns[ i ] ) && fns[ i ];\n    \n                                // deferred[ done | fail | progress ] for\n                                // forwarding actions to newDefer\n                                deferred[ tuple[ 1 ] ](function() {\n                                    var returned;\n    \n                                    returned = fn && fn.apply( this, arguments );\n    \n                                    if ( returned &&\n                                            $.isFunction( returned.promise ) ) {\n    \n                                        returned.promise()\n                                                .done( newDefer.resolve )\n                                                .fail( newDefer.reject )\n                                                .progress( newDefer.notify );\n                                    } else {\n                                        newDefer[ action + 'With' ](\n                                                this === promise ?\n                                                newDefer.promise() :\n                                                this,\n                                                fn ? [ returned ] : arguments );\n                                    }\n                                });\n                            });\n                            fns = null;\n                        }).promise();\n                    },\n    \n                    // Get a promise for this deferred\n                    // If obj is provided, the promise aspect is added to the object\n                    promise: function( obj ) {\n    \n                        return obj != null ? $.extend( obj, promise ) : promise;\n                    }\n                },\n                deferred = {};\n    \n            // Keep pipe for back-compat\n            promise.pipe = promise.then;\n    \n            // Add list-specific methods\n            $.each( tuples, function( i, tuple ) {\n                var list = tuple[ 2 ],\n                    stateString = tuple[ 3 ];\n    \n                // promise[ done | fail | progress ] = list.add\n                promise[ tuple[ 1 ] ] = list.add;\n    \n                // Handle state\n                if ( stateString ) {\n                    list.add(function() {\n                        // state = [ resolved | rejected ]\n                        state = stateString;\n    \n                    // [ reject_list | resolve_list ].disable; progress_list.lock\n                    }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n                }\n    \n                // deferred[ resolve | reject | notify ]\n                deferred[ tuple[ 0 ] ] = function() {\n                    deferred[ tuple[ 0 ] + 'With' ]( this === deferred ? promise :\n                            this, arguments );\n                    return this;\n                };\n                deferred[ tuple[ 0 ] + 'With' ] = list.fireWith;\n            });\n    \n            // Make the deferred a promise\n            promise.promise( deferred );\n    \n            // Call given func if any\n            if ( func ) {\n                func.call( deferred, deferred );\n            }\n    \n            // All done!\n            return deferred;\n        }\n    \n        api = {\n            /**\n             * 创建一个[Deferred](http://api.jquery.com/category/deferred-object/)对象。\n             * 详细的Deferred用法说明，请参照jQuery的API文档。\n             *\n             * Deferred对象在钩子回掉函数中经常要用到，用来处理需要等待的异步操作。\n             *\n             * @for  Base\n             * @method Deferred\n             * @grammar Base.Deferred() => Deferred\n             * @example\n             * // 在文件开始发送前做些异步操作。\n             * // WebUploader会等待此异步操作完成后，开始发送文件。\n             * Uploader.register({\n             *     'before-send-file': 'doSomthingAsync'\n             * }, {\n             *\n             *     doSomthingAsync: function() {\n             *         var deferred = Base.Deferred();\n             *\n             *         // 模拟一次异步操作。\n             *         setTimeout(deferred.resolve, 2000);\n             *\n             *         return deferred.promise();\n             *     }\n             * });\n             */\n            Deferred: Deferred,\n    \n            /**\n             * 判断传入的参数是否为一个promise对象。\n             * @method isPromise\n             * @grammar Base.isPromise( anything ) => Boolean\n             * @param  {*}  anything 检测对象。\n             * @return {Boolean}\n             * @for  Base\n             * @example\n             * console.log( Base.isPromise() );    // => false\n             * console.log( Base.isPromise({ key: '123' }) );    // => false\n             * console.log( Base.isPromise( Base.Deferred().promise() ) );    // => true\n             *\n             * // Deferred也是一个Promise\n             * console.log( Base.isPromise( Base.Deferred() ) );    // => true\n             */\n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            },\n    \n            /**\n             * 返回一个promise，此promise在所有传入的promise都完成了后完成。\n             * 详细请查看[这里](http://api.jquery.com/jQuery.when/)。\n             *\n             * @method when\n             * @for  Base\n             * @grammar Base.when( promise1[, promise2[, promise3...]] ) => Promise\n             */\n            when: function( subordinate /* , ..., subordinateN */ ) {\n                var i = 0,\n                    slice = [].slice,\n                    resolveValues = slice.call( arguments ),\n                    length = resolveValues.length,\n    \n                    // the count of uncompleted subordinates\n                    remaining = length !== 1 || (subordinate &&\n                        $.isFunction( subordinate.promise )) ? length : 0,\n    \n                    // the master Deferred. If resolveValues consist of\n                    // only a single Deferred, just use that.\n                    deferred = remaining === 1 ? subordinate : Deferred(),\n    \n                    // Update function for both resolve and progress values\n                    updateFunc = function( i, contexts, values ) {\n                        return function( value ) {\n                            contexts[ i ] = this;\n                            values[ i ] = arguments.length > 1 ?\n                                    slice.call( arguments ) : value;\n    \n                            if ( values === progressValues ) {\n                                deferred.notifyWith( contexts, values );\n                            } else if ( !(--remaining) ) {\n                                deferred.resolveWith( contexts, values );\n                            }\n                        };\n                    },\n    \n                    progressValues, progressContexts, resolveContexts;\n    \n                // add listeners to Deferred subordinates; treat others as resolved\n                if ( length > 1 ) {\n                    progressValues = new Array( length );\n                    progressContexts = new Array( length );\n                    resolveContexts = new Array( length );\n                    for ( ; i < length; i++ ) {\n                        if ( resolveValues[ i ] &&\n                                $.isFunction( resolveValues[ i ].promise ) ) {\n    \n                            resolveValues[ i ].promise()\n                                    .done( updateFunc( i, resolveContexts,\n                                            resolveValues ) )\n                                    .fail( deferred.reject )\n                                    .progress( updateFunc( i, progressContexts,\n                                            progressValues ) );\n                        } else {\n                            --remaining;\n                        }\n                    }\n                }\n    \n                // if we're not waiting on anything, resolve the master\n                if ( !remaining ) {\n                    deferred.resolveWith( resolveContexts, resolveValues );\n                }\n    \n                return deferred.promise();\n            }\n        };\n    \n        return api;\n    });\n    define('promise',[\n        'promise-builtin'\n    ], function( $ ) {\n        return $;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n    \n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n    \n        var noop = function() {},\n            call = Function.call;\n    \n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n    \n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n    \n        function createObject( proto ) {\n            var f;\n    \n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n    \n    \n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n    \n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n    \n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n    \n            Deferred: promise.Deferred,\n    \n            isPromise: promise.isPromise,\n    \n            when: promise.when,\n    \n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n    \n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n    \n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n    \n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n    \n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n    \n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n    \n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n    \n                /* jshint camelcase: false */\n    \n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n    \n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n    \n                return child;\n            },\n    \n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n    \n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n    \n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n    \n            nextTick: (function() {\n    \n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n    \n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n    \n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n    \n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n    \n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n    \n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n    \n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n    \n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n    \n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n    \n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n    \n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n    \n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n    \n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n    \n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n    \n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n    \n            while ( ++i < len ) {\n                handler = events[ i ];\n    \n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n    \n            return !stoped;\n        }\n    \n        protos = {\n    \n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n    \n                if ( !callback ) {\n                    return this;\n                }\n    \n                set = this._events || (this._events = []);\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n    \n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n    \n                    set.push( handler );\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n    \n                if ( !callback ) {\n                    return me;\n                }\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n    \n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n    \n                return me;\n            },\n    \n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n    \n                if ( !events ) {\n                    return this;\n                }\n    \n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n    \n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n    \n                if ( !this._events || !type ) {\n                    return this;\n                }\n    \n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n    \n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n    \n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n    \n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n    \n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$;\n    \n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n    \n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n    \n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n    \n        $.extend( Uploader.prototype, {\n            state: 'pending',\n    \n            _init: function( opts ) {\n                var me = this;\n    \n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n    \n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n    \n                // setter\n                if ( arguments.length > 1 ) {\n    \n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n    \n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n    \n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n    \n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n    \n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n    \n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n    \n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n    \n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n    \n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n    \n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n    \n                    return false;\n                }\n    \n                return true;\n            },\n    \n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n    \n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n    \n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n    \n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n    \n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            factories = {},\n    \n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n    \n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n    \n        $.extend( Runtime.prototype, {\n    \n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n    \n                if ( this._container ) {\n                    return this._container;\n                }\n    \n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n    \n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n    \n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n    \n            init: Base.noop,\n            exec: Base.noop,\n    \n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n    \n        Runtime.orders = 'html5,flash';\n    \n    \n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n    \n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n    \n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n    \n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n    \n            type = type || getFirstKey( factories );\n    \n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n    \n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n    \n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n    \n        var cache;\n    \n        cache = (function() {\n            var obj = {};\n    \n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n    \n                get: function( ruid, standalone ) {\n                    var i;\n    \n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n    \n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n    \n                        return obj[ i ];\n                    }\n    \n                    return null;\n                },\n    \n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n    \n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n    \n            this.uid = Base.guid('client_');\n    \n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n    \n            this.connectRuntime = function( opts, cb ) {\n    \n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n    \n                deferred.done( cb );\n    \n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n    \n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n    \n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n    \n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                runtime.__client--;\n    \n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n    \n                runtime = null;\n            };\n    \n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n    \n                return runtime.exec.apply( this, args );\n            };\n    \n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n    \n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n    \n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n    \n        function Blob( ruid, source ) {\n            var me = this;\n    \n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n    \n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n    \n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n    \n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n    \n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n    \n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n    \n            getSource: function() {\n                return this.source;\n            }\n        });\n    \n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n    \n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n    \n        function File( ruid, file ) {\n            var ext;\n    \n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n    \n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n    \n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n    \n            Blob.apply( this, arguments );\n        }\n    \n        return Base.inherits( Blob, File );\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n    \n        var $ = Base.$;\n    \n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n    \n            opts.container = $( opts.id );\n    \n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n    \n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n    \n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n    \n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n    \n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n    \n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n    \n                button.addClass('webuploader-pick');\n    \n                me.on( 'all', function( type ) {\n                    var files;\n    \n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n    \n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n    \n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n    \n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n    \n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n    \n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n    \n                    pos = button.offset();\n    \n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n    \n            enable: function() {\n                var btn = this.options.button;\n    \n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n    \n            disable: function() {\n                var btn = this.options.button;\n    \n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n    \n                btn.addClass('webuploader-pick-disable');\n            },\n    \n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n    \n        return FilePicker;\n    });\n    \n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n    \n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n    \n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n    \n            var length = obj.length,\n                type = $.type( obj );\n    \n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n    \n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n    \n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n    \n        $.extend( Widget.prototype, {\n    \n            init: Base.noop,\n    \n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n    \n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n    \n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n    \n                    return IGNORE;\n                }\n    \n                return this[ map[ apiName ] ].apply( this, args );\n    \n            },\n    \n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n    \n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n    \n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n    \n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n    \n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n    \n                return _init.apply( me, arguments );\n            },\n    \n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n    \n                args = isArrayLike( args ) ? args : [ args ];\n    \n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n    \n                    if ( rlt !== IGNORE ) {\n    \n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n    \n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n    \n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n    \n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n    \n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n    \n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n    \n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n    \n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n    \n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n    \n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n    \n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n    \n            } else {\n                map = $.extend( map, responseMap );\n            }\n    \n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n    \n            return klass;\n        };\n    \n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *     \n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n            \n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n    \n        return Widget;\n    });\n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n    \n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n    \n        return Uploader.register({\n            name: 'picker',\n    \n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n    \n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n    \n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n    \n                if ( !pick ) {\n                    return;\n                }\n    \n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n    \n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n    \n                    deferred = Base.Deferred();\n    \n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n    \n                    picker = new FilePicker( options );\n    \n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n    \n                    me.pickers.push( picker );\n    \n                    promises.push( deferred.promise() );\n                });\n    \n                return Base.when.apply( Base, promises );\n            },\n    \n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n    \n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n    \n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n    \n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n    \n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n    \n        // 默认选项。\n        Image.options = {\n    \n            // 默认的图片处理质量\n            quality: 90,\n    \n            // 是否裁剪\n            crop: false,\n    \n            // 是否保留头部信息\n            preserveHeaders: false,\n    \n            // 是否允许放大。\n            allowMagnify: false\n        };\n    \n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n    \n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n    \n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n    \n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n    \n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    \n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n    \n        var $ = Base.$,\n            throttle;\n    \n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n    \n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n    \n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n    \n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n    \n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n    \n        return Uploader.register({\n    \n            name: 'image',\n    \n    \n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n    \n                opts = $.extend({}, this.options.thumb );\n    \n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n    \n                width = width || opts.width;\n                height = height || opts.height;\n    \n                image = new Image( opts );\n    \n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n    \n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n    \n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n    \n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n    \n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n    \n                image = new Image( opts );\n    \n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n    \n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                image.once( 'complete', function() {\n                    var blob, size;\n    \n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n    \n                        size = file.size;\n    \n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n    \n                            file.trigger( 'resize', blob.size, size );\n                        }\n    \n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n    \n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n    \n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n    \n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n    \n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n    \n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n    \n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n    \n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n    \n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n    \n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n    \n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n    \n    \n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n    \n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n    \n            this.source = source;\n            this.loaded = 0;\n    \n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n    \n        $.extend( WUFile.prototype, {\n    \n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n    \n                var prevStatus = statusMap[ this.id ];\n    \n                typeof text !== 'undefined' && (this.statusText = text);\n    \n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n    \n            },\n    \n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n    \n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n    \n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n    \n        Mediator.installTo( WUFile.prototype );\n    \n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n    \n        return WUFile;\n    });\n    \n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n    \n        var $ = Base.$,\n            STATUS = WUFile.Status;\n    \n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n    \n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n    \n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n    \n            // 存储所有文件\n            this._map = {};\n        }\n    \n        $.extend( Queue.prototype, {\n    \n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n    \n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n    \n                status = status || STATUS.QUEUED;\n    \n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n    \n                return null;\n            },\n    \n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n    \n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n    \n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n    \n                    ret.push( file );\n                }\n    \n                return ret;\n            },\n    \n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n    \n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n    \n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n    \n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n    \n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n    \n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n    \n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n    \n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n    \n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n    \n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n    \n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n    \n        });\n    \n        Mediator.installTo( Queue.prototype );\n    \n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n    \n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n    \n        return Uploader.register({\n            name: 'queue',\n    \n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n    \n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n    \n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n    \n                    me.accept = new RegExp( accept, 'i' );\n                }\n    \n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n    \n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n    \n    \n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n    \n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n    \n                    file = new WUFile( file );\n                }\n    \n                return file;\n            },\n    \n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n    \n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n    \n                return !invalid;\n            },\n    \n    \n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n    \n            _addFile: function( file ) {\n                var me = this;\n    \n                file = me._wrapFile( file );\n    \n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n    \n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n    \n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n    \n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n    \n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n            \n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             * \n             */\n    \n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n    \n                if ( !files.length ) {\n                    files = [ files ];\n                }\n    \n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n    \n                me.owner.trigger( 'filesQueued', files );\n    \n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n    \n            getStats: function() {\n                return this.stats;\n            },\n    \n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n    \n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n    \n                file = file.id ? file : me.queue.getFile( file );\n    \n                this.request( 'cancel-file', file );\n    \n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n    \n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n    \n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n    \n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n    \n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n    \n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n    \n                me.request('start-upload');\n            },\n    \n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n    \n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n    \n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n    \n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n    \n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n    \n        return Uploader.register({\n            name: 'runtime',\n    \n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n    \n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n    \n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n    \n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n    \n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n    \n        var $ = Base.$;\n    \n        function Transport( opts ) {\n            var me = this;\n    \n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n    \n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n    \n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n    \n        Transport.options = {\n            server: '',\n            method: 'POST',\n    \n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n    \n        $.extend( Transport.prototype, {\n    \n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n    \n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n    \n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n    \n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n    \n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n    \n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n    \n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n    \n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n    \n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n    \n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n    \n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n    \n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n    \n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n    \n                if ( !duration ) {\n                    return;\n                }\n    \n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n    \n        });\n    \n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n    \n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n    \n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n    \n        // 添加默认配置项\n        $.extend( Uploader.options, {\n    \n    \n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n    \n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n    \n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n    \n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n    \n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n    \n    \n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n    \n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n    \n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n    \n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n    \n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n    \n            api = {\n                file: file,\n    \n                has: function() {\n                    return !!pending.length;\n                },\n    \n                shift: function() {\n                    return pending.shift();\n                },\n    \n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n    \n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n    \n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n    \n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n    \n            return api;\n        }\n    \n        Uploader.register({\n            name: 'upload',\n    \n            init: function() {\n                var owner = this.owner,\n                    me = this;\n    \n                this.runing = false;\n                this.progress = false;\n    \n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n    \n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n    \n                // 缓存分好片的文件。\n                this.stack = [];\n    \n                // 缓存即将上传的文件。\n                this.pending = [];\n    \n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n    \n                owner.on( 'uploadComplete', function( file ) {\n    \n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n    \n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n    \n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n    \n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n    \n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n    \n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n    \n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n    \n                            v.transport && v.transport.send();\n                        });\n    \n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n    \n                if ( me.runing ) {\n                    return;\n                }\n    \n                me.runing = true;\n    \n                var files = [];\n    \n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n    \n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n    \n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n    \n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n    \n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n    \n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n    \n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n    \n                if ( me.runing === false ) {\n                    return;\n                }\n    \n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n    \n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n    \n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n    \n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n    \n                    return Base.nextTick( me.__tick );\n                }\n    \n                me.runing = false;\n    \n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n    \n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n    \n                me.owner.trigger('stopUpload');\n            },\n    \n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n    \n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n    \n            _getStats: function() {\n                return this.request('get-stats');\n            },\n    \n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                this.owner.trigger( 'uploadSkip', file );\n            },\n    \n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n    \n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n    \n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n    \n                    fn = function( val ) {\n                        me._promise = null;\n    \n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n    \n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n    \n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n    \n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n    \n            _putback: function(block) {\n                var idx;\n    \n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n    \n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n    \n            _getStack: function() {\n                var i = 0,\n                    act;\n    \n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n    \n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n    \n                return null;\n            },\n    \n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n    \n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n    \n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n    \n                    return act.shift();\n    \n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n    \n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n    \n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n    \n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n    \n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n    \n                    return done( next );\n                }\n            },\n    \n    \n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n    \n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n    \n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n    \n                        return me._finishFile( file );\n                    });\n    \n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n    \n                    promise.file = file;\n    \n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n    \n                        ~idx && pending.splice( idx, 1, file );\n                    });\n    \n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n    \n                    pending.push( promise );\n                }\n            },\n    \n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n    \n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n    \n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n    \n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n    \n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n    \n                    return;\n                }\n    \n                me.pool.push( block );\n                me.remaning++;\n    \n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n    \n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n    \n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n    \n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n    \n    \n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n    \n    \n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n    \n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n    \n                block.transport = tr;\n    \n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n    \n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n    \n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n    \n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n    \n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n    \n                    return reject;\n                };\n    \n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n    \n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n    \n                        block.retried++;\n                        tr.send();\n    \n                    } else {\n    \n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n    \n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n    \n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n    \n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n    \n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n    \n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n    \n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n    \n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n    \n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n    \n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n    \n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n    \n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n    \n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n    \n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n    \n                if (!file.blocks) {\n                    return;\n                }\n    \n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n    \n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n    \n        });\n    });\n    /**\n     * @fileOverview 日志组件，主要用来收集错误信息，可以帮助 webuploader 更好的定位问题和发展。\n     *\n     * 如果您不想要启用此功能，请在打包的时候去掉 log 模块。\n     *\n     * 或者可以在初始化的时候通过 options.disableWidgets 属性禁用。\n     *\n     * 如：\n     * WebUploader.create({\n     *     ...\n     *\n     *     disableWidgets: 'log',\n     *\n     *     ...\n     * })\n     */\n    define('widgets/log',[\n        'base',\n        'uploader',\n        'widgets/widget'\n    ], function( Base, Uploader ) {\n        var $ = Base.$,\n            logUrl = ' http://static.tieba.baidu.com/tb/pms/img/st.gif??',\n            product = (location.hostname || location.host || 'protected').toLowerCase(),\n    \n            // 只针对 baidu 内部产品用户做统计功能。\n            enable = product && /baidu/i.exec(product),\n            base;\n    \n        if (!enable) {\n            return;\n        }\n    \n        base = {\n            dv: 3,\n            master: 'webuploader',\n            online: /test/.exec(product) ? 0 : 1,\n            module: '',\n            product: product,\n            type: 0\n        };\n    \n        function send(data) {\n            var obj = $.extend({}, base, data),\n                url = logUrl.replace(/^(.*)\\?/, '$1' + $.param( obj )),\n                image = new Image();\n    \n            image.src = url;\n        }\n    \n        return Uploader.register({\n            name: 'log',\n    \n            init: function() {\n                var owner = this.owner,\n                    count = 0,\n                    size = 0;\n    \n                owner\n                    .on('error', function(code) {\n                        send({\n                            type: 2,\n                            c_error_code: code\n                        });\n                    })\n                    .on('uploadError', function(file, reason) {\n                        send({\n                            type: 2,\n                            c_error_code: 'UPLOAD_ERROR',\n                            c_reason: '' + reason\n                        });\n                    })\n                    .on('uploadComplete', function(file) {\n                        count++;\n                        size += file.size;\n                    }).\n                    on('uploadFinished', function() {\n                        send({\n                            c_count: count,\n                            c_size: size\n                        });\n                        count = size = 0;\n                    });\n    \n                send({\n                    c_usage: 1\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n    \n        function CompBase( owner, runtime ) {\n    \n            this.owner = owner;\n            this.options = owner.options;\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.getRuid = function() {\n                return runtime.uid;\n            };\n    \n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n    \n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var type = 'html5',\n            components = {};\n    \n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n    \n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n    \n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n    \n        });\n    \n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n    \n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n    \n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n    \n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n    \n                blob = slice.call( blob, start, end );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var $ = Base.$;\n    \n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n    \n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n    \n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n    \n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n    \n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n    \n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n    \n                    input.attr( 'accept', arr.join(',') );\n                }\n    \n                container.append( input );\n                container.append( label );\n    \n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n    \n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n    \n                    me.files = e.target.files;\n    \n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n    \n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n    \n                    owner.trigger('change');\n                });\n    \n                label.on( 'mouseenter mouseleave', mouseHandler );\n    \n            },\n    \n    \n            getFiles: function() {\n                return this.files;\n            },\n    \n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/util',[\n        'base'\n    ], function( Base ) {\n    \n        var urlAPI = window.createObjectURL && window ||\n                window.URL && URL.revokeObjectURL && URL ||\n                window.webkitURL,\n            createObjectURL = Base.noop,\n            revokeObjectURL = createObjectURL;\n    \n        if ( urlAPI ) {\n    \n            // 更安全的方式调用，比如android里面就能把context改成其他的对象。\n            createObjectURL = function() {\n                return urlAPI.createObjectURL.apply( urlAPI, arguments );\n            };\n    \n            revokeObjectURL = function() {\n                return urlAPI.revokeObjectURL.apply( urlAPI, arguments );\n            };\n        }\n    \n        return {\n            createObjectURL: createObjectURL,\n            revokeObjectURL: revokeObjectURL,\n    \n            dataURL2Blob: function( dataURI ) {\n                var byteStr, intArray, ab, i, mimetype, parts;\n    \n                parts = dataURI.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                ab = new ArrayBuffer( byteStr.length );\n                intArray = new Uint8Array( ab );\n    \n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n    \n                mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ];\n    \n                return this.arrayBufferToBlob( ab, mimetype );\n            },\n    \n            dataURL2ArrayBuffer: function( dataURI ) {\n                var byteStr, intArray, i, parts;\n    \n                parts = dataURI.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                intArray = new Uint8Array( byteStr.length );\n    \n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n    \n                return intArray.buffer;\n            },\n    \n            arrayBufferToBlob: function( buffer, type ) {\n                var builder = window.BlobBuilder || window.WebKitBlobBuilder,\n                    bb;\n    \n                // android不支持直接new Blob, 只能借助blobbuilder.\n                if ( builder ) {\n                    bb = new builder();\n                    bb.append( buffer );\n                    return bb.getBlob( type );\n                }\n    \n                return new Blob([ buffer ], type ? { type: type } : {} );\n            },\n    \n            // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg.\n            // 你得到的结果是png.\n            canvasToDataUrl: function( canvas, type, quality ) {\n                return canvas.toDataURL( type, quality / 100 );\n            },\n    \n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            parseMeta: function( blob, callback ) {\n                callback( false, {});\n            },\n    \n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            updateImageHead: function( data ) {\n                return data;\n            }\n        };\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/imagemeta',[\n        'runtime/html5/util'\n    ], function( Util ) {\n    \n        var api;\n    \n        api = {\n            parsers: {\n                0xffe1: []\n            },\n    \n            maxMetaDataSize: 262144,\n    \n            parse: function( blob, cb ) {\n                var me = this,\n                    fr = new FileReader();\n    \n                fr.onload = function() {\n                    cb( false, me._parse( this.result ) );\n                    fr = fr.onload = fr.onerror = null;\n                };\n    \n                fr.onerror = function( e ) {\n                    cb( e.message );\n                    fr = fr.onload = fr.onerror = null;\n                };\n    \n                blob = blob.slice( 0, me.maxMetaDataSize );\n                fr.readAsArrayBuffer( blob.getSource() );\n            },\n    \n            _parse: function( buffer, noParse ) {\n                if ( buffer.byteLength < 6 ) {\n                    return;\n                }\n    \n                var dataview = new DataView( buffer ),\n                    offset = 2,\n                    maxOffset = dataview.byteLength - 4,\n                    headLength = offset,\n                    ret = {},\n                    markerBytes, markerLength, parsers, i;\n    \n                if ( dataview.getUint16( 0 ) === 0xffd8 ) {\n    \n                    while ( offset < maxOffset ) {\n                        markerBytes = dataview.getUint16( offset );\n    \n                        if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef ||\n                                markerBytes === 0xfffe ) {\n    \n                            markerLength = dataview.getUint16( offset + 2 ) + 2;\n    \n                            if ( offset + markerLength > dataview.byteLength ) {\n                                break;\n                            }\n    \n                            parsers = api.parsers[ markerBytes ];\n    \n                            if ( !noParse && parsers ) {\n                                for ( i = 0; i < parsers.length; i += 1 ) {\n                                    parsers[ i ].call( api, dataview, offset,\n                                            markerLength, ret );\n                                }\n                            }\n    \n                            offset += markerLength;\n                            headLength = offset;\n                        } else {\n                            break;\n                        }\n                    }\n    \n                    if ( headLength > 6 ) {\n                        if ( buffer.slice ) {\n                            ret.imageHead = buffer.slice( 2, headLength );\n                        } else {\n                            // Workaround for IE10, which does not yet\n                            // support ArrayBuffer.slice:\n                            ret.imageHead = new Uint8Array( buffer )\n                                    .subarray( 2, headLength );\n                        }\n                    }\n                }\n    \n                return ret;\n            },\n    \n            updateImageHead: function( buffer, head ) {\n                var data = this._parse( buffer, true ),\n                    buf1, buf2, bodyoffset;\n    \n    \n                bodyoffset = 2;\n                if ( data.imageHead ) {\n                    bodyoffset = 2 + data.imageHead.byteLength;\n                }\n    \n                if ( buffer.slice ) {\n                    buf2 = buffer.slice( bodyoffset );\n                } else {\n                    buf2 = new Uint8Array( buffer ).subarray( bodyoffset );\n                }\n    \n                buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength );\n    \n                buf1[ 0 ] = 0xFF;\n                buf1[ 1 ] = 0xD8;\n                buf1.set( new Uint8Array( head ), 2 );\n                buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 );\n    \n                return buf1.buffer;\n            }\n        };\n    \n        Util.parseMeta = function() {\n            return api.parse.apply( api, arguments );\n        };\n    \n        Util.updateImageHead = function() {\n            return api.updateImageHead.apply( api, arguments );\n        };\n    \n        return api;\n    });\n    /**\n     * 代码来自于：https://github.com/blueimp/JavaScript-Load-Image\n     * 暂时项目中只用了orientation.\n     *\n     * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail.\n     * @fileOverview EXIF解析\n     */\n    \n    // Sample\n    // ====================================\n    // Make : Apple\n    // Model : iPhone 4S\n    // Orientation : 1\n    // XResolution : 72 [72/1]\n    // YResolution : 72 [72/1]\n    // ResolutionUnit : 2\n    // Software : QuickTime 7.7.1\n    // DateTime : 2013:09:01 22:53:55\n    // ExifIFDPointer : 190\n    // ExposureTime : 0.058823529411764705 [1/17]\n    // FNumber : 2.4 [12/5]\n    // ExposureProgram : Normal program\n    // ISOSpeedRatings : 800\n    // ExifVersion : 0220\n    // DateTimeOriginal : 2013:09:01 22:52:51\n    // DateTimeDigitized : 2013:09:01 22:52:51\n    // ComponentsConfiguration : YCbCr\n    // ShutterSpeedValue : 4.058893515764426\n    // ApertureValue : 2.5260688216892597 [4845/1918]\n    // BrightnessValue : -0.3126686601998395\n    // MeteringMode : Pattern\n    // Flash : Flash did not fire, compulsory flash mode\n    // FocalLength : 4.28 [107/25]\n    // SubjectArea : [4 values]\n    // FlashpixVersion : 0100\n    // ColorSpace : 1\n    // PixelXDimension : 2448\n    // PixelYDimension : 3264\n    // SensingMethod : One-chip color area sensor\n    // ExposureMode : 0\n    // WhiteBalance : Auto white balance\n    // FocalLengthIn35mmFilm : 35\n    // SceneCaptureType : Standard\n    define('runtime/html5/imagemeta/exif',[\n        'base',\n        'runtime/html5/imagemeta'\n    ], function( Base, ImageMeta ) {\n    \n        var EXIF = {};\n    \n        EXIF.ExifMap = function() {\n            return this;\n        };\n    \n        EXIF.ExifMap.prototype.map = {\n            'Orientation': 0x0112\n        };\n    \n        EXIF.ExifMap.prototype.get = function( id ) {\n            return this[ id ] || this[ this.map[ id ] ];\n        };\n    \n        EXIF.exifTagTypes = {\n            // byte, 8-bit unsigned int:\n            1: {\n                getValue: function( dataView, dataOffset ) {\n                    return dataView.getUint8( dataOffset );\n                },\n                size: 1\n            },\n    \n            // ascii, 8-bit byte:\n            2: {\n                getValue: function( dataView, dataOffset ) {\n                    return String.fromCharCode( dataView.getUint8( dataOffset ) );\n                },\n                size: 1,\n                ascii: true\n            },\n    \n            // short, 16 bit int:\n            3: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint16( dataOffset, littleEndian );\n                },\n                size: 2\n            },\n    \n            // long, 32 bit int:\n            4: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n    \n            // rational = two long values,\n            // first is numerator, second is denominator:\n            5: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian ) /\n                        dataView.getUint32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            },\n    \n            // slong, 32 bit signed int:\n            9: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n    \n            // srational, two slongs, first is numerator, second is denominator:\n            10: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian ) /\n                        dataView.getInt32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            }\n        };\n    \n        // undefined, 8-bit byte, value depending on field:\n        EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ];\n    \n        EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length,\n                littleEndian ) {\n    \n            var tagType = EXIF.exifTagTypes[ type ],\n                tagSize, dataOffset, values, i, str, c;\n    \n            if ( !tagType ) {\n                Base.log('Invalid Exif data: Invalid tag type.');\n                return;\n            }\n    \n            tagSize = tagType.size * length;\n    \n            // Determine if the value is contained in the dataOffset bytes,\n            // or if the value at the dataOffset is a pointer to the actual data:\n            dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8,\n                    littleEndian ) : (offset + 8);\n    \n            if ( dataOffset + tagSize > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid data offset.');\n                return;\n            }\n    \n            if ( length === 1 ) {\n                return tagType.getValue( dataView, dataOffset, littleEndian );\n            }\n    \n            values = [];\n    \n            for ( i = 0; i < length; i += 1 ) {\n                values[ i ] = tagType.getValue( dataView,\n                        dataOffset + i * tagType.size, littleEndian );\n            }\n    \n            if ( tagType.ascii ) {\n                str = '';\n    \n                // Concatenate the chars:\n                for ( i = 0; i < values.length; i += 1 ) {\n                    c = values[ i ];\n    \n                    // Ignore the terminating NULL byte(s):\n                    if ( c === '\\u0000' ) {\n                        break;\n                    }\n                    str += c;\n                }\n    \n                return str;\n            }\n            return values;\n        };\n    \n        EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian,\n                data ) {\n    \n            var tag = dataView.getUint16( offset, littleEndian );\n            data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset,\n                    dataView.getUint16( offset + 2, littleEndian ),    // tag type\n                    dataView.getUint32( offset + 4, littleEndian ),    // tag length\n                    littleEndian );\n        };\n    \n        EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset,\n                littleEndian, data ) {\n    \n            var tagsNumber, dirEndOffset, i;\n    \n            if ( dirOffset + 6 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory offset.');\n                return;\n            }\n    \n            tagsNumber = dataView.getUint16( dirOffset, littleEndian );\n            dirEndOffset = dirOffset + 2 + 12 * tagsNumber;\n    \n            if ( dirEndOffset + 4 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory size.');\n                return;\n            }\n    \n            for ( i = 0; i < tagsNumber; i += 1 ) {\n                this.parseExifTag( dataView, tiffOffset,\n                        dirOffset + 2 + 12 * i,    // tag offset\n                        littleEndian, data );\n            }\n    \n            // Return the offset to the next directory:\n            return dataView.getUint32( dirEndOffset, littleEndian );\n        };\n    \n        // EXIF.getExifThumbnail = function(dataView, offset, length) {\n        //     var hexData,\n        //         i,\n        //         b;\n        //     if (!length || offset + length > dataView.byteLength) {\n        //         Base.log('Invalid Exif data: Invalid thumbnail data.');\n        //         return;\n        //     }\n        //     hexData = [];\n        //     for (i = 0; i < length; i += 1) {\n        //         b = dataView.getUint8(offset + i);\n        //         hexData.push((b < 16 ? '0' : '') + b.toString(16));\n        //     }\n        //     return 'data:image/jpeg,%' + hexData.join('%');\n        // };\n    \n        EXIF.parseExifData = function( dataView, offset, length, data ) {\n    \n            var tiffOffset = offset + 10,\n                littleEndian, dirOffset;\n    \n            // Check for the ASCII code for \"Exif\" (0x45786966):\n            if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) {\n                // No Exif data, might be XMP data instead\n                return;\n            }\n            if ( tiffOffset + 8 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid segment size.');\n                return;\n            }\n    \n            // Check for the two null bytes:\n            if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) {\n                Base.log('Invalid Exif data: Missing byte alignment offset.');\n                return;\n            }\n    \n            // Check the byte alignment:\n            switch ( dataView.getUint16( tiffOffset ) ) {\n                case 0x4949:\n                    littleEndian = true;\n                    break;\n    \n                case 0x4D4D:\n                    littleEndian = false;\n                    break;\n    \n                default:\n                    Base.log('Invalid Exif data: Invalid byte alignment marker.');\n                    return;\n            }\n    \n            // Check for the TIFF tag marker (0x002A):\n            if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) {\n                Base.log('Invalid Exif data: Missing TIFF marker.');\n                return;\n            }\n    \n            // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:\n            dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian );\n            // Create the exif object to store the tags:\n            data.exif = new EXIF.ExifMap();\n            // Parse the tags of the main image directory and retrieve the\n            // offset to the next directory, usually the thumbnail directory:\n            dirOffset = EXIF.parseExifTags( dataView, tiffOffset,\n                    tiffOffset + dirOffset, littleEndian, data );\n    \n            // 尝试读取缩略图\n            // if ( dirOffset ) {\n            //     thumbnailData = {exif: {}};\n            //     dirOffset = EXIF.parseExifTags(\n            //         dataView,\n            //         tiffOffset,\n            //         tiffOffset + dirOffset,\n            //         littleEndian,\n            //         thumbnailData\n            //     );\n    \n            //     // Check for JPEG Thumbnail offset:\n            //     if (thumbnailData.exif[0x0201]) {\n            //         data.exif.Thumbnail = EXIF.getExifThumbnail(\n            //             dataView,\n            //             tiffOffset + thumbnailData.exif[0x0201],\n            //             thumbnailData.exif[0x0202] // Thumbnail data length\n            //         );\n            //     }\n            // }\n        };\n    \n        ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData );\n        return EXIF;\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('runtime/html5/image',[\n        'base',\n        'runtime/html5/runtime',\n        'runtime/html5/util'\n    ], function( Base, Html5Runtime, Util ) {\n    \n        var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';\n    \n        return Html5Runtime.register( 'Image', {\n    \n            // flag: 标记是否被修改过。\n            modified: false,\n    \n            init: function() {\n                var me = this,\n                    img = new Image();\n    \n                img.onload = function() {\n    \n                    me._info = {\n                        type: me.type,\n                        width: this.width,\n                        height: this.height\n                    };\n    \n                    // 读取meta信息。\n                    if ( !me._metas && 'image/jpeg' === me.type ) {\n                        Util.parseMeta( me._blob, function( error, ret ) {\n                            me._metas = ret;\n                            me.owner.trigger('load');\n                        });\n                    } else {\n                        me.owner.trigger('load');\n                    }\n                };\n    \n                img.onerror = function() {\n                    me.owner.trigger('error');\n                };\n    \n                me._img = img;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    img = me._img;\n    \n                me._blob = blob;\n                me.type = blob.type;\n                img.src = Util.createObjectURL( blob.getSource() );\n                me.owner.once( 'load', function() {\n                    Util.revokeObjectURL( img.src );\n                });\n            },\n    \n            resize: function( width, height ) {\n                var canvas = this._canvas ||\n                        (this._canvas = document.createElement('canvas'));\n    \n                this._resize( this._img, canvas, width, height );\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'resize' );\n            },\n    \n            crop: function( x, y, w, h, s ) {\n                var cvs = this._canvas ||\n                        (this._canvas = document.createElement('canvas')),\n                    opts = this.options,\n                    img = this._img,\n                    iw = img.naturalWidth,\n                    ih = img.naturalHeight,\n                    orientation = this.getOrientation();\n    \n                s = s || 1;\n    \n                // todo 解决 orientation 的问题。\n                // values that require 90 degree rotation\n                // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n    \n                //     switch ( orientation ) {\n                //         case 6:\n                //             tmp = x;\n                //             x = y;\n                //             y = iw * s - tmp - w;\n                //             console.log(ih * s, tmp, w)\n                //             break;\n                //     }\n    \n                //     (w ^= h, h ^= w, w ^= h);\n                // }\n    \n                cvs.width = w;\n                cvs.height = h;\n    \n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n                this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s );\n    \n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'crop' );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this._blob,\n                    opts = this.options,\n                    canvas;\n    \n                type = type || this.type;\n    \n                // blob需要重新生成。\n                if ( this.modified || this.type !== type ) {\n                    canvas = this._canvas;\n    \n                    if ( type === 'image/jpeg' ) {\n    \n                        blob = Util.canvasToDataUrl( canvas, type, opts.quality );\n    \n                        if ( opts.preserveHeaders && this._metas &&\n                                this._metas.imageHead ) {\n    \n                            blob = Util.dataURL2ArrayBuffer( blob );\n                            blob = Util.updateImageHead( blob,\n                                    this._metas.imageHead );\n                            blob = Util.arrayBufferToBlob( blob, type );\n                            return blob;\n                        }\n                    } else {\n                        blob = Util.canvasToDataUrl( canvas, type );\n                    }\n    \n                    blob = Util.dataURL2Blob( blob );\n                }\n    \n                return blob;\n            },\n    \n            getAsDataUrl: function( type ) {\n                var opts = this.options;\n    \n                type = type || this.type;\n    \n                if ( type === 'image/jpeg' ) {\n                    return Util.canvasToDataUrl( this._canvas, type, opts.quality );\n                } else {\n                    return this._canvas.toDataURL( type );\n                }\n            },\n    \n            getOrientation: function() {\n                return this._metas && this._metas.exif &&\n                        this._metas.exif.get('Orientation') || 1;\n            },\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            destroy: function() {\n                var canvas = this._canvas;\n                this._img.onload = null;\n    \n                if ( canvas ) {\n                    canvas.getContext('2d')\n                            .clearRect( 0, 0, canvas.width, canvas.height );\n                    canvas.width = canvas.height = 0;\n                    this._canvas = null;\n                }\n    \n                // 释放内存。非常重要，否则释放不了image的内存。\n                this._img.src = BLANK;\n                this._img = this._blob = null;\n            },\n    \n            _resize: function( img, cvs, width, height ) {\n                var opts = this.options,\n                    naturalWidth = img.width,\n                    naturalHeight = img.height,\n                    orientation = this.getOrientation(),\n                    scale, w, h, x, y;\n    \n                // values that require 90 degree rotation\n                if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n    \n                    // 交换width, height的值。\n                    width ^= height;\n                    height ^= width;\n                    width ^= height;\n                }\n    \n                scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth,\n                        height / naturalHeight );\n    \n                // 不允许放大。\n                opts.allowMagnify || (scale = Math.min( 1, scale ));\n    \n                w = naturalWidth * scale;\n                h = naturalHeight * scale;\n    \n                if ( opts.crop ) {\n                    cvs.width = width;\n                    cvs.height = height;\n                } else {\n                    cvs.width = w;\n                    cvs.height = h;\n                }\n    \n                x = (cvs.width - w) / 2;\n                y = (cvs.height - h) / 2;\n    \n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n    \n                this._renderImageToCanvas( cvs, img, x, y, w, h );\n            },\n    \n            _rotate2Orientaion: function( canvas, orientation ) {\n                var width = canvas.width,\n                    height = canvas.height,\n                    ctx = canvas.getContext('2d');\n    \n                switch ( orientation ) {\n                    case 5:\n                    case 6:\n                    case 7:\n                    case 8:\n                        canvas.width = height;\n                        canvas.height = width;\n                        break;\n                }\n    \n                switch ( orientation ) {\n                    case 2:    // horizontal flip\n                        ctx.translate( width, 0 );\n                        ctx.scale( -1, 1 );\n                        break;\n    \n                    case 3:    // 180 rotate left\n                        ctx.translate( width, height );\n                        ctx.rotate( Math.PI );\n                        break;\n    \n                    case 4:    // vertical flip\n                        ctx.translate( 0, height );\n                        ctx.scale( 1, -1 );\n                        break;\n    \n                    case 5:    // vertical flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.scale( 1, -1 );\n                        break;\n    \n                    case 6:    // 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( 0, -height );\n                        break;\n    \n                    case 7:    // horizontal flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( width, -height );\n                        ctx.scale( -1, 1 );\n                        break;\n    \n                    case 8:    // 90 rotate left\n                        ctx.rotate( -0.5 * Math.PI );\n                        ctx.translate( -width, 0 );\n                        break;\n                }\n            },\n    \n            // https://github.com/stomita/ios-imagefile-megapixel/\n            // blob/master/src/megapix-image.js\n            _renderImageToCanvas: (function() {\n    \n                // 如果不是ios, 不需要这么复杂！\n                if ( !Base.os.ios ) {\n                    return function( canvas ) {\n                        var args = Base.slice( arguments, 1 ),\n                            ctx = canvas.getContext('2d');\n    \n                        ctx.drawImage.apply( ctx, args );\n                    };\n                }\n    \n                /**\n                 * Detecting vertical squash in loaded image.\n                 * Fixes a bug which squash image vertically while drawing into\n                 * canvas for some images.\n                 */\n                function detectVerticalSquash( img, iw, ih ) {\n                    var canvas = document.createElement('canvas'),\n                        ctx = canvas.getContext('2d'),\n                        sy = 0,\n                        ey = ih,\n                        py = ih,\n                        data, alpha, ratio;\n    \n    \n                    canvas.width = 1;\n                    canvas.height = ih;\n                    ctx.drawImage( img, 0, 0 );\n                    data = ctx.getImageData( 0, 0, 1, ih ).data;\n    \n                    // search image edge pixel position in case\n                    // it is squashed vertically.\n                    while ( py > sy ) {\n                        alpha = data[ (py - 1) * 4 + 3 ];\n    \n                        if ( alpha === 0 ) {\n                            ey = py;\n                        } else {\n                            sy = py;\n                        }\n    \n                        py = (ey + sy) >> 1;\n                    }\n    \n                    ratio = (py / ih);\n                    return (ratio === 0) ? 1 : ratio;\n                }\n    \n                // fix ie7 bug\n                // http://stackoverflow.com/questions/11929099/\n                // html5-canvas-drawimage-ratio-bug-ios\n                if ( Base.os.ios >= 7 ) {\n                    return function( canvas, img, x, y, w, h ) {\n                        var iw = img.naturalWidth,\n                            ih = img.naturalHeight,\n                            vertSquashRatio = detectVerticalSquash( img, iw, ih );\n    \n                        return canvas.getContext('2d').drawImage( img, 0, 0,\n                                iw * vertSquashRatio, ih * vertSquashRatio,\n                                x, y, w, h );\n                    };\n                }\n    \n                /**\n                 * Detect subsampling in loaded image.\n                 * In iOS, larger images than 2M pixels may be\n                 * subsampled in rendering.\n                 */\n                function detectSubsampling( img ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        canvas, ctx;\n    \n                    // subsampling may happen overmegapixel image\n                    if ( iw * ih > 1024 * 1024 ) {\n                        canvas = document.createElement('canvas');\n                        canvas.width = canvas.height = 1;\n                        ctx = canvas.getContext('2d');\n                        ctx.drawImage( img, -iw + 1, 0 );\n    \n                        // subsampled image becomes half smaller in rendering size.\n                        // check alpha channel value to confirm image is covering\n                        // edge pixel or not. if alpha value is 0\n                        // image is not covering, hence subsampled.\n                        return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0;\n                    } else {\n                        return false;\n                    }\n                }\n    \n    \n                return function( canvas, img, x, y, width, height ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        ctx = canvas.getContext('2d'),\n                        subsampled = detectSubsampling( img ),\n                        doSquash = this.type === 'image/jpeg',\n                        d = 1024,\n                        sy = 0,\n                        dy = 0,\n                        tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx;\n    \n                    if ( subsampled ) {\n                        iw /= 2;\n                        ih /= 2;\n                    }\n    \n                    ctx.save();\n                    tmpCanvas = document.createElement('canvas');\n                    tmpCanvas.width = tmpCanvas.height = d;\n    \n                    tmpCtx = tmpCanvas.getContext('2d');\n                    vertSquashRatio = doSquash ?\n                            detectVerticalSquash( img, iw, ih ) : 1;\n    \n                    dw = Math.ceil( d * width / iw );\n                    dh = Math.ceil( d * height / ih / vertSquashRatio );\n    \n                    while ( sy < ih ) {\n                        sx = 0;\n                        dx = 0;\n                        while ( sx < iw ) {\n                            tmpCtx.clearRect( 0, 0, d, d );\n                            tmpCtx.drawImage( img, -sx, -sy );\n                            ctx.drawImage( tmpCanvas, 0, 0, d, d,\n                                    x + dx, y + dy, dw, dh );\n                            sx += d;\n                            dx += dw;\n                        }\n                        sy += d;\n                        dy += dh;\n                    }\n                    ctx.restore();\n                    tmpCanvas = tmpCtx = null;\n                };\n            })()\n        });\n    });\n    /**\n     * 这个方式性能不行，但是可以解决android里面的toDataUrl的bug\n     * android里面toDataUrl('image/jpege')得到的结果却是png.\n     *\n     * 所以这里没辙，只能借助这个工具\n     * @fileOverview jpeg encoder\n     */\n    define('runtime/html5/jpegencoder',[], function( require, exports, module ) {\n    \n        /*\n          Copyright (c) 2008, Adobe Systems Incorporated\n          All rights reserved.\n    \n          Redistribution and use in source and binary forms, with or without\n          modification, are permitted provided that the following conditions are\n          met:\n    \n          * Redistributions of source code must retain the above copyright notice,\n            this list of conditions and the following disclaimer.\n    \n          * Redistributions in binary form must reproduce the above copyright\n            notice, this list of conditions and the following disclaimer in the\n            documentation and/or other materials provided with the distribution.\n    \n          * Neither the name of Adobe Systems Incorporated nor the names of its\n            contributors may be used to endorse or promote products derived from\n            this software without specific prior written permission.\n    \n          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n          IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n          THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n          PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n          CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n          EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n          PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n          PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n          LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n          NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n        */\n        /*\n        JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009\n    \n        Basic GUI blocking jpeg encoder\n        */\n    \n        function JPEGEncoder(quality) {\n          var self = this;\n            var fround = Math.round;\n            var ffloor = Math.floor;\n            var YTable = new Array(64);\n            var UVTable = new Array(64);\n            var fdtbl_Y = new Array(64);\n            var fdtbl_UV = new Array(64);\n            var YDC_HT;\n            var UVDC_HT;\n            var YAC_HT;\n            var UVAC_HT;\n    \n            var bitcode = new Array(65535);\n            var category = new Array(65535);\n            var outputfDCTQuant = new Array(64);\n            var DU = new Array(64);\n            var byteout = [];\n            var bytenew = 0;\n            var bytepos = 7;\n    \n            var YDU = new Array(64);\n            var UDU = new Array(64);\n            var VDU = new Array(64);\n            var clt = new Array(256);\n            var RGB_YUV_TABLE = new Array(2048);\n            var currentQuality;\n    \n            var ZigZag = [\n                     0, 1, 5, 6,14,15,27,28,\n                     2, 4, 7,13,16,26,29,42,\n                     3, 8,12,17,25,30,41,43,\n                     9,11,18,24,31,40,44,53,\n                    10,19,23,32,39,45,52,54,\n                    20,22,33,38,46,51,55,60,\n                    21,34,37,47,50,56,59,61,\n                    35,36,48,49,57,58,62,63\n                ];\n    \n            var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];\n            var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];\n            var std_ac_luminance_values = [\n                    0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,\n                    0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,\n                    0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,\n                    0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,\n                    0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,\n                    0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,\n                    0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,\n                    0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,\n                    0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,\n                    0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,\n                    0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,\n                    0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,\n                    0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,\n                    0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,\n                    0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,\n                    0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,\n                    0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,\n                    0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,\n                    0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,\n                    0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n    \n            var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];\n            var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];\n            var std_ac_chrominance_values = [\n                    0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,\n                    0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,\n                    0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,\n                    0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,\n                    0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,\n                    0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,\n                    0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,\n                    0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,\n                    0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,\n                    0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,\n                    0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,\n                    0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,\n                    0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,\n                    0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,\n                    0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,\n                    0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,\n                    0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,\n                    0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,\n                    0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,\n                    0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n    \n            function initQuantTables(sf){\n                    var YQT = [\n                        16, 11, 10, 16, 24, 40, 51, 61,\n                        12, 12, 14, 19, 26, 58, 60, 55,\n                        14, 13, 16, 24, 40, 57, 69, 56,\n                        14, 17, 22, 29, 51, 87, 80, 62,\n                        18, 22, 37, 56, 68,109,103, 77,\n                        24, 35, 55, 64, 81,104,113, 92,\n                        49, 64, 78, 87,103,121,120,101,\n                        72, 92, 95, 98,112,100,103, 99\n                    ];\n    \n                    for (var i = 0; i < 64; i++) {\n                        var t = ffloor((YQT[i]*sf+50)/100);\n                        if (t < 1) {\n                            t = 1;\n                        } else if (t > 255) {\n                            t = 255;\n                        }\n                        YTable[ZigZag[i]] = t;\n                    }\n                    var UVQT = [\n                        17, 18, 24, 47, 99, 99, 99, 99,\n                        18, 21, 26, 66, 99, 99, 99, 99,\n                        24, 26, 56, 99, 99, 99, 99, 99,\n                        47, 66, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99\n                    ];\n                    for (var j = 0; j < 64; j++) {\n                        var u = ffloor((UVQT[j]*sf+50)/100);\n                        if (u < 1) {\n                            u = 1;\n                        } else if (u > 255) {\n                            u = 255;\n                        }\n                        UVTable[ZigZag[j]] = u;\n                    }\n                    var aasf = [\n                        1.0, 1.387039845, 1.306562965, 1.175875602,\n                        1.0, 0.785694958, 0.541196100, 0.275899379\n                    ];\n                    var k = 0;\n                    for (var row = 0; row < 8; row++)\n                    {\n                        for (var col = 0; col < 8; col++)\n                        {\n                            fdtbl_Y[k]  = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            k++;\n                        }\n                    }\n                }\n    \n                function computeHuffmanTbl(nrcodes, std_table){\n                    var codevalue = 0;\n                    var pos_in_table = 0;\n                    var HT = new Array();\n                    for (var k = 1; k <= 16; k++) {\n                        for (var j = 1; j <= nrcodes[k]; j++) {\n                            HT[std_table[pos_in_table]] = [];\n                            HT[std_table[pos_in_table]][0] = codevalue;\n                            HT[std_table[pos_in_table]][1] = k;\n                            pos_in_table++;\n                            codevalue++;\n                        }\n                        codevalue*=2;\n                    }\n                    return HT;\n                }\n    \n                function initHuffmanTbl()\n                {\n                    YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);\n                    UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);\n                    YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);\n                    UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);\n                }\n    \n                function initCategoryNumber()\n                {\n                    var nrlower = 1;\n                    var nrupper = 2;\n                    for (var cat = 1; cat <= 15; cat++) {\n                        //Positive numbers\n                        for (var nr = nrlower; nr<nrupper; nr++) {\n                            category[32767+nr] = cat;\n                            bitcode[32767+nr] = [];\n                            bitcode[32767+nr][1] = cat;\n                            bitcode[32767+nr][0] = nr;\n                        }\n                        //Negative numbers\n                        for (var nrneg =-(nrupper-1); nrneg<=-nrlower; nrneg++) {\n                            category[32767+nrneg] = cat;\n                            bitcode[32767+nrneg] = [];\n                            bitcode[32767+nrneg][1] = cat;\n                            bitcode[32767+nrneg][0] = nrupper-1+nrneg;\n                        }\n                        nrlower <<= 1;\n                        nrupper <<= 1;\n                    }\n                }\n    \n                function initRGBYUVTable() {\n                    for(var i = 0; i < 256;i++) {\n                        RGB_YUV_TABLE[i]            =  19595 * i;\n                        RGB_YUV_TABLE[(i+ 256)>>0]  =  38470 * i;\n                        RGB_YUV_TABLE[(i+ 512)>>0]  =   7471 * i + 0x8000;\n                        RGB_YUV_TABLE[(i+ 768)>>0]  = -11059 * i;\n                        RGB_YUV_TABLE[(i+1024)>>0]  = -21709 * i;\n                        RGB_YUV_TABLE[(i+1280)>>0]  =  32768 * i + 0x807FFF;\n                        RGB_YUV_TABLE[(i+1536)>>0]  = -27439 * i;\n                        RGB_YUV_TABLE[(i+1792)>>0]  = - 5329 * i;\n                    }\n                }\n    \n                // IO functions\n                function writeBits(bs)\n                {\n                    var value = bs[0];\n                    var posval = bs[1]-1;\n                    while ( posval >= 0 ) {\n                        if (value & (1 << posval) ) {\n                            bytenew |= (1 << bytepos);\n                        }\n                        posval--;\n                        bytepos--;\n                        if (bytepos < 0) {\n                            if (bytenew == 0xFF) {\n                                writeByte(0xFF);\n                                writeByte(0);\n                            }\n                            else {\n                                writeByte(bytenew);\n                            }\n                            bytepos=7;\n                            bytenew=0;\n                        }\n                    }\n                }\n    \n                function writeByte(value)\n                {\n                    byteout.push(clt[value]); // write char directly instead of converting later\n                }\n    \n                function writeWord(value)\n                {\n                    writeByte((value>>8)&0xFF);\n                    writeByte((value   )&0xFF);\n                }\n    \n                // DCT & quantization core\n                function fDCTQuant(data, fdtbl)\n                {\n                    var d0, d1, d2, d3, d4, d5, d6, d7;\n                    /* Pass 1: process rows. */\n                    var dataOff=0;\n                    var i;\n                    var I8 = 8;\n                    var I64 = 64;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff+1];\n                        d2 = data[dataOff+2];\n                        d3 = data[dataOff+3];\n                        d4 = data[dataOff+4];\n                        d5 = data[dataOff+5];\n                        d6 = data[dataOff+6];\n                        d7 = data[dataOff+7];\n    \n                        var tmp0 = d0 + d7;\n                        var tmp7 = d0 - d7;\n                        var tmp1 = d1 + d6;\n                        var tmp6 = d1 - d6;\n                        var tmp2 = d2 + d5;\n                        var tmp5 = d2 - d5;\n                        var tmp3 = d3 + d4;\n                        var tmp4 = d3 - d4;\n    \n                        /* Even part */\n                        var tmp10 = tmp0 + tmp3;    /* phase 2 */\n                        var tmp13 = tmp0 - tmp3;\n                        var tmp11 = tmp1 + tmp2;\n                        var tmp12 = tmp1 - tmp2;\n    \n                        data[dataOff] = tmp10 + tmp11; /* phase 3 */\n                        data[dataOff+4] = tmp10 - tmp11;\n    \n                        var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */\n                        data[dataOff+2] = tmp13 + z1; /* phase 5 */\n                        data[dataOff+6] = tmp13 - z1;\n    \n                        /* Odd part */\n                        tmp10 = tmp4 + tmp5; /* phase 2 */\n                        tmp11 = tmp5 + tmp6;\n                        tmp12 = tmp6 + tmp7;\n    \n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */\n                        var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */\n                        var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */\n                        var z3 = tmp11 * 0.707106781; /* c4 */\n    \n                        var z11 = tmp7 + z3;    /* phase 5 */\n                        var z13 = tmp7 - z3;\n    \n                        data[dataOff+5] = z13 + z2; /* phase 6 */\n                        data[dataOff+3] = z13 - z2;\n                        data[dataOff+1] = z11 + z4;\n                        data[dataOff+7] = z11 - z4;\n    \n                        dataOff += 8; /* advance pointer to next row */\n                    }\n    \n                    /* Pass 2: process columns. */\n                    dataOff = 0;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff + 8];\n                        d2 = data[dataOff + 16];\n                        d3 = data[dataOff + 24];\n                        d4 = data[dataOff + 32];\n                        d5 = data[dataOff + 40];\n                        d6 = data[dataOff + 48];\n                        d7 = data[dataOff + 56];\n    \n                        var tmp0p2 = d0 + d7;\n                        var tmp7p2 = d0 - d7;\n                        var tmp1p2 = d1 + d6;\n                        var tmp6p2 = d1 - d6;\n                        var tmp2p2 = d2 + d5;\n                        var tmp5p2 = d2 - d5;\n                        var tmp3p2 = d3 + d4;\n                        var tmp4p2 = d3 - d4;\n    \n                        /* Even part */\n                        var tmp10p2 = tmp0p2 + tmp3p2;  /* phase 2 */\n                        var tmp13p2 = tmp0p2 - tmp3p2;\n                        var tmp11p2 = tmp1p2 + tmp2p2;\n                        var tmp12p2 = tmp1p2 - tmp2p2;\n    \n                        data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */\n                        data[dataOff+32] = tmp10p2 - tmp11p2;\n    \n                        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */\n                        data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */\n                        data[dataOff+48] = tmp13p2 - z1p2;\n    \n                        /* Odd part */\n                        tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */\n                        tmp11p2 = tmp5p2 + tmp6p2;\n                        tmp12p2 = tmp6p2 + tmp7p2;\n    \n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */\n                        var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */\n                        var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */\n                        var z3p2 = tmp11p2 * 0.707106781; /* c4 */\n    \n                        var z11p2 = tmp7p2 + z3p2;  /* phase 5 */\n                        var z13p2 = tmp7p2 - z3p2;\n    \n                        data[dataOff+40] = z13p2 + z2p2; /* phase 6 */\n                        data[dataOff+24] = z13p2 - z2p2;\n                        data[dataOff+ 8] = z11p2 + z4p2;\n                        data[dataOff+56] = z11p2 - z4p2;\n    \n                        dataOff++; /* advance pointer to next column */\n                    }\n    \n                    // Quantize/descale the coefficients\n                    var fDCTQuant;\n                    for (i=0; i<I64; ++i)\n                    {\n                        // Apply the quantization and scaling factor & Round to nearest integer\n                        fDCTQuant = data[i]*fdtbl[i];\n                        outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);\n                        //outputfDCTQuant[i] = fround(fDCTQuant);\n    \n                    }\n                    return outputfDCTQuant;\n                }\n    \n                function writeAPP0()\n                {\n                    writeWord(0xFFE0); // marker\n                    writeWord(16); // length\n                    writeByte(0x4A); // J\n                    writeByte(0x46); // F\n                    writeByte(0x49); // I\n                    writeByte(0x46); // F\n                    writeByte(0); // = \"JFIF\",'\\0'\n                    writeByte(1); // versionhi\n                    writeByte(1); // versionlo\n                    writeByte(0); // xyunits\n                    writeWord(1); // xdensity\n                    writeWord(1); // ydensity\n                    writeByte(0); // thumbnwidth\n                    writeByte(0); // thumbnheight\n                }\n    \n                function writeSOF0(width, height)\n                {\n                    writeWord(0xFFC0); // marker\n                    writeWord(17);   // length, truecolor YUV JPG\n                    writeByte(8);    // precision\n                    writeWord(height);\n                    writeWord(width);\n                    writeByte(3);    // nrofcomponents\n                    writeByte(1);    // IdY\n                    writeByte(0x11); // HVY\n                    writeByte(0);    // QTY\n                    writeByte(2);    // IdU\n                    writeByte(0x11); // HVU\n                    writeByte(1);    // QTU\n                    writeByte(3);    // IdV\n                    writeByte(0x11); // HVV\n                    writeByte(1);    // QTV\n                }\n    \n                function writeDQT()\n                {\n                    writeWord(0xFFDB); // marker\n                    writeWord(132);    // length\n                    writeByte(0);\n                    for (var i=0; i<64; i++) {\n                        writeByte(YTable[i]);\n                    }\n                    writeByte(1);\n                    for (var j=0; j<64; j++) {\n                        writeByte(UVTable[j]);\n                    }\n                }\n    \n                function writeDHT()\n                {\n                    writeWord(0xFFC4); // marker\n                    writeWord(0x01A2); // length\n    \n                    writeByte(0); // HTYDCinfo\n                    for (var i=0; i<16; i++) {\n                        writeByte(std_dc_luminance_nrcodes[i+1]);\n                    }\n                    for (var j=0; j<=11; j++) {\n                        writeByte(std_dc_luminance_values[j]);\n                    }\n    \n                    writeByte(0x10); // HTYACinfo\n                    for (var k=0; k<16; k++) {\n                        writeByte(std_ac_luminance_nrcodes[k+1]);\n                    }\n                    for (var l=0; l<=161; l++) {\n                        writeByte(std_ac_luminance_values[l]);\n                    }\n    \n                    writeByte(1); // HTUDCinfo\n                    for (var m=0; m<16; m++) {\n                        writeByte(std_dc_chrominance_nrcodes[m+1]);\n                    }\n                    for (var n=0; n<=11; n++) {\n                        writeByte(std_dc_chrominance_values[n]);\n                    }\n    \n                    writeByte(0x11); // HTUACinfo\n                    for (var o=0; o<16; o++) {\n                        writeByte(std_ac_chrominance_nrcodes[o+1]);\n                    }\n                    for (var p=0; p<=161; p++) {\n                        writeByte(std_ac_chrominance_values[p]);\n                    }\n                }\n    \n                function writeSOS()\n                {\n                    writeWord(0xFFDA); // marker\n                    writeWord(12); // length\n                    writeByte(3); // nrofcomponents\n                    writeByte(1); // IdY\n                    writeByte(0); // HTY\n                    writeByte(2); // IdU\n                    writeByte(0x11); // HTU\n                    writeByte(3); // IdV\n                    writeByte(0x11); // HTV\n                    writeByte(0); // Ss\n                    writeByte(0x3f); // Se\n                    writeByte(0); // Bf\n                }\n    \n                function processDU(CDU, fdtbl, DC, HTDC, HTAC){\n                    var EOB = HTAC[0x00];\n                    var M16zeroes = HTAC[0xF0];\n                    var pos;\n                    var I16 = 16;\n                    var I63 = 63;\n                    var I64 = 64;\n                    var DU_DCT = fDCTQuant(CDU, fdtbl);\n                    //ZigZag reorder\n                    for (var j=0;j<I64;++j) {\n                        DU[ZigZag[j]]=DU_DCT[j];\n                    }\n                    var Diff = DU[0] - DC; DC = DU[0];\n                    //Encode DC\n                    if (Diff==0) {\n                        writeBits(HTDC[0]); // Diff might be 0\n                    } else {\n                        pos = 32767+Diff;\n                        writeBits(HTDC[category[pos]]);\n                        writeBits(bitcode[pos]);\n                    }\n                    //Encode ACs\n                    var end0pos = 63; // was consts... which is crazy\n                    for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {};\n                    //end0pos = first element in reverse order !=0\n                    if ( end0pos == 0) {\n                        writeBits(EOB);\n                        return DC;\n                    }\n                    var i = 1;\n                    var lng;\n                    while ( i <= end0pos ) {\n                        var startpos = i;\n                        for (; (DU[i]==0) && (i<=end0pos); ++i) {}\n                        var nrzeroes = i-startpos;\n                        if ( nrzeroes >= I16 ) {\n                            lng = nrzeroes>>4;\n                            for (var nrmarker=1; nrmarker <= lng; ++nrmarker)\n                                writeBits(M16zeroes);\n                            nrzeroes = nrzeroes&0xF;\n                        }\n                        pos = 32767+DU[i];\n                        writeBits(HTAC[(nrzeroes<<4)+category[pos]]);\n                        writeBits(bitcode[pos]);\n                        i++;\n                    }\n                    if ( end0pos != I63 ) {\n                        writeBits(EOB);\n                    }\n                    return DC;\n                }\n    \n                function initCharLookupTable(){\n                    var sfcc = String.fromCharCode;\n                    for(var i=0; i < 256; i++){ ///// ACHTUNG // 255\n                        clt[i] = sfcc(i);\n                    }\n                }\n    \n                this.encode = function(image,quality) // image data object\n                {\n                    // var time_start = new Date().getTime();\n    \n                    if(quality) setQuality(quality);\n    \n                    // Initialize bit writer\n                    byteout = new Array();\n                    bytenew=0;\n                    bytepos=7;\n    \n                    // Add JPEG headers\n                    writeWord(0xFFD8); // SOI\n                    writeAPP0();\n                    writeDQT();\n                    writeSOF0(image.width,image.height);\n                    writeDHT();\n                    writeSOS();\n    \n    \n                    // Encode 8x8 macroblocks\n                    var DCY=0;\n                    var DCU=0;\n                    var DCV=0;\n    \n                    bytenew=0;\n                    bytepos=7;\n    \n    \n                    this.encode.displayName = \"_encode_\";\n    \n                    var imageData = image.data;\n                    var width = image.width;\n                    var height = image.height;\n    \n                    var quadWidth = width*4;\n                    var tripleWidth = width*3;\n    \n                    var x, y = 0;\n                    var r, g, b;\n                    var start,p, col,row,pos;\n                    while(y < height){\n                        x = 0;\n                        while(x < quadWidth){\n                        start = quadWidth * y + x;\n                        p = start;\n                        col = -1;\n                        row = 0;\n    \n                        for(pos=0; pos < 64; pos++){\n                            row = pos >> 3;// /8\n                            col = ( pos & 7 ) * 4; // %8\n                            p = start + ( row * quadWidth ) + col;\n    \n                            if(y+row >= height){ // padding bottom\n                                p-= (quadWidth*(y+1+row-height));\n                            }\n    \n                            if(x+col >= quadWidth){ // padding right\n                                p-= ((x+col) - quadWidth +4)\n                            }\n    \n                            r = imageData[ p++ ];\n                            g = imageData[ p++ ];\n                            b = imageData[ p++ ];\n    \n    \n                            /* // calculate YUV values dynamically\n                            YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80\n                            UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));\n                            VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));\n                            */\n    \n                            // use lookup table (slightly faster)\n                            YDU[pos] = ((RGB_YUV_TABLE[r]             + RGB_YUV_TABLE[(g +  256)>>0] + RGB_YUV_TABLE[(b +  512)>>0]) >> 16)-128;\n                            UDU[pos] = ((RGB_YUV_TABLE[(r +  768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128;\n                            VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128;\n    \n                        }\n    \n                        DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);\n                        DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);\n                        DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);\n                        x+=32;\n                        }\n                        y+=8;\n                    }\n    \n    \n                    ////////////////////////////////////////////////////////////////\n    \n                    // Do the bit alignment of the EOI marker\n                    if ( bytepos >= 0 ) {\n                        var fillbits = [];\n                        fillbits[1] = bytepos+1;\n                        fillbits[0] = (1<<(bytepos+1))-1;\n                        writeBits(fillbits);\n                    }\n    \n                    writeWord(0xFFD9); //EOI\n    \n                    var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join(''));\n    \n                    byteout = [];\n    \n                    // benchmarking\n                    // var duration = new Date().getTime() - time_start;\n                    // console.log('Encoding time: '+ currentQuality + 'ms');\n                    //\n    \n                    return jpegDataUri\n            }\n    \n            function setQuality(quality){\n                if (quality <= 0) {\n                    quality = 1;\n                }\n                if (quality > 100) {\n                    quality = 100;\n                }\n    \n                if(currentQuality == quality) return // don't recalc if unchanged\n    \n                var sf = 0;\n                if (quality < 50) {\n                    sf = Math.floor(5000 / quality);\n                } else {\n                    sf = Math.floor(200 - quality*2);\n                }\n    \n                initQuantTables(sf);\n                currentQuality = quality;\n                // console.log('Quality set to: '+quality +'%');\n            }\n    \n            function init(){\n                // var time_start = new Date().getTime();\n                if(!quality) quality = 50;\n                // Create tables\n                initCharLookupTable()\n                initHuffmanTbl();\n                initCategoryNumber();\n                initRGBYUVTable();\n    \n                setQuality(quality);\n                // var duration = new Date().getTime() - time_start;\n                // console.log('Initialization '+ duration + 'ms');\n            }\n    \n            init();\n    \n        };\n    \n        JPEGEncoder.encode = function( data, quality ) {\n            var encoder = new JPEGEncoder( quality );\n    \n            return encoder.encode( data );\n        }\n    \n        return JPEGEncoder;\n    });\n    /**\n     * @fileOverview Fix android canvas.toDataUrl bug.\n     */\n    define('runtime/html5/androidpatch',[\n        'runtime/html5/util',\n        'runtime/html5/jpegencoder',\n        'base'\n    ], function( Util, encoder, Base ) {\n        var origin = Util.canvasToDataUrl,\n            supportJpeg;\n    \n        Util.canvasToDataUrl = function( canvas, type, quality ) {\n            var ctx, w, h, fragement, parts;\n    \n            // 非android手机直接跳过。\n            if ( !Base.os.android ) {\n                return origin.apply( null, arguments );\n            }\n    \n            // 检测是否canvas支持jpeg导出，根据数据格式来判断。\n            // JPEG 前两位分别是：255, 216\n            if ( type === 'image/jpeg' && typeof supportJpeg === 'undefined' ) {\n                fragement = origin.apply( null, arguments );\n    \n                parts = fragement.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    fragement = atob( parts[ 1 ] );\n                } else {\n                    fragement = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                fragement = fragement.substring( 0, 2 );\n    \n                supportJpeg = fragement.charCodeAt( 0 ) === 255 &&\n                        fragement.charCodeAt( 1 ) === 216;\n            }\n    \n            // 只有在android环境下才修复\n            if ( type === 'image/jpeg' && !supportJpeg ) {\n                w = canvas.width;\n                h = canvas.height;\n                ctx = canvas.getContext('2d');\n    \n                return encoder.encode( ctx.getImageData( 0, 0, w, h ), quality );\n            }\n    \n            return origin.apply( null, arguments );\n        };\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var noop = Base.noop,\n            $ = Base.$;\n    \n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n    \n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n    \n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n    \n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n    \n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n    \n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n    \n            getResponse: function() {\n                return this._response;\n            },\n    \n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n    \n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n    \n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n    \n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n    \n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n    \n                    return me.trigger( 'progress', percentage );\n                };\n    \n                xhr.onreadystatechange = function() {\n    \n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n    \n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n    \n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n    \n    \n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n    \n            _parseJson: function( str ) {\n                var json;\n    \n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n    \n                return json;\n            }\n        });\n    });\n    define('webuploader',[\n        'base',\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/log',\n        'runtime/html5/blob',\n        'runtime/html5/filepicker',\n        'runtime/html5/imagemeta/exif',\n        'runtime/html5/image',\n        'runtime/html5/androidpatch',\n        'runtime/html5/transport'\n    ], function( Base ) {\n        return Base;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/webuploader.fis.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\nvar jQuery = require('example:widget/ui/jquery/jquery.js')\n\nreturn (function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        };\n\n    return makeExport( jQuery );\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n    \n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n    \n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n    \n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n    \n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n    \n        var noop = function() {},\n            call = Function.call;\n    \n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n    \n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n    \n        function createObject( proto ) {\n            var f;\n    \n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n    \n    \n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n    \n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n    \n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n    \n            Deferred: promise.Deferred,\n    \n            isPromise: promise.isPromise,\n    \n            when: promise.when,\n    \n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n    \n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n    \n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n    \n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n    \n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n    \n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n    \n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n    \n                /* jshint camelcase: false */\n    \n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n    \n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n    \n                return child;\n            },\n    \n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n    \n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n    \n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n    \n            nextTick: (function() {\n    \n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n    \n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n    \n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n    \n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n    \n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n    \n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n    \n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n    \n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n    \n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n    \n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n    \n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n    \n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n    \n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n    \n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n    \n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n    \n            while ( ++i < len ) {\n                handler = events[ i ];\n    \n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n    \n            return !stoped;\n        }\n    \n        protos = {\n    \n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n    \n                if ( !callback ) {\n                    return this;\n                }\n    \n                set = this._events || (this._events = []);\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n    \n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n    \n                    set.push( handler );\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n    \n                if ( !callback ) {\n                    return me;\n                }\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n    \n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n    \n                return me;\n            },\n    \n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n    \n                if ( !events ) {\n                    return this;\n                }\n    \n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n    \n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n    \n                if ( !this._events || !type ) {\n                    return this;\n                }\n    \n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n    \n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n    \n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n    \n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n    \n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$;\n    \n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n    \n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n    \n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n    \n        $.extend( Uploader.prototype, {\n            state: 'pending',\n    \n            _init: function( opts ) {\n                var me = this;\n    \n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n    \n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n    \n                // setter\n                if ( arguments.length > 1 ) {\n    \n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n    \n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n    \n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n    \n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n    \n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n    \n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n    \n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n    \n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n    \n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n    \n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n    \n                    return false;\n                }\n    \n                return true;\n            },\n    \n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n    \n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n    \n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n    \n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n    \n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            factories = {},\n    \n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n    \n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n    \n        $.extend( Runtime.prototype, {\n    \n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n    \n                if ( this._container ) {\n                    return this._container;\n                }\n    \n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n    \n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n    \n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n    \n            init: Base.noop,\n            exec: Base.noop,\n    \n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n    \n        Runtime.orders = 'html5,flash';\n    \n    \n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n    \n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n    \n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n    \n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n    \n            type = type || getFirstKey( factories );\n    \n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n    \n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n    \n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n    \n        var cache;\n    \n        cache = (function() {\n            var obj = {};\n    \n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n    \n                get: function( ruid, standalone ) {\n                    var i;\n    \n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n    \n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n    \n                        return obj[ i ];\n                    }\n    \n                    return null;\n                },\n    \n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n    \n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n    \n            this.uid = Base.guid('client_');\n    \n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n    \n            this.connectRuntime = function( opts, cb ) {\n    \n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n    \n                deferred.done( cb );\n    \n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n    \n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n    \n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n    \n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                runtime.__client--;\n    \n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n    \n                runtime = null;\n            };\n    \n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n    \n                return runtime.exec.apply( this, args );\n            };\n    \n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n    \n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n    \n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n    \n            opts.container = $( opts.container );\n    \n            if ( !opts.container.length ) {\n                return;\n            }\n    \n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n    \n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( DragAndDrop.prototype );\n    \n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n    \n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n    \n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n    \n            var length = obj.length,\n                type = $.type( obj );\n    \n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n    \n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n    \n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n    \n        $.extend( Widget.prototype, {\n    \n            init: Base.noop,\n    \n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n    \n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n    \n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n    \n                    return IGNORE;\n                }\n    \n                return this[ map[ apiName ] ].apply( this, args );\n    \n            },\n    \n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n    \n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n    \n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n    \n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n    \n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n    \n                return _init.apply( me, arguments );\n            },\n    \n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n    \n                args = isArrayLike( args ) ? args : [ args ];\n    \n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n    \n                    if ( rlt !== IGNORE ) {\n    \n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n    \n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n    \n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n    \n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n    \n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n    \n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n    \n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n    \n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n    \n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n    \n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n    \n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n    \n            } else {\n                map = $.extend( map, responseMap );\n            }\n    \n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n    \n            return klass;\n        };\n    \n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *     \n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n            \n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n    \n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n    \n        Uploader.options.dnd = '';\n    \n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n        \n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n    \n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n            \n            init: function( opts ) {\n    \n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n    \n                this.dnd = dnd = new Dnd( options );\n    \n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n    \n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n    \n                dnd.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( FilePaste.prototype );\n    \n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n    \n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n            \n            init: function( opts ) {\n    \n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n    \n                this.paste = paste = new FilePaste( options );\n    \n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n    \n        function Blob( ruid, source ) {\n            var me = this;\n    \n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n    \n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n    \n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n    \n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n    \n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n    \n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n    \n            getSource: function() {\n                return this.source;\n            }\n        });\n    \n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n    \n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n    \n        function File( ruid, file ) {\n            var ext;\n    \n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n    \n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n    \n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n    \n            Blob.apply( this, arguments );\n        }\n    \n        return Base.inherits( Blob, File );\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n    \n        var $ = Base.$;\n    \n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n    \n            opts.container = $( opts.id );\n    \n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n    \n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n    \n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n    \n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n    \n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n    \n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n    \n                button.addClass('webuploader-pick');\n    \n                me.on( 'all', function( type ) {\n                    var files;\n    \n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n    \n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n    \n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n    \n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n    \n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n    \n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n    \n                    pos = button.offset();\n    \n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n    \n            enable: function() {\n                var btn = this.options.button;\n    \n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n    \n            disable: function() {\n                var btn = this.options.button;\n    \n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n    \n                btn.addClass('webuploader-pick-disable');\n            },\n    \n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n    \n        return FilePicker;\n    });\n    \n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n    \n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n    \n        return Uploader.register({\n            name: 'picker',\n    \n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n    \n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n    \n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n    \n                if ( !pick ) {\n                    return;\n                }\n    \n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n    \n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n    \n                    deferred = Base.Deferred();\n    \n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n    \n                    picker = new FilePicker( options );\n    \n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n    \n                    me.pickers.push( picker );\n    \n                    promises.push( deferred.promise() );\n                });\n    \n                return Base.when.apply( Base, promises );\n            },\n    \n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n    \n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n    \n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n    \n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n    \n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n    \n        // 默认选项。\n        Image.options = {\n    \n            // 默认的图片处理质量\n            quality: 90,\n    \n            // 是否裁剪\n            crop: false,\n    \n            // 是否保留头部信息\n            preserveHeaders: false,\n    \n            // 是否允许放大。\n            allowMagnify: false\n        };\n    \n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n    \n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n    \n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n    \n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n    \n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    \n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n    \n        var $ = Base.$,\n            throttle;\n    \n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n    \n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n    \n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n    \n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n    \n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n    \n        return Uploader.register({\n    \n            name: 'image',\n    \n    \n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n    \n                opts = $.extend({}, this.options.thumb );\n    \n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n    \n                width = width || opts.width;\n                height = height || opts.height;\n    \n                image = new Image( opts );\n    \n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n    \n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n    \n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n    \n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n    \n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n    \n                image = new Image( opts );\n    \n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n    \n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                image.once( 'complete', function() {\n                    var blob, size;\n    \n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n    \n                        size = file.size;\n    \n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n    \n                            file.trigger( 'resize', blob.size, size );\n                        }\n    \n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n    \n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n    \n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n    \n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n    \n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n    \n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n    \n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n    \n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n    \n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n    \n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n    \n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n    \n    \n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n    \n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n    \n            this.source = source;\n            this.loaded = 0;\n    \n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n    \n        $.extend( WUFile.prototype, {\n    \n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n    \n                var prevStatus = statusMap[ this.id ];\n    \n                typeof text !== 'undefined' && (this.statusText = text);\n    \n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n    \n            },\n    \n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n    \n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n    \n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n    \n        Mediator.installTo( WUFile.prototype );\n    \n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n    \n        return WUFile;\n    });\n    \n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n    \n        var $ = Base.$,\n            STATUS = WUFile.Status;\n    \n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n    \n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n    \n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n    \n            // 存储所有文件\n            this._map = {};\n        }\n    \n        $.extend( Queue.prototype, {\n    \n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n    \n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n    \n                status = status || STATUS.QUEUED;\n    \n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n    \n                return null;\n            },\n    \n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n    \n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n    \n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n    \n                    ret.push( file );\n                }\n    \n                return ret;\n            },\n    \n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n    \n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n    \n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n    \n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n    \n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n    \n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n    \n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n    \n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n    \n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n    \n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n    \n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n    \n        });\n    \n        Mediator.installTo( Queue.prototype );\n    \n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n    \n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n    \n        return Uploader.register({\n            name: 'queue',\n    \n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n    \n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n    \n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n    \n                    me.accept = new RegExp( accept, 'i' );\n                }\n    \n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n    \n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n    \n    \n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n    \n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n    \n                    file = new WUFile( file );\n                }\n    \n                return file;\n            },\n    \n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n    \n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n    \n                return !invalid;\n            },\n    \n    \n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n    \n            _addFile: function( file ) {\n                var me = this;\n    \n                file = me._wrapFile( file );\n    \n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n    \n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n    \n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n    \n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n    \n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n            \n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             * \n             */\n    \n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n    \n                if ( !files.length ) {\n                    files = [ files ];\n                }\n    \n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n    \n                me.owner.trigger( 'filesQueued', files );\n    \n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n    \n            getStats: function() {\n                return this.stats;\n            },\n    \n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n    \n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n    \n                file = file.id ? file : me.queue.getFile( file );\n    \n                this.request( 'cancel-file', file );\n    \n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n    \n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n    \n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n    \n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n    \n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n    \n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n    \n                me.request('start-upload');\n            },\n    \n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n    \n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n    \n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n    \n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n    \n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n    \n        return Uploader.register({\n            name: 'runtime',\n    \n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n    \n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n    \n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n    \n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n    \n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n    \n        var $ = Base.$;\n    \n        function Transport( opts ) {\n            var me = this;\n    \n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n    \n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n    \n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n    \n        Transport.options = {\n            server: '',\n            method: 'POST',\n    \n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n    \n        $.extend( Transport.prototype, {\n    \n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n    \n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n    \n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n    \n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n    \n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n    \n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n    \n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n    \n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n    \n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n    \n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n    \n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n    \n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n    \n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n    \n                if ( !duration ) {\n                    return;\n                }\n    \n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n    \n        });\n    \n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n    \n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n    \n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n    \n        // 添加默认配置项\n        $.extend( Uploader.options, {\n    \n    \n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n    \n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n    \n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n    \n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n    \n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n    \n    \n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n    \n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n    \n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n    \n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n    \n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n    \n            api = {\n                file: file,\n    \n                has: function() {\n                    return !!pending.length;\n                },\n    \n                shift: function() {\n                    return pending.shift();\n                },\n    \n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n    \n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n    \n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n    \n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n    \n            return api;\n        }\n    \n        Uploader.register({\n            name: 'upload',\n    \n            init: function() {\n                var owner = this.owner,\n                    me = this;\n    \n                this.runing = false;\n                this.progress = false;\n    \n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n    \n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n    \n                // 缓存分好片的文件。\n                this.stack = [];\n    \n                // 缓存即将上传的文件。\n                this.pending = [];\n    \n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n    \n                owner.on( 'uploadComplete', function( file ) {\n    \n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n    \n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n    \n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n    \n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n    \n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n    \n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n    \n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n    \n                            v.transport && v.transport.send();\n                        });\n    \n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n    \n                if ( me.runing ) {\n                    return;\n                }\n    \n                me.runing = true;\n    \n                var files = [];\n    \n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n    \n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n    \n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n    \n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n    \n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n    \n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n    \n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n    \n                if ( me.runing === false ) {\n                    return;\n                }\n    \n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n    \n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n    \n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n    \n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n    \n                    return Base.nextTick( me.__tick );\n                }\n    \n                me.runing = false;\n    \n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n    \n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n    \n                me.owner.trigger('stopUpload');\n            },\n    \n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n    \n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n    \n            _getStats: function() {\n                return this.request('get-stats');\n            },\n    \n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                this.owner.trigger( 'uploadSkip', file );\n            },\n    \n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n    \n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n    \n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n    \n                    fn = function( val ) {\n                        me._promise = null;\n    \n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n    \n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n    \n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n    \n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n    \n            _putback: function(block) {\n                var idx;\n    \n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n    \n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n    \n            _getStack: function() {\n                var i = 0,\n                    act;\n    \n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n    \n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n    \n                return null;\n            },\n    \n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n    \n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n    \n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n    \n                    return act.shift();\n    \n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n    \n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n    \n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n    \n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n    \n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n    \n                    return done( next );\n                }\n            },\n    \n    \n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n    \n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n    \n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n    \n                        return me._finishFile( file );\n                    });\n    \n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n    \n                    promise.file = file;\n    \n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n    \n                        ~idx && pending.splice( idx, 1, file );\n                    });\n    \n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n    \n                    pending.push( promise );\n                }\n            },\n    \n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n    \n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n    \n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n    \n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n    \n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n    \n                    return;\n                }\n    \n                me.pool.push( block );\n                me.remaning++;\n    \n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n    \n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n    \n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n    \n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n    \n    \n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n    \n    \n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n    \n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n    \n                block.transport = tr;\n    \n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n    \n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n    \n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n    \n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n    \n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n    \n                    return reject;\n                };\n    \n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n    \n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n    \n                        block.retried++;\n                        tr.send();\n    \n                    } else {\n    \n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n    \n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n    \n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n    \n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n    \n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n    \n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n    \n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n    \n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n    \n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n    \n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n    \n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n    \n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n    \n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n    \n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n    \n                if (!file.blocks) {\n                    return;\n                }\n    \n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n    \n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n    \n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n    \n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n    \n        var $ = Base.$,\n            validators = {},\n            api;\n    \n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n    \n        // 暴露给外面的api\n        api = {\n    \n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n    \n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n    \n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n    \n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n    \n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return count >= max ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n    \n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n    \n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n    \n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return invalid ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n    \n            });\n    \n        });\n    \n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n    \n            if ( opts.duplicate ) {\n                return;\n            }\n    \n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n    \n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n    \n                return hash;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n    \n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (mapping[ hash ] = true);\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (delete mapping[ hash ]);\n            });\n    \n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n    \n        return api;\n    });\n    \n    /**\n     * @fileOverview Md5\n     */\n    define('lib/md5',[\n        'runtime/client',\n        'mediator'\n    ], function( RuntimeClient, Mediator ) {\n    \n        function Md5() {\n            RuntimeClient.call( this, 'Md5' );\n        }\n    \n        // 让 Md5 具备事件功能。\n        Mediator.installTo( Md5.prototype );\n    \n        Md5.prototype.loadFromBlob = function( blob ) {\n            var me = this;\n    \n            if ( me.getRuid() ) {\n                me.disconnectRuntime();\n            }\n    \n            // 连接到blob归属的同一个runtime.\n            me.connectRuntime( blob.ruid, function() {\n                me.exec('init');\n                me.exec( 'loadFromBlob', blob );\n            });\n        };\n    \n        Md5.prototype.getResult = function() {\n            return this.exec('getResult');\n        };\n    \n        return Md5;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/md5',[\n        'base',\n        'uploader',\n        'lib/md5',\n        'lib/blob',\n        'widgets/widget'\n    ], function( Base, Uploader, Md5, Blob ) {\n    \n        return Uploader.register({\n            name: 'md5',\n    \n    \n            /**\n             * 计算文件 md5 值，返回一个 promise 对象，可以监听 progress 进度。\n             *\n             *\n             * @method md5File\n             * @grammar md5File( file[, start[, end]] ) => promise\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.md5File( file )\n             *\n             *         // 及时显示进度\n             *         .progress(function(percentage) {\n             *             console.log('Percentage:', percentage);\n             *         })\n             *\n             *         // 完成\n             *         .then(function(val) {\n             *             console.log('md5 result:', val);\n             *         });\n             *\n             * });\n             */\n            md5File: function( file, start, end ) {\n                var md5 = new Md5(),\n                    deferred = Base.Deferred(),\n                    blob = (file instanceof Blob) ? file :\n                        this.request( 'get-file', file ).source;\n    \n                md5.on( 'progress load', function( e ) {\n                    e = e || {};\n                    deferred.notify( e.total ? e.loaded / e.total : 1 );\n                });\n    \n                md5.on( 'complete', function() {\n                    deferred.resolve( md5.getResult() );\n                });\n    \n                md5.on( 'error', function( reason ) {\n                    deferred.reject( reason );\n                });\n    \n                if ( arguments.length > 1 ) {\n                    start = start || 0;\n                    end = end || 0;\n                    start < 0 && (start = blob.size + start);\n                    end < 0 && (end = blob.size + end);\n                    end = Math.min( end, blob.size );\n                    blob = blob.slice( start, end );\n                }\n    \n                md5.loadFromBlob( blob );\n    \n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n    \n        function CompBase( owner, runtime ) {\n    \n            this.owner = owner;\n            this.options = owner.options;\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.getRuid = function() {\n                return runtime.uid;\n            };\n    \n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n    \n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var type = 'html5',\n            components = {};\n    \n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n    \n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n    \n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n    \n        });\n    \n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n    \n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n    \n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n    \n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n    \n                blob = slice.call( blob, start, end );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n    \n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n    \n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n    \n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n    \n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n    \n                e = e.originalEvent || e;\n    \n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n    \n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n    \n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n    \n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n    \n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n    \n                return false;\n            },\n    \n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n    \n                return false;\n            },\n    \n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n    \n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n    \n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n    \n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n    \n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n    \n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n    \n                if ( data ) {\n                    return;\n                }\n    \n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n    \n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n    \n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n    \n                items = dataTransfer.items;\n                files = dataTransfer.files;\n    \n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n    \n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n    \n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n    \n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n    \n                Base.when.apply( Base, promises ).done(function() {\n    \n                    if ( !results.length ) {\n                        return;\n                    }\n    \n                    callback( results );\n                });\n            },\n    \n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n    \n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n    \n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n    \n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                var elem = this.elem;\n    \n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n                \n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n    \n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n    \n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n    \n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n    \n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n    \n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n    \n                    allowed.push( new File( ruid, blob ) );\n                }\n    \n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n    \n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var $ = Base.$;\n    \n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n    \n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n    \n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n    \n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n    \n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n    \n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n    \n                    input.attr( 'accept', arr.join(',') );\n                }\n    \n                container.append( input );\n                container.append( label );\n    \n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n    \n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n    \n                    me.files = e.target.files;\n    \n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n    \n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n    \n                    owner.trigger('change');\n                });\n    \n                label.on( 'mouseenter mouseleave', mouseHandler );\n    \n            },\n    \n    \n            getFiles: function() {\n                return this.files;\n            },\n    \n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/util',[\n        'base'\n    ], function( Base ) {\n    \n        var urlAPI = window.createObjectURL && window ||\n                window.URL && URL.revokeObjectURL && URL ||\n                window.webkitURL,\n            createObjectURL = Base.noop,\n            revokeObjectURL = createObjectURL;\n    \n        if ( urlAPI ) {\n    \n            // 更安全的方式调用，比如android里面就能把context改成其他的对象。\n            createObjectURL = function() {\n                return urlAPI.createObjectURL.apply( urlAPI, arguments );\n            };\n    \n            revokeObjectURL = function() {\n                return urlAPI.revokeObjectURL.apply( urlAPI, arguments );\n            };\n        }\n    \n        return {\n            createObjectURL: createObjectURL,\n            revokeObjectURL: revokeObjectURL,\n    \n            dataURL2Blob: function( dataURI ) {\n                var byteStr, intArray, ab, i, mimetype, parts;\n    \n                parts = dataURI.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                ab = new ArrayBuffer( byteStr.length );\n                intArray = new Uint8Array( ab );\n    \n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n    \n                mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ];\n    \n                return this.arrayBufferToBlob( ab, mimetype );\n            },\n    \n            dataURL2ArrayBuffer: function( dataURI ) {\n                var byteStr, intArray, i, parts;\n    \n                parts = dataURI.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                intArray = new Uint8Array( byteStr.length );\n    \n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n    \n                return intArray.buffer;\n            },\n    \n            arrayBufferToBlob: function( buffer, type ) {\n                var builder = window.BlobBuilder || window.WebKitBlobBuilder,\n                    bb;\n    \n                // android不支持直接new Blob, 只能借助blobbuilder.\n                if ( builder ) {\n                    bb = new builder();\n                    bb.append( buffer );\n                    return bb.getBlob( type );\n                }\n    \n                return new Blob([ buffer ], type ? { type: type } : {} );\n            },\n    \n            // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg.\n            // 你得到的结果是png.\n            canvasToDataUrl: function( canvas, type, quality ) {\n                return canvas.toDataURL( type, quality / 100 );\n            },\n    \n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            parseMeta: function( blob, callback ) {\n                callback( false, {});\n            },\n    \n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            updateImageHead: function( data ) {\n                return data;\n            }\n        };\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/imagemeta',[\n        'runtime/html5/util'\n    ], function( Util ) {\n    \n        var api;\n    \n        api = {\n            parsers: {\n                0xffe1: []\n            },\n    \n            maxMetaDataSize: 262144,\n    \n            parse: function( blob, cb ) {\n                var me = this,\n                    fr = new FileReader();\n    \n                fr.onload = function() {\n                    cb( false, me._parse( this.result ) );\n                    fr = fr.onload = fr.onerror = null;\n                };\n    \n                fr.onerror = function( e ) {\n                    cb( e.message );\n                    fr = fr.onload = fr.onerror = null;\n                };\n    \n                blob = blob.slice( 0, me.maxMetaDataSize );\n                fr.readAsArrayBuffer( blob.getSource() );\n            },\n    \n            _parse: function( buffer, noParse ) {\n                if ( buffer.byteLength < 6 ) {\n                    return;\n                }\n    \n                var dataview = new DataView( buffer ),\n                    offset = 2,\n                    maxOffset = dataview.byteLength - 4,\n                    headLength = offset,\n                    ret = {},\n                    markerBytes, markerLength, parsers, i;\n    \n                if ( dataview.getUint16( 0 ) === 0xffd8 ) {\n    \n                    while ( offset < maxOffset ) {\n                        markerBytes = dataview.getUint16( offset );\n    \n                        if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef ||\n                                markerBytes === 0xfffe ) {\n    \n                            markerLength = dataview.getUint16( offset + 2 ) + 2;\n    \n                            if ( offset + markerLength > dataview.byteLength ) {\n                                break;\n                            }\n    \n                            parsers = api.parsers[ markerBytes ];\n    \n                            if ( !noParse && parsers ) {\n                                for ( i = 0; i < parsers.length; i += 1 ) {\n                                    parsers[ i ].call( api, dataview, offset,\n                                            markerLength, ret );\n                                }\n                            }\n    \n                            offset += markerLength;\n                            headLength = offset;\n                        } else {\n                            break;\n                        }\n                    }\n    \n                    if ( headLength > 6 ) {\n                        if ( buffer.slice ) {\n                            ret.imageHead = buffer.slice( 2, headLength );\n                        } else {\n                            // Workaround for IE10, which does not yet\n                            // support ArrayBuffer.slice:\n                            ret.imageHead = new Uint8Array( buffer )\n                                    .subarray( 2, headLength );\n                        }\n                    }\n                }\n    \n                return ret;\n            },\n    \n            updateImageHead: function( buffer, head ) {\n                var data = this._parse( buffer, true ),\n                    buf1, buf2, bodyoffset;\n    \n    \n                bodyoffset = 2;\n                if ( data.imageHead ) {\n                    bodyoffset = 2 + data.imageHead.byteLength;\n                }\n    \n                if ( buffer.slice ) {\n                    buf2 = buffer.slice( bodyoffset );\n                } else {\n                    buf2 = new Uint8Array( buffer ).subarray( bodyoffset );\n                }\n    \n                buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength );\n    \n                buf1[ 0 ] = 0xFF;\n                buf1[ 1 ] = 0xD8;\n                buf1.set( new Uint8Array( head ), 2 );\n                buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 );\n    \n                return buf1.buffer;\n            }\n        };\n    \n        Util.parseMeta = function() {\n            return api.parse.apply( api, arguments );\n        };\n    \n        Util.updateImageHead = function() {\n            return api.updateImageHead.apply( api, arguments );\n        };\n    \n        return api;\n    });\n    /**\n     * 代码来自于：https://github.com/blueimp/JavaScript-Load-Image\n     * 暂时项目中只用了orientation.\n     *\n     * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail.\n     * @fileOverview EXIF解析\n     */\n    \n    // Sample\n    // ====================================\n    // Make : Apple\n    // Model : iPhone 4S\n    // Orientation : 1\n    // XResolution : 72 [72/1]\n    // YResolution : 72 [72/1]\n    // ResolutionUnit : 2\n    // Software : QuickTime 7.7.1\n    // DateTime : 2013:09:01 22:53:55\n    // ExifIFDPointer : 190\n    // ExposureTime : 0.058823529411764705 [1/17]\n    // FNumber : 2.4 [12/5]\n    // ExposureProgram : Normal program\n    // ISOSpeedRatings : 800\n    // ExifVersion : 0220\n    // DateTimeOriginal : 2013:09:01 22:52:51\n    // DateTimeDigitized : 2013:09:01 22:52:51\n    // ComponentsConfiguration : YCbCr\n    // ShutterSpeedValue : 4.058893515764426\n    // ApertureValue : 2.5260688216892597 [4845/1918]\n    // BrightnessValue : -0.3126686601998395\n    // MeteringMode : Pattern\n    // Flash : Flash did not fire, compulsory flash mode\n    // FocalLength : 4.28 [107/25]\n    // SubjectArea : [4 values]\n    // FlashpixVersion : 0100\n    // ColorSpace : 1\n    // PixelXDimension : 2448\n    // PixelYDimension : 3264\n    // SensingMethod : One-chip color area sensor\n    // ExposureMode : 0\n    // WhiteBalance : Auto white balance\n    // FocalLengthIn35mmFilm : 35\n    // SceneCaptureType : Standard\n    define('runtime/html5/imagemeta/exif',[\n        'base',\n        'runtime/html5/imagemeta'\n    ], function( Base, ImageMeta ) {\n    \n        var EXIF = {};\n    \n        EXIF.ExifMap = function() {\n            return this;\n        };\n    \n        EXIF.ExifMap.prototype.map = {\n            'Orientation': 0x0112\n        };\n    \n        EXIF.ExifMap.prototype.get = function( id ) {\n            return this[ id ] || this[ this.map[ id ] ];\n        };\n    \n        EXIF.exifTagTypes = {\n            // byte, 8-bit unsigned int:\n            1: {\n                getValue: function( dataView, dataOffset ) {\n                    return dataView.getUint8( dataOffset );\n                },\n                size: 1\n            },\n    \n            // ascii, 8-bit byte:\n            2: {\n                getValue: function( dataView, dataOffset ) {\n                    return String.fromCharCode( dataView.getUint8( dataOffset ) );\n                },\n                size: 1,\n                ascii: true\n            },\n    \n            // short, 16 bit int:\n            3: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint16( dataOffset, littleEndian );\n                },\n                size: 2\n            },\n    \n            // long, 32 bit int:\n            4: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n    \n            // rational = two long values,\n            // first is numerator, second is denominator:\n            5: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian ) /\n                        dataView.getUint32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            },\n    \n            // slong, 32 bit signed int:\n            9: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n    \n            // srational, two slongs, first is numerator, second is denominator:\n            10: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian ) /\n                        dataView.getInt32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            }\n        };\n    \n        // undefined, 8-bit byte, value depending on field:\n        EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ];\n    \n        EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length,\n                littleEndian ) {\n    \n            var tagType = EXIF.exifTagTypes[ type ],\n                tagSize, dataOffset, values, i, str, c;\n    \n            if ( !tagType ) {\n                Base.log('Invalid Exif data: Invalid tag type.');\n                return;\n            }\n    \n            tagSize = tagType.size * length;\n    \n            // Determine if the value is contained in the dataOffset bytes,\n            // or if the value at the dataOffset is a pointer to the actual data:\n            dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8,\n                    littleEndian ) : (offset + 8);\n    \n            if ( dataOffset + tagSize > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid data offset.');\n                return;\n            }\n    \n            if ( length === 1 ) {\n                return tagType.getValue( dataView, dataOffset, littleEndian );\n            }\n    \n            values = [];\n    \n            for ( i = 0; i < length; i += 1 ) {\n                values[ i ] = tagType.getValue( dataView,\n                        dataOffset + i * tagType.size, littleEndian );\n            }\n    \n            if ( tagType.ascii ) {\n                str = '';\n    \n                // Concatenate the chars:\n                for ( i = 0; i < values.length; i += 1 ) {\n                    c = values[ i ];\n    \n                    // Ignore the terminating NULL byte(s):\n                    if ( c === '\\u0000' ) {\n                        break;\n                    }\n                    str += c;\n                }\n    \n                return str;\n            }\n            return values;\n        };\n    \n        EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian,\n                data ) {\n    \n            var tag = dataView.getUint16( offset, littleEndian );\n            data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset,\n                    dataView.getUint16( offset + 2, littleEndian ),    // tag type\n                    dataView.getUint32( offset + 4, littleEndian ),    // tag length\n                    littleEndian );\n        };\n    \n        EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset,\n                littleEndian, data ) {\n    \n            var tagsNumber, dirEndOffset, i;\n    \n            if ( dirOffset + 6 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory offset.');\n                return;\n            }\n    \n            tagsNumber = dataView.getUint16( dirOffset, littleEndian );\n            dirEndOffset = dirOffset + 2 + 12 * tagsNumber;\n    \n            if ( dirEndOffset + 4 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory size.');\n                return;\n            }\n    \n            for ( i = 0; i < tagsNumber; i += 1 ) {\n                this.parseExifTag( dataView, tiffOffset,\n                        dirOffset + 2 + 12 * i,    // tag offset\n                        littleEndian, data );\n            }\n    \n            // Return the offset to the next directory:\n            return dataView.getUint32( dirEndOffset, littleEndian );\n        };\n    \n        // EXIF.getExifThumbnail = function(dataView, offset, length) {\n        //     var hexData,\n        //         i,\n        //         b;\n        //     if (!length || offset + length > dataView.byteLength) {\n        //         Base.log('Invalid Exif data: Invalid thumbnail data.');\n        //         return;\n        //     }\n        //     hexData = [];\n        //     for (i = 0; i < length; i += 1) {\n        //         b = dataView.getUint8(offset + i);\n        //         hexData.push((b < 16 ? '0' : '') + b.toString(16));\n        //     }\n        //     return 'data:image/jpeg,%' + hexData.join('%');\n        // };\n    \n        EXIF.parseExifData = function( dataView, offset, length, data ) {\n    \n            var tiffOffset = offset + 10,\n                littleEndian, dirOffset;\n    \n            // Check for the ASCII code for \"Exif\" (0x45786966):\n            if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) {\n                // No Exif data, might be XMP data instead\n                return;\n            }\n            if ( tiffOffset + 8 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid segment size.');\n                return;\n            }\n    \n            // Check for the two null bytes:\n            if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) {\n                Base.log('Invalid Exif data: Missing byte alignment offset.');\n                return;\n            }\n    \n            // Check the byte alignment:\n            switch ( dataView.getUint16( tiffOffset ) ) {\n                case 0x4949:\n                    littleEndian = true;\n                    break;\n    \n                case 0x4D4D:\n                    littleEndian = false;\n                    break;\n    \n                default:\n                    Base.log('Invalid Exif data: Invalid byte alignment marker.');\n                    return;\n            }\n    \n            // Check for the TIFF tag marker (0x002A):\n            if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) {\n                Base.log('Invalid Exif data: Missing TIFF marker.');\n                return;\n            }\n    \n            // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:\n            dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian );\n            // Create the exif object to store the tags:\n            data.exif = new EXIF.ExifMap();\n            // Parse the tags of the main image directory and retrieve the\n            // offset to the next directory, usually the thumbnail directory:\n            dirOffset = EXIF.parseExifTags( dataView, tiffOffset,\n                    tiffOffset + dirOffset, littleEndian, data );\n    \n            // 尝试读取缩略图\n            // if ( dirOffset ) {\n            //     thumbnailData = {exif: {}};\n            //     dirOffset = EXIF.parseExifTags(\n            //         dataView,\n            //         tiffOffset,\n            //         tiffOffset + dirOffset,\n            //         littleEndian,\n            //         thumbnailData\n            //     );\n    \n            //     // Check for JPEG Thumbnail offset:\n            //     if (thumbnailData.exif[0x0201]) {\n            //         data.exif.Thumbnail = EXIF.getExifThumbnail(\n            //             dataView,\n            //             tiffOffset + thumbnailData.exif[0x0201],\n            //             thumbnailData.exif[0x0202] // Thumbnail data length\n            //         );\n            //     }\n            // }\n        };\n    \n        ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData );\n        return EXIF;\n    });\n    /**\n     * 这个方式性能不行，但是可以解决android里面的toDataUrl的bug\n     * android里面toDataUrl('image/jpege')得到的结果却是png.\n     *\n     * 所以这里没辙，只能借助这个工具\n     * @fileOverview jpeg encoder\n     */\n    define('runtime/html5/jpegencoder',[], function( require, exports, module ) {\n    \n        /*\n          Copyright (c) 2008, Adobe Systems Incorporated\n          All rights reserved.\n    \n          Redistribution and use in source and binary forms, with or without\n          modification, are permitted provided that the following conditions are\n          met:\n    \n          * Redistributions of source code must retain the above copyright notice,\n            this list of conditions and the following disclaimer.\n    \n          * Redistributions in binary form must reproduce the above copyright\n            notice, this list of conditions and the following disclaimer in the\n            documentation and/or other materials provided with the distribution.\n    \n          * Neither the name of Adobe Systems Incorporated nor the names of its\n            contributors may be used to endorse or promote products derived from\n            this software without specific prior written permission.\n    \n          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n          IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n          THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n          PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n          CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n          EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n          PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n          PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n          LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n          NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n        */\n        /*\n        JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009\n    \n        Basic GUI blocking jpeg encoder\n        */\n    \n        function JPEGEncoder(quality) {\n          var self = this;\n            var fround = Math.round;\n            var ffloor = Math.floor;\n            var YTable = new Array(64);\n            var UVTable = new Array(64);\n            var fdtbl_Y = new Array(64);\n            var fdtbl_UV = new Array(64);\n            var YDC_HT;\n            var UVDC_HT;\n            var YAC_HT;\n            var UVAC_HT;\n    \n            var bitcode = new Array(65535);\n            var category = new Array(65535);\n            var outputfDCTQuant = new Array(64);\n            var DU = new Array(64);\n            var byteout = [];\n            var bytenew = 0;\n            var bytepos = 7;\n    \n            var YDU = new Array(64);\n            var UDU = new Array(64);\n            var VDU = new Array(64);\n            var clt = new Array(256);\n            var RGB_YUV_TABLE = new Array(2048);\n            var currentQuality;\n    \n            var ZigZag = [\n                     0, 1, 5, 6,14,15,27,28,\n                     2, 4, 7,13,16,26,29,42,\n                     3, 8,12,17,25,30,41,43,\n                     9,11,18,24,31,40,44,53,\n                    10,19,23,32,39,45,52,54,\n                    20,22,33,38,46,51,55,60,\n                    21,34,37,47,50,56,59,61,\n                    35,36,48,49,57,58,62,63\n                ];\n    \n            var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];\n            var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];\n            var std_ac_luminance_values = [\n                    0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,\n                    0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,\n                    0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,\n                    0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,\n                    0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,\n                    0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,\n                    0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,\n                    0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,\n                    0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,\n                    0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,\n                    0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,\n                    0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,\n                    0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,\n                    0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,\n                    0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,\n                    0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,\n                    0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,\n                    0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,\n                    0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,\n                    0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n    \n            var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];\n            var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];\n            var std_ac_chrominance_values = [\n                    0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,\n                    0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,\n                    0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,\n                    0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,\n                    0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,\n                    0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,\n                    0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,\n                    0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,\n                    0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,\n                    0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,\n                    0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,\n                    0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,\n                    0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,\n                    0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,\n                    0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,\n                    0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,\n                    0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,\n                    0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,\n                    0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,\n                    0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n    \n            function initQuantTables(sf){\n                    var YQT = [\n                        16, 11, 10, 16, 24, 40, 51, 61,\n                        12, 12, 14, 19, 26, 58, 60, 55,\n                        14, 13, 16, 24, 40, 57, 69, 56,\n                        14, 17, 22, 29, 51, 87, 80, 62,\n                        18, 22, 37, 56, 68,109,103, 77,\n                        24, 35, 55, 64, 81,104,113, 92,\n                        49, 64, 78, 87,103,121,120,101,\n                        72, 92, 95, 98,112,100,103, 99\n                    ];\n    \n                    for (var i = 0; i < 64; i++) {\n                        var t = ffloor((YQT[i]*sf+50)/100);\n                        if (t < 1) {\n                            t = 1;\n                        } else if (t > 255) {\n                            t = 255;\n                        }\n                        YTable[ZigZag[i]] = t;\n                    }\n                    var UVQT = [\n                        17, 18, 24, 47, 99, 99, 99, 99,\n                        18, 21, 26, 66, 99, 99, 99, 99,\n                        24, 26, 56, 99, 99, 99, 99, 99,\n                        47, 66, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99\n                    ];\n                    for (var j = 0; j < 64; j++) {\n                        var u = ffloor((UVQT[j]*sf+50)/100);\n                        if (u < 1) {\n                            u = 1;\n                        } else if (u > 255) {\n                            u = 255;\n                        }\n                        UVTable[ZigZag[j]] = u;\n                    }\n                    var aasf = [\n                        1.0, 1.387039845, 1.306562965, 1.175875602,\n                        1.0, 0.785694958, 0.541196100, 0.275899379\n                    ];\n                    var k = 0;\n                    for (var row = 0; row < 8; row++)\n                    {\n                        for (var col = 0; col < 8; col++)\n                        {\n                            fdtbl_Y[k]  = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            k++;\n                        }\n                    }\n                }\n    \n                function computeHuffmanTbl(nrcodes, std_table){\n                    var codevalue = 0;\n                    var pos_in_table = 0;\n                    var HT = new Array();\n                    for (var k = 1; k <= 16; k++) {\n                        for (var j = 1; j <= nrcodes[k]; j++) {\n                            HT[std_table[pos_in_table]] = [];\n                            HT[std_table[pos_in_table]][0] = codevalue;\n                            HT[std_table[pos_in_table]][1] = k;\n                            pos_in_table++;\n                            codevalue++;\n                        }\n                        codevalue*=2;\n                    }\n                    return HT;\n                }\n    \n                function initHuffmanTbl()\n                {\n                    YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);\n                    UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);\n                    YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);\n                    UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);\n                }\n    \n                function initCategoryNumber()\n                {\n                    var nrlower = 1;\n                    var nrupper = 2;\n                    for (var cat = 1; cat <= 15; cat++) {\n                        //Positive numbers\n                        for (var nr = nrlower; nr<nrupper; nr++) {\n                            category[32767+nr] = cat;\n                            bitcode[32767+nr] = [];\n                            bitcode[32767+nr][1] = cat;\n                            bitcode[32767+nr][0] = nr;\n                        }\n                        //Negative numbers\n                        for (var nrneg =-(nrupper-1); nrneg<=-nrlower; nrneg++) {\n                            category[32767+nrneg] = cat;\n                            bitcode[32767+nrneg] = [];\n                            bitcode[32767+nrneg][1] = cat;\n                            bitcode[32767+nrneg][0] = nrupper-1+nrneg;\n                        }\n                        nrlower <<= 1;\n                        nrupper <<= 1;\n                    }\n                }\n    \n                function initRGBYUVTable() {\n                    for(var i = 0; i < 256;i++) {\n                        RGB_YUV_TABLE[i]            =  19595 * i;\n                        RGB_YUV_TABLE[(i+ 256)>>0]  =  38470 * i;\n                        RGB_YUV_TABLE[(i+ 512)>>0]  =   7471 * i + 0x8000;\n                        RGB_YUV_TABLE[(i+ 768)>>0]  = -11059 * i;\n                        RGB_YUV_TABLE[(i+1024)>>0]  = -21709 * i;\n                        RGB_YUV_TABLE[(i+1280)>>0]  =  32768 * i + 0x807FFF;\n                        RGB_YUV_TABLE[(i+1536)>>0]  = -27439 * i;\n                        RGB_YUV_TABLE[(i+1792)>>0]  = - 5329 * i;\n                    }\n                }\n    \n                // IO functions\n                function writeBits(bs)\n                {\n                    var value = bs[0];\n                    var posval = bs[1]-1;\n                    while ( posval >= 0 ) {\n                        if (value & (1 << posval) ) {\n                            bytenew |= (1 << bytepos);\n                        }\n                        posval--;\n                        bytepos--;\n                        if (bytepos < 0) {\n                            if (bytenew == 0xFF) {\n                                writeByte(0xFF);\n                                writeByte(0);\n                            }\n                            else {\n                                writeByte(bytenew);\n                            }\n                            bytepos=7;\n                            bytenew=0;\n                        }\n                    }\n                }\n    \n                function writeByte(value)\n                {\n                    byteout.push(clt[value]); // write char directly instead of converting later\n                }\n    \n                function writeWord(value)\n                {\n                    writeByte((value>>8)&0xFF);\n                    writeByte((value   )&0xFF);\n                }\n    \n                // DCT & quantization core\n                function fDCTQuant(data, fdtbl)\n                {\n                    var d0, d1, d2, d3, d4, d5, d6, d7;\n                    /* Pass 1: process rows. */\n                    var dataOff=0;\n                    var i;\n                    var I8 = 8;\n                    var I64 = 64;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff+1];\n                        d2 = data[dataOff+2];\n                        d3 = data[dataOff+3];\n                        d4 = data[dataOff+4];\n                        d5 = data[dataOff+5];\n                        d6 = data[dataOff+6];\n                        d7 = data[dataOff+7];\n    \n                        var tmp0 = d0 + d7;\n                        var tmp7 = d0 - d7;\n                        var tmp1 = d1 + d6;\n                        var tmp6 = d1 - d6;\n                        var tmp2 = d2 + d5;\n                        var tmp5 = d2 - d5;\n                        var tmp3 = d3 + d4;\n                        var tmp4 = d3 - d4;\n    \n                        /* Even part */\n                        var tmp10 = tmp0 + tmp3;    /* phase 2 */\n                        var tmp13 = tmp0 - tmp3;\n                        var tmp11 = tmp1 + tmp2;\n                        var tmp12 = tmp1 - tmp2;\n    \n                        data[dataOff] = tmp10 + tmp11; /* phase 3 */\n                        data[dataOff+4] = tmp10 - tmp11;\n    \n                        var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */\n                        data[dataOff+2] = tmp13 + z1; /* phase 5 */\n                        data[dataOff+6] = tmp13 - z1;\n    \n                        /* Odd part */\n                        tmp10 = tmp4 + tmp5; /* phase 2 */\n                        tmp11 = tmp5 + tmp6;\n                        tmp12 = tmp6 + tmp7;\n    \n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */\n                        var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */\n                        var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */\n                        var z3 = tmp11 * 0.707106781; /* c4 */\n    \n                        var z11 = tmp7 + z3;    /* phase 5 */\n                        var z13 = tmp7 - z3;\n    \n                        data[dataOff+5] = z13 + z2; /* phase 6 */\n                        data[dataOff+3] = z13 - z2;\n                        data[dataOff+1] = z11 + z4;\n                        data[dataOff+7] = z11 - z4;\n    \n                        dataOff += 8; /* advance pointer to next row */\n                    }\n    \n                    /* Pass 2: process columns. */\n                    dataOff = 0;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff + 8];\n                        d2 = data[dataOff + 16];\n                        d3 = data[dataOff + 24];\n                        d4 = data[dataOff + 32];\n                        d5 = data[dataOff + 40];\n                        d6 = data[dataOff + 48];\n                        d7 = data[dataOff + 56];\n    \n                        var tmp0p2 = d0 + d7;\n                        var tmp7p2 = d0 - d7;\n                        var tmp1p2 = d1 + d6;\n                        var tmp6p2 = d1 - d6;\n                        var tmp2p2 = d2 + d5;\n                        var tmp5p2 = d2 - d5;\n                        var tmp3p2 = d3 + d4;\n                        var tmp4p2 = d3 - d4;\n    \n                        /* Even part */\n                        var tmp10p2 = tmp0p2 + tmp3p2;  /* phase 2 */\n                        var tmp13p2 = tmp0p2 - tmp3p2;\n                        var tmp11p2 = tmp1p2 + tmp2p2;\n                        var tmp12p2 = tmp1p2 - tmp2p2;\n    \n                        data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */\n                        data[dataOff+32] = tmp10p2 - tmp11p2;\n    \n                        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */\n                        data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */\n                        data[dataOff+48] = tmp13p2 - z1p2;\n    \n                        /* Odd part */\n                        tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */\n                        tmp11p2 = tmp5p2 + tmp6p2;\n                        tmp12p2 = tmp6p2 + tmp7p2;\n    \n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */\n                        var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */\n                        var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */\n                        var z3p2 = tmp11p2 * 0.707106781; /* c4 */\n    \n                        var z11p2 = tmp7p2 + z3p2;  /* phase 5 */\n                        var z13p2 = tmp7p2 - z3p2;\n    \n                        data[dataOff+40] = z13p2 + z2p2; /* phase 6 */\n                        data[dataOff+24] = z13p2 - z2p2;\n                        data[dataOff+ 8] = z11p2 + z4p2;\n                        data[dataOff+56] = z11p2 - z4p2;\n    \n                        dataOff++; /* advance pointer to next column */\n                    }\n    \n                    // Quantize/descale the coefficients\n                    var fDCTQuant;\n                    for (i=0; i<I64; ++i)\n                    {\n                        // Apply the quantization and scaling factor & Round to nearest integer\n                        fDCTQuant = data[i]*fdtbl[i];\n                        outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);\n                        //outputfDCTQuant[i] = fround(fDCTQuant);\n    \n                    }\n                    return outputfDCTQuant;\n                }\n    \n                function writeAPP0()\n                {\n                    writeWord(0xFFE0); // marker\n                    writeWord(16); // length\n                    writeByte(0x4A); // J\n                    writeByte(0x46); // F\n                    writeByte(0x49); // I\n                    writeByte(0x46); // F\n                    writeByte(0); // = \"JFIF\",'\\0'\n                    writeByte(1); // versionhi\n                    writeByte(1); // versionlo\n                    writeByte(0); // xyunits\n                    writeWord(1); // xdensity\n                    writeWord(1); // ydensity\n                    writeByte(0); // thumbnwidth\n                    writeByte(0); // thumbnheight\n                }\n    \n                function writeSOF0(width, height)\n                {\n                    writeWord(0xFFC0); // marker\n                    writeWord(17);   // length, truecolor YUV JPG\n                    writeByte(8);    // precision\n                    writeWord(height);\n                    writeWord(width);\n                    writeByte(3);    // nrofcomponents\n                    writeByte(1);    // IdY\n                    writeByte(0x11); // HVY\n                    writeByte(0);    // QTY\n                    writeByte(2);    // IdU\n                    writeByte(0x11); // HVU\n                    writeByte(1);    // QTU\n                    writeByte(3);    // IdV\n                    writeByte(0x11); // HVV\n                    writeByte(1);    // QTV\n                }\n    \n                function writeDQT()\n                {\n                    writeWord(0xFFDB); // marker\n                    writeWord(132);    // length\n                    writeByte(0);\n                    for (var i=0; i<64; i++) {\n                        writeByte(YTable[i]);\n                    }\n                    writeByte(1);\n                    for (var j=0; j<64; j++) {\n                        writeByte(UVTable[j]);\n                    }\n                }\n    \n                function writeDHT()\n                {\n                    writeWord(0xFFC4); // marker\n                    writeWord(0x01A2); // length\n    \n                    writeByte(0); // HTYDCinfo\n                    for (var i=0; i<16; i++) {\n                        writeByte(std_dc_luminance_nrcodes[i+1]);\n                    }\n                    for (var j=0; j<=11; j++) {\n                        writeByte(std_dc_luminance_values[j]);\n                    }\n    \n                    writeByte(0x10); // HTYACinfo\n                    for (var k=0; k<16; k++) {\n                        writeByte(std_ac_luminance_nrcodes[k+1]);\n                    }\n                    for (var l=0; l<=161; l++) {\n                        writeByte(std_ac_luminance_values[l]);\n                    }\n    \n                    writeByte(1); // HTUDCinfo\n                    for (var m=0; m<16; m++) {\n                        writeByte(std_dc_chrominance_nrcodes[m+1]);\n                    }\n                    for (var n=0; n<=11; n++) {\n                        writeByte(std_dc_chrominance_values[n]);\n                    }\n    \n                    writeByte(0x11); // HTUACinfo\n                    for (var o=0; o<16; o++) {\n                        writeByte(std_ac_chrominance_nrcodes[o+1]);\n                    }\n                    for (var p=0; p<=161; p++) {\n                        writeByte(std_ac_chrominance_values[p]);\n                    }\n                }\n    \n                function writeSOS()\n                {\n                    writeWord(0xFFDA); // marker\n                    writeWord(12); // length\n                    writeByte(3); // nrofcomponents\n                    writeByte(1); // IdY\n                    writeByte(0); // HTY\n                    writeByte(2); // IdU\n                    writeByte(0x11); // HTU\n                    writeByte(3); // IdV\n                    writeByte(0x11); // HTV\n                    writeByte(0); // Ss\n                    writeByte(0x3f); // Se\n                    writeByte(0); // Bf\n                }\n    \n                function processDU(CDU, fdtbl, DC, HTDC, HTAC){\n                    var EOB = HTAC[0x00];\n                    var M16zeroes = HTAC[0xF0];\n                    var pos;\n                    var I16 = 16;\n                    var I63 = 63;\n                    var I64 = 64;\n                    var DU_DCT = fDCTQuant(CDU, fdtbl);\n                    //ZigZag reorder\n                    for (var j=0;j<I64;++j) {\n                        DU[ZigZag[j]]=DU_DCT[j];\n                    }\n                    var Diff = DU[0] - DC; DC = DU[0];\n                    //Encode DC\n                    if (Diff==0) {\n                        writeBits(HTDC[0]); // Diff might be 0\n                    } else {\n                        pos = 32767+Diff;\n                        writeBits(HTDC[category[pos]]);\n                        writeBits(bitcode[pos]);\n                    }\n                    //Encode ACs\n                    var end0pos = 63; // was consts... which is crazy\n                    for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {};\n                    //end0pos = first element in reverse order !=0\n                    if ( end0pos == 0) {\n                        writeBits(EOB);\n                        return DC;\n                    }\n                    var i = 1;\n                    var lng;\n                    while ( i <= end0pos ) {\n                        var startpos = i;\n                        for (; (DU[i]==0) && (i<=end0pos); ++i) {}\n                        var nrzeroes = i-startpos;\n                        if ( nrzeroes >= I16 ) {\n                            lng = nrzeroes>>4;\n                            for (var nrmarker=1; nrmarker <= lng; ++nrmarker)\n                                writeBits(M16zeroes);\n                            nrzeroes = nrzeroes&0xF;\n                        }\n                        pos = 32767+DU[i];\n                        writeBits(HTAC[(nrzeroes<<4)+category[pos]]);\n                        writeBits(bitcode[pos]);\n                        i++;\n                    }\n                    if ( end0pos != I63 ) {\n                        writeBits(EOB);\n                    }\n                    return DC;\n                }\n    \n                function initCharLookupTable(){\n                    var sfcc = String.fromCharCode;\n                    for(var i=0; i < 256; i++){ ///// ACHTUNG // 255\n                        clt[i] = sfcc(i);\n                    }\n                }\n    \n                this.encode = function(image,quality) // image data object\n                {\n                    // var time_start = new Date().getTime();\n    \n                    if(quality) setQuality(quality);\n    \n                    // Initialize bit writer\n                    byteout = new Array();\n                    bytenew=0;\n                    bytepos=7;\n    \n                    // Add JPEG headers\n                    writeWord(0xFFD8); // SOI\n                    writeAPP0();\n                    writeDQT();\n                    writeSOF0(image.width,image.height);\n                    writeDHT();\n                    writeSOS();\n    \n    \n                    // Encode 8x8 macroblocks\n                    var DCY=0;\n                    var DCU=0;\n                    var DCV=0;\n    \n                    bytenew=0;\n                    bytepos=7;\n    \n    \n                    this.encode.displayName = \"_encode_\";\n    \n                    var imageData = image.data;\n                    var width = image.width;\n                    var height = image.height;\n    \n                    var quadWidth = width*4;\n                    var tripleWidth = width*3;\n    \n                    var x, y = 0;\n                    var r, g, b;\n                    var start,p, col,row,pos;\n                    while(y < height){\n                        x = 0;\n                        while(x < quadWidth){\n                        start = quadWidth * y + x;\n                        p = start;\n                        col = -1;\n                        row = 0;\n    \n                        for(pos=0; pos < 64; pos++){\n                            row = pos >> 3;// /8\n                            col = ( pos & 7 ) * 4; // %8\n                            p = start + ( row * quadWidth ) + col;\n    \n                            if(y+row >= height){ // padding bottom\n                                p-= (quadWidth*(y+1+row-height));\n                            }\n    \n                            if(x+col >= quadWidth){ // padding right\n                                p-= ((x+col) - quadWidth +4)\n                            }\n    \n                            r = imageData[ p++ ];\n                            g = imageData[ p++ ];\n                            b = imageData[ p++ ];\n    \n    \n                            /* // calculate YUV values dynamically\n                            YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80\n                            UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));\n                            VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));\n                            */\n    \n                            // use lookup table (slightly faster)\n                            YDU[pos] = ((RGB_YUV_TABLE[r]             + RGB_YUV_TABLE[(g +  256)>>0] + RGB_YUV_TABLE[(b +  512)>>0]) >> 16)-128;\n                            UDU[pos] = ((RGB_YUV_TABLE[(r +  768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128;\n                            VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128;\n    \n                        }\n    \n                        DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);\n                        DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);\n                        DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);\n                        x+=32;\n                        }\n                        y+=8;\n                    }\n    \n    \n                    ////////////////////////////////////////////////////////////////\n    \n                    // Do the bit alignment of the EOI marker\n                    if ( bytepos >= 0 ) {\n                        var fillbits = [];\n                        fillbits[1] = bytepos+1;\n                        fillbits[0] = (1<<(bytepos+1))-1;\n                        writeBits(fillbits);\n                    }\n    \n                    writeWord(0xFFD9); //EOI\n    \n                    var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join(''));\n    \n                    byteout = [];\n    \n                    // benchmarking\n                    // var duration = new Date().getTime() - time_start;\n                    // console.log('Encoding time: '+ currentQuality + 'ms');\n                    //\n    \n                    return jpegDataUri\n            }\n    \n            function setQuality(quality){\n                if (quality <= 0) {\n                    quality = 1;\n                }\n                if (quality > 100) {\n                    quality = 100;\n                }\n    \n                if(currentQuality == quality) return // don't recalc if unchanged\n    \n                var sf = 0;\n                if (quality < 50) {\n                    sf = Math.floor(5000 / quality);\n                } else {\n                    sf = Math.floor(200 - quality*2);\n                }\n    \n                initQuantTables(sf);\n                currentQuality = quality;\n                // console.log('Quality set to: '+quality +'%');\n            }\n    \n            function init(){\n                // var time_start = new Date().getTime();\n                if(!quality) quality = 50;\n                // Create tables\n                initCharLookupTable()\n                initHuffmanTbl();\n                initCategoryNumber();\n                initRGBYUVTable();\n    \n                setQuality(quality);\n                // var duration = new Date().getTime() - time_start;\n                // console.log('Initialization '+ duration + 'ms');\n            }\n    \n            init();\n    \n        };\n    \n        JPEGEncoder.encode = function( data, quality ) {\n            var encoder = new JPEGEncoder( quality );\n    \n            return encoder.encode( data );\n        }\n    \n        return JPEGEncoder;\n    });\n    /**\n     * @fileOverview Fix android canvas.toDataUrl bug.\n     */\n    define('runtime/html5/androidpatch',[\n        'runtime/html5/util',\n        'runtime/html5/jpegencoder',\n        'base'\n    ], function( Util, encoder, Base ) {\n        var origin = Util.canvasToDataUrl,\n            supportJpeg;\n    \n        Util.canvasToDataUrl = function( canvas, type, quality ) {\n            var ctx, w, h, fragement, parts;\n    \n            // 非android手机直接跳过。\n            if ( !Base.os.android ) {\n                return origin.apply( null, arguments );\n            }\n    \n            // 检测是否canvas支持jpeg导出，根据数据格式来判断。\n            // JPEG 前两位分别是：255, 216\n            if ( type === 'image/jpeg' && typeof supportJpeg === 'undefined' ) {\n                fragement = origin.apply( null, arguments );\n    \n                parts = fragement.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    fragement = atob( parts[ 1 ] );\n                } else {\n                    fragement = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                fragement = fragement.substring( 0, 2 );\n    \n                supportJpeg = fragement.charCodeAt( 0 ) === 255 &&\n                        fragement.charCodeAt( 1 ) === 216;\n            }\n    \n            // 只有在android环境下才修复\n            if ( type === 'image/jpeg' && !supportJpeg ) {\n                w = canvas.width;\n                h = canvas.height;\n                ctx = canvas.getContext('2d');\n    \n                return encoder.encode( ctx.getImageData( 0, 0, w, h ), quality );\n            }\n    \n            return origin.apply( null, arguments );\n        };\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('runtime/html5/image',[\n        'base',\n        'runtime/html5/runtime',\n        'runtime/html5/util'\n    ], function( Base, Html5Runtime, Util ) {\n    \n        var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';\n    \n        return Html5Runtime.register( 'Image', {\n    \n            // flag: 标记是否被修改过。\n            modified: false,\n    \n            init: function() {\n                var me = this,\n                    img = new Image();\n    \n                img.onload = function() {\n    \n                    me._info = {\n                        type: me.type,\n                        width: this.width,\n                        height: this.height\n                    };\n    \n                    // 读取meta信息。\n                    if ( !me._metas && 'image/jpeg' === me.type ) {\n                        Util.parseMeta( me._blob, function( error, ret ) {\n                            me._metas = ret;\n                            me.owner.trigger('load');\n                        });\n                    } else {\n                        me.owner.trigger('load');\n                    }\n                };\n    \n                img.onerror = function() {\n                    me.owner.trigger('error');\n                };\n    \n                me._img = img;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    img = me._img;\n    \n                me._blob = blob;\n                me.type = blob.type;\n                img.src = Util.createObjectURL( blob.getSource() );\n                me.owner.once( 'load', function() {\n                    Util.revokeObjectURL( img.src );\n                });\n            },\n    \n            resize: function( width, height ) {\n                var canvas = this._canvas ||\n                        (this._canvas = document.createElement('canvas'));\n    \n                this._resize( this._img, canvas, width, height );\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'resize' );\n            },\n    \n            crop: function( x, y, w, h, s ) {\n                var cvs = this._canvas ||\n                        (this._canvas = document.createElement('canvas')),\n                    opts = this.options,\n                    img = this._img,\n                    iw = img.naturalWidth,\n                    ih = img.naturalHeight,\n                    orientation = this.getOrientation();\n    \n                s = s || 1;\n    \n                // todo 解决 orientation 的问题。\n                // values that require 90 degree rotation\n                // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n    \n                //     switch ( orientation ) {\n                //         case 6:\n                //             tmp = x;\n                //             x = y;\n                //             y = iw * s - tmp - w;\n                //             console.log(ih * s, tmp, w)\n                //             break;\n                //     }\n    \n                //     (w ^= h, h ^= w, w ^= h);\n                // }\n    \n                cvs.width = w;\n                cvs.height = h;\n    \n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n                this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s );\n    \n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'crop' );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this._blob,\n                    opts = this.options,\n                    canvas;\n    \n                type = type || this.type;\n    \n                // blob需要重新生成。\n                if ( this.modified || this.type !== type ) {\n                    canvas = this._canvas;\n    \n                    if ( type === 'image/jpeg' ) {\n    \n                        blob = Util.canvasToDataUrl( canvas, type, opts.quality );\n    \n                        if ( opts.preserveHeaders && this._metas &&\n                                this._metas.imageHead ) {\n    \n                            blob = Util.dataURL2ArrayBuffer( blob );\n                            blob = Util.updateImageHead( blob,\n                                    this._metas.imageHead );\n                            blob = Util.arrayBufferToBlob( blob, type );\n                            return blob;\n                        }\n                    } else {\n                        blob = Util.canvasToDataUrl( canvas, type );\n                    }\n    \n                    blob = Util.dataURL2Blob( blob );\n                }\n    \n                return blob;\n            },\n    \n            getAsDataUrl: function( type ) {\n                var opts = this.options;\n    \n                type = type || this.type;\n    \n                if ( type === 'image/jpeg' ) {\n                    return Util.canvasToDataUrl( this._canvas, type, opts.quality );\n                } else {\n                    return this._canvas.toDataURL( type );\n                }\n            },\n    \n            getOrientation: function() {\n                return this._metas && this._metas.exif &&\n                        this._metas.exif.get('Orientation') || 1;\n            },\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            destroy: function() {\n                var canvas = this._canvas;\n                this._img.onload = null;\n    \n                if ( canvas ) {\n                    canvas.getContext('2d')\n                            .clearRect( 0, 0, canvas.width, canvas.height );\n                    canvas.width = canvas.height = 0;\n                    this._canvas = null;\n                }\n    \n                // 释放内存。非常重要，否则释放不了image的内存。\n                this._img.src = BLANK;\n                this._img = this._blob = null;\n            },\n    \n            _resize: function( img, cvs, width, height ) {\n                var opts = this.options,\n                    naturalWidth = img.width,\n                    naturalHeight = img.height,\n                    orientation = this.getOrientation(),\n                    scale, w, h, x, y;\n    \n                // values that require 90 degree rotation\n                if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n    \n                    // 交换width, height的值。\n                    width ^= height;\n                    height ^= width;\n                    width ^= height;\n                }\n    \n                scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth,\n                        height / naturalHeight );\n    \n                // 不允许放大。\n                opts.allowMagnify || (scale = Math.min( 1, scale ));\n    \n                w = naturalWidth * scale;\n                h = naturalHeight * scale;\n    \n                if ( opts.crop ) {\n                    cvs.width = width;\n                    cvs.height = height;\n                } else {\n                    cvs.width = w;\n                    cvs.height = h;\n                }\n    \n                x = (cvs.width - w) / 2;\n                y = (cvs.height - h) / 2;\n    \n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n    \n                this._renderImageToCanvas( cvs, img, x, y, w, h );\n            },\n    \n            _rotate2Orientaion: function( canvas, orientation ) {\n                var width = canvas.width,\n                    height = canvas.height,\n                    ctx = canvas.getContext('2d');\n    \n                switch ( orientation ) {\n                    case 5:\n                    case 6:\n                    case 7:\n                    case 8:\n                        canvas.width = height;\n                        canvas.height = width;\n                        break;\n                }\n    \n                switch ( orientation ) {\n                    case 2:    // horizontal flip\n                        ctx.translate( width, 0 );\n                        ctx.scale( -1, 1 );\n                        break;\n    \n                    case 3:    // 180 rotate left\n                        ctx.translate( width, height );\n                        ctx.rotate( Math.PI );\n                        break;\n    \n                    case 4:    // vertical flip\n                        ctx.translate( 0, height );\n                        ctx.scale( 1, -1 );\n                        break;\n    \n                    case 5:    // vertical flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.scale( 1, -1 );\n                        break;\n    \n                    case 6:    // 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( 0, -height );\n                        break;\n    \n                    case 7:    // horizontal flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( width, -height );\n                        ctx.scale( -1, 1 );\n                        break;\n    \n                    case 8:    // 90 rotate left\n                        ctx.rotate( -0.5 * Math.PI );\n                        ctx.translate( -width, 0 );\n                        break;\n                }\n            },\n    \n            // https://github.com/stomita/ios-imagefile-megapixel/\n            // blob/master/src/megapix-image.js\n            _renderImageToCanvas: (function() {\n    \n                // 如果不是ios, 不需要这么复杂！\n                if ( !Base.os.ios ) {\n                    return function( canvas ) {\n                        var args = Base.slice( arguments, 1 ),\n                            ctx = canvas.getContext('2d');\n    \n                        ctx.drawImage.apply( ctx, args );\n                    };\n                }\n    \n                /**\n                 * Detecting vertical squash in loaded image.\n                 * Fixes a bug which squash image vertically while drawing into\n                 * canvas for some images.\n                 */\n                function detectVerticalSquash( img, iw, ih ) {\n                    var canvas = document.createElement('canvas'),\n                        ctx = canvas.getContext('2d'),\n                        sy = 0,\n                        ey = ih,\n                        py = ih,\n                        data, alpha, ratio;\n    \n    \n                    canvas.width = 1;\n                    canvas.height = ih;\n                    ctx.drawImage( img, 0, 0 );\n                    data = ctx.getImageData( 0, 0, 1, ih ).data;\n    \n                    // search image edge pixel position in case\n                    // it is squashed vertically.\n                    while ( py > sy ) {\n                        alpha = data[ (py - 1) * 4 + 3 ];\n    \n                        if ( alpha === 0 ) {\n                            ey = py;\n                        } else {\n                            sy = py;\n                        }\n    \n                        py = (ey + sy) >> 1;\n                    }\n    \n                    ratio = (py / ih);\n                    return (ratio === 0) ? 1 : ratio;\n                }\n    \n                // fix ie7 bug\n                // http://stackoverflow.com/questions/11929099/\n                // html5-canvas-drawimage-ratio-bug-ios\n                if ( Base.os.ios >= 7 ) {\n                    return function( canvas, img, x, y, w, h ) {\n                        var iw = img.naturalWidth,\n                            ih = img.naturalHeight,\n                            vertSquashRatio = detectVerticalSquash( img, iw, ih );\n    \n                        return canvas.getContext('2d').drawImage( img, 0, 0,\n                                iw * vertSquashRatio, ih * vertSquashRatio,\n                                x, y, w, h );\n                    };\n                }\n    \n                /**\n                 * Detect subsampling in loaded image.\n                 * In iOS, larger images than 2M pixels may be\n                 * subsampled in rendering.\n                 */\n                function detectSubsampling( img ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        canvas, ctx;\n    \n                    // subsampling may happen overmegapixel image\n                    if ( iw * ih > 1024 * 1024 ) {\n                        canvas = document.createElement('canvas');\n                        canvas.width = canvas.height = 1;\n                        ctx = canvas.getContext('2d');\n                        ctx.drawImage( img, -iw + 1, 0 );\n    \n                        // subsampled image becomes half smaller in rendering size.\n                        // check alpha channel value to confirm image is covering\n                        // edge pixel or not. if alpha value is 0\n                        // image is not covering, hence subsampled.\n                        return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0;\n                    } else {\n                        return false;\n                    }\n                }\n    \n    \n                return function( canvas, img, x, y, width, height ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        ctx = canvas.getContext('2d'),\n                        subsampled = detectSubsampling( img ),\n                        doSquash = this.type === 'image/jpeg',\n                        d = 1024,\n                        sy = 0,\n                        dy = 0,\n                        tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx;\n    \n                    if ( subsampled ) {\n                        iw /= 2;\n                        ih /= 2;\n                    }\n    \n                    ctx.save();\n                    tmpCanvas = document.createElement('canvas');\n                    tmpCanvas.width = tmpCanvas.height = d;\n    \n                    tmpCtx = tmpCanvas.getContext('2d');\n                    vertSquashRatio = doSquash ?\n                            detectVerticalSquash( img, iw, ih ) : 1;\n    \n                    dw = Math.ceil( d * width / iw );\n                    dh = Math.ceil( d * height / ih / vertSquashRatio );\n    \n                    while ( sy < ih ) {\n                        sx = 0;\n                        dx = 0;\n                        while ( sx < iw ) {\n                            tmpCtx.clearRect( 0, 0, d, d );\n                            tmpCtx.drawImage( img, -sx, -sy );\n                            ctx.drawImage( tmpCanvas, 0, 0, d, d,\n                                    x + dx, y + dy, dw, dh );\n                            sx += d;\n                            dx += dw;\n                        }\n                        sy += d;\n                        dy += dh;\n                    }\n                    ctx.restore();\n                    tmpCanvas = tmpCtx = null;\n                };\n            })()\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var noop = Base.noop,\n            $ = Base.$;\n    \n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n    \n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n    \n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n    \n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n    \n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n    \n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n    \n            getResponse: function() {\n                return this._response;\n            },\n    \n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n    \n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n    \n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n    \n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n    \n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n    \n                    return me.trigger( 'progress', percentage );\n                };\n    \n                xhr.onreadystatechange = function() {\n    \n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n    \n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n    \n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n    \n    \n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n    \n            _parseJson: function( str ) {\n                var json;\n    \n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n    \n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/html5/md5',[\n        'runtime/html5/runtime'\n    ], function( FlashRuntime ) {\n    \n        /*\n         * Fastest md5 implementation around (JKM md5)\n         * Credits: Joseph Myers\n         *\n         * @see http://www.myersdaily.org/joseph/javascript/md5-text.html\n         * @see http://jsperf.com/md5-shootout/7\n         */\n    \n        /* this function is much faster,\n          so if possible we use it. Some IEs\n          are the only ones I know of that\n          need the idiotic second function,\n          generated by an if clause.  */\n        var add32 = function (a, b) {\n            return (a + b) & 0xFFFFFFFF;\n        },\n    \n        cmn = function (q, a, b, x, s, t) {\n            a = add32(add32(a, q), add32(x, t));\n            return add32((a << s) | (a >>> (32 - s)), b);\n        },\n    \n        ff = function (a, b, c, d, x, s, t) {\n            return cmn((b & c) | ((~b) & d), a, b, x, s, t);\n        },\n    \n        gg = function (a, b, c, d, x, s, t) {\n            return cmn((b & d) | (c & (~d)), a, b, x, s, t);\n        },\n    \n        hh = function (a, b, c, d, x, s, t) {\n            return cmn(b ^ c ^ d, a, b, x, s, t);\n        },\n    \n        ii = function (a, b, c, d, x, s, t) {\n            return cmn(c ^ (b | (~d)), a, b, x, s, t);\n        },\n    \n        md5cycle = function (x, k) {\n            var a = x[0],\n                b = x[1],\n                c = x[2],\n                d = x[3];\n    \n            a = ff(a, b, c, d, k[0], 7, -680876936);\n            d = ff(d, a, b, c, k[1], 12, -389564586);\n            c = ff(c, d, a, b, k[2], 17, 606105819);\n            b = ff(b, c, d, a, k[3], 22, -1044525330);\n            a = ff(a, b, c, d, k[4], 7, -176418897);\n            d = ff(d, a, b, c, k[5], 12, 1200080426);\n            c = ff(c, d, a, b, k[6], 17, -1473231341);\n            b = ff(b, c, d, a, k[7], 22, -45705983);\n            a = ff(a, b, c, d, k[8], 7, 1770035416);\n            d = ff(d, a, b, c, k[9], 12, -1958414417);\n            c = ff(c, d, a, b, k[10], 17, -42063);\n            b = ff(b, c, d, a, k[11], 22, -1990404162);\n            a = ff(a, b, c, d, k[12], 7, 1804603682);\n            d = ff(d, a, b, c, k[13], 12, -40341101);\n            c = ff(c, d, a, b, k[14], 17, -1502002290);\n            b = ff(b, c, d, a, k[15], 22, 1236535329);\n    \n            a = gg(a, b, c, d, k[1], 5, -165796510);\n            d = gg(d, a, b, c, k[6], 9, -1069501632);\n            c = gg(c, d, a, b, k[11], 14, 643717713);\n            b = gg(b, c, d, a, k[0], 20, -373897302);\n            a = gg(a, b, c, d, k[5], 5, -701558691);\n            d = gg(d, a, b, c, k[10], 9, 38016083);\n            c = gg(c, d, a, b, k[15], 14, -660478335);\n            b = gg(b, c, d, a, k[4], 20, -405537848);\n            a = gg(a, b, c, d, k[9], 5, 568446438);\n            d = gg(d, a, b, c, k[14], 9, -1019803690);\n            c = gg(c, d, a, b, k[3], 14, -187363961);\n            b = gg(b, c, d, a, k[8], 20, 1163531501);\n            a = gg(a, b, c, d, k[13], 5, -1444681467);\n            d = gg(d, a, b, c, k[2], 9, -51403784);\n            c = gg(c, d, a, b, k[7], 14, 1735328473);\n            b = gg(b, c, d, a, k[12], 20, -1926607734);\n    \n            a = hh(a, b, c, d, k[5], 4, -378558);\n            d = hh(d, a, b, c, k[8], 11, -2022574463);\n            c = hh(c, d, a, b, k[11], 16, 1839030562);\n            b = hh(b, c, d, a, k[14], 23, -35309556);\n            a = hh(a, b, c, d, k[1], 4, -1530992060);\n            d = hh(d, a, b, c, k[4], 11, 1272893353);\n            c = hh(c, d, a, b, k[7], 16, -155497632);\n            b = hh(b, c, d, a, k[10], 23, -1094730640);\n            a = hh(a, b, c, d, k[13], 4, 681279174);\n            d = hh(d, a, b, c, k[0], 11, -358537222);\n            c = hh(c, d, a, b, k[3], 16, -722521979);\n            b = hh(b, c, d, a, k[6], 23, 76029189);\n            a = hh(a, b, c, d, k[9], 4, -640364487);\n            d = hh(d, a, b, c, k[12], 11, -421815835);\n            c = hh(c, d, a, b, k[15], 16, 530742520);\n            b = hh(b, c, d, a, k[2], 23, -995338651);\n    \n            a = ii(a, b, c, d, k[0], 6, -198630844);\n            d = ii(d, a, b, c, k[7], 10, 1126891415);\n            c = ii(c, d, a, b, k[14], 15, -1416354905);\n            b = ii(b, c, d, a, k[5], 21, -57434055);\n            a = ii(a, b, c, d, k[12], 6, 1700485571);\n            d = ii(d, a, b, c, k[3], 10, -1894986606);\n            c = ii(c, d, a, b, k[10], 15, -1051523);\n            b = ii(b, c, d, a, k[1], 21, -2054922799);\n            a = ii(a, b, c, d, k[8], 6, 1873313359);\n            d = ii(d, a, b, c, k[15], 10, -30611744);\n            c = ii(c, d, a, b, k[6], 15, -1560198380);\n            b = ii(b, c, d, a, k[13], 21, 1309151649);\n            a = ii(a, b, c, d, k[4], 6, -145523070);\n            d = ii(d, a, b, c, k[11], 10, -1120210379);\n            c = ii(c, d, a, b, k[2], 15, 718787259);\n            b = ii(b, c, d, a, k[9], 21, -343485551);\n    \n            x[0] = add32(a, x[0]);\n            x[1] = add32(b, x[1]);\n            x[2] = add32(c, x[2]);\n            x[3] = add32(d, x[3]);\n        },\n    \n        /* there needs to be support for Unicode here,\n           * unless we pretend that we can redefine the MD-5\n           * algorithm for multi-byte characters (perhaps\n           * by adding every four 16-bit characters and\n           * shortening the sum to 32 bits). Otherwise\n           * I suggest performing MD-5 as if every character\n           * was two bytes--e.g., 0040 0025 = @%--but then\n           * how will an ordinary MD-5 sum be matched?\n           * There is no way to standardize text to something\n           * like UTF-8 before transformation; speed cost is\n           * utterly prohibitive. The JavaScript standard\n           * itself needs to look at this: it should start\n           * providing access to strings as preformed UTF-8\n           * 8-bit unsigned value arrays.\n           */\n        md5blk = function (s) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n    \n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);\n            }\n            return md5blks;\n        },\n    \n        md5blk_array = function (a) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n    \n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);\n            }\n            return md5blks;\n        },\n    \n        md51 = function (s) {\n            var n = s.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n    \n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk(s.substring(i - 64, i)));\n            }\n            s = s.substring(i - 64);\n            length = s.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);\n            }\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n    \n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n    \n            tail[14] = lo;\n            tail[15] = hi;\n    \n            md5cycle(state, tail);\n            return state;\n        },\n    \n        md51_array = function (a) {\n            var n = a.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n    \n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk_array(a.subarray(i - 64, i)));\n            }\n    \n            // Not sure if it is a bug, however IE10 will always produce a sub array of length 1\n            // containing the last element of the parent array if the sub array specified starts\n            // beyond the length of the parent array - weird.\n            // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue\n            a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);\n    \n            length = a.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= a[i] << ((i % 4) << 3);\n            }\n    \n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n    \n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n    \n            tail[14] = lo;\n            tail[15] = hi;\n    \n            md5cycle(state, tail);\n    \n            return state;\n        },\n    \n        hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],\n    \n        rhex = function (n) {\n            var s = '',\n                j;\n            for (j = 0; j < 4; j += 1) {\n                s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];\n            }\n            return s;\n        },\n    \n        hex = function (x) {\n            var i;\n            for (i = 0; i < x.length; i += 1) {\n                x[i] = rhex(x[i]);\n            }\n            return x.join('');\n        },\n    \n        md5 = function (s) {\n            return hex(md51(s));\n        },\n    \n    \n    \n        ////////////////////////////////////////////////////////////////////////////\n    \n        /**\n         * SparkMD5 OOP implementation.\n         *\n         * Use this class to perform an incremental md5, otherwise use the\n         * static methods instead.\n         */\n        SparkMD5 = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n    \n    \n        // In some cases the fast add32 function cannot be used..\n        if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {\n            add32 = 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    \n    \n        /**\n         * Appends a string.\n         * A conversion will be applied if an utf8 string is detected.\n         *\n         * @param {String} str The string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.append = function (str) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n    \n            // then append as binary\n            this.appendBinary(str);\n    \n            return this;\n        };\n    \n        /**\n         * Appends a binary string.\n         *\n         * @param {String} contents The binary string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.appendBinary = function (contents) {\n            this._buff += contents;\n            this._length += contents.length;\n    \n            var length = this._buff.length,\n                i;\n    \n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));\n            }\n    \n            this._buff = this._buff.substr(i - 64);\n    \n            return this;\n        };\n    \n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                i,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                ret;\n    \n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);\n            }\n    \n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n    \n            this.reset();\n    \n            return ret;\n        };\n    \n        /**\n         * Finish the final calculation based on the tail.\n         *\n         * @param {Array}  tail   The tail (will be modified)\n         * @param {Number} length The length of the remaining buffer\n         */\n        SparkMD5.prototype._finish = function (tail, length) {\n            var i = length,\n                tmp,\n                lo,\n                hi;\n    \n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(this._state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n    \n            // Do the final computation based on the tail and length\n            // Beware that the final length may not fit in 32 bits so we take care of that\n            tmp = this._length * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n    \n            tail[14] = lo;\n            tail[15] = hi;\n            md5cycle(this._state, tail);\n        };\n    \n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.reset = function () {\n            this._buff = \"\";\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n    \n            return this;\n        };\n    \n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.prototype.destroy = function () {\n            delete this._state;\n            delete this._buff;\n            delete this._length;\n        };\n    \n    \n        /**\n         * Performs the md5 hash on a string.\n         * A conversion will be applied if utf8 string is detected.\n         *\n         * @param {String}  str The string\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hash = function (str, raw) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n    \n            var hash = md51(str);\n    \n            return !!raw ? hash : hex(hash);\n        };\n    \n        /**\n         * Performs the md5 hash on a binary string.\n         *\n         * @param {String}  content The binary string\n         * @param {Boolean} raw     True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hashBinary = function (content, raw) {\n            var hash = md51(content);\n    \n            return !!raw ? hash : hex(hash);\n        };\n    \n        /**\n         * SparkMD5 OOP implementation for array buffers.\n         *\n         * Use this class to perform an incremental md5 ONLY for array buffers.\n         */\n        SparkMD5.ArrayBuffer = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n    \n        ////////////////////////////////////////////////////////////////////////////\n    \n        /**\n         * Appends an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array to be appended\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.append = function (arr) {\n            // TODO: we could avoid the concatenation here but the algorithm would be more complex\n            //       if you find yourself needing extra performance, please make a PR.\n            var buff = this._concatArrayBuffer(this._buff, arr),\n                length = buff.length,\n                i;\n    \n            this._length += arr.byteLength;\n    \n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));\n            }\n    \n            // Avoids IE10 weirdness (documented above)\n            this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);\n    \n            return this;\n        };\n    \n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                i,\n                ret;\n    \n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff[i] << ((i % 4) << 3);\n            }\n    \n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n    \n            this.reset();\n    \n            return ret;\n        };\n    \n        SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;\n    \n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.reset = function () {\n            this._buff = new Uint8Array(0);\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n    \n            return this;\n        };\n    \n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;\n    \n        /**\n         * Concats two array buffers, returning a new one.\n         *\n         * @param  {ArrayBuffer} first  The first array buffer\n         * @param  {ArrayBuffer} second The second array buffer\n         *\n         * @return {ArrayBuffer} The new array buffer\n         */\n        SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {\n            var firstLength = first.length,\n                result = new Uint8Array(firstLength + second.byteLength);\n    \n            result.set(first);\n            result.set(new Uint8Array(second), firstLength);\n    \n            return result;\n        };\n    \n        /**\n         * Performs the md5 hash on an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array buffer\n         * @param {Boolean}     raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.hash = function (arr, raw) {\n            var hash = md51_array(new Uint8Array(arr));\n    \n            return !!raw ? hash : hex(hash);\n        };\n        \n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n    \n            loadFromBlob: function( file ) {\n                var blob = file.getSource(),\n                    chunkSize = 2 * 1024 * 1024,\n                    chunks = Math.ceil( blob.size / chunkSize ),\n                    chunk = 0,\n                    owner = this.owner,\n                    spark = new SparkMD5.ArrayBuffer(),\n                    me = this,\n                    blobSlice = blob.mozSlice || blob.webkitSlice || blob.slice,\n                    loadNext, fr;\n    \n                fr = new FileReader();\n    \n                loadNext = function() {\n                    var start, end;\n    \n                    start = chunk * chunkSize;\n                    end = Math.min( start + chunkSize, blob.size );\n    \n                    fr.onload = function( e ) {\n                        spark.append( e.target.result );\n                        owner.trigger( 'progress', {\n                            total: file.size,\n                            loaded: end\n                        });\n                    };\n    \n                    fr.onloadend = function() {\n                        fr.onloadend = fr.onload = null;\n    \n                        if ( ++chunk < chunks ) {\n                            setTimeout( loadNext, 1 );\n                        } else {\n                            setTimeout(function(){\n                                owner.trigger('load');\n                                me.result = spark.end();\n                                loadNext = file = blob = spark = null;\n                                owner.trigger('complete');\n                            }, 50 );\n                        }\n                    };\n    \n                    fr.readAsArrayBuffer( blobSlice.call( blob, start, end ) );\n                };\n    \n                loadNext();\n            },\n    \n            getResult: function() {\n                return this.result;\n            }\n        });\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n    \n    \n        function getFlashVersion() {\n            var version;\n    \n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n    \n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                clients[ uid ] = client;\n    \n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n    \n                    instance = pool[ uid ];\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n    \n                return me.flashExec.apply( client, arguments );\n            };\n    \n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n    \n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n    \n                // console.log.apply( console, arguments );\n    \n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n    \n                // Base.log( evt, obj );\n            }\n    \n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n    \n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n    \n            this.jsreciver = jsreciver;\n    \n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n    \n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n    \n                return flash.exec( this.uid, comp, fn, args );\n            };\n    \n            // @todo\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n    \n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n    \n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n    \n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n    \n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n    \n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n    \n                container.html( html );\n            },\n    \n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n    \n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n    \n        });\n    \n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n    \n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n    \n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n    \n            return component;\n        };\n    \n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n    \n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n    \n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n    \n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n    \n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n    \n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview 图片压缩\n     */\n    define('runtime/flash/image',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n    \n        return FlashRuntime.register( 'Image', {\n            // init: function( options ) {\n            //     var owner = this.owner;\n    \n            //     this.flashExec( 'Image', 'init', options );\n            //     owner.on( 'load', function() {\n            //         debugger;\n            //     });\n            // },\n    \n            loadFromBlob: function( blob ) {\n                var owner = this.owner;\n    \n                owner.info() && this.flashExec( 'Image', 'info', owner.info() );\n                owner.meta() && this.flashExec( 'Image', 'meta', owner.meta() );\n    \n                this.flashExec( 'Image', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n    \n                xhr.connectRuntime( blob.ruid );\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n    \n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            getResponse: function() {\n                return this._response || '';\n            },\n    \n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n    \n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n    \n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n    \n                    xhr.off();\n                    me._xhr = null;\n    \n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n    \n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n    \n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n                            \n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n                            \n                        // }\n                    }\n                    \n                    xhr.destroy();\n                    xhr = null;\n    \n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n    \n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/flash/blob',[\n        'runtime/flash/runtime',\n        'lib/blob'\n    ], function( FlashRuntime, Blob ) {\n    \n        return FlashRuntime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.flashExec( 'Blob', 'slice', start, end );\n    \n                return new Blob( blob.uid, blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Md5 flash实现\n     */\n    define('runtime/flash/md5',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n        \n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n    \n            loadFromBlob: function( blob ) {\n                return this.flashExec( 'Md5', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview 完全版本。\n     */\n    define('preset/all',[\n        'base',\n    \n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n        'widgets/md5',\n    \n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/imagemeta/exif',\n        'runtime/html5/androidpatch',\n        'runtime/html5/image',\n        'runtime/html5/transport',\n        'runtime/html5/md5',\n    \n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/image',\n        'runtime/flash/transport',\n        'runtime/flash/blob',\n        'runtime/flash/md5'\n    ], function( Base ) {\n        return Base;\n    });\n    /**\n     * @fileOverview 日志组件，主要用来收集错误信息，可以帮助 webuploader 更好的定位问题和发展。\n     *\n     * 如果您不想要启用此功能，请在打包的时候去掉 log 模块。\n     *\n     * 或者可以在初始化的时候通过 options.disableWidgets 属性禁用。\n     *\n     * 如：\n     * WebUploader.create({\n     *     ...\n     *\n     *     disableWidgets: 'log',\n     *\n     *     ...\n     * })\n     */\n    define('widgets/log',[\n        'base',\n        'uploader',\n        'widgets/widget'\n    ], function( Base, Uploader ) {\n        var $ = Base.$,\n            logUrl = ' http://static.tieba.baidu.com/tb/pms/img/st.gif??',\n            product = (location.hostname || location.host || 'protected').toLowerCase(),\n    \n            // 只针对 baidu 内部产品用户做统计功能。\n            enable = product && /baidu/i.exec(product),\n            base;\n    \n        if (!enable) {\n            return;\n        }\n    \n        base = {\n            dv: 3,\n            master: 'webuploader',\n            online: /test/.exec(product) ? 0 : 1,\n            module: '',\n            product: product,\n            type: 0\n        };\n    \n        function send(data) {\n            var obj = $.extend({}, base, data),\n                url = logUrl.replace(/^(.*)\\?/, '$1' + $.param( obj )),\n                image = new Image();\n    \n            image.src = url;\n        }\n    \n        return Uploader.register({\n            name: 'log',\n    \n            init: function() {\n                var owner = this.owner,\n                    count = 0,\n                    size = 0;\n    \n                owner\n                    .on('error', function(code) {\n                        send({\n                            type: 2,\n                            c_error_code: code\n                        });\n                    })\n                    .on('uploadError', function(file, reason) {\n                        send({\n                            type: 2,\n                            c_error_code: 'UPLOAD_ERROR',\n                            c_reason: '' + reason\n                        });\n                    })\n                    .on('uploadComplete', function(file) {\n                        count++;\n                        size += file.size;\n                    }).\n                    on('uploadFinished', function() {\n                        send({\n                            c_count: count,\n                            c_size: size\n                        });\n                        count = size = 0;\n                    });\n    \n                send({\n                    c_usage: 1\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('webuploader',[\n        'preset/all',\n        'widgets/log'\n    ], function( preset ) {\n        return preset;\n    });\n\n    var _require = require;\n    return _require('webuploader');\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/webuploader.flashonly.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n    \n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n    \n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n    \n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n    \n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n    \n        var noop = function() {},\n            call = Function.call;\n    \n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n    \n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n    \n        function createObject( proto ) {\n            var f;\n    \n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n    \n    \n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n    \n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n    \n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n    \n            Deferred: promise.Deferred,\n    \n            isPromise: promise.isPromise,\n    \n            when: promise.when,\n    \n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n    \n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n    \n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n    \n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n    \n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n    \n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n    \n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n    \n                /* jshint camelcase: false */\n    \n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n    \n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n    \n                return child;\n            },\n    \n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n    \n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n    \n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n    \n            nextTick: (function() {\n    \n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n    \n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n    \n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n    \n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n    \n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n    \n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n    \n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n    \n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n    \n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n    \n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n    \n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n    \n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n    \n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n    \n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n    \n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n    \n            while ( ++i < len ) {\n                handler = events[ i ];\n    \n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n    \n            return !stoped;\n        }\n    \n        protos = {\n    \n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n    \n                if ( !callback ) {\n                    return this;\n                }\n    \n                set = this._events || (this._events = []);\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n    \n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n    \n                    set.push( handler );\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n    \n                if ( !callback ) {\n                    return me;\n                }\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n    \n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n    \n                return me;\n            },\n    \n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n    \n                if ( !events ) {\n                    return this;\n                }\n    \n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n    \n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n    \n                if ( !this._events || !type ) {\n                    return this;\n                }\n    \n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n    \n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n    \n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n    \n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n    \n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$;\n    \n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n    \n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n    \n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n    \n        $.extend( Uploader.prototype, {\n            state: 'pending',\n    \n            _init: function( opts ) {\n                var me = this;\n    \n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n    \n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n    \n                // setter\n                if ( arguments.length > 1 ) {\n    \n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n    \n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n    \n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n    \n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n    \n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n    \n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n    \n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n    \n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n    \n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n    \n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n    \n                    return false;\n                }\n    \n                return true;\n            },\n    \n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n    \n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n    \n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n    \n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n    \n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            factories = {},\n    \n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n    \n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n    \n        $.extend( Runtime.prototype, {\n    \n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n    \n                if ( this._container ) {\n                    return this._container;\n                }\n    \n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n    \n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n    \n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n    \n            init: Base.noop,\n            exec: Base.noop,\n    \n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n    \n        Runtime.orders = 'html5,flash';\n    \n    \n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n    \n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n    \n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n    \n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n    \n            type = type || getFirstKey( factories );\n    \n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n    \n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n    \n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n    \n        var cache;\n    \n        cache = (function() {\n            var obj = {};\n    \n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n    \n                get: function( ruid, standalone ) {\n                    var i;\n    \n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n    \n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n    \n                        return obj[ i ];\n                    }\n    \n                    return null;\n                },\n    \n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n    \n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n    \n            this.uid = Base.guid('client_');\n    \n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n    \n            this.connectRuntime = function( opts, cb ) {\n    \n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n    \n                deferred.done( cb );\n    \n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n    \n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n    \n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n    \n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                runtime.__client--;\n    \n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n    \n                runtime = null;\n            };\n    \n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n    \n                return runtime.exec.apply( this, args );\n            };\n    \n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n    \n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n    \n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n    \n        function Blob( ruid, source ) {\n            var me = this;\n    \n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n    \n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n    \n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n    \n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n    \n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n    \n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n    \n            getSource: function() {\n                return this.source;\n            }\n        });\n    \n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n    \n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n    \n        function File( ruid, file ) {\n            var ext;\n    \n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n    \n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n    \n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n    \n            Blob.apply( this, arguments );\n        }\n    \n        return Base.inherits( Blob, File );\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n    \n        var $ = Base.$;\n    \n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n    \n            opts.container = $( opts.id );\n    \n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n    \n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n    \n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n    \n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n    \n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n    \n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n    \n                button.addClass('webuploader-pick');\n    \n                me.on( 'all', function( type ) {\n                    var files;\n    \n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n    \n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n    \n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n    \n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n    \n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n    \n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n    \n                    pos = button.offset();\n    \n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n    \n            enable: function() {\n                var btn = this.options.button;\n    \n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n    \n            disable: function() {\n                var btn = this.options.button;\n    \n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n    \n                btn.addClass('webuploader-pick-disable');\n            },\n    \n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n    \n        return FilePicker;\n    });\n    \n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n    \n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n    \n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n    \n            var length = obj.length,\n                type = $.type( obj );\n    \n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n    \n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n    \n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n    \n        $.extend( Widget.prototype, {\n    \n            init: Base.noop,\n    \n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n    \n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n    \n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n    \n                    return IGNORE;\n                }\n    \n                return this[ map[ apiName ] ].apply( this, args );\n    \n            },\n    \n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n    \n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n    \n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n    \n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n    \n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n    \n                return _init.apply( me, arguments );\n            },\n    \n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n    \n                args = isArrayLike( args ) ? args : [ args ];\n    \n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n    \n                    if ( rlt !== IGNORE ) {\n    \n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n    \n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n    \n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n    \n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n    \n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n    \n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n    \n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n    \n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n    \n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n    \n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n    \n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n    \n            } else {\n                map = $.extend( map, responseMap );\n            }\n    \n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n    \n            return klass;\n        };\n    \n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *     \n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n            \n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n    \n        return Widget;\n    });\n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n    \n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n    \n        return Uploader.register({\n            name: 'picker',\n    \n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n    \n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n    \n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n    \n                if ( !pick ) {\n                    return;\n                }\n    \n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n    \n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n    \n                    deferred = Base.Deferred();\n    \n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n    \n                    picker = new FilePicker( options );\n    \n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n    \n                    me.pickers.push( picker );\n    \n                    promises.push( deferred.promise() );\n                });\n    \n                return Base.when.apply( Base, promises );\n            },\n    \n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n    \n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n    \n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n    \n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n    \n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n    \n        // 默认选项。\n        Image.options = {\n    \n            // 默认的图片处理质量\n            quality: 90,\n    \n            // 是否裁剪\n            crop: false,\n    \n            // 是否保留头部信息\n            preserveHeaders: false,\n    \n            // 是否允许放大。\n            allowMagnify: false\n        };\n    \n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n    \n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n    \n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n    \n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n    \n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    \n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n    \n        var $ = Base.$,\n            throttle;\n    \n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n    \n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n    \n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n    \n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n    \n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n    \n        return Uploader.register({\n    \n            name: 'image',\n    \n    \n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n    \n                opts = $.extend({}, this.options.thumb );\n    \n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n    \n                width = width || opts.width;\n                height = height || opts.height;\n    \n                image = new Image( opts );\n    \n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n    \n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n    \n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n    \n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n    \n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n    \n                image = new Image( opts );\n    \n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n    \n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                image.once( 'complete', function() {\n                    var blob, size;\n    \n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n    \n                        size = file.size;\n    \n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n    \n                            file.trigger( 'resize', blob.size, size );\n                        }\n    \n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n    \n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n    \n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n    \n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n    \n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n    \n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n    \n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n    \n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n    \n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n    \n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n    \n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n    \n    \n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n    \n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n    \n            this.source = source;\n            this.loaded = 0;\n    \n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n    \n        $.extend( WUFile.prototype, {\n    \n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n    \n                var prevStatus = statusMap[ this.id ];\n    \n                typeof text !== 'undefined' && (this.statusText = text);\n    \n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n    \n            },\n    \n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n    \n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n    \n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n    \n        Mediator.installTo( WUFile.prototype );\n    \n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n    \n        return WUFile;\n    });\n    \n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n    \n        var $ = Base.$,\n            STATUS = WUFile.Status;\n    \n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n    \n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n    \n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n    \n            // 存储所有文件\n            this._map = {};\n        }\n    \n        $.extend( Queue.prototype, {\n    \n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n    \n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n    \n                status = status || STATUS.QUEUED;\n    \n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n    \n                return null;\n            },\n    \n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n    \n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n    \n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n    \n                    ret.push( file );\n                }\n    \n                return ret;\n            },\n    \n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n    \n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n    \n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n    \n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n    \n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n    \n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n    \n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n    \n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n    \n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n    \n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n    \n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n    \n        });\n    \n        Mediator.installTo( Queue.prototype );\n    \n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n    \n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n    \n        return Uploader.register({\n            name: 'queue',\n    \n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n    \n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n    \n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n    \n                    me.accept = new RegExp( accept, 'i' );\n                }\n    \n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n    \n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n    \n    \n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n    \n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n    \n                    file = new WUFile( file );\n                }\n    \n                return file;\n            },\n    \n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n    \n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n    \n                return !invalid;\n            },\n    \n    \n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n    \n            _addFile: function( file ) {\n                var me = this;\n    \n                file = me._wrapFile( file );\n    \n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n    \n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n    \n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n    \n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n    \n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n            \n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             * \n             */\n    \n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n    \n                if ( !files.length ) {\n                    files = [ files ];\n                }\n    \n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n    \n                me.owner.trigger( 'filesQueued', files );\n    \n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n    \n            getStats: function() {\n                return this.stats;\n            },\n    \n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n    \n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n    \n                file = file.id ? file : me.queue.getFile( file );\n    \n                this.request( 'cancel-file', file );\n    \n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n    \n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n    \n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n    \n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n    \n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n    \n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n    \n                me.request('start-upload');\n            },\n    \n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n    \n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n    \n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n    \n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n    \n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n    \n        return Uploader.register({\n            name: 'runtime',\n    \n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n    \n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n    \n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n    \n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n    \n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n    \n        var $ = Base.$;\n    \n        function Transport( opts ) {\n            var me = this;\n    \n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n    \n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n    \n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n    \n        Transport.options = {\n            server: '',\n            method: 'POST',\n    \n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n    \n        $.extend( Transport.prototype, {\n    \n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n    \n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n    \n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n    \n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n    \n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n    \n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n    \n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n    \n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n    \n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n    \n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n    \n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n    \n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n    \n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n    \n                if ( !duration ) {\n                    return;\n                }\n    \n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n    \n        });\n    \n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n    \n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n    \n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n    \n        // 添加默认配置项\n        $.extend( Uploader.options, {\n    \n    \n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n    \n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n    \n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n    \n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n    \n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n    \n    \n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n    \n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n    \n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n    \n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n    \n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n    \n            api = {\n                file: file,\n    \n                has: function() {\n                    return !!pending.length;\n                },\n    \n                shift: function() {\n                    return pending.shift();\n                },\n    \n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n    \n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n    \n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n    \n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n    \n            return api;\n        }\n    \n        Uploader.register({\n            name: 'upload',\n    \n            init: function() {\n                var owner = this.owner,\n                    me = this;\n    \n                this.runing = false;\n                this.progress = false;\n    \n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n    \n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n    \n                // 缓存分好片的文件。\n                this.stack = [];\n    \n                // 缓存即将上传的文件。\n                this.pending = [];\n    \n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n    \n                owner.on( 'uploadComplete', function( file ) {\n    \n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n    \n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n    \n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n    \n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n    \n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n    \n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n    \n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n    \n                            v.transport && v.transport.send();\n                        });\n    \n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n    \n                if ( me.runing ) {\n                    return;\n                }\n    \n                me.runing = true;\n    \n                var files = [];\n    \n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n    \n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n    \n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n    \n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n    \n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n    \n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n    \n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n    \n                if ( me.runing === false ) {\n                    return;\n                }\n    \n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n    \n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n    \n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n    \n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n    \n                    return Base.nextTick( me.__tick );\n                }\n    \n                me.runing = false;\n    \n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n    \n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n    \n                me.owner.trigger('stopUpload');\n            },\n    \n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n    \n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n    \n            _getStats: function() {\n                return this.request('get-stats');\n            },\n    \n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                this.owner.trigger( 'uploadSkip', file );\n            },\n    \n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n    \n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n    \n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n    \n                    fn = function( val ) {\n                        me._promise = null;\n    \n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n    \n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n    \n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n    \n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n    \n            _putback: function(block) {\n                var idx;\n    \n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n    \n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n    \n            _getStack: function() {\n                var i = 0,\n                    act;\n    \n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n    \n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n    \n                return null;\n            },\n    \n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n    \n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n    \n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n    \n                    return act.shift();\n    \n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n    \n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n    \n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n    \n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n    \n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n    \n                    return done( next );\n                }\n            },\n    \n    \n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n    \n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n    \n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n    \n                        return me._finishFile( file );\n                    });\n    \n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n    \n                    promise.file = file;\n    \n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n    \n                        ~idx && pending.splice( idx, 1, file );\n                    });\n    \n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n    \n                    pending.push( promise );\n                }\n            },\n    \n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n    \n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n    \n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n    \n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n    \n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n    \n                    return;\n                }\n    \n                me.pool.push( block );\n                me.remaning++;\n    \n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n    \n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n    \n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n    \n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n    \n    \n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n    \n    \n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n    \n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n    \n                block.transport = tr;\n    \n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n    \n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n    \n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n    \n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n    \n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n    \n                    return reject;\n                };\n    \n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n    \n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n    \n                        block.retried++;\n                        tr.send();\n    \n                    } else {\n    \n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n    \n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n    \n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n    \n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n    \n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n    \n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n    \n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n    \n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n    \n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n    \n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n    \n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n    \n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n    \n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n    \n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n    \n                if (!file.blocks) {\n                    return;\n                }\n    \n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n    \n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n    \n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n    \n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n    \n        var $ = Base.$,\n            validators = {},\n            api;\n    \n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n    \n        // 暴露给外面的api\n        api = {\n    \n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n    \n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n    \n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n    \n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n    \n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return count >= max ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n    \n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n    \n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n    \n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return invalid ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n    \n            });\n    \n        });\n    \n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n    \n            if ( opts.duplicate ) {\n                return;\n            }\n    \n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n    \n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n    \n                return hash;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n    \n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (mapping[ hash ] = true);\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (delete mapping[ hash ]);\n            });\n    \n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n    \n        return api;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n    \n        function CompBase( owner, runtime ) {\n    \n            this.owner = owner;\n            this.options = owner.options;\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.getRuid = function() {\n                return runtime.uid;\n            };\n    \n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n    \n        return CompBase;\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n    \n    \n        function getFlashVersion() {\n            var version;\n    \n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n    \n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                clients[ uid ] = client;\n    \n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n    \n                    instance = pool[ uid ];\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n    \n                return me.flashExec.apply( client, arguments );\n            };\n    \n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n    \n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n    \n                // console.log.apply( console, arguments );\n    \n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n    \n                // Base.log( evt, obj );\n            }\n    \n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n    \n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n    \n            this.jsreciver = jsreciver;\n    \n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n    \n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n    \n                return flash.exec( this.uid, comp, fn, args );\n            };\n    \n            // @todo\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n    \n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n    \n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n    \n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n    \n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n    \n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n    \n                container.html( html );\n            },\n    \n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n    \n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n    \n        });\n    \n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n    \n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n    \n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n    \n            return component;\n        };\n    \n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n    \n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n    \n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n    \n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n    \n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n    \n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview 图片压缩\n     */\n    define('runtime/flash/image',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n    \n        return FlashRuntime.register( 'Image', {\n            // init: function( options ) {\n            //     var owner = this.owner;\n    \n            //     this.flashExec( 'Image', 'init', options );\n            //     owner.on( 'load', function() {\n            //         debugger;\n            //     });\n            // },\n    \n            loadFromBlob: function( blob ) {\n                var owner = this.owner;\n    \n                owner.info() && this.flashExec( 'Image', 'info', owner.info() );\n                owner.meta() && this.flashExec( 'Image', 'meta', owner.meta() );\n    \n                this.flashExec( 'Image', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/flash/blob',[\n        'runtime/flash/runtime',\n        'lib/blob'\n    ], function( FlashRuntime, Blob ) {\n    \n        return FlashRuntime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.flashExec( 'Blob', 'slice', start, end );\n    \n                return new Blob( blob.uid, blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n    \n                xhr.connectRuntime( blob.ruid );\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n    \n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            getResponse: function() {\n                return this._response || '';\n            },\n    \n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n    \n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n    \n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n    \n                    xhr.off();\n                    me._xhr = null;\n    \n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n    \n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n    \n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n                            \n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n                            \n                        // }\n                    }\n                    \n                    xhr.destroy();\n                    xhr = null;\n    \n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n    \n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview 只有flash实现的文件版本。\n     */\n    define('preset/flashonly',[\n        'base',\n    \n        // widgets\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n    \n        // runtimes\n    \n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/image',\n        'runtime/flash/blob',\n        'runtime/flash/transport'\n    ], function( Base ) {\n        return Base;\n    });\n    define('webuploader',[\n        'preset/flashonly'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/webuploader.html5only.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n    \n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n    \n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n    \n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n    \n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n    \n        var noop = function() {},\n            call = Function.call;\n    \n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n    \n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n    \n        function createObject( proto ) {\n            var f;\n    \n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n    \n    \n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n    \n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n    \n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n    \n            Deferred: promise.Deferred,\n    \n            isPromise: promise.isPromise,\n    \n            when: promise.when,\n    \n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n    \n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n    \n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n    \n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n    \n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n    \n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n    \n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n    \n                /* jshint camelcase: false */\n    \n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n    \n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n    \n                return child;\n            },\n    \n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n    \n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n    \n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n    \n            nextTick: (function() {\n    \n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n    \n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n    \n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n    \n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n    \n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n    \n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n    \n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n    \n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n    \n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n    \n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n    \n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n    \n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n    \n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n    \n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n    \n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n    \n            while ( ++i < len ) {\n                handler = events[ i ];\n    \n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n    \n            return !stoped;\n        }\n    \n        protos = {\n    \n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n    \n                if ( !callback ) {\n                    return this;\n                }\n    \n                set = this._events || (this._events = []);\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n    \n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n    \n                    set.push( handler );\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n    \n                if ( !callback ) {\n                    return me;\n                }\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n    \n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n    \n                return me;\n            },\n    \n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n    \n                if ( !events ) {\n                    return this;\n                }\n    \n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n    \n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n    \n                if ( !this._events || !type ) {\n                    return this;\n                }\n    \n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n    \n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n    \n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n    \n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n    \n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$;\n    \n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n    \n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n    \n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n    \n        $.extend( Uploader.prototype, {\n            state: 'pending',\n    \n            _init: function( opts ) {\n                var me = this;\n    \n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n    \n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n    \n                // setter\n                if ( arguments.length > 1 ) {\n    \n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n    \n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n    \n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n    \n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n    \n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n    \n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n    \n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n    \n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n    \n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n    \n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n    \n                    return false;\n                }\n    \n                return true;\n            },\n    \n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n    \n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n    \n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n    \n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n    \n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            factories = {},\n    \n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n    \n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n    \n        $.extend( Runtime.prototype, {\n    \n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n    \n                if ( this._container ) {\n                    return this._container;\n                }\n    \n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n    \n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n    \n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n    \n            init: Base.noop,\n            exec: Base.noop,\n    \n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n    \n        Runtime.orders = 'html5,flash';\n    \n    \n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n    \n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n    \n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n    \n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n    \n            type = type || getFirstKey( factories );\n    \n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n    \n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n    \n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n    \n        var cache;\n    \n        cache = (function() {\n            var obj = {};\n    \n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n    \n                get: function( ruid, standalone ) {\n                    var i;\n    \n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n    \n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n    \n                        return obj[ i ];\n                    }\n    \n                    return null;\n                },\n    \n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n    \n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n    \n            this.uid = Base.guid('client_');\n    \n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n    \n            this.connectRuntime = function( opts, cb ) {\n    \n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n    \n                deferred.done( cb );\n    \n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n    \n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n    \n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n    \n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                runtime.__client--;\n    \n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n    \n                runtime = null;\n            };\n    \n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n    \n                return runtime.exec.apply( this, args );\n            };\n    \n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n    \n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n    \n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n    \n            opts.container = $( opts.container );\n    \n            if ( !opts.container.length ) {\n                return;\n            }\n    \n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n    \n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( DragAndDrop.prototype );\n    \n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n    \n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n    \n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n    \n            var length = obj.length,\n                type = $.type( obj );\n    \n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n    \n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n    \n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n    \n        $.extend( Widget.prototype, {\n    \n            init: Base.noop,\n    \n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n    \n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n    \n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n    \n                    return IGNORE;\n                }\n    \n                return this[ map[ apiName ] ].apply( this, args );\n    \n            },\n    \n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n    \n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n    \n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n    \n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n    \n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n    \n                return _init.apply( me, arguments );\n            },\n    \n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n    \n                args = isArrayLike( args ) ? args : [ args ];\n    \n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n    \n                    if ( rlt !== IGNORE ) {\n    \n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n    \n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n    \n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n    \n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n    \n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n    \n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n    \n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n    \n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n    \n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n    \n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n    \n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n    \n            } else {\n                map = $.extend( map, responseMap );\n            }\n    \n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n    \n            return klass;\n        };\n    \n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *     \n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n            \n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n    \n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n    \n        Uploader.options.dnd = '';\n    \n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n        \n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n    \n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n            \n            init: function( opts ) {\n    \n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n    \n                this.dnd = dnd = new Dnd( options );\n    \n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n    \n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n    \n                dnd.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( FilePaste.prototype );\n    \n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n    \n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n            \n            init: function( opts ) {\n    \n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n    \n                this.paste = paste = new FilePaste( options );\n    \n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n    \n        function Blob( ruid, source ) {\n            var me = this;\n    \n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n    \n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n    \n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n    \n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n    \n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n    \n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n    \n            getSource: function() {\n                return this.source;\n            }\n        });\n    \n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n    \n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n    \n        function File( ruid, file ) {\n            var ext;\n    \n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n    \n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n    \n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n    \n            Blob.apply( this, arguments );\n        }\n    \n        return Base.inherits( Blob, File );\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n    \n        var $ = Base.$;\n    \n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n    \n            opts.container = $( opts.id );\n    \n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n    \n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n    \n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n    \n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n    \n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n    \n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n    \n                button.addClass('webuploader-pick');\n    \n                me.on( 'all', function( type ) {\n                    var files;\n    \n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n    \n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n    \n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n    \n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n    \n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n    \n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n    \n                    pos = button.offset();\n    \n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n    \n            enable: function() {\n                var btn = this.options.button;\n    \n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n    \n            disable: function() {\n                var btn = this.options.button;\n    \n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n    \n                btn.addClass('webuploader-pick-disable');\n            },\n    \n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n    \n        return FilePicker;\n    });\n    \n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n    \n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n    \n        return Uploader.register({\n            name: 'picker',\n    \n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n    \n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n    \n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n    \n                if ( !pick ) {\n                    return;\n                }\n    \n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n    \n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n    \n                    deferred = Base.Deferred();\n    \n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n    \n                    picker = new FilePicker( options );\n    \n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n    \n                    me.pickers.push( picker );\n    \n                    promises.push( deferred.promise() );\n                });\n    \n                return Base.when.apply( Base, promises );\n            },\n    \n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n    \n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n    \n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n    \n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n    \n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n    \n        // 默认选项。\n        Image.options = {\n    \n            // 默认的图片处理质量\n            quality: 90,\n    \n            // 是否裁剪\n            crop: false,\n    \n            // 是否保留头部信息\n            preserveHeaders: false,\n    \n            // 是否允许放大。\n            allowMagnify: false\n        };\n    \n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n    \n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n    \n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n    \n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n    \n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    \n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n    \n        var $ = Base.$,\n            throttle;\n    \n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n    \n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n    \n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n    \n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n    \n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n    \n        return Uploader.register({\n    \n            name: 'image',\n    \n    \n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n    \n                opts = $.extend({}, this.options.thumb );\n    \n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n    \n                width = width || opts.width;\n                height = height || opts.height;\n    \n                image = new Image( opts );\n    \n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n    \n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n    \n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n    \n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n    \n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n    \n                image = new Image( opts );\n    \n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n    \n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                image.once( 'complete', function() {\n                    var blob, size;\n    \n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n    \n                        size = file.size;\n    \n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n    \n                            file.trigger( 'resize', blob.size, size );\n                        }\n    \n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n    \n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n    \n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n    \n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n    \n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n    \n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n    \n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n    \n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n    \n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n    \n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n    \n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n    \n    \n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n    \n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n    \n            this.source = source;\n            this.loaded = 0;\n    \n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n    \n        $.extend( WUFile.prototype, {\n    \n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n    \n                var prevStatus = statusMap[ this.id ];\n    \n                typeof text !== 'undefined' && (this.statusText = text);\n    \n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n    \n            },\n    \n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n    \n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n    \n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n    \n        Mediator.installTo( WUFile.prototype );\n    \n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n    \n        return WUFile;\n    });\n    \n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n    \n        var $ = Base.$,\n            STATUS = WUFile.Status;\n    \n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n    \n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n    \n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n    \n            // 存储所有文件\n            this._map = {};\n        }\n    \n        $.extend( Queue.prototype, {\n    \n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n    \n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n    \n                status = status || STATUS.QUEUED;\n    \n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n    \n                return null;\n            },\n    \n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n    \n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n    \n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n    \n                    ret.push( file );\n                }\n    \n                return ret;\n            },\n    \n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n    \n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n    \n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n    \n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n    \n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n    \n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n    \n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n    \n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n    \n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n    \n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n    \n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n    \n        });\n    \n        Mediator.installTo( Queue.prototype );\n    \n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n    \n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n    \n        return Uploader.register({\n            name: 'queue',\n    \n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n    \n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n    \n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n    \n                    me.accept = new RegExp( accept, 'i' );\n                }\n    \n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n    \n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n    \n    \n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n    \n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n    \n                    file = new WUFile( file );\n                }\n    \n                return file;\n            },\n    \n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n    \n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n    \n                return !invalid;\n            },\n    \n    \n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n    \n            _addFile: function( file ) {\n                var me = this;\n    \n                file = me._wrapFile( file );\n    \n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n    \n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n    \n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n    \n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n    \n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n            \n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             * \n             */\n    \n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n    \n                if ( !files.length ) {\n                    files = [ files ];\n                }\n    \n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n    \n                me.owner.trigger( 'filesQueued', files );\n    \n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n    \n            getStats: function() {\n                return this.stats;\n            },\n    \n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n    \n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n    \n                file = file.id ? file : me.queue.getFile( file );\n    \n                this.request( 'cancel-file', file );\n    \n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n    \n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n    \n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n    \n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n    \n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n    \n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n    \n                me.request('start-upload');\n            },\n    \n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n    \n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n    \n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n    \n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n    \n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n    \n        return Uploader.register({\n            name: 'runtime',\n    \n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n    \n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n    \n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n    \n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n    \n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n    \n        var $ = Base.$;\n    \n        function Transport( opts ) {\n            var me = this;\n    \n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n    \n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n    \n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n    \n        Transport.options = {\n            server: '',\n            method: 'POST',\n    \n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n    \n        $.extend( Transport.prototype, {\n    \n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n    \n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n    \n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n    \n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n    \n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n    \n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n    \n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n    \n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n    \n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n    \n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n    \n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n    \n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n    \n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n    \n                if ( !duration ) {\n                    return;\n                }\n    \n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n    \n        });\n    \n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n    \n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n    \n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n    \n        // 添加默认配置项\n        $.extend( Uploader.options, {\n    \n    \n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n    \n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n    \n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n    \n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n    \n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n    \n    \n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n    \n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n    \n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n    \n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n    \n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n    \n            api = {\n                file: file,\n    \n                has: function() {\n                    return !!pending.length;\n                },\n    \n                shift: function() {\n                    return pending.shift();\n                },\n    \n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n    \n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n    \n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n    \n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n    \n            return api;\n        }\n    \n        Uploader.register({\n            name: 'upload',\n    \n            init: function() {\n                var owner = this.owner,\n                    me = this;\n    \n                this.runing = false;\n                this.progress = false;\n    \n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n    \n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n    \n                // 缓存分好片的文件。\n                this.stack = [];\n    \n                // 缓存即将上传的文件。\n                this.pending = [];\n    \n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n    \n                owner.on( 'uploadComplete', function( file ) {\n    \n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n    \n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n    \n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n    \n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n    \n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n    \n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n    \n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n    \n                            v.transport && v.transport.send();\n                        });\n    \n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n    \n                if ( me.runing ) {\n                    return;\n                }\n    \n                me.runing = true;\n    \n                var files = [];\n    \n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n    \n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n    \n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n    \n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n    \n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n    \n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n    \n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n    \n                if ( me.runing === false ) {\n                    return;\n                }\n    \n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n    \n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n    \n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n    \n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n    \n                    return Base.nextTick( me.__tick );\n                }\n    \n                me.runing = false;\n    \n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n    \n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n    \n                me.owner.trigger('stopUpload');\n            },\n    \n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n    \n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n    \n            _getStats: function() {\n                return this.request('get-stats');\n            },\n    \n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                this.owner.trigger( 'uploadSkip', file );\n            },\n    \n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n    \n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n    \n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n    \n                    fn = function( val ) {\n                        me._promise = null;\n    \n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n    \n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n    \n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n    \n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n    \n            _putback: function(block) {\n                var idx;\n    \n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n    \n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n    \n            _getStack: function() {\n                var i = 0,\n                    act;\n    \n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n    \n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n    \n                return null;\n            },\n    \n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n    \n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n    \n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n    \n                    return act.shift();\n    \n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n    \n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n    \n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n    \n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n    \n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n    \n                    return done( next );\n                }\n            },\n    \n    \n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n    \n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n    \n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n    \n                        return me._finishFile( file );\n                    });\n    \n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n    \n                    promise.file = file;\n    \n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n    \n                        ~idx && pending.splice( idx, 1, file );\n                    });\n    \n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n    \n                    pending.push( promise );\n                }\n            },\n    \n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n    \n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n    \n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n    \n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n    \n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n    \n                    return;\n                }\n    \n                me.pool.push( block );\n                me.remaning++;\n    \n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n    \n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n    \n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n    \n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n    \n    \n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n    \n    \n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n    \n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n    \n                block.transport = tr;\n    \n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n    \n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n    \n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n    \n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n    \n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n    \n                    return reject;\n                };\n    \n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n    \n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n    \n                        block.retried++;\n                        tr.send();\n    \n                    } else {\n    \n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n    \n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n    \n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n    \n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n    \n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n    \n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n    \n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n    \n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n    \n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n    \n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n    \n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n    \n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n    \n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n    \n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n    \n                if (!file.blocks) {\n                    return;\n                }\n    \n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n    \n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n    \n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n    \n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n    \n        var $ = Base.$,\n            validators = {},\n            api;\n    \n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n    \n        // 暴露给外面的api\n        api = {\n    \n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n    \n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n    \n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n    \n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n    \n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return count >= max ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n    \n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n    \n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n    \n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return invalid ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n    \n            });\n    \n        });\n    \n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n    \n            if ( opts.duplicate ) {\n                return;\n            }\n    \n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n    \n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n    \n                return hash;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n    \n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (mapping[ hash ] = true);\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (delete mapping[ hash ]);\n            });\n    \n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n    \n        return api;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n    \n        function CompBase( owner, runtime ) {\n    \n            this.owner = owner;\n            this.options = owner.options;\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.getRuid = function() {\n                return runtime.uid;\n            };\n    \n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n    \n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var type = 'html5',\n            components = {};\n    \n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n    \n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n    \n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n    \n        });\n    \n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n    \n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n    \n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n    \n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n    \n                blob = slice.call( blob, start, end );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n    \n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n    \n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n    \n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n    \n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n    \n                e = e.originalEvent || e;\n    \n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n    \n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n    \n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n    \n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n    \n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n    \n                return false;\n            },\n    \n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n    \n                return false;\n            },\n    \n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n    \n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n    \n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n    \n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n    \n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n    \n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n    \n                if ( data ) {\n                    return;\n                }\n    \n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n    \n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n    \n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n    \n                items = dataTransfer.items;\n                files = dataTransfer.files;\n    \n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n    \n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n    \n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n    \n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n    \n                Base.when.apply( Base, promises ).done(function() {\n    \n                    if ( !results.length ) {\n                        return;\n                    }\n    \n                    callback( results );\n                });\n            },\n    \n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n    \n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n    \n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n    \n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                var elem = this.elem;\n    \n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n                \n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n    \n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n    \n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n    \n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n    \n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n    \n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n    \n                    allowed.push( new File( ruid, blob ) );\n                }\n    \n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n    \n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var $ = Base.$;\n    \n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n    \n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n    \n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n    \n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n    \n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n    \n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n    \n                    input.attr( 'accept', arr.join(',') );\n                }\n    \n                container.append( input );\n                container.append( label );\n    \n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n    \n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n    \n                    me.files = e.target.files;\n    \n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n    \n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n    \n                    owner.trigger('change');\n                });\n    \n                label.on( 'mouseenter mouseleave', mouseHandler );\n    \n            },\n    \n    \n            getFiles: function() {\n                return this.files;\n            },\n    \n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/util',[\n        'base'\n    ], function( Base ) {\n    \n        var urlAPI = window.createObjectURL && window ||\n                window.URL && URL.revokeObjectURL && URL ||\n                window.webkitURL,\n            createObjectURL = Base.noop,\n            revokeObjectURL = createObjectURL;\n    \n        if ( urlAPI ) {\n    \n            // 更安全的方式调用，比如android里面就能把context改成其他的对象。\n            createObjectURL = function() {\n                return urlAPI.createObjectURL.apply( urlAPI, arguments );\n            };\n    \n            revokeObjectURL = function() {\n                return urlAPI.revokeObjectURL.apply( urlAPI, arguments );\n            };\n        }\n    \n        return {\n            createObjectURL: createObjectURL,\n            revokeObjectURL: revokeObjectURL,\n    \n            dataURL2Blob: function( dataURI ) {\n                var byteStr, intArray, ab, i, mimetype, parts;\n    \n                parts = dataURI.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                ab = new ArrayBuffer( byteStr.length );\n                intArray = new Uint8Array( ab );\n    \n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n    \n                mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ];\n    \n                return this.arrayBufferToBlob( ab, mimetype );\n            },\n    \n            dataURL2ArrayBuffer: function( dataURI ) {\n                var byteStr, intArray, i, parts;\n    \n                parts = dataURI.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                intArray = new Uint8Array( byteStr.length );\n    \n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n    \n                return intArray.buffer;\n            },\n    \n            arrayBufferToBlob: function( buffer, type ) {\n                var builder = window.BlobBuilder || window.WebKitBlobBuilder,\n                    bb;\n    \n                // android不支持直接new Blob, 只能借助blobbuilder.\n                if ( builder ) {\n                    bb = new builder();\n                    bb.append( buffer );\n                    return bb.getBlob( type );\n                }\n    \n                return new Blob([ buffer ], type ? { type: type } : {} );\n            },\n    \n            // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg.\n            // 你得到的结果是png.\n            canvasToDataUrl: function( canvas, type, quality ) {\n                return canvas.toDataURL( type, quality / 100 );\n            },\n    \n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            parseMeta: function( blob, callback ) {\n                callback( false, {});\n            },\n    \n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            updateImageHead: function( data ) {\n                return data;\n            }\n        };\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/imagemeta',[\n        'runtime/html5/util'\n    ], function( Util ) {\n    \n        var api;\n    \n        api = {\n            parsers: {\n                0xffe1: []\n            },\n    \n            maxMetaDataSize: 262144,\n    \n            parse: function( blob, cb ) {\n                var me = this,\n                    fr = new FileReader();\n    \n                fr.onload = function() {\n                    cb( false, me._parse( this.result ) );\n                    fr = fr.onload = fr.onerror = null;\n                };\n    \n                fr.onerror = function( e ) {\n                    cb( e.message );\n                    fr = fr.onload = fr.onerror = null;\n                };\n    \n                blob = blob.slice( 0, me.maxMetaDataSize );\n                fr.readAsArrayBuffer( blob.getSource() );\n            },\n    \n            _parse: function( buffer, noParse ) {\n                if ( buffer.byteLength < 6 ) {\n                    return;\n                }\n    \n                var dataview = new DataView( buffer ),\n                    offset = 2,\n                    maxOffset = dataview.byteLength - 4,\n                    headLength = offset,\n                    ret = {},\n                    markerBytes, markerLength, parsers, i;\n    \n                if ( dataview.getUint16( 0 ) === 0xffd8 ) {\n    \n                    while ( offset < maxOffset ) {\n                        markerBytes = dataview.getUint16( offset );\n    \n                        if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef ||\n                                markerBytes === 0xfffe ) {\n    \n                            markerLength = dataview.getUint16( offset + 2 ) + 2;\n    \n                            if ( offset + markerLength > dataview.byteLength ) {\n                                break;\n                            }\n    \n                            parsers = api.parsers[ markerBytes ];\n    \n                            if ( !noParse && parsers ) {\n                                for ( i = 0; i < parsers.length; i += 1 ) {\n                                    parsers[ i ].call( api, dataview, offset,\n                                            markerLength, ret );\n                                }\n                            }\n    \n                            offset += markerLength;\n                            headLength = offset;\n                        } else {\n                            break;\n                        }\n                    }\n    \n                    if ( headLength > 6 ) {\n                        if ( buffer.slice ) {\n                            ret.imageHead = buffer.slice( 2, headLength );\n                        } else {\n                            // Workaround for IE10, which does not yet\n                            // support ArrayBuffer.slice:\n                            ret.imageHead = new Uint8Array( buffer )\n                                    .subarray( 2, headLength );\n                        }\n                    }\n                }\n    \n                return ret;\n            },\n    \n            updateImageHead: function( buffer, head ) {\n                var data = this._parse( buffer, true ),\n                    buf1, buf2, bodyoffset;\n    \n    \n                bodyoffset = 2;\n                if ( data.imageHead ) {\n                    bodyoffset = 2 + data.imageHead.byteLength;\n                }\n    \n                if ( buffer.slice ) {\n                    buf2 = buffer.slice( bodyoffset );\n                } else {\n                    buf2 = new Uint8Array( buffer ).subarray( bodyoffset );\n                }\n    \n                buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength );\n    \n                buf1[ 0 ] = 0xFF;\n                buf1[ 1 ] = 0xD8;\n                buf1.set( new Uint8Array( head ), 2 );\n                buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 );\n    \n                return buf1.buffer;\n            }\n        };\n    \n        Util.parseMeta = function() {\n            return api.parse.apply( api, arguments );\n        };\n    \n        Util.updateImageHead = function() {\n            return api.updateImageHead.apply( api, arguments );\n        };\n    \n        return api;\n    });\n    /**\n     * 代码来自于：https://github.com/blueimp/JavaScript-Load-Image\n     * 暂时项目中只用了orientation.\n     *\n     * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail.\n     * @fileOverview EXIF解析\n     */\n    \n    // Sample\n    // ====================================\n    // Make : Apple\n    // Model : iPhone 4S\n    // Orientation : 1\n    // XResolution : 72 [72/1]\n    // YResolution : 72 [72/1]\n    // ResolutionUnit : 2\n    // Software : QuickTime 7.7.1\n    // DateTime : 2013:09:01 22:53:55\n    // ExifIFDPointer : 190\n    // ExposureTime : 0.058823529411764705 [1/17]\n    // FNumber : 2.4 [12/5]\n    // ExposureProgram : Normal program\n    // ISOSpeedRatings : 800\n    // ExifVersion : 0220\n    // DateTimeOriginal : 2013:09:01 22:52:51\n    // DateTimeDigitized : 2013:09:01 22:52:51\n    // ComponentsConfiguration : YCbCr\n    // ShutterSpeedValue : 4.058893515764426\n    // ApertureValue : 2.5260688216892597 [4845/1918]\n    // BrightnessValue : -0.3126686601998395\n    // MeteringMode : Pattern\n    // Flash : Flash did not fire, compulsory flash mode\n    // FocalLength : 4.28 [107/25]\n    // SubjectArea : [4 values]\n    // FlashpixVersion : 0100\n    // ColorSpace : 1\n    // PixelXDimension : 2448\n    // PixelYDimension : 3264\n    // SensingMethod : One-chip color area sensor\n    // ExposureMode : 0\n    // WhiteBalance : Auto white balance\n    // FocalLengthIn35mmFilm : 35\n    // SceneCaptureType : Standard\n    define('runtime/html5/imagemeta/exif',[\n        'base',\n        'runtime/html5/imagemeta'\n    ], function( Base, ImageMeta ) {\n    \n        var EXIF = {};\n    \n        EXIF.ExifMap = function() {\n            return this;\n        };\n    \n        EXIF.ExifMap.prototype.map = {\n            'Orientation': 0x0112\n        };\n    \n        EXIF.ExifMap.prototype.get = function( id ) {\n            return this[ id ] || this[ this.map[ id ] ];\n        };\n    \n        EXIF.exifTagTypes = {\n            // byte, 8-bit unsigned int:\n            1: {\n                getValue: function( dataView, dataOffset ) {\n                    return dataView.getUint8( dataOffset );\n                },\n                size: 1\n            },\n    \n            // ascii, 8-bit byte:\n            2: {\n                getValue: function( dataView, dataOffset ) {\n                    return String.fromCharCode( dataView.getUint8( dataOffset ) );\n                },\n                size: 1,\n                ascii: true\n            },\n    \n            // short, 16 bit int:\n            3: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint16( dataOffset, littleEndian );\n                },\n                size: 2\n            },\n    \n            // long, 32 bit int:\n            4: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n    \n            // rational = two long values,\n            // first is numerator, second is denominator:\n            5: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian ) /\n                        dataView.getUint32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            },\n    \n            // slong, 32 bit signed int:\n            9: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n    \n            // srational, two slongs, first is numerator, second is denominator:\n            10: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian ) /\n                        dataView.getInt32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            }\n        };\n    \n        // undefined, 8-bit byte, value depending on field:\n        EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ];\n    \n        EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length,\n                littleEndian ) {\n    \n            var tagType = EXIF.exifTagTypes[ type ],\n                tagSize, dataOffset, values, i, str, c;\n    \n            if ( !tagType ) {\n                Base.log('Invalid Exif data: Invalid tag type.');\n                return;\n            }\n    \n            tagSize = tagType.size * length;\n    \n            // Determine if the value is contained in the dataOffset bytes,\n            // or if the value at the dataOffset is a pointer to the actual data:\n            dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8,\n                    littleEndian ) : (offset + 8);\n    \n            if ( dataOffset + tagSize > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid data offset.');\n                return;\n            }\n    \n            if ( length === 1 ) {\n                return tagType.getValue( dataView, dataOffset, littleEndian );\n            }\n    \n            values = [];\n    \n            for ( i = 0; i < length; i += 1 ) {\n                values[ i ] = tagType.getValue( dataView,\n                        dataOffset + i * tagType.size, littleEndian );\n            }\n    \n            if ( tagType.ascii ) {\n                str = '';\n    \n                // Concatenate the chars:\n                for ( i = 0; i < values.length; i += 1 ) {\n                    c = values[ i ];\n    \n                    // Ignore the terminating NULL byte(s):\n                    if ( c === '\\u0000' ) {\n                        break;\n                    }\n                    str += c;\n                }\n    \n                return str;\n            }\n            return values;\n        };\n    \n        EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian,\n                data ) {\n    \n            var tag = dataView.getUint16( offset, littleEndian );\n            data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset,\n                    dataView.getUint16( offset + 2, littleEndian ),    // tag type\n                    dataView.getUint32( offset + 4, littleEndian ),    // tag length\n                    littleEndian );\n        };\n    \n        EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset,\n                littleEndian, data ) {\n    \n            var tagsNumber, dirEndOffset, i;\n    \n            if ( dirOffset + 6 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory offset.');\n                return;\n            }\n    \n            tagsNumber = dataView.getUint16( dirOffset, littleEndian );\n            dirEndOffset = dirOffset + 2 + 12 * tagsNumber;\n    \n            if ( dirEndOffset + 4 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory size.');\n                return;\n            }\n    \n            for ( i = 0; i < tagsNumber; i += 1 ) {\n                this.parseExifTag( dataView, tiffOffset,\n                        dirOffset + 2 + 12 * i,    // tag offset\n                        littleEndian, data );\n            }\n    \n            // Return the offset to the next directory:\n            return dataView.getUint32( dirEndOffset, littleEndian );\n        };\n    \n        // EXIF.getExifThumbnail = function(dataView, offset, length) {\n        //     var hexData,\n        //         i,\n        //         b;\n        //     if (!length || offset + length > dataView.byteLength) {\n        //         Base.log('Invalid Exif data: Invalid thumbnail data.');\n        //         return;\n        //     }\n        //     hexData = [];\n        //     for (i = 0; i < length; i += 1) {\n        //         b = dataView.getUint8(offset + i);\n        //         hexData.push((b < 16 ? '0' : '') + b.toString(16));\n        //     }\n        //     return 'data:image/jpeg,%' + hexData.join('%');\n        // };\n    \n        EXIF.parseExifData = function( dataView, offset, length, data ) {\n    \n            var tiffOffset = offset + 10,\n                littleEndian, dirOffset;\n    \n            // Check for the ASCII code for \"Exif\" (0x45786966):\n            if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) {\n                // No Exif data, might be XMP data instead\n                return;\n            }\n            if ( tiffOffset + 8 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid segment size.');\n                return;\n            }\n    \n            // Check for the two null bytes:\n            if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) {\n                Base.log('Invalid Exif data: Missing byte alignment offset.');\n                return;\n            }\n    \n            // Check the byte alignment:\n            switch ( dataView.getUint16( tiffOffset ) ) {\n                case 0x4949:\n                    littleEndian = true;\n                    break;\n    \n                case 0x4D4D:\n                    littleEndian = false;\n                    break;\n    \n                default:\n                    Base.log('Invalid Exif data: Invalid byte alignment marker.');\n                    return;\n            }\n    \n            // Check for the TIFF tag marker (0x002A):\n            if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) {\n                Base.log('Invalid Exif data: Missing TIFF marker.');\n                return;\n            }\n    \n            // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:\n            dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian );\n            // Create the exif object to store the tags:\n            data.exif = new EXIF.ExifMap();\n            // Parse the tags of the main image directory and retrieve the\n            // offset to the next directory, usually the thumbnail directory:\n            dirOffset = EXIF.parseExifTags( dataView, tiffOffset,\n                    tiffOffset + dirOffset, littleEndian, data );\n    \n            // 尝试读取缩略图\n            // if ( dirOffset ) {\n            //     thumbnailData = {exif: {}};\n            //     dirOffset = EXIF.parseExifTags(\n            //         dataView,\n            //         tiffOffset,\n            //         tiffOffset + dirOffset,\n            //         littleEndian,\n            //         thumbnailData\n            //     );\n    \n            //     // Check for JPEG Thumbnail offset:\n            //     if (thumbnailData.exif[0x0201]) {\n            //         data.exif.Thumbnail = EXIF.getExifThumbnail(\n            //             dataView,\n            //             tiffOffset + thumbnailData.exif[0x0201],\n            //             thumbnailData.exif[0x0202] // Thumbnail data length\n            //         );\n            //     }\n            // }\n        };\n    \n        ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData );\n        return EXIF;\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('runtime/html5/image',[\n        'base',\n        'runtime/html5/runtime',\n        'runtime/html5/util'\n    ], function( Base, Html5Runtime, Util ) {\n    \n        var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';\n    \n        return Html5Runtime.register( 'Image', {\n    \n            // flag: 标记是否被修改过。\n            modified: false,\n    \n            init: function() {\n                var me = this,\n                    img = new Image();\n    \n                img.onload = function() {\n    \n                    me._info = {\n                        type: me.type,\n                        width: this.width,\n                        height: this.height\n                    };\n    \n                    // 读取meta信息。\n                    if ( !me._metas && 'image/jpeg' === me.type ) {\n                        Util.parseMeta( me._blob, function( error, ret ) {\n                            me._metas = ret;\n                            me.owner.trigger('load');\n                        });\n                    } else {\n                        me.owner.trigger('load');\n                    }\n                };\n    \n                img.onerror = function() {\n                    me.owner.trigger('error');\n                };\n    \n                me._img = img;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    img = me._img;\n    \n                me._blob = blob;\n                me.type = blob.type;\n                img.src = Util.createObjectURL( blob.getSource() );\n                me.owner.once( 'load', function() {\n                    Util.revokeObjectURL( img.src );\n                });\n            },\n    \n            resize: function( width, height ) {\n                var canvas = this._canvas ||\n                        (this._canvas = document.createElement('canvas'));\n    \n                this._resize( this._img, canvas, width, height );\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'resize' );\n            },\n    \n            crop: function( x, y, w, h, s ) {\n                var cvs = this._canvas ||\n                        (this._canvas = document.createElement('canvas')),\n                    opts = this.options,\n                    img = this._img,\n                    iw = img.naturalWidth,\n                    ih = img.naturalHeight,\n                    orientation = this.getOrientation();\n    \n                s = s || 1;\n    \n                // todo 解决 orientation 的问题。\n                // values that require 90 degree rotation\n                // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n    \n                //     switch ( orientation ) {\n                //         case 6:\n                //             tmp = x;\n                //             x = y;\n                //             y = iw * s - tmp - w;\n                //             console.log(ih * s, tmp, w)\n                //             break;\n                //     }\n    \n                //     (w ^= h, h ^= w, w ^= h);\n                // }\n    \n                cvs.width = w;\n                cvs.height = h;\n    \n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n                this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s );\n    \n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'crop' );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this._blob,\n                    opts = this.options,\n                    canvas;\n    \n                type = type || this.type;\n    \n                // blob需要重新生成。\n                if ( this.modified || this.type !== type ) {\n                    canvas = this._canvas;\n    \n                    if ( type === 'image/jpeg' ) {\n    \n                        blob = Util.canvasToDataUrl( canvas, type, opts.quality );\n    \n                        if ( opts.preserveHeaders && this._metas &&\n                                this._metas.imageHead ) {\n    \n                            blob = Util.dataURL2ArrayBuffer( blob );\n                            blob = Util.updateImageHead( blob,\n                                    this._metas.imageHead );\n                            blob = Util.arrayBufferToBlob( blob, type );\n                            return blob;\n                        }\n                    } else {\n                        blob = Util.canvasToDataUrl( canvas, type );\n                    }\n    \n                    blob = Util.dataURL2Blob( blob );\n                }\n    \n                return blob;\n            },\n    \n            getAsDataUrl: function( type ) {\n                var opts = this.options;\n    \n                type = type || this.type;\n    \n                if ( type === 'image/jpeg' ) {\n                    return Util.canvasToDataUrl( this._canvas, type, opts.quality );\n                } else {\n                    return this._canvas.toDataURL( type );\n                }\n            },\n    \n            getOrientation: function() {\n                return this._metas && this._metas.exif &&\n                        this._metas.exif.get('Orientation') || 1;\n            },\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            destroy: function() {\n                var canvas = this._canvas;\n                this._img.onload = null;\n    \n                if ( canvas ) {\n                    canvas.getContext('2d')\n                            .clearRect( 0, 0, canvas.width, canvas.height );\n                    canvas.width = canvas.height = 0;\n                    this._canvas = null;\n                }\n    \n                // 释放内存。非常重要，否则释放不了image的内存。\n                this._img.src = BLANK;\n                this._img = this._blob = null;\n            },\n    \n            _resize: function( img, cvs, width, height ) {\n                var opts = this.options,\n                    naturalWidth = img.width,\n                    naturalHeight = img.height,\n                    orientation = this.getOrientation(),\n                    scale, w, h, x, y;\n    \n                // values that require 90 degree rotation\n                if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n    \n                    // 交换width, height的值。\n                    width ^= height;\n                    height ^= width;\n                    width ^= height;\n                }\n    \n                scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth,\n                        height / naturalHeight );\n    \n                // 不允许放大。\n                opts.allowMagnify || (scale = Math.min( 1, scale ));\n    \n                w = naturalWidth * scale;\n                h = naturalHeight * scale;\n    \n                if ( opts.crop ) {\n                    cvs.width = width;\n                    cvs.height = height;\n                } else {\n                    cvs.width = w;\n                    cvs.height = h;\n                }\n    \n                x = (cvs.width - w) / 2;\n                y = (cvs.height - h) / 2;\n    \n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n    \n                this._renderImageToCanvas( cvs, img, x, y, w, h );\n            },\n    \n            _rotate2Orientaion: function( canvas, orientation ) {\n                var width = canvas.width,\n                    height = canvas.height,\n                    ctx = canvas.getContext('2d');\n    \n                switch ( orientation ) {\n                    case 5:\n                    case 6:\n                    case 7:\n                    case 8:\n                        canvas.width = height;\n                        canvas.height = width;\n                        break;\n                }\n    \n                switch ( orientation ) {\n                    case 2:    // horizontal flip\n                        ctx.translate( width, 0 );\n                        ctx.scale( -1, 1 );\n                        break;\n    \n                    case 3:    // 180 rotate left\n                        ctx.translate( width, height );\n                        ctx.rotate( Math.PI );\n                        break;\n    \n                    case 4:    // vertical flip\n                        ctx.translate( 0, height );\n                        ctx.scale( 1, -1 );\n                        break;\n    \n                    case 5:    // vertical flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.scale( 1, -1 );\n                        break;\n    \n                    case 6:    // 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( 0, -height );\n                        break;\n    \n                    case 7:    // horizontal flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( width, -height );\n                        ctx.scale( -1, 1 );\n                        break;\n    \n                    case 8:    // 90 rotate left\n                        ctx.rotate( -0.5 * Math.PI );\n                        ctx.translate( -width, 0 );\n                        break;\n                }\n            },\n    \n            // https://github.com/stomita/ios-imagefile-megapixel/\n            // blob/master/src/megapix-image.js\n            _renderImageToCanvas: (function() {\n    \n                // 如果不是ios, 不需要这么复杂！\n                if ( !Base.os.ios ) {\n                    return function( canvas ) {\n                        var args = Base.slice( arguments, 1 ),\n                            ctx = canvas.getContext('2d');\n    \n                        ctx.drawImage.apply( ctx, args );\n                    };\n                }\n    \n                /**\n                 * Detecting vertical squash in loaded image.\n                 * Fixes a bug which squash image vertically while drawing into\n                 * canvas for some images.\n                 */\n                function detectVerticalSquash( img, iw, ih ) {\n                    var canvas = document.createElement('canvas'),\n                        ctx = canvas.getContext('2d'),\n                        sy = 0,\n                        ey = ih,\n                        py = ih,\n                        data, alpha, ratio;\n    \n    \n                    canvas.width = 1;\n                    canvas.height = ih;\n                    ctx.drawImage( img, 0, 0 );\n                    data = ctx.getImageData( 0, 0, 1, ih ).data;\n    \n                    // search image edge pixel position in case\n                    // it is squashed vertically.\n                    while ( py > sy ) {\n                        alpha = data[ (py - 1) * 4 + 3 ];\n    \n                        if ( alpha === 0 ) {\n                            ey = py;\n                        } else {\n                            sy = py;\n                        }\n    \n                        py = (ey + sy) >> 1;\n                    }\n    \n                    ratio = (py / ih);\n                    return (ratio === 0) ? 1 : ratio;\n                }\n    \n                // fix ie7 bug\n                // http://stackoverflow.com/questions/11929099/\n                // html5-canvas-drawimage-ratio-bug-ios\n                if ( Base.os.ios >= 7 ) {\n                    return function( canvas, img, x, y, w, h ) {\n                        var iw = img.naturalWidth,\n                            ih = img.naturalHeight,\n                            vertSquashRatio = detectVerticalSquash( img, iw, ih );\n    \n                        return canvas.getContext('2d').drawImage( img, 0, 0,\n                                iw * vertSquashRatio, ih * vertSquashRatio,\n                                x, y, w, h );\n                    };\n                }\n    \n                /**\n                 * Detect subsampling in loaded image.\n                 * In iOS, larger images than 2M pixels may be\n                 * subsampled in rendering.\n                 */\n                function detectSubsampling( img ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        canvas, ctx;\n    \n                    // subsampling may happen overmegapixel image\n                    if ( iw * ih > 1024 * 1024 ) {\n                        canvas = document.createElement('canvas');\n                        canvas.width = canvas.height = 1;\n                        ctx = canvas.getContext('2d');\n                        ctx.drawImage( img, -iw + 1, 0 );\n    \n                        // subsampled image becomes half smaller in rendering size.\n                        // check alpha channel value to confirm image is covering\n                        // edge pixel or not. if alpha value is 0\n                        // image is not covering, hence subsampled.\n                        return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0;\n                    } else {\n                        return false;\n                    }\n                }\n    \n    \n                return function( canvas, img, x, y, width, height ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        ctx = canvas.getContext('2d'),\n                        subsampled = detectSubsampling( img ),\n                        doSquash = this.type === 'image/jpeg',\n                        d = 1024,\n                        sy = 0,\n                        dy = 0,\n                        tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx;\n    \n                    if ( subsampled ) {\n                        iw /= 2;\n                        ih /= 2;\n                    }\n    \n                    ctx.save();\n                    tmpCanvas = document.createElement('canvas');\n                    tmpCanvas.width = tmpCanvas.height = d;\n    \n                    tmpCtx = tmpCanvas.getContext('2d');\n                    vertSquashRatio = doSquash ?\n                            detectVerticalSquash( img, iw, ih ) : 1;\n    \n                    dw = Math.ceil( d * width / iw );\n                    dh = Math.ceil( d * height / ih / vertSquashRatio );\n    \n                    while ( sy < ih ) {\n                        sx = 0;\n                        dx = 0;\n                        while ( sx < iw ) {\n                            tmpCtx.clearRect( 0, 0, d, d );\n                            tmpCtx.drawImage( img, -sx, -sy );\n                            ctx.drawImage( tmpCanvas, 0, 0, d, d,\n                                    x + dx, y + dy, dw, dh );\n                            sx += d;\n                            dx += dw;\n                        }\n                        sy += d;\n                        dy += dh;\n                    }\n                    ctx.restore();\n                    tmpCanvas = tmpCtx = null;\n                };\n            })()\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var noop = Base.noop,\n            $ = Base.$;\n    \n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n    \n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n    \n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n    \n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n    \n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n    \n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n    \n            getResponse: function() {\n                return this._response;\n            },\n    \n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n    \n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n    \n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n    \n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n    \n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n    \n                    return me.trigger( 'progress', percentage );\n                };\n    \n                xhr.onreadystatechange = function() {\n    \n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n    \n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n    \n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n    \n    \n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n    \n            _parseJson: function( str ) {\n                var json;\n    \n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n    \n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview 只有html5实现的文件版本。\n     */\n    define('preset/html5only',[\n        'base',\n    \n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n    \n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/imagemeta/exif',\n        'runtime/html5/image',\n        'runtime/html5/transport'\n    ], function( Base ) {\n        return Base;\n    });\n    define('webuploader',[\n        'preset/html5only'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/webuploader.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n    \n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n    \n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n    \n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n    \n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n    \n        var noop = function() {},\n            call = Function.call;\n    \n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n    \n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n    \n        function createObject( proto ) {\n            var f;\n    \n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n    \n    \n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n    \n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n    \n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n    \n            Deferred: promise.Deferred,\n    \n            isPromise: promise.isPromise,\n    \n            when: promise.when,\n    \n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n    \n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n    \n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n    \n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n    \n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n    \n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n    \n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n    \n                /* jshint camelcase: false */\n    \n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n    \n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n    \n                return child;\n            },\n    \n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n    \n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n    \n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n    \n            nextTick: (function() {\n    \n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n    \n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n    \n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n    \n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n    \n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n    \n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n    \n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n    \n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n    \n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n    \n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n    \n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n    \n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n    \n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n    \n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n    \n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n    \n            while ( ++i < len ) {\n                handler = events[ i ];\n    \n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n    \n            return !stoped;\n        }\n    \n        protos = {\n    \n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n    \n                if ( !callback ) {\n                    return this;\n                }\n    \n                set = this._events || (this._events = []);\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n    \n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n    \n                    set.push( handler );\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n    \n                if ( !callback ) {\n                    return me;\n                }\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n    \n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n    \n                return me;\n            },\n    \n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n    \n                if ( !events ) {\n                    return this;\n                }\n    \n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n    \n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n    \n                if ( !this._events || !type ) {\n                    return this;\n                }\n    \n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n    \n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n    \n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n    \n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n    \n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$;\n    \n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n    \n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n    \n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n    \n        $.extend( Uploader.prototype, {\n            state: 'pending',\n    \n            _init: function( opts ) {\n                var me = this;\n    \n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n    \n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n    \n                // setter\n                if ( arguments.length > 1 ) {\n    \n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n    \n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n    \n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n    \n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n    \n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n    \n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n    \n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n    \n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n    \n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n    \n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n    \n                    return false;\n                }\n    \n                return true;\n            },\n    \n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n    \n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n    \n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n    \n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n    \n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            factories = {},\n    \n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n    \n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n    \n        $.extend( Runtime.prototype, {\n    \n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n    \n                if ( this._container ) {\n                    return this._container;\n                }\n    \n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n    \n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n    \n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n    \n            init: Base.noop,\n            exec: Base.noop,\n    \n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n    \n        Runtime.orders = 'html5,flash';\n    \n    \n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n    \n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n    \n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n    \n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n    \n            type = type || getFirstKey( factories );\n    \n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n    \n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n    \n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n    \n        var cache;\n    \n        cache = (function() {\n            var obj = {};\n    \n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n    \n                get: function( ruid, standalone ) {\n                    var i;\n    \n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n    \n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n    \n                        return obj[ i ];\n                    }\n    \n                    return null;\n                },\n    \n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n    \n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n    \n            this.uid = Base.guid('client_');\n    \n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n    \n            this.connectRuntime = function( opts, cb ) {\n    \n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n    \n                deferred.done( cb );\n    \n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n    \n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n    \n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n    \n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                runtime.__client--;\n    \n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n    \n                runtime = null;\n            };\n    \n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n    \n                return runtime.exec.apply( this, args );\n            };\n    \n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n    \n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n    \n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n    \n            opts.container = $( opts.container );\n    \n            if ( !opts.container.length ) {\n                return;\n            }\n    \n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n    \n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( DragAndDrop.prototype );\n    \n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n    \n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n    \n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n    \n            var length = obj.length,\n                type = $.type( obj );\n    \n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n    \n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n    \n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n    \n        $.extend( Widget.prototype, {\n    \n            init: Base.noop,\n    \n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n    \n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n    \n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n    \n                    return IGNORE;\n                }\n    \n                return this[ map[ apiName ] ].apply( this, args );\n    \n            },\n    \n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n    \n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n    \n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n    \n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n    \n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n    \n                return _init.apply( me, arguments );\n            },\n    \n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n    \n                args = isArrayLike( args ) ? args : [ args ];\n    \n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n    \n                    if ( rlt !== IGNORE ) {\n    \n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n    \n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n    \n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n    \n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n    \n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n    \n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n    \n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n    \n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n    \n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n    \n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n    \n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n    \n            } else {\n                map = $.extend( map, responseMap );\n            }\n    \n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n    \n            return klass;\n        };\n    \n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *     \n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n            \n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n    \n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n    \n        Uploader.options.dnd = '';\n    \n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n        \n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n    \n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n            \n            init: function( opts ) {\n    \n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n    \n                this.dnd = dnd = new Dnd( options );\n    \n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n    \n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n    \n                dnd.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( FilePaste.prototype );\n    \n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n    \n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n            \n            init: function( opts ) {\n    \n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n    \n                this.paste = paste = new FilePaste( options );\n    \n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n    \n        function Blob( ruid, source ) {\n            var me = this;\n    \n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n    \n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n    \n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n    \n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n    \n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n    \n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n    \n            getSource: function() {\n                return this.source;\n            }\n        });\n    \n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n    \n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n    \n        function File( ruid, file ) {\n            var ext;\n    \n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n    \n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n    \n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n    \n            Blob.apply( this, arguments );\n        }\n    \n        return Base.inherits( Blob, File );\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n    \n        var $ = Base.$;\n    \n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n    \n            opts.container = $( opts.id );\n    \n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n    \n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n    \n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n    \n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n    \n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n    \n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n    \n                button.addClass('webuploader-pick');\n    \n                me.on( 'all', function( type ) {\n                    var files;\n    \n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n    \n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n    \n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n    \n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n    \n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n    \n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n    \n                    pos = button.offset();\n    \n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n    \n            enable: function() {\n                var btn = this.options.button;\n    \n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n    \n            disable: function() {\n                var btn = this.options.button;\n    \n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n    \n                btn.addClass('webuploader-pick-disable');\n            },\n    \n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n    \n        return FilePicker;\n    });\n    \n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n    \n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n    \n        return Uploader.register({\n            name: 'picker',\n    \n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n    \n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n    \n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n    \n                if ( !pick ) {\n                    return;\n                }\n    \n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n    \n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n    \n                    deferred = Base.Deferred();\n    \n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n    \n                    picker = new FilePicker( options );\n    \n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n    \n                    me.pickers.push( picker );\n    \n                    promises.push( deferred.promise() );\n                });\n    \n                return Base.when.apply( Base, promises );\n            },\n    \n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n    \n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n    \n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n    \n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n    \n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n    \n        // 默认选项。\n        Image.options = {\n    \n            // 默认的图片处理质量\n            quality: 90,\n    \n            // 是否裁剪\n            crop: false,\n    \n            // 是否保留头部信息\n            preserveHeaders: false,\n    \n            // 是否允许放大。\n            allowMagnify: false\n        };\n    \n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n    \n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n    \n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n    \n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n    \n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    \n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n    \n        var $ = Base.$,\n            throttle;\n    \n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n    \n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n    \n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n    \n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n    \n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n    \n        return Uploader.register({\n    \n            name: 'image',\n    \n    \n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n    \n                opts = $.extend({}, this.options.thumb );\n    \n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n    \n                width = width || opts.width;\n                height = height || opts.height;\n    \n                image = new Image( opts );\n    \n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n    \n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n    \n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n    \n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n    \n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n    \n                image = new Image( opts );\n    \n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n    \n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                image.once( 'complete', function() {\n                    var blob, size;\n    \n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n    \n                        size = file.size;\n    \n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n    \n                            file.trigger( 'resize', blob.size, size );\n                        }\n    \n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n    \n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n    \n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n    \n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n    \n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n    \n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n    \n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n    \n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n    \n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n    \n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n    \n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n    \n    \n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n    \n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n    \n            this.source = source;\n            this.loaded = 0;\n    \n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n    \n        $.extend( WUFile.prototype, {\n    \n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n    \n                var prevStatus = statusMap[ this.id ];\n    \n                typeof text !== 'undefined' && (this.statusText = text);\n    \n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n    \n            },\n    \n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n    \n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n    \n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n    \n        Mediator.installTo( WUFile.prototype );\n    \n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n    \n        return WUFile;\n    });\n    \n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n    \n        var $ = Base.$,\n            STATUS = WUFile.Status;\n    \n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n    \n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n    \n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n    \n            // 存储所有文件\n            this._map = {};\n        }\n    \n        $.extend( Queue.prototype, {\n    \n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n    \n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n    \n                status = status || STATUS.QUEUED;\n    \n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n    \n                return null;\n            },\n    \n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n    \n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n    \n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n    \n                    ret.push( file );\n                }\n    \n                return ret;\n            },\n    \n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n    \n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n    \n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n    \n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n    \n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n    \n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n    \n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n    \n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n    \n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n    \n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n    \n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n    \n        });\n    \n        Mediator.installTo( Queue.prototype );\n    \n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n    \n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n    \n        return Uploader.register({\n            name: 'queue',\n    \n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n    \n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n    \n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n    \n                    me.accept = new RegExp( accept, 'i' );\n                }\n    \n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n    \n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n    \n    \n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n    \n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n    \n                    file = new WUFile( file );\n                }\n    \n                return file;\n            },\n    \n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n    \n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n    \n                return !invalid;\n            },\n    \n    \n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n    \n            _addFile: function( file ) {\n                var me = this;\n    \n                file = me._wrapFile( file );\n    \n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n    \n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n    \n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n    \n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n    \n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n            \n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             * \n             */\n    \n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n    \n                if ( !files.length ) {\n                    files = [ files ];\n                }\n    \n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n    \n                me.owner.trigger( 'filesQueued', files );\n    \n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n    \n            getStats: function() {\n                return this.stats;\n            },\n    \n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n    \n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n    \n                file = file.id ? file : me.queue.getFile( file );\n    \n                this.request( 'cancel-file', file );\n    \n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n    \n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n    \n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n    \n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n    \n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n    \n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n    \n                me.request('start-upload');\n            },\n    \n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n    \n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n    \n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n    \n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n    \n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n    \n        return Uploader.register({\n            name: 'runtime',\n    \n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n    \n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n    \n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n    \n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n    \n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n    \n        var $ = Base.$;\n    \n        function Transport( opts ) {\n            var me = this;\n    \n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n    \n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n    \n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n    \n        Transport.options = {\n            server: '',\n            method: 'POST',\n    \n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n    \n        $.extend( Transport.prototype, {\n    \n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n    \n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n    \n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n    \n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n    \n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n    \n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n    \n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n    \n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n    \n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n    \n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n    \n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n    \n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n    \n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n    \n                if ( !duration ) {\n                    return;\n                }\n    \n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n    \n        });\n    \n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n    \n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n    \n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n    \n        // 添加默认配置项\n        $.extend( Uploader.options, {\n    \n    \n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n    \n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n    \n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n    \n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n    \n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n    \n    \n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n    \n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n    \n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n    \n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n    \n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n    \n            api = {\n                file: file,\n    \n                has: function() {\n                    return !!pending.length;\n                },\n    \n                shift: function() {\n                    return pending.shift();\n                },\n    \n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n    \n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n    \n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n    \n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n    \n            return api;\n        }\n    \n        Uploader.register({\n            name: 'upload',\n    \n            init: function() {\n                var owner = this.owner,\n                    me = this;\n    \n                this.runing = false;\n                this.progress = false;\n    \n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n    \n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n    \n                // 缓存分好片的文件。\n                this.stack = [];\n    \n                // 缓存即将上传的文件。\n                this.pending = [];\n    \n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n    \n                owner.on( 'uploadComplete', function( file ) {\n    \n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n    \n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n    \n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n    \n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n    \n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n    \n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n    \n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n    \n                            v.transport && v.transport.send();\n                        });\n    \n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n    \n                if ( me.runing ) {\n                    return;\n                }\n    \n                me.runing = true;\n    \n                var files = [];\n    \n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n    \n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n    \n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n    \n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n    \n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n    \n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n    \n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n    \n                if ( me.runing === false ) {\n                    return;\n                }\n    \n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n    \n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n    \n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n    \n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n    \n                    return Base.nextTick( me.__tick );\n                }\n    \n                me.runing = false;\n    \n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n    \n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n    \n                me.owner.trigger('stopUpload');\n            },\n    \n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n    \n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n    \n            _getStats: function() {\n                return this.request('get-stats');\n            },\n    \n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                this.owner.trigger( 'uploadSkip', file );\n            },\n    \n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n    \n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n    \n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n    \n                    fn = function( val ) {\n                        me._promise = null;\n    \n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n    \n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n    \n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n    \n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n    \n            _putback: function(block) {\n                var idx;\n    \n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n    \n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n    \n            _getStack: function() {\n                var i = 0,\n                    act;\n    \n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n    \n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n    \n                return null;\n            },\n    \n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n    \n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n    \n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n    \n                    return act.shift();\n    \n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n    \n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n    \n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n    \n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n    \n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n    \n                    return done( next );\n                }\n            },\n    \n    \n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n    \n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n    \n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n    \n                        return me._finishFile( file );\n                    });\n    \n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n    \n                    promise.file = file;\n    \n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n    \n                        ~idx && pending.splice( idx, 1, file );\n                    });\n    \n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n    \n                    pending.push( promise );\n                }\n            },\n    \n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n    \n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n    \n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n    \n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n    \n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n    \n                    return;\n                }\n    \n                me.pool.push( block );\n                me.remaning++;\n    \n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n    \n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n    \n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n    \n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n    \n    \n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n    \n    \n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n    \n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n    \n                block.transport = tr;\n    \n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n    \n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n    \n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n    \n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n    \n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n    \n                    return reject;\n                };\n    \n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n    \n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n    \n                        block.retried++;\n                        tr.send();\n    \n                    } else {\n    \n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n    \n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n    \n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n    \n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n    \n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n    \n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n    \n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n    \n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n    \n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n    \n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n    \n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n    \n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n    \n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n    \n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n    \n                if (!file.blocks) {\n                    return;\n                }\n    \n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n    \n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n    \n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n    \n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n    \n        var $ = Base.$,\n            validators = {},\n            api;\n    \n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n    \n        // 暴露给外面的api\n        api = {\n    \n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n    \n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n    \n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n    \n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n    \n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return count >= max ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n    \n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n    \n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n    \n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return invalid ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n    \n            });\n    \n        });\n    \n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n    \n            if ( opts.duplicate ) {\n                return;\n            }\n    \n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n    \n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n    \n                return hash;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n    \n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', '文件已选择，请勿重复选中', file );\n                    return false;\n                }\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (mapping[ hash ] = true);\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (delete mapping[ hash ]);\n            });\n    \n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n    \n        return api;\n    });\n    \n    /**\n     * @fileOverview Md5\n     */\n    define('lib/md5',[\n        'runtime/client',\n        'mediator'\n    ], function( RuntimeClient, Mediator ) {\n    \n        function Md5() {\n            RuntimeClient.call( this, 'Md5' );\n        }\n    \n        // 让 Md5 具备事件功能。\n        Mediator.installTo( Md5.prototype );\n    \n        Md5.prototype.loadFromBlob = function( blob ) {\n            var me = this;\n    \n            if ( me.getRuid() ) {\n                me.disconnectRuntime();\n            }\n    \n            // 连接到blob归属的同一个runtime.\n            me.connectRuntime( blob.ruid, function() {\n                me.exec('init');\n                me.exec( 'loadFromBlob', blob );\n            });\n        };\n    \n        Md5.prototype.getResult = function() {\n            return this.exec('getResult');\n        };\n    \n        return Md5;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/md5',[\n        'base',\n        'uploader',\n        'lib/md5',\n        'lib/blob',\n        'widgets/widget'\n    ], function( Base, Uploader, Md5, Blob ) {\n    \n        return Uploader.register({\n            name: 'md5',\n    \n    \n            /**\n             * 计算文件 md5 值，返回一个 promise 对象，可以监听 progress 进度。\n             *\n             *\n             * @method md5File\n             * @grammar md5File( file[, start[, end]] ) => promise\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.md5File( file )\n             *\n             *         // 及时显示进度\n             *         .progress(function(percentage) {\n             *             console.log('Percentage:', percentage);\n             *         })\n             *\n             *         // 完成\n             *         .then(function(val) {\n             *             console.log('md5 result:', val);\n             *         });\n             *\n             * });\n             */\n            md5File: function( file, start, end ) {\n                var md5 = new Md5(),\n                    deferred = Base.Deferred(),\n                    blob = (file instanceof Blob) ? file :\n                        this.request( 'get-file', file ).source;\n    \n                md5.on( 'progress load', function( e ) {\n                    e = e || {};\n                    deferred.notify( e.total ? e.loaded / e.total : 1 );\n                });\n    \n                md5.on( 'complete', function() {\n                    deferred.resolve( md5.getResult() );\n                });\n    \n                md5.on( 'error', function( reason ) {\n                    deferred.reject( reason );\n                });\n    \n                if ( arguments.length > 1 ) {\n                    start = start || 0;\n                    end = end || 0;\n                    start < 0 && (start = blob.size + start);\n                    end < 0 && (end = blob.size + end);\n                    end = Math.min( end, blob.size );\n                    blob = blob.slice( start, end );\n                }\n    \n                md5.loadFromBlob( blob );\n    \n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n    \n        function CompBase( owner, runtime ) {\n    \n            this.owner = owner;\n            this.options = owner.options;\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.getRuid = function() {\n                return runtime.uid;\n            };\n    \n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n    \n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var type = 'html5',\n            components = {};\n    \n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n    \n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n    \n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n    \n        });\n    \n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n    \n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n    \n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n    \n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n    \n                blob = slice.call( blob, start, end );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n    \n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n    \n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n    \n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n    \n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n    \n                e = e.originalEvent || e;\n    \n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n    \n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n    \n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n    \n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n    \n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n    \n                return false;\n            },\n    \n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n    \n                return false;\n            },\n    \n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n    \n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n    \n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n    \n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n    \n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n    \n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n    \n                if ( data ) {\n                    return;\n                }\n    \n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n    \n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n    \n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n    \n                items = dataTransfer.items;\n                files = dataTransfer.files;\n    \n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n    \n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n    \n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n    \n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n    \n                Base.when.apply( Base, promises ).done(function() {\n    \n                    if ( !results.length ) {\n                        return;\n                    }\n    \n                    callback( results );\n                });\n            },\n    \n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n    \n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n    \n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n    \n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                var elem = this.elem;\n    \n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n                \n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n    \n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n    \n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n    \n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n    \n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n    \n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n    \n                    allowed.push( new File( ruid, blob ) );\n                }\n    \n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n    \n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var $ = Base.$;\n    \n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n    \n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n    \n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n    \n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n    \n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n    \n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n    \n                    input.attr( 'accept', arr.join(',') );\n                }\n    \n                container.append( input );\n                container.append( label );\n    \n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n    \n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n    \n                    me.files = e.target.files;\n    \n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n    \n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n    \n                    owner.trigger('change');\n                });\n    \n                label.on( 'mouseenter mouseleave', mouseHandler );\n    \n            },\n    \n    \n            getFiles: function() {\n                return this.files;\n            },\n    \n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/util',[\n        'base'\n    ], function( Base ) {\n    \n        var urlAPI = window.createObjectURL && window ||\n                window.URL && URL.revokeObjectURL && URL ||\n                window.webkitURL,\n            createObjectURL = Base.noop,\n            revokeObjectURL = createObjectURL;\n    \n        if ( urlAPI ) {\n    \n            // 更安全的方式调用，比如android里面就能把context改成其他的对象。\n            createObjectURL = function() {\n                return urlAPI.createObjectURL.apply( urlAPI, arguments );\n            };\n    \n            revokeObjectURL = function() {\n                return urlAPI.revokeObjectURL.apply( urlAPI, arguments );\n            };\n        }\n    \n        return {\n            createObjectURL: createObjectURL,\n            revokeObjectURL: revokeObjectURL,\n    \n            dataURL2Blob: function( dataURI ) {\n                var byteStr, intArray, ab, i, mimetype, parts;\n    \n                parts = dataURI.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                ab = new ArrayBuffer( byteStr.length );\n                intArray = new Uint8Array( ab );\n    \n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n    \n                mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ];\n    \n                return this.arrayBufferToBlob( ab, mimetype );\n            },\n    \n            dataURL2ArrayBuffer: function( dataURI ) {\n                var byteStr, intArray, i, parts;\n    \n                parts = dataURI.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                intArray = new Uint8Array( byteStr.length );\n    \n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n    \n                return intArray.buffer;\n            },\n    \n            arrayBufferToBlob: function( buffer, type ) {\n                var builder = window.BlobBuilder || window.WebKitBlobBuilder,\n                    bb;\n    \n                // android不支持直接new Blob, 只能借助blobbuilder.\n                if ( builder ) {\n                    bb = new builder();\n                    bb.append( buffer );\n                    return bb.getBlob( type );\n                }\n    \n                return new Blob([ buffer ], type ? { type: type } : {} );\n            },\n    \n            // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg.\n            // 你得到的结果是png.\n            canvasToDataUrl: function( canvas, type, quality ) {\n                return canvas.toDataURL( type, quality / 100 );\n            },\n    \n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            parseMeta: function( blob, callback ) {\n                callback( false, {});\n            },\n    \n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            updateImageHead: function( data ) {\n                return data;\n            }\n        };\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/imagemeta',[\n        'runtime/html5/util'\n    ], function( Util ) {\n    \n        var api;\n    \n        api = {\n            parsers: {\n                0xffe1: []\n            },\n    \n            maxMetaDataSize: 262144,\n    \n            parse: function( blob, cb ) {\n                var me = this,\n                    fr = new FileReader();\n    \n                fr.onload = function() {\n                    cb( false, me._parse( this.result ) );\n                    fr = fr.onload = fr.onerror = null;\n                };\n    \n                fr.onerror = function( e ) {\n                    cb( e.message );\n                    fr = fr.onload = fr.onerror = null;\n                };\n    \n                blob = blob.slice( 0, me.maxMetaDataSize );\n                fr.readAsArrayBuffer( blob.getSource() );\n            },\n    \n            _parse: function( buffer, noParse ) {\n                if ( buffer.byteLength < 6 ) {\n                    return;\n                }\n    \n                var dataview = new DataView( buffer ),\n                    offset = 2,\n                    maxOffset = dataview.byteLength - 4,\n                    headLength = offset,\n                    ret = {},\n                    markerBytes, markerLength, parsers, i;\n    \n                if ( dataview.getUint16( 0 ) === 0xffd8 ) {\n    \n                    while ( offset < maxOffset ) {\n                        markerBytes = dataview.getUint16( offset );\n    \n                        if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef ||\n                                markerBytes === 0xfffe ) {\n    \n                            markerLength = dataview.getUint16( offset + 2 ) + 2;\n    \n                            if ( offset + markerLength > dataview.byteLength ) {\n                                break;\n                            }\n    \n                            parsers = api.parsers[ markerBytes ];\n    \n                            if ( !noParse && parsers ) {\n                                for ( i = 0; i < parsers.length; i += 1 ) {\n                                    parsers[ i ].call( api, dataview, offset,\n                                            markerLength, ret );\n                                }\n                            }\n    \n                            offset += markerLength;\n                            headLength = offset;\n                        } else {\n                            break;\n                        }\n                    }\n    \n                    if ( headLength > 6 ) {\n                        if ( buffer.slice ) {\n                            ret.imageHead = buffer.slice( 2, headLength );\n                        } else {\n                            // Workaround for IE10, which does not yet\n                            // support ArrayBuffer.slice:\n                            ret.imageHead = new Uint8Array( buffer )\n                                    .subarray( 2, headLength );\n                        }\n                    }\n                }\n    \n                return ret;\n            },\n    \n            updateImageHead: function( buffer, head ) {\n                var data = this._parse( buffer, true ),\n                    buf1, buf2, bodyoffset;\n    \n    \n                bodyoffset = 2;\n                if ( data.imageHead ) {\n                    bodyoffset = 2 + data.imageHead.byteLength;\n                }\n    \n                if ( buffer.slice ) {\n                    buf2 = buffer.slice( bodyoffset );\n                } else {\n                    buf2 = new Uint8Array( buffer ).subarray( bodyoffset );\n                }\n    \n                buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength );\n    \n                buf1[ 0 ] = 0xFF;\n                buf1[ 1 ] = 0xD8;\n                buf1.set( new Uint8Array( head ), 2 );\n                buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 );\n    \n                return buf1.buffer;\n            }\n        };\n    \n        Util.parseMeta = function() {\n            return api.parse.apply( api, arguments );\n        };\n    \n        Util.updateImageHead = function() {\n            return api.updateImageHead.apply( api, arguments );\n        };\n    \n        return api;\n    });\n    /**\n     * 代码来自于：https://github.com/blueimp/JavaScript-Load-Image\n     * 暂时项目中只用了orientation.\n     *\n     * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail.\n     * @fileOverview EXIF解析\n     */\n    \n    // Sample\n    // ====================================\n    // Make : Apple\n    // Model : iPhone 4S\n    // Orientation : 1\n    // XResolution : 72 [72/1]\n    // YResolution : 72 [72/1]\n    // ResolutionUnit : 2\n    // Software : QuickTime 7.7.1\n    // DateTime : 2013:09:01 22:53:55\n    // ExifIFDPointer : 190\n    // ExposureTime : 0.058823529411764705 [1/17]\n    // FNumber : 2.4 [12/5]\n    // ExposureProgram : Normal program\n    // ISOSpeedRatings : 800\n    // ExifVersion : 0220\n    // DateTimeOriginal : 2013:09:01 22:52:51\n    // DateTimeDigitized : 2013:09:01 22:52:51\n    // ComponentsConfiguration : YCbCr\n    // ShutterSpeedValue : 4.058893515764426\n    // ApertureValue : 2.5260688216892597 [4845/1918]\n    // BrightnessValue : -0.3126686601998395\n    // MeteringMode : Pattern\n    // Flash : Flash did not fire, compulsory flash mode\n    // FocalLength : 4.28 [107/25]\n    // SubjectArea : [4 values]\n    // FlashpixVersion : 0100\n    // ColorSpace : 1\n    // PixelXDimension : 2448\n    // PixelYDimension : 3264\n    // SensingMethod : One-chip color area sensor\n    // ExposureMode : 0\n    // WhiteBalance : Auto white balance\n    // FocalLengthIn35mmFilm : 35\n    // SceneCaptureType : Standard\n    define('runtime/html5/imagemeta/exif',[\n        'base',\n        'runtime/html5/imagemeta'\n    ], function( Base, ImageMeta ) {\n    \n        var EXIF = {};\n    \n        EXIF.ExifMap = function() {\n            return this;\n        };\n    \n        EXIF.ExifMap.prototype.map = {\n            'Orientation': 0x0112\n        };\n    \n        EXIF.ExifMap.prototype.get = function( id ) {\n            return this[ id ] || this[ this.map[ id ] ];\n        };\n    \n        EXIF.exifTagTypes = {\n            // byte, 8-bit unsigned int:\n            1: {\n                getValue: function( dataView, dataOffset ) {\n                    return dataView.getUint8( dataOffset );\n                },\n                size: 1\n            },\n    \n            // ascii, 8-bit byte:\n            2: {\n                getValue: function( dataView, dataOffset ) {\n                    return String.fromCharCode( dataView.getUint8( dataOffset ) );\n                },\n                size: 1,\n                ascii: true\n            },\n    \n            // short, 16 bit int:\n            3: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint16( dataOffset, littleEndian );\n                },\n                size: 2\n            },\n    \n            // long, 32 bit int:\n            4: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n    \n            // rational = two long values,\n            // first is numerator, second is denominator:\n            5: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian ) /\n                        dataView.getUint32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            },\n    \n            // slong, 32 bit signed int:\n            9: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n    \n            // srational, two slongs, first is numerator, second is denominator:\n            10: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian ) /\n                        dataView.getInt32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            }\n        };\n    \n        // undefined, 8-bit byte, value depending on field:\n        EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ];\n    \n        EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length,\n                littleEndian ) {\n    \n            var tagType = EXIF.exifTagTypes[ type ],\n                tagSize, dataOffset, values, i, str, c;\n    \n            if ( !tagType ) {\n                Base.log('Invalid Exif data: Invalid tag type.');\n                return;\n            }\n    \n            tagSize = tagType.size * length;\n    \n            // Determine if the value is contained in the dataOffset bytes,\n            // or if the value at the dataOffset is a pointer to the actual data:\n            dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8,\n                    littleEndian ) : (offset + 8);\n    \n            if ( dataOffset + tagSize > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid data offset.');\n                return;\n            }\n    \n            if ( length === 1 ) {\n                return tagType.getValue( dataView, dataOffset, littleEndian );\n            }\n    \n            values = [];\n    \n            for ( i = 0; i < length; i += 1 ) {\n                values[ i ] = tagType.getValue( dataView,\n                        dataOffset + i * tagType.size, littleEndian );\n            }\n    \n            if ( tagType.ascii ) {\n                str = '';\n    \n                // Concatenate the chars:\n                for ( i = 0; i < values.length; i += 1 ) {\n                    c = values[ i ];\n    \n                    // Ignore the terminating NULL byte(s):\n                    if ( c === '\\u0000' ) {\n                        break;\n                    }\n                    str += c;\n                }\n    \n                return str;\n            }\n            return values;\n        };\n    \n        EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian,\n                data ) {\n    \n            var tag = dataView.getUint16( offset, littleEndian );\n            data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset,\n                    dataView.getUint16( offset + 2, littleEndian ),    // tag type\n                    dataView.getUint32( offset + 4, littleEndian ),    // tag length\n                    littleEndian );\n        };\n    \n        EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset,\n                littleEndian, data ) {\n    \n            var tagsNumber, dirEndOffset, i;\n    \n            if ( dirOffset + 6 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory offset.');\n                return;\n            }\n    \n            tagsNumber = dataView.getUint16( dirOffset, littleEndian );\n            dirEndOffset = dirOffset + 2 + 12 * tagsNumber;\n    \n            if ( dirEndOffset + 4 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory size.');\n                return;\n            }\n    \n            for ( i = 0; i < tagsNumber; i += 1 ) {\n                this.parseExifTag( dataView, tiffOffset,\n                        dirOffset + 2 + 12 * i,    // tag offset\n                        littleEndian, data );\n            }\n    \n            // Return the offset to the next directory:\n            return dataView.getUint32( dirEndOffset, littleEndian );\n        };\n    \n        // EXIF.getExifThumbnail = function(dataView, offset, length) {\n        //     var hexData,\n        //         i,\n        //         b;\n        //     if (!length || offset + length > dataView.byteLength) {\n        //         Base.log('Invalid Exif data: Invalid thumbnail data.');\n        //         return;\n        //     }\n        //     hexData = [];\n        //     for (i = 0; i < length; i += 1) {\n        //         b = dataView.getUint8(offset + i);\n        //         hexData.push((b < 16 ? '0' : '') + b.toString(16));\n        //     }\n        //     return 'data:image/jpeg,%' + hexData.join('%');\n        // };\n    \n        EXIF.parseExifData = function( dataView, offset, length, data ) {\n    \n            var tiffOffset = offset + 10,\n                littleEndian, dirOffset;\n    \n            // Check for the ASCII code for \"Exif\" (0x45786966):\n            if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) {\n                // No Exif data, might be XMP data instead\n                return;\n            }\n            if ( tiffOffset + 8 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid segment size.');\n                return;\n            }\n    \n            // Check for the two null bytes:\n            if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) {\n                Base.log('Invalid Exif data: Missing byte alignment offset.');\n                return;\n            }\n    \n            // Check the byte alignment:\n            switch ( dataView.getUint16( tiffOffset ) ) {\n                case 0x4949:\n                    littleEndian = true;\n                    break;\n    \n                case 0x4D4D:\n                    littleEndian = false;\n                    break;\n    \n                default:\n                    Base.log('Invalid Exif data: Invalid byte alignment marker.');\n                    return;\n            }\n    \n            // Check for the TIFF tag marker (0x002A):\n            if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) {\n                Base.log('Invalid Exif data: Missing TIFF marker.');\n                return;\n            }\n    \n            // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:\n            dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian );\n            // Create the exif object to store the tags:\n            data.exif = new EXIF.ExifMap();\n            // Parse the tags of the main image directory and retrieve the\n            // offset to the next directory, usually the thumbnail directory:\n            dirOffset = EXIF.parseExifTags( dataView, tiffOffset,\n                    tiffOffset + dirOffset, littleEndian, data );\n    \n            // 尝试读取缩略图\n            // if ( dirOffset ) {\n            //     thumbnailData = {exif: {}};\n            //     dirOffset = EXIF.parseExifTags(\n            //         dataView,\n            //         tiffOffset,\n            //         tiffOffset + dirOffset,\n            //         littleEndian,\n            //         thumbnailData\n            //     );\n    \n            //     // Check for JPEG Thumbnail offset:\n            //     if (thumbnailData.exif[0x0201]) {\n            //         data.exif.Thumbnail = EXIF.getExifThumbnail(\n            //             dataView,\n            //             tiffOffset + thumbnailData.exif[0x0201],\n            //             thumbnailData.exif[0x0202] // Thumbnail data length\n            //         );\n            //     }\n            // }\n        };\n    \n        ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData );\n        return EXIF;\n    });\n    /**\n     * 这个方式性能不行，但是可以解决android里面的toDataUrl的bug\n     * android里面toDataUrl('image/jpege')得到的结果却是png.\n     *\n     * 所以这里没辙，只能借助这个工具\n     * @fileOverview jpeg encoder\n     */\n    define('runtime/html5/jpegencoder',[], function( require, exports, module ) {\n    \n        /*\n          Copyright (c) 2008, Adobe Systems Incorporated\n          All rights reserved.\n    \n          Redistribution and use in source and binary forms, with or without\n          modification, are permitted provided that the following conditions are\n          met:\n    \n          * Redistributions of source code must retain the above copyright notice,\n            this list of conditions and the following disclaimer.\n    \n          * Redistributions in binary form must reproduce the above copyright\n            notice, this list of conditions and the following disclaimer in the\n            documentation and/or other materials provided with the distribution.\n    \n          * Neither the name of Adobe Systems Incorporated nor the names of its\n            contributors may be used to endorse or promote products derived from\n            this software without specific prior written permission.\n    \n          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n          IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n          THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n          PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n          CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n          EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n          PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n          PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n          LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n          NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n        */\n        /*\n        JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009\n    \n        Basic GUI blocking jpeg encoder\n        */\n    \n        function JPEGEncoder(quality) {\n          var self = this;\n            var fround = Math.round;\n            var ffloor = Math.floor;\n            var YTable = new Array(64);\n            var UVTable = new Array(64);\n            var fdtbl_Y = new Array(64);\n            var fdtbl_UV = new Array(64);\n            var YDC_HT;\n            var UVDC_HT;\n            var YAC_HT;\n            var UVAC_HT;\n    \n            var bitcode = new Array(65535);\n            var category = new Array(65535);\n            var outputfDCTQuant = new Array(64);\n            var DU = new Array(64);\n            var byteout = [];\n            var bytenew = 0;\n            var bytepos = 7;\n    \n            var YDU = new Array(64);\n            var UDU = new Array(64);\n            var VDU = new Array(64);\n            var clt = new Array(256);\n            var RGB_YUV_TABLE = new Array(2048);\n            var currentQuality;\n    \n            var ZigZag = [\n                     0, 1, 5, 6,14,15,27,28,\n                     2, 4, 7,13,16,26,29,42,\n                     3, 8,12,17,25,30,41,43,\n                     9,11,18,24,31,40,44,53,\n                    10,19,23,32,39,45,52,54,\n                    20,22,33,38,46,51,55,60,\n                    21,34,37,47,50,56,59,61,\n                    35,36,48,49,57,58,62,63\n                ];\n    \n            var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];\n            var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];\n            var std_ac_luminance_values = [\n                    0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,\n                    0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,\n                    0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,\n                    0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,\n                    0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,\n                    0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,\n                    0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,\n                    0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,\n                    0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,\n                    0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,\n                    0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,\n                    0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,\n                    0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,\n                    0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,\n                    0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,\n                    0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,\n                    0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,\n                    0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,\n                    0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,\n                    0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n    \n            var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];\n            var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];\n            var std_ac_chrominance_values = [\n                    0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,\n                    0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,\n                    0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,\n                    0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,\n                    0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,\n                    0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,\n                    0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,\n                    0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,\n                    0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,\n                    0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,\n                    0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,\n                    0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,\n                    0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,\n                    0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,\n                    0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,\n                    0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,\n                    0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,\n                    0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,\n                    0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,\n                    0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n    \n            function initQuantTables(sf){\n                    var YQT = [\n                        16, 11, 10, 16, 24, 40, 51, 61,\n                        12, 12, 14, 19, 26, 58, 60, 55,\n                        14, 13, 16, 24, 40, 57, 69, 56,\n                        14, 17, 22, 29, 51, 87, 80, 62,\n                        18, 22, 37, 56, 68,109,103, 77,\n                        24, 35, 55, 64, 81,104,113, 92,\n                        49, 64, 78, 87,103,121,120,101,\n                        72, 92, 95, 98,112,100,103, 99\n                    ];\n    \n                    for (var i = 0; i < 64; i++) {\n                        var t = ffloor((YQT[i]*sf+50)/100);\n                        if (t < 1) {\n                            t = 1;\n                        } else if (t > 255) {\n                            t = 255;\n                        }\n                        YTable[ZigZag[i]] = t;\n                    }\n                    var UVQT = [\n                        17, 18, 24, 47, 99, 99, 99, 99,\n                        18, 21, 26, 66, 99, 99, 99, 99,\n                        24, 26, 56, 99, 99, 99, 99, 99,\n                        47, 66, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99\n                    ];\n                    for (var j = 0; j < 64; j++) {\n                        var u = ffloor((UVQT[j]*sf+50)/100);\n                        if (u < 1) {\n                            u = 1;\n                        } else if (u > 255) {\n                            u = 255;\n                        }\n                        UVTable[ZigZag[j]] = u;\n                    }\n                    var aasf = [\n                        1.0, 1.387039845, 1.306562965, 1.175875602,\n                        1.0, 0.785694958, 0.541196100, 0.275899379\n                    ];\n                    var k = 0;\n                    for (var row = 0; row < 8; row++)\n                    {\n                        for (var col = 0; col < 8; col++)\n                        {\n                            fdtbl_Y[k]  = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            k++;\n                        }\n                    }\n                }\n    \n                function computeHuffmanTbl(nrcodes, std_table){\n                    var codevalue = 0;\n                    var pos_in_table = 0;\n                    var HT = new Array();\n                    for (var k = 1; k <= 16; k++) {\n                        for (var j = 1; j <= nrcodes[k]; j++) {\n                            HT[std_table[pos_in_table]] = [];\n                            HT[std_table[pos_in_table]][0] = codevalue;\n                            HT[std_table[pos_in_table]][1] = k;\n                            pos_in_table++;\n                            codevalue++;\n                        }\n                        codevalue*=2;\n                    }\n                    return HT;\n                }\n    \n                function initHuffmanTbl()\n                {\n                    YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);\n                    UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);\n                    YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);\n                    UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);\n                }\n    \n                function initCategoryNumber()\n                {\n                    var nrlower = 1;\n                    var nrupper = 2;\n                    for (var cat = 1; cat <= 15; cat++) {\n                        //Positive numbers\n                        for (var nr = nrlower; nr<nrupper; nr++) {\n                            category[32767+nr] = cat;\n                            bitcode[32767+nr] = [];\n                            bitcode[32767+nr][1] = cat;\n                            bitcode[32767+nr][0] = nr;\n                        }\n                        //Negative numbers\n                        for (var nrneg =-(nrupper-1); nrneg<=-nrlower; nrneg++) {\n                            category[32767+nrneg] = cat;\n                            bitcode[32767+nrneg] = [];\n                            bitcode[32767+nrneg][1] = cat;\n                            bitcode[32767+nrneg][0] = nrupper-1+nrneg;\n                        }\n                        nrlower <<= 1;\n                        nrupper <<= 1;\n                    }\n                }\n    \n                function initRGBYUVTable() {\n                    for(var i = 0; i < 256;i++) {\n                        RGB_YUV_TABLE[i]            =  19595 * i;\n                        RGB_YUV_TABLE[(i+ 256)>>0]  =  38470 * i;\n                        RGB_YUV_TABLE[(i+ 512)>>0]  =   7471 * i + 0x8000;\n                        RGB_YUV_TABLE[(i+ 768)>>0]  = -11059 * i;\n                        RGB_YUV_TABLE[(i+1024)>>0]  = -21709 * i;\n                        RGB_YUV_TABLE[(i+1280)>>0]  =  32768 * i + 0x807FFF;\n                        RGB_YUV_TABLE[(i+1536)>>0]  = -27439 * i;\n                        RGB_YUV_TABLE[(i+1792)>>0]  = - 5329 * i;\n                    }\n                }\n    \n                // IO functions\n                function writeBits(bs)\n                {\n                    var value = bs[0];\n                    var posval = bs[1]-1;\n                    while ( posval >= 0 ) {\n                        if (value & (1 << posval) ) {\n                            bytenew |= (1 << bytepos);\n                        }\n                        posval--;\n                        bytepos--;\n                        if (bytepos < 0) {\n                            if (bytenew == 0xFF) {\n                                writeByte(0xFF);\n                                writeByte(0);\n                            }\n                            else {\n                                writeByte(bytenew);\n                            }\n                            bytepos=7;\n                            bytenew=0;\n                        }\n                    }\n                }\n    \n                function writeByte(value)\n                {\n                    byteout.push(clt[value]); // write char directly instead of converting later\n                }\n    \n                function writeWord(value)\n                {\n                    writeByte((value>>8)&0xFF);\n                    writeByte((value   )&0xFF);\n                }\n    \n                // DCT & quantization core\n                function fDCTQuant(data, fdtbl)\n                {\n                    var d0, d1, d2, d3, d4, d5, d6, d7;\n                    /* Pass 1: process rows. */\n                    var dataOff=0;\n                    var i;\n                    var I8 = 8;\n                    var I64 = 64;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff+1];\n                        d2 = data[dataOff+2];\n                        d3 = data[dataOff+3];\n                        d4 = data[dataOff+4];\n                        d5 = data[dataOff+5];\n                        d6 = data[dataOff+6];\n                        d7 = data[dataOff+7];\n    \n                        var tmp0 = d0 + d7;\n                        var tmp7 = d0 - d7;\n                        var tmp1 = d1 + d6;\n                        var tmp6 = d1 - d6;\n                        var tmp2 = d2 + d5;\n                        var tmp5 = d2 - d5;\n                        var tmp3 = d3 + d4;\n                        var tmp4 = d3 - d4;\n    \n                        /* Even part */\n                        var tmp10 = tmp0 + tmp3;    /* phase 2 */\n                        var tmp13 = tmp0 - tmp3;\n                        var tmp11 = tmp1 + tmp2;\n                        var tmp12 = tmp1 - tmp2;\n    \n                        data[dataOff] = tmp10 + tmp11; /* phase 3 */\n                        data[dataOff+4] = tmp10 - tmp11;\n    \n                        var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */\n                        data[dataOff+2] = tmp13 + z1; /* phase 5 */\n                        data[dataOff+6] = tmp13 - z1;\n    \n                        /* Odd part */\n                        tmp10 = tmp4 + tmp5; /* phase 2 */\n                        tmp11 = tmp5 + tmp6;\n                        tmp12 = tmp6 + tmp7;\n    \n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */\n                        var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */\n                        var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */\n                        var z3 = tmp11 * 0.707106781; /* c4 */\n    \n                        var z11 = tmp7 + z3;    /* phase 5 */\n                        var z13 = tmp7 - z3;\n    \n                        data[dataOff+5] = z13 + z2; /* phase 6 */\n                        data[dataOff+3] = z13 - z2;\n                        data[dataOff+1] = z11 + z4;\n                        data[dataOff+7] = z11 - z4;\n    \n                        dataOff += 8; /* advance pointer to next row */\n                    }\n    \n                    /* Pass 2: process columns. */\n                    dataOff = 0;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff + 8];\n                        d2 = data[dataOff + 16];\n                        d3 = data[dataOff + 24];\n                        d4 = data[dataOff + 32];\n                        d5 = data[dataOff + 40];\n                        d6 = data[dataOff + 48];\n                        d7 = data[dataOff + 56];\n    \n                        var tmp0p2 = d0 + d7;\n                        var tmp7p2 = d0 - d7;\n                        var tmp1p2 = d1 + d6;\n                        var tmp6p2 = d1 - d6;\n                        var tmp2p2 = d2 + d5;\n                        var tmp5p2 = d2 - d5;\n                        var tmp3p2 = d3 + d4;\n                        var tmp4p2 = d3 - d4;\n    \n                        /* Even part */\n                        var tmp10p2 = tmp0p2 + tmp3p2;  /* phase 2 */\n                        var tmp13p2 = tmp0p2 - tmp3p2;\n                        var tmp11p2 = tmp1p2 + tmp2p2;\n                        var tmp12p2 = tmp1p2 - tmp2p2;\n    \n                        data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */\n                        data[dataOff+32] = tmp10p2 - tmp11p2;\n    \n                        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */\n                        data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */\n                        data[dataOff+48] = tmp13p2 - z1p2;\n    \n                        /* Odd part */\n                        tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */\n                        tmp11p2 = tmp5p2 + tmp6p2;\n                        tmp12p2 = tmp6p2 + tmp7p2;\n    \n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */\n                        var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */\n                        var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */\n                        var z3p2 = tmp11p2 * 0.707106781; /* c4 */\n    \n                        var z11p2 = tmp7p2 + z3p2;  /* phase 5 */\n                        var z13p2 = tmp7p2 - z3p2;\n    \n                        data[dataOff+40] = z13p2 + z2p2; /* phase 6 */\n                        data[dataOff+24] = z13p2 - z2p2;\n                        data[dataOff+ 8] = z11p2 + z4p2;\n                        data[dataOff+56] = z11p2 - z4p2;\n    \n                        dataOff++; /* advance pointer to next column */\n                    }\n    \n                    // Quantize/descale the coefficients\n                    var fDCTQuant;\n                    for (i=0; i<I64; ++i)\n                    {\n                        // Apply the quantization and scaling factor & Round to nearest integer\n                        fDCTQuant = data[i]*fdtbl[i];\n                        outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);\n                        //outputfDCTQuant[i] = fround(fDCTQuant);\n    \n                    }\n                    return outputfDCTQuant;\n                }\n    \n                function writeAPP0()\n                {\n                    writeWord(0xFFE0); // marker\n                    writeWord(16); // length\n                    writeByte(0x4A); // J\n                    writeByte(0x46); // F\n                    writeByte(0x49); // I\n                    writeByte(0x46); // F\n                    writeByte(0); // = \"JFIF\",'\\0'\n                    writeByte(1); // versionhi\n                    writeByte(1); // versionlo\n                    writeByte(0); // xyunits\n                    writeWord(1); // xdensity\n                    writeWord(1); // ydensity\n                    writeByte(0); // thumbnwidth\n                    writeByte(0); // thumbnheight\n                }\n    \n                function writeSOF0(width, height)\n                {\n                    writeWord(0xFFC0); // marker\n                    writeWord(17);   // length, truecolor YUV JPG\n                    writeByte(8);    // precision\n                    writeWord(height);\n                    writeWord(width);\n                    writeByte(3);    // nrofcomponents\n                    writeByte(1);    // IdY\n                    writeByte(0x11); // HVY\n                    writeByte(0);    // QTY\n                    writeByte(2);    // IdU\n                    writeByte(0x11); // HVU\n                    writeByte(1);    // QTU\n                    writeByte(3);    // IdV\n                    writeByte(0x11); // HVV\n                    writeByte(1);    // QTV\n                }\n    \n                function writeDQT()\n                {\n                    writeWord(0xFFDB); // marker\n                    writeWord(132);    // length\n                    writeByte(0);\n                    for (var i=0; i<64; i++) {\n                        writeByte(YTable[i]);\n                    }\n                    writeByte(1);\n                    for (var j=0; j<64; j++) {\n                        writeByte(UVTable[j]);\n                    }\n                }\n    \n                function writeDHT()\n                {\n                    writeWord(0xFFC4); // marker\n                    writeWord(0x01A2); // length\n    \n                    writeByte(0); // HTYDCinfo\n                    for (var i=0; i<16; i++) {\n                        writeByte(std_dc_luminance_nrcodes[i+1]);\n                    }\n                    for (var j=0; j<=11; j++) {\n                        writeByte(std_dc_luminance_values[j]);\n                    }\n    \n                    writeByte(0x10); // HTYACinfo\n                    for (var k=0; k<16; k++) {\n                        writeByte(std_ac_luminance_nrcodes[k+1]);\n                    }\n                    for (var l=0; l<=161; l++) {\n                        writeByte(std_ac_luminance_values[l]);\n                    }\n    \n                    writeByte(1); // HTUDCinfo\n                    for (var m=0; m<16; m++) {\n                        writeByte(std_dc_chrominance_nrcodes[m+1]);\n                    }\n                    for (var n=0; n<=11; n++) {\n                        writeByte(std_dc_chrominance_values[n]);\n                    }\n    \n                    writeByte(0x11); // HTUACinfo\n                    for (var o=0; o<16; o++) {\n                        writeByte(std_ac_chrominance_nrcodes[o+1]);\n                    }\n                    for (var p=0; p<=161; p++) {\n                        writeByte(std_ac_chrominance_values[p]);\n                    }\n                }\n    \n                function writeSOS()\n                {\n                    writeWord(0xFFDA); // marker\n                    writeWord(12); // length\n                    writeByte(3); // nrofcomponents\n                    writeByte(1); // IdY\n                    writeByte(0); // HTY\n                    writeByte(2); // IdU\n                    writeByte(0x11); // HTU\n                    writeByte(3); // IdV\n                    writeByte(0x11); // HTV\n                    writeByte(0); // Ss\n                    writeByte(0x3f); // Se\n                    writeByte(0); // Bf\n                }\n    \n                function processDU(CDU, fdtbl, DC, HTDC, HTAC){\n                    var EOB = HTAC[0x00];\n                    var M16zeroes = HTAC[0xF0];\n                    var pos;\n                    var I16 = 16;\n                    var I63 = 63;\n                    var I64 = 64;\n                    var DU_DCT = fDCTQuant(CDU, fdtbl);\n                    //ZigZag reorder\n                    for (var j=0;j<I64;++j) {\n                        DU[ZigZag[j]]=DU_DCT[j];\n                    }\n                    var Diff = DU[0] - DC; DC = DU[0];\n                    //Encode DC\n                    if (Diff==0) {\n                        writeBits(HTDC[0]); // Diff might be 0\n                    } else {\n                        pos = 32767+Diff;\n                        writeBits(HTDC[category[pos]]);\n                        writeBits(bitcode[pos]);\n                    }\n                    //Encode ACs\n                    var end0pos = 63; // was consts... which is crazy\n                    for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {};\n                    //end0pos = first element in reverse order !=0\n                    if ( end0pos == 0) {\n                        writeBits(EOB);\n                        return DC;\n                    }\n                    var i = 1;\n                    var lng;\n                    while ( i <= end0pos ) {\n                        var startpos = i;\n                        for (; (DU[i]==0) && (i<=end0pos); ++i) {}\n                        var nrzeroes = i-startpos;\n                        if ( nrzeroes >= I16 ) {\n                            lng = nrzeroes>>4;\n                            for (var nrmarker=1; nrmarker <= lng; ++nrmarker)\n                                writeBits(M16zeroes);\n                            nrzeroes = nrzeroes&0xF;\n                        }\n                        pos = 32767+DU[i];\n                        writeBits(HTAC[(nrzeroes<<4)+category[pos]]);\n                        writeBits(bitcode[pos]);\n                        i++;\n                    }\n                    if ( end0pos != I63 ) {\n                        writeBits(EOB);\n                    }\n                    return DC;\n                }\n    \n                function initCharLookupTable(){\n                    var sfcc = String.fromCharCode;\n                    for(var i=0; i < 256; i++){ ///// ACHTUNG // 255\n                        clt[i] = sfcc(i);\n                    }\n                }\n    \n                this.encode = function(image,quality) // image data object\n                {\n                    // var time_start = new Date().getTime();\n    \n                    if(quality) setQuality(quality);\n    \n                    // Initialize bit writer\n                    byteout = new Array();\n                    bytenew=0;\n                    bytepos=7;\n    \n                    // Add JPEG headers\n                    writeWord(0xFFD8); // SOI\n                    writeAPP0();\n                    writeDQT();\n                    writeSOF0(image.width,image.height);\n                    writeDHT();\n                    writeSOS();\n    \n    \n                    // Encode 8x8 macroblocks\n                    var DCY=0;\n                    var DCU=0;\n                    var DCV=0;\n    \n                    bytenew=0;\n                    bytepos=7;\n    \n    \n                    this.encode.displayName = \"_encode_\";\n    \n                    var imageData = image.data;\n                    var width = image.width;\n                    var height = image.height;\n    \n                    var quadWidth = width*4;\n                    var tripleWidth = width*3;\n    \n                    var x, y = 0;\n                    var r, g, b;\n                    var start,p, col,row,pos;\n                    while(y < height){\n                        x = 0;\n                        while(x < quadWidth){\n                        start = quadWidth * y + x;\n                        p = start;\n                        col = -1;\n                        row = 0;\n    \n                        for(pos=0; pos < 64; pos++){\n                            row = pos >> 3;// /8\n                            col = ( pos & 7 ) * 4; // %8\n                            p = start + ( row * quadWidth ) + col;\n    \n                            if(y+row >= height){ // padding bottom\n                                p-= (quadWidth*(y+1+row-height));\n                            }\n    \n                            if(x+col >= quadWidth){ // padding right\n                                p-= ((x+col) - quadWidth +4)\n                            }\n    \n                            r = imageData[ p++ ];\n                            g = imageData[ p++ ];\n                            b = imageData[ p++ ];\n    \n    \n                            /* // calculate YUV values dynamically\n                            YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80\n                            UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));\n                            VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));\n                            */\n    \n                            // use lookup table (slightly faster)\n                            YDU[pos] = ((RGB_YUV_TABLE[r]             + RGB_YUV_TABLE[(g +  256)>>0] + RGB_YUV_TABLE[(b +  512)>>0]) >> 16)-128;\n                            UDU[pos] = ((RGB_YUV_TABLE[(r +  768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128;\n                            VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128;\n    \n                        }\n    \n                        DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);\n                        DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);\n                        DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);\n                        x+=32;\n                        }\n                        y+=8;\n                    }\n    \n    \n                    ////////////////////////////////////////////////////////////////\n    \n                    // Do the bit alignment of the EOI marker\n                    if ( bytepos >= 0 ) {\n                        var fillbits = [];\n                        fillbits[1] = bytepos+1;\n                        fillbits[0] = (1<<(bytepos+1))-1;\n                        writeBits(fillbits);\n                    }\n    \n                    writeWord(0xFFD9); //EOI\n    \n                    var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join(''));\n    \n                    byteout = [];\n    \n                    // benchmarking\n                    // var duration = new Date().getTime() - time_start;\n                    // console.log('Encoding time: '+ currentQuality + 'ms');\n                    //\n    \n                    return jpegDataUri\n            }\n    \n            function setQuality(quality){\n                if (quality <= 0) {\n                    quality = 1;\n                }\n                if (quality > 100) {\n                    quality = 100;\n                }\n    \n                if(currentQuality == quality) return // don't recalc if unchanged\n    \n                var sf = 0;\n                if (quality < 50) {\n                    sf = Math.floor(5000 / quality);\n                } else {\n                    sf = Math.floor(200 - quality*2);\n                }\n    \n                initQuantTables(sf);\n                currentQuality = quality;\n                // console.log('Quality set to: '+quality +'%');\n            }\n    \n            function init(){\n                // var time_start = new Date().getTime();\n                if(!quality) quality = 50;\n                // Create tables\n                initCharLookupTable()\n                initHuffmanTbl();\n                initCategoryNumber();\n                initRGBYUVTable();\n    \n                setQuality(quality);\n                // var duration = new Date().getTime() - time_start;\n                // console.log('Initialization '+ duration + 'ms');\n            }\n    \n            init();\n    \n        };\n    \n        JPEGEncoder.encode = function( data, quality ) {\n            var encoder = new JPEGEncoder( quality );\n    \n            return encoder.encode( data );\n        }\n    \n        return JPEGEncoder;\n    });\n    /**\n     * @fileOverview Fix android canvas.toDataUrl bug.\n     */\n    define('runtime/html5/androidpatch',[\n        'runtime/html5/util',\n        'runtime/html5/jpegencoder',\n        'base'\n    ], function( Util, encoder, Base ) {\n        var origin = Util.canvasToDataUrl,\n            supportJpeg;\n    \n        Util.canvasToDataUrl = function( canvas, type, quality ) {\n            var ctx, w, h, fragement, parts;\n    \n            // 非android手机直接跳过。\n            if ( !Base.os.android ) {\n                return origin.apply( null, arguments );\n            }\n    \n            // 检测是否canvas支持jpeg导出，根据数据格式来判断。\n            // JPEG 前两位分别是：255, 216\n            if ( type === 'image/jpeg' && typeof supportJpeg === 'undefined' ) {\n                fragement = origin.apply( null, arguments );\n    \n                parts = fragement.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    fragement = atob( parts[ 1 ] );\n                } else {\n                    fragement = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                fragement = fragement.substring( 0, 2 );\n    \n                supportJpeg = fragement.charCodeAt( 0 ) === 255 &&\n                        fragement.charCodeAt( 1 ) === 216;\n            }\n    \n            // 只有在android环境下才修复\n            if ( type === 'image/jpeg' && !supportJpeg ) {\n                w = canvas.width;\n                h = canvas.height;\n                ctx = canvas.getContext('2d');\n    \n                return encoder.encode( ctx.getImageData( 0, 0, w, h ), quality );\n            }\n    \n            return origin.apply( null, arguments );\n        };\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('runtime/html5/image',[\n        'base',\n        'runtime/html5/runtime',\n        'runtime/html5/util'\n    ], function( Base, Html5Runtime, Util ) {\n    \n        var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';\n    \n        return Html5Runtime.register( 'Image', {\n    \n            // flag: 标记是否被修改过。\n            modified: false,\n    \n            init: function() {\n                var me = this,\n                    img = new Image();\n    \n                img.onload = function() {\n    \n                    me._info = {\n                        type: me.type,\n                        width: this.width,\n                        height: this.height\n                    };\n    \n                    // 读取meta信息。\n                    if ( !me._metas && 'image/jpeg' === me.type ) {\n                        Util.parseMeta( me._blob, function( error, ret ) {\n                            me._metas = ret;\n                            me.owner.trigger('load');\n                        });\n                    } else {\n                        me.owner.trigger('load');\n                    }\n                };\n    \n                img.onerror = function() {\n                    me.owner.trigger('error');\n                };\n    \n                me._img = img;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    img = me._img;\n    \n                me._blob = blob;\n                me.type = blob.type;\n                img.src = Util.createObjectURL( blob.getSource() );\n                me.owner.once( 'load', function() {\n                    Util.revokeObjectURL( img.src );\n                });\n            },\n    \n            resize: function( width, height ) {\n                var canvas = this._canvas ||\n                        (this._canvas = document.createElement('canvas'));\n    \n                this._resize( this._img, canvas, width, height );\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'resize' );\n            },\n    \n            crop: function( x, y, w, h, s ) {\n                var cvs = this._canvas ||\n                        (this._canvas = document.createElement('canvas')),\n                    opts = this.options,\n                    img = this._img,\n                    iw = img.naturalWidth,\n                    ih = img.naturalHeight,\n                    orientation = this.getOrientation();\n    \n                s = s || 1;\n    \n                // todo 解决 orientation 的问题。\n                // values that require 90 degree rotation\n                // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n    \n                //     switch ( orientation ) {\n                //         case 6:\n                //             tmp = x;\n                //             x = y;\n                //             y = iw * s - tmp - w;\n                //             console.log(ih * s, tmp, w)\n                //             break;\n                //     }\n    \n                //     (w ^= h, h ^= w, w ^= h);\n                // }\n    \n                cvs.width = w;\n                cvs.height = h;\n    \n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n                this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s );\n    \n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'crop' );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this._blob,\n                    opts = this.options,\n                    canvas;\n    \n                type = type || this.type;\n    \n                // blob需要重新生成。\n                if ( this.modified || this.type !== type ) {\n                    canvas = this._canvas;\n    \n                    if ( type === 'image/jpeg' ) {\n    \n                        blob = Util.canvasToDataUrl( canvas, type, opts.quality );\n    \n                        if ( opts.preserveHeaders && this._metas &&\n                                this._metas.imageHead ) {\n    \n                            blob = Util.dataURL2ArrayBuffer( blob );\n                            blob = Util.updateImageHead( blob,\n                                    this._metas.imageHead );\n                            blob = Util.arrayBufferToBlob( blob, type );\n                            return blob;\n                        }\n                    } else {\n                        blob = Util.canvasToDataUrl( canvas, type );\n                    }\n    \n                    blob = Util.dataURL2Blob( blob );\n                }\n    \n                return blob;\n            },\n    \n            getAsDataUrl: function( type ) {\n                var opts = this.options;\n    \n                type = type || this.type;\n    \n                if ( type === 'image/jpeg' ) {\n                    return Util.canvasToDataUrl( this._canvas, type, opts.quality );\n                } else {\n                    return this._canvas.toDataURL( type );\n                }\n            },\n    \n            getOrientation: function() {\n                return this._metas && this._metas.exif &&\n                        this._metas.exif.get('Orientation') || 1;\n            },\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            destroy: function() {\n                var canvas = this._canvas;\n                this._img.onload = null;\n    \n                if ( canvas ) {\n                    canvas.getContext('2d')\n                            .clearRect( 0, 0, canvas.width, canvas.height );\n                    canvas.width = canvas.height = 0;\n                    this._canvas = null;\n                }\n    \n                // 释放内存。非常重要，否则释放不了image的内存。\n                this._img.src = BLANK;\n                this._img = this._blob = null;\n            },\n    \n            _resize: function( img, cvs, width, height ) {\n                var opts = this.options,\n                    naturalWidth = img.width,\n                    naturalHeight = img.height,\n                    orientation = this.getOrientation(),\n                    scale, w, h, x, y;\n    \n                // values that require 90 degree rotation\n                if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n    \n                    // 交换width, height的值。\n                    width ^= height;\n                    height ^= width;\n                    width ^= height;\n                }\n    \n                scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth,\n                        height / naturalHeight );\n    \n                // 不允许放大。\n                opts.allowMagnify || (scale = Math.min( 1, scale ));\n    \n                w = naturalWidth * scale;\n                h = naturalHeight * scale;\n    \n                if ( opts.crop ) {\n                    cvs.width = width;\n                    cvs.height = height;\n                } else {\n                    cvs.width = w;\n                    cvs.height = h;\n                }\n    \n                x = (cvs.width - w) / 2;\n                y = (cvs.height - h) / 2;\n    \n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n    \n                this._renderImageToCanvas( cvs, img, x, y, w, h );\n            },\n    \n            _rotate2Orientaion: function( canvas, orientation ) {\n                var width = canvas.width,\n                    height = canvas.height,\n                    ctx = canvas.getContext('2d');\n    \n                switch ( orientation ) {\n                    case 5:\n                    case 6:\n                    case 7:\n                    case 8:\n                        canvas.width = height;\n                        canvas.height = width;\n                        break;\n                }\n    \n                switch ( orientation ) {\n                    case 2:    // horizontal flip\n                        ctx.translate( width, 0 );\n                        ctx.scale( -1, 1 );\n                        break;\n    \n                    case 3:    // 180 rotate left\n                        ctx.translate( width, height );\n                        ctx.rotate( Math.PI );\n                        break;\n    \n                    case 4:    // vertical flip\n                        ctx.translate( 0, height );\n                        ctx.scale( 1, -1 );\n                        break;\n    \n                    case 5:    // vertical flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.scale( 1, -1 );\n                        break;\n    \n                    case 6:    // 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( 0, -height );\n                        break;\n    \n                    case 7:    // horizontal flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( width, -height );\n                        ctx.scale( -1, 1 );\n                        break;\n    \n                    case 8:    // 90 rotate left\n                        ctx.rotate( -0.5 * Math.PI );\n                        ctx.translate( -width, 0 );\n                        break;\n                }\n            },\n    \n            // https://github.com/stomita/ios-imagefile-megapixel/\n            // blob/master/src/megapix-image.js\n            _renderImageToCanvas: (function() {\n    \n                // 如果不是ios, 不需要这么复杂！\n                if ( !Base.os.ios ) {\n                    return function( canvas ) {\n                        var args = Base.slice( arguments, 1 ),\n                            ctx = canvas.getContext('2d');\n    \n                        ctx.drawImage.apply( ctx, args );\n                    };\n                }\n    \n                /**\n                 * Detecting vertical squash in loaded image.\n                 * Fixes a bug which squash image vertically while drawing into\n                 * canvas for some images.\n                 */\n                function detectVerticalSquash( img, iw, ih ) {\n                    var canvas = document.createElement('canvas'),\n                        ctx = canvas.getContext('2d'),\n                        sy = 0,\n                        ey = ih,\n                        py = ih,\n                        data, alpha, ratio;\n    \n    \n                    canvas.width = 1;\n                    canvas.height = ih;\n                    ctx.drawImage( img, 0, 0 );\n                    data = ctx.getImageData( 0, 0, 1, ih ).data;\n    \n                    // search image edge pixel position in case\n                    // it is squashed vertically.\n                    while ( py > sy ) {\n                        alpha = data[ (py - 1) * 4 + 3 ];\n    \n                        if ( alpha === 0 ) {\n                            ey = py;\n                        } else {\n                            sy = py;\n                        }\n    \n                        py = (ey + sy) >> 1;\n                    }\n    \n                    ratio = (py / ih);\n                    return (ratio === 0) ? 1 : ratio;\n                }\n    \n                // fix ie7 bug\n                // http://stackoverflow.com/questions/11929099/\n                // html5-canvas-drawimage-ratio-bug-ios\n                if ( Base.os.ios >= 7 ) {\n                    return function( canvas, img, x, y, w, h ) {\n                        var iw = img.naturalWidth,\n                            ih = img.naturalHeight,\n                            vertSquashRatio = detectVerticalSquash( img, iw, ih );\n    \n                        return canvas.getContext('2d').drawImage( img, 0, 0,\n                                iw * vertSquashRatio, ih * vertSquashRatio,\n                                x, y, w, h );\n                    };\n                }\n    \n                /**\n                 * Detect subsampling in loaded image.\n                 * In iOS, larger images than 2M pixels may be\n                 * subsampled in rendering.\n                 */\n                function detectSubsampling( img ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        canvas, ctx;\n    \n                    // subsampling may happen overmegapixel image\n                    if ( iw * ih > 1024 * 1024 ) {\n                        canvas = document.createElement('canvas');\n                        canvas.width = canvas.height = 1;\n                        ctx = canvas.getContext('2d');\n                        ctx.drawImage( img, -iw + 1, 0 );\n    \n                        // subsampled image becomes half smaller in rendering size.\n                        // check alpha channel value to confirm image is covering\n                        // edge pixel or not. if alpha value is 0\n                        // image is not covering, hence subsampled.\n                        return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0;\n                    } else {\n                        return false;\n                    }\n                }\n    \n    \n                return function( canvas, img, x, y, width, height ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        ctx = canvas.getContext('2d'),\n                        subsampled = detectSubsampling( img ),\n                        doSquash = this.type === 'image/jpeg',\n                        d = 1024,\n                        sy = 0,\n                        dy = 0,\n                        tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx;\n    \n                    if ( subsampled ) {\n                        iw /= 2;\n                        ih /= 2;\n                    }\n    \n                    ctx.save();\n                    tmpCanvas = document.createElement('canvas');\n                    tmpCanvas.width = tmpCanvas.height = d;\n    \n                    tmpCtx = tmpCanvas.getContext('2d');\n                    vertSquashRatio = doSquash ?\n                            detectVerticalSquash( img, iw, ih ) : 1;\n    \n                    dw = Math.ceil( d * width / iw );\n                    dh = Math.ceil( d * height / ih / vertSquashRatio );\n    \n                    while ( sy < ih ) {\n                        sx = 0;\n                        dx = 0;\n                        while ( sx < iw ) {\n                            tmpCtx.clearRect( 0, 0, d, d );\n                            tmpCtx.drawImage( img, -sx, -sy );\n                            ctx.drawImage( tmpCanvas, 0, 0, d, d,\n                                    x + dx, y + dy, dw, dh );\n                            sx += d;\n                            dx += dw;\n                        }\n                        sy += d;\n                        dy += dh;\n                    }\n                    ctx.restore();\n                    tmpCanvas = tmpCtx = null;\n                };\n            })()\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var noop = Base.noop,\n            $ = Base.$;\n    \n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n    \n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n    \n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n    \n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n    \n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n    \n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n    \n            getResponse: function() {\n                return this._response;\n            },\n    \n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n    \n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n    \n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n    \n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n    \n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n    \n                    return me.trigger( 'progress', percentage );\n                };\n    \n                xhr.onreadystatechange = function() {\n    \n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n    \n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n    \n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n    \n    \n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n    \n            _parseJson: function( str ) {\n                var json;\n    \n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n    \n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/html5/md5',[\n        'runtime/html5/runtime'\n    ], function( FlashRuntime ) {\n    \n        /*\n         * Fastest md5 implementation around (JKM md5)\n         * Credits: Joseph Myers\n         *\n         * @see http://www.myersdaily.org/joseph/javascript/md5-text.html\n         * @see http://jsperf.com/md5-shootout/7\n         */\n    \n        /* this function is much faster,\n          so if possible we use it. Some IEs\n          are the only ones I know of that\n          need the idiotic second function,\n          generated by an if clause.  */\n        var add32 = function (a, b) {\n            return (a + b) & 0xFFFFFFFF;\n        },\n    \n        cmn = function (q, a, b, x, s, t) {\n            a = add32(add32(a, q), add32(x, t));\n            return add32((a << s) | (a >>> (32 - s)), b);\n        },\n    \n        ff = function (a, b, c, d, x, s, t) {\n            return cmn((b & c) | ((~b) & d), a, b, x, s, t);\n        },\n    \n        gg = function (a, b, c, d, x, s, t) {\n            return cmn((b & d) | (c & (~d)), a, b, x, s, t);\n        },\n    \n        hh = function (a, b, c, d, x, s, t) {\n            return cmn(b ^ c ^ d, a, b, x, s, t);\n        },\n    \n        ii = function (a, b, c, d, x, s, t) {\n            return cmn(c ^ (b | (~d)), a, b, x, s, t);\n        },\n    \n        md5cycle = function (x, k) {\n            var a = x[0],\n                b = x[1],\n                c = x[2],\n                d = x[3];\n    \n            a = ff(a, b, c, d, k[0], 7, -680876936);\n            d = ff(d, a, b, c, k[1], 12, -389564586);\n            c = ff(c, d, a, b, k[2], 17, 606105819);\n            b = ff(b, c, d, a, k[3], 22, -1044525330);\n            a = ff(a, b, c, d, k[4], 7, -176418897);\n            d = ff(d, a, b, c, k[5], 12, 1200080426);\n            c = ff(c, d, a, b, k[6], 17, -1473231341);\n            b = ff(b, c, d, a, k[7], 22, -45705983);\n            a = ff(a, b, c, d, k[8], 7, 1770035416);\n            d = ff(d, a, b, c, k[9], 12, -1958414417);\n            c = ff(c, d, a, b, k[10], 17, -42063);\n            b = ff(b, c, d, a, k[11], 22, -1990404162);\n            a = ff(a, b, c, d, k[12], 7, 1804603682);\n            d = ff(d, a, b, c, k[13], 12, -40341101);\n            c = ff(c, d, a, b, k[14], 17, -1502002290);\n            b = ff(b, c, d, a, k[15], 22, 1236535329);\n    \n            a = gg(a, b, c, d, k[1], 5, -165796510);\n            d = gg(d, a, b, c, k[6], 9, -1069501632);\n            c = gg(c, d, a, b, k[11], 14, 643717713);\n            b = gg(b, c, d, a, k[0], 20, -373897302);\n            a = gg(a, b, c, d, k[5], 5, -701558691);\n            d = gg(d, a, b, c, k[10], 9, 38016083);\n            c = gg(c, d, a, b, k[15], 14, -660478335);\n            b = gg(b, c, d, a, k[4], 20, -405537848);\n            a = gg(a, b, c, d, k[9], 5, 568446438);\n            d = gg(d, a, b, c, k[14], 9, -1019803690);\n            c = gg(c, d, a, b, k[3], 14, -187363961);\n            b = gg(b, c, d, a, k[8], 20, 1163531501);\n            a = gg(a, b, c, d, k[13], 5, -1444681467);\n            d = gg(d, a, b, c, k[2], 9, -51403784);\n            c = gg(c, d, a, b, k[7], 14, 1735328473);\n            b = gg(b, c, d, a, k[12], 20, -1926607734);\n    \n            a = hh(a, b, c, d, k[5], 4, -378558);\n            d = hh(d, a, b, c, k[8], 11, -2022574463);\n            c = hh(c, d, a, b, k[11], 16, 1839030562);\n            b = hh(b, c, d, a, k[14], 23, -35309556);\n            a = hh(a, b, c, d, k[1], 4, -1530992060);\n            d = hh(d, a, b, c, k[4], 11, 1272893353);\n            c = hh(c, d, a, b, k[7], 16, -155497632);\n            b = hh(b, c, d, a, k[10], 23, -1094730640);\n            a = hh(a, b, c, d, k[13], 4, 681279174);\n            d = hh(d, a, b, c, k[0], 11, -358537222);\n            c = hh(c, d, a, b, k[3], 16, -722521979);\n            b = hh(b, c, d, a, k[6], 23, 76029189);\n            a = hh(a, b, c, d, k[9], 4, -640364487);\n            d = hh(d, a, b, c, k[12], 11, -421815835);\n            c = hh(c, d, a, b, k[15], 16, 530742520);\n            b = hh(b, c, d, a, k[2], 23, -995338651);\n    \n            a = ii(a, b, c, d, k[0], 6, -198630844);\n            d = ii(d, a, b, c, k[7], 10, 1126891415);\n            c = ii(c, d, a, b, k[14], 15, -1416354905);\n            b = ii(b, c, d, a, k[5], 21, -57434055);\n            a = ii(a, b, c, d, k[12], 6, 1700485571);\n            d = ii(d, a, b, c, k[3], 10, -1894986606);\n            c = ii(c, d, a, b, k[10], 15, -1051523);\n            b = ii(b, c, d, a, k[1], 21, -2054922799);\n            a = ii(a, b, c, d, k[8], 6, 1873313359);\n            d = ii(d, a, b, c, k[15], 10, -30611744);\n            c = ii(c, d, a, b, k[6], 15, -1560198380);\n            b = ii(b, c, d, a, k[13], 21, 1309151649);\n            a = ii(a, b, c, d, k[4], 6, -145523070);\n            d = ii(d, a, b, c, k[11], 10, -1120210379);\n            c = ii(c, d, a, b, k[2], 15, 718787259);\n            b = ii(b, c, d, a, k[9], 21, -343485551);\n    \n            x[0] = add32(a, x[0]);\n            x[1] = add32(b, x[1]);\n            x[2] = add32(c, x[2]);\n            x[3] = add32(d, x[3]);\n        },\n    \n        /* there needs to be support for Unicode here,\n           * unless we pretend that we can redefine the MD-5\n           * algorithm for multi-byte characters (perhaps\n           * by adding every four 16-bit characters and\n           * shortening the sum to 32 bits). Otherwise\n           * I suggest performing MD-5 as if every character\n           * was two bytes--e.g., 0040 0025 = @%--but then\n           * how will an ordinary MD-5 sum be matched?\n           * There is no way to standardize text to something\n           * like UTF-8 before transformation; speed cost is\n           * utterly prohibitive. The JavaScript standard\n           * itself needs to look at this: it should start\n           * providing access to strings as preformed UTF-8\n           * 8-bit unsigned value arrays.\n           */\n        md5blk = function (s) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n    \n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);\n            }\n            return md5blks;\n        },\n    \n        md5blk_array = function (a) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n    \n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);\n            }\n            return md5blks;\n        },\n    \n        md51 = function (s) {\n            var n = s.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n    \n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk(s.substring(i - 64, i)));\n            }\n            s = s.substring(i - 64);\n            length = s.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);\n            }\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n    \n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n    \n            tail[14] = lo;\n            tail[15] = hi;\n    \n            md5cycle(state, tail);\n            return state;\n        },\n    \n        md51_array = function (a) {\n            var n = a.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n    \n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk_array(a.subarray(i - 64, i)));\n            }\n    \n            // Not sure if it is a bug, however IE10 will always produce a sub array of length 1\n            // containing the last element of the parent array if the sub array specified starts\n            // beyond the length of the parent array - weird.\n            // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue\n            a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);\n    \n            length = a.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= a[i] << ((i % 4) << 3);\n            }\n    \n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n    \n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n    \n            tail[14] = lo;\n            tail[15] = hi;\n    \n            md5cycle(state, tail);\n    \n            return state;\n        },\n    \n        hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],\n    \n        rhex = function (n) {\n            var s = '',\n                j;\n            for (j = 0; j < 4; j += 1) {\n                s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];\n            }\n            return s;\n        },\n    \n        hex = function (x) {\n            var i;\n            for (i = 0; i < x.length; i += 1) {\n                x[i] = rhex(x[i]);\n            }\n            return x.join('');\n        },\n    \n        md5 = function (s) {\n            return hex(md51(s));\n        },\n    \n    \n    \n        ////////////////////////////////////////////////////////////////////////////\n    \n        /**\n         * SparkMD5 OOP implementation.\n         *\n         * Use this class to perform an incremental md5, otherwise use the\n         * static methods instead.\n         */\n        SparkMD5 = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n    \n    \n        // In some cases the fast add32 function cannot be used..\n        if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {\n            add32 = 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    \n    \n        /**\n         * Appends a string.\n         * A conversion will be applied if an utf8 string is detected.\n         *\n         * @param {String} str The string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.append = function (str) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n    \n            // then append as binary\n            this.appendBinary(str);\n    \n            return this;\n        };\n    \n        /**\n         * Appends a binary string.\n         *\n         * @param {String} contents The binary string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.appendBinary = function (contents) {\n            this._buff += contents;\n            this._length += contents.length;\n    \n            var length = this._buff.length,\n                i;\n    \n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));\n            }\n    \n            this._buff = this._buff.substr(i - 64);\n    \n            return this;\n        };\n    \n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                i,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                ret;\n    \n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);\n            }\n    \n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n    \n            this.reset();\n    \n            return ret;\n        };\n    \n        /**\n         * Finish the final calculation based on the tail.\n         *\n         * @param {Array}  tail   The tail (will be modified)\n         * @param {Number} length The length of the remaining buffer\n         */\n        SparkMD5.prototype._finish = function (tail, length) {\n            var i = length,\n                tmp,\n                lo,\n                hi;\n    \n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(this._state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n    \n            // Do the final computation based on the tail and length\n            // Beware that the final length may not fit in 32 bits so we take care of that\n            tmp = this._length * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n    \n            tail[14] = lo;\n            tail[15] = hi;\n            md5cycle(this._state, tail);\n        };\n    \n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.reset = function () {\n            this._buff = \"\";\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n    \n            return this;\n        };\n    \n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.prototype.destroy = function () {\n            delete this._state;\n            delete this._buff;\n            delete this._length;\n        };\n    \n    \n        /**\n         * Performs the md5 hash on a string.\n         * A conversion will be applied if utf8 string is detected.\n         *\n         * @param {String}  str The string\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hash = function (str, raw) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n    \n            var hash = md51(str);\n    \n            return !!raw ? hash : hex(hash);\n        };\n    \n        /**\n         * Performs the md5 hash on a binary string.\n         *\n         * @param {String}  content The binary string\n         * @param {Boolean} raw     True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hashBinary = function (content, raw) {\n            var hash = md51(content);\n    \n            return !!raw ? hash : hex(hash);\n        };\n    \n        /**\n         * SparkMD5 OOP implementation for array buffers.\n         *\n         * Use this class to perform an incremental md5 ONLY for array buffers.\n         */\n        SparkMD5.ArrayBuffer = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n    \n        ////////////////////////////////////////////////////////////////////////////\n    \n        /**\n         * Appends an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array to be appended\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.append = function (arr) {\n            // TODO: we could avoid the concatenation here but the algorithm would be more complex\n            //       if you find yourself needing extra performance, please make a PR.\n            var buff = this._concatArrayBuffer(this._buff, arr),\n                length = buff.length,\n                i;\n    \n            this._length += arr.byteLength;\n    \n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));\n            }\n    \n            // Avoids IE10 weirdness (documented above)\n            this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);\n    \n            return this;\n        };\n    \n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                i,\n                ret;\n    \n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff[i] << ((i % 4) << 3);\n            }\n    \n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n    \n            this.reset();\n    \n            return ret;\n        };\n    \n        SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;\n    \n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.reset = function () {\n            this._buff = new Uint8Array(0);\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n    \n            return this;\n        };\n    \n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;\n    \n        /**\n         * Concats two array buffers, returning a new one.\n         *\n         * @param  {ArrayBuffer} first  The first array buffer\n         * @param  {ArrayBuffer} second The second array buffer\n         *\n         * @return {ArrayBuffer} The new array buffer\n         */\n        SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {\n            var firstLength = first.length,\n                result = new Uint8Array(firstLength + second.byteLength);\n    \n            result.set(first);\n            result.set(new Uint8Array(second), firstLength);\n    \n            return result;\n        };\n    \n        /**\n         * Performs the md5 hash on an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array buffer\n         * @param {Boolean}     raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.hash = function (arr, raw) {\n            var hash = md51_array(new Uint8Array(arr));\n    \n            return !!raw ? hash : hex(hash);\n        };\n        \n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n    \n            loadFromBlob: function( file ) {\n                var blob = file.getSource(),\n                    chunkSize = 2 * 1024 * 1024,\n                    chunks = Math.ceil( blob.size / chunkSize ),\n                    chunk = 0,\n                    owner = this.owner,\n                    spark = new SparkMD5.ArrayBuffer(),\n                    me = this,\n                    blobSlice = blob.mozSlice || blob.webkitSlice || blob.slice,\n                    loadNext, fr;\n    \n                fr = new FileReader();\n    \n                loadNext = function() {\n                    var start, end;\n    \n                    start = chunk * chunkSize;\n                    end = Math.min( start + chunkSize, blob.size );\n    \n                    fr.onload = function( e ) {\n                        spark.append( e.target.result );\n                        owner.trigger( 'progress', {\n                            total: file.size,\n                            loaded: end\n                        });\n                    };\n    \n                    fr.onloadend = function() {\n                        fr.onloadend = fr.onload = null;\n    \n                        if ( ++chunk < chunks ) {\n                            setTimeout( loadNext, 1 );\n                        } else {\n                            setTimeout(function(){\n                                owner.trigger('load');\n                                me.result = spark.end();\n                                loadNext = file = blob = spark = null;\n                                owner.trigger('complete');\n                            }, 50 );\n                        }\n                    };\n    \n                    fr.readAsArrayBuffer( blobSlice.call( blob, start, end ) );\n                };\n    \n                loadNext();\n            },\n    \n            getResult: function() {\n                return this.result;\n            }\n        });\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n    \n    \n        function getFlashVersion() {\n            var version;\n    \n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n    \n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                clients[ uid ] = client;\n    \n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n    \n                    instance = pool[ uid ];\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n    \n                return me.flashExec.apply( client, arguments );\n            };\n    \n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n    \n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n    \n                // console.log.apply( console, arguments );\n    \n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n    \n                // Base.log( evt, obj );\n            }\n    \n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n    \n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n    \n            this.jsreciver = jsreciver;\n    \n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n    \n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n    \n                return flash.exec( this.uid, comp, fn, args );\n            };\n    \n            // @todo\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n    \n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n    \n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n    \n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n    \n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n    \n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n    \n                container.html( html );\n            },\n    \n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n    \n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n    \n        });\n    \n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n    \n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n    \n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n    \n            return component;\n        };\n    \n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n    \n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n    \n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n    \n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n    \n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n    \n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview 图片压缩\n     */\n    define('runtime/flash/image',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n    \n        return FlashRuntime.register( 'Image', {\n            // init: function( options ) {\n            //     var owner = this.owner;\n    \n            //     this.flashExec( 'Image', 'init', options );\n            //     owner.on( 'load', function() {\n            //         debugger;\n            //     });\n            // },\n    \n            loadFromBlob: function( blob ) {\n                var owner = this.owner;\n    \n                owner.info() && this.flashExec( 'Image', 'info', owner.info() );\n                owner.meta() && this.flashExec( 'Image', 'meta', owner.meta() );\n    \n                this.flashExec( 'Image', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n    \n                xhr.connectRuntime( blob.ruid );\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n    \n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            getResponse: function() {\n                return this._response || '';\n            },\n    \n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n    \n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n    \n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n    \n                    xhr.off();\n                    me._xhr = null;\n    \n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n    \n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n    \n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n                            \n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n                            \n                        // }\n                    }\n                    \n                    xhr.destroy();\n                    xhr = null;\n    \n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n    \n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/flash/blob',[\n        'runtime/flash/runtime',\n        'lib/blob'\n    ], function( FlashRuntime, Blob ) {\n    \n        return FlashRuntime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.flashExec( 'Blob', 'slice', start, end );\n    \n                return new Blob( blob.uid, blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Md5 flash实现\n     */\n    define('runtime/flash/md5',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n        \n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n    \n            loadFromBlob: function( blob ) {\n                return this.flashExec( 'Md5', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview 完全版本。\n     */\n    define('preset/all',[\n        'base',\n    \n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n        'widgets/md5',\n    \n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/imagemeta/exif',\n        'runtime/html5/androidpatch',\n        'runtime/html5/image',\n        'runtime/html5/transport',\n        'runtime/html5/md5',\n    \n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/image',\n        'runtime/flash/transport',\n        'runtime/flash/blob',\n        'runtime/flash/md5'\n    ], function( Base ) {\n        return Base;\n    });\n    /**\n     * @fileOverview 日志组件，主要用来收集错误信息，可以帮助 webuploader 更好的定位问题和发展。\n     *\n     * 如果您不想要启用此功能，请在打包的时候去掉 log 模块。\n     *\n     * 或者可以在初始化的时候通过 options.disableWidgets 属性禁用。\n     *\n     * 如：\n     * WebUploader.create({\n     *     ...\n     *\n     *     disableWidgets: 'log',\n     *\n     *     ...\n     * })\n     */\n    define('widgets/log',[\n        'base',\n        'uploader',\n        'widgets/widget'\n    ], function( Base, Uploader ) {\n        var $ = Base.$,\n            logUrl = ' http://static.tieba.baidu.com/tb/pms/img/st.gif??',\n            product = (location.hostname || location.host || 'protected').toLowerCase(),\n    \n            // 只针对 baidu 内部产品用户做统计功能。\n            enable = product && /baidu/i.exec(product),\n            base;\n    \n        if (!enable) {\n            return;\n        }\n    \n        base = {\n            dv: 3,\n            master: 'webuploader',\n            online: /test/.exec(product) ? 0 : 1,\n            module: '',\n            product: product,\n            type: 0\n        };\n    \n        function send(data) {\n            var obj = $.extend({}, base, data),\n                url = logUrl.replace(/^(.*)\\?/, '$1' + $.param( obj )),\n                image = new Image();\n    \n            image.src = url;\n        }\n    \n        return Uploader.register({\n            name: 'log',\n    \n            init: function() {\n                var owner = this.owner,\n                    count = 0,\n                    size = 0;\n    \n                owner\n                    .on('error', function(code) {\n                        send({\n                            type: 2,\n                            c_error_code: code\n                        });\n                    })\n                    .on('uploadError', function(file, reason) {\n                        send({\n                            type: 2,\n                            c_error_code: 'UPLOAD_ERROR',\n                            c_reason: '' + reason\n                        });\n                    })\n                    .on('uploadComplete', function(file) {\n                        count++;\n                        size += file.size;\n                    }).\n                    on('uploadFinished', function() {\n                        send({\n                            c_count: count,\n                            c_size: size\n                        });\n                        count = size = 0;\n                    });\n    \n                send({\n                    c_usage: 1\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('webuploader',[\n        'preset/all',\n        'widgets/log'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/webuploader.noimage.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n    \n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n    \n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n    \n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n    \n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n    \n        var noop = function() {},\n            call = Function.call;\n    \n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n    \n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n    \n        function createObject( proto ) {\n            var f;\n    \n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n    \n    \n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n    \n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n    \n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n    \n            Deferred: promise.Deferred,\n    \n            isPromise: promise.isPromise,\n    \n            when: promise.when,\n    \n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n    \n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n    \n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n    \n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n    \n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n    \n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n    \n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n    \n                /* jshint camelcase: false */\n    \n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n    \n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n    \n                return child;\n            },\n    \n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n    \n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n    \n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n    \n            nextTick: (function() {\n    \n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n    \n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n    \n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n    \n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n    \n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n    \n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n    \n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n    \n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n    \n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n    \n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n    \n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n    \n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n    \n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n    \n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n    \n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n    \n            while ( ++i < len ) {\n                handler = events[ i ];\n    \n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n    \n            return !stoped;\n        }\n    \n        protos = {\n    \n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n    \n                if ( !callback ) {\n                    return this;\n                }\n    \n                set = this._events || (this._events = []);\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n    \n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n    \n                    set.push( handler );\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n    \n                if ( !callback ) {\n                    return me;\n                }\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n    \n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n    \n                return me;\n            },\n    \n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n    \n                if ( !events ) {\n                    return this;\n                }\n    \n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n    \n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n    \n                if ( !this._events || !type ) {\n                    return this;\n                }\n    \n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n    \n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n    \n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n    \n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n    \n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$;\n    \n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n    \n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n    \n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n    \n        $.extend( Uploader.prototype, {\n            state: 'pending',\n    \n            _init: function( opts ) {\n                var me = this;\n    \n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n    \n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n    \n                // setter\n                if ( arguments.length > 1 ) {\n    \n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n    \n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n    \n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n    \n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n    \n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n    \n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n    \n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n    \n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n    \n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n    \n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n    \n                    return false;\n                }\n    \n                return true;\n            },\n    \n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n    \n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n    \n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n    \n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n    \n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            factories = {},\n    \n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n    \n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n    \n        $.extend( Runtime.prototype, {\n    \n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n    \n                if ( this._container ) {\n                    return this._container;\n                }\n    \n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n    \n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n    \n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n    \n            init: Base.noop,\n            exec: Base.noop,\n    \n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n    \n        Runtime.orders = 'html5,flash';\n    \n    \n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n    \n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n    \n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n    \n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n    \n            type = type || getFirstKey( factories );\n    \n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n    \n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n    \n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n    \n        var cache;\n    \n        cache = (function() {\n            var obj = {};\n    \n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n    \n                get: function( ruid, standalone ) {\n                    var i;\n    \n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n    \n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n    \n                        return obj[ i ];\n                    }\n    \n                    return null;\n                },\n    \n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n    \n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n    \n            this.uid = Base.guid('client_');\n    \n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n    \n            this.connectRuntime = function( opts, cb ) {\n    \n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n    \n                deferred.done( cb );\n    \n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n    \n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n    \n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n    \n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                runtime.__client--;\n    \n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n    \n                runtime = null;\n            };\n    \n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n    \n                return runtime.exec.apply( this, args );\n            };\n    \n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n    \n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n    \n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n    \n            opts.container = $( opts.container );\n    \n            if ( !opts.container.length ) {\n                return;\n            }\n    \n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n    \n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( DragAndDrop.prototype );\n    \n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n    \n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n    \n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n    \n            var length = obj.length,\n                type = $.type( obj );\n    \n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n    \n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n    \n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n    \n        $.extend( Widget.prototype, {\n    \n            init: Base.noop,\n    \n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n    \n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n    \n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n    \n                    return IGNORE;\n                }\n    \n                return this[ map[ apiName ] ].apply( this, args );\n    \n            },\n    \n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n    \n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n    \n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n    \n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n    \n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n    \n                return _init.apply( me, arguments );\n            },\n    \n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n    \n                args = isArrayLike( args ) ? args : [ args ];\n    \n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n    \n                    if ( rlt !== IGNORE ) {\n    \n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n    \n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n    \n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n    \n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n    \n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n    \n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n    \n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n    \n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n    \n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n    \n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n    \n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n    \n            } else {\n                map = $.extend( map, responseMap );\n            }\n    \n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n    \n            return klass;\n        };\n    \n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *     \n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n            \n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n    \n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n    \n        Uploader.options.dnd = '';\n    \n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n        \n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n    \n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n            \n            init: function( opts ) {\n    \n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n    \n                this.dnd = dnd = new Dnd( options );\n    \n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n    \n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n    \n                dnd.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( FilePaste.prototype );\n    \n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n    \n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n            \n            init: function( opts ) {\n    \n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n    \n                this.paste = paste = new FilePaste( options );\n    \n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n    \n        function Blob( ruid, source ) {\n            var me = this;\n    \n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n    \n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n    \n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n    \n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n    \n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n    \n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n    \n            getSource: function() {\n                return this.source;\n            }\n        });\n    \n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n    \n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n    \n        function File( ruid, file ) {\n            var ext;\n    \n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n    \n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n    \n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n    \n            Blob.apply( this, arguments );\n        }\n    \n        return Base.inherits( Blob, File );\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n    \n        var $ = Base.$;\n    \n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n    \n            opts.container = $( opts.id );\n    \n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n    \n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n    \n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n    \n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n    \n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n    \n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n    \n                button.addClass('webuploader-pick');\n    \n                me.on( 'all', function( type ) {\n                    var files;\n    \n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n    \n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n    \n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n    \n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n    \n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n    \n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n    \n                    pos = button.offset();\n    \n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n    \n            enable: function() {\n                var btn = this.options.button;\n    \n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n    \n            disable: function() {\n                var btn = this.options.button;\n    \n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n    \n                btn.addClass('webuploader-pick-disable');\n            },\n    \n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n    \n        return FilePicker;\n    });\n    \n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n    \n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n    \n        return Uploader.register({\n            name: 'picker',\n    \n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n    \n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n    \n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n    \n                if ( !pick ) {\n                    return;\n                }\n    \n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n    \n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n    \n                    deferred = Base.Deferred();\n    \n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n    \n                    picker = new FilePicker( options );\n    \n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n    \n                    me.pickers.push( picker );\n    \n                    promises.push( deferred.promise() );\n                });\n    \n                return Base.when.apply( Base, promises );\n            },\n    \n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n    \n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n    \n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n    \n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n    \n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n    \n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n    \n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n    \n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n    \n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n    \n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n    \n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n    \n    \n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n    \n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n    \n            this.source = source;\n            this.loaded = 0;\n    \n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n    \n        $.extend( WUFile.prototype, {\n    \n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n    \n                var prevStatus = statusMap[ this.id ];\n    \n                typeof text !== 'undefined' && (this.statusText = text);\n    \n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n    \n            },\n    \n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n    \n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n    \n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n    \n        Mediator.installTo( WUFile.prototype );\n    \n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n    \n        return WUFile;\n    });\n    \n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n    \n        var $ = Base.$,\n            STATUS = WUFile.Status;\n    \n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n    \n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n    \n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n    \n            // 存储所有文件\n            this._map = {};\n        }\n    \n        $.extend( Queue.prototype, {\n    \n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n    \n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n    \n                status = status || STATUS.QUEUED;\n    \n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n    \n                return null;\n            },\n    \n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n    \n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n    \n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n    \n                    ret.push( file );\n                }\n    \n                return ret;\n            },\n    \n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n    \n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n    \n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n    \n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n    \n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n    \n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n    \n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n    \n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n    \n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n    \n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n    \n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n    \n        });\n    \n        Mediator.installTo( Queue.prototype );\n    \n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n    \n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n    \n        return Uploader.register({\n            name: 'queue',\n    \n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n    \n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n    \n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n    \n                    me.accept = new RegExp( accept, 'i' );\n                }\n    \n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n    \n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n    \n    \n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n    \n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n    \n                    file = new WUFile( file );\n                }\n    \n                return file;\n            },\n    \n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n    \n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n    \n                return !invalid;\n            },\n    \n    \n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n    \n            _addFile: function( file ) {\n                var me = this;\n    \n                file = me._wrapFile( file );\n    \n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n    \n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n    \n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n    \n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n    \n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n            \n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             * \n             */\n    \n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n    \n                if ( !files.length ) {\n                    files = [ files ];\n                }\n    \n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n    \n                me.owner.trigger( 'filesQueued', files );\n    \n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n    \n            getStats: function() {\n                return this.stats;\n            },\n    \n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n    \n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n    \n                file = file.id ? file : me.queue.getFile( file );\n    \n                this.request( 'cancel-file', file );\n    \n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n    \n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n    \n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n    \n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n    \n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n    \n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n    \n                me.request('start-upload');\n            },\n    \n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n    \n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n    \n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n    \n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n    \n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n    \n        return Uploader.register({\n            name: 'runtime',\n    \n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n    \n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n    \n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n    \n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n    \n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n    \n        var $ = Base.$;\n    \n        function Transport( opts ) {\n            var me = this;\n    \n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n    \n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n    \n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n    \n        Transport.options = {\n            server: '',\n            method: 'POST',\n    \n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n    \n        $.extend( Transport.prototype, {\n    \n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n    \n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n    \n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n    \n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n    \n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n    \n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n    \n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n    \n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n    \n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n    \n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n    \n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n    \n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n    \n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n    \n                if ( !duration ) {\n                    return;\n                }\n    \n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n    \n        });\n    \n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n    \n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n    \n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n    \n        // 添加默认配置项\n        $.extend( Uploader.options, {\n    \n    \n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n    \n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n    \n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n    \n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n    \n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n    \n    \n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n    \n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n    \n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n    \n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n    \n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n    \n            api = {\n                file: file,\n    \n                has: function() {\n                    return !!pending.length;\n                },\n    \n                shift: function() {\n                    return pending.shift();\n                },\n    \n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n    \n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n    \n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n    \n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n    \n            return api;\n        }\n    \n        Uploader.register({\n            name: 'upload',\n    \n            init: function() {\n                var owner = this.owner,\n                    me = this;\n    \n                this.runing = false;\n                this.progress = false;\n    \n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n    \n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n    \n                // 缓存分好片的文件。\n                this.stack = [];\n    \n                // 缓存即将上传的文件。\n                this.pending = [];\n    \n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n    \n                owner.on( 'uploadComplete', function( file ) {\n    \n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n    \n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n    \n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n    \n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n    \n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n    \n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n    \n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n    \n                            v.transport && v.transport.send();\n                        });\n    \n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n    \n                if ( me.runing ) {\n                    return;\n                }\n    \n                me.runing = true;\n    \n                var files = [];\n    \n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n    \n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n    \n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n    \n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n    \n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n    \n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n    \n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n    \n                if ( me.runing === false ) {\n                    return;\n                }\n    \n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n    \n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n    \n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n    \n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n    \n                    return Base.nextTick( me.__tick );\n                }\n    \n                me.runing = false;\n    \n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n    \n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n    \n                me.owner.trigger('stopUpload');\n            },\n    \n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n    \n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n    \n            _getStats: function() {\n                return this.request('get-stats');\n            },\n    \n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                this.owner.trigger( 'uploadSkip', file );\n            },\n    \n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n    \n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n    \n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n    \n                    fn = function( val ) {\n                        me._promise = null;\n    \n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n    \n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n    \n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n    \n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n    \n            _putback: function(block) {\n                var idx;\n    \n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n    \n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n    \n            _getStack: function() {\n                var i = 0,\n                    act;\n    \n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n    \n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n    \n                return null;\n            },\n    \n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n    \n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n    \n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n    \n                    return act.shift();\n    \n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n    \n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n    \n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n    \n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n    \n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n    \n                    return done( next );\n                }\n            },\n    \n    \n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n    \n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n    \n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n    \n                        return me._finishFile( file );\n                    });\n    \n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n    \n                    promise.file = file;\n    \n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n    \n                        ~idx && pending.splice( idx, 1, file );\n                    });\n    \n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n    \n                    pending.push( promise );\n                }\n            },\n    \n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n    \n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n    \n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n    \n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n    \n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n    \n                    return;\n                }\n    \n                me.pool.push( block );\n                me.remaning++;\n    \n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n    \n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n    \n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n    \n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n    \n    \n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n    \n    \n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n    \n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n    \n                block.transport = tr;\n    \n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n    \n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n    \n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n    \n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n    \n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n    \n                    return reject;\n                };\n    \n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n    \n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n    \n                        block.retried++;\n                        tr.send();\n    \n                    } else {\n    \n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n    \n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n    \n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n    \n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n    \n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n    \n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n    \n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n    \n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n    \n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n    \n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n    \n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n    \n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n    \n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n    \n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n    \n                if (!file.blocks) {\n                    return;\n                }\n    \n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n    \n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n    \n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n    \n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n    \n        var $ = Base.$,\n            validators = {},\n            api;\n    \n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n    \n        // 暴露给外面的api\n        api = {\n    \n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n    \n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n    \n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n    \n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n    \n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return count >= max ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n    \n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n    \n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n    \n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return invalid ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n    \n            });\n    \n        });\n    \n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n    \n            if ( opts.duplicate ) {\n                return;\n            }\n    \n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n    \n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n    \n                return hash;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n    \n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (mapping[ hash ] = true);\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (delete mapping[ hash ]);\n            });\n    \n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n    \n        return api;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n    \n        function CompBase( owner, runtime ) {\n    \n            this.owner = owner;\n            this.options = owner.options;\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.getRuid = function() {\n                return runtime.uid;\n            };\n    \n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n    \n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var type = 'html5',\n            components = {};\n    \n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n    \n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n    \n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n    \n        });\n    \n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n    \n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n    \n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n    \n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n    \n                blob = slice.call( blob, start, end );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n    \n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n    \n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n    \n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n    \n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n    \n                e = e.originalEvent || e;\n    \n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n    \n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n    \n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n    \n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n    \n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n    \n                return false;\n            },\n    \n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n    \n                return false;\n            },\n    \n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n    \n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n    \n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n    \n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n    \n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n    \n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n    \n                if ( data ) {\n                    return;\n                }\n    \n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n    \n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n    \n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n    \n                items = dataTransfer.items;\n                files = dataTransfer.files;\n    \n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n    \n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n    \n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n    \n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n    \n                Base.when.apply( Base, promises ).done(function() {\n    \n                    if ( !results.length ) {\n                        return;\n                    }\n    \n                    callback( results );\n                });\n            },\n    \n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n    \n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n    \n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n    \n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                var elem = this.elem;\n    \n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n                \n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n    \n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n    \n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n    \n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n    \n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n    \n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n    \n                    allowed.push( new File( ruid, blob ) );\n                }\n    \n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n    \n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var $ = Base.$;\n    \n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n    \n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n    \n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n    \n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n    \n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n    \n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n    \n                    input.attr( 'accept', arr.join(',') );\n                }\n    \n                container.append( input );\n                container.append( label );\n    \n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n    \n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n    \n                    me.files = e.target.files;\n    \n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n    \n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n    \n                    owner.trigger('change');\n                });\n    \n                label.on( 'mouseenter mouseleave', mouseHandler );\n    \n            },\n    \n    \n            getFiles: function() {\n                return this.files;\n            },\n    \n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var noop = Base.noop,\n            $ = Base.$;\n    \n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n    \n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n    \n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n    \n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n    \n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n    \n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n    \n            getResponse: function() {\n                return this._response;\n            },\n    \n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n    \n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n    \n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n    \n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n    \n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n    \n                    return me.trigger( 'progress', percentage );\n                };\n    \n                xhr.onreadystatechange = function() {\n    \n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n    \n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n    \n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n    \n    \n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n    \n            _parseJson: function( str ) {\n                var json;\n    \n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n    \n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n    \n    \n        function getFlashVersion() {\n            var version;\n    \n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n    \n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                clients[ uid ] = client;\n    \n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n    \n                    instance = pool[ uid ];\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n    \n                return me.flashExec.apply( client, arguments );\n            };\n    \n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n    \n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n    \n                // console.log.apply( console, arguments );\n    \n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n    \n                // Base.log( evt, obj );\n            }\n    \n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n    \n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n    \n            this.jsreciver = jsreciver;\n    \n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n    \n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n    \n                return flash.exec( this.uid, comp, fn, args );\n            };\n    \n            // @todo\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n    \n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n    \n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n    \n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n    \n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n    \n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n    \n                container.html( html );\n            },\n    \n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n    \n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n    \n        });\n    \n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n    \n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n    \n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n    \n            return component;\n        };\n    \n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n    \n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n    \n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n    \n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n    \n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n    \n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n    \n                xhr.connectRuntime( blob.ruid );\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n    \n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            getResponse: function() {\n                return this._response || '';\n            },\n    \n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n    \n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n    \n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n    \n                    xhr.off();\n                    me._xhr = null;\n    \n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n    \n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n    \n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n                            \n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n                            \n                        // }\n                    }\n                    \n                    xhr.destroy();\n                    xhr = null;\n    \n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n    \n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/flash/blob',[\n        'runtime/flash/runtime',\n        'lib/blob'\n    ], function( FlashRuntime, Blob ) {\n    \n        return FlashRuntime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.flashExec( 'Blob', 'slice', start, end );\n    \n                return new Blob( blob.uid, blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview 没有图像处理的版本。\n     */\n    define('preset/withoutimage',[\n        'base',\n    \n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n    \n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/transport',\n    \n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/transport',\n        'runtime/flash/blob'\n    ], function( Base ) {\n        return Base;\n    });\n    define('webuploader',[\n        'preset/withoutimage'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/webuploader.nolog.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n    \n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n    \n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n    \n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n    \n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n    \n        var noop = function() {},\n            call = Function.call;\n    \n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n    \n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n    \n        function createObject( proto ) {\n            var f;\n    \n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n    \n    \n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n    \n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n    \n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n    \n            Deferred: promise.Deferred,\n    \n            isPromise: promise.isPromise,\n    \n            when: promise.when,\n    \n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n    \n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n    \n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n    \n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n    \n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n    \n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n    \n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n    \n                /* jshint camelcase: false */\n    \n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n    \n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n    \n                return child;\n            },\n    \n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n    \n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n    \n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n    \n            nextTick: (function() {\n    \n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n    \n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n    \n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n    \n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n    \n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n    \n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n    \n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n    \n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n    \n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n    \n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n    \n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n    \n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n    \n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n    \n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n    \n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n    \n            while ( ++i < len ) {\n                handler = events[ i ];\n    \n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n    \n            return !stoped;\n        }\n    \n        protos = {\n    \n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n    \n                if ( !callback ) {\n                    return this;\n                }\n    \n                set = this._events || (this._events = []);\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n    \n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n    \n                    set.push( handler );\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n    \n                if ( !callback ) {\n                    return me;\n                }\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n    \n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n    \n                return me;\n            },\n    \n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n    \n                if ( !events ) {\n                    return this;\n                }\n    \n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n    \n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n    \n                if ( !this._events || !type ) {\n                    return this;\n                }\n    \n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n    \n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n    \n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n    \n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n    \n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$;\n    \n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n    \n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n    \n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n    \n        $.extend( Uploader.prototype, {\n            state: 'pending',\n    \n            _init: function( opts ) {\n                var me = this;\n    \n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n    \n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n    \n                // setter\n                if ( arguments.length > 1 ) {\n    \n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n    \n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n    \n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n    \n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n    \n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n    \n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n    \n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n    \n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n    \n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n    \n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n    \n                    return false;\n                }\n    \n                return true;\n            },\n    \n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n    \n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n    \n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n    \n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n    \n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            factories = {},\n    \n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n    \n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n    \n        $.extend( Runtime.prototype, {\n    \n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n    \n                if ( this._container ) {\n                    return this._container;\n                }\n    \n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n    \n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n    \n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n    \n            init: Base.noop,\n            exec: Base.noop,\n    \n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n    \n        Runtime.orders = 'html5,flash';\n    \n    \n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n    \n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n    \n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n    \n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n    \n            type = type || getFirstKey( factories );\n    \n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n    \n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n    \n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n    \n        var cache;\n    \n        cache = (function() {\n            var obj = {};\n    \n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n    \n                get: function( ruid, standalone ) {\n                    var i;\n    \n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n    \n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n    \n                        return obj[ i ];\n                    }\n    \n                    return null;\n                },\n    \n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n    \n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n    \n            this.uid = Base.guid('client_');\n    \n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n    \n            this.connectRuntime = function( opts, cb ) {\n    \n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n    \n                deferred.done( cb );\n    \n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n    \n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n    \n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n    \n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                runtime.__client--;\n    \n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n    \n                runtime = null;\n            };\n    \n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n    \n                return runtime.exec.apply( this, args );\n            };\n    \n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n    \n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n    \n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n    \n            opts.container = $( opts.container );\n    \n            if ( !opts.container.length ) {\n                return;\n            }\n    \n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n    \n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( DragAndDrop.prototype );\n    \n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n    \n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n    \n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n    \n            var length = obj.length,\n                type = $.type( obj );\n    \n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n    \n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n    \n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n    \n        $.extend( Widget.prototype, {\n    \n            init: Base.noop,\n    \n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n    \n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n    \n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n    \n                    return IGNORE;\n                }\n    \n                return this[ map[ apiName ] ].apply( this, args );\n    \n            },\n    \n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n    \n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n    \n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n    \n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n    \n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n    \n                return _init.apply( me, arguments );\n            },\n    \n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n    \n                args = isArrayLike( args ) ? args : [ args ];\n    \n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n    \n                    if ( rlt !== IGNORE ) {\n    \n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n    \n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n    \n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n    \n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n    \n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n    \n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n    \n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n    \n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n    \n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n    \n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n    \n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n    \n            } else {\n                map = $.extend( map, responseMap );\n            }\n    \n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n    \n            return klass;\n        };\n    \n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *     \n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n            \n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n    \n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n    \n        Uploader.options.dnd = '';\n    \n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n        \n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n    \n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n            \n            init: function( opts ) {\n    \n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n    \n                this.dnd = dnd = new Dnd( options );\n    \n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n    \n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n    \n                dnd.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( FilePaste.prototype );\n    \n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n    \n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n            \n            init: function( opts ) {\n    \n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n    \n                this.paste = paste = new FilePaste( options );\n    \n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n    \n        function Blob( ruid, source ) {\n            var me = this;\n    \n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n    \n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n    \n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n    \n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n    \n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n    \n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n    \n            getSource: function() {\n                return this.source;\n            }\n        });\n    \n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n    \n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n    \n        function File( ruid, file ) {\n            var ext;\n    \n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n    \n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n    \n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n    \n            Blob.apply( this, arguments );\n        }\n    \n        return Base.inherits( Blob, File );\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n    \n        var $ = Base.$;\n    \n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n    \n            opts.container = $( opts.id );\n    \n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n    \n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n    \n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n    \n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n    \n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n    \n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n    \n                button.addClass('webuploader-pick');\n    \n                me.on( 'all', function( type ) {\n                    var files;\n    \n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n    \n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n    \n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n    \n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n    \n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n    \n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n    \n                    pos = button.offset();\n    \n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n    \n            enable: function() {\n                var btn = this.options.button;\n    \n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n    \n            disable: function() {\n                var btn = this.options.button;\n    \n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n    \n                btn.addClass('webuploader-pick-disable');\n            },\n    \n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n    \n        return FilePicker;\n    });\n    \n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor|dom} 指定选择文件的按钮容器，不指定则不创建按钮。**注意** 这里虽然写的是 id, 但是不是只支持 id, 还支持 class, 或者 dom 节点。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n    \n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n    \n        return Uploader.register({\n            name: 'picker',\n    \n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n    \n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n    \n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n    \n                if ( !pick ) {\n                    return;\n                }\n    \n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n    \n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n    \n                    deferred = Base.Deferred();\n    \n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n    \n                    picker = new FilePicker( options );\n    \n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n    \n                    me.pickers.push( picker );\n    \n                    promises.push( deferred.promise() );\n                });\n    \n                return Base.when.apply( Base, promises );\n            },\n    \n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n    \n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n    \n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('lib/image',[\n        'base',\n        'runtime/client',\n        'lib/blob'\n    ], function( Base, RuntimeClient, Blob ) {\n        var $ = Base.$;\n    \n        // 构造器。\n        function Image( opts ) {\n            this.options = $.extend({}, Image.options, opts );\n            RuntimeClient.call( this, 'Image' );\n    \n            this.on( 'load', function() {\n                this._info = this.exec('info');\n                this._meta = this.exec('meta');\n            });\n        }\n    \n        // 默认选项。\n        Image.options = {\n    \n            // 默认的图片处理质量\n            quality: 90,\n    \n            // 是否裁剪\n            crop: false,\n    \n            // 是否保留头部信息\n            preserveHeaders: false,\n    \n            // 是否允许放大。\n            allowMagnify: false\n        };\n    \n        // 继承RuntimeClient.\n        Base.inherits( RuntimeClient, {\n            constructor: Image,\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    ruid = blob.getRuid();\n    \n                this.connectRuntime( ruid, function() {\n                    me.exec( 'init', me.options );\n                    me.exec( 'loadFromBlob', blob );\n                });\n            },\n    \n            resize: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'resize' ].concat( args ) );\n            },\n    \n            crop: function() {\n                var args = Base.slice( arguments );\n                return this.exec.apply( this, [ 'crop' ].concat( args ) );\n            },\n    \n            getAsDataUrl: function( type ) {\n                return this.exec( 'getAsDataUrl', type );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this.exec( 'getAsBlob', type );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    \n        return Image;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/image',[\n        'base',\n        'uploader',\n        'lib/image',\n        'widgets/widget'\n    ], function( Base, Uploader, Image ) {\n    \n        var $ = Base.$,\n            throttle;\n    \n        // 根据要处理的文件大小来节流，一次不能处理太多，会卡。\n        throttle = (function( max ) {\n            var occupied = 0,\n                waiting = [],\n                tick = function() {\n                    var item;\n    \n                    while ( waiting.length && occupied < max ) {\n                        item = waiting.shift();\n                        occupied += item[ 0 ];\n                        item[ 1 ]();\n                    }\n                };\n    \n            return function( emiter, size, cb ) {\n                waiting.push([ size, cb ]);\n                emiter.once( 'destroy', function() {\n                    occupied -= size;\n                    setTimeout( tick, 1 );\n                });\n                setTimeout( tick, 1 );\n            };\n        })( 5 * 1024 * 1024 );\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Object} [thumb]\n             * @namespace options\n             * @for Uploader\n             * @description 配置生成缩略图的选项。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 110,\n             *     height: 110,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 70,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: true,\n             *\n             *     // 是否允许裁剪。\n             *     crop: true,\n             *\n             *     // 为空的话则保留原有图片格式。\n             *     // 否则强制转换成指定的类型。\n             *     type: 'image/jpeg'\n             * }\n             * ```\n             */\n            thumb: {\n                width: 110,\n                height: 110,\n                quality: 70,\n                allowMagnify: true,\n                crop: true,\n                preserveHeaders: false,\n    \n                // 为空的话则保留原有图片格式。\n                // 否则强制转换成指定的类型。\n                // IE 8下面 base64 大小不能超过 32K 否则预览失败，而非 jpeg 编码的图片很可\n                // 能会超过 32k, 所以这里设置成预览的时候都是 image/jpeg\n                type: 'image/jpeg'\n            },\n    \n            /**\n             * @property {Object} [compress]\n             * @namespace options\n             * @for Uploader\n             * @description 配置压缩的图片的选项。如果此选项为`false`, 则图片在上传前不进行压缩。\n             *\n             * 默认为：\n             *\n             * ```javascript\n             * {\n             *     width: 1600,\n             *     height: 1600,\n             *\n             *     // 图片质量，只有type为`image/jpeg`的时候才有效。\n             *     quality: 90,\n             *\n             *     // 是否允许放大，如果想要生成小图的时候不失真，此选项应该设置为false.\n             *     allowMagnify: false,\n             *\n             *     // 是否允许裁剪。\n             *     crop: false,\n             *\n             *     // 是否保留头部meta信息。\n             *     preserveHeaders: true,\n             *\n             *     // 如果发现压缩后文件大小比原来还大，则使用原来图片\n             *     // 此属性可能会影响图片自动纠正功能\n             *     noCompressIfLarger: false,\n             *\n             *     // 单位字节，如果图片大小小于此值，不会采用压缩。\n             *     compressSize: 0\n             * }\n             * ```\n             */\n            compress: {\n                width: 1600,\n                height: 1600,\n                quality: 90,\n                allowMagnify: false,\n                crop: false,\n                preserveHeaders: true\n            }\n        });\n    \n        return Uploader.register({\n    \n            name: 'image',\n    \n    \n            /**\n             * 生成缩略图，此过程为异步，所以需要传入`callback`。\n             * 通常情况在图片加入队里后调用此方法来生成预览图以增强交互效果。\n             *\n             * 当 width 或者 height 的值介于 0 - 1 时，被当成百分比使用。\n             *\n             * `callback`中可以接收到两个参数。\n             * * 第一个为error，如果生成缩略图有错误，此error将为真。\n             * * 第二个为ret, 缩略图的Data URL值。\n             *\n             * **注意**\n             * Date URL在IE6/7中不支持，所以不用调用此方法了，直接显示一张暂不支持预览图片好了。\n             * 也可以借助服务端，将 base64 数据传给服务端，生成一个临时文件供预览。\n             *\n             * @method makeThumb\n             * @grammar makeThumb( file, callback ) => undefined\n             * @grammar makeThumb( file, callback, width, height ) => undefined\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.makeThumb( file, function( error, ret ) {\n             *         if ( error ) {\n             *             $li.text('预览错误');\n             *         } else {\n             *             $li.append('<img alt=\"\" src=\"' + ret + '\" />');\n             *         }\n             *     });\n             *\n             * });\n             */\n            makeThumb: function( file, cb, width, height ) {\n                var opts, image;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只预览图片格式。\n                if ( !file.type.match( /^image/ ) ) {\n                    cb( true );\n                    return;\n                }\n    \n                opts = $.extend({}, this.options.thumb );\n    \n                // 如果传入的是object.\n                if ( $.isPlainObject( width ) ) {\n                    opts = $.extend( opts, width );\n                    width = null;\n                }\n    \n                width = width || opts.width;\n                height = height || opts.height;\n    \n                image = new Image( opts );\n    \n                image.once( 'load', function() {\n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                // 当 resize 完后\n                image.once( 'complete', function() {\n                    cb( false, image.getAsDataUrl( opts.type ) );\n                    image.destroy();\n                });\n    \n                image.once( 'error', function( reason ) {\n                    cb( reason || true );\n                    image.destroy();\n                });\n    \n                throttle( image, file.source.size, function() {\n                    file._info && image.info( file._info );\n                    file._meta && image.meta( file._meta );\n                    image.loadFromBlob( file.source );\n                });\n            },\n    \n            beforeSendFile: function( file ) {\n                var opts = this.options.compress || this.options.resize,\n                    compressSize = opts && opts.compressSize || 0,\n                    noCompressIfLarger = opts && opts.noCompressIfLarger || false,\n                    image, deferred;\n    \n                file = this.request( 'get-file', file );\n    \n                // 只压缩 jpeg 图片格式。\n                // gif 可能会丢失针\n                // bmp png 基本上尺寸都不大，且压缩比比较小。\n                if ( !opts || !~'image/jpeg,image/jpg'.indexOf( file.type ) ||\n                        file.size < compressSize ||\n                        file._compressed ) {\n                    return;\n                }\n    \n                opts = $.extend({}, opts );\n                deferred = Base.Deferred();\n    \n                image = new Image( opts );\n    \n                deferred.always(function() {\n                    image.destroy();\n                    image = null;\n                });\n                image.once( 'error', deferred.reject );\n                image.once( 'load', function() {\n                    var width = opts.width,\n                        height = opts.height;\n    \n                    file._info = file._info || image.info();\n                    file._meta = file._meta || image.meta();\n    \n                    // 如果 width 的值介于 0 - 1\n                    // 说明设置的是百分比。\n                    if ( width <= 1 && width > 0 ) {\n                        width = file._info.width * width;\n                    }\n    \n                    // 同样的规则应用于 height\n                    if ( height <= 1 && height > 0 ) {\n                        height = file._info.height * height;\n                    }\n    \n                    image.resize( width, height );\n                });\n    \n                image.once( 'complete', function() {\n                    var blob, size;\n    \n                    // 移动端 UC / qq 浏览器的无图模式下\n                    // ctx.getImageData 处理大图的时候会报 Exception\n                    // INDEX_SIZE_ERR: DOM Exception 1\n                    try {\n                        blob = image.getAsBlob( opts.type );\n    \n                        size = file.size;\n    \n                        // 如果压缩后，比原来还大则不用压缩后的。\n                        if ( !noCompressIfLarger || blob.size < size ) {\n                            // file.source.destroy && file.source.destroy();\n                            file.source = blob;\n                            file.size = blob.size;\n    \n                            file.trigger( 'resize', blob.size, size );\n                        }\n    \n                        // 标记，避免重复压缩。\n                        file._compressed = true;\n                        deferred.resolve();\n                    } catch ( e ) {\n                        // 出错了直接继续，让其上传原始图片\n                        deferred.resolve();\n                    }\n                });\n    \n                file._info && image.info( file._info );\n                file._meta && image.meta( file._meta );\n    \n                image.loadFromBlob( file.source );\n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n    \n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n    \n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n    \n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n    \n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n    \n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n    \n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n    \n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n    \n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n    \n    \n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n    \n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n    \n            this.source = source;\n            this.loaded = 0;\n    \n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n    \n        $.extend( WUFile.prototype, {\n    \n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n    \n                var prevStatus = statusMap[ this.id ];\n    \n                typeof text !== 'undefined' && (this.statusText = text);\n    \n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n    \n            },\n    \n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n    \n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n    \n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n    \n        Mediator.installTo( WUFile.prototype );\n    \n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n    \n        return WUFile;\n    });\n    \n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n    \n        var $ = Base.$,\n            STATUS = WUFile.Status;\n    \n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n    \n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0\n            };\n    \n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n    \n            // 存储所有文件\n            this._map = {};\n        }\n    \n        $.extend( Queue.prototype, {\n    \n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n    \n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n    \n                status = status || STATUS.QUEUED;\n    \n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n    \n                return null;\n            },\n    \n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n    \n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n    \n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n    \n                    ret.push( file );\n                }\n    \n                return ret;\n            },\n    \n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n    \n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n    \n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n    \n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n    \n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n    \n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n    \n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n    \n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n    \n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n    \n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n    \n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n    \n        });\n    \n        Mediator.installTo( Queue.prototype );\n    \n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n    \n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n    \n        return Uploader.register({\n            name: 'queue',\n    \n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n    \n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n    \n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n    \n                    me.accept = new RegExp( accept, 'i' );\n                }\n    \n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n    \n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n    \n    \n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n    \n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n    \n                    file = new WUFile( file );\n                }\n    \n                return file;\n            },\n    \n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n    \n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n    \n                return !invalid;\n            },\n    \n    \n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n    \n            _addFile: function( file ) {\n                var me = this;\n    \n                file = me._wrapFile( file );\n    \n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n    \n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n    \n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n    \n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n    \n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n            \n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             * \n             */\n    \n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n    \n                if ( !files.length ) {\n                    files = [ files ];\n                }\n    \n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n    \n                me.owner.trigger( 'filesQueued', files );\n    \n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n    \n            getStats: function() {\n                return this.stats;\n            },\n    \n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n    \n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n    \n                file = file.id ? file : me.queue.getFile( file );\n    \n                this.request( 'cancel-file', file );\n    \n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n    \n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n    \n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n    \n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n    \n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n    \n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n    \n                me.request('start-upload');\n            },\n    \n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n    \n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n    \n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n    \n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n    \n        /**\n         * @property {Object} [runtimeOrder=html5,flash]\n         * @namespace options\n         * @for Uploader\n         * @description 指定运行时启动顺序。默认会想尝试 html5 是否支持，如果支持则使用 html5, 否则则使用 flash.\n         *\n         * 可以将此值设置成 `flash`，来强制使用 flash 运行时。\n         */\n    \n        return Uploader.register({\n            name: 'runtime',\n    \n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n    \n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n    \n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n    \n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n    \n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n    \n        var $ = Base.$;\n    \n        function Transport( opts ) {\n            var me = this;\n    \n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n    \n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n    \n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n    \n        Transport.options = {\n            server: '',\n            method: 'POST',\n    \n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n    \n        $.extend( Transport.prototype, {\n    \n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n    \n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n    \n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n    \n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n    \n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n    \n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n    \n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n    \n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n    \n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n    \n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n    \n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n    \n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n    \n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n    \n                if ( !duration ) {\n                    return;\n                }\n    \n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n    \n        });\n    \n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n    \n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n    \n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n    \n        // 添加默认配置项\n        $.extend( Uploader.options, {\n    \n    \n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n    \n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n    \n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n    \n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n    \n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n    \n    \n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n    \n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n    \n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n    \n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n    \n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n    \n            api = {\n                file: file,\n    \n                has: function() {\n                    return !!pending.length;\n                },\n    \n                shift: function() {\n                    return pending.shift();\n                },\n    \n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n    \n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n    \n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n    \n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n    \n            return api;\n        }\n    \n        Uploader.register({\n            name: 'upload',\n    \n            init: function() {\n                var owner = this.owner,\n                    me = this;\n    \n                this.runing = false;\n                this.progress = false;\n    \n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n    \n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n    \n                // 缓存分好片的文件。\n                this.stack = [];\n    \n                // 缓存即将上传的文件。\n                this.pending = [];\n    \n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n    \n                owner.on( 'uploadComplete', function( file ) {\n    \n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n    \n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n    \n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n    \n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n    \n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n    \n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n    \n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n    \n                            v.transport && v.transport.send();\n                        });\n    \n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n    \n                if ( me.runing ) {\n                    return;\n                }\n    \n                me.runing = true;\n    \n                var files = [];\n    \n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n    \n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        files.push(file);\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n    \n                var file;\n                while ( (file = files.shift()) ) {\n                    file.setStatus( Status.PROGRESS );\n                }\n    \n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n    \n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n    \n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n    \n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n    \n                if ( me.runing === false ) {\n                    return;\n                }\n    \n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n    \n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n    \n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n    \n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n    \n                    return Base.nextTick( me.__tick );\n                }\n    \n                me.runing = false;\n    \n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n    \n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n    \n                me.owner.trigger('stopUpload');\n            },\n    \n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n    \n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n    \n            _getStats: function() {\n                return this.request('get-stats');\n            },\n    \n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                this.owner.trigger( 'uploadSkip', file );\n            },\n    \n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n    \n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n    \n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n    \n                    fn = function( val ) {\n                        me._promise = null;\n    \n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n    \n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n    \n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n    \n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n    \n            _putback: function(block) {\n                var idx;\n    \n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n    \n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n    \n            _getStack: function() {\n                var i = 0,\n                    act;\n    \n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n    \n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n    \n                return null;\n            },\n    \n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n    \n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n    \n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n    \n                    return act.shift();\n    \n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n    \n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n    \n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n    \n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n    \n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n    \n                    return done( next );\n                }\n            },\n    \n    \n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n    \n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n    \n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS ||\n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n    \n                        return me._finishFile( file );\n                    });\n    \n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n    \n                    promise.file = file;\n    \n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n    \n                        ~idx && pending.splice( idx, 1, file );\n                    });\n    \n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n    \n                    pending.push( promise );\n                }\n            },\n    \n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n    \n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n    \n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n    \n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n    \n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n    \n                    return;\n                }\n    \n                me.pool.push( block );\n                me.remaning++;\n    \n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n    \n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n    \n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n    \n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me.updateFileProgress( file );\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n    \n    \n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n    \n    \n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n    \n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n    \n                block.transport = tr;\n    \n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n    \n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    block.percentage = percentage;\n                    me.updateFileProgress( file );\n                });\n    \n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n    \n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n    \n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n    \n                    return reject;\n                };\n    \n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n    \n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n    \n                        block.retried++;\n                        tr.send();\n    \n                    } else {\n    \n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n    \n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n    \n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n    \n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n    \n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n    \n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n    \n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n    \n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n    \n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n    \n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n    \n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n    \n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n    \n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            },\n    \n            updateFileProgress: function(file) {\n                var totalPercent = 0,\n                    uploaded = 0;\n    \n                if (!file.blocks) {\n                    return;\n                }\n    \n                $.each( file.blocks, function( _, v ) {\n                    uploaded += (v.percentage || 0) * (v.end - v.start);\n                });\n    \n                totalPercent = uploaded / file.size;\n                this.owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n            }\n    \n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n    \n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n    \n        var $ = Base.$,\n            validators = {},\n            api;\n    \n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n    \n        // 暴露给外面的api\n        api = {\n    \n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n    \n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n    \n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n    \n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n    \n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return count >= max ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n    \n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n    \n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n    \n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return invalid ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n    \n            });\n    \n        });\n    \n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n    \n            if ( opts.duplicate ) {\n                return;\n            }\n    \n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n    \n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n    \n                return hash;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n    \n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (mapping[ hash ] = true);\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (delete mapping[ hash ]);\n            });\n    \n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n    \n        return api;\n    });\n    \n    /**\n     * @fileOverview Md5\n     */\n    define('lib/md5',[\n        'runtime/client',\n        'mediator'\n    ], function( RuntimeClient, Mediator ) {\n    \n        function Md5() {\n            RuntimeClient.call( this, 'Md5' );\n        }\n    \n        // 让 Md5 具备事件功能。\n        Mediator.installTo( Md5.prototype );\n    \n        Md5.prototype.loadFromBlob = function( blob ) {\n            var me = this;\n    \n            if ( me.getRuid() ) {\n                me.disconnectRuntime();\n            }\n    \n            // 连接到blob归属的同一个runtime.\n            me.connectRuntime( blob.ruid, function() {\n                me.exec('init');\n                me.exec( 'loadFromBlob', blob );\n            });\n        };\n    \n        Md5.prototype.getResult = function() {\n            return this.exec('getResult');\n        };\n    \n        return Md5;\n    });\n    /**\n     * @fileOverview 图片操作, 负责预览图片和上传前压缩图片\n     */\n    define('widgets/md5',[\n        'base',\n        'uploader',\n        'lib/md5',\n        'lib/blob',\n        'widgets/widget'\n    ], function( Base, Uploader, Md5, Blob ) {\n    \n        return Uploader.register({\n            name: 'md5',\n    \n    \n            /**\n             * 计算文件 md5 值，返回一个 promise 对象，可以监听 progress 进度。\n             *\n             *\n             * @method md5File\n             * @grammar md5File( file[, start[, end]] ) => promise\n             * @for Uploader\n             * @example\n             *\n             * uploader.on( 'fileQueued', function( file ) {\n             *     var $li = ...;\n             *\n             *     uploader.md5File( file )\n             *\n             *         // 及时显示进度\n             *         .progress(function(percentage) {\n             *             console.log('Percentage:', percentage);\n             *         })\n             *\n             *         // 完成\n             *         .then(function(val) {\n             *             console.log('md5 result:', val);\n             *         });\n             *\n             * });\n             */\n            md5File: function( file, start, end ) {\n                var md5 = new Md5(),\n                    deferred = Base.Deferred(),\n                    blob = (file instanceof Blob) ? file :\n                        this.request( 'get-file', file ).source;\n    \n                md5.on( 'progress load', function( e ) {\n                    e = e || {};\n                    deferred.notify( e.total ? e.loaded / e.total : 1 );\n                });\n    \n                md5.on( 'complete', function() {\n                    deferred.resolve( md5.getResult() );\n                });\n    \n                md5.on( 'error', function( reason ) {\n                    deferred.reject( reason );\n                });\n    \n                if ( arguments.length > 1 ) {\n                    start = start || 0;\n                    end = end || 0;\n                    start < 0 && (start = blob.size + start);\n                    end < 0 && (end = blob.size + end);\n                    end = Math.min( end, blob.size );\n                    blob = blob.slice( start, end );\n                }\n    \n                md5.loadFromBlob( blob );\n    \n                return deferred.promise();\n            }\n        });\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n    \n        function CompBase( owner, runtime ) {\n    \n            this.owner = owner;\n            this.options = owner.options;\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.getRuid = function() {\n                return runtime.uid;\n            };\n    \n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n    \n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var type = 'html5',\n            components = {};\n    \n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n    \n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n    \n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n    \n        });\n    \n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n    \n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n    \n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n    \n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n    \n                blob = slice.call( blob, start, end );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n    \n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n    \n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n    \n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n    \n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n    \n                e = e.originalEvent || e;\n    \n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n    \n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n    \n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n    \n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n    \n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n    \n                return false;\n            },\n    \n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n    \n                return false;\n            },\n    \n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n    \n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n    \n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n    \n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n    \n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n    \n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n    \n                if ( data ) {\n                    return;\n                }\n    \n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n    \n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n    \n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n    \n                items = dataTransfer.items;\n                files = dataTransfer.files;\n    \n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n    \n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n    \n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n    \n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n    \n                Base.when.apply( Base, promises ).done(function() {\n    \n                    if ( !results.length ) {\n                        return;\n                    }\n    \n                    callback( results );\n                });\n            },\n    \n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n    \n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n    \n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n    \n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                var elem = this.elem;\n    \n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n                \n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n    \n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n    \n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n    \n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n    \n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n    \n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n    \n                    allowed.push( new File( ruid, blob ) );\n                }\n    \n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n    \n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var $ = Base.$;\n    \n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n    \n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n    \n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n    \n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n    \n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n    \n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n    \n                    input.attr( 'accept', arr.join(',') );\n                }\n    \n                container.append( input );\n                container.append( label );\n    \n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n    \n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n    \n                    me.files = e.target.files;\n    \n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n    \n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n    \n                    owner.trigger('change');\n                });\n    \n                label.on( 'mouseenter mouseleave', mouseHandler );\n    \n            },\n    \n    \n            getFiles: function() {\n                return this.files;\n            },\n    \n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/util',[\n        'base'\n    ], function( Base ) {\n    \n        var urlAPI = window.createObjectURL && window ||\n                window.URL && URL.revokeObjectURL && URL ||\n                window.webkitURL,\n            createObjectURL = Base.noop,\n            revokeObjectURL = createObjectURL;\n    \n        if ( urlAPI ) {\n    \n            // 更安全的方式调用，比如android里面就能把context改成其他的对象。\n            createObjectURL = function() {\n                return urlAPI.createObjectURL.apply( urlAPI, arguments );\n            };\n    \n            revokeObjectURL = function() {\n                return urlAPI.revokeObjectURL.apply( urlAPI, arguments );\n            };\n        }\n    \n        return {\n            createObjectURL: createObjectURL,\n            revokeObjectURL: revokeObjectURL,\n    \n            dataURL2Blob: function( dataURI ) {\n                var byteStr, intArray, ab, i, mimetype, parts;\n    \n                parts = dataURI.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                ab = new ArrayBuffer( byteStr.length );\n                intArray = new Uint8Array( ab );\n    \n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n    \n                mimetype = parts[ 0 ].split(':')[ 1 ].split(';')[ 0 ];\n    \n                return this.arrayBufferToBlob( ab, mimetype );\n            },\n    \n            dataURL2ArrayBuffer: function( dataURI ) {\n                var byteStr, intArray, i, parts;\n    \n                parts = dataURI.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    byteStr = atob( parts[ 1 ] );\n                } else {\n                    byteStr = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                intArray = new Uint8Array( byteStr.length );\n    \n                for ( i = 0; i < byteStr.length; i++ ) {\n                    intArray[ i ] = byteStr.charCodeAt( i );\n                }\n    \n                return intArray.buffer;\n            },\n    \n            arrayBufferToBlob: function( buffer, type ) {\n                var builder = window.BlobBuilder || window.WebKitBlobBuilder,\n                    bb;\n    \n                // android不支持直接new Blob, 只能借助blobbuilder.\n                if ( builder ) {\n                    bb = new builder();\n                    bb.append( buffer );\n                    return bb.getBlob( type );\n                }\n    \n                return new Blob([ buffer ], type ? { type: type } : {} );\n            },\n    \n            // 抽出来主要是为了解决android下面canvas.toDataUrl不支持jpeg.\n            // 你得到的结果是png.\n            canvasToDataUrl: function( canvas, type, quality ) {\n                return canvas.toDataURL( type, quality / 100 );\n            },\n    \n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            parseMeta: function( blob, callback ) {\n                callback( false, {});\n            },\n    \n            // imagemeat会复写这个方法，如果用户选择加载那个文件了的话。\n            updateImageHead: function( data ) {\n                return data;\n            }\n        };\n    });\n    /**\n     * Terms:\n     *\n     * Uint8Array, FileReader, BlobBuilder, atob, ArrayBuffer\n     * @fileOverview Image控件\n     */\n    define('runtime/html5/imagemeta',[\n        'runtime/html5/util'\n    ], function( Util ) {\n    \n        var api;\n    \n        api = {\n            parsers: {\n                0xffe1: []\n            },\n    \n            maxMetaDataSize: 262144,\n    \n            parse: function( blob, cb ) {\n                var me = this,\n                    fr = new FileReader();\n    \n                fr.onload = function() {\n                    cb( false, me._parse( this.result ) );\n                    fr = fr.onload = fr.onerror = null;\n                };\n    \n                fr.onerror = function( e ) {\n                    cb( e.message );\n                    fr = fr.onload = fr.onerror = null;\n                };\n    \n                blob = blob.slice( 0, me.maxMetaDataSize );\n                fr.readAsArrayBuffer( blob.getSource() );\n            },\n    \n            _parse: function( buffer, noParse ) {\n                if ( buffer.byteLength < 6 ) {\n                    return;\n                }\n    \n                var dataview = new DataView( buffer ),\n                    offset = 2,\n                    maxOffset = dataview.byteLength - 4,\n                    headLength = offset,\n                    ret = {},\n                    markerBytes, markerLength, parsers, i;\n    \n                if ( dataview.getUint16( 0 ) === 0xffd8 ) {\n    \n                    while ( offset < maxOffset ) {\n                        markerBytes = dataview.getUint16( offset );\n    \n                        if ( markerBytes >= 0xffe0 && markerBytes <= 0xffef ||\n                                markerBytes === 0xfffe ) {\n    \n                            markerLength = dataview.getUint16( offset + 2 ) + 2;\n    \n                            if ( offset + markerLength > dataview.byteLength ) {\n                                break;\n                            }\n    \n                            parsers = api.parsers[ markerBytes ];\n    \n                            if ( !noParse && parsers ) {\n                                for ( i = 0; i < parsers.length; i += 1 ) {\n                                    parsers[ i ].call( api, dataview, offset,\n                                            markerLength, ret );\n                                }\n                            }\n    \n                            offset += markerLength;\n                            headLength = offset;\n                        } else {\n                            break;\n                        }\n                    }\n    \n                    if ( headLength > 6 ) {\n                        if ( buffer.slice ) {\n                            ret.imageHead = buffer.slice( 2, headLength );\n                        } else {\n                            // Workaround for IE10, which does not yet\n                            // support ArrayBuffer.slice:\n                            ret.imageHead = new Uint8Array( buffer )\n                                    .subarray( 2, headLength );\n                        }\n                    }\n                }\n    \n                return ret;\n            },\n    \n            updateImageHead: function( buffer, head ) {\n                var data = this._parse( buffer, true ),\n                    buf1, buf2, bodyoffset;\n    \n    \n                bodyoffset = 2;\n                if ( data.imageHead ) {\n                    bodyoffset = 2 + data.imageHead.byteLength;\n                }\n    \n                if ( buffer.slice ) {\n                    buf2 = buffer.slice( bodyoffset );\n                } else {\n                    buf2 = new Uint8Array( buffer ).subarray( bodyoffset );\n                }\n    \n                buf1 = new Uint8Array( head.byteLength + 2 + buf2.byteLength );\n    \n                buf1[ 0 ] = 0xFF;\n                buf1[ 1 ] = 0xD8;\n                buf1.set( new Uint8Array( head ), 2 );\n                buf1.set( new Uint8Array( buf2 ), head.byteLength + 2 );\n    \n                return buf1.buffer;\n            }\n        };\n    \n        Util.parseMeta = function() {\n            return api.parse.apply( api, arguments );\n        };\n    \n        Util.updateImageHead = function() {\n            return api.updateImageHead.apply( api, arguments );\n        };\n    \n        return api;\n    });\n    /**\n     * 代码来自于：https://github.com/blueimp/JavaScript-Load-Image\n     * 暂时项目中只用了orientation.\n     *\n     * 去除了 Exif Sub IFD Pointer, GPS Info IFD Pointer, Exif Thumbnail.\n     * @fileOverview EXIF解析\n     */\n    \n    // Sample\n    // ====================================\n    // Make : Apple\n    // Model : iPhone 4S\n    // Orientation : 1\n    // XResolution : 72 [72/1]\n    // YResolution : 72 [72/1]\n    // ResolutionUnit : 2\n    // Software : QuickTime 7.7.1\n    // DateTime : 2013:09:01 22:53:55\n    // ExifIFDPointer : 190\n    // ExposureTime : 0.058823529411764705 [1/17]\n    // FNumber : 2.4 [12/5]\n    // ExposureProgram : Normal program\n    // ISOSpeedRatings : 800\n    // ExifVersion : 0220\n    // DateTimeOriginal : 2013:09:01 22:52:51\n    // DateTimeDigitized : 2013:09:01 22:52:51\n    // ComponentsConfiguration : YCbCr\n    // ShutterSpeedValue : 4.058893515764426\n    // ApertureValue : 2.5260688216892597 [4845/1918]\n    // BrightnessValue : -0.3126686601998395\n    // MeteringMode : Pattern\n    // Flash : Flash did not fire, compulsory flash mode\n    // FocalLength : 4.28 [107/25]\n    // SubjectArea : [4 values]\n    // FlashpixVersion : 0100\n    // ColorSpace : 1\n    // PixelXDimension : 2448\n    // PixelYDimension : 3264\n    // SensingMethod : One-chip color area sensor\n    // ExposureMode : 0\n    // WhiteBalance : Auto white balance\n    // FocalLengthIn35mmFilm : 35\n    // SceneCaptureType : Standard\n    define('runtime/html5/imagemeta/exif',[\n        'base',\n        'runtime/html5/imagemeta'\n    ], function( Base, ImageMeta ) {\n    \n        var EXIF = {};\n    \n        EXIF.ExifMap = function() {\n            return this;\n        };\n    \n        EXIF.ExifMap.prototype.map = {\n            'Orientation': 0x0112\n        };\n    \n        EXIF.ExifMap.prototype.get = function( id ) {\n            return this[ id ] || this[ this.map[ id ] ];\n        };\n    \n        EXIF.exifTagTypes = {\n            // byte, 8-bit unsigned int:\n            1: {\n                getValue: function( dataView, dataOffset ) {\n                    return dataView.getUint8( dataOffset );\n                },\n                size: 1\n            },\n    \n            // ascii, 8-bit byte:\n            2: {\n                getValue: function( dataView, dataOffset ) {\n                    return String.fromCharCode( dataView.getUint8( dataOffset ) );\n                },\n                size: 1,\n                ascii: true\n            },\n    \n            // short, 16 bit int:\n            3: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint16( dataOffset, littleEndian );\n                },\n                size: 2\n            },\n    \n            // long, 32 bit int:\n            4: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n    \n            // rational = two long values,\n            // first is numerator, second is denominator:\n            5: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getUint32( dataOffset, littleEndian ) /\n                        dataView.getUint32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            },\n    \n            // slong, 32 bit signed int:\n            9: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian );\n                },\n                size: 4\n            },\n    \n            // srational, two slongs, first is numerator, second is denominator:\n            10: {\n                getValue: function( dataView, dataOffset, littleEndian ) {\n                    return dataView.getInt32( dataOffset, littleEndian ) /\n                        dataView.getInt32( dataOffset + 4, littleEndian );\n                },\n                size: 8\n            }\n        };\n    \n        // undefined, 8-bit byte, value depending on field:\n        EXIF.exifTagTypes[ 7 ] = EXIF.exifTagTypes[ 1 ];\n    \n        EXIF.getExifValue = function( dataView, tiffOffset, offset, type, length,\n                littleEndian ) {\n    \n            var tagType = EXIF.exifTagTypes[ type ],\n                tagSize, dataOffset, values, i, str, c;\n    \n            if ( !tagType ) {\n                Base.log('Invalid Exif data: Invalid tag type.');\n                return;\n            }\n    \n            tagSize = tagType.size * length;\n    \n            // Determine if the value is contained in the dataOffset bytes,\n            // or if the value at the dataOffset is a pointer to the actual data:\n            dataOffset = tagSize > 4 ? tiffOffset + dataView.getUint32( offset + 8,\n                    littleEndian ) : (offset + 8);\n    \n            if ( dataOffset + tagSize > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid data offset.');\n                return;\n            }\n    \n            if ( length === 1 ) {\n                return tagType.getValue( dataView, dataOffset, littleEndian );\n            }\n    \n            values = [];\n    \n            for ( i = 0; i < length; i += 1 ) {\n                values[ i ] = tagType.getValue( dataView,\n                        dataOffset + i * tagType.size, littleEndian );\n            }\n    \n            if ( tagType.ascii ) {\n                str = '';\n    \n                // Concatenate the chars:\n                for ( i = 0; i < values.length; i += 1 ) {\n                    c = values[ i ];\n    \n                    // Ignore the terminating NULL byte(s):\n                    if ( c === '\\u0000' ) {\n                        break;\n                    }\n                    str += c;\n                }\n    \n                return str;\n            }\n            return values;\n        };\n    \n        EXIF.parseExifTag = function( dataView, tiffOffset, offset, littleEndian,\n                data ) {\n    \n            var tag = dataView.getUint16( offset, littleEndian );\n            data.exif[ tag ] = EXIF.getExifValue( dataView, tiffOffset, offset,\n                    dataView.getUint16( offset + 2, littleEndian ),    // tag type\n                    dataView.getUint32( offset + 4, littleEndian ),    // tag length\n                    littleEndian );\n        };\n    \n        EXIF.parseExifTags = function( dataView, tiffOffset, dirOffset,\n                littleEndian, data ) {\n    \n            var tagsNumber, dirEndOffset, i;\n    \n            if ( dirOffset + 6 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory offset.');\n                return;\n            }\n    \n            tagsNumber = dataView.getUint16( dirOffset, littleEndian );\n            dirEndOffset = dirOffset + 2 + 12 * tagsNumber;\n    \n            if ( dirEndOffset + 4 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid directory size.');\n                return;\n            }\n    \n            for ( i = 0; i < tagsNumber; i += 1 ) {\n                this.parseExifTag( dataView, tiffOffset,\n                        dirOffset + 2 + 12 * i,    // tag offset\n                        littleEndian, data );\n            }\n    \n            // Return the offset to the next directory:\n            return dataView.getUint32( dirEndOffset, littleEndian );\n        };\n    \n        // EXIF.getExifThumbnail = function(dataView, offset, length) {\n        //     var hexData,\n        //         i,\n        //         b;\n        //     if (!length || offset + length > dataView.byteLength) {\n        //         Base.log('Invalid Exif data: Invalid thumbnail data.');\n        //         return;\n        //     }\n        //     hexData = [];\n        //     for (i = 0; i < length; i += 1) {\n        //         b = dataView.getUint8(offset + i);\n        //         hexData.push((b < 16 ? '0' : '') + b.toString(16));\n        //     }\n        //     return 'data:image/jpeg,%' + hexData.join('%');\n        // };\n    \n        EXIF.parseExifData = function( dataView, offset, length, data ) {\n    \n            var tiffOffset = offset + 10,\n                littleEndian, dirOffset;\n    \n            // Check for the ASCII code for \"Exif\" (0x45786966):\n            if ( dataView.getUint32( offset + 4 ) !== 0x45786966 ) {\n                // No Exif data, might be XMP data instead\n                return;\n            }\n            if ( tiffOffset + 8 > dataView.byteLength ) {\n                Base.log('Invalid Exif data: Invalid segment size.');\n                return;\n            }\n    \n            // Check for the two null bytes:\n            if ( dataView.getUint16( offset + 8 ) !== 0x0000 ) {\n                Base.log('Invalid Exif data: Missing byte alignment offset.');\n                return;\n            }\n    \n            // Check the byte alignment:\n            switch ( dataView.getUint16( tiffOffset ) ) {\n                case 0x4949:\n                    littleEndian = true;\n                    break;\n    \n                case 0x4D4D:\n                    littleEndian = false;\n                    break;\n    \n                default:\n                    Base.log('Invalid Exif data: Invalid byte alignment marker.');\n                    return;\n            }\n    \n            // Check for the TIFF tag marker (0x002A):\n            if ( dataView.getUint16( tiffOffset + 2, littleEndian ) !== 0x002A ) {\n                Base.log('Invalid Exif data: Missing TIFF marker.');\n                return;\n            }\n    \n            // Retrieve the directory offset bytes, usually 0x00000008 or 8 decimal:\n            dirOffset = dataView.getUint32( tiffOffset + 4, littleEndian );\n            // Create the exif object to store the tags:\n            data.exif = new EXIF.ExifMap();\n            // Parse the tags of the main image directory and retrieve the\n            // offset to the next directory, usually the thumbnail directory:\n            dirOffset = EXIF.parseExifTags( dataView, tiffOffset,\n                    tiffOffset + dirOffset, littleEndian, data );\n    \n            // 尝试读取缩略图\n            // if ( dirOffset ) {\n            //     thumbnailData = {exif: {}};\n            //     dirOffset = EXIF.parseExifTags(\n            //         dataView,\n            //         tiffOffset,\n            //         tiffOffset + dirOffset,\n            //         littleEndian,\n            //         thumbnailData\n            //     );\n    \n            //     // Check for JPEG Thumbnail offset:\n            //     if (thumbnailData.exif[0x0201]) {\n            //         data.exif.Thumbnail = EXIF.getExifThumbnail(\n            //             dataView,\n            //             tiffOffset + thumbnailData.exif[0x0201],\n            //             thumbnailData.exif[0x0202] // Thumbnail data length\n            //         );\n            //     }\n            // }\n        };\n    \n        ImageMeta.parsers[ 0xffe1 ].push( EXIF.parseExifData );\n        return EXIF;\n    });\n    /**\n     * 这个方式性能不行，但是可以解决android里面的toDataUrl的bug\n     * android里面toDataUrl('image/jpege')得到的结果却是png.\n     *\n     * 所以这里没辙，只能借助这个工具\n     * @fileOverview jpeg encoder\n     */\n    define('runtime/html5/jpegencoder',[], function( require, exports, module ) {\n    \n        /*\n          Copyright (c) 2008, Adobe Systems Incorporated\n          All rights reserved.\n    \n          Redistribution and use in source and binary forms, with or without\n          modification, are permitted provided that the following conditions are\n          met:\n    \n          * Redistributions of source code must retain the above copyright notice,\n            this list of conditions and the following disclaimer.\n    \n          * Redistributions in binary form must reproduce the above copyright\n            notice, this list of conditions and the following disclaimer in the\n            documentation and/or other materials provided with the distribution.\n    \n          * Neither the name of Adobe Systems Incorporated nor the names of its\n            contributors may be used to endorse or promote products derived from\n            this software without specific prior written permission.\n    \n          THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS\n          IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\n          THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\n          PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n          CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n          EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n          PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n          PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n          LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n          NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n          SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n        */\n        /*\n        JPEG encoder ported to JavaScript and optimized by Andreas Ritter, www.bytestrom.eu, 11/2009\n    \n        Basic GUI blocking jpeg encoder\n        */\n    \n        function JPEGEncoder(quality) {\n          var self = this;\n            var fround = Math.round;\n            var ffloor = Math.floor;\n            var YTable = new Array(64);\n            var UVTable = new Array(64);\n            var fdtbl_Y = new Array(64);\n            var fdtbl_UV = new Array(64);\n            var YDC_HT;\n            var UVDC_HT;\n            var YAC_HT;\n            var UVAC_HT;\n    \n            var bitcode = new Array(65535);\n            var category = new Array(65535);\n            var outputfDCTQuant = new Array(64);\n            var DU = new Array(64);\n            var byteout = [];\n            var bytenew = 0;\n            var bytepos = 7;\n    \n            var YDU = new Array(64);\n            var UDU = new Array(64);\n            var VDU = new Array(64);\n            var clt = new Array(256);\n            var RGB_YUV_TABLE = new Array(2048);\n            var currentQuality;\n    \n            var ZigZag = [\n                     0, 1, 5, 6,14,15,27,28,\n                     2, 4, 7,13,16,26,29,42,\n                     3, 8,12,17,25,30,41,43,\n                     9,11,18,24,31,40,44,53,\n                    10,19,23,32,39,45,52,54,\n                    20,22,33,38,46,51,55,60,\n                    21,34,37,47,50,56,59,61,\n                    35,36,48,49,57,58,62,63\n                ];\n    \n            var std_dc_luminance_nrcodes = [0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0];\n            var std_dc_luminance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_luminance_nrcodes = [0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d];\n            var std_ac_luminance_values = [\n                    0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,\n                    0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,\n                    0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,\n                    0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,\n                    0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,\n                    0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,\n                    0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,\n                    0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,\n                    0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,\n                    0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,\n                    0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,\n                    0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,\n                    0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,\n                    0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,\n                    0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,\n                    0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,\n                    0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,\n                    0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,\n                    0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,\n                    0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n    \n            var std_dc_chrominance_nrcodes = [0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0];\n            var std_dc_chrominance_values = [0,1,2,3,4,5,6,7,8,9,10,11];\n            var std_ac_chrominance_nrcodes = [0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77];\n            var std_ac_chrominance_values = [\n                    0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,\n                    0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,\n                    0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,\n                    0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,\n                    0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,\n                    0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,\n                    0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,\n                    0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,\n                    0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,\n                    0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,\n                    0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,\n                    0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,\n                    0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,\n                    0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,\n                    0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,\n                    0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,\n                    0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,\n                    0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,\n                    0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,\n                    0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,\n                    0xf9,0xfa\n                ];\n    \n            function initQuantTables(sf){\n                    var YQT = [\n                        16, 11, 10, 16, 24, 40, 51, 61,\n                        12, 12, 14, 19, 26, 58, 60, 55,\n                        14, 13, 16, 24, 40, 57, 69, 56,\n                        14, 17, 22, 29, 51, 87, 80, 62,\n                        18, 22, 37, 56, 68,109,103, 77,\n                        24, 35, 55, 64, 81,104,113, 92,\n                        49, 64, 78, 87,103,121,120,101,\n                        72, 92, 95, 98,112,100,103, 99\n                    ];\n    \n                    for (var i = 0; i < 64; i++) {\n                        var t = ffloor((YQT[i]*sf+50)/100);\n                        if (t < 1) {\n                            t = 1;\n                        } else if (t > 255) {\n                            t = 255;\n                        }\n                        YTable[ZigZag[i]] = t;\n                    }\n                    var UVQT = [\n                        17, 18, 24, 47, 99, 99, 99, 99,\n                        18, 21, 26, 66, 99, 99, 99, 99,\n                        24, 26, 56, 99, 99, 99, 99, 99,\n                        47, 66, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99,\n                        99, 99, 99, 99, 99, 99, 99, 99\n                    ];\n                    for (var j = 0; j < 64; j++) {\n                        var u = ffloor((UVQT[j]*sf+50)/100);\n                        if (u < 1) {\n                            u = 1;\n                        } else if (u > 255) {\n                            u = 255;\n                        }\n                        UVTable[ZigZag[j]] = u;\n                    }\n                    var aasf = [\n                        1.0, 1.387039845, 1.306562965, 1.175875602,\n                        1.0, 0.785694958, 0.541196100, 0.275899379\n                    ];\n                    var k = 0;\n                    for (var row = 0; row < 8; row++)\n                    {\n                        for (var col = 0; col < 8; col++)\n                        {\n                            fdtbl_Y[k]  = (1.0 / (YTable [ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            fdtbl_UV[k] = (1.0 / (UVTable[ZigZag[k]] * aasf[row] * aasf[col] * 8.0));\n                            k++;\n                        }\n                    }\n                }\n    \n                function computeHuffmanTbl(nrcodes, std_table){\n                    var codevalue = 0;\n                    var pos_in_table = 0;\n                    var HT = new Array();\n                    for (var k = 1; k <= 16; k++) {\n                        for (var j = 1; j <= nrcodes[k]; j++) {\n                            HT[std_table[pos_in_table]] = [];\n                            HT[std_table[pos_in_table]][0] = codevalue;\n                            HT[std_table[pos_in_table]][1] = k;\n                            pos_in_table++;\n                            codevalue++;\n                        }\n                        codevalue*=2;\n                    }\n                    return HT;\n                }\n    \n                function initHuffmanTbl()\n                {\n                    YDC_HT = computeHuffmanTbl(std_dc_luminance_nrcodes,std_dc_luminance_values);\n                    UVDC_HT = computeHuffmanTbl(std_dc_chrominance_nrcodes,std_dc_chrominance_values);\n                    YAC_HT = computeHuffmanTbl(std_ac_luminance_nrcodes,std_ac_luminance_values);\n                    UVAC_HT = computeHuffmanTbl(std_ac_chrominance_nrcodes,std_ac_chrominance_values);\n                }\n    \n                function initCategoryNumber()\n                {\n                    var nrlower = 1;\n                    var nrupper = 2;\n                    for (var cat = 1; cat <= 15; cat++) {\n                        //Positive numbers\n                        for (var nr = nrlower; nr<nrupper; nr++) {\n                            category[32767+nr] = cat;\n                            bitcode[32767+nr] = [];\n                            bitcode[32767+nr][1] = cat;\n                            bitcode[32767+nr][0] = nr;\n                        }\n                        //Negative numbers\n                        for (var nrneg =-(nrupper-1); nrneg<=-nrlower; nrneg++) {\n                            category[32767+nrneg] = cat;\n                            bitcode[32767+nrneg] = [];\n                            bitcode[32767+nrneg][1] = cat;\n                            bitcode[32767+nrneg][0] = nrupper-1+nrneg;\n                        }\n                        nrlower <<= 1;\n                        nrupper <<= 1;\n                    }\n                }\n    \n                function initRGBYUVTable() {\n                    for(var i = 0; i < 256;i++) {\n                        RGB_YUV_TABLE[i]            =  19595 * i;\n                        RGB_YUV_TABLE[(i+ 256)>>0]  =  38470 * i;\n                        RGB_YUV_TABLE[(i+ 512)>>0]  =   7471 * i + 0x8000;\n                        RGB_YUV_TABLE[(i+ 768)>>0]  = -11059 * i;\n                        RGB_YUV_TABLE[(i+1024)>>0]  = -21709 * i;\n                        RGB_YUV_TABLE[(i+1280)>>0]  =  32768 * i + 0x807FFF;\n                        RGB_YUV_TABLE[(i+1536)>>0]  = -27439 * i;\n                        RGB_YUV_TABLE[(i+1792)>>0]  = - 5329 * i;\n                    }\n                }\n    \n                // IO functions\n                function writeBits(bs)\n                {\n                    var value = bs[0];\n                    var posval = bs[1]-1;\n                    while ( posval >= 0 ) {\n                        if (value & (1 << posval) ) {\n                            bytenew |= (1 << bytepos);\n                        }\n                        posval--;\n                        bytepos--;\n                        if (bytepos < 0) {\n                            if (bytenew == 0xFF) {\n                                writeByte(0xFF);\n                                writeByte(0);\n                            }\n                            else {\n                                writeByte(bytenew);\n                            }\n                            bytepos=7;\n                            bytenew=0;\n                        }\n                    }\n                }\n    \n                function writeByte(value)\n                {\n                    byteout.push(clt[value]); // write char directly instead of converting later\n                }\n    \n                function writeWord(value)\n                {\n                    writeByte((value>>8)&0xFF);\n                    writeByte((value   )&0xFF);\n                }\n    \n                // DCT & quantization core\n                function fDCTQuant(data, fdtbl)\n                {\n                    var d0, d1, d2, d3, d4, d5, d6, d7;\n                    /* Pass 1: process rows. */\n                    var dataOff=0;\n                    var i;\n                    var I8 = 8;\n                    var I64 = 64;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff+1];\n                        d2 = data[dataOff+2];\n                        d3 = data[dataOff+3];\n                        d4 = data[dataOff+4];\n                        d5 = data[dataOff+5];\n                        d6 = data[dataOff+6];\n                        d7 = data[dataOff+7];\n    \n                        var tmp0 = d0 + d7;\n                        var tmp7 = d0 - d7;\n                        var tmp1 = d1 + d6;\n                        var tmp6 = d1 - d6;\n                        var tmp2 = d2 + d5;\n                        var tmp5 = d2 - d5;\n                        var tmp3 = d3 + d4;\n                        var tmp4 = d3 - d4;\n    \n                        /* Even part */\n                        var tmp10 = tmp0 + tmp3;    /* phase 2 */\n                        var tmp13 = tmp0 - tmp3;\n                        var tmp11 = tmp1 + tmp2;\n                        var tmp12 = tmp1 - tmp2;\n    \n                        data[dataOff] = tmp10 + tmp11; /* phase 3 */\n                        data[dataOff+4] = tmp10 - tmp11;\n    \n                        var z1 = (tmp12 + tmp13) * 0.707106781; /* c4 */\n                        data[dataOff+2] = tmp13 + z1; /* phase 5 */\n                        data[dataOff+6] = tmp13 - z1;\n    \n                        /* Odd part */\n                        tmp10 = tmp4 + tmp5; /* phase 2 */\n                        tmp11 = tmp5 + tmp6;\n                        tmp12 = tmp6 + tmp7;\n    \n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5 = (tmp10 - tmp12) * 0.382683433; /* c6 */\n                        var z2 = 0.541196100 * tmp10 + z5; /* c2-c6 */\n                        var z4 = 1.306562965 * tmp12 + z5; /* c2+c6 */\n                        var z3 = tmp11 * 0.707106781; /* c4 */\n    \n                        var z11 = tmp7 + z3;    /* phase 5 */\n                        var z13 = tmp7 - z3;\n    \n                        data[dataOff+5] = z13 + z2; /* phase 6 */\n                        data[dataOff+3] = z13 - z2;\n                        data[dataOff+1] = z11 + z4;\n                        data[dataOff+7] = z11 - z4;\n    \n                        dataOff += 8; /* advance pointer to next row */\n                    }\n    \n                    /* Pass 2: process columns. */\n                    dataOff = 0;\n                    for (i=0; i<I8; ++i)\n                    {\n                        d0 = data[dataOff];\n                        d1 = data[dataOff + 8];\n                        d2 = data[dataOff + 16];\n                        d3 = data[dataOff + 24];\n                        d4 = data[dataOff + 32];\n                        d5 = data[dataOff + 40];\n                        d6 = data[dataOff + 48];\n                        d7 = data[dataOff + 56];\n    \n                        var tmp0p2 = d0 + d7;\n                        var tmp7p2 = d0 - d7;\n                        var tmp1p2 = d1 + d6;\n                        var tmp6p2 = d1 - d6;\n                        var tmp2p2 = d2 + d5;\n                        var tmp5p2 = d2 - d5;\n                        var tmp3p2 = d3 + d4;\n                        var tmp4p2 = d3 - d4;\n    \n                        /* Even part */\n                        var tmp10p2 = tmp0p2 + tmp3p2;  /* phase 2 */\n                        var tmp13p2 = tmp0p2 - tmp3p2;\n                        var tmp11p2 = tmp1p2 + tmp2p2;\n                        var tmp12p2 = tmp1p2 - tmp2p2;\n    \n                        data[dataOff] = tmp10p2 + tmp11p2; /* phase 3 */\n                        data[dataOff+32] = tmp10p2 - tmp11p2;\n    \n                        var z1p2 = (tmp12p2 + tmp13p2) * 0.707106781; /* c4 */\n                        data[dataOff+16] = tmp13p2 + z1p2; /* phase 5 */\n                        data[dataOff+48] = tmp13p2 - z1p2;\n    \n                        /* Odd part */\n                        tmp10p2 = tmp4p2 + tmp5p2; /* phase 2 */\n                        tmp11p2 = tmp5p2 + tmp6p2;\n                        tmp12p2 = tmp6p2 + tmp7p2;\n    \n                        /* The rotator is modified from fig 4-8 to avoid extra negations. */\n                        var z5p2 = (tmp10p2 - tmp12p2) * 0.382683433; /* c6 */\n                        var z2p2 = 0.541196100 * tmp10p2 + z5p2; /* c2-c6 */\n                        var z4p2 = 1.306562965 * tmp12p2 + z5p2; /* c2+c6 */\n                        var z3p2 = tmp11p2 * 0.707106781; /* c4 */\n    \n                        var z11p2 = tmp7p2 + z3p2;  /* phase 5 */\n                        var z13p2 = tmp7p2 - z3p2;\n    \n                        data[dataOff+40] = z13p2 + z2p2; /* phase 6 */\n                        data[dataOff+24] = z13p2 - z2p2;\n                        data[dataOff+ 8] = z11p2 + z4p2;\n                        data[dataOff+56] = z11p2 - z4p2;\n    \n                        dataOff++; /* advance pointer to next column */\n                    }\n    \n                    // Quantize/descale the coefficients\n                    var fDCTQuant;\n                    for (i=0; i<I64; ++i)\n                    {\n                        // Apply the quantization and scaling factor & Round to nearest integer\n                        fDCTQuant = data[i]*fdtbl[i];\n                        outputfDCTQuant[i] = (fDCTQuant > 0.0) ? ((fDCTQuant + 0.5)|0) : ((fDCTQuant - 0.5)|0);\n                        //outputfDCTQuant[i] = fround(fDCTQuant);\n    \n                    }\n                    return outputfDCTQuant;\n                }\n    \n                function writeAPP0()\n                {\n                    writeWord(0xFFE0); // marker\n                    writeWord(16); // length\n                    writeByte(0x4A); // J\n                    writeByte(0x46); // F\n                    writeByte(0x49); // I\n                    writeByte(0x46); // F\n                    writeByte(0); // = \"JFIF\",'\\0'\n                    writeByte(1); // versionhi\n                    writeByte(1); // versionlo\n                    writeByte(0); // xyunits\n                    writeWord(1); // xdensity\n                    writeWord(1); // ydensity\n                    writeByte(0); // thumbnwidth\n                    writeByte(0); // thumbnheight\n                }\n    \n                function writeSOF0(width, height)\n                {\n                    writeWord(0xFFC0); // marker\n                    writeWord(17);   // length, truecolor YUV JPG\n                    writeByte(8);    // precision\n                    writeWord(height);\n                    writeWord(width);\n                    writeByte(3);    // nrofcomponents\n                    writeByte(1);    // IdY\n                    writeByte(0x11); // HVY\n                    writeByte(0);    // QTY\n                    writeByte(2);    // IdU\n                    writeByte(0x11); // HVU\n                    writeByte(1);    // QTU\n                    writeByte(3);    // IdV\n                    writeByte(0x11); // HVV\n                    writeByte(1);    // QTV\n                }\n    \n                function writeDQT()\n                {\n                    writeWord(0xFFDB); // marker\n                    writeWord(132);    // length\n                    writeByte(0);\n                    for (var i=0; i<64; i++) {\n                        writeByte(YTable[i]);\n                    }\n                    writeByte(1);\n                    for (var j=0; j<64; j++) {\n                        writeByte(UVTable[j]);\n                    }\n                }\n    \n                function writeDHT()\n                {\n                    writeWord(0xFFC4); // marker\n                    writeWord(0x01A2); // length\n    \n                    writeByte(0); // HTYDCinfo\n                    for (var i=0; i<16; i++) {\n                        writeByte(std_dc_luminance_nrcodes[i+1]);\n                    }\n                    for (var j=0; j<=11; j++) {\n                        writeByte(std_dc_luminance_values[j]);\n                    }\n    \n                    writeByte(0x10); // HTYACinfo\n                    for (var k=0; k<16; k++) {\n                        writeByte(std_ac_luminance_nrcodes[k+1]);\n                    }\n                    for (var l=0; l<=161; l++) {\n                        writeByte(std_ac_luminance_values[l]);\n                    }\n    \n                    writeByte(1); // HTUDCinfo\n                    for (var m=0; m<16; m++) {\n                        writeByte(std_dc_chrominance_nrcodes[m+1]);\n                    }\n                    for (var n=0; n<=11; n++) {\n                        writeByte(std_dc_chrominance_values[n]);\n                    }\n    \n                    writeByte(0x11); // HTUACinfo\n                    for (var o=0; o<16; o++) {\n                        writeByte(std_ac_chrominance_nrcodes[o+1]);\n                    }\n                    for (var p=0; p<=161; p++) {\n                        writeByte(std_ac_chrominance_values[p]);\n                    }\n                }\n    \n                function writeSOS()\n                {\n                    writeWord(0xFFDA); // marker\n                    writeWord(12); // length\n                    writeByte(3); // nrofcomponents\n                    writeByte(1); // IdY\n                    writeByte(0); // HTY\n                    writeByte(2); // IdU\n                    writeByte(0x11); // HTU\n                    writeByte(3); // IdV\n                    writeByte(0x11); // HTV\n                    writeByte(0); // Ss\n                    writeByte(0x3f); // Se\n                    writeByte(0); // Bf\n                }\n    \n                function processDU(CDU, fdtbl, DC, HTDC, HTAC){\n                    var EOB = HTAC[0x00];\n                    var M16zeroes = HTAC[0xF0];\n                    var pos;\n                    var I16 = 16;\n                    var I63 = 63;\n                    var I64 = 64;\n                    var DU_DCT = fDCTQuant(CDU, fdtbl);\n                    //ZigZag reorder\n                    for (var j=0;j<I64;++j) {\n                        DU[ZigZag[j]]=DU_DCT[j];\n                    }\n                    var Diff = DU[0] - DC; DC = DU[0];\n                    //Encode DC\n                    if (Diff==0) {\n                        writeBits(HTDC[0]); // Diff might be 0\n                    } else {\n                        pos = 32767+Diff;\n                        writeBits(HTDC[category[pos]]);\n                        writeBits(bitcode[pos]);\n                    }\n                    //Encode ACs\n                    var end0pos = 63; // was consts... which is crazy\n                    for (; (end0pos>0)&&(DU[end0pos]==0); end0pos--) {};\n                    //end0pos = first element in reverse order !=0\n                    if ( end0pos == 0) {\n                        writeBits(EOB);\n                        return DC;\n                    }\n                    var i = 1;\n                    var lng;\n                    while ( i <= end0pos ) {\n                        var startpos = i;\n                        for (; (DU[i]==0) && (i<=end0pos); ++i) {}\n                        var nrzeroes = i-startpos;\n                        if ( nrzeroes >= I16 ) {\n                            lng = nrzeroes>>4;\n                            for (var nrmarker=1; nrmarker <= lng; ++nrmarker)\n                                writeBits(M16zeroes);\n                            nrzeroes = nrzeroes&0xF;\n                        }\n                        pos = 32767+DU[i];\n                        writeBits(HTAC[(nrzeroes<<4)+category[pos]]);\n                        writeBits(bitcode[pos]);\n                        i++;\n                    }\n                    if ( end0pos != I63 ) {\n                        writeBits(EOB);\n                    }\n                    return DC;\n                }\n    \n                function initCharLookupTable(){\n                    var sfcc = String.fromCharCode;\n                    for(var i=0; i < 256; i++){ ///// ACHTUNG // 255\n                        clt[i] = sfcc(i);\n                    }\n                }\n    \n                this.encode = function(image,quality) // image data object\n                {\n                    // var time_start = new Date().getTime();\n    \n                    if(quality) setQuality(quality);\n    \n                    // Initialize bit writer\n                    byteout = new Array();\n                    bytenew=0;\n                    bytepos=7;\n    \n                    // Add JPEG headers\n                    writeWord(0xFFD8); // SOI\n                    writeAPP0();\n                    writeDQT();\n                    writeSOF0(image.width,image.height);\n                    writeDHT();\n                    writeSOS();\n    \n    \n                    // Encode 8x8 macroblocks\n                    var DCY=0;\n                    var DCU=0;\n                    var DCV=0;\n    \n                    bytenew=0;\n                    bytepos=7;\n    \n    \n                    this.encode.displayName = \"_encode_\";\n    \n                    var imageData = image.data;\n                    var width = image.width;\n                    var height = image.height;\n    \n                    var quadWidth = width*4;\n                    var tripleWidth = width*3;\n    \n                    var x, y = 0;\n                    var r, g, b;\n                    var start,p, col,row,pos;\n                    while(y < height){\n                        x = 0;\n                        while(x < quadWidth){\n                        start = quadWidth * y + x;\n                        p = start;\n                        col = -1;\n                        row = 0;\n    \n                        for(pos=0; pos < 64; pos++){\n                            row = pos >> 3;// /8\n                            col = ( pos & 7 ) * 4; // %8\n                            p = start + ( row * quadWidth ) + col;\n    \n                            if(y+row >= height){ // padding bottom\n                                p-= (quadWidth*(y+1+row-height));\n                            }\n    \n                            if(x+col >= quadWidth){ // padding right\n                                p-= ((x+col) - quadWidth +4)\n                            }\n    \n                            r = imageData[ p++ ];\n                            g = imageData[ p++ ];\n                            b = imageData[ p++ ];\n    \n    \n                            /* // calculate YUV values dynamically\n                            YDU[pos]=((( 0.29900)*r+( 0.58700)*g+( 0.11400)*b))-128; //-0x80\n                            UDU[pos]=(((-0.16874)*r+(-0.33126)*g+( 0.50000)*b));\n                            VDU[pos]=((( 0.50000)*r+(-0.41869)*g+(-0.08131)*b));\n                            */\n    \n                            // use lookup table (slightly faster)\n                            YDU[pos] = ((RGB_YUV_TABLE[r]             + RGB_YUV_TABLE[(g +  256)>>0] + RGB_YUV_TABLE[(b +  512)>>0]) >> 16)-128;\n                            UDU[pos] = ((RGB_YUV_TABLE[(r +  768)>>0] + RGB_YUV_TABLE[(g + 1024)>>0] + RGB_YUV_TABLE[(b + 1280)>>0]) >> 16)-128;\n                            VDU[pos] = ((RGB_YUV_TABLE[(r + 1280)>>0] + RGB_YUV_TABLE[(g + 1536)>>0] + RGB_YUV_TABLE[(b + 1792)>>0]) >> 16)-128;\n    \n                        }\n    \n                        DCY = processDU(YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);\n                        DCU = processDU(UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);\n                        DCV = processDU(VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);\n                        x+=32;\n                        }\n                        y+=8;\n                    }\n    \n    \n                    ////////////////////////////////////////////////////////////////\n    \n                    // Do the bit alignment of the EOI marker\n                    if ( bytepos >= 0 ) {\n                        var fillbits = [];\n                        fillbits[1] = bytepos+1;\n                        fillbits[0] = (1<<(bytepos+1))-1;\n                        writeBits(fillbits);\n                    }\n    \n                    writeWord(0xFFD9); //EOI\n    \n                    var jpegDataUri = 'data:image/jpeg;base64,' + btoa(byteout.join(''));\n    \n                    byteout = [];\n    \n                    // benchmarking\n                    // var duration = new Date().getTime() - time_start;\n                    // console.log('Encoding time: '+ currentQuality + 'ms');\n                    //\n    \n                    return jpegDataUri\n            }\n    \n            function setQuality(quality){\n                if (quality <= 0) {\n                    quality = 1;\n                }\n                if (quality > 100) {\n                    quality = 100;\n                }\n    \n                if(currentQuality == quality) return // don't recalc if unchanged\n    \n                var sf = 0;\n                if (quality < 50) {\n                    sf = Math.floor(5000 / quality);\n                } else {\n                    sf = Math.floor(200 - quality*2);\n                }\n    \n                initQuantTables(sf);\n                currentQuality = quality;\n                // console.log('Quality set to: '+quality +'%');\n            }\n    \n            function init(){\n                // var time_start = new Date().getTime();\n                if(!quality) quality = 50;\n                // Create tables\n                initCharLookupTable()\n                initHuffmanTbl();\n                initCategoryNumber();\n                initRGBYUVTable();\n    \n                setQuality(quality);\n                // var duration = new Date().getTime() - time_start;\n                // console.log('Initialization '+ duration + 'ms');\n            }\n    \n            init();\n    \n        };\n    \n        JPEGEncoder.encode = function( data, quality ) {\n            var encoder = new JPEGEncoder( quality );\n    \n            return encoder.encode( data );\n        }\n    \n        return JPEGEncoder;\n    });\n    /**\n     * @fileOverview Fix android canvas.toDataUrl bug.\n     */\n    define('runtime/html5/androidpatch',[\n        'runtime/html5/util',\n        'runtime/html5/jpegencoder',\n        'base'\n    ], function( Util, encoder, Base ) {\n        var origin = Util.canvasToDataUrl,\n            supportJpeg;\n    \n        Util.canvasToDataUrl = function( canvas, type, quality ) {\n            var ctx, w, h, fragement, parts;\n    \n            // 非android手机直接跳过。\n            if ( !Base.os.android ) {\n                return origin.apply( null, arguments );\n            }\n    \n            // 检测是否canvas支持jpeg导出，根据数据格式来判断。\n            // JPEG 前两位分别是：255, 216\n            if ( type === 'image/jpeg' && typeof supportJpeg === 'undefined' ) {\n                fragement = origin.apply( null, arguments );\n    \n                parts = fragement.split(',');\n    \n                if ( ~parts[ 0 ].indexOf('base64') ) {\n                    fragement = atob( parts[ 1 ] );\n                } else {\n                    fragement = decodeURIComponent( parts[ 1 ] );\n                }\n    \n                fragement = fragement.substring( 0, 2 );\n    \n                supportJpeg = fragement.charCodeAt( 0 ) === 255 &&\n                        fragement.charCodeAt( 1 ) === 216;\n            }\n    \n            // 只有在android环境下才修复\n            if ( type === 'image/jpeg' && !supportJpeg ) {\n                w = canvas.width;\n                h = canvas.height;\n                ctx = canvas.getContext('2d');\n    \n                return encoder.encode( ctx.getImageData( 0, 0, w, h ), quality );\n            }\n    \n            return origin.apply( null, arguments );\n        };\n    });\n    /**\n     * @fileOverview Image\n     */\n    define('runtime/html5/image',[\n        'base',\n        'runtime/html5/runtime',\n        'runtime/html5/util'\n    ], function( Base, Html5Runtime, Util ) {\n    \n        var BLANK = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D';\n    \n        return Html5Runtime.register( 'Image', {\n    \n            // flag: 标记是否被修改过。\n            modified: false,\n    \n            init: function() {\n                var me = this,\n                    img = new Image();\n    \n                img.onload = function() {\n    \n                    me._info = {\n                        type: me.type,\n                        width: this.width,\n                        height: this.height\n                    };\n    \n                    // 读取meta信息。\n                    if ( !me._metas && 'image/jpeg' === me.type ) {\n                        Util.parseMeta( me._blob, function( error, ret ) {\n                            me._metas = ret;\n                            me.owner.trigger('load');\n                        });\n                    } else {\n                        me.owner.trigger('load');\n                    }\n                };\n    \n                img.onerror = function() {\n                    me.owner.trigger('error');\n                };\n    \n                me._img = img;\n            },\n    \n            loadFromBlob: function( blob ) {\n                var me = this,\n                    img = me._img;\n    \n                me._blob = blob;\n                me.type = blob.type;\n                img.src = Util.createObjectURL( blob.getSource() );\n                me.owner.once( 'load', function() {\n                    Util.revokeObjectURL( img.src );\n                });\n            },\n    \n            resize: function( width, height ) {\n                var canvas = this._canvas ||\n                        (this._canvas = document.createElement('canvas'));\n    \n                this._resize( this._img, canvas, width, height );\n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'resize' );\n            },\n    \n            crop: function( x, y, w, h, s ) {\n                var cvs = this._canvas ||\n                        (this._canvas = document.createElement('canvas')),\n                    opts = this.options,\n                    img = this._img,\n                    iw = img.naturalWidth,\n                    ih = img.naturalHeight,\n                    orientation = this.getOrientation();\n    \n                s = s || 1;\n    \n                // todo 解决 orientation 的问题。\n                // values that require 90 degree rotation\n                // if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n    \n                //     switch ( orientation ) {\n                //         case 6:\n                //             tmp = x;\n                //             x = y;\n                //             y = iw * s - tmp - w;\n                //             console.log(ih * s, tmp, w)\n                //             break;\n                //     }\n    \n                //     (w ^= h, h ^= w, w ^= h);\n                // }\n    \n                cvs.width = w;\n                cvs.height = h;\n    \n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n                this._renderImageToCanvas( cvs, img, -x, -y, iw * s, ih * s );\n    \n                this._blob = null;    // 没用了，可以删掉了。\n                this.modified = true;\n                this.owner.trigger( 'complete', 'crop' );\n            },\n    \n            getAsBlob: function( type ) {\n                var blob = this._blob,\n                    opts = this.options,\n                    canvas;\n    \n                type = type || this.type;\n    \n                // blob需要重新生成。\n                if ( this.modified || this.type !== type ) {\n                    canvas = this._canvas;\n    \n                    if ( type === 'image/jpeg' ) {\n    \n                        blob = Util.canvasToDataUrl( canvas, type, opts.quality );\n    \n                        if ( opts.preserveHeaders && this._metas &&\n                                this._metas.imageHead ) {\n    \n                            blob = Util.dataURL2ArrayBuffer( blob );\n                            blob = Util.updateImageHead( blob,\n                                    this._metas.imageHead );\n                            blob = Util.arrayBufferToBlob( blob, type );\n                            return blob;\n                        }\n                    } else {\n                        blob = Util.canvasToDataUrl( canvas, type );\n                    }\n    \n                    blob = Util.dataURL2Blob( blob );\n                }\n    \n                return blob;\n            },\n    \n            getAsDataUrl: function( type ) {\n                var opts = this.options;\n    \n                type = type || this.type;\n    \n                if ( type === 'image/jpeg' ) {\n                    return Util.canvasToDataUrl( this._canvas, type, opts.quality );\n                } else {\n                    return this._canvas.toDataURL( type );\n                }\n            },\n    \n            getOrientation: function() {\n                return this._metas && this._metas.exif &&\n                        this._metas.exif.get('Orientation') || 1;\n            },\n    \n            info: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._info = val;\n                    return this;\n                }\n    \n                // getter\n                return this._info;\n            },\n    \n            meta: function( val ) {\n    \n                // setter\n                if ( val ) {\n                    this._meta = val;\n                    return this;\n                }\n    \n                // getter\n                return this._meta;\n            },\n    \n            destroy: function() {\n                var canvas = this._canvas;\n                this._img.onload = null;\n    \n                if ( canvas ) {\n                    canvas.getContext('2d')\n                            .clearRect( 0, 0, canvas.width, canvas.height );\n                    canvas.width = canvas.height = 0;\n                    this._canvas = null;\n                }\n    \n                // 释放内存。非常重要，否则释放不了image的内存。\n                this._img.src = BLANK;\n                this._img = this._blob = null;\n            },\n    \n            _resize: function( img, cvs, width, height ) {\n                var opts = this.options,\n                    naturalWidth = img.width,\n                    naturalHeight = img.height,\n                    orientation = this.getOrientation(),\n                    scale, w, h, x, y;\n    \n                // values that require 90 degree rotation\n                if ( ~[ 5, 6, 7, 8 ].indexOf( orientation ) ) {\n    \n                    // 交换width, height的值。\n                    width ^= height;\n                    height ^= width;\n                    width ^= height;\n                }\n    \n                scale = Math[ opts.crop ? 'max' : 'min' ]( width / naturalWidth,\n                        height / naturalHeight );\n    \n                // 不允许放大。\n                opts.allowMagnify || (scale = Math.min( 1, scale ));\n    \n                w = naturalWidth * scale;\n                h = naturalHeight * scale;\n    \n                if ( opts.crop ) {\n                    cvs.width = width;\n                    cvs.height = height;\n                } else {\n                    cvs.width = w;\n                    cvs.height = h;\n                }\n    \n                x = (cvs.width - w) / 2;\n                y = (cvs.height - h) / 2;\n    \n                opts.preserveHeaders || this._rotate2Orientaion( cvs, orientation );\n    \n                this._renderImageToCanvas( cvs, img, x, y, w, h );\n            },\n    \n            _rotate2Orientaion: function( canvas, orientation ) {\n                var width = canvas.width,\n                    height = canvas.height,\n                    ctx = canvas.getContext('2d');\n    \n                switch ( orientation ) {\n                    case 5:\n                    case 6:\n                    case 7:\n                    case 8:\n                        canvas.width = height;\n                        canvas.height = width;\n                        break;\n                }\n    \n                switch ( orientation ) {\n                    case 2:    // horizontal flip\n                        ctx.translate( width, 0 );\n                        ctx.scale( -1, 1 );\n                        break;\n    \n                    case 3:    // 180 rotate left\n                        ctx.translate( width, height );\n                        ctx.rotate( Math.PI );\n                        break;\n    \n                    case 4:    // vertical flip\n                        ctx.translate( 0, height );\n                        ctx.scale( 1, -1 );\n                        break;\n    \n                    case 5:    // vertical flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.scale( 1, -1 );\n                        break;\n    \n                    case 6:    // 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( 0, -height );\n                        break;\n    \n                    case 7:    // horizontal flip + 90 rotate right\n                        ctx.rotate( 0.5 * Math.PI );\n                        ctx.translate( width, -height );\n                        ctx.scale( -1, 1 );\n                        break;\n    \n                    case 8:    // 90 rotate left\n                        ctx.rotate( -0.5 * Math.PI );\n                        ctx.translate( -width, 0 );\n                        break;\n                }\n            },\n    \n            // https://github.com/stomita/ios-imagefile-megapixel/\n            // blob/master/src/megapix-image.js\n            _renderImageToCanvas: (function() {\n    \n                // 如果不是ios, 不需要这么复杂！\n                if ( !Base.os.ios ) {\n                    return function( canvas ) {\n                        var args = Base.slice( arguments, 1 ),\n                            ctx = canvas.getContext('2d');\n    \n                        ctx.drawImage.apply( ctx, args );\n                    };\n                }\n    \n                /**\n                 * Detecting vertical squash in loaded image.\n                 * Fixes a bug which squash image vertically while drawing into\n                 * canvas for some images.\n                 */\n                function detectVerticalSquash( img, iw, ih ) {\n                    var canvas = document.createElement('canvas'),\n                        ctx = canvas.getContext('2d'),\n                        sy = 0,\n                        ey = ih,\n                        py = ih,\n                        data, alpha, ratio;\n    \n    \n                    canvas.width = 1;\n                    canvas.height = ih;\n                    ctx.drawImage( img, 0, 0 );\n                    data = ctx.getImageData( 0, 0, 1, ih ).data;\n    \n                    // search image edge pixel position in case\n                    // it is squashed vertically.\n                    while ( py > sy ) {\n                        alpha = data[ (py - 1) * 4 + 3 ];\n    \n                        if ( alpha === 0 ) {\n                            ey = py;\n                        } else {\n                            sy = py;\n                        }\n    \n                        py = (ey + sy) >> 1;\n                    }\n    \n                    ratio = (py / ih);\n                    return (ratio === 0) ? 1 : ratio;\n                }\n    \n                // fix ie7 bug\n                // http://stackoverflow.com/questions/11929099/\n                // html5-canvas-drawimage-ratio-bug-ios\n                if ( Base.os.ios >= 7 ) {\n                    return function( canvas, img, x, y, w, h ) {\n                        var iw = img.naturalWidth,\n                            ih = img.naturalHeight,\n                            vertSquashRatio = detectVerticalSquash( img, iw, ih );\n    \n                        return canvas.getContext('2d').drawImage( img, 0, 0,\n                                iw * vertSquashRatio, ih * vertSquashRatio,\n                                x, y, w, h );\n                    };\n                }\n    \n                /**\n                 * Detect subsampling in loaded image.\n                 * In iOS, larger images than 2M pixels may be\n                 * subsampled in rendering.\n                 */\n                function detectSubsampling( img ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        canvas, ctx;\n    \n                    // subsampling may happen overmegapixel image\n                    if ( iw * ih > 1024 * 1024 ) {\n                        canvas = document.createElement('canvas');\n                        canvas.width = canvas.height = 1;\n                        ctx = canvas.getContext('2d');\n                        ctx.drawImage( img, -iw + 1, 0 );\n    \n                        // subsampled image becomes half smaller in rendering size.\n                        // check alpha channel value to confirm image is covering\n                        // edge pixel or not. if alpha value is 0\n                        // image is not covering, hence subsampled.\n                        return ctx.getImageData( 0, 0, 1, 1 ).data[ 3 ] === 0;\n                    } else {\n                        return false;\n                    }\n                }\n    \n    \n                return function( canvas, img, x, y, width, height ) {\n                    var iw = img.naturalWidth,\n                        ih = img.naturalHeight,\n                        ctx = canvas.getContext('2d'),\n                        subsampled = detectSubsampling( img ),\n                        doSquash = this.type === 'image/jpeg',\n                        d = 1024,\n                        sy = 0,\n                        dy = 0,\n                        tmpCanvas, tmpCtx, vertSquashRatio, dw, dh, sx, dx;\n    \n                    if ( subsampled ) {\n                        iw /= 2;\n                        ih /= 2;\n                    }\n    \n                    ctx.save();\n                    tmpCanvas = document.createElement('canvas');\n                    tmpCanvas.width = tmpCanvas.height = d;\n    \n                    tmpCtx = tmpCanvas.getContext('2d');\n                    vertSquashRatio = doSquash ?\n                            detectVerticalSquash( img, iw, ih ) : 1;\n    \n                    dw = Math.ceil( d * width / iw );\n                    dh = Math.ceil( d * height / ih / vertSquashRatio );\n    \n                    while ( sy < ih ) {\n                        sx = 0;\n                        dx = 0;\n                        while ( sx < iw ) {\n                            tmpCtx.clearRect( 0, 0, d, d );\n                            tmpCtx.drawImage( img, -sx, -sy );\n                            ctx.drawImage( tmpCanvas, 0, 0, d, d,\n                                    x + dx, y + dy, dw, dh );\n                            sx += d;\n                            dx += dw;\n                        }\n                        sy += d;\n                        dy += dh;\n                    }\n                    ctx.restore();\n                    tmpCanvas = tmpCtx = null;\n                };\n            })()\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var noop = Base.noop,\n            $ = Base.$;\n    \n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n    \n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n    \n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n    \n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n    \n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n    \n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n    \n            getResponse: function() {\n                return this._response;\n            },\n    \n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n    \n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n    \n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n    \n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n    \n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n    \n                    return me.trigger( 'progress', percentage );\n                };\n    \n                xhr.onreadystatechange = function() {\n    \n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n    \n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n    \n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n    \n    \n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n    \n            _parseJson: function( str ) {\n                var json;\n    \n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n    \n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/html5/md5',[\n        'runtime/html5/runtime'\n    ], function( FlashRuntime ) {\n    \n        /*\n         * Fastest md5 implementation around (JKM md5)\n         * Credits: Joseph Myers\n         *\n         * @see http://www.myersdaily.org/joseph/javascript/md5-text.html\n         * @see http://jsperf.com/md5-shootout/7\n         */\n    \n        /* this function is much faster,\n          so if possible we use it. Some IEs\n          are the only ones I know of that\n          need the idiotic second function,\n          generated by an if clause.  */\n        var add32 = function (a, b) {\n            return (a + b) & 0xFFFFFFFF;\n        },\n    \n        cmn = function (q, a, b, x, s, t) {\n            a = add32(add32(a, q), add32(x, t));\n            return add32((a << s) | (a >>> (32 - s)), b);\n        },\n    \n        ff = function (a, b, c, d, x, s, t) {\n            return cmn((b & c) | ((~b) & d), a, b, x, s, t);\n        },\n    \n        gg = function (a, b, c, d, x, s, t) {\n            return cmn((b & d) | (c & (~d)), a, b, x, s, t);\n        },\n    \n        hh = function (a, b, c, d, x, s, t) {\n            return cmn(b ^ c ^ d, a, b, x, s, t);\n        },\n    \n        ii = function (a, b, c, d, x, s, t) {\n            return cmn(c ^ (b | (~d)), a, b, x, s, t);\n        },\n    \n        md5cycle = function (x, k) {\n            var a = x[0],\n                b = x[1],\n                c = x[2],\n                d = x[3];\n    \n            a = ff(a, b, c, d, k[0], 7, -680876936);\n            d = ff(d, a, b, c, k[1], 12, -389564586);\n            c = ff(c, d, a, b, k[2], 17, 606105819);\n            b = ff(b, c, d, a, k[3], 22, -1044525330);\n            a = ff(a, b, c, d, k[4], 7, -176418897);\n            d = ff(d, a, b, c, k[5], 12, 1200080426);\n            c = ff(c, d, a, b, k[6], 17, -1473231341);\n            b = ff(b, c, d, a, k[7], 22, -45705983);\n            a = ff(a, b, c, d, k[8], 7, 1770035416);\n            d = ff(d, a, b, c, k[9], 12, -1958414417);\n            c = ff(c, d, a, b, k[10], 17, -42063);\n            b = ff(b, c, d, a, k[11], 22, -1990404162);\n            a = ff(a, b, c, d, k[12], 7, 1804603682);\n            d = ff(d, a, b, c, k[13], 12, -40341101);\n            c = ff(c, d, a, b, k[14], 17, -1502002290);\n            b = ff(b, c, d, a, k[15], 22, 1236535329);\n    \n            a = gg(a, b, c, d, k[1], 5, -165796510);\n            d = gg(d, a, b, c, k[6], 9, -1069501632);\n            c = gg(c, d, a, b, k[11], 14, 643717713);\n            b = gg(b, c, d, a, k[0], 20, -373897302);\n            a = gg(a, b, c, d, k[5], 5, -701558691);\n            d = gg(d, a, b, c, k[10], 9, 38016083);\n            c = gg(c, d, a, b, k[15], 14, -660478335);\n            b = gg(b, c, d, a, k[4], 20, -405537848);\n            a = gg(a, b, c, d, k[9], 5, 568446438);\n            d = gg(d, a, b, c, k[14], 9, -1019803690);\n            c = gg(c, d, a, b, k[3], 14, -187363961);\n            b = gg(b, c, d, a, k[8], 20, 1163531501);\n            a = gg(a, b, c, d, k[13], 5, -1444681467);\n            d = gg(d, a, b, c, k[2], 9, -51403784);\n            c = gg(c, d, a, b, k[7], 14, 1735328473);\n            b = gg(b, c, d, a, k[12], 20, -1926607734);\n    \n            a = hh(a, b, c, d, k[5], 4, -378558);\n            d = hh(d, a, b, c, k[8], 11, -2022574463);\n            c = hh(c, d, a, b, k[11], 16, 1839030562);\n            b = hh(b, c, d, a, k[14], 23, -35309556);\n            a = hh(a, b, c, d, k[1], 4, -1530992060);\n            d = hh(d, a, b, c, k[4], 11, 1272893353);\n            c = hh(c, d, a, b, k[7], 16, -155497632);\n            b = hh(b, c, d, a, k[10], 23, -1094730640);\n            a = hh(a, b, c, d, k[13], 4, 681279174);\n            d = hh(d, a, b, c, k[0], 11, -358537222);\n            c = hh(c, d, a, b, k[3], 16, -722521979);\n            b = hh(b, c, d, a, k[6], 23, 76029189);\n            a = hh(a, b, c, d, k[9], 4, -640364487);\n            d = hh(d, a, b, c, k[12], 11, -421815835);\n            c = hh(c, d, a, b, k[15], 16, 530742520);\n            b = hh(b, c, d, a, k[2], 23, -995338651);\n    \n            a = ii(a, b, c, d, k[0], 6, -198630844);\n            d = ii(d, a, b, c, k[7], 10, 1126891415);\n            c = ii(c, d, a, b, k[14], 15, -1416354905);\n            b = ii(b, c, d, a, k[5], 21, -57434055);\n            a = ii(a, b, c, d, k[12], 6, 1700485571);\n            d = ii(d, a, b, c, k[3], 10, -1894986606);\n            c = ii(c, d, a, b, k[10], 15, -1051523);\n            b = ii(b, c, d, a, k[1], 21, -2054922799);\n            a = ii(a, b, c, d, k[8], 6, 1873313359);\n            d = ii(d, a, b, c, k[15], 10, -30611744);\n            c = ii(c, d, a, b, k[6], 15, -1560198380);\n            b = ii(b, c, d, a, k[13], 21, 1309151649);\n            a = ii(a, b, c, d, k[4], 6, -145523070);\n            d = ii(d, a, b, c, k[11], 10, -1120210379);\n            c = ii(c, d, a, b, k[2], 15, 718787259);\n            b = ii(b, c, d, a, k[9], 21, -343485551);\n    \n            x[0] = add32(a, x[0]);\n            x[1] = add32(b, x[1]);\n            x[2] = add32(c, x[2]);\n            x[3] = add32(d, x[3]);\n        },\n    \n        /* there needs to be support for Unicode here,\n           * unless we pretend that we can redefine the MD-5\n           * algorithm for multi-byte characters (perhaps\n           * by adding every four 16-bit characters and\n           * shortening the sum to 32 bits). Otherwise\n           * I suggest performing MD-5 as if every character\n           * was two bytes--e.g., 0040 0025 = @%--but then\n           * how will an ordinary MD-5 sum be matched?\n           * There is no way to standardize text to something\n           * like UTF-8 before transformation; speed cost is\n           * utterly prohibitive. The JavaScript standard\n           * itself needs to look at this: it should start\n           * providing access to strings as preformed UTF-8\n           * 8-bit unsigned value arrays.\n           */\n        md5blk = function (s) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n    \n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);\n            }\n            return md5blks;\n        },\n    \n        md5blk_array = function (a) {\n            var md5blks = [],\n                i; /* Andy King said do it this way. */\n    \n            for (i = 0; i < 64; i += 4) {\n                md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);\n            }\n            return md5blks;\n        },\n    \n        md51 = function (s) {\n            var n = s.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n    \n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk(s.substring(i - 64, i)));\n            }\n            s = s.substring(i - 64);\n            length = s.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);\n            }\n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n    \n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n    \n            tail[14] = lo;\n            tail[15] = hi;\n    \n            md5cycle(state, tail);\n            return state;\n        },\n    \n        md51_array = function (a) {\n            var n = a.length,\n                state = [1732584193, -271733879, -1732584194, 271733878],\n                i,\n                length,\n                tail,\n                tmp,\n                lo,\n                hi;\n    \n            for (i = 64; i <= n; i += 64) {\n                md5cycle(state, md5blk_array(a.subarray(i - 64, i)));\n            }\n    \n            // Not sure if it is a bug, however IE10 will always produce a sub array of length 1\n            // containing the last element of the parent array if the sub array specified starts\n            // beyond the length of the parent array - weird.\n            // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue\n            a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);\n    \n            length = a.length;\n            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];\n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= a[i] << ((i % 4) << 3);\n            }\n    \n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n    \n            // Beware that the final length might not fit in 32 bits so we take care of that\n            tmp = n * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n    \n            tail[14] = lo;\n            tail[15] = hi;\n    \n            md5cycle(state, tail);\n    \n            return state;\n        },\n    \n        hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],\n    \n        rhex = function (n) {\n            var s = '',\n                j;\n            for (j = 0; j < 4; j += 1) {\n                s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];\n            }\n            return s;\n        },\n    \n        hex = function (x) {\n            var i;\n            for (i = 0; i < x.length; i += 1) {\n                x[i] = rhex(x[i]);\n            }\n            return x.join('');\n        },\n    \n        md5 = function (s) {\n            return hex(md51(s));\n        },\n    \n    \n    \n        ////////////////////////////////////////////////////////////////////////////\n    \n        /**\n         * SparkMD5 OOP implementation.\n         *\n         * Use this class to perform an incremental md5, otherwise use the\n         * static methods instead.\n         */\n        SparkMD5 = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n    \n    \n        // In some cases the fast add32 function cannot be used..\n        if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {\n            add32 = 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    \n    \n        /**\n         * Appends a string.\n         * A conversion will be applied if an utf8 string is detected.\n         *\n         * @param {String} str The string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.append = function (str) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n    \n            // then append as binary\n            this.appendBinary(str);\n    \n            return this;\n        };\n    \n        /**\n         * Appends a binary string.\n         *\n         * @param {String} contents The binary string to be appended\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.appendBinary = function (contents) {\n            this._buff += contents;\n            this._length += contents.length;\n    \n            var length = this._buff.length,\n                i;\n    \n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));\n            }\n    \n            this._buff = this._buff.substr(i - 64);\n    \n            return this;\n        };\n    \n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                i,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                ret;\n    \n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);\n            }\n    \n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n    \n            this.reset();\n    \n            return ret;\n        };\n    \n        /**\n         * Finish the final calculation based on the tail.\n         *\n         * @param {Array}  tail   The tail (will be modified)\n         * @param {Number} length The length of the remaining buffer\n         */\n        SparkMD5.prototype._finish = function (tail, length) {\n            var i = length,\n                tmp,\n                lo,\n                hi;\n    \n            tail[i >> 2] |= 0x80 << ((i % 4) << 3);\n            if (i > 55) {\n                md5cycle(this._state, tail);\n                for (i = 0; i < 16; i += 1) {\n                    tail[i] = 0;\n                }\n            }\n    \n            // Do the final computation based on the tail and length\n            // Beware that the final length may not fit in 32 bits so we take care of that\n            tmp = this._length * 8;\n            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);\n            lo = parseInt(tmp[2], 16);\n            hi = parseInt(tmp[1], 16) || 0;\n    \n            tail[14] = lo;\n            tail[15] = hi;\n            md5cycle(this._state, tail);\n        };\n    \n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5} The instance itself\n         */\n        SparkMD5.prototype.reset = function () {\n            this._buff = \"\";\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n    \n            return this;\n        };\n    \n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.prototype.destroy = function () {\n            delete this._state;\n            delete this._buff;\n            delete this._length;\n        };\n    \n    \n        /**\n         * Performs the md5 hash on a string.\n         * A conversion will be applied if utf8 string is detected.\n         *\n         * @param {String}  str The string\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hash = function (str, raw) {\n            // converts the string to utf8 bytes if necessary\n            if (/[\\u0080-\\uFFFF]/.test(str)) {\n                str = unescape(encodeURIComponent(str));\n            }\n    \n            var hash = md51(str);\n    \n            return !!raw ? hash : hex(hash);\n        };\n    \n        /**\n         * Performs the md5 hash on a binary string.\n         *\n         * @param {String}  content The binary string\n         * @param {Boolean} raw     True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.hashBinary = function (content, raw) {\n            var hash = md51(content);\n    \n            return !!raw ? hash : hex(hash);\n        };\n    \n        /**\n         * SparkMD5 OOP implementation for array buffers.\n         *\n         * Use this class to perform an incremental md5 ONLY for array buffers.\n         */\n        SparkMD5.ArrayBuffer = function () {\n            // call reset to init the instance\n            this.reset();\n        };\n    \n        ////////////////////////////////////////////////////////////////////////////\n    \n        /**\n         * Appends an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array to be appended\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.append = function (arr) {\n            // TODO: we could avoid the concatenation here but the algorithm would be more complex\n            //       if you find yourself needing extra performance, please make a PR.\n            var buff = this._concatArrayBuffer(this._buff, arr),\n                length = buff.length,\n                i;\n    \n            this._length += arr.byteLength;\n    \n            for (i = 64; i <= length; i += 64) {\n                md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));\n            }\n    \n            // Avoids IE10 weirdness (documented above)\n            this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);\n    \n            return this;\n        };\n    \n        /**\n         * Finishes the incremental computation, reseting the internal state and\n         * returning the result.\n         * Use the raw parameter to obtain the raw result instead of the hex one.\n         *\n         * @param {Boolean} raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.prototype.end = function (raw) {\n            var buff = this._buff,\n                length = buff.length,\n                tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],\n                i,\n                ret;\n    \n            for (i = 0; i < length; i += 1) {\n                tail[i >> 2] |= buff[i] << ((i % 4) << 3);\n            }\n    \n            this._finish(tail, length);\n            ret = !!raw ? this._state : hex(this._state);\n    \n            this.reset();\n    \n            return ret;\n        };\n    \n        SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;\n    \n        /**\n         * Resets the internal state of the computation.\n         *\n         * @return {SparkMD5.ArrayBuffer} The instance itself\n         */\n        SparkMD5.ArrayBuffer.prototype.reset = function () {\n            this._buff = new Uint8Array(0);\n            this._length = 0;\n            this._state = [1732584193, -271733879, -1732584194, 271733878];\n    \n            return this;\n        };\n    \n        /**\n         * Releases memory used by the incremental buffer and other aditional\n         * resources. If you plan to use the instance again, use reset instead.\n         */\n        SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;\n    \n        /**\n         * Concats two array buffers, returning a new one.\n         *\n         * @param  {ArrayBuffer} first  The first array buffer\n         * @param  {ArrayBuffer} second The second array buffer\n         *\n         * @return {ArrayBuffer} The new array buffer\n         */\n        SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {\n            var firstLength = first.length,\n                result = new Uint8Array(firstLength + second.byteLength);\n    \n            result.set(first);\n            result.set(new Uint8Array(second), firstLength);\n    \n            return result;\n        };\n    \n        /**\n         * Performs the md5 hash on an array buffer.\n         *\n         * @param {ArrayBuffer} arr The array buffer\n         * @param {Boolean}     raw True to get the raw result, false to get the hex result\n         *\n         * @return {String|Array} The result\n         */\n        SparkMD5.ArrayBuffer.hash = function (arr, raw) {\n            var hash = md51_array(new Uint8Array(arr));\n    \n            return !!raw ? hash : hex(hash);\n        };\n        \n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n    \n            loadFromBlob: function( file ) {\n                var blob = file.getSource(),\n                    chunkSize = 2 * 1024 * 1024,\n                    chunks = Math.ceil( blob.size / chunkSize ),\n                    chunk = 0,\n                    owner = this.owner,\n                    spark = new SparkMD5.ArrayBuffer(),\n                    me = this,\n                    blobSlice = blob.mozSlice || blob.webkitSlice || blob.slice,\n                    loadNext, fr;\n    \n                fr = new FileReader();\n    \n                loadNext = function() {\n                    var start, end;\n    \n                    start = chunk * chunkSize;\n                    end = Math.min( start + chunkSize, blob.size );\n    \n                    fr.onload = function( e ) {\n                        spark.append( e.target.result );\n                        owner.trigger( 'progress', {\n                            total: file.size,\n                            loaded: end\n                        });\n                    };\n    \n                    fr.onloadend = function() {\n                        fr.onloadend = fr.onload = null;\n    \n                        if ( ++chunk < chunks ) {\n                            setTimeout( loadNext, 1 );\n                        } else {\n                            setTimeout(function(){\n                                owner.trigger('load');\n                                me.result = spark.end();\n                                loadNext = file = blob = spark = null;\n                                owner.trigger('complete');\n                            }, 50 );\n                        }\n                    };\n    \n                    fr.readAsArrayBuffer( blobSlice.call( blob, start, end ) );\n                };\n    \n                loadNext();\n            },\n    \n            getResult: function() {\n                return this.result;\n            }\n        });\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n    \n    \n        function getFlashVersion() {\n            var version;\n    \n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n    \n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                clients[ uid ] = client;\n    \n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n    \n                    instance = pool[ uid ];\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n    \n                return me.flashExec.apply( client, arguments );\n            };\n    \n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n    \n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n    \n                // console.log.apply( console, arguments );\n    \n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n    \n                // Base.log( evt, obj );\n            }\n    \n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n    \n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n    \n            this.jsreciver = jsreciver;\n    \n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n    \n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n    \n                return flash.exec( this.uid, comp, fn, args );\n            };\n    \n            // @todo\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n    \n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n    \n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n    \n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n    \n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n    \n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n    \n                container.html( html );\n            },\n    \n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n    \n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n    \n        });\n    \n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n    \n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n    \n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n    \n            return component;\n        };\n    \n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n    \n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n    \n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n    \n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n    \n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n    \n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview 图片压缩\n     */\n    define('runtime/flash/image',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n    \n        return FlashRuntime.register( 'Image', {\n            // init: function( options ) {\n            //     var owner = this.owner;\n    \n            //     this.flashExec( 'Image', 'init', options );\n            //     owner.on( 'load', function() {\n            //         debugger;\n            //     });\n            // },\n    \n            loadFromBlob: function( blob ) {\n                var owner = this.owner;\n    \n                owner.info() && this.flashExec( 'Image', 'info', owner.info() );\n                owner.meta() && this.flashExec( 'Image', 'meta', owner.meta() );\n    \n                this.flashExec( 'Image', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n    \n                xhr.connectRuntime( blob.ruid );\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n    \n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            getResponse: function() {\n                return this._response || '';\n            },\n    \n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n    \n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n    \n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n    \n                    xhr.off();\n                    me._xhr = null;\n    \n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n    \n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n    \n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n                            \n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n                            \n                        // }\n                    }\n                    \n                    xhr.destroy();\n                    xhr = null;\n    \n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n    \n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/flash/blob',[\n        'runtime/flash/runtime',\n        'lib/blob'\n    ], function( FlashRuntime, Blob ) {\n    \n        return FlashRuntime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.flashExec( 'Blob', 'slice', start, end );\n    \n                return new Blob( blob.uid, blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Md5 flash实现\n     */\n    define('runtime/flash/md5',[\n        'runtime/flash/runtime'\n    ], function( FlashRuntime ) {\n        \n        return FlashRuntime.register( 'Md5', {\n            init: function() {\n                // do nothing.\n            },\n    \n            loadFromBlob: function( blob ) {\n                return this.flashExec( 'Md5', 'loadFromBlob', blob.uid );\n            }\n        });\n    });\n    /**\n     * @fileOverview 完全版本。\n     */\n    define('preset/all',[\n        'base',\n    \n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/image',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n        'widgets/md5',\n    \n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/imagemeta/exif',\n        'runtime/html5/androidpatch',\n        'runtime/html5/image',\n        'runtime/html5/transport',\n        'runtime/html5/md5',\n    \n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/image',\n        'runtime/flash/transport',\n        'runtime/flash/blob',\n        'runtime/flash/md5'\n    ], function( Base ) {\n        return Base;\n    });\n    define('webuploader',[\n        'preset/all'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/webuploader/0.1.5/webuploader.withoutimage.js",
    "content": "/*! WebUploader 0.1.5 */\n\n\n/**\n * @fileOverview 让内部各个部件的代码可以用[amd](https://github.com/amdjs/amdjs-api/wiki/AMD)模块定义方式组织起来。\n *\n * AMD API 内部的简单不完全实现，请忽略。只有当WebUploader被合并成一个文件的时候才会引入。\n */\n(function( root, factory ) {\n    var modules = {},\n\n        // 内部require, 简单不完全实现。\n        // https://github.com/amdjs/amdjs-api/wiki/require\n        _require = function( deps, callback ) {\n            var args, len, i;\n\n            // 如果deps不是数组，则直接返回指定module\n            if ( typeof deps === 'string' ) {\n                return getModule( deps );\n            } else {\n                args = [];\n                for( len = deps.length, i = 0; i < len; i++ ) {\n                    args.push( getModule( deps[ i ] ) );\n                }\n\n                return callback.apply( null, args );\n            }\n        },\n\n        // 内部define，暂时不支持不指定id.\n        _define = function( id, deps, factory ) {\n            if ( arguments.length === 2 ) {\n                factory = deps;\n                deps = null;\n            }\n\n            _require( deps || [], function() {\n                setModule( id, factory, arguments );\n            });\n        },\n\n        // 设置module, 兼容CommonJs写法。\n        setModule = function( id, factory, args ) {\n            var module = {\n                    exports: factory\n                },\n                returned;\n\n            if ( typeof factory === 'function' ) {\n                args.length || (args = [ _require, module.exports, module ]);\n                returned = factory.apply( null, args );\n                returned !== undefined && (module.exports = returned);\n            }\n\n            modules[ id ] = module.exports;\n        },\n\n        // 根据id获取module\n        getModule = function( id ) {\n            var module = modules[ id ] || root[ id ];\n\n            if ( !module ) {\n                throw new Error( '`' + id + '` is undefined' );\n            }\n\n            return module;\n        },\n\n        // 将所有modules，将路径ids装换成对象。\n        exportsTo = function( obj ) {\n            var key, host, parts, part, last, ucFirst;\n\n            // make the first character upper case.\n            ucFirst = function( str ) {\n                return str && (str.charAt( 0 ).toUpperCase() + str.substr( 1 ));\n            };\n\n            for ( key in modules ) {\n                host = obj;\n\n                if ( !modules.hasOwnProperty( key ) ) {\n                    continue;\n                }\n\n                parts = key.split('/');\n                last = ucFirst( parts.pop() );\n\n                while( (part = ucFirst( parts.shift() )) ) {\n                    host[ part ] = host[ part ] || {};\n                    host = host[ part ];\n                }\n\n                host[ last ] = modules[ key ];\n            }\n\n            return obj;\n        },\n\n        makeExport = function( dollar ) {\n            root.__dollar = dollar;\n\n            // exports every module.\n            return exportsTo( factory( root, _define, _require ) );\n        },\n\n        origin;\n\n    if ( typeof module === 'object' && typeof module.exports === 'object' ) {\n\n        // For CommonJS and CommonJS-like environments where a proper window is present,\n        module.exports = makeExport();\n    } else if ( typeof define === 'function' && define.amd ) {\n\n        // Allow using this built library as an AMD module\n        // in another project. That other project will only\n        // see this AMD call, not the internal modules in\n        // the closure below.\n        define([ 'jquery' ], makeExport );\n    } else {\n\n        // Browser globals case. Just assign the\n        // result to a property on the global.\n        origin = root.WebUploader;\n        root.WebUploader = makeExport();\n        root.WebUploader.noConflict = function() {\n            root.WebUploader = origin;\n        };\n    }\n})( window, function( window, define, require ) {\n\n\n    /**\n     * @fileOverview jQuery or Zepto\n     */\n    define('dollar-third',[],function() {\n        var $ = window.__dollar || window.jQuery || window.Zepto;\n    \n        if ( !$ ) {\n            throw new Error('jQuery or Zepto not found!');\n        }\n    \n        return $;\n    });\n    /**\n     * @fileOverview Dom 操作相关\n     */\n    define('dollar',[\n        'dollar-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 使用jQuery的Promise\n     */\n    define('promise-third',[\n        'dollar'\n    ], function( $ ) {\n        return {\n            Deferred: $.Deferred,\n            when: $.when,\n    \n            isPromise: function( anything ) {\n                return anything && typeof anything.then === 'function';\n            }\n        };\n    });\n    /**\n     * @fileOverview Promise/A+\n     */\n    define('promise',[\n        'promise-third'\n    ], function( _ ) {\n        return _;\n    });\n    /**\n     * @fileOverview 基础类方法。\n     */\n    \n    /**\n     * Web Uploader内部类的详细说明，以下提及的功能类，都可以在`WebUploader`这个变量中访问到。\n     *\n     * As you know, Web Uploader的每个文件都是用过[AMD](https://github.com/amdjs/amdjs-api/wiki/AMD)规范中的`define`组织起来的, 每个Module都会有个module id.\n     * 默认module id为该文件的路径，而此路径将会转化成名字空间存放在WebUploader中。如：\n     *\n     * * module `base`：WebUploader.Base\n     * * module `file`: WebUploader.File\n     * * module `lib/dnd`: WebUploader.Lib.Dnd\n     * * module `runtime/html5/dnd`: WebUploader.Runtime.Html5.Dnd\n     *\n     *\n     * 以下文档中对类的使用可能省略掉了`WebUploader`前缀。\n     * @module WebUploader\n     * @title WebUploader API文档\n     */\n    define('base',[\n        'dollar',\n        'promise'\n    ], function( $, promise ) {\n    \n        var noop = function() {},\n            call = Function.call;\n    \n        // http://jsperf.com/uncurrythis\n        // 反科里化\n        function uncurryThis( fn ) {\n            return function() {\n                return call.apply( fn, arguments );\n            };\n        }\n    \n        function bindFn( fn, context ) {\n            return function() {\n                return fn.apply( context, arguments );\n            };\n        }\n    \n        function createObject( proto ) {\n            var f;\n    \n            if ( Object.create ) {\n                return Object.create( proto );\n            } else {\n                f = function() {};\n                f.prototype = proto;\n                return new f();\n            }\n        }\n    \n    \n        /**\n         * 基础类，提供一些简单常用的方法。\n         * @class Base\n         */\n        return {\n    \n            /**\n             * @property {String} version 当前版本号。\n             */\n            version: '0.1.5',\n    \n            /**\n             * @property {jQuery|Zepto} $ 引用依赖的jQuery或者Zepto对象。\n             */\n            $: $,\n    \n            Deferred: promise.Deferred,\n    \n            isPromise: promise.isPromise,\n    \n            when: promise.when,\n    \n            /**\n             * @description  简单的浏览器检查结果。\n             *\n             * * `webkit`  webkit版本号，如果浏览器为非webkit内核，此属性为`undefined`。\n             * * `chrome`  chrome浏览器版本号，如果浏览器为chrome，此属性为`undefined`。\n             * * `ie`  ie浏览器版本号，如果浏览器为非ie，此属性为`undefined`。**暂不支持ie10+**\n             * * `firefox`  firefox浏览器版本号，如果浏览器为非firefox，此属性为`undefined`。\n             * * `safari`  safari浏览器版本号，如果浏览器为非safari，此属性为`undefined`。\n             * * `opera`  opera浏览器版本号，如果浏览器为非opera，此属性为`undefined`。\n             *\n             * @property {Object} [browser]\n             */\n            browser: (function( ua ) {\n                var ret = {},\n                    webkit = ua.match( /WebKit\\/([\\d.]+)/ ),\n                    chrome = ua.match( /Chrome\\/([\\d.]+)/ ) ||\n                        ua.match( /CriOS\\/([\\d.]+)/ ),\n    \n                    ie = ua.match( /MSIE\\s([\\d\\.]+)/ ) ||\n                        ua.match( /(?:trident)(?:.*rv:([\\w.]+))?/i ),\n                    firefox = ua.match( /Firefox\\/([\\d.]+)/ ),\n                    safari = ua.match( /Safari\\/([\\d.]+)/ ),\n                    opera = ua.match( /OPR\\/([\\d.]+)/ );\n    \n                webkit && (ret.webkit = parseFloat( webkit[ 1 ] ));\n                chrome && (ret.chrome = parseFloat( chrome[ 1 ] ));\n                ie && (ret.ie = parseFloat( ie[ 1 ] ));\n                firefox && (ret.firefox = parseFloat( firefox[ 1 ] ));\n                safari && (ret.safari = parseFloat( safari[ 1 ] ));\n                opera && (ret.opera = parseFloat( opera[ 1 ] ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * @description  操作系统检查结果。\n             *\n             * * `android`  如果在android浏览器环境下，此值为对应的android版本号，否则为`undefined`。\n             * * `ios` 如果在ios浏览器环境下，此值为对应的ios版本号，否则为`undefined`。\n             * @property {Object} [os]\n             */\n            os: (function( ua ) {\n                var ret = {},\n    \n                    // osx = !!ua.match( /\\(Macintosh\\; Intel / ),\n                    android = ua.match( /(?:Android);?[\\s\\/]+([\\d.]+)?/ ),\n                    ios = ua.match( /(?:iPad|iPod|iPhone).*OS\\s([\\d_]+)/ );\n    \n                // osx && (ret.osx = true);\n                android && (ret.android = parseFloat( android[ 1 ] ));\n                ios && (ret.ios = parseFloat( ios[ 1 ].replace( /_/g, '.' ) ));\n    \n                return ret;\n            })( navigator.userAgent ),\n    \n            /**\n             * 实现类与类之间的继承。\n             * @method inherits\n             * @grammar Base.inherits( super ) => child\n             * @grammar Base.inherits( super, protos ) => child\n             * @grammar Base.inherits( super, protos, statics ) => child\n             * @param  {Class} super 父类\n             * @param  {Object | Function} [protos] 子类或者对象。如果对象中包含constructor，子类将是用此属性值。\n             * @param  {Function} [protos.constructor] 子类构造器，不指定的话将创建个临时的直接执行父类构造器的方法。\n             * @param  {Object} [statics] 静态属性或方法。\n             * @return {Class} 返回子类。\n             * @example\n             * function Person() {\n             *     console.log( 'Super' );\n             * }\n             * Person.prototype.hello = function() {\n             *     console.log( 'hello' );\n             * };\n             *\n             * var Manager = Base.inherits( Person, {\n             *     world: function() {\n             *         console.log( 'World' );\n             *     }\n             * });\n             *\n             * // 因为没有指定构造器，父类的构造器将会执行。\n             * var instance = new Manager();    // => Super\n             *\n             * // 继承子父类的方法\n             * instance.hello();    // => hello\n             * instance.world();    // => World\n             *\n             * // 子类的__super__属性指向父类\n             * console.log( Manager.__super__ === Person );    // => true\n             */\n            inherits: function( Super, protos, staticProtos ) {\n                var child;\n    \n                if ( typeof protos === 'function' ) {\n                    child = protos;\n                    protos = null;\n                } else if ( protos && protos.hasOwnProperty('constructor') ) {\n                    child = protos.constructor;\n                } else {\n                    child = function() {\n                        return Super.apply( this, arguments );\n                    };\n                }\n    \n                // 复制静态方法\n                $.extend( true, child, Super, staticProtos || {} );\n    \n                /* jshint camelcase: false */\n    \n                // 让子类的__super__属性指向父类。\n                child.__super__ = Super.prototype;\n    \n                // 构建原型，添加原型方法或属性。\n                // 暂时用Object.create实现。\n                child.prototype = createObject( Super.prototype );\n                protos && $.extend( true, child.prototype, protos );\n    \n                return child;\n            },\n    \n            /**\n             * 一个不做任何事情的方法。可以用来赋值给默认的callback.\n             * @method noop\n             */\n            noop: noop,\n    \n            /**\n             * 返回一个新的方法，此方法将已指定的`context`来执行。\n             * @grammar Base.bindFn( fn, context ) => Function\n             * @method bindFn\n             * @example\n             * var doSomething = function() {\n             *         console.log( this.name );\n             *     },\n             *     obj = {\n             *         name: 'Object Name'\n             *     },\n             *     aliasFn = Base.bind( doSomething, obj );\n             *\n             *  aliasFn();    // => Object Name\n             *\n             */\n            bindFn: bindFn,\n    \n            /**\n             * 引用Console.log如果存在的话，否则引用一个[空函数noop](#WebUploader:Base.noop)。\n             * @grammar Base.log( args... ) => undefined\n             * @method log\n             */\n            log: (function() {\n                if ( window.console ) {\n                    return bindFn( console.log, console );\n                }\n                return noop;\n            })(),\n    \n            nextTick: (function() {\n    \n                return function( cb ) {\n                    setTimeout( cb, 1 );\n                };\n    \n                // @bug 当浏览器不在当前窗口时就停了。\n                // var next = window.requestAnimationFrame ||\n                //     window.webkitRequestAnimationFrame ||\n                //     window.mozRequestAnimationFrame ||\n                //     function( cb ) {\n                //         window.setTimeout( cb, 1000 / 60 );\n                //     };\n    \n                // // fix: Uncaught TypeError: Illegal invocation\n                // return bindFn( next, window );\n            })(),\n    \n            /**\n             * 被[uncurrythis](http://www.2ality.com/2011/11/uncurrying-this.html)的数组slice方法。\n             * 将用来将非数组对象转化成数组对象。\n             * @grammar Base.slice( target, start[, end] ) => Array\n             * @method slice\n             * @example\n             * function doSomthing() {\n             *     var args = Base.slice( arguments, 1 );\n             *     console.log( args );\n             * }\n             *\n             * doSomthing( 'ignored', 'arg2', 'arg3' );    // => Array [\"arg2\", \"arg3\"]\n             */\n            slice: uncurryThis( [].slice ),\n    \n            /**\n             * 生成唯一的ID\n             * @method guid\n             * @grammar Base.guid() => String\n             * @grammar Base.guid( prefx ) => String\n             */\n            guid: (function() {\n                var counter = 0;\n    \n                return function( prefix ) {\n                    var guid = (+new Date()).toString( 32 ),\n                        i = 0;\n    \n                    for ( ; i < 5; i++ ) {\n                        guid += Math.floor( Math.random() * 65535 ).toString( 32 );\n                    }\n    \n                    return (prefix || 'wu_') + guid + (counter++).toString( 32 );\n                };\n            })(),\n    \n            /**\n             * 格式化文件大小, 输出成带单位的字符串\n             * @method formatSize\n             * @grammar Base.formatSize( size ) => String\n             * @grammar Base.formatSize( size, pointLength ) => String\n             * @grammar Base.formatSize( size, pointLength, units ) => String\n             * @param {Number} size 文件大小\n             * @param {Number} [pointLength=2] 精确到的小数点数。\n             * @param {Array} [units=[ 'B', 'K', 'M', 'G', 'TB' ]] 单位数组。从字节，到千字节，一直往上指定。如果单位数组里面只指定了到了K(千字节)，同时文件大小大于M, 此方法的输出将还是显示成多少K.\n             * @example\n             * console.log( Base.formatSize( 100 ) );    // => 100B\n             * console.log( Base.formatSize( 1024 ) );    // => 1.00K\n             * console.log( Base.formatSize( 1024, 0 ) );    // => 1K\n             * console.log( Base.formatSize( 1024 * 1024 ) );    // => 1.00M\n             * console.log( Base.formatSize( 1024 * 1024 * 1024 ) );    // => 1.00G\n             * console.log( Base.formatSize( 1024 * 1024 * 1024, 0, ['B', 'KB', 'MB'] ) );    // => 1024MB\n             */\n            formatSize: function( size, pointLength, units ) {\n                var unit;\n    \n                units = units || [ 'B', 'K', 'M', 'G', 'TB' ];\n    \n                while ( (unit = units.shift()) && size > 1024 ) {\n                    size = size / 1024;\n                }\n    \n                return (unit === 'B' ? size : size.toFixed( pointLength || 2 )) +\n                        unit;\n            }\n        };\n    });\n    /**\n     * 事件处理类，可以独立使用，也可以扩展给对象使用。\n     * @fileOverview Mediator\n     */\n    define('mediator',[\n        'base'\n    ], function( Base ) {\n        var $ = Base.$,\n            slice = [].slice,\n            separator = /\\s+/,\n            protos;\n    \n        // 根据条件过滤出事件handlers.\n        function findHandlers( arr, name, callback, context ) {\n            return $.grep( arr, function( handler ) {\n                return handler &&\n                        (!name || handler.e === name) &&\n                        (!callback || handler.cb === callback ||\n                        handler.cb._cb === callback) &&\n                        (!context || handler.ctx === context);\n            });\n        }\n    \n        function eachEvent( events, callback, iterator ) {\n            // 不支持对象，只支持多个event用空格隔开\n            $.each( (events || '').split( separator ), function( _, key ) {\n                iterator( key, callback );\n            });\n        }\n    \n        function triggerHanders( events, args ) {\n            var stoped = false,\n                i = -1,\n                len = events.length,\n                handler;\n    \n            while ( ++i < len ) {\n                handler = events[ i ];\n    \n                if ( handler.cb.apply( handler.ctx2, args ) === false ) {\n                    stoped = true;\n                    break;\n                }\n            }\n    \n            return !stoped;\n        }\n    \n        protos = {\n    \n            /**\n             * 绑定事件。\n             *\n             * `callback`方法在执行时，arguments将会来源于trigger的时候携带的参数。如\n             * ```javascript\n             * var obj = {};\n             *\n             * // 使得obj有事件行为\n             * Mediator.installTo( obj );\n             *\n             * obj.on( 'testa', function( arg1, arg2 ) {\n             *     console.log( arg1, arg2 ); // => 'arg1', 'arg2'\n             * });\n             *\n             * obj.trigger( 'testa', 'arg1', 'arg2' );\n             * ```\n             *\n             * 如果`callback`中，某一个方法`return false`了，则后续的其他`callback`都不会被执行到。\n             * 切会影响到`trigger`方法的返回值，为`false`。\n             *\n             * `on`还可以用来添加一个特殊事件`all`, 这样所有的事件触发都会响应到。同时此类`callback`中的arguments有一个不同处，\n             * 就是第一个参数为`type`，记录当前是什么事件在触发。此类`callback`的优先级比脚低，会再正常`callback`执行完后触发。\n             * ```javascript\n             * obj.on( 'all', function( type, arg1, arg2 ) {\n             *     console.log( type, arg1, arg2 ); // => 'testa', 'arg1', 'arg2'\n             * });\n             * ```\n             *\n             * @method on\n             * @grammar on( name, callback[, context] ) => self\n             * @param  {String}   name     事件名，支持多个事件用空格隔开\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             * @class Mediator\n             */\n            on: function( name, callback, context ) {\n                var me = this,\n                    set;\n    \n                if ( !callback ) {\n                    return this;\n                }\n    \n                set = this._events || (this._events = []);\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var handler = { e: name };\n    \n                    handler.cb = callback;\n                    handler.ctx = context;\n                    handler.ctx2 = context || me;\n                    handler.id = set.length;\n    \n                    set.push( handler );\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 绑定事件，且当handler执行完后，自动解除绑定。\n             * @method once\n             * @grammar once( name, callback[, context] ) => self\n             * @param  {String}   name     事件名\n             * @param  {Function} callback 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            once: function( name, callback, context ) {\n                var me = this;\n    \n                if ( !callback ) {\n                    return me;\n                }\n    \n                eachEvent( name, callback, function( name, callback ) {\n                    var once = function() {\n                            me.off( name, once );\n                            return callback.apply( context || me, arguments );\n                        };\n    \n                    once._cb = callback;\n                    me.on( name, once, context );\n                });\n    \n                return me;\n            },\n    \n            /**\n             * 解除事件绑定\n             * @method off\n             * @grammar off( [name[, callback[, context] ] ] ) => self\n             * @param  {String}   [name]     事件名\n             * @param  {Function} [callback] 事件处理器\n             * @param  {Object}   [context]  事件处理器的上下文。\n             * @return {self} 返回自身，方便链式\n             * @chainable\n             */\n            off: function( name, cb, ctx ) {\n                var events = this._events;\n    \n                if ( !events ) {\n                    return this;\n                }\n    \n                if ( !name && !cb && !ctx ) {\n                    this._events = [];\n                    return this;\n                }\n    \n                eachEvent( name, cb, function( name, cb ) {\n                    $.each( findHandlers( events, name, cb, ctx ), function() {\n                        delete events[ this.id ];\n                    });\n                });\n    \n                return this;\n            },\n    \n            /**\n             * 触发事件\n             * @method trigger\n             * @grammar trigger( name[, args...] ) => self\n             * @param  {String}   type     事件名\n             * @param  {*} [...] 任意参数\n             * @return {Boolean} 如果handler中return false了，则返回false, 否则返回true\n             */\n            trigger: function( type ) {\n                var args, events, allEvents;\n    \n                if ( !this._events || !type ) {\n                    return this;\n                }\n    \n                args = slice.call( arguments, 1 );\n                events = findHandlers( this._events, type );\n                allEvents = findHandlers( this._events, 'all' );\n    \n                return triggerHanders( events, args ) &&\n                        triggerHanders( allEvents, arguments );\n            }\n        };\n    \n        /**\n         * 中介者，它本身是个单例，但可以通过[installTo](#WebUploader:Mediator:installTo)方法，使任何对象具备事件行为。\n         * 主要目的是负责模块与模块之间的合作，降低耦合度。\n         *\n         * @class Mediator\n         */\n        return $.extend({\n    \n            /**\n             * 可以通过这个接口，使任何对象具备事件功能。\n             * @method installTo\n             * @param  {Object} obj 需要具备事件行为的对象。\n             * @return {Object} 返回obj.\n             */\n            installTo: function( obj ) {\n                return $.extend( obj, protos );\n            }\n    \n        }, protos );\n    });\n    /**\n     * @fileOverview Uploader上传类\n     */\n    define('uploader',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$;\n    \n        /**\n         * 上传入口类。\n         * @class Uploader\n         * @constructor\n         * @grammar new Uploader( opts ) => Uploader\n         * @example\n         * var uploader = WebUploader.Uploader({\n         *     swf: 'path_of_swf/Uploader.swf',\n         *\n         *     // 开起分片上传。\n         *     chunked: true\n         * });\n         */\n        function Uploader( opts ) {\n            this.options = $.extend( true, {}, Uploader.options, opts );\n            this._init( this.options );\n        }\n    \n        // default Options\n        // widgets中有相应扩展\n        Uploader.options = {};\n        Mediator.installTo( Uploader.prototype );\n    \n        // 批量添加纯命令式方法。\n        $.each({\n            upload: 'start-upload',\n            stop: 'stop-upload',\n            getFile: 'get-file',\n            getFiles: 'get-files',\n            addFile: 'add-file',\n            addFiles: 'add-file',\n            sort: 'sort-files',\n            removeFile: 'remove-file',\n            cancelFile: 'cancel-file',\n            skipFile: 'skip-file',\n            retry: 'retry',\n            isInProgress: 'is-in-progress',\n            makeThumb: 'make-thumb',\n            md5File: 'md5-file',\n            getDimension: 'get-dimension',\n            addButton: 'add-btn',\n            predictRuntimeType: 'predict-runtime-type',\n            refresh: 'refresh',\n            disable: 'disable',\n            enable: 'enable',\n            reset: 'reset'\n        }, function( fn, command ) {\n            Uploader.prototype[ fn ] = function() {\n                return this.request( command, arguments );\n            };\n        });\n    \n        $.extend( Uploader.prototype, {\n            state: 'pending',\n    \n            _init: function( opts ) {\n                var me = this;\n    \n                me.request( 'init', opts, function() {\n                    me.state = 'ready';\n                    me.trigger('ready');\n                });\n            },\n    \n            /**\n             * 获取或者设置Uploader配置项。\n             * @method option\n             * @grammar option( key ) => *\n             * @grammar option( key, val ) => self\n             * @example\n             *\n             * // 初始状态图片上传前不会压缩\n             * var uploader = new WebUploader.Uploader({\n             *     compress: null;\n             * });\n             *\n             * // 修改后图片上传前，尝试将图片压缩到1600 * 1600\n             * uploader.option( 'compress', {\n             *     width: 1600,\n             *     height: 1600\n             * });\n             */\n            option: function( key, val ) {\n                var opts = this.options;\n    \n                // setter\n                if ( arguments.length > 1 ) {\n    \n                    if ( $.isPlainObject( val ) &&\n                            $.isPlainObject( opts[ key ] ) ) {\n                        $.extend( opts[ key ], val );\n                    } else {\n                        opts[ key ] = val;\n                    }\n    \n                } else {    // getter\n                    return key ? opts[ key ] : opts;\n                }\n            },\n    \n            /**\n             * 获取文件统计信息。返回一个包含一下信息的对象。\n             * * `successNum` 上传成功的文件数\n             * * `progressNum` 上传中的文件数\n             * * `cancelNum` 被删除的文件数\n             * * `invalidNum` 无效的文件数\n             * * `uploadFailNum` 上传失败的文件数\n             * * `queueNum` 还在队列中的文件数\n             * * `interruptNum` 被暂停的文件数\n             * @method getStats\n             * @grammar getStats() => Object\n             */\n            getStats: function() {\n                // return this._mgr.getStats.apply( this._mgr, arguments );\n                var stats = this.request('get-stats');\n    \n                return stats ? {\n                    successNum: stats.numOfSuccess,\n                    progressNum: stats.numOfProgress,\n    \n                    // who care?\n                    // queueFailNum: 0,\n                    cancelNum: stats.numOfCancel,\n                    invalidNum: stats.numOfInvalid,\n                    uploadFailNum: stats.numOfUploadFailed,\n                    queueNum: stats.numOfQueue,\n                    interruptNum: stats.numofInterrupt\n                } : {};\n            },\n    \n            // 需要重写此方法来来支持opts.onEvent和instance.onEvent的处理器\n            trigger: function( type/*, args...*/ ) {\n                var args = [].slice.call( arguments, 1 ),\n                    opts = this.options,\n                    name = 'on' + type.substring( 0, 1 ).toUpperCase() +\n                        type.substring( 1 );\n    \n                if (\n                        // 调用通过on方法注册的handler.\n                        Mediator.trigger.apply( this, arguments ) === false ||\n    \n                        // 调用opts.onEvent\n                        $.isFunction( opts[ name ] ) &&\n                        opts[ name ].apply( this, args ) === false ||\n    \n                        // 调用this.onEvent\n                        $.isFunction( this[ name ] ) &&\n                        this[ name ].apply( this, args ) === false ||\n    \n                        // 广播所有uploader的事件。\n                        Mediator.trigger.apply( Mediator,\n                        [ this, type ].concat( args ) ) === false ) {\n    \n                    return false;\n                }\n    \n                return true;\n            },\n    \n            /**\n             * 销毁 webuploader 实例\n             * @method destroy\n             * @grammar destroy() => undefined\n             */\n            destroy: function() {\n                this.request( 'destroy', arguments );\n                this.off();\n            },\n    \n            // widgets/widget.js将补充此方法的详细文档。\n            request: Base.noop\n        });\n    \n        /**\n         * 创建Uploader实例，等同于new Uploader( opts );\n         * @method create\n         * @class Base\n         * @static\n         * @grammar Base.create( opts ) => Uploader\n         */\n        Base.create = Uploader.create = function( opts ) {\n            return new Uploader( opts );\n        };\n    \n        // 暴露Uploader，可以通过它来扩展业务逻辑。\n        Base.Uploader = Uploader;\n    \n        return Uploader;\n    });\n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/runtime',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            factories = {},\n    \n            // 获取对象的第一个key\n            getFirstKey = function( obj ) {\n                for ( var key in obj ) {\n                    if ( obj.hasOwnProperty( key ) ) {\n                        return key;\n                    }\n                }\n                return null;\n            };\n    \n        // 接口类。\n        function Runtime( options ) {\n            this.options = $.extend({\n                container: document.body\n            }, options );\n            this.uid = Base.guid('rt_');\n        }\n    \n        $.extend( Runtime.prototype, {\n    \n            getContainer: function() {\n                var opts = this.options,\n                    parent, container;\n    \n                if ( this._container ) {\n                    return this._container;\n                }\n    \n                parent = $( opts.container || document.body );\n                container = $( document.createElement('div') );\n    \n                container.attr( 'id', 'rt_' + this.uid );\n                container.css({\n                    position: 'absolute',\n                    top: '0px',\n                    left: '0px',\n                    width: '1px',\n                    height: '1px',\n                    overflow: 'hidden'\n                });\n    \n                parent.append( container );\n                parent.addClass('webuploader-container');\n                this._container = container;\n                this._parent = parent;\n                return container;\n            },\n    \n            init: Base.noop,\n            exec: Base.noop,\n    \n            destroy: function() {\n                this._container && this._container.remove();\n                this._parent && this._parent.removeClass('webuploader-container');\n                this.off();\n            }\n        });\n    \n        Runtime.orders = 'html5,flash';\n    \n    \n        /**\n         * 添加Runtime实现。\n         * @param {String} type    类型\n         * @param {Runtime} factory 具体Runtime实现。\n         */\n        Runtime.addRuntime = function( type, factory ) {\n            factories[ type ] = factory;\n        };\n    \n        Runtime.hasRuntime = function( type ) {\n            return !!(type ? factories[ type ] : getFirstKey( factories ));\n        };\n    \n        Runtime.create = function( opts, orders ) {\n            var type, runtime;\n    \n            orders = orders || Runtime.orders;\n            $.each( orders.split( /\\s*,\\s*/g ), function() {\n                if ( factories[ this ] ) {\n                    type = this;\n                    return false;\n                }\n            });\n    \n            type = type || getFirstKey( factories );\n    \n            if ( !type ) {\n                throw new Error('Runtime Error');\n            }\n    \n            runtime = new factories[ type ]( opts );\n            return runtime;\n        };\n    \n        Mediator.installTo( Runtime.prototype );\n        return Runtime;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/client',[\n        'base',\n        'mediator',\n        'runtime/runtime'\n    ], function( Base, Mediator, Runtime ) {\n    \n        var cache;\n    \n        cache = (function() {\n            var obj = {};\n    \n            return {\n                add: function( runtime ) {\n                    obj[ runtime.uid ] = runtime;\n                },\n    \n                get: function( ruid, standalone ) {\n                    var i;\n    \n                    if ( ruid ) {\n                        return obj[ ruid ];\n                    }\n    \n                    for ( i in obj ) {\n                        // 有些类型不能重用，比如filepicker.\n                        if ( standalone && obj[ i ].__standalone ) {\n                            continue;\n                        }\n    \n                        return obj[ i ];\n                    }\n    \n                    return null;\n                },\n    \n                remove: function( runtime ) {\n                    delete obj[ runtime.uid ];\n                }\n            };\n        })();\n    \n        function RuntimeClient( component, standalone ) {\n            var deferred = Base.Deferred(),\n                runtime;\n    \n            this.uid = Base.guid('client_');\n    \n            // 允许runtime没有初始化之前，注册一些方法在初始化后执行。\n            this.runtimeReady = function( cb ) {\n                return deferred.done( cb );\n            };\n    \n            this.connectRuntime = function( opts, cb ) {\n    \n                // already connected.\n                if ( runtime ) {\n                    throw new Error('already connected!');\n                }\n    \n                deferred.done( cb );\n    \n                if ( typeof opts === 'string' && cache.get( opts ) ) {\n                    runtime = cache.get( opts );\n                }\n    \n                // 像filePicker只能独立存在，不能公用。\n                runtime = runtime || cache.get( null, standalone );\n    \n                // 需要创建\n                if ( !runtime ) {\n                    runtime = Runtime.create( opts, opts.runtimeOrder );\n                    runtime.__promise = deferred.promise();\n                    runtime.once( 'ready', deferred.resolve );\n                    runtime.init();\n                    cache.add( runtime );\n                    runtime.__client = 1;\n                } else {\n                    // 来自cache\n                    Base.$.extend( runtime.options, opts );\n                    runtime.__promise.then( deferred.resolve );\n                    runtime.__client++;\n                }\n    \n                standalone && (runtime.__standalone = standalone);\n                return runtime;\n            };\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.disconnectRuntime = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                runtime.__client--;\n    \n                if ( runtime.__client <= 0 ) {\n                    cache.remove( runtime );\n                    delete runtime.__promise;\n                    runtime.destroy();\n                }\n    \n                runtime = null;\n            };\n    \n            this.exec = function() {\n                if ( !runtime ) {\n                    return;\n                }\n    \n                var args = Base.slice( arguments );\n                component && args.unshift( component );\n    \n                return runtime.exec.apply( this, args );\n            };\n    \n            this.getRuid = function() {\n                return runtime && runtime.uid;\n            };\n    \n            this.destroy = (function( destroy ) {\n                return function() {\n                    destroy && destroy.apply( this, arguments );\n                    this.trigger('destroy');\n                    this.off();\n                    this.exec('destroy');\n                    this.disconnectRuntime();\n                };\n            })( this.destroy );\n        }\n    \n        Mediator.installTo( RuntimeClient.prototype );\n        return RuntimeClient;\n    });\n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/dnd',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function DragAndDrop( opts ) {\n            opts = this.options = $.extend({}, DragAndDrop.options, opts );\n    \n            opts.container = $( opts.container );\n    \n            if ( !opts.container.length ) {\n                return;\n            }\n    \n            RuntimeClent.call( this, 'DragAndDrop' );\n        }\n    \n        DragAndDrop.options = {\n            accept: null,\n            disableGlobalDnd: false\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: DragAndDrop,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( DragAndDrop.prototype );\n    \n        return DragAndDrop;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/widget',[\n        'base',\n        'uploader'\n    ], function( Base, Uploader ) {\n    \n        var $ = Base.$,\n            _init = Uploader.prototype._init,\n            _destroy = Uploader.prototype.destroy,\n            IGNORE = {},\n            widgetClass = [];\n    \n        function isArrayLike( obj ) {\n            if ( !obj ) {\n                return false;\n            }\n    \n            var length = obj.length,\n                type = $.type( obj );\n    \n            if ( obj.nodeType === 1 && length ) {\n                return true;\n            }\n    \n            return type === 'array' || type !== 'function' && type !== 'string' &&\n                    (length === 0 || typeof length === 'number' && length > 0 &&\n                    (length - 1) in obj);\n        }\n    \n        function Widget( uploader ) {\n            this.owner = uploader;\n            this.options = uploader.options;\n        }\n    \n        $.extend( Widget.prototype, {\n    \n            init: Base.noop,\n    \n            // 类Backbone的事件监听声明，监听uploader实例上的事件\n            // widget直接无法监听事件，事件只能通过uploader来传递\n            invoke: function( apiName, args ) {\n    \n                /*\n                    {\n                        'make-thumb': 'makeThumb'\n                    }\n                 */\n                var map = this.responseMap;\n    \n                // 如果无API响应声明则忽略\n                if ( !map || !(apiName in map) || !(map[ apiName ] in this) ||\n                        !$.isFunction( this[ map[ apiName ] ] ) ) {\n    \n                    return IGNORE;\n                }\n    \n                return this[ map[ apiName ] ].apply( this, args );\n    \n            },\n    \n            /**\n             * 发送命令。当传入`callback`或者`handler`中返回`promise`时。返回一个当所有`handler`中的promise都完成后完成的新`promise`。\n             * @method request\n             * @grammar request( command, args ) => * | Promise\n             * @grammar request( command, args, callback ) => Promise\n             * @for  Uploader\n             */\n            request: function() {\n                return this.owner.request.apply( this.owner, arguments );\n            }\n        });\n    \n        // 扩展Uploader.\n        $.extend( Uploader.prototype, {\n    \n            /**\n             * @property {String | Array} [disableWidgets=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 默认所有 Uploader.register 了的 widget 都会被加载，如果禁用某一部分，请通过此 option 指定黑名单。\n             */\n    \n            // 覆写_init用来初始化widgets\n            _init: function() {\n                var me = this,\n                    widgets = me._widgets = [],\n                    deactives = me.options.disableWidgets || '';\n    \n                $.each( widgetClass, function( _, klass ) {\n                    (!deactives || !~deactives.indexOf( klass._name )) &&\n                        widgets.push( new klass( me ) );\n                });\n    \n                return _init.apply( me, arguments );\n            },\n    \n            request: function( apiName, args, callback ) {\n                var i = 0,\n                    widgets = this._widgets,\n                    len = widgets && widgets.length,\n                    rlts = [],\n                    dfds = [],\n                    widget, rlt, promise, key;\n    \n                args = isArrayLike( args ) ? args : [ args ];\n    \n                for ( ; i < len; i++ ) {\n                    widget = widgets[ i ];\n                    rlt = widget.invoke( apiName, args );\n    \n                    if ( rlt !== IGNORE ) {\n    \n                        // Deferred对象\n                        if ( Base.isPromise( rlt ) ) {\n                            dfds.push( rlt );\n                        } else {\n                            rlts.push( rlt );\n                        }\n                    }\n                }\n    \n                // 如果有callback，则用异步方式。\n                if ( callback || dfds.length ) {\n                    promise = Base.when.apply( Base, dfds );\n                    key = promise.pipe ? 'pipe' : 'then';\n    \n                    // 很重要不能删除。删除了会死循环。\n                    // 保证执行顺序。让callback总是在下一个 tick 中执行。\n                    return promise[ key ](function() {\n                                var deferred = Base.Deferred(),\n                                    args = arguments;\n    \n                                if ( args.length === 1 ) {\n                                    args = args[ 0 ];\n                                }\n    \n                                setTimeout(function() {\n                                    deferred.resolve( args );\n                                }, 1 );\n    \n                                return deferred.promise();\n                            })[ callback ? key : 'done' ]( callback || Base.noop );\n                } else {\n                    return rlts[ 0 ];\n                }\n            },\n    \n            destroy: function() {\n                _destroy.apply( this, arguments );\n                this._widgets = null;\n            }\n        });\n    \n        /**\n         * 添加组件\n         * @grammar Uploader.register(proto);\n         * @grammar Uploader.register(map, proto);\n         * @param  {object} responseMap API 名称与函数实现的映射\n         * @param  {object} proto 组件原型，构造函数通过 constructor 属性定义\n         * @method Uploader.register\n         * @for Uploader\n         * @example\n         * Uploader.register({\n         *     'make-thumb': 'makeThumb'\n         * }, {\n         *     init: function( options ) {},\n         *     makeThumb: function() {}\n         * });\n         *\n         * Uploader.register({\n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         */\n        Uploader.register = Widget.register = function( responseMap, widgetProto ) {\n            var map = { init: 'init', destroy: 'destroy', name: 'anonymous' },\n                klass;\n    \n            if ( arguments.length === 1 ) {\n                widgetProto = responseMap;\n    \n                // 自动生成 map 表。\n                $.each(widgetProto, function(key) {\n                    if ( key[0] === '_' || key === 'name' ) {\n                        key === 'name' && (map.name = widgetProto.name);\n                        return;\n                    }\n    \n                    map[key.replace(/[A-Z]/g, '-$&').toLowerCase()] = key;\n                });\n    \n            } else {\n                map = $.extend( map, responseMap );\n            }\n    \n            widgetProto.responseMap = map;\n            klass = Base.inherits( Widget, widgetProto );\n            klass._name = map.name;\n            widgetClass.push( klass );\n    \n            return klass;\n        };\n    \n        /**\n         * 删除插件，只有在注册时指定了名字的才能被删除。\n         * @grammar Uploader.unRegister(name);\n         * @param  {string} name 组件名字\n         * @method Uploader.unRegister\n         * @for Uploader\n         * @example\n         *\n         * Uploader.register({\n         *     name: 'custom',\n         *     \n         *     'make-thumb': function() {\n         *         \n         *     }\n         * });\n         *\n         * Uploader.unRegister('custom');\n         */\n        Uploader.unRegister = Widget.unRegister = function( name ) {\n            if ( !name || name === 'anonymous' ) {\n                return;\n            }\n            \n            // 删除指定的插件。\n            for ( var i = widgetClass.length; i--; ) {\n                if ( widgetClass[i]._name === name ) {\n                    widgetClass.splice(i, 1)\n                }\n            }\n        };\n    \n        return Widget;\n    });\n    /**\n     * @fileOverview DragAndDrop Widget。\n     */\n    define('widgets/filednd',[\n        'base',\n        'uploader',\n        'lib/dnd',\n        'widgets/widget'\n    ], function( Base, Uploader, Dnd ) {\n        var $ = Base.$;\n    \n        Uploader.options.dnd = '';\n    \n        /**\n         * @property {Selector} [dnd=undefined]  指定Drag And Drop拖拽的容器，如果不指定，则不启动。\n         * @namespace options\n         * @for Uploader\n         */\n        \n        /**\n         * @property {Selector} [disableGlobalDnd=false]  是否禁掉整个页面的拖拽功能，如果不禁用，图片拖进来的时候会默认被浏览器打开。\n         * @namespace options\n         * @for Uploader\n         */\n    \n        /**\n         * @event dndAccept\n         * @param {DataTransferItemList} items DataTransferItem\n         * @description 阻止此事件可以拒绝某些类型的文件拖入进来。目前只有 chrome 提供这样的 API，且只能通过 mime-type 验证。\n         * @for  Uploader\n         */\n        return Uploader.register({\n            name: 'dnd',\n            \n            init: function( opts ) {\n    \n                if ( !opts.dnd ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        disableGlobalDnd: opts.disableGlobalDnd,\n                        container: opts.dnd,\n                        accept: opts.accept\n                    }),\n                    dnd;\n    \n                this.dnd = dnd = new Dnd( options );\n    \n                dnd.once( 'ready', deferred.resolve );\n                dnd.on( 'drop', function( files ) {\n                    me.request( 'add-file', [ files ]);\n                });\n    \n                // 检测文件是否全部允许添加。\n                dnd.on( 'accept', function( items ) {\n                    return me.owner.trigger( 'dndAccept', items );\n                });\n    \n                dnd.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.dnd && this.dnd.destroy();\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepaste',[\n        'base',\n        'mediator',\n        'runtime/client'\n    ], function( Base, Mediator, RuntimeClent ) {\n    \n        var $ = Base.$;\n    \n        function FilePaste( opts ) {\n            opts = this.options = $.extend({}, opts );\n            opts.container = $( opts.container || document.body );\n            RuntimeClent.call( this, 'FilePaste' );\n        }\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePaste,\n    \n            init: function() {\n                var me = this;\n    \n                me.connectRuntime( me.options, function() {\n                    me.exec('init');\n                    me.trigger('ready');\n                });\n            }\n        });\n    \n        Mediator.installTo( FilePaste.prototype );\n    \n        return FilePaste;\n    });\n    /**\n     * @fileOverview 组件基类。\n     */\n    define('widgets/filepaste',[\n        'base',\n        'uploader',\n        'lib/filepaste',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePaste ) {\n        var $ = Base.$;\n    \n        /**\n         * @property {Selector} [paste=undefined]  指定监听paste事件的容器，如果不指定，不启用此功能。此功能为通过粘贴来添加截屏的图片。建议设置为`document.body`.\n         * @namespace options\n         * @for Uploader\n         */\n        return Uploader.register({\n            name: 'paste',\n            \n            init: function( opts ) {\n    \n                if ( !opts.paste ||\n                        this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                var me = this,\n                    deferred = Base.Deferred(),\n                    options = $.extend({}, {\n                        container: opts.paste,\n                        accept: opts.accept\n                    }),\n                    paste;\n    \n                this.paste = paste = new FilePaste( options );\n    \n                paste.once( 'ready', deferred.resolve );\n                paste.on( 'paste', function( files ) {\n                    me.owner.request( 'add-file', [ files ]);\n                });\n                paste.init();\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                this.paste && this.paste.destroy();\n            }\n        });\n    });\n    /**\n     * @fileOverview Blob\n     */\n    define('lib/blob',[\n        'base',\n        'runtime/client'\n    ], function( Base, RuntimeClient ) {\n    \n        function Blob( ruid, source ) {\n            var me = this;\n    \n            me.source = source;\n            me.ruid = ruid;\n            this.size = source.size || 0;\n    \n            // 如果没有指定 mimetype, 但是知道文件后缀。\n            if ( !source.type && this.ext &&\n                    ~'jpg,jpeg,png,gif,bmp'.indexOf( this.ext ) ) {\n                this.type = 'image/' + (this.ext === 'jpg' ? 'jpeg' : this.ext);\n            } else {\n                this.type = source.type || 'application/octet-stream';\n            }\n    \n            RuntimeClient.call( me, 'Blob' );\n            this.uid = source.uid || this.uid;\n    \n            if ( ruid ) {\n                me.connectRuntime( ruid );\n            }\n        }\n    \n        Base.inherits( RuntimeClient, {\n            constructor: Blob,\n    \n            slice: function( start, end ) {\n                return this.exec( 'slice', start, end );\n            },\n    \n            getSource: function() {\n                return this.source;\n            }\n        });\n    \n        return Blob;\n    });\n    /**\n     * 为了统一化Flash的File和HTML5的File而存在。\n     * 以至于要调用Flash里面的File，也可以像调用HTML5版本的File一下。\n     * @fileOverview File\n     */\n    define('lib/file',[\n        'base',\n        'lib/blob'\n    ], function( Base, Blob ) {\n    \n        var uid = 1,\n            rExt = /\\.([^.]+)$/;\n    \n        function File( ruid, file ) {\n            var ext;\n    \n            this.name = file.name || ('untitled' + uid++);\n            ext = rExt.exec( file.name ) ? RegExp.$1.toLowerCase() : '';\n    \n            // todo 支持其他类型文件的转换。\n            // 如果有 mimetype, 但是文件名里面没有找出后缀规律\n            if ( !ext && file.type ) {\n                ext = /\\/(jpg|jpeg|png|gif|bmp)$/i.exec( file.type ) ?\n                        RegExp.$1.toLowerCase() : '';\n                this.name += '.' + ext;\n            }\n    \n            this.ext = ext;\n            this.lastModifiedDate = file.lastModifiedDate ||\n                    (new Date()).toLocaleString();\n    \n            Blob.apply( this, arguments );\n        }\n    \n        return Base.inherits( Blob, File );\n    });\n    \n    /**\n     * @fileOverview 错误信息\n     */\n    define('lib/filepicker',[\n        'base',\n        'runtime/client',\n        'lib/file'\n    ], function( Base, RuntimeClent, File ) {\n    \n        var $ = Base.$;\n    \n        function FilePicker( opts ) {\n            opts = this.options = $.extend({}, FilePicker.options, opts );\n    \n            opts.container = $( opts.id );\n    \n            if ( !opts.container.length ) {\n                throw new Error('按钮指定错误');\n            }\n    \n            opts.innerHTML = opts.innerHTML || opts.label ||\n                    opts.container.html() || '';\n    \n            opts.button = $( opts.button || document.createElement('div') );\n            opts.button.html( opts.innerHTML );\n            opts.container.html( opts.button );\n    \n            RuntimeClent.call( this, 'FilePicker', true );\n        }\n    \n        FilePicker.options = {\n            button: null,\n            container: null,\n            label: null,\n            innerHTML: null,\n            multiple: true,\n            accept: null,\n            name: 'file'\n        };\n    \n        Base.inherits( RuntimeClent, {\n            constructor: FilePicker,\n    \n            init: function() {\n                var me = this,\n                    opts = me.options,\n                    button = opts.button;\n    \n                button.addClass('webuploader-pick');\n    \n                me.on( 'all', function( type ) {\n                    var files;\n    \n                    switch ( type ) {\n                        case 'mouseenter':\n                            button.addClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'mouseleave':\n                            button.removeClass('webuploader-pick-hover');\n                            break;\n    \n                        case 'change':\n                            files = me.exec('getFiles');\n                            me.trigger( 'select', $.map( files, function( file ) {\n                                file = new File( me.getRuid(), file );\n    \n                                // 记录来源。\n                                file._refer = opts.container;\n                                return file;\n                            }), opts.container );\n                            break;\n                    }\n                });\n    \n                me.connectRuntime( opts, function() {\n                    me.refresh();\n                    me.exec( 'init', opts );\n                    me.trigger('ready');\n                });\n    \n                this._resizeHandler = Base.bindFn( this.refresh, this );\n                $( window ).on( 'resize', this._resizeHandler );\n            },\n    \n            refresh: function() {\n                var shimContainer = this.getRuntime().getContainer(),\n                    button = this.options.button,\n                    width = button.outerWidth ?\n                            button.outerWidth() : button.width(),\n    \n                    height = button.outerHeight ?\n                            button.outerHeight() : button.height(),\n    \n                    pos = button.offset();\n    \n                width && height && shimContainer.css({\n                    bottom: 'auto',\n                    right: 'auto',\n                    width: width + 'px',\n                    height: height + 'px'\n                }).offset( pos );\n            },\n    \n            enable: function() {\n                var btn = this.options.button;\n    \n                btn.removeClass('webuploader-pick-disable');\n                this.refresh();\n            },\n    \n            disable: function() {\n                var btn = this.options.button;\n    \n                this.getRuntime().getContainer().css({\n                    top: '-99999px'\n                });\n    \n                btn.addClass('webuploader-pick-disable');\n            },\n    \n            destroy: function() {\n                var btn = this.options.button;\n                $( window ).off( 'resize', this._resizeHandler );\n                btn.removeClass('webuploader-pick-disable webuploader-pick-hover ' +\n                    'webuploader-pick');\n            }\n        });\n    \n        return FilePicker;\n    });\n    \n    /**\n     * @fileOverview 文件选择相关\n     */\n    define('widgets/filepicker',[\n        'base',\n        'uploader',\n        'lib/filepicker',\n        'widgets/widget'\n    ], function( Base, Uploader, FilePicker ) {\n        var $ = Base.$;\n    \n        $.extend( Uploader.options, {\n    \n            /**\n             * @property {Selector | Object} [pick=undefined]\n             * @namespace options\n             * @for Uploader\n             * @description 指定选择文件的按钮容器，不指定则不创建按钮。\n             *\n             * * `id` {Seletor} 指定选择文件的按钮容器，不指定则不创建按钮。\n             * * `label` {String} 请采用 `innerHTML` 代替\n             * * `innerHTML` {String} 指定按钮文字。不指定时优先从指定的容器中看是否自带文字。\n             * * `multiple` {Boolean} 是否开起同时选择多个文件能力。\n             */\n            pick: null,\n    \n            /**\n             * @property {Arroy} [accept=null]\n             * @namespace options\n             * @for Uploader\n             * @description 指定接受哪些类型的文件。 由于目前还有ext转mimeType表，所以这里需要分开指定。\n             *\n             * * `title` {String} 文字描述\n             * * `extensions` {String} 允许的文件后缀，不带点，多个用逗号分割。\n             * * `mimeTypes` {String} 多个用逗号分割。\n             *\n             * 如：\n             *\n             * ```\n             * {\n             *     title: 'Images',\n             *     extensions: 'gif,jpg,jpeg,bmp,png',\n             *     mimeTypes: 'image/*'\n             * }\n             * ```\n             */\n            accept: null/*{\n                title: 'Images',\n                extensions: 'gif,jpg,jpeg,bmp,png',\n                mimeTypes: 'image/*'\n            }*/\n        });\n    \n        return Uploader.register({\n            name: 'picker',\n    \n            init: function( opts ) {\n                this.pickers = [];\n                return opts.pick && this.addBtn( opts.pick );\n            },\n    \n            refresh: function() {\n                $.each( this.pickers, function() {\n                    this.refresh();\n                });\n            },\n    \n            /**\n             * @method addButton\n             * @for Uploader\n             * @grammar addButton( pick ) => Promise\n             * @description\n             * 添加文件选择按钮，如果一个按钮不够，需要调用此方法来添加。参数跟[options.pick](#WebUploader:Uploader:options)一致。\n             * @example\n             * uploader.addButton({\n             *     id: '#btnContainer',\n             *     innerHTML: '选择文件'\n             * });\n             */\n            addBtn: function( pick ) {\n                var me = this,\n                    opts = me.options,\n                    accept = opts.accept,\n                    promises = [];\n    \n                if ( !pick ) {\n                    return;\n                }\n                \n                $.isPlainObject( pick ) || (pick = {\n                    id: pick\n                });\n    \n                $( pick.id ).each(function() {\n                    var options, picker, deferred;\n    \n                    deferred = Base.Deferred();\n    \n                    options = $.extend({}, pick, {\n                        accept: $.isPlainObject( accept ) ? [ accept ] : accept,\n                        swf: opts.swf,\n                        runtimeOrder: opts.runtimeOrder,\n                        id: this\n                    });\n    \n                    picker = new FilePicker( options );\n    \n                    picker.once( 'ready', deferred.resolve );\n                    picker.on( 'select', function( files ) {\n                        me.owner.request( 'add-file', [ files ]);\n                    });\n                    picker.init();\n    \n                    me.pickers.push( picker );\n    \n                    promises.push( deferred.promise() );\n                });\n    \n                return Base.when.apply( Base, promises );\n            },\n    \n            disable: function() {\n                $.each( this.pickers, function() {\n                    this.disable();\n                });\n            },\n    \n            enable: function() {\n                $.each( this.pickers, function() {\n                    this.enable();\n                });\n            },\n    \n            destroy: function() {\n                $.each( this.pickers, function() {\n                    this.destroy();\n                });\n                this.pickers = null;\n            }\n        });\n    });\n    /**\n     * @fileOverview 文件属性封装\n     */\n    define('file',[\n        'base',\n        'mediator'\n    ], function( Base, Mediator ) {\n    \n        var $ = Base.$,\n            idPrefix = 'WU_FILE_',\n            idSuffix = 0,\n            rExt = /\\.([^.]+)$/,\n            statusMap = {};\n    \n        function gid() {\n            return idPrefix + idSuffix++;\n        }\n    \n        /**\n         * 文件类\n         * @class File\n         * @constructor 构造函数\n         * @grammar new File( source ) => File\n         * @param {Lib.File} source [lib.File](#Lib.File)实例, 此source对象是带有Runtime信息的。\n         */\n        function WUFile( source ) {\n    \n            /**\n             * 文件名，包括扩展名（后缀）\n             * @property name\n             * @type {string}\n             */\n            this.name = source.name || 'Untitled';\n    \n            /**\n             * 文件体积（字节）\n             * @property size\n             * @type {uint}\n             * @default 0\n             */\n            this.size = source.size || 0;\n    \n            /**\n             * 文件MIMETYPE类型，与文件类型的对应关系请参考[http://t.cn/z8ZnFny](http://t.cn/z8ZnFny)\n             * @property type\n             * @type {string}\n             * @default 'application/octet-stream'\n             */\n            this.type = source.type || 'application/octet-stream';\n    \n            /**\n             * 文件最后修改日期\n             * @property lastModifiedDate\n             * @type {int}\n             * @default 当前时间戳\n             */\n            this.lastModifiedDate = source.lastModifiedDate || (new Date() * 1);\n    \n            /**\n             * 文件ID，每个对象具有唯一ID，与文件名无关\n             * @property id\n             * @type {string}\n             */\n            this.id = gid();\n    \n            /**\n             * 文件扩展名，通过文件名获取，例如test.png的扩展名为png\n             * @property ext\n             * @type {string}\n             */\n            this.ext = rExt.exec( this.name ) ? RegExp.$1 : '';\n    \n    \n            /**\n             * 状态文字说明。在不同的status语境下有不同的用途。\n             * @property statusText\n             * @type {string}\n             */\n            this.statusText = '';\n    \n            // 存储文件状态，防止通过属性直接修改\n            statusMap[ this.id ] = WUFile.Status.INITED;\n    \n            this.source = source;\n            this.loaded = 0;\n    \n            this.on( 'error', function( msg ) {\n                this.setStatus( WUFile.Status.ERROR, msg );\n            });\n        }\n    \n        $.extend( WUFile.prototype, {\n    \n            /**\n             * 设置状态，状态变化时会触发`change`事件。\n             * @method setStatus\n             * @grammar setStatus( status[, statusText] );\n             * @param {File.Status|String} status [文件状态值](#WebUploader:File:File.Status)\n             * @param {String} [statusText=''] 状态说明，常在error时使用，用http, abort,server等来标记是由于什么原因导致文件错误。\n             */\n            setStatus: function( status, text ) {\n    \n                var prevStatus = statusMap[ this.id ];\n    \n                typeof text !== 'undefined' && (this.statusText = text);\n    \n                if ( status !== prevStatus ) {\n                    statusMap[ this.id ] = status;\n                    /**\n                     * 文件状态变化\n                     * @event statuschange\n                     */\n                    this.trigger( 'statuschange', status, prevStatus );\n                }\n    \n            },\n    \n            /**\n             * 获取文件状态\n             * @return {File.Status}\n             * @example\n                     文件状态具体包括以下几种类型：\n                     {\n                         // 初始化\n                        INITED:     0,\n                        // 已入队列\n                        QUEUED:     1,\n                        // 正在上传\n                        PROGRESS:     2,\n                        // 上传出错\n                        ERROR:         3,\n                        // 上传成功\n                        COMPLETE:     4,\n                        // 上传取消\n                        CANCELLED:     5\n                    }\n             */\n            getStatus: function() {\n                return statusMap[ this.id ];\n            },\n    \n            /**\n             * 获取文件原始信息。\n             * @return {*}\n             */\n            getSource: function() {\n                return this.source;\n            },\n    \n            destroy: function() {\n                this.off();\n                delete statusMap[ this.id ];\n            }\n        });\n    \n        Mediator.installTo( WUFile.prototype );\n    \n        /**\n         * 文件状态值，具体包括以下几种类型：\n         * * `inited` 初始状态\n         * * `queued` 已经进入队列, 等待上传\n         * * `progress` 上传中\n         * * `complete` 上传完成。\n         * * `error` 上传出错，可重试\n         * * `interrupt` 上传中断，可续传。\n         * * `invalid` 文件不合格，不能重试上传。会自动从队列中移除。\n         * * `cancelled` 文件被移除。\n         * @property {Object} Status\n         * @namespace File\n         * @class File\n         * @static\n         */\n        WUFile.Status = {\n            INITED:     'inited',    // 初始状态\n            QUEUED:     'queued',    // 已经进入队列, 等待上传\n            PROGRESS:   'progress',    // 上传中\n            ERROR:      'error',    // 上传出错，可重试\n            COMPLETE:   'complete',    // 上传完成。\n            CANCELLED:  'cancelled',    // 上传取消。\n            INTERRUPT:  'interrupt',    // 上传中断，可续传。\n            INVALID:    'invalid'    // 文件不合格，不能重试上传。\n        };\n    \n        return WUFile;\n    });\n    \n    /**\n     * @fileOverview 文件队列\n     */\n    define('queue',[\n        'base',\n        'mediator',\n        'file'\n    ], function( Base, Mediator, WUFile ) {\n    \n        var $ = Base.$,\n            STATUS = WUFile.Status;\n    \n        /**\n         * 文件队列, 用来存储各个状态中的文件。\n         * @class Queue\n         * @extends Mediator\n         */\n        function Queue() {\n    \n            /**\n             * 统计文件数。\n             * * `numOfQueue` 队列中的文件数。\n             * * `numOfSuccess` 上传成功的文件数\n             * * `numOfCancel` 被取消的文件数\n             * * `numOfProgress` 正在上传中的文件数\n             * * `numOfUploadFailed` 上传错误的文件数。\n             * * `numOfInvalid` 无效的文件数。\n             * * `numofDeleted` 被移除的文件数。\n             * @property {Object} stats\n             */\n            this.stats = {\n                numOfQueue: 0,\n                numOfSuccess: 0,\n                numOfCancel: 0,\n                numOfProgress: 0,\n                numOfUploadFailed: 0,\n                numOfInvalid: 0,\n                numofDeleted: 0,\n                numofInterrupt: 0,\n            };\n    \n            // 上传队列，仅包括等待上传的文件\n            this._queue = [];\n    \n            // 存储所有文件\n            this._map = {};\n        }\n    \n        $.extend( Queue.prototype, {\n    \n            /**\n             * 将新文件加入对队列尾部\n             *\n             * @method append\n             * @param  {File} file   文件对象\n             */\n            append: function( file ) {\n                this._queue.push( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 将新文件加入对队列头部\n             *\n             * @method prepend\n             * @param  {File} file   文件对象\n             */\n            prepend: function( file ) {\n                this._queue.unshift( file );\n                this._fileAdded( file );\n                return this;\n            },\n    \n            /**\n             * 获取文件对象\n             *\n             * @method getFile\n             * @param  {String} fileId   文件ID\n             * @return {File}\n             */\n            getFile: function( fileId ) {\n                if ( typeof fileId !== 'string' ) {\n                    return fileId;\n                }\n                return this._map[ fileId ];\n            },\n    \n            /**\n             * 从队列中取出一个指定状态的文件。\n             * @grammar fetch( status ) => File\n             * @method fetch\n             * @param {String} status [文件状态值](#WebUploader:File:File.Status)\n             * @return {File} [File](#WebUploader:File)\n             */\n            fetch: function( status ) {\n                var len = this._queue.length,\n                    i, file;\n    \n                status = status || STATUS.QUEUED;\n    \n                for ( i = 0; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( status === file.getStatus() ) {\n                        return file;\n                    }\n                }\n    \n                return null;\n            },\n    \n            /**\n             * 对队列进行排序，能够控制文件上传顺序。\n             * @grammar sort( fn ) => undefined\n             * @method sort\n             * @param {Function} fn 排序方法\n             */\n            sort: function( fn ) {\n                if ( typeof fn === 'function' ) {\n                    this._queue.sort( fn );\n                }\n            },\n    \n            /**\n             * 获取指定类型的文件列表, 列表中每一个成员为[File](#WebUploader:File)对象。\n             * @grammar getFiles( [status1[, status2 ...]] ) => Array\n             * @method getFiles\n             * @param {String} [status] [文件状态值](#WebUploader:File:File.Status)\n             */\n            getFiles: function() {\n                var sts = [].slice.call( arguments, 0 ),\n                    ret = [],\n                    i = 0,\n                    len = this._queue.length,\n                    file;\n    \n                for ( ; i < len; i++ ) {\n                    file = this._queue[ i ];\n    \n                    if ( sts.length && !~$.inArray( file.getStatus(), sts ) ) {\n                        continue;\n                    }\n    \n                    ret.push( file );\n                }\n    \n                return ret;\n            },\n    \n            /**\n             * 在队列中删除文件。\n             * @grammar removeFile( file ) => Array\n             * @method removeFile\n             * @param {File} 文件对象。\n             */\n            removeFile: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( existing ) {\n                    delete this._map[ file.id ];\n                    file.destroy();\n                    this.stats.numofDeleted++;\n                }\n            },\n    \n            _fileAdded: function( file ) {\n                var me = this,\n                    existing = this._map[ file.id ];\n    \n                if ( !existing ) {\n                    this._map[ file.id ] = file;\n    \n                    file.on( 'statuschange', function( cur, pre ) {\n                        me._onFileStatusChange( cur, pre );\n                    });\n                }\n            },\n    \n            _onFileStatusChange: function( curStatus, preStatus ) {\n                var stats = this.stats;\n    \n                switch ( preStatus ) {\n                    case STATUS.PROGRESS:\n                        stats.numOfProgress--;\n                        break;\n    \n                    case STATUS.QUEUED:\n                        stats.numOfQueue --;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed--;\n                        break;\n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid--;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt--;\n                        break;\n                }\n    \n                switch ( curStatus ) {\n                    case STATUS.QUEUED:\n                        stats.numOfQueue++;\n                        break;\n    \n                    case STATUS.PROGRESS:\n                        stats.numOfProgress++;\n                        break;\n    \n                    case STATUS.ERROR:\n                        stats.numOfUploadFailed++;\n                        break;\n    \n                    case STATUS.COMPLETE:\n                        stats.numOfSuccess++;\n                        break;\n    \n                    case STATUS.CANCELLED:\n                        stats.numOfCancel++;\n                        break;\n    \n    \n                    case STATUS.INVALID:\n                        stats.numOfInvalid++;\n                        break;\n    \n                    case STATUS.INTERRUPT:\n                        stats.numofInterrupt++;\n                        break;\n                }\n            }\n    \n        });\n    \n        Mediator.installTo( Queue.prototype );\n    \n        return Queue;\n    });\n    /**\n     * @fileOverview 队列\n     */\n    define('widgets/queue',[\n        'base',\n        'uploader',\n        'queue',\n        'file',\n        'lib/file',\n        'runtime/client',\n        'widgets/widget'\n    ], function( Base, Uploader, Queue, WUFile, File, RuntimeClient ) {\n    \n        var $ = Base.$,\n            rExt = /\\.\\w+$/,\n            Status = WUFile.Status;\n    \n        return Uploader.register({\n            name: 'queue',\n    \n            init: function( opts ) {\n                var me = this,\n                    deferred, len, i, item, arr, accept, runtime;\n    \n                if ( $.isPlainObject( opts.accept ) ) {\n                    opts.accept = [ opts.accept ];\n                }\n    \n                // accept中的中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].extensions;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = '\\\\.' + arr.join(',')\n                                .replace( /,/g, '$|\\\\.' )\n                                .replace( /\\*/g, '.*' ) + '$';\n                    }\n    \n                    me.accept = new RegExp( accept, 'i' );\n                }\n    \n                me.queue = new Queue();\n                me.stats = me.queue.stats;\n    \n                // 如果当前不是html5运行时，那就算了。\n                // 不执行后续操作\n                if ( this.request('predict-runtime-type') !== 'html5' ) {\n                    return;\n                }\n    \n                // 创建一个 html5 运行时的 placeholder\n                // 以至于外部添加原生 File 对象的时候能正确包裹一下供 webuploader 使用。\n                deferred = Base.Deferred();\n                this.placeholder = runtime = new RuntimeClient('Placeholder');\n                runtime.connectRuntime({\n                    runtimeOrder: 'html5'\n                }, function() {\n                    me._ruid = runtime.getRuid();\n                    deferred.resolve();\n                });\n                return deferred.promise();\n            },\n    \n    \n            // 为了支持外部直接添加一个原生File对象。\n            _wrapFile: function( file ) {\n                if ( !(file instanceof WUFile) ) {\n    \n                    if ( !(file instanceof File) ) {\n                        if ( !this._ruid ) {\n                            throw new Error('Can\\'t add external files.');\n                        }\n                        file = new File( this._ruid, file );\n                    }\n    \n                    file = new WUFile( file );\n                }\n    \n                return file;\n            },\n    \n            // 判断文件是否可以被加入队列\n            acceptFile: function( file ) {\n                var invalid = !file || !file.size || this.accept &&\n    \n                        // 如果名字中有后缀，才做后缀白名单处理。\n                        rExt.exec( file.name ) && !this.accept.test( file.name );\n    \n                return !invalid;\n            },\n    \n    \n            /**\n             * @event beforeFileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列之前触发，此事件的handler返回值为`false`，则此文件不会被添加进入队列。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event fileQueued\n             * @param {File} file File对象\n             * @description 当文件被加入队列以后触发。\n             * @for  Uploader\n             */\n    \n            _addFile: function( file ) {\n                var me = this;\n    \n                file = me._wrapFile( file );\n    \n                // 不过类型判断允许不允许，先派送 `beforeFileQueued`\n                if ( !me.owner.trigger( 'beforeFileQueued', file ) ) {\n                    return;\n                }\n    \n                // 类型不匹配，则派送错误事件，并返回。\n                if ( !me.acceptFile( file ) ) {\n                    me.owner.trigger( 'error', 'Q_TYPE_DENIED', file );\n                    return;\n                }\n    \n                me.queue.append( file );\n                me.owner.trigger( 'fileQueued', file );\n                return file;\n            },\n    \n            getFile: function( fileId ) {\n                return this.queue.getFile( fileId );\n            },\n    \n            /**\n             * @event filesQueued\n             * @param {File} files 数组，内容为原始File(lib/File）对象。\n             * @description 当一批文件添加进队列以后触发。\n             * @for  Uploader\n             */\n            \n            /**\n             * @property {Boolean} [auto=false]\n             * @namespace options\n             * @for Uploader\n             * @description 设置为 true 后，不需要手动调用上传，有文件选择即开始上传。\n             * \n             */\n    \n            /**\n             * @method addFiles\n             * @grammar addFiles( file ) => undefined\n             * @grammar addFiles( [file1, file2 ...] ) => undefined\n             * @param {Array of File or File} [files] Files 对象 数组\n             * @description 添加文件到队列\n             * @for  Uploader\n             */\n            addFile: function( files ) {\n                var me = this;\n    \n                if ( !files.length ) {\n                    files = [ files ];\n                }\n    \n                files = $.map( files, function( file ) {\n                    return me._addFile( file );\n                });\n    \n                me.owner.trigger( 'filesQueued', files );\n    \n                if ( me.options.auto ) {\n                    setTimeout(function() {\n                        me.request('start-upload');\n                    }, 20 );\n                }\n            },\n    \n            getStats: function() {\n                return this.stats;\n            },\n    \n            /**\n             * @event fileDequeued\n             * @param {File} file File对象\n             * @description 当文件被移除队列后触发。\n             * @for  Uploader\n             */\n    \n             /**\n             * @method removeFile\n             * @grammar removeFile( file ) => undefined\n             * @grammar removeFile( id ) => undefined\n             * @grammar removeFile( file, true ) => undefined\n             * @grammar removeFile( id, true ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 移除某一文件, 默认只会标记文件状态为已取消，如果第二个参数为 `true` 则会从 queue 中移除。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.removeFile( file );\n             * })\n             */\n            removeFile: function( file, remove ) {\n                var me = this;\n    \n                file = file.id ? file : me.queue.getFile( file );\n    \n                this.request( 'cancel-file', file );\n    \n                if ( remove ) {\n                    this.queue.removeFile( file );\n                }\n            },\n    \n            /**\n             * @method getFiles\n             * @grammar getFiles() => Array\n             * @grammar getFiles( status1, status2, status... ) => Array\n             * @description 返回指定状态的文件集合，不传参数将返回所有状态的文件。\n             * @for  Uploader\n             * @example\n             * console.log( uploader.getFiles() );    // => all files\n             * console.log( uploader.getFiles('error') )    // => all error files.\n             */\n            getFiles: function() {\n                return this.queue.getFiles.apply( this.queue, arguments );\n            },\n    \n            fetchFile: function() {\n                return this.queue.fetch.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @method retry\n             * @grammar retry() => undefined\n             * @grammar retry( file ) => undefined\n             * @description 重试上传，重试指定文件，或者从出错的文件开始重新上传。\n             * @for  Uploader\n             * @example\n             * function retry() {\n             *     uploader.retry();\n             * }\n             */\n            retry: function( file, noForceStart ) {\n                var me = this,\n                    files, i, len;\n    \n                if ( file ) {\n                    file = file.id ? file : me.queue.getFile( file );\n                    file.setStatus( Status.QUEUED );\n                    noForceStart || me.request('start-upload');\n                    return;\n                }\n    \n                files = me.queue.getFiles( Status.ERROR );\n                i = 0;\n                len = files.length;\n    \n                for ( ; i < len; i++ ) {\n                    file = files[ i ];\n                    file.setStatus( Status.QUEUED );\n                }\n    \n                me.request('start-upload');\n            },\n    \n            /**\n             * @method sort\n             * @grammar sort( fn ) => undefined\n             * @description 排序队列中的文件，在上传之前调整可以控制上传顺序。\n             * @for  Uploader\n             */\n            sortFiles: function() {\n                return this.queue.sort.apply( this.queue, arguments );\n            },\n    \n            /**\n             * @event reset\n             * @description 当 uploader 被重置的时候触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @method reset\n             * @grammar reset() => undefined\n             * @description 重置uploader。目前只重置了队列。\n             * @for  Uploader\n             * @example\n             * uploader.reset();\n             */\n            reset: function() {\n                this.owner.trigger('reset');\n                this.queue = new Queue();\n                this.stats = this.queue.stats;\n            },\n    \n            destroy: function() {\n                this.reset();\n                this.placeholder && this.placeholder.destroy();\n            }\n        });\n    \n    });\n    /**\n     * @fileOverview 添加获取Runtime相关信息的方法。\n     */\n    define('widgets/runtime',[\n        'uploader',\n        'runtime/runtime',\n        'widgets/widget'\n    ], function( Uploader, Runtime ) {\n    \n        Uploader.support = function() {\n            return Runtime.hasRuntime.apply( Runtime, arguments );\n        };\n    \n        return Uploader.register({\n            name: 'runtime',\n    \n            init: function() {\n                if ( !this.predictRuntimeType() ) {\n                    throw Error('Runtime Error');\n                }\n            },\n    \n            /**\n             * 预测Uploader将采用哪个`Runtime`\n             * @grammar predictRuntimeType() => String\n             * @method predictRuntimeType\n             * @for  Uploader\n             */\n            predictRuntimeType: function() {\n                var orders = this.options.runtimeOrder || Runtime.orders,\n                    type = this.type,\n                    i, len;\n    \n                if ( !type ) {\n                    orders = orders.split( /\\s*,\\s*/g );\n    \n                    for ( i = 0, len = orders.length; i < len; i++ ) {\n                        if ( Runtime.hasRuntime( orders[ i ] ) ) {\n                            this.type = type = orders[ i ];\n                            break;\n                        }\n                    }\n                }\n    \n                return type;\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     */\n    define('lib/transport',[\n        'base',\n        'runtime/client',\n        'mediator'\n    ], function( Base, RuntimeClient, Mediator ) {\n    \n        var $ = Base.$;\n    \n        function Transport( opts ) {\n            var me = this;\n    \n            opts = me.options = $.extend( true, {}, Transport.options, opts || {} );\n            RuntimeClient.call( this, 'Transport' );\n    \n            this._blob = null;\n            this._formData = opts.formData || {};\n            this._headers = opts.headers || {};\n    \n            this.on( 'progress', this._timeout );\n            this.on( 'load error', function() {\n                me.trigger( 'progress', 1 );\n                clearTimeout( me._timer );\n            });\n        }\n    \n        Transport.options = {\n            server: '',\n            method: 'POST',\n    \n            // 跨域时，是否允许携带cookie, 只有html5 runtime才有效\n            withCredentials: false,\n            fileVal: 'file',\n            timeout: 2 * 60 * 1000,    // 2分钟\n            formData: {},\n            headers: {},\n            sendAsBinary: false\n        };\n    \n        $.extend( Transport.prototype, {\n    \n            // 添加Blob, 只能添加一次，最后一次有效。\n            appendBlob: function( key, blob, filename ) {\n                var me = this,\n                    opts = me.options;\n    \n                if ( me.getRuid() ) {\n                    me.disconnectRuntime();\n                }\n    \n                // 连接到blob归属的同一个runtime.\n                me.connectRuntime( blob.ruid, function() {\n                    me.exec('init');\n                });\n    \n                me._blob = blob;\n                opts.fileVal = key || opts.fileVal;\n                opts.filename = filename || opts.filename;\n            },\n    \n            // 添加其他字段\n            append: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._formData, key );\n                } else {\n                    this._formData[ key ] = value;\n                }\n            },\n    \n            setRequestHeader: function( key, value ) {\n                if ( typeof key === 'object' ) {\n                    $.extend( this._headers, key );\n                } else {\n                    this._headers[ key ] = value;\n                }\n            },\n    \n            send: function( method ) {\n                this.exec( 'send', method );\n                this._timeout();\n            },\n    \n            abort: function() {\n                clearTimeout( this._timer );\n                return this.exec('abort');\n            },\n    \n            destroy: function() {\n                this.trigger('destroy');\n                this.off();\n                this.exec('destroy');\n                this.disconnectRuntime();\n            },\n    \n            getResponse: function() {\n                return this.exec('getResponse');\n            },\n    \n            getResponseAsJson: function() {\n                return this.exec('getResponseAsJson');\n            },\n    \n            getStatus: function() {\n                return this.exec('getStatus');\n            },\n    \n            _timeout: function() {\n                var me = this,\n                    duration = me.options.timeout;\n    \n                if ( !duration ) {\n                    return;\n                }\n    \n                clearTimeout( me._timer );\n                me._timer = setTimeout(function() {\n                    me.abort();\n                    me.trigger( 'error', 'timeout' );\n                }, duration );\n            }\n    \n        });\n    \n        // 让Transport具备事件功能。\n        Mediator.installTo( Transport.prototype );\n    \n        return Transport;\n    });\n    /**\n     * @fileOverview 负责文件上传相关。\n     */\n    define('widgets/upload',[\n        'base',\n        'uploader',\n        'file',\n        'lib/transport',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile, Transport ) {\n    \n        var $ = Base.$,\n            isPromise = Base.isPromise,\n            Status = WUFile.Status;\n    \n        // 添加默认配置项\n        $.extend( Uploader.options, {\n    \n    \n            /**\n             * @property {Boolean} [prepareNextFile=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否允许在文件传输时提前把下一个文件准备好。\n             * 对于一个文件的准备工作比较耗时，比如图片压缩，md5序列化。\n             * 如果能提前在当前文件传输期处理，可以节省总体耗时。\n             */\n            prepareNextFile: false,\n    \n            /**\n             * @property {Boolean} [chunked=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否要分片处理大文件上传。\n             */\n            chunked: false,\n    \n            /**\n             * @property {Boolean} [chunkSize=5242880]\n             * @namespace options\n             * @for Uploader\n             * @description 如果要分片，分多大一片？ 默认大小为5M.\n             */\n            chunkSize: 5 * 1024 * 1024,\n    \n            /**\n             * @property {Boolean} [chunkRetry=2]\n             * @namespace options\n             * @for Uploader\n             * @description 如果某个分片由于网络问题出错，允许自动重传多少次？\n             */\n            chunkRetry: 2,\n    \n            /**\n             * @property {Boolean} [threads=3]\n             * @namespace options\n             * @for Uploader\n             * @description 上传并发数。允许同时最大上传进程数。\n             */\n            threads: 3,\n    \n    \n            /**\n             * @property {Object} [formData={}]\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传请求的参数表，每次发送都会发送此对象中的参数。\n             */\n            formData: {}\n    \n            /**\n             * @property {Object} [fileVal='file']\n             * @namespace options\n             * @for Uploader\n             * @description 设置文件上传域的name。\n             */\n    \n            /**\n             * @property {Object} [method='POST']\n             * @namespace options\n             * @for Uploader\n             * @description 文件上传方式，`POST`或者`GET`。\n             */\n    \n            /**\n             * @property {Object} [sendAsBinary=false]\n             * @namespace options\n             * @for Uploader\n             * @description 是否已二进制的流的方式发送文件，这样整个上传内容`php://input`都为文件内容，\n             * 其他参数在$_GET数组中。\n             */\n        });\n    \n        // 负责将文件切片。\n        function CuteFile( file, chunkSize ) {\n            var pending = [],\n                blob = file.source,\n                total = blob.size,\n                chunks = chunkSize ? Math.ceil( total / chunkSize ) : 1,\n                start = 0,\n                index = 0,\n                len, api;\n    \n            api = {\n                file: file,\n    \n                has: function() {\n                    return !!pending.length;\n                },\n    \n                shift: function() {\n                    return pending.shift();\n                },\n    \n                unshift: function( block ) {\n                    pending.unshift( block );\n                }\n            };\n    \n            while ( index < chunks ) {\n                len = Math.min( chunkSize, total - start );\n    \n                pending.push({\n                    file: file,\n                    start: start,\n                    end: chunkSize ? (start + len) : total,\n                    total: total,\n                    chunks: chunks,\n                    chunk: index++,\n                    cuted: api\n                });\n                start += len;\n            }\n    \n            file.blocks = pending.concat();\n            file.remaning = pending.length;\n    \n            return api;\n        }\n    \n        Uploader.register({\n            name: 'upload',\n    \n            init: function() {\n                var owner = this.owner,\n                    me = this;\n    \n                this.runing = false;\n                this.progress = false;\n    \n                owner\n                    .on( 'startUpload', function() {\n                        me.progress = true;\n                    })\n                    .on( 'uploadFinished', function() {\n                        me.progress = false;\n                    });\n    \n                // 记录当前正在传的数据，跟threads相关\n                this.pool = [];\n    \n                // 缓存分好片的文件。\n                this.stack = [];\n    \n                // 缓存即将上传的文件。\n                this.pending = [];\n    \n                // 跟踪还有多少分片在上传中但是没有完成上传。\n                this.remaning = 0;\n                this.__tick = Base.bindFn( this._tick, this );\n    \n                owner.on( 'uploadComplete', function( file ) {\n                    \n                    // 把其他块取消了。\n                    file.blocks && $.each( file.blocks, function( _, v ) {\n                        v.transport && (v.transport.abort(), v.transport.destroy());\n                        delete v.transport;\n                    });\n    \n                    delete file.blocks;\n                    delete file.remaning;\n                });\n            },\n    \n            reset: function() {\n                this.request( 'stop-upload', true );\n                this.runing = false;\n                this.pool = [];\n                this.stack = [];\n                this.pending = [];\n                this.remaning = 0;\n                this._trigged = false;\n                this._promise = null;\n            },\n    \n            /**\n             * @event startUpload\n             * @description 当开始上传流程时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 开始上传。此方法可以从初始状态调用开始上传流程，也可以从暂停状态调用，继续上传流程。\n             *\n             * 可以指定开始某一个文件。\n             * @grammar upload() => undefined\n             * @grammar upload( file | fileId) => undefined\n             * @method upload\n             * @for  Uploader\n             */\n            startUpload: function(file) {\n                var me = this;\n    \n                // 移出invalid的文件\n                $.each( me.request( 'get-files', Status.INVALID ), function() {\n                    me.request( 'remove-file', this );\n                });\n    \n                // 如果指定了开始某个文件，则只开始指定文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if (file.getStatus() === Status.INTERRUPT) {\n                        $.each( me.pool, function( _, v ) {\n                        \n                            // 之前暂停过。\n                            if (v.file !== file) {\n                                return;\n                            }\n    \n                            v.transport && v.transport.send();\n                        });\n                        \n                        file.setStatus( Status.QUEUED );\n                    } else if (file.getStatus() === Status.PROGRESS) {\n                        return;\n                    } else {\n                        file.setStatus( Status.QUEUED );\n                    }\n                } else {\n                    $.each( me.request( 'get-files', [ Status.INITED ] ), function() {\n                        this.setStatus( Status.QUEUED );\n                    });\n                }\n    \n                if ( me.runing ) {\n                    return;\n                }\n    \n                me.runing = true;\n    \n                // 如果有暂停的，则续传\n                $.each( me.pool, function( _, v ) {\n                    var file = v.file;\n    \n                    if ( file.getStatus() === Status.INTERRUPT ) {\n                        file.setStatus( Status.PROGRESS );\n                        me._trigged = false;\n                        v.transport && v.transport.send();\n                    }\n                });\n    \n                file || $.each( me.request( 'get-files',\n                        Status.INTERRUPT ), function() {\n                    this.setStatus( Status.PROGRESS );\n                });\n    \n                me._trigged = false;\n                Base.nextTick( me.__tick );\n                me.owner.trigger('startUpload');\n            },\n    \n            /**\n             * @event stopUpload\n             * @description 当开始上传流程暂停时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * 暂停上传。第一个参数为是否中断上传当前正在上传的文件。\n             *\n             * 如果第一个参数是文件，则只暂停指定文件。\n             * @grammar stop() => undefined\n             * @grammar stop( true ) => undefined\n             * @grammar stop( file ) => undefined\n             * @method stop\n             * @for  Uploader\n             */\n            stopUpload: function( file, interrupt ) {\n                var me = this;\n    \n                if (file === true) {\n                    interrupt = file;\n                    file = null;\n                }\n    \n                if ( me.runing === false ) {\n                    return;\n                }\n    \n                // 如果只是暂停某个文件。\n                if ( file ) {\n                    file = file.id ? file : me.request( 'get-file', file );\n    \n                    if ( file.getStatus() !== Status.PROGRESS &&\n                            file.getStatus() !== Status.QUEUED ) {\n                        return;\n                    }\n    \n                    file.setStatus( Status.INTERRUPT );\n                    $.each( me.pool, function( _, v ) {\n                        \n                        // 只 abort 指定的文件。\n                        if (v.file !== file) {\n                            return;\n                        }\n    \n                        v.transport && v.transport.abort();\n                        me._putback(v);\n                        me._popBlock(v);\n                    });\n    \n                    return Base.nextTick( me.__tick );\n                }\n    \n                me.runing = false;\n    \n                if (this._promise && this._promise.file) {\n                    this._promise.file.setStatus( Status.INTERRUPT );\n                }\n    \n                interrupt && $.each( me.pool, function( _, v ) {\n                    v.transport && v.transport.abort();\n                    v.file.setStatus( Status.INTERRUPT );\n                });\n    \n                me.owner.trigger('stopUpload');\n            },\n    \n            /**\n             * @method cancelFile\n             * @grammar cancelFile( file ) => undefined\n             * @grammar cancelFile( id ) => undefined\n             * @param {File|id} file File对象或这File对象的id\n             * @description 标记文件状态为已取消, 同时将中断文件传输。\n             * @for  Uploader\n             * @example\n             *\n             * $li.on('click', '.remove-this', function() {\n             *     uploader.cancelFile( file );\n             * })\n             */\n            cancelFile: function( file ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                file.setStatus( Status.CANCELLED );\n                this.owner.trigger( 'fileDequeued', file );\n            },\n    \n            /**\n             * 判断`Uplaode`r是否正在上传中。\n             * @grammar isInProgress() => Boolean\n             * @method isInProgress\n             * @for  Uploader\n             */\n            isInProgress: function() {\n                return !!this.progress;\n            },\n    \n            _getStats: function() {\n                return this.request('get-stats');\n            },\n    \n            /**\n             * 掉过一个文件上传，直接标记指定文件为已上传状态。\n             * @grammar skipFile( file ) => undefined\n             * @method skipFile\n             * @for  Uploader\n             */\n            skipFile: function( file, status ) {\n                file = file.id ? file : this.request( 'get-file', file );\n    \n                file.setStatus( status || Status.COMPLETE );\n                file.skipped = true;\n    \n                // 如果正在上传。\n                file.blocks && $.each( file.blocks, function( _, v ) {\n                    var _tr = v.transport;\n    \n                    if ( _tr ) {\n                        _tr.abort();\n                        _tr.destroy();\n                        delete v.transport;\n                    }\n                });\n    \n                this.owner.trigger( 'uploadSkip', file );\n            },\n    \n            /**\n             * @event uploadFinished\n             * @description 当所有文件上传结束时触发。\n             * @for  Uploader\n             */\n            _tick: function() {\n                var me = this,\n                    opts = me.options,\n                    fn, val;\n    \n                // 上一个promise还没有结束，则等待完成后再执行。\n                if ( me._promise ) {\n                    return me._promise.always( me.__tick );\n                }\n    \n                // 还有位置，且还有文件要处理的话。\n                if ( me.pool.length < opts.threads && (val = me._nextBlock()) ) {\n                    me._trigged = false;\n    \n                    fn = function( val ) {\n                        me._promise = null;\n    \n                        // 有可能是reject过来的，所以要检测val的类型。\n                        val && val.file && me._startSend( val );\n                        Base.nextTick( me.__tick );\n                    };\n    \n                    me._promise = isPromise( val ) ? val.always( fn ) : fn( val );\n    \n                // 没有要上传的了，且没有正在传输的了。\n                } else if ( !me.remaning && !me._getStats().numOfQueue &&\n                    !me._getStats().numofInterrupt ) {\n                    me.runing = false;\n    \n                    me._trigged || Base.nextTick(function() {\n                        me.owner.trigger('uploadFinished');\n                    });\n                    me._trigged = true;\n                }\n            },\n    \n            _putback: function(block) {\n                var idx;\n    \n                block.cuted.unshift(block);\n                idx = this.stack.indexOf(block.cuted);\n    \n                if (!~idx) {\n                    this.stack.unshift(block.cuted);\n                }\n            },\n    \n            _getStack: function() {\n                var i = 0,\n                    act;\n    \n                while ( (act = this.stack[ i++ ]) ) {\n                    if ( act.has() && act.file.getStatus() === Status.PROGRESS ) {\n                        return act;\n                    } else if (!act.has() ||\n                            act.file.getStatus() !== Status.PROGRESS &&\n                            act.file.getStatus() !== Status.INTERRUPT ) {\n    \n                        // 把已经处理完了的，或者，状态为非 progress（上传中）、\n                        // interupt（暂停中） 的移除。\n                        this.stack.splice( --i, 1 );\n                    }\n                }\n    \n                return null;\n            },\n    \n            _nextBlock: function() {\n                var me = this,\n                    opts = me.options,\n                    act, next, done, preparing;\n    \n                // 如果当前文件还有没有需要传输的，则直接返回剩下的。\n                if ( (act = this._getStack()) ) {\n    \n                    // 是否提前准备下一个文件\n                    if ( opts.prepareNextFile && !me.pending.length ) {\n                        me._prepareNextFile();\n                    }\n    \n                    return act.shift();\n    \n                // 否则，如果正在运行，则准备下一个文件，并等待完成后返回下个分片。\n                } else if ( me.runing ) {\n    \n                    // 如果缓存中有，则直接在缓存中取，没有则去queue中取。\n                    if ( !me.pending.length && me._getStats().numOfQueue ) {\n                        me._prepareNextFile();\n                    }\n    \n                    next = me.pending.shift();\n                    done = function( file ) {\n                        if ( !file ) {\n                            return null;\n                        }\n                            \n                        act = CuteFile( file, opts.chunked ? opts.chunkSize : 0 );\n                        me.stack.push(act);\n                        return act.shift();\n                    };\n    \n                    // 文件可能还在prepare中，也有可能已经完全准备好了。\n                    if ( isPromise( next) ) {\n                        preparing = next.file;\n                        next = next[ next.pipe ? 'pipe' : 'then' ]( done );\n                        next.file = preparing;\n                        return next;\n                    }\n    \n                    return done( next );\n                }\n            },\n    \n    \n            /**\n             * @event uploadStart\n             * @param {File} file File对象\n             * @description 某个文件开始上传前触发，一个文件只会触发一次。\n             * @for  Uploader\n             */\n            _prepareNextFile: function() {\n                var me = this,\n                    file = me.request('fetch-file'),\n                    pending = me.pending,\n                    promise;\n    \n                if ( file ) {\n                    promise = me.request( 'before-send-file', file, function() {\n    \n                        // 有可能文件被skip掉了。文件被skip掉后，状态坑定不是Queued.\n                        if ( file.getStatus() === Status.PROGRESS || \n                            file.getStatus() === Status.INTERRUPT ) {\n                            return file;\n                        }\n    \n                        return me._finishFile( file );\n                    });\n    \n                    me.owner.trigger( 'uploadStart', file );\n                    file.setStatus( Status.PROGRESS );\n    \n                    promise.file = file;\n    \n                    // 如果还在pending中，则替换成文件本身。\n                    promise.done(function() {\n                        var idx = $.inArray( promise, pending );\n    \n                        ~idx && pending.splice( idx, 1, file );\n                    });\n    \n                    // befeore-send-file的钩子就有错误发生。\n                    promise.fail(function( reason ) {\n                        file.setStatus( Status.ERROR, reason );\n                        me.owner.trigger( 'uploadError', file, reason );\n                        me.owner.trigger( 'uploadComplete', file );\n                    });\n    \n                    pending.push( promise );\n                }\n            },\n    \n            // 让出位置了，可以让其他分片开始上传\n            _popBlock: function( block ) {\n                var idx = $.inArray( block, this.pool );\n    \n                this.pool.splice( idx, 1 );\n                block.file.remaning--;\n                this.remaning--;\n            },\n    \n            // 开始上传，可以被掉过。如果promise被reject了，则表示跳过此分片。\n            _startSend: function( block ) {\n                var me = this,\n                    file = block.file,\n                    promise;\n    \n                // 有可能在 before-send-file 的 promise 期间改变了文件状态。\n                // 如：暂停，取消\n                // 我们不能中断 promise, 但是可以在 promise 完后，不做上传操作。\n                if ( file.getStatus() !== Status.PROGRESS ) {\n                    \n                    // 如果是中断，则还需要放回去。\n                    if (file.getStatus() === Status.INTERRUPT) {\n                        me._putback(block);\n                    }\n    \n                    return;\n                }\n    \n                me.pool.push( block );\n                me.remaning++;\n    \n                // 如果没有分片，则直接使用原始的。\n                // 不会丢失content-type信息。\n                block.blob = block.chunks === 1 ? file.source :\n                        file.source.slice( block.start, block.end );\n    \n                // hook, 每个分片发送之前可能要做些异步的事情。\n                promise = me.request( 'before-send', block, function() {\n    \n                    // 有可能文件已经上传出错了，所以不需要再传输了。\n                    if ( file.getStatus() === Status.PROGRESS ) {\n                        me._doSend( block );\n                    } else {\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n    \n                // 如果为fail了，则跳过此分片。\n                promise.fail(function() {\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file ).always(function() {\n                            block.percentage = 1;\n                            me._popBlock( block );\n                            me.owner.trigger( 'uploadComplete', file );\n                            Base.nextTick( me.__tick );\n                        });\n                    } else {\n                        block.percentage = 1;\n                        me._popBlock( block );\n                        Base.nextTick( me.__tick );\n                    }\n                });\n            },\n    \n    \n            /**\n             * @event uploadBeforeSend\n             * @param {Object} object\n             * @param {Object} data 默认的上传参数，可以扩展此对象来控制上传参数。\n             * @param {Object} headers 可以扩展此对象来控制上传头部。\n             * @description 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadAccept\n             * @param {Object} object\n             * @param {Object} ret 服务端的返回数据，json格式，如果服务端不是json格式，从ret._raw中取数据，自行解析。\n             * @description 当某个文件上传到服务端响应后，会派送此事件来询问服务端响应是否有效。如果此事件handler返回值为`false`, 则此文件将派送`server`类型的`uploadError`事件。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadProgress\n             * @param {File} file File对象\n             * @param {Number} percentage 上传进度\n             * @description 上传过程中触发，携带上传进度。\n             * @for  Uploader\n             */\n    \n    \n            /**\n             * @event uploadError\n             * @param {File} file File对象\n             * @param {String} reason 出错的code\n             * @description 当文件上传出错时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadSuccess\n             * @param {File} file File对象\n             * @param {Object} response 服务端返回的数据\n             * @description 当文件上传成功时触发。\n             * @for  Uploader\n             */\n    \n            /**\n             * @event uploadComplete\n             * @param {File} [file] File对象\n             * @description 不管成功或者失败，文件上传完成时触发。\n             * @for  Uploader\n             */\n    \n            // 做上传操作。\n            _doSend: function( block ) {\n                var me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    file = block.file,\n                    tr = new Transport( opts ),\n                    data = $.extend({}, opts.formData ),\n                    headers = $.extend({}, opts.headers ),\n                    requestAccept, ret;\n    \n                block.transport = tr;\n    \n                tr.on( 'destroy', function() {\n                    delete block.transport;\n                    me._popBlock( block );\n                    Base.nextTick( me.__tick );\n                });\n    \n                // 广播上传进度。以文件为单位。\n                tr.on( 'progress', function( percentage ) {\n                    var totalPercent = 0,\n                        uploaded = 0;\n    \n                    // 可能没有abort掉，progress还是执行进来了。\n                    // if ( !file.blocks ) {\n                    //     return;\n                    // }\n    \n                    totalPercent = block.percentage = percentage;\n    \n                    if ( block.chunks > 1 ) {    // 计算文件的整体速度。\n                        $.each( file.blocks, function( _, v ) {\n                            uploaded += (v.percentage || 0) * (v.end - v.start);\n                        });\n    \n                        totalPercent = uploaded / file.size;\n                    }\n    \n                    owner.trigger( 'uploadProgress', file, totalPercent || 0 );\n                });\n    \n                // 用来询问，是否返回的结果是有错误的。\n                requestAccept = function( reject ) {\n                    var fn;\n    \n                    ret = tr.getResponseAsJson() || {};\n                    ret._raw = tr.getResponse();\n                    fn = function( value ) {\n                        reject = value;\n                    };\n    \n                    // 服务端响应了，不代表成功了，询问是否响应正确。\n                    if ( !owner.trigger( 'uploadAccept', block, ret, fn ) ) {\n                        reject = reject || 'server';\n                    }\n    \n                    return reject;\n                };\n    \n                // 尝试重试，然后广播文件上传出错。\n                tr.on( 'error', function( type, flag ) {\n                    block.retried = block.retried || 0;\n    \n                    // 自动重试\n                    if ( block.chunks > 1 && ~'http,abort'.indexOf( type ) &&\n                            block.retried < opts.chunkRetry ) {\n    \n                        block.retried++;\n                        tr.send();\n    \n                    } else {\n    \n                        // http status 500 ~ 600\n                        if ( !flag && type === 'server' ) {\n                            type = requestAccept( type );\n                        }\n    \n                        file.setStatus( Status.ERROR, type );\n                        owner.trigger( 'uploadError', file, type );\n                        owner.trigger( 'uploadComplete', file );\n                    }\n                });\n    \n                // 上传成功\n                tr.on( 'load', function() {\n                    var reason;\n    \n                    // 如果非预期，转向上传出错。\n                    if ( (reason = requestAccept()) ) {\n                        tr.trigger( 'error', reason, true );\n                        return;\n                    }\n    \n                    // 全部上传完成。\n                    if ( file.remaning === 1 ) {\n                        me._finishFile( file, ret );\n                    } else {\n                        tr.destroy();\n                    }\n                });\n    \n                // 配置默认的上传字段。\n                data = $.extend( data, {\n                    id: file.id,\n                    name: file.name,\n                    type: file.type,\n                    lastModifiedDate: file.lastModifiedDate,\n                    size: file.size\n                });\n    \n                block.chunks > 1 && $.extend( data, {\n                    chunks: block.chunks,\n                    chunk: block.chunk\n                });\n    \n                // 在发送之间可以添加字段什么的。。。\n                // 如果默认的字段不够使用，可以通过监听此事件来扩展\n                owner.trigger( 'uploadBeforeSend', block, data, headers );\n    \n                // 开始发送。\n                tr.appendBlob( opts.fileVal, block.blob, file.name );\n                tr.append( data );\n                tr.setRequestHeader( headers );\n                tr.send();\n            },\n    \n            // 完成上传。\n            _finishFile: function( file, ret, hds ) {\n                var owner = this.owner;\n    \n                return owner\n                        .request( 'after-send-file', arguments, function() {\n                            file.setStatus( Status.COMPLETE );\n                            owner.trigger( 'uploadSuccess', file, ret, hds );\n                        })\n                        .fail(function( reason ) {\n    \n                            // 如果外部已经标记为invalid什么的，不再改状态。\n                            if ( file.getStatus() === Status.PROGRESS ) {\n                                file.setStatus( Status.ERROR, reason );\n                            }\n    \n                            owner.trigger( 'uploadError', file, reason );\n                        })\n                        .always(function() {\n                            owner.trigger( 'uploadComplete', file );\n                        });\n            }\n    \n        });\n    });\n    /**\n     * @fileOverview 各种验证，包括文件总大小是否超出、单文件是否超出和文件是否重复。\n     */\n    \n    define('widgets/validator',[\n        'base',\n        'uploader',\n        'file',\n        'widgets/widget'\n    ], function( Base, Uploader, WUFile ) {\n    \n        var $ = Base.$,\n            validators = {},\n            api;\n    \n        /**\n         * @event error\n         * @param {String} type 错误类型。\n         * @description 当validate不通过时，会以派送错误事件的形式通知调用者。通过`upload.on('error', handler)`可以捕获到此类错误，目前有以下错误会在特定的情况下派送错来。\n         *\n         * * `Q_EXCEED_NUM_LIMIT` 在设置了`fileNumLimit`且尝试给`uploader`添加的文件数量超出这个值时派送。\n         * * `Q_EXCEED_SIZE_LIMIT` 在设置了`Q_EXCEED_SIZE_LIMIT`且尝试给`uploader`添加的文件总大小超出这个值时派送。\n         * * `Q_TYPE_DENIED` 当文件类型不满足时触发。。\n         * @for  Uploader\n         */\n    \n        // 暴露给外面的api\n        api = {\n    \n            // 添加验证器\n            addValidator: function( type, cb ) {\n                validators[ type ] = cb;\n            },\n    \n            // 移除验证器\n            removeValidator: function( type ) {\n                delete validators[ type ];\n            }\n        };\n    \n        // 在Uploader初始化的时候启动Validators的初始化\n        Uploader.register({\n            name: 'validator',\n    \n            init: function() {\n                var me = this;\n                Base.nextTick(function() {\n                    $.each( validators, function() {\n                        this.call( me.owner );\n                    });\n                });\n            }\n        });\n    \n        /**\n         * @property {int} [fileNumLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总数量, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileNumLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileNumLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( count >= max && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_NUM_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return count >= max ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function() {\n                count++;\n            });\n    \n            uploader.on( 'fileDequeued', function() {\n                count--;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n    \n        /**\n         * @property {int} [fileSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证文件总大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                count = 0,\n                max = parseInt( opts.fileSizeLimit, 10 ),\n                flag = true;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var invalid = count + file.size > max;\n    \n                if ( invalid && flag ) {\n                    flag = false;\n                    this.trigger( 'error', 'Q_EXCEED_SIZE_LIMIT', max, file );\n                    setTimeout(function() {\n                        flag = true;\n                    }, 1 );\n                }\n    \n                return invalid ? false : true;\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                count += file.size;\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                count -= file.size;\n            });\n    \n            uploader.on( 'reset', function() {\n                count = 0;\n            });\n        });\n    \n        /**\n         * @property {int} [fileSingleSizeLimit=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 验证单个文件大小是否超出限制, 超出则不允许加入队列。\n         */\n        api.addValidator( 'fileSingleSizeLimit', function() {\n            var uploader = this,\n                opts = uploader.options,\n                max = opts.fileSingleSizeLimit;\n    \n            if ( !max ) {\n                return;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n    \n                if ( file.size > max ) {\n                    file.setStatus( WUFile.Status.INVALID, 'exceed_size' );\n                    this.trigger( 'error', 'F_EXCEED_SIZE', max, file );\n                    return false;\n                }\n    \n            });\n    \n        });\n    \n        /**\n         * @property {Boolean} [duplicate=undefined]\n         * @namespace options\n         * @for Uploader\n         * @description 去重， 根据文件名字、文件大小和最后修改时间来生成hash Key.\n         */\n        api.addValidator( 'duplicate', function() {\n            var uploader = this,\n                opts = uploader.options,\n                mapping = {};\n    \n            if ( opts.duplicate ) {\n                return;\n            }\n    \n            function hashString( str ) {\n                var hash = 0,\n                    i = 0,\n                    len = str.length,\n                    _char;\n    \n                for ( ; i < len; i++ ) {\n                    _char = str.charCodeAt( i );\n                    hash = _char + (hash << 6) + (hash << 16) - hash;\n                }\n    \n                return hash;\n            }\n    \n            uploader.on( 'beforeFileQueued', function( file ) {\n                var hash = file.__hash || (file.__hash = hashString( file.name +\n                        file.size + file.lastModifiedDate ));\n    \n                // 已经重复了\n                if ( mapping[ hash ] ) {\n                    this.trigger( 'error', 'F_DUPLICATE', file );\n                    return false;\n                }\n            });\n    \n            uploader.on( 'fileQueued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (mapping[ hash ] = true);\n            });\n    \n            uploader.on( 'fileDequeued', function( file ) {\n                var hash = file.__hash;\n    \n                hash && (delete mapping[ hash ]);\n            });\n    \n            uploader.on( 'reset', function() {\n                mapping = {};\n            });\n        });\n    \n        return api;\n    });\n    \n    /**\n     * @fileOverview Runtime管理器，负责Runtime的选择, 连接\n     */\n    define('runtime/compbase',[],function() {\n    \n        function CompBase( owner, runtime ) {\n    \n            this.owner = owner;\n            this.options = owner.options;\n    \n            this.getRuntime = function() {\n                return runtime;\n            };\n    \n            this.getRuid = function() {\n                return runtime.uid;\n            };\n    \n            this.trigger = function() {\n                return owner.trigger.apply( owner, arguments );\n            };\n        }\n    \n        return CompBase;\n    });\n    /**\n     * @fileOverview Html5Runtime\n     */\n    define('runtime/html5/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var type = 'html5',\n            components = {};\n    \n        function Html5Runtime() {\n            var pool = {},\n                me = this,\n                destroy = this.destroy;\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                if ( components[ comp ] ) {\n                    instance = pool[ uid ] = pool[ uid ] ||\n                            new components[ comp ]( client, me );\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n            };\n    \n            me.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: Html5Runtime,\n    \n            // 不需要连接其他程序，直接执行callback\n            init: function() {\n                var me = this;\n                setTimeout(function() {\n                    me.trigger('ready');\n                }, 1 );\n            }\n    \n        });\n    \n        // 注册Components\n        Html5Runtime.register = function( name, component ) {\n            var klass = components[ name ] = Base.inherits( CompBase, component );\n            return klass;\n        };\n    \n        // 注册html5运行时。\n        // 只有在支持的前提下注册。\n        if ( window.Blob && window.FileReader && window.DataView ) {\n            Runtime.addRuntime( type, Html5Runtime );\n        }\n    \n        return Html5Runtime;\n    });\n    /**\n     * @fileOverview Blob Html实现\n     */\n    define('runtime/html5/blob',[\n        'runtime/html5/runtime',\n        'lib/blob'\n    ], function( Html5Runtime, Blob ) {\n    \n        return Html5Runtime.register( 'Blob', {\n            slice: function( start, end ) {\n                var blob = this.owner.source,\n                    slice = blob.slice || blob.webkitSlice || blob.mozSlice;\n    \n                blob = slice.call( blob, start, end );\n    \n                return new Blob( this.getRuid(), blob );\n            }\n        });\n    });\n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/dnd',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        var $ = Base.$,\n            prefix = 'webuploader-dnd-';\n    \n        return Html5Runtime.register( 'DragAndDrop', {\n            init: function() {\n                var elem = this.elem = this.options.container;\n    \n                this.dragEnterHandler = Base.bindFn( this._dragEnterHandler, this );\n                this.dragOverHandler = Base.bindFn( this._dragOverHandler, this );\n                this.dragLeaveHandler = Base.bindFn( this._dragLeaveHandler, this );\n                this.dropHandler = Base.bindFn( this._dropHandler, this );\n                this.dndOver = false;\n    \n                elem.on( 'dragenter', this.dragEnterHandler );\n                elem.on( 'dragover', this.dragOverHandler );\n                elem.on( 'dragleave', this.dragLeaveHandler );\n                elem.on( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).on( 'dragover', this.dragOverHandler );\n                    $( document ).on( 'drop', this.dropHandler );\n                }\n            },\n    \n            _dragEnterHandler: function( e ) {\n                var me = this,\n                    denied = me._denied || false,\n                    items;\n    \n                e = e.originalEvent || e;\n    \n                if ( !me.dndOver ) {\n                    me.dndOver = true;\n    \n                    // 注意只有 chrome 支持。\n                    items = e.dataTransfer.items;\n    \n                    if ( items && items.length ) {\n                        me._denied = denied = !me.trigger( 'accept', items );\n                    }\n    \n                    me.elem.addClass( prefix + 'over' );\n                    me.elem[ denied ? 'addClass' :\n                            'removeClass' ]( prefix + 'denied' );\n                }\n    \n                e.dataTransfer.dropEffect = denied ? 'none' : 'copy';\n    \n                return false;\n            },\n    \n            _dragOverHandler: function( e ) {\n                // 只处理框内的。\n                var parentElem = this.elem.parent().get( 0 );\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                clearTimeout( this._leaveTimer );\n                this._dragEnterHandler.call( this, e );\n    \n                return false;\n            },\n    \n            _dragLeaveHandler: function() {\n                var me = this,\n                    handler;\n    \n                handler = function() {\n                    me.dndOver = false;\n                    me.elem.removeClass( prefix + 'over ' + prefix + 'denied' );\n                };\n    \n                clearTimeout( me._leaveTimer );\n                me._leaveTimer = setTimeout( handler, 100 );\n                return false;\n            },\n    \n            _dropHandler: function( e ) {\n                var me = this,\n                    ruid = me.getRuid(),\n                    parentElem = me.elem.parent().get( 0 ),\n                    dataTransfer, data;\n    \n                // 只处理框内的。\n                if ( parentElem && !$.contains( parentElem, e.currentTarget ) ) {\n                    return false;\n                }\n    \n                e = e.originalEvent || e;\n                dataTransfer = e.dataTransfer;\n    \n                // 如果是页面内拖拽，还不能处理，不阻止事件。\n                // 此处 ie11 下会报参数错误，\n                try {\n                    data = dataTransfer.getData('text/html');\n                } catch( err ) {\n                }\n    \n                if ( data ) {\n                    return;\n                }\n    \n                me._getTansferFiles( dataTransfer, function( results ) {\n                    me.trigger( 'drop', $.map( results, function( file ) {\n                        return new File( ruid, file );\n                    }) );\n                });\n    \n                me.dndOver = false;\n                me.elem.removeClass( prefix + 'over' );\n                return false;\n            },\n    \n            // 如果传入 callback 则去查看文件夹，否则只管当前文件夹。\n            _getTansferFiles: function( dataTransfer, callback ) {\n                var results  = [],\n                    promises = [],\n                    items, files, file, item, i, len, canAccessFolder;\n    \n                items = dataTransfer.items;\n                files = dataTransfer.files;\n    \n                canAccessFolder = !!(items && items[ 0 ].webkitGetAsEntry);\n    \n                for ( i = 0, len = files.length; i < len; i++ ) {\n                    file = files[ i ];\n                    item = items && items[ i ];\n    \n                    if ( canAccessFolder && item.webkitGetAsEntry().isDirectory ) {\n    \n                        promises.push( this._traverseDirectoryTree(\n                                item.webkitGetAsEntry(), results ) );\n                    } else {\n                        results.push( file );\n                    }\n                }\n    \n                Base.when.apply( Base, promises ).done(function() {\n    \n                    if ( !results.length ) {\n                        return;\n                    }\n    \n                    callback( results );\n                });\n            },\n    \n            _traverseDirectoryTree: function( entry, results ) {\n                var deferred = Base.Deferred(),\n                    me = this;\n    \n                if ( entry.isFile ) {\n                    entry.file(function( file ) {\n                        results.push( file );\n                        deferred.resolve();\n                    });\n                } else if ( entry.isDirectory ) {\n                    entry.createReader().readEntries(function( entries ) {\n                        var len = entries.length,\n                            promises = [],\n                            arr = [],    // 为了保证顺序。\n                            i;\n    \n                        for ( i = 0; i < len; i++ ) {\n                            promises.push( me._traverseDirectoryTree(\n                                    entries[ i ], arr ) );\n                        }\n    \n                        Base.when.apply( Base, promises ).then(function() {\n                            results.push.apply( results, arr );\n                            deferred.resolve();\n                        }, deferred.reject );\n                    });\n                }\n    \n                return deferred.promise();\n            },\n    \n            destroy: function() {\n                var elem = this.elem;\n    \n                // 还没 init 就调用 destroy\n                if (!elem) {\n                    return;\n                }\n                \n                elem.off( 'dragenter', this.dragEnterHandler );\n                elem.off( 'dragover', this.dragOverHandler );\n                elem.off( 'dragleave', this.dragLeaveHandler );\n                elem.off( 'drop', this.dropHandler );\n    \n                if ( this.options.disableGlobalDnd ) {\n                    $( document ).off( 'dragover', this.dragOverHandler );\n                    $( document ).off( 'drop', this.dropHandler );\n                }\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePaste\n     */\n    define('runtime/html5/filepaste',[\n        'base',\n        'runtime/html5/runtime',\n        'lib/file'\n    ], function( Base, Html5Runtime, File ) {\n    \n        return Html5Runtime.register( 'FilePaste', {\n            init: function() {\n                var opts = this.options,\n                    elem = this.elem = opts.container,\n                    accept = '.*',\n                    arr, i, len, item;\n    \n                // accetp的mimeTypes中生成匹配正则。\n                if ( opts.accept ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        item = opts.accept[ i ].mimeTypes;\n                        item && arr.push( item );\n                    }\n    \n                    if ( arr.length ) {\n                        accept = arr.join(',');\n                        accept = accept.replace( /,/g, '|' ).replace( /\\*/g, '.*' );\n                    }\n                }\n                this.accept = accept = new RegExp( accept, 'i' );\n                this.hander = Base.bindFn( this._pasteHander, this );\n                elem.on( 'paste', this.hander );\n            },\n    \n            _pasteHander: function( e ) {\n                var allowed = [],\n                    ruid = this.getRuid(),\n                    items, item, blob, i, len;\n    \n                e = e.originalEvent || e;\n                items = e.clipboardData.items;\n    \n                for ( i = 0, len = items.length; i < len; i++ ) {\n                    item = items[ i ];\n    \n                    if ( item.kind !== 'file' || !(blob = item.getAsFile()) ) {\n                        continue;\n                    }\n    \n                    allowed.push( new File( ruid, blob ) );\n                }\n    \n                if ( allowed.length ) {\n                    // 不阻止非文件粘贴（文字粘贴）的事件冒泡\n                    e.preventDefault();\n                    e.stopPropagation();\n                    this.trigger( 'paste', allowed );\n                }\n            },\n    \n            destroy: function() {\n                this.elem.off( 'paste', this.hander );\n            }\n        });\n    });\n    \n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/html5/filepicker',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var $ = Base.$;\n    \n        return Html5Runtime.register( 'FilePicker', {\n            init: function() {\n                var container = this.getRuntime().getContainer(),\n                    me = this,\n                    owner = me.owner,\n                    opts = me.options,\n                    label = this.label = $( document.createElement('label') ),\n                    input =  this.input = $( document.createElement('input') ),\n                    arr, i, len, mouseHandler;\n    \n                input.attr( 'type', 'file' );\n                input.attr( 'name', opts.name );\n                input.addClass('webuploader-element-invisible');\n    \n                label.on( 'click', function() {\n                    input.trigger('click');\n                });\n    \n                label.css({\n                    opacity: 0,\n                    width: '100%',\n                    height: '100%',\n                    display: 'block',\n                    cursor: 'pointer',\n                    background: '#ffffff'\n                });\n    \n                if ( opts.multiple ) {\n                    input.attr( 'multiple', 'multiple' );\n                }\n    \n                // @todo Firefox不支持单独指定后缀\n                if ( opts.accept && opts.accept.length > 0 ) {\n                    arr = [];\n    \n                    for ( i = 0, len = opts.accept.length; i < len; i++ ) {\n                        arr.push( opts.accept[ i ].mimeTypes );\n                    }\n    \n                    input.attr( 'accept', arr.join(',') );\n                }\n    \n                container.append( input );\n                container.append( label );\n    \n                mouseHandler = function( e ) {\n                    owner.trigger( e.type );\n                };\n    \n                input.on( 'change', function( e ) {\n                    var fn = arguments.callee,\n                        clone;\n    \n                    me.files = e.target.files;\n    \n                    // reset input\n                    clone = this.cloneNode( true );\n                    clone.value = null;\n                    this.parentNode.replaceChild( clone, this );\n    \n                    input.off();\n                    input = $( clone ).on( 'change', fn )\n                            .on( 'mouseenter mouseleave', mouseHandler );\n    \n                    owner.trigger('change');\n                });\n    \n                label.on( 'mouseenter mouseleave', mouseHandler );\n    \n            },\n    \n    \n            getFiles: function() {\n                return this.files;\n            },\n    \n            destroy: function() {\n                this.input.off();\n                this.label.off();\n            }\n        });\n    });\n    /**\n     * @fileOverview Transport\n     * @todo 支持chunked传输，优势：\n     * 可以将大文件分成小块，挨个传输，可以提高大文件成功率，当失败的时候，也只需要重传那小部分，\n     * 而不需要重头再传一次。另外断点续传也需要用chunked方式。\n     */\n    define('runtime/html5/transport',[\n        'base',\n        'runtime/html5/runtime'\n    ], function( Base, Html5Runtime ) {\n    \n        var noop = Base.noop,\n            $ = Base.$;\n    \n        return Html5Runtime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    formData, binary, fr;\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.getSource();\n                } else {\n                    formData = new FormData();\n                    $.each( owner._formData, function( k, v ) {\n                        formData.append( k, v );\n                    });\n    \n                    formData.append( opts.fileVal, blob.getSource(),\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                if ( opts.withCredentials && 'withCredentials' in xhr ) {\n                    xhr.open( opts.method, server, true );\n                    xhr.withCredentials = true;\n                } else {\n                    xhr.open( opts.method, server );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n    \n                if ( binary ) {\n                    // 强制设置成 content-type 为文件流。\n                    xhr.overrideMimeType &&\n                            xhr.overrideMimeType('application/octet-stream');\n    \n                    // android直接发送blob会导致服务端接收到的是空文件。\n                    // bug详情。\n                    // https://code.google.com/p/android/issues/detail?id=39882\n                    // 所以先用fileReader读取出来再通过arraybuffer的方式发送。\n                    if ( Base.os.android ) {\n                        fr = new FileReader();\n    \n                        fr.onload = function() {\n                            xhr.send( this.result );\n                            fr = fr.onload = null;\n                        };\n    \n                        fr.readAsArrayBuffer( binary );\n                    } else {\n                        xhr.send( binary );\n                    }\n                } else {\n                    xhr.send( formData );\n                }\n            },\n    \n            getResponse: function() {\n                return this._response;\n            },\n    \n            getResponseAsJson: function() {\n                return this._parseJson( this._response );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    xhr.abort();\n    \n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new XMLHttpRequest(),\n                    opts = this.options;\n    \n                if ( opts.withCredentials && !('withCredentials' in xhr) &&\n                        typeof XDomainRequest !== 'undefined' ) {\n                    xhr = new XDomainRequest();\n                }\n    \n                xhr.upload.onprogress = function( e ) {\n                    var percentage = 0;\n    \n                    if ( e.lengthComputable ) {\n                        percentage = e.loaded / e.total;\n                    }\n    \n                    return me.trigger( 'progress', percentage );\n                };\n    \n                xhr.onreadystatechange = function() {\n    \n                    if ( xhr.readyState !== 4 ) {\n                        return;\n                    }\n    \n                    xhr.upload.onprogress = noop;\n                    xhr.onreadystatechange = noop;\n                    me._xhr = null;\n                    me._status = xhr.status;\n    \n                    if ( xhr.status >= 200 && xhr.status < 300 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger('load');\n                    } else if ( xhr.status >= 500 && xhr.status < 600 ) {\n                        me._response = xhr.responseText;\n                        return me.trigger( 'error', 'server' );\n                    }\n    \n    \n                    return me.trigger( 'error', me._status ? 'http' : 'abort' );\n                };\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.setRequestHeader( key, val );\n                });\n            },\n    \n            _parseJson: function( str ) {\n                var json;\n    \n                try {\n                    json = JSON.parse( str );\n                } catch ( ex ) {\n                    json = {};\n                }\n    \n                return json;\n            }\n        });\n    });\n    /**\n     * @fileOverview FlashRuntime\n     */\n    define('runtime/flash/runtime',[\n        'base',\n        'runtime/runtime',\n        'runtime/compbase'\n    ], function( Base, Runtime, CompBase ) {\n    \n        var $ = Base.$,\n            type = 'flash',\n            components = {};\n    \n    \n        function getFlashVersion() {\n            var version;\n    \n            try {\n                version = navigator.plugins[ 'Shockwave Flash' ];\n                version = version.description;\n            } catch ( ex ) {\n                try {\n                    version = new ActiveXObject('ShockwaveFlash.ShockwaveFlash')\n                            .GetVariable('$version');\n                } catch ( ex2 ) {\n                    version = '0.0';\n                }\n            }\n            version = version.match( /\\d+/g );\n            return parseFloat( version[ 0 ] + '.' + version[ 1 ], 10 );\n        }\n    \n        function FlashRuntime() {\n            var pool = {},\n                clients = {},\n                destroy = this.destroy,\n                me = this,\n                jsreciver = Base.guid('webuploader_');\n    \n            Runtime.apply( me, arguments );\n            me.type = type;\n    \n    \n            // 这个方法的调用者，实际上是RuntimeClient\n            me.exec = function( comp, fn/*, args...*/ ) {\n                var client = this,\n                    uid = client.uid,\n                    args = Base.slice( arguments, 2 ),\n                    instance;\n    \n                clients[ uid ] = client;\n    \n                if ( components[ comp ] ) {\n                    if ( !pool[ uid ] ) {\n                        pool[ uid ] = new components[ comp ]( client, me );\n                    }\n    \n                    instance = pool[ uid ];\n    \n                    if ( instance[ fn ] ) {\n                        return instance[ fn ].apply( instance, args );\n                    }\n                }\n    \n                return me.flashExec.apply( client, arguments );\n            };\n    \n            function handler( evt, obj ) {\n                var type = evt.type || evt,\n                    parts, uid;\n    \n                parts = type.split('::');\n                uid = parts[ 0 ];\n                type = parts[ 1 ];\n    \n                // console.log.apply( console, arguments );\n    \n                if ( type === 'Ready' && uid === me.uid ) {\n                    me.trigger('ready');\n                } else if ( clients[ uid ] ) {\n                    clients[ uid ].trigger( type.toLowerCase(), evt, obj );\n                }\n    \n                // Base.log( evt, obj );\n            }\n    \n            // flash的接受器。\n            window[ jsreciver ] = function() {\n                var args = arguments;\n    \n                // 为了能捕获得到。\n                setTimeout(function() {\n                    handler.apply( null, args );\n                }, 1 );\n            };\n    \n            this.jsreciver = jsreciver;\n    \n            this.destroy = function() {\n                // @todo 删除池子中的所有实例\n                return destroy && destroy.apply( this, arguments );\n            };\n    \n            this.flashExec = function( comp, fn ) {\n                var flash = me.getFlash(),\n                    args = Base.slice( arguments, 2 );\n    \n                return flash.exec( this.uid, comp, fn, args );\n            };\n    \n            // @todo\n        }\n    \n        Base.inherits( Runtime, {\n            constructor: FlashRuntime,\n    \n            init: function() {\n                var container = this.getContainer(),\n                    opts = this.options,\n                    html;\n    \n                // if not the minimal height, shims are not initialized\n                // in older browsers (e.g FF3.6, IE6,7,8, Safari 4.0,5.0, etc)\n                container.css({\n                    position: 'absolute',\n                    top: '-8px',\n                    left: '-8px',\n                    width: '9px',\n                    height: '9px',\n                    overflow: 'hidden'\n                });\n    \n                // insert flash object\n                html = '<object id=\"' + this.uid + '\" type=\"application/' +\n                        'x-shockwave-flash\" data=\"' +  opts.swf + '\" ';\n    \n                if ( Base.browser.ie ) {\n                    html += 'classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" ';\n                }\n    \n                html += 'width=\"100%\" height=\"100%\" style=\"outline:0\">'  +\n                    '<param name=\"movie\" value=\"' + opts.swf + '\" />' +\n                    '<param name=\"flashvars\" value=\"uid=' + this.uid +\n                    '&jsreciver=' + this.jsreciver + '\" />' +\n                    '<param name=\"wmode\" value=\"transparent\" />' +\n                    '<param name=\"allowscriptaccess\" value=\"always\" />' +\n                '</object>';\n    \n                container.html( html );\n            },\n    \n            getFlash: function() {\n                if ( this._flash ) {\n                    return this._flash;\n                }\n    \n                this._flash = $( '#' + this.uid ).get( 0 );\n                return this._flash;\n            }\n    \n        });\n    \n        FlashRuntime.register = function( name, component ) {\n            component = components[ name ] = Base.inherits( CompBase, $.extend({\n    \n                // @todo fix this later\n                flashExec: function() {\n                    var owner = this.owner,\n                        runtime = this.getRuntime();\n    \n                    return runtime.flashExec.apply( owner, arguments );\n                }\n            }, component ) );\n    \n            return component;\n        };\n    \n        if ( getFlashVersion() >= 11.4 ) {\n            Runtime.addRuntime( type, FlashRuntime );\n        }\n    \n        return FlashRuntime;\n    });\n    /**\n     * @fileOverview FilePicker\n     */\n    define('runtime/flash/filepicker',[\n        'base',\n        'runtime/flash/runtime'\n    ], function( Base, FlashRuntime ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'FilePicker', {\n            init: function( opts ) {\n                var copy = $.extend({}, opts ),\n                    len, i;\n    \n                // 修复Flash再没有设置title的情况下无法弹出flash文件选择框的bug.\n                len = copy.accept && copy.accept.length;\n                for (  i = 0; i < len; i++ ) {\n                    if ( !copy.accept[ i ].title ) {\n                        copy.accept[ i ].title = 'Files';\n                    }\n                }\n    \n                delete copy.button;\n                delete copy.id;\n                delete copy.container;\n    \n                this.flashExec( 'FilePicker', 'init', copy );\n            },\n    \n            destroy: function() {\n                this.flashExec( 'FilePicker', 'destroy' );\n            }\n        });\n    });\n    /**\n     * @fileOverview  Transport flash实现\n     */\n    define('runtime/flash/transport',[\n        'base',\n        'runtime/flash/runtime',\n        'runtime/client'\n    ], function( Base, FlashRuntime, RuntimeClient ) {\n        var $ = Base.$;\n    \n        return FlashRuntime.register( 'Transport', {\n            init: function() {\n                this._status = 0;\n                this._response = null;\n                this._responseJson = null;\n            },\n    \n            send: function() {\n                var owner = this.owner,\n                    opts = this.options,\n                    xhr = this._initAjax(),\n                    blob = owner._blob,\n                    server = opts.server,\n                    binary;\n    \n                xhr.connectRuntime( blob.ruid );\n    \n                if ( opts.sendAsBinary ) {\n                    server += (/\\?/.test( server ) ? '&' : '?') +\n                            $.param( owner._formData );\n    \n                    binary = blob.uid;\n                } else {\n                    $.each( owner._formData, function( k, v ) {\n                        xhr.exec( 'append', k, v );\n                    });\n    \n                    xhr.exec( 'appendBlob', opts.fileVal, blob.uid,\n                            opts.filename || owner._formData.name || '' );\n                }\n    \n                this._setRequestHeader( xhr, opts.headers );\n                xhr.exec( 'send', {\n                    method: opts.method,\n                    url: server,\n                    forceURLStream: opts.forceURLStream,\n                    mimeType: 'application/octet-stream'\n                }, binary );\n            },\n    \n            getStatus: function() {\n                return this._status;\n            },\n    \n            getResponse: function() {\n                return this._response || '';\n            },\n    \n            getResponseAsJson: function() {\n                return this._responseJson;\n            },\n    \n            abort: function() {\n                var xhr = this._xhr;\n    \n                if ( xhr ) {\n                    xhr.exec('abort');\n                    xhr.destroy();\n                    this._xhr = xhr = null;\n                }\n            },\n    \n            destroy: function() {\n                this.abort();\n            },\n    \n            _initAjax: function() {\n                var me = this,\n                    xhr = new RuntimeClient('XMLHttpRequest');\n    \n                xhr.on( 'uploadprogress progress', function( e ) {\n                    var percent = e.loaded / e.total;\n                    percent = Math.min( 1, Math.max( 0, percent ) );\n                    return me.trigger( 'progress', percent );\n                });\n    \n                xhr.on( 'load', function() {\n                    var status = xhr.exec('getStatus'),\n                        readBody = false,\n                        err = '',\n                        p;\n    \n                    xhr.off();\n                    me._xhr = null;\n    \n                    if ( status >= 200 && status < 300 ) {\n                        readBody = true;\n                    } else if ( status >= 500 && status < 600 ) {\n                        readBody = true;\n                        err = 'server';\n                    } else {\n                        err = 'http';\n                    }\n    \n                    if ( readBody ) {\n                        me._response = xhr.exec('getResponse');\n                        me._response = decodeURIComponent( me._response );\n    \n                        // flash 处理可能存在 bug, 没辙只能靠 js 了\n                        // try {\n                        //     me._responseJson = xhr.exec('getResponseAsJson');\n                        // } catch ( error ) {\n                            \n                        p = window.JSON && window.JSON.parse || function( s ) {\n                            try {\n                                return new Function('return ' + s).call();\n                            } catch ( err ) {\n                                return {};\n                            }\n                        };\n                        me._responseJson  = me._response ? p(me._response) : {};\n                            \n                        // }\n                    }\n                    \n                    xhr.destroy();\n                    xhr = null;\n    \n                    return err ? me.trigger( 'error', err ) : me.trigger('load');\n                });\n    \n                xhr.on( 'error', function() {\n                    xhr.off();\n                    me._xhr = null;\n                    me.trigger( 'error', 'http' );\n                });\n    \n                me._xhr = xhr;\n                return xhr;\n            },\n    \n            _setRequestHeader: function( xhr, headers ) {\n                $.each( headers, function( key, val ) {\n                    xhr.exec( 'setRequestHeader', key, val );\n                });\n            }\n        });\n    });\n    /**\n     * @fileOverview 没有图像处理的版本。\n     */\n    define('preset/withoutimage',[\n        'base',\n    \n        // widgets\n        'widgets/filednd',\n        'widgets/filepaste',\n        'widgets/filepicker',\n        'widgets/queue',\n        'widgets/runtime',\n        'widgets/upload',\n        'widgets/validator',\n    \n        // runtimes\n        // html5\n        'runtime/html5/blob',\n        'runtime/html5/dnd',\n        'runtime/html5/filepaste',\n        'runtime/html5/filepicker',\n        'runtime/html5/transport',\n    \n        // flash\n        'runtime/flash/filepicker',\n        'runtime/flash/transport'\n    ], function( Base ) {\n        return Base;\n    });\n    define('webuploader',[\n        'preset/withoutimage'\n    ], function( preset ) {\n        return preset;\n    });\n    return require('webuploader');\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/API_cn.html",
    "content": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t\t<title>API 文档 [zTree --  jQuery 树插件]</title>\n\t\t<link rel=\"stylesheet\" href=\"apiCss/common.css\" type=\"text/css\">\n\t\t<link rel='stylesheet' href='apiCss/zTreeStyleForApi.css' type='text/css'>\n\t\t<script type=\"text/javascript\">\n\t\t\tvar ie = (function(){\n\t\t\t\tvar undef,\n\t\t\t\tv = 3,\n\t\t\t\tdiv = document.createElement('div'),\n\t\t\t\tall = div.getElementsByTagName('i');\n\t\t\t\twhile (\n\t\t\t\tdiv.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',\n\t\t\t\tall[0]\n\t\t\t);\n\t\t\t\treturn v > 4 ? v : undef;\n\t\t\t}()), ie6 = (ie === 6),\n\t\t\tpath = window.location.pathname.replace(/.*\\/([^\\/\\.]*)\\..*/g,\"$1\"),\n\t\t\tlangLib = [];\n\t\t\tie = ie<9;\n\t\t\tif(ie) {\n\t\t\t\tdocument.write('<link rel=\"stylesheet\" href=\"apiCss/common_ie6.css\" type=\"text/css\">');\n\t\t\t}\n\t\t\tvar lang = \"cn\",\n\t\t\tajaxMsg = \"如果你使用的是 Chrome 浏览器，那么请把 API 文档发布到 web 服务目录下访问。\\n\\n（Chrome 浏览器不支持本地 ajax 访问, 即：file://）\";\n\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"header_wrap\" class=\"header_wrap\" style=\"padding-top: 30px;\">\n\t\t\t<div id=\"header\" class=\"header round\">\n\t\t\t\t<div class=\"light-bulb\" alt=\"\"></div>\n\t\t\t\t<div class=\"ieSuggest\">浏览本网站建议您使用 Chrome、FireFox、Opera、IE9 等浏览器（只要不是 IE6 7 8 就行）, 速度会更快，画面会更炫！</div>\n\t\t\t\t<div class=\"google_plus\"><g:plusone></g:plusone></div>\n\t\t\t\t<div class=\"header-text\">\n\t\t\t\t\t<h1><em>zTree v3.5.17 API 文档</em></h1><p></p>\n\t\t\t\t\t<p>all.js = core + excheck + exedit ( 不包括 exhide ); 发现错误请及时通知，谢谢。</p>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"shortcuts language\" style=\"top:0;\">\n\t\t\t\t\t<li><a href=\"API_en.html\" onclick=\"window.location.href='API_en.html'\"><button class=\"ico en\" title=\"英文版\" type=\"button\"></button><span class=\"\"></span></a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<div id=\"content_wrap\" class=\"content_wrap\">\n\t\t\t<div id=\"content\" class=\"content\">\n\t\t\t\t<div class=\"nav_section\">\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t<li class=\"first\">注释：</li>\n\t\t\t\t\t\t<li><button class=\"ico16 z_core\" onfocus=\"this.blur();\"></button><span>core 核心包</span></li>\n\t\t\t\t\t\t<li><button class=\"ico16 z_check\" onfocus=\"this.blur();\"></button><span>excheck 扩展</span></li>\n\t\t\t\t\t\t<li><button class=\"ico16 z_edit\" onfocus=\"this.blur();\"></button><span>exedit 扩展</span></li>\n\t\t\t\t\t\t<li><button class=\"ico16 z_hide\" onfocus=\"this.blur();\"></button><span>exhide 扩展</span></li>\n\t\t\t\t\t\t<li class=\"noline\">\n\t\t\t\t\t\t\t<button class=\"ico16 z_search\" onfocus=\"this.blur();\" title=\"Enter 以及 左、右键可以快速定位查找结果\"></button>\n\t\t\t\t\t\t\t<input type=\"text\" class=\"searchKey search empty\" value=\"\"><input type=\"text\" class=\"searchResult search\" value=\"\">\n\t\t\t\t\t\t\t<button class=\"ico16 searchPrev disabled\" onfocus=\"this.blur();\" title=\"Enter 以及 左、右键可以快速定位查找结果\"></button><button class=\"ico16 searchNext disabled\" onfocus=\"this.blur();\" title=\"Enter 以及 左、右键可以快速定位查找结果\"></button>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\n\t\t\t\t<div id=\"contentBox\" class=\"contentBox round clearfix\">\n\t\t\t\t\t<div id=\"apiContent\" class=\"apiContent\">\n\t\t\t\t\t\t<div id=\"api_setting\" class=\"api_setting left\">\n\t\t\t\t\t\t\t<ul class=\"api_content_title\"><li>setting 配置详解</li></ul>\n\t\t\t\t\t\t\t<ul id=\"settingTree\" class=\"ztree\"></ul>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"api_function\" class=\"api_function right\">\n\t\t\t\t\t\t\t<ul class=\"api_content_title\"><li>zTree 方法详解</li></ul>\n\t\t\t\t\t\t\t<ul id=\"functionTree\" class=\"ztree\"></ul>\n\t\t\t\t\t\t\t<ul class=\"api_content_title\"><li>treeNode 节点数据详解</li></ul>\n\t\t\t\t\t\t\t<ul id=\"treenodeTree\" class=\"ztree\"></ul>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"clear\"></div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- overlayed -->\n\t\t<div id=\"overlayDiv\" class=\"baby_overlay\">\n\t\t\t<div id=\"overlayContent\" class=\"content round clearfix\">\n\t\t\t\t<div class=\"overlaySearch\">\n\t\t\t\t\t<button class=\"ico16 z_search\" onfocus=\"this.blur();\" title=\"Enter 以及 左、右键可以快速定位查找结果\"></button>\n\t\t\t\t\t<input type=\"text\" class=\"searchKey search empty\" value=\"\"><input type=\"text\" class=\"searchResult search\" value=\"\">\n\t\t\t\t\t<button class=\"ico16 searchPrev disabled\" onfocus=\"this.blur();\" title=\"Enter 以及 左、右键可以快速定位查找结果\"></button><button class=\"ico16 searchNext disabled\" onfocus=\"this.blur();\" title=\"Enter 以及 左、右键可以快速定位查找结果\"></button>\n\t\t\t\t</div>\n\t\t\t\t<a id=\"overlayDivCloseBtn\" class=\"close\"></a>\n\t\t\t\t<div id=\"overlayDetailDiv\" class=\"details\"></div>\n\t\t\t</div>\n\t\t\t<div id=\"overlayDivArrow\" class=\"baby_overlay_arrow\"></div>\n\t\t</div>\n\t\t<script type=\"text/javascript\" src=\"apiCss/jquery-1.6.2.min.js\"></script>\n\t\t<script type='text/javascript' src='apiCss/jquery.ztree.core-3.5.js'></script>\n\t\t<script type='text/javascript' src='apiCss/api.js'></script>\n\t\t<script type=\"text/javascript\">\n\t\t\t$(document).ready(function(){\n\t\t\t\tapiContent._init();\n\t\t\t});\n\t\t</script>\n\t</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/API_en.html",
    "content": "<!DOCTYPE html>\n<html>\n\t<head>\n\t\t<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\t\t<title>API Document [zTree -- jQuery tree plug-ins.]</title>\n\t\t<link rel=\"stylesheet\" href=\"apiCss/common.css\" type=\"text/css\">\n\t\t<link rel='stylesheet' href='apiCss/zTreeStyleForApi.css' type='text/css'>\n\t\t<script type=\"text/javascript\">\n\t\t\tvar ie = (function(){\n\t\t\t\tvar undef,\n\t\t\t\tv = 3,\n\t\t\t\tdiv = document.createElement('div'),\n\t\t\t\tall = div.getElementsByTagName('i');\n\t\t\t\twhile (\n\t\t\t\tdiv.innerHTML = '<!--[if gt IE ' + (++v) + ']><i></i><![endif]-->',\n\t\t\t\tall[0]\n\t\t\t);\n\t\t\t\treturn v > 4 ? v : undef;\n\t\t\t}()), ie6 = (ie === 6),\n\t\t\tpath = window.location.pathname.replace(/.*\\/([^\\/\\.]*)\\..*/g,\"$1\"),\n\t\t\tlangLib = [];\n\t\t\tie = ie<9;\n\t\t\tif(ie) {\n\t\t\t\tdocument.write('<link rel=\"stylesheet\" href=\"apiCss/common_ie6.css\" type=\"text/css\">');\n\t\t\t}\n\t\t\tvar lang = \"en\",\n\t\t\tajaxMsg = \"If you use chrome browser, please copy the API files to local webserver. \\n\\n( because chrome browser can't allow AJAX access to 'file://' )\";\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div id=\"header_wrap\" class=\"header_wrap\" style=\"padding-top: 30px;\">\n\t\t\t<div id=\"header\" class=\"header round\">\n\t\t\t\t<div class=\"light-bulb\" alt=\"\"></div>\n\t\t\t\t<div class=\"ieSuggest\">If you use the Chrome / FireFox / Opera / IE9 browser will be even more dazzling effect!</div>\n\t\t\t\t<div class=\"google_plus\"><g:plusone></g:plusone></div>\n\t\t\t\t<div class=\"header-text\">\n\t\t\t\t\t<h1><em>zTree v3.5.17 API Document</em></h1><p></p>\n\t\t\t\t\t<p>all.js = core + excheck + exedit ( without exhide ); if you found some mistakes please contact me.</p>\n\t\t\t\t</div>\n\t\t\t\t<ul class=\"shortcuts language\" style=\"top:0;\">\n\t\t\t\t\t<li><a href=\"API_cn.html\" onclick=\"window.location.href='API_cn.html'\"><button class=\"ico cn\" title=\"Chinese\" type=\"button\"></button><span class=\"\"></span></a></li>\n\t\t\t\t</ul>\n\t\t\t</div>\n\t\t</div>\n\t\t<div id=\"content_wrap\" class=\"content_wrap\">\n\t\t\t<div id=\"content\" class=\"content\">\n\t\t\t\t<div class=\"nav_section\">\n\t\t\t\t\t<ul>\n\t\t\t\t\t\t<li class=\"first\">Notes: </li>\n\t\t\t\t\t\t<li><button class=\"ico16 z_core\" onfocus=\"this.blur();\"></button><span>core package</span></li>\n\t\t\t\t\t\t<li><button class=\"ico16 z_check\" onfocus=\"this.blur();\"></button><span>excheck pack</span></li>\n\t\t\t\t\t\t<li><button class=\"ico16 z_edit\" onfocus=\"this.blur();\"></button><span>exedit pack</span></li>\n\t\t\t\t\t\t<li><button class=\"ico16 z_hide\" onfocus=\"this.blur();\"></button><span>exhide pack</span></li>\n\t\t\t\t\t\t<li class=\"noline\">\n\t\t\t\t\t\t\t<button class=\"ico16 z_search\" onfocus=\"this.blur();\" title=\"'Enter', 'left' and 'right' key can locate the search results quickly.\"></button>\n\t\t\t\t\t\t\t<input type=\"text\" class=\"searchKey search empty\" value=\"\"><input type=\"text\" class=\"searchResult search\" value=\"\">\n\t\t\t\t\t\t\t<button class=\"ico16 searchPrev disabled\" onfocus=\"this.blur();\" title=\"'Enter', 'left' and 'right' key can locate the search results quickly.\"></button><button class=\"ico16 searchNext disabled\" onfocus=\"this.blur();\" title=\"'Enter', 'left' and 'right' key can locate the search results quickly.\"></button>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t</ul>\n\t\t\t\t</div>\n\n\t\t\t\t<div id=\"contentBox\" class=\"contentBox round clearfix\">\n\t\t\t\t\t<div id=\"apiContent\" class=\"apiContent\">\n\t\t\t\t\t\t<div id=\"api_setting\" class=\"api_setting left\">\n\t\t\t\t\t\t\t<ul class=\"api_content_title\"><li>setting details</li></ul>\n\t\t\t\t\t\t\t<ul id=\"settingTree\" class=\"ztree\"></ul>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<div id=\"api_function\" class=\"api_function right\">\n\t\t\t\t\t\t\t<ul class=\"api_content_title\"><li>zTree method details</li></ul>\n\t\t\t\t\t\t\t<ul id=\"functionTree\" class=\"ztree\"></ul>\n\t\t\t\t\t\t\t<ul class=\"api_content_title\"><li>treeNode data details</li></ul>\n\t\t\t\t\t\t\t<ul id=\"treenodeTree\" class=\"ztree\"></ul>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"clear\"></div>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- overlayed -->\n\t\t<div id=\"overlayDiv\" class=\"baby_overlay\">\n\t\t\t<div id=\"overlayContent\" class=\"content round clearfix\">\n\t\t\t\t<div class=\"overlaySearch\">\n\t\t\t\t\t<button class=\"ico16 z_search\" onfocus=\"this.blur();\" title=\"'Enter', 'left' and 'right' key can locate the search results quickly.\"></button>\n\t\t\t\t\t<input type=\"text\" class=\"searchKey search empty\" value=\"\"><input type=\"text\" class=\"searchResult search\" value=\"\">\n\t\t\t\t\t<button class=\"ico16 searchPrev disabled\" onfocus=\"this.blur();\" title=\"'Enter', 'left' and 'right' key can locate the search results quickly.\"></button><button class=\"ico16 searchNext disabled\" onfocus=\"this.blur();\" title=\"'Enter', 'left' and 'right' key can locate the search results quickly.\"></button>\n\t\t\t\t</div>\n\t\t\t\t<a id=\"overlayDivCloseBtn\" class=\"close\"></a>\n\t\t\t\t<div id=\"overlayDetailDiv\" class=\"details\"></div>\n\t\t\t</div>\n\t\t\t<div id=\"overlayDivArrow\" class=\"baby_overlay_arrow\"></div>\n\t\t</div>\n\t\t<script type=\"text/javascript\" src=\"apiCss/jquery-1.6.2.min.js\"></script>\n\t\t<script type='text/javascript' src='apiCss/jquery.ztree.core-3.5.js'></script>\n\t\t<script type='text/javascript' src='apiCss/api.js'></script>\n\t\t<script type=\"text/javascript\">\n\t\t\t$(document).ready(function(){\n\t\t\t\tapiContent._init();\n\t\t\t});\n\t\t</script>\n\t</body>\n</html>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/apiCss/api.js",
    "content": "var apiContent = {\n\tzTree_Setting: null,\n\tzTree_Node: null,\n\tzTree_Function: null,\n\toverlayDiv : null,\n\toverlayContent : null,\n\toverlayDetailDiv : null,\n\toverlayCloseBtn: null,\n\toverlayArrow: null,\n\tcontentBoxDiv : null,\n\tsettingDiv : null,\n\tfunctionDiv : null,\n\toverlaySearch: null,\n\tsearchKey: null,\n\tsearchResultInput: null,\n\tsearchPrevBtn: null,\n\tsearchNextBtn: null,\n\tapiCache: {},\n\tlastValue: \"\",\n\tsearchNodes: [],\n\tsearchNodesCur: 0,\n\n\t_init: function() {\n\t\tthis.overlayDiv = $(\"#overlayDiv\");\n\t\tthis.overlayContent = $(\"#overlayContent\");\n\t\tthis.overlayDetailDiv = $(\"#overlayDetailDiv\");\n\t\tthis.overlayCloseBtn = $(\"#overlayDivCloseBtn\");\n\t\tthis.overlayArrow = $(\"#overlayDivArrow\");\n\t\tthis.contentBoxDiv = $(\"#contentBox\");\n\t\tthis.settingDiv = $(\"#api_setting\");\n\t\tthis.functionDiv = $(\"#api_function\");\n\t\tthis.searchKey = $(\".searchKey\");\n\t\tthis.overlaySearch = $(\".overlaySearch\");\n\t\tthis.searchResultInput = $(\".searchResult\");\n\t\tthis.searchPrevBtn = $(\".searchPrev\");\n\t\tthis.searchNextBtn = $(\".searchNext\");\n\t\tvar setting = {\n\t\t\tview: {\n\t\t\t\tfontCss: this.getFontCss,\n\t\t\t\tshowLine: false,\n\t\t\t\tshowIcon: this.showIcon,\n\t\t\t\tshowTitle: this.getTitle,\n\t\t\t\tselectedMulti: false,\n\t\t\t\tdblClickExpand: false\n\t\t\t},\n\t\t\tdata: {\n\t\t\t\tkey: {\n\t\t\t\t\ttitle: \"tt\"\n\t\t\t\t},\n\t\t\t\tsimpleData: {\n\t\t\t\t\tenable:true,\n\t\t\t\t\tidKey: \"id\",\n\t\t\t\t\tpIdKey: \"pId\",\n\t\t\t\t\trootPId: \"\"\n\t\t\t\t}\n\t\t\t},\n\t\t\tcallback: {\n\t\t\t\tonNodeCreated: this.onNodeCreated,\n\t\t\t\tbeforeClick: this.beforeClick\n\t\t\t}\n\t\t};\n\t\tvar setting_nodes =[\n\t\t\t{id:1, pId:0, t:\"setting\", name:\"var setting = {\", open:true},\n\t\t\t{id:11, pId:1, t:\"treeId\", name:\"treeId : \\\"\\\",\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:12, pId:1, t:\"treeObj\", name:\"treeObj : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:121, pId:1, name:\"\"},\n\n\t\t\t{id:20, pId:1, t:\"async\", name:\"async : {\", open:true},\n\t\t\t{id:201, pId:20, t:\"autoParam\", name:\"autoParam : [],\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:208, pId:20, t:\"contentType\", name:\"contentType : \\\"application...\\\",\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:202, pId:20, t:\"dataFilter\", name:\"dataFilter : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:203, pId:20, t:\"dataType\", name:\"dataType : \\\"text\\\",\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:204, pId:20, t:\"enable\", name:\"enable : false,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:205, pId:20, t:\"otherParam\", name:\"otherParam : [],\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:206, pId:20, t:\"type\", name:\"type : \\\"post\\\",\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:207, pId:20, t:\"url\", name:\"url : \\\"\\\"\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:21, pId:1, name:\"},\"},\n\t\t\t{id:22, pId:1, name:\"\"},\n\n\t\t\t{id:30, pId:1, t:\"callback\", name:\"callback : {\", open:true},\n\t\t\t{id:3001, pId:30, t:\"beforeAsync\", name:\"beforeAsync : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3002, pId:30, t:\"beforeCheck\", name:\"beforeCheck : null,\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:3003, pId:30, t:\"beforeClick\", name:\"beforeClick : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3004, pId:30, t:\"beforeCollapse\", name:\"beforeCollapse : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3004, pId:30, t:\"beforeDblClick\", name:\"beforeDblClick : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3005, pId:30, t:\"beforeDrag\", name:\"beforeDrag : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3006, pId:30, t:\"beforeDragOpen\", name:\"beforeDragOpen : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3007, pId:30, t:\"beforeDrop\", name:\"beforeDrop : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3029, pId:30, t:\"beforeEditName\", name:\"beforeEditName : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3008, pId:30, t:\"beforeExpand\", name:\"beforeExpand : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3009, pId:30, t:\"beforeMouseDown\", name:\"beforeMouseDown : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3010, pId:30, t:\"beforeMouseUp\", name:\"beforeMouseUp : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3011, pId:30, t:\"beforeRemove\", name:\"beforeRemove : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3012, pId:30, t:\"beforeRename\", name:\"beforeRename : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3013, pId:30, t:\"beforeRightClick\", name:\"beforeRightClick : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3014, pId:30, name:\"\"},\n\t\t\t{id:3015, pId:30, t:\"onAsyncError\", name:\"onAsyncError : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3016, pId:30, t:\"onAsyncSuccess\", name:\"onAsyncSuccess : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3017, pId:30, t:\"onCheck\", name:\"onCheck : null,\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:3018, pId:30, t:\"onClick\", name:\"onClick : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3019, pId:30, t:\"onCollapse\", name:\"onCollapse : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3029, pId:30, t:\"onDblClick\", name:\"onDblClick : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3020, pId:30, t:\"onDrag\", name:\"onDrag : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3030, pId:30, t:\"onDragMove\", name:\"onDragMove : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3021, pId:30, t:\"onDrop\", name:\"onDrop : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3022, pId:30, t:\"onExpand\", name:\"onExpand : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3023, pId:30, t:\"onMouseDown\", name:\"onMouseDown : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3024, pId:30, t:\"onMouseUp\", name:\"onMouseUp : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3025, pId:30, t:\"onNodeCreated\", name:\"onNodeCreated : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:3026, pId:30, t:\"onRemove\", name:\"onRemove : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3027, pId:30, t:\"onRename\", name:\"onRename : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:3028, pId:30, t:\"onRightClick\", name:\"onRightClick : null\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:31, pId:1, name:\"},\"},\n\t\t\t{id:32, pId:1, name:\"\"},\n\n\t\t\t{id:40, pId:1, t:\"check\", name:\"check : {\", open:true},\n\t\t\t{id:405, pId:40, t:\"autoCheckTrigger\", name:\"autoCheckTrigger : false,\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:401, pId:40, t:\"chkboxType\", name:\"chkboxType : {\\\"Y\\\": \\\"ps\\\", \\\"N\\\": \\\"ps\\\"},\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:402, pId:40, t:\"chkStyle\", name:\"chkStyle : \\\"checkbox\\\",\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:403, pId:40, t:\"enable\", name:\"enable : false,\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:406, pId:40, t:\"nocheckInherit\", name:\"nocheckInherit : false\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:407, pId:40, t:\"chkDisabledInherit\", name:\"chkDisabledInherit : false\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:404, pId:40, t:\"radioType\", name:\"radioType : \\\"level\\\"\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:41, pId:1, name:\"},\"},\n\t\t\t{id:42, pId:1, name:\"\"},\n\n\t\t\t{id:50, pId:1, t:\"data\", name:\"data : {\", open:true},\n\t\t\t{id:500, pId:50, t:\"keep\", name:\"keep : {\", open:true},\n\t\t\t{id:5001, pId:500, t:\"leaf\", name:\"leaf : false,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:5002, pId:500, t:\"parent\", name:\"parent : false\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:501, pId:50, name:\"},\"},\n\n\t\t\t{id:510, pId:50, t:\"key\", name:\"key : {\", open:true},\n\t\t\t{id:5101, pId:510, t:\"checked\", name:\"checked : \\\"checked\\\",\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:5102, pId:510, t:\"children\", name:\"children : \\\"children\\\",\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:5103, pId:510, t:\"name\", name:\"name : \\\"name\\\",\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:5104, pId:510, t:\"title\", name:\"title : \\\"\\\"\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:5105, pId:510, t:\"url\", name:\"url : \\\"url\\\"\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:511, pId:50, name:\"},\"},\n\n\t\t\t{id:520, pId:50, t:\"simpleData\", name:\"simpleData : {\", open:true},\n\t\t\t{id:5201, pId:520, t:\"enable\", name:\"enable : false,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:5202, pId:520, t:\"idKey\", name:\"idKey : \\\"id\\\",\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:5203, pId:520, t:\"pIdKey\", name:\"pIdKey : \\\"pId\\\",\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:5204, pId:520, t:\"rootPId\", name:\"rootPId : null\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:521, pId:50, name:\"}\"},\n\t\t\t{id:51, pId:1, name:\"},\"},\n\t\t\t{id:52, pId:1, name:\"\"},\n\n\t\t\t{id:60, pId:1, t:\"edit\", name:\"edit : {\", open:true},\n\t\t\t{id:601, pId:60, t:\"drag\", name:\"drag : {\", open:true},\n\t\t\t{id:60111, pId:601, t:\"autoExpandTrigger\", name:\"autoExpandTrigger : true,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:60101, pId:601, t:\"isCopy\", name:\"isCopy : true,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:60102, pId:601, t:\"isMove\", name:\"isMove : true,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:60103, pId:601, t:\"prev\", name:\"prev : true,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:60104, pId:601, t:\"next\", name:\"next : true,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:60105, pId:601, t:\"inner\", name:\"inner : true,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:60107, pId:601, t:\"borderMax\", name:\"borderMax : 10,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:60108, pId:601, t:\"borderMin\", name:\"borderMin : -5,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:60106, pId:601, t:\"minMoveSize\", name:\"minMoveSize : 5,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:60109, pId:601, t:\"maxShowNodeNum\", name:\"maxShowNodeNum : 5,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:60110, pId:601, t:\"autoOpenTime\", name:\"autoOpenTime : 500\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:602, pId:60, name:\"},\"},\n\t\t\t{id:608, pId:60, t:\"editNameSelectAll\", name:\"editNameSelectAll : false,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:603, pId:60, t:\"enable\", name:\"enable : false,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:604, pId:60, t:\"removeTitle\", name:\"removeTitle : \\\"remove\\\",\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:605, pId:60, t:\"renameTitle\", name:\"renameTitle : \\\"rename\\\",\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:606, pId:60, t:\"showRemoveBtn\", name:\"showRemoveBtn : true,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:607, pId:60, t:\"showRenameBtn\", name:\"showRenameBtn : true\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:61, pId:1, name:\"},\"},\n\t\t\t{id:62, pId:1, name:\"\"},\n\n\t\t\t{id:70, pId:1, t:\"view\", name:\"view : {\", open:true},\n\t\t\t{id:7001, pId:70, t:\"addDiyDom\", name:\"addDiyDom : null,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:7002, pId:70, t:\"addHoverDom\", name:\"addHoverDom : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:7003, pId:70, t:\"autoCancelSelected\", name:\"autoCancelSelected : true,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:7004, pId:70, t:\"dblClickExpand\", name:\"dblClickExpand : true,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:7005, pId:70, t:\"expandSpeed\", name:\"expandSpeed : \\\"fast\\\",\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:7006, pId:70, t:\"fontCss\", name:\"fontCss : {},\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:7012, pId:70, t:\"nameIsHTML\", name:\"nameIsHTML : false,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:7007, pId:70, t:\"removeHoverDom\", name:\"removeHoverDom : null,\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:7008, pId:70, t:\"selectedMulti\", name:\"selectedMulti : true,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:7009, pId:70, t:\"showIcon\", name:\"showIcon : true,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:7010, pId:70, t:\"showLine\", name:\"showLine : true,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:7011, pId:70, t:\"showTitle\", name:\"showTitle : true,\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:7012, pId:70, t:\"txtSelectedEnable\", name:\"txtSelectedEnable : false\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:71, pId:1, name:\"}\"},\n\n\t\t\t{id:2, pId:0, name:\"}\"}\n\t\t];\n\n\t\tvar treenode_nodes =[\n\t\t\t{id:1, pId:0, t:\"treeNode\", name:\"treeNode : {\", open:true},\n\t\t\t{id:101, pId:1, t:\"checked\", name:\"checked\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:102, pId:1, t:\"children\", name:\"children\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:128, pId:1, t:\"chkDisabled\", name:\"chkDisabled\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:127, pId:1, t:\"click\", name:\"click\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:103, pId:1, t:\"getCheckStatus\", name:\"getCheckStatus ()\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:104, pId:1, t:\"getNextNode\", name:\"getNextNode ()\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:105, pId:1, t:\"getParentNode\", name:\"getParentNode ()\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:106, pId:1, t:\"getPreNode\", name:\"getPreNode ()\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:129, pId:1, t:\"halfCheck\", name:\"halfCheck\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:107, pId:1, t:\"icon\", name:\"icon\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:108, pId:1, t:\"iconClose\", name:\"iconClose\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:109, pId:1, t:\"iconOpen\", name:\"iconOpen\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:110, pId:1, t:\"iconSkin\", name:\"iconSkin\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:131, pId:1, t:\"isHidden\", name:\"isHidden\", iconSkin:\"hide\", showAPI:true},\n\t\t\t{id:111, pId:1, t:\"isParent\", name:\"isParent\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:132, pId:1, t:\"name\", name:\"name\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:112, pId:1, t:\"nocheck\", name:\"nocheck\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:113, pId:1, t:\"open\", name:\"open\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:133, pId:1, t:\"target\", name:\"target\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:134, pId:1, t:\"url\", name:\"url\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:114, pId:1, t:\"diy\", name:\"*DIY*\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:115, pId:1, name:\"\"},\n\t\t\t{id:116, pId:1, t:\"check_Child_State\", name:\"[check_Child_State]\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:117, pId:1, t:\"check_Focus\", name:\"[check_Focus]\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:118, pId:1, t:\"checkedOld\", name:\"[checkedOld]\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:119, pId:1, t:\"editNameFlag\", name:\"[editNameFlag]\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:120, pId:1, t:\"isAjaxing\", name:\"[isAjaxing]\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:121, pId:1, t:\"isFirstNode\", name:\"[isFirstNode]\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:122, pId:1, t:\"isHover\", name:\"[isHover]\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:123, pId:1, t:\"isLastNode\", name:\"[isLastNode]\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:124, pId:1, t:\"level\", name:\"[level]\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:125, pId:1, t:\"parentTId\", name:\"[parentTId]\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:126, pId:1, t:\"tId\", name:\"[tId]\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:130, pId:1, t:\"zAsync\", name:\"[zAsync]\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:2, pId:0, name:\"}\"}\n\t\t];\n\n\t\tvar function_nodes =[\n\t\t\t{id:1, pId:0, t:\"$.fn.zTree\", name:\"$.fn.zTree : {\", open:true},\n\t\t\t{id:11, pId:1, t:\"init\", name:\"init (obj, zSetting, zNodes)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:12, pId:1, t:\"getZTreeObj\", name:\"getZTreeObj (treeId)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:14, pId:1, t:\"destroy\", name:\"destroy (treeId)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:13, pId:1, t:\"_z\", name:\"_z : {tools, view, event, data}\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:2, pId:0, name:\"}\"},\n\t\t\t{id:3, pId:0, name:\"\"},\n\t\t\t{id:4, pId:0, t:\"zTreeObj\", name:\"zTreeObj : {\", open:true},\n\t\t\t{id:401, pId:4, t:\"setting\", name:\"setting\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:402, pId:4, t:\"addNodes\", name:\"addNodes (parentNode, newNodes, isSilent)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:403, pId:4, t:\"cancelEditName\", name:\"cancelEditName (newName)\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:404, pId:4, t:\"cancelSelectedNode\", name:\"cancelSelectedNode (node)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:405, pId:4, t:\"checkAllNodes\", name:\"checkAllNodes (checked)\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:406, pId:4, t:\"checkNode\", name:\"checkNode (node, checked, checkTypeFlag, callbackFlag)\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:407, pId:4, t:\"copyNode\", name:\"copyNode (targetNode, node, moveType, isSilent)\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:436, pId:4, t:\"destroy\", name:\"destroy ()\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:408, pId:4, t:\"editName\", name:\"editName (node)\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:409, pId:4, t:\"expandAll\", name:\"expandAll (expandFlag)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:410, pId:4, t:\"expandNode\", name:\"expandNode (node, expandFlag, sonSign, focus, callbackFlag)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:411, pId:4, t:\"getChangeCheckedNodes\", name:\"getChangeCheckedNodes ()\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:412, pId:4, t:\"getCheckedNodes\", name:\"getCheckedNodes (checked)\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:413, pId:4, t:\"getNodeByParam\", name:\"getNodeByParam (key, value, parentNode)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:414, pId:4, t:\"getNodeByTId\", name:\"getNodeByTId (tId)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:415, pId:4, t:\"getNodeIndex\", name:\"getNodeIndex (node)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:416, pId:4, t:\"getNodes\", name:\"getNodes ()\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:431, pId:4, t:\"getNodesByFilter\", name:\"getNodesByFilter (filter, isSingle, parentNode, invokeParam)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:417, pId:4, t:\"getNodesByParam\", name:\"getNodesByParam (key, value, parentNode)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:418, pId:4, t:\"getNodesByParamFuzzy\", name:\"getNodesByParamFuzzy (key, value, parentNode)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:419, pId:4, t:\"getSelectedNodes\", name:\"getSelectedNodes ()\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:432, pId:4, t:\"hideNode\", name:\"hideNode (node)\", iconSkin:\"hide\", showAPI:true},\n\t\t\t{id:433, pId:4, t:\"hideNodes\", name:\"hideNodes (nodes)\", iconSkin:\"hide\", showAPI:true},\n\t\t\t{id:420, pId:4, t:\"moveNode\", name:\"moveNode (targetNode, node, moveType, isSilent)\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:421, pId:4, t:\"reAsyncChildNodes\", name:\"reAsyncChildNodes (parentNode, reloadType, isSilent)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:422, pId:4, t:\"refresh\", name:\"refresh ()\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:423, pId:4, t:\"removeChildNodes\", name:\"removeChildNodes (parentNode)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:424, pId:4, t:\"removeNode\", name:\"removeNode (node, callbackFlag)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:425, pId:4, t:\"selectNode\", name:\"selectNode (node, addFlag)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:430, pId:4, t:\"setChkDisabled\", name:\"setChkDisabled (node, disabled, inheritParent, inheritChildren)\", iconSkin:\"check\", showAPI:true},\n\t\t\t{id:426, pId:4, t:\"setEditable\", name:\"setEditable (editable)\", iconSkin:\"edit\", showAPI:true},\n\t\t\t{id:434, pId:4, t:\"showNode\", name:\"showNode (node)\", iconSkin:\"hide\", showAPI:true},\n\t\t\t{id:435, pId:4, t:\"showNodes\", name:\"showNodes (nodes)\", iconSkin:\"hide\", showAPI:true},\n\t\t\t{id:427, pId:4, t:\"transformToArray\", name:\"transformToArray (nodes)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:428, pId:4, t:\"transformTozTreeNodes\", name:\"transformTozTreeNodes (simpleNodes)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:429, pId:4, t:\"updateNode\", name:\"updateNode (node, checkTypeFlag)\", iconSkin:\"core\", showAPI:true},\n\t\t\t{id:5, pId:0, name:\"}\"}\n\t\t];\n\n\t\tapiContent.zTree_Setting = $.fn.zTree.init($(\"#settingTree\"), $.fn.zTree._z.tools.clone(setting), setting_nodes);\n\t\tapiContent.zTree_Node = $.fn.zTree.init($(\"#treenodeTree\"), $.fn.zTree._z.tools.clone(setting), treenode_nodes);\n\t\tapiContent.zTree_Function = $.fn.zTree.init($(\"#functionTree\"), $.fn.zTree._z.tools.clone(setting), function_nodes);\n\t\tthis.bindEvent();\n\n\t},\n\tbindEvent: function() {\n\t\t$(document).bind(\"keydown\", this.listenKeyDown)\n\t\tthis.overlayCloseBtn.bind(\"click\", apiContent.overlayClose);\n\t\tthis.searchResultInput.bind(\"click\", function(e) {\n\t\t\t$(this).prev().get(0).focus();\n\t\t\tthis.blur();\n\t\t}).bind(\"focus\", function(e) {\n\t\t\tthis.blur();\n\t\t});\n\t\tthis.searchKey.bind(\"focus\", this.focusKey)\n\t\t\t.bind(\"blur\", this.blurKey)\n\t\t\t.bind(\"propertychange\", this.searchNode)\n\t\t\t.bind(\"input\", this.searchNode);\n\t\tthis.searchPrevBtn.bind(\"click\", this.searchPrev);\n\t\tthis.searchNextBtn.bind(\"click\", this.searchNext);\n\t},\n\tsetSameKey: function(value) {\n\t\tapiContent.searchKey.attr(\"value\", value);\n\t},\n\tfocusKey: function(e) {\n\t\tif (apiContent.searchKey.hasClass(\"empty\")) {\n\t\t\tapiContent.searchKey.removeClass(\"empty\");\n\t\t}\n\t},\n\tblurKey: function(e) {\n\t\tapiContent.setSameKey(e.target.value);\n\t\tif (e.target.value === \"\") {\n\t\t\tapiContent.searchKey.addClass(\"empty\");\n\t\t}\n\t},\n\tlistenKeyDown: function(e) {\n\t\tif (e.keyCode==\"13\" && apiContent.overlayDiv.is(\":hidden\")) {\n\t\t\tapiContent.openAPI();\n\t\t} else if (e.keyCode==\"37\") {\n\t\t\tapiContent.searchPrev();\n\t\t} else if (e.keyCode==\"13\" || e.keyCode==\"39\") {\n\t\t\tapiContent.searchNext();\n\t\t}\n\t},\n\topenAPI: function() {\n\t\tif (apiContent.searchNodes.length > 0) {\n\t\t\tvar setting_zTree = $.fn.zTree.getZTreeObj(\"settingTree\"),\n\t\t\ttreenode_zTree = $.fn.zTree.getZTreeObj(\"treenodeTree\"),\n\t\t\tfunction_zTree = $.fn.zTree.getZTreeObj(\"functionTree\");\n\t\t\tif (apiContent.searchNodesCur < 0 || apiContent.searchNodesCur > apiContent.searchNodes.length -1) {\n\t\t\t\tapiContent.searchNodesCur = 0;\n\t\t\t}\n\t\t\tvar node = apiContent.searchNodes[apiContent.searchNodesCur];\n\n\t\t\tif (node.tId.indexOf(\"setting\") > -1) {\n\t\t\t\tsetting_zTree.selectNode(node);\n\t\t\t} else if (node.tId.indexOf(\"treenode\") > -1) {\n\t\t\t\ttreenode_zTree.selectNode(node);\n\t\t\t} else {\n\t\t\t\tfunction_zTree.selectNode(node);\n\t\t\t}\n\t\t\tapiContent.beforeClick(node.tId.substring(0, node.tId.indexOf(\"_\")), node, true);\n\t\t\tapiContent.searchCur();\n\t\t}\n\t},\n\tsearchNode: function(e) {\n\t\tvar setting_zTree = $.fn.zTree.getZTreeObj(\"settingTree\"),\n\t\ttreenode_zTree = $.fn.zTree.getZTreeObj(\"treenodeTree\"),\n\t\tfunction_zTree = $.fn.zTree.getZTreeObj(\"functionTree\");\n\t\tif (apiContent.curKey == e.target.value) return;\n\t\tapiContent.curKey = e.target.value;\n\t\tvar value = $.trim(apiContent.curKey);\n\t\tapiContent.setSameKey(apiContent.curKey);\n\t\tif (apiContent.searchKey.hasClass(\"empty\")) {\n\t\t\tvalue = \"\";\n\t\t\tapiContent.searchResultInput.removeClass(\"noResult\").attr(\"value\",\"\");\n\t\t}\n\t\tif (apiContent.lastValue === value) return;\n\n\t\tapiContent.updateNodes(false);\n\t\tapiContent.lastValue = value;\n\t\tif (value === \"\" || value.length < 2) {\n\t\t\tapiContent.searchNodes = [];\n\t\t\tapiContent.searchNodesCur = -1;\n\t\t\tapiContent.searchCur(true);\n\t\t\treturn;\n\t\t}\n\n\t\tvar settingNodeList = setting_zTree.getNodesByFilter(apiContent.searchFilter);\n\t\tvar functionNodeList = function_zTree.getNodesByFilter(apiContent.searchFilter);\n\t\tvar treenodeNodeList = treenode_zTree.getNodesByFilter(apiContent.searchFilter);\n\t\tapiContent.searchNodes = settingNodeList.concat(functionNodeList).concat(treenodeNodeList);\n\t\tapiContent.searchNodesCur = -1;\n\t\tapiContent.searchCur();\n\t\tapiContent.updateNodes(true);\n\t},\n\tsearchFilter: function(node) {\n\t\tvar value = $.trim(apiContent.searchKey.get(0).value).toLowerCase();\n\t\treturn (node.showAPI && node.name.toLowerCase().indexOf(value) > -1);\n\t},\n\tsearchPrev: function(e) {\n\t\tif (apiContent.searchPrevBtn.hasClass(\"disabled\")) return;\n\t\tapiContent.searchNodesCur--;\n\t\tif (apiContent.searchNodesCur < 0 || apiContent.searchNodesCur > apiContent.searchNodes.length -1) {\n\t\t\tapiContent.searchNodesCur = apiContent.searchNodes.length -1;\n\t\t}\n\t\tapiContent.openAPI();\n\t},\n\tsearchNext: function(e) {\n\t\tif (apiContent.searchNextBtn.hasClass(\"disabled\")) return;\n\t\tapiContent.searchNodesCur++;\n\t\tapiContent.openAPI();\n\t},\n\tsearchCur: function(init) {\n\t\tvar result = apiContent.searchNodes;\n\t\tif (init) {\n\t\t\tapiContent.searchResultInput.removeClass(\"noResult\").attr(\"value\",\"\");\n\t\t} else if (result.length == 0) {\n\t\t\tapiContent.searchResultInput.addClass(\"noResult\").attr(\"value\",\"  [ 0 / 0 ]  \");\n\t\t} else {\n\t\t\tapiContent.searchResultInput.removeClass(\"noResult\").attr(\"value\",\" [ \" + (apiContent.searchNodesCur > -1 ? apiContent.searchNodesCur+1 : \"?\")+ \" / \" + result.length + \" ] \");\n\t\t}\n\t\tif (result.length > 0) {\n\t\t\tapiContent.searchPrevBtn.removeClass(\"disabled\");\n\t\t\tapiContent.searchNextBtn.removeClass(\"disabled\");\n\t\t} else {\n\t\t\tapiContent.searchPrevBtn.addClass(\"disabled\");\n\t\t\tapiContent.searchNextBtn.addClass(\"disabled\");\n\t\t}\n\t},\n\tupdateNodes: function(highlight) {\n\t\tvar setting_zTree = $.fn.zTree.getZTreeObj(\"settingTree\"),\n\t\ttreenode_zTree = $.fn.zTree.getZTreeObj(\"treenodeTree\"),\n\t\tfunction_zTree = $.fn.zTree.getZTreeObj(\"functionTree\"),\n\t\tnode = null;\n\t\tfor( var i=0, l=apiContent.searchNodes.length; i<l; i++) {\n\t\t\tnode = apiContent.searchNodes[i];\n\t\t\tif (node.level > 0) {\n\t\t\t\tnode.highlight = highlight;\n\t\t\t\tif (node.tId.indexOf(\"setting\") > -1) {\n\t\t\t\t\tsetting_zTree.updateNode(node);\n\t\t\t\t} else if (node.tId.indexOf(\"treenode\") > -1) {\n\t\t\t\t\ttreenode_zTree.updateNode(node);\n\t\t\t\t} else {\n\t\t\t\t\tfunction_zTree.updateNode(node);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\tgetFontCss: function(treeId, treeNode) {\n\t\treturn (!!treeNode.highlight) ? {color:\"#A60000\", \"font-weight\":\"bold\"} : {color:\"#333\", \"font-weight\":\"normal\"};\n\t},\n\tgetTitle: function(treeId, node) {\n\t\tvar t = [], n = node;\n\t\twhile (n && !!n.t) {\n\t\t\tt.push(n.t);\n\t\t\tn = n.getParentNode();\n\t\t}\n\t\tt = t.reverse();\n\t\tnode.tt = t.join('.');\n\t\treturn true;\n\t},\n\tshowIcon: function(treeId, node) {\n\t\treturn (!!node.iconSkin);\n\t},\n\tonNodeCreated: function (e, treeId, node) {\n\t\tvar a = $(\"#\" + node.tId + \"_a\");\n\t\tif (node.showAPI) {\n\t\t\ta.attr(\"rel\", \"#overlayDiv\");\n\t\t} else {\n\t\t\ta.css({cursor: \"default\"});\n\t\t}\n\t},\n\tbeforeClick: function (treeId, node, noClear) {\n\t\tif (!node.showAPI) return false;\n\t\tvar o = $(\"#\" + node.tId + \"_a\");\n\t\tif (!!apiContent.apiCache[node.tId]) {\n\t\t\tapiContent.tmpDiv.html(apiContent.apiCache[node.tId]);\n\t\t\tapiContent.overlayShow(o, (apiContent.lastNode === node));\n\t\t} else {\n\t\t\tapiContent.overlayAjax(treeId, node);\n\t\t}\n\t\tapiContent.lastNode = node;\n\t\tif (node.tId.indexOf(\"settingTree\")>-1) {\n\t\t\tapiContent.settingDiv.removeClass(\"right\").addClass(\"left\");\n\t\t\tapiContent.functionDiv.removeClass(\"left\").addClass(\"right\");\n\t\t} else {\n\t\t\tapiContent.settingDiv.removeClass(\"left\").addClass(\"right\");\n\t\t\tapiContent.functionDiv.removeClass(\"right\").addClass(\"left\");\n\t\t}\n\n\t\tif (!noClear) {\n\t\t\tapiContent.clearSelectedNode();\n\t\t}\n\t\treturn true;\n\t},\n\tclearSelectedNode: function() {\n\t\tapiContent.zTree_Setting.cancelSelectedNode();\n\t\tapiContent.zTree_Node.cancelSelectedNode();\n\t\tapiContent.zTree_Function.cancelSelectedNode();\n\t},\n\toverlayAutoClose: function(e) {\n\t\tvar eId = e.target.id, eRel = e.target.getAttribute(\"rel\"), eClass = e.target.className;\n\t\tif (eId === \"overlayDiv\" || eId === \"overlayDivArrow\" || eClass.indexOf(\"searchPrev\") > -1 || eClass.indexOf(\"searchNext\") > -1 || !!eRel) return;\n\t\tif (!$(e.target).parents(\"[rel]\").length && !$(e.target).parents(\"#overlayDiv\").length) {\n\t\t\tapiContent.overlayClose();\n\t\t}\n\t},\n\toverlayClose: function() {\n\t\tvar o = apiContent.overlayDiv;\n\t\to.stop();\n\t\tapiContent.clearSelectedNode();\n\t\tif (ie) {\n\t\t\to.hide();\n\t\t} else {\n\t\t\tsetTimeout(function() {o.fadeTo(\"fast\", 0, function(){o.hide();})}, 200);\n\t\t}\n\t\t$(document).unbind(\"click\", apiContent.overlayAutoClose);\n\t},\n\toverlayShow: function(target, isSameNode) {\n\t\tvar w = $(window), o = apiContent.overlayDiv, a = apiContent.overlayArrow,\n\t\toc = apiContent.overlayContent, c = apiContent.contentBoxDiv,\n\t\tt = target.offset().top - 30,\n\t\tcMaxLeft = c.offset().left + c.outerWidth({margin:true}) - o.outerWidth({margin:true}) - 10,\n\t\tl = Math.min(cMaxLeft, target.offset().left + target.width() + 40),\n\t\tarrowT = target.offset().top + 16,\n\t\twMinTop = 100, footerHeight = 50, onlyFade = false,\n\t\twHeight = w.height(), wScrollTop=w.scrollTop(), wMaxTop = wHeight + wScrollTop - footerHeight;\n\t\tif (!apiContent.overlayMaxTop) {\n\t\t\tapiContent.overlayMaxTop = apiContent.contentBoxDiv.offset().top + apiContent.contentBoxDiv.height();\n\t\t}\n\t\to.stop();\n\t\tif (o.css(\"display\") !== \"block\") {\n\t\t\to.css({top: t, left: l});\n\t\t\ta.css({top:arrowT - t});\n\t\t\t$(document).bind(\"click\", apiContent.overlayAutoClose);\n\t\t}\n\t\tif (ie) {\n\t\t\tonlyFade = true;\n\t\t\to.show();\n\t\t} else {\n\t\t\to.fadeTo(\"fast\", 1);\n\t\t}\n\n\t\tvar h = apiContent.tmpDiv.outerHeight({margin:true}) + apiContent.overlaySearch.outerHeight();\n\t\tif ((t + h) > wMaxTop) {\n\t\t\tt = wMaxTop - h;\n\t\t}\n\t\tif ((t + h) > apiContent.overlayMaxTop) {\n\t\t\tt = apiContent.overlayMaxTop - h;\n\t\t}\n\t\tt = Math.max(t, wScrollTop, wMinTop);\n\t\tif ((t + h) > ($(\"body\").height()-footerHeight-20)) {\n\t\t\to.css(\"padding-bottom\", footerHeight + \"px\");\n\t\t} else {\n\t\t\to.css(\"padding-bottom\", \"0\");\n\t\t}\n\t\tapiContent.overlayDetailDiv.empty();\n\t\tapiContent.overlayDetailDiv.append(apiContent.tmpDiv.children());\n\t\tif (!onlyFade) {\n\t\t\tonlyFade = (isSameNode && t === parseInt(o.css(\"top\").replace(\"px\", \"\")));\n\t\t}\n\n\t\ta.removeClass(\"reverse\");\n\t\tif ( (arrowT - t) > (h-55) ) {\n\t\t\ta.addClass(\"reverse\");\n\t\t\tarrowT -= 55;\n\t\t}\n\n\t\tif (onlyFade) {\n\t\t\to.css({top: t, left: l});\n\t\t\toc.css({height: h});\n\t\t\ta.css({top:arrowT - t});\n\t\t} else {\n\t\t\to.animate({top: t, left: l}, {duration: \"normal\",easing: \"swing\", complete:null});\n\t\t\toc.animate({height: h}, {duration: \"fast\",easing: \"swing\", complete:null});\n\t\t\ta.animate({top:arrowT - t}, {duration: \"normal\",easing: \"linear\", complete:null});\n\t\t}\n\t},\n\toverlayAjax: function(treeId, node) {\n\t\tvar o = $(\"#\" + node.tId + \"_a\");\n\t\tif (node.isAjax) return;\n\t\tnode.isAjax = true;\n\t\t$.ajax({\n\t\t\ttype: \"get\",\n\t\t\turl: \"\" + lang + \"/\" + node.tt.replace(\"$.\", \"\") + \".html\",\n\t\t\tdata: null,\n\t\t\tdataType: \"text\",\n\t\t\tsuccess: function(msg) {\n\t\t\t\tif (!apiContent.tmpDiv) {\n\t\t\t\t\tvar tmpDiv = $(document.createElement(\"div\"));\n\t\t\t\t\ttmpDiv.addClass(\"baby_overlay_tmp\");\n\t\t\t\t\t$(\"body\").append(tmpDiv)\n\t\t\t\t\tapiContent.tmpDiv = $(document.createElement(\"div\"));\n\t\t\t\t\tapiContent.tmpDiv.addClass(\"details\");\n\t\t\t\t\ttmpDiv.append(apiContent.tmpDiv);\n\n\t\t\t\t} else {\n\t\t\t\t\tapiContent.tmpDiv.empty();\n\t\t\t\t}\n\t\t\t\tapiContent.tmpDiv.html(msg);\n\t\t\t\tapiContent.overlayShow(o, false);\n\t\t\t\tapiContent.apiCache[node.tId] = msg;\n\t\t\t\tnode.isAjax = false;\n\t\t\t},\n\t\t\terror: function(XMLHttpRequest, textStatus, errorThrown) {\n\t\t\t\talert(ajaxMsg)\n\t\t\t\tif (apiContent.tmpDiv) apiContent.tmpDiv.empty();\n\t\t\t\tnode.isAjax = false;\n\t\t\t}\n\t\t});\n\t}\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/apiCss/common.css",
    "content": "/* Resets */\nhtml, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {\n\tmargin: 0;padding: 0;border: 0;outline: 0;font-weight: inherit;font-style: inherit;font-size: 100%;font-family: inherit;vertical-align: baseline;}\n:focus {outline: 0;}\nbody {color: #2f332a;font: 15px/21px Arial, Helvetica, simsun, sans-serif;background: #528036 url(img/background.jpg) no-repeat fixed 0 0;}\np {padding-bottom: 20px;}\nol, ul {list-style: none;}\ntable {border-collapse: separate;border-spacing: 0;}\ncaption, th, td {text-align: left;font-weight: normal;}\nstrong {font-weight: bold;}\nem {font-style: italic;}\nhr {display: none;}\n.font1 {color: white;background-color: #528036;}\n.right {float: right;}\n.left {float: left;}\n.hide {display: none;}\n.round {-moz-border-radius: 15px;-webkit-border-radius: 15px;-khtml-border-radius: 15px;border-radius: 15px;}\n.clear {clear: both;}\n.clearfix {display: block;}\n.clearfix:after {content: \".\";display: block;clear: both;visibility: hidden;line-height: 0;height: 0;}\nhtml[xmlns] .clearfix {display: block;}\n* html .clearfix {height: 1%;}\n\n/* Link Styles */\na {color: #528036;}\na:link, a:visited {text-decoration: none;}\na:hover {color: #000;text-decoration: none;}\na:active {text-decoration: none;}\n\n/* Headings */\nh1, h2, h3, h4, h5, h6 {color: #2f332a;font-weight: bold;font-family: Helvetica, Arial, simsun, sans-serif;padding-bottom: 5px;}\nh1 {font-size: 36px;line-height: 44px;}\nh2 {font-size: 20px;line-height: 20px;}\nh3 {font-size: 14px;line-height: 14px;}\nh4 {font-size: 14px;font-weight: normal;line-height: 25px;}\n\n/* Wraps */\n.header_wrap {position: relative;min-width: 940px;padding: 100px 30px 0 30px;}\n.content_wrap {position: relative;min-width: 940px;padding: 0 30px 50px 30px;}\n.footer_wrap {bottom: 0;height: 47px;width: 100%;background-color: #1b1b1b;border-top: 1px solid #749e58;}\n\n/* Header */\n.header {position: relative;width: 940px;margin: 0 auto;height: 160px;border: 1px solid white;background: transparent url(img/header-bg.png) repeat-x 0 -50px;}\n.header-text {padding: 40px 25px 15px 120px;font-size: 18px;line-height: 24px;color: #747d67;font-family: Helvetica, sans-serif;}\n.header-text img {padding-bottom: 5px;}\n.shortcuts {white-space: nowrap;text-align: right;position: absolute;top: -45px;right: 5px;}\n.shortcuts.language {top: -85px;right:0px;}\n.shortcuts li {display: inline;font-size: 18px;line-height: 28px;font-family: Helvetica, Arial, simsun, sans-serif;padding-bottom: 5px;margin-left: 30px;cursor: pointer;}\n.shortcuts li button {cursor: pointer;}\n.shortcuts li span {border-bottom: 1px dotted white;}\n.shortcuts li span.selected {padding: 2px;background-color: #528036;}\n.shortcuts li a {color: #fff;}\n.ieSuggest {display:none;font-size: 12px;color: silver;position: absolute;left: 10px;top: 2px;}\n.google_plus {position: absolute;right: 10px; top:10px;}\n.light-bulb {position: absolute;left: -20px;bottom: -35px;width:116px;height:180px;background-image:url(img/lightbulb.png);background-repeat: no-repeat;}\n\n/* Content */\n.content {position: relative;width: 940px;margin: 0 auto;}\n.nav_section {position: relative;height: 20px;font-family: \"Myriad Pro\", \"Trebuchet MS\", sans-serif;font-size: 15px;color: #253;padding: 20px 0;}\n.nav_section ul {position: absolute;right: 10px;}\n.nav_section ul li {display: inline;line-height: 20px;margin: 0 5px 0 20px;border-bottom: 1px dotted white;}\n.nav_section ul li.noline {border-bottom: 0;}\n.nav_section ul li a {color: #fff;}\n.nav_section ul li a.selected {padding: 2px;background-color: #528036;}\n.nav_section ul li.first {border: none;}\n.content .title {margin: 50px 30px 20px 70px;}\n.content li {margin-bottom: 5px;}\n.contentBox {position: relative;overflow: hidden;border: 1px solid white;min-height: 200px;line-height: 25px;background: transparent url(img/contact-bg.png) repeat-x 0 0;}\n\n.zTreeInfo {display:none;width: 940px;position: absolute;}\n.zTreeInfo p {padding-bottom: 50px;}\n.zTreeInfo-left {float: left;width: 280px;height:300px;padding: 0 50px 60px 75px;background:url(img/zTreeIntroduction.jpg) no-repeat 30px 30px;}\n.zTreeInfo-right {position: relative;float: right;width: 475px;padding: 0 50px 60px 0;}\n.zTreeInfo-right li {font-size: 12px;list-style-type: disc;}\n\n.license {display:none;width: 940px;position: absolute;}\n\n.donateInfo {display:block;width: 940px;position: absolute;}\n\n.links {display:none;width: 940px;position: absolute;}\n.links .content {float: left;width: 160px;height:200px;padding: 0 10px 10px 2px;text-align: center;}\n.links .content.first {margin-left: 30px;}\n\n.contact {display:none;width: 940px;position: absolute;}\n.contact .myhome { position: absolute; top:10px; left:620px; width:300px; height:266px; background: transparent url(img/myhome.gif) scroll no-repeat 0 0;}\n\n.siteTag {position: absolute;left: -16px;top: 109px;z-index: 10;width: 65px;height: 46px;padding:0;margin:0 10px 0 0;\n\t\t vertical-align:middle;border:0 none;background: transparent url(img/siteTag.png) scroll no-repeat 0 0;}\n.siteTag.tag_zTreeInfo {background-position: 0 0}\n.siteTag.tag_license {background-position: 0 -46px}\n.siteTag.tag_donate {background-position: 0 -92px}\n.siteTag.tag_contact {background-position: 0 -138px}\n\n.apiContent {width: 940px;}\n.apiContent .right {float: right;padding-right: 100px;}\n.apiContent .left {float: left;padding-right: 20px;border-right: 1px dotted silver;}\n.api_setting {position: relative;margin:20px 0 20px 20px;}\n.api_function {position: relative;margin:20px 0 20px 30px;padding-right: 10px;}\n.api_content_title {text-align: center;font-weight: bold;}\n\n.demoContent {width: 940px;}\n.demoContent .right {float: right;padding: 20px;width: 600px;}\n.demoContent .left {float: left;padding: 20px;}\n.demoContent iframe {width:600px;min-height: 530px;}\n\n.faqContent {width: 940px;}\n.faqContent .right {float: right;padding: 20px;width: 600px;}\n.faqContent .left {float: left;padding: 20px;}\n.faqContent iframe {width:600px;min-height: 300px;}\n\n.baby_overlay_tmp {position: absolute;top:0; left:-5000px;display:block;visibility: hidden;width:640px;font-size:11px;}\n.baby_overlay_tmp .details {padding: 20px;}\n.baby_overlay {display:none;position:absolute;z-index:99;left:0; top:0;width:640px;color:#fff;font-size:11px;}\n.baby_overlay .content {width:100%; height:100px;overflow: hidden;background: transparent url(img/overlay_bg.png) scroll repeat 0 0;}\n.baby_overlay .details {padding:0 20px 20px 20px;}\n.baby_overlay .close {background-image:url(img/close.png);position:absolute; right:5px; top:5px;cursor:pointer;height:36px;width:36px;}\n.baby_overlay_arrow {background-image:url(img/overlay_arrow.png);background-position:0 0;position:absolute;height:40px;width:40px;left: -40px;}\n.baby_overlay_arrow.reverse {background-position:0 -40px;}\n\n/* Footer */\n.footer {position: relative;min-width: 1000px;font: 14px/24px arial, helvetica, sans-serif;}\n.footer ul {position:absolute;left: 0px;border:1px solid #393939;background:#262626;padding:12px 0px;line-height: 18px;display: none;list-style: none;}\n.footer ul li a {display:block;padding: 2px 15px;color: #9c9c9c;text-indent: 0;}\n.footer ul li a:hover {text-decoration:none;color: #fff;}\n.footer-logo {position:absolute;margin: 10px 0 0 30px;width:122px; height:24px;top:0; left:0;background: transparent url(img/footer-logo.png) no-repeat 0 0;}\n.footer_mii {position: absolute;right: 558px;top: 8px;z-index: 10;padding: 4px 0;}\n.footer_mii a {font-size:10px;color:#649140}\n.footer_mii a:hover {color:#B6D76F}\n.footer_siteMap {position: absolute;right: 358px;top: 8px;width: 155px;z-index: 10;padding: 4px 0;}\n.footer_siteMap .footer_siteMap_header {width:155px;text-indent: -9999px;background: transparent url(img/footer_siteMap.gif) no-repeat 0 0;}\n.footer_siteMap ul {top:-202px;width:180px;}\n.footer_siteMap:hover ul {left: 0}\n.footer_contact {position: absolute;right: 193px;top: 8px;width: 155px;z-index: 10;padding: 4px 0;}\n.footer_contact .footer_contact_header {width:155px;text-indent: -9999px;background: transparent url(img/footer_contact.gif) no-repeat 0px 0px;}\n.footer_contact ul {top:-113px;width:153px;}\n.footer_contact:hover ul {left: 0}\n.footer_download {position: absolute;right: 60px;top: 8px;width: 123px;z-index: 10;padding: 4px 0;}\n.footer_download .footer_download_header {width:123px;text-indent: -9999px;background: transparent url(img/footer_download.png) no-repeat 0px 0px;}\n.footer_download ul {top:-113px;width:140px;}\n.footer_download:hover ul {left: 0}\n\n/* button icon */\nbutton {vertical-align:middle;border:0 none;background: transparent no-repeat 0 0 scroll;}\n\n.shortcuts button.ico {width:24px; height:24px;padding:0; margin:0 10px 0 0;background-image:url(img/menuIcon.png)}\n.shortcuts button.home {background-position: 0 0}\n.shortcuts button.demo {background-position: 0 -24px}\n.shortcuts button.api {background-position: 0 -48px}\n.shortcuts button.faq {background-position: 0 -72px}\n.shortcuts button.donate {background-position: 0 -144px}\n.shortcuts button.download {background-position: 0 -96px}\n.shortcuts button.face {background-position: 0 -120px}\n.shortcuts button.cn {width:48px; height:24px;padding:0; margin:0 10px 0 0;background-image:url(img/chinese.png)}\n.shortcuts button.en {width:48px; height:24px;padding:0; margin:0 10px 0 0;background-image:url(img/english.png)}\n\n.content button.ico {width:24px; height:24px;padding:0; margin:0 10px 0 0;}\n\n.content button.ico16 {width:16px; height:16px;padding:0; margin:0 5px 0 0;background-image:url(\"img/apiMenu.png\");}\nbutton.z_core {margin-top: -4px;background-position:0 0;}\nbutton.z_check {margin-top: -4px;background-position:0 -16px;}\nbutton.z_edit {margin-top: -4px;background-position:0 -32px;}\nbutton.z_hide {margin-top: -4px;background-position:0 -64px;}\nbutton.z_search {margin-top: -4px;background-position:0 -48px;}\nbutton.searchPrev {margin-top: -4px;background-position:-16px 0;cursor:pointer}\nbutton.searchNext {margin-top: -4px;background-position:-16px -16px;cursor:pointer}\nbutton.searchPrev.disabled {margin-top: -4px;background-position:-16px -32px;cursor:auto}\nbutton.searchNext.disabled {margin-top: -4px;background-position:-16px -48px;cursor:auto}\ninput.search {margin:0;padding:2px 0; border:0;}\ninput.searchKey {width:150px;}\ninput.searchResult {margin-left:-3px;width:65px;text-align:right;background-color:white;color:#707070}\ninput.searchResult.noResult {background-color:#ff6666;color:black}\n.baby_overlay div.overlaySearch {text-align:right;padding-right:50px;padding-top:12px;}\n\n/* api overlay*/\n.apiDetail .topLine {border-top: 1px dashed #376B29;margin-top: 5px;padding-top: 5px;}\n.apiDetail .highlight_red {color:#A60000;}\n.apiDetail .highlight_green {color:#A7F43D;}\n.apiDetail h1, .apiDetail h2, .apiDetail h3, .apiDetail h4, .apiDetail h5, .apiDetail h6 {color: white;padding: 0;}\n.apiDetail h2 {color: #A7F43D;margin: 5px auto;padding: 5px;font-size: 20px;}\n.apiDetail h2 span {font-size: 14px;float: right;font-weight: normal;margin: 2px 20px 0 0;vertical-align: bottom;}\n.apiDetail h2 span.path {float: left;margin: 2px 0 0 0;vertical-align: bottom;}\n.apiDetail h3 {margin: 5px auto;padding: 5px;font-size: 14px;font-weight: normal;}\n.apiDetail h3 span.h3_info {margin-left: 20px;font-size: 12px;}\n.apiDetail h4 {margin: 0 auto;padding: 0 5px;font-size: 12px;font-weight: normal;line-height: 16px;}\n.apiDetail .desc h4 {color: black;}\n.apiDetail h4 b{width: 150px;display:inline-block;}\n.apiDetail h4 span{width: 230px;display:inline-block;}\n\n.apiDetail pre, .apiDetail .desc {background: #E8FCD6;color: black;margin: 10px;padding: 10px;display: block;}\n.apiDetail pre {word-wrap: break-word;}\n.apiDetail p{margin-left: 5px;padding: 0;}\n.apiDetail .longdesc {margin-top: 5px;}\n.apiDetail .longdesc p{font-size: 12px;line-height:1.5;margin:3px 0;}\n.apiDetail .longdesc b{font-size: 14px;}\n.apiDetail table {border-collapse:collapse;}\n.apiDetail table td {border:1px solid silver;text-align: center;vertical-align: middle;}\n.apiDetail table thead td {font-weight: bold}\n\n.apiDetail button {width:16px; height:16px; vertical-align:middle; border:0 none; cursor: pointer;\n\tbackground-color:transparent; background-repeat:no-repeat; background-attachment: scroll;\n\tbackground-image:url(\"zTreeStyle/img/zTreeStandard.png\");}\n\n.apiDetail button.chk {width:13px; height:13px; margin:0 3px 2px 0; cursor: auto}\n.apiDetail button.chk.checkbox_false_full {background-position:0 0}\n.apiDetail button.chk.checkbox_false_full_focus {background-position:0 -14px}\n.apiDetail button.chk.checkbox_false_part {background-position:0 -28px}\n.apiDetail button.chk.checkbox_false_part_focus {background-position:0 -42px}\n.apiDetail button.chk.checkbox_true_full {background-position:-14px 0}\n.apiDetail button.chk.checkbox_true_full_focus {background-position:-14px -14px}\n.apiDetail button.chk.checkbox_true_part {background-position:-14px -28px}\n.apiDetail button.chk.checkbox_true_part_focus {background-position:-14px -42px}\n.apiDetail button.chk.radio_false_full {background-position:-28px 0}\n.apiDetail button.chk.radio_false_full_focus {background-position:-28px -14px}\n.apiDetail button.chk.radio_false_part {background-position:-28px -28px}\n.apiDetail button.chk.radio_false_part_focus {background-position:-28px -42px}\n.apiDetail button.chk.radio_true_full {background-position:-42px 0}\n.apiDetail button.chk.radio_true_full_focus {background-position:-42px -14px}\n.apiDetail button.chk.radio_true_part {background-position:-42px -28px}\n.apiDetail button.chk.radio_true_part_focus {background-position:-42px -42px}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/apiCss/common_ie6.css",
    "content": "* html{\n/*\tbackground-image:url(about:blank);*/\n\tbackground-attachment:fixed;\n}\nhtml pre {word-wrap: break-word}\n.header {background-image: none;background-color: #F0F6E4;}\n\n.ieSuggest {display:block;}\n.shortcuts button.cn {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='apiCss/img/chinese.png');background-image: none;}\n.shortcuts button.en {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='apiCss/img/english.png');background-image: none;}\n\n.light-bulb {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='apiCss/img/lightbulb.png');background-image: none;}\n.contentBox {background-image: none;background-color: #F0F6E4;}\n.zTreeInfo {background-image: none;background-color: #F0F6E4;}\n\n.content button.ico16 {*background-image:url(\"img/apiMenu.gif\")}\n.siteTag {background-image: none;}\n.apiContent .right {float: right;padding-right: 50px;}\n\ndiv.baby_overlay {background-color: #3C6E31;background-image:none;color:#fff;}\ndiv.baby_overlay .close {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='apiCss/img/overlay_close_IE6.gif');background-image: none;}\n.baby_overlay_arrow {background-image:url(img/overlay_arrow.gif);}\n.apiDetail button {background-image:url(\"img/zTreeStandard.gif\")}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/apiCss/jquery.ztree.core-3.5.js",
    "content": "/*\n * JQuery zTree core v3.5.18\n * http://zTree.me/\n *\n * Copyright (c) 2010 Hunter.z\n *\n * Licensed same as jquery - MIT License\n * http://www.opensource.org/licenses/mit-license.php\n *\n * email: hunter.z@263.net\n * Date: 2015-05-25\n */\n(function(p){var G,H,I,J,K,L,r={},u={},v={},M={treeId:\"\",treeObj:null,view:{addDiyDom:null,autoCancelSelected:!0,dblClickExpand:!0,expandSpeed:\"fast\",fontCss:{},nameIsHTML:!1,selectedMulti:!0,showIcon:!0,showLine:!0,showTitle:!0,txtSelectedEnable:!1},data:{key:{children:\"children\",name:\"name\",title:\"\",url:\"url\"},simpleData:{enable:!1,idKey:\"id\",pIdKey:\"pId\",rootPId:null},keep:{parent:!1,leaf:!1}},async:{enable:!1,contentType:\"application/x-www-form-urlencoded\",type:\"post\",dataType:\"text\",url:\"\",autoParam:[],\notherParam:[],dataFilter:null},callback:{beforeAsync:null,beforeClick:null,beforeDblClick:null,beforeRightClick:null,beforeMouseDown:null,beforeMouseUp:null,beforeExpand:null,beforeCollapse:null,beforeRemove:null,onAsyncError:null,onAsyncSuccess:null,onNodeCreated:null,onClick:null,onDblClick:null,onRightClick:null,onMouseDown:null,onMouseUp:null,onExpand:null,onCollapse:null,onRemove:null}},w=[function(b){var a=b.treeObj,c=e.event;a.bind(c.NODECREATED,function(a,c,g){j.apply(b.callback.onNodeCreated,\n[a,c,g])});a.bind(c.CLICK,function(a,c,g,l,h){j.apply(b.callback.onClick,[c,g,l,h])});a.bind(c.EXPAND,function(a,c,g){j.apply(b.callback.onExpand,[a,c,g])});a.bind(c.COLLAPSE,function(a,c,g){j.apply(b.callback.onCollapse,[a,c,g])});a.bind(c.ASYNC_SUCCESS,function(a,c,g,l){j.apply(b.callback.onAsyncSuccess,[a,c,g,l])});a.bind(c.ASYNC_ERROR,function(a,c,g,l,h,e){j.apply(b.callback.onAsyncError,[a,c,g,l,h,e])});a.bind(c.REMOVE,function(a,c,g){j.apply(b.callback.onRemove,[a,c,g])});a.bind(c.SELECTED,\nfunction(a,c,g,l){j.apply(b.callback.onSelected,[c,g,l])});a.bind(c.UNSELECTED,function(a,c,g,l){j.apply(b.callback.onUnSelected,[c,g,l])})}],x=[function(b){var a=e.event;b.treeObj.unbind(a.NODECREATED).unbind(a.CLICK).unbind(a.EXPAND).unbind(a.COLLAPSE).unbind(a.ASYNC_SUCCESS).unbind(a.ASYNC_ERROR).unbind(a.REMOVE).unbind(a.SELECTED).unbind(a.UNSELECTED)}],y=[function(b){var a=h.getCache(b);a||(a={},h.setCache(b,a));a.nodes=[];a.doms=[]}],z=[function(b,a,c,d,f,g){if(c){var l=h.getRoot(b),e=b.data.key.children;\nc.level=a;c.tId=b.treeId+\"_\"+ ++l.zId;c.parentTId=d?d.tId:null;c.open=typeof c.open==\"string\"?j.eqs(c.open,\"true\"):!!c.open;c[e]&&c[e].length>0?(c.isParent=!0,c.zAsync=!0):(c.isParent=typeof c.isParent==\"string\"?j.eqs(c.isParent,\"true\"):!!c.isParent,c.open=c.isParent&&!b.async.enable?c.open:!1,c.zAsync=!c.isParent);c.isFirstNode=f;c.isLastNode=g;c.getParentNode=function(){return h.getNodeCache(b,c.parentTId)};c.getPreNode=function(){return h.getPreNode(b,c)};c.getNextNode=function(){return h.getNextNode(b,\nc)};c.isAjaxing=!1;h.fixPIdKeyValue(b,c)}}],s=[function(b){var a=b.target,c=h.getSetting(b.data.treeId),d=\"\",f=null,g=\"\",l=\"\",i=null,o=null,k=null;if(j.eqs(b.type,\"mousedown\"))l=\"mousedown\";else if(j.eqs(b.type,\"mouseup\"))l=\"mouseup\";else if(j.eqs(b.type,\"contextmenu\"))l=\"contextmenu\";else if(j.eqs(b.type,\"click\"))if(j.eqs(a.tagName,\"span\")&&a.getAttribute(\"treeNode\"+e.id.SWITCH)!==null)d=j.getNodeMainDom(a).id,g=\"switchNode\";else{if(k=j.getMDom(c,a,[{tagName:\"a\",attrName:\"treeNode\"+e.id.A}]))d=j.getNodeMainDom(k).id,\ng=\"clickNode\"}else if(j.eqs(b.type,\"dblclick\")&&(l=\"dblclick\",k=j.getMDom(c,a,[{tagName:\"a\",attrName:\"treeNode\"+e.id.A}])))d=j.getNodeMainDom(k).id,g=\"switchNode\";if(l.length>0&&d.length==0&&(k=j.getMDom(c,a,[{tagName:\"a\",attrName:\"treeNode\"+e.id.A}])))d=j.getNodeMainDom(k).id;if(d.length>0)switch(f=h.getNodeCache(c,d),g){case \"switchNode\":f.isParent?j.eqs(b.type,\"click\")||j.eqs(b.type,\"dblclick\")&&j.apply(c.view.dblClickExpand,[c.treeId,f],c.view.dblClickExpand)?i=G:g=\"\":g=\"\";break;case \"clickNode\":i=\nH}switch(l){case \"mousedown\":o=I;break;case \"mouseup\":o=J;break;case \"dblclick\":o=K;break;case \"contextmenu\":o=L}return{stop:!1,node:f,nodeEventType:g,nodeEventCallback:i,treeEventType:l,treeEventCallback:o}}],A=[function(b){var a=h.getRoot(b);a||(a={},h.setRoot(b,a));a[b.data.key.children]=[];a.expandTriggerFlag=!1;a.curSelectedList=[];a.noSelection=!0;a.createdNodes=[];a.zId=0;a._ver=(new Date).getTime()}],B=[],C=[],D=[],E=[],F=[],h={addNodeCache:function(b,a){h.getCache(b).nodes[h.getNodeCacheId(a.tId)]=\na},getNodeCacheId:function(b){return b.substring(b.lastIndexOf(\"_\")+1)},addAfterA:function(b){C.push(b)},addBeforeA:function(b){B.push(b)},addInnerAfterA:function(b){E.push(b)},addInnerBeforeA:function(b){D.push(b)},addInitBind:function(b){w.push(b)},addInitUnBind:function(b){x.push(b)},addInitCache:function(b){y.push(b)},addInitNode:function(b){z.push(b)},addInitProxy:function(b,a){a?s.splice(0,0,b):s.push(b)},addInitRoot:function(b){A.push(b)},addNodesData:function(b,a,c){var d=b.data.key.children;\na[d]||(a[d]=[]);if(a[d].length>0)a[d][a[d].length-1].isLastNode=!1,i.setNodeLineIcos(b,a[d][a[d].length-1]);a.isParent=!0;a[d]=a[d].concat(c)},addSelectedNode:function(b,a){var c=h.getRoot(b);h.isSelectedNode(b,a)||c.curSelectedList.push(a)},addCreatedNode:function(b,a){(b.callback.onNodeCreated||b.view.addDiyDom)&&h.getRoot(b).createdNodes.push(a)},addZTreeTools:function(b){F.push(b)},exSetting:function(b){p.extend(!0,M,b)},fixPIdKeyValue:function(b,a){b.data.simpleData.enable&&(a[b.data.simpleData.pIdKey]=\na.parentTId?a.getParentNode()[b.data.simpleData.idKey]:b.data.simpleData.rootPId)},getAfterA:function(b,a,c){for(var d=0,f=C.length;d<f;d++)C[d].apply(this,arguments)},getBeforeA:function(b,a,c){for(var d=0,f=B.length;d<f;d++)B[d].apply(this,arguments)},getInnerAfterA:function(b,a,c){for(var d=0,f=E.length;d<f;d++)E[d].apply(this,arguments)},getInnerBeforeA:function(b,a,c){for(var d=0,f=D.length;d<f;d++)D[d].apply(this,arguments)},getCache:function(b){return v[b.treeId]},getNextNode:function(b,a){if(!a)return null;\nfor(var c=b.data.key.children,d=a.parentTId?a.getParentNode():h.getRoot(b),f=0,g=d[c].length-1;f<=g;f++)if(d[c][f]===a)return f==g?null:d[c][f+1];return null},getNodeByParam:function(b,a,c,d){if(!a||!c)return null;for(var f=b.data.key.children,g=0,l=a.length;g<l;g++){if(a[g][c]==d)return a[g];var e=h.getNodeByParam(b,a[g][f],c,d);if(e)return e}return null},getNodeCache:function(b,a){if(!a)return null;var c=v[b.treeId].nodes[h.getNodeCacheId(a)];return c?c:null},getNodeName:function(b,a){return\"\"+\na[b.data.key.name]},getNodeTitle:function(b,a){return\"\"+a[b.data.key.title===\"\"?b.data.key.name:b.data.key.title]},getNodes:function(b){return h.getRoot(b)[b.data.key.children]},getNodesByParam:function(b,a,c,d){if(!a||!c)return[];for(var f=b.data.key.children,g=[],l=0,e=a.length;l<e;l++)a[l][c]==d&&g.push(a[l]),g=g.concat(h.getNodesByParam(b,a[l][f],c,d));return g},getNodesByParamFuzzy:function(b,a,c,d){if(!a||!c)return[];for(var f=b.data.key.children,g=[],d=d.toLowerCase(),l=0,e=a.length;l<e;l++)typeof a[l][c]==\n\"string\"&&a[l][c].toLowerCase().indexOf(d)>-1&&g.push(a[l]),g=g.concat(h.getNodesByParamFuzzy(b,a[l][f],c,d));return g},getNodesByFilter:function(b,a,c,d,f){if(!a)return d?null:[];for(var g=b.data.key.children,e=d?null:[],i=0,o=a.length;i<o;i++){if(j.apply(c,[a[i],f],!1)){if(d)return a[i];e.push(a[i])}var k=h.getNodesByFilter(b,a[i][g],c,d,f);if(d&&k)return k;e=d?k:e.concat(k)}return e},getPreNode:function(b,a){if(!a)return null;for(var c=b.data.key.children,d=a.parentTId?a.getParentNode():h.getRoot(b),\nf=0,g=d[c].length;f<g;f++)if(d[c][f]===a)return f==0?null:d[c][f-1];return null},getRoot:function(b){return b?u[b.treeId]:null},getRoots:function(){return u},getSetting:function(b){return r[b]},getSettings:function(){return r},getZTreeTools:function(b){return(b=this.getRoot(this.getSetting(b)))?b.treeTools:null},initCache:function(b){for(var a=0,c=y.length;a<c;a++)y[a].apply(this,arguments)},initNode:function(b,a,c,d,f,g){for(var e=0,h=z.length;e<h;e++)z[e].apply(this,arguments)},initRoot:function(b){for(var a=\n0,c=A.length;a<c;a++)A[a].apply(this,arguments)},isSelectedNode:function(b,a){for(var c=h.getRoot(b),d=0,f=c.curSelectedList.length;d<f;d++)if(a===c.curSelectedList[d])return!0;return!1},removeNodeCache:function(b,a){var c=b.data.key.children;if(a[c])for(var d=0,f=a[c].length;d<f;d++)arguments.callee(b,a[c][d]);h.getCache(b).nodes[h.getNodeCacheId(a.tId)]=null},removeSelectedNode:function(b,a){for(var c=h.getRoot(b),d=0,f=c.curSelectedList.length;d<f;d++)if(a===c.curSelectedList[d]||!h.getNodeCache(b,\nc.curSelectedList[d].tId))c.curSelectedList.splice(d,1),d--,f--},setCache:function(b,a){v[b.treeId]=a},setRoot:function(b,a){u[b.treeId]=a},setZTreeTools:function(b,a){for(var c=0,d=F.length;c<d;c++)F[c].apply(this,arguments)},transformToArrayFormat:function(b,a){if(!a)return[];var c=b.data.key.children,d=[];if(j.isArray(a))for(var f=0,g=a.length;f<g;f++)d.push(a[f]),a[f][c]&&(d=d.concat(h.transformToArrayFormat(b,a[f][c])));else d.push(a),a[c]&&(d=d.concat(h.transformToArrayFormat(b,a[c])));return d},\ntransformTozTreeFormat:function(b,a){var c,d,f=b.data.simpleData.idKey,g=b.data.simpleData.pIdKey,e=b.data.key.children;if(!f||f==\"\"||!a)return[];if(j.isArray(a)){var h=[],i=[];for(c=0,d=a.length;c<d;c++)i[a[c][f]]=a[c];for(c=0,d=a.length;c<d;c++)i[a[c][g]]&&a[c][f]!=a[c][g]?(i[a[c][g]][e]||(i[a[c][g]][e]=[]),i[a[c][g]][e].push(a[c])):h.push(a[c]);return h}else return[a]}},m={bindEvent:function(b){for(var a=0,c=w.length;a<c;a++)w[a].apply(this,arguments)},unbindEvent:function(b){for(var a=0,c=x.length;a<\nc;a++)x[a].apply(this,arguments)},bindTree:function(b){var a={treeId:b.treeId},c=b.treeObj;b.view.txtSelectedEnable||c.bind(\"selectstart\",function(a){a=a.originalEvent.srcElement.nodeName.toLowerCase();return a===\"input\"||a===\"textarea\"}).css({\"-moz-user-select\":\"-moz-none\"});c.bind(\"click\",a,m.proxy);c.bind(\"dblclick\",a,m.proxy);c.bind(\"mouseover\",a,m.proxy);c.bind(\"mouseout\",a,m.proxy);c.bind(\"mousedown\",a,m.proxy);c.bind(\"mouseup\",a,m.proxy);c.bind(\"contextmenu\",a,m.proxy)},unbindTree:function(b){b.treeObj.unbind(\"click\",\nm.proxy).unbind(\"dblclick\",m.proxy).unbind(\"mouseover\",m.proxy).unbind(\"mouseout\",m.proxy).unbind(\"mousedown\",m.proxy).unbind(\"mouseup\",m.proxy).unbind(\"contextmenu\",m.proxy)},doProxy:function(b){for(var a=[],c=0,d=s.length;c<d;c++){var f=s[c].apply(this,arguments);a.push(f);if(f.stop)break}return a},proxy:function(b){var a=h.getSetting(b.data.treeId);if(!j.uCanDo(a,b))return!0;for(var a=m.doProxy(b),c=!0,d=0,f=a.length;d<f;d++){var g=a[d];g.nodeEventCallback&&(c=g.nodeEventCallback.apply(g,[b,g.node])&&\nc);g.treeEventCallback&&(c=g.treeEventCallback.apply(g,[b,g.node])&&c)}return c}};G=function(b,a){var c=h.getSetting(b.data.treeId);if(a.open){if(j.apply(c.callback.beforeCollapse,[c.treeId,a],!0)==!1)return!0}else if(j.apply(c.callback.beforeExpand,[c.treeId,a],!0)==!1)return!0;h.getRoot(c).expandTriggerFlag=!0;i.switchNode(c,a);return!0};H=function(b,a){var c=h.getSetting(b.data.treeId),d=c.view.autoCancelSelected&&(b.ctrlKey||b.metaKey)&&h.isSelectedNode(c,a)?0:c.view.autoCancelSelected&&(b.ctrlKey||\nb.metaKey)&&c.view.selectedMulti?2:1;if(j.apply(c.callback.beforeClick,[c.treeId,a,d],!0)==!1)return!0;d===0?i.cancelPreSelectedNode(c,a):i.selectNode(c,a,d===2);c.treeObj.trigger(e.event.CLICK,[b,c.treeId,a,d]);return!0};I=function(b,a){var c=h.getSetting(b.data.treeId);j.apply(c.callback.beforeMouseDown,[c.treeId,a],!0)&&j.apply(c.callback.onMouseDown,[b,c.treeId,a]);return!0};J=function(b,a){var c=h.getSetting(b.data.treeId);j.apply(c.callback.beforeMouseUp,[c.treeId,a],!0)&&j.apply(c.callback.onMouseUp,\n[b,c.treeId,a]);return!0};K=function(b,a){var c=h.getSetting(b.data.treeId);j.apply(c.callback.beforeDblClick,[c.treeId,a],!0)&&j.apply(c.callback.onDblClick,[b,c.treeId,a]);return!0};L=function(b,a){var c=h.getSetting(b.data.treeId);j.apply(c.callback.beforeRightClick,[c.treeId,a],!0)&&j.apply(c.callback.onRightClick,[b,c.treeId,a]);return typeof c.callback.onRightClick!=\"function\"};var j={apply:function(b,a,c){return typeof b==\"function\"?b.apply(N,a?a:[]):c},canAsync:function(b,a){var c=b.data.key.children;\nreturn b.async.enable&&a&&a.isParent&&!(a.zAsync||a[c]&&a[c].length>0)},clone:function(b){if(b===null)return null;var a=j.isArray(b)?[]:{},c;for(c in b)a[c]=b[c]instanceof Date?new Date(b[c].getTime()):typeof b[c]===\"object\"?arguments.callee(b[c]):b[c];return a},eqs:function(b,a){return b.toLowerCase()===a.toLowerCase()},isArray:function(b){return Object.prototype.toString.apply(b)===\"[object Array]\"},$:function(b,a,c){a&&typeof a!=\"string\"&&(c=a,a=\"\");return typeof b==\"string\"?p(b,c?c.treeObj.get(0).ownerDocument:\nnull):p(\"#\"+b.tId+a,c?c.treeObj:null)},getMDom:function(b,a,c){if(!a)return null;for(;a&&a.id!==b.treeId;){for(var d=0,f=c.length;a.tagName&&d<f;d++)if(j.eqs(a.tagName,c[d].tagName)&&a.getAttribute(c[d].attrName)!==null)return a;a=a.parentNode}return null},getNodeMainDom:function(b){return p(b).parent(\"li\").get(0)||p(b).parentsUntil(\"li\").parent().get(0)},isChildOrSelf:function(b,a){return p(b).closest(\"#\"+a).length>0},uCanDo:function(){return!0}},i={addNodes:function(b,a,c,d){if(!b.data.keep.leaf||\n!a||a.isParent)if(j.isArray(c)||(c=[c]),b.data.simpleData.enable&&(c=h.transformTozTreeFormat(b,c)),a){var f=k(a,e.id.SWITCH,b),g=k(a,e.id.ICON,b),l=k(a,e.id.UL,b);if(!a.open)i.replaceSwitchClass(a,f,e.folder.CLOSE),i.replaceIcoClass(a,g,e.folder.CLOSE),a.open=!1,l.css({display:\"none\"});h.addNodesData(b,a,c);i.createNodes(b,a.level+1,c,a);d||i.expandCollapseParentNode(b,a,!0)}else h.addNodesData(b,h.getRoot(b),c),i.createNodes(b,0,c,null)},appendNodes:function(b,a,c,d,f,g){if(!c)return[];for(var e=\n[],j=b.data.key.children,k=0,m=c.length;k<m;k++){var n=c[k];if(f){var t=(d?d:h.getRoot(b))[j].length==c.length&&k==0;h.initNode(b,a,n,d,t,k==c.length-1,g);h.addNodeCache(b,n)}t=[];n[j]&&n[j].length>0&&(t=i.appendNodes(b,a+1,n[j],n,f,g&&n.open));g&&(i.makeDOMNodeMainBefore(e,b,n),i.makeDOMNodeLine(e,b,n),h.getBeforeA(b,n,e),i.makeDOMNodeNameBefore(e,b,n),h.getInnerBeforeA(b,n,e),i.makeDOMNodeIcon(e,b,n),h.getInnerAfterA(b,n,e),i.makeDOMNodeNameAfter(e,b,n),h.getAfterA(b,n,e),n.isParent&&n.open&&i.makeUlHtml(b,\nn,e,t.join(\"\")),i.makeDOMNodeMainAfter(e,b,n),h.addCreatedNode(b,n))}return e},appendParentULDom:function(b,a){var c=[],d=k(a,b);!d.get(0)&&a.parentTId&&(i.appendParentULDom(b,a.getParentNode()),d=k(a,b));var f=k(a,e.id.UL,b);f.get(0)&&f.remove();f=i.appendNodes(b,a.level+1,a[b.data.key.children],a,!1,!0);i.makeUlHtml(b,a,c,f.join(\"\"));d.append(c.join(\"\"))},asyncNode:function(b,a,c,d){var f,g;if(a&&!a.isParent)return j.apply(d),!1;else if(a&&a.isAjaxing)return!1;else if(j.apply(b.callback.beforeAsync,\n[b.treeId,a],!0)==!1)return j.apply(d),!1;if(a)a.isAjaxing=!0,k(a,e.id.ICON,b).attr({style:\"\",\"class\":e.className.BUTTON+\" \"+e.className.ICO_LOADING});var l={};for(f=0,g=b.async.autoParam.length;a&&f<g;f++){var q=b.async.autoParam[f].split(\"=\"),o=q;q.length>1&&(o=q[1],q=q[0]);l[o]=a[q]}if(j.isArray(b.async.otherParam))for(f=0,g=b.async.otherParam.length;f<g;f+=2)l[b.async.otherParam[f]]=b.async.otherParam[f+1];else for(var m in b.async.otherParam)l[m]=b.async.otherParam[m];var n=h.getRoot(b)._ver;\np.ajax({contentType:b.async.contentType,cache:!1,type:b.async.type,url:j.apply(b.async.url,[b.treeId,a],b.async.url),data:l,dataType:b.async.dataType,success:function(f){if(n==h.getRoot(b)._ver){var g=[];try{g=!f||f.length==0?[]:typeof f==\"string\"?eval(\"(\"+f+\")\"):f}catch(l){g=f}if(a)a.isAjaxing=null,a.zAsync=!0;i.setNodeLineIcos(b,a);g&&g!==\"\"?(g=j.apply(b.async.dataFilter,[b.treeId,a,g],g),i.addNodes(b,a,g?j.clone(g):[],!!c)):i.addNodes(b,a,[],!!c);b.treeObj.trigger(e.event.ASYNC_SUCCESS,[b.treeId,\na,f]);j.apply(d)}},error:function(c,d,f){if(n==h.getRoot(b)._ver){if(a)a.isAjaxing=null;i.setNodeLineIcos(b,a);b.treeObj.trigger(e.event.ASYNC_ERROR,[b.treeId,a,c,d,f])}}});return!0},cancelPreSelectedNode:function(b,a,c){var d=h.getRoot(b).curSelectedList,f,g;for(f=d.length-1;f>=0;f--)if(g=d[f],a===g||!a&&(!c||c!==g))if(k(g,e.id.A,b).removeClass(e.node.CURSELECTED),a){h.removeSelectedNode(b,a);b.treeObj.trigger(e.event.UNSELECTED,[m,b.treeId,g]);break}else d.splice(f,1),b.treeObj.trigger(e.event.UNSELECTED,\n[m,b.treeId,g])},createNodeCallback:function(b){if(b.callback.onNodeCreated||b.view.addDiyDom)for(var a=h.getRoot(b);a.createdNodes.length>0;){var c=a.createdNodes.shift();j.apply(b.view.addDiyDom,[b.treeId,c]);b.callback.onNodeCreated&&b.treeObj.trigger(e.event.NODECREATED,[b.treeId,c])}},createNodes:function(b,a,c,d){if(c&&c.length!=0){var f=h.getRoot(b),g=b.data.key.children,g=!d||d.open||!!k(d[g][0],b).get(0);f.createdNodes=[];a=i.appendNodes(b,a,c,d,!0,g);d?(d=k(d,e.id.UL,b),d.get(0)&&d.append(a.join(\"\"))):\nb.treeObj.append(a.join(\"\"));i.createNodeCallback(b)}},destroy:function(b){b&&(h.initCache(b),h.initRoot(b),m.unbindTree(b),m.unbindEvent(b),b.treeObj.empty(),delete r[b.treeId])},expandCollapseNode:function(b,a,c,d,f){var g=h.getRoot(b),l=b.data.key.children;if(a){if(g.expandTriggerFlag){var q=f,f=function(){q&&q();a.open?b.treeObj.trigger(e.event.EXPAND,[b.treeId,a]):b.treeObj.trigger(e.event.COLLAPSE,[b.treeId,a])};g.expandTriggerFlag=!1}if(!a.open&&a.isParent&&(!k(a,e.id.UL,b).get(0)||a[l]&&a[l].length>\n0&&!k(a[l][0],b).get(0)))i.appendParentULDom(b,a),i.createNodeCallback(b);if(a.open==c)j.apply(f,[]);else{var c=k(a,e.id.UL,b),g=k(a,e.id.SWITCH,b),o=k(a,e.id.ICON,b);a.isParent?(a.open=!a.open,a.iconOpen&&a.iconClose&&o.attr(\"style\",i.makeNodeIcoStyle(b,a)),a.open?(i.replaceSwitchClass(a,g,e.folder.OPEN),i.replaceIcoClass(a,o,e.folder.OPEN),d==!1||b.view.expandSpeed==\"\"?(c.show(),j.apply(f,[])):a[l]&&a[l].length>0?c.slideDown(b.view.expandSpeed,f):(c.show(),j.apply(f,[]))):(i.replaceSwitchClass(a,\ng,e.folder.CLOSE),i.replaceIcoClass(a,o,e.folder.CLOSE),d==!1||b.view.expandSpeed==\"\"||!(a[l]&&a[l].length>0)?(c.hide(),j.apply(f,[])):c.slideUp(b.view.expandSpeed,f))):j.apply(f,[])}}else j.apply(f,[])},expandCollapseParentNode:function(b,a,c,d,f){a&&(a.parentTId?(i.expandCollapseNode(b,a,c,d),a.parentTId&&i.expandCollapseParentNode(b,a.getParentNode(),c,d,f)):i.expandCollapseNode(b,a,c,d,f))},expandCollapseSonNode:function(b,a,c,d,f){var g=h.getRoot(b),e=b.data.key.children,g=a?a[e]:g[e],e=a?!1:\nd,j=h.getRoot(b).expandTriggerFlag;h.getRoot(b).expandTriggerFlag=!1;if(g)for(var k=0,m=g.length;k<m;k++)g[k]&&i.expandCollapseSonNode(b,g[k],c,e);h.getRoot(b).expandTriggerFlag=j;i.expandCollapseNode(b,a,c,d,f)},isSelectedNode:function(b,a){if(!a)return!1;var c=h.getRoot(b).curSelectedList,d;for(d=c.length-1;d>=0;d--)if(a===c[d])return!0;return!1},makeDOMNodeIcon:function(b,a,c){var d=h.getNodeName(a,c),d=a.view.nameIsHTML?d:d.replace(/&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\");b.push(\"<span id='\",\nc.tId,e.id.ICON,\"' title='' treeNode\",e.id.ICON,\" class='\",i.makeNodeIcoClass(a,c),\"' style='\",i.makeNodeIcoStyle(a,c),\"'></span><span id='\",c.tId,e.id.SPAN,\"'>\",d,\"</span>\")},makeDOMNodeLine:function(b,a,c){b.push(\"<span id='\",c.tId,e.id.SWITCH,\"' title='' class='\",i.makeNodeLineClass(a,c),\"' treeNode\",e.id.SWITCH,\"></span>\")},makeDOMNodeMainAfter:function(b){b.push(\"</li>\")},makeDOMNodeMainBefore:function(b,a,c){b.push(\"<li id='\",c.tId,\"' class='\",e.className.LEVEL,c.level,\"' tabindex='0' hidefocus='true' treenode>\")},\nmakeDOMNodeNameAfter:function(b){b.push(\"</a>\")},makeDOMNodeNameBefore:function(b,a,c){var d=h.getNodeTitle(a,c),f=i.makeNodeUrl(a,c),g=i.makeNodeFontCss(a,c),l=[],k;for(k in g)l.push(k,\":\",g[k],\";\");b.push(\"<a id='\",c.tId,e.id.A,\"' class='\",e.className.LEVEL,c.level,\"' treeNode\",e.id.A,' onclick=\"',c.click||\"\",'\" ',f!=null&&f.length>0?\"href='\"+f+\"'\":\"\",\" target='\",i.makeNodeTarget(c),\"' style='\",l.join(\"\"),\"'\");j.apply(a.view.showTitle,[a.treeId,c],a.view.showTitle)&&d&&b.push(\"title='\",d.replace(/'/g,\n\"&#39;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\"),\"'\");b.push(\">\")},makeNodeFontCss:function(b,a){var c=j.apply(b.view.fontCss,[b.treeId,a],b.view.fontCss);return c&&typeof c!=\"function\"?c:{}},makeNodeIcoClass:function(b,a){var c=[\"ico\"];a.isAjaxing||(c[0]=(a.iconSkin?a.iconSkin+\"_\":\"\")+c[0],a.isParent?c.push(a.open?e.folder.OPEN:e.folder.CLOSE):c.push(e.folder.DOCU));return e.className.BUTTON+\" \"+c.join(\"_\")},makeNodeIcoStyle:function(b,a){var c=[];if(!a.isAjaxing){var d=a.isParent&&a.iconOpen&&\na.iconClose?a.open?a.iconOpen:a.iconClose:a.icon;d&&c.push(\"background:url(\",d,\") 0 0 no-repeat;\");(b.view.showIcon==!1||!j.apply(b.view.showIcon,[b.treeId,a],!0))&&c.push(\"width:0px;height:0px;\")}return c.join(\"\")},makeNodeLineClass:function(b,a){var c=[];b.view.showLine?a.level==0&&a.isFirstNode&&a.isLastNode?c.push(e.line.ROOT):a.level==0&&a.isFirstNode?c.push(e.line.ROOTS):a.isLastNode?c.push(e.line.BOTTOM):c.push(e.line.CENTER):c.push(e.line.NOLINE);a.isParent?c.push(a.open?e.folder.OPEN:e.folder.CLOSE):\nc.push(e.folder.DOCU);return i.makeNodeLineClassEx(a)+c.join(\"_\")},makeNodeLineClassEx:function(b){return e.className.BUTTON+\" \"+e.className.LEVEL+b.level+\" \"+e.className.SWITCH+\" \"},makeNodeTarget:function(b){return b.target||\"_blank\"},makeNodeUrl:function(b,a){var c=b.data.key.url;return a[c]?a[c]:null},makeUlHtml:function(b,a,c,d){c.push(\"<ul id='\",a.tId,e.id.UL,\"' class='\",e.className.LEVEL,a.level,\" \",i.makeUlLineClass(b,a),\"' style='display:\",a.open?\"block\":\"none\",\"'>\");c.push(d);c.push(\"</ul>\")},\nmakeUlLineClass:function(b,a){return b.view.showLine&&!a.isLastNode?e.line.LINE:\"\"},removeChildNodes:function(b,a){if(a){var c=b.data.key.children,d=a[c];if(d){for(var f=0,g=d.length;f<g;f++)h.removeNodeCache(b,d[f]);h.removeSelectedNode(b);delete a[c];b.data.keep.parent?k(a,e.id.UL,b).empty():(a.isParent=!1,a.open=!1,c=k(a,e.id.SWITCH,b),d=k(a,e.id.ICON,b),i.replaceSwitchClass(a,c,e.folder.DOCU),i.replaceIcoClass(a,d,e.folder.DOCU),k(a,e.id.UL,b).remove())}}},setFirstNode:function(b,a){var c=b.data.key.children;\nif(a[c].length>0)a[c][0].isFirstNode=!0},setLastNode:function(b,a){var c=b.data.key.children,d=a[c].length;if(d>0)a[c][d-1].isLastNode=!0},removeNode:function(b,a){var c=h.getRoot(b),d=b.data.key.children,f=a.parentTId?a.getParentNode():c;a.isFirstNode=!1;a.isLastNode=!1;a.getPreNode=function(){return null};a.getNextNode=function(){return null};if(h.getNodeCache(b,a.tId)){k(a,b).remove();h.removeNodeCache(b,a);h.removeSelectedNode(b,a);for(var g=0,l=f[d].length;g<l;g++)if(f[d][g].tId==a.tId){f[d].splice(g,\n1);break}i.setFirstNode(b,f);i.setLastNode(b,f);var j,g=f[d].length;if(!b.data.keep.parent&&g==0)f.isParent=!1,f.open=!1,g=k(f,e.id.UL,b),l=k(f,e.id.SWITCH,b),j=k(f,e.id.ICON,b),i.replaceSwitchClass(f,l,e.folder.DOCU),i.replaceIcoClass(f,j,e.folder.DOCU),g.css(\"display\",\"none\");else if(b.view.showLine&&g>0){var o=f[d][g-1],g=k(o,e.id.UL,b),l=k(o,e.id.SWITCH,b);j=k(o,e.id.ICON,b);f==c?f[d].length==1?i.replaceSwitchClass(o,l,e.line.ROOT):(c=k(f[d][0],e.id.SWITCH,b),i.replaceSwitchClass(f[d][0],c,e.line.ROOTS),\ni.replaceSwitchClass(o,l,e.line.BOTTOM)):i.replaceSwitchClass(o,l,e.line.BOTTOM);g.removeClass(e.line.LINE)}}},replaceIcoClass:function(b,a,c){if(a&&!b.isAjaxing&&(b=a.attr(\"class\"),b!=void 0)){b=b.split(\"_\");switch(c){case e.folder.OPEN:case e.folder.CLOSE:case e.folder.DOCU:b[b.length-1]=c}a.attr(\"class\",b.join(\"_\"))}},replaceSwitchClass:function(b,a,c){if(a){var d=a.attr(\"class\");if(d!=void 0){d=d.split(\"_\");switch(c){case e.line.ROOT:case e.line.ROOTS:case e.line.CENTER:case e.line.BOTTOM:case e.line.NOLINE:d[0]=\ni.makeNodeLineClassEx(b)+c;break;case e.folder.OPEN:case e.folder.CLOSE:case e.folder.DOCU:d[1]=c}a.attr(\"class\",d.join(\"_\"));c!==e.folder.DOCU?a.removeAttr(\"disabled\"):a.attr(\"disabled\",\"disabled\")}}},selectNode:function(b,a,c){c||i.cancelPreSelectedNode(b,null,a);k(a,e.id.A,b).addClass(e.node.CURSELECTED);h.addSelectedNode(b,a);b.treeObj.trigger(e.event.SELECTED,[m,b.treeId,a])},setNodeFontCss:function(b,a){var c=k(a,e.id.A,b),d=i.makeNodeFontCss(b,a);d&&c.css(d)},setNodeLineIcos:function(b,a){if(a){var c=\nk(a,e.id.SWITCH,b),d=k(a,e.id.UL,b),f=k(a,e.id.ICON,b),g=i.makeUlLineClass(b,a);g.length==0?d.removeClass(e.line.LINE):d.addClass(g);c.attr(\"class\",i.makeNodeLineClass(b,a));a.isParent?c.removeAttr(\"disabled\"):c.attr(\"disabled\",\"disabled\");f.removeAttr(\"style\");f.attr(\"style\",i.makeNodeIcoStyle(b,a));f.attr(\"class\",i.makeNodeIcoClass(b,a))}},setNodeName:function(b,a){var c=h.getNodeTitle(b,a),d=k(a,e.id.SPAN,b);d.empty();b.view.nameIsHTML?d.html(h.getNodeName(b,a)):d.text(h.getNodeName(b,a));j.apply(b.view.showTitle,\n[b.treeId,a],b.view.showTitle)&&k(a,e.id.A,b).attr(\"title\",!c?\"\":c)},setNodeTarget:function(b,a){k(a,e.id.A,b).attr(\"target\",i.makeNodeTarget(a))},setNodeUrl:function(b,a){var c=k(a,e.id.A,b),d=i.makeNodeUrl(b,a);d==null||d.length==0?c.removeAttr(\"href\"):c.attr(\"href\",d)},switchNode:function(b,a){a.open||!j.canAsync(b,a)?i.expandCollapseNode(b,a,!a.open):b.async.enable?i.asyncNode(b,a)||i.expandCollapseNode(b,a,!a.open):a&&i.expandCollapseNode(b,a,!a.open)}};p.fn.zTree={consts:{className:{BUTTON:\"button\",\nLEVEL:\"level\",ICO_LOADING:\"ico_loading\",SWITCH:\"switch\"},event:{NODECREATED:\"ztree_nodeCreated\",CLICK:\"ztree_click\",EXPAND:\"ztree_expand\",COLLAPSE:\"ztree_collapse\",ASYNC_SUCCESS:\"ztree_async_success\",ASYNC_ERROR:\"ztree_async_error\",REMOVE:\"ztree_remove\",SELECTED:\"ztree_selected\",UNSELECTED:\"ztree_unselected\"},id:{A:\"_a\",ICON:\"_ico\",SPAN:\"_span\",SWITCH:\"_switch\",UL:\"_ul\"},line:{ROOT:\"root\",ROOTS:\"roots\",CENTER:\"center\",BOTTOM:\"bottom\",NOLINE:\"noline\",LINE:\"line\"},folder:{OPEN:\"open\",CLOSE:\"close\",\nDOCU:\"docu\"},node:{CURSELECTED:\"curSelectedNode\"}},_z:{tools:j,view:i,event:m,data:h},getZTreeObj:function(b){return(b=h.getZTreeTools(b))?b:null},destroy:function(b){if(b&&b.length>0)i.destroy(h.getSetting(b));else for(var a in r)i.destroy(r[a])},init:function(b,a,c){var d=j.clone(M);p.extend(!0,d,a);d.treeId=b.attr(\"id\");d.treeObj=b;d.treeObj.empty();r[d.treeId]=d;if(typeof document.body.style.maxHeight===\"undefined\")d.view.expandSpeed=\"\";h.initRoot(d);b=h.getRoot(d);a=d.data.key.children;c=c?j.clone(j.isArray(c)?\nc:[c]):[];b[a]=d.data.simpleData.enable?h.transformTozTreeFormat(d,c):c;h.initCache(d);m.unbindTree(d);m.bindTree(d);m.unbindEvent(d);m.bindEvent(d);c={setting:d,addNodes:function(a,b,c){function e(){i.addNodes(d,a,h,c==!0)}if(!b)return null;a||(a=null);if(a&&!a.isParent&&d.data.keep.leaf)return null;var h=j.clone(j.isArray(b)?b:[b]);j.canAsync(d,a)?i.asyncNode(d,a,c,e):e();return h},cancelSelectedNode:function(a){i.cancelPreSelectedNode(d,a)},destroy:function(){i.destroy(d)},expandAll:function(a){a=\n!!a;i.expandCollapseSonNode(d,null,a,!0);return a},expandNode:function(a,b,c,e,m){if(!a||!a.isParent)return null;b!==!0&&b!==!1&&(b=!a.open);if((m=!!m)&&b&&j.apply(d.callback.beforeExpand,[d.treeId,a],!0)==!1)return null;else if(m&&!b&&j.apply(d.callback.beforeCollapse,[d.treeId,a],!0)==!1)return null;b&&a.parentTId&&i.expandCollapseParentNode(d,a.getParentNode(),b,!1);if(b===a.open&&!c)return null;h.getRoot(d).expandTriggerFlag=m;if(!j.canAsync(d,a)&&c)i.expandCollapseSonNode(d,a,b,!0,function(){if(e!==\n!1)try{k(a,d).focus().blur()}catch(b){}});else if(a.open=!b,i.switchNode(this.setting,a),e!==!1)try{k(a,d).focus().blur()}catch(p){}return b},getNodes:function(){return h.getNodes(d)},getNodeByParam:function(a,b,c){return!a?null:h.getNodeByParam(d,c?c[d.data.key.children]:h.getNodes(d),a,b)},getNodeByTId:function(a){return h.getNodeCache(d,a)},getNodesByParam:function(a,b,c){return!a?null:h.getNodesByParam(d,c?c[d.data.key.children]:h.getNodes(d),a,b)},getNodesByParamFuzzy:function(a,b,c){return!a?\nnull:h.getNodesByParamFuzzy(d,c?c[d.data.key.children]:h.getNodes(d),a,b)},getNodesByFilter:function(a,b,c,e){b=!!b;return!a||typeof a!=\"function\"?b?null:[]:h.getNodesByFilter(d,c?c[d.data.key.children]:h.getNodes(d),a,b,e)},getNodeIndex:function(a){if(!a)return null;for(var b=d.data.key.children,c=a.parentTId?a.getParentNode():h.getRoot(d),e=0,i=c[b].length;e<i;e++)if(c[b][e]==a)return e;return-1},getSelectedNodes:function(){for(var a=[],b=h.getRoot(d).curSelectedList,c=0,e=b.length;c<e;c++)a.push(b[c]);\nreturn a},isSelectedNode:function(a){return h.isSelectedNode(d,a)},reAsyncChildNodes:function(a,b,c){if(this.setting.async.enable){var j=!a;j&&(a=h.getRoot(d));if(b==\"refresh\"){for(var b=this.setting.data.key.children,m=0,p=a[b]?a[b].length:0;m<p;m++)h.removeNodeCache(d,a[b][m]);h.removeSelectedNode(d);a[b]=[];j?this.setting.treeObj.empty():k(a,e.id.UL,d).empty()}i.asyncNode(this.setting,j?null:a,!!c)}},refresh:function(){this.setting.treeObj.empty();var a=h.getRoot(d),b=a[d.data.key.children];h.initRoot(d);\na[d.data.key.children]=b;h.initCache(d);i.createNodes(d,0,a[d.data.key.children])},removeChildNodes:function(a){if(!a)return null;var b=a[d.data.key.children];i.removeChildNodes(d,a);return b?b:null},removeNode:function(a,b){a&&(b=!!b,b&&j.apply(d.callback.beforeRemove,[d.treeId,a],!0)==!1||(i.removeNode(d,a),b&&this.setting.treeObj.trigger(e.event.REMOVE,[d.treeId,a])))},selectNode:function(a,b){if(a&&j.uCanDo(d)){b=d.view.selectedMulti&&b;if(a.parentTId)i.expandCollapseParentNode(d,a.getParentNode(),\n!0,!1,function(){try{k(a,d).focus().blur()}catch(b){}});else try{k(a,d).focus().blur()}catch(c){}i.selectNode(d,a,b)}},transformTozTreeNodes:function(a){return h.transformTozTreeFormat(d,a)},transformToArray:function(a){return h.transformToArrayFormat(d,a)},updateNode:function(a){a&&k(a,d).get(0)&&j.uCanDo(d)&&(i.setNodeName(d,a),i.setNodeTarget(d,a),i.setNodeUrl(d,a),i.setNodeLineIcos(d,a),i.setNodeFontCss(d,a))}};b.treeTools=c;h.setZTreeTools(d,c);b[a]&&b[a].length>0?i.createNodes(d,0,b[a]):d.async.enable&&\nd.async.url&&d.async.url!==\"\"&&i.asyncNode(d);return c}};var N=p.fn.zTree,k=j.$,e=N.consts})(jQuery);\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/apiCss/zTreeStyleForApi.css",
    "content": "/*-------------------------------------\nzTree Style\n\nversion:\t3.0\nauthor:\t\tHunter.z\nemail:\t\thunter.z@263.net\nwebsite:\thttp://code.google.com/p/jquerytree/\n\n-------------------------------------*/\n\n.ztree * {padding:0; margin:0; font-size:12px; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif}\n.ztree {margin:0; padding:5px; color:#333}\n.ztree li{padding:0; margin:0; list-style:none; line-height:14px; text-align:left; white-space:nowrap}\n.ztree li ul{ margin:0; padding:0 0 0 18px}\n.ztree li ul.line{ background:url(./img/line_conn.gif) 0 0 repeat-y;}\n\n.ztree li a {padding:1px 3px 0 0; margin:0; cursor:pointer; color:#333; height:17px; text-decoration:none; vertical-align:top; display: inline-block}\n.ztree li a:hover {text-decoration:none}\n.ztree li a.curSelectedNode {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid;}\n.ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid; opacity:0.8; filter:alpha(opacity=80)}\n.ztree li a.tmpTargetNode_inner {padding-top:0px; background-color:#316AC5; color:white; height:16px; border:1px #316AC5 solid; opacity:0.8; filter:alpha(opacity=80)}\n.ztree li a.tmpTargetNode_prev {}\n.ztree li a.tmpTargetNode_next {}\n.ztree li a input.rename {height:14px; width:80px; padding:0; margin:0;\n\tfont-size:12px; border:1px #7EC4CC solid; *border:0px}\n.ztree li span {line-height:16px; margin-right: 2px}\n.ztree li span.button {line-height:0; margin:0;width:16px; height:16px; display: inline-block; vertical-align:middle;\n\tborder:0 none; cursor: pointer;\n\tbackground-color:transparent; background-repeat:no-repeat; background-attachment: scroll;\n\tbackground-image:url(\"./img/zTreeStandard.png\"); *background-image:url(\"./img/zTreeStandard.gif\")}\n\n.ztree li span.button.switch {width:1px; height:18px; visibility: hidden}\n\n.zTreeDragUL {margin:0; padding:0; position:absolute; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)}\n.zTreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute}\n\n/* level 等级样式*/\n/*.ztree li button.level0 {\n\tdisplay:none;\n}\n.ztree li ul.level0 {\n\tpadding:0;\n\tbackground:none;\n}*/\n\n.ztree li span.button.core_ico_docu{margin-right:2px; background-position:-126px 0; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.check_ico_docu{margin-right:2px; background-position:-126px -16px; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.edit_ico_docu{margin-right:2px; background-position:-126px -32px; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.hide_ico_docu{margin-right:2px; background-position:-160px 0; vertical-align:top; *vertical-align:middle}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/fn.zTree._z.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>JSON</span><span class=\"path\">$.fn.zTree.</span>_z</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree v3.x 内部的全部方法都可以通过 $.fn.zTree._z 进行调用，开放出来是为了更便于大家开发制作自己的 zTree 插件。 </p>\n\t\t\t<p class=\"highlight_red\">如无特殊需求请勿使用此对象，以及修改此对象内部的各个函数。</p>\n\t\t</div>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/fn.zTree.destroy.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId)</span><span class=\"path\">$.fn.zTree.</span>destroy</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>从 zTree v3.4 开始提供销毁 zTree 的方法。 </p>\n\t\t\t<p>1、用此方法可以销毁指定 treeId 的 zTree，也可以销毁当前页面全部的 zTree。</p>\n\t\t\t<p class=\"highlight_red\">2、销毁指定 treeId 的 zTree 也可以使用 zTreeObj.destroy() 方法。</p>\n\t\t\t<p class=\"highlight_red\">3、重新使用已经被销毁的树，必须要使用 init 方法进行初始化。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree 的 DOM 容器的 id</p>\n\t<p class=\"highlight_red\">省略 treeId，表示销毁当前页面全部的 zTree</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 销毁 id 为 \"treeDemo\" 的 zTree</h4>\n\t<pre xmlns=\"\"><code>$.fn.zTree.destroy(\"treeDemo\");</code></pre>\n\t<h4>2. 销毁全部 的 zTree</h4>\n\t<pre xmlns=\"\"><code>$.fn.zTree.destroy();</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/fn.zTree.getZTreeObj.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId)</span><span class=\"path\">$.fn.zTree.</span>getZTreeObj</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree v3.x 专门提供的根据 treeId 获取 zTree 对象的方法。 </p>\n\t\t\t<p class=\"highlight_red\">必须在初始化 zTree 以后才可以使用此方法。</p>\n\t\t\t<p>有了这个方法，用户不再需要自己设定全局变量来保存 zTree 初始化后得到的对象了，而且在所有回调函数中全都会返回 treeId 属性，用户可以随时使用此方法获取需要进行操作的 zTree 对象</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree 的 DOM 容器的 id</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>JSON</span></h4>\n\t<p>zTree 对象，提供操作 zTree 的各种方法，对于通过 js 操作 zTree 来说必须通过此对象</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 获取 id 为 tree 的 zTree 对象</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/fn.zTree.init.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(obj, zSetting, zNodes)</span><span class=\"path\">$.fn.zTree.</span>init</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 初始化方法，创建 zTree 必须使用此方法</p>\n\t\t\t<p>1、页面需要进行 W3C 申明，例如：&lt;!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"&nbsp;&nbsp; &nbsp;\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"&gt;。</p>\n\t\t\t<p>2、需要首先加载 jquery-1.4.2.js 或其他更高版本的 jQuery 。</p>\n\t\t\t<p>3、需要加载 jquery-ztree.core-3.0.js，如果需要用到 编辑功能 或 checkbox / radio 还需要分别加载 jquery-ztree.exedit-3.0.js 和 jquery-ztree.excheck-3.0.js 。</p>\n\t\t\t<p>4、需要加载 zTreeStyle.css 以及 zTreeStyle 目录下的 img 文件。</p>\n\t\t\t<p>5、如果需要使用自定义图标请参考相应的Demo。</p>\n\t\t\t<p>6、请注意设置 zTree 的容器样式 class=\"ztree\"，其中 \"ztree\" 这个 className，可以根据需要随意修改，别忘了修改 css 中对应名字就是了，对于容器如果需要增加其他特殊样式，可根据自己的需要进行修改。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>obj</b><span>jQuery Object</span></h4>\n\t<p>用于展现 zTree 的 DOM 容器</p>\n\t<h4 class=\"topLine\"><b>zSetting</b><span>JSON</span></h4>\n\t<p>zTree 的配置数据，具体请参考 “setting 配置详解”中的各个属性详细说明</p>\n\t<h4 class=\"topLine\"><b>zNodes</b><span>Array(JSON) / JSON</span></h4>\n\t<p>zTree 的节点数据，具体请参考 “treeNode 节点数据详解”中的各个属性详细说明</p>\n\t<p class=\"highlight_red\">1、v3.x 支持单独添加一个节点，即如果只新增一个节点，不用必须包在数组中</p>\n\t<p class=\"highlight_red\">2、如果需要异步加载根节点，可以设置为 null 或 [ ]</p>\n\t<p class=\"highlight_red\">3、使用简单数据模式，请参考 setting.data.simpleData 内的属性说明</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>JSON</span></h4>\n\t<p>zTree 对象，提供操作 zTree 的各种方法，对于通过 js 操作 zTree 来说必须通过此对象</p>\n\t<p class=\"highlight_red\">如果不需要自行设定全局变量保存，可以利用 $.fn.zTree.getZTreeObj 方法随时获取</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 简单创建 zTree 演示</h4>\n\t<pre xmlns=\"\"><code>&lt;!DOCTYPE html&gt;\n&lt;HTML&gt;\n &lt;HEAD&gt;\n  &lt;TITLE&gt; ZTREE DEMO &lt;/TITLE&gt;\n  &lt;meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"&gt;\n  &lt;link rel=\"stylesheet\" href=\"zTreeStyle/zTreeStyle.css\" type=\"text/css\"&gt;\n  &lt;script type=\"text/javascript\" src=\"jquery-1.4.2.js\"&gt;&lt;/script&gt;\n  &lt;script type=\"text/javascript\" src=\"jquery.ztree.core-3.5.js\"&gt;&lt;/script&gt;\n&lt;!--\n  &lt;script type=\"text/javascript\" src=\"jquery.ztree.excheck-3.5.js\"&gt;&lt;/script&gt;\n  &lt;script type=\"text/javascript\" src=\"jquery.ztree.exedit-3.5.js\"&gt;&lt;/script&gt;\n--&gt;\n  &lt;SCRIPT type=\"text/javascript\" &gt;\n\tvar zTreeObj,\n\tsetting = {\n\t\tview: {\n\t\t\tselectedMulti: false\n\t\t}\n\t},\n\tzTreeNodes = [\n\t\t{\"name\":\"网站导航\", open:true, children: [\n\t\t\t{ \"name\":\"google\", \"url\":\"http://g.cn\", \"target\":\"_blank\"},\n\t\t\t{ \"name\":\"baidu\", \"url\":\"http://baidu.com\", \"target\":\"_blank\"},\n\t\t\t{ \"name\":\"sina\", \"url\":\"http://www.sina.com.cn\", \"target\":\"_blank\"}\n\t\t\t]\n\t\t}\n\t];\n\n\t$(document).ready(function(){\n\t\tzTreeObj = $.fn.zTree.init($(\"#tree\"), setting, zTreeNodes);\n\n\t});\n  &lt;/SCRIPT&gt;\n &lt;/HEAD&gt;\n\n&lt;BODY&gt;\n&lt;ul id=\"tree\" class=\"ztree\" style=\"width:230px; overflow:auto;\"&gt;&lt;/ul&gt;\n &lt;/BODY&gt;\n&lt;/HTML&gt;</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.async.autoParam.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Array(String)</span><span class=\"path\">setting.async.</span>autoParam</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>异步加载时需要自动提交父节点属性的参数。<span class=\"highlight_red\">[setting.async.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：[ ]</p>\n\t\t</div>\n\t</div>\n\t<h3>Array(String) 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>1、将需要作为参数提交的属性名称，制作成 Array 即可，例如：[\"id\", \"name\"]</p>\n\t<p>2、可以设置提交时的参数名称，例如 server 只接受 zId : [\"id=zId\"]</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 id 属性为自动提交的参数</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id\"]\n\t}\n};\n假设 异步加载 父节点(node = {id:1, name:\"test\"}) 的子节点时，将提交参数 id=1\n......</code></pre>\n\t<h4>2. 设置 id 属性作为 zId 成为自动提交的参数</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id=zId\"]\n\t}\n};\n假设 对父节点 node = {id:1, name:\"test\"}，进行异步加载时，将提交参数 zId=1\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.async.contentType.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.async.</span>contentType</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Ajax 提交参数的数据类型。<span class=\"highlight_red\">[setting.async.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：\"application/x-www-form-urlencoded\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> contentType = \"application/x-www-form-urlencoded\" 可以满足绝大部分请求，按照标准的 Form 格式提交参数</p>\n\t<p> contentType = \"application/json\" 可以满足 .Net 的编程需要，按照 JSON 格式提交参数</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 Ajax 提交参数的数据类型为 JSON 格式</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\tcontentType: \"application/json\",\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.async.dataFilter.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, parentNode, responseData)</span><span class=\"path\">setting.async.</span>dataFilter</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于对 Ajax 返回数据进行预处理的函数。<span class=\"highlight_red\">[setting.async.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>parentNode</b><span>JSON</span></h4>\n\t<p>进行异步加载的父节点 JSON 数据对象</p>\n\t<p class=\"highlight_red\">对根进行异步加载时，parentNode = null</p>\n\t<h4 class=\"topLine\"><b>responseData</b><span>Array(JSON) / JSON / String</span></h4>\n\t<p>异步加载获取到的数据转换后的 Array(JSON) / JSON / String 数据对象</p>\n\t<p class=\"highlight_red\">v3.4开始 支持 XML 数据格式的 String</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Array(JSON) / JSON</span></h4>\n\t<p>返回值是 zTree 支持的JSON 数据结构即可。</p>\n\t<p class=\"highlight_red\">v3.x 支持单个 JSON 节点数据进行加载</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 修改异步获取到的节点name属性</h4>\n\t<pre xmlns=\"\"><code>function ajaxDataFilter(treeId, parentNode, responseData) {\n    if (responseData) {\n      for(var i =0; i < responseData.length; i++) {\n        responseData[i].name += \"_filter\";\n      }\n    }\n    return responseData;\n};\nvar setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\tdataFilter: ajaxDataFilter\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.async.dataType.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.async.</span>dataType</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Ajax 获取的数据类型。<span class=\"highlight_red\">[setting.async.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：\"text\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> dataType = \"text\" 可以满足绝大部分请求</p>\n\t<p class=\"highlight_red\">其余 dataType 类型请参考 jQuery ajax 中的 dataType 参数</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 Ajax 获取的数据类型为 纯文本</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\tdataType: \"text\",\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.async.enable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.async.</span>enable</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置 zTree 是否开启异步加载模式</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示 开启 异步加载模式</p>\n\t<p> false 表示 关闭 异步加载模式</p>\n\t<p class=\"highlight_red\">如果设置为 true，请务必设置 setting.async 内的其它参数。</p>\n\t<p class=\"highlight_red\">如果需要根节点也异步加载，初始化时 treeNodes 参数设置为 null 即可。</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 需要开启异步加载模式</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.async.otherParam.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Array(String) / JSON</span><span class=\"path\">setting.async.</span>otherParam</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Ajax 请求提交的静态参数键值对。<span class=\"highlight_red\">[setting.async.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：[ ]</p>\n\t\t</div>\n\t</div>\n\t<h3>Array(String) 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>可以为空[ ]，如果有 key，则必须存在 value。 例如：[key, value]</p>\n\t</div>\n\t<h3>JSON 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>直接用 JSON 格式制作键值对，例如：{ key1:value1, key2:value2 }</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 Array(String) 格式的参数</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\totherParam: [\"id\", \"1\", \"name\", \"test\"]\n\t}\n};\n进行异步加载时，将提交参数 id=1&name=test</code></pre>\n\t<h4>2. 设置 JSON 格式的参数</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\totherParam: { \"id\":\"1\", \"name\":\"test\"}\n\t}\n};\n进行异步加载时，将提交参数 id=1&name=test</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.async.type.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.async.</span>type</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Ajax 的 http 请求模式。<span class=\"highlight_red\">[setting.async.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：\"post\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> type = \"post\" 表示异步加载采用 post 方法请求</p>\n\t<p> type = \"get\" 表示异步加载采用 get 方法请求</p>\n\t<p class=\"highlight_red\">对应于 jQuery ajax 中的 type 参数</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置使用 get 方式请求数据</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\ttype: \"get\",\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.async.url.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String / Function(treeId, treeNode)</span><span class=\"path\">setting.async.</span>url</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Ajax 获取数据的 URL 地址。<span class=\"highlight_red\">[setting.async.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：\"\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>设置固定的异步加载 url 字符串，请注意地址的路径，确保页面能正常加载</p>\n\t<p class=\"highlight_red\">url 内也可以带参数，这些参数就只能是通过 get 方式提交了，并且请注意进行转码</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要异步加载子节点的的父节点 JSON 数据对象</p>\n\t<p class=\"highlight_red\">针对根进行异步加载时，treeNode = null</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>String</span></h4>\n\t<p>返回值同 String 格式的数据</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 设置异步获取节点的 URL 为 nodes.php</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"nodes.php\",\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n\t<h4>2. 设置异步获取节点的 URL 为 function 动态获取</h4>\n\t<pre xmlns=\"\"><code>function getAsyncUrl(treeId, treeNode) {\n    return treeNode.isParent ? \"nodes1.php\" : \"nodes2.php\";\n};\nvar setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: getAsyncUrl,\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeAsync.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeAsync</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获异步加载之前的事件回调函数，zTree 根据返回值确定是否允许进行异步加载</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>进行异步加载的父节点 JSON 数据对象</p>\n\t<p class=\"highlight_red\">针对根进行异步加载时，treeNode = null</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，zTree 将不进行异步加载，也无法触发 onAsyncSuccess / onAsyncError 事件回调函数</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止 id 为 1 的父节点进行异步加载操作</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeAsync(treeId, treeNode) {\n    return (treeNode.id !== 1);\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeAsync: zTreeBeforeAsync\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeCheck.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeCheck</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获 勾选 或 取消勾选 之前的事件回调函数，并且根据返回值确定是否允许 勾选 或 取消勾选 </p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>进行 勾选 或 取消勾选 的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，将不会改变勾选状态，并且无法触发 onCheck 事件回调函数</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止所有勾选操作，保持初始化的勾选状态</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeCheck(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeCheck: zTreeBeforeCheck\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode, clickFlag)</span><span class=\"path\">setting.callback.</span>beforeClick</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获单击节点之前的事件回调函数，并且根据返回值确定是否允许单击操作</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>被单击的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>clickFlag</b><span>Number</span></h4>\n\t<p>节点被点击后的选中操作类型，详细看下表</p>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead><tr><td>clickFlag</td><td title=\"是否允许多点选中\">selectedMulti</td><td title=\"是否按下 Ctrl 或 Cmd 键\">autoCancelSelected<br/>&&<br/>event.ctrlKey / metaKey</td><td title=\"节点当前选择状态\">isSelected</td><td>选中操作</td></tr></thead>\n\t\t<tbody>\n\t\t\t<tr><td>1</td><td>true</td><td>false</td><td>false</td><td>普通选中</td></tr>\n\t\t\t<tr><td>1</td><td>true</td><td>false</td><td>true</td><td>普通选中</td></tr>\n\t\t\t<tr><td>2</td><td>true</td><td>true</td><td>false</td><td>追加选中</td></tr>\n\t\t\t<tr><td>0</td><td>true</td><td>true</td><td>true</td><td>取消选中</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>false</td><td>false</td><td>普通选中</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>false</td><td>true</td><td>普通选中</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>true</td><td>false</td><td>普通选中</td></tr>\n\t\t\t<tr><td>0</td><td>false</td><td>true</td><td>true</td><td>取消选中</td></tr>\n\t\t</tbody>\n\t</table>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，zTree 将不会选中节点，也无法触发 onClick 事件回调函数</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止节点被选中</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeClick(treeId, treeNode, clickFlag) {\n    return (treeNode.id !== 1);\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeClick: zTreeBeforeClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeCollapse.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeCollapse</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获父节点折叠之前的事件回调函数，并且根据返回值确定是否允许折叠操作</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>要折叠的父节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，zTree 将不会折叠节点，也无法触发 onCollapse 事件回调函数</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止所有已展开的父节点折叠</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeCollapse(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeCollapse: zTreeBeforeCollapse\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeDblClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeDblClick</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获 zTree 上鼠标双击之前的事件回调函数，并且根据返回值确定触发 onDblClick 事件回调函数</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>鼠标双击时所在节点的 JSON 数据对象</p>\n\t<p class=\"highlight_red\">如果不在节点上，则返回 null</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，将仅仅无法触发 onDblClick 事件回调函数，对其他操作无任何影响</p>\n\t<p class=\"highlight_red\">此事件回调函数对双击节点展开功能无任何影响，如果需要设置请参考 setting.view.dblClickExpand 属性</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止 onDblClick 事件</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeDblClick(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeDblClick: zTreeBeforeDblClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeDrag.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNodes)</span><span class=\"path\">setting.callback.</span>beforeDrag</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点被拖拽之前的事件回调函数，并且根据返回值确定是否允许开启拖拽操作</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>被拖拽的节点 treeNodes 所在 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>要被拖拽的节点 JSON 数据集合</p>\n\t<p class=\"highlight_red\">v3.x 允许多个同级节点同时被拖拽，因此将此参数修改为 Array(JSON)</p>\n\t<p class=\"highlight_red\">如果拖拽时多个被选择的节点不是同级关系，则只能拖拽鼠标当前所在位置的节点</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，zTree 将终止拖拽，也无法触发 onDrag / beforeDrop / onDrop 事件回调函数</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止全部拖拽操作</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeDrag(treeId, treeNodes) {\n    return false;\n};\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeDrag: zTreeBeforeDrag\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeDragOpen.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeDragOpen</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获拖拽节点移动到折叠状态的父节点后，即将自动展开该父节点之前的事件回调函数，并且根据返回值确定是否允许自动展开操作</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>需要被展开的父节点 treeNode 所在 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>要被自动展开的父节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，zTree 将无法进行自动展开操作</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止全部拖拽时的自动展开操作</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeDragOpen(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeDragOpen: zTreeBeforeDragOpen\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeDrop.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNodes, targetNode, moveType, isCopy)</span><span class=\"path\">setting.callback.</span>beforeDrop</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点拖拽操作结束之前的事件回调函数，并且根据返回值确定是否允许此拖拽操作</p>\n\t\t\t<p>默认值：null</p>\n\t\t\t<p class=\"highlight_red\">如未拖拽到有效位置，则不触发此回调函数，直接将节点恢复原位置</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>目标节点 targetNode 所在 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>被拖拽的节点 JSON 数据集合</p>\n\t<p class=\"highlight_red\">无论拖拽操作为 复制 还是 移动，treeNodes 都是当前被拖拽节点的数据集合。</p>\n\t<h4 class=\"topLine\"><b>targetNode</b><span>JSON</span></h4>\n\t<p>treeNodes 被拖拽放开的目标节点 JSON 数据对象。</p>\n\t<p class=\"highlight_red\">如果拖拽成为根节点，则 targetNode = null</p>\n\t<h4 class=\"topLine\"><b>moveType</b><span>String</span></h4>\n\t<p>指定移动到目标节点的相对位置</p>\n\t<p class=\"highlight_red\">\"inner\"：成为子节点，\"prev\"：成为同级前一个节点，\"next\"：成为同级后一个节点</p>\n\t<h4 class=\"topLine\"><b>isCopy</b><span>Boolean</span></h4>\n\t<p>拖拽节点操作是 复制 或 移动</p>\n\t<p class=\"highlight_red\">true：复制；false：移动</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，zTree 将恢复被拖拽的节点，也无法触发 onDrop 事件回调函数</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止将节点拖拽成为根节点</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeDrop(treeId, treeNodes, targetNode, moveType) {\n    return !(targetNode == null || (moveType != \"inner\" && !targetNode.parentTId));\n};\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeDrop: zTreeBeforeDrop\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeEditName.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeEditName</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点编辑按钮的 click 事件，并且根据返回值确定是否允许进入名称编辑状态</p>\n\t\t\t<p class=\"highlight_red\">此事件回调函数最主要是用于捕获编辑按钮的点击事件，然后触发自定义的编辑界面操作。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>将要进入编辑名称状态的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，节点将无法进入 zTree 默认的编辑名称状态</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止修改父节点的名称</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeEditName(treeId, treeNode) {\n\treturn !treeNode.isParent;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeEditName: zTreeBeforeEditName\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeExpand.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeExpand</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获父节点展开之前的事件回调函数，并且根据返回值确定是否允许展开操作</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>要展开的父节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，zTree 将不会展开节点，也无法触发 onExpand 事件回调函数</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止所有已折叠的父节点展开</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeExpand(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeExpand: zTreeBeforeExpand\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeMouseDown.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeMouseDown</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获 zTree 上鼠标按键按下之前的事件回调函数，并且根据返回值确定触发 onMouseDown 事件回调函数</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>鼠标按键按下时所在节点的 JSON 数据对象</p>\n\t<p class=\"highlight_red\">如果不在节点上，则返回 null</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，将仅仅无法触发 onMouseDown 事件回调函数，对其他操作无任何影响</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止 onMouseDown 事件</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeMouseDown(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeMouseDown: zTreeBeforeMouseDown\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeMouseUp.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeMouseUp</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获 zTree 上鼠标按键松开之前的事件回调函数，并且根据返回值确定触发 onMouseUp 事件回调函数</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>鼠标按键松开时所在节点的 JSON 数据对象</p>\n\t<p class=\"highlight_red\">如果不在节点上，则返回 null</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，将仅仅无法触发 onMouseUp 事件回调函数，对其他操作无任何影响</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止 onMouseUp 事件</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeMouseUp(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeMouseUp: zTreeBeforeMouseUp\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeRemove.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeRemove</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点被删除之前的事件回调函数，并且根据返回值确定是否允许删除操作</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>将要删除的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，zTree 将不删除节点，也无法触发 onRemove 事件回调函数</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止全部删除操作</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeRemove(treeId, treeNode) {\n\treturn false;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeRemove: zTreeBeforeRemove\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeRename.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode, newName, isCancel)</span><span class=\"path\">setting.callback.</span>beforeRename</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点编辑名称结束（Input 失去焦点 或 按下 Enter 键）之后，更新节点名称数据之前的事件回调函数，并且根据返回值确定是否允许更改名称的操作</p>\n\t\t\t<p class=\"highlight_red\">节点进入编辑名称状态后，按 ESC 键可以放弃当前修改，恢复原名称，取消编辑名称状态</p>\n\t\t\t<p class=\"highlight_red\">从 v3.5.13 开始，取消编辑状态也会触发此回调，根据 isCancel 参数判断</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>将要更改名称的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>newName</b><span>String</span></h4>\n\t<p>修改后的新名称</p>\n\t<h4 class=\"topLine\"><b>isCancel</b><span>Boolean</span></h4>\n\t<p>是否取消操作 (v3.5.13+)</p>\n\t<p class=\"highlight_red\">isCancel = true 表示取消编辑操作（按下 ESC 或 使用 cancelEditName 方法）</p>\n\t<p class=\"highlight_red\">isCancel = false 表示确认修改操作</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，zTree 将保持名称编辑状态，无法触发 onRename 事件回调函数，并且会导致屏蔽其它事件，直到修改名称使得 beforeRename 返回 true</p>\n\t<p class=\"highlight_red\">如果返回 false，不会让 input 输入框获取焦点，避免由于警告信息而导致反复触发 beforeRename。 请在关闭提示警告信息后，利用 editName 方法让 input 重新获取焦点。</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止修改的名称的长度小于 5</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeRename(treeId, treeNode, newName, isCancel) {\n\treturn newName.length > 5;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeRename: zTreeBeforeRename\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.beforeRightClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeRightClick</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获 zTree 上鼠标右键点击之前的事件回调函数，并且根据返回值确定触发 onRightClick 事件回调函数</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>鼠标右键点击时所在节点的 JSON 数据对象</p>\n\t<p class=\"highlight_red\">如果不在节点上，则返回 null</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值是 true / false</p>\n\t<p class=\"highlight_red\">如果返回 false，将仅仅无法触发 onRightClick 事件回调函数，对其他操作无任何影响</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止 onRightClick 事件</h4>\n\t<pre xmlns=\"\"><code>function zTreeBeforeRightClick(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeRightClick: zTreeBeforeRightClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onAsyncError.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span class=\"path\">setting.callback.</span>onAsyncError</h2>\n\t<h2><span>Function(event, treeId, treeNode, XMLHttpRequest, textStatus, errorThrown)</span>&nbsp;</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获异步加载出现异常错误的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeAsync 方法，且返回 false，将无法触发 onAsyncSuccess / onAsyncError 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>进行异步加载的父节点 JSON 数据对象</p>\n\t<p class=\"highlight_red\">针对根进行异步加载时，treeNode = null</p>\n\t<h4 class=\"topLine\"><b>XMLHttpRequest</b><span>String</span></h4>\n\t<p>标准 XMLHttpRequest 对象，请参考 JQuery API 文档。</p>\n\t<h4 class=\"topLine\"><b>textStatus</b><span>String</span></h4>\n\t<p>请求状态：success，error，请参考 JQuery API 文档。</p>\n\t<h4 class=\"topLine\"><b>errorThrown</b><span>String</span></h4>\n\t<p>errorThrown 只有当异常发生时才会被传递，请参考 JQuery API 文档。</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 异步加载出现异常后，弹出错误信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnAsyncError(event, treeId, treeNode, XMLHttpRequest, textStatus, errorThrown) {\n    alert(XMLHttpRequest);\n};\nvar setting = {\n\tcallback: {\n\t\tonAsyncError: zTreeOnAsyncError\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onAsyncSuccess.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode, msg)</span><span class=\"path\">setting.callback.</span>onAsyncSuccess</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获异步加载正常结束的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeAsync 方法，且返回 false，将无法触发 onAsyncSuccess / onAsyncError 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>进行异步加载的父节点 JSON 数据对象</p>\n\t<p class=\"highlight_red\">针对根进行异步加载时，treeNode = null</p>\n\t<h4 class=\"topLine\"><b>msg</b><span>String / Object</span></h4>\n\t<p>异步获取的节点数据字符串，主要便于用户调试使用。</p>\n\t<p class=\"highlight_red\">实际数据类型会受 setting.async.dataType 的设置影响，请参考 JQuery API 文档。</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 异步加载成功后，弹出提示信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnAsyncSuccess(event, treeId, treeNode, msg) {\n    alert(msg);\n};\nvar setting = {\n\tcallback: {\n\t\tonAsyncSuccess: zTreeOnAsyncSuccess\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onCheck.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onCheck</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获 checkbox / radio 被勾选 或 取消勾选的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeCheck 方法，且返回 false，将无法触发 onCheck 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>被勾选 或 取消勾选的节点 JSON 数据对象</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 每次点击 checkbox 或 radio 后， 弹出该节点的 tId、name 以及当前勾选状态的信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnCheck(event, treeId, treeNode) {\n    alert(treeNode.tId + \", \" + treeNode.name + \",\" + treeNode.checked);\n};\nvar setting = {\n\tcallback: {\n\t\tonCheck: zTreeOnCheck\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode, clickFlag)</span><span class=\"path\">setting.callback.</span>onClick</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点被点击的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeClick 方法，且返回 false，将无法触发 onClick 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>被点击的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>clickFlag</b><span>Number</span></h4>\n\t<p>节点被点击后的选中操作类型，详细看下表</p>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead><tr><td>clickFlag</td><td title=\"是否允许多点选中\">selectedMulti</td><td title=\"是否按下 Ctrl 或 Cmd 键\">autoCancelSelected<br/>&&<br/>event.ctrlKey / metaKey</td><td title=\"节点当前选择状态\">isSelected</td><td>选中操作</td></tr></thead>\n\t\t<tbody>\n\t\t\t<tr><td>1</td><td>true</td><td>false</td><td>false</td><td>普通选中</td></tr>\n\t\t\t<tr><td>1</td><td>true</td><td>false</td><td>true</td><td>普通选中</td></tr>\n\t\t\t<tr><td>2</td><td>true</td><td>true</td><td>false</td><td>追加选中</td></tr>\n\t\t\t<tr><td>0</td><td>true</td><td>true</td><td>true</td><td>取消选中</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>false</td><td>false</td><td>普通选中</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>false</td><td>true</td><td>普通选中</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>true</td><td>false</td><td>普通选中</td></tr>\n\t\t\t<tr><td>0</td><td>false</td><td>true</td><td>true</td><td>取消选中</td></tr>\n\t\t</tbody>\n\t</table>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 每次点击节点后， 弹出该节点的 tId、name 的信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnClick(event, treeId, treeNode) {\n    alert(treeNode.tId + \", \" + treeNode.name);\n};\nvar setting = {\n\tcallback: {\n\t\tonClick: zTreeOnClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onCollapse.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onCollapse</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点被折叠的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeCollapse 方法，且返回 false，将无法触发 onCollapse 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>被折叠的节点 JSON 数据对象</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 每次折叠节点后， 弹出该节点的 tId、name 的信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnCollapse(event, treeId, treeNode) {\n    alert(treeNode.tId + \", \" + treeNode.name);\n};\nvar setting = {\n\tcallback: {\n\t\tonCollapse: zTreeOnCollapse\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onDblClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onDblClick</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获 zTree 上鼠标双击之后的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeDblClick 方法，且返回 false，将无法触发 onDblClick 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>鼠标双击时所在节点的 JSON 数据对象</p>\n\t<p class=\"highlight_red\">如果不在节点上，则返回 null</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 每次鼠标双击后， 弹出鼠标所在节点的 tId、name 的信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnDblClick(event, treeId, treeNode) {\n    alert(treeNode ? treeNode.tId + \", \" + treeNode.name : \"isRoot\");\n};\nvar setting = {\n\tcallback: {\n\t\tonDblClick: zTreeOnDblClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onDrag.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNodes)</span><span class=\"path\">setting.callback.</span>onDrag</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点被拖拽的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeDrag 方法，且返回 false，将无法触发 onDragMove 和 onDrag 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>被拖拽的节点 treeNodes 所在 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>要被拖拽的节点 JSON 数据集合</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 每次开始进行拖拽节点后， 弹出被拖拽节点的个数信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnDrag(event, treeId, treeNodes) {\n    alert(treeNodes.length);\n};\nvar setting = {\n\tcallback: {\n\t\tonDrag: zTreeOnDrag\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onDragMove.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNodes)</span><span class=\"path\">setting.callback.</span>onDragMove</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点被拖拽过程中移动的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">主要用于捕获 zTree 节点拖拽到的 DOM，从而操作对应的 DOM。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>被拖拽的节点 treeNodes 所在 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>要被拖拽的节点 JSON 数据集合</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 拖拽节点时，随时输出 当前拖拽到的目标 DOM</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnDragMove(event, treeId, treeNodes) {\n    console.log(event.target);\n};\nvar setting = {\n\tcallback: {\n\t\tonDragMove: zTreeOnDragMove\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onDrop.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNodes, targetNode, moveType, isCopy)</span><span class=\"path\">setting.callback.</span>onDrop</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点拖拽操作结束的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeDrop 方法，且返回 false，将无法触发 onDrop 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>目标节点 targetNode 所在 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>被拖拽的节点 JSON 数据集合</p>\n\t<p class=\"highlight_red\">如果拖拽操作为 移动，treeNodes 是当前被拖拽节点的数据集合。</p>\n\t<p class=\"highlight_red\">如果拖拽操作为 复制，treeNodes 是复制后 clone 得到的新节点数据。</p>\n\t<h4 class=\"topLine\"><b>targetNode</b><span>JSON</span></h4>\n\t<p>成为 treeNodes 拖拽结束的目标节点 JSON 数据对象。</p>\n\t<p class=\"highlight_red\">如果拖拽成为根节点，则 targetNode = null</p>\n\t<h4 class=\"topLine\"><b>moveType</b><span>String</span></h4>\n\t<p>指定移动到目标节点的相对位置</p>\n\t<p class=\"highlight_red\">\"inner\"：成为子节点，\"prev\"：成为同级前一个节点，\"next\"：成为同级后一个节点</p>\n\t<p class=\"highlight_red\">如果 moveType = null，表明拖拽无效</p>\n\t<h4 class=\"topLine\"><b>isCopy</b><span>Boolean</span></h4>\n\t<p>拖拽节点操作是 复制 或 移动</p>\n\t<p class=\"highlight_red\">true：复制；false：移动</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 每次拖拽操作结束后， 弹出该被拖拽节点的个数以及目标节点的 tId、name 的信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnDrop(event, treeId, treeNodes, targetNode, moveType) {\n    alert(treeNodes.length + \",\" + (targetNode ? (targetNode.tId + \", \" + targetNode.name) : \"isRoot\" ));\n};\nvar setting = {\n\tcallback: {\n\t\tonDrop: zTreeOnDrop\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onExpand.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onExpand</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点被展开的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeExpand 方法，且返回 false，将无法触发 onExpand 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>被展开的节点 JSON 数据对象</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 每次展开节点后， 弹出该节点的 tId、name 的信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnExpand(event, treeId, treeNode) {\n    alert(treeNode.tId + \", \" + treeNode.name);\n};\nvar setting = {\n\tcallback: {\n\t\tonExpand: zTreeOnExpand\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onMouseDown.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onMouseDown</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获 zTree 上鼠标按键按下后的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeMouseDown 方法，且返回 false，将无法触发 onMouseDown 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>鼠标按键按下时所在节点的 JSON 数据对象</p>\n\t<p class=\"highlight_red\">如果不在节点上，则返回 null</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 每次鼠标按键按下后， 弹出鼠标所在节点的 tId、name 的信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnMouseDown(event, treeId, treeNode) {\n    alert(treeNode ? treeNode.tId + \", \" + treeNode.name : \"isRoot\");\n};\nvar setting = {\n\tcallback: {\n\t\tonMouseDown: zTreeOnMouseDown\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onMouseUp.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onMouseUp</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获 zTree 上鼠标按键松开后的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">如果设置了 setting.callback.beforeMouseUp 方法，且返回 false，将无法触发 onMouseUp 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>鼠标按键松开时所在节点的 JSON 数据对象</p>\n\t<p class=\"highlight_red\">如果不在节点上，则返回 null</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 每次鼠标按键松开后， 弹出鼠标所在节点的 tId、name 的信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnMouseUp(event, treeId, treeNode) {\n    alert(treeNode ? treeNode.tId + \", \" + treeNode.name : \"isRoot\");\n};\nvar setting = {\n\tcallback: {\n\t\tonMouseUp: zTreeOnMouseUp\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onNodeCreated.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onNodeCreated</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点生成 DOM 后的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">v3.x 采用了延迟加载技术，因此对于父节点未展开的子节点来说，初始化后是不会触发此回调函数，直到其父节点被展开</p>\n\t\t\t<p class=\"highlight_red\">大数据量的节点加载请注意：不设置 onNodeCreated，可以提升一部分初始化性能</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>生成 DOM 完毕的节点的 JSON 数据对象</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 创建节点 DOM 后， 弹出该节点的 tId、name 的信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnNodeCreated(event, treeId, treeNode) {\n    alert(treeNode.tId + \", \" + treeNode.name);\n};\nvar setting = {\n\tcallback: {\n\t\tonNodeCreated: zTreeOnNodeCreated\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onRemove.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onRemove</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获删除节点之后的事件回调函数。</p>\n\t\t\t<p class=\"highlight_red\">如果用户设置了 beforeRemove 回调函数，并返回 false，将无法触发 onRemove 事件回调函数。</p>\n\t\t\t<p>默认值：null</p>\t\t\t\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>将要删除的节点 JSON 数据对象</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 删除节点时，弹出被删除的节点的 tId 以及 name 信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnRemove(event, treeId, treeNode) {\n\talert(treeNode.tId + \", \" + treeNode.name);\n}\nvar setting = {\n\tcallback: {\n\t\tonRemove: zTreeOnRemove\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onRename.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode, isCancel)</span><span class=\"path\">setting.callback.</span>onRename</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获节点编辑名称结束之后的事件回调函数。</p>\n\t\t\t<p>1、节点进入编辑名称状态，并且修改节点名称后触发此回调函数。<span class=\"highlight_red\">如果用户设置了 beforeRename 回调函数，并返回 false，将无法触发 onRename 事件回调函数。</span></p>\n\t\t\t<p>2、<span class=\"highlight_red\">如果通过直接修改 treeNode 的数据，并且利用 updateNode 方法更新，是不会触发此回调函数的。</span></p>\n\t\t\t<p class=\"highlight_red\">3、从 v3.5.13 开始，取消编辑状态也会触发此回调，根据 isCancel 参数判断</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>被修改名称的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>isCancel</b><span>Boolean</span></h4>\n\t<p>是否取消操作 (v3.5.13+)</p>\n\t<p class=\"highlight_red\">isCancel = true 表示取消编辑操作（按下 ESC 或 使用 cancelEditName 方法）</p>\n\t<p class=\"highlight_red\">isCancel = false 表示确认修改操作</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 修改名称后，弹出被修改名称的节点的 tId 以及 name 信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnRename(event, treeId, treeNode, isCancel) {\n\talert(treeNode.tId + \", \" + treeNode.name);\n}\nvar setting = {\n\tcallback: {\n\t\tonRename: zTreeOnRename\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.callback.onRightClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onRightClick</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于捕获 zTree 上鼠标右键点击之后的事件回调函数</p>\n\t\t\t<p class=\"highlight_red\">1、如果设置了 setting.callback.beforeRightClick 方法，且返回 false，将无法触发 onRightClick 事件回调函数。</p>\n\t\t\t<p class=\"highlight_red\">2、只要将 function 的引用赋给 onRightClick 属性，则右键点击 zTree 时，将屏蔽浏览器的右键菜单。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event 对象</span></h4>\n\t<p>标准的 js event 对象</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>鼠标右键点击时所在节点的 JSON 数据对象</p>\n\t<p class=\"highlight_red\">如果不在节点上，则返回 null</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 每次鼠标右键点击后， 弹出鼠标所在节点的 tId、name 的信息</h4>\n\t<pre xmlns=\"\"><code>function zTreeOnRightClick(event, treeId, treeNode) {\n    alert(treeNode ? treeNode.tId + \", \" + treeNode.name : \"isRoot\");\n};\nvar setting = {\n\tcallback: {\n\t\tonRightClick: zTreeOnRightClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.check.autoCheckTrigger.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.check.</span>autoCheckTrigger</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置自动关联勾选时是否触发 beforeCheck / onCheck 事件回调函数。<span class=\"highlight_red\">[setting.check.enable = true 且 setting.check.chkStyle = \"checkbox\" 时生效]</span></p>\n\t\t\t<p class=\"highlight_red\">1、如果设置 setting.check.chkboxType = { \"Y\": \"\", \"N\": \"\" }，将不会有任何自动关联勾选的操作。</p>\n\t\t\t<p class=\"highlight_red\">2、如果开启触发，对于节点较多的树将会影响性能，因为所有被联动勾选的操作都会触发事件回调函数，请根据需要决定是否使用此功能。</p>\n\t\t\t<p>默认值: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 触发 / 不触发 事件回调函数</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 需要触发自动关联勾选操作</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tautoCheckTrigger: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.check.chkDisabledInherit.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.check.</span>chkDisabledInherit</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>当父节点设置 chkDisabled = true 时，设置子节点是否自动继承 chkDisabled = true 。<span class=\"highlight_red\">[setting.check.enable = true 时生效]</span></p>\n\t\t\t<p class=\"highlight_red\">1、只使用于初始化节点时，便于批量操作。 对于已存在的节点请利用 setChkDisabled 方法单个节点设置。</p>\n\t\t\t<p>默认值: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示 新加入子节点时，自动继承父节点 chkDisabled = true 的属性。</p>\n\t<p> false 表示 新加入子节点时，不继承父节点 chkDisabled 的属性。</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 需要子节点自动继承 chkDisabled = true</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tchkDisabledInherit: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.check.chkStyle.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.check.</span>chkStyle</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>勾选框类型(checkbox 或 radio）<span class=\"highlight_red\">[setting.check.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：\"checkbox\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>chkStyle = \"checkbox\" 时，显示 checkbox 选择框，<span class=\"highlight_red\">setting.check.chkboxType</span> 属性有效。\n<br/>chkStyle = \"radio\" 时，显示 radio 选择框， <span class=\"highlight_red\">setting.check.radioType</span> 属性有效。</p>\n\t<p class=\"highlight_red\">请注意大小写，不要改变</p>\n\t</div>\n\t<h3>checkbox 状态说明</h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p><button type=\"button\" class=\"chk checkbox_false_full\"></button>未勾选；<span class=\"highlight_red\">如果是父节点，则无子节点被勾选</span>。鼠标移到该节点上显示为：<button type=\"button\" class=\"chk checkbox_false_full_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk checkbox_false_part\"></button>未勾选；（只有父节点存在此状态）<span class=\"highlight_red\">存在被勾选的子节点</span>。鼠标移到该节点上显示为：<button type=\"button\" class=\"chk checkbox_false_part_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk checkbox_true_full\"></button>被勾选；<span class=\"highlight_red\">如果是父节点，则全部子节点都被勾选</span>。鼠标移到该节点上显示为：<button type=\"button\" class=\"chk checkbox_true_full_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk checkbox_true_part\"></button>被勾选；（只有父节点存在此状态）<span class=\"highlight_red\">且部分或无子节点被勾选</span>。鼠标移到该节点上显示为：<button type=\"button\" class=\"chk checkbox_true_part_focus\"></button></p>\n\t\t</div>\n\t</div>\n\t<h3>radio 状态说明</h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p><button type=\"button\" class=\"chk radio_false_full\"></button>未勾选；<span class=\"highlight_red\">如果是父节点，则没有子节点被勾选</span>。鼠标移到该节点上显示为：<button type=\"button\" class=\"chk radio_false_full_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk radio_false_part\"></button>未勾选；（只有父节点存在此状态）<span class=\"highlight_red\">且存在被勾选的子节点</span>。鼠标移到该节点上显示为：<button type=\"button\" class=\"chk radio_false_part_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk radio_true_full\"></button>被勾选；<span class=\"highlight_red\">如果是父节点，则没有子节点被勾选</span>。鼠标移到该节点上显示为：<button type=\"button\" class=\"chk radio_true_full_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk radio_true_part\"></button>被勾选；（只有父节点存在此状态）<span class=\"highlight_red\">且存在被勾选的子节点</span>。鼠标移到该节点上显示为：<button type=\"button\" class=\"chk radio_true_part_focus\"></button></p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置选择框为 radio</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tchkStyle: \"radio\"\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.check.chkboxType.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>JSON</span><span class=\"path\">setting.check.</span>chkboxType</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>勾选 checkbox 对于父子节点的关联关系。<span class=\"highlight_red\">[setting.check.enable = true 且 setting.check.chkStyle = \"checkbox\" 时生效]</span></p>\n\t\t\t<p>默认值：{ \"Y\": \"ps\", \"N\": \"ps\" }</p>\n\t\t</div>\n\t</div>\n\t<h3>JSON 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>Y 属性定义 checkbox 被勾选后的情况；\n<br/>N 属性定义 checkbox 取消勾选后的情况；\n<br/>\"p\" 表示操作会影响父级节点；\n<br/>\"s\" 表示操作会影响子级节点。</p>\n\t<p class=\"highlight_red\">请注意大小写，不要改变</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. checkbox 勾选操作，只影响父级节点；取消勾选操作，只影响子级节点</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tchkStyle: \"checkbox\",\n\t\tchkboxType: { \"Y\": \"p\", \"N\": \"s\" }\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.check.enable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.check.</span>enable</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置 zTree 的节点上是否显示 checkbox / radio</p>\n\t\t\t<p>默认值: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 显示 / 不显示 复选框或单选框</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 需要显示 checkbox</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.check.nocheckInherit.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.check.</span>nocheckInherit</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>当父节点设置 nocheck = true 时，设置子节点是否自动继承 nocheck = true 。<span class=\"highlight_red\">[setting.check.enable = true 时生效]</span></p>\n\t\t\t<p class=\"highlight_red\">1、只使用于初始化节点时，便于批量操作。 对于已存在的节点请利用 updateNode 方法单个节点设置。</p>\n\t\t\t<p>默认值: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示 新加入子节点时，自动继承父节点 nocheck = true 的属性。</p>\n\t<p> false 表示 新加入子节点时，不继承父节点 nocheck 的属性。</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 需要子节点自动继承 nocheck = true</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tnocheckInherit: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.check.radioType.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.check.</span>radioType</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>radio 的分组范围。<span class=\"highlight_red\">[setting.check.enable = true 且 setting.check.chkStyle = \"radio\" 时生效]</span></p>\n\t\t\t<p>默认值：\"level\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>radioType = \"level\" 时，在每一级节点范围内当做一个分组。\n<br/>radioType = \"all\" 时，在整棵树范围内当做一个分组。</p>\n\t<p class=\"highlight_red\">请注意大小写，不要改变</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 radio 的判别规则为整棵树内</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tchkStyle: \"radio\",\n\t\tradioType: \"all\"\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.keep.leaf.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.data.keep.</span>leaf</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 的节点叶子节点属性锁，是否始终保持 isParent = false</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 锁定 / 不锁定 叶子节点属性</p>\n\t<p class=\"highlight_red\">如果设置为 true，则所有 isParent = false 的节点，都无法添加子节点。</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 需要锁定叶子节点状态</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkeep: {\n\t\t\tleaf: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.keep.parent.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.data.keep.</span>parent</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 的节点父节点属性锁，是否始终保持 isParent = true</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 锁定 / 不锁定 父节点属性</p>\n\t<p class=\"highlight_red\">如果设置为 true，则所有 isParent = true 的节点，即使该节点的子节点被全部删除或移走，依旧保持父节点状态。</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 需要锁定父节点状态</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkeep: {\n\t\t\tparent: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.key.checked.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.key.</span>checked</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 节点数据中保存 check 状态的属性名称。</p>\n\t\t\t<p>默认值：\"checked\"</p>\n\t\t\t<p class=\"highlight_red\">请勿与 zTree 节点数据的其他参数冲突，例如：checkedOld</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 zTree 显示节点时，将 treeNode 的 isChecked 属性当做节点名称</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkey: {\n\t\t\tchecked: \"isChecked\"\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.key.children.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.key.</span>children</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 节点数据中保存子节点数据的属性名称。</p>\n\t\t\t<p>默认值：\"children\"</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 zTree 显示节点时，将 treeNode 的 nodes 属性当做节点名称</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkey: {\n\t\t\tchildren: \"nodes\"\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.key.name.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.key.</span>name</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 节点数据保存节点名称的属性名称。</p>\n\t\t\t<p>默认值：\"name\"</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 zTree 显示节点时，将 treeNode 的 ename 属性当做节点名称</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkey: {\n\t\t\tname: \"ename\"\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.key.title.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.key.</span>title</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 节点数据保存节点提示信息的属性名称。<span class=\"highlight_red\">[setting.view.showTitle = true 时生效]</span></p>\n\t\t\t<p class=\"highlight_red\">如果设置为 \"\" ，则自动与 setting.data.key.name 保持一致，避免用户反复设置</p>\n\t\t\t<p>默认值：\"\"</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 zTree 显示节点时，将 treeNode 的 fullName 属性当做节点名称</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkey: {\n\t\t\ttitle: \"fullName\"\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.key.url.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.key.</span>url</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 节点数据保存节点链接的目标 URL 的属性名称。</p>\n\t\t\t<p class=\"highlight_red\">特殊用途：当后台数据只能生成 url 属性，又不想实现点击节点跳转的功能时，可以直接修改此属性为其他不存在的属性名称</p>\n\t\t\t<p>默认值：\"url\"</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 zTree 显示节点时，将 treeNode 的 xUrl 属性当做节点链接的目标 URL</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkey: {\n\t\t\turl: \"xUrl\"\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.simpleData.enable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.data.simpleData.</span>enable</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>确定 zTree 初始化时的节点数据、异步加载时的节点数据、或 <span class=\"highlight_red\">addNodes</span> 方法中输入的 newNodes 数据是否采用简单数据模式 (Array)</p>\n\t\t\t<p>不需要用户再把数据库中取出的 List 强行转换为复杂的 JSON 嵌套格式</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 使用 / 不使用 简单数据模式</p>\n\t<p class=\"highlight_red\">如果设置为 true，请务必设置 setting.data.simpleData 内的其他参数: idKey / pIdKey / rootPId，并且让数据满足父子关系。</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 使用简单 Array 格式的数据</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"id\",\n\t\t\tpIdKey: \"pId\",\n\t\t\trootPId: 0\n\t\t}\n\t}\n};\nvar treeNodes = [\n    {\"id\":1, \"pId\":0, \"name\":\"test1\"},\n    {\"id\":11, \"pId\":1, \"name\":\"test11\"},\n    {\"id\":12, \"pId\":1, \"name\":\"test12\"},\n    {\"id\":111, \"pId\":11, \"name\":\"test111\"}\n];\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.simpleData.idKey.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.simpleData.</span>idKey</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>节点数据中保存唯一标识的属性名称。<span class=\"highlight_red\">[setting.data.simpleData.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：\"id\"</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 使用简单 Array 格式的数据</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"id\",\n\t\t\tpIdKey: \"pId\",\n\t\t\trootPId: 0\n\t\t}\n\t}\n};\nvar treeNodes = [\n    {\"id\":1, \"pId\":0, \"name\":\"test1\"},\n    {\"id\":11, \"pId\":1, \"name\":\"test11\"},\n    {\"id\":12, \"pId\":1, \"name\":\"test12\"},\n    {\"id\":111, \"pId\":11, \"name\":\"test111\"}\n];\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.simpleData.pIdKey.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.simpleData.</span>pIdKey</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>节点数据中保存其父节点唯一标识的属性名称。<span class=\"highlight_red\">[setting.data.simpleData.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：\"pId\"</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 使用简单 Array 格式的数据</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"id\",\n\t\t\tpIdKey: \"pId\",\n\t\t\trootPId: 0\n\t\t}\n\t}\n};\nvar treeNodes = [\n    {\"id\":1, \"pId\":0, \"name\":\"test1\"},\n    {\"id\":11, \"pId\":1, \"name\":\"test11\"},\n    {\"id\":12, \"pId\":1, \"name\":\"test12\"},\n    {\"id\":111, \"pId\":11, \"name\":\"test111\"}\n];\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.data.simpleData.rootPId.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String / Number</span><span class=\"path\">setting.data.simpleData.</span>rootPId</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于修正根节点父节点数据，即 pIdKey 指定的属性值。<span class=\"highlight_red\">[setting.data.simpleData.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 使用简单 Array 格式的数据</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"id\",\n\t\t\tpIdKey: \"pId\",\n\t\t\trootPId: 0\n\t\t}\n\t}\n};\nvar treeNodes = [\n    {\"id\":1, \"pId\":0, \"name\":\"test1\"},\n    {\"id\":11, \"pId\":1, \"name\":\"test11\"},\n    {\"id\":12, \"pId\":1, \"name\":\"test12\"},\n    {\"id\":111, \"pId\":11, \"name\":\"test111\"}\n];\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.autoExpandTrigger.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.edit.drag.</span>autoExpandTrigger</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>拖拽时父节点自动展开是否触发 onExpand 事件回调函数。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 触发 / 不触发 onExpand 事件回调函数。</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置拖拽时父节点自动展开触发 onExpand 事件回调函数</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tautoExpandTrigger: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.autoOpenTime.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">setting.edit.drag.</span>autoOpenTime</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>拖拽时父节点自动展开的延时间隔。 (单位：ms)<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：500</p>\n\t\t\t<p class=\"highlight_red\">请根据自己的需求适当调整此值</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置拖拽到父节点上立刻自动展开</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tautoOpenTime: 0\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.borderMax.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">setting.edit.drag.</span>borderMax</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>拖拽节点成为根节点时的 Tree 内边界范围 (单位：px)。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：10</p>\n\t\t\t<p class=\"highlight_red\">请根据自己的需求适当调整此值</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 更改拖拽操作节点成为根节点时的 Tree 内边界范围为20px</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tborderMax: 20\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.borderMin.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">setting.edit.drag.</span>borderMin</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>拖拽节点成为根节点时的 Tree 外边界范围 (单位：px)。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：-5</p>\n\t\t\t<p class=\"highlight_red\">请根据自己的需求适当调整此值</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 更改拖拽操作节点成为根节点时的 Tree 外边界范围为10px</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tborderMin: -10\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.inner.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNodes, targetNode)</span><span class=\"path\">setting.edit.drag.</span>inner</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>拖拽到目标节点时，设置是否允许成为目标节点的子节点。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p class=\"highlight_red\">拖拽目标是 根 的时候，不触发 prev 和 next，只会触发 inner</p>\n\t\t\t<p class=\"highlight_red\">此功能主要作用是对拖拽进行适当限制（辅助箭头），需要结合 prev、next 一起使用，才能实现完整功能。</p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 允许 / 不允许 成为目标节点的子节点</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控（多棵树拖拽时，是目标节点所在树的 treeId）</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>被拖拽的节点 JSON 数据集合</p>\n\t<h4 class=\"topLine\"><b>targetNode</b><span>JSON</span></h4>\n\t<p>拖拽时的目标节点 JSON 数据对象</p>\n\t<p class=\"highlight_red\">如果拖拽的节点要成为根节点，则 targetNode = null</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值同 Boolean 格式的数据</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止拖拽成为目标节点的子节点</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: true,\n\t\t\tnext: true,\n\t\t\tinner: false\n\t\t}\n\t}\n};\n......</code></pre>\n\t<h4>2. 禁止拖拽成为根节点的子节点</h4>\n\t<pre xmlns=\"\"><code>function canInner(treeId, nodes, targetNode) {\n\treturn !(targetNode && targetNode.level === 0);\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: true,\n\t\t\tnext: true,\n\t\t\tinner: canInner\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.isCopy.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.edit.drag.</span>isCopy</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>拖拽时, 设置是否允许复制节点。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>规则说明</h3>\n\t<div class=\"desc\">\n\t<p>1、isCopy = true; isMove = true 时，拖拽节点按下 Ctrl 或 Cmd 键表示 copy; 否则为 move</p>\n\t<p>2、isCopy = true; isMove = false 时，所有拖拽操作都是 copy</p>\n\t<p>3、isCopy = false; isMove = true 时，所有拖拽操作都是 move</p>\n\t<p>4、isCopy = false; isMove = false 时，禁止拖拽操作</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置所有拖拽操作都是 copy</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tisCopy: true,\n\t\t\tisMove: false\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.isMove.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.edit.drag.</span>isMove</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>拖拽时, 设置是否允许移动节点。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>规则说明</h3>\n\t<div class=\"desc\">\n\t<p>1、isCopy = true; isMove = true 时，拖拽节点按下 Ctrl 或 Cmd 键表示 copy; 否则为 move</p>\n\t<p>2、isCopy = true; isMove = false 时，所有拖拽操作都是 copy</p>\n\t<p>3、isCopy = false; isMove = true 时，所有拖拽操作都是 move</p>\n\t<p>4、isCopy = false; isMove = false 时，禁止拖拽操作</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置所有拖拽操作都是 move</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tisCopy: false,\n\t\t\tisMove: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.maxShowNodeNum.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">setting.edit.drag.</span>maxShowNodeNum</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>拖拽多个兄弟节点时，浮动图层中显示的最大节点数。 多余的节点用...代替。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p>默认值：5</p>\n\t\t\t<p class=\"highlight_red\">请根据自己的需求适当调整此值</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置拖拽时最多可显示10个节点</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tmaxShowNodeNum: 10\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.minMoveSize.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">setting.edit.drag.</span>minMoveSize</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>判定是否拖拽操作的最小位移值 (单位：px)。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p class=\"highlight_red\">根据自己的需求可适当调整此值，如果太小容易导致点击鼠标时误操作进行拖拽</p>\n\t\t\t<p>默认值：5</p>\n\t\t</div>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 更改拖拽操作启动位移值为10px</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tminMoveSize: 10\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.next.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNodes, targetNode)</span><span class=\"path\">setting.edit.drag.</span>next</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>拖拽到目标节点时，设置是否允许移动到目标节点后面的操作。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p class=\"highlight_red\">拖拽目标是 根 的时候，不触发 prev 和 next，只会触发 inner</p>\n\t\t\t<p class=\"highlight_red\">此功能主要作用是对拖拽进行适当限制（辅助箭头），需要结合 prev、inner 一起使用，才能实现完整功能。</p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 允许 / 不允许 移动到目标节点后面</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控（多棵树拖拽时，是目标节点所在树的 treeId）</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>被拖拽的节点 JSON 数据集合</p>\n\t<h4 class=\"topLine\"><b>targetNode</b><span>JSON</span></h4>\n\t<p>拖拽时的目标节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值同 Boolean 格式的数据</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止拖拽到节点后面的操作</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: true,\n\t\t\tnext: false,\n\t\t\tinner: true\n\t\t}\n\t}\n};\n......</code></pre>\n\t<h4>2. 禁止拖拽到父节点后面的操作</h4>\n\t<pre xmlns=\"\"><code>function canNext(treeId, nodes, targetNode) {\n\treturn !targetNode.isParent;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: true,\n\t\t\tnext: canNext,\n\t\t\tinner: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.drag.prev.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNodes, targetNode)</span><span class=\"path\">setting.edit.drag.</span>prev</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>拖拽到目标节点时，设置是否允许移动到目标节点前面的操作。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p class=\"highlight_red\">拖拽目标是 根 的时候，不触发 prev 和 next，只会触发 inner</p>\n\t\t\t<p class=\"highlight_red\">此功能主要作用是对拖拽进行适当限制（辅助箭头），需要结合 next、inner 一起使用，才能实现完整功能。</p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 允许 / 不允许 移动到目标节点前面</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控（多棵树拖拽时，是目标节点所在树的 treeId）</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>被拖拽的节点 JSON 数据集合</p>\n\t<h4 class=\"topLine\"><b>targetNode</b><span>JSON</span></h4>\n\t<p>拖拽时的目标节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值同 Boolean 格式的数据</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 禁止拖拽到节点前面的操作</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: false,\n\t\t\tnext: true,\n\t\t\tinner: true\n\t\t}\n\t}\n};\n......</code></pre>\n\t<h4>2. 禁止拖拽到父节点前面的操作</h4>\n\t<pre xmlns=\"\"><code>function canPrev(treeId, nodes, targetNode) {\n\treturn !targetNode.isParent;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: canPrev,\n\t\t\tnext: true,\n\t\t\tinner: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.editNameSelectAll.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.edit.</span>editNameSelectAll</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>节点编辑名称 input 初次显示时,设置 txt 内容是否为全选状态。 <span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p>默认值: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示 全选状态</p>\n\t<p> false 表示 不是全选状态，光标默认在最后</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置节点编辑名称 input 初次显示时，txt内容为全选状态</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\teditNameSelectAll: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.enable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.edit.</span>enable</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置 zTree 是否处于编辑状态</p>\n\t\t\t<p class=\"highlight_red\">请在初始化之前设置，初始化后需要改变编辑状态请使用 zTreeObj.setEditable() 方法</p>\n\t\t\t<p>默认值: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 可以 / 不可以 编辑</p>\n\t</div>\n\t<h3>编辑状态规则说明</h3>\n\t<div class=\"desc\">\n\t<p>1、点击节点时，不会打开 <span class=\"highlight_red\">node.url</span> 指定的 URL。\n<br/>2、全面支持 编辑 与 异步加载 状态共存。\n<br/>3、可以对节点进行拖拽，且支持多棵树之间进行拖拽。\n<br/>4、支持拖拽时 复制/移动 节点。（参考: <span class=\"highlight_red\">setting.edit.drag.isCopy / setting.edit.drag.isMove</span>）\n<br/>5、可以通过编辑按钮修改 name 属性。\n<br/>6、可以通过删除按钮删除节点。\n<br/>\n</p>\n\t<p class=\"highlight_red\">请注意大小写，不要改变</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 zTree 进入编辑状态</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.removeTitle.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String / Function(treeId, treeNode)</span><span class=\"path\">setting.edit.</span>removeTitle</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>删除按钮的 Title 辅助信息。<span class=\"highlight_red\">[setting.edit.enable = true & setting.edit.showRemoveBtn = true 时生效]</span></p>\n\t\t\t<p>默认值：\"remove\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>鼠标移动到 删除按钮 上时，浏览器自动弹出的辅助信息内容，可根据用户需要自行修改</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要设置删除按钮 Title 信息的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>String</span></h4>\n\t<p>返回值同 String 格式的数据</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 设置删除按钮的 Title 辅助信息为: \"删除节点\"</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRemoveBtn: true,\n\t\tremoveTitle: \"删除节点\"\n\t}\n};\n......</code></pre>\n\t<h4>2. 设置父节点删除按钮的 Title 辅助信息为: \"删除父节点\"</h4>\n\t<pre xmlns=\"\"><code>function setRemoveTitle(treeId, treeNode) {\n\treturn treeNode.isParent ? \"删除父节点\":\"删除叶子节点\";\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRemoveBtn: true,\n\t\tremoveTitle: setRemoveTitle\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.renameTitle.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String / Function(treeId, treeNode)</span><span class=\"path\">setting.edit.</span>renameTitle</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>编辑名称按钮的 Title 辅助信息。<span class=\"highlight_red\">[setting.edit.enable = true & setting.edit.showRenameBtn = true 时生效]</span></p>\n\t\t\t<p>默认值：\"rename\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>设置鼠标移动到 编辑名称按钮 上时，浏览器自动弹出的辅助信息内容，可根据用户需要自行修改</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要设置编辑名称按钮 Title 信息的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>String</span></h4>\n\t<p>返回值同 String 格式的数据</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 设置编辑名称按钮的 Title 辅助信息为: \"编辑节点名称\"</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRenameBtn: true,\n\t\trenameTitle: \"编辑节点名称\"\n\t}\n};\n......</code></pre>\n\t<h4>2. 设置父节点编辑名称按钮的 Title 辅助信息为: \"编辑父节点名称\"</h4>\n\t<pre xmlns=\"\"><code>function setRenameTitle(treeId, treeNode) {\n\treturn treeNode.isParent ? \"编辑父节点名称\":\"编辑叶子节点名称\";\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRenameBtn: true,\n\t\trenameTitle: setRenameTitle\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.showRemoveBtn.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNode)</span><span class=\"path\">setting.edit.</span>showRemoveBtn</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置是否显示删除按钮。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p>当点击某节点的删除按钮时：</p>\n\t\t\t<p>1、首先触发 <span class=\"highlight_red\">setting.callback.beforeRemove</span> 回调函数，用户可判定是否进行删除操作。</p>\n\t\t\t<p>2、如果未设置 beforeRemove 或 beforeRemove 返回 true，则删除节点并触发 <span class=\"highlight_red\">setting.callback.onRemove</span> 回调函数。</p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 显示 / 隐藏 删除按钮</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要设置是否显示删除按钮的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值同 Boolean 格式的数据</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 不显示删除按钮</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRemoveBtn: false\n\t}\n};\n......</code></pre>\n\t<h4>2. 设置所有的父节点不显示删除按钮</h4>\n\t<pre xmlns=\"\"><code>function setRemoveBtn(treeId, treeNode) {\n\treturn !treeNode.isParent;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRemoveBtn: setRemoveBtn\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.edit.showRenameBtn.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNode)</span><span class=\"path\">setting.edit.</span>showRenameBtn</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置是否显示编辑名称按钮。<span class=\"highlight_red\">[setting.edit.enable = true 时生效]</span></p>\n\t\t\t<p>当点击某节点的编辑名称按钮时：</p>\n\t\t\t<p>1、进入节点编辑名称状态。</p>\n\t\t\t<p>2、编辑名称完毕（Input 失去焦点 或 按下 Enter 键），会触发 <span class=\"highlight_red\">setting.callback.beforeRename</span> 回调函数，用户可根据自己的规则判定是否允许修改名称。</p>\n\t\t\t<p>3、如果 beforeRename 返回 false，则继续保持编辑名称状态，直到名称符合规则位置 （按下 ESC 键可取消编辑名称状态，恢复原名称）。</p>\n\t\t\t<p>4、如果未设置 beforeRename 或 beforeRename 返回 true，则结束节点编辑名称状态，更新节点名称，并触发 <span class=\"highlight_red\">setting.callback.onRename</span> 回调函数。</p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 显示 / 隐藏 编辑名称按钮</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要设置是否显示编辑名称按钮的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值同 Boolean 格式的数据</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 不显示编辑名称按钮</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRenameBtn: false\n\t}\n};\n......</code></pre>\n\t<h4>2. 设置所有的父节点不显示编辑名称按钮</h4>\n\t<pre xmlns=\"\"><code>function setRenameBtn(treeId, treeNode) {\n\treturn !treeNode.isParent;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRenameBtn: setRenameBtn\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.treeId.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.</span>treeId</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 的唯一标识，初始化后，等于 用户定义的 zTree 容器的 id 属性值。</p>\n\t\t\t<p class=\"highlight_red\">请勿进行初始化 或 修改，属于内部参数。</p>\n\t\t</div>\n\t</div>\n\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.treeObj.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Object</span><span class=\"path\">setting.</span>treeObj</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 容器的 jQuery 对象，主要功能：便于操作。</p>\n\t\t\t<p class=\"highlight_red\">请勿进行初始化 或 修改，属于内部参数。</p>\n\t\t</div>\n\t</div>\n\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.addDiyDom.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>addDiyDom</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于在节点上固定显示用户自定义控件</p>\n\t\t\t<p class=\"highlight_red\">1. 大数据量的节点加载请注意：在 addDiyDom 中针对每个节点 查找 DOM 对象并且添加新 DOM 控件，肯定会影响初始化性能；如果不是必须使用，建议不使用此功能</p>\n\t\t\t<p class=\"highlight_red\">2. 属于高级应用，使用时请确保对 zTree 比较了解。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要显示自定义控件的节点 JSON 数据对象</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 设置节点后面显示一个按钮</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\taddDiyDom: addDiyDom\n\t}\n};\nfunction addDiyDom(treeId, treeNode) {\n\tvar aObj = $(\"#\" + treeNode.tId + \"_a\");\n\tif ($(\"#diyBtn_\"+treeNode.id).length>0) return;\n\tvar editStr = \"&lt;span id='diyBtn_space_\" +treeNode.id+ \"' &gt; &lt;/span&gt;\"\n\t\t+ \"&lt;button type='button' class='diyBtn1' id='diyBtn_\" + treeNode.id\n\t\t+ \"' title='\"+treeNode.name+\"' onfocus='this.blur();'&gt;&lt;/button&gt;\";\n\taObj.append(editStr);\n\tvar btn = $(\"#diyBtn_\"+treeNode.id);\n\tif (btn) btn.bind(\"click\", function(){alert(\"diy Button for \" + treeNode.name);});\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.addHoverDom.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>addHoverDom</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于当鼠标移动到节点上时，显示用户自定义控件，显示隐藏状态同 zTree 内部的编辑、删除按钮</p>\n\t\t\t<p class=\"highlight_red\">请务必与 <span class=\"highlight_red\">setting.view.removeHoverDom</span> 同时使用；属于高级应用，使用时请确保对 zTree 比较了解。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要显示自定义控件的节点 JSON 数据对象</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 设置鼠标移到节点上，在后面显示一个按钮</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\taddHoverDom: addHoverDom,\n\t\tremoveHoverDom: removeHoverDom,\n\t\t......\n\t}\n};\nfunction addHoverDom(treeId, treeNode) {\n\tvar aObj = $(\"#\" + treeNode.tId + \"_a\");\n\tif ($(\"#diyBtn_\"+treeNode.id).length>0) return;\n\tvar editStr = \"&lt;span id='diyBtn_space_\" +treeNode.id+ \"' &gt;&nbsp;&lt;/span&gt;\"\n\t\t+ \"&lt;button type='button' class='diyBtn1' id='diyBtn_\" + treeNode.id\n\t\t+ \"' title='\"+treeNode.name+\"' onfocus='this.blur();'&gt;&lt;/button&gt;\";\n\taObj.append(editStr);\n\tvar btn = $(\"#diyBtn_\"+treeNode.id);\n\tif (btn) btn.bind(\"click\", function(){alert(\"diy Button for \" + treeNode.name);});\n};\nfunction removeHoverDom(treeId, treeNode) {\n\t$(\"#diyBtn_\"+treeNode.id).unbind().remove();\n\t$(\"#diyBtn_space_\" +treeNode.id).unbind().remove();\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.autoCancelSelected.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.view.</span>autoCancelSelected</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>点击节点时，按下 Ctrl 或 Cmd 键是否允许取消选择操作。</p>\n\t\t\t<p class=\"highlight_red\">如果不需要此功能，请设置为 false。</p>\n\t\t\t<p>默认值: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 支持 / 不支持 配合 Ctrl 或 Cmd 键进行取消节点选择的操作</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 禁止配合 Ctrl 或 Cmd 键进行取消节点选择的操作</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tautoCancelSelected: false\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.dblClickExpand.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>dblClickExpand</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>双击节点时，是否自动展开父节点的标识</p>\n\t\t\t<p>默认值: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示双击节点 切换 / 不切换 展开状态</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要设置是否双击切换展开状态的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值同 Boolean 格式的数据</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 取消默认双击展开父节点的功能</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tdblClickExpand: false\n\t}\n};\n......</code></pre>\n\t<h4>2. 设置 zTree 仅仅 level=0 的父节点取消双击展开的功能</h4>\n\t<pre xmlns=\"\"><code>function dblClickExpand(treeId, treeNode) {\n\treturn treeNode.level > 0;\n};\nvar setting = {\n\tview: {\n\t\tdblClickExpand: dblClickExpand\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.expandSpeed.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String / Number</span><span class=\"path\">setting.view.</span>expandSpeed</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 节点展开、折叠时的动画速度，设置方法同 JQuery 动画效果中 speed 参数。</p>\n\t\t\t<p class=\"highlight_red\">IE6 下会自动关闭动画效果，以保证 zTree 的操作速度</p>\n\t\t\t<p>默认值：\"fast\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>三种预定速度之一的字符串(\"slow\", \"normal\", or \"fast\")</p>\n\t<p class=\"highlight_red\">设置为 \"\" 时，不显示动画效果</p>\n\t</div>\n\t<h3>Number 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>表示动画时长的毫秒数值 (如：1000)</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置为慢速显示动画效果</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\texpandSpeed: \"slow\"\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.fontCss.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>JSON / Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>fontCss</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>个性化文字样式，只针对 zTree 在节点上显示的&lt;A&gt;对象。</p>\n\t\t\t<p>默认值：{}</p>\n\t\t</div>\n\t</div>\n\t<h3>JSON 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>JSON 格式为 JQuery css方法中的 JSON 对象格式，例如：<span class=\"highlight_red\">{color:\"#ff0011\", background:\"blue\"}</span></p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要设置自定义样式的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>JSON</span></h4>\n\t<p>返回值同 JSON 格式的数据，例如：<span class=\"highlight_red\">{color:\"#ff0011\", background:\"blue\"}</span></p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 不修改CSS，设置全部节点 name 显示为红色</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tfontCss : {color:\"red\"}\n\t}\n};</code></pre>\n\t<h4>2. 设置 level=0 的节点 name 显示为红色</h4>\n\t<pre xmlns=\"\"><code>function setFontCss(treeId, treeNode) {\n\treturn treeNode.level == 0 ? {color:\"red\"} : {};\n};\nvar setting = {\n\tview: {\n\t\tfontCss: setFontCss\n\t}\n};</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.nameIsHTML.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.view.</span>nameIsHTML</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置 name 属性是否支持 HTML 脚本</p>\n\t\t\t<p class=\"highlight_red\">如果允许 HTML 脚本，请根据自己的需求做校验，避免出现 js 注入等安全问题。</p>\n\t\t\t<p>默认值: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 支持 / 不支持 HTML 脚本</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 name 属性支持 HTML 脚本</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tnameIsHTML: true\n\t}\n};\nvar node = {\"name\":\"&lt;font color='red'&gt;test&lt;/font&gt;\"};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.removeHoverDom.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>removeHoverDom</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于当鼠标移出节点时，隐藏用户自定义控件，显示隐藏状态同 zTree 内部的编辑、删除按钮</p>\n\t\t\t<p class=\"highlight_red\">请务必与 <span class=\"highlight_red\">addHoverDom</span> 同时使用；属于高级应用，使用时请确保对 zTree 比较了解。</p>\n\t\t\t<p>默认值：null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要隐藏自定义控件的节点 JSON 数据对象</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 设置鼠标移到节点上，在后面显示一个按钮</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\taddHoverDom: addHoverDom,\n\t\tremoveHoverDom: removeHoverDom,\n\t\t......\n\t}\n};\nfunction addHoverDom(treeId, treeNode) {\n\tvar aObj = $(\"#\" + treeNode.tId + \"_a\");\n\tif ($(\"#diyBtn_\"+treeNode.id).length>0) return;\n\tvar editStr = \"&lt;span id='diyBtn_space_\" +treeNode.id+ \"' &gt;&nbsp;&lt;/span&gt;\"\n\t\t+ \"&lt;button type='button' class='diyBtn1' id='diyBtn_\" + treeNode.id\n\t\t+ \"' title='\"+treeNode.name+\"' onfocus='this.blur();'&gt;&lt;/button&gt;\";\n\taObj.append(editStr);\n\tvar btn = $(\"#diyBtn_\"+treeNode.id);\n\tif (btn) btn.bind(\"click\", function(){alert(\"diy Button for \" + treeNode.name);});\n};\nfunction removeHoverDom(treeId, treeNode) {\n\t$(\"#diyBtn_\"+treeNode.id).unbind().remove();\n\t$(\"#diyBtn_space_\" +treeNode.id).unbind().remove();\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.selectedMulti.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.view.</span>selectedMulti</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置是否允许同时选中多个节点。</p>\n\t\t\t<p>默认值: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 支持 / 不支持 同时选中多个节点</p>\n\t<p class=\"highlight_red\">1、设置为 true时，按下 Ctrl 或 Cmd 键可以选中多个节点</p>\n\t<p class=\"highlight_red\">2、设置为 true / false 都不影响按下 Ctrl 或 Cmd 键可以让已选中的节点取消选中状态（ 取消选中状态可以参考 setting.view.autoCancelSelected ）</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 禁止多点同时选中的功能</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tselectedMulti: false\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.showIcon.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>showIcon</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置 zTree 是否显示节点的图标。</p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 显示 / 隐藏 图标</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要设置是否显示图标的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值同 Boolean 格式的数据</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 设置 zTree 不显示图标</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tshowIcon: false\n\t}\n};\n......</code></pre>\n\t<h4>2. 设置 zTree 仅仅 level=2 的节点不显示图标</h4>\n\t<pre xmlns=\"\"><code>function showIconForTree(treeId, treeNode) {\n\treturn treeNode.level != 2;\n};\nvar setting = {\n\tview: {\n\t\tshowIcon: showIconForTree\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.showLine.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.view.</span>showLine</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置 zTree 是否显示节点之间的连线。</p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 显示 / 不显示 连线</p>\n\t</div>\n\t<h3>setting 举例</h3>\n\t<h4>1. 设置 zTree 不显示节点之间的连线</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tshowLine: false\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.showTitle.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>showTitle</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置 zTree 是否显示节点的 title 提示信息(即节点 DOM 的 title 属性)。</p>\n\t\t\t<p class=\"highlight_red\">请务必与 <span class=\"highlight_red\">setting.data.key.title</span> 同时使用。</p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 显示 / 隐藏 提示信息</p>\n\t<p class=\"highlight_red\">如果 setting.view.showTitle = true & setting.data.key.title = ''，zTree 会自动使用 setting.data.key.name 指定的节点名称当做 title</p>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>对应 zTree 的 <b class=\"highlight_red\">treeId</b>，便于用户操控</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要设置是否显示提示信息的节点 JSON 数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值同 Boolean 格式的数据</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 设置 zTree 不显示提示信息</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tshowTitle: false\n\t}\n};\n......</code></pre>\n\t<h4>2. 设置 zTree 仅仅 level=2 的节点不显示提示信息</h4>\n\t<pre xmlns=\"\"><code>function showTitleForTree(treeId, treeNode) {\n\treturn treeNode.level != 2;\n};\nvar setting = {\n\tview: {\n\t\tshowTitle: showTitleForTree\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/setting.view.txtSelectedEnable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.view.</span>txtSelectedEnable</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置 zTree 是否允许可以选择 zTree DOM 内的文本。</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true / false 分别表示 允许 / 不允许 选择 zTree Dom 内的文本</p>\n\t</div>\n\t<h3>setting & function 举例</h3>\n\t<h4>1. 设置 zTree 允许选择文本</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\ttxtSelectedEnable: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.check_Child_State.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">treeNode.</span>check_Child_State</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于设置节点的子节点的 checkBox / radio 的半选状态。<span class=\"highlight_red\">[setting.check.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">v3.x 针对节点数据对象提供 treeNode.getCheckStatus() 方法获取标准的半选状态</p>\n\t\t\t<p class=\"highlight_red\">zTree 内部使用，请勿进行初始化 或 随意修改</p>\n\t\t\t<p>默认值：true</p>\n\t\t</div>\n\t</div>\n\t<h3>Number 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>规则如下：</p>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead>\n\t\t\t<tr><td colspan=\"4\">setting.check.checkType = \"checkbox\"</td></tr>\n\t\t\t<tr><td>treeNode.check_Child_State</td><td>勾选状态说明</td></tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<tr><td>-1</td><td>不存在子节点 或 子节点全部设置为 nocheck = true</td></tr>\n\t\t\t<tr><td>0</td><td>无 子节点被勾选</td></tr>\n\t\t\t<tr><td>1</td><td>部分 子节点被勾选</td></tr>\n\t\t\t<tr><td>2</td><td>全部 子节点被勾选</td></tr>\n\t\t</tbody>\n\t</table>\n\t<br/>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead>\n\t\t\t<tr><td colspan=\"4\">setting.check.checkType = \"radio\"</td></tr>\n\t\t\t<tr><td>treeNode.check_Child_State</td><td>勾选状态说明</td></tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<tr><td>-1</td><td>不存在子节点 或 子节点全部设置为 nocheck = true</td></tr>\n\t\t\t<tr><td>0</td><td>无 子节点被勾选</td></tr>\n\t\t\t<tr><td>2</td><td>有 子节点被勾选</td></tr>\n\t\t</tbody>\n\t</table>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.check_Focus.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>check_Focus</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于设置节点的 checkBox / radio 的 focus 状态。<span class=\"highlight_red\">[setting.check.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">zTree 内部使用，请勿进行初始化 或 随意修改</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>true 表示当前鼠标移动到输入框内</p>\n\t<p>false 表示当前鼠标移动到输入框外</p>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.checked.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>checked</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>节点的 checkBox / radio 的 勾选状态。<span class=\"highlight_red\">[setting.check.enable = true & treeNode.nocheck = false 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">1、如果不使用 checked 属性设置勾选状态，请修改 setting.data.key.checked </p>\n\t\t\t<p class=\"highlight_red\">2、建立 treeNode 数据时设置 treeNode.checked = true 可以让节点的输入框默认为勾选状态</p>\n\t\t\t<p class=\"highlight_red\">3、修改节点勾选状态，可以使用 treeObj.checkNode / checkAllNodes / updateNode 方法，具体使用哪种请根据自己的需求而定</p>\n\t\t\t<p class=\"highlight_red\">4、为了解决部分朋友生成 json 数据出现的兼容问题, 支持 \"false\",\"true\" 字符串格式的数据</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>true 表示节点的输入框被勾选</p>\n\t<p>false 表示节点的输入框未勾选</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 初始化的数据设置 默认为勾选状态</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n{ \"id\":1, \"name\":\"test1\", checked:true },\n{ \"id\":2, \"name\":\"test2\", checked:true }\n]</code></pre>\n\t<h4>2. 获取第一个根节点的勾选状态</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar checked = treeObj.getNodes()[0].checked;\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.checkedOld.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>checkedOld</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>节点的 checkBox / radio 在初始化时的 勾选状态。<span class=\"highlight_red\">[setting.check.enable = true & treeNode.nocheck = false 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">1、zTree 初始化节点数据时会对此属性进行赋值，因此请勿对此属性初始化</p>\n\t\t\t<p class=\"highlight_red\">2、如需配合 zTreeObj.getChangeCheckedNodes 方法实现特殊功能，可以根据需求在使用中自行修改 checkedOld 数据</p>\n\t\t\t<p>默认值：checked的初始化值</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>true 表示节点初始化时 输入框被勾选</p>\n\t<p>false 表示节点初始化时 输入框未勾选</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 获取第一个根节点的初始勾选状态</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar checkedOld = treeObj.getNodes()[0].checkedOld;\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.children.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Array(JSON)</span><span class=\"path\">treeNode.</span>children</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>节点的子节点数据集合。</p>\n\t\t\t<p class=\"highlight_red\">1、如果不使用 children 属性保存子节点数据，请修改 setting.data.key.children </p>\n\t\t\t<p class=\"highlight_red\">2、异步加载时，对于设置了 isParent = true 的节点，在展开时将进行异步加载</p>\n\t\t\t<p>默认值：无</p>\n\t\t</div>\n\t</div>\n\t<h3>Array(JSON) 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>标准的 JSON 数据对象</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 初始化的标准嵌套格式的 JSON 数据对象</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n{ \"id\":1, \"name\":\"test1\",\n\tchildren: [\n\t{ \"id\":3, \"name\":\"test3\"},\n\t{ \"id\":4, \"name\":\"test4\"},\n\t{ \"id\":5, \"name\":\"test5\"}\n\t]\n},\n{ \"id\":2, \"name\":\"test2\"  }\n]</code></pre>\n\t<h4>2. 获取第一个根节点的子节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes()[0].children;\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.chkDisabled.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>chkDisabled</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>1、设置节点的 checkbox / radio 是否禁用 <span class=\"highlight_red\">[setting.check.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">2、为了解决部分朋友生成 json 数据出现的兼容问题, 支持 \"false\",\"true\" 字符串格式的数据</p>\n\t\t\t<p class=\"highlight_red\">3、请勿对已加载的节点修改此属性，禁止 或 取消禁止 请使用 setChkDisabled() 方法</p>\n\t\t\t<p class=\"highlight_red\">4、初始化时，如果需要子孙节点继承父节点的 chkDisabled 属性，请设置 setting.check.chkDisabledInherit 属性</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p class=\"highlight_red\">true 表示此节点的 checkbox / radio 被禁用。</p>\n\t<p class=\"highlight_red\">false 表示此节点的 checkbox / radio 可以使用。</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 禁用节点 checkbox / radio </h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"test1\", \"checked\":true, \"chkDisabled\":true},\n\t{ \"id\":2, \"name\":\"test2\", \"chkDisabled\":true},\n\t{ \"id\":3, \"name\":\"test3\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.click.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>click</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>最简单的 click 事件操作。相当于 onclick=\"...\" 的内容。 如果操作较复杂，请使用 onClick 事件回调函数。</p>\n\t\t\t<p class=\"highlight_red\">由于 IE 对于 onclick 和 click事件共存时的处理与其他浏览器不同，所以请不要利用此参数控制是否允许跳转的操作（例如：treeNode.click = \"return false;\"）。如有类似需求，请不要使用 url 属性设置网址，同时利用 onClick 回调函数控制跳转。</p>\n\t\t\t<p>默认值：无</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>标准 javascript 语法， 例如：alert(\"test\"); 等</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 设置某节点点击时，弹出信息框</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"Google CN\", \"url\":\"http://g.cn\", \"click\":\"alert('test');\"},\n\t......\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.diy.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>?</span><span class=\"path\">treeNode.</span>* DIY *</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于保存节点的其他自定义数据信息，不要与 zTree 使用的属性相同即可，用户可随意设定。</p>\n\t\t</div>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 设置节点的备用英文名称</h4>\n\t<pre xmlns=\"\"><code>var node = { \"id\":1, \"name\":\"test1\", \"ename\":\"test eName\"};</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.editNameFlag.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>editNameFlag</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>用于记录节点是否处于编辑名称状态。<span class=\"highlight_red\">[setting.edit.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">zTree 内部使用，请勿进行初始化 或 随意修改</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>true 表示节点处于编辑名称状态</p>\n\t<p>false 表示节点未处于编辑名称状态</p>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.getCheckStatus.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">treeNode.</span>getCheckStatus</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>获取节点 checkbox / radio 半勾选状态。<span class=\"highlight_red\">[setting.check.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>返回值</b><span>JSON</span></h4>\n\t<pre xmlns=\"\"><code>{\n\tchecked: true, //等同于 treeNode.checked\n\thalf: true  //规则见下表\n}</code></pre>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead>\n\t\t\t<tr><td colspan=\"4\">setting.check.checkType = \"checkbox\"</td></tr>\n\t\t\t<tr><td>treeNode.checked</td><td>treeNode.check_Child_State</td><td>treeNode.halfCheck</td><td> half </td></tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<tr><td>-</td><td>-</td><td>true</td><td>true</td></tr>\n\t\t\t<tr><td colspan=\"4\">&nbsp;</td></tr>\n\t\t\t<tr><td>true</td><td>-1</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>true</td><td>0</td><td>false</td><td>true</td></tr>\n\t\t\t<tr><td>true</td><td>1</td><td>false</td><td>true</td></tr>\n\t\t\t<tr><td>true</td><td>2</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td colspan=\"4\">&nbsp;</td></tr>\n\t\t\t<tr><td>false</td><td>-1</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>false</td><td>0</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>false</td><td>1</td><td>false</td><td>true</td></tr>\n\t\t\t<tr><td>false</td><td>2</td><td>false</td><td>true</td></tr>\n\t\t</tbody>\n\t</table>\n\t<br/>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead>\n\t\t\t<tr><td colspan=\"4\">setting.check.checkType = \"radio\"</td></tr>\n\t\t\t<tr><td>treeNode.checked</td><td>treeNode.check_Child_State</td><td>treeNode.halfCheck</td><td> half </td></tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<tr><td>-</td><td>-</td><td>true</td><td>true</td></tr>\n\t\t\t<tr><td colspan=\"4\">&nbsp;</td></tr>\n\t\t\t<tr><td>true</td><td>-1</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>true</td><td>0</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>true</td><td>2</td><td>false</td><td>true</td></tr>\n\t\t\t<tr><td colspan=\"4\">&nbsp;</td></tr>\n\t\t\t<tr><td>false</td><td>-1</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>false</td><td>0</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>false</td><td>2</td><td>false</td><td>true</td></tr>\n\t\t</tbody>\n\t</table>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 获取第一个根节点的半选状态</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar halfCheck = treeObj.getNodes()[0].getCheckStatus();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.getNextNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">treeNode.</span>getNextNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>获取与 treeNode 节点相邻的后一个节点。</p>\n\t\t\t<p class=\"highlight_red\">初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>返回值</b><span>JSON</span></h4>\n\t<p>与 treeNode 节点相邻的后一个节点。</p>\n\t<p class=\"highlight_red\">如果 treeNode 是最后一个节点，返回 null 。</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 获取当前被选中的节点的下一个节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar node = sNodes[0].getNextNode();\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.getParentNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">treeNode.</span>getParentNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>获取 treeNode 节点的父节点。</p>\n\t\t\t<p class=\"highlight_red\">初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>返回值</b><span>JSON</span></h4>\n\t<p> treeNode 节点的父节点 JSON 数据对象。</p>\n\t<p class=\"highlight_red\">如果 treeNode 是根节点，返回 null 。</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 获取当前被选中的节点的父节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar node = sNodes[0].getParentNode();\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.getPreNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">treeNode.</span>getPreNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>获取与 treeNode 节点相邻的前一个节点。</p>\n\t\t\t<p class=\"highlight_red\">初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>返回值</b><span>JSON</span></h4>\n\t<p>与 treeNode 节点相邻的前一个节点。</p>\n\t<p class=\"highlight_red\">如果 treeNode 是第一个节点，返回 null 。</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 获取当前被选中的节点的前一个节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar node = sNodes[0].getPreNode();\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.halfCheck.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>halfCheck</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>强制节点的 checkBox / radio 的 半勾选状态。<span class=\"highlight_red\">[setting.check.enable = true & treeNode.nocheck = false 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">1、强制为半勾选状态后，不再进行自动计算半勾选状态</p>\n\t\t\t<p class=\"highlight_red\">2、设置 treeNode.halfCheck = false 或 null 才能恢复自动计算半勾选状态</p>\n\t\t\t<p class=\"highlight_red\">3、为了解决部分朋友生成 json 数据出现的兼容问题, 支持 \"false\",\"true\" 字符串格式的数据</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>true 表示节点的输入框 强行设置为半勾选</p>\n\t<p>false 表示节点的输入框 根据 zTree 的规则自动计算半勾选状态</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 初始化的数据设置 默认为半勾选状态</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n{ \"id\":1, \"name\":\"test1\", isParent:true, checked:true, halfCheck:true },\n{ \"id\":2, \"name\":\"test2\", isParent:true, checked:false, halfCheck:true },\n{ \"id\":3, \"name\":\"test3\", isParent:true, checked:true },\n{ \"id\":4, \"name\":\"test4\", isParent:true, checked:false }\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.icon.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>icon</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>节点自定义图标的 URL 路径。</p>\n\t\t\t<p class=\"highlight_red\">1、父节点如果只设置 icon ，会导致展开、折叠时都使用同一个图标</p>\n\t\t\t<p class=\"highlight_red\">2、父节点展开、折叠使用不同的个性化图标需要同时设置 treeNode.iconOpen / treeNode.iconClose 两个属性</p>\n\t\t\t<p class=\"highlight_red\">3、如果想利用 className 设置个性化图标，需要设置 treeNode.iconSkin 属性</p>\n\t\t\t<p>默认值：无</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>图标图片的 url 可以是相对路径也可以是绝对路径</p>\n\t<p class=\"highlight_red\">设置相对路径请注意页面与图片之间的关系，确保图片能够正常加载</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 设置节点的个性化图标</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t//父节点展开 折叠时使用相同的图标\n\t{ name:\"父节点1\", icon:\"/img/parent.gif\"},\n\n\t//父节点展开 折叠时分别使用不同的图标\n\t{ name:\"父节点2\", iconOpen:\"/img/open.gif\", iconClose:\"/img/close.gif\"}, \n\n\t//叶子节点个性化图标\n\t{ name:\"叶子节点\", icon:\"/img/leaf.gif\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.iconClose.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>iconClose</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>父节点自定义折叠时图标的 URL 路径。</p>\n\t\t\t<p class=\"highlight_red\">1、此属性只针对父节点有效</p>\n\t\t\t<p class=\"highlight_red\">2、此属性必须与 iconOpen 同时使用</p>\n\t\t\t<p class=\"highlight_red\">3、如果想利用 className 设置个性化图标，需要设置 treeNode.iconSkin 属性</p>\n\t\t\t<p>默认值：无</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>图标图片的 url 可以是相对路径也可以是绝对路径</p>\n\t<p class=\"highlight_red\">设置相对路径请注意页面与图片之间的关系，确保图片能够正常加载</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 设置节点的个性化图标</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t//父节点展开 折叠时使用相同的图标\n\t{ name:\"父节点1\", icon:\"/img/parent.gif\"},\n\n\t//父节点展开 折叠时分别使用不同的图标\n\t{ name:\"父节点2\", iconOpen:\"/img/open.gif\", iconClose:\"/img/close.gif\"}, \n\n\t//叶子节点个性化图标\n\t{ name:\"叶子节点\", icon:\"/img/leaf.gif\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.iconOpen.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>iconOpen</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>父节点自定义展开时图标的 URL 路径。</p>\n\t\t\t<p class=\"highlight_red\">1、此属性只针对父节点有效</p>\n\t\t\t<p class=\"highlight_red\">2、此属性必须与 iconClose 同时使用</p>\n\t\t\t<p class=\"highlight_red\">3、如果想利用 className 设置个性化图标，需要设置 treeNode.iconSkin 属性</p>\n\t\t\t<p>默认值：无</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>图标图片的 url 可以是相对路径也可以是绝对路径</p>\n\t<p class=\"highlight_red\">设置相对路径请注意页面与图片之间的关系，确保图片能够正常加载</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 设置节点的个性化图标</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t//父节点展开 折叠时使用相同的图标\n\t{ name:\"父节点1\", icon:\"/img/parent.gif\"},\n\n\t//父节点展开 折叠时分别使用不同的图标\n\t{ name:\"父节点2\", iconOpen:\"/img/open.gif\", iconClose:\"/img/close.gif\"}, \n\n\t//叶子节点个性化图标\n\t{ name:\"叶子节点\", icon:\"/img/leaf.gif\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.iconSkin.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>iconSkin</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>节点自定义图标的 className</p>\n\t\t\t<p class=\"highlight_red\">1、需要修改 css，增加相应 className 的设置</p>\n\t\t\t<p class=\"highlight_red\">2、css 方式简单、方便，并且同时支持父节点展开、折叠状态切换图片</p>\n\t\t\t<p class=\"highlight_red\">3、css 建议采用图片分割渲染的方式以减少反复加载图片，并且避免图片闪动</p>\n\t\t\t<p class=\"highlight_red\">4、zTree v3.x 的 iconSkin 同样支持 IE6</p>\n\t\t\t<p class=\"highlight_red\">5、如果想直接使用 图片的Url路径 设置节点的个性化图标，需要设置 treeNode.icon / treeNode.iconOpen / treeNode.iconClose 属性</p>\n\t\t\t<p>默认值：无</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>设置个性图标的 className</p>\n\t</div>\n\t<h3>css & treeNode 举例</h3>\n\t<h4>1. 设置节点的个性化图标</h4>\n\t<pre xmlns=\"\"><code>css 内容：\n.ztree li span.button.diy01_ico_open, .ztree li span.button.diy01_ico_close{...}\n\n.ztree li span.button.diy02_ico_open{...}\n.ztree li span.button.diy02_ico_close{...}\n\n.ztree li span.button.diy03_ico_docu{...}\n\njs中节点数据：\nvar nodes = [\n\t//父节点展开 折叠时使用相同的图标\n\t{ name:\"父节点1\", iconSkin:\"diy01\"},\n\n\t//父节点展开 折叠时分别使用不同的图标\n\t{ name:\"父节点2\", iconSkin:\"diy02\"},\n\n\t//叶子节点个性化图标\n\t{ name:\"叶子节点\", iconSkin:\"diy03\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.isAjaxing.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isAjaxing</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>记录 treeNode 节点是否正在进行异步加载。</p>\n\t\t\t<p class=\"highlight_red\">初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示节点正在进行异步加载</p>\n\t<p> false 表示节点没有进行异步加载</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 查看当前被选中的节点是否节点正在进行异步加载</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar isAjaxing = sNodes[0].isAjaxing;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.isFirstNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isFirstNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>记录 treeNode 节点是否为同级节点中的第一个节点。</p>\n\t\t\t<p class=\"highlight_red\">使用 exhide 扩展后，只针对显示的节点设置此属性</p>\n\t\t\t<p class=\"highlight_red\">初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示是同级节点中的第一个节点</p>\n\t<p> false 表示不是同级节点中的第一个节点</p>\n\t<p class=\"highlight_red\">节点被隐藏后，isFirstNode = false</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 查看当前被选中的节点是否是同级节点中的第一个节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar isFirstNode = sNodes[0].isFirstNode;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.isHidden.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isHidden</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exhide</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>判断 treeNode 节点是否被隐藏。</p>\n\t\t\t<p class=\"highlight_red\">1、初始化 zTree 时，如果节点设置 isHidden = true，会被自动隐藏</p>\n\t\t\t<p class=\"highlight_red\">2、请勿对已加载的节点修改此属性，隐藏 / 显示 请使用 hideNode() / hideNodes() / showNode() / showNodes() 方法</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示被隐藏</p>\n\t<p> false 表示被显示</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 查看第一个根节点是否被隐藏</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getNodes();\nif (sNodes.length > 0) {\n\tvar isHidden = sNodes[0].isHidden;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.isHover.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isHover</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>记录节点 的 hover 状态，主要用于 setting.view.addHoverDom / removeHoverDom 。</p>\n\t\t\t<p class=\"highlight_red\">zTree 内部使用，请勿进行初始化 或 随意修改</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>true 表示节点处于 hover 状态</p>\n\t<p>false 表示节点未处于 hover 状态</p>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.isLastNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isLastNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>记录 treeNode 节点是否为同级节点中的最后一个节点。</p>\n\t\t\t<p class=\"highlight_red\">使用 exhide 扩展后，只针对显示的节点设置此属性</p>\n\t\t\t<p class=\"highlight_red\">初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示是同级节点中的最后一个节点</p>\n\t<p> false 表示不是同级节点中的最后一个节点</p>\n\t<p class=\"highlight_red\">节点被隐藏后，isLastNode = false</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 查看当前被选中的节点是否是同级节点中的最后一个节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar isLastNode = sNodes[0].isLastNode;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.isParent.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isParent</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>记录 treeNode 节点是否为父节点。</p>\n\t\t\t<p class=\"highlight_red\">1、初始化节点数据时，根据 treeNode.children 属性判断，有子节点则设置为 true，否则为 false</p>\n\t\t\t<p class=\"highlight_red\">2、初始化节点数据时，如果设定 treeNode.isParent = true，即使无子节点数据，也会设置为父节点</p>\n\t\t\t<p class=\"highlight_red\">3、为了解决部分朋友生成 json 数据出现的兼容问题, 支持 \"false\",\"true\" 字符串格式的数据</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示是父节点</p>\n\t<p> false 表示不是父节点</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 查看当前被选中的节点是否是父节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar isParent = sNodes[0].isParent;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.level.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">treeNode.</span>level</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>记录节点的层级</p>\n\t\t\t<p class=\"highlight_red\">初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t</div>\n\t</div>\n\t<h3>Number 格式说明</h3>\n\t<div class=\"desc\">\n\t<p class=\"highlight_red\">根节点 level = 0，依次递增</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 查看当前被选中的节点的级数</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar level = sNodes[0].level;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.name.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>name</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>节点名称。</p>\n\t\t\t<p class=\"highlight_red\">1、如果不使用 name 属性保存节点名称，请修改 setting.data.key.name </p>\n\t\t\t<p>默认值：无</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>节点显示的名称字符串，标准 String 即可，所有特殊字符都会被自动转义</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 设置节点的名称为 test1、test2、test3</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"test1\"},\n\t{ \"id\":2, \"name\":\"test2\"},\n\t{ \"id\":3, \"name\":\"test3\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.nocheck.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>nocheck</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>1、设置节点是否隐藏 checkbox / radio <span class=\"highlight_red\">[setting.check.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">2、为了解决部分朋友生成 json 数据出现的兼容问题, 支持 \"false\",\"true\" 字符串格式的数据</p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p class=\"highlight_red\">true 表示此节点不显示 checkbox / radio，不影响勾选的关联关系，不影响父节点的半选状态。</p>\n\t<p class=\"highlight_red\">false 表示节点具有正常的勾选功能</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 不显示某个节点的 checkbox / radio </h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"test1\", \"nocheck\":true},\n\t{ \"id\":2, \"name\":\"test2\"},\n\t{ \"id\":3, \"name\":\"test3\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.open.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>open</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>记录 treeNode 节点的 展开 / 折叠 状态。</p>\n\t\t\t<p class=\"highlight_red\">1、初始化节点数据时，如果设定 treeNode.open = true，则会直接展开此节点</p>\n\t\t\t<p class=\"highlight_red\">2、叶子节点 treeNode.open = false</p>\n\t\t\t<p class=\"highlight_red\">3、为了解决部分朋友生成 json 数据出现的兼容问题, 支持 \"false\",\"true\" 字符串格式的数据</p>\n\t\t\t<p class=\"highlight_red\">4、非异步加载模式下，无子节点的父节点设置 open=true 后，可显示为展开状态，但异步加载模式下不会生效。（v3.5.15+） </p>\n\t\t\t<p>默认值：false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示节点为 展开 状态</p>\n\t<p> false 表示节点为 折叠 状态</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 查看当前被选中的节点的 展开 / 折叠 状态</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar isOpen = sNodes[0].open;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.parentTId.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>parentTId</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>treeNode 节点的父节点唯一标识 tId。</p>\n\t\t\t<p class=\"highlight_red\">1、v3.x 用 parentTId 替换了原先的 parentNode 属性，同时增加了 getParentNode 方法，以避免原先 parentNode 造成的 clone 死循环</p>\n\t\t\t<p class=\"highlight_red\">2、初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>zTree 内部生成的节点唯一标识，请参考 treeNode.tId 的说明</p>\n\t<p class=\"highlight_red\">如果 treeNode 是根节点，则 parentTId = null</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 查看当前被选中的节点的父节点 tId</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar parentTId = sNodes[0].parentTId;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.tId.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>tId</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>treeNode 节点的唯一标识 tId。</p>\n\t\t\t<p class=\"highlight_red\">初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>生成规则：setting.treeId + \"_\" + 内部计数</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 查看当前被选中的节点的 tId</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar tId = sNodes[0].tId;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.target.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>target</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置点击节点后在何处打开 url。<span class=\"highlight_red\">[treeNode.url 存在时有效]</span></p>\n\t\t\t<p>默认值：无</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>同超链接 target 属性: \"_blank\", \"_self\" 或 其他指定窗口名称 </p>\n\t<p>省略此属性，则默认为 \"_blank\"</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 设置点击某节点时，弹出新页面</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"test1\", \"url\":\"http://myTest.com\", \"target\":\"_blank\"},\n\t......\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.url.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>url</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>节点链接的目标 URL</p>\n\t\t\t<p class=\"highlight_red\">1、编辑模式 (setting.edit.enable = true) 下此属性功能失效，如果必须使用类似功能，请利用 onClick 事件回调函数自行控制。</p>\n\t\t\t<p class=\"highlight_red\">2、如果需要在 onClick 事件回调函数中进行跳转控制，那么请将 URL 地址保存在其他自定义的属性内，请勿使用 url</p>\n\t\t\t<p>默认值：无</p>\n\t\t</div>\n\t</div>\n\t<h3>String 格式说明</h3>\n\t<div class=\"desc\">\n\t<p>同超链接 href 属性</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 设置某节点点击时，跳转到 g.cn</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"Google CN\", \"url\":\"http://g.cn\"},\n\t......\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/treeNode.zAsync.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>zAsync</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>记录 treeNode 节点是否已经进行过异步加载，避免父节点反复异步加载数据。</p>\n\t\t\t<p class=\"highlight_red\">初始化节点数据时，由 zTree 增加此属性，请勿提前赋值</p>\n\t\t\t<p class=\"highlight_red\">默认值：false （无子节点的父节点）； true （有子节点的父节点 & 叶子节点）</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean 格式说明</h3>\n\t<div class=\"desc\">\n\t<p> true 表示父节点展开时不需要自动异步加载</p>\n\t<p> false 表示父节点展开时需要自动异步加载</p>\n\t<p class=\"highlight_red\"> 此参数不会对 reAsyncChildNodes 方法造成任何影响</p>\n\t</div>\n\t<h3>treeNode 举例</h3>\n\t<h4>1. 查看当前被选中的节点是否节点是否需要自动异步加载</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar zAsync = sNodes[0].zAsync;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.addNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(parentNode, newNodes, isSilent)</span><span class=\"path\">zTreeObj.</span>addNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>添加节点。</p>\n\t\t\t<p class=\"highlight_red\">v3.x 为了避免原先反复初始化造成的数据重复问题，在 初始化 和 添加节点 时内部进行 clone 操作。如果需要获取数据在 zTree 内的对象，请获取此方法的返回值。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>parentNode</b><span>JSON</span></h4>\n\t<p>指定的父节点，如果增加根节点，请设置 parentNode 为 null 即可。</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>newNodes</b><span>JSON / Array(JSON)</span></h4>\n\t<p>需要增加的节点数据 JSON 对象集合，数据只需要满足 zTree 的节点数据必需的属性即可，详细请参考“treeNode 节点数据详解”</p>\n\t<p class=\"highlight_red\">1、v3.x 支持单独添加一个节点，即如果只新增一个节点，不用必须包在数组中</p>\n\t<p class=\"highlight_red\">2、使用简单数据模式，请参考 setting.data.simpleData 内的属性说明</p>\n\t<h4 class=\"topLine\"><b>isSilent</b><span>Boolean</span></h4>\n\t<p>设定增加节点后是否自动展开父节点。</p>\n\t<p>isSilent = true 时，不展开父节点，其他值或缺省状态都自动展开。</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Array(JSON)</span></h4>\n\t<p>返回值是 zTree 最终添加的节点数据集合</p>\n\t<p class=\"highlight_red\">如果 newNodes 是单个节点数据 JSON，返回值也是将其包在 Array 内</p>\n\t<p class=\"highlight_red\">请务必记住：返回值中的数据对象 是 newNodes 被 clone 后的，所以绝对不相等！</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 对于 id = \"tree\" 的 zTree 增加 1 个根节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar newNode = {name:\"newNode1\"};\nnewNode = treeObj.addNodes(null, newNode);\n</code></pre>\n\t<h4>2. 对于 id = \"tree\" 的 zTree 增加 3 个根节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar newNodes = [{name:\"newNode1\"}, {name:\"newNode2\"}, {name:\"newNode3\"}];\nnewNodes = treeObj.addNodes(null, newNodes);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.cancelEditName.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(newName)</span><span class=\"path\">zTreeObj.</span>cancelEditName</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>取消节点的编辑名称状态，可以恢复原名称，也可以强行赋给新的名称。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>newName</b><span>String</span></h4>\n\t<p>重新给定的新名称。</p>\n\t<p class=\"highlight_red\">如果省略此参数，则恢复原名称。</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 取消 zTree 的编辑名称状态，恢复该节点原有名称</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.cancelEditName();\n</code></pre>\n\t<h4>2. 取消 zTree 的编辑名称状态，并且重新设定该节点名称</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.cancelEditName(\"test_new_name\");\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.cancelSelectedNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode)</span><span class=\"path\">zTreeObj.</span>cancelSelectedNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>取消节点的选中状态。</p>\n\t\t\t<p class=\"highlight_red\">v3.x 支持多点同时选中，因此取消选中状态可以全部取消，也可以单独取消某个节点的选中状态。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要取消选中状态的节点。</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<p class=\"highlight_red\">如果省略此参数，则将取消全部被选中节点的选中状态。</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 取消当前所有被选中节点的选中状态</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.cancelSelectedNode();\n</code></pre>\n\t<h4>2. 取消当前第一个被选中节点的选中状态</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nif (nodes.length>0) { \n\ttreeObj.cancelSelectedNode(nodes[0]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.checkAllNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(checked)</span><span class=\"path\">zTreeObj.</span>checkAllNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>勾选 或 取消勾选 全部节点。<span class=\"highlight_red\">[setting.check.enable = true 且 setting.check.chkStyle = \"checkbox\" 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">此方法不会触发 beforeCheck / onCheck 事件回调函数。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>checked</b><span>Boolean</span></h4>\n\t<p>checked = true  表示勾选全部节点</p>\n\t<p>checked = false 表示全部节点取消勾选</p>\n\t<p class=\"highlight_red\">不会影响 treeNode.nochecked = true 的节点。</p>\n\t<p class=\"highlight_red\">不会影响未加载的节点。</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 勾选全部节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.checkAllNodes(true);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.checkNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode, checked, checkTypeFlag, callbackFlag)</span><span class=\"path\">zTreeObj.</span>checkNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>勾选 或 取消勾选 单个节点。<span class=\"highlight_red\">[setting.check.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">v3.x 中 checkNode() 方法可以触发 beforeCheck / onCheck 事件回调函数。便于减少冗余代码</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要勾选 或 取消勾选 的节点数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>checked</b><span>Boolean</span></h4>\n\t<p>checked = true  表示勾选节点</p>\n\t<p>checked = false 表示节点取消勾选</p>\n\t<p class=\"highlight_red\">省略此参数，则根据对此节点的勾选状态进行 toggle 切换</p>\n\t<p class=\"highlight_red\">不影响 treeNode.nochecked = true 的节点。</p>\n\t<h4 class=\"topLine\"><b>checkTypeFlag</b><span>Boolean</span></h4>\n\t<p>checkTypeFlag = true 表示按照 setting.check.chkboxType 属性进行父子节点的勾选联动操作</p>\n\t<p>checkTypeFlag = false 表示只修改此节点勾选状态，无任何勾选联动操作</p>\n\t<p class=\"highlight_red\">checkTypeFlag = false 且 treeNode.checked = checked 时，不会触发回调函数，直接返回</p>\n\t<p class=\"highlight_red\">不影响父子节点中 treeNode.nochecked = true 的节点。</p>\n\t<h4 class=\"topLine\"><b>callbackFlag</b><span>Boolean</span></h4>\n\t<p>callbackFlag = true 表示执行此方法时触发 beforeCheck & onCheck 事件回调函数</p>\n\t<p>callbackFlag = false 表示执行此方法时不触发事件回调函数</p>\n\t<p class=\"highlight_red\">省略此参数，等同于 false</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 勾选当前选中的节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nfor (var i=0, l=nodes.length; i < l; i++) {\n\ttreeObj.checkNode(nodes[i], true, true);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.copyNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(targetNode, treeNode, moveType, isSilent)</span><span class=\"path\">zTreeObj.</span>copyNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>复制节点。</p>\n\t\t\t<p class=\"highlight_red\">v3.x 复制节点时进行 clone 操作。如果需要获取数据在 zTree 内的对象，请获取此方法的返回值。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>targetNode</b><span>JSON</span></h4>\n\t<p>要复制到的目标节点 JSON 数据</p>\n\t<p class=\"highlight_red\">如果复制成为根节点，请设置 targetNode 为 null 即可</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要被复制的节点数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>moveType</b><span>String</span></h4>\n\t<p>复制到目标节点的相对位置</p>\n\t<p class=\"highlight_red\">\"inner\"：成为子节点，\"prev\"：成为同级前一个节点，\"next\"：成为同级后一个节点</p>\n\t<h4 class=\"topLine\"><b>isSilent</b><span>Boolean</span></h4>\n\t<p>设定复制节点后是否自动展开父节点。</p>\n\t<p>isSilent = true 时，不展开父节点，其他值或缺省状态都自动展开。</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>JSON</span></h4>\n\t<p>返回值是最终加入到 zTree 内的节点数据</p>\n\t<p class=\"highlight_red\">请务必记住：返回值中的数据对象 是 treeNode 被 clone 后的，所以绝对不相等！</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 将根节点中第二个节点 复制成为 第一个节点的子节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.copyNode(nodes[0], nodes[1], \"inner\");\n</code></pre>\n\t<h4>2. 将根节点中第二个节点 复制成为 第一个节点的前一个节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.copyNode(nodes[0], nodes[1], \"before\");\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.destroy.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId)</span><span class=\"path\">zTreeObj.</span>destroy</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>从 zTree v3.4 开始提供销毁 zTree 的方法。</p>\n\t\t\t<p>1、用此方法可以销毁 zTreeObj 代表的 zTree。</p>\n\t\t\t<p class=\"highlight_red\">2、销毁当前页面全部的 zTree，也可以使用 $.fn.zTree.destroy() 方法。</p>\n\t\t\t<p class=\"highlight_red\">3、重新使用已经被销毁的树，必须要使用 init 方法进行初始化。</p>\n\t\t</div>\n\t</div>\n        <h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 销毁 id 为 \"treeDemo\" 的 zTree</h4>\n\t<pre xmlns=\"\"><code>var zTreeObj = $.fn.zTree.getZTreeObj(\"treeDemo\");\nzTreeObj.destroy();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.editName.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode)</span><span class=\"path\">zTreeObj.</span>editName</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置某节点进入编辑名称状态。</p>\n\t\t\t<p class=\"highlight_red\">1、如果需要用 js 取消编辑名称状态，请使用 cancelEditName(newName) 方法。</p>\n\t\t\t<p class=\"highlight_red\">2、可利用此方法让当前正编辑的节点 input 输入框获取焦点。</p>\n\t\t\t<p class=\"highlight_red\">3、请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>指定进入编辑名称状态的节点 JSON 数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 设置根节点第一个节点进入编辑名称状态</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.editName(nodes[0]);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.expandAll.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(expandFlag)</span><span class=\"path\">zTreeObj.</span>expandAll</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>展开 / 折叠 全部节点</p>\n\t\t\t<p class=\"highlight_red\">此方法不会触发  beforeExpand / onExpand  和 beforeCollapse / onCollapse 事件回调函数。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>expandFlag</b><span>Boolean</span></h4>\n\t<p>expandFlag = true 表示 展开 全部节点</p>\n\t<p>expandFlag =  false 表示 折叠 全部节点</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值表示最终实际操作情况</p>\n\t<p>true 表示 展开 全部节点</p>\n\t<p>false 表示 折叠 全部节点</p>\n\t<p>null 表示 不存在任何父节点</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 展开全部节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.expandAll(true);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.expandNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode, expandFlag, sonSign, focus, callbackFlag)</span><span class=\"path\">zTreeObj.</span>expandNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>展开 / 折叠 指定的节点</p>\n\t\t\t<p class=\"highlight_red\">v3.x 中执行此方法可以触发 beforeExpand / onExpand  或 beforeCollapse / onCollapse 事件回调函数。便于减少冗余代码</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要 展开 / 折叠 的节点数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>expandFlag</b><span>Boolean</span></h4>\n\t<p>expandFlag = true 表示 展开 节点</p>\n\t<p>expandFlag = false 表示 折叠 节点</p>\n\t<p class=\"highlight_red\">省略此参数，则根据对此节点的展开状态进行 toggle 切换</p>\n\t<h4 class=\"topLine\"><b>sonSign</b><span>Boolean</span></h4>\n\t<p>sonSign = true 表示 全部子孙节点 进行与 expandFlag 相同的操作</p>\n\t<p>sonSign = false 表示 只影响此节点，对于其 子孙节点无任何影响</p>\n\t<p class=\"highlight_red\">sonSign = false 且 treeNode.open = expandFlag 时，不会触发回调函数，直接返回</p>\n\t<p class=\"highlight_red\">省略此参数，等同于 false</p>\n\t<h4 class=\"topLine\"><b>focus</b><span>Boolean</span></h4>\n\t<p>focus = true 表示 展开 / 折叠 操作后，通过设置焦点保证此焦点进入可视区域内</p>\n\t<p>focus =  false 表示 展开 / 折叠 操作后，不设置任何焦点</p>\n\t<p class=\"highlight_red\">省略此参数，等同于 true</p>\n\t<h4 class=\"topLine\"><b>callbackFlag</b><span>Boolean</span></h4>\n\t<p>callbackFlag = true 表示执行此方法时触发 beforeExpand / onExpand  或 beforeCollapse / onCollapse 事件回调函数</p>\n\t<p>callbackFlag = false 表示执行此方法时不触发事件回调函数</p>\n\t<p class=\"highlight_red\">省略此参数，等同于 false</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Boolean</span></h4>\n\t<p>返回值表示最终实际操作情况</p>\n\t<p>true 表示 展开 节点</p>\n\t<p>false 表示 折叠 节点</p>\n\t<p>null 表示 不是父节点</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 展开当前选择的第一个节点（包括其全部子节点）</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nif (nodes.length>0) {\n\ttreeObj.expandNode(nodes[0], true, true, true);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.getChangeCheckedNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">zTreeObj.</span>getChangeCheckedNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>获取输入框勾选状态被改变的节点集合（与原始数据 checkedOld 对比）。<span class=\"highlight_red\">[setting.check.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>返回值</b><span>Array(JSON)</span></h4>\n\t<p>返回全部勾选状态被改变的节点集合 Array</p>\n\t<p class=\"highlight_red\">如果需要获取每次操作后全部被改变勾选状态的节点数据，请在每次勾选操作后，遍历所有被改变勾选状态的节点数据，让其 checkedOld = checked 就可以了。</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 获取当前勾选状态被改变的节点集合</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getChangeCheckedNodes();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.getCheckedNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(checked)</span><span class=\"path\">zTreeObj.</span>getCheckedNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>获取输入框被勾选 或 未勾选的节点集合。<span class=\"highlight_red\">[setting.check.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>checked</b><span>Boolean</span></h4>\n\t<p>checked = true  表示获取 被勾选 的节点集合</p>\n\t<p>checked = false 表示获取 未勾选 的节点集合</p>\n\t<p class=\"highlight_red\">省略此参数，等同于 true。</p>\n\t<p class=\"highlight_red\">对于 treeNode.nochecked = true 的节点不进行获取。</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Array(JSON)</span></h4>\n\t<p>返回全部符合要求的节点集合 Array</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 获取当前被勾选的节点集合</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getCheckedNodes(true);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.getNodeByParam.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(key, value, parentNode)</span><span class=\"path\">zTreeObj.</span>getNodeByParam</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>根据节点数据的属性搜索，获取条件完全匹配的节点数据 JSON 对象</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>key</b><span>String</span></h4>\n\t<p>需要精确匹配的属性名称</p>\n\t<h4 class=\"topLine\"><b>value</b><span>?</span></h4>\n\t<p>需要精确匹配的属性值，可以是任何类型，只要保证与 key 指定的属性值保持一致即可</p>\n\t<h4 class=\"topLine\"><b>parentNode</b><span>JSON</span></h4>\n\t<p>搜索范围，指定在某个父节点下的子节点中进行搜索</p>\n\t<p class=\"highlight_red\">忽略此参数，表示在全部节点中搜索</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>JSON</span></h4>\n\t<p>匹配精确搜索的节点数据</p>\n\t<p class=\"highlight_red\">1、如无结果，返回 null</p>\n\t<p class=\"highlight_red\">2、如有多个节点满足查询条件，只返回第一个匹配到的节点</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 查找 id = 1 的节点数据</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar node = treeObj.getNodeByParam(\"id\", 1, null);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.getNodeByTId.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(tId)</span><span class=\"path\">zTreeObj.</span>getNodeByTId</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>根据 zTree 的唯一标识 tId 快速获取节点 JSON 数据对象</p>\n\t\t\t<p class=\"highlight_red\">通过内部的 cache 获取，不需要遍历节点。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>tId</b><span>String</span></h4>\n\t<p>节点在 zTree 内的唯一标识 tId</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>JSON</span></h4>\n\t<p>tId 对应的节点 JSON 数据对象</p>\n\t<p class=\"highlight_red\">如无结果，返回 null</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 获取 tId = \"tree_10\" 的节点数据</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar node = treeObj.getNodeByTId(\"tree_10\");\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.getNodeIndex.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode)</span><span class=\"path\">zTreeObj.</span>getNodeIndex</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>获取某节点在同级节点中的序号（从0开始）</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要查询顺序的节点 JSON 数据对象</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Number</span></h4>\n\t<p class=\"highlight_red\">返回值从 0 开始计数</p>\n\t<p class=\"highlight_red\">如果不存在该节点数据，返回 -1</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 获取当前选中的第一个节点在同级节点中的序号</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nif (nodes.length>0) {\n\tvar index = treeObj.getNodeIndex(nodes[0]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.getNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">zTreeObj.</span>getNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>获取 zTree 的全部节点数据</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>返回值</b><span>Array(JSON)</span></h4>\n\t<p>全部节点数据</p>\n\t<p class=\"highlight_red\">1、Array 仅仅是根节点的集合（默认情况子节点都处于 children 属性下）； </p>\n\t<p class=\"highlight_red\">2、如需遍历全部节点需要利用递归，或利用 transformToArray 方法 将数据变成简单的 Array 集合</p>\n\t<p class=\"highlight_red\">3、对于异步加载模式下，尚未加载的子节点是无法通过此方法获取的。</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 获取全部节点数据</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.getNodesByFilter.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(filter, isSingle, parentNode, invokeParam)</span><span class=\"path\">zTreeObj.</span>getNodesByFilter</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>根据自定义规则搜索节点数据 JSON 对象集合 或 单个节点数据</p>\n\t\t\t<p class=\"highlight_red\">可自定义复杂的搜索规则</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>filter</b><span>Function</span></h4>\n\t<p>自定义过滤器函数 function filter(node) {...}</p>\n\t<p>filter 参数：node (节点数据 JSON)</p>\n\t<p>filter 返回值：boolean (true 表示符合搜索条件；false 表示不符合搜索条件)</p>\n\t<h4 class=\"topLine\"><b>isSingle</b><span>Boolean</span></h4>\n\t<p>isSingle = true 表示只查找单个节点</p>\n\t<p>isSingle = false 表示查找节点集合</p>\n\t<p class=\"highlight_red\">忽略此参数，表示查找节点集合</p>\n\t<h4 class=\"topLine\"><b>parentNode</b><span>JSON</span></h4>\n\t<p>可以指定在某个父节点下的子节点中搜索</p>\n\t<p class=\"highlight_red\">忽略此参数，表示在全部节点中搜索</p>\n\t<h4 class=\"topLine\"><b>invokeParam</b><span>任意类型</span></h4>\n\t<p>用户自定义的数据对象，用于 filter 中进行计算</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Array(JSON) / JSON</span></h4>\n\t<p>isSingle = true 返回 第一个找到的节点数据 JSON，无结果时返回 null</p>\n\t<p>isSingle = false 返回 节点数据集合 Array(JSON)，无结果时返回 [ ]</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 查找 level = 2 & name 中包含 \"test\" 的节点数据</h4>\n\t<pre xmlns=\"\"><code>function filter(node) {\n    return (node.level == 2 && node.name.indexOf(\"test\")>-1);\n}\n......\nvar treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar node = treeObj.getNodesByFilter(filter, true); // 仅查找一个节点\nvar nodes = treeObj.getNodesByFilter(filter); // 查找节点集合\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.getNodesByParam.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(key, value, parentNode)</span><span class=\"path\">zTreeObj.</span>getNodesByParam</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>根据节点数据的属性搜索，获取条件完全匹配的节点数据 JSON 对象集合</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>key</b><span>String</span></h4>\n\t<p>需要精确匹配的属性名称</p>\n\t<h4 class=\"topLine\"><b>value</b><span>?</span></h4>\n\t<p>需要精确匹配的属性值，可以是任何类型，只要保证与 key 指定的属性值保持一致即可</p>\n\t<h4 class=\"topLine\"><b>parentNode</b><span>JSON</span></h4>\n\t<p>可以指定在某个父节点下的子节点中搜索</p>\n\t<p class=\"highlight_red\">忽略此参数，表示在全部节点中搜索</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Array(JSON)</span></h4>\n\t<p>匹配精确搜索的节点数据集合</p>\n\t<p class=\"highlight_red\">如无结果，返回 [ ]</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 查找 name = \"test\" 的节点数据</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodesByParam(\"name\", \"test\", null);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.getNodesByParamFuzzy.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(key, value, parentNode)</span><span class=\"path\">zTreeObj.</span>getNodesByParamFuzzy</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>根据节点数据的属性搜索，获取条件模糊匹配的节点数据 JSON 对象集合</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>key</b><span>String</span></h4>\n\t<p>需要模糊匹配的属性名称</p>\n\t<h4 class=\"topLine\"><b>value</b><span>String</span></h4>\n\t<p>需要模糊匹配的属性值</p>\n\t<p class=\"highlight_red\">模糊匹配只能针对 String 类型的数据</p>\n\t<h4 class=\"topLine\"><b>parentNode</b><span>JSON</span></h4>\n\t<p>可以指定在某个父节点下的子节点中搜索</p>\n\t<p class=\"highlight_red\">忽略此参数，表示在全部节点中搜索</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Array(JSON)</span></h4>\n\t<p>匹配模糊搜索的节点数据集合</p>\n\t<p class=\"highlight_red\">如无结果，返回 [ ]</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 查找 name 包含 \"test\" 的节点数据</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodesByParamFuzzy(\"name\", \"test\", null);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.getSelectedNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">zTreeObj.</span>getSelectedNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>获取 zTree 当前被选中的节点数据集合</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>返回值</b><span>Array(JSON)</span></h4>\n\t<p>当前被选中的节点数据集合</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 获取当前被选中的节点数据集合</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.hideNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode)</span><span class=\"path\">zTreeObj.</span>hideNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exhide</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>隐藏某个节点。</p>\n\t\t\t<p class=\"highlight_red\">1、此功能不支持 exedit 扩展，因此不要在编辑状态时使用隐藏节点的方法。</p>\n\t\t\t<p class=\"highlight_red\">2、隐藏/显示节点，会影响节点的 isFirstNode 和 isLastNode 属性。</p>\n\t\t\t<p class=\"highlight_red\">3、请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>指定被隐藏的节点 JSON 数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 隐藏根节点第一个节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.hideNode(nodes[0]);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.hideNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNodes)</span><span class=\"path\">zTreeObj.</span>hideNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exhide</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>隐藏一批节点。</p>\n\t\t\t<p class=\"highlight_red\">1、此功能不支持 exedit 扩展，因此不要在编辑状态时使用隐藏节点的方法。</p>\n\t\t\t<p class=\"highlight_red\">2、隐藏/显示节点，会影响节点的 isFirstNode 和 isLastNode 属性。</p>\n\t\t\t<p class=\"highlight_red\">3、请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>指定被隐藏的节点 JSON 数据集合</p>\n\t<p class=\"highlight_red\">请务必保证这些节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 隐藏根节点第一个节点的子节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.hideNodes(nodes[0].children);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.moveNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(targetNode, treeNode, moveType, isSilent)</span><span class=\"path\">zTreeObj.</span>moveNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>移动节点。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>targetNode</b><span>JSON</span></h4>\n\t<p>要移动到的目标节点 JSON 数据</p>\n\t<p class=\"highlight_red\">如果移动成为根节点，请设置 targetNode 为 null 即可</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要被移动的节点数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>moveType</b><span>String</span></h4>\n\t<p>指定移动到目标节点的相对位置</p>\n\t<p class=\"highlight_red\">\"inner\"：成为子节点，\"prev\"：成为同级前一个节点，\"next\"：成为同级后一个节点</p>\n\t<h4 class=\"topLine\"><b>isSilent</b><span>Boolean</span></h4>\n\t<p>设定移动节点后是否自动展开父节点。</p>\n\t<p>isSilent = true 时，不展开父节点，其他值或缺省状态都自动展开。</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>JSON</span></h4>\n\t<p>返回值是最终被移动的节点数据，正常情况下与 treeNode 参数完全相同</p>\n\t<p class=\"highlight_red\">如果 返回值 为 null，说明 移动失败，主要原因有：<br/>\n\t\t&nbsp;1、targetNode 是 treeNode 父节点，且 moveType = \"inner\"<br/>\n\t\t&nbsp;2、targetNode 是 treeNode 子孙节点\n\t</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 将根节点中第二个节点 移动成为 第一个节点的子节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.moveNode(nodes[0], nodes[1], \"inner\");\n</code></pre>\n\t<h4>2. 将根节点中第二个节点 移动成为 第一个节点的前一个节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.moveNode(nodes[0], nodes[1], \"prev\");\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.reAsyncChildNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(parentNode, reloadType, isSilent)</span><span class=\"path\">zTreeObj.</span>reAsyncChildNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>强行异步加载父节点的子节点。<span class=\"highlight_red\">[setting.async.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">已经加载过的父节点可反复使用此方法重新加载。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>parentNode</b><span>JSON</span></h4>\n\t<p>指定需要异步加载的父节点 JSON 数据</p>\n\t<p class=\"highlight_red\">1、parentNode = null 时，相当于从根节点 Root 进行异步加载</p>\n\t<p class=\"highlight_red\">2、parentNode.isParent = false 时，不进行异步加载</p>\n\t<p class=\"highlight_red\">3、请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>reloadType</b><span>String</span></h4>\n\t<p>reloadType = \"refresh\" 表示清空后重新加载。</p>\n\t<p>reloadType != \"refresh\" 时，表示追加子节点处理。</p>\n\t<h4 class=\"topLine\"><b>isSilent</b><span>Boolean</span></h4>\n\t<p>设定异步加载后是否自动展开父节点。</p>\n\t<p>isSilent = true 时，不展开父节点，其他值或缺省状态都自动展开。</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 重新异步加载 zTree </h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.reAsyncChildNodes(null, \"refresh\");\n</code></pre>\n\t<h4>2. 重新异步加载当前选中的第一个节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nif (nodes.length>0) {\n\ttreeObj.reAsyncChildNodes(nodes[0], \"refresh\");\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.refresh.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">zTreeObj.</span>refresh</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>刷新 zTree 。</p>\n\t\t\t<p class=\"highlight_red\">没有特殊必要，尽量不要使用此方法。单个节点更新请使用 updateNode 方法，异步加载模式下请使用 reAsyncChildNodes 方法。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 刷新 zTree </h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.refresh();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.removeChildNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(parentNode)</span><span class=\"path\">zTreeObj.</span>removeChildNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>清空某父节点的子节点。</p>\n\t\t\t<p class=\"highlight_red\">1、清空子节点后，父节点会自动变为叶子节点，如需要父节点保持父节点状态，请设置 setting.data.keep.parent 属性。</p>\n\t\t\t<p class=\"highlight_red\">2、请勿用此方法清空根节点，如果需要清空根节点，直接初始化 zTree，并且设置初始节点为 null 即可。</p>\n\t\t\t<p class=\"highlight_red\">3、此方法不会触发任何事件回调函数。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>parentNode</b><span>JSON</span></h4>\n\t<p>需要清空子节点的父节点数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Array(JSON)</span></h4>\n\t<p>将该父节点的子节点数据返回，如果不存在则返回 null</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 清空选中的第一个节点的子节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nif (nodes && nodes.length>0) {\n\ttreeObj.removeChildNodes(nodes[0]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.removeNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode, callbackFlag)</span><span class=\"path\">zTreeObj.</span>removeNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>删除节点。</p>\n\t\t\t<p class=\"highlight_red\">v3.x 中删除节点可以触发 beforeRemove / onRemove 事件回调函数。便于减少冗余代码</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要被删除的节点数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>callbackFlag</b><span>Boolean</span></h4>\n\t<p>callbackFlag = true 表示执行此方法时触发 beforeRemove & onRemove 事件回调函数</p>\n\t<p>callbackFlag = false 表示执行此方法时不触发事件回调函数</p>\n\t<p class=\"highlight_red\">省略此参数，等同于 false</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 删除所有选中的节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nfor (var i=0, l=nodes.length; i < l; i++) {\n\ttreeObj.removeNode(nodes[i]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.selectNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode, addFlag)</span><span class=\"path\">zTreeObj.</span>selectNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>选中指定节点</p>\n\t\t\t<p class=\"highlight_red\">v3.x 支持同时选中多个节点。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要被选中的节点数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>addFlag</b><span>Boolean</span></h4>\n\t<p>addFlag = true 表示追加选中，会出现多点同时被选中的情况</p>\n\t<p>addFlag = false 表示单独选中，原先被选中的节点会被取消选中状态</p>\n\t<p class=\"highlight_red\">setting.view.selectedMulti = false 时，此参数无效，始终进行单独选中</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 单独选中根节点中第一个节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\nif (nodes.length>0) {\n\ttreeObj.selectNode(nodes[0]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.setChkDisabled.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(node, disabled, inheritParent, inheritChildren)</span><span class=\"path\">zTreeObj.</span>setChkDisabled</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.excheck</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>禁用 或 解禁 某个节点的 checkbox / radio <span class=\"highlight_red\">[setting.check.enable = true 时有效]</span></p>\n\t\t\t<p class=\"highlight_red\">1、节点的 checkbox / radio 被禁用后，无法勾选或取消勾选，但能够影响父节点的半选状态</p>\n\t\t\t<p class=\"highlight_red\">2、请不要直接修改已加载节点的 treeNode.chkDisabled 属性。</p>\n\t\t\t<p class=\"highlight_red\">3、请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>需要禁用 或 解禁 checkbox / radio 的节点数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>disabled</b><span>Boolean</span></h4>\n\t<p>disabled = true  表示禁用 checkbox / radio</p>\n\t<p>disabled = false 表示解禁 checkbox / radio</p>\n\t<p class=\"highlight_red\">省略此参数，等同于 disabled = false </p>\n\t<p class=\"highlight_red\">不影响 treeNode.nochecked = true 的节点。</p>\n\t<h4 class=\"topLine\"><b>inheritParent</b><span>Boolean</span></h4>\n\t<p>inheritParent = true 表示全部父节点进行同样的操作</p>\n\t<p>inheritParent = false 表示不影响父节点</p>\n\t<p class=\"highlight_red\">省略此参数，等同于 inheritParent = false </p>\n\t<h4 class=\"topLine\"><b>inheritChildren</b><span>Boolean</span></h4>\n\t<p>inheritChildren = true 表示全部子节点进行同样的操作</p>\n\t<p>inheritChildren = false 表示不影响子节点</p>\n\t<p class=\"highlight_red\">省略此参数，等同于 inheritChildren = false </p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 禁用当前选中的节点的 checkbox / radio</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nfor (var i=0, l=nodes.length; i < l; i++) {\n\ttreeObj.setChkDisabled(nodes[i], true);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.setEditable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(editable)</span><span class=\"path\">zTreeObj.</span>setEditable</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exedit</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>设置 zTree 进入 / 取消 编辑状态。</p>\n\t\t\t<p class=\"highlight_red\">对于编辑状态的各种功能需要提前设置对应 setting 中的不同属性</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>editable</b><span>Boolean</span></h4>\n\t<p>true 表示进入 编辑状态</p>\n\t<p>false 表示取消 编辑状态</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 设置 zTree 进入编辑状态</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.setEditable(true);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.setting.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>JSON</span><span class=\"path\">zTreeObj.</span>setting</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree 对象使用的 setting 配置数据，详细请参考 “setting 配置详解”中的各个属性详细说明</p>\n\t\t\t<p class=\"highlight_red\">v3.x 取消了原先操作 setting 的方法，让用户可以较自由的修改参数，但请注意，对于 zTree 初始化有影响的参数后期修改是不会起作用的，请对各个属性有较深入的了解以后再考虑进行修改。</p>\n\t\t</div>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.showNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode)</span><span class=\"path\">zTreeObj.</span>showNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exhide</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>显示某个被隐藏的节点。</p>\n\t\t\t<p class=\"highlight_red\">1、此功能不支持 exedit 扩展，因此不要在编辑状态时使用隐藏节点的方法。</p>\n\t\t\t<p class=\"highlight_red\">2、隐藏/显示节点，会影响节点的 isFirstNode 和 isLastNode 属性。</p>\n\t\t\t<p class=\"highlight_red\">3、请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>指定被显示的节点 JSON 数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 显示某个隐藏的节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar node = treeObj.getNodeByParam(\"isHidden\", true);\nif (node) {\n  treeObj.showNode(node);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.showNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNodes)</span><span class=\"path\">zTreeObj.</span>showNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.exhide</span> 扩展 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>显示一批已经被隐藏的节点。</p>\n\t\t\t<p class=\"highlight_red\">1、此功能不支持 exedit 扩展，因此不要在编辑状态时使用隐藏节点的方法。</p>\n\t\t\t<p class=\"highlight_red\">2、隐藏/显示节点，会影响节点的 isFirstNode 和 isLastNode 属性。</p>\n\t\t\t<p class=\"highlight_red\">3、请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>指定被显示的节点 JSON 数据集合</p>\n\t<p class=\"highlight_red\">请务必保证这些节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 显示全部隐藏的节点</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodesByParam(\"isHidden\", true);\ntreeObj.showNodes(nodes);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.transformToArray.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNodes)</span><span class=\"path\">zTreeObj.</span>transformToArray</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>将 zTree 使用的标准 JSON 嵌套格式的数据转换为简单 Array 格式。(免去用户自行编写递归遍历全部节点的麻烦)</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNodes</b><span>Array(JSON) / JSON</span></h4>\n\t<p>需要被转换的 zTree 节点数据对象集合 或 某个单独节点的数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Array(JSON)</span></h4>\n\t<p>转换后的简单 Array 数据格式</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 将 zTree 节点数据转换为简单 Array 格式</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.transformToArray(treeObj.getNodes());\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.transformTozTreeNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(simpleNodes)</span><span class=\"path\">zTreeObj.</span>transformTozTreeNodes</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>将简单 Array 格式数据转换为 zTree 使用的标准 JSON 嵌套数据格式。</p>\n\t\t\t<p class=\"highlight_red\">使用此方法，请务必设置节点唯一标识属性名称 setting.data.simpleData.idKey 和 父节点唯一标识属性名称 setting.data.simpleData.pIdKey，并且让数据满足父子关系。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>simpleNodes</b><span>Array(JSON) / JSON</span></h4>\n\t<p>需要被转换的简单 Array 格式数据 或 某个单独的数据对象</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>Array(JSON)</span></h4>\n\t<p>zTree 使用的标准数据，子节点都存在于父节点数据的 children 属性中</p>\n\t<p class=\"highlight_red\">如果 simpleNodes 是一个 JSON 对象，则被简单封装成长度为 1 的数组。</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 将简单 Array 格式转换为zTree使用的标准格式</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"id\",\n\t\t\tpIdKey: \"pId\",\n\t\t\trootPId: 0\n\t\t}\n\t}\n};\nvar simpleNodes = [\n    {\"id\":1, \"pId\":0, \"name\":\"test1\"},\n    {\"id\":11, \"pId\":1, \"name\":\"test11\"},\n    {\"id\":12, \"pId\":1, \"name\":\"test12\"},\n    {\"id\":111, \"pId\":11, \"name\":\"test111\"}\n];\nvar treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.transformTozTreeNodes(simpleNodes);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/cn/zTreeObj.updateNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode, checkTypeFlag)</span><span class=\"path\">zTreeObj.</span>updateNode</h2>\n\t<h3>概述<span class=\"h3_info\">[ 依赖 <span class=\"highlight_green\">jquery.ztree.core</span> 核心 js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>更新某节点数据，主要用于该节点显示属性的更新。</p>\n\t\t\t<p class=\"highlight_red\">1、可针对 name、target、 url、icon、 iconSkin、checked、nocheck 等这几个用于显示效果的参数进行更新，其他用于 zTreeNodes 的参数请不要随意更新，对于展开节点，还请调用 expandNode方法，因此请勿随意修改 open 属性。</p>\n\t\t\t<p class=\"highlight_red\">2、用此方法修改 checked 勾选状态不会触发 beforeCheck / onCheck 事件回调函数。</p>\n\t\t\t<p class=\"highlight_red\">请通过 zTree 对象执行此方法。</p>\n\t\t</div>\n\t</div>\n\t<h3>Function 参数说明</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>指定需要更新的节点 JSON 数据</p>\n\t<p class=\"highlight_red\">请务必保证此节点数据对象 是 zTree 内部的数据对象</p>\n\t<h4 class=\"topLine\"><b>checkTypeFlag</b><span>Boolean</span></h4>\n\t<p>checkTypeFlag = true 表示按照 setting.check.chkboxType 属性进行父子节点的勾选联动操作</p>\n\t<p>checkTypeFlag = false 表示只修改此节点勾选状态，无任何勾选联动操作</p>\n\t<p class=\"highlight_red\">当 setting.check.enable = true 且 setting.check.chkStyle = \"checkbox\" 时才有效</p>\n\t<p class=\"highlight_red\">不影响父子节点中 treeNode.nochecked = true 的节点。</p>\n\t<h4 class=\"topLine\"><b>返回值</b><span>无</span></h4>\n\t<p>目前无任何返回值</p>\n\t</div>\n\t<h3>function 举例</h3>\n\t<h4>1. 更新根节点中第一个节点的名称</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\nif (nodes.length>0) {\n\tnodes[0].name = \"test\";\n\ttreeObj.updateNode(nodes[0]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/fn.zTree._z.html",
    "content": "<div class=\"apiDetail\">\n<div>\n    <h2><span>JSON</span><span class=\"path\">$.fn.zTree.</span>_z</h2>\n    <h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n    <div class=\"desc\">\n        <p></p>\n        <div class=\"longdesc\">\n                <p>All of the internal methods in zTree v3.x are available through '$. fn.zTree._z', \n                    use this if you want to develop your own zTree plug-ins.</p>\n                <p class=\"highlight_red\">Unless you are writing a plugin, \n                    you should not use this object.</p>\n        </div>\n    </div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/fn.zTree.destroy.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId)</span><span class=\"path\">$.fn.zTree.</span>destroy</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>From zTree v3.4, zTree provides a method for destruction.</p>\n\t\t\t<p>1. This method can destroy a zTree by treeId, or destroy all zTree instances.</p>\n\t\t\t<p class=\"highlight_red\">2. If you want to destroy a zTree, you can use the 'zTreeObj.destroy()' method.</p>\n\t\t\t<p class=\"highlight_red\">3. If you want to re-use the tree which has been destroyed, \n                            you must first re-initialise it with the 'init()' method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, all zTree instances will be destroyed.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Destroy the zTree with id === 'treeDemo'</h4>\n\t<pre xmlns=\"\"><code>$.fn.zTree.destroy(\"treeDemo\");</code></pre>\n\t<h4>2. Destroy all zTree instances</h4>\n\t<pre xmlns=\"\"><code>$.fn.zTree.destroy();</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/fn.zTree.getZTreeObj.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId)</span><span class=\"path\">$.fn.zTree.</span>getZTreeObj</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree v3.x provides this method to get zTree object from the tree's Id.</p>\n\t\t\t<p class=\"highlight_red\">Please initialize zTree first, then you can use this method.</p>\n\t\t\t<p>Users don't need to use a global variable to reference the zTree object, \n                            as all of the callback methods will pass 'treeId' parameters, \n                            and you can always call this method to get the zTree object.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>JSON</span></h4>\n\t<p>zTree object</p>\n\t<p>This is a reference to the zTree object.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Get the zTree object with id='tree'</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/fn.zTree.init.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(obj, zSetting, zNodes)</span><span class=\"path\">$.fn.zTree.</span>init</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>This method is used to create a zTree.</p>\n\t\t\t<p>1. The web page must use the W3C DTD. For example: &lt;!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"&nbsp;&nbsp; &nbsp;\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"&gt;</p>\n\t\t\t<p>2. Needs jquery-1.4.2.js or better.</p>\n\t\t\t<p>3. Needs jquery-ztree.core-3.0.js or better.\n                            If you are using edit mode or checkbox / radio mode, \n                            make sure you load jquery-ztree.exedit-3.0.js and jquery-ztree.excheck-3.0.js.</p>\n\t\t\t<p>4. Needs zTreeStyle.css and image files</p>\n\t\t\t<p>5. If you plan to use custom icons, please refer to the Demo, \n                            or see the help on iconSkin.</p>\n\t\t\t<p>6. Note: You need to set zTree container's class name to \"ztree\". \n                            If you need to change it, don't forget to modify the css file. \n                            If you need other special styles, you can modify the css file.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>object</b><span>jQuery Object</span></h4>\n\t<p>DOM Container for zTree</p>\n\t<h4 class=\"topLine\"><b>zSetting</b><span>JSON</span></h4>\n\t<p>zTree's configuration data, please refer to \"setting details\" in the API Document.</p>\n\t<h4 class=\"topLine\"><b>zNodes</b><span>Array(JSON) / JSON</span></h4>\n\t<p>zTree's node data, please refer to \"treeNode data details\" in the API Document.</p>\n\t<p class=\"highlight_red\">1. zTree v3.x support to add single node, that is, if only to add one node, \n                you can use JSON without using Array.</p>\n\t<p class=\"highlight_red\">2. If you are planning on using asynchronous loading of root nodes, set it to null or [ ]</p>\n\t<p class=\"highlight_red\">3. If you are using simple data mode, please refer to \"setting.data.simpleData\" in the API Document.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>JSON</span></h4>\n\t<p>zTree object</p>\n\t<p>This object can provide the methods of operate the zTree</p>\n\t<p class=\"highlight_red\">You can use $.fn.zTree.getZTreeObj method at any time to obtain.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. create a simple tree</h4>\n\t<pre xmlns=\"\"><code>&lt;!DOCTYPE html&gt;\n&lt;HTML&gt;\n &lt;HEAD&gt;\n  &lt;TITLE&gt; ZTREE DEMO &lt;/TITLE&gt;\n  &lt;meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\"&gt;\n  &lt;link rel=\"stylesheet\" href=\"zTreeStyle/zTreeStyle.css\" type=\"text/css\"&gt;\n  &lt;script type=\"text/javascript\" src=\"jquery-1.4.2.js\"&gt;&lt;/script&gt;\n  &lt;script type=\"text/javascript\" src=\"jquery.ztree.core-3.5.js\"&gt;&lt;/script&gt;\n&lt;!--\n  &lt;script type=\"text/javascript\" src=\"jquery.ztree.excheck-3.5.js\"&gt;&lt;/script&gt;\n  &lt;script type=\"text/javascript\" src=\"jquery.ztree.exedit-3.5.js\"&gt;&lt;/script&gt;\n--&gt;\n  &lt;SCRIPT type=\"text/javascript\" &gt;\n\tvar zTreeObj,\n\tsetting = {\n\t\tview: {\n\t\t\tselectedMulti: false\n\t\t}\n\t},\n\tzTreeNodes = [\n\t\t{\"name\":\"Site Map\", open:true, children: [\n\t\t\t{ \"name\":\"google\", \"url\":\"http://www.google.com\", \"target\":\"_blank\"},\n\t\t\t{ \"name\":\"baidu\", \"url\":\"http://baidu.com\", \"target\":\"_blank\"},\n\t\t\t{ \"name\":\"sina\", \"url\":\"http://www.sina.com.cn\", \"target\":\"_blank\"}\n\t\t\t]\n\t\t}\n\t];\n\n\t$(document).ready(function(){\n\t\tzTreeObj = $.fn.zTree.init($(\"#tree\"), setting, zTreeNodes);\n\n\t});\n  &lt;/SCRIPT&gt;\n &lt;/HEAD&gt;\n\n&lt;BODY&gt;\n&lt;ul id=\"tree\" class=\"ztree\" style=\"width:230px; overflow:auto;\"&gt;&lt;/ul&gt;\n &lt;/BODY&gt;\n&lt;/HTML&gt;</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.async.autoParam.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Array(String)</span><span class=\"path\">setting.async.</span>autoParam</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>During asynchronous loading, a request is sent to the server, which contains the identify of the parent node, \n                            so it can retrieve the children.\n                            This attribute is an array of strings, which is the identity parameter (or parameters).\n                            It applies when <span class=\"highlight_red\">[setting.async.enable = true]</span></p>\n\t\t\t<p>Default：[ ]</p>\n\t\t</div>\n\t</div>\n\t<h3>Array(String) Format</h3>\n\t<div class=\"desc\">\n\t<p>1. Put the attribute name(s) of node to the array. For example: [\"id\", \"name\"]</p>\n\t<p>2. You can rename the parameter name as sent to the server. For example: server only accepts \"zId\" -- [\"id=zId\"]</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. set auto commit 'id' attribute</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id\"]\n\t}\n};\nIf we have a parent node: {id:1, name:\"test\"}, When we are asynchronously loading this parent node's children, it will be submitted to the server with parameters: id=1\n......</code></pre>\n\t<h4>2. set auto commit 'id' attribute, but the parameter name expected by the server is 'zId'</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id=zId\"]\n\t}\n};\nIf we have a parent node: {id:1, name:\"test\"}, When we are asynchronously loading this parent node's children, it will be submitted to the server with parameters: zId=1\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.async.contentType.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.async.</span>contentType</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When Ajax sends data to the server, it uses this content-type. \n                            It is used when <span class=\"highlight_red\">[setting.async.enable = true]</span></p>\n\t\t\t<p>Default：\"application/x-www-form-urlencoded\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p> contentType = \"application/x-www-form-urlencoded\", means: the sending data format is \"form\" format.</p>\n\t<p> contentType = \"application/json\",  means: the sending data format is \"json\" format. (for .Net)</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. set the sending data format to \"json\" format.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\tcontentType: \"application/json\",\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.async.dataFilter.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, parentNode, responseData)</span><span class=\"path\">setting.async.</span>dataFilter</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback function to pre-process Ajax return data. It is valid when <span class=\"highlight_red\">[setting.async.enable = true]</span></p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b></p>\n\t<h4 class=\"topLine\"><b>parentNode</b><span>JSON</span></h4>\n\t<p>Parent node's JSON data object</p>\n\t<p class=\"highlight_red\">When asynchronously loading the root, the parentNode = null</p>\n\t<h4 class=\"topLine\"><b>responseData</b><span>Array(JSON) / JSON / String</span></h4>\n\t<p>Array (JSON) / JSON / String data objects</p>\n\t<p class=\"highlight_red\">From v3.4, support XML strings.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Array(JSON) / JSON</span></h4>\n\t<p>The return value should be the JSON data structure which is supported by the zTree.</p>\n\t<p class=\"highlight_red\">v3.x supports to load single node JSON data object.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Modify the node name attributes returned by an Ajax request.</h4>\n\t<pre xmlns=\"\"><code>function ajaxDataFilter(treeId, parentNode, responseData) {\n    if (responseData) {\n      for(var i =0; i < responseData.length; i++) {\n        responseData[i].name += \"_filter\";\n      }\n    }\n    return responseData;\n};\nvar setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\tdataFilter: ajaxDataFilter\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.async.dataType.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.async.</span>dataType</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The data type of Ajax requests. It is valid when <span class=\"highlight_red\">[setting.async.enable = true]</span></p>\n\t\t\t<p>Default：\"text\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p> dataType = \"text\", There is probably no need to change this.</p>\n\t<p class=\"highlight_red\">The 'dataType' in zTree and jQuery's ajax requests is same.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set the dataType which ajax retrieves to \"text\".</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\tdataType: \"text\",\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.async.enable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.async.</span>enable</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set zTree asynchronous loading mode on/off.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true - turn on asynchronous loading mode</p>\n\t<p> false - turn off asynchronous loading mode</p>\n\t<p class=\"highlight_red\">If set it is true, you must set other attributes in setting.async</p>\n\t<p class=\"highlight_red\">If you don't pass the 'treeNodes' parameter when you initialize zTree, the root nodes will be retrieved using ajax.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Turn on asynchronous loading mode</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.async.otherParam.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Array(String) / JSON</span><span class=\"path\">setting.async.</span>otherParam</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The query parameters of the Ajax request. (key - value) It is valid when <span class=\"highlight_red\">[setting.async.enable = true]</span></p>\n\t\t\t<p>Default: [ ]</p>\n\t\t</div>\n\t</div>\n\t<h3>Array(String) Format</h3>\n\t<div class=\"desc\">\n\t<p>Can be an empty array. e.g. [ ].  The array should contain key value pairs, e.g. [key, value]. (Either or [key] or [key, value, key] is wrong!!)</p>\n\t</div>\n\t<h3>JSON Format</h3>\n\t<div class=\"desc\">\n\t<p>Use JSON hash data to set the key-value pairs. e.g. { key1:value1, key2:value2 }</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Using Array(String) Format</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\t<span style=\"color:red\">otherParam: [\"id\", \"1\", \"name\", \"test\"]</span>\n\t}\n};\nwhen zTree sends the ajax request, the query string will be like this: id=1&name=test</code></pre>\n\t<h4>2. Using JSON data Format</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"http://host/getNode.php\",\n\t\t<span style=\"color:red\">otherParam: { \"id\":\"1\", \"name\":\"test\"}</span>\n\t}\n};\nwhen zTree sends the ajax request, the query string will be like this: id=1&name=test</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.async.type.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.async.</span>type</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Http request tyoe in ajax. It is valid when <span class=\"highlight_red\">[setting.async.enable = true]</span></p>\n\t\t\t<p>Default: \"post\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p> \"post\" - http request mode</p>\n\t<p> \"get\" - http request mode</p>\n\t<p class=\"highlight_red\">Both zTree and jQuery's this 'type' for ajax requests.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set http request mode is 'get'</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\ttype: \"get\",\n\t\turl: \"http://host/getNode.php\",\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.async.url.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String / Function(treeId, treeNode)</span><span class=\"path\">setting.async.</span>url</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The URL to which the ajax request is sent. It is valid when <span class=\"highlight_red\">[setting.async.enable = true]</span></p>\n\t\t\t<p>Default: \"\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>A url string(e.g. \"http://www.domain.com/cgi-bin/my-script.cgi\"). Note: please check that the url can be loaded with a browser</p>\n\t<p class=\"highlight_red\">Url can also take parameters, please note that they need to be urlencoded.</p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>Parent node's JSON data object</p>\n\t<p class=\"highlight_red\">When asynchronously loading the root, the treeNode = null</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>String</span></h4>\n\t<p>Return value is same as 'String Format'</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. set ajax url is \"nodes.php\"</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: \"nodes.php\",\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n\t<h4>2. set ajax url is \"function\"</h4>\n\t<pre xmlns=\"\"><code>function getAsyncUrl(treeId, treeNode) {\n    return treeNode.isParent ? \"nodes1.php\" : \"nodes2.php\";\n};\nvar setting = {\n\tasync: {\n\t\tenable: true,\n\t\turl: getAsyncUrl,\n\t\tautoParam: [\"id\", \"name\"]\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeAsync.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeAsync</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>This callback is made before zTree makes an ajax request, giving you an opportunity to decide if it should proceed or not. \n                            Return false to prevent zTree from sending the ajax request.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the parent node</p>\n\t<p class=\"highlight_red\">When asynchronously loading the root, treeNode = null</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If the function returns false, zTree will not send the ajax request, and will not trigger the 'onAsyncSuccess / onAsyncError' callback.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. If the parent node's attribute 'id' is 1, don't send the ajax request.</h4>\n\t<pre xmlns=\"\"><code>function myBeforeCallBack(treeId, treeNode) {\n    return (treeNode.id !== 1);\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeAsync: myBeforeCallBack\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeCheck.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeCheck</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback before checking or unchecking a node, A false return value from the callback will prevent any change in the checked state.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which is checked or unchecked</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, zTree will not change the checkbox state, and will not trigger the 'onCheck' callback.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. This example returns false, preventing all checkboxes in the tree from toggling.</h4>\n\t<pre xmlns=\"\"><code>function myBeforeCheckCallBack(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeCheck: myBeforeCheckCallBack\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode, clickFlag)</span><span class=\"path\">setting.callback.</span>beforeClick</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Before click callback, return false to prevent the 'onClick' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which is clicked</p>\n\t<h4 class=\"topLine\"><b>clickFlag</b><span>Number</span></h4>\n\t<p>Node is selected or deselected state, please see table below for details</p>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead><tr><td>clickFlag</td><td title=\"Whether to allow multi-select\">selectedMulti</td><td title=\"Whether to press Ctrl-key or Cmd-key\">autoCancelSelected<br/>&&<br/>event.ctrlKey / metaKey</td><td title=\"Node's selection state\">isSelected</td><td>operate for selected</td></tr></thead>\n\t\t<tbody>\n\t\t\t<tr><td>1</td><td>true</td><td>false</td><td>false</td><td>node is selected (single)</td></tr>\n\t\t\t<tr><td>1</td><td>true</td><td>false</td><td>true</td><td>node is selected (single)</td></tr>\n\t\t\t<tr><td>2</td><td>true</td><td>true</td><td>false</td><td>node is selected (multi)</td></tr>\n\t\t\t<tr><td>0</td><td>true</td><td>true</td><td>true</td><td>node is deselected</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>false</td><td>false</td><td>node is selected (single)</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>false</td><td>true</td><td>node is selected (single)</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>true</td><td>false</td><td>node is selected (single)</td></tr>\n\t\t\t<tr><td>0</td><td>false</td><td>true</td><td>true</td><td>node is deselected</td></tr>\n\t\t</tbody>\n\t</table>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, zTree will not change selected state, and will not trigger the 'onClick' callback.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disabled to click the node</h4>\n\t<pre xmlns=\"\"><code>function myBeforeClick(treeId, treeNode, clickFlag) {\n    return (treeNode.id !== 1);\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeClick: myBeforeClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeCollapse.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeCollapse</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Specify callback function to be called before collapse node, The return value controls the  collapse node.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be collapsed</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, zTree will not collapse node, and will not trigger the 'onCollapse' callback.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disabled to collapse node which is expanded</h4>\n\t<pre xmlns=\"\"><code>function myBeforeCollapse(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeCollapse: myBeforeCollapse\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeDblClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeDblClick</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Specify callback function, executed before the 'onDblClick' callback, The return value controls the 'onDblClick' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which is double clicked</p>\n\t<p class=\"highlight_red\">If the DOM which dblclicked isn't a node, it will return null.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, ztree will not trigger the 'onDblClick' callback, no effect on other operations.</p>\n\t<p class=\"highlight_red\">This callback function does not affect the auto expand of the parent node , please refer to setting.view.dblClickExpand properties.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable to trigger the 'onDblClick' callback</h4>\n\t<pre xmlns=\"\"><code>function myBeforeDblClick(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeDblClick: myBeforeDblClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeDrag.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNodes)</span><span class=\"path\">setting.callback.</span>beforeDrag</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Specify callback function to be called before the drag node callback, The return value controls whether the drag node callback will execute.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>, the id of the containing tree.</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>A collection of the nodes being dragged</p>\n\t<p class=\"highlight_red\">v3.x allows the drag and drop of multiple sibling nodes, so this parameter's type is changed to Array(JSON).</p>\n\t<p class=\"highlight_red\">If the selected nodes aren't sibling nodes, you can only drag one node.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, zTree will abort the drag and drop, and will not trigger the 'onDrag / beforeDrop / onDrop' sequence of callbacks.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable drag completely (by returning false)</h4>\n\t<pre xmlns=\"\"><code>function myBeforeDrag(treeId, treeNodes) {\n    return false;\n};\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeDrag: myBeforeDrag\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeDragOpen.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeDragOpen</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback executed before drag node to collapsed parent node, The return value controls the auto expand behaviour of the parent node.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>, the tree is what the treeNode(parent node) is belong to.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the parent node which will be auto expanded</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, zTree will not auto expand parent node.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable to auto expand parent node.</h4>\n\t<pre xmlns=\"\"><code>function myBeforeDragOpen(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeDragOpen: myBeforeDragOpen\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeDrop.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNodes, targetNode, moveType, isCopy)</span><span class=\"path\">setting.callback.</span>beforeDrop</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Specify callback function to be called before drag-drop of a node, The return value controls the execution of drag-drop callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t\t<p class=\"highlight_red\">When a node is dropped, if the drop is not in a valid location, this callback will not be triggered, and will revert to the original position.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>, the id of the containing tree.</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>A collection of the nodes which has been dragged</p>\n\t<p class=\"highlight_red\">The treeNodes which have been dragged, when copying nodes or moving nodes.</p>\n\t<h4 class=\"topLine\"><b>targetNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the destination node on which treeNodes are being dropped.</p>\n\t<p class=\"highlight_red\">If the treeNodes is the root node, the targetNode = null</p>\n\t<h4 class=\"topLine\"><b>moveType</b><span>String</span></h4>\n\t<p>the relative position of move to the target node</p>\n\t<p class=\"highlight_red\">\"inner\": will be child of targetNode</p>\n\t<p class=\"highlight_red\">\"prev\": will be sibling node, and be in front of targetNode</p>\n\t<p class=\"highlight_red\">\"next\":  will be sibling node, and be behind targetNode</p>\n\t<h4 class=\"topLine\"><b>isCopy</b><span>Boolean</span></h4>\n\t<p>the flag used to determine if the drop is to copy or move the node</p>\n\t<p class=\"highlight_red\">true: copy node; false: move node</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, zTree will restore the dragged nodes, and will not trigger the 'onDrop' callback.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable to drag nodes to root</h4>\n\t<pre xmlns=\"\"><code>function myBeforeDrop(treeId, treeNodes, targetNode, moveType) {\n    return !(targetNode == null || (moveType != \"inner\" && !targetNode.parentTId));\n};\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeDrop: myBeforeDrop\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeEditName.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeEditName</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Specify callback function to be called before click edit button, The return value controls the editing of the name.</p>\n\t\t\t<p class=\"highlight_red\">This callback is fired when the edit button is clicked, to control the custom editing operation.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be edited.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, allow editing of the name.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable editing of any parent node's name</h4>\n\t<pre xmlns=\"\"><code>function myBeforeEditName(treeId, treeNode) {\n\treturn !treeNode.isParent;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeEditName: myBeforeEditName\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeExpand.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeExpand</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Specify callback function to be called before expanding a node, The return value controls the expand node callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be expanded</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, zTree will not expand node, and will not trigger the 'onExpand' callback.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disables expanding of all nodes</h4>\n\t<pre xmlns=\"\"><code>function myBeforeExpand(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeExpand: myBeforeExpand\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeMouseDown.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeMouseDown</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Specify callback function, executed before the 'onMouseDown' callback, The return value controls the 'onMouseDown' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which mouse over</p>\n\t<p class=\"highlight_red\">If the DOM which mouse over isn't a node, it will return null.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, zTree will not trigger the 'onMouseDown' callback, no effect on other operations.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable to trigger the 'onMouseDown' callback</h4>\n\t<pre xmlns=\"\"><code>function myBeforeMouseDown(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeMouseDown: myBeforeMouseDown\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeMouseUp.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeMouseUp</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Specify callback function, executed before the 'onMouseUp' callback, The return value controls the 'onMouseUp' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which mouse over</p>\n\t<p class=\"highlight_red\">If the DOM which mouse over isn't a node, it will return null.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, zTree will not trigger the 'onMouseUp' callback, no effect on other operations.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable to trigger the 'onMouseUp' callback</h4>\n\t<pre xmlns=\"\"><code>function myBeforeMouseUp(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeMouseUp: myBeforeMouseUp\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeRemove.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeRemove</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Specify callback function to be called before remove node, The return value controls the  allow to remove node.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be removed.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, zTree will not remove node, and will not trigger the 'onRemove' callback.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable to remove node</h4>\n\t<pre xmlns=\"\"><code>function myBeforeRemove(treeId, treeNode) {\n\treturn false;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeRemove: myBeforeRemove\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeRename.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode, newName, isCancel)</span><span class=\"path\">setting.callback.</span>beforeRename</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Specify callback function to be called before rename(when input DOM blur or press Enter Key), The return value controls the  allow to rename node.</p>\n\t\t\t<p class=\"highlight_red\">When node is editing name, press the ESC key to restore the original name and stop edit name.</p>\n\t\t\t<p class=\"highlight_red\">From v3.5.13, zTree will trigger this callback when user cancel edit name. please see 'isCancel' parameter.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be rename.</p>\n\t<h4 class=\"topLine\"><b>newName</b><span>String</span></h4>\n\t<p>the new name</p>\n\t<h4 class=\"topLine\"><b>isCancel</b><span>Boolean</span></h4>\n\t<p>the status about cancel edit name (v3.5.13+)</p>\n\t<p class=\"highlight_red\">isCancel = true means: user cancel edit name. (press ESC or use cancelEditName() function)</p>\n\t<p class=\"highlight_red\">isCancel = false means: user submit edit name.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, the treeNode will keep the editing name, don't trigger the 'onRename' callback, and will ignore other enents, until the callback return true.</p>\n\t<p class=\"highlight_red\">If returns false, zTree will not set the input box to get focus to avoid the warning message which led to repeated triggering ‘beforeRename’ callback. Please use editName() method to set the input box to get focus when user close the warning message.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. the length of the new name can't less than 5</h4>\n\t<pre xmlns=\"\"><code>function myBeforeRename(treeId, treeNode, newName, isCancel) {\n\treturn newName.length > 5;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true\n\t},\n\tcallback: {\n\t\tbeforeRename: myBeforeRename\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.beforeRightClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.callback.</span>beforeRightClick</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to capture the right click event before the 'onRightClick' callback, The return value controls the 'onRightClick' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which is mouse right clicked</p>\n\t<p class=\"highlight_red\">If the DOM which mouse right clicked isn't a node, it will return null.</p>\n\t<h4 class=\"topLine\"><b>Return</b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t<p class=\"highlight_red\">If return false, ztree will not trigger the 'onRightClick' callback, no effect on other operations.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable to trigger the 'onRightClick' callback</h4>\n\t<pre xmlns=\"\"><code>function myBeforeRightClick(treeId, treeNode) {\n    return false;\n};\nvar setting = {\n\tcallback: {\n\t\tbeforeRightClick: myBeforeRightClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onAsyncError.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span class=\"path\">setting.callback.</span>onAsyncError</h2>\n\t<h2><span>Function(event, treeId, treeNode, XMLHttpRequest, textStatus, errorThrown)</span>&nbsp;</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to capture the error event when execute ajax.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeAsync',and return false, zTree will not execute ajax, and will not trigger the 'onAsyncSuccess / onAsyncError' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the parent node</p>\n\t<p class=\"highlight_red\">When load root nodes, treeNode = null</p>\n\t<h4 class=\"topLine\"><b>XMLHttpRequest</b><span>String</span></h4>\n\t<p>XMLHttpRequest Object, please refer to JQuery API documentation.</p>\n\t<h4 class=\"topLine\"><b>textStatus</b><span>String</span></h4>\n\t<p>a string categorizing the status of the request(\"success\", \"error\"...), please refer to JQuery API documentation.</p>\n\t<h4 class=\"topLine\"><b>errorThrown</b><span>String</span></h4>\n\t<p>eWhen an HTTP error occurs, errorThrown receives the textual portion of the HTTP status, please refer to JQuery API documentation.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When execute ajax make error, alert message.</h4>\n\t<pre xmlns=\"\"><code>function myOnAsyncError(event, treeId, treeNode, XMLHttpRequest, textStatus, errorThrown) {\n    alert(XMLHttpRequest);\n};\nvar setting = {\n\tcallback: {\n\t\tonAsyncError: myOnAsyncError\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onAsyncSuccess.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode, msg)</span><span class=\"path\">setting.callback.</span>onAsyncSuccess</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to capture the complete success event when execute ajax.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeAsync',and return false, zTree will not execute ajax, and will not trigger the 'onAsyncSuccess / onAsyncError' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the parent node</p>\n\t<p class=\"highlight_red\">When load root nodes, treeNode = null</p>\n\t<h4 class=\"topLine\"><b>msg</b><span>String / Object</span></h4>\n\t<p>The actualnode data which got by ajax. User-friendly debugging.</p>\n\t<p class=\"highlight_red\">The actual data's type of msg is affected by 'setting.async.dataType', please refer to JQuery API documentation.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When execute ajax complete success, alert message.</h4>\n\t<pre xmlns=\"\"><code>function myOnAsyncSuccess(event, treeId, treeNode, msg) {\n    alert(msg);\n};\nvar setting = {\n\tcallback: {\n\t\tonAsyncSuccess: myOnAsyncSuccess\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onCheck.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onCheck</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to capture the check or uncheck event when check or uncheck the checkbox and radio.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeCheck',and return false, zTree will not change check state, and will not trigger the 'onCheck' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which is checked or unchecked</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When check or uncheck the checkbox and radio, alert info about 'tId' and 'name' and 'checked'.</h4>\n\t<pre xmlns=\"\"><code>function myOnCheck(event, treeId, treeNode) {\n    alert(treeNode.tId + \", \" + treeNode.name + \",\" + treeNode.checked);\n};\nvar setting = {\n\tcallback: {\n\t\tonCheck: myOnCheck\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode, clickFlag)</span><span class=\"path\">setting.callback.</span>onClick</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to capture the click event when click node.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeClick',and return false, zTree will not change selected state, and will not trigger the 'onClick' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which is clicked</p>\n\t<h4 class=\"topLine\"><b>clickFlag</b><span>Number</span></h4>\n\t<p>Node is selected or deselected state, please see table below for details</p>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead><tr><td>clickFlag</td><td title=\"Whether to allow multi-select\">selectedMulti</td><td title=\"Whether to press Ctrl-key or Cmd-key\">autoCancelSelected<br/>&&<br/>event.ctrlKey / metaKey</td><td title=\"Node's selection state\">isSelected</td><td>operate for selected</td></tr></thead>\n\t\t<tbody>\n\t\t\t<tr><td>1</td><td>true</td><td>false</td><td>false</td><td>node is selected (single)</td></tr>\n\t\t\t<tr><td>1</td><td>true</td><td>false</td><td>true</td><td>node is selected (single)</td></tr>\n\t\t\t<tr><td>2</td><td>true</td><td>true</td><td>false</td><td>node is selected (multi)</td></tr>\n\t\t\t<tr><td>0</td><td>true</td><td>true</td><td>true</td><td>node is deselected</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>false</td><td>false</td><td>node is selected (single)</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>false</td><td>true</td><td>node is selected (single)</td></tr>\n\t\t\t<tr><td>1</td><td>false</td><td>true</td><td>false</td><td>node is selected (single)</td></tr>\n\t\t\t<tr><td>0</td><td>false</td><td>true</td><td>true</td><td>node is deselected</td></tr>\n\t\t</tbody>\n\t</table>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When click node, alert info about 'tId' and 'name'.</h4>\n\t<pre xmlns=\"\"><code>function myOnClick(event, treeId, treeNode) {\n    alert(treeNode.tId + \", \" + treeNode.name);\n};\nvar setting = {\n\tcallback: {\n\t\tonClick: myOnClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onCollapse.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onCollapse</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback for collapse node.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeCollapse',and return false, zTree will not collapse node, and will not trigger the 'onCollapse' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be collapsed</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When collapse node, alert info about 'tId' and 'name'.</h4>\n\t<pre xmlns=\"\"><code>function myOnCollapse(event, treeId, treeNode) {\n    alert(treeNode.tId + \", \" + treeNode.name);\n};\nvar setting = {\n\tcallback: {\n\t\tonCollapse: myOnCollapse\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onDblClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onDblClick</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to capture the dblclick event when double click node.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeDblClick',and return false, zTree will not trigger the 'onDblClick' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which is double clicked</p>\n\t<p class=\"highlight_red\">If the DOM which dblclicked isn't a node, it will return null.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When double click node, alert info about 'tId' and 'name'.</h4>\n\t<pre xmlns=\"\"><code>function myOnDblClick(event, treeId, treeNode) {\n    alert(treeNode ? treeNode.tId + \", \" + treeNode.name : \"isRoot\");\n};\nvar setting = {\n\tcallback: {\n\t\tonDblClick: myOnDblClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onDrag.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNodes)</span><span class=\"path\">setting.callback.</span>onDrag</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to capture the drag event when drag node.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeDrag',and return false, zTree will stop drag, and will not trigger the 'onDragMove' & 'onDrag' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>, the id of the containing tree.</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>A collection of the nodes which will be dragged</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When drag nodes, alert the number of dragged nodes.</h4>\n\t<pre xmlns=\"\"><code>function myOnDrag(event, treeId, treeNodes) {\n    alert(treeNodes.length);\n};\nvar setting = {\n\tcallback: {\n\t\tonDrag: myOnDrag\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onDragMove.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNodes)</span><span class=\"path\">setting.callback.</span>onDragMove</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to capture the drag-move event when drag & drop node.</p>\n\t\t\t<p class=\"highlight_red\">Mainly used to capture the DOM which the nodes was drag in. </p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>, the id of the containing tree.</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>A collection of the nodes which will be dragged</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When drag nodes, output the target dom.</h4>\n\t<pre xmlns=\"\"><code>function myOnDragMove(event, treeId, treeNodes) {\n\tconsole.log(event.target);\n};\nvar setting = {\n\tcallback: {\n\t\tonDragMove: myOnDragMove\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onDrop.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNodes, targetNode, moveType, isCopy)</span><span class=\"path\">setting.callback.</span>onDrop</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to capture the drop event when drag-drop node.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeDrop',and return false, zTree will restore the dragged nodes, and will not trigger the 'onDrop' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>, the id of the containing tree.</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>A collection of the nodes which has been dragged</p>\n\t<p class=\"highlight_red\">The treeNodes are the data of the nodes which be dragged, when move nodes.</p>\n\t<p class=\"highlight_red\">The treeNodes are the clone data of the nodes which be dragged, when copy nodes.</p>\n\t<h4 class=\"topLine\"><b>targetNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the target node which treeNodes are drag-dropped.</p>\n\t<p class=\"highlight_red\">If the treeNodes will be root node, the targetNode = null</p>\n\t<h4 class=\"topLine\"><b>moveType</b><span>String</span></h4>\n\t<p>the relative position of move to the target node</p>\n\t<p class=\"highlight_red\">\"inner\": will be child of targetNode</p>\n\t<p class=\"highlight_red\">\"prev\": will be sibling node, and be in front of targetNode</p>\n\t<p class=\"highlight_red\">\"next\":  will be sibling node, and be behind targetNode</p>\n\t<p class=\"highlight_red\">If moveType is null, means drag & drop is cancel.</p>\n\t<h4 class=\"topLine\"><b>isCopy</b><span>Boolean</span></h4>\n\t<p>the flag used to judge copy node or move node</p>\n\t<p class=\"highlight_red\">true: copy node; false: move node</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When drag-drop nodes complete, alert the number of dragged nodes and info about targetNode.</h4>\n\t<pre xmlns=\"\"><code>function myOnDrop(event, treeId, treeNodes, targetNode, moveType) {\n    alert(treeNodes.length + \",\" + (targetNode ? (targetNode.tId + \", \" + targetNode.name) : \"isRoot\" ));\n};\nvar setting = {\n\tcallback: {\n\t\tonDrop: myOnDrop\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onExpand.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onExpand</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback for expand node.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeExpand',and return false, zTree will not expand node, and will not trigger the 'onExpand' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be expanded</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When expand node, alert info about 'tId' and 'name'.</h4>\n\t<pre xmlns=\"\"><code>function myOnExpand(event, treeId, treeNode) {\n    alert(treeNode.tId + \", \" + treeNode.name);\n};\nvar setting = {\n\tcallback: {\n\t\tonExpand: myOnExpand\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onMouseDown.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onMouseDown</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback for mouse down.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeMouseDown',and return false, zTree will not trigger the 'onMouseDown' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which mouse over</p>\n\t<p class=\"highlight_red\">If the DOM which mouse over isn't a node, it will return null.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When mouse down, alert info about 'tId' and 'name'.</h4>\n\t<pre xmlns=\"\"><code>function myOnMouseDown(event, treeId, treeNode) {\n    alert(treeNode ? treeNode.tId + \", \" + treeNode.name : \"isRoot\");\n};\nvar setting = {\n\tcallback: {\n\t\tonMouseDown: myOnMouseDown\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onMouseUp.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onMouseUp</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback for mouse up.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeMouseUp',and return false, zTree will not trigger the 'onMouseUp' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which mouse over</p>\n\t<p class=\"highlight_red\">If the DOM which mouse over isn't a node, it will return null.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When mouse up, alert info about 'tId' and 'name'.</h4>\n\t<pre xmlns=\"\"><code>function myOnMouseUp(event, treeId, treeNode) {\n    alert(treeNode ? treeNode.tId + \", \" + treeNode.name : \"isRoot\");\n};\nvar setting = {\n\tcallback: {\n\t\tonMouseUp: myOnMouseUp\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onNodeCreated.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onNodeCreated</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback for node's DOM is created.</p>\n\t\t\t<p class=\"highlight_red\">Because v3.x uses lazy loading technology, so the nodes which doesn't create DOM when initialized will not trigger this callback, until its parent node is expanded.</p>\n\t\t\t<p class=\"highlight_red\">Large amount of data to load, please note: do not set onNodeCreated, can improve performance as when initialized.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which DOM is created</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When node's DOM is created, alert info about 'tId' and 'name'.</h4>\n\t<pre xmlns=\"\"><code>function myOnNodeCreated(event, treeId, treeNode) {\n    alert(treeNode.tId + \", \" + treeNode.name);\n};\nvar setting = {\n\tcallback: {\n\t\tonNodeCreated: myOnNodeCreated\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onRemove.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onRemove</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback for remove node.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeRemove',and return false, zTree will not remove node, and will not trigger the 'onRemove' callback.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which was removed.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When remove node, alert info about 'tId' and 'name'.</h4>\n\t<pre xmlns=\"\"><code>function myOnRemove(event, treeId, treeNode) {\n\talert(treeNode.tId + \", \" + treeNode.name);\n}\nvar setting = {\n\tcallback: {\n\t\tonRemove: myOnRemove\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onRename.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode, isCancel)</span><span class=\"path\">setting.callback.</span>onRename</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback for remove node.</p>\n\t\t\t<p class=\"highlight_red\">1. If you set 'setting.callback.beforeRename',and return false, zTree will keep the editing name, and will not trigger the 'onRename' callback.</p>\n\t\t\t<p class=\"highlight_red\">2. If you modify treeNode data, and use 'updateNode' function, zTree will not trigger the 'onRename' callback.</p>\n\t\t\t<p class=\"highlight_red\">3. From v3.5.13, zTree will trigger this callback when user cancel edit name. please see 'isCancel' parameter.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which was rename.</p>\n\t<h4 class=\"topLine\"><b>isCancel</b><span>Boolean</span></h4>\n\t<p>the status about cancel edit name (v3.5.13+)</p>\n\t<p class=\"highlight_red\">isCancel = true means: user cancel edit name. (press ESC or use cancelEditName() function)</p>\n\t<p class=\"highlight_red\">isCancel = false means: user submit edit name.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When rename node, alert info about 'tId' and 'name'.</h4>\n\t<pre xmlns=\"\"><code>function myOnRename(event, treeId, treeNode, isCancel) {\n\talert(treeNode.tId + \", \" + treeNode.name);\n}\nvar setting = {\n\tcallback: {\n\t\tonRename: myOnRename\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.callback.onRightClick.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(event, treeId, treeNode)</span><span class=\"path\">setting.callback.</span>onRightClick</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Callback for mouse right click node.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.beforeRightClick',and return false, zTree will not trigger the 'onRightClick' callback.</p>\n\t\t\t<p class=\"highlight_red\">If you set 'setting.callback.onRightClick', zTree will shield the browser context menu when mouse right click on zTree.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>event</b><span>js event Object</span></h4>\n\t<p>event Object</p>\n\t<h4 class=\"topLine\"><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which is mouse right clicked</p>\n\t<p class=\"highlight_red\">If the DOM which mouse right clicked isn't a node, it will return null.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. When mouse right click node, alert info about 'tId' and 'name'.</h4>\n\t<pre xmlns=\"\"><code>function myOnRightClick(event, treeId, treeNode) {\n    alert(treeNode ? treeNode.tId + \", \" + treeNode.name : \"isRoot\");\n};\nvar setting = {\n\tcallback: {\n\t\tonRightClick: myOnRightClick\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.check.autoCheckTrigger.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.check.</span>autoCheckTrigger</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When node is automatically checked or unchecked, this parameter used to set to trigger 'beforeCheck / onCheck' callback. It is valid when <span class=\"highlight_red\">[setting.check.enable = true & setting.check.chkStyle = \"checkbox\"]</span></p>\n\t\t\t<p class=\"highlight_red\">1. If you set 'setting.check.chkboxType' to { \"Y\": \"\", \"N\": \"\" }, will not automatically checked or unchecked.</p>\n\t\t\t<p class=\"highlight_red\">2. If you turn on the trigger and there are many more nodes, will affect the performance, because the check or uncheck node can cause many nodes to be automatically checked or unchecked, it will trigger a lot of callbacks, according to the need to decide whether to use this feature.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: trigger callback</p>\n\t<p> false means: don't trigger callback</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. When node is automatically checked or unchecked, zTree trigger 'beforeCheck / onCheck' callback.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tautoCheckTrigger: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.check.chkDisabledInherit.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.check.</span>chkDisabledInherit</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When the parent node's 'chkDisabled' attribute is true, set the child nodes automatically inherit the 'chkDisabled' attribute. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">1. Only be used to initialize the nodes, easy batch operations. Please use the 'updateNode' method modify existing node.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: When add new child nodes, if parent node's 'chkDisabled' attribute is true, the child nodes automatically inherit the 'chkDisabled' attribute.</p>\n\t<p> false means: When add new child nodes, the child nodes don't inherit the 'chkDisabled' attribute from parent node.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1.  When add new child nodes, the child nodes automatically inherit the 'chkDisabled' attribute from parent node.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tchkDisabledInherit: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.check.chkStyle.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.check.</span>chkStyle</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Use the checkbox or radio. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p>Default: \"checkbox\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>When chkStyle = \"checkbox\", zTree show checkbox, and '<span class=\"highlight_red\">setting.check.chkboxType</span>' attribute is valid.\n<br/>When chkStyle = \"radio\", zTree show radio, and '<span class=\"highlight_red\">setting.check.radioType</span>' attribute is valid.</p>\n\t<p class=\"highlight_red\">Please note that letter case, do not change.</p>\n\t</div>\n\t<h3>checkbox States Descriptions</h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p><button type=\"button\" class=\"chk checkbox_false_full\"></button>not checked; <span class=\"highlight_red\">If node is parent, so its child nodes have been not checked.</span> when mouse over: <button type=\"button\" class=\"chk checkbox_false_full_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk checkbox_false_part\"></button>not checked; (only parent node) <span class=\"highlight_red\">some of its child nodes have been checked.</span> when mouse over: <button type=\"button\" class=\"chk checkbox_false_part_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk checkbox_true_full\"></button>be checked; <span class=\"highlight_red\">If node is parent, so its all child nodes have been checked.</span> when mouse over: <button type=\"button\" class=\"chk checkbox_true_full_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk checkbox_true_part\"></button>be checked; (only parent node) <span class=\"highlight_red\">some of its child nodes or all have been not checked.</span> when mouse over: <button type=\"button\" class=\"chk checkbox_true_part_focus\"></button></p>\n\t\t</div>\n\t</div>\n\t<h3>radio States Descriptions</h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p><button type=\"button\" class=\"chk radio_false_full\"></button>not checked; <span class=\"highlight_red\">If node is parent, so its child have been not checked.</span> when mouse over: <button type=\"button\" class=\"chk radio_false_full_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk radio_false_part\"></button>not checked; (only parent node) <span class=\"highlight_red\">some of its child have been checked.</span> when mouse over: <button type=\"button\" class=\"chk radio_false_part_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk radio_true_full\"></button>be checked; <span class=\"highlight_red\">If node is parent, so its child have been not checked.</span> when mouse over: <button type=\"button\" class=\"chk radio_true_full_focus\"></button></p>\n\t\t\t<p><button type=\"button\" class=\"chk radio_true_part\"></button>be checked; (only parent node) <span class=\"highlight_red\">some of its child have been checked.</span> when mouse over: <button type=\"button\" class=\"chk radio_true_part_focus\"></button></p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. use radio</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tchkStyle: \"radio\"\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.check.chkboxType.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>JSON</span><span class=\"path\">setting.check.</span>chkboxType</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When one node is checked or unchecked, control its parent node and its child node auto checked or unchecked. It is valid when <span class=\"highlight_red\">[setting.check.enable = true &amp; setting.check.chkStyle = \"checkbox\"]</span></p>\n\t\t\t<p>Default: { \"Y\": \"ps\", \"N\": \"ps\" }</p>\n\t\t</div>\n\t</div>\n\t<h3>JSON Format</h3>\n\t<div class=\"desc\">\n\t<p>\"Y\" attribute use to set auto check after checkbox was checked.\n<br/>\"N\" attribute use to set auto uncheck after checkbox was unchecked.\n<br/>If value has \"p\", so parent nodes will be checked or unchecked.\n<br/>If value has \"s\", so child nodes will be checked or unchecked.</p>\n\t<p class=\"highlight_red\">Please note that letter case, do not change.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. If check the node, so only auto check parent nodes; If uncheck the node, so only auto uncheck child nodes;</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tchkStyle: \"checkbox\",\n\t\tchkboxType: { \"Y\": \"p\", \"N\": \"s\" }\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.check.enable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.check.</span>enable</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set to use checkbox or radio in zTree</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: use the checkbox or radio</p>\n\t<p> false means: don't use the checkbox or radio</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. use the checkbox</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.check.nocheckInherit.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.check.</span>nocheckInherit</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When the parent node's 'nocheck' attribute is true, set the child nodes automatically inherit the 'nocheck' attribute. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">1. Only be used to initialize the nodes, easy batch operations. Please use the 'updateNode' method modify existing node.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: When add new child nodes, if parent node's 'nocheck' attribute is true, the child nodes automatically inherit the 'nocheck' attribute.</p>\n\t<p> false means: When add new child nodes, the child nodes don't inherit the 'nocheck' attribute from parent node.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1.  When add new child nodes, the child nodes automatically inherit the 'nocheck' attribute from parent node.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tnocheckInherit: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.check.radioType.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.check.</span>radioType</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The group about radio. It is valid when <span class=\"highlight_red\">[setting.check.enable = true &amp; setting.check.chkStyle = \"radio\"]</span></p>\n\t\t\t<p>Default: \"level\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>When radioType = \"level\", will be grouped with same level nodes which have the same parent node.\n<br/>When radioType = \"all\", will be grouped with all nodes.</p>\n\t<p class=\"highlight_red\">Please note that letter case, do not change.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set the group about radio is all nodes.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tcheck: {\n\t\tenable: true,\n\t\tchkStyle: \"radio\",\n\t\tradioType: \"all\"\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.keep.leaf.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.data.keep.</span>leaf</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The leaf node's lock, the leaf node will lock the 'isParent' attribute to false.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: lock the leaf node, and <span class=\"highlight_red\">the node which 'isParent' attribute is false can't add child nodes</span>.</p>\n\t<p> false means: don't lock the leaf node, and <span class=\"highlight_red\">the node which 'isParent' attribute is false can add child nodes</span>.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. lock the leaf node</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkeep: {\n\t\t\tleaf: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.keep.parent.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.data.keep.</span>parent</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The parent node's lock, the parent node will lock 'isParent' attribute to true.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: lock the parent node, and <span class=\"highlight_red\">if remove all of the parent node's child nodes, its 'isParent' attribute still keep to be true.</span>.</p>\n\t<p> false means: don't lock the parent node, and <span class=\"highlight_red\">if remove all of the parent node's child nodes, its 'isParent' attribute will change to be false.</span>.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. lock the parent node</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkeep: {\n\t\t\tparent: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.key.checked.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.key.</span>checked</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The node data's attribute to save the checked state.</p>\n\t\t\t<p>Default: \"checked\"</p>\n\t\t\t<p class=\"highlight_red\">Please don't set the other node attribute which zTree used. (e.g., checkedOld)</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. set the 'isChecked' attribute to save the checked state.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkey: {\n\t\t\tchecked: \"isChecked\"\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.key.children.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.key.</span>children</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The node data's attribute to save the child nodes.</p>\n\t\t\t<p>Default: \"children\"</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set the 'nodes' attribute to save the child nodes.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkey: {\n\t\t\tchildren: \"nodes\"\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.key.name.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.key.</span>name</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The node data's attribute to save the node name.</p>\n\t\t\t<p>Default: \"name\"</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set the 'ename' attribute to save the node name.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkey: {\n\t\t\tname: \"ename\"\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.key.title.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.key.</span>title</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The node data's attribute to save the 'title' attribute of node DOM. It is valid when <span class=\"highlight_red\">[setting.view.showTitle = true]</span></p>\n\t\t\t<p class=\"highlight_red\">If set it to \"\", the title of node DOM will be same as 'setting.data.key.name' attribute.</p>\n\t\t\t<p>Default: \"\"</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set the 'fullName' attribute to save the title of node DOM.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkey: {\n\t\t\ttitle: \"fullName\"\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.key.url.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.key.</span>url</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The node data's attribute to save the node link's url.</p>\n\t\t\t<p class=\"highlight_red\">Special: If the nodes's data can only use the 'url' attribute, and don't use the link to jump feature, you can modify this attribute to any nonexistent attribute.</p>\n\t\t\t<p>Default: \"url\"</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set the 'xUrl' attribute to save the node link's url.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tkey: {\n\t\t\turl: \"xUrl\"\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.simpleData.enable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.data.simpleData.</span>enable</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set zTree's node to accept the simple data format, when zTree is initialized or when ajax get / or when use <span class=\"highlight_red\">addNodes</span> method.</p>\n\t\t\t<p>Don't have to generate the complex nested data.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: zTree's node accept the simple data format.</p>\n\t<p> false means: zTree's node only accept the nested data format.</p>\n\t<p class=\"highlight_red\">If set it is true, you must set the other attributes in 'setting.data.simpleData'. (e.g., idKey, pIdKey, rootPId)  And let the data satisfy the parent-child relationship.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. use the simple data format</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"id\",\n\t\t\tpIdKey: \"pId\",\n\t\t\trootPId: 0\n\t\t}\n\t}\n};\nvar treeNodes = [\n    {\"id\":1, \"pId\":0, \"name\":\"test1\"},\n    {\"id\":11, \"pId\":1, \"name\":\"test11\"},\n    {\"id\":12, \"pId\":1, \"name\":\"test12\"},\n    {\"id\":111, \"pId\":11, \"name\":\"test111\"}\n];\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.simpleData.idKey.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.simpleData.</span>idKey</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The node data's attribute to save node data's unique identifier. It is valid when <span class=\"highlight_red\">[setting.data.simpleData.enable = true]</span></p>\n\t\t\t<p>Default: \"id\"</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. use the simple data format</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"id\",\n\t\t\tpIdKey: \"pId\",\n\t\t\trootPId: 0\n\t\t}\n\t}\n};\nvar treeNodes = [\n    {\"id\":1, \"pId\":0, \"name\":\"test1\"},\n    {\"id\":11, \"pId\":1, \"name\":\"test11\"},\n    {\"id\":12, \"pId\":1, \"name\":\"test12\"},\n    {\"id\":111, \"pId\":11, \"name\":\"test111\"}\n];\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.simpleData.pIdKey.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.data.simpleData.</span>pIdKey</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The node data's attribute to save its parent node data's unique identifier. It is valid when <span class=\"highlight_red\">[setting.data.simpleData.enable = true]</span></p>\n\t\t\t<p>Default: \"pId\"</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. use the simple data format</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"id\",\n\t\t\tpIdKey: \"pId\",\n\t\t\trootPId: 0\n\t\t}\n\t}\n};\nvar treeNodes = [\n    {\"id\":1, \"pId\":0, \"name\":\"test1\"},\n    {\"id\":11, \"pId\":1, \"name\":\"test11\"},\n    {\"id\":12, \"pId\":1, \"name\":\"test12\"},\n    {\"id\":111, \"pId\":11, \"name\":\"test111\"}\n];\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.data.simpleData.rootPId.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String / Number</span><span class=\"path\">setting.data.simpleData.</span>rootPId</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set the default value of root's 'pIdKey' specified attribute values​​. It is valid when <span class=\"highlight_red\">[setting.data.simpleData.enable = true]</span></p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. use the simple data format</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"id\",\n\t\t\tpIdKey: \"pId\",\n\t\t\trootPId: 0\n\t\t}\n\t}\n};\nvar treeNodes = [\n    {\"id\":1, \"pId\":0, \"name\":\"test1\"},\n    {\"id\":11, \"pId\":1, \"name\":\"test11\"},\n    {\"id\":12, \"pId\":1, \"name\":\"test12\"},\n    {\"id\":111, \"pId\":11, \"name\":\"test111\"}\n];\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.autoExpandTrigger.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.edit.drag.</span>autoExpandTrigger</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When drag node cause the parent node is automatically expanded, set whether to allow to trigger the 'onExpand' callback. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: trigger the 'onExpand' callback.</p>\n\t<p> false means: don't trigger the 'onExpand' callback.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set to allow to trigger the 'onExpand' callback</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tautoExpandTrigger: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.autoOpenTime.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">setting.edit.drag.</span>autoOpenTime</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Drag to the parent node, the parent node auto expand time interval. (Unit: ms) It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p>Default: 500</p>\n\t\t\t<p class=\"highlight_red\">Please adjust the value according to needs.</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. When drag node to other parent node, expand it at once.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tautoOpenTime: 0\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.borderMax.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">setting.edit.drag.</span>borderMax</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When drag a node to root, the zTree's inner border width. (Unit: px) It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p>Default: 10</p>\n\t\t\t<p class=\"highlight_red\">Please adjust the value according to needs.</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. adjust the inner border width is 20px</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tborderMax: 20\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.borderMin.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">setting.edit.drag.</span>borderMin</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When drag a node to root, the zTree's outer border width. (Unit: px) It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p>Default: -5</p>\n\t\t\t<p class=\"highlight_red\">Please adjust the value according to needs.</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. adjust the outer border width is 10px</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tborderMin: -10\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.inner.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNodes, targetNode)</span><span class=\"path\">setting.edit.drag.</span>inner</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When drag one node to the target node, set whether to allow the node to be the target node's child. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">If the target node is root, so zTree will only trigger 'inner' and not trigger 'prev / next'.</p>\n\t\t\t<p class=\"highlight_red\">This function mainly for the appropriate limit drag and drop (auxiliary arrow), it requires a combination of 'prev, next' together, to achieve full functionality.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: allow the node to be the target node's child.</p>\n\t<p> false means: don't allow the node to be the target node's child.</p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>A collection of the nodes which has been dragged</p>\n\t<h4 class=\"topLine\"><b>targetNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the target node which treeNodes are draged over.</p>\n\t<p class=\"highlight_red\">If the treeNodes will be root node, the targetNode = null</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable to drag the node to the target node's inner.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: true,\n\t\t\tnext: true,\n\t\t\tinner: false\n\t\t}\n\t}\n};\n......</code></pre>\n\t<h4>2. disable to drag the node to be root node's child.</h4>\n\t<pre xmlns=\"\"><code>function canInner(treeId, nodes, targetNode) {\n\treturn !(targetNode && targetNode.level === 0);\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: true,\n\t\t\tnext: true,\n\t\t\tinner: canInner\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.isCopy.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.edit.drag.</span>isCopy</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When drag-drop node, set whether to allow to copy node. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Rules Description</h3>\n\t<div class=\"desc\">\n\t<p>1. If isCopy = true and isMove = true, when drag-drop node, press Ctrl-Key or Cmd-key can copy node, don't press Ctrl-Key or Cmd-key can move node.</p>\n\t<p>2. If isCopy = true and isMove = false, when drag-drop node, will copy node.</p>\n\t<p>3. If isCopy = false and isMove = true, when drag-drop node, will move node.</p>\n\t<p>4. If isCopy = false and isMove = false, so disable to drag-drop node.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. all of the drag-drop operation will copy node.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tisCopy: true,\n\t\t\tisMove: false\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.isMove.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.edit.drag.</span>isMove</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When drag-drop node, set whether to allow to move node. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Rules Description</h3>\n\t<div class=\"desc\">\n\t<p>1. If isCopy = true and isMove = true, when drag-drop node, press Ctrl-Key or Cmd-key can copy node, don't press Ctrl-Key or Cmd-key can move node.</p>\n\t<p>2. If isCopy = true and isMove = false, when drag-drop node, will copy node.</p>\n\t<p>3. If isCopy = false and isMove = true, when drag-drop node, will move node.</p>\n\t<p>4. If isCopy = false and isMove = false, so disable to drag-drop node.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. all of the drag-drop operation will move node.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tisCopy: false,\n\t\t\tisMove: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.maxShowNodeNum.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">setting.edit.drag.</span>maxShowNodeNum</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When dragging more than one sibling node, the floating layer shows the maximum number of nodes. zTree using '...' instead of redundant nodes. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p>Default: 5</p>\n\t\t\t<p class=\"highlight_red\">Please adjust the value according to needs.</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set the maximum number is 10</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tmaxShowNodeNum: 10\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.minMoveSize.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">setting.edit.drag.</span>minMoveSize</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The minimum offset which used to determine the drag operator start. (Unit: px) It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">Please adjust the value according to needs. Note: If it is too small, will easily lead to misoperation when you click mouse.</p>\n\t\t\t<p>Default: 5</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set the minimum offset is 10px.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tminMoveSize: 10\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.next.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNodes, targetNode)</span><span class=\"path\">setting.edit.drag.</span>next</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When drag one node to the target node, set whether to allow the node to be the target node's next sibling. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">If the target node is root, so zTree will only trigger 'inner' and not trigger 'prev / next'.</p>\n\t\t\t<p class=\"highlight_red\">This function mainly for the appropriate limit drag and drop (auxiliary arrow), it requires a combination of 'prev, inner' together, to achieve full functionality.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: allow the node to be the target node's next sibling.</p>\n\t<p> false means: don't allow the node to be the target node's next sibling.</p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>A collection of the nodes which has been dragged</p>\n\t<h4 class=\"topLine\"><b>targetNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the target node which treeNodes are draged over.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable to drag the node to the target node's next sibling.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: true,\n\t\t\tnext: false,\n\t\t\tinner: true\n\t\t}\n\t}\n};\n......</code></pre>\n\t<h4>2. disable to drag the node to be all of the parent nodes's next sibling.</h4>\n\t<pre xmlns=\"\"><code>function canNext(treeId, nodes, targetNode) {\n\treturn !targetNode.isParent;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: true,\n\t\t\tnext: canNext,\n\t\t\tinner: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.drag.prev.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNodes, targetNode)</span><span class=\"path\">setting.edit.drag.</span>prev</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When drag one node to the target node, set whether to allow the node to be the target node's previous sibling. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">If the target node is root, so zTree will only trigger 'inner' and not trigger 'prev / next'.</p>\n\t\t\t<p class=\"highlight_red\">This function mainly for the appropriate limit drag and drop (auxiliary arrow), it requires a combination of 'next, inner' together, to achieve full functionality.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: allow the node to be the target node's previous sibling.</p>\n\t<p> false means: don't allow the node to be the target node's previous sibling.</p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>A collection of the nodes which has been dragged</p>\n\t<h4 class=\"topLine\"><b>targetNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the target node which treeNodes are draged over.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return true or false</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. disable to drag the node to the target node's previous sibling.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: false,\n\t\t\tnext: true,\n\t\t\tinner: true\n\t\t}\n\t}\n};\n......</code></pre>\n\t<h4>2. disable to drag the node to be all of the parent nodes's previous sibling.</h4>\n\t<pre xmlns=\"\"><code>function canPrev(treeId, nodes, targetNode) {\n\treturn !targetNode.isParent;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tdrag: {\n\t\t\tprev: canPrev,\n\t\t\tnext: true,\n\t\t\tinner: true\n\t\t}\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.editNameSelectAll.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.edit.</span>editNameSelectAll</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When edit node's name, the text in input is selected or unselected. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: when show the input, the text in input is selected</p>\n\t<p> false means: when show the input, the text in input is not selected</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. When edit node's name, the text in input is selected.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\teditNameSelectAll: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.enable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.edit.</span>enable</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set zTree is in edit mode</p>\n\t\t\t<p class=\"highlight_red\">Please set this attribute before zTree initialization. If you need to change the edit mode after the initialization, please use zTreeObj.setEditable() method.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: zTree is in edit mode.</p>\n\t<p> false means: zTree is not in edit mode.</p>\n\t</div>\n\t<h3>Editing Rules Description</h3>\n\t<div class=\"desc\">\n\t<p>1. When click the node, it will not open '<span class=\"highlight_red\">node.url</span>' specified URL.\n<br/>2. Support for dynamic tree editing.\n<br/>3. You can drag-drop nodes, and support drag-drop nodes between multiple trees.\n<br/>4. Support use drag-drop to copy or move the node. (Reference: <span class=\"highlight_red\">setting.edit.drag.isCopy / setting.edit.drag.isMove</span>)\n<br/>5. You can use the Edit button to modify the name attribute.\n<br/>6. You can use the Remove button to remove the node.\n<br/>\n\t</p>\n\t<p class=\"highlight_red\">Please note that letter case, do not change.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. edit the tree</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.removeTitle.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String / Function(treeId, treeNode)</span><span class=\"path\">setting.edit.</span>removeTitle</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>the title of the remove button DOM. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true & setting.edit.showRemoveBtn = true]</span></p>\n\t\t\t<p>Default: \"remove\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>When the mouse over the remove button, the browser auto pop-up message content.</p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which show the remove button</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>String</span></h4>\n\t<p>Return value is same as 'String Format'</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Set title is 'remove the node' about all the remove button</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRemoveBtn: true,\n\t\tremoveTitle: \"remove the node\"\n\t}\n};\n......</code></pre>\n\t<h4>2. Set title is 'remove the parent node' about the parent node, and is 'remove the leaf node' about the leaf node</h4>\n\t<pre xmlns=\"\"><code>function setRemoveTitle(treeId, treeNode) {\n\treturn treeNode.isParent ? \"remove the parent node\":\"remove the leaf node\";\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRemoveBtn: true,\n\t\tremoveTitle: setRemoveTitle\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.renameTitle.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String / Function(treeId, treeNode)</span><span class=\"path\">setting.edit.</span>renameTitle</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>the title of the rename button DOM. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true & setting.edit.showRenameBtn = true]</span></p>\n\t\t\t<p>Default: \"rename\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>When the mouse over the rename button, the browser auto pop-up message content.</p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which show the rename button</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>String</span></h4>\n\t<p>return value is same as 'String Format'</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Set title is 'rename the node' about all the rename button</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRenameBtn: true,\n\t\trenameTitle: \"rename the node\"\n\t}\n};\n......</code></pre>\n\t<h4>2. Set title is 'rename the parent node' about the parent node, and is 'rename the leaf node' about the leaf node</h4>\n\t<pre xmlns=\"\"><code>function setRenameTitle(treeId, treeNode) {\n\treturn treeNode.isParent ? \"rename the parent node\":\"rename the leaf node\";\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRenameBtn: true,\n\t\trenameTitle: setRenameTitle\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.showRemoveBtn.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNode)</span><span class=\"path\">setting.edit.</span>showRemoveBtn</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set to show or hide the remove button. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p>When you click the remove button:</p>\n\t\t\t<p>1. zTree will trigger the <span class=\"highlight_red\">setting.callback.beforeRemove</span> callback, and you can decide whether to allow delete.</p>\n\t\t\t<p>2. If you don't set the 'beforeRemove' or  the 'beforeRemove' callback return true, so zTree will trigger the <span class=\"highlight_red\">setting.callback.onRemove</span> callback after remove the node.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: show the remove button</p>\n\t<p> false means: hide the remove button</p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which show the remove button</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>Return value is same as 'Boolean Format'</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Hide the remove button</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRemoveBtn: false\n\t}\n};\n......</code></pre>\n\t<h4>2. Hide the remove button of parent node</h4>\n\t<pre xmlns=\"\"><code>function setRemoveBtn(treeId, treeNode) {\n\treturn !treeNode.isParent;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRemoveBtn: setRemoveBtn\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.edit.showRenameBtn.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNode)</span><span class=\"path\">setting.edit.</span>showRenameBtn</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set to show or hide the rename button. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p>When you click the rename button:</p>\n\t\t\t<p>1. Click the rename button, you can rename the node.</p>\n\t\t\t<p>2. After rename operation (the input DOM blur or press the Enter Key), zTree will trigger the <span class=\"highlight_red\">setting.callback.beforeRename</span> callback, and you can decide whether to allow rename.</p>\n\t\t\t<p>3. If the 'beforeRename' callback return false, so zTree will keep the edit status. (Press the ESC key, can be restored to the original state.</p>\n\t\t\t<p>4. If you don't set the 'beforeRename' or  the 'beforeRename' callback return true, so zTree will trigger the <span class=\"highlight_red\">setting.callback.onRename</span> callback after rename the node.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: show the rename button</p>\n\t<p> false means: hide the rename button</p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which show the rename button</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>Return value is same as 'Boolean Format'</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Hide the rename button</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRenameBtn: false\n\t}\n};\n......</code></pre>\n\t<h4>2. Hide the rename button of parent node</h4>\n\t<pre xmlns=\"\"><code>function setRenameBtn(treeId, treeNode) {\n\treturn !treeNode.isParent;\n}\nvar setting = {\n\tedit: {\n\t\tenable: true,\n\t\tshowRenameBtn: setRenameBtn\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.treeId.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">setting.</span>treeId</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree unique identifier. After the initialization, it equals to the id attribute value of the user-defined zTree container.</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is an internal argument.</p>\n\t\t</div>\n\t</div>\n\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.treeObj.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Object</span><span class=\"path\">setting.</span>treeObj</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>zTree DOM's jQuery object, the main function: easy to internal operations.</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is an internal argument.</p>\n\t\t</div>\n\t</div>\n\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.addDiyDom.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>addDiyDom</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>This function used to display the custom control on the node.</p>\n\t\t\t<p class=\"highlight_red\">1. If you have huge node data, please note: this function will affect the initialization performance. If not required, it is recommended not to use this function.</p>\n\t\t\t<p class=\"highlight_red\">2. This function is an advanced application, please make sure that a better understanding of zTree before you use it.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which display the custom control.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Display button in all nodes.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\taddDiyDom: addDiyDom\n\t}\n};\nfunction addDiyDom(treeId, treeNode) {\n\tvar aObj = $(\"#\" + treeNode.tId + \"_a\");\n\tif ($(\"#diyBtn_\"+treeNode.id).length>0) return;\n\tvar editStr = \"&lt;span id='diyBtn_space_\" +treeNode.id+ \"' &gt; &lt;/span&gt;\"\n\t\t+ \"&lt;button type='button' class='diyBtn1' id='diyBtn_\" + treeNode.id\n\t\t+ \"' title='\"+treeNode.name+\"' onfocus='this.blur();'&gt;&lt;/button&gt;\";\n\taObj.append(editStr);\n\tvar btn = $(\"#diyBtn_\"+treeNode.id);\n\tif (btn) btn.bind(\"click\", function(){alert(\"diy Button for \" + treeNode.name);});\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.addHoverDom.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>addHoverDom</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to display custom control when mouse move over the node. (e.g. the rename and remove button)</p>\n\t\t\t<p class=\"highlight_red\">If you use this function, so must set <span class=\"highlight_red\">setting.view.removeHoverDom</span>, please make sure that a better understanding of zTree before you use it.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which need to display the custom control.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Display a button when mouse move over the node, and hide the button when mouse move out.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\taddHoverDom: addHoverDom,\n\t\tremoveHoverDom: removeHoverDom,\n\t\t......\n\t}\n};\nfunction addHoverDom(treeId, treeNode) {\n\tvar aObj = $(\"#\" + treeNode.tId + \"_a\");\n\tif ($(\"#diyBtn_\"+treeNode.id).length>0) return;\n\tvar editStr = \"&lt;span id='diyBtn_space_\" +treeNode.id+ \"' &gt;&nbsp;&lt;/span&gt;\"\n\t\t+ \"&lt;button type='button' class='diyBtn1' id='diyBtn_\" + treeNode.id\n\t\t+ \"' title='\"+treeNode.name+\"' onfocus='this.blur();'&gt;&lt;/button&gt;\";\n\taObj.append(editStr);\n\tvar btn = $(\"#diyBtn_\"+treeNode.id);\n\tif (btn) btn.bind(\"click\", function(){alert(\"diy Button for \" + treeNode.name);});\n};\nfunction removeHoverDom(treeId, treeNode) {\n\t$(\"#diyBtn_\"+treeNode.id).unbind().remove();\n\t$(\"#diyBtn_space_\" +treeNode.id).unbind().remove();\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.autoCancelSelected.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.view.</span>autoCancelSelected</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When click the selected node while pressing the Ctrl-key or Cmd-key, allow to cancel selected the node.</p>\n\t\t\t<p class=\"highlight_red\">If you don't need this function, please set to false.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: press the Ctrl-key or Cmd-key, can cancel selected node.</p>\n\t<p> false means: press the Ctrl-key or Cmd-key, can't cancel selected node.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Press the Ctrl-key or Cmd-key, can't cancel selected node.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tautoCancelSelected: false\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.dblClickExpand.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>dblClickExpand</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>When double-click the parent node, 'dblClickExpand' is used to decide whether to expand the parent node.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: When double-click the parent node, zTree will expand the parent node.</p>\n\t<p> false means: When double-click the parent node, zTree will not expand the parent node.</p>\n\t</div>\n\t<h3>Function Pamameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which be double-clicked.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>Return value is same as 'Boolean Format'</p>\n\t</div>\n\t<h3>Example of setting</h3>\n\t<h4>1. When double-click the parent node, zTree will not expand the parent node.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tdblClickExpand: false\n\t}\n};\n......</code></pre>\n\t<h4>2. When double-click the parent node, zTree will expand the parent node which level>0.</h4>\n\t<pre xmlns=\"\"><code>function dblClickExpand(treeId, treeNode) {\n\treturn treeNode.level > 0;\n};\nvar setting = {\n\tview: {\n\t\tdblClickExpand: dblClickExpand\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.expandSpeed.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String / Number</span><span class=\"path\">setting.view.</span>expandSpeed</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The animation speed of expand or collapse node. As same as 'speed' parameter in jQuery</p>\n\t\t\t<p class=\"highlight_red\">In order to ensure zTree operating speed,  if use the IE6,  zTree will not use animation.</p>\n\t\t\t<p>Default: \"fast\"</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>e.g. \"slow\", \"normal\", or \"fast\"</p>\n\t<p class=\"highlight_red\">If set to \"\", zTree will not use animation.</p>\n\t</div>\n\t<h3>Number Format</h3>\n\t<div class=\"desc\">\n\t<p>How long the animation will run. [Unit: ms] (e.g. 1000)</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set the animation speed to slow</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\texpandSpeed: \"slow\"\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.fontCss.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>JSON / Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>fontCss</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Personalized text style, only applies to &lt;A&gt; object in the node DOM</p>\n\t\t\t<p>Default: {}</p>\n\t\t</div>\n\t</div>\n\t<h3>JSON Format</h3>\n\t<div class=\"desc\">\n\t<p>As same as .css() method in jQuery. e.g. <span class=\"highlight_red\">{color:\"#ff0011\", background:\"blue\"}</span></p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which use the personalized text style</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>JSON</span></h4>\n\t<p>Return value is same as 'JSON Format'. e.g. <span class=\"highlight_red\">{color:\"#ff0011\", background:\"blue\"}</span></p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Don't modify css file, and set the node name's color to red</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tfontCss : {color:\"red\"}\n\t}\n};</code></pre>\n\t<h4>2. Don't modify css file, and set the root node name's color to red</h4>\n\t<pre xmlns=\"\"><code>function setFontCss(treeId, treeNode) {\n\treturn treeNode.level == 0 ? {color:\"red\"} : {};\n};\nvar setting = {\n\tview: {\n\t\tfontCss: setFontCss\n\t}\n};</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.nameIsHTML.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.view.</span>nameIsHTML</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set to use HTML in 'name' attribute.</p>\n\t\t\t<p class=\"highlight_red\">If allow HTML, please do check to avoid security issues, e.g. JavaScript Injection...</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: 'name' attribute can be HTML.</p>\n\t<p> false means: 'name' attribute is only TEXT.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Set to allow HTML</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tnameIsHTML: true\n\t}\n};\nvar node = {\"name\":\"&lt;font color='red'&gt;test&lt;/font&gt;\"};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.removeHoverDom.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>removeHoverDom</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to hide custom control when mouse move out the node. (e.g. the rename and remove button)</p>\n\t\t\t<p class=\"highlight_red\">If you use this function, so must set <span class=\"highlight_red\">setting.view.addHoverDom</span>, please make sure that a better understanding of zTree before you use it.</p>\n\t\t\t<p>Default: null</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which need to hide the custom control.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Display a button when mouse move over the node, and hide the button when mouse move out.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\taddHoverDom: addHoverDom,\n\t\tremoveHoverDom: removeHoverDom,\n\t\t......\n\t}\n};\nfunction addHoverDom(treeId, treeNode) {\n\tvar aObj = $(\"#\" + treeNode.tId + \"_a\");\n\tif ($(\"#diyBtn_\"+treeNode.id).length>0) return;\n\tvar editStr = \"&lt;span id='diyBtn_space_\" +treeNode.id+ \"' &gt;&nbsp;&lt;/span&gt;\"\n\t\t+ \"&lt;button type='button' class='diyBtn1' id='diyBtn_\" + treeNode.id\n\t\t+ \"' title='\"+treeNode.name+\"' onfocus='this.blur();'&gt;&lt;/button&gt;\";\n\taObj.append(editStr);\n\tvar btn = $(\"#diyBtn_\"+treeNode.id);\n\tif (btn) btn.bind(\"click\", function(){alert(\"diy Button for \" + treeNode.name);});\n};\nfunction removeHoverDom(treeId, treeNode) {\n\t$(\"#diyBtn_\"+treeNode.id).unbind().remove();\n\t$(\"#diyBtn_space_\" +treeNode.id).unbind().remove();\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.selectedMulti.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.view.</span>selectedMulti</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set whether to allow select multiple nodes.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true mean: you can select multiple nodes.</p>\n\t<p> false mean: you can only select one node.</p>\n\t<p class=\"highlight_red\">1. Press Ctrl-key or Cmd-key, you can select multiple nodes.</p>\n\t<p class=\"highlight_red\">2、This attribute don't affect the feature of cancel select node. ( please see setting.view.autoCancelSelected )</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Only select one node.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tselectedMulti: false\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.showIcon.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>showIcon</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set to show or hide node icon.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: show node icon.</p>\n\t<p> false means: hide node icon.</p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which need to show icon.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>Return value is same as 'Boolean Format'</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Hide node icon</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tshowIcon: false\n\t}\n};\n......</code></pre>\n\t<h4>2. Hide node icon which level=2</h4>\n\t<pre xmlns=\"\"><code>function showIconForTree(treeId, treeNode) {\n\treturn treeNode.level != 2;\n};\nvar setting = {\n\tview: {\n\t\tshowIcon: showIconForTree\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.showLine.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.view.</span>showLine</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set to show or hide line.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: show line.</p>\n\t<p> false means: hide line.</p>\n\t</div>\n\t<h3>Examples of setting</h3>\n\t<h4>1. Hide line</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tshowLine: false\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.showTitle.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean / Function(treeId, treeNode)</span><span class=\"path\">setting.view.</span>showTitle</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set to show or hide the 'title' attribute of node DOM.</p>\n\t\t\t<p class=\"highlight_red\">Please see the <span class=\"highlight_red\">setting.data.key.title</span> attribute</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: show the 'title' attribute of node DOM.</p>\n\t<p> false means: hide the 'title' attribute of node DOM.</p>\n\t<p class=\"highlight_red\">When setting.view.showTitle = true & setting.data.key.title = '', zTree will set the 'setting.data.key.name' attribute to the 'setting.data.key.title'.</p>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeId</b><span>String</span></h4>\n\t<p>zTree unique identifier: <b class=\"highlight_red\">treeId</b>.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which need to show title.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>Return value is same as 'Boolean Format'</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Hide the 'title' attribute of node DOM.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\tshowTitle: false\n\t}\n};\n......</code></pre>\n\t<h4>2. Hide the 'title' attribute of node DOM which level=2.</h4>\n\t<pre xmlns=\"\"><code>function showTitleForTree(treeId, treeNode) {\n\treturn treeNode.level != 2;\n};\nvar setting = {\n\tview: {\n\t\tshowTitle: showTitleForTree\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/setting.view.txtSelectedEnable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">setting.view.</span>txtSelectedEnable</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set to allow or don't allow to select the text which in zTree's DOM.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: Allow to select the txt which in zTree's DOM.</p>\n\t<p> false means: Don't allow to select the txt which in zTree's DOM.</p>\n\t</div>\n\t<h3>Examples of setting & function</h3>\n\t<h4>1. Allow to select the txt which in zTree's DOM.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tview: {\n\t\ttxtSelectedEnable: true\n\t}\n};\n......</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.check_Child_State.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">treeNode.</span>check_Child_State</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to record the node's half-checked state about its all child nodes's checkbox or radio. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">zTree v3.x provides treeNode.getCheckStatus () method to get an accurate the half-checked status.</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is an internal argument.</p>\n\t\t\t<p>Default: true</p>\n\t\t</div>\n\t</div>\n\t<h3>Number Format</h3>\n\t<div class=\"desc\">\n\t<p>Rules:</p>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead>\n\t\t\t<tr><td colspan=\"4\">setting.check.checkType = \"checkbox\"</td></tr>\n\t\t\t<tr><td>treeNode.check_Child_State</td><td>Checked Status Description</td></tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<tr><td>-1</td><td>Has no child nodes or all child nodes's 'nocheck' attribute is true.</td></tr>\n\t\t\t<tr><td>0</td><td>All of the child nodes has not been checked.</td></tr>\n\t\t\t<tr><td>1</td><td>Some of the child nodes has been checked.</td></tr>\n\t\t\t<tr><td>2</td><td>All of the child nodes has been checked.</td></tr>\n\t\t</tbody>\n\t</table>\n\t<br/>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead>\n\t\t\t<tr><td colspan=\"4\">setting.check.checkType = \"radio\"</td></tr>\n\t\t\t<tr><td>treeNode.check_Child_State</td><td>Checked Status Description</td></tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<tr><td>-1</td><td>Has no child nodes or all child nodes's 'nocheck' attribute is true.</td></tr>\n\t\t\t<tr><td>0</td><td>All of the child nodes has not been checked.</td></tr>\n\t\t\t<tr><td>2</td><td>Some of the child nodes has been checked.</td></tr>\n\t\t</tbody>\n\t</table>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.check_Focus.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>check_Focus</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to record the status which the checkbox or radio get focus. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is an internal argument.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p>true means: mouse move over the checkbox</p>\n\t<p>false means: mouse move out the checkbox</p>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.checked.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>checked</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The checked status about node's checkbox or radio. It is valid when <span class=\"highlight_red\">[setting.check.enable = true & treeNode.nocheck = false]</span></p>\n\t\t\t<p class=\"highlight_red\">1. If change the 'checked' to other attribute, please set the 'setting.data.key.checked' attribute.</p>\n\t\t\t<p class=\"highlight_red\">2. If you create node data, and set 'checked' attribute to true, zTree will check this node's checkbox or radio when zTree is initialized.</p>\n\t\t\t<p class=\"highlight_red\">3. Use the treeObj.checkNode or checkAllNodes or updateNode method, you can check or uncheck the node. Please see the API about these methods.</p>\n\t\t\t<p class=\"highlight_red\">4. zTree support identification string 'true' & 'false'.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p>true means: check the checkbox or radio when zTree is initialized.</p>\n\t<p>false means: uncheck the checkbox or radio when zTree is initialized.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. check the checkbox when zTree is initialized</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n{ \"id\":1, \"name\":\"test1\", checked:true },\n{ \"id\":2, \"name\":\"test2\", checked:true }\n]</code></pre>\n\t<h4>2. Get the checked status of the first root node</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar checked = treeObj.getNodes()[0].checked;\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.checkedOld.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>checkedOld</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The checked status about node's checkbox or radio when zTree was initialized. It is valid when <span class=\"highlight_red\">[setting.check.enable = true & treeNode.nocheck = false]</span></p>\n\t\t\t<p class=\"highlight_red\">1. Do not initialize it, it will be initialized when the node is initialized.</p>\n\t\t\t<p class=\"highlight_red\">2. If you need to achieve special features, you can use the zTreeObj.getChangeCheckedNodes method and modify the value of 'checkedOld' attribute.</p>\n\t\t\t<p>Default: the value of 'checked' attribute when zTree is initialized</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p>true means: the checkbox or radio is checked when zTree is initialized.</p>\n\t<p>false means: the checkbox or radio is not checked when zTree is initialized.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Get the original checked status of the first root node</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar checkedOld = treeObj.getNodes()[0].checkedOld;\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.children.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Array(JSON)</span><span class=\"path\">treeNode.</span>children</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The data collections of node's child nodes.</p>\n\t\t\t<p class=\"highlight_red\">1. If change the 'children' to other attribute, please set the 'setting.data.key.children' attribute.</p>\n\t\t\t<p class=\"highlight_red\">2. If you set to use dynamic tree, when a node is expanded which 'isParent' attribute is true and which has no child nodes, zTree will use ajax to get its child nodes.</p>\n\t\t\t<p>Default: undefined</p>\n\t\t</div>\n\t</div>\n\t<h3>Array(JSON) Format</h3>\n\t<div class=\"desc\">\n\t<p>Standard JSON Data object</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Use the standard JSON data object.</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n{ \"id\":1, \"name\":\"test1\",\n\tchildren: [\n\t{ \"id\":3, \"name\":\"test3\"},\n\t{ \"id\":4, \"name\":\"test4\"},\n\t{ \"id\":5, \"name\":\"test5\"}\n\t]\n},\n{ \"id\":2, \"name\":\"test2\"  }\n]</code></pre>\n\t<h4>2. Get the first root node's child nodes</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes()[0].children;\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.chkDisabled.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>chkDisabled</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>1. Set node's checkbox / radio to disabled. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">2. zTree support identification string 'true' & 'false'.</p>\n\t\t\t<p class=\"highlight_red\">3. Please don't change this attribute of the nodes which have been created. If you want to disable or undisable the nodes, please use 'setChkDisabled()' methods.</p>\n\t\t\t<p class=\"highlight_red\">4. When zTree initialize the nodes, if you need to the child nodes automatically inherit the 'chkDisabled' attribute, please see 'setting.check.chkDisabledInherit'.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p class=\"highlight_red\">true means: this node's checkbox / radio is disabled.</p>\n\t<p class=\"highlight_red\">false means: this node's checkbox / radio is able.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. disable some node's checkbox / radio </h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"test1\", \"checked\":true, \"chkDisabled\":true},\n\t{ \"id\":2, \"name\":\"test2\", \"chkDisabled\":true},\n\t{ \"id\":3, \"name\":\"test3\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.click.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>click</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Simple click event operations. As same as : (onclick =\"...\") the code. If the operation is more complex, please use the onClick callback.</p>\n\t\t\t<p class=\"highlight_red\">Because IE is different to other browsers in operating the event of ‘onclick’ and ‘click’ coexistence, please do not use this parameter to control whether to allow the redirection operation (for example: treeNode.click = \"return false;\"). If there is similar requirements, please do not use the 'url' attribute to save the website address, but use the 'onClick' callback to control jumps.</p>\n\t\t\t<p>Default: undefined</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>Standard javascript syntax, for example: alert (\"test\"); etc.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. When click this node, will alert msg.</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"Google CN\", \"url\":\"http://g.cn\", \"click\":\"alert('test');\"},\n\t......\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.diy.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>?</span><span class=\"path\">treeNode.</span>* DIY *</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to save other custom data of node, do not use the same attribute name with ztree used, the user can freely set.</p>\n\t\t</div>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Use 'ename' attribute to save more info</h4>\n\t<pre xmlns=\"\"><code>var node = { \"id\":1, \"name\":\"test1\", \"ename\":\"test eName\"};</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.editNameFlag.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>editNameFlag</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to save the node editing name status. It is valid when <span class=\"highlight_red\">[setting.edit.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is an internal argument.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p>true means: node is being edited.</p>\n\t<p>false means: node is not being edited.</p>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.getCheckStatus.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">treeNode.</span>getCheckStatus</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Get the node's half-checked status of checkbox or radio. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is created by the zTree.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>Return</b><span>JSON</span></h4>\n\t<pre xmlns=\"\"><code>{\n\tchecked: true, //As same as 'treeNode.checked'\n\thalf: true  //Rule the table below\n}</code></pre>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead>\n\t\t\t<tr><td colspan=\"4\">setting.check.checkType = \"checkbox\"</td></tr>\n\t\t\t<tr><td>treeNode.checked</td><td>treeNode.check_Child_State</td><td>treeNode.halfCheck</td><td> half </td></tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<tr><td>-</td><td>-</td><td>true</td><td>true</td></tr>\n\t\t\t<tr><td colspan=\"4\">&nbsp;</td></tr>\n\t\t\t<tr><td>true</td><td>-1</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>true</td><td>0</td><td>false</td><td>true</td></tr>\n\t\t\t<tr><td>true</td><td>1</td><td>false</td><td>true</td></tr>\n\t\t\t<tr><td>true</td><td>2</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td colspan=\"4\">&nbsp;</td></tr>\n\t\t\t<tr><td>false</td><td>-1</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>false</td><td>0</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>false</td><td>1</td><td>false</td><td>true</td></tr>\n\t\t\t<tr><td>false</td><td>2</td><td>false</td><td>true</td></tr>\n\t\t</tbody>\n\t</table>\n\t<br/>\n\t<table width=\"100%\" border=\"0\" cellspacing=\"1\" cellpadding=\"0\">\n\t\t<thead>\n\t\t\t<tr><td colspan=\"4\">setting.check.checkType = \"radio\"</td></tr>\n\t\t\t<tr><td>treeNode.checked</td><td>treeNode.check_Child_State</td><td>treeNode.halfCheck</td><td> half </td></tr>\n\t\t</thead>\n\t\t<tbody>\n\t\t\t<tr><td>-</td><td>-</td><td>true</td><td>true</td></tr>\n\t\t\t<tr><td colspan=\"4\">&nbsp;</td></tr>\n\t\t\t<tr><td>true</td><td>-1</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>true</td><td>0</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>true</td><td>2</td><td>false</td><td>true</td></tr>\n\t\t\t<tr><td colspan=\"4\">&nbsp;</td></tr>\n\t\t\t<tr><td>false</td><td>-1</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>false</td><td>0</td><td>false</td><td>false</td></tr>\n\t\t\t<tr><td>false</td><td>2</td><td>false</td><td>true</td></tr>\n\t\t</tbody>\n\t</table>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Get the first root node's half-checked status</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar halfCheck = treeObj.getNodes()[0].getCheckStatus();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.getNextNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">treeNode.</span>getNextNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Get the treeNode's next sibling node.</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is created by the zTree.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>Return</b><span>JSON</span></h4>\n\t<p>JSON data object of the treeNode's next sibling node</p>\n\t<p class=\"highlight_red\">If have not the next node, return null.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Get the first selected node's next sibling node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar node = sNodes[0].getNextNode();\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.getParentNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">treeNode.</span>getParentNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Get the treeNode's parent node.</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is created by the zTree.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>Return</b><span>JSON</span></h4>\n\t<p>JSON data object of treeNode's parent node.</p>\n\t<p class=\"highlight_red\">If treeNode is root, return null.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Get the first selected node's parent node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar node = sNodes[0].getParentNode();\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.getPreNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">treeNode.</span>getPreNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Get the treeNode's previous sibling node.</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is created by the zTree.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>Return</b><span>JSON</span></h4>\n\t<p>JSON data object of the treeNode's previous sibling node</p>\n\t<p class=\"highlight_red\">If have not the previous node, return null.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Get the first selected node's previous sibling node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar node = sNodes[0].getPreNode();\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.halfCheck.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>halfCheck</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Force node checkBox / radio to the half-checked status. It is valid when <span class=\"highlight_red\">[setting.check.enable = true & treeNode.nocheck = false]</span></p>\n\t\t\t<p class=\"highlight_red\">1. If you force to the half-checked status, zTree will not automatically calculated the half-checked status about this node.</p>\n\t\t\t<p class=\"highlight_red\">2. Until you set treeNode.halfCheck to false or null, zTree will automatically calculated the half-checked status about this node.</p>\n\t\t\t<p class=\"highlight_red\">3. zTree support identification string 'true' & 'false'.</p>\n\t\t\t<p>Defaul: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p>true means: the checkbox or radio is half-checked when zTree is initialized.</p>\n\t<p>false means: the half-checked status will be automatically calculated</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. set the half-checked status when zTree is initialized</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n{ \"id\":1, \"name\":\"test1\", isParent:true, checked:true, halfCheck:true },\n{ \"id\":2, \"name\":\"test2\", isParent:true, checked:false, halfCheck:true },\n{ \"id\":3, \"name\":\"test3\", isParent:true, checked:true },\n{ \"id\":4, \"name\":\"test4\", isParent:true, checked:false }\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.icon.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>icon</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>URL path of node's custom icon.</p>\n\t\t\t<p class=\"highlight_red\">1. If you only set the 'icon' attribute to parent node, the parent node will only show one icon when it is expanded or collapsed.</p>\n\t\t\t<p class=\"highlight_red\">2. If you need to show two icons when it is expanded or collapsed, please set the 'treeNode.iconOpen' and 'treeNode.iconClose' attribute.</p>\n\t\t\t<p class=\"highlight_red\">3. If you need to use css to set the custom icon, please set the 'treeNode.iconSkin' attribute.</p>\n\t\t\t<p>Default: undefined</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>Icon image url can be a relative path or absolute path.</p>\n\t<p class=\"highlight_red\">If use a relative path, please note the relationship between icon image and the page, ensure the correct image path.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Set the custom icon</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t//Only show one icon when it is expanded or collapsed.\n\t{ name:\"Parent Node 1\", icon:\"/img/parent.gif\"},\n\n\t//Show two icons when it is expanded or collapsed.\n\t{ name:\"Parent Node 2\", iconOpen:\"/img/open.gif\", iconClose:\"/img/close.gif\"},\n\n\t//the custom icon for leaf node\n\t{ name:\"Leaf Node\", icon:\"/img/leaf.gif\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.iconClose.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>iconClose</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>URL path of parent node's custom icon when it is collapsed.</p>\n\t\t\t<p class=\"highlight_red\">1. Only parent node support this attribute.</p>\n\t\t\t<p class=\"highlight_red\">2. This attribute must be used simultaneously with 'iconOpen' attribute.</p>\n\t\t\t<p class=\"highlight_red\">3. If you need to use css to set the custom icon, please set the 'treeNode.iconSkin' attribute.</p>\n\t\t\t<p>Default: undefined</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>Icon image url can be a relative path or absolute path.</p>\n\t<p class=\"highlight_red\">If use a relative path, please note the relationship between icon image and the page, ensure the correct image path.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Set the custom icon</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t//Only show one icon when it is expanded or collapsed.\n\t{ name:\"Parent Node 1\", icon:\"/img/parent.gif\"},\n\n\t//Show two icons when it is expanded or collapsed.\n\t{ name:\"Parent Node 2\", iconOpen:\"/img/open.gif\", iconClose:\"/img/close.gif\"},\n\n\t//the custom icon for leaf node\n\t{ name:\"Leaf Node\", icon:\"/img/leaf.gif\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.iconOpen.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>iconOpen</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>URL path of parent node's custom icon when it is expanded.</p>\n\t\t\t<p class=\"highlight_red\">1. Only parent node support this attribute.</p>\n\t\t\t<p class=\"highlight_red\">2. This attribute must be used simultaneously with 'iconClose' attribute.</p>\n\t\t\t<p class=\"highlight_red\">3. If you need to use css to set the custom icon, please set the 'treeNode.iconSkin' attribute.</p>\n\t\t\t<p>Default: undefined</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>Icon image url can be a relative path or absolute path.</p>\n\t<p class=\"highlight_red\">If use a relative path, please note the relationship between icon image and the page, ensure the correct image path.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Set the custom icon</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t//Only show one icon when it is expanded or collapsed.\n\t{ name:\"Parent Node 1\", icon:\"/img/parent.gif\"},\n\n\t//Show two icons when it is expanded or collapsed.\n\t{ name:\"Parent Node 2\", iconOpen:\"/img/open.gif\", iconClose:\"/img/close.gif\"},\n\n\t//the custom icon for leaf node\n\t{ name:\"Leaf Node\", icon:\"/img/leaf.gif\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.iconSkin.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>iconSkin</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The className of node's custom icon.</p>\n\t\t\t<p class=\"highlight_red\">1. You need to modify the css, add the definition of className.</p>\n\t\t\t<p class=\"highlight_red\">2. The css is simple, convenient, and support the parent node to switch icons when it is expanded or collapsed.</p>\n\t\t\t<p class=\"highlight_red\">3. Recommend the use of CSS Sprites, can reduce repeating load the image, to avoid image flicker.</p>\n\t\t\t<p class=\"highlight_red\">4. The 'iconSkin' support IE6 in zTree v3.x.</p>\n\t\t\t<p class=\"highlight_red\">5. If you need to use image's URL to set the custom icon, please set the 'treeNode.icon' or 'treeNode.iconOpen' or 'treeNode.iconClose' attribute.</p>\n\t\t\t<p>Default: undefined</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>The string about custom icon's className.</p>\n\t</div>\n\t<h3>Examples of css & treeNode</h3>\n\t<h4>1. Set the custom icon</h4>\n\t<pre xmlns=\"\"><code>css example：\n.ztree li span.button.diy01_ico_open, .ztree li span.button.diy01_ico_close{...}\n\n.ztree li span.button.diy02_ico_open{...}\n.ztree li span.button.diy02_ico_close{...}\n\n.ztree li span.button.diy03_ico_docu{...}\n\nnode's data example：\nvar nodes = [\n\t//Only show one icon when it is expanded or collapsed.\n\t{ name:\"Parent Node 1\", iconSkin:\"diy01\"},\n\n\t//Show two icons when it is expanded or collapsed.\n\t{ name:\"Parent Node 2\", iconSkin:\"diy02\"},\n\n\t//the custom icon for leaf node\n\t{ name:\"Leaf Node\", iconSkin:\"diy03\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.isAjaxing.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isAjaxing</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Judge whether the node's child nodes being loaded asynchronously.</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is created by the zTree.</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: the node's child nodes is being loaded asynchronously</p>\n\t<p> false means: the node's child nodes is not being loaded asynchronously</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Judge whether the first selected node's child nodes being loaded asynchronously</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar isAjaxing = sNodes[0].isAjaxing;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.isFirstNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isFirstNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Judge whether the node is the sibling nodes's first node.</p>\n\t\t\t<p class=\"highlight_red\">If you use the 'exhide' pack, so this attribute will only support the node which be shown. </p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is created by the zTree.</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: the node is first node.</p>\n\t<p> false means: the node is not first node.</p>\n\t<p class=\"highlight_red\">If the node has been hidden, isFirstNode = false</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Judge whether the first selected node is the sibling nodes's first node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar isFirstNode = sNodes[0].isFirstNode;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.isHidden.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isHidden</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exhide</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Judge whether the node has been hidden.</p>\n\t\t\t<p class=\"highlight_red\">1. When initialize zTree, the nodes which be set 'isHidden = true' will be hidden.</p>\n\t\t\t<p class=\"highlight_red\"></p>\n\t\t\t<p class=\"highlight_red\">2. Please don't change this attribute of the nodes which have been created. If you want to hide or show nodes, please use 'hideNode() / hideNodes() / showNode() / showNodes()' methods.</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: this node is hidden.</p>\n\t<p> false means: this node is shown.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Judge whether the first root node has been hidden.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getNodes();\nif (sNodes.length > 0) {\n\tvar isHidden = sNodes[0].isHidden;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.isHover.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isHover</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to record the hover status of node's DOM. For 'setting.view.addHoverDom / removeHoverDom'.</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is an internal argument.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p>true means: the node's DOM is in hover.</p>\n\t<p>false means: the node's DOM is not in hover.</p>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.isLastNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isLastNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Judge whether the node is the sibling nodes's last node.</p>\n\t\t\t<p class=\"highlight_red\">If you use the 'exhide' pack, so this attribute will only support the node which be shown. </p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is created by the zTree.</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: the node is last node.</p>\n\t<p> false means: the node is not last node.</p>\n\t<p class=\"highlight_red\">If the node has been hidden, isLastNode = false</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Judge whether the first selected node is the sibling nodes's last node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar isLastNode = sNodes[0].isLastNode;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.isParent.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>isParent</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Judge whether the node is the parent node.</p>\n\t\t\t<p class=\"highlight_red\">1. When zTree initialize the node data, the node which has children is set to true, otherwise false.</p>\n\t\t\t<p class=\"highlight_red\">2. When zTree initialize the node data, if set treeNode.isParent to true, the node will be set to be parent node.</p>\n\t\t\t<p class=\"highlight_red\">3. In order to solve the problem of someone make json data, supporting \"false\", \"true\" format of the data string.</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: the node is parent node.</p>\n\t<p> false means: the node is not parent node.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Judge whether the first selected node is the parent node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar isParent = sNodes[0].isParent;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.level.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Number</span><span class=\"path\">treeNode.</span>level</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The level of node</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is created by the zTree.</p>\n\t\t</div>\n\t</div>\n\t<h3>Number Format</h3>\n\t<div class=\"desc\">\n\t<p class=\"highlight_red\">The root node's level = 0, and next level = 1, ...</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Get the first selected node's level</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar level = sNodes[0].level;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.name.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>name</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The node's name</p>\n\t\t\t<p class=\"highlight_red\">1. If you want to change 'name' attribute, please modify the 'setting.data.key.name' attribute.</p>\n\t\t\t<p>Default: undenfined</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>String object. The HTML special characters are escaped</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Set node's name to 'test1', 'test2', 'test3'</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"test1\"},\n\t{ \"id\":2, \"name\":\"test2\"},\n\t{ \"id\":3, \"name\":\"test3\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.nocheck.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>nocheck</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>1. Set node to hide the checkbox or radio. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">2. zTree support identification string 'true' & 'false'.</p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p class=\"highlight_red\">true means: the node hide the checkbox or radio, and don't affect the checked association, and don't affect its parent node's half-checked status.</p>\n\t<p class=\"highlight_red\">false means: the node show the checkbox or radio.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Hide some node's checkbox / radio </h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"test1\", \"nocheck\":true},\n\t{ \"id\":2, \"name\":\"test2\"},\n\t{ \"id\":3, \"name\":\"test3\"}\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.open.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>open</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to record the parent node's expand status.</p>\n\t\t\t<p class=\"highlight_red\">1. When zTree initialize the node data, if you set treeNode.open = true, zTree will default expand this parent node.</p>\n\t\t\t<p class=\"highlight_red\">2. Leaf node's 'open' attribute is false.</p>\n\t\t\t<p class=\"highlight_red\">3. In order to solve the problem of someone make json data, supporting \"false\", \"true\" format of the data string.</p>\n\t\t\t<p class=\"highlight_red\">4. When setting.async.enable = false, the parent node will be expanded which have no child nodes and its attribute 'open' is true. (v3.5.15+)  </p>\n\t\t\t<p>Default: false</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: the parent node is expanded.</p>\n\t<p> false means: the parent node is collapsed.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Get the first selected node's expand status.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar isOpen = sNodes[0].open;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.parentTId.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>parentTId</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The unique identifier of node's parent node.</p>\n\t\t\t<p class=\"highlight_red\">1. zTree v3.x using 'parentTId' replaced the original 'parentNode' attribute, and increased getParentNode () method, in order to avoid the original 'parentNode' cause the clone () method infinite loop.</p>\n\t\t\t<p class=\"highlight_red\">2. Do not initialize or modify it, it is created by the zTree.</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>String object of node's parent node's tId. please see API about 'treeNode.tId'</p>\n\t<p class=\"highlight_red\">If treeNode is root node, parentTId is null.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Get the first selected node's parent node's tId</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar parentTId = sNodes[0].parentTId;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.tId.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>tId</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The unique identifier of node.</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is created by the zTree.</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>tId rules: setting.treeId + \"_\" + zTree counter</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Get the first selected node's tId</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar tId = sNodes[0].tId;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.target.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>target</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Used to set the target where the node is clicked to open url. It is valid when <span class=\"highlight_red\">[treeNode.url exists]</span></p>\n\t\t\t<p>Default: undefined</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>As same as &lt;a&gt; tag's 'target' attribute. e.g.  '_blank', '_self' or other window name.</p>\n\t<p>if this attribute is omitted, zTree default set it to '_blank'</p>\n\t</div>\n\t<h3>Exmaples of treeNode</h3>\n\t<h4>1. Set target is '_blank'</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"test1\", \"url\":\"http://myTest.com\", \"target\":\"_blank\"},\n\t......\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.url.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>String</span><span class=\"path\">treeNode.</span>url</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The URL of node link</p>\n\t\t\t<p class=\"highlight_red\">1. In edit mode (setting.edit.enable = true) , this feature fails. If you must use a similar feature, please use the 'onClick' callback for their own control.</p>\n\t\t\t<p class=\"highlight_red\">2. If you use  the 'onClick' callback function to control opening URL , then set the URL  in the other custom attribute, do not use the 'url' attribute.</p>\n\t\t\t<p>Default: undefined</p>\n\t\t</div>\n\t</div>\n\t<h3>String Format</h3>\n\t<div class=\"desc\">\n\t<p>As same as &lt;a&gt; tag's 'href' attribute.</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Set the URL is 'g.cn'</h4>\n\t<pre xmlns=\"\"><code>var nodes = [\n\t{ \"id\":1, \"name\":\"Google CN\", \"url\":\"http://g.cn\"},\n\t......\n]</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/treeNode.zAsync.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Boolean</span><span class=\"path\">treeNode.</span>zAsync</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Judge whether the parent node's child nodes will be loaded asynchronously when the parent node is expanded.</p>\n\t\t\t<p class=\"highlight_red\">Do not initialize or modify it, it is created by the zTree.</p>\n\t\t\t<p class=\"highlight_red\">Default：false (the parent node which have no child nodes); true (the parent node which have child nodes or the leaf node)</p>\n\t\t</div>\n\t</div>\n\t<h3>Boolean Format</h3>\n\t<div class=\"desc\">\n\t<p> true means: the node's child nodes will not be loaded asynchronously when the parent node is expanded.</p>\n\t<p> false means: the node's child nodes will be loaded asynchronously when the parent node is expanded.</p>\n\t<p class=\"highlight_red\"> This attribute will not effect to 'reAsyncChildNodes()' method</p>\n\t</div>\n\t<h3>Examples of treeNode</h3>\n\t<h4>1. Judge whether the first selected node's child nodes has been loaded asynchronously</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar sNodes = treeObj.getSelectedNodes();\nif (sNodes.length > 0) {\n\tvar zAsync = sNodes[0].zAsync;\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.addNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(parentNode, newNodes, isSilent)</span><span class=\"path\">zTreeObj.</span>addNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Add nodes</p>\n\t\t\t<p class=\"highlight_red\">In order to avoid duplication data resulting from repeated initialization, zTree v3.x will automatically clone node data when zTree initialized or add nodes. If you need to get the data objects within the zTree, please get the return value of this method.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>parentNode</b><span>JSON</span></h4>\n\t<p>The additional node's parent node. If additional node is root node, please the parentNode is null.</p>\n\t<p class=\"highlight_red\">Please ensure this node data object is a data object within zTree.</p>\n\t<h4 class=\"topLine\"><b>newNodes</b><span>JSON / Array(JSON)</span></h4>\n\t<p>The node data's JSON object collection which need to increase, refer to 'treeNode treeNode data details'</p>\n\t<p class=\"highlight_red\">1. zTree v3.x support to add single node, that is, if you only add a node, you can don't use the array.</p>\n\t<p class=\"highlight_red\">2. If you use simple data model, please refer to the attributes within the 'setting.data.simpleData'.</p>\n\t<h4 class=\"topLine\"><b>isSilent</b><span>Boolean</span></h4>\n\t<p>Set whether to automatically expand the parent node, after add nodes.</p>\n\t<p>isSilent = true means: don't auto expand the parent node. Otherwise auto expand.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Array(JSON)</span></h4>\n\t<p>return the new nodes in zTree</p>\n\t<p class=\"highlight_red\">If the newNodes is single data object, the return value is a array with length is 1.</p>\n\t<p class=\"highlight_red\">Note: the node data JSON object in the return value is not equal to the JSON object in the 'newNodes'.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Add one root node to zTree which id is 'tree'</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar newNode = {name:\"newNode1\"};\nnewNode = treeObj.addNodes(null, newNode);\n</code></pre>\n\t<h4>2. Add three root nodes to zTree which id is 'tree'</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar newNodes = [{name:\"newNode1\"}, {name:\"newNode2\"}, {name:\"newNode3\"}];\nnewNodes = treeObj.addNodes(null, newNodes);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.cancelEditName.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(newName)</span><span class=\"path\">zTreeObj.</span>cancelEditName</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Cancel the edit name status. Can restore the original name, and can also force assigned to a new name.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>newName</b><span>String</span></h4>\n\t<p>Re given a new name</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, then restore the original name.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Cancel edit name, and restore the original name.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.cancelEditName();\n</code></pre>\n\t<h4>2. Cancel edit name , and set the new name.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.cancelEditName(\"test_new_name\");\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.cancelSelectedNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode)</span><span class=\"path\">zTreeObj.</span>cancelSelectedNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>To cancel the selected node.</p>\n\t\t\t<p class=\"highlight_red\">zTree v3.x support to select multiple nodes, so you can cancel a single selected node, and you can cancel all of the selected nodes too.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which need to cancel selected.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<p class=\"highlight_red\">If you omit this parameter,  zTree will cancel all of the selected nodes.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Cancel all of the selected nodes</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.cancelSelectedNode();\n</code></pre>\n\t<h4>2. Cancel the first node of the selected nodes</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nif (nodes.length>0) { \n\ttreeObj.cancelSelectedNode(nodes[0]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.checkAllNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(checked)</span><span class=\"path\">zTreeObj.</span>checkAllNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Check or unCheck all nodes which have been initialized. It is valid when <span class=\"highlight_red\">[setting.check.enable = true & setting.check.chkStyle = \"checkbox\"]</span></p>\n\t\t\t<p class=\"highlight_red\">This method does not trigger 'beforeCheck' or 'onCheck' callback function.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>checked</b><span>Boolean</span></h4>\n\t<p>checked = true means: check all nodes.</p>\n\t<p>checked = false means: uncheck all nodes.</p>\n\t<p class=\"highlight_red\">Don't affect the node which 'nochecked' attribute is true.</p>\n\t<p class=\"highlight_red\">Don't affect the node is not loaded.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. check all nodes</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.checkAllNodes(true);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.checkNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode, checked, checkTypeFlag, callbackFlag)</span><span class=\"path\">zTreeObj.</span>checkNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Check or unCheck a single node. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">Use checkNode() method of zTree v3.x can trigger 'beforeCheck' or 'onCheck' callback function. for reduce redundant code.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which need to be checked or unchecked.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>checked</b><span>Boolean</span></h4>\n\t<p>checked = true means: check node.</p>\n\t<p>checked = false means: uncheck node.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, then toggle check or uncheck depend this node's expanded state.</p>\n\t<p class=\"highlight_red\">Don't affect the node which 'nochecked' attribute is true.</p>\n\t<h4 class=\"topLine\"><b>checkTypeFlag</b><span>Boolean</span></h4>\n\t<p>checkTypeFlag = true means: According to 'setting.check.chkboxType' attribute automatically check or uncheck the parent and child nodes.</p>\n\t<p>checkTypeFlag = false means: only check or uncheck this node, don't affect its parent and child nodes.</p>\n\t<p class=\"highlight_red\">When checkTypeFlag = false and treeNode.checked = checked, will not trigger callback function.</p>\n\t<p class=\"highlight_red\">Don't affect the parent and child nodes which 'nochecked' attribute is true.</p>\n\t<h4 class=\"topLine\"><b>callbackFlag</b><span>Boolean</span></h4>\n\t<p>callbackFlag = true means: call this method, will trigger 'beforeCheck' & 'onCheck' callback.</p>\n\t<p>callbackFlag = false means: call this method, will not trigger callback.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, it is same as 'callbackFlag = false'</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. check the selected nodes</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nfor (var i=0, l=nodes.length; i < l; i++) {\n\ttreeObj.checkNode(nodes[i], true, true);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.copyNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(targetNode, treeNode, moveType, isSilent)</span><span class=\"path\">zTreeObj.</span>copyNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Copy the node</p>\n\t\t\t<p class=\"highlight_red\">When copy nodes, zTree v3.x will clone nodes. If you need to get the data object in zTree, please get the return value of this method.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>targetNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be target.</p>\n\t<p class=\"highlight_red\">If copy the node to root node, please set the 'targetNode' to null.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be copied.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>moveType</b><span>String</span></h4>\n\t<p>Copied to the target node's relative position.</p>\n\t<p class=\"highlight_red\">\"inner\" means: to be taregetNode's child node.</p>\n\t<p class=\"highlight_red\">\"prev\" means: to be taregetNode's previous sibling node.</p>\n\t<p class=\"highlight_red\">\"next\" means: to be taregetNode's next sibling node.</p>\n\t<h4 class=\"topLine\"><b>isSilent</b><span>Boolean</span></h4>\n\t<p>After copy the node, whether to automatically expand its parent node.</p>\n\t<p>isSilent = true means: don't expand its parent node.</p>\n\t<p>isSilent = false or omit this parameter means: expand its parent node.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>JSON</span></h4>\n\t<p>return the new node in zTree</p>\n\t<p class=\"highlight_red\">Note: the node data JSON object in the return value is not equal to the treeNode.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Copy the second root node to the first root node's child node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.copyNode(nodes[0], nodes[1], \"inner\");\n</code></pre>\n\t<h4>2. Copy the second root node to the first root node's previous sibling node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.copyNode(nodes[0], nodes[1], \"before\");\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.destroy.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeId)</span><span class=\"path\">zTreeObj.</span>destroy</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>From zTree v3.4, zTree support the method for destruction.</p>\n\t\t\t<p>1. This method can destroy the zTreeObj's zTree.</p>\n\t\t\t<p class=\"highlight_red\">2. If you want to destory all of the zTrees, you can use the '$.fn.zTree.destroy()' method.</p>\n\t\t\t<p class=\"highlight_red\">3. If you want to use the tree which has been destroyed, you must use the 'init()' method at first.</p>\n\t\t</div>\n\t</div>\n        <h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. destroy the zTree which its id is 'treeDemo'</h4>\n\t<pre xmlns=\"\"><code>var zTreeObj = $.fn.zTree.getZTreeObj(\"treeDemo\");\nzTreeObj.destroy();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.editName.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode)</span><span class=\"path\">zTreeObj.</span>editName</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Start editing the node's name.</p>\n\t\t\t<p class=\"highlight_red\">1. If need to cancel editing the node's name, please use cancelEditName(newName) method.</p>\n\t\t\t<p class=\"highlight_red\">2. This method can be used to set the editing node‘s input box to get focus.</p>\n\t\t\t<p class=\"highlight_red\">3. Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be editing name</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>Retrun </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Start editing the first selected node's name.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.editName(nodes[0]);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.expandAll.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(expandFlag)</span><span class=\"path\">zTreeObj.</span>expandAll</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Expand or collapse all nodes.</p>\n\t\t\t<p class=\"highlight_red\">This method does not trigger 'beforeExpand / onExpand' or 'beforeCollapse / onCollapse' callback function.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>expandFlag</b><span>Boolean</span></h4>\n\t<p>expandFlag = true means: expand all nodes.</p>\n\t<p>expandFlag =  false means: collapse all nodes.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return the result of expand or collapse.</p>\n\t<p>true means: expand all nodes</p>\n\t<p>false means: collapse all nodes</p>\n\t<p>null means: have no parent node to expand or collapse.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Expand all nodes</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.expandAll(true);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.expandNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode, expandFlag, sonSign, focus, callbackFlag)</span><span class=\"path\">zTreeObj.</span>expandNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Expand or collapse single node.</p>\n\t\t\t<p class=\"highlight_red\">Use expandNode() method of zTree v3.x can trigger 'beforeExpand / onExpand' or 'beforeCollapse / onCollapse' callback function. for reduce redundant code.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be expanded or collapsed</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>expandFlag</b><span>Boolean</span></h4>\n\t<p>expandFlag = true means: expand the node.</p>\n\t<p>expandFlag = false means: collapse the node.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, then toggle expand or collapse depend this node's expanded state.</p>\n\t<h4 class=\"topLine\"><b>sonSign</b><span>Boolean</span></h4>\n\t<p>sonSign = true means: expand or collapse all of the child nodes depend the 'expandFlag' parameter.</p>\n\t<p>sonSign = false means: only expand or collapse this node.</p>\n\t<p class=\"highlight_red\">When sonSign = false and treeNode.open = expandFlag, will not trigger the callback.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, it is same as 'sonSign = false'.</p>\n\t<h4 class=\"topLine\"><b>focus</b><span>Boolean</span></h4>\n\t<p>focus = true means: after expand or collapse, set the focus of this node for view.</p>\n\t<p>focus =  false means: after expand or coolapse, don't set the focus of this node.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, it is same as 'focus = true'.</p>\n\t<h4 class=\"topLine\"><b>callbackFlag</b><span>Boolean</span></h4>\n\t<p>callbackFlag = true means: call this method, will trigger 'beforeExpand / onExpand' or 'beforeCollapse / onCollapse' callback.</p>\n\t<p>callbackFlag = false means: call this method, will not trigger callback.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, it is same as 'callbackFlag = false'</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Boolean</span></h4>\n\t<p>return the result of expand or collapse.</p>\n\t<p>true means: expand node</p>\n\t<p>false means: collapse node</p>\n\t<p>null means: the node is not parent node.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Expand the first selected node. (and expand this node's child nodes)</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nif (nodes.length>0) {\n\ttreeObj.expandNode(nodes[0], true, true, true);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.getChangeCheckedNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">zTreeObj.</span>getChangeCheckedNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Get the collection of nodes which be changed checked status. (Compared with the original data checkedOld) It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>Return </b><span>Array(JSON)</span></h4>\n\t<p>return the collection of nodes which be changed checked status (Array)</p>\n\t<p class=\"highlight_red\">If you need to get the collection of nodes which changed the checked status, when nodes be checked or unchecked, so please set treeNode.checkedOld = treeNode.checked ( for all of the be changed checked status nodes ).</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Get the collection of nodes which be changed checked status</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getChangeCheckedNodes();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.getCheckedNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(checked)</span><span class=\"path\">zTreeObj.</span>getCheckedNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Get the collection of nodes which be checked or unchecked. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>checked</b><span>Boolean</span></h4>\n\t<p>checked = true means: get the collection of nodes which be checked</p>\n\t<p>checked = false means: get the collection of nodes which be unchecked</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, it is same as 'checked = true'</p>\n\t<p class=\"highlight_red\">Don't get the nodes which 'nochecked' attribute is true.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Array(JSON)</span></h4>\n\t<p>return the collection of nodes which be checked or unchecked. (Array)</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Get the collection of nodes which be checked.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getCheckedNodes(true);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.getNodeByParam.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(key, value, parentNode)</span><span class=\"path\">zTreeObj.</span>getNodeByParam</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>According to the node data attribute, search the node which exactly matches, and get the JSON object of node.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>key</b><span>String</span></h4>\n\t<p>The name of attribute which need to exactly match</p>\n\t<h4 class=\"topLine\"><b>value</b><span>?</span></h4>\n\t<p>The value which need to exactly match, can be any type, please ensure its type consistent with the attribute values.</p>\n\t<h4 class=\"topLine\"><b>parentNode</b><span>JSON</span></h4>\n\t<p>The search range, you can search node from a parent node's child nodes.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, zTree will search node from all nodes.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>JSON</span></h4>\n\t<p>JSON data object of the node which be searched.</p>\n\t<p class=\"highlight_red\">1. If search none node, return null.</p>\n\t<p class=\"highlight_red\">2. If there are many nodes can be searched, return the first node.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Search the node which its 'id' attribute is 1.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar node = treeObj.getNodeByParam(\"id\", 1, null);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.getNodeByTId.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(tId)</span><span class=\"path\">zTreeObj.</span>getNodeByTId</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>According the unique identifier tId of zTree, quick get the node's JSON data object.</p>\n\t\t\t<p class=\"highlight_red\">Get the node from the cache, don't need to search from all nodes.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>tId</b><span>String</span></h4>\n\t<p>The unique identifier of node.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>JSON</span></h4>\n\t<p>JSON data object of the node which be searched.</p>\n\t<p class=\"highlight_red\">If no result, return null.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. 1. Search the node which its 'tId' attribute is 'tree_10'</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar node = treeObj.getNodeByTId(\"tree_10\");\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.getNodeIndex.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode)</span><span class=\"path\">zTreeObj.</span>getNodeIndex</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Get the node's index in the same level nodes. (start from 0)</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which need to get index.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Number</span></h4>\n\t<p class=\"highlight_red\">return the index. (start from 0)</p>\n\t<p class=\"highlight_red\">If there is no this node, return -1.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Get the first selected node's index in the same level nodes.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nif (nodes.length>0) {\n\tvar index = treeObj.getNodeIndex(nodes[0]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.getNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">zTreeObj.</span>getNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Get all of the nodes in zTree</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>Return </b><span>Array(JSON)</span></h4>\n\t<p>return all of the nodes</p>\n\t<p class=\"highlight_red\">1. This array is a collection of the root nodes  (the default child nodes are in the 'children' attributes);</p>\n\t<p class=\"highlight_red\">2. Traverse all the nodes need to use recursion, or the use of transformToArray() method make the nodes to be a simple array.</p>\n\t<p class=\"highlight_red\">3. For the asynchronous loading mode, can't get the nodes which are yet loaded.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Get all of the nodes</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.getNodesByFilter.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(filter, isSingle, parentNode, invokeParam)</span><span class=\"path\">zTreeObj.</span>getNodesByFilter</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Search the single node's data or collection of nodes's data by custom rules.</p>\n\t\t\t<p class=\"highlight_red\">Can be customized complex search rules.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>filter</b><span>Function</span></h4>\n\t<p>Custom search function. e.g. function filter(node) {...}</p>\n\t<p>filter's parameter: node (node's data -- JSON)</p>\n\t<p>filter's return: boolean (true means: match the rules; false means: don't match the rules)</p>\n\t<h4 class=\"topLine\"><b>isSingle</b><span>Boolean</span></h4>\n\t<p>isSingle = true means: search only one node</p>\n\t<p>isSingle = false means: search the array of the nodes</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, as same as false</p>\n\t<h4 class=\"topLine\"><b>parentNode</b><span>JSON</span></h4>\n\t<p>The search range, you can search node from a parent node's child nodes.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, zTree will search node from all nodes.</p>\n\t<h4 class=\"topLine\"><b>invokeParam</b><span>anything</span></h4>\n\t<p>Custom data object by user, used to calculate in the filter function.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Array(JSON) / JSON</span></h4>\n\t<p>If isSingle = true, will return the first node's data (JSON) what be matched. If no match, return null.</p>\n\t<p>If isSingle = false, will return the array of all nodes's data what be matched. if no match, return [ ].</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Search the nodes which their 'name' contains 'test' and 'level' is 2.</h4>\n\t<pre xmlns=\"\"><code>function filter(node) {\n    return (node.level == 2 && node.name.indexOf(\"test\")>-1);\n}\n......\nvar treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar node = treeObj.getNodesByFilter(filter, true); // search only one node\nvar nodes = treeObj.getNodesByFilter(filter); // search the array of the nodes\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.getNodesByParam.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(key, value, parentNode)</span><span class=\"path\">zTreeObj.</span>getNodesByParam</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>According to the node data attribute, search the nodes which exactly matches, and get the JSON objects collection of nodes.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>key</b><span>String</span></h4>\n\t<p>The name of attribute which need to exactly match</p>\n\t<h4 class=\"topLine\"><b>value</b><span>?</span></h4>\n\t<p>The value which need to exactly match, can be any type, please ensure its type consistent with the attribute values.</p>\n\t<h4 class=\"topLine\"><b>parentNode</b><span>JSON</span></h4>\n\t<p>The search range, you can search node from a parent node's child nodes.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, zTree will search node from all nodes.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Array(JSON)</span></h4>\n\t<p>The JSON data objects collection of the nodes which be searched.</p>\n\t<p class=\"highlight_red\">If search none node, return [ ].</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Search the nodes which their 'name' attribute is 'test'.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodesByParam(\"name\", \"test\", null);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.getNodesByParamFuzzy.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(key, value, parentNode)</span><span class=\"path\">zTreeObj.</span>getNodesByParamFuzzy</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>According to the node data attribute, search the nodes which fuzzy matches, and get the JSON objects collection of nodes.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>key</b><span>String</span></h4>\n\t<p>The name of attribute which need to fuzzy match</p>\n\t<h4 class=\"topLine\"><b>value</b><span>String</span></h4>\n\t<p>The value which need to fuzzy match.</p>\n\t<p class=\"highlight_red\">The type of value can only be String</p>\n\t<h4 class=\"topLine\"><b>parentNode</b><span>JSON</span></h4>\n\t<p>The search range, you can search node from a parent node's child nodes.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, zTree will search node from all nodes.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Array(JSON)</span></h4>\n\t<p>The JSON data objects collection of the nodes which be searched.</p>\n\t<p class=\"highlight_red\">If search none node, return [ ].</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Search the nodes which their 'name' attribute contains the string 'test'.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodesByParamFuzzy(\"name\", \"test\", null);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.getSelectedNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">zTreeObj.</span>getSelectedNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Get the JSON data objects collection of the selected nodes in zTree.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>Return </b><span>Array(JSON)</span></h4>\n\t<p>The JSON data objects collection of the selected nodes.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. get the selected nodes</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.hideNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode)</span><span class=\"path\">zTreeObj.</span>hideNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exhide</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>To hide any node.</p>\n\t\t\t<p class=\"highlight_red\">1. This feature can't support the 'exedit' feature, so please don't use this feature in edit mode.</p>\n\t\t\t<p class=\"highlight_red\">2. If you hide or show the nodes, it will effect the 'isFirstNode' and 'isLastNode' attribute.</p>\n\t\t\t<p class=\"highlight_red\">3. Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be hidden</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>Retrun </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. hide the first root node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.hideNode(nodes[0]);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.hideNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNodes)</span><span class=\"path\">zTreeObj.</span>hideNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exhide</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>To hide a group of nodes.</p>\n\t\t\t<p class=\"highlight_red\">1. This feature can't support the 'exedit' feature, so please don't use this feature in edit mode.</p>\n\t\t\t<p class=\"highlight_red\">2. If you hide or show the nodes, it will effect the 'isFirstNode' and 'isLastNode' attribute.</p>\n\t\t\t<p class=\"highlight_red\">3. Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>the array of the nodes which will be hidden</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>Retrun </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. hide the first root node's children.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.hideNodes(nodes[0].children);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.moveNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(targetNode, treeNode, moveType, isSilent)</span><span class=\"path\">zTreeObj.</span>moveNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Move the node</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>targetNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be target.</p>\n\t<p class=\"highlight_red\">If move the node to root node, please set the 'targetNode' to null.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be moved.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>moveType</b><span>String</span></h4>\n\t<p>Moved to the target node's relative position.</p>\n\t<p class=\"highlight_red\">\"inner\" means: to be taregetNode's child node.</p>\n\t<p class=\"highlight_red\">\"prev\" means: to be taregetNode's previous sibling node.</p>\n\t<p class=\"highlight_red\">\"next\" means: to be taregetNode's next sibling node.</p>\n\t<h4 class=\"topLine\"><b>isSilent</b><span>Boolean</span></h4>\n\t<p>After move the node, whether to automatically expand its parent node.</p>\n\t<p>isSilent = true means: don't expand its parent node.</p>\n\t<p>isSilent = false or omit this parameter means: expand its parent node.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>JSON</span></h4>\n\t<p>return the node which be moved, it is same as the 'treeNode' parameter.</p>\n\t<p class=\"highlight_red\">Return null means: move node has failed. The cause:<br/>\n\t\t&nbsp;1. the targetNode is the treeNode's parent node, and moveType = \"inner\"<br/>\n\t\t&nbsp;2. the targetNode is the treeNode's child node.\n\t</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Move the second root node to the first root node's child node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.moveNode(nodes[0], nodes[1], \"inner\");\n</code></pre>\n\t<h4>2. Move the second root node to the first root node's previous sibling node.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\ntreeObj.moveNode(nodes[0], nodes[1], \"prev\");\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.reAsyncChildNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(parentNode, reloadType, isSilent)</span><span class=\"path\">zTreeObj.</span>reAsyncChildNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Forced asynchronous loading child nodes of parent node. It is valid when <span class=\"highlight_red\">[setting.async.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">You can use this method to reload child nodes.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>parentNode</b><span>JSON</span></h4>\n\t<p>The parent node which will asynchronous loading child nodes.</p>\n\t<p class=\"highlight_red\">1. If parentNode = null, it is same as reload root nodes.</p>\n\t<p class=\"highlight_red\">2. If parentNode.isParent = false, don't load nodes.</p>\n\t<p class=\"highlight_red\">3. Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>reloadType</b><span>String</span></h4>\n\t<p>reloadType = \"refresh\" means: reload child nodes.</p>\n\t<p>reloadType != \"refresh\" means: append to load child nodes.</p>\n\t<h4 class=\"topLine\"><b>isSilent</b><span>Boolean</span></h4>\n\t<p>Set whether to automatically expand the parent node, after load nodes.</p>\n\t<p>isSilent = true means: don't auto expand the parent node. Otherwise auto expand.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. reload root nodes</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.reAsyncChildNodes(null, \"refresh\");\n</code></pre>\n\t<h4>2. reload the first selected node's child nodes.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nif (nodes.length>0) {\n\ttreeObj.reAsyncChildNodes(nodes[0], \"refresh\");\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.refresh.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function()</span><span class=\"path\">zTreeObj.</span>refresh</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Refresh zTree</p>\n\t\t\t<p class=\"highlight_red\">If you have no special need, try not to use this method. If you refresh single node, please use updateNode() method. If you refresh child nodes in dynamic mode, please use the reAsyncChildNodes() method.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. refresh zTree </h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.refresh();\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.removeChildNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(parentNode)</span><span class=\"path\">zTreeObj.</span>removeChildNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Remove a parent node's child nodes</p>\n\t\t\t<p class=\"highlight_red\">1. After remove child nodes, the parent node will become a leaf node. Such as the need to maintain the parent node is still a parent node, set 'setting.data.keep.parent' attribute.</p>\n\t\t\t<p class=\"highlight_red\">2. Do not use this method to empty the root. If you need to empty the root, you can initialization zTree, and set the initial nodes is null.</p>\n\t\t\t<p class=\"highlight_red\">3. This method does not trigger any callback function.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>parentNode</b><span>JSON</span></h4>\n\t<p>The parent node which need to clear its child nodes.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Array(JSON)</span></h4>\n\t<p>Return the parent node's child nodes which have been removed. If has no child nodes, return null.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Remove the first selected node's child nodes</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nif (nodes && nodes.length>0) {\n\ttreeObj.removeChildNodes(nodes[0]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.removeNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode, callbackFlag)</span><span class=\"path\">zTreeObj.</span>removeNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Remove a node</p>\n\t\t\t<p class=\"highlight_red\">Use removeNode() method of zTree v3.x can trigger 'beforeRemove / onRemove' callback function. for reduce redundant code.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be removed.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>callbackFlag</b><span>Boolean</span></h4>\n\t<p>callbackFlag = true means: call this method, will trigger 'beforeRemove' & 'onRemove' callback.</p>\n\t<p>callbackFlag = false means: call this method, will not trigger callback.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, it is same as 'callbackFlag = false'</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Remove all of the selected nodes.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nfor (var i=0, l=nodes.length; i < l; i++) {\n\ttreeObj.removeNode(nodes[i]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.selectNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode, addFlag)</span><span class=\"path\">zTreeObj.</span>selectNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Select a node</p>\n\t\t\t<p class=\"highlight_red\">zTree v3.x supports select multiple nodes.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node to be selected.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>addFlag</b><span>Boolean</span></h4>\n\t<p>addFlag = true means: append to select node, don't affect the previously selected node, can select multiple nodes.</p>\n\t<p>addFlag = false means: select single node, prior the selected node is deselected.</p>\n\t<p class=\"highlight_red\">If setting.view.selectedMulti = false, this para, this parameter is not valid, always select single node</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Exampleso of function</h3>\n\t<h4>1. Select single node which be first selected.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\nif (nodes.length>0) {\n\ttreeObj.selectNode(nodes[0]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.setChkDisabled.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(node, disabled, inheritParent, inheritChildren)</span><span class=\"path\">zTreeObj.</span>setChkDisabled</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.excheck</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Set the node's checkbox or radio is disabled or remove disabled. It is valid when <span class=\"highlight_red\">[setting.check.enable = true]</span></p>\n\t\t\t<p class=\"highlight_red\">1. After the node's checkbox / radio is disabled, it can not be checked or unchecked, but it can affect the half-checked status of the parent node.</p>\n\t\t\t<p class=\"highlight_red\">2. Please do not directly modify the 'chkDisabled' attribute of the loaded node.</p>\n\t\t\t<p class=\"highlight_red\">3. Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which need to be checked or unchecked.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>disabled</b><span>Boolean</span></h4>\n\t<p>disabled = true means: the node's checkbox / radio is disabled.</p>\n\t<p>disabled = false means: the node's checkbox / radio is removed disabled.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, it is same as disabled = false </p>\n\t<p class=\"highlight_red\">Don't affect the node which 'nochecked' attribute is true.</p>\n\t<h4 class=\"topLine\"><b>inheritParent</b><span>Boolean</span></h4>\n\t<p>inheritParent = true means: all parent nodes's disabled status will be same as this node.</p>\n\t<p>inheritParent = false means: all parent nodes's disabled status will be not affected.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, it is same as 'inheritParent = false'</p>\n\t<h4 class=\"topLine\"><b>inheritChildren</b><span>Boolean</span></h4>\n\t<p>inheritChildren = true means: all child nodes's disabled status will be same as this node.</p>\n\t<p>inheritChildren = false means: all child nodes's disabled status will be not affected.</p>\n\t<p class=\"highlight_red\">If this parameter is omitted, it is same as 'inheritChildren = false'</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Set the selected nodes's checkbox / radio to disable.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getSelectedNodes();\nfor (var i=0, l=nodes.length; i < l; i++) {\n\ttreeObj.setChkDisabled(nodes[i], true);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.setEditable.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(editable)</span><span class=\"path\">zTreeObj.</span>setEditable</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exedit</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Edit mode and normal mode switch.</p>\n\t\t\t<p class=\"highlight_red\">To use edit mode, please set the attributes in 'setting.edit'</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>editable</b><span>Boolean</span></h4>\n\t<p>true means: set zTree to edit mode.</p>\n\t<p>false means: set zTree to normal mode.</p>\n\t<h4><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. set zTree to edit mode</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\ntreeObj.setEditable(true);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.setting.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>JSON</span><span class=\"path\">zTreeObj.</span>setting</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>The configuration data of zTree, refer to \"<span class=\"highlight_red\">setting details</span>\" </p>\n\t\t\t<p class=\"highlight_red\">zTree v3.x to cancel the original operation setting method, so users can modify.</p>\n\t\t\t<p class=\"highlight_red\">Note: Modify the parameters which affect zTree initialization will not work, please first understand the different attributes.</p>\n\t\t</div>\n\t</div>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.showNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode)</span><span class=\"path\">zTreeObj.</span>showNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exhide</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>To hide any node which be hidden.</p>\n\t\t\t<p class=\"highlight_red\">1. This feature can't support the 'exedit' feature, so please don't use this feature in edit mode.</p>\n\t\t\t<p class=\"highlight_red\">2. If you hide or show the nodes, it will effect the 'isFirstNode' and 'isLastNode' attribute.</p>\n\t\t\t<p class=\"highlight_red\">3. Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>JSON data object of the node to be shown</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>Retrun </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. show someone node which be hidden.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar node = treeObj.getNodeByParam(\"isHidden\", true);\nif (node) {\n  treeObj.showNode(node);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.showNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNodes)</span><span class=\"path\">zTreeObj.</span>showNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.exhide</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>To show a group of nodes which be hidden.</p>\n\t\t\t<p class=\"highlight_red\">1. This feature can't support the 'exedit' feature, so please don't use this feature in edit mode.</p>\n\t\t\t<p class=\"highlight_red\">2. If you hide or show the nodes, it will effect the 'isFirstNode' and 'isLastNode' attribute.</p>\n\t\t\t<p class=\"highlight_red\">3. Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNodes</b><span>Array(JSON)</span></h4>\n\t<p>the array of the nodes which will be shown</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>Retrun </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. show all of the nodes which be hidden.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodesByParam(\"isHidden\", true);\ntreeObj.showNodes(nodes);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.transformToArray.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNodes)</span><span class=\"path\">zTreeObj.</span>transformToArray</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p></p>\n\t\t\t<p>Transform the zTree nodes data into simple array.  (To avoid the user to write code to traverse all nodes)</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNodes</b><span>Array(JSON) / JSON</span></h4>\n\t<p>JSON data object of the node which need to be transformed.</p>\n\t<p>or JSON data objects collection of the nodes which need to be transformed.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Array(JSON)</span></h4>\n\t<p>The JSON data objects array of the nodes which be transformed.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Transform the zTree nodes data into simple array.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.transformToArray(treeObj.getNodes());\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.transformTozTreeNodes.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(simpleNodes)</span><span class=\"path\">zTreeObj.</span>transformTozTreeNodes</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Transform the simple array into zTree nodes data.</p>\n\t\t\t<p class=\"highlight_red\">If you use this method, you must set 'setting.data.simpleData.idKey' and 'setting.data.simpleData.pIdKey' attribute, and let the data are consistent with parent-child relationship.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>simpleNodes</b><span>Array(JSON) / JSON</span></h4>\n\t<p>JSON data object of the node which need to be transformed.</p>\n\t<p>or JSON data objects array of the nodes which need to be transformed.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>Array(JSON)</span></h4>\n\t<p>Standard data which zTree use. The child nodes are stored in the parent node's 'children' attribute.</p>\n\t<p class=\"highlight_red\">If simpleNodes is a single JSON, so the return array's length is 1.</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Transform the simple array data into zTree nodes format.</h4>\n\t<pre xmlns=\"\"><code>var setting = {\n\tdata: {\n\t\tsimpleData: {\n\t\t\tenable: true,\n\t\t\tidKey: \"id\",\n\t\t\tpIdKey: \"pId\",\n\t\t\trootPId: 0\n\t\t}\n\t}\n};\nvar simpleNodes = [\n    {\"id\":1, \"pId\":0, \"name\":\"test1\"},\n    {\"id\":11, \"pId\":1, \"name\":\"test11\"},\n    {\"id\":12, \"pId\":1, \"name\":\"test12\"},\n    {\"id\":111, \"pId\":11, \"name\":\"test111\"}\n];\nvar treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.transformTozTreeNodes(simpleNodes);\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/api/en/zTreeObj.updateNode.html",
    "content": "<div class=\"apiDetail\">\n<div>\n\t<h2><span>Function(treeNode, checkTypeFlag)</span><span class=\"path\">zTreeObj.</span>updateNode</h2>\n\t<h3>Overview<span class=\"h3_info\">[ depends on <span class=\"highlight_green\">jquery.ztree.core</span> js ]</span></h3>\n\t<div class=\"desc\">\n\t\t<p></p>\n\t\t<div class=\"longdesc\">\n\t\t\t<p>Update node data. Primarily used to update the node's DOM.</p>\n\t\t\t<p class=\"highlight_red\">1. Can update the attributes for display (e.g. 'name', 'target', 'url', 'icon', 'iconSkin', 'checked', 'nocheck'), do not update the other attributes. For example: If you need to expand the node, please use expandNode() method, do not modify the 'open' attribute.</p>\n\t\t\t<p class=\"highlight_red\">2. Use updateNode() method of zTree can't trigger 'beforeCheck' or 'onCheck' callback function.</p>\n\t\t\t<p class=\"highlight_red\">Please use zTree object to executing the method.</p>\n\t\t</div>\n\t</div>\n\t<h3>Function Parameter Descriptions</h3>\n\t<div class=\"desc\">\n\t<h4><b>treeNode</b><span>JSON</span></h4>\n\t<p>JSON data object of the node which need to update.</p>\n\t<p class=\"highlight_red\">Please ensure that this data object is an internal node data object in zTree.</p>\n\t<h4 class=\"topLine\"><b>checkTypeFlag</b><span>Boolean</span></h4>\n\t<p>checkTypeFlag = true means: According to 'setting.check.chkboxType' attribute automatically check or uncheck the parent and child nodes.</p>\n\t<p>checkTypeFlag = false means: only check or uncheck this node, don't affect its parent and child nodes.</p>\n\t<p class=\"highlight_red\">This parameter is valid when 'setting.check.enable = true' and 'setting.check.chkStyle = \"checkbox\"'</p>\n\t<p class=\"highlight_red\">Don't affect the parent and child nodes which 'nochecked' attribute is true.</p>\n\t<h4 class=\"topLine\"><b>Return </b><span>none</span></h4>\n\t<p>no return value</p>\n\t</div>\n\t<h3>Examples of function</h3>\n\t<h4>1. Modify the first selected node's name, and update it.</h4>\n\t<pre xmlns=\"\"><code>var treeObj = $.fn.zTree.getZTreeObj(\"tree\");\nvar nodes = treeObj.getNodes();\nif (nodes.length>0) {\n\tnodes[0].name = \"test\";\n\ttreeObj.updateNode(nodes[0]);\n}\n</code></pre>\n</div>\n</div>"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/css/metroStyle/metroStyle.css",
    "content": "/*-------------------------------------\nzTree Style\n\nversion:    3.4\nauthor:     Hunter.z\nemail:      hunter.z@263.net\nwebsite:    http://code.google.com/p/jquerytree/\n\n-------------------------------------*/\n\n.ztree * {padding:0; margin:0; font-size:12px; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif}\n.ztree {margin:0; padding:5px; color:#333}\n.ztree li{padding:0; margin:0; list-style:none; line-height:17px; text-align:left; white-space:nowrap; outline:0}\n.ztree li ul{ margin:0; padding:0 0 0 18px}\n.ztree li ul.line{ background:url(./img/line_conn.png) 0 0 repeat-y;}\n\n.ztree li a {padding-right:3px; margin:0; cursor:pointer; height:21px; color:#333; background-color: transparent; text-decoration:none; vertical-align:top; display: inline-block}\n.ztree li a:hover {text-decoration:underline}\n.ztree li a.curSelectedNode {padding-top:0px; background-color:#e5e5e5; color:black; height:21px; opacity:0.8;}\n.ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#e5e5e5; color:black; height:21px; border:1px #666 solid; opacity:0.8;}\n.ztree li a.tmpTargetNode_inner {padding-top:0px; background-color:#aaa; color:white; height:21px; border:1px #666 solid;\n  opacity:0.8; filter:alpha(opacity=80)}\n.ztree li a.tmpTargetNode_prev {}\n.ztree li a.tmpTargetNode_next {}\n.ztree li a input.rename {height:14px; width:80px; padding:0; margin:0;\n  font-size:12px; border:1px #585956 solid; *border:0px}\n.ztree li span {line-height:21px; margin-right:2px}\n.ztree li span.button {line-height:0; margin:0; padding: 0; width:21px; height:21px; display: inline-block; vertical-align:middle;\n  border:0 none; cursor: pointer;outline:none;\n  background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;\n  background-image:url(\"./img/metro.png\"); *background-image:url(\"./img/metro.gif\")}\n\n.ztree li span.button.chk {width:13px; height:13px; margin:0 2px; cursor: auto}\n.ztree li span.button.chk.checkbox_false_full {background-position: -5px -5px;}\n.ztree li span.button.chk.checkbox_false_full_focus {background-position: -5px -26px;}\n.ztree li span.button.chk.checkbox_false_part {background-position: -5px -48px;}\n.ztree li span.button.chk.checkbox_false_part_focus {background-position: -5px -68px;}\n.ztree li span.button.chk.checkbox_false_disable {background-position: -5px -89px;}\n.ztree li span.button.chk.checkbox_true_full {background-position: -26px -5px;}\n.ztree li span.button.chk.checkbox_true_full_focus {background-position: -26px -26px;}\n.ztree li span.button.chk.checkbox_true_part {background-position: -26px -48px;}\n.ztree li span.button.chk.checkbox_true_part_focus {background-position: -26px -68px;}\n.ztree li span.button.chk.checkbox_true_disable {background-position: -26px -89px;}\n.ztree li span.button.chk.radio_false_full {background-position: -47px -5px;}\n.ztree li span.button.chk.radio_false_full_focus {background-position: -47px -26px;}\n.ztree li span.button.chk.radio_false_part {background-position: -47px -47px;}\n.ztree li span.button.chk.radio_false_part_focus {background-position: -47px -68px;}\n.ztree li span.button.chk.radio_false_disable {background-position: -47px -89px;}\n.ztree li span.button.chk.radio_true_full {background-position: -68px -5px;}\n.ztree li span.button.chk.radio_true_full_focus {background-position: -68px -26px;}\n.ztree li span.button.chk.radio_true_part {background-position: -68px -47px;}\n.ztree li span.button.chk.radio_true_part_focus {background-position: -68px -68px;}\n.ztree li span.button.chk.radio_true_disable {background-position: -68px -89px;}\n\n.ztree li span.button.switch {width:21px; height:21px}\n.ztree li span.button.root_open{background-position:-105px -63px}\n.ztree li span.button.root_close{background-position:-126px -63px}\n.ztree li span.button.roots_open{background-position: -105px 0;}\n.ztree li span.button.roots_close{background-position: -126px 0;}\n.ztree li span.button.center_open{background-position: -105px -21px;}\n.ztree li span.button.center_close{background-position: -126px -21px;}\n.ztree li span.button.bottom_open{background-position: -105px -42px;}\n.ztree li span.button.bottom_close{background-position: -126px -42px;}\n.ztree li span.button.noline_open{background-position: -105px -84px;}\n.ztree li span.button.noline_close{background-position: -126px -84px;}\n.ztree li span.button.root_docu{ background:none;}\n.ztree li span.button.roots_docu{background-position: -84px 0;}\n.ztree li span.button.center_docu{background-position: -84px -21px;}\n.ztree li span.button.bottom_docu{background-position: -84px -42px;}\n.ztree li span.button.noline_docu{ background:none;}\n\n.ztree li span.button.ico_open{margin-right:2px; background-position: -147px -21px; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.ico_close{margin-right:2px; margin-right:2px; background-position: -147px 0; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.ico_docu{margin-right:2px; background-position: -147px -42px; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.edit {margin-left:2px; margin-right: -1px; background-position: -189px -21px; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.edit:hover {\n  background-position: -168px -21px;\n}\n.ztree li span.button.remove {margin-left:2px; margin-right: -1px; background-position: -189px -42px; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.remove:hover {\n  background-position: -168px -42px;\n}\n.ztree li span.button.add {margin-left:2px; margin-right: -1px; background-position: -189px 0; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.add:hover {\n  background-position: -168px 0;\n}\n.ztree li span.button.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}\n\nul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}\n\nspan.tmpzTreeMove_arrow {width:16px; height:21px; display: inline-block; padding:0; margin:2px 0 0 1px; border:0 none; position:absolute;\n    background-color:transparent; background-repeat:no-repeat; background-attachment: scroll;\n    background-position:-168px -84px; background-image:url(\"./img/metro.png\"); *background-image:url(\"./img/metro.gif\")}\n\nul.ztreeul.ztreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)}\n.ztreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/css/zTreeStyle/zTreeStyle.css",
    "content": "/*-------------------------------------\nzTree Style\n\nversion:\t3.5.17\nauthor:\t\tHunter.z\nemail:\t\thunter.z@263.net\nwebsite:\thttp://code.google.com/p/jquerytree/\n\n-------------------------------------*/\n\n.ztree * {padding:0; margin:0; font-size:12px; font-family: Verdana, Arial, Helvetica, AppleGothic, sans-serif}\n.ztree {margin:0; padding:5px; color:#333}\n.ztree li{padding:0; margin:0; list-style:none; line-height:14px; text-align:left; white-space:nowrap; outline:0}\n.ztree li ul{ margin:0; padding:0 0 0 18px}\n.ztree li ul.line{ background:url(./img/line_conn.gif) 0 0 repeat-y;}\n\n.ztree li a {padding:1px 3px 0 0; margin:0; cursor:pointer; height:17px; color:#333; background-color: transparent;\n\ttext-decoration:none; vertical-align:top; display: inline-block}\n.ztree li a:hover {text-decoration:underline}\n.ztree li a.curSelectedNode {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid; opacity:0.8;}\n.ztree li a.curSelectedNode_Edit {padding-top:0px; background-color:#FFE6B0; color:black; height:16px; border:1px #FFB951 solid; opacity:0.8;}\n.ztree li a.tmpTargetNode_inner {padding-top:0px; background-color:#316AC5; color:white; height:16px; border:1px #316AC5 solid;\n\topacity:0.8; filter:alpha(opacity=80)}\n.ztree li a.tmpTargetNode_prev {}\n.ztree li a.tmpTargetNode_next {}\n.ztree li a input.rename {height:14px; width:80px; padding:0; margin:0;\n\tfont-size:12px; border:1px #7EC4CC solid; *border:0px}\n.ztree li span {line-height:16px; margin-right:2px}\n.ztree li span.button {line-height:0; margin:0; width:16px; height:16px; display: inline-block; vertical-align:middle;\n\tborder:0 none; cursor: pointer;outline:none;\n\tbackground-color:transparent; background-repeat:no-repeat; background-attachment: scroll;\n\tbackground-image:url(\"./img/zTreeStandard.png\"); *background-image:url(\"./img/zTreeStandard.gif\")}\n\n.ztree li span.button.chk {width:13px; height:13px; margin:0 3px 0 0; cursor: auto}\n.ztree li span.button.chk.checkbox_false_full {background-position:0 0}\n.ztree li span.button.chk.checkbox_false_full_focus {background-position:0 -14px}\n.ztree li span.button.chk.checkbox_false_part {background-position:0 -28px}\n.ztree li span.button.chk.checkbox_false_part_focus {background-position:0 -42px}\n.ztree li span.button.chk.checkbox_false_disable {background-position:0 -56px}\n.ztree li span.button.chk.checkbox_true_full {background-position:-14px 0}\n.ztree li span.button.chk.checkbox_true_full_focus {background-position:-14px -14px}\n.ztree li span.button.chk.checkbox_true_part {background-position:-14px -28px}\n.ztree li span.button.chk.checkbox_true_part_focus {background-position:-14px -42px}\n.ztree li span.button.chk.checkbox_true_disable {background-position:-14px -56px}\n.ztree li span.button.chk.radio_false_full {background-position:-28px 0}\n.ztree li span.button.chk.radio_false_full_focus {background-position:-28px -14px}\n.ztree li span.button.chk.radio_false_part {background-position:-28px -28px}\n.ztree li span.button.chk.radio_false_part_focus {background-position:-28px -42px}\n.ztree li span.button.chk.radio_false_disable {background-position:-28px -56px}\n.ztree li span.button.chk.radio_true_full {background-position:-42px 0}\n.ztree li span.button.chk.radio_true_full_focus {background-position:-42px -14px}\n.ztree li span.button.chk.radio_true_part {background-position:-42px -28px}\n.ztree li span.button.chk.radio_true_part_focus {background-position:-42px -42px}\n.ztree li span.button.chk.radio_true_disable {background-position:-42px -56px}\n\n.ztree li span.button.switch {width:18px; height:18px}\n.ztree li span.button.root_open{background-position:-92px -54px}\n.ztree li span.button.root_close{background-position:-74px -54px}\n.ztree li span.button.roots_open{background-position:-92px 0}\n.ztree li span.button.roots_close{background-position:-74px 0}\n.ztree li span.button.center_open{background-position:-92px -18px}\n.ztree li span.button.center_close{background-position:-74px -18px}\n.ztree li span.button.bottom_open{background-position:-92px -36px}\n.ztree li span.button.bottom_close{background-position:-74px -36px}\n.ztree li span.button.noline_open{background-position:-92px -72px}\n.ztree li span.button.noline_close{background-position:-74px -72px}\n.ztree li span.button.root_docu{ background:none;}\n.ztree li span.button.roots_docu{background-position:-56px 0}\n.ztree li span.button.center_docu{background-position:-56px -18px}\n.ztree li span.button.bottom_docu{background-position:-56px -36px}\n.ztree li span.button.noline_docu{ background:none;}\n\n.ztree li span.button.ico_open{margin-right:2px; background-position:-110px -16px; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.ico_close{margin-right:2px; background-position:-110px 0; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.ico_docu{margin-right:2px; background-position:-110px -32px; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.edit {margin-right:2px; background-position:-110px -48px; vertical-align:top; *vertical-align:middle}\n.ztree li span.button.remove {margin-right:2px; background-position:-110px -64px; vertical-align:top; *vertical-align:middle}\n\n.ztree li span.button.ico_loading{margin-right:2px; background:url(./img/loading.gif) no-repeat scroll 0 0 transparent; vertical-align:top; *vertical-align:middle}\n\nul.tmpTargetzTree {background-color:#FFE6B0; opacity:0.8; filter:alpha(opacity=80)}\n\nspan.tmpzTreeMove_arrow {width:16px; height:16px; display: inline-block; padding:0; margin:2px 0 0 1px; border:0 none; position:absolute;\n\tbackground-color:transparent; background-repeat:no-repeat; background-attachment: scroll;\n\tbackground-position:-110px -80px; background-image:url(\"./img/zTreeStandard.png\"); *background-image:url(\"./img/zTreeStandard.gif\")}\n\nul.ztree.zTreeDragUL {margin:0; padding:0; position:absolute; width:auto; height:auto;overflow:hidden; background-color:#cfcfcf; border:1px #00B83F dotted; opacity:0.8; filter:alpha(opacity=80)}\n.zTreeMask {z-index:10000; background-color:#cfcfcf; opacity:0.0; filter:alpha(opacity=0); position:absolute}\n\n/* level style*/\n/*.ztree li span.button.level0 {\n\tdisplay:none;\n}\n.ztree li ul.level0 {\n\tpadding:0;\n\tbackground:none;\n}*/"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/js/jquery.ztree.all-3.5.js",
    "content": "\n/*\n * JQuery zTree core v3.5.18\n * http://zTree.me/\n *\n * Copyright (c) 2010 Hunter.z\n *\n * Licensed same as jquery - MIT License\n * http://www.opensource.org/licenses/mit-license.php\n *\n * email: hunter.z@263.net\n * Date: 2015-05-25\n */\n(function($){\n\tvar settings = {}, roots = {}, caches = {},\n\t//default consts of core\n\t_consts = {\n\t\tclassName: {\n\t\t\tBUTTON: \"button\",\n\t\t\tLEVEL: \"level\",\n\t\t\tICO_LOADING: \"ico_loading\",\n\t\t\tSWITCH: \"switch\"\n\t\t},\n\t\tevent: {\n\t\t\tNODECREATED: \"ztree_nodeCreated\",\n\t\t\tCLICK: \"ztree_click\",\n\t\t\tEXPAND: \"ztree_expand\",\n\t\t\tCOLLAPSE: \"ztree_collapse\",\n\t\t\tASYNC_SUCCESS: \"ztree_async_success\",\n\t\t\tASYNC_ERROR: \"ztree_async_error\",\n\t\t\tREMOVE: \"ztree_remove\",\n\t\t\tSELECTED: \"ztree_selected\",\n\t\t\tUNSELECTED: \"ztree_unselected\"\n\t\t},\n\t\tid: {\n\t\t\tA: \"_a\",\n\t\t\tICON: \"_ico\",\n\t\t\tSPAN: \"_span\",\n\t\t\tSWITCH: \"_switch\",\n\t\t\tUL: \"_ul\"\n\t\t},\n\t\tline: {\n\t\t\tROOT: \"root\",\n\t\t\tROOTS: \"roots\",\n\t\t\tCENTER: \"center\",\n\t\t\tBOTTOM: \"bottom\",\n\t\t\tNOLINE: \"noline\",\n\t\t\tLINE: \"line\"\n\t\t},\n\t\tfolder: {\n\t\t\tOPEN: \"open\",\n\t\t\tCLOSE: \"close\",\n\t\t\tDOCU: \"docu\"\n\t\t},\n\t\tnode: {\n\t\t\tCURSELECTED: \"curSelectedNode\"\n\t\t}\n\t},\n\t//default setting of core\n\t_setting = {\n\t\ttreeId: \"\",\n\t\ttreeObj: null,\n\t\tview: {\n\t\t\taddDiyDom: null,\n\t\t\tautoCancelSelected: true,\n\t\t\tdblClickExpand: true,\n\t\t\texpandSpeed: \"fast\",\n\t\t\tfontCss: {},\n\t\t\tnameIsHTML: false,\n\t\t\tselectedMulti: true,\n\t\t\tshowIcon: true,\n\t\t\tshowLine: true,\n\t\t\tshowTitle: true,\n\t\t\ttxtSelectedEnable: false\n\t\t},\n\t\tdata: {\n\t\t\tkey: {\n\t\t\t\tchildren: \"children\",\n\t\t\t\tname: \"name\",\n\t\t\t\ttitle: \"\",\n\t\t\t\turl: \"url\"\n\t\t\t},\n\t\t\tsimpleData: {\n\t\t\t\tenable: false,\n\t\t\t\tidKey: \"id\",\n\t\t\t\tpIdKey: \"pId\",\n\t\t\t\trootPId: null\n\t\t\t},\n\t\t\tkeep: {\n\t\t\t\tparent: false,\n\t\t\t\tleaf: false\n\t\t\t}\n\t\t},\n\t\tasync: {\n\t\t\tenable: false,\n\t\t\tcontentType: \"application/x-www-form-urlencoded\",\n\t\t\ttype: \"post\",\n\t\t\tdataType: \"text\",\n\t\t\turl: \"\",\n\t\t\tautoParam: [],\n\t\t\totherParam: [],\n\t\t\tdataFilter: null\n\t\t},\n\t\tcallback: {\n\t\t\tbeforeAsync:null,\n\t\t\tbeforeClick:null,\n\t\t\tbeforeDblClick:null,\n\t\t\tbeforeRightClick:null,\n\t\t\tbeforeMouseDown:null,\n\t\t\tbeforeMouseUp:null,\n\t\t\tbeforeExpand:null,\n\t\t\tbeforeCollapse:null,\n\t\t\tbeforeRemove:null,\n\n\t\t\tonAsyncError:null,\n\t\t\tonAsyncSuccess:null,\n\t\t\tonNodeCreated:null,\n\t\t\tonClick:null,\n\t\t\tonDblClick:null,\n\t\t\tonRightClick:null,\n\t\t\tonMouseDown:null,\n\t\t\tonMouseUp:null,\n\t\t\tonExpand:null,\n\t\t\tonCollapse:null,\n\t\t\tonRemove:null\n\t\t}\n\t},\n\t//default root of core\n\t//zTree use root to save full data\n\t_initRoot = function (setting) {\n\t\tvar r = data.getRoot(setting);\n\t\tif (!r) {\n\t\t\tr = {};\n\t\t\tdata.setRoot(setting, r);\n\t\t}\n\t\tr[setting.data.key.children] = [];\n\t\tr.expandTriggerFlag = false;\n\t\tr.curSelectedList = [];\n\t\tr.noSelection = true;\n\t\tr.createdNodes = [];\n\t\tr.zId = 0;\n\t\tr._ver = (new Date()).getTime();\n\t},\n\t//default cache of core\n\t_initCache = function(setting) {\n\t\tvar c = data.getCache(setting);\n\t\tif (!c) {\n\t\t\tc = {};\n\t\t\tdata.setCache(setting, c);\n\t\t}\n\t\tc.nodes = [];\n\t\tc.doms = [];\n\t},\n\t//default bindEvent of core\n\t_bindEvent = function(setting) {\n\t\tvar o = setting.treeObj,\n\t\tc = consts.event;\n\t\to.bind(c.NODECREATED, function (event, treeId, node) {\n\t\t\ttools.apply(setting.callback.onNodeCreated, [event, treeId, node]);\n\t\t});\n\n\t\to.bind(c.CLICK, function (event, srcEvent, treeId, node, clickFlag) {\n\t\t\ttools.apply(setting.callback.onClick, [srcEvent, treeId, node, clickFlag]);\n\t\t});\n\n\t\to.bind(c.EXPAND, function (event, treeId, node) {\n\t\t\ttools.apply(setting.callback.onExpand, [event, treeId, node]);\n\t\t});\n\n\t\to.bind(c.COLLAPSE, function (event, treeId, node) {\n\t\t\ttools.apply(setting.callback.onCollapse, [event, treeId, node]);\n\t\t});\n\n\t\to.bind(c.ASYNC_SUCCESS, function (event, treeId, node, msg) {\n\t\t\ttools.apply(setting.callback.onAsyncSuccess, [event, treeId, node, msg]);\n\t\t});\n\n\t\to.bind(c.ASYNC_ERROR, function (event, treeId, node, XMLHttpRequest, textStatus, errorThrown) {\n\t\t\ttools.apply(setting.callback.onAsyncError, [event, treeId, node, XMLHttpRequest, textStatus, errorThrown]);\n\t\t});\n\n\t\to.bind(c.REMOVE, function (event, treeId, treeNode) {\n\t\t\ttools.apply(setting.callback.onRemove, [event, treeId, treeNode]);\n\t\t});\n\n\t\to.bind(c.SELECTED, function (event, srcEvent, treeId, node) {\n\t\t\ttools.apply(setting.callback.onSelected, [srcEvent, treeId, node]);\n\t\t});\n\t\to.bind(c.UNSELECTED, function (event, srcEvent, treeId, node) {\n\t\t\ttools.apply(setting.callback.onUnSelected, [srcEvent, treeId, node]);\n\t\t});\n\t},\n\t_unbindEvent = function(setting) {\n\t\tvar o = setting.treeObj,\n\t\tc = consts.event;\n\t\to.unbind(c.NODECREATED)\n\t\t.unbind(c.CLICK)\n\t\t.unbind(c.EXPAND)\n\t\t.unbind(c.COLLAPSE)\n\t\t.unbind(c.ASYNC_SUCCESS)\n\t\t.unbind(c.ASYNC_ERROR)\n\t\t.unbind(c.REMOVE)\n\t\t.unbind(c.SELECTED)\n\t\t.unbind(c.UNSELECTED);\n\t},\n\t//default event proxy of core\n\t_eventProxy = function(event) {\n\t\tvar target = event.target,\n\t\tsetting = data.getSetting(event.data.treeId),\n\t\ttId = \"\", node = null,\n\t\tnodeEventType = \"\", treeEventType = \"\",\n\t\tnodeEventCallback = null, treeEventCallback = null,\n\t\ttmp = null;\n\n\t\tif (tools.eqs(event.type, \"mousedown\")) {\n\t\t\ttreeEventType = \"mousedown\";\n\t\t} else if (tools.eqs(event.type, \"mouseup\")) {\n\t\t\ttreeEventType = \"mouseup\";\n\t\t} else if (tools.eqs(event.type, \"contextmenu\")) {\n\t\t\ttreeEventType = \"contextmenu\";\n\t\t} else if (tools.eqs(event.type, \"click\")) {\n\t\t\tif (tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\"+ consts.id.SWITCH) !== null) {\n\t\t\t\ttId = tools.getNodeMainDom(target).id;\n\t\t\t\tnodeEventType = \"switchNode\";\n\t\t\t} else {\n\t\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\t\tif (tmp) {\n\t\t\t\t\ttId = tools.getNodeMainDom(tmp).id;\n\t\t\t\t\tnodeEventType = \"clickNode\";\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (tools.eqs(event.type, \"dblclick\")) {\n\t\t\ttreeEventType = \"dblclick\";\n\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (tmp) {\n\t\t\t\ttId = tools.getNodeMainDom(tmp).id;\n\t\t\t\tnodeEventType = \"switchNode\";\n\t\t\t}\n\t\t}\n\t\tif (treeEventType.length > 0 && tId.length == 0) {\n\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (tmp) {tId = tools.getNodeMainDom(tmp).id;}\n\t\t}\n\t\t// event to node\n\t\tif (tId.length>0) {\n\t\t\tnode = data.getNodeCache(setting, tId);\n\t\t\tswitch (nodeEventType) {\n\t\t\t\tcase \"switchNode\" :\n\t\t\t\t\tif (!node.isParent) {\n\t\t\t\t\t\tnodeEventType = \"\";\n\t\t\t\t\t} else if (tools.eqs(event.type, \"click\")\n\t\t\t\t\t\t|| (tools.eqs(event.type, \"dblclick\") && tools.apply(setting.view.dblClickExpand, [setting.treeId, node], setting.view.dblClickExpand))) {\n\t\t\t\t\t\tnodeEventCallback = handler.onSwitchNode;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnodeEventType = \"\";\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"clickNode\" :\n\t\t\t\t\tnodeEventCallback = handler.onClickNode;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t// event to zTree\n\t\tswitch (treeEventType) {\n\t\t\tcase \"mousedown\" :\n\t\t\t\ttreeEventCallback = handler.onZTreeMousedown;\n\t\t\t\tbreak;\n\t\t\tcase \"mouseup\" :\n\t\t\t\ttreeEventCallback = handler.onZTreeMouseup;\n\t\t\t\tbreak;\n\t\t\tcase \"dblclick\" :\n\t\t\t\ttreeEventCallback = handler.onZTreeDblclick;\n\t\t\t\tbreak;\n\t\t\tcase \"contextmenu\" :\n\t\t\t\ttreeEventCallback = handler.onZTreeContextmenu;\n\t\t\t\tbreak;\n\t\t}\n\t\tvar proxyResult = {\n\t\t\tstop: false,\n\t\t\tnode: node,\n\t\t\tnodeEventType: nodeEventType,\n\t\t\tnodeEventCallback: nodeEventCallback,\n\t\t\ttreeEventType: treeEventType,\n\t\t\ttreeEventCallback: treeEventCallback\n\t\t};\n\t\treturn proxyResult\n\t},\n\t//default init node of core\n\t_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n\t\tif (!n) return;\n\t\tvar r = data.getRoot(setting),\n\t\tchildKey = setting.data.key.children;\n\t\tn.level = level;\n\t\tn.tId = setting.treeId + \"_\" + (++r.zId);\n\t\tn.parentTId = parentNode ? parentNode.tId : null;\n\t\tn.open = (typeof n.open == \"string\") ? tools.eqs(n.open, \"true\") : !!n.open;\n\t\tif (n[childKey] && n[childKey].length > 0) {\n\t\t\tn.isParent = true;\n\t\t\tn.zAsync = true;\n\t\t} else {\n\t\t\tn.isParent = (typeof n.isParent == \"string\") ? tools.eqs(n.isParent, \"true\") : !!n.isParent;\n\t\t\tn.open = (n.isParent && !setting.async.enable) ? n.open : false;\n\t\t\tn.zAsync = !n.isParent;\n\t\t}\n\t\tn.isFirstNode = isFirstNode;\n\t\tn.isLastNode = isLastNode;\n\t\tn.getParentNode = function() {return data.getNodeCache(setting, n.parentTId);};\n\t\tn.getPreNode = function() {return data.getPreNode(setting, n);};\n\t\tn.getNextNode = function() {return data.getNextNode(setting, n);};\n\t\tn.isAjaxing = false;\n\t\tdata.fixPIdKeyValue(setting, n);\n\t},\n\t_init = {\n\t\tbind: [_bindEvent],\n\t\tunbind: [_unbindEvent],\n\t\tcaches: [_initCache],\n\t\tnodes: [_initNode],\n\t\tproxys: [_eventProxy],\n\t\troots: [_initRoot],\n\t\tbeforeA: [],\n\t\tafterA: [],\n\t\tinnerBeforeA: [],\n\t\tinnerAfterA: [],\n\t\tzTreeTools: []\n\t},\n\t//method of operate data\n\tdata = {\n\t\taddNodeCache: function(setting, node) {\n\t\t\tdata.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = node;\n\t\t},\n\t\tgetNodeCacheId: function(tId) {\n\t\t\treturn tId.substring(tId.lastIndexOf(\"_\")+1);\n\t\t},\n\t\taddAfterA: function(afterA) {\n\t\t\t_init.afterA.push(afterA);\n\t\t},\n\t\taddBeforeA: function(beforeA) {\n\t\t\t_init.beforeA.push(beforeA);\n\t\t},\n\t\taddInnerAfterA: function(innerAfterA) {\n\t\t\t_init.innerAfterA.push(innerAfterA);\n\t\t},\n\t\taddInnerBeforeA: function(innerBeforeA) {\n\t\t\t_init.innerBeforeA.push(innerBeforeA);\n\t\t},\n\t\taddInitBind: function(bindEvent) {\n\t\t\t_init.bind.push(bindEvent);\n\t\t},\n\t\taddInitUnBind: function(unbindEvent) {\n\t\t\t_init.unbind.push(unbindEvent);\n\t\t},\n\t\taddInitCache: function(initCache) {\n\t\t\t_init.caches.push(initCache);\n\t\t},\n\t\taddInitNode: function(initNode) {\n\t\t\t_init.nodes.push(initNode);\n\t\t},\n\t\taddInitProxy: function(initProxy, isFirst) {\n\t\t\tif (!!isFirst) {\n\t\t\t\t_init.proxys.splice(0,0,initProxy);\n\t\t\t} else {\n\t\t\t\t_init.proxys.push(initProxy);\n\t\t\t}\n\t\t},\n\t\taddInitRoot: function(initRoot) {\n\t\t\t_init.roots.push(initRoot);\n\t\t},\n\t\taddNodesData: function(setting, parentNode, nodes) {\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tif (!parentNode[childKey]) parentNode[childKey] = [];\n\t\t\tif (parentNode[childKey].length > 0) {\n\t\t\t\tparentNode[childKey][parentNode[childKey].length - 1].isLastNode = false;\n\t\t\t\tview.setNodeLineIcos(setting, parentNode[childKey][parentNode[childKey].length - 1]);\n\t\t\t}\n\t\t\tparentNode.isParent = true;\n\t\t\tparentNode[childKey] = parentNode[childKey].concat(nodes);\n\t\t},\n\t\taddSelectedNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\tif (!data.isSelectedNode(setting, node)) {\n\t\t\t\troot.curSelectedList.push(node);\n\t\t\t}\n\t\t},\n\t\taddCreatedNode: function(setting, node) {\n\t\t\tif (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {\n\t\t\t\tvar root = data.getRoot(setting);\n\t\t\t\troot.createdNodes.push(node);\n\t\t\t}\n\t\t},\n\t\taddZTreeTools: function(zTreeTools) {\n\t\t\t_init.zTreeTools.push(zTreeTools);\n\t\t},\n\t\texSetting: function(s) {\n\t\t\t$.extend(true, _setting, s);\n\t\t},\n\t\tfixPIdKeyValue: function(setting, node) {\n\t\t\tif (setting.data.simpleData.enable) {\n\t\t\t\tnode[setting.data.simpleData.pIdKey] = node.parentTId ? node.getParentNode()[setting.data.simpleData.idKey] : setting.data.simpleData.rootPId;\n\t\t\t}\n\t\t},\n\t\tgetAfterA: function(setting, node, array) {\n\t\t\tfor (var i=0, j=_init.afterA.length; i<j; i++) {\n\t\t\t\t_init.afterA[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tgetBeforeA: function(setting, node, array) {\n\t\t\tfor (var i=0, j=_init.beforeA.length; i<j; i++) {\n\t\t\t\t_init.beforeA[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tgetInnerAfterA: function(setting, node, array) {\n\t\t\tfor (var i=0, j=_init.innerAfterA.length; i<j; i++) {\n\t\t\t\t_init.innerAfterA[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tgetInnerBeforeA: function(setting, node, array) {\n\t\t\tfor (var i=0, j=_init.innerBeforeA.length; i<j; i++) {\n\t\t\t\t_init.innerBeforeA[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tgetCache: function(setting) {\n\t\t\treturn caches[setting.treeId];\n\t\t},\n\t\tgetNextNode: function(setting, node) {\n\t\t\tif (!node) return null;\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tp = node.parentTId ? node.getParentNode() : data.getRoot(setting);\n\t\t\tfor (var i=0, l=p[childKey].length-1; i<=l; i++) {\n\t\t\t\tif (p[childKey][i] === node) {\n\t\t\t\t\treturn (i==l ? null : p[childKey][i+1]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tgetNodeByParam: function(setting, nodes, key, value) {\n\t\t\tif (!nodes || !key) return null;\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (nodes[i][key] == value) {\n\t\t\t\t\treturn nodes[i];\n\t\t\t\t}\n\t\t\t\tvar tmp = data.getNodeByParam(setting, nodes[i][childKey], key, value);\n\t\t\t\tif (tmp) return tmp;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tgetNodeCache: function(setting, tId) {\n\t\t\tif (!tId) return null;\n\t\t\tvar n = caches[setting.treeId].nodes[data.getNodeCacheId(tId)];\n\t\t\treturn n ? n : null;\n\t\t},\n\t\tgetNodeName: function(setting, node) {\n\t\t\tvar nameKey = setting.data.key.name;\n\t\t\treturn \"\" + node[nameKey];\n\t\t},\n\t\tgetNodeTitle: function(setting, node) {\n\t\t\tvar t = setting.data.key.title === \"\" ? setting.data.key.name : setting.data.key.title;\n\t\t\treturn \"\" + node[t];\n\t\t},\n\t\tgetNodes: function(setting) {\n\t\t\treturn data.getRoot(setting)[setting.data.key.children];\n\t\t},\n\t\tgetNodesByParam: function(setting, nodes, key, value) {\n\t\t\tif (!nodes || !key) return [];\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tresult = [];\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (nodes[i][key] == value) {\n\t\t\t\t\tresult.push(nodes[i]);\n\t\t\t\t}\n\t\t\t\tresult = result.concat(data.getNodesByParam(setting, nodes[i][childKey], key, value));\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t\tgetNodesByParamFuzzy: function(setting, nodes, key, value) {\n\t\t\tif (!nodes || !key) return [];\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tresult = [];\n\t\t\tvalue = value.toLowerCase();\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (typeof nodes[i][key] == \"string\" && nodes[i][key].toLowerCase().indexOf(value)>-1) {\n\t\t\t\t\tresult.push(nodes[i]);\n\t\t\t\t}\n\t\t\t\tresult = result.concat(data.getNodesByParamFuzzy(setting, nodes[i][childKey], key, value));\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t\tgetNodesByFilter: function(setting, nodes, filter, isSingle, invokeParam) {\n\t\t\tif (!nodes) return (isSingle ? null : []);\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tresult = isSingle ? null : [];\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (tools.apply(filter, [nodes[i], invokeParam], false)) {\n\t\t\t\t\tif (isSingle) {return nodes[i];}\n\t\t\t\t\tresult.push(nodes[i]);\n\t\t\t\t}\n\t\t\t\tvar tmpResult = data.getNodesByFilter(setting, nodes[i][childKey], filter, isSingle, invokeParam);\n\t\t\t\tif (isSingle && !!tmpResult) {return tmpResult;}\n\t\t\t\tresult = isSingle ? tmpResult : result.concat(tmpResult);\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t\tgetPreNode: function(setting, node) {\n\t\t\tif (!node) return null;\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tp = node.parentTId ? node.getParentNode() : data.getRoot(setting);\n\t\t\tfor (var i=0, l=p[childKey].length; i<l; i++) {\n\t\t\t\tif (p[childKey][i] === node) {\n\t\t\t\t\treturn (i==0 ? null : p[childKey][i-1]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tgetRoot: function(setting) {\n\t\t\treturn setting ? roots[setting.treeId] : null;\n\t\t},\n\t\tgetRoots: function() {\n\t\t\treturn roots;\n\t\t},\n\t\tgetSetting: function(treeId) {\n\t\t\treturn settings[treeId];\n\t\t},\n\t\tgetSettings: function() {\n\t\t\treturn settings;\n\t\t},\n\t\tgetZTreeTools: function(treeId) {\n\t\t\tvar r = this.getRoot(this.getSetting(treeId));\n\t\t\treturn r ? r.treeTools : null;\n\t\t},\n\t\tinitCache: function(setting) {\n\t\t\tfor (var i=0, j=_init.caches.length; i<j; i++) {\n\t\t\t\t_init.caches[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tinitNode: function(setting, level, node, parentNode, preNode, nextNode) {\n\t\t\tfor (var i=0, j=_init.nodes.length; i<j; i++) {\n\t\t\t\t_init.nodes[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tinitRoot: function(setting) {\n\t\t\tfor (var i=0, j=_init.roots.length; i<j; i++) {\n\t\t\t\t_init.roots[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tisSelectedNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\tfor (var i=0, j=root.curSelectedList.length; i<j; i++) {\n\t\t\t\tif(node === root.curSelectedList[i]) return true;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t\tremoveNodeCache: function(setting, node) {\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tif (node[childKey]) {\n\t\t\t\tfor (var i=0, l=node[childKey].length; i<l; i++) {\n\t\t\t\t\targuments.callee(setting, node[childKey][i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdata.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = null;\n\t\t},\n\t\tremoveSelectedNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\tfor (var i=0, j=root.curSelectedList.length; i<j; i++) {\n\t\t\t\tif(node === root.curSelectedList[i] || !data.getNodeCache(setting, root.curSelectedList[i].tId)) {\n\t\t\t\t\troot.curSelectedList.splice(i, 1);\n\t\t\t\t\ti--;j--;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsetCache: function(setting, cache) {\n\t\t\tcaches[setting.treeId] = cache;\n\t\t},\n\t\tsetRoot: function(setting, root) {\n\t\t\troots[setting.treeId] = root;\n\t\t},\n\t\tsetZTreeTools: function(setting, zTreeTools) {\n\t\t\tfor (var i=0, j=_init.zTreeTools.length; i<j; i++) {\n\t\t\t\t_init.zTreeTools[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\ttransformToArrayFormat: function (setting, nodes) {\n\t\t\tif (!nodes) return [];\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tr = [];\n\t\t\tif (tools.isArray(nodes)) {\n\t\t\t\tfor (var i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\tr.push(nodes[i]);\n\t\t\t\t\tif (nodes[i][childKey])\n\t\t\t\t\t\tr = r.concat(data.transformToArrayFormat(setting, nodes[i][childKey]));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tr.push(nodes);\n\t\t\t\tif (nodes[childKey])\n\t\t\t\t\tr = r.concat(data.transformToArrayFormat(setting, nodes[childKey]));\n\t\t\t}\n\t\t\treturn r;\n\t\t},\n\t\ttransformTozTreeFormat: function(setting, sNodes) {\n\t\t\tvar i,l,\n\t\t\tkey = setting.data.simpleData.idKey,\n\t\t\tparentKey = setting.data.simpleData.pIdKey,\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tif (!key || key==\"\" || !sNodes) return [];\n\n\t\t\tif (tools.isArray(sNodes)) {\n\t\t\t\tvar r = [];\n\t\t\t\tvar tmpMap = [];\n\t\t\t\tfor (i=0, l=sNodes.length; i<l; i++) {\n\t\t\t\t\ttmpMap[sNodes[i][key]] = sNodes[i];\n\t\t\t\t}\n\t\t\t\tfor (i=0, l=sNodes.length; i<l; i++) {\n\t\t\t\t\tif (tmpMap[sNodes[i][parentKey]] && sNodes[i][key] != sNodes[i][parentKey]) {\n\t\t\t\t\t\tif (!tmpMap[sNodes[i][parentKey]][childKey])\n\t\t\t\t\t\t\ttmpMap[sNodes[i][parentKey]][childKey] = [];\n\t\t\t\t\t\ttmpMap[sNodes[i][parentKey]][childKey].push(sNodes[i]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tr.push(sNodes[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn r;\n\t\t\t}else {\n\t\t\t\treturn [sNodes];\n\t\t\t}\n\t\t}\n\t},\n\t//method of event proxy\n\tevent = {\n\t\tbindEvent: function(setting) {\n\t\t\tfor (var i=0, j=_init.bind.length; i<j; i++) {\n\t\t\t\t_init.bind[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tunbindEvent: function(setting) {\n\t\t\tfor (var i=0, j=_init.unbind.length; i<j; i++) {\n\t\t\t\t_init.unbind[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tbindTree: function(setting) {\n\t\t\tvar eventParam = {\n\t\t\t\ttreeId: setting.treeId\n\t\t\t},\n\t\t\to = setting.treeObj;\n\t\t\tif (!setting.view.txtSelectedEnable) {\n\t\t\t\t// for can't select text\n\t\t\t\to.bind('selectstart', function(e){\n\t\t\t\t\tvar node\n\t\t\t\t\tvar n = e.originalEvent.srcElement.nodeName.toLowerCase();\n\t\t\t\t\treturn (n === \"input\" || n === \"textarea\" );\n\t\t\t\t}).css({\n\t\t\t\t\t\"-moz-user-select\":\"-moz-none\"\n\t\t\t\t});\n\t\t\t}\n\t\t\to.bind('click', eventParam, event.proxy);\n\t\t\to.bind('dblclick', eventParam, event.proxy);\n\t\t\to.bind('mouseover', eventParam, event.proxy);\n\t\t\to.bind('mouseout', eventParam, event.proxy);\n\t\t\to.bind('mousedown', eventParam, event.proxy);\n\t\t\to.bind('mouseup', eventParam, event.proxy);\n\t\t\to.bind('contextmenu', eventParam, event.proxy);\n\t\t},\n\t\tunbindTree: function(setting) {\n\t\t\tvar o = setting.treeObj;\n\t\t\to.unbind('click', event.proxy)\n\t\t\t.unbind('dblclick', event.proxy)\n\t\t\t.unbind('mouseover', event.proxy)\n\t\t\t.unbind('mouseout', event.proxy)\n\t\t\t.unbind('mousedown', event.proxy)\n\t\t\t.unbind('mouseup', event.proxy)\n\t\t\t.unbind('contextmenu', event.proxy);\n\t\t},\n\t\tdoProxy: function(e) {\n\t\t\tvar results = [];\n\t\t\tfor (var i=0, j=_init.proxys.length; i<j; i++) {\n\t\t\t\tvar proxyResult = _init.proxys[i].apply(this, arguments);\n\t\t\t\tresults.push(proxyResult);\n\t\t\t\tif (proxyResult.stop) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn results;\n\t\t},\n\t\tproxy: function(e) {\n\t\t\tvar setting = data.getSetting(e.data.treeId);\n\t\t\tif (!tools.uCanDo(setting, e)) return true;\n\t\t\tvar results = event.doProxy(e),\n\t\t\tr = true, x = false;\n\t\t\tfor (var i=0, l=results.length; i<l; i++) {\n\t\t\t\tvar proxyResult = results[i];\n\t\t\t\tif (proxyResult.nodeEventCallback) {\n\t\t\t\t\tx = true;\n\t\t\t\t\tr = proxyResult.nodeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;\n\t\t\t\t}\n\t\t\t\tif (proxyResult.treeEventCallback) {\n\t\t\t\t\tx = true;\n\t\t\t\t\tr = proxyResult.treeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn r;\n\t\t}\n\t},\n\t//method of event handler\n\thandler = {\n\t\tonSwitchNode: function (event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId);\n\t\t\tif (node.open) {\n\t\t\t\tif (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false) return true;\n\t\t\t\tdata.getRoot(setting).expandTriggerFlag = true;\n\t\t\t\tview.switchNode(setting, node);\n\t\t\t} else {\n\t\t\t\tif (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false) return true;\n\t\t\t\tdata.getRoot(setting).expandTriggerFlag = true;\n\t\t\t\tview.switchNode(setting, node);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\tonClickNode: function (event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\tclickFlag = ( (setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey)) && data.isSelectedNode(setting, node)) ? 0 : (setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey) && setting.view.selectedMulti) ? 2 : 1;\n\t\t\tif (tools.apply(setting.callback.beforeClick, [setting.treeId, node, clickFlag], true) == false) return true;\n\t\t\tif (clickFlag === 0) {\n\t\t\t\tview.cancelPreSelectedNode(setting, node);\n\t\t\t} else {\n\t\t\t\tview.selectNode(setting, node, clickFlag === 2);\n\t\t\t}\n\t\t\tsetting.treeObj.trigger(consts.event.CLICK, [event, setting.treeId, node, clickFlag]);\n\t\t\treturn true;\n\t\t},\n\t\tonZTreeMousedown: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId);\n\t\t\tif (tools.apply(setting.callback.beforeMouseDown, [setting.treeId, node], true)) {\n\t\t\t\ttools.apply(setting.callback.onMouseDown, [event, setting.treeId, node]);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\tonZTreeMouseup: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId);\n\t\t\tif (tools.apply(setting.callback.beforeMouseUp, [setting.treeId, node], true)) {\n\t\t\t\ttools.apply(setting.callback.onMouseUp, [event, setting.treeId, node]);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\tonZTreeDblclick: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId);\n\t\t\tif (tools.apply(setting.callback.beforeDblClick, [setting.treeId, node], true)) {\n\t\t\t\ttools.apply(setting.callback.onDblClick, [event, setting.treeId, node]);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\tonZTreeContextmenu: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId);\n\t\t\tif (tools.apply(setting.callback.beforeRightClick, [setting.treeId, node], true)) {\n\t\t\t\ttools.apply(setting.callback.onRightClick, [event, setting.treeId, node]);\n\t\t\t}\n\t\t\treturn (typeof setting.callback.onRightClick) != \"function\";\n\t\t}\n\t},\n\t//method of tools for zTree\n\ttools = {\n\t\tapply: function(fun, param, defaultValue) {\n\t\t\tif ((typeof fun) == \"function\") {\n\t\t\t\treturn fun.apply(zt, param?param:[]);\n\t\t\t}\n\t\t\treturn defaultValue;\n\t\t},\n\t\tcanAsync: function(setting, node) {\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\treturn (setting.async.enable && node && node.isParent && !(node.zAsync || (node[childKey] && node[childKey].length > 0)));\n\t\t},\n\t\tclone: function (obj){\n\t\t\tif (obj === null) return null;\n\t\t\tvar o = tools.isArray(obj) ? [] : {};\n\t\t\tfor(var i in obj){\n\t\t\t\to[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === \"object\" ? arguments.callee(obj[i]) : obj[i]);\n\t\t\t}\n\t\t\treturn o;\n\t\t},\n\t\teqs: function(str1, str2) {\n\t\t\treturn str1.toLowerCase() === str2.toLowerCase();\n\t\t},\n\t\tisArray: function(arr) {\n\t\t\treturn Object.prototype.toString.apply(arr) === \"[object Array]\";\n\t\t},\n\t\t$: function(node, exp, setting) {\n\t\t\tif (!!exp && typeof exp != \"string\") {\n\t\t\t\tsetting = exp;\n\t\t\t\texp = \"\";\n\t\t\t}\n\t\t\tif (typeof node == \"string\") {\n\t\t\t\treturn $(node, setting ? setting.treeObj.get(0).ownerDocument : null);\n\t\t\t} else {\n\t\t\t\treturn $(\"#\" + node.tId + exp, setting ? setting.treeObj : null);\n\t\t\t}\n\t\t},\n\t\tgetMDom: function (setting, curDom, targetExpr) {\n\t\t\tif (!curDom) return null;\n\t\t\twhile (curDom && curDom.id !== setting.treeId) {\n\t\t\t\tfor (var i=0, l=targetExpr.length; curDom.tagName && i<l; i++) {\n\t\t\t\t\tif (tools.eqs(curDom.tagName, targetExpr[i].tagName) && curDom.getAttribute(targetExpr[i].attrName) !== null) {\n\t\t\t\t\t\treturn curDom;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcurDom = curDom.parentNode;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tgetNodeMainDom:function(target) {\n\t\t\treturn ($(target).parent(\"li\").get(0) || $(target).parentsUntil(\"li\").parent().get(0));\n\t\t},\n\t\tisChildOrSelf: function(dom, parentId) {\n\t\t\treturn ( $(dom).closest(\"#\" + parentId).length> 0 );\n\t\t},\n\t\tuCanDo: function(setting, e) {\n\t\t\treturn true;\n\t\t}\n\t},\n\t//method of operate ztree dom\n\tview = {\n\t\taddNodes: function(setting, parentNode, newNodes, isSilent) {\n\t\t\tif (setting.data.keep.leaf && parentNode && !parentNode.isParent) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!tools.isArray(newNodes)) {\n\t\t\t\tnewNodes = [newNodes];\n\t\t\t}\n\t\t\tif (setting.data.simpleData.enable) {\n\t\t\t\tnewNodes = data.transformTozTreeFormat(setting, newNodes);\n\t\t\t}\n\t\t\tif (parentNode) {\n\t\t\t\tvar target_switchObj = $$(parentNode, consts.id.SWITCH, setting),\n\t\t\t\ttarget_icoObj = $$(parentNode, consts.id.ICON, setting),\n\t\t\t\ttarget_ulObj = $$(parentNode, consts.id.UL, setting);\n\n\t\t\t\tif (!parentNode.open) {\n\t\t\t\t\tview.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE);\n\t\t\t\t\tview.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE);\n\t\t\t\t\tparentNode.open = false;\n\t\t\t\t\ttarget_ulObj.css({\n\t\t\t\t\t\t\"display\": \"none\"\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tdata.addNodesData(setting, parentNode, newNodes);\n\t\t\t\tview.createNodes(setting, parentNode.level + 1, newNodes, parentNode);\n\t\t\t\tif (!isSilent) {\n\t\t\t\t\tview.expandCollapseParentNode(setting, parentNode, true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdata.addNodesData(setting, data.getRoot(setting), newNodes);\n\t\t\t\tview.createNodes(setting, 0, newNodes, null);\n\t\t\t}\n\t\t},\n\t\tappendNodes: function(setting, level, nodes, parentNode, initFlag, openFlag) {\n\t\t\tif (!nodes) return [];\n\t\t\tvar html = [],\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tvar node = nodes[i];\n\t\t\t\tif (initFlag) {\n\t\t\t\t\tvar tmpPNode = (parentNode) ? parentNode: data.getRoot(setting),\n\t\t\t\t\ttmpPChild = tmpPNode[childKey],\n\t\t\t\t\tisFirstNode = ((tmpPChild.length == nodes.length) && (i == 0)),\n\t\t\t\t\tisLastNode = (i == (nodes.length - 1));\n\t\t\t\t\tdata.initNode(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag);\n\t\t\t\t\tdata.addNodeCache(setting, node);\n\t\t\t\t}\n\n\t\t\t\tvar childHtml = [];\n\t\t\t\tif (node[childKey] && node[childKey].length > 0) {\n\t\t\t\t\t//make child html first, because checkType\n\t\t\t\t\tchildHtml = view.appendNodes(setting, level + 1, node[childKey], node, initFlag, openFlag && node.open);\n\t\t\t\t}\n\t\t\t\tif (openFlag) {\n\n\t\t\t\t\tview.makeDOMNodeMainBefore(html, setting, node);\n\t\t\t\t\tview.makeDOMNodeLine(html, setting, node);\n\t\t\t\t\tdata.getBeforeA(setting, node, html);\n\t\t\t\t\tview.makeDOMNodeNameBefore(html, setting, node);\n\t\t\t\t\tdata.getInnerBeforeA(setting, node, html);\n\t\t\t\t\tview.makeDOMNodeIcon(html, setting, node);\n\t\t\t\t\tdata.getInnerAfterA(setting, node, html);\n\t\t\t\t\tview.makeDOMNodeNameAfter(html, setting, node);\n\t\t\t\t\tdata.getAfterA(setting, node, html);\n\t\t\t\t\tif (node.isParent && node.open) {\n\t\t\t\t\t\tview.makeUlHtml(setting, node, html, childHtml.join(''));\n\t\t\t\t\t}\n\t\t\t\t\tview.makeDOMNodeMainAfter(html, setting, node);\n\t\t\t\t\tdata.addCreatedNode(setting, node);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn html;\n\t\t},\n\t\tappendParentULDom: function(setting, node) {\n\t\t\tvar html = [],\n\t\t\tnObj = $$(node, setting);\n\t\t\tif (!nObj.get(0) && !!node.parentTId) {\n\t\t\t\tview.appendParentULDom(setting, node.getParentNode());\n\t\t\t\tnObj = $$(node, setting);\n\t\t\t}\n\t\t\tvar ulObj = $$(node, consts.id.UL, setting);\n\t\t\tif (ulObj.get(0)) {\n\t\t\t\tulObj.remove();\n\t\t\t}\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tchildHtml = view.appendNodes(setting, node.level+1, node[childKey], node, false, true);\n\t\t\tview.makeUlHtml(setting, node, html, childHtml.join(''));\n\t\t\tnObj.append(html.join(''));\n\t\t},\n\t\tasyncNode: function(setting, node, isSilent, callback) {\n\t\t\tvar i, l;\n\t\t\tif (node && !node.isParent) {\n\t\t\t\ttools.apply(callback);\n\t\t\t\treturn false;\n\t\t\t} else if (node && node.isAjaxing) {\n\t\t\t\treturn false;\n\t\t\t} else if (tools.apply(setting.callback.beforeAsync, [setting.treeId, node], true) == false) {\n\t\t\t\ttools.apply(callback);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (node) {\n\t\t\t\tnode.isAjaxing = true;\n\t\t\t\tvar icoObj = $$(node, consts.id.ICON, setting);\n\t\t\t\ticoObj.attr({\"style\":\"\", \"class\":consts.className.BUTTON + \" \" + consts.className.ICO_LOADING});\n\t\t\t}\n\n\t\t\tvar tmpParam = {};\n\t\t\tfor (i = 0, l = setting.async.autoParam.length; node && i < l; i++) {\n\t\t\t\tvar pKey = setting.async.autoParam[i].split(\"=\"), spKey = pKey;\n\t\t\t\tif (pKey.length>1) {\n\t\t\t\t\tspKey = pKey[1];\n\t\t\t\t\tpKey = pKey[0];\n\t\t\t\t}\n\t\t\t\ttmpParam[spKey] = node[pKey];\n\t\t\t}\n\t\t\tif (tools.isArray(setting.async.otherParam)) {\n\t\t\t\tfor (i = 0, l = setting.async.otherParam.length; i < l; i += 2) {\n\t\t\t\t\ttmpParam[setting.async.otherParam[i]] = setting.async.otherParam[i + 1];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (var p in setting.async.otherParam) {\n\t\t\t\t\ttmpParam[p] = setting.async.otherParam[p];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar _tmpV = data.getRoot(setting)._ver;\n\t\t\t$.ajax({\n\t\t\t\tcontentType: setting.async.contentType,\n                cache: false,\n\t\t\t\ttype: setting.async.type,\n\t\t\t\turl: tools.apply(setting.async.url, [setting.treeId, node], setting.async.url),\n\t\t\t\tdata: tmpParam,\n\t\t\t\tdataType: setting.async.dataType,\n\t\t\t\tsuccess: function(msg) {\n\t\t\t\t\tif (_tmpV != data.getRoot(setting)._ver) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar newNodes = [];\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!msg || msg.length == 0) {\n\t\t\t\t\t\t\tnewNodes = [];\n\t\t\t\t\t\t} else if (typeof msg == \"string\") {\n\t\t\t\t\t\t\tnewNodes = eval(\"(\" + msg + \")\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnewNodes = msg;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\tnewNodes = msg;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (node) {\n\t\t\t\t\t\tnode.isAjaxing = null;\n\t\t\t\t\t\tnode.zAsync = true;\n\t\t\t\t\t}\n\t\t\t\t\tview.setNodeLineIcos(setting, node);\n\t\t\t\t\tif (newNodes && newNodes !== \"\") {\n\t\t\t\t\t\tnewNodes = tools.apply(setting.async.dataFilter, [setting.treeId, node, newNodes], newNodes);\n\t\t\t\t\t\tview.addNodes(setting, node, !!newNodes ? tools.clone(newNodes) : [], !!isSilent);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tview.addNodes(setting, node, [], !!isSilent);\n\t\t\t\t\t}\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.ASYNC_SUCCESS, [setting.treeId, node, msg]);\n\t\t\t\t\ttools.apply(callback);\n\t\t\t\t},\n\t\t\t\terror: function(XMLHttpRequest, textStatus, errorThrown) {\n\t\t\t\t\tif (_tmpV != data.getRoot(setting)._ver) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (node) node.isAjaxing = null;\n\t\t\t\t\tview.setNodeLineIcos(setting, node);\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.ASYNC_ERROR, [setting.treeId, node, XMLHttpRequest, textStatus, errorThrown]);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn true;\n\t\t},\n\t\tcancelPreSelectedNode: function (setting, node, excludeNode) {\n\t\t\tvar list = data.getRoot(setting).curSelectedList,\n\t\t\t\ti, n;\n\t\t\tfor (i=list.length-1; i>=0; i--) {\n\t\t\t\tn = list[i];\n\t\t\t\tif (node === n || (!node && (!excludeNode || excludeNode !== n))) {\n\t\t\t\t\t$$(n, consts.id.A, setting).removeClass(consts.node.CURSELECTED);\n\t\t\t\t\tif (node) {\n\t\t\t\t\t\tdata.removeSelectedNode(setting, node);\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.UNSELECTED, [event, setting.treeId, n]);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlist.splice(i, 1);\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.UNSELECTED, [event, setting.treeId, n]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcreateNodeCallback: function(setting) {\n\t\t\tif (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {\n\t\t\t\tvar root = data.getRoot(setting);\n\t\t\t\twhile (root.createdNodes.length>0) {\n\t\t\t\t\tvar node = root.createdNodes.shift();\n\t\t\t\t\ttools.apply(setting.view.addDiyDom, [setting.treeId, node]);\n\t\t\t\t\tif (!!setting.callback.onNodeCreated) {\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.NODECREATED, [setting.treeId, node]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcreateNodes: function(setting, level, nodes, parentNode) {\n\t\t\tif (!nodes || nodes.length == 0) return;\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children,\n\t\t\topenFlag = !parentNode || parentNode.open || !!$$(parentNode[childKey][0], setting).get(0);\n\t\t\troot.createdNodes = [];\n\t\t\tvar zTreeHtml = view.appendNodes(setting, level, nodes, parentNode, true, openFlag);\n\t\t\tif (!parentNode) {\n\t\t\t\tsetting.treeObj.append(zTreeHtml.join(''));\n\t\t\t} else {\n\t\t\t\tvar ulObj = $$(parentNode, consts.id.UL, setting);\n\t\t\t\tif (ulObj.get(0)) {\n\t\t\t\t\tulObj.append(zTreeHtml.join(''));\n\t\t\t\t}\n\t\t\t}\n\t\t\tview.createNodeCallback(setting);\n\t\t},\n\t\tdestroy: function(setting) {\n\t\t\tif (!setting) return;\n\t\t\tdata.initCache(setting);\n\t\t\tdata.initRoot(setting);\n\t\t\tevent.unbindTree(setting);\n\t\t\tevent.unbindEvent(setting);\n\t\t\tsetting.treeObj.empty();\n\t\t\tdelete settings[setting.treeId];\n\t\t},\n\t\texpandCollapseNode: function(setting, node, expandFlag, animateFlag, callback) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tif (!node) {\n\t\t\t\ttools.apply(callback, []);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (root.expandTriggerFlag) {\n\t\t\t\tvar _callback = callback;\n\t\t\t\tcallback = function(){\n\t\t\t\t\tif (_callback) _callback();\n\t\t\t\t\tif (node.open) {\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.EXPAND, [setting.treeId, node]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.COLLAPSE, [setting.treeId, node]);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\troot.expandTriggerFlag = false;\n\t\t\t}\n\t\t\tif (!node.open && node.isParent && ((!$$(node, consts.id.UL, setting).get(0)) || (node[childKey] && node[childKey].length>0 && !$$(node[childKey][0], setting).get(0)))) {\n\t\t\t\tview.appendParentULDom(setting, node);\n\t\t\t\tview.createNodeCallback(setting);\n\t\t\t}\n\t\t\tif (node.open == expandFlag) {\n\t\t\t\ttools.apply(callback, []);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar ulObj = $$(node, consts.id.UL, setting),\n\t\t\tswitchObj = $$(node, consts.id.SWITCH, setting),\n\t\t\ticoObj = $$(node, consts.id.ICON, setting);\n\n\t\t\tif (node.isParent) {\n\t\t\t\tnode.open = !node.open;\n\t\t\t\tif (node.iconOpen && node.iconClose) {\n\t\t\t\t\ticoObj.attr(\"style\", view.makeNodeIcoStyle(setting, node));\n\t\t\t\t}\n\n\t\t\t\tif (node.open) {\n\t\t\t\t\tview.replaceSwitchClass(node, switchObj, consts.folder.OPEN);\n\t\t\t\t\tview.replaceIcoClass(node, icoObj, consts.folder.OPEN);\n\t\t\t\t\tif (animateFlag == false || setting.view.expandSpeed == \"\") {\n\t\t\t\t\t\tulObj.show();\n\t\t\t\t\t\ttools.apply(callback, []);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (node[childKey] && node[childKey].length > 0) {\n\t\t\t\t\t\t\tulObj.slideDown(setting.view.expandSpeed, callback);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tulObj.show();\n\t\t\t\t\t\t\ttools.apply(callback, []);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tview.replaceSwitchClass(node, switchObj, consts.folder.CLOSE);\n\t\t\t\t\tview.replaceIcoClass(node, icoObj, consts.folder.CLOSE);\n\t\t\t\t\tif (animateFlag == false || setting.view.expandSpeed == \"\" || !(node[childKey] && node[childKey].length > 0)) {\n\t\t\t\t\t\tulObj.hide();\n\t\t\t\t\t\ttools.apply(callback, []);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tulObj.slideUp(setting.view.expandSpeed, callback);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttools.apply(callback, []);\n\t\t\t}\n\t\t},\n\t\texpandCollapseParentNode: function(setting, node, expandFlag, animateFlag, callback) {\n\t\t\tif (!node) return;\n\t\t\tif (!node.parentTId) {\n\t\t\t\tview.expandCollapseNode(setting, node, expandFlag, animateFlag, callback);\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tview.expandCollapseNode(setting, node, expandFlag, animateFlag);\n\t\t\t}\n\t\t\tif (node.parentTId) {\n\t\t\t\tview.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, animateFlag, callback);\n\t\t\t}\n\t\t},\n\t\texpandCollapseSonNode: function(setting, node, expandFlag, animateFlag, callback) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children,\n\t\t\ttreeNodes = (node) ? node[childKey]: root[childKey],\n\t\t\tselfAnimateSign = (node) ? false : animateFlag,\n\t\t\texpandTriggerFlag = data.getRoot(setting).expandTriggerFlag;\n\t\t\tdata.getRoot(setting).expandTriggerFlag = false;\n\t\t\tif (treeNodes) {\n\t\t\t\tfor (var i = 0, l = treeNodes.length; i < l; i++) {\n\t\t\t\t\tif (treeNodes[i]) view.expandCollapseSonNode(setting, treeNodes[i], expandFlag, selfAnimateSign);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdata.getRoot(setting).expandTriggerFlag = expandTriggerFlag;\n\t\t\tview.expandCollapseNode(setting, node, expandFlag, animateFlag, callback );\n\t\t},\n\t\tisSelectedNode: function (setting, node) {\n\t\t\tif (!node) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar list = data.getRoot(setting).curSelectedList,\n\t\t\t\ti;\n\t\t\tfor (i=list.length-1; i>=0; i--) {\n\t\t\t\tif (node === list[i]) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t\tmakeDOMNodeIcon: function(html, setting, node) {\n\t\t\tvar nameStr = data.getNodeName(setting, node),\n\t\t\tname = setting.view.nameIsHTML ? nameStr : nameStr.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n\t\t\thtml.push(\"<span id='\", node.tId, consts.id.ICON,\n\t\t\t\t\"' title='' treeNode\", consts.id.ICON,\" class='\", view.makeNodeIcoClass(setting, node),\n\t\t\t\t\"' style='\", view.makeNodeIcoStyle(setting, node), \"'></span><span id='\", node.tId, consts.id.SPAN,\n\t\t\t\t\"'>\",name,\"</span>\");\n\t\t},\n\t\tmakeDOMNodeLine: function(html, setting, node) {\n\t\t\thtml.push(\"<span id='\", node.tId, consts.id.SWITCH,\t\"' title='' class='\", view.makeNodeLineClass(setting, node), \"' treeNode\", consts.id.SWITCH,\"></span>\");\n\t\t},\n\t\tmakeDOMNodeMainAfter: function(html, setting, node) {\n\t\t\thtml.push(\"</li>\");\n\t\t},\n\t\tmakeDOMNodeMainBefore: function(html, setting, node) {\n\t\t\thtml.push(\"<li id='\", node.tId, \"' class='\", consts.className.LEVEL, node.level,\"' tabindex='0' hidefocus='true' treenode>\");\n\t\t},\n\t\tmakeDOMNodeNameAfter: function(html, setting, node) {\n\t\t\thtml.push(\"</a>\");\n\t\t},\n\t\tmakeDOMNodeNameBefore: function(html, setting, node) {\n\t\t\tvar title = data.getNodeTitle(setting, node),\n\t\t\turl = view.makeNodeUrl(setting, node),\n\t\t\tfontcss = view.makeNodeFontCss(setting, node),\n\t\t\tfontStyle = [];\n\t\t\tfor (var f in fontcss) {\n\t\t\t\tfontStyle.push(f, \":\", fontcss[f], \";\");\n\t\t\t}\n\t\t\thtml.push(\"<a id='\", node.tId, consts.id.A, \"' class='\", consts.className.LEVEL, node.level,\"' treeNode\", consts.id.A,\" onclick=\\\"\", (node.click || ''),\n\t\t\t\t\"\\\" \", ((url != null && url.length > 0) ? \"href='\" + url + \"'\" : \"\"), \" target='\",view.makeNodeTarget(node),\"' style='\", fontStyle.join(''),\n\t\t\t\t\"'\");\n\t\t\tif (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle) && title) {html.push(\"title='\", title.replace(/'/g,\"&#39;\").replace(/</g,'&lt;').replace(/>/g,'&gt;'),\"'\");}\n\t\t\thtml.push(\">\");\n\t\t},\n\t\tmakeNodeFontCss: function(setting, node) {\n\t\t\tvar fontCss = tools.apply(setting.view.fontCss, [setting.treeId, node], setting.view.fontCss);\n\t\t\treturn (fontCss && ((typeof fontCss) != \"function\")) ? fontCss : {};\n\t\t},\n\t\tmakeNodeIcoClass: function(setting, node) {\n\t\t\tvar icoCss = [\"ico\"];\n\t\t\tif (!node.isAjaxing) {\n\t\t\t\ticoCss[0] = (node.iconSkin ? node.iconSkin + \"_\" : \"\") + icoCss[0];\n\t\t\t\tif (node.isParent) {\n\t\t\t\t\ticoCss.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);\n\t\t\t\t} else {\n\t\t\t\t\ticoCss.push(consts.folder.DOCU);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn consts.className.BUTTON + \" \" + icoCss.join('_');\n\t\t},\n\t\tmakeNodeIcoStyle: function(setting, node) {\n\t\t\tvar icoStyle = [];\n\t\t\tif (!node.isAjaxing) {\n\t\t\t\tvar icon = (node.isParent && node.iconOpen && node.iconClose) ? (node.open ? node.iconOpen : node.iconClose) : node.icon;\n\t\t\t\tif (icon) icoStyle.push(\"background:url(\", icon, \") 0 0 no-repeat;\");\n\t\t\t\tif (setting.view.showIcon == false || !tools.apply(setting.view.showIcon, [setting.treeId, node], true)) {\n\t\t\t\t\ticoStyle.push(\"width:0px;height:0px;\");\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn icoStyle.join('');\n\t\t},\n\t\tmakeNodeLineClass: function(setting, node) {\n\t\t\tvar lineClass = [];\n\t\t\tif (setting.view.showLine) {\n\t\t\t\tif (node.level == 0 && node.isFirstNode && node.isLastNode) {\n\t\t\t\t\tlineClass.push(consts.line.ROOT);\n\t\t\t\t} else if (node.level == 0 && node.isFirstNode) {\n\t\t\t\t\tlineClass.push(consts.line.ROOTS);\n\t\t\t\t} else if (node.isLastNode) {\n\t\t\t\t\tlineClass.push(consts.line.BOTTOM);\n\t\t\t\t} else {\n\t\t\t\t\tlineClass.push(consts.line.CENTER);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlineClass.push(consts.line.NOLINE);\n\t\t\t}\n\t\t\tif (node.isParent) {\n\t\t\t\tlineClass.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);\n\t\t\t} else {\n\t\t\t\tlineClass.push(consts.folder.DOCU);\n\t\t\t}\n\t\t\treturn view.makeNodeLineClassEx(node) + lineClass.join('_');\n\t\t},\n\t\tmakeNodeLineClassEx: function(node) {\n\t\t\treturn consts.className.BUTTON + \" \" + consts.className.LEVEL + node.level + \" \" + consts.className.SWITCH + \" \";\n\t\t},\n\t\tmakeNodeTarget: function(node) {\n\t\t\treturn (node.target || \"_blank\");\n\t\t},\n\t\tmakeNodeUrl: function(setting, node) {\n\t\t\tvar urlKey = setting.data.key.url;\n\t\t\treturn node[urlKey] ? node[urlKey] : null;\n\t\t},\n\t\tmakeUlHtml: function(setting, node, html, content) {\n\t\t\thtml.push(\"<ul id='\", node.tId, consts.id.UL, \"' class='\", consts.className.LEVEL, node.level, \" \", view.makeUlLineClass(setting, node), \"' style='display:\", (node.open ? \"block\": \"none\"),\"'>\");\n\t\t\thtml.push(content);\n\t\t\thtml.push(\"</ul>\");\n\t\t},\n\t\tmakeUlLineClass: function(setting, node) {\n\t\t\treturn ((setting.view.showLine && !node.isLastNode) ? consts.line.LINE : \"\");\n\t\t},\n\t\tremoveChildNodes: function(setting, node) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tnodes = node[childKey];\n\t\t\tif (!nodes) return;\n\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tdata.removeNodeCache(setting, nodes[i]);\n\t\t\t}\n\t\t\tdata.removeSelectedNode(setting);\n\t\t\tdelete node[childKey];\n\n\t\t\tif (!setting.data.keep.parent) {\n\t\t\t\tnode.isParent = false;\n\t\t\t\tnode.open = false;\n\t\t\t\tvar tmp_switchObj = $$(node, consts.id.SWITCH, setting),\n\t\t\t\ttmp_icoObj = $$(node, consts.id.ICON, setting);\n\t\t\t\tview.replaceSwitchClass(node, tmp_switchObj, consts.folder.DOCU);\n\t\t\t\tview.replaceIcoClass(node, tmp_icoObj, consts.folder.DOCU);\n\t\t\t\t$$(node, consts.id.UL, setting).remove();\n\t\t\t} else {\n\t\t\t\t$$(node, consts.id.UL, setting).empty();\n\t\t\t}\n\t\t},\n\t\tsetFirstNode: function(setting, parentNode) {\n\t\t\tvar childKey = setting.data.key.children, childLength = parentNode[childKey].length;\n\t\t\tif ( childLength > 0) {\n\t\t\t\tparentNode[childKey][0].isFirstNode = true;\n\t\t\t}\n\t\t},\n\t\tsetLastNode: function(setting, parentNode) {\n\t\t\tvar childKey = setting.data.key.children, childLength = parentNode[childKey].length;\n\t\t\tif ( childLength > 0) {\n\t\t\t\tparentNode[childKey][childLength - 1].isLastNode = true;\n\t\t\t}\n\t\t},\n\t\tremoveNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children,\n\t\t\tparentNode = (node.parentTId) ? node.getParentNode() : root;\n\n\t\t\tnode.isFirstNode = false;\n\t\t\tnode.isLastNode = false;\n\t\t\tnode.getPreNode = function() {return null;};\n\t\t\tnode.getNextNode = function() {return null;};\n\n\t\t\tif (!data.getNodeCache(setting, node.tId)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$$(node, setting).remove();\n\t\t\tdata.removeNodeCache(setting, node);\n\t\t\tdata.removeSelectedNode(setting, node);\n\n\t\t\tfor (var i = 0, l = parentNode[childKey].length; i < l; i++) {\n\t\t\t\tif (parentNode[childKey][i].tId == node.tId) {\n\t\t\t\t\tparentNode[childKey].splice(i, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tview.setFirstNode(setting, parentNode);\n\t\t\tview.setLastNode(setting, parentNode);\n\n\t\t\tvar tmp_ulObj,tmp_switchObj,tmp_icoObj,\n\t\t\tchildLength = parentNode[childKey].length;\n\n\t\t\t//repair nodes old parent\n\t\t\tif (!setting.data.keep.parent && childLength == 0) {\n\t\t\t\t//old parentNode has no child nodes\n\t\t\t\tparentNode.isParent = false;\n\t\t\t\tparentNode.open = false;\n\t\t\t\ttmp_ulObj = $$(parentNode, consts.id.UL, setting);\n\t\t\t\ttmp_switchObj = $$(parentNode, consts.id.SWITCH, setting);\n\t\t\t\ttmp_icoObj = $$(parentNode, consts.id.ICON, setting);\n\t\t\t\tview.replaceSwitchClass(parentNode, tmp_switchObj, consts.folder.DOCU);\n\t\t\t\tview.replaceIcoClass(parentNode, tmp_icoObj, consts.folder.DOCU);\n\t\t\t\ttmp_ulObj.css(\"display\", \"none\");\n\n\t\t\t} else if (setting.view.showLine && childLength > 0) {\n\t\t\t\t//old parentNode has child nodes\n\t\t\t\tvar newLast = parentNode[childKey][childLength - 1];\n\t\t\t\ttmp_ulObj = $$(newLast, consts.id.UL, setting);\n\t\t\t\ttmp_switchObj = $$(newLast, consts.id.SWITCH, setting);\n\t\t\t\ttmp_icoObj = $$(newLast, consts.id.ICON, setting);\n\t\t\t\tif (parentNode == root) {\n\t\t\t\t\tif (parentNode[childKey].length == 1) {\n\t\t\t\t\t\t//node was root, and ztree has only one root after move node\n\t\t\t\t\t\tview.replaceSwitchClass(newLast, tmp_switchObj, consts.line.ROOT);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar tmp_first_switchObj = $$(parentNode[childKey][0], consts.id.SWITCH, setting);\n\t\t\t\t\t\tview.replaceSwitchClass(parentNode[childKey][0], tmp_first_switchObj, consts.line.ROOTS);\n\t\t\t\t\t\tview.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tview.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);\n\t\t\t\t}\n\t\t\t\ttmp_ulObj.removeClass(consts.line.LINE);\n\t\t\t}\n\t\t},\n\t\treplaceIcoClass: function(node, obj, newName) {\n\t\t\tif (!obj || node.isAjaxing) return;\n\t\t\tvar tmpName = obj.attr(\"class\");\n\t\t\tif (tmpName == undefined) return;\n\t\t\tvar tmpList = tmpName.split(\"_\");\n\t\t\tswitch (newName) {\n\t\t\t\tcase consts.folder.OPEN:\n\t\t\t\tcase consts.folder.CLOSE:\n\t\t\t\tcase consts.folder.DOCU:\n\t\t\t\t\ttmpList[tmpList.length-1] = newName;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tobj.attr(\"class\", tmpList.join(\"_\"));\n\t\t},\n\t\treplaceSwitchClass: function(node, obj, newName) {\n\t\t\tif (!obj) return;\n\t\t\tvar tmpName = obj.attr(\"class\");\n\t\t\tif (tmpName == undefined) return;\n\t\t\tvar tmpList = tmpName.split(\"_\");\n\t\t\tswitch (newName) {\n\t\t\t\tcase consts.line.ROOT:\n\t\t\t\tcase consts.line.ROOTS:\n\t\t\t\tcase consts.line.CENTER:\n\t\t\t\tcase consts.line.BOTTOM:\n\t\t\t\tcase consts.line.NOLINE:\n\t\t\t\t\ttmpList[0] = view.makeNodeLineClassEx(node) + newName;\n\t\t\t\t\tbreak;\n\t\t\t\tcase consts.folder.OPEN:\n\t\t\t\tcase consts.folder.CLOSE:\n\t\t\t\tcase consts.folder.DOCU:\n\t\t\t\t\ttmpList[1] = newName;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tobj.attr(\"class\", tmpList.join(\"_\"));\n\t\t\tif (newName !== consts.folder.DOCU) {\n\t\t\t\tobj.removeAttr(\"disabled\");\n\t\t\t} else {\n\t\t\t\tobj.attr(\"disabled\", \"disabled\");\n\t\t\t}\n\t\t},\n\t\tselectNode: function(setting, node, addFlag) {\n\t\t\tif (!addFlag) {\n\t\t\t\tview.cancelPreSelectedNode(setting, null, node);\n\t\t\t}\n\t\t\t$$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED);\n\t\t\tdata.addSelectedNode(setting, node);\n\t\t\tsetting.treeObj.trigger(consts.event.SELECTED, [event, setting.treeId, node]);\n\t\t},\n\t\tsetNodeFontCss: function(setting, treeNode) {\n\t\t\tvar aObj = $$(treeNode, consts.id.A, setting),\n\t\t\tfontCss = view.makeNodeFontCss(setting, treeNode);\n\t\t\tif (fontCss) {\n\t\t\t\taObj.css(fontCss);\n\t\t\t}\n\t\t},\n\t\tsetNodeLineIcos: function(setting, node) {\n\t\t\tif (!node) return;\n\t\t\tvar switchObj = $$(node, consts.id.SWITCH, setting),\n\t\t\tulObj = $$(node, consts.id.UL, setting),\n\t\t\ticoObj = $$(node, consts.id.ICON, setting),\n\t\t\tulLine = view.makeUlLineClass(setting, node);\n\t\t\tif (ulLine.length==0) {\n\t\t\t\tulObj.removeClass(consts.line.LINE);\n\t\t\t} else {\n\t\t\t\tulObj.addClass(ulLine);\n\t\t\t}\n\t\t\tswitchObj.attr(\"class\", view.makeNodeLineClass(setting, node));\n\t\t\tif (node.isParent) {\n\t\t\t\tswitchObj.removeAttr(\"disabled\");\n\t\t\t} else {\n\t\t\t\tswitchObj.attr(\"disabled\", \"disabled\");\n\t\t\t}\n\t\t\ticoObj.removeAttr(\"style\");\n\t\t\ticoObj.attr(\"style\", view.makeNodeIcoStyle(setting, node));\n\t\t\ticoObj.attr(\"class\", view.makeNodeIcoClass(setting, node));\n\t\t},\n\t\tsetNodeName: function(setting, node) {\n\t\t\tvar title = data.getNodeTitle(setting, node),\n\t\t\tnObj = $$(node, consts.id.SPAN, setting);\n\t\t\tnObj.empty();\n\t\t\tif (setting.view.nameIsHTML) {\n\t\t\t\tnObj.html(data.getNodeName(setting, node));\n\t\t\t} else {\n\t\t\t\tnObj.text(data.getNodeName(setting, node));\n\t\t\t}\n\t\t\tif (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle)) {\n\t\t\t\tvar aObj = $$(node, consts.id.A, setting);\n\t\t\t\taObj.attr(\"title\", !title ? \"\" : title);\n\t\t\t}\n\t\t},\n\t\tsetNodeTarget: function(setting, node) {\n\t\t\tvar aObj = $$(node, consts.id.A, setting);\n\t\t\taObj.attr(\"target\", view.makeNodeTarget(node));\n\t\t},\n\t\tsetNodeUrl: function(setting, node) {\n\t\t\tvar aObj = $$(node, consts.id.A, setting),\n\t\t\turl = view.makeNodeUrl(setting, node);\n\t\t\tif (url == null || url.length == 0) {\n\t\t\t\taObj.removeAttr(\"href\");\n\t\t\t} else {\n\t\t\t\taObj.attr(\"href\", url);\n\t\t\t}\n\t\t},\n\t\tswitchNode: function(setting, node) {\n\t\t\tif (node.open || !tools.canAsync(setting, node)) {\n\t\t\t\tview.expandCollapseNode(setting, node, !node.open);\n\t\t\t} else if (setting.async.enable) {\n\t\t\t\tif (!view.asyncNode(setting, node)) {\n\t\t\t\t\tview.expandCollapseNode(setting, node, !node.open);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else if (node) {\n\t\t\t\tview.expandCollapseNode(setting, node, !node.open);\n\t\t\t}\n\t\t}\n\t};\n\t// zTree defind\n\t$.fn.zTree = {\n\t\tconsts : _consts,\n\t\t_z : {\n\t\t\ttools: tools,\n\t\t\tview: view,\n\t\t\tevent: event,\n\t\t\tdata: data\n\t\t},\n\t\tgetZTreeObj: function(treeId) {\n\t\t\tvar o = data.getZTreeTools(treeId);\n\t\t\treturn o ? o : null;\n\t\t},\n\t\tdestroy: function(treeId) {\n\t\t\tif (!!treeId && treeId.length > 0) {\n\t\t\t\tview.destroy(data.getSetting(treeId));\n\t\t\t} else {\n\t\t\t\tfor(var s in settings) {\n\t\t\t\t\tview.destroy(settings[s]);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tinit: function(obj, zSetting, zNodes) {\n\t\t\tvar setting = tools.clone(_setting);\n\t\t\t$.extend(true, setting, zSetting);\n\t\t\tsetting.treeId = obj.attr(\"id\");\n\t\t\tsetting.treeObj = obj;\n\t\t\tsetting.treeObj.empty();\n\t\t\tsettings[setting.treeId] = setting;\n\t\t\t//For some older browser,(e.g., ie6)\n\t\t\tif(typeof document.body.style.maxHeight === \"undefined\") {\n\t\t\t\tsetting.view.expandSpeed = \"\";\n\t\t\t}\n\t\t\tdata.initRoot(setting);\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tzNodes = zNodes ? tools.clone(tools.isArray(zNodes)? zNodes : [zNodes]) : [];\n\t\t\tif (setting.data.simpleData.enable) {\n\t\t\t\troot[childKey] = data.transformTozTreeFormat(setting, zNodes);\n\t\t\t} else {\n\t\t\t\troot[childKey] = zNodes;\n\t\t\t}\n\n\t\t\tdata.initCache(setting);\n\t\t\tevent.unbindTree(setting);\n\t\t\tevent.bindTree(setting);\n\t\t\tevent.unbindEvent(setting);\n\t\t\tevent.bindEvent(setting);\n\n\t\t\tvar zTreeTools = {\n\t\t\t\tsetting : setting,\n\t\t\t\taddNodes : function(parentNode, newNodes, isSilent) {\n\t\t\t\t\tif (!newNodes) return null;\n\t\t\t\t\tif (!parentNode) parentNode = null;\n\t\t\t\t\tif (parentNode && !parentNode.isParent && setting.data.keep.leaf) return null;\n\t\t\t\t\tvar xNewNodes = tools.clone(tools.isArray(newNodes)? newNodes: [newNodes]);\n\t\t\t\t\tfunction addCallback() {\n\t\t\t\t\t\tview.addNodes(setting, parentNode, xNewNodes, (isSilent==true));\n\t\t\t\t\t}\n\n\t\t\t\t\tif (tools.canAsync(setting, parentNode)) {\n\t\t\t\t\t\tview.asyncNode(setting, parentNode, isSilent, addCallback);\n\t\t\t\t\t} else {\n\t\t\t\t\t\taddCallback();\n\t\t\t\t\t}\n\t\t\t\t\treturn xNewNodes;\n\t\t\t\t},\n\t\t\t\tcancelSelectedNode : function(node) {\n\t\t\t\t\tview.cancelPreSelectedNode(setting, node);\n\t\t\t\t},\n\t\t\t\tdestroy : function() {\n\t\t\t\t\tview.destroy(setting);\n\t\t\t\t},\n\t\t\t\texpandAll : function(expandFlag) {\n\t\t\t\t\texpandFlag = !!expandFlag;\n\t\t\t\t\tview.expandCollapseSonNode(setting, null, expandFlag, true);\n\t\t\t\t\treturn expandFlag;\n\t\t\t\t},\n\t\t\t\texpandNode : function(node, expandFlag, sonSign, focus, callbackFlag) {\n\t\t\t\t\tif (!node || !node.isParent) return null;\n\t\t\t\t\tif (expandFlag !== true && expandFlag !== false) {\n\t\t\t\t\t\texpandFlag = !node.open;\n\t\t\t\t\t}\n\t\t\t\t\tcallbackFlag = !!callbackFlag;\n\n\t\t\t\t\tif (callbackFlag && expandFlag && (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t} else if (callbackFlag && !expandFlag && (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tif (expandFlag && node.parentTId) {\n\t\t\t\t\t\tview.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, false);\n\t\t\t\t\t}\n\t\t\t\t\tif (expandFlag === node.open && !sonSign) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\tdata.getRoot(setting).expandTriggerFlag = callbackFlag;\n\t\t\t\t\tif (!tools.canAsync(setting, node) && sonSign) {\n\t\t\t\t\t\tview.expandCollapseSonNode(setting, node, expandFlag, true, function() {\n\t\t\t\t\t\t\tif (focus !== false) {try{$$(node, setting).focus().blur();}catch(e){}}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnode.open = !expandFlag;\n\t\t\t\t\t\tview.switchNode(this.setting, node);\n\t\t\t\t\t\tif (focus !== false) {try{$$(node, setting).focus().blur();}catch(e){}}\n\t\t\t\t\t}\n\t\t\t\t\treturn expandFlag;\n\t\t\t\t},\n\t\t\t\tgetNodes : function() {\n\t\t\t\t\treturn data.getNodes(setting);\n\t\t\t\t},\n\t\t\t\tgetNodeByParam : function(key, value, parentNode) {\n\t\t\t\t\tif (!key) return null;\n\t\t\t\t\treturn data.getNodeByParam(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), key, value);\n\t\t\t\t},\n\t\t\t\tgetNodeByTId : function(tId) {\n\t\t\t\t\treturn data.getNodeCache(setting, tId);\n\t\t\t\t},\n\t\t\t\tgetNodesByParam : function(key, value, parentNode) {\n\t\t\t\t\tif (!key) return null;\n\t\t\t\t\treturn data.getNodesByParam(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), key, value);\n\t\t\t\t},\n\t\t\t\tgetNodesByParamFuzzy : function(key, value, parentNode) {\n\t\t\t\t\tif (!key) return null;\n\t\t\t\t\treturn data.getNodesByParamFuzzy(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), key, value);\n\t\t\t\t},\n\t\t\t\tgetNodesByFilter: function(filter, isSingle, parentNode, invokeParam) {\n\t\t\t\t\tisSingle = !!isSingle;\n\t\t\t\t\tif (!filter || (typeof filter != \"function\")) return (isSingle ? null : []);\n\t\t\t\t\treturn data.getNodesByFilter(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), filter, isSingle, invokeParam);\n\t\t\t\t},\n\t\t\t\tgetNodeIndex : function(node) {\n\t\t\t\t\tif (!node) return null;\n\t\t\t\t\tvar childKey = setting.data.key.children,\n\t\t\t\t\tparentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting);\n\t\t\t\t\tfor (var i=0, l = parentNode[childKey].length; i < l; i++) {\n\t\t\t\t\t\tif (parentNode[childKey][i] == node) return i;\n\t\t\t\t\t}\n\t\t\t\t\treturn -1;\n\t\t\t\t},\n\t\t\t\tgetSelectedNodes : function() {\n\t\t\t\t\tvar r = [], list = data.getRoot(setting).curSelectedList;\n\t\t\t\t\tfor (var i=0, l=list.length; i<l; i++) {\n\t\t\t\t\t\tr.push(list[i]);\n\t\t\t\t\t}\n\t\t\t\t\treturn r;\n\t\t\t\t},\n\t\t\t\tisSelectedNode : function(node) {\n\t\t\t\t\treturn data.isSelectedNode(setting, node);\n\t\t\t\t},\n\t\t\t\treAsyncChildNodes : function(parentNode, reloadType, isSilent) {\n\t\t\t\t\tif (!this.setting.async.enable) return;\n\t\t\t\t\tvar isRoot = !parentNode;\n\t\t\t\t\tif (isRoot) {\n\t\t\t\t\t\tparentNode = data.getRoot(setting);\n\t\t\t\t\t}\n\t\t\t\t\tif (reloadType==\"refresh\") {\n\t\t\t\t\t\tvar childKey = this.setting.data.key.children;\n\t\t\t\t\t\tfor (var i = 0, l = parentNode[childKey] ? parentNode[childKey].length : 0; i < l; i++) {\n\t\t\t\t\t\t\tdata.removeNodeCache(setting, parentNode[childKey][i]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdata.removeSelectedNode(setting);\n\t\t\t\t\t\tparentNode[childKey] = [];\n\t\t\t\t\t\tif (isRoot) {\n\t\t\t\t\t\t\tthis.setting.treeObj.empty();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar ulObj = $$(parentNode, consts.id.UL, setting);\n\t\t\t\t\t\t\tulObj.empty();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tview.asyncNode(this.setting, isRoot? null:parentNode, !!isSilent);\n\t\t\t\t},\n\t\t\t\trefresh : function() {\n\t\t\t\t\tthis.setting.treeObj.empty();\n\t\t\t\t\tvar root = data.getRoot(setting),\n\t\t\t\t\tnodes = root[setting.data.key.children]\n\t\t\t\t\tdata.initRoot(setting);\n\t\t\t\t\troot[setting.data.key.children] = nodes\n\t\t\t\t\tdata.initCache(setting);\n\t\t\t\t\tview.createNodes(setting, 0, root[setting.data.key.children]);\n\t\t\t\t},\n\t\t\t\tremoveChildNodes : function(node) {\n\t\t\t\t\tif (!node) return null;\n\t\t\t\t\tvar childKey = setting.data.key.children,\n\t\t\t\t\tnodes = node[childKey];\n\t\t\t\t\tview.removeChildNodes(setting, node);\n\t\t\t\t\treturn nodes ? nodes : null;\n\t\t\t\t},\n\t\t\t\tremoveNode : function(node, callbackFlag) {\n\t\t\t\t\tif (!node) return;\n\t\t\t\t\tcallbackFlag = !!callbackFlag;\n\t\t\t\t\tif (callbackFlag && tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return;\n\t\t\t\t\tview.removeNode(setting, node);\n\t\t\t\t\tif (callbackFlag) {\n\t\t\t\t\t\tthis.setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tselectNode : function(node, addFlag) {\n\t\t\t\t\tif (!node) return;\n\t\t\t\t\tif (tools.uCanDo(setting)) {\n\t\t\t\t\t\taddFlag = setting.view.selectedMulti && addFlag;\n\t\t\t\t\t\tif (node.parentTId) {\n\t\t\t\t\t\t\tview.expandCollapseParentNode(setting, node.getParentNode(), true, false, function() {\n\t\t\t\t\t\t\t\ttry{$$(node, setting).focus().blur();}catch(e){}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttry{$$(node, setting).focus().blur();}catch(e){}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tview.selectNode(setting, node, addFlag);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\ttransformTozTreeNodes : function(simpleNodes) {\n\t\t\t\t\treturn data.transformTozTreeFormat(setting, simpleNodes);\n\t\t\t\t},\n\t\t\t\ttransformToArray : function(nodes) {\n\t\t\t\t\treturn data.transformToArrayFormat(setting, nodes);\n\t\t\t\t},\n\t\t\t\tupdateNode : function(node, checkTypeFlag) {\n\t\t\t\t\tif (!node) return;\n\t\t\t\t\tvar nObj = $$(node, setting);\n\t\t\t\t\tif (nObj.get(0) && tools.uCanDo(setting)) {\n\t\t\t\t\t\tview.setNodeName(setting, node);\n\t\t\t\t\t\tview.setNodeTarget(setting, node);\n\t\t\t\t\t\tview.setNodeUrl(setting, node);\n\t\t\t\t\t\tview.setNodeLineIcos(setting, node);\n\t\t\t\t\t\tview.setNodeFontCss(setting, node);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\troot.treeTools = zTreeTools;\n\t\t\tdata.setZTreeTools(setting, zTreeTools);\n\n\t\t\tif (root[childKey] && root[childKey].length > 0) {\n\t\t\t\tview.createNodes(setting, 0, root[childKey]);\n\t\t\t} else if (setting.async.enable && setting.async.url && setting.async.url !== '') {\n\t\t\t\tview.asyncNode(setting);\n\t\t\t}\n\t\t\treturn zTreeTools;\n\t\t}\n\t};\n\n\tvar zt = $.fn.zTree,\n\t$$ = tools.$,\n\tconsts = zt.consts;\n})(jQuery);\n/*\n * JQuery zTree excheck v3.5.18\n * http://zTree.me/\n *\n * Copyright (c) 2010 Hunter.z\n *\n * Licensed same as jquery - MIT License\n * http://www.opensource.org/licenses/mit-license.php\n *\n * email: hunter.z@263.net\n * Date: 2015-05-25\n */\n(function($){\n\t//default consts of excheck\n\tvar _consts = {\n\t\tevent: {\n\t\t\tCHECK: \"ztree_check\"\n\t\t},\n\t\tid: {\n\t\t\tCHECK: \"_check\"\n\t\t},\n\t\tcheckbox: {\n\t\t\tSTYLE: \"checkbox\",\n\t\t\tDEFAULT: \"chk\",\n\t\t\tDISABLED: \"disable\",\n\t\t\tFALSE: \"false\",\n\t\t\tTRUE: \"true\",\n\t\t\tFULL: \"full\",\n\t\t\tPART: \"part\",\n\t\t\tFOCUS: \"focus\"\n\t\t},\n\t\tradio: {\n\t\t\tSTYLE: \"radio\",\n\t\t\tTYPE_ALL: \"all\",\n\t\t\tTYPE_LEVEL: \"level\"\n\t\t}\n\t},\n\t//default setting of excheck\n\t_setting = {\n\t\tcheck: {\n\t\t\tenable: false,\n\t\t\tautoCheckTrigger: false,\n\t\t\tchkStyle: _consts.checkbox.STYLE,\n\t\t\tnocheckInherit: false,\n\t\t\tchkDisabledInherit: false,\n\t\t\tradioType: _consts.radio.TYPE_LEVEL,\n\t\t\tchkboxType: {\n\t\t\t\t\"Y\": \"ps\",\n\t\t\t\t\"N\": \"ps\"\n\t\t\t}\n\t\t},\n\t\tdata: {\n\t\t\tkey: {\n\t\t\t\tchecked: \"checked\"\n\t\t\t}\n\t\t},\n\t\tcallback: {\n\t\t\tbeforeCheck:null,\n\t\t\tonCheck:null\n\t\t}\n\t},\n\t//default root of excheck\n\t_initRoot = function (setting) {\n\t\tvar r = data.getRoot(setting);\n\t\tr.radioCheckedList = [];\n\t},\n\t//default cache of excheck\n\t_initCache = function(treeId) {},\n\t//default bind event of excheck\n\t_bindEvent = function(setting) {\n\t\tvar o = setting.treeObj,\n\t\tc = consts.event;\n\t\to.bind(c.CHECK, function (event, srcEvent, treeId, node) {\n\t\t\tevent.srcEvent = srcEvent;\n\t\t\ttools.apply(setting.callback.onCheck, [event, treeId, node]);\n\t\t});\n\t},\n\t_unbindEvent = function(setting) {\n\t\tvar o = setting.treeObj,\n\t\tc = consts.event;\n\t\to.unbind(c.CHECK);\n\t},\n\t//default event proxy of excheck\n\t_eventProxy = function(e) {\n\t\tvar target = e.target,\n\t\tsetting = data.getSetting(e.data.treeId),\n\t\ttId = \"\", node = null,\n\t\tnodeEventType = \"\", treeEventType = \"\",\n\t\tnodeEventCallback = null, treeEventCallback = null;\n\n\t\tif (tools.eqs(e.type, \"mouseover\")) {\n\t\t\tif (setting.check.enable && tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\"+ consts.id.CHECK) !== null) {\n\t\t\t\ttId = tools.getNodeMainDom(target).id;\n\t\t\t\tnodeEventType = \"mouseoverCheck\";\n\t\t\t}\n\t\t} else if (tools.eqs(e.type, \"mouseout\")) {\n\t\t\tif (setting.check.enable && tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\"+ consts.id.CHECK) !== null) {\n\t\t\t\ttId = tools.getNodeMainDom(target).id;\n\t\t\t\tnodeEventType = \"mouseoutCheck\";\n\t\t\t}\n\t\t} else if (tools.eqs(e.type, \"click\")) {\n\t\t\tif (setting.check.enable && tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\"+ consts.id.CHECK) !== null) {\n\t\t\t\ttId = tools.getNodeMainDom(target).id;\n\t\t\t\tnodeEventType = \"checkNode\";\n\t\t\t}\n\t\t}\n\t\tif (tId.length>0) {\n\t\t\tnode = data.getNodeCache(setting, tId);\n\t\t\tswitch (nodeEventType) {\n\t\t\t\tcase \"checkNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onCheckNode;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"mouseoverCheck\" :\n\t\t\t\t\tnodeEventCallback = _handler.onMouseoverCheck;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"mouseoutCheck\" :\n\t\t\t\t\tnodeEventCallback = _handler.onMouseoutCheck;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tvar proxyResult = {\n\t\t\tstop: nodeEventType === \"checkNode\",\n\t\t\tnode: node,\n\t\t\tnodeEventType: nodeEventType,\n\t\t\tnodeEventCallback: nodeEventCallback,\n\t\t\ttreeEventType: treeEventType,\n\t\t\ttreeEventCallback: treeEventCallback\n\t\t};\n\t\treturn proxyResult\n\t},\n\t//default init node of excheck\n\t_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n\t\tif (!n) return;\n\t\tvar checkedKey = setting.data.key.checked;\n\t\tif (typeof n[checkedKey] == \"string\") n[checkedKey] = tools.eqs(n[checkedKey], \"true\");\n\t\tn[checkedKey] = !!n[checkedKey];\n\t\tn.checkedOld = n[checkedKey];\n\t\tif (typeof n.nocheck == \"string\") n.nocheck = tools.eqs(n.nocheck, \"true\");\n\t\tn.nocheck = !!n.nocheck || (setting.check.nocheckInherit && parentNode && !!parentNode.nocheck);\n\t\tif (typeof n.chkDisabled == \"string\") n.chkDisabled = tools.eqs(n.chkDisabled, \"true\");\n\t\tn.chkDisabled = !!n.chkDisabled || (setting.check.chkDisabledInherit && parentNode && !!parentNode.chkDisabled);\n\t\tif (typeof n.halfCheck == \"string\") n.halfCheck = tools.eqs(n.halfCheck, \"true\");\n\t\tn.halfCheck = !!n.halfCheck;\n\t\tn.check_Child_State = -1;\n\t\tn.check_Focus = false;\n\t\tn.getCheckStatus = function() {return data.getCheckStatus(setting, n);};\n\n\t\tif (setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL && n[checkedKey] ) {\n\t\t\tvar r = data.getRoot(setting);\n\t\t\tr.radioCheckedList.push(n);\n\t\t}\n\t},\n\t//add dom for check\n\t_beforeA = function(setting, node, html) {\n\t\tvar checkedKey = setting.data.key.checked;\n\t\tif (setting.check.enable) {\n\t\t\tdata.makeChkFlag(setting, node);\n\t\t\thtml.push(\"<span ID='\", node.tId, consts.id.CHECK, \"' class='\", view.makeChkClass(setting, node), \"' treeNode\", consts.id.CHECK, (node.nocheck === true?\" style='display:none;'\":\"\"),\"></span>\");\n\t\t}\n\t},\n\t//update zTreeObj, add method of check\n\t_zTreeTools = function(setting, zTreeTools) {\n\t\tzTreeTools.checkNode = function(node, checked, checkTypeFlag, callbackFlag) {\n\t\t\tvar checkedKey = this.setting.data.key.checked;\n\t\t\tif (node.chkDisabled === true) return;\n\t\t\tif (checked !== true && checked !== false) {\n\t\t\t\tchecked = !node[checkedKey];\n\t\t\t}\n\t\t\tcallbackFlag = !!callbackFlag;\n\n\t\t\tif (node[checkedKey] === checked && !checkTypeFlag) {\n\t\t\t\treturn;\n\t\t\t} else if (callbackFlag && tools.apply(this.setting.callback.beforeCheck, [this.setting.treeId, node], true) == false) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (tools.uCanDo(this.setting) && this.setting.check.enable && node.nocheck !== true) {\n\t\t\t\tnode[checkedKey] = checked;\n\t\t\t\tvar checkObj = $$(node, consts.id.CHECK, this.setting);\n\t\t\t\tif (checkTypeFlag || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);\n\t\t\t\tview.setChkClass(this.setting, checkObj, node);\n\t\t\t\tview.repairParentChkClassWithSelf(this.setting, node);\n\t\t\t\tif (callbackFlag) {\n\t\t\t\t\tthis.setting.treeObj.trigger(consts.event.CHECK, [null, this.setting.treeId, node]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tzTreeTools.checkAllNodes = function(checked) {\n\t\t\tview.repairAllChk(this.setting, !!checked);\n\t\t}\n\n\t\tzTreeTools.getCheckedNodes = function(checked) {\n\t\t\tvar childKey = this.setting.data.key.children;\n\t\t\tchecked = (checked !== false);\n\t\t\treturn data.getTreeCheckedNodes(this.setting, data.getRoot(this.setting)[childKey], checked);\n\t\t}\n\n\t\tzTreeTools.getChangeCheckedNodes = function() {\n\t\t\tvar childKey = this.setting.data.key.children;\n\t\t\treturn data.getTreeChangeCheckedNodes(this.setting, data.getRoot(this.setting)[childKey]);\n\t\t}\n\n\t\tzTreeTools.setChkDisabled = function(node, disabled, inheritParent, inheritChildren) {\n\t\t\tdisabled = !!disabled;\n\t\t\tinheritParent = !!inheritParent;\n\t\t\tinheritChildren = !!inheritChildren;\n\t\t\tview.repairSonChkDisabled(this.setting, node, disabled, inheritChildren);\n\t\t\tview.repairParentChkDisabled(this.setting, node.getParentNode(), disabled, inheritParent);\n\t\t}\n\n\t\tvar _updateNode = zTreeTools.updateNode;\n\t\tzTreeTools.updateNode = function(node, checkTypeFlag) {\n\t\t\tif (_updateNode) _updateNode.apply(zTreeTools, arguments);\n\t\t\tif (!node || !this.setting.check.enable) return;\n\t\t\tvar nObj = $$(node, this.setting);\n\t\t\tif (nObj.get(0) && tools.uCanDo(this.setting)) {\n\t\t\t\tvar checkObj = $$(node, consts.id.CHECK, this.setting);\n\t\t\t\tif (checkTypeFlag == true || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);\n\t\t\t\tview.setChkClass(this.setting, checkObj, node);\n\t\t\t\tview.repairParentChkClassWithSelf(this.setting, node);\n\t\t\t}\n\t\t}\n\t},\n\t//method of operate data\n\t_data = {\n\t\tgetRadioCheckedList: function(setting) {\n\t\t\tvar checkedList = data.getRoot(setting).radioCheckedList;\n\t\t\tfor (var i=0, j=checkedList.length; i<j; i++) {\n\t\t\t\tif(!data.getNodeCache(setting, checkedList[i].tId)) {\n\t\t\t\t\tcheckedList.splice(i, 1);\n\t\t\t\t\ti--; j--;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn checkedList;\n\t\t},\n\t\tgetCheckStatus: function(setting, node) {\n\t\t\tif (!setting.check.enable || node.nocheck || node.chkDisabled) return null;\n\t\t\tvar checkedKey = setting.data.key.checked,\n\t\t\tr = {\n\t\t\t\tchecked: node[checkedKey],\n\t\t\t\thalf: node.halfCheck ? node.halfCheck : (setting.check.chkStyle == consts.radio.STYLE ? (node.check_Child_State === 2) : (node[checkedKey] ? (node.check_Child_State > -1 && node.check_Child_State < 2) : (node.check_Child_State > 0)))\n\t\t\t};\n\t\t\treturn r;\n\t\t},\n\t\tgetTreeCheckedNodes: function(setting, nodes, checked, results) {\n\t\t\tif (!nodes) return [];\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked,\n\t\t\tonlyOne = (checked && setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL);\n\t\t\tresults = !results ? [] : results;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (nodes[i].nocheck !== true && nodes[i].chkDisabled !== true && nodes[i][checkedKey] == checked) {\n\t\t\t\t\tresults.push(nodes[i]);\n\t\t\t\t\tif(onlyOne) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdata.getTreeCheckedNodes(setting, nodes[i][childKey], checked, results);\n\t\t\t\tif(onlyOne && results.length > 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn results;\n\t\t},\n\t\tgetTreeChangeCheckedNodes: function(setting, nodes, results) {\n\t\t\tif (!nodes) return [];\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked;\n\t\t\tresults = !results ? [] : results;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (nodes[i].nocheck !== true && nodes[i].chkDisabled !== true && nodes[i][checkedKey] != nodes[i].checkedOld) {\n\t\t\t\t\tresults.push(nodes[i]);\n\t\t\t\t}\n\t\t\t\tdata.getTreeChangeCheckedNodes(setting, nodes[i][childKey], results);\n\t\t\t}\n\t\t\treturn results;\n\t\t},\n\t\tmakeChkFlag: function(setting, node) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked,\n\t\t\tchkFlag = -1;\n\t\t\tif (node[childKey]) {\n\t\t\t\tfor (var i = 0, l = node[childKey].length; i < l; i++) {\n\t\t\t\t\tvar cNode = node[childKey][i];\n\t\t\t\t\tvar tmp = -1;\n\t\t\t\t\tif (setting.check.chkStyle == consts.radio.STYLE) {\n\t\t\t\t\t\tif (cNode.nocheck === true || cNode.chkDisabled === true) {\n\t\t\t\t\t\t\ttmp = cNode.check_Child_State;\n\t\t\t\t\t\t} else if (cNode.halfCheck === true) {\n\t\t\t\t\t\t\ttmp = 2;\n\t\t\t\t\t\t} else if (cNode[checkedKey]) {\n\t\t\t\t\t\t\ttmp = 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttmp = cNode.check_Child_State > 0 ? 2:0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (tmp == 2) {\n\t\t\t\t\t\t\tchkFlag = 2; break;\n\t\t\t\t\t\t} else if (tmp == 0){\n\t\t\t\t\t\t\tchkFlag = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (setting.check.chkStyle == consts.checkbox.STYLE) {\n\t\t\t\t\t\tif (cNode.nocheck === true || cNode.chkDisabled === true) {\n\t\t\t\t\t\t\ttmp = cNode.check_Child_State;\n\t\t\t\t\t\t} else if (cNode.halfCheck === true) {\n\t\t\t\t\t\t\ttmp = 1;\n\t\t\t\t\t\t} else if (cNode[checkedKey] ) {\n\t\t\t\t\t\t\ttmp = (cNode.check_Child_State === -1 || cNode.check_Child_State === 2) ? 2 : 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttmp = (cNode.check_Child_State > 0) ? 1 : 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (tmp === 1) {\n\t\t\t\t\t\t\tchkFlag = 1; break;\n\t\t\t\t\t\t} else if (tmp === 2 && chkFlag > -1 && i > 0 && tmp !== chkFlag) {\n\t\t\t\t\t\t\tchkFlag = 1; break;\n\t\t\t\t\t\t} else if (chkFlag === 2 && tmp > -1 && tmp < 2) {\n\t\t\t\t\t\t\tchkFlag = 1; break;\n\t\t\t\t\t\t} else if (tmp > -1) {\n\t\t\t\t\t\t\tchkFlag = tmp;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tnode.check_Child_State = chkFlag;\n\t\t}\n\t},\n\t//method of event proxy\n\t_event = {\n\n\t},\n\t//method of event handler\n\t_handler = {\n\t\tonCheckNode: function (event, node) {\n\t\t\tif (node.chkDisabled === true) return false;\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\tcheckedKey = setting.data.key.checked;\n\t\t\tif (tools.apply(setting.callback.beforeCheck, [setting.treeId, node], true) == false) return true;\n\t\t\tnode[checkedKey] = !node[checkedKey];\n\t\t\tview.checkNodeRelation(setting, node);\n\t\t\tvar checkObj = $$(node, consts.id.CHECK, setting);\n\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\tview.repairParentChkClassWithSelf(setting, node);\n\t\t\tsetting.treeObj.trigger(consts.event.CHECK, [event, setting.treeId, node]);\n\t\t\treturn true;\n\t\t},\n\t\tonMouseoverCheck: function(event, node) {\n\t\t\tif (node.chkDisabled === true) return false;\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\tcheckObj = $$(node, consts.id.CHECK, setting);\n\t\t\tnode.check_Focus = true;\n\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\treturn true;\n\t\t},\n\t\tonMouseoutCheck: function(event, node) {\n\t\t\tif (node.chkDisabled === true) return false;\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\tcheckObj = $$(node, consts.id.CHECK, setting);\n\t\t\tnode.check_Focus = false;\n\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\treturn true;\n\t\t}\n\t},\n\t//method of tools for zTree\n\t_tools = {\n\n\t},\n\t//method of operate ztree dom\n\t_view = {\n\t\tcheckNodeRelation: function(setting, node) {\n\t\t\tvar pNode, i, l,\n\t\t\tchildKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked,\n\t\t\tr = consts.radio;\n\t\t\tif (setting.check.chkStyle == r.STYLE) {\n\t\t\t\tvar checkedList = data.getRadioCheckedList(setting);\n\t\t\t\tif (node[checkedKey]) {\n\t\t\t\t\tif (setting.check.radioType == r.TYPE_ALL) {\n\t\t\t\t\t\tfor (i = checkedList.length-1; i >= 0; i--) {\n\t\t\t\t\t\t\tpNode = checkedList[i];\n\t\t\t\t\t\t\tif (pNode[checkedKey] && pNode != node) {\n\t\t\t\t\t\t\t\tpNode[checkedKey] = false;\n\t\t\t\t\t\t\t\tcheckedList.splice(i, 1);\n\n\t\t\t\t\t\t\t\tview.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode);\n\t\t\t\t\t\t\t\tif (pNode.parentTId != node.parentTId) {\n\t\t\t\t\t\t\t\t\tview.repairParentChkClassWithSelf(setting, pNode);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcheckedList.push(node);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting);\n\t\t\t\t\t\tfor (i = 0, l = parentNode[childKey].length; i < l; i++) {\n\t\t\t\t\t\t\tpNode = parentNode[childKey][i];\n\t\t\t\t\t\t\tif (pNode[checkedKey] && pNode != node) {\n\t\t\t\t\t\t\t\tpNode[checkedKey] = false;\n\t\t\t\t\t\t\t\tview.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (setting.check.radioType == r.TYPE_ALL) {\n\t\t\t\t\tfor (i = 0, l = checkedList.length; i < l; i++) {\n\t\t\t\t\t\tif (node == checkedList[i]) {\n\t\t\t\t\t\t\tcheckedList.splice(i, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tif (node[checkedKey] && (!node[childKey] || node[childKey].length==0 || setting.check.chkboxType.Y.indexOf(\"s\") > -1)) {\n\t\t\t\t\tview.setSonNodeCheckBox(setting, node, true);\n\t\t\t\t}\n\t\t\t\tif (!node[checkedKey] && (!node[childKey] || node[childKey].length==0 || setting.check.chkboxType.N.indexOf(\"s\") > -1)) {\n\t\t\t\t\tview.setSonNodeCheckBox(setting, node, false);\n\t\t\t\t}\n\t\t\t\tif (node[checkedKey] && setting.check.chkboxType.Y.indexOf(\"p\") > -1) {\n\t\t\t\t\tview.setParentNodeCheckBox(setting, node, true);\n\t\t\t\t}\n\t\t\t\tif (!node[checkedKey] && setting.check.chkboxType.N.indexOf(\"p\") > -1) {\n\t\t\t\t\tview.setParentNodeCheckBox(setting, node, false);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tmakeChkClass: function(setting, node) {\n\t\t\tvar checkedKey = setting.data.key.checked,\n\t\t\tc = consts.checkbox, r = consts.radio,\n\t\t\tfullStyle = \"\";\n\t\t\tif (node.chkDisabled === true) {\n\t\t\t\tfullStyle = c.DISABLED;\n\t\t\t} else if (node.halfCheck) {\n\t\t\t\tfullStyle = c.PART;\n\t\t\t} else if (setting.check.chkStyle == r.STYLE) {\n\t\t\t\tfullStyle = (node.check_Child_State < 1)? c.FULL:c.PART;\n\t\t\t} else {\n\t\t\t\tfullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART);\n\t\t\t}\n\t\t\tvar chkName = setting.check.chkStyle + \"_\" + (node[checkedKey] ? c.TRUE : c.FALSE) + \"_\" + fullStyle;\n\t\t\tchkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + \"_\" + c.FOCUS : chkName;\n\t\t\treturn consts.className.BUTTON + \" \" + c.DEFAULT + \" \" + chkName;\n\t\t},\n\t\trepairAllChk: function(setting, checked) {\n\t\t\tif (setting.check.enable && setting.check.chkStyle === consts.checkbox.STYLE) {\n\t\t\t\tvar checkedKey = setting.data.key.checked,\n\t\t\t\tchildKey = setting.data.key.children,\n\t\t\t\troot = data.getRoot(setting);\n\t\t\t\tfor (var i = 0, l = root[childKey].length; i<l ; i++) {\n\t\t\t\t\tvar node = root[childKey][i];\n\t\t\t\t\tif (node.nocheck !== true && node.chkDisabled !== true) {\n\t\t\t\t\t\tnode[checkedKey] = checked;\n\t\t\t\t\t}\n\t\t\t\t\tview.setSonNodeCheckBox(setting, node, checked);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\trepairChkClass: function(setting, node) {\n\t\t\tif (!node) return;\n\t\t\tdata.makeChkFlag(setting, node);\n\t\t\tif (node.nocheck !== true) {\n\t\t\t\tvar checkObj = $$(node, consts.id.CHECK, setting);\n\t\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\t}\n\t\t},\n\t\trepairParentChkClass: function(setting, node) {\n\t\t\tif (!node || !node.parentTId) return;\n\t\t\tvar pNode = node.getParentNode();\n\t\t\tview.repairChkClass(setting, pNode);\n\t\t\tview.repairParentChkClass(setting, pNode);\n\t\t},\n\t\trepairParentChkClassWithSelf: function(setting, node) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tif (node[childKey] && node[childKey].length > 0) {\n\t\t\t\tview.repairParentChkClass(setting, node[childKey][0]);\n\t\t\t} else {\n\t\t\t\tview.repairParentChkClass(setting, node);\n\t\t\t}\n\t\t},\n\t\trepairSonChkDisabled: function(setting, node, chkDisabled, inherit) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tif (node.chkDisabled != chkDisabled) {\n\t\t\t\tnode.chkDisabled = chkDisabled;\n\t\t\t}\n\t\t\tview.repairChkClass(setting, node);\n\t\t\tif (node[childKey] && inherit) {\n\t\t\t\tfor (var i = 0, l = node[childKey].length; i < l; i++) {\n\t\t\t\t\tvar sNode = node[childKey][i];\n\t\t\t\t\tview.repairSonChkDisabled(setting, sNode, chkDisabled, inherit);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\trepairParentChkDisabled: function(setting, node, chkDisabled, inherit) {\n\t\t\tif (!node) return;\n\t\t\tif (node.chkDisabled != chkDisabled && inherit) {\n\t\t\t\tnode.chkDisabled = chkDisabled;\n\t\t\t}\n\t\t\tview.repairChkClass(setting, node);\n\t\t\tview.repairParentChkDisabled(setting, node.getParentNode(), chkDisabled, inherit);\n\t\t},\n\t\tsetChkClass: function(setting, obj, node) {\n\t\t\tif (!obj) return;\n\t\t\tif (node.nocheck === true) {\n\t\t\t\tobj.hide();\n\t\t\t} else {\n\t\t\t\tobj.show();\n\t\t\t}\n            obj.attr('class', view.makeChkClass(setting, node));\n\t\t},\n\t\tsetParentNodeCheckBox: function(setting, node, value, srcNode) {\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked,\n\t\t\tcheckObj = $$(node, consts.id.CHECK, setting);\n\t\t\tif (!srcNode) srcNode = node;\n\t\t\tdata.makeChkFlag(setting, node);\n\t\t\tif (node.nocheck !== true && node.chkDisabled !== true) {\n\t\t\t\tnode[checkedKey] = value;\n\t\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\t\tif (setting.check.autoCheckTrigger && node != srcNode) {\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (node.parentTId) {\n\t\t\t\tvar pSign = true;\n\t\t\t\tif (!value) {\n\t\t\t\t\tvar pNodes = node.getParentNode()[childKey];\n\t\t\t\t\tfor (var i = 0, l = pNodes.length; i < l; i++) {\n\t\t\t\t\t\tif ((pNodes[i].nocheck !== true && pNodes[i].chkDisabled !== true && pNodes[i][checkedKey])\n\t\t\t\t\t\t|| ((pNodes[i].nocheck === true || pNodes[i].chkDisabled === true) && pNodes[i].check_Child_State > 0)) {\n\t\t\t\t\t\t\tpSign = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (pSign) {\n\t\t\t\t\tview.setParentNodeCheckBox(setting, node.getParentNode(), value, srcNode);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsetSonNodeCheckBox: function(setting, node, value, srcNode) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked,\n\t\t\tcheckObj = $$(node, consts.id.CHECK, setting);\n\t\t\tif (!srcNode) srcNode = node;\n\n\t\t\tvar hasDisable = false;\n\t\t\tif (node[childKey]) {\n\t\t\t\tfor (var i = 0, l = node[childKey].length; i < l && node.chkDisabled !== true; i++) {\n\t\t\t\t\tvar sNode = node[childKey][i];\n\t\t\t\t\tview.setSonNodeCheckBox(setting, sNode, value, srcNode);\n\t\t\t\t\tif (sNode.chkDisabled === true) hasDisable = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (node != data.getRoot(setting) && node.chkDisabled !== true) {\n\t\t\t\tif (hasDisable && node.nocheck !== true) {\n\t\t\t\t\tdata.makeChkFlag(setting, node);\n\t\t\t\t}\n\t\t\t\tif (node.nocheck !== true && node.chkDisabled !== true) {\n\t\t\t\t\tnode[checkedKey] = value;\n\t\t\t\t\tif (!hasDisable) node.check_Child_State = (node[childKey] && node[childKey].length > 0) ? (value ? 2 : 0) : -1;\n\t\t\t\t} else {\n\t\t\t\t\tnode.check_Child_State = -1;\n\t\t\t\t}\n\t\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\t\tif (setting.check.autoCheckTrigger && node != srcNode && node.nocheck !== true && node.chkDisabled !== true) {\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t},\n\n\t_z = {\n\t\ttools: _tools,\n\t\tview: _view,\n\t\tevent: _event,\n\t\tdata: _data\n\t};\n\t$.extend(true, $.fn.zTree.consts, _consts);\n\t$.extend(true, $.fn.zTree._z, _z);\n\n\tvar zt = $.fn.zTree,\n\ttools = zt._z.tools,\n\tconsts = zt.consts,\n\tview = zt._z.view,\n\tdata = zt._z.data,\n\tevent = zt._z.event,\n\t$$ = tools.$;\n\n\tdata.exSetting(_setting);\n\tdata.addInitBind(_bindEvent);\n\tdata.addInitUnBind(_unbindEvent);\n\tdata.addInitCache(_initCache);\n\tdata.addInitNode(_initNode);\n\tdata.addInitProxy(_eventProxy, true);\n\tdata.addInitRoot(_initRoot);\n\tdata.addBeforeA(_beforeA);\n\tdata.addZTreeTools(_zTreeTools);\n\n\tvar _createNodes = view.createNodes;\n\tview.createNodes = function(setting, level, nodes, parentNode) {\n\t\tif (_createNodes) _createNodes.apply(view, arguments);\n\t\tif (!nodes) return;\n\t\tview.repairParentChkClassWithSelf(setting, parentNode);\n\t}\n\tvar _removeNode = view.removeNode;\n\tview.removeNode = function(setting, node) {\n\t\tvar parentNode = node.getParentNode();\n\t\tif (_removeNode) _removeNode.apply(view, arguments);\n\t\tif (!node || !parentNode) return;\n\t\tview.repairChkClass(setting, parentNode);\n\t\tview.repairParentChkClass(setting, parentNode);\n\t}\n\n\tvar _appendNodes = view.appendNodes;\n\tview.appendNodes = function(setting, level, nodes, parentNode, initFlag, openFlag) {\n\t\tvar html = \"\";\n\t\tif (_appendNodes) {\n\t\t\thtml = _appendNodes.apply(view, arguments);\n\t\t}\n\t\tif (parentNode) {\n\t\t\tdata.makeChkFlag(setting, parentNode);\n\t\t}\n\t\treturn html;\n\t}\n})(jQuery);\n/*\n * JQuery zTree exedit v3.5.18\n * http://zTree.me/\n *\n * Copyright (c) 2010 Hunter.z\n *\n * Licensed same as jquery - MIT License\n * http://www.opensource.org/licenses/mit-license.php\n *\n * email: hunter.z@263.net\n * Date: 2015-05-25\n */\n(function($){\n\t//default consts of exedit\n\tvar _consts = {\n\t\tevent: {\n\t\t\tDRAG: \"ztree_drag\",\n\t\t\tDROP: \"ztree_drop\",\n\t\t\tRENAME: \"ztree_rename\",\n\t\t\tDRAGMOVE:\"ztree_dragmove\"\n\t\t},\n\t\tid: {\n\t\t\tEDIT: \"_edit\",\n\t\t\tINPUT: \"_input\",\n\t\t\tREMOVE: \"_remove\"\n\t\t},\n\t\tmove: {\n\t\t\tTYPE_INNER: \"inner\",\n\t\t\tTYPE_PREV: \"prev\",\n\t\t\tTYPE_NEXT: \"next\"\n\t\t},\n\t\tnode: {\n\t\t\tCURSELECTED_EDIT: \"curSelectedNode_Edit\",\n\t\t\tTMPTARGET_TREE: \"tmpTargetzTree\",\n\t\t\tTMPTARGET_NODE: \"tmpTargetNode\"\n\t\t}\n\t},\n\t//default setting of exedit\n\t_setting = {\n\t\tedit: {\n\t\t\tenable: false,\n\t\t\teditNameSelectAll: false,\n\t\t\tshowRemoveBtn: true,\n\t\t\tshowRenameBtn: true,\n\t\t\tremoveTitle: \"remove\",\n\t\t\trenameTitle: \"rename\",\n\t\t\tdrag: {\n\t\t\t\tautoExpandTrigger: false,\n\t\t\t\tisCopy: true,\n\t\t\t\tisMove: true,\n\t\t\t\tprev: true,\n\t\t\t\tnext: true,\n\t\t\t\tinner: true,\n\t\t\t\tminMoveSize: 5,\n\t\t\t\tborderMax: 10,\n\t\t\t\tborderMin: -5,\n\t\t\t\tmaxShowNodeNum: 5,\n\t\t\t\tautoOpenTime: 500\n\t\t\t}\n\t\t},\n\t\tview: {\n\t\t\taddHoverDom: null,\n\t\t\tremoveHoverDom: null\n\t\t},\n\t\tcallback: {\n\t\t\tbeforeDrag:null,\n\t\t\tbeforeDragOpen:null,\n\t\t\tbeforeDrop:null,\n\t\t\tbeforeEditName:null,\n\t\t\tbeforeRename:null,\n\t\t\tonDrag:null,\n\t\t\tonDragMove:null,\n\t\t\tonDrop:null,\n\t\t\tonRename:null\n\t\t}\n\t},\n\t//default root of exedit\n\t_initRoot = function (setting) {\n\t\tvar r = data.getRoot(setting), rs = data.getRoots();\n\t\tr.curEditNode = null;\n\t\tr.curEditInput = null;\n\t\tr.curHoverNode = null;\n\t\tr.dragFlag = 0;\n\t\tr.dragNodeShowBefore = [];\n\t\tr.dragMaskList = new Array();\n\t\trs.showHoverDom = true;\n\t},\n\t//default cache of exedit\n\t_initCache = function(treeId) {},\n\t//default bind event of exedit\n\t_bindEvent = function(setting) {\n\t\tvar o = setting.treeObj;\n\t\tvar c = consts.event;\n\t\to.bind(c.RENAME, function (event, treeId, treeNode, isCancel) {\n\t\t\ttools.apply(setting.callback.onRename, [event, treeId, treeNode, isCancel]);\n\t\t});\n\n\t\to.bind(c.DRAG, function (event, srcEvent, treeId, treeNodes) {\n\t\t\ttools.apply(setting.callback.onDrag, [srcEvent, treeId, treeNodes]);\n\t\t});\n\n\t\to.bind(c.DRAGMOVE,function(event, srcEvent, treeId, treeNodes){\n\t\t\ttools.apply(setting.callback.onDragMove,[srcEvent, treeId, treeNodes]);\n\t\t});\n\n\t\to.bind(c.DROP, function (event, srcEvent, treeId, treeNodes, targetNode, moveType, isCopy) {\n\t\t\ttools.apply(setting.callback.onDrop, [srcEvent, treeId, treeNodes, targetNode, moveType, isCopy]);\n\t\t});\n\t},\n\t_unbindEvent = function(setting) {\n\t\tvar o = setting.treeObj;\n\t\tvar c = consts.event;\n\t\to.unbind(c.RENAME);\n\t\to.unbind(c.DRAG);\n\t\to.unbind(c.DRAGMOVE);\n\t\to.unbind(c.DROP);\n\t},\n\t//default event proxy of exedit\n\t_eventProxy = function(e) {\n\t\tvar target = e.target,\n\t\tsetting = data.getSetting(e.data.treeId),\n\t\trelatedTarget = e.relatedTarget,\n\t\ttId = \"\", node = null,\n\t\tnodeEventType = \"\", treeEventType = \"\",\n\t\tnodeEventCallback = null, treeEventCallback = null,\n\t\ttmp = null;\n\n\t\tif (tools.eqs(e.type, \"mouseover\")) {\n\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (tmp) {\n\t\t\t\ttId = tools.getNodeMainDom(tmp).id;\n\t\t\t\tnodeEventType = \"hoverOverNode\";\n\t\t\t}\n\t\t} else if (tools.eqs(e.type, \"mouseout\")) {\n\t\t\ttmp = tools.getMDom(setting, relatedTarget, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (!tmp) {\n\t\t\t\ttId = \"remove\";\n\t\t\t\tnodeEventType = \"hoverOutNode\";\n\t\t\t}\n\t\t} else if (tools.eqs(e.type, \"mousedown\")) {\n\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (tmp) {\n\t\t\t\ttId = tools.getNodeMainDom(tmp).id;\n\t\t\t\tnodeEventType = \"mousedownNode\";\n\t\t\t}\n\t\t}\n\t\tif (tId.length>0) {\n\t\t\tnode = data.getNodeCache(setting, tId);\n\t\t\tswitch (nodeEventType) {\n\t\t\t\tcase \"mousedownNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onMousedownNode;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hoverOverNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onHoverOverNode;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hoverOutNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onHoverOutNode;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tvar proxyResult = {\n\t\t\tstop: false,\n\t\t\tnode: node,\n\t\t\tnodeEventType: nodeEventType,\n\t\t\tnodeEventCallback: nodeEventCallback,\n\t\t\ttreeEventType: treeEventType,\n\t\t\ttreeEventCallback: treeEventCallback\n\t\t};\n\t\treturn proxyResult\n\t},\n\t//default init node of exedit\n\t_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n\t\tif (!n) return;\n\t\tn.isHover = false;\n\t\tn.editNameFlag = false;\n\t},\n\t//update zTreeObj, add method of edit\n\t_zTreeTools = function(setting, zTreeTools) {\n\t\tzTreeTools.cancelEditName = function(newName) {\n\t\t\tvar root = data.getRoot(this.setting);\n\t\t\tif (!root.curEditNode) return;\n\t\t\tview.cancelCurEditNode(this.setting, newName?newName:null, true);\n\t\t}\n\t\tzTreeTools.copyNode = function(targetNode, node, moveType, isSilent) {\n\t\t\tif (!node) return null;\n\t\t\tif (targetNode && !targetNode.isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) return null;\n\t\t\tvar _this = this,\n\t\t\t\tnewNode = tools.clone(node);\n\t\t\tif (!targetNode) {\n\t\t\t\ttargetNode = null;\n\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t}\n\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\tfunction copyCallback() {\n\t\t\t\t\tview.addNodes(_this.setting, targetNode, [newNode], isSilent);\n\t\t\t\t}\n\n\t\t\t\tif (tools.canAsync(this.setting, targetNode)) {\n\t\t\t\t\tview.asyncNode(this.setting, targetNode, isSilent, copyCallback);\n\t\t\t\t} else {\n\t\t\t\t\tcopyCallback();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tview.addNodes(this.setting, targetNode.parentNode, [newNode], isSilent);\n\t\t\t\tview.moveNode(this.setting, targetNode, newNode, moveType, false, isSilent);\n\t\t\t}\n\t\t\treturn newNode;\n\t\t}\n\t\tzTreeTools.editName = function(node) {\n\t\t\tif (!node || !node.tId || node !== data.getNodeCache(this.setting, node.tId)) return;\n\t\t\tif (node.parentTId) view.expandCollapseParentNode(this.setting, node.getParentNode(), true);\n\t\t\tview.editNode(this.setting, node)\n\t\t}\n\t\tzTreeTools.moveNode = function(targetNode, node, moveType, isSilent) {\n\t\t\tif (!node) return node;\n\t\t\tif (targetNode && !targetNode.isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) {\n\t\t\t\treturn null;\n\t\t\t} else if (targetNode && ((node.parentTId == targetNode.tId && moveType == consts.move.TYPE_INNER) || $$(node, this.setting).find(\"#\" + targetNode.tId).length > 0)) {\n\t\t\t\treturn null;\n\t\t\t} else if (!targetNode) {\n\t\t\t\ttargetNode = null;\n\t\t\t}\n\t\t\tvar _this = this;\n\t\t\tfunction moveCallback() {\n\t\t\t\tview.moveNode(_this.setting, targetNode, node, moveType, false, isSilent);\n\t\t\t}\n\t\t\tif (tools.canAsync(this.setting, targetNode) && moveType === consts.move.TYPE_INNER) {\n\t\t\t\tview.asyncNode(this.setting, targetNode, isSilent, moveCallback);\n\t\t\t} else {\n\t\t\t\tmoveCallback();\n\t\t\t}\n\t\t\treturn node;\n\t\t}\n\t\tzTreeTools.setEditable = function(editable) {\n\t\t\tthis.setting.edit.enable = editable;\n\t\t\treturn this.refresh();\n\t\t}\n\t},\n\t//method of operate data\n\t_data = {\n\t\tsetSonNodeLevel: function(setting, parentNode, node) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tnode.level = (parentNode)? parentNode.level + 1 : 0;\n\t\t\tif (!node[childKey]) return;\n\t\t\tfor (var i = 0, l = node[childKey].length; i < l; i++) {\n\t\t\t\tif (node[childKey][i]) data.setSonNodeLevel(setting, node, node[childKey][i]);\n\t\t\t}\n\t\t}\n\t},\n\t//method of event proxy\n\t_event = {\n\n\t},\n\t//method of event handler\n\t_handler = {\n\t\tonHoverOverNode: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\troot = data.getRoot(setting);\n\t\t\tif (root.curHoverNode != node) {\n\t\t\t\t_handler.onHoverOutNode(event);\n\t\t\t}\n\t\t\troot.curHoverNode = node;\n\t\t\tview.addHoverDom(setting, node);\n\t\t},\n\t\tonHoverOutNode: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\troot = data.getRoot(setting);\n\t\t\tif (root.curHoverNode && !data.isSelectedNode(setting, root.curHoverNode)) {\n\t\t\t\tview.removeTreeDom(setting, root.curHoverNode);\n\t\t\t\troot.curHoverNode = null;\n\t\t\t}\n\t\t},\n\t\tonMousedownNode: function(eventMouseDown, _node) {\n\t\t\tvar i,l,\n\t\t\tsetting = data.getSetting(eventMouseDown.data.treeId),\n\t\t\troot = data.getRoot(setting), roots = data.getRoots();\n\t\t\t//right click can't drag & drop\n\t\t\tif (eventMouseDown.button == 2 || !setting.edit.enable || (!setting.edit.drag.isCopy && !setting.edit.drag.isMove)) return true;\n\n\t\t\t//input of edit node name can't drag & drop\n\t\t\tvar target = eventMouseDown.target,\n\t\t\t_nodes = data.getRoot(setting).curSelectedList,\n\t\t\tnodes = [];\n\t\t\tif (!data.isSelectedNode(setting, _node)) {\n\t\t\t\tnodes = [_node];\n\t\t\t} else {\n\t\t\t\tfor (i=0, l=_nodes.length; i<l; i++) {\n\t\t\t\t\tif (_nodes[i].editNameFlag && tools.eqs(target.tagName, \"input\") && target.getAttribute(\"treeNode\"+consts.id.INPUT) !== null) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tnodes.push(_nodes[i]);\n\t\t\t\t\tif (nodes[0].parentTId !== _nodes[i].parentTId) {\n\t\t\t\t\t\tnodes = [_node];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tview.editNodeBlur = true;\n\t\t\tview.cancelCurEditNode(setting);\n\n\t\t\tvar doc = $(setting.treeObj.get(0).ownerDocument),\n\t\t\tbody = $(setting.treeObj.get(0).ownerDocument.body), curNode, tmpArrow, tmpTarget,\n\t\t\tisOtherTree = false,\n\t\t\ttargetSetting = setting,\n\t\t\tsourceSetting = setting,\n\t\t\tpreNode, nextNode,\n\t\t\tpreTmpTargetNodeId = null,\n\t\t\tpreTmpMoveType = null,\n\t\t\ttmpTargetNodeId = null,\n\t\t\tmoveType = consts.move.TYPE_INNER,\n\t\t\tmouseDownX = eventMouseDown.clientX,\n\t\t\tmouseDownY = eventMouseDown.clientY,\n\t\t\tstartTime = (new Date()).getTime();\n\n\t\t\tif (tools.uCanDo(setting)) {\n\t\t\t\tdoc.bind(\"mousemove\", _docMouseMove);\n\t\t\t}\n\t\t\tfunction _docMouseMove(event) {\n\t\t\t\t//avoid start drag after click node\n\t\t\t\tif (root.dragFlag == 0 && Math.abs(mouseDownX - event.clientX) < setting.edit.drag.minMoveSize\n\t\t\t\t\t&& Math.abs(mouseDownY - event.clientY) < setting.edit.drag.minMoveSize) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tvar i, l, tmpNode, tmpDom, tmpNodes,\n\t\t\t\tchildKey = setting.data.key.children;\n\t\t\t\tbody.css(\"cursor\", \"pointer\");\n\n\t\t\t\tif (root.dragFlag == 0) {\n\t\t\t\t\tif (tools.apply(setting.callback.beforeDrag, [setting.treeId, nodes], true) == false) {\n\t\t\t\t\t\t_docMouseUp(event);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\tif (i==0) {\n\t\t\t\t\t\t\troot.dragNodeShowBefore = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\t\tif (tmpNode.isParent && tmpNode.open) {\n\t\t\t\t\t\t\tview.expandCollapseNode(setting, tmpNode, !tmpNode.open);\n\t\t\t\t\t\t\troot.dragNodeShowBefore[tmpNode.tId] = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\troot.dragNodeShowBefore[tmpNode.tId] = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\troot.dragFlag = 1;\n\t\t\t\t\troots.showHoverDom = false;\n\t\t\t\t\ttools.showIfameMask(setting, true);\n\n\t\t\t\t\t//sort\n\t\t\t\t\tvar isOrder = true, lastIndex = -1;\n\t\t\t\t\tif (nodes.length>1) {\n\t\t\t\t\t\tvar pNodes = nodes[0].parentTId ? nodes[0].getParentNode()[childKey] : data.getNodes(setting);\n\t\t\t\t\t\ttmpNodes = [];\n\t\t\t\t\t\tfor (i=0, l=pNodes.length; i<l; i++) {\n\t\t\t\t\t\t\tif (root.dragNodeShowBefore[pNodes[i].tId] !== undefined) {\n\t\t\t\t\t\t\t\tif (isOrder && lastIndex > -1 && (lastIndex+1) !== i) {\n\t\t\t\t\t\t\t\t\tisOrder = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttmpNodes.push(pNodes[i]);\n\t\t\t\t\t\t\t\tlastIndex = i;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (nodes.length === tmpNodes.length) {\n\t\t\t\t\t\t\t\tnodes = tmpNodes;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (isOrder) {\n\t\t\t\t\t\tpreNode = nodes[0].getPreNode();\n\t\t\t\t\t\tnextNode = nodes[nodes.length-1].getNextNode();\n\t\t\t\t\t}\n\n\t\t\t\t\t//set node in selected\n\t\t\t\t\tcurNode = $$(\"<ul class='zTreeDragUL'></ul>\", setting);\n\t\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\t\ttmpNode.editNameFlag = false;\n\t\t\t\t\t\tview.selectNode(setting, tmpNode, i>0);\n\t\t\t\t\t\tview.removeTreeDom(setting, tmpNode);\n\n\t\t\t\t\t\tif (i > setting.edit.drag.maxShowNodeNum-1) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttmpDom = $$(\"<li id='\"+ tmpNode.tId +\"_tmp'></li>\", setting);\n\t\t\t\t\t\ttmpDom.append($$(tmpNode, consts.id.A, setting).clone());\n\t\t\t\t\t\ttmpDom.css(\"padding\", \"0\");\n\t\t\t\t\t\ttmpDom.children(\"#\" + tmpNode.tId + consts.id.A).removeClass(consts.node.CURSELECTED);\n\t\t\t\t\t\tcurNode.append(tmpDom);\n\t\t\t\t\t\tif (i == setting.edit.drag.maxShowNodeNum-1) {\n\t\t\t\t\t\t\ttmpDom = $$(\"<li id='\"+ tmpNode.tId +\"_moretmp'><a>  ...  </a></li>\", setting);\n\t\t\t\t\t\t\tcurNode.append(tmpDom);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcurNode.attr(\"id\", nodes[0].tId + consts.id.UL + \"_tmp\");\n\t\t\t\t\tcurNode.addClass(setting.treeObj.attr(\"class\"));\n\t\t\t\t\tcurNode.appendTo(body);\n\n\t\t\t\t\ttmpArrow = $$(\"<span class='tmpzTreeMove_arrow'></span>\", setting);\n\t\t\t\t\ttmpArrow.attr(\"id\", \"zTreeMove_arrow_tmp\");\n\t\t\t\t\ttmpArrow.appendTo(body);\n\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.DRAG, [event, setting.treeId, nodes]);\n\t\t\t\t}\n\n\t\t\t\tif (root.dragFlag == 1) {\n\t\t\t\t\tif (tmpTarget && tmpArrow.attr(\"id\") == event.target.id && tmpTargetNodeId && (event.clientX + doc.scrollLeft()+2) > ($(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).offset().left)) {\n\t\t\t\t\t\tvar xT = $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget);\n\t\t\t\t\t\tevent.target = (xT.length > 0) ? xT.get(0) : event.target;\n\t\t\t\t\t} else if (tmpTarget) {\n\t\t\t\t\t\ttmpTarget.removeClass(consts.node.TMPTARGET_TREE);\n\t\t\t\t\t\tif (tmpTargetNodeId) $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + \"_\" + consts.move.TYPE_PREV)\n\t\t\t\t\t\t\t.removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_INNER);\n\t\t\t\t\t}\n\t\t\t\t\ttmpTarget = null;\n\t\t\t\t\ttmpTargetNodeId = null;\n\n\t\t\t\t\t//judge drag & drop in multi ztree\n\t\t\t\t\tisOtherTree = false;\n\t\t\t\t\ttargetSetting = setting;\n\t\t\t\t\tvar settings = data.getSettings();\n\t\t\t\t\tfor (var s in settings) {\n\t\t\t\t\t\tif (settings[s].treeId && settings[s].edit.enable && settings[s].treeId != setting.treeId\n\t\t\t\t\t\t\t&& (event.target.id == settings[s].treeId || $(event.target).parents(\"#\" + settings[s].treeId).length>0)) {\n\t\t\t\t\t\t\tisOtherTree = true;\n\t\t\t\t\t\t\ttargetSetting = settings[s];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar docScrollTop = doc.scrollTop(),\n\t\t\t\t\tdocScrollLeft = doc.scrollLeft(),\n\t\t\t\t\ttreeOffset = targetSetting.treeObj.offset(),\n\t\t\t\t\tscrollHeight = targetSetting.treeObj.get(0).scrollHeight,\n\t\t\t\t\tscrollWidth = targetSetting.treeObj.get(0).scrollWidth,\n\t\t\t\t\tdTop = (event.clientY + docScrollTop - treeOffset.top),\n\t\t\t\t\tdBottom = (targetSetting.treeObj.height() + treeOffset.top - event.clientY - docScrollTop),\n\t\t\t\t\tdLeft = (event.clientX + docScrollLeft - treeOffset.left),\n\t\t\t\t\tdRight = (targetSetting.treeObj.width() + treeOffset.left - event.clientX - docScrollLeft),\n\t\t\t\t\tisTop = (dTop < setting.edit.drag.borderMax && dTop > setting.edit.drag.borderMin),\n\t\t\t\t\tisBottom = (dBottom < setting.edit.drag.borderMax && dBottom > setting.edit.drag.borderMin),\n\t\t\t\t\tisLeft = (dLeft < setting.edit.drag.borderMax && dLeft > setting.edit.drag.borderMin),\n\t\t\t\t\tisRight = (dRight < setting.edit.drag.borderMax && dRight > setting.edit.drag.borderMin),\n\t\t\t\t\tisTreeInner = dTop > setting.edit.drag.borderMin && dBottom > setting.edit.drag.borderMin && dLeft > setting.edit.drag.borderMin && dRight > setting.edit.drag.borderMin,\n\t\t\t\t\tisTreeTop = (isTop && targetSetting.treeObj.scrollTop() <= 0),\n\t\t\t\t\tisTreeBottom = (isBottom && (targetSetting.treeObj.scrollTop() + targetSetting.treeObj.height()+10) >= scrollHeight),\n\t\t\t\t\tisTreeLeft = (isLeft && targetSetting.treeObj.scrollLeft() <= 0),\n\t\t\t\t\tisTreeRight = (isRight && (targetSetting.treeObj.scrollLeft() + targetSetting.treeObj.width()+10) >= scrollWidth);\n\n\t\t\t\t\tif (event.target && tools.isChildOrSelf(event.target, targetSetting.treeId)) {\n\t\t\t\t\t\t//get node <li> dom\n\t\t\t\t\t\tvar targetObj = event.target;\n\t\t\t\t\t\twhile (targetObj && targetObj.tagName && !tools.eqs(targetObj.tagName, \"li\") && targetObj.id != targetSetting.treeId) {\n\t\t\t\t\t\t\ttargetObj = targetObj.parentNode;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar canMove = true;\n\t\t\t\t\t\t//don't move to self or children of self\n\t\t\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\t\t\tif (targetObj.id === tmpNode.tId) {\n\t\t\t\t\t\t\t\tcanMove = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} else if ($$(tmpNode, setting).find(\"#\" + targetObj.id).length > 0) {\n\t\t\t\t\t\t\t\tcanMove = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (canMove && event.target && tools.isChildOrSelf(event.target, targetObj.id + consts.id.A)) {\n\t\t\t\t\t\t\ttmpTarget = $(targetObj);\n\t\t\t\t\t\t\ttmpTargetNodeId = targetObj.id;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t//the mouse must be in zTree\n\t\t\t\t\ttmpNode = nodes[0];\n\t\t\t\t\tif (isTreeInner && tools.isChildOrSelf(event.target, targetSetting.treeId)) {\n\t\t\t\t\t\t//judge mouse move in root of ztree\n\t\t\t\t\t\tif (!tmpTarget && (event.target.id == targetSetting.treeId || isTreeTop || isTreeBottom || isTreeLeft || isTreeRight) && (isOtherTree || (!isOtherTree && tmpNode.parentTId))) {\n\t\t\t\t\t\t\ttmpTarget = targetSetting.treeObj;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//auto scroll top\n\t\t\t\t\t\tif (isTop) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop()-10);\n\t\t\t\t\t\t} else if (isBottom)  {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop()+10);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isLeft) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()-10);\n\t\t\t\t\t\t} else if (isRight) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()+10);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//auto scroll left\n\t\t\t\t\t\tif (tmpTarget && tmpTarget != targetSetting.treeObj && tmpTarget.offset().left < targetSetting.treeObj.offset().left) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()+ tmpTarget.offset().left - targetSetting.treeObj.offset().left);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcurNode.css({\n\t\t\t\t\t\t\"top\": (event.clientY + docScrollTop + 3) + \"px\",\n\t\t\t\t\t\t\"left\": (event.clientX + docScrollLeft + 3) + \"px\"\n\t\t\t\t\t});\n\n\t\t\t\t\tvar dX = 0;\n\t\t\t\t\tvar dY = 0;\n\t\t\t\t\tif (tmpTarget && tmpTarget.attr(\"id\")!=targetSetting.treeId) {\n\t\t\t\t\t\tvar tmpTargetNode = tmpTargetNodeId == null ? null: data.getNodeCache(targetSetting, tmpTargetNodeId),\n\t\t\t\t\t\tisCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy),\n\t\t\t\t\t\tisPrev = !!(preNode && tmpTargetNodeId === preNode.tId),\n\t\t\t\t\t\tisNext = !!(nextNode && tmpTargetNodeId === nextNode.tId),\n\t\t\t\t\t\tisInner = (tmpNode.parentTId && tmpNode.parentTId == tmpTargetNodeId),\n\t\t\t\t\t\tcanPrev = (isCopy || !isNext) && tools.apply(targetSetting.edit.drag.prev, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.prev),\n\t\t\t\t\t\tcanNext = (isCopy || !isPrev) && tools.apply(targetSetting.edit.drag.next, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.next),\n\t\t\t\t\t\tcanInner = (isCopy || !isInner) && !(targetSetting.data.keep.leaf && !tmpTargetNode.isParent) && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.inner);\n\t\t\t\t\t\tif (!canPrev && !canNext && !canInner) {\n\t\t\t\t\t\t\ttmpTarget = null;\n\t\t\t\t\t\t\ttmpTargetNodeId = \"\";\n\t\t\t\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t\t\t\t\ttmpArrow.css({\n\t\t\t\t\t\t\t\t\"display\":\"none\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (window.zTreeMoveTimer) {\n\t\t\t\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar tmpTargetA = $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget),\n\t\t\t\t\t\t\ttmpNextA = tmpTargetNode.isLastNode ? null : $(\"#\" + tmpTargetNode.getNextNode().tId + consts.id.A, tmpTarget.next()),\n\t\t\t\t\t\t\ttmpTop = tmpTargetA.offset().top,\n\t\t\t\t\t\t\ttmpLeft = tmpTargetA.offset().left,\n\t\t\t\t\t\t\tprevPercent = canPrev ? (canInner ? 0.25 : (canNext ? 0.5 : 1) ) : -1,\n\t\t\t\t\t\t\tnextPercent = canNext ? (canInner ? 0.75 : (canPrev ? 0.5 : 0) ) : -1,\n\t\t\t\t\t\t\tdY_percent = (event.clientY + docScrollTop - tmpTop)/tmpTargetA.height();\n\t\t\t\t\t\t\tif ((prevPercent==1 ||dY_percent<=prevPercent && dY_percent>=-.2) && canPrev) {\n\t\t\t\t\t\t\t\tdX = 1 - tmpArrow.width();\n\t\t\t\t\t\t\t\tdY = tmpTop - tmpArrow.height()/2;\n\t\t\t\t\t\t\t\tmoveType = consts.move.TYPE_PREV;\n\t\t\t\t\t\t\t} else if ((nextPercent==0 || dY_percent>=nextPercent && dY_percent<=1.2) && canNext) {\n\t\t\t\t\t\t\t\tdX = 1 - tmpArrow.width();\n\t\t\t\t\t\t\t\tdY = (tmpNextA == null || (tmpTargetNode.isParent && tmpTargetNode.open)) ? (tmpTop + tmpTargetA.height() - tmpArrow.height()/2) : (tmpNextA.offset().top - tmpArrow.height()/2);\n\t\t\t\t\t\t\t\tmoveType = consts.move.TYPE_NEXT;\n\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\tdX = 5 - tmpArrow.width();\n\t\t\t\t\t\t\t\tdY = tmpTop;\n\t\t\t\t\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttmpArrow.css({\n\t\t\t\t\t\t\t\t\"display\":\"block\",\n\t\t\t\t\t\t\t\t\"top\": dY + \"px\",\n\t\t\t\t\t\t\t\t\"left\": (tmpLeft + dX) + \"px\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttmpTargetA.addClass(consts.node.TMPTARGET_NODE + \"_\" + moveType);\n\n\t\t\t\t\t\t\tif (preTmpTargetNodeId != tmpTargetNodeId || preTmpMoveType != moveType) {\n\t\t\t\t\t\t\t\tstartTime = (new Date()).getTime();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (tmpTargetNode && tmpTargetNode.isParent && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\t\t\t\tvar startTimer = true;\n\t\t\t\t\t\t\t\tif (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId !== tmpTargetNode.tId) {\n\t\t\t\t\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null;\n\t\t\t\t\t\t\t\t}else if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId === tmpTargetNode.tId) {\n\t\t\t\t\t\t\t\t\tstartTimer = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (startTimer) {\n\t\t\t\t\t\t\t\t\twindow.zTreeMoveTimer = setTimeout(function() {\n\t\t\t\t\t\t\t\t\t\tif (moveType != consts.move.TYPE_INNER) return;\n\t\t\t\t\t\t\t\t\t\tif (tmpTargetNode && tmpTargetNode.isParent && !tmpTargetNode.open && (new Date()).getTime() - startTime > targetSetting.edit.drag.autoOpenTime\n\t\t\t\t\t\t\t\t\t\t\t&& tools.apply(targetSetting.callback.beforeDragOpen, [targetSetting.treeId, tmpTargetNode], true)) {\n\t\t\t\t\t\t\t\t\t\t\tview.switchNode(targetSetting, tmpTargetNode);\n\t\t\t\t\t\t\t\t\t\t\tif (targetSetting.edit.drag.autoExpandTrigger) {\n\t\t\t\t\t\t\t\t\t\t\t\ttargetSetting.treeObj.trigger(consts.event.EXPAND, [targetSetting.treeId, tmpTargetNode]);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}, targetSetting.edit.drag.autoOpenTime+50);\n\t\t\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = tmpTargetNode.tId;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t\t\t\tif (tmpTarget && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, null], !!targetSetting.edit.drag.inner)) {\n\t\t\t\t\t\t\ttmpTarget.addClass(consts.node.TMPTARGET_TREE);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttmpTarget = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttmpArrow.css({\n\t\t\t\t\t\t\t\"display\":\"none\"\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (window.zTreeMoveTimer) {\n\t\t\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpreTmpTargetNodeId = tmpTargetNodeId;\n\t\t\t\t\tpreTmpMoveType = moveType;\n\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.DRAGMOVE, [event, setting.treeId, nodes]);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tdoc.bind(\"mouseup\", _docMouseUp);\n\t\t\tfunction _docMouseUp(event) {\n\t\t\t\tif (window.zTreeMoveTimer) {\n\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null;\n\t\t\t\t}\n\t\t\t\tpreTmpTargetNodeId = null;\n\t\t\t\tpreTmpMoveType = null;\n\t\t\t\tdoc.unbind(\"mousemove\", _docMouseMove);\n\t\t\t\tdoc.unbind(\"mouseup\", _docMouseUp);\n\t\t\t\tdoc.unbind(\"selectstart\", _docSelect);\n\t\t\t\tbody.css(\"cursor\", \"auto\");\n\t\t\t\tif (tmpTarget) {\n\t\t\t\t\ttmpTarget.removeClass(consts.node.TMPTARGET_TREE);\n\t\t\t\t\tif (tmpTargetNodeId) $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + \"_\" + consts.move.TYPE_PREV)\n\t\t\t\t\t\t\t.removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_INNER);\n\t\t\t\t}\n\t\t\t\ttools.showIfameMask(setting, false);\n\n\t\t\t\troots.showHoverDom = true;\n\t\t\t\tif (root.dragFlag == 0) return;\n\t\t\t\troot.dragFlag = 0;\n\n\t\t\t\tvar i, l, tmpNode;\n\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\tif (tmpNode.isParent && root.dragNodeShowBefore[tmpNode.tId] && !tmpNode.open) {\n\t\t\t\t\t\tview.expandCollapseNode(setting, tmpNode, !tmpNode.open);\n\t\t\t\t\t\tdelete root.dragNodeShowBefore[tmpNode.tId];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (curNode) curNode.remove();\n\t\t\t\tif (tmpArrow) tmpArrow.remove();\n\n\t\t\t\tvar isCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy);\n\t\t\t\tif (!isCopy && tmpTarget && tmpTargetNodeId && nodes[0].parentTId && tmpTargetNodeId==nodes[0].parentTId && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\ttmpTarget = null;\n\t\t\t\t}\n\t\t\t\tif (tmpTarget) {\n\t\t\t\t\tvar dragTargetNode = tmpTargetNodeId == null ? null: data.getNodeCache(targetSetting, tmpTargetNodeId);\n\t\t\t\t\tif (tools.apply(setting.callback.beforeDrop, [targetSetting.treeId, nodes, dragTargetNode, moveType, isCopy], true) == false) {\n\t\t\t\t\t\tview.selectNodes(sourceSetting, nodes);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar newNodes = isCopy ? tools.clone(nodes) : nodes;\n\n\t\t\t\t\tfunction dropCallback() {\n\t\t\t\t\t\tif (isOtherTree) {\n\t\t\t\t\t\t\tif (!isCopy) {\n\t\t\t\t\t\t\t\tfor(var i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\t\t\t\tview.removeNode(setting, nodes[i]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode, newNodes);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode.getParentNode(), newNodes);\n\t\t\t\t\t\t\t\tif (moveType == consts.move.TYPE_PREV) {\n\t\t\t\t\t\t\t\t\tfor (i=0, l=newNodes.length; i<l; i++) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfor (i=-1, l=newNodes.length-1; i<l; l--) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (isCopy && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode, newNodes);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (isCopy) {\n\t\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode.getParentNode(), newNodes);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (moveType != consts.move.TYPE_NEXT) {\n\t\t\t\t\t\t\t\t\tfor (i=0, l=newNodes.length; i<l; i++) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfor (i=-1, l=newNodes.length-1; i<l; l--) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tview.selectNodes(targetSetting, newNodes);\n\t\t\t\t\t\t$$(newNodes[0], setting).focus().blur();\n\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.DROP, [event, targetSetting.treeId, newNodes, dragTargetNode, moveType, isCopy]);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (moveType == consts.move.TYPE_INNER && tools.canAsync(targetSetting, dragTargetNode)) {\n\t\t\t\t\t\tview.asyncNode(targetSetting, dragTargetNode, false, dropCallback);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdropCallback();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tview.selectNodes(sourceSetting, nodes);\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.DROP, [event, setting.treeId, nodes, null, null, null]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdoc.bind(\"selectstart\", _docSelect);\n\t\t\tfunction _docSelect() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t//Avoid FireFox's Bug\n\t\t\t//If zTree Div CSS set 'overflow', so drag node outside of zTree, and event.target is error.\n\t\t\tif(eventMouseDown.preventDefault) {\n\t\t\t\teventMouseDown.preventDefault();\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t},\n\t//method of tools for zTree\n\t_tools = {\n\t\tgetAbs: function (obj) {\n\t\t\tvar oRect = obj.getBoundingClientRect(),\n\t\t\tscrollTop = document.body.scrollTop+document.documentElement.scrollTop,\n\t\t\tscrollLeft = document.body.scrollLeft+document.documentElement.scrollLeft;\n\t\t\treturn [oRect.left+scrollLeft,oRect.top+scrollTop];\n\t\t},\n\t\tinputFocus: function(inputObj) {\n\t\t\tif (inputObj.get(0)) {\n\t\t\t\tinputObj.focus();\n\t\t\t\ttools.setCursorPosition(inputObj.get(0), inputObj.val().length);\n\t\t\t}\n\t\t},\n\t\tinputSelect: function(inputObj) {\n\t\t\tif (inputObj.get(0)) {\n\t\t\t\tinputObj.focus();\n\t\t\t\tinputObj.select();\n\t\t\t}\n\t\t},\n\t\tsetCursorPosition: function(obj, pos){\n\t\t\tif(obj.setSelectionRange) {\n\t\t\t\tobj.focus();\n\t\t\t\tobj.setSelectionRange(pos,pos);\n\t\t\t} else if (obj.createTextRange) {\n\t\t\t\tvar range = obj.createTextRange();\n\t\t\t\trange.collapse(true);\n\t\t\t\trange.moveEnd('character', pos);\n\t\t\t\trange.moveStart('character', pos);\n\t\t\t\trange.select();\n\t\t\t}\n\t\t},\n\t\tshowIfameMask: function(setting, showSign) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\t//clear full mask\n\t\t\twhile (root.dragMaskList.length > 0) {\n\t\t\t\troot.dragMaskList[0].remove();\n\t\t\t\troot.dragMaskList.shift();\n\t\t\t}\n\t\t\tif (showSign) {\n\t\t\t\t//show mask\n\t\t\t\tvar iframeList = $$(\"iframe\", setting);\n\t\t\t\tfor (var i = 0, l = iframeList.length; i < l; i++) {\n\t\t\t\t\tvar obj = iframeList.get(i),\n\t\t\t\t\tr = tools.getAbs(obj),\n\t\t\t\t\tdragMask = $$(\"<div id='zTreeMask_\" + i + \"' class='zTreeMask' style='top:\" + r[1] + \"px; left:\" + r[0] + \"px; width:\" + obj.offsetWidth + \"px; height:\" + obj.offsetHeight + \"px;'></div>\", setting);\n\t\t\t\t\tdragMask.appendTo($$(\"body\", setting));\n\t\t\t\t\troot.dragMaskList.push(dragMask);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t//method of operate ztree dom\n\t_view = {\n\t\taddEditBtn: function(setting, node) {\n\t\t\tif (node.editNameFlag || $$(node, consts.id.EDIT, setting).length > 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!tools.apply(setting.edit.showRenameBtn, [setting.treeId, node], setting.edit.showRenameBtn)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar aObj = $$(node, consts.id.A, setting),\n\t\t\teditStr = \"<span class='\" + consts.className.BUTTON + \" edit' id='\" + node.tId + consts.id.EDIT + \"' title='\"+tools.apply(setting.edit.renameTitle, [setting.treeId, node], setting.edit.renameTitle)+\"' treeNode\"+consts.id.EDIT+\" style='display:none;'></span>\";\n\t\t\taObj.append(editStr);\n\n\t\t\t$$(node, consts.id.EDIT, setting).bind('click',\n\t\t\t\tfunction() {\n\t\t\t\t\tif (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeEditName, [setting.treeId, node], true) == false) return false;\n\t\t\t\t\tview.editNode(setting, node);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t).show();\n\t\t},\n\t\taddRemoveBtn: function(setting, node) {\n\t\t\tif (node.editNameFlag || $$(node, consts.id.REMOVE, setting).length > 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!tools.apply(setting.edit.showRemoveBtn, [setting.treeId, node], setting.edit.showRemoveBtn)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar aObj = $$(node, consts.id.A, setting),\n\t\t\tremoveStr = \"<span class='\" + consts.className.BUTTON + \" remove' id='\" + node.tId + consts.id.REMOVE + \"' title='\"+tools.apply(setting.edit.removeTitle, [setting.treeId, node], setting.edit.removeTitle)+\"' treeNode\"+consts.id.REMOVE+\" style='display:none;'></span>\";\n\t\t\taObj.append(removeStr);\n\n\t\t\t$$(node, consts.id.REMOVE, setting).bind('click',\n\t\t\t\tfunction() {\n\t\t\t\t\tif (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return false;\n\t\t\t\t\tview.removeNode(setting, node);\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t).bind('mousedown',\n\t\t\t\tfunction(eventMouseDown) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t).show();\n\t\t},\n\t\taddHoverDom: function(setting, node) {\n\t\t\tif (data.getRoots().showHoverDom) {\n\t\t\t\tnode.isHover = true;\n\t\t\t\tif (setting.edit.enable) {\n\t\t\t\t\tview.addEditBtn(setting, node);\n\t\t\t\t\tview.addRemoveBtn(setting, node);\n\t\t\t\t}\n\t\t\t\ttools.apply(setting.view.addHoverDom, [setting.treeId, node]);\n\t\t\t}\n\t\t},\n\t\tcancelCurEditNode: function (setting, forceName, isCancel) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tnameKey = setting.data.key.name,\n\t\t\tnode = root.curEditNode;\n\n\t\t\tif (node) {\n\t\t\t\tvar inputObj = root.curEditInput,\n\t\t\t\tnewName = forceName ? forceName:(isCancel ? node[nameKey]: inputObj.val());\n\t\t\t\tif (tools.apply(setting.callback.beforeRename, [setting.treeId, node, newName, isCancel], true) === false) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n                node[nameKey] = newName;\n                var aObj = $$(node, consts.id.A, setting);\n\t\t\t\taObj.removeClass(consts.node.CURSELECTED_EDIT);\n\t\t\t\tinputObj.unbind();\n\t\t\t\tview.setNodeName(setting, node);\n\t\t\t\tnode.editNameFlag = false;\n\t\t\t\troot.curEditNode = null;\n\t\t\t\troot.curEditInput = null;\n\t\t\t\tview.selectNode(setting, node, false);\n                setting.treeObj.trigger(consts.event.RENAME, [setting.treeId, node, isCancel]);\n\t\t\t}\n\t\t\troot.noSelection = true;\n\t\t\treturn true;\n\t\t},\n\t\teditNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\tview.editNodeBlur = false;\n\t\t\tif (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {\n\t\t\t\tsetTimeout(function() {tools.inputFocus(root.curEditInput);}, 0);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar nameKey = setting.data.key.name;\n\t\t\tnode.editNameFlag = true;\n\t\t\tview.removeTreeDom(setting, node);\n\t\t\tview.cancelCurEditNode(setting);\n\t\t\tview.selectNode(setting, node, false);\n\t\t\t$$(node, consts.id.SPAN, setting).html(\"<input type=text class='rename' id='\" + node.tId + consts.id.INPUT + \"' treeNode\" + consts.id.INPUT + \" >\");\n\t\t\tvar inputObj = $$(node, consts.id.INPUT, setting);\n\t\t\tinputObj.attr(\"value\", node[nameKey]);\n\t\t\tif (setting.edit.editNameSelectAll) {\n\t\t\t\ttools.inputSelect(inputObj);\n\t\t\t} else {\n\t\t\t\ttools.inputFocus(inputObj);\n\t\t\t}\n\n\t\t\tinputObj.bind('blur', function(event) {\n\t\t\t\tif (!view.editNodeBlur) {\n\t\t\t\t\tview.cancelCurEditNode(setting);\n\t\t\t\t}\n\t\t\t}).bind('keydown', function(event) {\n\t\t\t\tif (event.keyCode==\"13\") {\n\t\t\t\t\tview.editNodeBlur = true;\n\t\t\t\t\tview.cancelCurEditNode(setting);\n\t\t\t\t} else if (event.keyCode==\"27\") {\n\t\t\t\t\tview.cancelCurEditNode(setting, null, true);\n\t\t\t\t}\n\t\t\t}).bind('click', function(event) {\n\t\t\t\treturn false;\n\t\t\t}).bind('dblclick', function(event) {\n\t\t\t\treturn false;\n\t\t\t});\n\n\t\t\t$$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED_EDIT);\n\t\t\troot.curEditInput = inputObj;\n\t\t\troot.noSelection = false;\n\t\t\troot.curEditNode = node;\n\t\t},\n\t\tmoveNode: function(setting, targetNode, node, moveType, animateFlag, isSilent) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tif (targetNode == node) return;\n\t\t\tif (setting.data.keep.leaf && targetNode && !targetNode.isParent && moveType == consts.move.TYPE_INNER) return;\n\t\t\tvar oldParentNode = (node.parentTId ? node.getParentNode(): root),\n\t\t\ttargetNodeIsRoot = (targetNode === null || targetNode == root);\n\t\t\tif (targetNodeIsRoot && targetNode === null) targetNode = root;\n\t\t\tif (targetNodeIsRoot) moveType = consts.move.TYPE_INNER;\n\t\t\tvar targetParentNode = (targetNode.parentTId ? targetNode.getParentNode() : root);\n\n\t\t\tif (moveType != consts.move.TYPE_PREV && moveType != consts.move.TYPE_NEXT) {\n\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t}\n\n\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\tif (targetNodeIsRoot) {\n\t\t\t\t\t//parentTId of root node is null\n\t\t\t\t\tnode.parentTId = null;\n\t\t\t\t} else {\n\t\t\t\t\tif (!targetNode.isParent) {\n\t\t\t\t\t\ttargetNode.isParent = true;\n\t\t\t\t\t\ttargetNode.open = !!targetNode.open;\n\t\t\t\t\t\tview.setNodeLineIcos(setting, targetNode);\n\t\t\t\t\t}\n\t\t\t\t\tnode.parentTId = targetNode.tId;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//move node Dom\n\t\t\tvar targetObj, target_ulObj;\n\t\t\tif (targetNodeIsRoot) {\n\t\t\t\ttargetObj = setting.treeObj;\n\t\t\t\ttarget_ulObj = targetObj;\n\t\t\t} else {\n\t\t\t\tif (!isSilent && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\tview.expandCollapseNode(setting, targetNode, true, false);\n\t\t\t\t} else if (!isSilent) {\n\t\t\t\t\tview.expandCollapseNode(setting, targetNode.getParentNode(), true, false);\n\t\t\t\t}\n\t\t\t\ttargetObj = $$(targetNode, setting);\n\t\t\t\ttarget_ulObj = $$(targetNode, consts.id.UL, setting);\n\t\t\t\tif (!!targetObj.get(0) && !target_ulObj.get(0)) {\n\t\t\t\t\tvar ulstr = [];\n\t\t\t\t\tview.makeUlHtml(setting, targetNode, ulstr, '');\n\t\t\t\t\ttargetObj.append(ulstr.join(''));\n\t\t\t\t}\n\t\t\t\ttarget_ulObj = $$(targetNode, consts.id.UL, setting);\n\t\t\t}\n\t\t\tvar nodeDom = $$(node, setting);\n\t\t\tif (!nodeDom.get(0)) {\n\t\t\t\tnodeDom = view.appendNodes(setting, node.level, [node], null, false, true).join('');\n\t\t\t} else if (!targetObj.get(0)) {\n\t\t\t\tnodeDom.remove();\n\t\t\t}\n\t\t\tif (target_ulObj.get(0) && moveType == consts.move.TYPE_INNER) {\n\t\t\t\ttarget_ulObj.append(nodeDom);\n\t\t\t} else if (targetObj.get(0) && moveType == consts.move.TYPE_PREV) {\n\t\t\t\ttargetObj.before(nodeDom);\n\t\t\t} else if (targetObj.get(0) && moveType == consts.move.TYPE_NEXT) {\n\t\t\t\ttargetObj.after(nodeDom);\n\t\t\t}\n\n\t\t\t//repair the data after move\n\t\t\tvar i,l,\n\t\t\ttmpSrcIndex = -1,\n\t\t\ttmpTargetIndex = 0,\n\t\t\toldNeighbor = null,\n\t\t\tnewNeighbor = null,\n\t\t\toldLevel = node.level;\n\t\t\tif (node.isFirstNode) {\n\t\t\t\ttmpSrcIndex = 0;\n\t\t\t\tif (oldParentNode[childKey].length > 1 ) {\n\t\t\t\t\toldNeighbor = oldParentNode[childKey][1];\n\t\t\t\t\toldNeighbor.isFirstNode = true;\n\t\t\t\t}\n\t\t\t} else if (node.isLastNode) {\n\t\t\t\ttmpSrcIndex = oldParentNode[childKey].length -1;\n\t\t\t\toldNeighbor = oldParentNode[childKey][tmpSrcIndex - 1];\n\t\t\t\toldNeighbor.isLastNode = true;\n\t\t\t} else {\n\t\t\t\tfor (i = 0, l = oldParentNode[childKey].length; i < l; i++) {\n\t\t\t\t\tif (oldParentNode[childKey][i].tId == node.tId) {\n\t\t\t\t\t\ttmpSrcIndex = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tmpSrcIndex >= 0) {\n\t\t\t\toldParentNode[childKey].splice(tmpSrcIndex, 1);\n\t\t\t}\n\t\t\tif (moveType != consts.move.TYPE_INNER) {\n\t\t\t\tfor (i = 0, l = targetParentNode[childKey].length; i < l; i++) {\n\t\t\t\t\tif (targetParentNode[childKey][i].tId == targetNode.tId) tmpTargetIndex = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\tif (!targetNode[childKey]) targetNode[childKey] = new Array();\n\t\t\t\tif (targetNode[childKey].length > 0) {\n\t\t\t\t\tnewNeighbor = targetNode[childKey][targetNode[childKey].length - 1];\n\t\t\t\t\tnewNeighbor.isLastNode = false;\n\t\t\t\t}\n\t\t\t\ttargetNode[childKey].splice(targetNode[childKey].length, 0, node);\n\t\t\t\tnode.isLastNode = true;\n\t\t\t\tnode.isFirstNode = (targetNode[childKey].length == 1);\n\t\t\t} else if (targetNode.isFirstNode && moveType == consts.move.TYPE_PREV) {\n\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex, 0, node);\n\t\t\t\tnewNeighbor = targetNode;\n\t\t\t\tnewNeighbor.isFirstNode = false;\n\t\t\t\tnode.parentTId = targetNode.parentTId;\n\t\t\t\tnode.isFirstNode = true;\n\t\t\t\tnode.isLastNode = false;\n\n\t\t\t} else if (targetNode.isLastNode && moveType == consts.move.TYPE_NEXT) {\n\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);\n\t\t\t\tnewNeighbor = targetNode;\n\t\t\t\tnewNeighbor.isLastNode = false;\n\t\t\t\tnode.parentTId = targetNode.parentTId;\n\t\t\t\tnode.isFirstNode = false;\n\t\t\t\tnode.isLastNode = true;\n\n\t\t\t} else {\n\t\t\t\tif (moveType == consts.move.TYPE_PREV) {\n\t\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex, 0, node);\n\t\t\t\t} else {\n\t\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);\n\t\t\t\t}\n\t\t\t\tnode.parentTId = targetNode.parentTId;\n\t\t\t\tnode.isFirstNode = false;\n\t\t\t\tnode.isLastNode = false;\n\t\t\t}\n\t\t\tdata.fixPIdKeyValue(setting, node);\n\t\t\tdata.setSonNodeLevel(setting, node.getParentNode(), node);\n\n\t\t\t//repair node what been moved\n\t\t\tview.setNodeLineIcos(setting, node);\n\t\t\tview.repairNodeLevelClass(setting, node, oldLevel)\n\n\t\t\t//repair node's old parentNode dom\n\t\t\tif (!setting.data.keep.parent && oldParentNode[childKey].length < 1) {\n\t\t\t\t//old parentNode has no child nodes\n\t\t\t\toldParentNode.isParent = false;\n\t\t\t\toldParentNode.open = false;\n\t\t\t\tvar tmp_ulObj = $$(oldParentNode, consts.id.UL, setting),\n\t\t\t\ttmp_switchObj = $$(oldParentNode, consts.id.SWITCH, setting),\n\t\t\t\ttmp_icoObj = $$(oldParentNode, consts.id.ICON, setting);\n\t\t\t\tview.replaceSwitchClass(oldParentNode, tmp_switchObj, consts.folder.DOCU);\n\t\t\t\tview.replaceIcoClass(oldParentNode, tmp_icoObj, consts.folder.DOCU);\n\t\t\t\ttmp_ulObj.css(\"display\", \"none\");\n\n\t\t\t} else if (oldNeighbor) {\n\t\t\t\t//old neigbor node\n\t\t\t\tview.setNodeLineIcos(setting, oldNeighbor);\n\t\t\t}\n\n\t\t\t//new neigbor node\n\t\t\tif (newNeighbor) {\n\t\t\t\tview.setNodeLineIcos(setting, newNeighbor);\n\t\t\t}\n\n\t\t\t//repair checkbox / radio\n\t\t\tif (!!setting.check && setting.check.enable && view.repairChkClass) {\n\t\t\t\tview.repairChkClass(setting, oldParentNode);\n\t\t\t\tview.repairParentChkClassWithSelf(setting, oldParentNode);\n\t\t\t\tif (oldParentNode != node.parent)\n\t\t\t\t\tview.repairParentChkClassWithSelf(setting, node);\n\t\t\t}\n\n\t\t\t//expand parents after move\n\t\t\tif (!isSilent) {\n\t\t\t\tview.expandCollapseParentNode(setting, node.getParentNode(), true, animateFlag);\n\t\t\t}\n\t\t},\n\t\tremoveEditBtn: function(setting, node) {\n\t\t\t$$(node, consts.id.EDIT, setting).unbind().remove();\n\t\t},\n\t\tremoveRemoveBtn: function(setting, node) {\n\t\t\t$$(node, consts.id.REMOVE, setting).unbind().remove();\n\t\t},\n\t\tremoveTreeDom: function(setting, node) {\n\t\t\tnode.isHover = false;\n\t\t\tview.removeEditBtn(setting, node);\n\t\t\tview.removeRemoveBtn(setting, node);\n\t\t\ttools.apply(setting.view.removeHoverDom, [setting.treeId, node]);\n\t\t},\n\t\trepairNodeLevelClass: function(setting, node, oldLevel) {\n\t\t\tif (oldLevel === node.level) return;\n\t\t\tvar liObj = $$(node, setting),\n\t\t\taObj = $$(node, consts.id.A, setting),\n\t\t\tulObj = $$(node, consts.id.UL, setting),\n\t\t\toldClass = consts.className.LEVEL + oldLevel,\n\t\t\tnewClass = consts.className.LEVEL + node.level;\n\t\t\tliObj.removeClass(oldClass);\n\t\t\tliObj.addClass(newClass);\n\t\t\taObj.removeClass(oldClass);\n\t\t\taObj.addClass(newClass);\n\t\t\tulObj.removeClass(oldClass);\n\t\t\tulObj.addClass(newClass);\n\t\t},\n\t\tselectNodes : function(setting, nodes) {\n\t\t\tfor (var i=0, l=nodes.length; i<l; i++) {\n\t\t\t\tview.selectNode(setting, nodes[i], i>0);\n\t\t\t}\n\t\t}\n\t},\n\n\t_z = {\n\t\ttools: _tools,\n\t\tview: _view,\n\t\tevent: _event,\n\t\tdata: _data\n\t};\n\t$.extend(true, $.fn.zTree.consts, _consts);\n\t$.extend(true, $.fn.zTree._z, _z);\n\n\tvar zt = $.fn.zTree,\n\ttools = zt._z.tools,\n\tconsts = zt.consts,\n\tview = zt._z.view,\n\tdata = zt._z.data,\n\tevent = zt._z.event,\n\t$$ = tools.$;\n\n\tdata.exSetting(_setting);\n\tdata.addInitBind(_bindEvent);\n\tdata.addInitUnBind(_unbindEvent);\n\tdata.addInitCache(_initCache);\n\tdata.addInitNode(_initNode);\n\tdata.addInitProxy(_eventProxy);\n\tdata.addInitRoot(_initRoot);\n\tdata.addZTreeTools(_zTreeTools);\n\n\tvar _cancelPreSelectedNode = view.cancelPreSelectedNode;\n\tview.cancelPreSelectedNode = function (setting, node) {\n\t\tvar list = data.getRoot(setting).curSelectedList;\n\t\tfor (var i=0, j=list.length; i<j; i++) {\n\t\t\tif (!node || node === list[i]) {\n\t\t\t\tview.removeTreeDom(setting, list[i]);\n\t\t\t\tif (node) break;\n\t\t\t}\n\t\t}\n\t\tif (_cancelPreSelectedNode) _cancelPreSelectedNode.apply(view, arguments);\n\t}\n\n\tvar _createNodes = view.createNodes;\n\tview.createNodes = function(setting, level, nodes, parentNode) {\n\t\tif (_createNodes) {\n\t\t\t_createNodes.apply(view, arguments);\n\t\t}\n\t\tif (!nodes) return;\n\t\tif (view.repairParentChkClassWithSelf) {\n\t\t\tview.repairParentChkClassWithSelf(setting, parentNode);\n\t\t}\n\t}\n\n\tvar _makeNodeUrl = view.makeNodeUrl;\n\tview.makeNodeUrl = function(setting, node) {\n\t\treturn setting.edit.enable ? null : (_makeNodeUrl.apply(view, arguments));\n\t}\n\n\tvar _removeNode = view.removeNode;\n\tview.removeNode = function(setting, node) {\n\t\tvar root = data.getRoot(setting);\n\t\tif (root.curEditNode === node) root.curEditNode = null;\n\t\tif (_removeNode) {\n\t\t\t_removeNode.apply(view, arguments);\n\t\t}\n\t}\n\n\tvar _selectNode = view.selectNode;\n\tview.selectNode = function(setting, node, addFlag) {\n\t\tvar root = data.getRoot(setting);\n\t\tif (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {\n\t\t\treturn false;\n\t\t}\n\t\tif (_selectNode) _selectNode.apply(view, arguments);\n\t\tview.addHoverDom(setting, node);\n\t\treturn true;\n\t}\n\n\tvar _uCanDo = tools.uCanDo;\n\ttools.uCanDo = function(setting, e) {\n\t\tvar root = data.getRoot(setting);\n\t\tif (e && (tools.eqs(e.type, \"mouseover\") || tools.eqs(e.type, \"mouseout\") || tools.eqs(e.type, \"mousedown\") || tools.eqs(e.type, \"mouseup\"))) {\n\t\t\treturn true;\n\t\t}\n\t\tif (root.curEditNode) {\n\t\t\tview.editNodeBlur = false;\n\t\t\troot.curEditInput.focus();\n\t\t}\n\t\treturn (!root.curEditNode) && (_uCanDo ? _uCanDo.apply(view, arguments) : true);\n\t}\n})(jQuery);\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/js/jquery.ztree.core-3.5.js",
    "content": "/*\n * JQuery zTree core v3.5.18\n * http://zTree.me/\n *\n * Copyright (c) 2010 Hunter.z\n *\n * Licensed same as jquery - MIT License\n * http://www.opensource.org/licenses/mit-license.php\n *\n * email: hunter.z@263.net\n * Date: 2015-05-25\n */\n(function($){\n\tvar settings = {}, roots = {}, caches = {},\n\t//default consts of core\n\t_consts = {\n\t\tclassName: {\n\t\t\tBUTTON: \"button\",\n\t\t\tLEVEL: \"level\",\n\t\t\tICO_LOADING: \"ico_loading\",\n\t\t\tSWITCH: \"switch\"\n\t\t},\n\t\tevent: {\n\t\t\tNODECREATED: \"ztree_nodeCreated\",\n\t\t\tCLICK: \"ztree_click\",\n\t\t\tEXPAND: \"ztree_expand\",\n\t\t\tCOLLAPSE: \"ztree_collapse\",\n\t\t\tASYNC_SUCCESS: \"ztree_async_success\",\n\t\t\tASYNC_ERROR: \"ztree_async_error\",\n\t\t\tREMOVE: \"ztree_remove\",\n\t\t\tSELECTED: \"ztree_selected\",\n\t\t\tUNSELECTED: \"ztree_unselected\"\n\t\t},\n\t\tid: {\n\t\t\tA: \"_a\",\n\t\t\tICON: \"_ico\",\n\t\t\tSPAN: \"_span\",\n\t\t\tSWITCH: \"_switch\",\n\t\t\tUL: \"_ul\"\n\t\t},\n\t\tline: {\n\t\t\tROOT: \"root\",\n\t\t\tROOTS: \"roots\",\n\t\t\tCENTER: \"center\",\n\t\t\tBOTTOM: \"bottom\",\n\t\t\tNOLINE: \"noline\",\n\t\t\tLINE: \"line\"\n\t\t},\n\t\tfolder: {\n\t\t\tOPEN: \"open\",\n\t\t\tCLOSE: \"close\",\n\t\t\tDOCU: \"docu\"\n\t\t},\n\t\tnode: {\n\t\t\tCURSELECTED: \"curSelectedNode\"\n\t\t}\n\t},\n\t//default setting of core\n\t_setting = {\n\t\ttreeId: \"\",\n\t\ttreeObj: null,\n\t\tview: {\n\t\t\taddDiyDom: null,\n\t\t\tautoCancelSelected: true,\n\t\t\tdblClickExpand: true,\n\t\t\texpandSpeed: \"fast\",\n\t\t\tfontCss: {},\n\t\t\tnameIsHTML: false,\n\t\t\tselectedMulti: true,\n\t\t\tshowIcon: true,\n\t\t\tshowLine: true,\n\t\t\tshowTitle: true,\n\t\t\ttxtSelectedEnable: false\n\t\t},\n\t\tdata: {\n\t\t\tkey: {\n\t\t\t\tchildren: \"children\",\n\t\t\t\tname: \"name\",\n\t\t\t\ttitle: \"\",\n\t\t\t\turl: \"url\"\n\t\t\t},\n\t\t\tsimpleData: {\n\t\t\t\tenable: false,\n\t\t\t\tidKey: \"id\",\n\t\t\t\tpIdKey: \"pId\",\n\t\t\t\trootPId: null\n\t\t\t},\n\t\t\tkeep: {\n\t\t\t\tparent: false,\n\t\t\t\tleaf: false\n\t\t\t}\n\t\t},\n\t\tasync: {\n\t\t\tenable: false,\n\t\t\tcontentType: \"application/x-www-form-urlencoded\",\n\t\t\ttype: \"post\",\n\t\t\tdataType: \"text\",\n\t\t\turl: \"\",\n\t\t\tautoParam: [],\n\t\t\totherParam: [],\n\t\t\tdataFilter: null\n\t\t},\n\t\tcallback: {\n\t\t\tbeforeAsync:null,\n\t\t\tbeforeClick:null,\n\t\t\tbeforeDblClick:null,\n\t\t\tbeforeRightClick:null,\n\t\t\tbeforeMouseDown:null,\n\t\t\tbeforeMouseUp:null,\n\t\t\tbeforeExpand:null,\n\t\t\tbeforeCollapse:null,\n\t\t\tbeforeRemove:null,\n\n\t\t\tonAsyncError:null,\n\t\t\tonAsyncSuccess:null,\n\t\t\tonNodeCreated:null,\n\t\t\tonClick:null,\n\t\t\tonDblClick:null,\n\t\t\tonRightClick:null,\n\t\t\tonMouseDown:null,\n\t\t\tonMouseUp:null,\n\t\t\tonExpand:null,\n\t\t\tonCollapse:null,\n\t\t\tonRemove:null\n\t\t}\n\t},\n\t//default root of core\n\t//zTree use root to save full data\n\t_initRoot = function (setting) {\n\t\tvar r = data.getRoot(setting);\n\t\tif (!r) {\n\t\t\tr = {};\n\t\t\tdata.setRoot(setting, r);\n\t\t}\n\t\tr[setting.data.key.children] = [];\n\t\tr.expandTriggerFlag = false;\n\t\tr.curSelectedList = [];\n\t\tr.noSelection = true;\n\t\tr.createdNodes = [];\n\t\tr.zId = 0;\n\t\tr._ver = (new Date()).getTime();\n\t},\n\t//default cache of core\n\t_initCache = function(setting) {\n\t\tvar c = data.getCache(setting);\n\t\tif (!c) {\n\t\t\tc = {};\n\t\t\tdata.setCache(setting, c);\n\t\t}\n\t\tc.nodes = [];\n\t\tc.doms = [];\n\t},\n\t//default bindEvent of core\n\t_bindEvent = function(setting) {\n\t\tvar o = setting.treeObj,\n\t\tc = consts.event;\n\t\to.bind(c.NODECREATED, function (event, treeId, node) {\n\t\t\ttools.apply(setting.callback.onNodeCreated, [event, treeId, node]);\n\t\t});\n\n\t\to.bind(c.CLICK, function (event, srcEvent, treeId, node, clickFlag) {\n\t\t\ttools.apply(setting.callback.onClick, [srcEvent, treeId, node, clickFlag]);\n\t\t});\n\n\t\to.bind(c.EXPAND, function (event, treeId, node) {\n\t\t\ttools.apply(setting.callback.onExpand, [event, treeId, node]);\n\t\t});\n\n\t\to.bind(c.COLLAPSE, function (event, treeId, node) {\n\t\t\ttools.apply(setting.callback.onCollapse, [event, treeId, node]);\n\t\t});\n\n\t\to.bind(c.ASYNC_SUCCESS, function (event, treeId, node, msg) {\n\t\t\ttools.apply(setting.callback.onAsyncSuccess, [event, treeId, node, msg]);\n\t\t});\n\n\t\to.bind(c.ASYNC_ERROR, function (event, treeId, node, XMLHttpRequest, textStatus, errorThrown) {\n\t\t\ttools.apply(setting.callback.onAsyncError, [event, treeId, node, XMLHttpRequest, textStatus, errorThrown]);\n\t\t});\n\n\t\to.bind(c.REMOVE, function (event, treeId, treeNode) {\n\t\t\ttools.apply(setting.callback.onRemove, [event, treeId, treeNode]);\n\t\t});\n\n\t\to.bind(c.SELECTED, function (event, srcEvent, treeId, node) {\n\t\t\ttools.apply(setting.callback.onSelected, [srcEvent, treeId, node]);\n\t\t});\n\t\to.bind(c.UNSELECTED, function (event, srcEvent, treeId, node) {\n\t\t\ttools.apply(setting.callback.onUnSelected, [srcEvent, treeId, node]);\n\t\t});\n\t},\n\t_unbindEvent = function(setting) {\n\t\tvar o = setting.treeObj,\n\t\tc = consts.event;\n\t\to.unbind(c.NODECREATED)\n\t\t.unbind(c.CLICK)\n\t\t.unbind(c.EXPAND)\n\t\t.unbind(c.COLLAPSE)\n\t\t.unbind(c.ASYNC_SUCCESS)\n\t\t.unbind(c.ASYNC_ERROR)\n\t\t.unbind(c.REMOVE)\n\t\t.unbind(c.SELECTED)\n\t\t.unbind(c.UNSELECTED);\n\t},\n\t//default event proxy of core\n\t_eventProxy = function(event) {\n\t\tvar target = event.target,\n\t\tsetting = data.getSetting(event.data.treeId),\n\t\ttId = \"\", node = null,\n\t\tnodeEventType = \"\", treeEventType = \"\",\n\t\tnodeEventCallback = null, treeEventCallback = null,\n\t\ttmp = null;\n\n\t\tif (tools.eqs(event.type, \"mousedown\")) {\n\t\t\ttreeEventType = \"mousedown\";\n\t\t} else if (tools.eqs(event.type, \"mouseup\")) {\n\t\t\ttreeEventType = \"mouseup\";\n\t\t} else if (tools.eqs(event.type, \"contextmenu\")) {\n\t\t\ttreeEventType = \"contextmenu\";\n\t\t} else if (tools.eqs(event.type, \"click\")) {\n\t\t\tif (tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\"+ consts.id.SWITCH) !== null) {\n\t\t\t\ttId = tools.getNodeMainDom(target).id;\n\t\t\t\tnodeEventType = \"switchNode\";\n\t\t\t} else {\n\t\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\t\tif (tmp) {\n\t\t\t\t\ttId = tools.getNodeMainDom(tmp).id;\n\t\t\t\t\tnodeEventType = \"clickNode\";\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (tools.eqs(event.type, \"dblclick\")) {\n\t\t\ttreeEventType = \"dblclick\";\n\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (tmp) {\n\t\t\t\ttId = tools.getNodeMainDom(tmp).id;\n\t\t\t\tnodeEventType = \"switchNode\";\n\t\t\t}\n\t\t}\n\t\tif (treeEventType.length > 0 && tId.length == 0) {\n\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (tmp) {tId = tools.getNodeMainDom(tmp).id;}\n\t\t}\n\t\t// event to node\n\t\tif (tId.length>0) {\n\t\t\tnode = data.getNodeCache(setting, tId);\n\t\t\tswitch (nodeEventType) {\n\t\t\t\tcase \"switchNode\" :\n\t\t\t\t\tif (!node.isParent) {\n\t\t\t\t\t\tnodeEventType = \"\";\n\t\t\t\t\t} else if (tools.eqs(event.type, \"click\")\n\t\t\t\t\t\t|| (tools.eqs(event.type, \"dblclick\") && tools.apply(setting.view.dblClickExpand, [setting.treeId, node], setting.view.dblClickExpand))) {\n\t\t\t\t\t\tnodeEventCallback = handler.onSwitchNode;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnodeEventType = \"\";\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"clickNode\" :\n\t\t\t\t\tnodeEventCallback = handler.onClickNode;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\t// event to zTree\n\t\tswitch (treeEventType) {\n\t\t\tcase \"mousedown\" :\n\t\t\t\ttreeEventCallback = handler.onZTreeMousedown;\n\t\t\t\tbreak;\n\t\t\tcase \"mouseup\" :\n\t\t\t\ttreeEventCallback = handler.onZTreeMouseup;\n\t\t\t\tbreak;\n\t\t\tcase \"dblclick\" :\n\t\t\t\ttreeEventCallback = handler.onZTreeDblclick;\n\t\t\t\tbreak;\n\t\t\tcase \"contextmenu\" :\n\t\t\t\ttreeEventCallback = handler.onZTreeContextmenu;\n\t\t\t\tbreak;\n\t\t}\n\t\tvar proxyResult = {\n\t\t\tstop: false,\n\t\t\tnode: node,\n\t\t\tnodeEventType: nodeEventType,\n\t\t\tnodeEventCallback: nodeEventCallback,\n\t\t\ttreeEventType: treeEventType,\n\t\t\ttreeEventCallback: treeEventCallback\n\t\t};\n\t\treturn proxyResult\n\t},\n\t//default init node of core\n\t_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n\t\tif (!n) return;\n\t\tvar r = data.getRoot(setting),\n\t\tchildKey = setting.data.key.children;\n\t\tn.level = level;\n\t\tn.tId = setting.treeId + \"_\" + (++r.zId);\n\t\tn.parentTId = parentNode ? parentNode.tId : null;\n\t\tn.open = (typeof n.open == \"string\") ? tools.eqs(n.open, \"true\") : !!n.open;\n\t\tif (n[childKey] && n[childKey].length > 0) {\n\t\t\tn.isParent = true;\n\t\t\tn.zAsync = true;\n\t\t} else {\n\t\t\tn.isParent = (typeof n.isParent == \"string\") ? tools.eqs(n.isParent, \"true\") : !!n.isParent;\n\t\t\tn.open = (n.isParent && !setting.async.enable) ? n.open : false;\n\t\t\tn.zAsync = !n.isParent;\n\t\t}\n\t\tn.isFirstNode = isFirstNode;\n\t\tn.isLastNode = isLastNode;\n\t\tn.getParentNode = function() {return data.getNodeCache(setting, n.parentTId);};\n\t\tn.getPreNode = function() {return data.getPreNode(setting, n);};\n\t\tn.getNextNode = function() {return data.getNextNode(setting, n);};\n\t\tn.isAjaxing = false;\n\t\tdata.fixPIdKeyValue(setting, n);\n\t},\n\t_init = {\n\t\tbind: [_bindEvent],\n\t\tunbind: [_unbindEvent],\n\t\tcaches: [_initCache],\n\t\tnodes: [_initNode],\n\t\tproxys: [_eventProxy],\n\t\troots: [_initRoot],\n\t\tbeforeA: [],\n\t\tafterA: [],\n\t\tinnerBeforeA: [],\n\t\tinnerAfterA: [],\n\t\tzTreeTools: []\n\t},\n\t//method of operate data\n\tdata = {\n\t\taddNodeCache: function(setting, node) {\n\t\t\tdata.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = node;\n\t\t},\n\t\tgetNodeCacheId: function(tId) {\n\t\t\treturn tId.substring(tId.lastIndexOf(\"_\")+1);\n\t\t},\n\t\taddAfterA: function(afterA) {\n\t\t\t_init.afterA.push(afterA);\n\t\t},\n\t\taddBeforeA: function(beforeA) {\n\t\t\t_init.beforeA.push(beforeA);\n\t\t},\n\t\taddInnerAfterA: function(innerAfterA) {\n\t\t\t_init.innerAfterA.push(innerAfterA);\n\t\t},\n\t\taddInnerBeforeA: function(innerBeforeA) {\n\t\t\t_init.innerBeforeA.push(innerBeforeA);\n\t\t},\n\t\taddInitBind: function(bindEvent) {\n\t\t\t_init.bind.push(bindEvent);\n\t\t},\n\t\taddInitUnBind: function(unbindEvent) {\n\t\t\t_init.unbind.push(unbindEvent);\n\t\t},\n\t\taddInitCache: function(initCache) {\n\t\t\t_init.caches.push(initCache);\n\t\t},\n\t\taddInitNode: function(initNode) {\n\t\t\t_init.nodes.push(initNode);\n\t\t},\n\t\taddInitProxy: function(initProxy, isFirst) {\n\t\t\tif (!!isFirst) {\n\t\t\t\t_init.proxys.splice(0,0,initProxy);\n\t\t\t} else {\n\t\t\t\t_init.proxys.push(initProxy);\n\t\t\t}\n\t\t},\n\t\taddInitRoot: function(initRoot) {\n\t\t\t_init.roots.push(initRoot);\n\t\t},\n\t\taddNodesData: function(setting, parentNode, nodes) {\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tif (!parentNode[childKey]) parentNode[childKey] = [];\n\t\t\tif (parentNode[childKey].length > 0) {\n\t\t\t\tparentNode[childKey][parentNode[childKey].length - 1].isLastNode = false;\n\t\t\t\tview.setNodeLineIcos(setting, parentNode[childKey][parentNode[childKey].length - 1]);\n\t\t\t}\n\t\t\tparentNode.isParent = true;\n\t\t\tparentNode[childKey] = parentNode[childKey].concat(nodes);\n\t\t},\n\t\taddSelectedNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\tif (!data.isSelectedNode(setting, node)) {\n\t\t\t\troot.curSelectedList.push(node);\n\t\t\t}\n\t\t},\n\t\taddCreatedNode: function(setting, node) {\n\t\t\tif (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {\n\t\t\t\tvar root = data.getRoot(setting);\n\t\t\t\troot.createdNodes.push(node);\n\t\t\t}\n\t\t},\n\t\taddZTreeTools: function(zTreeTools) {\n\t\t\t_init.zTreeTools.push(zTreeTools);\n\t\t},\n\t\texSetting: function(s) {\n\t\t\t$.extend(true, _setting, s);\n\t\t},\n\t\tfixPIdKeyValue: function(setting, node) {\n\t\t\tif (setting.data.simpleData.enable) {\n\t\t\t\tnode[setting.data.simpleData.pIdKey] = node.parentTId ? node.getParentNode()[setting.data.simpleData.idKey] : setting.data.simpleData.rootPId;\n\t\t\t}\n\t\t},\n\t\tgetAfterA: function(setting, node, array) {\n\t\t\tfor (var i=0, j=_init.afterA.length; i<j; i++) {\n\t\t\t\t_init.afterA[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tgetBeforeA: function(setting, node, array) {\n\t\t\tfor (var i=0, j=_init.beforeA.length; i<j; i++) {\n\t\t\t\t_init.beforeA[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tgetInnerAfterA: function(setting, node, array) {\n\t\t\tfor (var i=0, j=_init.innerAfterA.length; i<j; i++) {\n\t\t\t\t_init.innerAfterA[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tgetInnerBeforeA: function(setting, node, array) {\n\t\t\tfor (var i=0, j=_init.innerBeforeA.length; i<j; i++) {\n\t\t\t\t_init.innerBeforeA[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tgetCache: function(setting) {\n\t\t\treturn caches[setting.treeId];\n\t\t},\n\t\tgetNextNode: function(setting, node) {\n\t\t\tif (!node) return null;\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tp = node.parentTId ? node.getParentNode() : data.getRoot(setting);\n\t\t\tfor (var i=0, l=p[childKey].length-1; i<=l; i++) {\n\t\t\t\tif (p[childKey][i] === node) {\n\t\t\t\t\treturn (i==l ? null : p[childKey][i+1]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tgetNodeByParam: function(setting, nodes, key, value) {\n\t\t\tif (!nodes || !key) return null;\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (nodes[i][key] == value) {\n\t\t\t\t\treturn nodes[i];\n\t\t\t\t}\n\t\t\t\tvar tmp = data.getNodeByParam(setting, nodes[i][childKey], key, value);\n\t\t\t\tif (tmp) return tmp;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tgetNodeCache: function(setting, tId) {\n\t\t\tif (!tId) return null;\n\t\t\tvar n = caches[setting.treeId].nodes[data.getNodeCacheId(tId)];\n\t\t\treturn n ? n : null;\n\t\t},\n\t\tgetNodeName: function(setting, node) {\n\t\t\tvar nameKey = setting.data.key.name;\n\t\t\treturn \"\" + node[nameKey];\n\t\t},\n\t\tgetNodeTitle: function(setting, node) {\n\t\t\tvar t = setting.data.key.title === \"\" ? setting.data.key.name : setting.data.key.title;\n\t\t\treturn \"\" + node[t];\n\t\t},\n\t\tgetNodes: function(setting) {\n\t\t\treturn data.getRoot(setting)[setting.data.key.children];\n\t\t},\n\t\tgetNodesByParam: function(setting, nodes, key, value) {\n\t\t\tif (!nodes || !key) return [];\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tresult = [];\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (nodes[i][key] == value) {\n\t\t\t\t\tresult.push(nodes[i]);\n\t\t\t\t}\n\t\t\t\tresult = result.concat(data.getNodesByParam(setting, nodes[i][childKey], key, value));\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t\tgetNodesByParamFuzzy: function(setting, nodes, key, value) {\n\t\t\tif (!nodes || !key) return [];\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tresult = [];\n\t\t\tvalue = value.toLowerCase();\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (typeof nodes[i][key] == \"string\" && nodes[i][key].toLowerCase().indexOf(value)>-1) {\n\t\t\t\t\tresult.push(nodes[i]);\n\t\t\t\t}\n\t\t\t\tresult = result.concat(data.getNodesByParamFuzzy(setting, nodes[i][childKey], key, value));\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t\tgetNodesByFilter: function(setting, nodes, filter, isSingle, invokeParam) {\n\t\t\tif (!nodes) return (isSingle ? null : []);\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tresult = isSingle ? null : [];\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (tools.apply(filter, [nodes[i], invokeParam], false)) {\n\t\t\t\t\tif (isSingle) {return nodes[i];}\n\t\t\t\t\tresult.push(nodes[i]);\n\t\t\t\t}\n\t\t\t\tvar tmpResult = data.getNodesByFilter(setting, nodes[i][childKey], filter, isSingle, invokeParam);\n\t\t\t\tif (isSingle && !!tmpResult) {return tmpResult;}\n\t\t\t\tresult = isSingle ? tmpResult : result.concat(tmpResult);\n\t\t\t}\n\t\t\treturn result;\n\t\t},\n\t\tgetPreNode: function(setting, node) {\n\t\t\tif (!node) return null;\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tp = node.parentTId ? node.getParentNode() : data.getRoot(setting);\n\t\t\tfor (var i=0, l=p[childKey].length; i<l; i++) {\n\t\t\t\tif (p[childKey][i] === node) {\n\t\t\t\t\treturn (i==0 ? null : p[childKey][i-1]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tgetRoot: function(setting) {\n\t\t\treturn setting ? roots[setting.treeId] : null;\n\t\t},\n\t\tgetRoots: function() {\n\t\t\treturn roots;\n\t\t},\n\t\tgetSetting: function(treeId) {\n\t\t\treturn settings[treeId];\n\t\t},\n\t\tgetSettings: function() {\n\t\t\treturn settings;\n\t\t},\n\t\tgetZTreeTools: function(treeId) {\n\t\t\tvar r = this.getRoot(this.getSetting(treeId));\n\t\t\treturn r ? r.treeTools : null;\n\t\t},\n\t\tinitCache: function(setting) {\n\t\t\tfor (var i=0, j=_init.caches.length; i<j; i++) {\n\t\t\t\t_init.caches[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tinitNode: function(setting, level, node, parentNode, preNode, nextNode) {\n\t\t\tfor (var i=0, j=_init.nodes.length; i<j; i++) {\n\t\t\t\t_init.nodes[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tinitRoot: function(setting) {\n\t\t\tfor (var i=0, j=_init.roots.length; i<j; i++) {\n\t\t\t\t_init.roots[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tisSelectedNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\tfor (var i=0, j=root.curSelectedList.length; i<j; i++) {\n\t\t\t\tif(node === root.curSelectedList[i]) return true;\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t\tremoveNodeCache: function(setting, node) {\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tif (node[childKey]) {\n\t\t\t\tfor (var i=0, l=node[childKey].length; i<l; i++) {\n\t\t\t\t\targuments.callee(setting, node[childKey][i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdata.getCache(setting).nodes[data.getNodeCacheId(node.tId)] = null;\n\t\t},\n\t\tremoveSelectedNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\tfor (var i=0, j=root.curSelectedList.length; i<j; i++) {\n\t\t\t\tif(node === root.curSelectedList[i] || !data.getNodeCache(setting, root.curSelectedList[i].tId)) {\n\t\t\t\t\troot.curSelectedList.splice(i, 1);\n\t\t\t\t\ti--;j--;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsetCache: function(setting, cache) {\n\t\t\tcaches[setting.treeId] = cache;\n\t\t},\n\t\tsetRoot: function(setting, root) {\n\t\t\troots[setting.treeId] = root;\n\t\t},\n\t\tsetZTreeTools: function(setting, zTreeTools) {\n\t\t\tfor (var i=0, j=_init.zTreeTools.length; i<j; i++) {\n\t\t\t\t_init.zTreeTools[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\ttransformToArrayFormat: function (setting, nodes) {\n\t\t\tif (!nodes) return [];\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tr = [];\n\t\t\tif (tools.isArray(nodes)) {\n\t\t\t\tfor (var i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\tr.push(nodes[i]);\n\t\t\t\t\tif (nodes[i][childKey])\n\t\t\t\t\t\tr = r.concat(data.transformToArrayFormat(setting, nodes[i][childKey]));\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tr.push(nodes);\n\t\t\t\tif (nodes[childKey])\n\t\t\t\t\tr = r.concat(data.transformToArrayFormat(setting, nodes[childKey]));\n\t\t\t}\n\t\t\treturn r;\n\t\t},\n\t\ttransformTozTreeFormat: function(setting, sNodes) {\n\t\t\tvar i,l,\n\t\t\tkey = setting.data.simpleData.idKey,\n\t\t\tparentKey = setting.data.simpleData.pIdKey,\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tif (!key || key==\"\" || !sNodes) return [];\n\n\t\t\tif (tools.isArray(sNodes)) {\n\t\t\t\tvar r = [];\n\t\t\t\tvar tmpMap = [];\n\t\t\t\tfor (i=0, l=sNodes.length; i<l; i++) {\n\t\t\t\t\ttmpMap[sNodes[i][key]] = sNodes[i];\n\t\t\t\t}\n\t\t\t\tfor (i=0, l=sNodes.length; i<l; i++) {\n\t\t\t\t\tif (tmpMap[sNodes[i][parentKey]] && sNodes[i][key] != sNodes[i][parentKey]) {\n\t\t\t\t\t\tif (!tmpMap[sNodes[i][parentKey]][childKey])\n\t\t\t\t\t\t\ttmpMap[sNodes[i][parentKey]][childKey] = [];\n\t\t\t\t\t\ttmpMap[sNodes[i][parentKey]][childKey].push(sNodes[i]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tr.push(sNodes[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn r;\n\t\t\t}else {\n\t\t\t\treturn [sNodes];\n\t\t\t}\n\t\t}\n\t},\n\t//method of event proxy\n\tevent = {\n\t\tbindEvent: function(setting) {\n\t\t\tfor (var i=0, j=_init.bind.length; i<j; i++) {\n\t\t\t\t_init.bind[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tunbindEvent: function(setting) {\n\t\t\tfor (var i=0, j=_init.unbind.length; i<j; i++) {\n\t\t\t\t_init.unbind[i].apply(this, arguments);\n\t\t\t}\n\t\t},\n\t\tbindTree: function(setting) {\n\t\t\tvar eventParam = {\n\t\t\t\ttreeId: setting.treeId\n\t\t\t},\n\t\t\to = setting.treeObj;\n\t\t\tif (!setting.view.txtSelectedEnable) {\n\t\t\t\t// for can't select text\n\t\t\t\to.bind('selectstart', function(e){\n\t\t\t\t\tvar node\n\t\t\t\t\tvar n = e.originalEvent.srcElement.nodeName.toLowerCase();\n\t\t\t\t\treturn (n === \"input\" || n === \"textarea\" );\n\t\t\t\t}).css({\n\t\t\t\t\t\"-moz-user-select\":\"-moz-none\"\n\t\t\t\t});\n\t\t\t}\n\t\t\to.bind('click', eventParam, event.proxy);\n\t\t\to.bind('dblclick', eventParam, event.proxy);\n\t\t\to.bind('mouseover', eventParam, event.proxy);\n\t\t\to.bind('mouseout', eventParam, event.proxy);\n\t\t\to.bind('mousedown', eventParam, event.proxy);\n\t\t\to.bind('mouseup', eventParam, event.proxy);\n\t\t\to.bind('contextmenu', eventParam, event.proxy);\n\t\t},\n\t\tunbindTree: function(setting) {\n\t\t\tvar o = setting.treeObj;\n\t\t\to.unbind('click', event.proxy)\n\t\t\t.unbind('dblclick', event.proxy)\n\t\t\t.unbind('mouseover', event.proxy)\n\t\t\t.unbind('mouseout', event.proxy)\n\t\t\t.unbind('mousedown', event.proxy)\n\t\t\t.unbind('mouseup', event.proxy)\n\t\t\t.unbind('contextmenu', event.proxy);\n\t\t},\n\t\tdoProxy: function(e) {\n\t\t\tvar results = [];\n\t\t\tfor (var i=0, j=_init.proxys.length; i<j; i++) {\n\t\t\t\tvar proxyResult = _init.proxys[i].apply(this, arguments);\n\t\t\t\tresults.push(proxyResult);\n\t\t\t\tif (proxyResult.stop) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn results;\n\t\t},\n\t\tproxy: function(e) {\n\t\t\tvar setting = data.getSetting(e.data.treeId);\n\t\t\tif (!tools.uCanDo(setting, e)) return true;\n\t\t\tvar results = event.doProxy(e),\n\t\t\tr = true, x = false;\n\t\t\tfor (var i=0, l=results.length; i<l; i++) {\n\t\t\t\tvar proxyResult = results[i];\n\t\t\t\tif (proxyResult.nodeEventCallback) {\n\t\t\t\t\tx = true;\n\t\t\t\t\tr = proxyResult.nodeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;\n\t\t\t\t}\n\t\t\t\tif (proxyResult.treeEventCallback) {\n\t\t\t\t\tx = true;\n\t\t\t\t\tr = proxyResult.treeEventCallback.apply(proxyResult, [e, proxyResult.node]) && r;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn r;\n\t\t}\n\t},\n\t//method of event handler\n\thandler = {\n\t\tonSwitchNode: function (event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId);\n\t\t\tif (node.open) {\n\t\t\t\tif (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false) return true;\n\t\t\t\tdata.getRoot(setting).expandTriggerFlag = true;\n\t\t\t\tview.switchNode(setting, node);\n\t\t\t} else {\n\t\t\t\tif (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false) return true;\n\t\t\t\tdata.getRoot(setting).expandTriggerFlag = true;\n\t\t\t\tview.switchNode(setting, node);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\tonClickNode: function (event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\tclickFlag = ( (setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey)) && data.isSelectedNode(setting, node)) ? 0 : (setting.view.autoCancelSelected && (event.ctrlKey || event.metaKey) && setting.view.selectedMulti) ? 2 : 1;\n\t\t\tif (tools.apply(setting.callback.beforeClick, [setting.treeId, node, clickFlag], true) == false) return true;\n\t\t\tif (clickFlag === 0) {\n\t\t\t\tview.cancelPreSelectedNode(setting, node);\n\t\t\t} else {\n\t\t\t\tview.selectNode(setting, node, clickFlag === 2);\n\t\t\t}\n\t\t\tsetting.treeObj.trigger(consts.event.CLICK, [event, setting.treeId, node, clickFlag]);\n\t\t\treturn true;\n\t\t},\n\t\tonZTreeMousedown: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId);\n\t\t\tif (tools.apply(setting.callback.beforeMouseDown, [setting.treeId, node], true)) {\n\t\t\t\ttools.apply(setting.callback.onMouseDown, [event, setting.treeId, node]);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\tonZTreeMouseup: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId);\n\t\t\tif (tools.apply(setting.callback.beforeMouseUp, [setting.treeId, node], true)) {\n\t\t\t\ttools.apply(setting.callback.onMouseUp, [event, setting.treeId, node]);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\tonZTreeDblclick: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId);\n\t\t\tif (tools.apply(setting.callback.beforeDblClick, [setting.treeId, node], true)) {\n\t\t\t\ttools.apply(setting.callback.onDblClick, [event, setting.treeId, node]);\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\t\tonZTreeContextmenu: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId);\n\t\t\tif (tools.apply(setting.callback.beforeRightClick, [setting.treeId, node], true)) {\n\t\t\t\ttools.apply(setting.callback.onRightClick, [event, setting.treeId, node]);\n\t\t\t}\n\t\t\treturn (typeof setting.callback.onRightClick) != \"function\";\n\t\t}\n\t},\n\t//method of tools for zTree\n\ttools = {\n\t\tapply: function(fun, param, defaultValue) {\n\t\t\tif ((typeof fun) == \"function\") {\n\t\t\t\treturn fun.apply(zt, param?param:[]);\n\t\t\t}\n\t\t\treturn defaultValue;\n\t\t},\n\t\tcanAsync: function(setting, node) {\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\treturn (setting.async.enable && node && node.isParent && !(node.zAsync || (node[childKey] && node[childKey].length > 0)));\n\t\t},\n\t\tclone: function (obj){\n\t\t\tif (obj === null) return null;\n\t\t\tvar o = tools.isArray(obj) ? [] : {};\n\t\t\tfor(var i in obj){\n\t\t\t\to[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === \"object\" ? arguments.callee(obj[i]) : obj[i]);\n\t\t\t}\n\t\t\treturn o;\n\t\t},\n\t\teqs: function(str1, str2) {\n\t\t\treturn str1.toLowerCase() === str2.toLowerCase();\n\t\t},\n\t\tisArray: function(arr) {\n\t\t\treturn Object.prototype.toString.apply(arr) === \"[object Array]\";\n\t\t},\n\t\t$: function(node, exp, setting) {\n\t\t\tif (!!exp && typeof exp != \"string\") {\n\t\t\t\tsetting = exp;\n\t\t\t\texp = \"\";\n\t\t\t}\n\t\t\tif (typeof node == \"string\") {\n\t\t\t\treturn $(node, setting ? setting.treeObj.get(0).ownerDocument : null);\n\t\t\t} else {\n\t\t\t\treturn $(\"#\" + node.tId + exp, setting ? setting.treeObj : null);\n\t\t\t}\n\t\t},\n\t\tgetMDom: function (setting, curDom, targetExpr) {\n\t\t\tif (!curDom) return null;\n\t\t\twhile (curDom && curDom.id !== setting.treeId) {\n\t\t\t\tfor (var i=0, l=targetExpr.length; curDom.tagName && i<l; i++) {\n\t\t\t\t\tif (tools.eqs(curDom.tagName, targetExpr[i].tagName) && curDom.getAttribute(targetExpr[i].attrName) !== null) {\n\t\t\t\t\t\treturn curDom;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcurDom = curDom.parentNode;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tgetNodeMainDom:function(target) {\n\t\t\treturn ($(target).parent(\"li\").get(0) || $(target).parentsUntil(\"li\").parent().get(0));\n\t\t},\n\t\tisChildOrSelf: function(dom, parentId) {\n\t\t\treturn ( $(dom).closest(\"#\" + parentId).length> 0 );\n\t\t},\n\t\tuCanDo: function(setting, e) {\n\t\t\treturn true;\n\t\t}\n\t},\n\t//method of operate ztree dom\n\tview = {\n\t\taddNodes: function(setting, parentNode, newNodes, isSilent) {\n\t\t\tif (setting.data.keep.leaf && parentNode && !parentNode.isParent) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!tools.isArray(newNodes)) {\n\t\t\t\tnewNodes = [newNodes];\n\t\t\t}\n\t\t\tif (setting.data.simpleData.enable) {\n\t\t\t\tnewNodes = data.transformTozTreeFormat(setting, newNodes);\n\t\t\t}\n\t\t\tif (parentNode) {\n\t\t\t\tvar target_switchObj = $$(parentNode, consts.id.SWITCH, setting),\n\t\t\t\ttarget_icoObj = $$(parentNode, consts.id.ICON, setting),\n\t\t\t\ttarget_ulObj = $$(parentNode, consts.id.UL, setting);\n\n\t\t\t\tif (!parentNode.open) {\n\t\t\t\t\tview.replaceSwitchClass(parentNode, target_switchObj, consts.folder.CLOSE);\n\t\t\t\t\tview.replaceIcoClass(parentNode, target_icoObj, consts.folder.CLOSE);\n\t\t\t\t\tparentNode.open = false;\n\t\t\t\t\ttarget_ulObj.css({\n\t\t\t\t\t\t\"display\": \"none\"\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tdata.addNodesData(setting, parentNode, newNodes);\n\t\t\t\tview.createNodes(setting, parentNode.level + 1, newNodes, parentNode);\n\t\t\t\tif (!isSilent) {\n\t\t\t\t\tview.expandCollapseParentNode(setting, parentNode, true);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdata.addNodesData(setting, data.getRoot(setting), newNodes);\n\t\t\t\tview.createNodes(setting, 0, newNodes, null);\n\t\t\t}\n\t\t},\n\t\tappendNodes: function(setting, level, nodes, parentNode, initFlag, openFlag) {\n\t\t\tif (!nodes) return [];\n\t\t\tvar html = [],\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tvar node = nodes[i];\n\t\t\t\tif (initFlag) {\n\t\t\t\t\tvar tmpPNode = (parentNode) ? parentNode: data.getRoot(setting),\n\t\t\t\t\ttmpPChild = tmpPNode[childKey],\n\t\t\t\t\tisFirstNode = ((tmpPChild.length == nodes.length) && (i == 0)),\n\t\t\t\t\tisLastNode = (i == (nodes.length - 1));\n\t\t\t\t\tdata.initNode(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag);\n\t\t\t\t\tdata.addNodeCache(setting, node);\n\t\t\t\t}\n\n\t\t\t\tvar childHtml = [];\n\t\t\t\tif (node[childKey] && node[childKey].length > 0) {\n\t\t\t\t\t//make child html first, because checkType\n\t\t\t\t\tchildHtml = view.appendNodes(setting, level + 1, node[childKey], node, initFlag, openFlag && node.open);\n\t\t\t\t}\n\t\t\t\tif (openFlag) {\n\n\t\t\t\t\tview.makeDOMNodeMainBefore(html, setting, node);\n\t\t\t\t\tview.makeDOMNodeLine(html, setting, node);\n\t\t\t\t\tdata.getBeforeA(setting, node, html);\n\t\t\t\t\tview.makeDOMNodeNameBefore(html, setting, node);\n\t\t\t\t\tdata.getInnerBeforeA(setting, node, html);\n\t\t\t\t\tview.makeDOMNodeIcon(html, setting, node);\n\t\t\t\t\tdata.getInnerAfterA(setting, node, html);\n\t\t\t\t\tview.makeDOMNodeNameAfter(html, setting, node);\n\t\t\t\t\tdata.getAfterA(setting, node, html);\n\t\t\t\t\tif (node.isParent && node.open) {\n\t\t\t\t\t\tview.makeUlHtml(setting, node, html, childHtml.join(''));\n\t\t\t\t\t}\n\t\t\t\t\tview.makeDOMNodeMainAfter(html, setting, node);\n\t\t\t\t\tdata.addCreatedNode(setting, node);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn html;\n\t\t},\n\t\tappendParentULDom: function(setting, node) {\n\t\t\tvar html = [],\n\t\t\tnObj = $$(node, setting);\n\t\t\tif (!nObj.get(0) && !!node.parentTId) {\n\t\t\t\tview.appendParentULDom(setting, node.getParentNode());\n\t\t\t\tnObj = $$(node, setting);\n\t\t\t}\n\t\t\tvar ulObj = $$(node, consts.id.UL, setting);\n\t\t\tif (ulObj.get(0)) {\n\t\t\t\tulObj.remove();\n\t\t\t}\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tchildHtml = view.appendNodes(setting, node.level+1, node[childKey], node, false, true);\n\t\t\tview.makeUlHtml(setting, node, html, childHtml.join(''));\n\t\t\tnObj.append(html.join(''));\n\t\t},\n\t\tasyncNode: function(setting, node, isSilent, callback) {\n\t\t\tvar i, l;\n\t\t\tif (node && !node.isParent) {\n\t\t\t\ttools.apply(callback);\n\t\t\t\treturn false;\n\t\t\t} else if (node && node.isAjaxing) {\n\t\t\t\treturn false;\n\t\t\t} else if (tools.apply(setting.callback.beforeAsync, [setting.treeId, node], true) == false) {\n\t\t\t\ttools.apply(callback);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (node) {\n\t\t\t\tnode.isAjaxing = true;\n\t\t\t\tvar icoObj = $$(node, consts.id.ICON, setting);\n\t\t\t\ticoObj.attr({\"style\":\"\", \"class\":consts.className.BUTTON + \" \" + consts.className.ICO_LOADING});\n\t\t\t}\n\n\t\t\tvar tmpParam = {};\n\t\t\tfor (i = 0, l = setting.async.autoParam.length; node && i < l; i++) {\n\t\t\t\tvar pKey = setting.async.autoParam[i].split(\"=\"), spKey = pKey;\n\t\t\t\tif (pKey.length>1) {\n\t\t\t\t\tspKey = pKey[1];\n\t\t\t\t\tpKey = pKey[0];\n\t\t\t\t}\n\t\t\t\ttmpParam[spKey] = node[pKey];\n\t\t\t}\n\t\t\tif (tools.isArray(setting.async.otherParam)) {\n\t\t\t\tfor (i = 0, l = setting.async.otherParam.length; i < l; i += 2) {\n\t\t\t\t\ttmpParam[setting.async.otherParam[i]] = setting.async.otherParam[i + 1];\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor (var p in setting.async.otherParam) {\n\t\t\t\t\ttmpParam[p] = setting.async.otherParam[p];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar _tmpV = data.getRoot(setting)._ver;\n\t\t\t$.ajax({\n\t\t\t\tcontentType: setting.async.contentType,\n                cache: false,\n\t\t\t\ttype: setting.async.type,\n\t\t\t\turl: tools.apply(setting.async.url, [setting.treeId, node], setting.async.url),\n\t\t\t\tdata: tmpParam,\n\t\t\t\tdataType: setting.async.dataType,\n\t\t\t\tsuccess: function(msg) {\n\t\t\t\t\tif (_tmpV != data.getRoot(setting)._ver) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar newNodes = [];\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif (!msg || msg.length == 0) {\n\t\t\t\t\t\t\tnewNodes = [];\n\t\t\t\t\t\t} else if (typeof msg == \"string\") {\n\t\t\t\t\t\t\tnewNodes = eval(\"(\" + msg + \")\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tnewNodes = msg;\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\tnewNodes = msg;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (node) {\n\t\t\t\t\t\tnode.isAjaxing = null;\n\t\t\t\t\t\tnode.zAsync = true;\n\t\t\t\t\t}\n\t\t\t\t\tview.setNodeLineIcos(setting, node);\n\t\t\t\t\tif (newNodes && newNodes !== \"\") {\n\t\t\t\t\t\tnewNodes = tools.apply(setting.async.dataFilter, [setting.treeId, node, newNodes], newNodes);\n\t\t\t\t\t\tview.addNodes(setting, node, !!newNodes ? tools.clone(newNodes) : [], !!isSilent);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tview.addNodes(setting, node, [], !!isSilent);\n\t\t\t\t\t}\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.ASYNC_SUCCESS, [setting.treeId, node, msg]);\n\t\t\t\t\ttools.apply(callback);\n\t\t\t\t},\n\t\t\t\terror: function(XMLHttpRequest, textStatus, errorThrown) {\n\t\t\t\t\tif (_tmpV != data.getRoot(setting)._ver) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (node) node.isAjaxing = null;\n\t\t\t\t\tview.setNodeLineIcos(setting, node);\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.ASYNC_ERROR, [setting.treeId, node, XMLHttpRequest, textStatus, errorThrown]);\n\t\t\t\t}\n\t\t\t});\n\t\t\treturn true;\n\t\t},\n\t\tcancelPreSelectedNode: function (setting, node, excludeNode) {\n\t\t\tvar list = data.getRoot(setting).curSelectedList,\n\t\t\t\ti, n;\n\t\t\tfor (i=list.length-1; i>=0; i--) {\n\t\t\t\tn = list[i];\n\t\t\t\tif (node === n || (!node && (!excludeNode || excludeNode !== n))) {\n\t\t\t\t\t$$(n, consts.id.A, setting).removeClass(consts.node.CURSELECTED);\n\t\t\t\t\tif (node) {\n\t\t\t\t\t\tdata.removeSelectedNode(setting, node);\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.UNSELECTED, [event, setting.treeId, n]);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlist.splice(i, 1);\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.UNSELECTED, [event, setting.treeId, n]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcreateNodeCallback: function(setting) {\n\t\t\tif (!!setting.callback.onNodeCreated || !!setting.view.addDiyDom) {\n\t\t\t\tvar root = data.getRoot(setting);\n\t\t\t\twhile (root.createdNodes.length>0) {\n\t\t\t\t\tvar node = root.createdNodes.shift();\n\t\t\t\t\ttools.apply(setting.view.addDiyDom, [setting.treeId, node]);\n\t\t\t\t\tif (!!setting.callback.onNodeCreated) {\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.NODECREATED, [setting.treeId, node]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tcreateNodes: function(setting, level, nodes, parentNode) {\n\t\t\tif (!nodes || nodes.length == 0) return;\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children,\n\t\t\topenFlag = !parentNode || parentNode.open || !!$$(parentNode[childKey][0], setting).get(0);\n\t\t\troot.createdNodes = [];\n\t\t\tvar zTreeHtml = view.appendNodes(setting, level, nodes, parentNode, true, openFlag);\n\t\t\tif (!parentNode) {\n\t\t\t\tsetting.treeObj.append(zTreeHtml.join(''));\n\t\t\t} else {\n\t\t\t\tvar ulObj = $$(parentNode, consts.id.UL, setting);\n\t\t\t\tif (ulObj.get(0)) {\n\t\t\t\t\tulObj.append(zTreeHtml.join(''));\n\t\t\t\t}\n\t\t\t}\n\t\t\tview.createNodeCallback(setting);\n\t\t},\n\t\tdestroy: function(setting) {\n\t\t\tif (!setting) return;\n\t\t\tdata.initCache(setting);\n\t\t\tdata.initRoot(setting);\n\t\t\tevent.unbindTree(setting);\n\t\t\tevent.unbindEvent(setting);\n\t\t\tsetting.treeObj.empty();\n\t\t\tdelete settings[setting.treeId];\n\t\t},\n\t\texpandCollapseNode: function(setting, node, expandFlag, animateFlag, callback) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tif (!node) {\n\t\t\t\ttools.apply(callback, []);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (root.expandTriggerFlag) {\n\t\t\t\tvar _callback = callback;\n\t\t\t\tcallback = function(){\n\t\t\t\t\tif (_callback) _callback();\n\t\t\t\t\tif (node.open) {\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.EXPAND, [setting.treeId, node]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.COLLAPSE, [setting.treeId, node]);\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\troot.expandTriggerFlag = false;\n\t\t\t}\n\t\t\tif (!node.open && node.isParent && ((!$$(node, consts.id.UL, setting).get(0)) || (node[childKey] && node[childKey].length>0 && !$$(node[childKey][0], setting).get(0)))) {\n\t\t\t\tview.appendParentULDom(setting, node);\n\t\t\t\tview.createNodeCallback(setting);\n\t\t\t}\n\t\t\tif (node.open == expandFlag) {\n\t\t\t\ttools.apply(callback, []);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar ulObj = $$(node, consts.id.UL, setting),\n\t\t\tswitchObj = $$(node, consts.id.SWITCH, setting),\n\t\t\ticoObj = $$(node, consts.id.ICON, setting);\n\n\t\t\tif (node.isParent) {\n\t\t\t\tnode.open = !node.open;\n\t\t\t\tif (node.iconOpen && node.iconClose) {\n\t\t\t\t\ticoObj.attr(\"style\", view.makeNodeIcoStyle(setting, node));\n\t\t\t\t}\n\n\t\t\t\tif (node.open) {\n\t\t\t\t\tview.replaceSwitchClass(node, switchObj, consts.folder.OPEN);\n\t\t\t\t\tview.replaceIcoClass(node, icoObj, consts.folder.OPEN);\n\t\t\t\t\tif (animateFlag == false || setting.view.expandSpeed == \"\") {\n\t\t\t\t\t\tulObj.show();\n\t\t\t\t\t\ttools.apply(callback, []);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (node[childKey] && node[childKey].length > 0) {\n\t\t\t\t\t\t\tulObj.slideDown(setting.view.expandSpeed, callback);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tulObj.show();\n\t\t\t\t\t\t\ttools.apply(callback, []);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tview.replaceSwitchClass(node, switchObj, consts.folder.CLOSE);\n\t\t\t\t\tview.replaceIcoClass(node, icoObj, consts.folder.CLOSE);\n\t\t\t\t\tif (animateFlag == false || setting.view.expandSpeed == \"\" || !(node[childKey] && node[childKey].length > 0)) {\n\t\t\t\t\t\tulObj.hide();\n\t\t\t\t\t\ttools.apply(callback, []);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tulObj.slideUp(setting.view.expandSpeed, callback);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttools.apply(callback, []);\n\t\t\t}\n\t\t},\n\t\texpandCollapseParentNode: function(setting, node, expandFlag, animateFlag, callback) {\n\t\t\tif (!node) return;\n\t\t\tif (!node.parentTId) {\n\t\t\t\tview.expandCollapseNode(setting, node, expandFlag, animateFlag, callback);\n\t\t\t\treturn;\n\t\t\t} else {\n\t\t\t\tview.expandCollapseNode(setting, node, expandFlag, animateFlag);\n\t\t\t}\n\t\t\tif (node.parentTId) {\n\t\t\t\tview.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, animateFlag, callback);\n\t\t\t}\n\t\t},\n\t\texpandCollapseSonNode: function(setting, node, expandFlag, animateFlag, callback) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children,\n\t\t\ttreeNodes = (node) ? node[childKey]: root[childKey],\n\t\t\tselfAnimateSign = (node) ? false : animateFlag,\n\t\t\texpandTriggerFlag = data.getRoot(setting).expandTriggerFlag;\n\t\t\tdata.getRoot(setting).expandTriggerFlag = false;\n\t\t\tif (treeNodes) {\n\t\t\t\tfor (var i = 0, l = treeNodes.length; i < l; i++) {\n\t\t\t\t\tif (treeNodes[i]) view.expandCollapseSonNode(setting, treeNodes[i], expandFlag, selfAnimateSign);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdata.getRoot(setting).expandTriggerFlag = expandTriggerFlag;\n\t\t\tview.expandCollapseNode(setting, node, expandFlag, animateFlag, callback );\n\t\t},\n\t\tisSelectedNode: function (setting, node) {\n\t\t\tif (!node) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar list = data.getRoot(setting).curSelectedList,\n\t\t\t\ti;\n\t\t\tfor (i=list.length-1; i>=0; i--) {\n\t\t\t\tif (node === list[i]) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t},\n\t\tmakeDOMNodeIcon: function(html, setting, node) {\n\t\t\tvar nameStr = data.getNodeName(setting, node),\n\t\t\tname = setting.view.nameIsHTML ? nameStr : nameStr.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');\n\t\t\thtml.push(\"<span id='\", node.tId, consts.id.ICON,\n\t\t\t\t\"' title='' treeNode\", consts.id.ICON,\" class='\", view.makeNodeIcoClass(setting, node),\n\t\t\t\t\"' style='\", view.makeNodeIcoStyle(setting, node), \"'></span><span id='\", node.tId, consts.id.SPAN,\n\t\t\t\t\"'>\",name,\"</span>\");\n\t\t},\n\t\tmakeDOMNodeLine: function(html, setting, node) {\n\t\t\thtml.push(\"<span id='\", node.tId, consts.id.SWITCH,\t\"' title='' class='\", view.makeNodeLineClass(setting, node), \"' treeNode\", consts.id.SWITCH,\"></span>\");\n\t\t},\n\t\tmakeDOMNodeMainAfter: function(html, setting, node) {\n\t\t\thtml.push(\"</li>\");\n\t\t},\n\t\tmakeDOMNodeMainBefore: function(html, setting, node) {\n\t\t\thtml.push(\"<li id='\", node.tId, \"' class='\", consts.className.LEVEL, node.level,\"' tabindex='0' hidefocus='true' treenode>\");\n\t\t},\n\t\tmakeDOMNodeNameAfter: function(html, setting, node) {\n\t\t\thtml.push(\"</a>\");\n\t\t},\n\t\tmakeDOMNodeNameBefore: function(html, setting, node) {\n\t\t\tvar title = data.getNodeTitle(setting, node),\n\t\t\turl = view.makeNodeUrl(setting, node),\n\t\t\tfontcss = view.makeNodeFontCss(setting, node),\n\t\t\tfontStyle = [];\n\t\t\tfor (var f in fontcss) {\n\t\t\t\tfontStyle.push(f, \":\", fontcss[f], \";\");\n\t\t\t}\n\t\t\thtml.push(\"<a id='\", node.tId, consts.id.A, \"' class='\", consts.className.LEVEL, node.level,\"' treeNode\", consts.id.A,\" onclick=\\\"\", (node.click || ''),\n\t\t\t\t\"\\\" \", ((url != null && url.length > 0) ? \"href='\" + url + \"'\" : \"\"), \" target='\",view.makeNodeTarget(node),\"' style='\", fontStyle.join(''),\n\t\t\t\t\"'\");\n\t\t\tif (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle) && title) {html.push(\"title='\", title.replace(/'/g,\"&#39;\").replace(/</g,'&lt;').replace(/>/g,'&gt;'),\"'\");}\n\t\t\thtml.push(\">\");\n\t\t},\n\t\tmakeNodeFontCss: function(setting, node) {\n\t\t\tvar fontCss = tools.apply(setting.view.fontCss, [setting.treeId, node], setting.view.fontCss);\n\t\t\treturn (fontCss && ((typeof fontCss) != \"function\")) ? fontCss : {};\n\t\t},\n\t\tmakeNodeIcoClass: function(setting, node) {\n\t\t\tvar icoCss = [\"ico\"];\n\t\t\tif (!node.isAjaxing) {\n\t\t\t\ticoCss[0] = (node.iconSkin ? node.iconSkin + \"_\" : \"\") + icoCss[0];\n\t\t\t\tif (node.isParent) {\n\t\t\t\t\ticoCss.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);\n\t\t\t\t} else {\n\t\t\t\t\ticoCss.push(consts.folder.DOCU);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn consts.className.BUTTON + \" \" + icoCss.join('_');\n\t\t},\n\t\tmakeNodeIcoStyle: function(setting, node) {\n\t\t\tvar icoStyle = [];\n\t\t\tif (!node.isAjaxing) {\n\t\t\t\tvar icon = (node.isParent && node.iconOpen && node.iconClose) ? (node.open ? node.iconOpen : node.iconClose) : node.icon;\n\t\t\t\tif (icon) icoStyle.push(\"background:url(\", icon, \") 0 0 no-repeat;\");\n\t\t\t\tif (setting.view.showIcon == false || !tools.apply(setting.view.showIcon, [setting.treeId, node], true)) {\n\t\t\t\t\ticoStyle.push(\"width:0px;height:0px;\");\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn icoStyle.join('');\n\t\t},\n\t\tmakeNodeLineClass: function(setting, node) {\n\t\t\tvar lineClass = [];\n\t\t\tif (setting.view.showLine) {\n\t\t\t\tif (node.level == 0 && node.isFirstNode && node.isLastNode) {\n\t\t\t\t\tlineClass.push(consts.line.ROOT);\n\t\t\t\t} else if (node.level == 0 && node.isFirstNode) {\n\t\t\t\t\tlineClass.push(consts.line.ROOTS);\n\t\t\t\t} else if (node.isLastNode) {\n\t\t\t\t\tlineClass.push(consts.line.BOTTOM);\n\t\t\t\t} else {\n\t\t\t\t\tlineClass.push(consts.line.CENTER);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlineClass.push(consts.line.NOLINE);\n\t\t\t}\n\t\t\tif (node.isParent) {\n\t\t\t\tlineClass.push(node.open ? consts.folder.OPEN : consts.folder.CLOSE);\n\t\t\t} else {\n\t\t\t\tlineClass.push(consts.folder.DOCU);\n\t\t\t}\n\t\t\treturn view.makeNodeLineClassEx(node) + lineClass.join('_');\n\t\t},\n\t\tmakeNodeLineClassEx: function(node) {\n\t\t\treturn consts.className.BUTTON + \" \" + consts.className.LEVEL + node.level + \" \" + consts.className.SWITCH + \" \";\n\t\t},\n\t\tmakeNodeTarget: function(node) {\n\t\t\treturn (node.target || \"_blank\");\n\t\t},\n\t\tmakeNodeUrl: function(setting, node) {\n\t\t\tvar urlKey = setting.data.key.url;\n\t\t\treturn node[urlKey] ? node[urlKey] : null;\n\t\t},\n\t\tmakeUlHtml: function(setting, node, html, content) {\n\t\t\thtml.push(\"<ul id='\", node.tId, consts.id.UL, \"' class='\", consts.className.LEVEL, node.level, \" \", view.makeUlLineClass(setting, node), \"' style='display:\", (node.open ? \"block\": \"none\"),\"'>\");\n\t\t\thtml.push(content);\n\t\t\thtml.push(\"</ul>\");\n\t\t},\n\t\tmakeUlLineClass: function(setting, node) {\n\t\t\treturn ((setting.view.showLine && !node.isLastNode) ? consts.line.LINE : \"\");\n\t\t},\n\t\tremoveChildNodes: function(setting, node) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tnodes = node[childKey];\n\t\t\tif (!nodes) return;\n\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tdata.removeNodeCache(setting, nodes[i]);\n\t\t\t}\n\t\t\tdata.removeSelectedNode(setting);\n\t\t\tdelete node[childKey];\n\n\t\t\tif (!setting.data.keep.parent) {\n\t\t\t\tnode.isParent = false;\n\t\t\t\tnode.open = false;\n\t\t\t\tvar tmp_switchObj = $$(node, consts.id.SWITCH, setting),\n\t\t\t\ttmp_icoObj = $$(node, consts.id.ICON, setting);\n\t\t\t\tview.replaceSwitchClass(node, tmp_switchObj, consts.folder.DOCU);\n\t\t\t\tview.replaceIcoClass(node, tmp_icoObj, consts.folder.DOCU);\n\t\t\t\t$$(node, consts.id.UL, setting).remove();\n\t\t\t} else {\n\t\t\t\t$$(node, consts.id.UL, setting).empty();\n\t\t\t}\n\t\t},\n\t\tsetFirstNode: function(setting, parentNode) {\n\t\t\tvar childKey = setting.data.key.children, childLength = parentNode[childKey].length;\n\t\t\tif ( childLength > 0) {\n\t\t\t\tparentNode[childKey][0].isFirstNode = true;\n\t\t\t}\n\t\t},\n\t\tsetLastNode: function(setting, parentNode) {\n\t\t\tvar childKey = setting.data.key.children, childLength = parentNode[childKey].length;\n\t\t\tif ( childLength > 0) {\n\t\t\t\tparentNode[childKey][childLength - 1].isLastNode = true;\n\t\t\t}\n\t\t},\n\t\tremoveNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children,\n\t\t\tparentNode = (node.parentTId) ? node.getParentNode() : root;\n\n\t\t\tnode.isFirstNode = false;\n\t\t\tnode.isLastNode = false;\n\t\t\tnode.getPreNode = function() {return null;};\n\t\t\tnode.getNextNode = function() {return null;};\n\n\t\t\tif (!data.getNodeCache(setting, node.tId)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$$(node, setting).remove();\n\t\t\tdata.removeNodeCache(setting, node);\n\t\t\tdata.removeSelectedNode(setting, node);\n\n\t\t\tfor (var i = 0, l = parentNode[childKey].length; i < l; i++) {\n\t\t\t\tif (parentNode[childKey][i].tId == node.tId) {\n\t\t\t\t\tparentNode[childKey].splice(i, 1);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tview.setFirstNode(setting, parentNode);\n\t\t\tview.setLastNode(setting, parentNode);\n\n\t\t\tvar tmp_ulObj,tmp_switchObj,tmp_icoObj,\n\t\t\tchildLength = parentNode[childKey].length;\n\n\t\t\t//repair nodes old parent\n\t\t\tif (!setting.data.keep.parent && childLength == 0) {\n\t\t\t\t//old parentNode has no child nodes\n\t\t\t\tparentNode.isParent = false;\n\t\t\t\tparentNode.open = false;\n\t\t\t\ttmp_ulObj = $$(parentNode, consts.id.UL, setting);\n\t\t\t\ttmp_switchObj = $$(parentNode, consts.id.SWITCH, setting);\n\t\t\t\ttmp_icoObj = $$(parentNode, consts.id.ICON, setting);\n\t\t\t\tview.replaceSwitchClass(parentNode, tmp_switchObj, consts.folder.DOCU);\n\t\t\t\tview.replaceIcoClass(parentNode, tmp_icoObj, consts.folder.DOCU);\n\t\t\t\ttmp_ulObj.css(\"display\", \"none\");\n\n\t\t\t} else if (setting.view.showLine && childLength > 0) {\n\t\t\t\t//old parentNode has child nodes\n\t\t\t\tvar newLast = parentNode[childKey][childLength - 1];\n\t\t\t\ttmp_ulObj = $$(newLast, consts.id.UL, setting);\n\t\t\t\ttmp_switchObj = $$(newLast, consts.id.SWITCH, setting);\n\t\t\t\ttmp_icoObj = $$(newLast, consts.id.ICON, setting);\n\t\t\t\tif (parentNode == root) {\n\t\t\t\t\tif (parentNode[childKey].length == 1) {\n\t\t\t\t\t\t//node was root, and ztree has only one root after move node\n\t\t\t\t\t\tview.replaceSwitchClass(newLast, tmp_switchObj, consts.line.ROOT);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar tmp_first_switchObj = $$(parentNode[childKey][0], consts.id.SWITCH, setting);\n\t\t\t\t\t\tview.replaceSwitchClass(parentNode[childKey][0], tmp_first_switchObj, consts.line.ROOTS);\n\t\t\t\t\t\tview.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tview.replaceSwitchClass(newLast, tmp_switchObj, consts.line.BOTTOM);\n\t\t\t\t}\n\t\t\t\ttmp_ulObj.removeClass(consts.line.LINE);\n\t\t\t}\n\t\t},\n\t\treplaceIcoClass: function(node, obj, newName) {\n\t\t\tif (!obj || node.isAjaxing) return;\n\t\t\tvar tmpName = obj.attr(\"class\");\n\t\t\tif (tmpName == undefined) return;\n\t\t\tvar tmpList = tmpName.split(\"_\");\n\t\t\tswitch (newName) {\n\t\t\t\tcase consts.folder.OPEN:\n\t\t\t\tcase consts.folder.CLOSE:\n\t\t\t\tcase consts.folder.DOCU:\n\t\t\t\t\ttmpList[tmpList.length-1] = newName;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tobj.attr(\"class\", tmpList.join(\"_\"));\n\t\t},\n\t\treplaceSwitchClass: function(node, obj, newName) {\n\t\t\tif (!obj) return;\n\t\t\tvar tmpName = obj.attr(\"class\");\n\t\t\tif (tmpName == undefined) return;\n\t\t\tvar tmpList = tmpName.split(\"_\");\n\t\t\tswitch (newName) {\n\t\t\t\tcase consts.line.ROOT:\n\t\t\t\tcase consts.line.ROOTS:\n\t\t\t\tcase consts.line.CENTER:\n\t\t\t\tcase consts.line.BOTTOM:\n\t\t\t\tcase consts.line.NOLINE:\n\t\t\t\t\ttmpList[0] = view.makeNodeLineClassEx(node) + newName;\n\t\t\t\t\tbreak;\n\t\t\t\tcase consts.folder.OPEN:\n\t\t\t\tcase consts.folder.CLOSE:\n\t\t\t\tcase consts.folder.DOCU:\n\t\t\t\t\ttmpList[1] = newName;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tobj.attr(\"class\", tmpList.join(\"_\"));\n\t\t\tif (newName !== consts.folder.DOCU) {\n\t\t\t\tobj.removeAttr(\"disabled\");\n\t\t\t} else {\n\t\t\t\tobj.attr(\"disabled\", \"disabled\");\n\t\t\t}\n\t\t},\n\t\tselectNode: function(setting, node, addFlag) {\n\t\t\tif (!addFlag) {\n\t\t\t\tview.cancelPreSelectedNode(setting, null, node);\n\t\t\t}\n\t\t\t$$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED);\n\t\t\tdata.addSelectedNode(setting, node);\n\t\t\tsetting.treeObj.trigger(consts.event.SELECTED, [event, setting.treeId, node]);\n\t\t},\n\t\tsetNodeFontCss: function(setting, treeNode) {\n\t\t\tvar aObj = $$(treeNode, consts.id.A, setting),\n\t\t\tfontCss = view.makeNodeFontCss(setting, treeNode);\n\t\t\tif (fontCss) {\n\t\t\t\taObj.css(fontCss);\n\t\t\t}\n\t\t},\n\t\tsetNodeLineIcos: function(setting, node) {\n\t\t\tif (!node) return;\n\t\t\tvar switchObj = $$(node, consts.id.SWITCH, setting),\n\t\t\tulObj = $$(node, consts.id.UL, setting),\n\t\t\ticoObj = $$(node, consts.id.ICON, setting),\n\t\t\tulLine = view.makeUlLineClass(setting, node);\n\t\t\tif (ulLine.length==0) {\n\t\t\t\tulObj.removeClass(consts.line.LINE);\n\t\t\t} else {\n\t\t\t\tulObj.addClass(ulLine);\n\t\t\t}\n\t\t\tswitchObj.attr(\"class\", view.makeNodeLineClass(setting, node));\n\t\t\tif (node.isParent) {\n\t\t\t\tswitchObj.removeAttr(\"disabled\");\n\t\t\t} else {\n\t\t\t\tswitchObj.attr(\"disabled\", \"disabled\");\n\t\t\t}\n\t\t\ticoObj.removeAttr(\"style\");\n\t\t\ticoObj.attr(\"style\", view.makeNodeIcoStyle(setting, node));\n\t\t\ticoObj.attr(\"class\", view.makeNodeIcoClass(setting, node));\n\t\t},\n\t\tsetNodeName: function(setting, node) {\n\t\t\tvar title = data.getNodeTitle(setting, node),\n\t\t\tnObj = $$(node, consts.id.SPAN, setting);\n\t\t\tnObj.empty();\n\t\t\tif (setting.view.nameIsHTML) {\n\t\t\t\tnObj.html(data.getNodeName(setting, node));\n\t\t\t} else {\n\t\t\t\tnObj.text(data.getNodeName(setting, node));\n\t\t\t}\n\t\t\tif (tools.apply(setting.view.showTitle, [setting.treeId, node], setting.view.showTitle)) {\n\t\t\t\tvar aObj = $$(node, consts.id.A, setting);\n\t\t\t\taObj.attr(\"title\", !title ? \"\" : title);\n\t\t\t}\n\t\t},\n\t\tsetNodeTarget: function(setting, node) {\n\t\t\tvar aObj = $$(node, consts.id.A, setting);\n\t\t\taObj.attr(\"target\", view.makeNodeTarget(node));\n\t\t},\n\t\tsetNodeUrl: function(setting, node) {\n\t\t\tvar aObj = $$(node, consts.id.A, setting),\n\t\t\turl = view.makeNodeUrl(setting, node);\n\t\t\tif (url == null || url.length == 0) {\n\t\t\t\taObj.removeAttr(\"href\");\n\t\t\t} else {\n\t\t\t\taObj.attr(\"href\", url);\n\t\t\t}\n\t\t},\n\t\tswitchNode: function(setting, node) {\n\t\t\tif (node.open || !tools.canAsync(setting, node)) {\n\t\t\t\tview.expandCollapseNode(setting, node, !node.open);\n\t\t\t} else if (setting.async.enable) {\n\t\t\t\tif (!view.asyncNode(setting, node)) {\n\t\t\t\t\tview.expandCollapseNode(setting, node, !node.open);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} else if (node) {\n\t\t\t\tview.expandCollapseNode(setting, node, !node.open);\n\t\t\t}\n\t\t}\n\t};\n\t// zTree defind\n\t$.fn.zTree = {\n\t\tconsts : _consts,\n\t\t_z : {\n\t\t\ttools: tools,\n\t\t\tview: view,\n\t\t\tevent: event,\n\t\t\tdata: data\n\t\t},\n\t\tgetZTreeObj: function(treeId) {\n\t\t\tvar o = data.getZTreeTools(treeId);\n\t\t\treturn o ? o : null;\n\t\t},\n\t\tdestroy: function(treeId) {\n\t\t\tif (!!treeId && treeId.length > 0) {\n\t\t\t\tview.destroy(data.getSetting(treeId));\n\t\t\t} else {\n\t\t\t\tfor(var s in settings) {\n\t\t\t\t\tview.destroy(settings[s]);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tinit: function(obj, zSetting, zNodes) {\n\t\t\tvar setting = tools.clone(_setting);\n\t\t\t$.extend(true, setting, zSetting);\n\t\t\tsetting.treeId = obj.attr(\"id\");\n\t\t\tsetting.treeObj = obj;\n\t\t\tsetting.treeObj.empty();\n\t\t\tsettings[setting.treeId] = setting;\n\t\t\t//For some older browser,(e.g., ie6)\n\t\t\tif(typeof document.body.style.maxHeight === \"undefined\") {\n\t\t\t\tsetting.view.expandSpeed = \"\";\n\t\t\t}\n\t\t\tdata.initRoot(setting);\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tzNodes = zNodes ? tools.clone(tools.isArray(zNodes)? zNodes : [zNodes]) : [];\n\t\t\tif (setting.data.simpleData.enable) {\n\t\t\t\troot[childKey] = data.transformTozTreeFormat(setting, zNodes);\n\t\t\t} else {\n\t\t\t\troot[childKey] = zNodes;\n\t\t\t}\n\n\t\t\tdata.initCache(setting);\n\t\t\tevent.unbindTree(setting);\n\t\t\tevent.bindTree(setting);\n\t\t\tevent.unbindEvent(setting);\n\t\t\tevent.bindEvent(setting);\n\n\t\t\tvar zTreeTools = {\n\t\t\t\tsetting : setting,\n\t\t\t\taddNodes : function(parentNode, newNodes, isSilent) {\n\t\t\t\t\tif (!newNodes) return null;\n\t\t\t\t\tif (!parentNode) parentNode = null;\n\t\t\t\t\tif (parentNode && !parentNode.isParent && setting.data.keep.leaf) return null;\n\t\t\t\t\tvar xNewNodes = tools.clone(tools.isArray(newNodes)? newNodes: [newNodes]);\n\t\t\t\t\tfunction addCallback() {\n\t\t\t\t\t\tview.addNodes(setting, parentNode, xNewNodes, (isSilent==true));\n\t\t\t\t\t}\n\n\t\t\t\t\tif (tools.canAsync(setting, parentNode)) {\n\t\t\t\t\t\tview.asyncNode(setting, parentNode, isSilent, addCallback);\n\t\t\t\t\t} else {\n\t\t\t\t\t\taddCallback();\n\t\t\t\t\t}\n\t\t\t\t\treturn xNewNodes;\n\t\t\t\t},\n\t\t\t\tcancelSelectedNode : function(node) {\n\t\t\t\t\tview.cancelPreSelectedNode(setting, node);\n\t\t\t\t},\n\t\t\t\tdestroy : function() {\n\t\t\t\t\tview.destroy(setting);\n\t\t\t\t},\n\t\t\t\texpandAll : function(expandFlag) {\n\t\t\t\t\texpandFlag = !!expandFlag;\n\t\t\t\t\tview.expandCollapseSonNode(setting, null, expandFlag, true);\n\t\t\t\t\treturn expandFlag;\n\t\t\t\t},\n\t\t\t\texpandNode : function(node, expandFlag, sonSign, focus, callbackFlag) {\n\t\t\t\t\tif (!node || !node.isParent) return null;\n\t\t\t\t\tif (expandFlag !== true && expandFlag !== false) {\n\t\t\t\t\t\texpandFlag = !node.open;\n\t\t\t\t\t}\n\t\t\t\t\tcallbackFlag = !!callbackFlag;\n\n\t\t\t\t\tif (callbackFlag && expandFlag && (tools.apply(setting.callback.beforeExpand, [setting.treeId, node], true) == false)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t} else if (callbackFlag && !expandFlag && (tools.apply(setting.callback.beforeCollapse, [setting.treeId, node], true) == false)) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\t\t\t\t\tif (expandFlag && node.parentTId) {\n\t\t\t\t\t\tview.expandCollapseParentNode(setting, node.getParentNode(), expandFlag, false);\n\t\t\t\t\t}\n\t\t\t\t\tif (expandFlag === node.open && !sonSign) {\n\t\t\t\t\t\treturn null;\n\t\t\t\t\t}\n\n\t\t\t\t\tdata.getRoot(setting).expandTriggerFlag = callbackFlag;\n\t\t\t\t\tif (!tools.canAsync(setting, node) && sonSign) {\n\t\t\t\t\t\tview.expandCollapseSonNode(setting, node, expandFlag, true, function() {\n\t\t\t\t\t\t\tif (focus !== false) {try{$$(node, setting).focus().blur();}catch(e){}}\n\t\t\t\t\t\t});\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnode.open = !expandFlag;\n\t\t\t\t\t\tview.switchNode(this.setting, node);\n\t\t\t\t\t\tif (focus !== false) {try{$$(node, setting).focus().blur();}catch(e){}}\n\t\t\t\t\t}\n\t\t\t\t\treturn expandFlag;\n\t\t\t\t},\n\t\t\t\tgetNodes : function() {\n\t\t\t\t\treturn data.getNodes(setting);\n\t\t\t\t},\n\t\t\t\tgetNodeByParam : function(key, value, parentNode) {\n\t\t\t\t\tif (!key) return null;\n\t\t\t\t\treturn data.getNodeByParam(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), key, value);\n\t\t\t\t},\n\t\t\t\tgetNodeByTId : function(tId) {\n\t\t\t\t\treturn data.getNodeCache(setting, tId);\n\t\t\t\t},\n\t\t\t\tgetNodesByParam : function(key, value, parentNode) {\n\t\t\t\t\tif (!key) return null;\n\t\t\t\t\treturn data.getNodesByParam(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), key, value);\n\t\t\t\t},\n\t\t\t\tgetNodesByParamFuzzy : function(key, value, parentNode) {\n\t\t\t\t\tif (!key) return null;\n\t\t\t\t\treturn data.getNodesByParamFuzzy(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), key, value);\n\t\t\t\t},\n\t\t\t\tgetNodesByFilter: function(filter, isSingle, parentNode, invokeParam) {\n\t\t\t\t\tisSingle = !!isSingle;\n\t\t\t\t\tif (!filter || (typeof filter != \"function\")) return (isSingle ? null : []);\n\t\t\t\t\treturn data.getNodesByFilter(setting, parentNode?parentNode[setting.data.key.children]:data.getNodes(setting), filter, isSingle, invokeParam);\n\t\t\t\t},\n\t\t\t\tgetNodeIndex : function(node) {\n\t\t\t\t\tif (!node) return null;\n\t\t\t\t\tvar childKey = setting.data.key.children,\n\t\t\t\t\tparentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting);\n\t\t\t\t\tfor (var i=0, l = parentNode[childKey].length; i < l; i++) {\n\t\t\t\t\t\tif (parentNode[childKey][i] == node) return i;\n\t\t\t\t\t}\n\t\t\t\t\treturn -1;\n\t\t\t\t},\n\t\t\t\tgetSelectedNodes : function() {\n\t\t\t\t\tvar r = [], list = data.getRoot(setting).curSelectedList;\n\t\t\t\t\tfor (var i=0, l=list.length; i<l; i++) {\n\t\t\t\t\t\tr.push(list[i]);\n\t\t\t\t\t}\n\t\t\t\t\treturn r;\n\t\t\t\t},\n\t\t\t\tisSelectedNode : function(node) {\n\t\t\t\t\treturn data.isSelectedNode(setting, node);\n\t\t\t\t},\n\t\t\t\treAsyncChildNodes : function(parentNode, reloadType, isSilent) {\n\t\t\t\t\tif (!this.setting.async.enable) return;\n\t\t\t\t\tvar isRoot = !parentNode;\n\t\t\t\t\tif (isRoot) {\n\t\t\t\t\t\tparentNode = data.getRoot(setting);\n\t\t\t\t\t}\n\t\t\t\t\tif (reloadType==\"refresh\") {\n\t\t\t\t\t\tvar childKey = this.setting.data.key.children;\n\t\t\t\t\t\tfor (var i = 0, l = parentNode[childKey] ? parentNode[childKey].length : 0; i < l; i++) {\n\t\t\t\t\t\t\tdata.removeNodeCache(setting, parentNode[childKey][i]);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdata.removeSelectedNode(setting);\n\t\t\t\t\t\tparentNode[childKey] = [];\n\t\t\t\t\t\tif (isRoot) {\n\t\t\t\t\t\t\tthis.setting.treeObj.empty();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar ulObj = $$(parentNode, consts.id.UL, setting);\n\t\t\t\t\t\t\tulObj.empty();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tview.asyncNode(this.setting, isRoot? null:parentNode, !!isSilent);\n\t\t\t\t},\n\t\t\t\trefresh : function() {\n\t\t\t\t\tthis.setting.treeObj.empty();\n\t\t\t\t\tvar root = data.getRoot(setting),\n\t\t\t\t\tnodes = root[setting.data.key.children]\n\t\t\t\t\tdata.initRoot(setting);\n\t\t\t\t\troot[setting.data.key.children] = nodes\n\t\t\t\t\tdata.initCache(setting);\n\t\t\t\t\tview.createNodes(setting, 0, root[setting.data.key.children]);\n\t\t\t\t},\n\t\t\t\tremoveChildNodes : function(node) {\n\t\t\t\t\tif (!node) return null;\n\t\t\t\t\tvar childKey = setting.data.key.children,\n\t\t\t\t\tnodes = node[childKey];\n\t\t\t\t\tview.removeChildNodes(setting, node);\n\t\t\t\t\treturn nodes ? nodes : null;\n\t\t\t\t},\n\t\t\t\tremoveNode : function(node, callbackFlag) {\n\t\t\t\t\tif (!node) return;\n\t\t\t\t\tcallbackFlag = !!callbackFlag;\n\t\t\t\t\tif (callbackFlag && tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return;\n\t\t\t\t\tview.removeNode(setting, node);\n\t\t\t\t\tif (callbackFlag) {\n\t\t\t\t\t\tthis.setting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tselectNode : function(node, addFlag) {\n\t\t\t\t\tif (!node) return;\n\t\t\t\t\tif (tools.uCanDo(setting)) {\n\t\t\t\t\t\taddFlag = setting.view.selectedMulti && addFlag;\n\t\t\t\t\t\tif (node.parentTId) {\n\t\t\t\t\t\t\tview.expandCollapseParentNode(setting, node.getParentNode(), true, false, function() {\n\t\t\t\t\t\t\t\ttry{$$(node, setting).focus().blur();}catch(e){}\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttry{$$(node, setting).focus().blur();}catch(e){}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tview.selectNode(setting, node, addFlag);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\ttransformTozTreeNodes : function(simpleNodes) {\n\t\t\t\t\treturn data.transformTozTreeFormat(setting, simpleNodes);\n\t\t\t\t},\n\t\t\t\ttransformToArray : function(nodes) {\n\t\t\t\t\treturn data.transformToArrayFormat(setting, nodes);\n\t\t\t\t},\n\t\t\t\tupdateNode : function(node, checkTypeFlag) {\n\t\t\t\t\tif (!node) return;\n\t\t\t\t\tvar nObj = $$(node, setting);\n\t\t\t\t\tif (nObj.get(0) && tools.uCanDo(setting)) {\n\t\t\t\t\t\tview.setNodeName(setting, node);\n\t\t\t\t\t\tview.setNodeTarget(setting, node);\n\t\t\t\t\t\tview.setNodeUrl(setting, node);\n\t\t\t\t\t\tview.setNodeLineIcos(setting, node);\n\t\t\t\t\t\tview.setNodeFontCss(setting, node);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\troot.treeTools = zTreeTools;\n\t\t\tdata.setZTreeTools(setting, zTreeTools);\n\n\t\t\tif (root[childKey] && root[childKey].length > 0) {\n\t\t\t\tview.createNodes(setting, 0, root[childKey]);\n\t\t\t} else if (setting.async.enable && setting.async.url && setting.async.url !== '') {\n\t\t\t\tview.asyncNode(setting);\n\t\t\t}\n\t\t\treturn zTreeTools;\n\t\t}\n\t};\n\n\tvar zt = $.fn.zTree,\n\t$$ = tools.$,\n\tconsts = zt.consts;\n})(jQuery);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/js/jquery.ztree.excheck-3.5.js",
    "content": "/*\n * JQuery zTree excheck v3.5.18\n * http://zTree.me/\n *\n * Copyright (c) 2010 Hunter.z\n *\n * Licensed same as jquery - MIT License\n * http://www.opensource.org/licenses/mit-license.php\n *\n * email: hunter.z@263.net\n * Date: 2015-05-25\n */\n(function($){\n\t//default consts of excheck\n\tvar _consts = {\n\t\tevent: {\n\t\t\tCHECK: \"ztree_check\"\n\t\t},\n\t\tid: {\n\t\t\tCHECK: \"_check\"\n\t\t},\n\t\tcheckbox: {\n\t\t\tSTYLE: \"checkbox\",\n\t\t\tDEFAULT: \"chk\",\n\t\t\tDISABLED: \"disable\",\n\t\t\tFALSE: \"false\",\n\t\t\tTRUE: \"true\",\n\t\t\tFULL: \"full\",\n\t\t\tPART: \"part\",\n\t\t\tFOCUS: \"focus\"\n\t\t},\n\t\tradio: {\n\t\t\tSTYLE: \"radio\",\n\t\t\tTYPE_ALL: \"all\",\n\t\t\tTYPE_LEVEL: \"level\"\n\t\t}\n\t},\n\t//default setting of excheck\n\t_setting = {\n\t\tcheck: {\n\t\t\tenable: false,\n\t\t\tautoCheckTrigger: false,\n\t\t\tchkStyle: _consts.checkbox.STYLE,\n\t\t\tnocheckInherit: false,\n\t\t\tchkDisabledInherit: false,\n\t\t\tradioType: _consts.radio.TYPE_LEVEL,\n\t\t\tchkboxType: {\n\t\t\t\t\"Y\": \"ps\",\n\t\t\t\t\"N\": \"ps\"\n\t\t\t}\n\t\t},\n\t\tdata: {\n\t\t\tkey: {\n\t\t\t\tchecked: \"checked\"\n\t\t\t}\n\t\t},\n\t\tcallback: {\n\t\t\tbeforeCheck:null,\n\t\t\tonCheck:null\n\t\t}\n\t},\n\t//default root of excheck\n\t_initRoot = function (setting) {\n\t\tvar r = data.getRoot(setting);\n\t\tr.radioCheckedList = [];\n\t},\n\t//default cache of excheck\n\t_initCache = function(treeId) {},\n\t//default bind event of excheck\n\t_bindEvent = function(setting) {\n\t\tvar o = setting.treeObj,\n\t\tc = consts.event;\n\t\to.bind(c.CHECK, function (event, srcEvent, treeId, node) {\n\t\t\tevent.srcEvent = srcEvent;\n\t\t\ttools.apply(setting.callback.onCheck, [event, treeId, node]);\n\t\t});\n\t},\n\t_unbindEvent = function(setting) {\n\t\tvar o = setting.treeObj,\n\t\tc = consts.event;\n\t\to.unbind(c.CHECK);\n\t},\n\t//default event proxy of excheck\n\t_eventProxy = function(e) {\n\t\tvar target = e.target,\n\t\tsetting = data.getSetting(e.data.treeId),\n\t\ttId = \"\", node = null,\n\t\tnodeEventType = \"\", treeEventType = \"\",\n\t\tnodeEventCallback = null, treeEventCallback = null;\n\n\t\tif (tools.eqs(e.type, \"mouseover\")) {\n\t\t\tif (setting.check.enable && tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\"+ consts.id.CHECK) !== null) {\n\t\t\t\ttId = tools.getNodeMainDom(target).id;\n\t\t\t\tnodeEventType = \"mouseoverCheck\";\n\t\t\t}\n\t\t} else if (tools.eqs(e.type, \"mouseout\")) {\n\t\t\tif (setting.check.enable && tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\"+ consts.id.CHECK) !== null) {\n\t\t\t\ttId = tools.getNodeMainDom(target).id;\n\t\t\t\tnodeEventType = \"mouseoutCheck\";\n\t\t\t}\n\t\t} else if (tools.eqs(e.type, \"click\")) {\n\t\t\tif (setting.check.enable && tools.eqs(target.tagName, \"span\") && target.getAttribute(\"treeNode\"+ consts.id.CHECK) !== null) {\n\t\t\t\ttId = tools.getNodeMainDom(target).id;\n\t\t\t\tnodeEventType = \"checkNode\";\n\t\t\t}\n\t\t}\n\t\tif (tId.length>0) {\n\t\t\tnode = data.getNodeCache(setting, tId);\n\t\t\tswitch (nodeEventType) {\n\t\t\t\tcase \"checkNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onCheckNode;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"mouseoverCheck\" :\n\t\t\t\t\tnodeEventCallback = _handler.onMouseoverCheck;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"mouseoutCheck\" :\n\t\t\t\t\tnodeEventCallback = _handler.onMouseoutCheck;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tvar proxyResult = {\n\t\t\tstop: nodeEventType === \"checkNode\",\n\t\t\tnode: node,\n\t\t\tnodeEventType: nodeEventType,\n\t\t\tnodeEventCallback: nodeEventCallback,\n\t\t\ttreeEventType: treeEventType,\n\t\t\ttreeEventCallback: treeEventCallback\n\t\t};\n\t\treturn proxyResult\n\t},\n\t//default init node of excheck\n\t_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n\t\tif (!n) return;\n\t\tvar checkedKey = setting.data.key.checked;\n\t\tif (typeof n[checkedKey] == \"string\") n[checkedKey] = tools.eqs(n[checkedKey], \"true\");\n\t\tn[checkedKey] = !!n[checkedKey];\n\t\tn.checkedOld = n[checkedKey];\n\t\tif (typeof n.nocheck == \"string\") n.nocheck = tools.eqs(n.nocheck, \"true\");\n\t\tn.nocheck = !!n.nocheck || (setting.check.nocheckInherit && parentNode && !!parentNode.nocheck);\n\t\tif (typeof n.chkDisabled == \"string\") n.chkDisabled = tools.eqs(n.chkDisabled, \"true\");\n\t\tn.chkDisabled = !!n.chkDisabled || (setting.check.chkDisabledInherit && parentNode && !!parentNode.chkDisabled);\n\t\tif (typeof n.halfCheck == \"string\") n.halfCheck = tools.eqs(n.halfCheck, \"true\");\n\t\tn.halfCheck = !!n.halfCheck;\n\t\tn.check_Child_State = -1;\n\t\tn.check_Focus = false;\n\t\tn.getCheckStatus = function() {return data.getCheckStatus(setting, n);};\n\n\t\tif (setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL && n[checkedKey] ) {\n\t\t\tvar r = data.getRoot(setting);\n\t\t\tr.radioCheckedList.push(n);\n\t\t}\n\t},\n\t//add dom for check\n\t_beforeA = function(setting, node, html) {\n\t\tvar checkedKey = setting.data.key.checked;\n\t\tif (setting.check.enable) {\n\t\t\tdata.makeChkFlag(setting, node);\n\t\t\thtml.push(\"<span ID='\", node.tId, consts.id.CHECK, \"' class='\", view.makeChkClass(setting, node), \"' treeNode\", consts.id.CHECK, (node.nocheck === true?\" style='display:none;'\":\"\"),\"></span>\");\n\t\t}\n\t},\n\t//update zTreeObj, add method of check\n\t_zTreeTools = function(setting, zTreeTools) {\n\t\tzTreeTools.checkNode = function(node, checked, checkTypeFlag, callbackFlag) {\n\t\t\tvar checkedKey = this.setting.data.key.checked;\n\t\t\tif (node.chkDisabled === true) return;\n\t\t\tif (checked !== true && checked !== false) {\n\t\t\t\tchecked = !node[checkedKey];\n\t\t\t}\n\t\t\tcallbackFlag = !!callbackFlag;\n\n\t\t\tif (node[checkedKey] === checked && !checkTypeFlag) {\n\t\t\t\treturn;\n\t\t\t} else if (callbackFlag && tools.apply(this.setting.callback.beforeCheck, [this.setting.treeId, node], true) == false) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (tools.uCanDo(this.setting) && this.setting.check.enable && node.nocheck !== true) {\n\t\t\t\tnode[checkedKey] = checked;\n\t\t\t\tvar checkObj = $$(node, consts.id.CHECK, this.setting);\n\t\t\t\tif (checkTypeFlag || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);\n\t\t\t\tview.setChkClass(this.setting, checkObj, node);\n\t\t\t\tview.repairParentChkClassWithSelf(this.setting, node);\n\t\t\t\tif (callbackFlag) {\n\t\t\t\t\tthis.setting.treeObj.trigger(consts.event.CHECK, [null, this.setting.treeId, node]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tzTreeTools.checkAllNodes = function(checked) {\n\t\t\tview.repairAllChk(this.setting, !!checked);\n\t\t}\n\n\t\tzTreeTools.getCheckedNodes = function(checked) {\n\t\t\tvar childKey = this.setting.data.key.children;\n\t\t\tchecked = (checked !== false);\n\t\t\treturn data.getTreeCheckedNodes(this.setting, data.getRoot(this.setting)[childKey], checked);\n\t\t}\n\n\t\tzTreeTools.getChangeCheckedNodes = function() {\n\t\t\tvar childKey = this.setting.data.key.children;\n\t\t\treturn data.getTreeChangeCheckedNodes(this.setting, data.getRoot(this.setting)[childKey]);\n\t\t}\n\n\t\tzTreeTools.setChkDisabled = function(node, disabled, inheritParent, inheritChildren) {\n\t\t\tdisabled = !!disabled;\n\t\t\tinheritParent = !!inheritParent;\n\t\t\tinheritChildren = !!inheritChildren;\n\t\t\tview.repairSonChkDisabled(this.setting, node, disabled, inheritChildren);\n\t\t\tview.repairParentChkDisabled(this.setting, node.getParentNode(), disabled, inheritParent);\n\t\t}\n\n\t\tvar _updateNode = zTreeTools.updateNode;\n\t\tzTreeTools.updateNode = function(node, checkTypeFlag) {\n\t\t\tif (_updateNode) _updateNode.apply(zTreeTools, arguments);\n\t\t\tif (!node || !this.setting.check.enable) return;\n\t\t\tvar nObj = $$(node, this.setting);\n\t\t\tif (nObj.get(0) && tools.uCanDo(this.setting)) {\n\t\t\t\tvar checkObj = $$(node, consts.id.CHECK, this.setting);\n\t\t\t\tif (checkTypeFlag == true || this.setting.check.chkStyle === consts.radio.STYLE) view.checkNodeRelation(this.setting, node);\n\t\t\t\tview.setChkClass(this.setting, checkObj, node);\n\t\t\t\tview.repairParentChkClassWithSelf(this.setting, node);\n\t\t\t}\n\t\t}\n\t},\n\t//method of operate data\n\t_data = {\n\t\tgetRadioCheckedList: function(setting) {\n\t\t\tvar checkedList = data.getRoot(setting).radioCheckedList;\n\t\t\tfor (var i=0, j=checkedList.length; i<j; i++) {\n\t\t\t\tif(!data.getNodeCache(setting, checkedList[i].tId)) {\n\t\t\t\t\tcheckedList.splice(i, 1);\n\t\t\t\t\ti--; j--;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn checkedList;\n\t\t},\n\t\tgetCheckStatus: function(setting, node) {\n\t\t\tif (!setting.check.enable || node.nocheck || node.chkDisabled) return null;\n\t\t\tvar checkedKey = setting.data.key.checked,\n\t\t\tr = {\n\t\t\t\tchecked: node[checkedKey],\n\t\t\t\thalf: node.halfCheck ? node.halfCheck : (setting.check.chkStyle == consts.radio.STYLE ? (node.check_Child_State === 2) : (node[checkedKey] ? (node.check_Child_State > -1 && node.check_Child_State < 2) : (node.check_Child_State > 0)))\n\t\t\t};\n\t\t\treturn r;\n\t\t},\n\t\tgetTreeCheckedNodes: function(setting, nodes, checked, results) {\n\t\t\tif (!nodes) return [];\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked,\n\t\t\tonlyOne = (checked && setting.check.chkStyle == consts.radio.STYLE && setting.check.radioType == consts.radio.TYPE_ALL);\n\t\t\tresults = !results ? [] : results;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (nodes[i].nocheck !== true && nodes[i].chkDisabled !== true && nodes[i][checkedKey] == checked) {\n\t\t\t\t\tresults.push(nodes[i]);\n\t\t\t\t\tif(onlyOne) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdata.getTreeCheckedNodes(setting, nodes[i][childKey], checked, results);\n\t\t\t\tif(onlyOne && results.length > 0) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn results;\n\t\t},\n\t\tgetTreeChangeCheckedNodes: function(setting, nodes, results) {\n\t\t\tif (!nodes) return [];\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked;\n\t\t\tresults = !results ? [] : results;\n\t\t\tfor (var i = 0, l = nodes.length; i < l; i++) {\n\t\t\t\tif (nodes[i].nocheck !== true && nodes[i].chkDisabled !== true && nodes[i][checkedKey] != nodes[i].checkedOld) {\n\t\t\t\t\tresults.push(nodes[i]);\n\t\t\t\t}\n\t\t\t\tdata.getTreeChangeCheckedNodes(setting, nodes[i][childKey], results);\n\t\t\t}\n\t\t\treturn results;\n\t\t},\n\t\tmakeChkFlag: function(setting, node) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked,\n\t\t\tchkFlag = -1;\n\t\t\tif (node[childKey]) {\n\t\t\t\tfor (var i = 0, l = node[childKey].length; i < l; i++) {\n\t\t\t\t\tvar cNode = node[childKey][i];\n\t\t\t\t\tvar tmp = -1;\n\t\t\t\t\tif (setting.check.chkStyle == consts.radio.STYLE) {\n\t\t\t\t\t\tif (cNode.nocheck === true || cNode.chkDisabled === true) {\n\t\t\t\t\t\t\ttmp = cNode.check_Child_State;\n\t\t\t\t\t\t} else if (cNode.halfCheck === true) {\n\t\t\t\t\t\t\ttmp = 2;\n\t\t\t\t\t\t} else if (cNode[checkedKey]) {\n\t\t\t\t\t\t\ttmp = 2;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttmp = cNode.check_Child_State > 0 ? 2:0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (tmp == 2) {\n\t\t\t\t\t\t\tchkFlag = 2; break;\n\t\t\t\t\t\t} else if (tmp == 0){\n\t\t\t\t\t\t\tchkFlag = 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (setting.check.chkStyle == consts.checkbox.STYLE) {\n\t\t\t\t\t\tif (cNode.nocheck === true || cNode.chkDisabled === true) {\n\t\t\t\t\t\t\ttmp = cNode.check_Child_State;\n\t\t\t\t\t\t} else if (cNode.halfCheck === true) {\n\t\t\t\t\t\t\ttmp = 1;\n\t\t\t\t\t\t} else if (cNode[checkedKey] ) {\n\t\t\t\t\t\t\ttmp = (cNode.check_Child_State === -1 || cNode.check_Child_State === 2) ? 2 : 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttmp = (cNode.check_Child_State > 0) ? 1 : 0;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (tmp === 1) {\n\t\t\t\t\t\t\tchkFlag = 1; break;\n\t\t\t\t\t\t} else if (tmp === 2 && chkFlag > -1 && i > 0 && tmp !== chkFlag) {\n\t\t\t\t\t\t\tchkFlag = 1; break;\n\t\t\t\t\t\t} else if (chkFlag === 2 && tmp > -1 && tmp < 2) {\n\t\t\t\t\t\t\tchkFlag = 1; break;\n\t\t\t\t\t\t} else if (tmp > -1) {\n\t\t\t\t\t\t\tchkFlag = tmp;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tnode.check_Child_State = chkFlag;\n\t\t}\n\t},\n\t//method of event proxy\n\t_event = {\n\n\t},\n\t//method of event handler\n\t_handler = {\n\t\tonCheckNode: function (event, node) {\n\t\t\tif (node.chkDisabled === true) return false;\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\tcheckedKey = setting.data.key.checked;\n\t\t\tif (tools.apply(setting.callback.beforeCheck, [setting.treeId, node], true) == false) return true;\n\t\t\tnode[checkedKey] = !node[checkedKey];\n\t\t\tview.checkNodeRelation(setting, node);\n\t\t\tvar checkObj = $$(node, consts.id.CHECK, setting);\n\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\tview.repairParentChkClassWithSelf(setting, node);\n\t\t\tsetting.treeObj.trigger(consts.event.CHECK, [event, setting.treeId, node]);\n\t\t\treturn true;\n\t\t},\n\t\tonMouseoverCheck: function(event, node) {\n\t\t\tif (node.chkDisabled === true) return false;\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\tcheckObj = $$(node, consts.id.CHECK, setting);\n\t\t\tnode.check_Focus = true;\n\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\treturn true;\n\t\t},\n\t\tonMouseoutCheck: function(event, node) {\n\t\t\tif (node.chkDisabled === true) return false;\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\tcheckObj = $$(node, consts.id.CHECK, setting);\n\t\t\tnode.check_Focus = false;\n\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\treturn true;\n\t\t}\n\t},\n\t//method of tools for zTree\n\t_tools = {\n\n\t},\n\t//method of operate ztree dom\n\t_view = {\n\t\tcheckNodeRelation: function(setting, node) {\n\t\t\tvar pNode, i, l,\n\t\t\tchildKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked,\n\t\t\tr = consts.radio;\n\t\t\tif (setting.check.chkStyle == r.STYLE) {\n\t\t\t\tvar checkedList = data.getRadioCheckedList(setting);\n\t\t\t\tif (node[checkedKey]) {\n\t\t\t\t\tif (setting.check.radioType == r.TYPE_ALL) {\n\t\t\t\t\t\tfor (i = checkedList.length-1; i >= 0; i--) {\n\t\t\t\t\t\t\tpNode = checkedList[i];\n\t\t\t\t\t\t\tif (pNode[checkedKey] && pNode != node) {\n\t\t\t\t\t\t\t\tpNode[checkedKey] = false;\n\t\t\t\t\t\t\t\tcheckedList.splice(i, 1);\n\n\t\t\t\t\t\t\t\tview.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode);\n\t\t\t\t\t\t\t\tif (pNode.parentTId != node.parentTId) {\n\t\t\t\t\t\t\t\t\tview.repairParentChkClassWithSelf(setting, pNode);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcheckedList.push(node);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar parentNode = (node.parentTId) ? node.getParentNode() : data.getRoot(setting);\n\t\t\t\t\t\tfor (i = 0, l = parentNode[childKey].length; i < l; i++) {\n\t\t\t\t\t\t\tpNode = parentNode[childKey][i];\n\t\t\t\t\t\t\tif (pNode[checkedKey] && pNode != node) {\n\t\t\t\t\t\t\t\tpNode[checkedKey] = false;\n\t\t\t\t\t\t\t\tview.setChkClass(setting, $$(pNode, consts.id.CHECK, setting), pNode);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (setting.check.radioType == r.TYPE_ALL) {\n\t\t\t\t\tfor (i = 0, l = checkedList.length; i < l; i++) {\n\t\t\t\t\t\tif (node == checkedList[i]) {\n\t\t\t\t\t\t\tcheckedList.splice(i, 1);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tif (node[checkedKey] && (!node[childKey] || node[childKey].length==0 || setting.check.chkboxType.Y.indexOf(\"s\") > -1)) {\n\t\t\t\t\tview.setSonNodeCheckBox(setting, node, true);\n\t\t\t\t}\n\t\t\t\tif (!node[checkedKey] && (!node[childKey] || node[childKey].length==0 || setting.check.chkboxType.N.indexOf(\"s\") > -1)) {\n\t\t\t\t\tview.setSonNodeCheckBox(setting, node, false);\n\t\t\t\t}\n\t\t\t\tif (node[checkedKey] && setting.check.chkboxType.Y.indexOf(\"p\") > -1) {\n\t\t\t\t\tview.setParentNodeCheckBox(setting, node, true);\n\t\t\t\t}\n\t\t\t\tif (!node[checkedKey] && setting.check.chkboxType.N.indexOf(\"p\") > -1) {\n\t\t\t\t\tview.setParentNodeCheckBox(setting, node, false);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tmakeChkClass: function(setting, node) {\n\t\t\tvar checkedKey = setting.data.key.checked,\n\t\t\tc = consts.checkbox, r = consts.radio,\n\t\t\tfullStyle = \"\";\n\t\t\tif (node.chkDisabled === true) {\n\t\t\t\tfullStyle = c.DISABLED;\n\t\t\t} else if (node.halfCheck) {\n\t\t\t\tfullStyle = c.PART;\n\t\t\t} else if (setting.check.chkStyle == r.STYLE) {\n\t\t\t\tfullStyle = (node.check_Child_State < 1)? c.FULL:c.PART;\n\t\t\t} else {\n\t\t\t\tfullStyle = node[checkedKey] ? ((node.check_Child_State === 2 || node.check_Child_State === -1) ? c.FULL:c.PART) : ((node.check_Child_State < 1)? c.FULL:c.PART);\n\t\t\t}\n\t\t\tvar chkName = setting.check.chkStyle + \"_\" + (node[checkedKey] ? c.TRUE : c.FALSE) + \"_\" + fullStyle;\n\t\t\tchkName = (node.check_Focus && node.chkDisabled !== true) ? chkName + \"_\" + c.FOCUS : chkName;\n\t\t\treturn consts.className.BUTTON + \" \" + c.DEFAULT + \" \" + chkName;\n\t\t},\n\t\trepairAllChk: function(setting, checked) {\n\t\t\tif (setting.check.enable && setting.check.chkStyle === consts.checkbox.STYLE) {\n\t\t\t\tvar checkedKey = setting.data.key.checked,\n\t\t\t\tchildKey = setting.data.key.children,\n\t\t\t\troot = data.getRoot(setting);\n\t\t\t\tfor (var i = 0, l = root[childKey].length; i<l ; i++) {\n\t\t\t\t\tvar node = root[childKey][i];\n\t\t\t\t\tif (node.nocheck !== true && node.chkDisabled !== true) {\n\t\t\t\t\t\tnode[checkedKey] = checked;\n\t\t\t\t\t}\n\t\t\t\t\tview.setSonNodeCheckBox(setting, node, checked);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\trepairChkClass: function(setting, node) {\n\t\t\tif (!node) return;\n\t\t\tdata.makeChkFlag(setting, node);\n\t\t\tif (node.nocheck !== true) {\n\t\t\t\tvar checkObj = $$(node, consts.id.CHECK, setting);\n\t\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\t}\n\t\t},\n\t\trepairParentChkClass: function(setting, node) {\n\t\t\tif (!node || !node.parentTId) return;\n\t\t\tvar pNode = node.getParentNode();\n\t\t\tview.repairChkClass(setting, pNode);\n\t\t\tview.repairParentChkClass(setting, pNode);\n\t\t},\n\t\trepairParentChkClassWithSelf: function(setting, node) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tif (node[childKey] && node[childKey].length > 0) {\n\t\t\t\tview.repairParentChkClass(setting, node[childKey][0]);\n\t\t\t} else {\n\t\t\t\tview.repairParentChkClass(setting, node);\n\t\t\t}\n\t\t},\n\t\trepairSonChkDisabled: function(setting, node, chkDisabled, inherit) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tif (node.chkDisabled != chkDisabled) {\n\t\t\t\tnode.chkDisabled = chkDisabled;\n\t\t\t}\n\t\t\tview.repairChkClass(setting, node);\n\t\t\tif (node[childKey] && inherit) {\n\t\t\t\tfor (var i = 0, l = node[childKey].length; i < l; i++) {\n\t\t\t\t\tvar sNode = node[childKey][i];\n\t\t\t\t\tview.repairSonChkDisabled(setting, sNode, chkDisabled, inherit);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\trepairParentChkDisabled: function(setting, node, chkDisabled, inherit) {\n\t\t\tif (!node) return;\n\t\t\tif (node.chkDisabled != chkDisabled && inherit) {\n\t\t\t\tnode.chkDisabled = chkDisabled;\n\t\t\t}\n\t\t\tview.repairChkClass(setting, node);\n\t\t\tview.repairParentChkDisabled(setting, node.getParentNode(), chkDisabled, inherit);\n\t\t},\n\t\tsetChkClass: function(setting, obj, node) {\n\t\t\tif (!obj) return;\n\t\t\tif (node.nocheck === true) {\n\t\t\t\tobj.hide();\n\t\t\t} else {\n\t\t\t\tobj.show();\n\t\t\t}\n            obj.attr('class', view.makeChkClass(setting, node));\n\t\t},\n\t\tsetParentNodeCheckBox: function(setting, node, value, srcNode) {\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked,\n\t\t\tcheckObj = $$(node, consts.id.CHECK, setting);\n\t\t\tif (!srcNode) srcNode = node;\n\t\t\tdata.makeChkFlag(setting, node);\n\t\t\tif (node.nocheck !== true && node.chkDisabled !== true) {\n\t\t\t\tnode[checkedKey] = value;\n\t\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\t\tif (setting.check.autoCheckTrigger && node != srcNode) {\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (node.parentTId) {\n\t\t\t\tvar pSign = true;\n\t\t\t\tif (!value) {\n\t\t\t\t\tvar pNodes = node.getParentNode()[childKey];\n\t\t\t\t\tfor (var i = 0, l = pNodes.length; i < l; i++) {\n\t\t\t\t\t\tif ((pNodes[i].nocheck !== true && pNodes[i].chkDisabled !== true && pNodes[i][checkedKey])\n\t\t\t\t\t\t|| ((pNodes[i].nocheck === true || pNodes[i].chkDisabled === true) && pNodes[i].check_Child_State > 0)) {\n\t\t\t\t\t\t\tpSign = false;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (pSign) {\n\t\t\t\t\tview.setParentNodeCheckBox(setting, node.getParentNode(), value, srcNode);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tsetSonNodeCheckBox: function(setting, node, value, srcNode) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children,\n\t\t\tcheckedKey = setting.data.key.checked,\n\t\t\tcheckObj = $$(node, consts.id.CHECK, setting);\n\t\t\tif (!srcNode) srcNode = node;\n\n\t\t\tvar hasDisable = false;\n\t\t\tif (node[childKey]) {\n\t\t\t\tfor (var i = 0, l = node[childKey].length; i < l && node.chkDisabled !== true; i++) {\n\t\t\t\t\tvar sNode = node[childKey][i];\n\t\t\t\t\tview.setSonNodeCheckBox(setting, sNode, value, srcNode);\n\t\t\t\t\tif (sNode.chkDisabled === true) hasDisable = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (node != data.getRoot(setting) && node.chkDisabled !== true) {\n\t\t\t\tif (hasDisable && node.nocheck !== true) {\n\t\t\t\t\tdata.makeChkFlag(setting, node);\n\t\t\t\t}\n\t\t\t\tif (node.nocheck !== true && node.chkDisabled !== true) {\n\t\t\t\t\tnode[checkedKey] = value;\n\t\t\t\t\tif (!hasDisable) node.check_Child_State = (node[childKey] && node[childKey].length > 0) ? (value ? 2 : 0) : -1;\n\t\t\t\t} else {\n\t\t\t\t\tnode.check_Child_State = -1;\n\t\t\t\t}\n\t\t\t\tview.setChkClass(setting, checkObj, node);\n\t\t\t\tif (setting.check.autoCheckTrigger && node != srcNode && node.nocheck !== true && node.chkDisabled !== true) {\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.CHECK, [null, setting.treeId, node]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t},\n\n\t_z = {\n\t\ttools: _tools,\n\t\tview: _view,\n\t\tevent: _event,\n\t\tdata: _data\n\t};\n\t$.extend(true, $.fn.zTree.consts, _consts);\n\t$.extend(true, $.fn.zTree._z, _z);\n\n\tvar zt = $.fn.zTree,\n\ttools = zt._z.tools,\n\tconsts = zt.consts,\n\tview = zt._z.view,\n\tdata = zt._z.data,\n\tevent = zt._z.event,\n\t$$ = tools.$;\n\n\tdata.exSetting(_setting);\n\tdata.addInitBind(_bindEvent);\n\tdata.addInitUnBind(_unbindEvent);\n\tdata.addInitCache(_initCache);\n\tdata.addInitNode(_initNode);\n\tdata.addInitProxy(_eventProxy, true);\n\tdata.addInitRoot(_initRoot);\n\tdata.addBeforeA(_beforeA);\n\tdata.addZTreeTools(_zTreeTools);\n\n\tvar _createNodes = view.createNodes;\n\tview.createNodes = function(setting, level, nodes, parentNode) {\n\t\tif (_createNodes) _createNodes.apply(view, arguments);\n\t\tif (!nodes) return;\n\t\tview.repairParentChkClassWithSelf(setting, parentNode);\n\t}\n\tvar _removeNode = view.removeNode;\n\tview.removeNode = function(setting, node) {\n\t\tvar parentNode = node.getParentNode();\n\t\tif (_removeNode) _removeNode.apply(view, arguments);\n\t\tif (!node || !parentNode) return;\n\t\tview.repairChkClass(setting, parentNode);\n\t\tview.repairParentChkClass(setting, parentNode);\n\t}\n\n\tvar _appendNodes = view.appendNodes;\n\tview.appendNodes = function(setting, level, nodes, parentNode, initFlag, openFlag) {\n\t\tvar html = \"\";\n\t\tif (_appendNodes) {\n\t\t\thtml = _appendNodes.apply(view, arguments);\n\t\t}\n\t\tif (parentNode) {\n\t\t\tdata.makeChkFlag(setting, parentNode);\n\t\t}\n\t\treturn html;\n\t}\n})(jQuery);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/js/jquery.ztree.exedit-3.5.js",
    "content": "/*\n * JQuery zTree exedit v3.5.18\n * http://zTree.me/\n *\n * Copyright (c) 2010 Hunter.z\n *\n * Licensed same as jquery - MIT License\n * http://www.opensource.org/licenses/mit-license.php\n *\n * email: hunter.z@263.net\n * Date: 2015-05-25\n */\n(function($){\n\t//default consts of exedit\n\tvar _consts = {\n\t\tevent: {\n\t\t\tDRAG: \"ztree_drag\",\n\t\t\tDROP: \"ztree_drop\",\n\t\t\tRENAME: \"ztree_rename\",\n\t\t\tDRAGMOVE:\"ztree_dragmove\"\n\t\t},\n\t\tid: {\n\t\t\tEDIT: \"_edit\",\n\t\t\tINPUT: \"_input\",\n\t\t\tREMOVE: \"_remove\"\n\t\t},\n\t\tmove: {\n\t\t\tTYPE_INNER: \"inner\",\n\t\t\tTYPE_PREV: \"prev\",\n\t\t\tTYPE_NEXT: \"next\"\n\t\t},\n\t\tnode: {\n\t\t\tCURSELECTED_EDIT: \"curSelectedNode_Edit\",\n\t\t\tTMPTARGET_TREE: \"tmpTargetzTree\",\n\t\t\tTMPTARGET_NODE: \"tmpTargetNode\"\n\t\t}\n\t},\n\t//default setting of exedit\n\t_setting = {\n\t\tedit: {\n\t\t\tenable: false,\n\t\t\teditNameSelectAll: false,\n\t\t\tshowRemoveBtn: true,\n\t\t\tshowRenameBtn: true,\n\t\t\tremoveTitle: \"remove\",\n\t\t\trenameTitle: \"rename\",\n\t\t\tdrag: {\n\t\t\t\tautoExpandTrigger: false,\n\t\t\t\tisCopy: true,\n\t\t\t\tisMove: true,\n\t\t\t\tprev: true,\n\t\t\t\tnext: true,\n\t\t\t\tinner: true,\n\t\t\t\tminMoveSize: 5,\n\t\t\t\tborderMax: 10,\n\t\t\t\tborderMin: -5,\n\t\t\t\tmaxShowNodeNum: 5,\n\t\t\t\tautoOpenTime: 500\n\t\t\t}\n\t\t},\n\t\tview: {\n\t\t\taddHoverDom: null,\n\t\t\tremoveHoverDom: null\n\t\t},\n\t\tcallback: {\n\t\t\tbeforeDrag:null,\n\t\t\tbeforeDragOpen:null,\n\t\t\tbeforeDrop:null,\n\t\t\tbeforeEditName:null,\n\t\t\tbeforeRename:null,\n\t\t\tonDrag:null,\n\t\t\tonDragMove:null,\n\t\t\tonDrop:null,\n\t\t\tonRename:null\n\t\t}\n\t},\n\t//default root of exedit\n\t_initRoot = function (setting) {\n\t\tvar r = data.getRoot(setting), rs = data.getRoots();\n\t\tr.curEditNode = null;\n\t\tr.curEditInput = null;\n\t\tr.curHoverNode = null;\n\t\tr.dragFlag = 0;\n\t\tr.dragNodeShowBefore = [];\n\t\tr.dragMaskList = new Array();\n\t\trs.showHoverDom = true;\n\t},\n\t//default cache of exedit\n\t_initCache = function(treeId) {},\n\t//default bind event of exedit\n\t_bindEvent = function(setting) {\n\t\tvar o = setting.treeObj;\n\t\tvar c = consts.event;\n\t\to.bind(c.RENAME, function (event, treeId, treeNode, isCancel) {\n\t\t\ttools.apply(setting.callback.onRename, [event, treeId, treeNode, isCancel]);\n\t\t});\n\n\t\to.bind(c.DRAG, function (event, srcEvent, treeId, treeNodes) {\n\t\t\ttools.apply(setting.callback.onDrag, [srcEvent, treeId, treeNodes]);\n\t\t});\n\n\t\to.bind(c.DRAGMOVE,function(event, srcEvent, treeId, treeNodes){\n\t\t\ttools.apply(setting.callback.onDragMove,[srcEvent, treeId, treeNodes]);\n\t\t});\n\n\t\to.bind(c.DROP, function (event, srcEvent, treeId, treeNodes, targetNode, moveType, isCopy) {\n\t\t\ttools.apply(setting.callback.onDrop, [srcEvent, treeId, treeNodes, targetNode, moveType, isCopy]);\n\t\t});\n\t},\n\t_unbindEvent = function(setting) {\n\t\tvar o = setting.treeObj;\n\t\tvar c = consts.event;\n\t\to.unbind(c.RENAME);\n\t\to.unbind(c.DRAG);\n\t\to.unbind(c.DRAGMOVE);\n\t\to.unbind(c.DROP);\n\t},\n\t//default event proxy of exedit\n\t_eventProxy = function(e) {\n\t\tvar target = e.target,\n\t\tsetting = data.getSetting(e.data.treeId),\n\t\trelatedTarget = e.relatedTarget,\n\t\ttId = \"\", node = null,\n\t\tnodeEventType = \"\", treeEventType = \"\",\n\t\tnodeEventCallback = null, treeEventCallback = null,\n\t\ttmp = null;\n\n\t\tif (tools.eqs(e.type, \"mouseover\")) {\n\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (tmp) {\n\t\t\t\ttId = tools.getNodeMainDom(tmp).id;\n\t\t\t\tnodeEventType = \"hoverOverNode\";\n\t\t\t}\n\t\t} else if (tools.eqs(e.type, \"mouseout\")) {\n\t\t\ttmp = tools.getMDom(setting, relatedTarget, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (!tmp) {\n\t\t\t\ttId = \"remove\";\n\t\t\t\tnodeEventType = \"hoverOutNode\";\n\t\t\t}\n\t\t} else if (tools.eqs(e.type, \"mousedown\")) {\n\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (tmp) {\n\t\t\t\ttId = tools.getNodeMainDom(tmp).id;\n\t\t\t\tnodeEventType = \"mousedownNode\";\n\t\t\t}\n\t\t}\n\t\tif (tId.length>0) {\n\t\t\tnode = data.getNodeCache(setting, tId);\n\t\t\tswitch (nodeEventType) {\n\t\t\t\tcase \"mousedownNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onMousedownNode;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hoverOverNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onHoverOverNode;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hoverOutNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onHoverOutNode;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tvar proxyResult = {\n\t\t\tstop: false,\n\t\t\tnode: node,\n\t\t\tnodeEventType: nodeEventType,\n\t\t\tnodeEventCallback: nodeEventCallback,\n\t\t\ttreeEventType: treeEventType,\n\t\t\ttreeEventCallback: treeEventCallback\n\t\t};\n\t\treturn proxyResult\n\t},\n\t//default init node of exedit\n\t_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n\t\tif (!n) return;\n\t\tn.isHover = false;\n\t\tn.editNameFlag = false;\n\t},\n\t//update zTreeObj, add method of edit\n\t_zTreeTools = function(setting, zTreeTools) {\n\t\tzTreeTools.cancelEditName = function(newName) {\n\t\t\tvar root = data.getRoot(this.setting);\n\t\t\tif (!root.curEditNode) return;\n\t\t\tview.cancelCurEditNode(this.setting, newName?newName:null, true);\n\t\t}\n\t\tzTreeTools.copyNode = function(targetNode, node, moveType, isSilent) {\n\t\t\tif (!node) return null;\n\t\t\tif (targetNode && !targetNode.isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) return null;\n\t\t\tvar _this = this,\n\t\t\t\tnewNode = tools.clone(node);\n\t\t\tif (!targetNode) {\n\t\t\t\ttargetNode = null;\n\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t}\n\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\tfunction copyCallback() {\n\t\t\t\t\tview.addNodes(_this.setting, targetNode, [newNode], isSilent);\n\t\t\t\t}\n\n\t\t\t\tif (tools.canAsync(this.setting, targetNode)) {\n\t\t\t\t\tview.asyncNode(this.setting, targetNode, isSilent, copyCallback);\n\t\t\t\t} else {\n\t\t\t\t\tcopyCallback();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tview.addNodes(this.setting, targetNode.parentNode, [newNode], isSilent);\n\t\t\t\tview.moveNode(this.setting, targetNode, newNode, moveType, false, isSilent);\n\t\t\t}\n\t\t\treturn newNode;\n\t\t}\n\t\tzTreeTools.editName = function(node) {\n\t\t\tif (!node || !node.tId || node !== data.getNodeCache(this.setting, node.tId)) return;\n\t\t\tif (node.parentTId) view.expandCollapseParentNode(this.setting, node.getParentNode(), true);\n\t\t\tview.editNode(this.setting, node)\n\t\t}\n\t\tzTreeTools.moveNode = function(targetNode, node, moveType, isSilent) {\n\t\t\tif (!node) return node;\n\t\t\tif (targetNode && !targetNode.isParent && this.setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) {\n\t\t\t\treturn null;\n\t\t\t} else if (targetNode && ((node.parentTId == targetNode.tId && moveType == consts.move.TYPE_INNER) || $$(node, this.setting).find(\"#\" + targetNode.tId).length > 0)) {\n\t\t\t\treturn null;\n\t\t\t} else if (!targetNode) {\n\t\t\t\ttargetNode = null;\n\t\t\t}\n\t\t\tvar _this = this;\n\t\t\tfunction moveCallback() {\n\t\t\t\tview.moveNode(_this.setting, targetNode, node, moveType, false, isSilent);\n\t\t\t}\n\t\t\tif (tools.canAsync(this.setting, targetNode) && moveType === consts.move.TYPE_INNER) {\n\t\t\t\tview.asyncNode(this.setting, targetNode, isSilent, moveCallback);\n\t\t\t} else {\n\t\t\t\tmoveCallback();\n\t\t\t}\n\t\t\treturn node;\n\t\t}\n\t\tzTreeTools.setEditable = function(editable) {\n\t\t\tthis.setting.edit.enable = editable;\n\t\t\treturn this.refresh();\n\t\t}\n\t},\n\t//method of operate data\n\t_data = {\n\t\tsetSonNodeLevel: function(setting, parentNode, node) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tnode.level = (parentNode)? parentNode.level + 1 : 0;\n\t\t\tif (!node[childKey]) return;\n\t\t\tfor (var i = 0, l = node[childKey].length; i < l; i++) {\n\t\t\t\tif (node[childKey][i]) data.setSonNodeLevel(setting, node, node[childKey][i]);\n\t\t\t}\n\t\t}\n\t},\n\t//method of event proxy\n\t_event = {\n\n\t},\n\t//method of event handler\n\t_handler = {\n\t\tonHoverOverNode: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\troot = data.getRoot(setting);\n\t\t\tif (root.curHoverNode != node) {\n\t\t\t\t_handler.onHoverOutNode(event);\n\t\t\t}\n\t\t\troot.curHoverNode = node;\n\t\t\tview.addHoverDom(setting, node);\n\t\t},\n\t\tonHoverOutNode: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\troot = data.getRoot(setting);\n\t\t\tif (root.curHoverNode && !data.isSelectedNode(setting, root.curHoverNode)) {\n\t\t\t\tview.removeTreeDom(setting, root.curHoverNode);\n\t\t\t\troot.curHoverNode = null;\n\t\t\t}\n\t\t},\n\t\tonMousedownNode: function(eventMouseDown, _node) {\n\t\t\tvar i,l,\n\t\t\tsetting = data.getSetting(eventMouseDown.data.treeId),\n\t\t\troot = data.getRoot(setting), roots = data.getRoots();\n\t\t\t//right click can't drag & drop\n\t\t\tif (eventMouseDown.button == 2 || !setting.edit.enable || (!setting.edit.drag.isCopy && !setting.edit.drag.isMove)) return true;\n\n\t\t\t//input of edit node name can't drag & drop\n\t\t\tvar target = eventMouseDown.target,\n\t\t\t_nodes = data.getRoot(setting).curSelectedList,\n\t\t\tnodes = [];\n\t\t\tif (!data.isSelectedNode(setting, _node)) {\n\t\t\t\tnodes = [_node];\n\t\t\t} else {\n\t\t\t\tfor (i=0, l=_nodes.length; i<l; i++) {\n\t\t\t\t\tif (_nodes[i].editNameFlag && tools.eqs(target.tagName, \"input\") && target.getAttribute(\"treeNode\"+consts.id.INPUT) !== null) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tnodes.push(_nodes[i]);\n\t\t\t\t\tif (nodes[0].parentTId !== _nodes[i].parentTId) {\n\t\t\t\t\t\tnodes = [_node];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tview.editNodeBlur = true;\n\t\t\tview.cancelCurEditNode(setting);\n\n\t\t\tvar doc = $(setting.treeObj.get(0).ownerDocument),\n\t\t\tbody = $(setting.treeObj.get(0).ownerDocument.body), curNode, tmpArrow, tmpTarget,\n\t\t\tisOtherTree = false,\n\t\t\ttargetSetting = setting,\n\t\t\tsourceSetting = setting,\n\t\t\tpreNode, nextNode,\n\t\t\tpreTmpTargetNodeId = null,\n\t\t\tpreTmpMoveType = null,\n\t\t\ttmpTargetNodeId = null,\n\t\t\tmoveType = consts.move.TYPE_INNER,\n\t\t\tmouseDownX = eventMouseDown.clientX,\n\t\t\tmouseDownY = eventMouseDown.clientY,\n\t\t\tstartTime = (new Date()).getTime();\n\n\t\t\tif (tools.uCanDo(setting)) {\n\t\t\t\tdoc.bind(\"mousemove\", _docMouseMove);\n\t\t\t}\n\t\t\tfunction _docMouseMove(event) {\n\t\t\t\t//avoid start drag after click node\n\t\t\t\tif (root.dragFlag == 0 && Math.abs(mouseDownX - event.clientX) < setting.edit.drag.minMoveSize\n\t\t\t\t\t&& Math.abs(mouseDownY - event.clientY) < setting.edit.drag.minMoveSize) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tvar i, l, tmpNode, tmpDom, tmpNodes,\n\t\t\t\tchildKey = setting.data.key.children;\n\t\t\t\tbody.css(\"cursor\", \"pointer\");\n\n\t\t\t\tif (root.dragFlag == 0) {\n\t\t\t\t\tif (tools.apply(setting.callback.beforeDrag, [setting.treeId, nodes], true) == false) {\n\t\t\t\t\t\t_docMouseUp(event);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\tif (i==0) {\n\t\t\t\t\t\t\troot.dragNodeShowBefore = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\t\tif (tmpNode.isParent && tmpNode.open) {\n\t\t\t\t\t\t\tview.expandCollapseNode(setting, tmpNode, !tmpNode.open);\n\t\t\t\t\t\t\troot.dragNodeShowBefore[tmpNode.tId] = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\troot.dragNodeShowBefore[tmpNode.tId] = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\troot.dragFlag = 1;\n\t\t\t\t\troots.showHoverDom = false;\n\t\t\t\t\ttools.showIfameMask(setting, true);\n\n\t\t\t\t\t//sort\n\t\t\t\t\tvar isOrder = true, lastIndex = -1;\n\t\t\t\t\tif (nodes.length>1) {\n\t\t\t\t\t\tvar pNodes = nodes[0].parentTId ? nodes[0].getParentNode()[childKey] : data.getNodes(setting);\n\t\t\t\t\t\ttmpNodes = [];\n\t\t\t\t\t\tfor (i=0, l=pNodes.length; i<l; i++) {\n\t\t\t\t\t\t\tif (root.dragNodeShowBefore[pNodes[i].tId] !== undefined) {\n\t\t\t\t\t\t\t\tif (isOrder && lastIndex > -1 && (lastIndex+1) !== i) {\n\t\t\t\t\t\t\t\t\tisOrder = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttmpNodes.push(pNodes[i]);\n\t\t\t\t\t\t\t\tlastIndex = i;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (nodes.length === tmpNodes.length) {\n\t\t\t\t\t\t\t\tnodes = tmpNodes;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (isOrder) {\n\t\t\t\t\t\tpreNode = nodes[0].getPreNode();\n\t\t\t\t\t\tnextNode = nodes[nodes.length-1].getNextNode();\n\t\t\t\t\t}\n\n\t\t\t\t\t//set node in selected\n\t\t\t\t\tcurNode = $$(\"<ul class='zTreeDragUL'></ul>\", setting);\n\t\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\t\ttmpNode.editNameFlag = false;\n\t\t\t\t\t\tview.selectNode(setting, tmpNode, i>0);\n\t\t\t\t\t\tview.removeTreeDom(setting, tmpNode);\n\n\t\t\t\t\t\tif (i > setting.edit.drag.maxShowNodeNum-1) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttmpDom = $$(\"<li id='\"+ tmpNode.tId +\"_tmp'></li>\", setting);\n\t\t\t\t\t\ttmpDom.append($$(tmpNode, consts.id.A, setting).clone());\n\t\t\t\t\t\ttmpDom.css(\"padding\", \"0\");\n\t\t\t\t\t\ttmpDom.children(\"#\" + tmpNode.tId + consts.id.A).removeClass(consts.node.CURSELECTED);\n\t\t\t\t\t\tcurNode.append(tmpDom);\n\t\t\t\t\t\tif (i == setting.edit.drag.maxShowNodeNum-1) {\n\t\t\t\t\t\t\ttmpDom = $$(\"<li id='\"+ tmpNode.tId +\"_moretmp'><a>  ...  </a></li>\", setting);\n\t\t\t\t\t\t\tcurNode.append(tmpDom);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcurNode.attr(\"id\", nodes[0].tId + consts.id.UL + \"_tmp\");\n\t\t\t\t\tcurNode.addClass(setting.treeObj.attr(\"class\"));\n\t\t\t\t\tcurNode.appendTo(body);\n\n\t\t\t\t\ttmpArrow = $$(\"<span class='tmpzTreeMove_arrow'></span>\", setting);\n\t\t\t\t\ttmpArrow.attr(\"id\", \"zTreeMove_arrow_tmp\");\n\t\t\t\t\ttmpArrow.appendTo(body);\n\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.DRAG, [event, setting.treeId, nodes]);\n\t\t\t\t}\n\n\t\t\t\tif (root.dragFlag == 1) {\n\t\t\t\t\tif (tmpTarget && tmpArrow.attr(\"id\") == event.target.id && tmpTargetNodeId && (event.clientX + doc.scrollLeft()+2) > ($(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).offset().left)) {\n\t\t\t\t\t\tvar xT = $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget);\n\t\t\t\t\t\tevent.target = (xT.length > 0) ? xT.get(0) : event.target;\n\t\t\t\t\t} else if (tmpTarget) {\n\t\t\t\t\t\ttmpTarget.removeClass(consts.node.TMPTARGET_TREE);\n\t\t\t\t\t\tif (tmpTargetNodeId) $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + \"_\" + consts.move.TYPE_PREV)\n\t\t\t\t\t\t\t.removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_INNER);\n\t\t\t\t\t}\n\t\t\t\t\ttmpTarget = null;\n\t\t\t\t\ttmpTargetNodeId = null;\n\n\t\t\t\t\t//judge drag & drop in multi ztree\n\t\t\t\t\tisOtherTree = false;\n\t\t\t\t\ttargetSetting = setting;\n\t\t\t\t\tvar settings = data.getSettings();\n\t\t\t\t\tfor (var s in settings) {\n\t\t\t\t\t\tif (settings[s].treeId && settings[s].edit.enable && settings[s].treeId != setting.treeId\n\t\t\t\t\t\t\t&& (event.target.id == settings[s].treeId || $(event.target).parents(\"#\" + settings[s].treeId).length>0)) {\n\t\t\t\t\t\t\tisOtherTree = true;\n\t\t\t\t\t\t\ttargetSetting = settings[s];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar docScrollTop = doc.scrollTop(),\n\t\t\t\t\tdocScrollLeft = doc.scrollLeft(),\n\t\t\t\t\ttreeOffset = targetSetting.treeObj.offset(),\n\t\t\t\t\tscrollHeight = targetSetting.treeObj.get(0).scrollHeight,\n\t\t\t\t\tscrollWidth = targetSetting.treeObj.get(0).scrollWidth,\n\t\t\t\t\tdTop = (event.clientY + docScrollTop - treeOffset.top),\n\t\t\t\t\tdBottom = (targetSetting.treeObj.height() + treeOffset.top - event.clientY - docScrollTop),\n\t\t\t\t\tdLeft = (event.clientX + docScrollLeft - treeOffset.left),\n\t\t\t\t\tdRight = (targetSetting.treeObj.width() + treeOffset.left - event.clientX - docScrollLeft),\n\t\t\t\t\tisTop = (dTop < setting.edit.drag.borderMax && dTop > setting.edit.drag.borderMin),\n\t\t\t\t\tisBottom = (dBottom < setting.edit.drag.borderMax && dBottom > setting.edit.drag.borderMin),\n\t\t\t\t\tisLeft = (dLeft < setting.edit.drag.borderMax && dLeft > setting.edit.drag.borderMin),\n\t\t\t\t\tisRight = (dRight < setting.edit.drag.borderMax && dRight > setting.edit.drag.borderMin),\n\t\t\t\t\tisTreeInner = dTop > setting.edit.drag.borderMin && dBottom > setting.edit.drag.borderMin && dLeft > setting.edit.drag.borderMin && dRight > setting.edit.drag.borderMin,\n\t\t\t\t\tisTreeTop = (isTop && targetSetting.treeObj.scrollTop() <= 0),\n\t\t\t\t\tisTreeBottom = (isBottom && (targetSetting.treeObj.scrollTop() + targetSetting.treeObj.height()+10) >= scrollHeight),\n\t\t\t\t\tisTreeLeft = (isLeft && targetSetting.treeObj.scrollLeft() <= 0),\n\t\t\t\t\tisTreeRight = (isRight && (targetSetting.treeObj.scrollLeft() + targetSetting.treeObj.width()+10) >= scrollWidth);\n\n\t\t\t\t\tif (event.target && tools.isChildOrSelf(event.target, targetSetting.treeId)) {\n\t\t\t\t\t\t//get node <li> dom\n\t\t\t\t\t\tvar targetObj = event.target;\n\t\t\t\t\t\twhile (targetObj && targetObj.tagName && !tools.eqs(targetObj.tagName, \"li\") && targetObj.id != targetSetting.treeId) {\n\t\t\t\t\t\t\ttargetObj = targetObj.parentNode;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar canMove = true;\n\t\t\t\t\t\t//don't move to self or children of self\n\t\t\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\t\t\tif (targetObj.id === tmpNode.tId) {\n\t\t\t\t\t\t\t\tcanMove = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} else if ($$(tmpNode, setting).find(\"#\" + targetObj.id).length > 0) {\n\t\t\t\t\t\t\t\tcanMove = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (canMove && event.target && tools.isChildOrSelf(event.target, targetObj.id + consts.id.A)) {\n\t\t\t\t\t\t\ttmpTarget = $(targetObj);\n\t\t\t\t\t\t\ttmpTargetNodeId = targetObj.id;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t//the mouse must be in zTree\n\t\t\t\t\ttmpNode = nodes[0];\n\t\t\t\t\tif (isTreeInner && tools.isChildOrSelf(event.target, targetSetting.treeId)) {\n\t\t\t\t\t\t//judge mouse move in root of ztree\n\t\t\t\t\t\tif (!tmpTarget && (event.target.id == targetSetting.treeId || isTreeTop || isTreeBottom || isTreeLeft || isTreeRight) && (isOtherTree || (!isOtherTree && tmpNode.parentTId))) {\n\t\t\t\t\t\t\ttmpTarget = targetSetting.treeObj;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//auto scroll top\n\t\t\t\t\t\tif (isTop) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop()-10);\n\t\t\t\t\t\t} else if (isBottom)  {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop()+10);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isLeft) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()-10);\n\t\t\t\t\t\t} else if (isRight) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()+10);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//auto scroll left\n\t\t\t\t\t\tif (tmpTarget && tmpTarget != targetSetting.treeObj && tmpTarget.offset().left < targetSetting.treeObj.offset().left) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()+ tmpTarget.offset().left - targetSetting.treeObj.offset().left);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcurNode.css({\n\t\t\t\t\t\t\"top\": (event.clientY + docScrollTop + 3) + \"px\",\n\t\t\t\t\t\t\"left\": (event.clientX + docScrollLeft + 3) + \"px\"\n\t\t\t\t\t});\n\n\t\t\t\t\tvar dX = 0;\n\t\t\t\t\tvar dY = 0;\n\t\t\t\t\tif (tmpTarget && tmpTarget.attr(\"id\")!=targetSetting.treeId) {\n\t\t\t\t\t\tvar tmpTargetNode = tmpTargetNodeId == null ? null: data.getNodeCache(targetSetting, tmpTargetNodeId),\n\t\t\t\t\t\tisCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy),\n\t\t\t\t\t\tisPrev = !!(preNode && tmpTargetNodeId === preNode.tId),\n\t\t\t\t\t\tisNext = !!(nextNode && tmpTargetNodeId === nextNode.tId),\n\t\t\t\t\t\tisInner = (tmpNode.parentTId && tmpNode.parentTId == tmpTargetNodeId),\n\t\t\t\t\t\tcanPrev = (isCopy || !isNext) && tools.apply(targetSetting.edit.drag.prev, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.prev),\n\t\t\t\t\t\tcanNext = (isCopy || !isPrev) && tools.apply(targetSetting.edit.drag.next, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.next),\n\t\t\t\t\t\tcanInner = (isCopy || !isInner) && !(targetSetting.data.keep.leaf && !tmpTargetNode.isParent) && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.inner);\n\t\t\t\t\t\tif (!canPrev && !canNext && !canInner) {\n\t\t\t\t\t\t\ttmpTarget = null;\n\t\t\t\t\t\t\ttmpTargetNodeId = \"\";\n\t\t\t\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t\t\t\t\ttmpArrow.css({\n\t\t\t\t\t\t\t\t\"display\":\"none\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (window.zTreeMoveTimer) {\n\t\t\t\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar tmpTargetA = $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget),\n\t\t\t\t\t\t\ttmpNextA = tmpTargetNode.isLastNode ? null : $(\"#\" + tmpTargetNode.getNextNode().tId + consts.id.A, tmpTarget.next()),\n\t\t\t\t\t\t\ttmpTop = tmpTargetA.offset().top,\n\t\t\t\t\t\t\ttmpLeft = tmpTargetA.offset().left,\n\t\t\t\t\t\t\tprevPercent = canPrev ? (canInner ? 0.25 : (canNext ? 0.5 : 1) ) : -1,\n\t\t\t\t\t\t\tnextPercent = canNext ? (canInner ? 0.75 : (canPrev ? 0.5 : 0) ) : -1,\n\t\t\t\t\t\t\tdY_percent = (event.clientY + docScrollTop - tmpTop)/tmpTargetA.height();\n\t\t\t\t\t\t\tif ((prevPercent==1 ||dY_percent<=prevPercent && dY_percent>=-.2) && canPrev) {\n\t\t\t\t\t\t\t\tdX = 1 - tmpArrow.width();\n\t\t\t\t\t\t\t\tdY = tmpTop - tmpArrow.height()/2;\n\t\t\t\t\t\t\t\tmoveType = consts.move.TYPE_PREV;\n\t\t\t\t\t\t\t} else if ((nextPercent==0 || dY_percent>=nextPercent && dY_percent<=1.2) && canNext) {\n\t\t\t\t\t\t\t\tdX = 1 - tmpArrow.width();\n\t\t\t\t\t\t\t\tdY = (tmpNextA == null || (tmpTargetNode.isParent && tmpTargetNode.open)) ? (tmpTop + tmpTargetA.height() - tmpArrow.height()/2) : (tmpNextA.offset().top - tmpArrow.height()/2);\n\t\t\t\t\t\t\t\tmoveType = consts.move.TYPE_NEXT;\n\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\tdX = 5 - tmpArrow.width();\n\t\t\t\t\t\t\t\tdY = tmpTop;\n\t\t\t\t\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttmpArrow.css({\n\t\t\t\t\t\t\t\t\"display\":\"block\",\n\t\t\t\t\t\t\t\t\"top\": dY + \"px\",\n\t\t\t\t\t\t\t\t\"left\": (tmpLeft + dX) + \"px\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttmpTargetA.addClass(consts.node.TMPTARGET_NODE + \"_\" + moveType);\n\n\t\t\t\t\t\t\tif (preTmpTargetNodeId != tmpTargetNodeId || preTmpMoveType != moveType) {\n\t\t\t\t\t\t\t\tstartTime = (new Date()).getTime();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (tmpTargetNode && tmpTargetNode.isParent && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\t\t\t\tvar startTimer = true;\n\t\t\t\t\t\t\t\tif (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId !== tmpTargetNode.tId) {\n\t\t\t\t\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null;\n\t\t\t\t\t\t\t\t}else if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId === tmpTargetNode.tId) {\n\t\t\t\t\t\t\t\t\tstartTimer = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (startTimer) {\n\t\t\t\t\t\t\t\t\twindow.zTreeMoveTimer = setTimeout(function() {\n\t\t\t\t\t\t\t\t\t\tif (moveType != consts.move.TYPE_INNER) return;\n\t\t\t\t\t\t\t\t\t\tif (tmpTargetNode && tmpTargetNode.isParent && !tmpTargetNode.open && (new Date()).getTime() - startTime > targetSetting.edit.drag.autoOpenTime\n\t\t\t\t\t\t\t\t\t\t\t&& tools.apply(targetSetting.callback.beforeDragOpen, [targetSetting.treeId, tmpTargetNode], true)) {\n\t\t\t\t\t\t\t\t\t\t\tview.switchNode(targetSetting, tmpTargetNode);\n\t\t\t\t\t\t\t\t\t\t\tif (targetSetting.edit.drag.autoExpandTrigger) {\n\t\t\t\t\t\t\t\t\t\t\t\ttargetSetting.treeObj.trigger(consts.event.EXPAND, [targetSetting.treeId, tmpTargetNode]);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}, targetSetting.edit.drag.autoOpenTime+50);\n\t\t\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = tmpTargetNode.tId;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t\t\t\tif (tmpTarget && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, null], !!targetSetting.edit.drag.inner)) {\n\t\t\t\t\t\t\ttmpTarget.addClass(consts.node.TMPTARGET_TREE);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttmpTarget = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttmpArrow.css({\n\t\t\t\t\t\t\t\"display\":\"none\"\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (window.zTreeMoveTimer) {\n\t\t\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpreTmpTargetNodeId = tmpTargetNodeId;\n\t\t\t\t\tpreTmpMoveType = moveType;\n\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.DRAGMOVE, [event, setting.treeId, nodes]);\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tdoc.bind(\"mouseup\", _docMouseUp);\n\t\t\tfunction _docMouseUp(event) {\n\t\t\t\tif (window.zTreeMoveTimer) {\n\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null;\n\t\t\t\t}\n\t\t\t\tpreTmpTargetNodeId = null;\n\t\t\t\tpreTmpMoveType = null;\n\t\t\t\tdoc.unbind(\"mousemove\", _docMouseMove);\n\t\t\t\tdoc.unbind(\"mouseup\", _docMouseUp);\n\t\t\t\tdoc.unbind(\"selectstart\", _docSelect);\n\t\t\t\tbody.css(\"cursor\", \"auto\");\n\t\t\t\tif (tmpTarget) {\n\t\t\t\t\ttmpTarget.removeClass(consts.node.TMPTARGET_TREE);\n\t\t\t\t\tif (tmpTargetNodeId) $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + \"_\" + consts.move.TYPE_PREV)\n\t\t\t\t\t\t\t.removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_INNER);\n\t\t\t\t}\n\t\t\t\ttools.showIfameMask(setting, false);\n\n\t\t\t\troots.showHoverDom = true;\n\t\t\t\tif (root.dragFlag == 0) return;\n\t\t\t\troot.dragFlag = 0;\n\n\t\t\t\tvar i, l, tmpNode;\n\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\tif (tmpNode.isParent && root.dragNodeShowBefore[tmpNode.tId] && !tmpNode.open) {\n\t\t\t\t\t\tview.expandCollapseNode(setting, tmpNode, !tmpNode.open);\n\t\t\t\t\t\tdelete root.dragNodeShowBefore[tmpNode.tId];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (curNode) curNode.remove();\n\t\t\t\tif (tmpArrow) tmpArrow.remove();\n\n\t\t\t\tvar isCopy = ((event.ctrlKey || event.metaKey) && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy);\n\t\t\t\tif (!isCopy && tmpTarget && tmpTargetNodeId && nodes[0].parentTId && tmpTargetNodeId==nodes[0].parentTId && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\ttmpTarget = null;\n\t\t\t\t}\n\t\t\t\tif (tmpTarget) {\n\t\t\t\t\tvar dragTargetNode = tmpTargetNodeId == null ? null: data.getNodeCache(targetSetting, tmpTargetNodeId);\n\t\t\t\t\tif (tools.apply(setting.callback.beforeDrop, [targetSetting.treeId, nodes, dragTargetNode, moveType, isCopy], true) == false) {\n\t\t\t\t\t\tview.selectNodes(sourceSetting, nodes);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tvar newNodes = isCopy ? tools.clone(nodes) : nodes;\n\n\t\t\t\t\tfunction dropCallback() {\n\t\t\t\t\t\tif (isOtherTree) {\n\t\t\t\t\t\t\tif (!isCopy) {\n\t\t\t\t\t\t\t\tfor(var i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\t\t\t\tview.removeNode(setting, nodes[i]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode, newNodes);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode.getParentNode(), newNodes);\n\t\t\t\t\t\t\t\tif (moveType == consts.move.TYPE_PREV) {\n\t\t\t\t\t\t\t\t\tfor (i=0, l=newNodes.length; i<l; i++) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfor (i=-1, l=newNodes.length-1; i<l; l--) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (isCopy && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode, newNodes);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (isCopy) {\n\t\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode.getParentNode(), newNodes);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (moveType != consts.move.TYPE_NEXT) {\n\t\t\t\t\t\t\t\t\tfor (i=0, l=newNodes.length; i<l; i++) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfor (i=-1, l=newNodes.length-1; i<l; l--) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tview.selectNodes(targetSetting, newNodes);\n\t\t\t\t\t\t$$(newNodes[0], setting).focus().blur();\n\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.DROP, [event, targetSetting.treeId, newNodes, dragTargetNode, moveType, isCopy]);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (moveType == consts.move.TYPE_INNER && tools.canAsync(targetSetting, dragTargetNode)) {\n\t\t\t\t\t\tview.asyncNode(targetSetting, dragTargetNode, false, dropCallback);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdropCallback();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tview.selectNodes(sourceSetting, nodes);\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.DROP, [event, setting.treeId, nodes, null, null, null]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdoc.bind(\"selectstart\", _docSelect);\n\t\t\tfunction _docSelect() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t//Avoid FireFox's Bug\n\t\t\t//If zTree Div CSS set 'overflow', so drag node outside of zTree, and event.target is error.\n\t\t\tif(eventMouseDown.preventDefault) {\n\t\t\t\teventMouseDown.preventDefault();\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t},\n\t//method of tools for zTree\n\t_tools = {\n\t\tgetAbs: function (obj) {\n\t\t\tvar oRect = obj.getBoundingClientRect(),\n\t\t\tscrollTop = document.body.scrollTop+document.documentElement.scrollTop,\n\t\t\tscrollLeft = document.body.scrollLeft+document.documentElement.scrollLeft;\n\t\t\treturn [oRect.left+scrollLeft,oRect.top+scrollTop];\n\t\t},\n\t\tinputFocus: function(inputObj) {\n\t\t\tif (inputObj.get(0)) {\n\t\t\t\tinputObj.focus();\n\t\t\t\ttools.setCursorPosition(inputObj.get(0), inputObj.val().length);\n\t\t\t}\n\t\t},\n\t\tinputSelect: function(inputObj) {\n\t\t\tif (inputObj.get(0)) {\n\t\t\t\tinputObj.focus();\n\t\t\t\tinputObj.select();\n\t\t\t}\n\t\t},\n\t\tsetCursorPosition: function(obj, pos){\n\t\t\tif(obj.setSelectionRange) {\n\t\t\t\tobj.focus();\n\t\t\t\tobj.setSelectionRange(pos,pos);\n\t\t\t} else if (obj.createTextRange) {\n\t\t\t\tvar range = obj.createTextRange();\n\t\t\t\trange.collapse(true);\n\t\t\t\trange.moveEnd('character', pos);\n\t\t\t\trange.moveStart('character', pos);\n\t\t\t\trange.select();\n\t\t\t}\n\t\t},\n\t\tshowIfameMask: function(setting, showSign) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\t//clear full mask\n\t\t\twhile (root.dragMaskList.length > 0) {\n\t\t\t\troot.dragMaskList[0].remove();\n\t\t\t\troot.dragMaskList.shift();\n\t\t\t}\n\t\t\tif (showSign) {\n\t\t\t\t//show mask\n\t\t\t\tvar iframeList = $$(\"iframe\", setting);\n\t\t\t\tfor (var i = 0, l = iframeList.length; i < l; i++) {\n\t\t\t\t\tvar obj = iframeList.get(i),\n\t\t\t\t\tr = tools.getAbs(obj),\n\t\t\t\t\tdragMask = $$(\"<div id='zTreeMask_\" + i + \"' class='zTreeMask' style='top:\" + r[1] + \"px; left:\" + r[0] + \"px; width:\" + obj.offsetWidth + \"px; height:\" + obj.offsetHeight + \"px;'></div>\", setting);\n\t\t\t\t\tdragMask.appendTo($$(\"body\", setting));\n\t\t\t\t\troot.dragMaskList.push(dragMask);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t//method of operate ztree dom\n\t_view = {\n\t\taddEditBtn: function(setting, node) {\n\t\t\tif (node.editNameFlag || $$(node, consts.id.EDIT, setting).length > 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!tools.apply(setting.edit.showRenameBtn, [setting.treeId, node], setting.edit.showRenameBtn)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar aObj = $$(node, consts.id.A, setting),\n\t\t\teditStr = \"<span class='\" + consts.className.BUTTON + \" edit' id='\" + node.tId + consts.id.EDIT + \"' title='\"+tools.apply(setting.edit.renameTitle, [setting.treeId, node], setting.edit.renameTitle)+\"' treeNode\"+consts.id.EDIT+\" style='display:none;'></span>\";\n\t\t\taObj.append(editStr);\n\n\t\t\t$$(node, consts.id.EDIT, setting).bind('click',\n\t\t\t\tfunction() {\n\t\t\t\t\tif (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeEditName, [setting.treeId, node], true) == false) return false;\n\t\t\t\t\tview.editNode(setting, node);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t).show();\n\t\t},\n\t\taddRemoveBtn: function(setting, node) {\n\t\t\tif (node.editNameFlag || $$(node, consts.id.REMOVE, setting).length > 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!tools.apply(setting.edit.showRemoveBtn, [setting.treeId, node], setting.edit.showRemoveBtn)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar aObj = $$(node, consts.id.A, setting),\n\t\t\tremoveStr = \"<span class='\" + consts.className.BUTTON + \" remove' id='\" + node.tId + consts.id.REMOVE + \"' title='\"+tools.apply(setting.edit.removeTitle, [setting.treeId, node], setting.edit.removeTitle)+\"' treeNode\"+consts.id.REMOVE+\" style='display:none;'></span>\";\n\t\t\taObj.append(removeStr);\n\n\t\t\t$$(node, consts.id.REMOVE, setting).bind('click',\n\t\t\t\tfunction() {\n\t\t\t\t\tif (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return false;\n\t\t\t\t\tview.removeNode(setting, node);\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t).bind('mousedown',\n\t\t\t\tfunction(eventMouseDown) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t).show();\n\t\t},\n\t\taddHoverDom: function(setting, node) {\n\t\t\tif (data.getRoots().showHoverDom) {\n\t\t\t\tnode.isHover = true;\n\t\t\t\tif (setting.edit.enable) {\n\t\t\t\t\tview.addEditBtn(setting, node);\n\t\t\t\t\tview.addRemoveBtn(setting, node);\n\t\t\t\t}\n\t\t\t\ttools.apply(setting.view.addHoverDom, [setting.treeId, node]);\n\t\t\t}\n\t\t},\n\t\tcancelCurEditNode: function (setting, forceName, isCancel) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tnameKey = setting.data.key.name,\n\t\t\tnode = root.curEditNode;\n\n\t\t\tif (node) {\n\t\t\t\tvar inputObj = root.curEditInput,\n\t\t\t\tnewName = forceName ? forceName:(isCancel ? node[nameKey]: inputObj.val());\n\t\t\t\tif (tools.apply(setting.callback.beforeRename, [setting.treeId, node, newName, isCancel], true) === false) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n                node[nameKey] = newName;\n                var aObj = $$(node, consts.id.A, setting);\n\t\t\t\taObj.removeClass(consts.node.CURSELECTED_EDIT);\n\t\t\t\tinputObj.unbind();\n\t\t\t\tview.setNodeName(setting, node);\n\t\t\t\tnode.editNameFlag = false;\n\t\t\t\troot.curEditNode = null;\n\t\t\t\troot.curEditInput = null;\n\t\t\t\tview.selectNode(setting, node, false);\n                setting.treeObj.trigger(consts.event.RENAME, [setting.treeId, node, isCancel]);\n\t\t\t}\n\t\t\troot.noSelection = true;\n\t\t\treturn true;\n\t\t},\n\t\teditNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\tview.editNodeBlur = false;\n\t\t\tif (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {\n\t\t\t\tsetTimeout(function() {tools.inputFocus(root.curEditInput);}, 0);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar nameKey = setting.data.key.name;\n\t\t\tnode.editNameFlag = true;\n\t\t\tview.removeTreeDom(setting, node);\n\t\t\tview.cancelCurEditNode(setting);\n\t\t\tview.selectNode(setting, node, false);\n\t\t\t$$(node, consts.id.SPAN, setting).html(\"<input type=text class='rename' id='\" + node.tId + consts.id.INPUT + \"' treeNode\" + consts.id.INPUT + \" >\");\n\t\t\tvar inputObj = $$(node, consts.id.INPUT, setting);\n\t\t\tinputObj.attr(\"value\", node[nameKey]);\n\t\t\tif (setting.edit.editNameSelectAll) {\n\t\t\t\ttools.inputSelect(inputObj);\n\t\t\t} else {\n\t\t\t\ttools.inputFocus(inputObj);\n\t\t\t}\n\n\t\t\tinputObj.bind('blur', function(event) {\n\t\t\t\tif (!view.editNodeBlur) {\n\t\t\t\t\tview.cancelCurEditNode(setting);\n\t\t\t\t}\n\t\t\t}).bind('keydown', function(event) {\n\t\t\t\tif (event.keyCode==\"13\") {\n\t\t\t\t\tview.editNodeBlur = true;\n\t\t\t\t\tview.cancelCurEditNode(setting);\n\t\t\t\t} else if (event.keyCode==\"27\") {\n\t\t\t\t\tview.cancelCurEditNode(setting, null, true);\n\t\t\t\t}\n\t\t\t}).bind('click', function(event) {\n\t\t\t\treturn false;\n\t\t\t}).bind('dblclick', function(event) {\n\t\t\t\treturn false;\n\t\t\t});\n\n\t\t\t$$(node, consts.id.A, setting).addClass(consts.node.CURSELECTED_EDIT);\n\t\t\troot.curEditInput = inputObj;\n\t\t\troot.noSelection = false;\n\t\t\troot.curEditNode = node;\n\t\t},\n\t\tmoveNode: function(setting, targetNode, node, moveType, animateFlag, isSilent) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tif (targetNode == node) return;\n\t\t\tif (setting.data.keep.leaf && targetNode && !targetNode.isParent && moveType == consts.move.TYPE_INNER) return;\n\t\t\tvar oldParentNode = (node.parentTId ? node.getParentNode(): root),\n\t\t\ttargetNodeIsRoot = (targetNode === null || targetNode == root);\n\t\t\tif (targetNodeIsRoot && targetNode === null) targetNode = root;\n\t\t\tif (targetNodeIsRoot) moveType = consts.move.TYPE_INNER;\n\t\t\tvar targetParentNode = (targetNode.parentTId ? targetNode.getParentNode() : root);\n\n\t\t\tif (moveType != consts.move.TYPE_PREV && moveType != consts.move.TYPE_NEXT) {\n\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t}\n\n\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\tif (targetNodeIsRoot) {\n\t\t\t\t\t//parentTId of root node is null\n\t\t\t\t\tnode.parentTId = null;\n\t\t\t\t} else {\n\t\t\t\t\tif (!targetNode.isParent) {\n\t\t\t\t\t\ttargetNode.isParent = true;\n\t\t\t\t\t\ttargetNode.open = !!targetNode.open;\n\t\t\t\t\t\tview.setNodeLineIcos(setting, targetNode);\n\t\t\t\t\t}\n\t\t\t\t\tnode.parentTId = targetNode.tId;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//move node Dom\n\t\t\tvar targetObj, target_ulObj;\n\t\t\tif (targetNodeIsRoot) {\n\t\t\t\ttargetObj = setting.treeObj;\n\t\t\t\ttarget_ulObj = targetObj;\n\t\t\t} else {\n\t\t\t\tif (!isSilent && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\tview.expandCollapseNode(setting, targetNode, true, false);\n\t\t\t\t} else if (!isSilent) {\n\t\t\t\t\tview.expandCollapseNode(setting, targetNode.getParentNode(), true, false);\n\t\t\t\t}\n\t\t\t\ttargetObj = $$(targetNode, setting);\n\t\t\t\ttarget_ulObj = $$(targetNode, consts.id.UL, setting);\n\t\t\t\tif (!!targetObj.get(0) && !target_ulObj.get(0)) {\n\t\t\t\t\tvar ulstr = [];\n\t\t\t\t\tview.makeUlHtml(setting, targetNode, ulstr, '');\n\t\t\t\t\ttargetObj.append(ulstr.join(''));\n\t\t\t\t}\n\t\t\t\ttarget_ulObj = $$(targetNode, consts.id.UL, setting);\n\t\t\t}\n\t\t\tvar nodeDom = $$(node, setting);\n\t\t\tif (!nodeDom.get(0)) {\n\t\t\t\tnodeDom = view.appendNodes(setting, node.level, [node], null, false, true).join('');\n\t\t\t} else if (!targetObj.get(0)) {\n\t\t\t\tnodeDom.remove();\n\t\t\t}\n\t\t\tif (target_ulObj.get(0) && moveType == consts.move.TYPE_INNER) {\n\t\t\t\ttarget_ulObj.append(nodeDom);\n\t\t\t} else if (targetObj.get(0) && moveType == consts.move.TYPE_PREV) {\n\t\t\t\ttargetObj.before(nodeDom);\n\t\t\t} else if (targetObj.get(0) && moveType == consts.move.TYPE_NEXT) {\n\t\t\t\ttargetObj.after(nodeDom);\n\t\t\t}\n\n\t\t\t//repair the data after move\n\t\t\tvar i,l,\n\t\t\ttmpSrcIndex = -1,\n\t\t\ttmpTargetIndex = 0,\n\t\t\toldNeighbor = null,\n\t\t\tnewNeighbor = null,\n\t\t\toldLevel = node.level;\n\t\t\tif (node.isFirstNode) {\n\t\t\t\ttmpSrcIndex = 0;\n\t\t\t\tif (oldParentNode[childKey].length > 1 ) {\n\t\t\t\t\toldNeighbor = oldParentNode[childKey][1];\n\t\t\t\t\toldNeighbor.isFirstNode = true;\n\t\t\t\t}\n\t\t\t} else if (node.isLastNode) {\n\t\t\t\ttmpSrcIndex = oldParentNode[childKey].length -1;\n\t\t\t\toldNeighbor = oldParentNode[childKey][tmpSrcIndex - 1];\n\t\t\t\toldNeighbor.isLastNode = true;\n\t\t\t} else {\n\t\t\t\tfor (i = 0, l = oldParentNode[childKey].length; i < l; i++) {\n\t\t\t\t\tif (oldParentNode[childKey][i].tId == node.tId) {\n\t\t\t\t\t\ttmpSrcIndex = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tmpSrcIndex >= 0) {\n\t\t\t\toldParentNode[childKey].splice(tmpSrcIndex, 1);\n\t\t\t}\n\t\t\tif (moveType != consts.move.TYPE_INNER) {\n\t\t\t\tfor (i = 0, l = targetParentNode[childKey].length; i < l; i++) {\n\t\t\t\t\tif (targetParentNode[childKey][i].tId == targetNode.tId) tmpTargetIndex = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\tif (!targetNode[childKey]) targetNode[childKey] = new Array();\n\t\t\t\tif (targetNode[childKey].length > 0) {\n\t\t\t\t\tnewNeighbor = targetNode[childKey][targetNode[childKey].length - 1];\n\t\t\t\t\tnewNeighbor.isLastNode = false;\n\t\t\t\t}\n\t\t\t\ttargetNode[childKey].splice(targetNode[childKey].length, 0, node);\n\t\t\t\tnode.isLastNode = true;\n\t\t\t\tnode.isFirstNode = (targetNode[childKey].length == 1);\n\t\t\t} else if (targetNode.isFirstNode && moveType == consts.move.TYPE_PREV) {\n\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex, 0, node);\n\t\t\t\tnewNeighbor = targetNode;\n\t\t\t\tnewNeighbor.isFirstNode = false;\n\t\t\t\tnode.parentTId = targetNode.parentTId;\n\t\t\t\tnode.isFirstNode = true;\n\t\t\t\tnode.isLastNode = false;\n\n\t\t\t} else if (targetNode.isLastNode && moveType == consts.move.TYPE_NEXT) {\n\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);\n\t\t\t\tnewNeighbor = targetNode;\n\t\t\t\tnewNeighbor.isLastNode = false;\n\t\t\t\tnode.parentTId = targetNode.parentTId;\n\t\t\t\tnode.isFirstNode = false;\n\t\t\t\tnode.isLastNode = true;\n\n\t\t\t} else {\n\t\t\t\tif (moveType == consts.move.TYPE_PREV) {\n\t\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex, 0, node);\n\t\t\t\t} else {\n\t\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);\n\t\t\t\t}\n\t\t\t\tnode.parentTId = targetNode.parentTId;\n\t\t\t\tnode.isFirstNode = false;\n\t\t\t\tnode.isLastNode = false;\n\t\t\t}\n\t\t\tdata.fixPIdKeyValue(setting, node);\n\t\t\tdata.setSonNodeLevel(setting, node.getParentNode(), node);\n\n\t\t\t//repair node what been moved\n\t\t\tview.setNodeLineIcos(setting, node);\n\t\t\tview.repairNodeLevelClass(setting, node, oldLevel)\n\n\t\t\t//repair node's old parentNode dom\n\t\t\tif (!setting.data.keep.parent && oldParentNode[childKey].length < 1) {\n\t\t\t\t//old parentNode has no child nodes\n\t\t\t\toldParentNode.isParent = false;\n\t\t\t\toldParentNode.open = false;\n\t\t\t\tvar tmp_ulObj = $$(oldParentNode, consts.id.UL, setting),\n\t\t\t\ttmp_switchObj = $$(oldParentNode, consts.id.SWITCH, setting),\n\t\t\t\ttmp_icoObj = $$(oldParentNode, consts.id.ICON, setting);\n\t\t\t\tview.replaceSwitchClass(oldParentNode, tmp_switchObj, consts.folder.DOCU);\n\t\t\t\tview.replaceIcoClass(oldParentNode, tmp_icoObj, consts.folder.DOCU);\n\t\t\t\ttmp_ulObj.css(\"display\", \"none\");\n\n\t\t\t} else if (oldNeighbor) {\n\t\t\t\t//old neigbor node\n\t\t\t\tview.setNodeLineIcos(setting, oldNeighbor);\n\t\t\t}\n\n\t\t\t//new neigbor node\n\t\t\tif (newNeighbor) {\n\t\t\t\tview.setNodeLineIcos(setting, newNeighbor);\n\t\t\t}\n\n\t\t\t//repair checkbox / radio\n\t\t\tif (!!setting.check && setting.check.enable && view.repairChkClass) {\n\t\t\t\tview.repairChkClass(setting, oldParentNode);\n\t\t\t\tview.repairParentChkClassWithSelf(setting, oldParentNode);\n\t\t\t\tif (oldParentNode != node.parent)\n\t\t\t\t\tview.repairParentChkClassWithSelf(setting, node);\n\t\t\t}\n\n\t\t\t//expand parents after move\n\t\t\tif (!isSilent) {\n\t\t\t\tview.expandCollapseParentNode(setting, node.getParentNode(), true, animateFlag);\n\t\t\t}\n\t\t},\n\t\tremoveEditBtn: function(setting, node) {\n\t\t\t$$(node, consts.id.EDIT, setting).unbind().remove();\n\t\t},\n\t\tremoveRemoveBtn: function(setting, node) {\n\t\t\t$$(node, consts.id.REMOVE, setting).unbind().remove();\n\t\t},\n\t\tremoveTreeDom: function(setting, node) {\n\t\t\tnode.isHover = false;\n\t\t\tview.removeEditBtn(setting, node);\n\t\t\tview.removeRemoveBtn(setting, node);\n\t\t\ttools.apply(setting.view.removeHoverDom, [setting.treeId, node]);\n\t\t},\n\t\trepairNodeLevelClass: function(setting, node, oldLevel) {\n\t\t\tif (oldLevel === node.level) return;\n\t\t\tvar liObj = $$(node, setting),\n\t\t\taObj = $$(node, consts.id.A, setting),\n\t\t\tulObj = $$(node, consts.id.UL, setting),\n\t\t\toldClass = consts.className.LEVEL + oldLevel,\n\t\t\tnewClass = consts.className.LEVEL + node.level;\n\t\t\tliObj.removeClass(oldClass);\n\t\t\tliObj.addClass(newClass);\n\t\t\taObj.removeClass(oldClass);\n\t\t\taObj.addClass(newClass);\n\t\t\tulObj.removeClass(oldClass);\n\t\t\tulObj.addClass(newClass);\n\t\t},\n\t\tselectNodes : function(setting, nodes) {\n\t\t\tfor (var i=0, l=nodes.length; i<l; i++) {\n\t\t\t\tview.selectNode(setting, nodes[i], i>0);\n\t\t\t}\n\t\t}\n\t},\n\n\t_z = {\n\t\ttools: _tools,\n\t\tview: _view,\n\t\tevent: _event,\n\t\tdata: _data\n\t};\n\t$.extend(true, $.fn.zTree.consts, _consts);\n\t$.extend(true, $.fn.zTree._z, _z);\n\n\tvar zt = $.fn.zTree,\n\ttools = zt._z.tools,\n\tconsts = zt.consts,\n\tview = zt._z.view,\n\tdata = zt._z.data,\n\tevent = zt._z.event,\n\t$$ = tools.$;\n\n\tdata.exSetting(_setting);\n\tdata.addInitBind(_bindEvent);\n\tdata.addInitUnBind(_unbindEvent);\n\tdata.addInitCache(_initCache);\n\tdata.addInitNode(_initNode);\n\tdata.addInitProxy(_eventProxy);\n\tdata.addInitRoot(_initRoot);\n\tdata.addZTreeTools(_zTreeTools);\n\n\tvar _cancelPreSelectedNode = view.cancelPreSelectedNode;\n\tview.cancelPreSelectedNode = function (setting, node) {\n\t\tvar list = data.getRoot(setting).curSelectedList;\n\t\tfor (var i=0, j=list.length; i<j; i++) {\n\t\t\tif (!node || node === list[i]) {\n\t\t\t\tview.removeTreeDom(setting, list[i]);\n\t\t\t\tif (node) break;\n\t\t\t}\n\t\t}\n\t\tif (_cancelPreSelectedNode) _cancelPreSelectedNode.apply(view, arguments);\n\t}\n\n\tvar _createNodes = view.createNodes;\n\tview.createNodes = function(setting, level, nodes, parentNode) {\n\t\tif (_createNodes) {\n\t\t\t_createNodes.apply(view, arguments);\n\t\t}\n\t\tif (!nodes) return;\n\t\tif (view.repairParentChkClassWithSelf) {\n\t\t\tview.repairParentChkClassWithSelf(setting, parentNode);\n\t\t}\n\t}\n\n\tvar _makeNodeUrl = view.makeNodeUrl;\n\tview.makeNodeUrl = function(setting, node) {\n\t\treturn setting.edit.enable ? null : (_makeNodeUrl.apply(view, arguments));\n\t}\n\n\tvar _removeNode = view.removeNode;\n\tview.removeNode = function(setting, node) {\n\t\tvar root = data.getRoot(setting);\n\t\tif (root.curEditNode === node) root.curEditNode = null;\n\t\tif (_removeNode) {\n\t\t\t_removeNode.apply(view, arguments);\n\t\t}\n\t}\n\n\tvar _selectNode = view.selectNode;\n\tview.selectNode = function(setting, node, addFlag) {\n\t\tvar root = data.getRoot(setting);\n\t\tif (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {\n\t\t\treturn false;\n\t\t}\n\t\tif (_selectNode) _selectNode.apply(view, arguments);\n\t\tview.addHoverDom(setting, node);\n\t\treturn true;\n\t}\n\n\tvar _uCanDo = tools.uCanDo;\n\ttools.uCanDo = function(setting, e) {\n\t\tvar root = data.getRoot(setting);\n\t\tif (e && (tools.eqs(e.type, \"mouseover\") || tools.eqs(e.type, \"mouseout\") || tools.eqs(e.type, \"mousedown\") || tools.eqs(e.type, \"mouseup\"))) {\n\t\t\treturn true;\n\t\t}\n\t\tif (root.curEditNode) {\n\t\t\tview.editNodeBlur = false;\n\t\t\troot.curEditInput.focus();\n\t\t}\n\t\treturn (!root.curEditNode) && (_uCanDo ? _uCanDo.apply(view, arguments) : true);\n\t}\n})(jQuery);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/js/jquery.ztree.exedit.js",
    "content": "(function($){\n\t//default consts of exedit\n\tvar _consts = {\n\t\tevent: {\n\t\t\tDRAG: \"ztree_drag\",\n\t\t\tDROP: \"ztree_drop\",\n\t\t\tREMOVE: \"ztree_remove\",\n\t\t\tRENAME: \"ztree_rename\"\n\t\t},\n\t\tid: {\n\t\t\tEDIT: \"_edit\",\n\t\t\tINPUT: \"_input\",\n\t\t\tREMOVE: \"_remove\"\n\t\t},\n\t\tmove: {\n\t\t\tTYPE_INNER: \"inner\",\n\t\t\tTYPE_PREV: \"prev\",\n\t\t\tTYPE_NEXT: \"next\"\n\t\t},\n\t\tnode: {\n\t\t\tCURSELECTED_EDIT: \"curSelectedNode_Edit\",\n\t\t\tTMPTARGET_TREE: \"tmpTargetzTree\",\n\t\t\tTMPTARGET_NODE: \"tmpTargetNode\"\n\t\t}\n\t},\n\t//default setting of exedit\n\t_setting = {\n\t\tedit: {\n\t\t\tenable: false,\n\t\t\teditNameSelectAll: false,\n\t\t\tshowRemoveBtn: true,\n\t\t\tshowRenameBtn: true,\n\t\t\tremoveTitle: \"remove\",\n\t\t\trenameTitle: \"rename\",\n\t\t\tdrag: {\n\t\t\t\tautoExpandTrigger: false,\n\t\t\t\tisCopy: true,\n\t\t\t\tisMove: true,\n\t\t\t\tprev: true,\n\t\t\t\tnext: true,\n\t\t\t\tinner: true,\n\t\t\t\tminMoveSize: 5,\n\t\t\t\tborderMax: 10,\n\t\t\t\tborderMin: -5,\n\t\t\t\tmaxShowNodeNum: 5,\n\t\t\t\tautoOpenTime: 500\n\t\t\t}\n\t\t},\n\t\tview: {\n\t\t\taddHoverDom: null,\n\t\t\tremoveHoverDom: null\n\t\t},\n\t\tcallback: {\n\t\t\tbeforeDrag:null,\n\t\t\tbeforeDragOpen:null,\n\t\t\tbeforeDrop:null,\n\t\t\tbeforeEditName:null,\n\t\t\tbeforeRename:null,\n\t\t\tonDrag:null,\n\t\t\tonDrop:null,\n\t\t\tonRename:null\n\t\t}\n\t},\n\t//default root of exedit\n\t_initRoot = function (setting) {\n\t\tvar r = data.getRoot(setting);\n\t\tr.curEditNode = null;\n\t\tr.curEditInput = null;\n\t\tr.curHoverNode = null;\n\t\tr.dragFlag = 0;\n\t\tr.dragNodeShowBefore = [];\n\t\tr.dragMaskList = new Array();\n\t\tr.showHoverDom = true;\n\t},\n\t//default cache of exedit\n\t_initCache = function(treeId) {},\n\t//default bind event of exedit\n\t_bindEvent = function(setting) {\n\t\tvar o = setting.treeObj;\n\t\tvar c = consts.event;\n\t\to.bind(c.RENAME, function (event, treeId, treeNode) {\n\t\t\ttools.apply(setting.callback.onRename, [event, treeId, treeNode]);\n\t\t});\n\n\t\to.bind(c.REMOVE, function (event, treeId, treeNode) {\n\t\t\ttools.apply(setting.callback.onRemove, [event, treeId, treeNode]);\n\t\t});\n\n\t\to.bind(c.DRAG, function (event, srcEvent, treeId, treeNodes) {\n\t\t\ttools.apply(setting.callback.onDrag, [srcEvent, treeId, treeNodes]);\n\t\t});\n\n\t\to.bind(c.DROP, function (event, srcEvent, treeId, treeNodes, targetNode, moveType, isCopy) {\n\t\t\ttools.apply(setting.callback.onDrop, [srcEvent, treeId, treeNodes, targetNode, moveType, isCopy]);\n\t\t});\n\t},\n\t_unbindEvent = function(setting) {\n\t\tvar o = setting.treeObj;\n\t\tvar c = consts.event;\n\t\to.unbind(c.RENAME);\n\t\to.unbind(c.REMOVE);\n\t\to.unbind(c.DRAG);\n\t\to.unbind(c.DROP);\n\t},\n\t//default event proxy of exedit\n\t_eventProxy = function(e) {\n\t\tvar target = e.target,\n\t\tsetting = data.getSetting(e.data.treeId),\n\t\trelatedTarget = e.relatedTarget,\n\t\ttId = \"\", node = null,\n\t\tnodeEventType = \"\", treeEventType = \"\",\n\t\tnodeEventCallback = null, treeEventCallback = null,\n\t\ttmp = null;\n\n\t\tif (tools.eqs(e.type, \"mouseover\")) {\n\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (tmp) {\n\t\t\t\ttId = tmp.parentNode.id;\n\t\t\t\tnodeEventType = \"hoverOverNode\";\n\t\t\t}\n\t\t} else if (tools.eqs(e.type, \"mouseout\")) {\n\t\t\ttmp = tools.getMDom(setting, relatedTarget, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (!tmp) {\n\t\t\t\ttId = \"remove\";\n\t\t\t\tnodeEventType = \"hoverOutNode\";\n\t\t\t}\n\t\t} else if (tools.eqs(e.type, \"mousedown\")) {\n\t\t\ttmp = tools.getMDom(setting, target, [{tagName:\"a\", attrName:\"treeNode\"+consts.id.A}]);\n\t\t\tif (tmp) {\n\t\t\t\ttId = tmp.parentNode.id;\n\t\t\t\tnodeEventType = \"mousedownNode\";\n\t\t\t}\n\t\t}\n\t\tif (tId.length>0) {\n\t\t\tnode = data.getNodeCache(setting, tId);\n\t\t\tswitch (nodeEventType) {\n\t\t\t\tcase \"mousedownNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onMousedownNode;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hoverOverNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onHoverOverNode;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"hoverOutNode\" :\n\t\t\t\t\tnodeEventCallback = _handler.onHoverOutNode;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tvar proxyResult = {\n\t\t\tstop: false,\n\t\t\tnode: node,\n\t\t\tnodeEventType: nodeEventType,\n\t\t\tnodeEventCallback: nodeEventCallback,\n\t\t\ttreeEventType: treeEventType,\n\t\t\ttreeEventCallback: treeEventCallback\n\t\t};\n\t\treturn proxyResult\n\t},\n\t//default init node of exedit\n\t_initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n\t\tif (!n) return;\n\t\tn.isHover = false;\n\t\tn.editNameFlag = false;\n\t},\n\t//update zTreeObj, add method of edit\n\t_zTreeTools = function(setting, zTreeTools) {\n\t\tzTreeTools.cancelEditName = function(newName) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tnameKey = setting.data.key.name,\n\t\t\tnode = root.curEditNode;\n\t\t\tif (!root.curEditNode) return;\n\t\t\tview.cancelCurEditNode(setting, newName?newName:node[nameKey]);\n\t\t}\n\t\tzTreeTools.copyNode = function(targetNode, node, moveType, isSilent) {\n\t\t\tif (!node) return null;\n\t\t\tif (targetNode && !targetNode.isParent && setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) return null;\n\t\t\tvar newNode = tools.clone(node);\n\t\t\tif (!targetNode) {\n\t\t\t\ttargetNode = null;\n\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t}\n\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\tfunction copyCallback() {\n\t\t\t\t\tview.addNodes(setting, targetNode, [newNode], isSilent);\n\t\t\t\t}\n\n\t\t\t\tif (tools.canAsync(setting, targetNode)) {\n\t\t\t\t\tview.asyncNode(setting, targetNode, isSilent, copyCallback);\n\t\t\t\t} else {\n\t\t\t\t\tcopyCallback();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tview.addNodes(setting, targetNode.parentNode, [newNode], isSilent);\n\t\t\t\tview.moveNode(setting, targetNode, newNode, moveType, false, isSilent);\n\t\t\t}\n\t\t\treturn newNode;\n\t\t}\n\t\tzTreeTools.editName = function(node) {\n\t\t\tif (!node || !node.tId || node !== data.getNodeCache(setting, node.tId)) return;\n\t\t\tif (node.parentTId) view.expandCollapseParentNode(setting, node.getParentNode(), true);\n\t\t\tview.editNode(setting, node)\n\t\t}\n\t\tzTreeTools.moveNode = function(targetNode, node, moveType, isSilent) {\n\t\t\tif (!node) return node;\n\t\t\tif (targetNode && !targetNode.isParent && setting.data.keep.leaf && moveType === consts.move.TYPE_INNER) {\n\t\t\t\treturn null;\n\t\t\t} else if (targetNode && ((node.parentTId == targetNode.tId && moveType == consts.move.TYPE_INNER) || $(\"#\" + node.tId).find(\"#\" + targetNode.tId).length > 0)) {\n\t\t\t\treturn null;\n\t\t\t} else if (!targetNode) {\n\t\t\t\ttargetNode = null;\n\t\t\t}\n\t\t\tfunction moveCallback() {\n\t\t\t\tview.moveNode(setting, targetNode, node, moveType, false, isSilent);\n\t\t\t}\n\t\t\tif (tools.canAsync(setting, targetNode) && moveType === consts.move.TYPE_INNER) {\n\t\t\t\tview.asyncNode(setting, targetNode, isSilent, moveCallback);\n\t\t\t} else {\n\t\t\t\tmoveCallback();\n\t\t\t}\n\t\t\treturn node;\n\t\t}\n\t\tzTreeTools.setEditable = function(editable) {\n\t\t\tsetting.edit.enable = editable;\n\t\t\treturn this.refresh();\n\t\t}\n\t},\n\t//method of operate data\n\t_data = {\n\t\tsetSonNodeLevel: function(setting, parentNode, node) {\n\t\t\tif (!node) return;\n\t\t\tvar childKey = setting.data.key.children;\n\t\t\tnode.level = (parentNode)? parentNode.level + 1 : 0;\n\t\t\tif (!node[childKey]) return;\n\t\t\tfor (var i = 0, l = node[childKey].length; i < l; i++) {\n\t\t\t\tif (node[childKey][i]) data.setSonNodeLevel(setting, node, node[childKey][i]);\n\t\t\t}\n\t\t}\n\t},\n\t//method of event proxy\n\t_event = {\n\n\t},\n\t//method of event handler\n\t_handler = {\n\t\tonHoverOverNode: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\troot = data.getRoot(setting);\n\t\t\tif (root.curHoverNode != node) {\n\t\t\t\t_handler.onHoverOutNode(event);\n\t\t\t}\n\t\t\troot.curHoverNode = node;\n\t\t\tview.addHoverDom(setting, node);\n\t\t},\n\t\tonHoverOutNode: function(event, node) {\n\t\t\tvar setting = data.getSetting(event.data.treeId),\n\t\t\troot = data.getRoot(setting);\n\t\t\tif (root.curHoverNode && !data.isSelectedNode(setting, root.curHoverNode)) {\n\t\t\t\tview.removeTreeDom(setting, root.curHoverNode);\n\t\t\t\troot.curHoverNode = null;\n\t\t\t}\n\t\t},\n\t\tonMousedownNode: function(eventMouseDown, _node) {\n\t\t\tvar i,l,\n\t\t\tsetting = data.getSetting(eventMouseDown.data.treeId),\n\t\t\troot = data.getRoot(setting);\n\t\t\t//right click can't drag & drop\n\t\t\tif (eventMouseDown.button == 2 || !setting.edit.enable || (!setting.edit.drag.isCopy && !setting.edit.drag.isMove)) return true;\n\n\t\t\t//input of edit node name can't drag & drop\n\t\t\tvar target = eventMouseDown.target,\n\t\t\t_nodes = data.getRoot(setting).curSelectedList,\n\t\t\tnodes = [];\n\t\t\tif (!data.isSelectedNode(setting, _node)) {\n\t\t\t\tnodes = [_node];\n\t\t\t} else {\n\t\t\t\tfor (i=0, l=_nodes.length; i<l; i++) {\n\t\t\t\t\tif (_nodes[i].editNameFlag && tools.eqs(target.tagName, \"input\") && target.getAttribute(\"treeNode\"+consts.id.INPUT) !== null) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t\tnodes.push(_nodes[i]);\n\t\t\t\t\tif (nodes[0].parentTId !== _nodes[i].parentTId) {\n\t\t\t\t\t\tnodes = [_node];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tview.editNodeBlur = true;\n\t\t\tview.cancelCurEditNode(setting, null, true);\n\t\t\t\n\n\t\t\tvar doc = $(document), curNode, tmpArrow, tmpTarget,\n\t\t\tisOtherTree = false,\n\t\t\ttargetSetting = setting,\n\t\t\tpreNode, nextNode,\n\t\t\tpreTmpTargetNodeId = null,\n\t\t\tpreTmpMoveType = null,\n\t\t\ttmpTargetNodeId = null,\n\t\t\tmoveType = consts.move.TYPE_INNER,\n\t\t\tmouseDownX = eventMouseDown.clientX,\n\t\t\tmouseDownY = eventMouseDown.clientY,\n\t\t\tstartTime = (new Date()).getTime();\n\n\t\t\tif (tools.uCanDo(setting)) {\n\t\t\t\tdoc.bind(\"mousemove\", _docMouseMove);\n\t\t\t}\n\t\t\tfunction _docMouseMove(event) {\n\t\t\t\t//avoid start drag after click node\n\t\t\t\tif (root.dragFlag == 0 && Math.abs(mouseDownX - event.clientX) < setting.edit.drag.minMoveSize\n\t\t\t\t\t&& Math.abs(mouseDownY - event.clientY) < setting.edit.drag.minMoveSize) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tvar i, l, tmpNode, tmpDom, tmpNodes,\n\t\t\t\tchildKey = setting.data.key.children;\n\t\t\t\t$(\"body\").css(\"cursor\", \"pointer\");\n\n\t\t\t\tif (root.dragFlag == 0) {\n\t\t\t\t\tif (tools.apply(setting.callback.beforeDrag, [setting.treeId, nodes], true) == false) {\n\t\t\t\t\t\t_docMouseUp(event);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\n\t\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\tif (i==0) {\n\t\t\t\t\t\t\troot.dragNodeShowBefore = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\t\tif (tmpNode.isParent && tmpNode.open) {\n\t\t\t\t\t\t\tview.expandCollapseNode(setting, tmpNode, !tmpNode.open);\n\t\t\t\t\t\t\troot.dragNodeShowBefore[tmpNode.tId] = true;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\troot.dragNodeShowBefore[tmpNode.tId] = false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\troot.dragFlag = 1;\n\t\t\t\t\troot.showHoverDom = false;\n\t\t\t\t\ttools.showIfameMask(setting, true);\n\n\t\t\t\t\t//sort\n\t\t\t\t\tvar isOrder = true, lastIndex = -1;\n\t\t\t\t\tif (nodes.length>1) {\n\t\t\t\t\t\tvar pNodes = nodes[0].parentTId ? nodes[0].getParentNode()[childKey] : data.getNodes(setting);\n\t\t\t\t\t\ttmpNodes = [];\n\t\t\t\t\t\tfor (i=0, l=pNodes.length; i<l; i++) {\n\t\t\t\t\t\t\tif (root.dragNodeShowBefore[pNodes[i].tId] !== undefined) {\n\t\t\t\t\t\t\t\tif (isOrder && lastIndex > -1 && (lastIndex+1) !== i) {\n\t\t\t\t\t\t\t\t\tisOrder = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\ttmpNodes.push(pNodes[i]);\n\t\t\t\t\t\t\t\tlastIndex = i;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (nodes.length === tmpNodes.length) {\n\t\t\t\t\t\t\t\tnodes = tmpNodes;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (isOrder) {\n\t\t\t\t\t\tpreNode = nodes[0].getPreNode();\n\t\t\t\t\t\tnextNode = nodes[nodes.length-1].getNextNode();\n\t\t\t\t\t}\n\n\t\t\t\t\t//set node in selected\n\t\t\t\t\tcurNode = $(\"<ul class='zTreeDragUL'></ul>\");\n\t\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\t\ttmpNode.editNameFlag = false;\n\t\t\t\t\t\tview.selectNode(setting, tmpNode, i>0);\n\t\t\t\t\t\tview.removeTreeDom(setting, tmpNode);\n\n\t\t\t\t\t\ttmpDom = $(\"<li id='\"+ tmpNode.tId +\"_tmp'></li>\");\n\t\t\t\t\t\ttmpDom.append($(\"#\" + tmpNode.tId + consts.id.A).clone());\n\t\t\t\t\t\ttmpDom.css(\"padding\", \"0\");\n\t\t\t\t\t\ttmpDom.children(\"#\" + tmpNode.tId + consts.id.A).removeClass(consts.node.CURSELECTED);\n\t\t\t\t\t\tcurNode.append(tmpDom);\n\t\t\t\t\t\tif (i == setting.edit.drag.maxShowNodeNum-1) {\n\t\t\t\t\t\t\ttmpDom = $(\"<li id='\"+ tmpNode.tId +\"_moretmp'><a>  ...  </a></li>\");\n\t\t\t\t\t\t\tcurNode.append(tmpDom);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcurNode.attr(\"id\", nodes[0].tId + consts.id.UL + \"_tmp\");\n\t\t\t\t\tcurNode.addClass(setting.treeObj.attr(\"class\"));\n\t\t\t\t\tcurNode.appendTo(\"body\");\n\n\t\t\t\t\ttmpArrow = $(\"<span class='tmpzTreeMove_arrow'></span>\");\n\t\t\t\t\ttmpArrow.attr(\"id\", \"zTreeMove_arrow_tmp\");\n\t\t\t\t\ttmpArrow.appendTo(\"body\");\n\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.DRAG, [event, setting.treeId, nodes]);\n\t\t\t\t}\n\n\t\t\t\tif (root.dragFlag == 1) {\n\t\t\t\t\tif (tmpTarget && tmpArrow.attr(\"id\") == event.target.id && tmpTargetNodeId && (event.clientX + doc.scrollLeft()+2) > ($(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).offset().left)) {\n\t\t\t\t\t\tvar xT = $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget);\n\t\t\t\t\t\tevent.target = (xT.length > 0) ? xT.get(0) : event.target;\n\t\t\t\t\t} else if (tmpTarget) {\n\t\t\t\t\t\ttmpTarget.removeClass(consts.node.TMPTARGET_TREE);\n\t\t\t\t\t\tif (tmpTargetNodeId) $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + \"_\" + consts.move.TYPE_PREV)\n\t\t\t\t\t\t\t.removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_INNER);\n\t\t\t\t\t}\n\t\t\t\t\ttmpTarget = null;\n\t\t\t\t\ttmpTargetNodeId = null;\n\n\t\t\t\t\t//judge drag & drop in multi ztree\n\t\t\t\t\tisOtherTree = false;\n\t\t\t\t\ttargetSetting = setting;\n\t\t\t\t\tvar settings = data.getSettings();\n\t\t\t\t\tfor (var s in settings) {\n\t\t\t\t\t\tif (settings[s].treeId && settings[s].edit.enable && settings[s].treeId != setting.treeId\n\t\t\t\t\t\t\t&& (event.target.id == settings[s].treeId || $(event.target).parents(\"#\" + settings[s].treeId).length>0)) {\n\t\t\t\t\t\t\tisOtherTree = true;\n\t\t\t\t\t\t\ttargetSetting = settings[s];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tvar docScrollTop = doc.scrollTop(),\n\t\t\t\t\tdocScrollLeft = doc.scrollLeft(),\n\t\t\t\t\ttreeOffset = targetSetting.treeObj.offset(),\n\t\t\t\t\tscrollHeight = targetSetting.treeObj.get(0).scrollHeight,\n\t\t\t\t\tscrollWidth = targetSetting.treeObj.get(0).scrollWidth,\n\t\t\t\t\tdTop = (event.clientY + docScrollTop - treeOffset.top),\n\t\t\t\t\tdBottom = (targetSetting.treeObj.height() + treeOffset.top - event.clientY - docScrollTop),\n\t\t\t\t\tdLeft = (event.clientX + docScrollLeft - treeOffset.left),\n\t\t\t\t\tdRight = (targetSetting.treeObj.width() + treeOffset.left - event.clientX - docScrollLeft),\n\t\t\t\t\tisTop = (dTop < setting.edit.drag.borderMax && dTop > setting.edit.drag.borderMin),\n\t\t\t\t\tisBottom = (dBottom < setting.edit.drag.borderMax && dBottom > setting.edit.drag.borderMin),\n\t\t\t\t\tisLeft = (dLeft < setting.edit.drag.borderMax && dLeft > setting.edit.drag.borderMin),\n\t\t\t\t\tisRight = (dRight < setting.edit.drag.borderMax && dRight > setting.edit.drag.borderMin),\n\t\t\t\t\tisTreeInner = dTop > setting.edit.drag.borderMin && dBottom > setting.edit.drag.borderMin && dLeft > setting.edit.drag.borderMin && dRight > setting.edit.drag.borderMin,\n\t\t\t\t\tisTreeTop = (isTop && targetSetting.treeObj.scrollTop() <= 0),\n\t\t\t\t\tisTreeBottom = (isBottom && (targetSetting.treeObj.scrollTop() + targetSetting.treeObj.height()+10) >= scrollHeight),\n\t\t\t\t\tisTreeLeft = (isLeft && targetSetting.treeObj.scrollLeft() <= 0),\n\t\t\t\t\tisTreeRight = (isRight && (targetSetting.treeObj.scrollLeft() + targetSetting.treeObj.width()+10) >= scrollWidth);\n\n\t\t\t\t\tif (event.target.id && targetSetting.treeObj.find(\"#\" + event.target.id).length > 0) {\n\t\t\t\t\t\t//get node <li> dom\n\t\t\t\t\t\tvar targetObj = event.target;\n\t\t\t\t\t\twhile (targetObj && targetObj.tagName && !tools.eqs(targetObj.tagName, \"li\") && targetObj.id != targetSetting.treeId) {\n\t\t\t\t\t\t\ttargetObj = targetObj.parentNode;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tvar canMove = true;\n\t\t\t\t\t\t//don't move to self or children of self\n\t\t\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\t\t\tif (targetObj.id === tmpNode.tId) {\n\t\t\t\t\t\t\t\tcanMove = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t} else if ($(\"#\" + tmpNode.tId).find(\"#\" + targetObj.id).length > 0) {\n\t\t\t\t\t\t\t\tcanMove = false;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (canMove) {\n\t\t\t\t\t\t\tif (event.target.id &&\n\t\t\t\t\t\t\t\t(event.target.id == (targetObj.id + consts.id.A) || $(event.target).parents(\"#\" + targetObj.id + consts.id.A).length > 0)) {\n\t\t\t\t\t\t\t\ttmpTarget = $(targetObj);\n\t\t\t\t\t\t\t\ttmpTargetNodeId = targetObj.id;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t//the mouse must be in zTree\n\t\t\t\t\ttmpNode = nodes[0];\n\t\t\t\t\tif (isTreeInner && (event.target.id == targetSetting.treeId || $(event.target).parents(\"#\" + targetSetting.treeId).length>0)) {\n\t\t\t\t\t\t//judge mouse move in root of ztree\n\t\t\t\t\t\tif (!tmpTarget && (event.target.id == targetSetting.treeId || isTreeTop || isTreeBottom || isTreeLeft || isTreeRight) && (isOtherTree || (!isOtherTree && tmpNode.parentTId))) {\n\t\t\t\t\t\t\ttmpTarget = targetSetting.treeObj;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//auto scroll top\n\t\t\t\t\t\tif (isTop) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop()-10);\n\t\t\t\t\t\t} else if (isBottom)  {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollTop(targetSetting.treeObj.scrollTop()+10);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (isLeft) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()-10);\n\t\t\t\t\t\t} else if (isRight) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()+10);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t//auto scroll left\n\t\t\t\t\t\tif (tmpTarget && tmpTarget != targetSetting.treeObj && tmpTarget.offset().left < targetSetting.treeObj.offset().left) {\n\t\t\t\t\t\t\ttargetSetting.treeObj.scrollLeft(targetSetting.treeObj.scrollLeft()+ tmpTarget.offset().left - targetSetting.treeObj.offset().left);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tcurNode.css({\n\t\t\t\t\t\t\"top\": (event.clientY + docScrollTop + 3) + \"px\",\n\t\t\t\t\t\t\"left\": (event.clientX + docScrollLeft + 3) + \"px\"\n\t\t\t\t\t});\n\n\t\t\t\t\tvar dX = 0;\n\t\t\t\t\tvar dY = 0;\n\t\t\t\t\tif (tmpTarget && tmpTarget.attr(\"id\")!=targetSetting.treeId) {\n\t\t\t\t\t\tvar tmpTargetNode = tmpTargetNodeId == null ? null: data.getNodeCache(targetSetting, tmpTargetNodeId),\n\t\t\t\t\t\tisCopy = (event.ctrlKey && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy),\n\t\t\t\t\t\tisPrev = !!(preNode && tmpTargetNodeId === preNode.tId),\n\t\t\t\t\t\tisNext = !!(nextNode && tmpTargetNodeId === nextNode.tId),\n\t\t\t\t\t\tisInner = (tmpNode.parentTId && tmpNode.parentTId == tmpTargetNodeId),\n\t\t\t\t\t\tcanPrev = (isCopy || !isNext) && tools.apply(targetSetting.edit.drag.prev, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.prev),\n\t\t\t\t\t\tcanNext = (isCopy || !isPrev) && tools.apply(targetSetting.edit.drag.next, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.next),\n\t\t\t\t\t\tcanInner = (isCopy || !isInner) && !(targetSetting.data.keep.leaf && !tmpTargetNode.isParent) && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, tmpTargetNode], !!targetSetting.edit.drag.inner);\n\t\t\t\t\t\tif (!canPrev && !canNext && !canInner) {\n\t\t\t\t\t\t\ttmpTarget = null;\n\t\t\t\t\t\t\ttmpTargetNodeId = \"\";\n\t\t\t\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t\t\t\t\ttmpArrow.css({\n\t\t\t\t\t\t\t\t\"display\":\"none\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (window.zTreeMoveTimer) {\n\t\t\t\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar tmpTargetA = $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget),\n\t\t\t\t\t\t\ttmpNextA = tmpTargetNode.isLastNode ? null : $(\"#\" + tmpTargetNode.getNextNode().tId + consts.id.A, tmpTarget.next()),\n\t\t\t\t\t\t\ttmpTop = tmpTargetA.offset().top,\n\t\t\t\t\t\t\ttmpLeft = tmpTargetA.offset().left,\n\t\t\t\t\t\t\tprevPercent = canPrev ? (canInner ? 0.25 : (canNext ? 0.5 : 1) ) : -1,\n\t\t\t\t\t\t\tnextPercent = canNext ? (canInner ? 0.75 : (canPrev ? 0.5 : 0) ) : -1,\n\t\t\t\t\t\t\tdY_percent = (event.clientY + docScrollTop - tmpTop)/tmpTargetA.height();\n\t\t\t\t\t\t\tif ((prevPercent==1 ||dY_percent<=prevPercent && dY_percent>=-.2) && canPrev) {\n\t\t\t\t\t\t\t\tdX = 1 - tmpArrow.width();\n\t\t\t\t\t\t\t\tdY = tmpTop - tmpArrow.height()/2;\n\t\t\t\t\t\t\t\tmoveType = consts.move.TYPE_PREV;\n\t\t\t\t\t\t\t} else if ((nextPercent==0 || dY_percent>=nextPercent && dY_percent<=1.2) && canNext) {\n\t\t\t\t\t\t\t\tdX = 1 - tmpArrow.width();\n\t\t\t\t\t\t\t\tdY = (tmpNextA == null || (tmpTargetNode.isParent && tmpTargetNode.open)) ? (tmpTop + tmpTargetA.height() - tmpArrow.height()/2) : (tmpNextA.offset().top - tmpArrow.height()/2);\n\t\t\t\t\t\t\t\tmoveType = consts.move.TYPE_NEXT;\n\t\t\t\t\t\t\t}else {\n\t\t\t\t\t\t\t\tdX = 5 - tmpArrow.width();\n\t\t\t\t\t\t\t\tdY = tmpTop;\n\t\t\t\t\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\ttmpArrow.css({\n\t\t\t\t\t\t\t\t\"display\":\"block\",\n\t\t\t\t\t\t\t\t\"top\": dY + \"px\",\n\t\t\t\t\t\t\t\t\"left\": (tmpLeft + dX) + \"px\"\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\ttmpTargetA.addClass(consts.node.TMPTARGET_NODE + \"_\" + moveType);\n\n\t\t\t\t\t\t\tif (preTmpTargetNodeId != tmpTargetNodeId || preTmpMoveType != moveType) {\n\t\t\t\t\t\t\t\tstartTime = (new Date()).getTime();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (tmpTargetNode && tmpTargetNode.isParent && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\t\t\t\tvar startTimer = true;\n\t\t\t\t\t\t\t\tif (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId !== tmpTargetNode.tId) {\n\t\t\t\t\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null;\n\t\t\t\t\t\t\t\t} else if (window.zTreeMoveTimer && window.zTreeMoveTargetNodeTId === tmpTargetNode.tId) {\n\t\t\t\t\t\t\t\t\tstartTimer = false;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (startTimer) {\n\t\t\t\t\t\t\t\t\twindow.zTreeMoveTimer = setTimeout(function() {\n\t\t\t\t\t\t\t\t\t\tif (moveType != consts.move.TYPE_INNER) return;\n\t\t\t\t\t\t\t\t\t\tif (tmpTargetNode && tmpTargetNode.isParent && !tmpTargetNode.open && (new Date()).getTime() - startTime > targetSetting.edit.drag.autoOpenTime\n\t\t\t\t\t\t\t\t\t\t\t&& tools.apply(targetSetting.callback.beforeDragOpen, [targetSetting.treeId, tmpTargetNode], true)) {\n\t\t\t\t\t\t\t\t\t\t\tview.switchNode(targetSetting, tmpTargetNode);\n\t\t\t\t\t\t\t\t\t\t\tif (targetSetting.edit.drag.autoExpandTrigger) {\n\t\t\t\t\t\t\t\t\t\t\t\ttargetSetting.treeObj.trigger(consts.event.EXPAND, [targetSetting.treeId, tmpTargetNode]);\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}, targetSetting.edit.drag.autoOpenTime+50);\n\t\t\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = tmpTargetNode.tId;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t\t\t\tif (tmpTarget && tools.apply(targetSetting.edit.drag.inner, [targetSetting.treeId, nodes, null], !!targetSetting.edit.drag.inner)) {\n\t\t\t\t\t\t\ttmpTarget.addClass(consts.node.TMPTARGET_TREE);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttmpTarget = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttmpArrow.css({\n\t\t\t\t\t\t\t\"display\":\"none\"\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (window.zTreeMoveTimer) {\n\t\t\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpreTmpTargetNodeId = tmpTargetNodeId;\n\t\t\t\t\tpreTmpMoveType = moveType;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tdoc.bind(\"mouseup\", _docMouseUp);\n\t\t\tfunction _docMouseUp(event) {\n\t\t\t\tif (window.zTreeMoveTimer) {\n\t\t\t\t\tclearTimeout(window.zTreeMoveTimer);\n\t\t\t\t\twindow.zTreeMoveTargetNodeTId = null;\n\t\t\t\t}\n\t\t\t\tpreTmpTargetNodeId = null;\n\t\t\t\tpreTmpMoveType = null;\n\t\t\t\tdoc.unbind(\"mousemove\", _docMouseMove);\n\t\t\t\tdoc.unbind(\"mouseup\", _docMouseUp);\n\t\t\t\tdoc.unbind(\"selectstart\", _docSelect);\n\t\t\t\t$(\"body\").css(\"cursor\", \"auto\");\n\t\t\t\tif (tmpTarget) {\n\t\t\t\t\ttmpTarget.removeClass(consts.node.TMPTARGET_TREE);\n\t\t\t\t\tif (tmpTargetNodeId) $(\"#\" + tmpTargetNodeId + consts.id.A, tmpTarget).removeClass(consts.node.TMPTARGET_NODE + \"_\" + consts.move.TYPE_PREV)\n\t\t\t\t\t\t\t.removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_NEXT).removeClass(consts.node.TMPTARGET_NODE + \"_\" + _consts.move.TYPE_INNER);\n\t\t\t\t}\n\t\t\t\ttools.showIfameMask(setting, false);\n\n\t\t\t\troot.showHoverDom = true;\n\t\t\t\tif (root.dragFlag == 0) return;\n\t\t\t\troot.dragFlag = 0;\n\n\t\t\t\tvar i, l, tmpNode;\n\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\ttmpNode = nodes[i];\n\t\t\t\t\tif (tmpNode.isParent && root.dragNodeShowBefore[tmpNode.tId] && !tmpNode.open) {\n\t\t\t\t\t\tview.expandCollapseNode(setting, tmpNode, !tmpNode.open);\n\t\t\t\t\t\tdelete root.dragNodeShowBefore[tmpNode.tId];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (curNode) curNode.remove();\n\t\t\t\tif (tmpArrow) tmpArrow.remove();\n\n\t\t\t\tvar isCopy = (event.ctrlKey && setting.edit.drag.isMove && setting.edit.drag.isCopy) || (!setting.edit.drag.isMove && setting.edit.drag.isCopy);\n\t\t\t\tif (!isCopy && tmpTarget && tmpTargetNodeId && nodes[0].parentTId && tmpTargetNodeId==nodes[0].parentTId && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\ttmpTarget = null;\n\t\t\t\t}\n\t\t\t\tif (tmpTarget) {\n\t\t\t\t\tvar dragTargetNode = tmpTargetNodeId == null ? null: data.getNodeCache(targetSetting, tmpTargetNodeId);\n\t\t\t\t\tif (tools.apply(setting.callback.beforeDrop, [targetSetting.treeId, nodes, dragTargetNode, moveType, isCopy], true) == false) return;\n\t\t\t\t\tvar newNodes = isCopy ? tools.clone(nodes) : nodes;\n\t\t\t\t\t\n\t\t\t\t\tfunction dropCallback() {\n\t\t\t\t\t\tif (isOtherTree) {\t\t\t\t\t\t\t\n\t\t\t\t\t\t\tif (!isCopy) {\n\t\t\t\t\t\t\t\tfor(var i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\t\t\t\tview.removeNode(setting, nodes[i]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode, newNodes);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode.getParentNode(), newNodes);\n\t\t\t\t\t\t\t\tif (moveType == consts.move.TYPE_PREV) {\n\t\t\t\t\t\t\t\t\tfor (i=0, l=newNodes.length; i<l; i++) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfor (i=-1, l=newNodes.length-1; i<l; l--) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif (isCopy && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode, newNodes);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tif (isCopy) {\n\t\t\t\t\t\t\t\t\tview.addNodes(targetSetting, dragTargetNode.getParentNode(), newNodes);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif (moveType != consts.move.TYPE_NEXT) {\n\t\t\t\t\t\t\t\t\tfor (i=0, l=newNodes.length; i<l; i++) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[i], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tfor (i=-1, l=newNodes.length-1; i<l; l--) {\n\t\t\t\t\t\t\t\t\t\tview.moveNode(targetSetting, dragTargetNode, newNodes[l], moveType, false);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tfor (i=0, l=newNodes.length; i<l; i++) {\n\t\t\t\t\t\t\tview.selectNode(targetSetting, newNodes[i], i>0);\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$(\"#\" + newNodes[0].tId).focus().blur();\n\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.DROP, [event, targetSetting.treeId, newNodes, dragTargetNode, moveType, isCopy]);\n\t\t\t\t\t}\n\n\t\t\t\t\tif (moveType == consts.move.TYPE_INNER && tools.canAsync(targetSetting, dragTargetNode)) {\n\t\t\t\t\t\tview.asyncNode(targetSetting, dragTargetNode, false, dropCallback);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdropCallback();\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\t\t\t\t\tfor (i=0, l=nodes.length; i<l; i++) {\n\t\t\t\t\t\tview.selectNode(targetSetting, nodes[i], i>0);\n\t\t\t\t\t}\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.DROP, [event, setting.treeId, nodes, null, null, null]);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdoc.bind(\"selectstart\", _docSelect);\n\t\t\tfunction _docSelect() {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t//Avoid FireFox's Bug\n\t\t\t//If zTree Div CSS set 'overflow', so drag node outside of zTree, and event.target is error.\n\t\t\tif(eventMouseDown.preventDefault) {\n\t\t\t\teventMouseDown.preventDefault();\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t},\n\t//method of tools for zTree\n\t_tools = {\n\t\tgetAbs: function (obj) {\n\t\t\tvar oRect = obj.getBoundingClientRect();\n\t\t\treturn [oRect.left,oRect.top]\n\t\t},\n\t\tinputFocus: function(inputObj) {\n\t\t\tif (inputObj.get(0)) {\n\t\t\t\tinputObj.focus();\n\t\t\t\ttools.setCursorPosition(inputObj.get(0), inputObj.val().length);\n\t\t\t}\n\t\t},\n\t\tinputSelect: function(inputObj) {\n\t\t\tif (inputObj.get(0)) {\n\t\t\t\tinputObj.focus();\n\t\t\t\tinputObj.select();\n\t\t\t}\n\t\t},\n\t\tsetCursorPosition: function(obj, pos){\n\t\t\tif(obj.setSelectionRange) {\n\t\t\t\tobj.focus();\n\t\t\t\tobj.setSelectionRange(pos,pos);\n\t\t\t} else if (obj.createTextRange) {\n\t\t\t\tvar range = obj.createTextRange();\n\t\t\t\trange.collapse(true);\n\t\t\t\trange.moveEnd('character', pos);\n\t\t\t\trange.moveStart('character', pos);\n\t\t\t\trange.select();\n\t\t\t}\n\t\t},\n\t\tshowIfameMask: function(setting, showSign) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\t//clear full mask\n\t\t\twhile (root.dragMaskList.length > 0) {\n\t\t\t\troot.dragMaskList[0].remove();\n\t\t\t\troot.dragMaskList.shift();\n\t\t\t}\n\t\t\tif (showSign) {\n\t\t\t\t//show mask\n\t\t\t\tvar iframeList = $(\"iframe\");\n\t\t\t\tfor (var i = 0, l = iframeList.length; i < l; i++) {\n\t\t\t\t\tvar obj = iframeList.get(i),\n\t\t\t\t\tr = tools.getAbs(obj),\n\t\t\t\t\tdragMask = $(\"<div id='zTreeMask_\" + i + \"' class='zTreeMask' style='top:\" + r[1] + \"px; left:\" + r[0] + \"px; width:\" + obj.offsetWidth + \"px; height:\" + obj.offsetHeight + \"px;'></div>\");\n\t\t\t\t\tdragMask.appendTo(\"body\");\n\t\t\t\t\troot.dragMaskList.push(dragMask);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t//method of operate ztree dom\n\t_view = {\n\t\taddEditBtn: function(setting, node) {\n\t\t\tif (node.editNameFlag || $(\"#\" + node.tId + consts.id.EDIT).length > 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!tools.apply(setting.edit.showRenameBtn, [setting.treeId, node], setting.edit.showRenameBtn)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar aObj = $(\"#\" + node.tId + consts.id.A),\n\t\t\teditStr = \"<span class='button edit' id='\" + node.tId + consts.id.EDIT + \"' title='\"+tools.apply(setting.edit.renameTitle, [setting.treeId, node], setting.edit.renameTitle)+\"' treeNode\"+consts.id.EDIT+\" style='display:none;'></span>\";\n\t\t\taObj.append(editStr);\n\n\t\t\t$(\"#\" + node.tId + consts.id.EDIT).bind('click',\n\t\t\t\tfunction() {\n\t\t\t\t\tif (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeEditName, [setting.treeId, node], true) == false) return false;\n\t\t\t\t\tview.editNode(setting, node);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t).show();\n\t\t},\n\t\taddRemoveBtn: function(setting, node) {\n\t\t\tif (node.editNameFlag || $(\"#\" + node.tId + consts.id.REMOVE).length > 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!tools.apply(setting.edit.showRemoveBtn, [setting.treeId, node], setting.edit.showRemoveBtn)) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar aObj = $(\"#\" + node.tId + consts.id.A),\n\t\t\tremoveStr = \"<span class='button remove' id='\" + node.tId + consts.id.REMOVE + \"' title='\"+tools.apply(setting.edit.removeTitle, [setting.treeId, node], setting.edit.removeTitle)+\"' treeNode\"+consts.id.REMOVE+\" style='display:none;'></span>\";\n\t\t\taObj.append(removeStr);\n\n\t\t\t$(\"#\" + node.tId + consts.id.REMOVE).bind('click',\n\t\t\t\tfunction() {\n\t\t\t\t\tif (!tools.uCanDo(setting) || tools.apply(setting.callback.beforeRemove, [setting.treeId, node], true) == false) return false;\n\t\t\t\t\tview.removeNode(setting, node);\n\t\t\t\t\tsetting.treeObj.trigger(consts.event.REMOVE, [setting.treeId, node]);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\t).bind('mousedown',\n\t\t\t\tfunction(eventMouseDown) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\t).show();\n\t\t},\n\t\taddHoverDom: function(setting, node) {\n\t\t\tif (data.getRoot(setting).showHoverDom) {\n\t\t\t\tnode.isHover = true;\n\t\t\t\tif (setting.edit.enable) {\n\t\t\t\t\tview.addEditBtn(setting, node);\n\t\t\t\t\tview.addRemoveBtn(setting, node);\n\t\t\t\t}\n\t\t\t\ttools.apply(setting.view.addHoverDom, [setting.treeId, node]);\n\t\t\t}\n\t\t},\n\t\tcancelCurEditNode: function (setting, forceName) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tnameKey = setting.data.key.name,\n\t\t\tnode = root.curEditNode;\n\t\t\t\n\t\t\tif (node) {\n\t\t\t\tvar inputObj = root.curEditInput;\n\t\t\t\tvar newName = forceName ? forceName:inputObj.val();\n\t\t\t\tif (!forceName && tools.apply(setting.callback.beforeRename, [setting.treeId, node, newName], true) === false) {\n\t\t\t\t\treturn false;\n\t\t\t\t} else {\n\t\t\t\t\tnode[nameKey] = newName ? newName:inputObj.val();\n\t\t\t\t\tif (!forceName) {\n\t\t\t\t\t\tsetting.treeObj.trigger(consts.event.RENAME, [setting.treeId, node]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvar aObj = $(\"#\" + node.tId + consts.id.A);\n\t\t\t\taObj.removeClass(consts.node.CURSELECTED_EDIT);\n\t\t\t\tinputObj.unbind();\n\t\t\t\tview.setNodeName(setting, node);\n\t\t\t\tnode.editNameFlag = false;\n\t\t\t\troot.curEditNode = null;\n\t\t\t\troot.curEditInput = null;\n\t\t\t\tview.selectNode(setting, node, false);\n\t\t\t}\n\t\t\troot.noSelection = true;\n\t\t\treturn true;\n\t\t},\n\t\teditNode: function(setting, node) {\n\t\t\tvar root = data.getRoot(setting);\n\t\t\tview.editNodeBlur = false;\n\t\t\tif (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {\n\t\t\t\tsetTimeout(function() {tools.inputFocus(root.curEditInput);}, 0);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar nameKey = setting.data.key.name;\n\t\t\tnode.editNameFlag = true;\n\t\t\tview.removeTreeDom(setting, node);\n\t\t\tview.cancelCurEditNode(setting);\n\t\t\tview.selectNode(setting, node, false);\n\t\t\t$(\"#\" + node.tId + consts.id.SPAN).html(\"<input type=text class='rename' id='\" + node.tId + consts.id.INPUT + \"' treeNode\" + consts.id.INPUT + \" >\");\n\t\t\tvar inputObj = $(\"#\" + node.tId + consts.id.INPUT);\n\t\t\tinputObj.attr(\"value\", node[nameKey]);\n\t\t\tif (setting.edit.editNameSelectAll) {\n\t\t\t\ttools.inputSelect(inputObj);\n\t\t\t} else {\n\t\t\t\ttools.inputFocus(inputObj);\n\t\t\t}\n\n\t\t\tinputObj.bind('blur', function(event) {\n\t\t\t\tif (!view.editNodeBlur) {\n\t\t\t\t\tview.cancelCurEditNode(setting);\n\t\t\t\t}\n\t\t\t}).bind('keydown', function(event) {\n\t\t\t\tif (event.keyCode==\"13\") {\n\t\t\t\t\tview.editNodeBlur = true;\n\t\t\t\t\tview.cancelCurEditNode(setting, null, true);\n\t\t\t\t} else if (event.keyCode==\"27\") {\n\t\t\t\t\tview.cancelCurEditNode(setting, node[nameKey]);\n\t\t\t\t}\n\t\t\t}).bind('click', function(event) {\n\t\t\t\treturn false;\n\t\t\t}).bind('dblclick', function(event) {\n\t\t\t\treturn false;\n\t\t\t});\n\n\t\t\t$(\"#\" + node.tId + consts.id.A).addClass(consts.node.CURSELECTED_EDIT);\n\t\t\troot.curEditInput = inputObj;\n\t\t\troot.noSelection = false;\n\t\t\troot.curEditNode = node;\n\t\t},\n\t\tmoveNode: function(setting, targetNode, node, moveType, animateFlag, isSilent) {\n\t\t\tvar root = data.getRoot(setting),\n\t\t\tchildKey = setting.data.key.children;\n\t\t\tif (targetNode == node) return;\n\t\t\tif (setting.data.keep.leaf && targetNode && !targetNode.isParent && moveType == consts.move.TYPE_INNER) return;\n\t\t\tvar oldParentNode = (node.parentTId ? node.getParentNode(): root),\n\t\t\ttargetNodeIsRoot = (targetNode === null || targetNode == root);\n\t\t\tif (targetNodeIsRoot && targetNode === null) targetNode = root;\n\t\t\tif (targetNodeIsRoot) moveType = consts.move.TYPE_INNER;\n\t\t\tvar targetParentNode = (targetNode.parentTId ? targetNode.getParentNode() : root);\n\n\t\t\tif (moveType != consts.move.TYPE_PREV && moveType != consts.move.TYPE_NEXT) {\n\t\t\t\tmoveType = consts.move.TYPE_INNER;\n\t\t\t}\n\t\t\t\n\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\tif (targetNodeIsRoot) {\n\t\t\t\t\t//parentTId of root node is null\n\t\t\t\t\tnode.parentTId = null;\n\t\t\t\t} else {\n\t\t\t\t\tif (!targetNode.isParent) {\n\t\t\t\t\t\ttargetNode.isParent = true;\n\t\t\t\t\t\ttargetNode.open = !!targetNode.open;\n\t\t\t\t\t\tview.setNodeLineIcos(setting, targetNode);\n\t\t\t\t\t}\n\t\t\t\t\tnode.parentTId = targetNode.tId;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t//move node Dom\n\t\t\tvar targetObj, target_ulObj;\n\t\t\tif (targetNodeIsRoot) {\n\t\t\t\ttargetObj = setting.treeObj;\n\t\t\t\ttarget_ulObj = targetObj;\n\t\t\t} else {\n\t\t\t\tif (!isSilent && moveType == consts.move.TYPE_INNER) {\n\t\t\t\t\tview.expandCollapseNode(setting, targetNode, true, false);\n\t\t\t\t} else if (!isSilent) {\n\t\t\t\t\tview.expandCollapseNode(setting, targetNode.getParentNode(), true, false);\n\t\t\t\t}\n\t\t\t\ttargetObj = $(\"#\" + targetNode.tId);\n\t\t\t\ttarget_ulObj = $(\"#\" + targetNode.tId + consts.id.UL);\n\t\t\t\tif (!!targetObj.get(0) && !target_ulObj.get(0)) {\n\t\t\t\t\tvar ulstr = [];\n\t\t\t\t\tview.makeUlHtml(setting, targetNode, ulstr, '');\n\t\t\t\t\ttargetObj.append(ulstr.join(''));\n\t\t\t\t}\n\t\t\t\ttarget_ulObj = $(\"#\" + targetNode.tId + consts.id.UL);\n\t\t\t}\n\t\t\tvar nodeDom = $(\"#\" + node.tId);\n\t\t\tif (!nodeDom.get(0)) {\n\t\t\t\tnodeDom = view.appendNodes(setting, node.level, [node], null, false, true).join('');\n\t\t\t} else if (!targetObj.get(0)) {\n\t\t\t\tnodeDom.remove();\n\t\t\t}\n\t\t\tif (target_ulObj.get(0) && moveType == consts.move.TYPE_INNER) {\n\t\t\t\ttarget_ulObj.append(nodeDom);\n\t\t\t} else if (targetObj.get(0) && moveType == consts.move.TYPE_PREV) {\n\t\t\t\ttargetObj.before(nodeDom);\n\t\t\t} else if (targetObj.get(0) && moveType == consts.move.TYPE_NEXT) {\n\t\t\t\ttargetObj.after(nodeDom);\n\t\t\t}\n\n\t\t\t//repair the data after move\n\t\t\tvar i,l,\n\t\t\ttmpSrcIndex = -1,\n\t\t\ttmpTargetIndex = 0,\n\t\t\toldNeighbor = null,\n\t\t\tnewNeighbor = null,\n\t\t\toldLevel = node.level;\n\t\t\tif (node.isFirstNode) {\n\t\t\t\ttmpSrcIndex = 0;\n\t\t\t\tif (oldParentNode[childKey].length > 1 ) {\n\t\t\t\t\toldNeighbor = oldParentNode[childKey][1];\n\t\t\t\t\toldNeighbor.isFirstNode = true;\n\t\t\t\t}\n\t\t\t} else if (node.isLastNode) {\n\t\t\t\ttmpSrcIndex = oldParentNode[childKey].length -1;\n\t\t\t\toldNeighbor = oldParentNode[childKey][tmpSrcIndex - 1];\n\t\t\t\toldNeighbor.isLastNode = true;\n\t\t\t} else {\n\t\t\t\tfor (i = 0, l = oldParentNode[childKey].length; i < l; i++) {\n\t\t\t\t\tif (oldParentNode[childKey][i].tId == node.tId) {\n\t\t\t\t\t\ttmpSrcIndex = i;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (tmpSrcIndex >= 0) {\n\t\t\t\toldParentNode[childKey].splice(tmpSrcIndex, 1);\n\t\t\t}\n\t\t\tif (moveType != consts.move.TYPE_INNER) {\n\t\t\t\tfor (i = 0, l = targetParentNode[childKey].length; i < l; i++) {\n\t\t\t\t\tif (targetParentNode[childKey][i].tId == targetNode.tId) tmpTargetIndex = i;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (moveType == consts.move.TYPE_INNER) {\n\t\t\t\tif (!targetNode[childKey]) targetNode[childKey] = new Array();\n\t\t\t\tif (targetNode[childKey].length > 0) {\n\t\t\t\t\tnewNeighbor = targetNode[childKey][targetNode[childKey].length - 1];\n\t\t\t\t\tnewNeighbor.isLastNode = false;\n\t\t\t\t}\n\t\t\t\ttargetNode[childKey].splice(targetNode[childKey].length, 0, node);\n\t\t\t\tnode.isLastNode = true;\n\t\t\t\tnode.isFirstNode = (targetNode[childKey].length == 1);\n\t\t\t} else if (targetNode.isFirstNode && moveType == consts.move.TYPE_PREV) {\n\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex, 0, node);\n\t\t\t\tnewNeighbor = targetNode;\n\t\t\t\tnewNeighbor.isFirstNode = false;\n\t\t\t\tnode.parentTId = targetNode.parentTId;\n\t\t\t\tnode.isFirstNode = true;\n\t\t\t\tnode.isLastNode = false;\n\n\t\t\t} else if (targetNode.isLastNode && moveType == consts.move.TYPE_NEXT) {\n\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);\n\t\t\t\tnewNeighbor = targetNode;\n\t\t\t\tnewNeighbor.isLastNode = false;\n\t\t\t\tnode.parentTId = targetNode.parentTId;\n\t\t\t\tnode.isFirstNode = false;\n\t\t\t\tnode.isLastNode = true;\n\n\t\t\t} else {\n\t\t\t\tif (moveType == consts.move.TYPE_PREV) {\n\t\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex, 0, node);\n\t\t\t\t} else {\n\t\t\t\t\ttargetParentNode[childKey].splice(tmpTargetIndex + 1, 0, node);\n\t\t\t\t}\n\t\t\t\tnode.parentTId = targetNode.parentTId;\n\t\t\t\tnode.isFirstNode = false;\n\t\t\t\tnode.isLastNode = false;\n\t\t\t}\n\t\t\tdata.fixPIdKeyValue(setting, node);\n\t\t\tdata.setSonNodeLevel(setting, node.getParentNode(), node);\n\n\t\t\t//repair node what been moved\n\t\t\tview.setNodeLineIcos(setting, node);\n\t\t\tview.repairNodeLevelClass(setting, node, oldLevel)\n\n\t\t\t//repair node's old parentNode dom\n\t\t\tif (!setting.data.keep.parent && oldParentNode[childKey].length < 1) {\n\t\t\t\t//old parentNode has no child nodes\n\t\t\t\toldParentNode.isParent = false;\n\t\t\t\toldParentNode.open = false;\n\t\t\t\tvar tmp_ulObj = $(\"#\" + oldParentNode.tId + consts.id.UL),\n\t\t\t\ttmp_switchObj = $(\"#\" + oldParentNode.tId + consts.id.SWITCH),\n\t\t\t\ttmp_icoObj = $(\"#\" + oldParentNode.tId + consts.id.ICON);\n\t\t\t\tview.replaceSwitchClass(oldParentNode, tmp_switchObj, consts.folder.DOCU);\n\t\t\t\tview.replaceIcoClass(oldParentNode, tmp_icoObj, consts.folder.DOCU);\n\t\t\t\ttmp_ulObj.css(\"display\", \"none\");\n\n\t\t\t} else if (oldNeighbor) {\n\t\t\t\t//old neigbor node\n\t\t\t\tview.setNodeLineIcos(setting, oldNeighbor);\n\t\t\t}\n\n\t\t\t//new neigbor node\n\t\t\tif (newNeighbor) {\n\t\t\t\tview.setNodeLineIcos(setting, newNeighbor);\n\t\t\t}\n\n\t\t\t//repair checkbox / radio\n\t\t\tif (!!setting.check && setting.check.enable && view.repairChkClass) {\n\t\t\t\tview.repairChkClass(setting, oldParentNode);\n\t\t\t\tview.repairParentChkClassWithSelf(setting, oldParentNode);\n\t\t\t\tif (oldParentNode != node.parent)\n\t\t\t\t\tview.repairParentChkClassWithSelf(setting, node);\n\t\t\t}\n\n\t\t\t//expand parents after move\n\t\t\tif (!isSilent) {\n\t\t\t\tview.expandCollapseParentNode(setting, node.getParentNode(), true, animateFlag);\n\t\t\t}\n\t\t},\n\t\tremoveEditBtn: function(node) {\n\t\t\t$(\"#\" + node.tId + consts.id.EDIT).unbind().remove();\n\t\t},\n\t\tremoveRemoveBtn: function(node) {\n\t\t\t$(\"#\" + node.tId + consts.id.REMOVE).unbind().remove();\n\t\t},\n\t\tremoveTreeDom: function(setting, node) {\n\t\t\tnode.isHover = false;\n\t\t\tview.removeEditBtn(node);\n\t\t\tview.removeRemoveBtn(node);\n\t\t\ttools.apply(setting.view.removeHoverDom, [setting.treeId, node]);\n\t\t},\n\t\trepairNodeLevelClass: function(setting, node, oldLevel) {\n\t\t\tif (oldLevel === node.level) return;\n\t\t\tvar liObj = $(\"#\" + node.tId),\n\t\t\taObj = $(\"#\" + node.tId + consts.id.A),\n\t\t\tulObj = $(\"#\" + node.tId + consts.id.UL),\n\t\t\toldClass = \"level\" + oldLevel,\n\t\t\tnewClass = \"level\" + node.level;\n\t\t\tliObj.removeClass(oldClass);\n\t\t\tliObj.addClass(newClass);\n\t\t\taObj.removeClass(oldClass);\n\t\t\taObj.addClass(newClass);\n\t\t\tulObj.removeClass(oldClass);\n\t\t\tulObj.addClass(newClass);\n\t\t}\n\t},\n\n\t_z = {\n\t\ttools: _tools,\n\t\tview: _view,\n\t\tevent: _event,\n\t\tdata: _data\n\t};\n\t$.extend(true, $.fn.zTree.consts, _consts);\n\t$.extend(true, $.fn.zTree._z, _z);\n\n\tvar zt = $.fn.zTree,\n\ttools = zt._z.tools,\n\tconsts = zt.consts,\n\tview = zt._z.view,\n\tdata = zt._z.data,\n\tevent = zt._z.event;\n\n\tdata.exSetting(_setting);\n\tdata.addInitBind(_bindEvent);\n\tdata.addInitUnBind(_unbindEvent);\n\tdata.addInitCache(_initCache);\n\tdata.addInitNode(_initNode);\n\tdata.addInitProxy(_eventProxy);\n\tdata.addInitRoot(_initRoot);\n\tdata.addZTreeTools(_zTreeTools);\n\n\tvar _cancelPreSelectedNode = view.cancelPreSelectedNode;\n\tview.cancelPreSelectedNode = function (setting, node) {\n\t\tvar list = data.getRoot(setting).curSelectedList;\n\t\tfor (var i=0, j=list.length; i<j; i++) {\n\t\t\tif (!node || node === list[i]) {\n\t\t\t\tview.removeTreeDom(setting, list[i]);\n\t\t\t\tif (node) break;\n\t\t\t}\n\t\t}\n\t\tif (_cancelPreSelectedNode) _cancelPreSelectedNode.apply(view, arguments);\n\t}\n\n\tvar _createNodes = view.createNodes;\n\tview.createNodes = function(setting, level, nodes, parentNode) {\n\t\tif (_createNodes) {\n\t\t\t_createNodes.apply(view, arguments);\n\t\t}\n\t\tif (!nodes) return;\n\t\tif (view.repairParentChkClassWithSelf) {\n\t\t\tview.repairParentChkClassWithSelf(setting, parentNode);\n\t\t}\n\t}\n\n\tvar _makeNodeUrl = view.makeNodeUrl;\n\tview.makeNodeUrl = function(setting, node) {\n\t\treturn setting.edit.enable ? null : (_makeNodeUrl.apply(view, arguments));\n\t}\n\n\tvar _removeNode = view.removeNode;\n\tview.removeNode = function(setting, node) {\n\t\tvar root = data.getRoot(setting);\n\t\tif (root.curEditNode === node) root.curEditNode = null;\n\t\tif (_removeNode) {\n\t\t\t_removeNode.apply(view, arguments);\n\t\t}\n\t}\n\n\tvar _selectNode = view.selectNode;\n\tview.selectNode = function(setting, node, addFlag) {\n\t\tvar root = data.getRoot(setting);\n\t\tif (data.isSelectedNode(setting, node) && root.curEditNode == node && node.editNameFlag) {\n\t\t\treturn false;\n\t\t}\n\t\tif (_selectNode) _selectNode.apply(view, arguments);\n\t\tview.addHoverDom(setting, node);\n\t\treturn true;\n\t}\n\n\tvar _uCanDo = tools.uCanDo;\n\ttools.uCanDo = function(setting, e) {\n\t\tvar root = data.getRoot(setting);\n\t\tif (e && (tools.eqs(e.type, \"mouseover\") || tools.eqs(e.type, \"mouseout\") || tools.eqs(e.type, \"mousedown\") || tools.eqs(e.type, \"mouseup\"))) {\n\t\t\treturn true;\n\t\t}\n\t\treturn (!root.curEditNode) && (_uCanDo ? _uCanDo.apply(view, arguments) : true);\n\t}\n})(jQuery);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/lib/zTree/v3/js/jquery.ztree.exhide-3.5.js",
    "content": "/*\n * JQuery zTree exHideNodes v3.5.18\n * http://zTree.me/\n *\n * Copyright (c) 2010 Hunter.z\n *\n * Licensed same as jquery - MIT License\n * http://www.opensource.org/licenses/mit-license.php\n *\n * email: hunter.z@263.net\n * Date: 2015-05-25\n */\n(function($){\n\t//default init node of exLib\n\tvar _initNode = function(setting, level, n, parentNode, isFirstNode, isLastNode, openFlag) {\n\t\tif (typeof n.isHidden == \"string\") n.isHidden = tools.eqs(n.isHidden, \"true\");\n\t\tn.isHidden = !!n.isHidden;\n\t\tdata.initHideForExCheck(setting, n);\n\t},\n\t//add dom for check\n\t_beforeA = function(setting, node, html) {},\n\t//update zTreeObj, add method of exLib\n\t_zTreeTools = function(setting, zTreeTools) {\n\t\tzTreeTools.showNodes = function(nodes, options) {\n\t\t\tview.showNodes(setting, nodes, options);\n\t\t}\n\t\tzTreeTools.showNode = function(node, options) {\n\t\t\tif (!node) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tview.showNodes(setting, [node], options);\n\t\t}\n\t\tzTreeTools.hideNodes = function(nodes, options) {\n\t\t\tview.hideNodes(setting, nodes, options);\n\t\t}\n\t\tzTreeTools.hideNode = function(node, options) {\n\t\t\tif (!node) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tview.hideNodes(setting, [node], options);\n\t\t}\n\n\t\tvar _checkNode = zTreeTools.checkNode;\n\t\tif (_checkNode) {\n\t\t\tzTreeTools.checkNode = function(node, checked, checkTypeFlag, callbackFlag) {\n\t\t\t\tif (!!node && !!node.isHidden) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t_checkNode.apply(zTreeTools, arguments);\n\t\t\t}\n\t\t}\n\t},\n\t//method of operate data\n\t_data = {\n\t\tinitHideForExCheck: function(setting, n) {\n\t\t\tif (n.isHidden && setting.check && setting.check.enable) {\n\t\t\t\tif(typeof n._nocheck == \"undefined\") {\n\t\t\t\t\tn._nocheck = !!n.nocheck\n\t\t\t\t\tn.nocheck = true;\n\t\t\t\t}\n\t\t\t\tn.check_Child_State = -1;\n\t\t\t\tif (view.repairParentChkClassWithSelf) {\n\t\t\t\t\tview.repairParentChkClassWithSelf(setting, n);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tinitShowForExCheck: function(setting, n) {\n\t\t\tif (!n.isHidden && setting.check && setting.check.enable) {\n\t\t\t\tif(typeof n._nocheck != \"undefined\") {\n\t\t\t\t\tn.nocheck = n._nocheck;\n\t\t\t\t\tdelete n._nocheck;\n\t\t\t\t}\n\t\t\t\tif (view.setChkClass) {\n\t\t\t\t\tvar checkObj = $$(n, consts.id.CHECK, setting);\n\t\t\t\t\tview.setChkClass(setting, checkObj, n);\n\t\t\t\t}\n\t\t\t\tif (view.repairParentChkClassWithSelf) {\n\t\t\t\t\tview.repairParentChkClassWithSelf(setting, n);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\t//method of operate ztree dom\n\t_view = {\n\t\tclearOldFirstNode: function(setting, node) {\n\t\t\tvar n = node.getNextNode();\n\t\t\twhile(!!n){\n\t\t\t\tif (n.isFirstNode) {\n\t\t\t\t\tn.isFirstNode = false;\n\t\t\t\t\tview.setNodeLineIcos(setting, n);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (n.isLastNode) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tn = n.getNextNode();\n\t\t\t}\n\t\t},\n        clearOldLastNode: function(setting, node, openFlag) {\n            var n = node.getPreNode();\n            while(!!n){\n                if (n.isLastNode) {\n                    n.isLastNode = false;\n                    if (openFlag) {\n                        view.setNodeLineIcos(setting, n);\n                    }\n                    break;\n                }\n                if (n.isFirstNode) {\n                    break;\n                }\n                n = n.getPreNode();\n            }\n        },\n\t\tmakeDOMNodeMainBefore: function(html, setting, node) {\n\t\t\thtml.push(\"<li \", (node.isHidden ? \"style='display:none;' \" : \"\"), \"id='\", node.tId, \"' class='\", consts.className.LEVEL, node.level,\"' tabindex='0' hidefocus='true' treenode>\");\n\t\t},\n\t\tshowNode: function(setting, node, options) {\n\t\t\tnode.isHidden = false;\n\t\t\tdata.initShowForExCheck(setting, node);\n\t\t\t$$(node, setting).show();\n\t\t},\n\t\tshowNodes: function(setting, nodes, options) {\n\t\t\tif (!nodes || nodes.length == 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar pList = {}, i, j;\n\t\t\tfor (i=0, j=nodes.length; i<j; i++) {\n\t\t\t\tvar n = nodes[i];\n\t\t\t\tif (!pList[n.parentTId]) {\n\t\t\t\t\tvar pn = n.getParentNode();\n\t\t\t\t\tpList[n.parentTId] = (pn === null) ? data.getRoot(setting) : n.getParentNode();\n\t\t\t\t}\n\t\t\t\tview.showNode(setting, n, options);\n\t\t\t}\n\t\t\tfor (var tId in pList) {\n\t\t\t\tvar children = pList[tId][setting.data.key.children];\n\t\t\t\tview.setFirstNodeForShow(setting, children);\n\t\t\t\tview.setLastNodeForShow(setting, children);\n\t\t\t}\n\t\t},\n\t\thideNode: function(setting, node, options) {\n\t\t\tnode.isHidden = true;\n\t\t\tnode.isFirstNode = false;\n\t\t\tnode.isLastNode = false;\n\t\t\tdata.initHideForExCheck(setting, node);\n\t\t\tview.cancelPreSelectedNode(setting, node);\n\t\t\t$$(node, setting).hide();\n\t\t},\n\t\thideNodes: function(setting, nodes, options) {\n\t\t\tif (!nodes || nodes.length == 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar pList = {}, i, j;\n\t\t\tfor (i=0, j=nodes.length; i<j; i++) {\n\t\t\t\tvar n = nodes[i];\n\t\t\t\tif ((n.isFirstNode || n.isLastNode) && !pList[n.parentTId]) {\n\t\t\t\t\tvar pn = n.getParentNode();\n\t\t\t\t\tpList[n.parentTId] = (pn === null) ? data.getRoot(setting) : n.getParentNode();\n\t\t\t\t}\n\t\t\t\tview.hideNode(setting, n, options);\n\t\t\t}\n\t\t\tfor (var tId in pList) {\n\t\t\t\tvar children = pList[tId][setting.data.key.children];\n\t\t\t\tview.setFirstNodeForHide(setting, children);\n\t\t\t\tview.setLastNodeForHide(setting, children);\n\t\t\t}\n\t\t},\n\t\tsetFirstNode: function(setting, parentNode) {\n\t\t\tvar childKey = setting.data.key.children, childLength = parentNode[childKey].length;\n\t\t\tif (childLength > 0 && !parentNode[childKey][0].isHidden) {\n\t\t\t\tparentNode[childKey][0].isFirstNode = true;\n\t\t\t} else if (childLength > 0) {\n\t\t\t\tview.setFirstNodeForHide(setting, parentNode[childKey]);\n\t\t\t}\n\t\t},\n\t\tsetLastNode: function(setting, parentNode) {\n\t\t\tvar childKey = setting.data.key.children, childLength = parentNode[childKey].length;\n\t\t\tif (childLength > 0 && !parentNode[childKey][0].isHidden) {\n\t\t\t\tparentNode[childKey][childLength - 1].isLastNode = true;\n\t\t\t} else if (childLength > 0) {\n\t\t\t\tview.setLastNodeForHide(setting, parentNode[childKey]);\n\t\t\t}\n\t\t},\n\t\tsetFirstNodeForHide: function(setting, nodes) {\n\t\t\tvar n,i,j;\n\t\t\tfor (i=0, j=nodes.length; i<j; i++) {\n\t\t\t\tn = nodes[i];\n\t\t\t\tif (n.isFirstNode) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!n.isHidden && !n.isFirstNode) {\n\t\t\t\t\tn.isFirstNode = true;\n\t\t\t\t\tview.setNodeLineIcos(setting, n);\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tn = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn n;\n\t\t},\n\t\tsetFirstNodeForShow: function(setting, nodes) {\n\t\t\tvar n,i,j, first, old;\n\t\t\tfor(i=0, j=nodes.length; i<j; i++) {\n\t\t\t\tn = nodes[i];\n\t\t\t\tif (!first && !n.isHidden && n.isFirstNode) {\n\t\t\t\t\tfirst = n;\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (!first && !n.isHidden && !n.isFirstNode) {\n\t\t\t\t\tn.isFirstNode = true;\n\t\t\t\t\tfirst = n;\n\t\t\t\t\tview.setNodeLineIcos(setting, n);\n\t\t\t\t} else if (first && n.isFirstNode) {\n\t\t\t\t\tn.isFirstNode = false;\n\t\t\t\t\told = n;\n\t\t\t\t\tview.setNodeLineIcos(setting, n);\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tn = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\"new\":first, \"old\":old};\n\t\t},\n\t\tsetLastNodeForHide: function(setting, nodes) {\n\t\t\tvar n,i;\n\t\t\tfor (i=nodes.length-1; i>=0; i--) {\n\t\t\t\tn = nodes[i];\n\t\t\t\tif (n.isLastNode) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!n.isHidden && !n.isLastNode) {\n\t\t\t\t\tn.isLastNode = true;\n\t\t\t\t\tview.setNodeLineIcos(setting, n);\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tn = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn n;\n\t\t},\n\t\tsetLastNodeForShow: function(setting, nodes) {\n\t\t\tvar n,i,j, last, old;\n\t\t\tfor (i=nodes.length-1; i>=0; i--) {\n\t\t\t\tn = nodes[i];\n\t\t\t\tif (!last && !n.isHidden && n.isLastNode) {\n\t\t\t\t\tlast = n;\n\t\t\t\t\tbreak;\n\t\t\t\t} else if (!last && !n.isHidden && !n.isLastNode) {\n\t\t\t\t\tn.isLastNode = true;\n\t\t\t\t\tlast = n;\n\t\t\t\t\tview.setNodeLineIcos(setting, n);\n\t\t\t\t} else if (last && n.isLastNode) {\n\t\t\t\t\tn.isLastNode = false;\n\t\t\t\t\told = n;\n\t\t\t\t\tview.setNodeLineIcos(setting, n);\n\t\t\t\t\tbreak;\n\t\t\t\t} else {\n\t\t\t\t\tn = null;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn {\"new\":last, \"old\":old};\n\t\t}\n\t},\n\n\t_z = {\n\t\tview: _view,\n\t\tdata: _data\n\t};\n\t$.extend(true, $.fn.zTree._z, _z);\n\n\tvar zt = $.fn.zTree,\n\ttools = zt._z.tools,\n\tconsts = zt.consts,\n\tview = zt._z.view,\n\tdata = zt._z.data,\n\tevent = zt._z.event,\n\t$$ = tools.$;\n\n\tdata.addInitNode(_initNode);\n\tdata.addBeforeA(_beforeA);\n\tdata.addZTreeTools(_zTreeTools);\n\n//\tOverride method in core\n\tvar _dInitNode = data.initNode;\n    data.initNode = function(setting, level, node, parentNode, isFirstNode, isLastNode, openFlag) {\n        var tmpPNode = (parentNode) ? parentNode: data.getRoot(setting),\n            children = tmpPNode[setting.data.key.children];\n        data.tmpHideFirstNode = view.setFirstNodeForHide(setting, children);\n        data.tmpHideLastNode = view.setLastNodeForHide(setting, children);\n        if (openFlag) {\n            view.setNodeLineIcos(setting, data.tmpHideFirstNode);\n            view.setNodeLineIcos(setting, data.tmpHideLastNode);\n        }\n        isFirstNode = (data.tmpHideFirstNode === node);\n        isLastNode = (data.tmpHideLastNode === node);\n        if (_dInitNode) _dInitNode.apply(data, arguments);\n        if (openFlag && isLastNode) {\n            view.clearOldLastNode(setting, node, openFlag);\n        }\n    };\n\n\tvar _makeChkFlag = data.makeChkFlag;\n\tif (!!_makeChkFlag) {\n\t\tdata.makeChkFlag = function(setting, node) {\n\t\t\tif (!!node && !!node.isHidden) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t_makeChkFlag.apply(data, arguments);\n\t\t}\n\t}\n\n\tvar _getTreeCheckedNodes = data.getTreeCheckedNodes;\n\tif (!!_getTreeCheckedNodes) {\n\t\tdata.getTreeCheckedNodes = function(setting, nodes, checked, results) {\n\t\t\tif (!!nodes && nodes.length > 0) {\n\t\t\t\tvar p = nodes[0].getParentNode();\n\t\t\t\tif (!!p && !!p.isHidden) {\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn _getTreeCheckedNodes.apply(data, arguments);\n\t\t}\n\t}\n\n\tvar _getTreeChangeCheckedNodes = data.getTreeChangeCheckedNodes;\n\tif (!!_getTreeChangeCheckedNodes) {\n\t\tdata.getTreeChangeCheckedNodes = function(setting, nodes, results) {\n\t\t\tif (!!nodes && nodes.length > 0) {\n\t\t\t\tvar p = nodes[0].getParentNode();\n\t\t\t\tif (!!p && !!p.isHidden) {\n\t\t\t\t\treturn [];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn _getTreeChangeCheckedNodes.apply(data, arguments);\n\t\t}\n\t}\n\n\tvar _expandCollapseSonNode = view.expandCollapseSonNode;\n\tif (!!_expandCollapseSonNode) {\n\t\tview.expandCollapseSonNode = function(setting, node, expandFlag, animateFlag, callback) {\n\t\t\tif (!!node && !!node.isHidden) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t_expandCollapseSonNode.apply(view, arguments);\n\t\t}\n\t}\n\n\tvar _setSonNodeCheckBox = view.setSonNodeCheckBox;\n\tif (!!_setSonNodeCheckBox) {\n\t\tview.setSonNodeCheckBox = function(setting, node, value, srcNode) {\n\t\t\tif (!!node && !!node.isHidden) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t_setSonNodeCheckBox.apply(view, arguments);\n\t\t}\n\t}\n\n\tvar _repairParentChkClassWithSelf = view.repairParentChkClassWithSelf;\n\tif (!!_repairParentChkClassWithSelf) {\n\t\tview.repairParentChkClassWithSelf = function(setting, node) {\n\t\t\tif (!!node && !!node.isHidden) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t_repairParentChkClassWithSelf.apply(view, arguments);\n\t\t}\n\t}\n})(jQuery);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/ajaxfileupload/ajaxfileupload.js",
    "content": "\njQuery.extend({\n\n\n    createUploadIframe: function(id, uri)\n    {\n        //create frame\n        var frameId = 'jUploadFrame' + id;\n\n        if(window.ActiveXObject) {\n            var io = document.createElement('<iframe id=\"' + frameId + '\" name=\"' + frameId + '\" />');\n            if(typeof uri== 'boolean'){\n                io.src = 'javascript:false';\n            }\n            else if(typeof uri== 'string'){\n                io.src = uri;\n            }\n        }\n        else {\n            var io = document.createElement('iframe');\n            io.id = frameId;\n            io.name = frameId;\n        }\n        io.style.position = 'absolute';\n        io.style.top = '-1000px';\n        io.style.left = '-1000px';\n\n        document.body.appendChild(io);\n\n        return io\n    },\n    createUploadForm: function(id, fileElementId)\n    {\n        //create form\n        var formId = 'jUploadForm' + id;\n        var fileId = 'jUploadFile' + id;\n        var form = $('<form  action=\"\" method=\"POST\" name=\"' + formId + '\" id=\"' + formId + '\" enctype=\"multipart/form-data\"></form>');\n        var oldElement = $('#' + fileElementId);\n        var newElement = $(oldElement).clone();\n        $(oldElement).attr('id', fileId);\n        $(oldElement).before(newElement);\n        $(oldElement).appendTo(form);\n        //set attributes\n        $(form).css('position', 'absolute');\n        $(form).css('top', '-1200px');\n        $(form).css('left', '-1200px');\n        $(form).appendTo('body');\n        return form;\n    },\n    addOtherRequestsToForm: function(form,data)\n    {\n        // add extra parameter\n        var originalElement = $('<input type=\"hidden\" name=\"\" value=\"\">');\n        for (var key in data) {\n            name = key;\n            value = data[key];\n            var cloneElement = originalElement.clone();\n            cloneElement.attr({'name':name,'value':value});\n            $(cloneElement).appendTo(form);\n        }\n        return form;\n    },\n\n    ajaxFileUpload: function(s) {\n        // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout\n        s = jQuery.extend({}, jQuery.ajaxSettings, s);\n        var id = new Date().getTime()\n        var form = jQuery.createUploadForm(id, s.fileElementId);\n        if ( s.data ) form = jQuery.addOtherRequestsToForm(form,s.data);\n        var io = jQuery.createUploadIframe(id, s.secureuri);\n        var frameId = 'jUploadFrame' + id;\n        var formId = 'jUploadForm' + id;\n        // Watch for a new set of requests\n        if ( s.global && ! jQuery.active++ )\n        {\n            jQuery.event.trigger( \"ajaxStart\" );\n        }\n        var requestDone = false;\n        // Create the request object\n        var xml = {}\n        if ( s.global )\n            jQuery.event.trigger(\"ajaxSend\", [xml, s]);\n        // Wait for a response to come back\n        var uploadCallback = function(isTimeout)\n        {\n            var io = document.getElementById(frameId);\n            try\n            {\n                if(io.contentWindow)\n                {\n                    xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null;\n                    xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document;\n\n                }else if(io.contentDocument)\n                {\n                    xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null;\n                    xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document;\n                }\n            }catch(e)\n            {\n                jQuery.handleError(s, xml, null, e);\n            }\n            if ( xml || isTimeout == \"timeout\")\n            {\n                requestDone = true;\n                var status;\n                try {\n                    status = isTimeout != \"timeout\" ? \"success\" : \"error\";\n                    // Make sure that the request was successful or notmodified\n                    if ( status != \"error\" )\n                    {\n                        // process the data (runs the xml through httpData regardless of callback)\n                        var data = jQuery.uploadHttpData( xml, s.dataType );\n                        // If a local callback was specified, fire it and pass it the data\n                        if ( s.success )\n                            s.success( data, status );\n\n                        // Fire the global callback\n                        if( s.global )\n                            jQuery.event.trigger( \"ajaxSuccess\", [xml, s] );\n                    } else\n                        jQuery.handleError(s, xml, status);\n                } catch(e)\n                {\n                    status = \"error\";\n                    jQuery.handleError(s, xml, status, e);\n                }\n\n                // The request was completed\n                if( s.global )\n                    jQuery.event.trigger( \"ajaxComplete\", [xml, s] );\n\n                // Handle the global AJAX counter\n                if ( s.global && ! --jQuery.active )\n                    jQuery.event.trigger( \"ajaxStop\" );\n\n                // Process result\n                if ( s.complete )\n                    s.complete(xml, status);\n\n                jQuery(io).unbind()\n\n                setTimeout(function()\n                {\ttry\n                    {\n                        $(io).remove();\n                        $(form).remove();\n\n                    } catch(e)\n                    {\n                        jQuery.handleError(s, xml, null, e);\n                    }\n\n                }, 100)\n\n                xml = null\n\n            }\n        }\n        // Timeout checker\n        if ( s.timeout > 0 )\n        {\n            setTimeout(function(){\n                // Check to see if the request is still happening\n                if( !requestDone ) uploadCallback( \"timeout\" );\n            }, s.timeout);\n        }\n        try\n        {\n            // var io = $('#' + frameId);\n            var form = $('#' + formId);\n            $(form).attr('action', s.url);\n            $(form).attr('method', 'POST');\n            $(form).attr('target', frameId);\n            if(form.encoding)\n            {\n                form.encoding = 'multipart/form-data';\n            }\n            else\n            {\n                form.enctype = 'multipart/form-data';\n            }\n            $(form).submit();\n\n        } catch(e)\n        {\n            jQuery.handleError(s, xml, null, e);\n        }\n        if(window.attachEvent){\n            document.getElementById(frameId).attachEvent('onload', uploadCallback);\n        }\n        else{\n            document.getElementById(frameId).addEventListener('load', uploadCallback, false);\n        }\n        return {abort: function () {}};\n\n    },\n\n    uploadHttpData: function( r, type ) {\n        var data = !type;\n        data = type == \"xml\" || data ? r.responseXML : r.responseText;\n        // If the type is \"script\", eval it in global context\n        if ( type == \"script\" )\n            jQuery.globalEval( data );\n        // Get the JavaScript object, if JSON is used.\n        if ( type == \"json\" )\n        {\n            // If you add mimetype in your response,\n            // you have to delete the '<pre></pre>' tag.\n            // The pre tag in Chrome has attribute, so have to use regex to remove\n            var data = r.responseText;\n            var rx = new RegExp(\"<pre.*?>(.*?)</pre>\",\"i\");\n            var am = rx.exec(data);\n            //this is the desired data extracted\n            var data = (am) ? am[1] : \"\";    //the only submatch or empty\n            eval( \"data = \" + data );\n        }\n        // evaluate scripts within html\n        if ( type == \"html\" )\n            jQuery(\"<div>\").html(data).evalScripts();\n        //alert($('param', data).each(function(){alert($(this).attr('value'));}));\n        return data;\n    }\n})\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/dropzone/basic.css",
    "content": "/*\n * The MIT License\n * Copyright (c) 2012 Matias Meno <m@tias.me>\n */\n.dropzone, .dropzone * {\n  box-sizing: border-box; }\n\n.dropzone {\n  position: relative; }\n  .dropzone .dz-preview {\n    position: relative;\n    display: inline-block;\n    width: 120px;\n    margin: 0.5em; }\n    .dropzone .dz-preview .dz-progress {\n      display: block;\n      height: 15px;\n      border: 1px solid #aaa; }\n      .dropzone .dz-preview .dz-progress .dz-upload {\n        display: block;\n        height: 100%;\n        width: 0;\n        background: green; }\n    .dropzone .dz-preview .dz-error-message {\n      color: red;\n      display: none; }\n    .dropzone .dz-preview.dz-error .dz-error-message, .dropzone .dz-preview.dz-error .dz-error-mark {\n      display: block; }\n    .dropzone .dz-preview.dz-success .dz-success-mark {\n      display: block; }\n    .dropzone .dz-preview .dz-error-mark, .dropzone .dz-preview .dz-success-mark {\n      position: absolute;\n      display: none;\n      left: 30px;\n      top: 30px;\n      width: 54px;\n      height: 58px;\n      left: 50%;\n      margin-left: -27px; }\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/dropzone/dropzone-amd-module.js",
    "content": "// Uses AMD or browser globals to create a jQuery plugin.\n(function (factory) {\n  if (typeof define === 'function' && define.amd) {\n      // AMD. Register as an anonymous module.\n      define(['jquery'], factory);\n  } else {\n      // Browser globals\n      factory(jQuery);\n  }\n} (function (jQuery) {\n    var module = { exports: { } }; // Fake component\n\n\"use strict\";\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n/*\n *\n * More info at [www.dropzonejs.com](http://www.dropzonejs.com)\n *\n * Copyright (c) 2012, Matias Meno\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n// The Emitter class provides the ability to call `.on()` on Dropzone to listen\n// to events.\n// It is strongly based on component's emitter class, and I removed the\n// functionality because of the dependency hell with different frameworks.\nvar Emitter = function () {\n  function Emitter() {\n    _classCallCheck(this, Emitter);\n  }\n\n  _createClass(Emitter, [{\n    key: \"on\",\n\n    // Add an event listener for given event\n    value: function on(event, fn) {\n      this._callbacks = this._callbacks || {};\n      // Create namespace for this event\n      if (!this._callbacks[event]) {\n        this._callbacks[event] = [];\n      }\n      this._callbacks[event].push(fn);\n      return this;\n    }\n  }, {\n    key: \"emit\",\n    value: function emit(event) {\n      this._callbacks = this._callbacks || {};\n      var callbacks = this._callbacks[event];\n\n      if (callbacks) {\n        for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n          args[_key - 1] = arguments[_key];\n        }\n\n        for (var _iterator = callbacks, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {\n          var _ref;\n\n          if (_isArray) {\n            if (_i >= _iterator.length) break;\n            _ref = _iterator[_i++];\n          } else {\n            _i = _iterator.next();\n            if (_i.done) break;\n            _ref = _i.value;\n          }\n\n          var callback = _ref;\n\n          callback.apply(this, args);\n        }\n      }\n\n      return this;\n    }\n\n    // Remove event listener for given event. If fn is not provided, all event\n    // listeners for that event will be removed. If neither is provided, all\n    // event listeners will be removed.\n\n  }, {\n    key: \"off\",\n    value: function off(event, fn) {\n      if (!this._callbacks || arguments.length === 0) {\n        this._callbacks = {};\n        return this;\n      }\n\n      // specific event\n      var callbacks = this._callbacks[event];\n      if (!callbacks) {\n        return this;\n      }\n\n      // remove all handlers\n      if (arguments.length === 1) {\n        delete this._callbacks[event];\n        return this;\n      }\n\n      // remove specific handler\n      for (var i = 0; i < callbacks.length; i++) {\n        var callback = callbacks[i];\n        if (callback === fn) {\n          callbacks.splice(i, 1);\n          break;\n        }\n      }\n\n      return this;\n    }\n  }]);\n\n  return Emitter;\n}();\n\nvar Dropzone = function (_Emitter) {\n  _inherits(Dropzone, _Emitter);\n\n  _createClass(Dropzone, null, [{\n    key: \"initClass\",\n    value: function initClass() {\n\n      // Exposing the emitter class, mainly for tests\n      this.prototype.Emitter = Emitter;\n\n      /*\n       This is a list of all available events you can register on a dropzone object.\n        You can register an event handler like this:\n        dropzone.on(\"dragEnter\", function() { });\n        */\n      this.prototype.events = [\"drop\", \"dragstart\", \"dragend\", \"dragenter\", \"dragover\", \"dragleave\", \"addedfile\", \"addedfiles\", \"removedfile\", \"thumbnail\", \"error\", \"errormultiple\", \"processing\", \"processingmultiple\", \"uploadprogress\", \"totaluploadprogress\", \"sending\", \"sendingmultiple\", \"success\", \"successmultiple\", \"canceled\", \"canceledmultiple\", \"complete\", \"completemultiple\", \"reset\", \"maxfilesexceeded\", \"maxfilesreached\", \"queuecomplete\"];\n\n      this.prototype.defaultOptions = {\n        /**\n         * Has to be specified on elements other than form (or when the form\n         * doesn't have an `action` attribute). You can also\n         * provide a function that will be called with `files` and\n         * must return the url (since `v3.12.0`)\n         */\n        url: null,\n\n        /**\n         * Can be changed to `\"put\"` if necessary. You can also provide a function\n         * that will be called with `files` and must return the method (since `v3.12.0`).\n         */\n        method: \"post\",\n\n        /**\n         * Will be set on the XHRequest.\n         */\n        withCredentials: false,\n\n        /**\n         * The timeout for the XHR requests in milliseconds (since `v4.4.0`).\n         */\n        timeout: 30000,\n\n        /**\n         * How many file uploads to process in parallel (See the\n         * Enqueuing file uploads* documentation section for more info)\n         */\n        parallelUploads: 2,\n\n        /**\n         * Whether to send multiple files in one request. If\n         * this it set to true, then the fallback file input element will\n         * have the `multiple` attribute as well. This option will\n         * also trigger additional events (like `processingmultiple`). See the events\n         * documentation section for more information.\n         */\n        uploadMultiple: false,\n\n        /**\n         * Whether you want files to be uploaded in chunks to your server. This can't be\n         * used in combination with `uploadMultiple`.\n         *\n         * See [chunksUploaded](#config-chunksUploaded) for the callback to finalise an upload.\n         */\n        chunking: false,\n\n        /**\n         * If `chunking` is enabled, this defines whether **every** file should be chunked,\n         * even if the file size is below chunkSize. This means, that the additional chunk\n         * form data will be submitted and the `chunksUploaded` callback will be invoked.\n         */\n        forceChunking: false,\n\n        /**\n         * If `chunking` is `true`, then this defines the chunk size in bytes.\n         */\n        chunkSize: 2000000,\n\n        /**\n         * If `true`, the individual chunks of a file are being uploaded simultaneously.\n         */\n        parallelChunkUploads: false,\n\n        /**\n         * Whether a chunk should be retried if it fails.\n         */\n        retryChunks: false,\n\n        /**\n         * If `retryChunks` is true, how many times should it be retried.\n         */\n        retryChunksLimit: 3,\n\n        /**\n         * If not `null` defines how many files this Dropzone handles. If it exceeds,\n         * the event `maxfilesexceeded` will be called. The dropzone element gets the\n         * class `dz-max-files-reached` accordingly so you can provide visual feedback.\n         */\n        maxFilesize: 256,\n\n        /**\n         * The name of the file param that gets transferred.\n         * **NOTE**: If you have the option  `uploadMultiple` set to `true`, then\n         * Dropzone will append `[]` to the name.\n         */\n        paramName: \"file\",\n\n        /**\n         * Whether thumbnails for images should be generated\n         */\n        createImageThumbnails: true,\n\n        /**\n         * In MB. When the filename exceeds this limit, the thumbnail will not be generated.\n         */\n        maxThumbnailFilesize: 10,\n\n        /**\n         * If `null`, the ratio of the image will be used to calculate it.\n         */\n        thumbnailWidth: 120,\n\n        /**\n         * The same as `thumbnailWidth`. If both are null, images will not be resized.\n         */\n        thumbnailHeight: 120,\n\n        /**\n         * How the images should be scaled down in case both, `thumbnailWidth` and `thumbnailHeight` are provided.\n         * Can be either `contain` or `crop`.\n         */\n        thumbnailMethod: 'crop',\n\n        /**\n         * If set, images will be resized to these dimensions before being **uploaded**.\n         * If only one, `resizeWidth` **or** `resizeHeight` is provided, the original aspect\n         * ratio of the file will be preserved.\n         *\n         * The `options.transformFile` function uses these options, so if the `transformFile` function\n         * is overridden, these options don't do anything.\n         */\n        resizeWidth: null,\n\n        /**\n         * See `resizeWidth`.\n         */\n        resizeHeight: null,\n\n        /**\n         * The mime type of the resized image (before it gets uploaded to the server).\n         * If `null` the original mime type will be used. To force jpeg, for example, use `image/jpeg`.\n         * See `resizeWidth` for more information.\n         */\n        resizeMimeType: null,\n\n        /**\n         * The quality of the resized images. See `resizeWidth`.\n         */\n        resizeQuality: 0.8,\n\n        /**\n         * How the images should be scaled down in case both, `resizeWidth` and `resizeHeight` are provided.\n         * Can be either `contain` or `crop`.\n         */\n        resizeMethod: 'contain',\n\n        /**\n         * The base that is used to calculate the filesize. You can change this to\n         * 1024 if you would rather display kibibytes, mebibytes, etc...\n         * 1024 is technically incorrect, because `1024 bytes` are `1 kibibyte` not `1 kilobyte`.\n         * You can change this to `1024` if you don't care about validity.\n         */\n        filesizeBase: 1000,\n\n        /**\n         * Can be used to limit the maximum number of files that will be handled by this Dropzone\n         */\n        maxFiles: null,\n\n        /**\n         * An optional object to send additional headers to the server. Eg:\n         * `{ \"My-Awesome-Header\": \"header value\" }`\n         */\n        headers: null,\n\n        /**\n         * If `true`, the dropzone element itself will be clickable, if `false`\n         * nothing will be clickable.\n         *\n         * You can also pass an HTML element, a CSS selector (for multiple elements)\n         * or an array of those. In that case, all of those elements will trigger an\n         * upload when clicked.\n         */\n        clickable: true,\n\n        /**\n         * Whether hidden files in directories should be ignored.\n         */\n        ignoreHiddenFiles: true,\n\n        /**\n         * The default implementation of `accept` checks the file's mime type or\n         * extension against this list. This is a comma separated list of mime\n         * types or file extensions.\n         *\n         * Eg.: `image/*,application/pdf,.psd`\n         *\n         * If the Dropzone is `clickable` this option will also be used as\n         * [`accept`](https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept)\n         * parameter on the hidden file input as well.\n         */\n        acceptedFiles: null,\n\n        /**\n         * **Deprecated!**\n         * Use acceptedFiles instead.\n         */\n        acceptedMimeTypes: null,\n\n        /**\n         * If false, files will be added to the queue but the queue will not be\n         * processed automatically.\n         * This can be useful if you need some additional user input before sending\n         * files (or if you want want all files sent at once).\n         * If you're ready to send the file simply call `myDropzone.processQueue()`.\n         *\n         * See the [enqueuing file uploads](#enqueuing-file-uploads) documentation\n         * section for more information.\n         */\n        autoProcessQueue: true,\n\n        /**\n         * If false, files added to the dropzone will not be queued by default.\n         * You'll have to call `enqueueFile(file)` manually.\n         */\n        autoQueue: true,\n\n        /**\n         * If `true`, this will add a link to every file preview to remove or cancel (if\n         * already uploading) the file. The `dictCancelUpload`, `dictCancelUploadConfirmation`\n         * and `dictRemoveFile` options are used for the wording.\n         */\n        addRemoveLinks: false,\n\n        /**\n         * Defines where to display the file previews – if `null` the\n         * Dropzone element itself is used. Can be a plain `HTMLElement` or a CSS\n         * selector. The element should have the `dropzone-previews` class so\n         * the previews are displayed properly.\n         */\n        previewsContainer: null,\n\n        /**\n         * This is the element the hidden input field (which is used when clicking on the\n         * dropzone to trigger file selection) will be appended to. This might\n         * be important in case you use frameworks to switch the content of your page.\n         */\n        hiddenInputContainer: \"body\",\n\n        /**\n         * If null, no capture type will be specified\n         * If camera, mobile devices will skip the file selection and choose camera\n         * If microphone, mobile devices will skip the file selection and choose the microphone\n         * If camcorder, mobile devices will skip the file selection and choose the camera in video mode\n         * On apple devices multiple must be set to false.  AcceptedFiles may need to\n         * be set to an appropriate mime type (e.g. \"image/*\", \"audio/*\", or \"video/*\").\n         */\n        capture: null,\n\n        /**\n         * **Deprecated**. Use `renameFile` instead.\n         */\n        renameFilename: null,\n\n        /**\n         * A function that is invoked before the file is uploaded to the server and renames the file.\n         * This function gets the `File` as argument and can use the `file.name`. The actual name of the\n         * file that gets used during the upload can be accessed through `file.upload.filename`.\n         */\n        renameFile: null,\n\n        /**\n         * If `true` the fallback will be forced. This is very useful to test your server\n         * implementations first and make sure that everything works as\n         * expected without dropzone if you experience problems, and to test\n         * how your fallbacks will look.\n         */\n        forceFallback: false,\n\n        /**\n         * The text used before any files are dropped.\n         */\n        dictDefaultMessage: \"Drop files here to upload\",\n\n        /**\n         * The text that replaces the default message text it the browser is not supported.\n         */\n        dictFallbackMessage: \"Your browser does not support drag'n'drop file uploads.\",\n\n        /**\n         * The text that will be added before the fallback form.\n         * If you provide a  fallback element yourself, or if this option is `null` this will\n         * be ignored.\n         */\n        dictFallbackText: \"Please use the fallback form below to upload your files like in the olden days.\",\n\n        /**\n         * If the filesize is too big.\n         * `{{filesize}}` and `{{maxFilesize}}` will be replaced with the respective configuration values.\n         */\n        dictFileTooBig: \"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.\",\n\n        /**\n         * If the file doesn't match the file type.\n         */\n        dictInvalidFileType: \"You can't upload files of this type.\",\n\n        /**\n         * If the server response was invalid.\n         * `{{statusCode}}` will be replaced with the servers status code.\n         */\n        dictResponseError: \"Server responded with {{statusCode}} code.\",\n\n        /**\n         * If `addRemoveLinks` is true, the text to be used for the cancel upload link.\n         */\n        dictCancelUpload: \"Cancel upload\",\n\n        /**\n         * The text that is displayed if an upload was manually canceled\n         */\n        dictUploadCanceled: \"Upload canceled.\",\n\n        /**\n         * If `addRemoveLinks` is true, the text to be used for confirmation when cancelling upload.\n         */\n        dictCancelUploadConfirmation: \"Are you sure you want to cancel this upload?\",\n\n        /**\n         * If `addRemoveLinks` is true, the text to be used to remove a file.\n         */\n        dictRemoveFile: \"Remove file\",\n\n        /**\n         * If this is not null, then the user will be prompted before removing a file.\n         */\n        dictRemoveFileConfirmation: null,\n\n        /**\n         * Displayed if `maxFiles` is st and exceeded.\n         * The string `{{maxFiles}}` will be replaced by the configuration value.\n         */\n        dictMaxFilesExceeded: \"You can not upload any more files.\",\n\n        /**\n         * Allows you to translate the different units. Starting with `tb` for terabytes and going down to\n         * `b` for bytes.\n         */\n        dictFileSizeUnits: { tb: \"TB\", gb: \"GB\", mb: \"MB\", kb: \"KB\", b: \"b\" },\n        /**\n         * Called when dropzone initialized\n         * You can add event listeners here\n         */\n        init: function init() {},\n\n\n        /**\n         * Can be an **object** of additional parameters to transfer to the server, **or** a `Function`\n         * that gets invoked with the `files`, `xhr` and, if it's a chunked upload, `chunk` arguments. In case\n         * of a function, this needs to return a map.\n         *\n         * The default implementation does nothing for normal uploads, but adds relevant information for\n         * chunked uploads.\n         *\n         * This is the same as adding hidden input fields in the form element.\n         */\n        params: function params(files, xhr, chunk) {\n          if (chunk) {\n            return {\n              dzuuid: chunk.file.upload.uuid,\n              dzchunkindex: chunk.index,\n              dztotalfilesize: chunk.file.size,\n              dzchunksize: this.options.chunkSize,\n              dztotalchunkcount: chunk.file.upload.totalChunkCount,\n              dzchunkbyteoffset: chunk.index * this.options.chunkSize\n            };\n          }\n        },\n\n\n        /**\n         * A function that gets a [file](https://developer.mozilla.org/en-US/docs/DOM/File)\n         * and a `done` function as parameters.\n         *\n         * If the done function is invoked without arguments, the file is \"accepted\" and will\n         * be processed. If you pass an error message, the file is rejected, and the error\n         * message will be displayed.\n         * This function will not be called if the file is too big or doesn't match the mime types.\n         */\n        accept: function accept(file, done) {\n          return done();\n        },\n\n\n        /**\n         * The callback that will be invoked when all chunks have been uploaded for a file.\n         * It gets the file for which the chunks have been uploaded as the first parameter,\n         * and the `done` function as second. `done()` needs to be invoked when everything\n         * needed to finish the upload process is done.\n         */\n        chunksUploaded: function chunksUploaded(file, done) {\n          done();\n        },\n\n        /**\n         * Gets called when the browser is not supported.\n         * The default implementation shows the fallback input field and adds\n         * a text.\n         */\n        fallback: function fallback() {\n          // This code should pass in IE7... :(\n          var messageElement = void 0;\n          this.element.className = this.element.className + \" dz-browser-not-supported\";\n\n          for (var _iterator2 = this.element.getElementsByTagName(\"div\"), _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {\n            var _ref2;\n\n            if (_isArray2) {\n              if (_i2 >= _iterator2.length) break;\n              _ref2 = _iterator2[_i2++];\n            } else {\n              _i2 = _iterator2.next();\n              if (_i2.done) break;\n              _ref2 = _i2.value;\n            }\n\n            var child = _ref2;\n\n            if (/(^| )dz-message($| )/.test(child.className)) {\n              messageElement = child;\n              child.className = \"dz-message\"; // Removes the 'dz-default' class\n              break;\n            }\n          }\n          if (!messageElement) {\n            messageElement = Dropzone.createElement(\"<div class=\\\"dz-message\\\"><span></span></div>\");\n            this.element.appendChild(messageElement);\n          }\n\n          var span = messageElement.getElementsByTagName(\"span\")[0];\n          if (span) {\n            if (span.textContent != null) {\n              span.textContent = this.options.dictFallbackMessage;\n            } else if (span.innerText != null) {\n              span.innerText = this.options.dictFallbackMessage;\n            }\n          }\n\n          return this.element.appendChild(this.getFallbackForm());\n        },\n\n\n        /**\n         * Gets called to calculate the thumbnail dimensions.\n         *\n         * It gets `file`, `width` and `height` (both may be `null`) as parameters and must return an object containing:\n         *\n         *  - `srcWidth` & `srcHeight` (required)\n         *  - `trgWidth` & `trgHeight` (required)\n         *  - `srcX` & `srcY` (optional, default `0`)\n         *  - `trgX` & `trgY` (optional, default `0`)\n         *\n         * Those values are going to be used by `ctx.drawImage()`.\n         */\n        resize: function resize(file, width, height, resizeMethod) {\n          var info = {\n            srcX: 0,\n            srcY: 0,\n            srcWidth: file.width,\n            srcHeight: file.height\n          };\n\n          var srcRatio = file.width / file.height;\n\n          // Automatically calculate dimensions if not specified\n          if (width == null && height == null) {\n            width = info.srcWidth;\n            height = info.srcHeight;\n          } else if (width == null) {\n            width = height * srcRatio;\n          } else if (height == null) {\n            height = width / srcRatio;\n          }\n\n          // Make sure images aren't upscaled\n          width = Math.min(width, info.srcWidth);\n          height = Math.min(height, info.srcHeight);\n\n          var trgRatio = width / height;\n\n          if (info.srcWidth > width || info.srcHeight > height) {\n            // Image is bigger and needs rescaling\n            if (resizeMethod === 'crop') {\n              if (srcRatio > trgRatio) {\n                info.srcHeight = file.height;\n                info.srcWidth = info.srcHeight * trgRatio;\n              } else {\n                info.srcWidth = file.width;\n                info.srcHeight = info.srcWidth / trgRatio;\n              }\n            } else if (resizeMethod === 'contain') {\n              // Method 'contain'\n              if (srcRatio > trgRatio) {\n                height = width / srcRatio;\n              } else {\n                width = height * srcRatio;\n              }\n            } else {\n              throw new Error(\"Unknown resizeMethod '\" + resizeMethod + \"'\");\n            }\n          }\n\n          info.srcX = (file.width - info.srcWidth) / 2;\n          info.srcY = (file.height - info.srcHeight) / 2;\n\n          info.trgWidth = width;\n          info.trgHeight = height;\n\n          return info;\n        },\n\n\n        /**\n         * Can be used to transform the file (for example, resize an image if necessary).\n         *\n         * The default implementation uses `resizeWidth` and `resizeHeight` (if provided) and resizes\n         * images according to those dimensions.\n         *\n         * Gets the `file` as the first parameter, and a `done()` function as the second, that needs\n         * to be invoked with the file when the transformation is done.\n         */\n        transformFile: function transformFile(file, done) {\n          if ((this.options.resizeWidth || this.options.resizeHeight) && file.type.match(/image.*/)) {\n            return this.resizeImage(file, this.options.resizeWidth, this.options.resizeHeight, this.options.resizeMethod, done);\n          } else {\n            return done(file);\n          }\n        },\n\n\n        /**\n         * A string that contains the template used for each dropped\n         * file. Change it to fulfill your needs but make sure to properly\n         * provide all elements.\n         *\n         * If you want to use an actual HTML element instead of providing a String\n         * as a config option, you could create a div with the id `tpl`,\n         * put the template inside it and provide the element like this:\n         *\n         *     document\n         *       .querySelector('#tpl')\n         *       .innerHTML\n         *\n         */\n        previewTemplate: \"<div class=\\\"dz-preview dz-file-preview\\\">\\n  <div class=\\\"dz-image\\\"><img data-dz-thumbnail /></div>\\n  <div class=\\\"dz-details\\\">\\n    <div class=\\\"dz-size\\\"><span data-dz-size></span></div>\\n    <div class=\\\"dz-filename\\\"><span data-dz-name></span></div>\\n  </div>\\n  <div class=\\\"dz-progress\\\"><span class=\\\"dz-upload\\\" data-dz-uploadprogress></span></div>\\n  <div class=\\\"dz-error-message\\\"><span data-dz-errormessage></span></div>\\n  <div class=\\\"dz-success-mark\\\">\\n    <svg width=\\\"54px\\\" height=\\\"54px\\\" viewBox=\\\"0 0 54 54\\\" version=\\\"1.1\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" xmlns:sketch=\\\"http://www.bohemiancoding.com/sketch/ns\\\">\\n      <title>Check</title>\\n      <defs></defs>\\n      <g id=\\\"Page-1\\\" stroke=\\\"none\\\" stroke-width=\\\"1\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" sketch:type=\\\"MSPage\\\">\\n        <path d=\\\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\\\" id=\\\"Oval-2\\\" stroke-opacity=\\\"0.198794158\\\" stroke=\\\"#747474\\\" fill-opacity=\\\"0.816519475\\\" fill=\\\"#FFFFFF\\\" sketch:type=\\\"MSShapeGroup\\\"></path>\\n      </g>\\n    </svg>\\n  </div>\\n  <div class=\\\"dz-error-mark\\\">\\n    <svg width=\\\"54px\\\" height=\\\"54px\\\" viewBox=\\\"0 0 54 54\\\" version=\\\"1.1\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" xmlns:sketch=\\\"http://www.bohemiancoding.com/sketch/ns\\\">\\n      <title>Error</title>\\n      <defs></defs>\\n      <g id=\\\"Page-1\\\" stroke=\\\"none\\\" stroke-width=\\\"1\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" sketch:type=\\\"MSPage\\\">\\n        <g id=\\\"Check-+-Oval-2\\\" sketch:type=\\\"MSLayerGroup\\\" stroke=\\\"#747474\\\" stroke-opacity=\\\"0.198794158\\\" fill=\\\"#FFFFFF\\\" fill-opacity=\\\"0.816519475\\\">\\n          <path d=\\\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\\\" id=\\\"Oval-2\\\" sketch:type=\\\"MSShapeGroup\\\"></path>\\n        </g>\\n      </g>\\n    </svg>\\n  </div>\\n</div>\",\n\n        // END OPTIONS\n        // (Required by the dropzone documentation parser)\n\n\n        /*\n         Those functions register themselves to the events on init and handle all\n         the user interface specific stuff. Overwriting them won't break the upload\n         but can break the way it's displayed.\n         You can overwrite them if you don't like the default behavior. If you just\n         want to add an additional event handler, register it on the dropzone object\n         and don't overwrite those options.\n         */\n\n        // Those are self explanatory and simply concern the DragnDrop.\n        drop: function drop(e) {\n          return this.element.classList.remove(\"dz-drag-hover\");\n        },\n        dragstart: function dragstart(e) {},\n        dragend: function dragend(e) {\n          return this.element.classList.remove(\"dz-drag-hover\");\n        },\n        dragenter: function dragenter(e) {\n          return this.element.classList.add(\"dz-drag-hover\");\n        },\n        dragover: function dragover(e) {\n          return this.element.classList.add(\"dz-drag-hover\");\n        },\n        dragleave: function dragleave(e) {\n          return this.element.classList.remove(\"dz-drag-hover\");\n        },\n        paste: function paste(e) {},\n\n\n        // Called whenever there are no files left in the dropzone anymore, and the\n        // dropzone should be displayed as if in the initial state.\n        reset: function reset() {\n          return this.element.classList.remove(\"dz-started\");\n        },\n\n\n        // Called when a file is added to the queue\n        // Receives `file`\n        addedfile: function addedfile(file) {\n          var _this2 = this;\n\n          if (this.element === this.previewsContainer) {\n            this.element.classList.add(\"dz-started\");\n          }\n\n          if (this.previewsContainer) {\n            file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());\n            file.previewTemplate = file.previewElement; // Backwards compatibility\n\n            this.previewsContainer.appendChild(file.previewElement);\n            for (var _iterator3 = file.previewElement.querySelectorAll(\"[data-dz-name]\"), _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {\n              var _ref3;\n\n              if (_isArray3) {\n                if (_i3 >= _iterator3.length) break;\n                _ref3 = _iterator3[_i3++];\n              } else {\n                _i3 = _iterator3.next();\n                if (_i3.done) break;\n                _ref3 = _i3.value;\n              }\n\n              var node = _ref3;\n\n              node.textContent = file.name;\n            }\n            for (var _iterator4 = file.previewElement.querySelectorAll(\"[data-dz-size]\"), _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {\n              if (_isArray4) {\n                if (_i4 >= _iterator4.length) break;\n                node = _iterator4[_i4++];\n              } else {\n                _i4 = _iterator4.next();\n                if (_i4.done) break;\n                node = _i4.value;\n              }\n\n              node.innerHTML = this.filesize(file.size);\n            }\n\n            if (this.options.addRemoveLinks) {\n              file._removeLink = Dropzone.createElement(\"<a class=\\\"dz-remove\\\" href=\\\"javascript:undefined;\\\" data-dz-remove>\" + this.options.dictRemoveFile + \"</a>\");\n              file.previewElement.appendChild(file._removeLink);\n            }\n\n            var removeFileEvent = function removeFileEvent(e) {\n              e.preventDefault();\n              e.stopPropagation();\n              if (file.status === Dropzone.UPLOADING) {\n                return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation, function () {\n                  return _this2.removeFile(file);\n                });\n              } else {\n                if (_this2.options.dictRemoveFileConfirmation) {\n                  return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation, function () {\n                    return _this2.removeFile(file);\n                  });\n                } else {\n                  return _this2.removeFile(file);\n                }\n              }\n            };\n\n            for (var _iterator5 = file.previewElement.querySelectorAll(\"[data-dz-remove]\"), _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {\n              var _ref4;\n\n              if (_isArray5) {\n                if (_i5 >= _iterator5.length) break;\n                _ref4 = _iterator5[_i5++];\n              } else {\n                _i5 = _iterator5.next();\n                if (_i5.done) break;\n                _ref4 = _i5.value;\n              }\n\n              var removeLink = _ref4;\n\n              removeLink.addEventListener(\"click\", removeFileEvent);\n            }\n          }\n        },\n\n\n        // Called whenever a file is removed.\n        removedfile: function removedfile(file) {\n          if (file.previewElement != null && file.previewElement.parentNode != null) {\n            file.previewElement.parentNode.removeChild(file.previewElement);\n          }\n          return this._updateMaxFilesReachedClass();\n        },\n\n\n        // Called when a thumbnail has been generated\n        // Receives `file` and `dataUrl`\n        thumbnail: function thumbnail(file, dataUrl) {\n          if (file.previewElement) {\n            file.previewElement.classList.remove(\"dz-file-preview\");\n            for (var _iterator6 = file.previewElement.querySelectorAll(\"[data-dz-thumbnail]\"), _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {\n              var _ref5;\n\n              if (_isArray6) {\n                if (_i6 >= _iterator6.length) break;\n                _ref5 = _iterator6[_i6++];\n              } else {\n                _i6 = _iterator6.next();\n                if (_i6.done) break;\n                _ref5 = _i6.value;\n              }\n\n              var thumbnailElement = _ref5;\n\n              thumbnailElement.alt = file.name;\n              thumbnailElement.src = dataUrl;\n            }\n\n            return setTimeout(function () {\n              return file.previewElement.classList.add(\"dz-image-preview\");\n            }, 1);\n          }\n        },\n\n\n        // Called whenever an error occurs\n        // Receives `file` and `message`\n        error: function error(file, message) {\n          if (file.previewElement) {\n            file.previewElement.classList.add(\"dz-error\");\n            if (typeof message !== \"String\" && message.error) {\n              message = message.error;\n            }\n            for (var _iterator7 = file.previewElement.querySelectorAll(\"[data-dz-errormessage]\"), _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) {\n              var _ref6;\n\n              if (_isArray7) {\n                if (_i7 >= _iterator7.length) break;\n                _ref6 = _iterator7[_i7++];\n              } else {\n                _i7 = _iterator7.next();\n                if (_i7.done) break;\n                _ref6 = _i7.value;\n              }\n\n              var node = _ref6;\n\n              node.textContent = message;\n            }\n          }\n        },\n        errormultiple: function errormultiple() {},\n\n\n        // Called when a file gets processed. Since there is a cue, not all added\n        // files are processed immediately.\n        // Receives `file`\n        processing: function processing(file) {\n          if (file.previewElement) {\n            file.previewElement.classList.add(\"dz-processing\");\n            if (file._removeLink) {\n              return file._removeLink.textContent = this.options.dictCancelUpload;\n            }\n          }\n        },\n        processingmultiple: function processingmultiple() {},\n\n\n        // Called whenever the upload progress gets updated.\n        // Receives `file`, `progress` (percentage 0-100) and `bytesSent`.\n        // To get the total number of bytes of the file, use `file.size`\n        uploadprogress: function uploadprogress(file, progress, bytesSent) {\n          if (file.previewElement) {\n            for (var _iterator8 = file.previewElement.querySelectorAll(\"[data-dz-uploadprogress]\"), _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) {\n              var _ref7;\n\n              if (_isArray8) {\n                if (_i8 >= _iterator8.length) break;\n                _ref7 = _iterator8[_i8++];\n              } else {\n                _i8 = _iterator8.next();\n                if (_i8.done) break;\n                _ref7 = _i8.value;\n              }\n\n              var node = _ref7;\n\n              node.nodeName === 'PROGRESS' ? node.value = progress : node.style.width = progress + \"%\";\n            }\n          }\n        },\n\n\n        // Called whenever the total upload progress gets updated.\n        // Called with totalUploadProgress (0-100), totalBytes and totalBytesSent\n        totaluploadprogress: function totaluploadprogress() {},\n\n\n        // Called just before the file is sent. Gets the `xhr` object as second\n        // parameter, so you can modify it (for example to add a CSRF token) and a\n        // `formData` object to add additional information.\n        sending: function sending() {},\n        sendingmultiple: function sendingmultiple() {},\n\n\n        // When the complete upload is finished and successful\n        // Receives `file`\n        success: function success(file) {\n          if (file.previewElement) {\n            return file.previewElement.classList.add(\"dz-success\");\n          }\n        },\n        successmultiple: function successmultiple() {},\n\n\n        // When the upload is canceled.\n        canceled: function canceled(file) {\n          return this.emit(\"error\", file, this.options.dictUploadCanceled);\n        },\n        canceledmultiple: function canceledmultiple() {},\n\n\n        // When the upload is finished, either with success or an error.\n        // Receives `file`\n        complete: function complete(file) {\n          if (file._removeLink) {\n            file._removeLink.textContent = this.options.dictRemoveFile;\n          }\n          if (file.previewElement) {\n            return file.previewElement.classList.add(\"dz-complete\");\n          }\n        },\n        completemultiple: function completemultiple() {},\n        maxfilesexceeded: function maxfilesexceeded() {},\n        maxfilesreached: function maxfilesreached() {},\n        queuecomplete: function queuecomplete() {},\n        addedfiles: function addedfiles() {}\n      };\n\n      this.prototype._thumbnailQueue = [];\n      this.prototype._processingThumbnail = false;\n    }\n\n    // global utility\n\n  }, {\n    key: \"extend\",\n    value: function extend(target) {\n      for (var _len2 = arguments.length, objects = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n        objects[_key2 - 1] = arguments[_key2];\n      }\n\n      for (var _iterator9 = objects, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {\n        var _ref8;\n\n        if (_isArray9) {\n          if (_i9 >= _iterator9.length) break;\n          _ref8 = _iterator9[_i9++];\n        } else {\n          _i9 = _iterator9.next();\n          if (_i9.done) break;\n          _ref8 = _i9.value;\n        }\n\n        var object = _ref8;\n\n        for (var key in object) {\n          var val = object[key];\n          target[key] = val;\n        }\n      }\n      return target;\n    }\n  }]);\n\n  function Dropzone(el, options) {\n    _classCallCheck(this, Dropzone);\n\n    var _this = _possibleConstructorReturn(this, (Dropzone.__proto__ || Object.getPrototypeOf(Dropzone)).call(this));\n\n    var fallback = void 0,\n        left = void 0;\n    _this.element = el;\n    // For backwards compatibility since the version was in the prototype previously\n    _this.version = Dropzone.version;\n\n    _this.defaultOptions.previewTemplate = _this.defaultOptions.previewTemplate.replace(/\\n*/g, \"\");\n\n    _this.clickableElements = [];\n    _this.listeners = [];\n    _this.files = []; // All files\n\n    if (typeof _this.element === \"string\") {\n      _this.element = document.querySelector(_this.element);\n    }\n\n    // Not checking if instance of HTMLElement or Element since IE9 is extremely weird.\n    if (!_this.element || _this.element.nodeType == null) {\n      throw new Error(\"Invalid dropzone element.\");\n    }\n\n    if (_this.element.dropzone) {\n      throw new Error(\"Dropzone already attached.\");\n    }\n\n    // Now add this dropzone to the instances.\n    Dropzone.instances.push(_this);\n\n    // Put the dropzone inside the element itself.\n    _this.element.dropzone = _this;\n\n    var elementOptions = (left = Dropzone.optionsForElement(_this.element)) != null ? left : {};\n\n    _this.options = Dropzone.extend({}, _this.defaultOptions, elementOptions, options != null ? options : {});\n\n    // If the browser failed, just call the fallback and leave\n    if (_this.options.forceFallback || !Dropzone.isBrowserSupported()) {\n      var _ret;\n\n      return _ret = _this.options.fallback.call(_this), _possibleConstructorReturn(_this, _ret);\n    }\n\n    // @options.url = @element.getAttribute \"action\" unless @options.url?\n    if (_this.options.url == null) {\n      _this.options.url = _this.element.getAttribute(\"action\");\n    }\n\n    if (!_this.options.url) {\n      throw new Error(\"No URL provided.\");\n    }\n\n    if (_this.options.acceptedFiles && _this.options.acceptedMimeTypes) {\n      throw new Error(\"You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.\");\n    }\n\n    if (_this.options.uploadMultiple && _this.options.chunking) {\n      throw new Error('You cannot set both: uploadMultiple and chunking.');\n    }\n\n    // Backwards compatibility\n    if (_this.options.acceptedMimeTypes) {\n      _this.options.acceptedFiles = _this.options.acceptedMimeTypes;\n      delete _this.options.acceptedMimeTypes;\n    }\n\n    // Backwards compatibility\n    if (_this.options.renameFilename != null) {\n      _this.options.renameFile = function (file) {\n        return _this.options.renameFilename.call(_this, file.name, file);\n      };\n    }\n\n    _this.options.method = _this.options.method.toUpperCase();\n\n    if ((fallback = _this.getExistingFallback()) && fallback.parentNode) {\n      // Remove the fallback\n      fallback.parentNode.removeChild(fallback);\n    }\n\n    // Display previews in the previewsContainer element or the Dropzone element unless explicitly set to false\n    if (_this.options.previewsContainer !== false) {\n      if (_this.options.previewsContainer) {\n        _this.previewsContainer = Dropzone.getElement(_this.options.previewsContainer, \"previewsContainer\");\n      } else {\n        _this.previewsContainer = _this.element;\n      }\n    }\n\n    if (_this.options.clickable) {\n      if (_this.options.clickable === true) {\n        _this.clickableElements = [_this.element];\n      } else {\n        _this.clickableElements = Dropzone.getElements(_this.options.clickable, \"clickable\");\n      }\n    }\n\n    _this.init();\n    return _this;\n  }\n\n  // Returns all files that have been accepted\n\n\n  _createClass(Dropzone, [{\n    key: \"getAcceptedFiles\",\n    value: function getAcceptedFiles() {\n      return this.files.filter(function (file) {\n        return file.accepted;\n      }).map(function (file) {\n        return file;\n      });\n    }\n\n    // Returns all files that have been rejected\n    // Not sure when that's going to be useful, but added for completeness.\n\n  }, {\n    key: \"getRejectedFiles\",\n    value: function getRejectedFiles() {\n      return this.files.filter(function (file) {\n        return !file.accepted;\n      }).map(function (file) {\n        return file;\n      });\n    }\n  }, {\n    key: \"getFilesWithStatus\",\n    value: function getFilesWithStatus(status) {\n      return this.files.filter(function (file) {\n        return file.status === status;\n      }).map(function (file) {\n        return file;\n      });\n    }\n\n    // Returns all files that are in the queue\n\n  }, {\n    key: \"getQueuedFiles\",\n    value: function getQueuedFiles() {\n      return this.getFilesWithStatus(Dropzone.QUEUED);\n    }\n  }, {\n    key: \"getUploadingFiles\",\n    value: function getUploadingFiles() {\n      return this.getFilesWithStatus(Dropzone.UPLOADING);\n    }\n  }, {\n    key: \"getAddedFiles\",\n    value: function getAddedFiles() {\n      return this.getFilesWithStatus(Dropzone.ADDED);\n    }\n\n    // Files that are either queued or uploading\n\n  }, {\n    key: \"getActiveFiles\",\n    value: function getActiveFiles() {\n      return this.files.filter(function (file) {\n        return file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED;\n      }).map(function (file) {\n        return file;\n      });\n    }\n\n    // The function that gets called when Dropzone is initialized. You\n    // can (and should) setup event listeners inside this function.\n\n  }, {\n    key: \"init\",\n    value: function init() {\n      var _this3 = this;\n\n      // In case it isn't set already\n      if (this.element.tagName === \"form\") {\n        this.element.setAttribute(\"enctype\", \"multipart/form-data\");\n      }\n\n      if (this.element.classList.contains(\"dropzone\") && !this.element.querySelector(\".dz-message\")) {\n        this.element.appendChild(Dropzone.createElement(\"<div class=\\\"dz-default dz-message\\\"><span>\" + this.options.dictDefaultMessage + \"</span></div>\"));\n      }\n\n      if (this.clickableElements.length) {\n        var setupHiddenFileInput = function setupHiddenFileInput() {\n          if (_this3.hiddenFileInput) {\n            _this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);\n          }\n          _this3.hiddenFileInput = document.createElement(\"input\");\n          _this3.hiddenFileInput.setAttribute(\"type\", \"file\");\n          if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) {\n            _this3.hiddenFileInput.setAttribute(\"multiple\", \"multiple\");\n          }\n          _this3.hiddenFileInput.className = \"dz-hidden-input\";\n\n          if (_this3.options.acceptedFiles !== null) {\n            _this3.hiddenFileInput.setAttribute(\"accept\", _this3.options.acceptedFiles);\n          }\n          if (_this3.options.capture !== null) {\n            _this3.hiddenFileInput.setAttribute(\"capture\", _this3.options.capture);\n          }\n\n          // Not setting `display=\"none\"` because some browsers don't accept clicks\n          // on elements that aren't displayed.\n          _this3.hiddenFileInput.style.visibility = \"hidden\";\n          _this3.hiddenFileInput.style.position = \"absolute\";\n          _this3.hiddenFileInput.style.top = \"0\";\n          _this3.hiddenFileInput.style.left = \"0\";\n          _this3.hiddenFileInput.style.height = \"0\";\n          _this3.hiddenFileInput.style.width = \"0\";\n          document.querySelector(_this3.options.hiddenInputContainer).appendChild(_this3.hiddenFileInput);\n          return _this3.hiddenFileInput.addEventListener(\"change\", function () {\n            var files = _this3.hiddenFileInput.files;\n\n            if (files.length) {\n              for (var _iterator10 = files, _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {\n                var _ref9;\n\n                if (_isArray10) {\n                  if (_i10 >= _iterator10.length) break;\n                  _ref9 = _iterator10[_i10++];\n                } else {\n                  _i10 = _iterator10.next();\n                  if (_i10.done) break;\n                  _ref9 = _i10.value;\n                }\n\n                var file = _ref9;\n\n                _this3.addFile(file);\n              }\n            }\n            _this3.emit(\"addedfiles\", files);\n            return setupHiddenFileInput();\n          });\n        };\n        setupHiddenFileInput();\n      }\n\n      this.URL = window.URL !== null ? window.URL : window.webkitURL;\n\n      // Setup all event listeners on the Dropzone object itself.\n      // They're not in @setupEventListeners() because they shouldn't be removed\n      // again when the dropzone gets disabled.\n      for (var _iterator11 = this.events, _isArray11 = Array.isArray(_iterator11), _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) {\n        var _ref10;\n\n        if (_isArray11) {\n          if (_i11 >= _iterator11.length) break;\n          _ref10 = _iterator11[_i11++];\n        } else {\n          _i11 = _iterator11.next();\n          if (_i11.done) break;\n          _ref10 = _i11.value;\n        }\n\n        var eventName = _ref10;\n\n        this.on(eventName, this.options[eventName]);\n      }\n\n      this.on(\"uploadprogress\", function () {\n        return _this3.updateTotalUploadProgress();\n      });\n\n      this.on(\"removedfile\", function () {\n        return _this3.updateTotalUploadProgress();\n      });\n\n      this.on(\"canceled\", function (file) {\n        return _this3.emit(\"complete\", file);\n      });\n\n      // Emit a `queuecomplete` event if all files finished uploading.\n      this.on(\"complete\", function (file) {\n        if (_this3.getAddedFiles().length === 0 && _this3.getUploadingFiles().length === 0 && _this3.getQueuedFiles().length === 0) {\n          // This needs to be deferred so that `queuecomplete` really triggers after `complete`\n          return setTimeout(function () {\n            return _this3.emit(\"queuecomplete\");\n          }, 0);\n        }\n      });\n\n      var noPropagation = function noPropagation(e) {\n        e.stopPropagation();\n        if (e.preventDefault) {\n          return e.preventDefault();\n        } else {\n          return e.returnValue = false;\n        }\n      };\n\n      // Create the listeners\n      this.listeners = [{\n        element: this.element,\n        events: {\n          \"dragstart\": function dragstart(e) {\n            return _this3.emit(\"dragstart\", e);\n          },\n          \"dragenter\": function dragenter(e) {\n            noPropagation(e);\n            return _this3.emit(\"dragenter\", e);\n          },\n          \"dragover\": function dragover(e) {\n            // Makes it possible to drag files from chrome's download bar\n            // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar\n            // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception)\n            var efct = void 0;\n            try {\n              efct = e.dataTransfer.effectAllowed;\n            } catch (error) {}\n            e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';\n\n            noPropagation(e);\n            return _this3.emit(\"dragover\", e);\n          },\n          \"dragleave\": function dragleave(e) {\n            return _this3.emit(\"dragleave\", e);\n          },\n          \"drop\": function drop(e) {\n            noPropagation(e);\n            return _this3.drop(e);\n          },\n          \"dragend\": function dragend(e) {\n            return _this3.emit(\"dragend\", e);\n          }\n\n          // This is disabled right now, because the browsers don't implement it properly.\n          // \"paste\": (e) =>\n          //   noPropagation e\n          //   @paste e\n        } }];\n\n      this.clickableElements.forEach(function (clickableElement) {\n        return _this3.listeners.push({\n          element: clickableElement,\n          events: {\n            \"click\": function click(evt) {\n              // Only the actual dropzone or the message element should trigger file selection\n              if (clickableElement !== _this3.element || evt.target === _this3.element || Dropzone.elementInside(evt.target, _this3.element.querySelector(\".dz-message\"))) {\n                _this3.hiddenFileInput.click(); // Forward the click\n              }\n              return true;\n            }\n          }\n        });\n      });\n\n      this.enable();\n\n      return this.options.init.call(this);\n    }\n\n    // Not fully tested yet\n\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      this.disable();\n      this.removeAllFiles(true);\n      if (this.hiddenFileInput != null ? this.hiddenFileInput.parentNode : undefined) {\n        this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);\n        this.hiddenFileInput = null;\n      }\n      delete this.element.dropzone;\n      return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);\n    }\n  }, {\n    key: \"updateTotalUploadProgress\",\n    value: function updateTotalUploadProgress() {\n      var totalUploadProgress = void 0;\n      var totalBytesSent = 0;\n      var totalBytes = 0;\n\n      var activeFiles = this.getActiveFiles();\n\n      if (activeFiles.length) {\n        for (var _iterator12 = this.getActiveFiles(), _isArray12 = Array.isArray(_iterator12), _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) {\n          var _ref11;\n\n          if (_isArray12) {\n            if (_i12 >= _iterator12.length) break;\n            _ref11 = _iterator12[_i12++];\n          } else {\n            _i12 = _iterator12.next();\n            if (_i12.done) break;\n            _ref11 = _i12.value;\n          }\n\n          var file = _ref11;\n\n          totalBytesSent += file.upload.bytesSent;\n          totalBytes += file.upload.total;\n        }\n        totalUploadProgress = 100 * totalBytesSent / totalBytes;\n      } else {\n        totalUploadProgress = 100;\n      }\n\n      return this.emit(\"totaluploadprogress\", totalUploadProgress, totalBytes, totalBytesSent);\n    }\n\n    // @options.paramName can be a function taking one parameter rather than a string.\n    // A parameter name for a file is obtained simply by calling this with an index number.\n\n  }, {\n    key: \"_getParamName\",\n    value: function _getParamName(n) {\n      if (typeof this.options.paramName === \"function\") {\n        return this.options.paramName(n);\n      } else {\n        return \"\" + this.options.paramName + (this.options.uploadMultiple ? \"[\" + n + \"]\" : \"\");\n      }\n    }\n\n    // If @options.renameFile is a function,\n    // the function will be used to rename the file.name before appending it to the formData\n\n  }, {\n    key: \"_renameFile\",\n    value: function _renameFile(file) {\n      if (typeof this.options.renameFile !== \"function\") {\n        return file.name;\n      }\n      return this.options.renameFile(file);\n    }\n\n    // Returns a form that can be used as fallback if the browser does not support DragnDrop\n    //\n    // If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided.\n    // This code has to pass in IE7 :(\n\n  }, {\n    key: \"getFallbackForm\",\n    value: function getFallbackForm() {\n      var existingFallback = void 0,\n          form = void 0;\n      if (existingFallback = this.getExistingFallback()) {\n        return existingFallback;\n      }\n\n      var fieldsString = \"<div class=\\\"dz-fallback\\\">\";\n      if (this.options.dictFallbackText) {\n        fieldsString += \"<p>\" + this.options.dictFallbackText + \"</p>\";\n      }\n      fieldsString += \"<input type=\\\"file\\\" name=\\\"\" + this._getParamName(0) + \"\\\" \" + (this.options.uploadMultiple ? 'multiple=\"multiple\"' : undefined) + \" /><input type=\\\"submit\\\" value=\\\"Upload!\\\"></div>\";\n\n      var fields = Dropzone.createElement(fieldsString);\n      if (this.element.tagName !== \"FORM\") {\n        form = Dropzone.createElement(\"<form action=\\\"\" + this.options.url + \"\\\" enctype=\\\"multipart/form-data\\\" method=\\\"\" + this.options.method + \"\\\"></form>\");\n        form.appendChild(fields);\n      } else {\n        // Make sure that the enctype and method attributes are set properly\n        this.element.setAttribute(\"enctype\", \"multipart/form-data\");\n        this.element.setAttribute(\"method\", this.options.method);\n      }\n      return form != null ? form : fields;\n    }\n\n    // Returns the fallback elements if they exist already\n    //\n    // This code has to pass in IE7 :(\n\n  }, {\n    key: \"getExistingFallback\",\n    value: function getExistingFallback() {\n      var getFallback = function getFallback(elements) {\n        for (var _iterator13 = elements, _isArray13 = Array.isArray(_iterator13), _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) {\n          var _ref12;\n\n          if (_isArray13) {\n            if (_i13 >= _iterator13.length) break;\n            _ref12 = _iterator13[_i13++];\n          } else {\n            _i13 = _iterator13.next();\n            if (_i13.done) break;\n            _ref12 = _i13.value;\n          }\n\n          var el = _ref12;\n\n          if (/(^| )fallback($| )/.test(el.className)) {\n            return el;\n          }\n        }\n      };\n\n      var _arr = [\"div\", \"form\"];\n      for (var _i14 = 0; _i14 < _arr.length; _i14++) {\n        var tagName = _arr[_i14];\n        var fallback;\n        if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {\n          return fallback;\n        }\n      }\n    }\n\n    // Activates all listeners stored in @listeners\n\n  }, {\n    key: \"setupEventListeners\",\n    value: function setupEventListeners() {\n      return this.listeners.map(function (elementListeners) {\n        return function () {\n          var result = [];\n          for (var event in elementListeners.events) {\n            var listener = elementListeners.events[event];\n            result.push(elementListeners.element.addEventListener(event, listener, false));\n          }\n          return result;\n        }();\n      });\n    }\n\n    // Deactivates all listeners stored in @listeners\n\n  }, {\n    key: \"removeEventListeners\",\n    value: function removeEventListeners() {\n      return this.listeners.map(function (elementListeners) {\n        return function () {\n          var result = [];\n          for (var event in elementListeners.events) {\n            var listener = elementListeners.events[event];\n            result.push(elementListeners.element.removeEventListener(event, listener, false));\n          }\n          return result;\n        }();\n      });\n    }\n\n    // Removes all event listeners and cancels all files in the queue or being processed.\n\n  }, {\n    key: \"disable\",\n    value: function disable() {\n      var _this4 = this;\n\n      this.clickableElements.forEach(function (element) {\n        return element.classList.remove(\"dz-clickable\");\n      });\n      this.removeEventListeners();\n      this.disabled = true;\n\n      return this.files.map(function (file) {\n        return _this4.cancelUpload(file);\n      });\n    }\n  }, {\n    key: \"enable\",\n    value: function enable() {\n      delete this.disabled;\n      this.clickableElements.forEach(function (element) {\n        return element.classList.add(\"dz-clickable\");\n      });\n      return this.setupEventListeners();\n    }\n\n    // Returns a nicely formatted filesize\n\n  }, {\n    key: \"filesize\",\n    value: function filesize(size) {\n      var selectedSize = 0;\n      var selectedUnit = \"b\";\n\n      if (size > 0) {\n        var units = ['tb', 'gb', 'mb', 'kb', 'b'];\n\n        for (var i = 0; i < units.length; i++) {\n          var unit = units[i];\n          var cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;\n\n          if (size >= cutoff) {\n            selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);\n            selectedUnit = unit;\n            break;\n          }\n        }\n\n        selectedSize = Math.round(10 * selectedSize) / 10; // Cutting of digits\n      }\n\n      return \"<strong>\" + selectedSize + \"</strong> \" + this.options.dictFileSizeUnits[selectedUnit];\n    }\n\n    // Adds or removes the `dz-max-files-reached` class from the form.\n\n  }, {\n    key: \"_updateMaxFilesReachedClass\",\n    value: function _updateMaxFilesReachedClass() {\n      if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {\n        if (this.getAcceptedFiles().length === this.options.maxFiles) {\n          this.emit('maxfilesreached', this.files);\n        }\n        return this.element.classList.add(\"dz-max-files-reached\");\n      } else {\n        return this.element.classList.remove(\"dz-max-files-reached\");\n      }\n    }\n  }, {\n    key: \"drop\",\n    value: function drop(e) {\n      if (!e.dataTransfer) {\n        return;\n      }\n      this.emit(\"drop\", e);\n\n      // Convert the FileList to an Array\n      // This is necessary for IE11\n      var files = [];\n      for (var i = 0; i < e.dataTransfer.files.length; i++) {\n        files[i] = e.dataTransfer.files[i];\n      }\n\n      this.emit(\"addedfiles\", files);\n\n      // Even if it's a folder, files.length will contain the folders.\n      if (files.length) {\n        var items = e.dataTransfer.items;\n\n        if (items && items.length && items[0].webkitGetAsEntry != null) {\n          // The browser supports dropping of folders, so handle items instead of files\n          this._addFilesFromItems(items);\n        } else {\n          this.handleFiles(files);\n        }\n      }\n    }\n  }, {\n    key: \"paste\",\n    value: function paste(e) {\n      if (__guard__(e != null ? e.clipboardData : undefined, function (x) {\n        return x.items;\n      }) == null) {\n        return;\n      }\n\n      this.emit(\"paste\", e);\n      var items = e.clipboardData.items;\n\n\n      if (items.length) {\n        return this._addFilesFromItems(items);\n      }\n    }\n  }, {\n    key: \"handleFiles\",\n    value: function handleFiles(files) {\n      for (var _iterator14 = files, _isArray14 = Array.isArray(_iterator14), _i15 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) {\n        var _ref13;\n\n        if (_isArray14) {\n          if (_i15 >= _iterator14.length) break;\n          _ref13 = _iterator14[_i15++];\n        } else {\n          _i15 = _iterator14.next();\n          if (_i15.done) break;\n          _ref13 = _i15.value;\n        }\n\n        var file = _ref13;\n\n        this.addFile(file);\n      }\n    }\n\n    // When a folder is dropped (or files are pasted), items must be handled\n    // instead of files.\n\n  }, {\n    key: \"_addFilesFromItems\",\n    value: function _addFilesFromItems(items) {\n      var _this5 = this;\n\n      return function () {\n        var result = [];\n        for (var _iterator15 = items, _isArray15 = Array.isArray(_iterator15), _i16 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) {\n          var _ref14;\n\n          if (_isArray15) {\n            if (_i16 >= _iterator15.length) break;\n            _ref14 = _iterator15[_i16++];\n          } else {\n            _i16 = _iterator15.next();\n            if (_i16.done) break;\n            _ref14 = _i16.value;\n          }\n\n          var item = _ref14;\n\n          var entry;\n          if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) {\n            if (entry.isFile) {\n              result.push(_this5.addFile(item.getAsFile()));\n            } else if (entry.isDirectory) {\n              // Append all files from that directory to files\n              result.push(_this5._addFilesFromDirectory(entry, entry.name));\n            } else {\n              result.push(undefined);\n            }\n          } else if (item.getAsFile != null) {\n            if (item.kind == null || item.kind === \"file\") {\n              result.push(_this5.addFile(item.getAsFile()));\n            } else {\n              result.push(undefined);\n            }\n          } else {\n            result.push(undefined);\n          }\n        }\n        return result;\n      }();\n    }\n\n    // Goes through the directory, and adds each file it finds recursively\n\n  }, {\n    key: \"_addFilesFromDirectory\",\n    value: function _addFilesFromDirectory(directory, path) {\n      var _this6 = this;\n\n      var dirReader = directory.createReader();\n\n      var errorHandler = function errorHandler(error) {\n        return __guardMethod__(console, 'log', function (o) {\n          return o.log(error);\n        });\n      };\n\n      var readEntries = function readEntries() {\n        return dirReader.readEntries(function (entries) {\n          if (entries.length > 0) {\n            for (var _iterator16 = entries, _isArray16 = Array.isArray(_iterator16), _i17 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) {\n              var _ref15;\n\n              if (_isArray16) {\n                if (_i17 >= _iterator16.length) break;\n                _ref15 = _iterator16[_i17++];\n              } else {\n                _i17 = _iterator16.next();\n                if (_i17.done) break;\n                _ref15 = _i17.value;\n              }\n\n              var entry = _ref15;\n\n              if (entry.isFile) {\n                entry.file(function (file) {\n                  if (_this6.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {\n                    return;\n                  }\n                  file.fullPath = path + \"/\" + file.name;\n                  return _this6.addFile(file);\n                });\n              } else if (entry.isDirectory) {\n                _this6._addFilesFromDirectory(entry, path + \"/\" + entry.name);\n              }\n            }\n\n            // Recursively call readEntries() again, since browser only handle\n            // the first 100 entries.\n            // See: https://developer.mozilla.org/en-US/docs/Web/API/DirectoryReader#readEntries\n            readEntries();\n          }\n          return null;\n        }, errorHandler);\n      };\n\n      return readEntries();\n    }\n\n    // If `done()` is called without argument the file is accepted\n    // If you call it with an error message, the file is rejected\n    // (This allows for asynchronous validation)\n    //\n    // This function checks the filesize, and if the file.type passes the\n    // `acceptedFiles` check.\n\n  }, {\n    key: \"accept\",\n    value: function accept(file, done) {\n      if (file.size > this.options.maxFilesize * 1024 * 1024) {\n        return done(this.options.dictFileTooBig.replace(\"{{filesize}}\", Math.round(file.size / 1024 / 10.24) / 100).replace(\"{{maxFilesize}}\", this.options.maxFilesize));\n      } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {\n        return done(this.options.dictInvalidFileType);\n      } else if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {\n        done(this.options.dictMaxFilesExceeded.replace(\"{{maxFiles}}\", this.options.maxFiles));\n        return this.emit(\"maxfilesexceeded\", file);\n      } else {\n        return this.options.accept.call(this, file, done);\n      }\n    }\n  }, {\n    key: \"addFile\",\n    value: function addFile(file) {\n      var _this7 = this;\n\n      file.upload = {\n        uuid: Dropzone.uuidv4(),\n        progress: 0,\n        // Setting the total upload size to file.size for the beginning\n        // It's actual different than the size to be transmitted.\n        total: file.size,\n        bytesSent: 0,\n        filename: this._renameFile(file),\n        chunked: this.options.chunking && (this.options.forceChunking || file.size > this.options.chunkSize),\n        totalChunkCount: Math.ceil(file.size / this.options.chunkSize)\n      };\n      this.files.push(file);\n\n      file.status = Dropzone.ADDED;\n\n      this.emit(\"addedfile\", file);\n\n      this._enqueueThumbnail(file);\n\n      return this.accept(file, function (error) {\n        if (error) {\n          file.accepted = false;\n          _this7._errorProcessing([file], error); // Will set the file.status\n        } else {\n          file.accepted = true;\n          if (_this7.options.autoQueue) {\n            _this7.enqueueFile(file);\n          } // Will set .accepted = true\n        }\n        return _this7._updateMaxFilesReachedClass();\n      });\n    }\n\n    // Wrapper for enqueueFile\n\n  }, {\n    key: \"enqueueFiles\",\n    value: function enqueueFiles(files) {\n      for (var _iterator17 = files, _isArray17 = Array.isArray(_iterator17), _i18 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) {\n        var _ref16;\n\n        if (_isArray17) {\n          if (_i18 >= _iterator17.length) break;\n          _ref16 = _iterator17[_i18++];\n        } else {\n          _i18 = _iterator17.next();\n          if (_i18.done) break;\n          _ref16 = _i18.value;\n        }\n\n        var file = _ref16;\n\n        this.enqueueFile(file);\n      }\n      return null;\n    }\n  }, {\n    key: \"enqueueFile\",\n    value: function enqueueFile(file) {\n      var _this8 = this;\n\n      if (file.status === Dropzone.ADDED && file.accepted === true) {\n        file.status = Dropzone.QUEUED;\n        if (this.options.autoProcessQueue) {\n          return setTimeout(function () {\n            return _this8.processQueue();\n          }, 0); // Deferring the call\n        }\n      } else {\n        throw new Error(\"This file can't be queued because it has already been processed or was rejected.\");\n      }\n    }\n  }, {\n    key: \"_enqueueThumbnail\",\n    value: function _enqueueThumbnail(file) {\n      var _this9 = this;\n\n      if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {\n        this._thumbnailQueue.push(file);\n        return setTimeout(function () {\n          return _this9._processThumbnailQueue();\n        }, 0); // Deferring the call\n      }\n    }\n  }, {\n    key: \"_processThumbnailQueue\",\n    value: function _processThumbnailQueue() {\n      var _this10 = this;\n\n      if (this._processingThumbnail || this._thumbnailQueue.length === 0) {\n        return;\n      }\n\n      this._processingThumbnail = true;\n      var file = this._thumbnailQueue.shift();\n      return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, function (dataUrl) {\n        _this10.emit(\"thumbnail\", file, dataUrl);\n        _this10._processingThumbnail = false;\n        return _this10._processThumbnailQueue();\n      });\n    }\n\n    // Can be called by the user to remove a file\n\n  }, {\n    key: \"removeFile\",\n    value: function removeFile(file) {\n      if (file.status === Dropzone.UPLOADING) {\n        this.cancelUpload(file);\n      }\n      this.files = without(this.files, file);\n\n      this.emit(\"removedfile\", file);\n      if (this.files.length === 0) {\n        return this.emit(\"reset\");\n      }\n    }\n\n    // Removes all files that aren't currently processed from the list\n\n  }, {\n    key: \"removeAllFiles\",\n    value: function removeAllFiles(cancelIfNecessary) {\n      // Create a copy of files since removeFile() changes the @files array.\n      if (cancelIfNecessary == null) {\n        cancelIfNecessary = false;\n      }\n      for (var _iterator18 = this.files.slice(), _isArray18 = Array.isArray(_iterator18), _i19 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) {\n        var _ref17;\n\n        if (_isArray18) {\n          if (_i19 >= _iterator18.length) break;\n          _ref17 = _iterator18[_i19++];\n        } else {\n          _i19 = _iterator18.next();\n          if (_i19.done) break;\n          _ref17 = _i19.value;\n        }\n\n        var file = _ref17;\n\n        if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {\n          this.removeFile(file);\n        }\n      }\n      return null;\n    }\n\n    // Resizes an image before it gets sent to the server. This function is the default behavior of\n    // `options.transformFile` if `resizeWidth` or `resizeHeight` are set. The callback is invoked with\n    // the resized blob.\n\n  }, {\n    key: \"resizeImage\",\n    value: function resizeImage(file, width, height, resizeMethod, callback) {\n      var _this11 = this;\n\n      return this.createThumbnail(file, width, height, resizeMethod, false, function (dataUrl, canvas) {\n        if (canvas == null) {\n          // The image has not been resized\n          return callback(file);\n        } else {\n          var resizeMimeType = _this11.options.resizeMimeType;\n\n          if (resizeMimeType == null) {\n            resizeMimeType = file.type;\n          }\n          var resizedDataURL = canvas.toDataURL(resizeMimeType, _this11.options.resizeQuality);\n          if (resizeMimeType === 'image/jpeg' || resizeMimeType === 'image/jpg') {\n            // Now add the original EXIF information\n            resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL);\n          }\n          return callback(Dropzone.dataURItoBlob(resizedDataURL));\n        }\n      });\n    }\n  }, {\n    key: \"createThumbnail\",\n    value: function createThumbnail(file, width, height, resizeMethod, fixOrientation, callback) {\n      var _this12 = this;\n\n      var fileReader = new FileReader();\n\n      fileReader.onload = function () {\n\n        file.dataURL = fileReader.result;\n\n        // Don't bother creating a thumbnail for SVG images since they're vector\n        if (file.type === \"image/svg+xml\") {\n          if (callback != null) {\n            callback(fileReader.result);\n          }\n          return;\n        }\n\n        return _this12.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback);\n      };\n\n      return fileReader.readAsDataURL(file);\n    }\n  }, {\n    key: \"createThumbnailFromUrl\",\n    value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) {\n      var _this13 = this;\n\n      // Not using `new Image` here because of a bug in latest Chrome versions.\n      // See https://github.com/enyo/dropzone/pull/226\n      var img = document.createElement(\"img\");\n\n      if (crossOrigin) {\n        img.crossOrigin = crossOrigin;\n      }\n\n      img.onload = function () {\n        var loadExif = function loadExif(callback) {\n          return callback(1);\n        };\n        if (typeof EXIF !== 'undefined' && EXIF !== null && fixOrientation) {\n          loadExif = function loadExif(callback) {\n            return EXIF.getData(img, function () {\n              return callback(EXIF.getTag(this, 'Orientation'));\n            });\n          };\n        }\n\n        return loadExif(function (orientation) {\n          file.width = img.width;\n          file.height = img.height;\n\n          var resizeInfo = _this13.options.resize.call(_this13, file, width, height, resizeMethod);\n\n          var canvas = document.createElement(\"canvas\");\n          var ctx = canvas.getContext(\"2d\");\n\n          canvas.width = resizeInfo.trgWidth;\n          canvas.height = resizeInfo.trgHeight;\n\n          if (orientation > 4) {\n            canvas.width = resizeInfo.trgHeight;\n            canvas.height = resizeInfo.trgWidth;\n          }\n\n          switch (orientation) {\n            case 2:\n              // horizontal flip\n              ctx.translate(canvas.width, 0);\n              ctx.scale(-1, 1);\n              break;\n            case 3:\n              // 180° rotate left\n              ctx.translate(canvas.width, canvas.height);\n              ctx.rotate(Math.PI);\n              break;\n            case 4:\n              // vertical flip\n              ctx.translate(0, canvas.height);\n              ctx.scale(1, -1);\n              break;\n            case 5:\n              // vertical flip + 90 rotate right\n              ctx.rotate(0.5 * Math.PI);\n              ctx.scale(1, -1);\n              break;\n            case 6:\n              // 90° rotate right\n              ctx.rotate(0.5 * Math.PI);\n              ctx.translate(0, -canvas.height);\n              break;\n            case 7:\n              // horizontal flip + 90 rotate right\n              ctx.rotate(0.5 * Math.PI);\n              ctx.translate(canvas.width, -canvas.height);\n              ctx.scale(-1, 1);\n              break;\n            case 8:\n              // 90° rotate left\n              ctx.rotate(-0.5 * Math.PI);\n              ctx.translate(-canvas.width, 0);\n              break;\n          }\n\n          // This is a bugfix for iOS' scaling bug.\n          drawImageIOSFix(ctx, img, resizeInfo.srcX != null ? resizeInfo.srcX : 0, resizeInfo.srcY != null ? resizeInfo.srcY : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, resizeInfo.trgX != null ? resizeInfo.trgX : 0, resizeInfo.trgY != null ? resizeInfo.trgY : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);\n\n          var thumbnail = canvas.toDataURL(\"image/png\");\n\n          if (callback != null) {\n            return callback(thumbnail, canvas);\n          }\n        });\n      };\n\n      if (callback != null) {\n        img.onerror = callback;\n      }\n\n      return img.src = file.dataURL;\n    }\n\n    // Goes through the queue and processes files if there aren't too many already.\n\n  }, {\n    key: \"processQueue\",\n    value: function processQueue() {\n      var parallelUploads = this.options.parallelUploads;\n\n      var processingLength = this.getUploadingFiles().length;\n      var i = processingLength;\n\n      // There are already at least as many files uploading than should be\n      if (processingLength >= parallelUploads) {\n        return;\n      }\n\n      var queuedFiles = this.getQueuedFiles();\n\n      if (!(queuedFiles.length > 0)) {\n        return;\n      }\n\n      if (this.options.uploadMultiple) {\n        // The files should be uploaded in one request\n        return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));\n      } else {\n        while (i < parallelUploads) {\n          if (!queuedFiles.length) {\n            return;\n          } // Nothing left to process\n          this.processFile(queuedFiles.shift());\n          i++;\n        }\n      }\n    }\n\n    // Wrapper for `processFiles`\n\n  }, {\n    key: \"processFile\",\n    value: function processFile(file) {\n      return this.processFiles([file]);\n    }\n\n    // Loads the file, then calls finishedLoading()\n\n  }, {\n    key: \"processFiles\",\n    value: function processFiles(files) {\n      for (var _iterator19 = files, _isArray19 = Array.isArray(_iterator19), _i20 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) {\n        var _ref18;\n\n        if (_isArray19) {\n          if (_i20 >= _iterator19.length) break;\n          _ref18 = _iterator19[_i20++];\n        } else {\n          _i20 = _iterator19.next();\n          if (_i20.done) break;\n          _ref18 = _i20.value;\n        }\n\n        var file = _ref18;\n\n        file.processing = true; // Backwards compatibility\n        file.status = Dropzone.UPLOADING;\n\n        this.emit(\"processing\", file);\n      }\n\n      if (this.options.uploadMultiple) {\n        this.emit(\"processingmultiple\", files);\n      }\n\n      return this.uploadFiles(files);\n    }\n  }, {\n    key: \"_getFilesWithXhr\",\n    value: function _getFilesWithXhr(xhr) {\n      var files = void 0;\n      return files = this.files.filter(function (file) {\n        return file.xhr === xhr;\n      }).map(function (file) {\n        return file;\n      });\n    }\n\n    // Cancels the file upload and sets the status to CANCELED\n    // **if** the file is actually being uploaded.\n    // If it's still in the queue, the file is being removed from it and the status\n    // set to CANCELED.\n\n  }, {\n    key: \"cancelUpload\",\n    value: function cancelUpload(file) {\n      if (file.status === Dropzone.UPLOADING) {\n        var groupedFiles = this._getFilesWithXhr(file.xhr);\n        for (var _iterator20 = groupedFiles, _isArray20 = Array.isArray(_iterator20), _i21 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) {\n          var _ref19;\n\n          if (_isArray20) {\n            if (_i21 >= _iterator20.length) break;\n            _ref19 = _iterator20[_i21++];\n          } else {\n            _i21 = _iterator20.next();\n            if (_i21.done) break;\n            _ref19 = _i21.value;\n          }\n\n          var groupedFile = _ref19;\n\n          groupedFile.status = Dropzone.CANCELED;\n        }\n        if (typeof file.xhr !== 'undefined') {\n          file.xhr.abort();\n        }\n        for (var _iterator21 = groupedFiles, _isArray21 = Array.isArray(_iterator21), _i22 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) {\n          var _ref20;\n\n          if (_isArray21) {\n            if (_i22 >= _iterator21.length) break;\n            _ref20 = _iterator21[_i22++];\n          } else {\n            _i22 = _iterator21.next();\n            if (_i22.done) break;\n            _ref20 = _i22.value;\n          }\n\n          var _groupedFile = _ref20;\n\n          this.emit(\"canceled\", _groupedFile);\n        }\n        if (this.options.uploadMultiple) {\n          this.emit(\"canceledmultiple\", groupedFiles);\n        }\n      } else if (file.status === Dropzone.ADDED || file.status === Dropzone.QUEUED) {\n        file.status = Dropzone.CANCELED;\n        this.emit(\"canceled\", file);\n        if (this.options.uploadMultiple) {\n          this.emit(\"canceledmultiple\", [file]);\n        }\n      }\n\n      if (this.options.autoProcessQueue) {\n        return this.processQueue();\n      }\n    }\n  }, {\n    key: \"resolveOption\",\n    value: function resolveOption(option) {\n      if (typeof option === 'function') {\n        for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n          args[_key3 - 1] = arguments[_key3];\n        }\n\n        return option.apply(this, args);\n      }\n      return option;\n    }\n  }, {\n    key: \"uploadFile\",\n    value: function uploadFile(file) {\n      return this.uploadFiles([file]);\n    }\n  }, {\n    key: \"uploadFiles\",\n    value: function uploadFiles(files) {\n      var _this14 = this;\n\n      this._transformFiles(files, function (transformedFiles) {\n        if (files[0].upload.chunked) {\n          // This file should be sent in chunks!\n\n          // If the chunking option is set, we **know** that there can only be **one** file, since\n          // uploadMultiple is not allowed with this option.\n          var file = files[0];\n          var transformedFile = transformedFiles[0];\n          var startedChunkCount = 0;\n\n          file.upload.chunks = [];\n\n          var handleNextChunk = function handleNextChunk() {\n            var chunkIndex = 0;\n\n            // Find the next item in file.upload.chunks that is not defined yet.\n            while (file.upload.chunks[chunkIndex] !== undefined) {\n              chunkIndex++;\n            }\n\n            // This means, that all chunks have already been started.\n            if (chunkIndex >= file.upload.totalChunkCount) return;\n\n            startedChunkCount++;\n\n            var start = chunkIndex * _this14.options.chunkSize;\n            var end = Math.min(start + _this14.options.chunkSize, file.size);\n\n            var dataBlock = {\n              name: _this14._getParamName(0),\n              data: transformedFile.webkitSlice ? transformedFile.webkitSlice(start, end) : transformedFile.slice(start, end),\n              filename: file.upload.filename,\n              chunkIndex: chunkIndex\n            };\n\n            file.upload.chunks[chunkIndex] = {\n              file: file,\n              index: chunkIndex,\n              dataBlock: dataBlock, // In case we want to retry.\n              status: Dropzone.UPLOADING,\n              progress: 0,\n              retries: 0 // The number of times this block has been retried.\n            };\n\n            _this14._uploadData(files, [dataBlock]);\n          };\n\n          file.upload.finishedChunkUpload = function (chunk) {\n            var allFinished = true;\n            chunk.status = Dropzone.SUCCESS;\n\n            // Clear the data from the chunk\n            chunk.dataBlock = null;\n\n            for (var i = 0; i < file.upload.totalChunkCount; i++) {\n              if (file.upload.chunks[i] === undefined) {\n                return handleNextChunk();\n              }\n              if (file.upload.chunks[i].status !== Dropzone.SUCCESS) {\n                allFinished = false;\n              }\n            }\n\n            if (allFinished) {\n              _this14.options.chunksUploaded(file, function () {\n                _this14._finished(files, '', null);\n              });\n            }\n          };\n\n          if (_this14.options.parallelChunkUploads) {\n            for (var i = 0; i < file.upload.totalChunkCount; i++) {\n              handleNextChunk();\n            }\n          } else {\n            handleNextChunk();\n          }\n        } else {\n          var dataBlocks = [];\n          for (var _i23 = 0; _i23 < files.length; _i23++) {\n            dataBlocks[_i23] = {\n              name: _this14._getParamName(_i23),\n              data: transformedFiles[_i23],\n              filename: files[_i23].upload.filename\n            };\n          }\n          _this14._uploadData(files, dataBlocks);\n        }\n      });\n    }\n\n    /// Returns the right chunk for given file and xhr\n\n  }, {\n    key: \"_getChunk\",\n    value: function _getChunk(file, xhr) {\n      for (var i = 0; i < file.upload.totalChunkCount; i++) {\n        if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].xhr === xhr) {\n          return file.upload.chunks[i];\n        }\n      }\n    }\n\n    // This function actually uploads the file(s) to the server.\n    // If dataBlocks contains the actual data to upload (meaning, that this could either be transformed\n    // files, or individual chunks for chunked upload).\n\n  }, {\n    key: \"_uploadData\",\n    value: function _uploadData(files, dataBlocks) {\n      var _this15 = this;\n\n      var xhr = new XMLHttpRequest();\n\n      // Put the xhr object in the file objects to be able to reference it later.\n      for (var _iterator22 = files, _isArray22 = Array.isArray(_iterator22), _i24 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) {\n        var _ref21;\n\n        if (_isArray22) {\n          if (_i24 >= _iterator22.length) break;\n          _ref21 = _iterator22[_i24++];\n        } else {\n          _i24 = _iterator22.next();\n          if (_i24.done) break;\n          _ref21 = _i24.value;\n        }\n\n        var file = _ref21;\n\n        file.xhr = xhr;\n      }\n      if (files[0].upload.chunked) {\n        // Put the xhr object in the right chunk object, so it can be associated later, and found with _getChunk\n        files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr = xhr;\n      }\n\n      var method = this.resolveOption(this.options.method, files);\n      var url = this.resolveOption(this.options.url, files);\n      xhr.open(method, url, true);\n\n      // Setting the timeout after open because of IE11 issue: https://gitlab.com/meno/dropzone/issues/8\n      xhr.timeout = this.resolveOption(this.options.timeout, files);\n\n      // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179\n      xhr.withCredentials = !!this.options.withCredentials;\n\n      xhr.onload = function (e) {\n        _this15._finishedUploading(files, xhr, e);\n      };\n\n      xhr.onerror = function () {\n        _this15._handleUploadError(files, xhr);\n      };\n\n      // Some browsers do not have the .upload property\n      var progressObj = xhr.upload != null ? xhr.upload : xhr;\n      progressObj.onprogress = function (e) {\n        return _this15._updateFilesUploadProgress(files, xhr, e);\n      };\n\n      var headers = {\n        \"Accept\": \"application/json\",\n        \"Cache-Control\": \"no-cache\",\n        \"X-Requested-With\": \"XMLHttpRequest\"\n      };\n\n      if (this.options.headers) {\n        Dropzone.extend(headers, this.options.headers);\n      }\n\n      for (var headerName in headers) {\n        var headerValue = headers[headerName];\n        if (headerValue) {\n          xhr.setRequestHeader(headerName, headerValue);\n        }\n      }\n\n      var formData = new FormData();\n\n      // Adding all @options parameters\n      if (this.options.params) {\n        var additionalParams = this.options.params;\n        if (typeof additionalParams === 'function') {\n          additionalParams = additionalParams.call(this, files, xhr, files[0].upload.chunked ? this._getChunk(files[0], xhr) : null);\n        }\n\n        for (var key in additionalParams) {\n          var value = additionalParams[key];\n          formData.append(key, value);\n        }\n      }\n\n      // Let the user add additional data if necessary\n      for (var _iterator23 = files, _isArray23 = Array.isArray(_iterator23), _i25 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) {\n        var _ref22;\n\n        if (_isArray23) {\n          if (_i25 >= _iterator23.length) break;\n          _ref22 = _iterator23[_i25++];\n        } else {\n          _i25 = _iterator23.next();\n          if (_i25.done) break;\n          _ref22 = _i25.value;\n        }\n\n        var _file = _ref22;\n\n        this.emit(\"sending\", _file, xhr, formData);\n      }\n      if (this.options.uploadMultiple) {\n        this.emit(\"sendingmultiple\", files, xhr, formData);\n      }\n\n      this._addFormElementData(formData);\n\n      // Finally add the files\n      // Has to be last because some servers (eg: S3) expect the file to be the last parameter\n      for (var i = 0; i < dataBlocks.length; i++) {\n        var dataBlock = dataBlocks[i];\n        formData.append(dataBlock.name, dataBlock.data, dataBlock.filename);\n      }\n\n      this.submitRequest(xhr, formData, files);\n    }\n\n    // Transforms all files with this.options.transformFile and invokes done with the transformed files when done.\n\n  }, {\n    key: \"_transformFiles\",\n    value: function _transformFiles(files, done) {\n      var _this16 = this;\n\n      var transformedFiles = [];\n      // Clumsy way of handling asynchronous calls, until I get to add a proper Future library.\n      var doneCounter = 0;\n\n      var _loop = function _loop(i) {\n        _this16.options.transformFile.call(_this16, files[i], function (transformedFile) {\n          transformedFiles[i] = transformedFile;\n          if (++doneCounter === files.length) {\n            done(transformedFiles);\n          }\n        });\n      };\n\n      for (var i = 0; i < files.length; i++) {\n        _loop(i);\n      }\n    }\n\n    // Takes care of adding other input elements of the form to the AJAX request\n\n  }, {\n    key: \"_addFormElementData\",\n    value: function _addFormElementData(formData) {\n      // Take care of other input elements\n      if (this.element.tagName === \"FORM\") {\n        for (var _iterator24 = this.element.querySelectorAll(\"input, textarea, select, button\"), _isArray24 = Array.isArray(_iterator24), _i26 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) {\n          var _ref23;\n\n          if (_isArray24) {\n            if (_i26 >= _iterator24.length) break;\n            _ref23 = _iterator24[_i26++];\n          } else {\n            _i26 = _iterator24.next();\n            if (_i26.done) break;\n            _ref23 = _i26.value;\n          }\n\n          var input = _ref23;\n\n          var inputName = input.getAttribute(\"name\");\n          var inputType = input.getAttribute(\"type\");\n          if (inputType) inputType = inputType.toLowerCase();\n\n          // If the input doesn't have a name, we can't use it.\n          if (typeof inputName === 'undefined' || inputName === null) continue;\n\n          if (input.tagName === \"SELECT\" && input.hasAttribute(\"multiple\")) {\n            // Possibly multiple values\n            for (var _iterator25 = input.options, _isArray25 = Array.isArray(_iterator25), _i27 = 0, _iterator25 = _isArray25 ? _iterator25 : _iterator25[Symbol.iterator]();;) {\n              var _ref24;\n\n              if (_isArray25) {\n                if (_i27 >= _iterator25.length) break;\n                _ref24 = _iterator25[_i27++];\n              } else {\n                _i27 = _iterator25.next();\n                if (_i27.done) break;\n                _ref24 = _i27.value;\n              }\n\n              var option = _ref24;\n\n              if (option.selected) {\n                formData.append(inputName, option.value);\n              }\n            }\n          } else if (!inputType || inputType !== \"checkbox\" && inputType !== \"radio\" || input.checked) {\n            formData.append(inputName, input.value);\n          }\n        }\n      }\n    }\n\n    // Invoked when there is new progress information about given files.\n    // If e is not provided, it is assumed that the upload is finished.\n\n  }, {\n    key: \"_updateFilesUploadProgress\",\n    value: function _updateFilesUploadProgress(files, xhr, e) {\n      var progress = void 0;\n      if (typeof e !== 'undefined') {\n        progress = 100 * e.loaded / e.total;\n\n        if (files[0].upload.chunked) {\n          var file = files[0];\n          // Since this is a chunked upload, we need to update the appropriate chunk progress.\n          var chunk = this._getChunk(file, xhr);\n          chunk.progress = progress;\n          chunk.total = e.total;\n          chunk.bytesSent = e.loaded;\n          var fileProgress = 0,\n              fileTotal = void 0,\n              fileBytesSent = void 0;\n          file.upload.progress = 0;\n          file.upload.total = 0;\n          file.upload.bytesSent = 0;\n          for (var i = 0; i < file.upload.totalChunkCount; i++) {\n            if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].progress !== undefined) {\n              file.upload.progress += file.upload.chunks[i].progress;\n              file.upload.total += file.upload.chunks[i].total;\n              file.upload.bytesSent += file.upload.chunks[i].bytesSent;\n            }\n          }\n          file.upload.progress = file.upload.progress / file.upload.totalChunkCount;\n        } else {\n          for (var _iterator26 = files, _isArray26 = Array.isArray(_iterator26), _i28 = 0, _iterator26 = _isArray26 ? _iterator26 : _iterator26[Symbol.iterator]();;) {\n            var _ref25;\n\n            if (_isArray26) {\n              if (_i28 >= _iterator26.length) break;\n              _ref25 = _iterator26[_i28++];\n            } else {\n              _i28 = _iterator26.next();\n              if (_i28.done) break;\n              _ref25 = _i28.value;\n            }\n\n            var _file2 = _ref25;\n\n            _file2.upload.progress = progress;\n            _file2.upload.total = e.total;\n            _file2.upload.bytesSent = e.loaded;\n          }\n        }\n        for (var _iterator27 = files, _isArray27 = Array.isArray(_iterator27), _i29 = 0, _iterator27 = _isArray27 ? _iterator27 : _iterator27[Symbol.iterator]();;) {\n          var _ref26;\n\n          if (_isArray27) {\n            if (_i29 >= _iterator27.length) break;\n            _ref26 = _iterator27[_i29++];\n          } else {\n            _i29 = _iterator27.next();\n            if (_i29.done) break;\n            _ref26 = _i29.value;\n          }\n\n          var _file3 = _ref26;\n\n          this.emit(\"uploadprogress\", _file3, _file3.upload.progress, _file3.upload.bytesSent);\n        }\n      } else {\n        // Called when the file finished uploading\n\n        var allFilesFinished = true;\n\n        progress = 100;\n\n        for (var _iterator28 = files, _isArray28 = Array.isArray(_iterator28), _i30 = 0, _iterator28 = _isArray28 ? _iterator28 : _iterator28[Symbol.iterator]();;) {\n          var _ref27;\n\n          if (_isArray28) {\n            if (_i30 >= _iterator28.length) break;\n            _ref27 = _iterator28[_i30++];\n          } else {\n            _i30 = _iterator28.next();\n            if (_i30.done) break;\n            _ref27 = _i30.value;\n          }\n\n          var _file4 = _ref27;\n\n          if (_file4.upload.progress !== 100 || _file4.upload.bytesSent !== _file4.upload.total) {\n            allFilesFinished = false;\n          }\n          _file4.upload.progress = progress;\n          _file4.upload.bytesSent = _file4.upload.total;\n        }\n\n        // Nothing to do, all files already at 100%\n        if (allFilesFinished) {\n          return;\n        }\n\n        for (var _iterator29 = files, _isArray29 = Array.isArray(_iterator29), _i31 = 0, _iterator29 = _isArray29 ? _iterator29 : _iterator29[Symbol.iterator]();;) {\n          var _ref28;\n\n          if (_isArray29) {\n            if (_i31 >= _iterator29.length) break;\n            _ref28 = _iterator29[_i31++];\n          } else {\n            _i31 = _iterator29.next();\n            if (_i31.done) break;\n            _ref28 = _i31.value;\n          }\n\n          var _file5 = _ref28;\n\n          this.emit(\"uploadprogress\", _file5, progress, _file5.upload.bytesSent);\n        }\n      }\n    }\n  }, {\n    key: \"_finishedUploading\",\n    value: function _finishedUploading(files, xhr, e) {\n      var response = void 0;\n\n      if (files[0].status === Dropzone.CANCELED) {\n        return;\n      }\n\n      if (xhr.readyState !== 4) {\n        return;\n      }\n\n      if (xhr.responseType !== 'arraybuffer' && xhr.responseType !== 'blob') {\n        response = xhr.responseText;\n\n        if (xhr.getResponseHeader(\"content-type\") && ~xhr.getResponseHeader(\"content-type\").indexOf(\"application/json\")) {\n          try {\n            response = JSON.parse(response);\n          } catch (error) {\n            e = error;\n            response = \"Invalid JSON response from server.\";\n          }\n        }\n      }\n\n      this._updateFilesUploadProgress(files);\n\n      if (!(200 <= xhr.status && xhr.status < 300)) {\n        this._handleUploadError(files, xhr, response);\n      } else {\n        if (files[0].upload.chunked) {\n          files[0].upload.finishedChunkUpload(this._getChunk(files[0], xhr));\n        } else {\n          this._finished(files, response, e);\n        }\n      }\n    }\n  }, {\n    key: \"_handleUploadError\",\n    value: function _handleUploadError(files, xhr, response) {\n      if (files[0].status === Dropzone.CANCELED) {\n        return;\n      }\n\n      if (files[0].upload.chunked && this.options.retryChunks) {\n        var chunk = this._getChunk(files[0], xhr);\n        if (chunk.retries++ < this.options.retryChunksLimit) {\n          this._uploadData(files, [chunk.dataBlock]);\n          return;\n        } else {\n          console.warn('Retried this chunk too often. Giving up.');\n        }\n      }\n\n      for (var _iterator30 = files, _isArray30 = Array.isArray(_iterator30), _i32 = 0, _iterator30 = _isArray30 ? _iterator30 : _iterator30[Symbol.iterator]();;) {\n        var _ref29;\n\n        if (_isArray30) {\n          if (_i32 >= _iterator30.length) break;\n          _ref29 = _iterator30[_i32++];\n        } else {\n          _i32 = _iterator30.next();\n          if (_i32.done) break;\n          _ref29 = _i32.value;\n        }\n\n        var file = _ref29;\n\n        this._errorProcessing(files, response || this.options.dictResponseError.replace(\"{{statusCode}}\", xhr.status), xhr);\n      }\n    }\n  }, {\n    key: \"submitRequest\",\n    value: function submitRequest(xhr, formData, files) {\n      xhr.send(formData);\n    }\n\n    // Called internally when processing is finished.\n    // Individual callbacks have to be called in the appropriate sections.\n\n  }, {\n    key: \"_finished\",\n    value: function _finished(files, responseText, e) {\n      for (var _iterator31 = files, _isArray31 = Array.isArray(_iterator31), _i33 = 0, _iterator31 = _isArray31 ? _iterator31 : _iterator31[Symbol.iterator]();;) {\n        var _ref30;\n\n        if (_isArray31) {\n          if (_i33 >= _iterator31.length) break;\n          _ref30 = _iterator31[_i33++];\n        } else {\n          _i33 = _iterator31.next();\n          if (_i33.done) break;\n          _ref30 = _i33.value;\n        }\n\n        var file = _ref30;\n\n        file.status = Dropzone.SUCCESS;\n        this.emit(\"success\", file, responseText, e);\n        this.emit(\"complete\", file);\n      }\n      if (this.options.uploadMultiple) {\n        this.emit(\"successmultiple\", files, responseText, e);\n        this.emit(\"completemultiple\", files);\n      }\n\n      if (this.options.autoProcessQueue) {\n        return this.processQueue();\n      }\n    }\n\n    // Called internally when processing is finished.\n    // Individual callbacks have to be called in the appropriate sections.\n\n  }, {\n    key: \"_errorProcessing\",\n    value: function _errorProcessing(files, message, xhr) {\n      for (var _iterator32 = files, _isArray32 = Array.isArray(_iterator32), _i34 = 0, _iterator32 = _isArray32 ? _iterator32 : _iterator32[Symbol.iterator]();;) {\n        var _ref31;\n\n        if (_isArray32) {\n          if (_i34 >= _iterator32.length) break;\n          _ref31 = _iterator32[_i34++];\n        } else {\n          _i34 = _iterator32.next();\n          if (_i34.done) break;\n          _ref31 = _i34.value;\n        }\n\n        var file = _ref31;\n\n        file.status = Dropzone.ERROR;\n        this.emit(\"error\", file, message, xhr);\n        this.emit(\"complete\", file);\n      }\n      if (this.options.uploadMultiple) {\n        this.emit(\"errormultiple\", files, message, xhr);\n        this.emit(\"completemultiple\", files);\n      }\n\n      if (this.options.autoProcessQueue) {\n        return this.processQueue();\n      }\n    }\n  }], [{\n    key: \"uuidv4\",\n    value: function uuidv4() {\n      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n        var r = Math.random() * 16 | 0,\n            v = c === 'x' ? r : r & 0x3 | 0x8;\n        return v.toString(16);\n      });\n    }\n  }]);\n\n  return Dropzone;\n}(Emitter);\n\nDropzone.initClass();\n\nDropzone.version = \"5.4.0\";\n\n// This is a map of options for your different dropzones. Add configurations\n// to this object for your different dropzone elemens.\n//\n// Example:\n//\n//     Dropzone.options.myDropzoneElementId = { maxFilesize: 1 };\n//\n// To disable autoDiscover for a specific element, you can set `false` as an option:\n//\n//     Dropzone.options.myDisabledElementId = false;\n//\n// And in html:\n//\n//     <form action=\"/upload\" id=\"my-dropzone-element-id\" class=\"dropzone\"></form>\nDropzone.options = {};\n\n// Returns the options for an element or undefined if none available.\nDropzone.optionsForElement = function (element) {\n  // Get the `Dropzone.options.elementId` for this element if it exists\n  if (element.getAttribute(\"id\")) {\n    return Dropzone.options[camelize(element.getAttribute(\"id\"))];\n  } else {\n    return undefined;\n  }\n};\n\n// Holds a list of all dropzone instances\nDropzone.instances = [];\n\n// Returns the dropzone for given element if any\nDropzone.forElement = function (element) {\n  if (typeof element === \"string\") {\n    element = document.querySelector(element);\n  }\n  if ((element != null ? element.dropzone : undefined) == null) {\n    throw new Error(\"No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.\");\n  }\n  return element.dropzone;\n};\n\n// Set to false if you don't want Dropzone to automatically find and attach to .dropzone elements.\nDropzone.autoDiscover = true;\n\n// Looks for all .dropzone elements and creates a dropzone for them\nDropzone.discover = function () {\n  var dropzones = void 0;\n  if (document.querySelectorAll) {\n    dropzones = document.querySelectorAll(\".dropzone\");\n  } else {\n    dropzones = [];\n    // IE :(\n    var checkElements = function checkElements(elements) {\n      return function () {\n        var result = [];\n        for (var _iterator33 = elements, _isArray33 = Array.isArray(_iterator33), _i35 = 0, _iterator33 = _isArray33 ? _iterator33 : _iterator33[Symbol.iterator]();;) {\n          var _ref32;\n\n          if (_isArray33) {\n            if (_i35 >= _iterator33.length) break;\n            _ref32 = _iterator33[_i35++];\n          } else {\n            _i35 = _iterator33.next();\n            if (_i35.done) break;\n            _ref32 = _i35.value;\n          }\n\n          var el = _ref32;\n\n          if (/(^| )dropzone($| )/.test(el.className)) {\n            result.push(dropzones.push(el));\n          } else {\n            result.push(undefined);\n          }\n        }\n        return result;\n      }();\n    };\n    checkElements(document.getElementsByTagName(\"div\"));\n    checkElements(document.getElementsByTagName(\"form\"));\n  }\n\n  return function () {\n    var result = [];\n    for (var _iterator34 = dropzones, _isArray34 = Array.isArray(_iterator34), _i36 = 0, _iterator34 = _isArray34 ? _iterator34 : _iterator34[Symbol.iterator]();;) {\n      var _ref33;\n\n      if (_isArray34) {\n        if (_i36 >= _iterator34.length) break;\n        _ref33 = _iterator34[_i36++];\n      } else {\n        _i36 = _iterator34.next();\n        if (_i36.done) break;\n        _ref33 = _i36.value;\n      }\n\n      var dropzone = _ref33;\n\n      // Create a dropzone unless auto discover has been disabled for specific element\n      if (Dropzone.optionsForElement(dropzone) !== false) {\n        result.push(new Dropzone(dropzone));\n      } else {\n        result.push(undefined);\n      }\n    }\n    return result;\n  }();\n};\n\n// Since the whole Drag'n'Drop API is pretty new, some browsers implement it,\n// but not correctly.\n// So I created a blacklist of userAgents. Yes, yes. Browser sniffing, I know.\n// But what to do when browsers *theoretically* support an API, but crash\n// when using it.\n//\n// This is a list of regular expressions tested against navigator.userAgent\n//\n// ** It should only be used on browser that *do* support the API, but\n// incorrectly **\n//\nDropzone.blacklistedBrowsers = [\n// The mac os and windows phone version of opera 12 seems to have a problem with the File drag'n'drop API.\n/opera.*(Macintosh|Windows Phone).*version\\/12/i];\n\n// Checks if the browser is supported\nDropzone.isBrowserSupported = function () {\n  var capableBrowser = true;\n\n  if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {\n    if (!(\"classList\" in document.createElement(\"a\"))) {\n      capableBrowser = false;\n    } else {\n      // The browser supports the API, but may be blacklisted.\n      for (var _iterator35 = Dropzone.blacklistedBrowsers, _isArray35 = Array.isArray(_iterator35), _i37 = 0, _iterator35 = _isArray35 ? _iterator35 : _iterator35[Symbol.iterator]();;) {\n        var _ref34;\n\n        if (_isArray35) {\n          if (_i37 >= _iterator35.length) break;\n          _ref34 = _iterator35[_i37++];\n        } else {\n          _i37 = _iterator35.next();\n          if (_i37.done) break;\n          _ref34 = _i37.value;\n        }\n\n        var regex = _ref34;\n\n        if (regex.test(navigator.userAgent)) {\n          capableBrowser = false;\n          continue;\n        }\n      }\n    }\n  } else {\n    capableBrowser = false;\n  }\n\n  return capableBrowser;\n};\n\nDropzone.dataURItoBlob = function (dataURI) {\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, end = byteString.length, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) {\n    ia[i] = byteString.charCodeAt(i);\n  }\n\n  // write the ArrayBuffer to a blob\n  return new Blob([ab], { type: mimeString });\n};\n\n// Returns an array without the rejected item\nvar without = function without(list, rejectedItem) {\n  return list.filter(function (item) {\n    return item !== rejectedItem;\n  }).map(function (item) {\n    return item;\n  });\n};\n\n// abc-def_ghi -> abcDefGhi\nvar camelize = function camelize(str) {\n  return str.replace(/[\\-_](\\w)/g, function (match) {\n    return match.charAt(1).toUpperCase();\n  });\n};\n\n// Creates an element from string\nDropzone.createElement = function (string) {\n  var div = document.createElement(\"div\");\n  div.innerHTML = string;\n  return div.childNodes[0];\n};\n\n// Tests if given element is inside (or simply is) the container\nDropzone.elementInside = function (element, container) {\n  if (element === container) {\n    return true;\n  } // Coffeescript doesn't support do/while loops\n  while (element = element.parentNode) {\n    if (element === container) {\n      return true;\n    }\n  }\n  return false;\n};\n\nDropzone.getElement = function (el, name) {\n  var element = void 0;\n  if (typeof el === \"string\") {\n    element = document.querySelector(el);\n  } else if (el.nodeType != null) {\n    element = el;\n  }\n  if (element == null) {\n    throw new Error(\"Invalid `\" + name + \"` option provided. Please provide a CSS selector or a plain HTML element.\");\n  }\n  return element;\n};\n\nDropzone.getElements = function (els, name) {\n  var el = void 0,\n      elements = void 0;\n  if (els instanceof Array) {\n    elements = [];\n    try {\n      for (var _iterator36 = els, _isArray36 = Array.isArray(_iterator36), _i38 = 0, _iterator36 = _isArray36 ? _iterator36 : _iterator36[Symbol.iterator]();;) {\n        if (_isArray36) {\n          if (_i38 >= _iterator36.length) break;\n          el = _iterator36[_i38++];\n        } else {\n          _i38 = _iterator36.next();\n          if (_i38.done) break;\n          el = _i38.value;\n        }\n\n        elements.push(this.getElement(el, name));\n      }\n    } catch (e) {\n      elements = null;\n    }\n  } else if (typeof els === \"string\") {\n    elements = [];\n    for (var _iterator37 = document.querySelectorAll(els), _isArray37 = Array.isArray(_iterator37), _i39 = 0, _iterator37 = _isArray37 ? _iterator37 : _iterator37[Symbol.iterator]();;) {\n      if (_isArray37) {\n        if (_i39 >= _iterator37.length) break;\n        el = _iterator37[_i39++];\n      } else {\n        _i39 = _iterator37.next();\n        if (_i39.done) break;\n        el = _i39.value;\n      }\n\n      elements.push(el);\n    }\n  } else if (els.nodeType != null) {\n    elements = [els];\n  }\n\n  if (elements == null || !elements.length) {\n    throw new Error(\"Invalid `\" + name + \"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.\");\n  }\n\n  return elements;\n};\n\n// Asks the user the question and calls accepted or rejected accordingly\n//\n// The default implementation just uses `window.confirm` and then calls the\n// appropriate callback.\nDropzone.confirm = function (question, accepted, rejected) {\n  if (window.confirm(question)) {\n    return accepted();\n  } else if (rejected != null) {\n    return rejected();\n  }\n};\n\n// Validates the mime type like this:\n//\n// https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept\nDropzone.isValidFile = function (file, acceptedFiles) {\n  if (!acceptedFiles) {\n    return true;\n  } // If there are no accepted mime types, it's OK\n  acceptedFiles = acceptedFiles.split(\",\");\n\n  var mimeType = file.type;\n  var baseMimeType = mimeType.replace(/\\/.*$/, \"\");\n\n  for (var _iterator38 = acceptedFiles, _isArray38 = Array.isArray(_iterator38), _i40 = 0, _iterator38 = _isArray38 ? _iterator38 : _iterator38[Symbol.iterator]();;) {\n    var _ref35;\n\n    if (_isArray38) {\n      if (_i40 >= _iterator38.length) break;\n      _ref35 = _iterator38[_i40++];\n    } else {\n      _i40 = _iterator38.next();\n      if (_i40.done) break;\n      _ref35 = _i40.value;\n    }\n\n    var validType = _ref35;\n\n    validType = validType.trim();\n    if (validType.charAt(0) === \".\") {\n      if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {\n        return true;\n      }\n    } else if (/\\/\\*$/.test(validType)) {\n      // This is something like a image/* mime type\n      if (baseMimeType === validType.replace(/\\/.*$/, \"\")) {\n        return true;\n      }\n    } else {\n      if (mimeType === validType) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n};\n\n// Augment jQuery\nif (typeof jQuery !== 'undefined' && jQuery !== null) {\n  jQuery.fn.dropzone = function (options) {\n    return this.each(function () {\n      return new Dropzone(this, options);\n    });\n  };\n}\n\nif (typeof module !== 'undefined' && module !== null) {\n  module.exports = Dropzone;\n} else {\n  window.Dropzone = Dropzone;\n}\n\n// Dropzone file status codes\nDropzone.ADDED = \"added\";\n\nDropzone.QUEUED = \"queued\";\n// For backwards compatibility. Now, if a file is accepted, it's either queued\n// or uploading.\nDropzone.ACCEPTED = Dropzone.QUEUED;\n\nDropzone.UPLOADING = \"uploading\";\nDropzone.PROCESSING = Dropzone.UPLOADING; // alias\n\nDropzone.CANCELED = \"canceled\";\nDropzone.ERROR = \"error\";\nDropzone.SUCCESS = \"success\";\n\n/*\n\n Bugfix for iOS 6 and 7\n Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios\n based on the work of https://github.com/stomita/ios-imagefile-megapixel\n\n */\n\n// Detecting vertical squash in loaded image.\n// Fixes a bug which squash image vertically while drawing into canvas for some images.\n// This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel\nvar detectVerticalSquash = function detectVerticalSquash(img) {\n  var iw = img.naturalWidth;\n  var ih = img.naturalHeight;\n  var canvas = document.createElement(\"canvas\");\n  canvas.width = 1;\n  canvas.height = ih;\n  var ctx = canvas.getContext(\"2d\");\n  ctx.drawImage(img, 0, 0);\n\n  var _ctx$getImageData = ctx.getImageData(1, 0, 1, ih),\n      data = _ctx$getImageData.data;\n\n  // search image edge pixel position in case it is squashed vertically.\n\n\n  var sy = 0;\n  var ey = ih;\n  var py = ih;\n  while (py > sy) {\n    var alpha = data[(py - 1) * 4 + 3];\n\n    if (alpha === 0) {\n      ey = py;\n    } else {\n      sy = py;\n    }\n\n    py = ey + sy >> 1;\n  }\n  var ratio = py / ih;\n\n  if (ratio === 0) {\n    return 1;\n  } else {\n    return ratio;\n  }\n};\n\n// A replacement for context.drawImage\n// (args are for source and destination).\nvar drawImageIOSFix = function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {\n  var vertSquashRatio = detectVerticalSquash(img);\n  return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);\n};\n\n// Based on MinifyJpeg\n// Source: http://www.perry.cz/files/ExifRestorer.js\n// http://elicon.blog57.fc2.com/blog-entry-206.html\n\nvar ExifRestore = function () {\n  function ExifRestore() {\n    _classCallCheck(this, ExifRestore);\n  }\n\n  _createClass(ExifRestore, null, [{\n    key: \"initClass\",\n    value: function initClass() {\n      this.KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n    }\n  }, {\n    key: \"encode64\",\n    value: function encode64(input) {\n      var output = '';\n      var chr1 = undefined;\n      var chr2 = undefined;\n      var chr3 = '';\n      var enc1 = undefined;\n      var enc2 = undefined;\n      var enc3 = undefined;\n      var enc4 = '';\n      var i = 0;\n      while (true) {\n        chr1 = input[i++];\n        chr2 = input[i++];\n        chr3 = input[i++];\n        enc1 = chr1 >> 2;\n        enc2 = (chr1 & 3) << 4 | chr2 >> 4;\n        enc3 = (chr2 & 15) << 2 | chr3 >> 6;\n        enc4 = chr3 & 63;\n        if (isNaN(chr2)) {\n          enc3 = enc4 = 64;\n        } else if (isNaN(chr3)) {\n          enc4 = 64;\n        }\n        output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4);\n        chr1 = chr2 = chr3 = '';\n        enc1 = enc2 = enc3 = enc4 = '';\n        if (!(i < input.length)) {\n          break;\n        }\n      }\n      return output;\n    }\n  }, {\n    key: \"restore\",\n    value: function restore(origFileBase64, resizedFileBase64) {\n      if (!origFileBase64.match('data:image/jpeg;base64,')) {\n        return resizedFileBase64;\n      }\n      var rawImage = this.decode64(origFileBase64.replace('data:image/jpeg;base64,', ''));\n      var segments = this.slice2Segments(rawImage);\n      var image = this.exifManipulation(resizedFileBase64, segments);\n      return \"data:image/jpeg;base64,\" + this.encode64(image);\n    }\n  }, {\n    key: \"exifManipulation\",\n    value: function exifManipulation(resizedFileBase64, segments) {\n      var exifArray = this.getExifArray(segments);\n      var newImageArray = this.insertExif(resizedFileBase64, exifArray);\n      var aBuffer = new Uint8Array(newImageArray);\n      return aBuffer;\n    }\n  }, {\n    key: \"getExifArray\",\n    value: function getExifArray(segments) {\n      var seg = undefined;\n      var x = 0;\n      while (x < segments.length) {\n        seg = segments[x];\n        if (seg[0] === 255 & seg[1] === 225) {\n          return seg;\n        }\n        x++;\n      }\n      return [];\n    }\n  }, {\n    key: \"insertExif\",\n    value: function insertExif(resizedFileBase64, exifArray) {\n      var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', '');\n      var buf = this.decode64(imageData);\n      var separatePoint = buf.indexOf(255, 3);\n      var mae = buf.slice(0, separatePoint);\n      var ato = buf.slice(separatePoint);\n      var array = mae;\n      array = array.concat(exifArray);\n      array = array.concat(ato);\n      return array;\n    }\n  }, {\n    key: \"slice2Segments\",\n    value: function slice2Segments(rawImageArray) {\n      var head = 0;\n      var segments = [];\n      while (true) {\n        var length;\n        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {\n          break;\n        }\n        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {\n          head += 2;\n        } else {\n          length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3];\n          var endPoint = head + length + 2;\n          var seg = rawImageArray.slice(head, endPoint);\n          segments.push(seg);\n          head = endPoint;\n        }\n        if (head > rawImageArray.length) {\n          break;\n        }\n      }\n      return segments;\n    }\n  }, {\n    key: \"decode64\",\n    value: function decode64(input) {\n      var output = '';\n      var chr1 = undefined;\n      var chr2 = undefined;\n      var chr3 = '';\n      var enc1 = undefined;\n      var enc2 = undefined;\n      var enc3 = undefined;\n      var enc4 = '';\n      var i = 0;\n      var buf = [];\n      // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n      var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n      if (base64test.exec(input)) {\n        console.warn('There were invalid base64 characters in the input text.\\nValid base64 characters are A-Z, a-z, 0-9, \\'+\\', \\'/\\',and \\'=\\'\\nExpect errors in decoding.');\n      }\n      input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, '');\n      while (true) {\n        enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n        chr1 = enc1 << 2 | enc2 >> 4;\n        chr2 = (enc2 & 15) << 4 | enc3 >> 2;\n        chr3 = (enc3 & 3) << 6 | enc4;\n        buf.push(chr1);\n        if (enc3 !== 64) {\n          buf.push(chr2);\n        }\n        if (enc4 !== 64) {\n          buf.push(chr3);\n        }\n        chr1 = chr2 = chr3 = '';\n        enc1 = enc2 = enc3 = enc4 = '';\n        if (!(i < input.length)) {\n          break;\n        }\n      }\n      return buf;\n    }\n  }]);\n\n  return ExifRestore;\n}();\n\nExifRestore.initClass();\n\n/*\n * contentloaded.js\n *\n * Author: Diego Perini (diego.perini at gmail.com)\n * Summary: cross-browser wrapper for DOMContentLoaded\n * Updated: 20101020\n * License: MIT\n * Version: 1.2\n *\n * URL:\n * http://javascript.nwbox.com/ContentLoaded/\n * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE\n */\n\n// @win window reference\n// @fn function reference\nvar contentLoaded = function contentLoaded(win, fn) {\n  var done = false;\n  var top = true;\n  var doc = win.document;\n  var root = doc.documentElement;\n  var add = doc.addEventListener ? \"addEventListener\" : \"attachEvent\";\n  var rem = doc.addEventListener ? \"removeEventListener\" : \"detachEvent\";\n  var pre = doc.addEventListener ? \"\" : \"on\";\n  var init = function init(e) {\n    if (e.type === \"readystatechange\" && doc.readyState !== \"complete\") {\n      return;\n    }\n    (e.type === \"load\" ? win : doc)[rem](pre + e.type, init, false);\n    if (!done && (done = true)) {\n      return fn.call(win, e.type || e);\n    }\n  };\n\n  var poll = function poll() {\n    try {\n      root.doScroll(\"left\");\n    } catch (e) {\n      setTimeout(poll, 50);\n      return;\n    }\n    return init(\"poll\");\n  };\n\n  if (doc.readyState !== \"complete\") {\n    if (doc.createEventObject && root.doScroll) {\n      try {\n        top = !win.frameElement;\n      } catch (error) {}\n      if (top) {\n        poll();\n      }\n    }\n    doc[add](pre + \"DOMContentLoaded\", init, false);\n    doc[add](pre + \"readystatechange\", init, false);\n    return win[add](pre + \"load\", init, false);\n  }\n};\n\n// As a single function to be able to write tests.\nDropzone._autoDiscoverFunction = function () {\n  if (Dropzone.autoDiscover) {\n    return Dropzone.discover();\n  }\n};\ncontentLoaded(window, Dropzone._autoDiscoverFunction);\n\nfunction __guard__(value, transform) {\n  return typeof value !== 'undefined' && value !== null ? transform(value) : undefined;\n}\nfunction __guardMethod__(obj, methodName, transform) {\n  if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') {\n    return transform(obj, methodName);\n  } else {\n    return undefined;\n  }\n}\n\n    return module.exports;\n}));"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/dropzone/dropzone.css",
    "content": "/*\n * The MIT License\n * Copyright (c) 2012 Matias Meno <m@tias.me>\n */\n@-webkit-keyframes passing-through {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(40px);\n    -moz-transform: translateY(40px);\n    -ms-transform: translateY(40px);\n    -o-transform: translateY(40px);\n    transform: translateY(40px); }\n  30%, 70% {\n    opacity: 1;\n    -webkit-transform: translateY(0px);\n    -moz-transform: translateY(0px);\n    -ms-transform: translateY(0px);\n    -o-transform: translateY(0px);\n    transform: translateY(0px); }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-40px);\n    -moz-transform: translateY(-40px);\n    -ms-transform: translateY(-40px);\n    -o-transform: translateY(-40px);\n    transform: translateY(-40px); } }\n@-moz-keyframes passing-through {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(40px);\n    -moz-transform: translateY(40px);\n    -ms-transform: translateY(40px);\n    -o-transform: translateY(40px);\n    transform: translateY(40px); }\n  30%, 70% {\n    opacity: 1;\n    -webkit-transform: translateY(0px);\n    -moz-transform: translateY(0px);\n    -ms-transform: translateY(0px);\n    -o-transform: translateY(0px);\n    transform: translateY(0px); }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-40px);\n    -moz-transform: translateY(-40px);\n    -ms-transform: translateY(-40px);\n    -o-transform: translateY(-40px);\n    transform: translateY(-40px); } }\n@keyframes passing-through {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(40px);\n    -moz-transform: translateY(40px);\n    -ms-transform: translateY(40px);\n    -o-transform: translateY(40px);\n    transform: translateY(40px); }\n  30%, 70% {\n    opacity: 1;\n    -webkit-transform: translateY(0px);\n    -moz-transform: translateY(0px);\n    -ms-transform: translateY(0px);\n    -o-transform: translateY(0px);\n    transform: translateY(0px); }\n  100% {\n    opacity: 0;\n    -webkit-transform: translateY(-40px);\n    -moz-transform: translateY(-40px);\n    -ms-transform: translateY(-40px);\n    -o-transform: translateY(-40px);\n    transform: translateY(-40px); } }\n@-webkit-keyframes slide-in {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(40px);\n    -moz-transform: translateY(40px);\n    -ms-transform: translateY(40px);\n    -o-transform: translateY(40px);\n    transform: translateY(40px); }\n  30% {\n    opacity: 1;\n    -webkit-transform: translateY(0px);\n    -moz-transform: translateY(0px);\n    -ms-transform: translateY(0px);\n    -o-transform: translateY(0px);\n    transform: translateY(0px); } }\n@-moz-keyframes slide-in {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(40px);\n    -moz-transform: translateY(40px);\n    -ms-transform: translateY(40px);\n    -o-transform: translateY(40px);\n    transform: translateY(40px); }\n  30% {\n    opacity: 1;\n    -webkit-transform: translateY(0px);\n    -moz-transform: translateY(0px);\n    -ms-transform: translateY(0px);\n    -o-transform: translateY(0px);\n    transform: translateY(0px); } }\n@keyframes slide-in {\n  0% {\n    opacity: 0;\n    -webkit-transform: translateY(40px);\n    -moz-transform: translateY(40px);\n    -ms-transform: translateY(40px);\n    -o-transform: translateY(40px);\n    transform: translateY(40px); }\n  30% {\n    opacity: 1;\n    -webkit-transform: translateY(0px);\n    -moz-transform: translateY(0px);\n    -ms-transform: translateY(0px);\n    -o-transform: translateY(0px);\n    transform: translateY(0px); } }\n@-webkit-keyframes pulse {\n  0% {\n    -webkit-transform: scale(1);\n    -moz-transform: scale(1);\n    -ms-transform: scale(1);\n    -o-transform: scale(1);\n    transform: scale(1); }\n  10% {\n    -webkit-transform: scale(1.1);\n    -moz-transform: scale(1.1);\n    -ms-transform: scale(1.1);\n    -o-transform: scale(1.1);\n    transform: scale(1.1); }\n  20% {\n    -webkit-transform: scale(1);\n    -moz-transform: scale(1);\n    -ms-transform: scale(1);\n    -o-transform: scale(1);\n    transform: scale(1); } }\n@-moz-keyframes pulse {\n  0% {\n    -webkit-transform: scale(1);\n    -moz-transform: scale(1);\n    -ms-transform: scale(1);\n    -o-transform: scale(1);\n    transform: scale(1); }\n  10% {\n    -webkit-transform: scale(1.1);\n    -moz-transform: scale(1.1);\n    -ms-transform: scale(1.1);\n    -o-transform: scale(1.1);\n    transform: scale(1.1); }\n  20% {\n    -webkit-transform: scale(1);\n    -moz-transform: scale(1);\n    -ms-transform: scale(1);\n    -o-transform: scale(1);\n    transform: scale(1); } }\n@keyframes pulse {\n  0% {\n    -webkit-transform: scale(1);\n    -moz-transform: scale(1);\n    -ms-transform: scale(1);\n    -o-transform: scale(1);\n    transform: scale(1); }\n  10% {\n    -webkit-transform: scale(1.1);\n    -moz-transform: scale(1.1);\n    -ms-transform: scale(1.1);\n    -o-transform: scale(1.1);\n    transform: scale(1.1); }\n  20% {\n    -webkit-transform: scale(1);\n    -moz-transform: scale(1);\n    -ms-transform: scale(1);\n    -o-transform: scale(1);\n    transform: scale(1); } }\n.dropzone, .dropzone * {\n  box-sizing: border-box; }\n\n.dropzone {\n  min-height: 150px;\n  border: 2px dashed #00C0EF;\n  background: white;\n  padding: 20px 20px; }\n  .dropzone.dz-clickable {\n    cursor: pointer; }\n    .dropzone.dz-clickable * {\n      cursor: default; }\n    .dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * {\n      cursor: pointer; }\n  .dropzone.dz-started .dz-message {\n    display: none; }\n  .dropzone.dz-drag-hover {\n    border-style: solid; }\n    .dropzone.dz-drag-hover .dz-message {\n      opacity: 0.5; }\n  .dropzone .dz-message {\n    text-align: center;\n    margin: 2em 0; }\n  .dropzone .dz-preview {\n    position: relative;\n    display: inline-block;\n    vertical-align: top;\n    margin: 16px;\n    min-height: 100px; }\n    .dropzone .dz-preview:hover {\n      z-index: 1000; }\n      .dropzone .dz-preview:hover .dz-details {\n        opacity: 1; }\n    .dropzone .dz-preview.dz-file-preview .dz-image {\n      border-radius: 20px;\n      background: #999;\n      background: linear-gradient(to bottom, #eee, #ddd); }\n    .dropzone .dz-preview.dz-file-preview .dz-details {\n      opacity: 1; }\n    .dropzone .dz-preview.dz-image-preview {\n      background: white; }\n      .dropzone .dz-preview.dz-image-preview .dz-details {\n        -webkit-transition: opacity 0.2s linear;\n        -moz-transition: opacity 0.2s linear;\n        -ms-transition: opacity 0.2s linear;\n        -o-transition: opacity 0.2s linear;\n        transition: opacity 0.2s linear; }\n    .dropzone .dz-preview .dz-remove {\n      font-size: 14px;\n      text-align: center;\n      display: block;\n      cursor: pointer;\n      border: none; }\n      .dropzone .dz-preview .dz-remove:hover {\n        text-decoration: underline; }\n    .dropzone .dz-preview:hover .dz-details {\n      opacity: 1; }\n    .dropzone .dz-preview .dz-details {\n      z-index: 20;\n      position: absolute;\n      top: 0;\n      left: 0;\n      opacity: 0;\n      font-size: 13px;\n      min-width: 100%;\n      max-width: 100%;\n      padding: 2em 1em;\n      text-align: center;\n      color: rgba(0, 0, 0, 0.9);\n      line-height: 150%; }\n      .dropzone .dz-preview .dz-details .dz-size {\n        margin-bottom: 1em;\n        font-size: 16px; }\n      .dropzone .dz-preview .dz-details .dz-filename {\n        white-space: nowrap; }\n        .dropzone .dz-preview .dz-details .dz-filename:hover span {\n          border: 1px solid rgba(200, 200, 200, 0.8);\n          background-color: rgba(255, 255, 255, 0.8); }\n        .dropzone .dz-preview .dz-details .dz-filename:not(:hover) {\n          overflow: hidden;\n          text-overflow: ellipsis; }\n          .dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {\n            border: 1px solid transparent; }\n      .dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {\n        background-color: rgba(255, 255, 255, 0.4);\n        padding: 0 0.4em;\n        border-radius: 3px; }\n    .dropzone .dz-preview:hover .dz-image img {\n      -webkit-transform: scale(1.05, 1.05);\n      -moz-transform: scale(1.05, 1.05);\n      -ms-transform: scale(1.05, 1.05);\n      -o-transform: scale(1.05, 1.05);\n      transform: scale(1.05, 1.05);\n      -webkit-filter: blur(8px);\n      filter: blur(8px); }\n    .dropzone .dz-preview .dz-image {\n      border-radius: 20px;\n      overflow: hidden;\n      width: 120px;\n      height: 120px;\n      position: relative;\n      display: block;\n      z-index: 10; }\n      .dropzone .dz-preview .dz-image img {\n        display: block; }\n    .dropzone .dz-preview.dz-success .dz-success-mark {\n      -webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);\n      -moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);\n      -ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);\n      -o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);\n      animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); }\n    .dropzone .dz-preview.dz-error .dz-error-mark {\n      opacity: 1;\n      -webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);\n      -moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);\n      -ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);\n      -o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);\n      animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); }\n    .dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {\n      pointer-events: none;\n      opacity: 0;\n      z-index: 500;\n      position: absolute;\n      display: block;\n      top: 50%;\n      left: 50%;\n      margin-left: -27px;\n      margin-top: -27px; }\n      .dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg {\n        display: block;\n        width: 54px;\n        height: 54px; }\n    .dropzone .dz-preview.dz-processing .dz-progress {\n      opacity: 1;\n      -webkit-transition: all 0.2s linear;\n      -moz-transition: all 0.2s linear;\n      -ms-transition: all 0.2s linear;\n      -o-transition: all 0.2s linear;\n      transition: all 0.2s linear; }\n    .dropzone .dz-preview.dz-complete .dz-progress {\n      opacity: 0;\n      -webkit-transition: opacity 0.4s ease-in;\n      -moz-transition: opacity 0.4s ease-in;\n      -ms-transition: opacity 0.4s ease-in;\n      -o-transition: opacity 0.4s ease-in;\n      transition: opacity 0.4s ease-in; }\n    .dropzone .dz-preview:not(.dz-processing) .dz-progress {\n      -webkit-animation: pulse 6s ease infinite;\n      -moz-animation: pulse 6s ease infinite;\n      -ms-animation: pulse 6s ease infinite;\n      -o-animation: pulse 6s ease infinite;\n      animation: pulse 6s ease infinite; }\n    .dropzone .dz-preview .dz-progress {\n      opacity: 1;\n      z-index: 1000;\n      pointer-events: none;\n      position: absolute;\n      height: 16px;\n      left: 50%;\n      top: 50%;\n      margin-top: -8px;\n      width: 80px;\n      margin-left: -40px;\n      background: rgba(255, 255, 255, 0.9);\n      -webkit-transform: scale(1);\n      border-radius: 8px;\n      overflow: hidden; }\n      .dropzone .dz-preview .dz-progress .dz-upload {\n        background: #333;\n        background: linear-gradient(to bottom, #666, #444);\n        position: absolute;\n        top: 0;\n        left: 0;\n        bottom: 0;\n        width: 0;\n        -webkit-transition: width 300ms ease-in-out;\n        -moz-transition: width 300ms ease-in-out;\n        -ms-transition: width 300ms ease-in-out;\n        -o-transition: width 300ms ease-in-out;\n        transition: width 300ms ease-in-out; }\n    .dropzone .dz-preview.dz-error .dz-error-message {\n      display: block; }\n    .dropzone .dz-preview.dz-error:hover .dz-error-message {\n      opacity: 1;\n      pointer-events: auto; }\n    .dropzone .dz-preview .dz-error-message {\n      pointer-events: none;\n      z-index: 1000;\n      position: absolute;\n      display: block;\n      display: none;\n      opacity: 0;\n      -webkit-transition: opacity 0.3s ease;\n      -moz-transition: opacity 0.3s ease;\n      -ms-transition: opacity 0.3s ease;\n      -o-transition: opacity 0.3s ease;\n      transition: opacity 0.3s ease;\n      border-radius: 8px;\n      font-size: 13px;\n      top: 130px;\n      left: -10px;\n      width: 140px;\n      background: #be2626;\n      background: linear-gradient(to bottom, #be2626, #a92222);\n      padding: 0.5em 1.2em;\n      color: white; }\n      .dropzone .dz-preview .dz-error-message:after {\n        content: '';\n        position: absolute;\n        top: -6px;\n        left: 64px;\n        width: 0;\n        height: 0;\n        border-left: 6px solid transparent;\n        border-right: 6px solid transparent;\n        border-bottom: 6px solid #be2626; }\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/dropzone/dropzone.js",
    "content": "\"use strict\";\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n/*\n *\n * More info at [www.dropzonejs.com](http://www.dropzonejs.com)\n *\n * Copyright (c) 2012, Matias Meno\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *\n */\n\n// The Emitter class provides the ability to call `.on()` on Dropzone to listen\n// to events.\n// It is strongly based on component's emitter class, and I removed the\n// functionality because of the dependency hell with different frameworks.\nvar Emitter = function () {\n  function Emitter() {\n    _classCallCheck(this, Emitter);\n  }\n\n  _createClass(Emitter, [{\n    key: \"on\",\n\n    // Add an event listener for given event\n    value: function on(event, fn) {\n      this._callbacks = this._callbacks || {};\n      // Create namespace for this event\n      if (!this._callbacks[event]) {\n        this._callbacks[event] = [];\n      }\n      this._callbacks[event].push(fn);\n      return this;\n    }\n  }, {\n    key: \"emit\",\n    value: function emit(event) {\n      this._callbacks = this._callbacks || {};\n      var callbacks = this._callbacks[event];\n\n      if (callbacks) {\n        for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n          args[_key - 1] = arguments[_key];\n        }\n\n        for (var _iterator = callbacks, _isArray = true, _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {\n          var _ref;\n\n          if (_isArray) {\n            if (_i >= _iterator.length) break;\n            _ref = _iterator[_i++];\n          } else {\n            _i = _iterator.next();\n            if (_i.done) break;\n            _ref = _i.value;\n          }\n\n          var callback = _ref;\n\n          callback.apply(this, args);\n        }\n      }\n\n      return this;\n    }\n\n    // Remove event listener for given event. If fn is not provided, all event\n    // listeners for that event will be removed. If neither is provided, all\n    // event listeners will be removed.\n\n  }, {\n    key: \"off\",\n    value: function off(event, fn) {\n      if (!this._callbacks || arguments.length === 0) {\n        this._callbacks = {};\n        return this;\n      }\n\n      // specific event\n      var callbacks = this._callbacks[event];\n      if (!callbacks) {\n        return this;\n      }\n\n      // remove all handlers\n      if (arguments.length === 1) {\n        delete this._callbacks[event];\n        return this;\n      }\n\n      // remove specific handler\n      for (var i = 0; i < callbacks.length; i++) {\n        var callback = callbacks[i];\n        if (callback === fn) {\n          callbacks.splice(i, 1);\n          break;\n        }\n      }\n\n      return this;\n    }\n  }]);\n\n  return Emitter;\n}();\n\nvar Dropzone = function (_Emitter) {\n  _inherits(Dropzone, _Emitter);\n\n  _createClass(Dropzone, null, [{\n    key: \"initClass\",\n    value: function initClass() {\n\n      // Exposing the emitter class, mainly for tests\n      this.prototype.Emitter = Emitter;\n\n      /*\n       This is a list of all available events you can register on a dropzone object.\n        You can register an event handler like this:\n        dropzone.on(\"dragEnter\", function() { });\n        */\n      this.prototype.events = [\"drop\", \"initimage\", \"dragstart\", \"dragend\", \"dragenter\", \"dragover\", \"dragleave\", \"addedfile\", \"addedfiles\", \"removedfile\", \"thumbnail\", \"error\", \"errormultiple\", \"processing\", \"processingmultiple\", \"uploadprogress\", \"totaluploadprogress\", \"sending\", \"sendingmultiple\", \"success\", \"successmultiple\", \"canceled\", \"canceledmultiple\", \"complete\", \"completemultiple\", \"reset\", \"maxfilesexceeded\", \"maxfilesreached\", \"queuecomplete\"];\n\n      this.prototype.defaultOptions = {\n        /**\n         * Has to be specified on elements other than form (or when the form\n         * doesn't have an `action` attribute). You can also\n         * provide a function that will be called with `files` and\n         * must return the url (since `v3.12.0`)\n         */\n        url: null,\n\n        /**\n         * Can be changed to `\"put\"` if necessary. You can also provide a function\n         * that will be called with `files` and must return the method (since `v3.12.0`).\n         */\n        method: \"post\",\n\n        /**\n         * Will be set on the XHRequest.\n         */\n        withCredentials: false,\n\n        /**\n         * The timeout for the XHR requests in milliseconds (since `v4.4.0`).\n         */\n        timeout: 30000,\n\n        /**\n         * How many file uploads to process in parallel (See the\n         * Enqueuing file uploads* documentation section for more info)\n         */\n        parallelUploads: 2,\n\n        /**\n         * Whether to send multiple files in one request. If\n         * this it set to true, then the fallback file input element will\n         * have the `multiple` attribute as well. This option will\n         * also trigger additional events (like `processingmultiple`). See the events\n         * documentation section for more information.\n         */\n        uploadMultiple: false,\n\n        /**\n         * Whether you want files to be uploaded in chunks to your server. This can't be\n         * used in combination with `uploadMultiple`.\n         *\n         * See [chunksUploaded](#config-chunksUploaded) for the callback to finalise an upload.\n         */\n        chunking: false,\n\n        /**\n         * If `chunking` is enabled, this defines whether **every** file should be chunked,\n         * even if the file size is below chunkSize. This means, that the additional chunk\n         * form data will be submitted and the `chunksUploaded` callback will be invoked.\n         */\n        forceChunking: false,\n\n        /**\n         * If `chunking` is `true`, then this defines the chunk size in bytes.\n         */\n        chunkSize: 2000000,\n\n        /**\n         * If `true`, the individual chunks of a file are being uploaded simultaneously.\n         */\n        parallelChunkUploads: false,\n\n        /**\n         * Whether a chunk should be retried if it fails.\n         */\n        retryChunks: false,\n\n        /**\n         * If `retryChunks` is true, how many times should it be retried.\n         */\n        retryChunksLimit: 3,\n\n        /**\n         * If not `null` defines how many files this Dropzone handles. If it exceeds,\n         * the event `maxfilesexceeded` will be called. The dropzone element gets the\n         * class `dz-max-files-reached` accordingly so you can provide visual feedback.\n         */\n        maxFilesize: 256,\n\n        /**\n         * The name of the file param that gets transferred.\n         * **NOTE**: If you have the option  `uploadMultiple` set to `true`, then\n         * Dropzone will append `[]` to the name.\n         */\n        paramName: \"file\",\n\n        /**\n         * Whether thumbnails for images should be generated\n         */\n        createImageThumbnails: true,\n\n        /**\n         * In MB. When the filename exceeds this limit, the thumbnail will not be generated.\n         */\n        maxThumbnailFilesize: 10,\n\n        /**\n         * If `null`, the ratio of the image will be used to calculate it.\n         */\n        thumbnailWidth: 120,\n\n        /**\n         * The same as `thumbnailWidth`. If both are null, images will not be resized.\n         */\n        thumbnailHeight: 120,\n\n        /**\n         * How the images should be scaled down in case both, `thumbnailWidth` and `thumbnailHeight` are provided.\n         * Can be either `contain` or `crop`.\n         */\n        thumbnailMethod: 'crop',\n\n        /**\n         * If set, images will be resized to these dimensions before being **uploaded**.\n         * If only one, `resizeWidth` **or** `resizeHeight` is provided, the original aspect\n         * ratio of the file will be preserved.\n         *\n         * The `options.transformFile` function uses these options, so if the `transformFile` function\n         * is overridden, these options don't do anything.\n         */\n        resizeWidth: null,\n\n        /**\n         * See `resizeWidth`.\n         */\n        resizeHeight: null,\n\n        /**\n         * The mime type of the resized image (before it gets uploaded to the server).\n         * If `null` the original mime type will be used. To force jpeg, for example, use `image/jpeg`.\n         * See `resizeWidth` for more information.\n         */\n        resizeMimeType: null,\n\n        /**\n         * The quality of the resized images. See `resizeWidth`.\n         */\n        resizeQuality: 0.8,\n\n        /**\n         * How the images should be scaled down in case both, `resizeWidth` and `resizeHeight` are provided.\n         * Can be either `contain` or `crop`.\n         */\n        resizeMethod: 'contain',\n\n        /**\n         * The base that is used to calculate the filesize. You can change this to\n         * 1024 if you would rather display kibibytes, mebibytes, etc...\n         * 1024 is technically incorrect, because `1024 bytes` are `1 kibibyte` not `1 kilobyte`.\n         * You can change this to `1024` if you don't care about validity.\n         */\n        filesizeBase: 1000,\n\n        /**\n         * Can be used to limit the maximum number of files that will be handled by this Dropzone\n         */\n        maxFiles: null,\n\n        /**\n         * An optional object to send additional headers to the server. Eg:\n         * `{ \"My-Awesome-Header\": \"header value\" }`\n         */\n        headers: null,\n\n        /**\n         * If `true`, the dropzone element itself will be clickable, if `false`\n         * nothing will be clickable.\n         *\n         * You can also pass an HTML element, a CSS selector (for multiple elements)\n         * or an array of those. In that case, all of those elements will trigger an\n         * upload when clicked.\n         */\n        clickable: true,\n\n        /**\n         * Whether hidden files in directories should be ignored.\n         */\n        ignoreHiddenFiles: true,\n\n        /**\n         * The default implementation of `accept` checks the file's mime type or\n         * extension against this list. This is a comma separated list of mime\n         * types or file extensions.\n         *\n         * Eg.: `image/*,application/pdf,.psd`\n         *\n         * If the Dropzone is `clickable` this option will also be used as\n         * [`accept`](https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept)\n         * parameter on the hidden file input as well.\n         */\n        acceptedFiles: null,\n\n        /**\n         * **Deprecated!**\n         * Use acceptedFiles instead.\n         */\n        acceptedMimeTypes: null,\n\n        /**\n         * If false, files will be added to the queue but the queue will not be\n         * processed automatically.\n         * This can be useful if you need some additional user input before sending\n         * files (or if you want want all files sent at once).\n         * If you're ready to send the file simply call `myDropzone.processQueue()`.\n         *\n         * See the [enqueuing file uploads](#enqueuing-file-uploads) documentation\n         * section for more information.\n         */\n        autoProcessQueue: true,\n\n        /**\n         * If false, files added to the dropzone will not be queued by default.\n         * You'll have to call `enqueueFile(file)` manually.\n         */\n        autoQueue: true,\n\n        /**\n         * If `true`, this will add a link to every file preview to remove or cancel (if\n         * already uploading) the file. The `dictCancelUpload`, `dictCancelUploadConfirmation`\n         * and `dictRemoveFile` options are used for the wording.\n         */\n        addRemoveLinks: false,\n\n        /**\n         * Defines where to display the file previews – if `null` the\n         * Dropzone element itself is used. Can be a plain `HTMLElement` or a CSS\n         * selector. The element should have the `dropzone-previews` class so\n         * the previews are displayed properly.\n         */\n        previewsContainer: null,\n\n        /**\n         * This is the element the hidden input field (which is used when clicking on the\n         * dropzone to trigger file selection) will be appended to. This might\n         * be important in case you use frameworks to switch the content of your page.\n         */\n        hiddenInputContainer: \"body\",\n\n        /**\n         * If null, no capture type will be specified\n         * If camera, mobile devices will skip the file selection and choose camera\n         * If microphone, mobile devices will skip the file selection and choose the microphone\n         * If camcorder, mobile devices will skip the file selection and choose the camera in video mode\n         * On apple devices multiple must be set to false.  AcceptedFiles may need to\n         * be set to an appropriate mime type (e.g. \"image/*\", \"audio/*\", or \"video/*\").\n         */\n        capture: null,\n\n        /**\n         * **Deprecated**. Use `renameFile` instead.\n         */\n        renameFilename: null,\n\n        /**\n         * A function that is invoked before the file is uploaded to the server and renames the file.\n         * This function gets the `File` as argument and can use the `file.name`. The actual name of the\n         * file that gets used during the upload can be accessed through `file.upload.filename`.\n         */\n        renameFile: null,\n\n        /**\n         * If `true` the fallback will be forced. This is very useful to test your server\n         * implementations first and make sure that everything works as\n         * expected without dropzone if you experience problems, and to test\n         * how your fallbacks will look.\n         */\n        forceFallback: false,\n\n        /**\n         * The text used before any files are dropped.\n         */\n        dictDefaultMessage: \"Drop files here to upload\",\n\n        /**\n         * The text that replaces the default message text it the browser is not supported.\n         */\n        dictFallbackMessage: \"Your browser does not support drag'n'drop file uploads.\",\n\n        /**\n         * The text that will be added before the fallback form.\n         * If you provide a  fallback element yourself, or if this option is `null` this will\n         * be ignored.\n         */\n        dictFallbackText: \"Please use the fallback form below to upload your files like in the olden days.\",\n\n        /**\n         * If the filesize is too big.\n         * `{{filesize}}` and `{{maxFilesize}}` will be replaced with the respective configuration values.\n         */\n        dictFileTooBig: \"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.\",\n\n        /**\n         * If the file doesn't match the file type.\n         */\n        dictInvalidFileType: \"You can't upload files of this type.\",\n\n        /**\n         * If the server response was invalid.\n         * `{{statusCode}}` will be replaced with the servers status code.\n         */\n        dictResponseError: \"Server responded with {{statusCode}} code.\",\n\n        /**\n         * If `addRemoveLinks` is true, the text to be used for the cancel upload link.\n         */\n        dictCancelUpload: \"Cancel upload\",\n\n        /**\n         * The text that is displayed if an upload was manually canceled\n         */\n        dictUploadCanceled: \"Upload canceled.\",\n\n        /**\n         * If `addRemoveLinks` is true, the text to be used for confirmation when cancelling upload.\n         */\n        dictCancelUploadConfirmation: \"Are you sure you want to cancel this upload?\",\n\n        /**\n         * If `addRemoveLinks` is true, the text to be used to remove a file.\n         */\n        dictRemoveFile: \"Remove file\",\n\n        /**\n         * If this is not null, then the user will be prompted before removing a file.\n         */\n        dictRemoveFileConfirmation: null,\n\n        /**\n         * Displayed if `maxFiles` is st and exceeded.\n         * The string `{{maxFiles}}` will be replaced by the configuration value.\n         */\n        dictMaxFilesExceeded: \"You can not upload any more files.\",\n\n        /**\n         * Allows you to translate the different units. Starting with `tb` for terabytes and going down to\n         * `b` for bytes.\n         */\n        dictFileSizeUnits: { tb: \"TB\", gb: \"GB\", mb: \"MB\", kb: \"KB\", b: \"b\" },\n        /**\n         * Called when dropzone initialized\n         * You can add event listeners here\n         */\n        init: function init() {},\n\n\n        /**\n         * Can be an **object** of additional parameters to transfer to the server, **or** a `Function`\n         * that gets invoked with the `files`, `xhr` and, if it's a chunked upload, `chunk` arguments. In case\n         * of a function, this needs to return a map.\n         *\n         * The default implementation does nothing for normal uploads, but adds relevant information for\n         * chunked uploads.\n         *\n         * This is the same as adding hidden input fields in the form element.\n         */\n        params: function params(files, xhr, chunk) {\n          if (chunk) {\n            return {\n              dzuuid: chunk.file.upload.uuid,\n              dzchunkindex: chunk.index,\n              dztotalfilesize: chunk.file.size,\n              dzchunksize: this.options.chunkSize,\n              dztotalchunkcount: chunk.file.upload.totalChunkCount,\n              dzchunkbyteoffset: chunk.index * this.options.chunkSize\n            };\n          }\n        },\n\n\n        /**\n         * A function that gets a [file](https://developer.mozilla.org/en-US/docs/DOM/File)\n         * and a `done` function as parameters.\n         *\n         * If the done function is invoked without arguments, the file is \"accepted\" and will\n         * be processed. If you pass an error message, the file is rejected, and the error\n         * message will be displayed.\n         * This function will not be called if the file is too big or doesn't match the mime types.\n         */\n        accept: function accept(file, done) {\n          return done();\n        },\n\n\n        /**\n         * The callback that will be invoked when all chunks have been uploaded for a file.\n         * It gets the file for which the chunks have been uploaded as the first parameter,\n         * and the `done` function as second. `done()` needs to be invoked when everything\n         * needed to finish the upload process is done.\n         */\n        chunksUploaded: function chunksUploaded(file, done) {\n          done();\n        },\n\n        /**\n         * Gets called when the browser is not supported.\n         * The default implementation shows the fallback input field and adds\n         * a text.\n         */\n        fallback: function fallback() {\n          // This code should pass in IE7... :(\n          var messageElement = void 0;\n          this.element.className = this.element.className + \" dz-browser-not-supported\";\n\n          for (var _iterator2 = this.element.getElementsByTagName(\"div\"), _isArray2 = true, _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {\n            var _ref2;\n\n            if (_isArray2) {\n              if (_i2 >= _iterator2.length) break;\n              _ref2 = _iterator2[_i2++];\n            } else {\n              _i2 = _iterator2.next();\n              if (_i2.done) break;\n              _ref2 = _i2.value;\n            }\n\n            var child = _ref2;\n\n            if (/(^| )dz-message($| )/.test(child.className)) {\n              messageElement = child;\n              child.className = \"dz-message\"; // Removes the 'dz-default' class\n              break;\n            }\n          }\n          if (!messageElement) {\n            messageElement = Dropzone.createElement(\"<div class=\\\"dz-message\\\"><span></span></div>\");\n            this.element.appendChild(messageElement);\n          }\n\n          var span = messageElement.getElementsByTagName(\"span\")[0];\n          if (span) {\n            if (span.textContent != null) {\n              span.textContent = this.options.dictFallbackMessage;\n            } else if (span.innerText != null) {\n              span.innerText = this.options.dictFallbackMessage;\n            }\n          }\n\n          return this.element.appendChild(this.getFallbackForm());\n        },\n\n\n        /**\n         * Gets called to calculate the thumbnail dimensions.\n         *\n         * It gets `file`, `width` and `height` (both may be `null`) as parameters and must return an object containing:\n         *\n         *  - `srcWidth` & `srcHeight` (required)\n         *  - `trgWidth` & `trgHeight` (required)\n         *  - `srcX` & `srcY` (optional, default `0`)\n         *  - `trgX` & `trgY` (optional, default `0`)\n         *\n         * Those values are going to be used by `ctx.drawImage()`.\n         */\n        resize: function resize(file, width, height, resizeMethod) {\n          var info = {\n            srcX: 0,\n            srcY: 0,\n            srcWidth: file.width,\n            srcHeight: file.height\n          };\n\n          var srcRatio = file.width / file.height;\n\n          // Automatically calculate dimensions if not specified\n          if (width == null && height == null) {\n            width = info.srcWidth;\n            height = info.srcHeight;\n          } else if (width == null) {\n            width = height * srcRatio;\n          } else if (height == null) {\n            height = width / srcRatio;\n          }\n\n          // Make sure images aren't upscaled\n          width = Math.min(width, info.srcWidth);\n          height = Math.min(height, info.srcHeight);\n\n          var trgRatio = width / height;\n\n          if (info.srcWidth > width || info.srcHeight > height) {\n            // Image is bigger and needs rescaling\n            if (resizeMethod === 'crop') {\n              if (srcRatio > trgRatio) {\n                info.srcHeight = file.height;\n                info.srcWidth = info.srcHeight * trgRatio;\n              } else {\n                info.srcWidth = file.width;\n                info.srcHeight = info.srcWidth / trgRatio;\n              }\n            } else if (resizeMethod === 'contain') {\n              // Method 'contain'\n              if (srcRatio > trgRatio) {\n                height = width / srcRatio;\n              } else {\n                width = height * srcRatio;\n              }\n            } else {\n              throw new Error(\"Unknown resizeMethod '\" + resizeMethod + \"'\");\n            }\n          }\n\n          info.srcX = (file.width - info.srcWidth) / 2;\n          info.srcY = (file.height - info.srcHeight) / 2;\n\n          info.trgWidth = width;\n          info.trgHeight = height;\n\n          return info;\n        },\n\n\n        /**\n         * Can be used to transform the file (for example, resize an image if necessary).\n         *\n         * The default implementation uses `resizeWidth` and `resizeHeight` (if provided) and resizes\n         * images according to those dimensions.\n         *\n         * Gets the `file` as the first parameter, and a `done()` function as the second, that needs\n         * to be invoked with the file when the transformation is done.\n         */\n        transformFile: function transformFile(file, done) {\n          if ((this.options.resizeWidth || this.options.resizeHeight) && file.type.match(/image.*/)) {\n            return this.resizeImage(file, this.options.resizeWidth, this.options.resizeHeight, this.options.resizeMethod, done);\n          } else {\n            return done(file);\n          }\n        },\n\n\n        /**\n         * A string that contains the template used for each dropped\n         * file. Change it to fulfill your needs but make sure to properly\n         * provide all elements.\n         *\n         * If you want to use an actual HTML element instead of providing a String\n         * as a config option, you could create a div with the id `tpl`,\n         * put the template inside it and provide the element like this:\n         *\n         *     document\n         *       .querySelector('#tpl')\n         *       .innerHTML\n         *\n         */\n        previewTemplate: \"<div class=\\\"dz-preview dz-file-preview\\\">\\n  <div class=\\\"dz-image\\\"><img data-dz-thumbnail /></div>\\n  <div class=\\\"dz-details\\\">\\n    <div class=\\\"dz-size\\\"><span data-dz-size></span></div>\\n    <div class=\\\"dz-filename\\\"><span data-dz-name></span></div>\\n  </div>\\n  <div class=\\\"dz-progress\\\"><span class=\\\"dz-upload\\\" data-dz-uploadprogress></span></div>\\n  <div class=\\\"dz-error-message\\\"><span data-dz-errormessage></span></div>\\n  <div class=\\\"dz-success-mark\\\">\\n    <svg width=\\\"54px\\\" height=\\\"54px\\\" viewBox=\\\"0 0 54 54\\\" version=\\\"1.1\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" xmlns:sketch=\\\"http://www.bohemiancoding.com/sketch/ns\\\">\\n      <title>Check</title>\\n      <defs></defs>\\n      <g id=\\\"Page-1\\\" stroke=\\\"none\\\" stroke-width=\\\"1\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" sketch:type=\\\"MSPage\\\">\\n        <path d=\\\"M23.5,31.8431458 L17.5852419,25.9283877 C16.0248253,24.3679711 13.4910294,24.366835 11.9289322,25.9289322 C10.3700136,27.4878508 10.3665912,30.0234455 11.9283877,31.5852419 L20.4147581,40.0716123 C20.5133999,40.1702541 20.6159315,40.2626649 20.7218615,40.3488435 C22.2835669,41.8725651 24.794234,41.8626202 26.3461564,40.3106978 L43.3106978,23.3461564 C44.8771021,21.7797521 44.8758057,19.2483887 43.3137085,17.6862915 C41.7547899,16.1273729 39.2176035,16.1255422 37.6538436,17.6893022 L23.5,31.8431458 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\\\" id=\\\"Oval-2\\\" stroke-opacity=\\\"0.198794158\\\" stroke=\\\"#747474\\\" fill-opacity=\\\"0.816519475\\\" fill=\\\"#FFFFFF\\\" sketch:type=\\\"MSShapeGroup\\\"></path>\\n      </g>\\n    </svg>\\n  </div>\\n  <div class=\\\"dz-error-mark\\\">\\n    <svg width=\\\"54px\\\" height=\\\"54px\\\" viewBox=\\\"0 0 54 54\\\" version=\\\"1.1\\\" xmlns=\\\"http://www.w3.org/2000/svg\\\" xmlns:xlink=\\\"http://www.w3.org/1999/xlink\\\" xmlns:sketch=\\\"http://www.bohemiancoding.com/sketch/ns\\\">\\n      <title>Error</title>\\n      <defs></defs>\\n      <g id=\\\"Page-1\\\" stroke=\\\"none\\\" stroke-width=\\\"1\\\" fill=\\\"none\\\" fill-rule=\\\"evenodd\\\" sketch:type=\\\"MSPage\\\">\\n        <g id=\\\"Check-+-Oval-2\\\" sketch:type=\\\"MSLayerGroup\\\" stroke=\\\"#747474\\\" stroke-opacity=\\\"0.198794158\\\" fill=\\\"#FFFFFF\\\" fill-opacity=\\\"0.816519475\\\">\\n          <path d=\\\"M32.6568542,29 L38.3106978,23.3461564 C39.8771021,21.7797521 39.8758057,19.2483887 38.3137085,17.6862915 C36.7547899,16.1273729 34.2176035,16.1255422 32.6538436,17.6893022 L27,23.3431458 L21.3461564,17.6893022 C19.7823965,16.1255422 17.2452101,16.1273729 15.6862915,17.6862915 C14.1241943,19.2483887 14.1228979,21.7797521 15.6893022,23.3461564 L21.3431458,29 L15.6893022,34.6538436 C14.1228979,36.2202479 14.1241943,38.7516113 15.6862915,40.3137085 C17.2452101,41.8726271 19.7823965,41.8744578 21.3461564,40.3106978 L27,34.6568542 L32.6538436,40.3106978 C34.2176035,41.8744578 36.7547899,41.8726271 38.3137085,40.3137085 C39.8758057,38.7516113 39.8771021,36.2202479 38.3106978,34.6538436 L32.6568542,29 Z M27,53 C41.3594035,53 53,41.3594035 53,27 C53,12.6405965 41.3594035,1 27,1 C12.6405965,1 1,12.6405965 1,27 C1,41.3594035 12.6405965,53 27,53 Z\\\" id=\\\"Oval-2\\\" sketch:type=\\\"MSShapeGroup\\\"></path>\\n        </g>\\n      </g>\\n    </svg>\\n  </div>\\n</div>\",\n\n        // END OPTIONS\n        // (Required by the dropzone documentation parser)\n\n\n        /*\n         Those functions register themselves to the events on init and handle all\n         the user interface specific stuff. Overwriting them won't break the upload\n         but can break the way it's displayed.\n         You can overwrite them if you don't like the default behavior. If you just\n         want to add an additional event handler, register it on the dropzone object\n         and don't overwrite those options.\n         */\n\n        // Those are self explanatory and simply concern the DragnDrop.\n        drop: function drop(e) {\n          return this.element.classList.remove(\"dz-drag-hover\");\n        },\n        dragstart: function dragstart(e) {},\n        dragend: function dragend(e) {\n          return this.element.classList.remove(\"dz-drag-hover\");\n        },\n        dragenter: function dragenter(e) {\n          return this.element.classList.add(\"dz-drag-hover\");\n        },\n        dragover: function dragover(e) {\n          return this.element.classList.add(\"dz-drag-hover\");\n        },\n        dragleave: function dragleave(e) {\n          return this.element.classList.remove(\"dz-drag-hover\");\n        },\n        paste: function paste(e) {},\n\n\n        // Called whenever there are no files left in the dropzone anymore, and the\n        // dropzone should be displayed as if in the initial state.\n        reset: function reset() {\n          return this.element.classList.remove(\"dz-started\");\n        },\n\n\n        // Called when a file is added to the queue\n        // Receives `file`\n        addedfile: function addedfile(file) {\n          var _this2 = this;\n\n          if (this.element === this.previewsContainer) {\n            this.element.classList.add(\"dz-started\");\n          }\n\n          if (this.previewsContainer) {\n            file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());\n            file.previewTemplate = file.previewElement; // Backwards compatibility\n\n            this.previewsContainer.appendChild(file.previewElement);\n            for (var _iterator3 = file.previewElement.querySelectorAll(\"[data-dz-name]\"), _isArray3 = true, _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {\n              var _ref3;\n\n              if (_isArray3) {\n                if (_i3 >= _iterator3.length) break;\n                _ref3 = _iterator3[_i3++];\n              } else {\n                _i3 = _iterator3.next();\n                if (_i3.done) break;\n                _ref3 = _i3.value;\n              }\n\n              var node = _ref3;\n\n              node.textContent = file.name;\n            }\n            for (var _iterator4 = file.previewElement.querySelectorAll(\"[data-dz-size]\"), _isArray4 = true, _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : _iterator4[Symbol.iterator]();;) {\n              if (_isArray4) {\n                if (_i4 >= _iterator4.length) break;\n                node = _iterator4[_i4++];\n              } else {\n                _i4 = _iterator4.next();\n                if (_i4.done) break;\n                node = _i4.value;\n              }\n\n              node.innerHTML = this.filesize(file.size);\n            }\n\n            if (this.options.addRemoveLinks) {\n              file._removeLink = Dropzone.createElement(\"<a class=\\\"dz-remove\\\" href=\\\"javascript:undefined;\\\" data-dz-remove>\" + this.options.dictRemoveFile + \"</a>\");\n              file.previewElement.appendChild(file._removeLink);\n            }\n\n            var removeFileEvent = function removeFileEvent(e) {\n              e.preventDefault();\n              e.stopPropagation();\n              if (file.status === Dropzone.UPLOADING) {\n                return Dropzone.confirm(_this2.options.dictCancelUploadConfirmation, function () {\n                  return _this2.removeFile(file);\n                });\n              } else {\n                if (_this2.options.dictRemoveFileConfirmation) {\n                  return Dropzone.confirm(_this2.options.dictRemoveFileConfirmation, function () {\n                    return _this2.removeFile(file);\n                  });\n                } else {\n                  return _this2.removeFile(file);\n                }\n              }\n            };\n\n            for (var _iterator5 = file.previewElement.querySelectorAll(\"[data-dz-remove]\"), _isArray5 = true, _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : _iterator5[Symbol.iterator]();;) {\n              var _ref4;\n\n              if (_isArray5) {\n                if (_i5 >= _iterator5.length) break;\n                _ref4 = _iterator5[_i5++];\n              } else {\n                _i5 = _iterator5.next();\n                if (_i5.done) break;\n                _ref4 = _i5.value;\n              }\n\n              var removeLink = _ref4;\n\n              removeLink.addEventListener(\"click\", removeFileEvent);\n            }\n          }\n        },\n\n\n        // Called whenever a file is removed.\n        removedfile: function removedfile(file) {\n          if (file.previewElement != null && file.previewElement.parentNode != null) {\n            file.previewElement.parentNode.removeChild(file.previewElement);\n          }\n          return this._updateMaxFilesReachedClass();\n        },\n\n\n        // Called when a thumbnail has been generated\n        // Receives `file` and `dataUrl`\n        thumbnail: function thumbnail(file, dataUrl) {\n          if (file.previewElement) {\n            file.previewElement.classList.remove(\"dz-file-preview\");\n            for (var _iterator6 = file.previewElement.querySelectorAll(\"[data-dz-thumbnail]\"), _isArray6 = true, _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : _iterator6[Symbol.iterator]();;) {\n              var _ref5;\n\n              if (_isArray6) {\n                if (_i6 >= _iterator6.length) break;\n                _ref5 = _iterator6[_i6++];\n              } else {\n                _i6 = _iterator6.next();\n                if (_i6.done) break;\n                _ref5 = _i6.value;\n              }\n\n              var thumbnailElement = _ref5;\n\n              thumbnailElement.alt = file.name;\n              thumbnailElement.src = dataUrl;\n            }\n\n            return setTimeout(function () {\n              return file.previewElement.classList.add(\"dz-image-preview\");\n            }, 1);\n          }\n        },\n\n\n        // Called whenever an error occurs\n        // Receives `file` and `message`\n        error: function error(file, message) {\n          if (file.previewElement) {\n            file.previewElement.classList.add(\"dz-error\");\n            if (typeof message !== \"String\" && message.error) {\n              message = message.error;\n            }\n            for (var _iterator7 = file.previewElement.querySelectorAll(\"[data-dz-errormessage]\"), _isArray7 = true, _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : _iterator7[Symbol.iterator]();;) {\n              var _ref6;\n\n              if (_isArray7) {\n                if (_i7 >= _iterator7.length) break;\n                _ref6 = _iterator7[_i7++];\n              } else {\n                _i7 = _iterator7.next();\n                if (_i7.done) break;\n                _ref6 = _i7.value;\n              }\n\n              var node = _ref6;\n\n              node.textContent = message;\n            }\n          }\n        },\n        errormultiple: function errormultiple() {},\n\n\n        // Called when a file gets processed. Since there is a cue, not all added\n        // files are processed immediately.\n        // Receives `file`\n        processing: function processing(file) {\n          if (file.previewElement) {\n            file.previewElement.classList.add(\"dz-processing\");\n            if (file._removeLink) {\n              return file._removeLink.textContent = this.options.dictCancelUpload;\n            }\n          }\n        },\n        processingmultiple: function processingmultiple() {},\n\n\n        // Called whenever the upload progress gets updated.\n        // Receives `file`, `progress` (percentage 0-100) and `bytesSent`.\n        // To get the total number of bytes of the file, use `file.size`\n        uploadprogress: function uploadprogress(file, progress, bytesSent) {\n          if (file.previewElement) {\n            for (var _iterator8 = file.previewElement.querySelectorAll(\"[data-dz-uploadprogress]\"), _isArray8 = true, _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : _iterator8[Symbol.iterator]();;) {\n              var _ref7;\n\n              if (_isArray8) {\n                if (_i8 >= _iterator8.length) break;\n                _ref7 = _iterator8[_i8++];\n              } else {\n                _i8 = _iterator8.next();\n                if (_i8.done) break;\n                _ref7 = _i8.value;\n              }\n\n              var node = _ref7;\n\n              node.nodeName === 'PROGRESS' ? node.value = progress : node.style.width = progress + \"%\";\n            }\n          }\n        },\n\n\n        // Called whenever the total upload progress gets updated.\n        // Called with totalUploadProgress (0-100), totalBytes and totalBytesSent\n        totaluploadprogress: function totaluploadprogress() {},\n\n\n        // Called just before the file is sent. Gets the `xhr` object as second\n        // parameter, so you can modify it (for example to add a CSRF token) and a\n        // `formData` object to add additional information.\n        sending: function sending() {},\n        sendingmultiple: function sendingmultiple() {},\n\n\n        // When the complete upload is finished and successful\n        // Receives `file`\n        success: function success(file) {\n          if (file.previewElement) {\n            return file.previewElement.classList.add(\"dz-success\");\n          }\n        },\n        successmultiple: function successmultiple() {},\n\n\n        // When the upload is canceled.\n        canceled: function canceled(file) {\n          return this.emit(\"error\", file, this.options.dictUploadCanceled);\n        },\n        canceledmultiple: function canceledmultiple() {},\n\n\n        // When the upload is finished, either with success or an error.\n        // Receives `file`\n        complete: function complete(file) {\n          if (file._removeLink) {\n            file._removeLink.textContent = this.options.dictRemoveFile;\n          }\n          if (file.previewElement) {\n            return file.previewElement.classList.add(\"dz-complete\");\n          }\n        },\n        initimage: function(info) {\n            if( info=='' || !info ) return false;\n            var info_array = info.split(\",\");\n            for( var i in info_array )\n            {\n                var hidefileval_str = info_array[i];\n                var mockfile_object = { name: hidefileval_str, accepted:true }\n\n                function getBase64Image(img) {\n                    var canvas = document.createElement(\"canvas\");\n                    canvas.width = 120;\n                    canvas.height = 120;\n                    var ctx = canvas.getContext(\"2d\");\n                    ctx.drawImage(img, 0, 0, img.width, img.height);\n                    var ext = img.src.substring(img.src.lastIndexOf(\".\")+1).toLowerCase();\n                    var dataURL = canvas.toDataURL(\"image/\"+ext);\n                    return dataURL;\n                }\n                var image = new Image();\n                image.crossOrigin = '';\n                image.src = hidefileval_str;\n                var base64;\n                var me = this;\n                image.onload = function(){\n                     base64 = getBase64Image(image);\n                    me.emit('addedfile', mockfile_object);\n                    me.emit('thumbnail', mockfile_object, base64);\n                    me.emit('success', mockfile_object);\n                    me.emit('processing', mockfile_object);\n                    me.emit('complete', mockfile_object);\n                    me.files.push( mockfile_object );\n                    mockfile_object = null;\n                }\n         }},\n        completemultiple: function completemultiple() {},\n        maxfilesexceeded: function maxfilesexceeded() {},\n        maxfilesreached: function maxfilesreached() {},\n        queuecomplete: function queuecomplete() {},\n        addedfiles: function addedfiles() {}\n      };\n\n\n\n\n\n      this.prototype._thumbnailQueue = [];\n      this.prototype._processingThumbnail = false;\n    }\n\n    // global utility\n\n  }, {\n    key: \"extend\",\n    value: function extend(target) {\n      for (var _len2 = arguments.length, objects = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n        objects[_key2 - 1] = arguments[_key2];\n      }\n\n      for (var _iterator9 = objects, _isArray9 = true, _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : _iterator9[Symbol.iterator]();;) {\n        var _ref8;\n\n        if (_isArray9) {\n          if (_i9 >= _iterator9.length) break;\n          _ref8 = _iterator9[_i9++];\n        } else {\n          _i9 = _iterator9.next();\n          if (_i9.done) break;\n          _ref8 = _i9.value;\n        }\n\n        var object = _ref8;\n\n        for (var key in object) {\n          var val = object[key];\n          target[key] = val;\n        }\n      }\n      return target;\n    }\n  }]);\n\n  function Dropzone(el, options) {\n    _classCallCheck(this, Dropzone);\n\n    var _this = _possibleConstructorReturn(this, (Dropzone.__proto__ || Object.getPrototypeOf(Dropzone)).call(this));\n\n    var fallback = void 0,\n        left = void 0;\n    _this.element = el;\n    // For backwards compatibility since the version was in the prototype previously\n    _this.version = Dropzone.version;\n\n    _this.defaultOptions.previewTemplate = _this.defaultOptions.previewTemplate.replace(/\\n*/g, \"\");\n\n    _this.clickableElements = [];\n    _this.listeners = [];\n    _this.files = []; // All files\n\n    if (typeof _this.element === \"string\") {\n      _this.element = document.querySelector(_this.element);\n    }\n\n    // Not checking if instance of HTMLElement or Element since IE9 is extremely weird.\n    if (!_this.element || _this.element.nodeType == null) {\n      throw new Error(\"Invalid dropzone element.\");\n    }\n\n    if (_this.element.dropzone) {\n      throw new Error(\"Dropzone already attached.\");\n    }\n\n    // Now add this dropzone to the instances.\n    Dropzone.instances.push(_this);\n\n    // Put the dropzone inside the element itself.\n    _this.element.dropzone = _this;\n\n    var elementOptions = (left = Dropzone.optionsForElement(_this.element)) != null ? left : {};\n\n    _this.options = Dropzone.extend({}, _this.defaultOptions, elementOptions, options != null ? options : {});\n\n    // If the browser failed, just call the fallback and leave\n    if (_this.options.forceFallback || !Dropzone.isBrowserSupported()) {\n      var _ret;\n\n      return _ret = _this.options.fallback.call(_this), _possibleConstructorReturn(_this, _ret);\n    }\n\n    // @options.url = @element.getAttribute \"action\" unless @options.url?\n    if (_this.options.url == null) {\n      _this.options.url = _this.element.getAttribute(\"action\");\n    }\n\n    if (!_this.options.url) {\n      throw new Error(\"No URL provided.\");\n    }\n\n    if (_this.options.acceptedFiles && _this.options.acceptedMimeTypes) {\n      throw new Error(\"You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.\");\n    }\n\n    if (_this.options.uploadMultiple && _this.options.chunking) {\n      throw new Error('You cannot set both: uploadMultiple and chunking.');\n    }\n\n    // Backwards compatibility\n    if (_this.options.acceptedMimeTypes) {\n      _this.options.acceptedFiles = _this.options.acceptedMimeTypes;\n      delete _this.options.acceptedMimeTypes;\n    }\n\n    // Backwards compatibility\n    if (_this.options.renameFilename != null) {\n      _this.options.renameFile = function (file) {\n        return _this.options.renameFilename.call(_this, file.name, file);\n      };\n    }\n\n    _this.options.method = _this.options.method.toUpperCase();\n\n    if ((fallback = _this.getExistingFallback()) && fallback.parentNode) {\n      // Remove the fallback\n      fallback.parentNode.removeChild(fallback);\n    }\n\n    // Display previews in the previewsContainer element or the Dropzone element unless explicitly set to false\n    if (_this.options.previewsContainer !== false) {\n      if (_this.options.previewsContainer) {\n        _this.previewsContainer = Dropzone.getElement(_this.options.previewsContainer, \"previewsContainer\");\n      } else {\n        _this.previewsContainer = _this.element;\n      }\n    }\n\n    if (_this.options.clickable) {\n      if (_this.options.clickable === true) {\n        _this.clickableElements = [_this.element];\n      } else {\n        _this.clickableElements = Dropzone.getElements(_this.options.clickable, \"clickable\");\n      }\n    }\n\n    _this.init();\n    return _this;\n  }\n\n  // Returns all files that have been accepted\n\n\n  _createClass(Dropzone, [{\n    key: \"getAcceptedFiles\",\n    value: function getAcceptedFiles() {\n      return this.files.filter(function (file) {\n        return file.accepted;\n      }).map(function (file) {\n        return file;\n      });\n    }\n\n    // Returns all files that have been rejected\n    // Not sure when that's going to be useful, but added for completeness.\n\n  }, {\n    key: \"getRejectedFiles\",\n    value: function getRejectedFiles() {\n      return this.files.filter(function (file) {\n        return !file.accepted;\n      }).map(function (file) {\n        return file;\n      });\n    }\n  }, {\n    key: \"getFilesWithStatus\",\n    value: function getFilesWithStatus(status) {\n      return this.files.filter(function (file) {\n        return file.status === status;\n      }).map(function (file) {\n        return file;\n      });\n    }\n\n    // Returns all files that are in the queue\n\n  }, {\n    key: \"getQueuedFiles\",\n    value: function getQueuedFiles() {\n      return this.getFilesWithStatus(Dropzone.QUEUED);\n    }\n  }, {\n    key: \"getUploadingFiles\",\n    value: function getUploadingFiles() {\n      return this.getFilesWithStatus(Dropzone.UPLOADING);\n    }\n  }, {\n    key: \"getAddedFiles\",\n    value: function getAddedFiles() {\n      return this.getFilesWithStatus(Dropzone.ADDED);\n    }\n\n    // Files that are either queued or uploading\n\n  }, {\n    key: \"getActiveFiles\",\n    value: function getActiveFiles() {\n      return this.files.filter(function (file) {\n        return file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED;\n      }).map(function (file) {\n        return file;\n      });\n    }\n\n    // The function that gets called when Dropzone is initialized. You\n    // can (and should) setup event listeners inside this function.\n\n  }, {\n    key: \"init\",\n    value: function init() {\n      var _this3 = this;\n\n      // In case it isn't set already\n      if (this.element.tagName === \"form\") {\n        this.element.setAttribute(\"enctype\", \"multipart/form-data\");\n      }\n\n      if (this.element.classList.contains(\"dropzone\") && !this.element.querySelector(\".dz-message\")) {\n        this.element.appendChild(Dropzone.createElement(\"<div class=\\\"dz-default dz-message\\\"><span>\" + this.options.dictDefaultMessage + \"</span></div>\"));\n      }\n\n      if (this.clickableElements.length) {\n        var setupHiddenFileInput = function setupHiddenFileInput() {\n          if (_this3.hiddenFileInput) {\n            _this3.hiddenFileInput.parentNode.removeChild(_this3.hiddenFileInput);\n          }\n          _this3.hiddenFileInput = document.createElement(\"input\");\n          _this3.hiddenFileInput.setAttribute(\"type\", \"file\");\n          if (_this3.options.maxFiles === null || _this3.options.maxFiles > 1) {\n            _this3.hiddenFileInput.setAttribute(\"multiple\", \"multiple\");\n          }\n          _this3.hiddenFileInput.className = \"dz-hidden-input\";\n\n          if (_this3.options.acceptedFiles !== null) {\n            _this3.hiddenFileInput.setAttribute(\"accept\", _this3.options.acceptedFiles);\n          }\n          if (_this3.options.capture !== null) {\n            _this3.hiddenFileInput.setAttribute(\"capture\", _this3.options.capture);\n          }\n\n          // Not setting `display=\"none\"` because some browsers don't accept clicks\n          // on elements that aren't displayed.\n          _this3.hiddenFileInput.style.visibility = \"hidden\";\n          _this3.hiddenFileInput.style.position = \"absolute\";\n          _this3.hiddenFileInput.style.top = \"0\";\n          _this3.hiddenFileInput.style.left = \"0\";\n          _this3.hiddenFileInput.style.height = \"0\";\n          _this3.hiddenFileInput.style.width = \"0\";\n          document.querySelector(_this3.options.hiddenInputContainer).appendChild(_this3.hiddenFileInput);\n          return _this3.hiddenFileInput.addEventListener(\"change\", function () {\n            var files = _this3.hiddenFileInput.files;\n\n            if (files.length) {\n              for (var _iterator10 = files, _isArray10 = true, _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : _iterator10[Symbol.iterator]();;) {\n                var _ref9;\n\n                if (_isArray10) {\n                  if (_i10 >= _iterator10.length) break;\n                  _ref9 = _iterator10[_i10++];\n                } else {\n                  _i10 = _iterator10.next();\n                  if (_i10.done) break;\n                  _ref9 = _i10.value;\n                }\n\n                var file = _ref9;\n\n                _this3.addFile(file);\n              }\n            }\n            _this3.emit(\"addedfiles\", files);\n            return setupHiddenFileInput();\n          });\n        };\n        setupHiddenFileInput();\n      }\n\n      this.URL = window.URL !== null ? window.URL : window.webkitURL;\n\n      // Setup all event listeners on the Dropzone object itself.\n      // They're not in @setupEventListeners() because they shouldn't be removed\n      // again when the dropzone gets disabled.\n      for (var _iterator11 = this.events, _isArray11 = true, _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : _iterator11[Symbol.iterator]();;) {\n        var _ref10;\n\n        if (_isArray11) {\n          if (_i11 >= _iterator11.length) break;\n          _ref10 = _iterator11[_i11++];\n        } else {\n          _i11 = _iterator11.next();\n          if (_i11.done) break;\n          _ref10 = _i11.value;\n        }\n\n        var eventName = _ref10;\n\n        this.on(eventName, this.options[eventName]);\n      }\n\n      this.on(\"uploadprogress\", function () {\n        return _this3.updateTotalUploadProgress();\n      });\n\n      this.on(\"removedfile\", function () {\n        return _this3.updateTotalUploadProgress();\n      });\n\n      this.on(\"canceled\", function (file) {\n        return _this3.emit(\"complete\", file);\n      });\n\n      // Emit a `queuecomplete` event if all files finished uploading.\n      this.on(\"complete\", function (file) {\n        if (_this3.getAddedFiles().length === 0 && _this3.getUploadingFiles().length === 0 && _this3.getQueuedFiles().length === 0) {\n          // This needs to be deferred so that `queuecomplete` really triggers after `complete`\n          return setTimeout(function () {\n            return _this3.emit(\"queuecomplete\");\n          }, 0);\n        }\n      });\n\n      var noPropagation = function noPropagation(e) {\n        e.stopPropagation();\n        if (e.preventDefault) {\n          return e.preventDefault();\n        } else {\n          return e.returnValue = false;\n        }\n      };\n\n      // Create the listeners\n      this.listeners = [{\n        element: this.element,\n        events: {\n          \"dragstart\": function dragstart(e) {\n            return _this3.emit(\"dragstart\", e);\n          },\n          \"dragenter\": function dragenter(e) {\n            noPropagation(e);\n            return _this3.emit(\"dragenter\", e);\n          },\n          \"dragover\": function dragover(e) {\n            // Makes it possible to drag files from chrome's download bar\n            // http://stackoverflow.com/questions/19526430/drag-and-drop-file-uploads-from-chrome-downloads-bar\n            // Try is required to prevent bug in Internet Explorer 11 (SCRIPT65535 exception)\n            var efct = void 0;\n            try {\n              efct = e.dataTransfer.effectAllowed;\n            } catch (error) {}\n            e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';\n\n            noPropagation(e);\n            return _this3.emit(\"dragover\", e);\n          },\n          \"dragleave\": function dragleave(e) {\n            return _this3.emit(\"dragleave\", e);\n          },\n          \"drop\": function drop(e) {\n            noPropagation(e);\n            return _this3.drop(e);\n          },\n          \"dragend\": function dragend(e) {\n            return _this3.emit(\"dragend\", e);\n          }\n\n          // This is disabled right now, because the browsers don't implement it properly.\n          // \"paste\": (e) =>\n          //   noPropagation e\n          //   @paste e\n        } }];\n\n      this.clickableElements.forEach(function (clickableElement) {\n        return _this3.listeners.push({\n          element: clickableElement,\n          events: {\n            \"click\": function click(evt) {\n              // Only the actual dropzone or the message element should trigger file selection\n              if (clickableElement !== _this3.element || evt.target === _this3.element || Dropzone.elementInside(evt.target, _this3.element.querySelector(\".dz-message\"))) {\n                _this3.hiddenFileInput.click(); // Forward the click\n              }\n              return true;\n            }\n          }\n        });\n      });\n\n      this.enable();\n\n      return this.options.init.call(this);\n    }\n\n    // Not fully tested yet\n\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      this.disable();\n      this.removeAllFiles(true);\n      if (this.hiddenFileInput != null ? this.hiddenFileInput.parentNode : undefined) {\n        this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);\n        this.hiddenFileInput = null;\n      }\n      delete this.element.dropzone;\n      return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);\n    }\n  }, {\n    key: \"updateTotalUploadProgress\",\n    value: function updateTotalUploadProgress() {\n      var totalUploadProgress = void 0;\n      var totalBytesSent = 0;\n      var totalBytes = 0;\n\n      var activeFiles = this.getActiveFiles();\n\n      if (activeFiles.length) {\n        for (var _iterator12 = this.getActiveFiles(), _isArray12 = true, _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : _iterator12[Symbol.iterator]();;) {\n          var _ref11;\n\n          if (_isArray12) {\n            if (_i12 >= _iterator12.length) break;\n            _ref11 = _iterator12[_i12++];\n          } else {\n            _i12 = _iterator12.next();\n            if (_i12.done) break;\n            _ref11 = _i12.value;\n          }\n\n          var file = _ref11;\n\n          totalBytesSent += file.upload.bytesSent;\n          totalBytes += file.upload.total;\n        }\n        totalUploadProgress = 100 * totalBytesSent / totalBytes;\n      } else {\n        totalUploadProgress = 100;\n      }\n\n      return this.emit(\"totaluploadprogress\", totalUploadProgress, totalBytes, totalBytesSent);\n    }\n\n    // @options.paramName can be a function taking one parameter rather than a string.\n    // A parameter name for a file is obtained simply by calling this with an index number.\n\n  }, {\n    key: \"_getParamName\",\n    value: function _getParamName(n) {\n      if (typeof this.options.paramName === \"function\") {\n        return this.options.paramName(n);\n      } else {\n        return \"\" + this.options.paramName + (this.options.uploadMultiple ? \"[\" + n + \"]\" : \"\");\n      }\n    }\n\n    // If @options.renameFile is a function,\n    // the function will be used to rename the file.name before appending it to the formData\n\n  }, {\n    key: \"_renameFile\",\n    value: function _renameFile(file) {\n      if (typeof this.options.renameFile !== \"function\") {\n        return file.name;\n      }\n      return this.options.renameFile(file);\n    }\n\n    // Returns a form that can be used as fallback if the browser does not support DragnDrop\n    //\n    // If the dropzone is already a form, only the input field and button are returned. Otherwise a complete form element is provided.\n    // This code has to pass in IE7 :(\n\n  }, {\n    key: \"getFallbackForm\",\n    value: function getFallbackForm() {\n      var existingFallback = void 0,\n          form = void 0;\n      if (existingFallback = this.getExistingFallback()) {\n        return existingFallback;\n      }\n\n      var fieldsString = \"<div class=\\\"dz-fallback\\\">\";\n      if (this.options.dictFallbackText) {\n        fieldsString += \"<p>\" + this.options.dictFallbackText + \"</p>\";\n      }\n      fieldsString += \"<input type=\\\"file\\\" name=\\\"\" + this._getParamName(0) + \"\\\" \" + (this.options.uploadMultiple ? 'multiple=\"multiple\"' : undefined) + \" /><input type=\\\"submit\\\" value=\\\"Upload!\\\"></div>\";\n\n      var fields = Dropzone.createElement(fieldsString);\n      if (this.element.tagName !== \"FORM\") {\n        form = Dropzone.createElement(\"<form action=\\\"\" + this.options.url + \"\\\" enctype=\\\"multipart/form-data\\\" method=\\\"\" + this.options.method + \"\\\"></form>\");\n        form.appendChild(fields);\n      } else {\n        // Make sure that the enctype and method attributes are set properly\n        this.element.setAttribute(\"enctype\", \"multipart/form-data\");\n        this.element.setAttribute(\"method\", this.options.method);\n      }\n      return form != null ? form : fields;\n    }\n\n    // Returns the fallback elements if they exist already\n    //\n    // This code has to pass in IE7 :(\n\n  }, {\n    key: \"getExistingFallback\",\n    value: function getExistingFallback() {\n      var getFallback = function getFallback(elements) {\n        for (var _iterator13 = elements, _isArray13 = true, _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : _iterator13[Symbol.iterator]();;) {\n          var _ref12;\n\n          if (_isArray13) {\n            if (_i13 >= _iterator13.length) break;\n            _ref12 = _iterator13[_i13++];\n          } else {\n            _i13 = _iterator13.next();\n            if (_i13.done) break;\n            _ref12 = _i13.value;\n          }\n\n          var el = _ref12;\n\n          if (/(^| )fallback($| )/.test(el.className)) {\n            return el;\n          }\n        }\n      };\n\n      var _arr = [\"div\", \"form\"];\n      for (var _i14 = 0; _i14 < _arr.length; _i14++) {\n        var tagName = _arr[_i14];\n        var fallback;\n        if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {\n          return fallback;\n        }\n      }\n    }\n\n    // Activates all listeners stored in @listeners\n\n  }, {\n    key: \"setupEventListeners\",\n    value: function setupEventListeners() {\n      return this.listeners.map(function (elementListeners) {\n        return function () {\n          var result = [];\n          for (var event in elementListeners.events) {\n            var listener = elementListeners.events[event];\n            result.push(elementListeners.element.addEventListener(event, listener, false));\n          }\n          return result;\n        }();\n      });\n    }\n\n    // Deactivates all listeners stored in @listeners\n\n  }, {\n    key: \"removeEventListeners\",\n    value: function removeEventListeners() {\n      return this.listeners.map(function (elementListeners) {\n        return function () {\n          var result = [];\n          for (var event in elementListeners.events) {\n            var listener = elementListeners.events[event];\n            result.push(elementListeners.element.removeEventListener(event, listener, false));\n          }\n          return result;\n        }();\n      });\n    }\n\n    // Removes all event listeners and cancels all files in the queue or being processed.\n\n  }, {\n    key: \"disable\",\n    value: function disable() {\n      var _this4 = this;\n\n      this.clickableElements.forEach(function (element) {\n        return element.classList.remove(\"dz-clickable\");\n      });\n      this.removeEventListeners();\n      this.disabled = true;\n\n      return this.files.map(function (file) {\n        return _this4.cancelUpload(file);\n      });\n    }\n  }, {\n    key: \"enable\",\n    value: function enable() {\n      delete this.disabled;\n      this.clickableElements.forEach(function (element) {\n        return element.classList.add(\"dz-clickable\");\n      });\n      return this.setupEventListeners();\n    }\n\n    // Returns a nicely formatted filesize\n\n  }, {\n    key: \"filesize\",\n    value: function filesize(size) {\n      var selectedSize = 0;\n      var selectedUnit = \"b\";\n\n      if (size > 0) {\n        var units = ['tb', 'gb', 'mb', 'kb', 'b'];\n\n        for (var i = 0; i < units.length; i++) {\n          var unit = units[i];\n          var cutoff = Math.pow(this.options.filesizeBase, 4 - i) / 10;\n\n          if (size >= cutoff) {\n            selectedSize = size / Math.pow(this.options.filesizeBase, 4 - i);\n            selectedUnit = unit;\n            break;\n          }\n        }\n\n        selectedSize = Math.round(10 * selectedSize) / 10; // Cutting of digits\n      }\n\n      return \"<strong>\" + selectedSize + \"</strong> \" + this.options.dictFileSizeUnits[selectedUnit];\n    }\n\n    // Adds or removes the `dz-max-files-reached` class from the form.\n\n  }, {\n    key: \"_updateMaxFilesReachedClass\",\n    value: function _updateMaxFilesReachedClass() {\n      if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {\n        if (this.getAcceptedFiles().length === this.options.maxFiles) {\n          this.emit('maxfilesreached', this.files);\n        }\n        return this.element.classList.add(\"dz-max-files-reached\");\n      } else {\n        return this.element.classList.remove(\"dz-max-files-reached\");\n      }\n    }\n  }, {\n    key: \"drop\",\n    value: function drop(e) {\n      if (!e.dataTransfer) {\n        return;\n      }\n      this.emit(\"drop\", e);\n\n      // Convert the FileList to an Array\n      // This is necessary for IE11\n      var files = [];\n      for (var i = 0; i < e.dataTransfer.files.length; i++) {\n        files[i] = e.dataTransfer.files[i];\n      }\n\n      this.emit(\"addedfiles\", files);\n\n      // Even if it's a folder, files.length will contain the folders.\n      if (files.length) {\n        var items = e.dataTransfer.items;\n\n        if (items && items.length && items[0].webkitGetAsEntry != null) {\n          // The browser supports dropping of folders, so handle items instead of files\n          this._addFilesFromItems(items);\n        } else {\n          this.handleFiles(files);\n        }\n      }\n    }\n  }, {\n    key: \"paste\",\n    value: function paste(e) {\n      if (__guard__(e != null ? e.clipboardData : undefined, function (x) {\n        return x.items;\n      }) == null) {\n        return;\n      }\n\n      this.emit(\"paste\", e);\n      var items = e.clipboardData.items;\n\n\n      if (items.length) {\n        return this._addFilesFromItems(items);\n      }\n    }\n  }, {\n    key: \"handleFiles\",\n    value: function handleFiles(files) {\n      for (var _iterator14 = files, _isArray14 = true, _i15 = 0, _iterator14 = _isArray14 ? _iterator14 : _iterator14[Symbol.iterator]();;) {\n        var _ref13;\n\n        if (_isArray14) {\n          if (_i15 >= _iterator14.length) break;\n          _ref13 = _iterator14[_i15++];\n        } else {\n          _i15 = _iterator14.next();\n          if (_i15.done) break;\n          _ref13 = _i15.value;\n        }\n\n        var file = _ref13;\n\n        this.addFile(file);\n      }\n    }\n\n    // When a folder is dropped (or files are pasted), items must be handled\n    // instead of files.\n\n  }, {\n    key: \"_addFilesFromItems\",\n    value: function _addFilesFromItems(items) {\n      var _this5 = this;\n\n      return function () {\n        var result = [];\n        for (var _iterator15 = items, _isArray15 = true, _i16 = 0, _iterator15 = _isArray15 ? _iterator15 : _iterator15[Symbol.iterator]();;) {\n          var _ref14;\n\n          if (_isArray15) {\n            if (_i16 >= _iterator15.length) break;\n            _ref14 = _iterator15[_i16++];\n          } else {\n            _i16 = _iterator15.next();\n            if (_i16.done) break;\n            _ref14 = _i16.value;\n          }\n\n          var item = _ref14;\n\n          var entry;\n          if (item.webkitGetAsEntry != null && (entry = item.webkitGetAsEntry())) {\n            if (entry.isFile) {\n              result.push(_this5.addFile(item.getAsFile()));\n            } else if (entry.isDirectory) {\n              // Append all files from that directory to files\n              result.push(_this5._addFilesFromDirectory(entry, entry.name));\n            } else {\n              result.push(undefined);\n            }\n          } else if (item.getAsFile != null) {\n            if (item.kind == null || item.kind === \"file\") {\n              result.push(_this5.addFile(item.getAsFile()));\n            } else {\n              result.push(undefined);\n            }\n          } else {\n            result.push(undefined);\n          }\n        }\n        return result;\n      }();\n    }\n\n    // Goes through the directory, and adds each file it finds recursively\n\n  }, {\n    key: \"_addFilesFromDirectory\",\n    value: function _addFilesFromDirectory(directory, path) {\n      var _this6 = this;\n\n      var dirReader = directory.createReader();\n\n      var errorHandler = function errorHandler(error) {\n        return __guardMethod__(console, 'log', function (o) {\n          return o.log(error);\n        });\n      };\n\n      var readEntries = function readEntries() {\n        return dirReader.readEntries(function (entries) {\n          if (entries.length > 0) {\n            for (var _iterator16 = entries, _isArray16 = true, _i17 = 0, _iterator16 = _isArray16 ? _iterator16 : _iterator16[Symbol.iterator]();;) {\n              var _ref15;\n\n              if (_isArray16) {\n                if (_i17 >= _iterator16.length) break;\n                _ref15 = _iterator16[_i17++];\n              } else {\n                _i17 = _iterator16.next();\n                if (_i17.done) break;\n                _ref15 = _i17.value;\n              }\n\n              var entry = _ref15;\n\n              if (entry.isFile) {\n                entry.file(function (file) {\n                  if (_this6.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {\n                    return;\n                  }\n                  file.fullPath = path + \"/\" + file.name;\n                  return _this6.addFile(file);\n                });\n              } else if (entry.isDirectory) {\n                _this6._addFilesFromDirectory(entry, path + \"/\" + entry.name);\n              }\n            }\n\n            // Recursively call readEntries() again, since browser only handle\n            // the first 100 entries.\n            // See: https://developer.mozilla.org/en-US/docs/Web/API/DirectoryReader#readEntries\n            readEntries();\n          }\n          return null;\n        }, errorHandler);\n      };\n\n      return readEntries();\n    }\n\n    // If `done()` is called without argument the file is accepted\n    // If you call it with an error message, the file is rejected\n    // (This allows for asynchronous validation)\n    //\n    // This function checks the filesize, and if the file.type passes the\n    // `acceptedFiles` check.\n\n  }, {\n    key: \"accept\",\n    value: function accept(file, done) {\n      if (file.size > this.options.maxFilesize * 1024 * 1024) {\n        return done(this.options.dictFileTooBig.replace(\"{{filesize}}\", Math.round(file.size / 1024 / 10.24) / 100).replace(\"{{maxFilesize}}\", this.options.maxFilesize));\n      } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {\n        return done(this.options.dictInvalidFileType);\n      } else if (this.options.maxFiles != null && this.getAcceptedFiles().length >= this.options.maxFiles) {\n        done(this.options.dictMaxFilesExceeded.replace(\"{{maxFiles}}\", this.options.maxFiles));\n        return this.emit(\"maxfilesexceeded\", file);\n      } else {\n        return this.options.accept.call(this, file, done);\n      }\n    }\n  }, {\n    key: \"addFile\",\n    value: function addFile(file) {\n      var _this7 = this;\n\n      file.upload = {\n        uuid: Dropzone.uuidv4(),\n        progress: 0,\n        // Setting the total upload size to file.size for the beginning\n        // It's actual different than the size to be transmitted.\n        total: file.size,\n        bytesSent: 0,\n        filename: this._renameFile(file),\n        chunked: this.options.chunking && (this.options.forceChunking || file.size > this.options.chunkSize),\n        totalChunkCount: Math.ceil(file.size / this.options.chunkSize)\n      };\n      this.files.push(file);\n\n      file.status = Dropzone.ADDED;\n\n      this.emit(\"addedfile\", file);\n\n      this._enqueueThumbnail(file);\n\n      return this.accept(file, function (error) {\n        if (error) {\n          file.accepted = false;\n          _this7._errorProcessing([file], error); // Will set the file.status\n        } else {\n          file.accepted = true;\n          if (_this7.options.autoQueue) {\n            _this7.enqueueFile(file);\n          } // Will set .accepted = true\n        }\n        return _this7._updateMaxFilesReachedClass();\n      });\n    }\n\n    // Wrapper for enqueueFile\n\n  }, {\n    key: \"enqueueFiles\",\n    value: function enqueueFiles(files) {\n      for (var _iterator17 = files, _isArray17 = true, _i18 = 0, _iterator17 = _isArray17 ? _iterator17 : _iterator17[Symbol.iterator]();;) {\n        var _ref16;\n\n        if (_isArray17) {\n          if (_i18 >= _iterator17.length) break;\n          _ref16 = _iterator17[_i18++];\n        } else {\n          _i18 = _iterator17.next();\n          if (_i18.done) break;\n          _ref16 = _i18.value;\n        }\n\n        var file = _ref16;\n\n        this.enqueueFile(file);\n      }\n      return null;\n    }\n  }, {\n    key: \"enqueueFile\",\n    value: function enqueueFile(file) {\n      var _this8 = this;\n\n      if (file.status === Dropzone.ADDED && file.accepted === true) {\n        file.status = Dropzone.QUEUED;\n        if (this.options.autoProcessQueue) {\n          return setTimeout(function () {\n            return _this8.processQueue();\n          }, 0); // Deferring the call\n        }\n      } else {\n        throw new Error(\"This file can't be queued because it has already been processed or was rejected.\");\n      }\n    }\n  }, {\n    key: \"_enqueueThumbnail\",\n    value: function _enqueueThumbnail(file) {\n      var _this9 = this;\n\n      if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {\n        this._thumbnailQueue.push(file);\n        return setTimeout(function () {\n          return _this9._processThumbnailQueue();\n        }, 0); // Deferring the call\n      }\n    }\n  }, {\n    key: \"_processThumbnailQueue\",\n    value: function _processThumbnailQueue() {\n      var _this10 = this;\n\n      if (this._processingThumbnail || this._thumbnailQueue.length === 0) {\n        return;\n      }\n\n      this._processingThumbnail = true;\n      var file = this._thumbnailQueue.shift();\n      return this.createThumbnail(file, this.options.thumbnailWidth, this.options.thumbnailHeight, this.options.thumbnailMethod, true, function (dataUrl) {\n        _this10.emit(\"thumbnail\", file, dataUrl);\n        _this10._processingThumbnail = false;\n        return _this10._processThumbnailQueue();\n      });\n    }\n\n    // Can be called by the user to remove a file\n\n  }, {\n    key: \"removeFile\",\n    value: function removeFile(file) {\n      if (file.status === Dropzone.UPLOADING) {\n        this.cancelUpload(file);\n      }\n      this.files = without(this.files, file);\n\n      this.emit(\"removedfile\", file);\n      if (this.files.length === 0) {\n        return this.emit(\"reset\");\n      }\n    }\n\n    // Removes all files that aren't currently processed from the list\n\n  }, {\n    key: \"removeAllFiles\",\n    value: function removeAllFiles(cancelIfNecessary) {\n      // Create a copy of files since removeFile() changes the @files array.\n      if (cancelIfNecessary == null) {\n        cancelIfNecessary = false;\n      }\n      for (var _iterator18 = this.files.slice(), _isArray18 = true, _i19 = 0, _iterator18 = _isArray18 ? _iterator18 : _iterator18[Symbol.iterator]();;) {\n        var _ref17;\n\n        if (_isArray18) {\n          if (_i19 >= _iterator18.length) break;\n          _ref17 = _iterator18[_i19++];\n        } else {\n          _i19 = _iterator18.next();\n          if (_i19.done) break;\n          _ref17 = _i19.value;\n        }\n\n        var file = _ref17;\n\n        if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {\n          this.removeFile(file);\n        }\n      }\n      return null;\n    }\n\n    // Resizes an image before it gets sent to the server. This function is the default behavior of\n    // `options.transformFile` if `resizeWidth` or `resizeHeight` are set. The callback is invoked with\n    // the resized blob.\n\n  }, {\n    key: \"resizeImage\",\n    value: function resizeImage(file, width, height, resizeMethod, callback) {\n      var _this11 = this;\n\n      return this.createThumbnail(file, width, height, resizeMethod, false, function (dataUrl, canvas) {\n        if (canvas == null) {\n          // The image has not been resized\n          return callback(file);\n        } else {\n          var resizeMimeType = _this11.options.resizeMimeType;\n\n          if (resizeMimeType == null) {\n            resizeMimeType = file.type;\n          }\n          var resizedDataURL = canvas.toDataURL(resizeMimeType, _this11.options.resizeQuality);\n          if (resizeMimeType === 'image/jpeg' || resizeMimeType === 'image/jpg') {\n            // Now add the original EXIF information\n            resizedDataURL = ExifRestore.restore(file.dataURL, resizedDataURL);\n          }\n          return callback(Dropzone.dataURItoBlob(resizedDataURL));\n        }\n      });\n    }\n  }, {\n    key: \"createThumbnail\",\n    value: function createThumbnail(file, width, height, resizeMethod, fixOrientation, callback) {\n      var _this12 = this;\n\n      var fileReader = new FileReader();\n\n      fileReader.onload = function () {\n\n        file.dataURL = fileReader.result;\n\n        // Don't bother creating a thumbnail for SVG images since they're vector\n        if (file.type === \"image/svg+xml\") {\n          if (callback != null) {\n            callback(fileReader.result);\n          }\n          return;\n        }\n\n        return _this12.createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback);\n      };\n\n      return fileReader.readAsDataURL(file);\n    }\n  }, {\n    key: \"createThumbnailFromUrl\",\n    value: function createThumbnailFromUrl(file, width, height, resizeMethod, fixOrientation, callback, crossOrigin) {\n      var _this13 = this;\n\n      // Not using `new Image` here because of a bug in latest Chrome versions.\n      // See https://github.com/enyo/dropzone/pull/226\n      var img = document.createElement(\"img\");\n\n      if (crossOrigin) {\n        img.crossOrigin = crossOrigin;\n      }\n\n      img.onload = function () {\n        var loadExif = function loadExif(callback) {\n          return callback(1);\n        };\n        if (typeof EXIF !== 'undefined' && EXIF !== null && fixOrientation) {\n          loadExif = function loadExif(callback) {\n            return EXIF.getData(img, function () {\n              return callback(EXIF.getTag(this, 'Orientation'));\n            });\n          };\n        }\n\n        return loadExif(function (orientation) {\n          file.width = img.width;\n          file.height = img.height;\n\n          var resizeInfo = _this13.options.resize.call(_this13, file, width, height, resizeMethod);\n\n          var canvas = document.createElement(\"canvas\");\n          var ctx = canvas.getContext(\"2d\");\n\n          canvas.width = resizeInfo.trgWidth;\n          canvas.height = resizeInfo.trgHeight;\n\n          if (orientation > 4) {\n            canvas.width = resizeInfo.trgHeight;\n            canvas.height = resizeInfo.trgWidth;\n          }\n\n          switch (orientation) {\n            case 2:\n              // horizontal flip\n              ctx.translate(canvas.width, 0);\n              ctx.scale(-1, 1);\n              break;\n            case 3:\n              // 180° rotate left\n              ctx.translate(canvas.width, canvas.height);\n              ctx.rotate(Math.PI);\n              break;\n            case 4:\n              // vertical flip\n              ctx.translate(0, canvas.height);\n              ctx.scale(1, -1);\n              break;\n            case 5:\n              // vertical flip + 90 rotate right\n              ctx.rotate(0.5 * Math.PI);\n              ctx.scale(1, -1);\n              break;\n            case 6:\n              // 90° rotate right\n              ctx.rotate(0.5 * Math.PI);\n              ctx.translate(0, -canvas.height);\n              break;\n            case 7:\n              // horizontal flip + 90 rotate right\n              ctx.rotate(0.5 * Math.PI);\n              ctx.translate(canvas.width, -canvas.height);\n              ctx.scale(-1, 1);\n              break;\n            case 8:\n              // 90° rotate left\n              ctx.rotate(-0.5 * Math.PI);\n              ctx.translate(-canvas.width, 0);\n              break;\n          }\n\n          // This is a bugfix for iOS' scaling bug.\n          drawImageIOSFix(ctx, img, resizeInfo.srcX != null ? resizeInfo.srcX : 0, resizeInfo.srcY != null ? resizeInfo.srcY : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, resizeInfo.trgX != null ? resizeInfo.trgX : 0, resizeInfo.trgY != null ? resizeInfo.trgY : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);\n\n          var thumbnail = canvas.toDataURL(\"image/png\");\n\n          if (callback != null) {\n            return callback(thumbnail, canvas);\n          }\n        });\n      };\n\n      if (callback != null) {\n        img.onerror = callback;\n      }\n\n      return img.src = file.dataURL;\n    }\n\n    // Goes through the queue and processes files if there aren't too many already.\n\n  }, {\n    key: \"processQueue\",\n    value: function processQueue() {\n      var parallelUploads = this.options.parallelUploads;\n\n      var processingLength = this.getUploadingFiles().length;\n      var i = processingLength;\n\n      // There are already at least as many files uploading than should be\n      if (processingLength >= parallelUploads) {\n        return;\n      }\n\n      var queuedFiles = this.getQueuedFiles();\n\n      if (!(queuedFiles.length > 0)) {\n        return;\n      }\n\n      if (this.options.uploadMultiple) {\n        // The files should be uploaded in one request\n        return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));\n      } else {\n        while (i < parallelUploads) {\n          if (!queuedFiles.length) {\n            return;\n          } // Nothing left to process\n          this.processFile(queuedFiles.shift());\n          i++;\n        }\n      }\n    }\n\n    // Wrapper for `processFiles`\n\n  }, {\n    key: \"processFile\",\n    value: function processFile(file) {\n      return this.processFiles([file]);\n    }\n\n    // Loads the file, then calls finishedLoading()\n\n  }, {\n    key: \"processFiles\",\n    value: function processFiles(files) {\n      for (var _iterator19 = files, _isArray19 = true, _i20 = 0, _iterator19 = _isArray19 ? _iterator19 : _iterator19[Symbol.iterator]();;) {\n        var _ref18;\n\n        if (_isArray19) {\n          if (_i20 >= _iterator19.length) break;\n          _ref18 = _iterator19[_i20++];\n        } else {\n          _i20 = _iterator19.next();\n          if (_i20.done) break;\n          _ref18 = _i20.value;\n        }\n\n        var file = _ref18;\n\n        file.processing = true; // Backwards compatibility\n        file.status = Dropzone.UPLOADING;\n\n        this.emit(\"processing\", file);\n      }\n\n      if (this.options.uploadMultiple) {\n        this.emit(\"processingmultiple\", files);\n      }\n\n      return this.uploadFiles(files);\n    }\n  }, {\n    key: \"_getFilesWithXhr\",\n    value: function _getFilesWithXhr(xhr) {\n      var files = void 0;\n      return files = this.files.filter(function (file) {\n        return file.xhr === xhr;\n      }).map(function (file) {\n        return file;\n      });\n    }\n\n    // Cancels the file upload and sets the status to CANCELED\n    // **if** the file is actually being uploaded.\n    // If it's still in the queue, the file is being removed from it and the status\n    // set to CANCELED.\n\n  }, {\n    key: \"cancelUpload\",\n    value: function cancelUpload(file) {\n      if (file.status === Dropzone.UPLOADING) {\n        var groupedFiles = this._getFilesWithXhr(file.xhr);\n        for (var _iterator20 = groupedFiles, _isArray20 = true, _i21 = 0, _iterator20 = _isArray20 ? _iterator20 : _iterator20[Symbol.iterator]();;) {\n          var _ref19;\n\n          if (_isArray20) {\n            if (_i21 >= _iterator20.length) break;\n            _ref19 = _iterator20[_i21++];\n          } else {\n            _i21 = _iterator20.next();\n            if (_i21.done) break;\n            _ref19 = _i21.value;\n          }\n\n          var groupedFile = _ref19;\n\n          groupedFile.status = Dropzone.CANCELED;\n        }\n        if (typeof file.xhr !== 'undefined') {\n          file.xhr.abort();\n        }\n        for (var _iterator21 = groupedFiles, _isArray21 = true, _i22 = 0, _iterator21 = _isArray21 ? _iterator21 : _iterator21[Symbol.iterator]();;) {\n          var _ref20;\n\n          if (_isArray21) {\n            if (_i22 >= _iterator21.length) break;\n            _ref20 = _iterator21[_i22++];\n          } else {\n            _i22 = _iterator21.next();\n            if (_i22.done) break;\n            _ref20 = _i22.value;\n          }\n\n          var _groupedFile = _ref20;\n\n          this.emit(\"canceled\", _groupedFile);\n        }\n        if (this.options.uploadMultiple) {\n          this.emit(\"canceledmultiple\", groupedFiles);\n        }\n      } else if (file.status === Dropzone.ADDED || file.status === Dropzone.QUEUED) {\n        file.status = Dropzone.CANCELED;\n        this.emit(\"canceled\", file);\n        if (this.options.uploadMultiple) {\n          this.emit(\"canceledmultiple\", [file]);\n        }\n      }\n\n      if (this.options.autoProcessQueue) {\n        return this.processQueue();\n      }\n    }\n  }, {\n    key: \"resolveOption\",\n    value: function resolveOption(option) {\n      if (typeof option === 'function') {\n        for (var _len3 = arguments.length, args = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {\n          args[_key3 - 1] = arguments[_key3];\n        }\n\n        return option.apply(this, args);\n      }\n      return option;\n    }\n  }, {\n    key: \"uploadFile\",\n    value: function uploadFile(file) {\n      return this.uploadFiles([file]);\n    }\n  }, {\n    key: \"uploadFiles\",\n    value: function uploadFiles(files) {\n      var _this14 = this;\n\n      this._transformFiles(files, function (transformedFiles) {\n        if (files[0].upload.chunked) {\n          // This file should be sent in chunks!\n\n          // If the chunking option is set, we **know** that there can only be **one** file, since\n          // uploadMultiple is not allowed with this option.\n          var file = files[0];\n          var transformedFile = transformedFiles[0];\n          var startedChunkCount = 0;\n\n          file.upload.chunks = [];\n\n          var handleNextChunk = function handleNextChunk() {\n            var chunkIndex = 0;\n\n            // Find the next item in file.upload.chunks that is not defined yet.\n            while (file.upload.chunks[chunkIndex] !== undefined) {\n              chunkIndex++;\n            }\n\n            // This means, that all chunks have already been started.\n            if (chunkIndex >= file.upload.totalChunkCount) return;\n\n            startedChunkCount++;\n\n            var start = chunkIndex * _this14.options.chunkSize;\n            var end = Math.min(start + _this14.options.chunkSize, file.size);\n\n            var dataBlock = {\n              name: _this14._getParamName(0),\n              data: transformedFile.webkitSlice ? transformedFile.webkitSlice(start, end) : transformedFile.slice(start, end),\n              filename: file.upload.filename,\n              chunkIndex: chunkIndex\n            };\n\n            file.upload.chunks[chunkIndex] = {\n              file: file,\n              index: chunkIndex,\n              dataBlock: dataBlock, // In case we want to retry.\n              status: Dropzone.UPLOADING,\n              progress: 0,\n              retries: 0 // The number of times this block has been retried.\n            };\n\n            _this14._uploadData(files, [dataBlock]);\n          };\n\n          file.upload.finishedChunkUpload = function (chunk) {\n            var allFinished = true;\n            chunk.status = Dropzone.SUCCESS;\n\n            // Clear the data from the chunk\n            chunk.dataBlock = null;\n\n            for (var i = 0; i < file.upload.totalChunkCount; i++) {\n              if (file.upload.chunks[i] === undefined) {\n                return handleNextChunk();\n              }\n              if (file.upload.chunks[i].status !== Dropzone.SUCCESS) {\n                allFinished = false;\n              }\n            }\n\n            if (allFinished) {\n              _this14.options.chunksUploaded(file, function () {\n                _this14._finished(files, '', null);\n              });\n            }\n          };\n\n          if (_this14.options.parallelChunkUploads) {\n            for (var i = 0; i < file.upload.totalChunkCount; i++) {\n              handleNextChunk();\n            }\n          } else {\n            handleNextChunk();\n          }\n        } else {\n          var dataBlocks = [];\n          for (var _i23 = 0; _i23 < files.length; _i23++) {\n            dataBlocks[_i23] = {\n              name: _this14._getParamName(_i23),\n              data: transformedFiles[_i23],\n              filename: files[_i23].upload.filename\n            };\n          }\n          _this14._uploadData(files, dataBlocks);\n        }\n      });\n    }\n\n    /// Returns the right chunk for given file and xhr\n\n  }, {\n    key: \"_getChunk\",\n    value: function _getChunk(file, xhr) {\n      for (var i = 0; i < file.upload.totalChunkCount; i++) {\n        if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].xhr === xhr) {\n          return file.upload.chunks[i];\n        }\n      }\n    }\n\n    // This function actually uploads the file(s) to the server.\n    // If dataBlocks contains the actual data to upload (meaning, that this could either be transformed\n    // files, or individual chunks for chunked upload).\n\n  }, {\n    key: \"_uploadData\",\n    value: function _uploadData(files, dataBlocks) {\n      var _this15 = this;\n\n      var xhr = new XMLHttpRequest();\n\n      // Put the xhr object in the file objects to be able to reference it later.\n      for (var _iterator22 = files, _isArray22 = true, _i24 = 0, _iterator22 = _isArray22 ? _iterator22 : _iterator22[Symbol.iterator]();;) {\n        var _ref21;\n\n        if (_isArray22) {\n          if (_i24 >= _iterator22.length) break;\n          _ref21 = _iterator22[_i24++];\n        } else {\n          _i24 = _iterator22.next();\n          if (_i24.done) break;\n          _ref21 = _i24.value;\n        }\n\n        var file = _ref21;\n\n        file.xhr = xhr;\n      }\n      if (files[0].upload.chunked) {\n        // Put the xhr object in the right chunk object, so it can be associated later, and found with _getChunk\n        files[0].upload.chunks[dataBlocks[0].chunkIndex].xhr = xhr;\n      }\n\n      var method = this.resolveOption(this.options.method, files);\n      var url = this.resolveOption(this.options.url, files);\n      xhr.open(method, url, true);\n\n      // Setting the timeout after open because of IE11 issue: https://gitlab.com/meno/dropzone/issues/8\n      xhr.timeout = this.resolveOption(this.options.timeout, files);\n\n      // Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179\n      xhr.withCredentials = !!this.options.withCredentials;\n\n      xhr.onload = function (e) {\n        _this15._finishedUploading(files, xhr, e);\n      };\n\n      xhr.onerror = function () {\n        _this15._handleUploadError(files, xhr);\n      };\n\n      // Some browsers do not have the .upload property\n      var progressObj = xhr.upload != null ? xhr.upload : xhr;\n      progressObj.onprogress = function (e) {\n        return _this15._updateFilesUploadProgress(files, xhr, e);\n      };\n\n      var headers = {\n        \"Accept\": \"application/json\",\n        \"Cache-Control\": \"no-cache\",\n        \"X-Requested-With\": \"XMLHttpRequest\"\n      };\n\n      if (this.options.headers) {\n        Dropzone.extend(headers, this.options.headers);\n      }\n\n      for (var headerName in headers) {\n        var headerValue = headers[headerName];\n        if (headerValue) {\n          xhr.setRequestHeader(headerName, headerValue);\n        }\n      }\n\n      var formData = new FormData();\n\n      // Adding all @options parameters\n      if (this.options.params) {\n        var additionalParams = this.options.params;\n        if (typeof additionalParams === 'function') {\n          additionalParams = additionalParams.call(this, files, xhr, files[0].upload.chunked ? this._getChunk(files[0], xhr) : null);\n        }\n\n        for (var key in additionalParams) {\n          var value = additionalParams[key];\n          formData.append(key, value);\n        }\n      }\n\n      // Let the user add additional data if necessary\n      for (var _iterator23 = files, _isArray23 = true, _i25 = 0, _iterator23 = _isArray23 ? _iterator23 : _iterator23[Symbol.iterator]();;) {\n        var _ref22;\n\n        if (_isArray23) {\n          if (_i25 >= _iterator23.length) break;\n          _ref22 = _iterator23[_i25++];\n        } else {\n          _i25 = _iterator23.next();\n          if (_i25.done) break;\n          _ref22 = _i25.value;\n        }\n\n        var _file = _ref22;\n\n        this.emit(\"sending\", _file, xhr, formData);\n      }\n      if (this.options.uploadMultiple) {\n        this.emit(\"sendingmultiple\", files, xhr, formData);\n      }\n\n      this._addFormElementData(formData);\n\n      // Finally add the files\n      // Has to be last because some servers (eg: S3) expect the file to be the last parameter\n      for (var i = 0; i < dataBlocks.length; i++) {\n        var dataBlock = dataBlocks[i];\n        formData.append(dataBlock.name, dataBlock.data, dataBlock.filename);\n      }\n\n      this.submitRequest(xhr, formData, files);\n    }\n\n    // Transforms all files with this.options.transformFile and invokes done with the transformed files when done.\n\n  }, {\n    key: \"_transformFiles\",\n    value: function _transformFiles(files, done) {\n      var _this16 = this;\n\n      var transformedFiles = [];\n      // Clumsy way of handling asynchronous calls, until I get to add a proper Future library.\n      var doneCounter = 0;\n\n      var _loop = function _loop(i) {\n        _this16.options.transformFile.call(_this16, files[i], function (transformedFile) {\n          transformedFiles[i] = transformedFile;\n          if (++doneCounter === files.length) {\n            done(transformedFiles);\n          }\n        });\n      };\n\n      for (var i = 0; i < files.length; i++) {\n        _loop(i);\n      }\n    }\n\n    // Takes care of adding other input elements of the form to the AJAX request\n\n  }, {\n    key: \"_addFormElementData\",\n    value: function _addFormElementData(formData) {\n      // Take care of other input elements\n      if (this.element.tagName === \"FORM\") {\n        for (var _iterator24 = this.element.querySelectorAll(\"input, textarea, select, button\"), _isArray24 = true, _i26 = 0, _iterator24 = _isArray24 ? _iterator24 : _iterator24[Symbol.iterator]();;) {\n          var _ref23;\n\n          if (_isArray24) {\n            if (_i26 >= _iterator24.length) break;\n            _ref23 = _iterator24[_i26++];\n          } else {\n            _i26 = _iterator24.next();\n            if (_i26.done) break;\n            _ref23 = _i26.value;\n          }\n\n          var input = _ref23;\n\n          var inputName = input.getAttribute(\"name\");\n          var inputType = input.getAttribute(\"type\");\n          if (inputType) inputType = inputType.toLowerCase();\n\n          // If the input doesn't have a name, we can't use it.\n          if (typeof inputName === 'undefined' || inputName === null) continue;\n\n          if (input.tagName === \"SELECT\" && input.hasAttribute(\"multiple\")) {\n            // Possibly multiple values\n            for (var _iterator25 = input.options, _isArray25 = true, _i27 = 0, _iterator25 = _isArray25 ? _iterator25 : _iterator25[Symbol.iterator]();;) {\n              var _ref24;\n\n              if (_isArray25) {\n                if (_i27 >= _iterator25.length) break;\n                _ref24 = _iterator25[_i27++];\n              } else {\n                _i27 = _iterator25.next();\n                if (_i27.done) break;\n                _ref24 = _i27.value;\n              }\n\n              var option = _ref24;\n\n              if (option.selected) {\n                formData.append(inputName, option.value);\n              }\n            }\n          } else if (!inputType || inputType !== \"checkbox\" && inputType !== \"radio\" || input.checked) {\n            formData.append(inputName, input.value);\n          }\n        }\n      }\n    }\n\n    // Invoked when there is new progress information about given files.\n    // If e is not provided, it is assumed that the upload is finished.\n\n  }, {\n    key: \"_updateFilesUploadProgress\",\n    value: function _updateFilesUploadProgress(files, xhr, e) {\n      var progress = void 0;\n      if (typeof e !== 'undefined') {\n        progress = 100 * e.loaded / e.total;\n\n        if (files[0].upload.chunked) {\n          var file = files[0];\n          // Since this is a chunked upload, we need to update the appropriate chunk progress.\n          var chunk = this._getChunk(file, xhr);\n          chunk.progress = progress;\n          chunk.total = e.total;\n          chunk.bytesSent = e.loaded;\n          var fileProgress = 0,\n              fileTotal = void 0,\n              fileBytesSent = void 0;\n          file.upload.progress = 0;\n          file.upload.total = 0;\n          file.upload.bytesSent = 0;\n          for (var i = 0; i < file.upload.totalChunkCount; i++) {\n            if (file.upload.chunks[i] !== undefined && file.upload.chunks[i].progress !== undefined) {\n              file.upload.progress += file.upload.chunks[i].progress;\n              file.upload.total += file.upload.chunks[i].total;\n              file.upload.bytesSent += file.upload.chunks[i].bytesSent;\n            }\n          }\n          file.upload.progress = file.upload.progress / file.upload.totalChunkCount;\n        } else {\n          for (var _iterator26 = files, _isArray26 = true, _i28 = 0, _iterator26 = _isArray26 ? _iterator26 : _iterator26[Symbol.iterator]();;) {\n            var _ref25;\n\n            if (_isArray26) {\n              if (_i28 >= _iterator26.length) break;\n              _ref25 = _iterator26[_i28++];\n            } else {\n              _i28 = _iterator26.next();\n              if (_i28.done) break;\n              _ref25 = _i28.value;\n            }\n\n            var _file2 = _ref25;\n\n            _file2.upload.progress = progress;\n            _file2.upload.total = e.total;\n            _file2.upload.bytesSent = e.loaded;\n          }\n        }\n        for (var _iterator27 = files, _isArray27 = true, _i29 = 0, _iterator27 = _isArray27 ? _iterator27 : _iterator27[Symbol.iterator]();;) {\n          var _ref26;\n\n          if (_isArray27) {\n            if (_i29 >= _iterator27.length) break;\n            _ref26 = _iterator27[_i29++];\n          } else {\n            _i29 = _iterator27.next();\n            if (_i29.done) break;\n            _ref26 = _i29.value;\n          }\n\n          var _file3 = _ref26;\n\n          this.emit(\"uploadprogress\", _file3, _file3.upload.progress, _file3.upload.bytesSent);\n        }\n      } else {\n        // Called when the file finished uploading\n\n        var allFilesFinished = true;\n\n        progress = 100;\n\n        for (var _iterator28 = files, _isArray28 = true, _i30 = 0, _iterator28 = _isArray28 ? _iterator28 : _iterator28[Symbol.iterator]();;) {\n          var _ref27;\n\n          if (_isArray28) {\n            if (_i30 >= _iterator28.length) break;\n            _ref27 = _iterator28[_i30++];\n          } else {\n            _i30 = _iterator28.next();\n            if (_i30.done) break;\n            _ref27 = _i30.value;\n          }\n\n          var _file4 = _ref27;\n\n          if (_file4.upload.progress !== 100 || _file4.upload.bytesSent !== _file4.upload.total) {\n            allFilesFinished = false;\n          }\n          _file4.upload.progress = progress;\n          _file4.upload.bytesSent = _file4.upload.total;\n        }\n\n        // Nothing to do, all files already at 100%\n        if (allFilesFinished) {\n          return;\n        }\n\n        for (var _iterator29 = files, _isArray29 = true, _i31 = 0, _iterator29 = _isArray29 ? _iterator29 : _iterator29[Symbol.iterator]();;) {\n          var _ref28;\n\n          if (_isArray29) {\n            if (_i31 >= _iterator29.length) break;\n            _ref28 = _iterator29[_i31++];\n          } else {\n            _i31 = _iterator29.next();\n            if (_i31.done) break;\n            _ref28 = _i31.value;\n          }\n\n          var _file5 = _ref28;\n\n          this.emit(\"uploadprogress\", _file5, progress, _file5.upload.bytesSent);\n        }\n      }\n    }\n  }, {\n    key: \"_finishedUploading\",\n    value: function _finishedUploading(files, xhr, e) {\n      var response = void 0;\n\n      if (files[0].status === Dropzone.CANCELED) {\n        return;\n      }\n\n      if (xhr.readyState !== 4) {\n        return;\n      }\n\n      if (xhr.responseType !== 'arraybuffer' && xhr.responseType !== 'blob') {\n        response = xhr.responseText;\n\n        if (xhr.getResponseHeader(\"content-type\") && ~xhr.getResponseHeader(\"content-type\").indexOf(\"application/json\")) {\n          try {\n            response = JSON.parse(response);\n          } catch (error) {\n            e = error;\n            response = \"Invalid JSON response from server.\";\n          }\n        }\n      }\n\n      this._updateFilesUploadProgress(files);\n\n      if (!(200 <= xhr.status && xhr.status < 300)) {\n        this._handleUploadError(files, xhr, response);\n      } else {\n        if (files[0].upload.chunked) {\n          files[0].upload.finishedChunkUpload(this._getChunk(files[0], xhr));\n        } else {\n          this._finished(files, response, e);\n        }\n      }\n    }\n  }, {\n    key: \"_handleUploadError\",\n    value: function _handleUploadError(files, xhr, response) {\n      if (files[0].status === Dropzone.CANCELED) {\n        return;\n      }\n\n      if (files[0].upload.chunked && this.options.retryChunks) {\n        var chunk = this._getChunk(files[0], xhr);\n        if (chunk.retries++ < this.options.retryChunksLimit) {\n          this._uploadData(files, [chunk.dataBlock]);\n          return;\n        } else {\n          console.warn('Retried this chunk too often. Giving up.');\n        }\n      }\n\n      for (var _iterator30 = files, _isArray30 = true, _i32 = 0, _iterator30 = _isArray30 ? _iterator30 : _iterator30[Symbol.iterator]();;) {\n        var _ref29;\n\n        if (_isArray30) {\n          if (_i32 >= _iterator30.length) break;\n          _ref29 = _iterator30[_i32++];\n        } else {\n          _i32 = _iterator30.next();\n          if (_i32.done) break;\n          _ref29 = _i32.value;\n        }\n\n        var file = _ref29;\n\n        this._errorProcessing(files, response || this.options.dictResponseError.replace(\"{{statusCode}}\", xhr.status), xhr);\n      }\n    }\n  }, {\n    key: \"submitRequest\",\n    value: function submitRequest(xhr, formData, files) {\n      xhr.send(formData);\n    }\n\n    // Called internally when processing is finished.\n    // Individual callbacks have to be called in the appropriate sections.\n\n  }, {\n    key: \"_finished\",\n    value: function _finished(files, responseText, e) {\n      for (var _iterator31 = files, _isArray31 = true, _i33 = 0, _iterator31 = _isArray31 ? _iterator31 : _iterator31[Symbol.iterator]();;) {\n        var _ref30;\n\n        if (_isArray31) {\n          if (_i33 >= _iterator31.length) break;\n          _ref30 = _iterator31[_i33++];\n        } else {\n          _i33 = _iterator31.next();\n          if (_i33.done) break;\n          _ref30 = _i33.value;\n        }\n\n        var file = _ref30;\n\n        file.status = Dropzone.SUCCESS;\n        this.emit(\"success\", file, responseText, e);\n        this.emit(\"complete\", file);\n      }\n      if (this.options.uploadMultiple) {\n        this.emit(\"successmultiple\", files, responseText, e);\n        this.emit(\"completemultiple\", files);\n      }\n\n      if (this.options.autoProcessQueue) {\n        return this.processQueue();\n      }\n    }\n\n    // Called internally when processing is finished.\n    // Individual callbacks have to be called in the appropriate sections.\n\n  }, {\n    key: \"_errorProcessing\",\n    value: function _errorProcessing(files, message, xhr) {\n      for (var _iterator32 = files, _isArray32 = true, _i34 = 0, _iterator32 = _isArray32 ? _iterator32 : _iterator32[Symbol.iterator]();;) {\n        var _ref31;\n\n        if (_isArray32) {\n          if (_i34 >= _iterator32.length) break;\n          _ref31 = _iterator32[_i34++];\n        } else {\n          _i34 = _iterator32.next();\n          if (_i34.done) break;\n          _ref31 = _i34.value;\n        }\n\n        var file = _ref31;\n\n        file.status = Dropzone.ERROR;\n        this.emit(\"error\", file, message, xhr);\n        this.emit(\"complete\", file);\n      }\n      if (this.options.uploadMultiple) {\n        this.emit(\"errormultiple\", files, message, xhr);\n        this.emit(\"completemultiple\", files);\n      }\n\n      if (this.options.autoProcessQueue) {\n        return this.processQueue();\n      }\n    }\n  }], [{\n    key: \"uuidv4\",\n    value: function uuidv4() {\n      return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {\n        var r = Math.random() * 16 | 0,\n            v = c === 'x' ? r : r & 0x3 | 0x8;\n        return v.toString(16);\n      });\n    }\n  }]);\n\n  return Dropzone;\n}(Emitter);\n\nDropzone.initClass();\n\nDropzone.version = \"5.4.0\";\n\n// This is a map of options for your different dropzones. Add configurations\n// to this object for your different dropzone elemens.\n//\n// Example:\n//\n//     Dropzone.options.myDropzoneElementId = { maxFilesize: 1 };\n//\n// To disable autoDiscover for a specific element, you can set `false` as an option:\n//\n//     Dropzone.options.myDisabledElementId = false;\n//\n// And in html:\n//\n//     <form action=\"/upload\" id=\"my-dropzone-element-id\" class=\"dropzone\"></form>\nDropzone.options = {};\n\n// Returns the options for an element or undefined if none available.\nDropzone.optionsForElement = function (element) {\n  // Get the `Dropzone.options.elementId` for this element if it exists\n  if (element.getAttribute(\"id\")) {\n    return Dropzone.options[camelize(element.getAttribute(\"id\"))];\n  } else {\n    return undefined;\n  }\n};\n\n// Holds a list of all dropzone instances\nDropzone.instances = [];\n\n// Returns the dropzone for given element if any\nDropzone.forElement = function (element) {\n  if (typeof element === \"string\") {\n    element = document.querySelector(element);\n  }\n  if ((element != null ? element.dropzone : undefined) == null) {\n    throw new Error(\"No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.\");\n  }\n  return element.dropzone;\n};\n\n// Set to false if you don't want Dropzone to automatically find and attach to .dropzone elements.\nDropzone.autoDiscover = true;\n\n// Looks for all .dropzone elements and creates a dropzone for them\nDropzone.discover = function () {\n  var dropzones = void 0;\n  if (document.querySelectorAll) {\n    dropzones = document.querySelectorAll(\".dropzone\");\n  } else {\n    dropzones = [];\n    // IE :(\n    var checkElements = function checkElements(elements) {\n      return function () {\n        var result = [];\n        for (var _iterator33 = elements, _isArray33 = true, _i35 = 0, _iterator33 = _isArray33 ? _iterator33 : _iterator33[Symbol.iterator]();;) {\n          var _ref32;\n\n          if (_isArray33) {\n            if (_i35 >= _iterator33.length) break;\n            _ref32 = _iterator33[_i35++];\n          } else {\n            _i35 = _iterator33.next();\n            if (_i35.done) break;\n            _ref32 = _i35.value;\n          }\n\n          var el = _ref32;\n\n          if (/(^| )dropzone($| )/.test(el.className)) {\n            result.push(dropzones.push(el));\n          } else {\n            result.push(undefined);\n          }\n        }\n        return result;\n      }();\n    };\n    checkElements(document.getElementsByTagName(\"div\"));\n    checkElements(document.getElementsByTagName(\"form\"));\n  }\n\n  return function () {\n    var result = [];\n    for (var _iterator34 = dropzones, _isArray34 = true, _i36 = 0, _iterator34 = _isArray34 ? _iterator34 : _iterator34[Symbol.iterator]();;) {\n      var _ref33;\n\n      if (_isArray34) {\n        if (_i36 >= _iterator34.length) break;\n        _ref33 = _iterator34[_i36++];\n      } else {\n        _i36 = _iterator34.next();\n        if (_i36.done) break;\n        _ref33 = _i36.value;\n      }\n\n      var dropzone = _ref33;\n\n      // Create a dropzone unless auto discover has been disabled for specific element\n      if (Dropzone.optionsForElement(dropzone) !== false) {\n        result.push(new Dropzone(dropzone));\n      } else {\n        result.push(undefined);\n      }\n    }\n    return result;\n  }();\n};\n\n// Since the whole Drag'n'Drop API is pretty new, some browsers implement it,\n// but not correctly.\n// So I created a blacklist of userAgents. Yes, yes. Browser sniffing, I know.\n// But what to do when browsers *theoretically* support an API, but crash\n// when using it.\n//\n// This is a list of regular expressions tested against navigator.userAgent\n//\n// ** It should only be used on browser that *do* support the API, but\n// incorrectly **\n//\nDropzone.blacklistedBrowsers = [\n// The mac os and windows phone version of opera 12 seems to have a problem with the File drag'n'drop API.\n/opera.*(Macintosh|Windows Phone).*version\\/12/i];\n\n// Checks if the browser is supported\nDropzone.isBrowserSupported = function () {\n  var capableBrowser = true;\n\n  if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {\n    if (!(\"classList\" in document.createElement(\"a\"))) {\n      capableBrowser = false;\n    } else {\n      // The browser supports the API, but may be blacklisted.\n      for (var _iterator35 = Dropzone.blacklistedBrowsers, _isArray35 = true, _i37 = 0, _iterator35 = _isArray35 ? _iterator35 : _iterator35[Symbol.iterator]();;) {\n        var _ref34;\n\n        if (_isArray35) {\n          if (_i37 >= _iterator35.length) break;\n          _ref34 = _iterator35[_i37++];\n        } else {\n          _i37 = _iterator35.next();\n          if (_i37.done) break;\n          _ref34 = _i37.value;\n        }\n\n        var regex = _ref34;\n\n        if (regex.test(navigator.userAgent)) {\n          capableBrowser = false;\n          continue;\n        }\n      }\n    }\n  } else {\n    capableBrowser = false;\n  }\n\n  return capableBrowser;\n};\n\nDropzone.dataURItoBlob = function (dataURI) {\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, end = byteString.length, asc = 0 <= end; asc ? i <= end : i >= end; asc ? i++ : i--) {\n    ia[i] = byteString.charCodeAt(i);\n  }\n\n  // write the ArrayBuffer to a blob\n  return new Blob([ab], { type: mimeString });\n};\n\n// Returns an array without the rejected item\nvar without = function without(list, rejectedItem) {\n  return list.filter(function (item) {\n    return item !== rejectedItem;\n  }).map(function (item) {\n    return item;\n  });\n};\n\n// abc-def_ghi -> abcDefGhi\nvar camelize = function camelize(str) {\n  return str.replace(/[\\-_](\\w)/g, function (match) {\n    return match.charAt(1).toUpperCase();\n  });\n};\n\n// Creates an element from string\nDropzone.createElement = function (string) {\n  var div = document.createElement(\"div\");\n  div.innerHTML = string;\n  return div.childNodes[0];\n};\n\n// Tests if given element is inside (or simply is) the container\nDropzone.elementInside = function (element, container) {\n  if (element === container) {\n    return true;\n  } // Coffeescript doesn't support do/while loops\n  while (element = element.parentNode) {\n    if (element === container) {\n      return true;\n    }\n  }\n  return false;\n};\n\nDropzone.getElement = function (el, name) {\n  var element = void 0;\n  if (typeof el === \"string\") {\n    element = document.querySelector(el);\n  } else if (el.nodeType != null) {\n    element = el;\n  }\n  if (element == null) {\n    throw new Error(\"Invalid `\" + name + \"` option provided. Please provide a CSS selector or a plain HTML element.\");\n  }\n  return element;\n};\n\nDropzone.getElements = function (els, name) {\n  var el = void 0,\n      elements = void 0;\n  if (els instanceof Array) {\n    elements = [];\n    try {\n      for (var _iterator36 = els, _isArray36 = true, _i38 = 0, _iterator36 = _isArray36 ? _iterator36 : _iterator36[Symbol.iterator]();;) {\n        if (_isArray36) {\n          if (_i38 >= _iterator36.length) break;\n          el = _iterator36[_i38++];\n        } else {\n          _i38 = _iterator36.next();\n          if (_i38.done) break;\n          el = _i38.value;\n        }\n\n        elements.push(this.getElement(el, name));\n      }\n    } catch (e) {\n      elements = null;\n    }\n  } else if (typeof els === \"string\") {\n    elements = [];\n    for (var _iterator37 = document.querySelectorAll(els), _isArray37 = true, _i39 = 0, _iterator37 = _isArray37 ? _iterator37 : _iterator37[Symbol.iterator]();;) {\n      if (_isArray37) {\n        if (_i39 >= _iterator37.length) break;\n        el = _iterator37[_i39++];\n      } else {\n        _i39 = _iterator37.next();\n        if (_i39.done) break;\n        el = _i39.value;\n      }\n\n      elements.push(el);\n    }\n  } else if (els.nodeType != null) {\n    elements = [els];\n  }\n\n  if (elements == null || !elements.length) {\n    throw new Error(\"Invalid `\" + name + \"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.\");\n  }\n\n  return elements;\n};\n\n// Asks the user the question and calls accepted or rejected accordingly\n//\n// The default implementation just uses `window.confirm` and then calls the\n// appropriate callback.\nDropzone.confirm = function (question, accepted, rejected) {\n  if (window.confirm(question)) {\n    return accepted();\n  } else if (rejected != null) {\n    return rejected();\n  }\n};\n\n// Validates the mime type like this:\n//\n// https://developer.mozilla.org/en-US/docs/HTML/Element/input#attr-accept\nDropzone.isValidFile = function (file, acceptedFiles) {\n  if (!acceptedFiles) {\n    return true;\n  } // If there are no accepted mime types, it's OK\n  acceptedFiles = acceptedFiles.split(\",\");\n\n  var mimeType = file.type;\n  var baseMimeType = mimeType.replace(/\\/.*$/, \"\");\n\n  for (var _iterator38 = acceptedFiles, _isArray38 = true, _i40 = 0, _iterator38 = _isArray38 ? _iterator38 : _iterator38[Symbol.iterator]();;) {\n    var _ref35;\n\n    if (_isArray38) {\n      if (_i40 >= _iterator38.length) break;\n      _ref35 = _iterator38[_i40++];\n    } else {\n      _i40 = _iterator38.next();\n      if (_i40.done) break;\n      _ref35 = _i40.value;\n    }\n\n    var validType = _ref35;\n\n    validType = validType.trim();\n    if (validType.charAt(0) === \".\") {\n      if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {\n        return true;\n      }\n    } else if (/\\/\\*$/.test(validType)) {\n      // This is something like a image/* mime type\n      if (baseMimeType === validType.replace(/\\/.*$/, \"\")) {\n        return true;\n      }\n    } else {\n      if (mimeType === validType) {\n        return true;\n      }\n    }\n  }\n\n  return false;\n};\n\n// Augment jQuery\nif (typeof jQuery !== 'undefined' && jQuery !== null) {\n  jQuery.fn.dropzone = function (options) {\n    return this.each(function () {\n      return new Dropzone(this, options);\n    });\n  };\n}\n\nif (typeof module !== 'undefined' && module !== null) {\n  module.exports = Dropzone;\n} else {\n  window.Dropzone = Dropzone;\n}\n\n// Dropzone file status codes\nDropzone.ADDED = \"added\";\n\nDropzone.QUEUED = \"queued\";\n// For backwards compatibility. Now, if a file is accepted, it's either queued\n// or uploading.\nDropzone.ACCEPTED = Dropzone.QUEUED;\n\nDropzone.UPLOADING = \"uploading\";\nDropzone.PROCESSING = Dropzone.UPLOADING; // alias\n\nDropzone.CANCELED = \"canceled\";\nDropzone.ERROR = \"error\";\nDropzone.SUCCESS = \"success\";\n\n/*\n\n Bugfix for iOS 6 and 7\n Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios\n based on the work of https://github.com/stomita/ios-imagefile-megapixel\n\n */\n\n// Detecting vertical squash in loaded image.\n// Fixes a bug which squash image vertically while drawing into canvas for some images.\n// This is a bug in iOS6 devices. This function from https://github.com/stomita/ios-imagefile-megapixel\nvar detectVerticalSquash = function detectVerticalSquash(img) {\n  var iw = img.naturalWidth;\n  var ih = img.naturalHeight;\n  var canvas = document.createElement(\"canvas\");\n  canvas.width = 1;\n  canvas.height = ih;\n  var ctx = canvas.getContext(\"2d\");\n  ctx.drawImage(img, 0, 0);\n\n  var _ctx$getImageData = ctx.getImageData(1, 0, 1, ih),\n      data = _ctx$getImageData.data;\n\n  // search image edge pixel position in case it is squashed vertically.\n\n\n  var sy = 0;\n  var ey = ih;\n  var py = ih;\n  while (py > sy) {\n    var alpha = data[(py - 1) * 4 + 3];\n\n    if (alpha === 0) {\n      ey = py;\n    } else {\n      sy = py;\n    }\n\n    py = ey + sy >> 1;\n  }\n  var ratio = py / ih;\n\n  if (ratio === 0) {\n    return 1;\n  } else {\n    return ratio;\n  }\n};\n\n// A replacement for context.drawImage\n// (args are for source and destination).\nvar drawImageIOSFix = function drawImageIOSFix(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {\n  var vertSquashRatio = detectVerticalSquash(img);\n  return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);\n};\n\n// Based on MinifyJpeg\n// Source: http://www.perry.cz/files/ExifRestorer.js\n// http://elicon.blog57.fc2.com/blog-entry-206.html\n\nvar ExifRestore = function () {\n  function ExifRestore() {\n    _classCallCheck(this, ExifRestore);\n  }\n\n  _createClass(ExifRestore, null, [{\n    key: \"initClass\",\n    value: function initClass() {\n      this.KEY_STR = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';\n    }\n  }, {\n    key: \"encode64\",\n    value: function encode64(input) {\n      var output = '';\n      var chr1 = undefined;\n      var chr2 = undefined;\n      var chr3 = '';\n      var enc1 = undefined;\n      var enc2 = undefined;\n      var enc3 = undefined;\n      var enc4 = '';\n      var i = 0;\n      while (true) {\n        chr1 = input[i++];\n        chr2 = input[i++];\n        chr3 = input[i++];\n        enc1 = chr1 >> 2;\n        enc2 = (chr1 & 3) << 4 | chr2 >> 4;\n        enc3 = (chr2 & 15) << 2 | chr3 >> 6;\n        enc4 = chr3 & 63;\n        if (isNaN(chr2)) {\n          enc3 = enc4 = 64;\n        } else if (isNaN(chr3)) {\n          enc4 = 64;\n        }\n        output = output + this.KEY_STR.charAt(enc1) + this.KEY_STR.charAt(enc2) + this.KEY_STR.charAt(enc3) + this.KEY_STR.charAt(enc4);\n        chr1 = chr2 = chr3 = '';\n        enc1 = enc2 = enc3 = enc4 = '';\n        if (!(i < input.length)) {\n          break;\n        }\n      }\n      return output;\n    }\n  }, {\n    key: \"restore\",\n    value: function restore(origFileBase64, resizedFileBase64) {\n      if (!origFileBase64.match('data:image/jpeg;base64,')) {\n        return resizedFileBase64;\n      }\n      var rawImage = this.decode64(origFileBase64.replace('data:image/jpeg;base64,', ''));\n      var segments = this.slice2Segments(rawImage);\n      var image = this.exifManipulation(resizedFileBase64, segments);\n      return \"data:image/jpeg;base64,\" + this.encode64(image);\n    }\n  }, {\n    key: \"exifManipulation\",\n    value: function exifManipulation(resizedFileBase64, segments) {\n      var exifArray = this.getExifArray(segments);\n      var newImageArray = this.insertExif(resizedFileBase64, exifArray);\n      var aBuffer = new Uint8Array(newImageArray);\n      return aBuffer;\n    }\n  }, {\n    key: \"getExifArray\",\n    value: function getExifArray(segments) {\n      var seg = undefined;\n      var x = 0;\n      while (x < segments.length) {\n        seg = segments[x];\n        if (seg[0] === 255 & seg[1] === 225) {\n          return seg;\n        }\n        x++;\n      }\n      return [];\n    }\n  }, {\n    key: \"insertExif\",\n    value: function insertExif(resizedFileBase64, exifArray) {\n      var imageData = resizedFileBase64.replace('data:image/jpeg;base64,', '');\n      var buf = this.decode64(imageData);\n      var separatePoint = buf.indexOf(255, 3);\n      var mae = buf.slice(0, separatePoint);\n      var ato = buf.slice(separatePoint);\n      var array = mae;\n      array = array.concat(exifArray);\n      array = array.concat(ato);\n      return array;\n    }\n  }, {\n    key: \"slice2Segments\",\n    value: function slice2Segments(rawImageArray) {\n      var head = 0;\n      var segments = [];\n      while (true) {\n        var length;\n        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 218) {\n          break;\n        }\n        if (rawImageArray[head] === 255 & rawImageArray[head + 1] === 216) {\n          head += 2;\n        } else {\n          length = rawImageArray[head + 2] * 256 + rawImageArray[head + 3];\n          var endPoint = head + length + 2;\n          var seg = rawImageArray.slice(head, endPoint);\n          segments.push(seg);\n          head = endPoint;\n        }\n        if (head > rawImageArray.length) {\n          break;\n        }\n      }\n      return segments;\n    }\n  }, {\n    key: \"decode64\",\n    value: function decode64(input) {\n      var output = '';\n      var chr1 = undefined;\n      var chr2 = undefined;\n      var chr3 = '';\n      var enc1 = undefined;\n      var enc2 = undefined;\n      var enc3 = undefined;\n      var enc4 = '';\n      var i = 0;\n      var buf = [];\n      // remove all characters that are not A-Z, a-z, 0-9, +, /, or =\n      var base64test = /[^A-Za-z0-9\\+\\/\\=]/g;\n      if (base64test.exec(input)) {\n        console.warn('There were invalid base64 characters in the input text.\\nValid base64 characters are A-Z, a-z, 0-9, \\'+\\', \\'/\\',and \\'=\\'\\nExpect errors in decoding.');\n      }\n      input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, '');\n      while (true) {\n        enc1 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc2 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc3 = this.KEY_STR.indexOf(input.charAt(i++));\n        enc4 = this.KEY_STR.indexOf(input.charAt(i++));\n        chr1 = enc1 << 2 | enc2 >> 4;\n        chr2 = (enc2 & 15) << 4 | enc3 >> 2;\n        chr3 = (enc3 & 3) << 6 | enc4;\n        buf.push(chr1);\n        if (enc3 !== 64) {\n          buf.push(chr2);\n        }\n        if (enc4 !== 64) {\n          buf.push(chr3);\n        }\n        chr1 = chr2 = chr3 = '';\n        enc1 = enc2 = enc3 = enc4 = '';\n        if (!(i < input.length)) {\n          break;\n        }\n      }\n      return buf;\n    }\n  }]);\n\n  return ExifRestore;\n}();\n\nExifRestore.initClass();\n\n/*\n * contentloaded.js\n *\n * Author: Diego Perini (diego.perini at gmail.com)\n * Summary: cross-browser wrapper for DOMContentLoaded\n * Updated: 20101020\n * License: MIT\n * Version: 1.2\n *\n * URL:\n * http://javascript.nwbox.com/ContentLoaded/\n * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE\n */\n\n// @win window reference\n// @fn function reference\nvar contentLoaded = function contentLoaded(win, fn) {\n  var done = false;\n  var top = true;\n  var doc = win.document;\n  var root = doc.documentElement;\n  var add = doc.addEventListener ? \"addEventListener\" : \"attachEvent\";\n  var rem = doc.addEventListener ? \"removeEventListener\" : \"detachEvent\";\n  var pre = doc.addEventListener ? \"\" : \"on\";\n  var init = function init(e) {\n    if (e.type === \"readystatechange\" && doc.readyState !== \"complete\") {\n      return;\n    }\n    (e.type === \"load\" ? win : doc)[rem](pre + e.type, init, false);\n    if (!done && (done = true)) {\n      return fn.call(win, e.type || e);\n    }\n  };\n\n  var poll = function poll() {\n    try {\n      root.doScroll(\"left\");\n    } catch (e) {\n      setTimeout(poll, 50);\n      return;\n    }\n    return init(\"poll\");\n  };\n\n  if (doc.readyState !== \"complete\") {\n    if (doc.createEventObject && root.doScroll) {\n      try {\n        top = !win.frameElement;\n      } catch (error) {}\n      if (top) {\n        poll();\n      }\n    }\n    doc[add](pre + \"DOMContentLoaded\", init, false);\n    doc[add](pre + \"readystatechange\", init, false);\n    return win[add](pre + \"load\", init, false);\n  }\n};\n\n// As a single function to be able to write tests.\nDropzone._autoDiscoverFunction = function () {\n  if (Dropzone.autoDiscover) {\n    return Dropzone.discover();\n  }\n};\ncontentLoaded(window, Dropzone._autoDiscoverFunction);\n\nfunction __guard__(value, transform) {\n  return typeof value !== 'undefined' && value !== null ? transform(value) : undefined;\n}\nfunction __guardMethod__(obj, methodName, transform) {\n  if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') {\n    return transform(obj, methodName);\n  } else {\n    return undefined;\n  }\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/dropzone/readme.md",
    "content": "# Warning!\n\nYou shouldn't pull these files from the github master branch directly!\n\nThey might be outdated or not working at all since I normally only push them\nwhen I create a version release.\n\nTo be sure to get a proper release, please go to the\n[dropzone releases section on github](https://github.com/enyo/dropzone/releases/latest).\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/all.css",
    "content": "/* iCheck plugin skins\n----------------------------------- */\n@import url(\"minimal/_all.css\");\n/*\n@import url(\"minimal/minimal.css\");\n@import url(\"minimal/red.css\");\n@import url(\"minimal/green.css\");\n@import url(\"minimal/blue.css\");\n@import url(\"minimal/aero.css\");\n@import url(\"minimal/grey.css\");\n@import url(\"minimal/orange.css\");\n@import url(\"minimal/yellow.css\");\n@import url(\"minimal/pink.css\");\n@import url(\"minimal/purple.css\");\n*/\n\n@import url(\"square/_all.css\");\n/*\n@import url(\"square/square.css\");\n@import url(\"square/red.css\");\n@import url(\"square/green.css\");\n@import url(\"square/blue.css\");\n@import url(\"square/aero.css\");\n@import url(\"square/grey.css\");\n@import url(\"square/orange.css\");\n@import url(\"square/yellow.css\");\n@import url(\"square/pink.css\");\n@import url(\"square/purple.css\");\n*/\n\n@import url(\"flat/_all.css\");\n/*\n@import url(\"flat/flat.css\");\n@import url(\"flat/red.css\");\n@import url(\"flat/green.css\");\n@import url(\"flat/blue.css\");\n@import url(\"flat/aero.css\");\n@import url(\"flat/grey.css\");\n@import url(\"flat/orange.css\");\n@import url(\"flat/yellow.css\");\n@import url(\"flat/pink.css\");\n@import url(\"flat/purple.css\");\n*/\n\n@import url(\"line/_all.css\");\n/*\n@import url(\"line/line.css\");\n@import url(\"line/red.css\");\n@import url(\"line/green.css\");\n@import url(\"line/blue.css\");\n@import url(\"line/aero.css\");\n@import url(\"line/grey.css\");\n@import url(\"line/orange.css\");\n@import url(\"line/yellow.css\");\n@import url(\"line/pink.css\");\n@import url(\"line/purple.css\");\n*/\n\n@import url(\"polaris/polaris.css\");\n\n@import url(\"futurico/futurico.css\");"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/_all.css",
    "content": "/* iCheck plugin Flat skin\n----------------------------------- */\n.icheckbox_flat,\n.iradio_flat {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(flat.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat {\n    background-position: 0 0;\n}\n    .icheckbox_flat.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat {\n    background-position: -88px 0;\n}\n    .iradio_flat.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat,\n    .iradio_flat {\n        background-image: url(flat@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* red */\n.icheckbox_flat-red,\n.iradio_flat-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-red {\n    background-position: 0 0;\n}\n    .icheckbox_flat-red.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-red.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-red.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-red {\n    background-position: -88px 0;\n}\n    .iradio_flat-red.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-red.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-red.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-red,\n    .iradio_flat-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* green */\n.icheckbox_flat-green,\n.iradio_flat-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-green {\n    background-position: 0 0;\n}\n    .icheckbox_flat-green.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-green.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-green.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-green {\n    background-position: -88px 0;\n}\n    .iradio_flat-green.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-green.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-green.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-green,\n    .iradio_flat-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* blue */\n.icheckbox_flat-blue,\n.iradio_flat-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-blue {\n    background-position: 0 0;\n}\n    .icheckbox_flat-blue.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-blue.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-blue.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-blue {\n    background-position: -88px 0;\n}\n    .iradio_flat-blue.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-blue.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-blue.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-blue,\n    .iradio_flat-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* aero */\n.icheckbox_flat-aero,\n.iradio_flat-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-aero {\n    background-position: 0 0;\n}\n    .icheckbox_flat-aero.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-aero.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-aero.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-aero {\n    background-position: -88px 0;\n}\n    .iradio_flat-aero.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-aero.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-aero.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-aero,\n    .iradio_flat-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* grey */\n.icheckbox_flat-grey,\n.iradio_flat-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-grey {\n    background-position: 0 0;\n}\n    .icheckbox_flat-grey.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-grey.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-grey.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-grey {\n    background-position: -88px 0;\n}\n    .iradio_flat-grey.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-grey.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-grey.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-grey,\n    .iradio_flat-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* orange */\n.icheckbox_flat-orange,\n.iradio_flat-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-orange {\n    background-position: 0 0;\n}\n    .icheckbox_flat-orange.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-orange.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-orange.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-orange {\n    background-position: -88px 0;\n}\n    .iradio_flat-orange.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-orange.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-orange.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-orange,\n    .iradio_flat-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* yellow */\n.icheckbox_flat-yellow,\n.iradio_flat-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_flat-yellow.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-yellow.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-yellow.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-yellow {\n    background-position: -88px 0;\n}\n    .iradio_flat-yellow.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-yellow.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-yellow.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-yellow,\n    .iradio_flat-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* pink */\n.icheckbox_flat-pink,\n.iradio_flat-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-pink {\n    background-position: 0 0;\n}\n    .icheckbox_flat-pink.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-pink.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-pink.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-pink {\n    background-position: -88px 0;\n}\n    .iradio_flat-pink.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-pink.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-pink.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-pink,\n    .iradio_flat-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* purple */\n.icheckbox_flat-purple,\n.iradio_flat-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-purple {\n    background-position: 0 0;\n}\n    .icheckbox_flat-purple.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-purple.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-purple.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-purple {\n    background-position: -88px 0;\n}\n    .iradio_flat-purple.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-purple.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-purple.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-purple,\n    .iradio_flat-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/aero.css",
    "content": "/* iCheck plugin Flat skin, aero\n----------------------------------- */\n.icheckbox_flat-aero,\n.iradio_flat-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-aero {\n    background-position: 0 0;\n}\n    .icheckbox_flat-aero.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-aero.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-aero.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-aero {\n    background-position: -88px 0;\n}\n    .iradio_flat-aero.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-aero.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-aero.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-aero,\n    .iradio_flat-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/blue.css",
    "content": "/* iCheck plugin Flat skin, blue\n----------------------------------- */\n.icheckbox_flat-blue,\n.iradio_flat-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-blue {\n    background-position: 0 0;\n}\n    .icheckbox_flat-blue.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-blue.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-blue.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-blue {\n    background-position: -88px 0;\n}\n    .iradio_flat-blue.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-blue.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-blue.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-blue,\n    .iradio_flat-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/flat.css",
    "content": "/* iCheck plugin flat skin, black\n----------------------------------- */\n.icheckbox_flat,\n.iradio_flat {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(flat.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat {\n    background-position: 0 0;\n}\n    .icheckbox_flat.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat {\n    background-position: -88px 0;\n}\n    .iradio_flat.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat,\n    .iradio_flat {\n        background-image: url(flat@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/green.css",
    "content": "/* iCheck plugin Flat skin, green\n----------------------------------- */\n.icheckbox_flat-green,\n.iradio_flat-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-green {\n    background-position: 0 0;\n}\n    .icheckbox_flat-green.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-green.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-green.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-green {\n    background-position: -88px 0;\n}\n    .iradio_flat-green.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-green.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-green.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-green,\n    .iradio_flat-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/grey.css",
    "content": "/* iCheck plugin Flat skin, grey\n----------------------------------- */\n.icheckbox_flat-grey,\n.iradio_flat-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-grey {\n    background-position: 0 0;\n}\n    .icheckbox_flat-grey.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-grey.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-grey.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-grey {\n    background-position: -88px 0;\n}\n    .iradio_flat-grey.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-grey.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-grey.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-grey,\n    .iradio_flat-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/orange.css",
    "content": "/* iCheck plugin Flat skin, orange\n----------------------------------- */\n.icheckbox_flat-orange,\n.iradio_flat-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-orange {\n    background-position: 0 0;\n}\n    .icheckbox_flat-orange.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-orange.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-orange.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-orange {\n    background-position: -88px 0;\n}\n    .iradio_flat-orange.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-orange.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-orange.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-orange,\n    .iradio_flat-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/pink.css",
    "content": "/* iCheck plugin Flat skin, pink\n----------------------------------- */\n.icheckbox_flat-pink,\n.iradio_flat-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-pink {\n    background-position: 0 0;\n}\n    .icheckbox_flat-pink.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-pink.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-pink.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-pink {\n    background-position: -88px 0;\n}\n    .iradio_flat-pink.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-pink.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-pink.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-pink,\n    .iradio_flat-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/purple.css",
    "content": "/* iCheck plugin Flat skin, purple\n----------------------------------- */\n.icheckbox_flat-purple,\n.iradio_flat-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-purple {\n    background-position: 0 0;\n}\n    .icheckbox_flat-purple.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-purple.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-purple.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-purple {\n    background-position: -88px 0;\n}\n    .iradio_flat-purple.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-purple.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-purple.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-purple,\n    .iradio_flat-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/red.css",
    "content": "/* iCheck plugin Flat skin, red\n----------------------------------- */\n.icheckbox_flat-red,\n.iradio_flat-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-red {\n    background-position: 0 0;\n}\n    .icheckbox_flat-red.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-red.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-red.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-red {\n    background-position: -88px 0;\n}\n    .iradio_flat-red.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-red.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-red.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-red,\n    .iradio_flat-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/flat/yellow.css",
    "content": "/* iCheck plugin Flat skin, yellow\n----------------------------------- */\n.icheckbox_flat-yellow,\n.iradio_flat-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_flat-yellow.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-yellow.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-yellow.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-yellow {\n    background-position: -88px 0;\n}\n    .iradio_flat-yellow.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-yellow.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-yellow.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-yellow,\n    .iradio_flat-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/futurico/futurico.css",
    "content": "/* iCheck plugin Futurico skin\n----------------------------------- */\n.icheckbox_futurico,\n.iradio_futurico {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 16px;\n    height: 17px;\n    background: url(futurico.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_futurico {\n    background-position: 0 0;\n}\n    .icheckbox_futurico.checked {\n        background-position: -18px 0;\n    }\n    .icheckbox_futurico.disabled {\n        background-position: -36px 0;\n        cursor: default;\n    }\n    .icheckbox_futurico.checked.disabled {\n        background-position: -54px 0;\n    }\n\n.iradio_futurico {\n    background-position: -72px 0;\n}\n    .iradio_futurico.checked {\n        background-position: -90px 0;\n    }\n    .iradio_futurico.disabled {\n        background-position: -108px 0;\n        cursor: default;\n    }\n    .iradio_futurico.checked.disabled {\n        background-position: -126px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_futurico,\n    .iradio_futurico {\n        background-image: url(futurico@2x.png);\n        -webkit-background-size: 144px 19px;\n        background-size: 144px 19px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/icheck.js",
    "content": "/*!\n * iCheck v1.0.1, http://git.io/arlzeA\n * =================================\n * Powerful jQuery and Zepto plugin for checkboxes and radio buttons customization\n *\n * (c) 2013 Damir Sultanov, http://fronteed.com\n * MIT Licensed\n */\n\n(function($) {\n\n  // Cached vars\n  var _iCheck = 'iCheck',\n    _iCheckHelper = _iCheck + '-helper',\n    _checkbox = 'checkbox',\n    _radio = 'radio',\n    _checked = 'checked',\n    _unchecked = 'un' + _checked,\n    _disabled = 'disabled',\n    _determinate = 'determinate',\n    _indeterminate = 'in' + _determinate,\n    _update = 'update',\n    _type = 'type',\n    _click = 'click',\n    _touch = 'touchbegin.i touchend.i',\n    _add = 'addClass',\n    _remove = 'removeClass',\n    _callback = 'trigger',\n    _label = 'label',\n    _cursor = 'cursor',\n    _mobile = /ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent);\n\n  // Plugin init\n  $.fn[_iCheck] = function(options, fire) {\n\n    // Walker\n    var handle = 'input[type=\"' + _checkbox + '\"], input[type=\"' + _radio + '\"]',\n      stack = $(),\n      walker = function(object) {\n        object.each(function() {\n          var self = $(this);\n\n          if (self.is(handle)) {\n            stack = stack.add(self);\n          } else {\n            stack = stack.add(self.find(handle));\n          }\n        });\n      };\n\n    // Check if we should operate with some method\n    if (/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(options)) {\n\n      // Normalize method's name\n      options = options.toLowerCase();\n\n      // Find checkboxes and radio buttons\n      walker(this);\n\n      return stack.each(function() {\n        var self = $(this);\n\n        if (options == 'destroy') {\n          tidy(self, 'ifDestroyed');\n        } else {\n          operate(self, true, options);\n        }\n          // Fire method's callback\n        if ($.isFunction(fire)) {\n          fire();\n        }\n      });\n\n    // Customization\n    } else if (typeof options == 'object' || !options) {\n\n      // Check if any options were passed\n      var settings = $.extend({\n          checkedClass: _checked,\n          disabledClass: _disabled,\n          indeterminateClass: _indeterminate,\n          labelHover: true,\n          aria: false\n        }, options),\n\n        selector = settings.handle,\n        hoverClass = settings.hoverClass || 'hover',\n        focusClass = settings.focusClass || 'focus',\n        activeClass = settings.activeClass || 'active',\n        labelHover = !!settings.labelHover,\n        labelHoverClass = settings.labelHoverClass || 'hover',\n\n        // Setup clickable area\n        area = ('' + settings.increaseArea).replace('%', '') | 0;\n\n      // Selector limit\n      if (selector == _checkbox || selector == _radio) {\n        handle = 'input[type=\"' + selector + '\"]';\n      }\n        // Clickable area limit\n      if (area < -50) {\n        area = -50;\n      }\n        // Walk around the selector\n      walker(this);\n\n      return stack.each(function() {\n        var self = $(this);\n\n        // If already customized\n        tidy(self);\n\n        var node = this,\n          id = node.id,\n\n          // Layer styles\n          offset = -area + '%',\n          size = 100 + (area * 2) + '%',\n          layer = {\n            position: 'absolute',\n            top: offset,\n            left: offset,\n            display: 'block',\n            width: size,\n            height: size,\n            margin: 0,\n            padding: 0,\n            background: '#fff',\n            border: 0,\n            opacity: 0\n          },\n\n          // Choose how to hide input\n          hide = _mobile ? {\n            position: 'absolute',\n            visibility: 'hidden'\n          } : area ? layer : {\n            position: 'absolute',\n            opacity: 0\n          },\n\n          // Get proper class\n          className = node[_type] == _checkbox ? settings.checkboxClass || 'i' + _checkbox : settings.radioClass || 'i' + _radio,\n\n          // Find assigned labels\n          label = $(_label + '[for=\"' + id + '\"]').add(self.closest(_label)),\n\n          // Check ARIA option\n          aria = !!settings.aria,\n\n          // Set ARIA placeholder\n          ariaID = _iCheck + '-' + Math.random().toString(36).replace('0.', ''),\n\n          // Parent & helper\n          parent = '<div class=\"' + className + '\" ' + (aria ? 'role=\"' + node[_type] + '\" ' : ''),\n          helper;\n\n        // Set ARIA \"labelledby\"\n        if (label.length && aria) {\n          label.each(function() {\n            parent += 'aria-labelledby=\"';\n\n            if (this.id) {\n              parent += this.id;\n            } else {\n              this.id = ariaID;\n              parent += ariaID;\n            }\n\n            parent += '\"';\n          });\n        }\n          // Wrap input\n        parent = self.wrap(parent + '/>')[_callback]('ifCreated').parent().append(settings.insert);\n\n        // Layer addition\n        helper = $('<ins class=\"' + _iCheckHelper + '\"/>').css(layer).appendTo(parent);\n\n        // Finalize customization\n        self.data(_iCheck, {o: settings, s: self.attr('style')}).css(hide);\n        !!settings.inheritClass && parent[_add](node.className || '');\n        !!settings.inheritID && id && parent.attr('id', _iCheck + '-' + id);\n        parent.css('position') == 'static' && parent.css('position', 'relative');\n        operate(self, true, _update);\n\n        // Label events\n        if (label.length) {\n          label.on(_click + '.i mouseover.i mouseout.i ' + _touch, function(event) {\n            var type = event[_type],\n              item = $(this);\n\n            // Do nothing if input is disabled\n            if (!node[_disabled]) {\n\n              // Click\n              if (type == _click) {\n                if ($(event.target).is('a')) {\n                  return;\n                }\n                operate(self, false, true);\n\n              // Hover state\n              } else if (labelHover) {\n\n                // mouseout|touchend\n                if (/ut|nd/.test(type)) {\n                  parent[_remove](hoverClass);\n                  item[_remove](labelHoverClass);\n                } else {\n                  parent[_add](hoverClass);\n                  item[_add](labelHoverClass);\n                }\n              }\n                if (_mobile) {\n                event.stopPropagation();\n              } else {\n                return false;\n              }\n            }\n          });\n        }\n          // Input events\n        self.on(_click + '.i focus.i blur.i keyup.i keydown.i keypress.i', function(event) {\n          var type = event[_type],\n            key = event.keyCode;\n\n          // Click\n          if (type == _click) {\n            return false;\n\n          // Keydown\n          } else if (type == 'keydown' && key == 32) {\n            if (!(node[_type] == _radio && node[_checked])) {\n              if (node[_checked]) {\n                off(self, _checked);\n              } else {\n                on(self, _checked);\n              }\n            }\n              return false;\n\n          // Keyup\n          } else if (type == 'keyup' && node[_type] == _radio) {\n            !node[_checked] && on(self, _checked);\n\n          // Focus/blur\n          } else if (/us|ur/.test(type)) {\n            parent[type == 'blur' ? _remove : _add](focusClass);\n          }\n        });\n\n        // Helper events\n        helper.on(_click + ' mousedown mouseup mouseover mouseout ' + _touch, function(event) {\n          var type = event[_type],\n\n            // mousedown|mouseup\n            toggle = /wn|up/.test(type) ? activeClass : hoverClass;\n\n          // Do nothing if input is disabled\n          if (!node[_disabled]) {\n\n            // Click\n            if (type == _click) {\n              operate(self, false, true);\n\n            // Active and hover states\n            } else {\n\n              // State is on\n              if (/wn|er|in/.test(type)) {\n\n                // mousedown|mouseover|touchbegin\n                parent[_add](toggle);\n\n              // State is off\n              } else {\n                parent[_remove](toggle + ' ' + activeClass);\n              }\n                // Label hover\n              if (label.length && labelHover && toggle == hoverClass) {\n\n                // mouseout|touchend\n                label[/ut|nd/.test(type) ? _remove : _add](labelHoverClass);\n              }\n            }\n              if (_mobile) {\n              event.stopPropagation();\n            } else {\n              return false;\n            }\n          }\n        });\n      });\n    } else {\n      return this;\n    }\n  };\n\n  // Do something with inputs\n  function operate(input, direct, method) {\n    var node = input[0],\n      state = /er/.test(method) ? _indeterminate : /bl/.test(method) ? _disabled : _checked,\n      active = method == _update ? {\n        checked: node[_checked],\n        disabled: node[_disabled],\n        indeterminate: input.attr(_indeterminate) == 'true' || input.attr(_determinate) == 'false'\n      } : node[state];\n\n    // Check, disable or indeterminate\n    if (/^(ch|di|in)/.test(method) && !active) {\n      on(input, state);\n\n    // Uncheck, enable or determinate\n    } else if (/^(un|en|de)/.test(method) && active) {\n      off(input, state);\n\n    // Update\n    } else if (method == _update) {\n\n      // Handle states\n      for (var state in active) {\n        if (active[state]) {\n          on(input, state, true);\n        } else {\n          off(input, state, true);\n        }\n      }\n    } else if (!direct || method == 'toggle') {\n\n      // Helper or label was clicked\n      if (!direct) {\n        input[_callback]('ifClicked');\n      }\n        // Toggle checked state\n      if (active) {\n        if (node[_type] !== _radio) {\n          off(input, state);\n        }\n      } else {\n        on(input, state);\n      }\n    }\n  }\n    // Add checked, disabled or indeterminate state\n  function on(input, state, keep) {\n    var node = input[0],\n      parent = input.parent(),\n      checked = state == _checked,\n      indeterminate = state == _indeterminate,\n      disabled = state == _disabled,\n      callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled',\n      regular = option(input, callback + capitalize(node[_type])),\n      specific = option(input, state + capitalize(node[_type]));\n\n    // Prevent unnecessary actions\n    if (node[state] !== true) {\n\n      // Toggle assigned radio buttons\n      if (!keep && state == _checked && node[_type] == _radio && node.name) {\n        var form = input.closest('form'),\n          inputs = 'input[name=\"' + node.name + '\"]';\n\n        inputs = form.length ? form.find(inputs) : $(inputs);\n\n        inputs.each(function() {\n          if (this !== node && $(this).data(_iCheck)) {\n            off($(this), state);\n          }\n        });\n      }\n        // Indeterminate state\n      if (indeterminate) {\n\n        // Add indeterminate state\n        node[state] = true;\n\n        // Remove checked state\n        if (node[_checked]) {\n          off(input, _checked, 'force');\n        }\n          // Checked or disabled state\n      } else {\n\n        // Add checked or disabled state\n        if (!keep) {\n          node[state] = true;\n        }\n          // Remove indeterminate state\n        if (checked && node[_indeterminate]) {\n          off(input, _indeterminate, false);\n        }\n      }\n        // Trigger callbacks\n      callbacks(input, checked, state, keep);\n    }\n      // Add proper cursor\n    if (node[_disabled] && !!option(input, _cursor, true)) {\n      parent.find('.' + _iCheckHelper).css(_cursor, 'default');\n    }\n      // Add state class\n    parent[_add](specific || option(input, state) || '');\n\n    // Set ARIA attribute\n    disabled ? parent.attr('aria-disabled', 'true') : parent.attr('aria-checked', indeterminate ? 'mixed' : 'true');\n\n    // Remove regular state class\n    parent[_remove](regular || option(input, callback) || '');\n  }\n    // Remove checked, disabled or indeterminate state\n  function off(input, state, keep) {\n    var node = input[0],\n      parent = input.parent(),\n      checked = state == _checked,\n      indeterminate = state == _indeterminate,\n      disabled = state == _disabled,\n      callback = indeterminate ? _determinate : checked ? _unchecked : 'enabled',\n      regular = option(input, callback + capitalize(node[_type])),\n      specific = option(input, state + capitalize(node[_type]));\n\n    // Prevent unnecessary actions\n    if (node[state] !== false) {\n\n      // Toggle state\n      if (indeterminate || !keep || keep == 'force') {\n        node[state] = false;\n      }\n        // Trigger callbacks\n      callbacks(input, checked, callback, keep);\n    }\n      // Add proper cursor\n    if (!node[_disabled] && !!option(input, _cursor, true)) {\n      parent.find('.' + _iCheckHelper).css(_cursor, 'pointer');\n    }\n      // Remove state class\n    parent[_remove](specific || option(input, state) || '');\n\n    // Set ARIA attribute\n    disabled ? parent.attr('aria-disabled', 'false') : parent.attr('aria-checked', 'false');\n\n    // Add regular state class\n    parent[_add](regular || option(input, callback) || '');\n  }\n    // Remove all traces\n  function tidy(input, callback) {\n    if (input.data(_iCheck)) {\n\n      // Remove everything except input\n      input.parent().html(input.attr('style', input.data(_iCheck).s || ''));\n\n      // Callback\n      if (callback) {\n        input[_callback](callback);\n      }\n        // Unbind events\n      input.off('.i').unwrap();\n      $(_label + '[for=\"' + input[0].id + '\"]').add(input.closest(_label)).off('.i');\n    }\n  }\n    // Get some option\n  function option(input, state, regular) {\n    if (input.data(_iCheck)) {\n      return input.data(_iCheck).o[state + (regular ? '' : 'Class')];\n    }\n  }\n    // Capitalize some string\n  function capitalize(string) {\n    return string.charAt(0).toUpperCase() + string.slice(1);\n  }\n    // Executable handlers\n  function callbacks(input, checked, callback, keep) {\n    if (!keep) {\n      if (checked) {\n        input[_callback]('ifToggled');\n      }\n        input[_callback]('ifChanged')[_callback]('if' + capitalize(callback));\n    }\n  }\n})(window.jQuery || window.Zepto);\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/_all.css",
    "content": "/* iCheck plugin Line skin\n----------------------------------- */\n.icheckbox_line,\n.iradio_line {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #000;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line .icheck_line-icon,\n    .iradio_line .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line.hover,\n    .icheckbox_line.checked.hover,\n    .iradio_line.hover {\n        background: #444;\n    }\n    .icheckbox_line.checked,\n    .iradio_line.checked {\n        background: #000;\n    }\n        .icheckbox_line.checked .icheck_line-icon,\n        .iradio_line.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line.disabled,\n    .iradio_line.disabled {\n        background: #ccc;\n        cursor: default;\n    }\n        .icheckbox_line.disabled .icheck_line-icon,\n        .iradio_line.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line.checked.disabled,\n    .iradio_line.checked.disabled {\n        background: #ccc;\n    }\n        .icheckbox_line.checked.disabled .icheck_line-icon,\n        .iradio_line.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line .icheck_line-icon,\n    .iradio_line .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* red */\n.icheckbox_line-red,\n.iradio_line-red {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #e56c69;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-red .icheck_line-icon,\n    .iradio_line-red .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-red.hover,\n    .icheckbox_line-red.checked.hover,\n    .iradio_line-red.hover {\n        background: #E98582;\n    }\n    .icheckbox_line-red.checked,\n    .iradio_line-red.checked {\n        background: #e56c69;\n    }\n        .icheckbox_line-red.checked .icheck_line-icon,\n        .iradio_line-red.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-red.disabled,\n    .iradio_line-red.disabled {\n        background: #F7D3D2;\n        cursor: default;\n    }\n        .icheckbox_line-red.disabled .icheck_line-icon,\n        .iradio_line-red.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-red.checked.disabled,\n    .iradio_line-red.checked.disabled {\n        background: #F7D3D2;\n    }\n        .icheckbox_line-red.checked.disabled .icheck_line-icon,\n        .iradio_line-red.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-red .icheck_line-icon,\n    .iradio_line-red .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* green */\n.icheckbox_line-green,\n.iradio_line-green {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #1b7e5a;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-green .icheck_line-icon,\n    .iradio_line-green .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-green.hover,\n    .icheckbox_line-green.checked.hover,\n    .iradio_line-green.hover {\n        background: #24AA7A;\n    }\n    .icheckbox_line-green.checked,\n    .iradio_line-green.checked {\n        background: #1b7e5a;\n    }\n        .icheckbox_line-green.checked .icheck_line-icon,\n        .iradio_line-green.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-green.disabled,\n    .iradio_line-green.disabled {\n        background: #89E6C4;\n        cursor: default;\n    }\n        .icheckbox_line-green.disabled .icheck_line-icon,\n        .iradio_line-green.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-green.checked.disabled,\n    .iradio_line-green.checked.disabled {\n        background: #89E6C4;\n    }\n        .icheckbox_line-green.checked.disabled .icheck_line-icon,\n        .iradio_line-green.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-green .icheck_line-icon,\n    .iradio_line-green .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* blue */\n.icheckbox_line-blue,\n.iradio_line-blue {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #2489c5;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-blue .icheck_line-icon,\n    .iradio_line-blue .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-blue.hover,\n    .icheckbox_line-blue.checked.hover,\n    .iradio_line-blue.hover {\n        background: #3DA0DB;\n    }\n    .icheckbox_line-blue.checked,\n    .iradio_line-blue.checked {\n        background: #2489c5;\n    }\n        .icheckbox_line-blue.checked .icheck_line-icon,\n        .iradio_line-blue.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-blue.disabled,\n    .iradio_line-blue.disabled {\n        background: #ADD7F0;\n        cursor: default;\n    }\n        .icheckbox_line-blue.disabled .icheck_line-icon,\n        .iradio_line-blue.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-blue.checked.disabled,\n    .iradio_line-blue.checked.disabled {\n        background: #ADD7F0;\n    }\n        .icheckbox_line-blue.checked.disabled .icheck_line-icon,\n        .iradio_line-blue.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-blue .icheck_line-icon,\n    .iradio_line-blue .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* aero */\n.icheckbox_line-aero,\n.iradio_line-aero {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #9cc2cb;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-aero .icheck_line-icon,\n    .iradio_line-aero .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-aero.hover,\n    .icheckbox_line-aero.checked.hover,\n    .iradio_line-aero.hover {\n        background: #B5D1D8;\n    }\n    .icheckbox_line-aero.checked,\n    .iradio_line-aero.checked {\n        background: #9cc2cb;\n    }\n        .icheckbox_line-aero.checked .icheck_line-icon,\n        .iradio_line-aero.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-aero.disabled,\n    .iradio_line-aero.disabled {\n        background: #D2E4E8;\n        cursor: default;\n    }\n        .icheckbox_line-aero.disabled .icheck_line-icon,\n        .iradio_line-aero.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-aero.checked.disabled,\n    .iradio_line-aero.checked.disabled {\n        background: #D2E4E8;\n    }\n        .icheckbox_line-aero.checked.disabled .icheck_line-icon,\n        .iradio_line-aero.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-aero .icheck_line-icon,\n    .iradio_line-aero .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* grey */\n.icheckbox_line-grey,\n.iradio_line-grey {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #73716e;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-grey .icheck_line-icon,\n    .iradio_line-grey .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-grey.hover,\n    .icheckbox_line-grey.checked.hover,\n    .iradio_line-grey.hover {\n        background: #8B8986;\n    }\n    .icheckbox_line-grey.checked,\n    .iradio_line-grey.checked {\n        background: #73716e;\n    }\n        .icheckbox_line-grey.checked .icheck_line-icon,\n        .iradio_line-grey.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-grey.disabled,\n    .iradio_line-grey.disabled {\n        background: #D5D4D3;\n        cursor: default;\n    }\n        .icheckbox_line-grey.disabled .icheck_line-icon,\n        .iradio_line-grey.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-grey.checked.disabled,\n    .iradio_line-grey.checked.disabled {\n        background: #D5D4D3;\n    }\n        .icheckbox_line-grey.checked.disabled .icheck_line-icon,\n        .iradio_line-grey.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-grey .icheck_line-icon,\n    .iradio_line-grey .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* orange */\n.icheckbox_line-orange,\n.iradio_line-orange {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #f70;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-orange .icheck_line-icon,\n    .iradio_line-orange .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-orange.hover,\n    .icheckbox_line-orange.checked.hover,\n    .iradio_line-orange.hover {\n        background: #FF9233;\n    }\n    .icheckbox_line-orange.checked,\n    .iradio_line-orange.checked {\n        background: #f70;\n    }\n        .icheckbox_line-orange.checked .icheck_line-icon,\n        .iradio_line-orange.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-orange.disabled,\n    .iradio_line-orange.disabled {\n        background: #FFD6B3;\n        cursor: default;\n    }\n        .icheckbox_line-orange.disabled .icheck_line-icon,\n        .iradio_line-orange.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-orange.checked.disabled,\n    .iradio_line-orange.checked.disabled {\n        background: #FFD6B3;\n    }\n        .icheckbox_line-orange.checked.disabled .icheck_line-icon,\n        .iradio_line-orange.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-orange .icheck_line-icon,\n    .iradio_line-orange .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* yellow */\n.icheckbox_line-yellow,\n.iradio_line-yellow {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #FFC414;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-yellow .icheck_line-icon,\n    .iradio_line-yellow .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-yellow.hover,\n    .icheckbox_line-yellow.checked.hover,\n    .iradio_line-yellow.hover {\n        background: #FFD34F;\n    }\n    .icheckbox_line-yellow.checked,\n    .iradio_line-yellow.checked {\n        background: #FFC414;\n    }\n        .icheckbox_line-yellow.checked .icheck_line-icon,\n        .iradio_line-yellow.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-yellow.disabled,\n    .iradio_line-yellow.disabled {\n        background: #FFE495;\n        cursor: default;\n    }\n        .icheckbox_line-yellow.disabled .icheck_line-icon,\n        .iradio_line-yellow.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-yellow.checked.disabled,\n    .iradio_line-yellow.checked.disabled {\n        background: #FFE495;\n    }\n        .icheckbox_line-yellow.checked.disabled .icheck_line-icon,\n        .iradio_line-yellow.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-yellow .icheck_line-icon,\n    .iradio_line-yellow .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* pink */\n.icheckbox_line-pink,\n.iradio_line-pink {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #a77a94;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-pink .icheck_line-icon,\n    .iradio_line-pink .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-pink.hover,\n    .icheckbox_line-pink.checked.hover,\n    .iradio_line-pink.hover {\n        background: #B995A9;\n    }\n    .icheckbox_line-pink.checked,\n    .iradio_line-pink.checked {\n        background: #a77a94;\n    }\n        .icheckbox_line-pink.checked .icheck_line-icon,\n        .iradio_line-pink.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-pink.disabled,\n    .iradio_line-pink.disabled {\n        background: #E0D0DA;\n        cursor: default;\n    }\n        .icheckbox_line-pink.disabled .icheck_line-icon,\n        .iradio_line-pink.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-pink.checked.disabled,\n    .iradio_line-pink.checked.disabled {\n        background: #E0D0DA;\n    }\n        .icheckbox_line-pink.checked.disabled .icheck_line-icon,\n        .iradio_line-pink.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-pink .icheck_line-icon,\n    .iradio_line-pink .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* purple */\n.icheckbox_line-purple,\n.iradio_line-purple {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #6a5a8c;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-purple .icheck_line-icon,\n    .iradio_line-purple .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-purple.hover,\n    .icheckbox_line-purple.checked.hover,\n    .iradio_line-purple.hover {\n        background: #8677A7;\n    }\n    .icheckbox_line-purple.checked,\n    .iradio_line-purple.checked {\n        background: #6a5a8c;\n    }\n        .icheckbox_line-purple.checked .icheck_line-icon,\n        .iradio_line-purple.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-purple.disabled,\n    .iradio_line-purple.disabled {\n        background: #D2CCDE;\n        cursor: default;\n    }\n        .icheckbox_line-purple.disabled .icheck_line-icon,\n        .iradio_line-purple.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-purple.checked.disabled,\n    .iradio_line-purple.checked.disabled {\n        background: #D2CCDE;\n    }\n        .icheckbox_line-purple.checked.disabled .icheck_line-icon,\n        .iradio_line-purple.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-purple .icheck_line-icon,\n    .iradio_line-purple .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/aero.css",
    "content": "/* iCheck plugin Line skin, aero\n----------------------------------- */\n.icheckbox_line-aero,\n.iradio_line-aero {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #9cc2cb;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-aero .icheck_line-icon,\n    .iradio_line-aero .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-aero.hover,\n    .icheckbox_line-aero.checked.hover,\n    .iradio_line-aero.hover {\n        background: #B5D1D8;\n    }\n    .icheckbox_line-aero.checked,\n    .iradio_line-aero.checked {\n        background: #9cc2cb;\n    }\n        .icheckbox_line-aero.checked .icheck_line-icon,\n        .iradio_line-aero.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-aero.disabled,\n    .iradio_line-aero.disabled {\n        background: #D2E4E8;\n        cursor: default;\n    }\n        .icheckbox_line-aero.disabled .icheck_line-icon,\n        .iradio_line-aero.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-aero.checked.disabled,\n    .iradio_line-aero.checked.disabled {\n        background: #D2E4E8;\n    }\n        .icheckbox_line-aero.checked.disabled .icheck_line-icon,\n        .iradio_line-aero.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-aero .icheck_line-icon,\n    .iradio_line-aero .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/blue.css",
    "content": "/* iCheck plugin Line skin, blue\n----------------------------------- */\n.icheckbox_line-blue,\n.iradio_line-blue {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #2489c5;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-blue .icheck_line-icon,\n    .iradio_line-blue .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-blue.hover,\n    .icheckbox_line-blue.checked.hover,\n    .iradio_line-blue.hover {\n        background: #3DA0DB;\n    }\n    .icheckbox_line-blue.checked,\n    .iradio_line-blue.checked {\n        background: #2489c5;\n    }\n        .icheckbox_line-blue.checked .icheck_line-icon,\n        .iradio_line-blue.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-blue.disabled,\n    .iradio_line-blue.disabled {\n        background: #ADD7F0;\n        cursor: default;\n    }\n        .icheckbox_line-blue.disabled .icheck_line-icon,\n        .iradio_line-blue.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-blue.checked.disabled,\n    .iradio_line-blue.checked.disabled {\n        background: #ADD7F0;\n    }\n        .icheckbox_line-blue.checked.disabled .icheck_line-icon,\n        .iradio_line-blue.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-blue .icheck_line-icon,\n    .iradio_line-blue .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/green.css",
    "content": "/* iCheck plugin Line skin, green\n----------------------------------- */\n.icheckbox_line-green,\n.iradio_line-green {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #1b7e5a;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-green .icheck_line-icon,\n    .iradio_line-green .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-green.hover,\n    .icheckbox_line-green.checked.hover,\n    .iradio_line-green.hover {\n        background: #24AA7A;\n    }\n    .icheckbox_line-green.checked,\n    .iradio_line-green.checked {\n        background: #1b7e5a;\n    }\n        .icheckbox_line-green.checked .icheck_line-icon,\n        .iradio_line-green.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-green.disabled,\n    .iradio_line-green.disabled {\n        background: #89E6C4;\n        cursor: default;\n    }\n        .icheckbox_line-green.disabled .icheck_line-icon,\n        .iradio_line-green.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-green.checked.disabled,\n    .iradio_line-green.checked.disabled {\n        background: #89E6C4;\n    }\n        .icheckbox_line-green.checked.disabled .icheck_line-icon,\n        .iradio_line-green.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-green .icheck_line-icon,\n    .iradio_line-green .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/grey.css",
    "content": "/* iCheck plugin Line skin, grey\n----------------------------------- */\n.icheckbox_line-grey,\n.iradio_line-grey {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #73716e;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-grey .icheck_line-icon,\n    .iradio_line-grey .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-grey.hover,\n    .icheckbox_line-grey.checked.hover,\n    .iradio_line-grey.hover {\n        background: #8B8986;\n    }\n    .icheckbox_line-grey.checked,\n    .iradio_line-grey.checked {\n        background: #73716e;\n    }\n        .icheckbox_line-grey.checked .icheck_line-icon,\n        .iradio_line-grey.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-grey.disabled,\n    .iradio_line-grey.disabled {\n        background: #D5D4D3;\n        cursor: default;\n    }\n        .icheckbox_line-grey.disabled .icheck_line-icon,\n        .iradio_line-grey.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-grey.checked.disabled,\n    .iradio_line-grey.checked.disabled {\n        background: #D5D4D3;\n    }\n        .icheckbox_line-grey.checked.disabled .icheck_line-icon,\n        .iradio_line-grey.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-grey .icheck_line-icon,\n    .iradio_line-grey .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/line.css",
    "content": "/* iCheck plugin Line skin, black\n----------------------------------- */\n.icheckbox_line,\n.iradio_line {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #000;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line .icheck_line-icon,\n    .iradio_line .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line.hover,\n    .icheckbox_line.checked.hover,\n    .iradio_line.hover {\n        background: #444;\n    }\n    .icheckbox_line.checked,\n    .iradio_line.checked {\n        background: #000;\n    }\n        .icheckbox_line.checked .icheck_line-icon,\n        .iradio_line.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line.disabled,\n    .iradio_line.disabled {\n        background: #ccc;\n        cursor: default;\n    }\n        .icheckbox_line.disabled .icheck_line-icon,\n        .iradio_line.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line.checked.disabled,\n    .iradio_line.checked.disabled {\n        background: #ccc;\n    }\n        .icheckbox_line.checked.disabled .icheck_line-icon,\n        .iradio_line.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line .icheck_line-icon,\n    .iradio_line .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/orange.css",
    "content": "/* iCheck plugin Line skin, orange\n----------------------------------- */\n.icheckbox_line-orange,\n.iradio_line-orange {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #f70;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-orange .icheck_line-icon,\n    .iradio_line-orange .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-orange.hover,\n    .icheckbox_line-orange.checked.hover,\n    .iradio_line-orange.hover {\n        background: #FF9233;\n    }\n    .icheckbox_line-orange.checked,\n    .iradio_line-orange.checked {\n        background: #f70;\n    }\n        .icheckbox_line-orange.checked .icheck_line-icon,\n        .iradio_line-orange.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-orange.disabled,\n    .iradio_line-orange.disabled {\n        background: #FFD6B3;\n        cursor: default;\n    }\n        .icheckbox_line-orange.disabled .icheck_line-icon,\n        .iradio_line-orange.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-orange.checked.disabled,\n    .iradio_line-orange.checked.disabled {\n        background: #FFD6B3;\n    }\n        .icheckbox_line-orange.checked.disabled .icheck_line-icon,\n        .iradio_line-orange.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-orange .icheck_line-icon,\n    .iradio_line-orange .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/pink.css",
    "content": "/* iCheck plugin Line skin, pink\n----------------------------------- */\n.icheckbox_line-pink,\n.iradio_line-pink {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #a77a94;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-pink .icheck_line-icon,\n    .iradio_line-pink .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-pink.hover,\n    .icheckbox_line-pink.checked.hover,\n    .iradio_line-pink.hover {\n        background: #B995A9;\n    }\n    .icheckbox_line-pink.checked,\n    .iradio_line-pink.checked {\n        background: #a77a94;\n    }\n        .icheckbox_line-pink.checked .icheck_line-icon,\n        .iradio_line-pink.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-pink.disabled,\n    .iradio_line-pink.disabled {\n        background: #E0D0DA;\n        cursor: default;\n    }\n        .icheckbox_line-pink.disabled .icheck_line-icon,\n        .iradio_line-pink.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-pink.checked.disabled,\n    .iradio_line-pink.checked.disabled {\n        background: #E0D0DA;\n    }\n        .icheckbox_line-pink.checked.disabled .icheck_line-icon,\n        .iradio_line-pink.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-pink .icheck_line-icon,\n    .iradio_line-pink .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/purple.css",
    "content": "/* iCheck plugin Line skin, purple\n----------------------------------- */\n.icheckbox_line-purple,\n.iradio_line-purple {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #6a5a8c;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-purple .icheck_line-icon,\n    .iradio_line-purple .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-purple.hover,\n    .icheckbox_line-purple.checked.hover,\n    .iradio_line-purple.hover {\n        background: #8677A7;\n    }\n    .icheckbox_line-purple.checked,\n    .iradio_line-purple.checked {\n        background: #6a5a8c;\n    }\n        .icheckbox_line-purple.checked .icheck_line-icon,\n        .iradio_line-purple.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-purple.disabled,\n    .iradio_line-purple.disabled {\n        background: #D2CCDE;\n        cursor: default;\n    }\n        .icheckbox_line-purple.disabled .icheck_line-icon,\n        .iradio_line-purple.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-purple.checked.disabled,\n    .iradio_line-purple.checked.disabled {\n        background: #D2CCDE;\n    }\n        .icheckbox_line-purple.checked.disabled .icheck_line-icon,\n        .iradio_line-purple.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-purple .icheck_line-icon,\n    .iradio_line-purple .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/red.css",
    "content": "/* iCheck plugin Line skin, red\n----------------------------------- */\n.icheckbox_line-red,\n.iradio_line-red {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #e56c69;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-red .icheck_line-icon,\n    .iradio_line-red .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-red.hover,\n    .icheckbox_line-red.checked.hover,\n    .iradio_line-red.hover {\n        background: #E98582;\n    }\n    .icheckbox_line-red.checked,\n    .iradio_line-red.checked {\n        background: #e56c69;\n    }\n        .icheckbox_line-red.checked .icheck_line-icon,\n        .iradio_line-red.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-red.disabled,\n    .iradio_line-red.disabled {\n        background: #F7D3D2;\n        cursor: default;\n    }\n        .icheckbox_line-red.disabled .icheck_line-icon,\n        .iradio_line-red.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-red.checked.disabled,\n    .iradio_line-red.checked.disabled {\n        background: #F7D3D2;\n    }\n        .icheckbox_line-red.checked.disabled .icheck_line-icon,\n        .iradio_line-red.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-red .icheck_line-icon,\n    .iradio_line-red .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/line/yellow.css",
    "content": "/* iCheck plugin Line skin, yellow\n----------------------------------- */\n.icheckbox_line-yellow,\n.iradio_line-yellow {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #FFC414;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-yellow .icheck_line-icon,\n    .iradio_line-yellow .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-yellow.hover,\n    .icheckbox_line-yellow.checked.hover,\n    .iradio_line-yellow.hover {\n        background: #FFD34F;\n    }\n    .icheckbox_line-yellow.checked,\n    .iradio_line-yellow.checked {\n        background: #FFC414;\n    }\n        .icheckbox_line-yellow.checked .icheck_line-icon,\n        .iradio_line-yellow.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-yellow.disabled,\n    .iradio_line-yellow.disabled {\n        background: #FFE495;\n        cursor: default;\n    }\n        .icheckbox_line-yellow.disabled .icheck_line-icon,\n        .iradio_line-yellow.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-yellow.checked.disabled,\n    .iradio_line-yellow.checked.disabled {\n        background: #FFE495;\n    }\n        .icheckbox_line-yellow.checked.disabled .icheck_line-icon,\n        .iradio_line-yellow.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-yellow .icheck_line-icon,\n    .iradio_line-yellow .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/_all.css",
    "content": "/* red */\n.icheckbox_minimal-red,\n.iradio_minimal-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-red {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-red.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-red.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-red.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-red.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-red {\n    background-position: -100px 0;\n}\n    .iradio_minimal-red.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-red.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-red.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-red.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-red,\n    .iradio_minimal-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* green */\n.icheckbox_minimal-green,\n.iradio_minimal-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-green {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-green.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-green.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-green.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-green.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-green {\n    background-position: -100px 0;\n}\n    .iradio_minimal-green.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-green.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-green.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-green.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-green,\n    .iradio_minimal-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* blue */\n.icheckbox_minimal-blue,\n.iradio_minimal-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-blue {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-blue.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-blue.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-blue.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-blue.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-blue {\n    background-position: -100px 0;\n}\n    .iradio_minimal-blue.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-blue.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-blue.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-blue.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-blue,\n    .iradio_minimal-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* aero */\n.icheckbox_minimal-aero,\n.iradio_minimal-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-aero {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-aero.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-aero.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-aero.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-aero.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-aero {\n    background-position: -100px 0;\n}\n    .iradio_minimal-aero.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-aero.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-aero.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-aero.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-aero,\n    .iradio_minimal-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* grey */\n.icheckbox_minimal-grey,\n.iradio_minimal-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-grey {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-grey.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-grey.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-grey.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-grey.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-grey {\n    background-position: -100px 0;\n}\n    .iradio_minimal-grey.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-grey.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-grey.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-grey.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-grey,\n    .iradio_minimal-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* orange */\n.icheckbox_minimal-orange,\n.iradio_minimal-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-orange {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-orange.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-orange.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-orange.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-orange.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-orange {\n    background-position: -100px 0;\n}\n    .iradio_minimal-orange.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-orange.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-orange.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-orange.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-orange,\n    .iradio_minimal-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* yellow */\n.icheckbox_minimal-yellow,\n.iradio_minimal-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-yellow.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-yellow.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-yellow.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-yellow.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-yellow {\n    background-position: -100px 0;\n}\n    .iradio_minimal-yellow.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-yellow.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-yellow.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-yellow.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-yellow,\n    .iradio_minimal-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* pink */\n.icheckbox_minimal-pink,\n.iradio_minimal-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-pink {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-pink.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-pink.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-pink.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-pink.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-pink {\n    background-position: -100px 0;\n}\n    .iradio_minimal-pink.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-pink.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-pink.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-pink.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-pink,\n    .iradio_minimal-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* purple */\n.icheckbox_minimal-purple,\n.iradio_minimal-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-purple {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-purple.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-purple.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-purple.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-purple.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-purple {\n    background-position: -100px 0;\n}\n    .iradio_minimal-purple.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-purple.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-purple.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-purple.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-purple,\n    .iradio_minimal-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/aero.css",
    "content": "/* iCheck plugin Minimal skin, aero\n----------------------------------- */\n.icheckbox_minimal-aero,\n.iradio_minimal-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-aero {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-aero.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-aero.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-aero.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-aero.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-aero {\n    background-position: -100px 0;\n}\n    .iradio_minimal-aero.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-aero.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-aero.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-aero.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-aero,\n    .iradio_minimal-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/blue.css",
    "content": "/* iCheck plugin Minimal skin, blue\n----------------------------------- */\n.icheckbox_minimal-blue,\n.iradio_minimal-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-blue {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-blue.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-blue.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-blue.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-blue.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-blue {\n    background-position: -100px 0;\n}\n    .iradio_minimal-blue.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-blue.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-blue.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-blue.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-blue,\n    .iradio_minimal-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/green.css",
    "content": "/* iCheck plugin Minimal skin, green\n----------------------------------- */\n.icheckbox_minimal-green,\n.iradio_minimal-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-green {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-green.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-green.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-green.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-green.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-green {\n    background-position: -100px 0;\n}\n    .iradio_minimal-green.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-green.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-green.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-green.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-green,\n    .iradio_minimal-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/grey.css",
    "content": "/* iCheck plugin Minimal skin, grey\n----------------------------------- */\n.icheckbox_minimal-grey,\n.iradio_minimal-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-grey {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-grey.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-grey.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-grey.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-grey.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-grey {\n    background-position: -100px 0;\n}\n    .iradio_minimal-grey.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-grey.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-grey.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-grey.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-grey,\n    .iradio_minimal-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/minimal.css",
    "content": "/* iCheck plugin Minimal skin, black\n----------------------------------- */\n.icheckbox_minimal,\n.iradio_minimal {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(minimal.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal {\n    background-position: 0 0;\n}\n    .icheckbox_minimal.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal {\n    background-position: -100px 0;\n}\n    .iradio_minimal.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal,\n    .iradio_minimal {\n        background-image: url(minimal@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/orange.css",
    "content": "/* iCheck plugin Minimal skin, orange\n----------------------------------- */\n.icheckbox_minimal-orange,\n.iradio_minimal-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-orange {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-orange.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-orange.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-orange.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-orange.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-orange {\n    background-position: -100px 0;\n}\n    .iradio_minimal-orange.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-orange.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-orange.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-orange.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-orange,\n    .iradio_minimal-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/pink.css",
    "content": "/* iCheck plugin Minimal skin, pink\n----------------------------------- */\n.icheckbox_minimal-pink,\n.iradio_minimal-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-pink {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-pink.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-pink.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-pink.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-pink.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-pink {\n    background-position: -100px 0;\n}\n    .iradio_minimal-pink.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-pink.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-pink.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-pink.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-pink,\n    .iradio_minimal-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/purple.css",
    "content": "/* iCheck plugin Minimal skin, purple\n----------------------------------- */\n.icheckbox_minimal-purple,\n.iradio_minimal-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-purple {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-purple.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-purple.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-purple.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-purple.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-purple {\n    background-position: -100px 0;\n}\n    .iradio_minimal-purple.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-purple.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-purple.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-purple.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-purple,\n    .iradio_minimal-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/red.css",
    "content": "/* iCheck plugin Minimal skin, red\n----------------------------------- */\n.icheckbox_minimal-red,\n.iradio_minimal-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-red {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-red.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-red.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-red.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-red.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-red {\n    background-position: -100px 0;\n}\n    .iradio_minimal-red.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-red.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-red.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-red.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-red,\n    .iradio_minimal-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/minimal/yellow.css",
    "content": "/* iCheck plugin Minimal skin, yellow\n----------------------------------- */\n.icheckbox_minimal-yellow,\n.iradio_minimal-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-yellow.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-yellow.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-yellow.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-yellow.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-yellow {\n    background-position: -100px 0;\n}\n    .iradio_minimal-yellow.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-yellow.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-yellow.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-yellow.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-yellow,\n    .iradio_minimal-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/polaris/polaris.css",
    "content": "/* iCheck plugin Polaris skin\n----------------------------------- */\n.icheckbox_polaris,\n.iradio_polaris {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 29px;\n    height: 29px;\n    background: url(polaris.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_polaris {\n    background-position: 0 0;\n}\n    .icheckbox_polaris.hover {\n        background-position: -31px 0;\n    }\n    .icheckbox_polaris.checked {\n        background-position: -62px 0;\n    }\n    .icheckbox_polaris.disabled {\n        background-position: -93px 0;\n        cursor: default;\n    }\n    .icheckbox_polaris.checked.disabled {\n        background-position: -124px 0;\n    }\n\n.iradio_polaris {\n    background-position: -155px 0;\n}\n    .iradio_polaris.hover {\n        background-position: -186px 0;\n    }\n    .iradio_polaris.checked {\n        background-position: -217px 0;\n    }\n    .iradio_polaris.disabled {\n        background-position: -248px 0;\n        cursor: default;\n    }\n    .iradio_polaris.checked.disabled {\n        background-position: -279px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_polaris,\n    .iradio_polaris {\n        background-image: url(polaris@2x.png);\n        -webkit-background-size: 310px 31px;\n        background-size: 310px 31px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/_all.css",
    "content": "/* iCheck plugin Square skin\n----------------------------------- */\n.icheckbox_square,\n.iradio_square {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(square.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square {\n    background-position: 0 0;\n}\n    .icheckbox_square.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square {\n    background-position: -120px 0;\n}\n    .iradio_square.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square,\n    .iradio_square {\n        background-image: url(square@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* red */\n.icheckbox_square-red,\n.iradio_square-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-red {\n    background-position: 0 0;\n}\n    .icheckbox_square-red.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-red.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-red.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-red.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-red {\n    background-position: -120px 0;\n}\n    .iradio_square-red.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-red.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-red.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-red.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-red,\n    .iradio_square-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* green */\n.icheckbox_square-green,\n.iradio_square-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-green {\n    background-position: 0 0;\n}\n    .icheckbox_square-green.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-green.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-green.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-green.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-green {\n    background-position: -120px 0;\n}\n    .iradio_square-green.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-green.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-green.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-green.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-green,\n    .iradio_square-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* blue */\n.icheckbox_square-blue,\n.iradio_square-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-blue {\n    background-position: 0 0;\n}\n    .icheckbox_square-blue.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-blue.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-blue.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-blue.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-blue {\n    background-position: -120px 0;\n}\n    .iradio_square-blue.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-blue.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-blue.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-blue.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-blue,\n    .iradio_square-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* aero */\n.icheckbox_square-aero,\n.iradio_square-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-aero {\n    background-position: 0 0;\n}\n    .icheckbox_square-aero.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-aero.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-aero.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-aero.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-aero {\n    background-position: -120px 0;\n}\n    .iradio_square-aero.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-aero.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-aero.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-aero.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-aero,\n    .iradio_square-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* grey */\n.icheckbox_square-grey,\n.iradio_square-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-grey {\n    background-position: 0 0;\n}\n    .icheckbox_square-grey.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-grey.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-grey.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-grey.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-grey {\n    background-position: -120px 0;\n}\n    .iradio_square-grey.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-grey.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-grey.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-grey.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-grey,\n    .iradio_square-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* orange */\n.icheckbox_square-orange,\n.iradio_square-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-orange {\n    background-position: 0 0;\n}\n    .icheckbox_square-orange.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-orange.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-orange.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-orange.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-orange {\n    background-position: -120px 0;\n}\n    .iradio_square-orange.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-orange.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-orange.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-orange.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-orange,\n    .iradio_square-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* yellow */\n.icheckbox_square-yellow,\n.iradio_square-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_square-yellow.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-yellow.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-yellow.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-yellow.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-yellow {\n    background-position: -120px 0;\n}\n    .iradio_square-yellow.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-yellow.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-yellow.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-yellow.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-yellow,\n    .iradio_square-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* pink */\n.icheckbox_square-pink,\n.iradio_square-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-pink {\n    background-position: 0 0;\n}\n    .icheckbox_square-pink.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-pink.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-pink.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-pink.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-pink {\n    background-position: -120px 0;\n}\n    .iradio_square-pink.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-pink.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-pink.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-pink.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-pink,\n    .iradio_square-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* purple */\n.icheckbox_square-purple,\n.iradio_square-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-purple {\n    background-position: 0 0;\n}\n    .icheckbox_square-purple.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-purple.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-purple.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-purple.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-purple {\n    background-position: -120px 0;\n}\n    .iradio_square-purple.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-purple.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-purple.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-purple.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-purple,\n    .iradio_square-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/aero.css",
    "content": "/* iCheck plugin Square skin, aero\n----------------------------------- */\n.icheckbox_square-aero,\n.iradio_square-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-aero {\n    background-position: 0 0;\n}\n    .icheckbox_square-aero.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-aero.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-aero.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-aero.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-aero {\n    background-position: -120px 0;\n}\n    .iradio_square-aero.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-aero.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-aero.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-aero.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-aero,\n    .iradio_square-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/blue.css",
    "content": "/* iCheck plugin Square skin, blue\n----------------------------------- */\n.icheckbox_square-blue,\n.iradio_square-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-blue {\n    background-position: 0 0;\n}\n    .icheckbox_square-blue.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-blue.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-blue.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-blue.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-blue {\n    background-position: -120px 0;\n}\n    .iradio_square-blue.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-blue.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-blue.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-blue.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-blue,\n    .iradio_square-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/green.css",
    "content": "/* iCheck plugin Square skin, green\n----------------------------------- */\n.icheckbox_square-green,\n.iradio_square-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-green {\n    background-position: 0 0;\n}\n    .icheckbox_square-green.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-green.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-green.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-green.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-green {\n    background-position: -120px 0;\n}\n    .iradio_square-green.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-green.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-green.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-green.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-green,\n    .iradio_square-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/grey.css",
    "content": "/* iCheck plugin Square skin, grey\n----------------------------------- */\n.icheckbox_square-grey,\n.iradio_square-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-grey {\n    background-position: 0 0;\n}\n    .icheckbox_square-grey.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-grey.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-grey.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-grey.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-grey {\n    background-position: -120px 0;\n}\n    .iradio_square-grey.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-grey.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-grey.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-grey.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-grey,\n    .iradio_square-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/orange.css",
    "content": "/* iCheck plugin Square skin, orange\n----------------------------------- */\n.icheckbox_square-orange,\n.iradio_square-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-orange {\n    background-position: 0 0;\n}\n    .icheckbox_square-orange.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-orange.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-orange.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-orange.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-orange {\n    background-position: -120px 0;\n}\n    .iradio_square-orange.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-orange.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-orange.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-orange.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-orange,\n    .iradio_square-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/pink.css",
    "content": "/* iCheck plugin Square skin, pink\n----------------------------------- */\n.icheckbox_square-pink,\n.iradio_square-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-pink {\n    background-position: 0 0;\n}\n    .icheckbox_square-pink.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-pink.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-pink.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-pink.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-pink {\n    background-position: -120px 0;\n}\n    .iradio_square-pink.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-pink.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-pink.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-pink.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-pink,\n    .iradio_square-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/purple.css",
    "content": "/* iCheck plugin Square skin, purple\n----------------------------------- */\n.icheckbox_square-purple,\n.iradio_square-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-purple {\n    background-position: 0 0;\n}\n    .icheckbox_square-purple.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-purple.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-purple.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-purple.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-purple {\n    background-position: -120px 0;\n}\n    .iradio_square-purple.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-purple.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-purple.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-purple.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-purple,\n    .iradio_square-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/red.css",
    "content": "/* iCheck plugin Square skin, red\n----------------------------------- */\n.icheckbox_square-red,\n.iradio_square-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-red {\n    background-position: 0 0;\n}\n    .icheckbox_square-red.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-red.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-red.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-red.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-red {\n    background-position: -120px 0;\n}\n    .iradio_square-red.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-red.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-red.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-red.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-red,\n    .iradio_square-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/square.css",
    "content": "/* iCheck plugin Square skin, black\n----------------------------------- */\n.icheckbox_square,\n.iradio_square {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(square.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square {\n    background-position: 0 0;\n}\n    .icheckbox_square.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square {\n    background-position: -120px 0;\n}\n    .iradio_square.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square,\n    .iradio_square {\n        background-image: url(square@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/iCheck/square/yellow.css",
    "content": "/* iCheck plugin Square skin, yellow\n----------------------------------- */\n.icheckbox_square-yellow,\n.iradio_square-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_square-yellow.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-yellow.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-yellow.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-yellow.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-yellow {\n    background-position: -120px 0;\n}\n    .iradio_square-yellow.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-yellow.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-yellow.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-yellow.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-yellow,\n    .iradio_square-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/treeTable/demo/style/demo.css",
    "content": "@charset \"utf-8\";\nhtml { height:100% }\nbody { font:12px/1.5em \"微软雅黑\"; }\n#bg { display:none; width:100%; height:100%; overflow:hidden; position:fixed; top:0; left:0;z-index:10; }\nbody.showBg { overflow:hidden; }\nbody.showBg #bg { display:block;}\na { color:#1E9300; }\nul.nav { padding:0; margin:0; }\nul.nav li { margin:5px 0; list-style:none; }\npre { border-left:2px solid #A9EA1E; padding-left:8px; background:#FCFCFC; }\npre code { padding:1px; color:#333; background:#EAEAEA; }\n#page { width:760px; margin:auto; }\n#page h1 { font-size:1.8em; color:#214FA3; font-weight:700; }\n#page h1 em { font-size:9px; color:#CCC;}\n#page fieldset { margin-top:10px; border:solid 1px #EBEBEB; }\n#page fieldset legend { padding:3px 20px; color:#FFF; background:#214FA3; font-size:1.4em; }\n#page li { line-height:1.8em; list-style: circle; margin:5px 0; color:#333; }\n#page fieldset, #page fieldset legend { -moz-border-radius:4px; -webkit-border-radius: 4px; border-radius:4px; }\n#page button { }\n#page .content { margin:0 20px; }\n#page .content h3 { color:#000; }\n#page .content ol, #page .content ul{ padding-left:0; margin-left:20px; }\n#page strong { color:#1E9300; margin-right:5px; }\n#page .tips { color:#666; border-bottom:1px dashed #CCC; }\n#page label { cursor:pointer; }\n#page .api { background:#FCFCFC; }\n#page .api strong { width:5em; display:inline-block; *zoom:1;*display:inline; }\n#page .api li { border-bottom:1px dashed #CCC; padding:5px 3px; margin:0; }\n#page .api li:hover { background:#EAEAEA; }\n#page .runCode { margin-right:4px; }\n#page .runCode textarea { width:100%; color:#214FA3; font-size:12px; }\n#page .runCode textarea:focus { border-color:#CCC; border-style:solid; }\n#page .runCode .btn { text-align:right; }\n#page .runCode button { cursor:pointer; }\n#page .about { margin-top:30px; border-top:1px solid #F8F8F8; color:#666; }\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/treeTable/demo/treeTable.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n    <head>\n        <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n        <title>树表控件</title>\n        <link href=\"style/demo.css\" rel=\"stylesheet\" type=\"text/css\" />\n        <style type=\"text/css\">\n        table,td,th {  border: 1px solid #8DB9DB; padding:5px; border-collapse: collapse; font-size:16px; }\n        </style>\n\n        <!--引用的文件 Begin-->\n        <link href=\"../themes/default/jquery.treeTable.css\" rel=\"stylesheet\" type=\"text/css\" />\n        <link href=\"../themes/vsStyle/jquery.treeTable.css\" rel=\"stylesheet\" type=\"text/css\" />\n        <script src=\"../../../jquery/1.7.1/jquery.min.js\" type=\"text/javascript\"></script>\n        <script src=\"../jquery.treeTable.js\" type=\"text/javascript\"></script>\n        <!--引用的文件 End-->\n        <script type=\"text/javascript\">\n        $(function(){\n            var option = {\n                theme:'vsStyle',\n                expandLevel : 2,\n                beforeExpand : function($treeTable, id) {\n                    //判断id是否已经有了孩子节点，如果有了就不再加载，这样就可以起到缓存的作用\n                    if ($('.' + id, $treeTable).length) { return; }\n                    //这里的html可以是ajax请求\n                    var html = '<tr id=\"8\" pId=\"6\"><td>5.1</td><td>可以是ajax请求来的内容</td></tr>'\n                             + '<tr id=\"9\" pId=\"6\"><td>5.2</td><td>动态的内容</td></tr>';\n\n                    $treeTable.addChilds(html);\n                },\n                onSelect : function($treeTable, id) {\n                    window.console && console.log('onSelect:' + id);\n                    \n                }\n\n            };\n            $('#treeTable1').treeTable(option);\n\n            option.theme = 'default';\n            $('#treeTable2').treeTable(option);\n        });\n        </script>\n    </head>\n    <body>\n    <div id=\"page\">\n        <h1><span>treeTable <em>v 1.4.2</em></span></h1>\n            <fieldset>\n            <legend> 简介</legend>\n            <div class=\"content\">       \n              <p>treeTable是跨浏览器、性能很高的jquery的树表组件，它使用非常简单，只需要引用jquery库和一个js文件，接口也很简单。</p>\n              <h3>优点</h3>\n              <ol class=\"love\">\n                <li><strong>兼容主流浏览器</strong>: 支持IE6和IE6+, Firefox, chrome, Opera, Safari</li>\n                <li><strong>接口简洁</strong>: 在普通表格的基础上增加父子关系的自定义标签就可以</li>\n                <li><strong>组件性能高</strong>: 内部实现了只绑定了table的事件、使用了css sprite合并图片等</li>\n                <li><strong>提供两种风格</strong>: 通过参数来设置风格</li>\n              </ol>\n            </div>\n\n        </fieldset>\n        <fieldset>\n            <legend>演示</legend>\n            <table id=\"treeTable1\" style=\"width:100%\">\n                <tr>\n                    <td style=\"width:200px;\">标题</td>\n                    <td>内容</td>\n                </tr>\n                <tr id=\"1\">\n                    <td><span controller=\"true\">1</span></td>\n                    <td>内容</td></tr>\n                <tr id=\"2\" pId=\"1\">\n                    <td><span controller=\"true\">2</span></td>\n                    <td>内容</td></tr>\n                <tr id=\"3\" pId=\"2\">\n                    <td>3</td>\n                    <td>内容</td>\n                </tr>\n                <tr id=\"4\" pId=\"2\">\n                    <td>4</td>\n                    <td>内容</td>\n                </tr>\n                <tr id=\"5\" pId=\"4\">\n                    <td>4.1</td>\n                    <td>内容</td>\n                </tr>\n                <tr id=\"6\" pId=\"1\" hasChild=\"true\">\n                    <td>5</td>\n                    <td>注意这个节点是动态加载的</td>\n                </tr>\n                <tr id=\"7\">\n                    <td>8</td>\n                    <td>内容</td>\n                </tr>\n            </table>\n            <hr/>\n            <table id=\"treeTable2\" style=\"width:100%\">\n                <tr>\n                    <td style=\"width:200px;\">标题</td>\n                    <td>内容</td>\n                </tr>\n                <tr id=\"1\">\n                    <td><span controller=\"true\">1</span></td>\n                    <td>内容</td></tr>\n                <tr id=\"2\" pId=\"1\">\n                    <td><span controller=\"true\">2</span></td>\n                    <td>内容</td></tr>\n                <tr id=\"3\" pId=\"2\">\n                    <td>3</td>\n                    <td>内容</td>\n                </tr>\n                <tr id=\"4\" pId=\"2\">\n                    <td>4</td>\n                    <td>内容</td>\n                </tr>\n                <tr id=\"5\" pId=\"4\">\n                    <td>4.1</td>\n                    <td>内容</td>\n                </tr>\n                <tr id=\"6\" pId=\"1\" hasChild=\"true\">\n                    <td>5</td>\n                    <td>注意这个节点是动态加载的</td>\n                </tr>\n                <tr id=\"7\">\n                    <td>8</td>\n                    <td>内容</td>\n                </tr>\n            </table>\n        </fieldset>\n        <fieldset>\n            <legend>接口</legend>\n            <h3>配置参数</h3>\n            <div>\n               <ul class=\"love\">\n                  <li><strong>theme</strong>: string {主题，有两个选项：default、vsStyle. 默认:default}</li>\n                  <li><strong>expandLevel</strong>: int {树表的展开层次. 默认:1}</li>\n                  <li><strong>column</strong>: int {可控制列的序号. 默认:0，即第一列}</li>\n                  <li><strong>onSelect</strong>: function  {拥有controller自定义属性的元素的点击事件，return false则中止展开. 默认值:\n<pre><code>function($treeTable, id) {\n      //$treeTable 当前树表的jquery对象.\n      //id 当前行的id\n    \n      //返回false，则直接退出，不会激发后面的beforeExpand和子节点的展开\n      return true;\n}</code></pre>\n</li>\n                  <li><strong>beforeExpand</strong>: {展开子节点前触发的事件, 默认值：</li>\n<pre><code>function($treeTable, id) {\n      //$treeTable 当前树表的jquery对象.\n      //id 当前行的id\n}</code></pre>\n               </ul>\n            </div>\n            <h3>属性说明</h3>\n            <div>\n               <ul class=\"love\">\n                  <li><strong>id</strong>: string 行的id</li>\n                  <li><strong>pId</strong>: string 父行的id</li>\n                  <li><strong>controller</strong>: bool 指定某一个元素是否可以控制行的展开</li>\n                  <li><strong>hasChild</strong>: bool  指定某一个tr元素是否有孩子（动态加载需用到）</li>\n\t\t\t\t  <li><strong>isFirstOne</strong>: bool  指定某一个tr元素是否是第一个孩子（自动生成属性，只读）</li>\n\t\t\t\t  <li><strong>isLastOne</strong>: bool  指定某一个tr元素是否是最后一个孩子（自动生成属性，只读）</li>\n\t\t\t\t  <li><strong>prevId</strong>: string  前一个兄弟节点的id（自动生成属性，只读）</li>\n\t\t\t\t  <li><strong>depth</strong>: string  当前行的深度（自动生成属性，只读）</li>\n               </ul>\n            </div>\n        </fieldset>\n        <fieldset>\n            <legend>使用方式</legend>\n            <h3> $(\"#元素id\").treeTable({}) 如:</h3>\n\t\t\t<p>引用的文件</p>\n            <pre><code>&lt;script src=&quot;/script/jquery.js&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;\n&lt;script src=&quot;/script/treeTable/jquery.treeTable.js&quot; type=&quot;text/javascript&quot;&gt; &lt;/script&gt;</code></pre>\n            <p>js代码</p>\n            <pre><code>$(function(){\n    var option = {\n        theme:'vsStyle',\n        expandLevel : 2,\n        beforeExpand : function($treeTable, id) {\n            //判断id是否已经有了孩子节点，如果有了就不再加载，这样就可以起到缓存的作用\n            if ($('.' + id, $treeTable).length) { return; }\n            //这里的html可以是ajax请求\n            var html = '&lt;tr id=\"8\" pId=\"6\"&gt;&lt;td&gt;5.1&lt;/td&gt;&lt;td&gt;可以是ajax请求来的内容&lt;/td&gt;&lt;/tr&gt;'\n                     + '&lt;tr id=\"9\" pId=\"6\"&gt;&lt;td&gt;5.2&lt;/td&gt;&lt;td&gt;动态的内容&lt;/td&gt;&lt;/tr&gt;';\n\n            $treeTable.addChilds(html);\n        },\n        onSelect : function($treeTable, id) {\n            window.console && console.log('onSelect:' + id);\n        }\n\n    };\n    $('#treeTable1').treeTable(option);\n});</code></pre>\n           <p>html结构</p>\n           <pre><code>&lt;table id=\"treeTable1\" style=\"width:100%\"&gt;\n    &lt;tr&gt;\n        &lt;td style=\"width:200px;\"&gt;标题&lt;/td&gt;\n        &lt;td&gt;内容&lt;/td&gt;\n    &lt;/tr&gt;\n    &lt;tr id=\"1\"&gt;\n        &lt;td&gt;&lt;span controller=\"true\"&gt;1&lt;/span&gt;&lt;/td&gt;\n        &lt;td&gt;内容&lt;/td&gt;&lt;/tr&gt;\n    &lt;tr id=\"2\" pId=\"1\"&gt;\n        &lt;td&gt;&lt;span controller=\"true\"&gt;2&lt;/span&gt;&lt;/td&gt;\n        &lt;td&gt;内容&lt;/td&gt;&lt;/tr&gt;\n    &lt;tr id=\"3\" pId=\"2\"&gt;\n        &lt;td&gt;3&lt;/td&gt;\n        &lt;td&gt;内容&lt;/td&gt;\n    &lt;/tr&gt;\n    &lt;tr id=\"4\" pId=\"2\"&gt;\n        &lt;td&gt;4&lt;/td&gt;\n        &lt;td&gt;内容&lt;/td&gt;\n    &lt;/tr&gt;\n    &lt;tr id=\"5\" pId=\"4\"&gt;\n        &lt;td&gt;4.1&lt;/td&gt;\n        &lt;td&gt;内容&lt;/td&gt;\n    &lt;/tr&gt;\n    &lt;tr id=\"6\" pId=\"1\" hasChild=\"true\"&gt;\n        &lt;td&gt;5&lt;/td&gt;\n        &lt;td&gt;注意这个节点是动态加载的&lt;/td&gt;\n    &lt;/tr&gt;\n    &lt;tr id=\"7\"&gt;\n        &lt;td&gt;8&lt;/td&gt;\n        &lt;td&gt;内容&lt;/td&gt;\n    &lt;/tr&gt;\n&lt;/table&gt;</code></pre>\n      </fieldset>\n        <fieldset>\n            <legend>关于</legend>\n            <div class=\"content\">\n                <h3>作者: benzhan(詹潮江)</h3>\n                <h3>版本变更</h3>\n                <p>1.0版本：创建基本功能。(2011-05-04)</p>\n                <p>1.1版本：(2011-05-08)</p>\n                <pre>这个版本提高了性能，做了以下改进：\n \n* 1、使用了Css Sprite Tools 合并了分散的图标\n* 2、使用了.id的方式来代替原来[pId=id]，这样选择孩子效率更高\n* 3、把css剥离出来，增加动态添加css，每次家在前判断是否添加过\n \n关于第二点，非常感谢onli同学的提醒。但我并没有直接修改我的接口，直接除去pId，而是在第一次遍历时将pId作为class名添加到节点中。这样有两个好处：\n（1）接口可读性会比较好，pId比class更容易理解。\n（2）第二点，如果直接使用class，那节点本来就有样式，这样获取到的className还要去分解空格得到pId，挺麻烦的。</pre>\n                <hr>\n                <p>1.3版本：(2011-05-09)</p>\n                <pre>这个版本扩展了事件，做了以下改进：\n \n* 1、增加onSelect事件，onSelect: function($treeTable, id){}\n* 2、增加beforeExpand事件，beforeExpand : function($treeTable, id){}\n \n动态加载节点就靠beforeExpand 事件了。</pre>\n                <p>1.4.2版本：(2011-09-03)</p>\n                <pre>这个版本修复了bug，做了以下改进：\n* 1、修复了多个tableTree不在同个页面的bug，并且可以让不同的tableTree使用不同的主题。\n* 2、增加了controller的自定义标签来控制可点击的区域。</pre>\n            </div>\n       </fieldset>\n    </div>\n    </body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/treeTable/jquery.treeTable.js",
    "content": "/**\n* 树表组件\n* @author benzhan (詹潮江)\n* @version 1.4.2\n* @lastUpdateDate 2011-09-03\n* @mail zhanchaojiang@qq.com\n*/\n(function ($) {\n//\twindow.SITE_URL = window.SITE_URL || '';\n//\tif (document.location.href.indexOf('http://') != 0)\t{\n//\t\tvar path = '../themes/';\n//\t} else {\n//\t\tvar path = SITE_URL + '/themes/';\n//\t}\n\n    $.fn.treeTable = function (opts) {\n        opts = $.extend({\n        \tpath: '',\n            theme: 'default',\n            expandLevel: 1,\n            column: 0,\n            onSelect: function($treeTable, id){},\n            beforeExpand: function($treeTable, id){}\n        }, opts);\n\n        var $treeTable = this;\n        $treeTable.addClass('tree_table');\n\n//        //添加需要的样式\n//        if ($('head').find('#tree_table_' + opts.theme).length == 0) {\n//            $('head').append('<link id=\"tree_table_' + opts.theme + '\" href=\"' + opts.path + 'themes/' + opts.theme + '/treeTable.css\" rel=\"stylesheet\" type=\"text/css\" />');\n//        }\n\n        var css = {\n            'N' : opts.theme + '_node',\n            'AN' : opts.theme + '_active_node',\n            'O' : opts.theme + '_open',\n            'LO' : opts.theme + '_last_open',\n            'S' : opts.theme + '_shut',\n            'LS' : opts.theme + '_last_shut',\n            'HO' : opts.theme + '_hover_open',\n            'HS' : opts.theme + '_hover_shut',\n            'HLO' : opts.theme + '_hover_last_open',\n            'HLS' : opts.theme + '_hover_last_shut',\n            'L' : opts.theme + '_leaf',\n            'LL' : opts.theme + '_last_leaf',\n            'B' : opts.theme + '_blank',\n            'V' : opts.theme + '_vertline'\n        };\n\n        var pMap = {}, cMap = {};\n        var $trs = $treeTable.find('tr');\n        initRelation($trs, true);    \n\n        $treeTable.click(function (event) {\n            var $target = $(event.target);\n\n            if ($target.attr('controller')) {\n                $target = $target.parents('tr[haschild]').find('[arrow]');\n                //判断是否是叶子节点\n\t\t\t\tif ($target.attr('class').indexOf(css['AN']) == -1 && $target.attr('class').indexOf(css['N']) == -1) { return; }\n                var id = $target.parents('tr[haschild]')[0].id;\n                if (opts.onSelect && opts.onSelect($treeTable, id) === false) { return; }\n            }\n\n            if ($target.attr('arrow')) {\n                var className = $target.attr('class');\n                if (className == css['AN'] + ' ' + css['HLO'] || className == css['AN'] + ' ' + css['HO']) {\n                    var id = $target.parents('tr[haschild]')[0].id;\n                    $target.attr('class', css['AN'] + \" \" + (className.indexOf(css['HO']) != -1 ?  css['HS'] : css['HLS']));\n\n                    //关闭所有孩子的tr\n                    shut(id);\n\t\t\t\t\treturn;\n                } else if (className == css['AN'] + ' ' + css['HLS'] || className == css['AN'] + ' ' + css['HS']) {\n                    var id = $target.parents('tr')[0].id;\n                    $target.attr('class', css['AN'] + \" \" + (className.indexOf(css['HS']) != -1 ? css['HO'] : css['HLO']));\n                    \n                    opts.beforeExpand($treeTable, id);\n                    //展开所有直属节点，根据图标展开子孙节点\n                    open(id);\n\t\t\t\t\treturn;\n                }\n            }\n        });\n\t\t\n\t\t$treeTable.mouseover(hoverActiveNode).mouseout(hoverActiveNode);\n\n        function hoverActiveNode(event) {\n            var $target = $(event.target);\n\n            if ($target.attr('controller')) {\n                $target = $target.parents('tr[haschild]').find('[arrow]');\n            }\n\n            if ($target.attr('arrow')) { \n                var className = $target.attr('class');\n                if (className && !className.indexOf(css['AN'])) {\n                    var len = opts.theme.length + 1;\n                    className = className.split(' ')[1].substr(len);\n                    if (className.indexOf('hover_') === 0) {\n                        className = opts.theme + '_' + className.substr(6);\n                    } else {\n                        className = opts.theme + '_hover_' + className;\n                    }\n                    \n                    $target.attr('class', css['AN'] + ' ' + className);\n                    return;\n                }\n            } \n        }\n        \n        /** 初始化节点关系　*/\n        function initRelation($trs, hideLevel) {\n            //构造父子关系\n            $trs.each(function (i) {\n                var pId = $(this).attr('pId') || 0;\n                pMap[pId] || (pMap[pId] = []);\n                pMap[pId].push(this.id);\n                cMap[this.id] = pId;\n                \n                //给这个tr增加类为了提高选择器的效率\n                $(this).addClass(pId);\n            }).find('[controller]').css('cursor', 'pointer');\n\n            //标识父节点是否有孩子、是否最后一个节点\n            $trs.each(function (i) {\n                if (!this.id) { return; }\n                var $tr = $(this);\n                \n                pMap[this.id] && $tr.attr('hasChild', true);\n                var pArr = pMap[cMap[this.id]];\n                if (pArr[0] == this.id) {\n                    $tr.attr('isFirstOne', true);\n                } else {\n                    var prevId = 0;\n                    for (var i = 0; i < pArr.length; i++) {\n                        if (pArr[i] == this.id) { break; }\n                        prevId = pArr[i];\n                    }\n                    $tr.attr('prevId', prevId);\n                }\n\n                pArr[pArr.length - 1] == this.id && $tr.attr('isLastOne', true);\n\n                var depth = getDepth(this.id);\n                $tr.attr('depth', depth);\n\n                //格式化节点\n\t\t\t\tformatNode(this);\n\n                //判断是否要隐藏限制的层次\n                if (hideLevel) {\n                    depth > opts.expandLevel && $tr.hide();\n                    //判断是否小于深度，如果小于深度则要换成展开的图标\n                    if ($tr.attr('hasChild') && $tr.attr('depth') < opts.expandLevel) {\n                        var className = $tr.attr('isLastOne') ? css['LO'] : css['O'];\n                        $tr.find('.' + css['AN']).attr('class', css['AN'] + ' ' + className);\n                    }\n                }               \n            });\n            \n            //递归获取深度\n            function getDepth(id) {\n                if (cMap[id] == 0) { return 1; } \n                var $parentDepth = getDepth(cMap[id]);\n                return $parentDepth + 1; \n            }\n        }\n\n        //递归关闭所有的孩子\n        function shut(id) {\n            if (!pMap[id]) { return false; }\n            for (var i = 0; i < pMap[id].length; i++) {\n                shut(pMap[id][i]);\n            }\n            $('tr.' + id, $treeTable).hide();\n        }\n\n        //根据历史记录来展开节点\n        function open(id) {\n            $('tr.' + id, $treeTable).show();\n            if (!pMap[id]) { return false; }\n            for (var i = 0; i < pMap[id].length; i++) {\n                var cId = pMap[id][i];\n                if (pMap[cId]) {\n                    var className = $('#' + cId, $treeTable).find('.' + css['AN']).attr('class');\n                    //如果子节点是展开图表的，则需要展开此节点\n                    (className == css['AN'] + ' ' + css['O'] || className == css['AN'] + ' ' + css['LO']) && open(cId);\n                }\n            }\n        }\n\n        function formatNode(tr) {\n            var $cur = $(tr);\n            var id = tr.id;\n\n            //-------------下面一大段都是获取$preSpan---------\n            if (cMap[id] == 0) {\n                //如果是顶级节点，则没有prev_sp\n                var $preSpan = $('<span class=\"prev_sp\"></span>');\n            } else {\n                //先判断是否有上一个兄弟节点\n                if (!$cur.attr('isFirstOne')) {\n                    var $preSpan = $('#' + $cur.attr('prevId'), $treeTable).children(\"td\").eq(opts.column).find('.prev_sp').clone();\n                } else {\n                    var $parent = $('#' + cMap[id], $treeTable);\n                    //没有上一个兄弟节点，则使用父节点的prev_sp\n                    var $preSpan = $parent.children(\"td\").eq(opts.column).find('.prev_sp').clone();\n\n                    //如果父亲后面没有兄弟，则直接加空白，若有则加竖线\n                    if ($parent.attr('isLastOne')) {\n                        $preSpan.append('<span class=\"' + css['N'] + ' ' + css['B'] + '\"></span>');\n                    } else {\n                        $preSpan.append('<span class=\"' + css['N'] + ' ' + css['V'] + '\"></span>');\n                    }\n                }\n            }\n            //------------------------------------------------\n\n            if ($cur.attr('hasChild')) {\n                //如果有下一个节点，并且下一个节点的父亲与当前节点的父亲相同，则说明该节点不是最后一个节点\n                var className = $cur.attr('isLastOne') ? css['LS'] : css['S'];\n                className = css['AN'] + ' ' + className;\n            } else {\n                var className = css['N'] + ' ' + ($cur.attr('isLastOne') ? css['LL'] : css['L']);\n            }\n            \n            var $td = $cur.children(\"td\").eq(opts.column);\n            $td.prepend('<span arrow=\"true\" class=\"' + className + '\"></span>').prepend($preSpan);\n        };\n        \n        $treeTable.addChilds = function(trsHtml) {\n            var $trs = $(trsHtml);\n            if (!$trs.length) { return false; }\n            \n            var pId = $($trs[0]).attr('pId');\n            if (!pId) { return false; }\n            \n            //插入到最后一个孩子后面，或者直接插在父节点后面\n            var insertId = pMap[pId] && pMap[pId][pMap[pId].length - 1] || pId;\n            $('#' + insertId, $treeTable).after($trs);\n            initRelation($trs);\n        };\n\n        return $treeTable;\n    };\n})(jQuery);\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/treeTable/themes/default/treeTable.css",
    "content": ".tree_table .default_node, .tree_table .default_active_node {width:16px;height:16px;border: medium none; margin: 0; padding: 0;display: inline-block;}\n.tree_table .default_active_node {cursor: pointer;}\n.tree_table .default_leaf{background:url(./allbgs.gif) no-repeat -16px 0px;width:16px;}\n.tree_table .default_last_leaf{background:url(./allbgs.gif) no-repeat -64px 0px;width:16px;}\n.tree_table .default_vertline{background:url(./allbgs.gif) no-repeat -32px 0px;width:16px;}\n.tree_table .default_open, .tree_table .default_hover_open{background:url(./allbgs.gif) no-repeat 0px 0px;width:16px;}\n.tree_table .default_shut, .tree_table .default_hover_shut{background:url(./allbgs.gif) no-repeat -48px 0px;width:16px;}\n.tree_table .default_last_shut, .tree_table .default_hover_last_shut{background:url(./allbgs.gif) no-repeat -96px 0px;width:16px;}\n.tree_table .default_last_open, .tree_table .default_hover_last_open{background:url(./allbgs.gif) no-repeat -112px 0px;width:16px;}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/treeTable/themes/vsStyle/treeTable.css",
    "content": ".tree_table .default_node, .tree_table .default_active_node {width:16px;height:16px;border: medium none; margin: 0; padding: 0;display: inline-block;}\n.tree_table .default_active_node {cursor: pointer;}\n.tree_table .default_open, .tree_table .default_last_open{background:url(./allbgs.gif) no-repeat 0px 1px;width:16px;}\n.tree_table .default_shut, .tree_table .default_last_shut{background:url(./allbgs.gif) no-repeat -16px 1px;width:16px;}\n.tree_table .default_hover_open, .tree_table .default_hover_last_open{background:url(./allbgs.gif) no-repeat -32px 1px;width:16px;}\n.tree_table .default_hover_shut, .tree_table .default_hover_last_shut{background:url(./allbgs.gif) no-repeat -48px 1px;width:16px;}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/wangEditor/wangEditor-fullscreen-plugin.css",
    "content": "@CHARSET \"UTF-8\";\n\n.w-e-toolbar {\n\tflex-wrap: wrap;\n\t-webkit-box-lines: multiple;\n}\n\n.w-e-toolbar .w-e-menu:hover{\n\tz-index: 10002!important;\n}\n\n.w-e-menu a {\n\ttext-decoration: none;\n}\n\n.fullscreen-editor {\n\tposition: fixed !important;\n\twidth: 100% !important;\n\theight: 100% !important;\n\tleft: 0px !important;\n\ttop: 0px !important;\n\tbackground-color: white;\n\tz-index: 9999;\n}\n\n.fullscreen-editor .w-e-text-container {\n\twidth: 100% !important;\n\theight: 95% !important;\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/wangEditor/wangEditor-fullscreen-plugin.js",
    "content": "/**\n * \n */\nwindow.wangEditor.fullscreen = {\n\t// editor create之后调用\n\tinit: function(editorSelector){\n\t\t$(editorSelector + \" .w-e-toolbar\").append('<div class=\"w-e-menu\"><a class=\"_wangEditor_btn_fullscreen\" href=\"###\" onclick=\"window.wangEditor.fullscreen.toggleFullscreen(\\'' + editorSelector + '\\')\">全屏</a></div>');\n\t},\n\ttoggleFullscreen: function(editorSelector){\n\t\t$(editorSelector).toggleClass('fullscreen-editor');\n\t\tif($(editorSelector + ' ._wangEditor_btn_fullscreen').text() == '全屏'){\n\t\t\t$(editorSelector + ' ._wangEditor_btn_fullscreen').text('退出全屏');\n\t\t}else{\n\t\t\t$(editorSelector + ' ._wangEditor_btn_fullscreen').text('全屏');\n\t\t}\n\t}\n};"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/wangEditor/wangEditor.css",
    "content": ".w-e-toolbar,\n.w-e-text-container,\n.w-e-menu-panel {\n  padding: 0;\n  margin: 0;\n  box-sizing: border-box;\n}\n.w-e-toolbar *,\n.w-e-text-container *,\n.w-e-menu-panel * {\n  padding: 0;\n  margin: 0;\n  box-sizing: border-box;\n}\n.w-e-clear-fix:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n\n.w-e-toolbar .w-e-droplist {\n  position: absolute;\n  left: 0;\n  top: 0;\n  background-color: #fff;\n  border: 1px solid #f1f1f1;\n  border-right-color: #ccc;\n  border-bottom-color: #ccc;\n}\n.w-e-toolbar .w-e-droplist .w-e-dp-title {\n  text-align: center;\n  color: #999;\n  line-height: 2;\n  border-bottom: 1px solid #f1f1f1;\n  font-size: 13px;\n}\n.w-e-toolbar .w-e-droplist ul.w-e-list {\n  list-style: none;\n  line-height: 1;\n}\n.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item {\n  color: #333;\n  padding: 5px 0;\n}\n.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item:hover {\n  background-color: #f1f1f1;\n}\n.w-e-toolbar .w-e-droplist ul.w-e-block {\n  list-style: none;\n  text-align: left;\n  padding: 5px;\n}\n.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n  padding: 3px 5px;\n}\n.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item:hover {\n  background-color: #f1f1f1;\n}\n\n@font-face {\n  font-family: 'w-e-icon';\n  src: url(data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAABXAAAsAAAAAFXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIPAmNtYXAAAAFoAAAA9AAAAPRAxxN6Z2FzcAAAAlwAAAAIAAAACAAAABBnbHlmAAACZAAAEHwAABB8kRGt5WhlYWQAABLgAAAANgAAADYN4rlyaGhlYQAAExgAAAAkAAAAJAfEA99obXR4AAATPAAAAHwAAAB8cAcDvGxvY2EAABO4AAAAQAAAAEAx8jYEbWF4cAAAE/gAAAAgAAAAIAAqALZuYW1lAAAUGAAAAYYAAAGGmUoJ+3Bvc3QAABWgAAAAIAAAACAAAwAAAAMD3AGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA8fwDwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEANgAAAAyACAABAASAAEAIOkG6Q3pEulH6Wbpd+m56bvpxunL6d/qDepl6mjqcep58A3wFPEg8dzx/P/9//8AAAAAACDpBukN6RLpR+ll6Xfpuem76cbpy+nf6g3qYupo6nHqd/AN8BTxIPHc8fz//f//AAH/4xb+FvgW9BbAFqMWkxZSFlEWRxZDFjAWAxWvFa0VpRWgEA0QBw78DkEOIgADAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAPAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAIAAP/ABAADwAAEABMAAAE3AScBAy4BJxM3ASMBAyUBNQEHAYCAAcBA/kCfFzsyY4ABgMD+gMACgAGA/oBOAUBAAcBA/kD+nTI7FwERTgGA/oD9gMABgMD+gIAABAAAAAAEAAOAABAAIQAtADQAAAE4ATEROAExITgBMRE4ATEhNSEiBhURFBYzITI2NRE0JiMHFAYjIiY1NDYzMhYTITUTATM3A8D8gAOA/IAaJiYaA4AaJiYagDgoKDg4KCg4QP0A4AEAQOADQP0AAwBAJhr9ABomJhoDABom4Cg4OCgoODj9uIABgP7AwAAAAgAAAEAEAANAACgALAAAAS4DIyIOAgcOAxUUHgIXHgMzMj4CNz4DNTQuAicBEQ0BA9U2cXZ5Pz95dnE2Cw8LBgYLDws2cXZ5Pz95dnE2Cw8LBgYLDwv9qwFA/sADIAgMCAQECAwIKVRZWy8vW1lUKQgMCAQECAwIKVRZWy8vW1lUKf3gAYDAwAAAAAACAMD/wANAA8AAEwAfAAABIg4CFRQeAjEwPgI1NC4CAyImNTQ2MzIWFRQGAgBCdVcyZHhkZHhkMld1QlBwcFBQcHADwDJXdUJ4+syCgsz6eEJ1VzL+AHBQUHBwUFBwAAABAAAAAAQAA4AAIQAAASIOAgcnESEnPgEzMh4CFRQOAgcXPgM1NC4CIwIANWRcUiOWAYCQNYtQUItpPBIiMB5VKEAtGFCLu2oDgBUnNyOW/oCQNDw8aYtQK1FJQRpgI1ZibDlqu4tQAAEAAAAABAADgAAgAAATFB4CFzcuAzU0PgIzMhYXByERBy4DIyIOAgAYLUAoVR4wIhI8aYtQUIs1kAGAliNSXGQ1aruLUAGAOWxiViNgGkFJUStQi2k8PDSQAYCWIzcnFVCLuwACAAAAQAQBAwAAHgA9AAATMh4CFRQOAiMiLgI1JzQ+AjMVIgYHDgEHPgEhMh4CFRQOAiMiLgI1JzQ+AjMVIgYHDgEHPgHhLlI9IyM9Ui4uUj0jAUZ6o11AdS0JEAcIEgJJLlI9IyM9Ui4uUj0jAUZ6o11AdS0JEAcIEgIAIz1SLi5SPSMjPVIuIF2jekaAMC4IEwoCASM9Ui4uUj0jIz1SLiBdo3pGgDAuCBMKAgEAAAYAQP/ABAADwAADAAcACwARAB0AKQAAJSEVIREhFSERIRUhJxEjNSM1ExUzFSM1NzUjNTMVFREjNTM1IzUzNSM1AYACgP2AAoD9gAKA/YDAQEBAgMCAgMDAgICAgICAAgCAAgCAwP8AwED98jJAkjwyQJLu/sBAQEBAQAAGAAD/wAQAA8AAAwAHAAsAFwAjAC8AAAEhFSERIRUhESEVIQE0NjMyFhUUBiMiJhE0NjMyFhUUBiMiJhE0NjMyFhUUBiMiJgGAAoD9gAKA/YACgP2A/oBLNTVLSzU1S0s1NUtLNTVLSzU1S0s1NUsDgID/AID/AIADQDVLSzU1S0v+tTVLSzU1S0v+tTVLSzU1S0sAAwAAAAAEAAOgAAMADQAUAAA3IRUhJRUhNRMhFSE1ISUJASMRIxEABAD8AAQA/ACAAQABAAEA/WABIAEg4IBAQMBAQAEAgIDAASD+4P8AAQAAAAAAAgBT/8wDrQO0AC8AXAAAASImJy4BNDY/AT4BMzIWFx4BFAYPAQYiJyY0PwE2NCcuASMiBg8BBhQXFhQHDgEjAyImJy4BNDY/ATYyFxYUDwEGFBceATMyNj8BNjQnJjQ3NjIXHgEUBg8BDgEjAbgKEwgjJCQjwCNZMTFZIyMkJCNYDywPDw9YKSkUMxwcMxTAKSkPDwgTCrgxWSMjJCQjWA8sDw8PWCkpFDMcHDMUwCkpDw8PKxAjJCQjwCNZMQFECAckWl5aJMAiJSUiJFpeWiRXEBAPKw9YKXQpFBUVFMApdCkPKxAHCP6IJSIkWl5aJFcQEA8rD1gpdCkUFRUUwCl0KQ8rEA8PJFpeWiTAIiUAAAAABQAA/8AEAAPAABMAJwA7AEcAUwAABTI+AjU0LgIjIg4CFRQeAhMyHgIVFA4CIyIuAjU0PgITMj4CNw4DIyIuAiceAyc0NjMyFhUUBiMiJiU0NjMyFhUUBiMiJgIAaruLUFCLu2pqu4tQUIu7alaYcUFBcZhWVphxQUFxmFYrVVFMIwU3Vm8/P29WNwUjTFFV1SUbGyUlGxslAYAlGxslJRsbJUBQi7tqaruLUFCLu2pqu4tQA6BBcZhWVphxQUFxmFZWmHFB/gkMFSAUQ3RWMTFWdEMUIBUM9yg4OCgoODgoKDg4KCg4OAAAAAADAAD/wAQAA8AAEwAnADMAAAEiDgIVFB4CMzI+AjU0LgIDIi4CNTQ+AjMyHgIVFA4CEwcnBxcHFzcXNyc3AgBqu4tQUIu7amq7i1BQi7tqVphxQUFxmFZWmHFBQXGYSqCgYKCgYKCgYKCgA8BQi7tqaruLUFCLu2pqu4tQ/GBBcZhWVphxQUFxmFZWmHFBAqCgoGCgoGCgoGCgoAADAMAAAANAA4AAEgAbACQAAAE+ATU0LgIjIREhMj4CNTQmATMyFhUUBisBEyMRMzIWFRQGAsQcIChGXTX+wAGANV1GKET+hGUqPDwpZp+fnyw+PgHbIlQvNV1GKPyAKEZdNUZ0AUZLNTVL/oABAEs1NUsAAAIAwAAAA0ADgAAbAB8AAAEzERQOAiMiLgI1ETMRFBYXHgEzMjY3PgE1ASEVIQLAgDJXdUJCdVcygBsYHEkoKEkcGBv+AAKA/YADgP5gPGlOLS1OaTwBoP5gHjgXGBsbGBc4Hv6ggAAAAQCAAAADgAOAAAsAAAEVIwEzFSE1MwEjNQOAgP7AgP5AgAFAgAOAQP0AQEADAEAAAQAAAAAEAAOAAD0AAAEVIx4BFRQGBw4BIyImJy4BNTMUFjMyNjU0JiMhNSEuAScuATU0Njc+ATMyFhceARUjNCYjIgYVFBYzMhYXBADrFRY1MCxxPj5xLDA1gHJOTnJyTv4AASwCBAEwNTUwLHE+PnEsMDWAck5OcnJOO24rAcBAHUEiNWIkISQkISRiNTRMTDQ0TEABAwEkYjU1YiQhJCQhJGI1NExMNDRMIR8AAAAHAAD/wAQAA8AAAwAHAAsADwATABsAIwAAEzMVIzczFSMlMxUjNzMVIyUzFSMDEyETMxMhEwEDIQMjAyEDAICAwMDAAQCAgMDAwAEAgIAQEP0AECAQAoAQ/UAQAwAQIBD9gBABwEBAQEBAQEBAQAJA/kABwP6AAYD8AAGA/oABQP7AAAAKAAAAAAQAA4AAAwAHAAsADwATABcAGwAfACMAJwAAExEhEQE1IRUdASE1ARUhNSMVITURIRUhJSEVIRE1IRUBIRUhITUhFQAEAP2AAQD/AAEA/wBA/wABAP8AAoABAP8AAQD8gAEA/wACgAEAA4D8gAOA/cDAwEDAwAIAwMDAwP8AwMDAAQDAwP7AwMDAAAAFAAAAAAQAA4AAAwAHAAsADwATAAATIRUhFSEVIREhFSERIRUhESEVIQAEAPwAAoD9gAKA/YAEAPwABAD8AAOAgECA/wCAAUCA/wCAAAAAAAUAAAAABAADgAADAAcACwAPABMAABMhFSEXIRUhESEVIQMhFSERIRUhAAQA/ADAAoD9gAKA/YDABAD8AAQA/AADgIBAgP8AgAFAgP8AgAAABQAAAAAEAAOAAAMABwALAA8AEwAAEyEVIQUhFSERIRUhASEVIREhFSEABAD8AAGAAoD9gAKA/YD+gAQA/AAEAPwAA4CAQID/AIABQID/AIAAAAAAAQA/AD8C5gLmACwAACUUDwEGIyIvAQcGIyIvASY1ND8BJyY1ND8BNjMyHwE3NjMyHwEWFRQPARcWFQLmEE4QFxcQqKgQFxYQThAQqKgQEE4QFhcQqKgQFxcQThAQqKgQwxYQThAQqKgQEE4QFhcQqKgQFxcQThAQqKgQEE4QFxcQqKgQFwAAAAYAAAAAAyUDbgAUACgAPABNAFUAggAAAREUBwYrASInJjURNDc2OwEyFxYVMxEUBwYrASInJjURNDc2OwEyFxYXERQHBisBIicmNRE0NzY7ATIXFhMRIREUFxYXFjMhMjc2NzY1ASEnJicjBgcFFRQHBisBERQHBiMhIicmNREjIicmPQE0NzY7ATc2NzY7ATIXFh8BMzIXFhUBJQYFCCQIBQYGBQgkCAUGkgUFCCUIBQUFBQglCAUFkgUFCCUIBQUFBQglCAUFSf4ABAQFBAIB2wIEBAQE/oABABsEBrUGBAH3BgUINxobJv4lJhsbNwgFBQUFCLEoCBcWF7cXFhYJKLAIBQYCEv63CAUFBQUIAUkIBQYGBQj+twgFBQUFCAFJCAUGBgUI/rcIBQUFBQgBSQgFBgYF/lsCHf3jDQsKBQUFBQoLDQJmQwUCAgVVJAgGBf3jMCIjISIvAiAFBggkCAUFYBUPDw8PFWAFBQgAAgAHAEkDtwKvABoALgAACQEGIyIvASY1ND8BJyY1ND8BNjMyFwEWFRQHARUUBwYjISInJj0BNDc2MyEyFxYBTv72BgcIBR0GBuHhBgYdBQgHBgEKBgYCaQUFCP3bCAUFBQUIAiUIBQUBhf72BgYcBggHBuDhBgcHBh0FBf71BQgHBv77JQgFBQUFCCUIBQUFBQAAAAEAIwAAA90DbgCzAAAlIicmIyIHBiMiJyY1NDc2NzY3Njc2PQE0JyYjISIHBh0BFBcWFxYzFhcWFRQHBiMiJyYjIgcGIyInJjU0NzY3Njc2NzY9ARE0NTQ1NCc0JyYnJicmJyYnJiMiJyY1NDc2MzIXFjMyNzYzMhcWFRQHBiMGBwYHBh0BFBcWMyEyNzY9ATQnJicmJyY1NDc2MzIXFjMyNzYzMhcWFRQHBgciBwYHBhURFBcWFxYXMhcWFRQHBiMDwRkzMhoZMjMZDQgHCQoNDBEQChIBBxX+fhYHARUJEhMODgwLBwcOGzU1GhgxMRgNBwcJCQsMEA8JEgECAQIDBAQFCBIRDQ0KCwcHDho1NRoYMDEYDgcHCQoMDRAQCBQBBw8BkA4HARQKFxcPDgcHDhkzMhkZMTEZDgcHCgoNDRARCBQUCRERDg0KCwcHDgACAgICDAsPEQkJAQEDAwUMROAMBQMDBQzUUQ0GAQIBCAgSDwwNAgICAgwMDhEICQECAwMFDUUhAdACDQ0ICA4OCgoLCwcHAwYBAQgIEg8MDQICAgINDA8RCAgBAgEGDFC2DAcBAQcMtlAMBgEBBgcWDwwNAgICAg0MDxEICAEBAgYNT/3mRAwGAgIBCQgRDwwNAAACAAD/twP/A7cAEwA5AAABMhcWFRQHAgcGIyInJjU0NwE2MwEWFxYfARYHBiMiJyYnJicmNRYXFhcWFxYzMjc2NzY3Njc2NzY3A5soHh4avkw3RUg0NDUBbSEp/fgXJicvAQJMTHtHNjYhIRARBBMUEBASEQkXCA8SExUVHR0eHikDtxsaKCQz/plGNDU0SUkwAUsf/bErHx8NKHpNTBobLi86OkQDDw4LCwoKFiUbGhERCgsEBAIAAQAAAAAAANox8glfDzz1AAsEAAAAAADVYbp/AAAAANVhun8AAP+3BAEDwAAAAAgAAgAAAAAAAAABAAADwP/AAAAEAAAA//8EAQABAAAAAAAAAAAAAAAAAAAAHwQAAAAAAAAAAAAAAAIAAAAEAAAABAAAAAQAAAAEAADABAAAAAQAAAAEAAAABAAAQAQAAAAEAAAABAAAUwQAAAAEAAAABAAAwAQAAMAEAACABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAyUAPwMlAAADvgAHBAAAIwP/AAAAAAAAAAoAFAAeAEwAlADaAQoBPgFwAcgCBgJQAnoDBAN6A8gEAgQ2BE4EpgToBTAFWAWABaoF7gamBvAH4gg+AAEAAAAfALQACgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAHAAAAAQAAAAAAAgAHAGAAAQAAAAAAAwAHADYAAQAAAAAABAAHAHUAAQAAAAAABQALABUAAQAAAAAABgAHAEsAAQAAAAAACgAaAIoAAwABBAkAAQAOAAcAAwABBAkAAgAOAGcAAwABBAkAAwAOAD0AAwABBAkABAAOAHwAAwABBAkABQAWACAAAwABBAkABgAOAFIAAwABBAkACgA0AKRpY29tb29uAGkAYwBvAG0AbwBvAG5WZXJzaW9uIDEuMABWAGUAcgBzAGkAbwBuACAAMQAuADBpY29tb29uAGkAYwBvAG0AbwBvAG5pY29tb29uAGkAYwBvAG0AbwBvAG5SZWd1bGFyAFIAZQBnAHUAbABhAHJpY29tb29uAGkAYwBvAG0AbwBvAG5Gb250IGdlbmVyYXRlZCBieSBJY29Nb29uLgBGAG8AbgB0ACAAZwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAC4AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format('truetype');\n  font-weight: normal;\n  font-style: normal;\n}\n[class^=\"w-e-icon-\"],\n[class*=\" w-e-icon-\"] {\n  /* use !important to prevent issues with browser extensions that change fonts */\n  font-family: 'w-e-icon' !important;\n  speak: none;\n  font-style: normal;\n  font-weight: normal;\n  font-variant: normal;\n  text-transform: none;\n  line-height: 1;\n  /* Better Font Rendering =========== */\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n.w-e-icon-close:before {\n  content: \"\\f00d\";\n}\n.w-e-icon-upload2:before {\n  content: \"\\e9c6\";\n}\n.w-e-icon-trash-o:before {\n  content: \"\\f014\";\n}\n.w-e-icon-header:before {\n  content: \"\\f1dc\";\n}\n.w-e-icon-pencil2:before {\n  content: \"\\e906\";\n}\n.w-e-icon-paint-brush:before {\n  content: \"\\f1fc\";\n}\n.w-e-icon-image:before {\n  content: \"\\e90d\";\n}\n.w-e-icon-play:before {\n  content: \"\\e912\";\n}\n.w-e-icon-location:before {\n  content: \"\\e947\";\n}\n.w-e-icon-undo:before {\n  content: \"\\e965\";\n}\n.w-e-icon-redo:before {\n  content: \"\\e966\";\n}\n.w-e-icon-quotes-left:before {\n  content: \"\\e977\";\n}\n.w-e-icon-list-numbered:before {\n  content: \"\\e9b9\";\n}\n.w-e-icon-list2:before {\n  content: \"\\e9bb\";\n}\n.w-e-icon-link:before {\n  content: \"\\e9cb\";\n}\n.w-e-icon-happy:before {\n  content: \"\\e9df\";\n}\n.w-e-icon-bold:before {\n  content: \"\\ea62\";\n}\n.w-e-icon-underline:before {\n  content: \"\\ea63\";\n}\n.w-e-icon-italic:before {\n  content: \"\\ea64\";\n}\n.w-e-icon-strikethrough:before {\n  content: \"\\ea65\";\n}\n.w-e-icon-table2:before {\n  content: \"\\ea71\";\n}\n.w-e-icon-paragraph-left:before {\n  content: \"\\ea77\";\n}\n.w-e-icon-paragraph-center:before {\n  content: \"\\ea78\";\n}\n.w-e-icon-paragraph-right:before {\n  content: \"\\ea79\";\n}\n.w-e-icon-terminal:before {\n  content: \"\\f120\";\n}\n.w-e-icon-page-break:before {\n  content: \"\\ea68\";\n}\n.w-e-icon-cancel-circle:before {\n  content: \"\\ea0d\";\n}\n\n.w-e-toolbar {\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  padding: 0 5px;\n  /* flex-wrap: wrap; */\n  /* 单个菜单 */\n}\n.w-e-toolbar .w-e-menu {\n  position: relative;\n  text-align: center;\n  padding: 5px 10px;\n  cursor: pointer;\n}\n.w-e-toolbar .w-e-menu i {\n  color: #999;\n}\n.w-e-toolbar .w-e-menu:hover i {\n  color: #333;\n}\n.w-e-toolbar .w-e-active i {\n  color: #1e88e5;\n}\n.w-e-toolbar .w-e-active:hover i {\n  color: #1e88e5;\n}\n\n.w-e-text-container .w-e-panel-container {\n  position: absolute;\n  top: 0;\n  left: 50%;\n  border: 1px solid #ccc;\n  border-top: 0;\n  box-shadow: 1px 1px 2px #ccc;\n  color: #333;\n  background-color: #fff;\n  /* 为 emotion panel 定制的样式 */\n  /* 上传图片的 panel 定制样式 */\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-close {\n  position: absolute;\n  right: 0;\n  top: 0;\n  padding: 5px;\n  margin: 2px 5px 0 0;\n  cursor: pointer;\n  color: #999;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-close:hover {\n  color: #333;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-title {\n  list-style: none;\n  display: -webkit-box;\n  display: -ms-flexbox;\n  display: flex;\n  font-size: 14px;\n  margin: 2px 10px 0 10px;\n  border-bottom: 1px solid #f1f1f1;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-item {\n  padding: 3px 5px;\n  color: #999;\n  cursor: pointer;\n  margin: 0 3px;\n  position: relative;\n  top: 1px;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-active {\n  color: #333;\n  border-bottom: 1px solid #333;\n  cursor: default;\n  font-weight: 700;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content {\n  padding: 10px 15px 10px 15px;\n  font-size: 16px;\n  /* 输入框的样式 */\n  /* 按钮的样式 */\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input:focus,\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus,\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content button:focus {\n  outline: none;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea {\n  width: 100%;\n  border: 1px solid #ccc;\n  padding: 5px;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus {\n  border-color: #1e88e5;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text] {\n  border: none;\n  border-bottom: 1px solid #ccc;\n  font-size: 14px;\n  height: 20px;\n  color: #333;\n  text-align: left;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].small {\n  width: 30px;\n  text-align: center;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].block {\n  display: block;\n  width: 100%;\n  margin: 10px 0;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text]:focus {\n  border-bottom: 2px solid #1e88e5;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button {\n  font-size: 14px;\n  color: #1e88e5;\n  border: none;\n  padding: 5px 10px;\n  background-color: #fff;\n  cursor: pointer;\n  border-radius: 3px;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.left {\n  float: left;\n  margin-right: 10px;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.right {\n  float: right;\n  margin-left: 10px;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.gray {\n  color: #999;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.red {\n  color: #c24f4a;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button:hover {\n  background-color: #f1f1f1;\n}\n.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container:after {\n  content: \"\";\n  display: table;\n  clear: both;\n}\n.w-e-text-container .w-e-panel-container .w-e-emoticon-container .w-e-item {\n  cursor: pointer;\n  font-size: 18px;\n  padding: 0 3px;\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n}\n.w-e-text-container .w-e-panel-container .w-e-up-img-container {\n  text-align: center;\n}\n.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n  color: #999;\n  cursor: pointer;\n  font-size: 60px;\n  line-height: 1;\n}\n.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn:hover {\n  color: #333;\n}\n\n.w-e-text-container {\n  position: relative;\n}\n.w-e-text-container .w-e-progress {\n  position: absolute;\n  background-color: #1e88e5;\n  bottom: 0;\n  left: 0;\n  height: 1px;\n}\n.w-e-text {\n  padding: 0 10px;\n  overflow-y: scroll;\n}\n.w-e-text p,\n.w-e-text h1,\n.w-e-text h2,\n.w-e-text h3,\n.w-e-text h4,\n.w-e-text h5,\n.w-e-text table,\n.w-e-text pre {\n  margin: 10px 0;\n  line-height: 1.5;\n}\n.w-e-text ul,\n.w-e-text ol {\n  margin: 10px 0 10px 20px;\n}\n.w-e-text blockquote {\n  display: block;\n  border-left: 8px solid #d0e5f2;\n  padding: 5px 10px;\n  margin: 10px 0;\n  line-height: 1.4;\n  font-size: 100%;\n  background-color: #f1f1f1;\n}\n.w-e-text code {\n  display: inline-block;\n  *display: inline;\n  *zoom: 1;\n  background-color: #f1f1f1;\n  border-radius: 3px;\n  padding: 3px 5px;\n  margin: 0 3px;\n}\n.w-e-text pre code {\n  display: block;\n}\n.w-e-text table {\n  border-top: 1px solid #ccc;\n  border-left: 1px solid #ccc;\n}\n.w-e-text table td,\n.w-e-text table th {\n  border-bottom: 1px solid #ccc;\n  border-right: 1px solid #ccc;\n  padding: 3px 5px;\n}\n.w-e-text table th {\n  border-bottom: 2px solid #ccc;\n  text-align: center;\n}\n.w-e-text:focus {\n  outline: none;\n}\n.w-e-text img {\n  cursor: pointer;\n}\n.w-e-text img:hover {\n  box-shadow: 0 0 5px #333;\n}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/plugins/wangEditor/wangEditor.js",
    "content": "(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(global.wangEditor = factory());\n}(this, (function () { 'use strict';\n\n/*\n    poly-fill\n*/\n\nvar polyfill = function () {\n\n    // Object.assign\n    if (typeof Object.assign != 'function') {\n        Object.assign = function (target, varArgs) {\n            // .length of function is 2\n            if (target == null) {\n                // TypeError if undefined or null\n                throw new TypeError('Cannot convert undefined or null to object');\n            }\n\n            var to = Object(target);\n\n            for (var index = 1; index < arguments.length; index++) {\n                var nextSource = arguments[index];\n\n                if (nextSource != null) {\n                    // Skip over if undefined or null\n                    for (var nextKey in nextSource) {\n                        // Avoid bugs when hasOwnProperty is shadowed\n                        if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n                            to[nextKey] = nextSource[nextKey];\n                        }\n                    }\n                }\n            }\n            return to;\n        };\n    }\n\n    // IE 中兼容 Element.prototype.matches\n    if (!Element.prototype.matches) {\n        Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function (s) {\n            var matches = (this.document || this.ownerDocument).querySelectorAll(s),\n                i = matches.length;\n            while (--i >= 0 && matches.item(i) !== this) {}\n            return i > -1;\n        };\n    }\n};\n\n/*\n    DOM 操作 API\n*/\n\n// 根据 html 代码片段创建 dom 对象\nfunction createElemByHTML(html) {\n    var div = void 0;\n    div = document.createElement('div');\n    div.innerHTML = html;\n    return div.children;\n}\n\n// 是否是 DOM List\nfunction isDOMList(selector) {\n    if (!selector) {\n        return false;\n    }\n    if (selector instanceof HTMLCollection || selector instanceof NodeList) {\n        return true;\n    }\n    return false;\n}\n\n// 封装 document.querySelectorAll\nfunction querySelectorAll(selector) {\n    var result = document.querySelectorAll(selector);\n    if (isDOMList(result)) {\n        return result;\n    } else {\n        return [result];\n    }\n}\n\n// 记录所有的事件绑定\nvar eventList = [];\n\n// 创建构造函数\nfunction DomElement(selector) {\n    if (!selector) {\n        return;\n    }\n\n    // selector 本来就是 DomElement 对象，直接返回\n    if (selector instanceof DomElement) {\n        return selector;\n    }\n\n    this.selector = selector;\n    var nodeType = selector.nodeType;\n\n    // 根据 selector 得出的结果（如 DOM，DOM List）\n    var selectorResult = [];\n    if (nodeType === 9) {\n        // document 节点\n        selectorResult = [selector];\n    } else if (nodeType === 1) {\n        // 单个 DOM 节点\n        selectorResult = [selector];\n    } else if (isDOMList(selector) || selector instanceof Array) {\n        // DOM List 或者数组\n        selectorResult = selector;\n    } else if (typeof selector === 'string') {\n        // 字符串\n        selector = selector.replace('/\\n/mg', '').trim();\n        if (selector.indexOf('<') === 0) {\n            // 如 <div>\n            selectorResult = createElemByHTML(selector);\n        } else {\n            // 如 #id .class\n            selectorResult = querySelectorAll(selector);\n        }\n    }\n\n    var length = selectorResult.length;\n    if (!length) {\n        // 空数组\n        return this;\n    }\n\n    // 加入 DOM 节点\n    var i = void 0;\n    for (i = 0; i < length; i++) {\n        this[i] = selectorResult[i];\n    }\n    this.length = length;\n}\n\n// 修改原型\nDomElement.prototype = {\n    constructor: DomElement,\n\n    // 类数组，forEach\n    forEach: function forEach(fn) {\n        var i = void 0;\n        for (i = 0; i < this.length; i++) {\n            var elem = this[i];\n            var result = fn.call(elem, elem, i);\n            if (result === false) {\n                break;\n            }\n        }\n        return this;\n    },\n\n    // clone\n    clone: function clone(deep) {\n        var cloneList = [];\n        this.forEach(function (elem) {\n            cloneList.push(elem.cloneNode(!!deep));\n        });\n        return $(cloneList);\n    },\n\n    // 获取第几个元素\n    get: function get(index) {\n        var length = this.length;\n        if (index >= length) {\n            index = index % length;\n        }\n        return $(this[index]);\n    },\n\n    // 第一个\n    first: function first() {\n        return this.get(0);\n    },\n\n    // 最后一个\n    last: function last() {\n        var length = this.length;\n        return this.get(length - 1);\n    },\n\n    // 绑定事件\n    on: function on(type, selector, fn) {\n        // selector 不为空，证明绑定事件要加代理\n        if (!fn) {\n            fn = selector;\n            selector = null;\n        }\n\n        // type 是否有多个\n        var types = [];\n        types = type.split(/\\s+/);\n\n        return this.forEach(function (elem) {\n            types.forEach(function (type) {\n                if (!type) {\n                    return;\n                }\n\n                // 记录下，方便后面解绑\n                eventList.push({\n                    elem: elem,\n                    type: type,\n                    fn: fn\n                });\n\n                if (!selector) {\n                    // 无代理\n                    elem.addEventListener(type, fn);\n                    return;\n                }\n\n                // 有代理\n                elem.addEventListener(type, function (e) {\n                    var target = e.target;\n                    if (target.matches(selector)) {\n                        fn.call(target, e);\n                    }\n                });\n            });\n        });\n    },\n\n    // 取消事件绑定\n    off: function off(type, fn) {\n        return this.forEach(function (elem) {\n            elem.removeEventListener(type, fn);\n        });\n    },\n\n    // 获取/设置 属性\n    attr: function attr(key, val) {\n        if (val == null) {\n            // 获取值\n            return this[0].getAttribute(key);\n        } else {\n            // 设置值\n            return this.forEach(function (elem) {\n                elem.setAttribute(key, val);\n            });\n        }\n    },\n\n    // 添加 class\n    addClass: function addClass(className) {\n        if (!className) {\n            return this;\n        }\n        return this.forEach(function (elem) {\n            var arr = void 0;\n            if (elem.className) {\n                // 解析当前 className 转换为数组\n                arr = elem.className.split(/\\s/);\n                arr = arr.filter(function (item) {\n                    return !!item.trim();\n                });\n                // 添加 class\n                if (arr.indexOf(className) < 0) {\n                    arr.push(className);\n                }\n                // 修改 elem.class\n                elem.className = arr.join(' ');\n            } else {\n                elem.className = className;\n            }\n        });\n    },\n\n    // 删除 class\n    removeClass: function removeClass(className) {\n        if (!className) {\n            return this;\n        }\n        return this.forEach(function (elem) {\n            var arr = void 0;\n            if (elem.className) {\n                // 解析当前 className 转换为数组\n                arr = elem.className.split(/\\s/);\n                arr = arr.filter(function (item) {\n                    item = item.trim();\n                    // 删除 class\n                    if (!item || item === className) {\n                        return false;\n                    }\n                    return true;\n                });\n                // 修改 elem.class\n                elem.className = arr.join(' ');\n            }\n        });\n    },\n\n    // 修改 css\n    css: function css(key, val) {\n        var currentStyle = key + ':' + val + ';';\n        return this.forEach(function (elem) {\n            var style = (elem.getAttribute('style') || '').trim();\n            var styleArr = void 0,\n                resultArr = [];\n            if (style) {\n                // 将 style 按照 ; 拆分为数组\n                styleArr = style.split(';');\n                styleArr.forEach(function (item) {\n                    // 对每项样式，按照 : 拆分为 key 和 value\n                    var arr = item.split(':').map(function (i) {\n                        return i.trim();\n                    });\n                    if (arr.length === 2) {\n                        resultArr.push(arr[0] + ':' + arr[1]);\n                    }\n                });\n                // 替换或者新增\n                resultArr = resultArr.map(function (item) {\n                    if (item.indexOf(key) === 0) {\n                        return currentStyle;\n                    } else {\n                        return item;\n                    }\n                });\n                if (resultArr.indexOf(currentStyle) < 0) {\n                    resultArr.push(currentStyle);\n                }\n                // 结果\n                elem.setAttribute('style', resultArr.join('; '));\n            } else {\n                // style 无值\n                elem.setAttribute('style', currentStyle);\n            }\n        });\n    },\n\n    // 显示\n    show: function show() {\n        return this.css('display', 'block');\n    },\n\n    // 隐藏\n    hide: function hide() {\n        return this.css('display', 'none');\n    },\n\n    // 获取子节点\n    children: function children() {\n        var elem = this[0];\n        if (!elem) {\n            return null;\n        }\n\n        return $(elem.children);\n    },\n\n    // 获取子节点（包括文本节点）\n    childNodes: function childNodes() {\n        var elem = this[0];\n        if (!elem) {\n            return null;\n        }\n\n        return $(elem.childNodes);\n    },\n\n    // 增加子节点\n    append: function append($children) {\n        return this.forEach(function (elem) {\n            $children.forEach(function (child) {\n                elem.appendChild(child);\n            });\n        });\n    },\n\n    // 移除当前节点\n    remove: function remove() {\n        return this.forEach(function (elem) {\n            if (elem.remove) {\n                elem.remove();\n            } else {\n                var parent = elem.parentElement;\n                parent && parent.removeChild(elem);\n            }\n        });\n    },\n\n    // 是否包含某个子节点\n    isContain: function isContain($child) {\n        var elem = this[0];\n        var child = $child[0];\n        return elem.contains(child);\n    },\n\n    // 尺寸数据\n    getSizeData: function getSizeData() {\n        var elem = this[0];\n        return elem.getBoundingClientRect(); // 可得到 bottom height left right top width 的数据\n    },\n\n    // 封装 nodeName\n    getNodeName: function getNodeName() {\n        var elem = this[0];\n        return elem.nodeName;\n    },\n\n    // 从当前元素查找\n    find: function find(selector) {\n        var elem = this[0];\n        return $(elem.querySelectorAll(selector));\n    },\n\n    // 获取当前元素的 text\n    text: function text(val) {\n        if (!val) {\n            // 获取 text\n            var elem = this[0];\n            return elem.innerHTML.replace(/<.*?>/g, function () {\n                return '';\n            });\n        } else {\n            // 设置 text\n            return this.forEach(function (elem) {\n                elem.innerHTML = val;\n            });\n        }\n    },\n\n    // 获取 html\n    html: function html(value) {\n        var elem = this[0];\n        if (value == null) {\n            return elem.innerHTML;\n        } else {\n            elem.innerHTML = value;\n            return this;\n        }\n    },\n\n    // 获取 value\n    val: function val() {\n        var elem = this[0];\n        return elem.value.trim();\n    },\n\n    // focus\n    focus: function focus() {\n        return this.forEach(function (elem) {\n            elem.focus();\n        });\n    },\n\n    // parent\n    parent: function parent() {\n        var elem = this[0];\n        return $(elem.parentElement);\n    },\n\n    // parentUntil 找到符合 selector 的父节点\n    parentUntil: function parentUntil(selector, _currentElem) {\n        var results = document.querySelectorAll(selector);\n        var length = results.length;\n        if (!length) {\n            // 传入的 selector 无效\n            return null;\n        }\n\n        var elem = _currentElem || this[0];\n        if (elem.nodeName === 'BODY') {\n            return null;\n        }\n\n        var parent = elem.parentElement;\n        var i = void 0;\n        for (i = 0; i < length; i++) {\n            if (parent === results[i]) {\n                // 找到，并返回\n                return $(parent);\n            }\n        }\n\n        // 继续查找\n        return this.parentUntil(selector, parent);\n    },\n\n    // 判断两个 elem 是否相等\n    equal: function equal($elem) {\n        if ($elem.nodeType === 1) {\n            return this[0] === $elem;\n        } else {\n            return this[0] === $elem[0];\n        }\n    },\n\n    // 将该元素插入到某个元素前面\n    insertBefore: function insertBefore(selector) {\n        var $referenceNode = $(selector);\n        var referenceNode = $referenceNode[0];\n        if (!referenceNode) {\n            return this;\n        }\n        return this.forEach(function (elem) {\n            var parent = referenceNode.parentNode;\n            parent.insertBefore(elem, referenceNode);\n        });\n    },\n\n    // 将该元素插入到某个元素后面\n    insertAfter: function insertAfter(selector) {\n        var $referenceNode = $(selector);\n        var referenceNode = $referenceNode[0];\n        if (!referenceNode) {\n            return this;\n        }\n        return this.forEach(function (elem) {\n            var parent = referenceNode.parentNode;\n            if (parent.lastChild === referenceNode) {\n                // 最后一个元素\n                parent.appendChild(elem);\n            } else {\n                // 不是最后一个元素\n                parent.insertBefore(elem, referenceNode.nextSibling);\n            }\n        });\n    }\n};\n\n// new 一个对象\nfunction $(selector) {\n    return new DomElement(selector);\n}\n\n// 解绑所有事件，用于销毁编辑器\n$.offAll = function () {\n    eventList.forEach(function (item) {\n        var elem = item.elem;\n        var type = item.type;\n        var fn = item.fn;\n        // 解绑\n        elem.removeEventListener(type, fn);\n    });\n};\n\n/*\n    配置信息\n*/\n\nvar config = {\n\n    // 默认菜单配置\n    menus: ['head', 'bold', 'italic', 'underline', 'strikeThrough', 'foreColor', 'backColor', 'link', 'list', 'justify', 'quote', 'emoticon', 'image', 'table', 'video', 'code', 'undo', 'redo'],\n\n    colors: ['#000000', '#eeece0', '#1c487f', '#4d80bf', '#c24f4a', '#8baa4a', '#7b5ba1', '#46acc8', '#f9963b', '#ffffff'],\n\n    // // 语言配置\n    // lang: {\n    //     '设置标题': 'title',\n    //     '正文': 'p',\n    //     '链接文字': 'link text',\n    //     '链接': 'link',\n    //     '插入': 'insert',\n    //     '创建': 'init'\n    // },\n\n    // 表情\n    emotions: [{\n        // tab 的标题\n        title: '默认',\n        // type -> 'emoji' / 'image'\n        type: 'image',\n        // content -> 数组\n        content: [{\n            alt: '[坏笑]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/50/pcmoren_huaixiao_org.png'\n        }, {\n            alt: '[舔屏]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/40/pcmoren_tian_org.png'\n        }, {\n            alt: '[污]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/3c/pcmoren_wu_org.png'\n        }, {\n            alt: '[允悲]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/2c/moren_yunbei_org.png'\n        }, {\n            alt: '[笑而不语]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/3a/moren_xiaoerbuyu_org.png'\n        }, {\n            alt: '[费解]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/3c/moren_feijie_org.png'\n        }, {\n            alt: '[憧憬]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/37/moren_chongjing_org.png'\n        }, {\n            alt: '[并不简单]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/fc/moren_bbjdnew_org.png'\n        }, {\n            alt: '[微笑]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/5c/huanglianwx_org.gif'\n        }, {\n            alt: '[酷]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/8a/pcmoren_cool2017_org.png'\n        }, {\n            alt: '[嘻嘻]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/0b/tootha_org.gif'\n        }, {\n            alt: '[哈哈]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/6a/laugh.gif'\n        }, {\n            alt: '[可爱]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/14/tza_org.gif'\n        }, {\n            alt: '[可怜]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/af/kl_org.gif'\n        }, {\n            alt: '[挖鼻]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/0b/wabi_org.gif'\n        }, {\n            alt: '[吃惊]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/f4/cj_org.gif'\n        }, {\n            alt: '[害羞]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/6e/shamea_org.gif'\n        }, {\n            alt: '[挤眼]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/c3/zy_org.gif'\n        }, {\n            alt: '[闭嘴]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/29/bz_org.gif'\n        }, {\n            alt: '[鄙视]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/71/bs2_org.gif'\n        }, {\n            alt: '[爱你]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/6d/lovea_org.gif'\n        }, {\n            alt: '[泪]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/9d/sada_org.gif'\n        }, {\n            alt: '[偷笑]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/19/heia_org.gif'\n        }, {\n            alt: '[亲亲]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/8f/qq_org.gif'\n        }, {\n            alt: '[生病]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/b6/sb_org.gif'\n        }, {\n            alt: '[太开心]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/58/mb_org.gif'\n        }, {\n            alt: '[白眼]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/d9/landeln_org.gif'\n        }, {\n            alt: '[右哼哼]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/98/yhh_org.gif'\n        }, {\n            alt: '[左哼哼]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/6d/zhh_org.gif'\n        }, {\n            alt: '[嘘]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/a6/x_org.gif'\n        }, {\n            alt: '[衰]',\n            src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/af/cry.gif'\n        }]\n    }, {\n        // tab 的标题\n        title: '新浪',\n        // type -> 'emoji' / 'image'\n        type: 'image',\n        // content -> 数组\n        content: [{\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/7a/shenshou_thumb.gif',\n            alt: '[草泥马]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/60/horse2_thumb.gif',\n            alt: '[神马]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/bc/fuyun_thumb.gif',\n            alt: '[浮云]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/c9/geili_thumb.gif',\n            alt: '[给力]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/f2/wg_thumb.gif',\n            alt: '[围观]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/70/vw_thumb.gif',\n            alt: '[威武]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/6e/panda_thumb.gif',\n            alt: '[熊猫]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/81/rabbit_thumb.gif',\n            alt: '[兔子]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/bc/otm_thumb.gif',\n            alt: '[奥特曼]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/15/j_thumb.gif',\n            alt: '[囧]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/89/hufen_thumb.gif',\n            alt: '[互粉]'\n        }, {\n            src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/c4/liwu_thumb.gif',\n            alt: '[礼物]'\n        }]\n    }, {\n        // tab 的标题\n        title: 'emoji',\n        // type -> 'emoji' / 'image'\n        type: 'emoji',\n        // content -> 数组\n        content: '😀 😃 😄 😁 😆 😅 😂 😊 😇 🙂 🙃 😉 😌 😍 😘 😗 😙 😚 😋 😜 😝 😛 🤑 🤗 🤓 😎 😏 😒 😞 😔 😟 😕 🙁  😣 😖 😫 😩 😤 😠 😡 😶 😐 😑 😯 😦 😧 😮 😲 😵 😳 😱 😨 😰 😢 😥 😭 😓 😪 😴 🙄 🤔 😬 🤐'.split(/\\s/)\n    }],\n\n    // 编辑区域的 z-index\n    zIndex: 10000,\n\n    // 是否开启 debug 模式（debug 模式下错误会 throw error 形式抛出）\n    debug: false,\n\n    // 插入链接时候的格式校验\n    linkCheck: function linkCheck(text, link) {\n        // text 是插入的文字\n        // link 是插入的链接\n        return true; // 返回 true 即表示成功\n        // return '校验失败' // 返回字符串即表示失败的提示信息\n    },\n\n    // 插入网络图片的校验\n    linkImgCheck: function linkImgCheck(src) {\n        // src 即图片的地址\n        return true; // 返回 true 即表示成功\n        // return '校验失败'  // 返回字符串即表示失败的提示信息\n    },\n\n    // 粘贴过滤样式，默认开启\n    pasteFilterStyle: true,\n\n    // 对粘贴的文字进行自定义处理，返回处理后的结果。编辑器会将处理后的结果粘贴到编辑区域中。\n    // IE 暂时不支持\n    pasteTextHandle: function pasteTextHandle(content) {\n        // content 即粘贴过来的内容（html 或 纯文本），可进行自定义处理然后返回\n        return content;\n    },\n\n    // onchange 事件\n    // onchange: function (html) {\n    //     // html 即变化之后的内容\n    //     console.log(html)\n    // },\n\n    // 是否显示添加网络图片的 tab\n    showLinkImg: true,\n\n    // 插入网络图片的回调\n    linkImgCallback: function linkImgCallback(url) {\n        // console.log(url)  // url 即插入图片的地址\n    },\n\n    // 默认上传图片 max size: 5M\n    uploadImgMaxSize: 5 * 1024 * 1024,\n\n    // 配置一次最多上传几个图片\n    // uploadImgMaxLength: 5,\n\n    // 上传图片，是否显示 base64 格式\n    uploadImgShowBase64: false,\n\n    // 上传图片，server 地址（如果有值，则 base64 格式的配置则失效）\n    // uploadImgServer: '/upload',\n\n    // 自定义配置 filename\n    uploadFileName: '',\n\n    // 上传图片的自定义参数\n    uploadImgParams: {\n        // token: 'abcdef12345'\n    },\n\n    // 上传图片的自定义header\n    uploadImgHeaders: {\n        // 'Accept': 'text/x-json'\n    },\n\n    // 配置 XHR withCredentials\n    withCredentials: false,\n\n    // 自定义上传图片超时时间 ms\n    uploadImgTimeout: 10000,\n\n    // 上传图片 hook \n    uploadImgHooks: {\n        // customInsert: function (insertLinkImg, result, editor) {\n        //     console.log('customInsert')\n        //     // 图片上传并返回结果，自定义插入图片的事件，而不是编辑器自动插入图片\n        //     consts data = result.data1 || []\n        //     data.forEach(link => {\n        //         insertLinkImg(link)\n        //     })\n        // },\n        before: function before(xhr, editor, files) {\n            // 图片上传之前触发\n\n            // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传\n            // return {\n            //     prevent: true,\n            //     msg: '放弃上传'\n            // }\n        },\n        success: function success(xhr, editor, result) {\n            // 图片上传并返回结果，图片插入成功之后触发\n        },\n        fail: function fail(xhr, editor, result) {\n            // 图片上传并返回结果，但图片插入错误时触发\n        },\n        error: function error(xhr, editor) {\n            // 图片上传出错时触发\n        },\n        timeout: function timeout(xhr, editor) {\n            // 图片上传超时时触发\n        }\n    },\n\n    // 是否上传七牛云，默认为 false\n    qiniu: false\n\n};\n\n/*\n    工具\n*/\n\n// 和 UA 相关的属性\nvar UA = {\n    _ua: navigator.userAgent,\n\n    // 是否 webkit\n    isWebkit: function isWebkit() {\n        var reg = /webkit/i;\n        return reg.test(this._ua);\n    },\n\n    // 是否 IE\n    isIE: function isIE() {\n        return 'ActiveXObject' in window;\n    }\n};\n\n// 遍历对象\nfunction objForEach(obj, fn) {\n    var key = void 0,\n        result = void 0;\n    for (key in obj) {\n        if (obj.hasOwnProperty(key)) {\n            result = fn.call(obj, key, obj[key]);\n            if (result === false) {\n                break;\n            }\n        }\n    }\n}\n\n// 遍历类数组\nfunction arrForEach(fakeArr, fn) {\n    var i = void 0,\n        item = void 0,\n        result = void 0;\n    var length = fakeArr.length || 0;\n    for (i = 0; i < length; i++) {\n        item = fakeArr[i];\n        result = fn.call(fakeArr, item, i);\n        if (result === false) {\n            break;\n        }\n    }\n}\n\n// 获取随机数\nfunction getRandom(prefix) {\n    return prefix + Math.random().toString().slice(2);\n}\n\n// 替换 html 特殊字符\nfunction replaceHtmlSymbol(html) {\n    if (html == null) {\n        return '';\n    }\n    return html.replace(/</gm, '&lt;').replace(/>/gm, '&gt;').replace(/\"/gm, '&quot;');\n}\n\n// 返回百分比的格式\n\n\n// 判断是不是 function\nfunction isFunction(fn) {\n    return typeof fn === 'function';\n}\n\n/*\n    bold-menu\n*/\n// 构造函数\nfunction Bold(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\">\\n            <i class=\"w-e-icon-bold\"><i/>\\n        </div>');\n    this.type = 'click';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nBold.prototype = {\n    constructor: Bold,\n\n    // 点击事件\n    onClick: function onClick(e) {\n        // 点击菜单将触发这里\n\n        var editor = this.editor;\n        var isSeleEmpty = editor.selection.isSelectionEmpty();\n\n        if (isSeleEmpty) {\n            // 选区是空的，插入并选中一个“空白”\n            editor.selection.createEmptyRange();\n        }\n\n        // 执行 bold 命令\n        editor.cmd.do('bold');\n\n        if (isSeleEmpty) {\n            // 需要将选取折叠起来\n            editor.selection.collapseRange();\n            editor.selection.restoreSelection();\n        }\n    },\n\n    // 试图改变 active 状态\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        if (editor.cmd.queryCommandState('bold')) {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    替换多语言\n */\n\nvar replaceLang = function (editor, str) {\n    var langArgs = editor.config.langArgs || [];\n    var result = str;\n\n    langArgs.forEach(function (item) {\n        var reg = item.reg;\n        var val = item.val;\n\n        if (reg.test(result)) {\n            result = result.replace(reg, function () {\n                return val;\n            });\n        }\n    });\n\n    return result;\n};\n\n/*\n    droplist\n*/\nvar _emptyFn = function _emptyFn() {};\n\n// 构造函数\nfunction DropList(menu, opt) {\n    var _this = this;\n\n    // droplist 所依附的菜单\n    var editor = menu.editor;\n    this.menu = menu;\n    this.opt = opt;\n    // 容器\n    var $container = $('<div class=\"w-e-droplist\"></div>');\n\n    // 标题\n    var $title = opt.$title;\n    var titleHtml = void 0;\n    if ($title) {\n        // 替换多语言\n        titleHtml = $title.html();\n        titleHtml = replaceLang(editor, titleHtml);\n        $title.html(titleHtml);\n\n        $title.addClass('w-e-dp-title');\n        $container.append($title);\n    }\n\n    var list = opt.list || [];\n    var type = opt.type || 'list'; // 'list' 列表形式（如“标题”菜单） / 'inline-block' 块状形式（如“颜色”菜单）\n    var onClick = opt.onClick || _emptyFn;\n\n    // 加入 DOM 并绑定事件\n    var $list = $('<ul class=\"' + (type === 'list' ? 'w-e-list' : 'w-e-block') + '\"></ul>');\n    $container.append($list);\n    list.forEach(function (item) {\n        var $elem = item.$elem;\n\n        // 替换多语言\n        var elemHtml = $elem.html();\n        elemHtml = replaceLang(editor, elemHtml);\n        $elem.html(elemHtml);\n\n        var value = item.value;\n        var $li = $('<li class=\"w-e-item\"></li>');\n        if ($elem) {\n            $li.append($elem);\n            $list.append($li);\n            $li.on('click', function (e) {\n                onClick(value);\n\n                // 隐藏\n                _this.hideTimeoutId = setTimeout(function () {\n                    _this.hide();\n                }, 0);\n            });\n        }\n    });\n\n    // 绑定隐藏事件\n    $container.on('mouseleave', function (e) {\n        _this.hideTimeoutId = setTimeout(function () {\n            _this.hide();\n        }, 0);\n    });\n\n    // 记录属性\n    this.$container = $container;\n\n    // 基本属性\n    this._rendered = false;\n    this._show = false;\n}\n\n// 原型\nDropList.prototype = {\n    constructor: DropList,\n\n    // 显示（插入DOM）\n    show: function show() {\n        if (this.hideTimeoutId) {\n            // 清除之前的定时隐藏\n            clearTimeout(this.hideTimeoutId);\n        }\n\n        var menu = this.menu;\n        var $menuELem = menu.$elem;\n        var $container = this.$container;\n        if (this._show) {\n            return;\n        }\n        if (this._rendered) {\n            // 显示\n            $container.show();\n        } else {\n            // 加入 DOM 之前先定位位置\n            var menuHeight = $menuELem.getSizeData().height || 0;\n            var width = this.opt.width || 100; // 默认为 100\n            $container.css('margin-top', menuHeight + 'px').css('width', width + 'px');\n\n            // 加入到 DOM\n            $menuELem.append($container);\n            this._rendered = true;\n        }\n\n        // 修改属性\n        this._show = true;\n    },\n\n    // 隐藏（移除DOM）\n    hide: function hide() {\n        if (this.showTimeoutId) {\n            // 清除之前的定时显示\n            clearTimeout(this.showTimeoutId);\n        }\n\n        var $container = this.$container;\n        if (!this._show) {\n            return;\n        }\n        // 隐藏并需改属性\n        $container.hide();\n        this._show = false;\n    }\n};\n\n/*\n    menu - header\n*/\n// 构造函数\nfunction Head(editor) {\n    var _this = this;\n\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\"><i class=\"w-e-icon-header\"><i/></div>');\n    this.type = 'droplist';\n\n    // 当前是否 active 状态\n    this._active = false;\n\n    // 初始化 droplist\n    this.droplist = new DropList(this, {\n        width: 100,\n        $title: $('<p>设置标题</p>'),\n        type: 'list', // droplist 以列表形式展示\n        list: [{ $elem: $('<h1>H1</h1>'), value: '<h1>' }, { $elem: $('<h2>H2</h2>'), value: '<h2>' }, { $elem: $('<h3>H3</h3>'), value: '<h3>' }, { $elem: $('<h4>H4</h4>'), value: '<h4>' }, { $elem: $('<h5>H5</h5>'), value: '<h5>' }, { $elem: $('<p>正文</p>'), value: '<p>' }],\n        onClick: function onClick(value) {\n            // 注意 this 是指向当前的 Head 对象\n            _this._command(value);\n        }\n    });\n}\n\n// 原型\nHead.prototype = {\n    constructor: Head,\n\n    // 执行命令\n    _command: function _command(value) {\n        var editor = this.editor;\n\n        var $selectionElem = editor.selection.getSelectionContainerElem();\n        if (editor.$textElem.equal($selectionElem)) {\n            // 不能选中多行来设置标题，否则会出现问题\n            // 例如选中的是 <p>xxx</p><p>yyy</p> 来设置标题，设置之后会成为 <h1>xxx<br>yyy</h1> 不符合预期\n            return;\n        }\n\n        editor.cmd.do('formatBlock', value);\n    },\n\n    // 试图改变 active 状态\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        var reg = /^h/i;\n        var cmdValue = editor.cmd.queryCommandValue('formatBlock');\n        if (reg.test(cmdValue)) {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    panel\n*/\n\nvar emptyFn = function emptyFn() {};\n\n// 记录已经显示 panel 的菜单\nvar _isCreatedPanelMenus = [];\n\n// 构造函数\nfunction Panel(menu, opt) {\n    this.menu = menu;\n    this.opt = opt;\n}\n\n// 原型\nPanel.prototype = {\n    constructor: Panel,\n\n    // 显示（插入DOM）\n    show: function show() {\n        var _this = this;\n\n        var menu = this.menu;\n        if (_isCreatedPanelMenus.indexOf(menu) >= 0) {\n            // 该菜单已经创建了 panel 不能再创建\n            return;\n        }\n\n        var editor = menu.editor;\n        var $body = $('body');\n        var $textContainerElem = editor.$textContainerElem;\n        var opt = this.opt;\n\n        // panel 的容器\n        var $container = $('<div class=\"w-e-panel-container\"></div>');\n        var width = opt.width || 300; // 默认 300px\n        $container.css('width', width + 'px').css('margin-left', (0 - width) / 2 + 'px');\n\n        // 添加关闭按钮\n        var $closeBtn = $('<i class=\"w-e-icon-close w-e-panel-close\"></i>');\n        $container.append($closeBtn);\n        $closeBtn.on('click', function () {\n            _this.hide();\n        });\n\n        // 准备 tabs 容器\n        var $tabTitleContainer = $('<ul class=\"w-e-panel-tab-title\"></ul>');\n        var $tabContentContainer = $('<div class=\"w-e-panel-tab-content\"></div>');\n        $container.append($tabTitleContainer).append($tabContentContainer);\n\n        // 设置高度\n        var height = opt.height;\n        if (height) {\n            $tabContentContainer.css('height', height + 'px').css('overflow-y', 'auto');\n        }\n\n        // tabs\n        var tabs = opt.tabs || [];\n        var tabTitleArr = [];\n        var tabContentArr = [];\n        tabs.forEach(function (tab, tabIndex) {\n            if (!tab) {\n                return;\n            }\n            var title = tab.title || '';\n            var tpl = tab.tpl || '';\n\n            // 替换多语言\n            title = replaceLang(editor, title);\n            tpl = replaceLang(editor, tpl);\n\n            // 添加到 DOM\n            var $title = $('<li class=\"w-e-item\">' + title + '</li>');\n            $tabTitleContainer.append($title);\n            var $content = $(tpl);\n            $tabContentContainer.append($content);\n\n            // 记录到内存\n            $title._index = tabIndex;\n            tabTitleArr.push($title);\n            tabContentArr.push($content);\n\n            // 设置 active 项\n            if (tabIndex === 0) {\n                $title._active = true;\n                $title.addClass('w-e-active');\n            } else {\n                $content.hide();\n            }\n\n            // 绑定 tab 的事件\n            $title.on('click', function (e) {\n                if ($title._active) {\n                    return;\n                }\n                // 隐藏所有的 tab\n                tabTitleArr.forEach(function ($title) {\n                    $title._active = false;\n                    $title.removeClass('w-e-active');\n                });\n                tabContentArr.forEach(function ($content) {\n                    $content.hide();\n                });\n\n                // 显示当前的 tab\n                $title._active = true;\n                $title.addClass('w-e-active');\n                $content.show();\n            });\n        });\n\n        // 绑定关闭事件\n        $container.on('click', function (e) {\n            // 点击时阻止冒泡\n            e.stopPropagation();\n        });\n        $body.on('click', function (e) {\n            _this.hide();\n        });\n\n        // 添加到 DOM\n        $textContainerElem.append($container);\n\n        // 绑定 opt 的事件，只有添加到 DOM 之后才能绑定成功\n        tabs.forEach(function (tab, index) {\n            if (!tab) {\n                return;\n            }\n            var events = tab.events || [];\n            events.forEach(function (event) {\n                var selector = event.selector;\n                var type = event.type;\n                var fn = event.fn || emptyFn;\n                var $content = tabContentArr[index];\n                $content.find(selector).on(type, function (e) {\n                    e.stopPropagation();\n                    var needToHide = fn(e);\n                    // 执行完事件之后，是否要关闭 panel\n                    if (needToHide) {\n                        _this.hide();\n                    }\n                });\n            });\n        });\n\n        // focus 第一个 elem\n        var $inputs = $container.find('input[type=text],textarea');\n        if ($inputs.length) {\n            $inputs.get(0).focus();\n        }\n\n        // 添加到属性\n        this.$container = $container;\n\n        // 隐藏其他 panel\n        this._hideOtherPanels();\n        // 记录该 menu 已经创建了 panel\n        _isCreatedPanelMenus.push(menu);\n    },\n\n    // 隐藏（移除DOM）\n    hide: function hide() {\n        var menu = this.menu;\n        var $container = this.$container;\n        if ($container) {\n            $container.remove();\n        }\n\n        // 将该 menu 记录中移除\n        _isCreatedPanelMenus = _isCreatedPanelMenus.filter(function (item) {\n            if (item === menu) {\n                return false;\n            } else {\n                return true;\n            }\n        });\n    },\n\n    // 一个 panel 展示时，隐藏其他 panel\n    _hideOtherPanels: function _hideOtherPanels() {\n        if (!_isCreatedPanelMenus.length) {\n            return;\n        }\n        _isCreatedPanelMenus.forEach(function (menu) {\n            var panel = menu.panel || {};\n            if (panel.hide) {\n                panel.hide();\n            }\n        });\n    }\n};\n\n/*\n    menu - link\n*/\n// 构造函数\nfunction Link(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\"><i class=\"w-e-icon-link\"><i/></div>');\n    this.type = 'panel';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nLink.prototype = {\n    constructor: Link,\n\n    // 点击事件\n    onClick: function onClick(e) {\n        var editor = this.editor;\n        var $linkelem = void 0;\n\n        if (this._active) {\n            // 当前选区在链接里面\n            $linkelem = editor.selection.getSelectionContainerElem();\n            if (!$linkelem) {\n                return;\n            }\n            // 将该元素都包含在选取之内，以便后面整体替换\n            editor.selection.createRangeByElem($linkelem);\n            editor.selection.restoreSelection();\n            // 显示 panel\n            this._createPanel($linkelem.text(), $linkelem.attr('href'));\n        } else {\n            // 当前选区不在链接里面\n            if (editor.selection.isSelectionEmpty()) {\n                // 选区是空的，未选中内容\n                this._createPanel('', '');\n            } else {\n                // 选中内容了\n                this._createPanel(editor.selection.getSelectionText(), '');\n            }\n        }\n    },\n\n    // 创建 panel\n    _createPanel: function _createPanel(text, link) {\n        var _this = this;\n\n        // panel 中需要用到的id\n        var inputLinkId = getRandom('input-link');\n        var inputTextId = getRandom('input-text');\n        var btnOkId = getRandom('btn-ok');\n        var btnDelId = getRandom('btn-del');\n\n        // 是否显示“删除链接”\n        var delBtnDisplay = this._active ? 'inline-block' : 'none';\n\n        // 初始化并显示 panel\n        var panel = new Panel(this, {\n            width: 300,\n            // panel 中可包含多个 tab\n            tabs: [{\n                // tab 的标题\n                title: '链接',\n                // 模板\n                tpl: '<div>\\n                            <input id=\"' + inputTextId + '\" type=\"text\" class=\"block\" value=\"' + text + '\" placeholder=\"\\u94FE\\u63A5\\u6587\\u5B57\"/></td>\\n                            <input id=\"' + inputLinkId + '\" type=\"text\" class=\"block\" value=\"' + link + '\" placeholder=\"http://...\"/></td>\\n                            <div class=\"w-e-button-container\">\\n                                <button id=\"' + btnOkId + '\" class=\"right\">\\u63D2\\u5165</button>\\n                                <button id=\"' + btnDelId + '\" class=\"gray right\" style=\"display:' + delBtnDisplay + '\">\\u5220\\u9664\\u94FE\\u63A5</button>\\n                            </div>\\n                        </div>',\n                // 事件绑定\n                events: [\n                // 插入链接\n                {\n                    selector: '#' + btnOkId,\n                    type: 'click',\n                    fn: function fn() {\n                        // 执行插入链接\n                        var $link = $('#' + inputLinkId);\n                        var $text = $('#' + inputTextId);\n                        var link = $link.val();\n                        var text = $text.val();\n                        _this._insertLink(text, link);\n\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                },\n                // 删除链接\n                {\n                    selector: '#' + btnDelId,\n                    type: 'click',\n                    fn: function fn() {\n                        // 执行删除链接\n                        _this._delLink();\n\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                }]\n            } // tab end\n            ] // tabs end\n        });\n\n        // 显示 panel\n        panel.show();\n\n        // 记录属性\n        this.panel = panel;\n    },\n\n    // 删除当前链接\n    _delLink: function _delLink() {\n        if (!this._active) {\n            return;\n        }\n        var editor = this.editor;\n        var $selectionELem = editor.selection.getSelectionContainerElem();\n        if (!$selectionELem) {\n            return;\n        }\n        var selectionText = editor.selection.getSelectionText();\n        editor.cmd.do('insertHTML', '<span>' + selectionText + '</span>');\n    },\n\n    // 插入链接\n    _insertLink: function _insertLink(text, link) {\n        var editor = this.editor;\n        var config = editor.config;\n        var linkCheck = config.linkCheck;\n        var checkResult = true; // 默认为 true\n        if (linkCheck && typeof linkCheck === 'function') {\n            checkResult = linkCheck(text, link);\n        }\n        if (checkResult === true) {\n            editor.cmd.do('insertHTML', '<a href=\"' + link + '\" target=\"_blank\">' + text + '</a>');\n        } else {\n            alert(checkResult);\n        }\n    },\n\n    // 试图改变 active 状态\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        var $selectionELem = editor.selection.getSelectionContainerElem();\n        if (!$selectionELem) {\n            return;\n        }\n        if ($selectionELem.getNodeName() === 'A') {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    italic-menu\n*/\n// 构造函数\nfunction Italic(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\">\\n            <i class=\"w-e-icon-italic\"><i/>\\n        </div>');\n    this.type = 'click';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nItalic.prototype = {\n    constructor: Italic,\n\n    // 点击事件\n    onClick: function onClick(e) {\n        // 点击菜单将触发这里\n\n        var editor = this.editor;\n        var isSeleEmpty = editor.selection.isSelectionEmpty();\n\n        if (isSeleEmpty) {\n            // 选区是空的，插入并选中一个“空白”\n            editor.selection.createEmptyRange();\n        }\n\n        // 执行 italic 命令\n        editor.cmd.do('italic');\n\n        if (isSeleEmpty) {\n            // 需要将选取折叠起来\n            editor.selection.collapseRange();\n            editor.selection.restoreSelection();\n        }\n    },\n\n    // 试图改变 active 状态\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        if (editor.cmd.queryCommandState('italic')) {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    redo-menu\n*/\n// 构造函数\nfunction Redo(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\">\\n            <i class=\"w-e-icon-redo\"><i/>\\n        </div>');\n    this.type = 'click';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nRedo.prototype = {\n    constructor: Redo,\n\n    // 点击事件\n    onClick: function onClick(e) {\n        // 点击菜单将触发这里\n\n        var editor = this.editor;\n\n        // 执行 redo 命令\n        editor.cmd.do('redo');\n    }\n};\n\n/*\n    strikeThrough-menu\n*/\n// 构造函数\nfunction StrikeThrough(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\">\\n            <i class=\"w-e-icon-strikethrough\"><i/>\\n        </div>');\n    this.type = 'click';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nStrikeThrough.prototype = {\n    constructor: StrikeThrough,\n\n    // 点击事件\n    onClick: function onClick(e) {\n        // 点击菜单将触发这里\n\n        var editor = this.editor;\n        var isSeleEmpty = editor.selection.isSelectionEmpty();\n\n        if (isSeleEmpty) {\n            // 选区是空的，插入并选中一个“空白”\n            editor.selection.createEmptyRange();\n        }\n\n        // 执行 strikeThrough 命令\n        editor.cmd.do('strikeThrough');\n\n        if (isSeleEmpty) {\n            // 需要将选取折叠起来\n            editor.selection.collapseRange();\n            editor.selection.restoreSelection();\n        }\n    },\n\n    // 试图改变 active 状态\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        if (editor.cmd.queryCommandState('strikeThrough')) {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    underline-menu\n*/\n// 构造函数\nfunction Underline(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\">\\n            <i class=\"w-e-icon-underline\"><i/>\\n        </div>');\n    this.type = 'click';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nUnderline.prototype = {\n    constructor: Underline,\n\n    // 点击事件\n    onClick: function onClick(e) {\n        // 点击菜单将触发这里\n\n        var editor = this.editor;\n        var isSeleEmpty = editor.selection.isSelectionEmpty();\n\n        if (isSeleEmpty) {\n            // 选区是空的，插入并选中一个“空白”\n            editor.selection.createEmptyRange();\n        }\n\n        // 执行 underline 命令\n        editor.cmd.do('underline');\n\n        if (isSeleEmpty) {\n            // 需要将选取折叠起来\n            editor.selection.collapseRange();\n            editor.selection.restoreSelection();\n        }\n    },\n\n    // 试图改变 active 状态\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        if (editor.cmd.queryCommandState('underline')) {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    undo-menu\n*/\n// 构造函数\nfunction Undo(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\">\\n            <i class=\"w-e-icon-undo\"><i/>\\n        </div>');\n    this.type = 'click';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nUndo.prototype = {\n    constructor: Undo,\n\n    // 点击事件\n    onClick: function onClick(e) {\n        // 点击菜单将触发这里\n\n        var editor = this.editor;\n\n        // 执行 undo 命令\n        editor.cmd.do('undo');\n    }\n};\n\n/*\n    menu - list\n*/\n// 构造函数\nfunction List(editor) {\n    var _this = this;\n\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\"><i class=\"w-e-icon-list2\"><i/></div>');\n    this.type = 'droplist';\n\n    // 当前是否 active 状态\n    this._active = false;\n\n    // 初始化 droplist\n    this.droplist = new DropList(this, {\n        width: 120,\n        $title: $('<p>设置列表</p>'),\n        type: 'list', // droplist 以列表形式展示\n        list: [{ $elem: $('<span><i class=\"w-e-icon-list-numbered\"></i> 有序列表</span>'), value: 'insertOrderedList' }, { $elem: $('<span><i class=\"w-e-icon-list2\"></i> 无序列表</span>'), value: 'insertUnorderedList' }],\n        onClick: function onClick(value) {\n            // 注意 this 是指向当前的 List 对象\n            _this._command(value);\n        }\n    });\n}\n\n// 原型\nList.prototype = {\n    constructor: List,\n\n    // 执行命令\n    _command: function _command(value) {\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n        editor.selection.restoreSelection();\n        if (editor.cmd.queryCommandState(value)) {\n            return;\n        }\n        editor.cmd.do(value);\n\n        // 验证列表是否被包裹在 <p> 之内\n        var $selectionElem = editor.selection.getSelectionContainerElem();\n        if ($selectionElem.getNodeName() === 'LI') {\n            $selectionElem = $selectionElem.parent();\n        }\n        if (/^ol|ul$/i.test($selectionElem.getNodeName()) === false) {\n            return;\n        }\n        if ($selectionElem.equal($textElem)) {\n            // 证明是顶级标签，没有被 <p> 包裹\n            return;\n        }\n        var $parent = $selectionElem.parent();\n        if ($parent.equal($textElem)) {\n            // $parent 是顶级标签，不能删除\n            return;\n        }\n\n        $selectionElem.insertAfter($parent);\n        $parent.remove();\n    },\n\n    // 试图改变 active 状态\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        if (editor.cmd.queryCommandState('insertUnOrderedList') || editor.cmd.queryCommandState('insertOrderedList')) {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    menu - justify\n*/\n// 构造函数\nfunction Justify(editor) {\n    var _this = this;\n\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\"><i class=\"w-e-icon-paragraph-left\"><i/></div>');\n    this.type = 'droplist';\n\n    // 当前是否 active 状态\n    this._active = false;\n\n    // 初始化 droplist\n    this.droplist = new DropList(this, {\n        width: 100,\n        $title: $('<p>对齐方式</p>'),\n        type: 'list', // droplist 以列表形式展示\n        list: [{ $elem: $('<span><i class=\"w-e-icon-paragraph-left\"></i> 靠左</span>'), value: 'justifyLeft' }, { $elem: $('<span><i class=\"w-e-icon-paragraph-center\"></i> 居中</span>'), value: 'justifyCenter' }, { $elem: $('<span><i class=\"w-e-icon-paragraph-right\"></i> 靠右</span>'), value: 'justifyRight' }],\n        onClick: function onClick(value) {\n            // 注意 this 是指向当前的 List 对象\n            _this._command(value);\n        }\n    });\n}\n\n// 原型\nJustify.prototype = {\n    constructor: Justify,\n\n    // 执行命令\n    _command: function _command(value) {\n        var editor = this.editor;\n        editor.cmd.do(value);\n    }\n};\n\n/*\n    menu - Forecolor\n*/\n// 构造函数\nfunction ForeColor(editor) {\n    var _this = this;\n\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\"><i class=\"w-e-icon-pencil2\"><i/></div>');\n    this.type = 'droplist';\n\n    // 获取配置的颜色\n    var config = editor.config;\n    var colors = config.colors || [];\n\n    // 当前是否 active 状态\n    this._active = false;\n\n    // 初始化 droplist\n    this.droplist = new DropList(this, {\n        width: 120,\n        $title: $('<p>文字颜色</p>'),\n        type: 'inline-block', // droplist 内容以 block 形式展示\n        list: colors.map(function (color) {\n            return { $elem: $('<i style=\"color:' + color + ';\" class=\"w-e-icon-pencil2\"></i>'), value: color };\n        }),\n        onClick: function onClick(value) {\n            // 注意 this 是指向当前的 ForeColor 对象\n            _this._command(value);\n        }\n    });\n}\n\n// 原型\nForeColor.prototype = {\n    constructor: ForeColor,\n\n    // 执行命令\n    _command: function _command(value) {\n        var editor = this.editor;\n        editor.cmd.do('foreColor', value);\n    }\n};\n\n/*\n    menu - BackColor\n*/\n// 构造函数\nfunction BackColor(editor) {\n    var _this = this;\n\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\"><i class=\"w-e-icon-paint-brush\"><i/></div>');\n    this.type = 'droplist';\n\n    // 获取配置的颜色\n    var config = editor.config;\n    var colors = config.colors || [];\n\n    // 当前是否 active 状态\n    this._active = false;\n\n    // 初始化 droplist\n    this.droplist = new DropList(this, {\n        width: 120,\n        $title: $('<p>背景色</p>'),\n        type: 'inline-block', // droplist 内容以 block 形式展示\n        list: colors.map(function (color) {\n            return { $elem: $('<i style=\"color:' + color + ';\" class=\"w-e-icon-paint-brush\"></i>'), value: color };\n        }),\n        onClick: function onClick(value) {\n            // 注意 this 是指向当前的 BackColor 对象\n            _this._command(value);\n        }\n    });\n}\n\n// 原型\nBackColor.prototype = {\n    constructor: BackColor,\n\n    // 执行命令\n    _command: function _command(value) {\n        var editor = this.editor;\n        editor.cmd.do('backColor', value);\n    }\n};\n\n/*\n    menu - quote\n*/\n// 构造函数\nfunction Quote(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\">\\n            <i class=\"w-e-icon-quotes-left\"><i/>\\n        </div>');\n    this.type = 'click';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nQuote.prototype = {\n    constructor: Quote,\n\n    onClick: function onClick(e) {\n        var editor = this.editor;\n        var $selectionElem = editor.selection.getSelectionContainerElem();\n        var nodeName = $selectionElem.getNodeName();\n\n        if (!UA.isIE()) {\n            if (nodeName === 'BLOCKQUOTE') {\n                // 撤销 quote\n                editor.cmd.do('formatBlock', '<P>');\n            } else {\n                // 转换为 quote\n                editor.cmd.do('formatBlock', '<BLOCKQUOTE>');\n            }\n            return;\n        }\n\n        // IE 中不支持 formatBlock <BLOCKQUOTE> ，要用其他方式兼容\n        var content = void 0,\n            $targetELem = void 0;\n        if (nodeName === 'P') {\n            // 将 P 转换为 quote\n            content = $selectionElem.text();\n            $targetELem = $('<blockquote>' + content + '</blockquote>');\n            $targetELem.insertAfter($selectionElem);\n            $selectionElem.remove();\n            return;\n        }\n        if (nodeName === 'BLOCKQUOTE') {\n            // 撤销 quote\n            content = $selectionElem.text();\n            $targetELem = $('<p>' + content + '</p>');\n            $targetELem.insertAfter($selectionElem);\n            $selectionElem.remove();\n        }\n    },\n\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        var reg = /^BLOCKQUOTE$/i;\n        var cmdValue = editor.cmd.queryCommandValue('formatBlock');\n        if (reg.test(cmdValue)) {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    menu - code\n*/\n// 构造函数\nfunction Code(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\">\\n            <i class=\"w-e-icon-terminal\"><i/>\\n        </div>');\n    this.type = 'panel';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nCode.prototype = {\n    constructor: Code,\n\n    onClick: function onClick(e) {\n        var editor = this.editor;\n        var $startElem = editor.selection.getSelectionStartElem();\n        var $endElem = editor.selection.getSelectionEndElem();\n        var isSeleEmpty = editor.selection.isSelectionEmpty();\n        var selectionText = editor.selection.getSelectionText();\n        var $code = void 0;\n\n        if (!$startElem.equal($endElem)) {\n            // 跨元素选择，不做处理\n            editor.selection.restoreSelection();\n            return;\n        }\n        if (!isSeleEmpty) {\n            // 选取不是空，用 <code> 包裹即可\n            $code = $('<code>' + selectionText + '</code>');\n            editor.cmd.do('insertElem', $code);\n            editor.selection.createRangeByElem($code, false);\n            editor.selection.restoreSelection();\n            return;\n        }\n\n        // 选取是空，且没有夸元素选择，则插入 <pre><code></code></prev>\n        if (this._active) {\n            // 选中状态，将编辑内容\n            this._createPanel($startElem.html());\n        } else {\n            // 未选中状态，将创建内容\n            this._createPanel();\n        }\n    },\n\n    _createPanel: function _createPanel(value) {\n        var _this = this;\n\n        // value - 要编辑的内容\n        value = value || '';\n        var type = !value ? 'new' : 'edit';\n        var textId = getRandom('texxt');\n        var btnId = getRandom('btn');\n\n        var panel = new Panel(this, {\n            width: 500,\n            // 一个 Panel 包含多个 tab\n            tabs: [{\n                // 标题\n                title: '插入代码',\n                // 模板\n                tpl: '<div>\\n                        <textarea id=\"' + textId + '\" style=\"height:145px;;\">' + value + '</textarea>\\n                        <div class=\"w-e-button-container\">\\n                            <button id=\"' + btnId + '\" class=\"right\">\\u63D2\\u5165</button>\\n                        </div>\\n                    <div>',\n                // 事件绑定\n                events: [\n                // 插入代码\n                {\n                    selector: '#' + btnId,\n                    type: 'click',\n                    fn: function fn() {\n                        var $text = $('#' + textId);\n                        var text = $text.val() || $text.html();\n                        text = replaceHtmlSymbol(text);\n                        if (type === 'new') {\n                            // 新插入\n                            _this._insertCode(text);\n                        } else {\n                            // 编辑更新\n                            _this._updateCode(text);\n                        }\n\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                }]\n            } // first tab end\n            ] // tabs end\n        }); // new Panel end\n\n        // 显示 panel\n        panel.show();\n\n        // 记录属性\n        this.panel = panel;\n    },\n\n    // 插入代码\n    _insertCode: function _insertCode(value) {\n        var editor = this.editor;\n        editor.cmd.do('insertHTML', '<pre><code>' + value + '</code></pre><p><br></p>');\n    },\n\n    // 更新代码\n    _updateCode: function _updateCode(value) {\n        var editor = this.editor;\n        var $selectionELem = editor.selection.getSelectionContainerElem();\n        if (!$selectionELem) {\n            return;\n        }\n        $selectionELem.html(value);\n        editor.selection.restoreSelection();\n    },\n\n    // 试图改变 active 状态\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        var $selectionELem = editor.selection.getSelectionContainerElem();\n        if (!$selectionELem) {\n            return;\n        }\n        var $parentElem = $selectionELem.parent();\n        if ($selectionELem.getNodeName() === 'CODE' && $parentElem.getNodeName() === 'PRE') {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    menu - emoticon\n*/\n// 构造函数\nfunction Emoticon(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\">\\n            <i class=\"w-e-icon-happy\"><i/>\\n        </div>');\n    this.type = 'panel';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nEmoticon.prototype = {\n    constructor: Emoticon,\n\n    onClick: function onClick() {\n        this._createPanel();\n    },\n\n    _createPanel: function _createPanel() {\n        var _this = this;\n\n        var editor = this.editor;\n        var config = editor.config;\n        // 获取表情配置\n        var emotions = config.emotions || [];\n\n        // 创建表情 dropPanel 的配置\n        var tabConfig = [];\n        emotions.forEach(function (emotData) {\n            var emotType = emotData.type;\n            var content = emotData.content || [];\n\n            // 这一组表情最终拼接出来的 html\n            var faceHtml = '';\n\n            // emoji 表情\n            if (emotType === 'emoji') {\n                content.forEach(function (item) {\n                    if (item) {\n                        faceHtml += '<span class=\"w-e-item\">' + item + '</span>';\n                    }\n                });\n            }\n            // 图片表情\n            if (emotType === 'image') {\n                content.forEach(function (item) {\n                    var src = item.src;\n                    var alt = item.alt;\n                    if (src) {\n                        // 加一个 data-w-e 属性，点击图片的时候不再提示编辑图片\n                        faceHtml += '<span class=\"w-e-item\"><img src=\"' + src + '\" alt=\"' + alt + '\" data-w-e=\"1\"/></span>';\n                    }\n                });\n            }\n\n            tabConfig.push({\n                title: emotData.title,\n                tpl: '<div class=\"w-e-emoticon-container\">' + faceHtml + '</div>',\n                events: [{\n                    selector: 'span.w-e-item',\n                    type: 'click',\n                    fn: function fn(e) {\n                        var target = e.target;\n                        var $target = $(target);\n                        var nodeName = $target.getNodeName();\n\n                        var insertHtml = void 0;\n                        if (nodeName === 'IMG') {\n                            // 插入图片\n                            insertHtml = $target.parent().html();\n                        } else {\n                            // 插入 emoji\n                            insertHtml = '<span>' + $target.html() + '</span>';\n                        }\n\n                        _this._insert(insertHtml);\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                }]\n            });\n        });\n\n        var panel = new Panel(this, {\n            width: 300,\n            height: 200,\n            // 一个 Panel 包含多个 tab\n            tabs: tabConfig\n        });\n\n        // 显示 panel\n        panel.show();\n\n        // 记录属性\n        this.panel = panel;\n    },\n\n    // 插入表情\n    _insert: function _insert(emotHtml) {\n        var editor = this.editor;\n        editor.cmd.do('insertHTML', emotHtml);\n    }\n};\n\n/*\n    menu - table\n*/\n// 构造函数\nfunction Table(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\"><i class=\"w-e-icon-table2\"><i/></div>');\n    this.type = 'panel';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nTable.prototype = {\n    constructor: Table,\n\n    onClick: function onClick() {\n        if (this._active) {\n            // 编辑现有表格\n            this._createEditPanel();\n        } else {\n            // 插入新表格\n            this._createInsertPanel();\n        }\n    },\n\n    // 创建插入新表格的 panel\n    _createInsertPanel: function _createInsertPanel() {\n        var _this = this;\n\n        // 用到的 id\n        var btnInsertId = getRandom('btn');\n        var textRowNum = getRandom('row');\n        var textColNum = getRandom('col');\n\n        var panel = new Panel(this, {\n            width: 250,\n            // panel 包含多个 tab\n            tabs: [{\n                // 标题\n                title: '插入表格',\n                // 模板\n                tpl: '<div>\\n                        <p style=\"text-align:left; padding:5px 0;\">\\n                            \\u521B\\u5EFA\\n                            <input id=\"' + textRowNum + '\" type=\"text\" value=\"5\" style=\"width:40px;text-align:center;\"/>\\n                            \\u884C\\n                            <input id=\"' + textColNum + '\" type=\"text\" value=\"5\" style=\"width:40px;text-align:center;\"/>\\n                            \\u5217\\u7684\\u8868\\u683C\\n                        </p>\\n                        <div class=\"w-e-button-container\">\\n                            <button id=\"' + btnInsertId + '\" class=\"right\">\\u63D2\\u5165</button>\\n                        </div>\\n                    </div>',\n                // 事件绑定\n                events: [{\n                    // 点击按钮，插入表格\n                    selector: '#' + btnInsertId,\n                    type: 'click',\n                    fn: function fn() {\n                        var rowNum = parseInt($('#' + textRowNum).val());\n                        var colNum = parseInt($('#' + textColNum).val());\n\n                        if (rowNum && colNum && rowNum > 0 && colNum > 0) {\n                            // form 数据有效\n                            _this._insert(rowNum, colNum);\n                        }\n\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                }]\n            } // first tab end\n            ] // tabs end\n        }); // panel end\n\n        // 展示 panel\n        panel.show();\n\n        // 记录属性\n        this.panel = panel;\n    },\n\n    // 插入表格\n    _insert: function _insert(rowNum, colNum) {\n        // 拼接 table 模板\n        var r = void 0,\n            c = void 0;\n        var html = '<table border=\"0\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\">';\n        for (r = 0; r < rowNum; r++) {\n            html += '<tr>';\n            if (r === 0) {\n                for (c = 0; c < colNum; c++) {\n                    html += '<th>&nbsp;</th>';\n                }\n            } else {\n                for (c = 0; c < colNum; c++) {\n                    html += '<td>&nbsp;</td>';\n                }\n            }\n            html += '</tr>';\n        }\n        html += '</table><p><br></p>';\n\n        // 执行命令\n        var editor = this.editor;\n        editor.cmd.do('insertHTML', html);\n\n        // 防止 firefox 下出现 resize 的控制点\n        editor.cmd.do('enableObjectResizing', false);\n        editor.cmd.do('enableInlineTableEditing', false);\n    },\n\n    // 创建编辑表格的 panel\n    _createEditPanel: function _createEditPanel() {\n        var _this2 = this;\n\n        // 可用的 id\n        var addRowBtnId = getRandom('add-row');\n        var addColBtnId = getRandom('add-col');\n        var delRowBtnId = getRandom('del-row');\n        var delColBtnId = getRandom('del-col');\n        var delTableBtnId = getRandom('del-table');\n\n        // 创建 panel 对象\n        var panel = new Panel(this, {\n            width: 320,\n            // panel 包含多个 tab\n            tabs: [{\n                // 标题\n                title: '编辑表格',\n                // 模板\n                tpl: '<div>\\n                        <div class=\"w-e-button-container\" style=\"border-bottom:1px solid #f1f1f1;padding-bottom:5px;margin-bottom:5px;\">\\n                            <button id=\"' + addRowBtnId + '\" class=\"left\">\\u589E\\u52A0\\u884C</button>\\n                            <button id=\"' + delRowBtnId + '\" class=\"red left\">\\u5220\\u9664\\u884C</button>\\n                            <button id=\"' + addColBtnId + '\" class=\"left\">\\u589E\\u52A0\\u5217</button>\\n                            <button id=\"' + delColBtnId + '\" class=\"red left\">\\u5220\\u9664\\u5217</button>\\n                        </div>\\n                        <div class=\"w-e-button-container\">\\n                            <button id=\"' + delTableBtnId + '\" class=\"gray left\">\\u5220\\u9664\\u8868\\u683C</button>\\n                        </dv>\\n                    </div>',\n                // 事件绑定\n                events: [{\n                    // 增加行\n                    selector: '#' + addRowBtnId,\n                    type: 'click',\n                    fn: function fn() {\n                        _this2._addRow();\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                }, {\n                    // 增加列\n                    selector: '#' + addColBtnId,\n                    type: 'click',\n                    fn: function fn() {\n                        _this2._addCol();\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                }, {\n                    // 删除行\n                    selector: '#' + delRowBtnId,\n                    type: 'click',\n                    fn: function fn() {\n                        _this2._delRow();\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                }, {\n                    // 删除列\n                    selector: '#' + delColBtnId,\n                    type: 'click',\n                    fn: function fn() {\n                        _this2._delCol();\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                }, {\n                    // 删除表格\n                    selector: '#' + delTableBtnId,\n                    type: 'click',\n                    fn: function fn() {\n                        _this2._delTable();\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                }]\n            }]\n        });\n        // 显示 panel\n        panel.show();\n    },\n\n    // 获取选中的单元格的位置信息\n    _getLocationData: function _getLocationData() {\n        var result = {};\n        var editor = this.editor;\n        var $selectionELem = editor.selection.getSelectionContainerElem();\n        if (!$selectionELem) {\n            return;\n        }\n        var nodeName = $selectionELem.getNodeName();\n        if (nodeName !== 'TD' && nodeName !== 'TH') {\n            return;\n        }\n\n        // 获取 td index\n        var $tr = $selectionELem.parent();\n        var $tds = $tr.children();\n        var tdLength = $tds.length;\n        $tds.forEach(function (td, index) {\n            if (td === $selectionELem[0]) {\n                // 记录并跳出循环\n                result.td = {\n                    index: index,\n                    elem: td,\n                    length: tdLength\n                };\n                return false;\n            }\n        });\n\n        // 获取 tr index\n        var $tbody = $tr.parent();\n        var $trs = $tbody.children();\n        var trLength = $trs.length;\n        $trs.forEach(function (tr, index) {\n            if (tr === $tr[0]) {\n                // 记录并跳出循环\n                result.tr = {\n                    index: index,\n                    elem: tr,\n                    length: trLength\n                };\n                return false;\n            }\n        });\n\n        // 返回结果\n        return result;\n    },\n\n    // 增加行\n    _addRow: function _addRow() {\n        // 获取当前单元格的位置信息\n        var locationData = this._getLocationData();\n        if (!locationData) {\n            return;\n        }\n        var trData = locationData.tr;\n        var $currentTr = $(trData.elem);\n        var tdData = locationData.td;\n        var tdLength = tdData.length;\n\n        // 拼接即将插入的字符串\n        var newTr = document.createElement('tr');\n        var tpl = '',\n            i = void 0;\n        for (i = 0; i < tdLength; i++) {\n            tpl += '<td>&nbsp;</td>';\n        }\n        newTr.innerHTML = tpl;\n        // 插入\n        $(newTr).insertAfter($currentTr);\n    },\n\n    // 增加列\n    _addCol: function _addCol() {\n        // 获取当前单元格的位置信息\n        var locationData = this._getLocationData();\n        if (!locationData) {\n            return;\n        }\n        var trData = locationData.tr;\n        var tdData = locationData.td;\n        var tdIndex = tdData.index;\n        var $currentTr = $(trData.elem);\n        var $trParent = $currentTr.parent();\n        var $trs = $trParent.children();\n\n        // 遍历所有行\n        $trs.forEach(function (tr) {\n            var $tr = $(tr);\n            var $tds = $tr.children();\n            var $currentTd = $tds.get(tdIndex);\n            var name = $currentTd.getNodeName().toLowerCase();\n\n            // new 一个 td，并插入\n            var newTd = document.createElement(name);\n            $(newTd).insertAfter($currentTd);\n        });\n    },\n\n    // 删除行\n    _delRow: function _delRow() {\n        // 获取当前单元格的位置信息\n        var locationData = this._getLocationData();\n        if (!locationData) {\n            return;\n        }\n        var trData = locationData.tr;\n        var $currentTr = $(trData.elem);\n        $currentTr.remove();\n    },\n\n    // 删除列\n    _delCol: function _delCol() {\n        // 获取当前单元格的位置信息\n        var locationData = this._getLocationData();\n        if (!locationData) {\n            return;\n        }\n        var trData = locationData.tr;\n        var tdData = locationData.td;\n        var tdIndex = tdData.index;\n        var $currentTr = $(trData.elem);\n        var $trParent = $currentTr.parent();\n        var $trs = $trParent.children();\n\n        // 遍历所有行\n        $trs.forEach(function (tr) {\n            var $tr = $(tr);\n            var $tds = $tr.children();\n            var $currentTd = $tds.get(tdIndex);\n            // 删除\n            $currentTd.remove();\n        });\n    },\n\n    // 删除表格\n    _delTable: function _delTable() {\n        var editor = this.editor;\n        var $selectionELem = editor.selection.getSelectionContainerElem();\n        if (!$selectionELem) {\n            return;\n        }\n        var $table = $selectionELem.parentUntil('table');\n        if (!$table) {\n            return;\n        }\n        $table.remove();\n    },\n\n    // 试图改变 active 状态\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        var $selectionELem = editor.selection.getSelectionContainerElem();\n        if (!$selectionELem) {\n            return;\n        }\n        var nodeName = $selectionELem.getNodeName();\n        if (nodeName === 'TD' || nodeName === 'TH') {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    menu - video\n*/\n// 构造函数\nfunction Video(editor) {\n    this.editor = editor;\n    this.$elem = $('<div class=\"w-e-menu\"><i class=\"w-e-icon-play\"><i/></div>');\n    this.type = 'panel';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nVideo.prototype = {\n    constructor: Video,\n\n    onClick: function onClick() {\n        this._createPanel();\n    },\n\n    _createPanel: function _createPanel() {\n        var _this = this;\n\n        // 创建 id\n        var textValId = getRandom('text-val');\n        var btnId = getRandom('btn');\n\n        // 创建 panel\n        var panel = new Panel(this, {\n            width: 350,\n            // 一个 panel 多个 tab\n            tabs: [{\n                // 标题\n                title: '插入视频',\n                // 模板\n                tpl: '<div>\\n                        <input id=\"' + textValId + '\" type=\"text\" class=\"block\" placeholder=\"\\u683C\\u5F0F\\u5982\\uFF1A<iframe src=... ></iframe>\"/>\\n                        <div class=\"w-e-button-container\">\\n                            <button id=\"' + btnId + '\" class=\"right\">\\u63D2\\u5165</button>\\n                        </div>\\n                    </div>',\n                // 事件绑定\n                events: [{\n                    selector: '#' + btnId,\n                    type: 'click',\n                    fn: function fn() {\n                        var $text = $('#' + textValId);\n                        var val = $text.val().trim();\n\n                        // 测试用视频地址\n                        // <iframe height=498 width=510 src='http://player.youku.com/embed/XMjcwMzc3MzM3Mg==' frameborder=0 'allowfullscreen'></iframe>\n\n                        if (val) {\n                            // 插入视频\n                            _this._insert(val);\n                        }\n\n                        // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                        return true;\n                    }\n                }]\n            } // first tab end\n            ] // tabs end\n        }); // panel end\n\n        // 显示 panel\n        panel.show();\n\n        // 记录属性\n        this.panel = panel;\n    },\n\n    // 插入视频\n    _insert: function _insert(val) {\n        var editor = this.editor;\n        editor.cmd.do('insertHTML', val + '<p><br></p>');\n    }\n};\n\n/*\n    menu - img\n*/\n// 构造函数\nfunction Image(editor) {\n    this.editor = editor;\n    var imgMenuId = getRandom('w-e-img');\n    this.$elem = $('<div class=\"w-e-menu\" id=\"' + imgMenuId + '\"><i class=\"w-e-icon-image\"><i/></div>');\n    editor.imgMenuId = imgMenuId;\n    this.type = 'panel';\n\n    // 当前是否 active 状态\n    this._active = false;\n}\n\n// 原型\nImage.prototype = {\n    constructor: Image,\n\n    onClick: function onClick() {\n        var editor = this.editor;\n        var config = editor.config;\n        if (config.qiniu) {\n            return;\n        }\n        if (this._active) {\n            this._createEditPanel();\n        } else {\n            this._createInsertPanel();\n        }\n    },\n\n    _createEditPanel: function _createEditPanel() {\n        var editor = this.editor;\n\n        // id\n        var width30 = getRandom('width-30');\n        var width50 = getRandom('width-50');\n        var width100 = getRandom('width-100');\n        var delBtn = getRandom('del-btn');\n\n        // tab 配置\n        var tabsConfig = [{\n            title: '编辑图片',\n            tpl: '<div>\\n                    <div class=\"w-e-button-container\" style=\"border-bottom:1px solid #f1f1f1;padding-bottom:5px;margin-bottom:5px;\">\\n                        <span style=\"float:left;font-size:14px;margin:4px 5px 0 5px;color:#333;\">\\u6700\\u5927\\u5BBD\\u5EA6\\uFF1A</span>\\n                        <button id=\"' + width30 + '\" class=\"left\">30%</button>\\n                        <button id=\"' + width50 + '\" class=\"left\">50%</button>\\n                        <button id=\"' + width100 + '\" class=\"left\">100%</button>\\n                    </div>\\n                    <div class=\"w-e-button-container\">\\n                        <button id=\"' + delBtn + '\" class=\"gray left\">\\u5220\\u9664\\u56FE\\u7247</button>\\n                    </dv>\\n                </div>',\n            events: [{\n                selector: '#' + width30,\n                type: 'click',\n                fn: function fn() {\n                    var $img = editor._selectedImg;\n                    if ($img) {\n                        $img.css('max-width', '30%');\n                    }\n                    // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                    return true;\n                }\n            }, {\n                selector: '#' + width50,\n                type: 'click',\n                fn: function fn() {\n                    var $img = editor._selectedImg;\n                    if ($img) {\n                        $img.css('max-width', '50%');\n                    }\n                    // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                    return true;\n                }\n            }, {\n                selector: '#' + width100,\n                type: 'click',\n                fn: function fn() {\n                    var $img = editor._selectedImg;\n                    if ($img) {\n                        $img.css('max-width', '100%');\n                    }\n                    // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                    return true;\n                }\n            }, {\n                selector: '#' + delBtn,\n                type: 'click',\n                fn: function fn() {\n                    var $img = editor._selectedImg;\n                    if ($img) {\n                        $img.remove();\n                    }\n                    // 返回 true，表示该事件执行完之后，panel 要关闭。否则 panel 不会关闭\n                    return true;\n                }\n            }]\n        }];\n\n        // 创建 panel 并显示\n        var panel = new Panel(this, {\n            width: 300,\n            tabs: tabsConfig\n        });\n        panel.show();\n\n        // 记录属性\n        this.panel = panel;\n    },\n\n    _createInsertPanel: function _createInsertPanel() {\n        var editor = this.editor;\n        var uploadImg = editor.uploadImg;\n        var config = editor.config;\n\n        // id\n        var upTriggerId = getRandom('up-trigger');\n        var upFileId = getRandom('up-file');\n        var linkUrlId = getRandom('link-url');\n        var linkBtnId = getRandom('link-btn');\n\n        // tabs 的配置\n        var tabsConfig = [{\n            title: '上传图片',\n            tpl: '<div class=\"w-e-up-img-container\">\\n                    <div id=\"' + upTriggerId + '\" class=\"w-e-up-btn\">\\n                        <i class=\"w-e-icon-upload2\"></i>\\n                    </div>\\n                    <div style=\"display:none;\">\\n                        <input id=\"' + upFileId + '\" type=\"file\" multiple=\"multiple\" accept=\"image/jpg,image/jpeg,image/png,image/gif,image/bmp\"/>\\n                    </div>\\n                </div>',\n            events: [{\n                // 触发选择图片\n                selector: '#' + upTriggerId,\n                type: 'click',\n                fn: function fn() {\n                    var $file = $('#' + upFileId);\n                    var fileElem = $file[0];\n                    if (fileElem) {\n                        fileElem.click();\n                    } else {\n                        // 返回 true 可关闭 panel\n                        return true;\n                    }\n                }\n            }, {\n                // 选择图片完毕\n                selector: '#' + upFileId,\n                type: 'change',\n                fn: function fn() {\n                    var $file = $('#' + upFileId);\n                    var fileElem = $file[0];\n                    if (!fileElem) {\n                        // 返回 true 可关闭 panel\n                        return true;\n                    }\n\n                    // 获取选中的 file 对象列表\n                    var fileList = fileElem.files;\n                    if (fileList.length) {\n                        uploadImg.uploadImg(fileList);\n                    }\n\n                    // 返回 true 可关闭 panel\n                    return true;\n                }\n            }]\n        }, // first tab end\n        {\n            title: '网络图片',\n            tpl: '<div>\\n                    <input id=\"' + linkUrlId + '\" type=\"text\" class=\"block\" placeholder=\"\\u56FE\\u7247\\u94FE\\u63A5\"/></td>\\n                    <div class=\"w-e-button-container\">\\n                        <button id=\"' + linkBtnId + '\" class=\"right\">\\u63D2\\u5165</button>\\n                    </div>\\n                </div>',\n            events: [{\n                selector: '#' + linkBtnId,\n                type: 'click',\n                fn: function fn() {\n                    var $linkUrl = $('#' + linkUrlId);\n                    var url = $linkUrl.val().trim();\n\n                    if (url) {\n                        uploadImg.insertLinkImg(url);\n                    }\n\n                    // 返回 true 表示函数执行结束之后关闭 panel\n                    return true;\n                }\n            }]\n        } // second tab end\n        ]; // tabs end\n\n        // 判断 tabs 的显示\n        var tabsConfigResult = [];\n        if ((config.uploadImgShowBase64 || config.uploadImgServer || config.customUploadImg) && window.FileReader) {\n            // 显示“上传图片”\n            tabsConfigResult.push(tabsConfig[0]);\n        }\n        if (config.showLinkImg) {\n            // 显示“网络图片”\n            tabsConfigResult.push(tabsConfig[1]);\n        }\n\n        // 创建 panel 并显示\n        var panel = new Panel(this, {\n            width: 300,\n            tabs: tabsConfigResult\n        });\n        panel.show();\n\n        // 记录属性\n        this.panel = panel;\n    },\n\n    // 试图改变 active 状态\n    tryChangeActive: function tryChangeActive(e) {\n        var editor = this.editor;\n        var $elem = this.$elem;\n        if (editor._selectedImg) {\n            this._active = true;\n            $elem.addClass('w-e-active');\n        } else {\n            this._active = false;\n            $elem.removeClass('w-e-active');\n        }\n    }\n};\n\n/*\n    所有菜单的汇总\n*/\n\n// 存储菜单的构造函数\nvar MenuConstructors = {};\n\nMenuConstructors.bold = Bold;\n\nMenuConstructors.head = Head;\n\nMenuConstructors.link = Link;\n\nMenuConstructors.italic = Italic;\n\nMenuConstructors.redo = Redo;\n\nMenuConstructors.strikeThrough = StrikeThrough;\n\nMenuConstructors.underline = Underline;\n\nMenuConstructors.undo = Undo;\n\nMenuConstructors.list = List;\n\nMenuConstructors.justify = Justify;\n\nMenuConstructors.foreColor = ForeColor;\n\nMenuConstructors.backColor = BackColor;\n\nMenuConstructors.quote = Quote;\n\nMenuConstructors.code = Code;\n\nMenuConstructors.emoticon = Emoticon;\n\nMenuConstructors.table = Table;\n\nMenuConstructors.video = Video;\n\nMenuConstructors.image = Image;\n\n/*\n    菜单集合\n*/\n// 构造函数\nfunction Menus(editor) {\n    this.editor = editor;\n    this.menus = {};\n}\n\n// 修改原型\nMenus.prototype = {\n    constructor: Menus,\n\n    // 初始化菜单\n    init: function init() {\n        var _this = this;\n\n        var editor = this.editor;\n        var config = editor.config || {};\n        var configMenus = config.menus || []; // 获取配置中的菜单\n\n        // 根据配置信息，创建菜单\n        configMenus.forEach(function (menuKey) {\n            var MenuConstructor = MenuConstructors[menuKey];\n            if (MenuConstructor && typeof MenuConstructor === 'function') {\n                // 创建单个菜单\n                _this.menus[menuKey] = new MenuConstructor(editor);\n            }\n        });\n\n        // 添加到菜单栏\n        this._addToToolbar();\n\n        // 绑定事件\n        this._bindEvent();\n    },\n\n    // 添加到菜单栏\n    _addToToolbar: function _addToToolbar() {\n        var editor = this.editor;\n        var $toolbarElem = editor.$toolbarElem;\n        var menus = this.menus;\n        var config = editor.config;\n        // config.zIndex 是配置的编辑区域的 z-index，菜单的 z-index 得在其基础上 +1\n        var zIndex = config.zIndex + 1;\n        objForEach(menus, function (key, menu) {\n            var $elem = menu.$elem;\n            if ($elem) {\n                // 设置 z-index\n                $elem.css('z-index', zIndex);\n                $toolbarElem.append($elem);\n            }\n        });\n    },\n\n    // 绑定菜单 click mouseenter 事件\n    _bindEvent: function _bindEvent() {\n        var menus = this.menus;\n        var editor = this.editor;\n        objForEach(menus, function (key, menu) {\n            var type = menu.type;\n            if (!type) {\n                return;\n            }\n            var $elem = menu.$elem;\n            var droplist = menu.droplist;\n            var panel = menu.panel;\n\n            // 点击类型，例如 bold\n            if (type === 'click' && menu.onClick) {\n                $elem.on('click', function (e) {\n                    if (editor.selection.getRange() == null) {\n                        return;\n                    }\n                    menu.onClick(e);\n                });\n            }\n\n            // 下拉框，例如 head\n            if (type === 'droplist' && droplist) {\n                $elem.on('mouseenter', function (e) {\n                    if (editor.selection.getRange() == null) {\n                        return;\n                    }\n                    // 显示\n                    droplist.showTimeoutId = setTimeout(function () {\n                        droplist.show();\n                    }, 200);\n                }).on('mouseleave', function (e) {\n                    // 隐藏\n                    droplist.hideTimeoutId = setTimeout(function () {\n                        droplist.hide();\n                    }, 0);\n                });\n            }\n\n            // 弹框类型，例如 link\n            if (type === 'panel' && menu.onClick) {\n                $elem.on('click', function (e) {\n                    e.stopPropagation();\n                    if (editor.selection.getRange() == null) {\n                        return;\n                    }\n                    // 在自定义事件中显示 panel\n                    menu.onClick(e);\n                });\n            }\n        });\n    },\n\n    // 尝试修改菜单状态\n    changeActive: function changeActive() {\n        var menus = this.menus;\n        objForEach(menus, function (key, menu) {\n            if (menu.tryChangeActive) {\n                setTimeout(function () {\n                    menu.tryChangeActive();\n                }, 100);\n            }\n        });\n    }\n};\n\n/*\n    粘贴信息的处理\n*/\n\n// 获取粘贴的纯文本\nfunction getPasteText(e) {\n    var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData;\n    var pasteText = void 0;\n    if (clipboardData == null) {\n        pasteText = window.clipboardData && window.clipboardData.getData('text');\n    } else {\n        pasteText = clipboardData.getData('text/plain');\n    }\n\n    return replaceHtmlSymbol(pasteText);\n}\n\n// 获取粘贴的html\nfunction getPasteHtml(e, filterStyle) {\n    var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData;\n    var pasteText = void 0,\n        pasteHtml = void 0;\n    if (clipboardData == null) {\n        pasteText = window.clipboardData && window.clipboardData.getData('text');\n    } else {\n        pasteText = clipboardData.getData('text/plain');\n        pasteHtml = clipboardData.getData('text/html');\n    }\n    if (!pasteHtml && pasteText) {\n        pasteHtml = '<p>' + replaceHtmlSymbol(pasteText) + '</p>';\n    }\n    if (!pasteHtml) {\n        return;\n    }\n\n    // 过滤word中状态过来的无用字符\n    var docSplitHtml = pasteHtml.split('</html>');\n    if (docSplitHtml.length === 2) {\n        pasteHtml = docSplitHtml[0];\n    }\n\n    // 过滤无用标签\n    pasteHtml = pasteHtml.replace(/<(meta|script|link).+?>/igm, '');\n    // 去掉注释\n    pasteHtml = pasteHtml.replace(/<!--.*?-->/mg, '');\n    // 过滤 data-xxx 属性\n    pasteHtml = pasteHtml.replace(/\\s?data-.+?=('|\").+?('|\")/igm, '');\n\n    if (filterStyle) {\n        // 过滤样式\n        pasteHtml = pasteHtml.replace(/\\s?(class|style)=('|\").+?('|\")/igm, '');\n    } else {\n        // 保留样式\n        pasteHtml = pasteHtml.replace(/\\s?class=('|\").+?('|\")/igm, '');\n    }\n\n    return pasteHtml;\n}\n\n// 获取粘贴的图片文件\nfunction getPasteImgs(e) {\n    var result = [];\n    var txt = getPasteText(e);\n    if (txt) {\n        // 有文字，就忽略图片\n        return result;\n    }\n\n    var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData || {};\n    var items = clipboardData.items;\n    if (!items) {\n        return result;\n    }\n\n    objForEach(items, function (key, value) {\n        var type = value.type;\n        if (/image/i.test(type)) {\n            result.push(value.getAsFile());\n        }\n    });\n\n    return result;\n}\n\n/*\n    编辑区域\n*/\n\n// 获取一个 elem.childNodes 的 JSON 数据\nfunction getChildrenJSON($elem) {\n    var result = [];\n    var $children = $elem.childNodes() || []; // 注意 childNodes() 可以获取文本节点\n    $children.forEach(function (curElem) {\n        var elemResult = void 0;\n        var nodeType = curElem.nodeType;\n\n        // 文本节点\n        if (nodeType === 3) {\n            elemResult = curElem.textContent;\n        }\n\n        // 普通 DOM 节点\n        if (nodeType === 1) {\n            elemResult = {};\n\n            // tag\n            elemResult.tag = curElem.nodeName.toLowerCase();\n            // attr\n            var attrData = [];\n            var attrList = curElem.attributes || {};\n            var attrListLength = attrList.length || 0;\n            for (var i = 0; i < attrListLength; i++) {\n                var attr = attrList[i];\n                attrData.push({\n                    name: attr.name,\n                    value: attr.value\n                });\n            }\n            elemResult.attrs = attrData;\n            // children（递归）\n            elemResult.children = getChildrenJSON($(curElem));\n        }\n\n        result.push(elemResult);\n    });\n    return result;\n}\n\n// 构造函数\nfunction Text(editor) {\n    this.editor = editor;\n}\n\n// 修改原型\nText.prototype = {\n    constructor: Text,\n\n    // 初始化\n    init: function init() {\n        // 绑定事件\n        this._bindEvent();\n    },\n\n    // 清空内容\n    clear: function clear() {\n        this.html('<p><br></p>');\n    },\n\n    // 获取 设置 html\n    html: function html(val) {\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n        var html = void 0;\n        if (val == null) {\n            html = $textElem.html();\n            // 未选中任何内容的时候点击“加粗”或者“斜体”等按钮，就得需要一个空的占位符 &#8203 ，这里替换掉\n            html = html.replace(/\\u200b/gm, '');\n            return html;\n        } else {\n            $textElem.html(val);\n\n            // 初始化选取，将光标定位到内容尾部\n            editor.initSelection();\n        }\n    },\n\n    // 获取 JSON\n    getJSON: function getJSON() {\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n        return getChildrenJSON($textElem);\n    },\n\n    // 获取 设置 text\n    text: function text(val) {\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n        var text = void 0;\n        if (val == null) {\n            text = $textElem.text();\n            // 未选中任何内容的时候点击“加粗”或者“斜体”等按钮，就得需要一个空的占位符 &#8203 ，这里替换掉\n            text = text.replace(/\\u200b/gm, '');\n            return text;\n        } else {\n            $textElem.text('<p>' + val + '</p>');\n\n            // 初始化选取，将光标定位到内容尾部\n            editor.initSelection();\n        }\n    },\n\n    // 追加内容\n    append: function append(html) {\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n        $textElem.append($(html));\n\n        // 初始化选取，将光标定位到内容尾部\n        editor.initSelection();\n    },\n\n    // 绑定事件\n    _bindEvent: function _bindEvent() {\n        // 实时保存选取\n        this._saveRangeRealTime();\n\n        // 按回车建时的特殊处理\n        this._enterKeyHandle();\n\n        // 清空时保留 <p><br></p>\n        this._clearHandle();\n\n        // 粘贴事件（粘贴文字，粘贴图片）\n        this._pasteHandle();\n\n        // tab 特殊处理\n        this._tabHandle();\n\n        // img 点击\n        this._imgHandle();\n\n        // 拖拽事件\n        this._dragHandle();\n    },\n\n    // 实时保存选取\n    _saveRangeRealTime: function _saveRangeRealTime() {\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n\n        // 保存当前的选区\n        function saveRange(e) {\n            // 随时保存选区\n            editor.selection.saveRange();\n            // 更新按钮 ative 状态\n            editor.menus.changeActive();\n        }\n        // 按键后保存\n        $textElem.on('keyup', saveRange);\n        $textElem.on('mousedown', function (e) {\n            // mousedown 状态下，鼠标滑动到编辑区域外面，也需要保存选区\n            $textElem.on('mouseleave', saveRange);\n        });\n        $textElem.on('mouseup', function (e) {\n            saveRange();\n            // 在编辑器区域之内完成点击，取消鼠标滑动到编辑区外面的事件\n            $textElem.off('mouseleave', saveRange);\n        });\n    },\n\n    // 按回车键时的特殊处理\n    _enterKeyHandle: function _enterKeyHandle() {\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n\n        function insertEmptyP($selectionElem) {\n            var $p = $('<p><br></p>');\n            $p.insertBefore($selectionElem);\n            editor.selection.createRangeByElem($p, true);\n            editor.selection.restoreSelection();\n            $selectionElem.remove();\n        }\n\n        // 将回车之后生成的非 <p> 的顶级标签，改为 <p>\n        function pHandle(e) {\n            var $selectionElem = editor.selection.getSelectionContainerElem();\n            var $parentElem = $selectionElem.parent();\n\n            if ($parentElem.html() === '<code><br></code>') {\n                // 回车之前光标所在一个 <p><code>.....</code></p> ，忽然回车生成一个空的 <p><code><br></code></p>\n                // 而且继续回车跳不出去，因此只能特殊处理\n                insertEmptyP($selectionElem);\n                return;\n            }\n\n            if (!$parentElem.equal($textElem)) {\n                // 不是顶级标签\n                return;\n            }\n\n            var nodeName = $selectionElem.getNodeName();\n            if (nodeName === 'P') {\n                // 当前的标签是 P ，不用做处理\n                return;\n            }\n\n            if ($selectionElem.text()) {\n                // 有内容，不做处理\n                return;\n            }\n\n            // 插入 <p> ，并将选取定位到 <p>，删除当前标签\n            insertEmptyP($selectionElem);\n        }\n\n        $textElem.on('keyup', function (e) {\n            if (e.keyCode !== 13) {\n                // 不是回车键\n                return;\n            }\n            // 将回车之后生成的非 <p> 的顶级标签，改为 <p>\n            pHandle(e);\n        });\n\n        // <pre><code></code></pre> 回车时 特殊处理\n        function codeHandle(e) {\n            var $selectionElem = editor.selection.getSelectionContainerElem();\n            if (!$selectionElem) {\n                return;\n            }\n            var $parentElem = $selectionElem.parent();\n            var selectionNodeName = $selectionElem.getNodeName();\n            var parentNodeName = $parentElem.getNodeName();\n\n            if (selectionNodeName !== 'CODE' || parentNodeName !== 'PRE') {\n                // 不符合要求 忽略\n                return;\n            }\n\n            if (!editor.cmd.queryCommandSupported('insertHTML')) {\n                // 必须原生支持 insertHTML 命令\n                return;\n            }\n\n            // 处理：光标定位到代码末尾，联系点击两次回车，即跳出代码块\n            if (editor._willBreakCode === true) {\n                // 此时可以跳出代码块\n                // 插入 <p> ，并将选取定位到 <p>\n                var $p = $('<p><br></p>');\n                $p.insertAfter($parentElem);\n                editor.selection.createRangeByElem($p, true);\n                editor.selection.restoreSelection();\n\n                // 修改状态\n                editor._willBreakCode = false;\n\n                e.preventDefault();\n                return;\n            }\n\n            var _startOffset = editor.selection.getRange().startOffset;\n\n            // 处理：回车时，不能插入 <br> 而是插入 \\n ，因为是在 pre 标签里面\n            editor.cmd.do('insertHTML', '\\n');\n            editor.selection.saveRange();\n            if (editor.selection.getRange().startOffset === _startOffset) {\n                // 没起作用，再来一遍\n                editor.cmd.do('insertHTML', '\\n');\n            }\n\n            var codeLength = $selectionElem.html().length;\n            if (editor.selection.getRange().startOffset + 1 === codeLength) {\n                // 说明光标在代码最后的位置，执行了回车操作\n                // 记录下来，以便下次回车时候跳出 code\n                editor._willBreakCode = true;\n            }\n\n            // 阻止默认行为\n            e.preventDefault();\n        }\n\n        $textElem.on('keydown', function (e) {\n            if (e.keyCode !== 13) {\n                // 不是回车键\n                // 取消即将跳转代码块的记录\n                editor._willBreakCode = false;\n                return;\n            }\n            // <pre><code></code></pre> 回车时 特殊处理\n            codeHandle(e);\n        });\n    },\n\n    // 清空时保留 <p><br></p>\n    _clearHandle: function _clearHandle() {\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n\n        $textElem.on('keydown', function (e) {\n            if (e.keyCode !== 8) {\n                return;\n            }\n            var txtHtml = $textElem.html().toLowerCase().trim();\n            if (txtHtml === '<p><br></p>') {\n                // 最后剩下一个空行，就不再删除了\n                e.preventDefault();\n                return;\n            }\n        });\n\n        $textElem.on('keyup', function (e) {\n            if (e.keyCode !== 8) {\n                return;\n            }\n            var $p = void 0;\n            var txtHtml = $textElem.html().toLowerCase().trim();\n\n            // firefox 时用 txtHtml === '<br>' 判断，其他用 !txtHtml 判断\n            if (!txtHtml || txtHtml === '<br>') {\n                // 内容空了\n                $p = $('<p><br/></p>');\n                $textElem.html(''); // 一定要先清空，否则在 firefox 下有问题\n                $textElem.append($p);\n                editor.selection.createRangeByElem($p, false, true);\n                editor.selection.restoreSelection();\n            }\n        });\n    },\n\n    // 粘贴事件（粘贴文字 粘贴图片）\n    _pasteHandle: function _pasteHandle() {\n        var editor = this.editor;\n        var config = editor.config;\n        var pasteFilterStyle = config.pasteFilterStyle;\n        var pasteTextHandle = config.pasteTextHandle;\n        var $textElem = editor.$textElem;\n\n        // 粘贴图片、文本的事件，每次只能执行一个\n        // 判断该次粘贴事件是否可以执行\n        var pasteTime = 0;\n        function canDo() {\n            var now = Date.now();\n            var flag = false;\n            if (now - pasteTime >= 500) {\n                // 间隔大于 500 ms ，可以执行\n                flag = true;\n            }\n            pasteTime = now;\n            return flag;\n        }\n        function resetTime() {\n            pasteTime = 0;\n        }\n\n        // 粘贴文字\n        $textElem.on('paste', function (e) {\n            if (UA.isIE()) {\n                return;\n            } else {\n                // 阻止默认行为，使用 execCommand 的粘贴命令\n                e.preventDefault();\n            }\n\n            // 粘贴图片和文本，只能同时使用一个\n            if (!canDo()) {\n                return;\n            }\n\n            // 获取粘贴的文字\n            var pasteHtml = getPasteHtml(e, pasteFilterStyle);\n            var pasteText = getPasteText(e);\n            pasteText = pasteText.replace(/\\n/gm, '<br>');\n\n            var $selectionElem = editor.selection.getSelectionContainerElem();\n            if (!$selectionElem) {\n                return;\n            }\n            var nodeName = $selectionElem.getNodeName();\n\n            // code 中只能粘贴纯文本\n            if (nodeName === 'CODE' || nodeName === 'PRE') {\n                if (pasteTextHandle && isFunction(pasteTextHandle)) {\n                    // 用户自定义过滤处理粘贴内容\n                    pasteText = '' + (pasteTextHandle(pasteText) || '');\n                }\n                editor.cmd.do('insertHTML', '<p>' + pasteText + '</p>');\n                return;\n            }\n\n            // 先放开注释，有问题再追查 ————\n            // // 表格中忽略，可能会出现异常问题\n            // if (nodeName === 'TD' || nodeName === 'TH') {\n            //     return\n            // }\n\n            if (!pasteHtml) {\n                // 没有内容，可继续执行下面的图片粘贴\n                resetTime();\n                return;\n            }\n            try {\n                // firefox 中，获取的 pasteHtml 可能是没有 <ul> 包裹的 <li>\n                // 因此执行 insertHTML 会报错\n                if (pasteTextHandle && isFunction(pasteTextHandle)) {\n                    // 用户自定义过滤处理粘贴内容\n                    pasteHtml = '' + (pasteTextHandle(pasteHtml) || '');\n                }\n                editor.cmd.do('insertHTML', pasteHtml);\n            } catch (ex) {\n                // 此时使用 pasteText 来兼容一下\n                if (pasteTextHandle && isFunction(pasteTextHandle)) {\n                    // 用户自定义过滤处理粘贴内容\n                    pasteText = '' + (pasteTextHandle(pasteText) || '');\n                }\n                editor.cmd.do('insertHTML', '<p>' + pasteText + '</p>');\n            }\n        });\n\n        // 粘贴图片\n        $textElem.on('paste', function (e) {\n            if (UA.isIE()) {\n                return;\n            } else {\n                e.preventDefault();\n            }\n\n            // 粘贴图片和文本，只能同时使用一个\n            if (!canDo()) {\n                return;\n            }\n\n            // 获取粘贴的图片\n            var pasteFiles = getPasteImgs(e);\n            if (!pasteFiles || !pasteFiles.length) {\n                return;\n            }\n\n            // 获取当前的元素\n            var $selectionElem = editor.selection.getSelectionContainerElem();\n            if (!$selectionElem) {\n                return;\n            }\n            var nodeName = $selectionElem.getNodeName();\n\n            // code 中粘贴忽略\n            if (nodeName === 'CODE' || nodeName === 'PRE') {\n                return;\n            }\n\n            // 上传图片\n            var uploadImg = editor.uploadImg;\n            uploadImg.uploadImg(pasteFiles);\n        });\n    },\n\n    // tab 特殊处理\n    _tabHandle: function _tabHandle() {\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n\n        $textElem.on('keydown', function (e) {\n            if (e.keyCode !== 9) {\n                return;\n            }\n            if (!editor.cmd.queryCommandSupported('insertHTML')) {\n                // 必须原生支持 insertHTML 命令\n                return;\n            }\n            var $selectionElem = editor.selection.getSelectionContainerElem();\n            if (!$selectionElem) {\n                return;\n            }\n            var $parentElem = $selectionElem.parent();\n            var selectionNodeName = $selectionElem.getNodeName();\n            var parentNodeName = $parentElem.getNodeName();\n\n            if (selectionNodeName === 'CODE' && parentNodeName === 'PRE') {\n                // <pre><code> 里面\n                editor.cmd.do('insertHTML', '    ');\n            } else {\n                // 普通文字\n                editor.cmd.do('insertHTML', '&nbsp;&nbsp;&nbsp;&nbsp;');\n            }\n\n            e.preventDefault();\n        });\n    },\n\n    // img 点击\n    _imgHandle: function _imgHandle() {\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n\n        // 为图片增加 selected 样式\n        $textElem.on('click', 'img', function (e) {\n            var img = this;\n            var $img = $(img);\n\n            if ($img.attr('data-w-e') === '1') {\n                // 是表情图片，忽略\n                return;\n            }\n\n            // 记录当前点击过的图片\n            editor._selectedImg = $img;\n\n            // 修改选区并 restore ，防止用户此时点击退格键，会删除其他内容\n            editor.selection.createRangeByElem($img);\n            editor.selection.restoreSelection();\n        });\n\n        // 去掉图片的 selected 样式\n        $textElem.on('click  keyup', function (e) {\n            if (e.target.matches('img')) {\n                // 点击的是图片，忽略\n                return;\n            }\n            // 删除记录\n            editor._selectedImg = null;\n        });\n    },\n\n    // 拖拽事件\n    _dragHandle: function _dragHandle() {\n        var editor = this.editor;\n\n        // 禁用 document 拖拽事件\n        var $document = $(document);\n        $document.on('dragleave drop dragenter dragover', function (e) {\n            e.preventDefault();\n        });\n\n        // 添加编辑区域拖拽事件\n        var $textElem = editor.$textElem;\n        $textElem.on('drop', function (e) {\n            e.preventDefault();\n            var files = e.dataTransfer && e.dataTransfer.files;\n            if (!files || !files.length) {\n                return;\n            }\n\n            // 上传图片\n            var uploadImg = editor.uploadImg;\n            uploadImg.uploadImg(files);\n        });\n    }\n};\n\n/*\n    命令，封装 document.execCommand\n*/\n\n// 构造函数\nfunction Command(editor) {\n    this.editor = editor;\n}\n\n// 修改原型\nCommand.prototype = {\n    constructor: Command,\n\n    // 执行命令\n    do: function _do(name, value) {\n        var editor = this.editor;\n\n        // 如果无选区，忽略\n        if (!editor.selection.getRange()) {\n            return;\n        }\n\n        // 恢复选取\n        editor.selection.restoreSelection();\n\n        // 执行\n        var _name = '_' + name;\n        if (this[_name]) {\n            // 有自定义事件\n            this[_name](value);\n        } else {\n            // 默认 command\n            this._execCommand(name, value);\n        }\n\n        // 修改菜单状态\n        editor.menus.changeActive();\n\n        // 最后，恢复选取保证光标在原来的位置闪烁\n        editor.selection.saveRange();\n        editor.selection.restoreSelection();\n\n        // 触发 onchange\n        editor.change && editor.change();\n    },\n\n    // 自定义 insertHTML 事件\n    _insertHTML: function _insertHTML(html) {\n        var editor = this.editor;\n        var range = editor.selection.getRange();\n\n        if (this.queryCommandSupported('insertHTML')) {\n            // W3C\n            this._execCommand('insertHTML', html);\n        } else if (range.insertNode) {\n            // IE\n            range.deleteContents();\n            range.insertNode($(html)[0]);\n        } else if (range.pasteHTML) {\n            // IE <= 10\n            range.pasteHTML(html);\n        }\n    },\n\n    // 插入 elem\n    _insertElem: function _insertElem($elem) {\n        var editor = this.editor;\n        var range = editor.selection.getRange();\n\n        if (range.insertNode) {\n            range.deleteContents();\n            range.insertNode($elem[0]);\n        }\n    },\n\n    // 封装 execCommand\n    _execCommand: function _execCommand(name, value) {\n        document.execCommand(name, false, value);\n    },\n\n    // 封装 document.queryCommandValue\n    queryCommandValue: function queryCommandValue(name) {\n        return document.queryCommandValue(name);\n    },\n\n    // 封装 document.queryCommandState\n    queryCommandState: function queryCommandState(name) {\n        return document.queryCommandState(name);\n    },\n\n    // 封装 document.queryCommandSupported\n    queryCommandSupported: function queryCommandSupported(name) {\n        return document.queryCommandSupported(name);\n    }\n};\n\n/*\n    selection range API\n*/\n\n// 构造函数\nfunction API(editor) {\n    this.editor = editor;\n    this._currentRange = null;\n}\n\n// 修改原型\nAPI.prototype = {\n    constructor: API,\n\n    // 获取 range 对象\n    getRange: function getRange() {\n        return this._currentRange;\n    },\n\n    // 保存选区\n    saveRange: function saveRange(_range) {\n        if (_range) {\n            // 保存已有选区\n            this._currentRange = _range;\n            return;\n        }\n\n        // 获取当前的选区\n        var selection = window.getSelection();\n        if (selection.rangeCount === 0) {\n            return;\n        }\n        var range = selection.getRangeAt(0);\n\n        // 判断选区内容是否在编辑内容之内\n        var $containerElem = this.getSelectionContainerElem(range);\n        if (!$containerElem) {\n            return;\n        }\n        var editor = this.editor;\n        var $textElem = editor.$textElem;\n        if ($textElem.isContain($containerElem)) {\n            // 是编辑内容之内的\n            this._currentRange = range;\n        }\n    },\n\n    // 折叠选区\n    collapseRange: function collapseRange(toStart) {\n        if (toStart == null) {\n            // 默认为 false\n            toStart = false;\n        }\n        var range = this._currentRange;\n        if (range) {\n            range.collapse(toStart);\n        }\n    },\n\n    // 选中区域的文字\n    getSelectionText: function getSelectionText() {\n        var range = this._currentRange;\n        if (range) {\n            return this._currentRange.toString();\n        } else {\n            return '';\n        }\n    },\n\n    // 选区的 $Elem\n    getSelectionContainerElem: function getSelectionContainerElem(range) {\n        range = range || this._currentRange;\n        var elem = void 0;\n        if (range) {\n            elem = range.commonAncestorContainer;\n            return $(elem.nodeType === 1 ? elem : elem.parentNode);\n        }\n    },\n    getSelectionStartElem: function getSelectionStartElem(range) {\n        range = range || this._currentRange;\n        var elem = void 0;\n        if (range) {\n            elem = range.startContainer;\n            return $(elem.nodeType === 1 ? elem : elem.parentNode);\n        }\n    },\n    getSelectionEndElem: function getSelectionEndElem(range) {\n        range = range || this._currentRange;\n        var elem = void 0;\n        if (range) {\n            elem = range.endContainer;\n            return $(elem.nodeType === 1 ? elem : elem.parentNode);\n        }\n    },\n\n    // 选区是否为空\n    isSelectionEmpty: function isSelectionEmpty() {\n        var range = this._currentRange;\n        if (range && range.startContainer) {\n            if (range.startContainer === range.endContainer) {\n                if (range.startOffset === range.endOffset) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    },\n\n    // 恢复选区\n    restoreSelection: function restoreSelection() {\n        var selection = window.getSelection();\n        selection.removeAllRanges();\n        selection.addRange(this._currentRange);\n    },\n\n    // 创建一个空白（即 &#8203 字符）选区\n    createEmptyRange: function createEmptyRange() {\n        var editor = this.editor;\n        var range = this.getRange();\n        var $elem = void 0;\n\n        if (!range) {\n            // 当前无 range\n            return;\n        }\n        if (!this.isSelectionEmpty()) {\n            // 当前选区必须没有内容才可以\n            return;\n        }\n\n        try {\n            // 目前只支持 webkit 内核\n            if (UA.isWebkit()) {\n                // 插入 &#8203\n                editor.cmd.do('insertHTML', '&#8203;');\n                // 修改 offset 位置\n                range.setEnd(range.endContainer, range.endOffset + 1);\n                // 存储\n                this.saveRange(range);\n            } else {\n                $elem = $('<strong>&#8203;</strong>');\n                editor.cmd.do('insertElem', $elem);\n                this.createRangeByElem($elem, true);\n            }\n        } catch (ex) {\n            // 部分情况下会报错，兼容一下\n        }\n    },\n\n    // 根据 $Elem 设置选区\n    createRangeByElem: function createRangeByElem($elem, toStart, isContent) {\n        // $elem - 经过封装的 elem\n        // toStart - true 开始位置，false 结束位置\n        // isContent - 是否选中Elem的内容\n        if (!$elem.length) {\n            return;\n        }\n\n        var elem = $elem[0];\n        var range = document.createRange();\n\n        if (isContent) {\n            range.selectNodeContents(elem);\n        } else {\n            range.selectNode(elem);\n        }\n\n        if (typeof toStart === 'boolean') {\n            range.collapse(toStart);\n        }\n\n        // 存储 range\n        this.saveRange(range);\n    }\n};\n\n/*\n    上传进度条\n*/\n\nfunction Progress(editor) {\n    this.editor = editor;\n    this._time = 0;\n    this._isShow = false;\n    this._isRender = false;\n    this._timeoutId = 0;\n    this.$textContainer = editor.$textContainerElem;\n    this.$bar = $('<div class=\"w-e-progress\"></div>');\n}\n\nProgress.prototype = {\n    constructor: Progress,\n\n    show: function show(progress) {\n        var _this = this;\n\n        // 状态处理\n        if (this._isShow) {\n            return;\n        }\n        this._isShow = true;\n\n        // 渲染\n        var $bar = this.$bar;\n        if (!this._isRender) {\n            var $textContainer = this.$textContainer;\n            $textContainer.append($bar);\n        } else {\n            this._isRender = true;\n        }\n\n        // 改变进度（节流，100ms 渲染一次）\n        if (Date.now() - this._time > 100) {\n            if (progress <= 1) {\n                $bar.css('width', progress * 100 + '%');\n                this._time = Date.now();\n            }\n        }\n\n        // 隐藏\n        var timeoutId = this._timeoutId;\n        if (timeoutId) {\n            clearTimeout(timeoutId);\n        }\n        timeoutId = setTimeout(function () {\n            _this._hide();\n        }, 500);\n    },\n\n    _hide: function _hide() {\n        var $bar = this.$bar;\n        $bar.remove();\n\n        // 修改状态\n        this._time = 0;\n        this._isShow = false;\n        this._isRender = false;\n    }\n};\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) {\n  return typeof obj;\n} : function (obj) {\n  return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n};\n\n/*\n    上传图片\n*/\n\n// 构造函数\nfunction UploadImg(editor) {\n    this.editor = editor;\n}\n\n// 原型\nUploadImg.prototype = {\n    constructor: UploadImg,\n\n    // 根据 debug 弹出不同的信息\n    _alert: function _alert(alertInfo, debugInfo) {\n        var editor = this.editor;\n        var debug = editor.config.debug;\n        var customAlert = editor.config.customAlert;\n\n        if (debug) {\n            throw new Error('wangEditor: ' + (debugInfo || alertInfo));\n        } else {\n            if (customAlert && typeof customAlert === 'function') {\n                customAlert(alertInfo);\n            } else {\n                alert(alertInfo);\n            }\n        }\n    },\n\n    // 根据链接插入图片\n    insertLinkImg: function insertLinkImg(link) {\n        var _this2 = this;\n\n        if (!link) {\n            return;\n        }\n        var editor = this.editor;\n        var config = editor.config;\n\n        // 校验格式\n        var linkImgCheck = config.linkImgCheck;\n        var checkResult = void 0;\n        if (linkImgCheck && typeof linkImgCheck === 'function') {\n            checkResult = linkImgCheck(link);\n            if (typeof checkResult === 'string') {\n                // 校验失败，提示信息\n                alert(checkResult);\n                return;\n            }\n        }\n\n        editor.cmd.do('insertHTML', '<img src=\"' + link + '\" style=\"max-width:100%;\"/>');\n\n        // 验证图片 url 是否有效，无效的话给出提示\n        var img = document.createElement('img');\n        img.onload = function () {\n            var callback = config.linkImgCallback;\n            if (callback && typeof callback === 'function') {\n                callback(link);\n            }\n\n            img = null;\n        };\n        img.onerror = function () {\n            img = null;\n            // 无法成功下载图片\n            _this2._alert('插入图片错误', 'wangEditor: \\u63D2\\u5165\\u56FE\\u7247\\u51FA\\u9519\\uFF0C\\u56FE\\u7247\\u94FE\\u63A5\\u662F \"' + link + '\"\\uFF0C\\u4E0B\\u8F7D\\u8BE5\\u94FE\\u63A5\\u5931\\u8D25');\n            return;\n        };\n        img.onabort = function () {\n            img = null;\n        };\n        img.src = link;\n    },\n\n    // 上传图片\n    uploadImg: function uploadImg(files) {\n        var _this3 = this;\n\n        if (!files || !files.length) {\n            return;\n        }\n\n        // ------------------------------ 获取配置信息 ------------------------------\n        var editor = this.editor;\n        var config = editor.config;\n        var uploadImgServer = config.uploadImgServer;\n        var uploadImgShowBase64 = config.uploadImgShowBase64;\n\n        var maxSize = config.uploadImgMaxSize;\n        var maxSizeM = maxSize / 1024 / 1024;\n        var maxLength = config.uploadImgMaxLength || 10000;\n        var uploadFileName = config.uploadFileName || '';\n        var uploadImgParams = config.uploadImgParams || {};\n        var uploadImgParamsWithUrl = config.uploadImgParamsWithUrl;\n        var uploadImgHeaders = config.uploadImgHeaders || {};\n        var hooks = config.uploadImgHooks || {};\n        var timeout = config.uploadImgTimeout || 3000;\n        var withCredentials = config.withCredentials;\n        if (withCredentials == null) {\n            withCredentials = false;\n        }\n        var customUploadImg = config.customUploadImg;\n\n        if (!customUploadImg) {\n            // 没有 customUploadImg 的情况下，需要如下两个配置才能继续进行图片上传\n            if (!uploadImgServer && !uploadImgShowBase64) {\n                return;\n            }\n        }\n\n        // ------------------------------ 验证文件信息 ------------------------------\n        var resultFiles = [];\n        var errInfo = [];\n        arrForEach(files, function (file) {\n            var name = file.name;\n            var size = file.size;\n\n            // chrome 低版本 name === undefined\n            if (!name || !size) {\n                return;\n            }\n\n            if (/\\.(jpg|jpeg|png|bmp|gif)$/i.test(name) === false) {\n                // 后缀名不合法，不是图片\n                errInfo.push('\\u3010' + name + '\\u3011\\u4E0D\\u662F\\u56FE\\u7247');\n                return;\n            }\n            if (maxSize < size) {\n                // 上传图片过大\n                errInfo.push('\\u3010' + name + '\\u3011\\u5927\\u4E8E ' + maxSizeM + 'M');\n                return;\n            }\n\n            // 验证通过的加入结果列表\n            resultFiles.push(file);\n        });\n        // 抛出验证信息\n        if (errInfo.length) {\n            this._alert('图片验证未通过: \\n' + errInfo.join('\\n'));\n            return;\n        }\n        if (resultFiles.length > maxLength) {\n            this._alert('一次最多上传' + maxLength + '张图片');\n            return;\n        }\n\n        // ------------------------------ 自定义上传 ------------------------------\n        if (customUploadImg && typeof customUploadImg === 'function') {\n            customUploadImg(resultFiles, this.insertLinkImg.bind(this));\n\n            // 阻止以下代码执行\n            return;\n        }\n\n        // 添加图片数据\n        var formdata = new FormData();\n        arrForEach(resultFiles, function (file) {\n            var name = uploadFileName || file.name;\n            formdata.append(name, file);\n        });\n\n        // ------------------------------ 上传图片 ------------------------------\n        if (uploadImgServer && typeof uploadImgServer === 'string') {\n            // 添加参数\n            var uploadImgServerArr = uploadImgServer.split('#');\n            uploadImgServer = uploadImgServerArr[0];\n            var uploadImgServerHash = uploadImgServerArr[1] || '';\n            objForEach(uploadImgParams, function (key, val) {\n                val = encodeURIComponent(val);\n\n                // 第一，将参数拼接到 url 中\n                if (uploadImgParamsWithUrl) {\n                    if (uploadImgServer.indexOf('?') > 0) {\n                        uploadImgServer += '&';\n                    } else {\n                        uploadImgServer += '?';\n                    }\n                    uploadImgServer = uploadImgServer + key + '=' + val;\n                }\n\n                // 第二，将参数添加到 formdata 中\n                formdata.append(key, val);\n            });\n            if (uploadImgServerHash) {\n                uploadImgServer += '#' + uploadImgServerHash;\n            }\n\n            // 定义 xhr\n            var xhr = new XMLHttpRequest();\n            xhr.open('POST', uploadImgServer);\n\n            // 设置超时\n            xhr.timeout = timeout;\n            xhr.ontimeout = function () {\n                // hook - timeout\n                if (hooks.timeout && typeof hooks.timeout === 'function') {\n                    hooks.timeout(xhr, editor);\n                }\n\n                _this3._alert('上传图片超时');\n            };\n\n            // 监控 progress\n            if (xhr.upload) {\n                xhr.upload.onprogress = function (e) {\n                    var percent = void 0;\n                    // 进度条\n                    var progressBar = new Progress(editor);\n                    if (e.lengthComputable) {\n                        percent = e.loaded / e.total;\n                        progressBar.show(percent);\n                    }\n                };\n            }\n\n            // 返回数据\n            xhr.onreadystatechange = function () {\n                var result = void 0;\n                if (xhr.readyState === 4) {\n                    if (xhr.status < 200 || xhr.status >= 300) {\n                        // hook - error\n                        if (hooks.error && typeof hooks.error === 'function') {\n                            hooks.error(xhr, editor);\n                        }\n\n                        // xhr 返回状态错误\n                        _this3._alert('上传图片发生错误', '\\u4E0A\\u4F20\\u56FE\\u7247\\u53D1\\u751F\\u9519\\u8BEF\\uFF0C\\u670D\\u52A1\\u5668\\u8FD4\\u56DE\\u72B6\\u6001\\u662F ' + xhr.status);\n                        return;\n                    }\n\n                    result = xhr.responseText;\n                    if ((typeof result === 'undefined' ? 'undefined' : _typeof(result)) !== 'object') {\n                        try {\n                            result = JSON.parse(result);\n                        } catch (ex) {\n                            // hook - fail\n                            if (hooks.fail && typeof hooks.fail === 'function') {\n                                hooks.fail(xhr, editor, result);\n                            }\n\n                            _this3._alert('上传图片失败', '上传图片返回结果错误，返回结果是: ' + result);\n                            return;\n                        }\n                    }\n                    if (!hooks.customInsert && result.errno != '0') {\n                        // hook - fail\n                        if (hooks.fail && typeof hooks.fail === 'function') {\n                            hooks.fail(xhr, editor, result);\n                        }\n\n                        // 数据错误\n                        _this3._alert('上传图片失败', '上传图片返回结果错误，返回结果 errno=' + result.errno);\n                    } else {\n                        if (hooks.customInsert && typeof hooks.customInsert === 'function') {\n                            // 使用者自定义插入方法\n                            hooks.customInsert(_this3.insertLinkImg.bind(_this3), result, editor);\n                        } else {\n                            // 将图片插入编辑器\n                            var data = result.data || [];\n                            data.forEach(function (link) {\n                                _this3.insertLinkImg(link);\n                            });\n                        }\n\n                        // hook - success\n                        if (hooks.success && typeof hooks.success === 'function') {\n                            hooks.success(xhr, editor, result);\n                        }\n                    }\n                }\n            };\n\n            // hook - before\n            if (hooks.before && typeof hooks.before === 'function') {\n                var beforeResult = hooks.before(xhr, editor, resultFiles);\n                if (beforeResult && (typeof beforeResult === 'undefined' ? 'undefined' : _typeof(beforeResult)) === 'object') {\n                    if (beforeResult.prevent) {\n                        // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传\n                        this._alert(beforeResult.msg);\n                        return;\n                    }\n                }\n            }\n\n            // 自定义 headers\n            objForEach(uploadImgHeaders, function (key, val) {\n                xhr.setRequestHeader(key, val);\n            });\n\n            // 跨域传 cookie\n            xhr.withCredentials = withCredentials;\n\n            // 发送请求\n            xhr.send(formdata);\n\n            // 注意，要 return 。不去操作接下来的 base64 显示方式\n            return;\n        }\n\n        // ------------------------------ 显示 base64 格式 ------------------------------\n        if (uploadImgShowBase64) {\n            arrForEach(files, function (file) {\n                var _this = _this3;\n                var reader = new FileReader();\n                reader.readAsDataURL(file);\n                reader.onload = function () {\n                    _this.insertLinkImg(this.result);\n                };\n            });\n        }\n    }\n};\n\n/*\n    编辑器构造函数\n*/\n\n// id，累加\nvar editorId = 1;\n\n// 构造函数\nfunction Editor(toolbarSelector, textSelector) {\n    if (toolbarSelector == null) {\n        // 没有传入任何参数，报错\n        throw new Error('错误：初始化编辑器时候未传入任何参数，请查阅文档');\n    }\n    // id，用以区分单个页面不同的编辑器对象\n    this.id = 'wangEditor-' + editorId++;\n\n    this.toolbarSelector = toolbarSelector;\n    this.textSelector = textSelector;\n\n    // 自定义配置\n    this.customConfig = {};\n}\n\n// 修改原型\nEditor.prototype = {\n    constructor: Editor,\n\n    // 初始化配置\n    _initConfig: function _initConfig() {\n        // _config 是默认配置，this.customConfig 是用户自定义配置，将它们 merge 之后再赋值\n        var target = {};\n        this.config = Object.assign(target, config, this.customConfig);\n\n        // 将语言配置，生成正则表达式\n        var langConfig = this.config.lang || {};\n        var langArgs = [];\n        objForEach(langConfig, function (key, val) {\n            // key 即需要生成正则表达式的规则，如“插入链接”\n            // val 即需要被替换成的语言，如“insert link”\n            langArgs.push({\n                reg: new RegExp(key, 'img'),\n                val: val\n\n            });\n        });\n        this.config.langArgs = langArgs;\n    },\n\n    // 初始化 DOM\n    _initDom: function _initDom() {\n        var _this = this;\n\n        var toolbarSelector = this.toolbarSelector;\n        var $toolbarSelector = $(toolbarSelector);\n        var textSelector = this.textSelector;\n\n        var config$$1 = this.config;\n        var zIndex = config$$1.zIndex;\n\n        // 定义变量\n        var $toolbarElem = void 0,\n            $textContainerElem = void 0,\n            $textElem = void 0,\n            $children = void 0;\n\n        if (textSelector == null) {\n            // 只传入一个参数，即是容器的选择器或元素，toolbar 和 text 的元素自行创建\n            $toolbarElem = $('<div></div>');\n            $textContainerElem = $('<div></div>');\n\n            // 将编辑器区域原有的内容，暂存起来\n            $children = $toolbarSelector.children();\n\n            // 添加到 DOM 结构中\n            $toolbarSelector.append($toolbarElem).append($textContainerElem);\n\n            // 自行创建的，需要配置默认的样式\n            $toolbarElem.css('background-color', '#f1f1f1').css('border', '1px solid #ccc');\n            $textContainerElem.css('border', '1px solid #ccc').css('border-top', 'none').css('height', '300px');\n        } else {\n            // toolbar 和 text 的选择器都有值，记录属性\n            $toolbarElem = $toolbarSelector;\n            $textContainerElem = $(textSelector);\n            // 将编辑器区域原有的内容，暂存起来\n            $children = $textContainerElem.children();\n        }\n\n        // 编辑区域\n        $textElem = $('<div></div>');\n        $textElem.attr('contenteditable', 'true').css('width', '100%').css('height', '100%');\n\n        // 初始化编辑区域内容\n        if ($children && $children.length) {\n            $textElem.append($children);\n        } else {\n            $textElem.append($('<p><br></p>'));\n        }\n\n        // 编辑区域加入DOM\n        $textContainerElem.append($textElem);\n\n        // 设置通用的 class\n        $toolbarElem.addClass('w-e-toolbar');\n        $textContainerElem.addClass('w-e-text-container');\n        $textContainerElem.css('z-index', zIndex);\n        $textElem.addClass('w-e-text');\n\n        // 添加 ID\n        var toolbarElemId = getRandom('toolbar-elem');\n        $toolbarElem.attr('id', toolbarElemId);\n        var textElemId = getRandom('text-elem');\n        $textElem.attr('id', textElemId);\n\n        // 记录属性\n        this.$toolbarElem = $toolbarElem;\n        this.$textContainerElem = $textContainerElem;\n        this.$textElem = $textElem;\n        this.toolbarElemId = toolbarElemId;\n        this.textElemId = textElemId;\n\n        // 记录输入法的开始和结束\n        var compositionEnd = true;\n        $textContainerElem.on('compositionstart', function () {\n            // 输入法开始输入\n            compositionEnd = false;\n        });\n        $textContainerElem.on('compositionend', function () {\n            // 输入法结束输入\n            compositionEnd = true;\n        });\n\n        // 绑定 onchange\n        $textContainerElem.on('click keyup', function () {\n            // 输入法结束才出发 onchange\n            compositionEnd && _this.change && _this.change();\n        });\n        $toolbarElem.on('click', function () {\n            this.change && this.change();\n        });\n\n        //绑定 onfocus 与 onblur 事件\n        if (config$$1.onfocus || config$$1.onblur) {\n            // 当前编辑器是否是焦点状态\n            this.isFocus = false;\n\n            $(document).on('click', function (e) {\n                //判断当前点击元素是否在编辑器内\n                var isChild = $toolbarSelector.isContain($(e.target));\n\n                if (!isChild) {\n                    if (_this.isFocus) {\n                        _this.onblur && _this.onblur();\n                    }\n                    _this.isFocus = false;\n                } else {\n                    if (!_this.isFocus) {\n                        _this.onfocus && _this.onfocus();\n                    }\n                    _this.isFocus = true;\n                }\n            });\n        }\n    },\n\n    // 封装 command\n    _initCommand: function _initCommand() {\n        this.cmd = new Command(this);\n    },\n\n    // 封装 selection range API\n    _initSelectionAPI: function _initSelectionAPI() {\n        this.selection = new API(this);\n    },\n\n    // 添加图片上传\n    _initUploadImg: function _initUploadImg() {\n        this.uploadImg = new UploadImg(this);\n    },\n\n    // 初始化菜单\n    _initMenus: function _initMenus() {\n        this.menus = new Menus(this);\n        this.menus.init();\n    },\n\n    // 添加 text 区域\n    _initText: function _initText() {\n        this.txt = new Text(this);\n        this.txt.init();\n    },\n\n    // 初始化选区，将光标定位到内容尾部\n    initSelection: function initSelection(newLine) {\n        var $textElem = this.$textElem;\n        var $children = $textElem.children();\n        if (!$children.length) {\n            // 如果编辑器区域无内容，添加一个空行，重新设置选区\n            $textElem.append($('<p><br></p>'));\n            this.initSelection();\n            return;\n        }\n\n        var $last = $children.last();\n\n        if (newLine) {\n            // 新增一个空行\n            var html = $last.html().toLowerCase();\n            var nodeName = $last.getNodeName();\n            if (html !== '<br>' && html !== '<br\\/>' || nodeName !== 'P') {\n                // 最后一个元素不是 <p><br></p>，添加一个空行，重新设置选区\n                $textElem.append($('<p><br></p>'));\n                this.initSelection();\n                return;\n            }\n        }\n\n        this.selection.createRangeByElem($last, false, true);\n        this.selection.restoreSelection();\n    },\n\n    // 绑定事件\n    _bindEvent: function _bindEvent() {\n        // -------- 绑定 onchange 事件 --------\n        var onChangeTimeoutId = 0;\n        var beforeChangeHtml = this.txt.html();\n        var config$$1 = this.config;\n\n        // onchange 触发延迟时间\n        var onchangeTimeout = config$$1.onchangeTimeout;\n        onchangeTimeout = parseInt(onchangeTimeout, 10);\n        if (!onchangeTimeout || onchangeTimeout <= 0) {\n            onchangeTimeout = 200;\n        }\n\n        var onchange = config$$1.onchange;\n        if (onchange && typeof onchange === 'function') {\n            // 触发 change 的有三个场景：\n            // 1. $textContainerElem.on('click keyup')\n            // 2. $toolbarElem.on('click')\n            // 3. editor.cmd.do()\n            this.change = function () {\n                // 判断是否有变化\n                var currentHtml = this.txt.html();\n\n                if (currentHtml.length === beforeChangeHtml.length) {\n                    // 需要比较每一个字符\n                    if (currentHtml === beforeChangeHtml) {\n                        return;\n                    }\n                }\n\n                // 执行，使用节流\n                if (onChangeTimeoutId) {\n                    clearTimeout(onChangeTimeoutId);\n                }\n                onChangeTimeoutId = setTimeout(function () {\n                    // 触发配置的 onchange 函数\n                    onchange(currentHtml);\n                    beforeChangeHtml = currentHtml;\n                }, onchangeTimeout);\n            };\n        }\n\n        // -------- 绑定 onblur 事件 --------\n        var onblur = config$$1.onblur;\n        if (onblur && typeof onblur === 'function') {\n            this.onblur = function () {\n                var currentHtml = this.txt.html();\n                onblur(currentHtml);\n            };\n        }\n\n        // -------- 绑定 onfocus 事件 --------\n        var onfocus = config$$1.onfocus;\n        if (onfocus && typeof onfocus === 'function') {\n            this.onfocus = function () {\n                onfocus();\n            };\n        }\n    },\n\n    // 创建编辑器\n    create: function create() {\n        // 初始化配置信息\n        this._initConfig();\n\n        // 初始化 DOM\n        this._initDom();\n\n        // 封装 command API\n        this._initCommand();\n\n        // 封装 selection range API\n        this._initSelectionAPI();\n\n        // 添加 text\n        this._initText();\n\n        // 初始化菜单\n        this._initMenus();\n\n        // 添加 图片上传\n        this._initUploadImg();\n\n        // 初始化选区，将光标定位到内容尾部\n        this.initSelection(true);\n\n        // 绑定事件\n        this._bindEvent();\n    },\n\n    // 解绑所有事件（暂时不对外开放）\n    _offAllEvent: function _offAllEvent() {\n        $.offAll();\n    }\n};\n\n// 检验是否浏览器环境\ntry {\n    document;\n} catch (ex) {\n    throw new Error('请在浏览器环境下运行');\n}\n\n// polyfill\npolyfill();\n\n// 这里的 `inlinecss` 将被替换成 css 代码的内容，详情可去 ./gulpfile.js 中搜索 `inlinecss` 关键字\nvar inlinecss = '.w-e-toolbar,.w-e-text-container,.w-e-menu-panel {  padding: 0;  margin: 0;  box-sizing: border-box;}.w-e-toolbar *,.w-e-text-container *,.w-e-menu-panel * {  padding: 0;  margin: 0;  box-sizing: border-box;}.w-e-clear-fix:after {  content: \"\";  display: table;  clear: both;}.w-e-toolbar .w-e-droplist {  position: absolute;  left: 0;  top: 0;  background-color: #fff;  border: 1px solid #f1f1f1;  border-right-color: #ccc;  border-bottom-color: #ccc;}.w-e-toolbar .w-e-droplist .w-e-dp-title {  text-align: center;  color: #999;  line-height: 2;  border-bottom: 1px solid #f1f1f1;  font-size: 13px;}.w-e-toolbar .w-e-droplist ul.w-e-list {  list-style: none;  line-height: 1;}.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item {  color: #333;  padding: 5px 0;}.w-e-toolbar .w-e-droplist ul.w-e-list li.w-e-item:hover {  background-color: #f1f1f1;}.w-e-toolbar .w-e-droplist ul.w-e-block {  list-style: none;  text-align: left;  padding: 5px;}.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item {  display: inline-block;  *display: inline;  *zoom: 1;  padding: 3px 5px;}.w-e-toolbar .w-e-droplist ul.w-e-block li.w-e-item:hover {  background-color: #f1f1f1;}@font-face {  font-family: \\'w-e-icon\\';  src: url(data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAABXAAAsAAAAAFXQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABPUy8yAAABCAAAAGAAAABgDxIPAmNtYXAAAAFoAAAA9AAAAPRAxxN6Z2FzcAAAAlwAAAAIAAAACAAAABBnbHlmAAACZAAAEHwAABB8kRGt5WhlYWQAABLgAAAANgAAADYN4rlyaGhlYQAAExgAAAAkAAAAJAfEA99obXR4AAATPAAAAHwAAAB8cAcDvGxvY2EAABO4AAAAQAAAAEAx8jYEbWF4cAAAE/gAAAAgAAAAIAAqALZuYW1lAAAUGAAAAYYAAAGGmUoJ+3Bvc3QAABWgAAAAIAAAACAAAwAAAAMD3AGQAAUAAAKZAswAAACPApkCzAAAAesAMwEJAAAAAAAAAAAAAAAAAAAAARAAAAAAAAAAAAAAAAAAAAAAQAAA8fwDwP/AAEADwABAAAAAAQAAAAAAAAAAAAAAIAAAAAAAAwAAAAMAAAAcAAEAAwAAABwAAwABAAAAHAAEANgAAAAyACAABAASAAEAIOkG6Q3pEulH6Wbpd+m56bvpxunL6d/qDepl6mjqcep58A3wFPEg8dzx/P/9//8AAAAAACDpBukN6RLpR+ll6Xfpuem76cbpy+nf6g3qYupo6nHqd/AN8BTxIPHc8fz//f//AAH/4xb+FvgW9BbAFqMWkxZSFlEWRxZDFjAWAxWvFa0VpRWgEA0QBw78DkEOIgADAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAH//wAPAAEAAAAAAAAAAAACAAA3OQEAAAAAAQAAAAAAAAAAAAIAADc5AQAAAAABAAAAAAAAAAAAAgAANzkBAAAAAAIAAP/ABAADwAAEABMAAAE3AScBAy4BJxM3ASMBAyUBNQEHAYCAAcBA/kCfFzsyY4ABgMD+gMACgAGA/oBOAUBAAcBA/kD+nTI7FwERTgGA/oD9gMABgMD+gIAABAAAAAAEAAOAABAAIQAtADQAAAE4ATEROAExITgBMRE4ATEhNSEiBhURFBYzITI2NRE0JiMHFAYjIiY1NDYzMhYTITUTATM3A8D8gAOA/IAaJiYaA4AaJiYagDgoKDg4KCg4QP0A4AEAQOADQP0AAwBAJhr9ABomJhoDABom4Cg4OCgoODj9uIABgP7AwAAAAgAAAEAEAANAACgALAAAAS4DIyIOAgcOAxUUHgIXHgMzMj4CNz4DNTQuAicBEQ0BA9U2cXZ5Pz95dnE2Cw8LBgYLDws2cXZ5Pz95dnE2Cw8LBgYLDwv9qwFA/sADIAgMCAQECAwIKVRZWy8vW1lUKQgMCAQECAwIKVRZWy8vW1lUKf3gAYDAwAAAAAACAMD/wANAA8AAEwAfAAABIg4CFRQeAjEwPgI1NC4CAyImNTQ2MzIWFRQGAgBCdVcyZHhkZHhkMld1QlBwcFBQcHADwDJXdUJ4+syCgsz6eEJ1VzL+AHBQUHBwUFBwAAABAAAAAAQAA4AAIQAAASIOAgcnESEnPgEzMh4CFRQOAgcXPgM1NC4CIwIANWRcUiOWAYCQNYtQUItpPBIiMB5VKEAtGFCLu2oDgBUnNyOW/oCQNDw8aYtQK1FJQRpgI1ZibDlqu4tQAAEAAAAABAADgAAgAAATFB4CFzcuAzU0PgIzMhYXByERBy4DIyIOAgAYLUAoVR4wIhI8aYtQUIs1kAGAliNSXGQ1aruLUAGAOWxiViNgGkFJUStQi2k8PDSQAYCWIzcnFVCLuwACAAAAQAQBAwAAHgA9AAATMh4CFRQOAiMiLgI1JzQ+AjMVIgYHDgEHPgEhMh4CFRQOAiMiLgI1JzQ+AjMVIgYHDgEHPgHhLlI9IyM9Ui4uUj0jAUZ6o11AdS0JEAcIEgJJLlI9IyM9Ui4uUj0jAUZ6o11AdS0JEAcIEgIAIz1SLi5SPSMjPVIuIF2jekaAMC4IEwoCASM9Ui4uUj0jIz1SLiBdo3pGgDAuCBMKAgEAAAYAQP/ABAADwAADAAcACwARAB0AKQAAJSEVIREhFSERIRUhJxEjNSM1ExUzFSM1NzUjNTMVFREjNTM1IzUzNSM1AYACgP2AAoD9gAKA/YDAQEBAgMCAgMDAgICAgICAAgCAAgCAwP8AwED98jJAkjwyQJLu/sBAQEBAQAAGAAD/wAQAA8AAAwAHAAsAFwAjAC8AAAEhFSERIRUhESEVIQE0NjMyFhUUBiMiJhE0NjMyFhUUBiMiJhE0NjMyFhUUBiMiJgGAAoD9gAKA/YACgP2A/oBLNTVLSzU1S0s1NUtLNTVLSzU1S0s1NUsDgID/AID/AIADQDVLSzU1S0v+tTVLSzU1S0v+tTVLSzU1S0sAAwAAAAAEAAOgAAMADQAUAAA3IRUhJRUhNRMhFSE1ISUJASMRIxEABAD8AAQA/ACAAQABAAEA/WABIAEg4IBAQMBAQAEAgIDAASD+4P8AAQAAAAAAAgBT/8wDrQO0AC8AXAAAASImJy4BNDY/AT4BMzIWFx4BFAYPAQYiJyY0PwE2NCcuASMiBg8BBhQXFhQHDgEjAyImJy4BNDY/ATYyFxYUDwEGFBceATMyNj8BNjQnJjQ3NjIXHgEUBg8BDgEjAbgKEwgjJCQjwCNZMTFZIyMkJCNYDywPDw9YKSkUMxwcMxTAKSkPDwgTCrgxWSMjJCQjWA8sDw8PWCkpFDMcHDMUwCkpDw8PKxAjJCQjwCNZMQFECAckWl5aJMAiJSUiJFpeWiRXEBAPKw9YKXQpFBUVFMApdCkPKxAHCP6IJSIkWl5aJFcQEA8rD1gpdCkUFRUUwCl0KQ8rEA8PJFpeWiTAIiUAAAAABQAA/8AEAAPAABMAJwA7AEcAUwAABTI+AjU0LgIjIg4CFRQeAhMyHgIVFA4CIyIuAjU0PgITMj4CNw4DIyIuAiceAyc0NjMyFhUUBiMiJiU0NjMyFhUUBiMiJgIAaruLUFCLu2pqu4tQUIu7alaYcUFBcZhWVphxQUFxmFYrVVFMIwU3Vm8/P29WNwUjTFFV1SUbGyUlGxslAYAlGxslJRsbJUBQi7tqaruLUFCLu2pqu4tQA6BBcZhWVphxQUFxmFZWmHFB/gkMFSAUQ3RWMTFWdEMUIBUM9yg4OCgoODgoKDg4KCg4OAAAAAADAAD/wAQAA8AAEwAnADMAAAEiDgIVFB4CMzI+AjU0LgIDIi4CNTQ+AjMyHgIVFA4CEwcnBxcHFzcXNyc3AgBqu4tQUIu7amq7i1BQi7tqVphxQUFxmFZWmHFBQXGYSqCgYKCgYKCgYKCgA8BQi7tqaruLUFCLu2pqu4tQ/GBBcZhWVphxQUFxmFZWmHFBAqCgoGCgoGCgoGCgoAADAMAAAANAA4AAEgAbACQAAAE+ATU0LgIjIREhMj4CNTQmATMyFhUUBisBEyMRMzIWFRQGAsQcIChGXTX+wAGANV1GKET+hGUqPDwpZp+fnyw+PgHbIlQvNV1GKPyAKEZdNUZ0AUZLNTVL/oABAEs1NUsAAAIAwAAAA0ADgAAbAB8AAAEzERQOAiMiLgI1ETMRFBYXHgEzMjY3PgE1ASEVIQLAgDJXdUJCdVcygBsYHEkoKEkcGBv+AAKA/YADgP5gPGlOLS1OaTwBoP5gHjgXGBsbGBc4Hv6ggAAAAQCAAAADgAOAAAsAAAEVIwEzFSE1MwEjNQOAgP7AgP5AgAFAgAOAQP0AQEADAEAAAQAAAAAEAAOAAD0AAAEVIx4BFRQGBw4BIyImJy4BNTMUFjMyNjU0JiMhNSEuAScuATU0Njc+ATMyFhceARUjNCYjIgYVFBYzMhYXBADrFRY1MCxxPj5xLDA1gHJOTnJyTv4AASwCBAEwNTUwLHE+PnEsMDWAck5OcnJOO24rAcBAHUEiNWIkISQkISRiNTRMTDQ0TEABAwEkYjU1YiQhJCQhJGI1NExMNDRMIR8AAAAHAAD/wAQAA8AAAwAHAAsADwATABsAIwAAEzMVIzczFSMlMxUjNzMVIyUzFSMDEyETMxMhEwEDIQMjAyEDAICAwMDAAQCAgMDAwAEAgIAQEP0AECAQAoAQ/UAQAwAQIBD9gBABwEBAQEBAQEBAQAJA/kABwP6AAYD8AAGA/oABQP7AAAAKAAAAAAQAA4AAAwAHAAsADwATABcAGwAfACMAJwAAExEhEQE1IRUdASE1ARUhNSMVITURIRUhJSEVIRE1IRUBIRUhITUhFQAEAP2AAQD/AAEA/wBA/wABAP8AAoABAP8AAQD8gAEA/wACgAEAA4D8gAOA/cDAwEDAwAIAwMDAwP8AwMDAAQDAwP7AwMDAAAAFAAAAAAQAA4AAAwAHAAsADwATAAATIRUhFSEVIREhFSERIRUhESEVIQAEAPwAAoD9gAKA/YAEAPwABAD8AAOAgECA/wCAAUCA/wCAAAAAAAUAAAAABAADgAADAAcACwAPABMAABMhFSEXIRUhESEVIQMhFSERIRUhAAQA/ADAAoD9gAKA/YDABAD8AAQA/AADgIBAgP8AgAFAgP8AgAAABQAAAAAEAAOAAAMABwALAA8AEwAAEyEVIQUhFSERIRUhASEVIREhFSEABAD8AAGAAoD9gAKA/YD+gAQA/AAEAPwAA4CAQID/AIABQID/AIAAAAAAAQA/AD8C5gLmACwAACUUDwEGIyIvAQcGIyIvASY1ND8BJyY1ND8BNjMyHwE3NjMyHwEWFRQPARcWFQLmEE4QFxcQqKgQFxYQThAQqKgQEE4QFhcQqKgQFxcQThAQqKgQwxYQThAQqKgQEE4QFhcQqKgQFxcQThAQqKgQEE4QFxcQqKgQFwAAAAYAAAAAAyUDbgAUACgAPABNAFUAggAAAREUBwYrASInJjURNDc2OwEyFxYVMxEUBwYrASInJjURNDc2OwEyFxYXERQHBisBIicmNRE0NzY7ATIXFhMRIREUFxYXFjMhMjc2NzY1ASEnJicjBgcFFRQHBisBERQHBiMhIicmNREjIicmPQE0NzY7ATc2NzY7ATIXFh8BMzIXFhUBJQYFCCQIBQYGBQgkCAUGkgUFCCUIBQUFBQglCAUFkgUFCCUIBQUFBQglCAUFSf4ABAQFBAIB2wIEBAQE/oABABsEBrUGBAH3BgUINxobJv4lJhsbNwgFBQUFCLEoCBcWF7cXFhYJKLAIBQYCEv63CAUFBQUIAUkIBQYGBQj+twgFBQUFCAFJCAUGBgUI/rcIBQUFBQgBSQgFBgYF/lsCHf3jDQsKBQUFBQoLDQJmQwUCAgVVJAgGBf3jMCIjISIvAiAFBggkCAUFYBUPDw8PFWAFBQgAAgAHAEkDtwKvABoALgAACQEGIyIvASY1ND8BJyY1ND8BNjMyFwEWFRQHARUUBwYjISInJj0BNDc2MyEyFxYBTv72BgcIBR0GBuHhBgYdBQgHBgEKBgYCaQUFCP3bCAUFBQUIAiUIBQUBhf72BgYcBggHBuDhBgcHBh0FBf71BQgHBv77JQgFBQUFCCUIBQUFBQAAAAEAIwAAA90DbgCzAAAlIicmIyIHBiMiJyY1NDc2NzY3Njc2PQE0JyYjISIHBh0BFBcWFxYzFhcWFRQHBiMiJyYjIgcGIyInJjU0NzY3Njc2NzY9ARE0NTQ1NCc0JyYnJicmJyYnJiMiJyY1NDc2MzIXFjMyNzYzMhcWFRQHBiMGBwYHBh0BFBcWMyEyNzY9ATQnJicmJyY1NDc2MzIXFjMyNzYzMhcWFRQHBgciBwYHBhURFBcWFxYXMhcWFRQHBiMDwRkzMhoZMjMZDQgHCQoNDBEQChIBBxX+fhYHARUJEhMODgwLBwcOGzU1GhgxMRgNBwcJCQsMEA8JEgECAQIDBAQFCBIRDQ0KCwcHDho1NRoYMDEYDgcHCQoMDRAQCBQBBw8BkA4HARQKFxcPDgcHDhkzMhkZMTEZDgcHCgoNDRARCBQUCRERDg0KCwcHDgACAgICDAsPEQkJAQEDAwUMROAMBQMDBQzUUQ0GAQIBCAgSDwwNAgICAgwMDhEICQECAwMFDUUhAdACDQ0ICA4OCgoLCwcHAwYBAQgIEg8MDQICAgINDA8RCAgBAgEGDFC2DAcBAQcMtlAMBgEBBgcWDwwNAgICAg0MDxEICAEBAgYNT/3mRAwGAgIBCQgRDwwNAAACAAD/twP/A7cAEwA5AAABMhcWFRQHAgcGIyInJjU0NwE2MwEWFxYfARYHBiMiJyYnJicmNRYXFhcWFxYzMjc2NzY3Njc2NzY3A5soHh4avkw3RUg0NDUBbSEp/fgXJicvAQJMTHtHNjYhIRARBBMUEBASEQkXCA8SExUVHR0eHikDtxsaKCQz/plGNDU0SUkwAUsf/bErHx8NKHpNTBobLi86OkQDDw4LCwoKFiUbGhERCgsEBAIAAQAAAAAAANox8glfDzz1AAsEAAAAAADVYbp/AAAAANVhun8AAP+3BAEDwAAAAAgAAgAAAAAAAAABAAADwP/AAAAEAAAA//8EAQABAAAAAAAAAAAAAAAAAAAAHwQAAAAAAAAAAAAAAAIAAAAEAAAABAAAAAQAAAAEAADABAAAAAQAAAAEAAAABAAAQAQAAAAEAAAABAAAUwQAAAAEAAAABAAAwAQAAMAEAACABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAAyUAPwMlAAADvgAHBAAAIwP/AAAAAAAAAAoAFAAeAEwAlADaAQoBPgFwAcgCBgJQAnoDBAN6A8gEAgQ2BE4EpgToBTAFWAWABaoF7gamBvAH4gg+AAEAAAAfALQACgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAOAK4AAQAAAAAAAQAHAAAAAQAAAAAAAgAHAGAAAQAAAAAAAwAHADYAAQAAAAAABAAHAHUAAQAAAAAABQALABUAAQAAAAAABgAHAEsAAQAAAAAACgAaAIoAAwABBAkAAQAOAAcAAwABBAkAAgAOAGcAAwABBAkAAwAOAD0AAwABBAkABAAOAHwAAwABBAkABQAWACAAAwABBAkABgAOAFIAAwABBAkACgA0AKRpY29tb29uAGkAYwBvAG0AbwBvAG5WZXJzaW9uIDEuMABWAGUAcgBzAGkAbwBuACAAMQAuADBpY29tb29uAGkAYwBvAG0AbwBvAG5pY29tb29uAGkAYwBvAG0AbwBvAG5SZWd1bGFyAFIAZQBnAHUAbABhAHJpY29tb29uAGkAYwBvAG0AbwBvAG5Gb250IGdlbmVyYXRlZCBieSBJY29Nb29uLgBGAG8AbgB0ACAAZwBlAG4AZQByAGEAdABlAGQAIABiAHkAIABJAGMAbwBNAG8AbwBuAC4AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA) format(\\'truetype\\');  font-weight: normal;  font-style: normal;}[class^=\"w-e-icon-\"],[class*=\" w-e-icon-\"] {  /* use !important to prevent issues with browser extensions that change fonts */  font-family: \\'w-e-icon\\' !important;  speak: none;  font-style: normal;  font-weight: normal;  font-variant: normal;  text-transform: none;  line-height: 1;  /* Better Font Rendering =========== */  -webkit-font-smoothing: antialiased;  -moz-osx-font-smoothing: grayscale;}.w-e-icon-close:before {  content: \"\\\\f00d\";}.w-e-icon-upload2:before {  content: \"\\\\e9c6\";}.w-e-icon-trash-o:before {  content: \"\\\\f014\";}.w-e-icon-header:before {  content: \"\\\\f1dc\";}.w-e-icon-pencil2:before {  content: \"\\\\e906\";}.w-e-icon-paint-brush:before {  content: \"\\\\f1fc\";}.w-e-icon-image:before {  content: \"\\\\e90d\";}.w-e-icon-play:before {  content: \"\\\\e912\";}.w-e-icon-location:before {  content: \"\\\\e947\";}.w-e-icon-undo:before {  content: \"\\\\e965\";}.w-e-icon-redo:before {  content: \"\\\\e966\";}.w-e-icon-quotes-left:before {  content: \"\\\\e977\";}.w-e-icon-list-numbered:before {  content: \"\\\\e9b9\";}.w-e-icon-list2:before {  content: \"\\\\e9bb\";}.w-e-icon-link:before {  content: \"\\\\e9cb\";}.w-e-icon-happy:before {  content: \"\\\\e9df\";}.w-e-icon-bold:before {  content: \"\\\\ea62\";}.w-e-icon-underline:before {  content: \"\\\\ea63\";}.w-e-icon-italic:before {  content: \"\\\\ea64\";}.w-e-icon-strikethrough:before {  content: \"\\\\ea65\";}.w-e-icon-table2:before {  content: \"\\\\ea71\";}.w-e-icon-paragraph-left:before {  content: \"\\\\ea77\";}.w-e-icon-paragraph-center:before {  content: \"\\\\ea78\";}.w-e-icon-paragraph-right:before {  content: \"\\\\ea79\";}.w-e-icon-terminal:before {  content: \"\\\\f120\";}.w-e-icon-page-break:before {  content: \"\\\\ea68\";}.w-e-icon-cancel-circle:before {  content: \"\\\\ea0d\";}.w-e-toolbar {  display: -webkit-box;  display: -ms-flexbox;  display: flex;  padding: 0 5px;  /* flex-wrap: wrap; */  /* 单个菜单 */}.w-e-toolbar .w-e-menu {  position: relative;  text-align: center;  padding: 5px 10px;  cursor: pointer;}.w-e-toolbar .w-e-menu i {  color: #999;}.w-e-toolbar .w-e-menu:hover i {  color: #333;}.w-e-toolbar .w-e-active i {  color: #1e88e5;}.w-e-toolbar .w-e-active:hover i {  color: #1e88e5;}.w-e-text-container .w-e-panel-container {  position: absolute;  top: 0;  left: 50%;  border: 1px solid #ccc;  border-top: 0;  box-shadow: 1px 1px 2px #ccc;  color: #333;  background-color: #fff;  /* 为 emotion panel 定制的样式 */  /* 上传图片的 panel 定制样式 */}.w-e-text-container .w-e-panel-container .w-e-panel-close {  position: absolute;  right: 0;  top: 0;  padding: 5px;  margin: 2px 5px 0 0;  cursor: pointer;  color: #999;}.w-e-text-container .w-e-panel-container .w-e-panel-close:hover {  color: #333;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-title {  list-style: none;  display: -webkit-box;  display: -ms-flexbox;  display: flex;  font-size: 14px;  margin: 2px 10px 0 10px;  border-bottom: 1px solid #f1f1f1;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-item {  padding: 3px 5px;  color: #999;  cursor: pointer;  margin: 0 3px;  position: relative;  top: 1px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-title .w-e-active {  color: #333;  border-bottom: 1px solid #333;  cursor: default;  font-weight: 700;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content {  padding: 10px 15px 10px 15px;  font-size: 16px;  /* 输入框的样式 */  /* 按钮的样式 */}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input:focus,.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus,.w-e-text-container .w-e-panel-container .w-e-panel-tab-content button:focus {  outline: none;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea {  width: 100%;  border: 1px solid #ccc;  padding: 5px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content textarea:focus {  border-color: #1e88e5;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text] {  border: none;  border-bottom: 1px solid #ccc;  font-size: 14px;  height: 20px;  color: #333;  text-align: left;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].small {  width: 30px;  text-align: center;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text].block {  display: block;  width: 100%;  margin: 10px 0;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content input[type=text]:focus {  border-bottom: 2px solid #1e88e5;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button {  font-size: 14px;  color: #1e88e5;  border: none;  padding: 5px 10px;  background-color: #fff;  cursor: pointer;  border-radius: 3px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.left {  float: left;  margin-right: 10px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.right {  float: right;  margin-left: 10px;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.gray {  color: #999;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button.red {  color: #c24f4a;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container button:hover {  background-color: #f1f1f1;}.w-e-text-container .w-e-panel-container .w-e-panel-tab-content .w-e-button-container:after {  content: \"\";  display: table;  clear: both;}.w-e-text-container .w-e-panel-container .w-e-emoticon-container .w-e-item {  cursor: pointer;  font-size: 18px;  padding: 0 3px;  display: inline-block;  *display: inline;  *zoom: 1;}.w-e-text-container .w-e-panel-container .w-e-up-img-container {  text-align: center;}.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn {  display: inline-block;  *display: inline;  *zoom: 1;  color: #999;  cursor: pointer;  font-size: 60px;  line-height: 1;}.w-e-text-container .w-e-panel-container .w-e-up-img-container .w-e-up-btn:hover {  color: #333;}.w-e-text-container {  position: relative;}.w-e-text-container .w-e-progress {  position: absolute;  background-color: #1e88e5;  bottom: 0;  left: 0;  height: 1px;}.w-e-text {  padding: 0 10px;  overflow-y: scroll;}.w-e-text p,.w-e-text h1,.w-e-text h2,.w-e-text h3,.w-e-text h4,.w-e-text h5,.w-e-text table,.w-e-text pre {  margin: 10px 0;  line-height: 1.5;}.w-e-text ul,.w-e-text ol {  margin: 10px 0 10px 20px;}.w-e-text blockquote {  display: block;  border-left: 8px solid #d0e5f2;  padding: 5px 10px;  margin: 10px 0;  line-height: 1.4;  font-size: 100%;  background-color: #f1f1f1;}.w-e-text code {  display: inline-block;  *display: inline;  *zoom: 1;  background-color: #f1f1f1;  border-radius: 3px;  padding: 3px 5px;  margin: 0 3px;}.w-e-text pre code {  display: block;}.w-e-text table {  border-top: 1px solid #ccc;  border-left: 1px solid #ccc;}.w-e-text table td,.w-e-text table th {  border-bottom: 1px solid #ccc;  border-right: 1px solid #ccc;  padding: 3px 5px;}.w-e-text table th {  border-bottom: 2px solid #ccc;  text-align: center;}.w-e-text:focus {  outline: none;}.w-e-text img {  cursor: pointer;}.w-e-text img:hover {  box-shadow: 0 0 5px #333;}';\n\n// 将 css 代码添加到 <style> 中\nvar style = document.createElement('style');\nstyle.type = 'text/css';\nstyle.innerHTML = inlinecss;\ndocument.getElementsByTagName('HEAD').item(0).appendChild(style);\n\n// 返回\nvar index = window.wangEditor || Editor;\n\nreturn index;\n\n})));\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui/css/H-ui.css",
    "content": "@charset \"utf-8\";\n/* -----------H-ui前端框架-------------\n* H-ui.css v3.1.5\n* http://www.h-ui.net/\n* Created & Modified by guojunhui\n* Date modified 2017.07.19\n*\n* Copyright 2013-2017 北京颖杰联创科技有限公司 All rights reserved.\n* Licensed under MIT license.\n* http://opensource.org/licenses/MIT\n*\n*/\n/*------------------------------------\n结构目录：\n  1. css reset重定义浏览器默认样式\n  2. 框架\n    2.1 响应式栅格系统\n    2.2 响应式隐藏显示\n  3. 基础CSS\n    3.1 排版\n      3.1.1  标题\n      3.1.2  强调\n      3.1.3  对齐\n      3.1.4  定位\n      3.1.5  浮动\n\t  3.1.6  文字单行溢出省略号\n\t  3.1.7  线条\n      3.1.8  外边距\n      3.1.9  内填充\n      3.1.10 边框，css3圆角\n      3.1.11 css3阴影\n      3.1.12 行内分割竖线\n      3.1.13 文字尺寸\n      3.1.14 文字行距\n      3.1.15 文字颜色\n      3.1.16 文字颜色强调\n      3.1.17 缩略语\n      3.1.18 地址\n      3.1.19 引用\n      3.1.20 上标 下标\n      3.1.21 内容样式\n      3.1.22 列表\n      3.1.23 描述\n\t  3.1.24 隐藏 显示\n\t  3.1.25 尺寸\n    3.2 代码\n    3.3 表格\n    3.4 表单\n      3.4.1 input,textarea 文本域 文本区域\n      3.4.2 radio,checkbox 单选 多选\n\t  \t3.4.2.1 jQuery.icheck.css\n\t\t3.4.2.2 Bootsrtap.Switch.css\n      3.4.3 select 下拉框\n      3.4.4 input-file 文件上传\n\t  3.4.5 spinner 控件\n\t  3.4.6 邮箱提示\n      3.4.7 表单布局\n\t  3.4.8 表单验证\t  \n    3.5 按钮\n    3.6 图片\n    3.7 图标\n    3.8 动画\n  4. 组件\n    4.1 按钮组\n    4.2 导航\n      4.2.1 导航条\n      4.2.2 面包屑导航\n      4.2.3 翻页导航\n\t  4.2.4 顶部导航\n\t  4.2.5 向导\n\t  4.2.6 竖向导向tab导航\n\t  4.2.7 横向tab\n    4.3 菜单\n      4.3.1 下拉菜单\n      4.3.2 多级菜单\n      4.3.3 树状菜单（暂无）\n    4.4 幻灯片\n      4.4.1 焦点图效果(自动播放，圆点控制)\n      4.4.2 带缩略图效果\n    4.5 选项卡\n    4.6 便签与标号\n    4.7 缩略图\n    4.8 警告\n    4.9 进度条 loading\n    4.10 对话框 弹出层\n    4.11 客服\n    4.12 右侧悬浮工具\n\t\t4.12.1 返回顶部\n\t\t4.12.2 意见反馈\n    4.13 分享\n    4.14 面板\n    4.15 案例\n    4.16 滚动\n    4.17 搜索\n    4.18 广告\n    4.19 标签\n      4.19.1 标签输入效果\n      4.19.2 标签混排效果\n      4.19.3 tag云标签\n    4.20 折叠\n    4.21 遮罩条\n    4.22 评论列表\n\t4.23 页脚\n\t4.24 星星评价\n\t4.25 tooltip效果\n\t4.26 popover效果\n\t4.27 datetimepicker日期插件\n\t4.28 sortable拖动\n\t4.29 ColorPicker 颜色控件\n  5. 页面\n    5.1 404页面\n    5.2 博客列表页（暂无）\n    5.3 博客详情页（暂无）\n    5.4 关于我们页（暂无）\n    5.5 帮助列表页（暂无）\n    5.6 帮助详情页（暂无）\n\n----------------------------------\nCSS写作注意事项：\n  1. 页面编码规范\n    1.1. 统一使用 UTF-8 编码,用@charset \"utf-8\"指定页面编码。\n    1.2. 全局字体设置：\n         windows 7系统：微软雅黑 Arial；\n         windows XP及以下：新宋体，宋体，Arial\n         MAC默认字体：Helvetica Neue和Helvetica Hiragino Sans GB。\n    1.3. 中文字体使用编码转换，请参阅下节“中文字体css编码转换”\n    1.4. 推荐使用216web安全色\n  2. 属性写在一行内，属性之间、属性名和值之间以及属性与“{}”之间应减少空格，去掉最后一个“;”，例如：.class{width:200px;height:100px}\n  3. 属性的书写顺序：\n    3.1. 按照元素模型由外及内，由整体到细节书写，大致分为五组：\n      位置：position,left,right,float\n      盒模型属性：display,margin,padding,width,height\n      边框与背景：border,background\n      段落与文本：line-height,text-indent,font,color,text-decoration,...\n      其他属性：overflow,cursor,visibility,...\n    3.2. 针对特殊浏览器的属性，应写在标准属性之前，例如：-webkit-box-shadow:;-moz-box-shadow:;box-shaow:;\n  4. 带有前缀的属性，单独一行，通过缩进，让每个属性的值垂直对齐，方便编辑维护。\n  5. 谨慎添加新的选择符规则，尤其不可滥用 id，尽可能继承和复用已有样式\n  6. 选择符、属性、值均用小写（格式的颜色值除外），缩写的选择符名称须说明缩写前的全称，例如 .cl -> Clearfix\n  7. 避免使用各种 CSS Hack，如需对 IE 进行特殊定义，请参阅下节“关于 CSS Hack 的说明”\n  8. 勿使用冗余低效的 CSS 写法，例如：ul li a span{... }\n  9. 慎用 !important\n  10. 建议使用具有语义化的classname或id，请参阅下节“css 命名规范及对应的缩写”\n  11.避免使用兼容性不好的使用滤镜\n  12.开发过程中的未定事项，须用 [!] 标出，以便于后续讨论整理。\n  13.注释格式，统一使用双斜杠加*。\n  14.上下模块之间的间距统一使用下一个模块的margin-top来实现，好处是：如果没有下一个模块也不会多出一段空隙。\n  15.hover，selected，disabled，current等具有特定意义的请勿直接占用。\n  16.:link :visited :hover :active书写顺序 L-V-H-A，速记：LoVe（喜欢）HAte（讨厌）。\n  17.不要使用 @import\n----------------------------------\n中文字体css编码转换\n  微软雅黑   \\5FAE\\8F6F\\96C5\\9ED1  或 Microsoft YaHei\n  黑体       \\9ED1\\4F53\n  新宋体     \\65b0\\5b8b\\4f53\n  宋体       \\5b8b\\4f53\n----------------------------------\n关于 CSS Hack 的说明：\n  1. _          IE6\n  2. *          IE6/7\n  3. !important IE7/Firefox\n  4. *+         IE7\n  5. \\9         IE6/7/8\n  6. \\0         IE8\n  7. 条件hack\n      <!--[if lt IE 7]><html class=\"no-js lt-ie9 lt-ie8 lt-ie7\"><![endif]--> IE7以下版本\n      <!--[if IE 7]><html class=\"no-js lt-ie9 lt-ie8\"><![endif]--> IE7\n      <!--[if IE 8]> <html class=\"no-js lt-ie9\"><![endif]--> IE8\n      <!--[if gt IE 8]><!--><html class=\"no-js\"><!--<![endif]--> IE8以上\n----------------------------------\ncss 命名规范\n  1. 内容优先,表现为辅\n  2. css命名中英文对照\n  current 当前    hover 悬停    selected 挑选   disabled 禁用   focus 得到焦点    blur 失去焦点   checked 勾选    success 成功    error 出错\n\n  header(hd) 头部   content(cnt) 内容   title(tit) 标题   item 项目（条）    cell 单元   image/pic(img) 图片   text(txt) 文字    top 顶部    scrubber 时序菜单\n\n  nav 导航    mainNav 主导航   subNav 子导航    topNav 顶部导航   breadcrumb 面包屑导航\n\n  flink 友情链接    footer 尾    copyright 版权\n\n  menu 菜单   submenu 子菜单   dropdown 下拉菜单\n\n  searchBar 搜索条   search 搜索条    searchTxt 搜索框   searchBtn 搜索按钮    search_key 搜索词\n\n  member 会员   ucenter 用户中心    loginBar 登陆条    login 登录    loginBtn 登录按钮   regsiter 注册按钮   btn-regsiter注册按钮    name 用户名    password 密码   nickname 昵称   mobilephone/mobile 手机    telephone/tel 电话   defaultavatar 默认头像\n\n  hot 热点    news 新闻   banner/AD 广告    download 下载\n\n  content 内容    title 标题    summary 摘要    time 时间\n\n  share 分享    digg 顶    like 喜欢\n\n  list/-list 列表   pList 图片列表    tList 文字列表    tpList 图文列表\n\n  table 表格    row 行   column 列    gutter 间隔   viewport 视口\n\n  tab 标签    tags 标签   scroll 滚动\n\n  sidebar 侧边栏   column 栏目   section 区块    msg 提示信息    status 状态   vote 投票   tips 小技巧    guild 指南    note 注释\n\n  icon- 图标    btn- 按钮\n\n  goods 商品    goods-list 商品列表    goods-detail 商品详情    goods-info 商品信息\n\n  tuan 团购   tuan-list 团购列表   tuan-detail  团购详情    tuan-info 团购信息\n\n  transition 动画   shadow 阴影   fade 淡入淡出   flip 翻页效    slide 滑动    slideup 上滑动   slidedown 下滑动   turn 翻页   horizontal 水平   vertical 垂直   collapsible 折叠    corners 拐角    flow 流    reverse 反向    pop 弹窗\n\n  count 总数/计数   plus 加号/正   minus 减号/负    controlgroup 控制组\n----------------------------------\nhtml命名规范：\n  default/index.html    首页\n  404.html              404错误页\n  print.html            打印页\n  header.html           页头\n  footer.html           页脚\n  sitemap.html          网站地图\n  passport.html         通行证\n  rank.html             排行榜\n  roll.html             滚动新闻\n\n  solution.html         解决方案\n  joinus.html           加入我们\n  partner.html          合作伙伴\n  service.html          服务\n  aboutus.html          关于我们\n  contact.html          联系我们\n  company.html          公司介绍\n  organization.html     组织结构\n  culture.html          企业文化\n  strategy.html         发展策略\n  honor.html            公司荣誉\n  aptitudes.html        企业资质\n  events.html           大事记\n  business.html         商务合作\n  contract.html         服务条款\n  privacy.html          隐私声明\n  CSR.html              企业社会责任\n\n  news-开头.html         新闻相关\n  article-开头.html      资讯相关\n  picture-开头.html      图片相关\n  photo-开头.html        相册相关\n  product-开头.html      产品相关\n  goods-开头.html        商品相关\n  system-开头.html       系统相关\n  tag-开头.html          tag相关\n  brand-开头.html        品牌相关\n  help-开头.html         帮助相关\n  member-开头.html       会员相关\n  search-开头.html       搜索相关\n---------------------------------- */\n/*1 重定义浏览器默认样式\n\tName:\t\t\tstyle_reset\n\tExplain:\t\t重定义浏览器默认样式\n*/\n*{word-wrap:break-word}\nhtml,body,h1,h2,h3,h4,h5,h6,hr,p,iframe,dl,dt,dd,ul,ol,li,pre,form,button,input,textarea,th,td,fieldset{margin:0;padding:0}\nul,ol,dl{list-style-type:none}\nhtml,body{*position:static}\nhtml{font-family: sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0)}\naddress,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:400}\ninput,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit}\ninput,button{overflow: visible;vertical-align:middle;outline:none}\ninput[type=\"submit\"],input[type=\"reset\"],input[type=\"button\"],input[type=\"text\"],input[type=\"password\"]{-webkit-appearance:none;outline:none}\nbody,th,td,button,input,select,textarea{font-family:\"Microsoft Yahei\",\"Hiragino Sans GB\",\"Helvetica Neue\",Helvetica,tahoma,arial,\"WenQuanYi Micro Hei\",Verdana,sans-serif,\"\\5B8B\\4F53\";font-size:12px;color: #333;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing:grayscale}\n@media ( max-width : 767px) {\n\thtml{ overflow-y:auto}\n\tbody,th,td,button,input,select,textarea{ font-size:14px}\n}\nbody{line-height:1.6; position:relative}\nh1,h2,h3,h4,h5,h6{font-size:100%}\na,area{outline:none;blr:expression(this.onFocus=this.blur())}\na{text-decoration:none;cursor: pointer}\na:hover{text-decoration:underline;outline:none}\na.ie6:hover{zoom:1}\na:focus{outline:none}\na:hover,a:active{outline:none}:focus{outline:none}\nsub,sup{vertical-align:baseline}\nbutton,input[type=\"button\"], input[type=\"submit\"] {line-height:normal !important}\n/*img*/\nimg{border:0;vertical-align:middle}\na img,img{-ms-interpolation-mode:bicubic}\n\n/*IE下a:hover 背景闪烁*/\n*html{overflow:-moz-scrollbars-vertical;zoom:expression(function(ele){ele.style.zoom = \"1\";document.execCommand(\"BackgroundImageCache\",false,true)}(this))}\n\n/*HTML5 reset*/\nheader,footer,section,aside,details,menu,article,section,nav,address,hgroup,figure,figcaption,legend{display:block;margin:0;padding:0}time{display:inline}\naudio,canvas,video{display:inline-block;*display:inline;*zoom:1}\naudio:not([controls]){display:none}\nlegend{width:100%;margin-bottom:20px;font-size:21px;line-height:40px;border:0;border-bottom:1px solid #e5e5e5}\nlegend small{font-size:15px;color:#999}\nsvg:not(:root) {overflow: hidden}\nfieldset {border-width:0;padding: 0.35em 0.625em 0.75em;margin: 0 2px;border: 1px solid #c0c0c0}\ninput[type=\"number\"]::-webkit-inner-spin-button,input[type=\"number\"]::-webkit-outer-spin-button {height: auto}\ninput[type=\"search\"] {-webkit-appearance: textfield; /* 1 */}\ninput[type=\"search\"]::-webkit-search-cancel-button,input[type=\"search\"]::-webkit-search-decoration {-webkit-appearance: none}\n/*清除浮动\n\tName:\t\t\tstyle_clearfix\n\tExample:\t\tclass=\"clearfix|cl\"\n\tExplain:\t\tclearfix（简写cl）避免因子元素浮动而导致的父元素高度缺失能问题\n*/\n.cl:after,.clearfix:after{content:\"\\20\";display:block;height:0;clear:both;visibility:hidden}.cl,.clearfix{zoom:1}\n\n/*2.1 栅格系统\n\tName:\t\t\tstyle_container\n\tExample:\n\t<div class=\"responsive\">\n\t<div class=\"row cl\" role=\"grid\">\n\t  <div class=\"col-1\">……</div>\n\t  ……\n\t</div>\n\t</div>\n\tExplain:\t\t栅格系统\n*/\n/*2.1 响应式栅格系统*/\n.container {padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto}\n.container-fluid {padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto}\n\n@media ( min-width : 992px) {\n\t.container{width: 960px}\n}\n@media ( min-width : 1200px) {\n\t.container {width: 1170px}\n}\n@media ( min-width : 1300px) {\n\t.container {width: 1270px}\n}\n\n@media print{\n\t.container{width:auto}\n}\n.row.cl{}\n.row{box-sizing:border-box; margin-left:-15px; margin-right:-15px}\n.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {min-height: 1px;position: relative; padding-left:15px; padding-right:15px; box-sizing:border-box;-webkit-transition:all 0.3s ease-in;\n\t\t-moz-transition:all 0.3s ease-in;\n\t\t-o-transition:all 0.3s ease-in;\n\t\t\ttransition:all 0.3s ease-in}\n\n.col-1{width:8.33333%}\n.col-2{width:16.66667%}\n.col-3{width:25%}\n.col-4{width:33.33333%}\n.col-5{width:41.66667%}\n.col-6{width:50%}\n.col-7{width:58.33333%}\n.col-8{width:66.66667%}\n.col-9{width:75%}\n.col-10{width:83.33333%}\n.col-11{width:91.66667%}\n.col-12{width:100%}\n\n.col-offset-0{margin-left:0}\n.col-offset-1{margin-left:8.33333%}\n.col-offset-2{margin-left:16.66667%}\n.col-offset-3{margin-left:25%}\n.col-offset-4{margin-left:33.33333%}\n.col-offset-5{margin-left:41.66667%}\n.col-offset-6{margin-left:50%}\n.col-offset-7{margin-left:58.33333%}\n.col-offset-8{margin-left:66.66667%}\n.col-offset-9{margin-left:75%}\n.col-offset-10{margin-left:83.33333%}\n.col-offset-11{margin-left:91.66667%}\n\n.col-push-0{position:relative;left:0;right:auto}\n.col-pull-0{right:0;left:auto}\n.col-push-1{left:8.33333%;right:auto}\n.col-pull-1{right:8.33333%;left:auto}\n.col-push-2{left:16.66667%;right:auto}\n.col-pull-2{right:16.66667%;left:auto}\n.col-push-3{left:25%;right:auto}\n.col-pull-3{right:25%;left:auto}\n.col-push-4{left:33.33333%;right:auto}\n.col-pull-4{right:33.33333%;left:auto}\n.col-push-5{left:41.66667%;right:auto}\n.col-pull-5{right:41.66667%;left:auto}\n.col-push-6{left:50%;right:auto}\n.col-pull-6{right:50%;left:auto}\n.col-push-7{left:58.33333%;right:auto}\n.col-pull-7{right:58.33333%;left:auto}\n.col-push-8{left:66.66667%;right:auto}\n.col-pull-8{right:66.66667%;left:auto}\n.col-push-9{left:75%;right:auto}\n.col-pull-9{right:75%;left:auto}\n.col-push-10{left:83.33333%;right:auto}\n.col-pull-10{right:83.33333%;left:auto}\n.col-push-11{left:91.66667%;right:auto}\n.col-pull-11{right:91.66667%;left:auto}\n/*局部模块平分*/\n.col-1-1{ width:100%}\n.col-2-1{ width:50%}\n.col-3-1{ width:33.333333%}\n.col-3-2{ width:66.666667%}\n.col-4-1{ width:25%}\n.col-4-3{ width:75%}\n.col-5-1{ width:20%}\n.col-5-2{ width:40%}\n.col-5-3{ width:60%}\n.col-5-4{ width:80%}\n.col-6-1{ width:16.666667%}\n.col-6-5{ width:83.333333%}\n\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {float: left}\n.col-xs-12 {width: 100%}\n.col-xs-11 {width: 91.66666667%}\n.col-xs-10 {width: 83.33333333%}\n.col-xs-9 {width: 75%}\n.col-xs-8 {width: 66.66666667%}\n.col-xs-7 {width: 58.33333333%}\n.col-xs-6 {width: 50%}\n.col-xs-5 {width: 41.66666667%}\n.col-xs-4 {width: 33.33333333%}\n.col-xs-3 {width: 25%}\n.col-xs-2 {width: 16.66666667%}\n.col-xs-1 {width: 8.33333333%}\n.col-xs-pull-12 {right: 100%}\n.col-xs-pull-11 {right: 91.66666667%}\n.col-xs-pull-10 {right: 83.33333333%}\n.col-xs-pull-9 {right: 75%}\n.col-xs-pull-8 {right: 66.66666667%}\n.col-xs-pull-7 {right: 58.33333333%}\n.col-xs-pull-6 {right: 50%}\n.col-xs-pull-5 {right: 41.66666667%}\n.col-xs-pull-4 {right: 33.33333333%}\n.col-xs-pull-3 {right: 25%}\n.col-xs-pull-2 {right: 16.66666667%}\n.col-xs-pull-1 {right: 8.33333333%}\n.col-xs-pull-0 {right: auto}\n.col-xs-push-12 {left: 100%}\n.col-xs-push-11 {left: 91.66666667%}\n.col-xs-push-10 {left: 83.33333333%}\n.col-xs-push-9 {left: 75%}\n.col-xs-push-8 {left: 66.66666667%}\n.col-xs-push-7 {left: 58.33333333%}\n.col-xs-push-6 {left: 50%}\n.col-xs-push-5 {left: 41.66666667%}\n.col-xs-push-4 {left: 33.33333333%}\n.col-xs-push-3 {left: 25%}\n.col-xs-push-2 {left: 16.66666667%}\n.col-xs-push-1 {left: 8.33333333%}\n.col-xs-push-0 {left: auto}\n.col-xs-offset-12 {margin-left: 100%}\n.col-xs-offset-11 {margin-left: 91.66666667%}\n.col-xs-offset-10 {margin-left: 83.33333333%}\n.col-xs-offset-9 {margin-left: 75%}\n.col-xs-offset-8 {margin-left: 66.66666667%}\n.col-xs-offset-7 {margin-left: 58.33333333%}\n.col-xs-offset-6 {margin-left: 50%}\n.col-xs-offset-5 {margin-left: 41.66666667%}\n.col-xs-offset-4 {margin-left: 33.33333333%}\n.col-xs-offset-3 {margin-left: 25%}\n.col-xs-offset-2 {margin-left: 16.66666667%}\n.col-xs-offset-1 {margin-left: 8.33333333%}\n.col-xs-offset-0 {margin-left: 0}\n@media (max-width:767px){\n\t.responsive [class^=\"col-\"],.responsive [class*=\" col-\"]{float:none!important;width:auto!important}\n\t.responsive [class^=\"col-offset-\"],.responsive [class*=\" col-offset-\"]{ margin-left:0!important}\n}\n@media(min-width:768px){\n\t.col-sm-1,.col-sm-10,.col-sm-11,.col-sm-12,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9{float:left}\n\t.col-sm-12{width:100%}\n\t.col-sm-11{width:91.66666666666666%}\n\t.col-sm-10{width:83.33333333333334%}\n\t.col-sm-9{width:75%}\n\t.col-sm-8{width:66.66666666666666%}\n\t.col-sm-7{width:58.333333333333336%}\n\t.col-sm-6{width:50%}\n\t.col-sm-5{width:41.66666666666667%}\n\t.col-sm-4{width:33.33333333333333%}\n\t.col-sm-3{width:25%}\n\t.col-sm-2{width:16.666666666666664%}\n\t.col-sm-1{width:8.333333333333332%}\n\t.col-sm-pull-12{right:100%}\n\t.col-sm-pull-11{right:91.66666666666666%}\n\t.col-sm-pull-10{right:83.33333333333334%}\n\t.col-sm-pull-9{right:75%}\n\t.col-sm-pull-8{right:66.66666666666666%}\n\t.col-sm-pull-7{right:58.333333333333336%}\n\t.col-sm-pull-6{right:50%}\n\t.col-sm-pull-5{right:41.66666666666667%}\n\t.col-sm-pull-4{right:33.33333333333333%}\n\t.col-sm-pull-3{right:25%}\n\t.col-sm-pull-2{right:16.666666666666664%}\n\t.col-sm-pull-1{right:8.333333333333332%}\n\t.col-sm-pull-0{right:0}\n\t.col-sm-push-12{left:100%}\n\t.col-sm-push-11{left:91.66666666666666%}\n\t.col-sm-push-10{left:83.33333333333334%}\n\t.col-sm-push-9{left:75%}\n\t.col-sm-push-8{left:66.66666666666666%}\n\t.col-sm-push-7{left:58.333333333333336%}\n\t.col-sm-push-6{left:50%}\n\t.col-sm-push-5{left:41.66666666666667%}\n\t.col-sm-push-4{left:33.33333333333333%}\n\t.col-sm-push-3{left:25%}\n\t.col-sm-push-2{left:16.666666666666664%}\n\t.col-sm-push-1{left:8.333333333333332%}\n\t.col-sm-push-0{left:0}\n\t.col-sm-offset-12{margin-left:100%}\n\t.col-sm-offset-11{margin-left:91.66666666666666%}\n\t.col-sm-offset-10{margin-left:83.33333333333334%}\n\t.col-sm-offset-9{margin-left:75%}\n\t.col-sm-offset-8{margin-left:66.66666666666666%}\n\t.col-sm-offset-7{margin-left:58.333333333333336%}\n\t.col-sm-offset-6{margin-left:50%}\n\t.col-sm-offset-5{margin-left:41.66666666666667%}\n\t.col-sm-offset-4{margin-left:33.33333333333333%}\n\t.col-sm-offset-3{margin-left:25%}\n\t.col-sm-offset-2{margin-left:16.666666666666664%}\n\t.col-sm-offset-1{margin-left:8.333333333333332%}\n\t.col-sm-offset-0{margin-left:0}\n}\n@media(min-width:992px){\n\t.col-md-1,.col-md-10,.col-md-11,.col-md-12,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9{float:left}\n\t.col-md-12{width:100%}\n\t.col-md-11{width:91.66666666666666%}\n\t.col-md-10{width:83.33333333333334%}\n\t.col-md-9{width:75%}\n\t.col-md-8{width:66.66666666666666%}\n\t.col-md-7{width:58.333333333333336%}\n\t.col-md-6{width:50%}\n\t.col-md-5{width:41.66666666666667%}\n\t.col-md-4{width:33.33333333333333%}\n\t.col-md-3{width:25%}\n\t.col-md-2{width:16.666666666666664%}\n\t.col-md-1{width:8.333333333333332%}\n\t.col-md-pull-12{right:100%}\n\t.col-md-pull-11{right:91.66666666666666%}\n\t.col-md-pull-10{right:83.33333333333334%}\n\t.col-md-pull-9{right:75%}\n\t.col-md-pull-8{right:66.66666666666666%}\n\t.col-md-pull-7{right:58.333333333333336%}\n\t.col-md-pull-6{right:50%}\n\t.col-md-pull-5{right:41.66666666666667%}\n\t.col-md-pull-4{right:33.33333333333333%}\n\t.col-md-pull-3{right:25%}\n\t.col-md-pull-2{right:16.666666666666664%}\n\t.col-md-pull-1{right:8.333333333333332%}\n\t.col-md-pull-0{right:0}\n\t.col-md-push-12{left:100%}\n\t.col-md-push-11{left:91.66666666666666%}\n\t.col-md-push-10{left:83.33333333333334%}\n\t.col-md-push-9{left:75%}\n\t.col-md-push-8{left:66.66666666666666%}\n\t.col-md-push-7{left:58.333333333333336%}\n\t.col-md-push-6{left:50%}\n\t.col-md-push-5{left:41.66666666666667%}\n\t.col-md-push-4{left:33.33333333333333%}\n\t.col-md-push-3{left:25%}\n\t.col-md-push-2{left:16.666666666666664%}\n\t.col-md-push-1{left:8.333333333333332%}\n\t.col-md-push-0{left:0}\n\t.col-md-offset-12{margin-left:100%}\n\t.col-md-offset-11{margin-left:91.66666666666666%}\n\t.col-md-offset-10{margin-left:83.33333333333334%}\n\t.col-md-offset-9{margin-left:75%}\n\t.col-md-offset-8{margin-left:66.66666666666666%}\n\t.col-md-offset-7{margin-left:58.333333333333336%}\n\t.col-md-offset-6{margin-left:50%}\n\t.col-md-offset-5{margin-left:41.66666666666667%}\n\t.col-md-offset-4{margin-left:33.33333333333333%}\n\t.col-md-offset-3{margin-left:25%}\n\t.col-md-offset-2{margin-left:16.666666666666664%}\n\t.col-md-offset-1{margin-left:8.333333333333332%}\n\t.col-md-offset-0{margin-left:0}\n}\n@media(min-width:1200px){\n\t.col-lg-1,.col-lg-10,.col-lg-11,.col-lg-12,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9{float:left}\n\t.col-lg-12{width:100%}\n\t.col-lg-11{width:91.66666666666666%}\n\t.col-lg-10{width:83.33333333333334%}\n\t.col-lg-9{width:75%}\n\t.col-lg-8{width:66.66666666666666%}\n\t.col-lg-7{width:58.333333333333336%}\n\t.col-lg-6{width:50%}\n\t.col-lg-5{width:41.66666666666667%}\n\t.col-lg-4{width:33.33333333333333%}\n\t.col-lg-3{width:25%}\n\t.col-lg-2{width:16.666666666666664%}\n\t.col-lg-1{width:8.333333333333332%}\n\t.col-lg-pull-12{right:100%}\n\t.col-lg-pull-11{right:91.66666666666666%}\n\t.col-lg-pull-10{right:83.33333333333334%}\n\t.col-lg-pull-9{right:75%}\n\t.col-lg-pull-8{right:66.66666666666666%}\n\t.col-lg-pull-7{right:58.333333333333336%}\n\t.col-lg-pull-6{right:50%}\n\t.col-lg-pull-5{right:41.66666666666667%}\n\t.col-lg-pull-4{right:33.33333333333333%}\n\t.col-lg-pull-3{right:25%}\n\t.col-lg-pull-2{right:16.666666666666664%}\n\t.col-lg-pull-1{right:8.333333333333332%}\n\t.col-lg-pull-0{right:0}\n\t.col-lg-push-12{left:100%}\n\t.col-lg-push-11{left:91.66666666666666%}\n\t.col-lg-push-10{left:83.33333333333334%}\n\t.col-lg-push-9{left:75%}\n\t.col-lg-push-8{left:66.66666666666666%}\n\t.col-lg-push-7{left:58.333333333333336%}\n\t.col-lg-push-6{left:50%}\n\t.col-lg-push-5{left:41.66666666666667%}\n\t.col-lg-push-4{left:33.33333333333333%}\n\t.col-lg-push-3{left:25%}\n\t.col-lg-push-2{left:16.666666666666664%}\n\t.col-lg-push-1{left:8.333333333333332%}\n\t.col-lg-push-0{left:0}\n\t.col-lg-offset-12{margin-left:100%}\n\t.col-lg-offset-11{margin-left:91.66666666666666%}\n\t.col-lg-offset-10{margin-left:83.33333333333334%}\n\t.col-lg-offset-9{margin-left:75%}\n\t.col-lg-offset-8{margin-left:66.66666666666666%}\n\t.col-lg-offset-7{margin-left:58.333333333333336%}\n\t.col-lg-offset-6{margin-left:50%}\n\t.col-lg-offset-5{margin-left:41.66666666666667%}\n\t.col-lg-offset-4{margin-left:33.33333333333333%}\n\t.col-lg-offset-3{margin-left:25%}\n\t.col-lg-offset-2{margin-left:16.666666666666664%}\n\t.col-lg-offset-1{margin-left:8.333333333333332%}\n\t.col-lg-offset-0{margin-left:0}\n}\n/*2.2 响应式隐藏显示\n\tName:\t\t\tstyle_Layout\n\tExplain:\t\t左右两栏|左中右三栏|上中下\n\tLast Modify:\tguojunhui\n*/\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg,\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n  display: none !important}\n@media ( max-width : 767px) {\n\t.visible-xs {display: block !important}\n\ttable.visible-xs {display: table}\n\ttr.visible-xs {display: table-row !important}\n\tth.visible-xs,td.visible-xs {display: table-cell !important}\n\t.hidden-xs {display: none !important}\n\t.visible-xs-block {display: block !important}\n\t.visible-xs-inline {display: inline !important}\n\t.visible-xs-inline-block {display: inline-block !important}\n}\n@media ( min-width : 768px) and (max-width: 991px) {\n\t.visible-sm {display: block !important}\n\ttable.visible-sm {display: table}\n\ttr.visible-sm {display: table-row !important}\n\tth.visible-sm,td.visible-sm {display: table-cell !important}\n\t.hidden-sm {display: none !important}\n\t.visible-sm-block {display: block !important}\n\t.visible-sm-inline {display: inline !important}\n\t.visible-sm-inline-block {display: inline-block !important}\n}\n@media ( min-width : 992px) and (max-width: 1199px) {\n\t.visible-md {display: block !important}\n\ttable.visible-md {display: table}\n\ttr.visible-md {display: table-row !important}\n\tth.visible-md,td.visible-md {display: table-cell !important}\n\t.hidden-md {display: none !important}\n\t.visible-md-block {display: block !important}\n\t.visible-md-inline {display: inline !important}\n\t.visible-md-inline-block {display: inline-block !important}\n}\n@media ( min-width : 1200px) {\n\t.visible-lg {display: block !important}\n\ttable.visible-lg {display: table}\n\ttr.visible-lg {display: table-row !important}\n\tth.visible-lg,td.visible-lg {display: table-cell !important}\n\t.hidden-lg {display: none !important}\n\t.visible-lg-block {display: block !important}\n\t.visible-lg-inline {display: inline !important}\n\t.visible-lg-inline-block {display: inline-block !important}\n}\n\n.visible-print {display: none !important}\n.visible-print-block {display: none !important}\n.visible-print-inline {display: none !important}\n.visible-print-inline-block {display: none !important}\n@media print {\n\t.visible-print {display: block !important}\n\ttable.visible-print {display: table}\n\ttr.visible-print {display: table-row !important}\n\tth.visible-print,td.visible-print {display: table-cell !important}\n\t.visible-print-block {display: block !important}\n\t.visible-print-inline {display: inline !important}\n\t.visible-print-inline-block {display: inline-block !important}\n\t.hidden-print {display: none !important}\n}\n/*最外层*/\n.containBox {background-color:#fff;position:relative;z-index:100;zoom:1;-moz-transition:-moz-transform .2s ease-out;-webkit-transition:-webkit-transform .2s ease-out;-o-transition:-o-transform .2s ease-out;transition:transform .2s ease-out;top:0px;}\n.sideBox {display:none}\n\t.containBox-bg{ display: none}\n@media (max-width:767px) {\n    body,.content {font-size:16px;line-height:1.6}\n\thtml,body{height: 100%}\n\t.containBox{ position:fixed; top: 0; left: 0; right: 0; bottom: 0; overflow: hidden;\n\t}\n\t\t.containBox-bg{position:fixed;width:100%;top:0;left:0; display: block;z-index:2000}\n    /*隐藏的菜单*/\n    .sideBox {position:absolute;display:block;z-index:99;right:0;top:0;bottom:0;width:250px;background-color:#303135}\n    .sideBox .navbar-nav {display:block}\n    .sideBox .navbar-nav li {border-bottom:1px solid #222;display:block}\n    .sideBox .navbar-nav a {color:#fff;display:block;padding-left:20px;padding:10px 30px;}\n    .sideBox .navbar-nav a:hover {text-decoration:none;}\n    .Hui-wraper {width:auto;padding:0 10px}\n    .AD-img img {width:100%;height:auto}\n\tbody.sideBox-open .containBox{\n\t\t\t-moz-transform: translate3d(-250px,0,0);\n\t\t-webkit-transform: translate3d(-250px,0,0);\n\t\t\t\ttransform: translate3d(-250px,0,0);\n\t\t\t\tbackface-visibility: hidden;\n\t\t-webkit-backface-visibility: hidden;\n\t\t\t-moz-backface-visibility: hidden;\n\t\t\t-ms-backface-visibility: hidden;\n\t}\n\t.wap-container{ height: 100%;width: 100%;min-width: 320px;overflow: auto;}\n\tbody.sideBox-open .containBox-bg{bottom:0;right:0;}\n}\n/*2.3 常用布局\n\tName:\t\t\tstyle_Layout\n\tExplain:\t\t左右两栏|左中右三栏|上中下\n\tLast Modify:\tguojunhui\n*/\n.Hui-wraper,.wp{margin-left:auto;margin-right:auto;text-align:left}\n.sd{float:right}\n.ct2 .mn{float:left}\n.ct2 .sd{float:right}\n.ct2_r .leftmenu{float:left}\n.ct2_r .mn{float:right}\n.ct3 .app{float:left;margin-right:20px}\n.ct3 .mn{float:left;border-left:solid 1px #ddd}\n.ct3 .sd{float:right}\n.w-1000{width:1000px}\n.w-980{width:980px}\n.w-300{width:300px}\n.w-200{width:200px}\n@media (max-width: 1000px) {\n\t.Hui-wraper,.wp,{ width:auto!important;padding:0 15px!important}\n}\n@media print{\n\t.Hui-wraper{width:auto}\n}\n/*3.0 基础样式*/\n/*3.1 排版*/\n/*3.1.1 标题\n\tExample：\n\t<h1>h1. 大标题<small>小标题</small></h1>\n    <h2>h2. 大标题<small>小标题</small></h2>\n    <h3>h3. 大标题<small>小标题</small></h3>\n    <h4>h4. 大标题<small>小标题</small></h4>\n    <h5>h5. 大标题<small>小标题</small></h5>\n    <h6>h6. 大标题<small>小标题</small></h6>\n*/\nh1,h2,h3,h4,h5,h6{font-weight:500;line-height:1.1;color:inherit}\nh1 small,h2 small,h3 small,h4 small,h5 small,h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small{font-weight:400;line-height:1;color:#999}\nh1,h2,h3{padding-top:20px;padding-bottom:10px}\nh1 small,h2 small,h3 small,h1 .small,h2 .small,h3 .small{font-size:65%}\nh4,h5,h6{margin-top:10px;margin-bottom:10px}\nh4 small,h5 small,h6 small,h4 .small,h5 .small,h6 .small{font-size:75%}\nh1{font-size:36px}\nh2{font-size:30px}\nh3{font-size:24px}\nh4{font-size:18px}\nh5{font-size:14px}\nh6{font-size:12px}\n\n/*3.1.2 强调\n\tExample:\n\t<p>这是段落，向下10像素间距</p>\n\t<smail>小型文本，是父容器字体大小的85%</smail>\n\t<strong>重要文本，加粗显示</strong>\n\t<em>被强调的文本，斜体显示</em>\n\t<u>带下划线的文本</u>\n\t<cite>引用</cite>\n\t<mark>突出显示文本</mark>\n\t<del>带删除线的文本</del>\n\t<pre class=\"prettyprint linenums\">预格式化的文本</pre>\n*/\np{margin-bottom:10px}\t/*段落*/\nsmall{font-size:85%}\t/*小型文本*/\nb,strong {font-weight: bold}\t/*重要的文本，加粗*/\nem{font-style:italic}\t/*被强调的文本*/\ni{}\t/*斜体*/\nu{}\t/*加下划线*/\ncite{font-style:normal}\t/*引用*/\nmark{color:#000;background:#ff0}/*突出显示文本*/\nvar{}\t/*变量*/\nkbd{}\t/*键盘文本*/\ncode{}\t/*计算机代码文本*/\ndfn{font-style: italic}\t/*一个定义项目*/\ndel{}\t/*删除线*/\ncode,kbd,pre,samp {font-family: monospace, serif;font-size: 1em}\npre{white-space: pre-wrap}\t/*预格式化的文本*/\n.uppercase{text-transform:uppercase} /*文字大写*/\n.lowercase{text-transform:lowercase} /*文字小写*/\n.capitalize{text-transform:capitalize} /*首字母大写*/\n.en{font-family:Arial!important}\n/*3.1.3 对齐\n\tName:\t\t\tstyle_text-align\n\tExample:\t\tclass=\"text-l|text-r|text-c|va-t|va-m|va-b\"\n\tExplain:\t\t.text-水平对齐 （.text-l左对齐|.text-r右对齐|.text-c居中对齐）\n\t\t\t\t\t.va-上下对齐 （.va-t 居上对齐|.va-m 居中对齐|.va-b 居下对齐）\n*/\n.text-l{text-align:left}.text-r{text-align:right}.text-c{text-align:center}\n.va *{vertical-align:sub!important;*vertical-align:middle!important;_vertical-align:middle!important}\n.va-t{vertical-align:top!important}.va-m{vertical-align:middle!important}.va-b{vertical-align:bottom!important}\n/*3.1.4 定位\n\tName:\t\t\tstyle_position\n\tExample:\t\tclass=\"pos-r|pos-a|pos-f\"\n\tExplain:\t\t.pos-r 相对定位|.pos-a 绝对定位|.pos-f 固定\n*/\n.pos-r{position:relative}.pos-a{position:absolute}.pos-f{position:fixed}\n/*3.1.5 浮动\n\tName:\t\t\tstyle_float\n\tExample:\t\tclass=\"l|r\"\n\tExplain:\t\t.l 左浮动|.r 右浮动\n*/\n.l,.f-l{float:left!important;_display:inline}\n.r,.f-r{float:right!important;_display:inline}\n\n[class*=\"span\"].r,\n[class*=\"span\"].f-r{float:right}\n\n/*控制元素对定位的位置：居左|居右|j居上|居下*/\n.pos-left{left:0; right:auto}\n.pos-right{right:0; left:auto}\n.pos-top{top:0; bottom:auto}\n.pos-bottom{top:auto; bottom:0}\n\n/*3.1.6 文字单行溢出省略号\n\tName:\t\t\tstyle_text-overflow\n\tExample:\t\tclass=\"text-overflow\"\n*/\n.text-overflow{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n/*3.1.7 线条\n\tName:\t\t\tstyle_line\n\tExample:\t\tclass=\"line\"\n*/\n.line{font-size:0; line-height:0; border-top: solid 1px #eee; float: none}\n/*3.1.8 外边距\n\tName:\t\t\tstyle_margin\n\tExample:\t\tclass=\"mt-5|mt-10...\"\n\tExplain:\t\t.mt表示上边距|.mb表示下边距|.ml表示左边距|.mr表示右边距\n*/\n.mt-5{margin-top:5px}.mt-10{margin-top:10px}.mt-15{margin-top:15px}.mt-20{margin-top:20px}.mt-25{margin-top:25px}.mt-30{margin-top:30px}.mt-35{margin-top:35px}.mt-40{margin-top:40px}.mt-50{margin-top:50px}\n.mb-5{margin-bottom:5px}.mb-10{margin-bottom:10px}.mb-15{margin-bottom:15px}.mb-20{margin-bottom:20px}.mb-30{margin-bottom:30px}.mb-40{margin-bottom:40px}.mb-50{margin-bottom:50px}\n.ml-5{margin-left:5px}.ml-10{margin-left:10px}.ml-15{margin-left:15px}.ml-20{margin-left:20px}.ml-30{margin-left:30px}.ml-40{margin-left:40px}.ml-50{margin-left:50px}\n.mr-5{margin-right:5px}.mr-10{margin-right:10px}.mr-15{margin-right:15px}.mr-20{margin-right:20px}.mr-30{margin-right:30px}.mr-40{margin-right:40px}.mr-50{margin-right:50px}\n/*3.1.9 内填充\n\tName:\t\t\tstyle_padding\n\tExample:\t\tclass=\"pt-5|pt-10|……\"\n\tExplain:\t\t.pt表示上填充|.pb表示下填充|.pl表示左填充|.pr表示右填充\n*/\n.pt-5{padding-top:5px}.pt-10{padding-top:10px}.pt-15{padding-top:15px}.pt-20{padding-top:20px}.pt-25{padding-top:25px}.pt-30{padding-top:30px}\n.pb-5{padding-bottom:5px}.pb-10{padding-bottom:10px}.pb-15{padding-bottom:15px}.pb-20{padding-bottom:20px}.pb-25{padding-bottom:25px}.pb-30{padding-bottom:30px}\n.pl-5{padding-left:5px}.pl-10{padding-left:10px}.pl-15{padding-left:15px}.pl-20{padding-left:20px}.pl-25{padding-left:25px}.pl-30{padding-left:30px}\n.pr-5{padding-right:5px}.pr-10{padding-right:10px}.pr-15{padding-right:15px}.pr-20{padding-right:20px}.pr-25{padding-right:25px}.pr-30{padding-right:30px}\n.pd-5{padding:5px}.pd-10{padding:10px}.pd-15{padding:15px}.pd-20{padding:20px}.pd-25{padding:25px}.pd-30{padding:30px}.pd-40{padding:40px}\n/*3.1.10 边框，css3圆角\n\tName:\t\t\tstyle-border\n\tExample:\t\tclass=\"bk_gray radius\"\n\tExplain:\t\t.bk_gray 边框|radius 圆角|round 椭圆 | circle 圆形\n*/\n.bk-gray{border:solid 1px #eee}\n.radius{border-radius:4px}\n.size-MINI.radius{ border-radius:3px}\n.size-L.radius{ border-radius:5px}\n.size-XL.radius{ border-radius:6px}\n.round{border-radius:50%; overflow:hidden}\n\n/*3.1.11 css3阴影\n\tName:\t\t\tstyle_shadow\n\tExample:\t\tclass=\"box_shadow|text-shadow\"\n\tExplain:\t\tbox_shadow 块级元素阴影，全局样式，可用在表格，文本框，文本域，div等块级元素上。\n\t\t\t\t\ttext-shadow 文字阴影\n*/\n.box-shadow{-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.1);box-shadow:0 1px 2px rgba(0,0,0,0.1)}\n.text-shadow{-webkit-text-shadow:0 0 2px rgba(0,0,0,0.2);text-shadow:0 0 2px rgba(0,0,0,0.2)}\n/*3.1.12 行内分割竖线\n\tName:\t\t\tstyle_pipe\n\tExample:\t\t<span class=\"pipe\">|</span>\n*/\n.pipe{margin:0 5px;color:#CCC;font-size:10px!important}\n/*3.1.13 文字尺寸\n\tName:\t\t\tstyle_font-size\n\tExample:\t\tclass=\"f-12|f-14|f-16|f-18|f-20|f-24|f-26|f-28|f-30\"\n\tExplain:\t\t12px字体|14px字体|16px字体|18px字体|20px字体|24px字体|26px字体|28px字体|30px字体\n*/\n.f-12{font-size:12px}.f-14{font-size:14px}.f-16{font-size:16px}.f-18{font-size:18px}.f-20{font-size:20px}.f-22 { font-size: 22px }.f-24{font-size:24px}.f-26{font-size:26px}.f-28{font-size:28px}.f-30{font-size:30px}\n/*3.1.14 文字行距\n\tName:\t\t\tmod_line-height\n\tExample:\t\tclass=\"lh-16|lh-18|lh-20|lh-22|lh-24|lh-26|lh-28|lh-30\"\n\tExplain:\t\t16px行高|18px行高|20px行高|22px行高|24px行高|26px行高|30px行高\n*/\n.lh-16{line-height:16px}.lh-18{line-height:18px}.lh-20{line-height:20px}.lh-22{line-height:22px}.lh-24{line-height:24px}.lh-26{line-height:26px}.lh-28{line-height:28px}.lh-30{line-height:30px}\n/*2.0以前的兼容版本*/\n.l16{line-height:16px}.l18{line-height:18px}.l20{line-height:20px}.l22{line-height:22px}.l-24{line-height:24px}.l-26{line-height:26px}.l-28{line-height:28px}.l-30{line-height:30px}\n\n/*3.1.15 文字颜色\n\tName:\t\t\tstyle_color\n\tExample:\t\tclass=\"c-primary|c-sub|c-success|c-danger|c-warning|c-333|c-666|c-999|c-red|c-green|c-blue|c-white|c-black|c-orange\"\n\tExplain:\t\t主要颜色|次主色|强调色—成功|强调色—危险|强调色—警告色|强调色—错误色|次主色—浅黑|辅助色—灰色|标准色—红色|标准色—绿色|标准色—蓝色|标准色—白色|标准色—黑色|标准色—橙色\n*/\n/*全局默认链接颜色*/\nbody{ background-color:#fff; color:#333}\n.bg-fff{ background-color:#fff}\na{color:#333}\na:hover,.active a{color:#06c}\n\n/*主要颜色*/\n.c-primary,.c-primary a,a.c-primary{color:#5a98de}\n.c-primary a:hover,a.c-primary:hover{ color:#5a98de}\n/*次主色*/\n.c-secondary,.c-secondary a,a.c-secondary{color:#555}\n.c-secondary a:hover,a.c-secondary:hover{ color:#555}\n\n/*强调色—成功*/\n.c-success,.c-success a,a.c-success{color:#5eb95e}\n.c-success a:hover,a.c-success:hover{ color:#5eb95e}\n\n/*强调色—危险*/\n.c-danger,.c-danger a,a.c-danger{color:#dd514c}\n.c-danger a:hover,a.c-danger:hover{ color:#dd514c}\n\n/*强调色—警告*/\n.c-warning,.c-warning a,a.c-warning{color:#f37b1d}\n.c-warning a:hover,a.c-warning:hover{ color:#f37b1d}\n\n/*强调色—错误*/\n.c-error,.c-error a,a.c-error{color:#c00}\n.c-error a:hover,a.c-error:hover{ color:#c00}\n\n/*辅助色—浅黑*/\n.c-333,.c-333 a,a.c-333{color:#333}\n.c-333 a:hover,a.c-333:hover{ color:#333}\n\n/*辅助色—灰色*/\n.c-666,.c-666 a,a.c-666{color:#666}\n.c-666 a:hover,a.c-666:hover{ color:#666}\n.c-999,.c-999 a,a.c-999{color:#999}\n.c-999 a:hover,a.c-999:hover{color:#999}\n\n/*标准色—红色*/\n.c-red,.c-red a,a.c-red{color:red}\n.c-red a:hover,a.c-red:hover{ color:red}\n/*标准色—绿色*/\n.c-green,.c-green a,a.c-green{color:green}\n.c-red a:hover,a.c-red:hover{color:green}\n/*标准色—蓝色*/\n.c-blue,.c-blue a,a.c-blue{color:blue}\n.c-blue a:hover,a.c-blue:hover{color:blue}\n/*标准色—白色*/\n.c-white,.c-white a,a.c-white{color:white}\n.c-white a:hover,a.c-white:hover{color:white}\n/*标准色—黑色*/\n.c-black,.c-black a{color:black}\n.c-black a:hover,a.c-black:hover{color:black}\n/*标准色—橙色*/\n.c-orange,.c-orange a,a.c-orange{color:orange}\n.c-orange a:hover,a.c-orange:hover{color:orange}\n\n/*3.1.16 文字颜色强调\t从2.0起废弃3.1.16 文字强调，字体颜色全部放入到3.1.15\n\tExample:\t\tclass=\"text-muted|text-primary|text-warning|text-error|text-danger|text-success|text-info\"\n\tExplain:\t\t柔和|重要|警告|错误|危险|成功|信息\n*/\n\n\n/*3.1.17 缩略语\n\tExample:\t\t<abbr title=\"User Interface\" class=\"initialism\">UI</abbr>\n\tExplain:\n*/\nabbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}\nabbr.initialism{font-size:90%;text-transform:uppercase}\n/*3.1.18 地址\n\tExample:\t\t<address>北京市海淀区上地……</address>\n\tExplain:\n*/\naddress{display:block;margin-bottom:20px;font-style:normal;line-height:20px}\n/*3.1.19 引用\n\tExample:\t\t<blockquote>这是引用的内容</blockquote>\n\tExplain:\n*/\nblockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}\nblockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}\nblockquote small{display:block;line-height:20px;color:#999}\nblockquote small:before{content:'\\2014 \\00A0'}\nblockquote.text-r{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}\nblockquote.text-r p,blockquote.text-r small{text-align:right}\nblockquote.text-r small:before{content:''}\nblockquote.text-r small:after{content:'\\00A0 \\2014'}\nq:before,q:after,blockquote:before,blockquote:after{content:\"\"}\nq {/*短的引用*/quotes: \"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\n/*3.1.20 上标，下标\n\tExample:\t\t<sup>2</sup>\t<sub>2<sub>\n\tExplain:\t\t上标|下标\n*/\nsub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}\nsup{top:-0.5em}sub{bottom:-0.25em}\n/*3.1.21 内容样式\n\tName:\t\t\tstyle_content\n\tExample:\t\t<div class=\"content\"><p>……</p></div>\n\tExplain:\t\t内容样式\n*/\n.content{position:relative;font-size:17px;line-height:1.8;overflow:hidden;text-align:left;word-break: break-all;word-wrap: break-word}\n.content h3{font-size:18px}\n.content h4{font-size:16px}\n.content p{margin-bottom: 1.5rem;text-align: justify;word-break:break-all}\n.content p.text-c{ text-align:center}\n\t.indent{ text-indent:2em}\n.content img{max-width:100%}\n.content ul{text-indent:2em}\n@media (max-width: 767px) {\n\t.content{ font-size:16px}\n}\n@media (max-width: 480px) {\n\t.content img{max-width:100%!important; height:auto!important;width:expression(this.width > 320 ? \"320px\" : this.width)!important}\n\t*html .content img{width:expression(this.width>320&&this.width>this.height?320:auto)}\n}\n/*3.1.22 列表\n\tName:\t\t\tstyle_ulolli\n\tExample:\n<ul class=\"list-view\">\n\t<li class=\"item\">无序列表</li>\n\t<li class=\"item\">无序列表</li>\n\t<li class=\"item\">无序列表</li>\n</ul>\n<ol class=\"list-view\">\n\t<li class=\"item\">无序列表</li>\n\t<li class=\"item\">无序列表</li>\n\t<li class=\"item\">无序列表</li>\n</ol>\n\tExplain:\n*/\nul.unstyled,ol.unstyled{margin-left:0;list-style:none}\nul.inline,ol.inline{margin-left:0;list-style:none}\nul.inline > li,ol.inline > li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}\n.list-view > .item{ padding:10px; position:relative; overflow:hidden}/*禁止换行*/\n.list-view > .item .date{font-size:12px; font-family:Arial; color:#999}\n/*横向手机 竖向平板*/\n@media (max-width: 767px) {\n\t.list-view > .item{ font-size:18px; padding:11px 15px;border-bottom: 1px solid #eee}\n\t.list-view > .item > a{display:block; margin:-11px -15px}\n\t.night .list-view > .item{border-bottom: 1px solid #1F1F1F}\n\t.list-view > .item .date{display:none}\n\t.list-view > .item .Hui-iconfont {background-size:9px auto;margin-top:-7px;position: absolute;right:15px;top: 50%}\n}\n\n/*排行榜*/\n/*<ol class=\"list-view list-top\"><li class=\"item\"><em class=\"num\">1</em><a href=\"#\">排行榜列表</a><span class=\"date\">12</span></li></ol>*/\n.list-top > .item{padding-left: 30px}\n.list-top > .item .num{ position:absolute; top:11px; display:block; width:20px; height:20px; color:#fff; background-color:#5a98de; text-align:center}\n\n/*3.1.23 描述\n\tName:\t\t\tstyle_dldtdd\n\tExample:\t\t<dl class=\"dl-horizontal cl\"><dt>H-ui</dt><dd>基于Bootstrap框架的改进扩展的前端框架</dd></dl>\n\tExplain:\t\t.dl-horizontal 水平描述，默认不加为垂直模式。\n*/\n.dl-horizontal.cl{}\n.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}\n.dl-horizontal dd{margin-left:180px}\n/*3.1.24 隐藏 显示\n  Name:\t\t\t\tstyle_display\n  Example:    <div class=\"hide\">隐藏的内容</div> <div class=\"show\">显示的内容</div>\n  Explain:    \t\t.hide 隐藏 / .show 显示\n*/\n.hide{display:none}[hidden]{display: none}\n.hidden{display:none!important;visibility:hidden!important}\n.f-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}\n[class*=\"span\"].hide,.row-fluid [class*=\"span\"].hide{display:none}\n.show{display:block}\n.invisible{visibility:hidden}\n\n/*3.1.25 尺寸\t新增尺寸全局类名，用于表单、按钮、表格、头像、标签等元素上，要与元素一起配合使用，方能看到效果*/\n.size-MINI{}/*迷你*/\n.size-S{}/*小*/\n.size-M{}/*中 缺省默认尺寸，可以不写，可以理解为：均码*/\n.size-L{}/*L*/\n.size-XL{}/*大*/\n.size-XXL{}/*加大*/\n.size-XXXL{}/*超大*/\n\n.input-text,.btn,.input-text.size-M,.btn.size-M{ font-size:14px; height:31px;*height:auto;line-height:1.42857;padding:4px}/*默认为M，可以不写，可以理解为：均码*/\na.btn,a.btn.size-M,span.btn,span.btn.size-M{ line-height:21px}\n.btn,.btn.size-M{ padding:4px 12px}\n\n.input-text.size-MINI,.btn.size-MINI{font-size:12px; height:23px;padding:1px 2px;line-height:1.42857}/*迷你*/\na.btn.size-MINI,span.btn.size-MINI{ line-height:21px}\n.btn.size-MINI{ padding:1px 4px}\n\n.input-text.size-S,.btn.size-S{font-size:12px; height:27px;padding:3px;line-height:1.42857}/*小*/\na.btn.size-S,span.btn.size-S{ line-height:19px}\n.btn.size-S{ padding:3px 8px}\n\n.input-text.size-L,.btn.size-L{font-size:16px; height:41px; padding:8px}/*大*/\na.btn.size-L,span.btn.size-L{ line-height:23px}\n.btn.size-L{ padding:8px 16px}\n\n.input-text.size-XL,.btn.size-XL{font-size:18px; height:48px; padding:10px}/*特大*/\na.btn.size-XL,span.btn.size-XL{ line-height:26px}\n.btn.size-XL{ padding:10px 24px}\n\n@media (max-width: 767px) {\n\t.responsive .input-text.size-MINI,.responsive .btn.size-MINI{height:24px}\n\t.responsive .input-text.size-S,.responsive .btn.size-S{ font-size:14px; height:30px}\n\t.responsive .input-text,.btn,.responsive .input-text.size-M,.responsive .btn.size-M{ font-size:16px; height:36px}\n\t.responsive .input-text.size-L,.responsive .btn.size-L{ font-size:18px; height:42px}\n\t.responsive .input-text.size-XL,.responsive .btn.size-XL{ font-size:20px; height:48px}\n}\n\n/*3.2 代码\n\tName:\t\t\tstyle_pre\n\n\tExample:\t\t<code></code>,<pre class=\"prettyprint linenums\">转义过的代码</pre>\n\tExplain:\t\tcode：行内代码，pre：基本代码块;包装代码片段，.prettyprint颜色增强/.linenums显示行号\n*/\ncode{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,\"Courier New\",monospace}\npre .title,pre .keyword,pre .body,pre .des{color:#333}/*关键词*/\n\npre{display:block;font-family:Monaco,Menlo,Consolas,\"Courier New\",monospace;padding:9.5px;margin-bottom:10px;font-size:12px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px;color:#333}\n.prettyprint{margin-bottom:20px;padding:8px;background-color:#f7f7f9;border:1px solid #e1e1e8}\n.prettyprint .com { color: #998;font-style:italic }/*注释*/\n.prettyprint .tag{color:#007}/*标签*/\n.prettyprint .lit { color: #195f91}\n.prettyprint .pun,.prettyprint .opn,.prettyprint .clo { color: #93a1a1}/*等于*/\n.prettyprint .fun { color: #dc322f}\n.prettyprint .str,.prettyprint .atv { color: #D14}/*值*/\n.prettyprint .kwd,.prettyprint .prettyprint .tag { color: #1e347b}\n.prettyprint .typ,.prettyprint .atn,.prettyprint .dec,.prettyprint .var { color: teal}/*文档声明，属性*/\n.prettyprint .pln { color: #48484c}\n\n.prettyprint.linenums{box-shadow:inset 40px 0 0 #fbfbfc,inset 41px 0 0 #ececf0}\n.pre-scrollable{max-height:340px;overflow-y:scroll}\nol.linenums{list-style:decimal outside none; margin-left:20px}\nol.linenums li{ line-height:28px; padding-left:10px}\npre ol.linenums{margin:0 0 0 33px}\npre ol.linenums li{padding-left:12px;color:#bbb;line-height:18px;text-shadow:0 1px 0 #fff}\n\n@media (max-width: 767px) {\n\tpre ol.linenums{ margin-left:0; list-style:none}\n\tol.linenums li{ padding-left:0}\n\t.prettyprint.linenums{box-shadow:inset 0px 0 0 #fbfbfc,inset 0px 0 0 #ececf0}\n}\n\n/*3.3 表格\n\tName:\t\t\tstyle_table\n\tExample:\t\t<table class=\"table table-bordered table-striped table-condensed\"><thead><tr><th>…</th></tr></thead><tbody><tr><td>…</td></tr></tbody></table>\n\tExplain:\t\t表格，None无样式，仅仅有列和行|.table行与行之间以水平线相隔|.table-bordered表格外围均有外边框|.table-striped奇数行背景设为浅灰色|.table-condensed竖直方向padding缩减一半，从8px变为4px，所有的 td 和 th 元素都受影响\n*/\n/*默认table*/\ntable{width:100%;empty-cells:show;background-color:transparent;border-collapse:collapse;border-spacing:0}\ntable th{text-align:left; font-weight:400}\n/*带水平线*/\n.table th{font-weight:bold}\n.table th,.table td{padding:8px;line-height:20px;word-break:break-all}\n.table td{text-align:left}\n.table tbody tr.success > td{background-color:#dff0d8}\n.table tbody tr.error > td{background-color:#f2dede}\n.table tbody tr.warning > td{background-color:#fcf8e3}\n.table tbody tr.info > td{background-color:#d9edf7}\n.table tbody + tbody{border-top:2px solid #ddd}\n.table .table{background-color:#fff}\n\n/*带横向分割线*/\n.table-border{border-top:1px solid #ddd}\n.table-border th,.table-border td{border-bottom:1px solid #ddd}\n\n/*th带背景*/\n.table-bg thead th{background-color:#F5FAFE}\n/*带外边框*/\n.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0}\n.table-bordered th,.table-bordered td{border-left:1px solid #ddd}\n.table-border.table-bordered{border-bottom:0}\n\n/*奇数行背景设为浅灰色*/\n.table-striped tbody > tr:nth-child(odd) > td,\n.table-striped tbody > tr:nth-child(odd) > th{background-color:#f9f9f9}\n/*竖直方向padding缩减一半*/\n.table-condensed th,\n.table-condensed td{padding:4px 5px}\n/*鼠标悬停样式*/\n.table-hover tbody tr:hover td,\n.table-hover tbody tr:hover th{background-color: #f5f5f5}\n/*鼠标选择整行样式*/\n.table tbody tr.selected td{background-color:#F3F3F3}\n/*定义颜色*/\n/*悬停在行*/\n.table tbody tr.active,\n.table tbody tr.active > td,\n.table tbody tr.active > th,\n.table tbody tr .active{ background-color:#F5F5F5!important}\n/*成功或积极*/\n.table tbody tr.success,\n.table tbody tr.success > td,\n.table tbody tr.success > th,\n.table tbody tr .success{background-color:#DFF0D8!important}\n\n/*警告或出错*/\n.table tbody tr.warning,\n.table tbody tr.warning > td,\n.table tbody tr.warning > th,\n.table tbody tr .warning{background-color:#FCF8E3!important}\n/*危险*/\n.table tbody tr.danger,\n.table tbody tr.danger > td,\n.table tbody tr.danger > th,\n.table tbody tr .danger{background-color:#F2DEDE!important}\n\n/*表格文字对齐方式，默认是居左对齐*/\n.table .text-c th,.table .text-c td{text-align:center}/*整行居中*/\n.table .text-r th,.table .text-r td{text-align:right}/*整行居右*/\n.table th.text-l,.table td.text-l{text-align:left!important}/*单独列居左*/\n.table th.text-c,.table td.text-c{text-align:center!important}/*单独列居中*/\n.table th.text-r,.table td.text-r{text-align:right!important}/*单独列居右*/\n\n/*datatable*/\ntable.dataTable {border-collapse: separate;border-spacing: 0;clear: both}\ntable.dataTable thead .sorting_asc, table.dataTable thead .sorting_desc, table.dataTable thead .sorting {cursor: pointer; background-repeat:no-repeat;background-position:right center}\ntable.dataTable thead .sorting{background-image:url(../images/dataTable/sort_both.png)}\ntable.dataTable thead .sorting_asc {background-image:url(../images/dataTable/sort_asc.png)}\ntable.dataTable thead .sorting_desc {background-image:url(../images/dataTable/sort_desc.png)}\n.dataTable td.sorting_1 {background-color: #f5fafe}\n.dataTables_wrapper .dataTables_length {float: left;padding-bottom:20px}\n.dataTables_wrapper .dataTables_length .select{ width:50px}\n.dataTables_wrapper .dataTables_filter {float: right;text-align: right}\n.dataTables_wrapper .dataTables_filter .input-text { width:auto}\n.dataTables_wrapper .dataTables_info {clear: both;float: left;padding-top:10px;font-size:14px; color:#666}\n.dataTables_wrapper .dataTables_paginate {float: right;padding-top:10px;text-align: right}\n.dataTables_wrapper .dataTables_paginate .paginate_button {border: 1px solid #ccc;cursor: pointer;display: inline-block;margin-left: 2px;text-align: center;text-decoration: none;color: #666;height: 26px;line-height: 26px;text-decoration: none;margin: 0 0px 6px 6px;padding: 0 10px;font-size:14px}\n.dataTables_wrapper .dataTables_paginate .paginate_button:hover,\n.dataTables_wrapper .dataTables_paginate .paginate_button.current,\n.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {background:#5a98de;color:#fff}\n\n/*表格尺寸*/\n.table.size-MINI{}/*迷你*/\n.table.size-S{}/*小*/\n.table.size-M{}/*中*/\n.table.size-L{}/*默认为L，可以不写，可以理解为：均码*/\n.table.size-XL{}/*大*/\n.table.size-XXL{}/*加大*/\n.table.size-XXXL{}/*超大*/\n\n/*让表格支持响应式*/\n/*\n<div class=\"table-responsive\">\n  <table class=\"table\">\n    ...\n  </table>\n</div>\n*/\n@media (max-width: 767px) {\n\t/*.table-responsive {width: 100%;margin-bottom: 15px;overflow-x: scroll;overflow-y: hidden;border: 1px solid #ddd;-ms-overflow-style: -ms-autohiding-scrollbar;-webkit-overflow-scrolling: touch}\n\t.table-responsive > .table {margin-bottom: 0}\n\t.table-responsive > .table > thead > tr > th,\n\t.table-responsive > .table > tbody > tr > th,\n\t.table-responsive > .table > tfoot > tr > th,\n\t.table-responsive > .table > thead > tr > td,\n\t.table-responsive > .table > tbody > tr > td,\n\t.table-responsive > .table > tfoot > tr > td {white-space: nowrap}\n\t.table-responsive > .table-bordered {border: 0}\n\t.table-responsive > .table-bordered > thead > tr > th:first-child,\n\t.table-responsive > .table-bordered > tbody > tr > th:first-child,\n\t.table-responsive > .table-bordered > tfoot > tr > th:first-child,\n\t.table-responsive > .table-bordered > thead > tr > td:first-child,\n\t.table-responsive > .table-bordered > tbody > tr > td:first-child,\n\t.table-responsive > .table-bordered > tfoot > tr > td:first-child {border-left: 0}\n\t.table-responsive > .table-bordered > thead > tr > th:last-child,\n\t.table-responsive > .table-bordered > tbody > tr > th:last-child,\n\t.table-responsive > .table-bordered > tfoot > tr > th:last-child,\n\t.table-responsive > .table-bordered > thead > tr > td:last-child,\n\t.table-responsive > .table-bordered > tbody > tr > td:last-child,\n\t.table-responsive > .table-bordered > tfoot > tr > td:last-child {border-right: 0}\n\t.table-responsive > .table-bordered > tbody > tr:last-child > th,\n\t.table-responsive > .table-bordered > tfoot > tr:last-child > th,\n\t.table-responsive > .table-bordered > tbody > tr:last-child > td,\n\t.table-responsive > .table-bordered > tfoot > tr:last-child > td {border-bottom: 0}\n\t*/\n\t.table-responsive th,.table-responsive td{ display: block;width: 100%!important;box-sizing: border-box;}\n\n}\n\n/*3.4 表单\n\tName:\t\t\tstyle_form\n\tExample:\n\tExplain:\n\n*/\n/*3.4.1 input,textarea 文本域 文本区域*/\n/*默认状态*/\n.input-text,.textarea{box-sizing:border-box;border:solid 1px #ddd;width:100%;\n    -webkit-transition:all 0.2s linear 0s;\n       -moz-transition:all 0.2s linear 0s;\n         -o-transition:all 0.2s linear 0s;\n            transition:all 0.2s linear 0s}\n.textarea{ height:100px; resize:none; font-size:14px; padding:4px}\n\t.textarea-numberbar{ position:absolute; right:20px; bottom:5px; z-index:1; margin-bottom:0}\n\t.textarea-length{ font-style:normal}\n.input-text:hover,\n.textarea:hover{border: solid 1px #3bb4f2}\n/*得到焦点后*/\n.input-text.focus,\n.textarea.focus{border:solid 1px #0f9ae0 \\9;border-color:rgba(82,168,236,0.8);box-shadow:0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px rgba(102, 175, 233, 0.6)}\n/*不可点击*/\n.input-text.disabled\n,.textarea.disabled,\n.input-text.disabled.focus,\n.textarea.disabled.focus{background-color:#ededed; cursor:default;border-color: #ddd;\n\t-webkit-box-shadow:inset 0 2px 2px #e8e7e7;\n       -moz-box-shadow:inset 0 2px 2px #e8e7e7;\n            box-shadow:inset 0 2px 2px #e8e7e7}\n/*只读状态*/\n.input-text.disabled,\n.textarea.disabled{background-color:#e6e6e6; cursor:default}\n/*阴影*/\n.input-text.box-shadow,\n.textarea.box-shadow{-ms-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}\n/*行内元素*/\n.input-text.inline{ display:inline-block; width:auto}\n\n/*3.4.2 checkbox radio  单选 多选\n\tExample:\n<div class=\"skin-minimal\">\n  <div class=\"check-box\">\n    <input type=\"checkbox\" id=\"checkbox-1\">\n    <label for=\"checkbox-1\">复选框</label>\n  </div>\n</div>\n\n<div class=\"skin-minimal\">\n  <div class=\"radio-box\">\n    <input type=\"radio\" id=\"minimal-radio-1\" name=\"mapper-radio1\">\n    <label for=\"minimal-radio-1\">单选按钮</label>\n  </div>\n</div>\n\tExplain:\n*/\n\ninput[type=\"radio\"],input[type=\"checkbox\"] {line-height: normal; margin-top:-4px}\n.check-box,.radio-box{ display:inline-block; box-sizing:border-box; cursor:pointer; position:relative; padding-left:30px; padding-right:20px}\n.icheckbox,\n.icheckbox-red,\n.icheckbox-green,\n.icheckbox-blue,\n.icheckbox-aero,\n.icheckbox-grey,\n.icheckbox-orange,\n.icheckbox-yellow,\n.icheckbox-pink,\n.icheckbox-purple,\n.iradio,\n.iradio-red,\n.iradio-green,\n.iradio-blue,\n.iradio-aero,\n.iradio-grey,\n.iradio-orange,\n.iradio-yellow,\n.iradio-pink,\n.iradio-purple {position: absolute;top:4px;left: 0}\n@media (max-width: 767px) {\n\t.responsive .check-box,\n\t.responsive .radio-box{ display:block}\n}\n/*3.4.2.1 jQuery.icheck.css*/\n/* iCheck.js Minimal skin\n----------------------------------- */\n.icheckbox,.iradio{display: block;margin: 0;padding: 0;width: 18px;height: 18px;background: url(../images/iCheck/minimal.png) no-repeat;border: none;cursor: pointer}\n.icheckbox,.icheckbox.static:hover{background-position: 0 0}\n.icheckbox.hover,.icheckbox:hover{background-position: -20px 0}\n.icheckbox.checked{background-position: -40px 0}\n.icheckbox.disabled{background-position: -60px 0;cursor: default}\n.icheckbox.checked.disabled{background-position: -80px 0}\n.iradio,.iradio.static:hover{background-position: -100px 0}\n.iradio.hover,.iradio:hover{background-position: -120px 0}\n.iradio.checked{background-position: -140px 0}\n.iradio.disabled{background-position: -160px 0;cursor: default}\n.iradio.checked.disabled{background-position: -180px 0}\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  only screen and (-moz-min-device-pixel-ratio: 1.5),  only screen and (-o-min-device-pixel-ratio: 1.5),  only screen and (min-device-pixel-ratio: 1.5){.icheckbox,.iradio{background-image: url(../images/iCheck/minimal@2x.png);\n\t-webkit-background-size: 200px 20px;\n\tbackground-size: 200px 20px}\n}\n/* red */\n.icheckbox-red,.iradio-red{display: block;margin: 0;padding: 0;width: 18px;height: 18px;background: url(../images/iCheck/red.png) no-repeat;border: none;cursor: pointer}\n.icheckbox-red,.icheckbox-red.static:hover{background-position: 0 0}\n.icheckbox-red.hover,.icheckbox-red:hover{background-position: -20px 0}\n.icheckbox-red.checked{background-position: -40px 0}\n.icheckbox-red.disabled{background-position: -60px 0;cursor: default}\n.icheckbox-red.checked.disabled{background-position: -80px 0}\n.iradio-red,.iradio-red.static:hover{background-position: -100px 0}\n.iradio-red.hover,.iradio-red:hover{background-position: -120px 0}\n.iradio-red.checked{background-position: -140px 0}\n.iradio-red.disabled{background-position: -160px 0;cursor: default}\n.iradio-red.checked.disabled{background-position: -180px 0}\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  only screen and (-moz-min-device-pixel-ratio: 1.5),  only screen and (-o-min-device-pixel-ratio: 1.5),  only screen and (min-device-pixel-ratio: 1.5){.icheckbox-red,.iradio-red{background-image: url(../images/iCheck/red@2x.png);\n\t-webkit-background-size: 200px 20px;\n\tbackground-size: 200px 20px}\n}\n/* green */\n.icheckbox-green,.iradio-green{display: block;margin: 0;padding: 0;width: 18px;height: 18px;background: url(../images/iCheck/green.png) no-repeat;border: none;cursor: pointer}\n.icheckbox-green,.icheckbox-green.static:hover{background-position: 0 0}\n.icheckbox-green.hover,.icheckbox-green:hover{background-position: -20px 0}\n.icheckbox-green.checked{background-position: -40px 0}\n.icheckbox-green.disabled{background-position: -60px 0;cursor: default}\n.icheckbox-green.checked.disabled{background-position: -80px 0}\n.iradio-green,.iradio-green.static:hover{background-position: -100px 0}\n.iradio-green.hover,.iradio-green:hover{background-position: -120px 0}\n.iradio-green.checked{background-position: -140px 0}\n.iradio-green.disabled{background-position: -160px 0;cursor: default}\n.iradio-green.checked.disabled{background-position: -180px 0}\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  only screen and (-moz-min-device-pixel-ratio: 1.5),  only screen and (-o-min-device-pixel-ratio: 1.5),  only screen and (min-device-pixel-ratio: 1.5){.icheckbox-green,.iradio-green{background-image: url(../images/iCheck/green@2x.png);\n\t-webkit-background-size: 200px 20px;\n\tbackground-size: 200px 20px}\n}\n/* blue */\n.icheckbox-blue,.iradio-blue{display: block;margin: 0;padding: 0;width: 18px;height: 18px;background: url(../images/iCheck/blue.png) no-repeat;border: none;cursor: pointer}\n.icheckbox-blue,.icheckbox-blue.static:hover{background-position: 0 0}\n.icheckbox-blue.hover,.icheckbox-blue:hover{background-position: -20px 0}\n.icheckbox-blue.checked{background-position: -40px 0}\n.icheckbox-blue.disabled{background-position: -60px 0;cursor: default}\n.icheckbox-blue.checked.disabled{background-position: -80px 0}\n.iradio-blue,.iradio-blue.static:hover{background-position: -100px 0}\n.iradio-blue.hover,.iradio-blue:hover{background-position: -120px 0}\n.iradio-blue.checked{background-position: -140px 0}\n.iradio-blue.disabled{background-position: -160px 0;cursor: default}\n.iradio-blue.checked.disabled{background-position: -180px 0}\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  only screen and (-moz-min-device-pixel-ratio: 1.5),  only screen and (-o-min-device-pixel-ratio: 1.5),  only screen and (min-device-pixel-ratio: 1.5){.icheckbox-blue,.iradio-blue{background-image: url(../images/iCheck/blue@2x.png);\n\t-webkit-background-size: 200px 20px;\n\tbackground-size: 200px 20px}\n}\n/* aero */\n.icheckbox-aero,.iradio-aero{display: block;margin: 0;padding: 0;width: 18px;height: 18px;background: url(../images/iCheck/aero.png) no-repeat;border: none;cursor: pointer}\n.icheckbox-aero,.icheckbox-aero.static:hover{background-position: 0 0}\n.icheckbox-aero.hover,.icheckbox-aero:hover{background-position: -20px 0}\n.icheckbox-aero.checked{background-position: -40px 0}\n.icheckbox-aero.disabled{background-position: -60px 0;cursor: default}\n.icheckbox-aero.checked.disabled{background-position: -80px 0}\n.iradio-aero,.iradio-aero.static:hover{background-position: -100px 0}\n.iradio-aero.hover,.iradio-aero:hover{background-position: -120px 0}\n.iradio-aero.checked{background-position: -140px 0}\n.iradio-aero.disabled{background-position: -160px 0;cursor: default}\n.iradio-aero.checked.disabled{background-position: -180px 0}\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  only screen and (-moz-min-device-pixel-ratio: 1.5),  only screen and (-o-min-device-pixel-ratio: 1.5),  only screen and (min-device-pixel-ratio: 1.5){.icheckbox-aero,.iradio-aero{background-image: url(../images/iCheck/aero@2x.png);\n\t-webkit-background-size: 200px 20px;\n\tbackground-size: 200px 20px}\n}\n/* grey */\n.icheckbox-grey,.iradio-grey{display: block;margin: 0;padding: 0;width: 18px;height: 18px;background: url(../images/iCheck/grey.png) no-repeat;border: none;cursor: pointer}\n.icheckbox-grey,.icheckbox-grey.static:hover{background-position: 0 0}\n.icheckbox-grey.hover,.icheckbox-grey:hover{background-position: -20px 0}\n.icheckbox-grey.checked{background-position: -40px 0}\n.icheckbox-grey.disabled{background-position: -60px 0;cursor: default}\n.icheckbox-grey.checked.disabled{background-position: -80px 0}\n.iradio-grey,.iradio-grey.static:hover{background-position: -100px 0}\n.iradio-grey.hover,.iradio-grey:hover{background-position: -120px 0}\n.iradio-grey.checked{background-position: -140px 0}\n.iradio-grey.disabled{background-position: -160px 0;cursor: default}\n.iradio-grey.checked.disabled{background-position: -180px 0}\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  only screen and (-moz-min-device-pixel-ratio: 1.5),  only screen and (-o-min-device-pixel-ratio: 1.5),  only screen and (min-device-pixel-ratio: 1.5){.icheckbox-grey,.iradio-grey{background-image: url(../images/iCheck/grey@2x.png);\n\t-webkit-background-size: 200px 20px;\n\tbackground-size: 200px 20px}\n}\n/* orange */\n.icheckbox-orange,.iradio-orange{display: block;margin: 0;padding: 0;width: 18px;height: 18px;background: url(../images/iCheck/orange.png) no-repeat;border: none;cursor: pointer}\n.icheckbox-orange,.icheckbox-orange.static:hover{background-position: 0 0}\n.icheckbox-orange.hover,.icheckbox-orange:hover{background-position: -20px 0}\n.icheckbox-orange.checked{background-position: -40px 0}\n.icheckbox-orange.disabled{background-position: -60px 0;cursor: default}\n.icheckbox-orange.checked.disabled{background-position: -80px 0}\n.iradio-orange,.iradio-orange.static:hover{background-position: -100px 0}\n.iradio-orange.hover,.iradio-orange:hover{background-position: -120px 0}\n.iradio-orange.checked{background-position: -140px 0}\n.iradio-orange.disabled{background-position: -160px 0;cursor: default}\n.iradio-orange.checked.disabled{background-position: -180px 0}\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  only screen and (-moz-min-device-pixel-ratio: 1.5),  only screen and (-o-min-device-pixel-ratio: 1.5),  only screen and (min-device-pixel-ratio: 1.5){.icheckbox-orange,.iradio-orange{background-image: url(../images/iCheck/orange@2x.png);\n\t-webkit-background-size: 200px 20px;\n\tbackground-size: 200px 20px}\n}\n/* yellow */\n.icheckbox-yellow,.iradio-yellow{display: block;margin: 0;padding: 0;width: 18px;height: 18px;background: url(../images/iCheck/yellow.png) no-repeat;border: none;cursor: pointer}\n.icheckbox-yellow,.icheckbox-yellow.static:hover{background-position: 0 0}\n.icheckbox-yellow.hover,.icheckbox-yellow:hover{background-position: -20px 0}\n.icheckbox-yellow.checked{background-position: -40px 0}\n.icheckbox-yellow.disabled{background-position: -60px 0;cursor: default}\n.icheckbox-yellow.checked.disabled{background-position: -80px 0}\n.iradio-yellow,.iradio-yellow.static:hover{background-position: -100px 0}\n.iradio-yellow.hover,.iradio-yellow:hover{background-position: -120px 0}\n.iradio-yellow.checked{background-position: -140px 0}\n.iradio-yellow.disabled{background-position: -160px 0;cursor: default}\n.iradio-yellow.checked.disabled{background-position: -180px 0}\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  only screen and (-moz-min-device-pixel-ratio: 1.5),  only screen and (-o-min-device-pixel-ratio: 1.5),  only screen and (min-device-pixel-ratio: 1.5){.icheckbox-yellow,.iradio-yellow{background-image: url(../images/iCheck/yellow@2x.png);\n\t-webkit-background-size: 200px 20px;\n\tbackground-size: 200px 20px}\n}\n/* pink */\n.icheckbox-pink,.iradio-pink{display: block;margin: 0;padding: 0;width: 18px;height: 18px;background: url(../images/iCheck/pink.png) no-repeat;border: none;cursor: pointer}\n.icheckbox-pink,.icheckbox-pink.static:hover{background-position: 0 0}\n.icheckbox-pink.hover,.icheckbox-pink:hover{background-position: -20px 0}\n.icheckbox-pink.checked{background-position: -40px 0}\n.icheckbox-pink.disabled{background-position: -60px 0;cursor: default}\n.icheckbox-pink.checked.disabled{background-position: -80px 0}\n.iradio-pink,.iradio-pink.static:hover{background-position: -100px 0}\n.iradio-pink.hover,.iradio-pink:hover{background-position: -120px 0}\n.iradio-pink.checked{background-position: -140px 0}\n.iradio-pink.disabled{background-position: -160px 0;cursor: default}\n.iradio-pink.checked.disabled{background-position: -180px 0}\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  only screen and (-moz-min-device-pixel-ratio: 1.5),  only screen and (-o-min-device-pixel-ratio: 1.5),  only screen and (min-device-pixel-ratio: 1.5){.icheckbox-pink,.iradio-pink{background-image: url(../images/iCheck/pink@2x.png);\n\t-webkit-background-size: 200px 20px;\n\tbackground-size: 200px 20px}\n}\n/* purple */\n.icheckbox-purple,.iradio-purple{display: block;margin: 0;padding: 0;width: 18px;height: 18px;background: url(../images/iCheck/purple.png) no-repeat;border: none;cursor: pointer}\n.icheckbox-purple,.icheckbox-purple.static:hover{background-position: 0 0}\n.icheckbox-purple.hover,.icheckbox-purple:hover{background-position: -20px 0}\n.icheckbox-purple.checked{background-position: -40px 0}\n.icheckbox-purple.disabled{background-position: -60px 0;cursor: default}\n.icheckbox-purple.checked.disabled{background-position: -80px 0}\n.iradio-purple,.iradio-purple.static:hover{background-position: -100px 0}\n.iradio-purple.hover,.iradio-purple:hover{background-position: -120px 0}\n.iradio-purple.checked{background-position: -140px 0}\n.iradio-purple.disabled{background-position: -160px 0;cursor: default}\n.iradio-purple.checked.disabled{background-position: -180px 0}\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),  only screen and (-moz-min-device-pixel-ratio: 1.5),  only screen and (-o-min-device-pixel-ratio: 1.5),  only screen and (min-device-pixel-ratio: 1.5){.icheckbox-purple,.iradio-purple{background-image: url(../images/iCheck/purple@2x.png);\n\t-webkit-background-size: 200px 20px;\n\tbackground-size: 200px 20px}\n}\n\n/*3.4.2.2 Bootsrtap.Switch.css*/\n.has-switch{display:inline-block;cursor:pointer;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;border:1px solid;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);position:relative;text-align:left;overflow:hidden;line-height:8px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;min-width:100px}\n.has-switch.size-MINI{min-width:72px}\n.has-switch.size-S{min-width:80px}\n.has-switch.size-L{min-width:120px}\n.has-switch.deactivate{opacity:.5;filter:alpha(opacity=50);cursor:default!important}\n.has-switch.deactivate label,\n.has-switch.deactivate span{cursor:default!important}\n.has-switch>div{display:inline-block;width:150%;position:relative;top:0}\n.has-switch>div.switch-animate{-webkit-transition:left .5s;-moz-transition:left .5s;-o-transition:left .5s;transition:left .5s}\n.has-switch>div.switch-off{left:-50%}\n.has-switch>div.switch-on{left:0}\n.has-switch input[type=checkbox]{display:none}\n.has-switch span,.has-switch label{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;cursor:pointer;position:relative;display:inline-block;padding-bottom:4px;padding-top:4px;font-size:14px;line-height:20px}\n.has-switch span.size-MINI,.has-switch label.size-MINI{padding-bottom:4px;padding-top:4px;font-size:10px;line-height:9px}\n.has-switch span.size-S,\n.has-switch label.size-S{padding-bottom:3px;padding-top:3px;font-size:12px;line-height:18px}\n.has-switch span.size-L,.has-switch label.size-L{padding-bottom:9px;padding-top:9px;font-size:16px;line-height:normal}\n.has-switch label{text-align:center;margin-top:-1px;margin-bottom:-1px;z-index:100;width:34%;border-left:1px solid #ccc;border-right:1px solid #ccc;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#f5f5f5;\n\tbackground-image:-moz-linear-gradient(top,#fff,#e6e6e6);\n\tbackground-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));\n\tbackground-image:-webkit-linear-gradient(top,#fff,#e6e6e6);\n\tbackground-image:-o-linear-gradient(top,#fff,#e6e6e6);\n\tbackground-image:linear-gradient(to bottom,#fff,#e6e6e6);\n\tbackground-repeat:repeat-x;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);\n\tborder-color:#e6e6e6 #e6e6e6 #bfbfbf;\n\tborder-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);\n\t*background-color:#e6e6e6;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(enabled = false)\n}\n.has-switch label:hover,\n.has-switch label:focus,\n.has-switch label:active,\n.has-switch label.active,\n.has-switch label.disabled,\n.has-switch label[disabled]{color:#fff;background-color:#e6e6e6;*background-color:#d9d9d9}\n.has-switch label:active,\n.has-switch label.active{background-color:#ccc \\9}\n.has-switch label i{color:#000;text-shadow:0 1px 0 #fff;line-height:18px;pointer-events:none}\n.has-switch span{text-align:center;z-index:1;width:33%}\n.has-switch span.switch-left{\n\t-webkit-border-top-left-radius:4px;\n\t-moz-border-radius-topleft:4px;\n\tborder-top-left-radius:4px;\n\t-webkit-border-bottom-left-radius:4px;\n\t-moz-border-radius-bottomleft:4px;\n\tborder-bottom-left-radius:4px\n}\n.has-switch span.switch-right{color:#333;text-shadow:0 1px 1px rgba(255,255,255,0.75);background-color:#f0f0f0;\n\tbackground-image:-moz-linear-gradient(top,#e6e6e6,#fff);\n\tbackground-image:-webkit-gradient(linear,0 0,0 100%,from(#e6e6e6),to(#fff));\n\tbackground-image:-webkit-linear-gradient(top,#e6e6e6,#fff);\n\tbackground-image:-o-linear-gradient(top,#e6e6e6,#fff);\n\tbackground-image:linear-gradient(to bottom,#e6e6e6,#fff);\n\tbackground-repeat:repeat-x;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe6e6e6',endColorstr='#ffffffff',GradientType=0);\n\tborder-color:#fff #fff #d9d9d9;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);\n\t*background-color:#fff;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false)\n}\n.has-switch span.switch-right:hover,\n.has-switch span.switch-right:focus,\n.has-switch span.switch-right:active,\n.has-switch span.switch-right.active,\n.has-switch span.switch-right.disabled,\n.has-switch span.switch-right[disabled]{color:#333;background-color:#fff;*background-color:#f2f2f2}\n.has-switch span.switch-right:active,\n.has-switch span.switch-right.active{background-color:#e6e6e6 \\9}\n.has-switch span.switch-primary,\n.has-switch span.switch-left{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#005fcc;\n\tbackground-image:-moz-linear-gradient(top,#04c,#08c);\n\tbackground-image:-webkit-gradient(linear,0 0,0 100%,from(#04c),to(#08c));\n\tbackground-image:-webkit-linear-gradient(top,#04c,#08c);\n\tbackground-image:-o-linear-gradient(top,#04c,#08c);\n\tbackground-image:linear-gradient(to bottom,#04c,#08c);\n\tbackground-repeat:repeat-x;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0044cc',endColorstr='#ff0088cc',GradientType=0);\n\tborder-color:#08c #08c #005580;\n\tborder-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);\n\t*background-color:#08c;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(enabled = false)\n}\n.has-switch span.switch-primary:hover,\n.has-switch span.switch-left:hover,\n.has-switch span.switch-primary:focus,\n.has-switch span.switch-left:focus,\n.has-switch span.switch-primary:active,\n.has-switch span.switch-left:active,\n.has-switch span.switch-primary.active,\n.has-switch span.switch-left.active,\n.has-switch span.switch-primary.disabled,\n.has-switch span.switch-left.disabled,\n.has-switch span.switch-primary[disabled],\n.has-switch span.switch-left[disabled]{color:#fff;background-color:#08c;*background-color:#0077b3}\n.has-switch span.switch-primary:active,\n.has-switch span.switch-left:active,\n.has-switch span.switch-primary.active,\n.has-switch span.switch-left.active{background-color:#069 \\9}\n.has-switch span.switch-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#41a7c5;\n\tbackground-image:-moz-linear-gradient(top,#2f96b4,#5bc0de);\n\tbackground-image:-webkit-gradient(linear,0 0,0 100%,from(#2f96b4),to(#5bc0de));\n\tbackground-image:-webkit-linear-gradient(top,#2f96b4,#5bc0de);\n\tbackground-image:-o-linear-gradient(top,#2f96b4,#5bc0de);\n\tbackground-image:linear-gradient(to bottom,#2f96b4,#5bc0de);\n\tbackground-repeat:repeat-x;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff2f96b4',endColorstr='#ff5bc0de',GradientType=0);\n\tborder-color:#5bc0de #5bc0de #28a1c5;\n\tborder-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);\n\t*background-color:#5bc0de;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(enabled = false)\n}\n.has-switch span.switch-info:hover,\n.has-switch span.switch-info:focus,\n.has-switch span.switch-info:active,\n.has-switch span.switch-info.active,\n.has-switch span.switch-info.disabled,\n.has-switch span.switch-info[disabled]{color:#fff;background-color:#5bc0de;*background-color:#46b8da}\n.has-switch span.switch-info:active,\n.has-switch span.switch-info.active{background-color:#31b0d5 \\9}\n.has-switch span.switch-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#58b058;\n\tbackground-image:-moz-linear-gradient(top,#51a351,#62c462);\n\tbackground-image:-webkit-gradient(linear,0 0,0 100%,from(#51a351),to(#62c462));\n\tbackground-image:-webkit-linear-gradient(top,#51a351,#62c462);\n\tbackground-image:-o-linear-gradient(top,#51a351,#62c462);\n\tbackground-image:linear-gradient(to bottom,#51a351,#62c462);\n\tbackground-repeat:repeat-x;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff51a351',endColorstr='#ff62c462',GradientType=0);\n\tborder-color:#62c462 #62c462 #3b9e3b;\n\tborder-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);\n\t*background-color:#62c462;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(enabled = false)\n}\n.has-switch span.switch-success:hover,\n.has-switch span.switch-success:focus,\n.has-switch span.switch-success:active,\n.has-switch span.switch-success.active,\n.has-switch span.switch-success.disabled,\n.has-switch span.switch-success[disabled]{color:#fff;background-color:#62c462;*background-color:#4fbd4f}\n.has-switch span.switch-success:active,\n.has-switch span.switch-success.active{background-color:#42b142 \\9}\n.has-switch span.switch-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#f9a123;\n\tbackground-image:-moz-linear-gradient(top,#f89406,#fbb450);\n\tbackground-image:-webkit-gradient(linear,0 0,0 100%,from(#f89406),to(#fbb450));\n\tbackground-image:-webkit-linear-gradient(top,#f89406,#fbb450);\n\tbackground-image:-o-linear-gradient(top,#f89406,#fbb450);\n\tbackground-image:linear-gradient(to bottom,#f89406,#fbb450);\n\tbackground-repeat:repeat-x;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff89406',endColorstr='#fffbb450',GradientType=0);\n\tborder-color:#fbb450 #fbb450 #f89406;\n\tborder-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);\n\t*background-color:#fbb450;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(enabled = false)\n}\n.has-switch span.switch-warning:hover,\n.has-switch span.switch-warning:focus,\n.has-switch span.switch-warning:active,\n.has-switch span.switch-warning.active,\n.has-switch span.switch-warning.disabled,\n.has-switch span.switch-warning[disabled]{color:#fff;background-color:#fbb450;*background-color:#faa937}\n.has-switch span.switch-warning:active,\n.has-switch span.switch-warning.active{background-color:#fa9f1e \\9}\n.has-switch span.switch-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#d14641;\n\tbackground-image:-moz-linear-gradient(top,#bd362f,#ee5f5b);\n\tbackground-image:-webkit-gradient(linear,0 0,0 100%,from(#bd362f),to(#ee5f5b));\n\tbackground-image:-webkit-linear-gradient(top,#bd362f,#ee5f5b);\n\tbackground-image:-o-linear-gradient(top,#bd362f,#ee5f5b);\n\tbackground-image:linear-gradient(to bottom,#bd362f,#ee5f5b);\n\tbackground-repeat:repeat-x;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffbd362f',endColorstr='#ffee5f5b',GradientType=0);\n\tborder-color:#ee5f5b #ee5f5b #e51d18;\n\tborder-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);\n\t*background-color:#ee5f5b;\n\tfilter:progid:DXImageTransform.Microsoft.gradient(enabled = false)\n}\n.has-switch span.switch-danger:hover,\n.has-switch span.switch-danger:focus,\n.has-switch span.switch-danger:active,\n.has-switch span.switch-danger.active,\n.has-switch span.switch-danger.disabled,\n.has-switch span.switch-danger[disabled]{color:#fff;background-color:#ee5f5b;*background-color:#ec4844}\n.has-switch span.switch-danger:active,\n.has-switch span.switch-danger.active{background-color:#e9322d \\9}\n\n/*3.4.3 select 下拉框\n<span class=\"select-box\">\n  <select class=\"select\" size=\"1\" name=\"mapper\">\n    <option value=\"1\" selected>默认</option>\n    <option value=\"2\">菜单二</option>\n    <option value=\"3\">菜单三</option>\n  </select>\n</span>\n\tExplain:\n\tselect 是表单元素中最难美化的一个，有两种美化方式：\n\t\t1、修改源生的，修改有限，只能修改个边框，背景，字体。优点：程序方便操作；缺点：丑，浏览器之间存在很大差异。\n\t\t2、将源生的隐藏掉，用其他元素（如div li）通过js模拟下拉交互，然后再传值给源生的select。优点：好看，兼容好；缺点：代码冗余，依赖JS，不方便操作\n*/\n/*方法一、修改源生*/\n.select-box{border:solid 1px #ddd;box-sizing:border-box;vertical-align:middle; width:100%; display:inline-block}\n\t.select{border:solid 1px #ddd;box-sizing:border-box;cursor: pointer;line-height:normal;font-weight: normal;width:100%; white-space:nowrap}\n.select-box .select{ border:none}\n.select-box.inline,\n.select-box.inline .select{ width:auto}\n\n.select-box,\n.select-box.size-M{padding:4px 5px}\n\t.select,.size-M .select{font-size: 14px}\n\n.select-box.size-MINI{padding:0px 5px}\n\t.size-MINI .select{font-size: 12px}\n\n.select-box.size-S{padding:3px 5px}\n\t.size-S .select{font-size: 12px}\n\n.select-box.size-L{padding:8px 5px}\n\t.size-L .select{font-size: 16px}\n\n.select-box.size-XL{padding:10px 5px}\n\t.size-XL .select{font-size: 18px}\n\n@media (max-width: 767px) {\n\t.responsive .select-box{ border:none}\n\t.responsive .select-box .select,\n\t.responsive .select{border:solid 1px #ddd; padding:10px;font-size:16px}\n\t.responsive .select-box,\n\t.responsive .select-box.size-M,\n\t.responsive .select-box.size-MINI,\n\t.responsive .select-box.size-S,\n\t.responsive .select-box.size-L,\n\t.responsive .select-box.size-XL{ height:auto; padding:0}\n}\n\n/*方法二、JS模拟\n<select name=\"mapper\" data-enabled=\"false\">\n  <option value=\"1\" selected>默认</option>\n  <option value=\"2\">菜单二</option>\n  <option value=\"3\">菜单三</option>\n</select>\n需要引用2个js文件\n<script type=\"text/javascript\" src=\"lib/squid.js\"></script>\n<script type=\"text/javascript\" src=\"lib/jselect-1.0.js\"></script>\n页面调用方法\n<script type=\"text/javascript\">\nsquid.swing.jselect()\n</script>\n*/\n.select-wrapper {position:relative; display:inline-block;font-size:14px;cursor:default}\n.select-default{zoom: 1;display:block; padding-left:10px; padding-right:30px;background-color:#fff;border:solid 1px #d0d0d0;height:34px;line-height:34px}\n.jsselect.radius{ overflow:visible}\n.jsselect.radius .select-default{ border-radius:4px}\n.jsselect.radius .select-list{border-radius:4px;border-top-left-radius:0;border-top-right-radius:0}\n.select-icon {position: absolute;height:8px;width:12px;right:10px;top:50%; margin-top:-4px;background: url(../images/jselect/iconpic-arrow-down2.png) no-repeat center}\n.unselectable {\n\t-moz-user-select: none;\n\t-khtml-user-select: none;\n\t-webkit-user-select: none;\n\t-o-user-select: none;\n\tuser-select: none}\n\t.select-list {position:absolute;left:0; right:0;top:100%;z-index:1;line-height:34px;max-height:320px; overflow:auto;background-color:#fff;background-clip: padding-box;\n\t_height:expression(this.scrollHeight > 319 ? \"320px\" : \"auto\");\n\t-moz-box-shadow:0 1px 2px rgba(0, 1, 1, 0.2);\n\t-webkit-box-shadow:0 1px 2px rgba(0, 1, 1, 0.2);\n\tbox-shadow:0 1px 2px rgba(0, 1, 1, 0.2);\n\tbox-sizing:border-box;\n\n\tborder:solid 1px #d0d0d0}\n\t\t.select-item {margin: 0;padding: 0}\n\t\t.select-option {background:#fff;line-height:34px;text-align:left;white-space:nowrap; cursor:pointer; border-bottom:1px solid #f2f2f2; padding:0 10px}\n\t\t.select-item .selected {background-color:#148cf1;color:#fff}\n\n/*3.4.4 input-file 文件上传\n\tExample:\n<span class=\"btn-upload\">\n  <a style=\"z-index:2;\" href=\"javascript:void();\" class=\"btn btn-primary radius\"><i class=\"iconfont\">&#xf0020;</i> 浏览文件<input type=\"file\" multiple name=\"file_0\" class=\"input-file\"></a>\n</span>\n\tExplain：把文件选择域设为透明,通过绝对定位覆盖在长的好看的按钮上面。\n*/\n.btn-upload{position: relative; display:inline-block;height:31px; *display:inline;overflow:hidden;vertical-align:middle;cursor:pointer}\n\t.upload-url{cursor: pointer; width:300px}\n\t.input-file{position:absolute; right:0; top:0; cursor: pointer; z-index:1; font-size:30em;opacity:0;filter: alpha(opacity=0)}\n.form-group .upload-btn{ margin-left:-1px}\n.btn-upload .icon-add,.btn-upload .icon-minus{cursor: pointer;display: inline-block;font-family: Arial;font-size: 30px;height: 31px;line-height: 31px;text-align: center;vertical-align: middle;width: 36px}\n@media (max-width: 767px) {\n\t.upload-btn{ display:none}\n\t.upload-url{ display:none}\n}\n\n/*数字表单*/\n.numberControlBox{display:inline-block;overflow:hidden;vertical-align: middle}\n.ncb-up,.ncb-down{font-size:0px;display:block;height:10px;background-color:#f4f4f4;background:-moz-linear-gradient(top,rgb(255,255,255) 0%,rgb(230,230,230) 50%,rgb(255,255,255) 100%);width:24px;border:1px solid #d1d1d1;cursor:pointer}\n.ncb-up{margin-bottom:1px}\n.numberControlBox .ncb_ico{display:block;height:10px;background-image:url(../images/iconpic-arrow.png);background-repeat:no-repeat}\n.ncb-up .ncb_ico{background-position: -22px center}\n.ncb-down .ncb_ico{background-position: 1px center}\n.ncb_btn_hover{border:1px solid #9dc7e7;background-color:#dff2fc;background:-moz-linear-gradient(top,rgb(255,255,255) 0%,rgb(210,237,250) 50%,rgb(255,255,255) 100%)}\n.ncb_btn_selected{border:1px solid #6198c2;background-color:#aee1fb;background:-moz-linear-gradient(top,rgb(255,255,255) 0%,rgb(174,225,251) 50%,rgb(255,255,255) 100%)}\n.input-text[type=\"number\"]{width:80px}\n\n/*3.4.5 spinner 控件*/\n.spinner{display:block;overflow:hidden;width:100px; position:relative; padding-left:29px; padding-right:29px;}\n.spinner .input-text{height:30px; text-align:center; width:100%}\n.spinner a{display:inline-block; position:absolute;top:0; bottom:0; height:28px;line-height:28px;width:28px;cursor:pointer;outline:0; text-decoration:none;text-align:center;font-size:16px;border:1px solid #ddd;background-color:#f7f7f7;}\n.spinner a:hover{ text-decoration:none}\n.spinner a i{ font-style:normal;}\n.spinner a.subtract{ left:0}\n.spinner a.add{ right:0}\n.spinner a.add.disabled,\n.spinner a.subtract.disabled{ color:#999; cursor:not-allowed}\n\n\n/*3.4.6 邮箱提示*/\n.emailSug-wrapper {position: absolute;background: #fff;text-align: left;z-index: 99}\n.emailSug-wrapper .emailSug-list .emailSug-item {font-size: 14px;height: 25px;line-height: 25px;padding-left: 10px;color: #333}\n.emailSug-wrapper .emailSug-list .emailSug-item.active {background: #5a98de;cursor: pointer;color: #fff}\n\n/*3.4.7 表单布局*/\nlabel,.placeholder{font-size:14px}\n.form legend{font-size:20px}/*表单名称*/\n.form .row{margin-top:15px}/*表单行*/\n\t.form-label{display:block; color:#555}/*表单标题*/\n\t.formControls{position:relative}/*表单控制区*/\n\t.formControls > *{vertical-align:middle}\n\t.placeholder{position:absolute; left:4px; top:4px;color:#c6c6c6; cursor:text}/*表单默认值*/\n.form-horizontal .form-label{margin-top:3px;cursor:text;text-align:right}\n.form-horizontal .Validform_checktip{ margin-top:5px}\n/*设置placeholder颜色*/\n::-webkit-input-placeholder {color:#b3b3b3}/* WebKit browsers */\n:-moz-placeholder {color:#b3b3b3}/* Mozilla Firefox 4 to 18 */\n::-moz-placeholder {color:#b3b3b3}/* Mozilla Firefox 19+ */\n:-ms-input-placeholder {color:#b3b3b3}/* Internet Explorer 10+ */\n.placeholder{color:#adb0be; position:absolute; z-index:9}/*不兼容placeholder属性的浏览器，可使用<span class=\"placeholder\">表单默认值</span>*/\n@media (max-width: 767px) {\n\t.form-horizontal .form-label{ text-align:left}\n}\n/*3.4.8 表单验证*/\n/*文本框的错误状态*/\n.Validform_error,input.error,select.error,textarea.error{background-color:#fbe2e2; border-color:#c66161; color:#c00}\n.Validform_wrong,.Validform_right,.Validform_warning{display:inline-block;height:20px;font-size:12px;vertical-align:middle; padding-left:25px}\n/*错误*/\n.Validform_wrong{background:url(../images/validform/iconpic-error.png) no-repeat 0 center;color:#ef392b}\n/*正确*/\n.Validform_right{background:url(../images/validform/iconpic-right.png) no-repeat 0 center}\n/*警告*/\n.Validform_warning{background:url(../images/validform/iconpic-warning.png) no-repeat 0 center;color:#777}\nlabel.error{ position: absolute; right: 18px; top: 5px;color:#ef392b; font-size: 12px}\n.check-box label.error,\n.radio-box label.error{ right:auto; width:150px; left:210px;top:-2px}\n/*密码等级*/\n.passwordStrength b{font-weight:400}\n.passwordStrength b,.passwordStrength span{display:inline-block; vertical-align:middle;line-height:16px;line-height:18px\\9;height:16px}\n.passwordStrength span{width:57px;text-align:center;background-color:#d0d0d0;\tborder-right:1px solid #fff}\n.passwordStrength .last{border-right:none}\n.passwordStrength .bgStrength{color:#fff;background-color:#fcc900}\n/*Validform对话框*/\n#Validform_msg{font-size:14px;width:300px; -webkit-box-shadow:2px 2px 3px #aaa; -moz-box-shadow:2px 2px 3px #aaa; background:#fff; position:absolute; top:0px; right:50px; z-index:99999; display:none;filter: progid:DXImageTransform.Microsoft.Shadow(Strength=3, Direction=135, Color='#999999'); box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.1)}\n#Validform_msg .iframe{position:absolute; left:0px; top:-1px; z-index:-1}\n#Validform_msg .Validform_title{font-size:20px; padding:10px;text-align:left;color:#fff; position:relative; background-color:#fcc900}\n#Validform_msg a.Validform_close:link,#Validform_msg a.Validform_close:visited{position:absolute; right:8px; top:6px; color:#fff; text-decoration:none; font-family:Verdana}\n#Validform_msg a.Validform_close:hover{color:#fff}\n#Validform_msg .Validform_info{padding:10px;border:1px solid #bbb; border-top:none; text-align:left}\n@media (max-width: 767px) {\n\t.responsive .Validform_checktip{margin-top:10px}\n}\n\n/*3.5 按钮\n\tName:\t\t\tstyle_button\n\tExample:\t\t<button class=\"btn radius radius btn-primary|btn-info|btn-success|btn-warning|btn-danger|btn-inverse|btn-link\" type=\"button\">按钮</button>\n\tExplain:\t\tbtn-primary：主要|btn-info：信息|btn-success：成功|btn-warning：警告|btn-danger：危险|btn-inverse：反向|btn-link：链接\n\n*/\n/*关闭*/\n.close{font-size:20px;color: #000;text-shadow: 0 1px 0 #fff;opacity: 0.2;filter: alpha(opacity=20)}\n.close:hover,.close:focus{color: #000;text-decoration: none;cursor: pointer;opacity: 0.4;filter: alpha(opacity=40)}\n\nbutton.close{padding:0;cursor:pointer;background:transparent;border: 0;-webkit-appearance: none}\n/*按钮*/\n.btn{display:inline-block;box-sizing:border-box;cursor:pointer;text-align:center;font-weight:400;white-space:nowrap;vertical-align: middle;-moz-padding-start:npx; -moz-padding-end:npx;border:solid 1px #ddd; background-color:#fff; width:auto;*zoom:1;*overflow:visible;\n\t-webkit-transition:background-color .1s linear;\n\t\t-moz-transition:background-color .1s linear;\n\t\t-o-transition:background-color .1s linear;\n\t\t\ttransition:background-color .1s linear}\na.btn:hover,a.btn:focus,a.btn:active,a.btn.active,a.btn.disabled,a.btn[disabled]{text-decoration:none}\n.btn:active,.btn.active{background-color:#ccc}\n.btn:first-child{*margin-left:0}\n.btn.active,.btn:active{-moz-box-shadow:0 1px 8px rgba(0, 0, 0, 0.125) inset;-webkit-box-shadow:0 1px 8px rgba(0, 0, 0, 0.125) inset; box-shadow:0 1px 8px rgba(0, 0, 0, 0.125) inset}\n\n/*默认——灰色\t通常用于取消*/\n.btn-default{background-color:#e6e6e6;border-color:#e6e6e6}\n.btn-default:hover,\n.btn-default:focus,\n.btn-default:active,\n.btn-default.active{color:#333;background-color:#c7c7c7;border-color:#c7c7c7}\n\n/*主要——主色\t通常用于确定、提交、购买、支付等*/\n.btn-primary{color:#fff;background-color:#5a98de; border-color:#5a98de}\n.btn-primary:hover,\n.btn-primary:focus,\n.btn-primary:active,\n.btn-primary.active{color:#fff;background-color:#0a6999;border-color:#0a6999}\n\n/*次要按钮*/\n.btn-secondary{color:#fff;background-color:#3bb4f2; border-color:#3bb4f2}\n.btn-secondary:hover,\n.btn-secondary:focus,\n.btn-secondary:active,\n.btn-secondary.active{color:#fff;background-color:#0f9ae0;border-color:#0f9ae0}\n\n/*成功*/\n.btn-success{color:#fff;background-color:#5eb95e; border-color:#5eb95e}\n.btn-success:hover,\n.btn-success:focus,\n.btn-success:active,\n.btn-success.active{color:#fff;background-color:#429842;border-color:#429842}\n\n/*警告*/\n.btn-warning{color:#fff;background-color:#f37b1d; border-color:#f37b1d}\n.btn-warning:hover,\n.btn-warning:focus,\n.btn-warning:active,\n.btn-warning.active{color:#fff;background-color:#c85e0b;border-color:#c85e0b}\n\n/*危险*/\n.btn-danger{color:#fff;background-color:#dd514c; border-color:#dd514c}\n.btn-danger:hover,\n.btn-danger:focus,\n.btn-danger:active,\n.btn-danger.active{color:#fff;background-color:#c62b26;border-color:#c62b26}\n\n/*链接*/\n.btn-link{color:#0e90d2;cursor:pointer;border-color:transparent;background-color:transparent}\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active,\n.btn-link.active{color:#095f8a;text-decoration:underline;background-color:transparent}\n\n/*块级按钮*/\n.btn-block {-moz-box-sizing: border-box;display: block;padding-left: 0;padding-right: 0;width: 100%}\n/* Outline buttons */\n.btn-default-outline{background-color:transparent;border-color:#e6e6e6}\n.btn-default-outline:hover,\n.btn-default-outline:focus,\n.btn-default-outline:active,\n.btn-default-outline.active{color:#333;background-color:transparent;border-color:#c7c7c7}\n\n.btn-primary-outline{color:#5a98de;background-color:transparent; border-color:#5a98de}\n.btn-primary-outline:hover,\n.btn-primary-outline:focus,\n.btn-primary-outline:active,\n.btn-primary-outline.active{color:#0a6999;background-color:transparent;border-color:#0a6999}\n\n.btn-secondary-outline{color:#3bb4f2;background-color:transparent;background-image:none;border-color:#3bb4f2}\n.btn-secondary-outline.active,.btn-secondary-outline.focus,.btn-secondary-outline:active,.btn-secondary-outline:focus,.open>.btn-secondary-outline.dropdown-toggle{color:#fff;background-color:#3bb4f2;border-color:#3bb4f2}\n.btn-secondary-outline:hover{color:#fff;background-color:#3bb4f2;border-color:#3bb4f2}\n.btn-secondary-outline.disabled.focus,.btn-secondary-outline.disabled:focus,.btn-secondary-outline:disabled.focus,.btn-secondary-outline:disabled:focus,fieldset[disabled] .btn-secondary-outline.focus,fieldset[disabled] .btn-secondary-outline:focus{border-color:#0f9ae0}\n\n.btn-success-outline{color:#5eb95e;background-color:transparent;background-image:none;border-color:#5eb95e}\n.btn-success-outline.active,.btn-success-outline.focus,.btn-success-outline:active,.btn-success-outline:focus,.open>.btn-success-outline.dropdown-toggle{color:#fff;background-color:#5eb95e;border-color:#5eb95e}\n.btn-success-outline:hover{color:#fff;background-color:#5eb95e;border-color:#5eb95e}\n.btn-success-outline.disabled.focus,.btn-success-outline.disabled:focus,.btn-success-outline:disabled.focus,.btn-success-outline:disabled:focus,fieldset[disabled] .btn-success-outline.focus,fieldset[disabled] .btn-success-outline:focus{border-color:#429842}\n\n.btn-warning-outline{color:#f37b1d;background-color:transparent;background-image:none;border-color:#f37b1d}\n.btn-warning-outline.active,.btn-warning-outline.focus,.btn-warning-outline:active,.btn-warning-outline:focus,.open>.btn-warning-outline.dropdown-toggle{color:#fff;background-color:#f37b1d;border-color:#f37b1d}\n.btn-warning-outline:hover{color:#fff;background-color:#f37b1d;border-color:#f37b1d}\n.btn-warning-outline.disabled.focus,.btn-warning-outline.disabled:focus,.btn-success-outline:disabled.focus,.btn-warning-outline:disabled:focus,fieldset[disabled] .btn-warning-outline.focus,fieldset[disabled] .btn-warning-outline:focus{border-color:#c85e0b}\n\n.btn-danger-outline{color:#dd514c;background-color:transparent;background-image:none;border-color:#dd514c}\n.btn-danger-outline.active,.btn-danger-outline.focus,.btn-danger-outline:active,.btn-danger-outline:focus,.open>.btn-danger-outline.dropdown-toggle{color:#fff;background-color:#dd514c;border-color:#dd514c}\n.btn-danger-outline:hover{color:#fff;background-color:#dd514c;border-color:#dd514c}\n.btn-danger-outline.disabled.focus,.btn-danger-outline.disabled:focus,.btn-success-outline:disabled.focus,.btn-danger-outline:disabled:focus,fieldset[disabled] .btn-danger-outline.focus,fieldset[disabled] .btn-danger-outline:focus{border-color:#c62b26}\n\n/*禁用状态*/\n.btn.disabled{cursor:not-allowed;background-image:none;opacity:.65;filter:alpha(opacity=65);box-shadow:none; pointer-events:none}\n\n/*表单组*/\n.form-group{ display:inline-block;vertical-align:middle}\n.form-group .input-text{ position:relative; vertical-align:top}\n.form-group.radius{ overflow: hidden}\n.form-group.radius .input-text{border-radius:4px 0 0 4px}\n.form-group.round .input-text{border-radius:1000px 0 0 1000px}\n.form-group .btn{position:relative;margin-left:-1px}\n.form-group.radius .btn{ border-radius:0 4px 4px 0}\n.form-group.round .btn{ border-radius:0 1000px 1000px 0}\n\n/*3.6 图片*/\n/*3.6.1 图片效果\n<img src=\"\" class=\"img-responsive|radius|round|thumbnail\" />\nimg-responsive 响应式    .radius 圆角图片    .round 圆形图片   .thumbnail 缩略图\n*/\n.img-responsive{display:inline-block;max-width:100%;height:auto}\n.thumbnail{display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;max-width:100%;height:auto;padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #ddd;-webkit-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}\n@media (max-width: 767px) {\n\t.img-responsive{width:100%}\n}\n.duang-opacity img{-webkit-transition:opacity .1s linear;-moz-transition:opacity .1s linear;-o-transition:opacity .1s linear;transition:opacity .1s linear}\n.duang-opacity a:hover img,a:hover .opacity img{opacity:0.85;filter: alpha(opacity=85)}\n/*3.6.2 图集效果\n\tName:\t\t\tmodal_album\n\tExample:\n<div class=\"album-item\" style=\"width:160px\">\n\t<div class=\"album-img\">\n\t\t<img src=\"\" style=\"height: 160px;\">\n\t</div>\n\t<div class=\"album-title\">《仙剑奇侠传》赵灵儿<span class=\"c-999\">(20张)</span></div>\n\t<div class=\"album-bg\">\n\t\t<div class=\"album-bg-Fir\"></div>\n\t\t<div class=\"album-bg-Sec\"></div>\n\t</div>\n</div>*/\n.album-item{}\n\t.album-img{ border:1px solid #e0e0e0}\n\t.album-img img{ display:block; width: 100%}\n\t.album-title{display:block;text-align:left;padding:7px 5px;line-height:18px;color:#555;text-decoration:none;font-size:12px;border:solid 1px #e0e0e0;border-top:0}\n\t.album-bg-Fir,.album-bg-Sec{border:1px solid #e6e6e6;border-top:1px solid #f5f5f5;height:1px;margin:0 auto;overflow:hidden}\n\t.album-bg-Fir{ margin:0 3px}\n\t.album-bg-Sec{ margin:0 6px}\n\n/*3.6.3 头像\n\tName:\t\t\tmod_avatar\n\tExample:\t\t<i class=\"avatar avatar-L radius\"><img src=\"static/h-ui/images/ucenter/avatar-default.jpg\"></i>\n*/\n.avatar{display:inline-block;position:relative; overflow:hidden}\n.avatar img{ display:block}\n.avatar.radius,.avatar.radius img{border-radius:50%}\n.avatar,.avatar img{width:32px; height:32px}\n.avatar.size-MINI{ width:16px;height:16px}\n.avatar.size-S,.avatar.size-S img{width:24px; height:24px}\n.avatar.size-M,.avatar.size-M img{width:32px; height:32px}/*默认为中，可以不写，可以理解为：均码*/\n.avatar.size-L,.avatar.size-L img{width:48px; height:48px}\n.avatar.size-XL,.avatar.size-XL img{width:64px; height:64px}\n.avatar.size-XXL,.avatar.size-XXL img{width:100px; height:100px}\n.avatar.size-XXXL,.avatar.size-XXXL img{width:128px; height:128px}\n\n/*3.7 图标\nH-ui采用Font Awesome 3.2.1的整套图标，因为是图标字体，所以可以像控制字体那样随心所欲改变这些图标的颜色、大小、阴影以及任何CSS能控制的属性\n*/\n.iconpic{display:inline-block; vertical-align:sub;*vertical-align:middle;_vertical-align:middle; width:16px; height:16px; background-position:center; background-repeat:no-repeat}\n/*3.8 效果\n\tName:\t\t\tstyle_animation\n\tExample:\t\t<input class=\"btn hui-animation\" val=\"淡入\" type=\"button\" data-tra=\"hui-fadein\" />\n*/\n/* duang 加特效 */\n.hui-bounce,.hui-flip,.hui-flash,.hui-shake,.hui-swing,.hui-wobble,.hui-ring{-webkit-animation:1s ease;-moz-animation:1s ease;-ms-animation:1s ease;animation:1s ease}\n.hui-fadein,.hui-fadeinT,.hui-fadeinR,.hui-fadeinB,.hui-fadeinL,.hui-bouncein,.hui-bounceinT,.hui-bounceinR,.hui-bounceinB,.hui-bounceinL,.hui-rotatein,.hui-rotateinLT,.hui-rotateinLB,.hui-rotateinRT,.hui-rotateinRB,.hui-flipin,.hui-flipinX,.hui-flipinY{-webkit-animation:1s ease-out backwards;-moz-animation:1s ease-out backwards;-ms-animation:1s ease-out backwards;animation:1s ease-out backwards}\n.hui-fadeout,.hui-fadeoutT,.hui-fadeoutR,.hui-fadeoutB,.hui-fadeoutL,.hui-bounceout,.hui-bounceoutT,.hui-bounceoutR,.hui-bounceoutB,.hui-bounceoutL,.hui-rotateout,.hui-rotateoutLT,.hui-rotateoutLB,.hui-rotateoutRT,.hui-rotateoutRB,.hui-flipout,.hui-flipoutX,.hui-flipoutY{-webkit-animation:1s ease-in forwards;-moz-animation:1s ease-in forwards;-ms-animation:1s ease-in forwards;animation:1s ease-in forwards}\n\n/* 淡入 */\n.hui-fadein{-webkit-animation-name:fadein;-moz-animation-name:fadein;-ms-animation-name:fadein;animation-name:fadein}\n/* 淡入-从上 */\n.hui-fadeinT{-webkit-animation-name:fadeinT;-moz-animation-name:fadeinT;-ms-animation-name:fadeinT;animation-name:fadeinT}\n/* 淡入-从右 */\n.hui-fadeinR{-webkit-animation-name:fadeinR;-moz-animation-name:fadeinR;-ms-animation-name:fadeinR;animation-name:fadeinR}\n/* 淡入-从下 */\n.hui-fadeinB{-webkit-animation-name:fadeinB;-moz-animation-name:fadeinB;-ms-animation-name:fadeinB;animation-name:fadeinB}\n/* 淡入-从左 */\n.hui-fadeinL{-webkit-animation-name:fadeinL;-moz-animation-name:fadeinL;-ms-animation-name:fadeinL;animation-name:fadeinL}\n/* 淡出 */\n.hui-fadeout{-webkit-animation-name:fadeout;-moz-animation-name:fadeout;-ms-animation-name:fadeout;animation-name:fadeout}\n\n/* 淡出-向上 */\n.hui-fadeoutT{-webkit-animation-name:fadeoutT;-moz-animation-name:fadeoutT;-ms-animation-name:fadeoutT;animation-name:fadeoutT}\n/* 淡出-向右 */\n.hui-fadeoutR{-webkit-animation-name:fadeoutR;-moz-animation-name:fadeoutR;-ms-animation-name:fadeoutR;animation-name:fadeoutR}\n/* 淡出-向下 */\n.hui-fadeoutB{-webkit-animation-name:fadeoutB;-moz-animation-name:fadeoutB;-ms-animation-name:fadeoutB;animation-name:fadeoutB}\n/* 淡出-向左 */\n.hui-fadeoutL{-webkit-animation-name:fadeoutL;-moz-animation-name:fadeoutL;-ms-animation-name:fadeoutL;animation-name:fadeoutL}\n\n/* 弹跳 */\n.hui-bounce{-webkit-animation-name:bounce;-moz-animation-name:bounce;-ms-animation-name:bounce;animation-name:bounce}\n\n/* 弹入 */\n.hui-bouncein{-webkit-animation-name:bouncein;-moz-animation-name:bouncein;-ms-animation-name:bouncein;animation-name:bouncein}\n/* 弹入-从上 */\n.hui-bounceinT{-webkit-animation-name:bounceinT;-moz-animation-name:bounceinT;-ms-animation-name:bounceinT;animation-name:bounceinT}\n/* 弹入-从右 */\n.hui-bounceinR{-webkit-animation-name:bounceinR;-moz-animation-name:bounceinR;-ms-animation-name:bounceinR;animation-name:bounceinR}\n/* 弹入-从下 */\n.hui-bounceinB{-webkit-animation-name:bounceinB;-moz-animation-name:bounceinB;-ms-animation-name:bounceinB;animation-name:bounceinB}\n/* 弹入-从左 */\n.hui-bounceinL{-webkit-animation-name:bounceinL;-moz-animation-name:bounceinL;-ms-animation-name:bounceinL;animation-name:bounceinL}\n\n/* 弹出 */\n.hui-bounceout{-webkit-animation-name:bounceout;-moz-animation-name:bounceout;-ms-animation-name:bounceout;animation-name:bounceout}\n/* 弹出-向上 */\n.hui-bounceoutT{-webkit-animation-name:bounceoutT;-moz-animation-name:bounceoutT;-ms-animation-name:bounceoutT;animation-name:bounceoutT}\n/* 弹出-向右 */\n.hui-bounceoutR{-webkit-animation-name:bounceoutR;-moz-animation-name:bounceoutR;-ms-animation-name:bounceoutR;animation-name:bounceoutR}\n/* 弹出-向下 */\n.hui-bounceoutB{-webkit-animation-name:bounceoutB;-moz-animation-name:bounceoutB;-ms-animation-name:bounceoutB;animation-name:bounceoutB}\n/* 弹出-向左 */\n.hui-bounceoutL{-webkit-animation-name:bounceoutL;-moz-animation-name:bounceoutL;-ms-animation-name:bounceoutL;animation-name:bounceoutL}\n\n/* 转入 */\n.hui-rotatein{-webkit-animation-name:rotatein;-moz-animation-name:rotatein;-ms-animation-name:rotatein;animation-name:rotatein}\n/* 转入-从左上 */\n.hui-rotateinLT{-webkit-animation-name:rotateinLT;-moz-animation-name:rotateinLT;-ms-animation-name:rotateinLT;animation-name:rotateinLT}\n/* 转入-从左下 */\n.hui-rotateinLB{-webkit-animation-name:rotateinLB;-moz-animation-name:rotateinLB;-ms-animation-name:rotateinLB;animation-name:rotateinLB}\n/* 转入-从右上 */\n.hui-rotateinRT{-webkit-animation-name:rotateinRT;-moz-animation-name:rotateinRT;-ms-animation-name:rotateinRT;animation-name:rotateinRT}\n/* 转入-从右下*/\n.hui-rotateinRB{-webkit-animation-name:rotateinRB;-moz-animation-name:rotateinRB;-ms-animation-name:rotateinRB;animation-name:rotateinRB}\n\n/* 转出 */\n.hui-rotateout{-webkit-animation-name:rotateout;-moz-animation-name:rotateout;-ms-animation-name:rotateout;animation-name:rotateout}\n/* 转出-向左上 */\n.hui-rotateoutLT{-webkit-animation-name:rotateoutLT;-moz-animation-name:rotateoutLT;-ms-animation-name:rotateoutLT;animation-name:rotateoutLT}\n/* 转出-向左下 */\n.hui-rotateoutLB{-webkit-animation-name:rotateoutLB;-moz-animation-name:rotateoutLB;-ms-animation-name:rotateoutLB;animation-name:rotateoutLB}\n/* 转出-向右上 */\n.hui-rotateoutRT{-webkit-animation-name:rotateoutRT;-moz-animation-name:rotateoutRT;-ms-animation-name:rotateoutRT;animation-name:rotateoutRT}\n/* 转出-向右下 */\n.hui-rotateoutRB{-webkit-animation-name:rotateoutRB;-moz-animation-name:rotateoutRB;-ms-animation-name:rotateoutRB;animation-name:rotateoutRB}\n\n/* 翻转 */\n.hui-flip{-webkit-animation-name:flip;-moz-animation-name:flip;-ms-animation-name:flip;animation-name:flip}\n/* 翻入-X轴 */\n.hui-flipinX{-webkit-animation-name:flipinX;-moz-animation-name:flipinX;-ms-animation-name:flipinX;animation-name:flipinX}\n/* 翻入-Y轴 */\n.hui-flipin,.hui-flipinY{-webkit-animation-name:flipinY;-moz-animation-name:flipinY;-ms-animation-name:flipinY;animation-name:flipinY}\n/* 翻出-X轴 */\n.hui-flipoutX{-webkit-animation-name:flipoutX;-moz-animation-name:flipoutX;-ms-animation-name:flipoutX;animation-name:flipoutX}\n/* 翻出-Y轴 */\n.hui-flipout,.hui-flipoutY{-webkit-animation-name:flipoutY;-moz-animation-name:flipoutY;-ms-animation-name:flipoutY;animation-name:flipoutY}\n\n/* 闪烁 */\n.hui-flash{-webkit-animation-name:flash;-moz-animation-name:flash;-ms-animation-name:flash;animation-name:flash}\n/* 震颤 */\n.hui-shake{-webkit-animation-name:shake;-moz-animation-name:shake;-ms-animation-name:shake;animation-name:shake}\n/* 摇摆 */\n.hui-swing{-webkit-animation-name:swing;-moz-animation-name:swing;-ms-animation-name:swing;animation-name:swing}\n/* 摇晃 */\n.hui-wobble{-webkit-animation-name:wobble;-moz-animation-name:wobble;-ms-animation-name:wobble;animation-name:wobble}\n/* 震铃 */\n.hui-ring{-webkit-animation-name:ring;-moz-animation-name:ring;-ms-animation-name:ring;animation-name:ring}\n/* define */\n/* 淡入 */\n@-webkit-keyframes fadein{\n    0%{opacity:0}\n    100%{opacity:1}\n}\n@-moz-keyframes fadein{\n    0%{opacity:0}\n    100%{opacity:1}\n}\n@-ms-keyframes fadein{\n    0%{opacity:0}\n    100%{opacity:1}\n}\n@keyframes fadein{\n    0%{opacity:0}\n    100%{opacity:1}\n}\n/* 淡入-从上 */\n@-webkit-keyframes fadeinT{\n    0%{opacity:0;-webkit-transform:translateY(-100px)}\n    100%{opacity:1;-webkit-transform:translateY(0)}\n}\n@-moz-keyframes fadeinT{\n    0%{opacity:0;-moz-transform:translateY(-100px)}\n    100%{opacity:1;-moz-transform:translateY(0)}\n}\n@-ms-keyframes fadeinT{\n    0%{opacity:0;-ms-transform:translateY(-100px)}\n    100%{opacity:1;-ms-transform:translateY(0)}\n}\n@keyframes fadeinT{\n    0%{opacity:0;transform:translateY(-100px)}\n    100%{opacity:1;transform:translateY(0)}\n}\n/* 淡入-从右 */\n@-webkit-keyframes fadeinR{\n    0%{opacity:0;-webkit-transform:translateX(100px)}\n    100%{opacity:1;-webkit-transform:translateX(0)}\n}\n@-moz-keyframes fadeinR{\n    0%{opacity:0;-moz-transform:translateX(100px)}\n    100%{opacity:1;-moz-transform:translateX(0)}\n}\n@-ms-keyframes fadeinR{\n    0%{opacity:0;-ms-transform:translateX(100px)}\n    100%{opacity:1;-ms-transform:translateX(0)}\n}\n@keyframes fadeinR{\n    0%{opacity:0;transform:translateX(100px)}\n    100%{opacity:1;transform:translateX(0)}\n}\n/* 淡入-从下 */\n@-webkit-keyframes fadeinB{\n    0%{opacity:0;-webkit-transform:translateY(100px)}\n    100%{opacity:1;-webkit-transform:translateY(0)}\n}\n@-moz-keyframes fadeinB{\n    0%{opacity:0;-moz-transform:translateY(100px)}\n    100%{opacity:1;-moz-transform:translateY(0)}\n}\n@-ms-keyframes fadeinB{\n    0%{opacity:0;-ms-transform:translateY(100px)}\n    100%{opacity:1;-ms-transform:translateY(0)}\n}\n@keyframes fadeinB{\n    0%{opacity:0;transform:translateY(100px)}\n    100%{opacity:1;transform:translateY(0)}\n}\n/* 淡入-从左 */\n@-webkit-keyframes fadeinL{\n    0%{opacity:0;-webkit-transform:translateX(-100px)}\n    100%{opacity:1;-webkit-transform:translateX(0)}\n}\n@-moz-keyframes fadeinL{\n    0%{opacity:0;-moz-transform:translateX(-100px)}\n    100%{opacity:1;-moz-transform:translateX(0)}\n}\n@-ms-keyframes fadeinL{\n    0%{opacity:0;-ms-transform:translateX(-100px)}\n    100%{opacity:1;-ms-transform:translateX(0)}\n}\n@keyframes fadeinL{\n    0%{opacity:0;transform:translateX(-100px)}\n    100%{opacity:1;transform:translateX(0)}\n}\n/* 淡出 */\n@-webkit-keyframes fadeout{\n    0%{opacity:1}\n    100%{opacity:0}\n}\n@-moz-keyframes fadeout{\n    0%{opacity:1}\n    100%{opacity:0}\n}\n@-ms-keyframes fadeout{\n    0%{opacity:1}\n    100%{opacity:0}\n}\n@keyframes fadeout{\n    0%{opacity:1}\n    100%{opacity:0}\n}\n/* 淡出-向上 */\n@-webkit-keyframes fadeoutT{\n    0%{opacity:1;-webkit-transform:translateY(0)}\n    100%{opacity:0;-webkit-transform:translateY(-100px)}\n}\n@-moz-keyframes fadeoutT{\n    0%{opacity:1;-moz-transform:translateY(0)}\n    100%{opacity:0;-moz-transform:translateY(-100px)}\n}\n@-ms-keyframes fadeoutT{\n    0%{opacity:1;-ms-transform:translateY(0)}\n    100%{opacity:0;-ms-transform:translateY(-100px)}\n}\n@keyframes fadeoutT{\n    0%{opacity:1;transform:translateY(0)}\n    100%{opacity:0;transform:translateY(-100px)}\n}\n/* 淡出-向右 */\n@-webkit-keyframes fadeoutR{\n    0%{opacity:1;-webkit-transform:translateX(0)}\n    100%{opacity:0;-webkit-transform:translateX(100px)}\n}\n@-moz-keyframes fadeoutR{\n    0%{opacity:1;-moz-transform:translateX(0)}\n    100%{opacity:0;-moz-transform:translateX(100px)}\n}\n@-ms-keyframes fadeoutR{\n    0%{opacity:1;-ms-transform:translateX(0)}\n    100%{opacity:0;-ms-transform:translateX(100px)}\n}\n@keyframes fadeoutR{\n    0%{opacity:1;transform:translateX(0)}\n    100%{opacity:0;transform:translateX(100px)}\n}\n/* 淡出-向下 */\n@-webkit-keyframes fadeoutB{\n    0%{opacity:1;-webkit-transform:translateY(0)}\n    100%{opacity:0;-webkit-transform:translateY(100px)}\n}\n@-moz-keyframes fadeoutB{\n    0%{opacity:1;-moz-transform:translateY(0)}\n    100%{opacity:0;-moz-transform:translateY(100px)}\n}\n@-ms-keyframes fadeoutB{\n    0%{opacity:1;-ms-transform:translateY(0)}\n    100%{opacity:0;-ms-transform:translateY(100px)}\n}\n@keyframes fadeoutB{\n    0%{opacity:1;transform:translateY(0)}\n    100%{opacity:0;transform:translateY(100px)}\n}\n/* 淡出-向左 */\n@-webkit-keyframes fadeoutL{\n    0%{opacity:1;-webkit-transform:translateX(0)}\n    100%{opacity:0;-webkit-transform:translateX(-100px)}\n}\n@-moz-keyframes fadeoutL{\n    0%{opacity:1;-moz-transform:translateX(0)}\n    100%{opacity:0;-moz-transform:translateX(-100px)}\n}\n@-ms-keyframes fadeoutL{\n    0%{opacity:1;-ms-transform:translateX(0)}\n    100%{opacity:0;-ms-transform:translateX(-100px)}\n}\n@keyframes fadeoutL{\n    0%{opacity:1;transform:translateX(0)}\n    100%{opacity:0;transform:translateX(-100px)}\n}\n/* 弹跳 */\n@-webkit-keyframes bounce{\n    0%,20%,50%,80%,100%{-webkit-transform:translateY(0)}\n    40%{-webkit-transform:translateY(-30px)}\n    60%{-webkit-transform:translateY(-15px)}\n}\n@-moz-keyframes bounce{\n    0%,20%,50%,80%,100%{-moz-transform:translateY(0)}\n    40%{-moz-transform:translateY(-30px)}\n    60%{-moz-transform:translateY(-15px)}\n}\n@-ms-keyframes bounce{\n    0%,20%,50%,80%,100%{-ms-transform:translateY(0)}\n    40%{-ms-transform:translateY(-30px)}\n    60%{-ms-transform:translateY(-15px)}\n}\n@keyframes bounce{\n    0%,20%,50%,80%,100%{transform:translateY(0)}\n    40%{transform:translateY(-30px)}\n    60%{transform:translateY(-15px)}\n}\n/* 弹入 */\n@-webkit-keyframes bouncein{\n    0%{opacity:0;-webkit-transform:scale(0.3)}\n    50%{opacity:1;-webkit-transform:scale(1.05)}\n    70%{-webkit-transform:scale(0.9)}\n    100%{-webkit-transform:scale(1)}\n}\n@-moz-keyframes bouncein{\n    0%{opacity:0;-moz-transform:scale(0.3)}\n    50%{opacity:1;-moz-transform:scale(1.05)}\n    70%{-moz-transform:scale(0.9)}\n    100%{-moz-transform:scale(1)}\n}\n@-ms-keyframes bouncein{\n    0%{opacity:0;-ms-transform:scale(0.3)}\n    50%{opacity:1;-ms-transform:scale(1.05)}\n    70%{-ms-transform:scale(0.9)}\n    100%{-ms-transform:scale(1)}\n}\n@keyframes bouncein{\n    0%{opacity:0;transform:scale(0.3)}\n    50%{opacity:1;transform:scale(1.05)}\n    70%{transform:scale(0.9)}\n    100%{transform:scale(1)}\n}\n/* 弹入-从上 */\n@-webkit-keyframes bounceinT{\n    0%{opacity:0;-webkit-transform:translateY(-100px)}\n    60%{opacity:1;-webkit-transform:translateY(30px)}\n    80%{-webkit-transform:translateY(-10px)}\n    100%{-webkit-transform:translateY(0)}\n}\n@-moz-keyframes bounceinT{\n    0%{opacity:0;-moz-transform:translateY(-100px)}\n    60%{opacity:1;-moz-transform:translateY(30px)}\n    80%{-moz-transform:translateY(-10px)}\n    100%{-moz-transform:translateY(0)}\n}\n@-ms-keyframes bounceinT{\n    0%{opacity:0;-ms-transform:translateY(-100px)}\n    60%{opacity:1;-ms-transform:translateY(30px)}\n    80%{-ms-transform:translateY(-10px)}\n    100%{-ms-transform:translateY(0)}\n}\n@keyframes bounceinT{\n    0%{opacity:0;transform:translateY(-100px)}\n    60%{opacity:1;transform:translateY(30px)}\n    80%{transform:translateY(-10px)}\n    100%{transform:translateY(0)}\n}\n/* 弹入-从右 */\n@-webkit-keyframes bounceinR{\n    0%{opacity:0;-webkit-transform:translateX(100px)}\n    60%{opacity:1;-webkit-transform:translateX(-30px)}\n    80%{-webkit-transform:translateX(10px)}\n    100%{-webkit-transform:translateX(0)}\n}\n@-moz-keyframes bounceinR{\n    0%{opacity:0;-moz-transform:translateX(100px)}\n    60%{opacity:1;-moz-transform:translateX(-30px)}\n    80%{-moz-transform:translateX(10px)}\n    100%{-moz-transform:translateX(0)}\n}\n@-ms-keyframes bounceinR{\n    0%{opacity:0;-ms-transform:translateX(100px)}\n    60%{opacity:1;-ms-transform:translateX(-30px)}\n    80%{-ms-transform:translateX(10px)}\n    100%{-ms-transform:translateX(0)}\n}\n@keyframes bounceinR{\n    0%{opacity:0;transform:translateX(100px)}\n    60%{opacity:1;transform:translateX(-30px)}\n    80%{transform:translateX(10px)}\n    100%{transform:translateX(0)}\n}\n/* 弹入-从下 */\n@-webkit-keyframes bounceinB{\n    0%{opacity:0;-webkit-transform:translateY(100px)}\n    60%{opacity:1;-webkit-transform:translateY(-30px)}\n    80%{-webkit-transform:translateY(10px)}\n    100%{-webkit-transform:translateY(0)}\n}\n@-moz-keyframes bounceinB{\n    0%{opacity:0;-moz-transform:translateY(100px)}\n    60%{opacity:1;-moz-transform:translateY(-30px)}\n    80%{-moz-transform:translateY(10px)}\n    100%{-moz-transform:translateY(0)}\n}\n@-ms-keyframes bounceinB{\n    0%{opacity:0;-ms-transform:translateY(100px)}\n    60%{opacity:1;-ms-transform:translateY(-30px)}\n    80%{-ms-transform:translateY(10px)}\n    100%{-ms-transform:translateY(0)}\n}\n@keyframes bounceinB{\n    0%{opacity:0;transform:translateY(100px)}\n    60%{opacity:1;transform:translateY(-30px)}\n    80%{transform:translateY(10px)}\n    100%{transform:translateY(0)}\n}\n/* 弹入-从左 */\n@-webkit-keyframes bounceinL{\n    0%{opacity:0;-webkit-transform:translateX(-100px)}\n    60%{opacity:1;-webkit-transform:translateX(30px)}\n    80%{-webkit-transform:translateX(-10px)}\n    100%{-webkit-transform:translateX(0)}\n}\n@-moz-keyframes bounceinL{\n    0%{opacity:0;-moz-transform:translateX(-100px)}\n    60%{opacity:1;-moz-transform:translateX(30px)}\n    80%{-moz-transform:translateX(-10px)}\n    100%{-moz-transform:translateX(0)}\n}\n@-ms-keyframes bounceinL{\n    0%{opacity:0;-ms-transform:translateX(-100px)}\n    60%{opacity:1;-ms-transform:translateX(30px)}\n    80%{-ms-transform:translateX(-10px)}\n    100%{-ms-transform:translateX(0)}\n}\n@keyframes bounceinL{\n    0%{opacity:0;transform:translateX(-100px)}\n    60%{opacity:1;transform:translateX(30px)}\n    80%{transform:translateX(-10px)}\n    100%{transform:translateX(0)}\n}\n/* 弹出 */\n@-webkit-keyframes bounceout{\n    0%{-webkit-transform:scale(1)}\n    25%{-webkit-transform:scale(0.95)}\n    50%{opacity:1;-webkit-transform:scale(1.1)}\n    100%{opacity:0;-webkit-transform:scale(0.3)}\n}\n@-moz-keyframes bounceout{\n    0%{-moz-transform:scale(1)}\n    25%{-moz-transform:scale(0.95)}\n    50%{opacity:1;-moz-transform:scale(1.1)}\n    100%{opacity:0;-moz-transform:scale(0.3)}\n}\n@-ms-keyframes bounceout{\n    0%{-ms-transform:scale(1)}\n    25%{-ms-transform:scale(0.95)}\n    50%{opacity:1;-ms-transform:scale(1.1)}\n    100%{opacity:0;-ms-transform:scale(0.3)}\n}\n@keyframes bounceout{\n    0%{transform:scale(1)}\n    25%{transform:scale(0.95)}\n    50%{opacity:1;transform:scale(1.1)}\n    100%{opacity:0;transform:scale(0.3)}\n}\n/* 弹出-向上*/\n@-webkit-keyframes bounceoutT{\n    0%{-webkit-transform:translateY(0)}\n    20%{opacity:1;-webkit-transform:translateY(20px)}\n    100%{opacity:0;-webkit-transform:translateY(-100px)}\n}\n@-moz-keyframes bounceoutT{\n    0%{-moz-transform:translateY(0)}\n    20%{opacity:1;-moz-transform:translateY(20px)}\n    100%{opacity:0;-moz-transform:translateY(-100px)}\n}\n@-ms-keyframes bounceoutT{\n    0%{-ms-transform:translateY(0)}\n    20%{opacity:1;-ms-transform:translateY(20px)}\n    100%{opacity:0;-ms-transform:translateY(-100px)}\n}\n@keyframes bounceoutT{\n    0%{transform:translateY(0)}\n    20%{opacity:1;transform:translateY(20px)}\n    100%{opacity:0;transform:translateY(-100px)}\n}\n/* 弹出-向右*/\n@-webkit-keyframes bounceoutR{\n    0%{-webkit-transform:translateX(0)}\n    20%{opacity:1;-webkit-transform:translateX(-20px)}\n    100%{opacity:0;-webkit-transform:translateX(100px)}\n}\n@-moz-keyframes bounceoutR{\n    0%{-moz-transform:translateX(0)}\n    20%{opacity:1;-moz-transform:translateX(-20px)}\n    100%{opacity:0;-moz-transform:translateX(100px)}\n}\n@-ms-keyframes bounceoutR{\n    0%{-ms-transform:translateX(0)}\n    20%{opacity:1;-ms-transform:translateX(-20px)}\n    100%{opacity:0;-ms-transform:translateX(100px)}\n}\n@keyframes bounceoutR{\n    0%{transform:translateX(0)}\n    20%{opacity:1;transform:translateX(-20px)}\n    100%{opacity:0;transform:translateX(100px)}\n}\n/* 弹出-向下 */\n@-webkit-keyframes bounceoutB{\n    0%{-webkit-transform:translateY(0)}\n    20%{opacity:1;-webkit-transform:translateY(-20px)}\n    100%{opacity:0;-webkit-transform:translateY(100px)}\n}\n@-moz-keyframes bounceoutB{\n    0%{-moz-transform:translateY(0)}\n    20%{opacity:1;-moz-transform:translateY(-20px)}\n    100%{opacity:0;-moz-transform:translateY(100px)}\n}\n@-ms-keyframes bounceoutB{\n    0%{-ms-transform:translateY(0)}\n    20%{opacity:1;-ms-transform:translateY(-20px)}\n    100%{opacity:0;-ms-transform:translateY(100px)}\n}\n@keyframes bounceoutB{\n    0%{transform:translateY(0)}\n    20%{opacity:1;transform:translateY(-20px)}\n    100%{opacity:0;transform:translateY(100px)}\n}\n/* 弹出-向左 */\n@-webkit-keyframes bounceoutL{\n    0%{-webkit-transform:translateX(0)}\n    20%{opacity:1;-webkit-transform:translateX(20px)}\n    100%{opacity:0;-webkit-transform:translateX(-100px)}\n}\n@-moz-keyframes bounceoutL{\n    0%{-moz-transform:translateX(0)}\n    20%{opacity:1;-moz-transform:translateX(20px)}\n    100%{opacity:0;-moz-transform:translateX(-100px)}\n}\n@-ms-keyframes bounceoutL{\n    0%{-ms-transform:translateX(0)}\n    20%{opacity:1;-ms-transform:translateX(20px)}\n    100%{opacity:0;-ms-transform:translateX(-100px)}\n}\n@keyframes bounceoutL{\n    0%{transform:translateX(0)}\n    20%{opacity:1;transform:translateX(20px)}\n    100%{opacity:0;transform:translateX(-200px)}\n}\n/* 转入 */\n@-webkit-keyframes rotatein{\n    0%{opacity:0;-webkit-transform:rotate(-200deg)}\n    100%{opacity:1;-webkit-transform:rotate(0)}\n}\n@-moz-keyframes rotatein{\n    0%{opacity:0;-moz-transform:rotate(-200deg)}\n    100%{opacity:1;-moz-transform:rotate(0)}\n}\n@-ms-keyframes rotatein{\n    0%{opacity:0;-ms-transform:rotate(-200deg)}\n    100%{opacity:1;-ms-transform:rotate(0)}\n}\n@keyframes rotatein{\n    0%{opacity:0;transform:rotate(-200deg)}\n    100%{opacity:1;transform:rotate(0)}\n}\n/* 转入-从左上 */\n@-webkit-keyframes rotateinLT{\n    0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(-90deg);opacity:0}\n    100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}\n}\n@-moz-keyframes rotateinLT{\n    0%{-moz-transform-origin:left bottom;-moz-transform:rotate(-90deg);opacity:0}\n    100%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}\n}\n@-ms-keyframes rotateinLT{\n    0%{-ms-transform-origin:left bottom;-ms-transform:rotate(-90deg);opacity:0}\n    100%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}\n}\n@keyframes rotateinLT{\n    0%{transform-origin:left bottom;transform:rotate(-90deg);opacity:0}\n    100%{transform-origin:left bottom;transform:rotate(0);opacity:1}\n}\n/* 转入-从左下 */\n@-webkit-keyframes rotateineftB{\n    0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(90deg);opacity:0}\n    100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}\n}\n@-moz-keyframes rotateineftB{\n    0%{-moz-transform-origin:left bottom;-moz-transform:rotate(90deg);opacity:0}\n    100%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}\n}\n@-ms-keyframes rotateineftB{\n    0%{-ms-transform-origin:left bottom;-ms-transform:rotate(90deg);opacity:0}\n    100%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}\n}\n@keyframes rotateineftB{\n    0%{transform-origin:left bottom;transform:rotate(90deg);opacity:0}\n    100%{transform-origin:left bottom;transform:rotate(0);opacity:1}\n}\n/* 转入-从右上 */\n@-webkit-keyframes rotateinRT{\n    0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(90deg);opacity:0}\n    100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}\n}\n@-moz-keyframes rotateinRT{\n    0%{-moz-transform-origin:right bottom;-moz-transform:rotate(90deg);opacity:0}\n    100%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}\n}\n@-ms-keyframes rotateinRT{\n    0%{-ms-transform-origin:right bottom;-ms-transform:rotate(90deg);opacity:0}\n    100%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}\n}\n@keyframes rotateinRT{\n    0%{transform-origin:right bottom;transform:rotate(90deg);opacity:0}\n    100%{transform-origin:right bottom;transform:rotate(0);opacity:1}\n}\n/* 转入-从右下*/\n@-webkit-keyframes rotateinRB{\n    0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(-90deg);opacity:0}\n    100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}\n}\n@-moz-keyframes rotateinRB{\n    0%{-moz-transform-origin:right bottom;-moz-transform:rotate(-90deg);opacity:0}\n    100%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}\n}\n@-ms-keyframes rotateinRB{\n    0%{-ms-transform-origin:right bottom;-ms-transform:rotate(-90deg);opacity:0}\n    100%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}\n}\n@keyframes rotateinRB{\n    0%{transform-origin:right bottom;transform:rotate(-90deg);opacity:0}\n    100%{transform-origin:right bottom;transform:rotate(0);opacity:1}\n}\n/* 转出 */\n@-webkit-keyframes rotateout{\n    0%{-webkit-transform-origin:center center;-webkit-transform:rotate(0);opacity:1}\n    100%{-webkit-transform-origin:center center;-webkit-transform:rotate(200deg);opacity:0}\n}\n@-moz-keyframes rotateout{\n    0%{-moz-transform-origin:center center;-moz-transform:rotate(0);opacity:1}\n    100%{-moz-transform-origin:center center;-moz-transform:rotate(200deg);opacity:0}\n}\n@-ms-keyframes rotateout{\n    0%{-ms-transform-origin:center center;-ms-transform:rotate(0);opacity:1}\n    100%{-ms-transform-origin:center center;-ms-transform:rotate(200deg);opacity:0}\n}\n@keyframes rotateout{\n    0%{transform-origin:center center;transform:rotate(0);opacity:1}\n    100%{transform-origin:center center;transform:rotate(200deg);opacity:0}\n}\n/* 转出-向左上 */\n@-webkit-keyframes rotateoutLT{\n    0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}\n    100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(-90deg);opacity:0}\n}\n@-moz-keyframes rotateoutLT{\n    0%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}\n    100%{-moz-transform-origin:left bottom;-moz-transform:rotate(-90deg);opacity:0}\n}\n@-ms-keyframes rotateoutLT{\n    0%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}\n    100%{-ms-transform-origin:left bottom;-ms-transform:rotate(-90deg);opacity:0}\n}\n@keyframes rotateoutLT{\n    0%{transform-origin:left bottom;transform:rotate(0);opacity:1}\n    100%{transform-origin:left bottom;transform:rotate(-90deg);opacity:0}\n}\n/* 转出-向左下 */\n@-webkit-keyframes rotateoutLB{\n    0%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(0);opacity:1}\n    100%{-webkit-transform-origin:left bottom;-webkit-transform:rotate(90deg);opacity:0}\n}\n@-moz-keyframes rotateoutLB{\n    0%{-moz-transform-origin:left bottom;-moz-transform:rotate(0);opacity:1}\n    100%{-moz-transform-origin:left bottom;-moz-transform:rotate(90deg);opacity:0}\n}\n@-ms-keyframes rotateoutLB{\n    0%{-ms-transform-origin:left bottom;-ms-transform:rotate(0);opacity:1}\n    100%{-ms-transform-origin:left bottom;-ms-transform:rotate(90deg);opacity:0}\n}\n@keyframes rotateoutLB{\n    0%{transform-origin:left bottom;transform:rotate(0);opacity:1}\n    100%{transform-origin:left bottom;transform:rotate(90deg);opacity:0}\n}\n/* 转出-向右上 */\n@-webkit-keyframes rotateoutRT{\n    0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}\n    100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(90deg);opacity:0}\n}\n@-moz-keyframes rotateoutRT{\n    0%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}\n    100%{-moz-transform-origin:right bottom;-moz-transform:rotate(90deg);opacity:0}\n}\n@-ms-keyframes rotateoutRT{\n    0%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}\n    100%{-ms-transform-origin:right bottom;-ms-transform:rotate(90deg);opacity:0}\n}\n@keyframes rotateoutRT{\n    0%{transform-origin:right bottom;transform:rotate(0);opacity:1}\n    100%{transform-origin:right bottom;transform:rotate(90deg);opacity:0}\n}\n/* 转出-向右下 */\n@-webkit-keyframes rotateoutBR{\n    0%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(0);opacity:1}\n    100%{-webkit-transform-origin:right bottom;-webkit-transform:rotate(-90deg);opacity:0}\n}\n@-moz-keyframes rotateoutBR{\n    0%{-moz-transform-origin:right bottom;-moz-transform:rotate(0);opacity:1}\n    100%{-moz-transform-origin:right bottom;-moz-transform:rotate(-90deg);opacity:0}\n}\n@-ms-keyframes rotateoutBR{\n    0%{-ms-transform-origin:right bottom;-ms-transform:rotate(0);opacity:1}\n    100%{-ms-transform-origin:right bottom;-ms-transform:rotate(-90deg);opacity:0}\n}\n@keyframes rotateoutBR{\n    0%{transform-origin:right bottom;transform:rotate(0);opacity:1}\n    100%{transform-origin:right bottom;transform:rotate(-90deg);opacity:0}\n}\n/* 翻转 */\n@-webkit-keyframes flip{\n    0%{-webkit-transform:perspective(400px) rotateY(0);-webkit-animation-timing-function:ease-out}\n    40%{-webkit-transform:perspective(400px) translateZ(150px) rotateY(170deg);-webkit-animation-timing-function:ease-out}\n    50%{-webkit-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-webkit-animation-timing-function:ease-in}\n    80%{-webkit-transform:perspective(400px) rotateY(360deg) scale(0.95);-webkit-animation-timing-function:ease-in}\n    100%{-webkit-transform:perspective(400px) scale(1);-webkit-animation-timing-function:ease-in}\n}\n@-moz-keyframes flip{\n    0%{-moz-transform:perspective(400px) rotateY(0);-moz-animation-timing-function:ease-out}\n    40%{-moz-transform:perspective(400px) translateZ(150px) rotateY(170deg);-moz-animation-timing-function:ease-out}\n    50%{-moz-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-moz-animation-timing-function:ease-in}\n    80%{-moz-transform:perspective(400px) rotateY(360deg) scale(0.95);-moz-animation-timing-function:ease-in}\n    100%{-moz-transform:perspective(400px) scale(1);-moz-animation-timing-function:ease-in}\n}\n@-ms-keyframes flip{\n    0%{-ms-transform:perspective(400px) rotateY(0);-ms-animation-timing-function:ease-out}\n    40%{-ms-transform:perspective(400px) translateZ(150px) rotateY(170deg);-ms-animation-timing-function:ease-out}\n    50%{-ms-transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);-ms-animation-timing-function:ease-in}\n    80%{-ms-transform:perspective(400px) rotateY(360deg) scale(0.95);-ms-animation-timing-function:ease-in}\n    100%{-ms-transform:perspective(400px) scale(1);-ms-animation-timing-function:ease-in}\n}\n@keyframes flip{\n    0%{transform:perspective(400px) rotateY(0);animation-timing-function:ease-out}\n    40%{transform:perspective(400px) translateZ(150px) rotateY(170deg);animation-timing-function:ease-out}\n    50%{transform:perspective(400px) translateZ(150px) rotateY(190deg) scale(1);animation-timing-function:ease-in}\n    80%{transform:perspective(400px) rotateY(360deg) scale(0.95);animation-timing-function:ease-in}\n    100%{transform:perspective(400px) scale(1);animation-timing-function:ease-in}\n}\n/* 翻入-X轴 */\n@-webkit-keyframes flipinX{\n    0%{-webkit-transform:perspective(400px) rotateX(90deg);opacity:0}\n    40%{-webkit-transform:perspective(400px) rotateX(-10deg)}\n    70%{-webkit-transform:perspective(400px) rotateX(10deg)}\n    100%{-webkit-transform:perspective(400px) rotateX(0);opacity:1}\n}\n@-moz-keyframes flipinX{\n    0%{-moz-transform:perspective(400px) rotateX(90deg);opacity:0}\n    40%{-moz-transform:perspective(400px) rotateX(-10deg)}\n    70%{-moz-transform:perspective(400px) rotateX(10deg)}\n    100%{-moz-transform:perspective(400px) rotateX(0);opacity:1}\n}\n@-ms-keyframes flipinX{\n    0%{-ms-transform:perspective(400px) rotateX(90deg);opacity:0}\n    40%{-ms-transform:perspective(400px) rotateX(-10deg)}\n    70%{-ms-transform:perspective(400px) rotateX(10deg)}\n    100%{-ms-transform:perspective(400px) rotateX(0);opacity:1}\n}\n@keyframes flipinX{\n    0%{transform:perspective(400px) rotateX(90deg);opacity:0}\n    40%{transform:perspective(400px) rotateX(-10deg)}\n    70%{transform:perspective(400px) rotateX(10deg)}\n    100%{transform:perspective(400px) rotateX(0);opacity:1}\n}\n/* 翻入-Y轴 */\n@-webkit-keyframes flipinY{\n    0%{-webkit-transform:perspective(400px) rotateY(90deg);opacity:0}\n    40%{-webkit-transform:perspective(400px) rotateY(-10deg)}\n    70%{-webkit-transform:perspective(400px) rotateY(10deg)}\n    100%{-webkit-transform:perspective(400px) rotateY(0);opacity:1}\n}\n@-moz-keyframes flipinY{\n    0%{-moz-transform:perspective(400px) rotateY(90deg);opacity:0}\n    40%{-moz-transform:perspective(400px) rotateY(-10deg)}\n    70%{-moz-transform:perspective(400px) rotateY(10deg)}\n    100%{-moz-transform:perspective(400px) rotateY(0);opacity:1}\n}\n@-ms-keyframes flipinY{\n    0%{-ms-transform:perspective(400px) rotateY(90deg);opacity:0}\n    40%{-ms-transform:perspective(400px) rotateY(-10deg)}\n    70%{-ms-transform:perspective(400px) rotateY(10deg)}\n    100%{-ms-transform:perspective(400px) rotateY(0);opacity:1}\n}\n@keyframes flipinY{\n    0%{transform:perspective(400px) rotateY(90deg);opacity:0}\n    40%{transform:perspective(400px) rotateY(-10deg)}\n    70%{transform:perspective(400px) rotateY(10deg)}\n    100%{transform:perspective(400px) rotateY(0);opacity:1}\n}\n/* 翻出-X轴 */\n@-webkit-keyframes flipoutX{\n    0%{-webkit-transform:perspective(400px) rotateX(0);opacity:1}\n    100%{-webkit-transform:perspective(400px) rotateX(90deg);opacity:0}\n}\n@-moz-keyframes flipoutX{\n    0%{-moz-transform:perspective(400px) rotateX(0);opacity:1}\n    100%{-moz-transform:perspective(400px) rotateX(90deg);opacity:0}\n}\n@-ms-keyframes flipoutX{\n    0%{-ms-transform:perspective(400px) rotateX(0);opacity:1}\n    100%{-ms-transform:perspective(400px) rotateX(90deg);opacity:0}\n}\n@keyframes flipoutX{\n    0%{transform:perspective(400px) rotateX(0);opacity:1}\n    100%{transform:perspective(400px) rotateX(90deg);opacity:0}\n}\n/* 翻出-Y轴 */\n@-webkit-keyframes flipoutY{\n    0%{-webkit-transform:perspective(400px) rotateY(0);opacity:1}\n    100%{-webkit-transform:perspective(400px) rotateY(90deg);opacity:0}\n}\n@-moz-keyframes flipoutY{\n    0%{-moz-transform:perspective(400px) rotateY(0);opacity:1}\n    100%{-moz-transform:perspective(400px) rotateY(90deg);opacity:0}\n}\n@-ms-keyframes flipoutY{\n    0%{-ms-transform:perspective(400px) rotateY(0);opacity:1}\n    100%{-ms-transform:perspective(400px) rotateY(90deg);opacity:0}\n}\n@keyframes flipoutY{\n    0%{transform:perspective(400px) rotateY(0);opacity:1}\n    100%{transform:perspective(400px) rotateY(90deg);opacity:0}\n}\n/* 闪烁 */\n@-webkit-keyframes flash{\n    0%,50%,100%{opacity:1}\n    25%,75%{opacity:0}\n}\n@-moz-keyframes flash{\n    0%,50%,100%{opacity:1}\n    25%,75%{opacity:0}\n}\n@-ms-keyframes flash{\n    0%,50%,100%{opacity:1}\n    25%,75%{opacity:0}\n}\n@keyframes flash{\n    0%,50%,100%{opacity:1}\n    25%,75%{opacity:0}\n}\n/* 震颤 */\n@-webkit-keyframes shake{\n    0%,100%{-webkit-transform:translateX(0)}\n    10%,30%,50%,70%,90%{-webkit-transform:translateX(-10px)}\n    20%,40%,60%,80%{-webkit-transform:translateX(10px)}\n}\n@-moz-keyframes shake{\n    0%,100%{-moz-transform:translateX(0)}\n    10%,30%,50%,70%,90%{-moz-transform:translateX(-10px)}\n    20%,40%,60%,80%{-moz-transform:translateX(10px)}\n}\n@-ms-keyframes shake{\n    0%,100%{-ms-transform:translateX(0)}\n    10%,30%,50%,70%,90%{-ms-transform:translateX(-10px)}\n    20%,40%,60%,80%{-ms-transform:translateX(10px)}\n}\n@keyframes shake{\n    0%,100%{transform:translateX(0)}\n    10%,30%,50%,70%,90%{transform:translateX(-10px)}\n    20%,40%,60%,80%{transform:translateX(10px)}\n}\n/* 摇摆 */\n@-webkit-keyframes swing{\n    20%{-webkit-transform:rotate(15deg)}\n    40%{-webkit-transform:rotate(-10deg)}\n    60%{-webkit-transform:rotate(5deg)}\n    80%{-webkit-transform:rotate(-5deg)}\n    100%{-webkit-transform:rotate(0)}\n}\n@-moz-keyframes swing{\n    20%{-moz-transform:rotate(15deg)}\n    40%{-moz-transform:rotate(-10deg)}\n    60%{-moz-transform:rotate(5deg)}\n    80%{-moz-transform:rotate(-5deg)}\n    100%{-moz-transform:rotate(0)}\n}\n@-ms-keyframes swing{\n    20%{-ms-transform:rotate(15deg)}\n    40%{-ms-transform:rotate(-10deg)}\n    60%{-ms-transform:rotate(5deg)}\n    80%{-ms-transform:rotate(-5deg)}\n    100%{-ms-transform:rotate(0)}\n}\n@keyframes swing{\n    20%{transform:rotate(15deg)}\n    40%{transform:rotate(-10deg)}\n    60%{transform:rotate(5deg)}\n    80%{transform:rotate(-5deg)}\n    100%{transform:rotate(0)}\n}\n/* 摇晃 */\n@-webkit-keyframes wobble{\n    0%{-webkit-transform:translateX(0)}\n    15%{-webkit-transform:translateX(-100px) rotate(-5deg)}\n    30%{-webkit-transform:translateX(80px) rotate(3deg)}\n    45%{-webkit-transform:translateX(-65px) rotate(-3deg)}\n    60%{-webkit-transform:translateX(40px) rotate(2deg)}\n    75%{-webkit-transform:translateX(-20px) rotate(-1deg)}\n    100%{-webkit-transform:translateX(0)}\n}\n@-moz-keyframes wobble{\n    0%{-moz-transform:translateX(0)}\n    15%{-moz-transform:translateX(-100px) rotate(-5deg)}\n    30%{-moz-transform:translateX(80px) rotate(3deg)}\n    45%{-moz-transform:translateX(-65px) rotate(-3deg)}\n    60%{-moz-transform:translateX(40px) rotate(2deg)}\n    75%{-moz-transform:translateX(-20px) rotate(-1deg)}\n    100%{-moz-transform:translateX(0)}\n}\n@-ms-keyframes wobble{\n    0%{-ms-transform:translateX(0)}\n    15%{-ms-transform:translateX(-100px) rotate(-5deg)}\n    30%{-ms-transform:translateX(80px) rotate(3deg)}\n    45%{-ms-transform:translateX(-65px) rotate(-3deg)}\n    60%{-ms-transform:translateX(40px) rotate(2deg)}\n    75%{-ms-transform:translateX(-20px) rotate(-1deg)}\n    100%{-ms-transform:translateX(0)}\n}\n@keyframes wobble{\n    0%{transform:translateX(0)}\n    15%{transform:translateX(-100px) rotate(-5deg)}\n    30%{transform:translateX(80px) rotate(3deg)}\n    45%{transform:translateX(-65px) rotate(-3deg)}\n    60%{transform:translateX(40px) rotate(2deg)}\n    75%{transform:translateX(-20px) rotate(-1deg)}\n    100%{transform:translateX(0)}\n}\n/* 震铃 */\n@-webkit-keyframes ring{\n    0%{-webkit-transform:scale(1)}\n    10%,20%{-webkit-transform:scale(0.9) rotate(-3deg)}\n    30%,50%,70%,90%{-webkit-transform:scale(1.1) rotate(3deg)}\n    40%,60%,80%{-webkit-transform:scale(1.1) rotate(-3deg)}\n    100%{-webkit-transform:scale(1) rotate(0)}\n}\n@-moz-keyframes ring{\n    0%{-moz-transform:scale(1)}\n    10%,20%{-moz-transform:scale(0.9) rotate(-3deg)}\n    30%,50%,70%,90%{-moz-transform:scale(1.1) rotate(3deg)}\n    40%,60%,80%{-moz-transform:scale(1.1) rotate(-3deg)}\n    100%{-moz-transform:scale(1) rotate(0)}\n}\n@-ms-keyframes ring{\n    0%{-ms-transform:scale(1)}\n    10%,20%{-ms-transform:scale(0.9) rotate(-3deg)}\n    30%,50%,70%,90%{-ms-transform:scale(1.1) rotate(3deg)}\n    40%,60%,80%{-ms-transform:scale(1.1) rotate(-3deg)}\n    100%{-ms-transform:scale(1) rotate(0)}\n}\n@keyframes ring{\n    0%{transform:scale(1)}\n    10%,20%{transform:scale(0.9) rotate(-3deg)}\n    30%,50%,70%,90%{transform:scale(1.1) rotate(3deg)}\n    40%,60%,80%{transform:scale(1.1) rotate(-3deg)}\n    100%{transform:scale(1) rotate(0)}\n}\n/*4.1 按钮组\n  Name:     mod_btn-group\n  Example:\n<div class=\"btn-group\">\n  <span class=\"btn btn-primary radius\">左边按钮</span>\n  <span class=\"btn btn-default radius\">中间按钮</span>\n  <span class=\"btn btn-default radius\">中间按钮</span>\n  <span class=\"btn btn-default radius\">右边按钮</span>\n</div>\n  Explain:\n*/\n.btn-group{ font-size:0}\n.btn-group .btn{ margin-left:-1px}\n.btn-group .btn:not(:first-child):not(:last-child):not(.dropdown-toggle){ border-radius:0}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius: 0;border-top-right-radius: 0}\n.btn-group > .btn:last-child:not(:first-child),.btn-group > .dropdown-toggle:not(:first-child) {border-bottom-left-radius: 0;border-top-left-radius: 0}\n\n/*4.2.1 导航条\n\tName:\t\t\tmod_nav\n\tExample:\n<header class=\"navbar-wrapper\">\n\t<nav class=\"nav navbar-nav nav-collapse\" role=\"navigation\" id=\"Hui-navbar\">\n\t\t<ul class=\"cl\">\n\t\t\t<li class=\"current\"><a href=\"/\">首页</a></li>\n\t\t\t<li><a href=\"#\">核心</a></li>\n\t\t\t<li><a href=\"#\">扩展</a></li>\n\t\t\t<li class=\"dropDown dropDown_hover\"><a href=\"#\" class=\"dropDown_A\">一级导航 <i class=\"Hui-iconfont\">&#xe6d5;</i></a>\n\t\t\t\t<ul class=\"dropDown-menu menu radius box-shadow\">\n\t\t\t\t\t<li><a href=\"#\">二级导航</a></li>\n\t\t\t\t\t<li><a href=\"#\">二级导航<i class=\"arrow Hui-iconfont\">&#xe6d7;</i></a>\n\t\t\t\t\t\t<ul class=\"menu\">\n\t\t\t\t\t\t\t<li><a href=\"javascript:;\">三级菜单<i class=\"arrow Hui-iconfont\">&#xe6d7;</i></a>\n\t\t\t\t\t\t\t\t<ul class=\"menu\">\n\t\t\t\t\t\t\t\t\t<li><a href=\"javascript:;\">四级菜单</a></li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"javascript:;\">四级菜单</a></li>\n\t\t\t\t\t\t\t\t\t<li><a href=\"javascript:;\">四级菜单</a></li>\n\t\t\t\t\t\t\t\t</ul>\n\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t<li><a href=\"#\">三级导航</a></li>\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t</li>\n\t\t\t\t\t<li><a href=\"#\">二级导航</a></li>\n\t\t\t\t\t<li class=\"disabled\"><a href=\"javascript:;\">二级菜单</a></li>\n\t\t\t\t</ul>\n\t\t\t</li>\n\t\t\t<li><a href=\"#\">联系我们</a></li>\n\t\t</ul>\n\t</nav>\n</header>\n\tExplain: 鼠标经过状态a:hover，当前选中状态li:current。\n*/\n/*导航条*/\n.navbar-wrapper{ height: 45px}\n.navbar{ position:relative; z-index:1030; background-color: #fff}\n.navbar-black{ background-color: #222}\n.navbar-fixed-top{ position:fixed; top:0;left: 0; right: 0; z-index:1030}\n\n  /*logo*/\n\t.logo{ display:inline-block; text-decoration:none; cursor:pointer; background-repeat: no-repeat; background-position: left center; background-size: auto 100%}\n\ta.logo:hover{ text-decoration:none}\n\t.navbar .logo{height: 44px;line-height: 44px;margin-right: 10px;float: left}\n\t.navbar-logo,.navbar-logo-m{font-size: 16px}\n\t.navbar-slogan{ font-size:12px; cursor: default}\n\t.navbar .container{ position:relative}\n\t.navbar .container .navbar-userbar{ right:0px}\n  /*导航*/\n  .nav{ z-index:1}\n  .nav > ul{ font-size:0; line-height:0}\n  .nav > ul > li{ position:relative; float:left}\n  .nav > ul > li,.nav > ul > li > a{ display:inline-block;text-align:center}\n  .nav > ul > li > a{ padding:0 20px}\n  .nav > ul > li > a:hover,.nav > ul > li.current > a{background-color:rgba(255,255,255,0.2); text-decoration:none;\n\t\t-webkit-transition: background-color 0.3s ease 0s;\n\t\t-moz-transition: background-color 0.3s ease 0s;\n\t\t-o-transition: background-color 0.3s ease 0s;\n\t\t-ms-transition: background-color 0.3s ease 0s;\n\t\ttransition: background-color 0.3s ease 0s\n  }\n  .navbar-nav > ul > li,.navbar-nav > ul > li > a{line-height:44px;font-size:14px}\n  @media (max-width: 767px) {\n    .navbar-wrapper{ height: 45px!important}\n    .logo{ margin-right: 0}\n    .navbar .logo{height: 44px!important;line-height: 44px!important}\n    .navbar-nav{display: none; float: none!important}\n    .navbar-nav > ul > li{ width: 100%; text-align: left; border-bottom: solid 1px #eee}\n    .navbar-nav > ul > li > a{display:block;padding:0 15px; text-align: left}\n    .navbar-nav > ul > li.dropDown.open > .dropDown-menu{ display: none}\n    .navbar-nav > ul > li.dropDown > .dropDown_A > .Hui-iconfont{ display: none}\n    .navbar-nav > ul > li,\n\t.navbar-nav > ul > li > a{height: 44px!important;line-height: 44px!important}\n\n    .nav-collapse > ul,.nav-collapse > ul >li {width: 100%;display: block}\n    .js .nav-collapse {position: absolute;display: block;float:none; clear:both;max-height: 0;clip: rect(0 0 0 0);margin-left: -15px; margin-right: -15px;overflow: hidden;\n      -webkt-transition:max-height 284ms ease 0s;\n      -moz-transition:max-height 284ms ease 0s;\n      -o-transition:max-height 284ms ease 0s;\n      -ms-transition:max-height 284ms ease 0s;\n      transition:max-height 284ms ease 0s}\n    .js-nav-active .nav-collapse.closed {max-height: none}\n    .nav-collapse.opened {max-height: 9999px}\n\n  }\n\n/*导航条风格-黑色*/\n.navbar-black{background-color:#222;border-bottom:#080808 1px solid;-moz-box-shadow: 0 0 4px #333333;-webkit-box-shadow: 0 0 4px #333333;box-shadow: 0 0 4px #333333}\n.navbar-black .logo{ color: #fff }\n.navbar-black .navbar-logo-m{color: #eee}\n.navbar-black .navbar-nav > ul > li,\n.navbar-black .navbar-nav > ul > li > a{ color:#fff}\n.navbar-black .navbar-nav > ul > li > a:hover,\n.navbar-black .navbar-nav > ul > li.current > a{color:#fff}\n.navbar-black .navbar-userbar{ color: #fff}\n@media (max-width: 767px) {\n  .navbar-black .navbar-nav > ul > li{border-bottom: solid 1px #222}\n  .navbar-black .navbar-nav > ul > li > a:hover,\n  .navbar-black .navbar-nav > ul > li.current > a{ background: #777}\n}\n\n  /*面包导航*/\n  .nav-toggle,a.nav-toggle{position:absolute; top:0px; right:15px; font-size: 20px; color:#999; padding:6px 11px;background-color:rgba(0,0,0,0.5);color:#fff;-webkit-tap-highlight-color: rgba(0,0,0,0);\n    -webkit-touch-callout: none;\n    -webkit-user-select: none;\n    -moz-user-select: none;\n    -ms-user-select: none;\n    -o-user-select: none;\n    user-select: none}\n  .nav-toggle:hover,a.nav-toggle:hover{ text-decoration: none; color:#fff}\n\n/*2.1.9 版本之前的导航条代码*/\n.mainnav{z-index:1;background-color:#222}/*导航条背景*/\n.mainnav > ul{ font-size: 0; line-height: 0}\n.mainnav > ul > li,\n.mainnav > ul > li > a{height:40px;line-height:40px}/*导航条高度*/\n.mainnav > ul > li{display:inline-block;color:#fff;font-size:14px;font-weight:bold}/*设置字体*/\n.mainnav > ul > li > a{display:inline-block;padding:0 20px;color:#fff;text-align:center}/*链接颜色*/\n.mainnav > ul > li > a:hover,\n.mainnav > ul > li.current > a{color:#fff;text-decoration:none; background-color:#000;-webkit-transition: background-color 0.3s ease 0s; -moz-transition: background-color 0.3s ease 0s; -o-transition: background-color 0.3s ease 0s; -ms-transition: background-color 0.3s ease 0s;transition: background-color 0.3s ease 0s}/*交互颜色*/\n\n.Hui-nav-toggle,a.Hui-nav-toggle{position:absolute; top:0px; right:15px; font-size: 20px; color:#999; padding:6px 11px;background-color:rgba(0,0,0,0.5);color:#fff}\n.Hui-nav-toggle:hover,a.Hui-nav-toggle:hover{ text-decoration: none; color:#fff}\n@media (max-width: 767px) {\n\t.mainnav > ul > li{font-size:1.125em}\n}\n@media (max-width: 480px) {\n\t.mainnav > ul > li{text-align:center}\n\t.mainnav > ul > li{width:20%}\n\t.mainnav > ul > li > a{padding:0;padding:0;display:block}\n}\n/*4.2.2 面包屑导航\n\tName:\t\t\tmod_breadcrumb\n\tExample:\n<nav class=\"breadcrumb\">\n  <div class=\"container\">\n    <i class=\"Hui-iconfont\">&#xe67f;</i> <a href=\"/\" class=\"c-primary\">首页</a><span class=\"c-gray en\">&gt;</span><a href=\"#\">组件</a><span class=\"c-gray en\">&gt;</span><span class=\"c-gray\">当前页面</span>\n  </div>\n</nav>\n*/\n.breadcrumb{border-bottom: 1px solid #E5E5E5;line-height: 39px; height:39px;overflow:hidden}\n.breadcrumb span{padding:0 5px}\n@media (max-width: 767px) {\n  .breadcrumb > .container{padding: 0}\n}\n/*4.2.3 翻页导航\n\tName:\t\t\tmod_pageNav\n\tExample:\t\t<div class=\"pageNav\" id=\"pageNav\"></div>\n\tExplain:\t\t需要调用pagenav.cn.js\n\n*/\n.pageNav{float:none;clear:both;font-size:0;font-family:Arial,Helvetica,sans-serif;padding:18px 0;text-align:center}\n.pageNav span,.pageNav a,.pageNav b{font-size:14px;margin-right:5px;overflow:hidden;padding:3px 8px}\n.pageNav a{border:1px solid #CCDBE4;cursor:pointer}\n.pageNav b{color:#000}\n.pageNav .mor{padding:3px;font-weight:bold}\n\n/*4.2.4 顶部导航\n\tName:\t\t\tmod_topnav\n\tSample:\n\t<div class=\"topnav\"><div class=\"cl\"><div class=\"l\">您好，欢迎来到Hui！</div><div class=\"r\"><span class=\"r_nav\">[ <a rel=\"nofollow\" href=\"javascript:login();\">登录</a> ]</span><span class=\"pipe\">|</span><span class=\"r_nav\">[ <a href=\"javascript:register();\" rel=\"nofollow\">注册</a> ]</span><span class=\"pipe\">|</span><span class=\"r_nav\"><a title=\"收藏\" href=\"javascript:addFavorite();\">收藏本站</a></span><span class=\"pipe\">|</span><span class=\"r_nav\"><a href=\"javascript:void(0)\" onclick=\"setHome(this);\" title=\"设为首页\">设为首页</a></span></div></div></div>\n\n*/\n.topnav{height:30px;line-height:30px;background-color;#f7f7f7;border-bottom:1px solid #EBEBEB; font-size:12px}\n.topbar{background-color: #ECECEC;border-bottom:1px solid #ddd}\n.topbar a{margin-right:5px}\n.r_nav{display:inline-block; color:#999}\n\n/*4.2.5 向导\n\tName:\t\t\tmod_steps\n\tSample:\n\t<div class=\"four steps\">\n\t  <span class=\"step\">第一步</span>\n\t  <span class=\"active step\">第二步</span>\n\t  <span class=\"disabled step\">第三步</span>\n\t  <span class=\"disabled step\">第四步</span>\n\t</div>\n*/\n.steps,.step{display:inline-block;position:relative;padding:1em 2em 1em 3em;vertical-align:top;background-color:#FFF;color:#888;\n\t-webkit-box-sizing:border-box;\n\t-moz-box-sizing:border-box;\n\t-ms-box-sizing:border-box;\n\tbox-sizing:border-box\n}\n.step:after,.steps .step:after{position:absolute;z-index:2;content:'';top:0;right:-1.45em;border-bottom:1.5em solid transparent;border-left:1.5em solid #FFF;border-top:1.5em solid transparent;width:0;height:0}\n.step,.steps .step,.steps .step:after{\n\t-webkit-transition:opacity .1s ease,color .1s ease,-webkit-box-shadow .1s ease;\n\ttransition:opacity .1s ease,color .1s ease,box-shadow .1s ease\n}\n.steps{cursor:pointer;display:inline-block;font-size:0;box-shadow:0 0 0 1px rgba(0,0,0,.1);border-radius:.3125rem;line-height:1;\n\t-webkit-box-sizing:border-box;\n\t-moz-box-sizing:border-box;\n\t-ms-box-sizing:border-box;\n\tbox-sizing:border-box}\n.steps .step:first-child{padding-left:1.35em;border-radius:.3125em 0 0 .3125em}\n.steps .step:last-child{border-radius:0 .3125em .3125em 0}\n.steps .step:only-child{border-radius:.3125em}\n.steps .step:last-child{margin-right:0}\n.steps .step:last-child:after{display:none}\n.step:hover,.step.hover{background-color:#F7F7F7;color:rgba(0,0,0,.8)}\n.steps .step.hover:after,\n.steps .step:hover:after,\n.step:hover,\n.step.hover::after{border-left-color:#F7F7F7}\n.steps .step.down,\n.steps .step:active,\n.step.down,\n.step:active{background-color:#F0F0F0}\n.steps .step.down:after,\n.steps .step:active:after,\n.steps.down::after,\n.steps:active::after{border-left-color:#F0F0F0}\n.steps .step.active,\n.active.step{cursor:auto;background-color:#428BCA;color:#FFF;font-weight:700}.steps .step.active:after,.active.steps:after{border-left-color:#428BCA}\n.steps .disabled.step,\n.disabled.step{cursor:auto;background-color:#FFF;color:#CBCBCB}\n.disabled.step:after{border:0;background-color:#FFF;top:.42em;right:-1em;width:2.15em;height:2.15em;\n\t-webkit-transform:rotate(-45deg);\n\t-ms-transform:rotate(-45deg);\n\ttransform:rotate(-45deg);\n\tbox-shadow:-1px -1px 0 0 rgba(0,0,0,.1) inset\n}\n.attached.steps{margin:0;border-radius:.3125em .3125em 0 0}\n.attached.steps .step:first-child{border-radius:.3125em 0 0}\n.attached.steps .step:last-child{border-radius:0 .3125em 0 0}\n.bottom.attached.steps{margin-top:-1px;border-radius:0 0 .3125em .3125em}\n.bottom.attached.steps .step:first-child{border-radius:0 0 0 .3125em}\n.bottom.attached.steps .step:last-child{border-radius:0 0 .3125em}\n\n/*向导数量*/\n.one.steps,.two.steps,.three.steps,.four.steps,.five.steps,.six.steps,.seven.steps,.eight.steps{display:block}\n.one.steps > .step{width:100%}\n.two.steps > .step{width:50%}\n.three.steps > .step{width:33.333%}\n.four.steps > .step{width:25%}\n.five.steps > .step{width:20%}\n.six.steps > .step{width:16.666%}\n.seven.steps > .step{width:14.285%}\n.eight.steps > .step{width:12.5%}\n\n/*向导尺寸*/\n.small.step,.small.steps .step{font-size:.8rem}/*小*/\n.step,.steps .step{font-size:1rem}/*默认*/\n.large.step,.large.steps .step{font-size:1.25rem}/*大*/\n\n/*兼容写法\n\tSample:\n\t<div class=\"steps-ie cl\">\n\t  <a class=\"step-ie active\" href=\"#\">第一步<em class=\"arrow\"></em></a>\n\t  <a class=\"step-ie\" href=\"#\">第二步<em class=\"arrow\"></em></a>\n\t  <a class=\"step-ie\" href=\"#\">第三步<em class=\"arrow\"></em></a>\n\t</div>\n*/\n.steps-ie,.step-ie,.step-ie .arrow{height:44px; line-height:44px}\n.steps-ie{background-color:#eaf4fd; border:solid 1px #afcfcc}\n.step-ie{position:relative;display:inline-block; float:left; cursor:pointer; padding:0 20px 0 40px; background:url(../images/steps/step_bg.png) repeat-x 0 center}\n.step-ie .arrow{position:absolute;right:-21px; top:0; width:21px; height:44px; display:block; cursor:pointer; background:url(../images/steps/step_arrow.png) no-repeat 0 center;z-index:50}\n.step-ie.active{background-image:url(../images/steps/step_bg-active.png); color:#fff; z-index:100}\n.step-ie.active .arrow{background-image:url(../images/steps/step_arrow-active.png)}\n\n/*4.2.6 竖向导向tab导航\n\tSample:\n\t<div class=\"verticalTab\">\n\t  <a class=\"\" href=\"#\">导航一<em></em></a>\n\t  <a class=\"active\" href=\"#\">导航二<em></em></a>\n\t  <a href=\"#\">导航三<em></em></a>\n\t  <a href=\"#\">导航四<em></em></a>\n\t</div>\n*/\n.verticalTab{background:#fff url(../images/verticalTab/tab_bg.png) repeat-y 0 0; width:38px}\n.verticalTab a{position:relative; display:block; width:18px; height:auto; text-align:center; position:relative; padding:26px 10px 6px 10px; background:url(../images/verticalTab/tabNav.png) no-repeat 0 0}\n.verticalTab a em{position:absolute; left:0; bottom:-20px; width:38px; height:20px; background:url(../images/tabNav_right.png) no-repeat 0 0; z-index:50}\n.verticalTab a.active{background-image:url(../images/verticalTab/tabNav-active.png); color:#fff; z-index:99}\n.verticalTab a.active em{background-image:url(../images/verticalTab/tabNav_right-active.png)}\n\n/*4.2.6 横向导向tab导航\n\tSample:\n\t<ul class=\"acrossTab\">\n\t  <li>导航一<i></i><em></em></li>\n\t  <li class=\"active\">导航二<i></i><em></em></li>\n\t  <li>导航三<i></i><em></em></li>\n\t</ul>\n*/\n.acrossTab,.acrossTab li,.acrossTab li em{ background-image:url(../images/acrossTab/acrossTab-bg.png)}\n.acrossTab{height:29px; background-repeat: repeat-x; background-position: 0 0; padding-top:1px}\n.acrossTab li,.acrossTab li em{ background-repeat:no-repeat; background-position:0 0}\n.acrossTab li{position:relative;float:left; display:inline-block; height:29px; line-height:29px; font-size:12px;cursor:pointer;padding:0 30px; white-space:nowrap;color:#282828; background-position:0 0}\n.acrossTab li em{position:absolute; width:23px;height:29px;right:-20px; top:0;z-index:50; background-position:right -30px}\n.acrossTab li:hover{background-position:0 -60px}\n.acrossTab li:hover em{background-position:right -90px}\n.acrossTab li.active{background-position:0 -120px; z-index:99}\n.acrossTab li.active em{background-position:right -150px}\n.acrossTab li i{position:absolute; display:block; width:13px; height:13px; top:50%; margin-top:-6px; right:5px; font-size:0; line-height:0; cursor:pointer; background-image:url(../images/acrossTab/acrossTab-close.png); background-repeat:no-repeat; background-position:0 0}\n.acrossTab li i:hover{background-position:0 bottom}\n\n/*4.3.1 下拉菜单\n\tName:\t\t\tmod_dropDown\n\tExample:\n\t<span class=\"dropDown\">\n\t\t<a class=\"dropDown_A\" href=\"#\">下拉菜单</a>\n\t\t<ul class=\"dropDown-menu menu radius box-shadow\">\n\t\t\t<li><a href=\"#\">菜单一</a></li>\n\t\t\t<li><a href=\"#\">菜单二</a></li>\n\t\t</ul>\n\t</span>\n\tExplain:\t\t如需要在不同的地方显示不同的样式，请在<span class=\"dropDown\"> 追加class，采用覆盖的方式重写默认样式。\n\n*/\n.dropDown{display:inline-block}\n.dropDown_A{display:inline-block}\n.dropDown-menu{ display:none;transition: all 0.3s ease 0s}\n.dropDown:focus,.dropDown-menu:focus {outline:0}\n.dropDown-menu li.arrow{ position:absolute;display:block; width:12px; height:8px; margin-top:-13px; margin-left:20%; line-height:0;background:url(../images/dropDown/icon-jt.png) no-repeat 0 0}\n/*鼠标经过*/\n.dropDown.hover .dropDown_A,\n.dropDown.open .dropDown_A{text-decoration:none;background-color:rgba(255,255,255,0.2)}\n.dropDown.open .dropDown_A .menu_dropdown-arrow{transition-duration:0.3s ;transition-property:all;_background-position:0 0;transform: rotate(180deg)}\n\n.menu{background-color:#fff;border:solid 1px #f2f2f2; display: inline-block}\n.menu.radius{border-top-left-radius:0;border-top-right-radius:0}\n.menu.box-shadow{border-top:none}\n.menu > li{position:relative; clear:both;* float:left}\n.menu > li > a{ display: block;border-bottom:solid 1px #f2f2f2;padding:5px 20px; line-height:1.8;text-align:left;font-weight: normal;white-space:nowrap; vertical-align:top}\n.menu > li:last-child > a{ border-bottom:none}\n.menu > li > a:hover,.menu > li > a:focus,.menu > li.open > a{ text-decoration:none;background-color:#fafafa}\n.menu > li > a .arrow{ position:absolute; top:50%; margin-top:-10px; right:5px;line-height: 20px; height: 20px; color: #999}\n.menu > li > .menu{ display: none}\n.menu > li.open > .menu{ display: inline-block;position: absolute; left:100%;top:-1px;min-width:100%}\n\n/*禁用菜单*/\n.menu > li.disabled > a{color:#999;text-decoration:none; cursor:no-drop; background-color:transparent}\n/*线条*/\n.menu > li.divider{ display:block;height:0px; line-height:0px;margin:9px 0;overflow:hidden; border-top:solid 1px #eee}\n\n/*打开菜单*/\n.dropDown > .dropDown-menu{ display: none}\n.dropDown.open{position:relative;z-index:990}\n/*默认左对齐*/\n.dropDown.open > .dropDown-menu{position:absolute;z-index:1000;display:inline-block;top:100%;left:-1px;min-width:100%;background-color:#fff;border:solid 1px #f2f2f2}\n/*右对齐*/\n.dropDown.open.right > .dropDown-menu{right:-1px!important;left:auto!important}\n\n/*4.4 幻灯片\n\tName:\t\t\tmodule_slider\n\tSample:\n<div id=\"slider-1\">\n  <div class=\"slider\">\n    <div class=\"bd\">\n      <ul>\n        <li><a href=\"http://www.h-ui.net/\" target=\"_blank\"><img src=\"temp/banner1.jpg\" ></a></li>\n        <li><a href=\"http://www.h-ui.net/zhaishang.shtml\" target=\"_blank\"><img src=\"temp/banner2.jpg\" ></a></li>\n        <li><a href=\"http://h-ui.net/H-ui.admin.shtml\" target=\"_blank\"><img src=\"temp/banner4.jpg\" ></a></li>\n      </ul>\n    </div>\n    <ol class=\"hd cl dots\">\n      <li>1</li>\n      <li>2</li>\n      <li>3</li>\n    </ol>\n  </div>\n</div>\n\t<script type=\"text/javascript\" src=\"lib/jquery.SuperSlide/2.1.1/jquery.SuperSlide.min.js\"></script>\n\t<script type=\"text/javascript\">\n\t$(function() {\n\t\tjQuery(\"#slider-1 .slider\").slide({mainCell:\".bd ul\",titCell:\".hd li\",trigger:\"click\",effect:\"leftLoop\",autoPlay:true,delayTime:700,interTime:3000,pnLoop:false,titOnClassName:\"active\"});\n\t});\n\t</script>\n\tExplain: 默认dots为圆点，在slider后面追加numSlider样式就变成带数字的方框，boxSlider为不带数字长方条\n*/\n.slider{position:relative;text-align:center; margin:0 auto;z-index:1}\n.slider .bd,.slider .bd li,.slider .bd img{width:100%; height:100%}/*请给每个幻灯片套个div并设置id，通过id重置这个地方的宽度，达到自定义效果*/\n.slider .bd{z-index:2;overflow:hidden}\n.slider .bd li{float:left;width: 100%;overflow:hidden; background-position:center; background-repeat:no-repeat}\n.slider .bd li a{ display:block; width: 100%; height: 100%}\n.slider .bd li img{display:block}\n.slider .hd{ position: absolute; z-index: 3; left: 0; right: 0; bottom:10px; padding: 0 10px; text-align: center}\n.slider .hd li{display:inline-block;text-align:center;margin-right:10px;cursor:pointer;background-color:#C2C2C2}\n.slider .hd li.active{background-color:#222}\n\t/*圆点*/\n\t.dots li{width:10px; height:10px;font-size:0px;line-height:0px;border-radius:50%}\n\t/*数字*/\n\t.numbox li{width:20px; height:20px; line-height:20px; font-size:13px;font-family:Arial;font-weight:bold; text-indent:inherit}\n\t.numbox li.active{color:#fff}\n\t/*长方条*/\n\t.rectangle li{width:40px; height:10px;font-size:0px;line-height:0px}\n\n.slider-arrow{display:block; position:absolute; top:50%; margin-top:-25px;height: 50px;width: 50px; line-height: 50px; text-align: center; z-index:3;opacity: 0.7;filter: alpha(opacity=70)}\n.slider-arrow:hover{opacity: 1;filter: alpha(opacity=100)}\n.slider-arrow.prev{left:0px}\n.slider-arrow.next{right:0px}\n\n/*4.5 选项卡\n\tName:\t\t\tmodule_slider\n\tSample:\n\t<div id=\"tab_demo\" class=\"HuiTab\">\n      <div class=\"tabBar cl\"><span>选项卡一</span><span>选项卡二</span><span>自适应宽度</span></div>\n      <div class=\"tabCon\">内容一</div>\n      <div class=\"tabCon\">内容二</div>\n      <div class=\"tabCon\">内容三</div>\n    </div>\n*/\n.tabBar {border-bottom: 2px solid #222}\n.tabBar span {background-color: #e8e8e8;cursor: pointer;display: inline-block;float: left;\nfont-weight: bold;height: 30px;line-height: 30px;padding: 0 15px}\n.tabBar span.current{background-color: #222;color: #fff}\n.tabCon {display: none}\n\n/*4.6 标签与标号\n\tName:\t\t\tstyle_label\n\tExample:\t\t<span class=\"label label-default|label-primary|label-secondary|label-success|label-warning|label-danger\">默认</span>\n\tExplain:\t\t.label-default 默认|.label-primary 主要|.label-secondary 次要|.label-success 成功|.label-warning 警告|.label-danger 危险\n\n\tName:\t\t\tstyle_badge\n\tExample:\t\t<span class=\"badge badge-default|label-primary|badge-secondary|badge-success|badge-warning|badge-danger\">默认</span>\n\tExplain:\t\t.badge-default 默认|.badge-primary 主要|.badge-secondary 次要|.badge-success 成功|.badge-warning 警告|.badge-danger 危险\n\n*/\n.label, .badge{display: inline-block;padding:2px 4px;font-size: 11.844px;font-weight: bold;line-height:14px;color: #fff;white-space: nowrap;vertical-align:middle;background-color: #999; overflow: hidden}\n/*圆角*/\n.label.radius{border-radius: 3px}\n.badge{padding-right:9px;padding-left:9px;border-radius:9px}\n.label:empty, .badge:empty{display: none}\na.label:hover, a.label:focus, a.badge:hover, a.badge:focus{color: #fff;text-decoration: none;cursor: pointer}\n\n/*默认*/\n.label-default, .badge-default{background-color: #e6e6e6; color:#333}\n.label-default[href], .badge-default[href]{background-color: #e6e6e6;color:#333}\n\n/*主要*/\n.label-primary, .badge-primary{background-color: #5a98de}\n.label-primary[href], .badge-primary[href]{background-color: #5a98de}\n\n/*主要*/\n.label-secondary, .badge-secondary{background-color: #3bb4f2}\n.label-secondary[href], .badge-secondary[href]{background-color: #3bb4f2}\n\n/*成功*/\n.label-success, .badge-success{background-color:#5eb95e}\n.label-success[href], .badge-success[href]{background-color: #5eb95e}\n\n/*警告*/\n.label-warning, .badge-warning{background-color: #f37b1d}\n.label-warning[href], .badge-warning[href]{background-color: #f37b1d}\n\n/*危险*/\n.label-danger, .badge-danger{background-color: #dd514c}\n.label-danger[href], .badge-danger[href]{background-color: #dd514c}\n\n/*4.7 缩略图\n\tName:       style_img\n\tExample:\n\tExplain:\t\t缩略图 删除，转移到3.6 图片中\n*/\n\n/*4.8 警告\n\tName:\t\t\tmod_Hui-alert\n\tExample:\n<div class=\"Huialert Huialert-success/Huialert-danger/Huialert-error/Huialert-info/Huialert-block\">\n\t<i class=\"Hui-iconfont\">&#xe6a6;</i>\n\t警告内容\n\t<ul>\n\t\t<li>……</li>\n\t</ul>\n</div>\n\tExplain:\t\t警告,使用警告框jQuery插件\n*/\n.Huialert{position:relative;padding:8px 35px 8px 14px;margin-bottom: 20px;text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);background-color: #fcf8e3;border: 1px solid #fbeed5}\n.Huialert, .Huialert h4{color: #c09853}\n.Huialert h4{margin: 0}\n.Huialert .Hui-iconfont{position:absolute;top:9px;right:10px;line-height: 20px;cursor:pointer; color:#000; opacity:0.2;_color:#666}\n.Huialert .Hui-iconfont.hover{color:#000;opacity:0.8}\n.Huialert-success{color: #468847;background-color: #dff0d8;border-color: #d6e9c6}\n.Huialert-success h4{color: #468847}\n.Huialert-danger{color: #b94a48;background-color: #f2dede;border-color: #eed3d7}\n.Huialert-danger h4{color: #b94a48}\n.Huialert-error{color: #fff;background-color: #f37b1d;border-color: #e56c0c}\n.Huialert-error h4{color: #fff}\n.Huialert-info{color: #31708f;background-color: #d9edf7;border-color: #bce8f1}\n.Huialert-info h4{color:#31708f}\n.Huialert-block{padding-top: 14px;padding-bottom: 14px}\n.Huialert-block > p,.Huialert-block > ul{margin-bottom: 0}\n.Huialert-block p + p{margin-top: 5px}\n\n/*4.9 进度条 loading\n\tName:\t\t\tmod_progress\n\tExample:\n\t<div class=\"progress radius\"><div class=\"progress-bar\"><span class=\"sr-only\"></span></div></div>\n\tExplain:\t\t警告,使用警告框jQuery插件\n*/\n.progress,.progress-bar,.sr-only{height:10px; font-size:0;line-height:0}\n.progress{overflow:hidden; width:400px}\n.progress.radius{}/*自定义圆角*/\n.progress-bar{width:100%;background-color:#efefef;}\n.sr-only{\n\tdisplay:inline-block; background-color:#337ab7;\n\t-webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n          box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15);\n  -webkit-transition: width .6s ease;\n       -o-transition: width .6s ease;\n          transition: width .6s ease;\n}\n.progress-bar-success .sr-only{ background-color:#5cb85c}\n.progress-bar-warning .sr-only{background-color: #f0ad4e}\n.progress-bar-danger .sr-only{background-color: #d9534f}\n\n/*4.10 对话框\n\tName:\t\t\tmod_modal\n\tExample:\n<div id=\"modal-mapper\" class=\"modal fade\" tabindex=\"-1\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n\t<div class=\"modal-dialog\">\n\t\t<div class=\"modal-content\">\n\t\t\t<div class=\"modal-header\">\n\t\t\t\t<h3 id=\"myModalLabel\">对话框标题</h3>\n\t\t\t\t<a class=\"close\" data-dismiss=\"modal\" aria-hidden=\"true\" href=\"javascript:void();\">×</a>\n\t\t\t</div>\n\t\t\t<div class=\"modal-body\">\n\t\t\t\t<p>对话框内容…</p>\n\t\t\t</div>\n\t\t\t<div class=\"modal-footer\">\n\t\t\t\t<button class=\"btn btn-primary\">确定</button> <button class=\"btn\" data-dismiss=\"modal\" aria-hidden=\"true\">关闭</button>\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n*/\n.fade {opacity: 0;\n  -webkit-transition: opacity .15s linear;\n       -o-transition: opacity .15s linear;\n          transition: opacity .15s linear}\n.fade.in {opacity: 1}\n.modal-open {overflow: hidden}\n.modal{ position:fixed; left:0; top:0; right:0; bottom:0; z-index:1040; display:none; overflow:hidden;-webkit-overflow-scrolling:touch; outline:0}\n.modal.fade .modal-dialog{\n\t-webkit-transition: -webkit-transform .3s ease-out;\n\t\t -o-transition: -o-transform .3s ease-out;\n\t\t\ttransition: transform .3s ease-out;\n\t-webkit-transform: translate(0,-50%);\n\t\t-ms-transform: translate(0,-50%);\n\t\t -o-transform: translate(0,-50%);\n\t\t\ttransform: translate(0,-50%)}\n.modal.in .modal-dialog {\n  -webkit-transform: translate(0, 0);\n      -ms-transform: translate(0, 0);\n       -o-transform: translate(0, 0);\n          transform: translate(0, 0)}\n.modal-open .modal {overflow-x: hidden;overflow-y: auto}\n\t.modal-backdrop {position: fixed;top: 0;right: 0;bottom: 0;left: 0;background-color: #000}\n\t.modal-backdrop.fade {filter: alpha(opacity=0);opacity: 0}\n\t.modal-backdrop.in {filter: alpha(opacity=50);opacity: .5}\n\t.modal-dialog {position: relative;margin:10px}\n\t\t.modal-content{position: relative;background-color: #fff;border: 1px solid #999;border: 1px solid rgba(0,0,0,.2);outline: 0;\n    \t\t-webkit-background-clip: padding-box;\n\t\t\t\t\tbackground-clip: padding-box;\t\t\t\t\t\n\t\t\t-webkit-box-shadow: 0 3px 9px rgba(0,0,0,.5);\n\t\t\t\t\tbox-shadow: 0 3px 9px rgba(0,0,0,.5)}\n\t\t\n\t\t\t.modal-header {min-height: 16.42857143px;padding: 15px;border-bottom: 1px solid #eee; position:relative}\n\t\t\t.modal-header .close{position:absolute; right:15px; top:15px}\n\t\t\t.modal-close{position:absolute; right:15px; top:15px;font-size:24px; z-index: 9}\n\t\t\ta.modal-close:hover{ text-decoration: none}\n\t\t\t.modal-header h3,.modal-header .modal-title{margin:0; padding:10px 0; font-size:16px}\n\t\t\t\n\t\t\t.modal-body {position:relative;padding:15px;overflow-y:visible;word-break:break-all}\n\t\t\t\t.modal-form {margin-bottom: 0}\n\t\t\t\t\n\t\t\t.modal-footer {padding:15px;margin-bottom: 0;text-align: right;background-color: #f5f5f5;border-top: 1px solid #eee;*zoom: 1}\n\t\t\t\n\t\t\t.modal-footer:before,.modal-footer:after {display: table;content: \"\"}\n\t\t\t.modal-footer:after {clear: both}\n\t\t\t.modal-footer .btn + .btn {margin-left: 5px;margin-bottom: 0}\n\t\t\t.modal-footer .btn-group .btn + .btn {margin-left: -1px}\n\t\t\t.modal-footer .btn-block + .btn-block {margin-left: 0}\n\t\t.modal-scrollbar-measure {position: absolute;top: -9999px;width: 50px;height: 50px;overflow: scroll}\n\t\t\n\t\t.radius .modal-content{ border-radius:6px}\n\t\t.radius .modal-footer{ border-bottom-left-radius:6px; border-bottom-right-radius:6px}\n/*上下居中*/\n.modal.middle .modal-dialog{position:absolute;margin:10px;left:0;right:0;top:50%}\n.modal.fade.middle .modal-dialog{\n\t-webkit-transform: translate(0,-100%);\n\t\t-ms-transform: translate(0,-100%);\n\t\t -o-transform: translate(0,-100%);\n\t\t\ttransform: translate(0,-100%)}\n.modal.in.middle .modal-dialog{\n\t-webkit-transform:translate(0,-50%);\n\t-ms-transform:translate(0,-50%);\n\t-o-transform:translate(0,-50%);\n\ttransform:translate(0,-50%)\n}\n\n\n@media (min-width: 768px) {\n  .modal-dialog { width:600px;margin: 30px auto}\n  .modal.middle .modal-dialog{ margin:10px auto}\n  .modal-content {-webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);box-shadow: 0 5px 15px rgba(0, 0, 0, .5)}\n  .modal-sm {width: 300px}\n}\n@media (min-width: 992px) {\n  .modal-lg {width: 900px}\n}\n\n\n\t\n.modal-alert{position:fixed; right:auto; bottom:auto; width:300px; left:50%;margin-left:-150px; top:50%;margin-top:-30px; z-index:9999;background-color: #fff;border: 1px solid #999;border: 1px solid rgba(0,0,0,.2);outline: 0;\n-webkit-background-clip: padding-box;\n\t\tbackground-clip: padding-box;\t\t\t\t\t\n-webkit-box-shadow: 0 3px 9px rgba(0,0,0,.5);\n\t\tbox-shadow: 0 3px 9px rgba(0,0,0,.5)}\n\n\t.modal-alert-info{padding:30px; text-align:center; font-size:14px; background-color:#fff}\n\n\n.loading{height: 50px; width: 50px; background:#fff url(../images/loading/loading-b.gif) no-repeat center}\n.mask{position:fixed;top:0;left:0;z-index:999;width:100%;height:100%;background-color:rgba(0,0,0,0.7);-moz-transition:all 0.3s ease-in;-webkit-transition:all 0.3s ease-in;-o-transition:all 0.3s ease-in;transition:all 0.3s ease-in}\n* html .mask{position:absolute;left:expression(documentElement.scrollLeft + documentElement.clientWidth - this.offsetWidth);top:expression(documentElement.scrollTop + documentElement.clientHeight - this.offsetHeight)}\n\n.mask_box{background-image:none;display:none;z-index:99}\n.hover .mask_box{position:absolute;bottom:0; left:0;display:block;background-color:rgba(0,0,0,0.3);text-align:left}\n.modal-open .dropdown-menu {z-index: 2050}\n.modal-open .dropdown.open {*z-index: 2050}\n.modal-open .popover {z-index: 2060}\n.modal-open .tooltip {z-index: 2070}\n\t\t\n/*\t//old 版本\n\n\t//当弹出层出现时，隐藏body右侧滚动条\n\t.modal-open{overflow-x: hidden;overflow-y: auto}\n\t//隐藏body滚动条时，页面偏移\n\t.page-overflow{margin-right:16px}\n\t//弹出层，绝对定位，默认【宽度500px，高度自适应，背景白色，6px圆角，带阴影】，自定义宽度可在data-width中设置参数\n\t.modal {position:absolute;top:50%;left:50%; width:500px;margin-left:-250px;z-index:1050;overflow: visible;background-color: #fff;background-clip: padding-box;\n\t\tbox-shadow: 0 3px 7px rgba(0, 0, 0, 0.3);\n\t\t-webkit-background-clip:padding-box;\n\t\t-khtml-background-clip:padding-box;\n\t\t-moz-background-clip:padding-box;\n\t\t-ms-background-clip:padding-box;\n\t\t-o-background-clip:padding-box;\n\t\tbackground-clip:padding-box;\n\t\tborder-radius:6px;\n\t\tborder:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999}\n\n\t//弹出层进入动画效果\n\t.modal.fade {top: -100%}\n\t//弹出层进入后居顶距离，配合margin-top负值，实现上下自动居中\n\t.modal.fade.in{top:50%}\n\t//如果弹出层高度大于窗口，弹出窗口距顶0像素\n\t.modal.modal-overflow.fade.in{top:0}\n\t\n\t//隐藏body滚动条时，页面偏移\n\t.page-overflow{margin-right:16px}\n\t\n\t//弹出层的最外层，全屏，用户响应点击和滚动\n\t.modal-scrollable{position:fixed;top:0;right:0;bottom:0;left:0;overflow: auto}\n\t\n\t//弹窗超出屏幕高度时，弹出层替代body右侧滚动条，实现弹出层的整体滚动\n\t.modal-overflow .modal-scrollable{overflow-y:scroll}\n\t\n\t//默认遮罩层，全屏黑色\n\t.modal-backdrop {position:fixed;top:0;right:0;bottom:0;left:0;width:100%;height:100%;z-index:1040;background-color:#000}\n\t//解决IE下 遮罩层兼容性\n\t* html .modal-backdrop{position:absolute;left:expression(documentElement.scrollLeft + documentElement.clientWidth - this.offsetWidth);top:expression(documentElement.scrollTop + documentElement.clientHeight - this.offsetHeight)}\n\t\n\t//遮罩层失去时，透明度为0\n\t.modal-backdrop.fade {opacity:0;filter: alpha(opacity=0)}\n\t\n\t//遮罩层进入 0.7透明度\n\t.modal-backdrop,.modal-backdrop.fade.in {opacity: 0.7;filter: alpha(opacity=70)}\n\t\n\t//Ajax加载数据时loading\n\t.loading-spinner {position: absolute;top: 50%;left: 50%;margin: -12px 0 0 -12px}\n\t\n\t//弹出层header区\n\t//弹出层头部\n\t.modal-header {padding: 9px 15px;border-bottom: 1px solid #eee; position:relative}\n\t//关闭按钮，请调用4.1.1 按钮 .close\n\t.modal-header .close{position:absolute; right:10px; top:10px}\n\t//标题\n\t.modal-header h3{margin:0; padding:10px 0; font-size:16px}\n\t\n\t//内容不限高度，内填充15px，不满意可自行修改\n\t.modal-body {overflow-y:visible;padding: 15px; word-break:break-all}\n\t//弹出层表单\n\t.modal-form {margin-bottom: 0}\n\t//弹出层footer区，放按钮\n\t.modal-footer {padding: 14px 15px 15px;margin-bottom: 0;text-align: right;background-color: #f5f5f5;border-top: 1px solid #ddd;*zoom: 1;border-radius: 0 0 6px 6px;box-shadow: inset 0 1px 0 #fff}\n\t.modal-footer:before,.modal-footer:after {display: table;content: \"\"}\n\t.modal-footer:after {clear: both}\n\t.modal-footer .btn + .btn {margin-left: 5px;margin-bottom: 0}\n\t.modal-footer .btn-group .btn + .btn {margin-left: -1px}\n\t.modal-alert{position:fixed; width:300px;margin-left:-150px; margin-top:-30px; z-index:9999}\n\t.modal-alert-info{padding:30px; text-align:center; font-size:14px; background-color:#fff}*/\n\n/*.easyDialog_wrapper{width:320px; color:#444; border:3px solid rgba(0,0,0,0);border-radius:5px;box-shadow:0 0 10px rgba(0,0,0,0.4); display:none}\n.easyDialog_wrapper .easyDialog_content{border-radius:4px; background:#fff; border:1px solid #e5e5e5}\n.easyDialog_wrapper .easyDialog_title{height:30px; line-height:30px; overflow:hidden; color:#666; padding:0 10px; font-size:14px; border-bottom:1px solid #e5e5e5; background:#f7f7f7; border-radius:4px 4px 0 0; margin:0 }\n.easyDialog_wrapper .close_btn{font-family:arial; font-size:18px; _font-size:12px; font-weight:700; color:#999; text-decoration:none; float:right}\n.easyDialog_wrapper .close_btn:hover{color:#333}\n.easyDialog_wrapper .easyDialog_text{padding:25px 10px; font-size:13px; line-height:22px}\n.easyDialog_wrapper .easyDialog_footer{padding:10px; text-align:right; *zoom:1}\n.easyDialog_wrapper .easyDialog_footer:after{content:''; display:block; height:0; overflow:hidden; visibility:hidden; clear:both}\n.easyDialog_wrapper .btn_highlight,.easyDialog_wrapper .btn_normal{border:1px solid; border-radius:2px; cursor:pointer;float:right; font-size:12px; padding:0 12px; height:24px; line-height:24px; margin-bottom:10px}\n.easyDialog_wrapper .btn_highlight{background:#4787ed; background:-webkit-gradient(linear,center bottom,center top,from(#4787ed),to(#4d90fe)); background:-moz-linear-gradient(90deg, #4787ed, #4d90fe); border-color:#3079ed; color:#fff}\n.easyDialog_wrapper .btn_normal{margin-left:10px; border-color:#c3c3c3; background:#ececec; color:#333; background:-webkit-gradient(linear,center bottom,center top,from(#ececec),to(#f4f4f4)); background:-moz-linear-gradient(90deg,#ececec,#f4f4f4)}*/\n\n/*4.12 右侧悬浮工具\n\tName:\t\tmodal_tools-right\n*/\n.tools-right{position:fixed;right:15px;z-index:999;cursor: pointer;visibility:visible; background-color:#fff;border: 1px solid #d9d9d9;color: #9c9c9c;font-size: 16px;width: 38px;height: 38px;line-height: 38px;text-align: center; text-decoration:none;_position:absolute;_top:expression(documentElement.scrollTop + documentElement.clientHeight-this.offsetHeight)}\n.tools-right:hover{color:#fff; text-decoration:none; background-color:#999; border-color:#999}\n\t/*4.12.1 返回顶部\n\t\tName:\t\t\tmod_totop\n\t\tLevel:\t\t\tGlobal\n\t\tExample:\t\t<a href=\"javascript:void(0)\" class=\"tools-right toTop\" title=backToTopTxt alt=backToTopTxt></a>\n\t\tExplain:\t\t返回顶部\n\t*/\n\t.tools-right.toTop{bottom:60px;display:none}\n\t/*4.12.2 意见反馈\n\t\tName:\t\t\tmod_feedback\n\t\tLevel:\t\t\tGlobal\n\t\tExample:\t\t<a href=\"javascript:;\" class=\"tools-right feedback Hui-iconfont\" title=\"意见反馈\" onClick=\"feedback()\">&#xe70c;</a>\n\t\tExplain:\t\t意见反馈\n\t<div id=\"modal-feedback\" class=\"modal hide fade\">\n\t\t<div class=\"modal-header\">\n\t\t\t <h3>意见反馈</h3>\n\t\t\t <a class=\"Hui-iconfont close\" data-dismiss=\"modal\" aria-hidden=\"true\" href=\"javascript:void();\">&#xe6a6;</a>\n\t\t</div>\n\t\t<div class=\"modal-body\">\n\t\t\t<div>\n\t\t\t\t<label class=\"mr-20\"><input type=\"radio\" class=\"radio\" value=\"1\" name=\"radio-feedback\" id=\"feedback-1\"> 业务咨询</label>\n\t\t\t\t<label class=\"mr-20\"><input type=\"radio\" class=\"radio\" value=\"2\" name=\"radio-feedback\" id=\"feedback-2\"> 体验反馈</label>\n\t\t\t\t<label class=\"mr-20\"><input type=\"radio\" class=\"radio\" value=\"3\" name=\"radio-feedback\" id=\"feedback-3\"> 好点子</label>\n\t\t\t</div>\n\t\t\t<div class=\"formControls mt-20\">\n\t\t\t\t<textarea class=\"textarea valid\" onKeyUp=\"$.Huitextarealength(this,500)\" placeholder=\"吐槽点什么...最少输入10个字符\"></textarea>\n\t\t\t\t<p class=\"textarea-numberbar\"><em class=\"textarea-length\">0</em>/500</p>\n\t\t\t</div>\n\t\t</div>\n\t\t<div class=\"modal-footer\">\n\t\t\t<button class=\"btn btn-primary radius\">确定</button>\n\t\t\t<button class=\"btn btn-default radius ml-10\" data-dismiss=\"modal\" aria-hidden=\"true\">取消</button>\n\t\t</div>\n\t</div>\n\t*/\n\t.tools-right.feedback{ bottom:110px}\n\n/*4.13 分享到\n\tName:\t\t\tmod_share\n\tExample:\n\tExplain:\t分享到\n*/\n\t/*4.13.1 百度分享*/\n\t.bdsharebuttonbox.Hui-share a.bds_more,\n\t.bdsharebuttonbox.Hui-share a.bds_weixin,\n\t.bdsharebuttonbox.Hui-share a.bds_qzone,\n\t.bdsharebuttonbox.Hui-share a.bds_sqq,\n\t.bdsharebuttonbox.Hui-share a.bds_tsina,\n\t.bdsharebuttonbox.Hui-share a.bds_tqq,\n\t.bdsharebuttonbox.Hui-share a.bds_douban{ display:inline-block; background:none;padding-left:0; text-decoration:none; margin:0; margin-right:6px; height:auto; line-height:auto}\n\t.bdsharebuttonbox.Hui-share a:hover{ text-decoration:none}\n\t.bdsharebuttonbox.Hui-share .share-text{ display:inline-block; margin-right:6px; color:#999; cursor:default;float:left}\n\t\n\t.bdsharebuttonbox.bdshare-button-style0-16.Hui-share a,\n\t.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .share-text,\n\t.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .Hui-iconfont{line-height:16px}\n\t.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .share-text,\n\t.bdsharebuttonbox.bdshare-button-style0-16.Hui-share .Hui-iconfont{font-size:16px}\n\t\n\t.bdsharebuttonbox.bdshare-button-style0-24.Hui-share a,\n\t.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .share-text,\n\t.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .Hui-iconfont{line-height:24px}\n\t.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .share-text,\n\t.bdsharebuttonbox.bdshare-button-style0-24.Hui-share .Hui-iconfont{font-size:24px}\n\t/*4.13.2 jiathis分享*/\n\t.Hui-share.jiathis_style_24x24 .jtico{ background:none; padding-left:0!important}\n\t.Hui-share.jiathis_style_24x24 .jiathis_separator{ margin-left:0; margin-right:6px}\n/*4.14 Panel 面板\n\tName:\t\t\tmod_panel\n\tSample:\n\t<div class=\"panel panel-default\">\n\t\t<div class=\"panel-body\">默认面板</div>\n\t</div>\n*/\n.panel{ background-color:#fff; border:solid 1px transparent}\n\t.panel-header{ border-bottom:solid 1px transparent; padding:8px 15px; font-size:14px; font-weight:700; margin-bottom:-1px}/*面板标题*/\n\t.panel-body{ padding:15px}/*面板内容*/\n\t.panel-footer{background-color: #f5f5f5;border-top: 1px solid #ddd;padding:5px 20px}/*面板页脚*/\n/*默认面板*/\n.panel-default{border-color:#ddd}\n.panel-default > .panel-header{ border-color:#ddd; background-color:#f5f5f5; color:#444}\n\n/*主要面板*/\n.panel-primary{border-color:#5a98de}\n.panel-primary > .panel-header{ border-color:#5a98de; background-color:#5a98de; color:#fff}\n\n/*次要面板*/\n.panel-secondary{border-color:#3bb4f2}\n.panel-secondary > .panel-header{ border-color:#3bb4f2; background-color:#3bb4f2; color:#fff}\n\n/*成功面板*/\n.panel-success{border-color:#5eb95e}\n.panel-success > .panel-header{ border-color:#5eb95e; background-color:#5eb95e; color:#fff}\n\n/*警告面板*/\n.panel-warning{border-color:#f37b1d}\n.panel-warning > .panel-header{ border-color:#f37b1d; background-color:#f37b1d; color:#fff}\n\n/*危险面板*/\n.panel-danger{border-color:#dd514c}\n.panel-danger > .panel-header{ border-color:#dd514c; background-color:#dd514c; color:#fff}\n\n/*4.15 案例\n\tName:\t\t\tmod_docs-example\n\tExample:\t\t<div class=\"docs-example tooltip-mapper\">……</div>\n*/\n.docs-example{position:relative;*position:static;*padding-top: 19px;margin: 15px 0;padding: 39px 19px 14px;background-color: #fff;border: 1px solid #ddd;border-radius: 4px}\n.docs-example:after{content: \"Example\";position: absolute;top: -1px;left: -1px;*position:static;padding: 3px 7px;font-size: 12px;font-weight: bold;background-color: #f5f5f5;border: 1px solid #ddd;color: #9da0a4;border-radius: 4px 0 4px 0}\n\n/*4.16 滚动\n\tName:\t\t\tmod_rolling\n\tExample:\t\t<div class=\"rollpicshow\"><ul><li>……</li></ul></div>\n*/\n.marquee{height:22px;overflow:hidden;line-height:22px}\n.rollpic .prev,.rollpic .next{display:block; height:38px; width:38px; cursor:pointer; float:left; background:url(../images/rollpic/unslider-arrow.png) no-repeat 0 0; margin-top:70px}\n.rollpic .prev{background-position:0 0; margin-right:5px}\n.rollpic .prev:hover{background-position:0 -38px}\n.rollpic .next{background-position:0 -76px;margin-left:5px}\n.rollpic .next:hover{background-position:0 -114px}\n.rollpicshow{float:left; border:solid 1px #ddd}\n.rollpicshow li{padding:10px}\n\n/*4.17 搜索条\n\tName:\t\t\tmod_searchBar\n\tSample:\n<div class=\"searchBar\">\n  <form class=\"form-search\" method=\"post\" action=\"\">\n    <input id=\"searchKeyword\" name=\"searchKeyword\" value=\"请输入搜索关键词\" class=\"input-text searchTxt\">\n    <input id=\"searchBtn\" name=\"searchBtn\" type=\"submit\" value=\"搜索\" class=\"btn btn-default searchBtn\" onclick=\"b_onclick()\">\n  </form>\n</div>\n*/\n\t/*搜索下拉提示*/\n.ac_results{position:absolute;border:solid 1px #ddd;background-color:#fff; padding:3px; display:none; margin-top:-1px; z-index:999}\n.ac_results ul{width:100%;list-style-position:outside;list-style:none;padding:0;margin:0}\n.ac_results li{padding-left:5px;padding-right:5px;display:block;height:24px;line-height:24px;cursor:pointer}\n.ac_results li p{ float:left;margin:0;padding:0;overflow:hidden}\n.ac_results li p tt{color:#666}\n.ac_results li span{margin:0;padding:0;display:inline;float:right;color:#f93;width:90px; text-align:right; overflow:hidden}\n.ac_results li.ac_even{}\n.ac_results li.ac_odd{}\n.ac_results li.ac_over{background-color:#f0f1f2}\n\t.ac_loading{background:#fff url(../images/loading/loading-s.gif) right center no-repeat}\n\n/*4.18.1 对联广告\n\tName:\t\t\tmod_AD_dual\n\tSample:\n\t<div class=\"dual dual_l\"><div class=\"dual_con\">对联的内容</div><a href=\"#\" class=\"dual_close\">X关闭</a></div>\n\t<div class=\"dual dual_r\"><div class=\"dual_con\">对联的内容</div><a href=\"#\" class=\"dual_close\">X关闭</a></div>\n*/\n.AD{text-align:center}\n.dual{top:260px;position:absolute; width:102px; overflow:hidden; display:none; z-index:100}\n.dual_l{left:6px}\n.dual_r{right:6px}\n.dual_con{border:#CCC solid 1px;width:100px; height:300px; overflow:hidden; background-color:#0C9}\n.dual_close{width:100%;height:24px; line-height:24px; text-align:center; display:block; font-size:13px; color:#555; text-decoration:none}\n\n/*4.19 标签*/\n\t/*4.19.1 标签输入效果\n\t\tName:\t\t\tmod_Hui-tags\n\t\tSample:\n\t\t<div class=\"Hui-tags\">\n\t\t  <div class=\"Hui-tags-editor cl\"><i class=\"Hui-tags-icon\"></i>\n\t\t\t<span class=\"Hui-tags-token\">Hui前端框架</span>\n\t\t\t<span class=\"Hui-tags-token\">CSS3</span>\n\t\t\t<span class=\"Hui-tags-token\">HTML5</span>\n\t\t\t<div class=\"Hui-tags-iptwrap\"><input type=\"text\" class=\"Hui-tags-input\" maxlength=\"20\" value=\"\"><label class=\"Hui-tags-label\">添加相关标签，用空格或回车分隔</label></div>\n\t\t  </div>\n\t\t  <div class=\"Hui-tags-list\">\n\t\t\t<div class=\"Hui-notag\">暂无常用标签</div>\n\t\t\t<div class=\"Hui-tags-has\"><span>前端框架</span> <span>前端开发</span> <span>H-ui</span></div>\n\t\t  </div>\n\t\t  <input type=\"hidden\" class=\"Hui-tags-val\" name=\"\" value=\"\">\n\t\t</div>\n\t*/\n\t.Hui-tags,\n\t.Huitags-wraper{border:solid 1px #dedede; padding:0 10px}\n\t\t.Hui-tags-editor,\n\t\t.Huitags-editor{position:relative; padding:10px 0 10px 24px;min-height:20px}\n\t\t\n\t\t.Hui-tags-editor .Hui-tags-icon,\n\t\t.Huitags-editor .Huitags-icon{position:absolute; left:0; top:11px; font-size:14px; color:#666}\n\t\t\n\t\t\t.Hui-tags-token,\n\t\t\t.Huitags-token{color:#aaa; float:left; font-size:12px; height:20px; line-height:20px; margin-right:8px; padding:0 1px; white-space:nowrap; cursor:pointer}\n\t\t\t.Hui-tags-token:before,\n\t\t\t.Huitags-token:before{content:\"#\"}\n\t\t\t.Hui-tags-token:hover,\n\t\t\t.Huitags-token:hover{text-decoration:line-through}\n\t\t\t\n\t\t\t.Hui-tags-iptwrap{position:relative; float:left}\n\t\t\t.Huitags-input-wraper{}\n\t\t\t\t.Hui-tags-input\n\t\t\t\t{position:relative;height:20px;min-width:60px; border:0 none; vertical-align:top;line-height:20px; color:#333;z-index:2;background: url(../images/Hui-tags/empty.png) repeat scroll 0 0; display:inline-block; width:100%}\n\t\t\t\t.Huitags-input{}\n\t\t\t\t.Hui-tags-label,\n\t\t\t\t.Huitags-label{position:absolute; top:0; left:2px; width:240px; height:20px; line-height:20px; font-size:14px; overflow:hidden; z-index:1; color:#ccc}\n\t\t\t\t\n\t\t\t.Hui-tags-list,\n\t\t\t.Huitags-list{padding:0 0 10px 0;}\n\t\t\t\n\t\t.Hui-notag,\n\t\t.Huitags-notag{font-size:12px}\n\t\t\n\t\t.Hui-tags-has span,\n\t\t.Huitags-has span{cursor:pointer; font-size:12px; white-space:nowrap; margin-right:10px}\n\t\n\t/*4.19.2 标签混排效果\n\t\tName:\t\t\tmod_tags\n\t\tSample:\t\t\t<div class=\"pd-10 tags\"><a href=\"http://www.h-ui.net/\">H-ui前端框架</a>……</div>\n\t\n\t*/\n\t.tags a{height:26px; line-height:26px;padding-right:6px}\n\t\t.tags0{}\n\t\t.tags1{color:#C00; font-size:24px}\n\t\t.tags2{color:#030; font-size:16px}\n\t\t.tags3{color:#00F}\n\t\t.tags4{font-size:16px}\n\t\t.tags5{color:#C00; font-size:20px}\n\t\t.tags6{color:#F06; font-size:20px}\n\t\t.tags7{color:#030; font-weight:bold; font-size:18px}\n\t\t.tags8{color:#F06; font-weight:bold}\n\t\t.tags9{color:#C00; font-weight:bold;font-size:16px}\n\t.tags a:hover{color:#F00; text-decoration:underline}\n\t\n\t/*4.19.3 tag云标签*/\n\t#tagyun {position:relative}\n\t#tagyun a {position:absolute;top:0px;left:0px;font-weight:bold;text-decoration:none;padding:3px 6px}\n\n/*4.20 折叠\n\tName:\t\t\tmod_Huifold\n\tSample:\n\t<ul id=\"\" class=\"Huifold\">\n\t  <li class=\"item\"><h4>标题<b>+</b></h4><div class=\"info\">内容 </div></li>\n\t  ……\n\t</ul>\n*/\n.Huifold .item{position:relative}\n.Huifold .item h4{margin:0;font-weight:bold;position:relative;border-top: 1px solid #fff;font-size:15px;line-height:22px;padding:7px 10px;background-color:#eee;cursor:pointer;padding-right:30px}\n.Huifold .item h4 b{position:absolute;display: block; cursor:pointer;right:10px;top:7px;width:16px;height:16px; text-align:center; color:#666}\n.Huifold .item .info{display:none;padding:10px}\n\n/*4.21 遮罩条\n\tName:\t\t\tmod_maskBar\n*/\n.maskBar{position:absolute;height:auto;left:0; bottom:-100%; right:0;padding:10px;background-color:rgba(0,0,0,0.6);z-index:2; color:#fff!important}\n.maskWraper{position:relative; overflow:hidden}\n.maskWraper.hover .maskBar{bottom:0px;\n\ttransition: bottom 200ms;\n\t-moz-transition: bottom 200ms; /* Firefox 4 */\n\t-webkit-transition: bottom 200ms; /* Safari 和 Chrome */\n\t-o-transition: bottom 200ms; /* Opera */\n}\n.maskBox{position:absolute;width:100%; height:100%;top:0;left:0; bottom:0;right:0;z-index:2;color:#fff!important}\n.maskWraper.hover .maskBox{background-color:rgba(0,0,0,0.6);\n\ttransition: all 500ms;\n\t-moz-transition: all 500ms; /* Firefox 4 */\n\t-webkit-transition: all 500ms; /* Safari 和 Chrome */\n\t-o-transition: all 500ms; /* Opera */\n}\n\n/*4.22 评论列表\n\tName:\t\t\tmod_comment\n\tSample:\n\t<ul class=\"commentList\">\n\t  <li class=\"item clearfix\">\n\t    <a href=\"#\"><i class=\"avatar avatar-L radius\"><img alt=\"\" src=\"static/h-ui/images/ucenter/avatar-default.jpg\"></i></a>\n\t\t<div class=\"comment-main\">\n\t\t  <header class=\"comment-header\">\n\t\t    <div class=\"comment-meta\"><a class=\"comment-author\" href=\"#\">辉哥</a> 评论于 <time title=\"2014年8月31日 下午3:20\" datetime=\"2014-08-31T03:54:20\">2014-8-31 15:20</time></div>\n\t      </header>\n\t\t  <div class=\"comment-body\"><p><a href=\"#\">@某人</a> 你是猴子派来的救兵吗？</p></div></div>\n\t  </li>\n\t</ul>\n*/\n.commentList .item{list-style: none outside none;margin: 1.6rem 0 0}\n.commentList .avatar{border: 1px solid transparent;float: left}\n\t.comment-main{position:relative;margin-left:64px;border:1px solid #dedede;border-radius:2px}\n\t.comment-main:before,\n\t.comment-main:after{position:absolute;top:11px;left:-16px;right:100%;width:0;height:0;display:block;content:\" \";border-color:transparent;border-style:solid solid outset;pointer-events:none}\n\t.comment-main:before{border-right-color:#dedede;border-width:8px}\n\t.comment-main:after{border-width:7px;border-right-color:#f8f8f8;margin-top:1px;margin-left:2px}\n\t\t.comment-header{padding:10px 15px;background:#f8f8f8;border-bottom:1px solid #eee}\n\t\t.comment-title{margin:0 0 8px 0;font-size:1.6rem;line-height:1.2}\n\t\t.comment-meta{font-size:13px;color:#999;line-height:1.2}\n\t\t.comment-meta a{color:#999}\n\t\t.comment-author{font-weight:700;color:#999}\n\t\t.comment-body{padding:15px;overflow:hidden}\n\t\t.comment-body>:last-child{margin-bottom:0}\n.commentList .comment-flip .avatar {float: right}\n\t.comment-flip .comment-main{margin-left: 0; margin-right: 64px}\n\t.comment-flip .comment-main:before {border-left-color: #dedede;border-right-color: transparent}\n\t.comment-flip .comment-main:before,\n\t.comment-flip .comment-main:after {left: 100%;position: absolute;right: -16px}\n\t.comment-flip .comment-main:after {border-left-color: #f8f8f8;border-right-color: transparent;margin-left: auto;margin-right: 2px}\n\n/*4.23 页脚\n\tName:\t\t\tmod_footer\n\tSample:\n<footer class=\"footer mt-20\">\n  <div class=\"container\">\n    <nav class=\"footer-nav\">\n      <a target=\"_blank\" href=\"/aboutHui.html\">关于H-ui</a>\n      <span class=\"pipe\">|</span>\n      <a target=\"_blank\" href=\"/copyright.html\">软件著作权</a>\n      <span class=\"pipe\">|</span>\n      <a target=\"_blank\" href=\"/juanzeng.html\">感谢捐赠</a>\n    </nav>\n    <p>Copyright &copy;2013-2016 H-ui.net All Rights Reserved. <br>\n    <a rel=\"nofollow\" target=\"_blank\" href=\"http://www.miitbeian.gov.cn/\">京ICP备10000000号</a><br>\n    未经允许，禁止转载、抄袭、镜像</p>\n  </div>\n</footer>\n*/\n.footer{border-top:1px solid #E8E8E8; padding:15px 0;font-family:tahoma,Arial;font-size:12px;color:#999;line-height:22px;text-align:center}\n.footer a,.footer a:hover{color:#999}\n\n/*4.24 星星评价\n\tName:\t\t\tmod_star\n\tSample:\n显示分数效果 可以是百分比\n<div class=\"star-bar star-bar-show size-M\">\n\t<span class=\"star\" style=\"width:75%\"></span>\n</div>\n\n打分效果 结构是js生成。\n<div id=\"\" class=\"star-bar size-M \"></div>\n*/\n.star-bar-show{background:url(../images/star/iconpic-star-S-default.png) repeat-x 0 0}\n.star-bar-show .star{background:url(../images/star/iconpic-star-S.png) repeat-x 0 0}\n.star-1{width:20%}\n.star-2{ width:40%}\n.star-3{width:60%}\n.star-4{ width:80%}\n.star-5{ width:100%}\n.star-bar-show.size-M{width:120px;height:24px}\n.star-bar-show.size-M,.star-bar-show.size-M .star{background-size:24px}\n.star-bar-show.size-M .star{ height:24px}\n.star-bar-show.size-S{width:80px; height:16px}\n.star-bar-show.size-S,.star-bar-show.size-S .star{background-size:16px}\n.star-bar-show.size-S .star{ height:16px}\n\n.star-bar{font-size:0; line-height:0}\n.star-bar .star{display:inline-block;text-align:center}\n/*中*/\n.size-M img{ width:24px;height:24px}\n/*小*/\n.size-S img{width:16px;height:16px}\n\n/*4.25 tooltip 效果\n\tName:\t\t\tmod_tooltip\n*/\n.tooltip {position: absolute;z-index: 1070;display: block;font-size: 12px;line-height: 1.4;visibility: visible;filter: alpha(opacity=0);opacity: 0}\n.tooltip.in {filter: alpha(opacity=90);opacity: .9}\n.tooltip.top {padding: 5px 0;margin-top: -3px}\n.tooltip.right {padding: 0 5px;margin-left: 3px}\n.tooltip.bottom {padding: 5px 0;margin-top: 3px}\n.tooltip.left {padding: 0 5px;margin-left: -3px}\n\t.tooltip-inner {max-width: 200px;padding: 3px 8px;color: #fff;text-align: center;text-decoration: none;background-color: #000;border-radius: 4px}\n\t.tooltip-arrow {position: absolute;width: 0;height: 0;border-color: transparent;border-style: solid}\n.tooltip.top .tooltip-arrow {bottom: 0;left: 50%;margin-left: -5px;border-width: 5px 5px 0;border-top-color: #000}\n.tooltip.top-left .tooltip-arrow {bottom: 0;left: 5px;border-width: 5px 5px 0;border-top-color: #000}\n.tooltip.top-right .tooltip-arrow {right: 5px;bottom: 0;border-width: 5px 5px 0;border-top-color: #000}\n.tooltip.right .tooltip-arrow {top: 50%;left: 0;margin-top: -5px;border-width: 5px 5px 5px 0;border-right-color: #000}\n.tooltip.left .tooltip-arrow {top: 50%;right: 0;margin-top: -5px;border-width: 5px 0 5px 5px;border-left-color: #000}\n.tooltip.bottom .tooltip-arrow {top: 0;left: 50%;margin-left: -5px;border-width: 0 5px 5px;border-bottom-color: #000}\n.tooltip.bottom-left .tooltip-arrow {top: 0;left: 5px;border-width: 0 5px 5px;border-bottom-color: #000}\n.tooltip.bottom-right .tooltip-arrow {top: 0;right: 5px;border-width: 0 5px 5px;border-bottom-color: #000}\n\n/*4.26 popover 效果\n\tName:\t\t\tmod_popover\n*/\n.popover {position: absolute;top: 0;left: 0;z-index: 1060;display: none;max-width: 276px;padding: 1px;font-size: 14px;font-weight: normal;line-height: 1.42857143;text-align: left;white-space: normal;background-color: #fff;-webkit-background-clip: padding-box;background-clip: padding-box;border: 1px solid #ccc;border: 1px solid rgba(0, 0, 0, .2);border-radius: 6px;-webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2);box-shadow: 0 5px 10px rgba(0, 0, 0, .2)}\n.popover.top {margin-top: -10px}\n.popover.right {margin-left: 10px}\n.popover.bottom {margin-top: 10px}\n.popover.left {margin-left: -10px}\n.popover-title {padding: 8px 14px;margin: 0;font-size: 14px;background-color: #f7f7f7;border-bottom: 1px solid #ebebeb;border-radius: 5px 5px 0 0}\n.popover-content {padding: 9px 14px}\n.popover > .arrow,.popover > .arrow:after {position: absolute;display: block;width: 0;height: 0;border-color: transparent;border-style: solid}\n.popover > .arrow {border-width: 11px}\n.popover > .arrow:after {content: \"\";border-width: 10px}\n.popover.top > .arrow {bottom: -11px;left: 50%;margin-left: -11px;border-top-color: #999;border-top-color: rgba(0, 0, 0, .25);border-bottom-width: 0}\n.popover.top > .arrow:after {bottom: 1px;margin-left: -10px;content: \" \";border-top-color: #fff;border-bottom-width: 0}\n.popover.right > .arrow {top: 50%;left: -11px;margin-top: -11px;border-right-color: #999;border-right-color: rgba(0, 0, 0, .25);border-left-width: 0}\n.popover.right > .arrow:after {bottom: -10px;left: 1px;content: \" \";border-right-color: #fff;border-left-width: 0}\n.popover.bottom > .arrow {top: -11px;left: 50%;margin-left: -11px;border-top-width: 0;border-bottom-color: #999;border-bottom-color: rgba(0, 0, 0, .25)}\n.popover.bottom > .arrow:after {top: 1px;margin-left: -10px;content: \" \";border-top-width: 0;border-bottom-color: #fff}\n.popover.left > .arrow {top: 50%;right: -11px;margin-top: -11px;border-right-width: 0;border-left-color: #999;border-left-color: rgba(0, 0, 0, .25)}\n.popover.left > .arrow:after {right: 1px;bottom: -10px;content: \" \";border-right-width: 0;border-left-color: #fff}\n\n/*4.27 datetimepicker日期插件\n\tName:\t\t\tmod_datetimepicker\n\tSample:\n*/\n.datetimepicker {padding: 4px;margin-top: 1px;-webkit-border-radius: 4px;-moz-border-radius: 4px;border-radius: 4px;direction: ltr;position: absolute;top: 100%;left: 0;z-index: 1000;display: none;float: left;min-width: 160px;padding: 5px 0;margin: 2px 0 0;font-size: 14px;list-style: none;background-color: #ffffff;border: 1px solid #cccccc;border: 1px solid rgba(0, 0, 0, 0.15);border-radius: 4px;-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);background-clip: padding-box}\n.datetimepicker-inline {width: 220px}\n.datetimepicker.datetimepicker-rtl {direction: rtl}\n.datetimepicker.datetimepicker-rtl table tr td span {float: right}\n.datetimepicker-dropdown, .datetimepicker-dropdown-left {top: 0;left: 0}\n[class*=\" datetimepicker-dropdown\"]:before {content: '';display: inline-block;border-left: 7px solid transparent;border-right: 7px solid transparent;border-bottom: 7px solid #cccccc;border-bottom-color: rgba(0, 0, 0, 0.2);position: absolute}\n[class*=\" datetimepicker-dropdown\"]:after {content: '';display: inline-block;border-left: 6px solid transparent;border-right: 6px solid transparent;border-bottom: 6px solid #fff;position: absolute}\n[class*=\" datetimepicker-dropdown-top\"]:before {content: '';display: inline-block;border-left: 7px solid transparent;border-right: 7px solid transparent;border-top: 7px solid #ccc;border-top-color: rgba(0, 0, 0, 0.2);border-bottom: 0}\n[class*=\" datetimepicker-dropdown-top\"]:after {content: '';display: inline-block;border-left: 6px solid transparent;border-right: 6px solid transparent;border-top: 6px solid #fff;border-bottom: 0}\n.datetimepicker-dropdown-bottom-left:before {top: -7px;right: 6px}\n.datetimepicker-dropdown-bottom-left:after {top: -6px;right: 7px}\n.datetimepicker-dropdown-bottom-right:before {top: -7px;left: 6px}\n.datetimepicker-dropdown-bottom-right:after {top: -6px;left: 7px}\n.datetimepicker-dropdown-top-left:before {bottom: -7px;right: 6px}\n.datetimepicker-dropdown-top-left:after {bottom: -6px;right: 7px}\n.datetimepicker-dropdown-top-right:before {bottom: -7px;left: 6px}\n.datetimepicker-dropdown-top-right:after {bottom: -6px;left: 7px}\n.datetimepicker > div {display: none}\n.datetimepicker.minutes div.datetimepicker-minutes {display: block}\n.datetimepicker.hours div.datetimepicker-hours {display: block}\n.datetimepicker.days div.datetimepicker-days {display: block}\n.datetimepicker.months div.datetimepicker-months {display: block}\n.datetimepicker.years div.datetimepicker-years {display: block}\n.datetimepicker table {margin: 0}\n.datetimepicker  td,\n.datetimepicker th {text-align: center;width: 20px;height: 20px;-webkit-border-radius: 4px;-moz-border-radius: 4px;border-radius: 4px;border: none}\n.table-striped .datetimepicker table tr td,\n.table-striped .datetimepicker table tr th {background-color: transparent}\n.datetimepicker table tr td.minute:hover {background: #eee;cursor: pointer}\n.datetimepicker table tr td.hour:hover {background: #eee;cursor: pointer}\n.datetimepicker table tr td.day:hover {background: #eee;cursor: pointer}\n.datetimepicker table tr td.old,\n.datetimepicker table tr td.new {color: #999}\n.datetimepicker table tr td.disabled,\n.datetimepicker table tr td.disabled:hover {background: none;color: #999;cursor: default}\n\n.datetimepicker table tr td.today,\n.datetimepicker table tr td.today:hover,\n.datetimepicker table tr td.today.disabled,\n.datetimepicker table tr td.today.disabled:hover {background-color: #fde19a;background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);\n\tbackground-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);\n\tbackground-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));\n\tbackground-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);\n\tbackground-image: -o-linear-gradient(top, #fdd49a, #fdf59a);\n\tbackground-image: linear-gradient(top, #fdd49a, #fdf59a);\n\tbackground-repeat: repeat-x;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);border-color: #fdf59a #fdf59a #fbed50;border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter: progid:DXImageTransform.Microsoft.gradient(enabled=false)}\n\n.datetimepicker table tr td.today:hover,\n.datetimepicker table tr td.today:hover:hover,\n.datetimepicker table tr td.today.disabled:hover,\n.datetimepicker table tr td.today.disabled:hover:hover,\n.datetimepicker table tr td.today:active,\n.datetimepicker table tr td.today:hover:active,\n.datetimepicker table tr td.today.disabled:active,\n.datetimepicker table tr td.today.disabled:hover:active,\n.datetimepicker table tr td.today.active,\n.datetimepicker table tr td.today:hover.active,\n.datetimepicker table tr td.today.disabled.active,\n.datetimepicker table tr td.today.disabled:hover.active,\n.datetimepicker table tr td.today.disabled,\n.datetimepicker table tr td.today:hover.disabled,\n.datetimepicker table tr td.today.disabled.disabled,\n.datetimepicker table tr td.today.disabled:hover.disabled,\n.datetimepicker table tr td.today[disabled],\n.datetimepicker table tr td.today:hover[disabled],\n.datetimepicker table tr td.today.disabled[disabled],\n.datetimepicker table tr td.today.disabled:hover[disabled] {background-color: #fdf59a}\n.datetimepicker table tr td.today:active,\n.datetimepicker table tr td.today:hover:active,\n.datetimepicker table tr td.today.disabled:active,\n.datetimepicker table tr td.today.disabled:hover:active,\n.datetimepicker table tr td.today.active,\n.datetimepicker table tr td.today:hover.active,\n.datetimepicker table tr td.today.disabled.active,\n.datetimepicker table tr td.today.disabled:hover.active {background-color: #fbf069}\n.datetimepicker table tr td.active,\n.datetimepicker table tr td.active:hover,\n.datetimepicker table tr td.active.disabled,\n.datetimepicker table tr td.active.disabled:hover {background-color: #006dcc;\n\tbackground-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n\tbackground-image: -ms-linear-gradient(top, #0088cc, #0044cc);\n\tbackground-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n\tbackground-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n\tbackground-image: -o-linear-gradient(top, #0088cc, #0044cc);\n\tbackground-image: linear-gradient(top, #0088cc, #0044cc);\n\tbackground-repeat: repeat-x;filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color: #0044cc #0044cc #002a80;border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);color: #fff;text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25)}\n\n.datetimepicker table tr td.active:hover,\n.datetimepicker table tr td.active:hover:hover,\n.datetimepicker table tr td.active.disabled:hover,\n.datetimepicker table tr td.active.disabled:hover:hover,\n.datetimepicker table tr td.active:active,\n.datetimepicker table tr td.active:hover:active,\n.datetimepicker table tr td.active.disabled:active,\n.datetimepicker table tr td.active.disabled:hover:active,\n.datetimepicker table tr td.active.active,\n.datetimepicker table tr td.active:hover.active,\n.datetimepicker table tr td.active.disabled.active,\n.datetimepicker table tr td.active.disabled:hover.active,\n.datetimepicker table tr td.active.disabled,\n.datetimepicker table tr td.active:hover.disabled,\n.datetimepicker table tr td.active.disabled.disabled,\n.datetimepicker table tr td.active.disabled:hover.disabled,\n.datetimepicker table tr td.active[disabled],\n.datetimepicker table tr td.active:hover[disabled],\n.datetimepicker table tr td.active.disabled[disabled],\n.datetimepicker table tr td.active.disabled:hover[disabled] {background-color: #04c}\n\n.datetimepicker table tr td.active:active,\n.datetimepicker table tr td.active:hover:active,\n.datetimepicker table tr td.active.disabled:active,\n.datetimepicker table tr td.active.disabled:hover:active,\n.datetimepicker table tr td.active.active,\n.datetimepicker table tr td.active:hover.active,\n.datetimepicker table tr td.active.disabled.active,\n.datetimepicker table tr td.active.disabled:hover.active {background-color: #039}\n\n.datetimepicker table tr td span {display: block;width: 23%;height: 54px;line-height: 54px;float: left;margin: 1%;\tcursor: pointer;-webkit-border-radius: 4px;-moz-border-radius: 4px;border-radius: 4px}\n\n.datetimepicker .datetimepicker-hours span {height: 26px;line-height: 26px}\n\n.datetimepicker .datetimepicker-hours table tr td span.hour_am,\n.datetimepicker .datetimepicker-hours table tr td span.hour_pm {width: 14.6%}\n\n.datetimepicker .datetimepicker-hours fieldset legend,\n.datetimepicker .datetimepicker-minutes fieldset legend {margin-bottom: inherit;line-height: 30px}\n.datetimepicker .datetimepicker-minutes span {height: 26px;line-height: 26px}\n.datetimepicker table tr td span:hover {background: #eee}\n\n.datetimepicker table tr td span.disabled,\n.datetimepicker table tr td span.disabled:hover {background: none;color: #999;cursor: default}\n.datetimepicker table tr td span.active,\n.datetimepicker table tr td span.active:hover,\n.datetimepicker table tr td span.active.disabled,\n.datetimepicker table tr td span.active.disabled:hover {background-color: #006dcc;\n\tbackground-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n\tbackground-image: -ms-linear-gradient(top, #0088cc, #0044cc);\n\tbackground-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n\tbackground-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n\tbackground-image: -o-linear-gradient(top, #0088cc, #0044cc);\n\tbackground-image: linear-gradient(top, #0088cc, #0044cc);\n\tbackground-repeat: repeat-x;\n\tfilter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);border-color: #0044cc #0044cc #002a80;border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);color: #fff;text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25)}\n\n.datetimepicker table tr td span.active:hover,\n.datetimepicker table tr td span.active:hover:hover,\n.datetimepicker table tr td span.active.disabled:hover,\n.datetimepicker table tr td span.active.disabled:hover:hover,\n.datetimepicker table tr td span.active:active,\n.datetimepicker table tr td span.active:hover:active,\n.datetimepicker table tr td span.active.disabled:active,\n.datetimepicker table tr td span.active.disabled:hover:active,\n.datetimepicker table tr td span.active.active,\n.datetimepicker table tr td span.active:hover.active,\n.datetimepicker table tr td span.active.disabled.active,\n.datetimepicker table tr td span.active.disabled:hover.active,\n.datetimepicker table tr td span.active.disabled,\n.datetimepicker table tr td span.active:hover.disabled,\n.datetimepicker table tr td span.active.disabled.disabled,\n.datetimepicker table tr td span.active.disabled:hover.disabled,\n.datetimepicker table tr td span.active[disabled],\n.datetimepicker table tr td span.active:hover[disabled],\n.datetimepicker table tr td span.active.disabled[disabled],\n.datetimepicker table tr td span.active.disabled:hover[disabled] {background-color: #0044cc}\n\n.datetimepicker table tr td span.active:active,\n.datetimepicker table tr td span.active:hover:active,\n.datetimepicker table tr td span.active.disabled:active,\n.datetimepicker table tr td span.active.disabled:hover:active,\n.datetimepicker table tr td span.active.active,\n.datetimepicker table tr td span.active:hover.active,\n.datetimepicker table tr td span.active.disabled.active,\n.datetimepicker table tr td span.active.disabled:hover.active {background-color: #039}\n.datetimepicker table tr td span.old {color: #999}\n.datetimepicker th.switch {width: 145px}\n.datetimepicker th span.glyphicon {pointer-events: none}\n.datetimepicker thead tr:first-child th,\n.datetimepicker tfoot th {cursor: pointer}\n.datetimepicker thead tr:first-child th:hover,\n.datetimepicker tfoot th:hover {background: #eee}\n.input-append.date .add-on i,\n.input-prepend.date .add-on i,\n.input-group.date .input-group-addon span {cursor: pointer;width: 14px;height: 14px}\n\n/*4.27 分类检索\n\tName:\t\t\tmod_select-category\n\tSample:\n<div class=\"select-category\">\n\t<div class=\"item clearfix\">\n\t\t<dl>\n\t\t\t<dt class=\"dt\">选择区域：</dt>\n\t\t\t<dd class=\"dd\">\n\t\t\t\t<a href=\"#\" title=\"北京市\">北京市</a>  \n            </dd>\n\t\t</dl>\n\t</div>\n</div>\n*/\n.select-category{}\n.select-category .item{padding:5px; position:relative; border-bottom:solid 1px #ddd}\n.select-category .item .dt{ width:90px; float:left;white-space:nowrap}\n.select-category .item .dd{ margin-left:100px; text-align:left; font-size:14px; height:auto}\n.select-category .item .dd a{ display:inline-block;white-space:nowrap; overflow:hidden;text-overflow:ellipsis; margin-right:10px; padding:0 5px; text-decoration:none}\n\n/*4.28 sortable拖动*/\n.ui-state-highlight{ height:50px; margin-top:20px;border:1px solid #fcefa1;background:#fbf9ee;color:#363636}\n.sortable-control{ cursor:move}\n\n/*4.29 ColorPicker 颜色控件*/\n\n\n/*5 页面\n\tName:\t\t\tpage\n*/\n\n/*5.1 错误页-404*/\n.page-404{ color:#afb5bf; padding-top:60px; padding-bottom:90px}\n.page-404 .error-title{font-size:80px}\n.page-404 .error-title .iconfont{font-size:80px}\n.page-404 .error-description{font-size:24px}\n.page-404 .error-info{font-size:14px}\n\n/*5.2 博客列表页*/\n.page-blog-list{}\n/*5.3 博客详情页*/\n.page-blog-show{}\n/*5.4 关于我们页*/\n.page-about-show{}\n/*5.5 帮助列表页*/\n.page-help-list{}\n/*5.6 帮助详情页*/\n.page-help-show{}\n/*5.7 友情链接页*/\n.page-flink{}\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui/css/H-ui.ie.css",
    "content": "/* -----------H-ui前端框架-------------\n* H-ui.ie.css v1.0\n* http://www.h-ui.net/\n* Created & Modified by guojunhui\n* Date modified 2016.05.02\n*\n* Copyright 2013-2016 北京颖杰联创科技有限公司 All rights reserved.\n* Licensed under MIT license.\n* http://opensource.org/licenses/MIT\n*\n*/\n@charset \"utf-8\";\n.navbar-fixed-top{ border-bottom:solid 1px #eee}\n.col-1,.col-2,.col-3,.col-4,.col-5,.col-6,.col-7,.col-8,.col-9,.col-10,.col-11,.col-12,.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12{ float:left}\n.col-md-12{width:100%}\n.col-md-11{width:91.66666666666666%}\n.col-md-10{width:83.33333333333334%}\n.col-md-9{width:75%}\n.col-md-8{width:66.66666666666666%}\n.col-md-7{width:58.333333333333336%}\n.col-md-6{width:50%}\n.col-md-5{width:41.66666666666667%}\n.col-md-4{width:33.33333333333333%}\n.col-md-3{width:25%}\n.col-md-2{width:16.666666666666664%}\n.col-md-1{width:8.333333333333332%}\n.col-md-pull-12{right:100%}\n.col-md-pull-11{right:91.66666666666666%}\n.col-md-pull-10{right:83.33333333333334%}\n.col-md-pull-9{right:75%}\n.col-md-pull-8{right:66.66666666666666%}\n.col-md-pull-7{right:58.333333333333336%}\n.col-md-pull-6{right:50%}\n.col-md-pull-5{right:41.66666666666667%}\n.col-md-pull-4{right:33.33333333333333%}\n.col-md-pull-3{right:25%}\n.col-md-pull-2{right:16.666666666666664%}\n.col-md-pull-1{right:8.333333333333332%}\n.col-md-pull-0{right:0}\n.col-md-push-12{left:100%}\n.col-md-push-11{left:91.66666666666666%}\n.col-md-push-10{left:83.33333333333334%}\n.col-md-push-9{left:75%}\n.col-md-push-8{left:66.66666666666666%}\n.col-md-push-7{left:58.333333333333336%}\n.col-md-push-6{left:50%}\n.col-md-push-5{left:41.66666666666667%}\n.col-md-push-4{left:33.33333333333333%}\n.col-md-push-3{left:25%}\n.col-md-push-2{left:16.666666666666664%}\n.col-md-push-1{left:8.333333333333332%}\n.col-md-push-0{left:0}\n.col-md-offset-12{margin-left:100%}\n.col-md-offset-11{margin-left:91.66666666666666%}\n.col-md-offset-10{margin-left:83.33333333333334%}\n.col-md-offset-9{margin-left:75%}\n.col-md-offset-8{margin-left:66.66666666666666%}\n.col-md-offset-7{margin-left:58.333333333333336%}\n.col-md-offset-6{margin-left:50%}\n.col-md-offset-5{margin-left:41.66666666666667%}\n.col-md-offset-4{margin-left:33.33333333333333%}\n.col-md-offset-3{margin-left:25%}\n.col-md-offset-2{margin-left:16.666666666666664%}\n.col-md-offset-1{margin-left:8.333333333333332%}\n.col-md-offset-0{margin-left:0}\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui/css/H-ui.reset.css",
    "content": "﻿@charset \"utf-8\";\n/* -----------H-ui前端框架-------------\n* H-ui.reset.css v1.2\t重定义浏览器默认样式\n* http://www.h-ui.net/\n* Created & Modified by guojunhui\n* Date modified 2014.10.09\n*\n* Copyright 2013-2015 北京颖杰联创科技有限公司 All rights reserved.\n* Licensed under MIT license.\n* http://opensource.org/licenses/MIT\n*\n*/\n/*1 重定义浏览器默认样式\n\tName:\t\t\tstyle_reset\n\tLevel:\t\t\tGlobal\n\tExplain:\t\t重定义浏览器默认样式\n\tLast Modify:\tjackying\n*/\n*{word-wrap:break-word}\nhtml,body,h1,h2,h3,h4,h5,h6,hr,p,iframe,dl,dt,dd,ul,ol,li,pre,form,button,input,textarea,th,td,fieldset{margin:0;padding:0}\nul,ol,dl{list-style-type:none}\nhtml,body{*position:static}\nhtml{font-family: sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}\naddress,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:400}\ninput,button,textarea,select,optgroup,option{font-family:inherit;font-size:inherit;font-style:inherit;font-weight:inherit}\ninput,button{overflow: visible;vertical-align:middle;outline:none}\nbody,th,td,button,input,select,textarea{font-family:\"Microsoft Yahei\",\"Hiragino Sans GB\",\"Helvetica Neue\",Helvetica,tahoma,arial,Verdana,sans-serif,\"WenQuanYi Micro Hei\",\"\\5B8B\\4F53\";font-size:12px;color: #333;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing:grayscale}\nbody{line-height:1.6}\nh1,h2,h3,h4,h5,h6{font-size:100%}\na,area{outline:none;blr:expression(this.onFocus=this.blur())}\na{text-decoration:none;cursor: pointer}\na:hover{text-decoration:underline;outline:none}\na.ie6:hover{zoom:1}\na:focus{outline:none}\na:hover,a:active{outline:none}:focus{outline:none}\nsub,sup{vertical-align:baseline}\nbutton,input[type=\"button\"], input[type=\"submit\"] {line-height:normal !important;}\n/*img*/\nimg{border:0;vertical-align:middle}\na img,img{-ms-interpolation-mode:bicubic}\n.img-responsive{max-width: 100%;height: auto}\n\n/*IE下a:hover 背景闪烁*/\n*html{overflow:-moz-scrollbars-vertical;zoom:expression(function(ele){ele.style.zoom = \"1\";document.execCommand(\"BackgroundImageCache\",false,true)}(this))}\n\n/*HTML5 reset*/\nheader,footer,section,aside,details,menu,article,section,nav,address,hgroup,figure,figcaption,legend{display:block;margin:0;padding:0}time{display:inline}\naudio,canvas,video{display:inline-block;*display:inline;*zoom:1}\naudio:not([controls]){display:none}\nlegend{width:100%;margin-bottom:20px;font-size:21px;line-height:40px;border:0;border-bottom:1px solid #e5e5e5}\nlegend small{font-size:15px;color:#999}\nsvg:not(:root) {overflow: hidden}\nfieldset {border-width:0;padding: 0.35em 0.625em 0.75em;margin: 0 2px;border: 1px solid #c0c0c0}\ninput[type=\"number\"]::-webkit-inner-spin-button,input[type=\"number\"]::-webkit-outer-spin-button {height: auto}\ninput[type=\"search\"] {-webkit-appearance: textfield; /* 1 */-moz-box-sizing: content-box;-webkit-box-sizing: content-box; /* 2 */box-sizing: content-box}\ninput[type=\"search\"]::-webkit-search-cancel-button,input[type=\"search\"]::-webkit-search-decoration {-webkit-appearance: none}\n/*\n\tName:\t\t\tstyle_clearfix\n\tExample:\t\tclass=\"clearfix|cl\"\n\tExplain:\t\tClearfix（简写cl）避免因子元素浮动而导致的父元素高度缺失能问题\n*/\n.cl:after,.clearfix:after{content:\".\";display:block;height:0;clear:both;visibility:hidden}.cl,.clearfix{zoom:1}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui/js/H-ui.js",
    "content": "/*-----------H-ui前端框架-------------\n* H-ui.js v3.1.3\n* http://www.h-ui.net/\n* Created & Modified by guojunhui\n* Date modified 2017.05.26\n*\n* Copyright 2013-2017 北京颖杰联创科技有限公司 All rights reserved.\n* Licensed under MIT license.\n* http://opensource.org/licenses/MIT\n*/\n/*\nIncludes：\njQuery.IEMobileHack.js\njQuery.cookie.js v1.4.1\njQuery.form.js v3.51.0\njQuery.lazyload.js v1.9.3\njQuery.responsive-nav.js v1.0.39\njQuery.placeholder.js\njQuery.emailsuggest.js v1.0\njQuery.format.js\njQuery.togglePassword.js\njQuery.iCheck.js\njQuery.raty.js v2.4.5\njQuery.onePageNav.js\njQuery.stickUp.js\njQuery.ColorPicker.js\n\njQuery.HuiaddFavorite.js\njQuery.Huisethome.js\njQuery.Huisidenav.js\njQuery.Huihover.js v2.0\njQuery.Huifocusblur.js V2.0\njQuery.Huiselect.js\njQuery.Huitab.js v2.0\njQuery.Huifold.js v2.0\njQuery.Huitags.js v2.0\njQuery.Huitagsmixed.js\njQuery.Huitextarealength.js v2.0\njQuery.Huipreview.js v2.0\njQuery.Huimodalalert.js\njQuery.Huialert.js\njQuery.Huitotop.js v2.0\njQuery.Huimarquee.js\njQuery.Huispinner.js v2.0\n\nBootstrap.modal.js v3.3.0\nBootstrap.dropdown.js v3.3.0\nBootstrap.transition.js v3.3.0\nBootstrap.tooltip.js v3.3.0\nBootstrap.popover.js v3.3.0\nBootstrap.alert.js v3.3.0\nBootstrap.slider.js v1.0.1\nBootstrap.datetimepicker.js\nBootstrap.Switch v1.3\n\n*/\n/* =======================================================================\n * jQuery.IEMobileHack.js判断浏览器\n * ======================================================================== */\n!function(){\n\tif (navigator.userAgent.match(/IEMobile\\/10\\.0/)) {\n\t\tvar msViewportStyle = document.createElement(\"style\");\n\t\tmsViewportStyle.appendChild(\n\t\t\tdocument.createTextNode(\n\t\t\t\t\"@-ms-viewport{width:auto!important}\"\n\t\t\t)\n\t\t);\n\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(msViewportStyle);\n\t}\n} ();\n\n/* =======================================================================\n * jQuery.stopDefault.js 阻止默认浏览器动作\n * ======================================================================== */\nfunction stopDefault(e) {\n\tif (e && e.preventDefault) e.preventDefault();\n\t//IE中阻止函数器默认动作的方式\n\telse window.event.returnValue = false;\n\treturn false;\n}\n\n/* =======================================================================\n * jQuery.cookie.js v1.4.1\n * https://github.com/carhartl/jQuery-cookie\n *\n * Copyright 2006, 2014 Klaus Hartl\n * Released under the MIT license\n * ======================================================================== */\n!(function(factory) {\n\tif (typeof define === 'function' && define.amd) {\n\t\t// AMD (Register as an anonymous module)\n\t\tdefine(['jquery'], factory);\n\t} else if (typeof exports === 'object') {\n\t\t// Node/CommonJS\n\t\tmodule.exports = factory(require('jquery'));\n\t} else {\n\t\t// Browser globals\n\t\tfactory(jQuery);\n\t}\n}\n(function($){\n\tvar pluses = /\\+/g;\n\tfunction encode(s) {\n\t\treturn config.raw ? s : encodeURIComponent(s);\n\t}\n\tfunction decode(s) {\n\t\treturn config.raw ? s : decodeURIComponent(s);\n\t}\n\tfunction stringifyCookieValue(value) {\n\t\treturn encode(config.json ? JSON.stringify(value) : String(value));\n\t}\n\tfunction parseCookieValue(s) {\n\t\tif (s.indexOf('\"') === 0) {\n\t\t\t// This is a quoted cookie as according to RFC2068, unescape...\n\t\t\ts = s.slice(1, -1).replace(/\\\\\"/g, '\"').replace(/\\\\\\\\/g, '\\\\');\n\t\t}\n\n\t\ttry {\n\t\t\t// Replace server-side written pluses with spaces.\n\t\t\t// If we can't decode the cookie, ignore it, it's unusable.\n\t\t\t// If we can't parse the cookie, ignore it, it's unusable.\n\t\t\ts = decodeURIComponent(s.replace(pluses, ' '));\n\t\t\treturn config.json ? JSON.parse(s) : s;\n\t\t} catch(e) {}\n\t}\n\tfunction read(s, converter) {\n\t\tvar value = config.raw ? s: parseCookieValue(s);\n\t\treturn $.isFunction(converter) ? converter(value) : value;\n\t}\n\tvar config = $.cookie = function(key, value, options) {\n\t\t// Write\n\t\tif (arguments.length > 1 && !$.isFunction(value)) {\n\t\t\toptions = $.extend({},\n\t\t\tconfig.defaults, options);\n\n\t\t\tif (typeof options.expires === 'number') {\n\t\t\t\tvar days = options.expires,\n\t\t\t\tt = options.expires = new Date();\n\t\t\t\tt.setMilliseconds(t.getMilliseconds() + days * 864e+5);\n\t\t\t}\n\n\t\t\treturn (document.cookie = [encode(key), '=', stringifyCookieValue(value), options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE\n\t\t\toptions.path ? '; path=' + options.path: '', options.domain ? '; domain=' + options.domain: '', options.secure ? '; secure': ''].join(''));\n\t\t}\n\t\t// Read\n\t\tvar result = key ? undefined: {},\n\t\t// To prevent the for loop in the first place assign an empty array\n\t\t// in case there are no cookies at all. Also prevents odd result when\n\t\t// calling $.cookie().\n\t\tcookies = document.cookie ? document.cookie.split('; ') : [],\n\t\ti = 0,\n\t\tl = cookies.length;\n\t\tfor (; i < l; i++) {\n\t\t\tvar parts = cookies[i].split('='),\n\t\t\tname = decode(parts.shift()),\n\t\t\tcookie = parts.join('=');\n\t\t\tif (key === name) {\n\t\t\t\t// If second argument (value) is a function it's a converter...\n\t\t\t\tresult = read(cookie, value);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// Prevent storing a cookie that we couldn't decode.\n\t\t\tif (!key && (cookie = read(cookie)) !== undefined) {\n\t\t\t\tresult[name] = cookie;\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t};\n\tconfig.defaults = {};\n\t$.removeCookie = function(key, options) {\n\t\t// Must not alter options, thus extending a fresh object...\n\t\t$.cookie(key, '', $.extend({},\n\t\toptions, {\n\t\t\texpires: -1\n\t\t}));\n\t\treturn ! $.cookie(key);\n\t};\n}));\n\n/* =======================================================================\n * jQuery.form.js Plugin v3.51.0 2014.06.20\n * Requires jQuery v1.5 or later\n * Copyright (c) 2014 M. Alsup\n * Examples and documentation at: http://malsup.com/jquery/form/\n * Project repositories: https://github.com/malsup/form\n * Dual licensed under the MIT and GPL licenses.\n * https://github.com/malsup/form#copyright-and-license\n * ======================================================================== */\n// AMD support\n(function(factory) {\n\t\"use strict\";\n\tif (typeof define === 'function' && define.amd) {\n\t\t// using AMD; register as anon module\n\t\tdefine(['jquery'], factory);\n\t} else {\n\t\t// no AMD; invoke directly\n\t\tfactory((typeof(jQuery) != 'undefined') ? jQuery: window.Zepto);\n\t}\n} (function($) {\n\t\"use strict\";\n\t/*\n\t\t\tUsage Note:\n\t\t\t-----------\n\t\t\tDo not use both ajaxSubmit and ajaxForm on the same form.  These\n\t\t\tfunctions are mutually exclusive.  Use ajaxSubmit if you want\n\t\t\tto bind your own submit handler to the form.  For example,\n\n\t\t\t$(document).ready(function() {\n\t\t\t\t$('#myForm').on('submit', function(e) {\n\t\t\t\t\te.preventDefault(); // <-- important\n\t\t\t\t\t$(this).ajaxSubmit({\n\t\t\t\t\t\ttarget: '#output'\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tUse ajaxForm when you want the plugin to manage all the event binding\n\t\t\tfor you.  For example,\n\n\t\t\t$(document).ready(function() {\n\t\t\t\t$('#myForm').ajaxForm({\n\t\t\t\t\ttarget: '#output'\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tYou can also use ajaxForm with delegation (requires jQuery v1.7+), so the\n\t\t\tform does not have to exist when you invoke ajaxForm:\n\n\t\t\t$('#myForm').ajaxForm({\n\t\t\t\tdelegation: true,\n\t\t\t\ttarget: '#output'\n\t\t\t});\n\n\t\t\tWhen using ajaxForm, the ajaxSubmit function will be invoked for you\n\t\t\tat the appropriate time.\n\t\t*/\n\t/**\n\t\t * Feature detection\n\t\t */\n\tvar feature = {};\n\tfeature.fileapi = $(\"<input type='file'/>\").get(0).files !== undefined;\n\tfeature.formdata = window.FormData !== undefined;\n\tvar hasProp = !!$.fn.prop;\n\t// attr2 uses prop when it can but checks the return type for\n\t// an expected string.  this accounts for the case where a form\n\t// contains inputs with names like \"action\" or \"method\"; in those\n\t// cases \"prop\" returns the element\n\t$.fn.attr2 = function() {\n\t\tif (!hasProp) {\n\t\t\treturn this.attr.apply(this, arguments);\n\t\t}\n\t\tvar val = this.prop.apply(this, arguments);\n\t\tif ((val && val.jquery) || typeof val === 'string') {\n\t\t\treturn val;\n\t\t}\n\t\treturn this.attr.apply(this, arguments);\n\t};\n\n\t/**\n\t\t * ajaxSubmit() provides a mechanism for immediately submitting\n\t\t * an HTML form using AJAX.\n\t\t */\n\t$.fn.ajaxSubmit = function(options) {\n\t\t/*jshint scripturl:true */\n\t\t// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)\n\t\tif (!this.length) {\n\t\t\tlog('ajaxSubmit: skipping submit process - no element selected');\n\t\t\treturn this;\n\t\t}\n\t\tvar method, action, url, $form = this;\n\t\tif (typeof options == 'function') {\n\t\t\toptions = {\n\t\t\t\tsuccess: options\n\t\t\t};\n\t\t} else if (options === undefined) {\n\t\t\toptions = {};\n\t\t}\n\t\tmethod = options.type || this.attr2('method');\n\t\taction = options.url || this.attr2('action');\n\t\turl = (typeof action === 'string') ? $.trim(action) : '';\n\t\turl = url || window.location.href || '';\n\t\tif (url) {\n\t\t\t// clean url (don't include hash vaue)\n\t\t\turl = (url.match(/^([^#]+)/) || [])[1];\n\t\t}\n\n\t\toptions = $.extend(true, {\n\t\t\turl: url,\n\t\t\tsuccess: $.ajaxSettings.success,\n\t\t\ttype: method || $.ajaxSettings.type,\n\t\t\tiframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false': 'about:blank'\n\t\t},\n\t\toptions);\n\n\t\t// hook for manipulating the form data before it is extracted;\n\t\t// convenient for use with rich editors like tinyMCE or FCKEditor\n\t\tvar veto = {};\n\t\tthis.trigger('form-pre-serialize', [this, options, veto]);\n\t\tif (veto.veto) {\n\t\t\tlog('ajaxSubmit: submit vetoed via form-pre-serialize trigger');\n\t\t\treturn this;\n\t\t}\n\n\t\t// provide opportunity to alter form data before it is serialized\n\t\tif (options.beforeSerialize && options.beforeSerialize(this, options) === false) {\n\t\t\tlog('ajaxSubmit: submit aborted via beforeSerialize callback');\n\t\t\treturn this;\n\t\t}\n\n\t\tvar traditional = options.traditional;\n\t\tif (traditional === undefined) {\n\t\t\ttraditional = $.ajaxSettings.traditional;\n\t\t}\n\n\t\tvar elements = [];\n\t\tvar qx, a = this.formToArray(options.semantic, elements);\n\t\tif (options.data) {\n\t\t\toptions.extraData = options.data;\n\t\t\tqx = $.param(options.data, traditional);\n\t\t}\n\n\t\t// give pre-submit callback an opportunity to abort the submit\n\t\tif (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {\n\t\t\tlog('ajaxSubmit: submit aborted via beforeSubmit callback');\n\t\t\treturn this;\n\t\t}\n\n\t\t// fire vetoable 'validate' event\n\t\tthis.trigger('form-submit-validate', [a, this, options, veto]);\n\t\tif (veto.veto) {\n\t\t\tlog('ajaxSubmit: submit vetoed via form-submit-validate trigger');\n\t\t\treturn this;\n\t\t}\n\n\t\tvar q = $.param(a, traditional);\n\t\tif (qx) {\n\t\t\tq = (q ? (q + '&' + qx) : qx);\n\t\t}\n\t\tif (options.type.toUpperCase() == 'GET') {\n\t\t\toptions.url += (options.url.indexOf('?') >= 0 ? '&': '?') + q;\n\t\t\toptions.data = null; // data is null for 'get'\n\t\t} else {\n\t\t\toptions.data = q; // data is the query string for 'post'\n\t\t}\n\n\t\tvar callbacks = [];\n\t\tif (options.resetForm) {\n\t\t\tcallbacks.push(function() {\n\t\t\t\t$form.resetForm();\n\t\t\t});\n\t\t}\n\t\tif (options.clearForm) {\n\t\t\tcallbacks.push(function() {\n\t\t\t\t$form.clearForm(options.includeHidden);\n\t\t\t});\n\t\t}\n\n\t\t// perform a load on the target only if dataType is not provided\n\t\tif (!options.dataType && options.target) {\n\t\t\tvar oldSuccess = options.success ||\n\t\t\tfunction() {};\n\t\t\tcallbacks.push(function(data) {\n\t\t\t\tvar fn = options.replaceTarget ? 'replaceWith': 'html';\n\t\t\t\t$(options.target)[fn](data).each(oldSuccess, arguments);\n\t\t\t});\n\t\t} else if (options.success) {\n\t\t\tcallbacks.push(options.success);\n\t\t}\n\n\t\toptions.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg\n\t\t\tvar context = options.context || this; // jQuery 1.4+ supports scope context\n\t\t\tfor (var i = 0,\n\t\t\tmax = callbacks.length; i < max; i++) {\n\t\t\t\tcallbacks[i].apply(context, [data, status, xhr || $form, $form]);\n\t\t\t}\n\t\t};\n\n\t\tif (options.error) {\n\t\t\tvar oldError = options.error;\n\t\t\toptions.error = function(xhr, status, error) {\n\t\t\t\tvar context = options.context || this;\n\t\t\t\toldError.apply(context, [xhr, status, error, $form]);\n\t\t\t};\n\t\t}\n\n\t\tif (options.complete) {\n\t\t\tvar oldComplete = options.complete;\n\t\t\toptions.complete = function(xhr, status) {\n\t\t\t\tvar context = options.context || this;\n\t\t\t\toldComplete.apply(context, [xhr, status, $form]);\n\t\t\t};\n\t\t}\n\n\t\t// are there files to upload?\n\t\t// [value] (issue #113), also see comment:\n\t\t// https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219\n\t\tvar fileInputs = $('input[type=file]:enabled', this).filter(function() {\n\t\t\treturn $(this).val() !== '';\n\t\t});\n\n\t\tvar hasFileInputs = fileInputs.length > 0;\n\t\tvar mp = 'multipart/form-data';\n\t\tvar multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);\n\n\t\tvar fileAPI = feature.fileapi && feature.formdata;\n\t\tlog(\"fileAPI :\" + fileAPI);\n\t\tvar shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;\n\n\t\tvar jqxhr;\n\n\t\t// options.iframe allows user to force iframe mode\n\t\t// 06-NOV-09: now defaulting to iframe mode if file input is detected\n\t\tif (options.iframe !== false && (options.iframe || shouldUseFrame)) {\n\t\t\t// hack to fix Safari hang (thanks to Tim Molendijk for this)\n\t\t\t// see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d\n\t\t\tif (options.closeKeepAlive) {\n\t\t\t\t$.get(options.closeKeepAlive,\n\t\t\t\tfunction() {\n\t\t\t\t\tjqxhr = fileUploadIframe(a);\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tjqxhr = fileUploadIframe(a);\n\t\t\t}\n\t\t} else if ((hasFileInputs || multipart) && fileAPI) {\n\t\t\tjqxhr = fileUploadXhr(a);\n\t\t} else {\n\t\t\tjqxhr = $.ajax(options);\n\t\t}\n\n\t\t$form.removeData('jqxhr').data('jqxhr', jqxhr);\n\n\t\t// clear element array\n\t\tfor (var k = 0; k < elements.length; k++) {\n\t\t\telements[k] = null;\n\t\t}\n\n\t\t// fire 'notify' event\n\t\tthis.trigger('form-submit-notify', [this, options]);\n\t\treturn this;\n\n\t\t// utility fn for deep serialization\n\t\tfunction deepSerialize(extraData) {\n\t\t\tvar serialized = $.param(extraData, options.traditional).split('&');\n\t\t\tvar len = serialized.length;\n\t\t\tvar result = [];\n\t\t\tvar i, part;\n\t\t\tfor (i = 0; i < len; i++) {\n\t\t\t\t// #252; undo param space replacement\n\t\t\t\tserialized[i] = serialized[i].replace(/\\+/g, ' ');\n\t\t\t\tpart = serialized[i].split('=');\n\t\t\t\t// #278; use array instead of object storage, favoring array serializations\n\t\t\t\tresult.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\n\t\t// XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)\n\t\tfunction fileUploadXhr(a) {\n\t\t\tvar formdata = new FormData();\n\n\t\t\tfor (var i = 0; i < a.length; i++) {\n\t\t\t\tformdata.append(a[i].name, a[i].value);\n\t\t\t}\n\n\t\t\tif (options.extraData) {\n\t\t\t\tvar serializedData = deepSerialize(options.extraData);\n\t\t\t\tfor (i = 0; i < serializedData.length; i++) {\n\t\t\t\t\tif (serializedData[i]) {\n\t\t\t\t\t\tformdata.append(serializedData[i][0], serializedData[i][1]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toptions.data = null;\n\n\t\t\tvar s = $.extend(true, {},\n\t\t\t$.ajaxSettings, options, {\n\t\t\t\tcontentType: false,\n\t\t\t\tprocessData: false,\n\t\t\t\tcache: false,\n\t\t\t\ttype: method || 'POST'\n\t\t\t});\n\n\t\t\tif (options.uploadProgress) {\n\t\t\t\t// workaround because jqXHR does not expose upload property\n\t\t\t\ts.xhr = function() {\n\t\t\t\t\tvar xhr = $.ajaxSettings.xhr();\n\t\t\t\t\tif (xhr.upload) {\n\t\t\t\t\t\txhr.upload.addEventListener('progress',\n\t\t\t\t\t\tfunction(event) {\n\t\t\t\t\t\t\tvar percent = 0;\n\t\t\t\t\t\t\tvar position = event.loaded || event.position;\n\t\t\t\t\t\t\t/*event.position is deprecated*/\n\t\t\t\t\t\t\tvar total = event.total;\n\t\t\t\t\t\t\tif (event.lengthComputable) {\n\t\t\t\t\t\t\t\tpercent = Math.ceil(position / total * 100);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\toptions.uploadProgress(event, position, total, percent);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfalse);\n\t\t\t\t\t}\n\t\t\t\t\treturn xhr;\n\t\t\t\t};\n\t\t\t}\n\n\t\t\ts.data = null;\n\t\t\tvar beforeSend = s.beforeSend;\n\t\t\ts.beforeSend = function(xhr, o) {\n\t\t\t\t//Send FormData() provided by user\n\t\t\t\tif (options.formData) {\n\t\t\t\t\to.data = options.formData;\n\t\t\t\t} else {\n\t\t\t\t\to.data = formdata;\n\t\t\t\t}\n\t\t\t\tif (beforeSend) {\n\t\t\t\t\tbeforeSend.call(this, xhr, o);\n\t\t\t\t}\n\t\t\t};\n\t\t\treturn $.ajax(s);\n\t\t}\n\n\t\t// private function for handling file uploads (hat tip to YAHOO!)\n\t\tfunction fileUploadIframe(a) {\n\t\t\tvar form = $form[0],\n\t\t\tel,\n\t\t\ti,\n\t\t\ts,\n\t\t\tg,\n\t\t\tid,\n\t\t\t$io,\n\t\t\tio,\n\t\t\txhr,\n\t\t\tsub,\n\t\t\tn,\n\t\t\ttimedOut,\n\t\t\ttimeoutHandle;\n\t\t\tvar deferred = $.Deferred();\n\n\t\t\t// #341\n\t\t\tdeferred.abort = function(status) {\n\t\t\t\txhr.abort(status);\n\t\t\t};\n\n\t\t\tif (a) {\n\t\t\t\t// ensure that every serialized input is still enabled\n\t\t\t\tfor (i = 0; i < elements.length; i++) {\n\t\t\t\t\tel = $(elements[i]);\n\t\t\t\t\tif (hasProp) {\n\t\t\t\t\t\tel.prop('disabled', false);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tel.removeAttr('disabled');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ts = $.extend(true, {},\n\t\t\t$.ajaxSettings, options);\n\t\t\ts.context = s.context || s;\n\t\t\tid = 'jqFormIO' + (new Date().getTime());\n\t\t\tif (s.iframeTarget) {\n\t\t\t\t$io = $(s.iframeTarget);\n\t\t\t\tn = $io.attr2('name');\n\t\t\t\tif (!n) {\n\t\t\t\t\t$io.attr2('name', id);\n\t\t\t\t} else {\n\t\t\t\t\tid = n;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$io = $('<iframe name=\"' + id + '\" src=\"' + s.iframeSrc + '\" />');\n\t\t\t\t$io.css({\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\ttop: '-1000px',\n\t\t\t\t\tleft: '-1000px'\n\t\t\t\t});\n\t\t\t}\n\t\t\tio = $io[0];\n\n\t\t\txhr = { // mock object\n\t\t\t\taborted: 0,\n\t\t\t\tresponseText: null,\n\t\t\t\tresponseXML: null,\n\t\t\t\tstatus: 0,\n\t\t\t\tstatusText: 'n/a',\n\t\t\t\tgetAllResponseHeaders: function() {},\n\t\t\t\tgetResponseHeader: function() {},\n\t\t\t\tsetRequestHeader: function() {},\n\t\t\t\tabort: function(status) {\n\t\t\t\t\tvar e = (status === 'timeout' ? 'timeout': 'aborted');\n\t\t\t\t\tlog('aborting upload... ' + e);\n\t\t\t\t\tthis.aborted = 1;\n\n\t\t\t\t\ttry { // #214, #257\n\t\t\t\t\t\tif (io.contentWindow.document.execCommand) {\n\t\t\t\t\t\t\tio.contentWindow.document.execCommand('Stop');\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch(ignore) {}\n\n\t\t\t\t\t$io.attr('src', s.iframeSrc); // abort op in progress\n\t\t\t\t\txhr.error = e;\n\t\t\t\t\tif (s.error) {\n\t\t\t\t\t\ts.error.call(s.context, xhr, e, status);\n\t\t\t\t\t}\n\t\t\t\t\tif (g) {\n\t\t\t\t\t\t$.event.trigger(\"ajaxError\", [xhr, s, e]);\n\t\t\t\t\t}\n\t\t\t\t\tif (s.complete) {\n\t\t\t\t\t\ts.complete.call(s.context, xhr, e);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tg = s.global;\n\t\t\t// trigger ajax global events so that activity/block indicators work like normal\n\t\t\tif (g && 0 === $.active++) {\n\t\t\t\t$.event.trigger(\"ajaxStart\");\n\t\t\t}\n\t\t\tif (g) {\n\t\t\t\t$.event.trigger(\"ajaxSend\", [xhr, s]);\n\t\t\t}\n\n\t\t\tif (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {\n\t\t\t\tif (s.global) {\n\t\t\t\t\t$.active--;\n\t\t\t\t}\n\t\t\t\tdeferred.reject();\n\t\t\t\treturn deferred;\n\t\t\t}\n\t\t\tif (xhr.aborted) {\n\t\t\t\tdeferred.reject();\n\t\t\t\treturn deferred;\n\t\t\t}\n\n\t\t\t// add submitting element to data if we know it\n\t\t\tsub = form.clk;\n\t\t\tif (sub) {\n\t\t\t\tn = sub.name;\n\t\t\t\tif (n && !sub.disabled) {\n\t\t\t\t\ts.extraData = s.extraData || {};\n\t\t\t\t\ts.extraData[n] = sub.value;\n\t\t\t\t\tif (sub.type == \"image\") {\n\t\t\t\t\t\ts.extraData[n + '.x'] = form.clk_x;\n\t\t\t\t\t\ts.extraData[n + '.y'] = form.clk_y;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar CLIENT_TIMEOUT_ABORT = 1;\n\t\t\tvar SERVER_ABORT = 2;\n\n\t\t\tfunction getDoc(frame) {\n\t\t\t\t/* it looks like contentWindow or contentDocument do not\n\t\t\t\t\t * carry the protocol property in ie8, when running under ssl\n\t\t\t\t\t * frame.document is the only valid response document, since\n\t\t\t\t\t * the protocol is know but not on the other two objects. strange?\n\t\t\t\t\t * \"Same origin policy\" http://en.wikipedia.org/wiki/Same_origin_policy\n\t\t\t\t\t */\n\n\t\t\t\tvar doc = null;\n\n\t\t\t\t// IE8 cascading access check\n\t\t\t\ttry {\n\t\t\t\t\tif (frame.contentWindow) {\n\t\t\t\t\t\tdoc = frame.contentWindow.document;\n\t\t\t\t\t}\n\t\t\t\t} catch(err) {\n\t\t\t\t\t// IE8 access denied under ssl & missing protocol\n\t\t\t\t\tlog('cannot get iframe.contentWindow document: ' + err);\n\t\t\t\t}\n\n\t\t\t\tif (doc) { // successful getting content\n\t\t\t\t\treturn doc;\n\t\t\t\t}\n\n\t\t\t\ttry { // simply checking may throw in ie8 under ssl or mismatched protocol\n\t\t\t\t\tdoc = frame.contentDocument ? frame.contentDocument: frame.document;\n\t\t\t\t} catch(err) {\n\t\t\t\t\t// last attempt\n\t\t\t\t\tlog('cannot get iframe.contentDocument: ' + err);\n\t\t\t\t\tdoc = frame.document;\n\t\t\t\t}\n\t\t\t\treturn doc;\n\t\t\t}\n\n\t\t\t// Rails CSRF hack (thanks to Yvan Barthelemy)\n\t\t\tvar csrf_token = $('meta[name=csrf-token]').attr('content');\n\t\t\tvar csrf_param = $('meta[name=csrf-param]').attr('content');\n\t\t\tif (csrf_param && csrf_token) {\n\t\t\t\ts.extraData = s.extraData || {};\n\t\t\t\ts.extraData[csrf_param] = csrf_token;\n\t\t\t}\n\n\t\t\t// take a breath so that pending repaints get some cpu time before the upload starts\n\t\t\tfunction doSubmit() {\n\t\t\t\t// make sure form attrs are set\n\t\t\t\tvar t = $form.attr2('target'),\n\t\t\t\ta = $form.attr2('action'),\n\t\t\t\tmp = 'multipart/form-data',\n\t\t\t\tet = $form.attr('enctype') || $form.attr('encoding') || mp;\n\n\t\t\t\t// update form attrs in IE friendly way\n\t\t\t\tform.setAttribute('target', id);\n\t\t\t\tif (!method || /post/i.test(method)) {\n\t\t\t\t\tform.setAttribute('method', 'POST');\n\t\t\t\t}\n\t\t\t\tif (a != s.url) {\n\t\t\t\t\tform.setAttribute('action', s.url);\n\t\t\t\t}\n\n\t\t\t\t// ie borks in some cases when setting encoding\n\t\t\t\tif (!s.skipEncodingOverride && (!method || /post/i.test(method))) {\n\t\t\t\t\t$form.attr({\n\t\t\t\t\t\tencoding: 'multipart/form-data',\n\t\t\t\t\t\tenctype: 'multipart/form-data'\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// support timout\n\t\t\t\tif (s.timeout) {\n\t\t\t\t\ttimeoutHandle = setTimeout(function() {\n\t\t\t\t\t\ttimedOut = true;\n\t\t\t\t\t\tcb(CLIENT_TIMEOUT_ABORT);\n\t\t\t\t\t},\n\t\t\t\t\ts.timeout);\n\t\t\t\t}\n\n\t\t\t\t// look for server aborts\n\t\t\t\tfunction checkState() {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tvar state = getDoc(io).readyState;\n\t\t\t\t\t\tlog('state = ' + state);\n\t\t\t\t\t\tif (state && state.toLowerCase() == 'uninitialized') {\n\t\t\t\t\t\t\tsetTimeout(checkState, 50);\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\tlog('Server abort: ', e, ' (', e.name, ')');\n\t\t\t\t\t\tcb(SERVER_ABORT);\n\t\t\t\t\t\tif (timeoutHandle) {\n\t\t\t\t\t\t\tclearTimeout(timeoutHandle);\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttimeoutHandle = undefined;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// add \"extra\" data to form if provided in options\n\t\t\t\tvar extraInputs = [];\n\t\t\t\ttry {\n\t\t\t\t\tif (s.extraData) {\n\t\t\t\t\t\tfor (var n in s.extraData) {\n\t\t\t\t\t\t\tif (s.extraData.hasOwnProperty(n)) {\n\t\t\t\t\t\t\t\t// if using the $.param format that allows for multiple values with the same name\n\t\t\t\t\t\t\t\tif ($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {\n\t\t\t\t\t\t\t\t\textraInputs.push($('<input type=\"hidden\" name=\"' + s.extraData[n].name + '\">').val(s.extraData[n].value).appendTo(form)[0]);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\textraInputs.push($('<input type=\"hidden\" name=\"' + n + '\">').val(s.extraData[n]).appendTo(form)[0]);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!s.iframeTarget) {\n\t\t\t\t\t\t// add iframe to doc and submit the form\n\t\t\t\t\t\t$io.appendTo('body');\n\t\t\t\t\t}\n\t\t\t\t\tif (io.attachEvent) {\n\t\t\t\t\t\tio.attachEvent('onload', cb);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tio.addEventListener('load', cb, false);\n\t\t\t\t\t}\n\t\t\t\t\tsetTimeout(checkState, 15);\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tform.submit();\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\t// just in case form has element with name/id of 'submit'\n\t\t\t\t\t\tvar submitFn = document.createElement('form').submit;\n\t\t\t\t\t\tsubmitFn.apply(form);\n\t\t\t\t\t}\n\t\t\t\t} finally {\n\t\t\t\t\t// reset attrs and remove \"extra\" input elements\n\t\t\t\t\tform.setAttribute('action', a);\n\t\t\t\t\tform.setAttribute('enctype', et); // #380\n\t\t\t\t\tif (t) {\n\t\t\t\t\t\tform.setAttribute('target', t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$form.removeAttr('target');\n\t\t\t\t\t}\n\t\t\t\t\t$(extraInputs).remove();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (s.forceSync) {\n\t\t\t\tdoSubmit();\n\t\t\t} else {\n\t\t\t\tsetTimeout(doSubmit, 10); // this lets dom updates render\n\t\t\t}\n\n\t\t\tvar data, doc, domCheckCount = 50,\n\t\t\tcallbackProcessed;\n\n\t\t\tfunction cb(e) {\n\t\t\t\tif (xhr.aborted || callbackProcessed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tdoc = getDoc(io);\n\t\t\t\tif (!doc) {\n\t\t\t\t\tlog('cannot access response document');\n\t\t\t\t\te = SERVER_ABORT;\n\t\t\t\t}\n\t\t\t\tif (e === CLIENT_TIMEOUT_ABORT && xhr) {\n\t\t\t\t\txhr.abort('timeout');\n\t\t\t\t\tdeferred.reject(xhr, 'timeout');\n\t\t\t\t\treturn;\n\t\t\t\t} else if (e == SERVER_ABORT && xhr) {\n\t\t\t\t\txhr.abort('server abort');\n\t\t\t\t\tdeferred.reject(xhr, 'error', 'server abort');\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (!doc || doc.location.href == s.iframeSrc) {\n\t\t\t\t\t// response not received yet\n\t\t\t\t\tif (!timedOut) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (io.detachEvent) {\n\t\t\t\t\tio.detachEvent('onload', cb);\n\t\t\t\t} else {\n\t\t\t\t\tio.removeEventListener('load', cb, false);\n\t\t\t\t}\n\n\t\t\t\tvar status = 'success',\n\t\t\t\terrMsg;\n\t\t\t\ttry {\n\t\t\t\t\tif (timedOut) {\n\t\t\t\t\t\tthrow 'timeout';\n\t\t\t\t\t}\n\n\t\t\t\t\tvar isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);\n\t\t\t\t\tlog('isXml=' + isXml);\n\t\t\t\t\tif (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {\n\t\t\t\t\t\tif (--domCheckCount) {\n\t\t\t\t\t\t\t// in some browsers (Opera) the iframe DOM is not always traversable when\n\t\t\t\t\t\t\t// the onload callback fires, so we loop a bit to accommodate\n\t\t\t\t\t\t\tlog('requeing onLoad callback, DOM not available');\n\t\t\t\t\t\t\tsetTimeout(cb, 250);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// let this fall through because server response could be an empty document\n\t\t\t\t\t\t//log('Could not access iframe DOM after mutiple tries.');\n\t\t\t\t\t\t//throw 'DOMException: not available';\n\t\t\t\t\t}\n\n\t\t\t\t\t//log('response detected');\n\t\t\t\t\tvar docRoot = doc.body ? doc.body: doc.documentElement;\n\t\t\t\t\txhr.responseText = docRoot ? docRoot.innerHTML: null;\n\t\t\t\t\txhr.responseXML = doc.XMLDocument ? doc.XMLDocument: doc;\n\t\t\t\t\tif (isXml) {\n\t\t\t\t\t\ts.dataType = 'xml';\n\t\t\t\t\t}\n\t\t\t\t\txhr.getResponseHeader = function(header) {\n\t\t\t\t\t\tvar headers = {\n\t\t\t\t\t\t\t'content-type': s.dataType\n\t\t\t\t\t\t};\n\t\t\t\t\t\treturn headers[header.toLowerCase()];\n\t\t\t\t\t};\n\t\t\t\t\t// support for XHR 'status' & 'statusText' emulation :\n\t\t\t\t\tif (docRoot) {\n\t\t\t\t\t\txhr.status = Number(docRoot.getAttribute('status')) || xhr.status;\n\t\t\t\t\t\txhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar dt = (s.dataType || '').toLowerCase();\n\t\t\t\t\tvar scr = /(json|script|text)/.test(dt);\n\t\t\t\t\tif (scr || s.textarea) {\n\t\t\t\t\t\t// see if user embedded response in textarea\n\t\t\t\t\t\tvar ta = doc.getElementsByTagName('textarea')[0];\n\t\t\t\t\t\tif (ta) {\n\t\t\t\t\t\t\txhr.responseText = ta.value;\n\t\t\t\t\t\t\t// support for XHR 'status' & 'statusText' emulation :\n\t\t\t\t\t\t\txhr.status = Number(ta.getAttribute('status')) || xhr.status;\n\t\t\t\t\t\t\txhr.statusText = ta.getAttribute('statusText') || xhr.statusText;\n\t\t\t\t\t\t} else if (scr) {\n\t\t\t\t\t\t\t// account for browsers injecting pre around json response\n\t\t\t\t\t\t\tvar pre = doc.getElementsByTagName('pre')[0];\n\t\t\t\t\t\t\tvar b = doc.getElementsByTagName('body')[0];\n\t\t\t\t\t\t\tif (pre) {\n\t\t\t\t\t\t\t\txhr.responseText = pre.textContent ? pre.textContent: pre.innerText;\n\t\t\t\t\t\t\t} else if (b) {\n\t\t\t\t\t\t\t\txhr.responseText = b.textContent ? b.textContent: b.innerText;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {\n\t\t\t\t\t\txhr.responseXML = toXml(xhr.responseText);\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tdata = httpData(xhr, dt, s);\n\t\t\t\t\t} catch(err) {\n\t\t\t\t\t\tstatus = 'parsererror';\n\t\t\t\t\t\txhr.error = errMsg = (err || status);\n\t\t\t\t\t}\n\t\t\t\t} catch(err) {\n\t\t\t\t\tlog('error caught: ', err);\n\t\t\t\t\tstatus = 'error';\n\t\t\t\t\txhr.error = errMsg = (err || status);\n\t\t\t\t}\n\n\t\t\t\tif (xhr.aborted) {\n\t\t\t\t\tlog('upload aborted');\n\t\t\t\t\tstatus = null;\n\t\t\t\t}\n\n\t\t\t\tif (xhr.status) { // we've set xhr.status\n\t\t\t\t\tstatus = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success': 'error';\n\t\t\t\t}\n\n\t\t\t\t// ordering of these callbacks/triggers is odd, but that's how $.ajax does it\n\t\t\t\tif (status === 'success') {\n\t\t\t\t\tif (s.success) {\n\t\t\t\t\t\ts.success.call(s.context, data, 'success', xhr);\n\t\t\t\t\t}\n\t\t\t\t\tdeferred.resolve(xhr.responseText, 'success', xhr);\n\t\t\t\t\tif (g) {\n\t\t\t\t\t\t$.event.trigger(\"ajaxSuccess\", [xhr, s]);\n\t\t\t\t\t}\n\t\t\t\t} else if (status) {\n\t\t\t\t\tif (errMsg === undefined) {\n\t\t\t\t\t\terrMsg = xhr.statusText;\n\t\t\t\t\t}\n\t\t\t\t\tif (s.error) {\n\t\t\t\t\t\ts.error.call(s.context, xhr, status, errMsg);\n\t\t\t\t\t}\n\t\t\t\t\tdeferred.reject(xhr, 'error', errMsg);\n\t\t\t\t\tif (g) {\n\t\t\t\t\t\t$.event.trigger(\"ajaxError\", [xhr, s, errMsg]);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (g) {\n\t\t\t\t\t$.event.trigger(\"ajaxComplete\", [xhr, s]);\n\t\t\t\t}\n\n\t\t\t\tif (g && !--$.active) {\n\t\t\t\t\t$.event.trigger(\"ajaxStop\");\n\t\t\t\t}\n\n\t\t\t\tif (s.complete) {\n\t\t\t\t\ts.complete.call(s.context, xhr, status);\n\t\t\t\t}\n\n\t\t\t\tcallbackProcessed = true;\n\t\t\t\tif (s.timeout) {\n\t\t\t\t\tclearTimeout(timeoutHandle);\n\t\t\t\t}\n\n\t\t\t\t// clean up\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tif (!s.iframeTarget) {\n\t\t\t\t\t\t$io.remove();\n\t\t\t\t\t} else { //adding else to clean up existing iframe response.\n\t\t\t\t\t\t$io.attr('src', s.iframeSrc);\n\t\t\t\t\t}\n\t\t\t\t\txhr.responseXML = null;\n\t\t\t\t},\n\t\t\t\t100);\n\t\t\t}\n\n\t\t\tvar toXml = $.parseXML ||\n\t\t\tfunction(s, doc) { // use parseXML if available (jQuery 1.5+)\n\t\t\t\tif (window.ActiveXObject) {\n\t\t\t\t\tdoc = new ActiveXObject('Microsoft.XMLDOM');\n\t\t\t\t\tdoc.async = 'false';\n\t\t\t\t\tdoc.loadXML(s);\n\t\t\t\t} else {\n\t\t\t\t\tdoc = (new DOMParser()).parseFromString(s, 'text/xml');\n\t\t\t\t}\n\t\t\t\treturn (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc: null;\n\t\t\t};\n\t\t\tvar parseJSON = $.parseJSON ||\n\t\t\tfunction(s) {\n\t\t\t\t/*jslint evil:true */\n\t\t\t\treturn window['eval']('(' + s + ')');\n\t\t\t};\n\n\t\t\tvar httpData = function(xhr, type, s) { // mostly lifted from jq1.4.4\n\t\t\t\tvar ct = xhr.getResponseHeader('content-type') || '',\n\t\t\t\txml = type === 'xml' || !type && ct.indexOf('xml') >= 0,\n\t\t\t\tdata = xml ? xhr.responseXML: xhr.responseText;\n\n\t\t\t\tif (xml && data.documentElement.nodeName === 'parsererror') {\n\t\t\t\t\tif ($.error) {\n\t\t\t\t\t\t$.error('parsererror');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (s && s.dataFilter) {\n\t\t\t\t\tdata = s.dataFilter(data, type);\n\t\t\t\t}\n\t\t\t\tif (typeof data === 'string') {\n\t\t\t\t\tif (type === 'json' || !type && ct.indexOf('json') >= 0) {\n\t\t\t\t\t\tdata = parseJSON(data);\n\t\t\t\t\t} else if (type === \"script\" || !type && ct.indexOf(\"javascript\") >= 0) {\n\t\t\t\t\t\t$.globalEval(data);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn data;\n\t\t\t};\n\n\t\t\treturn deferred;\n\t\t}\n\t};\n\n\t/**\n\t\t * ajaxForm() provides a mechanism for fully automating form submission.\n\t\t *\n\t\t * The advantages of using this method instead of ajaxSubmit() are:\n\t\t *\n\t\t * 1: This method will include coordinates for <input type=\"image\" /> elements (if the element\n\t\t *    is used to submit the form).\n\t\t * 2. This method will include the submit element's name/value data (for the element that was\n\t\t *    used to submit the form).\n\t\t * 3. This method binds the submit() method to the form for you.\n\t\t *\n\t\t * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely\n\t\t * passes the options argument along after properly binding events for submit elements and\n\t\t * the form itself.\n\t\t */\n\t$.fn.ajaxForm = function(options) {\n\t\toptions = options || {};\n\t\toptions.delegation = options.delegation && $.isFunction($.fn.on);\n\n\t\t// in jQuery 1.3+ we can fix mistakes with the ready state\n\t\tif (!options.delegation && this.length === 0) {\n\t\t\tvar o = {\n\t\t\t\ts: this.selector,\n\t\t\t\tc: this.context\n\t\t\t};\n\t\t\tif (!$.isReady && o.s) {\n\t\t\t\tlog('DOM not ready, queuing ajaxForm');\n\t\t\t\t$(function() {\n\t\t\t\t\t$(o.s, o.c).ajaxForm(options);\n\t\t\t\t});\n\t\t\t\treturn this;\n\t\t\t}\n\t\t\t// is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()\n\t\t\tlog('terminating; zero elements found by selector' + ($.isReady ? '': ' (DOM not ready)'));\n\t\t\treturn this;\n\t\t}\n\n\t\tif (options.delegation) {\n\t\t\t$(document).off('submit.form-plugin', this.selector, doAjaxSubmit).off('click.form-plugin', this.selector, captureSubmittingElement).on('submit.form-plugin', this.selector, options, doAjaxSubmit).on('click.form-plugin', this.selector, options, captureSubmittingElement);\n\t\t\treturn this;\n\t\t}\n\n\t\treturn this.ajaxFormUnbind().on('submit.form-plugin', options, doAjaxSubmit).on('click.form-plugin', options, captureSubmittingElement);\n\t};\n\n\t// private event handlers\n\tfunction doAjaxSubmit(e) {\n\t\t/*jshint validthis:true */\n\t\tvar options = e.data;\n\t\tif (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed\n\t\t\te.preventDefault();\n\t\t\t$(e.target).ajaxSubmit(options); // #365\n\t\t}\n\t}\n\n\tfunction captureSubmittingElement(e) {\n\t\t/*jshint validthis:true */\n\t\tvar target = e.target;\n\t\tvar $el = $(target);\n\t\tif (! ($el.is(\"[type=submit],[type=image]\"))) {\n\t\t\t// is this a child element of the submit el?  (ex: a span within a button)\n\t\t\tvar t = $el.closest('[type=submit]');\n\t\t\tif (t.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttarget = t[0];\n\t\t}\n\t\tvar form = this;\n\t\tform.clk = target;\n\t\tif (target.type == 'image') {\n\t\t\tif (e.offsetX !== undefined) {\n\t\t\t\tform.clk_x = e.offsetX;\n\t\t\t\tform.clk_y = e.offsetY;\n\t\t\t} else if (typeof $.fn.offset == 'function') {\n\t\t\t\tvar offset = $el.offset();\n\t\t\t\tform.clk_x = e.pageX - offset.left;\n\t\t\t\tform.clk_y = e.pageY - offset.top;\n\t\t\t} else {\n\t\t\t\tform.clk_x = e.pageX - target.offsetLeft;\n\t\t\t\tform.clk_y = e.pageY - target.offsetTop;\n\t\t\t}\n\t\t}\n\t\t// clear form vars\n\t\tsetTimeout(function() {\n\t\t\tform.clk = form.clk_x = form.clk_y = null;\n\t\t},\n\t\t100);\n\t}\n\n\t// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm\n\t$.fn.ajaxFormUnbind = function() {\n\t\treturn this.unbind('submit.form-plugin click.form-plugin');\n\t};\n\n\t/**\n\t\t * formToArray() gathers form element data into an array of objects that can\n\t\t * be passed to any of the following ajax functions: $.get, $.post, or load.\n\t\t * Each object in the array has both a 'name' and 'value' property.  An example of\n\t\t * an array for a simple login form might be:\n\t\t *\n\t\t * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]\n\t\t *\n\t\t * It is this array that is passed to pre-submit callback functions provided to the\n\t\t * ajaxSubmit() and ajaxForm() methods.\n\t\t */\n\t$.fn.formToArray = function(semantic, elements) {\n\t\tvar a = [];\n\t\tif (this.length === 0) {\n\t\t\treturn a;\n\t\t}\n\n\t\tvar form = this[0];\n\t\tvar formId = this.attr('id');\n\t\tvar els = semantic ? form.getElementsByTagName('*') : form.elements;\n\t\tvar els2;\n\n\t\tif (els && !/MSIE [678]/.test(navigator.userAgent)) { // #390\n\t\t\tels = $(els).get(); // convert to standard array\n\t\t}\n\n\t\t// #386; account for inputs outside the form which use the 'form' attribute\n\t\tif (formId) {\n\t\t\tels2 = $(':input[form=\"' + formId + '\"]').get(); // hat tip @thet\n\t\t\tif (els2.length) {\n\t\t\t\tels = (els || []).concat(els2);\n\t\t\t}\n\t\t}\n\n\t\tif (!els || !els.length) {\n\t\t\treturn a;\n\t\t}\n\n\t\tvar i, j, n, v, el, max, jmax;\n\t\tfor (i = 0, max = els.length; i < max; i++) {\n\t\t\tel = els[i];\n\t\t\tn = el.name;\n\t\t\tif (!n || el.disabled) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (semantic && form.clk && el.type == \"image\") {\n\t\t\t\t// handle image inputs on the fly when semantic == true\n\t\t\t\tif (form.clk == el) {\n\t\t\t\t\ta.push({\n\t\t\t\t\t\tname: n,\n\t\t\t\t\t\tvalue: $(el).val(),\n\t\t\t\t\t\ttype: el.type\n\t\t\t\t\t});\n\t\t\t\t\ta.push({\n\t\t\t\t\t\tname: n + '.x',\n\t\t\t\t\t\tvalue: form.clk_x\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tname: n + '.y',\n\t\t\t\t\t\tvalue: form.clk_y\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tv = $.fieldValue(el, true);\n\t\t\tif (v && v.constructor == Array) {\n\t\t\t\tif (elements) {\n\t\t\t\t\telements.push(el);\n\t\t\t\t}\n\t\t\t\tfor (j = 0, jmax = v.length; j < jmax; j++) {\n\t\t\t\t\ta.push({\n\t\t\t\t\t\tname: n,\n\t\t\t\t\t\tvalue: v[j]\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (feature.fileapi && el.type == 'file') {\n\t\t\t\tif (elements) {\n\t\t\t\t\telements.push(el);\n\t\t\t\t}\n\t\t\t\tvar files = el.files;\n\t\t\t\tif (files.length) {\n\t\t\t\t\tfor (j = 0; j < files.length; j++) {\n\t\t\t\t\t\ta.push({\n\t\t\t\t\t\t\tname: n,\n\t\t\t\t\t\t\tvalue: files[j],\n\t\t\t\t\t\t\ttype: el.type\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// #180\n\t\t\t\t\ta.push({\n\t\t\t\t\t\tname: n,\n\t\t\t\t\t\tvalue: '',\n\t\t\t\t\t\ttype: el.type\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (v !== null && typeof v != 'undefined') {\n\t\t\t\tif (elements) {\n\t\t\t\t\telements.push(el);\n\t\t\t\t}\n\t\t\t\ta.push({\n\t\t\t\t\tname: n,\n\t\t\t\t\tvalue: v,\n\t\t\t\t\ttype: el.type,\n\t\t\t\t\trequired: el.required\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\tif (!semantic && form.clk) {\n\t\t\t// input type=='image' are not found in elements array! handle it here\n\t\t\tvar $input = $(form.clk),\n\t\t\tinput = $input[0];\n\t\t\tn = input.name;\n\t\t\tif (n && !input.disabled && input.type == 'image') {\n\t\t\t\ta.push({\n\t\t\t\t\tname: n,\n\t\t\t\t\tvalue: $input.val()\n\t\t\t\t});\n\t\t\t\ta.push({\n\t\t\t\t\tname: n + '.x',\n\t\t\t\t\tvalue: form.clk_x\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tname: n + '.y',\n\t\t\t\t\tvalue: form.clk_y\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn a;\n\t};\n\n\t/**\n\t\t * Serializes form data into a 'submittable' string. This method will return a string\n\t\t * in the format: name1=value1&amp;name2=value2\n\t\t */\n\t$.fn.formSerialize = function(semantic) {\n\t\t//hand off to jQuery.param for proper encoding\n\t\treturn $.param(this.formToArray(semantic));\n\t};\n\n\t/**\n\t\t * Serializes all field elements in the jQuery object into a query string.\n\t\t * This method will return a string in the format: name1=value1&amp;name2=value2\n\t\t */\n\t$.fn.fieldSerialize = function(successful) {\n\t\tvar a = [];\n\t\tthis.each(function() {\n\t\t\tvar n = this.name;\n\t\t\tif (!n) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar v = $.fieldValue(this, successful);\n\t\t\tif (v && v.constructor == Array) {\n\t\t\t\tfor (var i = 0,\n\t\t\t\tmax = v.length; i < max; i++) {\n\t\t\t\t\ta.push({\n\t\t\t\t\t\tname: n,\n\t\t\t\t\t\tvalue: v[i]\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t} else if (v !== null && typeof v != 'undefined') {\n\t\t\t\ta.push({\n\t\t\t\t\tname: this.name,\n\t\t\t\t\tvalue: v\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t\t//hand off to jQuery.param for proper encoding\n\t\treturn $.param(a);\n\t};\n\n\t/**\n\t\t * Returns the value(s) of the element in the matched set.  For example, consider the following form:\n\t\t *\n\t\t *  <form><fieldset>\n\t\t *      <input name=\"A\" type=\"text\" />\n\t\t *      <input name=\"A\" type=\"text\" />\n\t\t *      <input name=\"B\" type=\"checkbox\" value=\"B1\" />\n\t\t *      <input name=\"B\" type=\"checkbox\" value=\"B2\"/>\n\t\t *      <input name=\"C\" type=\"radio\" value=\"C1\" />\n\t\t *      <input name=\"C\" type=\"radio\" value=\"C2\" />\n\t\t *  </fieldset></form>\n\t\t *\n\t\t *  var v = $('input[type=text]').fieldValue();\n\t\t *  // if no values are entered into the text inputs\n\t\t *  v == ['','']\n\t\t *  // if values entered into the text inputs are 'foo' and 'bar'\n\t\t *  v == ['foo','bar']\n\t\t *\n\t\t *  var v = $('input[type=checkbox]').fieldValue();\n\t\t *  // if neither checkbox is checked\n\t\t *  v === undefined\n\t\t *  // if both checkboxes are checked\n\t\t *  v == ['B1', 'B2']\n\t\t *\n\t\t *  var v = $('input[type=radio]').fieldValue();\n\t\t *  // if neither radio is checked\n\t\t *  v === undefined\n\t\t *  // if first radio is checked\n\t\t *  v == ['C1']\n\t\t *\n\t\t * The successful argument controls whether or not the field element must be 'successful'\n\t\t * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).\n\t\t * The default value of the successful argument is true.  If this value is false the value(s)\n\t\t * for each element is returned.\n\t\t *\n\t\t * Note: This method *always* returns an array.  If no valid value can be determined the\n\t\t *    array will be empty, otherwise it will contain one or more values.\n\t\t */\n\t$.fn.fieldValue = function(successful) {\n\t\tfor (var val = [], i = 0, max = this.length; i < max; i++) {\n\t\t\tvar el = this[i];\n\t\t\tvar v = $.fieldValue(el, successful);\n\t\t\tif (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (v.constructor == Array) {\n\t\t\t\t$.merge(val, v);\n\t\t\t} else {\n\t\t\t\tval.push(v);\n\t\t\t}\n\t\t}\n\t\treturn val;\n\t};\n\n\t/**\n\t\t * Returns the value of the field element.\n\t\t */\n\t$.fieldValue = function(el, successful) {\n\t\tvar n = el.name,\n\t\tt = el.type,\n\t\ttag = el.tagName.toLowerCase();\n\t\tif (successful === undefined) {\n\t\t\tsuccessful = true;\n\t\t}\n\n\t\tif (successful && (!n || el.disabled || t == 'reset' || t == 'button' || (t == 'checkbox' || t == 'radio') && !el.checked || (t == 'submit' || t == 'image') && el.form && el.form.clk != el || tag == 'select' && el.selectedIndex == -1)) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (tag == 'select') {\n\t\t\tvar index = el.selectedIndex;\n\t\t\tif (index < 0) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tvar a = [],\n\t\t\tops = el.options;\n\t\t\tvar one = (t == 'select-one');\n\t\t\tvar max = (one ? index + 1 : ops.length);\n\t\t\tfor (var i = (one ? index: 0); i < max; i++) {\n\t\t\t\tvar op = ops[i];\n\t\t\t\tif (op.selected) {\n\t\t\t\t\tvar v = op.value;\n\t\t\t\t\tif (!v) { // extra pain for IE...\n\t\t\t\t\t\tv = (op.attributes && op.attributes.value && !(op.attributes.value.specified)) ? op.text: op.value;\n\t\t\t\t\t}\n\t\t\t\t\tif (one) {\n\t\t\t\t\t\treturn v;\n\t\t\t\t\t}\n\t\t\t\t\ta.push(v);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn a;\n\t\t}\n\t\treturn $(el).val();\n\t};\n\n\t/**\n\t\t * Clears the form data.  Takes the following actions on the form's input fields:\n\t\t *  - input text fields will have their 'value' property set to the empty string\n\t\t *  - select elements will have their 'selectedIndex' property set to -1\n\t\t *  - checkbox and radio inputs will have their 'checked' property set to false\n\t\t *  - inputs of type submit, button, reset, and hidden will *not* be effected\n\t\t *  - button elements will *not* be effected\n\t\t */\n\t$.fn.clearForm = function(includeHidden) {\n\t\treturn this.each(function() {\n\t\t\t$('input,select,textarea', this).clearFields(includeHidden);\n\t\t});\n\t};\n\n\t/**\n\t\t * Clears the selected form elements.\n\t\t */\n\t$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {\n\t\tvar re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list\n\t\treturn this.each(function() {\n\t\t\tvar t = this.type,\n\t\t\ttag = this.tagName.toLowerCase();\n\t\t\tif (re.test(t) || tag == 'textarea') {\n\t\t\t\tthis.value = '';\n\t\t\t} else if (t == 'checkbox' || t == 'radio') {\n\t\t\t\tthis.checked = false;\n\t\t\t} else if (tag == 'select') {\n\t\t\t\tthis.selectedIndex = -1;\n\t\t\t} else if (t == \"file\") {\n\t\t\t\tif (/MSIE/.test(navigator.userAgent)) {\n\t\t\t\t\t$(this).replaceWith($(this).clone(true));\n\t\t\t\t} else {\n\t\t\t\t\t$(this).val('');\n\t\t\t\t}\n\t\t\t} else if (includeHidden) {\n\t\t\t\t// includeHidden can be the value true, or it can be a selector string\n\t\t\t\t// indicating a special test; for example:\n\t\t\t\t//  $('#myForm').clearForm('.special:hidden')\n\t\t\t\t// the above would clean hidden inputs that have the class of 'special'\n\t\t\t\tif ((includeHidden === true && /hidden/.test(t)) || (typeof includeHidden == 'string' && $(this).is(includeHidden))) {\n\t\t\t\t\tthis.value = '';\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t};\n\n\t/**\n\t\t * Resets the form data.  Causes all form elements to be reset to their original value.\n\t\t */\n\t$.fn.resetForm = function() {\n\t\treturn this.each(function() {\n\t\t\t// guard against an input with the name of 'reset'\n\t\t\t// note that IE reports the reset function as an 'object'\n\t\t\tif (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {\n\t\t\t\tthis.reset();\n\t\t\t}\n\t\t});\n\t};\n\n\t/**\n\t\t * Enables or disables any matching elements.\n\t\t */\n\t$.fn.enable = function(b) {\n\t\tif (b === undefined) {\n\t\t\tb = true;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tthis.disabled = !b;\n\t\t});\n\t};\n\n\t/**\n\t\t * Checks/unchecks any matching checkboxes or radio buttons and\n\t\t * selects/deselects and matching option elements.\n\t\t */\n\t$.fn.selected = function(select) {\n\t\tif (select === undefined) {\n\t\t\tselect = true;\n\t\t}\n\t\treturn this.each(function() {\n\t\t\tvar t = this.type;\n\t\t\tif (t == 'checkbox' || t == 'radio') {\n\t\t\t\tthis.checked = select;\n\t\t\t} else if (this.tagName.toLowerCase() == 'option') {\n\t\t\t\tvar $sel = $(this).parent('select');\n\t\t\t\tif (select && $sel[0] && $sel[0].type == 'select-one') {\n\t\t\t\t\t// deselect all other options\n\t\t\t\t\t$sel.find('option').selected(false);\n\t\t\t\t}\n\t\t\t\tthis.selected = select;\n\t\t\t}\n\t\t});\n\t};\n\n\t// expose debug var\n\t$.fn.ajaxSubmit.debug = false;\n\tfunction log() {\n\t\tif (!$.fn.ajaxSubmit.debug) {\n\t\t\treturn;\n\t\t}\n\t\tvar msg = '[jquery.form] ' + Array.prototype.join.call(arguments, '');\n\t\tif (window.console && window.console.log) {\n\t\t\twindow.console.log(msg);\n\t\t} else if (window.opera && window.opera.postError) {\n\t\t\twindow.opera.postError(msg);\n\t\t}\n\t}\n}));\n\n/* =======================================================================\n * jQuery.lazyload v1.9.3\n * Lazy Load - jQuery plugin for lazy loading images\n * Copyright (c) 2007-2013 Mika Tuupola\n * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php\n * Project home: http://www.appelsiini.net/projects/lazyload\n * ======================================================================== */\n! (function($, window, document, undefined) {\n\tvar $window = $(window);\n\t$.fn.lazyload = function(options) {\n\t\tvar elements = this;\n\t\tvar $container;\n\t\tvar settings = {\n\t\t\tthreshold: 0,\n\t\t\tfailure_limit: 0,\n\t\t\tevent: \"scroll\",\n\t\t\teffect: \"show\",\n\t\t\tcontainer: window,\n\t\t\tdata_attribute: \"original\",\n\t\t\tskip_invisible: true,\n\t\t\tappear: null,\n\t\t\tload: null,\n\t\t\tplaceholder: \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC\"\n\t\t};\n\t\tfunction update() {\n\t\t\tvar counter = 0;\n\t\t\telements.each(function() {\n\t\t\t\tvar $this = $(this);\n\t\t\t\tif (settings.skip_invisible && !$this.is(\":visible\")) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif ($.abovethetop(this, settings) || $.leftofbegin(this, settings)) {\n\t\t\t\t\t/* Nothing. */\n\t\t\t\t} else if (!$.belowthefold(this, settings) && !$.rightoffold(this, settings)) {\n\t\t\t\t\t$this.trigger(\"appear\");\n\t\t\t\t\t/* if we found an image we'll load, reset the counter */\n\t\t\t\t\tcounter = 0;\n\t\t\t\t} else {\n\t\t\t\t\tif (++counter > settings.failure_limit) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tif (options) {\n\t\t\t/* Maintain BC for a couple of versions. */\n\t\t\tif (undefined !== options.failurelimit) {\n\t\t\t\toptions.failure_limit = options.failurelimit;\n\t\t\t\tdelete options.failurelimit;\n\t\t\t}\n\t\t\tif (undefined !== options.effectspeed) {\n\t\t\t\toptions.effect_speed = options.effectspeed;\n\t\t\t\tdelete options.effectspeed;\n\t\t\t}\n\t\t\t$.extend(settings, options);\n\t\t}\n\n\t\t/* Cache container as jQuery as object. */\n\t\t$container = (settings.container === undefined || settings.container === window) ? $window: $(settings.container);\n\n\t\t/* Fire one scroll event per scroll. Not one scroll event per image. */\n\t\tif (0 === settings.event.indexOf(\"scroll\")) {\n\t\t\t$container.on(settings.event,\n\t\t\tfunction() {\n\t\t\t\treturn update();\n\t\t\t});\n\t\t}\n\t\tthis.each(function() {\n\t\t\tvar self = this;\n\t\t\tvar $self = $(self);\n\t\t\tself.loaded = false;\n\n\t\t\t/* If no src attribute given use data:uri. */\n\t\t\tif ($self.attr(\"src\") === undefined || $self.attr(\"src\") === false) {\n\t\t\t\tif ($self.is(\"img\")) {\n\t\t\t\t\t$self.attr(\"src\", settings.placeholder);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/* When appear is triggered load original image. */\n\t\t\t$self.one(\"appear\",\n\t\t\tfunction() {\n\t\t\t\tif (!this.loaded) {\n\t\t\t\t\tif (settings.appear) {\n\t\t\t\t\t\tvar elements_left = elements.length;\n\t\t\t\t\t\tsettings.appear.call(self, elements_left, settings);\n\t\t\t\t\t}\n\t\t\t\t\t$(\"<img />\").on(\"load\",\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tvar original = $self.attr(\"data-\" + settings.data_attribute);\n\t\t\t\t\t\t$self.hide();\n\t\t\t\t\t\tif ($self.is(\"img\")) {\n\t\t\t\t\t\t\t$self.attr(\"src\", original);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$self.css(\"background-image\", \"url('\" + original + \"')\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$self[settings.effect](settings.effect_speed);\n\t\t\t\t\t\tself.loaded = true;\n\n\t\t\t\t\t\t/* Remove image from array so it is not looped next time. */\n\t\t\t\t\t\tvar temp = $.grep(elements,\n\t\t\t\t\t\tfunction(element) {\n\t\t\t\t\t\t\treturn ! element.loaded;\n\t\t\t\t\t\t});\n\t\t\t\t\t\telements = $(temp);\n\t\t\t\t\t\tif (settings.load) {\n\t\t\t\t\t\t\tvar elements_left = elements.length;\n\t\t\t\t\t\t\tsettings.load.call(self, elements_left, settings);\n\t\t\t\t\t\t}\n\t\t\t\t\t}).attr(\"src\", $self.attr(\"data-\" + settings.data_attribute));\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t/* When wanted event is triggered load original image */\n\t\t\t/* by triggering appear.                              */\n\t\t\tif (0 !== settings.event.indexOf(\"scroll\")) {\n\t\t\t\t$self.on(settings.event,\n\t\t\t\tfunction() {\n\t\t\t\t\tif (!self.loaded) {\n\t\t\t\t\t\t$self.trigger(\"appear\");\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\n\t\t/* Check if something appears when window is resized. */\n\t\t$window.on(\"resize\",\n\t\tfunction() {\n\t\t\tupdate();\n\t\t});\n\n\t\t/* With IOS5 force loading images when navigating with back button. */\n\t\t/* Non optimal workaround. */\n\t\tif ((/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion)) {\n\t\t\t$window.on(\"pageshow\",\n\t\t\tfunction(event) {\n\t\t\t\tif (event.originalEvent && event.originalEvent.persisted) {\n\t\t\t\t\telements.each(function() {\n\t\t\t\t\t\t$(this).trigger(\"appear\");\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t/* Force initial check if images should appear. */\n\t\t$(document).ready(function() {\n\t\t\tupdate();\n\t\t});\n\t\treturn this;\n\t};\n\n\t/* Convenience methods in jQuery namespace.           */\n\t/* Use as  $.belowthefold(element, {threshold : 100, container : window}) */\n\t$.belowthefold = function(element, settings) {\n\t\tvar fold;\n\t\tif (settings.container === undefined || settings.container === window) {\n\t\t\tfold = (window.innerHeight ? window.innerHeight: $window.height()) + $window.scrollTop();\n\t\t} else {\n\t\t\tfold = $(settings.container).offset().top + $(settings.container).height();\n\t\t}\n\t\treturn fold <= $(element).offset().top - settings.threshold;\n\t};\n\n\t$.rightoffold = function(element, settings) {\n\t\tvar fold;\n\t\tif (settings.container === undefined || settings.container === window) {\n\t\t\tfold = $window.width() + $window.scrollLeft();\n\t\t} else {\n\t\t\tfold = $(settings.container).offset().left + $(settings.container).width();\n\t\t}\n\t\treturn fold <= $(element).offset().left - settings.threshold;\n\t};\n\n\t$.abovethetop = function(element, settings) {\n\t\tvar fold;\n\t\tif (settings.container === undefined || settings.container === window) {\n\t\t\tfold = $window.scrollTop();\n\t\t} else {\n\t\t\tfold = $(settings.container).offset().top;\n\t\t}\n\t\treturn fold >= $(element).offset().top + settings.threshold + $(element).height();\n\t};\n\n\t$.leftofbegin = function(element, settings) {\n\t\tvar fold;\n\t\tif (settings.container === undefined || settings.container === window) {\n\t\t\tfold = $window.scrollLeft();\n\t\t} else {\n\t\t\tfold = $(settings.container).offset().left;\n\t\t}\n\t\treturn fold >= $(element).offset().left + settings.threshold + $(element).width();\n\t};\n\n\t$.inviewport = function(element, settings) {\n\t\treturn ! $.rightoffold(element, settings) && !$.leftofbegin(element, settings) && !$.belowthefold(element, settings) && !$.abovethetop(element, settings);\n\t};\n\n\t/* Custom selectors for your convenience.   */\n\t/* Use as $(\"img:below-the-fold\").something() or */\n\t/* $(\"img\").filter(\":below-the-fold\").something() which is faster */\n\t$.extend($.expr[\":\"], {\n\t\t\"below-the-fold\": function(a) {\n\t\t\treturn $.belowthefold(a, {\n\t\t\t\tthreshold: 0\n\t\t\t});\n\t\t},\n\t\t\"above-the-top\": function(a) {\n\t\t\treturn ! $.belowthefold(a, {\n\t\t\t\tthreshold: 0\n\t\t\t});\n\t\t},\n\t\t\"right-of-screen\": function(a) {\n\t\t\treturn $.rightoffold(a, {\n\t\t\t\tthreshold: 0\n\t\t\t});\n\t\t},\n\t\t\"left-of-screen\": function(a) {\n\t\t\treturn ! $.rightoffold(a, {\n\t\t\t\tthreshold: 0\n\t\t\t});\n\t\t},\n\t\t\"in-viewport\": function(a) {\n\t\t\treturn $.inviewport(a, {\n\t\t\t\tthreshold: 0\n\t\t\t});\n\t\t},\n\t\t/* Maintain BC for couple of versions. */\n\t\t\"above-the-fold\": function(a) {\n\t\t\treturn ! $.belowthefold(a, {\n\t\t\t\tthreshold: 0\n\t\t\t});\n\t\t},\n\t\t\"right-of-fold\": function(a) {\n\t\t\treturn $.rightoffold(a, {\n\t\t\t\tthreshold: 0\n\t\t\t});\n\t\t},\n\t\t\"left-of-fold\": function(a) {\n\t\t\treturn ! $.rightoffold(a, {\n\t\t\t\tthreshold: 0\n\t\t\t});\n\t\t}\n\t});\n})(jQuery, window, document);\n\n/* =======================================================================\n* jQuery.responsive-nav.js v1.0.39\n* https://github.com/viljamis/responsive-nav.js\n* http://responsive-nav.com\n*\n* Copyright (c) 2015 @viljamis\n* Available under the MIT license\n * ======================================================================== */\n/* global Event */\n(function(document, window, index) {\n\t// Index is used to keep multiple navs on the same page namespaced\n\t\"use strict\";\n\tvar responsiveNav = function(el, options) {\n\t\tvar computed = !!window.getComputedStyle;\n\n\t\t/**\n\t\t* getComputedStyle polyfill for old browsers\n\t\t*/\n\t\tif (!computed) {\n\t\t\twindow.getComputedStyle = function(el) {\n\t\t\t\tthis.el = el;\n\t\t\t\tthis.getPropertyValue = function(prop) {\n\t\t\t\t\tvar re = /(\\-([a-z]){1})/g;\n\t\t\t\t\tif (prop === \"float\") {\n\t\t\t\t\t\tprop = \"styleFloat\";\n\t\t\t\t\t}\n\t\t\t\t\tif (re.test(prop)) {\n\t\t\t\t\t\tprop = prop.replace(re,\n\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\treturn arguments[2].toUpperCase();\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t\treturn el.currentStyle[prop] ? el.currentStyle[prop] : null;\n\t\t\t\t};\n\t\t\t\treturn this;\n\t\t\t};\n\t\t}\n\t\t/* exported addEvent, removeEvent, getChildren, setAttributes, addClass, removeClass, forEach */\n\n\t\t/**\n\t\t* Add Event\n\t\t* fn arg can be an object or a function, thanks to handleEvent\n\t\t* read more at: http://www.thecssninja.com/javascript/handleevent\n\t\t*\n\t\t* @param  {element}  element\n\t\t* @param  {event}    event\n\t\t* @param  {Function} fn\n\t\t* @param  {boolean}  bubbling\n\t\t*/\n\t\tvar addEvent = function(el, evt, fn, bubble) {\n\t\t\tif (\"addEventListener\" in el) {\n\t\t\t\t// BBOS6 doesn't support handleEvent, catch and polyfill\n\t\t\t\ttry {\n\t\t\t\t\tel.addEventListener(evt, fn, bubble);\n\t\t\t\t} catch(e) {\n\t\t\t\t\tif (typeof fn === \"object\" && fn.handleEvent) {\n\t\t\t\t\t\tel.addEventListener(evt,\n\t\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\t\t// Bind fn as this and set first arg as event object\n\t\t\t\t\t\t\tfn.handleEvent.call(fn, e);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbubble);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (\"attachEvent\" in el) {\n\t\t\t\t// check if the callback is an object and contains handleEvent\n\t\t\t\tif (typeof fn === \"object\" && fn.handleEvent) {\n\t\t\t\t\tel.attachEvent(\"on\" + evt,\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\t// Bind fn as this\n\t\t\t\t\t\tfn.handleEvent.call(fn);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tel.attachEvent(\"on\" + evt, fn);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t* Remove Event\n\t*\n\t* @param  {element}  element\n\t* @param  {event}    event\n\t* @param  {Function} fn\n\t* @param  {boolean}  bubbling\n\t*/\n\t\tremoveEvent = function(el, evt, fn, bubble) {\n\t\t\tif (\"removeEventListener\" in el) {\n\t\t\t\ttry {\n\t\t\t\t\tel.removeEventListener(evt, fn, bubble);\n\t\t\t\t} catch(e) {\n\t\t\t\t\tif (typeof fn === \"object\" && fn.handleEvent) {\n\t\t\t\t\t\tel.removeEventListener(evt,\n\t\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\t\tfn.handleEvent.call(fn, e);\n\t\t\t\t\t\t},\n\t\t\t\t\t\tbubble);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (\"detachEvent\" in el) {\n\t\t\t\tif (typeof fn === \"object\" && fn.handleEvent) {\n\t\t\t\t\tel.detachEvent(\"on\" + evt,\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tfn.handleEvent.call(fn);\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tel.detachEvent(\"on\" + evt, fn);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t* Get the children of any element\n\t*\n\t* @param  {element}\n\t* @return {array} Returns matching elements in an array\n\t*/\n\t\tgetChildren = function(e) {\n\t\t\tif (e.children.length < 1) {\n\t\t\t\tthrow new Error(\"The Nav container has no containing elements\");\n\t\t\t}\n\t\t\t// Store all children in array\n\t\t\tvar children = [];\n\t\t\t// Loop through children and store in array if child != TextNode\n\t\t\tfor (var i = 0; i < e.children.length; i++) {\n\t\t\t\tif (e.children[i].nodeType === 1) {\n\t\t\t\t\tchildren.push(e.children[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn children;\n\t\t},\n\n\t\t/**\n\t* Sets multiple attributes at once\n\t*\n\t* @param {element} element\n\t* @param {attrs}   attrs\n\t*/\n\t\tsetAttributes = function(el, attrs) {\n\t\t\tfor (var key in attrs) {\n\t\t\t\tel.setAttribute(key, attrs[key]);\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t* Adds a class to any element\n\t*\n\t* @param {element} element\n\t* @param {string}  class\n\t*/\n\t\taddClass = function(el, cls) {\n\t\t\tif (el.className.indexOf(cls) !== 0) {\n\t\t\t\tel.className += \" \" + cls;\n\t\t\t\tel.className = el.className.replace(/(^\\s*)|(\\s*$)/g, \"\");\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t* Remove a class from any element\n\t*\n\t* @param  {element} element\n\t* @param  {string}  class\n\t*/\n\t\tremoveClass = function(el, cls) {\n\t\t\tvar reg = new RegExp(\"(\\\\s|^)\" + cls + \"(\\\\s|$)\");\n\t\t\tel.className = el.className.replace(reg, \" \").replace(/(^\\s*)|(\\s*$)/g, \"\");\n\t\t},\n\n\t\t/**\n\t* forEach method that passes back the stuff we need\n\t*\n\t* @param  {array}    array\n\t* @param  {Function} callback\n\t* @param  {scope}    scope\n\t*/\n\t\tforEach = function(array, callback, scope) {\n\t\t\tfor (var i = 0; i < array.length; i++) {\n\t\t\t\tcallback.call(scope, i, array[i]);\n\t\t\t}\n\t\t};\n\n\t\tvar nav, opts, navToggle, styleElement = document.createElement(\"style\"),\n\t\thtmlEl = document.documentElement,\n\t\thasAnimFinished,\n\t\tisMobile,\n\t\tnavOpen;\n\n\t\tvar ResponsiveNav = function(el, options) {\n\t\t\tvar i;\n\n\t\t\t/**\n\t\t* Default options\n\t\t* @type {Object}\n\t\t*/\n\t\t\tthis.options = {\n\t\t\t\tanimate: true,\n\t\t\t\t// Boolean: Use CSS3 transitions, true or false\n\t\t\t\ttransition: 284,\n\t\t\t\t// Integer: Speed of the transition, in milliseconds\n\t\t\t\tlabel: \"Menu\",\n\t\t\t\t// String: Label for the navigation toggle\n\t\t\t\tinsert: \"before\",\n\t\t\t\t// String: Insert the toggle before or after the navigation\n\t\t\t\tcustomToggle: \"\",\n\t\t\t\t// Selector: Specify the ID of a custom toggle\n\t\t\t\tcloseOnNavClick: false,\n\t\t\t\t// Boolean: Close the navigation when one of the links are clicked\n\t\t\t\topenPos: \"relative\",\n\t\t\t\t// String: Position of the opened nav, relative or static\n\t\t\t\tnavClass: \"nav-collapse\",\n\t\t\t\t// String: Default CSS class. If changed, you need to edit the CSS too!\n\t\t\t\tnavActiveClass: \"js-nav-active\",\n\t\t\t\t// String: Class that is added to <html> element when nav is active\n\t\t\t\tjsClass: \"js\",\n\t\t\t\t// String: 'JS enabled' class which is added to <html> element\n\t\t\t\tinit: function() {},\n\t\t\t\t// Function: Init callback\n\t\t\t\topen: function() {},\n\t\t\t\t// Function: Open callback\n\t\t\t\tclose: function() {} // Function: Close callback\n\t\t\t};\n\n\t\t\t// User defined options\n\t\t\tfor (i in options) {\n\t\t\t\tthis.options[i] = options[i];\n\t\t\t}\n\n\t\t\t// Adds \"js\" class for <html>\n\t\t\taddClass(htmlEl, this.options.jsClass);\n\n\t\t\t// Wrapper\n\t\t\tthis.wrapperEl = el.replace(\"#\", \"\");\n\n\t\t\t// Try selecting ID first\n\t\t\tif (document.getElementById(this.wrapperEl)) {\n\t\t\t\tthis.wrapper = document.getElementById(this.wrapperEl);\n\n\t\t\t\t// If element with an ID doesn't exist, use querySelector\n\t\t\t} else if (document.querySelector(this.wrapperEl)) {\n\t\t\t\tthis.wrapper = document.querySelector(this.wrapperEl);\n\n\t\t\t\t// If element doesn't exists, stop here.\n\t\t\t} else {\n\t\t\t\tthrow new Error(\"The nav element you are trying to select doesn't exist\");\n\t\t\t}\n\n\t\t\t// Inner wrapper\n\t\t\tthis.wrapper.inner = getChildren(this.wrapper);\n\n\t\t\t// For minification\n\t\t\topts = this.options;\n\t\t\tnav = this.wrapper;\n\n\t\t\t// Init\n\t\t\tthis._init(this);\n\t\t};\n\n\t\tResponsiveNav.prototype = {\n\n\t\t\t/**\n\t\t* Unattaches events and removes any classes that were added\n\t\t*/\n\t\t\tdestroy: function() {\n\t\t\t\tthis._removeStyles();\n\t\t\t\tremoveClass(nav, \"closed\");\n\t\t\t\tremoveClass(nav, \"opened\");\n\t\t\t\tremoveClass(nav, opts.navClass);\n\t\t\t\tremoveClass(nav, opts.navClass + \"-\" + this.index);\n\t\t\t\tremoveClass(htmlEl, opts.navActiveClass);\n\t\t\t\tnav.removeAttribute(\"style\");\n\t\t\t\tnav.removeAttribute(\"aria-hidden\");\n\n\t\t\t\tremoveEvent(window, \"resize\", this, false);\n\t\t\t\tremoveEvent(window, \"focus\", this, false);\n\t\t\t\tremoveEvent(document.body, \"touchmove\", this, false);\n\t\t\t\tremoveEvent(navToggle, \"touchstart\", this, false);\n\t\t\t\tremoveEvent(navToggle, \"touchend\", this, false);\n\t\t\t\tremoveEvent(navToggle, \"mouseup\", this, false);\n\t\t\t\tremoveEvent(navToggle, \"keyup\", this, false);\n\t\t\t\tremoveEvent(navToggle, \"click\", this, false);\n\n\t\t\t\tif (!opts.customToggle) {\n\t\t\t\t\tnavToggle.parentNode.removeChild(navToggle);\n\t\t\t\t} else {\n\t\t\t\t\tnavToggle.removeAttribute(\"aria-hidden\");\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Toggles the navigation open/close\n\t\t*/\n\t\t\ttoggle: function() {\n\t\t\t\tif (hasAnimFinished === true) {\n\t\t\t\t\tif (!navOpen) {\n\t\t\t\t\t\tthis.open();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.close();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Opens the navigation\n\t\t*/\n\t\t\topen: function() {\n\t\t\t\tif (!navOpen) {\n\t\t\t\t\tremoveClass(nav, \"closed\");\n\t\t\t\t\taddClass(nav, \"opened\");\n\t\t\t\t\taddClass(htmlEl, opts.navActiveClass);\n\t\t\t\t\taddClass(navToggle, \"active\");\n\t\t\t\t\tnav.style.position = opts.openPos;\n\t\t\t\t\tsetAttributes(nav, {\n\t\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t\t});\n\t\t\t\t\tnavOpen = true;\n\t\t\t\t\topts.open();\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Closes the navigation\n\t\t*/\n\t\t\tclose: function() {\n\t\t\t\tif (navOpen) {\n\t\t\t\t\taddClass(nav, \"closed\");\n\t\t\t\t\tremoveClass(nav, \"opened\");\n\t\t\t\t\tremoveClass(htmlEl, opts.navActiveClass);\n\t\t\t\t\tremoveClass(navToggle, \"active\");\n\t\t\t\t\tsetAttributes(nav, {\n\t\t\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t\t\t});\n\n\t\t\t\t\t// If animations are enabled, wait until they finish\n\t\t\t\t\tif (opts.animate) {\n\t\t\t\t\t\thasAnimFinished = false;\n\t\t\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t\t\tnav.style.position = \"absolute\";\n\t\t\t\t\t\t\thasAnimFinished = true;\n\t\t\t\t\t\t},\n\t\t\t\t\t\topts.transition + 10);\n\n\t\t\t\t\t\t// Animations aren't enabled, we can do these immediately\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnav.style.position = \"absolute\";\n\t\t\t\t\t}\n\n\t\t\t\t\tnavOpen = false;\n\t\t\t\t\topts.close();\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Resize is called on window resize and orientation change.\n\t\t* It initializes the CSS styles and height calculations.\n\t\t*/\n\t\t\tresize: function() {\n\n\t\t\t\t// Resize watches navigation toggle's display state\n\t\t\t\tif (window.getComputedStyle(navToggle, null).getPropertyValue(\"display\") !== \"none\") {\n\n\t\t\t\t\tisMobile = true;\n\t\t\t\t\tsetAttributes(navToggle, {\n\t\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t\t});\n\n\t\t\t\t\t// If the navigation is hidden\n\t\t\t\t\tif (nav.className.match(/(^|\\s)closed(\\s|$)/)) {\n\t\t\t\t\t\tsetAttributes(nav, {\n\t\t\t\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t\t\t\t});\n\t\t\t\t\t\tnav.style.position = \"absolute\";\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._createStyles();\n\t\t\t\t\tthis._calcHeight();\n\t\t\t\t} else {\n\t\t\t\t\tisMobile = false;\n\t\t\t\t\tsetAttributes(navToggle, {\n\t\t\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t\t\t});\n\t\t\t\t\tsetAttributes(nav, {\n\t\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t\t});\n\t\t\t\t\tnav.style.position = opts.openPos;\n\t\t\t\t\tthis._removeStyles();\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Takes care of all even handling\n\t\t*\n\t\t* @param  {event} event\n\t\t* @return {type} returns the type of event that should be used\n\t\t*/\n\t\t\thandleEvent: function(e) {\n\t\t\t\tvar evt = e || window.event;\n\t\t\t\tswitch (evt.type) {\n\t\t\t\tcase \"touchstart\":\n\t\t\t\t\tthis._onTouchStart(evt);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"touchmove\":\n\t\t\t\t\tthis._onTouchMove(evt);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"touchend\":\n\t\t\t\tcase \"mouseup\":\n\t\t\t\t\tthis._onTouchEnd(evt);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"click\":\n\t\t\t\t\tthis._preventDefault(evt);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"keyup\":\n\t\t\t\t\tthis._onKeyUp(evt);\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"focus\":\n\t\t\t\tcase \"resize\":\n\t\t\t\t\tthis.resize(evt);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Initializes the widget\n\t\t*/\n\t\t\t_init: function() {\n\t\t\t\tthis.index = index++;\n\n\t\t\t\taddClass(nav, opts.navClass);\n\t\t\t\taddClass(nav, opts.navClass + \"-\" + this.index);\n\t\t\t\taddClass(nav, \"closed\");\n\t\t\t\thasAnimFinished = true;\n\t\t\t\tnavOpen = false;\n\n\t\t\t\tthis._closeOnNavClick();\n\t\t\t\tthis._createToggle();\n\t\t\t\tthis._transitions();\n\t\t\t\tthis.resize();\n\n\t\t\t\t/**\n\t\t\t* On IE8 the resize event triggers too early for some reason\n\t\t\t* so it's called here again on init to make sure all the\n\t\t\t* calculated styles are correct.\n\t\t\t*/\n\t\t\t\tvar self = this;\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tself.resize();\n\t\t\t\t},\n\t\t\t\t20);\n\n\t\t\t\taddEvent(window, \"resize\", this, false);\n\t\t\t\taddEvent(window, \"focus\", this, false);\n\t\t\t\taddEvent(document.body, \"touchmove\", this, false);\n\t\t\t\taddEvent(navToggle, \"touchstart\", this, false);\n\t\t\t\taddEvent(navToggle, \"touchend\", this, false);\n\t\t\t\taddEvent(navToggle, \"mouseup\", this, false);\n\t\t\t\taddEvent(navToggle, \"keyup\", this, false);\n\t\t\t\taddEvent(navToggle, \"click\", this, false);\n\n\t\t\t\t/**\n\t\t\t* Init callback here\n\t\t\t*/\n\t\t\t\topts.init();\n\t\t\t},\n\n\t\t\t/**\n\t\t* Creates Styles to the <head>\n\t\t*/\n\t\t\t_createStyles: function() {\n\t\t\t\tif (!styleElement.parentNode) {\n\t\t\t\t\tstyleElement.type = \"text/css\";\n\t\t\t\t\tdocument.getElementsByTagName(\"head\")[0].appendChild(styleElement);\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Removes styles from the <head>\n\t\t*/\n\t\t\t_removeStyles: function() {\n\t\t\t\tif (styleElement.parentNode) {\n\t\t\t\t\tstyleElement.parentNode.removeChild(styleElement);\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Creates Navigation Toggle\n\t\t*/\n\t\t\t_createToggle: function() {\n\t\t\t\t// If there's no toggle, let's create one\n\t\t\t\tif (!opts.customToggle) {\n\t\t\t\t\tvar toggle = document.createElement(\"a\");\n\t\t\t\t\ttoggle.innerHTML = opts.label;\n\t\t\t\t\tsetAttributes(toggle, {\n\t\t\t\t\t\t\"href\": \"#\",\n\t\t\t\t\t\t\"class\": \"nav-toggle\"\n\t\t\t\t\t});\n\n\t\t\t\t\t// Determine where to insert the toggle\n\t\t\t\t\tif (opts.insert === \"after\") {\n\t\t\t\t\t\tnav.parentNode.insertBefore(toggle, nav.nextSibling);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnav.parentNode.insertBefore(toggle, nav);\n\t\t\t\t\t}\n\n\t\t\t\t\tnavToggle = toggle;\n\n\t\t\t\t\t// There is a toggle already, let's use that one\n\t\t\t\t} else {\n\t\t\t\t\tvar toggleEl = opts.customToggle.replace(\"#\", \"\");\n\n\t\t\t\t\tif (document.getElementById(toggleEl)) {\n\t\t\t\t\t\tnavToggle = document.getElementById(toggleEl);\n\t\t\t\t\t} else if (document.querySelector(toggleEl)) {\n\t\t\t\t\t\tnavToggle = document.querySelector(toggleEl);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow new Error(\"The custom nav toggle you are trying to select doesn't exist\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Closes the navigation when a link inside is clicked.\n\t\t*/\n\t\t\t_closeOnNavClick: function() {\n\t\t\t\tif (opts.closeOnNavClick) {\n\t\t\t\t\tvar links = nav.getElementsByTagName(\"a\"),\n\t\t\t\t\tself = this;\n\t\t\t\t\tforEach(links,\n\t\t\t\t\tfunction(i, el) {\n\t\t\t\t\t\taddEvent(links[i], \"click\",\n\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\tif (isMobile) {\n\t\t\t\t\t\t\t\tself.toggle();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfalse);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Prevents the default functionality.\n\t\t*\n\t\t* @param  {event} event\n\t\t*/\n\t\t\t_preventDefault: function(e) {\n\t\t\t\tif (e.preventDefault) {\n\t\t\t\t\tif (e.stopImmediatePropagation) {\n\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t}\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t\treturn false;\n\n\t\t\t\t\t// This is strictly for old IE\n\t\t\t\t} else {\n\t\t\t\t\te.returnValue = false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* On touch start we get the location of the touch.\n\t\t*\n\t\t* @param  {event} event\n\t\t*/\n\t\t\t_onTouchStart: function(e) {\n\t\t\t\tif (!Event.prototype.stopImmediatePropagation) {\n\t\t\t\t\tthis._preventDefault(e);\n\t\t\t\t}\n\t\t\t\tthis.startX = e.touches[0].clientX;\n\t\t\t\tthis.startY = e.touches[0].clientY;\n\t\t\t\tthis.touchHasMoved = false;\n\n\t\t\t\t/**\n\t\t\t* Remove mouseup event completely here to avoid\n\t\t\t* double triggering the event.\n\t\t\t*/\n\t\t\t\tremoveEvent(navToggle, \"mouseup\", this, false);\n\t\t\t},\n\n\t\t\t/**\n\t\t* Check if the user is scrolling instead of tapping.\n\t\t*\n\t\t* @param  {event} event\n\t\t*/\n\t\t\t_onTouchMove: function(e) {\n\t\t\t\tif (Math.abs(e.touches[0].clientX - this.startX) > 10 || Math.abs(e.touches[0].clientY - this.startY) > 10) {\n\t\t\t\t\tthis.touchHasMoved = true;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* On touch end toggle the navigation.\n\t\t*\n\t\t* @param  {event} event\n\t\t*/\n\t\t\t_onTouchEnd: function(e) {\n\t\t\t\tthis._preventDefault(e);\n\t\t\t\tif (!isMobile) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// If the user isn't scrolling\n\t\t\t\tif (!this.touchHasMoved) {\n\n\t\t\t\t\t// If the event type is touch\n\t\t\t\t\tif (e.type === \"touchend\") {\n\t\t\t\t\t\tthis.toggle();\n\t\t\t\t\t\treturn;\n\n\t\t\t\t\t\t// Event type was click, not touch\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar evt = e || window.event;\n\n\t\t\t\t\t\t// If it isn't a right click, do toggling\n\t\t\t\t\t\tif (! (evt.which === 3 || evt.button === 2)) {\n\t\t\t\t\t\t\tthis.toggle();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* For keyboard accessibility, toggle the navigation on Enter\n\t\t* keypress too.\n\t\t*\n\t\t* @param  {event} event\n\t\t*/\n\t\t\t_onKeyUp: function(e) {\n\t\t\t\tvar evt = e || window.event;\n\t\t\t\tif (evt.keyCode === 13) {\n\t\t\t\t\tthis.toggle();\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Adds the needed CSS transitions if animations are enabled\n\t\t*/\n\t\t\t_transitions: function() {\n\t\t\t\tif (opts.animate) {\n\t\t\t\t\tvar objStyle = nav.style,\n\t\t\t\t\ttransition = \"max-height \" + opts.transition + \"ms\";\n\t\t\t\t\tobjStyle.WebkitTransition = objStyle.MozTransition = objStyle.OTransition = objStyle.transition = transition;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t/**\n\t\t* Calculates the height of the navigation and then creates\n\t\t* styles which are later added to the page <head>\n\t\t*/\n\t\t\t_calcHeight: function() {\n\t\t\t\tvar savedHeight = 0;\n\t\t\t\tfor (var i = 0; i < nav.inner.length; i++) {\n\t\t\t\t\tsavedHeight += nav.inner[i].offsetHeight;\n\t\t\t\t}\n\t\t\t\tvar innerStyles = \".\" + opts.jsClass + \" .\" + opts.navClass + \"-\" + this.index + \".opened{max-height:\" + savedHeight + \"px !important} .\" + opts.jsClass + \" .\" + opts.navClass + \"-\" + this.index + \".opened.dropdown-active {max-height:9999px !important}\";\n\t\t\t\tif (styleElement.styleSheet) {\n\t\t\t\t\tstyleElement.styleSheet.cssText = innerStyles;\n\t\t\t\t} else {\n\t\t\t\t\tstyleElement.innerHTML = innerStyles;\n\t\t\t\t}\n\t\t\t\tinnerStyles = \"\";\n\t\t\t}\n\t\t};\n\t\t/**\n\t\t* Return new Responsive Nav\n\t\t*/\n\t\treturn new ResponsiveNav(el, options);\n\t};\n\tif (typeof module !== \"undefined\" && module.exports) {\n\t\tmodule.exports = responsiveNav;\n\t} else {\n\t\twindow.responsiveNav = responsiveNav;\n\t}\n} (document, window, 0));\n\n/* =======================================================================\n * jQuery.placeholder.js 兼容性处理\n * ======================================================================== */\n!function(window, document, $) {\n\tvar isInputSupported = 'placeholder' in document.createElement('input');\n\tvar isTextareaSupported = 'placeholder' in document.createElement('textarea');\n\tvar prototype = $.fn;\n\tvar valHooks = $.valHooks;\n\tvar propHooks = $.propHooks;\n\tvar hooks;\n\tvar placeholder;\n\n\tif (isInputSupported && isTextareaSupported) {\n\t\tplaceholder = prototype.placeholder = function() {\n\t\t\treturn this;\n\t\t};\n\t\tplaceholder.input = placeholder.textarea = true;\n\t} else {\n\t\tplaceholder = prototype.placeholder = function() {\n\t\t\tvar $this = this;\n\t\t\t$this.filter((isInputSupported ? 'textarea': ':input') + '[placeholder]').not('.placeholder').on({\n\t\t\t\t'focus.placeholder': clearPlaceholder,\n\t\t\t\t'blur.placeholder': setPlaceholder\n\t\t\t}).data('placeholder-enabled', true).trigger('blur.placeholder');\n\t\t\treturn $this;\n\t\t};\n\t\tplaceholder.input = isInputSupported;\n\t\tplaceholder.textarea = isTextareaSupported;\n\t\thooks = {\n\t\t\t'get': function(element) {\n\t\t\t\tvar $element = $(element);\n\t\t\t\tvar $passwordInput = $element.data('placeholder-password');\n\t\t\t\tif ($passwordInput) {\n\t\t\t\t\treturn $passwordInput[0].value;\n\t\t\t\t}\n\t\t\t\treturn $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '': element.value;\n\t\t\t},\n\t\t\t'set': function(element, value) {\n\t\t\t\tvar $element = $(element);\n\t\t\t\tvar $passwordInput = $element.data('placeholder-password');\n\t\t\t\tif ($passwordInput) {\n\t\t\t\t\treturn $passwordInput[0].value = value;\n\t\t\t\t}\n\t\t\t\tif (!$element.data('placeholder-enabled')) {\n\t\t\t\t\treturn element.value = value;\n\t\t\t\t}\n\t\t\t\tif (value == '') {\n\t\t\t\t\telement.value = value;\n\t\t\t\t\tif (element != safeActiveElement()) {\n\t\t\t\t\t\tsetPlaceholder.call(element);\n\t\t\t\t\t}\n\t\t\t\t} else if ($element.hasClass('placeholder')) {\n\t\t\t\t\tclearPlaceholder.call(element, true, value) || (element.value = value);\n\t\t\t\t} else {\n\t\t\t\t\telement.value = value;\n\t\t\t\t}\n\t\t\t\treturn $element;\n\t\t\t}\n\t\t};\n\n\t\tif (!isInputSupported) {\n\t\t\tvalHooks.input = hooks;\n\t\t\tpropHooks.value = hooks;\n\t\t}\n\t\tif (!isTextareaSupported) {\n\t\t\tvalHooks.textarea = hooks;\n\t\t\tpropHooks.value = hooks;\n\t\t}\n\n\t\t$(function() {\n\t\t\t$(document).delegate('form', 'submit.placeholder',\n\t\t\tfunction() {\n\t\t\t\tvar $inputs = $('.placeholder', this).each(clearPlaceholder);\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\t$inputs.each(setPlaceholder);\n\t\t\t\t},\n\t\t\t\t10);\n\t\t\t});\n\t\t});\n\n\t\t$(window).on('beforeunload.placeholder',\n\t\tfunction() {\n\t\t\t$('.placeholder').each(function() {\n\t\t\t\tthis.value = '';\n\t\t\t});\n\t\t});\n\t}\n\n\tfunction args(elem) {\n\t\tvar newAttrs = {};\n\t\tvar rinlinejQuery = /^jQuery\\d+$/;\n\t\t$.each(elem.attributes,\n\t\tfunction(i, attr) {\n\t\t\tif (attr.specified && !rinlinejQuery.test(attr.name)) {\n\t\t\t\tnewAttrs[attr.name] = attr.value;\n\t\t\t}\n\t\t});\n\t\treturn newAttrs;\n\t}\n\n\tfunction clearPlaceholder(event, value) {\n\t\tvar input = this;\n\t\tvar $input = $(input);\n\t\tif (input.value == $input.attr('placeholder') && $input.hasClass('placeholder')) {\n\t\t\tif ($input.data('placeholder-password')) {\n\t\t\t\t$input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));\n\t\t\t\tif (event === true) {\n\t\t\t\t\treturn $input[0].value = value;\n\t\t\t\t}\n\t\t\t\t$input.focus();\n\t\t\t} else {\n\t\t\t\tinput.value = '';\n\t\t\t\t$input.removeClass('placeholder');\n\t\t\t\tinput == safeActiveElement() && input.select();\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction setPlaceholder() {\n\t\tvar $replacement;\n\t\tvar input = this;\n\t\tvar $input = $(input);\n\t\tvar id = this.id;\n\t\tif (input.value == '') {\n\t\t\tif (input.type == 'password') {\n\t\t\t\tif (!$input.data('placeholder-textinput')) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t$replacement = $input.clone().prop('type', 'text');\n\t\t\t\t\t} catch(e) {\n\t\t\t\t\t\t$replacement = $('<input>').prop($.extend(args(this), {\n\t\t\t\t\t\t\t'type': 'text'\n\t\t\t\t\t\t}));\n\t\t\t\t\t}\n\t\t\t\t\t$replacement.removeAttr('name').data({\n\t\t\t\t\t\t'placeholder-password': $input,\n\t\t\t\t\t\t'placeholder-id': id\n\t\t\t\t\t}).on('focus.placeholder', clearPlaceholder);\n\t\t\t\t\t$input.data({\n\t\t\t\t\t\t'placeholder-textinput': $replacement,\n\t\t\t\t\t\t'placeholder-id': id\n\t\t\t\t\t}).before($replacement);\n\t\t\t\t}\n\t\t\t\t$input = $input.removeAttr('id').hide().prev().attr('id', id).show();\n\t\t\t}\n\t\t\t$input.addClass('placeholder');\n\t\t\t$input[0].value = $input.attr('placeholder');\n\t\t} else {\n\t\t\t$input.removeClass('placeholder');\n\t\t}\n\t}\n\tfunction safeActiveElement() {\n\t\ttry {\n\t\t\treturn document.activeElement;\n\t\t} catch(exception) {}\n\t}\n} (this, document, jQuery);\n\n/* =======================================================================\n * jquery.emailsuggest.js v1.0 邮箱自动提示\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n!function($) {\n\tvar\n\t// 插件名\n\tplugin = 'emailsuggest',\n\n\t// 默认参数配置\n\tdefaults = {\n\t\tsugClass: 'emailSug',\n\t\tdomains: ['163.com', '126.com', 'sohu.com', '139.com', 'sina.com', 'qq.com', 'gmail.com']\n\t};\n\n\tfunction EmailSug(elem, options) {\n\t\tthis.$field = $(elem);\n\t\tthis.options = $.extend(true, {},\n\t\tdefaults, options);\n\t\tthis._defaults = defaults;\n\t\tthis._domains = this.options.domains;\n\t\t// 当前选中元素下标\n\t\tthis.selectedIndex = 0;\n\n\t\tthis.init();\n\t}\n\n\tEmailSug.prototype = {\n\t\tinit: function() {\n\t\t\tthis.addEvent();\n\t\t},\n\n\t\taddEvent: function() {\n\t\t\tvar that = this,\n\t\t\tvalue;\n\n\t\t\tthis.$field.on('keyup.ema',\n\t\t\tfunction(e) {\n\t\t\t\tvalue = $.trim(this.value);\n\n\t\t\t\tif (value) {\n\t\t\t\t\tthat.create(this, value);\n\t\t\t\t\tthat.doSelect(e.keyCode);\n\t\t\t\t} else {\n\t\t\t\t\tthat.hide();\n\t\t\t\t}\n\t\t\t}).on('blur.ema',\n\t\t\tfunction() {\n\t\t\t\tsetTimeout(function() {\n\t\t\t\t\tthat.hide();\n\t\t\t\t},\n\t\t\t\t200);\n\t\t\t});\n\t\t},\n\t\tcreate: function(elem, value) {\n\t\t\tvar that = this,\n\t\t\tarr, len, fragment, ul = [],\n\t\t\toffset,\n\t\t\tleft,\n\t\t\ttop,\n\t\t\twidth,\n\t\t\theight,\n\t\t\tstyle,\n\t\t\t// 左右边框\n\t\t\tborderWidth = 2;\n\n\t\t\telem = $(elem);\n\t\t\toffset = elem.offset();\n\t\t\twidth = elem.outerWidth(true) - borderWidth;\n\t\t\theight = elem.outerHeight(true);\n\t\t\tleft = offset.left;\n\t\t\ttop = offset.top + height;\n\t\t\tstyle = 'left: ' + left + 'px; top: ' + top + 'px; width: ' + width + 'px; border: 1px solid #e2e2e2; border-top: 0; display: none';\n\t\t\tfragment = $('<div class=\"' + this.options.sugClass + '-wrapper\" style=\"' + style + '\" />');\n\t\t\tul.push('<ul class=\"' + this.options.sugClass + '-list\">');\n\n\t\t\tarr = this.filter(value, this._domains);\n\t\t\tlen = arr.length;\n\t\t\t$.each(arr,\n\t\t\tfunction(i, domain) {\n\t\t\t\tvar _class = that.options.sugClass + '-item';\n\n\t\t\t\tif (that.selectedIndex > len - 1) {\n\t\t\t\t\tif (i === 0) {\n\t\t\t\t\t\t_class += ' active';\n\t\t\t\t\t\tthat.selectedIndex = 0;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (i === that.selectedIndex) {\n\t\t\t\t\t\t_class += ' active';\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tul.push('<li class=\"' + _class + '\" data-index=\"' + i + '\">' + value.replace(/@.*/, '') + '@' + domain + '</li>');\n\t\t\t});\n\n\t\t\tul.push('</ul>');\n\t\t\tul = ul.join('');\n\t\t\tif (this.$suggest) {\n\t\t\t\tthis.$suggest.empty();\n\t\t\t\tthis.$suggest.append(ul);\n\t\t\t} else {\n\t\t\t\tfragment.append(ul);\n\t\t\t\t// 显示到页面\n\t\t\t\t$('body').append(fragment);\n\t\t\t\tthis.$suggest = fragment;\n\t\t\t\tthis.$suggest.on('mouseenter click', '.' + this.options.sugClass + '-item',\n\t\t\t\tfunction(e) {\n\t\t\t\t\tvar lis, li;\n\t\t\t\t\tli = $(this);\n\t\t\t\t\tlis = li.parent().children();\n\t\t\t\t\tif (e.type === 'mouseenter') {\n\t\t\t\t\t\tli.addClass('active').siblings().removeClass('active');\n\t\t\t\t\t\tthat.selectedIndex = $.inArray(this, lis);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// 当前选中\n\t\t\t\t\t\tthat.$field.val(lis.eq(that.selectedIndex).text());\n\t\t\t\t\t\t// 隐藏email sug\n\t\t\t\t\t\tthat.hide();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t\tthis.show();\n\t\t},\n\n\t\tdoSelect: function(keyCode) {\n\t\t\tvar elems = $('.' + this.options.sugClass + '-item', this.$suggest),\n\t\t\tmin = 0,\n\t\t\tmax = elems.length - 1;\n\t\t\tswitch (keyCode) {\n\t\t\tcase 13:\n\t\t\t\t// 回车选中当前已选项\n\t\t\t\t$('li.active', this.$suggest).trigger('click');\n\n\t\t\t\t// 下标重置\n\t\t\t\tthis.selectedIndex = 0;\n\n\t\t\t\tbreak;\n\t\t\t\t// 向上\n\t\t\tcase 38:\n\t\t\t\tthis.selectedIndex--;\n\n\t\t\t\tif (this.selectedIndex < min) {\n\t\t\t\t\tthis.selectedIndex = max;\n\t\t\t\t}\n\n\t\t\t\telems.removeClass('active').eq(this.selectedIndex).addClass('active');\n\t\t\t\tbreak;\n\t\t\t\t// 向下\n\t\t\tcase 40:\n\t\t\t\tthis.selectedIndex++;\n\n\t\t\t\tif (this.selectedIndex > max) {\n\t\t\t\t\tthis.selectedIndex = min;\n\t\t\t\t}\n\n\t\t\t\telems.removeClass('active').eq(this.selectedIndex).addClass('active');\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\t\tfilter: function(value, arr) {\n\t\t\tvar start, suffix, r = [];\n\n\t\t\tstart = value.indexOf('@');\n\t\t\tif (start > -1) {\n\t\t\t\tsuffix = value.substring(start + 1);\n\t\t\t\t$.each(arr,\n\t\t\t\tfunction(i, str) {\n\t\t\t\t\tif (str.indexOf(suffix) > -1) {\n\t\t\t\t\t\tr.push(str);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tr = arr;\n\t\t\t}\n\t\t\treturn r;\n\t\t},\n\t\tshow: function() {\n\t\t\tif (this.$suggest) {\n\t\t\t\tthis.$suggest.show();\n\t\t\t}\n\t\t},\n\n\t\thide: function() {\n\t\t\tif (this.$suggest) {\n\t\t\t\tthis.$suggest.hide();\n\t\t\t}\n\t\t}\n\t}\n\n\t$.fn[plugin] = function(options) {\n\t\treturn this.each(function() {\n\t\t\tif (!$.data(this, plugin)) {\n\t\t\t\t$.data(this, plugin, new EmailSug(this, options));\n\t\t\t}\n\t\t});\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huispinner.js v2.1.2 微调器\n * http://www.h-ui.net/\n * Created & Modified by guojunhui\n * Date modified 2017.06.26\n *\n * Copyright 2017 北京颖杰联创科技有限公司 All rights reserved.\n * Licensed under MIT license.\n * http://opensource.org/licenses/MIT\n * ========================================================================*/\n!function($) {\n\t$.fn.Huispinner = function(options, callback) {\n\t\tvar defaults = {\n\t\t\tvalue : 1,\n\t\t\tminValue : 1,\n\t\t\tmaxValue : 999,\n\t\t\tdis : 1,\n\t\t}\n\t\tvar options = $.extend(defaults, options);\n\t\tvar keyCodes = {\n\t\t\tup : 38,\n\t\t\tdown : 40\n\t\t}\n\n\t\tthis.each(function() {\n\t\t\tvar that = $(this);\n\t\t\tvar str = '<div class=\"spinner\">'\n\t\t\t\t\t+ '<a class=\"subtract\" href=\"javascript:void(0)\"><i>-</i></a>'\n\t\t\t\t\t+ '<input class=\"amount input-text\" value=\"'\n\t\t\t\t\t+ options.value + '\" autocomplete=\"off\">'\n\t\t\t\t\t+ '<a class=\"add\" href=\"javascript:void(0)\"><i>+</i></a>'\n\t\t\t\t\t+ '</div>';\n\t\t\tthat.append(str);\n\n\t\t\tvar input = that.find(\".input-text\"),\n\t\t\t\tsubtract = that.find(\".subtract\"),\n\t\t\t\tadd = that.find(\".add\"),\n\t\t\t\tvalue = parseInt(input.val());\n\n\t\t\tif (value <= options.minValue) {\n\t\t\t\tsubtract.addClass(\"disabled\");\n\t\t\t\tadd.removeClass(\"disabled\");\n\t\t\t}\n\t\t\tif (value >= options.maxValue) {\n\t\t\t\tsubtract.removeClass(\"disabled\");\n\t\t\t\tadd.addClass(\"disabled\");\n\t\t\t}\n\n\t\t\t// 输入框失去焦点\n\t\t\tinput.on('blur', function() {\n\t\t\t\tvar v = $(this).val();\n\t\t\t\tv = v.replace(/[^\\d]/g, \"\");\n\t\t\t\tv = v.replace(/\\b(0+)/gi, \"\");\n\n\t\t\t\tif (v != \"\") {\n\t\t\t\t\tif (v > options.minValue && v < options.maxValue) {\n\t\t\t\t\t\tinput.val(v)\n\t\t\t\t\t\tadd.removeClass(\"disabled\");\n\t\t\t\t\t\tsubtract.removeClass(\"disabled\");\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (v <= options.minValue) {\n\t\t\t\t\t\t\tinput.val(options.minValue);\n\t\t\t\t\t\t\tsubtract.addClass(\"disabled\");\n\t\t\t\t\t\t\tadd.removeClass(\"disabled\");\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tinput.val(options.maxValue);\n\t\t\t\t\t\t\tsubtract.removeClass(\"disabled\");\n\t\t\t\t\t\t\tadd.addClass(\"disabled\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$(this).val(options.minValue);\n\t\t\t\t\tsubtract.addClass(\"disabled\");\n\t\t\t\t\tadd.removeClass(\"disabled\");\n\t\t\t\t}\n\t\t\t\tif (callback) {\n\t\t\t\t\tcallback(input.val());\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// 上下方向键\n\t\t\tinput.on(\"keydown\", function(e) {\n\t\t\t\tvar evt = e || window.event;\n\t\t\t\tif (evt.keyCode === keyCodes.up) {\n\t\t\t\t\tsubtract.trigger(\"click\");\n\t\t\t\t\tevt.returnValue = false;\n\t\t\t\t}\n\t\t\t\tif (evt.keyCode === keyCodes.down) {\n\t\t\t\t\tadd.trigger(\"click\");\n\t\t\t\t\tevt.returnValue = false;\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// 减\n\t\t\tsubtract.on('click', function() {\n\t\t\t\tvar goodsCount = parseInt(input.val());\n\t\t\t\tinput.val(goodsCount <= options.minValue\n\t\t\t\t\t\t? options.minValue\n\t\t\t\t\t\t: goodsCount - options.dis);\n\t\t\t\tadd.removeClass(\"disabled\");\n\t\t\t\tif (input.val() <= options.minValue) {\n\t\t\t\t\tinput.val(options.minValue)\n\t\t\t\t\tsubtract.addClass(\"disabled\");\n\t\t\t\t}\n\t\t\t\tif (callback) {\n\t\t\t\t\tcallback(input.val());\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// 加\n\t\t\tadd.on('click', function() {\n\t\t\t\tvar goodsCount = parseInt(input.val());\n\t\t\t\tinput.val(goodsCount >= options.maxValue\n\t\t\t\t\t\t? options.maxValue\n\t\t\t\t\t\t: goodsCount + options.dis);\n\t\t\t\tsubtract.removeClass(\"disabled\");\n\n\t\t\t\tif (input.val() >= options.maxValue) {\n\t\t\t\t\tinput.val(options.maxValue);\n\t\t\t\t\tadd.addClass(\"disabled\");\n\t\t\t\t}\n\t\t\t\tif (callback) {\n\t\t\t\t\tcallback(input.val());\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n}(window.jQuery);\n\n/* =======================================================================\n * jQuery.format.js 金额格式化\n * ========================================================================*/\n!function($) {\n\t$.extend({\n\t\tformat: function(str, step, splitor) {\n\t\t\tstr = str.toString();\n\t\t\tvar len = str.length;\n\n\t\t\tif (len > step) {\n\t\t\t\tvar l1 = len % step,\n\t\t\t\tl2 = parseInt(len / step),\n\t\t\t\tarr = [],\n\t\t\t\tfirst = str.substr(0, l1);\n\t\t\t\tif (first != '') {\n\t\t\t\t\tarr.push(first);\n\t\t\t\t};\n\t\t\t\tfor (var i = 0; i < l2; i++) {\n\t\t\t\t\tarr.push(str.substr(l1 + i * step, step));\n\t\t\t\t};\n\t\t\t\tstr = arr.join(splitor);\n\t\t\t};\n\t\t\treturn str;\n\t\t}\n\t});\n} (window.jQuery);\n\n/* =======================================================================\n * jquery.togglePassword.js 隐藏显示密码\n * type=\"password\"\n * ========================================================================*/\n!function($) {\n\t$.fn.togglePassword = function(options) {\n\t\tvar s = $.extend($.fn.togglePassword.defaults, options),\n\t\tinput = $(this);\n\n\t\t$(s.el).on(s.ev,\n\t\tfunction() {\n\t\t\t\"password\" == $(input).attr(\"type\") ? $(input).attr(\"type\", \"text\") : $(input).attr(\"type\", \"password\");\n\t\t});\n\t};\n\n\t$.fn.togglePassword.defaults = {\n\t\tev: \"click\"\n\t};\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.iCheck.js v1.0.2, http://git.io/arlzeA\n * Powerful jQuery and Zepto plugin for checkboxes and radio buttons customization\n *\n * (c) 2013 Damir Sultanov, http://fronteed.com\n * MIT Licensed\n * ======================================================================== */\n!(function($) {\n\t// Cached vars\n\tvar _iCheck = 'iCheck',\n\t_iCheckHelper = _iCheck + '-helper',\n\t_checkbox = 'checkbox',\n\t_radio = 'radio',\n\t_checked = 'checked',\n\t_unchecked = 'un' + _checked,\n\t_disabled = 'disabled',\n\t_determinate = 'determinate',\n\t_indeterminate = 'in' + _determinate,\n\t_update = 'update',\n\t_type = 'type',\n\t_click = 'click',\n\t_touch = 'touchbegin.i touchend.i',\n\t_add = 'addClass',\n\t_remove = 'removeClass',\n\t_callback = 'trigger',\n\t_label = 'label',\n\t_cursor = 'cursor',\n\t_mobile = /ipad|iphone|ipod|android|blackberry|windows phone|opera mini|silk/i.test(navigator.userAgent);\n\n\t// Plugin init\n\t$.fn[_iCheck] = function(options, fire) {\n\t\t// Walker\n\t\tvar handle = 'input[type=\"' + _checkbox + '\"], input[type=\"' + _radio + '\"]',\n\t\tstack = $(),\n\t\twalker = function(object) {\n\t\t\tobject.each(function() {\n\t\t\t\tvar self = $(this);\n\n\t\t\t\tif (self.is(handle)) {\n\t\t\t\t\tstack = stack.add(self);\n\t\t\t\t} else {\n\t\t\t\t\tstack = stack.add(self.find(handle));\n\t\t\t\t}\n\t\t\t});\n\t\t};\n\n\t\t// Check if we should operate with some method\n\t\tif (/^(check|uncheck|toggle|indeterminate|determinate|disable|enable|update|destroy)$/i.test(options)) {\n\n\t\t\t// Normalize method's name\n\t\t\toptions = options.toLowerCase();\n\n\t\t\t// Find checkboxes and radio buttons\n\t\t\twalker(this);\n\n\t\t\treturn stack.each(function() {\n\t\t\t\tvar self = $(this);\n\n\t\t\t\tif (options == 'destroy') {\n\t\t\t\t\ttidy(self, 'ifDestroyed');\n\t\t\t\t} else {\n\t\t\t\t\toperate(self, true, options);\n\t\t\t\t}\n\n\t\t\t\t// Fire method's callback\n\t\t\t\tif ($.isFunction(fire)) {\n\t\t\t\t\tfire();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t// Customization\n\t\t} else if (typeof options == 'object' || !options) {\n\n\t\t\t// Check if any options were passed\n\t\t\tvar settings = $.extend({\n\t\t\t\tcheckedClass: _checked,\n\t\t\t\tdisabledClass: _disabled,\n\t\t\t\tindeterminateClass: _indeterminate,\n\t\t\t\tlabelHover: true\n\t\t\t},\n\t\t\toptions),\n\n\t\t\tselector = settings.handle,\n\t\t\thoverClass = settings.hoverClass || 'hover',\n\t\t\tfocusClass = settings.focusClass || 'focus',\n\t\t\tactiveClass = settings.activeClass || 'active',\n\t\t\tlabelHover = !!settings.labelHover,\n\t\t\tlabelHoverClass = settings.labelHoverClass || 'hover',\n\n\t\t\t// Setup clickable area\n\t\t\tarea = ('' + settings.increaseArea).replace('%', '') | 0;\n\n\t\t\t// Selector limit\n\t\t\tif (selector == _checkbox || selector == _radio) {\n\t\t\t\thandle = 'input[type=\"' + selector + '\"]';\n\t\t\t}\n\n\t\t\t// Clickable area limit\n\t\t\tif (area < -50) {\n\t\t\t\tarea = -50;\n\t\t\t}\n\n\t\t\t// Walk around the selector\n\t\t\twalker(this);\n\n\t\t\treturn stack.each(function() {\n\t\t\t\tvar self = $(this);\n\n\t\t\t\t// If already customized\n\t\t\t\ttidy(self);\n\n\t\t\t\tvar node = this,\n\t\t\t\tid = node.id,\n\n\t\t\t\t// Layer styles\n\t\t\t\toffset = -area + '%',\n\t\t\t\tsize = 100 + (area * 2) + '%',\n\t\t\t\tlayer = {\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\ttop: offset,\n\t\t\t\t\tleft: offset,\n\t\t\t\t\tdisplay: 'block',\n\t\t\t\t\twidth: size,\n\t\t\t\t\theight: size,\n\t\t\t\t\tmargin: 0,\n\t\t\t\t\tpadding: 0,\n\t\t\t\t\tbackground: '#fff',\n\t\t\t\t\tborder: 0,\n\t\t\t\t\topacity: 0\n\t\t\t\t},\n\n\t\t\t\t// Choose how to hide input\n\t\t\t\thide = _mobile ? {\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\tvisibility: 'hidden'\n\t\t\t\t}: area ? layer: {\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\topacity: 0\n\t\t\t\t},\n\n\t\t\t\t// Get proper class\n\t\t\t\tclassName = node[_type] == _checkbox ? settings.checkboxClass || 'i' + _checkbox: settings.radioClass || 'i' + _radio,\n\n\t\t\t\t// Find assigned labels\n\t\t\t\tlabel = $(_label + '[for=\"' + id + '\"]').add(self.closest(_label)),\n\n\t\t\t\t// Check ARIA option\n\t\t\t\taria = !!settings.aria,\n\n\t\t\t\t// Set ARIA placeholder\n\t\t\t\tariaID = _iCheck + '-' + Math.random().toString(36).substr(2, 6),\n\n\t\t\t\t// Parent & helper\n\t\t\t\tparent = '<div class=\"' + className + '\" ' + (aria ? 'role=\"' + node[_type] + '\" ': ''),\n\t\t\t\thelper;\n\n\t\t\t\t// Set ARIA \"labelledby\"\n\t\t\t\tif (aria) {\n\t\t\t\t\tlabel.each(function() {\n\t\t\t\t\t\tparent += 'aria-labelledby=\"';\n\n\t\t\t\t\t\tif (this.id) {\n\t\t\t\t\t\t\tparent += this.id;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.id = ariaID;\n\t\t\t\t\t\t\tparent += ariaID;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparent += '\"';\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Wrap input\n\t\t\t\tparent = self.wrap(parent + '/>')[_callback]('ifCreated').parent().append(settings.insert);\n\n\t\t\t\t// Layer addition\n\t\t\t\thelper = $('<ins class=\"' + _iCheckHelper + '\"/>').css(layer).appendTo(parent);\n\n\t\t\t\t// Finalize customization\n\t\t\t\tself.data(_iCheck, {\n\t\t\t\t\to: settings,\n\t\t\t\t\ts: self.attr('style')\n\t\t\t\t}).css(hide); !! settings.inheritClass && parent[_add](node.className || ''); !! settings.inheritID && id && parent.attr('id', _iCheck + '-' + id);\n\t\t\t\tparent.css('position') == 'static' && parent.css('position', 'relative');\n\t\t\t\toperate(self, true, _update);\n\n\t\t\t\t// Label events\n\t\t\t\tif (label.length) {\n\t\t\t\t\tlabel.on(_click + '.i mouseover.i mouseout.i ' + _touch,\n\t\t\t\t\tfunction(event) {\n\t\t\t\t\t\tvar type = event[_type],\n\t\t\t\t\t\titem = $(this);\n\n\t\t\t\t\t\t// Do nothing if input is disabled\n\t\t\t\t\t\tif (!node[_disabled]) {\n\n\t\t\t\t\t\t\t// Click\n\t\t\t\t\t\t\tif (type == _click) {\n\t\t\t\t\t\t\t\tif ($(event.target).is('a')) {\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\toperate(self, false, true);\n\n\t\t\t\t\t\t\t\t// Hover state\n\t\t\t\t\t\t\t} else if (labelHover) {\n\n\t\t\t\t\t\t\t\t// mouseout|touchend\n\t\t\t\t\t\t\t\tif (/ut|nd/.test(type)) {\n\t\t\t\t\t\t\t\t\tparent[_remove](hoverClass);\n\t\t\t\t\t\t\t\t\titem[_remove](labelHoverClass);\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tparent[_add](hoverClass);\n\t\t\t\t\t\t\t\t\titem[_add](labelHoverClass);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (_mobile) {\n\t\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Input events\n\t\t\t\tself.on(_click + '.i focus.i blur.i keyup.i keydown.i keypress.i',\n\t\t\t\tfunction(event) {\n\t\t\t\t\tvar type = event[_type],\n\t\t\t\t\tkey = event.keyCode;\n\n\t\t\t\t\t// Click\n\t\t\t\t\tif (type == _click) {\n\t\t\t\t\t\treturn false;\n\n\t\t\t\t\t\t// Keydown\n\t\t\t\t\t} else if (type == 'keydown' && key == 32) {\n\t\t\t\t\t\tif (! (node[_type] == _radio && node[_checked])) {\n\t\t\t\t\t\t\tif (node[_checked]) {\n\t\t\t\t\t\t\t\toff(self, _checked);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ton(self, _checked);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn false;\n\n\t\t\t\t\t\t// Keyup\n\t\t\t\t\t} else if (type == 'keyup' && node[_type] == _radio) { ! node[_checked] && on(self, _checked);\n\n\t\t\t\t\t\t// Focus/blur\n\t\t\t\t\t} else if (/us|ur/.test(type)) {\n\t\t\t\t\t\tparent[type == 'blur' ? _remove: _add](focusClass);\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\t// Helper events\n\t\t\t\thelper.on(_click + ' mousedown mouseup mouseover mouseout ' + _touch,\n\t\t\t\tfunction(event) {\n\t\t\t\t\tvar type = event[_type],\n\n\t\t\t\t\t// mousedown|mouseup\n\t\t\t\t\ttoggle = /wn|up/.test(type) ? activeClass: hoverClass;\n\n\t\t\t\t\t// Do nothing if input is disabled\n\t\t\t\t\tif (!node[_disabled]) {\n\n\t\t\t\t\t\t// Click\n\t\t\t\t\t\tif (type == _click) {\n\t\t\t\t\t\t\toperate(self, false, true);\n\n\t\t\t\t\t\t\t// Active and hover states\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// State is on\n\t\t\t\t\t\t\tif (/wn|er|in/.test(type)) {\n\n\t\t\t\t\t\t\t\t// mousedown|mouseover|touchbegin\n\t\t\t\t\t\t\t\tparent[_add](toggle);\n\n\t\t\t\t\t\t\t\t// State is off\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tparent[_remove](toggle + ' ' + activeClass);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Label hover\n\t\t\t\t\t\t\tif (label.length && labelHover && toggle == hoverClass) {\n\n\t\t\t\t\t\t\t\t// mouseout|touchend\n\t\t\t\t\t\t\t\tlabel[/ut|nd/.test(type) ? _remove: _add](labelHoverClass);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (_mobile) {\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t});\n\t\t} else {\n\t\t\treturn this;\n\t\t}\n\t};\n\n\t// Do something with inputs\n\tfunction operate(input, direct, method) {\n\t\tvar node = input[0],\n\t\tstate = /er/.test(method) ? _indeterminate: /bl/.test(method) ? _disabled: _checked,\n\t\tactive = method == _update ? {\n\t\t\tchecked: node[_checked],\n\t\t\tdisabled: node[_disabled],\n\t\t\tindeterminate: input.attr(_indeterminate) == 'true' || input.attr(_determinate) == 'false'\n\t\t}: node[state];\n\n\t\t// Check, disable or indeterminate\n\t\tif (/^(ch|di|in)/.test(method) && !active) {\n\t\t\ton(input, state);\n\n\t\t\t// Uncheck, enable or determinate\n\t\t} else if (/^(un|en|de)/.test(method) && active) {\n\t\t\toff(input, state);\n\n\t\t\t// Update\n\t\t} else if (method == _update) {\n\n\t\t\t// Handle states\n\t\t\tfor (var each in active) {\n\t\t\t\tif (active[each]) {\n\t\t\t\t\ton(input, each, true);\n\t\t\t\t} else {\n\t\t\t\t\toff(input, each, true);\n\t\t\t\t}\n\t\t\t}\n\n\t\t} else if (!direct || method == 'toggle') {\n\n\t\t\t// Helper or label was clicked\n\t\t\tif (!direct) {\n\t\t\t\tinput[_callback]('ifClicked');\n\t\t\t}\n\n\t\t\t// Toggle checked state\n\t\t\tif (active) {\n\t\t\t\tif (node[_type] !== _radio) {\n\t\t\t\t\toff(input, state);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ton(input, state);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Add checked, disabled or indeterminate state\n\tfunction on(input, state, keep) {\n\t\tvar node = input[0],\n\t\tparent = input.parent(),\n\t\tchecked = state == _checked,\n\t\tindeterminate = state == _indeterminate,\n\t\tdisabled = state == _disabled,\n\t\tcallback = indeterminate ? _determinate: checked ? _unchecked: 'enabled',\n\t\tregular = option(input, callback + capitalize(node[_type])),\n\t\tspecific = option(input, state + capitalize(node[_type]));\n\n\t\t// Prevent unnecessary actions\n\t\tif (node[state] !== true) {\n\n\t\t\t// Toggle assigned radio buttons\n\t\t\tif (!keep && state == _checked && node[_type] == _radio && node.name) {\n\t\t\t\tvar form = input.closest('form'),\n\t\t\t\tinputs = 'input[name=\"' + node.name + '\"]';\n\n\t\t\t\tinputs = form.length ? form.find(inputs) : $(inputs);\n\n\t\t\t\tinputs.each(function() {\n\t\t\t\t\tif (this !== node && $(this).data(_iCheck)) {\n\t\t\t\t\t\toff($(this), state);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t// Indeterminate state\n\t\t\tif (indeterminate) {\n\n\t\t\t\t// Add indeterminate state\n\t\t\t\tnode[state] = true;\n\n\t\t\t\t// Remove checked state\n\t\t\t\tif (node[_checked]) {\n\t\t\t\t\toff(input, _checked, 'force');\n\t\t\t\t}\n\n\t\t\t\t// Checked or disabled state\n\t\t\t} else {\n\n\t\t\t\t// Add checked or disabled state\n\t\t\t\tif (!keep) {\n\t\t\t\t\tnode[state] = true;\n\t\t\t\t}\n\n\t\t\t\t// Remove indeterminate state\n\t\t\t\tif (checked && node[_indeterminate]) {\n\t\t\t\t\toff(input, _indeterminate, false);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Trigger callbacks\n\t\t\tcallbacks(input, checked, state, keep);\n\t\t}\n\n\t\t// Add proper cursor\n\t\tif (node[_disabled] && !!option(input, _cursor, true)) {\n\t\t\tparent.find('.' + _iCheckHelper).css(_cursor, 'default');\n\t\t}\n\n\t\t// Add state class\n\t\tparent[_add](specific || option(input, state) || '');\n\n\t\t// Set ARIA attribute\n\t\tif ( !! parent.attr('role') && !indeterminate) {\n\t\t\tparent.attr('aria-' + (disabled ? _disabled: _checked), 'true');\n\t\t}\n\n\t\t// Remove regular state class\n\t\tparent[_remove](regular || option(input, callback) || '');\n\t}\n\n\t// Remove checked, disabled or indeterminate state\n\tfunction off(input, state, keep) {\n\t\tvar node = input[0],\n\t\tparent = input.parent(),\n\t\tchecked = state == _checked,\n\t\tindeterminate = state == _indeterminate,\n\t\tdisabled = state == _disabled,\n\t\tcallback = indeterminate ? _determinate: checked ? _unchecked: 'enabled',\n\t\tregular = option(input, callback + capitalize(node[_type])),\n\t\tspecific = option(input, state + capitalize(node[_type]));\n\n\t\t// Prevent unnecessary actions\n\t\tif (node[state] !== false) {\n\n\t\t\t// Toggle state\n\t\t\tif (indeterminate || !keep || keep == 'force') {\n\t\t\t\tnode[state] = false;\n\t\t\t}\n\n\t\t\t// Trigger callbacks\n\t\t\tcallbacks(input, checked, callback, keep);\n\t\t}\n\n\t\t// Add proper cursor\n\t\tif (!node[_disabled] && !!option(input, _cursor, true)) {\n\t\t\tparent.find('.' + _iCheckHelper).css(_cursor, 'pointer');\n\t\t}\n\n\t\t// Remove state class\n\t\tparent[_remove](specific || option(input, state) || '');\n\n\t\t// Set ARIA attribute\n\t\tif ( !! parent.attr('role') && !indeterminate) {\n\t\t\tparent.attr('aria-' + (disabled ? _disabled: _checked), 'false');\n\t\t}\n\n\t\t// Add regular state class\n\t\tparent[_add](regular || option(input, callback) || '');\n\t}\n\n\t// Remove all traces\n\tfunction tidy(input, callback) {\n\t\tif (input.data(_iCheck)) {\n\n\t\t\t// Remove everything except input\n\t\t\tinput.parent().html(input.attr('style', input.data(_iCheck).s || ''));\n\n\t\t\t// Callback\n\t\t\tif (callback) {\n\t\t\t\tinput[_callback](callback);\n\t\t\t}\n\n\t\t\t// Unbind events\n\t\t\tinput.off('.i').unwrap();\n\t\t\t$(_label + '[for=\"' + input[0].id + '\"]').add(input.closest(_label)).off('.i');\n\t\t}\n\t}\n\n\t// Get some option\n\tfunction option(input, state, regular) {\n\t\tif (input.data(_iCheck)) {\n\t\t\treturn input.data(_iCheck).o[state + (regular ? '': 'Class')];\n\t\t}\n\t}\n\n\t// Capitalize some string\n\tfunction capitalize(string) {\n\t\treturn string.charAt(0).toUpperCase() + string.slice(1);\n\t}\n\n\t// Executable handlers\n\tfunction callbacks(input, checked, callback, keep) {\n\t\tif (!keep) {\n\t\t\tif (checked) {\n\t\t\t\tinput[_callback]('ifToggled');\n\t\t\t}\n\n\t\t\tinput[_callback]('ifChanged')[_callback]('if' + capitalize(callback));\n\t\t}\n\t}\n})(window.jQuery || window.Zepto);\n\n/* =======================================================================\n * jQuery.raty.js v2.4.5- A Star Rating Plugin\n * -------------------------------------------------------------------\n * jQuery Raty is a plugin that generates a customizable star rating.\n * Licensed under The MIT License\n *\n * @version        2.4.5\n * @since          2010.06.11\n * @author         Washington Botelho\n * @documentation  wbotelhos.com/raty\n * @twitter        twitter.com/wbotelhos\n *\n * Usage:\n * -------------------------------------------------------------------\n * $('#star').raty();\n * <div id=\"star\"></div>\n * ======================================================================== */\n!(function($) {\n\tvar methods = {\n\t\tinit: function(settings) {\n\t\t\treturn this.each(function() {\n\t\t\t\tvar self = this,\n\t\t\t\t$this = $(self).empty();\n\t\t\t\tself.opt = $.extend(true, {},\n\t\t\t\t$.fn.raty.defaults, settings);\n\t\t\t\t$this.data('settings', self.opt);\n\t\t\t\tself.opt.number = methods.between(self.opt.number, 0, 20);\n\t\t\t\tif (self.opt.path.substring(self.opt.path.length - 1, self.opt.path.length) != '/') {\n\t\t\t\t\tself.opt.path += '/';\n\t\t\t\t}\n\t\t\t\tif (typeof self.opt.score == 'function') {\n\t\t\t\t\tself.opt.score = self.opt.score.call(self);\n\t\t\t\t}\n\t\t\t\tif (self.opt.score) {\n\t\t\t\t\tself.opt.score = methods.between(self.opt.score, 0, self.opt.number);\n\t\t\t\t}\n\t\t\t\tfor (var i = 1; i <= self.opt.number; i++) {\n\t\t\t\t\t$('<img />', {\n\t\t\t\t\t\tsrc: self.opt.path + ((!self.opt.score || self.opt.score < i) ? self.opt.starOff: self.opt.starOn),\n\t\t\t\t\t\talt: i,\n\t\t\t\t\t\ttitle: (i <= self.opt.hints.length && self.opt.hints[i - 1] !== null) ? self.opt.hints[i - 1] : i\n\t\t\t\t\t}).appendTo(self);\n\n\t\t\t\t\tif (self.opt.space) {\n\t\t\t\t\t\t$this.append((i < self.opt.number) ? '': '');\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tself.stars = $this.children('img:not(\".raty-cancel\")');\n\t\t\t\tself.score = $('<input />', {\n\t\t\t\t\ttype: 'hidden',\n\t\t\t\t\tname: self.opt.scoreName\n\t\t\t\t}).appendTo(self);\n\t\t\t\tif (self.opt.score && self.opt.score > 0) {\n\t\t\t\t\tself.score.val(self.opt.score);\n\t\t\t\t\tmethods.roundStar.call(self, self.opt.score);\n\t\t\t\t}\n\t\t\t\tif (self.opt.iconRange) {\n\t\t\t\t\tmethods.fill.call(self, self.opt.score);\t\t\t\t}\n\t\t\t\tmethods.setTarget.call(self, self.opt.score, self.opt.targetKeep);\n\t\t\t\tvar space = self.opt.space ? 4 : 0,\n\t\t\t\twidth = self.opt.width || (self.opt.number * self.opt.size + self.opt.number * space);\n\t\t\t\tif (self.opt.cancel) {\n\t\t\t\t\tself.cancel = $('<img />', {\n\t\t\t\t\t\tsrc: self.opt.path + self.opt.cancelOff,\n\t\t\t\t\t\talt: 'x',\n\t\t\t\t\t\ttitle: self.opt.cancelHint,\n\t\t\t\t\t\t'class': 'raty-cancel'\n\t\t\t\t\t});\n\t\t\t\t\tif (self.opt.cancelPlace == 'left') {\n\t\t\t\t\t\t//$this.prepend('&#160;').prepend(self.cancel);\n\t\t\t\t\t} else {\n\t\t\t\t\t\t//$this.append('&#160;').append(self.cancel);\n\t\t\t\t\t}\n\t\t\t\t\twidth += (self.opt.size + space);\n\t\t\t\t}\n\t\t\t\tif (self.opt.readOnly) {\n\t\t\t\t\tmethods.fixHint.call(self);\n\n\t\t\t\t\tif (self.cancel) {\n\t\t\t\t\t\tself.cancel.hide();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$this.css('cursor', 'pointer');\n\t\t\t\t\tmethods.bindAction.call(self);\n\t\t\t\t}\n\t\t\t\t//$this.css('width', width);\n\t\t\t});\n\t\t},\n\t\tbetween: function(value, min, max) {\n\t\t\treturn Math.min(Math.max(parseFloat(value), min), max);\n\t\t},\n\t\tbindAction: function() {\n\t\t\tvar self = this,\n\t\t\t$this = $(self);\n\t\t\t$this.mouseleave(function() {\n\t\t\t\tvar score = self.score.val() || undefined;\n\n\t\t\t\tmethods.initialize.call(self, score);\n\t\t\t\tmethods.setTarget.call(self, score, self.opt.targetKeep);\n\n\t\t\t\tif (self.opt.mouseover) {\n\t\t\t\t\tself.opt.mouseover.call(self, score);\n\t\t\t\t}\n\t\t\t});\n\t\t\tvar action = self.opt.half ? 'mousemove': 'mouseover';\n\t\t\tif (self.opt.cancel) {\n\t\t\t\tself.cancel.mouseenter(function() {\n\t\t\t\t\t$(this).attr('src', self.opt.path + self.opt.cancelOn);\n\n\t\t\t\t\tself.stars.attr('src', self.opt.path + self.opt.starOff);\n\n\t\t\t\t\tmethods.setTarget.call(self, null, true);\n\n\t\t\t\t\tif (self.opt.mouseover) {\n\t\t\t\t\t\tself.opt.mouseover.call(self, null);\n\t\t\t\t\t}\n\t\t\t\t}).mouseleave(function() {\n\t\t\t\t\t$(this).attr('src', self.opt.path + self.opt.cancelOff);\n\n\t\t\t\t\tif (self.opt.mouseover) {\n\t\t\t\t\t\tself.opt.mouseover.call(self, self.score.val() || null);\n\t\t\t\t\t}\n\t\t\t\t}).click(function(evt) {\n\t\t\t\t\tself.score.removeAttr('value');\n\t\t\t\t\tif (self.opt.click) {\n\t\t\t\t\t\tself.opt.click.call(self, null, evt);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tself.stars.bind(action,\n\t\t\tfunction(evt) {\n\t\t\t\tvar value = parseInt(this.alt, 10);\n\t\t\t\tif (self.opt.half) {\n\t\t\t\t\tvar position = parseFloat((evt.pageX - $(this).offset().left) / self.opt.size),\n\t\t\t\t\tdiff = (position > .5) ? 1 : .5;\n\t\t\t\t\tvalue = parseFloat(this.alt) - 1 + diff;\n\t\t\t\t\tmethods.fill.call(self, value);\n\t\t\t\t\tif (self.opt.precision) {\n\t\t\t\t\t\tvalue = value - diff + position;\n\t\t\t\t\t}\n\t\t\t\t\tmethods.showHalf.call(self, value);\n\t\t\t\t} else {\n\t\t\t\t\tmethods.fill.call(self, value);\n\t\t\t\t}\n\t\t\t\t$this.data('score', value);\n\t\t\t\tmethods.setTarget.call(self, value, true);\n\t\t\t\tif (self.opt.mouseover) {\n\t\t\t\t\tself.opt.mouseover.call(self, value, evt);\n\t\t\t\t}\n\t\t\t}).click(function(evt) {\n\t\t\t\tself.score.val((self.opt.half || self.opt.precision) ? $this.data('score') : this.alt);\n\t\t\t\tif (self.opt.click) {\n\t\t\t\t\tself.opt.click.call(self, self.score.val(), evt);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t\tcancel: function(isClick) {\n\t\t\treturn $(this).each(function() {\n\t\t\t\tvar self = this,\n\t\t\t\t$this = $(self);\n\n\t\t\t\tif ($this.data('readonly') === true) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t\tif (isClick) {\n\t\t\t\t\tmethods.click.call(self, null);\n\t\t\t\t} else {\n\t\t\t\t\tmethods.score.call(self, null);\n\t\t\t\t}\n\n\t\t\t\tself.score.removeAttr('value');\n\t\t\t});\n\t\t},\n\t\tclick: function(score) {\n\t\t\treturn $(this).each(function() {\n\t\t\t\tif ($(this).data('readonly') === true) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t\tmethods.initialize.call(this, score);\n\n\t\t\t\tif (this.opt.click) {\n\t\t\t\t\tthis.opt.click.call(this, score);\n\t\t\t\t} else {\n\t\t\t\t\tmethods.error.call(this, 'you must add the \"click: function(score, evt) { }\" callback.');\n\t\t\t\t}\n\t\t\t\tmethods.setTarget.call(this, score, true);\n\t\t\t});\n\t\t},\n\t\terror: function(message) {\n\t\t\t$(this).html(message);\n\t\t\t$.error(message);\n\t\t},\n\t\tfill: function(score) {\n\t\t\tvar self = this,\n\t\t\tnumber = self.stars.length,\n\t\t\tcount = 0,\n\t\t\t$star, star, icon;\n\t\t\tfor (var i = 1; i <= number; i++) {\n\t\t\t\t$star = self.stars.eq(i - 1);\n\t\t\t\tif (self.opt.iconRange && self.opt.iconRange.length > count) {\n\t\t\t\t\tstar = self.opt.iconRange[count];\n\t\t\t\t\tif (self.opt.single) {\n\t\t\t\t\t\ticon = (i == score) ? (star.on || self.opt.starOn) : (star.off || self.opt.starOff);\n\t\t\t\t\t} else {\n\t\t\t\t\t\ticon = (i <= score) ? (star.on || self.opt.starOn) : (star.off || self.opt.starOff);\n\t\t\t\t\t}\n\t\t\t\t\tif (i <= star.range) {\n\t\t\t\t\t\t$star.attr('src', self.opt.path + icon);\n\t\t\t\t\t}\n\t\t\t\t\tif (i == star.range) {\n\t\t\t\t\t\tcount++;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (self.opt.single) {\n\t\t\t\t\t\ticon = (i == score) ? self.opt.starOn: self.opt.starOff;\n\t\t\t\t\t} else {\n\t\t\t\t\t\ticon = (i <= score) ? self.opt.starOn: self.opt.starOff;\n\t\t\t\t\t}\n\t\t\t\t\t$star.attr('src', self.opt.path + icon);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tfixHint: function() {\n\t\t\tvar $this = $(this),\n\t\t\tscore = parseInt(this.score.val(), 10),\n\t\t\thint = this.opt.noRatedMsg;\n\n\t\t\tif (!isNaN(score) && score > 0) {\n\t\t\t\thint = (score <= this.opt.hints.length && this.opt.hints[score - 1] !== null) ? this.opt.hints[score - 1] : score;\n\t\t\t}\n\t\t\t$this.data('readonly', true).css('cursor', 'default').attr('title', hint);\n\t\t\tthis.score.attr('readonly', 'readonly');\n\t\t\tthis.stars.attr('title', hint);\n\t\t},\n\t\tgetScore: function() {\n\t\t\tvar score = [],\n\t\t\tvalue;\n\t\t\t$(this).each(function() {\n\t\t\t\tvalue = this.score.val();\n\t\t\t\tscore.push(value ? parseFloat(value) : undefined);\n\t\t\t});\n\t\t\treturn (score.length > 1) ? score: score[0];\n\t\t},\n\t\treadOnly: function(isReadOnly) {\n\t\t\treturn this.each(function() {\n\t\t\t\tvar $this = $(this);\n\t\t\t\tif ($this.data('readonly') === isReadOnly) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tif (this.cancel) {\n\t\t\t\t\tif (isReadOnly) {\n\t\t\t\t\t\tthis.cancel.hide();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.cancel.show();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (isReadOnly) {\n\t\t\t\t\t$this.unbind();\n\t\t\t\t\t$this.children('img').unbind();\n\t\t\t\t\tmethods.fixHint.call(this);\n\t\t\t\t} else {\n\t\t\t\t\tmethods.bindAction.call(this);\n\t\t\t\t\tmethods.unfixHint.call(this);\n\t\t\t\t}\n\n\t\t\t\t$this.data('readonly', isReadOnly);\n\t\t\t});\n\t\t},\n\t\treload: function() {\n\t\t\treturn methods.set.call(this, {});\n\t\t},\n\t\troundStar: function(score) {\n\t\t\tvar diff = (score - Math.floor(score)).toFixed(2);\n\n\t\t\tif (diff > this.opt.round.down) {\n\t\t\t\tvar icon = this.opt.starOn; // Full up: [x.76 .. x.99]\n\t\t\t\tif (diff < this.opt.round.up && this.opt.halfShow) { // Half: [x.26 .. x.75]\n\t\t\t\t\ticon = this.opt.starHalf;\n\t\t\t\t} else if (diff < this.opt.round.full) { // Full down: [x.00 .. x.5]\n\t\t\t\t\ticon = this.opt.starOff;\n\t\t\t\t}\n\n\t\t\t\tthis.stars.eq(Math.ceil(score) - 1).attr('src', this.opt.path + icon);\n\t\t\t} // Full down: [x.00 .. x.25]\n\t\t},\n\t\tscore: function() {\n\t\t\treturn arguments.length ? methods.setScore.apply(this, arguments) : methods.getScore.call(this);\n\t\t},\n\t\tset: function(settings) {\n\t\t\tthis.each(function() {\n\t\t\t\tvar $this = $(this),\n\t\t\t\tactual = $this.data('settings'),\n\t\t\t\tclone = $this.clone().removeAttr('style').insertBefore($this);\n\n\t\t\t\t$this.remove();\n\n\t\t\t\tclone.raty($.extend(actual, settings));\n\t\t\t});\n\n\t\t\treturn $(this.selector);\n\t\t},\n\t\tsetScore: function(score) {\n\t\t\treturn $(this).each(function() {\n\t\t\t\tif ($(this).data('readonly') === true) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t\tmethods.initialize.call(this, score);\n\t\t\t\tmethods.setTarget.call(this, score, true);\n\t\t\t});\n\t\t},\n\t\tsetTarget: function(value, isKeep) {\n\t\t\tif (this.opt.target) {\n\t\t\t\tvar $target = $(this.opt.target);\n\n\t\t\t\tif ($target.length == 0) {\n\t\t\t\t\tmethods.error.call(this, '目标选择器无效或丢失!');\n\t\t\t\t}\n\n\t\t\t\tvar score = value;\n\n\t\t\t\tif (!isKeep || score === undefined) {\n\t\t\t\t\tscore = this.opt.targetText;\n\t\t\t\t} else {\n\t\t\t\t\tif (this.opt.targetType == 'hint') {\n\t\t\t\t\t\tscore = (score === null && this.opt.cancel) ? this.opt.cancelHint: this.opt.hints[Math.ceil(score - 1)];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tscore = this.opt.precision ? parseFloat(score).toFixed(1) : parseInt(score, 10);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (this.opt.targetFormat.indexOf('{score}') < 0) {\n\t\t\t\t\tmethods.error.call(this, '模版 \"{score}\" 找不到!');\n\t\t\t\t}\n\n\t\t\t\tif (value !== null) {\n\t\t\t\t\tscore = this.opt.targetFormat.toString().replace('{score}', score);\n\t\t\t\t}\n\n\t\t\t\tif ($target.is(':input')) {\n\t\t\t\t\t$target.val(score);\n\t\t\t\t} else {\n\t\t\t\t\t$target.html(score);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\tshowHalf: function(score) {\n\t\t\tvar diff = (score - Math.floor(score)).toFixed(1);\n\n\t\t\tif (diff > 0 && diff < .6) {\n\t\t\t\tthis.stars.eq(Math.ceil(score) - 1).attr('src', this.opt.path + this.opt.starHalf);\n\t\t\t}\n\t\t},\n\t\tinitialize: function(score) {\n\t\t\tscore = !score ? 0 : methods.between(score, 0, this.opt.number);\n\n\t\t\tmethods.fill.call(this, score);\n\n\t\t\tif (score > 0) {\n\t\t\t\tif (this.opt.halfShow) {\n\t\t\t\t\tmethods.roundStar.call(this, score);\n\t\t\t\t}\n\n\t\t\t\tthis.score.val(score);\n\t\t\t}\n\t\t},\n\t\tunfixHint: function() {\n\t\t\tfor (var i = 0; i < this.opt.number; i++) {\n\t\t\t\tthis.stars.eq(i).attr('title', (i < this.opt.hints.length && this.opt.hints[i] !== null) ? this.opt.hints[i] : i);\n\t\t\t}\n\n\t\t\t$(this).data('readonly', false).css('cursor', 'pointer').removeAttr('title');\n\n\t\t\tthis.score.attr('readonly', 'readonly');\n\t\t}\n\t};\n\n\t$.fn.raty = function(method) {\n\t\tif (methods[method]) {\n\t\t\treturn methods[method].apply(this, Array.prototype.slice.call(arguments, 1));\n\t\t} else if (typeof method === 'object' || !method) {\n\t\t\treturn methods.init.apply(this, arguments);\n\t\t} else {\n\t\t\t$.error('方法 ' + method + ' 不存在!');\n\t\t}\n\t};\n\n\t$.fn.raty.defaults = {\n\t\tcancel: false,\n\t\tcancelHint: '取消评级!',\n\t\tcancelOff: 'cancel-off.png',\n\t\tcancelOn: 'cancel-on.png',\n\t\tcancelPlace: 'left',\n\t\tclick: undefined,\n\t\thalf: false,\n\t\thalfShow: true,\n\t\thints: ['10', '20', '30', '40', '50', '60', '70', '80', '90', '100'],\n\t\ticonRange: undefined,\n\t\tmouseover: undefined,\n\t\tnoRatedMsg: '没有额定',\n\t\tnumber: 10,\n\t\tpath: 'images/',\n\t\tprecision: false,\n\t\tround: {\n\t\t\tdown: .25,\n\t\t\tfull: .6,\n\t\t\tup: .76\n\t\t},\n\t\treadOnly: false,\n\t\tscore: undefined,\n\t\tscoreName: 'score',\n\t\tsingle: false,\n\t\tsize: 16,\n\t\tspace: true,\n\t\tstarHalf: 'star-half.png',\n\t\tstarOff: 'star-off.png',\n\t\tstarOn: 'star-on.png',\n\t\ttarget: undefined,\n\t\ttargetFormat: '{score}',\n\t\ttargetKeep: false,\n\t\ttargetText: '',\n\t\ttargetType: 'hint',\n\t\twidth: undefined\n\t};\n})(jQuery);\n\n/* =======================================================================\n * jQuery.onePageNav.js v0.9One Page Nav Plugin\n * http://github.com/davist11/jQuery-One-Page-Nav\n * Copyright (c) 2010 Trevor Davis (http://trevordavis.net)\n * Dual licensed under the MIT and GPL licenses.\n * Uses the same license as jQuery, see:\n * http://jquery.org/license\n * Example usage:\n * $('#nav').onePageNav({\n *   currentClass: 'current',\n *   changeHash: false,\n *   scrollSpeed: 750\n * });\n * ========================================================================*/\n!(function($) {\n\t$.fn.onePageNav = function(options) {\n\t\tvar opts = $.extend({},\n\t\t$.fn.onePageNav.defaults, options),\n\t\tonePageNav = {};\n\n\t\tonePageNav.sections = {};\n\n\t\tonePageNav.bindNav = function($el, $this, o) {\n\t\t\tvar $par = $el.parent(),\n\t\t\tnewLoc = $el.attr('href'),\n\t\t\t$win = $(window);\n\n\t\t\tif (!$par.hasClass(o.currentClass)) {\n\t\t\t\tif (o.begin) {\n\t\t\t\t\to.begin();\n\t\t\t\t}\n\t\t\t\tonePageNav.adjustNav($this, $par, o.currentClass);\n\t\t\t\t$win.unbind('.onePageNav');\n\t\t\t\t$.scrollTo(newLoc, o.scrollSpeed, {\n\t\t\t\t\teasing: o.easing,\n\t\t\t\t\toffset: {\n\t\t\t\t\t\ttop: -o.scrollOffset\n\t\t\t\t\t},\n\t\t\t\t\tonAfter: function() {\n\t\t\t\t\t\tif (o.changeHash) {\n\t\t\t\t\t\t\twindow.location.hash = newLoc;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$win.bind('scroll.onePageNav',\n\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\tonePageNav.scrollChange($this, o);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (o.end) {\n\t\t\t\t\t\t\to.end();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t};\n\n\t\tonePageNav.adjustNav = function($this, $el, curClass) {\n\t\t\t$this.find('.' + curClass).removeClass(curClass);\n\t\t\t$el.addClass(curClass);\n\t\t};\n\n\t\tonePageNav.getPositions = function($this, o) {\n\t\t\tvar $nav = $this.find('a');\n\n\t\t\tif (o.filter !== '') {\n\t\t\t\t$nav = $nav.filter(o.filter);\n\t\t\t}\n\n\t\t\t$nav.each(function() {\n\t\t\t\tvar linkHref = $(this).attr('href'),\n\t\t\t\tdivPos = $(linkHref).offset(),\n\t\t\t\ttopPos = divPos.top;\n\n\t\t\t\tonePageNav.sections[linkHref.substr(1)] = Math.round(topPos) - o.scrollOffset;\n\t\t\t});\n\t\t};\n\n\t\tonePageNav.getSection = function(windowPos, o) {\n\t\t\tvar returnValue = '',\n\t\t\twindowHeight = Math.round($(window).height() * o.scrollThreshold);\n\n\t\t\tfor (var section in onePageNav.sections) {\n\t\t\t\tif ((onePageNav.sections[section] - windowHeight) < windowPos) {\n\t\t\t\t\treturnValue = section;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn returnValue;\n\t\t};\n\n\t\tonePageNav.scrollChange = function($this, o) {\n\t\t\tonePageNav.getPositions($this, o);\n\n\t\t\tvar windowTop = $(window).scrollTop(),\n\t\t\tposition = onePageNav.getSection(windowTop, o);\n\n\t\t\tif (position !== '') {\n\t\t\t\tonePageNav.adjustNav($this, $this.find('a[href=#' + position + ']').parent(), o.currentClass);\n\t\t\t}\n\t\t};\n\n\t\tonePageNav.init = function($this, o) {\n\t\t\tvar didScroll = false,\n\t\t\t$nav = $this.find('a');\n\n\t\t\tif (o.filter !== '') {\n\t\t\t\t$nav = $nav.filter(o.filter);\n\t\t\t}\n\n\t\t\t$nav.bind('click',\n\t\t\tfunction(e) {\n\t\t\t\tonePageNav.bindNav($(this), $this, o);\n\t\t\t\te.preventDefault();\n\t\t\t});\n\n\t\t\tonePageNav.getPositions($this, o);\n\n\t\t\t$(window).bind('scroll.onePageNav',\n\t\t\tfunction() {\n\t\t\t\tdidScroll = true;\n\t\t\t});\n\n\t\t\tsetInterval(function() {\n\t\t\t\tif (didScroll) {\n\t\t\t\t\tdidScroll = false;\n\t\t\t\t\tonePageNav.scrollChange($this, o);\n\t\t\t\t}\n\t\t\t},\n\t\t\t250);\n\t\t};\n\n\t\treturn this.each(function() {\n\t\t\tvar $this = $(this),\n\t\t\to = $.meta ? $.extend({},\n\t\t\topts, $this.data()) : opts;\n\n\t\t\tonePageNav.init($this, o);\n\n\t\t});\n\t};\n\n\t// default options\n\t$.fn.onePageNav.defaults = {\n\t\tcurrentClass: 'current',\n\t\tchangeHash: false,\n\t\teasing: 'swing',\n\t\tfilter: '',\n\t\tscrollSpeed: 750,\n\t\tscrollOffset: 0,\n\t\tscrollThreshold: 0.5,\n\t\tbegin: false,\n\t\tend: false\n\t};\n})(jQuery);\n\n /* =======================================================================\n * jQuery.ColorPicker.js 颜色控件\n * ========================================================================*/\n(function($) {\n\t'use strict';\n\tvar name = 'Hui.colorPicker'; // modal name\n\tvar TEAMPLATE = '<div class=\"colorpicker\"><button type=\"button\" class=\"btn dropdown-toggle\" data-toggle=\"dropdown\"><span class=\"cp-title\"></span><i class=\"ic\"></i></button><ul class=\"dropdown-menu clearfix\"></ul></div>';\n\tvar LANG = {\n\t\tzh_cn: {\n\t\t\terrorTip: \"不是有效的颜色值\"\n\t\t},\n\t\tzh_tw: {\n\t\t\terrorTip: \"不是有效的顏色值\"\n\t\t},\n\t\ten: {\n\t\t\terrorTip: \"Not a valid color value\"\n\t\t}\n\t};\n\n\t// The ColorPicker modal class\n\tvar ColorPicker = function(element, options) {\n\t\tthis.name = name;\n\t\tthis.$ = $(element);\n\n\t\tthis.getOptions(options);\n\t\tthis.init();\n\t};\n\n\t// default options\n\tColorPicker.DEFAULTS = {\n\t\tcolors: ['#00BCD4', '#388E3C', '#3280fc', '#3F51B5', '#9C27B0', '#795548', '#F57C00', '#F44336', '#E91E63'],\n\t\tpullMenuRight: true,\n\t\twrapper: 'btn-wrapper',\n\t\ttileSize: 30,\n\t\tlineCount: 5,\n\t\toptional: true,\n\t\ttooltip: 'top',\n\t\ticon: 'caret-down',\n\t\t// btnTip: 'Tool tip in button'\n\t};\n\n\tColorPicker.prototype.init = function() {\n\t\tvar options = this.options,\n\t\tthat = this;\n\n\t\tthis.$picker = $(TEAMPLATE).addClass(options.wrapper);\n\t\tthis.$picker.find('.cp-title').toggle(options.title !== undefined).text(options.title);\n\t\tthis.$menu = this.$picker.find('.dropdown-menu').toggleClass('pull-right', options.pullMenuRight);\n\t\tthis.$btn = this.$picker.find('.btn.dropdown-toggle');\n\t\tthis.$btn.find('.ic').addClass('icon-' + options.icon);\n\t\tif (options.btnTip) {\n\t\t\tthis.$picker.attr('data-toggle', 'tooltip').tooltip({\n\t\t\t\ttitle: options.btnTip,\n\t\t\t\tplacement: options.tooltip,\n\t\t\t\tcontainer: 'body'\n\t\t\t});\n\t\t}\n\t\tthis.$.attr('data-provide', null).after(this.$picker);\n\n\t\t// init colors\n\t\tthis.colors = {};\n\t\t$.each(this.options.colors,\n\t\tfunction(idx, rawColor) {\n\t\t\tif ($.zui.Color.isColor(rawColor)) {\n\t\t\t\tvar color = new $.zui.Color(rawColor);\n\t\t\t\tthat.colors[color.toCssStr()] = color;\n\t\t\t}\n\t\t});\n\n\t\tthis.updateColors();\n\t\tvar that = this;\n\t\tthis.$picker.on('click', '.cp-tile',\n\t\tfunction() {\n\t\t\tthat.setValue($(this).data('color'));\n\t\t});\n\t\tvar $input = this.$;\n\t\tvar setInputColor = function() {\n\t\t\tvar val = $input.val();\n\t\t\tvar isColor = $.zui.Color.isColor(val);\n\t\t\t$input.parent().toggleClass('has-error', !isColor && !(options.optional && val === ''));\n\t\t\tif (isColor) {\n\t\t\t\tthat.setValue(val, true);\n\t\t\t} else {\n\t\t\t\tif (options.optional && val === '') {\n\t\t\t\t\t$input.tooltip('hide');\n\t\t\t\t} else if (!$input.is(':focus')) {\n\t\t\t\t\t$input.tooltip('show', options.errorTip);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif ($input.is('input:not([type=hidden])')) {\n\t\t\tif (options.tooltip) {\n\t\t\t\t$input.attr('data-toggle', 'tooltip').tooltip({\n\t\t\t\t\ttrigger: 'manual',\n\t\t\t\t\tplacement: options.tooltip,\n\t\t\t\t\ttipClass: 'tooltip-danger',\n\t\t\t\t\tcontainer: 'body'\n\t\t\t\t});\n\t\t\t}\n\t\t\t$input.on('keyup paste input change', setInputColor);\n\t\t} else {\n\t\t\t$input.appendTo(this.$picker);\n\t\t}\n\t\tsetInputColor();\n\t};\n\n\tColorPicker.prototype.addColor = function(color) {\n\t\tvar hex = color.toCssStr(),\n\t\toptions = this.options;\n\n\t\tif (!this.colors[hex]) {\n\t\t\tthis.colors[hex] = color;\n\t\t}\n\n\t\tvar $a = $('<a href=\"###\" class=\"cp-tile\"></a>', {\n\t\t\ttitile: color\n\t\t}).data('color', color).css({\n\t\t\t'color': color.contrast().toCssStr(),\n\t\t\t'background': hex,\n\t\t\t'border-color': color.luma() > 0.43 ? '#ccc': 'transparent'\n\t\t}).attr('data-color', hex);\n\t\tthis.$menu.append($('<li/>').css({\n\t\t\twidth: options.tileSize,\n\t\t\theight: options.tileSize\n\t\t}).append($a));\n\t\tif (options.optional) {\n\t\t\tthis.$menu.find('.cp-tile.empty').parent().detach().appendTo(this.$menu);\n\t\t}\n\t};\n\n\tColorPicker.prototype.updateColors = function(colors) {\n\t\tvar $picker = this.$picker,\n\t\t$menu = this.$menu.empty(),\n\t\toptions = this.options,\n\t\tcolors = colors || this.colors,\n\t\tthat = this;\n\t\tvar bestLineCount = 0;\n\t\t$.each(colors,\n\t\tfunction(idx, color) {\n\t\t\tthat.addColor(color);\n\t\t\tbestLineCount++;\n\t\t});\n\t\tif (options.optional) {\n\t\t\tvar $li = $('<li><a class=\"cp-tile empty\" href=\"###\"></a></li>').css({\n\t\t\t\twidth: options.tileSize,\n\t\t\t\theight: options.tileSize\n\t\t\t});\n\t\t\tthis.$menu.append($li);\n\t\t\tbestLineCount++;\n\t\t}\n\t\t$menu.css('width', Math.min(bestLineCount, options.lineCount) * options.tileSize + 6);\n\t};\n\n\tColorPicker.prototype.setValue = function(color, notSetInput) {\n\t\tvar options = this.options;\n\t\tthis.$menu.find('.cp-tile.active').removeClass('active');\n\t\tvar hex = '';\n\t\tif (color) {\n\t\t\tvar c = new $.zui.Color(color);\n\t\t\thex = c.toCssStr().toLowerCase();\n\t\t\tthis.$btn.css({\n\t\t\t\tbackground: hex,\n\t\t\t\tcolor: c.contrast().toCssStr(),\n\t\t\t\tborderColor: c.luma() > 0.43 ? '#ccc': hex\n\t\t\t});\n\t\t\tif (!this.colors[hex]) {\n\t\t\t\tthis.addColor(c);\n\t\t\t}\n\t\t\tif (!notSetInput && this.$.val().toLowerCase() !== hex) {\n\t\t\t\tthis.$.val(hex).trigger('change');\n\t\t\t}\n\t\t\tthis.$menu.find('.cp-tile[data-color=' + hex + ']').addClass('active');\n\t\t\tthis.$.tooltip('hide');\n\t\t\tthis.$.trigger('colorchange', c);\n\t\t} else {\n\t\t\tthis.$btn.attr('style', null);\n\t\t\tif (!notSetInput && this.$.val() !== '') {\n\t\t\t\tthis.$.val(hex).trigger('change');\n\t\t\t}\n\t\t\tif (options.optional) {\n\t\t\t\tthis.$.tooltip('hide');\n\t\t\t}\n\t\t\tthis.$menu.find('.cp-tile.empty').addClass('active');\n\t\t\tthis.$.trigger('colorchange', null);\n\t\t}\n\n\t\tif (options.updateBorder) {\n\t\t\t$(options.updateBorder).css('border-color', hex);\n\t\t}\n\t\tif (options.updateBackground) {\n\t\t\t$(options.updateBackground).css('background-color', hex);\n\t\t}\n\t\tif (options.updateColor) {\n\t\t\t$(options.updateText).css('color', hex);\n\t\t}\n\t\tif (options.updateText) {\n\t\t\t$(options.updateText).text(hex);\n\t\t}\n\t};\n\n\t// Get and init options\n\tColorPicker.prototype.getOptions = function(options) {\n\t\tvar thisOptions = $.extend({},\n\t\tColorPicker.DEFAULTS, this.$.data(), options);\n\t\tif (typeof thisOptions.colors === 'string') thisOptions.colors = thisOptions.colors.split(',');\n\t\tvar lang = (thisOptions.lang || $.zui.clientLang()).toLowerCase();\n\t\tif (!thisOptions.errorTip) {\n\t\t\tthisOptions.errorTip = LANG[lang].errorTip;\n\t\t}\n\t\tif (!$.fn.tooltip) thisOptions.btnTip = false;\n\t\tthis.options = thisOptions;\n\t};\n\n\t// Extense jquery element\n\t$.fn.colorPicker = function(option) {\n\t\treturn this.each(function() {\n\t\t\tvar $this = $(this);\n\t\t\tvar data = $this.data(name);\n\t\t\tvar options = typeof option == 'object' && option;\n\n\t\t\tif (!data) $this.data(name, (data = new ColorPicker(this, options)));\n\n\t\t\tif (typeof option == 'string') data[option]();\n\t\t});\n\t};\n\n\t$.fn.colorPicker.Constructor = ColorPicker;\n\n\t// Auto call colorPicker after document load complete\n\t$(function() {\n\t\t$('[data-provide=\"colorpicker\"]').colorPicker();\n\t});\n}(jQuery));\n\n/* =======================================================================\n * jquery.HuiaddFavorite.js 添加收藏\n * <a title=\"收藏本站\" href=\"javascript:;\" onClick=\"addFavoritepage('H-ui前端框架','http://www.h-ui.net/');\">收藏本站</a>\n * function shoucang(name,site){\n\t$.addFavorite({\n\t\tname:name,\n\t\tsite:site,\n\t});\n * ========================================================================*/\nfunction HuiaddFavorite(obj) {\n\tobj.site = obj.site || window.location.href;\n\tobj.name = obj.name || document.title;\n\ttry {\n\t\twindow.external.addFavorite(obj.site, obj.name);\n\t} catch(e) {\n\t\ttry {\n\t\t\twindow.sidebar.addPanel(name, site, \"\");\n\t\t} catch(e) {\n\t\t\t$.Huimodalalert(\"加入收藏失败，请使用Ctrl+D进行添加\", 2000);\n\t\t}\n\t}\n}\n\n/* ========================================================================\n * jQuery.Huisethome.js 设为首页\n * ======================================================================== */\nfunction Huisethome(obj){\n\ttry{\n\t\tobj.style.behavior=\"url(#default#homepage)\";\n\t\tobj.setHomePage(webSite);\n\t}\n\tcatch(e){\n\t\tif(window.netscape){\n\t\t\ttry {\n\t\t\t\tnetscape.security.PrivilegeManager.enablePrivilege(\"UniversalXPConnect\");\n\t\t\t\t}\n\t\t\tcatch(e){\n\t\t\t\t$.Huimodalalert(\"此操作被浏览器拒绝！\\n请在浏览器地址栏输入\\\"about:config\\\"并回车\\n然后将 [signed.applets.codebase_principal_support]的值设置为'true',双击即可。\",2000);\n\t\t\t}\n\t\t\tvar prefs = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch);\n\t\t\tprefs.setCharPref('browser.startup.homepage',url);\n\t\t}\n\t}\n}\n\n/* =======================================================================\n * jQuery.Huisidenav.js 左侧菜单-隐藏显示\n * ======================================================================== */\nfunction displaynavbar(obj){\n\tif($(obj).hasClass(\"open\")){\n\t\t$(obj).removeClass(\"open\");\n\t\t$(\"body\").removeClass(\"big-page\");\n\t} else {\n\t\t$(obj).addClass(\"open\");\n\t\t$(\"body\").addClass(\"big-page\");\n\t}\n}\n\n/* =======================================================================\n * jQuery.Huihover.js v2.0 Huihover\n * http://www.h-ui.net/\n * Created & Modified by guojunhui\n * Date modified 2017.05.05\n *\n * Copyright 2017 北京颖杰联创科技有限公司 All rights reserved.\n * Licensed under MIT license.\n * http://opensource.org/licenses/MIT\n * ========================================================================*/\n!function($) {\n\t$.fn.Huihover = function(options){\n\t\tvar defaults = {\n\t\t\tclassName:\"hover\",\n\t\t}\n\t\tvar options = $.extend(defaults, options);\n\t\tthis.each(function(){\n\t\t\tvar that = $(this);\n\t\t\tthat.hover(function() {\n\t\t\t\tthat.addClass(options.className);\n\t\t\t},\n\t\t\tfunction() {\n\t\t\t\tthat.removeClass(options.className);\n\t\t\t});\n\t\t});\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huifocusblur.js v2.0 得到失去焦点\n * http://www.h-ui.net/\n * Created & Modified by guojunhui\n * Date modified 2017.05.09\n *\n * Copyright 2017 北京颖杰联创科技有限公司 All rights reserved.\n * Licensed under MIT license.\n * http://opensource.org/licenses/MIT\n * ========================================================================*/\n!function($) {\n\t$.fn.Huifocusblur = function(options){\n\t\tvar defaults = {\n\t\t\tclassName:\"focus\",\n\t\t}\n\t\tvar options = $.extend(defaults, options);\n\t\tthis.each(function(){\n\t\t\tvar that = $(this);\n\t\t\tthat.focus(function() {\n\t\t\t\tthat.addClass(options.className).removeClass(\"inputError\");\n\t\t\t});\n\t\t\tthat.blur(function() {\n\t\t\t\tthat.removeClass(options.className);\n\t\t\t});\n\t\t});\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huiselect.js 选择\n * ========================================================================*/\n!function($) {\n\t$.Huiselect = function(divselectid, inputselectid) {\n\t\tvar inputselect = $(inputselectid);\n\t\t$(divselectid + \" cite\").click(function() {\n\t\t\tvar ul = $(divselectid + \" ul\");\n\t\t\tul.slideToggle();\n\t\t});\n\t\t$(divselectid + \" ul li a\").click(function() {\n\t\t\tvar txt = $(this).text();\n\t\t\t$(divselectid + \" cite\").html(txt);\n\t\t\tvar value = $(this).attr(\"selectid\");\n\t\t\tinputselect.val(value);\n\t\t\t$(divselectid + \" ul\").hide();\n\t\t});\n\t\t$(document).click(function() {\n\t\t\t$(divselectid + \" ul\").hide();\n\t\t});\n\t};\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huitab.js v2.0 选项卡\n * http://www.h-ui.net/\n * Created & Modified by guojunhui\n * Date modified 2017.05.05\n *\n * Copyright 2017 北京颖杰联创科技有限公司 All rights reserved.\n * Licensed under MIT license.\n * http://opensource.org/licenses/MIT\n * ========================================================================*/\n!function($) {\n\t$.fn.Huitab = function(options){\n\t\tvar defaults = {\n\t\t\ttabBar:'.tabBar span',\n\t\t\ttabCon:\".tabCon\",\n\t\t\tclassName:\"current\",\n\t\t\ttabEvent:\"click\",\n\t\t\tindex:0,\n\t\t}\n\t\tvar options = $.extend(defaults, options);\n\t\tthis.each(function(){\n\t\t\tvar that = $(this);\n\t\t\tthat.find(options.tabBar).removeClass(options.className);\n\t\t\tthat.find(options.tabBar).eq(options.index).addClass(options.className);\n\t\t\tthat.find(options.tabCon).hide();\n\t\t\tthat.find(options.tabCon).eq(options.index).show();\n\n\t\t\tthat.find(options.tabBar).on(options.tabEvent,function(){\n\t\t\t\tthat.find(options.tabBar).removeClass(options.className);\n\t\t\t\t$(this).addClass(options.className);\n\t\t\t\tvar index = that.find(options.tabBar).index(this);\n\t\t\t\tthat.find(options.tabCon).hide();\n\t\t\t\tthat.find(options.tabCon).eq(index).show();\n\t\t\t});\n\t\t});\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huifold.js v2.0 折叠\n * http://www.h-ui.net/\n * Created & Modified by guojunhui\n * Date modified 2017.05.05\n *\n * Copyright 2017 北京颖杰联创科技有限公司 All rights reserved.\n * Licensed under MIT license.\n * http://opensource.org/licenses/MIT\n * ========================================================================*/\n!function($) {\n\t$.fn.Huifold = function(options){\n\t\tvar defaults = {\n\t\t\ttitCell:'.item .Huifold-header',\n\t\t\tmainCell:'.item .Huifold-body',\n\t\t\ttype:1,//1\t只打开一个，可以全部关闭;2\t必须有一个打开;3\t可打开多个\n\t\t\ttrigger:'click',\n\t\t\tclassName:\"selected\",\n\t\t\tspeed:'first',\n\t\t}\n\t\tvar options = $.extend(defaults, options);\n\t\tthis.each(function(){\n\t\t\tvar that = $(this);\n\t\t\tthat.find(options.titCell).on(options.trigger,function(){\n\t\t\t\tif ($(this).next().is(\":visible\")) {\n\t\t\t\t\tif (options.type == 2) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$(this).next().slideUp(options.speed).end().removeClass(options.className);\n\t\t\t\t\t\tif ($(this).find(\"b\")) {\n\t\t\t\t\t\t\t$(this).find(\"b\").html(\"+\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}else {\n\t\t\t\t\tif (options.type == 3) {\n\t\t\t\t\t\t$(this).next().slideDown(options.speed).end().addClass(options.className);\n\t\t\t\t\t\tif ($(this).find(\"b\")) {\n\t\t\t\t\t\t\t$(this).find(\"b\").html(\"-\");\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthat.find(options.mainCell).slideUp(options.speed);\n\t\t\t\t\t\tthat.find(options.titCell).removeClass(options.className);\n\t\t\t\t\t\tif (that.find(options.titCell).find(\"b\")) {\n\t\t\t\t\t\t\tthat.find(options.titCell).find(\"b\").html(\"+\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$(this).next().slideDown(options.speed).end().addClass(options.className);\n\t\t\t\t\t\tif ($(this).find(\"b\")) {\n\t\t\t\t\t\t\t$(this).find(\"b\").html(\"-\");\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t});\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huitags.js v2.0 标签\n * http://www.h-ui.net/\n * Created & Modified by guojunhui\n * Date modified 2017.05.10\n *\n * Copyright 2017 北京颖杰联创科技有限公司 All rights reserved.\n * Licensed under MIT license.\n * http://opensource.org/licenses/MIT\n * ========================================================================*/\n!function($) {\n\t$.fn.Huitags = function(options) {\n\t\tvar defaults = {\n\t\t\tvalue:'Hui前端框架,H-ui,辉哥',\n\t\t\tmaxlength : 20,\n\t\t\tnumber : 5,\n\t\t\ttagsDefault : [\"Html\",\"CSS\",\"JS\"],\n\t\t}\n\t\tvar options = $.extend(defaults, options);\n\t\tvar keyCodes = {\n\t\t\tEnter : 13,\n\t\t\tEnter2 : 108,\n\t\t\tSpacebar:32\n\t\t}\n\t\tthis.each(function(){\n\t\t\tvar that = $(this);\n\t\t\tvar str =\n\t\t\t'<div class=\"Huitags-wraper\">'+\n\t\t\t\t'<div class=\"Huitags-editor cl\"></div>'+\n\t\t\t\t'<div class=\"Huitags-input-wraper\">'+\n\t\t\t\t\t'<input type=\"text\" class=\"input-text Huitags-input\" maxlength=\"'+options.maxlength+'\" value=\"\">'+\n\t\t\t\t'</div>'+\n\t\t\t\t'<div class=\"Huitags-list\">'+\n\t\t\t\t\t'<div class=\"Huitags-notag\" style=\"display:none\">暂无常用标签</div>'+\n\t\t\t\t\t'<div class=\"Huitags-has\"></div>'+\n\t\t\t\t'</div>'+\n\t\t\t\t'<input type=\"hidden\" class=\"Huitags-val\" name=\"\" value=\"'+options.value+'\">'+\n\t\t\t'</div>';\n\t\t\tthat.append(str);\n\t\t\tvar wraper = that.find(\".Huitags-wraper\");\n\t\t\tvar editor = that.find(\".Huitags-editor\");\n\t\t\tvar input =that.find(\".Huitags-input\");\n\t\t\tvar list = that.find(\".Huitags-list\");\n\t\t\tvar has = that.find(\".Huitags-has\");\n\t\t\tvar val = that.find(\".Huitags-val\");\n\n\n\n\t\t\tif(options.tagsDefault){\n\t\t\t\tvar tagsDefaultLength = (options.tagsDefault).length;\n\t\t\t\tfor(var i = 0;i< tagsDefaultLength; i++){\n\t\t\t\t\thas.append('<span>'+options.tagsDefault[i]+'</span>');\n\t\t\t\t}\n\t\t\t\thas.find(\"span\").on('click',function(){\n\t\t\t\t\tvar taghasV = $(this).text();\n\t\t\t\t\ttaghasV=taghasV.replace(/(^\\s*)|(\\s*$)/g,\"\");\n\t\t\t\t\teditor.append('<span class=\"Huitags-token\">'+taghasV+'</span>');\n\t\t\t\t\tgettagval(this);\n\t\t\t\t\t$(this).remove();\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tfunction gettagval(obj) {\n\t\t\t\tvar str = \"\";\n\t\t\t\tvar token = that.find(\".Huitags-token\");\n\t\t\t\tif (token.length < 1) {\n\t\t\t\t\tinput.val(\"\");\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tfor (var i = 0; i < token.length; i++) {\n\t\t\t\t\tstr += token.eq(i).text() + \",\";\n\t\t\t\t}\n\t\t\t\tstr = unique(str, 1);\n\t\t\t\tstr=str.join();\n\t\t\t\tval.val(str);\n\t\t\t}\n\t\t\t/*将字符串逗号分割成数组并去重*/\n\t\t\tfunction unique(o, type){\n\t\t\t\t//去掉前后空格\n\t\t\t\to=o.replace(/(^\\s*)|(\\s*$)/g,\"\");\n\t\t\t\tif(type == 1) {\n\t\t\t\t\t//把所有的空格和中文逗号替换成英文逗号\n\t\t\t\t\to=o.replace(/(\\s)|(，)/g, \",\");\n\t\t\t\t} else {\n\t\t\t\t\t//把所有的中文逗号替换成英文逗号\n\t\t\t\t\to=o.replace(/(，)/g, \",\");\n\t\t\t\t}\n\t\t\t\t//去掉前后英文逗号\n\t\t\t\to=o.replace(/^,|,$/g, \"\");\n\t\t\t\t//去重连续的英文逗号\n\t\t\t\to=o.replace(/,+/g,',');\n\t\t\t\to=o.split(\",\");\n\t\t\t\tvar n = [o[0]]; //结果数组\n\t\t\t\tfor(var i = 1; i < o.length; i++){\n\t\t\t\t\tif (o.indexOf(o[i]) == i) {\n\t\t\t\t\t\tif(o[i] == \"\")\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\tn.push(o[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn n;\n\t\t\t}\n\n\t\t\tinput.on(\"keydown\",function(e){\n\t\t\t\tvar evt = e || window.event;\n\t\t\t\tif (evt.keyCode == keyCodes.Enter || evt.keyCode == keyCodes.Enter2 || evt.keyCode == keyCodes.Spacebar) {\n\t\t\t\t\tvar v = input.val().replace(/\\s+/g, \"\");\n\t\t\t\t\tvar reg = /^,|,$/gi;\n\t\t\t\t\tv = v.replace(reg, \"\");\n\t\t\t\t\tv = $.trim(v);\n\t\t\t\t\tif (v != '') {\n\t\t\t\t\t\tinput.change();\n\t\t\t\t\t}else{\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tinput.on(\"change\",function(){\n\t\t\t\tvar v1 = input.val();\n\t\t\t\tvar v2 = val.val();\n\t\t\t\tvar v = v2+','+v1;\n\t\t\t\tif(v!=''){\n\t\t\t\t\tvar str='<i class=\"Huitags-icon Hui-iconfont\">&#xe64b;</i>';\n\t\t\t\t\tvar result = unique(v, 1);\n\t\t\t\t\tif(result.length>0){\n\t\t\t\t\t\tfor(var j=0;j<result.length;j++){\n\t\t\t\t\t\t\tstr+='<span class=\"Huitags-token\">'+result[j]+'</span>';\n\t\t\t\t\t\t}\n\t\t\t\t\t\tval.val(result);\n\t\t\t\t\t\teditor.html(str);\n\t\t\t\t\t\tinput.val(\"\").blur();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\n\t\t\t$(document).on(\"click\",\".Huitags-token\",function(){\n\t\t\t\t$(this).remove();\n\t\t\t\tvar str =\"\";\n\t\t\t\tif(that.find(\".Huitags-token\").length<1){\n\t\t\t\t\tval.val(\"\");\n\t\t\t\t\treturn false;\n\t\t\t\t}else{\n\t\t\t\t\tfor(var i = 0;i< that.find(\".Huitags-token\").length;i++){\n\t\t\t\t\t\tstr += that.find(\".Huitags-token\").eq(i).text() + \",\";\n\t\t\t\t\t}\n\t\t\t\t\tstr = str.substring(0,str.length-1);\n\t\t\t\t\tval.val(str);\n\t\t\t\t}\n\t\t\t});\n\t\t\tinput.change();\n\t\t});\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huitagsmixed.js 标签混排效果\n * ========================================================================*/\n!function($) {\n\t$.Huitagsmixed = function(obj) {\n\t\t$(obj).each(function() {\n\t\t\tvar x = 9;\n\t\t\tvar y = 0;\n\t\t\tvar rand = parseInt(Math.random() * (x - y + 1) + y);\n\t\t\t$(this).addClass(\"tags\" + rand);\n\t\t});\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huitextarealength.js v2.0 字数限制\n * http://www.h-ui.net/\n * Created & Modified by guojunhui\n * Date modified 2017.05.12\n *\n * Copyright 2017 北京颖杰联创科技有限公司 All rights reserved.\n * Licensed under MIT license.\n * http://opensource.org/licenses/MIT\n * ========================================================================*/\n!function($) {\n\t$.fn.Huitextarealength = function(options){\n\t\tvar defaults = {\n\t\t\tminlength:0,\n\t\t\tmaxlength:140,\n\t\t\terrorClass:\"error\",\n\t\t\texceed:true,\n\t\t}\n\t\tvar options = $.extend(defaults, options);\n\t\tthis.each(function(){\n\t\t\tvar that = $(this);\n\t\t\tvar v = that.val();\n\t\t\tvar l = v.length;\n\t\t\tvar str = '<p class=\"textarea-numberbar\"><em class=\"textarea-length\">'+l+'</em>/'+options.maxlength+'</p>';\n\t\t\tthat.parent().append(str);\n\n\t\t\tthat.on(\"keyup\",function(){\n\t\t\t\tv = that.val();\n\t\t\t\tl = v.length;\n\t\t\t\tif (l > options.maxlength) {\n\t\t\t\t\tif(options.exceed){\n\t\t\t\t\t\tthat.addClass(options.errorClass);\n\t\t\t\t\t}else{\n\t\t\t\t\t\tv = v.substring(0, options.maxlength);\n\t\t\t\t\t\tthat.val(v);\n\t\t\t\t\t\tthat.removeClass(options.errorClass);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if(l<options.minlength){\n\t\t\t\t\tthat.addClass(options.errorClass);\n\t\t\t\t}else{\n\t\t\t\t\tthat.removeClass(options.errorClass);\n\t\t\t\t}\n\t\t\t\tthat.parent().find(\".textarea-length\").text(v.length);\n\t\t\t});\n\n\t\t});\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huipreview.js v2.0 图片预览\n * http://www.h-ui.net/\n * Created & Modified by guojunhui\n * Date modified 2017.05.05\n *\n * Copyright 2017 北京颖杰联创科技有限公司 All rights reserved.\n * Licensed under MIT license.\n * http://opensource.org/licenses/MIT\n * ========================================================================*/\n!function($) {\n\t$.fn.Huipreview = function(options){\n\t\tvar defaults = {\n\t\t\tclassName:\"active\",\n\t\t\tbigImgWidth: 300,\n\t\t}\n\t\tvar options = $.extend(defaults, options);\n\t\tthis.each(function(){\n\t\t\tvar that = $(this);\n\t\t\tvar timer;\n\t\t\tthat.hover(\n\t\t\t\tfunction() {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\ttimer = setTimeout(function () {\n\t\t\t\t\t\t$(\"#tooltip-preview\").remove();\n\t\t\t\t\t\tvar smallImg = that.find(\"img\").attr(\"src\");\n\t\t\t\t\t\tvar bigImg = that.attr('data-src');\n\t\t\t\t\t\tvar bigImgW = that.attr('data-width');\n\t\t\t\t\t\tvar bigImgH = that.attr('data-height');\n\t\t\t\t\t\tvar winW = $(window).width();\n\t\t\t\t\t\tvar winW5 = winW / 2;\n\t\t\t\t\t\tvar imgT = that.parent().offset().top;\n\t\t\t\t\t\tvar imgL = that.parent().offset().left;\n\t\t\t\t\t\tvar imgW = that.parent().width();\n\t\t\t\t\t\tvar imgH = that.parent().height();\n\t\t\t\t\t\tvar ww = (imgL + imgW / 2);\n\t\t\t\t\t\tvar tooltipLeft = \"auto\",tooltipRight = \"auto\";\n\t\t\t\t\t\tif (ww < winW5) {\n\t\t\t\t\t\t\ttooltipLeft = (imgW + imgL) + \"px\";\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\ttooltipRight = (winW - imgL) + \"px\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthat.addClass(options.className);\n\t\t\t\t\t\tif (bigImg == '') {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvar tooltip_keleyi_com =\n\t\t\t\t\t\t\t'<div id=\"preview-wraper\" style=\"position: absolute;width:'+options.bigImgWidth+'px;height:auto;top:' + imgT + 'px;right:' + tooltipRight + ';left:' + tooltipLeft + '\">'+\n\t\t\t\t\t\t\t\t'<img src=\"'+smallImg+'\" width=\"'+options.bigImgWidth+'\">'+\n\t\t\t\t\t\t\t'</div>';\n\t\t\t\t\t\t\t$(\"body\").append(tooltip_keleyi_com);\n\t\t\t\t\t\t\t/*图片预加载*/\n\t\t\t\t\t\t\tvar image = new Image();\n\t\t\t\t\t\t\timage.src = bigImg;\n\t\t\t\t\t\t\t/*创建一个Image对象*/\n\t\t\t\t\t\t\timage.onload = function() {\n\t\t\t\t\t\t\t\t$('#preview-wraper').find(\"img\").attr(\"src\",bigImg).css(\"width\",options.bigImgWidth);\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t},500);\n\t\t\t\t},\n\t\t\t\tfunction() {\n\t\t\t\t\tclearTimeout(timer);\n\t\t\t\t\tthat.removeClass(options.className);\n\t\t\t\t\t$(\"#preview-wraper\").remove();\n\t\t\t\t}\n\t\t\t);\n\t\t});\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huimodalalert.js alert\n * ========================================================================*/\n!function($) {\n\t$.Huimodalalert = function(info, speed) {\n\t\tif ($(\".modal-alert\").length > 0) {\n\t\t\t$(\".modal-alert\").remove();\n\t\t}\n\t\tif (speed == 0 || typeof(speed) == \"undefined\") {\n\t\t\t$(document.body).append('<div id=\"modal-alert\" class=\"modal modal-alert radius\">' + '<div class=\"modal-alert-info\">' + info + '</div>' + '<div class=\"modal-footer\"> <button class=\"btn btn-primary radius\" onClick=\"$.Huimodal_alert.hide()\">确定</button></div>' + '</div>');\n\t\t\t$(\"#modal-alert\").fadeIn();\n\t\t} else {\n\t\t\t$(document.body).append('<div id=\"modal-alert\" class=\"modal modal-alert radius\">' + '<div class=\"modal-alert-info\">' + info + '</div>' + '</div>');\n\t\t\t$(\"#modal-alert\").fadeIn();\n\t\t\tsetTimeout($.Huimodalalert.hide, speed);\n\t\t}\n\t}\n\t$.Huimodalalert.hide = function() {\n\t\t$(\"#modal-alert\").fadeOut(\"normal\",\n\t\tfunction() {\n\t\t\t$(\"#modal-alert\").remove();\n\t\t});\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huialert.js alert\n * ========================================================================*/\n!function($) {\n\t$.Huialert = function() {\n\t\t$(\".Huialert i\").Huihover();\n\t\t$(\".Huialert i\").on(\"click\",function() {\n\t\t\tvar Huialert = $(this).parents(\".Huialert\");\n\t\t\tHuialert.fadeOut(\"normal\",\n\t\t\tfunction() {\n\t\t\t\tHuialert.remove();\n\t\t\t});\n\t\t});\n\t}\n\t$.Huialert();\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huitotop.js v2.0 返回顶部\n * http://www.h-ui.net/\n * Created & Modified by guojunhui\n * Date modified 2017.05.05\n *\n * Copyright 2017 北京颖杰联创科技有限公司 All rights reserved.\n * Licensed under MIT license.\n * http://opensource.org/licenses/MIT\n * ========================================================================*/\n!function($) {\n\t//bottom 距离底部高度\n\t$.Huitotop = function(bottom){\n\t\tif(!bottom){\n\t\t\tbottom = 60;\n\t\t}\n\t\tvar str ='<a href=\"javascript:void(0)\" class=\"tools-right toTop Hui-iconfont\" title=\"返回顶部\" alt=\"返回顶部\" style=\"display:none;bottom:'+bottom+'px\">&#xe684;</a>';\n\t\t$(str).appendTo($('body')).click(function() {\n\t\t\t$(\"html, body\").animate({\n\t\t\t\tscrollTop: 0\n\t\t\t},\n\t\t\t120);\n\t\t});\n\t\tvar backToTopFun = function(){\n\t\t\tvar st = $(document).scrollTop();\n\t\t\tvar winh = $(window).height();\n\t\t\tif(st> 0){\n\t\t\t\t$(\".toTop\").show();\n\t\t\t}else{\n\t\t\t\t$(\".toTop\").hide();\n\t\t\t}\n\t\t\t/*IE6下的定位*/\n\t\t\tif (!window.XMLHttpRequest) {\n\t\t\t\t$(\".toTop\").css(\"top\", st + winh - 166);\n\t\t\t}\n\n\t\t}\n\t\t$(window).on(\"scroll\",backToTopFun);\n\t}\n} (window.jQuery);\n\n/* =======================================================================\n * jQuery.Huimarquee.js 滚动\n * ========================================================================*/\n!function($) {\n\t$.Huimarquee = function(height, speed, delay) {\n\t\tvar scrollT;\n\t\tvar pause = false;\n\t\tvar ScrollBox = document.getElementById(\"marquee\");\n\t\tif (document.getElementById(\"holder\").offsetHeight <= height) return;\n\t\tvar _tmp = ScrollBox.innerHTML.replace('holder', 'holder2');\n\t\tScrollBox.innerHTML += _tmp;\n\t\tScrollBox.onmouseover = function() {\n\t\t\tpause = true;\n\t\t}\n\t\tScrollBox.onmouseout = function() {\n\t\t\tpause = false;\n\t\t}\n\t\tScrollBox.scrollTop = 0;\n\t\tvar start = function() {\n\t\t\tscrollT = setInterval(scrolling, speed);\n\t\t\tif (!pause) ScrollBox.scrollTop += 2;\n\t\t}\n\t\tvar scrolling = function() {\n\t\t\tif (ScrollBox.scrollTop % height != 0) {\n\t\t\t\tScrollBox.scrollTop += 2;\n\t\t\t\tif (ScrollBox.scrollTop >= ScrollBox.scrollHeight / 2) ScrollBox.scrollTop = 0;\n\t\t\t} else {\n\t\t\t\tclearInterval(scrollT);\n\t\t\t\tsetTimeout(start, delay);\n\t\t\t}\n\t\t}\n\t\tsetTimeout(start, delay);\n\t}\n} (window.jQuery);\n\n$(function() {\n\t/*全选*/\n\t$(\"table thead th input:checkbox\").on(\"click\",function() {\n\t\t$(this).closest(\"table\").find(\"tr > td:first-child input:checkbox\").prop(\"checked\", $(\"table thead th input:checkbox\").prop(\"checked\"));\n\t});\n\n\t/*上传*/\n\t$(document).on(\"change\", \".input-file\",function() {\n\t\tvar uploadVal = $(this).val();\n\t\t$(this).parent().find(\".upload-url\").val(uploadVal).focus().blur();\n\t});\n});\n\n/* ========================================================================\n * Bootstrap.button.js v3.3.0\n * http://getbootstrap.com/javascript/#buttons\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n!function($) {\n\t'use strict';\n\t// BUTTON PUBLIC CLASS DEFINITION\n\t// ==============================\n\tvar Button = function(element, options) {\n\t\tthis.$element = $(element);\n\t\tthis.options = $.extend({},Button.DEFAULTS, options);\n\t\tthis.isLoading = false;\n\t}\n\tButton.VERSION = '3.3.0'\n\n\tButton.DEFAULTS = {\n\t\tloadingText: 'loading...'\n\t}\n\n\tButton.prototype.setState = function(state) {\n\t\tvar d = 'disabled'\n\t\tvar $el = this.$element\n\t\tvar val = $el.is('input') ? 'val': 'html'\n\t\tvar data = $el.data();\n\t\tstate = state + 'Text';\n\t\tif (data.resetText == null) $el.data('resetText', $el[val]());\n\t\t// push to event loop to allow forms to submit\n\t\tsetTimeout($.proxy(function() {\n\t\t\t$el[val](data[state] == null ? this.options[state] : data[state]);\n\t\t\tif (state == 'loadingText') {\n\t\t\t\tthis.isLoading = true;\n\t\t\t\t$el.addClass(d).attr(d, d);\n\t\t\t} else if (this.isLoading) {\n\t\t\t\tthis.isLoading = false;\n\t\t\t\t$el.removeClass(d).removeAttr(d);\n\t\t\t}\n\t\t},\n\t\tthis), 0)\n\t}\n\n\tButton.prototype.toggle = function() {\n\t\tvar changed = true;\n\t\tvar $parent = this.$element.closest('[data-toggle=\"buttons\"]');\n\n\t\tif ($parent.length) {\n\t\t\tvar $input = this.$element.find('input');\n\t\t\tif ($input.prop('type') == 'radio') {\n\t\t\t\tif ($input.prop('checked') && this.$element.hasClass('active')) changed = false\n\t\t\t\telse $parent.find('.active').removeClass('active')\n\t\t\t}\n\t\t\tif (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')\n\t\t} else {\n\t\t\tthis.$element.attr('aria-pressed', !this.$element.hasClass('active'))\n\t\t}\n\n\t\tif (changed) this.$element.toggleClass('active')\n\t}\n\n\t// BUTTON PLUGIN DEFINITION\n\t// ========================\n\tfunction Plugin(option) {\n\t\treturn this.each(function() {\n\t\t\tvar $this = $(this);\n\t\t\tvar data = $this.data('bs.button');\n\t\t\tvar options = typeof option == 'object' && option;\n\t\t\tif (!data) $this.data('bs.button', (data = new Button(this, options)))\n\n\t\t\tif (option == 'toggle') data.toggle()\n\t\t\telse if (option) data.setState(option)\n\t\t})\n\t}\n\n\tvar old = $.fn.button;\n\n\t$.fn.button = Plugin;\n\t$.fn.button.Constructor = Button;\n\t// BUTTON NO CONFLICT\n\t// ==================\n\t$.fn.button.noConflict = function() {\n\t\t$.fn.button = old;\n\t\treturn this;\n\t}\n\n\t// BUTTON DATA-API\n\t// ===============\n\t$(document).on('click.bs.button.data-api', '[data-toggle^=\"button\"]',\n\tfunction(e) {\n\t\tvar $btn = $(e.target);\n\t\tif (!$btn.hasClass('btn'));\n\t\t$btn = $btn.closest('.btn');\n\t\tPlugin.call($btn, 'toggle');\n\t\te.preventDefault();\n\t}).on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^=\"button\"]',\n\tfunction(e) {\n\t\t$(e.target).closest('.btn').toggleClass('focus', e.type == 'focus');\n\t})\n} (jQuery);\n\n/* =======================================================================\n * jQuery.stickUp.js v0.5.7 BETA  by:LiranCohen\n * https://github.com/LiranCohen/stickUp\n * ======================================================================== */\njQuery(function($) {\n\t$(document).ready(function(){\n\t\tvar contentButton = [];\n\t\tvar contentTop = [];\n\t\tvar content = [];\n\t\tvar lastScrollTop = 0;\n\t\tvar scrollDir = '';\n\t\tvar itemClass = '';\n\t\tvar itemHover = '';\n\t\tvar menuSize = null;\n\t\tvar stickyHeight = 0;\n\t\tvar stickyMarginB = 0;\n\t\tvar currentMarginT = 0;\n\t\tvar topMargin = 0;\n\t\tvar vartop = 0;\n\t\t$(window).scroll(function(event){\n   \t\t\tvar st = $(this).scrollTop();\n   \t\t\tif (st > lastScrollTop){\n       \t\t\tscrollDir = 'down';\n   \t\t\t} else {\n      \t\t\tscrollDir = 'up';\n   \t\t\t}\n  \t\t\tlastScrollTop = st;\n\t\t});\n\t\t$.fn.stickUp = function( options ) {\n\t\t\t// adding a class to users div\n\t\t\t$(this).addClass('stuckMenu');\n        \t//getting options\n        \tvar objn = 0;\n        \tif(options != null) {\n\t        \tfor(var o in options.parts) {\n\t        \t\tif (options.parts.hasOwnProperty(o)){\n\t        \t\t\tcontent[objn] = options.parts[objn];\n\t        \t\t\tobjn++;\n\t        \t\t}\n\t        \t}\n\t  \t\t\tif(objn == 0) {\n\t  \t\t\t\tconsole.log('error:needs arguments');\n\t  \t\t\t}\n\n\t  \t\t\titemClass = options.itemClass;\n\t  \t\t\titemHover = options.itemHover;\n\t  \t\t\tif(options.topMargin != null) {\n\t  \t\t\t\tif(options.topMargin == 'auto') {\n\t  \t\t\t\t\ttopMargin = parseInt($('.stuckMenu').css('margin-top'));\n\t  \t\t\t\t} else {\n\t  \t\t\t\t\tif(isNaN(options.topMargin) && options.topMargin.search(\"px\") > 0){\n\t  \t\t\t\t\t\ttopMargin = parseInt(options.topMargin.replace(\"px\",\"\"));\n\t  \t\t\t\t\t} else if(!isNaN(parseInt(options.topMargin))) {\n\t  \t\t\t\t\t\ttopMargin = parseInt(options.topMargin);\n\t  \t\t\t\t\t} else {\n\t  \t\t\t\t\t\tconsole.log(\"incorrect argument, ignored.\");\n\t  \t\t\t\t\t\ttopMargin = 0;\n\t  \t\t\t\t\t}\n\t  \t\t\t\t}\n\t  \t\t\t} else {\n\t  \t\t\t\ttopMargin = 0;\n\t  \t\t\t}\n\t  \t\t\tmenuSize = $('.'+itemClass).size();\n  \t\t\t}\n\t\t\tstickyHeight = parseInt($(this).height());\n\t\t\tstickyMarginB = parseInt($(this).css('margin-bottom'));\n\t\t\tcurrentMarginT = parseInt($(this).next().closest('div').css('margin-top'));\n\t\t\tvartop = parseInt($(this).offset().top);\n\t\t\t//$(this).find('*').removeClass(itemHover);\n\t\t}\n\t\t$(document).on('scroll', function() {\n\t\t\tvarscroll = parseInt($(document).scrollTop());\n\t\t\tif(menuSize != null){\n\t\t\t\tfor(var i=0;i < menuSize;i++)\n\t\t\t\t{\n\t\t\t\t\tcontentTop[i] = $('#'+content[i]+'').offset().top;\n\t\t\t\t\tfunction bottomView(i) {\n\t\t\t\t\t\tcontentView = $('#'+content[i]+'').height()*.4;\n\t\t\t\t\t\ttestView = contentTop[i] - contentView;\n\t\t\t\t\t\tif(varscroll > testView){\n\t\t\t\t\t\t\t$('.'+itemClass).removeClass(itemHover);\n\t\t\t\t\t\t\t$('.'+itemClass+':eq('+i+')').addClass(itemHover);\n\t\t\t\t\t\t} else if(varscroll < 50){\n\t\t\t\t\t\t\t$('.'+itemClass).removeClass(itemHover);\n\t\t\t\t\t\t\t$('.'+itemClass+':eq(0)').addClass(itemHover);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif(scrollDir == 'down' && varscroll > contentTop[i]-50 && varscroll < contentTop[i]+50) {\n\t\t\t\t\t\t$('.'+itemClass).removeClass(itemHover);\n\t\t\t\t\t\t$('.'+itemClass+':eq('+i+')').addClass(itemHover);\n\t\t\t\t\t}\n\t\t\t\t\tif(scrollDir == 'up') {\n\t\t\t\t\t\tbottomView(i);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif(vartop < varscroll + topMargin){\n\t\t\t\t$('.stuckMenu').addClass('isStuck');\n\t\t\t\t$('.stuckMenu').next().closest('div').css({\n\t\t\t\t\t'margin-top': stickyHeight + stickyMarginB + currentMarginT + 'px'\n\t\t\t\t}, 10);\n\t\t\t\t$('.stuckMenu').css(\"position\",\"fixed\");\n\t\t\t\t$('.isStuck').css({\n\t\t\t\t\ttop: '0px'\n\t\t\t\t}, 10, function(){\n\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tif(varscroll + topMargin < vartop){\n\t\t\t\t$('.stuckMenu').removeClass('isStuck');\n\t\t\t\t$('.stuckMenu').next().closest('div').css({\n\t\t\t\t\t'margin-top': currentMarginT + 'px'\n\t\t\t\t}, 10);\n\t\t\t\t$('.stuckMenu').css(\"position\",\"relative\");\n\t\t\t};\n\t\t});\n\t});\n});\n\n/* =======================================================================\n * Bootstrap.modal.js v3.3.0\n * http://getbootstrap.com/javascript/#modals\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n!function($) {\n\t'use strict';\n\t// MODAL CLASS DEFINITION\n\t// ======================\n\tvar Modal = function(element, options) {\n\t\tthis.options = options;\n\t\tthis.$body = $(document.body);\n\t\tthis.$element = $(element);\n\t\tthis.$backdrop =\n\t\tthis.isShown = null;\n\t\tthis.scrollbarWidth = 0;\n\n\t\tif (this.options.remote) {\n\t\t\tthis.$element.find('.modal-content').load(this.options.remote, $.proxy(function() {\n\t\t\t\tthis.$element.trigger('loaded.bs.modal');\n\t\t\t},\n\t\t\tthis))\n\t\t}\n\t}\n\n\tModal.VERSION = '3.3.0';\n\tModal.TRANSITION_DURATION = 300;\n\tModal.BACKDROP_TRANSITION_DURATION = 150;\n\n\tModal.DEFAULTS = {\n\t\tbackdrop: true,\n\t\tkeyboard: true,\n\t\tshow: true,\n\t}\n\n\tModal.prototype.toggle = function(_relatedTarget) {\n\t\treturn this.isShown ? this.hide() : this.show(_relatedTarget)\n\t}\n\n\tModal.prototype.show = function(_relatedTarget) {\n\t\tvar that = this;\n\t\tvar e = $.Event('show.bs.modal', {\n\t\t\trelatedTarget: _relatedTarget\n\t\t});\n\n\t\tthis.$element.trigger(e);\n\t\tif (this.isShown || e.isDefaultPrevented()) return;\n\t\tthis.isShown = true;\n\t\tthis.checkScrollbar();\n\t\tthis.$body.addClass('modal-open');\n\t\tthis.setScrollbar();\n\t\tthis.escape();\n\t\tthis.$element.on('click.dismiss.bs.modal', '[data-dismiss=\"modal\"]', $.proxy(this.hide, this));\n\n\t\tthis.backdrop(function() {\n\t\t\tvar transition = $.support.transition && that.$element.hasClass('fade');\n\t\t\tif (!that.$element.parent().length) {\n\t\t\t\tthat.$element.appendTo(that.$body); // don't move modals dom position\n\t\t\t}\n\t\t\tthat.$element.show().scrollTop(0);\n\t\t\tif (transition) {\n\t\t\t\tthat.$element[0].offsetWidth; // force reflow\n\t\t\t}\n\t\t\tthat.$element.addClass('in').attr('aria-hidden', false);\n\n\t\t\tthat.enforceFocus();\n\n\t\t\tvar e = $.Event('shown.bs.modal', {\n\t\t\t\trelatedTarget: _relatedTarget\n\t\t\t})\n\n\t\t\ttransition ? that.$element.find('.modal-dialog') // wait for modal to slide in\n\t\t\t.one('bsTransitionEnd',\n\t\t\tfunction() {\n\t\t\t\tthat.$element.trigger('focus').trigger(e)\n\t\t\t}).emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger('focus').trigger(e)\n\t\t})\n\t}\n\n\tModal.prototype.hide = function(e) {\n\t\tif (e) e.preventDefault();\n\t\te = $.Event('hide.bs.modal');\n\t\tthis.$element.trigger(e);\n\t\tif (!this.isShown || e.isDefaultPrevented()) return;\n\t\tthis.isShown = false;\n\t\tthis.escape();\n\t\t$(document).off('focusin.bs.modal');\n\t\tthis.$element.removeClass('in').attr('aria-hidden', true).off('click.dismiss.bs.modal');\n\t\t$.support.transition && this.$element.hasClass('fade') ? this.$element.one('bsTransitionEnd', $.proxy(this.hideModal, this)).emulateTransitionEnd(Modal.TRANSITION_DURATION) : this.hideModal()\n\t}\n\n\tModal.prototype.enforceFocus = function() {\n\t\t$(document).off('focusin.bs.modal') // guard against infinite focus loop\n\t\t.on('focusin.bs.modal', $.proxy(function(e) {\n\t\t\tif (this.$element[0] !== e.target && !this.$element.has(e.target).length) {\n\t\t\t\tthis.$element.trigger('focus')\n\t\t\t}\n\t\t},\n\t\tthis))\n\t}\n\n\tModal.prototype.escape = function() {\n\t\tif (this.isShown && this.options.keyboard) {\n\t\t\tthis.$element.on('keydown.dismiss.bs.modal', $.proxy(function(e) {\n\t\t\t\te.which == 27 && this.hide()\n\t\t\t},\n\t\t\tthis))\n\t\t} else if (!this.isShown) {\n\t\t\tthis.$element.off('keydown.dismiss.bs.modal')\n\t\t}\n\t}\n\n\tModal.prototype.hideModal = function() {\n\t\tvar that = this;\n\t\tthis.$element.hide();\n\t\tthis.backdrop(function() {\n\t\t\tthat.$body.removeClass('modal-open');\n\t\t\tthat.resetScrollbar();\n\t\t\tthat.$element.trigger('hidden.bs.modal');\n\t\t})\n\t}\n\n\tModal.prototype.removeBackdrop = function() {\n\t\tthis.$backdrop && this.$backdrop.remove();\n\t\tthis.$backdrop = null;\n\t}\n\n\tModal.prototype.backdrop = function(callback) {\n\t\tvar that = this\n\t\tvar animate = this.$element.hasClass('fade') ? 'fade': ''\n\n\t\tif (this.isShown && this.options.backdrop) {\n\t\t\tvar doAnimate = $.support.transition && animate\n\n\t\t\tthis.$backdrop = $('<div class=\"modal-backdrop ' + animate + '\" />').prependTo(this.$element).on('click.dismiss.bs.modal', $.proxy(function(e) {\n\t\t\t\tif (e.target !== e.currentTarget) return this.options.backdrop == 'static' ? this.$element[0].focus.call(this.$element[0]) : this.hide.call(this)\n\t\t\t},\n\t\t\tthis))\n\n\t\t\tif (doAnimate) this.$backdrop[0].offsetWidth; // force reflow\n\t\t\tthis.$backdrop.addClass('in');\n\t\t\tif (!callback) return;\n\t\t\tdoAnimate ? this.$backdrop.one('bsTransitionEnd', callback).emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callback();\n\t\t} else if (!this.isShown && this.$backdrop) {\n\t\t\tthis.$backdrop.removeClass('in');\n\t\t\tvar callbackRemove = function() {\n\t\t\t\tthat.removeBackdrop();\n\t\t\t\tcallback && callback();\n\t\t\t}\n\t\t\t$.support.transition && this.$element.hasClass('fade') ? this.$backdrop.one('bsTransitionEnd', callbackRemove).emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callbackRemove()\n\n\t\t} else if (callback) {\n\t\t\tcallback();\n\t\t}\n\t}\n\n\tModal.prototype.checkScrollbar = function() {\n\t\tthis.scrollbarWidth = this.measureScrollbar();\n\t}\n\n\tModal.prototype.setScrollbar = function() {\n\t\tvar bodyPad = parseInt((this.$body.css('padding-right') || 0), 10);\n\t\tif (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth);\n\t}\n\n\tModal.prototype.resetScrollbar = function() {\n\t\tthis.$body.css('padding-right', '')\n\t}\n\n\tModal.prototype.measureScrollbar = function() { // thx walsh\n\t\tif (document.body.clientWidth >= window.innerWidth) return 0\n\t\tvar scrollDiv = document.createElement('div');\n\t\tscrollDiv.className = 'modal-scrollbar-measure';\n\t\tthis.$body.append(scrollDiv);\n\t\tvar scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;\n\t\tthis.$body[0].removeChild(scrollDiv);\n\t\treturn scrollbarWidth;\n\t}\n\n\t// MODAL PLUGIN DEFINITION\n\t// =======================\n\tfunction Plugin(option, _relatedTarget) {\n\t\treturn this.each(function() {\n\t\t\tvar $this = $(this);\n\t\t\tvar data = $this.data('bs.modal');\n\t\t\tvar options = $.extend({},Modal.DEFAULTS, $this.data(), typeof option == 'object' && option);\n\t\t\tif (!data) $this.data('bs.modal', (data = new Modal(this, options)));\n\t\t\tif (typeof option == 'string') data[option](_relatedTarget);\n\t\t\telse if (options.show) data.show(_relatedTarget);\n\t\t})\n\t}\n\n\tvar old = $.fn.modal;\n\t$.fn.modal = Plugin;\n\t$.fn.modal.Constructor = Modal;\n\n\t// MODAL NO CONFLICT\n\t// =================\n\t$.fn.modal.noConflict = function() {\n\t\t$.fn.modal = old;\n\t\treturn this;\n\t}\n\n\t// MODAL DATA-API\n\t// ==============\n\t$(document).on('click.bs.modal.data-api', '[data-toggle=\"modal\"]',\n\tfunction(e) {\n\t\tvar $this = $(this);\n\t\tvar href = $this.attr('href');\n\t\tvar $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\\s]+$)/, ''))); // strip for ie7\n\t\tvar option = $target.data('bs.modal') ? 'toggle': $.extend({remote: !/#/.test(href) && href},$target.data(), $this.data());\n\n\t\tif ($this.is('a')) e.preventDefault();\n\t\t$target.one('show.bs.modal',function(showEvent) {\n\t\t\tif (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown\n\t\t\t$target.one('hidden.bs.modal',function() {\n\t\t\t\t$this.is(':visible') && $this.trigger('focus');\n\t\t\t});\n\t\t});\n\t\tPlugin.call($target, option, this);\n\t});\n} (window.jQuery);\n\n/* =======================================================================\n * Bootstrap.dropdown.js v3.3.0\n * http://getbootstrap.com/javascript/#dropdowns\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n!function($) {\n\t'use strict';\n\tvar backdrop = '.dropdown-backdrop';\n\tvar toggle = '[data-toggle=\"dropdown\"]';\n\tvar Dropdown = function(element) {\n\t\t$(element).on('click.bs.dropdown', this.toggle)\n\t}\n\tDropdown.VERSION = '3.3.5';\n\tfunction getParent($this) {\n\t\tvar selector = $this.attr('data-target');\n\t\tif (!selector) {\n\t\t\tselector = $this.attr('href');\n\t\t\tselector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\\s]*$)/, ''); // strip for ie7\n\t\t}\n\t\tvar $parent = selector && $(selector);\n\t\treturn $parent && $parent.length ? $parent: $this.parent();\n\t}\n\tfunction clearMenus(e) {\n\t\tif (e && e.which === 3) return $(backdrop).remove();\n\t\t$(toggle).each(function() {\n\t\t\tvar $this = $(this);\n\t\t\tvar $parent = getParent($this);\n\t\t\tvar relatedTarget = {\n\t\t\t\trelatedTarget: this\n\t\t\t}\n\t\t\tif (!$parent.hasClass('open')) return;\n\t\t\tif (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget));\n\t\t\tif (e.isDefaultPrevented()) return;\n\t\t\t$this.attr('aria-expanded', 'false');\n\t\t\t$parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget);\n\t\t});\n\t}\n\tDropdown.prototype.toggle = function(e) {\n\t\tvar $this = $(this);\n\t\tif ($this.is('.disabled, :disabled')) return;\n\t\tvar $parent = getParent($this);\n\t\tvar isActive = $parent.hasClass('open');\n\t\tclearMenus();\n\t\tif (!isActive) {\n\t\t\tif ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {\n\t\t\t\t// if mobile we use a backdrop because click events don't delegate\n\t\t\t\t$(document.createElement('div')).addClass('dropdown-backdrop').insertAfter($(this)).on('click', clearMenus);\n\t\t\t}\n\t\t\tvar relatedTarget = {\n\t\t\t\trelatedTarget: this\n\t\t\t}\n\t\t\t$parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget));\n\t\t\tif (e.isDefaultPrevented()) return $this.trigger('focus').attr('aria-expanded', 'true');\n\t\t\t$parent.toggleClass('open').trigger('shown.bs.dropdown', relatedTarget);\n\t\t}\n\t\treturn false;\n\t}\n\tDropdown.prototype.keydown = function(e) {\n\t\tif (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return;\n\t\tvar $this = $(this);\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\tif ($this.is('.disabled, :disabled')) return;\n\t\tvar $parent = getParent($this);\n\t\tvar isActive = $parent.hasClass('open');\n\t\tif (!isActive && e.which != 27 || isActive && e.which == 27) {\n\t\t\tif (e.which == 27)\n\t\t\t$parent.find(toggle).trigger('focus');\n\t\t\treturn;\n\t\t\t$this.trigger('click');\n\t\t}\n\t\tvar desc = ' li:not(.disabled):visible a';\n\t\tvar $items = $parent.find('.dropdown-menu' + desc);\n\t\tif (!$items.length) return;\n\t\tvar index = $items.index(e.target);\n\t\tif (e.which == 38 && index > 0) index-- // up\n\t\tif (e.which == 40 && index < $items.length - 1) index++; // down\n\t\tif (!~index) index = 0;\n\t\t$items.eq(index).trigger('focus');\n\t}\n\tfunction Plugin(option) {\n\t\treturn this.each(function() {\n\t\t\tvar $this = $(this);\n\t\t\tvar data = $this.data('bs.dropdown');\n\t\t\tif (!data) {\n\t\t\t\t$this.data('bs.dropdown', (data = new Dropdown(this)));\n\t\t\t}\n\t\t\tif (typeof option == 'string') {\n\t\t\t\tdata[option].call($this);\n\t\t\t}\n\t\t});\n\t}\n\tvar old = $.fn.dropdown;\n\t$.fn.dropdown = Plugin;\n\t$.fn.dropdown.Constructor = Dropdown;\n\t$.fn.dropdown.noConflict = function() {\n\t\t$.fn.dropdown = old;\n\t\treturn this;\n\t}\n\t$(document).on('click.bs.dropdown.data-api', clearMenus).on('click.bs.dropdown.data-api', '.dropdown form',\n\tfunction(e) {\n\t\te.stopPropagation()\n\t}).on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle).on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown).on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown);\n} (window.jQuery);\n$(function() {\n\t/*下拉菜单*/\n\t$(document).on(\"mouseenter\", \".dropDown\",\n\tfunction() {\n\t\t$(this).addClass(\"hover\");\n\t});\n\t$(document).on(\"mouseleave\", \".dropDown\",\n\tfunction() {\n\t\t$(this).removeClass(\"hover\");\n\t});\n\t$(document).on(\"mouseenter\", \".dropDown_hover\",\n\tfunction() {\n\t\t$(this).addClass(\"open\");\n\t});\n\t$(document).on(\"mouseleave\", \".dropDown_hover\",\n\tfunction() {\n\t\t$(this).removeClass(\"open\");\n\t});\n\t$(document).on(\"click\", \".dropDown-menu li a\",\n\tfunction() {\n\t\t$(\".dropDown\").removeClass('open');\n\t});\n\t$(document).on(\"mouseenter\", \".menu > li\",\n\tfunction() {\n\t\t$(this).addClass(\"open\");\n\t});\n\t$(document).on(\"mouseleave\", \".menu > li\",\n\tfunction() {\n\t\t$(this).removeClass(\"open\");\n\t});\n});\n\n/* =======================================================================\n * Bootstrap.transition.js v3.3.0\n * http://getbootstrap.com/javascript/#transitions\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n!function ($) {\n\t'use strict';\n\tfunction transitionEnd() {\n\t\tvar el = document.createElement('bootstrap');\n\t\tvar transEndEventNames = {\n\t\t\tWebkitTransition : 'webkitTransitionEnd',\n\t\t\tMozTransition    : 'transitionend',\n\t\t\tOTransition      : 'oTransitionEnd otransitionend',\n\t\t\ttransition       : 'transitionend'\n\t\t}\n\t\tfor (var name in transEndEventNames) {\n\t\t\tif (el.style[name] !== undefined) {\n\t\t\t\treturn { end: transEndEventNames[name] }\n\t\t\t}\n\t\t}\n\t\treturn false // explicit for ie8 (  ._.)\n\t}\n\t// http://blog.alexmaccaw.com/css-transitions\n\t$.fn.emulateTransitionEnd = function (duration) {\n\t\tvar called = false;\n\t\tvar $el = this;\n\t\t$(this).one('bsTransitionEnd', function () { called = true })\n\t\tvar callback = function () {\n\t\t\tif (!called) $($el).trigger($.support.transition.end)\n\t\t}\n\t\tsetTimeout(callback, duration);\n\t\treturn this;\n\t}\n\t$(function () {\n\t\t$.support.transition = transitionEnd();\n\t\tif (!$.support.transition) return;\n\t\t$.event.special.bsTransitionEnd = {\n\t\t\tbindType: $.support.transition.end,\n\t\t\tdelegateType: $.support.transition.end,\n\t\t\thandle: function (e) {\n\t\t\t\tif ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments);\n\t\t\t}\n\t\t}\n\t})\n}(window.jQuery);\n\n/* =======================================================================\n * Bootstrap.tooltip.js v3.3.0\n * http://getbootstrap.com/javascript/#tooltip\n * Inspired by the original jQuery.tipsy by Jason Frame\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n!function($) {\n\t'use strict';\n\n\t// TOOLTIP PUBLIC CLASS DEFINITION\n\t// ===============================\n\tvar Tooltip = function(element, options) {\n\t\tthis.type = this.options = this.enabled = this.timeout = this.hoverState = this.$element = null;\n\t\tthis.init('tooltip', element, options);\n\t}\n\n\tTooltip.VERSION = '3.3.0';\n\tTooltip.TRANSITION_DURATION = 150;\n\n\tTooltip.DEFAULTS = {\n\t\tanimation: true,\n\t\tplacement: 'top',\n\t\tselector: false,\n\t\ttemplate: '<div class=\"tooltip\" role=\"tooltip\"><div class=\"tooltip-arrow\"></div><div class=\"tooltip-inner\"></div></div>',\n\t\ttrigger: 'hover focus',\n\t\ttitle: '',\n\t\tdelay: 0,\n\t\thtml: false,\n\t\tcontainer: false,\n\t\tviewport: {\n\t\t\tselector: 'body',\n\t\t\tpadding: 0\n\t\t}\n\t}\n\n\tTooltip.prototype.init = function(type, element, options) {\n\t\tthis.enabled = true;\n\t\tthis.type = type;\n\t\tthis.$element = $(element);\n\t\tthis.options = this.getOptions(options);\n\t\tthis.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport);\n\n\t\tvar triggers = this.options.trigger.split(' ');\n\t\tfor (var i = triggers.length; i--;) {\n\t\t\tvar trigger = triggers[i];\n\t\t\tif (trigger == 'click') {\n\t\t\t\tthis.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this));\n\t\t\t} else if (trigger != 'manual') {\n\t\t\t\tvar eventIn = trigger == 'hover' ? 'mouseenter': 'focusin';\n\t\t\t\tvar eventOut = trigger == 'hover' ? 'mouseleave': 'focusout';\n\t\t\t\tthis.$element.on(eventIn + '.' + this.type, this.options.selector, $.proxy(this.enter, this));\n\t\t\t\tthis.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this));\n\t\t\t}\n\t\t}\n\n\t\tthis.options.selector ? (this._options = $.extend({},\n\t\tthis.options, {\n\t\t\ttrigger: 'manual',\n\t\t\tselector: ''\n\t\t})) : this.fixTitle()\n\t}\n\n\tTooltip.prototype.getDefaults = function() {\n\t\treturn Tooltip.DEFAULTS;\n\t}\n\n\tTooltip.prototype.getOptions = function(options) {\n\t\toptions = $.extend({},\n\t\tthis.getDefaults(), this.$element.data(), options);\n\t\tif (options.delay && typeof options.delay == 'number') {\n\t\t\toptions.delay = {\n\t\t\t\tshow: options.delay,\n\t\t\t\thide: options.delay\n\t\t\t}\n\t\t}\n\t\treturn options;\n\t}\n\n\tTooltip.prototype.getDelegateOptions = function() {\n\t\tvar options = {}\n\t\tvar defaults = this.getDefaults()\n\n\t\tthis._options && $.each(this._options,\n\t\tfunction(key, value) {\n\t\t\tif (defaults[key] != value) options[key] = value;\n\t\t})\n\n\t\treturn options;\n\t}\n\n\tTooltip.prototype.enter = function(obj) {\n\t\tvar self = obj instanceof this.constructor ?\n\t\tobj: $(obj.currentTarget).data('bs.' + this.type);\n\n\t\tif (self && self.$tip && self.$tip.is(':visible')) {\n\t\t\tself.hoverState = 'in';\n\t\t\treturn;\n\t\t}\n\n\t\tif (!self) {\n\t\t\tself = new this.constructor(obj.currentTarget, this.getDelegateOptions());\n\t\t\t$(obj.currentTarget).data('bs.' + this.type, self);\n\t\t}\n\n\t\tclearTimeout(self.timeout);\n\t\tself.hoverState = 'in';\n\t\tif (!self.options.delay || !self.options.delay.show) return self.show()\n\n\t\tself.timeout = setTimeout(function() {\n\t\t\tif (self.hoverState == 'in') self.show();\n\t\t},\n\t\tself.options.delay.show);\n\t}\n\n\tTooltip.prototype.leave = function(obj) {\n\t\tvar self = obj instanceof this.constructor ? obj: $(obj.currentTarget).data('bs.' + this.type);\n\n\t\tif (!self) {\n\t\t\tself = new this.constructor(obj.currentTarget, this.getDelegateOptions());\n\t\t\t$(obj.currentTarget).data('bs.' + this.type, self);\n\t\t}\n\t\tclearTimeout(self.timeout);\n\t\tself.hoverState = 'out';\n\n\t\tif (!self.options.delay || !self.options.delay.hide) return self.hide();\n\t\tself.timeout = setTimeout(function() {\n\n\t\t\tif (self.hoverState == 'out') self.hide();\n\t\t},\n\t\tself.options.delay.hide);\n\t}\n\n\tTooltip.prototype.show = function() {\n\t\tvar e = $.Event('show.bs.' + this.type);\n\t\tif (this.hasContent() && this.enabled) {\n\t\t\tthis.$element.trigger(e);\n\n\t\t\tvar inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]);\n\t\t\tif (e.isDefaultPrevented() || !inDom) return;\n\t\t\tvar that = this;\n\t\t\tvar $tip = this.tip();\n\t\t\tvar tipId = this.getUID(this.type);\n\n\t\t\tthis.setContent();\n\t\t\t$tip.attr('id', tipId);\n\t\t\tthis.$element.attr('aria-describedby', tipId);\n\n\t\t\tif (this.options.animation) $tip.addClass('fade');\n\n\t\t\tvar placement = typeof this.options.placement == 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement;\n\n\t\t\tvar autoToken = /\\s?auto?\\s?/i;\n\t\t\tvar autoPlace = autoToken.test(placement);\n\t\t\tif (autoPlace) placement = placement.replace(autoToken, '') || 'top';\n\n\t\t\t$tip.detach().css({\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0,\n\t\t\t\tdisplay: 'block'\n\t\t\t}).addClass(placement).data('bs.' + this.type, this);\n\n\t\t\tthis.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element);\n\t\t\tvar pos = this.getPosition();\n\t\t\tvar actualWidth = $tip[0].offsetWidth;\n\t\t\tvar actualHeight = $tip[0].offsetHeight;\n\n\t\t\tif (autoPlace) {\n\t\t\t\tvar orgPlacement = placement;\n\t\t\t\tvar $container = this.options.container ? $(this.options.container) : this.$element.parent();\n\t\t\t\tvar containerDim = this.getPosition($container);\n\n\t\t\t\tplacement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top': placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom': placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left': placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right': placement\n\t\t\t\t$tip.removeClass(orgPlacement).addClass(placement);\n\t\t\t}\n\n\t\t\tvar calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight);\n\t\t\tthis.applyPlacement(calculatedOffset, placement);\n\t\t\tvar complete = function() {\n\t\t\t\tvar prevHoverState = that.hoverState;\n\t\t\t\tthat.$element.trigger('shown.bs.' + that.type);\n\t\t\t\tthat.hoverState = null;\n\t\t\t\tif (prevHoverState == 'out') that.leave(that);\n\t\t\t}\n\n\t\t\t$.support.transition && this.$tip.hasClass('fade') ? $tip.one('bsTransitionEnd', complete).emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete()\n\t\t}\n\t}\n\n\tTooltip.prototype.applyPlacement = function(offset, placement) {\n\t\tvar $tip = this.tip();\n\t\tvar width = $tip[0].offsetWidth;\n\t\tvar height = $tip[0].offsetHeight;\n\n\t\t// manually read margins because getBoundingClientRect includes difference\n\t\tvar marginTop = parseInt($tip.css('margin-top'), 10);\n\t\tvar marginLeft = parseInt($tip.css('margin-left'), 10);\n\n\t\t// we must check for NaN for ie 8/9\n\t\tif (isNaN(marginTop)) marginTop = 0;\n\t\tif (isNaN(marginLeft)) marginLeft = 0;\n\n\t\toffset.top = offset.top + marginTop;\n\t\toffset.left = offset.left + marginLeft;\n\n\t\t// $.fn.offset doesn't round pixel values\n\t\t// so we use setOffset directly with our own function B-0\n\t\t$.offset.setOffset($tip[0], $.extend({\n\t\t\tusing: function(props) {\n\t\t\t\t$tip.css({\n\t\t\t\t\ttop: Math.round(props.top),\n\t\t\t\t\tleft: Math.round(props.left)\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\toffset), 0);\n\n\t\t$tip.addClass('in');\n\n\t\t// check to see if placing tip in new offset caused the tip to resize itself\n\t\tvar actualWidth = $tip[0].offsetWidth;\n\t\tvar actualHeight = $tip[0].offsetHeight;\n\n\t\tif (placement == 'top' && actualHeight != height) {\n\t\t\toffset.top = offset.top + height - actualHeight;\n\t\t}\n\n\t\tvar delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);\n\n\t\tif (delta.left) offset.left += delta.left;\n\t\telse offset.top += delta.top;\n\n\t\tvar isVertical = /top|bottom/.test(placement);\n\t\tvar arrowDelta = isVertical ? delta.left * 2 - width + actualWidth: delta.top * 2 - height + actualHeight;\n\t\tvar arrowOffsetPosition = isVertical ? 'offsetWidth': 'offsetHeight';\n\n\t\t$tip.offset(offset);\n\t\tthis.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical);\n\t}\n\n\tTooltip.prototype.replaceArrow = function(delta, dimension, isHorizontal) {\n\t\tthis.arrow().css(isHorizontal ? 'left': 'top', 50 * (1 - delta / dimension) + '%').css(isHorizontal ? 'top': 'left', '');\n\t}\n\n\tTooltip.prototype.setContent = function() {\n\t\tvar $tip = this.tip();\n\t\tvar title = this.getTitle();\n\t\t$tip.find('.tooltip-inner')[this.options.html ? 'html': 'text'](title);\n\t\t$tip.removeClass('fade in top bottom left right');\n\t}\n\n\tTooltip.prototype.hide = function(callback) {\n\t\tvar that = this;\n\t\tvar $tip = this.tip();\n\t\tvar e = $.Event('hide.bs.' + this.type);\n\t\tfunction complete() {\n\t\t\tif (that.hoverState != 'in') $tip.detach();\n\t\t\tthat.$element.removeAttr('aria-describedby').trigger('hidden.bs.' + that.type);\n\t\t\tcallback && callback();\n\t\t}\n\t\tthis.$element.trigger(e);\n\t\tif (e.isDefaultPrevented()) return;\n\t\t$tip.removeClass('in');\n\n\t\t$.support.transition && this.$tip.hasClass('fade') ? $tip.one('bsTransitionEnd', complete).emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete();\n\t\tthis.hoverState = null;\n\t\treturn this;\n\t}\n\n\tTooltip.prototype.fixTitle = function() {\n\t\tvar $e = this.$element\n\t\tif ($e.attr('title') || typeof($e.attr('data-original-title')) != 'string') {\n\t\t\t$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')\n\t\t}\n\t}\n\n\tTooltip.prototype.hasContent = function() {\n\t\treturn this.getTitle();\n\t}\n\n\tTooltip.prototype.getPosition = function($element) {\n\t\t$element = $element || this.$element;\n\t\tvar el = $element[0];\n\t\tvar isBody = el.tagName == 'BODY';\n\t\tvar elRect = el.getBoundingClientRect();\n\t\tif (elRect.width == null) {\n\t\t\t// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093\n\t\t\telRect = $.extend({},\n\t\t\telRect, {\n\t\t\t\twidth: elRect.right - elRect.left,\n\t\t\t\theight: elRect.bottom - elRect.top\n\t\t\t});\n\t\t}\n\t\tvar elOffset = isBody ? {\n\t\t\ttop: 0,\n\t\t\tleft: 0\n\t\t}: $element.offset();\n\t\tvar scroll = {\n\t\t\tscroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop: $element.scrollTop()\n\t\t}\n\t\tvar outerDims = isBody ? {\n\t\t\twidth: $(window).width(),\n\t\t\theight: $(window).height()\n\t\t}: null\n\t\treturn $.extend({},\n\t\telRect, scroll, outerDims, elOffset)\n\t}\n\n\tTooltip.prototype.getCalculatedOffset = function(placement, pos, actualWidth, actualHeight) {\n\t\treturn placement == 'bottom' ? {\n\t\t\ttop: pos.top + pos.height,\n\t\t\tleft: pos.left + pos.width / 2 - actualWidth / 2\n\t\t}: placement == 'top' ? {\n\t\t\ttop: pos.top - actualHeight,\n\t\t\tleft: pos.left + pos.width / 2 - actualWidth / 2\n\t\t}: placement == 'left' ? {\n\t\t\ttop: pos.top + pos.height / 2 - actualHeight / 2,\n\t\t\tleft: pos.left - actualWidth\n\t\t}:\n\t\t/* placement == 'right' */\n\t\t{\n\t\t\ttop: pos.top + pos.height / 2 - actualHeight / 2,\n\t\t\tleft: pos.left + pos.width\n\t\t}\n\n\t}\n\n\tTooltip.prototype.getViewportAdjustedDelta = function(placement, pos, actualWidth, actualHeight) {\n\t\tvar delta = {\n\t\t\ttop: 0,\n\t\t\tleft: 0\n\t\t}\n\t\tif (!this.$viewport) return delta;\n\n\t\tvar viewportPadding = this.options.viewport && this.options.viewport.padding || 0;\n\t\tvar viewportDimensions = this.getPosition(this.$viewport);\n\n\t\tif (/right|left/.test(placement)) {\n\t\t\tvar topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll;\n\t\t\tvar bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight;\n\t\t\tif (topEdgeOffset < viewportDimensions.top) { // top overflow\n\t\t\t\tdelta.top = viewportDimensions.top - topEdgeOffset;\n\t\t\t} else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow\n\t\t\t\tdelta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;\n\t\t\t}\n\t\t} else {\n\t\t\tvar leftEdgeOffset = pos.left - viewportPadding;\n\t\t\tvar rightEdgeOffset = pos.left + viewportPadding + actualWidth;\n\t\t\tif (leftEdgeOffset < viewportDimensions.left) { // left overflow\n\t\t\t\tdelta.left = viewportDimensions.left - leftEdgeOffset;\n\t\t\t} else if (rightEdgeOffset > viewportDimensions.width) { // right overflow\n\t\t\t\tdelta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;\n\t\t\t}\n\t\t}\n\t\treturn delta\n\t}\n\n\tTooltip.prototype.getTitle = function() {\n\t\tvar title;\n\t\tvar $e = this.$element;\n\t\tvar o = this.options;\n\t\ttitle = $e.attr('data-original-title') || (typeof o.title == 'function' ? o.title.call($e[0]) : o.title)\n\t\treturn title;\n\t}\n\n\tTooltip.prototype.getUID = function(prefix) {\n\t\tdo prefix += ~~ (Math.random() * 1000000);\n\t\twhile (document.getElementById(prefix));\n\t\treturn prefix;\n\t}\n\n\tTooltip.prototype.tip = function() {\n\t\treturn (this.$tip = this.$tip || $(this.options.template));\n\t}\n\n\tTooltip.prototype.arrow = function() {\n\t\treturn (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'));\n\t}\n\n\tTooltip.prototype.enable = function() {\n\t\tthis.enabled = true;\n\t}\n\n\tTooltip.prototype.disable = function() {\n\t\tthis.enabled = false;\n\t}\n\n\tTooltip.prototype.toggleEnabled = function() {\n\t\tthis.enabled = !this.enabled;\n\t}\n\n\tTooltip.prototype.toggle = function(e) {\n\t\tvar self = this;\n\t\tif (e) {\n\t\t\tself = $(e.currentTarget).data('bs.' + this.type);\n\t\t\tif (!self) {\n\t\t\t\tself = new this.constructor(e.currentTarget, this.getDelegateOptions());\n\t\t\t\t$(e.currentTarget).data('bs.' + this.type, self);\n\t\t\t}\n\t\t}\n\t\tself.tip().hasClass('in') ? self.leave(self) : self.enter(self)\n\t}\n\n\tTooltip.prototype.destroy = function() {\n\t\tvar that = this;\n\t\tclearTimeout(this.timeout);\n\t\tthis.hide(function() {\n\t\t\tthat.$element.off('.' + that.type).removeData('bs.' + that.type);\n\t\t});\n\t}\n\n\t// TOOLTIP PLUGIN DEFINITION\n\t// =========================\n\tfunction Plugin(option) {\n\t\treturn this.each(function() {\n\t\t\tvar $this = $(this);\n\t\t\tvar data = $this.data('bs.tooltip');\n\t\t\tvar options = typeof option == 'object' && option;\n\t\t\tvar selector = options && options.selector;\n\n\t\t\tif (!data && option == 'destroy') return;\n\t\t\tif (selector) {\n\t\t\t\tif (!data) $this.data('bs.tooltip', (data = {}));\n\t\t\t\tif (!data[selector]) data[selector] = new Tooltip(this, options);\n\t\t\t} else {\n\t\t\t\tif (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)));\n\t\t\t}\n\t\t\tif (typeof option == 'string') data[option]()\n\t\t})\n\t}\n\n\tvar old = $.fn.tooltip;\n\t$.fn.tooltip = Plugin;\n\t$.fn.tooltip.Constructor = Tooltip;\n\t// TOOLTIP NO CONFLICT\n\t// ===================\n\t$.fn.tooltip.noConflict = function() {\n\t\t$.fn.tooltip = old;\n\t\treturn this;\n\t}\n} (window.jQuery);\n$(function() {\n\t$(\"[data-toggle='tooltip']\").tooltip();\n});\n\n/* =======================================================================\n * Bootstrap.popover.js v3.3.0\n * http://getbootstrap.com/javascript/#popovers\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n!\nfunction($) {\n\t'use strict';\n\t// POPOVER PUBLIC CLASS DEFINITION\n\t// ===============================\n\tvar Popover = function(element, options) {\n\t\tthis.init('popover', element, options)\n\t}\n\n\tif (!$.fn.tooltip) throw new Error('Popover requires tooltip.js');\n\tPopover.VERSION = '3.3.0';\n\tPopover.DEFAULTS = $.extend({},\n\t$.fn.tooltip.Constructor.DEFAULTS, {\n\t\tplacement: 'right',\n\t\ttrigger: 'click',\n\t\tcontent: '',\n\t\ttemplate: '<div class=\"popover\" role=\"tooltip\"><div class=\"arrow\"></div><h3 class=\"popover-title\"></h3><div class=\"popover-content\"></div></div>'\n\t})\n\n\t// NOTE: POPOVER EXTENDS tooltip.js\n\t// ================================\n\tPopover.prototype = $.extend({},$.fn.tooltip.Constructor.prototype);\n\tPopover.prototype.constructor = Popover;\n\tPopover.prototype.getDefaults = function() {\n\t\treturn Popover.DEFAULTS;\n\t}\n\n\tPopover.prototype.setContent = function() {\n\t\tvar $tip = this.tip();\n\t\tvar title = this.getTitle();\n\t\tvar content = this.getContent();\n\n\t\t$tip.find('.popover-title')[this.options.html ? 'html': 'text'](title);\n\t\t$tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events\n\t\t\tthis.options.html ? (typeof content == 'string' ? 'html': 'append') : 'text'](content)\n\n\t\t$tip.removeClass('fade top bottom left right in');\n\n\t\t// IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do\n\t\t// this manually by checking the contents.\n\t\tif (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide();\n\t}\n\n\tPopover.prototype.hasContent = function() {\n\t\treturn this.getTitle() || this.getContent()\n\t}\n\n\tPopover.prototype.getContent = function() {\n\t\tvar $e = this.$element;\n\t\tvar o = this.options;\n\n\t\treturn $e.attr('data-content') || (typeof o.content == 'function' ? o.content.call($e[0]) : o.content)\n\t}\n\n\tPopover.prototype.arrow = function() {\n\t\treturn (this.$arrow = this.$arrow || this.tip().find('.arrow'))\n\t}\n\n\tPopover.prototype.tip = function() {\n\t\tif (!this.$tip) this.$tip = $(this.options.template);\n\t\treturn this.$tip;\n\t}\n\n\t// POPOVER PLUGIN DEFINITION\n\t// =========================\n\tfunction Plugin(option) {\n\t\treturn this.each(function() {\n\t\t\tvar $this = $(this);\n\t\t\tvar data = $this.data('bs.popover');\n\t\t\tvar options = typeof option == 'object' && option;\n\t\t\tvar selector = options && options.selector;\n\n\t\t\tif (!data && option == 'destroy') return;\n\t\t\tif (selector) {\n\t\t\t\tif (!data) $this.data('bs.popover', (data = {}));\n\t\t\t\tif (!data[selector]) data[selector] = new Popover(this, options);\n\t\t\t} else {\n\t\t\t\tif (!data) $this.data('bs.popover', (data = new Popover(this, options)))\n\t\t\t}\n\t\t\tif (typeof option == 'string') data[option]()\n\t\t})\n\t}\n\n\tvar old = $.fn.popover\n\n\t$.fn.popover = Plugin;\n\t$.fn.popover.Constructor = Popover;\n\n\t// POPOVER NO CONFLICT\n\t// ===================\n\t$.fn.popover.noConflict = function() {\n\t\t$.fn.popover = old;\n\t\treturn this;\n\t}\n} (window.jQuery);\n$(function() {\n\t$(\"[data-toggle='popover']\").popover();\n});\n\n/* =======================================================================\n * Bootstrap.alert.js v3.3.0\n * http://getbootstrap.com/javascript/#alerts\n * ========================================================================\n * Copyright 2011-2014 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n * ======================================================================== */\n!function($) {\n\t'use strict';\n\t// ALERT CLASS DEFINITION\n\t// ======================\n\tvar dismiss = '[data-dismiss=\"alert\"]'\n\tvar Alert = function(el) {\n\t\t$(el).on('click', dismiss, this.close)\n\t}\n\n\tAlert.VERSION = '3.3.0'\n\n\tAlert.TRANSITION_DURATION = 150\n\n\tAlert.prototype.close = function(e) {\n\t\tvar $this = $(this);\n\t\tvar selector = $this.attr('data-target');\n\n\t\tif (!selector) {\n\t\t\tselector = $this.attr('href');\n\t\t\tselector = selector && selector.replace(/.*(?=#[^\\s]*$)/, ''); // strip for ie7\n\t\t}\n\n\t\tvar $parent = $(selector);\n\t\tif (e) e.preventDefault();\n\t\tif (!$parent.length) {\n\t\t\t$parent = $this.closest('.alert');\n\t\t}\n\n\t\t$parent.trigger(e = $.Event('close.bs.alert'))\n\n\t\tif (e.isDefaultPrevented()) return;\n\n\t\t$parent.removeClass('in');\n\t\tfunction removeElement() {\n\t\t\t// detach from parent, fire event then clean up data\n\t\t\t$parent.detach().trigger('closed.bs.alert').remove();\n\t\t}\n\n\t\t$.support.transition && $parent.hasClass('fade') ? $parent.one('bsTransitionEnd', removeElement).emulateTransitionEnd(Alert.TRANSITION_DURATION) : removeElement()\n\t}\n\n\t// ALERT PLUGIN DEFINITION\n\t// =======================\n\tfunction Plugin(option) {\n\t\treturn this.each(function() {\n\t\t\tvar $this = $(this);\n\t\t\tvar data = $this.data('bs.alert');\n\t\t\tif (!data) $this.data('bs.alert', (data = new Alert(this)));\n\t\t\tif (typeof option == 'string') data[option].call($this);\n\t\t})\n\t}\n\n\tvar old = $.fn.alert;\n\t$.fn.alert = Plugin;\n\t$.fn.alert.Constructor = Alert;\n\n\t// ALERT NO CONFLICT\n\t// =================\n\t$.fn.alert.noConflict = function() {\n\t\t$.fn.alert = old;\n\t\treturn this;\n\t}\n\t// ALERT DATA-API\n\t// ==============\n\t$(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)\n} (window.jQuery);\n\n/* =========================================================\n * Bootstrap.slider.js v1.0.1\n * Maintainers:\n *\t\tKyle Kemp\n *\t\t\t- Twitter: @seiyria\n *\t\t\t- Github:  seiyria\n *\t\tRohit Kalkur\n *\t\t\t- Twitter: @Rovolutionary\n *\t\t\t- Github:  rovolution\n *\n * =========================================================\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 * Bridget makes jQuery widgets\n * MIT license\n * ========================================================= */\n(function(root, factory) {\n\tif (typeof define === \"function\" && define.amd) {\n\t\tdefine([\"jquery\"], factory);\n\t} else if (typeof module === \"object\" && module.exports) {\n\t\tvar jQuery;\n\t\ttry {\n\t\t\tjQuery = require(\"jquery\");\n\t\t} catch(err) {\n\t\t\tjQuery = null;\n\t\t}\n\t\tmodule.exports = factory(jQuery);\n\t} else {\n\t\troot.Slider = factory(root.jQuery);\n\t}\n} (this,\nfunction($) {\n\t// Reference to Slider constructor\n\tvar Slider; (function($) {\n\t\t'use strict';\n\t\t// -------------------------- utils -------------------------- //\n\t\tvar slice = Array.prototype.slice;\n\t\tfunction noop() {}\n\t\t// -------------------------- definition -------------------------- //\n\t\tfunction defineBridget($) {\n\t\t\t// bail if no jQuery\n\t\t\tif (!$) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t// -------------------------- addOptionMethod -------------------------- //\n\t\t\t/**\n\t\t\t * adds option method -> $().plugin('option', {...})\n\t\t\t * @param {Function} PluginClass - constructor class\n\t\t\t */\n\t\t\tfunction addOptionMethod(PluginClass) {\n\t\t\t\t// don't overwrite original option method\n\t\t\t\tif (PluginClass.prototype.option) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\t// option setter\n\t\t\t\tPluginClass.prototype.option = function(opts) {\n\t\t\t\t\t// bail out if not an object\n\t\t\t\t\tif (!$.isPlainObject(opts)) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.options = $.extend(true, this.options, opts);\n\t\t\t\t};\n\t\t\t}\n\t\t\t// -------------------------- plugin bridge -------------------------- //\n\t\t\t// helper function for logging errors\n\t\t\t// $.error breaks jQuery chaining\n\t\t\tvar logError = typeof console === 'undefined' ? noop: function(message) {\n\t\t\t\tconsole.error(message);\n\t\t\t};\n\t\t\t/**\n\t\t\t * jQuery plugin bridge, access methods like $elem.plugin('method')\n\t\t\t * @param {String} namespace - plugin name\n\t\t\t * @param {Function} PluginClass - constructor class\n\t\t\t*/\n\t\t\tfunction bridge(namespace, PluginClass) {\n\t\t\t\t// add to jQuery fn namespace\n\t\t\t\t$.fn[namespace] = function(options) {\n\t\t\t\t\tif (typeof options === 'string') {\n\t\t\t\t\t\t// call plugin method when first argument is a string\n\t\t\t\t\t\t// get arguments for method\n\t\t\t\t\t\tvar args = slice.call(arguments, 1);\n\t\t\t\t\t\tfor (var i = 0,\n\t\t\t\t\t\tlen = this.length; i < len; i++) {\n\t\t\t\t\t\t\tvar elem = this[i];\n\t\t\t\t\t\t\tvar instance = $.data(elem, namespace);\n\t\t\t\t\t\t\tif (!instance) {\n\t\t\t\t\t\t\t\tlogError(\"cannot call methods on \" + namespace + \" prior to initialization; \" + \"attempted to call '\" + options + \"'\");\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!$.isFunction(instance[options]) || options.charAt(0) === '_') {\n\t\t\t\t\t\t\t\tlogError(\"no such method '\" + options + \"' for \" + namespace + \" instance\");\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// trigger method with arguments\n\t\t\t\t\t\t\tvar returnValue = instance[options].apply(instance, args);\n\n\t\t\t\t\t\t\t// break look and return first value if provided\n\t\t\t\t\t\t\tif (returnValue !== undefined && returnValue !== instance) {\n\t\t\t\t\t\t\t\treturn returnValue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// return this if no return value\n\t\t\t\t\t\treturn this;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvar objects = this.map(function() {\n\t\t\t\t\t\t\tvar instance = $.data(this, namespace);\n\t\t\t\t\t\t\tif (instance) {\n\t\t\t\t\t\t\t\t// apply options & init\n\t\t\t\t\t\t\t\tinstance.option(options);\n\t\t\t\t\t\t\t\tinstance._init();\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t// initialize new instance\n\t\t\t\t\t\t\t\tinstance = new PluginClass(this, options);\n\t\t\t\t\t\t\t\t$.data(this, namespace, instance);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn $(this);\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (!objects || objects.length > 1) {\n\t\t\t\t\t\t\treturn objects;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn objects[0];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// -------------------------- bridget -------------------------- //\n\t\t\t/**\n\t\t\t * converts a Prototypical class into a proper jQuery plugin\n\t\t\t *   the class must have a ._init method\n\t\t\t * @param {String} namespace - plugin name, used in $().pluginName\n\t\t\t * @param {Function} PluginClass - constructor class\n\t\t\t */\n\t\t\t$.bridget = function(namespace, PluginClass) {\n\t\t\t\taddOptionMethod(PluginClass);\n\t\t\t\tbridge(namespace, PluginClass);\n\t\t\t};\n\t\t\treturn $.bridget;\n\t\t}\n\n\t\t// get jquery from browser global\n\t\tdefineBridget($);\n\t})($);\n\t/*************************************************\n\t\t\tBOOTSTRAP-SLIDER SOURCE CODE\n\t**************************************************/\n\t(function($) {\n\t\tvar ErrorMsgs = {\n\t\t\tformatInvalidInputErrorMsg: function(input) {\n\t\t\t\treturn \"Invalid input value '\" + input + \"' passed in\";\n\t\t\t},\n\t\t\tcallingContextNotSliderInstance: \"Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method\"\n\t\t};\n\n\t\t/*************************************************\n\t\t\t\t\t\t\tCONSTRUCTOR\n\t\t**************************************************/\n\t\tSlider = function(element, options) {\n\t\t\tcreateNewSlider.call(this, element, options);\n\t\t\treturn this;\n\t\t};\n\t\tfunction createNewSlider(element, options) {\n\t\t\t/*************************************************\n\t\t\t\t\t\t\tCreate Markup\n\t\t\t**************************************************/\n\t\t\tif (typeof element === \"string\") {\n\t\t\t\tthis.element = document.querySelector(element);\n\t\t\t} else if (element instanceof HTMLElement) {\n\t\t\t\tthis.element = element;\n\t\t\t}\n\n\t\t\tvar origWidth = this.element.style.width;\n\t\t\tvar updateSlider = false;\n\t\t\tvar parent = this.element.parentNode;\n\t\t\tvar sliderTrackSelection;\n\t\t\tvar sliderMinHandle;\n\t\t\tvar sliderMaxHandle;\n\n\t\t\tif (this.sliderElem) {\n\t\t\t\tupdateSlider = true;\n\t\t\t} else {\n\t\t\t\t/* Create elements needed for slider */\n\t\t\t\tthis.sliderElem = document.createElement(\"div\");\n\t\t\t\tthis.sliderElem.className = \"slider\";\n\n\t\t\t\t/* Create slider track elements */\n\t\t\t\tvar sliderTrack = document.createElement(\"div\");\n\t\t\t\tsliderTrack.className = \"slider-track\";\n\n\t\t\t\tsliderTrackSelection = document.createElement(\"div\");\n\t\t\t\tsliderTrackSelection.className = \"slider-selection\";\n\n\t\t\t\tsliderMinHandle = document.createElement(\"div\");\n\t\t\t\tsliderMinHandle.className = \"slider-handle min-slider-handle\";\n\n\t\t\t\tsliderMaxHandle = document.createElement(\"div\");\n\t\t\t\tsliderMaxHandle.className = \"slider-handle max-slider-handle\";\n\n\t\t\t\tsliderTrack.appendChild(sliderTrackSelection);\n\t\t\t\tsliderTrack.appendChild(sliderMinHandle);\n\t\t\t\tsliderTrack.appendChild(sliderMaxHandle);\n\n\t\t\t\tvar createAndAppendTooltipSubElements = function(tooltipElem) {\n\t\t\t\t\tvar arrow = document.createElement(\"div\");\n\t\t\t\t\tarrow.className = \"tooltip-arrow\";\n\n\t\t\t\t\tvar inner = document.createElement(\"div\");\n\t\t\t\t\tinner.className = \"tooltip-inner\";\n\n\t\t\t\t\ttooltipElem.appendChild(arrow);\n\t\t\t\t\ttooltipElem.appendChild(inner);\n\t\t\t\t};\n\n\t\t\t\t/* Create tooltip elements */\n\t\t\t\tvar sliderTooltip = document.createElement(\"div\");\n\t\t\t\tsliderTooltip.className = \"tooltip tooltip-main\";\n\t\t\t\tcreateAndAppendTooltipSubElements(sliderTooltip);\n\n\t\t\t\tvar sliderTooltipMin = document.createElement(\"div\");\n\t\t\t\tsliderTooltipMin.className = \"tooltip tooltip-min\";\n\t\t\t\tcreateAndAppendTooltipSubElements(sliderTooltipMin);\n\n\t\t\t\tvar sliderTooltipMax = document.createElement(\"div\");\n\t\t\t\tsliderTooltipMax.className = \"tooltip tooltip-max\";\n\t\t\t\tcreateAndAppendTooltipSubElements(sliderTooltipMax);\n\n\t\t\t\t/* Append components to sliderElem */\n\t\t\t\tthis.sliderElem.appendChild(sliderTrack);\n\t\t\t\tthis.sliderElem.appendChild(sliderTooltip);\n\t\t\t\tthis.sliderElem.appendChild(sliderTooltipMin);\n\t\t\t\tthis.sliderElem.appendChild(sliderTooltipMax);\n\n\t\t\t\t/* Append slider element to parent container, right before the original <input> element */\n\t\t\t\tparent.insertBefore(this.sliderElem, this.element);\n\n\t\t\t\t/* Hide original <input> element */\n\t\t\t\tthis.element.style.display = \"none\";\n\t\t\t}\n\t\t\t/* If JQuery exists, cache JQ references */\n\t\t\tif ($) {\n\t\t\t\tthis.$element = $(this.element);\n\t\t\t\tthis.$sliderElem = $(this.sliderElem);\n\t\t\t}\n\n\t\t\t/*************************************************\n\t\t\t\t\t\t\tProcess Options\n\t\t\t**************************************************/\n\t\t\toptions = options ? options: {};\n\t\t\tvar optionTypes = Object.keys(this.defaultOptions);\n\n\t\t\tfor (var i = 0; i < optionTypes.length; i++) {\n\t\t\t\tvar optName = optionTypes[i];\n\n\t\t\t\t// First check if an option was passed in via the constructor\n\t\t\t\tvar val = options[optName];\n\t\t\t\t// If no data attrib, then check data atrributes\n\t\t\t\tval = (typeof val !== 'undefined') ? val : getDataAttrib(this.element, optName);\n\t\t\t\t// Finally, if nothing was specified, use the defaults\n\t\t\t\tval = (val !== null) ? val : this.defaultOptions[optName];\n\n\t\t\t\t// Set all options on the instance of the Slider\n\t\t\t\tif (!this.options) {\n\t\t\t\t\tthis.options = {};\n\t\t\t\t}\n\t\t\t\tthis.options[optName] = val;\n\t\t\t}\n\n\t\t\tfunction getDataAttrib(element, optName) {\n\t\t\t\tvar dataName = \"data-slider-\" + optName;\n\t\t\t\tvar dataValString = element.getAttribute(dataName);\n\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.parse(dataValString);\n\t\t\t\t} catch(err) {\n\t\t\t\t\treturn dataValString;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/*************************************************\n\t\t\t\t\t\t\t\tSetup\n\t\t\t**************************************************/\n\t\t\tthis.eventToCallbackMap = {};\n\t\t\tthis.sliderElem.id = this.options.id;\n\n\t\t\tthis.touchCapable = 'ontouchstart' in window || (window.DocumentTouch && document instanceof window.DocumentTouch);\n\n\t\t\tthis.tooltip = this.sliderElem.querySelector('.tooltip-main');\n\t\t\tthis.tooltipInner = this.tooltip.querySelector('.tooltip-inner');\n\n\t\t\tthis.tooltip_min = this.sliderElem.querySelector('.tooltip-min');\n\t\t\tthis.tooltipInner_min = this.tooltip_min.querySelector('.tooltip-inner');\n\n\t\t\tthis.tooltip_max = this.sliderElem.querySelector('.tooltip-max');\n\t\t\tthis.tooltipInner_max = this.tooltip_max.querySelector('.tooltip-inner');\n\n\t\t\tif (updateSlider === true) {\n\t\t\t\t// Reset classes\n\t\t\t\tthis._removeClass(this.sliderElem, 'slider-horizontal');\n\t\t\t\tthis._removeClass(this.sliderElem, 'slider-vertical');\n\t\t\t\tthis._removeClass(this.tooltip, 'hide');\n\t\t\t\tthis._removeClass(this.tooltip_min, 'hide');\n\t\t\t\tthis._removeClass(this.tooltip_max, 'hide');\n\n\t\t\t\t// Undo existing inline styles for track\n\t\t\t\t[\"left\", \"top\", \"width\", \"height\"].forEach(function(prop) {\n\t\t\t\t\tthis._removeProperty(this.trackSelection, prop);\n\t\t\t\t},\n\t\t\t\tthis);\n\n\t\t\t\t// Undo inline styles on handles\n\t\t\t\t[this.handle1, this.handle2].forEach(function(handle) {\n\t\t\t\t\tthis._removeProperty(handle, 'left');\n\t\t\t\t\tthis._removeProperty(handle, 'top');\n\t\t\t\t},\n\t\t\t\tthis);\n\n\t\t\t\t// Undo inline styles and classes on tooltips\n\t\t\t\t[this.tooltip, this.tooltip_min, this.tooltip_max].forEach(function(tooltip) {\n\t\t\t\t\tthis._removeProperty(tooltip, 'left');\n\t\t\t\t\tthis._removeProperty(tooltip, 'top');\n\t\t\t\t\tthis._removeProperty(tooltip, 'margin-left');\n\t\t\t\t\tthis._removeProperty(tooltip, 'margin-top');\n\n\t\t\t\t\tthis._removeClass(tooltip, 'right');\n\t\t\t\t\tthis._removeClass(tooltip, 'top');\n\t\t\t\t},\n\t\t\t\tthis);\n\t\t\t}\n\n\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\tthis._addClass(this.sliderElem, 'slider-vertical');\n\n\t\t\t\tthis.stylePos = 'top';\n\t\t\t\tthis.mousePos = 'pageY';\n\t\t\t\tthis.sizePos = 'offsetHeight';\n\n\t\t\t\tthis._addClass(this.tooltip, 'right');\n\t\t\t\tthis.tooltip.style.left = '100%';\n\n\t\t\t\tthis._addClass(this.tooltip_min, 'right');\n\t\t\t\tthis.tooltip_min.style.left = '100%';\n\n\t\t\t\tthis._addClass(this.tooltip_max, 'right');\n\t\t\t\tthis.tooltip_max.style.left = '100%';\n\t\t\t} else {\n\t\t\t\tthis._addClass(this.sliderElem, 'slider-horizontal');\n\t\t\t\tthis.sliderElem.style.width = origWidth;\n\n\t\t\t\tthis.options.orientation = 'horizontal';\n\t\t\t\tthis.stylePos = 'left';\n\t\t\t\tthis.mousePos = 'pageX';\n\t\t\t\tthis.sizePos = 'offsetWidth';\n\n\t\t\t\tthis._addClass(this.tooltip, 'top');\n\t\t\t\tthis.tooltip.style.top = -this.tooltip.outerHeight - 14 + 'px';\n\n\t\t\t\tthis._addClass(this.tooltip_min, 'top');\n\t\t\t\tthis.tooltip_min.style.top = -this.tooltip_min.outerHeight - 14 + 'px';\n\n\t\t\t\tthis._addClass(this.tooltip_max, 'top');\n\t\t\t\tthis.tooltip_max.style.top = -this.tooltip_max.outerHeight - 14 + 'px';\n\t\t\t}\n\n\t\t\tif (this.options.value instanceof Array) {\n\t\t\t\tthis.options.range = true;\n\t\t\t} else if (this.options.range) {\n\t\t\t\t// User wants a range, but value is not an array\n\t\t\t\tthis.options.value = [this.options.value, this.options.max];\n\t\t\t}\n\n\t\t\tthis.trackSelection = sliderTrackSelection || this.trackSelection;\n\t\t\tif (this.options.selection === 'none') {\n\t\t\t\tthis._addClass(this.trackSelection, 'hide');\n\t\t\t}\n\n\t\t\tthis.handle1 = sliderMinHandle || this.handle1;\n\t\t\tthis.handle2 = sliderMaxHandle || this.handle2;\n\n\t\t\tif (updateSlider === true) {\n\t\t\t\t// Reset classes\n\t\t\t\tthis._removeClass(this.handle1, 'round triangle');\n\t\t\t\tthis._removeClass(this.handle2, 'round triangle hide');\n\t\t\t}\n\n\t\t\tvar availableHandleModifiers = ['round', 'triangle', 'custom'];\n\t\t\tvar isValidHandleType = availableHandleModifiers.indexOf(this.options.handle) !== -1;\n\t\t\tif (isValidHandleType) {\n\t\t\t\tthis._addClass(this.handle1, this.options.handle);\n\t\t\t\tthis._addClass(this.handle2, this.options.handle);\n\t\t\t}\n\n\t\t\tthis.offset = this._offset(this.sliderElem);\n\t\t\tthis.size = this.sliderElem[this.sizePos];\n\t\t\tthis.setValue(this.options.value);\n\n\t\t\t/******************************************\n\t\t\t\t\t\tBind Event Listeners\n\t\t\t******************************************/\n\t\t\t// Bind keyboard handlers\n\t\t\tthis.handle1Keydown = this._keydown.bind(this, 0);\n\t\t\tthis.handle1.addEventListener(\"keydown\", this.handle1Keydown, false);\n\n\t\t\tthis.handle2Keydown = this._keydown.bind(this, 1);\n\t\t\tthis.handle2.addEventListener(\"keydown\", this.handle2Keydown, false);\n\n\t\t\tif (this.touchCapable) {\n\t\t\t\t// Bind touch handlers\n\t\t\t\tthis.mousedown = this._mousedown.bind(this);\n\t\t\t\tthis.sliderElem.addEventListener(\"touchstart\", this.mousedown, false);\n\t\t\t} else {\n\t\t\t\t// Bind mouse handlers\n\t\t\t\tthis.mousedown = this._mousedown.bind(this);\n\t\t\t\tthis.sliderElem.addEventListener(\"mousedown\", this.mousedown, false);\n\t\t\t}\n\n\t\t\t// Bind tooltip-related handlers\n\t\t\tif (this.options.tooltip === 'hide') {\n\t\t\t\tthis._addClass(this.tooltip, 'hide');\n\t\t\t\tthis._addClass(this.tooltip_min, 'hide');\n\t\t\t\tthis._addClass(this.tooltip_max, 'hide');\n\t\t\t} else if (this.options.tooltip === 'always') {\n\t\t\t\tthis._showTooltip();\n\t\t\t\tthis._alwaysShowTooltip = true;\n\t\t\t} else {\n\t\t\t\tthis.showTooltip = this._showTooltip.bind(this);\n\t\t\t\tthis.hideTooltip = this._hideTooltip.bind(this);\n\n\t\t\t\tthis.sliderElem.addEventListener(\"mouseenter\", this.showTooltip, false);\n\t\t\t\tthis.sliderElem.addEventListener(\"mouseleave\", this.hideTooltip, false);\n\n\t\t\t\tthis.handle1.addEventListener(\"focus\", this.showTooltip, false);\n\t\t\t\tthis.handle1.addEventListener(\"blur\", this.hideTooltip, false);\n\n\t\t\t\tthis.handle2.addEventListener(\"focus\", this.showTooltip, false);\n\t\t\t\tthis.handle2.addEventListener(\"blur\", this.hideTooltip, false);\n\t\t\t}\n\n\t\t\tif (this.options.enabled) {\n\t\t\t\tthis.enable();\n\t\t\t} else {\n\t\t\t\tthis.disable();\n\t\t\t}\n\t\t}\n\n\t\t/*************************************************\n\t\t\t\t\tINSTANCE PROPERTIES/METHODS\n\t\t- Any methods bound to the prototype are considered\n\t\tpart of the plugin's `public` interface\n\t\t**************************************************/\n\t\tSlider.prototype = {\n\t\t\t_init: function() {},\n\t\t\t// NOTE: Must exist to support bridget\n\t\t\tconstructor: Slider,\n\n\t\t\tdefaultOptions: {\n\t\t\t\tid: \"\",\n\t\t\t\tmin: 0,\n\t\t\t\tmax: 10,\n\t\t\t\tstep: 1,\n\t\t\t\tprecision: 0,\n\t\t\t\torientation: 'horizontal',\n\t\t\t\tvalue: 5,\n\t\t\t\trange: false,\n\t\t\t\tselection: 'before',\n\t\t\t\ttooltip: 'show',\n\t\t\t\ttooltip_split: false,\n\t\t\t\thandle: 'round',\n\t\t\t\treversed: false,\n\t\t\t\tenabled: true,\n\t\t\t\tformatter: function(val) {\n\t\t\t\t\tif (val instanceof Array) {\n\t\t\t\t\t\treturn val[0] + \" : \" + val[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn val;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tnatural_arrow_keys: false\n\t\t\t},\n\n\t\t\tover: false,\n\n\t\t\tinDrag: false,\n\n\t\t\tgetValue: function() {\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\treturn this.options.value;\n\t\t\t\t}\n\t\t\t\treturn this.options.value[0];\n\t\t\t},\n\n\t\t\tsetValue: function(val, triggerSlideEvent) {\n\t\t\t\tif (!val) {\n\t\t\t\t\tval = 0;\n\t\t\t\t}\n\t\t\t\tvar oldValue = this.getValue();\n\t\t\t\tthis.options.value = this._validateInputValue(val);\n\t\t\t\tvar applyPrecision = this._applyPrecision.bind(this);\n\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\tthis.options.value[0] = applyPrecision(this.options.value[0]);\n\t\t\t\t\tthis.options.value[1] = applyPrecision(this.options.value[1]);\n\n\t\t\t\t\tthis.options.value[0] = Math.max(this.options.min, Math.min(this.options.max, this.options.value[0]));\n\t\t\t\t\tthis.options.value[1] = Math.max(this.options.min, Math.min(this.options.max, this.options.value[1]));\n\t\t\t\t} else {\n\t\t\t\t\tthis.options.value = applyPrecision(this.options.value);\n\t\t\t\t\tthis.options.value = [Math.max(this.options.min, Math.min(this.options.max, this.options.value))];\n\t\t\t\t\tthis._addClass(this.handle2, 'hide');\n\t\t\t\t\tif (this.options.selection === 'after') {\n\t\t\t\t\t\tthis.options.value[1] = this.options.max;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.options.value[1] = this.options.min;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.diff = this.options.max - this.options.min;\n\t\t\t\tif (this.diff > 0) {\n\t\t\t\t\tthis.percentage = [\n\t\t\t\t\t\t(this.options.value[0] - this.options.min) * 100 / this.diff,\n\t\t\t\t\t\t(this.options.value[1] - this.options.min) * 100 / this.diff,\n\t\t\t\t\t\tthis.options.step * 100 / this.diff];\n\t\t\t\t} else {\n\t\t\t\t\tthis.percentage = [0, 0, 100];\n\t\t\t\t}\n\n\t\t\t\tthis._layout();\n\t\t\t\tvar newValue = this.options.range ? this.options.value : this.options.value[0];\n\n\t\t\t\tif (triggerSlideEvent === true) {\n\t\t\t\t\tthis._trigger('slide', newValue);\n\t\t\t\t}\n\t\t\t\tif (oldValue !== newValue) {\n\t\t\t\t\tthis._trigger('change', {\n\t\t\t\t\t\toldValue: oldValue,\n\t\t\t\t\t\tnewValue: newValue\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tthis._setDataVal(newValue);\n\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\tdestroy: function() {\n\t\t\t\t// Remove event handlers on slider elements\n\t\t\t\tthis._removeSliderEventHandlers();\n\n\t\t\t\t// Remove the slider from the DOM\n\t\t\t\tthis.sliderElem.parentNode.removeChild(this.sliderElem);\n\t\t\t\t/* Show original <input> element */\n\t\t\t\tthis.element.style.display = \"\";\n\n\t\t\t\t// Clear out custom event bindings\n\t\t\t\tthis._cleanUpEventCallbacksMap();\n\n\t\t\t\t// Remove data values\n\t\t\t\tthis.element.removeAttribute(\"data\");\n\n\t\t\t\t// Remove JQuery handlers/data\n\t\t\t\tif ($) {\n\t\t\t\t\tthis._unbindJQueryEventHandlers();\n\t\t\t\t\tthis.$element.removeData('slider');\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tdisable: function() {\n\t\t\t\tthis.options.enabled = false;\n\t\t\t\tthis.handle1.removeAttribute(\"tabindex\");\n\t\t\t\tthis.handle2.removeAttribute(\"tabindex\");\n\t\t\t\tthis._addClass(this.sliderElem, 'slider-disabled');\n\t\t\t\tthis._trigger('slideDisabled');\n\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\tenable: function() {\n\t\t\t\tthis.options.enabled = true;\n\t\t\t\tthis.handle1.setAttribute(\"tabindex\", 0);\n\t\t\t\tthis.handle2.setAttribute(\"tabindex\", 0);\n\t\t\t\tthis._removeClass(this.sliderElem, 'slider-disabled');\n\t\t\t\tthis._trigger('slideEnabled');\n\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\ttoggle: function() {\n\t\t\t\tif (this.options.enabled) {\n\t\t\t\t\tthis.disable();\n\t\t\t\t} else {\n\t\t\t\t\tthis.enable();\n\t\t\t\t}\n\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\tisEnabled: function() {\n\t\t\t\treturn this.options.enabled;\n\t\t\t},\n\n\t\t\ton: function(evt, callback) {\n\t\t\t\tif ($) {\n\t\t\t\t\tthis.$element.on(evt, callback);\n\t\t\t\t\tthis.$sliderElem.on(evt, callback);\n\t\t\t\t} else {\n\t\t\t\t\tthis._bindNonQueryEventHandler(evt, callback);\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\tgetAttribute: function(attribute) {\n\t\t\t\tif (attribute) {\n\n\t\t\t\t\treturn this.options[attribute];\n\t\t\t\t} else {\n\t\t\t\t\treturn this.options;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tsetAttribute: function(attribute, value) {\n\t\t\t\tthis.options[attribute] = value;\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\trefresh: function() {\n\t\t\t\tthis._removeSliderEventHandlers();\n\t\t\t\tcreateNewSlider.call(this, this.element, this.options);\n\t\t\t\tif ($) {\n\t\t\t\t\t// Bind new instance of slider to the element\n\t\t\t\t\t$.data(this.element, 'slider', this);\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\trelayout: function() {\n\t\t\t\tthis._layout();\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t/******************************+\n\t\t\t\t\t\tHELPERS\n\t\t\t- Any method that is not part of the public interface.\n\t\t\t- Place it underneath this comment block and write its signature like so:\n\t\t\t  \t\t\t\t\t_fnName : function() {...}\n\t\t\t********************************/\n\t\t\t_removeSliderEventHandlers: function() {\n\t\t\t\t// Remove event listeners from handle1\n\t\t\t\tthis.handle1.removeEventListener(\"keydown\", this.handle1Keydown, false);\n\t\t\t\tthis.handle1.removeEventListener(\"focus\", this.showTooltip, false);\n\t\t\t\tthis.handle1.removeEventListener(\"blur\", this.hideTooltip, false);\n\n\t\t\t\t// Remove event listeners from handle2\n\t\t\t\tthis.handle2.removeEventListener(\"keydown\", this.handle2Keydown, false);\n\t\t\t\tthis.handle2.removeEventListener(\"focus\", this.handle2Keydown, false);\n\t\t\t\tthis.handle2.removeEventListener(\"blur\", this.handle2Keydown, false);\n\n\t\t\t\t// Remove event listeners from sliderElem\n\t\t\t\tthis.sliderElem.removeEventListener(\"mouseenter\", this.showTooltip, false);\n\t\t\t\tthis.sliderElem.removeEventListener(\"mouseleave\", this.hideTooltip, false);\n\t\t\t\tthis.sliderElem.removeEventListener(\"touchstart\", this.mousedown, false);\n\t\t\t\tthis.sliderElem.removeEventListener(\"mousedown\", this.mousedown, false);\n\t\t\t},\n\t\t\t_bindNonQueryEventHandler: function(evt, callback) {\n\t\t\t\tif (this.eventToCallbackMap[evt] === undefined) {\n\t\t\t\t\tthis.eventToCallbackMap[evt] = [];\n\t\t\t\t}\n\t\t\t\tthis.eventToCallbackMap[evt].push(callback);\n\t\t\t},\n\t\t\t_cleanUpEventCallbacksMap: function() {\n\t\t\t\tvar eventNames = Object.keys(this.eventToCallbackMap);\n\t\t\t\tfor (var i = 0; i < eventNames.length; i++) {\n\t\t\t\t\tvar eventName = eventNames[i];\n\t\t\t\t\tthis.eventToCallbackMap[eventName] = null;\n\t\t\t\t}\n\t\t\t},\n\t\t\t_showTooltip: function() {\n\t\t\t\tif (this.options.tooltip_split === false) {\n\t\t\t\t\tthis._addClass(this.tooltip, 'in');\n\t\t\t\t} else {\n\t\t\t\t\tthis._addClass(this.tooltip_min, 'in');\n\t\t\t\t\tthis._addClass(this.tooltip_max, 'in');\n\t\t\t\t}\n\t\t\t\tthis.over = true;\n\t\t\t},\n\t\t\t_hideTooltip: function() {\n\t\t\t\tif (this.inDrag === false && this.alwaysShowTooltip !== true) {\n\t\t\t\t\tthis._removeClass(this.tooltip, 'in');\n\t\t\t\t\tthis._removeClass(this.tooltip_min, 'in');\n\t\t\t\t\tthis._removeClass(this.tooltip_max, 'in');\n\t\t\t\t}\n\t\t\t\tthis.over = false;\n\t\t\t},\n\t\t\t_layout: function() {\n\t\t\t\tvar positionPercentages;\n\n\t\t\t\tif (this.options.reversed) {\n\t\t\t\t\tpositionPercentages = [100 - this.percentage[0], this.percentage[1]];\n\t\t\t\t} else {\n\t\t\t\t\tpositionPercentages = [this.percentage[0], this.percentage[1]];\n\t\t\t\t}\n\n\t\t\t\tthis.handle1.style[this.stylePos] = positionPercentages[0] + '%';\n\t\t\t\tthis.handle2.style[this.stylePos] = positionPercentages[1] + '%';\n\n\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\tthis.trackSelection.style.top = Math.min(positionPercentages[0], positionPercentages[1]) + '%';\n\t\t\t\t\tthis.trackSelection.style.height = Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';\n\t\t\t\t} else {\n\t\t\t\t\tthis.trackSelection.style.left = Math.min(positionPercentages[0], positionPercentages[1]) + '%';\n\t\t\t\t\tthis.trackSelection.style.width = Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';\n\n\t\t\t\t\tvar offset_min = this.tooltip_min.getBoundingClientRect();\n\t\t\t\t\tvar offset_max = this.tooltip_max.getBoundingClientRect();\n\n\t\t\t\t\tif (offset_min.right > offset_max.left) {\n\t\t\t\t\t\tthis._removeClass(this.tooltip_max, 'top');\n\t\t\t\t\t\tthis._addClass(this.tooltip_max, 'bottom');\n\t\t\t\t\t\tthis.tooltip_max.style.top = 18 + 'px';\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._removeClass(this.tooltip_max, 'bottom');\n\t\t\t\t\t\tthis._addClass(this.tooltip_max, 'top');\n\t\t\t\t\t\tthis.tooltip_max.style.top = this.tooltip_min.style.top;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar formattedTooltipVal;\n\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\tformattedTooltipVal = this.options.formatter(this.options.value);\n\t\t\t\t\tthis._setText(this.tooltipInner, formattedTooltipVal);\n\t\t\t\t\tthis.tooltip.style[this.stylePos] = (positionPercentages[1] + positionPercentages[0]) / 2 + '%';\n\n\t\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px');\n\t\t\t\t\t}\n\n\t\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px');\n\t\t\t\t\t}\n\n\t\t\t\t\tvar innerTooltipMinText = this.options.formatter(this.options.value[0]);\n\t\t\t\t\tthis._setText(this.tooltipInner_min, innerTooltipMinText);\n\n\t\t\t\t\tvar innerTooltipMaxText = this.options.formatter(this.options.value[1]);\n\t\t\t\t\tthis._setText(this.tooltipInner_max, innerTooltipMaxText);\n\n\t\t\t\t\tthis.tooltip_min.style[this.stylePos] = positionPercentages[0] + '%';\n\n\t\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\t\tthis._css(this.tooltip_min, 'margin-top', -this.tooltip_min.offsetHeight / 2 + 'px');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._css(this.tooltip_min, 'margin-left', -this.tooltip_min.offsetWidth / 2 + 'px');\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.tooltip_max.style[this.stylePos] = positionPercentages[1] + '%';\n\n\t\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\t\tthis._css(this.tooltip_max, 'margin-top', -this.tooltip_max.offsetHeight / 2 + 'px');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._css(this.tooltip_max, 'margin-left', -this.tooltip_max.offsetWidth / 2 + 'px');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tformattedTooltipVal = this.options.formatter(this.options.value[0]);\n\t\t\t\t\tthis._setText(this.tooltipInner, formattedTooltipVal);\n\n\t\t\t\t\tthis.tooltip.style[this.stylePos] = positionPercentages[0] + '%';\n\t\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t_removeProperty: function(element, prop) {\n\t\t\t\tif (element.style.removeProperty) {\n\t\t\t\t\telement.style.removeProperty(prop);\n\t\t\t\t} else {\n\t\t\t\t\telement.style.removeAttribute(prop);\n\t\t\t\t}\n\t\t\t},\n\t\t\t_mousedown: function(ev) {\n\t\t\t\tif (!this.options.enabled) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tthis._triggerFocusOnHandle();\n\n\t\t\t\tthis.offset = this._offset(this.sliderElem);\n\t\t\t\tthis.size = this.sliderElem[this.sizePos];\n\n\t\t\t\tvar percentage = this._getPercentage(ev);\n\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\tvar diff1 = Math.abs(this.percentage[0] - percentage);\n\t\t\t\t\tvar diff2 = Math.abs(this.percentage[1] - percentage);\n\t\t\t\t\tthis.dragged = (diff1 < diff2) ? 0 : 1;\n\t\t\t\t} else {\n\t\t\t\t\tthis.dragged = 0;\n\t\t\t\t}\n\n\t\t\t\tthis.percentage[this.dragged] = this.options.reversed ? 100 - percentage: percentage;\n\t\t\t\tthis._layout();\n\n\t\t\t\tif (this.touchCapable) {\n\t\t\t\t\tdocument.removeEventListener(\"touchmove\", this.mousemove, false);\n\t\t\t\t\tdocument.removeEventListener(\"touchend\", this.mouseup, false);\n\t\t\t\t}\n\n\t\t\t\tif (this.mousemove) {\n\t\t\t\t\tdocument.removeEventListener(\"mousemove\", this.mousemove, false);\n\t\t\t\t}\n\t\t\t\tif (this.mouseup) {\n\t\t\t\t\tdocument.removeEventListener(\"mouseup\", this.mouseup, false);\n\t\t\t\t}\n\n\t\t\t\tthis.mousemove = this._mousemove.bind(this);\n\t\t\t\tthis.mouseup = this._mouseup.bind(this);\n\n\t\t\t\tif (this.touchCapable) {\n\t\t\t\t\t// Touch: Bind touch events:\n\t\t\t\t\tdocument.addEventListener(\"touchmove\", this.mousemove, false);\n\t\t\t\t\tdocument.addEventListener(\"touchend\", this.mouseup, false);\n\t\t\t\t}\n\t\t\t\t// Bind mouse events:\n\t\t\t\tdocument.addEventListener(\"mousemove\", this.mousemove, false);\n\t\t\t\tdocument.addEventListener(\"mouseup\", this.mouseup, false);\n\n\t\t\t\tthis.inDrag = true;\n\t\t\t\tvar newValue = this._calculateValue();\n\n\t\t\t\tthis._trigger('slideStart', newValue);\n\n\t\t\t\tthis._setDataVal(newValue);\n\t\t\t\tthis.setValue(newValue);\n\n\t\t\t\tthis._pauseEvent(ev);\n\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t_triggerFocusOnHandle: function(handleIdx) {\n\t\t\t\tif (handleIdx === 0) {\n\t\t\t\t\tthis.handle1.focus();\n\t\t\t\t}\n\t\t\t\tif (handleIdx === 1) {\n\t\t\t\t\tthis.handle2.focus();\n\t\t\t\t}\n\t\t\t},\n\t\t\t_keydown: function(handleIdx, ev) {\n\t\t\t\tif (!this.options.enabled) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tvar dir;\n\t\t\t\tswitch (ev.keyCode) {\n\t\t\t\tcase 37:\n\t\t\t\t\t// left\n\t\t\t\tcase 40:\n\t\t\t\t\t// down\n\t\t\t\t\tdir = -1;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 39:\n\t\t\t\t\t// right\n\t\t\t\tcase 38:\n\t\t\t\t\t// up\n\t\t\t\t\tdir = 1;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!dir) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// use natural arrow keys instead of from min to max\n\t\t\t\tif (this.options.natural_arrow_keys) {\n\t\t\t\t\tvar ifVerticalAndNotReversed = (this.options.orientation === 'vertical' && !this.options.reversed);\n\t\t\t\t\tvar ifHorizontalAndReversed = (this.options.orientation === 'horizontal' && this.options.reversed);\n\n\t\t\t\t\tif (ifVerticalAndNotReversed || ifHorizontalAndReversed) {\n\t\t\t\t\t\tdir = dir * -1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar oneStepValuePercentageChange = dir * this.percentage[2];\n\t\t\t\tvar percentage = this.percentage[handleIdx] + oneStepValuePercentageChange;\n\n\t\t\t\tif (percentage > 100) {\n\t\t\t\t\tpercentage = 100;\n\t\t\t\t} else if (percentage < 0) {\n\t\t\t\t\tpercentage = 0;\n\t\t\t\t}\n\n\t\t\t\tthis.dragged = handleIdx;\n\t\t\t\tthis._adjustPercentageForRangeSliders(percentage);\n\t\t\t\tthis.percentage[this.dragged] = percentage;\n\t\t\t\tthis._layout();\n\n\t\t\t\tvar val = this._calculateValue();\n\n\t\t\t\tthis._trigger('slideStart', val);\n\t\t\t\tthis._setDataVal(val);\n\t\t\t\tthis.setValue(val, true);\n\n\t\t\t\tthis._trigger('slideStop', val);\n\t\t\t\tthis._setDataVal(val);\n\n\t\t\t\tthis._pauseEvent(ev);\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t_pauseEvent: function(ev) {\n\t\t\t\tif (ev.stopPropagation) {\n\t\t\t\t\tev.stopPropagation();\n\t\t\t\t}\n\t\t\t\tif (ev.preventDefault) {\n\t\t\t\t\tev.preventDefault();\n\t\t\t\t}\n\t\t\t\tev.cancelBubble = true;\n\t\t\t\tev.returnValue = false;\n\t\t\t},\n\t\t\t_mousemove: function(ev) {\n\t\t\t\tif (!this.options.enabled) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tvar percentage = this._getPercentage(ev);\n\t\t\t\tthis._adjustPercentageForRangeSliders(percentage);\n\t\t\t\tthis.percentage[this.dragged] = this.options.reversed ? 100 - percentage: percentage;\n\t\t\t\tthis._layout();\n\n\t\t\t\tvar val = this._calculateValue();\n\t\t\t\tthis.setValue(val, true);\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t_adjustPercentageForRangeSliders: function(percentage) {\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\tif (this.dragged === 0 && this.percentage[1] < percentage) {\n\t\t\t\t\t\tthis.percentage[0] = this.percentage[1];\n\t\t\t\t\t\tthis.dragged = 1;\n\t\t\t\t\t} else if (this.dragged === 1 && this.percentage[0] > percentage) {\n\t\t\t\t\t\tthis.percentage[1] = this.percentage[0];\n\t\t\t\t\t\tthis.dragged = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t_mouseup: function() {\n\t\t\t\tif (!this.options.enabled) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (this.touchCapable) {\n\t\t\t\t\t// Touch: Unbind touch event handlers:\n\t\t\t\t\tdocument.removeEventListener(\"touchmove\", this.mousemove, false);\n\t\t\t\t\tdocument.removeEventListener(\"touchend\", this.mouseup, false);\n\t\t\t\t}\n\t\t\t\t// Unbind mouse event handlers:\n\t\t\t\tdocument.removeEventListener(\"mousemove\", this.mousemove, false);\n\t\t\t\tdocument.removeEventListener(\"mouseup\", this.mouseup, false);\n\n\t\t\t\tthis.inDrag = false;\n\t\t\t\tif (this.over === false) {\n\t\t\t\t\tthis._hideTooltip();\n\t\t\t\t}\n\t\t\t\tvar val = this._calculateValue();\n\n\t\t\t\tthis._layout();\n\t\t\t\tthis._trigger('slideStop', val);\n\t\t\t\tthis._setDataVal(val);\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t_calculateValue: function() {\n\t\t\t\tvar val;\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\tval = [this.options.min, this.options.max];\n\t\t\t\t\tif (this.percentage[0] !== 0) {\n\t\t\t\t\t\tval[0] = (Math.max(this.options.min, this.options.min + Math.round((this.diff * this.percentage[0] / 100) / this.options.step) * this.options.step));\n\t\t\t\t\t\tval[0] = this._applyPrecision(val[0]);\n\t\t\t\t\t}\n\t\t\t\t\tif (this.percentage[1] !== 100) {\n\t\t\t\t\t\tval[1] = (Math.min(this.options.max, this.options.min + Math.round((this.diff * this.percentage[1] / 100) / this.options.step) * this.options.step));\n\t\t\t\t\t\tval[1] = this._applyPrecision(val[1]);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tval = (this.options.min + Math.round((this.diff * this.percentage[0] / 100) / this.options.step) * this.options.step);\n\t\t\t\t\tif (val < this.options.min) {\n\t\t\t\t\t\tval = this.options.min;\n\t\t\t\t\t} else if (val > this.options.max) {\n\t\t\t\t\t\tval = this.options.max;\n\t\t\t\t\t}\n\t\t\t\t\tval = parseFloat(val);\n\t\t\t\t\tval = this._applyPrecision(val);\n\t\t\t\t}\n\t\t\t\treturn val;\n\t\t\t},\n\t\t\t_applyPrecision: function(val) {\n\t\t\t\tvar precision = this.options.precision || this._getNumDigitsAfterDecimalPlace(this.options.step);\n\t\t\t\treturn this._applyToFixedAndParseFloat(val, precision);\n\t\t\t},\n\t\t\t_getNumDigitsAfterDecimalPlace: function(num) {\n\t\t\t\tvar match = ('' + num).match(/(?:\\.(\\d+))?(?:[eE]([+-]?\\d+))?$/);\n\t\t\t\tif (!match) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t\treturn Math.max(0, (match[1] ? match[1].length: 0) - (match[2] ? +match[2] : 0));\n\t\t\t},\n\t\t\t_applyToFixedAndParseFloat: function(num, toFixedInput) {\n\t\t\t\tvar truncatedNum = num.toFixed(toFixedInput);\n\t\t\t\treturn parseFloat(truncatedNum);\n\t\t\t},\n\t\t\t/*\n\t\t\t\tCredits to Mike Samuel for the following method!\n\t\t\t\tSource: http://stackoverflow.com/questions/10454518/javascript-how-to-retrieve-the-number-of-decimals-of-a-string-number\n\t\t\t*/\n\t\t\t_getPercentage: function(ev) {\n\t\t\t\tif (this.touchCapable && (ev.type === 'touchstart' || ev.type === 'touchmove')) {\n\t\t\t\t\tev = ev.touches[0];\n\t\t\t\t}\n\t\t\t\tvar percentage = (ev[this.mousePos] - this.offset[this.stylePos]) * 100 / this.size;\n\t\t\t\tpercentage = Math.round(percentage / this.percentage[2]) * this.percentage[2];\n\t\t\t\treturn Math.max(0, Math.min(100, percentage));\n\t\t\t},\n\t\t\t_validateInputValue: function(val) {\n\t\t\t\tif (typeof val === 'number') {\n\t\t\t\t\treturn val;\n\t\t\t\t} else if (val instanceof Array) {\n\t\t\t\t\tthis._validateArray(val);\n\t\t\t\t\treturn val;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error(ErrorMsgs.formatInvalidInputErrorMsg(val));\n\t\t\t\t}\n\t\t\t},\n\t\t\t_validateArray: function(val) {\n\t\t\t\tfor (var i = 0; i < val.length; i++) {\n\t\t\t\t\tvar input = val[i];\n\t\t\t\t\tif (typeof input !== 'number') {\n\t\t\t\t\t\tthrow new Error(ErrorMsgs.formatInvalidInputErrorMsg(input));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t_setDataVal: function(val) {\n\t\t\t\tvar value = \"value: '\" + val + \"'\";\n\t\t\t\tthis.element.setAttribute('data', value);\n\t\t\t\tthis.element.setAttribute('value', val);\n\t\t\t},\n\t\t\t_trigger: function(evt, val) {\n\t\t\t\tval = (val || val === 0) ? val: undefined;\n\n\t\t\t\tvar callbackFnArray = this.eventToCallbackMap[evt];\n\t\t\t\tif (callbackFnArray && callbackFnArray.length) {\n\t\t\t\t\tfor (var i = 0; i < callbackFnArray.length; i++) {\n\t\t\t\t\t\tvar callbackFn = callbackFnArray[i];\n\t\t\t\t\t\tcallbackFn(val);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* If JQuery exists, trigger JQuery events */\n\t\t\t\tif ($) {\n\t\t\t\t\tthis._triggerJQueryEvent(evt, val);\n\t\t\t\t}\n\t\t\t},\n\t\t\t_triggerJQueryEvent: function(evt, val) {\n\t\t\t\tvar eventData = {\n\t\t\t\t\ttype: evt,\n\t\t\t\t\tvalue: val\n\t\t\t\t};\n\t\t\t\tthis.$element.trigger(eventData);\n\t\t\t\tthis.$sliderElem.trigger(eventData);\n\t\t\t},\n\t\t\t_unbindJQueryEventHandlers: function() {\n\t\t\t\tthis.$element.off();\n\t\t\t\tthis.$sliderElem.off();\n\t\t\t},\n\t\t\t_setText: function(element, text) {\n\t\t\t\tif (typeof element.innerText !== \"undefined\") {\n\t\t\t\t\telement.innerText = text;\n\t\t\t\t} else if (typeof element.textContent !== \"undefined\") {\n\t\t\t\t\telement.textContent = text;\n\t\t\t\t}\n\t\t\t},\n\t\t\t_removeClass: function(element, classString) {\n\t\t\t\tvar classes = classString.split(\" \");\n\t\t\t\tvar newClasses = element.className;\n\n\t\t\t\tfor (var i = 0; i < classes.length; i++) {\n\t\t\t\t\tvar classTag = classes[i];\n\t\t\t\t\tvar regex = new RegExp(\"(?:\\\\s|^)\" + classTag + \"(?:\\\\s|$)\");\n\t\t\t\t\tnewClasses = newClasses.replace(regex, \" \");\n\t\t\t\t}\n\n\t\t\t\telement.className = newClasses.trim();\n\t\t\t},\n\t\t\t_addClass: function(element, classString) {\n\t\t\t\tvar classes = classString.split(\" \");\n\t\t\t\tvar newClasses = element.className;\n\n\t\t\t\tfor (var i = 0; i < classes.length; i++) {\n\t\t\t\t\tvar classTag = classes[i];\n\t\t\t\t\tvar regex = new RegExp(\"(?:\\\\s|^)\" + classTag + \"(?:\\\\s|$)\");\n\t\t\t\t\tvar ifClassExists = regex.test(newClasses);\n\n\t\t\t\t\tif (!ifClassExists) {\n\t\t\t\t\t\tnewClasses += \" \" + classTag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telement.className = newClasses.trim();\n\t\t\t},\n\t\t\t_offset: function(obj) {\n\t\t\t\tvar ol = 0;\n\t\t\t\tvar ot = 0;\n\t\t\t\tif (obj.offsetParent) {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tol += obj.offsetLeft;\n\t\t\t\t\t\tot += obj.offsetTop;\n\t\t\t\t\t} while ( obj = obj . offsetParent );\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tleft: ol,\n\t\t\t\t\ttop: ot\n\t\t\t\t};\n\t\t\t},\n\t\t\t_css: function(elementRef, styleName, value) {\n\t\t\t\tif ($) {\n\t\t\t\t\t$.style(elementRef, styleName, value);\n\t\t\t\t} else {\n\t\t\t\t\tvar style = styleName.replace(/^-ms-/, \"ms-\").replace(/-([\\da-z])/gi,\n\t\t\t\t\tfunction(all, letter) {\n\t\t\t\t\t\treturn letter.toUpperCase();\n\t\t\t\t\t});\n\t\t\t\t\telementRef.style[style] = value;\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\n\t\t/*********************************\n\t\t\tAttach to global namespace\n\t\t*********************************/\n\t\tif ($) {\n\t\t\tvar namespace = $.fn.slider ? 'bootstrapSlider': 'slider';\n\t\t\t$.bridget(namespace, Slider);\n\t\t}\n\t})($);\n\treturn Slider;\n}));\n\n/* =========================================================\n* Bootstrap.datetimepicker.js\n* =========================================================\n* Copyright 2012 Stefan Petre\n*\n* Improvements by Andrew Rowls\n* Improvements by Sébastien Malot\n* Improvements by Yun Lai\n* Improvements by Kenneth Henderick\n* Improvements by CuGBabyBeaR\n* Improvements by Christian Vaas <auspex@auspex.eu>\n*\n* Project URL : http://www.malot.fr/bootstrap-datetimepicker\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! (function(factory) {\n\tif (typeof define === 'function' && define.amd) define(['jquery'], factory);\n\telse if (typeof exports === 'object') factory(require('jquery'));\n\telse factory(jQuery);\n} (function($, undefined) {\n\t// Add ECMA262-5 Array methods if not supported natively (IE8)\n\tif (! ('indexOf' in Array.prototype)) {\n\t\tArray.prototype.indexOf = function(find, i) {\n\t\t\tif (i === undefined) i = 0;\n\t\t\tif (i < 0) i += this.length;\n\t\t\tif (i < 0) i = 0;\n\t\t\tfor (var n = this.length; i < n; i++) {\n\t\t\t\tif (i in this && this[i] === find) {\n\t\t\t\t\treturn i;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn - 1;\n\t\t}\n\t}\n\n\tfunction elementOrParentIsFixed(element) {\n\t\tvar $element = $(element);\n\t\tvar $checkElements = $element.add($element.parents());\n\t\tvar isFixed = false;\n\t\t$checkElements.each(function() {\n\t\t\tif ($(this).css('position') === 'fixed') {\n\t\t\t\tisFixed = true;\n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\treturn isFixed;\n\t}\n\n\tfunction UTCDate() {\n\t\treturn new Date(Date.UTC.apply(Date, arguments));\n\t}\n\n\tfunction UTCToday() {\n\t\tvar today = new Date();\n\t\treturn UTCDate(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate(), today.getUTCHours(), today.getUTCMinutes(), today.getUTCSeconds(), 0);\n\t}\n\n\t// Picker object\n\tvar Datetimepicker = function(element, options) {\n\t\tvar that = this;\n\t\tthis.element = $(element);\n\n\t\t// add container for single page application\n\t\t// when page switch the datetimepicker div will be removed also.\n\t\tthis.container = options.container || 'body';\n\n\t\tthis.language = options.language || this.element.data('date-language') || 'en';\n\t\tthis.language = this.language in dates ? this.language: this.language.split('-')[0]; // fr-CA fallback to fr\n\t\tthis.language = this.language in dates ? this.language: 'en';\n\t\tthis.isRTL = dates[this.language].rtl || false;\n\t\tthis.formatType = options.formatType || this.element.data('format-type') || 'standard';\n\t\tthis.format = DPGlobal.parseFormat(options.format || this.element.data('date-format') || dates[this.language].format || DPGlobal.getDefaultFormat(this.formatType, 'input'), this.formatType);\n\t\tthis.isInline = false;\n\t\tthis.isVisible = false;\n\t\tthis.isInput = this.element.is('input');\n\t\tthis.fontAwesome = options.fontAwesome || this.element.data('font-awesome') || false;\n\n\t\tthis.bootcssVer = options.bootcssVer || (this.isInput ? (this.element.is('.form-control') ? 3 : 2) : (this.bootcssVer = this.element.is('.input-group') ? 3 : 2));\n\n\t\tthis.component = this.element.is('.date') ? (this.bootcssVer == 3 ? this.element.find('.input-group-addon .glyphicon-th, .input-group-addon .glyphicon-time, .input-group-addon .glyphicon-remove, .input-group-addon .glyphicon-calendar, .input-group-addon .fa-calendar, .input-group-addon .fa-clock-o').parent() : this.element.find('.add-on .icon-th, .add-on .icon-time, .add-on .icon-calendar, .add-on .fa-calendar, .add-on .fa-clock-o').parent()) : false;\n\t\tthis.componentReset = this.element.is('.date') ? (this.bootcssVer == 3 ? this.element.find('.input-group-addon .glyphicon-remove, .input-group-addon .fa-times').parent() : this.element.find('.add-on .icon-remove, .add-on .fa-times').parent()) : false;\n\t\tthis.hasInput = this.component && this.element.find('input').length;\n\t\tif (this.component && this.component.length === 0) {\n\t\t\tthis.component = false;\n\t\t}\n\t\tthis.linkField = options.linkField || this.element.data('link-field') || false;\n\t\tthis.linkFormat = DPGlobal.parseFormat(options.linkFormat || this.element.data('link-format') || DPGlobal.getDefaultFormat(this.formatType, 'link'), this.formatType);\n\t\tthis.minuteStep = options.minuteStep || this.element.data('minute-step') || 5;\n\t\tthis.pickerPosition = options.pickerPosition || this.element.data('picker-position') || 'bottom-right';\n\t\tthis.showMeridian = options.showMeridian || this.element.data('show-meridian') || false;\n\t\tthis.initialDate = options.initialDate || new Date();\n\t\tthis.zIndex = options.zIndex || this.element.data('z-index') || undefined;\n\t\tthis.title = typeof options.title === 'undefined' ? false: options.title;\n\t\tthis.defaultTimeZone = (new Date).toString().split('(')[1].slice(0, -1);\n\t\tthis.timezone = options.timezone || this.defaultTimeZone;\n\n\t\tthis.icons = {\n\t\t\tleftArrow: this.fontAwesome ? 'fa-arrow-left': (this.bootcssVer === 3 ? 'glyphicon-arrow-left': 'icon-arrow-left'),\n\t\t\trightArrow: this.fontAwesome ? 'fa-arrow-right': (this.bootcssVer === 3 ? 'glyphicon-arrow-right': 'icon-arrow-right')\n\t\t}\n\t\tthis.icontype = this.fontAwesome ? 'fa': 'glyphicon';\n\t\tthis._attachEvents();\n\t\tthis.clickedOutside = function(e) {\n\t\t\t// Clicked outside the datetimepicker, hide it\n\t\t\tif ($(e.target).closest('.datetimepicker').length === 0) {\n\t\t\t\tthat.hide();\n\t\t\t}\n\t\t}\n\n\t\tthis.formatViewType = 'datetime';\n\t\tif ('formatViewType' in options) {\n\t\t\tthis.formatViewType = options.formatViewType;\n\t\t} else if ('formatViewType' in this.element.data()) {\n\t\t\tthis.formatViewType = this.element.data('formatViewType');\n\t\t}\n\n\t\tthis.minView = 0;\n\t\tif ('minView' in options) {\n\t\t\tthis.minView = options.minView;\n\t\t} else if ('minView' in this.element.data()) {\n\t\t\tthis.minView = this.element.data('min-view');\n\t\t}\n\t\tthis.minView = DPGlobal.convertViewMode(this.minView);\n\n\t\tthis.maxView = DPGlobal.modes.length - 1;\n\t\tif ('maxView' in options) {\n\t\t\tthis.maxView = options.maxView;\n\t\t} else if ('maxView' in this.element.data()) {\n\t\t\tthis.maxView = this.element.data('max-view');\n\t\t}\n\t\tthis.maxView = DPGlobal.convertViewMode(this.maxView);\n\n\t\tthis.wheelViewModeNavigation = false;\n\t\tif ('wheelViewModeNavigation' in options) {\n\t\t\tthis.wheelViewModeNavigation = options.wheelViewModeNavigation;\n\t\t} else if ('wheelViewModeNavigation' in this.element.data()) {\n\t\t\tthis.wheelViewModeNavigation = this.element.data('view-mode-wheel-navigation');\n\t\t}\n\n\t\tthis.wheelViewModeNavigationInverseDirection = false;\n\n\t\tif ('wheelViewModeNavigationInverseDirection' in options) {\n\t\t\tthis.wheelViewModeNavigationInverseDirection = options.wheelViewModeNavigationInverseDirection;\n\t\t} else if ('wheelViewModeNavigationInverseDirection' in this.element.data()) {\n\t\t\tthis.wheelViewModeNavigationInverseDirection = this.element.data('view-mode-wheel-navigation-inverse-dir');\n\t\t}\n\n\t\tthis.wheelViewModeNavigationDelay = 100;\n\t\tif ('wheelViewModeNavigationDelay' in options) {\n\t\t\tthis.wheelViewModeNavigationDelay = options.wheelViewModeNavigationDelay;\n\t\t} else if ('wheelViewModeNavigationDelay' in this.element.data()) {\n\t\t\tthis.wheelViewModeNavigationDelay = this.element.data('view-mode-wheel-navigation-delay');\n\t\t}\n\n\t\tthis.startViewMode = 2;\n\t\tif ('startView' in options) {\n\t\t\tthis.startViewMode = options.startView;\n\t\t} else if ('startView' in this.element.data()) {\n\t\t\tthis.startViewMode = this.element.data('start-view');\n\t\t}\n\t\tthis.startViewMode = DPGlobal.convertViewMode(this.startViewMode);\n\t\tthis.viewMode = this.startViewMode;\n\n\t\tthis.viewSelect = this.minView;\n\t\tif ('viewSelect' in options) {\n\t\t\tthis.viewSelect = options.viewSelect;\n\t\t} else if ('viewSelect' in this.element.data()) {\n\t\t\tthis.viewSelect = this.element.data('view-select');\n\t\t}\n\t\tthis.viewSelect = DPGlobal.convertViewMode(this.viewSelect);\n\n\t\tthis.forceParse = true;\n\t\tif ('forceParse' in options) {\n\t\t\tthis.forceParse = options.forceParse;\n\t\t} else if ('dateForceParse' in this.element.data()) {\n\t\t\tthis.forceParse = this.element.data('date-force-parse');\n\t\t}\n\t\tvar template = this.bootcssVer === 3 ? DPGlobal.templateV3: DPGlobal.template;\n\t\twhile (template.indexOf('{iconType}') !== -1) {\n\t\t\ttemplate = template.replace('{iconType}', this.icontype);\n\t\t}\n\t\twhile (template.indexOf('{leftArrow}') !== -1) {\n\t\t\ttemplate = template.replace('{leftArrow}', this.icons.leftArrow);\n\t\t}\n\t\twhile (template.indexOf('{rightArrow}') !== -1) {\n\t\t\ttemplate = template.replace('{rightArrow}', this.icons.rightArrow);\n\t\t}\n\t\tthis.picker = $(template).appendTo(this.isInline ? this.element: this.container) // 'body')\n\t\t.on({\n\t\t\tclick: $.proxy(this.click, this),\n\t\t\tmousedown: $.proxy(this.mousedown, this)\n\t\t});\n\n\t\tif (this.wheelViewModeNavigation) {\n\t\t\tif ($.fn.mousewheel) {\n\t\t\t\tthis.picker.on({\n\t\t\t\t\tmousewheel: $.proxy(this.mousewheel, this)\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tconsole.log('Mouse Wheel event is not supported. Please include the jQuery Mouse Wheel plugin before enabling this option');\n\t\t\t}\n\t\t}\n\n\t\tif (this.isInline) {\n\t\t\tthis.picker.addClass('datetimepicker-inline');\n\t\t} else {\n\t\t\tthis.picker.addClass('datetimepicker-dropdown-' + this.pickerPosition + ' dropdown-menu');\n\t\t}\n\t\tif (this.isRTL) {\n\t\t\tthis.picker.addClass('datetimepicker-rtl');\n\t\t\tvar selector = this.bootcssVer === 3 ? '.prev span, .next span': '.prev i, .next i';\n\t\t\tthis.picker.find(selector).toggleClass(this.icons.leftArrow + ' ' + this.icons.rightArrow);\n\t\t}\n\n\t\t$(document).on('mousedown', this.clickedOutside);\n\t\tthis.autoclose = false;\n\t\tif ('autoclose' in options) {\n\t\t\tthis.autoclose = options.autoclose;\n\t\t} else if ('dateAutoclose' in this.element.data()) {\n\t\t\tthis.autoclose = this.element.data('date-autoclose');\n\t\t}\n\n\t\tthis.keyboardNavigation = true;\n\t\tif ('keyboardNavigation' in options) {\n\t\t\tthis.keyboardNavigation = options.keyboardNavigation;\n\t\t} else if ('dateKeyboardNavigation' in this.element.data()) {\n\t\t\tthis.keyboardNavigation = this.element.data('date-keyboard-navigation');\n\t\t}\n\n\t\tthis.todayBtn = (options.todayBtn || this.element.data('date-today-btn') || false);\n\t\tthis.clearBtn = (options.clearBtn || this.element.data('date-clear-btn') || false);\n\t\tthis.todayHighlight = (options.todayHighlight || this.element.data('date-today-highlight') || false);\n\n\t\tthis.weekStart = ((options.weekStart || this.element.data('date-weekstart') || dates[this.language].weekStart || 0) % 7);\n\t\tthis.weekEnd = ((this.weekStart + 6) % 7);\n\t\tthis.startDate = -Infinity;\n\t\tthis.endDate = Infinity;\n\t\tthis.datesDisabled = [];\n\t\tthis.daysOfWeekDisabled = [];\n\t\tthis.setStartDate(options.startDate || this.element.data('date-startdate'));\n\t\tthis.setEndDate(options.endDate || this.element.data('date-enddate'));\n\t\tthis.setDatesDisabled(options.datesDisabled || this.element.data('date-dates-disabled'));\n\t\tthis.setDaysOfWeekDisabled(options.daysOfWeekDisabled || this.element.data('date-days-of-week-disabled'));\n\t\tthis.setMinutesDisabled(options.minutesDisabled || this.element.data('date-minute-disabled'));\n\t\tthis.setHoursDisabled(options.hoursDisabled || this.element.data('date-hour-disabled'));\n\t\tthis.fillDow();\n\t\tthis.fillMonths();\n\t\tthis.update();\n\t\tthis.showMode();\n\n\t\tif (this.isInline) {\n\t\t\tthis.show();\n\t\t}\n\t};\n\n\tDatetimepicker.prototype = {\n\t\tconstructor: Datetimepicker,\n\t\t_events: [],\n\t\t_attachEvents: function() {\n\t\t\tthis._detachEvents();\n\t\t\tif (this.isInput) { // single input\n\t\t\t\tthis._events = [[this.element, {\n\t\t\t\t\tfocus: $.proxy(this.show, this),\n\t\t\t\t\tkeyup: $.proxy(this.update, this),\n\t\t\t\t\tkeydown: $.proxy(this.keydown, this)\n\t\t\t\t}]];\n\t\t\t} else if (this.component && this.hasInput) { // component: input + button\n\t\t\t\tthis._events = [\n\t\t\t\t// For components that are not readonly, allow keyboard nav\n\t\t\t\t[this.element.find('input'), {\n\t\t\t\t\tfocus: $.proxy(this.show, this),\n\t\t\t\t\tkeyup: $.proxy(this.update, this),\n\t\t\t\t\tkeydown: $.proxy(this.keydown, this)\n\t\t\t\t}], [this.component, {\n\t\t\t\t\tclick: $.proxy(this.show, this)\n\t\t\t\t}]];\n\t\t\t\tif (this.componentReset) {\n\t\t\t\t\tthis._events.push([this.componentReset, {\n\t\t\t\t\t\tclick: $.proxy(this.reset, this)\n\t\t\t\t\t}]);\n\t\t\t\t}\n\t\t\t} else if (this.element.is('div')) { // inline datetimepicker\n\t\t\t\tthis.isInline = true;\n\t\t\t} else {\n\t\t\t\tthis._events = [[this.element, {\n\t\t\t\t\tclick: $.proxy(this.show, this)\n\t\t\t\t}]];\n\t\t\t}\n\t\t\tfor (var i = 0,\n\t\t\tel, ev; i < this._events.length; i++) {\n\t\t\t\tel = this._events[i][0];\n\t\t\t\tev = this._events[i][1];\n\t\t\t\tel.on(ev);\n\t\t\t}\n\t\t},\n\n\t\t_detachEvents: function() {\n\t\t\tfor (var i = 0,\n\t\t\tel, ev; i < this._events.length; i++) {\n\t\t\t\tel = this._events[i][0];\n\t\t\t\tev = this._events[i][1];\n\t\t\t\tel.off(ev);\n\t\t\t}\n\t\t\tthis._events = [];\n\t\t},\n\n\t\tshow: function(e) {\n\t\t\tthis.picker.show();\n\t\t\tthis.height = this.component ? this.component.outerHeight() : this.element.outerHeight();\n\t\t\tif (this.forceParse) {\n\t\t\t\tthis.update();\n\t\t\t}\n\t\t\tthis.place();\n\t\t\t$(window).on('resize', $.proxy(this.place, this));\n\t\t\tif (e) {\n\t\t\t\te.stopPropagation();\n\t\t\t\te.preventDefault();\n\t\t\t}\n\t\t\tthis.isVisible = true;\n\t\t\tthis.element.trigger({\n\t\t\t\ttype: 'show',\n\t\t\t\tdate: this.date\n\t\t\t});\n\t\t},\n\n\t\thide: function(e) {\n\t\t\tif (!this.isVisible) return;\n\t\t\tif (this.isInline) return;\n\t\t\tthis.picker.hide();\n\t\t\t$(window).off('resize', this.place);\n\t\t\tthis.viewMode = this.startViewMode;\n\t\t\tthis.showMode();\n\t\t\tif (!this.isInput) {\n\t\t\t\t$(document).off('mousedown', this.hide);\n\t\t\t}\n\t\t\tif (this.forceParse && (this.isInput && this.element.val() || this.hasInput && this.element.find('input').val())) this.setValue();\n\t\t\tthis.isVisible = false;\n\t\t\tthis.element.trigger({\n\t\t\t\ttype: 'hide',\n\t\t\t\tdate: this.date\n\t\t\t});\n\t\t},\n\n\t\tremove: function() {\n\t\t\tthis._detachEvents();\n\t\t\t$(document).off('mousedown', this.clickedOutside);\n\t\t\tthis.picker.remove();\n\t\t\tdelete this.picker;\n\t\t\tdelete this.element.data().datetimepicker;\n\t\t},\n\n\t\tgetDate: function() {\n\t\t\tvar d = this.getUTCDate();\n\t\t\treturn new Date(d.getTime() + (d.getTimezoneOffset() * 60000));\n\t\t},\n\n\t\tgetUTCDate: function() {\n\t\t\treturn this.date;\n\t\t},\n\n\t\tgetInitialDate: function() {\n\t\t\treturn this.initialDate\n\t\t},\n\n\t\tsetInitialDate: function(initialDate) {\n\t\t\tthis.initialDate = initialDate;\n\t\t},\n\n\t\tsetDate: function(d) {\n\t\t\tthis.setUTCDate(new Date(d.getTime() - (d.getTimezoneOffset() * 60000)));\n\t\t},\n\n\t\tsetUTCDate: function(d) {\n\t\t\tif (d >= this.startDate && d <= this.endDate) {\n\t\t\t\tthis.date = d;\n\t\t\t\tthis.setValue();\n\t\t\t\tthis.viewDate = this.date;\n\t\t\t\tthis.fill();\n\t\t\t} else {\n\t\t\t\tthis.element.trigger({\n\t\t\t\t\ttype: 'outOfRange',\n\t\t\t\t\tdate: d,\n\t\t\t\t\tstartDate: this.startDate,\n\t\t\t\t\tendDate: this.endDate\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\tsetFormat: function(format) {\n\t\t\tthis.format = DPGlobal.parseFormat(format, this.formatType);\n\t\t\tvar element;\n\t\t\tif (this.isInput) {\n\t\t\t\telement = this.element;\n\t\t\t} else if (this.component) {\n\t\t\t\telement = this.element.find('input');\n\t\t\t}\n\t\t\tif (element && element.val()) {\n\t\t\t\tthis.setValue();\n\t\t\t}\n\t\t},\n\n\t\tsetValue: function() {\n\t\t\tvar formatted = this.getFormattedDate();\n\t\t\tif (!this.isInput) {\n\t\t\t\tif (this.component) {\n\t\t\t\t\tthis.element.find('input').val(formatted);\n\t\t\t\t}\n\t\t\t\tthis.element.data('date', formatted);\n\t\t\t} else {\n\t\t\t\tthis.element.val(formatted);\n\t\t\t}\n\t\t\tif (this.linkField) {\n\t\t\t\t$('#' + this.linkField).val(this.getFormattedDate(this.linkFormat));\n\t\t\t}\n\t\t},\n\n\t\tgetFormattedDate: function(format) {\n\t\t\tif (format == undefined) format = this.format;\n\t\t\treturn DPGlobal.formatDate(this.date, format, this.language, this.formatType, this.timezone);\n\t\t},\n\n\t\tsetStartDate: function(startDate) {\n\t\t\tthis.startDate = startDate || -Infinity;\n\t\t\tif (this.startDate !== -Infinity) {\n\t\t\t\tthis.startDate = DPGlobal.parseDate(this.startDate, this.format, this.language, this.formatType, this.timezone);\n\t\t\t}\n\t\t\tthis.update();\n\t\t\tthis.updateNavArrows();\n\t\t},\n\n\t\tsetEndDate: function(endDate) {\n\t\t\tthis.endDate = endDate || Infinity;\n\t\t\tif (this.endDate !== Infinity) {\n\t\t\t\tthis.endDate = DPGlobal.parseDate(this.endDate, this.format, this.language, this.formatType, this.timezone);\n\t\t\t}\n\t\t\tthis.update();\n\t\t\tthis.updateNavArrows();\n\t\t},\n\n\t\tsetDatesDisabled: function(datesDisabled) {\n\t\t\tthis.datesDisabled = datesDisabled || [];\n\t\t\tif (!$.isArray(this.datesDisabled)) {\n\t\t\t\tthis.datesDisabled = this.datesDisabled.split(/,\\s*/);\n\t\t\t}\n\t\t\tthis.datesDisabled = $.map(this.datesDisabled,\n\t\t\tfunction(d) {\n\t\t\t\treturn DPGlobal.parseDate(d, this.format, this.language, this.formatType, this.timezone).toDateString();\n\t\t\t});\n\t\t\tthis.update();\n\t\t\tthis.updateNavArrows();\n\t\t},\n\n\t\tsetTitle: function(selector, value) {\n\t\t\treturn this.picker.find(selector).find('th:eq(1)').text(this.title === false ? value: this.title);\n\t\t},\n\n\t\tsetDaysOfWeekDisabled: function(daysOfWeekDisabled) {\n\t\t\tthis.daysOfWeekDisabled = daysOfWeekDisabled || [];\n\t\t\tif (!$.isArray(this.daysOfWeekDisabled)) {\n\t\t\t\tthis.daysOfWeekDisabled = this.daysOfWeekDisabled.split(/,\\s*/);\n\t\t\t}\n\t\t\tthis.daysOfWeekDisabled = $.map(this.daysOfWeekDisabled,\n\t\t\tfunction(d) {\n\t\t\t\treturn parseInt(d, 10);\n\t\t\t});\n\t\t\tthis.update();\n\t\t\tthis.updateNavArrows();\n\t\t},\n\n\t\tsetMinutesDisabled: function(minutesDisabled) {\n\t\t\tthis.minutesDisabled = minutesDisabled || [];\n\t\t\tif (!$.isArray(this.minutesDisabled)) {\n\t\t\t\tthis.minutesDisabled = this.minutesDisabled.split(/,\\s*/);\n\t\t\t}\n\t\t\tthis.minutesDisabled = $.map(this.minutesDisabled,\n\t\t\tfunction(d) {\n\t\t\t\treturn parseInt(d, 10);\n\t\t\t});\n\t\t\tthis.update();\n\t\t\tthis.updateNavArrows();\n\t\t},\n\n\t\tsetHoursDisabled: function(hoursDisabled) {\n\t\t\tthis.hoursDisabled = hoursDisabled || [];\n\t\t\tif (!$.isArray(this.hoursDisabled)) {\n\t\t\t\tthis.hoursDisabled = this.hoursDisabled.split(/,\\s*/);\n\t\t\t}\n\t\t\tthis.hoursDisabled = $.map(this.hoursDisabled,\n\t\t\tfunction(d) {\n\t\t\t\treturn parseInt(d, 10);\n\t\t\t});\n\t\t\tthis.update();\n\t\t\tthis.updateNavArrows();\n\t\t},\n\n\t\tplace: function() {\n\t\t\tif (this.isInline) return;\n\t\t\tif (!this.zIndex) {\n\t\t\t\tvar index_highest = 0;\n\t\t\t\t$('div').each(function() {\n\t\t\t\t\tvar index_current = parseInt($(this).css('zIndex'), 10);\n\t\t\t\t\tif (index_current > index_highest) {\n\t\t\t\t\t\tindex_highest = index_current;\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tthis.zIndex = index_highest + 10;\n\t\t\t}\n\n\t\t\tvar offset, top, left, containerOffset;\n\t\t\tif (this.container instanceof $) {\n\t\t\t\tcontainerOffset = this.container.offset();\n\t\t\t} else {\n\t\t\t\tcontainerOffset = $(this.container).offset();\n\t\t\t}\n\n\t\t\tif (this.component) {\n\t\t\t\toffset = this.component.offset();\n\t\t\t\tleft = offset.left;\n\t\t\t\tif (this.pickerPosition == 'bottom-left' || this.pickerPosition == 'top-left') {\n\t\t\t\t\tleft += this.component.outerWidth() - this.picker.outerWidth();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\toffset = this.element.offset();\n\t\t\t\tleft = offset.left;\n\t\t\t\tif (this.pickerPosition == 'bottom-left' || this.pickerPosition == 'top-left') {\n\t\t\t\t\tleft += this.element.outerWidth() - this.picker.outerWidth();\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar bodyWidth = document.body.clientWidth || window.innerWidth;\n\t\t\tif (left + 220 > bodyWidth) {\n\t\t\t\tleft = bodyWidth - 220;\n\t\t\t}\n\n\t\t\tif (this.pickerPosition == 'top-left' || this.pickerPosition == 'top-right') {\n\t\t\t\ttop = offset.top - this.picker.outerHeight();\n\t\t\t} else {\n\t\t\t\ttop = offset.top + this.height;\n\t\t\t}\n\n\t\t\ttop = top - containerOffset.top;\n\t\t\tleft = left - containerOffset.left;\n\n\t\t\tthis.picker.css({\n\t\t\t\ttop: top,\n\t\t\t\tleft: left,\n\t\t\t\tzIndex: this.zIndex\n\t\t\t});\n\t\t},\n\n\t\tupdate: function() {\n\t\t\tvar date, fromArgs = false;\n\t\t\tif (arguments && arguments.length && (typeof arguments[0] === 'string' || arguments[0] instanceof Date)) {\n\t\t\t\tdate = arguments[0];\n\t\t\t\tfromArgs = true;\n\t\t\t} else {\n\t\t\t\tdate = (this.isInput ? this.element.val() : this.element.find('input').val()) || this.element.data('date') || this.initialDate;\n\t\t\t\tif (typeof date == 'string' || date instanceof String) {\n\t\t\t\t\tdate = date.replace(/^\\s+|\\s+$/g, '');\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!date) {\n\t\t\t\tdate = new Date();\n\t\t\t\tfromArgs = false;\n\t\t\t}\n\n\t\t\tthis.date = DPGlobal.parseDate(date, this.format, this.language, this.formatType, this.timezone);\n\n\t\t\tif (fromArgs) this.setValue();\n\n\t\t\tif (this.date < this.startDate) {\n\t\t\t\tthis.viewDate = new Date(this.startDate);\n\t\t\t} else if (this.date > this.endDate) {\n\t\t\t\tthis.viewDate = new Date(this.endDate);\n\t\t\t} else {\n\t\t\t\tthis.viewDate = new Date(this.date);\n\t\t\t}\n\t\t\tthis.fill();\n\t\t},\n\n\t\tfillDow: function() {\n\t\t\tvar dowCnt = this.weekStart,\n\t\t\thtml = '<tr>';\n\t\t\twhile (dowCnt < this.weekStart + 7) {\n\t\t\t\thtml += '<th class=\"dow\">' + dates[this.language].daysMin[(dowCnt++) % 7] + '</th>';\n\t\t\t}\n\t\t\thtml += '</tr>';\n\t\t\tthis.picker.find('.datetimepicker-days thead').append(html);\n\t\t},\n\n\t\tfillMonths: function() {\n\t\t\tvar html = '',\n\t\t\ti = 0;\n\t\t\twhile (i < 12) {\n\t\t\t\thtml += '<span class=\"month\">' + dates[this.language].monthsShort[i++] + '</span>';\n\t\t\t}\n\t\t\tthis.picker.find('.datetimepicker-months td').html(html);\n\t\t},\n\n\t\tfill: function() {\n\t\t\tif (this.date == null || this.viewDate == null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar d = new Date(this.viewDate),\n\t\t\tyear = d.getUTCFullYear(),\n\t\t\tmonth = d.getUTCMonth(),\n\t\t\tdayMonth = d.getUTCDate(),\n\t\t\thours = d.getUTCHours(),\n\t\t\tminutes = d.getUTCMinutes(),\n\t\t\tstartYear = this.startDate !== -Infinity ? this.startDate.getUTCFullYear() : -Infinity,\n\t\t\tstartMonth = this.startDate !== -Infinity ? this.startDate.getUTCMonth() : -Infinity,\n\t\t\tendYear = this.endDate !== Infinity ? this.endDate.getUTCFullYear() : Infinity,\n\t\t\tendMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() + 1 : Infinity,\n\t\t\tcurrentDate = (new UTCDate(this.date.getUTCFullYear(), this.date.getUTCMonth(), this.date.getUTCDate())).valueOf(),\n\t\t\ttoday = new Date();\n\t\t\tthis.setTitle('.datetimepicker-days', dates[this.language].months[month] + ' ' + year);\n\t\t\tif (this.formatViewType == 'time') {\n\t\t\t\tvar formatted = this.getFormattedDate();\n\t\t\t\tthis.setTitle('.datetimepicker-hours', formatted);\n\t\t\t\tthis.setTitle('.datetimepicker-minutes', formatted);\n\t\t\t} else {\n\t\t\t\tthis.setTitle('.datetimepicker-hours', dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);\n\t\t\t\tthis.setTitle('.datetimepicker-minutes', dayMonth + ' ' + dates[this.language].months[month] + ' ' + year);\n\t\t\t}\n\t\t\tthis.picker.find('tfoot th.today').text(dates[this.language].today || dates['en'].today).toggle(this.todayBtn !== false);\n\t\t\tthis.picker.find('tfoot th.clear').text(dates[this.language].clear || dates['en'].clear).toggle(this.clearBtn !== false);\n\t\t\tthis.updateNavArrows();\n\t\t\tthis.fillMonths();\n\t\t\t/*var prevMonth = UTCDate(year, month, 0,0,0,0,0);\n\t\tprevMonth.setUTCDate(prevMonth.getDate() - (prevMonth.getUTCDay() - this.weekStart + 7)%7);*/\n\t\t\tvar prevMonth = UTCDate(year, month - 1, 28, 0, 0, 0, 0),\n\t\t\tday = DPGlobal.getDaysInMonth(prevMonth.getUTCFullYear(), prevMonth.getUTCMonth());\n\t\t\tprevMonth.setUTCDate(day);\n\t\t\tprevMonth.setUTCDate(day - (prevMonth.getUTCDay() - this.weekStart + 7) % 7);\n\t\t\tvar nextMonth = new Date(prevMonth);\n\t\t\tnextMonth.setUTCDate(nextMonth.getUTCDate() + 42);\n\t\t\tnextMonth = nextMonth.valueOf();\n\t\t\tvar html = [];\n\t\t\tvar clsName;\n\t\t\twhile (prevMonth.valueOf() < nextMonth) {\n\t\t\t\tif (prevMonth.getUTCDay() == this.weekStart) {\n\t\t\t\t\thtml.push('<tr>');\n\t\t\t\t}\n\t\t\t\tclsName = '';\n\t\t\t\tif (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {\n\t\t\t\t\tclsName += ' old';\n\t\t\t\t} else if (prevMonth.getUTCFullYear() > year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() > month)) {\n\t\t\t\t\tclsName += ' new';\n\t\t\t\t}\n\t\t\t\t// Compare internal UTC date with local today, not UTC today\n\t\t\t\tif (this.todayHighlight && prevMonth.getUTCFullYear() == today.getFullYear() && prevMonth.getUTCMonth() == today.getMonth() && prevMonth.getUTCDate() == today.getDate()) {\n\t\t\t\t\tclsName += ' today';\n\t\t\t\t}\n\t\t\t\tif (prevMonth.valueOf() == currentDate) {\n\t\t\t\t\tclsName += ' active';\n\t\t\t\t}\n\t\t\t\tif ((prevMonth.valueOf() + 86400000) <= this.startDate || prevMonth.valueOf() > this.endDate || $.inArray(prevMonth.getUTCDay(), this.daysOfWeekDisabled) !== -1 || $.inArray(prevMonth.toDateString(), this.datesDisabled) !== -1) {\n\t\t\t\t\tclsName += ' disabled';\n\t\t\t\t}\n\t\t\t\thtml.push('<td class=\"day' + clsName + '\">' + prevMonth.getUTCDate() + '</td>');\n\t\t\t\tif (prevMonth.getUTCDay() == this.weekEnd) {\n\t\t\t\t\thtml.push('</tr>');\n\t\t\t\t}\n\t\t\t\tprevMonth.setUTCDate(prevMonth.getUTCDate() + 1);\n\t\t\t}\n\t\t\tthis.picker.find('.datetimepicker-days tbody').empty().append(html.join(''));\n\n\t\t\thtml = [];\n\t\t\tvar txt = '',\n\t\t\tmeridian = '',\n\t\t\tmeridianOld = '';\n\t\t\tvar hoursDisabled = this.hoursDisabled || [];\n\t\t\tfor (var i = 0; i < 24; i++) {\n\t\t\t\tif (hoursDisabled.indexOf(i) !== -1) continue;\n\t\t\t\tvar actual = UTCDate(year, month, dayMonth, i);\n\t\t\t\tclsName = '';\n\t\t\t\t// We want the previous hour for the startDate\n\t\t\t\tif ((actual.valueOf() + 3600000) <= this.startDate || actual.valueOf() > this.endDate) {\n\t\t\t\t\tclsName += ' disabled';\n\t\t\t\t} else if (hours == i) {\n\t\t\t\t\tclsName += ' active';\n\t\t\t\t}\n\t\t\t\tif (this.showMeridian && dates[this.language].meridiem.length == 2) {\n\t\t\t\t\tmeridian = (i < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]);\n\t\t\t\t\tif (meridian != meridianOld) {\n\t\t\t\t\t\tif (meridianOld != '') {\n\t\t\t\t\t\t\thtml.push('</fieldset>');\n\t\t\t\t\t\t}\n\t\t\t\t\t\thtml.push('<fieldset class=\"hour\"><legend>' + meridian.toUpperCase() + '</legend>');\n\t\t\t\t\t}\n\t\t\t\t\tmeridianOld = meridian;\n\t\t\t\t\ttxt = (i % 12 ? i % 12 : 12);\n\t\t\t\t\thtml.push('<span class=\"hour' + clsName + ' hour_' + (i < 12 ? 'am': 'pm') + '\">' + txt + '</span>');\n\t\t\t\t\tif (i == 23) {\n\t\t\t\t\t\thtml.push('</fieldset>');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttxt = i + ':00';\n\t\t\t\t\thtml.push('<span class=\"hour' + clsName + '\">' + txt + '</span>');\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.picker.find('.datetimepicker-hours td').html(html.join(''));\n\n\t\t\thtml = [];\n\t\t\ttxt = '',\n\t\t\tmeridian = '',\n\t\t\tmeridianOld = '';\n\t\t\tvar minutesDisabled = this.minutesDisabled || [];\n\t\t\tfor (var i = 0; i < 60; i += this.minuteStep) {\n\t\t\t\tif (minutesDisabled.indexOf(i) !== -1) continue;\n\t\t\t\tvar actual = UTCDate(year, month, dayMonth, hours, i, 0);\n\t\t\t\tclsName = '';\n\t\t\t\tif (actual.valueOf() < this.startDate || actual.valueOf() > this.endDate) {\n\t\t\t\t\tclsName += ' disabled';\n\t\t\t\t} else if (Math.floor(minutes / this.minuteStep) == Math.floor(i / this.minuteStep)) {\n\t\t\t\t\tclsName += ' active';\n\t\t\t\t}\n\t\t\t\tif (this.showMeridian && dates[this.language].meridiem.length == 2) {\n\t\t\t\t\tmeridian = (hours < 12 ? dates[this.language].meridiem[0] : dates[this.language].meridiem[1]);\n\t\t\t\t\tif (meridian != meridianOld) {\n\t\t\t\t\t\tif (meridianOld != '') {\n\t\t\t\t\t\t\thtml.push('</fieldset>');\n\t\t\t\t\t\t}\n\t\t\t\t\t\thtml.push('<fieldset class=\"minute\"><legend>' + meridian.toUpperCase() + '</legend>');\n\t\t\t\t\t}\n\t\t\t\t\tmeridianOld = meridian;\n\t\t\t\t\ttxt = (hours % 12 ? hours % 12 : 12);\n\t\t\t\t\t//html.push('<span class=\"minute'+clsName+' minute_'+(hours<12?'am':'pm')+'\">'+txt+'</span>');\n\t\t\t\t\thtml.push('<span class=\"minute' + clsName + '\">' + txt + ':' + (i < 10 ? '0' + i: i) + '</span>');\n\t\t\t\t\tif (i == 59) {\n\t\t\t\t\t\thtml.push('</fieldset>');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttxt = i + ':00';\n\t\t\t\t\t//html.push('<span class=\"hour'+clsName+'\">'+txt+'</span>');\n\t\t\t\t\thtml.push('<span class=\"minute' + clsName + '\">' + hours + ':' + (i < 10 ? '0' + i: i) + '</span>');\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.picker.find('.datetimepicker-minutes td').html(html.join(''));\n\n\t\t\tvar currentYear = this.date.getUTCFullYear();\n\t\t\tvar months = this.setTitle('.datetimepicker-months', year).end().find('span').removeClass('active');\n\t\t\tif (currentYear == year) {\n\t\t\t\t// getUTCMonths() returns 0 based, and we need to select the next one\n\t\t\t\t// To cater bootstrap 2 we don't need to select the next one\n\t\t\t\tvar offset = months.length - 12;\n\t\t\t\tmonths.eq(this.date.getUTCMonth() + offset).addClass('active');\n\t\t\t}\n\t\t\tif (year < startYear || year > endYear) {\n\t\t\t\tmonths.addClass('disabled');\n\t\t\t}\n\t\t\tif (year == startYear) {\n\t\t\t\tmonths.slice(0, startMonth).addClass('disabled');\n\t\t\t}\n\t\t\tif (year == endYear) {\n\t\t\t\tmonths.slice(endMonth).addClass('disabled');\n\t\t\t}\n\n\t\t\thtml = '';\n\t\t\tyear = parseInt(year / 10, 10) * 10;\n\t\t\tvar yearCont = this.setTitle('.datetimepicker-years', year + '-' + (year + 9)).end().find('td');\n\t\t\tyear -= 1;\n\t\t\tfor (var i = -1; i < 11; i++) {\n\t\t\t\thtml += '<span class=\"year' + (i == -1 || i == 10 ? ' old': '') + (currentYear == year ? ' active': '') + (year < startYear || year > endYear ? ' disabled': '') + '\">' + year + '</span>';\n\t\t\t\tyear += 1;\n\t\t\t}\n\t\t\tyearCont.html(html);\n\t\t\tthis.place();\n\t\t},\n\n\t\tupdateNavArrows: function() {\n\t\t\tvar d = new Date(this.viewDate),\n\t\t\tyear = d.getUTCFullYear(),\n\t\t\tmonth = d.getUTCMonth(),\n\t\t\tday = d.getUTCDate(),\n\t\t\thour = d.getUTCHours();\n\t\t\tswitch (this.viewMode) {\n\t\t\tcase 0:\n\t\t\t\tif (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth() && day <= this.startDate.getUTCDate() && hour <= this.startDate.getUTCHours()) {\n\t\t\t\t\tthis.picker.find('.prev').css({\n\t\t\t\t\t\tvisibility: 'hidden'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthis.picker.find('.prev').css({\n\t\t\t\t\t\tvisibility: 'visible'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth() && day >= this.endDate.getUTCDate() && hour >= this.endDate.getUTCHours()) {\n\t\t\t\t\tthis.picker.find('.next').css({\n\t\t\t\t\t\tvisibility: 'hidden'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthis.picker.find('.next').css({\n\t\t\t\t\t\tvisibility: 'visible'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\t\tif (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth() && day <= this.startDate.getUTCDate()) {\n\t\t\t\t\tthis.picker.find('.prev').css({\n\t\t\t\t\t\tvisibility: 'hidden'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthis.picker.find('.prev').css({\n\t\t\t\t\t\tvisibility: 'visible'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth() && day >= this.endDate.getUTCDate()) {\n\t\t\t\t\tthis.picker.find('.next').css({\n\t\t\t\t\t\tvisibility: 'hidden'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthis.picker.find('.next').css({\n\t\t\t\t\t\tvisibility: 'visible'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\tif (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear() && month <= this.startDate.getUTCMonth()) {\n\t\t\t\t\tthis.picker.find('.prev').css({\n\t\t\t\t\t\tvisibility: 'hidden'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthis.picker.find('.prev').css({\n\t\t\t\t\t\tvisibility: 'visible'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear() && month >= this.endDate.getUTCMonth()) {\n\t\t\t\t\tthis.picker.find('.next').css({\n\t\t\t\t\t\tvisibility: 'hidden'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthis.picker.find('.next').css({\n\t\t\t\t\t\tvisibility: 'visible'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\tcase 4:\n\t\t\t\tif (this.startDate !== -Infinity && year <= this.startDate.getUTCFullYear()) {\n\t\t\t\t\tthis.picker.find('.prev').css({\n\t\t\t\t\t\tvisibility: 'hidden'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthis.picker.find('.prev').css({\n\t\t\t\t\t\tvisibility: 'visible'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tif (this.endDate !== Infinity && year >= this.endDate.getUTCFullYear()) {\n\t\t\t\t\tthis.picker.find('.next').css({\n\t\t\t\t\t\tvisibility: 'hidden'\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tthis.picker.find('.next').css({\n\t\t\t\t\t\tvisibility: 'visible'\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\t\tmousewheel: function(e) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t\tif (this.wheelPause) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.wheelPause = true;\n\t\t\tvar originalEvent = e.originalEvent;\n\t\t\tvar delta = originalEvent.wheelDelta;\n\t\t\tvar mode = delta > 0 ? 1 : (delta === 0) ? 0 : -1;\n\t\t\tif (this.wheelViewModeNavigationInverseDirection) {\n\t\t\t\tmode = -mode;\n\t\t\t}\n\n\t\t\tthis.showMode(mode);\n\t\t\tsetTimeout($.proxy(function() {\n\t\t\t\tthis.wheelPause = false\n\t\t\t},\n\t\t\tthis), this.wheelViewModeNavigationDelay);\n\t\t},\n\n\t\tclick: function(e) {\n\t\t\te.stopPropagation();\n\t\t\te.preventDefault();\n\t\t\tvar target = $(e.target).closest('span, td, th, legend');\n\t\t\tif (target.is('.' + this.icontype)) {\n\t\t\t\ttarget = $(target).parent().closest('span, td, th, legend');\n\t\t\t}\n\t\t\tif (target.length == 1) {\n\t\t\t\tif (target.is('.disabled')) {\n\t\t\t\t\tthis.element.trigger({\n\t\t\t\t\t\ttype: 'outOfRange',\n\t\t\t\t\t\tdate: this.viewDate,\n\t\t\t\t\t\tstartDate: this.startDate,\n\t\t\t\t\t\tendDate: this.endDate\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tswitch (target[0].nodeName.toLowerCase()) {\n\t\t\t\tcase 'th':\n\t\t\t\t\tswitch (target[0].className) {\n\t\t\t\t\tcase 'switch':\n\t\t\t\t\t\tthis.showMode(1);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'prev':\n\t\t\t\t\tcase 'next':\n\t\t\t\t\t\tvar dir = DPGlobal.modes[this.viewMode].navStep * (target[0].className == 'prev' ? -1 : 1);\n\t\t\t\t\t\tswitch (this.viewMode) {\n\t\t\t\t\t\tcase 0:\n\t\t\t\t\t\t\tthis.viewDate = this.moveHour(this.viewDate, dir);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 1:\n\t\t\t\t\t\t\tthis.viewDate = this.moveDate(this.viewDate, dir);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 2:\n\t\t\t\t\t\t\tthis.viewDate = this.moveMonth(this.viewDate, dir);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 3:\n\t\t\t\t\t\tcase 4:\n\t\t\t\t\t\t\tthis.viewDate = this.moveYear(this.viewDate, dir);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.fill();\n\t\t\t\t\t\tthis.element.trigger({\n\t\t\t\t\t\t\ttype: target[0].className + ':' + this.convertViewModeText(this.viewMode),\n\t\t\t\t\t\t\tdate: this.viewDate,\n\t\t\t\t\t\t\tstartDate: this.startDate,\n\t\t\t\t\t\t\tendDate: this.endDate\n\t\t\t\t\t\t});\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'clear':\n\t\t\t\t\t\tthis.reset();\n\t\t\t\t\t\tif (this.autoclose) {\n\t\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'today':\n\t\t\t\t\t\tvar date = new Date();\n\t\t\t\t\t\tdate = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), 0);\n\n\t\t\t\t\t\t// Respect startDate and endDate.\n\t\t\t\t\t\tif (date < this.startDate) date = this.startDate;\n\t\t\t\t\t\telse if (date > this.endDate) date = this.endDate;\n\n\t\t\t\t\t\tthis.viewMode = this.startViewMode;\n\t\t\t\t\t\tthis.showMode(0);\n\t\t\t\t\t\tthis._setDate(date);\n\t\t\t\t\t\tthis.fill();\n\t\t\t\t\t\tif (this.autoclose) {\n\t\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'span':\n\t\t\t\t\tif (!target.is('.disabled')) {\n\t\t\t\t\t\tvar year = this.viewDate.getUTCFullYear(),\n\t\t\t\t\t\tmonth = this.viewDate.getUTCMonth(),\n\t\t\t\t\t\tday = this.viewDate.getUTCDate(),\n\t\t\t\t\t\thours = this.viewDate.getUTCHours(),\n\t\t\t\t\t\tminutes = this.viewDate.getUTCMinutes(),\n\t\t\t\t\t\tseconds = this.viewDate.getUTCSeconds();\n\n\t\t\t\t\t\tif (target.is('.month')) {\n\t\t\t\t\t\t\tthis.viewDate.setUTCDate(1);\n\t\t\t\t\t\t\tmonth = target.parent().find('span').index(target);\n\t\t\t\t\t\t\tday = this.viewDate.getUTCDate();\n\t\t\t\t\t\t\tthis.viewDate.setUTCMonth(month);\n\t\t\t\t\t\t\tthis.element.trigger({\n\t\t\t\t\t\t\t\ttype: 'changeMonth',\n\t\t\t\t\t\t\t\tdate: this.viewDate\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (this.viewSelect >= 3) {\n\t\t\t\t\t\t\t\tthis._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (target.is('.year')) {\n\t\t\t\t\t\t\tthis.viewDate.setUTCDate(1);\n\t\t\t\t\t\t\tyear = parseInt(target.text(), 10) || 0;\n\t\t\t\t\t\t\tthis.viewDate.setUTCFullYear(year);\n\t\t\t\t\t\t\tthis.element.trigger({\n\t\t\t\t\t\t\t\ttype: 'changeYear',\n\t\t\t\t\t\t\t\tdate: this.viewDate\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (this.viewSelect >= 4) {\n\t\t\t\t\t\t\t\tthis._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (target.is('.hour')) {\n\t\t\t\t\t\t\thours = parseInt(target.text(), 10) || 0;\n\t\t\t\t\t\t\tif (target.hasClass('hour_am') || target.hasClass('hour_pm')) {\n\t\t\t\t\t\t\t\tif (hours == 12 && target.hasClass('hour_am')) {\n\t\t\t\t\t\t\t\t\thours = 0;\n\t\t\t\t\t\t\t\t} else if (hours != 12 && target.hasClass('hour_pm')) {\n\t\t\t\t\t\t\t\t\thours += 12;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis.viewDate.setUTCHours(hours);\n\t\t\t\t\t\t\tthis.element.trigger({\n\t\t\t\t\t\t\t\ttype: 'changeHour',\n\t\t\t\t\t\t\t\tdate: this.viewDate\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (this.viewSelect >= 1) {\n\t\t\t\t\t\t\t\tthis._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (target.is('.minute')) {\n\t\t\t\t\t\t\tminutes = parseInt(target.text().substr(target.text().indexOf(':') + 1), 10) || 0;\n\t\t\t\t\t\t\tthis.viewDate.setUTCMinutes(minutes);\n\t\t\t\t\t\t\tthis.element.trigger({\n\t\t\t\t\t\t\t\ttype: 'changeMinute',\n\t\t\t\t\t\t\t\tdate: this.viewDate\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (this.viewSelect >= 0) {\n\t\t\t\t\t\t\t\tthis._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (this.viewMode != 0) {\n\t\t\t\t\t\t\tvar oldViewMode = this.viewMode;\n\t\t\t\t\t\t\tthis.showMode( - 1);\n\t\t\t\t\t\t\tthis.fill();\n\t\t\t\t\t\t\tif (oldViewMode == this.viewMode && this.autoclose) {\n\t\t\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tthis.fill();\n\t\t\t\t\t\t\tif (this.autoclose) {\n\t\t\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'td':\n\t\t\t\t\tif (target.is('.day') && !target.is('.disabled')) {\n\t\t\t\t\t\tvar day = parseInt(target.text(), 10) || 1;\n\t\t\t\t\t\tvar year = this.viewDate.getUTCFullYear(),\n\t\t\t\t\t\tmonth = this.viewDate.getUTCMonth(),\n\t\t\t\t\t\thours = this.viewDate.getUTCHours(),\n\t\t\t\t\t\tminutes = this.viewDate.getUTCMinutes(),\n\t\t\t\t\t\tseconds = this.viewDate.getUTCSeconds();\n\t\t\t\t\t\tif (target.is('.old')) {\n\t\t\t\t\t\t\tif (month === 0) {\n\t\t\t\t\t\t\t\tmonth = 11;\n\t\t\t\t\t\t\t\tyear -= 1;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tmonth -= 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (target.is('.new')) {\n\t\t\t\t\t\t\tif (month == 11) {\n\t\t\t\t\t\t\t\tmonth = 0;\n\t\t\t\t\t\t\t\tyear += 1;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tmonth += 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.viewDate.setUTCFullYear(year);\n\t\t\t\t\t\tthis.viewDate.setUTCMonth(month, day);\n\t\t\t\t\t\tthis.element.trigger({\n\t\t\t\t\t\t\ttype: 'changeDay',\n\t\t\t\t\t\t\tdate: this.viewDate\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (this.viewSelect >= 2) {\n\t\t\t\t\t\t\tthis._setDate(UTCDate(year, month, day, hours, minutes, seconds, 0));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvar oldViewMode = this.viewMode;\n\t\t\t\t\tthis.showMode( - 1);\n\t\t\t\t\tthis.fill();\n\t\t\t\t\tif (oldViewMode == this.viewMode && this.autoclose) {\n\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_setDate: function(date, which) {\n\t\t\tif (!which || which == 'date') this.date = date;\n\t\t\tif (!which || which == 'view') this.viewDate = date;\n\t\t\tthis.fill();\n\t\t\tthis.setValue();\n\t\t\tvar element;\n\t\t\tif (this.isInput) {\n\t\t\t\telement = this.element;\n\t\t\t} else if (this.component) {\n\t\t\t\telement = this.element.find('input');\n\t\t\t}\n\t\t\tif (element) {\n\t\t\t\telement.change();\n\t\t\t\tif (this.autoclose && (!which || which == 'date')) {\n\t\t\t\t\t//this.hide();\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.element.trigger({\n\t\t\t\ttype: 'changeDate',\n\t\t\t\tdate: this.getDate()\n\t\t\t});\n\t\t\tif (date == null) this.date = this.viewDate;\n\t\t},\n\n\t\tmoveMinute: function(date, dir) {\n\t\t\tif (!dir) return date;\n\t\t\tvar new_date = new Date(date.valueOf());\n\t\t\t//dir = dir > 0 ? 1 : -1;\n\t\t\tnew_date.setUTCMinutes(new_date.getUTCMinutes() + (dir * this.minuteStep));\n\t\t\treturn new_date;\n\t\t},\n\n\t\tmoveHour: function(date, dir) {\n\t\t\tif (!dir) return date;\n\t\t\tvar new_date = new Date(date.valueOf());\n\t\t\t//dir = dir > 0 ? 1 : -1;\n\t\t\tnew_date.setUTCHours(new_date.getUTCHours() + dir);\n\t\t\treturn new_date;\n\t\t},\n\n\t\tmoveDate: function(date, dir) {\n\t\t\tif (!dir) return date;\n\t\t\tvar new_date = new Date(date.valueOf());\n\t\t\t//dir = dir > 0 ? 1 : -1;\n\t\t\tnew_date.setUTCDate(new_date.getUTCDate() + dir);\n\t\t\treturn new_date;\n\t\t},\n\n\t\tmoveMonth: function(date, dir) {\n\t\t\tif (!dir) return date;\n\t\t\tvar new_date = new Date(date.valueOf()),\n\t\t\tday = new_date.getUTCDate(),\n\t\t\tmonth = new_date.getUTCMonth(),\n\t\t\tmag = Math.abs(dir),\n\t\t\tnew_month,\n\t\t\ttest;\n\t\t\tdir = dir > 0 ? 1 : -1;\n\t\t\tif (mag == 1) {\n\t\t\t\ttest = dir == -1\n\t\t\t\t// If going back one month, make sure month is not current month\n\t\t\t\t// (eg, Mar 31 -> Feb 31 == Feb 28, not Mar 02)\n\t\t\t\t?\n\t\t\t\tfunction() {\n\t\t\t\t\treturn new_date.getUTCMonth() == month;\n\t\t\t\t}\n\t\t\t\t// If going forward one month, make sure month is as expected\n\t\t\t\t// (eg, Jan 31 -> Feb 31 == Feb 28, not Mar 02)\n\t\t\t\t: function() {\n\t\t\t\t\treturn new_date.getUTCMonth() != new_month;\n\t\t\t\t};\n\t\t\t\tnew_month = month + dir;\n\t\t\t\tnew_date.setUTCMonth(new_month);\n\t\t\t\t// Dec -> Jan (12) or Jan -> Dec (-1) -- limit expected date to 0-11\n\t\t\t\tif (new_month < 0 || new_month > 11) new_month = (new_month + 12) % 12;\n\t\t\t} else {\n\t\t\t\t// For magnitudes >1, move one month at a time...\n\t\t\t\tfor (var i = 0; i < mag; i++)\n\t\t\t\t// ...which might decrease the day (eg, Jan 31 to Feb 28, etc)...\n\t\t\t\tnew_date = this.moveMonth(new_date, dir);\n\t\t\t\t// ...then reset the day, keeping it in the new month\n\t\t\t\tnew_month = new_date.getUTCMonth();\n\t\t\t\tnew_date.setUTCDate(day);\n\t\t\t\ttest = function() {\n\t\t\t\t\treturn new_month != new_date.getUTCMonth();\n\t\t\t\t};\n\t\t\t}\n\t\t\t// Common date-resetting loop -- if date is beyond end of month, make it\n\t\t\t// end of month\n\t\t\twhile (test()) {\n\t\t\t\tnew_date.setUTCDate(--day);\n\t\t\t\tnew_date.setUTCMonth(new_month);\n\t\t\t}\n\t\t\treturn new_date;\n\t\t},\n\n\t\tmoveYear: function(date, dir) {\n\t\t\treturn this.moveMonth(date, dir * 12);\n\t\t},\n\n\t\tdateWithinRange: function(date) {\n\t\t\treturn date >= this.startDate && date <= this.endDate;\n\t\t},\n\n\t\tkeydown: function(e) {\n\t\t\tif (this.picker.is(':not(:visible)')) {\n\t\t\t\tif (e.keyCode == 27) // allow escape to hide and re-show picker\n\t\t\t\tthis.show();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tvar dateChanged = false,\n\t\t\tdir, day, month, newDate, newViewDate;\n\t\t\tswitch (e.keyCode) {\n\t\t\tcase 27:\n\t\t\t\t// escape\n\t\t\t\tthis.hide();\n\t\t\t\te.preventDefault();\n\t\t\t\tbreak;\n\t\t\tcase 37:\n\t\t\t\t// left\n\t\t\tcase 39:\n\t\t\t\t// right\n\t\t\t\tif (!this.keyboardNavigation) break;\n\t\t\t\tdir = e.keyCode == 37 ? -1 : 1;\n\t\t\t\tviewMode = this.viewMode;\n\t\t\t\tif (e.ctrlKey) {\n\t\t\t\t\tviewMode += 2;\n\t\t\t\t} else if (e.shiftKey) {\n\t\t\t\t\tviewMode += 1;\n\t\t\t\t}\n\t\t\t\tif (viewMode == 4) {\n\t\t\t\t\tnewDate = this.moveYear(this.date, dir);\n\t\t\t\t\tnewViewDate = this.moveYear(this.viewDate, dir);\n\t\t\t\t} else if (viewMode == 3) {\n\t\t\t\t\tnewDate = this.moveMonth(this.date, dir);\n\t\t\t\t\tnewViewDate = this.moveMonth(this.viewDate, dir);\n\t\t\t\t} else if (viewMode == 2) {\n\t\t\t\t\tnewDate = this.moveDate(this.date, dir);\n\t\t\t\t\tnewViewDate = this.moveDate(this.viewDate, dir);\n\t\t\t\t} else if (viewMode == 1) {\n\t\t\t\t\tnewDate = this.moveHour(this.date, dir);\n\t\t\t\t\tnewViewDate = this.moveHour(this.viewDate, dir);\n\t\t\t\t} else if (viewMode == 0) {\n\t\t\t\t\tnewDate = this.moveMinute(this.date, dir);\n\t\t\t\t\tnewViewDate = this.moveMinute(this.viewDate, dir);\n\t\t\t\t}\n\t\t\t\tif (this.dateWithinRange(newDate)) {\n\t\t\t\t\tthis.date = newDate;\n\t\t\t\t\tthis.viewDate = newViewDate;\n\t\t\t\t\tthis.setValue();\n\t\t\t\t\tthis.update();\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tdateChanged = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 38:\n\t\t\t\t// up\n\t\t\tcase 40:\n\t\t\t\t// down\n\t\t\t\tif (!this.keyboardNavigation) break;\n\t\t\t\tdir = e.keyCode == 38 ? -1 : 1;\n\t\t\t\tviewMode = this.viewMode;\n\t\t\t\tif (e.ctrlKey) {\n\t\t\t\t\tviewMode += 2;\n\t\t\t\t} else if (e.shiftKey) {\n\t\t\t\t\tviewMode += 1;\n\t\t\t\t}\n\t\t\t\tif (viewMode == 4) {\n\t\t\t\t\tnewDate = this.moveYear(this.date, dir);\n\t\t\t\t\tnewViewDate = this.moveYear(this.viewDate, dir);\n\t\t\t\t} else if (viewMode == 3) {\n\t\t\t\t\tnewDate = this.moveMonth(this.date, dir);\n\t\t\t\t\tnewViewDate = this.moveMonth(this.viewDate, dir);\n\t\t\t\t} else if (viewMode == 2) {\n\t\t\t\t\tnewDate = this.moveDate(this.date, dir * 7);\n\t\t\t\t\tnewViewDate = this.moveDate(this.viewDate, dir * 7);\n\t\t\t\t} else if (viewMode == 1) {\n\t\t\t\t\tif (this.showMeridian) {\n\t\t\t\t\t\tnewDate = this.moveHour(this.date, dir * 6);\n\t\t\t\t\t\tnewViewDate = this.moveHour(this.viewDate, dir * 6);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tnewDate = this.moveHour(this.date, dir * 4);\n\t\t\t\t\t\tnewViewDate = this.moveHour(this.viewDate, dir * 4);\n\t\t\t\t\t}\n\t\t\t\t} else if (viewMode == 0) {\n\t\t\t\t\tnewDate = this.moveMinute(this.date, dir * 4);\n\t\t\t\t\tnewViewDate = this.moveMinute(this.viewDate, dir * 4);\n\t\t\t\t}\n\t\t\t\tif (this.dateWithinRange(newDate)) {\n\t\t\t\t\tthis.date = newDate;\n\t\t\t\t\tthis.viewDate = newViewDate;\n\t\t\t\t\tthis.setValue();\n\t\t\t\t\tthis.update();\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tdateChanged = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase 13:\n\t\t\t\t// enter\n\t\t\t\tif (this.viewMode != 0) {\n\t\t\t\t\tvar oldViewMode = this.viewMode;\n\t\t\t\t\tthis.showMode( - 1);\n\t\t\t\t\tthis.fill();\n\t\t\t\t\tif (oldViewMode == this.viewMode && this.autoclose) {\n\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.fill();\n\t\t\t\t\tif (this.autoclose) {\n\t\t\t\t\t\tthis.hide();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\te.preventDefault();\n\t\t\t\tbreak;\n\t\t\tcase 9:\n\t\t\t\t// tab\n\t\t\t\tthis.hide();\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (dateChanged) {\n\t\t\t\tvar element;\n\t\t\t\tif (this.isInput) {\n\t\t\t\t\telement = this.element;\n\t\t\t\t} else if (this.component) {\n\t\t\t\t\telement = this.element.find('input');\n\t\t\t\t}\n\t\t\t\tif (element) {\n\t\t\t\t\telement.change();\n\t\t\t\t}\n\t\t\t\tthis.element.trigger({\n\t\t\t\t\ttype: 'changeDate',\n\t\t\t\t\tdate: this.getDate()\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\n\t\tshowMode: function(dir) {\n\t\t\tif (dir) {\n\t\t\t\tvar newViewMode = Math.max(0, Math.min(DPGlobal.modes.length - 1, this.viewMode + dir));\n\t\t\t\tif (newViewMode >= this.minView && newViewMode <= this.maxView) {\n\t\t\t\t\tthis.element.trigger({\n\t\t\t\t\t\ttype: 'changeMode',\n\t\t\t\t\t\tdate: this.viewDate,\n\t\t\t\t\t\toldViewMode: this.viewMode,\n\t\t\t\t\t\tnewViewMode: newViewMode\n\t\t\t\t\t});\n\t\t\t\t\tthis.viewMode = newViewMode;\n\t\t\t\t}\n\t\t\t}\n\t\t\t/*\n\tvitalets: fixing bug of very special conditions:\n\tjquery 1.7.1 + webkit + show inline datetimepicker in bootstrap popover.\n\tMethod show() does not set display css correctly and datetimepicker is not shown.\n\tChanged to .css('display', 'block') solve the problem.\n\tSee https://github.com/vitalets/x-editable/issues/37\n\n\tIn jquery 1.7.2+ everything works fine.\n\t*/\n\t\t\t//this.picker.find('>div').hide().filter('.datetimepicker-'+DPGlobal.modes[this.viewMode].clsName).show();\n\t\t\tthis.picker.find('>div').hide().filter('.datetimepicker-' + DPGlobal.modes[this.viewMode].clsName).css('display', 'block');\n\t\t\tthis.updateNavArrows();\n\t\t},\n\n\t\treset: function(e) {\n\t\t\tthis._setDate(null, 'date');\n\t\t},\n\n\t\tconvertViewModeText: function(viewMode) {\n\t\t\tswitch (viewMode) {\n\t\t\tcase 4:\n\t\t\t\treturn 'decade';\n\t\t\tcase 3:\n\t\t\t\treturn 'year';\n\t\t\tcase 2:\n\t\t\t\treturn 'month';\n\t\t\tcase 1:\n\t\t\t\treturn 'day';\n\t\t\tcase 0:\n\t\t\t\treturn 'hour';\n\t\t\t}\n\t\t}\n\t};\n\n\tvar old = $.fn.datetimepicker;\n\t$.fn.datetimepicker = function(option) {\n\t\tvar args = Array.apply(null, arguments);\n\t\targs.shift();\n\t\tvar internal_return;\n\t\tthis.each(function() {\n\t\t\tvar $this = $(this),\n\t\t\tdata = $this.data('datetimepicker'),\n\t\t\toptions = typeof option == 'object' && option;\n\t\t\tif (!data) {\n\t\t\t\t$this.data('datetimepicker', (data = new Datetimepicker(this, $.extend({},\n\t\t\t\t$.fn.datetimepicker.defaults, options))));\n\t\t\t}\n\t\t\tif (typeof option == 'string' && typeof data[option] == 'function') {\n\t\t\t\tinternal_return = data[option].apply(data, args);\n\t\t\t\tif (internal_return !== undefined) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t\tif (internal_return !== undefined) return internal_return;\n\t\telse return this;\n\t};\n\n\t$.fn.datetimepicker.defaults = {};\n\t$.fn.datetimepicker.Constructor = Datetimepicker;\n\tvar dates = $.fn.datetimepicker.dates = {\n\t\ten: {\n\t\t\tdays: ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],\n\t\t\tdaysShort: ['日', '一', '二', '三', '四', '五', '六', '日'],\n\t\t\tdaysMin: ['日', '一', '二', '三', '四', '五', '六', '日'],\n\t\t\tmonths: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],\n\t\t\tmonthsShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],\n\t\t\tmeridiem: ['上午', '下午'],\n\t\t\tsuffix: ['st', 'nd', 'rd', 'th'],\n\t\t\ttoday: '今天',\n\t\t\tclear: '清空'\n\t\t}\n\t};\n\n\tvar DPGlobal = {\n\t\tmodes: [{\n\t\t\tclsName: 'minutes',\n\t\t\tnavFnc: 'Hours',\n\t\t\tnavStep: 1\n\t\t},\n\t\t{\n\t\t\tclsName: 'hours',\n\t\t\tnavFnc: 'Date',\n\t\t\tnavStep: 1\n\t\t},\n\t\t{\n\t\t\tclsName: 'days',\n\t\t\tnavFnc: 'Month',\n\t\t\tnavStep: 1\n\t\t},\n\t\t{\n\t\t\tclsName: 'months',\n\t\t\tnavFnc: 'FullYear',\n\t\t\tnavStep: 1\n\t\t},\n\t\t{\n\t\t\tclsName: 'years',\n\t\t\tnavFnc: 'FullYear',\n\t\t\tnavStep: 10\n\t\t}],\n\t\tisLeapYear: function(year) {\n\t\t\treturn (((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0))\n\t\t},\n\t\tgetDaysInMonth: function(year, month) {\n\t\t\treturn [31, (DPGlobal.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]\n\t\t},\n\t\tgetDefaultFormat: function(type, field) {\n\t\t\tif (type == 'standard') {\n\t\t\t\tif (field == 'input') return 'yyyy-mm-dd hh:ii';\n\t\t\t\telse return 'yyyy-mm-dd hh:ii:ss';\n\t\t\t} else if (type == 'php') {\n\t\t\t\tif (field == 'input') return 'Y-m-d H:i';\n\t\t\t\telse return 'Y-m-d H:i:s';\n\t\t\t} else {\n\t\t\t\tthrow new Error('Invalid format type.');\n\t\t\t}\n\t\t},\n\t\tvalidParts: function(type) {\n\t\t\tif (type == 'standard') {\n\t\t\t\treturn /t|hh?|HH?|p|P|z|Z|ii?|ss?|dd?|DD?|mm?|MM?|yy(?:yy)?/g;\n\t\t\t} else if (type == 'php') {\n\t\t\t\treturn /[dDjlNwzFmMnStyYaABgGhHis]/g;\n\t\t\t} else {\n\t\t\t\tthrow new Error('Invalid format type.');\n\t\t\t}\n\t\t},\n\t\tnonpunctuation: /[^ -\\/:-@\\[-`{-~\\t\\n\\rTZ]+/g,\n\t\tparseFormat: function(format, type) {\n\t\t\t// IE treats \\0 as a string end in inputs (truncating the value),\n\t\t\t// so it's a bad format delimiter, anyway\n\t\t\tvar separators = format.replace(this.validParts(type), '\\0').split('\\0'),\n\t\t\tparts = format.match(this.validParts(type));\n\t\t\tif (!separators || !separators.length || !parts || parts.length == 0) {\n\t\t\t\tthrow new Error('Invalid date format.');\n\t\t\t}\n\t\t\treturn {\n\t\t\t\tseparators: separators,\n\t\t\t\tparts: parts\n\t\t\t};\n\t\t},\n\t\tparseDate: function(date, format, language, type, timezone) {\n\t\t\tif (date instanceof Date) {\n\t\t\t\tvar dateUTC = new Date(date.valueOf() - date.getTimezoneOffset() * 60000);\n\t\t\t\tdateUTC.setMilliseconds(0);\n\t\t\t\treturn dateUTC;\n\t\t\t}\n\t\t\tif (/^\\d{4}\\-\\d{1,2}\\-\\d{1,2}$/.test(date)) {\n\t\t\t\tformat = this.parseFormat('yyyy-mm-dd', type);\n\t\t\t}\n\t\t\tif (/^\\d{4}\\-\\d{1,2}\\-\\d{1,2}[T ]\\d{1,2}\\:\\d{1,2}$/.test(date)) {\n\t\t\t\tformat = this.parseFormat('yyyy-mm-dd hh:ii', type);\n\t\t\t}\n\t\t\tif (/^\\d{4}\\-\\d{1,2}\\-\\d{1,2}[T ]\\d{1,2}\\:\\d{1,2}\\:\\d{1,2}[Z]{0,1}$/.test(date)) {\n\t\t\t\tformat = this.parseFormat('yyyy-mm-dd hh:ii:ss', type);\n\t\t\t}\n\t\t\tif (/^[-+]\\d+[dmwy]([\\s,]+[-+]\\d+[dmwy])*$/.test(date)) {\n\t\t\t\tvar part_re = /([-+]\\d+)([dmwy])/,\n\t\t\t\tparts = date.match(/([-+]\\d+)([dmwy])/g),\n\t\t\t\tpart,\n\t\t\t\tdir;\n\t\t\t\tdate = new Date();\n\t\t\t\tfor (var i = 0; i < parts.length; i++) {\n\t\t\t\t\tpart = part_re.exec(parts[i]);\n\t\t\t\t\tdir = parseInt(part[1]);\n\t\t\t\t\tswitch (part[2]) {\n\t\t\t\t\tcase 'd':\n\t\t\t\t\t\tdate.setUTCDate(date.getUTCDate() + dir);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'm':\n\t\t\t\t\t\tdate = Datetimepicker.prototype.moveMonth.call(Datetimepicker.prototype, date, dir);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'w':\n\t\t\t\t\t\tdate.setUTCDate(date.getUTCDate() + dir * 7);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 'y':\n\t\t\t\t\t\tdate = Datetimepicker.prototype.moveYear.call(Datetimepicker.prototype, date, dir);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn UTCDate(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), 0);\n\t\t\t}\n\t\t\tvar parts = date && date.toString().match(this.nonpunctuation) || [],\n\t\t\tdate = new Date(0, 0, 0, 0, 0, 0, 0),\n\t\t\tparsed = {},\n\t\t\tsetters_order = ['hh', 'h', 'ii', 'i', 'ss', 's', 'yyyy', 'yy', 'M', 'MM', 'm', 'mm', 'D', 'DD', 'd', 'dd', 'H', 'HH', 'p', 'P', 'z', 'Z'],\n\t\t\tsetters_map = {\n\t\t\t\thh: function(d, v) {\n\t\t\t\t\treturn d.setUTCHours(v);\n\t\t\t\t},\n\t\t\t\th: function(d, v) {\n\t\t\t\t\treturn d.setUTCHours(v);\n\t\t\t\t},\n\t\t\t\tHH: function(d, v) {\n\t\t\t\t\treturn d.setUTCHours(v == 12 ? 0 : v);\n\t\t\t\t},\n\t\t\t\tH: function(d, v) {\n\t\t\t\t\treturn d.setUTCHours(v == 12 ? 0 : v);\n\t\t\t\t},\n\t\t\t\tii: function(d, v) {\n\t\t\t\t\treturn d.setUTCMinutes(v);\n\t\t\t\t},\n\t\t\t\ti: function(d, v) {\n\t\t\t\t\treturn d.setUTCMinutes(v);\n\t\t\t\t},\n\t\t\t\tss: function(d, v) {\n\t\t\t\t\treturn d.setUTCSeconds(v);\n\t\t\t\t},\n\t\t\t\ts: function(d, v) {\n\t\t\t\t\treturn d.setUTCSeconds(v);\n\t\t\t\t},\n\t\t\t\tyyyy: function(d, v) {\n\t\t\t\t\treturn d.setUTCFullYear(v);\n\t\t\t\t},\n\t\t\t\tyy: function(d, v) {\n\t\t\t\t\treturn d.setUTCFullYear(2000 + v);\n\t\t\t\t},\n\t\t\t\tm: function(d, v) {\n\t\t\t\t\tv -= 1;\n\t\t\t\t\twhile (v < 0) v += 12;\n\t\t\t\t\tv %= 12;\n\t\t\t\t\td.setUTCMonth(v);\n\t\t\t\t\twhile (d.getUTCMonth() != v) if (isNaN(d.getUTCMonth())) return d;\n\t\t\t\t\telse d.setUTCDate(d.getUTCDate() - 1);\n\t\t\t\t\treturn d;\n\t\t\t\t},\n\t\t\t\td: function(d, v) {\n\t\t\t\t\treturn d.setUTCDate(v);\n\t\t\t\t},\n\t\t\t\tp: function(d, v) {\n\t\t\t\t\treturn d.setUTCHours(v == 1 ? d.getUTCHours() + 12 : d.getUTCHours());\n\t\t\t\t},\n\t\t\t\tz: function() {\n\t\t\t\t\treturn timezone\n\t\t\t\t}\n\t\t\t},\n\t\t\tval,\n\t\t\tfiltered,\n\t\t\tpart;\n\t\t\tsetters_map['M'] = setters_map['MM'] = setters_map['mm'] = setters_map['m'];\n\t\t\tsetters_map['dd'] = setters_map['d'];\n\t\t\tsetters_map['P'] = setters_map['p'];\n\t\t\tsetters_map['Z'] = setters_map['z'];\n\t\t\tdate = UTCDate(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds());\n\t\t\tif (parts.length == format.parts.length) {\n\t\t\t\tfor (var i = 0,\n\t\t\t\tcnt = format.parts.length; i < cnt; i++) {\n\t\t\t\t\tval = parseInt(parts[i], 10);\n\t\t\t\t\tpart = format.parts[i];\n\t\t\t\t\tif (isNaN(val)) {\n\t\t\t\t\t\tswitch (part) {\n\t\t\t\t\t\tcase 'MM':\n\t\t\t\t\t\t\tfiltered = $(dates[language].months).filter(function() {\n\t\t\t\t\t\t\t\tvar m = this.slice(0, parts[i].length),\n\t\t\t\t\t\t\t\tp = parts[i].slice(0, m.length);\n\t\t\t\t\t\t\t\treturn m == p;\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tval = $.inArray(filtered[0], dates[language].months) + 1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'M':\n\t\t\t\t\t\t\tfiltered = $(dates[language].monthsShort).filter(function() {\n\t\t\t\t\t\t\t\tvar m = this.slice(0, parts[i].length),\n\t\t\t\t\t\t\t\tp = parts[i].slice(0, m.length);\n\t\t\t\t\t\t\t\treturn m.toLowerCase() == p.toLowerCase();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tval = $.inArray(filtered[0], dates[language].monthsShort) + 1;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'p':\n\t\t\t\t\t\tcase 'P':\n\t\t\t\t\t\t\tval = $.inArray(parts[i].toLowerCase(), dates[language].meridiem);\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\tcase 'z':\n\t\t\t\t\t\tcase 'Z':\n\t\t\t\t\t\t\ttimezone;\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tparsed[part] = val;\n\t\t\t\t}\n\t\t\t\tfor (var i = 0,\n\t\t\t\ts; i < setters_order.length; i++) {\n\t\t\t\t\ts = setters_order[i];\n\t\t\t\t\tif (s in parsed && !isNaN(parsed[s])) setters_map[s](date, parsed[s])\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn date;\n\t\t},\n\t\tformatDate: function(date, format, language, type, timezone) {\n\t\t\tif (date == null) {\n\t\t\t\treturn '';\n\t\t\t}\n\t\t\tvar val;\n\t\t\tif (type == 'standard') {\n\t\t\t\tval = {\n\t\t\t\t\tt: date.getTime(),\n\t\t\t\t\t// year\n\t\t\t\t\tyy: date.getUTCFullYear().toString().substring(2),\n\t\t\t\t\tyyyy: date.getUTCFullYear(),\n\t\t\t\t\t// month\n\t\t\t\t\tm: date.getUTCMonth() + 1,\n\t\t\t\t\tM: dates[language].monthsShort[date.getUTCMonth()],\n\t\t\t\t\tMM: dates[language].months[date.getUTCMonth()],\n\t\t\t\t\t// day\n\t\t\t\t\td: date.getUTCDate(),\n\t\t\t\t\tD: dates[language].daysShort[date.getUTCDay()],\n\t\t\t\t\tDD: dates[language].days[date.getUTCDay()],\n\t\t\t\t\tp: (dates[language].meridiem.length == 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''),\n\t\t\t\t\t// hour\n\t\t\t\t\th: date.getUTCHours(),\n\t\t\t\t\t// minute\n\t\t\t\t\ti: date.getUTCMinutes(),\n\t\t\t\t\t// second\n\t\t\t\t\ts: date.getUTCSeconds(),\n\t\t\t\t\t// timezone\n\t\t\t\t\tz: timezone\n\t\t\t\t};\n\n\t\t\t\tif (dates[language].meridiem.length == 2) {\n\t\t\t\t\tval.H = (val.h % 12 == 0 ? 12 : val.h % 12);\n\t\t\t\t} else {\n\t\t\t\t\tval.H = val.h;\n\t\t\t\t}\n\t\t\t\tval.HH = (val.H < 10 ? '0': '') + val.H;\n\t\t\t\tval.P = val.p.toUpperCase();\n\t\t\t\tval.Z = val.z;\n\t\t\t\tval.hh = (val.h < 10 ? '0': '') + val.h;\n\t\t\t\tval.ii = (val.i < 10 ? '0': '') + val.i;\n\t\t\t\tval.ss = (val.s < 10 ? '0': '') + val.s;\n\t\t\t\tval.dd = (val.d < 10 ? '0': '') + val.d;\n\t\t\t\tval.mm = (val.m < 10 ? '0': '') + val.m;\n\t\t\t} else if (type == 'php') {\n\t\t\t\t// php format\n\t\t\t\tval = {\n\t\t\t\t\t// year\n\t\t\t\t\ty: date.getUTCFullYear().toString().substring(2),\n\t\t\t\t\tY: date.getUTCFullYear(),\n\t\t\t\t\t// month\n\t\t\t\t\tF: dates[language].months[date.getUTCMonth()],\n\t\t\t\t\tM: dates[language].monthsShort[date.getUTCMonth()],\n\t\t\t\t\tn: date.getUTCMonth() + 1,\n\t\t\t\t\tt: DPGlobal.getDaysInMonth(date.getUTCFullYear(), date.getUTCMonth()),\n\t\t\t\t\t// day\n\t\t\t\t\tj: date.getUTCDate(),\n\t\t\t\t\tl: dates[language].days[date.getUTCDay()],\n\t\t\t\t\tD: dates[language].daysShort[date.getUTCDay()],\n\t\t\t\t\tw: date.getUTCDay(),\n\t\t\t\t\t// 0 -> 6\n\t\t\t\t\tN: (date.getUTCDay() == 0 ? 7 : date.getUTCDay()),\n\t\t\t\t\t// 1 -> 7\n\t\t\t\t\tS: (date.getUTCDate() % 10 <= dates[language].suffix.length ? dates[language].suffix[date.getUTCDate() % 10 - 1] : ''),\n\t\t\t\t\t// hour\n\t\t\t\t\ta: (dates[language].meridiem.length == 2 ? dates[language].meridiem[date.getUTCHours() < 12 ? 0 : 1] : ''),\n\t\t\t\t\tg: (date.getUTCHours() % 12 == 0 ? 12 : date.getUTCHours() % 12),\n\t\t\t\t\tG: date.getUTCHours(),\n\t\t\t\t\t// minute\n\t\t\t\t\ti: date.getUTCMinutes(),\n\t\t\t\t\t// second\n\t\t\t\t\ts: date.getUTCSeconds()\n\t\t\t\t};\n\t\t\t\tval.m = (val.n < 10 ? '0': '') + val.n;\n\t\t\t\tval.d = (val.j < 10 ? '0': '') + val.j;\n\t\t\t\tval.A = val.a.toString().toUpperCase();\n\t\t\t\tval.h = (val.g < 10 ? '0': '') + val.g;\n\t\t\t\tval.H = (val.G < 10 ? '0': '') + val.G;\n\t\t\t\tval.i = (val.i < 10 ? '0': '') + val.i;\n\t\t\t\tval.s = (val.s < 10 ? '0': '') + val.s;\n\t\t\t} else {\n\t\t\t\tthrow new Error('Invalid format type.');\n\t\t\t}\n\t\t\tvar date = [],\n\t\t\tseps = $.extend([], format.separators);\n\t\t\tfor (var i = 0,\n\t\t\tcnt = format.parts.length; i < cnt; i++) {\n\t\t\t\tif (seps.length) {\n\t\t\t\t\tdate.push(seps.shift());\n\t\t\t\t}\n\t\t\t\tdate.push(val[format.parts[i]]);\n\t\t\t}\n\t\t\tif (seps.length) {\n\t\t\t\tdate.push(seps.shift());\n\t\t\t}\n\t\t\treturn date.join('');\n\t\t},\n\t\tconvertViewMode: function(viewMode) {\n\t\t\tswitch (viewMode) {\n\t\t\tcase 4:\n\t\t\tcase 'decade':\n\t\t\t\tviewMode = 4;\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\tcase 'year':\n\t\t\t\tviewMode = 3;\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\tcase 'month':\n\t\t\t\tviewMode = 2;\n\t\t\t\tbreak;\n\t\t\tcase 1:\n\t\t\tcase 'day':\n\t\t\t\tviewMode = 1;\n\t\t\t\tbreak;\n\t\t\tcase 0:\n\t\t\tcase 'hour':\n\t\t\t\tviewMode = 0;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn viewMode;\n\t\t},\n\t\theadTemplate: '<thead>' + '<tr>' + '<th class=\"prev\"><i class=\"{iconType} {leftArrow}\"/></th>' + '<th colspan=\"5\" class=\"switch\"></th>' + '<th class=\"next\"><i class=\"{iconType} {rightArrow}\"/></th>' + '</tr>' + '</thead>',\n\t\theadTemplateV3: '<thead>' + '<tr>' + '<th class=\"prev\"><span class=\"{iconType} {leftArrow}\"></span> </th>' + '<th colspan=\"5\" class=\"switch\"></th>' + '<th class=\"next\"><span class=\"{iconType} {rightArrow}\"></span> </th>' + '</tr>' + '</thead>',\n\t\tcontTemplate: '<tbody><tr><td colspan=\"7\"></td></tr></tbody>',\n\t\tfootTemplate: '<tfoot>' + '<tr><th colspan=\"7\" class=\"today\"></th></tr>' + '<tr><th colspan=\"7\" class=\"clear\"></th></tr>' + '</tfoot>'\n\t};\n\tDPGlobal.template = '<div class=\"datetimepicker\">' + '<div class=\"datetimepicker-minutes\">' + '<table class=\" table-condensed\">' + DPGlobal.headTemplate + DPGlobal.contTemplate + DPGlobal.footTemplate + '</table>' + '</div>' + '<div class=\"datetimepicker-hours\">' + '<table class=\" table-condensed\">' + DPGlobal.headTemplate + DPGlobal.contTemplate + DPGlobal.footTemplate + '</table>' + '</div>' + '<div class=\"datetimepicker-days\">' + '<table class=\" table-condensed\">' + DPGlobal.headTemplate + '<tbody></tbody>' + DPGlobal.footTemplate + '</table>' + '</div>' + '<div class=\"datetimepicker-months\">' + '<table class=\"table-condensed\">' + DPGlobal.headTemplate + DPGlobal.contTemplate + DPGlobal.footTemplate + '</table>' + '</div>' + '<div class=\"datetimepicker-years\">' + '<table class=\"table-condensed\">' + DPGlobal.headTemplate + DPGlobal.contTemplate + DPGlobal.footTemplate + '</table>' + '</div>' + '</div>';\n\tDPGlobal.templateV3 = '<div class=\"datetimepicker\">' + '<div class=\"datetimepicker-minutes\">' + '<table class=\" table-condensed\">' + DPGlobal.headTemplateV3 + DPGlobal.contTemplate + DPGlobal.footTemplate + '</table>' + '</div>' + '<div class=\"datetimepicker-hours\">' + '<table class=\" table-condensed\">' + DPGlobal.headTemplateV3 + DPGlobal.contTemplate + DPGlobal.footTemplate + '</table>' + '</div>' + '<div class=\"datetimepicker-days\">' + '<table class=\" table-condensed\">' + DPGlobal.headTemplateV3 + '<tbody></tbody>' + DPGlobal.footTemplate + '</table>' + '</div>' + '<div class=\"datetimepicker-months\">' + '<table class=\"table-condensed\">' + DPGlobal.headTemplateV3 + DPGlobal.contTemplate + DPGlobal.footTemplate + '</table>' + '</div>' + '<div class=\"datetimepicker-years\">' + '<table class=\"table-condensed\">' + DPGlobal.headTemplateV3 + DPGlobal.contTemplate + DPGlobal.footTemplate + '</table>' + '</div>' + '</div>';\n\t$.fn.datetimepicker.DPGlobal = DPGlobal;\n\n\t/* DATETIMEPICKER NO CONFLICT\n\t\t* =================== */\n\n\t$.fn.datetimepicker.noConflict = function() {\n\t\t$.fn.datetimepicker = old;\n\t\treturn this;\n\t};\n\n\t/* DATETIMEPICKER DATA-API\n\t\t* ================== */\n\n\t$(document).on('focus.datetimepicker.data-api click.datetimepicker.data-api', '[data-provide=\"datetimepicker\"]',\n\tfunction(e) {\n\t\tvar $this = $(this);\n\t\tif ($this.data('datetimepicker')) return;\n\t\te.preventDefault();\n\t\t// component click requires us to explicitly show it\n\t\t$this.datetimepicker('show');\n\t});\n\t$(function() {\n\t\t$('[data-provide=\"datetimepicker-inline\"]').datetimepicker();\n\t});\n}));\n\n/* ============================================================\n * Bootstrap.Switch v1.3 by Larentis Mattia @spiritualGuru\n * http://www.larentis.eu/switch/\n * ============================================================\n * Licensed under the Apache License, Version 2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n * ============================================================ */\n!function($) {\n\t\"use strict\";\n\t$.fn['bootstrapSwitch'] = function(method) {\n\t\tvar methods = {\n\t\t\tinit: function() {\n\t\t\t\treturn this.each(function() {\n\t\t\t\t\tvar $element = $(this),\n\t\t\t\t\t$div,\n\t\t\t\t\t$switchLeft,\n\t\t\t\t\t$switchRight,\n\t\t\t\t\t$label,\n\t\t\t\t\tmyClasses = \"\",\n\t\t\t\t\tclasses = $element.attr('class'),\n\t\t\t\t\tcolor,\n\t\t\t\t\tmoving,\n\t\t\t\t\tonLabel = \"ON\",\n\t\t\t\t\toffLabel = \"OFF\",\n\t\t\t\t\ticon = false;\n\n\t\t\t\t\t$.each(['size-MINI', 'size-S', 'size-L'],\n\t\t\t\t\tfunction(i, el) {\n\t\t\t\t\t\tif (classes.indexOf(el) >= 0) myClasses = el;\n\t\t\t\t\t});\n\t\t\t\t\t$element.addClass('has-switch');\n\t\t\t\t\tif ($element.data('on') !== undefined) color = \"switch-\" + $element.data('on');\n\t\t\t\t\tif ($element.data('on-label') !== undefined) onLabel = $element.data('on-label');\n\t\t\t\t\tif ($element.data('off-label') !== undefined) offLabel = $element.data('off-label');\n\t\t\t\t\tif ($element.data('icon') !== undefined) icon = $element.data('icon');\n\t\t\t\t\t$switchLeft = $('<span>').addClass(\"switch-left\").addClass(myClasses).addClass(color).html(onLabel);\n\t\t\t\t\tcolor = '';\n\t\t\t\t\tif ($element.data('off') !== undefined) color = \"switch-\" + $element.data('off');\n\t\t\t\t\t$switchRight = $('<span>').addClass(\"switch-right\").addClass(myClasses).addClass(color).html(offLabel);\n\t\t\t\t\t$label = $('<label>').html(\"&nbsp;\").addClass(myClasses).attr('for', $element.find('input').attr('id'));\n\t\t\t\t\tif (icon) {\n\t\t\t\t\t\t$label.html('<i class=\"icon icon-' + icon + '\"></i>');\n\t\t\t\t\t}\n\n\t\t\t\t\t$div = $element.find(':checkbox').wrap($('<div>')).parent().data('animated', false);\n\t\t\t\t\tif ($element.data('animated') !== false) $div.addClass('switch-animate').data('animated', true);\n\t\t\t\t\t$div.append($switchLeft).append($label).append($switchRight);\n\t\t\t\t\t$element.find('>div').addClass($element.find('input').is(':checked') ? 'switch-on': 'switch-off');\n\t\t\t\t\tif ($element.find('input').is(':disabled')) $(this).addClass('deactivate');\n\t\t\t\t\tvar changeStatus = function($this) {\n\t\t\t\t\t\t$this.siblings('label').trigger('mousedown').trigger('mouseup').trigger('click');\n\t\t\t\t\t};\n\t\t\t\t\t$element.on('keydown',\n\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\tif (e.keyCode === 32) {\n\t\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\tchangeStatus($(e.target).find('span:first'));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t\t$switchLeft.on('click',\n\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\tchangeStatus($(this));\n\t\t\t\t\t});\n\n\t\t\t\t\t$switchRight.on('click',\n\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\tchangeStatus($(this));\n\t\t\t\t\t});\n\t\t\t\t\t$element.find('input').on('change',\n\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\tvar $this = $(this),\n\t\t\t\t\t\t$element = $this.parent(),\n\t\t\t\t\t\tthisState = $this.is(':checked'),\n\t\t\t\t\t\tstate = $element.is('.switch-off');\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t$element.css('left', '');\n\t\t\t\t\t\tif (state === thisState) {\n\t\t\t\t\t\t\tif (thisState) $element.removeClass('switch-off').addClass('switch-on');\n\t\t\t\t\t\t\telse $element.removeClass('switch-on').addClass('switch-off');\n\t\t\t\t\t\t\tif ($element.data('animated') !== false) $element.addClass(\"switch-animate\");\n\t\t\t\t\t\t\t$element.parent().trigger('switch-change', {\n\t\t\t\t\t\t\t\t'el': $this,\n\t\t\t\t\t\t\t\t'value': thisState\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\n\t\t\t\t\t$element.find('label').on('mousedown touchstart',\n\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\tvar $this = $(this);\n\t\t\t\t\t\tmoving = false;\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t\t$this.closest('div').removeClass('switch-animate');\n\t\t\t\t\t\tif ($this.closest('.has-switch').is('.deactivate')) $this.unbind('click');\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t$this.on('mousemove touchmove',\n\t\t\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\t\t\tvar $element = $(this).closest('.switch'),\n\t\t\t\t\t\t\t\trelativeX = (e.pageX || e.originalEvent.targetTouches[0].pageX) - $element.offset().left,\n\t\t\t\t\t\t\t\tpercent = (relativeX / $element.width()) * 100,\n\t\t\t\t\t\t\t\tleft = 25,\n\t\t\t\t\t\t\t\tright = 75;\n\t\t\t\t\t\t\t\tmoving = true;\n\t\t\t\t\t\t\t\tif (percent < left) percent = left;\n\t\t\t\t\t\t\t\telse if (percent > right) percent = right;\n\t\t\t\t\t\t\t\t$element.find('>div').css('left', (percent - right) + \"%\")\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t$this.on('click touchend',\n\t\t\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\t\t\tvar $this = $(this),\n\t\t\t\t\t\t\t\t$target = $(e.target),\n\t\t\t\t\t\t\t\t$myCheckBox = $target.siblings('input');\n\t\t\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t$this.unbind('mouseleave');\n\t\t\t\t\t\t\t\tif (moving) $myCheckBox.prop('checked', !(parseInt($this.parent().css('left')) < -25));\n\t\t\t\t\t\t\t\telse $myCheckBox.prop(\"checked\", !$myCheckBox.is(\":checked\"));\n\t\t\t\t\t\t\t\tmoving = false;\n\t\t\t\t\t\t\t\t$myCheckBox.trigger('change');\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t$this.on('mouseleave',\n\t\t\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\t\t\tvar $this = $(this),\n\t\t\t\t\t\t\t\t$myCheckBox = $this.siblings('input');\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t\t\t\t$this.unbind('mouseleave');\n\t\t\t\t\t\t\t\t$this.trigger('mouseup');\n\t\t\t\t\t\t\t\t$myCheckBox.prop('checked', !(parseInt($this.parent().css('left')) < -25)).trigger('change');\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\t$this.on('mouseup',\n\t\t\t\t\t\t\tfunction(e) {\n\t\t\t\t\t\t\t\te.stopImmediatePropagation();\n\t\t\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\t\t\t$(this).unbind('mousemove');\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t},\n\t\t\ttoggleActivation: function() {\n\t\t\t\t$(this).toggleClass('deactivate');\n\t\t\t},\n\t\t\tisActive: function() {\n\t\t\t\treturn ! $(this).hasClass('deactivate');\n\t\t\t},\n\t\t\tsetActive: function(active) {\n\t\t\t\tif (active) $(this).removeClass('deactivate');\n\t\t\t\telse $(this).addClass('deactivate');\n\t\t\t},\n\t\t\ttoggleState: function(skipOnChange) {\n\t\t\t\tvar $input = $(this).find('input:checkbox');\n\t\t\t\t$input.prop('checked', !$input.is(':checked')).trigger('change', skipOnChange);\n\t\t\t},\n\t\t\tsetState: function(value, skipOnChange) {\n\t\t\t\t$(this).find('input:checkbox').prop('checked', value).trigger('change', skipOnChange);\n\t\t\t},\n\t\t\tstatus: function() {\n\t\t\t\treturn $(this).find('input:checkbox').is(':checked');\n\t\t\t},\n\t\t\tdestroy: function() {\n\t\t\t\tvar $div = $(this).find('div'),\n\t\t\t\t$checkbox;\n\t\t\t\t$div.find(':not(input:checkbox)').remove();\n\t\t\t\t$checkbox = $div.children();\n\t\t\t\t$checkbox.unwrap().unwrap();\n\t\t\t\t$checkbox.unbind('change');\n\t\t\t\treturn $checkbox;\n\t\t\t}\n\t\t};\n\n\t\tif (methods[method]) return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));\n\t\telse if (typeof method === 'object' || !method) return methods.init.apply(this, arguments);\n\t\telse $.error('Method ' + method + ' does not exist!');\n\t};\n} (jQuery);\n\n$(function() {\n\t$('.switch')['bootstrapSwitch']();\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/css/H-ui.admin.css",
    "content": "@charset \"utf-8\";\n/* -----------H-ui前端框架-------------\n* H-ui.admin.css v2.5\n* http://www.h-ui.net/\n* Created & Modified by guojunhui\n* Date modified 2016.05.31\n*\n* Copyright 2013-2016 北京颖杰联创科技有限公司 All rights reserved.\n* Licensed under MIT license.\n* http://opensource.org/licenses/MIT\n*\n*/\nhtml{height:100%}\nbody{min-height: 100%;position: relative;font-size:14px;color:#333; background-color:#fff}\na{color:#333}a:hover,a:focus,.maincolor,.maincolor a{color:#06c}\n.bg-1{ background-color:#f5fafe}\nh4{line-height:30px}\n\n/*页面框架*/\n.Hui-header{position:absolute;top:0; right:0; left:0;height:44px;z-index:999; padding:0 15px}\n.Hui-aside{position: absolute;top:44px;bottom:0;left:0;padding-top:10px;width:199px;z-index:99;overflow:auto; background-color:rgba(238,238,238,0.98);_background-color:rgb(238,238,238);border-right: 1px solid #e5e5e5}\n.Hui-article-box{position: absolute;top:44px;right:0;bottom: 0;left:199px; overflow:hidden; z-index:1; background-color:#fff}\n\t.Hui-article{position: absolute;top:34px;bottom:0;left:0; right:0;overflow:auto;z-index:1}\n.Hui-container{ padding:45px 0 0}\n.Hui-aside,.Hui-article-box,.dislpayArrow{-moz-transition: all 0.2s ease 0s;-webkit-transition: all 0.2s ease 0s;-ms-transition: all 0.2s ease 0s;-o-transition: all 0.2s ease 0s;transition: all 0.2s ease 0s}\n.big-page .Hui-article-box,.big-page .dislpayArrow,.big-page .breadcrumb{left:0px}\n.big-page .Hui-aside{ left:-200px}\n.page-container{ padding:20px}\n@media (max-width: 767px) {\n\t.page-container{ padding:15px}\n}\n/*组件*/\n/*logo*/\n\n/*导航*/\n#Hui-nav > ul > li{ font-weight:normal}\n@media (max-width: 767px) {\n\t#Hui-nav{display: block; top: 0; left: 65px; right: 65px}\n\t#Hui-nav > ul { width: 100%}\n\t#Hui-nav > ul > li{ width: 24%;text-align:center;}\n\t#Hui-nav > ul > li a{ text-align: center; padding: 0}\n}\n#Hui-userbar{right:20px; position:absolute; top:0;}\n#Hui-userbar > ul > li > a{padding:0 10px}\n\t\n#Hui-msg .badge{ position:absolute; left:19px; top:4px; font-size:12px; font-weight:normal; padding:1px 5px}\n/*左侧菜单*/\n.Hui-aside .menu_dropdown dl{ margin-bottom:0}\n.Hui-aside .menu_dropdown dt{display:block;line-height:35px;padding-left:15px;cursor:pointer;position:relative;border-bottom: 1px solid #e5e5e5;font-weight:normal}\n.Hui-aside .menu_dropdown dt .menu_dropdown-arrow{ position:absolute;overflow: hidden; top:0; right:15px;transition-duration:0.3s ;transition-property:all}\n.Hui-aside .menu_dropdown dd{ display:none}\n.Hui-aside .menu_dropdown dt.selected .menu_dropdown-arrow{transform: rotate(180deg)}\n.Hui-aside .menu_dropdown dd.selected{display:block; margin-left:0px}\n.Hui-aside .menu_dropdown ul{padding:0px}\n.Hui-aside .menu_dropdown li{line-height:35px;overflow:hidden;zoom:1}\n.Hui-aside .menu_dropdown li a{padding-left:15px; display:block;font-weight: bold; margin:0}\n.Hui-aside .menu_dropdown li a i{ font-weight: normal}\n.Hui-aside .menu_dropdown dd ul{padding:3px 8px}\n.Hui-aside .menu_dropdown dd li{line-height:32px}\n.Hui-aside .menu_dropdown dd li a{line-height:32px;padding-left:26px; border-bottom:none; font-weight:normal}\n.Hui-aside .menu_dropdown li a:hover{text-decoration:none}\n.Hui-aside .menu_dropdown li.current a,.menu_dropdown li.current a:hover{background-color:rgba(255,255,255,0.2)}\n/*菜单收缩切换*/\n.dislpayArrow{position: absolute;top: 0;bottom: 0;left:200px;width:0px; height:100%;z-index:10}\n.dislpayArrow a{ position:absolute; display:block; width:17px; height:61px;top:50%; margin-top:-30px;outline:none}\n.dislpayArrow a.open{ background-position:0 -61px}\n.dislpayArrow a:hover{ text-decoration:none; background-position:right 0}\n.dislpayArrow a.open:hover{background-position:right -61px}\n\n/*选项卡导航*/\n.Hui-tabNav-wp{position:relative; height:35px;overflow:hidden}\n.Hui-tabNav,\n.Hui-tabNav .acrossTab li\n,.Hui-tabNav .acrossTab li em{background-image:url(../images/acrossTab/acrossTab-2.png)}\n.Hui-tabNav{height:35px; padding-right:75px;overflow:hidden; position:relative;background-color:#efeef0; background-repeat: repeat-x; background-position: 0 -175px;}\n.Hui-tabNav .acrossTab{ position:absolute; height:26px; line-height:26px; background:none; top:8px; left:0;padding-top:0}\n.Hui-tabNav .acrossTab li{height:26px;line-height:26px;}\n.Hui-tabNav .acrossTab li em{ right:-16px; height: 26px; width: 16px}\n.loading {background:url(../images/loading.gif) no-repeat center; height:100px}\n.show_iframe{ position:absolute; top:0; right:0; left:0; bottom:0;}\n.show_iframe iframe {position: absolute;bottom: 0;height: 100%;width: 100%}\n.Hui-tabNav-more {position: absolute;right:0px;width:70px;top:4px;display: none}\n\n/*面包屑导航*/\n.breadcrumb{background-color:#f5f5f5; padding:0 20px; position:relative; z-index:99}\n@media (max-width: 767px) {\n\t.breadcrumb{ padding:0 15px;}\n\t.show_iframe{-webkit-overflow-scrolling: touch;overflow-y: scroll;}\n}\n\n/*横向手机 竖向平板*/\n@media (max-width: 767px) {\n\t.Hui-aside{ display:none;float:none; width:100%; height:auto; margin-top:0;padding-top:0;bottom:auto}\n\t.big-page .Hui-aside{ left:0!important}\n\t\t.menu_dropdown dt{line-height:44px}\n\t\t.menu_dropdown li,.menu_dropdown dd li,.menu_dropdown dd li a{ line-height:44px}\n  .Hui-tabNav{ position:fixed; z-index:998}\n  .Hui-article{ top:44px}\n  .Hui-article-box{ position:static; left:0}\n  .Hui-article-box .pd-20{padding:15px}\n\t\t.Hui-article{left:0}\n\t\t.Hui-container .bk-gray{ border:none}\n\t\t.Hui-container .pd-10{ padding:0}\n}\n\n/*==============以下是业务相关的样式====================*/\n/*权限*/\n.permission-list{ border:solid 1px #eee;}\n.permission-list > dt{ background-color:#efefef;padding:5px 10px}\n.permission-list > dd{ padding:10px; padding-left:30px}\n.permission-list > dd > dl{ border-bottom:solid 1px #eee; padding:5px 0}\n.permission-list > dd > dl > dt{ display:inline-block;float:left;white-space:nowrap;width:100px}\n.permission-list > dd > dl > dd{ margin-left:100px;}\n.permission-list > dd > dl > dd > label{ padding-right:10px}\n\n/*图片预览*/\n.portfolio-area{ margin-right: -20px;}\n.portfolio-area li{position: relative; float: left; margin-right: 20px; width:162px; height:162px;margin-top: 20px;}\n.portfolio-area li.hover{ z-index:9}\n.portfolio-area li .portfoliobox{ position: absolute; top: 0; left: 0; width: 152px; height: 152px;padding:5px;border: solid 1px #eee; background-color: #fff;}\n.portfolio-area li .checkbox{position: absolute; top: 10px; right: 5px; cursor:pointer}\n.portfolio-area li.hover .portfoliobox{ height:auto;padding-bottom:10px;box-shadow:0 1px 3px rgba(68, 68, 68,0.3);-moz-box-shadow:0 1px 3px rgba(68, 68, 68,0.3);-webkit-box-shadow:0 1px 3px rgba(68, 68, 68,0.3)}\n.portfolio-area li .picbox{width: 150px; height: 150px;overflow: hidden;text-align: center;vertical-align:middle;display:table-cell; line-height:150px;}\n.portfolio-area li .picbox img{max-width:150px; max-height:150px;vertical-align:middle;}\n.portfolio-area li .textbox{ display: none; margin-top: 5px;}\n.portfolio-area li.hover .textbox{ display: block;}\n.portfolio-area li label{ display:block; cursor:pointer}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/css/H-ui.login.css",
    "content": "@charset \"utf-8\";\n/* -----------H-ui前端框架-------------\n* H-ui.login.css v2.2.1\t后台登录页样式\n* http://www.h-ui.net/\n* Created & Modified by guojunhui\n* Date modified 2015.6.5\n*\n* Copyright 2013-2017 北京颖杰联创科技有限公司 All rights reserved.\n* Licensed under MIT license.\n* http://opensource.org/licenses/MIT\n*\n*/\nhtml, body{ height:100%}\nbody{font-size:14px}\n\n.header,.footer{ position:absolute; left:0; right:0; width:100%; z-index:99}\n.header{top:0; height:60px; background:#426374 url(../images/logo.png) no-repeat 0 center}\n\n.loginWraper{ position:absolute;width:100%; left:0; top:0; bottom:0; right:0; z-index:1; background:#3283AC url(../images/admin-login-bg.jpg) no-repeat center}\n.loginBox{ position:absolute; width:617px; height:330px; background:url(../images/admin-loginform-bg.png) no-repeat; left:50%; top:50%; margin-left:-309px; margin-top:-184px; padding-top:38px}\n@media (max-width:617px) {\n\t.loginbox{ width:100%; position:static; margin-top:0; margin-left:0;}\n}\n.loginBox .row{margin-top:20px;}\n.loginBox .row .form-label .Hui-iconfont{ font-size:24px}\n.loginBox .input-text{ width:360px}\n@media (max-width:617px) {\n\t.loginBox .input-text{ width:80%}\n}\n\t.yzm a{ color:#426374; font-size:12px}\n\n#span_msg{ font-size:14px; color:Red; line-height:40px; height:40px; margin-left:10px; width:160px;; float:left}\n\n.hd_msg{font-size:12px; color:#fff; height:30px; z-index:100;position: absolute; padding-left:50px; padding-top:5px}\n.hd_msg a{ color:#fff}\n.hd_msg a:hover{ color:#fff; text-decoration:underline}\n\n.footer{ height:46px; line-height:46px; bottom:0; text-align:center; color:#fff; font-size:12px; background-color:#426374}\n\n#ie6-warning{background:#fff url(/jscss/demoimg/201006/warning.gif) no-repeat 3px center;position:absolute;top:0;left:0;font-size:12px;color:#333;width:97%;padding: 2px 15px 2px 23px;text-align:left}\n#ie6-warning a {text-decoration:none}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/css/style.css",
    "content": "@charset \"utf-8\";\n/* 你自己的样式 */\n\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/js/H-ui.admin.js",
    "content": "/* -----------H-ui前端框架-------------\n* H-ui.admin.js v3.1\n* http://www.h-ui.net/\n* Created & Modified by guojunhui\n* Date modified 2017.02.03\n* Copyright 2013-2017 北京颖杰联创科技有限公司 All rights reserved.\n* Licensed under MIT license.\n* http://opensource.org/licenses/MIT\n*/\nvar num=0,oUl=$(\"#min_title_list\"),hide_nav=$(\"#Hui-tabNav\");\n\n/*获取顶部选项卡总长度*/\nfunction tabNavallwidth(){\n\tvar taballwidth=0,\n\t\t$tabNav = hide_nav.find(\".acrossTab\"),\n\t\t$tabNavWp = hide_nav.find(\".Hui-tabNav-wp\"),\n\t\t$tabNavitem = hide_nav.find(\".acrossTab li\"),\n\t\t$tabNavmore =hide_nav.find(\".Hui-tabNav-more\");\n\tif (!$tabNav[0]){return}\n\t$tabNavitem.each(function(index, element) {\n        taballwidth += Number(parseFloat($(this).width()+60))\n    });\n\t$tabNav.width(taballwidth+25);\n\tvar w = $tabNavWp.width();\n\tif(taballwidth+25>w){\n\t\t$tabNavmore.show()}\n\telse{\n\t\t$tabNavmore.hide();\n\t\t$tabNav.css({left:0});\n\t}\n}\n\n/*左侧菜单响应式*/\nfunction Huiasidedisplay(){\n\tif($(window).width()>=768){\n\t\t$(\".Hui-aside\").show();\n\t} \n}\n/*获取皮肤cookie*/\nfunction getskincookie(){\n\tvar v = $.cookie(\"Huiskin\");\n\tvar hrefStr=$(\"#skin\").attr(\"href\");\n\tif(v==null||v==\"\"){\n\t\tv=\"default\";\n\t}\n\tif(hrefStr!=undefined){\n\t\tvar hrefRes=hrefStr.substring(0,hrefStr.lastIndexOf('skin/'))+'skin/'+v+'/skin.css';\n\t\t$(\"#skin\").attr(\"href\",hrefRes);\n\t}\n}\n/*菜单导航*/\nfunction Hui_admin_tab(obj){\n\tvar bStop = false,\n\t\tbStopIndex = 0,\n\t\thref = $(obj).attr('data-href'),\n\t\ttitle = $(obj).attr(\"data-title\"),\n\t\ttopWindow = $(window.parent.document),\n\t\tshow_navLi = topWindow.find(\"#min_title_list li\"),\n\t\tiframe_box = topWindow.find(\"#iframe_box\");\n\t//console.log(topWindow);\n\tif(!href||href==\"\"){\n\t\talert(\"data-href不存在，v2.5版本之前用_href属性，升级后请改为data-href属性\");\n\t\treturn false;\n\t}if(!title){\n\t\talert(\"v2.5版本之后使用data-title属性\");\n\t\treturn false;\n\t}\n\tif(title==\"\"){\n\t\talert(\"data-title属性不能为空\");\n\t\treturn false;\n\t}\n\tshow_navLi.each(function() {\n\t\tif($(this).find('span').attr(\"data-href\")==href){\n\t\t\tbStop=true;\n\t\t\tbStopIndex=show_navLi.index($(this));\n\t\t\treturn false;\n\t\t}\n\t});\n\tif(!bStop){\n\t\tcreatIframe(href,title);\n\t\tmin_titleList();\n\t}\n\telse{\n\t\tshow_navLi.removeClass(\"active\").eq(bStopIndex).addClass(\"active\");\t\t\t\n\t\tiframe_box.find(\".show_iframe\").hide().eq(bStopIndex).show().find(\"iframe\").attr(\"src\",href);\n\t}\t\n}\n\n/*最新tab标题栏列表*/\nfunction min_titleList(){\n\tvar topWindow = $(window.parent.document),\n\t\tshow_nav = topWindow.find(\"#min_title_list\"),\n\t\taLi = show_nav.find(\"li\");\n}\n\n/*创建iframe*/\nfunction creatIframe(href,titleName){\n\tvar topWindow=$(window.parent.document),\n\t\tshow_nav=topWindow.find('#min_title_list'),\n\t\tiframe_box=topWindow.find('#iframe_box'),\n\t\tiframeBox=iframe_box.find('.show_iframe'),\n\t\t$tabNav = topWindow.find(\".acrossTab\"),\n\t\t$tabNavWp = topWindow.find(\".Hui-tabNav-wp\"),\n\t\t$tabNavmore =topWindow.find(\".Hui-tabNav-more\");\n\tvar taballwidth=0;\n\t\t\n\tshow_nav.find('li').removeClass(\"active\");\t\n\tshow_nav.append('<li class=\"active\"><span data-href=\"'+href+'\">'+titleName+'</span><i></i><em></em></li>');\n\tif('function'==typeof $('#min_title_list li').contextMenu){\n\t\t$(\"#min_title_list li\").contextMenu('Huiadminmenu', {\n\t\t\tbindings: {\n\t\t\t\t'closethis': function(t) {\n\t\t\t\t\tvar $t = $(t);\t\t\t\t\n\t\t\t\t\tif($t.find(\"i\")){\n\t\t\t\t\t\t$t.find(\"i\").trigger(\"click\");\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t'closeall': function(t) {\n\t\t\t\t\t$(\"#min_title_list li i\").trigger(\"click\");\n\t\t\t\t},\n\t\t\t}\n\t\t});\n\t}else {\n\t\t\n\t}\t\n\tvar $tabNavitem = topWindow.find(\".acrossTab li\");\n\tif (!$tabNav[0]){return}\n\t$tabNavitem.each(function(index, element) {\n        taballwidth+=Number(parseFloat($(this).width()+60))\n    });\n\t$tabNav.width(taballwidth+25);\n\tvar w = $tabNavWp.width();\n\tif(taballwidth+25>w){\n\t\t$tabNavmore.show()}\n\telse{\n\t\t$tabNavmore.hide();\n\t\t$tabNav.css({left:0})\n\t}\t\n\tiframeBox.hide();\n\tiframe_box.append('<div class=\"show_iframe\"><div class=\"loading\"></div><iframe frameborder=\"0\" src='+href+'></iframe></div>');\n\tvar showBox=iframe_box.find('.show_iframe:visible');\n\tshowBox.find('iframe').load(function(){\n\t\tshowBox.find('.loading').hide();\n\t});\n}\n\n\n\n/*关闭iframe*/\nfunction removeIframe(){\n\tvar topWindow = $(window.parent.document),\n\t\tiframe = topWindow.find('#iframe_box .show_iframe'),\n\t\ttab = topWindow.find(\".acrossTab li\"),\n\t\tshowTab = topWindow.find(\".acrossTab li.active\"),\n\t\tshowBox=topWindow.find('.show_iframe:visible'),\n\t\ti = showTab.index();\n\ttab.eq(i-1).addClass(\"active\");\n\ttab.eq(i).remove();\n\tiframe.eq(i-1).show();\t\n\tiframe.eq(i).remove();\n}\n\n/*关闭所有iframe*/\nfunction removeIframeAll(){\n\tvar topWindow = $(window.parent.document),\n\t\tiframe = topWindow.find('#iframe_box .show_iframe'),\n\t\ttab = topWindow.find(\".acrossTab li\");\n\tfor(var i=0;i<tab.length;i++){\n\t\tif(tab.eq(i).find(\"i\").length>0){\n\t\t\ttab.eq(i).remove();\n\t\t\tiframe.eq(i).remove();\n\t\t}\n\t}\n}\n\n/*弹出层*/\n/*\n\t参数解释：\n\ttitle\t标题\n\turl\t\t请求的url\n\tid\t\t需要操作的数据id\n\tw\t\t弹出层宽度（缺省调默认值）\n\th\t\t弹出层高度（缺省调默认值）\n*/\nfunction layer_show(title,url,w,h){\n\tif (title == null || title == '') {\n\t\ttitle=false;\n\t};\n\tif (url == null || url == '') {\n\t\turl=\"404.jsp\";\n\t};\n\tif (w == null || w == '') {\n\t\tw=800;\n\t};\n\tif (h == null || h == '') {\n\t\th=($(window).height() - 50);\n\t};\n\tlayer.open({\n\t\ttype: 2,\n\t\tarea: [w+'px', h +'px'],\n\t\tfix: false, //不固定\n\t\tmaxmin: true,\n\t\tshade:0.4,\n\t\ttitle: title,\n\t\tcontent: url\n\t});\n}\n/*关闭弹出框口*/\nfunction layer_close(){\n\tvar index = parent.layer.getFrameIndex(window.name);\n\tparent.layer.close(index);\n}\n\n/*时间*/\nfunction getHTMLDate(obj) {\n    var d = new Date();\n    var weekday = new Array(7);\n    var _mm = \"\";\n    var _dd = \"\";\n    var _ww = \"\";\n    weekday[0] = \"星期日\";\n    weekday[1] = \"星期一\";\n    weekday[2] = \"星期二\";\n    weekday[3] = \"星期三\";\n    weekday[4] = \"星期四\";\n    weekday[5] = \"星期五\";\n    weekday[6] = \"星期六\";\n    _yy = d.getFullYear();\n    _mm = d.getMonth() + 1;\n    _dd = d.getDate();\n    _ww = weekday[d.getDay()];\n    obj.html(_yy + \"年\" + _mm + \"月\" + _dd + \"日 \" + _ww);\n};\n\n$(function(){\n\tgetHTMLDate($(\"#top_time\"));\n\tgetskincookie();\n\t//layer.config({extend: 'extend/layer.ext.js'});\n\tHuiasidedisplay();\n\tvar resizeID;\n\t$(window).resize(function(){\n\t\tclearTimeout(resizeID);\n\t\tresizeID = setTimeout(function(){\n\t\t\tHuiasidedisplay();\n\t\t},500);\n\t});\n\t\n\t$(\".nav-toggle\").click(function(){\n\t\t$(\".Hui-aside\").slideToggle();\n\t});\n\t$(\".Hui-aside\").on(\"click\",\".menu_dropdown dd li a\",function(){\n\t\tif($(window).width()<768){\n\t\t\t$(\".Hui-aside\").slideToggle();\n\t\t}\n\t});\n\t/*左侧菜单*/\n\t$(\".Hui-aside\").Huifold({\n\t\ttitCell:'.menu_dropdown dl dt',\n\t\tmainCell:'.menu_dropdown dl dd',\n\t});\n\t\n\t/*选项卡导航*/\n\t$(\".Hui-aside\").on(\"click\",\".menu_dropdown a\",function(){\n\t\tHui_admin_tab(this);\n\t});\n\t\n\t$(document).on(\"click\",\"#min_title_list li\",function(){\n\t\tvar bStopIndex=$(this).index();\n\t\tvar iframe_box=$(\"#iframe_box\");\n\t\t$(\"#min_title_list li\").removeClass(\"active\").eq(bStopIndex).addClass(\"active\");\n\t\tiframe_box.find(\".show_iframe\").hide().eq(bStopIndex).show();\n\t});\n\t$(document).on(\"click\",\"#min_title_list li i\",function(){\n\t\tvar aCloseIndex=$(this).parents(\"li\").index();\n\t\t$(this).parent().remove();\n\t\t$('#iframe_box').find('.show_iframe').eq(aCloseIndex).remove();\t\n\t\tnum==0?num=0:num--;\n\t\ttabNavallwidth();\n\t});\n\t$(document).on(\"dblclick\",\"#min_title_list li\",function(){\n\t\tvar aCloseIndex=$(this).index();\n\t\tvar iframe_box=$(\"#iframe_box\");\n\t\tif(aCloseIndex>0){\n\t\t\t$(this).remove();\n\t\t\t$('#iframe_box').find('.show_iframe').eq(aCloseIndex).remove();\t\n\t\t\tnum==0?num=0:num--;\n\t\t\t$(\"#min_title_list li\").removeClass(\"active\").eq(aCloseIndex-1).addClass(\"active\");\n\t\t\tiframe_box.find(\".show_iframe\").hide().eq(aCloseIndex-1).show();\n\t\t\ttabNavallwidth();\n\t\t}else{\n\t\t\treturn false;\n\t\t}\n\t});\n\ttabNavallwidth();\n\t\n\t$('#js-tabNav-next').click(function(){\n\t\tnum==oUl.find('li').length-1?num=oUl.find('li').length-1:num++;\n\t\ttoNavPos();\n\t});\n\t$('#js-tabNav-prev').click(function(){\n\t\tnum==0?num=0:num--;\n\t\ttoNavPos();\n\t});\n\t\n\tfunction toNavPos(){\n\t\toUl.stop().animate({'left':-num*100},100);\n\t}\n\t\n\t/*换肤*/\n\t$(\"#Hui-skin .dropDown-menu a\").click(function(){\n\t\tvar v = $(this).attr(\"data-val\");\n        $.cookie('Huiskin', v, { expires: 365 });\n        var hrefStr=$(\"#skin\").attr(\"href\");\n\t\tvar hrefRes=hrefStr.substring(0,hrefStr.lastIndexOf('skin/'))+'skin/'+v+'/skin.css';\n\t\t$(window.frames.document).contents().find(\"#skin\").attr(\"href\",hrefRes);\n\t});\n}); \n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/js/de_DE.txt",
    "content": "{\r\n\t\"processing\": \"处理中...\",\r\n\t\"lengthMenu\": \"每页显示 _MENU_ 条\",\r\n\t\"zeroRecords\": \"没有找到匹配的记录\",\r\n\t\"sProcessing\": \"&lt;img src=’./loading.gif’ /&gt;\",\r\n\t\"info\": \"显示 _START_ 到 _END_ ，共 _TOTAL_ 条\",\r\n\t\"infoEmpty\": \"0条\",\r\n\t\"infoFiltered\": \"(从 _MAX_ 条中过滤)\",\r\n\t\"infoPostFix\": \"\",\r\n\t\"search\": \"当前检索\",\r\n\t\"url\": \"\",\r\n\t\"paginate\": {\r\n\t\t\"first\":    \"第一页\",\r\n\t\t\"previous\": \"上一页\",\r\n\t\t\"next\":     \"下一页\",\r\n\t\t\"last\":     \"最后一页\"\r\n\t}\r\n}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/skin/black/skin.css",
    "content": "@charset \"utf-8\";\n/* 默认 黑色 */\t\n/*全站默认字体颜色*/\na{color:#333}a:hover,a:focus,.maincolor,.maincolor a{color:#06c}\n.navbar{ background:#222}/*顶部导航*/\n\t.navbar-logo,.navbar-logo-m,.navbar-slogan,.navbar-userbar{color:#fff}/*logo 及 用户信息文字颜色*/\n\t.navbar-logo:hover,.navbar-logo-m:hover{color:#fff;text-decoration: none}\n\t\n.navbar-nav > ul > li, .navbar-nav > ul > li > a{ color:#fff}/*顶部导航文字颜色*/\n.navbar-userbar > ul> > li,.navbar-userbar > ul> > li > a{ color:#fff}\n\n.Hui-aside{}/*侧边栏*/\n\t.Hui-aside .menu_dropdown dt{color:#333}/*左侧二级导航菜单*/\n\t.Hui-aside .menu_dropdown dt:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt:hover [class^=\"icon-\"]{ color:#7e8795}\n\t.Hui-aside .menu_dropdown li a{color:#666;border-bottom: 1px solid #e5e5e5}\n\t.Hui-aside .menu_dropdown li a:hover{color:#148cf1;background-color:#fafafa}\n\t.Hui-aside .menu_dropdown li.current a,.menu_dropdown li.current a:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt .Hui-iconfont{ color:#a0a7b1}\n\t.Hui-aside .menu_dropdown dt .menu_dropdown-arrow{ color:#b6b7b8}\t\n\t.dislpayArrow a{background:url(icon_arrow.png) no-repeat 0 0}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/skin/default/skin.css",
    "content": "@charset \"utf-8\";\n/* 蓝色 */\n/*全站默认字体颜色*/\na{color:#333}a:hover,a:focus,.maincolor,.maincolor a{color:#06c}\n.navbar{ background:#2d6dcc}/*顶部导航*/\n\t.navbar-logo,.navbar-logo-m,.navbar-slogan,.navbar-userbar{color:#fff}/*logo 及 用户信息文字颜色*/\n\t.navbar-logo:hover,.navbar-logo-m:hover{color:#fff;text-decoration: none}\n\t\n.navbar-nav > ul > li, .navbar-nav > ul > li > a{ color:#fff}/*顶部导航文字颜色*/\n.navbar-userbar > ul> > li,.navbar-userbar > ul> > li > a{ color:#fff}\n\n.Hui-aside{}/*侧边栏*/\n\t.Hui-aside .menu_dropdown dt{color:#333}/*左侧二级导航菜单*/\n\t.Hui-aside .menu_dropdown dt:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt:hover [class^=\"icon-\"]{ color:#7e8795}\n\t.Hui-aside .menu_dropdown li a{color:#666;border-bottom: 1px solid #e5e5e5}\n\t.Hui-aside .menu_dropdown li a:hover{color:#148cf1;background-color:#fafafa}\n\t.Hui-aside .menu_dropdown li.current a,.menu_dropdown li.current a:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt .Hui-iconfont{ color:#a0a7b1}\n\t.Hui-aside .menu_dropdown dt .menu_dropdown-arrow{ color:#b6b7b8}\t\n\t.dislpayArrow a{background:url(icon_arrow.png) no-repeat 0 0}\n.tabBar {border-bottom: 2px solid #2d6dcc}\n.tabBar span.current{background-color:#2d6dcc}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/skin/green/skin.css",
    "content": "@charset \"utf-8\";\n/* 绿色 */\n/*全站默认字体颜色*/\na{color:#333}a:hover,a:focus,.maincolor,.maincolor a{color:#06c}\n.navbar{ background:#19a97b}/*顶部导航*/\n\t.navbar-logo,.navbar-logo-m,.navbar-slogan,.navbar-userbar{color:#fff}/*logo 及 用户信息文字颜色*/\n\t.navbar-logo:hover,.navbar-logo-m:hover{color:#fff;text-decoration: none}\n\t\n.navbar-nav > ul > li, .navbar-nav > ul > li > a{ color:#fff}/*顶部导航文字颜色*/\n.navbar-userbar > ul> > li,.navbar-userbar > ul> > li > a{ color:#fff}\n\n.Hui-aside{}/*侧边栏*/\n\t.Hui-aside .menu_dropdown dt{color:#333}/*左侧二级导航菜单*/\n\t.Hui-aside .menu_dropdown dt:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt:hover [class^=\"icon-\"]{ color:#7e8795}\n\t.Hui-aside .menu_dropdown li a{color:#666;border-bottom: 1px solid #e5e5e5}\n\t.Hui-aside .menu_dropdown li a:hover{color:#148cf1;background-color:#fafafa}\n\t.Hui-aside .menu_dropdown li.current a,.menu_dropdown li.current a:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt .Hui-iconfont{ color:#a0a7b1}\n\t.Hui-aside .menu_dropdown dt .menu_dropdown-arrow{ color:#b6b7b8}\t\n\t.dislpayArrow a{background:url(icon_arrow.png) no-repeat 0 0}\n.tabBar {border-bottom: 2px solid #19a97b}\n.tabBar span.current{background-color:#19a97b}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/skin/orange/skin.css",
    "content": "@charset \"utf-8\";\n/* 橙色 */\n/*全站默认字体颜色*/\na{color:#333}a:hover,a:focus,.maincolor,.maincolor a{color:#06c}\n.navbar{ background:#ff4a00}/*顶部导航*/\n\t.navbar-logo,.navbar-logo-m,.navbar-slogan,.navbar-userbar{color:#fff}/*logo 及 用户信息文字颜色*/\n\t.navbar-logo:hover,.navbar-logo-m:hover{color:#fff;text-decoration: none}\n\t\n.navbar-nav > ul > li, .navbar-nav > ul > li > a{ color:#fff}/*顶部导航文字颜色*/\n.navbar-userbar > ul> > li,.navbar-userbar > ul> > li > a{ color:#fff}\n\n.Hui-aside{}/*侧边栏*/\n\t.Hui-aside .menu_dropdown dt{color:#333}/*左侧二级导航菜单*/\n\t.Hui-aside .menu_dropdown dt:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt:hover [class^=\"icon-\"]{ color:#7e8795}\n\t.Hui-aside .menu_dropdown li a{color:#666;border-bottom: 1px solid #e5e5e5}\n\t.Hui-aside .menu_dropdown li a:hover{color:#148cf1;background-color:#fafafa}\n\t.Hui-aside .menu_dropdown li.current a,.menu_dropdown li.current a:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt .Hui-iconfont{ color:#a0a7b1}\n\t.Hui-aside .menu_dropdown dt .menu_dropdown-arrow{ color:#b6b7b8}\t\n\t.dislpayArrow a{background:url(icon_arrow.png) no-repeat 0 0}\n.tabBar {border-bottom: 2px solid #ff4a00}\n.tabBar span.current{background-color:#ff4a00}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/skin/red/skin.css",
    "content": "@charset \"utf-8\";\n/* 红色 */\n/*全站默认字体颜色*/\na{color:#333}a:hover,a:focus,.maincolor,.maincolor a{color:#06c}\n.navbar{ background:#c81623}/*顶部导航*/\n\t.navbar-logo,.navbar-logo-m,.navbar-slogan,.navbar-userbar{color:#fff}/*logo 及 用户信息文字颜色*/\n\t.navbar-logo:hover,.navbar-logo-m:hover{color:#fff;text-decoration: none}\n\t\n.navbar-nav > ul > li, .navbar-nav > ul > li > a{ color:#fff}/*顶部导航文字颜色*/\n.navbar-userbar > ul> > li,.navbar-userbar > ul> > li > a{ color:#fff}\n\n.Hui-aside{}/*侧边栏*/\n\t.Hui-aside .menu_dropdown dt{color:#333}/*左侧二级导航菜单*/\n\t.Hui-aside .menu_dropdown dt:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt:hover [class^=\"icon-\"]{ color:#7e8795}\n\t.Hui-aside .menu_dropdown li a{color:#666;border-bottom: 1px solid #e5e5e5}\n\t.Hui-aside .menu_dropdown li a:hover{color:#148cf1;background-color:#fafafa}\n\t.Hui-aside .menu_dropdown li.current a,.menu_dropdown li.current a:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt .Hui-iconfont{ color:#a0a7b1}\n\t.Hui-aside .menu_dropdown dt .menu_dropdown-arrow{ color:#b6b7b8}\t\n\t.dislpayArrow a{background:url(icon_arrow.png) no-repeat 0 0}\n.tabBar {border-bottom: 2px solid #c81623}\n.tabBar span.current{background-color:#c81623}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/h-ui.admin/skin/yellow/skin.css",
    "content": "@charset \"utf-8\";\n/* 黄色 */\n/*全站默认字体颜色*/\na{color:#333}a:hover,a:focus,.maincolor,.maincolor a{color:#06c}\n.navbar{ background:#ffd200}/*顶部导航*/\n\t.navbar-logo,.navbar-logo-m,.navbar-slogan,.navbar-userbar{color:#282828}/*logo 及 用户信息文字颜色*/\n\t.navbar-logo:hover,.navbar-logo-m:hover{color:#282828;text-decoration: none}\n\t\n.navbar-nav > ul > li, .navbar-nav > ul > li > a{ color:#282828}/*顶部导航文字颜色*/\n.navbar-userbar > ul> > li,.navbar-userbar > ul> > li > a{ color:#282828}\n\n.Hui-aside{}/*侧边栏*/\n\t.Hui-aside .menu_dropdown dt{color:#333}/*左侧二级导航菜单*/\n\t.Hui-aside .menu_dropdown dt:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt:hover [class^=\"icon-\"]{ color:#7e8795}\n\t.Hui-aside .menu_dropdown li a{color:#666;border-bottom: 1px solid #e5e5e5}\n\t.Hui-aside .menu_dropdown li a:hover{color:#148cf1;background-color:#fafafa}\n\t.Hui-aside .menu_dropdown li.current a,.menu_dropdown li.current a:hover{color:#148cf1}\n\t.Hui-aside .menu_dropdown dt .Hui-iconfont{ color:#a0a7b1}\n\t.Hui-aside .menu_dropdown dt .menu_dropdown-arrow{ color:#b6b7b8}\t\n\t.dislpayArrow a{background:url(icon_arrow.png) no-repeat 0 0}\n.tabBar {border-bottom: 2px solid #ffd200}\n.tabBar span.current{background-color:#ffd200;color:#282828}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/css/print.css",
    "content": ".swagger-section pre code{display:block;padding:.5em;background:#f0f0f0}.swagger-section pre .clojure .built_in,.swagger-section pre .lisp .title,.swagger-section pre .nginx .title,.swagger-section pre .subst,.swagger-section pre .tag .title,.swagger-section pre code{color:#000}.swagger-section pre .addition,.swagger-section pre .aggregate,.swagger-section pre .apache .cbracket,.swagger-section pre .apache .tag,.swagger-section pre .bash .variable,.swagger-section pre .constant,.swagger-section pre .django .variable,.swagger-section pre .erlang_repl .function_or_atom,.swagger-section pre .flow,.swagger-section pre .markdown .header,.swagger-section pre .parent,.swagger-section pre .preprocessor,.swagger-section pre .ruby .symbol,.swagger-section pre .ruby .symbol .string,.swagger-section pre .rules .value,.swagger-section pre .rules .value .number,.swagger-section pre .smalltalk .class,.swagger-section pre .stream,.swagger-section pre .string,.swagger-section pre .tag .value,.swagger-section pre .template_tag,.swagger-section pre .tex .command,.swagger-section pre .tex .special,.swagger-section pre .title{color:#800}.swagger-section pre .annotation,.swagger-section pre .chunk,.swagger-section pre .comment,.swagger-section pre .diff .header,.swagger-section pre .markdown .blockquote,.swagger-section pre .template_comment{color:#888}.swagger-section pre .change,.swagger-section pre .date,.swagger-section pre .go .constant,.swagger-section pre .literal,.swagger-section pre .markdown .bullet,.swagger-section pre .markdown .link_url,.swagger-section pre .number,.swagger-section pre .regexp,.swagger-section pre .smalltalk .char,.swagger-section pre .smalltalk .symbol{color:#080}.swagger-section pre .apache .sqbracket,.swagger-section pre .array,.swagger-section pre .attr_selector,.swagger-section pre .clojure .attribute,.swagger-section pre .coffeescript .property,.swagger-section pre .decorator,.swagger-section pre .deletion,.swagger-section pre .doctype,.swagger-section pre .envvar,.swagger-section pre .erlang_repl .reserved,.swagger-section pre .filter .argument,.swagger-section pre .important,.swagger-section pre .javadoc,.swagger-section pre .label,.swagger-section pre .localvars,.swagger-section pre .markdown .link_label,.swagger-section pre .nginx .built_in,.swagger-section pre .pi,.swagger-section pre .prompt,.swagger-section pre .pseudo,.swagger-section pre .ruby .string,.swagger-section pre .shebang,.swagger-section pre .tex .formula,.swagger-section pre .vhdl .attribute{color:#88f}.swagger-section pre .aggregate,.swagger-section pre .apache .tag,.swagger-section pre .bash .variable,.swagger-section pre .built_in,.swagger-section pre .css .tag,.swagger-section pre .go .typename,.swagger-section pre .id,.swagger-section pre .javadoctag,.swagger-section pre .keyword,.swagger-section pre .markdown .strong,.swagger-section pre .phpdoc,.swagger-section pre .request,.swagger-section pre .smalltalk .class,.swagger-section pre .status,.swagger-section pre .tex .command,.swagger-section pre .title,.swagger-section pre .winutils,.swagger-section pre .yardoctag{font-weight:700}.swagger-section pre .markdown .emphasis{font-style:italic}.swagger-section pre .nginx .built_in{font-weight:400}.swagger-section pre .coffeescript .javascript,.swagger-section pre .javascript .xml,.swagger-section pre .tex .formula,.swagger-section pre .xml .cdata,.swagger-section pre .xml .css,.swagger-section pre .xml .javascript,.swagger-section pre .xml .vbscript{opacity:.5}.swagger-section .hljs{display:block;overflow-x:auto;padding:.5em;background:#f0f0f0}.swagger-section .hljs,.swagger-section .hljs-subst{color:#444}.swagger-section .hljs-attribute,.swagger-section .hljs-doctag,.swagger-section .hljs-keyword,.swagger-section .hljs-meta-keyword,.swagger-section .hljs-name,.swagger-section .hljs-selector-tag{font-weight:700}.swagger-section .hljs-addition,.swagger-section .hljs-built_in,.swagger-section .hljs-bullet,.swagger-section .hljs-code,.swagger-section .hljs-literal{color:#1f811f}.swagger-section .hljs-link,.swagger-section .hljs-regexp,.swagger-section .hljs-selector-attr,.swagger-section .hljs-selector-pseudo,.swagger-section .hljs-symbol,.swagger-section .hljs-template-variable,.swagger-section .hljs-variable{color:#bc6060}.swagger-section .hljs-deletion,.swagger-section .hljs-number,.swagger-section .hljs-quote,.swagger-section .hljs-selector-class,.swagger-section .hljs-selector-id,.swagger-section .hljs-string,.swagger-section .hljs-template-tag,.swagger-section .hljs-type{color:#800}.swagger-section .hljs-section,.swagger-section .hljs-title{color:#800;font-weight:700}.swagger-section .hljs-comment{color:#888}.swagger-section .hljs-meta{color:#2b6ea1}.swagger-section .hljs-emphasis{font-style:italic}.swagger-section .hljs-strong{font-weight:700}.swagger-section .swagger-ui-wrap{line-height:1;font-family:Droid Sans,sans-serif;min-width:760px;max-width:960px;margin-left:auto;margin-right:auto}.swagger-section .swagger-ui-wrap b,.swagger-section .swagger-ui-wrap strong{font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap blockquote,.swagger-section .swagger-ui-wrap q{quotes:none}.swagger-section .swagger-ui-wrap p{line-height:1.4em;padding:0 0 10px;color:#333}.swagger-section .swagger-ui-wrap blockquote:after,.swagger-section .swagger-ui-wrap blockquote:before,.swagger-section .swagger-ui-wrap q:after,.swagger-section .swagger-ui-wrap q:before{content:none}.swagger-section .swagger-ui-wrap .heading_with_menu h1,.swagger-section .swagger-ui-wrap .heading_with_menu h2,.swagger-section .swagger-ui-wrap .heading_with_menu h3,.swagger-section .swagger-ui-wrap .heading_with_menu h4,.swagger-section .swagger-ui-wrap .heading_with_menu h5,.swagger-section .swagger-ui-wrap .heading_with_menu h6{display:block;clear:none;float:left;-ms-box-sizing:border-box;box-sizing:border-box;width:60%}.swagger-section .swagger-ui-wrap table{border-collapse:collapse;border-spacing:0}.swagger-section .swagger-ui-wrap table thead tr th{padding:5px;font-size:.9em;color:#666;border-bottom:1px solid #999}.swagger-section .swagger-ui-wrap table tbody tr:last-child td{border-bottom:none}.swagger-section .swagger-ui-wrap table tbody tr.offset{background-color:#f0f0f0}.swagger-section .swagger-ui-wrap table tbody tr td{padding:6px;font-size:.9em;border-bottom:1px solid #ccc;vertical-align:top;line-height:1.3em}.swagger-section .swagger-ui-wrap ol{margin:0 0 10px;padding:0 0 0 18px;list-style-type:decimal}.swagger-section .swagger-ui-wrap ol li{padding:5px 0;font-size:.9em;color:#333}.swagger-section .swagger-ui-wrap ol,.swagger-section .swagger-ui-wrap ul{list-style:none}.swagger-section .swagger-ui-wrap h1 a,.swagger-section .swagger-ui-wrap h2 a,.swagger-section .swagger-ui-wrap h3 a,.swagger-section .swagger-ui-wrap h4 a,.swagger-section .swagger-ui-wrap h5 a,.swagger-section .swagger-ui-wrap h6 a{text-decoration:none}.swagger-section .swagger-ui-wrap h1 a:hover,.swagger-section .swagger-ui-wrap h2 a:hover,.swagger-section .swagger-ui-wrap h3 a:hover,.swagger-section .swagger-ui-wrap h4 a:hover,.swagger-section .swagger-ui-wrap h5 a:hover,.swagger-section .swagger-ui-wrap h6 a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap h1 span.divider,.swagger-section .swagger-ui-wrap h2 span.divider,.swagger-section .swagger-ui-wrap h3 span.divider,.swagger-section .swagger-ui-wrap h4 span.divider,.swagger-section .swagger-ui-wrap h5 span.divider,.swagger-section .swagger-ui-wrap h6 span.divider{color:#aaa}.swagger-section .swagger-ui-wrap a{color:#547f00}.swagger-section .swagger-ui-wrap a img{border:none}.swagger-section .swagger-ui-wrap article,.swagger-section .swagger-ui-wrap aside,.swagger-section .swagger-ui-wrap details,.swagger-section .swagger-ui-wrap figcaption,.swagger-section .swagger-ui-wrap figure,.swagger-section .swagger-ui-wrap footer,.swagger-section .swagger-ui-wrap header,.swagger-section .swagger-ui-wrap hgroup,.swagger-section .swagger-ui-wrap menu,.swagger-section .swagger-ui-wrap nav,.swagger-section .swagger-ui-wrap section,.swagger-section .swagger-ui-wrap summary{display:block}.swagger-section .swagger-ui-wrap pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#fcf6db;border:1px solid #e5e0c6;padding:10px}.swagger-section .swagger-ui-wrap pre code{line-height:1.6em;background:none}.swagger-section .swagger-ui-wrap .content>.content-type>div>label{clear:both;display:block;color:#0f6ab4;font-size:1.1em;margin:0;padding:15px 0 5px}.swagger-section .swagger-ui-wrap .content pre{font-size:12px;margin-top:5px;padding:5px}.swagger-section .swagger-ui-wrap .icon-btn{cursor:pointer}.swagger-section .swagger-ui-wrap .info_title{padding-bottom:10px;font-weight:700;font-size:25px}.swagger-section .swagger-ui-wrap .footer{margin-top:20px}.swagger-section .swagger-ui-wrap div.big p,.swagger-section .swagger-ui-wrap p.big{font-size:1em;margin-bottom:10px}.swagger-section .swagger-ui-wrap form.fullwidth ol li.numeric input,.swagger-section .swagger-ui-wrap form.fullwidth ol li.string input,.swagger-section .swagger-ui-wrap form.fullwidth ol li.text textarea,.swagger-section .swagger-ui-wrap form.fullwidth ol li.url input{width:500px!important}.swagger-section .swagger-ui-wrap .info_license,.swagger-section .swagger-ui-wrap .info_tos{padding-bottom:5px}.swagger-section .swagger-ui-wrap .message-fail{color:#c00}.swagger-section .swagger-ui-wrap .info_email,.swagger-section .swagger-ui-wrap .info_name,.swagger-section .swagger-ui-wrap .info_url{padding-bottom:5px}.swagger-section .swagger-ui-wrap .info_description{padding-bottom:10px;font-size:15px}.swagger-section .swagger-ui-wrap .markdown ol li,.swagger-section .swagger-ui-wrap .markdown ul li{padding:3px 0;line-height:1.4em;color:#333}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input{display:block;padding:4px;width:auto;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input.title,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input.title,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input.title{font-size:1.3em}.swagger-section .swagger-ui-wrap table.fullwidth{width:100%}.swagger-section .swagger-ui-wrap .model-signature{font-family:Droid Sans,sans-serif;font-size:1em;line-height:1.5em}.swagger-section .swagger-ui-wrap .model-signature .signature-nav a{text-decoration:none;color:#aaa}.swagger-section .swagger-ui-wrap .model-signature .signature-nav a:hover{text-decoration:underline;color:#000}.swagger-section .swagger-ui-wrap .model-signature .signature-nav .selected{color:#000;text-decoration:none}.swagger-section .swagger-ui-wrap .model-signature .propType{color:#55a}.swagger-section .swagger-ui-wrap .model-signature pre:hover{background-color:#ffd}.swagger-section .swagger-ui-wrap .model-signature pre{font-size:.85em;line-height:1.2em;overflow:auto;height:200px;resize:vertical;cursor:pointer}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav{display:block;min-width:230px;margin:0;padding:0}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li{float:left;margin:0 5px 5px 0;padding:2px 5px 2px 0;border-right:1px solid #ddd}.swagger-section .swagger-ui-wrap .model-signature .propOpt{color:#555}.swagger-section .swagger-ui-wrap .model-signature .snippet small{font-size:.75em}.swagger-section .swagger-ui-wrap .model-signature .propOptKey{font-style:italic}.swagger-section .swagger-ui-wrap .model-signature .description .strong{font-weight:700;color:#000;font-size:.9em}.swagger-section .swagger-ui-wrap .model-signature .description div{font-size:.9em;line-height:1.5em;margin-left:1em}.swagger-section .swagger-ui-wrap .model-signature .description .stronger{font-weight:700;color:#000}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper{border-spacing:0;position:absolute;background-color:#fff;border:1px solid #bbb;display:none;font-size:11px;max-width:400px;line-height:30px;color:#000;padding:5px;margin-left:10px}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper th{text-align:center;background-color:#eee;border:1px solid #bbb;font-size:11px;color:#666;font-weight:700;padding:5px;line-height:15px}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper .optionName{font-weight:700}.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:first-child,.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:last-child{display:inline}.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:not(:first-child):before{display:block;content:\"\"}.swagger-section .swagger-ui-wrap .model-signature .description span:last-of-type.propDesc.markdown>p:only-child{margin-right:-3px}.swagger-section .swagger-ui-wrap .model-signature .propName{font-weight:700}.swagger-section .swagger-ui-wrap .model-signature .signature-container{clear:both}.swagger-section .swagger-ui-wrap .body-textarea{width:300px;height:100px;border:1px solid #aaa}.swagger-section .swagger-ui-wrap .markdown li code,.swagger-section .swagger-ui-wrap .markdown p code{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#f0f0f0;color:#000;padding:1px 3px}.swagger-section .swagger-ui-wrap .required{font-weight:700}.swagger-section .swagger-ui-wrap .editor_holder{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;font-size:.9em}.swagger-section .swagger-ui-wrap .editor_holder label{font-weight:400!important}.swagger-section .swagger-ui-wrap .editor_holder label.required{font-weight:700!important}.swagger-section .swagger-ui-wrap input.parameter{width:300px;border:1px solid #aaa}.swagger-section .swagger-ui-wrap h1{color:#000;font-size:1.5em;line-height:1.3em;padding:10px 0;font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap .heading_with_menu{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap .heading_with_menu ul{display:block;clear:none;float:right;-ms-box-sizing:border-box;box-sizing:border-box;margin-top:10px}.swagger-section .swagger-ui-wrap h2{color:#000;font-size:1.3em;padding:10px 0}.swagger-section .swagger-ui-wrap h2 a{color:#000}.swagger-section .swagger-ui-wrap h2 span.sub{font-size:.7em;color:#999;font-style:italic}.swagger-section .swagger-ui-wrap h2 span.sub a{color:#777}.swagger-section .swagger-ui-wrap span.weak{color:#666}.swagger-section .swagger-ui-wrap .message-success{color:#89bf04}.swagger-section .swagger-ui-wrap caption,.swagger-section .swagger-ui-wrap td,.swagger-section .swagger-ui-wrap th{text-align:left;font-weight:400;vertical-align:middle}.swagger-section .swagger-ui-wrap .code{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.text textarea{font-family:Droid Sans,sans-serif;height:250px;padding:4px;display:block;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.select select{display:block;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean label{display:block;float:left;clear:none;margin:0;padding:0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean input{display:block;float:left;clear:none;margin:0 5px 0 0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.required label{color:#000}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label{display:block;clear:both;width:auto;padding:0 0 3px;color:#666}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label abbr{padding-left:3px;color:#888}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li p.inline-hints{margin-left:0;font-style:italic;font-size:.9em;margin:0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.buttons{margin:0;padding:0}.swagger-section .swagger-ui-wrap span.blank,.swagger-section .swagger-ui-wrap span.empty{color:#888;font-style:italic}.swagger-section .swagger-ui-wrap .markdown h3{color:#547f00}.swagger-section .swagger-ui-wrap .markdown h4{color:#666}.swagger-section .swagger-ui-wrap .markdown pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#fcf6db;border:1px solid #e5e0c6;padding:10px;margin:0 0 10px}.swagger-section .swagger-ui-wrap .markdown pre code{line-height:1.6em;overflow:auto}.swagger-section .swagger-ui-wrap div.gist{margin:20px 0 25px!important}.swagger-section .swagger-ui-wrap ul#resources{font-family:Droid Sans,sans-serif;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource{border-bottom:1px solid #ddd}.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading h2 a,.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading h2 a{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading ul.options li a,.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading ul.options li a{color:#555}.swagger-section .swagger-ui-wrap ul#resources li.resource:last-child{border-bottom:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading{border:1px solid transparent;float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options{overflow:hidden;padding:0;display:block;clear:none;float:right;margin:14px 10px 0 0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li{float:left;clear:none;margin:0;padding:2px 10px;border-right:1px solid #ddd;color:#666;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a{color:#aaa;text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover{text-decoration:underline;color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a.active,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:active,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.first,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:first-child{padding-left:0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options.first,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options:first-child{padding-left:0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2{color:#999;padding-left:0;display:block;clear:none;float:left;font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a{color:#999}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation{float:none;clear:both;overflow:hidden;display:block;margin:0 0 10px;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading{float:none;clear:both;overflow:hidden;display:block;margin:0;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3{display:block;clear:none;float:left;width:auto;margin:0;padding:0;line-height:1.1em;color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path{padding-left:10px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a{color:#000;text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a.toggleOperation.deprecated{text-decoration:line-through}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.http_method a{text-transform:uppercase;text-decoration:none;color:#fff;display:inline-block;width:50px;font-size:.7em;text-align:center;padding:7px 0 4px;border-radius:2px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span{margin:0;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options{overflow:hidden;padding:0;display:block;clear:none;float:right;margin:6px 10px 0 0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li{float:left;clear:none;margin:0;padding:2px 10px;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a{text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a .markdown p{color:inherit;padding:0;line-height:inherit}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a .nickname{color:#aaa;padding:0;line-height:inherit}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li.access{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content{border-top:none;padding:10px;border-bottom-left-radius:6px;border-bottom-right-radius:6px;margin:0 0 20px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content h4{font-size:1.1em;margin:0;padding:15px 0 5px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header a{padding:4px 0 0 10px;display:inline-block;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit{display:block;clear:none;float:left;padding:6px 8px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header span.response_throbber{background-image:url(../images/throbber.gif);width:128px;height:16px;display:block;clear:none;float:right}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type=text].error{outline:2px solid #000;outline-color:#c00}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form select[name=parameterContentType]{max-width:300px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.response div.block pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;padding:10px;font-size:.9em;max-height:400px;overflow-y:auto}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading{background-color:#f9f2e9;border:1px solid #f0e0ca}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.http_method a{background-color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#f0e0ca;color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a{color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content{background-color:#faf5ee;border:1px solid #f0e0ca}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content h4{color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header a{color:#dcb67f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading{background-color:#fcffcd;border:1px solid #000;border-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading h3 span.http_method a{text-transform:uppercase;background-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#ffd20f;color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li a{color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content{background-color:#fcffcd;border:1px solid #000;border-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content h4{color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content div.sandbox_header a{color:#6fc992}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading{background-color:#f5e8e8;border:1px solid #e8c6c7}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.http_method a{text-transform:uppercase;background-color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#e8c6c7;color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a{color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content{background-color:#f7eded;border:1px solid #e8c6c7}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content h4{color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header a{color:#c8787a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading{background-color:#e7f6ec;border:1px solid #c3e8d1}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.http_method a{background-color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3e8d1;color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a{color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content{background-color:#ebf7f0;border:1px solid #c3e8d1}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content h4{color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header a{color:#6fc992}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading{background-color:#fce9e3;border:1px solid #f5d5c3}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading h3 span.http_method a{background-color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#f0cecb;color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li a{color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content{background-color:#faf0ef;border:1px solid #f0cecb}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content h4{color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content div.sandbox_header a{color:#dcb67f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading{background-color:#e7f0f7;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.http_method a{background-color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3d9ec;color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content{background-color:#ebf3f9;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content h4{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header a{color:#6fa5d2}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading{background-color:#e7f0f7;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading h3 span.http_method a{background-color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3d9ec;color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li a{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content{background-color:#ebf3f9;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content h4{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content div.sandbox_header a{color:#6fa5d2}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content{border-top:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a.active,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:active,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations.first,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations:first-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li.first,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li:first-child{padding-left:0}.swagger-section .swagger-ui-wrap p#colophon{margin:0 15px 40px;padding:10px 0;font-size:.8em;border-top:1px solid #ddd;font-family:Droid Sans,sans-serif;color:#999;font-style:italic}.swagger-section .swagger-ui-wrap p#colophon a{text-decoration:none;color:#547f00}.swagger-section .swagger-ui-wrap h3{color:#000;font-size:1.1em;padding:10px 0}.swagger-section .swagger-ui-wrap .markdown ol,.swagger-section .swagger-ui-wrap .markdown ul{font-family:Droid Sans,sans-serif;margin:5px 0 10px;padding:0 0 0 18px;list-style-type:disc}.swagger-section .swagger-ui-wrap form.form_box{background-color:#ebf3f9;border:1px solid #c3d9ec;padding:10px}.swagger-section .swagger-ui-wrap form.form_box label{color:#0f6ab4!important}.swagger-section .swagger-ui-wrap form.form_box input[type=submit]{display:block;padding:10px}.swagger-section .swagger-ui-wrap form.form_box p.weak{font-size:.8em}.swagger-section .swagger-ui-wrap form.form_box p{font-size:.9em;padding:0 0 15px;color:#7e7b6d}.swagger-section .swagger-ui-wrap form.form_box p a{color:#646257}.swagger-section .swagger-ui-wrap form.form_box p strong{color:#000}.swagger-section .swagger-ui-wrap .operation-status td.markdown>p:last-child{padding-bottom:0}.swagger-section .title{font-style:bold}.swagger-section .secondary_form{display:none}.swagger-section .main_image{display:block;margin-left:auto;margin-right:auto}.swagger-section .oauth_body{margin-left:100px;margin-right:100px}.swagger-section .oauth_submit{text-align:center;display:inline-block}.swagger-section .authorize-wrapper{margin:15px 0 10px}.swagger-section .authorize-wrapper_operation{float:right}.swagger-section .authorize__btn:hover{text-decoration:underline;cursor:pointer}.swagger-section .authorize__btn_operation:hover .authorize-scopes{display:block}.swagger-section .authorize-scopes{position:absolute;margin-top:20px;background:#fff;border:1px solid #ccc;border-radius:5px;display:none;font-size:13px;max-width:300px;line-height:30px;color:#000;padding:5px}.swagger-section .authorize-scopes .authorize__scope{text-decoration:none}.swagger-section .authorize__btn_operation{height:18px;vertical-align:middle;display:inline-block;background:url(../images/explorer_icons.png) no-repeat}.swagger-section .authorize__btn_operation_login{background-position:0 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section .authorize__btn_operation_logout{background-position:-30px 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section #auth_container{color:#fff;display:inline-block;border:none;padding:5px;width:87px;height:13px}.swagger-section #auth_container .authorize__btn{color:#fff}.swagger-section .auth_container{padding:0 0 10px;margin-bottom:5px;border-bottom:1px solid #ccc;font-size:.9em}.swagger-section .auth_container .auth__title{color:#547f00;font-size:1.2em}.swagger-section .auth_container .basic_auth__label{display:inline-block;width:60px}.swagger-section .auth_container .auth__description{color:#999;margin-bottom:5px}.swagger-section .auth_container .auth__button{margin-top:10px;height:30px}.swagger-section .auth_container .key_auth__field{margin:5px 0}.swagger-section .auth_container .key_auth__label{display:inline-block;width:60px}.swagger-section .api-popup-dialog{position:absolute;display:none}.swagger-section .api-popup-dialog-wrapper{z-index:2;width:500px;background:#fff;padding:20px;border:1px solid #ccc;border-radius:5px;font-size:13px;color:#777;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%)}.swagger-section .api-popup-dialog-shadow{position:fixed;top:0;left:0;width:100%;height:100%;opacity:.2;background-color:gray;z-index:1}.swagger-section .api-popup-dialog .api-popup-title{font-size:24px;padding:10px 0}.swagger-section .api-popup-dialog .error-msg{padding-left:5px;padding-bottom:5px}.swagger-section .api-popup-dialog .api-popup-content{max-height:500px;overflow-y:auto}.swagger-section .api-popup-dialog .api-popup-authbtn,.swagger-section .api-popup-dialog .api-popup-cancel{height:30px}.swagger-section .api-popup-scopes{padding:10px 20px}.swagger-section .api-popup-scopes li{padding:5px 0;line-height:20px}.swagger-section .api-popup-scopes li input{position:relative;top:2px}.swagger-section .api-popup-scopes .api-scope-desc{padding-left:20px;font-style:italic}.swagger-section .api-popup-actions{padding-top:10px}.swagger-section fieldset{padding-bottom:10px;padding-left:20px}#header{display:none}.swagger-section .swagger-ui-wrap .model-signature pre{max-height:none}.swagger-section .swagger-ui-wrap .body-textarea,.swagger-section .swagger-ui-wrap input.parameter{width:100px}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options{display:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content{display:block!important}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/css/reset.css",
    "content": "a,abbr,acronym,address,applet,article,aside,audio,b,big,blockquote,body,canvas,caption,center,cite,code,dd,del,details,dfn,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,header,hgroup,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,output,p,pre,q,ruby,s,samp,section,small,span,strike,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,tt,u,ul,var,video{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:after,blockquote:before,q:after,q:before{content:\"\";content:none}table{border-collapse:collapse;border-spacing:0}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/css/screen.css",
    "content": ".swagger-section pre code{display:block;padding:.5em;background:#f0f0f0}.swagger-section pre .clojure .built_in,.swagger-section pre .lisp .title,.swagger-section pre .nginx .title,.swagger-section pre .subst,.swagger-section pre .tag .title,.swagger-section pre code{color:#000}.swagger-section pre .addition,.swagger-section pre .aggregate,.swagger-section pre .apache .cbracket,.swagger-section pre .apache .tag,.swagger-section pre .bash .variable,.swagger-section pre .constant,.swagger-section pre .django .variable,.swagger-section pre .erlang_repl .function_or_atom,.swagger-section pre .flow,.swagger-section pre .markdown .header,.swagger-section pre .parent,.swagger-section pre .preprocessor,.swagger-section pre .ruby .symbol,.swagger-section pre .ruby .symbol .string,.swagger-section pre .rules .value,.swagger-section pre .rules .value .number,.swagger-section pre .smalltalk .class,.swagger-section pre .stream,.swagger-section pre .string,.swagger-section pre .tag .value,.swagger-section pre .template_tag,.swagger-section pre .tex .command,.swagger-section pre .tex .special,.swagger-section pre .title{color:#800}.swagger-section pre .annotation,.swagger-section pre .chunk,.swagger-section pre .comment,.swagger-section pre .diff .header,.swagger-section pre .markdown .blockquote,.swagger-section pre .template_comment{color:#888}.swagger-section pre .change,.swagger-section pre .date,.swagger-section pre .go .constant,.swagger-section pre .literal,.swagger-section pre .markdown .bullet,.swagger-section pre .markdown .link_url,.swagger-section pre .number,.swagger-section pre .regexp,.swagger-section pre .smalltalk .char,.swagger-section pre .smalltalk .symbol{color:#080}.swagger-section pre .apache .sqbracket,.swagger-section pre .array,.swagger-section pre .attr_selector,.swagger-section pre .clojure .attribute,.swagger-section pre .coffeescript .property,.swagger-section pre .decorator,.swagger-section pre .deletion,.swagger-section pre .doctype,.swagger-section pre .envvar,.swagger-section pre .erlang_repl .reserved,.swagger-section pre .filter .argument,.swagger-section pre .important,.swagger-section pre .javadoc,.swagger-section pre .label,.swagger-section pre .localvars,.swagger-section pre .markdown .link_label,.swagger-section pre .nginx .built_in,.swagger-section pre .pi,.swagger-section pre .prompt,.swagger-section pre .pseudo,.swagger-section pre .ruby .string,.swagger-section pre .shebang,.swagger-section pre .tex .formula,.swagger-section pre .vhdl .attribute{color:#88f}.swagger-section pre .aggregate,.swagger-section pre .apache .tag,.swagger-section pre .bash .variable,.swagger-section pre .built_in,.swagger-section pre .css .tag,.swagger-section pre .go .typename,.swagger-section pre .id,.swagger-section pre .javadoctag,.swagger-section pre .keyword,.swagger-section pre .markdown .strong,.swagger-section pre .phpdoc,.swagger-section pre .request,.swagger-section pre .smalltalk .class,.swagger-section pre .status,.swagger-section pre .tex .command,.swagger-section pre .title,.swagger-section pre .winutils,.swagger-section pre .yardoctag{font-weight:700}.swagger-section pre .markdown .emphasis{font-style:italic}.swagger-section pre .nginx .built_in{font-weight:400}.swagger-section pre .coffeescript .javascript,.swagger-section pre .javascript .xml,.swagger-section pre .tex .formula,.swagger-section pre .xml .cdata,.swagger-section pre .xml .css,.swagger-section pre .xml .javascript,.swagger-section pre .xml .vbscript{opacity:.5}.swagger-section .hljs{display:block;overflow-x:auto;padding:.5em;background:#f0f0f0}.swagger-section .hljs,.swagger-section .hljs-subst{color:#444}.swagger-section .hljs-attribute,.swagger-section .hljs-doctag,.swagger-section .hljs-keyword,.swagger-section .hljs-meta-keyword,.swagger-section .hljs-name,.swagger-section .hljs-selector-tag{font-weight:700}.swagger-section .hljs-addition,.swagger-section .hljs-built_in,.swagger-section .hljs-bullet,.swagger-section .hljs-code,.swagger-section .hljs-literal{color:#1f811f}.swagger-section .hljs-link,.swagger-section .hljs-regexp,.swagger-section .hljs-selector-attr,.swagger-section .hljs-selector-pseudo,.swagger-section .hljs-symbol,.swagger-section .hljs-template-variable,.swagger-section .hljs-variable{color:#bc6060}.swagger-section .hljs-deletion,.swagger-section .hljs-number,.swagger-section .hljs-quote,.swagger-section .hljs-selector-class,.swagger-section .hljs-selector-id,.swagger-section .hljs-string,.swagger-section .hljs-template-tag,.swagger-section .hljs-type{color:#800}.swagger-section .hljs-section,.swagger-section .hljs-title{color:#800;font-weight:700}.swagger-section .hljs-comment{color:#888}.swagger-section .hljs-meta{color:#2b6ea1}.swagger-section .hljs-emphasis{font-style:italic}.swagger-section .hljs-strong{font-weight:700}.swagger-section .swagger-ui-wrap{line-height:1;font-family:Droid Sans,sans-serif;min-width:760px;max-width:960px;margin-left:auto;margin-right:auto}.swagger-section .swagger-ui-wrap b,.swagger-section .swagger-ui-wrap strong{font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap blockquote,.swagger-section .swagger-ui-wrap q{quotes:none}.swagger-section .swagger-ui-wrap p{line-height:1.4em;padding:0 0 10px;color:#333}.swagger-section .swagger-ui-wrap blockquote:after,.swagger-section .swagger-ui-wrap blockquote:before,.swagger-section .swagger-ui-wrap q:after,.swagger-section .swagger-ui-wrap q:before{content:none}.swagger-section .swagger-ui-wrap .heading_with_menu h1,.swagger-section .swagger-ui-wrap .heading_with_menu h2,.swagger-section .swagger-ui-wrap .heading_with_menu h3,.swagger-section .swagger-ui-wrap .heading_with_menu h4,.swagger-section .swagger-ui-wrap .heading_with_menu h5,.swagger-section .swagger-ui-wrap .heading_with_menu h6{display:block;clear:none;float:left;-ms-box-sizing:border-box;box-sizing:border-box;width:60%}.swagger-section .swagger-ui-wrap table{border-collapse:collapse;border-spacing:0}.swagger-section .swagger-ui-wrap table thead tr th{padding:5px;font-size:.9em;color:#666;border-bottom:1px solid #999}.swagger-section .swagger-ui-wrap table tbody tr:last-child td{border-bottom:none}.swagger-section .swagger-ui-wrap table tbody tr.offset{background-color:#f0f0f0}.swagger-section .swagger-ui-wrap table tbody tr td{padding:6px;font-size:.9em;border-bottom:1px solid #ccc;vertical-align:top;line-height:1.3em}.swagger-section .swagger-ui-wrap ol{margin:0 0 10px;padding:0 0 0 18px;list-style-type:decimal}.swagger-section .swagger-ui-wrap ol li{padding:5px 0;font-size:.9em;color:#333}.swagger-section .swagger-ui-wrap ol,.swagger-section .swagger-ui-wrap ul{list-style:none}.swagger-section .swagger-ui-wrap h1 a,.swagger-section .swagger-ui-wrap h2 a,.swagger-section .swagger-ui-wrap h3 a,.swagger-section .swagger-ui-wrap h4 a,.swagger-section .swagger-ui-wrap h5 a,.swagger-section .swagger-ui-wrap h6 a{text-decoration:none}.swagger-section .swagger-ui-wrap h1 a:hover,.swagger-section .swagger-ui-wrap h2 a:hover,.swagger-section .swagger-ui-wrap h3 a:hover,.swagger-section .swagger-ui-wrap h4 a:hover,.swagger-section .swagger-ui-wrap h5 a:hover,.swagger-section .swagger-ui-wrap h6 a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap h1 span.divider,.swagger-section .swagger-ui-wrap h2 span.divider,.swagger-section .swagger-ui-wrap h3 span.divider,.swagger-section .swagger-ui-wrap h4 span.divider,.swagger-section .swagger-ui-wrap h5 span.divider,.swagger-section .swagger-ui-wrap h6 span.divider{color:#aaa}.swagger-section .swagger-ui-wrap a{color:#547f00}.swagger-section .swagger-ui-wrap a img{border:none}.swagger-section .swagger-ui-wrap article,.swagger-section .swagger-ui-wrap aside,.swagger-section .swagger-ui-wrap details,.swagger-section .swagger-ui-wrap figcaption,.swagger-section .swagger-ui-wrap figure,.swagger-section .swagger-ui-wrap footer,.swagger-section .swagger-ui-wrap header,.swagger-section .swagger-ui-wrap hgroup,.swagger-section .swagger-ui-wrap menu,.swagger-section .swagger-ui-wrap nav,.swagger-section .swagger-ui-wrap section,.swagger-section .swagger-ui-wrap summary{display:block}.swagger-section .swagger-ui-wrap pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#fcf6db;border:1px solid #e5e0c6;padding:10px}.swagger-section .swagger-ui-wrap pre code{line-height:1.6em;background:none}.swagger-section .swagger-ui-wrap .content>.content-type>div>label{clear:both;display:block;color:#0f6ab4;font-size:1.1em;margin:0;padding:15px 0 5px}.swagger-section .swagger-ui-wrap .content pre{font-size:12px;margin-top:5px;padding:5px}.swagger-section .swagger-ui-wrap .icon-btn{cursor:pointer}.swagger-section .swagger-ui-wrap .info_title{padding-bottom:10px;font-weight:700;font-size:25px}.swagger-section .swagger-ui-wrap .footer{margin-top:20px}.swagger-section .swagger-ui-wrap div.big p,.swagger-section .swagger-ui-wrap p.big{font-size:1em;margin-bottom:10px}.swagger-section .swagger-ui-wrap form.fullwidth ol li.numeric input,.swagger-section .swagger-ui-wrap form.fullwidth ol li.string input,.swagger-section .swagger-ui-wrap form.fullwidth ol li.text textarea,.swagger-section .swagger-ui-wrap form.fullwidth ol li.url input{width:500px!important}.swagger-section .swagger-ui-wrap .info_license,.swagger-section .swagger-ui-wrap .info_tos{padding-bottom:5px}.swagger-section .swagger-ui-wrap .message-fail{color:#c00}.swagger-section .swagger-ui-wrap .info_email,.swagger-section .swagger-ui-wrap .info_name,.swagger-section .swagger-ui-wrap .info_url{padding-bottom:5px}.swagger-section .swagger-ui-wrap .info_description{padding-bottom:10px;font-size:15px}.swagger-section .swagger-ui-wrap .markdown ol li,.swagger-section .swagger-ui-wrap .markdown ul li{padding:3px 0;line-height:1.4em;color:#333}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input{display:block;padding:4px;width:auto;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input.title,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input.title,.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input.title{font-size:1.3em}.swagger-section .swagger-ui-wrap table.fullwidth{width:100%}.swagger-section .swagger-ui-wrap .model-signature{font-family:Droid Sans,sans-serif;font-size:1em;line-height:1.5em}.swagger-section .swagger-ui-wrap .model-signature .signature-nav a{text-decoration:none;color:#aaa}.swagger-section .swagger-ui-wrap .model-signature .signature-nav a:hover{text-decoration:underline;color:#000}.swagger-section .swagger-ui-wrap .model-signature .signature-nav .selected{color:#000;text-decoration:none}.swagger-section .swagger-ui-wrap .model-signature .propType{color:#55a}.swagger-section .swagger-ui-wrap .model-signature pre:hover{background-color:#ffd}.swagger-section .swagger-ui-wrap .model-signature pre{font-size:.85em;line-height:1.2em;overflow:auto;height:200px;resize:vertical;cursor:pointer}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav{display:block;min-width:230px;margin:0;padding:0}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li{float:left;margin:0 5px 5px 0;padding:2px 5px 2px 0;border-right:1px solid #ddd}.swagger-section .swagger-ui-wrap .model-signature .propOpt{color:#555}.swagger-section .swagger-ui-wrap .model-signature .snippet small{font-size:.75em}.swagger-section .swagger-ui-wrap .model-signature .propOptKey{font-style:italic}.swagger-section .swagger-ui-wrap .model-signature .description .strong{font-weight:700;color:#000;font-size:.9em}.swagger-section .swagger-ui-wrap .model-signature .description div{font-size:.9em;line-height:1.5em;margin-left:1em}.swagger-section .swagger-ui-wrap .model-signature .description .stronger{font-weight:700;color:#000}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper{border-spacing:0;position:absolute;background-color:#fff;border:1px solid #bbb;display:none;font-size:11px;max-width:400px;line-height:30px;color:#000;padding:5px;margin-left:10px}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper th{text-align:center;background-color:#eee;border:1px solid #bbb;font-size:11px;color:#666;font-weight:700;padding:5px;line-height:15px}.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper .optionName{font-weight:700}.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:first-child,.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:last-child{display:inline}.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown>p:not(:first-child):before{display:block;content:\"\"}.swagger-section .swagger-ui-wrap .model-signature .description span:last-of-type.propDesc.markdown>p:only-child{margin-right:-3px}.swagger-section .swagger-ui-wrap .model-signature .propName{font-weight:700}.swagger-section .swagger-ui-wrap .model-signature .signature-container{clear:both}.swagger-section .swagger-ui-wrap .body-textarea{width:300px;height:100px;border:1px solid #aaa}.swagger-section .swagger-ui-wrap .markdown li code,.swagger-section .swagger-ui-wrap .markdown p code{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#f0f0f0;color:#000;padding:1px 3px}.swagger-section .swagger-ui-wrap .required{font-weight:700}.swagger-section .swagger-ui-wrap .editor_holder{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;font-size:.9em}.swagger-section .swagger-ui-wrap .editor_holder label{font-weight:400!important}.swagger-section .swagger-ui-wrap .editor_holder label.required{font-weight:700!important}.swagger-section .swagger-ui-wrap input.parameter{width:300px;border:1px solid #aaa}.swagger-section .swagger-ui-wrap h1{color:#000;font-size:1.5em;line-height:1.3em;padding:10px 0;font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap .heading_with_menu{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap .heading_with_menu ul{display:block;clear:none;float:right;-ms-box-sizing:border-box;box-sizing:border-box;margin-top:10px}.swagger-section .swagger-ui-wrap h2{color:#000;font-size:1.3em;padding:10px 0}.swagger-section .swagger-ui-wrap h2 a{color:#000}.swagger-section .swagger-ui-wrap h2 span.sub{font-size:.7em;color:#999;font-style:italic}.swagger-section .swagger-ui-wrap h2 span.sub a{color:#777}.swagger-section .swagger-ui-wrap span.weak{color:#666}.swagger-section .swagger-ui-wrap .message-success{color:#89bf04}.swagger-section .swagger-ui-wrap caption,.swagger-section .swagger-ui-wrap td,.swagger-section .swagger-ui-wrap th{text-align:left;font-weight:400;vertical-align:middle}.swagger-section .swagger-ui-wrap .code{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.text textarea{font-family:Droid Sans,sans-serif;height:250px;padding:4px;display:block;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.select select{display:block;clear:both}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean label{display:block;float:left;clear:none;margin:0;padding:0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean input{display:block;float:left;clear:none;margin:0 5px 0 0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.required label{color:#000}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label{display:block;clear:both;width:auto;padding:0 0 3px;color:#666}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label abbr{padding-left:3px;color:#888}.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li p.inline-hints{margin-left:0;font-style:italic;font-size:.9em;margin:0}.swagger-section .swagger-ui-wrap form.formtastic fieldset.buttons{margin:0;padding:0}.swagger-section .swagger-ui-wrap span.blank,.swagger-section .swagger-ui-wrap span.empty{color:#888;font-style:italic}.swagger-section .swagger-ui-wrap .markdown h3{color:#547f00}.swagger-section .swagger-ui-wrap .markdown h4{color:#666}.swagger-section .swagger-ui-wrap .markdown pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;background-color:#fcf6db;border:1px solid #e5e0c6;padding:10px;margin:0 0 10px}.swagger-section .swagger-ui-wrap .markdown pre code{line-height:1.6em;overflow:auto}.swagger-section .swagger-ui-wrap div.gist{margin:20px 0 25px!important}.swagger-section .swagger-ui-wrap ul#resources{font-family:Droid Sans,sans-serif;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource{border-bottom:1px solid #ddd}.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading h2 a,.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading h2 a{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading ul.options li a,.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading ul.options li a{color:#555}.swagger-section .swagger-ui-wrap ul#resources li.resource:last-child{border-bottom:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading{border:1px solid transparent;float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options{overflow:hidden;padding:0;display:block;clear:none;float:right;margin:14px 10px 0 0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li{float:left;clear:none;margin:0;padding:2px 10px;border-right:1px solid #ddd;color:#666;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a{color:#aaa;text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover{text-decoration:underline;color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a.active,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:active,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.first,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:first-child{padding-left:0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options.first,.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options:first-child{padding-left:0}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2{color:#999;padding-left:0;display:block;clear:none;float:left;font-family:Droid Sans,sans-serif;font-weight:700}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a{color:#999}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation{float:none;clear:both;overflow:hidden;display:block;margin:0 0 10px;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading{float:none;clear:both;overflow:hidden;display:block;margin:0;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3{display:block;clear:none;float:left;width:auto;margin:0;padding:0;line-height:1.1em;color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path{padding-left:10px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a{color:#000;text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a.toggleOperation.deprecated{text-decoration:line-through}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.http_method a{text-transform:uppercase;text-decoration:none;color:#fff;display:inline-block;width:50px;font-size:.7em;text-align:center;padding:7px 0 4px;border-radius:2px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span{margin:0;padding:0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options{overflow:hidden;padding:0;display:block;clear:none;float:right;margin:6px 10px 0 0}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li{float:left;clear:none;margin:0;padding:2px 10px;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a{text-decoration:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a .markdown p{color:inherit;padding:0;line-height:inherit}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a .nickname{color:#aaa;padding:0;line-height:inherit}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li.access{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content{border-top:none;padding:10px;border-bottom-left-radius:6px;border-bottom-right-radius:6px;margin:0 0 20px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content h4{font-size:1.1em;margin:0;padding:15px 0 5px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header{float:none;clear:both;overflow:hidden;display:block}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header a{padding:4px 0 0 10px;display:inline-block;font-size:.9em}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit{display:block;clear:none;float:left;padding:6px 8px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header span.response_throbber{background-image:url(../images/throbber.gif);width:128px;height:16px;display:block;clear:none;float:right}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type=text].error{outline:2px solid #000;outline-color:#c00}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form select[name=parameterContentType]{max-width:300px}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.response div.block pre{font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;padding:10px;font-size:.9em;max-height:400px;overflow-y:auto}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading{background-color:#f9f2e9;border:1px solid #f0e0ca}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.http_method a{background-color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#f0e0ca;color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a{color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content{background-color:#faf5ee;border:1px solid #f0e0ca}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content h4{color:#c5862b}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header a{color:#dcb67f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading{background-color:#fcffcd;border:1px solid #000;border-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading h3 span.http_method a{text-transform:uppercase;background-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#ffd20f;color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li a{color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content{background-color:#fcffcd;border:1px solid #000;border-color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content h4{color:#ffd20f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content div.sandbox_header a{color:#6fc992}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading{background-color:#f5e8e8;border:1px solid #e8c6c7}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.http_method a{text-transform:uppercase;background-color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#e8c6c7;color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a{color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content{background-color:#f7eded;border:1px solid #e8c6c7}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content h4{color:#a41e22}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header a{color:#c8787a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading{background-color:#e7f6ec;border:1px solid #c3e8d1}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.http_method a{background-color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3e8d1;color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a{color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content{background-color:#ebf7f0;border:1px solid #c3e8d1}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content h4{color:#10a54a}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header a{color:#6fc992}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading{background-color:#fce9e3;border:1px solid #f5d5c3}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading h3 span.http_method a{background-color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#f0cecb;color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li a{color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content{background-color:#faf0ef;border:1px solid #f0cecb}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content h4{color:#d38042}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content div.sandbox_header a{color:#dcb67f}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading{background-color:#e7f0f7;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.http_method a{background-color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3d9ec;color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content{background-color:#ebf3f9;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content h4{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header a{color:#6fa5d2}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading{background-color:#e7f0f7;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading h3 span.http_method a{background-color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li{border-right:1px solid #ddd;border-right-color:#c3d9ec;color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li a{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content{background-color:#ebf3f9;border:1px solid #c3d9ec}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content h4{color:#0f6ab4}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content div.sandbox_header a{color:#6fa5d2}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content{border-top:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:last-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.last,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:last-child{padding-right:0;border-right:none}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a.active,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:active,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:hover{text-decoration:underline}.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations.first,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations:first-child,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li.first,.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li:first-child{padding-left:0}.swagger-section .swagger-ui-wrap p#colophon{margin:0 15px 40px;padding:10px 0;font-size:.8em;border-top:1px solid #ddd;font-family:Droid Sans,sans-serif;color:#999;font-style:italic}.swagger-section .swagger-ui-wrap p#colophon a{text-decoration:none;color:#547f00}.swagger-section .swagger-ui-wrap h3{color:#000;font-size:1.1em;padding:10px 0}.swagger-section .swagger-ui-wrap .markdown ol,.swagger-section .swagger-ui-wrap .markdown ul{font-family:Droid Sans,sans-serif;margin:5px 0 10px;padding:0 0 0 18px;list-style-type:disc}.swagger-section .swagger-ui-wrap form.form_box{background-color:#ebf3f9;border:1px solid #c3d9ec;padding:10px}.swagger-section .swagger-ui-wrap form.form_box label{color:#0f6ab4!important}.swagger-section .swagger-ui-wrap form.form_box input[type=submit]{display:block;padding:10px}.swagger-section .swagger-ui-wrap form.form_box p.weak{font-size:.8em}.swagger-section .swagger-ui-wrap form.form_box p{font-size:.9em;padding:0 0 15px;color:#7e7b6d}.swagger-section .swagger-ui-wrap form.form_box p a{color:#646257}.swagger-section .swagger-ui-wrap form.form_box p strong{color:#000}.swagger-section .swagger-ui-wrap .operation-status td.markdown>p:last-child{padding-bottom:0}.swagger-section .title{font-style:bold}.swagger-section .secondary_form{display:none}.swagger-section .main_image{display:block;margin-left:auto;margin-right:auto}.swagger-section .oauth_body{margin-left:100px;margin-right:100px}.swagger-section .oauth_submit{text-align:center;display:inline-block}.swagger-section .authorize-wrapper{margin:15px 0 10px}.swagger-section .authorize-wrapper_operation{float:right}.swagger-section .authorize__btn:hover{text-decoration:underline;cursor:pointer}.swagger-section .authorize__btn_operation:hover .authorize-scopes{display:block}.swagger-section .authorize-scopes{position:absolute;margin-top:20px;background:#fff;border:1px solid #ccc;border-radius:5px;display:none;font-size:13px;max-width:300px;line-height:30px;color:#000;padding:5px}.swagger-section .authorize-scopes .authorize__scope{text-decoration:none}.swagger-section .authorize__btn_operation{height:18px;vertical-align:middle;display:inline-block;background:url(../images/explorer_icons.png) no-repeat}.swagger-section .authorize__btn_operation_login{background-position:0 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section .authorize__btn_operation_logout{background-position:-30px 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section #auth_container{color:#fff;display:inline-block;border:none;padding:5px;width:87px;height:13px}.swagger-section #auth_container .authorize__btn{color:#fff}.swagger-section .auth_container{padding:0 0 10px;margin-bottom:5px;border-bottom:1px solid #ccc;font-size:.9em}.swagger-section .auth_container .auth__title{color:#547f00;font-size:1.2em}.swagger-section .auth_container .basic_auth__label{display:inline-block;width:60px}.swagger-section .auth_container .auth__description{color:#999;margin-bottom:5px}.swagger-section .auth_container .auth__button{margin-top:10px;height:30px}.swagger-section .auth_container .key_auth__field{margin:5px 0}.swagger-section .auth_container .key_auth__label{display:inline-block;width:60px}.swagger-section .api-popup-dialog{position:absolute;display:none}.swagger-section .api-popup-dialog-wrapper{z-index:2;width:500px;background:#fff;padding:20px;border:1px solid #ccc;border-radius:5px;font-size:13px;color:#777;position:fixed;top:50%;left:50%;transform:translate(-50%,-50%)}.swagger-section .api-popup-dialog-shadow{position:fixed;top:0;left:0;width:100%;height:100%;opacity:.2;background-color:gray;z-index:1}.swagger-section .api-popup-dialog .api-popup-title{font-size:24px;padding:10px 0}.swagger-section .api-popup-dialog .error-msg{padding-left:5px;padding-bottom:5px}.swagger-section .api-popup-dialog .api-popup-content{max-height:500px;overflow-y:auto}.swagger-section .api-popup-dialog .api-popup-authbtn,.swagger-section .api-popup-dialog .api-popup-cancel{height:30px}.swagger-section .api-popup-scopes{padding:10px 20px}.swagger-section .api-popup-scopes li{padding:5px 0;line-height:20px}.swagger-section .api-popup-scopes li input{position:relative;top:2px}.swagger-section .api-popup-scopes .api-scope-desc{padding-left:20px;font-style:italic}.swagger-section .api-popup-actions{padding-top:10px}.swagger-section fieldset{padding-bottom:10px;padding-left:20px}.swagger-section .access,.swagger-section .auth{float:right}.swagger-section .api-ic{height:18px;vertical-align:middle;display:inline-block;background:url(../images/explorer_icons.png) no-repeat}.swagger-section .api-ic .api_information_panel{position:relative;margin-top:20px;margin-left:-5px;background:#fff;border:1px solid #ccc;border-radius:5px;display:none;font-size:13px;max-width:300px;line-height:30px;color:#000;padding:5px}.swagger-section .api-ic .api_information_panel p .api-msg-enabled{color:green}.swagger-section .api-ic .api_information_panel p .api-msg-disabled{color:red}.swagger-section .api-ic:hover .api_information_panel{position:absolute;display:block}.swagger-section .ic-info{background-position:0 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section .ic-warning{background-position:-60px 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section .ic-error{background-position:-30px 0;width:18px;margin-top:-6px;margin-left:4px}.swagger-section .ic-off{background-position:-90px 0;width:58px;margin-top:-4px;cursor:pointer}.swagger-section .ic-on{background-position:-160px 0;width:58px;margin-top:-4px;cursor:pointer}.swagger-section #header{background-color:#89bf04;padding:9px 14px 19px;height:23px;min-width:775px}.swagger-section #input_baseUrl{width:400px}.swagger-section #api_selector{display:block;clear:none;float:right}.swagger-section #api_selector .input{display:inline-block;clear:none;margin:0 10px 0 0}.swagger-section #api_selector input{font-size:.9em;padding:3px;margin:0}.swagger-section #input_apiKey{width:200px}.swagger-section #auth_container .authorize__btn,.swagger-section #explore{display:block;text-decoration:none;font-weight:700;padding:6px 8px;font-size:.9em;color:#fff;background-color:#547f00;border-radius:4px}.swagger-section #auth_container .authorize__btn:hover,.swagger-section #explore:hover{background-color:#547f00}.swagger-section #header #logo{font-size:1.5em;font-weight:700;text-decoration:none;color:#fff}.swagger-section #header #logo .logo__img{display:block;float:left;margin-top:2px}.swagger-section #header #logo .logo__title{display:inline-block;padding:5px 0 0 10px}.swagger-section #content_message{margin:10px 15px;font-style:italic;color:#999}.swagger-section #message-bar{min-height:30px;text-align:center;padding-top:10px}.swagger-section .swagger-collapse:before{content:\"-\"}.swagger-section .swagger-expand:before{content:\"+\"}.swagger-section .error{outline-color:#c00;background-color:#f2dede}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/css/style.css",
    "content": ".swagger-section #header a#logo{font-size:1.5em;font-weight:700;text-decoration:none;padding:20px 0 20px 40px}#text-head{font-size:80px;font-family:Roboto,sans-serif;color:#fff;float:right;margin-right:20%}.navbar-fixed-top .navbar-brand,.navbar-fixed-top .navbar-nav,.navbar-header{height:auto}.navbar-inverse{background-color:#000;border-color:#000}#navbar-brand{margin-left:20%}.navtext{font-size:10px}.h1,h1{font-size:60px}.navbar-default .navbar-header .navbar-brand{color:#a2dfee}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a{color:#393939;font-family:Arvo,serif;font-size:1.5em}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover{color:#000}.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2{color:#525252;padding-left:0;display:block;clear:none;float:left;font-family:Arvo,serif;font-weight:700}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#0a0a0a}.container1{width:1500px;margin:auto;margin-top:0;background-repeat:no-repeat;background-position:-40px -20px;margin-bottom:210px}.container-inner{width:1200px;margin:auto;background-color:hsla(192,8%,88%,.75);padding-bottom:40px;padding-top:40px;border-radius:15px}.header-content{padding:0;width:1000px}.title1{font-size:80px;font-family:Vollkorn,serif;color:#404040;text-align:center;padding-top:40px;padding-bottom:100px}#icon{margin-top:-18px}.subtext{font-size:25px;font-style:italic;color:#08b;text-align:right;padding-right:250px}.bg-primary{background-color:#00468b}.navbar-default .nav>li>a,.navbar-default .nav>li>a:focus,.navbar-default .nav>li>a:focus:hover,.navbar-default .nav>li>a:hover{color:#08b}.text-faded{font-size:25px;font-family:Vollkorn,serif}.section-heading{font-family:Vollkorn,serif;font-size:45px;padding-bottom:10px}hr{border-color:#00468b;padding-bottom:10px}.description{margin-top:20px;padding-bottom:200px}.description li{font-family:Vollkorn,serif;font-size:25px;color:#525252;margin-left:28%;padding-top:5px}.gap{margin-top:200px}.troubleshootingtext{color:hsla(0,0%,100%,.7);padding-left:30%}.troubleshootingtext li{list-style-type:circle;font-size:25px;padding-bottom:5px}.overlay{position:absolute;top:0;left:0;width:100%;height:100%;z-index:1}.block.response_body.json:hover{cursor:pointer}.backdrop{color:blue}#myModal{height:100%}.modal-backdrop{bottom:0;position:fixed}.curl{padding:10px;font-family:Anonymous Pro,Menlo,Consolas,Bitstream Vera Sans Mono,Courier New,monospace;font-size:.9em;max-height:400px;margin-top:5px;overflow-y:auto;background-color:#fcf6db;border:1px solid #e5e0c6;border-radius:4px}.curl_title{font-size:1.1em;margin:0;padding:15px 0 5px;font-family:Open Sans,Helvetica Neue,Arial,sans-serif;font-weight:500;line-height:1.1}.footer{display:none}.swagger-section .swagger-ui-wrap h2{padding:0}h2{margin:0;margin-bottom:5px}.markdown p,.swagger-section .swagger-ui-wrap .code{font-size:15px;font-family:Arvo,serif}.swagger-section .swagger-ui-wrap b{font-family:Arvo,serif}#signin:hover{cursor:pointer}.dropdown-menu{padding:15px}.navbar-right .dropdown-menu{left:0;right:auto}#signinbutton{width:100%;height:32px;font-size:13px;font-weight:700;color:#08b}.navbar-default .nav>li .details{color:#000;text-transform:none;font-size:15px;font-weight:400;font-family:Open Sans,sans-serif;font-style:italic;line-height:20px;top:-2px}.navbar-default .nav>li .details:hover{color:#000}#signout{width:100%;height:32px;font-size:13px;font-weight:700;color:#08b}"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/css/typography.css",
    "content": ""
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"UTF-8\">\n  <meta http-equiv=\"x-ua-compatible\" content=\"IE=edge\">\n  <title>Swagger UI</title>\n  <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-32x32.png\" sizes=\"32x32\" />\n  <link rel=\"icon\" type=\"image/png\" href=\"images/favicon-16x16.png\" sizes=\"16x16\" />\n  <link href='css/typography.css' media='screen' rel='stylesheet' type='text/css'/>\n  <link href='css/reset.css' media='screen' rel='stylesheet' type='text/css'/>\n  <link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>\n  <link href='css/reset.css' media='print' rel='stylesheet' type='text/css'/>\n  <link href='css/print.css' media='print' rel='stylesheet' type='text/css'/>\n\n  <script src='lib/object-assign-pollyfill.js' type='text/javascript'></script>\n  <script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>\n  <script src='lib/jquery.slideto.min.js' type='text/javascript'></script>\n  <script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>\n  <script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>\n  <script src='lib/handlebars-4.0.5.js' type='text/javascript'></script>\n  <script src='lib/lodash.min.js' type='text/javascript'></script>\n  <script src='lib/backbone-min.js' type='text/javascript'></script>\n  <script src='swagger-ui.js' type='text/javascript'></script>\n  <script src='lib/highlight.9.1.0.pack.js' type='text/javascript'></script>\n  <script src='lib/highlight.9.1.0.pack_extended.js' type='text/javascript'></script>\n  <script src='lib/jsoneditor.min.js' type='text/javascript'></script>\n  <script src='lib/marked.js' type='text/javascript'></script>\n  <script src='lib/swagger-oauth.js' type='text/javascript'></script>\n\n  <!-- Some basic translations -->\n  <!-- <script src='lang/translator.js' type='text/javascript'></script> -->\n  <!-- <script src='lang/en.js' type='text/javascript'></script> -->\n\n  <script type=\"text/javascript\">\n    $(function () {\n      var url = window.location.search.match(/url=([^&]+)/);\n      if (url && url.length > 1) {\n        url = decodeURIComponent(url[1]);\n      } else {\n        url = \"http://localhost:8888/v2/api-docs\";\n      }\n\n      hljs.configure({\n        highlightSizeThreshold: 5000\n      });\n\n      // Pre load translate...\n      if(window.SwaggerTranslator) {\n        window.SwaggerTranslator.translate();\n      }\n      window.swaggerUi = new SwaggerUi({\n        url: url,\n        dom_id: \"swagger-ui-container\",\n        supportedSubmitMethods: ['get', 'post', 'put', 'delete', 'patch'],\n        onComplete: function(swaggerApi, swaggerUi){\n          if(typeof initOAuth == \"function\") {\n            initOAuth({\n              clientId: \"your-client-id\",\n              clientSecret: \"your-client-secret-if-required\",\n              realm: \"your-realms\",\n              appName: \"your-app-name\",\n              scopeSeparator: \" \",\n              additionalQueryStringParams: {}\n            });\n          }\n\n          if(window.SwaggerTranslator) {\n            window.SwaggerTranslator.translate();\n          }\n        },\n        onFailure: function(data) {\n          log(\"Unable to Load SwaggerUI\");\n        },\n        docExpansion: \"none\",\n        jsonEditor: false,\n        defaultModelRendering: 'schema',\n        showRequestHeaders: false,\n        showOperationIds: false\n      });\n\n      window.swaggerUi.load();\n\n      function log() {\n        if ('console' in window) {\n          console.log.apply(console, arguments);\n        }\n      }\n  });\n  </script>\n</head>\n\n<body class=\"swagger-section\">\n<div id='header'>\n  <div class=\"swagger-ui-wrap\">\n    <a id=\"logo\" href=\"http://swagger.io\"><img class=\"logo__img\" alt=\"swagger\" height=\"30\" width=\"30\" src=\"images/logo_small.png\" /><span class=\"logo__title\">swagger</span></a>\n    <form id='api_selector'>\n      <div class='input'><input placeholder=\"http://example.com/api\" id=\"input_baseUrl\" name=\"baseUrl\" type=\"text\"/></div>\n      <div id='auth_container'></div>\n      <div class='input'><a id=\"explore\" class=\"header__btn\" href=\"#\" data-sw-translate>Explore</a></div>\n    </form>\n  </div>\n</div>\n\n<div id=\"message-bar\" class=\"swagger-ui-wrap\" data-sw-translate>&nbsp;</div>\n<div id=\"swagger-ui-container\" class=\"swagger-ui-wrap\"></div>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/el.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Προειδοποίηση: Έχει αποσυρθεί\",\n    \"Implementation Notes\":\"Σημειώσεις Υλοποίησης\",\n    \"Response Class\":\"Απόκριση\",\n    \"Status\":\"Κατάσταση\",\n    \"Parameters\":\"Παράμετροι\",\n    \"Parameter\":\"Παράμετρος\",\n    \"Value\":\"Τιμή\",\n    \"Description\":\"Περιγραφή\",\n    \"Parameter Type\":\"Τύπος Παραμέτρου\",\n    \"Data Type\":\"Τύπος Δεδομένων\",\n    \"Response Messages\":\"Μηνύματα Απόκρισης\",\n    \"HTTP Status Code\":\"Κωδικός Κατάστασης HTTP\",\n    \"Reason\":\"Αιτιολογία\",\n    \"Response Model\":\"Μοντέλο Απόκρισης\",\n    \"Request URL\":\"URL Αιτήματος\",\n    \"Response Body\":\"Σώμα Απόκρισης\",\n    \"Response Code\":\"Κωδικός Απόκρισης\",\n    \"Response Headers\":\"Επικεφαλίδες Απόκρισης\",\n    \"Hide Response\":\"Απόκρυψη Απόκρισης\",\n    \"Headers\":\"Επικεφαλίδες\",\n    \"Try it out!\":\"Δοκιμάστε το!\",\n    \"Show/Hide\":\"Εμφάνιση/Απόκρυψη\",\n    \"List Operations\":\"Λίστα Λειτουργιών\",\n    \"Expand Operations\":\"Ανάπτυξη Λειτουργιών\",\n    \"Raw\":\"Ακατέργαστο\",\n    \"can't parse JSON.  Raw result\":\"αδυναμία ανάλυσης JSON.  Ακατέργαστο αποτέλεσμα\",\n    \"Example Value\":\"Παράδειγμα Τιμής\",\n    \"Model Schema\":\"Σχήμα Μοντέλου\",\n    \"Model\":\"Μοντέλο\",\n    \"Click to set as parameter value\":\"Πατήστε για να θέσετε τιμή παραμέτρου\",\n    \"apply\":\"εφαρμογή\",\n    \"Username\":\"Όνομα χρήση\",\n    \"Password\":\"Κωδικός πρόσβασης\",\n    \"Terms of service\":\"Όροι χρήσης\",\n    \"Created by\":\"Δημιουργήθηκε από\",\n    \"See more at\":\"Δείτε περισσότερα στο\",\n    \"Contact the developer\":\"Επικοινωνήστε με τον προγραμματιστή\",\n    \"api version\":\"έκδοση api\",\n    \"Response Content Type\":\"Τύπος Περιεχομένου Απόκρισης\",\n    \"Parameter content type:\":\"Τύπος περιεχομένου παραμέτρου:\",\n    \"fetching resource\":\"παραλαβή πόρου\",\n    \"fetching resource list\":\"παραλαβή λίστας πόρων\",\n    \"Explore\":\"Εξερεύνηση\",\n    \"Show Swagger Petstore Example Apis\":\"Εμφάνιση Api Δειγμάτων Petstore του Swagger\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"Αδυναμία ανάγνωσης από τον εξυπηρετητή.  Μπορεί να μην έχει κατάλληλες ρυθμίσεις για access-control-origin.\",\n    \"Please specify the protocol for\":\"Παρακαλώ προσδιορίστε το πρωτόκολλο για\",\n    \"Can't read swagger JSON from\":\"Αδυναμία ανάγνωσης swagger JSON από\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"Ολοκλήρωση Φόρτωσης Πληροφορικών Πόρου. Παρουσίαση Swagger UI\",\n    \"Unable to read api\":\"Αδυναμία ανάγνωσης api\",\n    \"from path\":\"από το μονοπάτι\",\n    \"server returned\":\"ο εξυπηρετηρής επέστρεψε\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/en.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Warning: Deprecated\",\n    \"Implementation Notes\":\"Implementation Notes\",\n    \"Response Class\":\"Response Class\",\n    \"Status\":\"Status\",\n    \"Parameters\":\"Parameters\",\n    \"Parameter\":\"Parameter\",\n    \"Value\":\"Value\",\n    \"Description\":\"Description\",\n    \"Parameter Type\":\"Parameter Type\",\n    \"Data Type\":\"Data Type\",\n    \"Response Messages\":\"Response Messages\",\n    \"HTTP Status Code\":\"HTTP Status Code\",\n    \"Reason\":\"Reason\",\n    \"Response Model\":\"Response Model\",\n    \"Request URL\":\"Request URL\",\n    \"Response Body\":\"Response Body\",\n    \"Response Code\":\"Response Code\",\n    \"Response Headers\":\"Response Headers\",\n    \"Hide Response\":\"Hide Response\",\n    \"Headers\":\"Headers\",\n    \"Try it out!\":\"Try it out!\",\n    \"Show/Hide\":\"Show/Hide\",\n    \"List Operations\":\"List Operations\",\n    \"Expand Operations\":\"Expand Operations\",\n    \"Raw\":\"Raw\",\n    \"can't parse JSON.  Raw result\":\"can't parse JSON.  Raw result\",\n    \"Example Value\":\"Example Value\",\n    \"Model Schema\":\"Model Schema\",\n    \"Model\":\"Model\",\n    \"Click to set as parameter value\":\"Click to set as parameter value\",\n    \"apply\":\"apply\",\n    \"Username\":\"Username\",\n    \"Password\":\"Password\",\n    \"Terms of service\":\"Terms of service\",\n    \"Created by\":\"Created by\",\n    \"See more at\":\"See more at\",\n    \"Contact the developer\":\"Contact the developer\",\n    \"api version\":\"api version\",\n    \"Response Content Type\":\"Response Content Type\",\n    \"Parameter content type:\":\"Parameter content type:\",\n    \"fetching resource\":\"fetching resource\",\n    \"fetching resource list\":\"fetching resource list\",\n    \"Explore\":\"Explore\",\n    \"Show Swagger Petstore Example Apis\":\"Show Swagger Petstore Example Apis\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"Can't read from server.  It may not have the appropriate access-control-origin settings.\",\n    \"Please specify the protocol for\":\"Please specify the protocol for\",\n    \"Can't read swagger JSON from\":\"Can't read swagger JSON from\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"Finished Loading Resource Information. Rendering Swagger UI\",\n    \"Unable to read api\":\"Unable to read api\",\n    \"from path\":\"from path\",\n    \"server returned\":\"server returned\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/es.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Advertencia: Obsoleto\",\n    \"Implementation Notes\":\"Notas de implementación\",\n    \"Response Class\":\"Clase de la Respuesta\",\n    \"Status\":\"Status\",\n    \"Parameters\":\"Parámetros\",\n    \"Parameter\":\"Parámetro\",\n    \"Value\":\"Valor\",\n    \"Description\":\"Descripción\",\n    \"Parameter Type\":\"Tipo del Parámetro\",\n    \"Data Type\":\"Tipo del Dato\",\n    \"Response Messages\":\"Mensajes de la Respuesta\",\n    \"HTTP Status Code\":\"Código de Status HTTP\",\n    \"Reason\":\"Razón\",\n    \"Response Model\":\"Modelo de la Respuesta\",\n    \"Request URL\":\"URL de la Solicitud\",\n    \"Response Body\":\"Cuerpo de la Respuesta\",\n    \"Response Code\":\"Código de la Respuesta\",\n    \"Response Headers\":\"Encabezados de la Respuesta\",\n    \"Hide Response\":\"Ocultar Respuesta\",\n    \"Try it out!\":\"Pruébalo!\",\n    \"Show/Hide\":\"Mostrar/Ocultar\",\n    \"List Operations\":\"Listar Operaciones\",\n    \"Expand Operations\":\"Expandir Operaciones\",\n    \"Raw\":\"Crudo\",\n    \"can't parse JSON.  Raw result\":\"no puede parsear el JSON.  Resultado crudo\",\n    \"Example Value\":\"Valor de Ejemplo\",\n    \"Model Schema\":\"Esquema del Modelo\",\n    \"Model\":\"Modelo\",\n    \"apply\":\"aplicar\",\n    \"Username\":\"Nombre de usuario\",\n    \"Password\":\"Contraseña\",\n    \"Terms of service\":\"Términos de Servicio\",\n    \"Created by\":\"Creado por\",\n    \"See more at\":\"Ver más en\",\n    \"Contact the developer\":\"Contactar al desarrollador\",\n    \"api version\":\"versión de la api\",\n    \"Response Content Type\":\"Tipo de Contenido (Content Type) de la Respuesta\",\n    \"fetching resource\":\"buscando recurso\",\n    \"fetching resource list\":\"buscando lista del recurso\",\n    \"Explore\":\"Explorar\",\n    \"Show Swagger Petstore Example Apis\":\"Mostrar Api Ejemplo de Swagger Petstore\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"No se puede leer del servidor. Tal vez no tiene la configuración de control de acceso de origen (access-control-origin) apropiado.\",\n    \"Please specify the protocol for\":\"Por favor, especificar el protocola para\",\n    \"Can't read swagger JSON from\":\"No se puede leer el JSON de swagger desde\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"Finalizada la carga del recurso de Información. Mostrando Swagger UI\",\n    \"Unable to read api\":\"No se puede leer la api\",\n    \"from path\":\"desde ruta\",\n    \"server returned\":\"el servidor retornó\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/fr.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Avertissement : Obsolète\",\n    \"Implementation Notes\":\"Notes d'implémentation\",\n    \"Response Class\":\"Classe de la réponse\",\n    \"Status\":\"Statut\",\n    \"Parameters\":\"Paramètres\",\n    \"Parameter\":\"Paramètre\",\n    \"Value\":\"Valeur\",\n    \"Description\":\"Description\",\n    \"Parameter Type\":\"Type du paramètre\",\n    \"Data Type\":\"Type de données\",\n    \"Response Messages\":\"Messages de la réponse\",\n    \"HTTP Status Code\":\"Code de statut HTTP\",\n    \"Reason\":\"Raison\",\n    \"Response Model\":\"Modèle de réponse\",\n    \"Request URL\":\"URL appelée\",\n    \"Response Body\":\"Corps de la réponse\",\n    \"Response Code\":\"Code de la réponse\",\n    \"Response Headers\":\"En-têtes de la réponse\",\n    \"Hide Response\":\"Cacher la réponse\",\n    \"Headers\":\"En-têtes\",\n    \"Try it out!\":\"Testez !\",\n    \"Show/Hide\":\"Afficher/Masquer\",\n    \"List Operations\":\"Liste des opérations\",\n    \"Expand Operations\":\"Développer les opérations\",\n    \"Raw\":\"Brut\",\n    \"can't parse JSON.  Raw result\":\"impossible de décoder le JSON.  Résultat brut\",\n    \"Example Value\":\"Exemple la valeur\",\n    \"Model Schema\":\"Définition du modèle\",\n    \"Model\":\"Modèle\",\n    \"apply\":\"appliquer\",\n    \"Username\":\"Nom d'utilisateur\",\n    \"Password\":\"Mot de passe\",\n    \"Terms of service\":\"Conditions de service\",\n    \"Created by\":\"Créé par\",\n    \"See more at\":\"Voir plus sur\",\n    \"Contact the developer\":\"Contacter le développeur\",\n    \"api version\":\"version de l'api\",\n    \"Response Content Type\":\"Content Type de la réponse\",\n    \"fetching resource\":\"récupération de la ressource\",\n    \"fetching resource list\":\"récupération de la liste de ressources\",\n    \"Explore\":\"Explorer\",\n    \"Show Swagger Petstore Example Apis\":\"Montrer les Apis de l'exemple Petstore de Swagger\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"Impossible de lire à partir du serveur. Il se peut que les réglages access-control-origin ne soient pas appropriés.\",\n    \"Please specify the protocol for\":\"Veuillez spécifier un protocole pour\",\n    \"Can't read swagger JSON from\":\"Impossible de lire le JSON swagger à partir de\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"Chargement des informations terminé. Affichage de Swagger UI\",\n    \"Unable to read api\":\"Impossible de lire l'api\",\n    \"from path\":\"à partir du chemin\",\n    \"server returned\":\"réponse du serveur\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/geo.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"ყურადღება: აღარ გამოიყენება\",\n    \"Implementation Notes\":\"იმპლემენტაციის აღწერა\",\n    \"Response Class\":\"რესპონს კლასი\",\n    \"Status\":\"სტატუსი\",\n    \"Parameters\":\"პარამეტრები\",\n    \"Parameter\":\"პარამეტრი\",\n    \"Value\":\"მნიშვნელობა\",\n    \"Description\":\"აღწერა\",\n    \"Parameter Type\":\"პარამეტრის ტიპი\",\n    \"Data Type\":\"მონაცემის ტიპი\",\n    \"Response Messages\":\"პასუხი\",\n    \"HTTP Status Code\":\"HTTP სტატუსი\",\n    \"Reason\":\"მიზეზი\",\n    \"Response Model\":\"რესპონს მოდელი\",\n    \"Request URL\":\"მოთხოვნის URL\",\n    \"Response Body\":\"პასუხის სხეული\",\n    \"Response Code\":\"პასუხის კოდი\",\n    \"Response Headers\":\"პასუხის ჰედერები\",\n    \"Hide Response\":\"დამალე პასუხი\",\n    \"Headers\":\"ჰედერები\",\n    \"Try it out!\":\"ცადე !\",\n    \"Show/Hide\":\"გამოჩენა/დამალვა\",\n    \"List Operations\":\"ოპერაციების სია\",\n    \"Expand Operations\":\"ოპერაციები ვრცლად\",\n    \"Raw\":\"ნედლი\",\n    \"can't parse JSON.  Raw result\":\"JSON-ის დამუშავება ვერ მოხერხდა.  ნედლი პასუხი\",\n    \"Example Value\":\"მაგალითი\",\n    \"Model Schema\":\"მოდელის სტრუქტურა\",\n    \"Model\":\"მოდელი\",\n    \"Click to set as parameter value\":\"პარამეტრისთვის მნიშვნელობის მისანიჭებლად, დააკლიკე\",\n    \"apply\":\"გამოყენება\",\n    \"Username\":\"მოხმარებელი\",\n    \"Password\":\"პაროლი\",\n    \"Terms of service\":\"მომსახურების პირობები\",\n    \"Created by\":\"შექმნა\",\n    \"See more at\":\"ნახე ვრცლად\",\n    \"Contact the developer\":\"დაუკავშირდი დეველოპერს\",\n    \"api version\":\"api ვერსია\",\n    \"Response Content Type\":\"პასუხის კონტენტის ტიპი\",\n    \"Parameter content type:\":\"პარამეტრის კონტენტის ტიპი:\",\n    \"fetching resource\":\"რესურსების მიღება\",\n    \"fetching resource list\":\"რესურსების სიის მიღება\",\n    \"Explore\":\"ნახვა\",\n    \"Show Swagger Petstore Example Apis\":\"ნახე Swagger Petstore სამაგალითო Api\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"სერვერთან დაკავშირება ვერ ხერხდება.  შეამოწმეთ access-control-origin.\",\n    \"Please specify the protocol for\":\"მიუთითეთ პროტოკოლი\",\n    \"Can't read swagger JSON from\":\"swagger JSON წაკითხვა ვერ მოხერხდა\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"რესურსების ჩატვირთვა სრულდება. Swagger UI რენდერდება\",\n    \"Unable to read api\":\"api წაკითხვა ვერ მოხერხდა\",\n    \"from path\":\"მისამართიდან\",\n    \"server returned\":\"სერვერმა დააბრუნა\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/it.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Attenzione: Deprecato\",\n    \"Implementation Notes\":\"Note di implementazione\",\n    \"Response Class\":\"Classe della risposta\",\n    \"Status\":\"Stato\",\n    \"Parameters\":\"Parametri\",\n    \"Parameter\":\"Parametro\",\n    \"Value\":\"Valore\",\n    \"Description\":\"Descrizione\",\n    \"Parameter Type\":\"Tipo di parametro\",\n    \"Data Type\":\"Tipo di dato\",\n    \"Response Messages\":\"Messaggi della risposta\",\n    \"HTTP Status Code\":\"Codice stato HTTP\",\n    \"Reason\":\"Motivo\",\n    \"Response Model\":\"Modello di risposta\",\n    \"Request URL\":\"URL della richiesta\",\n    \"Response Body\":\"Corpo della risposta\",\n    \"Response Code\":\"Oggetto della risposta\",\n    \"Response Headers\":\"Intestazioni della risposta\",\n    \"Hide Response\":\"Nascondi risposta\",\n    \"Try it out!\":\"Provalo!\",\n    \"Show/Hide\":\"Mostra/Nascondi\",\n    \"List Operations\":\"Mostra operazioni\",\n    \"Expand Operations\":\"Espandi operazioni\",\n    \"Raw\":\"Grezzo (raw)\",\n    \"can't parse JSON.  Raw result\":\"non è possibile parsare il JSON. Risultato grezzo (raw).\",\n    \"Model Schema\":\"Schema del modello\",\n    \"Model\":\"Modello\",\n    \"apply\":\"applica\",\n    \"Username\":\"Nome utente\",\n    \"Password\":\"Password\",\n    \"Terms of service\":\"Condizioni del servizio\",\n    \"Created by\":\"Creato da\",\n    \"See more at\":\"Informazioni aggiuntive:\",\n    \"Contact the developer\":\"Contatta lo sviluppatore\",\n    \"api version\":\"versione api\",\n    \"Response Content Type\":\"Tipo di contenuto (content type) della risposta\",\n    \"fetching resource\":\"recuperando la risorsa\",\n    \"fetching resource list\":\"recuperando lista risorse\",\n    \"Explore\":\"Esplora\",\n    \"Show Swagger Petstore Example Apis\":\"Mostra le api di esempio di Swagger Petstore\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"Non è possibile leggere dal server. Potrebbe non avere le impostazioni di controllo accesso origine (access-control-origin) appropriate.\",\n    \"Please specify the protocol for\":\"Si prega di specificare il protocollo per\",\n    \"Can't read swagger JSON from\":\"Impossibile leggere JSON swagger da:\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"Lettura informazioni risorse termianta. Swagger UI viene mostrata\",\n    \"Unable to read api\":\"Impossibile leggere la api\",\n    \"from path\":\"da cartella\",\n    \"server returned\":\"il server ha restituito\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/ja.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"警告: 廃止予定\",\n    \"Implementation Notes\":\"実装メモ\",\n    \"Response Class\":\"レスポンスクラス\",\n    \"Status\":\"ステータス\",\n    \"Parameters\":\"パラメータ群\",\n    \"Parameter\":\"パラメータ\",\n    \"Value\":\"値\",\n    \"Description\":\"説明\",\n    \"Parameter Type\":\"パラメータタイプ\",\n    \"Data Type\":\"データタイプ\",\n    \"Response Messages\":\"レスポンスメッセージ\",\n    \"HTTP Status Code\":\"HTTPステータスコード\",\n    \"Reason\":\"理由\",\n    \"Response Model\":\"レスポンスモデル\",\n    \"Request URL\":\"リクエストURL\",\n    \"Response Body\":\"レスポンスボディ\",\n    \"Response Code\":\"レスポンスコード\",\n    \"Response Headers\":\"レスポンスヘッダ\",\n    \"Hide Response\":\"レスポンスを隠す\",\n    \"Headers\":\"ヘッダ\",\n    \"Try it out!\":\"実際に実行!\",\n    \"Show/Hide\":\"表示/非表示\",\n    \"List Operations\":\"操作一覧\",\n    \"Expand Operations\":\"操作の展開\",\n    \"Raw\":\"未加工\",\n    \"can't parse JSON.  Raw result\":\"JSONへ解釈できません.  未加工の結果\",\n    \"Example Value\":\"値の例\",\n    \"Model Schema\":\"モデルスキーマ\",\n    \"Model\":\"モデル\",\n    \"Click to set as parameter value\":\"パラメータ値と設定するにはクリック\",\n    \"apply\":\"実行\",\n    \"Username\":\"ユーザ名\",\n    \"Password\":\"パスワード\",\n    \"Terms of service\":\"サービス利用規約\",\n    \"Created by\":\"Created by\",\n    \"See more at\":\"詳細を見る\",\n    \"Contact the developer\":\"開発者に連絡\",\n    \"api version\":\"APIバージョン\",\n    \"Response Content Type\":\"レスポンス コンテンツタイプ\",\n    \"Parameter content type:\":\"パラメータコンテンツタイプ:\",\n    \"fetching resource\":\"リソースの取得\",\n    \"fetching resource list\":\"リソース一覧の取得\",\n    \"Explore\":\"調査\",\n    \"Show Swagger Petstore Example Apis\":\"SwaggerペットストアAPIの表示\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"サーバから読み込めません.  適切なaccess-control-origin設定を持っていない可能性があります.\",\n    \"Please specify the protocol for\":\"プロトコルを指定してください\",\n    \"Can't read swagger JSON from\":\"次からswagger JSONを読み込めません\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"リソース情報の読み込みが完了しました. Swagger UIを描画しています\",\n    \"Unable to read api\":\"APIを読み込めません\",\n    \"from path\":\"次のパスから\",\n    \"server returned\":\"サーバからの返答\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/ko-kr.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"경고：폐기예정됨\",\n    \"Implementation Notes\":\"구현 노트\",\n    \"Response Class\":\"응답 클래스\",\n    \"Status\":\"상태\",\n    \"Parameters\":\"매개변수들\",\n    \"Parameter\":\"매개변수\",\n    \"Value\":\"값\",\n    \"Description\":\"설명\",\n    \"Parameter Type\":\"매개변수 타입\",\n    \"Data Type\":\"데이터 타입\",\n    \"Response Messages\":\"응답 메세지\",\n    \"HTTP Status Code\":\"HTTP 상태 코드\",\n    \"Reason\":\"원인\",\n    \"Response Model\":\"응답 모델\",\n    \"Request URL\":\"요청 URL\",\n    \"Response Body\":\"응답 본문\",\n    \"Response Code\":\"응답 코드\",\n    \"Response Headers\":\"응답 헤더\",\n    \"Hide Response\":\"응답 숨기기\",\n    \"Headers\":\"헤더\",\n    \"Try it out!\":\"써보기！\",\n    \"Show/Hide\":\"보이기/숨기기\",\n    \"List Operations\":\"목록 작업\",\n    \"Expand Operations\":\"전개 작업\",\n    \"Raw\":\"원본\",\n    \"can't parse JSON.  Raw result\":\"JSON을 파싱할수 없음. 원본결과:\",\n    \"Model Schema\":\"모델 스키마\",\n    \"Model\":\"모델\",\n    \"apply\":\"적용\",\n    \"Username\":\"사용자 이름\",\n    \"Password\":\"암호\",\n    \"Terms of service\":\"이용약관\",\n    \"Created by\":\"작성자\",\n    \"See more at\":\"추가정보：\",\n    \"Contact the developer\":\"개발자에게 문의\",\n    \"api version\":\"api버전\",\n    \"Response Content Type\":\"응답Content Type\",\n    \"fetching resource\":\"리소스 가져오기\",\n    \"fetching resource list\":\"리소스 목록 가져오기\",\n    \"Explore\":\"탐색\",\n    \"Show Swagger Petstore Example Apis\":\"Swagger Petstore 예제 보기\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"서버로부터 읽어들일수 없습니다. access-control-origin 설정이 올바르지 않을수 있습니다.\",\n    \"Please specify the protocol for\":\"다음을 위한 프로토콜을 정하세요\",\n    \"Can't read swagger JSON from\":\"swagger JSON 을 다음으로 부터 읽을수 없습니다\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"리소스 정보 불러오기 완료. Swagger UI 랜더링\",\n    \"Unable to read api\":\"api를 읽을 수 없습니다.\",\n    \"from path\":\"다음 경로로 부터\",\n    \"server returned\":\"서버 응답함.\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/pl.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Uwaga: Wycofane\",\n    \"Implementation Notes\":\"Uwagi Implementacji\",\n    \"Response Class\":\"Klasa Odpowiedzi\",\n    \"Status\":\"Status\",\n    \"Parameters\":\"Parametry\",\n    \"Parameter\":\"Parametr\",\n    \"Value\":\"Wartość\",\n    \"Description\":\"Opis\",\n    \"Parameter Type\":\"Typ Parametru\",\n    \"Data Type\":\"Typ Danych\",\n    \"Response Messages\":\"Wiadomości Odpowiedzi\",\n    \"HTTP Status Code\":\"Kod Statusu HTTP\",\n    \"Reason\":\"Przyczyna\",\n    \"Response Model\":\"Model Odpowiedzi\",\n    \"Request URL\":\"URL Wywołania\",\n    \"Response Body\":\"Treść Odpowiedzi\",\n    \"Response Code\":\"Kod Odpowiedzi\",\n    \"Response Headers\":\"Nagłówki Odpowiedzi\",\n    \"Hide Response\":\"Ukryj Odpowiedź\",\n    \"Headers\":\"Nagłówki\",\n    \"Try it out!\":\"Wypróbuj!\",\n    \"Show/Hide\":\"Pokaż/Ukryj\",\n    \"List Operations\":\"Lista Operacji\",\n    \"Expand Operations\":\"Rozwiń Operacje\",\n    \"Raw\":\"Nieprzetworzone\",\n    \"can't parse JSON.  Raw result\":\"nie można przetworzyć pliku JSON.  Nieprzetworzone dane\",\n    \"Model Schema\":\"Schemat Modelu\",\n    \"Model\":\"Model\",\n    \"apply\":\"użyj\",\n    \"Username\":\"Nazwa użytkownika\",\n    \"Password\":\"Hasło\",\n    \"Terms of service\":\"Warunki używania\",\n    \"Created by\":\"Utworzone przez\",\n    \"See more at\":\"Zobacz więcej na\",\n    \"Contact the developer\":\"Kontakt z deweloperem\",\n    \"api version\":\"wersja api\",\n    \"Response Content Type\":\"Typ Zasobu Odpowiedzi\",\n    \"fetching resource\":\"ładowanie zasobu\",\n    \"fetching resource list\":\"ładowanie listy zasobów\",\n    \"Explore\":\"Eksploruj\",\n    \"Show Swagger Petstore Example Apis\":\"Pokaż Przykładowe Api Swagger Petstore\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"Brak połączenia z serwerem. Może on nie mieć odpowiednich ustawień access-control-origin.\",\n    \"Please specify the protocol for\":\"Proszę podać protokół dla\",\n    \"Can't read swagger JSON from\":\"Nie można odczytać swagger JSON z\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"Ukończono Ładowanie Informacji o Zasobie. Renderowanie Swagger UI\",\n    \"Unable to read api\":\"Nie można odczytać api\",\n    \"from path\":\"ze ścieżki\",\n    \"server returned\":\"serwer zwrócił\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/pt.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Aviso: Depreciado\",\n    \"Implementation Notes\":\"Notas de Implementação\",\n    \"Response Class\":\"Classe de resposta\",\n    \"Status\":\"Status\",\n    \"Parameters\":\"Parâmetros\",\n    \"Parameter\":\"Parâmetro\",\n    \"Value\":\"Valor\",\n    \"Description\":\"Descrição\",\n    \"Parameter Type\":\"Tipo de parâmetro\",\n    \"Data Type\":\"Tipo de dados\",\n    \"Response Messages\":\"Mensagens de resposta\",\n    \"HTTP Status Code\":\"Código de status HTTP\",\n    \"Reason\":\"Razão\",\n    \"Response Model\":\"Modelo resposta\",\n    \"Request URL\":\"URL requisição\",\n    \"Response Body\":\"Corpo da resposta\",\n    \"Response Code\":\"Código da resposta\",\n    \"Response Headers\":\"Cabeçalho da resposta\",\n    \"Headers\":\"Cabeçalhos\",\n    \"Hide Response\":\"Esconder resposta\",\n    \"Try it out!\":\"Tente agora!\",\n    \"Show/Hide\":\"Mostrar/Esconder\",\n    \"List Operations\":\"Listar operações\",\n    \"Expand Operations\":\"Expandir operações\",\n    \"Raw\":\"Cru\",\n    \"can't parse JSON.  Raw result\":\"Falha ao analisar JSON.  Resulto cru\",\n    \"Model Schema\":\"Modelo esquema\",\n    \"Model\":\"Modelo\",\n    \"apply\":\"Aplicar\",\n    \"Username\":\"Usuário\",\n    \"Password\":\"Senha\",\n    \"Terms of service\":\"Termos do serviço\",\n    \"Created by\":\"Criado por\",\n    \"See more at\":\"Veja mais em\",\n    \"Contact the developer\":\"Contate o desenvolvedor\",\n    \"api version\":\"Versão api\",\n    \"Response Content Type\":\"Tipo de conteúdo da resposta\",\n    \"fetching resource\":\"busca recurso\",\n    \"fetching resource list\":\"buscando lista de recursos\",\n    \"Explore\":\"Explorar\",\n    \"Show Swagger Petstore Example Apis\":\"Show Swagger Petstore Example Apis\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"Não é possível ler do servidor. Pode não ter as apropriadas configurações access-control-origin\",\n    \"Please specify the protocol for\":\"Por favor especifique o protocolo\",\n    \"Can't read swagger JSON from\":\"Não é possível ler o JSON Swagger de\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"Carregar informação de recurso finalizada. Renderizando Swagger UI\",\n    \"Unable to read api\":\"Não foi possível ler api\",\n    \"from path\":\"do caminho\",\n    \"server returned\":\"servidor retornou\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/ru.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Предупреждение: Устарело\",\n    \"Implementation Notes\":\"Заметки\",\n    \"Response Class\":\"Пример ответа\",\n    \"Status\":\"Статус\",\n    \"Parameters\":\"Параметры\",\n    \"Parameter\":\"Параметр\",\n    \"Value\":\"Значение\",\n    \"Description\":\"Описание\",\n    \"Parameter Type\":\"Тип параметра\",\n    \"Data Type\":\"Тип данных\",\n    \"HTTP Status Code\":\"HTTP код\",\n    \"Reason\":\"Причина\",\n    \"Response Model\":\"Структура ответа\",\n    \"Request URL\":\"URL запроса\",\n    \"Response Body\":\"Тело ответа\",\n    \"Response Code\":\"HTTP код ответа\",\n    \"Response Headers\":\"Заголовки ответа\",\n    \"Hide Response\":\"Спрятать ответ\",\n    \"Headers\":\"Заголовки\",\n    \"Response Messages\":\"Что может прийти в ответ\",\n    \"Try it out!\":\"Попробовать!\",\n    \"Show/Hide\":\"Показать/Скрыть\",\n    \"List Operations\":\"Операции кратко\",\n    \"Expand Operations\":\"Операции подробно\",\n    \"Raw\":\"В сыром виде\",\n    \"can't parse JSON.  Raw result\":\"Не удается распарсить ответ:\",\n    \"Example Value\":\"Пример\",\n    \"Model Schema\":\"Структура\",\n    \"Model\":\"Описание\",\n    \"Click to set as parameter value\":\"Нажмите, чтобы испльзовать в качестве значения параметра\",\n    \"apply\":\"применить\",\n    \"Username\":\"Имя пользователя\",\n    \"Password\":\"Пароль\",\n    \"Terms of service\":\"Условия использования\",\n    \"Created by\":\"Разработано\",\n    \"See more at\":\"Еще тут\",\n    \"Contact the developer\":\"Связаться с разработчиком\",\n    \"api version\":\"Версия API\",\n    \"Response Content Type\":\"Content Type ответа\",\n    \"Parameter content type:\":\"Content Type параметра:\",\n    \"fetching resource\":\"Получение ресурса\",\n    \"fetching resource list\":\"Получение ресурсов\",\n    \"Explore\":\"Показать\",\n    \"Show Swagger Petstore Example Apis\":\"Показать примеры АПИ\",\n    \"Can't read from server. It may not have the appropriate access-control-origin settings.\":\"Не удается получить ответ от сервера. Возможно, проблема с настройками доступа\",\n    \"Please specify the protocol for\":\"Пожалуйста, укажите протокол для\",\n    \"Can't read swagger JSON from\":\"Не получается прочитать swagger json из\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"Загрузка информации о ресурсах завершена. Рендерим\",\n    \"Unable to read api\":\"Не удалось прочитать api\",\n    \"from path\":\"по адресу\",\n    \"server returned\":\"сервер сказал\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/tr.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"Uyarı: Deprecated\",\n    \"Implementation Notes\":\"Gerçekleştirim Notları\",\n    \"Response Class\":\"Dönen Sınıf\",\n    \"Status\":\"Statü\",\n    \"Parameters\":\"Parametreler\",\n    \"Parameter\":\"Parametre\",\n    \"Value\":\"Değer\",\n    \"Description\":\"Açıklama\",\n    \"Parameter Type\":\"Parametre Tipi\",\n    \"Data Type\":\"Veri Tipi\",\n    \"Response Messages\":\"Dönüş Mesajı\",\n    \"HTTP Status Code\":\"HTTP Statü Kodu\",\n    \"Reason\":\"Gerekçe\",\n    \"Response Model\":\"Dönüş Modeli\",\n    \"Request URL\":\"İstek URL\",\n    \"Response Body\":\"Dönüş İçeriği\",\n    \"Response Code\":\"Dönüş Kodu\",\n    \"Response Headers\":\"Dönüş Üst Bilgileri\",\n    \"Hide Response\":\"Dönüşü Gizle\",\n    \"Headers\":\"Üst Bilgiler\",\n    \"Try it out!\":\"Dene!\",\n    \"Show/Hide\":\"Göster/Gizle\",\n    \"List Operations\":\"Operasyonları Listele\",\n    \"Expand Operations\":\"Operasyonları Aç\",\n    \"Raw\":\"Ham\",\n    \"can't parse JSON.  Raw result\":\"JSON çözümlenemiyor.  Ham sonuç\",\n    \"Model Schema\":\"Model Şema\",\n    \"Model\":\"Model\",\n    \"apply\":\"uygula\",\n    \"Username\":\"Kullanıcı Adı\",\n    \"Password\":\"Parola\",\n    \"Terms of service\":\"Servis şartları\",\n    \"Created by\":\"Oluşturan\",\n    \"See more at\":\"Daha fazlası için\",\n    \"Contact the developer\":\"Geliştirici ile İletişime Geçin\",\n    \"api version\":\"api versiyon\",\n    \"Response Content Type\":\"Dönüş İçerik Tipi\",\n    \"fetching resource\":\"kaynak getiriliyor\",\n    \"fetching resource list\":\"kaynak listesi getiriliyor\",\n    \"Explore\":\"Keşfet\",\n    \"Show Swagger Petstore Example Apis\":\"Swagger Petstore Örnek Api'yi Gör\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"Sunucudan okuma yapılamıyor. Sunucu access-control-origin ayarlarınızı kontrol edin.\",\n    \"Please specify the protocol for\":\"Lütfen istenen adres için protokol belirtiniz\",\n    \"Can't read swagger JSON from\":\"Swagger JSON bu kaynaktan okunamıyor\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"Kaynak baglantısı tamamlandı. Swagger UI gösterime hazırlanıyor\",\n    \"Unable to read api\":\"api okunamadı\",\n    \"from path\":\"yoldan\",\n    \"server returned\":\"sunucuya dönüldü\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/translator.js",
    "content": "'use strict';\n\n/**\n * Translator for documentation pages.\n *\n * To enable translation you should include one of language-files in your index.html\n * after <script src='lang/translator.js' type='text/javascript'></script>.\n * For example - <script src='lang/ru.js' type='text/javascript'></script>\n *\n * If you wish to translate some new texts you should do two things:\n * 1. Add a new phrase pair (\"New Phrase\": \"New Translation\") into your language file (for example lang/ru.js). It will be great if you add it in other language files too.\n * 2. Mark that text it templates this way <anyHtmlTag data-sw-translate>New Phrase</anyHtmlTag> or <anyHtmlTag data-sw-translate value='New Phrase'/>.\n * The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate.\n *\n */\nwindow.SwaggerTranslator = {\n\n    _words:[],\n\n    translate: function(sel) {\n      var $this = this;\n      sel = sel || '[data-sw-translate]';\n\n      $(sel).each(function() {\n        $(this).html($this._tryTranslate($(this).html()));\n\n        $(this).val($this._tryTranslate($(this).val()));\n        $(this).attr('title', $this._tryTranslate($(this).attr('title')));\n      });\n    },\n\n    _tryTranslate: function(word) {\n      return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word;\n    },\n\n    learn: function(wordsMap) {\n      this._words = wordsMap;\n    }\n};\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lang/zh-cn.js",
    "content": "'use strict';\n\n/* jshint quotmark: double */\nwindow.SwaggerTranslator.learn({\n    \"Warning: Deprecated\":\"警告：已过时\",\n    \"Implementation Notes\":\"实现备注\",\n    \"Response Class\":\"响应类\",\n    \"Status\":\"状态\",\n    \"Parameters\":\"参数\",\n    \"Parameter\":\"参数\",\n    \"Value\":\"值\",\n    \"Description\":\"描述\",\n    \"Parameter Type\":\"参数类型\",\n    \"Data Type\":\"数据类型\",\n    \"Response Messages\":\"响应消息\",\n    \"HTTP Status Code\":\"HTTP状态码\",\n    \"Reason\":\"原因\",\n    \"Response Model\":\"响应模型\",\n    \"Request URL\":\"请求URL\",\n    \"Response Body\":\"响应体\",\n    \"Response Code\":\"响应码\",\n    \"Response Headers\":\"响应头\",\n    \"Hide Response\":\"隐藏响应\",\n    \"Headers\":\"头\",\n    \"Try it out!\":\"试一下！\",\n    \"Show/Hide\":\"显示/隐藏\",\n    \"List Operations\":\"显示操作\",\n    \"Expand Operations\":\"展开操作\",\n    \"Raw\":\"原始\",\n    \"can't parse JSON.  Raw result\":\"无法解析JSON. 原始结果\",\n    \"Example Value\":\"示例\",\n    \"Click to set as parameter value\":\"点击设置参数\",\n    \"Model Schema\":\"模型架构\",\n    \"Model\":\"模型\",\n    \"apply\":\"应用\",\n    \"Username\":\"用户名\",\n    \"Password\":\"密码\",\n    \"Terms of service\":\"服务条款\",\n    \"Created by\":\"创建者\",\n    \"See more at\":\"查看更多：\",\n    \"Contact the developer\":\"联系开发者\",\n    \"api version\":\"api版本\",\n    \"Response Content Type\":\"响应Content Type\",\n    \"Parameter content type:\":\"参数类型:\",\n    \"fetching resource\":\"正在获取资源\",\n    \"fetching resource list\":\"正在获取资源列表\",\n    \"Explore\":\"浏览\",\n    \"Show Swagger Petstore Example Apis\":\"显示 Swagger Petstore 示例 Apis\",\n    \"Can't read from server.  It may not have the appropriate access-control-origin settings.\":\"无法从服务器读取。可能没有正确设置access-control-origin。\",\n    \"Please specify the protocol for\":\"请指定协议：\",\n    \"Can't read swagger JSON from\":\"无法读取swagger JSON于\",\n    \"Finished Loading Resource Information. Rendering Swagger UI\":\"已加载资源信息。正在渲染Swagger UI\",\n    \"Unable to read api\":\"无法读取api\",\n    \"from path\":\"从路径\",\n    \"server returned\":\"服务器返回\"\n});\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lib/backbone-min.js",
    "content": "!function(t,e){if(\"function\"==typeof define&&define.amd)define([\"underscore\",\"jquery\",\"exports\"],function(i,n,s){t.Backbone=e(t,s,i,n)});else if(\"undefined\"!=typeof exports){var i=require(\"underscore\");e(t,exports,i)}else t.Backbone=e(t,{},t._,t.jQuery||t.Zepto||t.ender||t.$)}(this,function(t,e,i,n){var s=t.Backbone,r=[],a=(r.push,r.slice);r.splice;e.VERSION=\"1.1.2\",e.$=n,e.noConflict=function(){return t.Backbone=s,this},e.emulateHTTP=!1,e.emulateJSON=!1;var o=e.Events={on:function(t,e,i){if(!c(this,\"on\",t,[e,i])||!e)return this;this._events||(this._events={});var n=this._events[t]||(this._events[t]=[]);return n.push({callback:e,context:i,ctx:i||this}),this},once:function(t,e,n){if(!c(this,\"once\",t,[e,n])||!e)return this;var s=this,r=i.once(function(){s.off(t,r),e.apply(this,arguments)});return r._callback=e,this.on(t,r,n)},off:function(t,e,n){var s,r,a,o,h,u,l,d;if(!this._events||!c(this,\"off\",t,[e,n]))return this;if(!t&&!e&&!n)return this._events=void 0,this;for(o=t?[t]:i.keys(this._events),h=0,u=o.length;h<u;h++)if(t=o[h],a=this._events[t]){if(this._events[t]=s=[],e||n)for(l=0,d=a.length;l<d;l++)r=a[l],(e&&e!==r.callback&&e!==r.callback._callback||n&&n!==r.context)&&s.push(r);s.length||delete this._events[t]}return this},trigger:function(t){if(!this._events)return this;var e=a.call(arguments,1);if(!c(this,\"trigger\",t,e))return this;var i=this._events[t],n=this._events.all;return i&&u(i,e),n&&u(n,arguments),this},stopListening:function(t,e,n){var s=this._listeningTo;if(!s)return this;var r=!e&&!n;n||\"object\"!=typeof e||(n=this),t&&((s={})[t._listenId]=t);for(var a in s)t=s[a],t.off(e,n,this),(r||i.isEmpty(t._events))&&delete this._listeningTo[a];return this}},h=/\\s+/,c=function(t,e,i,n){if(!i)return!0;if(\"object\"==typeof i){for(var s in i)t[e].apply(t,[s,i[s]].concat(n));return!1}if(h.test(i)){for(var r=i.split(h),a=0,o=r.length;a<o;a++)t[e].apply(t,[r[a]].concat(n));return!1}return!0},u=function(t,e){var i,n=-1,s=t.length,r=e[0],a=e[1],o=e[2];switch(e.length){case 0:for(;++n<s;)(i=t[n]).callback.call(i.ctx);return;case 1:for(;++n<s;)(i=t[n]).callback.call(i.ctx,r);return;case 2:for(;++n<s;)(i=t[n]).callback.call(i.ctx,r,a);return;case 3:for(;++n<s;)(i=t[n]).callback.call(i.ctx,r,a,o);return;default:for(;++n<s;)(i=t[n]).callback.apply(i.ctx,e);return}},l={listenTo:\"on\",listenToOnce:\"once\"};i.each(l,function(t,e){o[e]=function(e,n,s){var r=this._listeningTo||(this._listeningTo={}),a=e._listenId||(e._listenId=i.uniqueId(\"l\"));return r[a]=e,s||\"object\"!=typeof n||(s=this),e[t](n,s,this),this}}),o.bind=o.on,o.unbind=o.off,i.extend(e,o);var d=e.Model=function(t,e){var n=t||{};e||(e={}),this.cid=i.uniqueId(\"c\"),this.attributes={},e.collection&&(this.collection=e.collection),e.parse&&(n=this.parse(n,e)||{}),n=i.defaults({},n,i.result(this,\"defaults\")),this.set(n,e),this.changed={},this.initialize.apply(this,arguments)};i.extend(d.prototype,o,{changed:null,validationError:null,idAttribute:\"id\",initialize:function(){},toJSON:function(t){return i.clone(this.attributes)},sync:function(){return e.sync.apply(this,arguments)},get:function(t){return this.attributes[t]},escape:function(t){return i.escape(this.get(t))},has:function(t){return null!=this.get(t)},set:function(t,e,n){var s,r,a,o,h,c,u,l;if(null==t)return this;if(\"object\"==typeof t?(r=t,n=e):(r={})[t]=e,n||(n={}),!this._validate(r,n))return!1;a=n.unset,h=n.silent,o=[],c=this._changing,this._changing=!0,c||(this._previousAttributes=i.clone(this.attributes),this.changed={}),l=this.attributes,u=this._previousAttributes,this.idAttribute in r&&(this.id=r[this.idAttribute]);for(s in r)e=r[s],i.isEqual(l[s],e)||o.push(s),i.isEqual(u[s],e)?delete this.changed[s]:this.changed[s]=e,a?delete l[s]:l[s]=e;if(!h){o.length&&(this._pending=n);for(var d=0,f=o.length;d<f;d++)this.trigger(\"change:\"+o[d],this,l[o[d]],n)}if(c)return this;if(!h)for(;this._pending;)n=this._pending,this._pending=!1,this.trigger(\"change\",this,n);return this._pending=!1,this._changing=!1,this},unset:function(t,e){return this.set(t,void 0,i.extend({},e,{unset:!0}))},clear:function(t){var e={};for(var n in this.attributes)e[n]=void 0;return this.set(e,i.extend({},t,{unset:!0}))},hasChanged:function(t){return null==t?!i.isEmpty(this.changed):i.has(this.changed,t)},changedAttributes:function(t){if(!t)return!!this.hasChanged()&&i.clone(this.changed);var e,n=!1,s=this._changing?this._previousAttributes:this.attributes;for(var r in t)i.isEqual(s[r],e=t[r])||((n||(n={}))[r]=e);return n},previous:function(t){return null!=t&&this._previousAttributes?this._previousAttributes[t]:null},previousAttributes:function(){return i.clone(this._previousAttributes)},fetch:function(t){t=t?i.clone(t):{},void 0===t.parse&&(t.parse=!0);var e=this,n=t.success;return t.success=function(i){return!!e.set(e.parse(i,t),t)&&(n&&n(e,i,t),void e.trigger(\"sync\",e,i,t))},U(this,t),this.sync(\"read\",this,t)},save:function(t,e,n){var s,r,a,o=this.attributes;if(null==t||\"object\"==typeof t?(s=t,n=e):(s={})[t]=e,n=i.extend({validate:!0},n),s&&!n.wait){if(!this.set(s,n))return!1}else if(!this._validate(s,n))return!1;s&&n.wait&&(this.attributes=i.extend({},o,s)),void 0===n.parse&&(n.parse=!0);var h=this,c=n.success;return n.success=function(t){h.attributes=o;var e=h.parse(t,n);return n.wait&&(e=i.extend(s||{},e)),!(i.isObject(e)&&!h.set(e,n))&&(c&&c(h,t,n),void h.trigger(\"sync\",h,t,n))},U(this,n),r=this.isNew()?\"create\":n.patch?\"patch\":\"update\",\"patch\"===r&&(n.attrs=s),a=this.sync(r,this,n),s&&n.wait&&(this.attributes=o),a},destroy:function(t){t=t?i.clone(t):{};var e=this,n=t.success,s=function(){e.trigger(\"destroy\",e,e.collection,t)};if(t.success=function(i){(t.wait||e.isNew())&&s(),n&&n(e,i,t),e.isNew()||e.trigger(\"sync\",e,i,t)},this.isNew())return t.success(),!1;U(this,t);var r=this.sync(\"delete\",this,t);return t.wait||s(),r},url:function(){var t=i.result(this,\"urlRoot\")||i.result(this.collection,\"url\")||j();return this.isNew()?t:t.replace(/([^\\/])$/,\"$1/\")+encodeURIComponent(this.id)},parse:function(t,e){return t},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return!this.has(this.idAttribute)},isValid:function(t){return this._validate({},i.extend(t||{},{validate:!0}))},_validate:function(t,e){if(!e.validate||!this.validate)return!0;t=i.extend({},this.attributes,t);var n=this.validationError=this.validate(t,e)||null;return!n||(this.trigger(\"invalid\",this,n,i.extend(e,{validationError:n})),!1)}});var f=[\"keys\",\"values\",\"pairs\",\"invert\",\"pick\",\"omit\"];i.each(f,function(t){d.prototype[t]=function(){var e=a.call(arguments);return e.unshift(this.attributes),i[t].apply(i,e)}});var p=e.Collection=function(t,e){e||(e={}),e.model&&(this.model=e.model),void 0!==e.comparator&&(this.comparator=e.comparator),this._reset(),this.initialize.apply(this,arguments),t&&this.reset(t,i.extend({silent:!0},e))},g={add:!0,remove:!0,merge:!0},v={add:!0,remove:!1};i.extend(p.prototype,o,{model:d,initialize:function(){},toJSON:function(t){return this.map(function(e){return e.toJSON(t)})},sync:function(){return e.sync.apply(this,arguments)},add:function(t,e){return this.set(t,i.extend({merge:!1},e,v))},remove:function(t,e){var n=!i.isArray(t);t=n?[t]:i.clone(t),e||(e={});var s,r,a,o;for(s=0,r=t.length;s<r;s++)o=t[s]=this.get(t[s]),o&&(delete this._byId[o.id],delete this._byId[o.cid],a=this.indexOf(o),this.models.splice(a,1),this.length--,e.silent||(e.index=a,o.trigger(\"remove\",o,this,e)),this._removeReference(o,e));return n?t[0]:t},set:function(t,e){e=i.defaults({},e,g),e.parse&&(t=this.parse(t,e));var n=!i.isArray(t);t=n?t?[t]:[]:i.clone(t);var s,r,a,o,h,c,u,l=e.at,f=this.model,p=this.comparator&&null==l&&e.sort!==!1,v=i.isString(this.comparator)?this.comparator:null,m=[],y=[],_={},b=e.add,w=e.merge,x=e.remove,E=!(p||!b||!x)&&[];for(s=0,r=t.length;s<r;s++){if(h=t[s]||{},a=h instanceof d?o=h:h[f.prototype.idAttribute||\"id\"],c=this.get(a))x&&(_[c.cid]=!0),w&&(h=h===o?o.attributes:h,e.parse&&(h=c.parse(h,e)),c.set(h,e),p&&!u&&c.hasChanged(v)&&(u=!0)),t[s]=c;else if(b){if(o=t[s]=this._prepareModel(h,e),!o)continue;m.push(o),this._addReference(o,e)}o=c||o,!E||!o.isNew()&&_[o.id]||E.push(o),_[o.id]=!0}if(x){for(s=0,r=this.length;s<r;++s)_[(o=this.models[s]).cid]||y.push(o);y.length&&this.remove(y,e)}if(m.length||E&&E.length)if(p&&(u=!0),this.length+=m.length,null!=l)for(s=0,r=m.length;s<r;s++)this.models.splice(l+s,0,m[s]);else{E&&(this.models.length=0);var k=E||m;for(s=0,r=k.length;s<r;s++)this.models.push(k[s])}if(u&&this.sort({silent:!0}),!e.silent){for(s=0,r=m.length;s<r;s++)(o=m[s]).trigger(\"add\",o,this,e);(u||E&&E.length)&&this.trigger(\"sort\",this,e)}return n?t[0]:t},reset:function(t,e){e||(e={});for(var n=0,s=this.models.length;n<s;n++)this._removeReference(this.models[n],e);return e.previousModels=this.models,this._reset(),t=this.add(t,i.extend({silent:!0},e)),e.silent||this.trigger(\"reset\",this,e),t},push:function(t,e){return this.add(t,i.extend({at:this.length},e))},pop:function(t){var e=this.at(this.length-1);return this.remove(e,t),e},unshift:function(t,e){return this.add(t,i.extend({at:0},e))},shift:function(t){var e=this.at(0);return this.remove(e,t),e},slice:function(){return a.apply(this.models,arguments)},get:function(t){if(null!=t)return this._byId[t]||this._byId[t.id]||this._byId[t.cid]},at:function(t){return this.models[t]},where:function(t,e){return i.isEmpty(t)?e?void 0:[]:this[e?\"find\":\"filter\"](function(e){for(var i in t)if(t[i]!==e.get(i))return!1;return!0})},findWhere:function(t){return this.where(t,!0)},sort:function(t){if(!this.comparator)throw new Error(\"Cannot sort a set without a comparator\");return t||(t={}),i.isString(this.comparator)||1===this.comparator.length?this.models=this.sortBy(this.comparator,this):this.models.sort(i.bind(this.comparator,this)),t.silent||this.trigger(\"sort\",this,t),this},pluck:function(t){return i.invoke(this.models,\"get\",t)},fetch:function(t){t=t?i.clone(t):{},void 0===t.parse&&(t.parse=!0);var e=t.success,n=this;return t.success=function(i){var s=t.reset?\"reset\":\"set\";n[s](i,t),e&&e(n,i,t),n.trigger(\"sync\",n,i,t)},U(this,t),this.sync(\"read\",this,t)},create:function(t,e){if(e=e?i.clone(e):{},!(t=this._prepareModel(t,e)))return!1;e.wait||this.add(t,e);var n=this,s=e.success;return e.success=function(t,i){e.wait&&n.add(t,e),s&&s(t,i,e)},t.save(null,e),t},parse:function(t,e){return t},clone:function(){return new this.constructor(this.models)},_reset:function(){this.length=0,this.models=[],this._byId={}},_prepareModel:function(t,e){if(t instanceof d)return t;e=e?i.clone(e):{},e.collection=this;var n=new this.model(t,e);return n.validationError?(this.trigger(\"invalid\",this,n.validationError,e),!1):n},_addReference:function(t,e){this._byId[t.cid]=t,null!=t.id&&(this._byId[t.id]=t),t.collection||(t.collection=this),t.on(\"all\",this._onModelEvent,this)},_removeReference:function(t,e){this===t.collection&&delete t.collection,t.off(\"all\",this._onModelEvent,this)},_onModelEvent:function(t,e,i,n){(\"add\"!==t&&\"remove\"!==t||i===this)&&(\"destroy\"===t&&this.remove(e,n),e&&t===\"change:\"+e.idAttribute&&(delete this._byId[e.previous(e.idAttribute)],null!=e.id&&(this._byId[e.id]=e)),this.trigger.apply(this,arguments))}});var m=[\"forEach\",\"each\",\"map\",\"collect\",\"reduce\",\"foldl\",\"inject\",\"reduceRight\",\"foldr\",\"find\",\"detect\",\"filter\",\"select\",\"reject\",\"every\",\"all\",\"some\",\"any\",\"include\",\"contains\",\"invoke\",\"max\",\"min\",\"toArray\",\"size\",\"first\",\"head\",\"take\",\"initial\",\"rest\",\"tail\",\"drop\",\"last\",\"without\",\"difference\",\"indexOf\",\"shuffle\",\"lastIndexOf\",\"isEmpty\",\"chain\",\"sample\"];i.each(m,function(t){p.prototype[t]=function(){var e=a.call(arguments);return e.unshift(this.models),i[t].apply(i,e)}});var y=[\"groupBy\",\"countBy\",\"sortBy\",\"indexBy\"];i.each(y,function(t){p.prototype[t]=function(e,n){var s=i.isFunction(e)?e:function(t){return t.get(e)};return i[t](this.models,s,n)}});var _=e.View=function(t){this.cid=i.uniqueId(\"view\"),t||(t={}),i.extend(this,i.pick(t,w)),this._ensureElement(),this.initialize.apply(this,arguments),this.delegateEvents()},b=/^(\\S+)\\s*(.*)$/,w=[\"model\",\"collection\",\"el\",\"id\",\"attributes\",\"className\",\"tagName\",\"events\"];i.extend(_.prototype,o,{tagName:\"div\",$:function(t){return this.$el.find(t)},initialize:function(){},render:function(){return this},remove:function(){return this.$el.remove(),this.stopListening(),this},setElement:function(t,i){return this.$el&&this.undelegateEvents(),this.$el=t instanceof e.$?t:e.$(t),this.el=this.$el[0],i!==!1&&this.delegateEvents(),this},delegateEvents:function(t){if(!t&&!(t=i.result(this,\"events\")))return this;this.undelegateEvents();for(var e in t){var n=t[e];if(i.isFunction(n)||(n=this[t[e]]),n){var s=e.match(b),r=s[1],a=s[2];n=i.bind(n,this),r+=\".delegateEvents\"+this.cid,\"\"===a?this.$el.on(r,n):this.$el.on(r,a,n)}}return this},undelegateEvents:function(){return this.$el.off(\".delegateEvents\"+this.cid),this},_ensureElement:function(){if(this.el)this.setElement(i.result(this,\"el\"),!1);else{var t=i.extend({},i.result(this,\"attributes\"));this.id&&(t.id=i.result(this,\"id\")),this.className&&(t[\"class\"]=i.result(this,\"className\"));var n=e.$(\"<\"+i.result(this,\"tagName\")+\">\").attr(t);this.setElement(n,!1)}}}),e.sync=function(t,n,s){var r=E[t];i.defaults(s||(s={}),{emulateHTTP:e.emulateHTTP,emulateJSON:e.emulateJSON});var a={type:r,dataType:\"json\"};if(s.url||(a.url=i.result(n,\"url\")||j()),null!=s.data||!n||\"create\"!==t&&\"update\"!==t&&\"patch\"!==t||(a.contentType=\"application/json\",a.data=JSON.stringify(s.attrs||n.toJSON(s))),s.emulateJSON&&(a.contentType=\"application/x-www-form-urlencoded\",a.data=a.data?{model:a.data}:{}),s.emulateHTTP&&(\"PUT\"===r||\"DELETE\"===r||\"PATCH\"===r)){a.type=\"POST\",s.emulateJSON&&(a.data._method=r);var o=s.beforeSend;s.beforeSend=function(t){if(t.setRequestHeader(\"X-HTTP-Method-Override\",r),o)return o.apply(this,arguments)}}\"GET\"===a.type||s.emulateJSON||(a.processData=!1),\"PATCH\"===a.type&&x&&(a.xhr=function(){return new ActiveXObject(\"Microsoft.XMLHTTP\")});var h=s.xhr=e.ajax(i.extend(a,s));return n.trigger(\"request\",n,h,s),h};var x=!(\"undefined\"==typeof window||!window.ActiveXObject||window.XMLHttpRequest&&(new XMLHttpRequest).dispatchEvent),E={create:\"POST\",update:\"PUT\",patch:\"PATCH\",\"delete\":\"DELETE\",read:\"GET\"};e.ajax=function(){return e.$.ajax.apply(e.$,arguments)};var k=e.Router=function(t){t||(t={}),t.routes&&(this.routes=t.routes),this._bindRoutes(),this.initialize.apply(this,arguments)},T=/\\((.*?)\\)/g,$=/(\\(\\?)?:\\w+/g,S=/\\*\\w+/g,H=/[\\-{}\\[\\]+?.,\\\\\\^$|#\\s]/g;i.extend(k.prototype,o,{initialize:function(){},route:function(t,n,s){i.isRegExp(t)||(t=this._routeToRegExp(t)),i.isFunction(n)&&(s=n,n=\"\"),s||(s=this[n]);var r=this;return e.history.route(t,function(i){var a=r._extractParameters(t,i);r.execute(s,a),r.trigger.apply(r,[\"route:\"+n].concat(a)),r.trigger(\"route\",n,a),e.history.trigger(\"route\",r,n,a)}),this},execute:function(t,e){t&&t.apply(this,e)},navigate:function(t,i){return e.history.navigate(t,i),this},_bindRoutes:function(){if(this.routes){this.routes=i.result(this,\"routes\");for(var t,e=i.keys(this.routes);null!=(t=e.pop());)this.route(t,this.routes[t])}},_routeToRegExp:function(t){return t=t.replace(H,\"\\\\$&\").replace(T,\"(?:$1)?\").replace($,function(t,e){return e?t:\"([^/?]+)\"}).replace(S,\"([^?]*?)\"),new RegExp(\"^\"+t+\"(?:\\\\?([\\\\s\\\\S]*))?$\")},_extractParameters:function(t,e){var n=t.exec(e).slice(1);return i.map(n,function(t,e){return e===n.length-1?t||null:t?decodeURIComponent(t):null})}});var A=e.History=function(){this.handlers=[],i.bindAll(this,\"checkUrl\"),\"undefined\"!=typeof window&&(this.location=window.location,this.history=window.history)},I=/^[#\\/]|\\s+$/g,N=/^\\/+|\\/+$/g,R=/msie [\\w.]+/,O=/\\/$/,P=/#.*$/;A.started=!1,i.extend(A.prototype,o,{interval:50,atRoot:function(){return this.location.pathname.replace(/[^\\/]$/,\"$&/\")===this.root},getHash:function(t){var e=(t||this).location.href.match(/#(.*)$/);return e?e[1]:\"\"},getFragment:function(t,e){if(null==t)if(this._hasPushState||!this._wantsHashChange||e){t=decodeURI(this.location.pathname+this.location.search);var i=this.root.replace(O,\"\");t.indexOf(i)||(t=t.slice(i.length))}else t=this.getHash();return t.replace(I,\"\")},start:function(t){if(A.started)throw new Error(\"Backbone.history has already been started\");A.started=!0,this.options=i.extend({root:\"/\"},this.options,t),this.root=this.options.root,this._wantsHashChange=this.options.hashChange!==!1,this._wantsPushState=!!this.options.pushState,this._hasPushState=!!(this.options.pushState&&this.history&&this.history.pushState);var n=this.getFragment(),s=document.documentMode,r=R.exec(navigator.userAgent.toLowerCase())&&(!s||s<=7);if(this.root=(\"/\"+this.root+\"/\").replace(N,\"/\"),r&&this._wantsHashChange){var a=e.$('<iframe src=\"javascript:0\" tabindex=\"-1\">');this.iframe=a.hide().appendTo(\"body\")[0].contentWindow,this.navigate(n)}this._hasPushState?e.$(window).on(\"popstate\",this.checkUrl):this._wantsHashChange&&\"onhashchange\"in window&&!r?e.$(window).on(\"hashchange\",this.checkUrl):this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,this.interval)),this.fragment=n;var o=this.location;if(this._wantsHashChange&&this._wantsPushState){if(!this._hasPushState&&!this.atRoot())return this.fragment=this.getFragment(null,!0),this.location.replace(this.root+\"#\"+this.fragment),!0;this._hasPushState&&this.atRoot()&&o.hash&&(this.fragment=this.getHash().replace(I,\"\"),this.history.replaceState({},document.title,this.root+this.fragment))}if(!this.options.silent)return this.loadUrl()},stop:function(){e.$(window).off(\"popstate\",this.checkUrl).off(\"hashchange\",this.checkUrl),this._checkUrlInterval&&clearInterval(this._checkUrlInterval),A.started=!1},route:function(t,e){this.handlers.unshift({route:t,callback:e})},checkUrl:function(t){var e=this.getFragment();return e===this.fragment&&this.iframe&&(e=this.getFragment(this.getHash(this.iframe))),e!==this.fragment&&(this.iframe&&this.navigate(e),void this.loadUrl())},loadUrl:function(t){return t=this.fragment=this.getFragment(t),i.any(this.handlers,function(e){if(e.route.test(t))return e.callback(t),!0})},navigate:function(t,e){if(!A.started)return!1;e&&e!==!0||(e={trigger:!!e});var i=this.root+(t=this.getFragment(t||\"\"));if(t=t.replace(P,\"\"),this.fragment!==t){if(this.fragment=t,\"\"===t&&\"/\"!==i&&(i=i.slice(0,-1)),this._hasPushState)this.history[e.replace?\"replaceState\":\"pushState\"]({},document.title,i);else{if(!this._wantsHashChange)return this.location.assign(i);this._updateHash(this.location,t,e.replace),this.iframe&&t!==this.getFragment(this.getHash(this.iframe))&&(e.replace||this.iframe.document.open().close(),this._updateHash(this.iframe.location,t,e.replace))}return e.trigger?this.loadUrl(t):void 0}},_updateHash:function(t,e,i){if(i){var n=t.href.replace(/(javascript:|#).*$/,\"\");t.replace(n+\"#\"+e)}else t.hash=\"#\"+e}}),e.history=new A;var C=function(t,e){var n,s=this;n=t&&i.has(t,\"constructor\")?t.constructor:function(){return s.apply(this,arguments)},i.extend(n,s,e);var r=function(){this.constructor=n};return r.prototype=s.prototype,n.prototype=new r,t&&i.extend(n.prototype,t),n.__super__=s.prototype,n};d.extend=p.extend=k.extend=_.extend=A.extend=C;var j=function(){throw new Error('A \"url\" property or function must be specified')},U=function(t,e){var i=e.error;e.error=function(n){i&&i(t,n,e),t.trigger(\"error\",t,n,e)}};return e}),Backbone.View=function(t){return t.extend({constructor:function(e){this.options=e||{},t.apply(this,arguments)}})}(Backbone.View);"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lib/es5-shim.js",
    "content": "!function(t,e){\"use strict\";\"function\"==typeof define&&define.amd?define(e):\"object\"==typeof exports?module.exports=e():t.returnExports=e()}(this,function(){var t,e,r=Array,n=r.prototype,o=Object,i=o.prototype,a=Function,u=a.prototype,f=String,s=f.prototype,l=Number,c=l.prototype,h=n.slice,p=n.splice,y=n.push,d=n.unshift,g=n.concat,v=n.join,b=u.call,w=u.apply,T=Math.max,m=Math.min,D=i.toString,x=\"function\"==typeof Symbol&&\"symbol\"==typeof Symbol.toStringTag,S=Function.prototype.toString,O=/^\\s*class /,j=function(t){try{var e=S.call(t),r=e.replace(/\\/\\/.*\\n/g,\"\"),n=r.replace(/\\/\\*[.\\s\\S]*\\*\\//g,\"\"),o=n.replace(/\\n/gm,\" \").replace(/ {2}/g,\" \");return O.test(o)}catch(i){return!1}},E=function(t){try{return!j(t)&&(S.call(t),!0)}catch(e){return!1}},M=\"[object Function]\",I=\"[object GeneratorFunction]\",t=function(t){if(!t)return!1;if(\"function\"!=typeof t&&\"object\"!=typeof t)return!1;if(x)return E(t);if(j(t))return!1;var e=D.call(t);return e===M||e===I},U=RegExp.prototype.exec,F=function(t){try{return U.call(t),!0}catch(e){return!1}},N=\"[object RegExp]\";e=function(t){return\"object\"==typeof t&&(x?F(t):D.call(t)===N)};var k,C=String.prototype.valueOf,R=function(t){try{return C.call(t),!0}catch(e){return!1}},A=\"[object String]\";k=function(t){return\"string\"==typeof t||\"object\"==typeof t&&(x?R(t):D.call(t)===A)};var $=o.defineProperty&&function(){try{var t={};o.defineProperty(t,\"x\",{enumerable:!1,value:t});for(var e in t)return!1;return t.x===t}catch(r){return!1}}(),P=function(t){var e;return e=$?function(t,e,r,n){!n&&e in t||o.defineProperty(t,e,{configurable:!0,enumerable:!1,writable:!0,value:r})}:function(t,e,r,n){!n&&e in t||(t[e]=r)},function(r,n,o){for(var i in n)t.call(n,i)&&e(r,i,n[i],o)}}(i.hasOwnProperty),J=function(t){var e=typeof t;return null===t||\"object\"!==e&&\"function\"!==e},Z=l.isNaN||function(t){return t!==t},z={ToInteger:function(t){var e=+t;return Z(e)?e=0:0!==e&&e!==1/0&&e!==-(1/0)&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e},ToPrimitive:function(e){var r,n,o;if(J(e))return e;if(n=e.valueOf,t(n)&&(r=n.call(e),J(r)))return r;if(o=e.toString,t(o)&&(r=o.call(e),J(r)))return r;throw new TypeError},ToObject:function(t){if(null==t)throw new TypeError(\"can't convert \"+t+\" to object\");return o(t)},ToUint32:function(t){return t>>>0}},G=function(){};P(u,{bind:function(e){var r=this;if(!t(r))throw new TypeError(\"Function.prototype.bind called on incompatible \"+r);for(var n,i=h.call(arguments,1),u=function(){if(this instanceof n){var t=w.call(r,this,g.call(i,h.call(arguments)));return o(t)===t?t:this}return w.call(r,e,g.call(i,h.call(arguments)))},f=T(0,r.length-i.length),s=[],l=0;l<f;l++)y.call(s,\"$\"+l);return n=a(\"binder\",\"return function (\"+v.call(s,\",\")+\"){ return binder.apply(this, arguments); }\")(u),r.prototype&&(G.prototype=r.prototype,n.prototype=new G,G.prototype=null),n}});var Y=b.bind(i.hasOwnProperty),B=b.bind(i.toString),H=b.bind(h),W=w.bind(h),L=b.bind(s.slice),X=b.bind(s.split),q=b.bind(s.indexOf),K=b.bind(y),Q=b.bind(i.propertyIsEnumerable),V=b.bind(n.sort),_=r.isArray||function(t){return\"[object Array]\"===B(t)},tt=1!==[].unshift(0);P(n,{unshift:function(){return d.apply(this,arguments),this.length}},tt),P(r,{isArray:_});var et=o(\"a\"),rt=\"a\"!==et[0]||!(0 in et),nt=function(t){var e=!0,r=!0,n=!1;if(t)try{t.call(\"foo\",function(t,r,n){\"object\"!=typeof n&&(e=!1)}),t.call([1],function(){\"use strict\";r=\"string\"==typeof this},\"x\")}catch(o){n=!0}return!!t&&!n&&e&&r};P(n,{forEach:function(e){var r,n=z.ToObject(this),o=rt&&k(this)?X(this,\"\"):n,i=-1,a=z.ToUint32(o.length);if(arguments.length>1&&(r=arguments[1]),!t(e))throw new TypeError(\"Array.prototype.forEach callback must be a function\");for(;++i<a;)i in o&&(\"undefined\"==typeof r?e(o[i],i,n):e.call(r,o[i],i,n))}},!nt(n.forEach)),P(n,{map:function(e){var n,o=z.ToObject(this),i=rt&&k(this)?X(this,\"\"):o,a=z.ToUint32(i.length),u=r(a);if(arguments.length>1&&(n=arguments[1]),!t(e))throw new TypeError(\"Array.prototype.map callback must be a function\");for(var f=0;f<a;f++)f in i&&(\"undefined\"==typeof n?u[f]=e(i[f],f,o):u[f]=e.call(n,i[f],f,o));return u}},!nt(n.map)),P(n,{filter:function(e){var r,n,o=z.ToObject(this),i=rt&&k(this)?X(this,\"\"):o,a=z.ToUint32(i.length),u=[];if(arguments.length>1&&(n=arguments[1]),!t(e))throw new TypeError(\"Array.prototype.filter callback must be a function\");for(var f=0;f<a;f++)f in i&&(r=i[f],(\"undefined\"==typeof n?e(r,f,o):e.call(n,r,f,o))&&K(u,r));return u}},!nt(n.filter)),P(n,{every:function(e){var r,n=z.ToObject(this),o=rt&&k(this)?X(this,\"\"):n,i=z.ToUint32(o.length);if(arguments.length>1&&(r=arguments[1]),!t(e))throw new TypeError(\"Array.prototype.every callback must be a function\");for(var a=0;a<i;a++)if(a in o&&!(\"undefined\"==typeof r?e(o[a],a,n):e.call(r,o[a],a,n)))return!1;return!0}},!nt(n.every)),P(n,{some:function(e){var r,n=z.ToObject(this),o=rt&&k(this)?X(this,\"\"):n,i=z.ToUint32(o.length);if(arguments.length>1&&(r=arguments[1]),!t(e))throw new TypeError(\"Array.prototype.some callback must be a function\");for(var a=0;a<i;a++)if(a in o&&(\"undefined\"==typeof r?e(o[a],a,n):e.call(r,o[a],a,n)))return!0;return!1}},!nt(n.some));var ot=!1;n.reduce&&(ot=\"object\"==typeof n.reduce.call(\"es5\",function(t,e,r,n){return n})),P(n,{reduce:function(e){var r=z.ToObject(this),n=rt&&k(this)?X(this,\"\"):r,o=z.ToUint32(n.length);if(!t(e))throw new TypeError(\"Array.prototype.reduce callback must be a function\");if(0===o&&1===arguments.length)throw new TypeError(\"reduce of empty array with no initial value\");var i,a=0;if(arguments.length>=2)i=arguments[1];else for(;;){if(a in n){i=n[a++];break}if(++a>=o)throw new TypeError(\"reduce of empty array with no initial value\")}for(;a<o;a++)a in n&&(i=e(i,n[a],a,r));return i}},!ot);var it=!1;n.reduceRight&&(it=\"object\"==typeof n.reduceRight.call(\"es5\",function(t,e,r,n){return n})),P(n,{reduceRight:function(e){var r=z.ToObject(this),n=rt&&k(this)?X(this,\"\"):r,o=z.ToUint32(n.length);if(!t(e))throw new TypeError(\"Array.prototype.reduceRight callback must be a function\");if(0===o&&1===arguments.length)throw new TypeError(\"reduceRight of empty array with no initial value\");var i,a=o-1;if(arguments.length>=2)i=arguments[1];else for(;;){if(a in n){i=n[a--];break}if(--a<0)throw new TypeError(\"reduceRight of empty array with no initial value\")}if(a<0)return i;do a in n&&(i=e(i,n[a],a,r));while(a--);return i}},!it);var at=n.indexOf&&[0,1].indexOf(1,2)!==-1;P(n,{indexOf:function(t){var e=rt&&k(this)?X(this,\"\"):z.ToObject(this),r=z.ToUint32(e.length);if(0===r)return-1;var n=0;for(arguments.length>1&&(n=z.ToInteger(arguments[1])),n=n>=0?n:T(0,r+n);n<r;n++)if(n in e&&e[n]===t)return n;return-1}},at);var ut=n.lastIndexOf&&[0,1].lastIndexOf(0,-3)!==-1;P(n,{lastIndexOf:function(t){var e=rt&&k(this)?X(this,\"\"):z.ToObject(this),r=z.ToUint32(e.length);if(0===r)return-1;var n=r-1;for(arguments.length>1&&(n=m(n,z.ToInteger(arguments[1]))),n=n>=0?n:r-Math.abs(n);n>=0;n--)if(n in e&&t===e[n])return n;return-1}},ut);var ft=function(){var t=[1,2],e=t.splice();return 2===t.length&&_(e)&&0===e.length}();P(n,{splice:function(t,e){return 0===arguments.length?[]:p.apply(this,arguments)}},!ft);var st=function(){var t={};return n.splice.call(t,0,0,1),1===t.length}();P(n,{splice:function(t,e){if(0===arguments.length)return[];var r=arguments;return this.length=T(z.ToInteger(this.length),0),arguments.length>0&&\"number\"!=typeof e&&(r=H(arguments),r.length<2?K(r,this.length-t):r[1]=z.ToInteger(e)),p.apply(this,r)}},!st);var lt=function(){var t=new r(1e5);return t[8]=\"x\",t.splice(1,1),7===t.indexOf(\"x\")}(),ct=function(){var t=256,e=[];return e[t]=\"a\",e.splice(t+1,0,\"b\"),\"a\"===e[t]}();P(n,{splice:function(t,e){for(var r,n=z.ToObject(this),o=[],i=z.ToUint32(n.length),a=z.ToInteger(t),u=a<0?T(i+a,0):m(a,i),s=m(T(z.ToInteger(e),0),i-u),l=0;l<s;)r=f(u+l),Y(n,r)&&(o[l]=n[r]),l+=1;var c,h=H(arguments,2),p=h.length;if(p<s){l=u;for(var y=i-s;l<y;)r=f(l+s),c=f(l+p),Y(n,r)?n[c]=n[r]:delete n[c],l+=1;l=i;for(var d=i-s+p;l>d;)delete n[l-1],l-=1}else if(p>s)for(l=i-s;l>u;)r=f(l+s-1),c=f(l+p-1),Y(n,r)?n[c]=n[r]:delete n[c],l-=1;l=u;for(var g=0;g<h.length;++g)n[l]=h[g],l+=1;return n.length=i-s+p,o}},!lt||!ct);var ht,pt=n.join;try{ht=\"1,2,3\"!==Array.prototype.join.call(\"123\",\",\")}catch(yt){ht=!0}ht&&P(n,{join:function(t){var e=\"undefined\"==typeof t?\",\":t;return pt.call(k(this)?X(this,\"\"):this,e)}},ht);var dt=\"1,2\"!==[1,2].join(void 0);dt&&P(n,{join:function(t){var e=\"undefined\"==typeof t?\",\":t;return pt.call(this,e)}},dt);var gt=function(t){for(var e=z.ToObject(this),r=z.ToUint32(e.length),n=0;n<arguments.length;)e[r+n]=arguments[n],n+=1;return e.length=r+n,r+n},vt=function(){var t={},e=Array.prototype.push.call(t,void 0);return 1!==e||1!==t.length||\"undefined\"!=typeof t[0]||!Y(t,0)}();P(n,{push:function(t){return _(this)?y.apply(this,arguments):gt.apply(this,arguments)}},vt);var bt=function(){var t=[],e=t.push(void 0);return 1!==e||1!==t.length||\"undefined\"!=typeof t[0]||!Y(t,0)}();P(n,{push:gt},bt),P(n,{slice:function(t,e){var r=k(this)?X(this,\"\"):this;return W(r,arguments)}},rt);var wt=function(){try{return[1,2].sort(null),[1,2].sort({}),!0}catch(t){}return!1}(),Tt=function(){try{return[1,2].sort(/a/),!1}catch(t){}return!0}(),mt=function(){try{return[1,2].sort(void 0),!0}catch(t){}return!1}();P(n,{sort:function(e){if(\"undefined\"==typeof e)return V(this);if(!t(e))throw new TypeError(\"Array.prototype.sort callback must be a function\");return V(this,e)}},wt||!mt||!Tt);var Dt=!Q({toString:null},\"toString\"),xt=Q(function(){},\"prototype\"),St=!Y(\"x\",\"0\"),Ot=function(t){var e=t.constructor;return e&&e.prototype===t},jt={$window:!0,$console:!0,$parent:!0,$self:!0,$frame:!0,$frames:!0,$frameElement:!0,$webkitIndexedDB:!0,$webkitStorageInfo:!0,$external:!0},Et=function(){if(\"undefined\"==typeof window)return!1;for(var t in window)try{!jt[\"$\"+t]&&Y(window,t)&&null!==window[t]&&\"object\"==typeof window[t]&&Ot(window[t])}catch(e){return!0}return!1}(),Mt=function(t){if(\"undefined\"==typeof window||!Et)return Ot(t);try{return Ot(t)}catch(e){return!1}},It=[\"toString\",\"toLocaleString\",\"valueOf\",\"hasOwnProperty\",\"isPrototypeOf\",\"propertyIsEnumerable\",\"constructor\"],Ut=It.length,Ft=function(t){return\"[object Arguments]\"===B(t)},Nt=function(e){return null!==e&&\"object\"==typeof e&&\"number\"==typeof e.length&&e.length>=0&&!_(e)&&t(e.callee)},kt=Ft(arguments)?Ft:Nt;P(o,{keys:function(e){var r=t(e),n=kt(e),o=null!==e&&\"object\"==typeof e,i=o&&k(e);if(!o&&!r&&!n)throw new TypeError(\"Object.keys called on a non-object\");var a=[],u=xt&&r;if(i&&St||n)for(var s=0;s<e.length;++s)K(a,f(s));if(!n)for(var l in e)u&&\"prototype\"===l||!Y(e,l)||K(a,f(l));if(Dt)for(var c=Mt(e),h=0;h<Ut;h++){var p=It[h];c&&\"constructor\"===p||!Y(e,p)||K(a,p)}return a}});var Ct=o.keys&&function(){return 2===o.keys(arguments).length}(1,2),Rt=o.keys&&function(){var t=o.keys(arguments);return 1!==arguments.length||1!==t.length||1!==t[0]}(1),At=o.keys;P(o,{keys:function(t){return At(kt(t)?H(t):t)}},!Ct||Rt);var $t,Pt,Jt=0!==new Date((-0xc782b5b342b24)).getUTCMonth(),Zt=new Date((-0x55d318d56a724)),zt=new Date(14496624e5),Gt=\"Mon, 01 Jan -45875 11:59:59 GMT\"!==Zt.toUTCString(),Yt=Zt.getTimezoneOffset();Yt<-720?($t=\"Tue Jan 02 -45875\"!==Zt.toDateString(),Pt=!/^Thu Dec 10 2015 \\d\\d:\\d\\d:\\d\\d GMT[-\\+]\\d\\d\\d\\d(?: |$)/.test(zt.toString())):($t=\"Mon Jan 01 -45875\"!==Zt.toDateString(),Pt=!/^Wed Dec 09 2015 \\d\\d:\\d\\d:\\d\\d GMT[-\\+]\\d\\d\\d\\d(?: |$)/.test(zt.toString()));var Bt=b.bind(Date.prototype.getFullYear),Ht=b.bind(Date.prototype.getMonth),Wt=b.bind(Date.prototype.getDate),Lt=b.bind(Date.prototype.getUTCFullYear),Xt=b.bind(Date.prototype.getUTCMonth),qt=b.bind(Date.prototype.getUTCDate),Kt=b.bind(Date.prototype.getUTCDay),Qt=b.bind(Date.prototype.getUTCHours),Vt=b.bind(Date.prototype.getUTCMinutes),_t=b.bind(Date.prototype.getUTCSeconds),te=b.bind(Date.prototype.getUTCMilliseconds),ee=[\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\"],re=[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],ne=function(t,e){return Wt(new Date(e,t,0))};P(Date.prototype,{getFullYear:function(){if(!(this&&this instanceof Date))throw new TypeError(\"this is not a Date object.\");var t=Bt(this);return t<0&&Ht(this)>11?t+1:t},getMonth:function(){if(!(this&&this instanceof Date))throw new TypeError(\"this is not a Date object.\");var t=Bt(this),e=Ht(this);return t<0&&e>11?0:e},getDate:function(){if(!(this&&this instanceof Date))throw new TypeError(\"this is not a Date object.\");var t=Bt(this),e=Ht(this),r=Wt(this);if(t<0&&e>11){if(12===e)return r;var n=ne(0,t+1);return n-r+1}return r},getUTCFullYear:function(){if(!(this&&this instanceof Date))throw new TypeError(\"this is not a Date object.\");var t=Lt(this);return t<0&&Xt(this)>11?t+1:t},getUTCMonth:function(){if(!(this&&this instanceof Date))throw new TypeError(\"this is not a Date object.\");var t=Lt(this),e=Xt(this);return t<0&&e>11?0:e},getUTCDate:function(){if(!(this&&this instanceof Date))throw new TypeError(\"this is not a Date object.\");var t=Lt(this),e=Xt(this),r=qt(this);if(t<0&&e>11){if(12===e)return r;var n=ne(0,t+1);return n-r+1}return r}},Jt),P(Date.prototype,{toUTCString:function(){if(!(this&&this instanceof Date))throw new TypeError(\"this is not a Date object.\");var t=Kt(this),e=qt(this),r=Xt(this),n=Lt(this),o=Qt(this),i=Vt(this),a=_t(this);return ee[t]+\", \"+(e<10?\"0\"+e:e)+\" \"+re[r]+\" \"+n+\" \"+(o<10?\"0\"+o:o)+\":\"+(i<10?\"0\"+i:i)+\":\"+(a<10?\"0\"+a:a)+\" GMT\"}},Jt||Gt),P(Date.prototype,{toDateString:function(){if(!(this&&this instanceof Date))throw new TypeError(\"this is not a Date object.\");var t=this.getDay(),e=this.getDate(),r=this.getMonth(),n=this.getFullYear();return ee[t]+\" \"+re[r]+\" \"+(e<10?\"0\"+e:e)+\" \"+n}},Jt||$t),(Jt||Pt)&&(Date.prototype.toString=function(){if(!(this&&this instanceof Date))throw new TypeError(\"this is not a Date object.\");var t=this.getDay(),e=this.getDate(),r=this.getMonth(),n=this.getFullYear(),o=this.getHours(),i=this.getMinutes(),a=this.getSeconds(),u=this.getTimezoneOffset(),f=Math.floor(Math.abs(u)/60),s=Math.floor(Math.abs(u)%60);return ee[t]+\" \"+re[r]+\" \"+(e<10?\"0\"+e:e)+\" \"+n+\" \"+(o<10?\"0\"+o:o)+\":\"+(i<10?\"0\"+i:i)+\":\"+(a<10?\"0\"+a:a)+\" GMT\"+(u>0?\"-\":\"+\")+(f<10?\"0\"+f:f)+(s<10?\"0\"+s:s)},$&&o.defineProperty(Date.prototype,\"toString\",{configurable:!0,enumerable:!1,writable:!0}));var oe=-621987552e5,ie=\"-000001\",ae=Date.prototype.toISOString&&new Date(oe).toISOString().indexOf(ie)===-1,ue=Date.prototype.toISOString&&\"1969-12-31T23:59:59.999Z\"!==new Date((-1)).toISOString(),fe=b.bind(Date.prototype.getTime);P(Date.prototype,{toISOString:function(){if(!isFinite(this)||!isFinite(fe(this)))throw new RangeError(\"Date.prototype.toISOString called on non-finite value.\");var t=Lt(this),e=Xt(this);t+=Math.floor(e/12),e=(e%12+12)%12;var r=[e+1,qt(this),Qt(this),Vt(this),_t(this)];t=(t<0?\"-\":t>9999?\"+\":\"\")+L(\"00000\"+Math.abs(t),0<=t&&t<=9999?-4:-6);for(var n=0;n<r.length;++n)r[n]=L(\"00\"+r[n],-2);return t+\"-\"+H(r,0,2).join(\"-\")+\"T\"+H(r,2).join(\":\")+\".\"+L(\"000\"+te(this),-3)+\"Z\"}},ae||ue);var se=function(){try{return Date.prototype.toJSON&&null===new Date(NaN).toJSON()&&new Date(oe).toJSON().indexOf(ie)!==-1&&Date.prototype.toJSON.call({toISOString:function(){return!0}})}catch(t){return!1}}();se||(Date.prototype.toJSON=function(e){var r=o(this),n=z.ToPrimitive(r);if(\"number\"==typeof n&&!isFinite(n))return null;var i=r.toISOString;if(!t(i))throw new TypeError(\"toISOString property is not callable\");return i.call(r)});var le=1e15===Date.parse(\"+033658-09-27T01:46:40.000Z\"),ce=!isNaN(Date.parse(\"2012-04-04T24:00:00.500Z\"))||!isNaN(Date.parse(\"2012-11-31T23:59:59.000Z\"))||!isNaN(Date.parse(\"2012-12-31T23:59:60.000Z\")),he=isNaN(Date.parse(\"2000-01-01T00:00:00.000Z\"));if(he||ce||!le){var pe=Math.pow(2,31)-1,ye=Z(new Date(1970,0,1,0,0,0,pe+1).getTime());Date=function(t){var e=function(r,n,o,i,a,u,s){var l,c=arguments.length;if(this instanceof t){var h=u,p=s;if(ye&&c>=7&&s>pe){var y=Math.floor(s/pe)*pe,d=Math.floor(y/1e3);h+=d,p-=1e3*d}l=1===c&&f(r)===r?new t(e.parse(r)):c>=7?new t(r,n,o,i,a,h,p):c>=6?new t(r,n,o,i,a,h):c>=5?new t(r,n,o,i,a):c>=4?new t(r,n,o,i):c>=3?new t(r,n,o):c>=2?new t(r,n):c>=1?new t(r instanceof t?+r:r):new t}else l=t.apply(this,arguments);return J(l)||P(l,{constructor:e},!0),l},r=new RegExp(\"^(\\\\d{4}|[+-]\\\\d{6})(?:-(\\\\d{2})(?:-(\\\\d{2})(?:T(\\\\d{2}):(\\\\d{2})(?::(\\\\d{2})(?:(\\\\.\\\\d{1,}))?)?(Z|(?:([-+])(\\\\d{2}):(\\\\d{2})))?)?)?)?$\"),n=[0,31,59,90,120,151,181,212,243,273,304,334,365],o=function(t,e){var r=e>1?1:0;return n[e]+Math.floor((t-1969+r)/4)-Math.floor((t-1901+r)/100)+Math.floor((t-1601+r)/400)+365*(t-1970)},i=function(e){var r=0,n=e;if(ye&&n>pe){var o=Math.floor(n/pe)*pe,i=Math.floor(o/1e3);r+=i,n-=1e3*i}return l(new t(1970,0,1,0,0,r,n))};for(var a in t)Y(t,a)&&(e[a]=t[a]);P(e,{now:t.now,UTC:t.UTC},!0),e.prototype=t.prototype,P(e.prototype,{constructor:e},!0);var u=function(e){var n=r.exec(e);if(n){var a,u=l(n[1]),f=l(n[2]||1)-1,s=l(n[3]||1)-1,c=l(n[4]||0),h=l(n[5]||0),p=l(n[6]||0),y=Math.floor(1e3*l(n[7]||0)),d=Boolean(n[4]&&!n[8]),g=\"-\"===n[9]?1:-1,v=l(n[10]||0),b=l(n[11]||0),w=h>0||p>0||y>0;return c<(w?24:25)&&h<60&&p<60&&y<1e3&&f>-1&&f<12&&v<24&&b<60&&s>-1&&s<o(u,f+1)-o(u,f)&&(a=60*(24*(o(u,f)+s)+c+v*g),a=1e3*(60*(a+h+b*g)+p)+y,d&&(a=i(a)),-864e13<=a&&a<=864e13)?a:NaN}return t.parse.apply(this,arguments)};return P(e,{parse:u}),e}(Date)}Date.now||(Date.now=function(){return(new Date).getTime()});var de=c.toFixed&&(\"0.000\"!==8e-5.toFixed(3)||\"1\"!==.9.toFixed(0)||\"1.25\"!==1.255.toFixed(2)||\"1000000000000000128\"!==(0xde0b6b3a7640080).toFixed(0)),ge={base:1e7,size:6,data:[0,0,0,0,0,0],multiply:function(t,e){for(var r=-1,n=e;++r<ge.size;)n+=t*ge.data[r],ge.data[r]=n%ge.base,n=Math.floor(n/ge.base)},divide:function(t){for(var e=ge.size,r=0;--e>=0;)r+=ge.data[e],ge.data[e]=Math.floor(r/t),r=r%t*ge.base},numToString:function(){for(var t=ge.size,e=\"\";--t>=0;)if(\"\"!==e||0===t||0!==ge.data[t]){var r=f(ge.data[t]);\"\"===e?e=r:e+=L(\"0000000\",0,7-r.length)+r}return e},pow:function Ae(t,e,r){return 0===e?r:e%2===1?Ae(t,e-1,r*t):Ae(t*t,e/2,r)},log:function(t){for(var e=0,r=t;r>=4096;)e+=12,r/=4096;for(;r>=2;)e+=1,r/=2;return e}},ve=function(t){var e,r,n,o,i,a,u,s;if(e=l(t),e=Z(e)?0:Math.floor(e),e<0||e>20)throw new RangeError(\"Number.toFixed called with invalid number of decimals\");if(r=l(this),Z(r))return\"NaN\";if(r<=-1e21||r>=1e21)return f(r);if(n=\"\",r<0&&(n=\"-\",r=-r),o=\"0\",r>1e-21)if(i=ge.log(r*ge.pow(2,69,1))-69,a=i<0?r*ge.pow(2,-i,1):r/ge.pow(2,i,1),a*=4503599627370496,i=52-i,i>0){for(ge.multiply(0,a),u=e;u>=7;)ge.multiply(1e7,0),u-=7;for(ge.multiply(ge.pow(10,u,1),0),u=i-1;u>=23;)ge.divide(1<<23),u-=23;ge.divide(1<<u),ge.multiply(1,1),ge.divide(2),o=ge.numToString()}else ge.multiply(0,a),ge.multiply(1<<-i,0),o=ge.numToString()+L(\"0.00000000000000000000\",2,2+e);return e>0?(s=o.length,o=s<=e?n+L(\"0.0000000000000000000\",0,e-s+2)+o:n+L(o,0,s-e)+\".\"+L(o,s-e)):o=n+o,o};P(c,{toFixed:ve},de);var be=function(){try{return\"1\"===1..toPrecision(void 0)}catch(t){return!0}}(),we=c.toPrecision;P(c,{toPrecision:function(t){return\"undefined\"==typeof t?we.call(this):we.call(this,t)}},be),2!==\"ab\".split(/(?:ab)*/).length||4!==\".\".split(/(.?)(.?)/).length||\"t\"===\"tesst\".split(/(s)*/)[1]||4!==\"test\".split(/(?:)/,-1).length||\"\".split(/.?/).length||\".\".split(/()()/).length>1?!function(){var t=\"undefined\"==typeof/()??/.exec(\"\")[1],r=Math.pow(2,32)-1;s.split=function(n,o){var i=String(this);if(\"undefined\"==typeof n&&0===o)return[];if(!e(n))return X(this,n,o);var a,u,f,s,l=[],c=(n.ignoreCase?\"i\":\"\")+(n.multiline?\"m\":\"\")+(n.unicode?\"u\":\"\")+(n.sticky?\"y\":\"\"),h=0,p=new RegExp(n.source,c+\"g\");t||(a=new RegExp(\"^\"+p.source+\"$(?!\\\\s)\",c));var d=\"undefined\"==typeof o?r:z.ToUint32(o);for(u=p.exec(i);u&&(f=u.index+u[0].length,!(f>h&&(K(l,L(i,h,u.index)),!t&&u.length>1&&u[0].replace(a,function(){for(var t=1;t<arguments.length-2;t++)\"undefined\"==typeof arguments[t]&&(u[t]=void 0)}),u.length>1&&u.index<i.length&&y.apply(l,H(u,1)),s=u[0].length,h=f,l.length>=d)));)p.lastIndex===u.index&&p.lastIndex++,u=p.exec(i);return h===i.length?!s&&p.test(\"\")||K(l,\"\"):K(l,L(i,h)),l.length>d?H(l,0,d):l}}():\"0\".split(void 0,0).length&&(s.split=function(t,e){return\"undefined\"==typeof t&&0===e?[]:X(this,t,e)});var Te=s.replace,me=function(){var t=[];return\"x\".replace(/x(.)?/g,function(e,r){K(t,r)}),1===t.length&&\"undefined\"==typeof t[0]}();me||(s.replace=function(r,n){var o=t(n),i=e(r)&&/\\)[*?]/.test(r.source);if(o&&i){var a=function(t){var e=arguments.length,o=r.lastIndex;r.lastIndex=0;var i=r.exec(t)||[];return r.lastIndex=o,K(i,arguments[e-2],arguments[e-1]),n.apply(this,i)};return Te.call(this,r,a)}return Te.call(this,r,n)});var De=s.substr,xe=\"\".substr&&\"b\"!==\"0b\".substr(-1);P(s,{substr:function(t,e){var r=t;return t<0&&(r=T(this.length+t,0)),De.call(this,r,e)}},xe);var Se=\"\\t\\n\\x0B\\f\\r   ᠎             　\\u2028\\u2029\\ufeff\",Oe=\"​\",je=\"[\"+Se+\"]\",Ee=new RegExp(\"^\"+je+je+\"*\"),Me=new RegExp(je+je+\"*$\"),Ie=s.trim&&(Se.trim()||!Oe.trim());P(s,{trim:function(){if(\"undefined\"==typeof this||null===this)throw new TypeError(\"can't convert \"+this+\" to object\");return f(this).replace(Ee,\"\").replace(Me,\"\")}},Ie);var Ue=b.bind(String.prototype.trim),Fe=s.lastIndexOf&&\"abcあい\".lastIndexOf(\"あい\",2)!==-1;P(s,{lastIndexOf:function(t){if(\"undefined\"==typeof this||null===this)throw new TypeError(\"can't convert \"+this+\" to object\");for(var e=f(this),r=f(t),n=arguments.length>1?l(arguments[1]):NaN,o=Z(n)?1/0:z.ToInteger(n),i=m(T(o,0),e.length),a=r.length,u=i+a;u>0;){u=T(0,u-a);var s=q(L(e,u,i+a),r);if(s!==-1)return u+s}return-1}},Fe);var Ne=s.lastIndexOf;if(P(s,{lastIndexOf:function(t){return Ne.apply(this,arguments)}},1!==s.lastIndexOf.length),8===parseInt(Se+\"08\")&&22===parseInt(Se+\"0x16\")||(parseInt=function(t){var e=/^[\\-+]?0[xX]/;return function(r,n){var o=Ue(String(r)),i=l(n)||(e.test(o)?16:10);return t(o,i)}}(parseInt)),1/parseFloat(\"-0\")!==-(1/0)&&(parseFloat=function(t){return function(e){var r=Ue(String(e)),n=t(r);return 0===n&&\"-\"===L(r,0,1)?-0:n}}(parseFloat)),\"RangeError: test\"!==String(new RangeError(\"test\"))){var ke=function(){if(\"undefined\"==typeof this||null===this)throw new TypeError(\"can't convert \"+this+\" to object\");var t=this.name;\"undefined\"==typeof t?t=\"Error\":\"string\"!=typeof t&&(t=f(t));var e=this.message;return\"undefined\"==typeof e?e=\"\":\"string\"!=typeof e&&(e=f(e)),t?e?t+\": \"+e:t:e};Error.prototype.toString=ke}if($){var Ce=function(t,e){if(Q(t,e)){var r=Object.getOwnPropertyDescriptor(t,e);r.configurable&&(r.enumerable=!1,Object.defineProperty(t,e,r))}};Ce(Error.prototype,\"message\"),\"\"!==Error.prototype.message&&(Error.prototype.message=\"\"),Ce(Error.prototype,\"name\")}if(\"/a/gim\"!==String(/a/gim)){var Re=function(){var t=\"/\"+this.source+\"/\";return this.global&&(t+=\"g\"),this.ignoreCase&&(t+=\"i\"),this.multiline&&(t+=\"m\"),t};RegExp.prototype.toString=Re}});"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lib/handlebars-4.0.5.js",
    "content": "!function(t,e){\"object\"==typeof exports&&\"object\"==typeof module?module.exports=e():\"function\"==typeof define&&define.amd?define([],e):\"object\"==typeof exports?exports.Handlebars=e():t.Handlebars=e()}(this,function(){return function(t){function e(s){if(r[s])return r[s].exports;var i=r[s]={exports:{},id:s,loaded:!1};return t[s].call(i.exports,i,i.exports,e),i.loaded=!0,i.exports}var r={};return e.m=t,e.c=r,e.p=\"\",e(0)}([function(t,e,r){\"use strict\";function s(){var t=v();return t.compile=function(e,r){return l.compile(e,r,t)},t.precompile=function(e,r){return l.precompile(e,r,t)},t.AST=c[\"default\"],t.Compiler=l.Compiler,t.JavaScriptCompiler=u[\"default\"],t.Parser=h.parser,t.parse=h.parse,t}var i=r(1)[\"default\"];e.__esModule=!0;var a=r(2),n=i(a),o=r(21),c=i(o),h=r(22),l=r(27),p=r(28),u=i(p),f=r(25),d=i(f),m=r(20),g=i(m),v=n[\"default\"].create,y=s();y.create=s,g[\"default\"](y),y.Visitor=d[\"default\"],y[\"default\"]=y,e[\"default\"]=y,t.exports=e[\"default\"]},function(t,e){\"use strict\";e[\"default\"]=function(t){return t&&t.__esModule?t:{\"default\":t}},e.__esModule=!0},function(t,e,r){\"use strict\";function s(){var t=new o.HandlebarsEnvironment;return f.extend(t,o),t.SafeString=h[\"default\"],t.Exception=p[\"default\"],t.Utils=f,t.escapeExpression=f.escapeExpression,t.VM=m,t.template=function(e){return m.template(e,t)},t}var i=r(3)[\"default\"],a=r(1)[\"default\"];e.__esModule=!0;var n=r(4),o=i(n),c=r(18),h=a(c),l=r(6),p=a(l),u=r(5),f=i(u),d=r(19),m=i(d),g=r(20),v=a(g),y=s();y.create=s,v[\"default\"](y),y[\"default\"]=y,e[\"default\"]=y,t.exports=e[\"default\"]},function(t,e){\"use strict\";e[\"default\"]=function(t){if(t&&t.__esModule)return t;var e={};if(null!=t)for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&(e[r]=t[r]);return e[\"default\"]=t,e},e.__esModule=!0},function(t,e,r){\"use strict\";function s(t,e,r){this.helpers=t||{},this.partials=e||{},this.decorators=r||{},c.registerDefaultHelpers(this),h.registerDefaultDecorators(this)}var i=r(1)[\"default\"];e.__esModule=!0,e.HandlebarsEnvironment=s;var a=r(5),n=r(6),o=i(n),c=r(7),h=r(15),l=r(17),p=i(l),u=\"4.0.5\";e.VERSION=u;var f=7;e.COMPILER_REVISION=f;var d={1:\"<= 1.0.rc.2\",2:\"== 1.0.0-rc.3\",3:\"== 1.0.0-rc.4\",4:\"== 1.x.x\",5:\"== 2.0.0-alpha.x\",6:\">= 2.0.0-beta.1\",7:\">= 4.0.0\"};e.REVISION_CHANGES=d;var m=\"[object Object]\";s.prototype={constructor:s,logger:p[\"default\"],log:p[\"default\"].log,registerHelper:function(t,e){if(a.toString.call(t)===m){if(e)throw new o[\"default\"](\"Arg not supported with multiple helpers\");a.extend(this.helpers,t)}else this.helpers[t]=e},unregisterHelper:function(t){delete this.helpers[t]},registerPartial:function(t,e){if(a.toString.call(t)===m)a.extend(this.partials,t);else{if(\"undefined\"==typeof e)throw new o[\"default\"]('Attempting to register a partial called \"'+t+'\" as undefined');this.partials[t]=e}},unregisterPartial:function(t){delete this.partials[t]},registerDecorator:function(t,e){if(a.toString.call(t)===m){if(e)throw new o[\"default\"](\"Arg not supported with multiple decorators\");a.extend(this.decorators,t)}else this.decorators[t]=e},unregisterDecorator:function(t){delete this.decorators[t]}};var g=p[\"default\"].log;e.log=g,e.createFrame=a.createFrame,e.logger=p[\"default\"]},function(t,e){\"use strict\";function r(t){return l[t]}function s(t){for(var e=1;e<arguments.length;e++)for(var r in arguments[e])Object.prototype.hasOwnProperty.call(arguments[e],r)&&(t[r]=arguments[e][r]);return t}function i(t,e){for(var r=0,s=t.length;r<s;r++)if(t[r]===e)return r;return-1}function a(t){if(\"string\"!=typeof t){if(t&&t.toHTML)return t.toHTML();if(null==t)return\"\";if(!t)return t+\"\";t=\"\"+t}return u.test(t)?t.replace(p,r):t}function n(t){return!t&&0!==t||!(!m(t)||0!==t.length)}function o(t){var e=s({},t);return e._parent=t,e}function c(t,e){return t.path=e,t}function h(t,e){return(t?t+\".\":\"\")+e}e.__esModule=!0,e.extend=s,e.indexOf=i,e.escapeExpression=a,e.isEmpty=n,e.createFrame=o,e.blockParams=c,e.appendContextPath=h;var l={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#x27;\",\"`\":\"&#x60;\",\"=\":\"&#x3D;\"},p=/[&<>\"'`=]/g,u=/[&<>\"'`=]/,f=Object.prototype.toString;e.toString=f;var d=function(t){return\"function\"==typeof t};d(/x/)&&(e.isFunction=d=function(t){return\"function\"==typeof t&&\"[object Function]\"===f.call(t)}),e.isFunction=d;var m=Array.isArray||function(t){return!(!t||\"object\"!=typeof t)&&\"[object Array]\"===f.call(t)};e.isArray=m},function(t,e){\"use strict\";function r(t,e){var i=e&&e.loc,a=void 0,n=void 0;i&&(a=i.start.line,n=i.start.column,t+=\" - \"+a+\":\"+n);for(var o=Error.prototype.constructor.call(this,t),c=0;c<s.length;c++)this[s[c]]=o[s[c]];Error.captureStackTrace&&Error.captureStackTrace(this,r),i&&(this.lineNumber=a,this.column=n)}e.__esModule=!0;var s=[\"description\",\"fileName\",\"lineNumber\",\"message\",\"name\",\"number\",\"stack\"];r.prototype=new Error,e[\"default\"]=r,t.exports=e[\"default\"]},function(t,e,r){\"use strict\";function s(t){n[\"default\"](t),c[\"default\"](t),l[\"default\"](t),u[\"default\"](t),d[\"default\"](t),g[\"default\"](t),y[\"default\"](t)}var i=r(1)[\"default\"];e.__esModule=!0,e.registerDefaultHelpers=s;var a=r(8),n=i(a),o=r(9),c=i(o),h=r(10),l=i(h),p=r(11),u=i(p),f=r(12),d=i(f),m=r(13),g=i(m),v=r(14),y=i(v)},function(t,e,r){\"use strict\";e.__esModule=!0;var s=r(5);e[\"default\"]=function(t){t.registerHelper(\"blockHelperMissing\",function(e,r){var i=r.inverse,a=r.fn;if(e===!0)return a(this);if(e===!1||null==e)return i(this);if(s.isArray(e))return e.length>0?(r.ids&&(r.ids=[r.name]),t.helpers.each(e,r)):i(this);if(r.data&&r.ids){var n=s.createFrame(r.data);n.contextPath=s.appendContextPath(r.data.contextPath,r.name),r={data:n}}return a(e,r)})},t.exports=e[\"default\"]},function(t,e,r){\"use strict\";var s=r(1)[\"default\"];e.__esModule=!0;var i=r(5),a=r(6),n=s(a);e[\"default\"]=function(t){t.registerHelper(\"each\",function(t,e){function r(e,r,a){h&&(h.key=e,h.index=r,h.first=0===r,h.last=!!a,l&&(h.contextPath=l+e)),c+=s(t[e],{data:h,blockParams:i.blockParams([t[e],e],[l+e,null])})}if(!e)throw new n[\"default\"](\"Must pass iterator to #each\");var s=e.fn,a=e.inverse,o=0,c=\"\",h=void 0,l=void 0;if(e.data&&e.ids&&(l=i.appendContextPath(e.data.contextPath,e.ids[0])+\".\"),i.isFunction(t)&&(t=t.call(this)),e.data&&(h=i.createFrame(e.data)),t&&\"object\"==typeof t)if(i.isArray(t))for(var p=t.length;o<p;o++)o in t&&r(o,o,o===t.length-1);else{var u=void 0;for(var f in t)t.hasOwnProperty(f)&&(void 0!==u&&r(u,o-1),u=f,o++);void 0!==u&&r(u,o-1,!0)}return 0===o&&(c=a(this)),c})},t.exports=e[\"default\"]},function(t,e,r){\"use strict\";var s=r(1)[\"default\"];e.__esModule=!0;var i=r(6),a=s(i);e[\"default\"]=function(t){t.registerHelper(\"helperMissing\",function(){if(1!==arguments.length)throw new a[\"default\"]('Missing helper: \"'+arguments[arguments.length-1].name+'\"')})},t.exports=e[\"default\"]},function(t,e,r){\"use strict\";e.__esModule=!0;var s=r(5);e[\"default\"]=function(t){t.registerHelper(\"if\",function(t,e){return s.isFunction(t)&&(t=t.call(this)),!e.hash.includeZero&&!t||s.isEmpty(t)?e.inverse(this):e.fn(this)}),t.registerHelper(\"unless\",function(e,r){return t.helpers[\"if\"].call(this,e,{fn:r.inverse,inverse:r.fn,hash:r.hash})})},t.exports=e[\"default\"]},function(t,e){\"use strict\";e.__esModule=!0,e[\"default\"]=function(t){t.registerHelper(\"log\",function(){for(var e=[void 0],r=arguments[arguments.length-1],s=0;s<arguments.length-1;s++)e.push(arguments[s]);var i=1;null!=r.hash.level?i=r.hash.level:r.data&&null!=r.data.level&&(i=r.data.level),e[0]=i,t.log.apply(t,e)})},t.exports=e[\"default\"]},function(t,e){\"use strict\";e.__esModule=!0,e[\"default\"]=function(t){t.registerHelper(\"lookup\",function(t,e){return t&&t[e]})},t.exports=e[\"default\"]},function(t,e,r){\"use strict\";e.__esModule=!0;var s=r(5);e[\"default\"]=function(t){t.registerHelper(\"with\",function(t,e){s.isFunction(t)&&(t=t.call(this));var r=e.fn;if(s.isEmpty(t))return e.inverse(this);var i=e.data;return e.data&&e.ids&&(i=s.createFrame(e.data),i.contextPath=s.appendContextPath(e.data.contextPath,e.ids[0])),r(t,{data:i,blockParams:s.blockParams([t],[i&&i.contextPath])})})},t.exports=e[\"default\"]},function(t,e,r){\"use strict\";function s(t){n[\"default\"](t)}var i=r(1)[\"default\"];e.__esModule=!0,e.registerDefaultDecorators=s;var a=r(16),n=i(a)},function(t,e,r){\"use strict\";e.__esModule=!0;var s=r(5);e[\"default\"]=function(t){t.registerDecorator(\"inline\",function(t,e,r,i){var a=t;return e.partials||(e.partials={},a=function(i,a){var n=r.partials;r.partials=s.extend({},n,e.partials);var o=t(i,a);return r.partials=n,o}),e.partials[i.args[0]]=i.fn,a})},t.exports=e[\"default\"]},function(t,e,r){\"use strict\";e.__esModule=!0;var s=r(5),i={methodMap:[\"debug\",\"info\",\"warn\",\"error\"],level:\"info\",lookupLevel:function(t){if(\"string\"==typeof t){var e=s.indexOf(i.methodMap,t.toLowerCase());t=e>=0?e:parseInt(t,10)}return t},log:function(t){if(t=i.lookupLevel(t),\"undefined\"!=typeof console&&i.lookupLevel(i.level)<=t){var e=i.methodMap[t];console[e]||(e=\"log\");for(var r=arguments.length,s=Array(r>1?r-1:0),a=1;a<r;a++)s[a-1]=arguments[a];console[e].apply(console,s)}}};e[\"default\"]=i,t.exports=e[\"default\"]},function(t,e){\"use strict\";function r(t){this.string=t}e.__esModule=!0,r.prototype.toString=r.prototype.toHTML=function(){return\"\"+this.string},e[\"default\"]=r,t.exports=e[\"default\"]},function(t,e,r){\"use strict\";function s(t){var e=t&&t[0]||1,r=v.COMPILER_REVISION;if(e!==r){if(e<r){var s=v.REVISION_CHANGES[r],i=v.REVISION_CHANGES[e];throw new g[\"default\"](\"Template was precompiled with an older version of Handlebars than the current runtime. Please update your precompiler to a newer version (\"+s+\") or downgrade your runtime to an older version (\"+i+\").\")}throw new g[\"default\"](\"Template was precompiled with a newer version of Handlebars than the current runtime. Please update your runtime to a newer version (\"+t[1]+\").\")}}function i(t,e){function r(r,s,i){i.hash&&(s=d.extend({},s,i.hash),i.ids&&(i.ids[0]=!0)),r=e.VM.resolvePartial.call(this,r,s,i);var a=e.VM.invokePartial.call(this,r,s,i);if(null==a&&e.compile&&(i.partials[i.name]=e.compile(r,t.compilerOptions,e),a=i.partials[i.name](s,i)),null!=a){if(i.indent){for(var n=a.split(\"\\n\"),o=0,c=n.length;o<c&&(n[o]||o+1!==c);o++)n[o]=i.indent+n[o];a=n.join(\"\\n\")}return a}throw new g[\"default\"](\"The partial \"+i.name+\" could not be compiled when running in runtime-only mode\")}function s(e){function r(e){return\"\"+t.main(i,e,i.helpers,i.partials,n,c,o)}var a=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],n=a.data;s._setup(a),!a.partial&&t.useData&&(n=h(e,n));var o=void 0,c=t.useBlockParams?[]:void 0;return t.useDepths&&(o=a.depths?e!==a.depths[0]?[e].concat(a.depths):a.depths:[e]),(r=l(t.main,r,i,a.depths||[],n,c))(e,a)}if(!e)throw new g[\"default\"](\"No environment passed to template\");if(!t||!t.main)throw new g[\"default\"](\"Unknown template object: \"+typeof t);t.main.decorator=t.main_d,e.VM.checkRevision(t.compiler);var i={strict:function(t,e){if(!(e in t))throw new g[\"default\"]('\"'+e+'\" not defined in '+t);return t[e]},lookup:function(t,e){for(var r=t.length,s=0;s<r;s++)if(t[s]&&null!=t[s][e])return t[s][e]},lambda:function(t,e){return\"function\"==typeof t?t.call(e):t},escapeExpression:d.escapeExpression,invokePartial:r,fn:function(e){var r=t[e];return r.decorator=t[e+\"_d\"],r},programs:[],program:function(t,e,r,s,i){var n=this.programs[t],o=this.fn(t);return e||i||s||r?n=a(this,t,o,e,r,s,i):n||(n=this.programs[t]=a(this,t,o)),n},data:function(t,e){for(;t&&e--;)t=t._parent;return t},merge:function(t,e){var r=t||e;return t&&e&&t!==e&&(r=d.extend({},e,t)),r},noop:e.VM.noop,compilerInfo:t.compiler};return s.isTop=!0,s._setup=function(r){r.partial?(i.helpers=r.helpers,i.partials=r.partials,i.decorators=r.decorators):(i.helpers=i.merge(r.helpers,e.helpers),t.usePartial&&(i.partials=i.merge(r.partials,e.partials)),(t.usePartial||t.useDecorators)&&(i.decorators=i.merge(r.decorators,e.decorators)))},s._child=function(e,r,s,n){if(t.useBlockParams&&!s)throw new g[\"default\"](\"must pass block params\");if(t.useDepths&&!n)throw new g[\"default\"](\"must pass parent depths\");return a(i,e,t[e],r,0,s,n)},s}function a(t,e,r,s,i,a,n){function o(e){var i=arguments.length<=1||void 0===arguments[1]?{}:arguments[1],o=n;return n&&e!==n[0]&&(o=[e].concat(n)),r(t,e,t.helpers,t.partials,i.data||s,a&&[i.blockParams].concat(a),o)}return o=l(r,o,t,n,s,a),o.program=e,o.depth=n?n.length:0,o.blockParams=i||0,o}function n(t,e,r){return t?t.call||r.name||(r.name=t,t=r.partials[t]):t=\"@partial-block\"===r.name?r.data[\"partial-block\"]:r.partials[r.name],t}function o(t,e,r){r.partial=!0,r.ids&&(r.data.contextPath=r.ids[0]||r.data.contextPath);var s=void 0;if(r.fn&&r.fn!==c&&(r.data=v.createFrame(r.data),s=r.data[\"partial-block\"]=r.fn,s.partials&&(r.partials=d.extend({},r.partials,s.partials))),void 0===t&&s&&(t=s),void 0===t)throw new g[\"default\"](\"The partial \"+r.name+\" could not be found\");if(t instanceof Function)return t(e,r)}function c(){return\"\"}function h(t,e){return e&&\"root\"in e||(e=e?v.createFrame(e):{},e.root=t),e}function l(t,e,r,s,i,a){if(t.decorator){var n={};e=t.decorator(e,n,r,s&&s[0],i,a,s),d.extend(e,n)}return e}var p=r(3)[\"default\"],u=r(1)[\"default\"];e.__esModule=!0,e.checkRevision=s,e.template=i,e.wrapProgram=a,e.resolvePartial=n,e.invokePartial=o,e.noop=c;var f=r(5),d=p(f),m=r(6),g=u(m),v=r(4)},function(t,e){(function(r){\"use strict\";e.__esModule=!0,e[\"default\"]=function(t){var e=\"undefined\"!=typeof r?r:window,s=e.Handlebars;t.noConflict=function(){return e.Handlebars===t&&(e.Handlebars=s),t}},t.exports=e[\"default\"]}).call(e,function(){return this}())},function(t,e){\"use strict\";e.__esModule=!0;var r={helpers:{helperExpression:function(t){return\"SubExpression\"===t.type||(\"MustacheStatement\"===t.type||\"BlockStatement\"===t.type)&&!!(t.params&&t.params.length||t.hash)},scopedId:function(t){return/^\\.|this\\b/.test(t.original)},simpleId:function(t){return 1===t.parts.length&&!r.helpers.scopedId(t)&&!t.depth}}};e[\"default\"]=r,t.exports=e[\"default\"]},function(t,e,r){\"use strict\";function s(t,e){if(\"Program\"===t.type)return t;o[\"default\"].yy=f,f.locInfo=function(t){return new f.SourceLocation(e&&e.srcName,t)};var r=new h[\"default\"](e);return r.accept(o[\"default\"].parse(t))}var i=r(1)[\"default\"],a=r(3)[\"default\"];e.__esModule=!0,e.parse=s;var n=r(23),o=i(n),c=r(24),h=i(c),l=r(26),p=a(l),u=r(5);e.parser=o[\"default\"];var f={};u.extend(f,p)},function(t,e){\"use strict\";var r=function(){function t(){this.yy={}}var e={trace:function(){},yy:{},symbols_:{error:2,root:3,program:4,EOF:5,program_repetition0:6,statement:7,mustache:8,block:9,rawBlock:10,partial:11,partialBlock:12,content:13,COMMENT:14,CONTENT:15,openRawBlock:16,rawBlock_repetition_plus0:17,END_RAW_BLOCK:18,OPEN_RAW_BLOCK:19,helperName:20,openRawBlock_repetition0:21,openRawBlock_option0:22,CLOSE_RAW_BLOCK:23,openBlock:24,block_option0:25,closeBlock:26,openInverse:27,block_option1:28,OPEN_BLOCK:29,openBlock_repetition0:30,openBlock_option0:31,openBlock_option1:32,CLOSE:33,OPEN_INVERSE:34,openInverse_repetition0:35,openInverse_option0:36,openInverse_option1:37,openInverseChain:38,OPEN_INVERSE_CHAIN:39,openInverseChain_repetition0:40,openInverseChain_option0:41,openInverseChain_option1:42,inverseAndProgram:43,INVERSE:44,inverseChain:45,inverseChain_option0:46,OPEN_ENDBLOCK:47,OPEN:48,mustache_repetition0:49,mustache_option0:50,OPEN_UNESCAPED:51,mustache_repetition1:52,mustache_option1:53,CLOSE_UNESCAPED:54,OPEN_PARTIAL:55,partialName:56,partial_repetition0:57,partial_option0:58,openPartialBlock:59,OPEN_PARTIAL_BLOCK:60,openPartialBlock_repetition0:61,openPartialBlock_option0:62,param:63,sexpr:64,OPEN_SEXPR:65,sexpr_repetition0:66,sexpr_option0:67,CLOSE_SEXPR:68,hash:69,hash_repetition_plus0:70,hashSegment:71,ID:72,EQUALS:73,blockParams:74,OPEN_BLOCK_PARAMS:75,blockParams_repetition_plus0:76,CLOSE_BLOCK_PARAMS:77,path:78,dataName:79,STRING:80,NUMBER:81,BOOLEAN:82,UNDEFINED:83,NULL:84,DATA:85,pathSegments:86,SEP:87,$accept:0,$end:1},terminals_:{2:\"error\",5:\"EOF\",14:\"COMMENT\",15:\"CONTENT\",18:\"END_RAW_BLOCK\",19:\"OPEN_RAW_BLOCK\",23:\"CLOSE_RAW_BLOCK\",29:\"OPEN_BLOCK\",33:\"CLOSE\",34:\"OPEN_INVERSE\",39:\"OPEN_INVERSE_CHAIN\",44:\"INVERSE\",47:\"OPEN_ENDBLOCK\",48:\"OPEN\",51:\"OPEN_UNESCAPED\",54:\"CLOSE_UNESCAPED\",55:\"OPEN_PARTIAL\",60:\"OPEN_PARTIAL_BLOCK\",65:\"OPEN_SEXPR\",68:\"CLOSE_SEXPR\",72:\"ID\",73:\"EQUALS\",75:\"OPEN_BLOCK_PARAMS\",77:\"CLOSE_BLOCK_PARAMS\",80:\"STRING\",81:\"NUMBER\",82:\"BOOLEAN\",83:\"UNDEFINED\",84:\"NULL\",85:\"DATA\",87:\"SEP\"},productions_:[0,[3,2],[4,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[7,1],[13,1],[10,3],[16,5],[9,4],[9,4],[24,6],[27,6],[38,6],[43,2],[45,3],[45,1],[26,3],[8,5],[8,5],[11,5],[12,3],[59,5],[63,1],[63,1],[64,5],[69,1],[71,3],[74,3],[20,1],[20,1],[20,1],[20,1],[20,1],[20,1],[20,1],[56,1],[56,1],[79,2],[78,1],[86,3],[86,1],[6,0],[6,2],[17,1],[17,2],[21,0],[21,2],[22,0],[22,1],[25,0],[25,1],[28,0],[28,1],[30,0],[30,2],[31,0],[31,1],[32,0],[32,1],[35,0],[35,2],[36,0],[36,1],[37,0],[37,1],[40,0],[40,2],[41,0],[41,1],[42,0],[42,1],[46,0],[46,1],[49,0],[49,2],[50,0],[50,1],[52,0],[52,2],[53,0],[53,1],[57,0],[57,2],[58,0],[58,1],[61,0],[61,2],[62,0],[62,1],[66,0],[66,2],[67,0],[67,1],[70,1],[70,2],[76,1],[76,2]],performAction:function(t,e,r,s,i,a,n){var o=a.length-1;switch(i){case 1:return a[o-1];case 2:this.$=s.prepareProgram(a[o]);break;case 3:this.$=a[o];break;case 4:this.$=a[o];break;case 5:this.$=a[o];break;case 6:this.$=a[o];break;case 7:this.$=a[o];break;case 8:this.$=a[o];break;case 9:this.$={type:\"CommentStatement\",value:s.stripComment(a[o]),strip:s.stripFlags(a[o],a[o]),loc:s.locInfo(this._$)};break;case 10:this.$={type:\"ContentStatement\",original:a[o],value:a[o],loc:s.locInfo(this._$)};break;case 11:this.$=s.prepareRawBlock(a[o-2],a[o-1],a[o],this._$);break;case 12:this.$={path:a[o-3],params:a[o-2],hash:a[o-1]};break;case 13:this.$=s.prepareBlock(a[o-3],a[o-2],a[o-1],a[o],!1,this._$);break;case 14:this.$=s.prepareBlock(a[o-3],a[o-2],a[o-1],a[o],!0,this._$);break;case 15:this.$={open:a[o-5],path:a[o-4],params:a[o-3],hash:a[o-2],blockParams:a[o-1],strip:s.stripFlags(a[o-5],a[o])};break;case 16:this.$={path:a[o-4],params:a[o-3],hash:a[o-2],blockParams:a[o-1],strip:s.stripFlags(a[o-5],a[o])};break;case 17:this.$={path:a[o-4],params:a[o-3],hash:a[o-2],blockParams:a[o-1],strip:s.stripFlags(a[o-5],a[o])};break;case 18:this.$={strip:s.stripFlags(a[o-1],a[o-1]),program:a[o]};break;case 19:var c=s.prepareBlock(a[o-2],a[o-1],a[o],a[o],!1,this._$),h=s.prepareProgram([c],a[o-1].loc);h.chained=!0,this.$={strip:a[o-2].strip,program:h,chain:!0};break;case 20:this.$=a[o];break;case 21:this.$={path:a[o-1],strip:s.stripFlags(a[o-2],a[o])};break;case 22:this.$=s.prepareMustache(a[o-3],a[o-2],a[o-1],a[o-4],s.stripFlags(a[o-4],a[o]),this._$);break;case 23:this.$=s.prepareMustache(a[o-3],a[o-2],a[o-1],a[o-4],s.stripFlags(a[o-4],a[o]),this._$);break;case 24:this.$={type:\"PartialStatement\",name:a[o-3],params:a[o-2],hash:a[o-1],indent:\"\",strip:s.stripFlags(a[o-4],a[o]),loc:s.locInfo(this._$)};break;case 25:this.$=s.preparePartialBlock(a[o-2],a[o-1],a[o],this._$);break;case 26:this.$={path:a[o-3],params:a[o-2],hash:a[o-1],strip:s.stripFlags(a[o-4],a[o])};break;case 27:this.$=a[o];break;case 28:this.$=a[o];break;case 29:this.$={type:\"SubExpression\",path:a[o-3],params:a[o-2],hash:a[o-1],loc:s.locInfo(this._$)};break;case 30:this.$={type:\"Hash\",pairs:a[o],loc:s.locInfo(this._$)};break;case 31:this.$={type:\"HashPair\",key:s.id(a[o-2]),value:a[o],loc:s.locInfo(this._$)};break;case 32:this.$=s.id(a[o-1]);break;case 33:this.$=a[o];break;case 34:this.$=a[o];break;case 35:this.$={type:\"StringLiteral\",value:a[o],original:a[o],loc:s.locInfo(this._$)};break;case 36:this.$={type:\"NumberLiteral\",value:Number(a[o]),original:Number(a[o]),loc:s.locInfo(this._$)};break;case 37:this.$={type:\"BooleanLiteral\",value:\"true\"===a[o],original:\"true\"===a[o],loc:s.locInfo(this._$)};break;case 38:this.$={type:\"UndefinedLiteral\",original:void 0,value:void 0,loc:s.locInfo(this._$)};break;case 39:this.$={type:\"NullLiteral\",original:null,value:null,loc:s.locInfo(this._$)};break;case 40:this.$=a[o];break;case 41:this.$=a[o];break;case 42:this.$=s.preparePath(!0,a[o],this._$);break;case 43:this.$=s.preparePath(!1,a[o],this._$);break;case 44:a[o-2].push({part:s.id(a[o]),original:a[o],separator:a[o-1]}),this.$=a[o-2];break;case 45:this.$=[{part:s.id(a[o]),original:a[o]}];break;case 46:this.$=[];break;case 47:a[o-1].push(a[o]);break;case 48:this.$=[a[o]];break;case 49:a[o-1].push(a[o]);break;case 50:this.$=[];break;case 51:a[o-1].push(a[o]);break;case 58:this.$=[];break;case 59:a[o-1].push(a[o]);break;case 64:this.$=[];break;case 65:a[o-1].push(a[o]);break;case 70:this.$=[];break;case 71:a[o-1].push(a[o]);break;case 78:this.$=[];break;case 79:a[o-1].push(a[o]);break;case 82:this.$=[];break;case 83:a[o-1].push(a[o]);break;case 86:this.$=[];break;case 87:a[o-1].push(a[o]);break;case 90:this.$=[];break;case 91:a[o-1].push(a[o]);break;case 94:this.$=[];break;case 95:a[o-1].push(a[o]);break;case 98:this.$=[a[o]];break;case 99:a[o-1].push(a[o]);break;case 100:this.$=[a[o]];break;case 101:a[o-1].push(a[o])}},table:[{3:1,4:2,5:[2,46],6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{1:[3]},{5:[1,4]},{5:[2,2],7:5,8:6,9:7,10:8,11:9,12:10,13:11,14:[1,12],15:[1,20],16:17,19:[1,23],24:15,27:16,29:[1,21],34:[1,22],39:[2,2],44:[2,2],47:[2,2],48:[1,13],51:[1,14],55:[1,18],59:19,60:[1,24]},{1:[2,1]},{5:[2,47],14:[2,47],15:[2,47],19:[2,47],29:[2,47],34:[2,47],39:[2,47],44:[2,47],47:[2,47],48:[2,47],51:[2,47],55:[2,47],60:[2,47]},{5:[2,3],14:[2,3],15:[2,3],19:[2,3],29:[2,3],34:[2,3],39:[2,3],44:[2,3],47:[2,3],48:[2,3],51:[2,3],55:[2,3],60:[2,3]},{5:[2,4],14:[2,4],15:[2,4],19:[2,4],29:[2,4],34:[2,4],39:[2,4],44:[2,4],47:[2,4],48:[2,4],51:[2,4],55:[2,4],60:[2,4]},{5:[2,5],14:[2,5],15:[2,5],19:[2,5],29:[2,5],34:[2,5],39:[2,5],44:[2,5],47:[2,5],48:[2,5],51:[2,5],55:[2,5],60:[2,5]},{5:[2,6],14:[2,6],15:[2,6],19:[2,6],29:[2,6],34:[2,6],39:[2,6],44:[2,6],47:[2,6],48:[2,6],51:[2,6],55:[2,6],60:[2,6]},{5:[2,7],14:[2,7],15:[2,7],19:[2,7],29:[2,7],34:[2,7],39:[2,7],44:[2,7],47:[2,7],48:[2,7],51:[2,7],55:[2,7],60:[2,7]},{5:[2,8],14:[2,8],15:[2,8],19:[2,8],29:[2,8],34:[2,8],39:[2,8],44:[2,8],47:[2,8],48:[2,8],51:[2,8],55:[2,8],60:[2,8]},{5:[2,9],14:[2,9],15:[2,9],19:[2,9],29:[2,9],34:[2,9],39:[2,9],44:[2,9],47:[2,9],48:[2,9],51:[2,9],55:[2,9],60:[2,9]},{20:25,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:36,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{4:37,6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],39:[2,46],44:[2,46],47:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{4:38,6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],44:[2,46],47:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{13:40,15:[1,20],17:39},{20:42,56:41,64:43,65:[1,44],72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{4:45,6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],47:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{5:[2,10],14:[2,10],15:[2,10],18:[2,10],19:[2,10],29:[2,10],34:[2,10],39:[2,10],44:[2,10],47:[2,10],48:[2,10],51:[2,10],55:[2,10],60:[2,10]},{20:46,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:47,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:48,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:42,56:49,64:43,65:[1,44],72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{33:[2,78],49:50,65:[2,78],72:[2,78],80:[2,78],81:[2,78],82:[2,78],83:[2,78],84:[2,78],85:[2,78]},{23:[2,33],33:[2,33],54:[2,33],65:[2,33],68:[2,33],72:[2,33],75:[2,33],80:[2,33],81:[2,33],82:[2,33],83:[2,33],84:[2,33],85:[2,33]},{23:[2,34],33:[2,34],54:[2,34],65:[2,34],68:[2,34],72:[2,34],75:[2,34],80:[2,34],81:[2,34],82:[2,34],83:[2,34],84:[2,34],85:[2,34]},{23:[2,35],33:[2,35],54:[2,35],65:[2,35],68:[2,35],72:[2,35],75:[2,35],80:[2,35],81:[2,35],82:[2,35],83:[2,35],84:[2,35],85:[2,35]},{23:[2,36],33:[2,36],54:[2,36],65:[2,36],68:[2,36],72:[2,36],75:[2,36],80:[2,36],81:[2,36],82:[2,36],83:[2,36],84:[2,36],85:[2,36]},{23:[2,37],33:[2,37],54:[2,37],65:[2,37],68:[2,37],72:[2,37],75:[2,37],80:[2,37],81:[2,37],82:[2,37],83:[2,37],84:[2,37],85:[2,37]},{23:[2,38],33:[2,38],54:[2,38],65:[2,38],68:[2,38],72:[2,38],75:[2,38],80:[2,38],81:[2,38],82:[2,38],83:[2,38],84:[2,38],85:[2,38]},{23:[2,39],33:[2,39],54:[2,39],65:[2,39],68:[2,39],72:[2,39],75:[2,39],80:[2,39],81:[2,39],82:[2,39],83:[2,39],84:[2,39],85:[2,39]},{23:[2,43],33:[2,43],54:[2,43],65:[2,43],68:[2,43],72:[2,43],75:[2,43],80:[2,43],81:[2,43],82:[2,43],83:[2,43],84:[2,43],85:[2,43],87:[1,51]},{72:[1,35],86:52},{23:[2,45],33:[2,45],54:[2,45],65:[2,45],68:[2,45],72:[2,45],75:[2,45],80:[2,45],81:[2,45],82:[2,45],83:[2,45],84:[2,45],85:[2,45],87:[2,45]},{52:53,54:[2,82],65:[2,82],72:[2,82],80:[2,82],81:[2,82],82:[2,82],83:[2,82],84:[2,82],85:[2,82]},{25:54,38:56,39:[1,58],43:57,44:[1,59],45:55,47:[2,54]},{28:60,43:61,44:[1,59],47:[2,56]},{13:63,15:[1,20],18:[1,62]},{15:[2,48],18:[2,48]},{33:[2,86],57:64,65:[2,86],72:[2,86],80:[2,86],81:[2,86],82:[2,86],83:[2,86],84:[2,86],85:[2,86]},{33:[2,40],65:[2,40],72:[2,40],80:[2,40],81:[2,40],82:[2,40],83:[2,40],84:[2,40],85:[2,40]},{33:[2,41],65:[2,41],72:[2,41],80:[2,41],81:[2,41],82:[2,41],83:[2,41],84:[2,41],85:[2,41]},{20:65,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{26:66,47:[1,67]},{30:68,33:[2,58],65:[2,58],72:[2,58],75:[2,58],80:[2,58],81:[2,58],82:[2,58],83:[2,58],84:[2,58],85:[2,58]},{33:[2,64],35:69,65:[2,64],72:[2,64],75:[2,64],80:[2,64],81:[2,64],82:[2,64],83:[2,64],84:[2,64],85:[2,64]},{21:70,23:[2,50],65:[2,50],72:[2,50],80:[2,50],81:[2,50],82:[2,50],83:[2,50],84:[2,50],85:[2,50]},{33:[2,90],61:71,65:[2,90],72:[2,90],80:[2,90],81:[2,90],82:[2,90],83:[2,90],84:[2,90],85:[2,90]},{20:75,33:[2,80],50:72,63:73,64:76,65:[1,44],69:74,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{72:[1,80]},{23:[2,42],33:[2,42],54:[2,42],65:[2,42],68:[2,42],72:[2,42],75:[2,42],80:[2,42],81:[2,42],82:[2,42],83:[2,42],84:[2,42],85:[2,42],87:[1,51]},{20:75,53:81,54:[2,84],63:82,64:76,65:[1,44],69:83,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{26:84,47:[1,67]},{47:[2,55]},{4:85,6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],39:[2,46],44:[2,46],47:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{47:[2,20]},{20:86,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{4:87,6:3,14:[2,46],15:[2,46],19:[2,46],29:[2,46],34:[2,46],47:[2,46],48:[2,46],51:[2,46],55:[2,46],60:[2,46]},{26:88,47:[1,67]},{47:[2,57]},{5:[2,11],14:[2,11],15:[2,11],19:[2,11],29:[2,11],34:[2,11],39:[2,11],44:[2,11],47:[2,11],48:[2,11],51:[2,11],55:[2,11],60:[2,11]},{15:[2,49],18:[2,49]},{20:75,33:[2,88],58:89,63:90,64:76,65:[1,44],69:91,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{65:[2,94],66:92,68:[2,94],72:[2,94],80:[2,94],81:[2,94],82:[2,94],83:[2,94],84:[2,94],85:[2,94]},{5:[2,25],14:[2,25],15:[2,25],19:[2,25],29:[2,25],34:[2,25],39:[2,25],44:[2,25],47:[2,25],48:[2,25],51:[2,25],55:[2,25],60:[2,25]},{20:93,72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:75,31:94,33:[2,60],63:95,64:76,65:[1,44],69:96,70:77,71:78,72:[1,79],75:[2,60],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:75,33:[2,66],36:97,63:98,64:76,65:[1,44],69:99,70:77,71:78,72:[1,79],75:[2,66],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:75,22:100,23:[2,52],63:101,64:76,65:[1,44],69:102,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{20:75,33:[2,92],62:103,63:104,64:76,65:[1,44],69:105,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{33:[1,106]},{33:[2,79],65:[2,79],72:[2,79],80:[2,79],81:[2,79],82:[2,79],83:[2,79],84:[2,79],85:[2,79]},{33:[2,81]},{23:[2,27],33:[2,27],54:[2,27],65:[2,27],68:[2,27],72:[2,27],75:[2,27],80:[2,27],81:[2,27],82:[2,27],83:[2,27],84:[2,27],85:[2,27]},{23:[2,28],33:[2,28],54:[2,28],65:[2,28],68:[2,28],72:[2,28],75:[2,28],80:[2,28],81:[2,28],82:[2,28],83:[2,28],84:[2,28],85:[2,28]},{23:[2,30],33:[2,30],54:[2,30],68:[2,30],71:107,72:[1,108],75:[2,30]},{23:[2,98],33:[2,98],54:[2,98],68:[2,98],72:[2,98],75:[2,98]},{23:[2,45],33:[2,45],54:[2,45],65:[2,45],68:[2,45],72:[2,45],73:[1,109],75:[2,45],80:[2,45],81:[2,45],82:[2,45],83:[2,45],84:[2,45],85:[2,45],87:[2,45]},{23:[2,44],33:[2,44],54:[2,44],65:[2,44],68:[2,44],72:[2,44],75:[2,44],80:[2,44],81:[2,44],82:[2,44],83:[2,44],84:[2,44],85:[2,44],87:[2,44]},{54:[1,110]},{54:[2,83],65:[2,83],72:[2,83],80:[2,83],81:[2,83],82:[2,83],83:[2,83],84:[2,83],85:[2,83]},{54:[2,85]},{5:[2,13],14:[2,13],15:[2,13],19:[2,13],29:[2,13],34:[2,13],39:[2,13],44:[2,13],47:[2,13],48:[2,13],51:[2,13],55:[2,13],60:[2,13]},{38:56,39:[1,58],43:57,44:[1,59],45:112,46:111,47:[2,76]},{33:[2,70],40:113,65:[2,70],72:[2,70],75:[2,70],80:[2,70],81:[2,70],82:[2,70],83:[2,70],84:[2,70],85:[2,70]},{47:[2,18]},{5:[2,14],14:[2,14],15:[2,14],19:[2,14],29:[2,14],34:[2,14],39:[2,14],44:[2,14],47:[2,14],48:[2,14],51:[2,14],55:[2,14],60:[2,14]},{33:[1,114]},{33:[2,87],65:[2,87],72:[2,87],80:[2,87],81:[2,87],82:[2,87],83:[2,87],84:[2,87],85:[2,87]},{33:[2,89]},{20:75,63:116,64:76,65:[1,44],67:115,68:[2,96],69:117,70:77,71:78,72:[1,79],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{33:[1,118]},{32:119,33:[2,62],74:120,75:[1,121]},{33:[2,59],65:[2,59],72:[2,59],75:[2,59],80:[2,59],81:[2,59],82:[2,59],83:[2,59],84:[2,59],85:[2,59]},{33:[2,61],75:[2,61]},{33:[2,68],37:122,74:123,75:[1,121]},{33:[2,65],65:[2,65],72:[2,65],75:[2,65],80:[2,65],81:[2,65],82:[2,65],83:[2,65],84:[2,65],85:[2,65]},{33:[2,67],75:[2,67]},{23:[1,124]},{23:[2,51],65:[2,51],72:[2,51],80:[2,51],81:[2,51],82:[2,51],83:[2,51],84:[2,51],85:[2,51]},{23:[2,53]},{33:[1,125]},{33:[2,91],65:[2,91],72:[2,91],80:[2,91],81:[2,91],82:[2,91],83:[2,91],84:[2,91],85:[2,91]},{33:[2,93]},{5:[2,22],14:[2,22],15:[2,22],19:[2,22],29:[2,22],34:[2,22],39:[2,22],44:[2,22],47:[2,22],48:[2,22],51:[2,22],55:[2,22],60:[2,22]},{23:[2,99],33:[2,99],54:[2,99],68:[2,99],72:[2,99],75:[2,99]},{73:[1,109]},{20:75,63:126,64:76,65:[1,44],72:[1,35],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{5:[2,23],14:[2,23],15:[2,23],19:[2,23],29:[2,23],34:[2,23],39:[2,23],44:[2,23],47:[2,23],48:[2,23],51:[2,23],55:[2,23],60:[2,23]},{47:[2,19]},{47:[2,77]},{20:75,33:[2,72],41:127,63:128,64:76,65:[1,44],69:129,70:77,71:78,72:[1,79],75:[2,72],78:26,79:27,80:[1,28],81:[1,29],82:[1,30],83:[1,31],84:[1,32],85:[1,34],86:33},{5:[2,24],14:[2,24],15:[2,24],19:[2,24],29:[2,24],34:[2,24],39:[2,24],44:[2,24],47:[2,24],48:[2,24],51:[2,24],55:[2,24],60:[2,24]},{68:[1,130]},{65:[2,95],68:[2,95],72:[2,95],80:[2,95],81:[2,95],82:[2,95],83:[2,95],84:[2,95],85:[2,95]},{68:[2,97]},{5:[2,21],14:[2,21],15:[2,21],19:[2,21],29:[2,21],34:[2,21],39:[2,21],44:[2,21],47:[2,21],48:[2,21],51:[2,21],55:[2,21],60:[2,21]},{33:[1,131]},{33:[2,63]},{72:[1,133],76:132},{33:[1,134]},{33:[2,69]},{15:[2,12]},{14:[2,26],15:[2,26],19:[2,26],29:[2,26],34:[2,26],47:[2,26],48:[2,26],51:[2,26],55:[2,26],60:[2,26]},{23:[2,31],33:[2,31],54:[2,31],68:[2,31],72:[2,31],75:[2,31]},{33:[2,74],42:135,74:136,75:[1,121]},{33:[2,71],65:[2,71],72:[2,71],75:[2,71],80:[2,71],81:[2,71],82:[2,71],83:[2,71],84:[2,71],85:[2,71]},{33:[2,73],75:[2,73]},{23:[2,29],33:[2,29],54:[2,29],65:[2,29],68:[2,29],72:[2,29],75:[2,29],80:[2,29],81:[2,29],82:[2,29],83:[2,29],84:[2,29],85:[2,29]},{14:[2,15],15:[2,15],19:[2,15],29:[2,15],34:[2,15],39:[2,15],44:[2,15],47:[2,15],48:[2,15],51:[2,15],55:[2,15],60:[2,15]},{72:[1,138],77:[1,137]},{72:[2,100],77:[2,100]},{14:[2,16],15:[2,16],19:[2,16],29:[2,16],34:[2,16],44:[2,16],47:[2,16],\n48:[2,16],51:[2,16],55:[2,16],60:[2,16]},{33:[1,139]},{33:[2,75]},{33:[2,32]},{72:[2,101],77:[2,101]},{14:[2,17],15:[2,17],19:[2,17],29:[2,17],34:[2,17],39:[2,17],44:[2,17],47:[2,17],48:[2,17],51:[2,17],55:[2,17],60:[2,17]}],defaultActions:{4:[2,1],55:[2,55],57:[2,20],61:[2,57],74:[2,81],83:[2,85],87:[2,18],91:[2,89],102:[2,53],105:[2,93],111:[2,19],112:[2,77],117:[2,97],120:[2,63],123:[2,69],124:[2,12],136:[2,75],137:[2,32]},parseError:function(t,e){throw new Error(t)},parse:function(t){function e(){var t;return t=r.lexer.lex()||1,\"number\"!=typeof t&&(t=r.symbols_[t]||t),t}var r=this,s=[0],i=[null],a=[],n=this.table,o=\"\",c=0,h=0,l=0;this.lexer.setInput(t),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,this.yy.parser=this,\"undefined\"==typeof this.lexer.yylloc&&(this.lexer.yylloc={});var p=this.lexer.yylloc;a.push(p);var u=this.lexer.options&&this.lexer.options.ranges;\"function\"==typeof this.yy.parseError&&(this.parseError=this.yy.parseError);for(var f,d,m,g,v,y,k,S,b,_={};;){if(m=s[s.length-1],this.defaultActions[m]?g=this.defaultActions[m]:(null!==f&&\"undefined\"!=typeof f||(f=e()),g=n[m]&&n[m][f]),\"undefined\"==typeof g||!g.length||!g[0]){var P=\"\";if(!l){b=[];for(y in n[m])this.terminals_[y]&&y>2&&b.push(\"'\"+this.terminals_[y]+\"'\");P=this.lexer.showPosition?\"Parse error on line \"+(c+1)+\":\\n\"+this.lexer.showPosition()+\"\\nExpecting \"+b.join(\", \")+\", got '\"+(this.terminals_[f]||f)+\"'\":\"Parse error on line \"+(c+1)+\": Unexpected \"+(1==f?\"end of input\":\"'\"+(this.terminals_[f]||f)+\"'\"),this.parseError(P,{text:this.lexer.match,token:this.terminals_[f]||f,line:this.lexer.yylineno,loc:p,expected:b})}}if(g[0]instanceof Array&&g.length>1)throw new Error(\"Parse Error: multiple actions possible at state: \"+m+\", token: \"+f);switch(g[0]){case 1:s.push(f),i.push(this.lexer.yytext),a.push(this.lexer.yylloc),s.push(g[1]),f=null,d?(f=d,d=null):(h=this.lexer.yyleng,o=this.lexer.yytext,c=this.lexer.yylineno,p=this.lexer.yylloc,l>0&&l--);break;case 2:if(k=this.productions_[g[1]][1],_.$=i[i.length-k],_._$={first_line:a[a.length-(k||1)].first_line,last_line:a[a.length-1].last_line,first_column:a[a.length-(k||1)].first_column,last_column:a[a.length-1].last_column},u&&(_._$.range=[a[a.length-(k||1)].range[0],a[a.length-1].range[1]]),v=this.performAction.call(_,o,h,c,this.yy,g[1],i,a),\"undefined\"!=typeof v)return v;k&&(s=s.slice(0,-1*k*2),i=i.slice(0,-1*k),a=a.slice(0,-1*k)),s.push(this.productions_[g[1]][0]),i.push(_.$),a.push(_._$),S=n[s[s.length-2]][s[s.length-1]],s.push(S);break;case 3:return!0}}return!0}},r=function(){var t={EOF:1,parseError:function(t,e){if(!this.yy.parser)throw new Error(t);this.yy.parser.parseError(t,e)},setInput:function(t){return this._input=t,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match=\"\",this.conditionStack=[\"INITIAL\"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var t=this._input[0];this.yytext+=t,this.yyleng++,this.offset++,this.match+=t,this.matched+=t;var e=t.match(/(?:\\r\\n?|\\n).*/g);return e?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),t},unput:function(t){var e=t.length,r=t.split(/(?:\\r\\n?|\\n)/g);this._input=t+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-e-1),this.offset-=e;var s=this.match.split(/(?:\\r\\n?|\\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),r.length-1&&(this.yylineno-=r.length-1);var i=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:r?(r.length===s.length?this.yylloc.first_column:0)+s[s.length-r.length].length-r[0].length:this.yylloc.first_column-e},this.options.ranges&&(this.yylloc.range=[i[0],i[0]+this.yyleng-e]),this},more:function(){return this._more=!0,this},less:function(t){this.unput(this.match.slice(t))},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?\"...\":\"\")+t.substr(-20).replace(/\\n/g,\"\")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?\"...\":\"\")).replace(/\\n/g,\"\")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join(\"-\");return t+this.upcomingInput()+\"\\n\"+e+\"^\"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var t,e,r,s,i;this._more||(this.yytext=\"\",this.match=\"\");for(var a=this._currentRules(),n=0;n<a.length&&(r=this._input.match(this.rules[a[n]]),!r||e&&!(r[0].length>e[0].length)||(e=r,s=n,this.options.flex));n++);return e?(i=e[0].match(/(?:\\r\\n?|\\n).*/g),i&&(this.yylineno+=i.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:i?i[i.length-1].length-i[i.length-1].match(/\\r?\\n?/)[0].length:this.yylloc.last_column+e[0].length},this.yytext+=e[0],this.match+=e[0],this.matches=e,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._input=this._input.slice(e[0].length),this.matched+=e[0],t=this.performAction.call(this,this.yy,this,a[s],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),t?t:void 0):\"\"===this._input?this.EOF:this.parseError(\"Lexical error on line \"+(this.yylineno+1)+\". Unrecognized text.\\n\"+this.showPosition(),{text:\"\",token:null,line:this.yylineno})},lex:function(){var t=this.next();return\"undefined\"!=typeof t?t:this.lex()},begin:function(t){this.conditionStack.push(t)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(t){this.begin(t)}};return t.options={},t.performAction=function(t,e,r,s){function i(t,r){return e.yytext=e.yytext.substr(t,e.yyleng-r)}switch(r){case 0:if(\"\\\\\\\\\"===e.yytext.slice(-2)?(i(0,1),this.begin(\"mu\")):\"\\\\\"===e.yytext.slice(-1)?(i(0,1),this.begin(\"emu\")):this.begin(\"mu\"),e.yytext)return 15;break;case 1:return 15;case 2:return this.popState(),15;case 3:return this.begin(\"raw\"),15;case 4:return this.popState(),\"raw\"===this.conditionStack[this.conditionStack.length-1]?15:(e.yytext=e.yytext.substr(5,e.yyleng-9),\"END_RAW_BLOCK\");case 5:return 15;case 6:return this.popState(),14;case 7:return 65;case 8:return 68;case 9:return 19;case 10:return this.popState(),this.begin(\"raw\"),23;case 11:return 55;case 12:return 60;case 13:return 29;case 14:return 47;case 15:return this.popState(),44;case 16:return this.popState(),44;case 17:return 34;case 18:return 39;case 19:return 51;case 20:return 48;case 21:this.unput(e.yytext),this.popState(),this.begin(\"com\");break;case 22:return this.popState(),14;case 23:return 48;case 24:return 73;case 25:return 72;case 26:return 72;case 27:return 87;case 28:break;case 29:return this.popState(),54;case 30:return this.popState(),33;case 31:return e.yytext=i(1,2).replace(/\\\\\"/g,'\"'),80;case 32:return e.yytext=i(1,2).replace(/\\\\'/g,\"'\"),80;case 33:return 85;case 34:return 82;case 35:return 82;case 36:return 83;case 37:return 84;case 38:return 81;case 39:return 75;case 40:return 77;case 41:return 72;case 42:return e.yytext=e.yytext.replace(/\\\\([\\\\\\]])/g,\"$1\"),72;case 43:return\"INVALID\";case 44:return 5}},t.rules=[/^(?:[^\\x00]*?(?=(\\{\\{)))/,/^(?:[^\\x00]+)/,/^(?:[^\\x00]{2,}?(?=(\\{\\{|\\\\\\{\\{|\\\\\\\\\\{\\{|$)))/,/^(?:\\{\\{\\{\\{(?=[^\\/]))/,/^(?:\\{\\{\\{\\{\\/[^\\s!\"#%-,\\.\\/;->@\\[-\\^`\\{-~]+(?=[=}\\s\\/.])\\}\\}\\}\\})/,/^(?:[^\\x00]*?(?=(\\{\\{\\{\\{)))/,/^(?:[\\s\\S]*?--(~)?\\}\\})/,/^(?:\\()/,/^(?:\\))/,/^(?:\\{\\{\\{\\{)/,/^(?:\\}\\}\\}\\})/,/^(?:\\{\\{(~)?>)/,/^(?:\\{\\{(~)?#>)/,/^(?:\\{\\{(~)?#\\*?)/,/^(?:\\{\\{(~)?\\/)/,/^(?:\\{\\{(~)?\\^\\s*(~)?\\}\\})/,/^(?:\\{\\{(~)?\\s*else\\s*(~)?\\}\\})/,/^(?:\\{\\{(~)?\\^)/,/^(?:\\{\\{(~)?\\s*else\\b)/,/^(?:\\{\\{(~)?\\{)/,/^(?:\\{\\{(~)?&)/,/^(?:\\{\\{(~)?!--)/,/^(?:\\{\\{(~)?![\\s\\S]*?\\}\\})/,/^(?:\\{\\{(~)?\\*?)/,/^(?:=)/,/^(?:\\.\\.)/,/^(?:\\.(?=([=~}\\s\\/.)|])))/,/^(?:[\\/.])/,/^(?:\\s+)/,/^(?:\\}(~)?\\}\\})/,/^(?:(~)?\\}\\})/,/^(?:\"(\\\\[\"]|[^\"])*\")/,/^(?:'(\\\\[']|[^'])*')/,/^(?:@)/,/^(?:true(?=([~}\\s)])))/,/^(?:false(?=([~}\\s)])))/,/^(?:undefined(?=([~}\\s)])))/,/^(?:null(?=([~}\\s)])))/,/^(?:-?[0-9]+(?:\\.[0-9]+)?(?=([~}\\s)])))/,/^(?:as\\s+\\|)/,/^(?:\\|)/,/^(?:([^\\s!\"#%-,\\.\\/;->@\\[-\\^`\\{-~]+(?=([=~}\\s\\/.)|]))))/,/^(?:\\[(\\\\\\]|[^\\]])*\\])/,/^(?:.)/,/^(?:$)/],t.conditions={mu:{rules:[7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],inclusive:!1},emu:{rules:[2],inclusive:!1},com:{rules:[6],inclusive:!1},raw:{rules:[3,4,5],inclusive:!1},INITIAL:{rules:[0,1,44],inclusive:!0}},t}();return e.lexer=r,t.prototype=e,e.Parser=t,new t}();e.__esModule=!0,e[\"default\"]=r},function(t,e,r){\"use strict\";function s(){var t=arguments.length<=0||void 0===arguments[0]?{}:arguments[0];this.options=t}function i(t,e,r){void 0===e&&(e=t.length);var s=t[e-1],i=t[e-2];return s?\"ContentStatement\"===s.type?(i||!r?/\\r?\\n\\s*?$/:/(^|\\r?\\n)\\s*?$/).test(s.original):void 0:r}function a(t,e,r){void 0===e&&(e=-1);var s=t[e+1],i=t[e+2];return s?\"ContentStatement\"===s.type?(i||!r?/^\\s*?\\r?\\n/:/^\\s*?(\\r?\\n|$)/).test(s.original):void 0:r}function n(t,e,r){var s=t[null==e?0:e+1];if(s&&\"ContentStatement\"===s.type&&(r||!s.rightStripped)){var i=s.value;s.value=s.value.replace(r?/^\\s+/:/^[ \\t]*\\r?\\n?/,\"\"),s.rightStripped=s.value!==i}}function o(t,e,r){var s=t[null==e?t.length-1:e-1];if(s&&\"ContentStatement\"===s.type&&(r||!s.leftStripped)){var i=s.value;return s.value=s.value.replace(r?/\\s+$/:/[ \\t]+$/,\"\"),s.leftStripped=s.value!==i,s.leftStripped}}var c=r(1)[\"default\"];e.__esModule=!0;var h=r(25),l=c(h);s.prototype=new l[\"default\"],s.prototype.Program=function(t){var e=!this.options.ignoreStandalone,r=!this.isRootSeen;this.isRootSeen=!0;for(var s=t.body,c=0,h=s.length;c<h;c++){var l=s[c],p=this.accept(l);if(p){var u=i(s,c,r),f=a(s,c,r),d=p.openStandalone&&u,m=p.closeStandalone&&f,g=p.inlineStandalone&&u&&f;p.close&&n(s,c,!0),p.open&&o(s,c,!0),e&&g&&(n(s,c),o(s,c)&&\"PartialStatement\"===l.type&&(l.indent=/([ \\t]+$)/.exec(s[c-1].original)[1])),e&&d&&(n((l.program||l.inverse).body),o(s,c)),e&&m&&(n(s,c),o((l.inverse||l.program).body))}}return t},s.prototype.BlockStatement=s.prototype.DecoratorBlock=s.prototype.PartialBlockStatement=function(t){this.accept(t.program),this.accept(t.inverse);var e=t.program||t.inverse,r=t.program&&t.inverse,s=r,c=r;if(r&&r.chained)for(s=r.body[0].program;c.chained;)c=c.body[c.body.length-1].program;var h={open:t.openStrip.open,close:t.closeStrip.close,openStandalone:a(e.body),closeStandalone:i((s||e).body)};if(t.openStrip.close&&n(e.body,null,!0),r){var l=t.inverseStrip;l.open&&o(e.body,null,!0),l.close&&n(s.body,null,!0),t.closeStrip.open&&o(c.body,null,!0),!this.options.ignoreStandalone&&i(e.body)&&a(s.body)&&(o(e.body),n(s.body))}else t.closeStrip.open&&o(e.body,null,!0);return h},s.prototype.Decorator=s.prototype.MustacheStatement=function(t){return t.strip},s.prototype.PartialStatement=s.prototype.CommentStatement=function(t){var e=t.strip||{};return{inlineStandalone:!0,open:e.open,close:e.close}},e[\"default\"]=s,t.exports=e[\"default\"]},function(t,e,r){\"use strict\";function s(){this.parents=[]}function i(t){this.acceptRequired(t,\"path\"),this.acceptArray(t.params),this.acceptKey(t,\"hash\")}function a(t){i.call(this,t),this.acceptKey(t,\"program\"),this.acceptKey(t,\"inverse\")}function n(t){this.acceptRequired(t,\"name\"),this.acceptArray(t.params),this.acceptKey(t,\"hash\")}var o=r(1)[\"default\"];e.__esModule=!0;var c=r(6),h=o(c);s.prototype={constructor:s,mutating:!1,acceptKey:function(t,e){var r=this.accept(t[e]);if(this.mutating){if(r&&!s.prototype[r.type])throw new h[\"default\"]('Unexpected node type \"'+r.type+'\" found when accepting '+e+\" on \"+t.type);t[e]=r}},acceptRequired:function(t,e){if(this.acceptKey(t,e),!t[e])throw new h[\"default\"](t.type+\" requires \"+e)},acceptArray:function(t){for(var e=0,r=t.length;e<r;e++)this.acceptKey(t,e),t[e]||(t.splice(e,1),e--,r--)},accept:function(t){if(t){if(!this[t.type])throw new h[\"default\"](\"Unknown type: \"+t.type,t);this.current&&this.parents.unshift(this.current),this.current=t;var e=this[t.type](t);return this.current=this.parents.shift(),!this.mutating||e?e:e!==!1?t:void 0}},Program:function(t){this.acceptArray(t.body)},MustacheStatement:i,Decorator:i,BlockStatement:a,DecoratorBlock:a,PartialStatement:n,PartialBlockStatement:function(t){n.call(this,t),this.acceptKey(t,\"program\")},ContentStatement:function(){},CommentStatement:function(){},SubExpression:i,PathExpression:function(){},StringLiteral:function(){},NumberLiteral:function(){},BooleanLiteral:function(){},UndefinedLiteral:function(){},NullLiteral:function(){},Hash:function(t){this.acceptArray(t.pairs)},HashPair:function(t){this.acceptRequired(t,\"value\")}},e[\"default\"]=s,t.exports=e[\"default\"]},function(t,e,r){\"use strict\";function s(t,e){if(e=e.path?e.path.original:e,t.path.original!==e){var r={loc:t.path.loc};throw new g[\"default\"](t.path.original+\" doesn't match \"+e,r)}}function i(t,e){this.source=t,this.start={line:e.first_line,column:e.first_column},this.end={line:e.last_line,column:e.last_column}}function a(t){return/^\\[.*\\]$/.test(t)?t.substr(1,t.length-2):t}function n(t,e){return{open:\"~\"===t.charAt(2),close:\"~\"===e.charAt(e.length-3)}}function o(t){return t.replace(/^\\{\\{~?\\!-?-?/,\"\").replace(/-?-?~?\\}\\}$/,\"\")}function c(t,e,r){r=this.locInfo(r);for(var s=t?\"@\":\"\",i=[],a=0,n=\"\",o=0,c=e.length;o<c;o++){var h=e[o].part,l=e[o].original!==h;if(s+=(e[o].separator||\"\")+h,l||\"..\"!==h&&\".\"!==h&&\"this\"!==h)i.push(h);else{if(i.length>0)throw new g[\"default\"](\"Invalid path: \"+s,{loc:r});\"..\"===h&&(a++,n+=\"../\")}}return{type:\"PathExpression\",data:t,depth:a,parts:i,original:s,loc:r}}function h(t,e,r,s,i,a){var n=s.charAt(3)||s.charAt(2),o=\"{\"!==n&&\"&\"!==n,c=/\\*/.test(s);return{type:c?\"Decorator\":\"MustacheStatement\",path:t,params:e,hash:r,escaped:o,strip:i,loc:this.locInfo(a)}}function l(t,e,r,i){s(t,r),i=this.locInfo(i);var a={type:\"Program\",body:e,strip:{},loc:i};return{type:\"BlockStatement\",path:t.path,params:t.params,hash:t.hash,program:a,openStrip:{},inverseStrip:{},closeStrip:{},loc:i}}function p(t,e,r,i,a,n){i&&i.path&&s(t,i);var o=/\\*/.test(t.open);e.blockParams=t.blockParams;var c=void 0,h=void 0;if(r){if(o)throw new g[\"default\"](\"Unexpected inverse block on decorator\",r);r.chain&&(r.program.body[0].closeStrip=i.strip),h=r.strip,c=r.program}return a&&(a=c,c=e,e=a),{type:o?\"DecoratorBlock\":\"BlockStatement\",path:t.path,params:t.params,hash:t.hash,program:e,inverse:c,openStrip:t.strip,inverseStrip:h,closeStrip:i&&i.strip,loc:this.locInfo(n)}}function u(t,e){if(!e&&t.length){var r=t[0].loc,s=t[t.length-1].loc;r&&s&&(e={source:r.source,start:{line:r.start.line,column:r.start.column},end:{line:s.end.line,column:s.end.column}})}return{type:\"Program\",body:t,strip:{},loc:e}}function f(t,e,r,i){return s(t,r),{type:\"PartialBlockStatement\",name:t.path,params:t.params,hash:t.hash,program:e,openStrip:t.strip,closeStrip:r&&r.strip,loc:this.locInfo(i)}}var d=r(1)[\"default\"];e.__esModule=!0,e.SourceLocation=i,e.id=a,e.stripFlags=n,e.stripComment=o,e.preparePath=c,e.prepareMustache=h,e.prepareRawBlock=l,e.prepareBlock=p,e.prepareProgram=u,e.preparePartialBlock=f;var m=r(6),g=d(m)},function(t,e,r){\"use strict\";function s(){}function i(t,e,r){if(null==t||\"string\"!=typeof t&&\"Program\"!==t.type)throw new l[\"default\"](\"You must pass a string or Handlebars AST to Handlebars.precompile. You passed \"+t);e=e||{},\"data\"in e||(e.data=!0),e.compat&&(e.useDepths=!0);var s=r.parse(t,e),i=(new r.Compiler).compile(s,e);return(new r.JavaScriptCompiler).compile(i,e)}function a(t,e,r){function s(){var s=r.parse(t,e),i=(new r.Compiler).compile(s,e),a=(new r.JavaScriptCompiler).compile(i,e,void 0,!0);return r.template(a)}function i(t,e){return a||(a=s()),a.call(this,t,e)}if(void 0===e&&(e={}),null==t||\"string\"!=typeof t&&\"Program\"!==t.type)throw new l[\"default\"](\"You must pass a string or Handlebars AST to Handlebars.compile. You passed \"+t);\"data\"in e||(e.data=!0),e.compat&&(e.useDepths=!0);var a=void 0;return i._setup=function(t){return a||(a=s()),a._setup(t)},i._child=function(t,e,r,i){return a||(a=s()),a._child(t,e,r,i)},i}function n(t,e){if(t===e)return!0;if(p.isArray(t)&&p.isArray(e)&&t.length===e.length){for(var r=0;r<t.length;r++)if(!n(t[r],e[r]))return!1;return!0}}function o(t){if(!t.path.parts){var e=t.path;t.path={type:\"PathExpression\",data:!1,depth:0,parts:[e.original+\"\"],original:e.original+\"\",loc:e.loc}}}var c=r(1)[\"default\"];e.__esModule=!0,e.Compiler=s,e.precompile=i,e.compile=a;var h=r(6),l=c(h),p=r(5),u=r(21),f=c(u),d=[].slice;s.prototype={compiler:s,equals:function(t){var e=this.opcodes.length;if(t.opcodes.length!==e)return!1;for(var r=0;r<e;r++){var s=this.opcodes[r],i=t.opcodes[r];if(s.opcode!==i.opcode||!n(s.args,i.args))return!1}e=this.children.length;for(var r=0;r<e;r++)if(!this.children[r].equals(t.children[r]))return!1;return!0},guid:0,compile:function(t,e){this.sourceNode=[],this.opcodes=[],this.children=[],this.options=e,this.stringParams=e.stringParams,this.trackIds=e.trackIds,e.blockParams=e.blockParams||[];var r=e.knownHelpers;if(e.knownHelpers={helperMissing:!0,blockHelperMissing:!0,each:!0,\"if\":!0,unless:!0,\"with\":!0,log:!0,lookup:!0},r)for(var s in r)s in r&&(e.knownHelpers[s]=r[s]);return this.accept(t)},compileProgram:function(t){var e=new this.compiler,r=e.compile(t,this.options),s=this.guid++;return this.usePartial=this.usePartial||r.usePartial,this.children[s]=r,this.useDepths=this.useDepths||r.useDepths,s},accept:function(t){if(!this[t.type])throw new l[\"default\"](\"Unknown type: \"+t.type,t);this.sourceNode.unshift(t);var e=this[t.type](t);return this.sourceNode.shift(),e},Program:function(t){this.options.blockParams.unshift(t.blockParams);for(var e=t.body,r=e.length,s=0;s<r;s++)this.accept(e[s]);return this.options.blockParams.shift(),this.isSimple=1===r,this.blockParams=t.blockParams?t.blockParams.length:0,this},BlockStatement:function(t){o(t);var e=t.program,r=t.inverse;e=e&&this.compileProgram(e),r=r&&this.compileProgram(r);var s=this.classifySexpr(t);\"helper\"===s?this.helperSexpr(t,e,r):\"simple\"===s?(this.simpleSexpr(t),this.opcode(\"pushProgram\",e),this.opcode(\"pushProgram\",r),this.opcode(\"emptyHash\"),this.opcode(\"blockValue\",t.path.original)):(this.ambiguousSexpr(t,e,r),this.opcode(\"pushProgram\",e),this.opcode(\"pushProgram\",r),this.opcode(\"emptyHash\"),this.opcode(\"ambiguousBlockValue\")),this.opcode(\"append\")},DecoratorBlock:function(t){var e=t.program&&this.compileProgram(t.program),r=this.setupFullMustacheParams(t,e,void 0),s=t.path;this.useDecorators=!0,this.opcode(\"registerDecorator\",r.length,s.original)},PartialStatement:function(t){this.usePartial=!0;var e=t.program;e&&(e=this.compileProgram(t.program));var r=t.params;if(r.length>1)throw new l[\"default\"](\"Unsupported number of partial arguments: \"+r.length,t);r.length||(this.options.explicitPartialContext?this.opcode(\"pushLiteral\",\"undefined\"):r.push({type:\"PathExpression\",parts:[],depth:0}));var s=t.name.original,i=\"SubExpression\"===t.name.type;i&&this.accept(t.name),this.setupFullMustacheParams(t,e,void 0,!0);var a=t.indent||\"\";this.options.preventIndent&&a&&(this.opcode(\"appendContent\",a),a=\"\"),this.opcode(\"invokePartial\",i,s,a),this.opcode(\"append\")},PartialBlockStatement:function(t){this.PartialStatement(t)},MustacheStatement:function(t){this.SubExpression(t),t.escaped&&!this.options.noEscape?this.opcode(\"appendEscaped\"):this.opcode(\"append\")},Decorator:function(t){this.DecoratorBlock(t)},ContentStatement:function(t){t.value&&this.opcode(\"appendContent\",t.value)},CommentStatement:function(){},SubExpression:function(t){o(t);var e=this.classifySexpr(t);\"simple\"===e?this.simpleSexpr(t):\"helper\"===e?this.helperSexpr(t):this.ambiguousSexpr(t)},ambiguousSexpr:function(t,e,r){var s=t.path,i=s.parts[0],a=null!=e||null!=r;this.opcode(\"getContext\",s.depth),this.opcode(\"pushProgram\",e),this.opcode(\"pushProgram\",r),s.strict=!0,this.accept(s),this.opcode(\"invokeAmbiguous\",i,a)},simpleSexpr:function(t){var e=t.path;e.strict=!0,this.accept(e),this.opcode(\"resolvePossibleLambda\")},helperSexpr:function(t,e,r){var s=this.setupFullMustacheParams(t,e,r),i=t.path,a=i.parts[0];if(this.options.knownHelpers[a])this.opcode(\"invokeKnownHelper\",s.length,a);else{if(this.options.knownHelpersOnly)throw new l[\"default\"](\"You specified knownHelpersOnly, but used the unknown helper \"+a,t);i.strict=!0,i.falsy=!0,this.accept(i),this.opcode(\"invokeHelper\",s.length,i.original,f[\"default\"].helpers.simpleId(i))}},PathExpression:function(t){this.addDepth(t.depth),this.opcode(\"getContext\",t.depth);var e=t.parts[0],r=f[\"default\"].helpers.scopedId(t),s=!t.depth&&!r&&this.blockParamIndex(e);s?this.opcode(\"lookupBlockParam\",s,t.parts):e?t.data?(this.options.data=!0,this.opcode(\"lookupData\",t.depth,t.parts,t.strict)):this.opcode(\"lookupOnContext\",t.parts,t.falsy,t.strict,r):this.opcode(\"pushContext\")},StringLiteral:function(t){this.opcode(\"pushString\",t.value)},NumberLiteral:function(t){this.opcode(\"pushLiteral\",t.value)},BooleanLiteral:function(t){this.opcode(\"pushLiteral\",t.value)},UndefinedLiteral:function(){this.opcode(\"pushLiteral\",\"undefined\")},NullLiteral:function(){this.opcode(\"pushLiteral\",\"null\")},Hash:function(t){var e=t.pairs,r=0,s=e.length;for(this.opcode(\"pushHash\");r<s;r++)this.pushParam(e[r].value);for(;r--;)this.opcode(\"assignToHash\",e[r].key);this.opcode(\"popHash\")},opcode:function(t){this.opcodes.push({opcode:t,args:d.call(arguments,1),loc:this.sourceNode[0].loc})},addDepth:function(t){t&&(this.useDepths=!0)},classifySexpr:function(t){var e=f[\"default\"].helpers.simpleId(t.path),r=e&&!!this.blockParamIndex(t.path.parts[0]),s=!r&&f[\"default\"].helpers.helperExpression(t),i=!r&&(s||e);if(i&&!s){var a=t.path.parts[0],n=this.options;n.knownHelpers[a]?s=!0:n.knownHelpersOnly&&(i=!1)}return s?\"helper\":i?\"ambiguous\":\"simple\"},pushParams:function(t){for(var e=0,r=t.length;e<r;e++)this.pushParam(t[e])},pushParam:function(t){var e=null!=t.value?t.value:t.original||\"\";if(this.stringParams)e.replace&&(e=e.replace(/^(\\.?\\.\\/)*/g,\"\").replace(/\\//g,\".\")),t.depth&&this.addDepth(t.depth),this.opcode(\"getContext\",t.depth||0),this.opcode(\"pushStringParam\",e,t.type),\"SubExpression\"===t.type&&this.accept(t);else{if(this.trackIds){var r=void 0;if(!t.parts||f[\"default\"].helpers.scopedId(t)||t.depth||(r=this.blockParamIndex(t.parts[0])),r){var s=t.parts.slice(1).join(\".\");this.opcode(\"pushId\",\"BlockParam\",r,s)}else e=t.original||e,e.replace&&(e=e.replace(/^this(?:\\.|$)/,\"\").replace(/^\\.\\//,\"\").replace(/^\\.$/,\"\")),this.opcode(\"pushId\",t.type,e)}this.accept(t)}},setupFullMustacheParams:function(t,e,r,s){var i=t.params;return this.pushParams(i),this.opcode(\"pushProgram\",e),this.opcode(\"pushProgram\",r),t.hash?this.accept(t.hash):this.opcode(\"emptyHash\",s),i},blockParamIndex:function(t){for(var e=0,r=this.options.blockParams.length;e<r;e++){var s=this.options.blockParams[e],i=s&&p.indexOf(s,t);if(s&&i>=0)return[e,i]}}}},function(t,e,r){\"use strict\";function s(t){this.value=t}function i(){}function a(t,e,r,s){var i=e.popStack(),a=0,n=r.length;for(t&&n--;a<n;a++)i=e.nameLookup(i,r[a],s);return t?[e.aliasable(\"container.strict\"),\"(\",i,\", \",e.quotedString(r[a]),\")\"]:i}var n=r(1)[\"default\"];e.__esModule=!0;var o=r(4),c=r(6),h=n(c),l=r(5),p=r(29),u=n(p);i.prototype={nameLookup:function(t,e){return i.isValidJavaScriptVariableName(e)?[t,\".\",e]:[t,\"[\",JSON.stringify(e),\"]\"]},depthedLookup:function(t){return[this.aliasable(\"container.lookup\"),'(depths, \"',t,'\")']},compilerInfo:function(){var t=o.COMPILER_REVISION,e=o.REVISION_CHANGES[t];return[t,e]},appendToBuffer:function(t,e,r){return l.isArray(t)||(t=[t]),t=this.source.wrap(t,e),this.environment.isSimple?[\"return \",t,\";\"]:r?[\"buffer += \",t,\";\"]:(t.appendToBuffer=!0,t)},initializeBuffer:function(){return this.quotedString(\"\")},compile:function(t,e,r,s){this.environment=t,this.options=e,this.stringParams=this.options.stringParams,this.trackIds=this.options.trackIds,this.precompile=!s,this.name=this.environment.name,this.isChild=!!r,this.context=r||{decorators:[],programs:[],environments:[]},this.preamble(),this.stackSlot=0,this.stackVars=[],this.aliases={},this.registers={list:[]},this.hashes=[],this.compileStack=[],this.inlineStack=[],this.blockParams=[],this.compileChildren(t,e),this.useDepths=this.useDepths||t.useDepths||t.useDecorators||this.options.compat,this.useBlockParams=this.useBlockParams||t.useBlockParams;var i=t.opcodes,a=void 0,n=void 0,o=void 0,c=void 0;for(o=0,c=i.length;o<c;o++)a=i[o],this.source.currentLocation=a.loc,n=n||a.loc,this[a.opcode].apply(this,a.args);if(this.source.currentLocation=n,this.pushSource(\"\"),this.stackSlot||this.inlineStack.length||this.compileStack.length)throw new h[\"default\"](\"Compile completed with content left on stack\");this.decorators.isEmpty()?this.decorators=void 0:(this.useDecorators=!0,this.decorators.prepend(\"var decorators = container.decorators;\\n\"),this.decorators.push(\"return fn;\"),s?this.decorators=Function.apply(this,[\"fn\",\"props\",\"container\",\"depth0\",\"data\",\"blockParams\",\"depths\",this.decorators.merge()]):(this.decorators.prepend(\"function(fn, props, container, depth0, data, blockParams, depths) {\\n\"),this.decorators.push(\"}\\n\"),this.decorators=this.decorators.merge()));var l=this.createFunctionContext(s);if(this.isChild)return l;var p={compiler:this.compilerInfo(),main:l};this.decorators&&(p.main_d=this.decorators,p.useDecorators=!0);var u=this.context,f=u.programs,d=u.decorators;for(o=0,c=f.length;o<c;o++)f[o]&&(p[o]=f[o],d[o]&&(p[o+\"_d\"]=d[o],p.useDecorators=!0));return this.environment.usePartial&&(p.usePartial=!0),this.options.data&&(p.useData=!0),this.useDepths&&(p.useDepths=!0),this.useBlockParams&&(p.useBlockParams=!0),this.options.compat&&(p.compat=!0),s?p.compilerOptions=this.options:(p.compiler=JSON.stringify(p.compiler),this.source.currentLocation={start:{line:1,column:0}},p=this.objectLiteral(p),e.srcName?(p=p.toStringWithSourceMap({file:e.destName}),p.map=p.map&&p.map.toString()):p=p.toString()),p},preamble:function(){this.lastContext=0,this.source=new u[\"default\"](this.options.srcName),this.decorators=new u[\"default\"](this.options.srcName)},createFunctionContext:function(t){var e=\"\",r=this.stackVars.concat(this.registers.list);r.length>0&&(e+=\", \"+r.join(\", \"));var s=0;for(var i in this.aliases){var a=this.aliases[i];this.aliases.hasOwnProperty(i)&&a.children&&a.referenceCount>1&&(e+=\", alias\"+ ++s+\"=\"+i,a.children[0]=\"alias\"+s)}var n=[\"container\",\"depth0\",\"helpers\",\"partials\",\"data\"];(this.useBlockParams||this.useDepths)&&n.push(\"blockParams\"),this.useDepths&&n.push(\"depths\");var o=this.mergeSource(e);return t?(n.push(o),Function.apply(this,n)):this.source.wrap([\"function(\",n.join(\",\"),\") {\\n  \",o,\"}\"])},mergeSource:function(t){var e=this.environment.isSimple,r=!this.forceBuffer,s=void 0,i=void 0,a=void 0,n=void 0;return this.source.each(function(t){t.appendToBuffer?(a?t.prepend(\"  + \"):a=t,n=t):(a&&(i?a.prepend(\"buffer += \"):s=!0,n.add(\";\"),a=n=void 0),i=!0,e||(r=!1))}),r?a?(a.prepend(\"return \"),n.add(\";\")):i||this.source.push('return \"\";'):(t+=\", buffer = \"+(s?\"\":this.initializeBuffer()),a?(a.prepend(\"return buffer + \"),n.add(\";\")):this.source.push(\"return buffer;\")),t&&this.source.prepend(\"var \"+t.substring(2)+(s?\"\":\";\\n\")),this.source.merge()},blockValue:function(t){var e=this.aliasable(\"helpers.blockHelperMissing\"),r=[this.contextName(0)];this.setupHelperArgs(t,0,r);var s=this.popStack();r.splice(1,0,s),this.push(this.source.functionCall(e,\"call\",r))},ambiguousBlockValue:function(){var t=this.aliasable(\"helpers.blockHelperMissing\"),e=[this.contextName(0)];this.setupHelperArgs(\"\",0,e,!0),this.flushInline();var r=this.topStack();e.splice(1,0,r),this.pushSource([\"if (!\",this.lastHelper,\") { \",r,\" = \",this.source.functionCall(t,\"call\",e),\"}\"])},appendContent:function(t){this.pendingContent?t=this.pendingContent+t:this.pendingLocation=this.source.currentLocation,this.pendingContent=t},append:function(){if(this.isInline())this.replaceStack(function(t){return[\" != null ? \",t,' : \"\"']}),this.pushSource(this.appendToBuffer(this.popStack()));else{var t=this.popStack();this.pushSource([\"if (\",t,\" != null) { \",this.appendToBuffer(t,void 0,!0),\" }\"]),this.environment.isSimple&&this.pushSource([\"else { \",this.appendToBuffer(\"''\",void 0,!0),\" }\"])}},appendEscaped:function(){this.pushSource(this.appendToBuffer([this.aliasable(\"container.escapeExpression\"),\"(\",this.popStack(),\")\"]))},getContext:function(t){this.lastContext=t},pushContext:function(){this.pushStackLiteral(this.contextName(this.lastContext))},lookupOnContext:function(t,e,r,s){var i=0;s||!this.options.compat||this.lastContext?this.pushContext():this.push(this.depthedLookup(t[i++])),this.resolvePath(\"context\",t,i,e,r)},lookupBlockParam:function(t,e){this.useBlockParams=!0,this.push([\"blockParams[\",t[0],\"][\",t[1],\"]\"]),this.resolvePath(\"context\",e,1)},lookupData:function(t,e,r){t?this.pushStackLiteral(\"container.data(data, \"+t+\")\"):this.pushStackLiteral(\"data\"),this.resolvePath(\"data\",e,0,!0,r)},resolvePath:function(t,e,r,s,i){var n=this;if(this.options.strict||this.options.assumeObjects)return void this.push(a(this.options.strict&&i,this,e,t));for(var o=e.length;r<o;r++)this.replaceStack(function(i){var a=n.nameLookup(i,e[r],t);return s?[\" && \",a]:[\" != null ? \",a,\" : \",i]})},resolvePossibleLambda:function(){this.push([this.aliasable(\"container.lambda\"),\"(\",this.popStack(),\", \",this.contextName(0),\")\"])},pushStringParam:function(t,e){this.pushContext(),this.pushString(e),\"SubExpression\"!==e&&(\"string\"==typeof t?this.pushString(t):this.pushStackLiteral(t))},emptyHash:function(t){this.trackIds&&this.push(\"{}\"),this.stringParams&&(this.push(\"{}\"),this.push(\"{}\")),this.pushStackLiteral(t?\"undefined\":\"{}\")},pushHash:function(){this.hash&&this.hashes.push(this.hash),this.hash={values:[],types:[],contexts:[],ids:[]}},popHash:function(){var t=this.hash;this.hash=this.hashes.pop(),this.trackIds&&this.push(this.objectLiteral(t.ids)),this.stringParams&&(this.push(this.objectLiteral(t.contexts)),this.push(this.objectLiteral(t.types))),this.push(this.objectLiteral(t.values))},pushString:function(t){this.pushStackLiteral(this.quotedString(t))},pushLiteral:function(t){this.pushStackLiteral(t)},pushProgram:function(t){null!=t?this.pushStackLiteral(this.programExpression(t)):this.pushStackLiteral(null)},registerDecorator:function(t,e){var r=this.nameLookup(\"decorators\",e,\"decorator\"),s=this.setupHelperArgs(e,t);this.decorators.push([\"fn = \",this.decorators.functionCall(r,\"\",[\"fn\",\"props\",\"container\",s]),\" || fn;\"])},invokeHelper:function(t,e,r){var s=this.popStack(),i=this.setupHelper(t,e),a=r?[i.name,\" || \"]:\"\",n=[\"(\"].concat(a,s);this.options.strict||n.push(\" || \",this.aliasable(\"helpers.helperMissing\")),n.push(\")\"),this.push(this.source.functionCall(n,\"call\",i.callParams))},invokeKnownHelper:function(t,e){var r=this.setupHelper(t,e);this.push(this.source.functionCall(r.name,\"call\",r.callParams))},invokeAmbiguous:function(t,e){this.useRegister(\"helper\");var r=this.popStack();this.emptyHash();var s=this.setupHelper(0,t,e),i=this.lastHelper=this.nameLookup(\"helpers\",t,\"helper\"),a=[\"(\",\"(helper = \",i,\" || \",r,\")\"];this.options.strict||(a[0]=\"(helper = \",a.push(\" != null ? helper : \",this.aliasable(\"helpers.helperMissing\"))),this.push([\"(\",a,s.paramsInit?[\"),(\",s.paramsInit]:[],\"),\",\"(typeof helper === \",this.aliasable('\"function\"'),\" ? \",this.source.functionCall(\"helper\",\"call\",s.callParams),\" : helper))\"])},invokePartial:function(t,e,r){var s=[],i=this.setupParams(e,1,s);t&&(e=this.popStack(),delete i.name),r&&(i.indent=JSON.stringify(r)),i.helpers=\"helpers\",i.partials=\"partials\",i.decorators=\"container.decorators\",t?s.unshift(e):s.unshift(this.nameLookup(\"partials\",e,\"partial\")),this.options.compat&&(i.depths=\"depths\"),i=this.objectLiteral(i),\ns.push(i),this.push(this.source.functionCall(\"container.invokePartial\",\"\",s))},assignToHash:function(t){var e=this.popStack(),r=void 0,s=void 0,i=void 0;this.trackIds&&(i=this.popStack()),this.stringParams&&(s=this.popStack(),r=this.popStack());var a=this.hash;r&&(a.contexts[t]=r),s&&(a.types[t]=s),i&&(a.ids[t]=i),a.values[t]=e},pushId:function(t,e,r){\"BlockParam\"===t?this.pushStackLiteral(\"blockParams[\"+e[0]+\"].path[\"+e[1]+\"]\"+(r?\" + \"+JSON.stringify(\".\"+r):\"\")):\"PathExpression\"===t?this.pushString(e):\"SubExpression\"===t?this.pushStackLiteral(\"true\"):this.pushStackLiteral(\"null\")},compiler:i,compileChildren:function(t,e){for(var r=t.children,s=void 0,i=void 0,a=0,n=r.length;a<n;a++){s=r[a],i=new this.compiler;var o=this.matchExistingProgram(s);null==o?(this.context.programs.push(\"\"),o=this.context.programs.length,s.index=o,s.name=\"program\"+o,this.context.programs[o]=i.compile(s,e,this.context,!this.precompile),this.context.decorators[o]=i.decorators,this.context.environments[o]=s,this.useDepths=this.useDepths||i.useDepths,this.useBlockParams=this.useBlockParams||i.useBlockParams):(s.index=o,s.name=\"program\"+o,this.useDepths=this.useDepths||s.useDepths,this.useBlockParams=this.useBlockParams||s.useBlockParams)}},matchExistingProgram:function(t){for(var e=0,r=this.context.environments.length;e<r;e++){var s=this.context.environments[e];if(s&&s.equals(t))return e}},programExpression:function(t){var e=this.environment.children[t],r=[e.index,\"data\",e.blockParams];return(this.useBlockParams||this.useDepths)&&r.push(\"blockParams\"),this.useDepths&&r.push(\"depths\"),\"container.program(\"+r.join(\", \")+\")\"},useRegister:function(t){this.registers[t]||(this.registers[t]=!0,this.registers.list.push(t))},push:function(t){return t instanceof s||(t=this.source.wrap(t)),this.inlineStack.push(t),t},pushStackLiteral:function(t){this.push(new s(t))},pushSource:function(t){this.pendingContent&&(this.source.push(this.appendToBuffer(this.source.quotedString(this.pendingContent),this.pendingLocation)),this.pendingContent=void 0),t&&this.source.push(t)},replaceStack:function(t){var e=[\"(\"],r=void 0,i=void 0,a=void 0;if(!this.isInline())throw new h[\"default\"](\"replaceStack on non-inline\");var n=this.popStack(!0);if(n instanceof s)r=[n.value],e=[\"(\",r],a=!0;else{i=!0;var o=this.incrStack();e=[\"((\",this.push(o),\" = \",n,\")\"],r=this.topStack()}var c=t.call(this,r);a||this.popStack(),i&&this.stackSlot--,this.push(e.concat(c,\")\"))},incrStack:function(){return this.stackSlot++,this.stackSlot>this.stackVars.length&&this.stackVars.push(\"stack\"+this.stackSlot),this.topStackName()},topStackName:function(){return\"stack\"+this.stackSlot},flushInline:function(){var t=this.inlineStack;this.inlineStack=[];for(var e=0,r=t.length;e<r;e++){var i=t[e];if(i instanceof s)this.compileStack.push(i);else{var a=this.incrStack();this.pushSource([a,\" = \",i,\";\"]),this.compileStack.push(a)}}},isInline:function(){return this.inlineStack.length},popStack:function(t){var e=this.isInline(),r=(e?this.inlineStack:this.compileStack).pop();if(!t&&r instanceof s)return r.value;if(!e){if(!this.stackSlot)throw new h[\"default\"](\"Invalid stack pop\");this.stackSlot--}return r},topStack:function(){var t=this.isInline()?this.inlineStack:this.compileStack,e=t[t.length-1];return e instanceof s?e.value:e},contextName:function(t){return this.useDepths&&t?\"depths[\"+t+\"]\":\"depth\"+t},quotedString:function(t){return this.source.quotedString(t)},objectLiteral:function(t){return this.source.objectLiteral(t)},aliasable:function(t){var e=this.aliases[t];return e?(e.referenceCount++,e):(e=this.aliases[t]=this.source.wrap(t),e.aliasable=!0,e.referenceCount=1,e)},setupHelper:function(t,e,r){var s=[],i=this.setupHelperArgs(e,t,s,r),a=this.nameLookup(\"helpers\",e,\"helper\"),n=this.aliasable(this.contextName(0)+\" != null ? \"+this.contextName(0)+\" : {}\");return{params:s,paramsInit:i,name:a,callParams:[n].concat(s)}},setupParams:function(t,e,r){var s={},i=[],a=[],n=[],o=!r,c=void 0;o&&(r=[]),s.name=this.quotedString(t),s.hash=this.popStack(),this.trackIds&&(s.hashIds=this.popStack()),this.stringParams&&(s.hashTypes=this.popStack(),s.hashContexts=this.popStack());var h=this.popStack(),l=this.popStack();(l||h)&&(s.fn=l||\"container.noop\",s.inverse=h||\"container.noop\");for(var p=e;p--;)c=this.popStack(),r[p]=c,this.trackIds&&(n[p]=this.popStack()),this.stringParams&&(a[p]=this.popStack(),i[p]=this.popStack());return o&&(s.args=this.source.generateArray(r)),this.trackIds&&(s.ids=this.source.generateArray(n)),this.stringParams&&(s.types=this.source.generateArray(a),s.contexts=this.source.generateArray(i)),this.options.data&&(s.data=\"data\"),this.useBlockParams&&(s.blockParams=\"blockParams\"),s},setupHelperArgs:function(t,e,r,s){var i=this.setupParams(t,e,r);return i=this.objectLiteral(i),s?(this.useRegister(\"options\"),r.push(\"options\"),[\"options=\",i]):r?(r.push(i),\"\"):i}},function(){for(var t=\"break else new var case finally return void catch for switch while continue function this with default if throw delete in try do instanceof typeof abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws consts goto private transient debugger implements protected volatile double import public let yield await null true false\".split(\" \"),e=i.RESERVED_WORDS={},r=0,s=t.length;r<s;r++)e[t[r]]=!0}(),i.isValidJavaScriptVariableName=function(t){return!i.RESERVED_WORDS[t]&&/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(t)},e[\"default\"]=i,t.exports=e[\"default\"]},function(t,e,r){\"use strict\";function s(t,e,r){if(a.isArray(t)){for(var s=[],i=0,n=t.length;i<n;i++)s.push(e.wrap(t[i],r));return s}return\"boolean\"==typeof t||\"number\"==typeof t?t+\"\":t}function i(t){this.srcFile=t,this.source=[]}e.__esModule=!0;var a=r(5),n=void 0;try{}catch(o){}n||(n=function(t,e,r,s){this.src=\"\",s&&this.add(s)},n.prototype={add:function(t){a.isArray(t)&&(t=t.join(\"\")),this.src+=t},prepend:function(t){a.isArray(t)&&(t=t.join(\"\")),this.src=t+this.src},toStringWithSourceMap:function(){return{code:this.toString()}},toString:function(){return this.src}}),i.prototype={isEmpty:function(){return!this.source.length},prepend:function(t,e){this.source.unshift(this.wrap(t,e))},push:function(t,e){this.source.push(this.wrap(t,e))},merge:function(){var t=this.empty();return this.each(function(e){t.add([\"  \",e,\"\\n\"])}),t},each:function(t){for(var e=0,r=this.source.length;e<r;e++)t(this.source[e])},empty:function(){var t=this.currentLocation||{start:{}};return new n(t.start.line,t.start.column,this.srcFile)},wrap:function(t){var e=arguments.length<=1||void 0===arguments[1]?this.currentLocation||{start:{}}:arguments[1];return t instanceof n?t:(t=s(t,this,e),new n(e.start.line,e.start.column,this.srcFile,t))},functionCall:function(t,e,r){return r=this.generateList(r),this.wrap([t,e?\".\"+e+\"(\":\"(\",r,\")\"])},quotedString:function(t){return'\"'+(t+\"\").replace(/\\\\/g,\"\\\\\\\\\").replace(/\"/g,'\\\\\"').replace(/\\n/g,\"\\\\n\").replace(/\\r/g,\"\\\\r\").replace(/\\u2028/g,\"\\\\u2028\").replace(/\\u2029/g,\"\\\\u2029\")+'\"'},objectLiteral:function(t){var e=[];for(var r in t)if(t.hasOwnProperty(r)){var i=s(t[r],this);\"undefined\"!==i&&e.push([this.quotedString(r),\":\",i])}var a=this.generateList(e);return a.prepend(\"{\"),a.add(\"}\"),a},generateList:function(t){for(var e=this.empty(),r=0,i=t.length;r<i;r++)r&&e.add(\",\"),e.add(s(t[r],this));return e},generateArray:function(t){var e=this.generateList(t);return e.prepend(\"[\"),e.add(\"]\"),e}},e[\"default\"]=i,t.exports=e[\"default\"]}])});"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lib/highlight.9.1.0.pack.js",
    "content": "!function(e){\"undefined\"!=typeof exports?e(exports):(self.hljs=e({}),\"function\"==typeof define&&define.amd&&define(\"hljs\",[],function(){return self.hljs}))}(function(e){function r(e){return e.replace(/&/gm,\"&amp;\").replace(/</gm,\"&lt;\").replace(/>/gm,\"&gt;\")}function t(e){return e.nodeName.toLowerCase()}function n(e,r){var t=e&&e.exec(r);return t&&0==t.index}function a(e){return/^(no-?highlight|plain|text)$/i.test(e)}function c(e){var r,t,n,c=e.className+\" \";if(c+=e.parentNode?e.parentNode.className:\"\",t=/\\blang(?:uage)?-([\\w-]+)\\b/i.exec(c))return E(t[1])?t[1]:\"no-highlight\";for(c=c.split(/\\s+/),r=0,n=c.length;n>r;r++)if(E(c[r])||a(c[r]))return c[r]}function i(e,r){var t,n={};for(t in e)n[t]=e[t];if(r)for(t in r)n[t]=r[t];return n}function o(e){var r=[];return function n(e,a){for(var c=e.firstChild;c;c=c.nextSibling)3==c.nodeType?a+=c.nodeValue.length:1==c.nodeType&&(r.push({event:\"start\",offset:a,node:c}),a=n(c,a),t(c).match(/br|hr|img|input/)||r.push({event:\"stop\",offset:a,node:c}));return a}(e,0),r}function s(e,n,a){function c(){return e.length&&n.length?e[0].offset!=n[0].offset?e[0].offset<n[0].offset?e:n:\"start\"==n[0].event?e:n:e.length?e:n}function i(e){function n(e){return\" \"+e.nodeName+'=\"'+r(e.value)+'\"'}l+=\"<\"+t(e)+Array.prototype.map.call(e.attributes,n).join(\"\")+\">\"}function o(e){l+=\"</\"+t(e)+\">\"}function s(e){(\"start\"==e.event?i:o)(e.node)}for(var u=0,l=\"\",f=[];e.length||n.length;){var b=c();if(l+=r(a.substr(u,b[0].offset-u)),u=b[0].offset,b==e){f.reverse().forEach(o);do s(b.splice(0,1)[0]),b=c();while(b==e&&b.length&&b[0].offset==u);f.reverse().forEach(i)}else\"start\"==b[0].event?f.push(b[0].node):f.pop(),s(b.splice(0,1)[0])}return l+r(a.substr(u))}function u(e){function r(e){return e&&e.source||e}function t(t,n){return new RegExp(r(t),\"m\"+(e.cI?\"i\":\"\")+(n?\"g\":\"\"))}function n(a,c){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var o={},s=function(r,t){e.cI&&(t=t.toLowerCase()),t.split(\" \").forEach(function(e){var t=e.split(\"|\");o[t[0]]=[r,t[1]?Number(t[1]):1]})};\"string\"==typeof a.k?s(\"keyword\",a.k):Object.keys(a.k).forEach(function(e){s(e,a.k[e])}),a.k=o}a.lR=t(a.l||/\\b\\w+\\b/,!0),c&&(a.bK&&(a.b=\"\\\\b(\"+a.bK.split(\" \").join(\"|\")+\")\\\\b\"),a.b||(a.b=/\\B|\\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\\B|\\b/),a.e&&(a.eR=t(a.e)),a.tE=r(a.e)||\"\",a.eW&&c.tE&&(a.tE+=(a.e?\"|\":\"\")+c.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var u=[];a.c.forEach(function(e){e.v?e.v.forEach(function(r){u.push(i(e,r))}):u.push(\"self\"==e?a:e)}),a.c=u,a.c.forEach(function(e){n(e,a)}),a.starts&&n(a.starts,c);var l=a.c.map(function(e){return e.bK?\"\\\\.?(\"+e.b+\")\\\\.?\":e.b}).concat([a.tE,a.i]).map(r).filter(Boolean);a.t=l.length?t(l.join(\"|\"),!0):{exec:function(){return null}}}}n(e)}function l(e,t,a,c){function i(e,r){for(var t=0;t<r.c.length;t++)if(n(r.c[t].bR,e))return r.c[t]}function o(e,r){if(n(e.eR,r)){for(;e.endsParent&&e.parent;)e=e.parent;return e}return e.eW?o(e.parent,r):void 0}function s(e,r){return!a&&n(r.iR,e)}function b(e,r){var t=N.cI?r[0].toLowerCase():r[0];return e.k.hasOwnProperty(t)&&e.k[t]}function g(e,r,t,n){var a=n?\"\":w.classPrefix,c='<span class=\"'+a,i=t?\"\":\"</span>\";return c+=e+'\">',c+r+i}function p(){if(!M.k)return r(B);var e=\"\",t=0;M.lR.lastIndex=0;for(var n=M.lR.exec(B);n;){e+=r(B.substr(t,n.index-t));var a=b(M,n);a?(L+=a[1],e+=g(a[0],r(n[0]))):e+=r(n[0]),t=M.lR.lastIndex,n=M.lR.exec(B)}return e+r(B.substr(t))}function h(){var e=\"string\"==typeof M.sL;if(e&&!y[M.sL])return r(B);var t=e?l(M.sL,B,!0,R[M.sL]):f(B,M.sL.length?M.sL:void 0);return M.r>0&&(L+=t.r),e&&(R[M.sL]=t.top),g(t.language,t.value,!1,!0)}function d(){return void 0!==M.sL?h():p()}function m(e,t){var n=e.cN?g(e.cN,\"\",!0):\"\";e.rB?(x+=n,B=\"\"):e.eB?(x+=r(t)+n,B=\"\"):(x+=n,B=t),M=Object.create(e,{parent:{value:M}})}function v(e,t){if(B+=e,void 0===t)return x+=d(),0;var n=i(t,M);if(n)return x+=d(),m(n,t),n.rB?0:t.length;var a=o(M,t);if(a){var c=M;c.rE||c.eE||(B+=t),x+=d();do M.cN&&(x+=\"</span>\"),L+=M.r,M=M.parent;while(M!=a.parent);return c.eE&&(x+=r(t)),B=\"\",a.starts&&m(a.starts,\"\"),c.rE?0:t.length}if(s(t,M))throw new Error('Illegal lexeme \"'+t+'\" for mode \"'+(M.cN||\"<unnamed>\")+'\"');return B+=t,t.length||1}var N=E(e);if(!N)throw new Error('Unknown language: \"'+e+'\"');u(N);var C,M=c||N,R={},x=\"\";for(C=M;C!=N;C=C.parent)C.cN&&(x=g(C.cN,\"\",!0)+x);var B=\"\",L=0;try{for(var S,A,k=0;M.t.lastIndex=k,S=M.t.exec(t),S;)A=v(t.substr(k,S.index-k),S[0]),k=S.index+A;for(v(t.substr(k)),C=M;C.parent;C=C.parent)C.cN&&(x+=\"</span>\");return{r:L,value:x,language:e,top:M}}catch(I){if(-1!=I.message.indexOf(\"Illegal\"))return{r:0,value:r(t)};throw I}}function f(e,t){t=t||w.languages||Object.keys(y);var n={r:0,value:r(e)},a=n;return t.forEach(function(r){if(E(r)){var t=l(r,e,!1);t.language=r,t.r>a.r&&(a=t),t.r>n.r&&(a=n,n=t)}}),a.language&&(n.second_best=a),n}function b(e){return w.tabReplace&&(e=e.replace(/^((<[^>]+>|\\t)+)/gm,function(e,r){return r.replace(/\\t/g,w.tabReplace)})),w.useBR&&(e=e.replace(/\\n/g,\"<br>\")),e}function g(e,r,t){var n=r?C[r]:t,a=[e.trim()];return e.match(/\\bhljs\\b/)||a.push(\"hljs\"),-1===e.indexOf(n)&&a.push(n),a.join(\" \").trim()}function p(e){var r=c(e);if(!a(r)){var t;w.useBR?(t=document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"div\"),t.innerHTML=e.innerHTML.replace(/\\n/g,\"\").replace(/<br[ \\/]*>/g,\"\\n\")):t=e;var n=t.textContent,i=r?l(r,n,!0):f(n),u=o(t);if(u.length){var p=document.createElementNS(\"http://www.w3.org/1999/xhtml\",\"div\");p.innerHTML=i.value,i.value=s(u,o(p),n)}i.value=b(i.value),e.innerHTML=i.value,e.className=g(e.className,r,i.language),e.result={language:i.language,re:i.r},i.second_best&&(e.second_best={language:i.second_best.language,re:i.second_best.r})}}function h(e){w=i(w,e)}function d(){if(!d.called){d.called=!0;var e=document.querySelectorAll(\"pre code\");Array.prototype.forEach.call(e,p)}}function m(){addEventListener(\"DOMContentLoaded\",d,!1),addEventListener(\"load\",d,!1)}function v(r,t){var n=y[r]=t(e);n.aliases&&n.aliases.forEach(function(e){C[e]=r})}function N(){return Object.keys(y)}function E(e){return e=(e||\"\").toLowerCase(),y[e]||y[C[e]]}var w={classPrefix:\"hljs-\",tabReplace:null,useBR:!1,languages:void 0},y={},C={};return e.highlight=l,e.highlightAuto=f,e.fixMarkup=b,e.highlightBlock=p,e.configure=h,e.initHighlighting=d,e.initHighlightingOnLoad=m,e.registerLanguage=v,e.listLanguages=N,e.getLanguage=E,e.inherit=i,e.IR=\"[a-zA-Z]\\\\w*\",e.UIR=\"[a-zA-Z_]\\\\w*\",e.NR=\"\\\\b\\\\d+(\\\\.\\\\d+)?\",e.CNR=\"(-?)(\\\\b0[xX][a-fA-F0-9]+|(\\\\b\\\\d+(\\\\.\\\\d*)?|\\\\.\\\\d+)([eE][-+]?\\\\d+)?)\",e.BNR=\"\\\\b(0b[01]+)\",e.RSR=\"!|!=|!==|%|%=|&|&&|&=|\\\\*|\\\\*=|\\\\+|\\\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\\\?|\\\\[|\\\\{|\\\\(|\\\\^|\\\\^=|\\\\||\\\\|=|\\\\|\\\\||~\",e.BE={b:\"\\\\\\\\[\\\\s\\\\S]\",r:0},e.ASM={cN:\"string\",b:\"'\",e:\"'\",i:\"\\\\n\",c:[e.BE]},e.QSM={cN:\"string\",b:'\"',e:'\"',i:\"\\\\n\",c:[e.BE]},e.PWM={b:/\\b(a|an|the|are|I|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|like)\\b/},e.C=function(r,t,n){var a=e.inherit({cN:\"comment\",b:r,e:t,c:[]},n||{});return a.c.push(e.PWM),a.c.push({cN:\"doctag\",b:\"(?:TODO|FIXME|NOTE|BUG|XXX):\",r:0}),a},e.CLCM=e.C(\"//\",\"$\"),e.CBCM=e.C(\"/\\\\*\",\"\\\\*/\"),e.HCM=e.C(\"#\",\"$\"),e.NM={cN:\"number\",b:e.NR,r:0},e.CNM={cN:\"number\",b:e.CNR,r:0},e.BNM={cN:\"number\",b:e.BNR,r:0},e.CSSNM={cN:\"number\",b:e.NR+\"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?\",r:0},e.RM={cN:\"regexp\",b:/\\//,e:/\\/[gimuy]*/,i:/\\n/,c:[e.BE,{b:/\\[/,e:/\\]/,r:0,c:[e.BE]}]},e.TM={cN:\"title\",b:e.IR,r:0},e.UTM={cN:\"title\",b:e.UIR,r:0},e}),hljs.registerLanguage(\"json\",function(e){var r={literal:\"true false null\"},t=[e.QSM,e.CNM],n={e:\",\",eW:!0,eE:!0,c:t,k:r},a={b:\"{\",e:\"}\",c:[{cN:\"attr\",b:'\\\\s*\"',e:'\"\\\\s*:\\\\s*',eB:!0,eE:!0,c:[e.BE],i:\"\\\\n\",starts:n}],i:\"\\\\S\"},c={b:\"\\\\[\",e:\"\\\\]\",c:[e.inherit(n)],i:\"\\\\S\"};return t.splice(t.length,0,a,c),{c:t,k:r,i:\"\\\\S\"}}),hljs.registerLanguage(\"xml\",function(e){var r=\"[A-Za-z0-9\\\\._:-]+\",t={b:/<\\?(php)?(?!\\w)/,e:/\\?>/,sL:\"php\"},n={eW:!0,i:/</,r:0,c:[t,{cN:\"attr\",b:r,r:0},{b:\"=\",r:0,c:[{cN:\"string\",c:[t],v:[{b:/\"/,e:/\"/},{b:/'/,e:/'/},{b:/[^\\s\\/>]+/}]}]}]};return{aliases:[\"html\",\"xhtml\",\"rss\",\"atom\",\"xsl\",\"plist\"],cI:!0,c:[{cN:\"meta\",b:\"<!DOCTYPE\",e:\">\",r:10,c:[{b:\"\\\\[\",e:\"\\\\]\"}]},e.C(\"<!--\",\"-->\",{r:10}),{b:\"<\\\\!\\\\[CDATA\\\\[\",e:\"\\\\]\\\\]>\",r:10},{cN:\"tag\",b:\"<style(?=\\\\s|>|$)\",e:\">\",k:{name:\"style\"},c:[n],starts:{e:\"</style>\",rE:!0,sL:[\"css\",\"xml\"]}},{cN:\"tag\",b:\"<script(?=\\\\s|>|$)\",e:\">\",k:{name:\"script\"},c:[n],starts:{e:\"</script>\",rE:!0,sL:[\"actionscript\",\"javascript\",\"handlebars\",\"xml\"]}},t,{cN:\"meta\",b:/<\\?\\w+/,e:/\\?>/,r:10},{cN:\"tag\",b:\"</?\",e:\"/?>\",c:[{cN:\"name\",b:/[^\\/><\\s]+/,r:0},n]}]}}),hljs.registerLanguage(\"javascript\",function(e){return{aliases:[\"js\"],k:{keyword:\"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield consts export super debugger as async await import from as\",literal:\"true false null undefined NaN Infinity\",built_in:\"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise\"},c:[{cN:\"meta\",r:10,b:/^\\s*['\"]use (strict|asm)['\"]/},{cN:\"meta\",b:/^#!/,e:/$/},e.ASM,e.QSM,{cN:\"string\",b:\"`\",e:\"`\",c:[e.BE,{cN:\"subst\",b:\"\\\\$\\\\{\",e:\"\\\\}\"}]},e.CLCM,e.CBCM,{cN:\"number\",v:[{b:\"\\\\b(0[bB][01]+)\"},{b:\"\\\\b(0[oO][0-7]+)\"},{b:e.CNR}],r:0},{b:\"(\"+e.RSR+\"|\\\\b(case|return|throw)\\\\b)\\\\s*\",k:\"return throw case\",c:[e.CLCM,e.CBCM,e.RM,{b:/</,e:/>\\s*[);\\]]/,r:0,sL:\"xml\"}],r:0},{cN:\"function\",bK:\"function\",e:/\\{/,eE:!0,c:[e.inherit(e.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:\"params\",b:/\\(/,e:/\\)/,eB:!0,eE:!0,c:[e.CLCM,e.CBCM]}],i:/\\[|%/},{b:/\\$[(.]/},{b:\"\\\\.\"+e.IR,r:0},{cN:\"class\",bK:\"class\",e:/[{;=]/,eE:!0,i:/[:\"\\[\\]]/,c:[{bK:\"extends\"},e.UTM]},{bK:\"constructor\",e:/\\{/,eE:!0}],i:/#(?!!)/}}),hljs.registerLanguage(\"css\",function(e){var r=\"[a-zA-Z-][a-zA-Z0-9_-]*\",t={b:/[A-Z\\_\\.\\-]+\\s*:/,rB:!0,e:\";\",eW:!0,c:[{cN:\"attribute\",b:/\\S/,e:\":\",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\\w-]+\\s*\\(/,rB:!0,c:[{cN:\"built_in\",b:/[\\w-]+/}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:\"number\",b:\"#[0-9A-Fa-f]+\"},{cN:\"meta\",b:\"!important\"}]}}]};return{cI:!0,i:/[=\\/|'\\$]/,c:[e.CBCM,{cN:\"selector-id\",b:/#[A-Za-z0-9_-]+/},{cN:\"selector-class\",b:/\\.[A-Za-z0-9_-]+/},{cN:\"selector-attr\",b:/\\[/,e:/\\]/,i:\"$\"},{cN:\"selector-pseudo\",b:/:(:)?[a-zA-Z0-9\\_\\-\\+\\(\\)\"'.]+/},{b:\"@(font-face|page)\",l:\"[a-z-]+\",k:\"font-face page\"},{b:\"@\",e:\"[{;]\",c:[{cN:\"keyword\",b:/\\S+/},{b:/\\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:\"selector-tag\",b:r,r:0},{b:\"{\",e:\"}\",i:/\\S/,c:[e.CBCM,t]}]}});"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lib/highlight.9.1.0.pack_extended.js",
    "content": "\"use strict\";!function(){var h,l;h=hljs.configure,hljs.configure=function(l){var i=l.highlightSizeThreshold;hljs.highlightSizeThreshold=i===+i?i:null,h.call(this,l)},l=hljs.highlightBlock,hljs.highlightBlock=function(h){var i=h.innerHTML,g=hljs.highlightSizeThreshold;(null==g||g>i.length)&&l.call(hljs,h)}}();"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lib/marked.js",
    "content": "(function(){function e(e){this.tokens=[],this.tokens.links={},this.options=e||a.defaults,this.rules=p.normal,this.options.gfm&&(this.options.tables?this.rules=p.tables:this.rules=p.gfm)}function t(e,t){if(this.options=t||a.defaults,this.links=e,this.rules=u.normal,this.renderer=this.options.renderer||new n,this.renderer.options=this.options,!this.links)throw new Error(\"Tokens array requires a `links` property.\");this.options.gfm?this.options.breaks?this.rules=u.breaks:this.rules=u.gfm:this.options.pedantic&&(this.rules=u.pedantic)}function n(e){this.options=e||{}}function r(e){this.tokens=[],this.token=null,this.options=e||a.defaults,this.options.renderer=this.options.renderer||new n,this.renderer=this.options.renderer,this.renderer.options=this.options}function s(e,t){return e.replace(t?/&/g:/&(?!#?\\w+;)/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/>/g,\"&gt;\").replace(/\"/g,\"&quot;\").replace(/'/g,\"&#39;\")}function i(e){return e.replace(/&([#\\w]+);/g,function(e,t){return t=t.toLowerCase(),\"colon\"===t?\":\":\"#\"===t.charAt(0)?\"x\"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):\"\"})}function l(e,t){return e=e.source,t=t||\"\",function n(r,s){return r?(s=s.source||s,s=s.replace(/(^|[^\\[])\\^/g,\"$1\"),e=e.replace(r,s),n):new RegExp(e,t)}}function o(){}function h(e){for(var t,n,r=1;r<arguments.length;r++){t=arguments[r];for(n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])}return e}function a(t,n,i){if(i||\"function\"==typeof n){i||(i=n,n=null),n=h({},a.defaults,n||{});var l,o,p=n.highlight,u=0;try{l=e.lex(t,n)}catch(c){return i(c)}o=l.length;var g=function(e){if(e)return n.highlight=p,i(e);var t;try{t=r.parse(l,n)}catch(s){e=s}return n.highlight=p,e?i(e):i(null,t)};if(!p||p.length<3)return g();if(delete n.highlight,!o)return g();for(;u<l.length;u++)!function(e){return\"code\"!==e.type?--o||g():p(e.text,e.lang,function(t,n){return t?g(t):null==n||n===e.text?--o||g():(e.text=n,e.escaped=!0,void(--o||g()))})}(l[u])}else try{return n&&(n=h({},a.defaults,n)),r.parse(e.lex(t,n),n)}catch(c){if(c.message+=\"\\nPlease report this to https://github.com/chjj/marked.\",(n||a.defaults).silent)return\"<p>An error occured:</p><pre>\"+s(c.message+\"\",!0)+\"</pre>\";throw c}}var p={newline:/^\\n+/,code:/^( {4}[^\\n]+\\n*)+/,fences:o,hr:/^( *[-*_]){3,} *(?:\\n+|$)/,heading:/^ *(#{1,6}) *([^\\n]+?) *#* *(?:\\n+|$)/,nptable:o,lheading:/^([^\\n]+)\\n *(=|-){2,} *(?:\\n+|$)/,blockquote:/^( *>[^\\n]+(\\n(?!def)[^\\n]+)*\\n*)+/,list:/^( *)(bull) [\\s\\S]+?(?:hr|def|\\n{2,}(?! )(?!\\1bull )\\n*|\\s*$)/,html:/^ *(?:comment *(?:\\n|\\s*$)|closed *(?:\\n{2,}|\\s*$)|closing *(?:\\n{2,}|\\s*$))/,def:/^ *\\[([^\\]]+)\\]: *<?([^\\s>]+)>?(?: +[\"(]([^\\n]+)[\")])? *(?:\\n+|$)/,table:o,paragraph:/^((?:[^\\n]+\\n?(?!hr|heading|lheading|blockquote|tag|def))+)\\n*/,text:/^[^\\n]+/};p.bullet=/(?:[*+-]|\\d+\\.)/,p.item=/^( *)(bull) [^\\n]*(?:\\n(?!\\1bull )[^\\n]*)*/,p.item=l(p.item,\"gm\")(/bull/g,p.bullet)(),p.list=l(p.list)(/bull/g,p.bullet)(\"hr\",\"\\\\n+(?=\\\\1?(?:[-*_] *){3,}(?:\\\\n+|$))\")(\"def\",\"\\\\n+(?=\"+p.def.source+\")\")(),p.blockquote=l(p.blockquote)(\"def\",p.def)(),p._tag=\"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\\\b)\\\\w+(?!:/|[^\\\\w\\\\s@]*@)\\\\b\",p.html=l(p.html)(\"comment\",/<!--[\\s\\S]*?-->/)(\"closed\",/<(tag)[\\s\\S]+?<\\/\\1>/)(\"closing\",/<tag(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/)(/tag/g,p._tag)(),p.paragraph=l(p.paragraph)(\"hr\",p.hr)(\"heading\",p.heading)(\"lheading\",p.lheading)(\"blockquote\",p.blockquote)(\"tag\",\"<\"+p._tag)(\"def\",p.def)(),p.normal=h({},p),p.gfm=h({},p.normal,{fences:/^ *(`{3,}|~{3,}) *(\\S+)? *\\n([\\s\\S]+?)\\s*\\1 *(?:\\n+|$)/,paragraph:/^/}),p.gfm.paragraph=l(p.paragraph)(\"(?!\",\"(?!\"+p.gfm.fences.source.replace(\"\\\\1\",\"\\\\2\")+\"|\"+p.list.source.replace(\"\\\\1\",\"\\\\3\")+\"|\")(),p.tables=h({},p.gfm,{nptable:/^ *(\\S.*\\|.*)\\n *([-:]+ *\\|[-| :]*)\\n((?:.*\\|.*(?:\\n|$))*)\\n*/,table:/^ *\\|(.+)\\n *\\|( *[-:]+[-| :]*)\\n((?: *\\|.*(?:\\n|$))*)\\n*/}),e.rules=p,e.lex=function(t,n){var r=new e(n);return r.lex(t)},e.prototype.lex=function(e){return e=e.replace(/\\r\\n|\\r/g,\"\\n\").replace(/\\t/g,\"    \").replace(/\\u00a0/g,\" \").replace(/\\u2424/g,\"\\n\"),this.token(e,!0)},e.prototype.token=function(e,t,n){for(var r,s,i,l,o,h,a,u,c,e=e.replace(/^ +$/gm,\"\");e;)if((i=this.rules.newline.exec(e))&&(e=e.substring(i[0].length),i[0].length>1&&this.tokens.push({type:\"space\"})),i=this.rules.code.exec(e))e=e.substring(i[0].length),i=i[0].replace(/^ {4}/gm,\"\"),this.tokens.push({type:\"code\",text:this.options.pedantic?i:i.replace(/\\n+$/,\"\")});else if(i=this.rules.fences.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"code\",lang:i[2],text:i[3]});else if(i=this.rules.heading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"heading\",depth:i[1].length,text:i[2]});else if(t&&(i=this.rules.nptable.exec(e))){for(e=e.substring(i[0].length),h={type:\"table\",header:i[1].replace(/^ *| *\\| *$/g,\"\").split(/ *\\| */),align:i[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells:i[3].replace(/\\n$/,\"\").split(\"\\n\")},u=0;u<h.align.length;u++)/^ *-+: *$/.test(h.align[u])?h.align[u]=\"right\":/^ *:-+: *$/.test(h.align[u])?h.align[u]=\"center\":/^ *:-+ *$/.test(h.align[u])?h.align[u]=\"left\":h.align[u]=null;for(u=0;u<h.cells.length;u++)h.cells[u]=h.cells[u].split(/ *\\| */);this.tokens.push(h)}else if(i=this.rules.lheading.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"heading\",depth:\"=\"===i[2]?1:2,text:i[1]});else if(i=this.rules.hr.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"hr\"});else if(i=this.rules.blockquote.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"blockquote_start\"}),i=i[0].replace(/^ *> ?/gm,\"\"),this.token(i,t,!0),this.tokens.push({type:\"blockquote_end\"});else if(i=this.rules.list.exec(e)){for(e=e.substring(i[0].length),l=i[2],this.tokens.push({type:\"list_start\",ordered:l.length>1}),i=i[0].match(this.rules.item),r=!1,c=i.length,u=0;u<c;u++)h=i[u],a=h.length,h=h.replace(/^ *([*+-]|\\d+\\.) +/,\"\"),~h.indexOf(\"\\n \")&&(a-=h.length,h=this.options.pedantic?h.replace(/^ {1,4}/gm,\"\"):h.replace(new RegExp(\"^ {1,\"+a+\"}\",\"gm\"),\"\")),this.options.smartLists&&u!==c-1&&(o=p.bullet.exec(i[u+1])[0],l===o||l.length>1&&o.length>1||(e=i.slice(u+1).join(\"\\n\")+e,u=c-1)),s=r||/\\n\\n(?!\\s*$)/.test(h),u!==c-1&&(r=\"\\n\"===h.charAt(h.length-1),s||(s=r)),this.tokens.push({type:s?\"loose_item_start\":\"list_item_start\"}),this.token(h,!1,n),this.tokens.push({type:\"list_item_end\"});this.tokens.push({type:\"list_end\"})}else if(i=this.rules.html.exec(e))e=e.substring(i[0].length),this.tokens.push({type:this.options.sanitize?\"paragraph\":\"html\",pre:\"pre\"===i[1]||\"script\"===i[1]||\"style\"===i[1],text:i[0]});else if(!n&&t&&(i=this.rules.def.exec(e)))e=e.substring(i[0].length),this.tokens.links[i[1].toLowerCase()]={href:i[2],title:i[3]};else if(t&&(i=this.rules.table.exec(e))){for(e=e.substring(i[0].length),h={type:\"table\",header:i[1].replace(/^ *| *\\| *$/g,\"\").split(/ *\\| */),align:i[2].replace(/^ *|\\| *$/g,\"\").split(/ *\\| */),cells:i[3].replace(/(?: *\\| *)?\\n$/,\"\").split(\"\\n\")},u=0;u<h.align.length;u++)/^ *-+: *$/.test(h.align[u])?h.align[u]=\"right\":/^ *:-+: *$/.test(h.align[u])?h.align[u]=\"center\":/^ *:-+ *$/.test(h.align[u])?h.align[u]=\"left\":h.align[u]=null;for(u=0;u<h.cells.length;u++)h.cells[u]=h.cells[u].replace(/^ *\\| *| *\\| *$/g,\"\").split(/ *\\| */);this.tokens.push(h)}else if(t&&(i=this.rules.paragraph.exec(e)))e=e.substring(i[0].length),this.tokens.push({type:\"paragraph\",text:\"\\n\"===i[1].charAt(i[1].length-1)?i[1].slice(0,-1):i[1]});else if(i=this.rules.text.exec(e))e=e.substring(i[0].length),this.tokens.push({type:\"text\",text:i[0]});else if(e)throw new Error(\"Infinite loop on byte: \"+e.charCodeAt(0));return this.tokens};var u={escape:/^\\\\([\\\\`*{}\\[\\]()#+\\-.!_>])/,autolink:/^<([^ >]+(@|:\\/)[^ >]+)>/,url:o,tag:/^<!--[\\s\\S]*?-->|^<\\/?\\w+(?:\"[^\"]*\"|'[^']*'|[^'\">])*?>/,link:/^!?\\[(inside)\\]\\(href\\)/,reflink:/^!?\\[(inside)\\]\\s*\\[([^\\]]*)\\]/,nolink:/^!?\\[((?:\\[[^\\]]*\\]|[^\\[\\]])*)\\]/,strong:/^__([\\s\\S]+?)__(?!_)|^\\*\\*([\\s\\S]+?)\\*\\*(?!\\*)/,em:/^\\b_((?:__|[\\s\\S])+?)_\\b|^\\*((?:\\*\\*|[\\s\\S])+?)\\*(?!\\*)/,code:/^(`+)\\s*([\\s\\S]*?[^`])\\s*\\1(?!`)/,br:/^ {2,}\\n(?!\\s*$)/,del:o,text:/^[\\s\\S]+?(?=[\\\\<!\\[_*`]| {2,}\\n|$)/};u._inside=/(?:\\[[^\\]]*\\]|[^\\[\\]]|\\](?=[^\\[]*\\]))*/,u._href=/\\s*<?([\\s\\S]*?)>?(?:\\s+['\"]([\\s\\S]*?)['\"])?\\s*/,u.link=l(u.link)(\"inside\",u._inside)(\"href\",u._href)(),u.reflink=l(u.reflink)(\"inside\",u._inside)(),u.normal=h({},u),u.pedantic=h({},u.normal,{strong:/^__(?=\\S)([\\s\\S]*?\\S)__(?!_)|^\\*\\*(?=\\S)([\\s\\S]*?\\S)\\*\\*(?!\\*)/,em:/^_(?=\\S)([\\s\\S]*?\\S)_(?!_)|^\\*(?=\\S)([\\s\\S]*?\\S)\\*(?!\\*)/}),u.gfm=h({},u.normal,{escape:l(u.escape)(\"])\",\"~|])\")(),url:/^(https?:\\/\\/[^\\s<]+[^<.,:;\"')\\]\\s])/,del:/^~~(?=\\S)([\\s\\S]*?\\S)~~/,text:l(u.text)(\"]|\",\"~]|\")(\"|\",\"|https?://|\")()}),u.breaks=h({},u.gfm,{br:l(u.br)(\"{2,}\",\"*\")(),text:l(u.gfm.text)(\"{2,}\",\"*\")()}),t.rules=u,t.output=function(e,n,r){var s=new t(n,r);return s.output(e)},t.prototype.output=function(e){for(var t,n,r,i,l=\"\";e;)if(i=this.rules.escape.exec(e))e=e.substring(i[0].length),l+=i[1];else if(i=this.rules.autolink.exec(e))e=e.substring(i[0].length),\"@\"===i[2]?(n=\":\"===i[1].charAt(6)?this.mangle(i[1].substring(7)):this.mangle(i[1]),r=this.mangle(\"mailto:\")+n):(n=s(i[1]),r=n),l+=this.renderer.link(r,null,n);else if(this.inLink||!(i=this.rules.url.exec(e))){if(i=this.rules.tag.exec(e))!this.inLink&&/^<a /i.test(i[0])?this.inLink=!0:this.inLink&&/^<\\/a>/i.test(i[0])&&(this.inLink=!1),e=e.substring(i[0].length),l+=this.options.sanitize?s(i[0]):i[0];else if(i=this.rules.link.exec(e))e=e.substring(i[0].length),this.inLink=!0,l+=this.outputLink(i,{href:i[2],title:i[3]}),this.inLink=!1;else if((i=this.rules.reflink.exec(e))||(i=this.rules.nolink.exec(e))){if(e=e.substring(i[0].length),t=(i[2]||i[1]).replace(/\\s+/g,\" \"),t=this.links[t.toLowerCase()],!t||!t.href){l+=i[0].charAt(0),e=i[0].substring(1)+e;continue}this.inLink=!0,l+=this.outputLink(i,t),this.inLink=!1}else if(i=this.rules.strong.exec(e))e=e.substring(i[0].length),l+=this.renderer.strong(this.output(i[2]||i[1]));else if(i=this.rules.em.exec(e))e=e.substring(i[0].length),l+=this.renderer.em(this.output(i[2]||i[1]));else if(i=this.rules.code.exec(e))e=e.substring(i[0].length),l+=this.renderer.codespan(s(i[2],!0));else if(i=this.rules.br.exec(e))e=e.substring(i[0].length),l+=this.renderer.br();else if(i=this.rules.del.exec(e))e=e.substring(i[0].length),l+=this.renderer.del(this.output(i[1]));else if(i=this.rules.text.exec(e))e=e.substring(i[0].length),l+=s(this.smartypants(i[0]));else if(e)throw new Error(\"Infinite loop on byte: \"+e.charCodeAt(0))}else e=e.substring(i[0].length),n=s(i[1]),r=n,l+=this.renderer.link(r,null,n);return l},t.prototype.outputLink=function(e,t){var n=s(t.href),r=t.title?s(t.title):null;return\"!\"!==e[0].charAt(0)?this.renderer.link(n,r,this.output(e[1])):this.renderer.image(n,r,s(e[1]))},t.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/--/g,\"—\").replace(/(^|[-\\u2014\\/(\\[{\"\\s])'/g,\"$1‘\").replace(/'/g,\"’\").replace(/(^|[-\\u2014\\/(\\[{\\u2018\\s])\"/g,\"$1“\").replace(/\"/g,\"”\").replace(/\\.{3}/g,\"…\"):e},t.prototype.mangle=function(e){for(var t,n=\"\",r=e.length,s=0;s<r;s++)t=e.charCodeAt(s),Math.random()>.5&&(t=\"x\"+t.toString(16)),n+=\"&#\"+t+\";\";return n},n.prototype.code=function(e,t,n){if(this.options.highlight){var r=this.options.highlight(e,t);null!=r&&r!==e&&(n=!0,e=r)}return t?'<pre><code class=\"'+this.options.langPrefix+s(t,!0)+'\">'+(n?e:s(e,!0))+\"\\n</code></pre>\\n\":\"<pre><code>\"+(n?e:s(e,!0))+\"\\n</code></pre>\"},n.prototype.blockquote=function(e){return\"<blockquote>\\n\"+e+\"</blockquote>\\n\"},n.prototype.html=function(e){return e},n.prototype.heading=function(e,t,n){return\"<h\"+t+' id=\"'+this.options.headerPrefix+n.toLowerCase().replace(/[^\\w]+/g,\"-\")+'\">'+e+\"</h\"+t+\">\\n\"},n.prototype.hr=function(){return this.options.xhtml?\"<hr/>\\n\":\"<hr>\\n\"},n.prototype.list=function(e,t){var n=t?\"ol\":\"ul\";return\"<\"+n+\">\\n\"+e+\"</\"+n+\">\\n\"},n.prototype.listitem=function(e){return\"<li>\"+e+\"</li>\\n\"},n.prototype.paragraph=function(e){return\"<p>\"+e+\"</p>\\n\"},n.prototype.table=function(e,t){return\"<table>\\n<thead>\\n\"+e+\"</thead>\\n<tbody>\\n\"+t+\"</tbody>\\n</table>\\n\"},n.prototype.tablerow=function(e){return\"<tr>\\n\"+e+\"</tr>\\n\"},n.prototype.tablecell=function(e,t){var n=t.header?\"th\":\"td\",r=t.align?\"<\"+n+' style=\"text-align:'+t.align+'\">':\"<\"+n+\">\";return r+e+\"</\"+n+\">\\n\"},n.prototype.strong=function(e){return\"<strong>\"+e+\"</strong>\"},n.prototype.em=function(e){return\"<em>\"+e+\"</em>\"},n.prototype.codespan=function(e){return\"<code>\"+e+\"</code>\"},n.prototype.br=function(){return this.options.xhtml?\"<br/>\":\"<br>\"},n.prototype.del=function(e){return\"<del>\"+e+\"</del>\"},n.prototype.link=function(e,t,n){if(this.options.sanitize){try{var r=decodeURIComponent(i(e)).replace(/[^\\w:]/g,\"\").toLowerCase()}catch(s){return\"\"}if(0===r.indexOf(\"javascript:\"))return\"\"}var l='<a href=\"'+e+'\"';return t&&(l+=' title=\"'+t+'\"'),l+=\">\"+n+\"</a>\"},n.prototype.image=function(e,t,n){var r='<img src=\"'+e+'\" alt=\"'+n+'\"';return t&&(r+=' title=\"'+t+'\"'),r+=this.options.xhtml?\"/>\":\">\"},r.parse=function(e,t,n){var s=new r(t,n);return s.parse(e)},r.prototype.parse=function(e){this.inline=new t(e.links,this.options,this.renderer),this.tokens=e.reverse();for(var n=\"\";this.next();)n+=this.tok();return n},r.prototype.next=function(){return this.token=this.tokens.pop()},r.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},r.prototype.parseText=function(){for(var e=this.token.text;\"text\"===this.peek().type;)e+=\"\\n\"+this.next().text;return this.inline.output(e)},r.prototype.tok=function(){switch(this.token.type){case\"space\":return\"\";case\"hr\":return this.renderer.hr();case\"heading\":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case\"code\":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case\"table\":var e,t,n,r,s,i=\"\",l=\"\";for(n=\"\",e=0;e<this.token.header.length;e++)r={header:!0,align:this.token.align[e]},n+=this.renderer.tablecell(this.inline.output(this.token.header[e]),{header:!0,align:this.token.align[e]});for(i+=this.renderer.tablerow(n),e=0;e<this.token.cells.length;e++){for(t=this.token.cells[e],n=\"\",s=0;s<t.length;s++)n+=this.renderer.tablecell(this.inline.output(t[s]),{header:!1,align:this.token.align[s]});l+=this.renderer.tablerow(n)}return this.renderer.table(i,l);case\"blockquote_start\":for(var l=\"\";\"blockquote_end\"!==this.next().type;)l+=this.tok();return this.renderer.blockquote(l);case\"list_start\":for(var l=\"\",o=this.token.ordered;\"list_end\"!==this.next().type;)l+=this.tok();return this.renderer.list(l,o);case\"list_item_start\":for(var l=\"\";\"list_item_end\"!==this.next().type;)l+=\"text\"===this.token.type?this.parseText():this.tok();return this.renderer.listitem(l);case\"loose_item_start\":for(var l=\"\";\"list_item_end\"!==this.next().type;)l+=this.tok();return this.renderer.listitem(l);case\"html\":var h=this.token.pre||this.options.pedantic?this.token.text:this.inline.output(this.token.text);return this.renderer.html(h);case\"paragraph\":return this.renderer.paragraph(this.inline.output(this.token.text));case\"text\":return this.renderer.paragraph(this.parseText())}},o.exec=o,a.options=a.setOptions=function(e){return h(a.defaults,e),a},a.defaults={gfm:!0,tables:!0,breaks:!1,pedantic:!1,sanitize:!1,smartLists:!1,silent:!1,highlight:null,langPrefix:\"lang-\",smartypants:!1,headerPrefix:\"\",renderer:new n,xhtml:!1},a.Parser=r,a.parser=r.parse,a.Renderer=n,a.Lexer=e,a.lexer=e.lex,a.InlineLexer=t,a.inlineLexer=t.output,a.parse=a,\"undefined\"!=typeof module&&\"object\"==typeof exports?module.exports=a:\"function\"==typeof define&&define.amd?define(function(){return a}):this.marked=a}).call(function(){return this||(\"undefined\"!=typeof window?window:global)}());"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lib/object-assign-pollyfill.js",
    "content": "\"function\"!=typeof Object.assign&&!function(){Object.assign=function(n){\"use strict\";if(void 0===n||null===n)throw new TypeError(\"Cannot convert undefined or null to object\");for(var t=Object(n),o=1;o<arguments.length;o++){var r=arguments[o];if(void 0!==r&&null!==r)for(var e in r)Object.prototype.hasOwnProperty.call(r,e)&&(t[e]=r[e])}return t}}();"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/lib/swagger-oauth.js",
    "content": "function handleLogin(){var e=[],o=window.swaggerUiAuth.authSchemes||window.swaggerUiAuth.securityDefinitions;if(o){var i,n=o;for(i in n){var a=n[i];if(\"oauth2\"===a.type&&a.scopes){var t;if(Array.isArray(a.scopes)){var p;for(p=0;p<a.scopes.length;p++)e.push(a.scopes[p])}else for(t in a.scopes)e.push({scope:t,description:a.scopes[t],OAuthSchemeKey:i})}}}for(window.swaggerUi.api&&window.swaggerUi.api.info&&(appName=window.swaggerUi.api.info.title),$(\".api-popup-dialog\").remove(),popupDialog=$(['<div class=\"api-popup-dialog\">','<div class=\"api-popup-title\">Select OAuth2.0 Scopes</div>','<div class=\"api-popup-content\">',\"<p>Scopes are used to grant an application different levels of access to data on behalf of the end user. Each API may declare one or more scopes.\",'<a href=\"#\">Learn how to use</a>',\"</p>\",\"<p><strong>\"+appName+\"</strong> API requires the following scopes. Select which ones you want to grant to Swagger UI.</p>\",'<ul class=\"api-popup-scopes\">',\"</ul>\",'<p class=\"error-msg\"></p>','<div class=\"api-popup-actions\"><button class=\"api-popup-authbtn api-button green\" type=\"button\" data-sw-translate>Authorize</button><button class=\"api-popup-cancel api-button gray\" type=\"button\">Cancel</button></div>',\"</div>\",\"</div>\"].join(\"\")),$(document.body).append(popupDialog),popup=popupDialog.find(\"ul.api-popup-scopes\").empty(),p=0;p<e.length;p++)t=e[p],str='<li><input type=\"checkbox\" id=\"scope_'+p+'\" scope=\"'+t.scope+'\"\" oauthtype=\"'+t.OAuthSchemeKey+'\"/><label for=\"scope_'+p+'\">'+t.scope,t.description&&($.map(o,function(e,o){return o}).length>1?str+='<br/><span class=\"api-scope-desc\">'+t.description+\" (\"+t.OAuthSchemeKey+\")</span>\":str+='<br/><span class=\"api-scope-desc\">'+t.description+\"</span>\"),str+=\"</label></li>\",popup.append(str);var r=$(window),s=r.width(),c=r.height(),l=r.scrollTop(),d=popupDialog.outerWidth(),u=popupDialog.outerHeight(),h=(c-u)/2+l,g=(s-d)/2;popupDialog.css({top:(h<0?0:h)+\"px\",left:(g<0?0:g)+\"px\"}),popupDialog.find(\"button.api-popup-cancel\").click(function(){popupMask.hide(),popupDialog.hide(),popupDialog.empty(),popupDialog=[]}),$(\"button.api-popup-authbtn\").unbind(),popupDialog.find(\"button.api-popup-authbtn\").click(function(){function e(e){return e.vendorExtensions[\"x-tokenName\"]||e.tokenName}popupMask.hide(),popupDialog.hide();var o,i=window.swaggerUi.api.authSchemes,n=window.location,a=location.pathname.substring(0,location.pathname.lastIndexOf(\"/\")),t=n.protocol+\"//\"+n.host+a+\"/o2c.html\",p=window.oAuthRedirectUrl||t,r=null,s=[],c=popup.find(\"input:checked\"),l=[];for(k=0;k<c.length;k++){var d=$(c[k]).attr(\"scope\");s.indexOf(d)===-1&&s.push(d);var u=$(c[k]).attr(\"oauthtype\");l.indexOf(u)===-1&&l.push(u)}window.enabledScopes=s;for(var h in i)if(i.hasOwnProperty(h)&&l.indexOf(h)!=-1){var g=i[h].flow;if(\"oauth2\"!==i[h].type||!g||\"implicit\"!==g&&\"accessCode\"!==g){if(\"oauth2\"===i[h].type&&g&&\"application\"===g){var w=i[h];return window.swaggerUi.tokenName=e(w)||\"access_token\",void clientCredentialsFlow(s,w.tokenUrl,h)}if(i[h].grantTypes){var c=i[h].grantTypes;for(var f in c)if(c.hasOwnProperty(f)&&\"implicit\"===f){var w=c[f];w.loginEndpoint.url;r=w.loginEndpoint.url+\"?response_type=token\",window.swaggerUi.tokenName=e(w)}else if(c.hasOwnProperty(f)&&\"accessCode\"===f){var w=c[f];w.tokenRequestEndpoint.url;r=w.tokenRequestEndpoint.url+\"?response_type=code\",window.swaggerUi.tokenName=e(w)}}}else{var w=i[h];r=w.authorizationUrl+\"?response_type=\"+(\"implicit\"===g?\"token\":\"code\"),window.swaggerUi.tokenName=e(w)||\"access_token\",window.swaggerUi.tokenUrl=\"accessCode\"===g?w.tokenUrl:null,o=h}}redirect_uri=p,r+=\"&redirect_uri=\"+encodeURIComponent(p),r+=\"&realm=\"+encodeURIComponent(realm),r+=\"&client_id=\"+encodeURIComponent(clientId),r+=\"&scope=\"+encodeURIComponent(s.join(scopeSeparator)),r+=\"&state=\"+encodeURIComponent(o);for(var h in additionalQueryStringParams)r+=\"&\"+h+\"=\"+encodeURIComponent(additionalQueryStringParams[h]);window.open(r)}),popupMask.show(),popupDialog.show()}function handleLogout(){for(key in window.swaggerUi.api.clientAuthorizations.authz)window.swaggerUi.api.clientAuthorizations.remove(key);window.enabledScopes=null,$(\".api-ic.ic-on\").addClass(\"ic-off\"),$(\".api-ic.ic-on\").removeClass(\"ic-on\"),$(\".api-ic.ic-warning\").addClass(\"ic-error\"),$(\".api-ic.ic-warning\").removeClass(\"ic-warning\")}function initOAuth(e){var o=e||{},i=[];return appName=o.appName||i.push(\"missing appName\"),popupMask=o.popupMask||$(\"#api-common-mask\"),popupDialog=o.popupDialog||$(\".api-popup-dialog\"),clientId=o.clientId||i.push(\"missing client id\"),clientSecret=o.clientSecret||null,realm=o.realm||i.push(\"missing realm\"),scopeSeparator=o.scopeSeparator||\" \",additionalQueryStringParams=o.additionalQueryStringParams||{},i.length>0?void log(\"auth unable initialize oauth: \"+i):($(\"pre code\").each(function(e,o){hljs.highlightBlock(o)}),$(\".api-ic\").unbind(),void $(\".api-ic\").click(function(e){$(e.target).hasClass(\"ic-off\")?handleLogin():handleLogout()}))}function clientCredentialsFlow(e,o,i){var n={client_id:clientId,client_secret:clientSecret,scope:e.join(\" \"),grant_type:\"client_credentials\"};$.ajax({url:o,type:\"POST\",data:n,success:function(e,o,n){onOAuthComplete(e,i)},error:function(e,o,i){onOAuthComplete(\"\")}})}var appName,popupMask,popupDialog,clientId,realm,redirect_uri,clientSecret,scopeSeparator,additionalQueryStringParams;window.processOAuthCode=function(e){var o=e.state,i=window.location,n=location.pathname.substring(0,location.pathname.lastIndexOf(\"/\")),a=i.protocol+\"//\"+i.host+n+\"/o2c.html\",t=window.oAuthRedirectUrl||a,p={client_id:clientId,code:e.code,grant_type:\"authorization_code\",redirect_uri:t};clientSecret&&(p.client_secret=clientSecret),$.ajax({url:window.swaggerUiAuth.tokenUrl,type:\"POST\",data:p,success:function(e,i,n){onOAuthComplete(e,o)},error:function(e,o,i){onOAuthComplete(\"\")}})},window.onOAuthComplete=function(e,o){if(e)if(e.error){var i=$(\"input[type=checkbox],.secured\");i.each(function(e){i[e].checked=!1}),alert(e.error)}else{var n=e[window.swaggerUiAuth.tokenName];if(o||(o=e.state),n){var a=null;$.each($(\".auth .api-ic .api_information_panel\"),function(e,o){var i=o;if(i&&i.childNodes){var n=[];$.each(i.childNodes,function(e,o){var i=o.innerHTML;i&&n.push(i)});for(var t=[],p=0;p<n.length;p++){var r=n[p];window.enabledScopes&&window.enabledScopes.indexOf(r)==-1&&t.push(r)}t.length>0?(a=o.parentNode.parentNode,$(a.parentNode).find(\".api-ic.ic-on\").addClass(\"ic-off\"),$(a.parentNode).find(\".api-ic.ic-on\").removeClass(\"ic-on\"),$(a).find(\".api-ic\").addClass(\"ic-warning\"),$(a).find(\".api-ic\").removeClass(\"ic-error\")):(a=o.parentNode.parentNode,$(a.parentNode).find(\".api-ic.ic-off\").addClass(\"ic-on\"),$(a.parentNode).find(\".api-ic.ic-off\").removeClass(\"ic-off\"),$(a).find(\".api-ic\").addClass(\"ic-info\"),$(a).find(\".api-ic\").removeClass(\"ic-warning\"),$(a).find(\".api-ic\").removeClass(\"ic-error\"))}}),\"undefined\"!=typeof window.swaggerUi&&(window.swaggerUi.api.clientAuthorizations.add(window.swaggerUiAuth.OAuthSchemeKey,new SwaggerClient.ApiKeyAuthorization(\"Authorization\",\"Bearer \"+n,\"header\")),window.swaggerUi.load())}}};\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/o2c.html",
    "content": "<script>\nvar qp = null;\nif(/code|token|error/.test(window.location.hash)) {\n  qp = location.hash.substring(1);\n}\nelse {\n  qp = location.search.substring(1);\n}\nqp = qp ? JSON.parse('{\"' + qp.replace(/&/g, '\",\"').replace(/=/g,'\":\"') + '\"}',\n  function(key, value) {\n    return key===\"\"?value:decodeURIComponent(value) }\n  ):{}\n\nif (window.opener.swaggerUiAuth.tokenUrl)\n    window.opener.processOAuthCode(qp);\nelse\n    window.opener.onOAuthComplete(qp);\n\nwindow.close();\n</script>\n"
  },
  {
    "path": "ymall-web-admin/src/main/webapp/static/assets/static/swagger/swagger-ui.js",
    "content": "/**\n * swagger-ui - Swagger UI is a dependency-free collection of HTML, JavaScript, and CSS assets that dynamically generate beautiful documentation from a Swagger-compliant API\n * @version v2.2.10\n * @link http://swagger.io\n * @license Apache-2.0\n */\n(function(){/* jshint ignore:start */\n {(function() {\n  var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};\ntemplates['apikey_auth'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"                <span class=\\\"key_auth__value\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.value : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</span>\\n\";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    return \"                <input placeholder=\\\"api_key\\\" class=\\\"auth_input input_apiKey_entry\\\" name=\\\"apiKey\\\" type=\\\"text\\\"/>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<div class=\\\"key_input_container\\\">\\n    <h3 class=\\\"auth__title\\\">Api key authorization</h3>\\n    <div class=\\\"auth__description\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</div>\\n    <div>\\n        <div class=\\\"key_auth__field\\\">\\n            <span class=\\\"key_auth__label\\\">name:</span>\\n            <span class=\\\"key_auth__value\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</span>\\n        </div>\\n        <div class=\\\"key_auth__field\\\">\\n            <span class=\\\"key_auth__label\\\">in:</span>\\n            <span class=\\\"key_auth__value\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0[\"in\"] : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</span>\\n        </div>\\n        <div class=\\\"key_auth__field\\\">\\n            <span class=\\\"key_auth__label\\\">value:</span>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isLogout : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.program(3, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"        </div>\\n    </div>\\n</div>\\n\";\n},\"useData\":true});\ntemplates['auth_button'] = template({\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    return \"<a class='authorize__btn' href=\\\"#\\\" data-sw-translate>Authorize</a>\\n\";\n},\"useData\":true});\ntemplates['auth_button_operation'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    return \"        authorize__btn_operation_login\\n\";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    return \"        authorize__btn_operation_logout\\n\";\n},\"5\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"        <ul class=\\\"authorize-scopes\\\">\\n\"\n    + ((stack1 = helpers.each.call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.scopes : depth0),{\"name\":\"each\",\"hash\":{},\"fn\":container.program(6, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"        </ul>\\n\";\n},\"6\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"                <li class=\\\"authorize__scope\\\" title=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.scope : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</li>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {};\n\n  return \"<div class=\\\"authorize__btn authorize__btn_operation\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isLogout : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.program(3, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.scopes : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(5, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"</div>\\n\";\n},\"useData\":true});\ntemplates['auth_view'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    return \"            <button type=\\\"button\\\" class=\\\"auth__button auth_submit__button\\\" data-sw-translate>Authorize</button>\\n\";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    return \"            <button type=\\\"button\\\" class=\\\"auth__button auth_logout__button\\\" data-sw-translate>Logout</button>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {};\n\n  return \"<div class=\\\"auth_container\\\">\\n\\n    <div class=\\\"auth_inner\\\"></div>\\n    <div class=\\\"auth_submit\\\">\\n\"\n    + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.isLogout : depth0),{\"name\":\"unless\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isAuthorized : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(3, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"    </div>\\n\\n</div>\\n\";\n},\"useData\":true});\ntemplates['basic_auth'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    return \" - authorized\";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"                <span class=\\\"basic_auth__value\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.username : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</span>\\n\";\n},\"5\":function(container,depth0,helpers,partials,data) {\n    return \"                <input required placeholder=\\\"username\\\" class=\\\"basic_auth__username auth_input\\\" name=\\\"username\\\" type=\\\"text\\\"/>\\n\";\n},\"7\":function(container,depth0,helpers,partials,data) {\n    return \"            <div class=\\\"auth_label\\\">\\n                <span class=\\\"basic_auth__label\\\" data-sw-translate>password:</span>\\n                <input required placeholder=\\\"password\\\" class=\\\"basic_auth__password auth_input\\\" name=\\\"password\\\" type=\\\"password\\\"/></label>\\n            </div>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {};\n\n  return \"<div class='basic_auth_container'>\\n    <h3 class=\\\"auth__title\\\">Basic authentication\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isLogout : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"</h3>\\n    <form class=\\\"basic_input_container\\\">\\n        <div class=\\\"auth__description\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || helpers.helperMissing).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</div>\\n        <div class=\\\"auth_label\\\">\\n            <span class=\\\"basic_auth__label\\\" data-sw-translate>username:</span>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isLogout : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(3, data, 0),\"inverse\":container.program(5, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"        </div>\\n\"\n    + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.isLogout : depth0),{\"name\":\"unless\",\"hash\":{},\"fn\":container.program(7, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"    </form>\\n</div>\\n\";\n},\"useData\":true});\ntemplates['content_type'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers.each.call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.produces : depth0),{\"name\":\"each\",\"hash\":{},\"fn\":container.program(2, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\");\n},\"2\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"\t<option value=\\\"\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,depth0,{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,depth0,{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</option>\\n\";\n},\"4\":function(container,depth0,helpers,partials,data) {\n    return \"  <option value=\\\"application/json\\\">application/json</option>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<label data-sw-translate for=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.contentTypeId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">Response Content Type</label>\\n<select name=\\\"contentType\\\" id=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.contentTypeId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.produces : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.program(4, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"</select>\\n\";\n},\"useData\":true});\ntemplates['main'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"  <div class=\\\"info_title\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.title : stack1),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</div>\\n  <div class=\\\"info_description markdown\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.description : stack1),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</div>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.externalDocs : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(2, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"  \"\n    + ((stack1 = helpers[\"if\"].call(alias1,((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.termsOfServiceUrl : stack1),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(4, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n  \"\n    + ((stack1 = helpers[\"if\"].call(alias1,((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.name : stack1),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(6, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n  \"\n    + ((stack1 = helpers[\"if\"].call(alias1,((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.url : stack1),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(8, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n  \"\n    + ((stack1 = helpers[\"if\"].call(alias1,((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.email : stack1),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(10, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n  \"\n    + ((stack1 = helpers[\"if\"].call(alias1,((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.license : stack1),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(12, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n\";\n},\"2\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"  <p>\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,((stack1 = (depth0 != null ? depth0.externalDocs : depth0)) != null ? stack1.description : stack1),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</p>\\n  <a href=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,((stack1 = (depth0 != null ? depth0.externalDocs : depth0)) != null ? stack1.url : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\" target=\\\"_blank\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,((stack1 = (depth0 != null ? depth0.externalDocs : depth0)) != null ? stack1.url : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</a>\\n\";\n},\"4\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"<div class=\\\"info_tos\\\"><a target=\\\"_blank\\\" href=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || helpers.helperMissing).call(depth0 != null ? depth0 : {},((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.termsOfServiceUrl : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\" data-sw-translate>Terms of service</a></div>\";\n},\"6\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"<div><div class='info_name' style=\\\"display: inline\\\" data-sw-translate>Created by </div> \"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || helpers.helperMissing).call(depth0 != null ? depth0 : {},((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.name : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</div>\";\n},\"8\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<div class='info_url' data-sw-translate>See more at <a href=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.url : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.url : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</a></div>\";\n},\"10\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<div class='info_email'><a target=\\\"_parent\\\" href=\\\"mailto:\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.contact : stack1)) != null ? stack1.email : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"?subject=\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.title : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\" data-sw-translate>Contact the developer</a></div>\";\n},\"12\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<div class='info_license'><a target=\\\"_blank\\\" href='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.license : stack1)) != null ? stack1.url : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,((stack1 = ((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.license : stack1)) != null ? stack1.name : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</a></div>\";\n},\"14\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"  , <span style=\\\"font-variant: small-caps\\\" data-sw-translate>api version</span>: \"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || helpers.helperMissing).call(depth0 != null ? depth0 : {},((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.version : stack1),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n    \";\n},\"16\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"    <span style=\\\"float:right\\\"><a target=\\\"_blank\\\" href=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.validatorUrl : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"/debug?url=\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.url : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\"><img id=\\\"validator\\\" src=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.validatorUrl : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"?url=\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.url : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\"></a>\\n    </span>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {};\n\n  return \"<div class='info' id='api_info'>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.info : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"</div>\\n<div class='container' id='resources_container'>\\n  <div class='authorize-wrapper'></div>\\n\\n  <ul id='resources'></ul>\\n\\n  <div class=\\\"footer\\\">\\n    <h4 style=\\\"color: #999\\\">[ <span style=\\\"font-variant: small-caps\\\">base url</span>: \"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || helpers.helperMissing).call(alias1,(depth0 != null ? depth0.basePath : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,((stack1 = (depth0 != null ? depth0.info : depth0)) != null ? stack1.version : stack1),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(14, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"]\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.validatorUrl : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(16, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"    </h4>\\n    </div>\\n</div>\\n\";\n},\"useData\":true});\ntemplates['oauth2'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"<p>Authorization URL: \"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.authorizationUrl : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</p>\";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"<p>Token URL: \"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.tokenUrl : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</p>\";\n},\"5\":function(container,depth0,helpers,partials,data) {\n    return \"        <p>Please input username and password for password flow authorization</p>\\n        <fieldset>\\n            <div><label>Username: <input class=\\\"oauth-username\\\" type=\\\"text\\\" name=\\\"username\\\"></label></div>\\n            <div><label>Password: <input class=\\\"oauth-password\\\" type=\\\"password\\\" name=\\\"password\\\"></label></div>\\n        </fieldset>\\n\";\n},\"7\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"        <p>Setup client authentication.\"\n    + ((stack1 = helpers[\"if\"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.requireClientAuthenticaiton : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(8, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"</p>\\n        <fieldset>\\n            <div><label>Type:\\n                <select class=\\\"oauth-client-authentication-type\\\" name=\\\"client-authentication-type\\\">\\n                    <option value=\\\"none\\\" selected>None or other</option>\\n                    <option value=\\\"basic\\\">Basic auth</option>\\n                    <option value=\\\"request-body\\\">Request body</option>\\n                </select>\\n            </label></div>\\n            <div class=\\\"oauth-client-authentication\\\" hidden>\\n                <div><label>ClientId: <input class=\\\"oauth-client-id\\\" type=\\\"text\\\" name=\\\"client-id\\\"></label></div>\\n                <div><label>Secret: <input class=\\\"oauth-client-secret\\\" type=\\\"text\\\" name=\\\"client-secret\\\"></label></div>\\n            </div>\\n        </fieldset>\\n\";\n},\"8\":function(container,depth0,helpers,partials,data) {\n    return \"(Required)\";\n},\"10\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"            <li>\\n                <input class=\\\"oauth-scope\\\" type=\\\"checkbox\\\" data-scope=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.scope : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\" oauthtype=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.OAuthSchemeKey : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\"/>\\n                <label>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.scope : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</label><br/>\\n                <span class=\\\"api-scope-desc\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.OAuthSchemeKey : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(11, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"                </span>\\n            </li>\\n\";\n},\"11\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"                        (\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.OAuthSchemeKey : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \")\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<div>\\n    <h3 class=\\\"auth__title\\\">OAuth2.0</h3>\\n    <p>\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</p>\\n    \"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.authorizationUrl : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n    \"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.tokenUrl : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(3, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n    <p>flow: \"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.flow : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</p>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isPasswordFlow : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(5, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.clientAuthentication : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(7, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"    <p><strong> \"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.appName : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \" </strong> API requires the following scopes. Select which ones you want to grant to Swagger UI.</p>\\n    <p>Scopes are used to grant an application different levels of access to data on behalf of the end user. Each API may declare one or more scopes.\\n        <a href=\\\"#\\\">Learn how to use</a>\\n    </p>\\n    <ul class=\\\"api-popup-scopes\\\">\\n\"\n    + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.scopes : depth0),{\"name\":\"each\",\"hash\":{},\"fn\":container.program(10, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"    </ul>\\n</div>\";\n},\"useData\":true});\ntemplates['operation'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    return \"deprecated\";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    return \"            <h4><span data-sw-translate>Warning: Deprecated</span></h4>\\n\";\n},\"5\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"        <h4><span data-sw-translate>Implementation Notes</span></h4>\\n        <div class=\\\"markdown\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.description : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</div>\\n\";\n},\"7\":function(container,depth0,helpers,partials,data) {\n    return \"            <div class='authorize-wrapper authorize-wrapper_operation'></div>\\n\";\n},\"9\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {};\n\n  return \"          <div class=\\\"response-class\\\">\\n            <h4><span data-sw-translate>Response Class</span> (<span data-sw-translate>Status</span> \"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || helpers.helperMissing).call(alias1,(depth0 != null ? depth0.successCode : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \")</h4>\\n              \"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.successDescription : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(10, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n            <p><span class=\\\"model-signature\\\" /></p>\\n            <br/>\\n            <div class=\\\"response-content-type\\\" />\\n            </div>\\n\";\n},\"10\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"<div class=\\\"markdown\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.successDescription : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</div>\";\n},\"12\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"          <h4 data-sw-translate>Headers</h4>\\n          <table class=\\\"headers\\\">\\n            <thead>\\n              <tr>\\n                <th style=\\\"width: 100px; max-width: 100px\\\" data-sw-translate>Header</th>\\n                <th style=\\\"width: 310px; max-width: 310px\\\" data-sw-translate>Description</th>\\n                <th style=\\\"width: 200px; max-width: 200px\\\" data-sw-translate>Type</th>\\n                <th style=\\\"width: 320px; max-width: 320px\\\" data-sw-translate>Other</th>\\n              </tr>\\n            </thead>\\n            <tbody>\\n\"\n    + ((stack1 = helpers.each.call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.headers : depth0),{\"name\":\"each\",\"hash\":{},\"fn\":container.program(13, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"            </tbody>\\n          </table>\\n\";\n},\"13\":function(container,depth0,helpers,partials,data) {\n    var stack1, helper, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"              <tr>\\n                <td>\"\n    + container.escapeExpression(((helper = (helper = helpers.key || (data && data.key)) != null ? helper : alias2),(typeof helper === \"function\" ? helper.call(alias1,{\"name\":\"key\",\"hash\":{},\"data\":data}) : helper)))\n    + \"</td>\\n                <td>\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n                <td>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.type : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n                <td>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.other : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n              </tr>\\n\";\n},\"15\":function(container,depth0,helpers,partials,data) {\n    return \"          <h4 data-sw-translate>Parameters</h4>\\n          <table class='fullwidth parameters'>\\n          <thead>\\n            <tr>\\n            <th style=\\\"width: 100px; max-width: 100px\\\" data-sw-translate>Parameter</th>\\n            <th style=\\\"width: 310px; max-width: 310px\\\" data-sw-translate>Value</th>\\n            <th style=\\\"width: 200px; max-width: 200px\\\" data-sw-translate>Description</th>\\n            <th style=\\\"width: 100px; max-width: 100px\\\" data-sw-translate>Parameter Type</th>\\n            <th style=\\\"width: 220px; max-width: 230px\\\" data-sw-translate>Data Type</th>\\n            </tr>\\n          </thead>\\n          <tbody class=\\\"operation-params\\\">\\n\\n          </tbody>\\n          </table>\\n\";\n},\"17\":function(container,depth0,helpers,partials,data) {\n    return \"          <div style='margin:0;padding:0;display:inline'></div>\\n          <h4 data-sw-translate>Response Messages</h4>\\n          <table class='fullwidth response-messages'>\\n            <thead>\\n            <tr>\\n              <th data-sw-translate>HTTP Status Code</th>\\n              <th data-sw-translate>Reason</th>\\n              <th data-sw-translate>Response Model</th>\\n              <th data-sw-translate>Headers</th>\\n            </tr>\\n            </thead>\\n            <tbody class=\\\"operation-status\\\">\\n            </tbody>\\n          </table>\\n\";\n},\"19\":function(container,depth0,helpers,partials,data) {\n    return \"\";\n},\"21\":function(container,depth0,helpers,partials,data) {\n    return \"          <div class='sandbox_header'>\\n            <input class='submit' type='submit' value='Try it out!' data-sw-translate/>\\n            <a href='#' class='response_hider' style='display:none' data-sw-translate>Hide Response</a>\\n            <span class='response_throbber' style='display:none'></span>\\n          </div>\\n\";\n},\"23\":function(container,depth0,helpers,partials,data) {\n    return \"          <h4 data-sw-translate>Request Headers</h4>\\n          <div class='block request_headers'></div>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3=container.escapeExpression;\n\n  return \"  <ul class='operations' >\\n    <li class='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.method : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \" operation' id='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.parentId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"_\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.nickname : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'>\\n      <div class='heading'>\\n        <h3>\\n          <span class='http_method'>\\n          <a href='#!/\"\n    + alias3((helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.encodedParentId : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data}))\n    + \"/\"\n    + alias3((helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.nickname : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data}))\n    + \"' class=\\\"toggleOperation\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.method : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</a>\\n          </span>\\n          <span class='path'>\\n          <a href='#!/\"\n    + alias3((helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.encodedParentId : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data}))\n    + \"/\"\n    + alias3((helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.nickname : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data}))\n    + \"' class=\\\"toggleOperation \"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.deprecated : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.path : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</a>\\n          </span>\\n        </h3>\\n        <ul class='options'>\\n          <li>\\n          <a href='#!/\"\n    + alias3((helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.encodedParentId : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data}))\n    + \"/\"\n    + alias3((helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.nickname : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data}))\n    + \"' class=\\\"toggleOperation\\\"><span class=\\\"markdown\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.summary : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</span></a>\\n          </li>\\n        </ul>\\n      </div>\\n      <div class='content' id='\"\n    + alias3((helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.encodedParentId : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data}))\n    + \"_\"\n    + alias3((helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.nickname : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data}))\n    + \"_content' style='display:none'>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.deprecated : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(3, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(5, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.security : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(7, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.type : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(9, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.headers : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(12, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n        <form accept-charset='UTF-8' class='sandbox'>\\n          <div style='margin:0;padding:0;display:inline'></div>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.parameters : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(15, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.responseMessages : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(17, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isReadOnly : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(19, data, 0),\"inverse\":container.program(21, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"        </form>\\n        <div class='response' style='display:none'>\\n          <h4 class='curl'>Curl</h4>\\n          <div class='block curl'></div>\\n          <h4 data-sw-translate>Request URL</h4>\\n          <div class='block request_url'></div>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.showRequestHeaders : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(23, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"          <h4 data-sw-translate>Response Body</h4>\\n          <div class='block response_body'></div>\\n          <h4 data-sw-translate>Response Code</h4>\\n          <div class='block response_code'></div>\\n          <h4 data-sw-translate>Response Headers</h4>\\n          <div class='block response_headers'></div>\\n        </div>\\n      </div>\\n    </li>\\n  </ul>\\n\";\n},\"useData\":true});\ntemplates['param'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers[\"if\"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.isFile : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(2, data, 0),\"inverse\":container.program(4, data, 0),\"data\":data})) != null ? stack1 : \"\");\n},\"2\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"\t\t\t<input type=\\\"file\\\" name='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' id='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'/>\\n\t\t\t<div class=\\\"parameter-content-type\\\" />\\n\";\n},\"4\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers[\"if\"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0[\"default\"] : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(5, data, 0),\"inverse\":container.program(7, data, 0),\"data\":data})) != null ? stack1 : \"\");\n},\"5\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"\t\t\t\t<div class=\\\"editor_holder\\\"></div>\\n\t\t\t\t<textarea class='body-textarea' name='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' id='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0[\"default\"] : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</textarea>\\n        <br />\\n        <div class=\\\"parameter-content-type\\\" />\\n\";\n},\"7\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"\t\t\t\t<textarea class='body-textarea' name='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' id='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'></textarea>\\n\t\t\t\t<div class=\\\"editor_holder\\\"></div>\\n\t\t\t\t<br />\\n\t\t\t\t<div class=\\\"parameter-content-type\\\" />\\n\";\n},\"9\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers[\"if\"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.isFile : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(2, data, 0),\"inverse\":container.program(10, data, 0),\"data\":data})) != null ? stack1 : \"\");\n},\"10\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = (helpers.renderTextParam || (depth0 && depth0.renderTextParam) || helpers.helperMissing).call(depth0 != null ? depth0 : {},depth0,{\"name\":\"renderTextParam\",\"hash\":{},\"fn\":container.program(11, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\");\n},\"11\":function(container,depth0,helpers,partials,data) {\n    return \"\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<td class='code'><label for='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</label></td>\\n<td>\\n\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isBody : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.program(9, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n</td>\\n<td class=\\\"markdown\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.paramType : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td>\\n\t<span class=\\\"model-signature\\\"></span>\\n</td>\\n\";\n},\"useData\":true});\ntemplates['param_list'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    return \" required\";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    return \" multiple=\\\"multiple\\\"\";\n},\"5\":function(container,depth0,helpers,partials,data) {\n    return \" required \";\n},\"7\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"      <option \"\n    + ((stack1 = helpers.unless.call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.hasDefault : depth0),{\"name\":\"unless\",\"hash\":{},\"fn\":container.program(8, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \" value=''></option>\\n\";\n},\"8\":function(container,depth0,helpers,partials,data) {\n    return \"  selected=\\\"\\\" \";\n},\"10\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"\\n      <option \"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isDefault : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(11, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"  value='\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.value : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'> \"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.value : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \" \"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isDefault : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(13, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \" </option>\\n\\n\";\n},\"11\":function(container,depth0,helpers,partials,data) {\n    return \" selected=\\\"\\\"  \";\n},\"13\":function(container,depth0,helpers,partials,data) {\n    return \" (default) \";\n},\"15\":function(container,depth0,helpers,partials,data) {\n    return \"<strong>\";\n},\"17\":function(container,depth0,helpers,partials,data) {\n    return \"</strong>\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, helper, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<td class='code\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.required : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"'><label for='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'>\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</label></td>\\n<td>\\n  <select \"\n    + ((stack1 = (helpers.isArray || (depth0 && depth0.isArray) || alias2).call(alias1,depth0,{\"name\":\"isArray\",\"hash\":{},\"fn\":container.program(3, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \" class=\\\"parameter \"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.required : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(5, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\" name=\\\"\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\" id=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\\n\\n\"\n    + ((stack1 = helpers.unless.call(alias1,(depth0 != null ? depth0.required : depth0),{\"name\":\"unless\",\"hash\":{},\"fn\":container.program(7, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n\"\n    + ((stack1 = helpers.each.call(alias1,((stack1 = (depth0 != null ? depth0.allowableValues : depth0)) != null ? stack1.descriptiveValues : stack1),{\"name\":\"each\",\"hash\":{},\"fn\":container.program(10, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n  </select>\\n</td>\\n<td class=\\\"markdown\\\">\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.required : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(15, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + ((stack1 = ((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : alias2),(typeof helper === \"function\" ? helper.call(alias1,{\"name\":\"description\",\"hash\":{},\"data\":data}) : helper))) != null ? stack1 : \"\")\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.required : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(17, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.paramType : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td><span class=\\\"model-signature\\\"></span></td>\\n\";\n},\"useData\":true});\ntemplates['param_readonly'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"        <textarea class='body-textarea' readonly='readonly' name='\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' id='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'>\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0[\"default\"] : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</textarea>\\n        <div class=\\\"parameter-content-type\\\" />\\n\";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers[\"if\"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0[\"default\"] : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(4, data, 0),\"inverse\":container.program(6, data, 0),\"data\":data})) != null ? stack1 : \"\");\n},\"4\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"            \"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0[\"default\"] : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n\";\n},\"6\":function(container,depth0,helpers,partials,data) {\n    return \"            (empty)\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<td class='code'><label for='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'>\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</label></td>\\n<td>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isBody : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.program(3, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td class=\\\"markdown\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.paramType : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td><span class=\\\"model-signature\\\"></span></td>\\n\";\n},\"useData\":true});\ntemplates['param_readonly_required'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"        <textarea class='body-textarea' readonly='readonly' placeholder='(required)' name='\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' id='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'>\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0[\"default\"] : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</textarea>\\n\";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers[\"if\"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0[\"default\"] : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(4, data, 0),\"inverse\":container.program(6, data, 0),\"data\":data})) != null ? stack1 : \"\");\n},\"4\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"            \"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0[\"default\"] : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n\";\n},\"6\":function(container,depth0,helpers,partials,data) {\n    return \"            (empty)\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<td class='code required'><label for='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'>\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</label></td>\\n<td>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isBody : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.program(3, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td class=\\\"markdown\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.paramType : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td><span class=\\\"model-signature\\\"></span></td>\\n\";\n},\"useData\":true});\ntemplates['param_required'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers[\"if\"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.isFile : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(2, data, 0),\"inverse\":container.program(4, data, 0),\"data\":data})) != null ? stack1 : \"\");\n},\"2\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"\t\t\t<input type=\\\"file\\\" name='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' id='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'/>\\n\";\n},\"4\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers[\"if\"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0[\"default\"] : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(5, data, 0),\"inverse\":container.program(7, data, 0),\"data\":data})) != null ? stack1 : \"\");\n},\"5\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"\t\t\t\t<div class=\\\"editor_holder\\\"></div>\\n\t\t\t\t<textarea class='body-textarea required' placeholder='(required)' name='\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' id=\\\"\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0[\"default\"] : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</textarea>\\n        <br />\\n        <div class=\\\"parameter-content-type\\\" />\\n\";\n},\"7\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"\t\t\t\t<textarea class='body-textarea required' placeholder='(required)' name='\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' id='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'></textarea>\\n\t\t\t\t<div class=\\\"editor_holder\\\"></div>\\n\t\t\t\t<br />\\n\t\t\t\t<div class=\\\"parameter-content-type\\\" />\\n\";\n},\"9\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers[\"if\"].call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.isFile : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(10, data, 0),\"inverse\":container.program(12, data, 0),\"data\":data})) != null ? stack1 : \"\");\n},\"10\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"\t\t\t<input class='parameter required' type='file' name='\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' id='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'/>\\n\";\n},\"12\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = (helpers.renderTextParam || (depth0 && depth0.renderTextParam) || helpers.helperMissing).call(depth0 != null ? depth0 : {},depth0,{\"name\":\"renderTextParam\",\"hash\":{},\"fn\":container.program(13, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\");\n},\"13\":function(container,depth0,helpers,partials,data) {\n    return \"\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<td class='code required'><label for='\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.valueId : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"'>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</label></td>\\n<td>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isBody : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.program(9, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td>\\n\t<strong><span class=\\\"markdown\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</span></strong>\\n</td>\\n<td>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.paramType : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td><span class=\\\"model-signature\\\"></span></td>\\n\";\n},\"useData\":true});\ntemplates['parameter_content_type'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers.each.call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.consumes : depth0),{\"name\":\"each\",\"hash\":{},\"fn\":container.program(2, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\");\n},\"2\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"  <option value=\\\"\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,depth0,{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,depth0,{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</option>\\n\";\n},\"4\":function(container,depth0,helpers,partials,data) {\n    return \"  <option value=\\\"application/json\\\">application/json</option>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, helper, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<label for=\\\"\"\n    + container.escapeExpression(((helper = (helper = helpers.parameterContentTypeId || (depth0 != null ? depth0.parameterContentTypeId : depth0)) != null ? helper : alias2),(typeof helper === \"function\" ? helper.call(alias1,{\"name\":\"parameterContentTypeId\",\"hash\":{},\"data\":data}) : helper)))\n    + \"\\\" data-sw-translate>Parameter content type:</label>\\n<select name=\\\"parameterContentType\\\" id=\\\"\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.parameterContentTypeId : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.consumes : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.program(4, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"</select>\\n\";\n},\"useData\":true});\ntemplates['popup'] = template({\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var helper;\n\n  return \"<div class=\\\"api-popup-dialog-wrapper\\\">\\n    <div class=\\\"api-popup-title\\\">\"\n    + container.escapeExpression(((helper = (helper = helpers.title || (depth0 != null ? depth0.title : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === \"function\" ? helper.call(depth0 != null ? depth0 : {},{\"name\":\"title\",\"hash\":{},\"data\":data}) : helper)))\n    + \"</div>\\n    <div class=\\\"api-popup-content\\\"></div>\\n    <p class=\\\"error-msg\\\"></p>\\n    <div class=\\\"api-popup-actions\\\">\\n        <button class=\\\"api-popup-cancel api-button gray\\\" type=\\\"button\\\">Cancel</button>\\n    </div>\\n</div>\\n<div class=\\\"api-popup-dialog-shadow\\\"></div>\";\n},\"useData\":true});\ntemplates['resource'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    return \" : \";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"    <li>\\n      <a href='\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.url : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' data-sw-translate>Raw</a>\\n    </li>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, helper, options, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, buffer =\n  \"<div class='heading'>\\n  <h2>\\n    <a href='#!/\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.id : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' class=\\\"toggleEndpointList\\\" data-id=\\\"\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.id : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.name : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</a> \";\n  stack1 = ((helper = (helper = helpers.summary || (depth0 != null ? depth0.summary : depth0)) != null ? helper : alias2),(options={\"name\":\"summary\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.noop,\"data\":data}),(typeof helper === \"function\" ? helper.call(alias1,options) : helper));\n  if (!helpers.summary) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}\n  if (stack1 != null) { buffer += stack1; }\n  return buffer + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.summary : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n  </h2>\\n  <ul class='options'>\\n    <li>\\n      <a href='#!/\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.id : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' id='endpointListTogger_\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.id : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"' class=\\\"toggleEndpointList\\\" data-id=\\\"\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.id : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\" data-sw-translate>Show/Hide</a>\\n    </li>\\n    <li>\\n      <a href='#' class=\\\"collapseResource\\\" data-id=\\\"\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.id : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\" data-sw-translate>\\n        List Operations\\n      </a>\\n    </li>\\n    <li>\\n      <a href='#' class=\\\"expandResource\\\" data-id=\\\"\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.id : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\" data-sw-translate>\\n        Expand Operations\\n      </a>\\n    </li>\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.url : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(3, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"  </ul>\\n</div>\\n<ul class='endpoints' id='\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.id : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"_endpoint_list' style='display:none'>\\n\\n</ul>\\n\";\n},\"useData\":true});\ntemplates['response_content_type'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = helpers.each.call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.produces : depth0),{\"name\":\"each\",\"hash\":{},\"fn\":container.program(2, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\");\n},\"2\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"  <option value=\\\"\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,depth0,{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\\">\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,depth0,{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</option>\\n\";\n},\"4\":function(container,depth0,helpers,partials,data) {\n    return \"  <option value=\\\"application/json\\\">application/json</option>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, helper, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing, alias3=\"function\", alias4=container.escapeExpression;\n\n  return \"<label data-sw-translate for=\\\"\"\n    + alias4(((helper = (helper = helpers.responseContentTypeId || (depth0 != null ? depth0.responseContentTypeId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{\"name\":\"responseContentTypeId\",\"hash\":{},\"data\":data}) : helper)))\n    + \"\\\">Response Content Type</label>\\n<select name=\\\"responseContentType\\\" id=\\\"\"\n    + alias4(((helper = (helper = helpers.responseContentTypeId || (depth0 != null ? depth0.responseContentTypeId : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{\"name\":\"responseContentTypeId\",\"hash\":{},\"data\":data}) : helper)))\n    + \"\\\">\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.produces : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.program(4, data, 0),\"data\":data})) != null ? stack1 : \"\")\n    + \"</select>\\n\";\n},\"useData\":true});\ntemplates['signature'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {};\n\n  return \"\\n<div>\\n<ul class=\\\"signature-nav\\\">\\n  <li><a class=\\\"description-link\\\" href=\\\"#\\\" data-sw-translate>Model</a></li>\\n  <li><a class=\\\"snippet-link\\\" href=\\\"#\\\" data-sw-translate>Example Value</a></li>\\n</ul>\\n<div>\\n\\n<div class=\\\"signature-container\\\">\\n  <div class=\\\"description\\\">\\n      \"\n    + container.escapeExpression((helpers.sanitize || (depth0 && depth0.sanitize) || helpers.helperMissing).call(alias1,(depth0 != null ? depth0.signature : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data}))\n    + \"\\n  </div>\\n\\n  <div class=\\\"snippet\\\">\\n\"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.sampleJSON : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(2, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.sampleXML : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(5, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"  </div>\\n</div>\\n\";\n},\"2\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {};\n\n  return \"      <div class=\\\"snippet_json\\\">\\n        <pre><code>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || helpers.helperMissing).call(alias1,(depth0 != null ? depth0.sampleJSON : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</code></pre>\\n        \"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isParam : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(3, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n      </div>\\n\";\n},\"3\":function(container,depth0,helpers,partials,data) {\n    return \"<small class=\\\"notice\\\" data-sw-translate></small>\";\n},\"5\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {};\n\n  return \"    <div class=\\\"snippet_xml\\\">\\n      <pre><code>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || helpers.helperMissing).call(alias1,(depth0 != null ? depth0.sampleXML : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</code></pre>\\n      \"\n    + ((stack1 = helpers[\"if\"].call(alias1,(depth0 != null ? depth0.isParam : depth0),{\"name\":\"if\",\"hash\":{},\"fn\":container.program(3, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n    </div>\\n\";\n},\"7\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return \"    \"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.signature : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1;\n\n  return ((stack1 = (helpers.ifCond || (depth0 && depth0.ifCond) || helpers.helperMissing).call(depth0 != null ? depth0 : {},(depth0 != null ? depth0.sampleJSON : depth0),\"||\",(depth0 != null ? depth0.sampleXML : depth0),{\"name\":\"ifCond\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.program(7, data, 0),\"data\":data})) != null ? stack1 : \"\");\n},\"useData\":true});\ntemplates['status_code'] = template({\"1\":function(container,depth0,helpers,partials,data) {\n    var stack1, helper, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"      <tr>\\n        <td>\"\n    + container.escapeExpression(((helper = (helper = helpers.key || (data && data.key)) != null ? helper : alias2),(typeof helper === \"function\" ? helper.call(alias1,{\"name\":\"key\",\"hash\":{},\"data\":data}) : helper)))\n    + \"</td>\\n        <td>\"\n    + ((stack1 = (helpers.sanitize || (depth0 && depth0.sanitize) || alias2).call(alias1,(depth0 != null ? depth0.description : depth0),{\"name\":\"sanitize\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n        <td>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.type : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n      </tr>\\n\";\n},\"compiler\":[7,\">= 4.0.0\"],\"main\":function(container,depth0,helpers,partials,data) {\n    var stack1, alias1=depth0 != null ? depth0 : {}, alias2=helpers.helperMissing;\n\n  return \"<td width='15%' class='code'>\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.code : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td class=\\\"markdown\\\">\"\n    + ((stack1 = (helpers.escape || (depth0 && depth0.escape) || alias2).call(alias1,(depth0 != null ? depth0.message : depth0),{\"name\":\"escape\",\"hash\":{},\"data\":data})) != null ? stack1 : \"\")\n    + \"</td>\\n<td width='50%'><span class=\\\"model-signature\\\" /></td>\\n<td class=\\\"headers\\\">\\n  <table>\\n    <tbody>\\n\"\n    + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.headers : depth0),{\"name\":\"each\",\"hash\":{},\"fn\":container.program(1, data, 0),\"inverse\":container.noop,\"data\":data})) != null ? stack1 : \"\")\n    + \"    </tbody>\\n  </table>\\n</td>\";\n},\"useData\":true});\n})();}\n /* jshint ignore:end */\n'use strict';\n\n\n$(function() {\n\n\t// Helper function for vertically aligning DOM elements\n\t// http://www.seodenver.com/simple-vertical-align-plugin-for-jquery/\n\t$.fn.vAlign = function() {\n\t\treturn this.each(function(){\n\t\t\tvar ah = $(this).height();\n\t\t\tvar ph = $(this).parent().height();\n\t\t\tvar mh = (ph - ah) / 2;\n\t\t\t$(this).css('margin-top', mh);\n\t\t});\n\t};\n\n\t$.fn.stretchFormtasticInputWidthToParent = function() {\n\t\treturn this.each(function(){\n\t\t\tvar p_width = $(this).closest(\"form\").innerWidth();\n\t\t\tvar p_padding = parseInt($(this).closest(\"form\").css('padding-left') ,10) + parseInt($(this).closest('form').css('padding-right'), 10);\n\t\t\tvar this_padding = parseInt($(this).css('padding-left'), 10) + parseInt($(this).css('padding-right'), 10);\n\t\t\t$(this).css('width', p_width - p_padding - this_padding);\n\t\t});\n\t};\n\n\t$('form.formtastic li.string input, form.formtastic textarea').stretchFormtasticInputWidthToParent();\n\n\t// Vertically center these paragraphs\n\t// Parent may need a min-height for this to work..\n\t$('ul.downplayed li div.content p').vAlign();\n\n\t// When a sandbox form is submitted..\n\t$(\"form.sandbox\").submit(function(){\n\n\t\tvar error_free = true;\n\n\t\t// Cycle through the forms required inputs\n \t\t$(this).find(\"input.required\").each(function() {\n\n\t\t\t// Remove any existing error styles from the input\n\t\t\t$(this).removeClass('error');\n\n\t\t\t// Tack the error style on if the input is empty..\n\t\t\tif ($(this).val() === '') {\n\t\t\t\t$(this).addClass('error');\n\t\t\t\t$(this).wiggle();\n\t\t\t\terror_free = false;\n\t\t\t}\n\n\t\t});\n\n\t\treturn error_free;\n\t});\n\n});\n\nfunction clippyCopiedCallback() {\n  $('#api_key_copied').fadeIn().delay(1000).fadeOut();\n\n  // var b = $(\"#clippy_tooltip_\" + a);\n  // b.length != 0 && (b.attr(\"title\", \"copied!\").trigger(\"tipsy.reload\"), setTimeout(function() {\n  //   b.attr(\"title\", \"copy to clipboard\")\n  // },\n  // 500))\n}\n\n// Logging function that accounts for browsers that don't have window.console\nfunction log(){\n  log.history = log.history || [];\n  log.history.push(arguments);\n  if(this.console){\n    console.log( Array.prototype.slice.call(arguments)[0] );\n  }\n}\n\n// Handle browsers that do console incorrectly (IE9 and below, see http://stackoverflow.com/a/5539378/7913)\nif (Function.prototype.bind && console && typeof console.log === \"object\") {\n    [\n      \"log\",\"info\",\"warn\",\"error\",\"assert\",\"dir\",\"clear\",\"profile\",\"profileEnd\"\n    ].forEach(function (method) {\n        console[method] = this.bind(console[method], console);\n    }, Function.prototype.call);\n}\n\nwindow.Docs = {\n\n\tshebang: function() {\n\n\t\t// If shebang has an operation nickname in it..\n\t\t// e.g. /docs/#!/words/get_search\n\t\tvar fragments = $.param.fragment().split('/');\n\t\tfragments.shift(); // get rid of the bang\n\n\t\tswitch (fragments.length) {\n\t\t\tcase 1:\n        if (fragments[0].length > 0) { // prevent matching \"#/\"\n          // Expand all operations for the resource and scroll to it\n          var dom_id = 'resource_' + fragments[0];\n\n          Docs.expandEndpointListForResource(fragments[0]);\n          $(\"#\"+dom_id).slideto({highlight: false});\n        }\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\t// Refer to the endpoint DOM element, e.g. #words_get_search\n\n        // Expand Resource\n        Docs.expandEndpointListForResource(fragments[0]);\n        $(\"#\"+dom_id).slideto({highlight: false});\n\n            // Expand operation\n            var li_dom_id = fragments.join('_');\n            var li_content_dom_id = li_dom_id + \"_content\";\n\n\n            Docs.expandOperation($('#'+li_content_dom_id));\n            $('#'+li_dom_id).slideto({highlight: false});\n            break;\n\t\t}\n\t},\n\n\ttoggleEndpointListForResource: function(resource) {\n\t\tvar elem = $('li#resource_' + Docs.escapeResourceName(resource) + ' ul.endpoints');\n\t\tif (elem.is(':visible')) {\n\t\t\t$.bbq.pushState('#/', 2);\n\t\t\tDocs.collapseEndpointListForResource(resource);\n\t\t} else {\n            $.bbq.pushState('#/' + resource, 2);\n\t\t\tDocs.expandEndpointListForResource(resource);\n\t\t}\n\t},\n\n\t// Expand resource\n\texpandEndpointListForResource: function(resource) {\n\t\tvar resource = Docs.escapeResourceName(resource);\n\t\tif (resource == '') {\n\t\t\t$('.resource ul.endpoints').slideDown();\n\t\t\treturn;\n\t\t}\n\n\t\t$('li#resource_' + resource).addClass('active');\n\n\t\tvar elem = $('li#resource_' + resource + ' ul.endpoints');\n\t\telem.slideDown();\n\t},\n\n\t// Collapse resource and mark as explicitly closed\n\tcollapseEndpointListForResource: function(resource) {\n\t\tvar resource = Docs.escapeResourceName(resource);\n\t\tif (resource == '') {\n\t\t\t$('.resource ul.endpoints').slideUp();\n\t\t\treturn;\n\t\t}\n\n\t\t$('li#resource_' + resource).removeClass('active');\n\n\t\tvar elem = $('li#resource_' + resource + ' ul.endpoints');\n\t\telem.slideUp();\n\t},\n\n\texpandOperationsForResource: function(resource) {\n\t\t// Make sure the resource container is open..\n\t\tDocs.expandEndpointListForResource(resource);\n\n\t\tif (resource == '') {\n\t\t\t$('.resource ul.endpoints li.operation div.content').slideDown();\n\t\t\treturn;\n\t\t}\n\n\t\t$('li#resource_' + Docs.escapeResourceName(resource) + ' li.operation div.content').each(function() {\n\t\t\tDocs.expandOperation($(this));\n\t\t});\n\t},\n\n\tcollapseOperationsForResource: function(resource) {\n\t\t// Make sure the resource container is open..\n\t\tDocs.expandEndpointListForResource(resource);\n\n\t\tif (resource == '') {\n\t\t\t$('.resource ul.endpoints li.operation div.content').slideUp();\n\t\t\treturn;\n\t\t}\n\n\t\t$('li#resource_' + Docs.escapeResourceName(resource) + ' li.operation div.content').each(function() {\n\t\t\tDocs.collapseOperation($(this));\n\t\t});\n\t},\n\n\tescapeResourceName: function(resource) {\n\t\treturn resource.replace(/[!\"#$%&'()*+,.\\/:;<=>?@\\[\\\\\\]\\^`{|}~]/g, \"\\\\$&\");\n\t},\n\n\texpandOperation: function(elem) {\n\t\telem.slideDown();\n\t},\n\n\tcollapseOperation: function(elem) {\n\t\telem.slideUp();\n\t}\n};\n\n/*!\n * https://github.com/es-shims/es5-shim\n * @license es5-shim Copyright 2009-2015 by contributors, MIT License\n * see https://github.com/es-shims/es5-shim/blob/master/LICENSE\n */\n\n// vim: ts=4 sts=4 sw=4 expandtab\n\n// Add semicolon to prevent IIFE from being passed as argument to concatenated code.\n;\n\n// UMD (Universal Module Definition)\n// see https://github.com/umdjs/umd/blob/master/templates/returnExports.js\n(function (root, factory) {\n    'use strict';\n\n    /* global define, exports, module */\n    if (typeof define === 'function' && define.amd) {\n        // AMD. Register as an anonymous module.\n        define(factory);\n    } else if (typeof exports === 'object') {\n        // Node. Does not work with strict CommonJS, but\n        // only CommonJS-like enviroments that support module.exports,\n        // like Node.\n        module.exports = factory();\n    } else {\n        // Browser globals (root is window)\n        root.returnExports = factory();\n    }\n}(this, function () {\n    /**\n     * Brings an environment as close to ECMAScript 5 compliance\n     * as is possible with the facilities of erstwhile engines.\n     *\n     * Annotated ES5: http://es5.github.com/ (specific links below)\n     * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf\n     * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/\n     */\n\n    // Shortcut to an often accessed properties, in order to avoid multiple\n    // dereference that costs universally. This also holds a reference to known-good\n    // functions.\n    var $Array = Array;\n    var ArrayPrototype = $Array.prototype;\n    var $Object = Object;\n    var ObjectPrototype = $Object.prototype;\n    var $Function = Function;\n    var FunctionPrototype = $Function.prototype;\n    var $String = String;\n    var StringPrototype = $String.prototype;\n    var $Number = Number;\n    var NumberPrototype = $Number.prototype;\n    var array_slice = ArrayPrototype.slice;\n    var array_splice = ArrayPrototype.splice;\n    var array_push = ArrayPrototype.push;\n    var array_unshift = ArrayPrototype.unshift;\n    var array_concat = ArrayPrototype.concat;\n    var array_join = ArrayPrototype.join;\n    var call = FunctionPrototype.call;\n    var apply = FunctionPrototype.apply;\n    var max = Math.max;\n    var min = Math.min;\n\n    // Having a toString local variable name breaks in Opera so use to_string.\n    var to_string = ObjectPrototype.toString;\n\n    /* global Symbol */\n    /* eslint-disable one-var-declaration-per-line, no-redeclare, max-statements-per-line */\n    var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';\n    var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, constructorRegex = /^\\s*class /, isES6ClassFn = function isES6ClassFn(value) { try { var fnStr = fnToStr.call(value); var singleStripped = fnStr.replace(/\\/\\/.*\\n/g, ''); var multiStripped = singleStripped.replace(/\\/\\*[.\\s\\S]*\\*\\//g, ''); var spaceStripped = multiStripped.replace(/\\n/mg, ' ').replace(/ {2}/g, ' '); return constructorRegex.test(spaceStripped); } catch (e) { return false; /* not a function */ } }, tryFunctionObject = function tryFunctionObject(value) { try { if (isES6ClassFn(value)) { return false; } fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]', isCallable = function isCallable(value) { if (!value) { return false; } if (typeof value !== 'function' && typeof value !== 'object') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } if (isES6ClassFn(value)) { return false; } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; };\n\n    var isRegex; /* inlined from https://npmjs.com/is-regex */ var regexExec = RegExp.prototype.exec, tryRegexExec = function tryRegexExec(value) { try { regexExec.call(value); return true; } catch (e) { return false; } }, regexClass = '[object RegExp]'; isRegex = function isRegex(value) { if (typeof value !== 'object') { return false; } return hasToStringTag ? tryRegexExec(value) : to_string.call(value) === regexClass; };\n    var isString; /* inlined from https://npmjs.com/is-string */ var strValue = String.prototype.valueOf, tryStringObject = function tryStringObject(value) { try { strValue.call(value); return true; } catch (e) { return false; } }, stringClass = '[object String]'; isString = function isString(value) { if (typeof value === 'string') { return true; } if (typeof value !== 'object') { return false; } return hasToStringTag ? tryStringObject(value) : to_string.call(value) === stringClass; };\n    /* eslint-enable one-var-declaration-per-line, no-redeclare, max-statements-per-line */\n\n    /* inlined from http://npmjs.com/define-properties */\n    var supportsDescriptors = $Object.defineProperty && (function () {\n        try {\n            var obj = {};\n            $Object.defineProperty(obj, 'x', { enumerable: false, value: obj });\n            for (var _ in obj) { // jscs:ignore disallowUnusedVariables\n                return false;\n            }\n            return obj.x === obj;\n        } catch (e) { /* this is ES3 */\n            return false;\n        }\n    }());\n    var defineProperties = (function (has) {\n        // Define configurable, writable, and non-enumerable props\n        // if they don't exist.\n        var defineProperty;\n        if (supportsDescriptors) {\n            defineProperty = function (object, name, method, forceAssign) {\n                if (!forceAssign && (name in object)) {\n                    return;\n                }\n                $Object.defineProperty(object, name, {\n                    configurable: true,\n                    enumerable: false,\n                    writable: true,\n                    value: method\n                });\n            };\n        } else {\n            defineProperty = function (object, name, method, forceAssign) {\n                if (!forceAssign && (name in object)) {\n                    return;\n                }\n                object[name] = method;\n            };\n        }\n        return function defineProperties(object, map, forceAssign) {\n            for (var name in map) {\n                if (has.call(map, name)) {\n                    defineProperty(object, name, map[name], forceAssign);\n                }\n            }\n        };\n    }(ObjectPrototype.hasOwnProperty));\n\n    //\n    // Util\n    // ======\n    //\n\n    /* replaceable with https://npmjs.com/package/es-abstract /helpers/isPrimitive */\n    var isPrimitive = function isPrimitive(input) {\n        var type = typeof input;\n        return input === null || (type !== 'object' && type !== 'function');\n    };\n\n    var isActualNaN = $Number.isNaN || function isActualNaN(x) {\n        return x !== x;\n    };\n\n    var ES = {\n        // ES5 9.4\n        // http://es5.github.com/#x9.4\n        // http://jsperf.com/to-integer\n        /* replaceable with https://npmjs.com/package/es-abstract ES5.ToInteger */\n        ToInteger: function ToInteger(num) {\n            var n = +num;\n            if (isActualNaN(n)) {\n                n = 0;\n            } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {\n                n = (n > 0 || -1) * Math.floor(Math.abs(n));\n            }\n            return n;\n        },\n\n        /* replaceable with https://npmjs.com/package/es-abstract ES5.ToPrimitive */\n        ToPrimitive: function ToPrimitive(input) {\n            var val, valueOf, toStr;\n            if (isPrimitive(input)) {\n                return input;\n            }\n            valueOf = input.valueOf;\n            if (isCallable(valueOf)) {\n                val = valueOf.call(input);\n                if (isPrimitive(val)) {\n                    return val;\n                }\n            }\n            toStr = input.toString;\n            if (isCallable(toStr)) {\n                val = toStr.call(input);\n                if (isPrimitive(val)) {\n                    return val;\n                }\n            }\n            throw new TypeError();\n        },\n\n        // ES5 9.9\n        // http://es5.github.com/#x9.9\n        /* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */\n        ToObject: function (o) {\n            if (o == null) { // this matches both null and undefined\n                throw new TypeError(\"can't convert \" + o + ' to object');\n            }\n            return $Object(o);\n        },\n\n        /* replaceable with https://npmjs.com/package/es-abstract ES5.ToUint32 */\n        ToUint32: function ToUint32(x) {\n            return x >>> 0;\n        }\n    };\n\n    //\n    // Function\n    // ========\n    //\n\n    // ES-5 15.3.4.5\n    // http://es5.github.com/#x15.3.4.5\n\n    var Empty = function Empty() {};\n\n    defineProperties(FunctionPrototype, {\n        bind: function bind(that) { // .length is 1\n            // 1. Let Target be the this value.\n            var target = this;\n            // 2. If IsCallable(Target) is false, throw a TypeError exception.\n            if (!isCallable(target)) {\n                throw new TypeError('Function.prototype.bind called on incompatible ' + target);\n            }\n            // 3. Let A be a new (possibly empty) internal list of all of the\n            //   argument values provided after thisArg (arg1, arg2 etc), in order.\n            // XXX slicedArgs will stand in for \"A\" if used\n            var args = array_slice.call(arguments, 1); // for normal call\n            // 4. Let F be a new native ECMAScript object.\n            // 11. Set the [[Prototype]] internal property of F to the standard\n            //   built-in Function prototype object as specified in 15.3.3.1.\n            // 12. Set the [[Call]] internal property of F as described in\n            //   15.3.4.5.1.\n            // 13. Set the [[Construct]] internal property of F as described in\n            //   15.3.4.5.2.\n            // 14. Set the [[HasInstance]] internal property of F as described in\n            //   15.3.4.5.3.\n            var bound;\n            var binder = function () {\n\n                if (this instanceof bound) {\n                    // 15.3.4.5.2 [[Construct]]\n                    // When the [[Construct]] internal method of a function object,\n                    // F that was created using the bind function is called with a\n                    // list of arguments ExtraArgs, the following steps are taken:\n                    // 1. Let target be the value of F's [[TargetFunction]]\n                    //   internal property.\n                    // 2. If target has no [[Construct]] internal method, a\n                    //   TypeError exception is thrown.\n                    // 3. Let boundArgs be the value of F's [[BoundArgs]] internal\n                    //   property.\n                    // 4. Let args be a new list containing the same values as the\n                    //   list boundArgs in the same order followed by the same\n                    //   values as the list ExtraArgs in the same order.\n                    // 5. Return the result of calling the [[Construct]] internal\n                    //   method of target providing args as the arguments.\n\n                    var result = apply.call(\n                        target,\n                        this,\n                        array_concat.call(args, array_slice.call(arguments))\n                    );\n                    if ($Object(result) === result) {\n                        return result;\n                    }\n                    return this;\n\n                } else {\n                    // 15.3.4.5.1 [[Call]]\n                    // When the [[Call]] internal method of a function object, F,\n                    // which was created using the bind function is called with a\n                    // this value and a list of arguments ExtraArgs, the following\n                    // steps are taken:\n                    // 1. Let boundArgs be the value of F's [[BoundArgs]] internal\n                    //   property.\n                    // 2. Let boundThis be the value of F's [[BoundThis]] internal\n                    //   property.\n                    // 3. Let target be the value of F's [[TargetFunction]] internal\n                    //   property.\n                    // 4. Let args be a new list containing the same values as the\n                    //   list boundArgs in the same order followed by the same\n                    //   values as the list ExtraArgs in the same order.\n                    // 5. Return the result of calling the [[Call]] internal method\n                    //   of target providing boundThis as the this value and\n                    //   providing args as the arguments.\n\n                    // equiv: target.call(this, ...boundArgs, ...args)\n                    return apply.call(\n                        target,\n                        that,\n                        array_concat.call(args, array_slice.call(arguments))\n                    );\n\n                }\n\n            };\n\n            // 15. If the [[Class]] internal property of Target is \"Function\", then\n            //     a. Let L be the length property of Target minus the length of A.\n            //     b. Set the length own property of F to either 0 or L, whichever is\n            //       larger.\n            // 16. Else set the length own property of F to 0.\n\n            var boundLength = max(0, target.length - args.length);\n\n            // 17. Set the attributes of the length own property of F to the values\n            //   specified in 15.3.5.1.\n            var boundArgs = [];\n            for (var i = 0; i < boundLength; i++) {\n                array_push.call(boundArgs, '$' + i);\n            }\n\n            // XXX Build a dynamic function with desired amount of arguments is the only\n            // way to set the length property of a function.\n            // In environments where Content Security Policies enabled (Chrome extensions,\n            // for ex.) all use of eval or Function costructor throws an exception.\n            // However in all of these environments Function.prototype.bind exists\n            // and so this code will never be executed.\n            bound = $Function('binder', 'return function (' + array_join.call(boundArgs, ',') + '){ return binder.apply(this, arguments); }')(binder);\n\n            if (target.prototype) {\n                Empty.prototype = target.prototype;\n                bound.prototype = new Empty();\n                // Clean up dangling references.\n                Empty.prototype = null;\n            }\n\n            // TODO\n            // 18. Set the [[Extensible]] internal property of F to true.\n\n            // TODO\n            // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).\n            // 20. Call the [[DefineOwnProperty]] internal method of F with\n            //   arguments \"caller\", PropertyDescriptor {[[Get]]: thrower, [[Set]]:\n            //   thrower, [[Enumerable]]: false, [[Configurable]]: false}, and\n            //   false.\n            // 21. Call the [[DefineOwnProperty]] internal method of F with\n            //   arguments \"arguments\", PropertyDescriptor {[[Get]]: thrower,\n            //   [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},\n            //   and false.\n\n            // TODO\n            // NOTE Function objects created using Function.prototype.bind do not\n            // have a prototype property or the [[Code]], [[FormalParameters]], and\n            // [[Scope]] internal properties.\n            // XXX can't delete prototype in pure-js.\n\n            // 22. Return F.\n            return bound;\n        }\n    });\n\n    // _Please note: Shortcuts are defined after `Function.prototype.bind` as we\n    // use it in defining shortcuts.\n    var owns = call.bind(ObjectPrototype.hasOwnProperty);\n    var toStr = call.bind(ObjectPrototype.toString);\n    var arraySlice = call.bind(array_slice);\n    var arraySliceApply = apply.bind(array_slice);\n    var strSlice = call.bind(StringPrototype.slice);\n    var strSplit = call.bind(StringPrototype.split);\n    var strIndexOf = call.bind(StringPrototype.indexOf);\n    var pushCall = call.bind(array_push);\n    var isEnum = call.bind(ObjectPrototype.propertyIsEnumerable);\n    var arraySort = call.bind(ArrayPrototype.sort);\n\n    //\n    // Array\n    // =====\n    //\n\n    var isArray = $Array.isArray || function isArray(obj) {\n        return toStr(obj) === '[object Array]';\n    };\n\n    // ES5 15.4.4.12\n    // http://es5.github.com/#x15.4.4.13\n    // Return len+argCount.\n    // [bugfix, ielt8]\n    // IE < 8 bug: [].unshift(0) === undefined but should be \"1\"\n    var hasUnshiftReturnValueBug = [].unshift(0) !== 1;\n    defineProperties(ArrayPrototype, {\n        unshift: function () {\n            array_unshift.apply(this, arguments);\n            return this.length;\n        }\n    }, hasUnshiftReturnValueBug);\n\n    // ES5 15.4.3.2\n    // http://es5.github.com/#x15.4.3.2\n    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray\n    defineProperties($Array, { isArray: isArray });\n\n    // The IsCallable() check in the Array functions\n    // has been replaced with a strict check on the\n    // internal class of the object to trap cases where\n    // the provided function was actually a regular\n    // expression literal, which in V8 and\n    // JavaScriptCore is a typeof \"function\".  Only in\n    // V8 are regular expression literals permitted as\n    // reduce parameters, so it is desirable in the\n    // general case for the shim to match the more\n    // strict and common behavior of rejecting regular\n    // expressions.\n\n    // ES5 15.4.4.18\n    // http://es5.github.com/#x15.4.4.18\n    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach\n\n    // Check failure of by-index access of string characters (IE < 9)\n    // and failure of `0 in boxedString` (Rhino)\n    var boxedString = $Object('a');\n    var splitString = boxedString[0] !== 'a' || !(0 in boxedString);\n\n    var properlyBoxesContext = function properlyBoxed(method) {\n        // Check node 0.6.21 bug where third parameter is not boxed\n        var properlyBoxesNonStrict = true;\n        var properlyBoxesStrict = true;\n        var threwException = false;\n        if (method) {\n            try {\n                method.call('foo', function (_, __, context) {\n                    if (typeof context !== 'object') {\n                        properlyBoxesNonStrict = false;\n                    }\n                });\n\n                method.call([1], function () {\n                    'use strict';\n\n                    properlyBoxesStrict = typeof this === 'string';\n                }, 'x');\n            } catch (e) {\n                threwException = true;\n            }\n        }\n        return !!method && !threwException && properlyBoxesNonStrict && properlyBoxesStrict;\n    };\n\n    defineProperties(ArrayPrototype, {\n        forEach: function forEach(callbackfn/*, thisArg*/) {\n            var object = ES.ToObject(this);\n            var self = splitString && isString(this) ? strSplit(this, '') : object;\n            var i = -1;\n            var length = ES.ToUint32(self.length);\n            var T;\n            if (arguments.length > 1) {\n                T = arguments[1];\n            }\n\n            // If no callback function or if callback is not a callable function\n            if (!isCallable(callbackfn)) {\n                throw new TypeError('Array.prototype.forEach callback must be a function');\n            }\n\n            while (++i < length) {\n                if (i in self) {\n                    // Invoke the callback function with call, passing arguments:\n                    // context, property value, property key, thisArg object\n                    if (typeof T === 'undefined') {\n                        callbackfn(self[i], i, object);\n                    } else {\n                        callbackfn.call(T, self[i], i, object);\n                    }\n                }\n            }\n        }\n    }, !properlyBoxesContext(ArrayPrototype.forEach));\n\n    // ES5 15.4.4.19\n    // http://es5.github.com/#x15.4.4.19\n    // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map\n    defineProperties(ArrayPrototype, {\n        map: function map(callbackfn/*, thisArg*/) {\n            var object = ES.ToObject(this);\n            var self = splitString && isString(this) ? strSplit(this, '') : object;\n            var length = ES.ToUint32(self.length);\n            var result = $Array(length);\n            var T;\n            if (arguments.length > 1) {\n                T = arguments[1];\n            }\n\n            // If no callback function or if callback is not a callable function\n            if (!isCallable(callbackfn)) {\n                throw new TypeError('Array.prototype.map callback must be a function');\n            }\n\n            for (var i = 0; i < length; i++) {\n                if (i in self) {\n                    if (typeof T === 'undefined') {\n                        result[i] = callbackfn(self[i], i, object);\n                    } else {\n                        result[i] = callbackfn.call(T, self[i], i, object);\n                    }\n                }\n            }\n            return result;\n        }\n    }, !properlyBoxesContext(ArrayPrototype.map));\n\n    // ES5 15.4.4.20\n    // http://es5.github.com/#x15.4.4.20\n    // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter\n    defineProperties(ArrayPrototype, {\n        filter: function filter(callbackfn/*, thisArg*/) {\n            var object = ES.ToObject(this);\n            var self = splitString && isString(this) ? strSplit(this, '') : object;\n            var length = ES.ToUint32(self.length);\n            var result = [];\n            var value;\n            var T;\n            if (arguments.length > 1) {\n                T = arguments[1];\n            }\n\n            // If no callback function or if callback is not a callable function\n            if (!isCallable(callbackfn)) {\n                throw new TypeError('Array.prototype.filter callback must be a function');\n            }\n\n            for (var i = 0; i < length; i++) {\n                if (i in self) {\n                    value = self[i];\n                    if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) {\n                        pushCall(result, value);\n                    }\n                }\n            }\n            return result;\n        }\n    }, !properlyBoxesContext(ArrayPrototype.filter));\n\n    // ES5 15.4.4.16\n    // http://es5.github.com/#x15.4.4.16\n    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every\n    defineProperties(ArrayPrototype, {\n        every: function every(callbackfn/*, thisArg*/) {\n            var object = ES.ToObject(this);\n            var self = splitString && isString(this) ? strSplit(this, '') : object;\n            var length = ES.ToUint32(self.length);\n            var T;\n            if (arguments.length > 1) {\n                T = arguments[1];\n            }\n\n            // If no callback function or if callback is not a callable function\n            if (!isCallable(callbackfn)) {\n                throw new TypeError('Array.prototype.every callback must be a function');\n            }\n\n            for (var i = 0; i < length; i++) {\n                if (i in self && !(typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {\n                    return false;\n                }\n            }\n            return true;\n        }\n    }, !properlyBoxesContext(ArrayPrototype.every));\n\n    // ES5 15.4.4.17\n    // http://es5.github.com/#x15.4.4.17\n    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some\n    defineProperties(ArrayPrototype, {\n        some: function some(callbackfn/*, thisArg */) {\n            var object = ES.ToObject(this);\n            var self = splitString && isString(this) ? strSplit(this, '') : object;\n            var length = ES.ToUint32(self.length);\n            var T;\n            if (arguments.length > 1) {\n                T = arguments[1];\n            }\n\n            // If no callback function or if callback is not a callable function\n            if (!isCallable(callbackfn)) {\n                throw new TypeError('Array.prototype.some callback must be a function');\n            }\n\n            for (var i = 0; i < length; i++) {\n                if (i in self && (typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {\n                    return true;\n                }\n            }\n            return false;\n        }\n    }, !properlyBoxesContext(ArrayPrototype.some));\n\n    // ES5 15.4.4.21\n    // http://es5.github.com/#x15.4.4.21\n    // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce\n    var reduceCoercesToObject = false;\n    if (ArrayPrototype.reduce) {\n        reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) {\n            return list;\n        }) === 'object';\n    }\n    defineProperties(ArrayPrototype, {\n        reduce: function reduce(callbackfn/*, initialValue*/) {\n            var object = ES.ToObject(this);\n            var self = splitString && isString(this) ? strSplit(this, '') : object;\n            var length = ES.ToUint32(self.length);\n\n            // If no callback function or if callback is not a callable function\n            if (!isCallable(callbackfn)) {\n                throw new TypeError('Array.prototype.reduce callback must be a function');\n            }\n\n            // no value to return if no initial value and an empty array\n            if (length === 0 && arguments.length === 1) {\n                throw new TypeError('reduce of empty array with no initial value');\n            }\n\n            var i = 0;\n            var result;\n            if (arguments.length >= 2) {\n                result = arguments[1];\n            } else {\n                do {\n                    if (i in self) {\n                        result = self[i++];\n                        break;\n                    }\n\n                    // if array contains no values, no initial value to return\n                    if (++i >= length) {\n                        throw new TypeError('reduce of empty array with no initial value');\n                    }\n                } while (true);\n            }\n\n            for (; i < length; i++) {\n                if (i in self) {\n                    result = callbackfn(result, self[i], i, object);\n                }\n            }\n\n            return result;\n        }\n    }, !reduceCoercesToObject);\n\n    // ES5 15.4.4.22\n    // http://es5.github.com/#x15.4.4.22\n    // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight\n    var reduceRightCoercesToObject = false;\n    if (ArrayPrototype.reduceRight) {\n        reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) {\n            return list;\n        }) === 'object';\n    }\n    defineProperties(ArrayPrototype, {\n        reduceRight: function reduceRight(callbackfn/*, initial*/) {\n            var object = ES.ToObject(this);\n            var self = splitString && isString(this) ? strSplit(this, '') : object;\n            var length = ES.ToUint32(self.length);\n\n            // If no callback function or if callback is not a callable function\n            if (!isCallable(callbackfn)) {\n                throw new TypeError('Array.prototype.reduceRight callback must be a function');\n            }\n\n            // no value to return if no initial value, empty array\n            if (length === 0 && arguments.length === 1) {\n                throw new TypeError('reduceRight of empty array with no initial value');\n            }\n\n            var result;\n            var i = length - 1;\n            if (arguments.length >= 2) {\n                result = arguments[1];\n            } else {\n                do {\n                    if (i in self) {\n                        result = self[i--];\n                        break;\n                    }\n\n                    // if array contains no values, no initial value to return\n                    if (--i < 0) {\n                        throw new TypeError('reduceRight of empty array with no initial value');\n                    }\n                } while (true);\n            }\n\n            if (i < 0) {\n                return result;\n            }\n\n            do {\n                if (i in self) {\n                    result = callbackfn(result, self[i], i, object);\n                }\n            } while (i--);\n\n            return result;\n        }\n    }, !reduceRightCoercesToObject);\n\n    // ES5 15.4.4.14\n    // http://es5.github.com/#x15.4.4.14\n    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf\n    var hasFirefox2IndexOfBug = ArrayPrototype.indexOf && [0, 1].indexOf(1, 2) !== -1;\n    defineProperties(ArrayPrototype, {\n        indexOf: function indexOf(searchElement/*, fromIndex */) {\n            var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);\n            var length = ES.ToUint32(self.length);\n\n            if (length === 0) {\n                return -1;\n            }\n\n            var i = 0;\n            if (arguments.length > 1) {\n                i = ES.ToInteger(arguments[1]);\n            }\n\n            // handle negative indices\n            i = i >= 0 ? i : max(0, length + i);\n            for (; i < length; i++) {\n                if (i in self && self[i] === searchElement) {\n                    return i;\n                }\n            }\n            return -1;\n        }\n    }, hasFirefox2IndexOfBug);\n\n    // ES5 15.4.4.15\n    // http://es5.github.com/#x15.4.4.15\n    // https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf\n    var hasFirefox2LastIndexOfBug = ArrayPrototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;\n    defineProperties(ArrayPrototype, {\n        lastIndexOf: function lastIndexOf(searchElement/*, fromIndex */) {\n            var self = splitString && isString(this) ? strSplit(this, '') : ES.ToObject(this);\n            var length = ES.ToUint32(self.length);\n\n            if (length === 0) {\n                return -1;\n            }\n            var i = length - 1;\n            if (arguments.length > 1) {\n                i = min(i, ES.ToInteger(arguments[1]));\n            }\n            // handle negative indices\n            i = i >= 0 ? i : length - Math.abs(i);\n            for (; i >= 0; i--) {\n                if (i in self && searchElement === self[i]) {\n                    return i;\n                }\n            }\n            return -1;\n        }\n    }, hasFirefox2LastIndexOfBug);\n\n    // ES5 15.4.4.12\n    // http://es5.github.com/#x15.4.4.12\n    var spliceNoopReturnsEmptyArray = (function () {\n        var a = [1, 2];\n        var result = a.splice();\n        return a.length === 2 && isArray(result) && result.length === 0;\n    }());\n    defineProperties(ArrayPrototype, {\n        // Safari 5.0 bug where .splice() returns undefined\n        splice: function splice(start, deleteCount) {\n            if (arguments.length === 0) {\n                return [];\n            } else {\n                return array_splice.apply(this, arguments);\n            }\n        }\n    }, !spliceNoopReturnsEmptyArray);\n\n    var spliceWorksWithEmptyObject = (function () {\n        var obj = {};\n        ArrayPrototype.splice.call(obj, 0, 0, 1);\n        return obj.length === 1;\n    }());\n    defineProperties(ArrayPrototype, {\n        splice: function splice(start, deleteCount) {\n            if (arguments.length === 0) {\n                return [];\n            }\n            var args = arguments;\n            this.length = max(ES.ToInteger(this.length), 0);\n            if (arguments.length > 0 && typeof deleteCount !== 'number') {\n                args = arraySlice(arguments);\n                if (args.length < 2) {\n                    pushCall(args, this.length - start);\n                } else {\n                    args[1] = ES.ToInteger(deleteCount);\n                }\n            }\n            return array_splice.apply(this, args);\n        }\n    }, !spliceWorksWithEmptyObject);\n    var spliceWorksWithLargeSparseArrays = (function () {\n        // Per https://github.com/es-shims/es5-shim/issues/295\n        // Safari 7/8 breaks with sparse arrays of size 1e5 or greater\n        var arr = new $Array(1e5);\n        // note: the index MUST be 8 or larger or the test will false pass\n        arr[8] = 'x';\n        arr.splice(1, 1);\n        // note: this test must be defined *after* the indexOf shim\n        // per https://github.com/es-shims/es5-shim/issues/313\n        return arr.indexOf('x') === 7;\n    }());\n    var spliceWorksWithSmallSparseArrays = (function () {\n        // Per https://github.com/es-shims/es5-shim/issues/295\n        // Opera 12.15 breaks on this, no idea why.\n        var n = 256;\n        var arr = [];\n        arr[n] = 'a';\n        arr.splice(n + 1, 0, 'b');\n        return arr[n] === 'a';\n    }());\n    defineProperties(ArrayPrototype, {\n        splice: function splice(start, deleteCount) {\n            var O = ES.ToObject(this);\n            var A = [];\n            var len = ES.ToUint32(O.length);\n            var relativeStart = ES.ToInteger(start);\n            var actualStart = relativeStart < 0 ? max((len + relativeStart), 0) : min(relativeStart, len);\n            var actualDeleteCount = min(max(ES.ToInteger(deleteCount), 0), len - actualStart);\n\n            var k = 0;\n            var from;\n            while (k < actualDeleteCount) {\n                from = $String(actualStart + k);\n                if (owns(O, from)) {\n                    A[k] = O[from];\n                }\n                k += 1;\n            }\n\n            var items = arraySlice(arguments, 2);\n            var itemCount = items.length;\n            var to;\n            if (itemCount < actualDeleteCount) {\n                k = actualStart;\n                var maxK = len - actualDeleteCount;\n                while (k < maxK) {\n                    from = $String(k + actualDeleteCount);\n                    to = $String(k + itemCount);\n                    if (owns(O, from)) {\n                        O[to] = O[from];\n                    } else {\n                        delete O[to];\n                    }\n                    k += 1;\n                }\n                k = len;\n                var minK = len - actualDeleteCount + itemCount;\n                while (k > minK) {\n                    delete O[k - 1];\n                    k -= 1;\n                }\n            } else if (itemCount > actualDeleteCount) {\n                k = len - actualDeleteCount;\n                while (k > actualStart) {\n                    from = $String(k + actualDeleteCount - 1);\n                    to = $String(k + itemCount - 1);\n                    if (owns(O, from)) {\n                        O[to] = O[from];\n                    } else {\n                        delete O[to];\n                    }\n                    k -= 1;\n                }\n            }\n            k = actualStart;\n            for (var i = 0; i < items.length; ++i) {\n                O[k] = items[i];\n                k += 1;\n            }\n            O.length = len - actualDeleteCount + itemCount;\n\n            return A;\n        }\n    }, !spliceWorksWithLargeSparseArrays || !spliceWorksWithSmallSparseArrays);\n\n    var originalJoin = ArrayPrototype.join;\n    var hasStringJoinBug;\n    try {\n        hasStringJoinBug = Array.prototype.join.call('123', ',') !== '1,2,3';\n    } catch (e) {\n        hasStringJoinBug = true;\n    }\n    if (hasStringJoinBug) {\n        defineProperties(ArrayPrototype, {\n            join: function join(separator) {\n                var sep = typeof separator === 'undefined' ? ',' : separator;\n                return originalJoin.call(isString(this) ? strSplit(this, '') : this, sep);\n            }\n        }, hasStringJoinBug);\n    }\n\n    var hasJoinUndefinedBug = [1, 2].join(undefined) !== '1,2';\n    if (hasJoinUndefinedBug) {\n        defineProperties(ArrayPrototype, {\n            join: function join(separator) {\n                var sep = typeof separator === 'undefined' ? ',' : separator;\n                return originalJoin.call(this, sep);\n            }\n        }, hasJoinUndefinedBug);\n    }\n\n    var pushShim = function push(item) {\n        var O = ES.ToObject(this);\n        var n = ES.ToUint32(O.length);\n        var i = 0;\n        while (i < arguments.length) {\n            O[n + i] = arguments[i];\n            i += 1;\n        }\n        O.length = n + i;\n        return n + i;\n    };\n\n    var pushIsNotGeneric = (function () {\n        var obj = {};\n        var result = Array.prototype.push.call(obj, undefined);\n        return result !== 1 || obj.length !== 1 || typeof obj[0] !== 'undefined' || !owns(obj, 0);\n    }());\n    defineProperties(ArrayPrototype, {\n        push: function push(item) {\n            if (isArray(this)) {\n                return array_push.apply(this, arguments);\n            }\n            return pushShim.apply(this, arguments);\n        }\n    }, pushIsNotGeneric);\n\n    // This fixes a very weird bug in Opera 10.6 when pushing `undefined\n    var pushUndefinedIsWeird = (function () {\n        var arr = [];\n        var result = arr.push(undefined);\n        return result !== 1 || arr.length !== 1 || typeof arr[0] !== 'undefined' || !owns(arr, 0);\n    }());\n    defineProperties(ArrayPrototype, { push: pushShim }, pushUndefinedIsWeird);\n\n    // ES5 15.2.3.14\n    // http://es5.github.io/#x15.4.4.10\n    // Fix boxed string bug\n    defineProperties(ArrayPrototype, {\n        slice: function (start, end) {\n            var arr = isString(this) ? strSplit(this, '') : this;\n            return arraySliceApply(arr, arguments);\n        }\n    }, splitString);\n\n    var sortIgnoresNonFunctions = (function () {\n        try {\n            [1, 2].sort(null);\n            [1, 2].sort({});\n            return true;\n        } catch (e) {}\n        return false;\n    }());\n    var sortThrowsOnRegex = (function () {\n        // this is a problem in Firefox 4, in which `typeof /a/ === 'function'`\n        try {\n            [1, 2].sort(/a/);\n            return false;\n        } catch (e) {}\n        return true;\n    }());\n    var sortIgnoresUndefined = (function () {\n        // applies in IE 8, for one.\n        try {\n            [1, 2].sort(undefined);\n            return true;\n        } catch (e) {}\n        return false;\n    }());\n    defineProperties(ArrayPrototype, {\n        sort: function sort(compareFn) {\n            if (typeof compareFn === 'undefined') {\n                return arraySort(this);\n            }\n            if (!isCallable(compareFn)) {\n                throw new TypeError('Array.prototype.sort callback must be a function');\n            }\n            return arraySort(this, compareFn);\n        }\n    }, sortIgnoresNonFunctions || !sortIgnoresUndefined || !sortThrowsOnRegex);\n\n    //\n    // Object\n    // ======\n    //\n\n    // ES5 15.2.3.14\n    // http://es5.github.com/#x15.2.3.14\n\n    // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation\n    var hasDontEnumBug = !isEnum({ 'toString': null }, 'toString');\n    var hasProtoEnumBug = isEnum(function () {}, 'prototype');\n    var hasStringEnumBug = !owns('x', '0');\n    var equalsConstructorPrototype = function (o) {\n        var ctor = o.constructor;\n        return ctor && ctor.prototype === o;\n    };\n    var blacklistedKeys = {\n        $window: true,\n        $console: true,\n        $parent: true,\n        $self: true,\n        $frame: true,\n        $frames: true,\n        $frameElement: true,\n        $webkitIndexedDB: true,\n        $webkitStorageInfo: true,\n        $external: true\n    };\n    var hasAutomationEqualityBug = (function () {\n        /* globals window */\n        if (typeof window === 'undefined') {\n            return false;\n        }\n        for (var k in window) {\n            try {\n                if (!blacklistedKeys['$' + k] && owns(window, k) && window[k] !== null && typeof window[k] === 'object') {\n                    equalsConstructorPrototype(window[k]);\n                }\n            } catch (e) {\n                return true;\n            }\n        }\n        return false;\n    }());\n    var equalsConstructorPrototypeIfNotBuggy = function (object) {\n        if (typeof window === 'undefined' || !hasAutomationEqualityBug) {\n            return equalsConstructorPrototype(object);\n        }\n        try {\n            return equalsConstructorPrototype(object);\n        } catch (e) {\n            return false;\n        }\n    };\n    var dontEnums = [\n        'toString',\n        'toLocaleString',\n        'valueOf',\n        'hasOwnProperty',\n        'isPrototypeOf',\n        'propertyIsEnumerable',\n        'constructor'\n    ];\n    var dontEnumsLength = dontEnums.length;\n\n    // taken directly from https://github.com/ljharb/is-arguments/blob/master/index.js\n    // can be replaced with require('is-arguments') if we ever use a build process instead\n    var isStandardArguments = function isArguments(value) {\n        return toStr(value) === '[object Arguments]';\n    };\n    var isLegacyArguments = function isArguments(value) {\n        return value !== null &&\n            typeof value === 'object' &&\n            typeof value.length === 'number' &&\n            value.length >= 0 &&\n            !isArray(value) &&\n            isCallable(value.callee);\n    };\n    var isArguments = isStandardArguments(arguments) ? isStandardArguments : isLegacyArguments;\n\n    defineProperties($Object, {\n        keys: function keys(object) {\n            var isFn = isCallable(object);\n            var isArgs = isArguments(object);\n            var isObject = object !== null && typeof object === 'object';\n            var isStr = isObject && isString(object);\n\n            if (!isObject && !isFn && !isArgs) {\n                throw new TypeError('Object.keys called on a non-object');\n            }\n\n            var theKeys = [];\n            var skipProto = hasProtoEnumBug && isFn;\n            if ((isStr && hasStringEnumBug) || isArgs) {\n                for (var i = 0; i < object.length; ++i) {\n                    pushCall(theKeys, $String(i));\n                }\n            }\n\n            if (!isArgs) {\n                for (var name in object) {\n                    if (!(skipProto && name === 'prototype') && owns(object, name)) {\n                        pushCall(theKeys, $String(name));\n                    }\n                }\n            }\n\n            if (hasDontEnumBug) {\n                var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);\n                for (var j = 0; j < dontEnumsLength; j++) {\n                    var dontEnum = dontEnums[j];\n                    if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {\n                        pushCall(theKeys, dontEnum);\n                    }\n                }\n            }\n            return theKeys;\n        }\n    });\n\n    var keysWorksWithArguments = $Object.keys && (function () {\n        // Safari 5.0 bug\n        return $Object.keys(arguments).length === 2;\n    }(1, 2));\n    var keysHasArgumentsLengthBug = $Object.keys && (function () {\n        var argKeys = $Object.keys(arguments);\n        return arguments.length !== 1 || argKeys.length !== 1 || argKeys[0] !== 1;\n    }(1));\n    var originalKeys = $Object.keys;\n    defineProperties($Object, {\n        keys: function keys(object) {\n            if (isArguments(object)) {\n                return originalKeys(arraySlice(object));\n            } else {\n                return originalKeys(object);\n            }\n        }\n    }, !keysWorksWithArguments || keysHasArgumentsLengthBug);\n\n    //\n    // Date\n    // ====\n    //\n\n    var hasNegativeMonthYearBug = new Date(-3509827329600292).getUTCMonth() !== 0;\n    var aNegativeTestDate = new Date(-1509842289600292);\n    var aPositiveTestDate = new Date(1449662400000);\n    var hasToUTCStringFormatBug = aNegativeTestDate.toUTCString() !== 'Mon, 01 Jan -45875 11:59:59 GMT';\n    var hasToDateStringFormatBug;\n    var hasToStringFormatBug;\n    var timeZoneOffset = aNegativeTestDate.getTimezoneOffset();\n    if (timeZoneOffset < -720) {\n        hasToDateStringFormatBug = aNegativeTestDate.toDateString() !== 'Tue Jan 02 -45875';\n        hasToStringFormatBug = !(/^Thu Dec 10 2015 \\d\\d:\\d\\d:\\d\\d GMT[-\\+]\\d\\d\\d\\d(?: |$)/).test(aPositiveTestDate.toString());\n    } else {\n        hasToDateStringFormatBug = aNegativeTestDate.toDateString() !== 'Mon Jan 01 -45875';\n        hasToStringFormatBug = !(/^Wed Dec 09 2015 \\d\\d:\\d\\d:\\d\\d GMT[-\\+]\\d\\d\\d\\d(?: |$)/).test(aPositiveTestDate.toString());\n    }\n\n    var originalGetFullYear = call.bind(Date.prototype.getFullYear);\n    var originalGetMonth = call.bind(Date.prototype.getMonth);\n    var originalGetDate = call.bind(Date.prototype.getDate);\n    var originalGetUTCFullYear = call.bind(Date.prototype.getUTCFullYear);\n    var originalGetUTCMonth = call.bind(Date.prototype.getUTCMonth);\n    var originalGetUTCDate = call.bind(Date.prototype.getUTCDate);\n    var originalGetUTCDay = call.bind(Date.prototype.getUTCDay);\n    var originalGetUTCHours = call.bind(Date.prototype.getUTCHours);\n    var originalGetUTCMinutes = call.bind(Date.prototype.getUTCMinutes);\n    var originalGetUTCSeconds = call.bind(Date.prototype.getUTCSeconds);\n    var originalGetUTCMilliseconds = call.bind(Date.prototype.getUTCMilliseconds);\n    var dayName = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];\n    var monthName = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];\n    var daysInMonth = function daysInMonth(month, year) {\n        return originalGetDate(new Date(year, month, 0));\n    };\n\n    defineProperties(Date.prototype, {\n        getFullYear: function getFullYear() {\n            if (!this || !(this instanceof Date)) {\n                throw new TypeError('this is not a Date object.');\n            }\n            var year = originalGetFullYear(this);\n            if (year < 0 && originalGetMonth(this) > 11) {\n                return year + 1;\n            }\n            return year;\n        },\n        getMonth: function getMonth() {\n            if (!this || !(this instanceof Date)) {\n                throw new TypeError('this is not a Date object.');\n            }\n            var year = originalGetFullYear(this);\n            var month = originalGetMonth(this);\n            if (year < 0 && month > 11) {\n                return 0;\n            }\n            return month;\n        },\n        getDate: function getDate() {\n            if (!this || !(this instanceof Date)) {\n                throw new TypeError('this is not a Date object.');\n            }\n            var year = originalGetFullYear(this);\n            var month = originalGetMonth(this);\n            var date = originalGetDate(this);\n            if (year < 0 && month > 11) {\n                if (month === 12) {\n                    return date;\n                }\n                var days = daysInMonth(0, year + 1);\n                return (days - date) + 1;\n            }\n            return date;\n        },\n        getUTCFullYear: function getUTCFullYear() {\n            if (!this || !(this instanceof Date)) {\n                throw new TypeError('this is not a Date object.');\n            }\n            var year = originalGetUTCFullYear(this);\n            if (year < 0 && originalGetUTCMonth(this) > 11) {\n                return year + 1;\n            }\n            return year;\n        },\n        getUTCMonth: function getUTCMonth() {\n            if (!this || !(this instanceof Date)) {\n                throw new TypeError('this is not a Date object.');\n            }\n            var year = originalGetUTCFullYear(this);\n            var month = originalGetUTCMonth(this);\n            if (year < 0 && month > 11) {\n                return 0;\n            }\n            return month;\n        },\n        getUTCDate: function getUTCDate() {\n            if (!this || !(this instanceof Date)) {\n                throw new TypeError('this is not a Date object.');\n            }\n            var year = originalGetUTCFullYear(this);\n            var month = originalGetUTCMonth(this);\n            var date = originalGetUTCDate(this);\n            if (year < 0 && month > 11) {\n                if (month === 12) {\n                    return date;\n                }\n                var days = daysInMonth(0, year + 1);\n                return (days - date) + 1;\n            }\n            return date;\n        }\n    }, hasNegativeMonthYearBug);\n\n    defineProperties(Date.prototype, {\n        toUTCString: function toUTCString() {\n            if (!this || !(this instanceof Date)) {\n                throw new TypeError('this is not a Date object.');\n            }\n            var day = originalGetUTCDay(this);\n            var date = originalGetUTCDate(this);\n            var month = originalGetUTCMonth(this);\n            var year = originalGetUTCFullYear(this);\n            var hour = originalGetUTCHours(this);\n            var minute = originalGetUTCMinutes(this);\n            var second = originalGetUTCSeconds(this);\n            return dayName[day] + ', ' +\n                (date < 10 ? '0' + date : date) + ' ' +\n                monthName[month] + ' ' +\n                year + ' ' +\n                (hour < 10 ? '0' + hour : hour) + ':' +\n                (minute < 10 ? '0' + minute : minute) + ':' +\n                (second < 10 ? '0' + second : second) + ' GMT';\n        }\n    }, hasNegativeMonthYearBug || hasToUTCStringFormatBug);\n\n    // Opera 12 has `,`\n    defineProperties(Date.prototype, {\n        toDateString: function toDateString() {\n            if (!this || !(this instanceof Date)) {\n                throw new TypeError('this is not a Date object.');\n            }\n            var day = this.getDay();\n            var date = this.getDate();\n            var month = this.getMonth();\n            var year = this.getFullYear();\n            return dayName[day] + ' ' +\n                monthName[month] + ' ' +\n                (date < 10 ? '0' + date : date) + ' ' +\n                year;\n        }\n    }, hasNegativeMonthYearBug || hasToDateStringFormatBug);\n\n    // can't use defineProperties here because of toString enumeration issue in IE <= 8\n    if (hasNegativeMonthYearBug || hasToStringFormatBug) {\n        Date.prototype.toString = function toString() {\n            if (!this || !(this instanceof Date)) {\n                throw new TypeError('this is not a Date object.');\n            }\n            var day = this.getDay();\n            var date = this.getDate();\n            var month = this.getMonth();\n            var year = this.getFullYear();\n            var hour = this.getHours();\n            var minute = this.getMinutes();\n            var second = this.getSeconds();\n            var timezoneOffset = this.getTimezoneOffset();\n            var hoursOffset = Math.floor(Math.abs(timezoneOffset) / 60);\n            var minutesOffset = Math.floor(Math.abs(timezoneOffset) % 60);\n            return dayName[day] + ' ' +\n                monthName[month] + ' ' +\n                (date < 10 ? '0' + date : date) + ' ' +\n                year + ' ' +\n                (hour < 10 ? '0' + hour : hour) + ':' +\n                (minute < 10 ? '0' + minute : minute) + ':' +\n                (second < 10 ? '0' + second : second) + ' GMT' +\n                (timezoneOffset > 0 ? '-' : '+') +\n                (hoursOffset < 10 ? '0' + hoursOffset : hoursOffset) +\n                (minutesOffset < 10 ? '0' + minutesOffset : minutesOffset);\n        };\n        if (supportsDescriptors) {\n            $Object.defineProperty(Date.prototype, 'toString', {\n                configurable: true,\n                enumerable: false,\n                writable: true\n            });\n        }\n    }\n\n    // ES5 15.9.5.43\n    // http://es5.github.com/#x15.9.5.43\n    // This function returns a String value represent the instance in time\n    // represented by this Date object. The format of the String is the Date Time\n    // string format defined in 15.9.1.15. All fields are present in the String.\n    // The time zone is always UTC, denoted by the suffix Z. If the time value of\n    // this object is not a finite Number a RangeError exception is thrown.\n    var negativeDate = -62198755200000;\n    var negativeYearString = '-000001';\n    var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;\n    var hasSafari51DateBug = Date.prototype.toISOString && new Date(-1).toISOString() !== '1969-12-31T23:59:59.999Z';\n\n    var getTime = call.bind(Date.prototype.getTime);\n\n    defineProperties(Date.prototype, {\n        toISOString: function toISOString() {\n            if (!isFinite(this) || !isFinite(getTime(this))) {\n                // Adope Photoshop requires the second check.\n                throw new RangeError('Date.prototype.toISOString called on non-finite value.');\n            }\n\n            var year = originalGetUTCFullYear(this);\n\n            var month = originalGetUTCMonth(this);\n            // see https://github.com/es-shims/es5-shim/issues/111\n            year += Math.floor(month / 12);\n            month = (month % 12 + 12) % 12;\n\n            // the date time string format is specified in 15.9.1.15.\n            var result = [month + 1, originalGetUTCDate(this), originalGetUTCHours(this), originalGetUTCMinutes(this), originalGetUTCSeconds(this)];\n            year = (\n                (year < 0 ? '-' : (year > 9999 ? '+' : '')) +\n                strSlice('00000' + Math.abs(year), (0 <= year && year <= 9999) ? -4 : -6)\n            );\n\n            for (var i = 0; i < result.length; ++i) {\n                // pad months, days, hours, minutes, and seconds to have two digits.\n                result[i] = strSlice('00' + result[i], -2);\n            }\n            // pad milliseconds to have three digits.\n            return (\n                year + '-' + arraySlice(result, 0, 2).join('-') +\n                'T' + arraySlice(result, 2).join(':') + '.' +\n                strSlice('000' + originalGetUTCMilliseconds(this), -3) + 'Z'\n            );\n        }\n    }, hasNegativeDateBug || hasSafari51DateBug);\n\n    // ES5 15.9.5.44\n    // http://es5.github.com/#x15.9.5.44\n    // This function provides a String representation of a Date object for use by\n    // JSON.stringify (15.12.3).\n    var dateToJSONIsSupported = (function () {\n        try {\n            return Date.prototype.toJSON &&\n                new Date(NaN).toJSON() === null &&\n                new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 &&\n                Date.prototype.toJSON.call({ // generic\n                    toISOString: function () { return true; }\n                });\n        } catch (e) {\n            return false;\n        }\n    }());\n    if (!dateToJSONIsSupported) {\n        Date.prototype.toJSON = function toJSON(key) {\n            // When the toJSON method is called with argument key, the following\n            // steps are taken:\n\n            // 1.  Let O be the result of calling ToObject, giving it the this\n            // value as its argument.\n            // 2. Let tv be ES.ToPrimitive(O, hint Number).\n            var O = $Object(this);\n            var tv = ES.ToPrimitive(O);\n            // 3. If tv is a Number and is not finite, return null.\n            if (typeof tv === 'number' && !isFinite(tv)) {\n                return null;\n            }\n            // 4. Let toISO be the result of calling the [[Get]] internal method of\n            // O with argument \"toISOString\".\n            var toISO = O.toISOString;\n            // 5. If IsCallable(toISO) is false, throw a TypeError exception.\n            if (!isCallable(toISO)) {\n                throw new TypeError('toISOString property is not callable');\n            }\n            // 6. Return the result of calling the [[Call]] internal method of\n            //  toISO with O as the this value and an empty argument list.\n            return toISO.call(O);\n\n            // NOTE 1 The argument is ignored.\n\n            // NOTE 2 The toJSON function is intentionally generic; it does not\n            // require that its this value be a Date object. Therefore, it can be\n            // transferred to other kinds of objects for use as a method. However,\n            // it does require that any such object have a toISOString method. An\n            // object is free to use the argument key to filter its\n            // stringification.\n        };\n    }\n\n    // ES5 15.9.4.2\n    // http://es5.github.com/#x15.9.4.2\n    // based on work shared by Daniel Friesen (dantman)\n    // http://gist.github.com/303249\n    var supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15;\n    var acceptsInvalidDates = !isNaN(Date.parse('2012-04-04T24:00:00.500Z')) || !isNaN(Date.parse('2012-11-31T23:59:59.000Z')) || !isNaN(Date.parse('2012-12-31T23:59:60.000Z'));\n    var doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z'));\n    if (doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {\n        // XXX global assignment won't work in embeddings that use\n        // an alternate object for the context.\n        /* global Date: true */\n        /* eslint-disable no-undef */\n        var maxSafeUnsigned32Bit = Math.pow(2, 31) - 1;\n        var hasSafariSignedIntBug = isActualNaN(new Date(1970, 0, 1, 0, 0, 0, maxSafeUnsigned32Bit + 1).getTime());\n        /* eslint-disable no-implicit-globals */\n        Date = (function (NativeDate) {\n        /* eslint-enable no-implicit-globals */\n        /* eslint-enable no-undef */\n            // Date.length === 7\n            var DateShim = function Date(Y, M, D, h, m, s, ms) {\n                var length = arguments.length;\n                var date;\n                if (this instanceof NativeDate) {\n                    var seconds = s;\n                    var millis = ms;\n                    if (hasSafariSignedIntBug && length >= 7 && ms > maxSafeUnsigned32Bit) {\n                        // work around a Safari 8/9 bug where it treats the seconds as signed\n                        var msToShift = Math.floor(ms / maxSafeUnsigned32Bit) * maxSafeUnsigned32Bit;\n                        var sToShift = Math.floor(msToShift / 1e3);\n                        seconds += sToShift;\n                        millis -= sToShift * 1e3;\n                    }\n                    date = length === 1 && $String(Y) === Y ? // isString(Y)\n                        // We explicitly pass it through parse:\n                        new NativeDate(DateShim.parse(Y)) :\n                        // We have to manually make calls depending on argument\n                        // length here\n                        length >= 7 ? new NativeDate(Y, M, D, h, m, seconds, millis) :\n                        length >= 6 ? new NativeDate(Y, M, D, h, m, seconds) :\n                        length >= 5 ? new NativeDate(Y, M, D, h, m) :\n                        length >= 4 ? new NativeDate(Y, M, D, h) :\n                        length >= 3 ? new NativeDate(Y, M, D) :\n                        length >= 2 ? new NativeDate(Y, M) :\n                        length >= 1 ? new NativeDate(Y instanceof NativeDate ? +Y : Y) :\n                                      new NativeDate();\n                } else {\n                    date = NativeDate.apply(this, arguments);\n                }\n                if (!isPrimitive(date)) {\n                    // Prevent mixups with unfixed Date object\n                    defineProperties(date, { constructor: DateShim }, true);\n                }\n                return date;\n            };\n\n            // 15.9.1.15 Date Time String Format.\n            var isoDateExpression = new RegExp('^' +\n                '(\\\\d{4}|[+-]\\\\d{6})' + // four-digit year capture or sign +\n                                          // 6-digit extended year\n                '(?:-(\\\\d{2})' + // optional month capture\n                '(?:-(\\\\d{2})' + // optional day capture\n                '(?:' + // capture hours:minutes:seconds.milliseconds\n                    'T(\\\\d{2})' + // hours capture\n                    ':(\\\\d{2})' + // minutes capture\n                    '(?:' + // optional :seconds.milliseconds\n                        ':(\\\\d{2})' + // seconds capture\n                        '(?:(\\\\.\\\\d{1,}))?' + // milliseconds capture\n                    ')?' +\n                '(' + // capture UTC offset component\n                    'Z|' + // UTC capture\n                    '(?:' + // offset specifier +/-hours:minutes\n                        '([-+])' + // sign capture\n                        '(\\\\d{2})' + // hours offset capture\n                        ':(\\\\d{2})' + // minutes offset capture\n                    ')' +\n                ')?)?)?)?' +\n            '$');\n\n            var months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];\n\n            var dayFromMonth = function dayFromMonth(year, month) {\n                var t = month > 1 ? 1 : 0;\n                return (\n                    months[month] +\n                    Math.floor((year - 1969 + t) / 4) -\n                    Math.floor((year - 1901 + t) / 100) +\n                    Math.floor((year - 1601 + t) / 400) +\n                    365 * (year - 1970)\n                );\n            };\n\n            var toUTC = function toUTC(t) {\n                var s = 0;\n                var ms = t;\n                if (hasSafariSignedIntBug && ms > maxSafeUnsigned32Bit) {\n                    // work around a Safari 8/9 bug where it treats the seconds as signed\n                    var msToShift = Math.floor(ms / maxSafeUnsigned32Bit) * maxSafeUnsigned32Bit;\n                    var sToShift = Math.floor(msToShift / 1e3);\n                    s += sToShift;\n                    ms -= sToShift * 1e3;\n                }\n                return $Number(new NativeDate(1970, 0, 1, 0, 0, s, ms));\n            };\n\n            // Copy any custom methods a 3rd party library may have added\n            for (var key in NativeDate) {\n                if (owns(NativeDate, key)) {\n                    DateShim[key] = NativeDate[key];\n                }\n            }\n\n            // Copy \"native\" methods explicitly; they may be non-enumerable\n            defineProperties(DateShim, {\n                now: NativeDate.now,\n                UTC: NativeDate.UTC\n            }, true);\n            DateShim.prototype = NativeDate.prototype;\n            defineProperties(DateShim.prototype, {\n                constructor: DateShim\n            }, true);\n\n            // Upgrade Date.parse to handle simplified ISO 8601 strings\n            var parseShim = function parse(string) {\n                var match = isoDateExpression.exec(string);\n                if (match) {\n                    // parse months, days, hours, minutes, seconds, and milliseconds\n                    // provide default values if necessary\n                    // parse the UTC offset component\n                    var year = $Number(match[1]),\n                        month = $Number(match[2] || 1) - 1,\n                        day = $Number(match[3] || 1) - 1,\n                        hour = $Number(match[4] || 0),\n                        minute = $Number(match[5] || 0),\n                        second = $Number(match[6] || 0),\n                        millisecond = Math.floor($Number(match[7] || 0) * 1000),\n                        // When time zone is missed, local offset should be used\n                        // (ES 5.1 bug)\n                        // see https://bugs.ecmascript.org/show_bug.cgi?id=112\n                        isLocalTime = Boolean(match[4] && !match[8]),\n                        signOffset = match[9] === '-' ? 1 : -1,\n                        hourOffset = $Number(match[10] || 0),\n                        minuteOffset = $Number(match[11] || 0),\n                        result;\n                    var hasMinutesOrSecondsOrMilliseconds = minute > 0 || second > 0 || millisecond > 0;\n                    if (\n                        hour < (hasMinutesOrSecondsOrMilliseconds ? 24 : 25) &&\n                        minute < 60 && second < 60 && millisecond < 1000 &&\n                        month > -1 && month < 12 && hourOffset < 24 &&\n                        minuteOffset < 60 && // detect invalid offsets\n                        day > -1 &&\n                        day < (dayFromMonth(year, month + 1) - dayFromMonth(year, month))\n                    ) {\n                        result = (\n                            (dayFromMonth(year, month) + day) * 24 +\n                            hour +\n                            hourOffset * signOffset\n                        ) * 60;\n                        result = (\n                            (result + minute + minuteOffset * signOffset) * 60 +\n                            second\n                        ) * 1000 + millisecond;\n                        if (isLocalTime) {\n                            result = toUTC(result);\n                        }\n                        if (-8.64e15 <= result && result <= 8.64e15) {\n                            return result;\n                        }\n                    }\n                    return NaN;\n                }\n                return NativeDate.parse.apply(this, arguments);\n            };\n            defineProperties(DateShim, { parse: parseShim });\n\n            return DateShim;\n        }(Date));\n        /* global Date: false */\n    }\n\n    // ES5 15.9.4.4\n    // http://es5.github.com/#x15.9.4.4\n    if (!Date.now) {\n        Date.now = function now() {\n            return new Date().getTime();\n        };\n    }\n\n    //\n    // Number\n    // ======\n    //\n\n    // ES5.1 15.7.4.5\n    // http://es5.github.com/#x15.7.4.5\n    var hasToFixedBugs = NumberPrototype.toFixed && (\n      (0.00008).toFixed(3) !== '0.000' ||\n      (0.9).toFixed(0) !== '1' ||\n      (1.255).toFixed(2) !== '1.25' ||\n      (1000000000000000128).toFixed(0) !== '1000000000000000128'\n    );\n\n    var toFixedHelpers = {\n        base: 1e7,\n        size: 6,\n        data: [0, 0, 0, 0, 0, 0],\n        multiply: function multiply(n, c) {\n            var i = -1;\n            var c2 = c;\n            while (++i < toFixedHelpers.size) {\n                c2 += n * toFixedHelpers.data[i];\n                toFixedHelpers.data[i] = c2 % toFixedHelpers.base;\n                c2 = Math.floor(c2 / toFixedHelpers.base);\n            }\n        },\n        divide: function divide(n) {\n            var i = toFixedHelpers.size;\n            var c = 0;\n            while (--i >= 0) {\n                c += toFixedHelpers.data[i];\n                toFixedHelpers.data[i] = Math.floor(c / n);\n                c = (c % n) * toFixedHelpers.base;\n            }\n        },\n        numToString: function numToString() {\n            var i = toFixedHelpers.size;\n            var s = '';\n            while (--i >= 0) {\n                if (s !== '' || i === 0 || toFixedHelpers.data[i] !== 0) {\n                    var t = $String(toFixedHelpers.data[i]);\n                    if (s === '') {\n                        s = t;\n                    } else {\n                        s += strSlice('0000000', 0, 7 - t.length) + t;\n                    }\n                }\n            }\n            return s;\n        },\n        pow: function pow(x, n, acc) {\n            return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc)));\n        },\n        log: function log(x) {\n            var n = 0;\n            var x2 = x;\n            while (x2 >= 4096) {\n                n += 12;\n                x2 /= 4096;\n            }\n            while (x2 >= 2) {\n                n += 1;\n                x2 /= 2;\n            }\n            return n;\n        }\n    };\n\n    var toFixedShim = function toFixed(fractionDigits) {\n        var f, x, s, m, e, z, j, k;\n\n        // Test for NaN and round fractionDigits down\n        f = $Number(fractionDigits);\n        f = isActualNaN(f) ? 0 : Math.floor(f);\n\n        if (f < 0 || f > 20) {\n            throw new RangeError('Number.toFixed called with invalid number of decimals');\n        }\n\n        x = $Number(this);\n\n        if (isActualNaN(x)) {\n            return 'NaN';\n        }\n\n        // If it is too big or small, return the string value of the number\n        if (x <= -1e21 || x >= 1e21) {\n            return $String(x);\n        }\n\n        s = '';\n\n        if (x < 0) {\n            s = '-';\n            x = -x;\n        }\n\n        m = '0';\n\n        if (x > 1e-21) {\n            // 1e-21 < x < 1e21\n            // -70 < log2(x) < 70\n            e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69;\n            z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1));\n            z *= 0x10000000000000; // Math.pow(2, 52);\n            e = 52 - e;\n\n            // -18 < e < 122\n            // x = z / 2 ^ e\n            if (e > 0) {\n                toFixedHelpers.multiply(0, z);\n                j = f;\n\n                while (j >= 7) {\n                    toFixedHelpers.multiply(1e7, 0);\n                    j -= 7;\n                }\n\n                toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0);\n                j = e - 1;\n\n                while (j >= 23) {\n                    toFixedHelpers.divide(1 << 23);\n                    j -= 23;\n                }\n\n                toFixedHelpers.divide(1 << j);\n                toFixedHelpers.multiply(1, 1);\n                toFixedHelpers.divide(2);\n                m = toFixedHelpers.numToString();\n            } else {\n                toFixedHelpers.multiply(0, z);\n                toFixedHelpers.multiply(1 << (-e), 0);\n                m = toFixedHelpers.numToString() + strSlice('0.00000000000000000000', 2, 2 + f);\n            }\n        }\n\n        if (f > 0) {\n            k = m.length;\n\n            if (k <= f) {\n                m = s + strSlice('0.0000000000000000000', 0, f - k + 2) + m;\n            } else {\n                m = s + strSlice(m, 0, k - f) + '.' + strSlice(m, k - f);\n            }\n        } else {\n            m = s + m;\n        }\n\n        return m;\n    };\n    defineProperties(NumberPrototype, { toFixed: toFixedShim }, hasToFixedBugs);\n\n    var hasToPrecisionUndefinedBug = (function () {\n        try {\n            return 1.0.toPrecision(undefined) === '1';\n        } catch (e) {\n            return true;\n        }\n    }());\n    var originalToPrecision = NumberPrototype.toPrecision;\n    defineProperties(NumberPrototype, {\n        toPrecision: function toPrecision(precision) {\n            return typeof precision === 'undefined' ? originalToPrecision.call(this) : originalToPrecision.call(this, precision);\n        }\n    }, hasToPrecisionUndefinedBug);\n\n    //\n    // String\n    // ======\n    //\n\n    // ES5 15.5.4.14\n    // http://es5.github.com/#x15.5.4.14\n\n    // [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]\n    // Many browsers do not split properly with regular expressions or they\n    // do not perform the split correctly under obscure conditions.\n    // See http://blog.stevenlevithan.com/archives/cross-browser-split\n    // I've tested in many browsers and this seems to cover the deviant ones:\n    //    'ab'.split(/(?:ab)*/) should be [\"\", \"\"], not [\"\"]\n    //    '.'.split(/(.?)(.?)/) should be [\"\", \".\", \"\", \"\"], not [\"\", \"\"]\n    //    'tesst'.split(/(s)*/) should be [\"t\", undefined, \"e\", \"s\", \"t\"], not\n    //       [undefined, \"t\", undefined, \"e\", ...]\n    //    ''.split(/.?/) should be [], not [\"\"]\n    //    '.'.split(/()()/) should be [\".\"], not [\"\", \"\", \".\"]\n\n    if (\n        'ab'.split(/(?:ab)*/).length !== 2 ||\n        '.'.split(/(.?)(.?)/).length !== 4 ||\n        'tesst'.split(/(s)*/)[1] === 't' ||\n        'test'.split(/(?:)/, -1).length !== 4 ||\n        ''.split(/.?/).length ||\n        '.'.split(/()()/).length > 1\n    ) {\n        (function () {\n            var compliantExecNpcg = typeof (/()??/).exec('')[1] === 'undefined'; // NPCG: nonparticipating capturing group\n            var maxSafe32BitInt = Math.pow(2, 32) - 1;\n\n            StringPrototype.split = function (separator, limit) {\n                var string = String(this);\n                if (typeof separator === 'undefined' && limit === 0) {\n                    return [];\n                }\n\n                // If `separator` is not a regex, use native split\n                if (!isRegex(separator)) {\n                    return strSplit(this, separator, limit);\n                }\n\n                var output = [];\n                var flags = (separator.ignoreCase ? 'i' : '') +\n                            (separator.multiline ? 'm' : '') +\n                            (separator.unicode ? 'u' : '') + // in ES6\n                            (separator.sticky ? 'y' : ''), // Firefox 3+ and ES6\n                    lastLastIndex = 0,\n                    // Make `global` and avoid `lastIndex` issues by working with a copy\n                    separator2, match, lastIndex, lastLength;\n                var separatorCopy = new RegExp(separator.source, flags + 'g');\n                if (!compliantExecNpcg) {\n                    // Doesn't need flags gy, but they don't hurt\n                    separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\\\s)', flags);\n                }\n                /* Values for `limit`, per the spec:\n                 * If undefined: 4294967295 // maxSafe32BitInt\n                 * If 0, Infinity, or NaN: 0\n                 * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;\n                 * If negative number: 4294967296 - Math.floor(Math.abs(limit))\n                 * If other: Type-convert, then use the above rules\n                 */\n                var splitLimit = typeof limit === 'undefined' ? maxSafe32BitInt : ES.ToUint32(limit);\n                match = separatorCopy.exec(string);\n                while (match) {\n                    // `separatorCopy.lastIndex` is not reliable cross-browser\n                    lastIndex = match.index + match[0].length;\n                    if (lastIndex > lastLastIndex) {\n                        pushCall(output, strSlice(string, lastLastIndex, match.index));\n                        // Fix browsers whose `exec` methods don't consistently return `undefined` for\n                        // nonparticipating capturing groups\n                        if (!compliantExecNpcg && match.length > 1) {\n                            /* eslint-disable no-loop-func */\n                            match[0].replace(separator2, function () {\n                                for (var i = 1; i < arguments.length - 2; i++) {\n                                    if (typeof arguments[i] === 'undefined') {\n                                        match[i] = void 0;\n                                    }\n                                }\n                            });\n                            /* eslint-enable no-loop-func */\n                        }\n                        if (match.length > 1 && match.index < string.length) {\n                            array_push.apply(output, arraySlice(match, 1));\n                        }\n                        lastLength = match[0].length;\n                        lastLastIndex = lastIndex;\n                        if (output.length >= splitLimit) {\n                            break;\n                        }\n                    }\n                    if (separatorCopy.lastIndex === match.index) {\n                        separatorCopy.lastIndex++; // Avoid an infinite loop\n                    }\n                    match = separatorCopy.exec(string);\n                }\n                if (lastLastIndex === string.length) {\n                    if (lastLength || !separatorCopy.test('')) {\n                        pushCall(output, '');\n                    }\n                } else {\n                    pushCall(output, strSlice(string, lastLastIndex));\n                }\n                return output.length > splitLimit ? arraySlice(output, 0, splitLimit) : output;\n            };\n        }());\n\n    // [bugfix, chrome]\n    // If separator is undefined, then the result array contains just one String,\n    // which is the this value (converted to a String). If limit is not undefined,\n    // then the output array is truncated so that it contains no more than limit\n    // elements.\n    // \"0\".split(undefined, 0) -> []\n    } else if ('0'.split(void 0, 0).length) {\n        StringPrototype.split = function split(separator, limit) {\n            if (typeof separator === 'undefined' && limit === 0) {\n                return [];\n            }\n            return strSplit(this, separator, limit);\n        };\n    }\n\n    var str_replace = StringPrototype.replace;\n    var replaceReportsGroupsCorrectly = (function () {\n        var groups = [];\n        'x'.replace(/x(.)?/g, function (match, group) {\n            pushCall(groups, group);\n        });\n        return groups.length === 1 && typeof groups[0] === 'undefined';\n    }());\n\n    if (!replaceReportsGroupsCorrectly) {\n        StringPrototype.replace = function replace(searchValue, replaceValue) {\n            var isFn = isCallable(replaceValue);\n            var hasCapturingGroups = isRegex(searchValue) && (/\\)[*?]/).test(searchValue.source);\n            if (!isFn || !hasCapturingGroups) {\n                return str_replace.call(this, searchValue, replaceValue);\n            } else {\n                var wrappedReplaceValue = function (match) {\n                    var length = arguments.length;\n                    var originalLastIndex = searchValue.lastIndex;\n                    searchValue.lastIndex = 0;\n                    var args = searchValue.exec(match) || [];\n                    searchValue.lastIndex = originalLastIndex;\n                    pushCall(args, arguments[length - 2], arguments[length - 1]);\n                    return replaceValue.apply(this, args);\n                };\n                return str_replace.call(this, searchValue, wrappedReplaceValue);\n            }\n        };\n    }\n\n    // ECMA-262, 3rd B.2.3\n    // Not an ECMAScript standard, although ECMAScript 3rd Edition has a\n    // non-normative section suggesting uniform semantics and it should be\n    // normalized across all browsers\n    // [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE\n    var string_substr = StringPrototype.substr;\n    var hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';\n    defineProperties(StringPrototype, {\n        substr: function substr(start, length) {\n            var normalizedStart = start;\n            if (start < 0) {\n                normalizedStart = max(this.length + start, 0);\n            }\n            return string_substr.call(this, normalizedStart, length);\n        }\n    }, hasNegativeSubstrBug);\n\n    // ES5 15.5.4.20\n    // whitespace from: http://es5.github.io/#x15.5.4.20\n    var ws = '\\x09\\x0A\\x0B\\x0C\\x0D\\x20\\xA0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003' +\n        '\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\\u2028' +\n        '\\u2029\\uFEFF';\n    var zeroWidth = '\\u200b';\n    var wsRegexChars = '[' + ws + ']';\n    var trimBeginRegexp = new RegExp('^' + wsRegexChars + wsRegexChars + '*');\n    var trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + '*$');\n    var hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim());\n    defineProperties(StringPrototype, {\n        // http://blog.stevenlevithan.com/archives/faster-trim-javascript\n        // http://perfectionkills.com/whitespace-deviations/\n        trim: function trim() {\n            if (typeof this === 'undefined' || this === null) {\n                throw new TypeError(\"can't convert \" + this + ' to object');\n            }\n            return $String(this).replace(trimBeginRegexp, '').replace(trimEndRegexp, '');\n        }\n    }, hasTrimWhitespaceBug);\n    var trim = call.bind(String.prototype.trim);\n\n    var hasLastIndexBug = StringPrototype.lastIndexOf && 'abcあい'.lastIndexOf('あい', 2) !== -1;\n    defineProperties(StringPrototype, {\n        lastIndexOf: function lastIndexOf(searchString) {\n            if (typeof this === 'undefined' || this === null) {\n                throw new TypeError(\"can't convert \" + this + ' to object');\n            }\n            var S = $String(this);\n            var searchStr = $String(searchString);\n            var numPos = arguments.length > 1 ? $Number(arguments[1]) : NaN;\n            var pos = isActualNaN(numPos) ? Infinity : ES.ToInteger(numPos);\n            var start = min(max(pos, 0), S.length);\n            var searchLen = searchStr.length;\n            var k = start + searchLen;\n            while (k > 0) {\n                k = max(0, k - searchLen);\n                var index = strIndexOf(strSlice(S, k, start + searchLen), searchStr);\n                if (index !== -1) {\n                    return k + index;\n                }\n            }\n            return -1;\n        }\n    }, hasLastIndexBug);\n\n    var originalLastIndexOf = StringPrototype.lastIndexOf;\n    defineProperties(StringPrototype, {\n        lastIndexOf: function lastIndexOf(searchString) {\n            return originalLastIndexOf.apply(this, arguments);\n        }\n    }, StringPrototype.lastIndexOf.length !== 1);\n\n    // ES-5 15.1.2.2\n    /* eslint-disable radix */\n    if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {\n    /* eslint-enable radix */\n        /* global parseInt: true */\n        parseInt = (function (origParseInt) {\n            var hexRegex = /^[\\-+]?0[xX]/;\n            return function parseInt(str, radix) {\n                var string = trim(String(str));\n                var defaultedRadix = $Number(radix) || (hexRegex.test(string) ? 16 : 10);\n                return origParseInt(string, defaultedRadix);\n            };\n        }(parseInt));\n    }\n\n    // https://es5.github.io/#x15.1.2.3\n    if (1 / parseFloat('-0') !== -Infinity) {\n        /* global parseFloat: true */\n        parseFloat = (function (origParseFloat) {\n            return function parseFloat(string) {\n                var inputString = trim(String(string));\n                var result = origParseFloat(inputString);\n                return result === 0 && strSlice(inputString, 0, 1) === '-' ? -0 : result;\n            };\n        }(parseFloat));\n    }\n\n    if (String(new RangeError('test')) !== 'RangeError: test') {\n        var errorToStringShim = function toString() {\n            if (typeof this === 'undefined' || this === null) {\n                throw new TypeError(\"can't convert \" + this + ' to object');\n            }\n            var name = this.name;\n            if (typeof name === 'undefined') {\n                name = 'Error';\n            } else if (typeof name !== 'string') {\n                name = $String(name);\n            }\n            var msg = this.message;\n            if (typeof msg === 'undefined') {\n                msg = '';\n            } else if (typeof msg !== 'string') {\n                msg = $String(msg);\n            }\n            if (!name) {\n                return msg;\n            }\n            if (!msg) {\n                return name;\n            }\n            return name + ': ' + msg;\n        };\n        // can't use defineProperties here because of toString enumeration issue in IE <= 8\n        Error.prototype.toString = errorToStringShim;\n    }\n\n    if (supportsDescriptors) {\n        var ensureNonEnumerable = function (obj, prop) {\n            if (isEnum(obj, prop)) {\n                var desc = Object.getOwnPropertyDescriptor(obj, prop);\n                if (desc.configurable) {\n                    desc.enumerable = false;\n                    Object.defineProperty(obj, prop, desc);\n                }\n            }\n        };\n        ensureNonEnumerable(Error.prototype, 'message');\n        if (Error.prototype.message !== '') {\n            Error.prototype.message = '';\n        }\n        ensureNonEnumerable(Error.prototype, 'name');\n    }\n\n    if (String(/a/mig) !== '/a/gim') {\n        var regexToString = function toString() {\n            var str = '/' + this.source + '/';\n            if (this.global) {\n                str += 'g';\n            }\n            if (this.ignoreCase) {\n                str += 'i';\n            }\n            if (this.multiline) {\n                str += 'm';\n            }\n            return str;\n        };\n        // can't use defineProperties here because of toString enumeration issue in IE <= 8\n        RegExp.prototype.toString = regexToString;\n    }\n}));\n\n'use strict';\n/*jslint eqeq: true*/\n\nHandlebars.registerHelper('sanitize', function (text) {\n    var result;\n\n    if (text === undefined) { return ''; }\n\n    result = sanitizeHtml(text, {\n        allowedTags: [ 'div', 'span', 'b', 'i', 'em', 'strong', 'a', 'br', 'table', 'tbody', 'tr', 'th', 'td' ],\n        allowedAttributes: {\n            'div': [ 'class' ],\n            'span': [ 'class' ],\n            'table': [ 'class' ],\n            'td': [ 'class' ],\n            'th': [ 'colspan' ],\n            'a': [ 'href' ]\n        }\n    });\n\n    return new Handlebars.SafeString(result);\n});\n\nHandlebars.registerHelper('renderTextParam', function(param) {\n    var result, type = 'text', idAtt = '';\n\tvar paramType = (param.schema) ? param.type || param.schema.type || '' : param.type || '';\n    var isArray = paramType.toLowerCase() === 'array' || param.allowMultiple;\n    var defaultValue = isArray && Array.isArray(param.default) ? param.default.join('\\n') : param.default;\n    var name = Handlebars.Utils.escapeExpression(param.name);\n    var valueId = Handlebars.Utils.escapeExpression(param.valueId);\n    paramType = Handlebars.Utils.escapeExpression(paramType);\n\n    var dataVendorExtensions = Object.keys(param).filter(function(property) {\n        // filter X-data- properties\n        return property.match(/^X-data-/i) !== null;\n    }).reduce(function(result, property) {\n        // remove X- from property name, so it results in html attributes like data-foo='bar'\n        return result += ' ' + property.substring(2, property.length) + '=\\'' + param[property] + '\\'';\n    }, '');\n\n    if(param.format && param.format === 'password') {\n        type = 'password';\n    }\n\n    if(valueId) {\n        idAtt = ' id=\\'' + valueId + '\\'';\n    }\n\n    if (defaultValue) {\n      defaultValue = sanitizeHtml(defaultValue);\n    } else {\n      defaultValue = '';\n    }\n\n    if(isArray) {\n        result = '<textarea class=\\'body-textarea' + (param.required ? ' required' : '') + '\\' name=\\'' + name + '\\'' + idAtt + dataVendorExtensions;\n        result += ' placeholder=\\'Provide multiple values in new lines' + (param.required ? ' (at least one required).' : '.') + '\\'>';\n        result += defaultValue + '</textarea>';\n    } else {\n        var parameterClass = 'parameter';\n        if(param.required) {\n          parameterClass += ' required';\n        }\n        result = '<input class=\\'' + parameterClass + '\\' minlength=\\'' + (param.required ? 1 : 0) + '\\'';\n        result += ' name=\\'' + name +'\\' placeholder=\\'' + (param.required ? '(required)' : '') + '\\'' + idAtt + dataVendorExtensions;\n        result += ' type=\\'' + type + '\\' value=\\'' + defaultValue + '\\'/>';\n    }\n    return new Handlebars.SafeString(result);\n});\n\nHandlebars.registerHelper('ifCond', function (v1, operator, v2, options) {\n\n    switch (operator) {\n        case '==':\n            return (v1 == v2) ? options.fn(this) : options.inverse(this);\n        case '===':\n            return (v1 === v2) ? options.fn(this) : options.inverse(this);\n        case '<':\n            return (v1 < v2) ? options.fn(this) : options.inverse(this);\n        case '<=':\n            return (v1 <= v2) ? options.fn(this) : options.inverse(this);\n        case '>':\n            return (v1 > v2) ? options.fn(this) : options.inverse(this);\n        case '>=':\n            return (v1 >= v2) ? options.fn(this) : options.inverse(this);\n        case '&&':\n            return (v1 && v2) ? options.fn(this) : options.inverse(this);\n        case '||':\n            return (v1 || v2) ? options.fn(this) : options.inverse(this);\n        default:\n            return options.inverse(this);\n    }\n});\n\nHandlebars.registerHelper('escape', function (value) {\n    var text = Handlebars.Utils.escapeExpression(value);\n\n    return new Handlebars.SafeString(text);\n});\n\n(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.sanitizeHtml=f()}})(function(){var define,module,exports;return function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}({1:[function(require,module,exports){var htmlparser=require(\"htmlparser2\");var extend=require(\"xtend\");var quoteRegexp=require(\"regexp-quote\");function each(obj,cb){if(obj)Object.keys(obj).forEach(function(key){cb(obj[key],key)})}function has(obj,key){return{}.hasOwnProperty.call(obj,key)}module.exports=sanitizeHtml;function sanitizeHtml(html,options,_recursing){var result=\"\";function Frame(tag,attribs){var that=this;this.tag=tag;this.attribs=attribs||{};this.tagPosition=result.length;this.text=\"\";this.updateParentNodeText=function(){if(stack.length){var parentFrame=stack[stack.length-1];parentFrame.text+=that.text}}}if(!options){options=sanitizeHtml.defaults;options.parser=htmlParserDefaults}else{options=extend(sanitizeHtml.defaults,options);if(options.parser){options.parser=extend(htmlParserDefaults,options.parser)}else{options.parser=htmlParserDefaults}}var nonTextTagsArray=options.nonTextTags||[\"script\",\"style\",\"textarea\"];var allowedAttributesMap;var allowedAttributesGlobMap;if(options.allowedAttributes){allowedAttributesMap={};allowedAttributesGlobMap={};each(options.allowedAttributes,function(attributes,tag){allowedAttributesMap[tag]=[];var globRegex=[];attributes.forEach(function(name){if(name.indexOf(\"*\")>=0){globRegex.push(quoteRegexp(name).replace(/\\\\\\*/g,\".*\"))}else{allowedAttributesMap[tag].push(name)}});allowedAttributesGlobMap[tag]=new RegExp(\"^(\"+globRegex.join(\"|\")+\")$\")})}var allowedClassesMap={};each(options.allowedClasses,function(classes,tag){if(allowedAttributesMap){if(!has(allowedAttributesMap,tag)){allowedAttributesMap[tag]=[]}allowedAttributesMap[tag].push(\"class\")}allowedClassesMap[tag]=classes});var transformTagsMap={};var transformTagsAll;each(options.transformTags,function(transform,tag){var transFun;if(typeof transform===\"function\"){transFun=transform}else if(typeof transform===\"string\"){transFun=sanitizeHtml.simpleTransform(transform)}if(tag===\"*\"){transformTagsAll=transFun}else{transformTagsMap[tag]=transFun}});var depth=0;var stack=[];var skipMap={};var transformMap={};var skipText=false;var skipTextDepth=0;var parser=new htmlparser.Parser({onopentag:function(name,attribs){if(skipText){skipTextDepth++;return}var frame=new Frame(name,attribs);stack.push(frame);var skip=false;var hasText=frame.text?true:false;var transformedTag;if(has(transformTagsMap,name)){transformedTag=transformTagsMap[name](name,attribs);frame.attribs=attribs=transformedTag.attribs;if(transformedTag.text!==undefined){frame.innerText=transformedTag.text}if(name!==transformedTag.tagName){frame.name=name=transformedTag.tagName;transformMap[depth]=transformedTag.tagName}}if(transformTagsAll){transformedTag=transformTagsAll(name,attribs);frame.attribs=attribs=transformedTag.attribs;if(name!==transformedTag.tagName){frame.name=name=transformedTag.tagName;transformMap[depth]=transformedTag.tagName}}if(options.allowedTags&&options.allowedTags.indexOf(name)===-1){skip=true;if(nonTextTagsArray.indexOf(name)!==-1){skipText=true;skipTextDepth=1}skipMap[depth]=true}depth++;if(skip){return}result+=\"<\"+name;if(!allowedAttributesMap||has(allowedAttributesMap,name)||allowedAttributesMap[\"*\"]){each(attribs,function(value,a){if(!allowedAttributesMap||has(allowedAttributesMap,name)&&allowedAttributesMap[name].indexOf(a)!==-1||allowedAttributesMap[\"*\"]&&allowedAttributesMap[\"*\"].indexOf(a)!==-1||has(allowedAttributesGlobMap,name)&&allowedAttributesGlobMap[name].test(a)||allowedAttributesGlobMap[\"*\"]&&allowedAttributesGlobMap[\"*\"].test(a)){if(a===\"href\"||a===\"src\"){if(naughtyHref(name,value)){delete frame.attribs[a];return}}if(a===\"class\"){value=filterClasses(value,allowedClassesMap[name]);if(!value.length){delete frame.attribs[a];return}}result+=\" \"+a;if(value.length){result+='=\"'+escapeHtml(value)+'\"'}}else{delete frame.attribs[a]}})}if(options.selfClosing.indexOf(name)!==-1){result+=\" />\"}else{result+=\">\";if(frame.innerText&&!hasText&&!options.textFilter){result+=frame.innerText}}},ontext:function(text){if(skipText){return}var lastFrame=stack[stack.length-1];var tag;if(lastFrame){tag=lastFrame.tag;text=lastFrame.innerText!==undefined?lastFrame.innerText:text}if(tag===\"script\"||tag===\"style\"){result+=text}else{var escaped=escapeHtml(text);if(options.textFilter){result+=options.textFilter(escaped)}else{result+=escaped}}if(stack.length){var frame=stack[stack.length-1];frame.text+=text}},onclosetag:function(name){if(skipText){skipTextDepth--;if(!skipTextDepth){skipText=false}else{return}}var frame=stack.pop();if(!frame){return}skipText=false;depth--;if(skipMap[depth]){delete skipMap[depth];frame.updateParentNodeText();return}if(transformMap[depth]){name=transformMap[depth];delete transformMap[depth]}if(options.exclusiveFilter&&options.exclusiveFilter(frame)){result=result.substr(0,frame.tagPosition);return}frame.updateParentNodeText();if(options.selfClosing.indexOf(name)!==-1){return}result+=\"</\"+name+\">\"}},options.parser);parser.write(html);parser.end();return result;function escapeHtml(s){if(typeof s!==\"string\"){s=s+\"\"}return s.replace(/\\&/g,\"&amp;\").replace(/</g,\"&lt;\").replace(/\\>/g,\"&gt;\").replace(/\\\"/g,\"&quot;\")}function naughtyHref(name,href){href=href.replace(/[\\x00-\\x20]+/g,\"\");href=href.replace(/<\\!\\-\\-.*?\\-\\-\\>/g,\"\");var matches=href.match(/^([a-zA-Z]+)\\:/);if(!matches){return false}var scheme=matches[1].toLowerCase();if(has(options.allowedSchemesByTag,name)){return options.allowedSchemesByTag[name].indexOf(scheme)===-1}return!options.allowedSchemes||options.allowedSchemes.indexOf(scheme)===-1}function filterClasses(classes,allowed){if(!allowed){return classes}classes=classes.split(/\\s+/);return classes.filter(function(clss){return allowed.indexOf(clss)!==-1}).join(\" \")}}var htmlParserDefaults={decodeEntities:true};sanitizeHtml.defaults={allowedTags:[\"h3\",\"h4\",\"h5\",\"h6\",\"blockquote\",\"p\",\"a\",\"ul\",\"ol\",\"nl\",\"li\",\"b\",\"i\",\"strong\",\"em\",\"strike\",\"code\",\"hr\",\"br\",\"div\",\"table\",\"thead\",\"caption\",\"tbody\",\"tr\",\"th\",\"td\",\"pre\"],allowedAttributes:{a:[\"href\",\"name\",\"target\"],img:[\"src\"]},selfClosing:[\"img\",\"br\",\"hr\",\"area\",\"base\",\"basefont\",\"input\",\"link\",\"meta\"],allowedSchemes:[\"http\",\"https\",\"ftp\",\"mailto\"],allowedSchemesByTag:{}};sanitizeHtml.simpleTransform=function(newTagName,newAttribs,merge){merge=merge===undefined?true:merge;newAttribs=newAttribs||{};return function(tagName,attribs){var attrib;if(merge){for(attrib in newAttribs){attribs[attrib]=newAttribs[attrib]}}else{attribs=newAttribs}return{tagName:newTagName,attribs:attribs}}}},{htmlparser2:36,\"regexp-quote\":54,xtend:58}],2:[function(require,module,exports){\"use strict\";exports.toByteArray=toByteArray;exports.fromByteArray=fromByteArray;var lookup=[];var revLookup=[];var Arr=typeof Uint8Array!==\"undefined\"?Uint8Array:Array;function init(){var code=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";for(var i=0,len=code.length;i<len;++i){lookup[i]=code[i];revLookup[code.charCodeAt(i)]=i}revLookup[\"-\".charCodeAt(0)]=62;revLookup[\"_\".charCodeAt(0)]=63}init();function toByteArray(b64){var i,j,l,tmp,placeHolders,arr;var len=b64.length;if(len%4>0){throw new Error(\"Invalid string. Length must be a multiple of 4\")}placeHolders=b64[len-2]===\"=\"?2:b64[len-1]===\"=\"?1:0;arr=new Arr(len*3/4-placeHolders);l=placeHolders>0?len-4:len;var L=0;for(i=0,j=0;i<l;i+=4,j+=3){tmp=revLookup[b64.charCodeAt(i)]<<18|revLookup[b64.charCodeAt(i+1)]<<12|revLookup[b64.charCodeAt(i+2)]<<6|revLookup[b64.charCodeAt(i+3)];arr[L++]=tmp>>16&255;arr[L++]=tmp>>8&255;arr[L++]=tmp&255}if(placeHolders===2){tmp=revLookup[b64.charCodeAt(i)]<<2|revLookup[b64.charCodeAt(i+1)]>>4;arr[L++]=tmp&255}else if(placeHolders===1){tmp=revLookup[b64.charCodeAt(i)]<<10|revLookup[b64.charCodeAt(i+1)]<<4|revLookup[b64.charCodeAt(i+2)]>>2;arr[L++]=tmp>>8&255;arr[L++]=tmp&255}return arr}function tripletToBase64(num){return lookup[num>>18&63]+lookup[num>>12&63]+lookup[num>>6&63]+lookup[num&63]}function encodeChunk(uint8,start,end){var tmp;var output=[];for(var i=start;i<end;i+=3){tmp=(uint8[i]<<16)+(uint8[i+1]<<8)+uint8[i+2];output.push(tripletToBase64(tmp))}return output.join(\"\")}function fromByteArray(uint8){var tmp;var len=uint8.length;var extraBytes=len%3;var output=\"\";var parts=[];var maxChunkLength=16383;for(var i=0,len2=len-extraBytes;i<len2;i+=maxChunkLength){parts.push(encodeChunk(uint8,i,i+maxChunkLength>len2?len2:i+maxChunkLength))}if(extraBytes===1){tmp=uint8[len-1];output+=lookup[tmp>>2];output+=lookup[tmp<<4&63];output+=\"==\"}else if(extraBytes===2){tmp=(uint8[len-2]<<8)+uint8[len-1];output+=lookup[tmp>>10];output+=lookup[tmp>>4&63];output+=lookup[tmp<<2&63];output+=\"=\"}parts.push(output);return parts.join(\"\")}},{}],3:[function(require,module,exports){},{}],4:[function(require,module,exports){(function(global){\"use strict\";var buffer=require(\"buffer\");var Buffer=buffer.Buffer;var SlowBuffer=buffer.SlowBuffer;var MAX_LEN=buffer.kMaxLength||2147483647;exports.alloc=function alloc(size,fill,encoding){if(typeof Buffer.alloc===\"function\"){return Buffer.alloc(size,fill,encoding)}if(typeof encoding===\"number\"){throw new TypeError(\"encoding must not be number\")}if(typeof size!==\"number\"){throw new TypeError(\"size must be a number\")}if(size>MAX_LEN){throw new RangeError(\"size is too large\")}var enc=encoding;var _fill=fill;if(_fill===undefined){enc=undefined;_fill=0}var buf=new Buffer(size);if(typeof _fill===\"string\"){var fillBuf=new Buffer(_fill,enc);var flen=fillBuf.length;var i=-1;while(++i<size){buf[i]=fillBuf[i%flen]}}else{buf.fill(_fill)}return buf};exports.allocUnsafe=function allocUnsafe(size){if(typeof Buffer.allocUnsafe===\"function\"){return Buffer.allocUnsafe(size)}if(typeof size!==\"number\"){throw new TypeError(\"size must be a number\")}if(size>MAX_LEN){throw new RangeError(\"size is too large\")}return new Buffer(size)};exports.from=function from(value,encodingOrOffset,length){if(typeof Buffer.from===\"function\"&&(!global.Uint8Array||Uint8Array.from!==Buffer.from)){return Buffer.from(value,encodingOrOffset,length)}if(typeof value===\"number\"){throw new TypeError('\"value\" argument must not be a number')}if(typeof value===\"string\"){return new Buffer(value,encodingOrOffset)}if(typeof ArrayBuffer!==\"undefined\"&&value instanceof ArrayBuffer){var offset=encodingOrOffset;if(arguments.length===1){return new Buffer(value)}if(typeof offset===\"undefined\"){offset=0}var len=length;if(typeof len===\"undefined\"){len=value.byteLength-offset}if(offset>=value.byteLength){throw new RangeError(\"'offset' is out of bounds\")}if(len>value.byteLength-offset){throw new RangeError(\"'length' is out of bounds\")}return new Buffer(value.slice(offset,offset+len))}if(Buffer.isBuffer(value)){var out=new Buffer(value.length);value.copy(out,0,0,value.length);return out}if(value){if(Array.isArray(value)||typeof ArrayBuffer!==\"undefined\"&&value.buffer instanceof ArrayBuffer||\"length\"in value){return new Buffer(value)}if(value.type===\"Buffer\"&&Array.isArray(value.data)){return new Buffer(value.data)}}throw new TypeError(\"First argument must be a string, Buffer, \"+\"ArrayBuffer, Array, or array-like object.\")};exports.allocUnsafeSlow=function allocUnsafeSlow(size){if(typeof Buffer.allocUnsafeSlow===\"function\"){return Buffer.allocUnsafeSlow(size)}if(typeof size!==\"number\"){throw new TypeError(\"size must be a number\")}if(size>=MAX_LEN){throw new RangeError(\"size is too large\")}return new SlowBuffer(size)}}).call(this,typeof global!==\"undefined\"?global:typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{buffer:5}],5:[function(require,module,exports){(function(global){\"use strict\";var base64=require(\"base64-js\");var ieee754=require(\"ieee754\");var isArray=require(\"isarray\");exports.Buffer=Buffer;exports.SlowBuffer=SlowBuffer;exports.INSPECT_MAX_BYTES=50;Buffer.TYPED_ARRAY_SUPPORT=global.TYPED_ARRAY_SUPPORT!==undefined?global.TYPED_ARRAY_SUPPORT:typedArraySupport();exports.kMaxLength=kMaxLength();function typedArraySupport(){try{var arr=new Uint8Array(1);arr.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}};return arr.foo()===42&&typeof arr.subarray===\"function\"&&arr.subarray(1,1).byteLength===0}catch(e){return false}}function kMaxLength(){return Buffer.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function createBuffer(that,length){if(kMaxLength()<length){throw new RangeError(\"Invalid typed array length\")}if(Buffer.TYPED_ARRAY_SUPPORT){that=new Uint8Array(length);that.__proto__=Buffer.prototype}else{if(that===null){that=new Buffer(length)}that.length=length}return that}function Buffer(arg,encodingOrOffset,length){if(!Buffer.TYPED_ARRAY_SUPPORT&&!(this instanceof Buffer)){return new Buffer(arg,encodingOrOffset,length)}if(typeof arg===\"number\"){if(typeof encodingOrOffset===\"string\"){throw new Error(\"If encoding is specified then the first argument must be a string\")}return allocUnsafe(this,arg)}return from(this,arg,encodingOrOffset,length)}Buffer.poolSize=8192;Buffer._augment=function(arr){arr.__proto__=Buffer.prototype;return arr};function from(that,value,encodingOrOffset,length){if(typeof value===\"number\"){throw new TypeError('\"value\" argument must not be a number')}if(typeof ArrayBuffer!==\"undefined\"&&value instanceof ArrayBuffer){return fromArrayBuffer(that,value,encodingOrOffset,length)}if(typeof value===\"string\"){return fromString(that,value,encodingOrOffset)}return fromObject(that,value)}Buffer.from=function(value,encodingOrOffset,length){return from(null,value,encodingOrOffset,length)};if(Buffer.TYPED_ARRAY_SUPPORT){Buffer.prototype.__proto__=Uint8Array.prototype;Buffer.__proto__=Uint8Array;if(typeof Symbol!==\"undefined\"&&Symbol.species&&Buffer[Symbol.species]===Buffer){Object.defineProperty(Buffer,Symbol.species,{value:null,configurable:true})}}function assertSize(size){if(typeof size!==\"number\"){throw new TypeError('\"size\" argument must be a number')}else if(size<0){throw new RangeError('\"size\" argument must not be negative')}}function alloc(that,size,fill,encoding){assertSize(size);if(size<=0){return createBuffer(that,size)}if(fill!==undefined){return typeof encoding===\"string\"?createBuffer(that,size).fill(fill,encoding):createBuffer(that,size).fill(fill)}return createBuffer(that,size)}Buffer.alloc=function(size,fill,encoding){return alloc(null,size,fill,encoding)};function allocUnsafe(that,size){assertSize(size);that=createBuffer(that,size<0?0:checked(size)|0);if(!Buffer.TYPED_ARRAY_SUPPORT){for(var i=0;i<size;++i){that[i]=0}}return that}Buffer.allocUnsafe=function(size){return allocUnsafe(null,size)};Buffer.allocUnsafeSlow=function(size){return allocUnsafe(null,size)};function fromString(that,string,encoding){if(typeof encoding!==\"string\"||encoding===\"\"){encoding=\"utf8\"}if(!Buffer.isEncoding(encoding)){throw new TypeError('\"encoding\" must be a valid string encoding')}var length=byteLength(string,encoding)|0;that=createBuffer(that,length);var actual=that.write(string,encoding);if(actual!==length){that=that.slice(0,actual)}return that}function fromArrayLike(that,array){var length=array.length<0?0:checked(array.length)|0;that=createBuffer(that,length);for(var i=0;i<length;i+=1){that[i]=array[i]&255}return that}function fromArrayBuffer(that,array,byteOffset,length){array.byteLength;if(byteOffset<0||array.byteLength<byteOffset){throw new RangeError(\"'offset' is out of bounds\")}if(array.byteLength<byteOffset+(length||0)){throw new RangeError(\"'length' is out of bounds\")}if(byteOffset===undefined&&length===undefined){array=new Uint8Array(array)}else if(length===undefined){array=new Uint8Array(array,byteOffset)}else{array=new Uint8Array(array,byteOffset,length)}if(Buffer.TYPED_ARRAY_SUPPORT){that=array;that.__proto__=Buffer.prototype}else{that=fromArrayLike(that,array)}return that}function fromObject(that,obj){if(Buffer.isBuffer(obj)){var len=checked(obj.length)|0;that=createBuffer(that,len);if(that.length===0){return that}obj.copy(that,0,0,len);return that}if(obj){if(typeof ArrayBuffer!==\"undefined\"&&obj.buffer instanceof ArrayBuffer||\"length\"in obj){if(typeof obj.length!==\"number\"||isnan(obj.length)){return createBuffer(that,0)}return fromArrayLike(that,obj)}if(obj.type===\"Buffer\"&&isArray(obj.data)){return fromArrayLike(that,obj.data)}}throw new TypeError(\"First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.\")}function checked(length){if(length>=kMaxLength()){throw new RangeError(\"Attempt to allocate Buffer larger than maximum \"+\"size: 0x\"+kMaxLength().toString(16)+\" bytes\")}return length|0}function SlowBuffer(length){if(+length!=length){length=0}return Buffer.alloc(+length)}Buffer.isBuffer=function isBuffer(b){return!!(b!=null&&b._isBuffer)};Buffer.compare=function compare(a,b){if(!Buffer.isBuffer(a)||!Buffer.isBuffer(b)){throw new TypeError(\"Arguments must be Buffers\")}if(a===b)return 0;var x=a.length;var y=b.length;for(var i=0,len=Math.min(x,y);i<len;++i){if(a[i]!==b[i]){x=a[i];y=b[i];break}}if(x<y)return-1;if(y<x)return 1;return 0};Buffer.isEncoding=function isEncoding(encoding){switch(String(encoding).toLowerCase()){case\"hex\":case\"utf8\":case\"utf-8\":case\"ascii\":case\"latin1\":case\"binary\":case\"base64\":case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return true;default:return false}};Buffer.concat=function concat(list,length){if(!isArray(list)){throw new TypeError('\"list\" argument must be an Array of Buffers')}if(list.length===0){return Buffer.alloc(0)}var i;if(length===undefined){length=0;for(i=0;i<list.length;++i){length+=list[i].length}}var buffer=Buffer.allocUnsafe(length);var pos=0;for(i=0;i<list.length;++i){var buf=list[i];if(!Buffer.isBuffer(buf)){throw new TypeError('\"list\" argument must be an Array of Buffers')}buf.copy(buffer,pos);pos+=buf.length}return buffer};function byteLength(string,encoding){if(Buffer.isBuffer(string)){return string.length}if(typeof ArrayBuffer!==\"undefined\"&&typeof ArrayBuffer.isView===\"function\"&&(ArrayBuffer.isView(string)||string instanceof ArrayBuffer)){return string.byteLength}if(typeof string!==\"string\"){string=\"\"+string}var len=string.length;if(len===0)return 0;var loweredCase=false;for(;;){switch(encoding){case\"ascii\":case\"latin1\":case\"binary\":return len;case\"utf8\":case\"utf-8\":case undefined:return utf8ToBytes(string).length;case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return len*2;case\"hex\":return len>>>1;case\"base64\":return base64ToBytes(string).length;default:if(loweredCase)return utf8ToBytes(string).length;encoding=(\"\"+encoding).toLowerCase();loweredCase=true}}}Buffer.byteLength=byteLength;function slowToString(encoding,start,end){var loweredCase=false;if(start===undefined||start<0){start=0}if(start>this.length){return\"\"}if(end===undefined||end>this.length){end=this.length}if(end<=0){return\"\"}end>>>=0;start>>>=0;if(end<=start){return\"\"}if(!encoding)encoding=\"utf8\";while(true){switch(encoding){case\"hex\":return hexSlice(this,start,end);case\"utf8\":case\"utf-8\":return utf8Slice(this,start,end);case\"ascii\":return asciiSlice(this,start,end);case\"latin1\":case\"binary\":return latin1Slice(this,start,end);case\"base64\":return base64Slice(this,start,end);case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return utf16leSlice(this,start,end);default:if(loweredCase)throw new TypeError(\"Unknown encoding: \"+encoding);encoding=(encoding+\"\").toLowerCase();loweredCase=true}}}Buffer.prototype._isBuffer=true;function swap(b,n,m){var i=b[n];b[n]=b[m];b[m]=i}Buffer.prototype.swap16=function swap16(){var len=this.length;if(len%2!==0){throw new RangeError(\"Buffer size must be a multiple of 16-bits\")}for(var i=0;i<len;i+=2){swap(this,i,i+1)}return this};Buffer.prototype.swap32=function swap32(){var len=this.length;if(len%4!==0){throw new RangeError(\"Buffer size must be a multiple of 32-bits\")}for(var i=0;i<len;i+=4){swap(this,i,i+3);swap(this,i+1,i+2)}return this};Buffer.prototype.swap64=function swap64(){var len=this.length;if(len%8!==0){throw new RangeError(\"Buffer size must be a multiple of 64-bits\")}for(var i=0;i<len;i+=8){swap(this,i,i+7);swap(this,i+1,i+6);swap(this,i+2,i+5);swap(this,i+3,i+4)}return this};Buffer.prototype.toString=function toString(){var length=this.length|0;if(length===0)return\"\";if(arguments.length===0)return utf8Slice(this,0,length);return slowToString.apply(this,arguments)};Buffer.prototype.equals=function equals(b){if(!Buffer.isBuffer(b))throw new TypeError(\"Argument must be a Buffer\");if(this===b)return true;return Buffer.compare(this,b)===0};Buffer.prototype.inspect=function inspect(){var str=\"\";var max=exports.INSPECT_MAX_BYTES;if(this.length>0){str=this.toString(\"hex\",0,max).match(/.{2}/g).join(\" \");if(this.length>max)str+=\" ... \"}return\"<Buffer \"+str+\">\"};Buffer.prototype.compare=function compare(target,start,end,thisStart,thisEnd){if(!Buffer.isBuffer(target)){throw new TypeError(\"Argument must be a Buffer\")}if(start===undefined){start=0}if(end===undefined){end=target?target.length:0}if(thisStart===undefined){thisStart=0}if(thisEnd===undefined){thisEnd=this.length}if(start<0||end>target.length||thisStart<0||thisEnd>this.length){throw new RangeError(\"out of range index\")}if(thisStart>=thisEnd&&start>=end){return 0}if(thisStart>=thisEnd){return-1}if(start>=end){return 1}start>>>=0;end>>>=0;thisStart>>>=0;thisEnd>>>=0;if(this===target)return 0;var x=thisEnd-thisStart;var y=end-start;var len=Math.min(x,y);var thisCopy=this.slice(thisStart,thisEnd);var targetCopy=target.slice(start,end);for(var i=0;i<len;++i){if(thisCopy[i]!==targetCopy[i]){x=thisCopy[i];y=targetCopy[i];break}}if(x<y)return-1;if(y<x)return 1;return 0};function bidirectionalIndexOf(buffer,val,byteOffset,encoding,dir){if(buffer.length===0)return-1;if(typeof byteOffset===\"string\"){encoding=byteOffset;byteOffset=0}else if(byteOffset>2147483647){byteOffset=2147483647}else if(byteOffset<-2147483648){byteOffset=-2147483648}byteOffset=+byteOffset;if(isNaN(byteOffset)){byteOffset=dir?0:buffer.length-1}if(byteOffset<0)byteOffset=buffer.length+byteOffset;if(byteOffset>=buffer.length){if(dir)return-1;else byteOffset=buffer.length-1}else if(byteOffset<0){if(dir)byteOffset=0;else return-1}if(typeof val===\"string\"){val=Buffer.from(val,encoding)}if(Buffer.isBuffer(val)){if(val.length===0){return-1}return arrayIndexOf(buffer,val,byteOffset,encoding,dir)}else if(typeof val===\"number\"){val=val&255;if(Buffer.TYPED_ARRAY_SUPPORT&&typeof Uint8Array.prototype.indexOf===\"function\"){if(dir){return Uint8Array.prototype.indexOf.call(buffer,val,byteOffset)}else{return Uint8Array.prototype.lastIndexOf.call(buffer,val,byteOffset)}}return arrayIndexOf(buffer,[val],byteOffset,encoding,dir)}throw new TypeError(\"val must be string, number or Buffer\")}function arrayIndexOf(arr,val,byteOffset,encoding,dir){var indexSize=1;var arrLength=arr.length;var valLength=val.length;if(encoding!==undefined){encoding=String(encoding).toLowerCase();if(encoding===\"ucs2\"||encoding===\"ucs-2\"||encoding===\"utf16le\"||encoding===\"utf-16le\"){if(arr.length<2||val.length<2){return-1}indexSize=2;arrLength/=2;valLength/=2;byteOffset/=2}}function read(buf,i){if(indexSize===1){return buf[i]}else{return buf.readUInt16BE(i*indexSize)}}var i;if(dir){var foundIndex=-1;for(i=byteOffset;i<arrLength;i++){if(read(arr,i)===read(val,foundIndex===-1?0:i-foundIndex)){if(foundIndex===-1)foundIndex=i;if(i-foundIndex+1===valLength)return foundIndex*indexSize}else{if(foundIndex!==-1)i-=i-foundIndex;foundIndex=-1}}}else{if(byteOffset+valLength>arrLength)byteOffset=arrLength-valLength;for(i=byteOffset;i>=0;i--){var found=true;for(var j=0;j<valLength;j++){if(read(arr,i+j)!==read(val,j)){found=false;break}}if(found)return i}}return-1}Buffer.prototype.includes=function includes(val,byteOffset,encoding){return this.indexOf(val,byteOffset,encoding)!==-1};Buffer.prototype.indexOf=function indexOf(val,byteOffset,encoding){return bidirectionalIndexOf(this,val,byteOffset,encoding,true)};Buffer.prototype.lastIndexOf=function lastIndexOf(val,byteOffset,encoding){return bidirectionalIndexOf(this,val,byteOffset,encoding,false)};function hexWrite(buf,string,offset,length){offset=Number(offset)||0;var remaining=buf.length-offset;if(!length){length=remaining}else{length=Number(length);if(length>remaining){length=remaining}}var strLen=string.length;if(strLen%2!==0)throw new TypeError(\"Invalid hex string\");if(length>strLen/2){length=strLen/2}for(var i=0;i<length;++i){var parsed=parseInt(string.substr(i*2,2),16);if(isNaN(parsed))return i;buf[offset+i]=parsed}return i}function utf8Write(buf,string,offset,length){return blitBuffer(utf8ToBytes(string,buf.length-offset),buf,offset,length)}function asciiWrite(buf,string,offset,length){return blitBuffer(asciiToBytes(string),buf,offset,length)}function latin1Write(buf,string,offset,length){return asciiWrite(buf,string,offset,length)}function base64Write(buf,string,offset,length){return blitBuffer(base64ToBytes(string),buf,offset,length)}function ucs2Write(buf,string,offset,length){return blitBuffer(utf16leToBytes(string,buf.length-offset),buf,offset,length)}Buffer.prototype.write=function write(string,offset,length,encoding){if(offset===undefined){encoding=\"utf8\";length=this.length;offset=0}else if(length===undefined&&typeof offset===\"string\"){encoding=offset;length=this.length;offset=0}else if(isFinite(offset)){offset=offset|0;if(isFinite(length)){length=length|0;if(encoding===undefined)encoding=\"utf8\"}else{encoding=length;length=undefined}}else{throw new Error(\"Buffer.write(string, encoding, offset[, length]) is no longer supported\")}var remaining=this.length-offset;if(length===undefined||length>remaining)length=remaining;if(string.length>0&&(length<0||offset<0)||offset>this.length){throw new RangeError(\"Attempt to write outside buffer bounds\")}if(!encoding)encoding=\"utf8\";var loweredCase=false;for(;;){switch(encoding){case\"hex\":return hexWrite(this,string,offset,length);case\"utf8\":case\"utf-8\":return utf8Write(this,string,offset,length);case\"ascii\":return asciiWrite(this,string,offset,length);case\"latin1\":case\"binary\":return latin1Write(this,string,offset,length);case\"base64\":return base64Write(this,string,offset,length);case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":return ucs2Write(this,string,offset,length);default:if(loweredCase)throw new TypeError(\"Unknown encoding: \"+encoding);encoding=(\"\"+encoding).toLowerCase();loweredCase=true}}};Buffer.prototype.toJSON=function toJSON(){return{type:\"Buffer\",data:Array.prototype.slice.call(this._arr||this,0)}};function base64Slice(buf,start,end){if(start===0&&end===buf.length){return base64.fromByteArray(buf)}else{return base64.fromByteArray(buf.slice(start,end))}}function utf8Slice(buf,start,end){end=Math.min(buf.length,end);var res=[];var i=start;while(i<end){var firstByte=buf[i];var codePoint=null;var bytesPerSequence=firstByte>239?4:firstByte>223?3:firstByte>191?2:1;if(i+bytesPerSequence<=end){var secondByte,thirdByte,fourthByte,tempCodePoint;switch(bytesPerSequence){case 1:if(firstByte<128){codePoint=firstByte}break;case 2:secondByte=buf[i+1];if((secondByte&192)===128){tempCodePoint=(firstByte&31)<<6|secondByte&63;if(tempCodePoint>127){codePoint=tempCodePoint}}break;case 3:secondByte=buf[i+1];thirdByte=buf[i+2];if((secondByte&192)===128&&(thirdByte&192)===128){tempCodePoint=(firstByte&15)<<12|(secondByte&63)<<6|thirdByte&63;if(tempCodePoint>2047&&(tempCodePoint<55296||tempCodePoint>57343)){codePoint=tempCodePoint}}break;case 4:secondByte=buf[i+1];thirdByte=buf[i+2];fourthByte=buf[i+3];if((secondByte&192)===128&&(thirdByte&192)===128&&(fourthByte&192)===128){tempCodePoint=(firstByte&15)<<18|(secondByte&63)<<12|(thirdByte&63)<<6|fourthByte&63;if(tempCodePoint>65535&&tempCodePoint<1114112){codePoint=tempCodePoint}}}}if(codePoint===null){codePoint=65533;bytesPerSequence=1}else if(codePoint>65535){codePoint-=65536;res.push(codePoint>>>10&1023|55296);codePoint=56320|codePoint&1023}res.push(codePoint);i+=bytesPerSequence}return decodeCodePointsArray(res)}var MAX_ARGUMENTS_LENGTH=4096;function decodeCodePointsArray(codePoints){var len=codePoints.length;if(len<=MAX_ARGUMENTS_LENGTH){return String.fromCharCode.apply(String,codePoints)}var res=\"\";var i=0;while(i<len){res+=String.fromCharCode.apply(String,codePoints.slice(i,i+=MAX_ARGUMENTS_LENGTH))}return res}function asciiSlice(buf,start,end){var ret=\"\";end=Math.min(buf.length,end);for(var i=start;i<end;++i){ret+=String.fromCharCode(buf[i]&127)}return ret}function latin1Slice(buf,start,end){var ret=\"\";end=Math.min(buf.length,end);for(var i=start;i<end;++i){ret+=String.fromCharCode(buf[i])}return ret}function hexSlice(buf,start,end){var len=buf.length;if(!start||start<0)start=0;if(!end||end<0||end>len)end=len;var out=\"\";for(var i=start;i<end;++i){out+=toHex(buf[i])}return out}function utf16leSlice(buf,start,end){var bytes=buf.slice(start,end);var res=\"\";for(var i=0;i<bytes.length;i+=2){res+=String.fromCharCode(bytes[i]+bytes[i+1]*256)}return res}Buffer.prototype.slice=function slice(start,end){var len=this.length;start=~~start;end=end===undefined?len:~~end;if(start<0){start+=len;if(start<0)start=0}else if(start>len){start=len}if(end<0){end+=len;if(end<0)end=0}else if(end>len){end=len}if(end<start)end=start;var newBuf;if(Buffer.TYPED_ARRAY_SUPPORT){newBuf=this.subarray(start,end);newBuf.__proto__=Buffer.prototype}else{var sliceLen=end-start;newBuf=new Buffer(sliceLen,undefined);for(var i=0;i<sliceLen;++i){newBuf[i]=this[i+start]}}return newBuf};function checkOffset(offset,ext,length){if(offset%1!==0||offset<0)throw new RangeError(\"offset is not uint\");if(offset+ext>length)throw new RangeError(\"Trying to access beyond buffer length\")}Buffer.prototype.readUIntLE=function readUIntLE(offset,byteLength,noAssert){offset=offset|0;byteLength=byteLength|0;if(!noAssert)checkOffset(offset,byteLength,this.length);var val=this[offset];var mul=1;var i=0;while(++i<byteLength&&(mul*=256)){val+=this[offset+i]*mul}return val};Buffer.prototype.readUIntBE=function readUIntBE(offset,byteLength,noAssert){offset=offset|0;byteLength=byteLength|0;if(!noAssert){checkOffset(offset,byteLength,this.length)}var val=this[offset+--byteLength];var mul=1;while(byteLength>0&&(mul*=256)){val+=this[offset+--byteLength]*mul}return val};Buffer.prototype.readUInt8=function readUInt8(offset,noAssert){if(!noAssert)checkOffset(offset,1,this.length);return this[offset]};Buffer.prototype.readUInt16LE=function readUInt16LE(offset,noAssert){if(!noAssert)checkOffset(offset,2,this.length);return this[offset]|this[offset+1]<<8};Buffer.prototype.readUInt16BE=function readUInt16BE(offset,noAssert){if(!noAssert)checkOffset(offset,2,this.length);return this[offset]<<8|this[offset+1]};Buffer.prototype.readUInt32LE=function readUInt32LE(offset,noAssert){if(!noAssert)checkOffset(offset,4,this.length);return(this[offset]|this[offset+1]<<8|this[offset+2]<<16)+this[offset+3]*16777216};Buffer.prototype.readUInt32BE=function readUInt32BE(offset,noAssert){if(!noAssert)checkOffset(offset,4,this.length);return this[offset]*16777216+(this[offset+1]<<16|this[offset+2]<<8|this[offset+3])};Buffer.prototype.readIntLE=function readIntLE(offset,byteLength,noAssert){offset=offset|0;byteLength=byteLength|0;if(!noAssert)checkOffset(offset,byteLength,this.length);var val=this[offset];var mul=1;var i=0;while(++i<byteLength&&(mul*=256)){val+=this[offset+i]*mul}mul*=128;if(val>=mul)val-=Math.pow(2,8*byteLength);return val};Buffer.prototype.readIntBE=function readIntBE(offset,byteLength,noAssert){offset=offset|0;byteLength=byteLength|0;if(!noAssert)checkOffset(offset,byteLength,this.length);\nvar i=byteLength;var mul=1;var val=this[offset+--i];while(i>0&&(mul*=256)){val+=this[offset+--i]*mul}mul*=128;if(val>=mul)val-=Math.pow(2,8*byteLength);return val};Buffer.prototype.readInt8=function readInt8(offset,noAssert){if(!noAssert)checkOffset(offset,1,this.length);if(!(this[offset]&128))return this[offset];return(255-this[offset]+1)*-1};Buffer.prototype.readInt16LE=function readInt16LE(offset,noAssert){if(!noAssert)checkOffset(offset,2,this.length);var val=this[offset]|this[offset+1]<<8;return val&32768?val|4294901760:val};Buffer.prototype.readInt16BE=function readInt16BE(offset,noAssert){if(!noAssert)checkOffset(offset,2,this.length);var val=this[offset+1]|this[offset]<<8;return val&32768?val|4294901760:val};Buffer.prototype.readInt32LE=function readInt32LE(offset,noAssert){if(!noAssert)checkOffset(offset,4,this.length);return this[offset]|this[offset+1]<<8|this[offset+2]<<16|this[offset+3]<<24};Buffer.prototype.readInt32BE=function readInt32BE(offset,noAssert){if(!noAssert)checkOffset(offset,4,this.length);return this[offset]<<24|this[offset+1]<<16|this[offset+2]<<8|this[offset+3]};Buffer.prototype.readFloatLE=function readFloatLE(offset,noAssert){if(!noAssert)checkOffset(offset,4,this.length);return ieee754.read(this,offset,true,23,4)};Buffer.prototype.readFloatBE=function readFloatBE(offset,noAssert){if(!noAssert)checkOffset(offset,4,this.length);return ieee754.read(this,offset,false,23,4)};Buffer.prototype.readDoubleLE=function readDoubleLE(offset,noAssert){if(!noAssert)checkOffset(offset,8,this.length);return ieee754.read(this,offset,true,52,8)};Buffer.prototype.readDoubleBE=function readDoubleBE(offset,noAssert){if(!noAssert)checkOffset(offset,8,this.length);return ieee754.read(this,offset,false,52,8)};function checkInt(buf,value,offset,ext,max,min){if(!Buffer.isBuffer(buf))throw new TypeError('\"buffer\" argument must be a Buffer instance');if(value>max||value<min)throw new RangeError('\"value\" argument is out of bounds');if(offset+ext>buf.length)throw new RangeError(\"Index out of range\")}Buffer.prototype.writeUIntLE=function writeUIntLE(value,offset,byteLength,noAssert){value=+value;offset=offset|0;byteLength=byteLength|0;if(!noAssert){var maxBytes=Math.pow(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0)}var mul=1;var i=0;this[offset]=value&255;while(++i<byteLength&&(mul*=256)){this[offset+i]=value/mul&255}return offset+byteLength};Buffer.prototype.writeUIntBE=function writeUIntBE(value,offset,byteLength,noAssert){value=+value;offset=offset|0;byteLength=byteLength|0;if(!noAssert){var maxBytes=Math.pow(2,8*byteLength)-1;checkInt(this,value,offset,byteLength,maxBytes,0)}var i=byteLength-1;var mul=1;this[offset+i]=value&255;while(--i>=0&&(mul*=256)){this[offset+i]=value/mul&255}return offset+byteLength};Buffer.prototype.writeUInt8=function writeUInt8(value,offset,noAssert){value=+value;offset=offset|0;if(!noAssert)checkInt(this,value,offset,1,255,0);if(!Buffer.TYPED_ARRAY_SUPPORT)value=Math.floor(value);this[offset]=value&255;return offset+1};function objectWriteUInt16(buf,value,offset,littleEndian){if(value<0)value=65535+value+1;for(var i=0,j=Math.min(buf.length-offset,2);i<j;++i){buf[offset+i]=(value&255<<8*(littleEndian?i:1-i))>>>(littleEndian?i:1-i)*8}}Buffer.prototype.writeUInt16LE=function writeUInt16LE(value,offset,noAssert){value=+value;offset=offset|0;if(!noAssert)checkInt(this,value,offset,2,65535,0);if(Buffer.TYPED_ARRAY_SUPPORT){this[offset]=value&255;this[offset+1]=value>>>8}else{objectWriteUInt16(this,value,offset,true)}return offset+2};Buffer.prototype.writeUInt16BE=function writeUInt16BE(value,offset,noAssert){value=+value;offset=offset|0;if(!noAssert)checkInt(this,value,offset,2,65535,0);if(Buffer.TYPED_ARRAY_SUPPORT){this[offset]=value>>>8;this[offset+1]=value&255}else{objectWriteUInt16(this,value,offset,false)}return offset+2};function objectWriteUInt32(buf,value,offset,littleEndian){if(value<0)value=4294967295+value+1;for(var i=0,j=Math.min(buf.length-offset,4);i<j;++i){buf[offset+i]=value>>>(littleEndian?i:3-i)*8&255}}Buffer.prototype.writeUInt32LE=function writeUInt32LE(value,offset,noAssert){value=+value;offset=offset|0;if(!noAssert)checkInt(this,value,offset,4,4294967295,0);if(Buffer.TYPED_ARRAY_SUPPORT){this[offset+3]=value>>>24;this[offset+2]=value>>>16;this[offset+1]=value>>>8;this[offset]=value&255}else{objectWriteUInt32(this,value,offset,true)}return offset+4};Buffer.prototype.writeUInt32BE=function writeUInt32BE(value,offset,noAssert){value=+value;offset=offset|0;if(!noAssert)checkInt(this,value,offset,4,4294967295,0);if(Buffer.TYPED_ARRAY_SUPPORT){this[offset]=value>>>24;this[offset+1]=value>>>16;this[offset+2]=value>>>8;this[offset+3]=value&255}else{objectWriteUInt32(this,value,offset,false)}return offset+4};Buffer.prototype.writeIntLE=function writeIntLE(value,offset,byteLength,noAssert){value=+value;offset=offset|0;if(!noAssert){var limit=Math.pow(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit)}var i=0;var mul=1;var sub=0;this[offset]=value&255;while(++i<byteLength&&(mul*=256)){if(value<0&&sub===0&&this[offset+i-1]!==0){sub=1}this[offset+i]=(value/mul>>0)-sub&255}return offset+byteLength};Buffer.prototype.writeIntBE=function writeIntBE(value,offset,byteLength,noAssert){value=+value;offset=offset|0;if(!noAssert){var limit=Math.pow(2,8*byteLength-1);checkInt(this,value,offset,byteLength,limit-1,-limit)}var i=byteLength-1;var mul=1;var sub=0;this[offset+i]=value&255;while(--i>=0&&(mul*=256)){if(value<0&&sub===0&&this[offset+i+1]!==0){sub=1}this[offset+i]=(value/mul>>0)-sub&255}return offset+byteLength};Buffer.prototype.writeInt8=function writeInt8(value,offset,noAssert){value=+value;offset=offset|0;if(!noAssert)checkInt(this,value,offset,1,127,-128);if(!Buffer.TYPED_ARRAY_SUPPORT)value=Math.floor(value);if(value<0)value=255+value+1;this[offset]=value&255;return offset+1};Buffer.prototype.writeInt16LE=function writeInt16LE(value,offset,noAssert){value=+value;offset=offset|0;if(!noAssert)checkInt(this,value,offset,2,32767,-32768);if(Buffer.TYPED_ARRAY_SUPPORT){this[offset]=value&255;this[offset+1]=value>>>8}else{objectWriteUInt16(this,value,offset,true)}return offset+2};Buffer.prototype.writeInt16BE=function writeInt16BE(value,offset,noAssert){value=+value;offset=offset|0;if(!noAssert)checkInt(this,value,offset,2,32767,-32768);if(Buffer.TYPED_ARRAY_SUPPORT){this[offset]=value>>>8;this[offset+1]=value&255}else{objectWriteUInt16(this,value,offset,false)}return offset+2};Buffer.prototype.writeInt32LE=function writeInt32LE(value,offset,noAssert){value=+value;offset=offset|0;if(!noAssert)checkInt(this,value,offset,4,2147483647,-2147483648);if(Buffer.TYPED_ARRAY_SUPPORT){this[offset]=value&255;this[offset+1]=value>>>8;this[offset+2]=value>>>16;this[offset+3]=value>>>24}else{objectWriteUInt32(this,value,offset,true)}return offset+4};Buffer.prototype.writeInt32BE=function writeInt32BE(value,offset,noAssert){value=+value;offset=offset|0;if(!noAssert)checkInt(this,value,offset,4,2147483647,-2147483648);if(value<0)value=4294967295+value+1;if(Buffer.TYPED_ARRAY_SUPPORT){this[offset]=value>>>24;this[offset+1]=value>>>16;this[offset+2]=value>>>8;this[offset+3]=value&255}else{objectWriteUInt32(this,value,offset,false)}return offset+4};function checkIEEE754(buf,value,offset,ext,max,min){if(offset+ext>buf.length)throw new RangeError(\"Index out of range\");if(offset<0)throw new RangeError(\"Index out of range\")}function writeFloat(buf,value,offset,littleEndian,noAssert){if(!noAssert){checkIEEE754(buf,value,offset,4,3.4028234663852886e38,-3.4028234663852886e38)}ieee754.write(buf,value,offset,littleEndian,23,4);return offset+4}Buffer.prototype.writeFloatLE=function writeFloatLE(value,offset,noAssert){return writeFloat(this,value,offset,true,noAssert)};Buffer.prototype.writeFloatBE=function writeFloatBE(value,offset,noAssert){return writeFloat(this,value,offset,false,noAssert)};function writeDouble(buf,value,offset,littleEndian,noAssert){if(!noAssert){checkIEEE754(buf,value,offset,8,1.7976931348623157e308,-1.7976931348623157e308)}ieee754.write(buf,value,offset,littleEndian,52,8);return offset+8}Buffer.prototype.writeDoubleLE=function writeDoubleLE(value,offset,noAssert){return writeDouble(this,value,offset,true,noAssert)};Buffer.prototype.writeDoubleBE=function writeDoubleBE(value,offset,noAssert){return writeDouble(this,value,offset,false,noAssert)};Buffer.prototype.copy=function copy(target,targetStart,start,end){if(!start)start=0;if(!end&&end!==0)end=this.length;if(targetStart>=target.length)targetStart=target.length;if(!targetStart)targetStart=0;if(end>0&&end<start)end=start;if(end===start)return 0;if(target.length===0||this.length===0)return 0;if(targetStart<0){throw new RangeError(\"targetStart out of bounds\")}if(start<0||start>=this.length)throw new RangeError(\"sourceStart out of bounds\");if(end<0)throw new RangeError(\"sourceEnd out of bounds\");if(end>this.length)end=this.length;if(target.length-targetStart<end-start){end=target.length-targetStart+start}var len=end-start;var i;if(this===target&&start<targetStart&&targetStart<end){for(i=len-1;i>=0;--i){target[i+targetStart]=this[i+start]}}else if(len<1e3||!Buffer.TYPED_ARRAY_SUPPORT){for(i=0;i<len;++i){target[i+targetStart]=this[i+start]}}else{Uint8Array.prototype.set.call(target,this.subarray(start,start+len),targetStart)}return len};Buffer.prototype.fill=function fill(val,start,end,encoding){if(typeof val===\"string\"){if(typeof start===\"string\"){encoding=start;start=0;end=this.length}else if(typeof end===\"string\"){encoding=end;end=this.length}if(val.length===1){var code=val.charCodeAt(0);if(code<256){val=code}}if(encoding!==undefined&&typeof encoding!==\"string\"){throw new TypeError(\"encoding must be a string\")}if(typeof encoding===\"string\"&&!Buffer.isEncoding(encoding)){throw new TypeError(\"Unknown encoding: \"+encoding)}}else if(typeof val===\"number\"){val=val&255}if(start<0||this.length<start||this.length<end){throw new RangeError(\"Out of range index\")}if(end<=start){return this}start=start>>>0;end=end===undefined?this.length:end>>>0;if(!val)val=0;var i;if(typeof val===\"number\"){for(i=start;i<end;++i){this[i]=val}}else{var bytes=Buffer.isBuffer(val)?val:utf8ToBytes(new Buffer(val,encoding).toString());var len=bytes.length;for(i=0;i<end-start;++i){this[i+start]=bytes[i%len]}}return this};var INVALID_BASE64_RE=/[^+\\/0-9A-Za-z-_]/g;function base64clean(str){str=stringtrim(str).replace(INVALID_BASE64_RE,\"\");if(str.length<2)return\"\";while(str.length%4!==0){str=str+\"=\"}return str}function stringtrim(str){if(str.trim)return str.trim();return str.replace(/^\\s+|\\s+$/g,\"\")}function toHex(n){if(n<16)return\"0\"+n.toString(16);return n.toString(16)}function utf8ToBytes(string,units){units=units||Infinity;var codePoint;var length=string.length;var leadSurrogate=null;var bytes=[];for(var i=0;i<length;++i){codePoint=string.charCodeAt(i);if(codePoint>55295&&codePoint<57344){if(!leadSurrogate){if(codePoint>56319){if((units-=3)>-1)bytes.push(239,191,189);continue}else if(i+1===length){if((units-=3)>-1)bytes.push(239,191,189);continue}leadSurrogate=codePoint;continue}if(codePoint<56320){if((units-=3)>-1)bytes.push(239,191,189);leadSurrogate=codePoint;continue}codePoint=(leadSurrogate-55296<<10|codePoint-56320)+65536}else if(leadSurrogate){if((units-=3)>-1)bytes.push(239,191,189)}leadSurrogate=null;if(codePoint<128){if((units-=1)<0)break;bytes.push(codePoint)}else if(codePoint<2048){if((units-=2)<0)break;bytes.push(codePoint>>6|192,codePoint&63|128)}else if(codePoint<65536){if((units-=3)<0)break;bytes.push(codePoint>>12|224,codePoint>>6&63|128,codePoint&63|128)}else if(codePoint<1114112){if((units-=4)<0)break;bytes.push(codePoint>>18|240,codePoint>>12&63|128,codePoint>>6&63|128,codePoint&63|128)}else{throw new Error(\"Invalid code point\")}}return bytes}function asciiToBytes(str){var byteArray=[];for(var i=0;i<str.length;++i){byteArray.push(str.charCodeAt(i)&255)}return byteArray}function utf16leToBytes(str,units){var c,hi,lo;var byteArray=[];for(var i=0;i<str.length;++i){if((units-=2)<0)break;c=str.charCodeAt(i);hi=c>>8;lo=c%256;byteArray.push(lo);byteArray.push(hi)}return byteArray}function base64ToBytes(str){return base64.toByteArray(base64clean(str))}function blitBuffer(src,dst,offset,length){for(var i=0;i<length;++i){if(i+offset>=dst.length||i>=src.length)break;dst[i+offset]=src[i]}return i}function isnan(val){return val!==val}}).call(this,typeof global!==\"undefined\"?global:typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{\"base64-js\":2,ieee754:37,isarray:40}],6:[function(require,module,exports){(function(Buffer){function isArray(arg){if(Array.isArray){return Array.isArray(arg)}return objectToString(arg)===\"[object Array]\"}exports.isArray=isArray;function isBoolean(arg){return typeof arg===\"boolean\"}exports.isBoolean=isBoolean;function isNull(arg){return arg===null}exports.isNull=isNull;function isNullOrUndefined(arg){return arg==null}exports.isNullOrUndefined=isNullOrUndefined;function isNumber(arg){return typeof arg===\"number\"}exports.isNumber=isNumber;function isString(arg){return typeof arg===\"string\"}exports.isString=isString;function isSymbol(arg){return typeof arg===\"symbol\"}exports.isSymbol=isSymbol;function isUndefined(arg){return arg===void 0}exports.isUndefined=isUndefined;function isRegExp(re){return objectToString(re)===\"[object RegExp]\"}exports.isRegExp=isRegExp;function isObject(arg){return typeof arg===\"object\"&&arg!==null}exports.isObject=isObject;function isDate(d){return objectToString(d)===\"[object Date]\"}exports.isDate=isDate;function isError(e){return objectToString(e)===\"[object Error]\"||e instanceof Error}exports.isError=isError;function isFunction(arg){return typeof arg===\"function\"}exports.isFunction=isFunction;function isPrimitive(arg){return arg===null||typeof arg===\"boolean\"||typeof arg===\"number\"||typeof arg===\"string\"||typeof arg===\"symbol\"||typeof arg===\"undefined\"}exports.isPrimitive=isPrimitive;exports.isBuffer=Buffer.isBuffer;function objectToString(o){return Object.prototype.toString.call(o)}}).call(this,{isBuffer:require(\"../../is-buffer/index.js\")})},{\"../../is-buffer/index.js\":39}],7:[function(require,module,exports){var ElementType=require(\"domelementtype\");var entities=require(\"entities\");var booleanAttributes={__proto__:null,allowfullscreen:true,async:true,autofocus:true,autoplay:true,checked:true,controls:true,default:true,defer:true,disabled:true,hidden:true,ismap:true,loop:true,multiple:true,muted:true,open:true,readonly:true,required:true,reversed:true,scoped:true,seamless:true,selected:true,typemustmatch:true};var unencodedElements={__proto__:null,style:true,script:true,xmp:true,iframe:true,noembed:true,noframes:true,plaintext:true,noscript:true};function formatAttrs(attributes,opts){if(!attributes)return;var output=\"\",value;for(var key in attributes){value=attributes[key];if(output){output+=\" \"}if(!value&&booleanAttributes[key]){output+=key}else{output+=key+'=\"'+(opts.decodeEntities?entities.encodeXML(value):value)+'\"'}}return output}var singleTag={__proto__:null,area:true,base:true,basefont:true,br:true,col:true,command:true,embed:true,frame:true,hr:true,img:true,input:true,isindex:true,keygen:true,link:true,meta:true,param:true,source:true,track:true,wbr:true};var render=module.exports=function(dom,opts){if(!Array.isArray(dom)&&!dom.cheerio)dom=[dom];opts=opts||{};var output=\"\";for(var i=0;i<dom.length;i++){var elem=dom[i];if(elem.type===\"root\")output+=render(elem.children,opts);else if(ElementType.isTag(elem))output+=renderTag(elem,opts);else if(elem.type===ElementType.Directive)output+=renderDirective(elem);else if(elem.type===ElementType.Comment)output+=renderComment(elem);else if(elem.type===ElementType.CDATA)output+=renderCdata(elem);else output+=renderText(elem,opts)}return output};function renderTag(elem,opts){if(elem.name===\"svg\")opts={decodeEntities:opts.decodeEntities,xmlMode:true};var tag=\"<\"+elem.name,attribs=formatAttrs(elem.attribs,opts);if(attribs){tag+=\" \"+attribs}if(opts.xmlMode&&(!elem.children||elem.children.length===0)){tag+=\"/>\"}else{tag+=\">\";if(elem.children){tag+=render(elem.children,opts)}if(!singleTag[elem.name]||opts.xmlMode){tag+=\"</\"+elem.name+\">\"}}return tag}function renderDirective(elem){return\"<\"+elem.data+\">\"}function renderText(elem,opts){var data=elem.data||\"\";if(opts.decodeEntities&&!(elem.parent&&elem.parent.name in unencodedElements)){data=entities.encodeXML(data)}return data}function renderCdata(elem){return\"<![CDATA[\"+elem.children[0].data+\"]]>\"}function renderComment(elem){return\"<!--\"+elem.data+\"-->\"}},{domelementtype:8,entities:20}],8:[function(require,module,exports){module.exports={Text:\"text\",Directive:\"directive\",Comment:\"comment\",Script:\"script\",Style:\"style\",Tag:\"tag\",CDATA:\"cdata\",isTag:function(elem){return elem.type===\"tag\"||elem.type===\"script\"||elem.type===\"style\"}}},{}],9:[function(require,module,exports){module.exports={Text:\"text\",Directive:\"directive\",Comment:\"comment\",Script:\"script\",Style:\"style\",Tag:\"tag\",CDATA:\"cdata\",Doctype:\"doctype\",isTag:function(elem){return elem.type===\"tag\"||elem.type===\"script\"||elem.type===\"style\"}}},{}],10:[function(require,module,exports){var ElementType=require(\"domelementtype\");var re_whitespace=/\\s+/g;var NodePrototype=require(\"./lib/node\");var ElementPrototype=require(\"./lib/element\");function DomHandler(callback,options,elementCB){if(typeof callback===\"object\"){elementCB=options;options=callback;callback=null}else if(typeof options===\"function\"){elementCB=options;options=defaultOpts}this._callback=callback;this._options=options||defaultOpts;this._elementCB=elementCB;this.dom=[];this._done=false;this._tagStack=[];this._parser=this._parser||null}var defaultOpts={normalizeWhitespace:false,withStartIndices:false};DomHandler.prototype.onparserinit=function(parser){this._parser=parser};DomHandler.prototype.onreset=function(){DomHandler.call(this,this._callback,this._options,this._elementCB)};DomHandler.prototype.onend=function(){if(this._done)return;this._done=true;this._parser=null;this._handleCallback(null)};DomHandler.prototype._handleCallback=DomHandler.prototype.onerror=function(error){if(typeof this._callback===\"function\"){this._callback(error,this.dom)}else{if(error)throw error}};DomHandler.prototype.onclosetag=function(){var elem=this._tagStack.pop();if(this._elementCB)this._elementCB(elem)};DomHandler.prototype._addDomElement=function(element){var parent=this._tagStack[this._tagStack.length-1];var siblings=parent?parent.children:this.dom;var previousSibling=siblings[siblings.length-1];element.next=null;if(this._options.withStartIndices){element.startIndex=this._parser.startIndex}if(this._options.withDomLvl1){element.__proto__=element.type===\"tag\"?ElementPrototype:NodePrototype}if(previousSibling){element.prev=previousSibling;previousSibling.next=element}else{element.prev=null}siblings.push(element);element.parent=parent||null};DomHandler.prototype.onopentag=function(name,attribs){var element={type:name===\"script\"?ElementType.Script:name===\"style\"?ElementType.Style:ElementType.Tag,name:name,attribs:attribs,children:[]};this._addDomElement(element);this._tagStack.push(element)};DomHandler.prototype.ontext=function(data){var normalize=this._options.normalizeWhitespace||this._options.ignoreWhitespace;var lastTag;if(!this._tagStack.length&&this.dom.length&&(lastTag=this.dom[this.dom.length-1]).type===ElementType.Text){if(normalize){lastTag.data=(lastTag.data+data).replace(re_whitespace,\" \")}else{lastTag.data+=data}}else{if(this._tagStack.length&&(lastTag=this._tagStack[this._tagStack.length-1])&&(lastTag=lastTag.children[lastTag.children.length-1])&&lastTag.type===ElementType.Text){if(normalize){lastTag.data=(lastTag.data+data).replace(re_whitespace,\" \")}else{lastTag.data+=data}}else{if(normalize){data=data.replace(re_whitespace,\" \")}this._addDomElement({data:data,type:ElementType.Text})}}};DomHandler.prototype.oncomment=function(data){var lastTag=this._tagStack[this._tagStack.length-1];if(lastTag&&lastTag.type===ElementType.Comment){lastTag.data+=data;return}var element={data:data,type:ElementType.Comment};this._addDomElement(element);this._tagStack.push(element)};DomHandler.prototype.oncdatastart=function(){var element={children:[{data:\"\",type:ElementType.Text}],type:ElementType.CDATA};this._addDomElement(element);this._tagStack.push(element)};DomHandler.prototype.oncommentend=DomHandler.prototype.oncdataend=function(){this._tagStack.pop()};DomHandler.prototype.onprocessinginstruction=function(name,data){this._addDomElement({name:name,data:data,type:ElementType.Directive})};module.exports=DomHandler},{\"./lib/element\":11,\"./lib/node\":12,domelementtype:9}],11:[function(require,module,exports){var NodePrototype=require(\"./node\");var ElementPrototype=module.exports=Object.create(NodePrototype);var domLvl1={tagName:\"name\"};Object.keys(domLvl1).forEach(function(key){var shorthand=domLvl1[key];Object.defineProperty(ElementPrototype,key,{get:function(){return this[shorthand]||null},set:function(val){this[shorthand]=val;return val}})})},{\"./node\":12}],12:[function(require,module,exports){var NodePrototype=module.exports={get firstChild(){var children=this.children;return children&&children[0]||null},get lastChild(){var children=this.children;return children&&children[children.length-1]||null},get nodeType(){return nodeTypes[this.type]||nodeTypes.element}};var domLvl1={tagName:\"name\",childNodes:\"children\",parentNode:\"parent\",previousSibling:\"prev\",nextSibling:\"next\",nodeValue:\"data\"};var nodeTypes={element:1,text:3,cdata:4,comment:8};Object.keys(domLvl1).forEach(function(key){var shorthand=domLvl1[key];Object.defineProperty(NodePrototype,key,{get:function(){return this[shorthand]||null},set:function(val){this[shorthand]=val;return val}})})},{}],13:[function(require,module,exports){var DomUtils=module.exports;[require(\"./lib/stringify\"),require(\"./lib/traversal\"),require(\"./lib/manipulation\"),require(\"./lib/querying\"),require(\"./lib/legacy\"),require(\"./lib/helpers\")].forEach(function(ext){Object.keys(ext).forEach(function(key){DomUtils[key]=ext[key].bind(DomUtils)})})},{\"./lib/helpers\":14,\"./lib/legacy\":15,\"./lib/manipulation\":16,\"./lib/querying\":17,\"./lib/stringify\":18,\"./lib/traversal\":19}],14:[function(require,module,exports){exports.removeSubsets=function(nodes){var idx=nodes.length,node,ancestor,replace;while(--idx>-1){node=ancestor=nodes[idx];nodes[idx]=null;replace=true;while(ancestor){if(nodes.indexOf(ancestor)>-1){replace=false;nodes.splice(idx,1);break}ancestor=ancestor.parent}if(replace){nodes[idx]=node}}return nodes};var POSITION={DISCONNECTED:1,PRECEDING:2,FOLLOWING:4,CONTAINS:8,CONTAINED_BY:16};var comparePos=exports.compareDocumentPosition=function(nodeA,nodeB){var aParents=[];var bParents=[];var current,sharedParent,siblings,aSibling,bSibling,idx;if(nodeA===nodeB){return 0}current=nodeA;while(current){aParents.unshift(current);current=current.parent}current=nodeB;while(current){bParents.unshift(current);current=current.parent}idx=0;while(aParents[idx]===bParents[idx]){idx++}if(idx===0){return POSITION.DISCONNECTED}sharedParent=aParents[idx-1];siblings=sharedParent.children;aSibling=aParents[idx];bSibling=bParents[idx];if(siblings.indexOf(aSibling)>siblings.indexOf(bSibling)){if(sharedParent===nodeB){return POSITION.FOLLOWING|POSITION.CONTAINED_BY}return POSITION.FOLLOWING}else{if(sharedParent===nodeA){return POSITION.PRECEDING|POSITION.CONTAINS}return POSITION.PRECEDING}};exports.uniqueSort=function(nodes){var idx=nodes.length,node,position;nodes=nodes.slice();while(--idx>-1){node=nodes[idx];position=nodes.indexOf(node);if(position>-1&&position<idx){nodes.splice(idx,1)}}nodes.sort(function(a,b){var relative=comparePos(a,b);if(relative&POSITION.PRECEDING){return-1}else if(relative&POSITION.FOLLOWING){return 1}return 0});return nodes}},{}],15:[function(require,module,exports){var ElementType=require(\"domelementtype\");var isTag=exports.isTag=ElementType.isTag;exports.testElement=function(options,element){for(var key in options){if(!options.hasOwnProperty(key));else if(key===\"tag_name\"){if(!isTag(element)||!options.tag_name(element.name)){return false}}else if(key===\"tag_type\"){if(!options.tag_type(element.type))return false}else if(key===\"tag_contains\"){if(isTag(element)||!options.tag_contains(element.data)){return false}}else if(!element.attribs||!options[key](element.attribs[key])){return false}}return true};var Checks={tag_name:function(name){if(typeof name===\"function\"){return function(elem){return isTag(elem)&&name(elem.name)}}else if(name===\"*\"){return isTag}else{return function(elem){return isTag(elem)&&elem.name===name}}},tag_type:function(type){if(typeof type===\"function\"){return function(elem){return type(elem.type)}}else{return function(elem){return elem.type===type}}},tag_contains:function(data){if(typeof data===\"function\"){return function(elem){return!isTag(elem)&&data(elem.data)}}else{return function(elem){return!isTag(elem)&&elem.data===data}}}};function getAttribCheck(attrib,value){if(typeof value===\"function\"){return function(elem){return elem.attribs&&value(elem.attribs[attrib])}}else{return function(elem){return elem.attribs&&elem.attribs[attrib]===value}}}function combineFuncs(a,b){return function(elem){return a(elem)||b(elem)}}exports.getElements=function(options,element,recurse,limit){var funcs=Object.keys(options).map(function(key){var value=options[key];return key in Checks?Checks[key](value):getAttribCheck(key,value)});return funcs.length===0?[]:this.filter(funcs.reduce(combineFuncs),element,recurse,limit)};exports.getElementById=function(id,element,recurse){if(!Array.isArray(element))element=[element];return this.findOne(getAttribCheck(\"id\",id),element,recurse!==false)};exports.getElementsByTagName=function(name,element,recurse,limit){return this.filter(Checks.tag_name(name),element,recurse,limit)};exports.getElementsByTagType=function(type,element,recurse,limit){return this.filter(Checks.tag_type(type),element,recurse,limit)}},{domelementtype:9}],16:[function(require,module,exports){exports.removeElement=function(elem){if(elem.prev)elem.prev.next=elem.next;if(elem.next)elem.next.prev=elem.prev;if(elem.parent){var childs=elem.parent.children;childs.splice(childs.lastIndexOf(elem),1)}};exports.replaceElement=function(elem,replacement){var prev=replacement.prev=elem.prev;if(prev){prev.next=replacement}var next=replacement.next=elem.next;if(next){next.prev=replacement}var parent=replacement.parent=elem.parent;if(parent){var childs=parent.children;childs[childs.lastIndexOf(elem)]=replacement}};exports.appendChild=function(elem,child){child.parent=elem;if(elem.children.push(child)!==1){var sibling=elem.children[elem.children.length-2];sibling.next=child;child.prev=sibling;child.next=null}};exports.append=function(elem,next){var parent=elem.parent,currNext=elem.next;next.next=currNext;next.prev=elem;elem.next=next;next.parent=parent;if(currNext){currNext.prev=next;if(parent){var childs=parent.children;childs.splice(childs.lastIndexOf(currNext),0,next)}}else if(parent){parent.children.push(next)}};exports.prepend=function(elem,prev){var parent=elem.parent;if(parent){var childs=parent.children;childs.splice(childs.lastIndexOf(elem),0,prev)}if(elem.prev){elem.prev.next=prev}prev.parent=parent;prev.prev=elem.prev;prev.next=elem;elem.prev=prev}},{}],17:[function(require,module,exports){var isTag=require(\"domelementtype\").isTag;module.exports={filter:filter,find:find,findOneChild:findOneChild,findOne:findOne,existsOne:existsOne,findAll:findAll};function filter(test,element,recurse,limit){if(!Array.isArray(element))element=[element];if(typeof limit!==\"number\"||!isFinite(limit)){limit=Infinity}return find(test,element,recurse!==false,limit)}function find(test,elems,recurse,limit){var result=[],childs;for(var i=0,j=elems.length;i<j;i++){if(test(elems[i])){result.push(elems[i]);if(--limit<=0)break}childs=elems[i].children;if(recurse&&childs&&childs.length>0){childs=find(test,childs,recurse,limit);result=result.concat(childs);limit-=childs.length;if(limit<=0)break}}return result}function findOneChild(test,elems){for(var i=0,l=elems.length;i<l;i++){if(test(elems[i]))return elems[i]}return null}function findOne(test,elems){var elem=null;for(var i=0,l=elems.length;i<l&&!elem;i++){if(!isTag(elems[i])){continue}else if(test(elems[i])){elem=elems[i]}else if(elems[i].children.length>0){elem=findOne(test,elems[i].children)}}return elem}function existsOne(test,elems){for(var i=0,l=elems.length;i<l;i++){if(isTag(elems[i])&&(test(elems[i])||elems[i].children.length>0&&existsOne(test,elems[i].children))){return true}}return false}function findAll(test,elems){var result=[];for(var i=0,j=elems.length;i<j;i++){if(!isTag(elems[i]))continue;if(test(elems[i]))result.push(elems[i]);if(elems[i].children.length>0){result=result.concat(findAll(test,elems[i].children))}}return result}},{domelementtype:9}],18:[function(require,module,exports){var ElementType=require(\"domelementtype\"),getOuterHTML=require(\"dom-serializer\"),isTag=ElementType.isTag;module.exports={getInnerHTML:getInnerHTML,getOuterHTML:getOuterHTML,getText:getText};function getInnerHTML(elem,opts){return elem.children?elem.children.map(function(elem){return getOuterHTML(elem,opts)}).join(\"\"):\"\"}function getText(elem){if(Array.isArray(elem))return elem.map(getText).join(\"\");if(isTag(elem)||elem.type===ElementType.CDATA)return getText(elem.children);if(elem.type===ElementType.Text)return elem.data;return\"\"}},{\"dom-serializer\":7,domelementtype:9}],19:[function(require,module,exports){var getChildren=exports.getChildren=function(elem){return elem.children};var getParent=exports.getParent=function(elem){return elem.parent};exports.getSiblings=function(elem){var parent=getParent(elem);return parent?getChildren(parent):[elem]};exports.getAttributeValue=function(elem,name){return elem.attribs&&elem.attribs[name]};exports.hasAttrib=function(elem,name){return!!elem.attribs&&hasOwnProperty.call(elem.attribs,name)};exports.getName=function(elem){return elem.name}},{}],20:[function(require,module,exports){var encode=require(\"./lib/encode.js\"),decode=require(\"./lib/decode.js\");exports.decode=function(data,level){return(!level||level<=0?decode.XML:decode.HTML)(data)};exports.decodeStrict=function(data,level){return(!level||level<=0?decode.XML:decode.HTMLStrict)(data)};exports.encode=function(data,level){return(!level||level<=0?encode.XML:encode.HTML)(data)};exports.encodeXML=encode.XML;exports.encodeHTML4=exports.encodeHTML5=exports.encodeHTML=encode.HTML;exports.decodeXML=exports.decodeXMLStrict=decode.XML;exports.decodeHTML4=exports.decodeHTML5=exports.decodeHTML=decode.HTML;exports.decodeHTML4Strict=exports.decodeHTML5Strict=exports.decodeHTMLStrict=decode.HTMLStrict;exports.escape=encode.escape},{\"./lib/decode.js\":21,\"./lib/encode.js\":23}],21:[function(require,module,exports){var entityMap=require(\"../maps/entities.json\"),legacyMap=require(\"../maps/legacy.json\"),xmlMap=require(\"../maps/xml.json\"),decodeCodePoint=require(\"./decode_codepoint.js\");var decodeXMLStrict=getStrictDecoder(xmlMap),decodeHTMLStrict=getStrictDecoder(entityMap);function getStrictDecoder(map){var keys=Object.keys(map).join(\"|\"),replace=getReplacer(map);keys+=\"|#[xX][\\\\da-fA-F]+|#\\\\d+\";var re=new RegExp(\"&(?:\"+keys+\");\",\"g\");return function(str){return String(str).replace(re,replace)}}var decodeHTML=function(){var legacy=Object.keys(legacyMap).sort(sorter);var keys=Object.keys(entityMap).sort(sorter);for(var i=0,j=0;i<keys.length;i++){if(legacy[j]===keys[i]){keys[i]+=\";?\";j++}else{keys[i]+=\";\"}}var re=new RegExp(\"&(?:\"+keys.join(\"|\")+\"|#[xX][\\\\da-fA-F]+;?|#\\\\d+;?)\",\"g\"),replace=getReplacer(entityMap);function replacer(str){if(str.substr(-1)!==\";\")str+=\";\";return replace(str)}return function(str){return String(str).replace(re,replacer)}}();function sorter(a,b){return a<b?1:-1}function getReplacer(map){return function replace(str){if(str.charAt(1)===\"#\"){if(str.charAt(2)===\"X\"||str.charAt(2)===\"x\"){return decodeCodePoint(parseInt(str.substr(3),16))}return decodeCodePoint(parseInt(str.substr(2),10))}return map[str.slice(1,-1)];\n}}module.exports={XML:decodeXMLStrict,HTML:decodeHTML,HTMLStrict:decodeHTMLStrict}},{\"../maps/entities.json\":25,\"../maps/legacy.json\":26,\"../maps/xml.json\":27,\"./decode_codepoint.js\":22}],22:[function(require,module,exports){var decodeMap=require(\"../maps/decode.json\");module.exports=decodeCodePoint;function decodeCodePoint(codePoint){if(codePoint>=55296&&codePoint<=57343||codePoint>1114111){return\"�\"}if(codePoint in decodeMap){codePoint=decodeMap[codePoint]}var output=\"\";if(codePoint>65535){codePoint-=65536;output+=String.fromCharCode(codePoint>>>10&1023|55296);codePoint=56320|codePoint&1023}output+=String.fromCharCode(codePoint);return output}},{\"../maps/decode.json\":24}],23:[function(require,module,exports){var inverseXML=getInverseObj(require(\"../maps/xml.json\")),xmlReplacer=getInverseReplacer(inverseXML);exports.XML=getInverse(inverseXML,xmlReplacer);var inverseHTML=getInverseObj(require(\"../maps/entities.json\")),htmlReplacer=getInverseReplacer(inverseHTML);exports.HTML=getInverse(inverseHTML,htmlReplacer);function getInverseObj(obj){return Object.keys(obj).sort().reduce(function(inverse,name){inverse[obj[name]]=\"&\"+name+\";\";return inverse},{})}function getInverseReplacer(inverse){var single=[],multiple=[];Object.keys(inverse).forEach(function(k){if(k.length===1){single.push(\"\\\\\"+k)}else{multiple.push(k)}});multiple.unshift(\"[\"+single.join(\"\")+\"]\");return new RegExp(multiple.join(\"|\"),\"g\")}var re_nonASCII=/[^\\0-\\x7F]/g,re_astralSymbols=/[\\uD800-\\uDBFF][\\uDC00-\\uDFFF]/g;function singleCharReplacer(c){return\"&#x\"+c.charCodeAt(0).toString(16).toUpperCase()+\";\"}function astralReplacer(c){var high=c.charCodeAt(0);var low=c.charCodeAt(1);var codePoint=(high-55296)*1024+low-56320+65536;return\"&#x\"+codePoint.toString(16).toUpperCase()+\";\"}function getInverse(inverse,re){function func(name){return inverse[name]}return function(data){return data.replace(re,func).replace(re_astralSymbols,astralReplacer).replace(re_nonASCII,singleCharReplacer)}}var re_xmlChars=getInverseReplacer(inverseXML);function escapeXML(data){return data.replace(re_xmlChars,singleCharReplacer).replace(re_astralSymbols,astralReplacer).replace(re_nonASCII,singleCharReplacer)}exports.escape=escapeXML},{\"../maps/entities.json\":25,\"../maps/xml.json\":27}],24:[function(require,module,exports){module.exports={0:65533,128:8364,130:8218,131:402,132:8222,133:8230,134:8224,135:8225,136:710,137:8240,138:352,139:8249,140:338,142:381,145:8216,146:8217,147:8220,148:8221,149:8226,150:8211,151:8212,152:732,153:8482,154:353,155:8250,156:339,158:382,159:376}},{}],25:[function(require,module,exports){module.exports={Aacute:\"Á\",aacute:\"á\",Abreve:\"Ă\",abreve:\"ă\",ac:\"∾\",acd:\"∿\",acE:\"∾̳\",Acirc:\"Â\",acirc:\"â\",acute:\"´\",Acy:\"А\",acy:\"а\",AElig:\"Æ\",aelig:\"æ\",af:\"⁡\",Afr:\"𝔄\",afr:\"𝔞\",Agrave:\"À\",agrave:\"à\",alefsym:\"ℵ\",aleph:\"ℵ\",Alpha:\"Α\",alpha:\"α\",Amacr:\"Ā\",amacr:\"ā\",amalg:\"⨿\",amp:\"&\",AMP:\"&\",andand:\"⩕\",And:\"⩓\",and:\"∧\",andd:\"⩜\",andslope:\"⩘\",andv:\"⩚\",ang:\"∠\",ange:\"⦤\",angle:\"∠\",angmsdaa:\"⦨\",angmsdab:\"⦩\",angmsdac:\"⦪\",angmsdad:\"⦫\",angmsdae:\"⦬\",angmsdaf:\"⦭\",angmsdag:\"⦮\",angmsdah:\"⦯\",angmsd:\"∡\",angrt:\"∟\",angrtvb:\"⊾\",angrtvbd:\"⦝\",angsph:\"∢\",angst:\"Å\",angzarr:\"⍼\",Aogon:\"Ą\",aogon:\"ą\",Aopf:\"𝔸\",aopf:\"𝕒\",apacir:\"⩯\",ap:\"≈\",apE:\"⩰\",ape:\"≊\",apid:\"≋\",apos:\"'\",ApplyFunction:\"⁡\",approx:\"≈\",approxeq:\"≊\",Aring:\"Å\",aring:\"å\",Ascr:\"𝒜\",ascr:\"𝒶\",Assign:\"≔\",ast:\"*\",asymp:\"≈\",asympeq:\"≍\",Atilde:\"Ã\",atilde:\"ã\",Auml:\"Ä\",auml:\"ä\",awconint:\"∳\",awint:\"⨑\",backcong:\"≌\",backepsilon:\"϶\",backprime:\"‵\",backsim:\"∽\",backsimeq:\"⋍\",Backslash:\"∖\",Barv:\"⫧\",barvee:\"⊽\",barwed:\"⌅\",Barwed:\"⌆\",barwedge:\"⌅\",bbrk:\"⎵\",bbrktbrk:\"⎶\",bcong:\"≌\",Bcy:\"Б\",bcy:\"б\",bdquo:\"„\",becaus:\"∵\",because:\"∵\",Because:\"∵\",bemptyv:\"⦰\",bepsi:\"϶\",bernou:\"ℬ\",Bernoullis:\"ℬ\",Beta:\"Β\",beta:\"β\",beth:\"ℶ\",between:\"≬\",Bfr:\"𝔅\",bfr:\"𝔟\",bigcap:\"⋂\",bigcirc:\"◯\",bigcup:\"⋃\",bigodot:\"⨀\",bigoplus:\"⨁\",bigotimes:\"⨂\",bigsqcup:\"⨆\",bigstar:\"★\",bigtriangledown:\"▽\",bigtriangleup:\"△\",biguplus:\"⨄\",bigvee:\"⋁\",bigwedge:\"⋀\",bkarow:\"⤍\",blacklozenge:\"⧫\",blacksquare:\"▪\",blacktriangle:\"▴\",blacktriangledown:\"▾\",blacktriangleleft:\"◂\",blacktriangleright:\"▸\",blank:\"␣\",blk12:\"▒\",blk14:\"░\",blk34:\"▓\",block:\"█\",bne:\"=⃥\",bnequiv:\"≡⃥\",bNot:\"⫭\",bnot:\"⌐\",Bopf:\"𝔹\",bopf:\"𝕓\",bot:\"⊥\",bottom:\"⊥\",bowtie:\"⋈\",boxbox:\"⧉\",boxdl:\"┐\",boxdL:\"╕\",boxDl:\"╖\",boxDL:\"╗\",boxdr:\"┌\",boxdR:\"╒\",boxDr:\"╓\",boxDR:\"╔\",boxh:\"─\",boxH:\"═\",boxhd:\"┬\",boxHd:\"╤\",boxhD:\"╥\",boxHD:\"╦\",boxhu:\"┴\",boxHu:\"╧\",boxhU:\"╨\",boxHU:\"╩\",boxminus:\"⊟\",boxplus:\"⊞\",boxtimes:\"⊠\",boxul:\"┘\",boxuL:\"╛\",boxUl:\"╜\",boxUL:\"╝\",boxur:\"└\",boxuR:\"╘\",boxUr:\"╙\",boxUR:\"╚\",boxv:\"│\",boxV:\"║\",boxvh:\"┼\",boxvH:\"╪\",boxVh:\"╫\",boxVH:\"╬\",boxvl:\"┤\",boxvL:\"╡\",boxVl:\"╢\",boxVL:\"╣\",boxvr:\"├\",boxvR:\"╞\",boxVr:\"╟\",boxVR:\"╠\",bprime:\"‵\",breve:\"˘\",Breve:\"˘\",brvbar:\"¦\",bscr:\"𝒷\",Bscr:\"ℬ\",bsemi:\"⁏\",bsim:\"∽\",bsime:\"⋍\",bsolb:\"⧅\",bsol:\"\\\\\",bsolhsub:\"⟈\",bull:\"•\",bullet:\"•\",bump:\"≎\",bumpE:\"⪮\",bumpe:\"≏\",Bumpeq:\"≎\",bumpeq:\"≏\",Cacute:\"Ć\",cacute:\"ć\",capand:\"⩄\",capbrcup:\"⩉\",capcap:\"⩋\",cap:\"∩\",Cap:\"⋒\",capcup:\"⩇\",capdot:\"⩀\",CapitalDifferentialD:\"ⅅ\",caps:\"∩︀\",caret:\"⁁\",caron:\"ˇ\",Cayleys:\"ℭ\",ccaps:\"⩍\",Ccaron:\"Č\",ccaron:\"č\",Ccedil:\"Ç\",ccedil:\"ç\",Ccirc:\"Ĉ\",ccirc:\"ĉ\",Cconint:\"∰\",ccups:\"⩌\",ccupssm:\"⩐\",Cdot:\"Ċ\",cdot:\"ċ\",cedil:\"¸\",Cedilla:\"¸\",cemptyv:\"⦲\",cent:\"¢\",centerdot:\"·\",CenterDot:\"·\",cfr:\"𝔠\",Cfr:\"ℭ\",CHcy:\"Ч\",chcy:\"ч\",check:\"✓\",checkmark:\"✓\",Chi:\"Χ\",chi:\"χ\",circ:\"ˆ\",circeq:\"≗\",circlearrowleft:\"↺\",circlearrowright:\"↻\",circledast:\"⊛\",circledcirc:\"⊚\",circleddash:\"⊝\",CircleDot:\"⊙\",circledR:\"®\",circledS:\"Ⓢ\",CircleMinus:\"⊖\",CirclePlus:\"⊕\",CircleTimes:\"⊗\",cir:\"○\",cirE:\"⧃\",cire:\"≗\",cirfnint:\"⨐\",cirmid:\"⫯\",cirscir:\"⧂\",ClockwiseContourIntegral:\"∲\",CloseCurlyDoubleQuote:\"”\",CloseCurlyQuote:\"’\",clubs:\"♣\",clubsuit:\"♣\",colon:\":\",Colon:\"∷\",Colone:\"⩴\",colone:\"≔\",coloneq:\"≔\",comma:\",\",commat:\"@\",comp:\"∁\",compfn:\"∘\",complement:\"∁\",complexes:\"ℂ\",cong:\"≅\",congdot:\"⩭\",Congruent:\"≡\",conint:\"∮\",Conint:\"∯\",ContourIntegral:\"∮\",copf:\"𝕔\",Copf:\"ℂ\",coprod:\"∐\",Coproduct:\"∐\",copy:\"©\",COPY:\"©\",copysr:\"℗\",CounterClockwiseContourIntegral:\"∳\",crarr:\"↵\",cross:\"✗\",Cross:\"⨯\",Cscr:\"𝒞\",cscr:\"𝒸\",csub:\"⫏\",csube:\"⫑\",csup:\"⫐\",csupe:\"⫒\",ctdot:\"⋯\",cudarrl:\"⤸\",cudarrr:\"⤵\",cuepr:\"⋞\",cuesc:\"⋟\",cularr:\"↶\",cularrp:\"⤽\",cupbrcap:\"⩈\",cupcap:\"⩆\",CupCap:\"≍\",cup:\"∪\",Cup:\"⋓\",cupcup:\"⩊\",cupdot:\"⊍\",cupor:\"⩅\",cups:\"∪︀\",curarr:\"↷\",curarrm:\"⤼\",curlyeqprec:\"⋞\",curlyeqsucc:\"⋟\",curlyvee:\"⋎\",curlywedge:\"⋏\",curren:\"¤\",curvearrowleft:\"↶\",curvearrowright:\"↷\",cuvee:\"⋎\",cuwed:\"⋏\",cwconint:\"∲\",cwint:\"∱\",cylcty:\"⌭\",dagger:\"†\",Dagger:\"‡\",daleth:\"ℸ\",darr:\"↓\",Darr:\"↡\",dArr:\"⇓\",dash:\"‐\",Dashv:\"⫤\",dashv:\"⊣\",dbkarow:\"⤏\",dblac:\"˝\",Dcaron:\"Ď\",dcaron:\"ď\",Dcy:\"Д\",dcy:\"д\",ddagger:\"‡\",ddarr:\"⇊\",DD:\"ⅅ\",dd:\"ⅆ\",DDotrahd:\"⤑\",ddotseq:\"⩷\",deg:\"°\",Del:\"∇\",Delta:\"Δ\",delta:\"δ\",demptyv:\"⦱\",dfisht:\"⥿\",Dfr:\"𝔇\",dfr:\"𝔡\",dHar:\"⥥\",dharl:\"⇃\",dharr:\"⇂\",DiacriticalAcute:\"´\",DiacriticalDot:\"˙\",DiacriticalDoubleAcute:\"˝\",DiacriticalGrave:\"`\",DiacriticalTilde:\"˜\",diam:\"⋄\",diamond:\"⋄\",Diamond:\"⋄\",diamondsuit:\"♦\",diams:\"♦\",die:\"¨\",DifferentialD:\"ⅆ\",digamma:\"ϝ\",disin:\"⋲\",div:\"÷\",divide:\"÷\",divideontimes:\"⋇\",divonx:\"⋇\",DJcy:\"Ђ\",djcy:\"ђ\",dlcorn:\"⌞\",dlcrop:\"⌍\",dollar:\"$\",Dopf:\"𝔻\",dopf:\"𝕕\",Dot:\"¨\",dot:\"˙\",DotDot:\"⃜\",doteq:\"≐\",doteqdot:\"≑\",DotEqual:\"≐\",dotminus:\"∸\",dotplus:\"∔\",dotsquare:\"⊡\",doublebarwedge:\"⌆\",DoubleContourIntegral:\"∯\",DoubleDot:\"¨\",DoubleDownArrow:\"⇓\",DoubleLeftArrow:\"⇐\",DoubleLeftRightArrow:\"⇔\",DoubleLeftTee:\"⫤\",DoubleLongLeftArrow:\"⟸\",DoubleLongLeftRightArrow:\"⟺\",DoubleLongRightArrow:\"⟹\",DoubleRightArrow:\"⇒\",DoubleRightTee:\"⊨\",DoubleUpArrow:\"⇑\",DoubleUpDownArrow:\"⇕\",DoubleVerticalBar:\"∥\",DownArrowBar:\"⤓\",downarrow:\"↓\",DownArrow:\"↓\",Downarrow:\"⇓\",DownArrowUpArrow:\"⇵\",DownBreve:\"̑\",downdownarrows:\"⇊\",downharpoonleft:\"⇃\",downharpoonright:\"⇂\",DownLeftRightVector:\"⥐\",DownLeftTeeVector:\"⥞\",DownLeftVectorBar:\"⥖\",DownLeftVector:\"↽\",DownRightTeeVector:\"⥟\",DownRightVectorBar:\"⥗\",DownRightVector:\"⇁\",DownTeeArrow:\"↧\",DownTee:\"⊤\",drbkarow:\"⤐\",drcorn:\"⌟\",drcrop:\"⌌\",Dscr:\"𝒟\",dscr:\"𝒹\",DScy:\"Ѕ\",dscy:\"ѕ\",dsol:\"⧶\",Dstrok:\"Đ\",dstrok:\"đ\",dtdot:\"⋱\",dtri:\"▿\",dtrif:\"▾\",duarr:\"⇵\",duhar:\"⥯\",dwangle:\"⦦\",DZcy:\"Џ\",dzcy:\"џ\",dzigrarr:\"⟿\",Eacute:\"É\",eacute:\"é\",easter:\"⩮\",Ecaron:\"Ě\",ecaron:\"ě\",Ecirc:\"Ê\",ecirc:\"ê\",ecir:\"≖\",ecolon:\"≕\",Ecy:\"Э\",ecy:\"э\",eDDot:\"⩷\",Edot:\"Ė\",edot:\"ė\",eDot:\"≑\",ee:\"ⅇ\",efDot:\"≒\",Efr:\"𝔈\",efr:\"𝔢\",eg:\"⪚\",Egrave:\"È\",egrave:\"è\",egs:\"⪖\",egsdot:\"⪘\",el:\"⪙\",Element:\"∈\",elinters:\"⏧\",ell:\"ℓ\",els:\"⪕\",elsdot:\"⪗\",Emacr:\"Ē\",emacr:\"ē\",empty:\"∅\",emptyset:\"∅\",EmptySmallSquare:\"◻\",emptyv:\"∅\",EmptyVerySmallSquare:\"▫\",emsp13:\" \",emsp14:\" \",emsp:\" \",ENG:\"Ŋ\",eng:\"ŋ\",ensp:\" \",Eogon:\"Ę\",eogon:\"ę\",Eopf:\"𝔼\",eopf:\"𝕖\",epar:\"⋕\",eparsl:\"⧣\",eplus:\"⩱\",epsi:\"ε\",Epsilon:\"Ε\",epsilon:\"ε\",epsiv:\"ϵ\",eqcirc:\"≖\",eqcolon:\"≕\",eqsim:\"≂\",eqslantgtr:\"⪖\",eqslantless:\"⪕\",Equal:\"⩵\",equals:\"=\",EqualTilde:\"≂\",equest:\"≟\",Equilibrium:\"⇌\",equiv:\"≡\",equivDD:\"⩸\",eqvparsl:\"⧥\",erarr:\"⥱\",erDot:\"≓\",escr:\"ℯ\",Escr:\"ℰ\",esdot:\"≐\",Esim:\"⩳\",esim:\"≂\",Eta:\"Η\",eta:\"η\",ETH:\"Ð\",eth:\"ð\",Euml:\"Ë\",euml:\"ë\",euro:\"€\",excl:\"!\",exist:\"∃\",Exists:\"∃\",expectation:\"ℰ\",exponentiale:\"ⅇ\",ExponentialE:\"ⅇ\",fallingdotseq:\"≒\",Fcy:\"Ф\",fcy:\"ф\",female:\"♀\",ffilig:\"ﬃ\",fflig:\"ﬀ\",ffllig:\"ﬄ\",Ffr:\"𝔉\",ffr:\"𝔣\",filig:\"ﬁ\",FilledSmallSquare:\"◼\",FilledVerySmallSquare:\"▪\",fjlig:\"fj\",flat:\"♭\",fllig:\"ﬂ\",fltns:\"▱\",fnof:\"ƒ\",Fopf:\"𝔽\",fopf:\"𝕗\",forall:\"∀\",ForAll:\"∀\",fork:\"⋔\",forkv:\"⫙\",Fouriertrf:\"ℱ\",fpartint:\"⨍\",frac12:\"½\",frac13:\"⅓\",frac14:\"¼\",frac15:\"⅕\",frac16:\"⅙\",frac18:\"⅛\",frac23:\"⅔\",frac25:\"⅖\",frac34:\"¾\",frac35:\"⅗\",frac38:\"⅜\",frac45:\"⅘\",frac56:\"⅚\",frac58:\"⅝\",frac78:\"⅞\",frasl:\"⁄\",frown:\"⌢\",fscr:\"𝒻\",Fscr:\"ℱ\",gacute:\"ǵ\",Gamma:\"Γ\",gamma:\"γ\",Gammad:\"Ϝ\",gammad:\"ϝ\",gap:\"⪆\",Gbreve:\"Ğ\",gbreve:\"ğ\",Gcedil:\"Ģ\",Gcirc:\"Ĝ\",gcirc:\"ĝ\",Gcy:\"Г\",gcy:\"г\",Gdot:\"Ġ\",gdot:\"ġ\",ge:\"≥\",gE:\"≧\",gEl:\"⪌\",gel:\"⋛\",geq:\"≥\",geqq:\"≧\",geqslant:\"⩾\",gescc:\"⪩\",ges:\"⩾\",gesdot:\"⪀\",gesdoto:\"⪂\",gesdotol:\"⪄\",gesl:\"⋛︀\",gesles:\"⪔\",Gfr:\"𝔊\",gfr:\"𝔤\",gg:\"≫\",Gg:\"⋙\",ggg:\"⋙\",gimel:\"ℷ\",GJcy:\"Ѓ\",gjcy:\"ѓ\",gla:\"⪥\",gl:\"≷\",glE:\"⪒\",glj:\"⪤\",gnap:\"⪊\",gnapprox:\"⪊\",gne:\"⪈\",gnE:\"≩\",gneq:\"⪈\",gneqq:\"≩\",gnsim:\"⋧\",Gopf:\"𝔾\",gopf:\"𝕘\",grave:\"`\",GreaterEqual:\"≥\",GreaterEqualLess:\"⋛\",GreaterFullEqual:\"≧\",GreaterGreater:\"⪢\",GreaterLess:\"≷\",GreaterSlantEqual:\"⩾\",GreaterTilde:\"≳\",Gscr:\"𝒢\",gscr:\"ℊ\",gsim:\"≳\",gsime:\"⪎\",gsiml:\"⪐\",gtcc:\"⪧\",gtcir:\"⩺\",gt:\">\",GT:\">\",Gt:\"≫\",gtdot:\"⋗\",gtlPar:\"⦕\",gtquest:\"⩼\",gtrapprox:\"⪆\",gtrarr:\"⥸\",gtrdot:\"⋗\",gtreqless:\"⋛\",gtreqqless:\"⪌\",gtrless:\"≷\",gtrsim:\"≳\",gvertneqq:\"≩︀\",gvnE:\"≩︀\",Hacek:\"ˇ\",hairsp:\" \",half:\"½\",hamilt:\"ℋ\",HARDcy:\"Ъ\",hardcy:\"ъ\",harrcir:\"⥈\",harr:\"↔\",hArr:\"⇔\",harrw:\"↭\",Hat:\"^\",hbar:\"ℏ\",Hcirc:\"Ĥ\",hcirc:\"ĥ\",hearts:\"♥\",heartsuit:\"♥\",hellip:\"…\",hercon:\"⊹\",hfr:\"𝔥\",Hfr:\"ℌ\",HilbertSpace:\"ℋ\",hksearow:\"⤥\",hkswarow:\"⤦\",hoarr:\"⇿\",homtht:\"∻\",hookleftarrow:\"↩\",hookrightarrow:\"↪\",hopf:\"𝕙\",Hopf:\"ℍ\",horbar:\"―\",HorizontalLine:\"─\",hscr:\"𝒽\",Hscr:\"ℋ\",hslash:\"ℏ\",Hstrok:\"Ħ\",hstrok:\"ħ\",HumpDownHump:\"≎\",HumpEqual:\"≏\",hybull:\"⁃\",hyphen:\"‐\",Iacute:\"Í\",iacute:\"í\",ic:\"⁣\",Icirc:\"Î\",icirc:\"î\",Icy:\"И\",icy:\"и\",Idot:\"İ\",IEcy:\"Е\",iecy:\"е\",iexcl:\"¡\",iff:\"⇔\",ifr:\"𝔦\",Ifr:\"ℑ\",Igrave:\"Ì\",igrave:\"ì\",ii:\"ⅈ\",iiiint:\"⨌\",iiint:\"∭\",iinfin:\"⧜\",iiota:\"℩\",IJlig:\"Ĳ\",ijlig:\"ĳ\",Imacr:\"Ī\",imacr:\"ī\",image:\"ℑ\",ImaginaryI:\"ⅈ\",imagline:\"ℐ\",imagpart:\"ℑ\",imath:\"ı\",Im:\"ℑ\",imof:\"⊷\",imped:\"Ƶ\",Implies:\"⇒\",incare:\"℅\",in:\"∈\",infin:\"∞\",infintie:\"⧝\",inodot:\"ı\",intcal:\"⊺\",int:\"∫\",Int:\"∬\",integers:\"ℤ\",Integral:\"∫\",intercal:\"⊺\",Intersection:\"⋂\",intlarhk:\"⨗\",intprod:\"⨼\",InvisibleComma:\"⁣\",InvisibleTimes:\"⁢\",IOcy:\"Ё\",iocy:\"ё\",Iogon:\"Į\",iogon:\"į\",Iopf:\"𝕀\",iopf:\"𝕚\",Iota:\"Ι\",iota:\"ι\",iprod:\"⨼\",iquest:\"¿\",iscr:\"𝒾\",Iscr:\"ℐ\",isin:\"∈\",isindot:\"⋵\",isinE:\"⋹\",isins:\"⋴\",isinsv:\"⋳\",isinv:\"∈\",it:\"⁢\",Itilde:\"Ĩ\",itilde:\"ĩ\",Iukcy:\"І\",iukcy:\"і\",Iuml:\"Ï\",iuml:\"ï\",Jcirc:\"Ĵ\",jcirc:\"ĵ\",Jcy:\"Й\",jcy:\"й\",Jfr:\"𝔍\",jfr:\"𝔧\",jmath:\"ȷ\",Jopf:\"𝕁\",jopf:\"𝕛\",Jscr:\"𝒥\",jscr:\"𝒿\",Jsercy:\"Ј\",jsercy:\"ј\",Jukcy:\"Є\",jukcy:\"є\",Kappa:\"Κ\",kappa:\"κ\",kappav:\"ϰ\",Kcedil:\"Ķ\",kcedil:\"ķ\",Kcy:\"К\",kcy:\"к\",Kfr:\"𝔎\",kfr:\"𝔨\",kgreen:\"ĸ\",KHcy:\"Х\",khcy:\"х\",KJcy:\"Ќ\",kjcy:\"ќ\",Kopf:\"𝕂\",kopf:\"𝕜\",Kscr:\"𝒦\",kscr:\"𝓀\",lAarr:\"⇚\",Lacute:\"Ĺ\",lacute:\"ĺ\",laemptyv:\"⦴\",lagran:\"ℒ\",Lambda:\"Λ\",lambda:\"λ\",lang:\"⟨\",Lang:\"⟪\",langd:\"⦑\",langle:\"⟨\",lap:\"⪅\",Laplacetrf:\"ℒ\",laquo:\"«\",larrb:\"⇤\",larrbfs:\"⤟\",larr:\"←\",Larr:\"↞\",lArr:\"⇐\",larrfs:\"⤝\",larrhk:\"↩\",larrlp:\"↫\",larrpl:\"⤹\",larrsim:\"⥳\",larrtl:\"↢\",latail:\"⤙\",lAtail:\"⤛\",lat:\"⪫\",late:\"⪭\",lates:\"⪭︀\",lbarr:\"⤌\",lBarr:\"⤎\",lbbrk:\"❲\",lbrace:\"{\",lbrack:\"[\",lbrke:\"⦋\",lbrksld:\"⦏\",lbrkslu:\"⦍\",Lcaron:\"Ľ\",lcaron:\"ľ\",Lcedil:\"Ļ\",lcedil:\"ļ\",lceil:\"⌈\",lcub:\"{\",Lcy:\"Л\",lcy:\"л\",ldca:\"⤶\",ldquo:\"“\",ldquor:\"„\",ldrdhar:\"⥧\",ldrushar:\"⥋\",ldsh:\"↲\",le:\"≤\",lE:\"≦\",LeftAngleBracket:\"⟨\",LeftArrowBar:\"⇤\",leftarrow:\"←\",LeftArrow:\"←\",Leftarrow:\"⇐\",LeftArrowRightArrow:\"⇆\",leftarrowtail:\"↢\",LeftCeiling:\"⌈\",LeftDoubleBracket:\"⟦\",LeftDownTeeVector:\"⥡\",LeftDownVectorBar:\"⥙\",LeftDownVector:\"⇃\",LeftFloor:\"⌊\",leftharpoondown:\"↽\",leftharpoonup:\"↼\",leftleftarrows:\"⇇\",leftrightarrow:\"↔\",LeftRightArrow:\"↔\",Leftrightarrow:\"⇔\",leftrightarrows:\"⇆\",leftrightharpoons:\"⇋\",leftrightsquigarrow:\"↭\",LeftRightVector:\"⥎\",LeftTeeArrow:\"↤\",LeftTee:\"⊣\",LeftTeeVector:\"⥚\",leftthreetimes:\"⋋\",LeftTriangleBar:\"⧏\",LeftTriangle:\"⊲\",LeftTriangleEqual:\"⊴\",LeftUpDownVector:\"⥑\",LeftUpTeeVector:\"⥠\",LeftUpVectorBar:\"⥘\",LeftUpVector:\"↿\",LeftVectorBar:\"⥒\",LeftVector:\"↼\",lEg:\"⪋\",leg:\"⋚\",leq:\"≤\",leqq:\"≦\",leqslant:\"⩽\",lescc:\"⪨\",les:\"⩽\",lesdot:\"⩿\",lesdoto:\"⪁\",lesdotor:\"⪃\",lesg:\"⋚︀\",lesges:\"⪓\",lessapprox:\"⪅\",lessdot:\"⋖\",lesseqgtr:\"⋚\",lesseqqgtr:\"⪋\",LessEqualGreater:\"⋚\",LessFullEqual:\"≦\",LessGreater:\"≶\",lessgtr:\"≶\",LessLess:\"⪡\",lesssim:\"≲\",LessSlantEqual:\"⩽\",LessTilde:\"≲\",lfisht:\"⥼\",lfloor:\"⌊\",Lfr:\"𝔏\",lfr:\"𝔩\",lg:\"≶\",lgE:\"⪑\",lHar:\"⥢\",lhard:\"↽\",lharu:\"↼\",lharul:\"⥪\",lhblk:\"▄\",LJcy:\"Љ\",ljcy:\"љ\",llarr:\"⇇\",ll:\"≪\",Ll:\"⋘\",llcorner:\"⌞\",Lleftarrow:\"⇚\",llhard:\"⥫\",lltri:\"◺\",Lmidot:\"Ŀ\",lmidot:\"ŀ\",lmoustache:\"⎰\",lmoust:\"⎰\",lnap:\"⪉\",lnapprox:\"⪉\",lne:\"⪇\",lnE:\"≨\",lneq:\"⪇\",lneqq:\"≨\",lnsim:\"⋦\",loang:\"⟬\",loarr:\"⇽\",lobrk:\"⟦\",longleftarrow:\"⟵\",LongLeftArrow:\"⟵\",Longleftarrow:\"⟸\",longleftrightarrow:\"⟷\",LongLeftRightArrow:\"⟷\",Longleftrightarrow:\"⟺\",longmapsto:\"⟼\",longrightarrow:\"⟶\",LongRightArrow:\"⟶\",Longrightarrow:\"⟹\",looparrowleft:\"↫\",looparrowright:\"↬\",lopar:\"⦅\",Lopf:\"𝕃\",lopf:\"𝕝\",loplus:\"⨭\",lotimes:\"⨴\",lowast:\"∗\",lowbar:\"_\",LowerLeftArrow:\"↙\",LowerRightArrow:\"↘\",loz:\"◊\",lozenge:\"◊\",lozf:\"⧫\",lpar:\"(\",lparlt:\"⦓\",lrarr:\"⇆\",lrcorner:\"⌟\",lrhar:\"⇋\",lrhard:\"⥭\",lrm:\"‎\",lrtri:\"⊿\",lsaquo:\"‹\",lscr:\"𝓁\",Lscr:\"ℒ\",lsh:\"↰\",Lsh:\"↰\",lsim:\"≲\",lsime:\"⪍\",lsimg:\"⪏\",lsqb:\"[\",lsquo:\"‘\",lsquor:\"‚\",Lstrok:\"Ł\",lstrok:\"ł\",ltcc:\"⪦\",ltcir:\"⩹\",lt:\"<\",LT:\"<\",Lt:\"≪\",ltdot:\"⋖\",lthree:\"⋋\",ltimes:\"⋉\",ltlarr:\"⥶\",ltquest:\"⩻\",ltri:\"◃\",ltrie:\"⊴\",ltrif:\"◂\",ltrPar:\"⦖\",lurdshar:\"⥊\",luruhar:\"⥦\",lvertneqq:\"≨︀\",lvnE:\"≨︀\",macr:\"¯\",male:\"♂\",malt:\"✠\",maltese:\"✠\",Map:\"⤅\",map:\"↦\",mapsto:\"↦\",mapstodown:\"↧\",mapstoleft:\"↤\",mapstoup:\"↥\",marker:\"▮\",mcomma:\"⨩\",Mcy:\"М\",mcy:\"м\",mdash:\"—\",mDDot:\"∺\",measuredangle:\"∡\",MediumSpace:\" \",Mellintrf:\"ℳ\",Mfr:\"𝔐\",mfr:\"𝔪\",mho:\"℧\",micro:\"µ\",midast:\"*\",midcir:\"⫰\",mid:\"∣\",middot:\"·\",minusb:\"⊟\",minus:\"−\",minusd:\"∸\",minusdu:\"⨪\",MinusPlus:\"∓\",mlcp:\"⫛\",mldr:\"…\",mnplus:\"∓\",models:\"⊧\",Mopf:\"𝕄\",mopf:\"𝕞\",mp:\"∓\",mscr:\"𝓂\",Mscr:\"ℳ\",mstpos:\"∾\",Mu:\"Μ\",mu:\"μ\",multimap:\"⊸\",mumap:\"⊸\",nabla:\"∇\",Nacute:\"Ń\",nacute:\"ń\",nang:\"∠⃒\",nap:\"≉\",napE:\"⩰̸\",napid:\"≋̸\",napos:\"ŉ\",napprox:\"≉\",natural:\"♮\",naturals:\"ℕ\",natur:\"♮\",nbsp:\" \",nbump:\"≎̸\",nbumpe:\"≏̸\",ncap:\"⩃\",Ncaron:\"Ň\",ncaron:\"ň\",Ncedil:\"Ņ\",ncedil:\"ņ\",ncong:\"≇\",ncongdot:\"⩭̸\",ncup:\"⩂\",Ncy:\"Н\",ncy:\"н\",ndash:\"–\",nearhk:\"⤤\",nearr:\"↗\",neArr:\"⇗\",nearrow:\"↗\",ne:\"≠\",nedot:\"≐̸\",NegativeMediumSpace:\"​\",NegativeThickSpace:\"​\",NegativeThinSpace:\"​\",NegativeVeryThinSpace:\"​\",nequiv:\"≢\",nesear:\"⤨\",nesim:\"≂̸\",NestedGreaterGreater:\"≫\",NestedLessLess:\"≪\",NewLine:\"\\n\",nexist:\"∄\",nexists:\"∄\",Nfr:\"𝔑\",nfr:\"𝔫\",ngE:\"≧̸\",nge:\"≱\",ngeq:\"≱\",ngeqq:\"≧̸\",ngeqslant:\"⩾̸\",nges:\"⩾̸\",nGg:\"⋙̸\",ngsim:\"≵\",nGt:\"≫⃒\",ngt:\"≯\",ngtr:\"≯\",nGtv:\"≫̸\",nharr:\"↮\",nhArr:\"⇎\",nhpar:\"⫲\",ni:\"∋\",nis:\"⋼\",nisd:\"⋺\",niv:\"∋\",NJcy:\"Њ\",njcy:\"њ\",nlarr:\"↚\",nlArr:\"⇍\",nldr:\"‥\",nlE:\"≦̸\",nle:\"≰\",nleftarrow:\"↚\",nLeftarrow:\"⇍\",nleftrightarrow:\"↮\",nLeftrightarrow:\"⇎\",nleq:\"≰\",nleqq:\"≦̸\",nleqslant:\"⩽̸\",nles:\"⩽̸\",nless:\"≮\",nLl:\"⋘̸\",nlsim:\"≴\",nLt:\"≪⃒\",nlt:\"≮\",nltri:\"⋪\",nltrie:\"⋬\",nLtv:\"≪̸\",nmid:\"∤\",NoBreak:\"⁠\",NonBreakingSpace:\" \",nopf:\"𝕟\",Nopf:\"ℕ\",Not:\"⫬\",not:\"¬\",NotCongruent:\"≢\",NotCupCap:\"≭\",NotDoubleVerticalBar:\"∦\",NotElement:\"∉\",NotEqual:\"≠\",NotEqualTilde:\"≂̸\",NotExists:\"∄\",NotGreater:\"≯\",NotGreaterEqual:\"≱\",NotGreaterFullEqual:\"≧̸\",NotGreaterGreater:\"≫̸\",NotGreaterLess:\"≹\",NotGreaterSlantEqual:\"⩾̸\",NotGreaterTilde:\"≵\",NotHumpDownHump:\"≎̸\",NotHumpEqual:\"≏̸\",notin:\"∉\",notindot:\"⋵̸\",notinE:\"⋹̸\",notinva:\"∉\",notinvb:\"⋷\",notinvc:\"⋶\",NotLeftTriangleBar:\"⧏̸\",NotLeftTriangle:\"⋪\",NotLeftTriangleEqual:\"⋬\",NotLess:\"≮\",NotLessEqual:\"≰\",NotLessGreater:\"≸\",NotLessLess:\"≪̸\",NotLessSlantEqual:\"⩽̸\",NotLessTilde:\"≴\",NotNestedGreaterGreater:\"⪢̸\",NotNestedLessLess:\"⪡̸\",notni:\"∌\",notniva:\"∌\",notnivb:\"⋾\",notnivc:\"⋽\",NotPrecedes:\"⊀\",NotPrecedesEqual:\"⪯̸\",NotPrecedesSlantEqual:\"⋠\",NotReverseElement:\"∌\",NotRightTriangleBar:\"⧐̸\",NotRightTriangle:\"⋫\",NotRightTriangleEqual:\"⋭\",NotSquareSubset:\"⊏̸\",NotSquareSubsetEqual:\"⋢\",NotSquareSuperset:\"⊐̸\",NotSquareSupersetEqual:\"⋣\",NotSubset:\"⊂⃒\",NotSubsetEqual:\"⊈\",NotSucceeds:\"⊁\",NotSucceedsEqual:\"⪰̸\",NotSucceedsSlantEqual:\"⋡\",NotSucceedsTilde:\"≿̸\",NotSuperset:\"⊃⃒\",NotSupersetEqual:\"⊉\",NotTilde:\"≁\",NotTildeEqual:\"≄\",NotTildeFullEqual:\"≇\",NotTildeTilde:\"≉\",NotVerticalBar:\"∤\",nparallel:\"∦\",npar:\"∦\",nparsl:\"⫽⃥\",npart:\"∂̸\",npolint:\"⨔\",npr:\"⊀\",nprcue:\"⋠\",nprec:\"⊀\",npreceq:\"⪯̸\",npre:\"⪯̸\",nrarrc:\"⤳̸\",nrarr:\"↛\",nrArr:\"⇏\",nrarrw:\"↝̸\",nrightarrow:\"↛\",nRightarrow:\"⇏\",nrtri:\"⋫\",nrtrie:\"⋭\",nsc:\"⊁\",nsccue:\"⋡\",nsce:\"⪰̸\",Nscr:\"𝒩\",nscr:\"𝓃\",nshortmid:\"∤\",nshortparallel:\"∦\",nsim:\"≁\",nsime:\"≄\",nsimeq:\"≄\",nsmid:\"∤\",nspar:\"∦\",nsqsube:\"⋢\",nsqsupe:\"⋣\",nsub:\"⊄\",nsubE:\"⫅̸\",nsube:\"⊈\",nsubset:\"⊂⃒\",nsubseteq:\"⊈\",nsubseteqq:\"⫅̸\",nsucc:\"⊁\",nsucceq:\"⪰̸\",nsup:\"⊅\",nsupE:\"⫆̸\",nsupe:\"⊉\",nsupset:\"⊃⃒\",nsupseteq:\"⊉\",nsupseteqq:\"⫆̸\",ntgl:\"≹\",Ntilde:\"Ñ\",ntilde:\"ñ\",ntlg:\"≸\",ntriangleleft:\"⋪\",ntrianglelefteq:\"⋬\",ntriangleright:\"⋫\",ntrianglerighteq:\"⋭\",Nu:\"Ν\",nu:\"ν\",num:\"#\",numero:\"№\",numsp:\" \",nvap:\"≍⃒\",nvdash:\"⊬\",nvDash:\"⊭\",nVdash:\"⊮\",nVDash:\"⊯\",nvge:\"≥⃒\",nvgt:\">⃒\",nvHarr:\"⤄\",nvinfin:\"⧞\",nvlArr:\"⤂\",nvle:\"≤⃒\",nvlt:\"<⃒\",nvltrie:\"⊴⃒\",nvrArr:\"⤃\",nvrtrie:\"⊵⃒\",nvsim:\"∼⃒\",nwarhk:\"⤣\",nwarr:\"↖\",nwArr:\"⇖\",nwarrow:\"↖\",nwnear:\"⤧\",Oacute:\"Ó\",oacute:\"ó\",oast:\"⊛\",Ocirc:\"Ô\",ocirc:\"ô\",ocir:\"⊚\",Ocy:\"О\",ocy:\"о\",odash:\"⊝\",Odblac:\"Ő\",odblac:\"ő\",odiv:\"⨸\",odot:\"⊙\",odsold:\"⦼\",OElig:\"Œ\",oelig:\"œ\",ofcir:\"⦿\",Ofr:\"𝔒\",ofr:\"𝔬\",ogon:\"˛\",Ograve:\"Ò\",ograve:\"ò\",ogt:\"⧁\",ohbar:\"⦵\",ohm:\"Ω\",oint:\"∮\",olarr:\"↺\",olcir:\"⦾\",olcross:\"⦻\",oline:\"‾\",olt:\"⧀\",Omacr:\"Ō\",omacr:\"ō\",Omega:\"Ω\",omega:\"ω\",Omicron:\"Ο\",omicron:\"ο\",omid:\"⦶\",ominus:\"⊖\",Oopf:\"𝕆\",oopf:\"𝕠\",opar:\"⦷\",OpenCurlyDoubleQuote:\"“\",OpenCurlyQuote:\"‘\",operp:\"⦹\",oplus:\"⊕\",orarr:\"↻\",Or:\"⩔\",or:\"∨\",ord:\"⩝\",order:\"ℴ\",orderof:\"ℴ\",ordf:\"ª\",ordm:\"º\",origof:\"⊶\",oror:\"⩖\",orslope:\"⩗\",orv:\"⩛\",oS:\"Ⓢ\",Oscr:\"𝒪\",oscr:\"ℴ\",Oslash:\"Ø\",oslash:\"ø\",osol:\"⊘\",Otilde:\"Õ\",otilde:\"õ\",otimesas:\"⨶\",Otimes:\"⨷\",otimes:\"⊗\",Ouml:\"Ö\",ouml:\"ö\",ovbar:\"⌽\",OverBar:\"‾\",OverBrace:\"⏞\",OverBracket:\"⎴\",OverParenthesis:\"⏜\",para:\"¶\",parallel:\"∥\",par:\"∥\",parsim:\"⫳\",parsl:\"⫽\",part:\"∂\",PartialD:\"∂\",Pcy:\"П\",pcy:\"п\",percnt:\"%\",period:\".\",permil:\"‰\",perp:\"⊥\",pertenk:\"‱\",Pfr:\"𝔓\",pfr:\"𝔭\",Phi:\"Φ\",phi:\"φ\",phiv:\"ϕ\",phmmat:\"ℳ\",phone:\"☎\",Pi:\"Π\",pi:\"π\",pitchfork:\"⋔\",piv:\"ϖ\",planck:\"ℏ\",planckh:\"ℎ\",plankv:\"ℏ\",plusacir:\"⨣\",plusb:\"⊞\",pluscir:\"⨢\",plus:\"+\",plusdo:\"∔\",plusdu:\"⨥\",pluse:\"⩲\",PlusMinus:\"±\",plusmn:\"±\",plussim:\"⨦\",plustwo:\"⨧\",pm:\"±\",Poincareplane:\"ℌ\",pointint:\"⨕\",popf:\"𝕡\",Popf:\"ℙ\",pound:\"£\",prap:\"⪷\",Pr:\"⪻\",pr:\"≺\",prcue:\"≼\",precapprox:\"⪷\",prec:\"≺\",preccurlyeq:\"≼\",Precedes:\"≺\",PrecedesEqual:\"⪯\",PrecedesSlantEqual:\"≼\",PrecedesTilde:\"≾\",preceq:\"⪯\",precnapprox:\"⪹\",precneqq:\"⪵\",precnsim:\"⋨\",pre:\"⪯\",prE:\"⪳\",precsim:\"≾\",prime:\"′\",Prime:\"″\",primes:\"ℙ\",prnap:\"⪹\",prnE:\"⪵\",prnsim:\"⋨\",prod:\"∏\",Product:\"∏\",profalar:\"⌮\",profline:\"⌒\",profsurf:\"⌓\",prop:\"∝\",Proportional:\"∝\",Proportion:\"∷\",propto:\"∝\",prsim:\"≾\",prurel:\"⊰\",Pscr:\"𝒫\",pscr:\"𝓅\",Psi:\"Ψ\",psi:\"ψ\",puncsp:\" \",Qfr:\"𝔔\",qfr:\"𝔮\",qint:\"⨌\",qopf:\"𝕢\",Qopf:\"ℚ\",qprime:\"⁗\",Qscr:\"𝒬\",qscr:\"𝓆\",quaternions:\"ℍ\",quatint:\"⨖\",quest:\"?\",questeq:\"≟\",quot:'\"',QUOT:'\"',rAarr:\"⇛\",race:\"∽̱\",Racute:\"Ŕ\",racute:\"ŕ\",radic:\"√\",raemptyv:\"⦳\",rang:\"⟩\",Rang:\"⟫\",rangd:\"⦒\",range:\"⦥\",rangle:\"⟩\",raquo:\"»\",rarrap:\"⥵\",rarrb:\"⇥\",rarrbfs:\"⤠\",rarrc:\"⤳\",rarr:\"→\",Rarr:\"↠\",rArr:\"⇒\",rarrfs:\"⤞\",rarrhk:\"↪\",rarrlp:\"↬\",rarrpl:\"⥅\",rarrsim:\"⥴\",Rarrtl:\"⤖\",rarrtl:\"↣\",rarrw:\"↝\",ratail:\"⤚\",rAtail:\"⤜\",ratio:\"∶\",rationals:\"ℚ\",rbarr:\"⤍\",rBarr:\"⤏\",RBarr:\"⤐\",rbbrk:\"❳\",rbrace:\"}\",rbrack:\"]\",rbrke:\"⦌\",rbrksld:\"⦎\",rbrkslu:\"⦐\",Rcaron:\"Ř\",rcaron:\"ř\",Rcedil:\"Ŗ\",rcedil:\"ŗ\",rceil:\"⌉\",rcub:\"}\",Rcy:\"Р\",rcy:\"р\",rdca:\"⤷\",rdldhar:\"⥩\",rdquo:\"”\",rdquor:\"”\",rdsh:\"↳\",real:\"ℜ\",realine:\"ℛ\",realpart:\"ℜ\",reals:\"ℝ\",Re:\"ℜ\",rect:\"▭\",reg:\"®\",REG:\"®\",ReverseElement:\"∋\",ReverseEquilibrium:\"⇋\",ReverseUpEquilibrium:\"⥯\",rfisht:\"⥽\",rfloor:\"⌋\",rfr:\"𝔯\",Rfr:\"ℜ\",rHar:\"⥤\",rhard:\"⇁\",rharu:\"⇀\",rharul:\"⥬\",Rho:\"Ρ\",rho:\"ρ\",rhov:\"ϱ\",RightAngleBracket:\"⟩\",RightArrowBar:\"⇥\",rightarrow:\"→\",RightArrow:\"→\",Rightarrow:\"⇒\",RightArrowLeftArrow:\"⇄\",rightarrowtail:\"↣\",RightCeiling:\"⌉\",RightDoubleBracket:\"⟧\",RightDownTeeVector:\"⥝\",RightDownVectorBar:\"⥕\",RightDownVector:\"⇂\",RightFloor:\"⌋\",rightharpoondown:\"⇁\",rightharpoonup:\"⇀\",rightleftarrows:\"⇄\",rightleftharpoons:\"⇌\",rightrightarrows:\"⇉\",rightsquigarrow:\"↝\",RightTeeArrow:\"↦\",RightTee:\"⊢\",RightTeeVector:\"⥛\",rightthreetimes:\"⋌\",RightTriangleBar:\"⧐\",RightTriangle:\"⊳\",RightTriangleEqual:\"⊵\",RightUpDownVector:\"⥏\",RightUpTeeVector:\"⥜\",RightUpVectorBar:\"⥔\",RightUpVector:\"↾\",RightVectorBar:\"⥓\",RightVector:\"⇀\",ring:\"˚\",risingdotseq:\"≓\",rlarr:\"⇄\",rlhar:\"⇌\",rlm:\"‏\",rmoustache:\"⎱\",rmoust:\"⎱\",rnmid:\"⫮\",roang:\"⟭\",roarr:\"⇾\",robrk:\"⟧\",ropar:\"⦆\",ropf:\"𝕣\",Ropf:\"ℝ\",roplus:\"⨮\",rotimes:\"⨵\",RoundImplies:\"⥰\",rpar:\")\",rpargt:\"⦔\",rppolint:\"⨒\",rrarr:\"⇉\",Rrightarrow:\"⇛\",rsaquo:\"›\",rscr:\"𝓇\",Rscr:\"ℛ\",rsh:\"↱\",Rsh:\"↱\",rsqb:\"]\",rsquo:\"’\",rsquor:\"’\",rthree:\"⋌\",rtimes:\"⋊\",rtri:\"▹\",rtrie:\"⊵\",rtrif:\"▸\",rtriltri:\"⧎\",RuleDelayed:\"⧴\",ruluhar:\"⥨\",rx:\"℞\",Sacute:\"Ś\",sacute:\"ś\",sbquo:\"‚\",scap:\"⪸\",Scaron:\"Š\",scaron:\"š\",Sc:\"⪼\",sc:\"≻\",sccue:\"≽\",sce:\"⪰\",scE:\"⪴\",Scedil:\"Ş\",scedil:\"ş\",Scirc:\"Ŝ\",scirc:\"ŝ\",scnap:\"⪺\",scnE:\"⪶\",scnsim:\"⋩\",scpolint:\"⨓\",scsim:\"≿\",Scy:\"С\",scy:\"с\",sdotb:\"⊡\",sdot:\"⋅\",sdote:\"⩦\",searhk:\"⤥\",searr:\"↘\",seArr:\"⇘\",searrow:\"↘\",sect:\"§\",semi:\";\",seswar:\"⤩\",setminus:\"∖\",setmn:\"∖\",sext:\"✶\",Sfr:\"𝔖\",sfr:\"𝔰\",sfrown:\"⌢\",sharp:\"♯\",SHCHcy:\"Щ\",shchcy:\"щ\",SHcy:\"Ш\",shcy:\"ш\",ShortDownArrow:\"↓\",ShortLeftArrow:\"←\",shortmid:\"∣\",shortparallel:\"∥\",ShortRightArrow:\"→\",ShortUpArrow:\"↑\",shy:\"­\",Sigma:\"Σ\",sigma:\"σ\",sigmaf:\"ς\",sigmav:\"ς\",sim:\"∼\",simdot:\"⩪\",sime:\"≃\",simeq:\"≃\",simg:\"⪞\",simgE:\"⪠\",siml:\"⪝\",simlE:\"⪟\",simne:\"≆\",simplus:\"⨤\",simrarr:\"⥲\",slarr:\"←\",SmallCircle:\"∘\",smallsetminus:\"∖\",smashp:\"⨳\",smeparsl:\"⧤\",smid:\"∣\",smile:\"⌣\",smt:\"⪪\",smte:\"⪬\",smtes:\"⪬︀\",SOFTcy:\"Ь\",softcy:\"ь\",solbar:\"⌿\",solb:\"⧄\",sol:\"/\",Sopf:\"𝕊\",sopf:\"𝕤\",spades:\"♠\",spadesuit:\"♠\",spar:\"∥\",sqcap:\"⊓\",sqcaps:\"⊓︀\",sqcup:\"⊔\",sqcups:\"⊔︀\",Sqrt:\"√\",sqsub:\"⊏\",sqsube:\"⊑\",sqsubset:\"⊏\",sqsubseteq:\"⊑\",sqsup:\"⊐\",sqsupe:\"⊒\",sqsupset:\"⊐\",sqsupseteq:\"⊒\",square:\"□\",Square:\"□\",SquareIntersection:\"⊓\",SquareSubset:\"⊏\",SquareSubsetEqual:\"⊑\",SquareSuperset:\"⊐\",SquareSupersetEqual:\"⊒\",SquareUnion:\"⊔\",squarf:\"▪\",squ:\"□\",squf:\"▪\",srarr:\"→\",Sscr:\"𝒮\",sscr:\"𝓈\",ssetmn:\"∖\",ssmile:\"⌣\",sstarf:\"⋆\",Star:\"⋆\",star:\"☆\",starf:\"★\",straightepsilon:\"ϵ\",straightphi:\"ϕ\",strns:\"¯\",sub:\"⊂\",Sub:\"⋐\",subdot:\"⪽\",subE:\"⫅\",sube:\"⊆\",subedot:\"⫃\",submult:\"⫁\",subnE:\"⫋\",subne:\"⊊\",subplus:\"⪿\",subrarr:\"⥹\",subset:\"⊂\",Subset:\"⋐\",subseteq:\"⊆\",subseteqq:\"⫅\",SubsetEqual:\"⊆\",subsetneq:\"⊊\",subsetneqq:\"⫋\",subsim:\"⫇\",subsub:\"⫕\",subsup:\"⫓\",succapprox:\"⪸\",succ:\"≻\",succcurlyeq:\"≽\",Succeeds:\"≻\",SucceedsEqual:\"⪰\",SucceedsSlantEqual:\"≽\",SucceedsTilde:\"≿\",succeq:\"⪰\",succnapprox:\"⪺\",succneqq:\"⪶\",succnsim:\"⋩\",succsim:\"≿\",SuchThat:\"∋\",sum:\"∑\",Sum:\"∑\",sung:\"♪\",sup1:\"¹\",sup2:\"²\",sup3:\"³\",sup:\"⊃\",Sup:\"⋑\",supdot:\"⪾\",supdsub:\"⫘\",supE:\"⫆\",supe:\"⊇\",supedot:\"⫄\",Superset:\"⊃\",SupersetEqual:\"⊇\",suphsol:\"⟉\",suphsub:\"⫗\",suplarr:\"⥻\",supmult:\"⫂\",supnE:\"⫌\",supne:\"⊋\",supplus:\"⫀\",supset:\"⊃\",Supset:\"⋑\",supseteq:\"⊇\",supseteqq:\"⫆\",supsetneq:\"⊋\",supsetneqq:\"⫌\",supsim:\"⫈\",supsub:\"⫔\",supsup:\"⫖\",swarhk:\"⤦\",swarr:\"↙\",swArr:\"⇙\",swarrow:\"↙\",swnwar:\"⤪\",szlig:\"ß\",Tab:\"\\t\",target:\"⌖\",Tau:\"Τ\",tau:\"τ\",tbrk:\"⎴\",Tcaron:\"Ť\",tcaron:\"ť\",Tcedil:\"Ţ\",tcedil:\"ţ\",Tcy:\"Т\",tcy:\"т\",tdot:\"⃛\",telrec:\"⌕\",Tfr:\"𝔗\",tfr:\"𝔱\",there4:\"∴\",therefore:\"∴\",Therefore:\"∴\",Theta:\"Θ\",theta:\"θ\",thetasym:\"ϑ\",thetav:\"ϑ\",thickapprox:\"≈\",thicksim:\"∼\",ThickSpace:\"  \",ThinSpace:\" \",thinsp:\" \",thkap:\"≈\",thksim:\"∼\",THORN:\"Þ\",thorn:\"þ\",tilde:\"˜\",Tilde:\"∼\",TildeEqual:\"≃\",TildeFullEqual:\"≅\",TildeTilde:\"≈\",timesbar:\"⨱\",timesb:\"⊠\",times:\"×\",timesd:\"⨰\",tint:\"∭\",toea:\"⤨\",topbot:\"⌶\",topcir:\"⫱\",top:\"⊤\",Topf:\"𝕋\",topf:\"𝕥\",topfork:\"⫚\",tosa:\"⤩\",tprime:\"‴\",trade:\"™\",TRADE:\"™\",triangle:\"▵\",triangledown:\"▿\",triangleleft:\"◃\",trianglelefteq:\"⊴\",triangleq:\"≜\",triangleright:\"▹\",trianglerighteq:\"⊵\",tridot:\"◬\",trie:\"≜\",triminus:\"⨺\",TripleDot:\"⃛\",triplus:\"⨹\",trisb:\"⧍\",tritime:\"⨻\",trpezium:\"⏢\",Tscr:\"𝒯\",tscr:\"𝓉\",TScy:\"Ц\",tscy:\"ц\",TSHcy:\"Ћ\",tshcy:\"ћ\",Tstrok:\"Ŧ\",tstrok:\"ŧ\",twixt:\"≬\",twoheadleftarrow:\"↞\",twoheadrightarrow:\"↠\",Uacute:\"Ú\",uacute:\"ú\",uarr:\"↑\",Uarr:\"↟\",uArr:\"⇑\",Uarrocir:\"⥉\",Ubrcy:\"Ў\",ubrcy:\"ў\",Ubreve:\"Ŭ\",ubreve:\"ŭ\",Ucirc:\"Û\",ucirc:\"û\",Ucy:\"У\",ucy:\"у\",udarr:\"⇅\",Udblac:\"Ű\",udblac:\"ű\",udhar:\"⥮\",ufisht:\"⥾\",Ufr:\"𝔘\",ufr:\"𝔲\",Ugrave:\"Ù\",ugrave:\"ù\",uHar:\"⥣\",uharl:\"↿\",uharr:\"↾\",uhblk:\"▀\",ulcorn:\"⌜\",ulcorner:\"⌜\",ulcrop:\"⌏\",ultri:\"◸\",Umacr:\"Ū\",umacr:\"ū\",uml:\"¨\",UnderBar:\"_\",UnderBrace:\"⏟\",UnderBracket:\"⎵\",UnderParenthesis:\"⏝\",Union:\"⋃\",UnionPlus:\"⊎\",Uogon:\"Ų\",uogon:\"ų\",Uopf:\"𝕌\",uopf:\"𝕦\",UpArrowBar:\"⤒\",uparrow:\"↑\",UpArrow:\"↑\",Uparrow:\"⇑\",UpArrowDownArrow:\"⇅\",updownarrow:\"↕\",UpDownArrow:\"↕\",Updownarrow:\"⇕\",UpEquilibrium:\"⥮\",upharpoonleft:\"↿\",upharpoonright:\"↾\",uplus:\"⊎\",UpperLeftArrow:\"↖\",UpperRightArrow:\"↗\",upsi:\"υ\",Upsi:\"ϒ\",upsih:\"ϒ\",Upsilon:\"Υ\",upsilon:\"υ\",UpTeeArrow:\"↥\",UpTee:\"⊥\",upuparrows:\"⇈\",urcorn:\"⌝\",urcorner:\"⌝\",urcrop:\"⌎\",Uring:\"Ů\",uring:\"ů\",urtri:\"◹\",Uscr:\"𝒰\",uscr:\"𝓊\",utdot:\"⋰\",Utilde:\"Ũ\",utilde:\"ũ\",utri:\"▵\",utrif:\"▴\",uuarr:\"⇈\",Uuml:\"Ü\",uuml:\"ü\",uwangle:\"⦧\",vangrt:\"⦜\",varepsilon:\"ϵ\",varkappa:\"ϰ\",varnothing:\"∅\",varphi:\"ϕ\",varpi:\"ϖ\",varpropto:\"∝\",varr:\"↕\",vArr:\"⇕\",varrho:\"ϱ\",varsigma:\"ς\",varsubsetneq:\"⊊︀\",varsubsetneqq:\"⫋︀\",varsupsetneq:\"⊋︀\",varsupsetneqq:\"⫌︀\",vartheta:\"ϑ\",vartriangleleft:\"⊲\",vartriangleright:\"⊳\",vBar:\"⫨\",Vbar:\"⫫\",vBarv:\"⫩\",Vcy:\"В\",vcy:\"в\",vdash:\"⊢\",vDash:\"⊨\",Vdash:\"⊩\",VDash:\"⊫\",Vdashl:\"⫦\",veebar:\"⊻\",vee:\"∨\",Vee:\"⋁\",veeeq:\"≚\",vellip:\"⋮\",verbar:\"|\",Verbar:\"‖\",vert:\"|\",Vert:\"‖\",VerticalBar:\"∣\",VerticalLine:\"|\",VerticalSeparator:\"❘\",VerticalTilde:\"≀\",VeryThinSpace:\" \",Vfr:\"𝔙\",vfr:\"𝔳\",vltri:\"⊲\",vnsub:\"⊂⃒\",vnsup:\"⊃⃒\",Vopf:\"𝕍\",vopf:\"𝕧\",vprop:\"∝\",vrtri:\"⊳\",Vscr:\"𝒱\",vscr:\"𝓋\",vsubnE:\"⫋︀\",vsubne:\"⊊︀\",vsupnE:\"⫌︀\",vsupne:\"⊋︀\",Vvdash:\"⊪\",vzigzag:\"⦚\",Wcirc:\"Ŵ\",wcirc:\"ŵ\",wedbar:\"⩟\",wedge:\"∧\",Wedge:\"⋀\",wedgeq:\"≙\",weierp:\"℘\",Wfr:\"𝔚\",wfr:\"𝔴\",Wopf:\"𝕎\",wopf:\"𝕨\",wp:\"℘\",wr:\"≀\",wreath:\"≀\",Wscr:\"𝒲\",wscr:\"𝓌\",xcap:\"⋂\",xcirc:\"◯\",xcup:\"⋃\",xdtri:\"▽\",Xfr:\"𝔛\",xfr:\"𝔵\",xharr:\"⟷\",xhArr:\"⟺\",Xi:\"Ξ\",xi:\"ξ\",xlarr:\"⟵\",xlArr:\"⟸\",xmap:\"⟼\",xnis:\"⋻\",xodot:\"⨀\",Xopf:\"𝕏\",xopf:\"𝕩\",xoplus:\"⨁\",xotime:\"⨂\",xrarr:\"⟶\",xrArr:\"⟹\",Xscr:\"𝒳\",xscr:\"𝓍\",xsqcup:\"⨆\",xuplus:\"⨄\",xutri:\"△\",xvee:\"⋁\",xwedge:\"⋀\",Yacute:\"Ý\",yacute:\"ý\",YAcy:\"Я\",yacy:\"я\",Ycirc:\"Ŷ\",ycirc:\"ŷ\",Ycy:\"Ы\",ycy:\"ы\",yen:\"¥\",Yfr:\"𝔜\",yfr:\"𝔶\",YIcy:\"Ї\",yicy:\"ї\",Yopf:\"𝕐\",yopf:\"𝕪\",Yscr:\"𝒴\",yscr:\"𝓎\",YUcy:\"Ю\",yucy:\"ю\",yuml:\"ÿ\",Yuml:\"Ÿ\",Zacute:\"Ź\",zacute:\"ź\",Zcaron:\"Ž\",zcaron:\"ž\",Zcy:\"З\",zcy:\"з\",Zdot:\"Ż\",zdot:\"ż\",zeetrf:\"ℨ\",ZeroWidthSpace:\"​\",Zeta:\"Ζ\",zeta:\"ζ\",zfr:\"𝔷\",Zfr:\"ℨ\",ZHcy:\"Ж\",zhcy:\"ж\",zigrarr:\"⇝\",zopf:\"𝕫\",Zopf:\"ℤ\",Zscr:\"𝒵\",zscr:\"𝓏\",zwj:\"‍\",zwnj:\"‌\"}},{}],26:[function(require,module,exports){module.exports={Aacute:\"Á\",aacute:\"á\",Acirc:\"Â\",acirc:\"â\",acute:\"´\",AElig:\"Æ\",aelig:\"æ\",Agrave:\"À\",agrave:\"à\",amp:\"&\",AMP:\"&\",Aring:\"Å\",aring:\"å\",Atilde:\"Ã\",atilde:\"ã\",Auml:\"Ä\",auml:\"ä\",brvbar:\"¦\",Ccedil:\"Ç\",ccedil:\"ç\",cedil:\"¸\",cent:\"¢\",copy:\"©\",COPY:\"©\",curren:\"¤\",deg:\"°\",divide:\"÷\",Eacute:\"É\",eacute:\"é\",Ecirc:\"Ê\",ecirc:\"ê\",Egrave:\"È\",egrave:\"è\",ETH:\"Ð\",eth:\"ð\",Euml:\"Ë\",euml:\"ë\",frac12:\"½\",frac14:\"¼\",frac34:\"¾\",gt:\">\",GT:\">\",Iacute:\"Í\",iacute:\"í\",Icirc:\"Î\",icirc:\"î\",iexcl:\"¡\",Igrave:\"Ì\",igrave:\"ì\",iquest:\"¿\",Iuml:\"Ï\",iuml:\"ï\",laquo:\"«\",lt:\"<\",LT:\"<\",macr:\"¯\",micro:\"µ\",middot:\"·\",nbsp:\" \",not:\"¬\",Ntilde:\"Ñ\",ntilde:\"ñ\",Oacute:\"Ó\",oacute:\"ó\",Ocirc:\"Ô\",ocirc:\"ô\",Ograve:\"Ò\",ograve:\"ò\",ordf:\"ª\",ordm:\"º\",Oslash:\"Ø\",oslash:\"ø\",Otilde:\"Õ\",otilde:\"õ\",Ouml:\"Ö\",ouml:\"ö\",para:\"¶\",plusmn:\"±\",pound:\"£\",quot:'\"',QUOT:'\"',raquo:\"»\",reg:\"®\",REG:\"®\",sect:\"§\",shy:\"­\",sup1:\"¹\",sup2:\"²\",sup3:\"³\",szlig:\"ß\",THORN:\"Þ\",thorn:\"þ\",times:\"×\",Uacute:\"Ú\",uacute:\"ú\",Ucirc:\"Û\",ucirc:\"û\",Ugrave:\"Ù\",ugrave:\"ù\",uml:\"¨\",Uuml:\"Ü\",uuml:\"ü\",Yacute:\"Ý\",yacute:\"ý\",yen:\"¥\",yuml:\"ÿ\"}},{}],27:[function(require,module,exports){module.exports={amp:\"&\",apos:\"'\",gt:\">\",lt:\"<\",quot:'\"'}},{}],28:[function(require,module,exports){function EventEmitter(){this._events=this._events||{};this._maxListeners=this._maxListeners||undefined}module.exports=EventEmitter;EventEmitter.EventEmitter=EventEmitter;EventEmitter.prototype._events=undefined;EventEmitter.prototype._maxListeners=undefined;EventEmitter.defaultMaxListeners=10;EventEmitter.prototype.setMaxListeners=function(n){if(!isNumber(n)||n<0||isNaN(n))throw TypeError(\"n must be a positive number\");this._maxListeners=n;return this};EventEmitter.prototype.emit=function(type){var er,handler,len,args,i,listeners;if(!this._events)this._events={};if(type===\"error\"){if(!this._events.error||isObject(this._events.error)&&!this._events.error.length){er=arguments[1];if(er instanceof Error){throw er}else{var err=new Error('Uncaught, unspecified \"error\" event. ('+er+\")\");err.context=er;throw err}}}handler=this._events[type];if(isUndefined(handler))return false;if(isFunction(handler)){switch(arguments.length){case 1:handler.call(this);break;case 2:handler.call(this,arguments[1]);break;case 3:handler.call(this,arguments[1],arguments[2]);break;default:args=Array.prototype.slice.call(arguments,1);handler.apply(this,args)}}else if(isObject(handler)){args=Array.prototype.slice.call(arguments,1);listeners=handler.slice();len=listeners.length;for(i=0;i<len;i++)listeners[i].apply(this,args)}return true};EventEmitter.prototype.addListener=function(type,listener){var m;if(!isFunction(listener))throw TypeError(\"listener must be a function\");if(!this._events)this._events={};if(this._events.newListener)this.emit(\"newListener\",type,isFunction(listener.listener)?listener.listener:listener);if(!this._events[type])this._events[type]=listener;else if(isObject(this._events[type]))this._events[type].push(listener);else this._events[type]=[this._events[type],listener];if(isObject(this._events[type])&&!this._events[type].warned){if(!isUndefined(this._maxListeners)){m=this._maxListeners}else{m=EventEmitter.defaultMaxListeners}if(m&&m>0&&this._events[type].length>m){this._events[type].warned=true;console.error(\"(node) warning: possible EventEmitter memory \"+\"leak detected. %d listeners added. \"+\"Use emitter.setMaxListeners() to increase limit.\",this._events[type].length);if(typeof console.trace===\"function\"){console.trace()}}}return this};EventEmitter.prototype.on=EventEmitter.prototype.addListener;EventEmitter.prototype.once=function(type,listener){if(!isFunction(listener))throw TypeError(\"listener must be a function\");var fired=false;function g(){this.removeListener(type,g);if(!fired){fired=true;listener.apply(this,arguments)}}g.listener=listener;this.on(type,g);return this};EventEmitter.prototype.removeListener=function(type,listener){var list,position,length,i;if(!isFunction(listener))throw TypeError(\"listener must be a function\");if(!this._events||!this._events[type])return this;list=this._events[type];length=list.length;position=-1;if(list===listener||isFunction(list.listener)&&list.listener===listener){delete this._events[type];if(this._events.removeListener)this.emit(\"removeListener\",type,listener)}else if(isObject(list)){for(i=length;i-- >0;){if(list[i]===listener||list[i].listener&&list[i].listener===listener){position=i;break}}if(position<0)return this;if(list.length===1){list.length=0;delete this._events[type]}else{list.splice(position,1);\n}if(this._events.removeListener)this.emit(\"removeListener\",type,listener)}return this};EventEmitter.prototype.removeAllListeners=function(type){var key,listeners;if(!this._events)return this;if(!this._events.removeListener){if(arguments.length===0)this._events={};else if(this._events[type])delete this._events[type];return this}if(arguments.length===0){for(key in this._events){if(key===\"removeListener\")continue;this.removeAllListeners(key)}this.removeAllListeners(\"removeListener\");this._events={};return this}listeners=this._events[type];if(isFunction(listeners)){this.removeListener(type,listeners)}else if(listeners){while(listeners.length)this.removeListener(type,listeners[listeners.length-1])}delete this._events[type];return this};EventEmitter.prototype.listeners=function(type){var ret;if(!this._events||!this._events[type])ret=[];else if(isFunction(this._events[type]))ret=[this._events[type]];else ret=this._events[type].slice();return ret};EventEmitter.prototype.listenerCount=function(type){if(this._events){var evlistener=this._events[type];if(isFunction(evlistener))return 1;else if(evlistener)return evlistener.length}return 0};EventEmitter.listenerCount=function(emitter,type){return emitter.listenerCount(type)};function isFunction(arg){return typeof arg===\"function\"}function isNumber(arg){return typeof arg===\"number\"}function isObject(arg){return typeof arg===\"object\"&&arg!==null}function isUndefined(arg){return arg===void 0}},{}],29:[function(require,module,exports){module.exports=CollectingHandler;function CollectingHandler(cbs){this._cbs=cbs||{};this.events=[]}var EVENTS=require(\"./\").EVENTS;Object.keys(EVENTS).forEach(function(name){if(EVENTS[name]===0){name=\"on\"+name;CollectingHandler.prototype[name]=function(){this.events.push([name]);if(this._cbs[name])this._cbs[name]()}}else if(EVENTS[name]===1){name=\"on\"+name;CollectingHandler.prototype[name]=function(a){this.events.push([name,a]);if(this._cbs[name])this._cbs[name](a)}}else if(EVENTS[name]===2){name=\"on\"+name;CollectingHandler.prototype[name]=function(a,b){this.events.push([name,a,b]);if(this._cbs[name])this._cbs[name](a,b)}}else{throw Error(\"wrong number of arguments\")}});CollectingHandler.prototype.onreset=function(){this.events=[];if(this._cbs.onreset)this._cbs.onreset()};CollectingHandler.prototype.restart=function(){if(this._cbs.onreset)this._cbs.onreset();for(var i=0,len=this.events.length;i<len;i++){if(this._cbs[this.events[i][0]]){var num=this.events[i].length;if(num===1){this._cbs[this.events[i][0]]()}else if(num===2){this._cbs[this.events[i][0]](this.events[i][1])}else{this._cbs[this.events[i][0]](this.events[i][1],this.events[i][2])}}}}},{\"./\":36}],30:[function(require,module,exports){var index=require(\"./index.js\"),DomHandler=index.DomHandler,DomUtils=index.DomUtils;function FeedHandler(callback,options){this.init(callback,options)}require(\"inherits\")(FeedHandler,DomHandler);FeedHandler.prototype.init=DomHandler;function getElements(what,where){return DomUtils.getElementsByTagName(what,where,true)}function getOneElement(what,where){return DomUtils.getElementsByTagName(what,where,true,1)[0]}function fetch(what,where,recurse){return DomUtils.getText(DomUtils.getElementsByTagName(what,where,recurse,1)).trim()}function addConditionally(obj,prop,what,where,recurse){var tmp=fetch(what,where,recurse);if(tmp)obj[prop]=tmp}var isValidFeed=function(value){return value===\"rss\"||value===\"feed\"||value===\"rdf:RDF\"};FeedHandler.prototype.onend=function(){var feed={},feedRoot=getOneElement(isValidFeed,this.dom),tmp,childs;if(feedRoot){if(feedRoot.name===\"feed\"){childs=feedRoot.children;feed.type=\"atom\";addConditionally(feed,\"id\",\"id\",childs);addConditionally(feed,\"title\",\"title\",childs);if((tmp=getOneElement(\"link\",childs))&&(tmp=tmp.attribs)&&(tmp=tmp.href))feed.link=tmp;addConditionally(feed,\"description\",\"subtitle\",childs);if(tmp=fetch(\"updated\",childs))feed.updated=new Date(tmp);addConditionally(feed,\"author\",\"email\",childs,true);feed.items=getElements(\"entry\",childs).map(function(item){var entry={},tmp;item=item.children;addConditionally(entry,\"id\",\"id\",item);addConditionally(entry,\"title\",\"title\",item);if((tmp=getOneElement(\"link\",item))&&(tmp=tmp.attribs)&&(tmp=tmp.href))entry.link=tmp;if(tmp=fetch(\"summary\",item)||fetch(\"content\",item))entry.description=tmp;if(tmp=fetch(\"updated\",item))entry.pubDate=new Date(tmp);return entry})}else{childs=getOneElement(\"channel\",feedRoot.children).children;feed.type=feedRoot.name.substr(0,3);feed.id=\"\";addConditionally(feed,\"title\",\"title\",childs);addConditionally(feed,\"link\",\"link\",childs);addConditionally(feed,\"description\",\"description\",childs);if(tmp=fetch(\"lastBuildDate\",childs))feed.updated=new Date(tmp);addConditionally(feed,\"author\",\"managingEditor\",childs,true);feed.items=getElements(\"item\",feedRoot.children).map(function(item){var entry={},tmp;item=item.children;addConditionally(entry,\"id\",\"guid\",item);addConditionally(entry,\"title\",\"title\",item);addConditionally(entry,\"link\",\"link\",item);addConditionally(entry,\"description\",\"description\",item);if(tmp=fetch(\"pubDate\",item))entry.pubDate=new Date(tmp);return entry})}}this.dom=feed;DomHandler.prototype._handleCallback.call(this,feedRoot?null:Error(\"couldn't find root of feed\"))};module.exports=FeedHandler},{\"./index.js\":36,inherits:38}],31:[function(require,module,exports){var Tokenizer=require(\"./Tokenizer.js\");var formTags={input:true,option:true,optgroup:true,select:true,button:true,datalist:true,textarea:true};var openImpliesClose={tr:{tr:true,th:true,td:true},th:{th:true},td:{thead:true,th:true,td:true},body:{head:true,link:true,script:true},li:{li:true},p:{p:true},h1:{p:true},h2:{p:true},h3:{p:true},h4:{p:true},h5:{p:true},h6:{p:true},select:formTags,input:formTags,output:formTags,button:formTags,datalist:formTags,textarea:formTags,option:{option:true},optgroup:{optgroup:true}};var voidElements={__proto__:null,area:true,base:true,basefont:true,br:true,col:true,command:true,embed:true,frame:true,hr:true,img:true,input:true,isindex:true,keygen:true,link:true,meta:true,param:true,source:true,track:true,wbr:true,path:true,circle:true,ellipse:true,line:true,rect:true,use:true,stop:true,polyline:true,polygon:true};var re_nameEnd=/\\s|\\//;function Parser(cbs,options){this._options=options||{};this._cbs=cbs||{};this._tagname=\"\";this._attribname=\"\";this._attribvalue=\"\";this._attribs=null;this._stack=[];this.startIndex=0;this.endIndex=null;this._lowerCaseTagNames=\"lowerCaseTags\"in this._options?!!this._options.lowerCaseTags:!this._options.xmlMode;this._lowerCaseAttributeNames=\"lowerCaseAttributeNames\"in this._options?!!this._options.lowerCaseAttributeNames:!this._options.xmlMode;if(this._options.Tokenizer){Tokenizer=this._options.Tokenizer}this._tokenizer=new Tokenizer(this._options,this);if(this._cbs.onparserinit)this._cbs.onparserinit(this)}require(\"inherits\")(Parser,require(\"events\").EventEmitter);Parser.prototype._updatePosition=function(initialOffset){if(this.endIndex===null){if(this._tokenizer._sectionStart<=initialOffset){this.startIndex=0}else{this.startIndex=this._tokenizer._sectionStart-initialOffset}}else this.startIndex=this.endIndex+1;this.endIndex=this._tokenizer.getAbsoluteIndex()};Parser.prototype.ontext=function(data){this._updatePosition(1);this.endIndex--;if(this._cbs.ontext)this._cbs.ontext(data)};Parser.prototype.onopentagname=function(name){if(this._lowerCaseTagNames){name=name.toLowerCase()}this._tagname=name;if(!this._options.xmlMode&&name in openImpliesClose){for(var el;(el=this._stack[this._stack.length-1])in openImpliesClose[name];this.onclosetag(el));}if(this._options.xmlMode||!(name in voidElements)){this._stack.push(name)}if(this._cbs.onopentagname)this._cbs.onopentagname(name);if(this._cbs.onopentag)this._attribs={}};Parser.prototype.onopentagend=function(){this._updatePosition(1);if(this._attribs){if(this._cbs.onopentag)this._cbs.onopentag(this._tagname,this._attribs);this._attribs=null}if(!this._options.xmlMode&&this._cbs.onclosetag&&this._tagname in voidElements){this._cbs.onclosetag(this._tagname)}this._tagname=\"\"};Parser.prototype.onclosetag=function(name){this._updatePosition(1);if(this._lowerCaseTagNames){name=name.toLowerCase()}if(this._stack.length&&(!(name in voidElements)||this._options.xmlMode)){var pos=this._stack.lastIndexOf(name);if(pos!==-1){if(this._cbs.onclosetag){pos=this._stack.length-pos;while(pos--)this._cbs.onclosetag(this._stack.pop())}else this._stack.length=pos}else if(name===\"p\"&&!this._options.xmlMode){this.onopentagname(name);this._closeCurrentTag()}}else if(!this._options.xmlMode&&(name===\"br\"||name===\"p\")){this.onopentagname(name);this._closeCurrentTag()}};Parser.prototype.onselfclosingtag=function(){if(this._options.xmlMode||this._options.recognizeSelfClosing){this._closeCurrentTag()}else{this.onopentagend()}};Parser.prototype._closeCurrentTag=function(){var name=this._tagname;this.onopentagend();if(this._stack[this._stack.length-1]===name){if(this._cbs.onclosetag){this._cbs.onclosetag(name)}this._stack.pop()}};Parser.prototype.onattribname=function(name){if(this._lowerCaseAttributeNames){name=name.toLowerCase()}this._attribname=name};Parser.prototype.onattribdata=function(value){this._attribvalue+=value};Parser.prototype.onattribend=function(){if(this._cbs.onattribute)this._cbs.onattribute(this._attribname,this._attribvalue);if(this._attribs&&!Object.prototype.hasOwnProperty.call(this._attribs,this._attribname)){this._attribs[this._attribname]=this._attribvalue}this._attribname=\"\";this._attribvalue=\"\"};Parser.prototype._getInstructionName=function(value){var idx=value.search(re_nameEnd),name=idx<0?value:value.substr(0,idx);if(this._lowerCaseTagNames){name=name.toLowerCase()}return name};Parser.prototype.ondeclaration=function(value){if(this._cbs.onprocessinginstruction){var name=this._getInstructionName(value);this._cbs.onprocessinginstruction(\"!\"+name,\"!\"+value)}};Parser.prototype.onprocessinginstruction=function(value){if(this._cbs.onprocessinginstruction){var name=this._getInstructionName(value);this._cbs.onprocessinginstruction(\"?\"+name,\"?\"+value)}};Parser.prototype.oncomment=function(value){this._updatePosition(4);if(this._cbs.oncomment)this._cbs.oncomment(value);if(this._cbs.oncommentend)this._cbs.oncommentend()};Parser.prototype.oncdata=function(value){this._updatePosition(1);if(this._options.xmlMode||this._options.recognizeCDATA){if(this._cbs.oncdatastart)this._cbs.oncdatastart();if(this._cbs.ontext)this._cbs.ontext(value);if(this._cbs.oncdataend)this._cbs.oncdataend()}else{this.oncomment(\"[CDATA[\"+value+\"]]\")}};Parser.prototype.onerror=function(err){if(this._cbs.onerror)this._cbs.onerror(err)};Parser.prototype.onend=function(){if(this._cbs.onclosetag){for(var i=this._stack.length;i>0;this._cbs.onclosetag(this._stack[--i]));}if(this._cbs.onend)this._cbs.onend()};Parser.prototype.reset=function(){if(this._cbs.onreset)this._cbs.onreset();this._tokenizer.reset();this._tagname=\"\";this._attribname=\"\";this._attribs=null;this._stack=[];if(this._cbs.onparserinit)this._cbs.onparserinit(this)};Parser.prototype.parseComplete=function(data){this.reset();this.end(data)};Parser.prototype.write=function(chunk){this._tokenizer.write(chunk)};Parser.prototype.end=function(chunk){this._tokenizer.end(chunk)};Parser.prototype.pause=function(){this._tokenizer.pause()};Parser.prototype.resume=function(){this._tokenizer.resume()};Parser.prototype.parseChunk=Parser.prototype.write;Parser.prototype.done=Parser.prototype.end;module.exports=Parser},{\"./Tokenizer.js\":34,events:28,inherits:38}],32:[function(require,module,exports){module.exports=ProxyHandler;function ProxyHandler(cbs){this._cbs=cbs||{}}var EVENTS=require(\"./\").EVENTS;Object.keys(EVENTS).forEach(function(name){if(EVENTS[name]===0){name=\"on\"+name;ProxyHandler.prototype[name]=function(){if(this._cbs[name])this._cbs[name]()}}else if(EVENTS[name]===1){name=\"on\"+name;ProxyHandler.prototype[name]=function(a){if(this._cbs[name])this._cbs[name](a)}}else if(EVENTS[name]===2){name=\"on\"+name;ProxyHandler.prototype[name]=function(a,b){if(this._cbs[name])this._cbs[name](a,b)}}else{throw Error(\"wrong number of arguments\")}})},{\"./\":36}],33:[function(require,module,exports){module.exports=Stream;var Parser=require(\"./WritableStream.js\");function Stream(options){Parser.call(this,new Cbs(this),options)}require(\"inherits\")(Stream,Parser);Stream.prototype.readable=true;function Cbs(scope){this.scope=scope}var EVENTS=require(\"../\").EVENTS;Object.keys(EVENTS).forEach(function(name){if(EVENTS[name]===0){Cbs.prototype[\"on\"+name]=function(){this.scope.emit(name)}}else if(EVENTS[name]===1){Cbs.prototype[\"on\"+name]=function(a){this.scope.emit(name,a)}}else if(EVENTS[name]===2){Cbs.prototype[\"on\"+name]=function(a,b){this.scope.emit(name,a,b)}}else{throw Error(\"wrong number of arguments!\")}})},{\"../\":36,\"./WritableStream.js\":35,inherits:38}],34:[function(require,module,exports){module.exports=Tokenizer;var decodeCodePoint=require(\"entities/lib/decode_codepoint.js\"),entityMap=require(\"entities/maps/entities.json\"),legacyMap=require(\"entities/maps/legacy.json\"),xmlMap=require(\"entities/maps/xml.json\"),i=0,TEXT=i++,BEFORE_TAG_NAME=i++,IN_TAG_NAME=i++,IN_SELF_CLOSING_TAG=i++,BEFORE_CLOSING_TAG_NAME=i++,IN_CLOSING_TAG_NAME=i++,AFTER_CLOSING_TAG_NAME=i++,BEFORE_ATTRIBUTE_NAME=i++,IN_ATTRIBUTE_NAME=i++,AFTER_ATTRIBUTE_NAME=i++,BEFORE_ATTRIBUTE_VALUE=i++,IN_ATTRIBUTE_VALUE_DQ=i++,IN_ATTRIBUTE_VALUE_SQ=i++,IN_ATTRIBUTE_VALUE_NQ=i++,BEFORE_DECLARATION=i++,IN_DECLARATION=i++,IN_PROCESSING_INSTRUCTION=i++,BEFORE_COMMENT=i++,IN_COMMENT=i++,AFTER_COMMENT_1=i++,AFTER_COMMENT_2=i++,BEFORE_CDATA_1=i++,BEFORE_CDATA_2=i++,BEFORE_CDATA_3=i++,BEFORE_CDATA_4=i++,BEFORE_CDATA_5=i++,BEFORE_CDATA_6=i++,IN_CDATA=i++,AFTER_CDATA_1=i++,AFTER_CDATA_2=i++,BEFORE_SPECIAL=i++,BEFORE_SPECIAL_END=i++,BEFORE_SCRIPT_1=i++,BEFORE_SCRIPT_2=i++,BEFORE_SCRIPT_3=i++,BEFORE_SCRIPT_4=i++,BEFORE_SCRIPT_5=i++,AFTER_SCRIPT_1=i++,AFTER_SCRIPT_2=i++,AFTER_SCRIPT_3=i++,AFTER_SCRIPT_4=i++,AFTER_SCRIPT_5=i++,BEFORE_STYLE_1=i++,BEFORE_STYLE_2=i++,BEFORE_STYLE_3=i++,BEFORE_STYLE_4=i++,AFTER_STYLE_1=i++,AFTER_STYLE_2=i++,AFTER_STYLE_3=i++,AFTER_STYLE_4=i++,BEFORE_ENTITY=i++,BEFORE_NUMERIC_ENTITY=i++,IN_NAMED_ENTITY=i++,IN_NUMERIC_ENTITY=i++,IN_HEX_ENTITY=i++,j=0,SPECIAL_NONE=j++,SPECIAL_SCRIPT=j++,SPECIAL_STYLE=j++;function whitespace(c){return c===\" \"||c===\"\\n\"||c===\"\\t\"||c===\"\\f\"||c===\"\\r\"}function characterState(char,SUCCESS){return function(c){if(c===char)this._state=SUCCESS}}function ifElseState(upper,SUCCESS,FAILURE){var lower=upper.toLowerCase();if(upper===lower){return function(c){if(c===lower){this._state=SUCCESS}else{this._state=FAILURE;this._index--}}}else{return function(c){if(c===lower||c===upper){this._state=SUCCESS}else{this._state=FAILURE;this._index--}}}}function consumeSpecialNameChar(upper,NEXT_STATE){var lower=upper.toLowerCase();return function(c){if(c===lower||c===upper){this._state=NEXT_STATE}else{this._state=IN_TAG_NAME;this._index--}}}function Tokenizer(options,cbs){this._state=TEXT;this._buffer=\"\";this._sectionStart=0;this._index=0;this._bufferOffset=0;this._baseState=TEXT;this._special=SPECIAL_NONE;this._cbs=cbs;this._running=true;this._ended=false;this._xmlMode=!!(options&&options.xmlMode);this._decodeEntities=!!(options&&options.decodeEntities)}Tokenizer.prototype._stateText=function(c){if(c===\"<\"){if(this._index>this._sectionStart){this._cbs.ontext(this._getSection())}this._state=BEFORE_TAG_NAME;this._sectionStart=this._index}else if(this._decodeEntities&&this._special===SPECIAL_NONE&&c===\"&\"){if(this._index>this._sectionStart){this._cbs.ontext(this._getSection())}this._baseState=TEXT;this._state=BEFORE_ENTITY;this._sectionStart=this._index}};Tokenizer.prototype._stateBeforeTagName=function(c){if(c===\"/\"){this._state=BEFORE_CLOSING_TAG_NAME}else if(c===\"<\"){this._cbs.ontext(this._getSection());this._sectionStart=this._index}else if(c===\">\"||this._special!==SPECIAL_NONE||whitespace(c)){this._state=TEXT}else if(c===\"!\"){this._state=BEFORE_DECLARATION;this._sectionStart=this._index+1}else if(c===\"?\"){this._state=IN_PROCESSING_INSTRUCTION;this._sectionStart=this._index+1}else{this._state=!this._xmlMode&&(c===\"s\"||c===\"S\")?BEFORE_SPECIAL:IN_TAG_NAME;this._sectionStart=this._index}};Tokenizer.prototype._stateInTagName=function(c){if(c===\"/\"||c===\">\"||whitespace(c)){this._emitToken(\"onopentagname\");this._state=BEFORE_ATTRIBUTE_NAME;this._index--}};Tokenizer.prototype._stateBeforeCloseingTagName=function(c){if(whitespace(c));else if(c===\">\"){this._state=TEXT}else if(this._special!==SPECIAL_NONE){if(c===\"s\"||c===\"S\"){this._state=BEFORE_SPECIAL_END}else{this._state=TEXT;this._index--}}else{this._state=IN_CLOSING_TAG_NAME;this._sectionStart=this._index}};Tokenizer.prototype._stateInCloseingTagName=function(c){if(c===\">\"||whitespace(c)){this._emitToken(\"onclosetag\");this._state=AFTER_CLOSING_TAG_NAME;this._index--}};Tokenizer.prototype._stateAfterCloseingTagName=function(c){if(c===\">\"){this._state=TEXT;this._sectionStart=this._index+1}};Tokenizer.prototype._stateBeforeAttributeName=function(c){if(c===\">\"){this._cbs.onopentagend();this._state=TEXT;this._sectionStart=this._index+1}else if(c===\"/\"){this._state=IN_SELF_CLOSING_TAG}else if(!whitespace(c)){this._state=IN_ATTRIBUTE_NAME;this._sectionStart=this._index}};Tokenizer.prototype._stateInSelfClosingTag=function(c){if(c===\">\"){this._cbs.onselfclosingtag();this._state=TEXT;this._sectionStart=this._index+1}else if(!whitespace(c)){this._state=BEFORE_ATTRIBUTE_NAME;this._index--}};Tokenizer.prototype._stateInAttributeName=function(c){if(c===\"=\"||c===\"/\"||c===\">\"||whitespace(c)){this._cbs.onattribname(this._getSection());this._sectionStart=-1;this._state=AFTER_ATTRIBUTE_NAME;this._index--}};Tokenizer.prototype._stateAfterAttributeName=function(c){if(c===\"=\"){this._state=BEFORE_ATTRIBUTE_VALUE}else if(c===\"/\"||c===\">\"){this._cbs.onattribend();this._state=BEFORE_ATTRIBUTE_NAME;this._index--}else if(!whitespace(c)){this._cbs.onattribend();this._state=IN_ATTRIBUTE_NAME;this._sectionStart=this._index}};Tokenizer.prototype._stateBeforeAttributeValue=function(c){if(c==='\"'){this._state=IN_ATTRIBUTE_VALUE_DQ;this._sectionStart=this._index+1}else if(c===\"'\"){this._state=IN_ATTRIBUTE_VALUE_SQ;this._sectionStart=this._index+1}else if(!whitespace(c)){this._state=IN_ATTRIBUTE_VALUE_NQ;this._sectionStart=this._index;this._index--}};Tokenizer.prototype._stateInAttributeValueDoubleQuotes=function(c){if(c==='\"'){this._emitToken(\"onattribdata\");this._cbs.onattribend();this._state=BEFORE_ATTRIBUTE_NAME}else if(this._decodeEntities&&c===\"&\"){this._emitToken(\"onattribdata\");this._baseState=this._state;this._state=BEFORE_ENTITY;this._sectionStart=this._index}};Tokenizer.prototype._stateInAttributeValueSingleQuotes=function(c){if(c===\"'\"){this._emitToken(\"onattribdata\");this._cbs.onattribend();this._state=BEFORE_ATTRIBUTE_NAME}else if(this._decodeEntities&&c===\"&\"){this._emitToken(\"onattribdata\");this._baseState=this._state;this._state=BEFORE_ENTITY;this._sectionStart=this._index}};Tokenizer.prototype._stateInAttributeValueNoQuotes=function(c){if(whitespace(c)||c===\">\"){this._emitToken(\"onattribdata\");this._cbs.onattribend();this._state=BEFORE_ATTRIBUTE_NAME;this._index--}else if(this._decodeEntities&&c===\"&\"){this._emitToken(\"onattribdata\");this._baseState=this._state;this._state=BEFORE_ENTITY;this._sectionStart=this._index}};Tokenizer.prototype._stateBeforeDeclaration=function(c){this._state=c===\"[\"?BEFORE_CDATA_1:c===\"-\"?BEFORE_COMMENT:IN_DECLARATION};Tokenizer.prototype._stateInDeclaration=function(c){if(c===\">\"){this._cbs.ondeclaration(this._getSection());this._state=TEXT;this._sectionStart=this._index+1}};Tokenizer.prototype._stateInProcessingInstruction=function(c){if(c===\">\"){this._cbs.onprocessinginstruction(this._getSection());this._state=TEXT;this._sectionStart=this._index+1}};Tokenizer.prototype._stateBeforeComment=function(c){if(c===\"-\"){this._state=IN_COMMENT;this._sectionStart=this._index+1}else{this._state=IN_DECLARATION}};Tokenizer.prototype._stateInComment=function(c){if(c===\"-\")this._state=AFTER_COMMENT_1};Tokenizer.prototype._stateAfterComment1=function(c){if(c===\"-\"){this._state=AFTER_COMMENT_2}else{this._state=IN_COMMENT}};Tokenizer.prototype._stateAfterComment2=function(c){if(c===\">\"){this._cbs.oncomment(this._buffer.substring(this._sectionStart,this._index-2));this._state=TEXT;this._sectionStart=this._index+1}else if(c!==\"-\"){this._state=IN_COMMENT}};Tokenizer.prototype._stateBeforeCdata1=ifElseState(\"C\",BEFORE_CDATA_2,IN_DECLARATION);Tokenizer.prototype._stateBeforeCdata2=ifElseState(\"D\",BEFORE_CDATA_3,IN_DECLARATION);Tokenizer.prototype._stateBeforeCdata3=ifElseState(\"A\",BEFORE_CDATA_4,IN_DECLARATION);Tokenizer.prototype._stateBeforeCdata4=ifElseState(\"T\",BEFORE_CDATA_5,IN_DECLARATION);Tokenizer.prototype._stateBeforeCdata5=ifElseState(\"A\",BEFORE_CDATA_6,IN_DECLARATION);Tokenizer.prototype._stateBeforeCdata6=function(c){if(c===\"[\"){this._state=IN_CDATA;this._sectionStart=this._index+1}else{this._state=IN_DECLARATION;this._index--}};Tokenizer.prototype._stateInCdata=function(c){if(c===\"]\")this._state=AFTER_CDATA_1};Tokenizer.prototype._stateAfterCdata1=characterState(\"]\",AFTER_CDATA_2);Tokenizer.prototype._stateAfterCdata2=function(c){if(c===\">\"){this._cbs.oncdata(this._buffer.substring(this._sectionStart,this._index-2));this._state=TEXT;this._sectionStart=this._index+1}else if(c!==\"]\"){this._state=IN_CDATA}};Tokenizer.prototype._stateBeforeSpecial=function(c){if(c===\"c\"||c===\"C\"){this._state=BEFORE_SCRIPT_1}else if(c===\"t\"||c===\"T\"){this._state=BEFORE_STYLE_1}else{this._state=IN_TAG_NAME;this._index--}};Tokenizer.prototype._stateBeforeSpecialEnd=function(c){if(this._special===SPECIAL_SCRIPT&&(c===\"c\"||c===\"C\")){this._state=AFTER_SCRIPT_1}else if(this._special===SPECIAL_STYLE&&(c===\"t\"||c===\"T\")){this._state=AFTER_STYLE_1}else this._state=TEXT};Tokenizer.prototype._stateBeforeScript1=consumeSpecialNameChar(\"R\",BEFORE_SCRIPT_2);Tokenizer.prototype._stateBeforeScript2=consumeSpecialNameChar(\"I\",BEFORE_SCRIPT_3);Tokenizer.prototype._stateBeforeScript3=consumeSpecialNameChar(\"P\",BEFORE_SCRIPT_4);Tokenizer.prototype._stateBeforeScript4=consumeSpecialNameChar(\"T\",BEFORE_SCRIPT_5);Tokenizer.prototype._stateBeforeScript5=function(c){if(c===\"/\"||c===\">\"||whitespace(c)){this._special=SPECIAL_SCRIPT}this._state=IN_TAG_NAME;this._index--};Tokenizer.prototype._stateAfterScript1=ifElseState(\"R\",AFTER_SCRIPT_2,TEXT);Tokenizer.prototype._stateAfterScript2=ifElseState(\"I\",AFTER_SCRIPT_3,TEXT);Tokenizer.prototype._stateAfterScript3=ifElseState(\"P\",AFTER_SCRIPT_4,TEXT);Tokenizer.prototype._stateAfterScript4=ifElseState(\"T\",AFTER_SCRIPT_5,TEXT);Tokenizer.prototype._stateAfterScript5=function(c){if(c===\">\"||whitespace(c)){this._special=SPECIAL_NONE;this._state=IN_CLOSING_TAG_NAME;this._sectionStart=this._index-6;this._index--}else this._state=TEXT};Tokenizer.prototype._stateBeforeStyle1=consumeSpecialNameChar(\"Y\",BEFORE_STYLE_2);Tokenizer.prototype._stateBeforeStyle2=consumeSpecialNameChar(\"L\",BEFORE_STYLE_3);Tokenizer.prototype._stateBeforeStyle3=consumeSpecialNameChar(\"E\",BEFORE_STYLE_4);Tokenizer.prototype._stateBeforeStyle4=function(c){if(c===\"/\"||c===\">\"||whitespace(c)){this._special=SPECIAL_STYLE}this._state=IN_TAG_NAME;this._index--};Tokenizer.prototype._stateAfterStyle1=ifElseState(\"Y\",AFTER_STYLE_2,TEXT);Tokenizer.prototype._stateAfterStyle2=ifElseState(\"L\",AFTER_STYLE_3,TEXT);Tokenizer.prototype._stateAfterStyle3=ifElseState(\"E\",AFTER_STYLE_4,TEXT);Tokenizer.prototype._stateAfterStyle4=function(c){if(c===\">\"||whitespace(c)){this._special=SPECIAL_NONE;this._state=IN_CLOSING_TAG_NAME;this._sectionStart=this._index-5;this._index--}else this._state=TEXT};Tokenizer.prototype._stateBeforeEntity=ifElseState(\"#\",BEFORE_NUMERIC_ENTITY,IN_NAMED_ENTITY);Tokenizer.prototype._stateBeforeNumericEntity=ifElseState(\"X\",IN_HEX_ENTITY,IN_NUMERIC_ENTITY);Tokenizer.prototype._parseNamedEntityStrict=function(){if(this._sectionStart+1<this._index){var entity=this._buffer.substring(this._sectionStart+1,this._index),map=this._xmlMode?xmlMap:entityMap;if(map.hasOwnProperty(entity)){this._emitPartial(map[entity]);this._sectionStart=this._index+1}}};Tokenizer.prototype._parseLegacyEntity=function(){var start=this._sectionStart+1,limit=this._index-start;if(limit>6)limit=6;while(limit>=2){var entity=this._buffer.substr(start,limit);if(legacyMap.hasOwnProperty(entity)){this._emitPartial(legacyMap[entity]);this._sectionStart+=limit+1;return}else{limit--}}};Tokenizer.prototype._stateInNamedEntity=function(c){if(c===\";\"){this._parseNamedEntityStrict();if(this._sectionStart+1<this._index&&!this._xmlMode){this._parseLegacyEntity()}this._state=this._baseState}else if((c<\"a\"||c>\"z\")&&(c<\"A\"||c>\"Z\")&&(c<\"0\"||c>\"9\")){if(this._xmlMode);else if(this._sectionStart+1===this._index);else if(this._baseState!==TEXT){if(c!==\"=\"){this._parseNamedEntityStrict()}}else{this._parseLegacyEntity()}this._state=this._baseState;this._index--}};Tokenizer.prototype._decodeNumericEntity=function(offset,base){var sectionStart=this._sectionStart+offset;if(sectionStart!==this._index){var entity=this._buffer.substring(sectionStart,this._index);var parsed=parseInt(entity,base);this._emitPartial(decodeCodePoint(parsed));this._sectionStart=this._index}else{this._sectionStart--}this._state=this._baseState};Tokenizer.prototype._stateInNumericEntity=function(c){if(c===\";\"){this._decodeNumericEntity(2,10);this._sectionStart++}else if(c<\"0\"||c>\"9\"){if(!this._xmlMode){this._decodeNumericEntity(2,10)}else{this._state=this._baseState}this._index--}};Tokenizer.prototype._stateInHexEntity=function(c){if(c===\";\"){this._decodeNumericEntity(3,16);this._sectionStart++}else if((c<\"a\"||c>\"f\")&&(c<\"A\"||c>\"F\")&&(c<\"0\"||c>\"9\")){if(!this._xmlMode){this._decodeNumericEntity(3,16)}else{this._state=this._baseState}this._index--}};Tokenizer.prototype._cleanup=function(){if(this._sectionStart<0){this._buffer=\"\";this._index=0;this._bufferOffset+=this._index}else if(this._running){if(this._state===TEXT){if(this._sectionStart!==this._index){this._cbs.ontext(this._buffer.substr(this._sectionStart))}this._buffer=\"\";this._bufferOffset+=this._index;this._index=0}else if(this._sectionStart===this._index){this._buffer=\"\";this._bufferOffset+=this._index;this._index=0}else{this._buffer=this._buffer.substr(this._sectionStart);this._index-=this._sectionStart;this._bufferOffset+=this._sectionStart}this._sectionStart=0}};Tokenizer.prototype.write=function(chunk){if(this._ended)this._cbs.onerror(Error(\".write() after done!\"));this._buffer+=chunk;this._parse()};Tokenizer.prototype._parse=function(){while(this._index<this._buffer.length&&this._running){var c=this._buffer.charAt(this._index);if(this._state===TEXT){this._stateText(c)}else if(this._state===BEFORE_TAG_NAME){this._stateBeforeTagName(c)}else if(this._state===IN_TAG_NAME){this._stateInTagName(c)}else if(this._state===BEFORE_CLOSING_TAG_NAME){this._stateBeforeCloseingTagName(c)}else if(this._state===IN_CLOSING_TAG_NAME){this._stateInCloseingTagName(c)}else if(this._state===AFTER_CLOSING_TAG_NAME){this._stateAfterCloseingTagName(c)}else if(this._state===IN_SELF_CLOSING_TAG){this._stateInSelfClosingTag(c)}else if(this._state===BEFORE_ATTRIBUTE_NAME){this._stateBeforeAttributeName(c)}else if(this._state===IN_ATTRIBUTE_NAME){this._stateInAttributeName(c)}else if(this._state===AFTER_ATTRIBUTE_NAME){this._stateAfterAttributeName(c)}else if(this._state===BEFORE_ATTRIBUTE_VALUE){this._stateBeforeAttributeValue(c)}else if(this._state===IN_ATTRIBUTE_VALUE_DQ){this._stateInAttributeValueDoubleQuotes(c)}else if(this._state===IN_ATTRIBUTE_VALUE_SQ){this._stateInAttributeValueSingleQuotes(c)}else if(this._state===IN_ATTRIBUTE_VALUE_NQ){this._stateInAttributeValueNoQuotes(c)}else if(this._state===BEFORE_DECLARATION){this._stateBeforeDeclaration(c)}else if(this._state===IN_DECLARATION){this._stateInDeclaration(c)}else if(this._state===IN_PROCESSING_INSTRUCTION){this._stateInProcessingInstruction(c)}else if(this._state===BEFORE_COMMENT){this._stateBeforeComment(c)}else if(this._state===IN_COMMENT){this._stateInComment(c)}else if(this._state===AFTER_COMMENT_1){this._stateAfterComment1(c)}else if(this._state===AFTER_COMMENT_2){this._stateAfterComment2(c)}else if(this._state===BEFORE_CDATA_1){this._stateBeforeCdata1(c)}else if(this._state===BEFORE_CDATA_2){this._stateBeforeCdata2(c)}else if(this._state===BEFORE_CDATA_3){this._stateBeforeCdata3(c)}else if(this._state===BEFORE_CDATA_4){this._stateBeforeCdata4(c)}else if(this._state===BEFORE_CDATA_5){this._stateBeforeCdata5(c)}else if(this._state===BEFORE_CDATA_6){this._stateBeforeCdata6(c)}else if(this._state===IN_CDATA){this._stateInCdata(c)}else if(this._state===AFTER_CDATA_1){this._stateAfterCdata1(c)}else if(this._state===AFTER_CDATA_2){this._stateAfterCdata2(c)}else if(this._state===BEFORE_SPECIAL){this._stateBeforeSpecial(c)}else if(this._state===BEFORE_SPECIAL_END){this._stateBeforeSpecialEnd(c)}else if(this._state===BEFORE_SCRIPT_1){this._stateBeforeScript1(c)}else if(this._state===BEFORE_SCRIPT_2){this._stateBeforeScript2(c)}else if(this._state===BEFORE_SCRIPT_3){this._stateBeforeScript3(c)}else if(this._state===BEFORE_SCRIPT_4){this._stateBeforeScript4(c)}else if(this._state===BEFORE_SCRIPT_5){this._stateBeforeScript5(c)}else if(this._state===AFTER_SCRIPT_1){this._stateAfterScript1(c)}else if(this._state===AFTER_SCRIPT_2){this._stateAfterScript2(c)}else if(this._state===AFTER_SCRIPT_3){this._stateAfterScript3(c)}else if(this._state===AFTER_SCRIPT_4){this._stateAfterScript4(c)}else if(this._state===AFTER_SCRIPT_5){this._stateAfterScript5(c)}else if(this._state===BEFORE_STYLE_1){this._stateBeforeStyle1(c)}else if(this._state===BEFORE_STYLE_2){this._stateBeforeStyle2(c)}else if(this._state===BEFORE_STYLE_3){this._stateBeforeStyle3(c)}else if(this._state===BEFORE_STYLE_4){this._stateBeforeStyle4(c)}else if(this._state===AFTER_STYLE_1){this._stateAfterStyle1(c)}else if(this._state===AFTER_STYLE_2){this._stateAfterStyle2(c)}else if(this._state===AFTER_STYLE_3){this._stateAfterStyle3(c)}else if(this._state===AFTER_STYLE_4){this._stateAfterStyle4(c)}else if(this._state===BEFORE_ENTITY){this._stateBeforeEntity(c)}else if(this._state===BEFORE_NUMERIC_ENTITY){this._stateBeforeNumericEntity(c)}else if(this._state===IN_NAMED_ENTITY){this._stateInNamedEntity(c)}else if(this._state===IN_NUMERIC_ENTITY){this._stateInNumericEntity(c)}else if(this._state===IN_HEX_ENTITY){this._stateInHexEntity(c)}else{this._cbs.onerror(Error(\"unknown _state\"),this._state)}this._index++}this._cleanup()};Tokenizer.prototype.pause=function(){this._running=false};Tokenizer.prototype.resume=function(){this._running=true;if(this._index<this._buffer.length){this._parse()}if(this._ended){this._finish()}};Tokenizer.prototype.end=function(chunk){if(this._ended)this._cbs.onerror(Error(\".end() after done!\"));if(chunk)this.write(chunk);this._ended=true;if(this._running)this._finish()};Tokenizer.prototype._finish=function(){if(this._sectionStart<this._index){this._handleTrailingData()}this._cbs.onend()};Tokenizer.prototype._handleTrailingData=function(){var data=this._buffer.substr(this._sectionStart);if(this._state===IN_CDATA||this._state===AFTER_CDATA_1||this._state===AFTER_CDATA_2){this._cbs.oncdata(data)}else if(this._state===IN_COMMENT||this._state===AFTER_COMMENT_1||this._state===AFTER_COMMENT_2){this._cbs.oncomment(data)}else if(this._state===IN_NAMED_ENTITY&&!this._xmlMode){this._parseLegacyEntity();if(this._sectionStart<this._index){this._state=this._baseState;this._handleTrailingData()}}else if(this._state===IN_NUMERIC_ENTITY&&!this._xmlMode){this._decodeNumericEntity(2,10);if(this._sectionStart<this._index){this._state=this._baseState;this._handleTrailingData()}}else if(this._state===IN_HEX_ENTITY&&!this._xmlMode){this._decodeNumericEntity(3,16);if(this._sectionStart<this._index){this._state=this._baseState;this._handleTrailingData()}}else if(this._state!==IN_TAG_NAME&&this._state!==BEFORE_ATTRIBUTE_NAME&&this._state!==BEFORE_ATTRIBUTE_VALUE&&this._state!==AFTER_ATTRIBUTE_NAME&&this._state!==IN_ATTRIBUTE_NAME&&this._state!==IN_ATTRIBUTE_VALUE_SQ&&this._state!==IN_ATTRIBUTE_VALUE_DQ&&this._state!==IN_ATTRIBUTE_VALUE_NQ&&this._state!==IN_CLOSING_TAG_NAME){\nthis._cbs.ontext(data)}};Tokenizer.prototype.reset=function(){Tokenizer.call(this,{xmlMode:this._xmlMode,decodeEntities:this._decodeEntities},this._cbs)};Tokenizer.prototype.getAbsoluteIndex=function(){return this._bufferOffset+this._index};Tokenizer.prototype._getSection=function(){return this._buffer.substring(this._sectionStart,this._index)};Tokenizer.prototype._emitToken=function(name){this._cbs[name](this._getSection());this._sectionStart=-1};Tokenizer.prototype._emitPartial=function(value){if(this._baseState!==TEXT){this._cbs.onattribdata(value)}else{this._cbs.ontext(value)}}},{\"entities/lib/decode_codepoint.js\":22,\"entities/maps/entities.json\":25,\"entities/maps/legacy.json\":26,\"entities/maps/xml.json\":27}],35:[function(require,module,exports){module.exports=Stream;var Parser=require(\"./Parser.js\"),WritableStream=require(\"stream\").Writable||require(\"readable-stream\").Writable,StringDecoder=require(\"string_decoder\").StringDecoder,Buffer=require(\"buffer\").Buffer;function Stream(cbs,options){var parser=this._parser=new Parser(cbs,options);var decoder=this._decoder=new StringDecoder;WritableStream.call(this,{decodeStrings:false});this.once(\"finish\",function(){parser.end(decoder.end())})}require(\"inherits\")(Stream,WritableStream);WritableStream.prototype._write=function(chunk,encoding,cb){if(chunk instanceof Buffer)chunk=this._decoder.write(chunk);this._parser.write(chunk);cb()}},{\"./Parser.js\":31,buffer:5,inherits:38,\"readable-stream\":3,stream:55,string_decoder:56}],36:[function(require,module,exports){var Parser=require(\"./Parser.js\"),DomHandler=require(\"domhandler\");function defineProp(name,value){delete module.exports[name];module.exports[name]=value;return value}module.exports={Parser:Parser,Tokenizer:require(\"./Tokenizer.js\"),ElementType:require(\"domelementtype\"),DomHandler:DomHandler,get FeedHandler(){return defineProp(\"FeedHandler\",require(\"./FeedHandler.js\"))},get Stream(){return defineProp(\"Stream\",require(\"./Stream.js\"))},get WritableStream(){return defineProp(\"WritableStream\",require(\"./WritableStream.js\"))},get ProxyHandler(){return defineProp(\"ProxyHandler\",require(\"./ProxyHandler.js\"))},get DomUtils(){return defineProp(\"DomUtils\",require(\"domutils\"))},get CollectingHandler(){return defineProp(\"CollectingHandler\",require(\"./CollectingHandler.js\"))},DefaultHandler:DomHandler,get RssHandler(){return defineProp(\"RssHandler\",this.FeedHandler)},parseDOM:function(data,options){var handler=new DomHandler(options);new Parser(handler,options).end(data);return handler.dom},parseFeed:function(feed,options){var handler=new module.exports.FeedHandler(options);new Parser(handler,options).end(feed);return handler.dom},createDomStream:function(cb,options,elementCb){var handler=new DomHandler(cb,options,elementCb);return new Parser(handler,options)},EVENTS:{attribute:2,cdatastart:0,cdataend:0,text:1,processinginstruction:2,comment:1,commentend:0,closetag:1,opentag:2,opentagname:1,error:1,end:0}}},{\"./CollectingHandler.js\":29,\"./FeedHandler.js\":30,\"./Parser.js\":31,\"./ProxyHandler.js\":32,\"./Stream.js\":33,\"./Tokenizer.js\":34,\"./WritableStream.js\":35,domelementtype:9,domhandler:10,domutils:13}],37:[function(require,module,exports){exports.read=function(buffer,offset,isLE,mLen,nBytes){var e,m;var eLen=nBytes*8-mLen-1;var eMax=(1<<eLen)-1;var eBias=eMax>>1;var nBits=-7;var i=isLE?nBytes-1:0;var d=isLE?-1:1;var s=buffer[offset+i];i+=d;e=s&(1<<-nBits)-1;s>>=-nBits;nBits+=eLen;for(;nBits>0;e=e*256+buffer[offset+i],i+=d,nBits-=8){}m=e&(1<<-nBits)-1;e>>=-nBits;nBits+=mLen;for(;nBits>0;m=m*256+buffer[offset+i],i+=d,nBits-=8){}if(e===0){e=1-eBias}else if(e===eMax){return m?NaN:(s?-1:1)*Infinity}else{m=m+Math.pow(2,mLen);e=e-eBias}return(s?-1:1)*m*Math.pow(2,e-mLen)};exports.write=function(buffer,value,offset,isLE,mLen,nBytes){var e,m,c;var eLen=nBytes*8-mLen-1;var eMax=(1<<eLen)-1;var eBias=eMax>>1;var rt=mLen===23?Math.pow(2,-24)-Math.pow(2,-77):0;var i=isLE?0:nBytes-1;var d=isLE?1:-1;var s=value<0||value===0&&1/value<0?1:0;value=Math.abs(value);if(isNaN(value)||value===Infinity){m=isNaN(value)?1:0;e=eMax}else{e=Math.floor(Math.log(value)/Math.LN2);if(value*(c=Math.pow(2,-e))<1){e--;c*=2}if(e+eBias>=1){value+=rt/c}else{value+=rt*Math.pow(2,1-eBias)}if(value*c>=2){e++;c/=2}if(e+eBias>=eMax){m=0;e=eMax}else if(e+eBias>=1){m=(value*c-1)*Math.pow(2,mLen);e=e+eBias}else{m=value*Math.pow(2,eBias-1)*Math.pow(2,mLen);e=0}}for(;mLen>=8;buffer[offset+i]=m&255,i+=d,m/=256,mLen-=8){}e=e<<mLen|m;eLen+=mLen;for(;eLen>0;buffer[offset+i]=e&255,i+=d,e/=256,eLen-=8){}buffer[offset+i-d]|=s*128}},{}],38:[function(require,module,exports){if(typeof Object.create===\"function\"){module.exports=function inherits(ctor,superCtor){ctor.super_=superCtor;ctor.prototype=Object.create(superCtor.prototype,{constructor:{value:ctor,enumerable:false,writable:true,configurable:true}})}}else{module.exports=function inherits(ctor,superCtor){ctor.super_=superCtor;var TempCtor=function(){};TempCtor.prototype=superCtor.prototype;ctor.prototype=new TempCtor;ctor.prototype.constructor=ctor}}},{}],39:[function(require,module,exports){module.exports=function(obj){return obj!=null&&(isBuffer(obj)||isSlowBuffer(obj)||!!obj._isBuffer)};function isBuffer(obj){return!!obj.constructor&&typeof obj.constructor.isBuffer===\"function\"&&obj.constructor.isBuffer(obj)}function isSlowBuffer(obj){return typeof obj.readFloatLE===\"function\"&&typeof obj.slice===\"function\"&&isBuffer(obj.slice(0,0))}},{}],40:[function(require,module,exports){var toString={}.toString;module.exports=Array.isArray||function(arr){return toString.call(arr)==\"[object Array]\"}},{}],41:[function(require,module,exports){(function(process){\"use strict\";if(!process.version||process.version.indexOf(\"v0.\")===0||process.version.indexOf(\"v1.\")===0&&process.version.indexOf(\"v1.8.\")!==0){module.exports=nextTick}else{module.exports=process.nextTick}function nextTick(fn,arg1,arg2,arg3){if(typeof fn!==\"function\"){throw new TypeError('\"callback\" argument must be a function')}var len=arguments.length;var args,i;switch(len){case 0:case 1:return process.nextTick(fn);case 2:return process.nextTick(function afterTickOne(){fn.call(null,arg1)});case 3:return process.nextTick(function afterTickTwo(){fn.call(null,arg1,arg2)});case 4:return process.nextTick(function afterTickThree(){fn.call(null,arg1,arg2,arg3)});default:args=new Array(len-1);i=0;while(i<args.length){args[i++]=arguments[i]}return process.nextTick(function afterTick(){fn.apply(null,args)})}}}).call(this,require(\"_process\"))},{_process:42}],42:[function(require,module,exports){var process=module.exports={};var cachedSetTimeout;var cachedClearTimeout;function defaultSetTimout(){throw new Error(\"setTimeout has not been defined\")}function defaultClearTimeout(){throw new Error(\"clearTimeout has not been defined\")}(function(){try{if(typeof setTimeout===\"function\"){cachedSetTimeout=setTimeout}else{cachedSetTimeout=defaultSetTimout}}catch(e){cachedSetTimeout=defaultSetTimout}try{if(typeof clearTimeout===\"function\"){cachedClearTimeout=clearTimeout}else{cachedClearTimeout=defaultClearTimeout}}catch(e){cachedClearTimeout=defaultClearTimeout}})();function runTimeout(fun){if(cachedSetTimeout===setTimeout){return setTimeout(fun,0)}if((cachedSetTimeout===defaultSetTimout||!cachedSetTimeout)&&setTimeout){cachedSetTimeout=setTimeout;return setTimeout(fun,0)}try{return cachedSetTimeout(fun,0)}catch(e){try{return cachedSetTimeout.call(null,fun,0)}catch(e){return cachedSetTimeout.call(this,fun,0)}}}function runClearTimeout(marker){if(cachedClearTimeout===clearTimeout){return clearTimeout(marker)}if((cachedClearTimeout===defaultClearTimeout||!cachedClearTimeout)&&clearTimeout){cachedClearTimeout=clearTimeout;return clearTimeout(marker)}try{return cachedClearTimeout(marker)}catch(e){try{return cachedClearTimeout.call(null,marker)}catch(e){return cachedClearTimeout.call(this,marker)}}}var queue=[];var draining=false;var currentQueue;var queueIndex=-1;function cleanUpNextTick(){if(!draining||!currentQueue){return}draining=false;if(currentQueue.length){queue=currentQueue.concat(queue)}else{queueIndex=-1}if(queue.length){drainQueue()}}function drainQueue(){if(draining){return}var timeout=runTimeout(cleanUpNextTick);draining=true;var len=queue.length;while(len){currentQueue=queue;queue=[];while(++queueIndex<len){if(currentQueue){currentQueue[queueIndex].run()}}queueIndex=-1;len=queue.length}currentQueue=null;draining=false;runClearTimeout(timeout)}process.nextTick=function(fun){var args=new Array(arguments.length-1);if(arguments.length>1){for(var i=1;i<arguments.length;i++){args[i-1]=arguments[i]}}queue.push(new Item(fun,args));if(queue.length===1&&!draining){runTimeout(drainQueue)}};function Item(fun,array){this.fun=fun;this.array=array}Item.prototype.run=function(){this.fun.apply(null,this.array)};process.title=\"browser\";process.browser=true;process.env={};process.argv=[];process.version=\"\";process.versions={};function noop(){}process.on=noop;process.addListener=noop;process.once=noop;process.off=noop;process.removeListener=noop;process.removeAllListeners=noop;process.emit=noop;process.binding=function(name){throw new Error(\"process.binding is not supported\")};process.cwd=function(){return\"/\"};process.chdir=function(dir){throw new Error(\"process.chdir is not supported\")};process.umask=function(){return 0}},{}],43:[function(require,module,exports){module.exports=require(\"./lib/_stream_duplex.js\")},{\"./lib/_stream_duplex.js\":44}],44:[function(require,module,exports){\"use strict\";var objectKeys=Object.keys||function(obj){var keys=[];for(var key in obj){keys.push(key)}return keys};module.exports=Duplex;var processNextTick=require(\"process-nextick-args\");var util=require(\"core-util-is\");util.inherits=require(\"inherits\");var Readable=require(\"./_stream_readable\");var Writable=require(\"./_stream_writable\");util.inherits(Duplex,Readable);var keys=objectKeys(Writable.prototype);for(var v=0;v<keys.length;v++){var method=keys[v];if(!Duplex.prototype[method])Duplex.prototype[method]=Writable.prototype[method]}function Duplex(options){if(!(this instanceof Duplex))return new Duplex(options);Readable.call(this,options);Writable.call(this,options);if(options&&options.readable===false)this.readable=false;if(options&&options.writable===false)this.writable=false;this.allowHalfOpen=true;if(options&&options.allowHalfOpen===false)this.allowHalfOpen=false;this.once(\"end\",onend)}function onend(){if(this.allowHalfOpen||this._writableState.ended)return;processNextTick(onEndNT,this)}function onEndNT(self){self.end()}function forEach(xs,f){for(var i=0,l=xs.length;i<l;i++){f(xs[i],i)}}},{\"./_stream_readable\":46,\"./_stream_writable\":48,\"core-util-is\":6,inherits:38,\"process-nextick-args\":41}],45:[function(require,module,exports){\"use strict\";module.exports=PassThrough;var Transform=require(\"./_stream_transform\");var util=require(\"core-util-is\");util.inherits=require(\"inherits\");util.inherits(PassThrough,Transform);function PassThrough(options){if(!(this instanceof PassThrough))return new PassThrough(options);Transform.call(this,options)}PassThrough.prototype._transform=function(chunk,encoding,cb){cb(null,chunk)}},{\"./_stream_transform\":47,\"core-util-is\":6,inherits:38}],46:[function(require,module,exports){(function(process){\"use strict\";module.exports=Readable;var processNextTick=require(\"process-nextick-args\");var isArray=require(\"isarray\");Readable.ReadableState=ReadableState;var EE=require(\"events\").EventEmitter;var EElistenerCount=function(emitter,type){return emitter.listeners(type).length};var Stream;(function(){try{Stream=require(\"st\"+\"ream\")}catch(_){}finally{if(!Stream)Stream=require(\"events\").EventEmitter}})();var Buffer=require(\"buffer\").Buffer;var bufferShim=require(\"buffer-shims\");var util=require(\"core-util-is\");util.inherits=require(\"inherits\");var debugUtil=require(\"util\");var debug=void 0;if(debugUtil&&debugUtil.debuglog){debug=debugUtil.debuglog(\"stream\")}else{debug=function(){}}var BufferList=require(\"./internal/streams/BufferList\");var StringDecoder;util.inherits(Readable,Stream);function prependListener(emitter,event,fn){if(typeof emitter.prependListener===\"function\"){return emitter.prependListener(event,fn)}else{if(!emitter._events||!emitter._events[event])emitter.on(event,fn);else if(isArray(emitter._events[event]))emitter._events[event].unshift(fn);else emitter._events[event]=[fn,emitter._events[event]]}}var Duplex;function ReadableState(options,stream){Duplex=Duplex||require(\"./_stream_duplex\");options=options||{};this.objectMode=!!options.objectMode;if(stream instanceof Duplex)this.objectMode=this.objectMode||!!options.readableObjectMode;var hwm=options.highWaterMark;var defaultHwm=this.objectMode?16:16*1024;this.highWaterMark=hwm||hwm===0?hwm:defaultHwm;this.highWaterMark=~~this.highWaterMark;this.buffer=new BufferList;this.length=0;this.pipes=null;this.pipesCount=0;this.flowing=null;this.ended=false;this.endEmitted=false;this.reading=false;this.sync=true;this.needReadable=false;this.emittedReadable=false;this.readableListening=false;this.resumeScheduled=false;this.defaultEncoding=options.defaultEncoding||\"utf8\";this.ranOut=false;this.awaitDrain=0;this.readingMore=false;this.decoder=null;this.encoding=null;if(options.encoding){if(!StringDecoder)StringDecoder=require(\"string_decoder/\").StringDecoder;this.decoder=new StringDecoder(options.encoding);this.encoding=options.encoding}}var Duplex;function Readable(options){Duplex=Duplex||require(\"./_stream_duplex\");if(!(this instanceof Readable))return new Readable(options);this._readableState=new ReadableState(options,this);this.readable=true;if(options&&typeof options.read===\"function\")this._read=options.read;Stream.call(this)}Readable.prototype.push=function(chunk,encoding){var state=this._readableState;if(!state.objectMode&&typeof chunk===\"string\"){encoding=encoding||state.defaultEncoding;if(encoding!==state.encoding){chunk=bufferShim.from(chunk,encoding);encoding=\"\"}}return readableAddChunk(this,state,chunk,encoding,false)};Readable.prototype.unshift=function(chunk){var state=this._readableState;return readableAddChunk(this,state,chunk,\"\",true)};Readable.prototype.isPaused=function(){return this._readableState.flowing===false};function readableAddChunk(stream,state,chunk,encoding,addToFront){var er=chunkInvalid(state,chunk);if(er){stream.emit(\"error\",er)}else if(chunk===null){state.reading=false;onEofChunk(stream,state)}else if(state.objectMode||chunk&&chunk.length>0){if(state.ended&&!addToFront){var e=new Error(\"stream.push() after EOF\");stream.emit(\"error\",e)}else if(state.endEmitted&&addToFront){var _e=new Error(\"stream.unshift() after end event\");stream.emit(\"error\",_e)}else{var skipAdd;if(state.decoder&&!addToFront&&!encoding){chunk=state.decoder.write(chunk);skipAdd=!state.objectMode&&chunk.length===0}if(!addToFront)state.reading=false;if(!skipAdd){if(state.flowing&&state.length===0&&!state.sync){stream.emit(\"data\",chunk);stream.read(0)}else{state.length+=state.objectMode?1:chunk.length;if(addToFront)state.buffer.unshift(chunk);else state.buffer.push(chunk);if(state.needReadable)emitReadable(stream)}}maybeReadMore(stream,state)}}else if(!addToFront){state.reading=false}return needMoreData(state)}function needMoreData(state){return!state.ended&&(state.needReadable||state.length<state.highWaterMark||state.length===0)}Readable.prototype.setEncoding=function(enc){if(!StringDecoder)StringDecoder=require(\"string_decoder/\").StringDecoder;this._readableState.decoder=new StringDecoder(enc);this._readableState.encoding=enc;return this};var MAX_HWM=8388608;function computeNewHighWaterMark(n){if(n>=MAX_HWM){n=MAX_HWM}else{n--;n|=n>>>1;n|=n>>>2;n|=n>>>4;n|=n>>>8;n|=n>>>16;n++}return n}function howMuchToRead(n,state){if(n<=0||state.length===0&&state.ended)return 0;if(state.objectMode)return 1;if(n!==n){if(state.flowing&&state.length)return state.buffer.head.data.length;else return state.length}if(n>state.highWaterMark)state.highWaterMark=computeNewHighWaterMark(n);if(n<=state.length)return n;if(!state.ended){state.needReadable=true;return 0}return state.length}Readable.prototype.read=function(n){debug(\"read\",n);n=parseInt(n,10);var state=this._readableState;var nOrig=n;if(n!==0)state.emittedReadable=false;if(n===0&&state.needReadable&&(state.length>=state.highWaterMark||state.ended)){debug(\"read: emitReadable\",state.length,state.ended);if(state.length===0&&state.ended)endReadable(this);else emitReadable(this);return null}n=howMuchToRead(n,state);if(n===0&&state.ended){if(state.length===0)endReadable(this);return null}var doRead=state.needReadable;debug(\"need readable\",doRead);if(state.length===0||state.length-n<state.highWaterMark){doRead=true;debug(\"length less than watermark\",doRead)}if(state.ended||state.reading){doRead=false;debug(\"reading or ended\",doRead)}else if(doRead){debug(\"do read\");state.reading=true;state.sync=true;if(state.length===0)state.needReadable=true;this._read(state.highWaterMark);state.sync=false;if(!state.reading)n=howMuchToRead(nOrig,state)}var ret;if(n>0)ret=fromList(n,state);else ret=null;if(ret===null){state.needReadable=true;n=0}else{state.length-=n}if(state.length===0){if(!state.ended)state.needReadable=true;if(nOrig!==n&&state.ended)endReadable(this)}if(ret!==null)this.emit(\"data\",ret);return ret};function chunkInvalid(state,chunk){var er=null;if(!Buffer.isBuffer(chunk)&&typeof chunk!==\"string\"&&chunk!==null&&chunk!==undefined&&!state.objectMode){er=new TypeError(\"Invalid non-string/buffer chunk\")}return er}function onEofChunk(stream,state){if(state.ended)return;if(state.decoder){var chunk=state.decoder.end();if(chunk&&chunk.length){state.buffer.push(chunk);state.length+=state.objectMode?1:chunk.length}}state.ended=true;emitReadable(stream)}function emitReadable(stream){var state=stream._readableState;state.needReadable=false;if(!state.emittedReadable){debug(\"emitReadable\",state.flowing);state.emittedReadable=true;if(state.sync)processNextTick(emitReadable_,stream);else emitReadable_(stream)}}function emitReadable_(stream){debug(\"emit readable\");stream.emit(\"readable\");flow(stream)}function maybeReadMore(stream,state){if(!state.readingMore){state.readingMore=true;processNextTick(maybeReadMore_,stream,state)}}function maybeReadMore_(stream,state){var len=state.length;while(!state.reading&&!state.flowing&&!state.ended&&state.length<state.highWaterMark){debug(\"maybeReadMore read 0\");stream.read(0);if(len===state.length)break;else len=state.length}state.readingMore=false}Readable.prototype._read=function(n){this.emit(\"error\",new Error(\"not implemented\"))};Readable.prototype.pipe=function(dest,pipeOpts){var src=this;var state=this._readableState;switch(state.pipesCount){case 0:state.pipes=dest;break;case 1:state.pipes=[state.pipes,dest];break;default:state.pipes.push(dest);break}state.pipesCount+=1;debug(\"pipe count=%d opts=%j\",state.pipesCount,pipeOpts);var doEnd=(!pipeOpts||pipeOpts.end!==false)&&dest!==process.stdout&&dest!==process.stderr;var endFn=doEnd?onend:cleanup;if(state.endEmitted)processNextTick(endFn);else src.once(\"end\",endFn);dest.on(\"unpipe\",onunpipe);function onunpipe(readable){debug(\"onunpipe\");if(readable===src){cleanup()}}function onend(){debug(\"onend\");dest.end()}var ondrain=pipeOnDrain(src);dest.on(\"drain\",ondrain);var cleanedUp=false;function cleanup(){debug(\"cleanup\");dest.removeListener(\"close\",onclose);dest.removeListener(\"finish\",onfinish);dest.removeListener(\"drain\",ondrain);dest.removeListener(\"error\",onerror);dest.removeListener(\"unpipe\",onunpipe);src.removeListener(\"end\",onend);src.removeListener(\"end\",cleanup);src.removeListener(\"data\",ondata);cleanedUp=true;if(state.awaitDrain&&(!dest._writableState||dest._writableState.needDrain))ondrain()}var increasedAwaitDrain=false;src.on(\"data\",ondata);function ondata(chunk){debug(\"ondata\");increasedAwaitDrain=false;var ret=dest.write(chunk);if(false===ret&&!increasedAwaitDrain){if((state.pipesCount===1&&state.pipes===dest||state.pipesCount>1&&indexOf(state.pipes,dest)!==-1)&&!cleanedUp){debug(\"false write response, pause\",src._readableState.awaitDrain);src._readableState.awaitDrain++;increasedAwaitDrain=true}src.pause()}}function onerror(er){debug(\"onerror\",er);unpipe();dest.removeListener(\"error\",onerror);if(EElistenerCount(dest,\"error\")===0)dest.emit(\"error\",er)}prependListener(dest,\"error\",onerror);function onclose(){dest.removeListener(\"finish\",onfinish);unpipe()}dest.once(\"close\",onclose);function onfinish(){debug(\"onfinish\");dest.removeListener(\"close\",onclose);unpipe()}dest.once(\"finish\",onfinish);function unpipe(){debug(\"unpipe\");src.unpipe(dest)}dest.emit(\"pipe\",src);if(!state.flowing){debug(\"pipe resume\");src.resume()}return dest};function pipeOnDrain(src){return function(){var state=src._readableState;debug(\"pipeOnDrain\",state.awaitDrain);if(state.awaitDrain)state.awaitDrain--;if(state.awaitDrain===0&&EElistenerCount(src,\"data\")){state.flowing=true;flow(src)}}}Readable.prototype.unpipe=function(dest){var state=this._readableState;if(state.pipesCount===0)return this;if(state.pipesCount===1){if(dest&&dest!==state.pipes)return this;if(!dest)dest=state.pipes;state.pipes=null;state.pipesCount=0;state.flowing=false;if(dest)dest.emit(\"unpipe\",this);return this}if(!dest){var dests=state.pipes;var len=state.pipesCount;state.pipes=null;state.pipesCount=0;state.flowing=false;for(var _i=0;_i<len;_i++){dests[_i].emit(\"unpipe\",this)}return this}var i=indexOf(state.pipes,dest);if(i===-1)return this;state.pipes.splice(i,1);state.pipesCount-=1;if(state.pipesCount===1)state.pipes=state.pipes[0];dest.emit(\"unpipe\",this);return this};Readable.prototype.on=function(ev,fn){var res=Stream.prototype.on.call(this,ev,fn);if(ev===\"data\"){if(this._readableState.flowing!==false)this.resume()}else if(ev===\"readable\"){var state=this._readableState;if(!state.endEmitted&&!state.readableListening){state.readableListening=state.needReadable=true;state.emittedReadable=false;if(!state.reading){processNextTick(nReadingNextTick,this)}else if(state.length){emitReadable(this,state)}}}return res};Readable.prototype.addListener=Readable.prototype.on;function nReadingNextTick(self){debug(\"readable nexttick read 0\");self.read(0)}Readable.prototype.resume=function(){var state=this._readableState;if(!state.flowing){debug(\"resume\");state.flowing=true;resume(this,state)}return this};function resume(stream,state){if(!state.resumeScheduled){state.resumeScheduled=true;processNextTick(resume_,stream,state)}}function resume_(stream,state){if(!state.reading){debug(\"resume read 0\");stream.read(0)}state.resumeScheduled=false;state.awaitDrain=0;stream.emit(\"resume\");flow(stream);if(state.flowing&&!state.reading)stream.read(0)}Readable.prototype.pause=function(){debug(\"call pause flowing=%j\",this._readableState.flowing);if(false!==this._readableState.flowing){debug(\"pause\");this._readableState.flowing=false;this.emit(\"pause\")}return this};function flow(stream){var state=stream._readableState;debug(\"flow\",state.flowing);while(state.flowing&&stream.read()!==null){}}Readable.prototype.wrap=function(stream){var state=this._readableState;var paused=false;var self=this;stream.on(\"end\",function(){debug(\"wrapped end\");if(state.decoder&&!state.ended){var chunk=state.decoder.end();if(chunk&&chunk.length)self.push(chunk)}self.push(null)});stream.on(\"data\",function(chunk){debug(\"wrapped data\");if(state.decoder)chunk=state.decoder.write(chunk);if(state.objectMode&&(chunk===null||chunk===undefined))return;else if(!state.objectMode&&(!chunk||!chunk.length))return;var ret=self.push(chunk);if(!ret){paused=true;stream.pause()}});for(var i in stream){if(this[i]===undefined&&typeof stream[i]===\"function\"){this[i]=function(method){return function(){return stream[method].apply(stream,arguments)}}(i)}}var events=[\"error\",\"close\",\"destroy\",\"pause\",\"resume\"];forEach(events,function(ev){stream.on(ev,self.emit.bind(self,ev))});self._read=function(n){debug(\"wrapped _read\",n);if(paused){paused=false;stream.resume()}};return self};Readable._fromList=fromList;function fromList(n,state){if(state.length===0)return null;var ret;if(state.objectMode)ret=state.buffer.shift();else if(!n||n>=state.length){if(state.decoder)ret=state.buffer.join(\"\");else if(state.buffer.length===1)ret=state.buffer.head.data;else ret=state.buffer.concat(state.length);state.buffer.clear()}else{ret=fromListPartial(n,state.buffer,state.decoder)}return ret}function fromListPartial(n,list,hasStrings){var ret;if(n<list.head.data.length){ret=list.head.data.slice(0,n);list.head.data=list.head.data.slice(n)}else if(n===list.head.data.length){ret=list.shift()}else{ret=hasStrings?copyFromBufferString(n,list):copyFromBuffer(n,list)}return ret}function copyFromBufferString(n,list){var p=list.head;var c=1;var ret=p.data;n-=ret.length;while(p=p.next){var str=p.data;var nb=n>str.length?str.length:n;if(nb===str.length)ret+=str;else ret+=str.slice(0,n);n-=nb;if(n===0){if(nb===str.length){++c;if(p.next)list.head=p.next;else list.head=list.tail=null}else{list.head=p;p.data=str.slice(nb)}break}++c}list.length-=c;return ret}function copyFromBuffer(n,list){var ret=bufferShim.allocUnsafe(n);var p=list.head;var c=1;p.data.copy(ret);n-=p.data.length;while(p=p.next){var buf=p.data;var nb=n>buf.length?buf.length:n;buf.copy(ret,ret.length-n,0,nb);n-=nb;if(n===0){if(nb===buf.length){++c;if(p.next)list.head=p.next;else list.head=list.tail=null}else{list.head=p;p.data=buf.slice(nb)}break}++c}list.length-=c;return ret}function endReadable(stream){var state=stream._readableState;if(state.length>0)throw new Error('\"endReadable()\" called on non-empty stream');if(!state.endEmitted){state.ended=true;processNextTick(endReadableNT,state,stream)}}function endReadableNT(state,stream){if(!state.endEmitted&&state.length===0){state.endEmitted=true;stream.readable=false;stream.emit(\"end\")}}function forEach(xs,f){for(var i=0,l=xs.length;i<l;i++){f(xs[i],i)}}function indexOf(xs,x){for(var i=0,l=xs.length;i<l;i++){if(xs[i]===x)return i}return-1}}).call(this,require(\"_process\"))},{\"./_stream_duplex\":44,\"./internal/streams/BufferList\":49,_process:42,buffer:5,\"buffer-shims\":4,\"core-util-is\":6,events:28,inherits:38,isarray:40,\"process-nextick-args\":41,\"string_decoder/\":56,util:3}],47:[function(require,module,exports){\"use strict\";module.exports=Transform;var Duplex=require(\"./_stream_duplex\");var util=require(\"core-util-is\");util.inherits=require(\"inherits\");util.inherits(Transform,Duplex);function TransformState(stream){this.afterTransform=function(er,data){return afterTransform(stream,er,data)};this.needTransform=false;this.transforming=false;this.writecb=null;this.writechunk=null;this.writeencoding=null}function afterTransform(stream,er,data){var ts=stream._transformState;ts.transforming=false;var cb=ts.writecb;if(!cb)return stream.emit(\"error\",new Error(\"no writecb in Transform class\"));ts.writechunk=null;ts.writecb=null;if(data!==null&&data!==undefined)stream.push(data);cb(er);var rs=stream._readableState;rs.reading=false;if(rs.needReadable||rs.length<rs.highWaterMark){stream._read(rs.highWaterMark)}}function Transform(options){if(!(this instanceof Transform))return new Transform(options);Duplex.call(this,options);this._transformState=new TransformState(this);var stream=this;this._readableState.needReadable=true;this._readableState.sync=false;if(options){if(typeof options.transform===\"function\")this._transform=options.transform;if(typeof options.flush===\"function\")this._flush=options.flush}this.once(\"prefinish\",function(){if(typeof this._flush===\"function\")this._flush(function(er){done(stream,er)});else done(stream)})}Transform.prototype.push=function(chunk,encoding){this._transformState.needTransform=false;return Duplex.prototype.push.call(this,chunk,encoding)};Transform.prototype._transform=function(chunk,encoding,cb){throw new Error(\"Not implemented\")};Transform.prototype._write=function(chunk,encoding,cb){var ts=this._transformState;ts.writecb=cb;ts.writechunk=chunk;ts.writeencoding=encoding;if(!ts.transforming){var rs=this._readableState;if(ts.needTransform||rs.needReadable||rs.length<rs.highWaterMark)this._read(rs.highWaterMark)}};Transform.prototype._read=function(n){var ts=this._transformState;if(ts.writechunk!==null&&ts.writecb&&!ts.transforming){ts.transforming=true;this._transform(ts.writechunk,ts.writeencoding,ts.afterTransform)}else{ts.needTransform=true}};function done(stream,er){if(er)return stream.emit(\"error\",er);var ws=stream._writableState;var ts=stream._transformState;if(ws.length)throw new Error(\"Calling transform done when ws.length != 0\");if(ts.transforming)throw new Error(\"Calling transform done when still transforming\");return stream.push(null)}},{\"./_stream_duplex\":44,\"core-util-is\":6,inherits:38}],48:[function(require,module,exports){(function(process){\"use strict\";module.exports=Writable;var processNextTick=require(\"process-nextick-args\");var asyncWrite=!process.browser&&[\"v0.10\",\"v0.9.\"].indexOf(process.version.slice(0,5))>-1?setImmediate:processNextTick;Writable.WritableState=WritableState;var util=require(\"core-util-is\");util.inherits=require(\"inherits\");var internalUtil={deprecate:require(\"util-deprecate\")};var Stream;(function(){try{Stream=require(\"st\"+\"ream\")}catch(_){}finally{if(!Stream)Stream=require(\"events\").EventEmitter}})();var Buffer=require(\"buffer\").Buffer;var bufferShim=require(\"buffer-shims\");util.inherits(Writable,Stream);function nop(){}function WriteReq(chunk,encoding,cb){this.chunk=chunk;this.encoding=encoding;this.callback=cb;this.next=null}var Duplex;function WritableState(options,stream){Duplex=Duplex||require(\"./_stream_duplex\");options=options||{};this.objectMode=!!options.objectMode;if(stream instanceof Duplex)this.objectMode=this.objectMode||!!options.writableObjectMode;var hwm=options.highWaterMark;var defaultHwm=this.objectMode?16:16*1024;this.highWaterMark=hwm||hwm===0?hwm:defaultHwm;this.highWaterMark=~~this.highWaterMark;this.needDrain=false;this.ending=false;this.ended=false;this.finished=false;var noDecode=options.decodeStrings===false;this.decodeStrings=!noDecode;this.defaultEncoding=options.defaultEncoding||\"utf8\";this.length=0;this.writing=false;this.corked=0;this.sync=true;this.bufferProcessing=false;this.onwrite=function(er){onwrite(stream,er)};this.writecb=null;this.writelen=0;this.bufferedRequest=null;this.lastBufferedRequest=null;this.pendingcb=0;this.prefinished=false;this.errorEmitted=false;this.bufferedRequestCount=0;this.corkedRequestsFree=new CorkedRequest(this)}WritableState.prototype.getBuffer=function writableStateGetBuffer(){var current=this.bufferedRequest;var out=[];while(current){out.push(current);current=current.next}return out};(function(){try{Object.defineProperty(WritableState.prototype,\"buffer\",{get:internalUtil.deprecate(function(){return this.getBuffer()},\"_writableState.buffer is deprecated. Use _writableState.getBuffer \"+\"instead.\")})}catch(_){}})();var Duplex;function Writable(options){Duplex=Duplex||require(\"./_stream_duplex\");if(!(this instanceof Writable)&&!(this instanceof Duplex))return new Writable(options);this._writableState=new WritableState(options,this);this.writable=true;if(options){if(typeof options.write===\"function\")this._write=options.write;if(typeof options.writev===\"function\")this._writev=options.writev}Stream.call(this)}Writable.prototype.pipe=function(){this.emit(\"error\",new Error(\"Cannot pipe, not readable\"))};function writeAfterEnd(stream,cb){var er=new Error(\"write after end\");stream.emit(\"error\",er);processNextTick(cb,er)}function validChunk(stream,state,chunk,cb){var valid=true;var er=false;if(chunk===null){er=new TypeError(\"May not write null values to stream\")}else if(!Buffer.isBuffer(chunk)&&typeof chunk!==\"string\"&&chunk!==undefined&&!state.objectMode){er=new TypeError(\"Invalid non-string/buffer chunk\")}if(er){stream.emit(\"error\",er);processNextTick(cb,er);valid=false}return valid}Writable.prototype.write=function(chunk,encoding,cb){var state=this._writableState;var ret=false;if(typeof encoding===\"function\"){cb=encoding;encoding=null}if(Buffer.isBuffer(chunk))encoding=\"buffer\";else if(!encoding)encoding=state.defaultEncoding;if(typeof cb!==\"function\")cb=nop;if(state.ended)writeAfterEnd(this,cb);else if(validChunk(this,state,chunk,cb)){\nstate.pendingcb++;ret=writeOrBuffer(this,state,chunk,encoding,cb)}return ret};Writable.prototype.cork=function(){var state=this._writableState;state.corked++};Writable.prototype.uncork=function(){var state=this._writableState;if(state.corked){state.corked--;if(!state.writing&&!state.corked&&!state.finished&&!state.bufferProcessing&&state.bufferedRequest)clearBuffer(this,state)}};Writable.prototype.setDefaultEncoding=function setDefaultEncoding(encoding){if(typeof encoding===\"string\")encoding=encoding.toLowerCase();if(!([\"hex\",\"utf8\",\"utf-8\",\"ascii\",\"binary\",\"base64\",\"ucs2\",\"ucs-2\",\"utf16le\",\"utf-16le\",\"raw\"].indexOf((encoding+\"\").toLowerCase())>-1))throw new TypeError(\"Unknown encoding: \"+encoding);this._writableState.defaultEncoding=encoding;return this};function decodeChunk(state,chunk,encoding){if(!state.objectMode&&state.decodeStrings!==false&&typeof chunk===\"string\"){chunk=bufferShim.from(chunk,encoding)}return chunk}function writeOrBuffer(stream,state,chunk,encoding,cb){chunk=decodeChunk(state,chunk,encoding);if(Buffer.isBuffer(chunk))encoding=\"buffer\";var len=state.objectMode?1:chunk.length;state.length+=len;var ret=state.length<state.highWaterMark;if(!ret)state.needDrain=true;if(state.writing||state.corked){var last=state.lastBufferedRequest;state.lastBufferedRequest=new WriteReq(chunk,encoding,cb);if(last){last.next=state.lastBufferedRequest}else{state.bufferedRequest=state.lastBufferedRequest}state.bufferedRequestCount+=1}else{doWrite(stream,state,false,len,chunk,encoding,cb)}return ret}function doWrite(stream,state,writev,len,chunk,encoding,cb){state.writelen=len;state.writecb=cb;state.writing=true;state.sync=true;if(writev)stream._writev(chunk,state.onwrite);else stream._write(chunk,encoding,state.onwrite);state.sync=false}function onwriteError(stream,state,sync,er,cb){--state.pendingcb;if(sync)processNextTick(cb,er);else cb(er);stream._writableState.errorEmitted=true;stream.emit(\"error\",er)}function onwriteStateUpdate(state){state.writing=false;state.writecb=null;state.length-=state.writelen;state.writelen=0}function onwrite(stream,er){var state=stream._writableState;var sync=state.sync;var cb=state.writecb;onwriteStateUpdate(state);if(er)onwriteError(stream,state,sync,er,cb);else{var finished=needFinish(state);if(!finished&&!state.corked&&!state.bufferProcessing&&state.bufferedRequest){clearBuffer(stream,state)}if(sync){asyncWrite(afterWrite,stream,state,finished,cb)}else{afterWrite(stream,state,finished,cb)}}}function afterWrite(stream,state,finished,cb){if(!finished)onwriteDrain(stream,state);state.pendingcb--;cb();finishMaybe(stream,state)}function onwriteDrain(stream,state){if(state.length===0&&state.needDrain){state.needDrain=false;stream.emit(\"drain\")}}function clearBuffer(stream,state){state.bufferProcessing=true;var entry=state.bufferedRequest;if(stream._writev&&entry&&entry.next){var l=state.bufferedRequestCount;var buffer=new Array(l);var holder=state.corkedRequestsFree;holder.entry=entry;var count=0;while(entry){buffer[count]=entry;entry=entry.next;count+=1}doWrite(stream,state,true,state.length,buffer,\"\",holder.finish);state.pendingcb++;state.lastBufferedRequest=null;if(holder.next){state.corkedRequestsFree=holder.next;holder.next=null}else{state.corkedRequestsFree=new CorkedRequest(state)}}else{while(entry){var chunk=entry.chunk;var encoding=entry.encoding;var cb=entry.callback;var len=state.objectMode?1:chunk.length;doWrite(stream,state,false,len,chunk,encoding,cb);entry=entry.next;if(state.writing){break}}if(entry===null)state.lastBufferedRequest=null}state.bufferedRequestCount=0;state.bufferedRequest=entry;state.bufferProcessing=false}Writable.prototype._write=function(chunk,encoding,cb){cb(new Error(\"not implemented\"))};Writable.prototype._writev=null;Writable.prototype.end=function(chunk,encoding,cb){var state=this._writableState;if(typeof chunk===\"function\"){cb=chunk;chunk=null;encoding=null}else if(typeof encoding===\"function\"){cb=encoding;encoding=null}if(chunk!==null&&chunk!==undefined)this.write(chunk,encoding);if(state.corked){state.corked=1;this.uncork()}if(!state.ending&&!state.finished)endWritable(this,state,cb)};function needFinish(state){return state.ending&&state.length===0&&state.bufferedRequest===null&&!state.finished&&!state.writing}function prefinish(stream,state){if(!state.prefinished){state.prefinished=true;stream.emit(\"prefinish\")}}function finishMaybe(stream,state){var need=needFinish(state);if(need){if(state.pendingcb===0){prefinish(stream,state);state.finished=true;stream.emit(\"finish\")}else{prefinish(stream,state)}}return need}function endWritable(stream,state,cb){state.ending=true;finishMaybe(stream,state);if(cb){if(state.finished)processNextTick(cb);else stream.once(\"finish\",cb)}state.ended=true;stream.writable=false}function CorkedRequest(state){var _this=this;this.next=null;this.entry=null;this.finish=function(err){var entry=_this.entry;_this.entry=null;while(entry){var cb=entry.callback;state.pendingcb--;cb(err);entry=entry.next}if(state.corkedRequestsFree){state.corkedRequestsFree.next=_this}else{state.corkedRequestsFree=_this}}}}).call(this,require(\"_process\"))},{\"./_stream_duplex\":44,_process:42,buffer:5,\"buffer-shims\":4,\"core-util-is\":6,events:28,inherits:38,\"process-nextick-args\":41,\"util-deprecate\":57}],49:[function(require,module,exports){\"use strict\";var Buffer=require(\"buffer\").Buffer;var bufferShim=require(\"buffer-shims\");module.exports=BufferList;function BufferList(){this.head=null;this.tail=null;this.length=0}BufferList.prototype.push=function(v){var entry={data:v,next:null};if(this.length>0)this.tail.next=entry;else this.head=entry;this.tail=entry;++this.length};BufferList.prototype.unshift=function(v){var entry={data:v,next:this.head};if(this.length===0)this.tail=entry;this.head=entry;++this.length};BufferList.prototype.shift=function(){if(this.length===0)return;var ret=this.head.data;if(this.length===1)this.head=this.tail=null;else this.head=this.head.next;--this.length;return ret};BufferList.prototype.clear=function(){this.head=this.tail=null;this.length=0};BufferList.prototype.join=function(s){if(this.length===0)return\"\";var p=this.head;var ret=\"\"+p.data;while(p=p.next){ret+=s+p.data}return ret};BufferList.prototype.concat=function(n){if(this.length===0)return bufferShim.alloc(0);if(this.length===1)return this.head.data;var ret=bufferShim.allocUnsafe(n>>>0);var p=this.head;var i=0;while(p){p.data.copy(ret,i);i+=p.data.length;p=p.next}return ret}},{buffer:5,\"buffer-shims\":4}],50:[function(require,module,exports){module.exports=require(\"./lib/_stream_passthrough.js\")},{\"./lib/_stream_passthrough.js\":45}],51:[function(require,module,exports){(function(process){var Stream=function(){try{return require(\"st\"+\"ream\")}catch(_){}}();exports=module.exports=require(\"./lib/_stream_readable.js\");exports.Stream=Stream||exports;exports.Readable=exports;exports.Writable=require(\"./lib/_stream_writable.js\");exports.Duplex=require(\"./lib/_stream_duplex.js\");exports.Transform=require(\"./lib/_stream_transform.js\");exports.PassThrough=require(\"./lib/_stream_passthrough.js\");if(!process.browser&&process.env.READABLE_STREAM===\"disable\"&&Stream){module.exports=Stream}}).call(this,require(\"_process\"))},{\"./lib/_stream_duplex.js\":44,\"./lib/_stream_passthrough.js\":45,\"./lib/_stream_readable.js\":46,\"./lib/_stream_transform.js\":47,\"./lib/_stream_writable.js\":48,_process:42}],52:[function(require,module,exports){module.exports=require(\"./lib/_stream_transform.js\")},{\"./lib/_stream_transform.js\":47}],53:[function(require,module,exports){module.exports=require(\"./lib/_stream_writable.js\")},{\"./lib/_stream_writable.js\":48}],54:[function(require,module,exports){module.exports=function(string){return string.replace(/[-\\\\^$*+?.()|[\\]{}]/g,\"\\\\$&\")}},{}],55:[function(require,module,exports){module.exports=Stream;var EE=require(\"events\").EventEmitter;var inherits=require(\"inherits\");inherits(Stream,EE);Stream.Readable=require(\"readable-stream/readable.js\");Stream.Writable=require(\"readable-stream/writable.js\");Stream.Duplex=require(\"readable-stream/duplex.js\");Stream.Transform=require(\"readable-stream/transform.js\");Stream.PassThrough=require(\"readable-stream/passthrough.js\");Stream.Stream=Stream;function Stream(){EE.call(this)}Stream.prototype.pipe=function(dest,options){var source=this;function ondata(chunk){if(dest.writable){if(false===dest.write(chunk)&&source.pause){source.pause()}}}source.on(\"data\",ondata);function ondrain(){if(source.readable&&source.resume){source.resume()}}dest.on(\"drain\",ondrain);if(!dest._isStdio&&(!options||options.end!==false)){source.on(\"end\",onend);source.on(\"close\",onclose)}var didOnEnd=false;function onend(){if(didOnEnd)return;didOnEnd=true;dest.end()}function onclose(){if(didOnEnd)return;didOnEnd=true;if(typeof dest.destroy===\"function\")dest.destroy()}function onerror(er){cleanup();if(EE.listenerCount(this,\"error\")===0){throw er}}source.on(\"error\",onerror);dest.on(\"error\",onerror);function cleanup(){source.removeListener(\"data\",ondata);dest.removeListener(\"drain\",ondrain);source.removeListener(\"end\",onend);source.removeListener(\"close\",onclose);source.removeListener(\"error\",onerror);dest.removeListener(\"error\",onerror);source.removeListener(\"end\",cleanup);source.removeListener(\"close\",cleanup);dest.removeListener(\"close\",cleanup)}source.on(\"end\",cleanup);source.on(\"close\",cleanup);dest.on(\"close\",cleanup);dest.emit(\"pipe\",source);return dest}},{events:28,inherits:38,\"readable-stream/duplex.js\":43,\"readable-stream/passthrough.js\":50,\"readable-stream/readable.js\":51,\"readable-stream/transform.js\":52,\"readable-stream/writable.js\":53}],56:[function(require,module,exports){var Buffer=require(\"buffer\").Buffer;var isBufferEncoding=Buffer.isEncoding||function(encoding){switch(encoding&&encoding.toLowerCase()){case\"hex\":case\"utf8\":case\"utf-8\":case\"ascii\":case\"binary\":case\"base64\":case\"ucs2\":case\"ucs-2\":case\"utf16le\":case\"utf-16le\":case\"raw\":return true;default:return false}};function assertEncoding(encoding){if(encoding&&!isBufferEncoding(encoding)){throw new Error(\"Unknown encoding: \"+encoding)}}var StringDecoder=exports.StringDecoder=function(encoding){this.encoding=(encoding||\"utf8\").toLowerCase().replace(/[-_]/,\"\");assertEncoding(encoding);switch(this.encoding){case\"utf8\":this.surrogateSize=3;break;case\"ucs2\":case\"utf16le\":this.surrogateSize=2;this.detectIncompleteChar=utf16DetectIncompleteChar;break;case\"base64\":this.surrogateSize=3;this.detectIncompleteChar=base64DetectIncompleteChar;break;default:this.write=passThroughWrite;return}this.charBuffer=new Buffer(6);this.charReceived=0;this.charLength=0};StringDecoder.prototype.write=function(buffer){var charStr=\"\";while(this.charLength){var available=buffer.length>=this.charLength-this.charReceived?this.charLength-this.charReceived:buffer.length;buffer.copy(this.charBuffer,this.charReceived,0,available);this.charReceived+=available;if(this.charReceived<this.charLength){return\"\"}buffer=buffer.slice(available,buffer.length);charStr=this.charBuffer.slice(0,this.charLength).toString(this.encoding);var charCode=charStr.charCodeAt(charStr.length-1);if(charCode>=55296&&charCode<=56319){this.charLength+=this.surrogateSize;charStr=\"\";continue}this.charReceived=this.charLength=0;if(buffer.length===0){return charStr}break}this.detectIncompleteChar(buffer);var end=buffer.length;if(this.charLength){buffer.copy(this.charBuffer,0,buffer.length-this.charReceived,end);end-=this.charReceived}charStr+=buffer.toString(this.encoding,0,end);var end=charStr.length-1;var charCode=charStr.charCodeAt(end);if(charCode>=55296&&charCode<=56319){var size=this.surrogateSize;this.charLength+=size;this.charReceived+=size;this.charBuffer.copy(this.charBuffer,size,0,size);buffer.copy(this.charBuffer,0,0,size);return charStr.substring(0,end)}return charStr};StringDecoder.prototype.detectIncompleteChar=function(buffer){var i=buffer.length>=3?3:buffer.length;for(;i>0;i--){var c=buffer[buffer.length-i];if(i==1&&c>>5==6){this.charLength=2;break}if(i<=2&&c>>4==14){this.charLength=3;break}if(i<=3&&c>>3==30){this.charLength=4;break}}this.charReceived=i};StringDecoder.prototype.end=function(buffer){var res=\"\";if(buffer&&buffer.length)res=this.write(buffer);if(this.charReceived){var cr=this.charReceived;var buf=this.charBuffer;var enc=this.encoding;res+=buf.slice(0,cr).toString(enc)}return res};function passThroughWrite(buffer){return buffer.toString(this.encoding)}function utf16DetectIncompleteChar(buffer){this.charReceived=buffer.length%2;this.charLength=this.charReceived?2:0}function base64DetectIncompleteChar(buffer){this.charReceived=buffer.length%3;this.charLength=this.charReceived?3:0}},{buffer:5}],57:[function(require,module,exports){(function(global){module.exports=deprecate;function deprecate(fn,msg){if(config(\"noDeprecation\")){return fn}var warned=false;function deprecated(){if(!warned){if(config(\"throwDeprecation\")){throw new Error(msg)}else if(config(\"traceDeprecation\")){console.trace(msg)}else{console.warn(msg)}warned=true}return fn.apply(this,arguments)}return deprecated}function config(name){try{if(!global.localStorage)return false}catch(_){return false}var val=global.localStorage[name];if(null==val)return false;return String(val).toLowerCase()===\"true\"}}).call(this,typeof global!==\"undefined\"?global:typeof self!==\"undefined\"?self:typeof window!==\"undefined\"?window:{})},{}],58:[function(require,module,exports){module.exports=extend;var hasOwnProperty=Object.prototype.hasOwnProperty;function extend(){var target={};for(var i=0;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(hasOwnProperty.call(source,key)){target[key]=source[key]}}}return target}},{}]},{},[1])(1)});\n\n/**\n * swagger-client - swagger-client is a javascript client for use with swaggering APIs.\n * @version v2.1.32\n * @link http://swagger.io\n * @license Apache-2.0\n */\n(function(f){if(typeof exports===\"object\"&&typeof module!==\"undefined\"){module.exports=f()}else if(typeof define===\"function\"&&define.amd){define([],f)}else{var g;if(typeof window!==\"undefined\"){g=window}else if(typeof global!==\"undefined\"){g=global}else if(typeof self!==\"undefined\"){g=self}else{g=this}g.SwaggerClient = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n'use strict';\n\nvar auth = require('./lib/auth');\nvar helpers = require('./lib/helpers');\nvar SwaggerClient = require('./lib/client');\nvar deprecationWrapper = function (url, options) {\n  helpers.log('This is deprecated, use \"new SwaggerClient\" instead.');\n\n  return new SwaggerClient(url, options);\n};\n\n/* Here for IE8 Support */\nif (!Array.prototype.indexOf) {\n  Array.prototype.indexOf = function(obj, start) {\n    for (var i = (start || 0), j = this.length; i < j; i++) {\n      if (this[i] === obj) { return i; }\n    }\n    return -1;\n  };\n}\n\n/* Here for IE8 Support */\nif (!String.prototype.trim) {\n  String.prototype.trim = function () {\n    return this.replace(/^\\s+|\\s+$/g, '');\n  };\n}\n\n/* Here for node 10.x support */\nif (!String.prototype.endsWith) {\n  String.prototype.endsWith = function(suffix) {\n    return this.indexOf(suffix, this.length - suffix.length) !== -1;\n  };\n}\n\nmodule.exports = SwaggerClient;\n\nSwaggerClient.ApiKeyAuthorization = auth.ApiKeyAuthorization;\nSwaggerClient.PasswordAuthorization = auth.PasswordAuthorization;\nSwaggerClient.CookieAuthorization = auth.CookieAuthorization;\nSwaggerClient.SwaggerApi = deprecationWrapper;\nSwaggerClient.SwaggerClient = deprecationWrapper;\nSwaggerClient.SchemaMarkup = require('./lib/schema-markup');\n\n},{\"./lib/auth\":2,\"./lib/client\":3,\"./lib/helpers\":4,\"./lib/schema-markup\":7}],2:[function(require,module,exports){\n'use strict';\n\nvar helpers = require('./helpers');\nvar btoa = require('btoa'); // jshint ignore:line\nvar CookieJar = require('cookiejar').CookieJar;\nvar _ = {\n  each: require('lodash-compat/collection/each'),\n  includes: require('lodash-compat/collection/includes'),\n  isObject: require('lodash-compat/lang/isObject'),\n  isArray: require('lodash-compat/lang/isArray')\n};\n\n/**\n * SwaggerAuthorizations applies the correct authorization to an operation being executed\n */\nvar SwaggerAuthorizations = module.exports.SwaggerAuthorizations = function (authz) {\n  this.authz = authz || {};\n};\n\n/**\n * Add auths to the hash\n * Will overwrite any existing\n *\n */\nSwaggerAuthorizations.prototype.add = function (name, auth) {\n  if(_.isObject(name)) {\n    for (var key in name) {\n      this.authz[key] = name[key];\n    }\n  } else if(typeof name === 'string' ){\n    this.authz[name] = auth;\n  }\n\n  return auth;\n};\n\nSwaggerAuthorizations.prototype.remove = function (name) {\n  return delete this.authz[name];\n};\n\nSwaggerAuthorizations.prototype.apply = function (obj, securities) {\n  var status = true;\n  var applyAll = !securities;\n  var flattenedSecurities = [];\n\n  // favor the object-level authorizations over global\n  var authz = obj.clientAuthorizations || this.authz;\n\n  // Securities could be [ {} ]\n  _.each(securities, function (obj, key) {\n\n    // Make sure we account for securities being [ str ]\n    if(typeof key === 'string') {\n      flattenedSecurities.push(key);\n    }\n\n    // Flatten keys in to our array\n    _.each(obj, function (val, key) {\n      flattenedSecurities.push(key);\n    });\n  });\n\n  _.each(authz, function (auth, authName) {\n    if(applyAll || _.includes(flattenedSecurities, authName)) {\n      var newStatus = auth.apply(obj);\n      status = status && !!newStatus; // logical ORs regarding status\n    }\n  });\n\n  return status;\n};\n\n/**\n * ApiKeyAuthorization allows a query param or header to be injected\n */\nvar ApiKeyAuthorization = module.exports.ApiKeyAuthorization = function (name, value, type) {\n  this.name = name;\n  this.value = value;\n  this.type = type;\n};\n\nApiKeyAuthorization.prototype.apply = function (obj) {\n  if (this.type === 'query') {\n    // see if already applied.  If so, don't do it again\n\n    var qp;\n    if (obj.url.indexOf('?') > 0) {\n      qp = obj.url.substring(obj.url.indexOf('?') + 1);\n      var parts = qp.split('&');\n      if(parts && parts.length > 0) {\n        for(var i = 0; i < parts.length; i++) {\n          var kv = parts[i].split('=');\n          if(kv && kv.length > 0) {\n            if (kv[0] === this.name) {\n              // skip it\n              return false;\n            }\n          }\n        }\n      }\n    }\n\n    if (obj.url.indexOf('?') > 0) {\n      obj.url = obj.url + '&' + this.name + '=' + this.value;\n    } else {\n      obj.url = obj.url + '?' + this.name + '=' + this.value;\n    }\n\n    return true;\n  } else if (this.type === 'header') {\n    if(typeof obj.headers[this.name] === 'undefined') {\n      obj.headers[this.name] = this.value;\n    }\n\n    return true;\n  }\n};\n\nvar CookieAuthorization = module.exports.CookieAuthorization = function (cookie) {\n  this.cookie = cookie;\n};\n\nCookieAuthorization.prototype.apply = function (obj) {\n  obj.cookieJar = obj.cookieJar || new CookieJar();\n  obj.cookieJar.setCookie(this.cookie);\n\n  return true;\n};\n\n/**\n * Password Authorization is a basic auth implementation\n */\nvar PasswordAuthorization = module.exports.PasswordAuthorization = function (username, password) {\n  if (arguments.length === 3) {\n    helpers.log('PasswordAuthorization: the \\'name\\' argument has been removed, pass only username and password');\n    username = arguments[1];\n    password = arguments[2];\n  }\n  this.username = username;\n  this.password = password;\n};\n\nPasswordAuthorization.prototype.apply = function (obj) {\n  if(typeof obj.headers.Authorization === 'undefined') {\n    obj.headers.Authorization = 'Basic ' + btoa(this.username + ':' + this.password);\n  }\n\n  return true;\n};\n\n},{\"./helpers\":4,\"btoa\":13,\"cookiejar\":18,\"lodash-compat/collection/each\":52,\"lodash-compat/collection/includes\":55,\"lodash-compat/lang/isArray\":140,\"lodash-compat/lang/isObject\":144}],3:[function(require,module,exports){\n'use strict';\n\nvar _ = {\n  bind: require('lodash-compat/function/bind'),\n  cloneDeep: require('lodash-compat/lang/cloneDeep'),\n  find: require('lodash-compat/collection/find'),\n  forEach: require('lodash-compat/collection/forEach'),\n  indexOf: require('lodash-compat/array/indexOf'),\n  isArray: require('lodash-compat/lang/isArray'),\n  isObject: require('lodash-compat/lang/isObject'),\n  isFunction: require('lodash-compat/lang/isFunction'),\n  isPlainObject: require('lodash-compat/lang/isPlainObject'),\n  isUndefined: require('lodash-compat/lang/isUndefined')\n};\nvar auth = require('./auth');\nvar helpers = require('./helpers');\nvar Model = require('./types/model');\nvar Operation = require('./types/operation');\nvar OperationGroup = require('./types/operationGroup');\nvar Resolver = require('./resolver');\nvar SwaggerHttp = require('./http');\nvar SwaggerSpecConverter = require('./spec-converter');\nvar Q = require('q');\n\n// We have to keep track of the function/property names to avoid collisions for tag names which are used to allow the\n// following usage: 'client.{tagName}'\nvar reservedClientTags = [\n  'apis',\n  'authorizationScheme',\n  'authorizations',\n  'basePath',\n  'build',\n  'buildFrom1_1Spec',\n  'buildFrom1_2Spec',\n  'buildFromSpec',\n  'clientAuthorizations',\n  'convertInfo',\n  'debug',\n  'defaultErrorCallback',\n  'defaultSuccessCallback',\n  'enableCookies',\n  'fail',\n  'failure',\n  'finish',\n  'help',\n  'host',\n  'idFromOp',\n  'info',\n  'initialize',\n  'isBuilt',\n  'isValid',\n  'modelPropertyMacro',\n  'models',\n  'modelsArray',\n  'options',\n  'parameterMacro',\n  'parseUri',\n  'progress',\n  'resourceCount',\n  'sampleModels',\n  'selfReflect',\n  'setConsolidatedModels',\n  'spec',\n  'supportedSubmitMethods',\n  'swaggerRequestHeaders',\n  'tagFromLabel',\n  'title',\n  'url',\n  'useJQuery',\n  'jqueryAjaxCache'\n];\n// We have to keep track of the function/property names to avoid collisions for tag names which are used to allow the\n// following usage: 'client.apis.{tagName}'\nvar reservedApiTags = [\n  'apis',\n  'asCurl',\n  'description',\n  'externalDocs',\n  'help',\n  'label',\n  'name',\n  'operation',\n  'operations',\n  'operationsArray',\n  'path',\n  'tag'\n];\nvar supportedOperationMethods = ['delete', 'get', 'head', 'options', 'patch', 'post', 'put'];\nvar SwaggerClient = module.exports = function (url, options) {\n  this.authorizations = null;\n  this.authorizationScheme = null;\n  this.basePath = null;\n  this.debug = false;\n  this.enableCookies = false;\n  this.info = null;\n  this.isBuilt = false;\n  this.isValid = false;\n  this.modelsArray = [];\n  this.resourceCount = 0;\n  this.url = null;\n  this.useJQuery = false;\n  this.jqueryAjaxCache = false;\n  this.swaggerObject = {};\n  this.deferredClient = undefined;\n\n  this.clientAuthorizations = new auth.SwaggerAuthorizations();\n\n  if (typeof url !== 'undefined') {\n    return this.initialize(url, options);\n  } else {\n    return this;\n  }\n};\n\nSwaggerClient.prototype.initialize = function (url, options) {\n  this.models = {};\n  this.sampleModels = {};\n\n  if (typeof url === 'string') {\n    this.url = url;\n  } else if (_.isObject(url)) {\n    options = url;\n    this.url = options.url;\n  }\n\n  if(this.url && this.url.indexOf('http:') === -1 && this.url.indexOf('https:') === -1) {\n    // no protocol, so we can only use window if it exists\n    if(typeof(window) !== 'undefined' && typeof(window.location) !== 'undefined') {\n      this.url = window.location.origin + this.url;\n    }\n  }\n\n  options = options || {};\n  this.clientAuthorizations.add(options.authorizations);\n  this.swaggerRequestHeaders = options.swaggerRequestHeaders || 'application/json;charset=utf-8,*/*';\n  this.defaultSuccessCallback = options.defaultSuccessCallback || null;\n  this.defaultErrorCallback = options.defaultErrorCallback || null;\n  this.modelPropertyMacro = options.modelPropertyMacro || null;\n  this.connectionAgent = options.connectionAgent || null;\n  this.parameterMacro = options.parameterMacro || null;\n  this.usePromise = options.usePromise || null;\n\n  // operation request timeout default\n  this.timeout = options.timeout || null;\n  // default to request timeout when not specified\n  this.fetchSpecTimeout = typeof options.fetchSpecTimeout !== 'undefined' ?\n      options.fetchSpecTimeout : options.timeout || null;\n\n  if(this.usePromise) {\n    this.deferredClient = Q.defer();\n  }\n\n  if (typeof options.success === 'function') {\n    this.success = options.success;\n  }\n  if (options.useJQuery) {\n    this.useJQuery = options.useJQuery;\n  }\n\n  if (options.jqueryAjaxCache) {\n    this.jqueryAjaxCache = options.jqueryAjaxCache;\n  }\n\n  if (options.enableCookies) {\n    this.enableCookies = options.enableCookies;\n  }\n\n  this.options = options || {};\n\n  // maybe don't need this?\n  this.options.timeout = this.timeout;\n  this.options.fetchSpecTimeout = this.fetchSpecTimeout;\n\n  this.supportedSubmitMethods = options.supportedSubmitMethods || [];\n  this.failure = options.failure || function (err) { throw err; };\n  this.progress = options.progress || function () {};\n  this.spec = _.cloneDeep(options.spec); // Clone so we do not alter the provided document\n\n  if (options.scheme) {\n    this.scheme = options.scheme;\n  }\n\n  if (this.usePromise || typeof options.success === 'function') {\n    this.ready = true;\n    return this.build();\n  }\n};\n\nSwaggerClient.prototype.build = function (mock) {\n  if (this.isBuilt) {\n    return this;\n  }\n\n  var self = this;\n\n  if (this.spec) {\n    this.progress('fetching resource list; Please wait.');\n  } else {\n    this.progress('fetching resource list: ' + this.url + '; Please wait.');\n  }\n\n  var obj = {\n    useJQuery: this.useJQuery,\n    jqueryAjaxCache: this.jqueryAjaxCache,\n    connectionAgent: this.connectionAgent,\n    enableCookies: this.enableCookies,\n    url: this.url,\n    method: 'get',\n    headers: {\n      accept: this.swaggerRequestHeaders\n    },\n    on: {\n      error: function (response) {\n        if (self && self.url && self.url.substring(0, 4) !== 'http') {\n          return self.fail('Please specify the protocol for ' + self.url);\n        } else if (response.errObj && (response.errObj.code === 'ECONNABORTED' || response.errObj.message.indexOf('timeout') !== -1)) {\n          return self.fail('Request timed out after ' + self.fetchSpecTimeout + 'ms');\n        } else if (response.status === 0) {\n          return self.fail('Can\\'t read from server.  It may not have the appropriate access-control-origin settings.');\n        } else if (response.status === 404) {\n          return self.fail('Can\\'t read swagger JSON from ' + self.url);\n        } else {\n          return self.fail(response.status + ' : ' + response.statusText + ' ' + self.url);\n        }\n      },\n      response: function (resp) {\n\n        var responseObj = resp.obj;\n        if(!responseObj) {\n          return self.fail('failed to parse JSON/YAML response');\n        }\n\n        self.swaggerVersion = responseObj.swaggerVersion;\n        self.swaggerObject = responseObj;\n\n        if (responseObj.swagger && parseInt(responseObj.swagger) === 2) {\n          self.swaggerVersion = responseObj.swagger;\n\n          new Resolver().resolve(responseObj, self.url, self.buildFromSpec, self);\n\n          self.isValid = true;\n        } else {\n          var converter = new SwaggerSpecConverter();\n          self.oldSwaggerObject = self.swaggerObject;\n\n          converter.setDocumentationLocation(self.url);\n          converter.convert(responseObj, self.clientAuthorizations, self.options, function(spec) {\n            self.swaggerObject = spec;\n            new Resolver().resolve(spec, self.url, self.buildFromSpec, self);\n            self.isValid = true;\n          });\n        }\n      }\n    }\n  };\n\n  // only set timeout when specified\n  if (this.fetchSpecTimeout) {\n    obj.timeout = this.fetchSpecTimeout;\n  }\n\n  if (this.spec && typeof this.spec === 'object') {\n    self.swaggerObject = this.spec;\n    setTimeout(function () {\n      new Resolver().resolve(self.spec, self.url, self.buildFromSpec, self);\n    }, 10);\n  } else {\n    this.clientAuthorizations.apply(obj);\n\n    if (mock) {\n      return obj;\n    }\n\n    new SwaggerHttp().execute(obj, this.options);\n  }\n\n  return (this.usePromise) ? this.deferredClient.promise : this;\n};\n\nSwaggerClient.prototype.buildFromSpec = function (response) {\n  if (this.isBuilt) {\n    return this;\n  }\n\n  this.apis = {};\n  this.apisArray = [];\n  this.basePath = response.basePath || '';\n  this.consumes = response.consumes;\n  this.host = response.host || '';\n  this.info = response.info || {};\n  this.produces = response.produces;\n  this.schemes = response.schemes || [];\n  this.securityDefinitions = _.cloneDeep(response.securityDefinitions);\n  this.security = response.security;\n  this.title = response.title || '';\n\n  var key, definedTags = {}, k, location, self = this, i;\n\n  if (response.externalDocs) {\n    this.externalDocs = response.externalDocs;\n  }\n\n  // legacy support\n  this.authSchemes = this.securityDefinitions;\n\n  if(this.securityDefinitions) {\n    for(key in this.securityDefinitions) {\n      var securityDefinition = this.securityDefinitions[key];\n      securityDefinition.vendorExtensions = {};\n      for(var ext in securityDefinition) {\n        helpers.extractExtensions(ext, securityDefinition);\n        if (ext === 'scopes') {\n          var scopes = securityDefinition[ext];\n          if(typeof scopes === 'object') {\n            scopes.vendorExtensions = {};\n            for (var s in scopes) {\n              helpers.extractExtensions(s, scopes);\n              if(s.indexOf('x-') === 0) {\n                delete scopes[s];\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n\n  if (Array.isArray(response.tags)) {\n    definedTags = {};\n\n    for (k = 0; k < response.tags.length; k++) {\n      var t = _.cloneDeep(response.tags[k]);\n      definedTags[t.name] = t;\n      for(i in t) {\n        if(i === 'externalDocs' && typeof t[i] === 'object') {\n          for(var j in t[i]) {\n            helpers.extractExtensions(j, t[i]);\n          }\n        }\n        helpers.extractExtensions(i, t);\n      }\n    }\n  }\n\n\n  if (typeof this.url === 'string') {\n    location = this.parseUri(this.url);\n    if (typeof this.scheme === 'undefined' && typeof this.schemes === 'undefined' || this.schemes.length === 0) {\n      if (typeof location !== 'undefined' && typeof(location.scheme) !== 'undefined') {\n        this.scheme = location.scheme;\n      }\n      if(typeof window !== 'undefined' && typeof(window.location) !== 'undefined') {\n        // use the window scheme\n        this.scheme = window.location.protocol.replace(':','');\n      }\n      else {\n        this.scheme = location.scheme || 'http';\n      }\n    } else if (typeof window !== 'undefined' && typeof(window.location) !== 'undefined' && window.location.protocol.indexOf('chrome-extension') === 0) {\n\t\t// if it is chrome swagger ui extension scheme then let swagger doc url scheme decide the protocol\n\t\tthis.scheme = location.scheme;\n\t} else if (typeof this.scheme === 'undefined') {\n      if(typeof window !== 'undefined' && typeof(window.location) !== 'undefined') {\n        var scheme = window.location.protocol.replace(':','');\n        if(scheme === 'https' && this.schemes.indexOf(scheme) === -1) {\n          // can't call http from https served page in a browser!\n          helpers.log('Cannot call a http server from https inside a browser!');\n          this.scheme = 'http';\n        }\n        else if(this.schemes.indexOf(scheme) !== -1) {\n          this.scheme = scheme;\n        }\n        else {\n          if(this.schemes.indexOf('https') !== -1) {\n            this.scheme = 'https';\n          }\n          else {\n            this.scheme = 'http';\n          }\n        }\n      }\n      else {\n        this.scheme = this.schemes[0] || location.scheme;\n      }\n    }\n\n    if (typeof this.host === 'undefined' || this.host === '') {\n      this.host = location.host;\n\n      if (location.port) {\n        this.host = this.host + ':' + location.port;\n      }\n    }\n  }\n  else {\n    if (typeof this.schemes === 'undefined' || this.schemes.length === 0) {\n      this.scheme = 'http';\n    }\n    else if (typeof this.scheme === 'undefined') {\n      this.scheme = this.schemes[0];\n    }\n  }\n\n  this.definitions = response.definitions;\n\n  for (key in this.definitions) {\n    var model = new Model(key, this.definitions[key], this.models, this.modelPropertyMacro);\n\n    if (model) {\n      this.models[key] = model;\n    }\n  }\n\n  // get paths, create functions for each operationId\n\n  // Bind help to 'client.apis'\n  self.apis.help = _.bind(self.help, self);\n\n  _.forEach(response.paths, function (pathObj, path) {\n    // Only process a path if it's an object\n    if (!_.isPlainObject(pathObj)) {\n      return;\n    }\n\n    _.forEach(supportedOperationMethods, function (method) {\n      var operation = pathObj[method];\n\n      if (_.isUndefined(operation)) {\n        // Operation does not exist\n        return;\n      } else if (!_.isPlainObject(operation)) {\n        // Operation exists but it is not an Operation Object.  Since this is invalid, log it.\n        helpers.log('The \\'' + method + '\\' operation for \\'' + path + '\\' path is not an Operation Object');\n\n        return;\n      }\n\n      var tags = operation.tags;\n\n      if (_.isUndefined(tags) || !_.isArray(tags) || tags.length === 0) {\n        tags = operation.tags = [ 'default' ];\n      }\n\n      var operationId = self.idFromOp(path, method, operation);\n\n      var operationObject = new Operation(self,\n        operation.scheme,\n        operationId,\n        method,\n        path,\n        operation,\n        self.definitions,\n        self.models,\n        self.clientAuthorizations);\n\n      operationObject.connectionAgent = self.connectionAgent;\n      operationObject.vendorExtensions = {};\n      for(i in operation) {\n        helpers.extractExtensions(i, operationObject, operation[i]);\n      }\n      operationObject.externalDocs = operation.externalDocs;\n      if(operationObject.externalDocs) {\n        operationObject.externalDocs = _.cloneDeep(operationObject.externalDocs);\n        operationObject.externalDocs.vendorExtensions = {};\n        for(i in operationObject.externalDocs) {\n          helpers.extractExtensions(i, operationObject.externalDocs);\n        }\n      }\n\n      // bind self operation's execute command to the api\n      _.forEach(tags, function (tag) {\n        var clientProperty = _.indexOf(reservedClientTags, tag) > -1 ? '_' + tag : tag;\n        var apiProperty = _.indexOf(reservedApiTags, tag) > -1 ? '_' + tag : tag;\n        var operationGroup = self[clientProperty];\n\n        if (clientProperty !== tag) {\n          helpers.log('The \\'' + tag + '\\' tag conflicts with a SwaggerClient function/property name.  Use \\'client.' +\n                      clientProperty + '\\' or \\'client.apis.' + tag + '\\' instead of \\'client.' + tag + '\\'.');\n        }\n\n        if (apiProperty !== tag) {\n          helpers.log('The \\'' + tag + '\\' tag conflicts with a SwaggerClient operation function/property name.  Use ' +\n                      '\\'client.apis.' + apiProperty + '\\' instead of \\'client.apis.' + tag + '\\'.');\n        }\n\n        if (_.indexOf(reservedApiTags, operationId) > -1) {\n          helpers.log('The \\'' + operationId + '\\' operationId conflicts with a SwaggerClient operation ' +\n                      'function/property name.  Use \\'client.apis.' + apiProperty + '._' + operationId +\n                      '\\' instead of \\'client.apis.' + apiProperty + '.' + operationId + '\\'.');\n\n          operationId = '_' + operationId;\n          operationObject.nickname = operationId; // So 'client.apis.[tag].operationId.help() works properly\n        }\n\n        if (_.isUndefined(operationGroup)) {\n          operationGroup = self[clientProperty] = self.apis[apiProperty] = {};\n\n          operationGroup.operations = {};\n          operationGroup.label = apiProperty;\n          operationGroup.apis = {};\n\n          var tagDef = definedTags[tag];\n\n          if (!_.isUndefined(tagDef)) {\n            operationGroup.description = tagDef.description;\n            operationGroup.externalDocs = tagDef.externalDocs;\n            operationGroup.vendorExtensions = tagDef.vendorExtensions;\n          }\n\n          self[clientProperty].help = _.bind(self.help, operationGroup);\n          self.apisArray.push(new OperationGroup(tag, operationGroup.description, operationGroup.externalDocs, operationObject));\n        }\n\n        operationId = self.makeUniqueOperationId(operationId, self.apis[apiProperty]);\n\n        // Bind tag help\n        if (!_.isFunction(operationGroup.help)) {\n          operationGroup.help = _.bind(self.help, operationGroup);\n        }\n\n        // bind to the apis object\n        self.apis[apiProperty][operationId] = operationGroup[operationId] = _.bind(operationObject.execute,\n                                                                                  operationObject);\n        self.apis[apiProperty][operationId].help = operationGroup[operationId].help = _.bind(operationObject.help,\n                                                                                             operationObject);\n        self.apis[apiProperty][operationId].asCurl = operationGroup[operationId].asCurl = _.bind(operationObject.asCurl,\n                                                                                                 operationObject);\n\n        operationGroup.apis[operationId] = operationGroup.operations[operationId] = operationObject;\n\n        // legacy UI feature\n        var api = _.find(self.apisArray, function (api) {\n          return api.tag === tag;\n        });\n\n        if (api) {\n          api.operationsArray.push(operationObject);\n        }\n      });\n    });\n  });\n\n  // sort the apisArray according to the tags\n  var sortedApis = [];\n  _.forEach(Object.keys(definedTags), function (tag) {\n    var pos;\n    for(pos in self.apisArray) {\n      var _api = self.apisArray[pos];\n      if(_api && tag === _api.name) {\n        sortedApis.push(_api);\n        self.apisArray[pos] = null;\n      }\n    }\n  });\n  // add anything left\n  _.forEach(self.apisArray, function (api) {\n    if(api) {\n      sortedApis.push(api);\n    }\n  });\n  self.apisArray = sortedApis;\n\n  _.forEach(response.definitions, function (definitionObj, definition) {\n    definitionObj.id = definition.toLowerCase();\n    definitionObj.name = definition;\n    self.modelsArray.push(definitionObj);\n  });\n\n  this.isBuilt = true;\n\n  if (this.usePromise) {\n    this.isValid = true;\n    this.isBuilt = true;\n    this.deferredClient.resolve(this);\n\n    return this.deferredClient.promise;\n  }\n\n  if (this.success) {\n    this.success();\n  }\n\n  return this;\n};\n\nSwaggerClient.prototype.makeUniqueOperationId = function(operationId, api) {\n  var count = 0;\n  var name = operationId;\n\n  // make unique across this operation group\n  while(true) {\n    var matched = false;\n    _.forEach(api.operations, function (operation) {\n      if(operation.nickname === name) {\n        matched = true;\n      }\n    });\n    if(!matched) {\n      return name;\n    }\n    name = operationId + '_' + count;\n    count ++;\n  }\n\n  return operationId;\n};\n\nSwaggerClient.prototype.parseUri = function (uri) {\n  var urlParseRE = /^(((([^:\\/#\\?]+:)?(?:(\\/\\/)((?:(([^:@\\/#\\?]+)(?:\\:([^:@\\/#\\?]+))?)@)?(([^:\\/#\\?\\]\\[]+|\\[[^\\/\\]@#?]+\\])(?:\\:([0-9]+))?))?)?)?((\\/?(?:[^\\/\\?#]+\\/+)*)([^\\?#]*)))?(\\?[^#]+)?)(#.*)?/;\n  var parts = urlParseRE.exec(uri);\n\n  return {\n    scheme: parts[4] ? parts[4].replace(':','') : undefined,\n    host: parts[11],\n    port: parts[12],\n    path: parts[15]\n  };\n};\n\nSwaggerClient.prototype.help = function (dontPrint) {\n  var output = '';\n\n  if (this instanceof SwaggerClient) {\n    _.forEach(this.apis, function (api, name) {\n      if (_.isPlainObject(api)) {\n        output += 'operations for the \\'' + name + '\\' tag\\n';\n\n        _.forEach(api.operations, function (operation, name) {\n          output += '  * ' + name + ': ' + operation.summary + '\\n';\n        });\n      }\n    });\n  } else if (this instanceof OperationGroup || _.isPlainObject(this)) {\n    output += 'operations for the \\'' + this.label + '\\' tag\\n';\n\n    _.forEach(this.apis, function (operation, name) {\n      output += '  * ' + name + ': ' + operation.summary + '\\n';\n    });\n  }\n\n  if (dontPrint) {\n    return output;\n  } else {\n    helpers.log(output);\n\n    return output;\n  }\n};\n\nSwaggerClient.prototype.tagFromLabel = function (label) {\n  return label;\n};\n\nSwaggerClient.prototype.idFromOp = function (path, httpMethod, op) {\n  if(!op || !op.operationId) {\n    op = op || {};\n    op.operationId = httpMethod + '_' + path;\n  }\n  var opId = op.operationId.replace(/[\\s!@#$%^&*()_+=\\[{\\]};:<>|.\\/?,\\\\'\"\"-]/g, '_') || (path.substring(1) + '_' + httpMethod);\n\n  opId = opId.replace(/((_){2,})/g, '_');\n  opId = opId.replace(/^(_)*/g, '');\n  opId = opId.replace(/([_])*$/g, '');\n\n  return opId;\n};\n\nSwaggerClient.prototype.setHost = function (host) {\n  this.host = host;\n\n  if(this.apis) {\n    _.forEach(this.apis, function(api) {\n      if(api.operations) {\n        _.forEach(api.operations, function(operation) {\n          operation.host = host;\n        });\n      }\n    });\n  }\n};\n\nSwaggerClient.prototype.setBasePath = function (basePath) {\n  this.basePath = basePath;\n\n  if(this.apis) {\n    _.forEach(this.apis, function(api) {\n      if(api.operations) {\n        _.forEach(api.operations, function(operation) {\n          operation.basePath = basePath;\n        });\n      }\n    });\n  }\n};\n\nSwaggerClient.prototype.setSchemes = function (schemes) {\n  this.schemes = schemes;\n\n  if(schemes && schemes.length > 0) {\n    if(this.apis) {\n      _.forEach(this.apis, function (api) {\n        if (api.operations) {\n          _.forEach(api.operations, function (operation) {\n            operation.scheme = schemes[0];\n          });\n        }\n      });\n    }\n  }\n};\n\nSwaggerClient.prototype.fail = function (message) {\n  if (this.usePromise) {\n    this.deferredClient.reject(message);\n    return this.deferredClient.promise;\n  } else {\n    if (this.failure) {\n      this.failure(message);\n    }\n    else {\n      this.failure(message);\n    }\n  }\n};\n\n},{\"./auth\":2,\"./helpers\":4,\"./http\":5,\"./resolver\":6,\"./spec-converter\":8,\"./types/model\":9,\"./types/operation\":10,\"./types/operationGroup\":11,\"lodash-compat/array/indexOf\":49,\"lodash-compat/collection/find\":53,\"lodash-compat/collection/forEach\":54,\"lodash-compat/function/bind\":58,\"lodash-compat/lang/cloneDeep\":138,\"lodash-compat/lang/isArray\":140,\"lodash-compat/lang/isFunction\":142,\"lodash-compat/lang/isObject\":144,\"lodash-compat/lang/isPlainObject\":145,\"lodash-compat/lang/isUndefined\":148,\"q\":157}],4:[function(require,module,exports){\n(function (process){\n'use strict';\n\nvar _ = {\n  isPlainObject: require('lodash-compat/lang/isPlainObject'),\n  indexOf: require('lodash-compat/array/indexOf')\n};\n\nmodule.exports.__bind = function (fn, me) {\n  return function(){\n    return fn.apply(me, arguments);\n  };\n};\n\nvar log = module.exports.log = function() {\n  // Only log if available and we're not testing\n  if (console && process.env.NODE_ENV !== 'test') {\n    console.log(Array.prototype.slice.call(arguments)[0]);\n  }\n};\n\nmodule.exports.fail = function (message) {\n  log(message);\n};\n\nmodule.exports.optionHtml = function (label, value) {\n  return '<tr><td class=\"optionName\">' + label + ':</td><td>' + value + '</td></tr>';\n};\n\nvar resolveSchema = module.exports.resolveSchema = function (schema) {\n  if (_.isPlainObject(schema.schema)) {\n    schema = resolveSchema(schema.schema);\n  }\n\n  return schema;\n};\n\nmodule.exports.simpleRef = function (name) {\n  if (typeof name === 'undefined') {\n    return null;\n  }\n\n  if (name.indexOf('#/definitions/') === 0) {\n    return name.substring('#/definitions/'.length);\n  } else {\n    return name;\n  }\n};\n\n/**\n * helper to remove extensions and add them to an object\n *\n * @param keyname\n * @param obj\n */\nmodule.exports.extractExtensions = function (keyname, obj, value) {\n  if(!keyname || !obj) {\n    return;\n  }\n\n  if (typeof keyname === 'string' && keyname.indexOf('x-') === 0) {\n    obj.vendorExtensions = obj.vendorExtensions || {};\n    if(value) {\n      obj.vendorExtensions[keyname] = value;\n    }\n    else {\n      obj.vendorExtensions[keyname] = obj[keyname];\n    }\n  }\n};\n}).call(this,require('_process'))\n\n},{\"_process\":12,\"lodash-compat/array/indexOf\":49,\"lodash-compat/lang/isPlainObject\":145}],5:[function(require,module,exports){\n(function (Buffer){\n'use strict';\n\nvar helpers = require('./helpers');\nvar request = require('superagent');\nvar jsyaml = require('js-yaml');\nvar _ = {\n  isObject: require('lodash-compat/lang/isObject'),\n  keys: require('lodash-compat/object/keys')\n};\n\n/*\n * JQueryHttpClient is a light-weight, node or browser HTTP client\n */\nvar JQueryHttpClient = function () {\n  this.type = 'JQueryHttpClient';\n};\n\n/*\n * SuperagentHttpClient is a light-weight, node or browser HTTP client\n */\nvar SuperagentHttpClient = function () {\n  this.type = 'SuperagentHttpClient';\n};\n\n/**\n * SwaggerHttp is a wrapper for executing requests\n */\nvar SwaggerHttp = module.exports = function () {};\n\nSwaggerHttp.prototype.execute = function (obj, opts) {\n  var client;\n\n  if(opts && opts.client) {\n    client = opts.client;\n  }\n  else {\n    client = new SuperagentHttpClient(opts);\n  }\n  client.opts = opts || {};\n\n  if (opts && opts.requestAgent) {\n    request = opts.requestAgent;\n  }\n\n  // legacy support\n  var hasJQuery = false;\n  if(typeof window !== 'undefined') {\n    if(typeof window.jQuery !== 'undefined') {\n      hasJQuery = true;\n    }\n  }\n  // OPTIONS support\n  if(obj.method.toLowerCase() === 'options' && client.type === 'SuperagentHttpClient') {\n    log('forcing jQuery as OPTIONS are not supported by SuperAgent');\n    obj.useJQuery = true;\n  }\n  if(this.isInternetExplorer() && (obj.useJQuery === false || !hasJQuery )) {\n    throw new Error('Unsupported configuration! JQuery is required but not available');\n  }\n  if ((obj && obj.useJQuery === true) || this.isInternetExplorer() && hasJQuery) {\n    client = new JQueryHttpClient(opts);\n  }\n\n  var success = obj.on.response;\n  var error = obj.on.error;\n\n  var requestInterceptor = function(data) {\n    if(opts && opts.requestInterceptor) {\n      data = opts.requestInterceptor.apply(data);\n    }\n    return data;\n  };\n\n  var responseInterceptor = function(data) {\n    if(opts && opts.responseInterceptor) {\n      data = opts.responseInterceptor.apply(data, [obj]);\n    }\n    return success(data);\n  };\n\n  var errorInterceptor = function(data) {\n    if(opts && opts.responseInterceptor) {\n      data = opts.responseInterceptor.apply(data, [obj]);\n    }\n    error(data);\n  };\n\n  obj.on.error = function(data) {\n    errorInterceptor(data);\n  };\n\n  obj.on.response = function(data) {\n    if(data && data.status >= 400) {\n      errorInterceptor(data);\n    }\n    else {\n      responseInterceptor(data);\n    }\n  };\n\n  if (_.isObject(obj) && _.isObject(obj.body)) {\n    // special processing for file uploads via jquery\n    if (obj.body.type && obj.body.type === 'formData'){\n      if(opts.useJQuery) {\n        obj.contentType = false;\n        obj.processData = false;\n        delete obj.headers['Content-Type'];\n      }\n    }\n  }\n\n  obj = requestInterceptor(obj) || obj;\n  if (obj.beforeSend) {\n    obj.beforeSend(function(_obj) {\n      client.execute(_obj || obj);\n    });\n  } else {\n    client.execute(obj);\n  }\n\n  return (obj.deferred) ? obj.deferred.promise : obj;\n};\n\nSwaggerHttp.prototype.isInternetExplorer = function () {\n  var detectedIE = false;\n\n  if (typeof navigator !== 'undefined' && navigator.userAgent) {\n    var nav = navigator.userAgent.toLowerCase();\n\n    if (nav.indexOf('msie') !== -1) {\n      var version = parseInt(nav.split('msie')[1]);\n\n      if (version <= 8) {\n        detectedIE = true;\n      }\n    }\n  }\n\n  return detectedIE;\n};\n\nJQueryHttpClient.prototype.execute = function (obj) {\n  var jq = this.jQuery || (typeof window !== 'undefined' && window.jQuery);\n  var cb = obj.on;\n  var request = obj;\n\n  if(typeof jq === 'undefined' || jq === false) {\n    throw new Error('Unsupported configuration! JQuery is required but not available');\n  }\n\n  obj.type = obj.method;\n  obj.cache = obj.jqueryAjaxCache;\n  obj.data = obj.body;\n  delete obj.jqueryAjaxCache;\n  delete obj.useJQuery;\n  delete obj.body;\n\n  obj.complete = function (response) {\n    var headers = {};\n    var headerArray = response.getAllResponseHeaders().split('\\n');\n\n    for (var i = 0; i < headerArray.length; i++) {\n      var toSplit = headerArray[i].trim();\n\n      if (toSplit.length === 0) {\n        continue;\n      }\n\n      var separator = toSplit.indexOf(':');\n\n      if (separator === -1) {\n        // Name but no value in the header\n        headers[toSplit] = null;\n\n        continue;\n      }\n\n      var name = toSplit.substring(0, separator).trim();\n      var value = toSplit.substring(separator + 1).trim();\n\n      headers[name] = value;\n    }\n\n    var out = {\n      url: request.url,\n      method: request.method,\n      status: response.status,\n      statusText: response.statusText,\n      data: response.responseText,\n      headers: headers\n    };\n\n    try {\n      var possibleObj =  response.responseJSON || jsyaml.safeLoad(response.responseText);\n      out.obj = (typeof possibleObj === 'string') ? {} : possibleObj;\n    } catch (ex) {\n      // do not set out.obj\n      helpers.log('unable to parse JSON/YAML content');\n    }\n\n    // I can throw, or parse null?\n    out.obj = out.obj || null;\n\n    if (response.status >= 200 && response.status < 300) {\n      cb.response(out);\n    } else if (response.status === 0 || (response.status >= 400 && response.status < 599)) {\n      cb.error(out);\n    } else {\n      return cb.response(out);\n    }\n  };\n\n  jq.support.cors = true;\n\n  return jq.ajax(obj);\n};\n\nSuperagentHttpClient.prototype.execute = function (obj) {\n  var method = obj.method.toLowerCase();\n  var timeout = obj.timeout;\n\n  if (method === 'delete') {\n    method = 'del';\n  }\n  var headers = obj.headers || {};\n\n  var r = request[method](obj.url);\n\n  if (obj.connectionAgent) {\n    r.agent(obj.connectionAgent);\n  }\n\n  if (timeout) {\n    r.timeout(timeout);\n  }\n\n  if (obj.enableCookies) {\n    r.withCredentials();\n  }\n\n  var accept = obj.headers.Accept;\n\n  if(this.binaryRequest(accept)) {\n    r.on('request', function () {\n      if(this.xhr) {\n        this.xhr.responseType = 'blob';\n      }\n    });\n  }\n\n  if(obj.body) {\n    if(_.isObject(obj.body)) {\n      var contentType = obj.headers['Content-Type'] || '';\n      if (contentType.indexOf('multipart/form-data') === 0) {\n        delete headers['Content-Type'];\n        if({}.toString.apply(obj.body) === '[object FormData]') {\n          r.send(obj.body);\n        }\n        else {\n          var keyname, value, v;\n          for (keyname in obj.body) {\n            value = obj.body[keyname];\n            if(Array.isArray(value)) {\n              for(v in value) {\n                r.field(keyname, v);\n              }\n            }\n            else {\n              r.field(keyname, value);\n            }\n          }\n        }\n      }\n      else if (_.isObject(obj.body)) {\n        // non multipart/form-data\n        obj.body = JSON.stringify(obj.body);\n        r.send(obj.body);\n      }\n    }\n    else {\n      r.send(obj.body);\n    }\n  }\n\n  var name;\n  for (name in headers) {\n    r.set(name, headers[name]);\n  }\n\n  if(typeof r.buffer === 'function') {\n    r.buffer(); // force superagent to populate res.text with the raw response data\n  }\n\n  r.end(function (err, res) {\n    res = res || {\n      status: 0,\n      headers: {error: 'no response from server'}\n    };\n    var response = {\n      url: obj.url,\n      method: obj.method,\n      headers: res.headers\n    };\n    var cb;\n\n    if (!err && res.error) {\n      err = res.error;\n    }\n\n    if (err && obj.on && obj.on.error) {\n      response.errObj = err;\n      response.status = res ? res.status : 500;\n      response.statusText = res ? res.text : err.message;\n      if (res.headers && res.headers['content-type']) {\n        if (res.headers['content-type'].indexOf('application/json') >= 0) {\n          try {\n            response.obj = JSON.parse(response.statusText);\n          }\n          catch (e) {\n            response.obj = null;\n          }\n        }\n      }\n      cb = obj.on.error;\n    } else if (res && obj.on && obj.on.response) {\n      var possibleObj;\n\n      // Already parsed by by superagent?\n      if (res.body && _.keys(res.body).length > 0) {\n        possibleObj = res.body;\n      } else {\n        try {\n          possibleObj = jsyaml.safeLoad(res.text);\n          // can parse into a string... which we don't need running around in the system\n          possibleObj = (typeof possibleObj === 'string') ? null : possibleObj;\n        } catch (e) {\n          helpers.log('cannot parse JSON/YAML content');\n        }\n      }\n\n      // null means we can't parse into object\n      if(typeof Buffer === 'function' && Buffer.isBuffer(possibleObj)) {\n        response.data = possibleObj;\n      }\n      else {\n        response.obj = (typeof possibleObj === 'object') ? possibleObj : null;\n      }\n\n      response.status = res.status;\n      response.statusText = res.text;\n      cb = obj.on.response;\n    }\n    if (res.xhr && res.xhr.response) {\n      response.data = res.xhr.response;\n    }\n    else if(!response.data) {\n      response.data = response.statusText;\n    }\n\n    if (cb) {\n      cb(response);\n    }\n  });\n};\n\nSuperagentHttpClient.prototype. binaryRequest = function (accept) {\n  if(!accept) {\n    return false;\n  }\n  return (/^image/i).test(accept)\n    || (/^application\\/pdf/).test(accept)\n    || (/^application\\/octet-stream/).test(accept);\n};\n\n}).call(this,require(\"buffer\").Buffer)\n\n},{\"./helpers\":4,\"buffer\":14,\"js-yaml\":19,\"lodash-compat/lang/isObject\":144,\"lodash-compat/object/keys\":149,\"superagent\":158}],6:[function(require,module,exports){\n'use strict';\n\nvar SwaggerHttp = require('./http');\nvar _ = {\n  isObject: require('lodash-compat/lang/isObject'),\n  cloneDeep: require('lodash-compat/lang/cloneDeep'),\n  isArray: require('lodash-compat/lang/isArray'),\n  isString: require('lodash-compat/lang/isString')\n};\n\n\n/**\n * Resolves a spec's remote references\n */\nvar Resolver = module.exports = function () {\n  this.failedUrls = [];\n  this.resolverCache = {};\n  this.pendingUrls = {};\n};\n\nResolver.prototype.processAllOf = function(root, name, definition, resolutionTable, unresolvedRefs, spec) {\n  var i, location, property;\n\n  definition['x-resolved-from'] = [ '#/definitions/' + name ];\n  var allOf = definition.allOf;\n  // the refs go first\n  allOf.sort(function(a, b) {\n    if(a.$ref && b.$ref) { return 0; }\n    else if(a.$ref) { return -1; }\n    else { return 1; }\n  });\n  for (i = 0; i < allOf.length; i++) {\n    property = allOf[i];\n    location = '/definitions/' + name + '/allOf';\n    this.resolveInline(root, spec, property, resolutionTable, unresolvedRefs, location);\n  }\n};\n\nResolver.prototype.resolve = function (spec, arg1, arg2, arg3) {\n  this.spec = spec;\n  var root = arg1, callback = arg2, scope = arg3, opts = {}, location, i;\n  if(typeof arg1 === 'function') {\n    root = null;\n    callback = arg1;\n    scope = arg2;\n  }\n  var _root = root, modelName;\n  this.scope = (scope || this);\n  this.iteration = this.iteration || 0;\n\n  if(this.scope.options && this.scope.options.requestInterceptor){\n    opts.requestInterceptor = this.scope.options.requestInterceptor;\n  }\n\n  if(this.scope.options && this.scope.options.responseInterceptor){\n    opts.responseInterceptor = this.scope.options.responseInterceptor;\n  }\n\n  var name, path, property, propertyName, parameter, done, counter;\n  var processedCalls = 0, resolvedRefs = {}, unresolvedRefs = {};\n  var resolutionTable = []; // store objects for dereferencing\n\n  spec.definitions = spec.definitions || {};\n  // definitions\n  for (name in spec.definitions) {\n    var definition = spec.definitions[name];\n    if(definition.$ref) {\n      this.resolveInline(root, spec, definition, resolutionTable, unresolvedRefs, definition);\n    }\n    else {\n      for (propertyName in definition.properties) {\n        property = definition.properties[propertyName];\n        if (_.isArray(property.allOf)) {\n          this.processAllOf(root, name, property, resolutionTable, unresolvedRefs, spec);\n        }\n        else {\n          this.resolveTo(root, property, resolutionTable, '/definitions');\n        }\n      }\n\n      if (definition.allOf) {\n        this.processAllOf(root, name, definition, resolutionTable, unresolvedRefs, spec);\n      }\n    }\n  }\n\n  // shared parameters\n  spec.parameters = spec.parameters || {};\n  for(name in spec.parameters) {\n    parameter = spec.parameters[name];\n    if (parameter.in === 'body' && parameter.schema) {\n      if(_.isArray(parameter.schema.allOf)) {\n        // move to a definition\n        modelName = 'inline_model';\n        var _name = modelName;\n        done = false; counter = 0;\n        while(!done) {\n          if(typeof spec.definitions[_name] === 'undefined') {\n            done = true;\n            break;\n          }\n          _name = modelName + '_' + counter;\n          counter ++;\n        }\n        spec.definitions[_name] = { allOf: parameter.schema.allOf };\n        delete parameter.schema.allOf;\n        parameter.schema.$ref = '#/definitions/' + _name;\n        this.processAllOf(root, _name, spec.definitions[_name], resolutionTable, unresolvedRefs, spec);\n      }\n      else {\n        this.resolveTo(root, parameter.schema, resolutionTable, location);\n      }\n    }\n\n    if (parameter.$ref) {\n      // parameter reference\n      this.resolveInline(root, spec, parameter, resolutionTable, unresolvedRefs, parameter.$ref);\n    }\n  }\n\n  // operations\n  for (name in spec.paths) {\n    var method, operation, responseCode;\n    path = spec.paths[name];\n\n    if(typeof path === 'object') {\n      for (method in path) {\n        // operation reference\n        if (method === '$ref') {\n          // location = path[method];\n          location = '/paths' + name;\n          this.resolveInline(root, spec, path, resolutionTable, unresolvedRefs, location);\n        }\n        else {\n          operation = path[method];\n          var sharedParameters = path.parameters || [];\n          var parameters = operation.parameters || [];\n\n          sharedParameters.forEach(function(parameter) {\n            parameters.unshift(parameter);\n          });\n\n          if (method !== 'parameters' && _.isObject(operation)) {\n            operation.parameters = operation.parameters || parameters;\n          }\n\n          for (i in parameters) {\n            parameter = parameters[i];\n            location = '/paths' + name + '/' + method + '/parameters';\n\n            if (parameter.in === 'body' && parameter.schema) {\n              if (_.isArray(parameter.schema.allOf)) {\n                // move to a definition\n                modelName = 'inline_model';\n                name = modelName;\n                done = false;\n                counter = 0;\n                while (!done) {\n                  if (typeof spec.definitions[name] === 'undefined') {\n                    done = true;\n                    break;\n                  }\n                  name = modelName + '_' + counter;\n                  counter++;\n                }\n                spec.definitions[name] = {allOf: parameter.schema.allOf};\n                delete parameter.schema.allOf;\n                parameter.schema.$ref = '#/definitions/' + name;\n                this.processAllOf(root, name, spec.definitions[name], resolutionTable, unresolvedRefs, spec);\n              }\n              else {\n                this.resolveTo(root, parameter.schema, resolutionTable, location);\n              }\n            }\n\n            if (parameter.$ref) {\n              // parameter reference\n              this.resolveInline(root, spec, parameter, resolutionTable, unresolvedRefs, parameter.$ref);\n            }\n          }\n\n          for (responseCode in operation.responses) {\n            var response = operation.responses[responseCode];\n            location = '/paths' + name + '/' + method + '/responses/' + responseCode;\n\n            if (_.isObject(response)) {\n              if (response.$ref) {\n                // response reference\n                this.resolveInline(root, spec, response, resolutionTable, unresolvedRefs, location);\n              }\n              if (response.schema) {\n                var responseObj = response;\n                if (_.isArray(responseObj.schema.allOf)) {\n                  // move to a definition\n                  modelName = 'inline_model';\n                  name = modelName;\n                  done = false;\n                  counter = 0;\n                  while (!done) {\n                    if (typeof spec.definitions[name] === 'undefined') {\n                      done = true;\n                      break;\n                    }\n                    name = modelName + '_' + counter;\n                    counter++;\n                  }\n                  spec.definitions[name] = {allOf: responseObj.schema.allOf};\n                  delete responseObj.schema.allOf;\n                  delete responseObj.schema.type;\n                  responseObj.schema.$ref = '#/definitions/' + name;\n                  this.processAllOf(root, name, spec.definitions[name], resolutionTable, unresolvedRefs, spec);\n                }\n                else if ('array' === responseObj.schema.type) {\n                  if (responseObj.schema.items && responseObj.schema.items.$ref) {\n                    // response reference\n                    this.resolveInline(root, spec, responseObj.schema.items, resolutionTable, unresolvedRefs, location);\n                  }\n                }\n                else {\n                  this.resolveTo(root, response.schema, resolutionTable, location);\n                }\n              }\n            }\n          }\n        }\n      }\n      // clear them out to avoid multiple resolutions\n      path.parameters = [];\n    }\n  }\n\n  var expectedCalls = 0, toResolve = [];\n  // if the root is same as obj[i].root we can resolve locally\n  var all = resolutionTable;\n\n  var parts;\n  for(i = 0; i < all.length; i++) {\n    var a = all[i];\n    if(root === a.root) {\n      if(a.resolveAs === 'ref') {\n        // resolve any path walking\n        var joined = ((a.root || '') + '/' + a.key).split('/');\n        var normalized = [];\n        var url = '';\n        var k;\n\n        if(a.key.indexOf('../') >= 0) {\n          for(var j = 0; j < joined.length; j++) {\n            if(joined[j] === '..') {\n              normalized = normalized.slice(0, normalized.length-1);\n            }\n            else {\n              normalized.push(joined[j]);\n            }\n          }\n          for(k = 0; k < normalized.length; k ++) {\n            if(k > 0) {\n              url += '/';\n            }\n            url += normalized[k];\n          }\n          // we now have to remote resolve this because the path has changed\n          a.root = url;\n          toResolve.push(a);\n        }\n        else {\n          parts = a.key.split('#');\n          if(parts.length === 2) {\n            if(parts[0].indexOf('http:') === 0 || parts[0].indexOf('https:') === 0) {\n              a.root = parts[0];\n            }\n            location = parts[1].split('/');\n            var r;\n            var s = spec;\n            for(k = 0; k < location.length; k++) {\n              var part = location[k];\n              if(part !== '') {\n                s = s[part];\n                if(typeof s !== 'undefined') {\n                  r = s;\n                }\n                else {\n                  r = null;\n                  break;\n                }\n              }\n            }\n            if(r === null) {\n              // must resolve this too\n              toResolve.push(a);\n            }\n          }\n        }\n      }\n      else {\n        if (a.resolveAs === 'inline') {\n          if(a.key && a.key.indexOf('#') === -1 && a.key.charAt(0) !== '/') {\n            // handle relative schema\n            parts = a.root.split('/');\n            location = '';\n            for(i = 0; i < parts.length - 1; i++) {\n              location += parts[i] + '/';\n            }\n            location += a.key;\n            a.root = location;\n            a.location = '';\n          }\n          toResolve.push(a);\n        }\n      }\n    }\n    else {\n      toResolve.push(a);\n    }\n  }\n  expectedCalls = toResolve.length;\n\n  // resolve anything that is local\n\n  var lock = {};\n  for(var ii = 0; ii < toResolve.length; ii++) {\n    (function(item, spec, self, lock, ii) {\n      if(!item.root || item.root === root) {\n        // local resolve\n        self.resolveItem(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, item);\n        processedCalls += 1;\n\n        if(processedCalls === expectedCalls) {\n          self.finish(spec, root, resolutionTable, resolvedRefs, unresolvedRefs, callback, true);\n        }\n      }\n      else if(self.failedUrls.indexOf(item.root) === -1) {\n        var obj = {\n          useJQuery: false,  // TODO\n          url: item.root,\n          method: 'get',\n          headers: {\n            accept: self.scope.swaggerRequestHeaders || 'application/json'\n          },\n          on: {\n            error: function (error) {\n              processedCalls += 1;\n              console.log('failed url: ' + obj.url);\n              self.failedUrls.push(obj.url);\n              if (lock) {\n                delete lock[item.root];\n              }\n              unresolvedRefs[item.key] = {\n                root: item.root,\n                location: item.location\n              };\n\n              if (processedCalls === expectedCalls) {\n                self.finish(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, callback);\n              }\n            },  // jshint ignore:line\n            response: function (response) {\n              var swagger = response.obj;\n              if (lock) {\n                delete lock[item.root];\n              }\n              if (self.resolverCache) {\n                self.resolverCache[item.root] = swagger;\n              }\n              self.resolveItem(swagger, item.root, resolutionTable, resolvedRefs, unresolvedRefs, item);\n              processedCalls += 1;\n\n              if (processedCalls === expectedCalls) {\n                self.finish(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, callback);\n              }\n            }\n          } // jshint ignore:line\n        };\n\n        // apply timeout only when specified\n        if (scope && scope.fetchSpecTimeout) {\n          obj.timeout = scope.fetchSpecTimeout;\n        }\n\n        if (scope && scope.clientAuthorizations) {\n          scope.clientAuthorizations.apply(obj);\n        }\n\n        (function waitForUnlock() {\n          setTimeout(function() {\n            if (lock[obj.url]) {\n              waitForUnlock();\n            }\n            else {\n              var cached = self.resolverCache[obj.url];\n              if (_.isObject(cached)) {\n                obj.on.response({obj: cached});\n              }\n              else {\n                lock[obj.url] = true;\n                new SwaggerHttp().execute(obj, opts);\n              }\n            }\n          }, 0);\n        })();\n      }\n\n      else {\n        processedCalls += 1;\n        unresolvedRefs[item.key] = {\n          root: item.root,\n          location: item.location\n        };\n        if (processedCalls === expectedCalls) {\n          self.finish(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, callback);\n        }\n      }\n    }(toResolve[ii], spec, this, lock, ii));\n  }\n\n  if (Object.keys(toResolve).length === 0) {\n    this.finish(spec, _root, resolutionTable, resolvedRefs, unresolvedRefs, callback);\n  }\n};\n\nResolver.prototype.resolveItem = function(spec, root, resolutionTable, resolvedRefs, unresolvedRefs, item) {\n  var path = item.location;\n  var location = spec, parts = path.split('/');\n  if(path !== '') {\n    for (var j = 0; j < parts.length; j++) {\n      var segment = parts[j];\n      if (segment.indexOf('~1') !== -1) {\n        segment = parts[j].replace(/~0/g, '~').replace(/~1/g, '/');\n        if (segment.charAt(0) !== '/') {\n          segment = '/' + segment;\n        }\n      }\n      if (typeof location === 'undefined' || location === null) {\n        break;\n      }\n      if (segment === '' && j === (parts.length - 1) && parts.length > 1) {\n        location = null;\n        break;\n      }\n      if (segment.length > 0) {\n        location = location[segment];\n      }\n    }\n  }\n  var resolved = item.key;\n  parts = item.key.split('/');\n  var resolvedName = parts[parts.length-1];\n\n  if(resolvedName.indexOf('#') >= 0) {\n    resolvedName = resolvedName.split('#')[1];\n  }\n\n  if (location !== null && typeof location !== 'undefined') {\n    resolvedRefs[resolved] = {\n      name: resolvedName,\n      obj: location,\n      key: item.key,\n      root: item.root\n    };\n  } else {\n    unresolvedRefs[resolved] = {\n      root: item.root,\n      location: item.location\n    };\n  }\n};\n\nResolver.prototype.finish = function (spec, root, resolutionTable, resolvedRefs, unresolvedRefs, callback, localResolve) {\n  // walk resolution table and replace with resolved refs\n  var ref, abs;\n  for (ref in resolutionTable) {\n    var item = resolutionTable[ref];\n\n    var key = item.key;\n    var resolvedTo = resolvedRefs[key];\n    if (resolvedTo) {\n      spec.definitions = spec.definitions || {};\n      if (item.resolveAs === 'ref') {\n        if (localResolve !== true) {\n          // don't retain root for local definitions\n          for (key in resolvedTo.obj) {\n            abs = this.retainRoot(key, resolvedTo.obj[key], item.root);\n            resolvedTo.obj[key] = abs;\n          }\n        }\n        spec.definitions[resolvedTo.name] = resolvedTo.obj;\n        item.obj.$ref = '#/definitions/' + resolvedTo.name;\n      } else if (item.resolveAs === 'inline') {\n        var targetObj = item.obj;\n        targetObj['x-resolved-from'] = [ item.key ];\n        delete targetObj.$ref;\n\n        for (key in resolvedTo.obj) {\n          abs = resolvedTo.obj[key];\n\n          if (localResolve !== true) {\n            // don't retain root for local definitions\n            abs = this.retainRoot(key, resolvedTo.obj[key], item.root);\n          }\n          targetObj[key] = abs;\n        }\n      }\n    }\n  }\n  var existingUnresolved = this.countUnresolvedRefs(spec);\n\n  if(existingUnresolved === 0 || this.iteration > 5) {\n    this.resolveAllOf(spec.definitions);\n    this.resolverCache = null;\n    callback.call(this.scope, spec, unresolvedRefs);\n  }\n  else {\n    this.iteration += 1;\n    this.resolve(spec, root, callback, this.scope);\n  }\n};\n\nResolver.prototype.countUnresolvedRefs = function(spec) {\n  var i;\n  var refs = this.getRefs(spec);\n  var keys = [];\n  var unresolvedKeys = [];\n  for(i in refs) {\n    if(i.indexOf('#') === 0) {\n      keys.push(i.substring(1));\n    }\n    else {\n      unresolvedKeys.push(i);\n    }\n  }\n\n  // verify possible keys\n  for (i = 0; i < keys.length; i++) {\n    var part = keys[i];\n    var parts = part.split('/');\n    var obj = spec;\n\n    for (var k = 0; k < parts.length; k++) {\n      var key = parts[k];\n      if(key !== '') {\n        obj = obj[key];\n        if(typeof obj === 'undefined') {\n          unresolvedKeys.push(part);\n          break;\n        }\n      }\n    }\n  }\n  return unresolvedKeys.length;\n};\n\nResolver.prototype.getRefs = function(spec, obj) {\n  obj = obj || spec;\n  var output = {};\n  for(var key in obj) {\n    if (!obj.hasOwnProperty(key)) {\n      continue;\n    }\n    var item = obj[key];\n    if(key === '$ref' && typeof item === 'string') {\n      output[item] = null;\n    }\n    else if(_.isObject(item)) {\n      var o = this.getRefs(item);\n      for(var k in o) {\n        output[k] = null;\n      }\n    }\n  }\n  return output;\n};\n\nfunction splitUrl(url) {\n  var result = {};\n  var proto = /[a-z]+:\\/\\//i.exec(url);\n  if (proto) {\n    result.proto = proto[0].slice(0, -3);\n    url = url.slice(result.proto.length + 1);\n  }\n  if (url.slice(0, 2) === '//') {\n    result.domain = url.slice(2).split('/')[0];\n    url = url.slice(2 + result.domain.length);\n  }\n  var p = url.split('#');\n  if (p[0].length) {\n    result.path = p[0];\n  }\n  if (p.length > 1) {\n    result.fragment = p.slice(1).join('#');\n  }\n  return result;\n}\n\nfunction unsplitUrl(url) {\n  var result = url.path;\n  if (result === undefined) {\n    result = '';\n  }\n  if (url.fragment !== undefined) {\n    result += '#' + url.fragment;\n  }\n  if (url.domain !== undefined) {\n    if (result.slice(0, 1) === '/') {\n      result = result.slice(1);\n    }\n    result = '//' + url.domain + '/' + result;\n    if (url.proto !== undefined) {\n      result = url.proto + ':' + result;\n    }\n  }\n  return result;\n}\n\nfunction joinUrl(base, rel) {\n  var relsp = splitUrl(rel);\n  if (relsp.domain !== undefined) {\n    return rel;\n  }\n  var result = splitUrl(base);\n  if (relsp.path === undefined) {\n    // change only fragment part\n    result.fragment = relsp.fragment;\n  } else if (relsp.path.slice(0, 1) === '/') {\n    // relative to domain\n    result.path = relsp.path;\n    result.fragment = relsp.fragment;\n  } else {\n    // relative to path\n    var path = result.path === undefined ? [] : result.path.split('/');\n    var relpath = relsp.path.split('/');\n    if (path.length) {\n      path.pop();\n    }\n    while (relpath[0] === '..' || relpath[0] === '.') {\n      if (relpath[0] === '..') {\n        path.pop();\n      }\n      relpath.shift();\n    }\n    result.path = path.concat(relpath).join('/');\n    result.fragment = relsp.fragment;\n  }\n  return unsplitUrl(result);\n}\n\nResolver.prototype.retainRoot = function(origKey, obj, root) {\n  // walk object and look for relative $refs\n  if(_.isObject(obj)) {\n    for(var key in obj) {\n      var item = obj[key];\n      if (key === '$ref' && typeof item === 'string') {\n        obj[key] = joinUrl(root, item);\n      }\n      else if (_.isObject(item)) {\n        this.retainRoot(key, item, root);\n      }\n    }\n  }\n  else if(_.isString(obj) && origKey === '$ref') {\n    obj = joinUrl(root, obj);\n  }\n  return obj;\n};\n\n/**\n * immediately in-lines local refs, queues remote refs\n * for inline resolution\n */\nResolver.prototype.resolveInline = function (root, spec, property, resolutionTable, unresolvedRefs, location) {\n  var key = property.$ref, ref = property.$ref, i, p, p2, rs;\n  var rootTrimmed = false;\n\n  root = root || ''; // Guard against .split. @fehguy, you'll need to check if this logic fits\n  // More imporantly is how do we gracefully handle relative urls, when provided just a 'spec', not a 'url' ?\n\n  if (ref) {\n    if(ref.indexOf('../') === 0) {\n      // reset root\n      p = ref.split('../');\n      p2 = root.split('/');\n      ref = '';\n      for(i = 0; i < p.length; i++) {\n        if(p[i] === '') {\n          p2 = p2.slice(0, p2.length-1);\n        }\n        else {\n          ref += p[i];\n        }\n      }\n      root = '';\n      for(i = 0; i < p2.length - 1; i++) {\n        if(i > 0) { root += '/'; }\n        root += p2[i];\n      }\n      rootTrimmed = true;\n    }\n    if(ref.indexOf('#') >= 0) {\n      if(ref.indexOf('/') === 0) {\n        rs = ref.split('#');\n        p  = root.split('//');\n        p2 = p[1].split('/');\n        root = p[0] + '//' + p2[0] + rs[0];\n        location = rs[1];\n      }\n      else {\n        rs = ref.split('#');\n        if(rs[0] !== '') {\n          p2 = root.split('/');\n          p2 = p2.slice(0, p2.length - 1);\n          if(!rootTrimmed) {\n            root = '';\n            for (var k = 0; k < p2.length; k++) {\n              if(k > 0) { root += '/'; }\n              root += p2[k];\n            }\n          }\n          root += '/' + ref.split('#')[0];\n        }\n        location = rs[1];\n      }\n    }\n    if (ref.indexOf('http:') === 0 || ref.indexOf('https:') === 0) {\n      if(ref.indexOf('#') >= 0) {\n        root = ref.split('#')[0];\n        location = ref.split('#')[1];\n      }\n      else {\n        root = ref;\n        location = '';\n      }\n      resolutionTable.push({obj: property, resolveAs: 'inline', root: root, key: key, location: location});\n    } else if (ref.indexOf('#') === 0) {\n      location = ref.split('#')[1];\n      resolutionTable.push({obj: property, resolveAs: 'inline', root: root, key: key, location: location});\n    } else if (ref.indexOf('/') === 0 && ref.indexOf('#') === -1) {\n      location = ref;\n      var matches = root.match(/^https?\\:\\/\\/([^\\/?#]+)(?:[\\/?#]|$)/i);\n      if(matches) {\n        root = matches[0] + ref.substring(1);\n        location = '';\n      }\n      resolutionTable.push({obj: property, resolveAs: 'inline', root: root, key: key, location: location});\n    }\n    else {\n      resolutionTable.push({obj: property, resolveAs: 'inline', root: root, key: key, location: location});\n    }\n  }\n  else if (property.type === 'array') {\n    this.resolveTo(root, property.items, resolutionTable, location);\n  }\n};\n\nResolver.prototype.resolveTo = function (root, property, resolutionTable, location) {\n  var sp, i;\n  var ref = property.$ref;\n  var lroot = root;\n  if ((typeof ref !== 'undefined') && (ref !== null)) {\n    if(ref.indexOf('#') >= 0) {\n      var parts = ref.split('#');\n\n      // #/definitions/foo\n      // foo.json#/bar\n      if(parts[0] && ref.indexOf('/') === 0) {\n\n      }\n      else if(parts[0] && (parts[0].indexOf('http:') === 0 || parts[0].indexOf('https:') === 0)) {\n        lroot = parts[0];\n        ref = parts[1];\n      }\n      else if(parts[0] && parts[0].length > 0) {\n        // relative file\n        sp = root.split('/');\n        lroot = '';\n        for(i = 0; i < sp.length - 1; i++) {\n          lroot += sp[i] + '/';\n        }\n        lroot += parts[0];\n      }\n      else {\n\n      }\n\n      location = parts[1];\n    }\n    else if (ref.indexOf('http:') === 0 || ref.indexOf('https:') === 0) {\n      lroot = ref;\n      location = '';\n    }\n    else {\n      // relative file\n      sp = root.split('/');\n      lroot = '';\n      for(i = 0; i < sp.length - 1; i++) {\n        lroot += sp[i] + '/';\n      }\n      lroot += ref;\n      location = '';\n    }\n    resolutionTable.push({\n      obj: property, resolveAs: 'ref', root: lroot, key: ref, location: location\n    });\n  } else if (property.type === 'array') {\n    var items = property.items;\n    this.resolveTo(root, items, resolutionTable, location);\n  } else {\n    if(property && (property.properties || property.additionalProperties)) {\n      var name = this.uniqueName('inline_model');\n      if (property.title) {\n        name = this.uniqueName(property.title);\n      }\n      delete property.title;\n      this.spec.definitions[name] = _.cloneDeep(property);\n      property.$ref = '#/definitions/' + name;\n      delete property.type;\n      delete property.properties;\n    }\n  }\n};\n\nResolver.prototype.uniqueName = function(base) {\n  var name = base;\n  var count = 0;\n  while(true) {\n    if(!_.isObject(this.spec.definitions[name])) {\n      return name;\n    }\n    name = base + '_' + count;\n    count++;\n  }\n};\n\nResolver.prototype.resolveAllOf = function(spec, obj, depth) {\n  depth = depth || 0;\n  obj = obj || spec;\n  var name;\n  for(var key in obj) {\n    if (!obj.hasOwnProperty(key)) {\n      continue;\n    }\n    var item = obj[key];\n    if(item === null) {\n      throw new TypeError('Swagger 2.0 does not support null types (' + obj + ').  See https://github.com/swagger-api/swagger-spec/issues/229.');\n    }\n    if(typeof item === 'object') {\n      this.resolveAllOf(spec, item, depth + 1);\n    }\n    if(item && typeof item.allOf !== 'undefined') {\n      var allOf = item.allOf;\n      if(_.isArray(allOf)) {\n        var output = _.cloneDeep(item);\n        delete output.allOf;\n\n        output['x-composed'] = true;\n        if (typeof item['x-resolved-from'] !== 'undefined') {\n          output['x-resolved-from'] = item['x-resolved-from'];\n        }\n\n        for(var i = 0; i < allOf.length; i++) {\n          var component = allOf[i];\n          var source = 'self';\n          if(typeof component['x-resolved-from'] !== 'undefined') {\n            source = component['x-resolved-from'][0];\n          }\n\n          for(var part in component) {\n            if(!output.hasOwnProperty(part)) {\n              output[part] = _.cloneDeep(component[part]);\n              if(part === 'properties') {\n                for(name in output[part]) {\n                  output[part][name]['x-resolved-from'] = source;\n                }\n              }\n            }\n            else {\n              if(part === 'properties') {\n                var properties = component[part];\n                for(name in properties) {\n                  output.properties[name] = _.cloneDeep(properties[name]);\n                  var resolvedFrom = properties[name]['x-resolved-from'];\n                  if (typeof resolvedFrom === 'undefined' || resolvedFrom === 'self') {\n                    resolvedFrom = source;\n                  }\n                  output.properties[name]['x-resolved-from'] = resolvedFrom;\n                }\n              }\n              else if(part === 'required') {\n                // merge & dedup the required array\n                var a = output.required.concat(component[part]);\n                for(var k = 0; k < a.length; ++k) {\n                  for(var j = k + 1; j < a.length; ++j) {\n                    if(a[k] === a[j]) { a.splice(j--, 1); }\n                  }\n                }\n                output.required = a;\n              }\n              else if(part === 'x-resolved-from') {\n                output['x-resolved-from'].push(source);\n              }\n              else {\n                // TODO: need to merge this property\n                // console.log('what to do with ' + part)\n              }\n            }\n          }\n        }\n        obj[key] = output;\n      }\n    }\n  }\n};\n\n},{\"./http\":5,\"lodash-compat/lang/cloneDeep\":138,\"lodash-compat/lang/isArray\":140,\"lodash-compat/lang/isObject\":144,\"lodash-compat/lang/isString\":146}],7:[function(require,module,exports){\n'use strict';\n\nvar Helpers = require('./helpers');\n\nvar _ = {\n  isPlainObject: require('lodash-compat/lang/isPlainObject'),\n  isUndefined: require('lodash-compat/lang/isUndefined'),\n  isArray: require('lodash-compat/lang/isArray'),\n  isObject: require('lodash-compat/lang/isObject'),\n  isEmpty: require('lodash-compat/lang/isEmpty'),\n  map: require('lodash-compat/collection/map'),\n  indexOf: require('lodash-compat/array/indexOf'),\n  cloneDeep: require('lodash-compat/lang/cloneDeep'),\n  keys: require('lodash-compat/object/keys'),\n  forEach: require('lodash-compat/collection/forEach')\n};\n\nvar optionHtml = module.exports.optionHtml = function  (label, value) {\n  return '<tr><td class=\"optionName\">' + label + ':</td><td>' + value + '</td></tr>';\n};\n\nmodule.exports.typeFromJsonSchema = function (type, format) {\n  var str;\n\n  if (type === 'integer' && format === 'int32') {\n    str = 'integer';\n  } else if (type === 'integer' && format === 'int64') {\n    str = 'long';\n  } else if (type === 'integer' && typeof format === 'undefined') {\n    str = 'long';\n  } else if (type === 'string' && format === 'date-time') {\n    str = 'date-time';\n  } else if (type === 'string' && format === 'date') {\n    str = 'date';\n  } else if (type === 'number' && format === 'float') {\n    str = 'float';\n  } else if (type === 'number' && format === 'double') {\n    str = 'double';\n  } else if (type === 'number' && typeof format === 'undefined') {\n    str = 'double';\n  } else if (type === 'boolean') {\n    str = 'boolean';\n  } else if (type === 'string') {\n    str = 'string';\n  }\n\n  return str;\n};\n\nvar getStringSignature = module.exports.getStringSignature = function (obj, baseComponent) {\n  var str = '';\n\n  if (typeof obj.$ref !== 'undefined') {\n    str += Helpers.simpleRef(obj.$ref);\n  } else if (typeof obj.type === 'undefined') {\n    str += 'object';\n  } else if (obj.type === 'array') {\n    if (baseComponent) {\n      str += getStringSignature((obj.items || obj.$ref || {}));\n    } else {\n      str += 'Array[';\n      str += getStringSignature((obj.items || obj.$ref || {}));\n      str += ']';\n    }\n  } else if (obj.type === 'integer' && obj.format === 'int32') {\n    str += 'integer';\n  } else if (obj.type === 'integer' && obj.format === 'int64') {\n    str += 'long';\n  } else if (obj.type === 'integer' && typeof obj.format === 'undefined') {\n    str += 'long';\n  } else if (obj.type === 'string' && obj.format === 'date-time') {\n    str += 'date-time';\n  } else if (obj.type === 'string' && obj.format === 'date') {\n    str += 'date';\n  } else if (obj.type === 'string' && typeof obj.format === 'undefined') {\n    str += 'string';\n  } else if (obj.type === 'number' && obj.format === 'float') {\n    str += 'float';\n  } else if (obj.type === 'number' && obj.format === 'double') {\n    str += 'double';\n  } else if (obj.type === 'number' && typeof obj.format === 'undefined') {\n    str += 'double';\n  } else if (obj.type === 'boolean') {\n    str += 'boolean';\n  } else if (obj.$ref) {\n    str += Helpers.simpleRef(obj.$ref);\n  } else {\n    str += obj.type;\n  }\n\n  return str;\n};\n\nvar schemaToJSON = module.exports.schemaToJSON = function (schema, models, modelsToIgnore, modelPropertyMacro) {\n  // Resolve the schema (Handle nested schemas)\n  schema = Helpers.resolveSchema(schema);\n\n  if(typeof modelPropertyMacro !== 'function') {\n    modelPropertyMacro = function(prop){\n      return (prop || {}).default;\n    };\n  }\n\n  modelsToIgnore= modelsToIgnore || {};\n\n  var type = schema.type || 'object';\n  var format = schema.format;\n  var model;\n  var output;\n\n  if (!_.isUndefined(schema.example)) {\n    output = schema.example;\n  } else if (_.isUndefined(schema.items) && _.isArray(schema.enum)) {\n    output = schema.enum[0];\n  }\n\n  if (_.isUndefined(output)) {\n    if (schema.$ref) {\n      model = models[Helpers.simpleRef(schema.$ref)];\n\n      if (!_.isUndefined(model)) {\n        if (_.isUndefined(modelsToIgnore[model.name])) {\n          modelsToIgnore[model.name] = model;\n          output = schemaToJSON(model.definition, models, modelsToIgnore, modelPropertyMacro);\n          delete modelsToIgnore[model.name];\n        } else {\n          if (model.type === 'array') {\n            output = [];\n          } else {\n            output = {};\n          }\n        }\n      }\n    } else if (!_.isUndefined(schema.default)) {\n      output = schema.default;\n    } else if (type === 'string') {\n      if (format === 'date-time') {\n        output = new Date().toISOString();\n      } else if (format === 'date') {\n        output = new Date().toISOString().split('T')[0];\n      } else {\n        output = 'string';\n      }\n    } else if (type === 'integer') {\n      output = 0;\n    } else if (type === 'number') {\n      output = 0.0;\n    } else if (type === 'boolean') {\n      output = true;\n    } else if (type === 'object') {\n      output = {};\n\n      _.forEach(schema.properties, function (property, name) {\n        var cProperty = _.cloneDeep(property);\n\n        // Allow macro to set the default value\n        cProperty.default = modelPropertyMacro(property);\n\n        output[name] = schemaToJSON(cProperty, models, modelsToIgnore, modelPropertyMacro);\n      });\n    } else if (type === 'array') {\n      output = [];\n\n      if (_.isArray(schema.items)) {\n        _.forEach(schema.items, function (item) {\n          output.push(schemaToJSON(item, models, modelsToIgnore, modelPropertyMacro));\n        });\n      } else if (_.isPlainObject(schema.items)) {\n        output.push(schemaToJSON(schema.items, models, modelsToIgnore, modelPropertyMacro));\n      } else if (_.isUndefined(schema.items)) {\n        output.push({});\n      } else {\n        Helpers.log('Array type\\'s \\'items\\' property is not an array or an object, cannot process');\n      }\n    }\n  }\n\n  return output;\n};\n\nmodule.exports.schemaToHTML =function (name, schema, models, modelPropertyMacro) {\n  var strongOpen = '<span class=\"strong\">';\n  var strongClose = '</span>';\n\n  // Allow for ignoring the 'name' argument.... shifting the rest\n  if(_.isObject(arguments[0])) {\n    name = void 0;\n    schema = arguments[0];\n    models = arguments[1];\n    modelPropertyMacro = arguments[2];\n  }\n\n  models = models || {};\n\n  // Resolve the schema (Handle nested schemas)\n  schema = Helpers.resolveSchema(schema);\n\n  // Return for empty object\n  if(_.isEmpty(schema)) {\n    return strongOpen + 'Empty' + strongClose;\n  }\n\n  // Dereference $ref from 'models'\n  if(typeof schema.$ref === 'string') {\n    name = Helpers.simpleRef(schema.$ref);\n    schema = models[name];\n    if(typeof schema === 'undefined')\n    {\n      return strongOpen + name + ' is not defined!' + strongClose;\n    }\n  }\n\n  if(typeof name !== 'string') {\n    name = schema.title || 'Inline Model';\n  }\n\n  // If we are a Model object... adjust accordingly\n  if(schema.definition) {\n    schema = schema.definition;\n  }\n\n  if(typeof modelPropertyMacro !== 'function') {\n    modelPropertyMacro = function(prop){\n      return (prop || {}).default;\n    };\n  }\n\n  var references = {};\n  var seenModels = [];\n  var inlineModels = 0;\n\n\n\n  // Generate current HTML\n  var html = processModel(schema, name);\n\n  // Generate references HTML\n  while (_.keys(references).length > 0) {\n    /* jshint ignore:start */\n    _.forEach(references, function (schema, name) {\n      var seenModel = _.indexOf(seenModels, name) > -1;\n\n      delete references[name];\n\n      if (!seenModel) {\n        seenModels.push(name);\n\n        html += '<br />' + processModel(schema, name);\n      }\n    });\n    /* jshint ignore:end */\n  }\n\n  return html;\n\n  /////////////////////////////////\n\n  function addReference(schema, name, skipRef) {\n    var modelName = name;\n    var model;\n\n    if (schema.$ref) {\n      modelName = schema.title || Helpers.simpleRef(schema.$ref);\n      model = models[modelName];\n    } else if (_.isUndefined(name)) {\n      modelName = schema.title || 'Inline Model ' + (++inlineModels);\n      model = {definition: schema};\n    }\n\n    if (skipRef !== true) {\n      references[modelName] = _.isUndefined(model) ? {} : model.definition;\n    }\n\n    return modelName;\n  }\n\n  function primitiveToHTML(schema) {\n    var html = '<span class=\"propType\">';\n    var type = schema.type || 'object';\n\n    if (schema.$ref) {\n      html += addReference(schema, Helpers.simpleRef(schema.$ref));\n    } else if (type === 'object') {\n      if (!_.isUndefined(schema.properties)) {\n        html += addReference(schema);\n      } else {\n        html += 'object';\n      }\n    } else if (type === 'array') {\n      html += 'Array[';\n\n      if (_.isArray(schema.items)) {\n        html += _.map(schema.items, addReference).join(',');\n      } else if (_.isPlainObject(schema.items)) {\n        if (_.isUndefined(schema.items.$ref)) {\n          if (!_.isUndefined(schema.items.type) && _.indexOf(['array', 'object'], schema.items.type) === -1) {\n            html += schema.items.type;\n          } else {\n            html += addReference(schema.items);\n          }\n        } else {\n          html += addReference(schema.items, Helpers.simpleRef(schema.items.$ref));\n        }\n      } else {\n        Helpers.log('Array type\\'s \\'items\\' schema is not an array or an object, cannot process');\n        html += 'object';\n      }\n\n      html += ']';\n    } else {\n      html += schema.type;\n    }\n\n    html += '</span>';\n\n    return html;\n  }\n\n  function primitiveToOptionsHTML(schema, html) {\n    var options = '';\n    var type = schema.type || 'object';\n    var isArray = type === 'array';\n\n    if (isArray) {\n      if (_.isPlainObject(schema.items) && !_.isUndefined(schema.items.type)) {\n        type = schema.items.type;\n      } else {\n        type = 'object';\n      }\n    }\n\n    if (!_.isUndefined(schema.default)) {\n      options += optionHtml('Default', schema.default);\n    }\n\n    switch (type) {\n    case 'string':\n      if (schema.minLength) {\n        options += optionHtml('Min. Length', schema.minLength);\n      }\n\n      if (schema.maxLength) {\n        options += optionHtml('Max. Length', schema.maxLength);\n      }\n\n      if (schema.pattern) {\n        options += optionHtml('Reg. Exp.', schema.pattern);\n      }\n      break;\n    case 'integer':\n    case 'number':\n      if (schema.minimum) {\n        options += optionHtml('Min. Value', schema.minimum);\n      }\n\n      if (schema.exclusiveMinimum) {\n        options += optionHtml('Exclusive Min.', 'true');\n      }\n\n      if (schema.maximum) {\n        options += optionHtml('Max. Value', schema.maximum);\n      }\n\n      if (schema.exclusiveMaximum) {\n        options += optionHtml('Exclusive Max.', 'true');\n      }\n\n      if (schema.multipleOf) {\n        options += optionHtml('Multiple Of', schema.multipleOf);\n      }\n\n      break;\n    }\n\n    if (isArray) {\n      if (schema.minItems) {\n        options += optionHtml('Min. Items', schema.minItems);\n      }\n\n      if (schema.maxItems) {\n        options += optionHtml('Max. Items', schema.maxItems);\n      }\n\n      if (schema.uniqueItems) {\n        options += optionHtml('Unique Items', 'true');\n      }\n\n      if (schema.collectionFormat) {\n        options += optionHtml('Coll. Format', schema.collectionFormat);\n      }\n    }\n\n    if (_.isUndefined(schema.items)) {\n      if (_.isArray(schema.enum)) {\n        var enumString;\n\n        if (type === 'number' || type === 'integer') {\n          enumString = schema.enum.join(', ');\n        } else {\n          enumString = '\"' + schema.enum.join('\", \"') + '\"';\n        }\n\n        options += optionHtml('Enum', enumString);\n      }\n    }\n\n    if (options.length > 0) {\n      html = '<span class=\"propWrap\">' + html + '<table class=\"optionsWrapper\"><tr><th colspan=\"2\">' + type + '</th></tr>' + options + '</table></span>';\n    }\n\n    return html;\n  }\n\n  function processModel(schema, name) {\n    var type = schema.type || 'object';\n    var isArray = schema.type === 'array';\n    var html = strongOpen + name + ' ' + (isArray ? '[' : '{') + strongClose;\n\n    if (name) {\n      seenModels.push(name);\n    }\n\n    if (isArray) {\n      if (_.isArray(schema.items)) {\n        html += '<div>' + _.map(schema.items, function (item) {\n          var type = item.type || 'object';\n\n          if (_.isUndefined(item.$ref)) {\n            if (_.indexOf(['array', 'object'], type) > -1) {\n              if (type === 'object' && _.isUndefined(item.properties)) {\n                return 'object';\n              } else {\n                return addReference(item);\n              }\n            } else {\n              return primitiveToOptionsHTML(item, type);\n            }\n          } else {\n            return addReference(item, Helpers.simpleRef(item.$ref));\n          }\n        }).join(',</div><div>');\n      } else if (_.isPlainObject(schema.items)) {\n        if (_.isUndefined(schema.items.$ref)) {\n          if (_.indexOf(['array', 'object'], schema.items.type || 'object') > -1) {\n            if ((_.isUndefined(schema.items.type) || schema.items.type === 'object') && _.isUndefined(schema.items.properties)) {\n              html += '<div>object</div>';\n            } else {\n              html += '<div>' + addReference(schema.items) + '</div>';\n            }\n          } else {\n            html += '<div>' + primitiveToOptionsHTML(schema.items, schema.items.type) + '</div>';\n          }\n        } else {\n          html += '<div>' + addReference(schema.items, Helpers.simpleRef(schema.items.$ref)) + '</div>';\n        }\n      } else {\n        Helpers.log('Array type\\'s \\'items\\' property is not an array or an object, cannot process');\n        html += '<div>object</div>';\n      }\n    } else {\n      if (schema.$ref) {\n        html += '<div>' + addReference(schema, name) + '</div>';\n      } else if (type === 'object') {\n        if (_.isPlainObject(schema.properties)) {\n          var contents = _.map(schema.properties, function (property, name) {\n            var propertyIsRequired = (_.indexOf(schema.required, name) >= 0);\n            var cProperty = _.cloneDeep(property);\n\n            var requiredClass = propertyIsRequired ? 'required' : '';\n            var html = '<span class=\"propName ' + requiredClass + '\">' + name + '</span> (';\n            var model;\n            var propDescription;\n\n            // Allow macro to set the default value\n            cProperty.default = modelPropertyMacro(cProperty);\n\n            // Resolve the schema (Handle nested schemas)\n            cProperty = Helpers.resolveSchema(cProperty);\n\n            propDescription = property.description || cProperty.description;\n\n            // We need to handle property references to primitives (Issue 339)\n            if (!_.isUndefined(cProperty.$ref)) {\n              model = models[Helpers.simpleRef(cProperty.$ref)];\n\n              if (!_.isUndefined(model) && _.indexOf([undefined, 'array', 'object'], model.definition.type) === -1) {\n                // Use referenced schema\n                cProperty = Helpers.resolveSchema(model.definition);\n              }\n            }\n\n            html += primitiveToHTML(cProperty);\n\n            if(!propertyIsRequired) {\n              html += ', <span class=\"propOptKey\">optional</span>';\n            }\n\n            if(property.readOnly) {\n                html += ', <span class=\"propReadOnly\">read only</span>';\n            }\n\n            html += ')';\n\n            if (!_.isUndefined(propDescription)) {\n              html += ': ' + '<span class=\"propDesc\">' + propDescription + '</span>';\n            }\n\n            if (cProperty.enum) {\n              html += ' = <span class=\"propVals\">[\\'' + cProperty.enum.join('\\', \\'') + '\\']</span>';\n            }\n\n            return '<div' + (property.readOnly ? ' class=\"readOnly\"' : '') + '>' + primitiveToOptionsHTML(cProperty, html);\n          }).join(',</div>');\n\n          if (contents) {\n            html += contents + '</div>';\n          }\n        }\n      } else {\n        html += '<div>' + primitiveToOptionsHTML(schema, type) + '</div>';\n      }\n    }\n\n    return html + strongOpen + (isArray ? ']' : '}') + strongClose;\n  }\n};\n},{\"./helpers\":4,\"lodash-compat/array/indexOf\":49,\"lodash-compat/collection/forEach\":54,\"lodash-compat/collection/map\":56,\"lodash-compat/lang/cloneDeep\":138,\"lodash-compat/lang/isArray\":140,\"lodash-compat/lang/isEmpty\":141,\"lodash-compat/lang/isObject\":144,\"lodash-compat/lang/isPlainObject\":145,\"lodash-compat/lang/isUndefined\":148,\"lodash-compat/object/keys\":149}],8:[function(require,module,exports){\n'use strict';\n\nvar SwaggerHttp = require('./http');\nvar _ = {\n  isObject: require('lodash-compat/lang/isObject')\n};\n\nvar SwaggerSpecConverter = module.exports = function () {\n  this.errors = [];\n  this.warnings = [];\n  this.modelMap = {};\n};\n\nSwaggerSpecConverter.prototype.setDocumentationLocation = function (location) {\n  this.docLocation = location;\n};\n\n/**\n * converts a resource listing OR api declaration\n **/\nSwaggerSpecConverter.prototype.convert = function (obj, clientAuthorizations, opts, callback) {\n  // not a valid spec\n  if(!obj || !Array.isArray(obj.apis)) {\n    return this.finish(callback, null);\n  }\n  this.clientAuthorizations = clientAuthorizations;\n\n  // create a new swagger object to return\n  var swagger = { swagger: '2.0' };\n\n  swagger.originalVersion = obj.swaggerVersion;\n\n  // add the info\n  this.apiInfo(obj, swagger);\n\n  // add security definitions\n  this.securityDefinitions(obj, swagger);\n\n  // take basePath into account\n  if (obj.basePath) {\n    this.setDocumentationLocation(obj.basePath);\n  }\n\n  // see if this is a single-file swagger definition\n  var isSingleFileSwagger = false;\n  var i;\n  for(i = 0; i < obj.apis.length; i++) {\n    var api = obj.apis[i];\n    if(Array.isArray(api.operations)) {\n      isSingleFileSwagger = true;\n    }\n  }\n  if(isSingleFileSwagger) {\n    this.declaration(obj, swagger);\n    this.finish(callback, swagger);\n  }\n  else {\n    this.resourceListing(obj, swagger, opts, callback);\n  }\n};\n\nSwaggerSpecConverter.prototype.declaration = function(obj, swagger) {\n  var name, i, p, pos;\n  if(!obj.apis) {\n    return;\n  }\n\n  if (obj.basePath.indexOf('http://') === 0) {\n    p = obj.basePath.substring('http://'.length);\n    pos = p.indexOf('/');\n    if (pos > 0) {\n      swagger.host = p.substring(0, pos);\n      swagger.basePath = p.substring(pos);\n    }\n    else {\n      swagger.host = p;\n      swagger.basePath = '/';\n    }\n  } else if (obj.basePath.indexOf('https://') === 0) {\n    p = obj.basePath.substring('https://'.length);\n    pos = p.indexOf('/');\n    if (pos > 0) {\n      swagger.host = p.substring(0, pos);\n      swagger.basePath = p.substring(pos);\n    }\n    else {\n      swagger.host = p;\n      swagger.basePath = '/';\n    }\n  } else {\n    swagger.basePath = obj.basePath;\n  }\n\n  var resourceLevelAuth;\n  if(obj.authorizations) {\n    resourceLevelAuth = obj.authorizations;\n  }\n  if(obj.consumes) {\n    swagger.consumes = obj.consumes;\n  }\n  if(obj.produces) {\n    swagger.produces = obj.produces;\n  }\n\n  // build a mapping of id to name for 1.0 model resolutions\n  if(_.isObject(obj)) {\n    for(name in obj.models) {\n      var existingModel = obj.models[name];\n      var key = (existingModel.id || name);\n      this.modelMap[key] = name;\n    }\n  }\n\n  for(i = 0; i < obj.apis.length; i++) {\n    var api = obj.apis[i];\n    var path = api.path;\n    var operations = api.operations;\n    this.operations(path, obj.resourcePath, operations, resourceLevelAuth, swagger);\n  }\n\n  var models = obj.models || {};\n  this.models(models, swagger);\n};\n\nSwaggerSpecConverter.prototype.models = function(obj, swagger) {\n  if(!_.isObject(obj)) {\n    return;\n  }\n  var name;\n\n  swagger.definitions = swagger.definitions || {};\n  for(name in obj) {\n    var existingModel = obj[name];\n    var _required = [];\n    var schema = { properties: {}};\n    var propertyName;\n    for(propertyName in existingModel.properties) {\n      var existingProperty = existingModel.properties[propertyName];\n      var property = {};\n      this.dataType(existingProperty, property);\n      if(existingProperty.description) {\n        property.description = existingProperty.description;\n      }\n      if(existingProperty['enum']) {\n        property['enum'] = existingProperty['enum'];\n      }\n      if(typeof existingProperty.required === 'boolean' && existingProperty.required === true) {\n        _required.push(propertyName);\n      }\n      if(typeof existingProperty.required === 'string' && existingProperty.required === 'true') {\n        _required.push(propertyName);\n      }\n      schema.properties[propertyName] = property;\n    }\n    if(_required.length > 0) {\n      schema.required = _required;\n    } else {\n      schema.required = existingModel.required;\n    }\n    swagger.definitions[name] = schema;\n  }\n};\n\nSwaggerSpecConverter.prototype.extractTag = function(resourcePath) {\n  var pathString = resourcePath || 'default';\n  if(pathString.indexOf('http:') === 0 || pathString.indexOf('https:') === 0) {\n    pathString = pathString.split(['/']);\n    pathString = pathString[pathString.length -1].substring();\n  }\n  if(pathString.endsWith('.json')) {\n    pathString = pathString.substring(0, pathString.length - '.json'.length);\n  }\n  return pathString.replace('/','');\n};\n\nSwaggerSpecConverter.prototype.operations = function(path, resourcePath, obj, resourceLevelAuth, swagger) {\n  if(!Array.isArray(obj)) {\n    return;\n  }\n  var i;\n\n  if(!swagger.paths) {\n    swagger.paths = {};\n  }\n\n  var pathObj = swagger.paths[path] || {};\n  var tag = this.extractTag(resourcePath);\n  swagger.tags = swagger.tags || [];\n  var matched = false;\n  for(i = 0; i < swagger.tags.length; i++) {\n    var tagObject = swagger.tags[i];\n    if(tagObject.name === tag) {\n      matched = true;\n    }\n  }\n  if(!matched) {\n    swagger.tags.push({name: tag});\n  }\n\n  for(i = 0; i < obj.length; i++) {\n    var existingOperation = obj[i];\n    var method = (existingOperation.method || existingOperation.httpMethod).toLowerCase();\n    var operation = {tags: [tag]};\n    var existingAuthorizations = existingOperation.authorizations;\n\n    if(existingAuthorizations && Object.keys(existingAuthorizations).length === 0) {\n      existingAuthorizations = resourceLevelAuth;\n    }\n\n    if(typeof existingAuthorizations !== 'undefined') {\n      var scopesObject;\n      for(var key in existingAuthorizations) {\n        operation.security = operation.security || [];\n        var scopes = existingAuthorizations[key];\n        if(scopes) {\n          var securityScopes = [];\n          for(var j in scopes) {\n            securityScopes.push(scopes[j].scope);\n          }\n          scopesObject = {};\n          scopesObject[key] = securityScopes;\n          operation.security.push(scopesObject);\n        }\n        else {\n          scopesObject = {};\n          scopesObject[key] = [];\n          operation.security.push(scopesObject);\n        }\n      }\n    }\n\n    if(existingOperation.consumes) {\n      operation.consumes = existingOperation.consumes;\n    }\n    else if(swagger.consumes) {\n      operation.consumes = swagger.consumes;\n    }\n    if(existingOperation.produces) {\n      operation.produces = existingOperation.produces;\n    }\n    else if(swagger.produces) {\n      operation.produces = swagger.produces;\n    }\n    if(existingOperation.summary) {\n      operation.summary = existingOperation.summary;\n    }\n    if(existingOperation.notes) {\n      operation.description = existingOperation.notes;\n    }\n    if(existingOperation.nickname) {\n      operation.operationId = existingOperation.nickname;\n    }\n    if(existingOperation.deprecated) {\n      operation.deprecated = existingOperation.deprecated;\n    }\n\n    this.authorizations(existingAuthorizations, swagger);\n    this.parameters(operation, existingOperation.parameters, swagger);\n    this.responseMessages(operation, existingOperation, swagger);\n\n    pathObj[method] = operation;\n  }\n\n  swagger.paths[path] = pathObj;\n};\n\nSwaggerSpecConverter.prototype.responseMessages = function(operation, existingOperation) {\n  if(!_.isObject(existingOperation)) {\n    return;\n  }\n  // build default response from the operation (1.x)\n  var defaultResponse = {};\n  this.dataType(existingOperation, defaultResponse);\n  // TODO: look into the real problem of rendering responses in swagger-ui\n  // ....should reponseType have an implicit schema?\n  if(!defaultResponse.schema && defaultResponse.type) {\n    defaultResponse = {schema: defaultResponse};\n  }\n\n  operation.responses = operation.responses || {};\n\n  // grab from responseMessages (1.2)\n  var has200 = false;\n  if(Array.isArray(existingOperation.responseMessages)) {\n    var i;\n    var existingResponses = existingOperation.responseMessages;\n    for(i = 0; i < existingResponses.length; i++) {\n      var existingResponse = existingResponses[i];\n      var response = { description: existingResponse.message };\n      if(existingResponse.code === 200) {\n        has200 = true;\n      }\n      // Convert responseModel -> schema{$ref: responseModel}\n      if(existingResponse.responseModel) {\n        response.schema = {'$ref': '#/definitions/' + existingResponse.responseModel};\n      }\n      operation.responses['' + existingResponse.code] = response;\n    }\n  }\n\n  if(has200) {\n    operation.responses['default'] = defaultResponse;\n  }\n  else {\n    operation.responses['200'] = defaultResponse;\n  }\n};\n\nSwaggerSpecConverter.prototype.authorizations = function(obj) {\n  // TODO\n  if(!_.isObject(obj)) {\n    return;\n  }\n};\n\nSwaggerSpecConverter.prototype.parameters = function(operation, obj) {\n  if(!Array.isArray(obj)) {\n    return;\n  }\n  var i;\n  for(i = 0; i < obj.length; i++) {\n    var existingParameter = obj[i];\n    var parameter = {};\n    parameter.name = existingParameter.name;\n    parameter.description = existingParameter.description;\n    parameter.required = existingParameter.required;\n    parameter.in = existingParameter.paramType;\n\n    // per #168\n    if(parameter.in === 'body') {\n      parameter.name = 'body';\n    }\n    if(parameter.in === 'form') {\n      parameter.in = 'formData';\n    }\n\n    if(existingParameter.enum) {\n      parameter.enum = existingParameter.enum;\n    }\n\n    if(existingParameter.allowMultiple === true || existingParameter.allowMultiple === 'true') {\n      var innerType = {};\n      this.dataType(existingParameter, innerType);\n      parameter.type = 'array';\n      parameter.items = innerType;\n\n      if(existingParameter.allowableValues) {\n        var av = existingParameter.allowableValues;\n        if(av.valueType === 'LIST') {\n          parameter['enum'] = av.values;\n        }\n      }\n    }\n    else {\n      this.dataType(existingParameter, parameter);\n    }\n    if(typeof existingParameter.defaultValue !== 'undefined') {\n      parameter.default = existingParameter.defaultValue;\n    }\n\n    operation.parameters = operation.parameters || [];\n    operation.parameters.push(parameter);\n  }\n};\n\nSwaggerSpecConverter.prototype.dataType = function(source, target) {\n  if(!_.isObject(source)) {\n    return;\n  }\n\n  if(source.minimum) {\n    target.minimum = source.minimum;\n  }\n  if(source.maximum) {\n    target.maximum = source.maximum;\n  }\n  if (source.format) {\n    target.format = source.format;\n  }\n\n  // default can be 'false'\n  if(typeof source.defaultValue !== 'undefined') {\n    target.default = source.defaultValue;\n  }\n\n  var jsonSchemaType = this.toJsonSchema(source);\n  if(jsonSchemaType) {\n    target = target || {};\n    if(jsonSchemaType.type) {\n      target.type = jsonSchemaType.type;\n    }\n    if(jsonSchemaType.format) {\n      target.format = jsonSchemaType.format;\n    }\n    if(jsonSchemaType.$ref) {\n      target.schema = {$ref: jsonSchemaType.$ref};\n    }\n    if(jsonSchemaType.items) {\n      target.items = jsonSchemaType.items;\n    }\n  }\n};\n\nSwaggerSpecConverter.prototype.toJsonSchema = function(source) {\n  if(!source) {\n    return 'object';\n  }\n  var detectedType = (source.type || source.dataType || source.responseClass || '');\n  var lcType = detectedType.toLowerCase();\n  var format = (source.format || '').toLowerCase();\n\n  if(lcType.indexOf('list[') === 0) {\n    var innerType = detectedType.substring(5, detectedType.length - 1);\n    var jsonType = this.toJsonSchema({type: innerType});\n    return {type: 'array', items: jsonType};\n  } else if(lcType === 'int' || (lcType === 'integer' && format === 'int32')) {\n    {return {type: 'integer', format: 'int32'};}\n  } else if(lcType === 'long' || (lcType === 'integer' && format === 'int64')) {\n    {return {type: 'integer', format: 'int64'};}\n  } else if(lcType === 'integer') {\n    {return {type: 'integer', format: 'int64'};}\n  } else if(lcType === 'float' || (lcType === 'number' && format === 'float')) {\n    {return {type: 'number', format: 'float'};}\n  } else if(lcType === 'double' || (lcType === 'number' && format === 'double')) {\n    {return {type: 'number', format: 'double'};}\n  } else if((lcType === 'string' && format === 'date-time') || (lcType === 'date')) {\n    {return {type: 'string', format: 'date-time'};}\n  } else if(lcType === 'string') {\n    {return {type: 'string'};}\n  } else if(lcType === 'file') {\n    {return {type: 'file'};}\n  } else if(lcType === 'boolean') {\n    {return {type: 'boolean'};}\n  } else if(lcType === 'boolean') {\n    {return {type: 'boolean'};}\n  } else if(lcType === 'array' || lcType === 'list') {\n    if(source.items) {\n      var it = this.toJsonSchema(source.items);\n      return {type: 'array', items: it};\n    }\n    else {\n      return {type: 'array', items: {type: 'object'}};\n    }\n  } else if(source.$ref) {\n    return {$ref: this.modelMap[source.$ref] ? '#/definitions/' + this.modelMap[source.$ref] : source.$ref};\n  } else if(lcType === 'void' || lcType === '') {\n    {return {};}\n  } else if (this.modelMap[source.type]) {\n    // If this a model using `type` instead of `$ref`, that's fine.\n    return {$ref: '#/definitions/' + this.modelMap[source.type]};\n  } else {\n    // Unknown model type or 'object', pass it along.\n    return {type: source.type};\n  }\n};\n\nSwaggerSpecConverter.prototype.resourceListing = function(obj, swagger, opts, callback) {\n  var i;\n  var processedCount = 0;   // jshint ignore:line\n  var self = this;          // jshint ignore:line\n  var expectedCount = obj.apis.length;\n  var _swagger = swagger;   // jshint ignore:line\n  var _opts = {};\n\n  if(opts && opts.requestInterceptor){\n    _opts.requestInterceptor = opts.requestInterceptor;\n  }\n\n  if(opts && opts.responseInterceptor){\n    _opts.responseInterceptor = opts.responseInterceptor;\n  }\n\n  var swaggerRequestHeaders = 'application/json';\n\n  if(opts && opts.swaggerRequestHeaders) {\n    swaggerRequestHeaders = opts.swaggerRequestHeaders;\n  }\n\n  if(expectedCount === 0) {\n    this.finish(callback, swagger);\n  }\n\n  for(i = 0; i < expectedCount; i++) {\n    var api = obj.apis[i];\n    var path = api.path;\n    var absolutePath = this.getAbsolutePath(obj.swaggerVersion, this.docLocation, path);\n\n    if(api.description) {\n      swagger.tags = swagger.tags || [];\n      swagger.tags.push({\n        name : this.extractTag(api.path),\n        description : api.description || ''\n      });\n    }\n    var http = {\n      url: absolutePath,\n      headers: { accept: swaggerRequestHeaders },\n      on: {},\n      method: 'get',\n      timeout: opts.timeout\n    };\n    /* jshint ignore:start */\n    http.on.response = function(data) {\n      processedCount += 1;\n      var obj = data.obj;\n      if(obj) {\n        self.declaration(obj, _swagger);\n      }\n      if(processedCount === expectedCount) {\n        self.finish(callback, _swagger);\n      }\n    };\n    http.on.error = function(data) {\n      console.error(data);\n      processedCount += 1;\n      if(processedCount === expectedCount) {\n        self.finish(callback, _swagger);\n      }\n    };\n    /* jshint ignore:end */\n\n    if(this.clientAuthorizations && typeof this.clientAuthorizations.apply === 'function') {\n      this.clientAuthorizations.apply(http);\n    }\n\n    new SwaggerHttp().execute(http, _opts);\n  }\n};\n\nSwaggerSpecConverter.prototype.getAbsolutePath = function(version, docLocation, path)  {\n  if(version === '1.0') {\n    if(docLocation.endsWith('.json')) {\n      // get root path\n      var pos = docLocation.lastIndexOf('/');\n      if(pos > 0) {\n        docLocation = docLocation.substring(0, pos);\n      }\n    }\n  }\n\n  var location = docLocation;\n  if(path.indexOf('http:') === 0 || path.indexOf('https:') === 0) {\n    location = path;\n  }\n  else {\n    if(docLocation.endsWith('/')) {\n      location = docLocation.substring(0, docLocation.length - 1);\n    }\n    location += path;\n  }\n  location = location.replace('{format}', 'json');\n  return location;\n};\n\nSwaggerSpecConverter.prototype.securityDefinitions = function(obj, swagger) {\n  if(obj.authorizations) {\n    var name;\n    for(name in obj.authorizations) {\n      var isValid = false;\n      var securityDefinition = {\n        vendorExtensions: {}\n      };\n      var definition = obj.authorizations[name];\n      if(definition.type === 'apiKey') {\n        securityDefinition.type = 'apiKey';\n        securityDefinition.in = definition.passAs;\n        securityDefinition.name = definition.keyname || name;\n        isValid = true;\n      }\n      else if(definition.type === 'basicAuth') {\n        securityDefinition.type = 'basicAuth';\n        isValid = true;\n      }\n      else if(definition.type === 'oauth2') {\n        var existingScopes = definition.scopes || [];\n        var scopes = {};\n        var i;\n        for(i in existingScopes) {\n          var scope = existingScopes[i];\n          scopes[scope.scope] = scope.description;\n        }\n        securityDefinition.type = 'oauth2';\n        if(i > 0) {\n          securityDefinition.scopes = scopes;\n        }\n        if(definition.grantTypes) {\n          if(definition.grantTypes.implicit) {\n            var implicit = definition.grantTypes.implicit;\n            securityDefinition.flow = 'implicit';\n            securityDefinition.authorizationUrl = implicit.loginEndpoint;\n            isValid = true;\n          }\n          /* jshint ignore:start */\n          if(definition.grantTypes['authorization_code']) {\n            if(!securityDefinition.flow) {\n              // cannot set if flow is already defined\n              var authCode = definition.grantTypes['authorization_code'];\n              securityDefinition.flow = 'accessCode';\n              securityDefinition.authorizationUrl = authCode.tokenRequestEndpoint.url;\n              securityDefinition.tokenUrl = authCode.tokenEndpoint.url;\n              isValid = true;\n            }\n          }\n          /* jshint ignore:end */\n        }\n      }\n      if(isValid) {\n        swagger.securityDefinitions = swagger.securityDefinitions || {};\n        swagger.securityDefinitions[name] = securityDefinition;\n      }\n    }\n  }\n};\n\nSwaggerSpecConverter.prototype.apiInfo = function(obj, swagger) {\n  // info section\n  if(obj.info) {\n    var info = obj.info;\n    swagger.info = {};\n\n    if(info.contact) {\n      swagger.info.contact = {};\n      swagger.info.contact.email = info.contact;\n    }\n    if(info.description) {\n      swagger.info.description = info.description;\n    }\n    if(info.title) {\n      swagger.info.title = info.title;\n    }\n    if(info.termsOfServiceUrl) {\n      swagger.info.termsOfService = info.termsOfServiceUrl;\n    }\n    if(info.license || info.licenseUrl) {\n      swagger.license = {};\n      if(info.license) {\n        swagger.license.name = info.license;\n      }\n      if(info.licenseUrl) {\n        swagger.license.url = info.licenseUrl;\n      }\n    }\n  }\n  else {\n    this.warnings.push('missing info section');\n  }\n};\n\nSwaggerSpecConverter.prototype.finish = function (callback, obj) {\n  callback(obj);\n};\n\n},{\"./http\":5,\"lodash-compat/lang/isObject\":144}],9:[function(require,module,exports){\n'use strict';\n\nvar log = require('../helpers').log;\nvar _ = {\n  isPlainObject: require('lodash-compat/lang/isPlainObject'),\n  isString: require('lodash-compat/lang/isString'),\n};\n\nvar SchemaMarkup = require('../schema-markup.js');\nvar jsyaml = require('js-yaml');\n\nvar Model = module.exports = function (name, definition, models, modelPropertyMacro) {\n  this.definition = definition || {};\n  this.isArray = definition.type === 'array';\n  this.models = models || {};\n  this.name = name || definition.title || 'Inline Model';\n  this.modelPropertyMacro = modelPropertyMacro || function (property) {\n    return property.default;\n  };\n\n  return this;\n};\n\n// Note!  This function will be removed in 2.2.x!\nModel.prototype.createJSONSample = Model.prototype.getSampleValue = function (modelsToIgnore) {\n  modelsToIgnore = modelsToIgnore || {};\n\n  modelsToIgnore[this.name] = this;\n\n  // Response support\n  if (this.examples && _.isPlainObject(this.examples) && this.examples['application/json']) {\n    this.definition.example = this.examples['application/json'];\n\n    if (_.isString(this.definition.example)) {\n      this.definition.example = jsyaml.safeLoad(this.definition.example);\n    }\n  } else if (!this.definition.example) {\n    this.definition.example = this.examples;\n  }\n\n  return SchemaMarkup.schemaToJSON(this.definition, this.models, modelsToIgnore, this.modelPropertyMacro);\n};\n\nModel.prototype.getMockSignature = function () {\n  return SchemaMarkup.schemaToHTML(this.name, this.definition, this.models, this.modelPropertyMacro);\n};\n\n},{\"../helpers\":4,\"../schema-markup.js\":7,\"js-yaml\":19,\"lodash-compat/lang/isPlainObject\":145,\"lodash-compat/lang/isString\":146}],10:[function(require,module,exports){\n'use strict';\n\nvar _ = {\n  cloneDeep: require('lodash-compat/lang/cloneDeep'),\n  isUndefined: require('lodash-compat/lang/isUndefined'),\n  isEmpty: require('lodash-compat/lang/isEmpty'),\n  isObject: require('lodash-compat/lang/isObject')\n};\nvar helpers = require('../helpers');\nvar Model = require('./model');\nvar SwaggerHttp = require('../http');\nvar Q = require('q');\n\nvar Operation = module.exports = function (parent, scheme, operationId, httpMethod, path, args, definitions, models, clientAuthorizations) {\n  var errors = [];\n\n  parent = parent || {};\n  args = args || {};\n\n  if(parent && parent.options) {\n    this.client = parent.options.client || null;\n    this.requestInterceptor = parent.options.requestInterceptor || null;\n    this.responseInterceptor = parent.options.responseInterceptor || null;\n    this.requestAgent = parent.options.requestAgent;\n  }\n  this.authorizations = args.security;\n  this.basePath = parent.basePath || '/';\n  this.clientAuthorizations = clientAuthorizations;\n  this.consumes = args.consumes || parent.consumes || ['application/json'];\n  this.produces = args.produces || parent.produces || ['application/json'];\n  this.deprecated = args.deprecated;\n  this.description = args.description;\n  this.host = parent.host;\n  this.method = (httpMethod || errors.push('Operation ' + operationId + ' is missing method.'));\n  this.models = models || {};\n  this.nickname = (operationId || errors.push('Operations must have a nickname.'));\n  this.operation = args;\n  this.operations = {};\n  this.parameters = args !== null ? (args.parameters || []) : {};\n  this.parent = parent;\n  this.path = (path || errors.push('Operation ' + this.nickname + ' is missing path.'));\n  this.responses = (args.responses || {});\n  this.scheme = scheme || parent.scheme || 'http';\n  this.schemes = args.schemes || parent.schemes;\n  this.security = args.security || parent.security;\n  this.summary = args.summary || '';\n  this.timeout = parent.timeout;\n  this.type = null;\n  this.useJQuery = parent.useJQuery;\n  this.jqueryAjaxCache = parent.jqueryAjaxCache;\n  this.enableCookies = parent.enableCookies;\n\n  var key;\n\n  if(!this.host) {\n    if(typeof window !== 'undefined') {\n      this.host = window.location.host;\n    }\n    else {\n      this.host = 'localhost';\n    }\n  }\n  this.parameterMacro = parent.parameterMacro || function (operation, parameter) {\n    return parameter.default;\n  };\n\n  this.inlineModels = [];\n\n  if(this.basePath !== '/' && this.basePath.slice(-1) === '/') {\n    this.basePath = this.basePath.slice(0, -1);\n  }\n\n  if (typeof this.deprecated === 'string') {\n    switch(this.deprecated.toLowerCase()) {\n      case 'true': case 'yes': case '1': {\n        this.deprecated = true;\n        break;\n      }\n\n      case 'false': case 'no': case '0': case null: {\n        this.deprecated = false;\n        break;\n      }\n\n      default: this.deprecated = Boolean(this.deprecated);\n    }\n  }\n\n  var i, model;\n\n  if (definitions) {\n    // add to global models\n    for (key in definitions) {\n      model = new Model(key, definitions[key], this.models, parent.modelPropertyMacro);\n\n      if (model) {\n        this.models[key] = model;\n      }\n    }\n  }\n  else {\n    definitions = {};\n  }\n\n  for (i = 0; i < this.parameters.length; i++) {\n    var d, param = this.parameters[i];\n\n    // Allow macro to set the default value\n    param.default = this.parameterMacro(this, param);\n\n    if (param.type === 'array') {\n      param.isList = true;\n      param.allowMultiple = true;\n    }\n\n    var innerType = this.getType(param);\n\n    if (innerType && innerType.toString().toLowerCase() === 'boolean') {\n      param.allowableValues = {};\n      param.isList = true;\n      param['enum'] = [true, false]; // use actual primitives\n    }\n\n    for(key in param) {\n      helpers.extractExtensions(key, param);\n    }\n    if(typeof param['x-example'] !== 'undefined') {\n      d = param['x-example'];\n      param.default = d;\n    }\n    if(param['x-examples']) {\n      d = param['x-examples'].default;\n      if(typeof d !== 'undefined') {\n        param.default = d;\n      }\n    }\n\n    var enumValues = param['enum'] || (param.items && param.items['enum']);\n\n    if (typeof enumValues !== 'undefined') {\n      var id;\n\n      param.allowableValues = {};\n      param.allowableValues.values = [];\n      param.allowableValues.descriptiveValues = [];\n\n      for (id = 0; id < enumValues.length; id++) {\n        var value = enumValues[id];\n        var isDefault = (value === param.default || value+'' === param.default);\n\n        param.allowableValues.values.push(value);\n        // Always have string for descriptive values....\n        param.allowableValues.descriptiveValues.push({value : value+'', isDefault: isDefault});\n      }\n    }\n\n    if (param.type === 'array') {\n      innerType = [innerType];\n\n      if (typeof param.allowableValues === 'undefined') {\n        // can't show as a list if no values to select from\n        delete param.isList;\n        delete param.allowMultiple;\n      }\n    }\n\n    param.modelSignature = {type: innerType, definitions: this.models};\n    param.signature = this.getModelSignature(innerType, this.models).toString();\n    param.sampleJSON = this.getModelSampleJSON(innerType, this.models);\n    param.responseClassSignature = param.signature;\n  }\n\n  var keyname, defaultResponseCode, response, responses = this.responses;\n\n  if (responses['200']) {\n    response = responses['200'];\n    defaultResponseCode = '200';\n  } else if (responses['201']) {\n    response = responses['201'];\n    defaultResponseCode = '201';\n  } else if (responses['202']) {\n    response = responses['202'];\n    defaultResponseCode = '202';\n  } else if (responses['203']) {\n    response = responses['203'];\n    defaultResponseCode = '203';\n  } else if (responses['204']) {\n    response = responses['204'];\n    defaultResponseCode = '204';\n  } else if (responses['205']) {\n    response = responses['205'];\n    defaultResponseCode = '205';\n  } else if (responses['206']) {\n    response = responses['206'];\n    defaultResponseCode = '206';\n  } else if (responses['default']) {\n    response = responses['default'];\n    defaultResponseCode = 'default';\n  }\n\n  for(keyname in responses) {\n    helpers.extractExtensions(keyname, responses);\n    if(typeof keyname === 'string' && keyname.indexOf('x-') === -1) {\n      var responseObject = responses[keyname];\n      if(typeof responseObject === 'object' && typeof responseObject.headers === 'object') {\n        var headers = responseObject.headers;\n        for(var headerName in headers) {\n          var header = headers[headerName];\n          if(typeof header === 'object') {\n            for(var headerKey in header) {\n              helpers.extractExtensions(headerKey, header);\n            }\n          }\n        }\n      }\n    }\n  }\n\n  if (response) {\n    for(keyname in response) {\n      helpers.extractExtensions(keyname, response);\n    }\n  }\n\n  if (response && response.schema) {\n    var resolvedModel = this.resolveModel(response.schema, definitions);\n    var successResponse;\n\n    delete responses[defaultResponseCode];\n\n    if (resolvedModel) {\n      this.successResponse = {};\n      successResponse = this.successResponse[defaultResponseCode] = resolvedModel;\n    } else if (!response.schema.type || response.schema.type === 'object' || response.schema.type === 'array') {\n      // Inline model\n      this.successResponse = {};\n      successResponse = this.successResponse[defaultResponseCode] = new Model(undefined, response.schema || {}, this.models, parent.modelPropertyMacro);\n    } else {\n      // Primitive\n      this.successResponse = {};\n      successResponse = this.successResponse[defaultResponseCode] = response.schema;\n    }\n\n    if (successResponse) {\n      successResponse.vendorExtensions = response.vendorExtensions;\n      // Attach response properties\n      if (response.description) {\n        successResponse.description = response.description;\n      }\n\n      if (response.examples) {\n        successResponse.examples = response.examples;\n      }\n\n      if (response.headers) {\n        successResponse.headers = response.headers;\n      }\n    }\n\n    this.type = response;\n  }\n\n  if (errors.length > 0) {\n    if (this.resource && this.resource.api && this.resource.api.fail) {\n      this.resource.api.fail(errors);\n    }\n  }\n\n  return this;\n};\n\nOperation.prototype.isDefaultArrayItemValue = function(value, param) {\n  if (param.default && Array.isArray(param.default)) {\n    return param.default.indexOf(value) !== -1;\n  }\n  return value === param.default;\n};\n\nOperation.prototype.getType = function (param) {\n  var type = param.type;\n  var format = param.format;\n  var isArray = false;\n  var str;\n\n  if (type === 'integer' && format === 'int32') {\n    str = 'integer';\n  } else if (type === 'integer' && format === 'int64') {\n    str = 'long';\n  } else if (type === 'integer') {\n    str = 'integer';\n  } else if (type === 'string') {\n    if (format === 'date-time') {\n      str = 'date-time';\n    } else if (format === 'date') {\n      str = 'date';\n    } else {\n      str = 'string';\n    }\n  } else if (type === 'number' && format === 'float') {\n    str = 'float';\n  } else if (type === 'number' && format === 'double') {\n    str = 'double';\n  } else if (type === 'number') {\n    str = 'double';\n  } else if (type === 'boolean') {\n    str = 'boolean';\n  } else if (type === 'array') {\n    isArray = true;\n\n    if (param.items) {\n      str = this.getType(param.items);\n    }\n  } else if (type === 'file') {\n    str = 'file';\n  }\n\n  if (param.$ref) {\n    str = helpers.simpleRef(param.$ref);\n  }\n\n  var schema = param.schema;\n\n  if (schema) {\n    var ref = schema.$ref;\n\n    if (ref) {\n      ref = helpers.simpleRef(ref);\n\n      if (isArray) {\n        return [ ref ];\n      } else {\n        return ref;\n      }\n    } else {\n      // If inline schema, we add it our interal hash -> which gives us it's ID (int)\n      if(schema.type === 'object') {\n        return this.addInlineModel(schema);\n      }\n      return this.getType(schema);\n    }\n  }\n  if (isArray) {\n    return [ str ];\n  } else {\n    return str;\n  }\n};\n\n/**\n * adds an inline schema (model) to a hash, where we can ref it later\n * @param {object} schema a schema\n * @return {number} the ID of the schema being added, or null\n **/\nOperation.prototype.addInlineModel = function (schema) {\n  var len = this.inlineModels.length;\n  var model = this.resolveModel(schema, {});\n  if(model) {\n    this.inlineModels.push(model);\n    return 'Inline Model '+len; // return string ref of the inline model (used with #getInlineModel)\n  }\n  return null; // report errors?\n};\n\n/**\n * gets the internal ref to an inline model\n * @param {string} inline_str a string reference to an inline model\n * @return {Model} the model being referenced. Or null\n **/\nOperation.prototype.getInlineModel = function(inlineStr) {\n  if(/^Inline Model \\d+$/.test(inlineStr)) {\n    var id = parseInt(inlineStr.substr('Inline Model'.length).trim(),10); //\n    var model = this.inlineModels[id];\n    return model;\n  }\n  // I'm returning null here, should I rather throw an error?\n  return null;\n};\n\nOperation.prototype.resolveModel = function (schema, definitions) {\n  if (typeof schema.$ref !== 'undefined') {\n    var ref = schema.$ref;\n\n    if (ref.indexOf('#/definitions/') === 0) {\n      ref = ref.substring('#/definitions/'.length);\n    }\n\n    if (definitions[ref]) {\n      return new Model(ref, definitions[ref], this.models, this.parent.modelPropertyMacro);\n    }\n  // schema must at least be an object to get resolved to an inline Model\n  } else if (schema && typeof schema === 'object' &&\n            (schema.type === 'object' || _.isUndefined(schema.type))) {\n    return new Model(undefined, schema, this.models, this.parent.modelPropertyMacro);\n  }\n\n  return null;\n};\n\nOperation.prototype.help = function (dontPrint) {\n  var out = this.nickname + ': ' + this.summary + '\\n';\n\n  for (var i = 0; i < this.parameters.length; i++) {\n    var param = this.parameters[i];\n    var typeInfo = param.signature;\n\n    out += '\\n  * ' + param.name + ' (' + typeInfo + '): ' + param.description;\n  }\n\n  if (typeof dontPrint === 'undefined') {\n    helpers.log(out);\n  }\n\n  return out;\n};\n\nOperation.prototype.getModelSignature = function (type, definitions) {\n  var isPrimitive, listType;\n\n  if (type instanceof Array) {\n    listType = true;\n    type = type[0];\n  }\n\n  // Convert undefined to string of 'undefined'\n  if (typeof type === 'undefined') {\n    type = 'undefined';\n    isPrimitive = true;\n\n  } else if (definitions[type]){\n    // a model def exists?\n    type = definitions[type]; /* Model */\n    isPrimitive = false;\n\n  } else if (this.getInlineModel(type)) {\n    type = this.getInlineModel(type); /* Model */\n    isPrimitive = false;\n\n  } else {\n    // We default to primitive\n    isPrimitive = true;\n  }\n\n  if (isPrimitive) {\n    if (listType) {\n      return 'Array[' + type + ']';\n    } else {\n      return type.toString();\n    }\n  } else {\n    if (listType) {\n      return 'Array[' + type.getMockSignature() + ']';\n    } else {\n      return type.getMockSignature();\n    }\n  }\n};\n\nOperation.prototype.supportHeaderParams = function () {\n  return true;\n};\n\nOperation.prototype.supportedSubmitMethods = function () {\n  return this.parent.supportedSubmitMethods;\n};\n\nOperation.prototype.getHeaderParams = function (args) {\n  var headers = this.setContentTypes(args, {});\n  var headerParamsByLowerCase = {};\n\n  for (var i = 0; i < this.parameters.length; i++) {\n    var param = this.parameters[i];\n\n    if (param.in === 'header') {\n      headerParamsByLowerCase[param.name.toLowerCase()] = param;\n    }\n  }\n\n  for (var arg in args) {\n    var headerParam = headerParamsByLowerCase[arg.toLowerCase()];\n    if (typeof headerParam !== 'undefined') {\n      var value = args[arg];\n\n      if (Array.isArray(value)) {\n        value = value.toString();\n      }\n\n      headers[headerParam.name] = value;\n    }\n  }\n\n  return headers;\n};\n\nOperation.prototype.urlify = function (args, maskPasswords) {\n  var formParams = {};\n  var requestUrl = this.path.replace(/#.*/, ''); // remove URL fragment\n  var querystring = ''; // grab params from the args, build the querystring along the way\n\n  for (var i = 0; i < this.parameters.length; i++) {\n    var param = this.parameters[i];\n\n    if (typeof args[param.name] !== 'undefined') {\n      var isPassword;\n      if(param.type === 'string' && param.format === 'password' && maskPasswords) {\n        isPassword = true;\n      }\n\n      if (param.in === 'path') {\n        var reg = new RegExp('\\{' + param.name + '\\}', 'gi');\n        var value = args[param.name];\n\n        if (Array.isArray(value)) {\n          value = this.encodePathCollection(param.collectionFormat, param.name, value, isPassword);\n        } else {\n          if((typeof(param['x-escape']) === 'undefined') || (param['x-escape'] === true)) {\n            value = this.encodePathParam(value, isPassword);\n          }\n        }\n\n        requestUrl = requestUrl.replace(reg, value);\n      } else if (param.in === 'query' && typeof args[param.name] !== 'undefined') {\n        if (querystring === '' && requestUrl.indexOf('?') < 0) {\n          querystring += '?';\n        } else {\n          querystring += '&';\n        }\n\n        if (typeof param.collectionFormat !== 'undefined') {\n          var qp = args[param.name];\n\n          if (Array.isArray(qp)) {\n            querystring += this.encodeQueryCollection(param.collectionFormat, param.name, qp, isPassword);\n          } else {\n            querystring += this.encodeQueryKey(param.name) + '=' + this.encodeQueryParam(args[param.name], isPassword);\n          }\n        } else {\n          querystring += this.encodeQueryKey(param.name) + '=' + this.encodeQueryParam(args[param.name], isPassword);\n        }\n      } else if (param.in === 'formData') {\n        formParams[param.name] = args[param.name];\n      }\n    } else if(param.in === 'query' && typeof args[param.name] === 'undefined' && param.allowEmptyValue === true) {\n      if (querystring === '' && requestUrl.indexOf('?') < 0) {\n        querystring += '?';\n      } else {\n        querystring += '&';\n      }\n\n      if (typeof param.collectionFormat !== 'undefined' || param.type === 'array') {\n        var qp;\n        var collectionFormat = param.collectionFormat || 'multi';\n\n        if (Array.isArray(qp)) {\n          querystring += this.encodeQueryCollection(collectionFormat, param.name, qp, isPassword);\n        } else {\n          querystring += this.encodeQueryCollection(collectionFormat, param.name, [qp], isPassword);\n        }\n      } else {\n        querystring += this.encodeQueryKey(param.name) + '=' + this.encodeQueryParam('', isPassword);\n      }\n\n    }\n  }\n  var url = this.scheme + '://' + this.host;\n\n  if (this.basePath !== '/') {\n    url += this.basePath;\n  }\n  return url + requestUrl + querystring;\n};\n\nOperation.prototype.getMissingParams = function (args) {\n  var missingParams = []; // check required params, track the ones that are missing\n  var i;\n\n  for (i = 0; i < this.parameters.length; i++) {\n    var param = this.parameters[i];\n\n    if (param.required === true) {\n      if (typeof args[param.name] === 'undefined') {\n        missingParams = param.name;\n      }\n    }\n  }\n\n  return missingParams;\n};\n\nOperation.prototype.getBody = function (headers, args, opts) {\n  var formParams = {}, hasFormParams, param, body, key, value, hasBody = false;\n\n  // look at each param and put form params in an object\n  for (var i = 0; i < this.parameters.length; i++) {\n    param = this.parameters[i];\n    if (typeof args[param.name] !== 'undefined') {\n      var isPassword;\n      if(param.type === 'string' && param.format === 'password') {\n        isPassword = 'password';\n      }\n      if (param.in === 'body') {\n        body = args[param.name];\n      } else if (param.in === 'formData') {\n        formParams[param.name] = {\n          param: param,\n          value: args[param.name],\n          password: isPassword\n        };\n        hasFormParams = true;\n      }\n    }\n    else {\n      if(param.in === 'body') {\n        hasBody = true;\n      }\n    }\n  }\n\n  // if body is null and hasBody is true, AND a JSON body is requested, send empty {}\n  if(hasBody && typeof body === 'undefined') {\n    var contentType = headers['Content-Type'];\n    if(contentType && contentType.indexOf('application/json') === 0) {\n      body = '{}';\n    }\n  }\n\n  var isMultiPart = false;\n  if(headers['Content-Type'] && headers['Content-Type'].indexOf('multipart/form-data') >= 0) {\n    isMultiPart = true;\n  }\n\n  // handle form params\n  if (hasFormParams && !isMultiPart) {\n    var encoded = '';\n\n    for (key in formParams) {\n      param = formParams[key].param;\n      value = formParams[key].value;\n      var password;\n\n      if(opts && opts.maskPasswords) {\n        password = formParams[key].password;\n      }\n\n      if (typeof value !== 'undefined') {\n        if (Array.isArray(value)) {\n          if (encoded !== '') {\n            encoded += '&';\n          }\n          encoded += this.encodeQueryCollection(param.collectionFormat, key, value, password);\n        }\n        else {\n          if (encoded !== '') {\n            encoded += '&';\n          }\n\n          encoded += encodeURIComponent(key) + '=' + mask(encodeURIComponent(value), password);\n        }\n      }\n    }\n\n    body = encoded;\n  } else if (isMultiPart) {\n    var bodyParam;\n    if (typeof FormData === 'function') {\n      bodyParam = new FormData();\n\n      bodyParam.type = 'formData';\n\n      for (key in formParams) {\n        param = formParams[key].param;\n        value = args[key];\n\n        if (typeof value !== 'undefined') {\n          if({}.toString.apply(value) === '[object File]') {\n            bodyParam.append(key, value);\n          }\n          else if (value.type === 'file' && value.value) {\n            bodyParam.append(key, value.value);\n          } else {\n            if (Array.isArray(value)) {\n              if(param.collectionFormat === 'multi') {\n                bodyParam.delete(key);\n                for(var v in value) {\n                  bodyParam.append(key, value[v]);\n                }\n              }\n              else {\n                bodyParam.append(key, this.encodeQueryCollection(param.collectionFormat, key, value).split('=').slice(1).join('='));\n              }\n            }\n            else {\n              bodyParam.append(key, value);\n            }\n          }\n        }\n      }\n      body = bodyParam;\n    }\n    else {\n      bodyParam = {};\n      for (key in formParams) {\n        value = args[key];\n        if (Array.isArray(value)) {\n          var delimeter;\n          var format = param.collectionFormat || 'multi';\n          if(format === 'ssv') {\n            delimeter = ' ';\n          }\n          else if(format === 'pipes') {\n            delimeter = '|';\n          }\n          else if(format === 'tsv') {\n            delimeter = '\\t';\n          }\n          else if(format === 'multi') {\n            bodyParam[key] = value;\n            break;\n          }\n          else {\n            delimeter = ',';\n          }\n          var data;\n          value.forEach(function(v) {\n            if(data) {\n              data += delimeter;\n            }\n            else {\n              data = '';\n            }\n            data += v;\n          });\n          bodyParam[key] = data;\n        }\n        else {\n          bodyParam[key] = value;\n        }\n      }\n      body = bodyParam;\n    }\n    headers['Content-Type'] = 'multipart/form-data';\n  }\n\n  return body;\n};\n\n/**\n * gets sample response for a single operation\n **/\nOperation.prototype.getModelSampleJSON = function (type, models) {\n  var listType, sampleJson, innerType;\n  models = models || {};\n\n  listType = (type instanceof Array);\n  innerType = listType ? type[0] : type;\n\n  if(models[innerType]) {\n    sampleJson = models[innerType].createJSONSample();\n  } else if (this.getInlineModel(innerType)){\n    sampleJson = this.getInlineModel(innerType).createJSONSample(); // may return null, if type isn't correct\n  }\n\n\n  if (sampleJson) {\n    sampleJson = listType ? [sampleJson] : sampleJson;\n\n    if (typeof sampleJson === 'string') {\n      return sampleJson;\n    } else if (_.isObject(sampleJson)) {\n      var t = sampleJson;\n\n      if (sampleJson instanceof Array && sampleJson.length > 0) {\n        t = sampleJson[0];\n      }\n\n      if (t.nodeName && typeof t === 'Node') {\n        var xmlString = new XMLSerializer().serializeToString(t);\n\n        return this.formatXml(xmlString);\n      } else {\n        return JSON.stringify(sampleJson, null, 2);\n      }\n    } else {\n      return sampleJson;\n    }\n  }\n};\n\n/**\n * legacy binding\n **/\nOperation.prototype.do = function (args, opts, callback, error, parent) {\n  return this.execute(args, opts, callback, error, parent);\n};\n\n/**\n * executes an operation\n **/\nOperation.prototype.execute = function (arg1, arg2, arg3, arg4, parent) {\n  var args = arg1 || {};\n  var opts = {}, success, error, deferred, timeout;\n\n  if (_.isObject(arg2)) {\n    opts = arg2;\n    success = arg3;\n    error = arg4;\n  }\n\n  timeout = typeof opts.timeout !== 'undefined' ? opts.timeout : this.timeout;\n\n  if(this.client) {\n    opts.client = this.client;\n  }\n\n  if(this.requestAgent) {\n    opts.requestAgent = this.requestAgent;\n  }\n\n  // add the request interceptor from parent, if none sent from client\n  if(!opts.requestInterceptor && this.requestInterceptor ) {\n    opts.requestInterceptor = this.requestInterceptor ;\n  }\n\n  if(!opts.responseInterceptor && this.responseInterceptor) {\n    opts.responseInterceptor = this.responseInterceptor;\n  }\n\n  if (typeof arg2 === 'function') {\n    success = arg2;\n    error = arg3;\n  }\n\n  if (this.parent.usePromise) {\n    deferred = Q.defer();\n  } else {\n    success = (success || this.parent.defaultSuccessCallback || helpers.log);\n    error = (error || this.parent.defaultErrorCallback || helpers.log);\n  }\n\n  if (typeof opts.useJQuery === 'undefined') {\n    opts.useJQuery = this.useJQuery;\n  }\n\n  if (typeof opts.jqueryAjaxCache === 'undefined') {\n    opts.jqueryAjaxCache = this.jqueryAjaxCache;\n  }\n\n  if (typeof opts.enableCookies === 'undefined') {\n    opts.enableCookies = this.enableCookies;\n  }\n\n  var missingParams = this.getMissingParams(args);\n\n  if (missingParams.length > 0) {\n    var message = 'missing required params: ' + missingParams;\n\n    helpers.fail(message);\n\n    if (this.parent.usePromise) {\n      deferred.reject(message);\n      return deferred.promise;\n    } else {\n      error(message, parent);\n      return {};\n    }\n  }\n\n  var allHeaders = this.getHeaderParams(args);\n  var contentTypeHeaders = this.setContentTypes(args, opts);\n  var headers = {}, attrname;\n\n  for (attrname in allHeaders) { headers[attrname] = allHeaders[attrname]; }\n  for (attrname in contentTypeHeaders) { headers[attrname] = contentTypeHeaders[attrname]; }\n\n  var body = this.getBody(contentTypeHeaders, args, opts);\n  var url = this.urlify(args, opts.maskPasswords);\n\n  if(url.indexOf('.{format}') > 0) {\n    if(headers) {\n      var format = headers.Accept || headers.accept;\n      if(format && format.indexOf('json') > 0) {\n        url = url.replace('.{format}', '.json');\n      }\n      else if(format && format.indexOf('xml') > 0) {\n        url = url.replace('.{format}', '.xml');\n      }\n    }\n  }\n\n  var obj = {\n    url: url,\n    method: this.method.toUpperCase(),\n    body: body,\n    enableCookies: opts.enableCookies,\n    useJQuery: opts.useJQuery,\n    jqueryAjaxCache: opts.jqueryAjaxCache,\n    deferred: deferred,\n    headers: headers,\n    clientAuthorizations: opts.clientAuthorizations,\n    operation: this,\n    connectionAgent: this.connectionAgent,\n    on: {\n      response: function (response) {\n        if (deferred) {\n          deferred.resolve(response);\n          return deferred.promise;\n        } else {\n          return success(response, parent);\n        }\n      },\n      error: function (response) {\n        if (deferred) {\n          deferred.reject(response);\n          return deferred.promise;\n        } else {\n          return error(response, parent);\n        }\n      }\n    }\n  };\n\n  if (timeout) {\n    obj.timeout = timeout;\n  }\n\n  this.clientAuthorizations.apply(obj, this.operation.security);\n  if (opts.mock === true) {\n    if(opts.requestInterceptor) {\n      opts.requestInterceptor.apply(obj);\n    }\n    return obj;\n  } else {\n    return new SwaggerHttp().execute(obj, opts);\n  }\n};\n\nfunction itemByPriority(col, itemPriority) {\n\n  // No priorities? return first...\n  if(_.isEmpty(itemPriority)) {\n    return col[0];\n  }\n\n  for (var i = 0, len = itemPriority.length; i < len; i++) {\n    if(col.indexOf(itemPriority[i]) > -1) {\n      return itemPriority[i];\n    }\n  }\n\n  // Otherwise return first\n  return col[0];\n}\n\nOperation.prototype.setContentTypes = function (args, opts) {\n  // default type\n  var allDefinedParams = this.parameters;\n  var body;\n  var consumes = args.parameterContentType || itemByPriority(this.consumes, ['application/json', 'application/yaml']);\n  var accepts = opts.responseContentType || itemByPriority(this.produces, ['application/json', 'application/yaml']);\n  var definedFileParams = [];\n  var definedFormParams = [];\n  var headers = {};\n  var i;\n\n  // get params from the operation and set them in definedFileParams, definedFormParams, headers\n  for (i = 0; i < allDefinedParams.length; i++) {\n    var param = allDefinedParams[i];\n\n    if (param.in === 'formData') {\n      if (param.type === 'file') {\n        definedFileParams.push(param);\n      } else {\n        definedFormParams.push(param);\n      }\n    } else if (param.in === 'header' && opts) {\n      var key = param.name;\n      var headerValue = opts[param.name];\n\n      if (typeof opts[param.name] !== 'undefined') {\n        headers[key] = headerValue;\n      }\n    } else if (param.in === 'body' && typeof args[param.name] !== 'undefined') {\n      body = args[param.name];\n    }\n  }\n\n  // if there's a body, need to set the consumes header via requestContentType\n  var hasBody = body || definedFileParams.length || definedFormParams.length;\n  if (this.method === 'post' || this.method === 'put' || this.method === 'patch' ||\n      ((this.method === 'delete' || this.method === 'get') && hasBody)) {\n    if (opts.requestContentType) {\n      consumes = opts.requestContentType;\n    }\n    // if any form params, content type must be set\n    if (definedFormParams.length > 0) {\n      consumes = undefined;\n      if (opts.requestContentType) {             // override if set\n        consumes = opts.requestContentType;\n      } else if (definedFileParams.length > 0) { // if a file, must be multipart/form-data\n        consumes = 'multipart/form-data';\n      } else {\n        if (this.consumes && this.consumes.length > 0) {\n          // use the consumes setting\n          for(var c in this.consumes) {\n            var chk = this.consumes[c];\n            if(chk.indexOf('application/x-www-form-urlencoded') === 0 || chk.indexOf('multipart/form-data') === 0) {\n              consumes = chk;\n            }\n          }\n        }\n      }\n      if(typeof consumes === 'undefined') {\n        // default to x-www-from-urlencoded\n        consumes = 'application/x-www-form-urlencoded';\n      }\n    }\n  }\n  else {\n    consumes = null;\n  }\n\n  if (consumes && this.consumes) {\n    if (this.consumes.indexOf(consumes) === -1) {\n      helpers.log('server doesn\\'t consume ' + consumes + ', try ' + JSON.stringify(this.consumes));\n    }\n  }\n\n  if (!this.matchesAccept(accepts)) {\n    helpers.log('server can\\'t produce ' + accepts);\n  }\n\n  if ((consumes && body !== '') || (consumes === 'application/x-www-form-urlencoded')) {\n    headers['Content-Type'] = consumes;\n  }\n  else if(this.consumes && this.consumes.length > 0 && this.consumes[0] === 'application/x-www-form-urlencoded') {\n    headers['Content-Type'] = this.consumes[0];\n  }\n\n  if (accepts) {\n    headers.Accept = accepts;\n  }\n\n  return headers;\n};\n\n/**\n * Returns true if the request accepts header matches anything in this.produces.\n *  If this.produces contains * / *, ignore the accept header.\n * @param {string=} accepts The client request accept header.\n * @return {boolean}\n */\nOperation.prototype.matchesAccept = function(accepts) {\n  // no accepts or produces, no problem!\n  if (!accepts || !this.produces) {\n    return true;\n  }\n  return this.produces.indexOf(accepts) !== -1 || this.produces.indexOf('*/*') !== -1;\n};\n\nOperation.prototype.asCurl = function (args1, args2) {\n  var opts = {mock: true, maskPasswords: true};\n  if (typeof args2 === 'object') {\n    for (var argKey in args2) {\n      opts[argKey] = args2[argKey];\n    }\n  }\n  var obj = this.execute(args1, opts);\n\n  this.clientAuthorizations.apply(obj, this.operation.security);\n\n  var results = [];\n\n  results.push('-X ' + this.method.toUpperCase());\n\n  if (typeof obj.headers !== 'undefined') {\n    var key;\n\n    for (key in obj.headers) {\n      var value = obj.headers[key];\n      if(typeof value === 'string'){\n        value = value.replace(/\\'/g, '\\\\u0027');\n      }\n      results.push('--header \\'' + key + ': ' + value + '\\'');\n    }\n  }\n  var isFormData = false;\n  var isMultipart = false;\n\n  var type = obj.headers['Content-Type'];\n  if(type && type.indexOf('application/x-www-form-urlencoded') === 0) {\n    isFormData = true;\n  }\n  else if (type && type.indexOf('multipart/form-data') === 0) {\n    isFormData = true;\n    isMultipart = true;\n  }\n\n  if (obj.body) {\n    var body;\n    if (_.isObject(obj.body)) {\n      if(isMultipart) {\n        isMultipart = true;\n        // add the form data\n        for(var i = 0; i < this.parameters.length; i++) {\n          var parameter = this.parameters[i];\n          if(parameter.in === 'formData') {\n            if (!body) {\n              body = '';\n            }\n\n            var paramValue;\n            if(typeof FormData === 'function' && obj.body instanceof FormData) {\n              paramValue = obj.body.getAll(parameter.name);\n            }\n            else {\n              paramValue = obj.body[parameter.name];\n            }\n            if (paramValue) {\n              if (parameter.type === 'file') {\n                if(paramValue.name) {\n                  body += '-F ' + parameter.name + '=@\"' + paramValue.name + '\" ';\n                }\n              }\n              else {\n                if (Array.isArray(paramValue)) {\n                  if(parameter.collectionFormat === 'multi') {\n                    for(var v in paramValue) {\n                      body += '-F ' + this.encodeQueryKey(parameter.name) + '=' + mask(paramValue[v], parameter.format) + ' ';\n                    }\n                  }\n                  else {\n                    body += '-F ' + this.encodeQueryCollection(parameter.collectionFormat, parameter.name, mask(paramValue, parameter.format)) + ' ';\n                  }\n                } else {\n                  body += '-F ' + this.encodeQueryKey(parameter.name) + '=' + mask(paramValue, parameter.format) + ' ';\n                }\n              }\n            }\n          }\n        }\n      }\n      if(!body) {\n        body = JSON.stringify(obj.body);\n      }\n    } else {\n      body = obj.body;\n    }\n    // escape @ => %40, ' => %27\n    body = body.replace(/\\'/g, '%27').replace(/\\n/g, ' \\\\ \\n ');\n\n    if(!isFormData) {\n      // escape & => %26\n      body = body.replace(/&/g, '%26');\n    }\n    if(isMultipart) {\n      results.push(body);\n    }\n    else {\n      results.push('-d \\'' + body.replace(/@/g, '%40') + '\\'');\n    }\n  }\n\n  return 'curl ' + (results.join(' ')) + ' \\'' + obj.url + '\\'';\n};\n\nOperation.prototype.encodePathCollection = function (type, name, value, maskPasswords) {\n  var encoded = '';\n  var i;\n  var separator = '';\n\n  if (type === 'ssv') {\n    separator = '%20';\n  } else if (type === 'tsv') {\n    separator = '%09';\n  } else if (type === 'pipes') {\n    separator = '|';\n  } else {\n    separator = ',';\n  }\n\n  for (i = 0; i < value.length; i++) {\n    if (i === 0) {\n      encoded = this.encodeQueryParam(value[i], maskPasswords);\n    } else {\n      encoded += separator + this.encodeQueryParam(value[i], maskPasswords);\n    }\n  }\n\n  return encoded;\n};\n\nOperation.prototype.encodeQueryCollection = function (type, name, value, maskPasswords) {\n  var encoded = '';\n  var i;\n\n  type = type || 'default';\n  if (type === 'default' || type === 'multi') {\n    for (i = 0; i < value.length; i++) {\n      if (i > 0) {encoded += '&';}\n\n      encoded += this.encodeQueryKey(name) + '=' + mask(this.encodeQueryParam(value[i]), maskPasswords);\n    }\n  } else {\n    var separator = '';\n\n    if (type === 'csv') {\n      separator = ',';\n    } else if (type === 'ssv') {\n      separator = '%20';\n    } else if (type === 'tsv') {\n      separator = '%09';\n    } else if (type === 'pipes') {\n      separator = '|';\n    } else if (type === 'brackets') {\n      for (i = 0; i < value.length; i++) {\n        if (i !== 0) {\n          encoded += '&';\n        }\n        encoded += this.encodeQueryKey(name) + '[]=' + mask(this.encodeQueryParam(value[i]), maskPasswords);\n      }\n    }\n\n    if (separator !== '') {\n      for (i = 0; i < value.length; i++) {\n        if (i === 0) {\n          encoded = this.encodeQueryKey(name) + '=' + this.encodeQueryParam(value[i]);\n        } else {\n          encoded += separator + this.encodeQueryParam(value[i]);\n        }\n      }\n    }\n  }\n\n  return encoded;\n};\n\nOperation.prototype.encodeQueryKey = function (arg) {\n  return encodeURIComponent(arg)\n      .replace('%5B','[').replace('%5D', ']').replace('%24', '$');\n};\n\nOperation.prototype.encodeQueryParam = function (arg, maskPasswords) {\n  if(maskPasswords) {\n    return \"******\";\n  }\n  if(arg !== undefined && arg !== null) {\n    return encodeURIComponent(arg);\n  }\n  else {\n    return '';\n  }\n};\n\n/**\n * TODO revisit, might not want to leave '/'\n **/\nOperation.prototype.encodePathParam = function (pathParam, maskPasswords) {\n  return encodeURIComponent(pathParam, maskPasswords);\n};\n\nvar mask = function(value, format) {\n  if(typeof format === 'string' && format === 'password') {\n    return '******';\n  }\n  return value;\n}\n\n},{\"../helpers\":4,\"../http\":5,\"./model\":9,\"lodash-compat/lang/cloneDeep\":138,\"lodash-compat/lang/isEmpty\":141,\"lodash-compat/lang/isObject\":144,\"lodash-compat/lang/isUndefined\":148,\"q\":157}],11:[function(require,module,exports){\n'use strict';\n\nvar OperationGroup = module.exports = function (tag, description, externalDocs, operation) {\n  this.description = description;\n  this.externalDocs = externalDocs;\n  this.name = tag;\n  this.operation = operation;\n  this.operationsArray = [];\n  this.path = tag;\n  this.tag = tag;\n};\n\nOperationGroup.prototype.sort = function () {\n\n};\n\n\n},{}],12:[function(require,module,exports){\n// shim for using process in browser\n\nvar process = module.exports = {};\nvar queue = [];\nvar draining = false;\n\nfunction drainQueue() {\n    if (draining) {\n        return;\n    }\n    draining = true;\n    var currentQueue;\n    var len = queue.length;\n    while(len) {\n        currentQueue = queue;\n        queue = [];\n        var i = -1;\n        while (++i < len) {\n            currentQueue[i]();\n        }\n        len = queue.length;\n    }\n    draining = false;\n}\nprocess.nextTick = function (fun) {\n    queue.push(fun);\n    if (!draining) {\n        setTimeout(drainQueue, 0);\n    }\n};\n\nprocess.title = 'browser';\nprocess.browser = true;\nprocess.env = {};\nprocess.argv = [];\nprocess.version = ''; // empty string to avoid regexp issues\nprocess.versions = {};\n\nfunction noop() {}\n\nprocess.on = noop;\nprocess.addListener = noop;\nprocess.once = noop;\nprocess.off = noop;\nprocess.removeListener = noop;\nprocess.removeAllListeners = noop;\nprocess.emit = noop;\n\nprocess.binding = function (name) {\n    throw new Error('process.binding is not supported');\n};\n\n// TODO(shtylman)\nprocess.cwd = function () { return '/' };\nprocess.chdir = function (dir) {\n    throw new Error('process.chdir is not supported');\n};\nprocess.umask = function() { return 0; };\n\n},{}],13:[function(require,module,exports){\n(function (Buffer){\n(function () {\n  \"use strict\";\n\n  function btoa(str) {\n    var buffer\n      ;\n\n    if (str instanceof Buffer) {\n      buffer = str;\n    } else {\n      buffer = new Buffer(str.toString(), 'binary');\n    }\n\n    return buffer.toString('base64');\n  }\n\n  module.exports = btoa;\n}());\n\n}).call(this,require(\"buffer\").Buffer)\n\n},{\"buffer\":14}],14:[function(require,module,exports){\n/*!\n * The buffer module from node.js, for the browser.\n *\n * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>\n * @license  MIT\n */\n\nvar base64 = require('base64-js')\nvar ieee754 = require('ieee754')\nvar isArray = require('is-array')\n\nexports.Buffer = Buffer\nexports.SlowBuffer = SlowBuffer\nexports.INSPECT_MAX_BYTES = 50\nBuffer.poolSize = 8192 // not used by this implementation\n\nvar rootParent = {}\n\n/**\n * If `Buffer.TYPED_ARRAY_SUPPORT`:\n *   === true    Use Uint8Array implementation (fastest)\n *   === false   Use Object implementation (most compatible, even IE6)\n *\n * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,\n * Opera 11.6+, iOS 4.2+.\n *\n * Due to various browser bugs, sometimes the Object implementation will be used even\n * when the browser supports typed arrays.\n *\n * Note:\n *\n *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,\n *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.\n *\n *   - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property\n *     on objects.\n *\n *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.\n *\n *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of\n *     incorrect length in some situations.\n\n * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they\n * get the Object implementation, which is slower but behaves correctly.\n */\nBuffer.TYPED_ARRAY_SUPPORT = (function () {\n  function Bar () {}\n  try {\n    var arr = new Uint8Array(1)\n    arr.foo = function () { return 42 }\n    arr.constructor = Bar\n    return arr.foo() === 42 && // typed array instances can be augmented\n        arr.constructor === Bar && // constructor can be set\n        typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`\n        arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`\n  } catch (e) {\n    return false\n  }\n})()\n\nfunction kMaxLength () {\n  return Buffer.TYPED_ARRAY_SUPPORT\n    ? 0x7fffffff\n    : 0x3fffffff\n}\n\n/**\n * Class: Buffer\n * =============\n *\n * The Buffer constructor returns instances of `Uint8Array` that are augmented\n * with function properties for all the node `Buffer` API functions. We use\n * `Uint8Array` so that square bracket notation works as expected -- it returns\n * a single octet.\n *\n * By augmenting the instances, we can avoid modifying the `Uint8Array`\n * prototype.\n */\nfunction Buffer (arg) {\n  if (!(this instanceof Buffer)) {\n    // Avoid going through an ArgumentsAdaptorTrampoline in the common case.\n    if (arguments.length > 1) return new Buffer(arg, arguments[1])\n    return new Buffer(arg)\n  }\n\n  this.length = 0\n  this.parent = undefined\n\n  // Common case.\n  if (typeof arg === 'number') {\n    return fromNumber(this, arg)\n  }\n\n  // Slightly less common case.\n  if (typeof arg === 'string') {\n    return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')\n  }\n\n  // Unusual.\n  return fromObject(this, arg)\n}\n\nfunction fromNumber (that, length) {\n  that = allocate(that, length < 0 ? 0 : checked(length) | 0)\n  if (!Buffer.TYPED_ARRAY_SUPPORT) {\n    for (var i = 0; i < length; i++) {\n      that[i] = 0\n    }\n  }\n  return that\n}\n\nfunction fromString (that, string, encoding) {\n  if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'\n\n  // Assumption: byteLength() return value is always < kMaxLength.\n  var length = byteLength(string, encoding) | 0\n  that = allocate(that, length)\n\n  that.write(string, encoding)\n  return that\n}\n\nfunction fromObject (that, object) {\n  if (Buffer.isBuffer(object)) return fromBuffer(that, object)\n\n  if (isArray(object)) return fromArray(that, object)\n\n  if (object == null) {\n    throw new TypeError('must start with number, buffer, array or string')\n  }\n\n  if (typeof ArrayBuffer !== 'undefined') {\n    if (object.buffer instanceof ArrayBuffer) {\n      return fromTypedArray(that, object)\n    }\n    if (object instanceof ArrayBuffer) {\n      return fromArrayBuffer(that, object)\n    }\n  }\n\n  if (object.length) return fromArrayLike(that, object)\n\n  return fromJsonObject(that, object)\n}\n\nfunction fromBuffer (that, buffer) {\n  var length = checked(buffer.length) | 0\n  that = allocate(that, length)\n  buffer.copy(that, 0, 0, length)\n  return that\n}\n\nfunction fromArray (that, array) {\n  var length = checked(array.length) | 0\n  that = allocate(that, length)\n  for (var i = 0; i < length; i += 1) {\n    that[i] = array[i] & 255\n  }\n  return that\n}\n\n// Duplicate of fromArray() to keep fromArray() monomorphic.\nfunction fromTypedArray (that, array) {\n  var length = checked(array.length) | 0\n  that = allocate(that, length)\n  // Truncating the elements is probably not what people expect from typed\n  // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior\n  // of the old Buffer constructor.\n  for (var i = 0; i < length; i += 1) {\n    that[i] = array[i] & 255\n  }\n  return that\n}\n\nfunction fromArrayBuffer (that, array) {\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    // Return an augmented `Uint8Array` instance, for best performance\n    array.byteLength\n    that = Buffer._augment(new Uint8Array(array))\n  } else {\n    // Fallback: Return an object instance of the Buffer class\n    that = fromTypedArray(that, new Uint8Array(array))\n  }\n  return that\n}\n\nfunction fromArrayLike (that, array) {\n  var length = checked(array.length) | 0\n  that = allocate(that, length)\n  for (var i = 0; i < length; i += 1) {\n    that[i] = array[i] & 255\n  }\n  return that\n}\n\n// Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.\n// Returns a zero-length buffer for inputs that don't conform to the spec.\nfunction fromJsonObject (that, object) {\n  var array\n  var length = 0\n\n  if (object.type === 'Buffer' && isArray(object.data)) {\n    array = object.data\n    length = checked(array.length) | 0\n  }\n  that = allocate(that, length)\n\n  for (var i = 0; i < length; i += 1) {\n    that[i] = array[i] & 255\n  }\n  return that\n}\n\nfunction allocate (that, length) {\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    // Return an augmented `Uint8Array` instance, for best performance\n    that = Buffer._augment(new Uint8Array(length))\n  } else {\n    // Fallback: Return an object instance of the Buffer class\n    that.length = length\n    that._isBuffer = true\n  }\n\n  var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1\n  if (fromPool) that.parent = rootParent\n\n  return that\n}\n\nfunction checked (length) {\n  // Note: cannot use `length < kMaxLength` here because that fails when\n  // length is NaN (which is otherwise coerced to zero.)\n  if (length >= kMaxLength()) {\n    throw new RangeError('Attempt to allocate Buffer larger than maximum ' +\n                         'size: 0x' + kMaxLength().toString(16) + ' bytes')\n  }\n  return length | 0\n}\n\nfunction SlowBuffer (subject, encoding) {\n  if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)\n\n  var buf = new Buffer(subject, encoding)\n  delete buf.parent\n  return buf\n}\n\nBuffer.isBuffer = function isBuffer (b) {\n  return !!(b != null && b._isBuffer)\n}\n\nBuffer.compare = function compare (a, b) {\n  if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {\n    throw new TypeError('Arguments must be Buffers')\n  }\n\n  if (a === b) return 0\n\n  var x = a.length\n  var y = b.length\n\n  var i = 0\n  var len = Math.min(x, y)\n  while (i < len) {\n    if (a[i] !== b[i]) break\n\n    ++i\n  }\n\n  if (i !== len) {\n    x = a[i]\n    y = b[i]\n  }\n\n  if (x < y) return -1\n  if (y < x) return 1\n  return 0\n}\n\nBuffer.isEncoding = function isEncoding (encoding) {\n  switch (String(encoding).toLowerCase()) {\n    case 'hex':\n    case 'utf8':\n    case 'utf-8':\n    case 'ascii':\n    case 'binary':\n    case 'base64':\n    case 'raw':\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      return true\n    default:\n      return false\n  }\n}\n\nBuffer.concat = function concat (list, length) {\n  if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')\n\n  if (list.length === 0) {\n    return new Buffer(0)\n  }\n\n  var i\n  if (length === undefined) {\n    length = 0\n    for (i = 0; i < list.length; i++) {\n      length += list[i].length\n    }\n  }\n\n  var buf = new Buffer(length)\n  var pos = 0\n  for (i = 0; i < list.length; i++) {\n    var item = list[i]\n    item.copy(buf, pos)\n    pos += item.length\n  }\n  return buf\n}\n\nfunction byteLength (string, encoding) {\n  if (typeof string !== 'string') string = '' + string\n\n  var len = string.length\n  if (len === 0) return 0\n\n  // Use a for loop to avoid recursion\n  var loweredCase = false\n  for (;;) {\n    switch (encoding) {\n      case 'ascii':\n      case 'binary':\n      // Deprecated\n      case 'raw':\n      case 'raws':\n        return len\n      case 'utf8':\n      case 'utf-8':\n        return utf8ToBytes(string).length\n      case 'ucs2':\n      case 'ucs-2':\n      case 'utf16le':\n      case 'utf-16le':\n        return len * 2\n      case 'hex':\n        return len >>> 1\n      case 'base64':\n        return base64ToBytes(string).length\n      default:\n        if (loweredCase) return utf8ToBytes(string).length // assume utf8\n        encoding = ('' + encoding).toLowerCase()\n        loweredCase = true\n    }\n  }\n}\nBuffer.byteLength = byteLength\n\n// pre-set for values that may exist in the future\nBuffer.prototype.length = undefined\nBuffer.prototype.parent = undefined\n\nfunction slowToString (encoding, start, end) {\n  var loweredCase = false\n\n  start = start | 0\n  end = end === undefined || end === Infinity ? this.length : end | 0\n\n  if (!encoding) encoding = 'utf8'\n  if (start < 0) start = 0\n  if (end > this.length) end = this.length\n  if (end <= start) return ''\n\n  while (true) {\n    switch (encoding) {\n      case 'hex':\n        return hexSlice(this, start, end)\n\n      case 'utf8':\n      case 'utf-8':\n        return utf8Slice(this, start, end)\n\n      case 'ascii':\n        return asciiSlice(this, start, end)\n\n      case 'binary':\n        return binarySlice(this, start, end)\n\n      case 'base64':\n        return base64Slice(this, start, end)\n\n      case 'ucs2':\n      case 'ucs-2':\n      case 'utf16le':\n      case 'utf-16le':\n        return utf16leSlice(this, start, end)\n\n      default:\n        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)\n        encoding = (encoding + '').toLowerCase()\n        loweredCase = true\n    }\n  }\n}\n\nBuffer.prototype.toString = function toString () {\n  var length = this.length | 0\n  if (length === 0) return ''\n  if (arguments.length === 0) return utf8Slice(this, 0, length)\n  return slowToString.apply(this, arguments)\n}\n\nBuffer.prototype.equals = function equals (b) {\n  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')\n  if (this === b) return true\n  return Buffer.compare(this, b) === 0\n}\n\nBuffer.prototype.inspect = function inspect () {\n  var str = ''\n  var max = exports.INSPECT_MAX_BYTES\n  if (this.length > 0) {\n    str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')\n    if (this.length > max) str += ' ... '\n  }\n  return '<Buffer ' + str + '>'\n}\n\nBuffer.prototype.compare = function compare (b) {\n  if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')\n  if (this === b) return 0\n  return Buffer.compare(this, b)\n}\n\nBuffer.prototype.indexOf = function indexOf (val, byteOffset) {\n  if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff\n  else if (byteOffset < -0x80000000) byteOffset = -0x80000000\n  byteOffset >>= 0\n\n  if (this.length === 0) return -1\n  if (byteOffset >= this.length) return -1\n\n  // Negative offsets start from the end of the buffer\n  if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)\n\n  if (typeof val === 'string') {\n    if (val.length === 0) return -1 // special case: looking for empty string always fails\n    return String.prototype.indexOf.call(this, val, byteOffset)\n  }\n  if (Buffer.isBuffer(val)) {\n    return arrayIndexOf(this, val, byteOffset)\n  }\n  if (typeof val === 'number') {\n    if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {\n      return Uint8Array.prototype.indexOf.call(this, val, byteOffset)\n    }\n    return arrayIndexOf(this, [ val ], byteOffset)\n  }\n\n  function arrayIndexOf (arr, val, byteOffset) {\n    var foundIndex = -1\n    for (var i = 0; byteOffset + i < arr.length; i++) {\n      if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {\n        if (foundIndex === -1) foundIndex = i\n        if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex\n      } else {\n        foundIndex = -1\n      }\n    }\n    return -1\n  }\n\n  throw new TypeError('val must be string, number or Buffer')\n}\n\n// `get` is deprecated\nBuffer.prototype.get = function get (offset) {\n  console.log('.get() is deprecated. Access using array indexes instead.')\n  return this.readUInt8(offset)\n}\n\n// `set` is deprecated\nBuffer.prototype.set = function set (v, offset) {\n  console.log('.set() is deprecated. Access using array indexes instead.')\n  return this.writeUInt8(v, offset)\n}\n\nfunction hexWrite (buf, string, offset, length) {\n  offset = Number(offset) || 0\n  var remaining = buf.length - offset\n  if (!length) {\n    length = remaining\n  } else {\n    length = Number(length)\n    if (length > remaining) {\n      length = remaining\n    }\n  }\n\n  // must be an even number of digits\n  var strLen = string.length\n  if (strLen % 2 !== 0) throw new Error('Invalid hex string')\n\n  if (length > strLen / 2) {\n    length = strLen / 2\n  }\n  for (var i = 0; i < length; i++) {\n    var parsed = parseInt(string.substr(i * 2, 2), 16)\n    if (isNaN(parsed)) throw new Error('Invalid hex string')\n    buf[offset + i] = parsed\n  }\n  return i\n}\n\nfunction utf8Write (buf, string, offset, length) {\n  return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)\n}\n\nfunction asciiWrite (buf, string, offset, length) {\n  return blitBuffer(asciiToBytes(string), buf, offset, length)\n}\n\nfunction binaryWrite (buf, string, offset, length) {\n  return asciiWrite(buf, string, offset, length)\n}\n\nfunction base64Write (buf, string, offset, length) {\n  return blitBuffer(base64ToBytes(string), buf, offset, length)\n}\n\nfunction ucs2Write (buf, string, offset, length) {\n  return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)\n}\n\nBuffer.prototype.write = function write (string, offset, length, encoding) {\n  // Buffer#write(string)\n  if (offset === undefined) {\n    encoding = 'utf8'\n    length = this.length\n    offset = 0\n  // Buffer#write(string, encoding)\n  } else if (length === undefined && typeof offset === 'string') {\n    encoding = offset\n    length = this.length\n    offset = 0\n  // Buffer#write(string, offset[, length][, encoding])\n  } else if (isFinite(offset)) {\n    offset = offset | 0\n    if (isFinite(length)) {\n      length = length | 0\n      if (encoding === undefined) encoding = 'utf8'\n    } else {\n      encoding = length\n      length = undefined\n    }\n  // legacy write(string, encoding, offset, length) - remove in v0.13\n  } else {\n    var swap = encoding\n    encoding = offset\n    offset = length | 0\n    length = swap\n  }\n\n  var remaining = this.length - offset\n  if (length === undefined || length > remaining) length = remaining\n\n  if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {\n    throw new RangeError('attempt to write outside buffer bounds')\n  }\n\n  if (!encoding) encoding = 'utf8'\n\n  var loweredCase = false\n  for (;;) {\n    switch (encoding) {\n      case 'hex':\n        return hexWrite(this, string, offset, length)\n\n      case 'utf8':\n      case 'utf-8':\n        return utf8Write(this, string, offset, length)\n\n      case 'ascii':\n        return asciiWrite(this, string, offset, length)\n\n      case 'binary':\n        return binaryWrite(this, string, offset, length)\n\n      case 'base64':\n        // Warning: maxLength not taken into account in base64Write\n        return base64Write(this, string, offset, length)\n\n      case 'ucs2':\n      case 'ucs-2':\n      case 'utf16le':\n      case 'utf-16le':\n        return ucs2Write(this, string, offset, length)\n\n      default:\n        if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)\n        encoding = ('' + encoding).toLowerCase()\n        loweredCase = true\n    }\n  }\n}\n\nBuffer.prototype.toJSON = function toJSON () {\n  return {\n    type: 'Buffer',\n    data: Array.prototype.slice.call(this._arr || this, 0)\n  }\n}\n\nfunction base64Slice (buf, start, end) {\n  if (start === 0 && end === buf.length) {\n    return base64.fromByteArray(buf)\n  } else {\n    return base64.fromByteArray(buf.slice(start, end))\n  }\n}\n\nfunction utf8Slice (buf, start, end) {\n  end = Math.min(buf.length, end)\n  var res = []\n\n  var i = start\n  while (i < end) {\n    var firstByte = buf[i]\n    var codePoint = null\n    var bytesPerSequence = (firstByte > 0xEF) ? 4\n      : (firstByte > 0xDF) ? 3\n      : (firstByte > 0xBF) ? 2\n      : 1\n\n    if (i + bytesPerSequence <= end) {\n      var secondByte, thirdByte, fourthByte, tempCodePoint\n\n      switch (bytesPerSequence) {\n        case 1:\n          if (firstByte < 0x80) {\n            codePoint = firstByte\n          }\n          break\n        case 2:\n          secondByte = buf[i + 1]\n          if ((secondByte & 0xC0) === 0x80) {\n            tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)\n            if (tempCodePoint > 0x7F) {\n              codePoint = tempCodePoint\n            }\n          }\n          break\n        case 3:\n          secondByte = buf[i + 1]\n          thirdByte = buf[i + 2]\n          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {\n            tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)\n            if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {\n              codePoint = tempCodePoint\n            }\n          }\n          break\n        case 4:\n          secondByte = buf[i + 1]\n          thirdByte = buf[i + 2]\n          fourthByte = buf[i + 3]\n          if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {\n            tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)\n            if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {\n              codePoint = tempCodePoint\n            }\n          }\n      }\n    }\n\n    if (codePoint === null) {\n      // we did not generate a valid codePoint so insert a\n      // replacement char (U+FFFD) and advance only 1 byte\n      codePoint = 0xFFFD\n      bytesPerSequence = 1\n    } else if (codePoint > 0xFFFF) {\n      // encode to utf16 (surrogate pair dance)\n      codePoint -= 0x10000\n      res.push(codePoint >>> 10 & 0x3FF | 0xD800)\n      codePoint = 0xDC00 | codePoint & 0x3FF\n    }\n\n    res.push(codePoint)\n    i += bytesPerSequence\n  }\n\n  return decodeCodePointsArray(res)\n}\n\n// Based on http://stackoverflow.com/a/22747272/680742, the browser with\n// the lowest limit is Chrome, with 0x10000 args.\n// We go 1 magnitude less, for safety\nvar MAX_ARGUMENTS_LENGTH = 0x1000\n\nfunction decodeCodePointsArray (codePoints) {\n  var len = codePoints.length\n  if (len <= MAX_ARGUMENTS_LENGTH) {\n    return String.fromCharCode.apply(String, codePoints) // avoid extra slice()\n  }\n\n  // Decode in chunks to avoid \"call stack size exceeded\".\n  var res = ''\n  var i = 0\n  while (i < len) {\n    res += String.fromCharCode.apply(\n      String,\n      codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)\n    )\n  }\n  return res\n}\n\nfunction asciiSlice (buf, start, end) {\n  var ret = ''\n  end = Math.min(buf.length, end)\n\n  for (var i = start; i < end; i++) {\n    ret += String.fromCharCode(buf[i] & 0x7F)\n  }\n  return ret\n}\n\nfunction binarySlice (buf, start, end) {\n  var ret = ''\n  end = Math.min(buf.length, end)\n\n  for (var i = start; i < end; i++) {\n    ret += String.fromCharCode(buf[i])\n  }\n  return ret\n}\n\nfunction hexSlice (buf, start, end) {\n  var len = buf.length\n\n  if (!start || start < 0) start = 0\n  if (!end || end < 0 || end > len) end = len\n\n  var out = ''\n  for (var i = start; i < end; i++) {\n    out += toHex(buf[i])\n  }\n  return out\n}\n\nfunction utf16leSlice (buf, start, end) {\n  var bytes = buf.slice(start, end)\n  var res = ''\n  for (var i = 0; i < bytes.length; i += 2) {\n    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)\n  }\n  return res\n}\n\nBuffer.prototype.slice = function slice (start, end) {\n  var len = this.length\n  start = ~~start\n  end = end === undefined ? len : ~~end\n\n  if (start < 0) {\n    start += len\n    if (start < 0) start = 0\n  } else if (start > len) {\n    start = len\n  }\n\n  if (end < 0) {\n    end += len\n    if (end < 0) end = 0\n  } else if (end > len) {\n    end = len\n  }\n\n  if (end < start) end = start\n\n  var newBuf\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    newBuf = Buffer._augment(this.subarray(start, end))\n  } else {\n    var sliceLen = end - start\n    newBuf = new Buffer(sliceLen, undefined)\n    for (var i = 0; i < sliceLen; i++) {\n      newBuf[i] = this[i + start]\n    }\n  }\n\n  if (newBuf.length) newBuf.parent = this.parent || this\n\n  return newBuf\n}\n\n/*\n * Need to make sure that buffer isn't trying to write out of bounds.\n */\nfunction checkOffset (offset, ext, length) {\n  if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')\n  if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')\n}\n\nBuffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {\n  offset = offset | 0\n  byteLength = byteLength | 0\n  if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n  var val = this[offset]\n  var mul = 1\n  var i = 0\n  while (++i < byteLength && (mul *= 0x100)) {\n    val += this[offset + i] * mul\n  }\n\n  return val\n}\n\nBuffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {\n  offset = offset | 0\n  byteLength = byteLength | 0\n  if (!noAssert) {\n    checkOffset(offset, byteLength, this.length)\n  }\n\n  var val = this[offset + --byteLength]\n  var mul = 1\n  while (byteLength > 0 && (mul *= 0x100)) {\n    val += this[offset + --byteLength] * mul\n  }\n\n  return val\n}\n\nBuffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 1, this.length)\n  return this[offset]\n}\n\nBuffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  return this[offset] | (this[offset + 1] << 8)\n}\n\nBuffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  return (this[offset] << 8) | this[offset + 1]\n}\n\nBuffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return ((this[offset]) |\n      (this[offset + 1] << 8) |\n      (this[offset + 2] << 16)) +\n      (this[offset + 3] * 0x1000000)\n}\n\nBuffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return (this[offset] * 0x1000000) +\n    ((this[offset + 1] << 16) |\n    (this[offset + 2] << 8) |\n    this[offset + 3])\n}\n\nBuffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {\n  offset = offset | 0\n  byteLength = byteLength | 0\n  if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n  var val = this[offset]\n  var mul = 1\n  var i = 0\n  while (++i < byteLength && (mul *= 0x100)) {\n    val += this[offset + i] * mul\n  }\n  mul *= 0x80\n\n  if (val >= mul) val -= Math.pow(2, 8 * byteLength)\n\n  return val\n}\n\nBuffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {\n  offset = offset | 0\n  byteLength = byteLength | 0\n  if (!noAssert) checkOffset(offset, byteLength, this.length)\n\n  var i = byteLength\n  var mul = 1\n  var val = this[offset + --i]\n  while (i > 0 && (mul *= 0x100)) {\n    val += this[offset + --i] * mul\n  }\n  mul *= 0x80\n\n  if (val >= mul) val -= Math.pow(2, 8 * byteLength)\n\n  return val\n}\n\nBuffer.prototype.readInt8 = function readInt8 (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 1, this.length)\n  if (!(this[offset] & 0x80)) return (this[offset])\n  return ((0xff - this[offset] + 1) * -1)\n}\n\nBuffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  var val = this[offset] | (this[offset + 1] << 8)\n  return (val & 0x8000) ? val | 0xFFFF0000 : val\n}\n\nBuffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 2, this.length)\n  var val = this[offset + 1] | (this[offset] << 8)\n  return (val & 0x8000) ? val | 0xFFFF0000 : val\n}\n\nBuffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return (this[offset]) |\n    (this[offset + 1] << 8) |\n    (this[offset + 2] << 16) |\n    (this[offset + 3] << 24)\n}\n\nBuffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 4, this.length)\n\n  return (this[offset] << 24) |\n    (this[offset + 1] << 16) |\n    (this[offset + 2] << 8) |\n    (this[offset + 3])\n}\n\nBuffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 4, this.length)\n  return ieee754.read(this, offset, true, 23, 4)\n}\n\nBuffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 4, this.length)\n  return ieee754.read(this, offset, false, 23, 4)\n}\n\nBuffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 8, this.length)\n  return ieee754.read(this, offset, true, 52, 8)\n}\n\nBuffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {\n  if (!noAssert) checkOffset(offset, 8, this.length)\n  return ieee754.read(this, offset, false, 52, 8)\n}\n\nfunction checkInt (buf, value, offset, ext, max, min) {\n  if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')\n  if (value > max || value < min) throw new RangeError('value is out of bounds')\n  if (offset + ext > buf.length) throw new RangeError('index out of range')\n}\n\nBuffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset | 0\n  byteLength = byteLength | 0\n  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)\n\n  var mul = 1\n  var i = 0\n  this[offset] = value & 0xFF\n  while (++i < byteLength && (mul *= 0x100)) {\n    this[offset + i] = (value / mul) & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset | 0\n  byteLength = byteLength | 0\n  if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)\n\n  var i = byteLength - 1\n  var mul = 1\n  this[offset + i] = value & 0xFF\n  while (--i >= 0 && (mul *= 0x100)) {\n    this[offset + i] = (value / mul) & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)\n  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)\n  this[offset] = value\n  return offset + 1\n}\n\nfunction objectWriteUInt16 (buf, value, offset, littleEndian) {\n  if (value < 0) value = 0xffff + value + 1\n  for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {\n    buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>\n      (littleEndian ? i : 1 - i) * 8\n  }\n}\n\nBuffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    this[offset] = value\n    this[offset + 1] = (value >>> 8)\n  } else {\n    objectWriteUInt16(this, value, offset, true)\n  }\n  return offset + 2\n}\n\nBuffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    this[offset] = (value >>> 8)\n    this[offset + 1] = value\n  } else {\n    objectWriteUInt16(this, value, offset, false)\n  }\n  return offset + 2\n}\n\nfunction objectWriteUInt32 (buf, value, offset, littleEndian) {\n  if (value < 0) value = 0xffffffff + value + 1\n  for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {\n    buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff\n  }\n}\n\nBuffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    this[offset + 3] = (value >>> 24)\n    this[offset + 2] = (value >>> 16)\n    this[offset + 1] = (value >>> 8)\n    this[offset] = value\n  } else {\n    objectWriteUInt32(this, value, offset, true)\n  }\n  return offset + 4\n}\n\nBuffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    this[offset] = (value >>> 24)\n    this[offset + 1] = (value >>> 16)\n    this[offset + 2] = (value >>> 8)\n    this[offset + 3] = value\n  } else {\n    objectWriteUInt32(this, value, offset, false)\n  }\n  return offset + 4\n}\n\nBuffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) {\n    var limit = Math.pow(2, 8 * byteLength - 1)\n\n    checkInt(this, value, offset, byteLength, limit - 1, -limit)\n  }\n\n  var i = 0\n  var mul = 1\n  var sub = value < 0 ? 1 : 0\n  this[offset] = value & 0xFF\n  while (++i < byteLength && (mul *= 0x100)) {\n    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) {\n    var limit = Math.pow(2, 8 * byteLength - 1)\n\n    checkInt(this, value, offset, byteLength, limit - 1, -limit)\n  }\n\n  var i = byteLength - 1\n  var mul = 1\n  var sub = value < 0 ? 1 : 0\n  this[offset + i] = value & 0xFF\n  while (--i >= 0 && (mul *= 0x100)) {\n    this[offset + i] = ((value / mul) >> 0) - sub & 0xFF\n  }\n\n  return offset + byteLength\n}\n\nBuffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)\n  if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)\n  if (value < 0) value = 0xff + value + 1\n  this[offset] = value\n  return offset + 1\n}\n\nBuffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    this[offset] = value\n    this[offset + 1] = (value >>> 8)\n  } else {\n    objectWriteUInt16(this, value, offset, true)\n  }\n  return offset + 2\n}\n\nBuffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    this[offset] = (value >>> 8)\n    this[offset + 1] = value\n  } else {\n    objectWriteUInt16(this, value, offset, false)\n  }\n  return offset + 2\n}\n\nBuffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    this[offset] = value\n    this[offset + 1] = (value >>> 8)\n    this[offset + 2] = (value >>> 16)\n    this[offset + 3] = (value >>> 24)\n  } else {\n    objectWriteUInt32(this, value, offset, true)\n  }\n  return offset + 4\n}\n\nBuffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {\n  value = +value\n  offset = offset | 0\n  if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)\n  if (value < 0) value = 0xffffffff + value + 1\n  if (Buffer.TYPED_ARRAY_SUPPORT) {\n    this[offset] = (value >>> 24)\n    this[offset + 1] = (value >>> 16)\n    this[offset + 2] = (value >>> 8)\n    this[offset + 3] = value\n  } else {\n    objectWriteUInt32(this, value, offset, false)\n  }\n  return offset + 4\n}\n\nfunction checkIEEE754 (buf, value, offset, ext, max, min) {\n  if (value > max || value < min) throw new RangeError('value is out of bounds')\n  if (offset + ext > buf.length) throw new RangeError('index out of range')\n  if (offset < 0) throw new RangeError('index out of range')\n}\n\nfunction writeFloat (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)\n  }\n  ieee754.write(buf, value, offset, littleEndian, 23, 4)\n  return offset + 4\n}\n\nBuffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {\n  return writeFloat(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {\n  return writeFloat(this, value, offset, false, noAssert)\n}\n\nfunction writeDouble (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)\n  }\n  ieee754.write(buf, value, offset, littleEndian, 52, 8)\n  return offset + 8\n}\n\nBuffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {\n  return writeDouble(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {\n  return writeDouble(this, value, offset, false, noAssert)\n}\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function copy (target, targetStart, start, end) {\n  if (!start) start = 0\n  if (!end && end !== 0) end = this.length\n  if (targetStart >= target.length) targetStart = target.length\n  if (!targetStart) targetStart = 0\n  if (end > 0 && end < start) end = start\n\n  // Copy 0 bytes; we're done\n  if (end === start) return 0\n  if (target.length === 0 || this.length === 0) return 0\n\n  // Fatal error conditions\n  if (targetStart < 0) {\n    throw new RangeError('targetStart out of bounds')\n  }\n  if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')\n  if (end < 0) throw new RangeError('sourceEnd out of bounds')\n\n  // Are we oob?\n  if (end > this.length) end = this.length\n  if (target.length - targetStart < end - start) {\n    end = target.length - targetStart + start\n  }\n\n  var len = end - start\n  var i\n\n  if (this === target && start < targetStart && targetStart < end) {\n    // descending copy from end\n    for (i = len - 1; i >= 0; i--) {\n      target[i + targetStart] = this[i + start]\n    }\n  } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {\n    // ascending copy from start\n    for (i = 0; i < len; i++) {\n      target[i + targetStart] = this[i + start]\n    }\n  } else {\n    target._set(this.subarray(start, start + len), targetStart)\n  }\n\n  return len\n}\n\n// fill(value, start=0, end=buffer.length)\nBuffer.prototype.fill = function fill (value, start, end) {\n  if (!value) value = 0\n  if (!start) start = 0\n  if (!end) end = this.length\n\n  if (end < start) throw new RangeError('end < start')\n\n  // Fill 0 bytes; we're done\n  if (end === start) return\n  if (this.length === 0) return\n\n  if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')\n  if (end < 0 || end > this.length) throw new RangeError('end out of bounds')\n\n  var i\n  if (typeof value === 'number') {\n    for (i = start; i < end; i++) {\n      this[i] = value\n    }\n  } else {\n    var bytes = utf8ToBytes(value.toString())\n    var len = bytes.length\n    for (i = start; i < end; i++) {\n      this[i] = bytes[i % len]\n    }\n  }\n\n  return this\n}\n\n/**\n * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.\n * Added in Node 0.12. Only available in browsers that support ArrayBuffer.\n */\nBuffer.prototype.toArrayBuffer = function toArrayBuffer () {\n  if (typeof Uint8Array !== 'undefined') {\n    if (Buffer.TYPED_ARRAY_SUPPORT) {\n      return (new Buffer(this)).buffer\n    } else {\n      var buf = new Uint8Array(this.length)\n      for (var i = 0, len = buf.length; i < len; i += 1) {\n        buf[i] = this[i]\n      }\n      return buf.buffer\n    }\n  } else {\n    throw new TypeError('Buffer.toArrayBuffer not supported in this browser')\n  }\n}\n\n// HELPER FUNCTIONS\n// ================\n\nvar BP = Buffer.prototype\n\n/**\n * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods\n */\nBuffer._augment = function _augment (arr) {\n  arr.constructor = Buffer\n  arr._isBuffer = true\n\n  // save reference to original Uint8Array set method before overwriting\n  arr._set = arr.set\n\n  // deprecated\n  arr.get = BP.get\n  arr.set = BP.set\n\n  arr.write = BP.write\n  arr.toString = BP.toString\n  arr.toLocaleString = BP.toString\n  arr.toJSON = BP.toJSON\n  arr.equals = BP.equals\n  arr.compare = BP.compare\n  arr.indexOf = BP.indexOf\n  arr.copy = BP.copy\n  arr.slice = BP.slice\n  arr.readUIntLE = BP.readUIntLE\n  arr.readUIntBE = BP.readUIntBE\n  arr.readUInt8 = BP.readUInt8\n  arr.readUInt16LE = BP.readUInt16LE\n  arr.readUInt16BE = BP.readUInt16BE\n  arr.readUInt32LE = BP.readUInt32LE\n  arr.readUInt32BE = BP.readUInt32BE\n  arr.readIntLE = BP.readIntLE\n  arr.readIntBE = BP.readIntBE\n  arr.readInt8 = BP.readInt8\n  arr.readInt16LE = BP.readInt16LE\n  arr.readInt16BE = BP.readInt16BE\n  arr.readInt32LE = BP.readInt32LE\n  arr.readInt32BE = BP.readInt32BE\n  arr.readFloatLE = BP.readFloatLE\n  arr.readFloatBE = BP.readFloatBE\n  arr.readDoubleLE = BP.readDoubleLE\n  arr.readDoubleBE = BP.readDoubleBE\n  arr.writeUInt8 = BP.writeUInt8\n  arr.writeUIntLE = BP.writeUIntLE\n  arr.writeUIntBE = BP.writeUIntBE\n  arr.writeUInt16LE = BP.writeUInt16LE\n  arr.writeUInt16BE = BP.writeUInt16BE\n  arr.writeUInt32LE = BP.writeUInt32LE\n  arr.writeUInt32BE = BP.writeUInt32BE\n  arr.writeIntLE = BP.writeIntLE\n  arr.writeIntBE = BP.writeIntBE\n  arr.writeInt8 = BP.writeInt8\n  arr.writeInt16LE = BP.writeInt16LE\n  arr.writeInt16BE = BP.writeInt16BE\n  arr.writeInt32LE = BP.writeInt32LE\n  arr.writeInt32BE = BP.writeInt32BE\n  arr.writeFloatLE = BP.writeFloatLE\n  arr.writeFloatBE = BP.writeFloatBE\n  arr.writeDoubleLE = BP.writeDoubleLE\n  arr.writeDoubleBE = BP.writeDoubleBE\n  arr.fill = BP.fill\n  arr.inspect = BP.inspect\n  arr.toArrayBuffer = BP.toArrayBuffer\n\n  return arr\n}\n\nvar INVALID_BASE64_RE = /[^+\\/0-9A-Za-z-_]/g\n\nfunction base64clean (str) {\n  // Node strips out invalid characters like \\n and \\t from the string, base64-js does not\n  str = stringtrim(str).replace(INVALID_BASE64_RE, '')\n  // Node converts strings with length < 2 to ''\n  if (str.length < 2) return ''\n  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not\n  while (str.length % 4 !== 0) {\n    str = str + '='\n  }\n  return str\n}\n\nfunction stringtrim (str) {\n  if (str.trim) return str.trim()\n  return str.replace(/^\\s+|\\s+$/g, '')\n}\n\nfunction toHex (n) {\n  if (n < 16) return '0' + n.toString(16)\n  return n.toString(16)\n}\n\nfunction utf8ToBytes (string, units) {\n  units = units || Infinity\n  var codePoint\n  var length = string.length\n  var leadSurrogate = null\n  var bytes = []\n\n  for (var i = 0; i < length; i++) {\n    codePoint = string.charCodeAt(i)\n\n    // is surrogate component\n    if (codePoint > 0xD7FF && codePoint < 0xE000) {\n      // last char was a lead\n      if (!leadSurrogate) {\n        // no lead yet\n        if (codePoint > 0xDBFF) {\n          // unexpected trail\n          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n          continue\n        } else if (i + 1 === length) {\n          // unpaired lead\n          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n          continue\n        }\n\n        // valid lead\n        leadSurrogate = codePoint\n\n        continue\n      }\n\n      // 2 leads in a row\n      if (codePoint < 0xDC00) {\n        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n        leadSurrogate = codePoint\n        continue\n      }\n\n      // valid surrogate pair\n      codePoint = leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00 | 0x10000\n    } else if (leadSurrogate) {\n      // valid bmp char, but last char was a lead\n      if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)\n    }\n\n    leadSurrogate = null\n\n    // encode utf8\n    if (codePoint < 0x80) {\n      if ((units -= 1) < 0) break\n      bytes.push(codePoint)\n    } else if (codePoint < 0x800) {\n      if ((units -= 2) < 0) break\n      bytes.push(\n        codePoint >> 0x6 | 0xC0,\n        codePoint & 0x3F | 0x80\n      )\n    } else if (codePoint < 0x10000) {\n      if ((units -= 3) < 0) break\n      bytes.push(\n        codePoint >> 0xC | 0xE0,\n        codePoint >> 0x6 & 0x3F | 0x80,\n        codePoint & 0x3F | 0x80\n      )\n    } else if (codePoint < 0x110000) {\n      if ((units -= 4) < 0) break\n      bytes.push(\n        codePoint >> 0x12 | 0xF0,\n        codePoint >> 0xC & 0x3F | 0x80,\n        codePoint >> 0x6 & 0x3F | 0x80,\n        codePoint & 0x3F | 0x80\n      )\n    } else {\n      throw new Error('Invalid code point')\n    }\n  }\n\n  return bytes\n}\n\nfunction asciiToBytes (str) {\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    // Node's code seems to be doing this and not & 0x7F..\n    byteArray.push(str.charCodeAt(i) & 0xFF)\n  }\n  return byteArray\n}\n\nfunction utf16leToBytes (str, units) {\n  var c, hi, lo\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    if ((units -= 2) < 0) break\n\n    c = str.charCodeAt(i)\n    hi = c >> 8\n    lo = c % 256\n    byteArray.push(lo)\n    byteArray.push(hi)\n  }\n\n  return byteArray\n}\n\nfunction base64ToBytes (str) {\n  return base64.toByteArray(base64clean(str))\n}\n\nfunction blitBuffer (src, dst, offset, length) {\n  for (var i = 0; i < length; i++) {\n    if ((i + offset >= dst.length) || (i >= src.length)) break\n    dst[i + offset] = src[i]\n  }\n  return i\n}\n\n},{\"base64-js\":15,\"ieee754\":16,\"is-array\":17}],15:[function(require,module,exports){\nvar lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n;(function (exports) {\n\t'use strict';\n\n  var Arr = (typeof Uint8Array !== 'undefined')\n    ? Uint8Array\n    : Array\n\n\tvar PLUS   = '+'.charCodeAt(0)\n\tvar SLASH  = '/'.charCodeAt(0)\n\tvar NUMBER = '0'.charCodeAt(0)\n\tvar LOWER  = 'a'.charCodeAt(0)\n\tvar UPPER  = 'A'.charCodeAt(0)\n\tvar PLUS_URL_SAFE = '-'.charCodeAt(0)\n\tvar SLASH_URL_SAFE = '_'.charCodeAt(0)\n\n\tfunction decode (elt) {\n\t\tvar code = elt.charCodeAt(0)\n\t\tif (code === PLUS ||\n\t\t    code === PLUS_URL_SAFE)\n\t\t\treturn 62 // '+'\n\t\tif (code === SLASH ||\n\t\t    code === SLASH_URL_SAFE)\n\t\t\treturn 63 // '/'\n\t\tif (code < NUMBER)\n\t\t\treturn -1 //no match\n\t\tif (code < NUMBER + 10)\n\t\t\treturn code - NUMBER + 26 + 26\n\t\tif (code < UPPER + 26)\n\t\t\treturn code - UPPER\n\t\tif (code < LOWER + 26)\n\t\t\treturn code - LOWER + 26\n\t}\n\n\tfunction b64ToByteArray (b64) {\n\t\tvar i, j, l, tmp, placeHolders, arr\n\n\t\tif (b64.length % 4 > 0) {\n\t\t\tthrow new Error('Invalid string. Length must be a multiple of 4')\n\t\t}\n\n\t\t// the number of equal signs (place holders)\n\t\t// if there are two placeholders, than the two characters before it\n\t\t// represent one byte\n\t\t// if there is only one, then the three characters before it represent 2 bytes\n\t\t// this is just a cheap hack to not do indexOf twice\n\t\tvar len = b64.length\n\t\tplaceHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0\n\n\t\t// base64 is 4/3 + up to two characters of the original data\n\t\tarr = new Arr(b64.length * 3 / 4 - placeHolders)\n\n\t\t// if there are placeholders, only get up to the last complete 4 chars\n\t\tl = placeHolders > 0 ? b64.length - 4 : b64.length\n\n\t\tvar L = 0\n\n\t\tfunction push (v) {\n\t\t\tarr[L++] = v\n\t\t}\n\n\t\tfor (i = 0, j = 0; i < l; i += 4, j += 3) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))\n\t\t\tpush((tmp & 0xFF0000) >> 16)\n\t\t\tpush((tmp & 0xFF00) >> 8)\n\t\t\tpush(tmp & 0xFF)\n\t\t}\n\n\t\tif (placeHolders === 2) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)\n\t\t\tpush(tmp & 0xFF)\n\t\t} else if (placeHolders === 1) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)\n\t\t\tpush((tmp >> 8) & 0xFF)\n\t\t\tpush(tmp & 0xFF)\n\t\t}\n\n\t\treturn arr\n\t}\n\n\tfunction uint8ToBase64 (uint8) {\n\t\tvar i,\n\t\t\textraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes\n\t\t\toutput = \"\",\n\t\t\ttemp, length\n\n\t\tfunction encode (num) {\n\t\t\treturn lookup.charAt(num)\n\t\t}\n\n\t\tfunction tripletToBase64 (num) {\n\t\t\treturn encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)\n\t\t}\n\n\t\t// go through the array every three bytes, we'll deal with trailing stuff later\n\t\tfor (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {\n\t\t\ttemp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])\n\t\t\toutput += tripletToBase64(temp)\n\t\t}\n\n\t\t// pad the end with zeros, but make sure to not forget the extra bytes\n\t\tswitch (extraBytes) {\n\t\t\tcase 1:\n\t\t\t\ttemp = uint8[uint8.length - 1]\n\t\t\t\toutput += encode(temp >> 2)\n\t\t\t\toutput += encode((temp << 4) & 0x3F)\n\t\t\t\toutput += '=='\n\t\t\t\tbreak\n\t\t\tcase 2:\n\t\t\t\ttemp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])\n\t\t\t\toutput += encode(temp >> 10)\n\t\t\t\toutput += encode((temp >> 4) & 0x3F)\n\t\t\t\toutput += encode((temp << 2) & 0x3F)\n\t\t\t\toutput += '='\n\t\t\t\tbreak\n\t\t}\n\n\t\treturn output\n\t}\n\n\texports.toByteArray = b64ToByteArray\n\texports.fromByteArray = uint8ToBase64\n}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))\n\n},{}],16:[function(require,module,exports){\nexports.read = function (buffer, offset, isLE, mLen, nBytes) {\n  var e, m\n  var eLen = nBytes * 8 - mLen - 1\n  var eMax = (1 << eLen) - 1\n  var eBias = eMax >> 1\n  var nBits = -7\n  var i = isLE ? (nBytes - 1) : 0\n  var d = isLE ? -1 : 1\n  var s = buffer[offset + i]\n\n  i += d\n\n  e = s & ((1 << (-nBits)) - 1)\n  s >>= (-nBits)\n  nBits += eLen\n  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {}\n\n  m = e & ((1 << (-nBits)) - 1)\n  e >>= (-nBits)\n  nBits += mLen\n  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {}\n\n  if (e === 0) {\n    e = 1 - eBias\n  } else if (e === eMax) {\n    return m ? NaN : ((s ? -1 : 1) * Infinity)\n  } else {\n    m = m + Math.pow(2, mLen)\n    e = e - eBias\n  }\n  return (s ? -1 : 1) * m * Math.pow(2, e - mLen)\n}\n\nexports.write = function (buffer, value, offset, isLE, mLen, nBytes) {\n  var e, m, c\n  var eLen = nBytes * 8 - mLen - 1\n  var eMax = (1 << eLen) - 1\n  var eBias = eMax >> 1\n  var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)\n  var i = isLE ? 0 : (nBytes - 1)\n  var d = isLE ? 1 : -1\n  var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0\n\n  value = Math.abs(value)\n\n  if (isNaN(value) || value === Infinity) {\n    m = isNaN(value) ? 1 : 0\n    e = eMax\n  } else {\n    e = Math.floor(Math.log(value) / Math.LN2)\n    if (value * (c = Math.pow(2, -e)) < 1) {\n      e--\n      c *= 2\n    }\n    if (e + eBias >= 1) {\n      value += rt / c\n    } else {\n      value += rt * Math.pow(2, 1 - eBias)\n    }\n    if (value * c >= 2) {\n      e++\n      c /= 2\n    }\n\n    if (e + eBias >= eMax) {\n      m = 0\n      e = eMax\n    } else if (e + eBias >= 1) {\n      m = (value * c - 1) * Math.pow(2, mLen)\n      e = e + eBias\n    } else {\n      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen)\n      e = 0\n    }\n  }\n\n  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {}\n\n  e = (e << mLen) | m\n  eLen += mLen\n  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {}\n\n  buffer[offset + i - d] |= s * 128\n}\n\n},{}],17:[function(require,module,exports){\n\n/**\n * isArray\n */\n\nvar isArray = Array.isArray;\n\n/**\n * toString\n */\n\nvar str = Object.prototype.toString;\n\n/**\n * Whether or not the given `val`\n * is an array.\n *\n * example:\n *\n *        isArray([]);\n *        // > true\n *        isArray(arguments);\n *        // > false\n *        isArray('');\n *        // > false\n *\n * @param {mixed} val\n * @return {bool}\n */\n\nmodule.exports = isArray || function (val) {\n  return !! val && '[object Array]' == str.call(val);\n};\n\n},{}],18:[function(require,module,exports){\n/* jshint node: true */\n(function () {\n    \"use strict\";\n\n    function CookieAccessInfo(domain, path, secure, script) {\n        if (this instanceof CookieAccessInfo) {\n            this.domain = domain || undefined;\n            this.path = path || \"/\";\n            this.secure = !!secure;\n            this.script = !!script;\n            return this;\n        }\n        return new CookieAccessInfo(domain, path, secure, script);\n    }\n    exports.CookieAccessInfo = CookieAccessInfo;\n\n    function Cookie(cookiestr, request_domain, request_path) {\n        if (cookiestr instanceof Cookie) {\n            return cookiestr;\n        }\n        if (this instanceof Cookie) {\n            this.name = null;\n            this.value = null;\n            this.expiration_date = Infinity;\n            this.path = String(request_path || \"/\");\n            this.explicit_path = false;\n            this.domain = request_domain || null;\n            this.explicit_domain = false;\n            this.secure = false; //how to define default?\n            this.noscript = false; //httponly\n            if (cookiestr) {\n                this.parse(cookiestr, request_domain, request_path);\n            }\n            return this;\n        }\n        return new Cookie(cookiestr, request_domain, request_path);\n    }\n    exports.Cookie = Cookie;\n\n    Cookie.prototype.toString = function toString() {\n        var str = [this.name + \"=\" + this.value];\n        if (this.expiration_date !== Infinity) {\n            str.push(\"expires=\" + (new Date(this.expiration_date)).toGMTString());\n        }\n        if (this.domain) {\n            str.push(\"domain=\" + this.domain);\n        }\n        if (this.path) {\n            str.push(\"path=\" + this.path);\n        }\n        if (this.secure) {\n            str.push(\"secure\");\n        }\n        if (this.noscript) {\n            str.push(\"httponly\");\n        }\n        return str.join(\"; \");\n    };\n\n    Cookie.prototype.toValueString = function toValueString() {\n        return this.name + \"=\" + this.value;\n    };\n\n    var cookie_str_splitter = /[:](?=\\s*[a-zA-Z0-9_\\-]+\\s*[=])/g;\n    Cookie.prototype.parse = function parse(str, request_domain, request_path) {\n        if (this instanceof Cookie) {\n            var parts = str.split(\";\").filter(function (value) {\n                    return !!value;\n                }),\n                pair = parts[0].match(/([^=]+)=([\\s\\S]*)/),\n                key = pair[1],\n                value = pair[2],\n                i;\n            this.name = key;\n            this.value = value;\n\n            for (i = 1; i < parts.length; i += 1) {\n                pair = parts[i].match(/([^=]+)(?:=([\\s\\S]*))?/);\n                key = pair[1].trim().toLowerCase();\n                value = pair[2];\n                switch (key) {\n                case \"httponly\":\n                    this.noscript = true;\n                    break;\n                case \"expires\":\n                    this.expiration_date = value ?\n                            Number(Date.parse(value)) :\n                            Infinity;\n                    break;\n                case \"path\":\n                    this.path = value ?\n                            value.trim() :\n                            \"\";\n                    this.explicit_path = true;\n                    break;\n                case \"domain\":\n                    this.domain = value ?\n                            value.trim() :\n                            \"\";\n                    this.explicit_domain = !!this.domain;\n                    break;\n                case \"secure\":\n                    this.secure = true;\n                    break;\n                }\n            }\n\n            if (!this.explicit_path) {\n               this.path = request_path || \"/\";\n            }\n            if (!this.explicit_domain) {\n               this.domain = request_domain;\n            }\n\n            return this;\n        }\n        return new Cookie().parse(str, request_domain, request_path);\n    };\n\n    Cookie.prototype.matches = function matches(access_info) {\n        if (this.noscript && access_info.script ||\n                this.secure && !access_info.secure ||\n                !this.collidesWith(access_info)) {\n            return false;\n        }\n        return true;\n    };\n\n    Cookie.prototype.collidesWith = function collidesWith(access_info) {\n        if ((this.path && !access_info.path) || (this.domain && !access_info.domain)) {\n            return false;\n        }\n        if (this.path && access_info.path.indexOf(this.path) !== 0) {\n            return false;\n        }\n        if (this.explicit_path && access_info.path.indexOf( this.path ) !== 0) {\n           return false;\n        }\n        var access_domain = access_info.domain && access_info.domain.replace(/^[\\.]/,'');\n        var cookie_domain = this.domain && this.domain.replace(/^[\\.]/,'');\n        if (cookie_domain === access_domain) {\n            return true;\n        }\n        if (cookie_domain) {\n            if (!this.explicit_domain) {\n                return false; // we already checked if the domains were exactly the same\n            }\n            var wildcard = access_domain.indexOf(cookie_domain);\n            if (wildcard === -1 || wildcard !== access_domain.length - cookie_domain.length) {\n                return false;\n            }\n            return true;\n        }\n        return true;\n    };\n\n    function CookieJar() {\n        var cookies, cookies_list, collidable_cookie;\n        if (this instanceof CookieJar) {\n            cookies = Object.create(null); //name: [Cookie]\n\n            this.setCookie = function setCookie(cookie, request_domain, request_path) {\n                var remove, i;\n                cookie = new Cookie(cookie, request_domain, request_path);\n                //Delete the cookie if the set is past the current time\n                remove = cookie.expiration_date <= Date.now();\n                if (cookies[cookie.name] !== undefined) {\n                    cookies_list = cookies[cookie.name];\n                    for (i = 0; i < cookies_list.length; i += 1) {\n                        collidable_cookie = cookies_list[i];\n                        if (collidable_cookie.collidesWith(cookie)) {\n                            if (remove) {\n                                cookies_list.splice(i, 1);\n                                if (cookies_list.length === 0) {\n                                    delete cookies[cookie.name];\n                                }\n                                return false;\n                            }\n                            cookies_list[i] = cookie;\n                            return cookie;\n                        }\n                    }\n                    if (remove) {\n                        return false;\n                    }\n                    cookies_list.push(cookie);\n                    return cookie;\n                }\n                if (remove) {\n                    return false;\n                }\n                cookies[cookie.name] = [cookie];\n                return cookies[cookie.name];\n            };\n            //returns a cookie\n            this.getCookie = function getCookie(cookie_name, access_info) {\n                var cookie, i;\n                cookies_list = cookies[cookie_name];\n                if (!cookies_list) {\n                    return;\n                }\n                for (i = 0; i < cookies_list.length; i += 1) {\n                    cookie = cookies_list[i];\n                    if (cookie.expiration_date <= Date.now()) {\n                        if (cookies_list.length === 0) {\n                            delete cookies[cookie.name];\n                        }\n                        continue;\n                    }\n\n                    if (cookie.matches(access_info)) {\n                        return cookie;\n                    }\n                }\n            };\n            //returns a list of cookies\n            this.getCookies = function getCookies(access_info) {\n                var matches = [], cookie_name, cookie;\n                for (cookie_name in cookies) {\n                    cookie = this.getCookie(cookie_name, access_info);\n                    if (cookie) {\n                        matches.push(cookie);\n                    }\n                }\n                matches.toString = function toString() {\n                    return matches.join(\":\");\n                };\n                matches.toValueString = function toValueString() {\n                    return matches.map(function (c) {\n                        return c.toValueString();\n                    }).join(';');\n                };\n                return matches;\n            };\n\n            return this;\n        }\n        return new CookieJar();\n    }\n    exports.CookieJar = CookieJar;\n\n    //returns list of cookies that were set correctly. Cookies that are expired and removed are not returned.\n    CookieJar.prototype.setCookies = function setCookies(cookies, request_domain, request_path) {\n        cookies = Array.isArray(cookies) ?\n                cookies :\n                cookies.split(cookie_str_splitter);\n        var successful = [],\n            i,\n            cookie;\n        cookies = cookies.map(function(item){\n            return new Cookie(item, request_domain, request_path);\n        });\n        for (i = 0; i < cookies.length; i += 1) {\n            cookie = cookies[i];\n            if (this.setCookie(cookie, request_domain, request_path)) {\n                successful.push(cookie);\n            }\n        }\n        return successful;\n    };\n}());\n\n},{}],19:[function(require,module,exports){\n'use strict';\n\n\nvar yaml = require('./lib/js-yaml.js');\n\n\nmodule.exports = yaml;\n\n},{\"./lib/js-yaml.js\":20}],20:[function(require,module,exports){\n'use strict';\n\n\nvar loader = require('./js-yaml/loader');\nvar dumper = require('./js-yaml/dumper');\n\n\nfunction deprecated(name) {\n  return function () {\n    throw new Error('Function ' + name + ' is deprecated and cannot be used.');\n  };\n}\n\n\nmodule.exports.Type                = require('./js-yaml/type');\nmodule.exports.Schema              = require('./js-yaml/schema');\nmodule.exports.FAILSAFE_SCHEMA     = require('./js-yaml/schema/failsafe');\nmodule.exports.JSON_SCHEMA         = require('./js-yaml/schema/json');\nmodule.exports.CORE_SCHEMA         = require('./js-yaml/schema/core');\nmodule.exports.DEFAULT_SAFE_SCHEMA = require('./js-yaml/schema/default_safe');\nmodule.exports.DEFAULT_FULL_SCHEMA = require('./js-yaml/schema/default_full');\nmodule.exports.load                = loader.load;\nmodule.exports.loadAll             = loader.loadAll;\nmodule.exports.safeLoad            = loader.safeLoad;\nmodule.exports.safeLoadAll         = loader.safeLoadAll;\nmodule.exports.dump                = dumper.dump;\nmodule.exports.safeDump            = dumper.safeDump;\nmodule.exports.YAMLException       = require('./js-yaml/exception');\n\n// Deprecated schema names from JS-YAML 2.0.x\nmodule.exports.MINIMAL_SCHEMA = require('./js-yaml/schema/failsafe');\nmodule.exports.SAFE_SCHEMA    = require('./js-yaml/schema/default_safe');\nmodule.exports.DEFAULT_SCHEMA = require('./js-yaml/schema/default_full');\n\n// Deprecated functions from JS-YAML 1.x.x\nmodule.exports.scan           = deprecated('scan');\nmodule.exports.parse          = deprecated('parse');\nmodule.exports.compose        = deprecated('compose');\nmodule.exports.addConstructor = deprecated('addConstructor');\n\n},{\"./js-yaml/dumper\":22,\"./js-yaml/exception\":23,\"./js-yaml/loader\":24,\"./js-yaml/schema\":26,\"./js-yaml/schema/core\":27,\"./js-yaml/schema/default_full\":28,\"./js-yaml/schema/default_safe\":29,\"./js-yaml/schema/failsafe\":30,\"./js-yaml/schema/json\":31,\"./js-yaml/type\":32}],21:[function(require,module,exports){\n'use strict';\n\n\nfunction isNothing(subject) {\n  return (typeof subject === 'undefined') || (subject === null);\n}\n\n\nfunction isObject(subject) {\n  return (typeof subject === 'object') && (subject !== null);\n}\n\n\nfunction toArray(sequence) {\n  if (Array.isArray(sequence)) return sequence;\n  else if (isNothing(sequence)) return [];\n\n  return [ sequence ];\n}\n\n\nfunction extend(target, source) {\n  var index, length, key, sourceKeys;\n\n  if (source) {\n    sourceKeys = Object.keys(source);\n\n    for (index = 0, length = sourceKeys.length; index < length; index += 1) {\n      key = sourceKeys[index];\n      target[key] = source[key];\n    }\n  }\n\n  return target;\n}\n\n\nfunction repeat(string, count) {\n  var result = '', cycle;\n\n  for (cycle = 0; cycle < count; cycle += 1) {\n    result += string;\n  }\n\n  return result;\n}\n\n\nfunction isNegativeZero(number) {\n  return (number === 0) && (Number.NEGATIVE_INFINITY === 1 / number);\n}\n\n\nmodule.exports.isNothing      = isNothing;\nmodule.exports.isObject       = isObject;\nmodule.exports.toArray        = toArray;\nmodule.exports.repeat         = repeat;\nmodule.exports.isNegativeZero = isNegativeZero;\nmodule.exports.extend         = extend;\n\n},{}],22:[function(require,module,exports){\n'use strict';\n\n/*eslint-disable no-use-before-define*/\n\nvar common              = require('./common');\nvar YAMLException       = require('./exception');\nvar DEFAULT_FULL_SCHEMA = require('./schema/default_full');\nvar DEFAULT_SAFE_SCHEMA = require('./schema/default_safe');\n\nvar _toString       = Object.prototype.toString;\nvar _hasOwnProperty = Object.prototype.hasOwnProperty;\n\nvar CHAR_TAB                  = 0x09; /* Tab */\nvar CHAR_LINE_FEED            = 0x0A; /* LF */\nvar CHAR_SPACE                = 0x20; /* Space */\nvar CHAR_EXCLAMATION          = 0x21; /* ! */\nvar CHAR_DOUBLE_QUOTE         = 0x22; /* \" */\nvar CHAR_SHARP                = 0x23; /* # */\nvar CHAR_PERCENT              = 0x25; /* % */\nvar CHAR_AMPERSAND            = 0x26; /* & */\nvar CHAR_SINGLE_QUOTE         = 0x27; /* ' */\nvar CHAR_ASTERISK             = 0x2A; /* * */\nvar CHAR_COMMA                = 0x2C; /* , */\nvar CHAR_MINUS                = 0x2D; /* - */\nvar CHAR_COLON                = 0x3A; /* : */\nvar CHAR_GREATER_THAN         = 0x3E; /* > */\nvar CHAR_QUESTION             = 0x3F; /* ? */\nvar CHAR_COMMERCIAL_AT        = 0x40; /* @ */\nvar CHAR_LEFT_SQUARE_BRACKET  = 0x5B; /* [ */\nvar CHAR_RIGHT_SQUARE_BRACKET = 0x5D; /* ] */\nvar CHAR_GRAVE_ACCENT         = 0x60; /* ` */\nvar CHAR_LEFT_CURLY_BRACKET   = 0x7B; /* { */\nvar CHAR_VERTICAL_LINE        = 0x7C; /* | */\nvar CHAR_RIGHT_CURLY_BRACKET  = 0x7D; /* } */\n\nvar ESCAPE_SEQUENCES = {};\n\nESCAPE_SEQUENCES[0x00]   = '\\\\0';\nESCAPE_SEQUENCES[0x07]   = '\\\\a';\nESCAPE_SEQUENCES[0x08]   = '\\\\b';\nESCAPE_SEQUENCES[0x09]   = '\\\\t';\nESCAPE_SEQUENCES[0x0A]   = '\\\\n';\nESCAPE_SEQUENCES[0x0B]   = '\\\\v';\nESCAPE_SEQUENCES[0x0C]   = '\\\\f';\nESCAPE_SEQUENCES[0x0D]   = '\\\\r';\nESCAPE_SEQUENCES[0x1B]   = '\\\\e';\nESCAPE_SEQUENCES[0x22]   = '\\\\\"';\nESCAPE_SEQUENCES[0x5C]   = '\\\\\\\\';\nESCAPE_SEQUENCES[0x85]   = '\\\\N';\nESCAPE_SEQUENCES[0xA0]   = '\\\\_';\nESCAPE_SEQUENCES[0x2028] = '\\\\L';\nESCAPE_SEQUENCES[0x2029] = '\\\\P';\n\nvar DEPRECATED_BOOLEANS_SYNTAX = [\n  'y', 'Y', 'yes', 'Yes', 'YES', 'on', 'On', 'ON',\n  'n', 'N', 'no', 'No', 'NO', 'off', 'Off', 'OFF'\n];\n\nfunction compileStyleMap(schema, map) {\n  var result, keys, index, length, tag, style, type;\n\n  if (map === null) return {};\n\n  result = {};\n  keys = Object.keys(map);\n\n  for (index = 0, length = keys.length; index < length; index += 1) {\n    tag = keys[index];\n    style = String(map[tag]);\n\n    if (tag.slice(0, 2) === '!!') {\n      tag = 'tag:yaml.org,2002:' + tag.slice(2);\n    }\n\n    type = schema.compiledTypeMap[tag];\n\n    if (type && _hasOwnProperty.call(type.styleAliases, style)) {\n      style = type.styleAliases[style];\n    }\n\n    result[tag] = style;\n  }\n\n  return result;\n}\n\nfunction encodeHex(character) {\n  var string, handle, length;\n\n  string = character.toString(16).toUpperCase();\n\n  if (character <= 0xFF) {\n    handle = 'x';\n    length = 2;\n  } else if (character <= 0xFFFF) {\n    handle = 'u';\n    length = 4;\n  } else if (character <= 0xFFFFFFFF) {\n    handle = 'U';\n    length = 8;\n  } else {\n    throw new YAMLException('code point within a string may not be greater than 0xFFFFFFFF');\n  }\n\n  return '\\\\' + handle + common.repeat('0', length - string.length) + string;\n}\n\nfunction State(options) {\n  this.schema       = options['schema'] || DEFAULT_FULL_SCHEMA;\n  this.indent       = Math.max(1, (options['indent'] || 2));\n  this.skipInvalid  = options['skipInvalid'] || false;\n  this.flowLevel    = (common.isNothing(options['flowLevel']) ? -1 : options['flowLevel']);\n  this.styleMap     = compileStyleMap(this.schema, options['styles'] || null);\n  this.sortKeys     = options['sortKeys'] || false;\n  this.lineWidth    = options['lineWidth'] || 80;\n  this.noRefs       = options['noRefs'] || false;\n  this.noCompatMode = options['noCompatMode'] || false;\n\n  this.implicitTypes = this.schema.compiledImplicit;\n  this.explicitTypes = this.schema.compiledExplicit;\n\n  this.tag = null;\n  this.result = '';\n\n  this.duplicates = [];\n  this.usedDuplicates = null;\n}\n\n// Indents every line in a string. Empty lines (\\n only) are not indented.\nfunction indentString(string, spaces) {\n  var ind = common.repeat(' ', spaces),\n      position = 0,\n      next = -1,\n      result = '',\n      line,\n      length = string.length;\n\n  while (position < length) {\n    next = string.indexOf('\\n', position);\n    if (next === -1) {\n      line = string.slice(position);\n      position = length;\n    } else {\n      line = string.slice(position, next + 1);\n      position = next + 1;\n    }\n\n    if (line.length && line !== '\\n') result += ind;\n\n    result += line;\n  }\n\n  return result;\n}\n\nfunction generateNextLine(state, level) {\n  return '\\n' + common.repeat(' ', state.indent * level);\n}\n\nfunction testImplicitResolving(state, str) {\n  var index, length, type;\n\n  for (index = 0, length = state.implicitTypes.length; index < length; index += 1) {\n    type = state.implicitTypes[index];\n\n    if (type.resolve(str)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\n// [33] s-white ::= s-space | s-tab\nfunction isWhitespace(c) {\n  return c === CHAR_SPACE || c === CHAR_TAB;\n}\n\n// Returns true if the character can be printed without escaping.\n// From YAML 1.2: \"any allowed characters known to be non-printable\n// should also be escaped. [However,] This isn’t mandatory\"\n// Derived from nb-char - \\t - #x85 - #xA0 - #x2028 - #x2029.\nfunction isPrintable(c) {\n  return  (0x00020 <= c && c <= 0x00007E)\n      || ((0x000A1 <= c && c <= 0x00D7FF) && c !== 0x2028 && c !== 0x2029)\n      || ((0x0E000 <= c && c <= 0x00FFFD) && c !== 0xFEFF /* BOM */)\n      ||  (0x10000 <= c && c <= 0x10FFFF);\n}\n\n// Simplified test for values allowed after the first character in plain style.\nfunction isPlainSafe(c) {\n  // Uses a subset of nb-char - c-flow-indicator - \":\" - \"#\"\n  // where nb-char ::= c-printable - b-char - c-byte-order-mark.\n  return isPrintable(c) && c !== 0xFEFF\n    // - c-flow-indicator\n    && c !== CHAR_COMMA\n    && c !== CHAR_LEFT_SQUARE_BRACKET\n    && c !== CHAR_RIGHT_SQUARE_BRACKET\n    && c !== CHAR_LEFT_CURLY_BRACKET\n    && c !== CHAR_RIGHT_CURLY_BRACKET\n    // - \":\" - \"#\"\n    && c !== CHAR_COLON\n    && c !== CHAR_SHARP;\n}\n\n// Simplified test for values allowed as the first character in plain style.\nfunction isPlainSafeFirst(c) {\n  // Uses a subset of ns-char - c-indicator\n  // where ns-char = nb-char - s-white.\n  return isPrintable(c) && c !== 0xFEFF\n    && !isWhitespace(c) // - s-white\n    // - (c-indicator ::=\n    // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”\n    && c !== CHAR_MINUS\n    && c !== CHAR_QUESTION\n    && c !== CHAR_COLON\n    && c !== CHAR_COMMA\n    && c !== CHAR_LEFT_SQUARE_BRACKET\n    && c !== CHAR_RIGHT_SQUARE_BRACKET\n    && c !== CHAR_LEFT_CURLY_BRACKET\n    && c !== CHAR_RIGHT_CURLY_BRACKET\n    // | “#” | “&” | “*” | “!” | “|” | “>” | “'” | “\"”\n    && c !== CHAR_SHARP\n    && c !== CHAR_AMPERSAND\n    && c !== CHAR_ASTERISK\n    && c !== CHAR_EXCLAMATION\n    && c !== CHAR_VERTICAL_LINE\n    && c !== CHAR_GREATER_THAN\n    && c !== CHAR_SINGLE_QUOTE\n    && c !== CHAR_DOUBLE_QUOTE\n    // | “%” | “@” | “`”)\n    && c !== CHAR_PERCENT\n    && c !== CHAR_COMMERCIAL_AT\n    && c !== CHAR_GRAVE_ACCENT;\n}\n\nvar STYLE_PLAIN   = 1,\n    STYLE_SINGLE  = 2,\n    STYLE_LITERAL = 3,\n    STYLE_FOLDED  = 4,\n    STYLE_DOUBLE  = 5;\n\n// Determines which scalar styles are possible and returns the preferred style.\n// lineWidth = -1 => no limit.\n// Pre-conditions: str.length > 0.\n// Post-conditions:\n//    STYLE_PLAIN or STYLE_SINGLE => no \\n are in the string.\n//    STYLE_LITERAL => no lines are suitable for folding (or lineWidth is -1).\n//    STYLE_FOLDED => a line > lineWidth and can be folded (and lineWidth != -1).\nfunction chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType) {\n  var i;\n  var char;\n  var hasLineBreak = false;\n  var hasFoldableLine = false; // only checked if shouldTrackWidth\n  var shouldTrackWidth = lineWidth !== -1;\n  var previousLineBreak = -1; // count the first line correctly\n  var plain = isPlainSafeFirst(string.charCodeAt(0))\n          && !isWhitespace(string.charCodeAt(string.length - 1));\n\n  if (singleLineOnly) {\n    // Case: no block styles.\n    // Check for disallowed characters to rule out plain and single.\n    for (i = 0; i < string.length; i++) {\n      char = string.charCodeAt(i);\n      if (!isPrintable(char)) {\n        return STYLE_DOUBLE;\n      }\n      plain = plain && isPlainSafe(char);\n    }\n  } else {\n    // Case: block styles permitted.\n    for (i = 0; i < string.length; i++) {\n      char = string.charCodeAt(i);\n      if (char === CHAR_LINE_FEED) {\n        hasLineBreak = true;\n        // Check if any line can be folded.\n        if (shouldTrackWidth) {\n          hasFoldableLine = hasFoldableLine ||\n            // Foldable line = too long, and not more-indented.\n            (i - previousLineBreak - 1 > lineWidth &&\n             string[previousLineBreak + 1] !== ' ');\n          previousLineBreak = i;\n        }\n      } else if (!isPrintable(char)) {\n        return STYLE_DOUBLE;\n      }\n      plain = plain && isPlainSafe(char);\n    }\n    // in case the end is missing a \\n\n    hasFoldableLine = hasFoldableLine || (shouldTrackWidth &&\n      (i - previousLineBreak - 1 > lineWidth &&\n       string[previousLineBreak + 1] !== ' '));\n  }\n  // Although every style can represent \\n without escaping, prefer block styles\n  // for multiline, since they're more readable and they don't add empty lines.\n  // Also prefer folding a super-long line.\n  if (!hasLineBreak && !hasFoldableLine) {\n    // Strings interpretable as another type have to be quoted;\n    // e.g. the string 'true' vs. the boolean true.\n    return plain && !testAmbiguousType(string)\n      ? STYLE_PLAIN : STYLE_SINGLE;\n  }\n  // Edge case: block indentation indicator can only have one digit.\n  if (string[0] === ' ' && indentPerLevel > 9) {\n    return STYLE_DOUBLE;\n  }\n  // At this point we know block styles are valid.\n  // Prefer literal style unless we want to fold.\n  return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;\n}\n\n// Note: line breaking/folding is implemented for only the folded style.\n// NB. We drop the last trailing newline (if any) of a returned block scalar\n//  since the dumper adds its own newline. This always works:\n//    • No ending newline => unaffected; already using strip \"-\" chomping.\n//    • Ending newline    => removed then restored.\n//  Importantly, this keeps the \"+\" chomp indicator from gaining an extra line.\nfunction writeScalar(state, string, level, iskey) {\n  state.dump = (function () {\n    if (string.length === 0) {\n      return \"''\";\n    }\n    if (!state.noCompatMode &&\n        DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1) {\n      return \"'\" + string + \"'\";\n    }\n\n    var indent = state.indent * Math.max(1, level); // no 0-indent scalars\n    // As indentation gets deeper, let the width decrease monotonically\n    // to the lower bound min(state.lineWidth, 40).\n    // Note that this implies\n    //  state.lineWidth ≤ 40 + state.indent: width is fixed at the lower bound.\n    //  state.lineWidth > 40 + state.indent: width decreases until the lower bound.\n    // This behaves better than a constant minimum width which disallows narrower options,\n    // or an indent threshold which causes the width to suddenly increase.\n    var lineWidth = state.lineWidth === -1\n      ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);\n\n    // Without knowing if keys are implicit/explicit, assume implicit for safety.\n    var singleLineOnly = iskey\n      // No block styles in flow mode.\n      || (state.flowLevel > -1 && level >= state.flowLevel);\n    function testAmbiguity(string) {\n      return testImplicitResolving(state, string);\n    }\n\n    switch (chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity)) {\n      case STYLE_PLAIN:\n        return string;\n      case STYLE_SINGLE:\n        return \"'\" + string.replace(/'/g, \"''\") + \"'\";\n      case STYLE_LITERAL:\n        return '|' + blockHeader(string, state.indent)\n          + dropEndingNewline(indentString(string, indent));\n      case STYLE_FOLDED:\n        return '>' + blockHeader(string, state.indent)\n          + dropEndingNewline(indentString(foldString(string, lineWidth), indent));\n      case STYLE_DOUBLE:\n        return '\"' + escapeString(string, lineWidth) + '\"';\n      default:\n        throw new YAMLException('impossible error: invalid scalar style');\n    }\n  }());\n}\n\n// Pre-conditions: string is valid for a block scalar, 1 <= indentPerLevel <= 9.\nfunction blockHeader(string, indentPerLevel) {\n  var indentIndicator = (string[0] === ' ') ? String(indentPerLevel) : '';\n\n  // note the special case: the string '\\n' counts as a \"trailing\" empty line.\n  var clip =          string[string.length - 1] === '\\n';\n  var keep = clip && (string[string.length - 2] === '\\n' || string === '\\n');\n  var chomp = keep ? '+' : (clip ? '' : '-');\n\n  return indentIndicator + chomp + '\\n';\n}\n\n// (See the note for writeScalar.)\nfunction dropEndingNewline(string) {\n  return string[string.length - 1] === '\\n' ? string.slice(0, -1) : string;\n}\n\n// Note: a long line without a suitable break point will exceed the width limit.\n// Pre-conditions: every char in str isPrintable, str.length > 0, width > 0.\nfunction foldString(string, width) {\n  // In folded style, $k$ consecutive newlines output as $k+1$ newlines—\n  // unless they're before or after a more-indented line, or at the very\n  // beginning or end, in which case $k$ maps to $k$.\n  // Therefore, parse each chunk as newline(s) followed by a content line.\n  var lineRe = /(\\n+)([^\\n]*)/g;\n\n  // first line (possibly an empty line)\n  var result = (function () {\n    var nextLF = string.indexOf('\\n');\n    nextLF = nextLF !== -1 ? nextLF : string.length;\n    lineRe.lastIndex = nextLF;\n    return foldLine(string.slice(0, nextLF), width);\n  }());\n  // If we haven't reached the first content line yet, don't add an extra \\n.\n  var prevMoreIndented = string[0] === '\\n' || string[0] === ' ';\n  var moreIndented;\n\n  // rest of the lines\n  var match;\n  while ((match = lineRe.exec(string))) {\n    var prefix = match[1], line = match[2];\n    moreIndented = (line[0] === ' ');\n    result += prefix\n      + (!prevMoreIndented && !moreIndented && line !== ''\n        ? '\\n' : '')\n      + foldLine(line, width);\n    prevMoreIndented = moreIndented;\n  }\n\n  return result;\n}\n\n// Greedy line breaking.\n// Picks the longest line under the limit each time,\n// otherwise settles for the shortest line over the limit.\n// NB. More-indented lines *cannot* be folded, as that would add an extra \\n.\nfunction foldLine(line, width) {\n  if (line === '' || line[0] === ' ') return line;\n\n  // Since a more-indented line adds a \\n, breaks can't be followed by a space.\n  var breakRe = / [^ ]/g; // note: the match index will always be <= length-2.\n  var match;\n  // start is an inclusive index. end, curr, and next are exclusive.\n  var start = 0, end, curr = 0, next = 0;\n  var result = '';\n\n  // Invariants: 0 <= start <= length-1.\n  //   0 <= curr <= next <= max(0, length-2). curr - start <= width.\n  // Inside the loop:\n  //   A match implies length >= 2, so curr and next are <= length-2.\n  while ((match = breakRe.exec(line))) {\n    next = match.index;\n    // maintain invariant: curr - start <= width\n    if (next - start > width) {\n      end = (curr > start) ? curr : next; // derive end <= length-2\n      result += '\\n' + line.slice(start, end);\n      // skip the space that was output as \\n\n      start = end + 1;                    // derive start <= length-1\n    }\n    curr = next;\n  }\n\n  // By the invariants, start <= length-1, so there is something left over.\n  // It is either the whole string or a part starting from non-whitespace.\n  result += '\\n';\n  // Insert a break if the remainder is too long and there is a break available.\n  if (line.length - start > width && curr > start) {\n    result += line.slice(start, curr) + '\\n' + line.slice(curr + 1);\n  } else {\n    result += line.slice(start);\n  }\n\n  return result.slice(1); // drop extra \\n joiner\n}\n\n// Escapes a double-quoted string.\nfunction escapeString(string) {\n  var result = '';\n  var char;\n  var escapeSeq;\n\n  for (var i = 0; i < string.length; i++) {\n    char = string.charCodeAt(i);\n    escapeSeq = ESCAPE_SEQUENCES[char];\n    result += !escapeSeq && isPrintable(char)\n      ? string[i]\n      : escapeSeq || encodeHex(char);\n  }\n\n  return result;\n}\n\nfunction writeFlowSequence(state, level, object) {\n  var _result = '',\n      _tag    = state.tag,\n      index,\n      length;\n\n  for (index = 0, length = object.length; index < length; index += 1) {\n    // Write only valid elements.\n    if (writeNode(state, level, object[index], false, false)) {\n      if (index !== 0) _result += ', ';\n      _result += state.dump;\n    }\n  }\n\n  state.tag = _tag;\n  state.dump = '[' + _result + ']';\n}\n\nfunction writeBlockSequence(state, level, object, compact) {\n  var _result = '',\n      _tag    = state.tag,\n      index,\n      length;\n\n  for (index = 0, length = object.length; index < length; index += 1) {\n    // Write only valid elements.\n    if (writeNode(state, level + 1, object[index], true, true)) {\n      if (!compact || index !== 0) {\n        _result += generateNextLine(state, level);\n      }\n      _result += '- ' + state.dump;\n    }\n  }\n\n  state.tag = _tag;\n  state.dump = _result || '[]'; // Empty sequence if no valid values.\n}\n\nfunction writeFlowMapping(state, level, object) {\n  var _result       = '',\n      _tag          = state.tag,\n      objectKeyList = Object.keys(object),\n      index,\n      length,\n      objectKey,\n      objectValue,\n      pairBuffer;\n\n  for (index = 0, length = objectKeyList.length; index < length; index += 1) {\n    pairBuffer = '';\n\n    if (index !== 0) pairBuffer += ', ';\n\n    objectKey = objectKeyList[index];\n    objectValue = object[objectKey];\n\n    if (!writeNode(state, level, objectKey, false, false)) {\n      continue; // Skip this pair because of invalid key;\n    }\n\n    if (state.dump.length > 1024) pairBuffer += '? ';\n\n    pairBuffer += state.dump + ': ';\n\n    if (!writeNode(state, level, objectValue, false, false)) {\n      continue; // Skip this pair because of invalid value.\n    }\n\n    pairBuffer += state.dump;\n\n    // Both key and value are valid.\n    _result += pairBuffer;\n  }\n\n  state.tag = _tag;\n  state.dump = '{' + _result + '}';\n}\n\nfunction writeBlockMapping(state, level, object, compact) {\n  var _result       = '',\n      _tag          = state.tag,\n      objectKeyList = Object.keys(object),\n      index,\n      length,\n      objectKey,\n      objectValue,\n      explicitPair,\n      pairBuffer;\n\n  // Allow sorting keys so that the output file is deterministic\n  if (state.sortKeys === true) {\n    // Default sorting\n    objectKeyList.sort();\n  } else if (typeof state.sortKeys === 'function') {\n    // Custom sort function\n    objectKeyList.sort(state.sortKeys);\n  } else if (state.sortKeys) {\n    // Something is wrong\n    throw new YAMLException('sortKeys must be a boolean or a function');\n  }\n\n  for (index = 0, length = objectKeyList.length; index < length; index += 1) {\n    pairBuffer = '';\n\n    if (!compact || index !== 0) {\n      pairBuffer += generateNextLine(state, level);\n    }\n\n    objectKey = objectKeyList[index];\n    objectValue = object[objectKey];\n\n    if (!writeNode(state, level + 1, objectKey, true, true, true)) {\n      continue; // Skip this pair because of invalid key.\n    }\n\n    explicitPair = (state.tag !== null && state.tag !== '?') ||\n                   (state.dump && state.dump.length > 1024);\n\n    if (explicitPair) {\n      if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n        pairBuffer += '?';\n      } else {\n        pairBuffer += '? ';\n      }\n    }\n\n    pairBuffer += state.dump;\n\n    if (explicitPair) {\n      pairBuffer += generateNextLine(state, level);\n    }\n\n    if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {\n      continue; // Skip this pair because of invalid value.\n    }\n\n    if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {\n      pairBuffer += ':';\n    } else {\n      pairBuffer += ': ';\n    }\n\n    pairBuffer += state.dump;\n\n    // Both key and value are valid.\n    _result += pairBuffer;\n  }\n\n  state.tag = _tag;\n  state.dump = _result || '{}'; // Empty mapping if no valid pairs.\n}\n\nfunction detectType(state, object, explicit) {\n  var _result, typeList, index, length, type, style;\n\n  typeList = explicit ? state.explicitTypes : state.implicitTypes;\n\n  for (index = 0, length = typeList.length; index < length; index += 1) {\n    type = typeList[index];\n\n    if ((type.instanceOf  || type.predicate) &&\n        (!type.instanceOf || ((typeof object === 'object') && (object instanceof type.instanceOf))) &&\n        (!type.predicate  || type.predicate(object))) {\n\n      state.tag = explicit ? type.tag : '?';\n\n      if (type.represent) {\n        style = state.styleMap[type.tag] || type.defaultStyle;\n\n        if (_toString.call(type.represent) === '[object Function]') {\n          _result = type.represent(object, style);\n        } else if (_hasOwnProperty.call(type.represent, style)) {\n          _result = type.represent[style](object, style);\n        } else {\n          throw new YAMLException('!<' + type.tag + '> tag resolver accepts not \"' + style + '\" style');\n        }\n\n        state.dump = _result;\n      }\n\n      return true;\n    }\n  }\n\n  return false;\n}\n\n// Serializes `object` and writes it to global `result`.\n// Returns true on success, or false on invalid object.\n//\nfunction writeNode(state, level, object, block, compact, iskey) {\n  state.tag = null;\n  state.dump = object;\n\n  if (!detectType(state, object, false)) {\n    detectType(state, object, true);\n  }\n\n  var type = _toString.call(state.dump);\n\n  if (block) {\n    block = (state.flowLevel < 0 || state.flowLevel > level);\n  }\n\n  var objectOrArray = type === '[object Object]' || type === '[object Array]',\n      duplicateIndex,\n      duplicate;\n\n  if (objectOrArray) {\n    duplicateIndex = state.duplicates.indexOf(object);\n    duplicate = duplicateIndex !== -1;\n  }\n\n  if ((state.tag !== null && state.tag !== '?') || duplicate || (state.indent !== 2 && level > 0)) {\n    compact = false;\n  }\n\n  if (duplicate && state.usedDuplicates[duplicateIndex]) {\n    state.dump = '*ref_' + duplicateIndex;\n  } else {\n    if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {\n      state.usedDuplicates[duplicateIndex] = true;\n    }\n    if (type === '[object Object]') {\n      if (block && (Object.keys(state.dump).length !== 0)) {\n        writeBlockMapping(state, level, state.dump, compact);\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + state.dump;\n        }\n      } else {\n        writeFlowMapping(state, level, state.dump);\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;\n        }\n      }\n    } else if (type === '[object Array]') {\n      if (block && (state.dump.length !== 0)) {\n        writeBlockSequence(state, level, state.dump, compact);\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + state.dump;\n        }\n      } else {\n        writeFlowSequence(state, level, state.dump);\n        if (duplicate) {\n          state.dump = '&ref_' + duplicateIndex + ' ' + state.dump;\n        }\n      }\n    } else if (type === '[object String]') {\n      if (state.tag !== '?') {\n        writeScalar(state, state.dump, level, iskey);\n      }\n    } else {\n      if (state.skipInvalid) return false;\n      throw new YAMLException('unacceptable kind of an object to dump ' + type);\n    }\n\n    if (state.tag !== null && state.tag !== '?') {\n      state.dump = '!<' + state.tag + '> ' + state.dump;\n    }\n  }\n\n  return true;\n}\n\nfunction getDuplicateReferences(object, state) {\n  var objects = [],\n      duplicatesIndexes = [],\n      index,\n      length;\n\n  inspectNode(object, objects, duplicatesIndexes);\n\n  for (index = 0, length = duplicatesIndexes.length; index < length; index += 1) {\n    state.duplicates.push(objects[duplicatesIndexes[index]]);\n  }\n  state.usedDuplicates = new Array(length);\n}\n\nfunction inspectNode(object, objects, duplicatesIndexes) {\n  var objectKeyList,\n      index,\n      length;\n\n  if (object !== null && typeof object === 'object') {\n    index = objects.indexOf(object);\n    if (index !== -1) {\n      if (duplicatesIndexes.indexOf(index) === -1) {\n        duplicatesIndexes.push(index);\n      }\n    } else {\n      objects.push(object);\n\n      if (Array.isArray(object)) {\n        for (index = 0, length = object.length; index < length; index += 1) {\n          inspectNode(object[index], objects, duplicatesIndexes);\n        }\n      } else {\n        objectKeyList = Object.keys(object);\n\n        for (index = 0, length = objectKeyList.length; index < length; index += 1) {\n          inspectNode(object[objectKeyList[index]], objects, duplicatesIndexes);\n        }\n      }\n    }\n  }\n}\n\nfunction dump(input, options) {\n  options = options || {};\n\n  var state = new State(options);\n\n  if (!state.noRefs) getDuplicateReferences(input, state);\n\n  if (writeNode(state, 0, input, true, true)) return state.dump + '\\n';\n\n  return '';\n}\n\nfunction safeDump(input, options) {\n  return dump(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));\n}\n\nmodule.exports.dump     = dump;\nmodule.exports.safeDump = safeDump;\n\n},{\"./common\":21,\"./exception\":23,\"./schema/default_full\":28,\"./schema/default_safe\":29}],23:[function(require,module,exports){\n// YAML error class. http://stackoverflow.com/questions/8458984\n//\n'use strict';\n\nfunction YAMLException(reason, mark) {\n  // Super constructor\n  Error.call(this);\n\n  // Include stack trace in error object\n  if (Error.captureStackTrace) {\n    // Chrome and NodeJS\n    Error.captureStackTrace(this, this.constructor);\n  } else {\n    // FF, IE 10+ and Safari 6+. Fallback for others\n    this.stack = (new Error()).stack || '';\n  }\n\n  this.name = 'YAMLException';\n  this.reason = reason;\n  this.mark = mark;\n  this.message = (this.reason || '(unknown reason)') + (this.mark ? ' ' + this.mark.toString() : '');\n}\n\n\n// Inherit from Error\nYAMLException.prototype = Object.create(Error.prototype);\nYAMLException.prototype.constructor = YAMLException;\n\n\nYAMLException.prototype.toString = function toString(compact) {\n  var result = this.name + ': ';\n\n  result += this.reason || '(unknown reason)';\n\n  if (!compact && this.mark) {\n    result += ' ' + this.mark.toString();\n  }\n\n  return result;\n};\n\n\nmodule.exports = YAMLException;\n\n},{}],24:[function(require,module,exports){\n'use strict';\n\n/*eslint-disable max-len,no-use-before-define*/\n\nvar common              = require('./common');\nvar YAMLException       = require('./exception');\nvar Mark                = require('./mark');\nvar DEFAULT_SAFE_SCHEMA = require('./schema/default_safe');\nvar DEFAULT_FULL_SCHEMA = require('./schema/default_full');\n\n\nvar _hasOwnProperty = Object.prototype.hasOwnProperty;\n\n\nvar CONTEXT_FLOW_IN   = 1;\nvar CONTEXT_FLOW_OUT  = 2;\nvar CONTEXT_BLOCK_IN  = 3;\nvar CONTEXT_BLOCK_OUT = 4;\n\n\nvar CHOMPING_CLIP  = 1;\nvar CHOMPING_STRIP = 2;\nvar CHOMPING_KEEP  = 3;\n\n\nvar PATTERN_NON_PRINTABLE         = /[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F-\\x84\\x86-\\x9F\\uFFFE\\uFFFF]|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?:[^\\uD800-\\uDBFF]|^)[\\uDC00-\\uDFFF]/;\nvar PATTERN_NON_ASCII_LINE_BREAKS = /[\\x85\\u2028\\u2029]/;\nvar PATTERN_FLOW_INDICATORS       = /[,\\[\\]\\{\\}]/;\nvar PATTERN_TAG_HANDLE            = /^(?:!|!!|![a-z\\-]+!)$/i;\nvar PATTERN_TAG_URI               = /^(?:!|[^,\\[\\]\\{\\}])(?:%[0-9a-f]{2}|[0-9a-z\\-#;\\/\\?:@&=\\+\\$,_\\.!~\\*'\\(\\)\\[\\]])*$/i;\n\n\nfunction is_EOL(c) {\n  return (c === 0x0A/* LF */) || (c === 0x0D/* CR */);\n}\n\nfunction is_WHITE_SPACE(c) {\n  return (c === 0x09/* Tab */) || (c === 0x20/* Space */);\n}\n\nfunction is_WS_OR_EOL(c) {\n  return (c === 0x09/* Tab */) ||\n         (c === 0x20/* Space */) ||\n         (c === 0x0A/* LF */) ||\n         (c === 0x0D/* CR */);\n}\n\nfunction is_FLOW_INDICATOR(c) {\n  return c === 0x2C/* , */ ||\n         c === 0x5B/* [ */ ||\n         c === 0x5D/* ] */ ||\n         c === 0x7B/* { */ ||\n         c === 0x7D/* } */;\n}\n\nfunction fromHexCode(c) {\n  var lc;\n\n  if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {\n    return c - 0x30;\n  }\n\n  /*eslint-disable no-bitwise*/\n  lc = c | 0x20;\n\n  if ((0x61/* a */ <= lc) && (lc <= 0x66/* f */)) {\n    return lc - 0x61 + 10;\n  }\n\n  return -1;\n}\n\nfunction escapedHexLen(c) {\n  if (c === 0x78/* x */) { return 2; }\n  if (c === 0x75/* u */) { return 4; }\n  if (c === 0x55/* U */) { return 8; }\n  return 0;\n}\n\nfunction fromDecimalCode(c) {\n  if ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) {\n    return c - 0x30;\n  }\n\n  return -1;\n}\n\nfunction simpleEscapeSequence(c) {\n  return (c === 0x30/* 0 */) ? '\\x00' :\n        (c === 0x61/* a */) ? '\\x07' :\n        (c === 0x62/* b */) ? '\\x08' :\n        (c === 0x74/* t */) ? '\\x09' :\n        (c === 0x09/* Tab */) ? '\\x09' :\n        (c === 0x6E/* n */) ? '\\x0A' :\n        (c === 0x76/* v */) ? '\\x0B' :\n        (c === 0x66/* f */) ? '\\x0C' :\n        (c === 0x72/* r */) ? '\\x0D' :\n        (c === 0x65/* e */) ? '\\x1B' :\n        (c === 0x20/* Space */) ? ' ' :\n        (c === 0x22/* \" */) ? '\\x22' :\n        (c === 0x2F/* / */) ? '/' :\n        (c === 0x5C/* \\ */) ? '\\x5C' :\n        (c === 0x4E/* N */) ? '\\x85' :\n        (c === 0x5F/* _ */) ? '\\xA0' :\n        (c === 0x4C/* L */) ? '\\u2028' :\n        (c === 0x50/* P */) ? '\\u2029' : '';\n}\n\nfunction charFromCodepoint(c) {\n  if (c <= 0xFFFF) {\n    return String.fromCharCode(c);\n  }\n  // Encode UTF-16 surrogate pair\n  // https://en.wikipedia.org/wiki/UTF-16#Code_points_U.2B010000_to_U.2B10FFFF\n  return String.fromCharCode(((c - 0x010000) >> 10) + 0xD800,\n                             ((c - 0x010000) & 0x03FF) + 0xDC00);\n}\n\nvar simpleEscapeCheck = new Array(256); // integer, for fast access\nvar simpleEscapeMap = new Array(256);\nfor (var i = 0; i < 256; i++) {\n  simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;\n  simpleEscapeMap[i] = simpleEscapeSequence(i);\n}\n\n\nfunction State(input, options) {\n  this.input = input;\n\n  this.filename  = options['filename']  || null;\n  this.schema    = options['schema']    || DEFAULT_FULL_SCHEMA;\n  this.onWarning = options['onWarning'] || null;\n  this.legacy    = options['legacy']    || false;\n  this.json      = options['json']      || false;\n  this.listener  = options['listener']  || null;\n\n  this.implicitTypes = this.schema.compiledImplicit;\n  this.typeMap       = this.schema.compiledTypeMap;\n\n  this.length     = input.length;\n  this.position   = 0;\n  this.line       = 0;\n  this.lineStart  = 0;\n  this.lineIndent = 0;\n\n  this.documents = [];\n\n  /*\n  this.version;\n  this.checkLineBreaks;\n  this.tagMap;\n  this.anchorMap;\n  this.tag;\n  this.anchor;\n  this.kind;\n  this.result;*/\n\n}\n\n\nfunction generateError(state, message) {\n  return new YAMLException(\n    message,\n    new Mark(state.filename, state.input, state.position, state.line, (state.position - state.lineStart)));\n}\n\nfunction throwError(state, message) {\n  throw generateError(state, message);\n}\n\nfunction throwWarning(state, message) {\n  if (state.onWarning) {\n    state.onWarning.call(null, generateError(state, message));\n  }\n}\n\n\nvar directiveHandlers = {\n\n  YAML: function handleYamlDirective(state, name, args) {\n\n    var match, major, minor;\n\n    if (state.version !== null) {\n      throwError(state, 'duplication of %YAML directive');\n    }\n\n    if (args.length !== 1) {\n      throwError(state, 'YAML directive accepts exactly one argument');\n    }\n\n    match = /^([0-9]+)\\.([0-9]+)$/.exec(args[0]);\n\n    if (match === null) {\n      throwError(state, 'ill-formed argument of the YAML directive');\n    }\n\n    major = parseInt(match[1], 10);\n    minor = parseInt(match[2], 10);\n\n    if (major !== 1) {\n      throwError(state, 'unacceptable YAML version of the document');\n    }\n\n    state.version = args[0];\n    state.checkLineBreaks = (minor < 2);\n\n    if (minor !== 1 && minor !== 2) {\n      throwWarning(state, 'unsupported YAML version of the document');\n    }\n  },\n\n  TAG: function handleTagDirective(state, name, args) {\n\n    var handle, prefix;\n\n    if (args.length !== 2) {\n      throwError(state, 'TAG directive accepts exactly two arguments');\n    }\n\n    handle = args[0];\n    prefix = args[1];\n\n    if (!PATTERN_TAG_HANDLE.test(handle)) {\n      throwError(state, 'ill-formed tag handle (first argument) of the TAG directive');\n    }\n\n    if (_hasOwnProperty.call(state.tagMap, handle)) {\n      throwError(state, 'there is a previously declared suffix for \"' + handle + '\" tag handle');\n    }\n\n    if (!PATTERN_TAG_URI.test(prefix)) {\n      throwError(state, 'ill-formed tag prefix (second argument) of the TAG directive');\n    }\n\n    state.tagMap[handle] = prefix;\n  }\n};\n\n\nfunction captureSegment(state, start, end, checkJson) {\n  var _position, _length, _character, _result;\n\n  if (start < end) {\n    _result = state.input.slice(start, end);\n\n    if (checkJson) {\n      for (_position = 0, _length = _result.length;\n           _position < _length;\n           _position += 1) {\n        _character = _result.charCodeAt(_position);\n        if (!(_character === 0x09 ||\n              (0x20 <= _character && _character <= 0x10FFFF))) {\n          throwError(state, 'expected valid JSON character');\n        }\n      }\n    } else if (PATTERN_NON_PRINTABLE.test(_result)) {\n      throwError(state, 'the stream contains non-printable characters');\n    }\n\n    state.result += _result;\n  }\n}\n\nfunction mergeMappings(state, destination, source, overridableKeys) {\n  var sourceKeys, key, index, quantity;\n\n  if (!common.isObject(source)) {\n    throwError(state, 'cannot merge mappings; the provided source object is unacceptable');\n  }\n\n  sourceKeys = Object.keys(source);\n\n  for (index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {\n    key = sourceKeys[index];\n\n    if (!_hasOwnProperty.call(destination, key)) {\n      destination[key] = source[key];\n      overridableKeys[key] = true;\n    }\n  }\n}\n\nfunction storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode) {\n  var index, quantity;\n\n  keyNode = String(keyNode);\n\n  if (_result === null) {\n    _result = {};\n  }\n\n  if (keyTag === 'tag:yaml.org,2002:merge') {\n    if (Array.isArray(valueNode)) {\n      for (index = 0, quantity = valueNode.length; index < quantity; index += 1) {\n        mergeMappings(state, _result, valueNode[index], overridableKeys);\n      }\n    } else {\n      mergeMappings(state, _result, valueNode, overridableKeys);\n    }\n  } else {\n    if (!state.json &&\n        !_hasOwnProperty.call(overridableKeys, keyNode) &&\n        _hasOwnProperty.call(_result, keyNode)) {\n      throwError(state, 'duplicated mapping key');\n    }\n    _result[keyNode] = valueNode;\n    delete overridableKeys[keyNode];\n  }\n\n  return _result;\n}\n\nfunction readLineBreak(state) {\n  var ch;\n\n  ch = state.input.charCodeAt(state.position);\n\n  if (ch === 0x0A/* LF */) {\n    state.position++;\n  } else if (ch === 0x0D/* CR */) {\n    state.position++;\n    if (state.input.charCodeAt(state.position) === 0x0A/* LF */) {\n      state.position++;\n    }\n  } else {\n    throwError(state, 'a line break is expected');\n  }\n\n  state.line += 1;\n  state.lineStart = state.position;\n}\n\nfunction skipSeparationSpace(state, allowComments, checkIndent) {\n  var lineBreaks = 0,\n      ch = state.input.charCodeAt(state.position);\n\n  while (ch !== 0) {\n    while (is_WHITE_SPACE(ch)) {\n      ch = state.input.charCodeAt(++state.position);\n    }\n\n    if (allowComments && ch === 0x23/* # */) {\n      do {\n        ch = state.input.charCodeAt(++state.position);\n      } while (ch !== 0x0A/* LF */ && ch !== 0x0D/* CR */ && ch !== 0);\n    }\n\n    if (is_EOL(ch)) {\n      readLineBreak(state);\n\n      ch = state.input.charCodeAt(state.position);\n      lineBreaks++;\n      state.lineIndent = 0;\n\n      while (ch === 0x20/* Space */) {\n        state.lineIndent++;\n        ch = state.input.charCodeAt(++state.position);\n      }\n    } else {\n      break;\n    }\n  }\n\n  if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {\n    throwWarning(state, 'deficient indentation');\n  }\n\n  return lineBreaks;\n}\n\nfunction testDocumentSeparator(state) {\n  var _position = state.position,\n      ch;\n\n  ch = state.input.charCodeAt(_position);\n\n  // Condition state.position === state.lineStart is tested\n  // in parent on each call, for efficiency. No needs to test here again.\n  if ((ch === 0x2D/* - */ || ch === 0x2E/* . */) &&\n      ch === state.input.charCodeAt(_position + 1) &&\n      ch === state.input.charCodeAt(_position + 2)) {\n\n    _position += 3;\n\n    ch = state.input.charCodeAt(_position);\n\n    if (ch === 0 || is_WS_OR_EOL(ch)) {\n      return true;\n    }\n  }\n\n  return false;\n}\n\nfunction writeFoldedLines(state, count) {\n  if (count === 1) {\n    state.result += ' ';\n  } else if (count > 1) {\n    state.result += common.repeat('\\n', count - 1);\n  }\n}\n\n\nfunction readPlainScalar(state, nodeIndent, withinFlowCollection) {\n  var preceding,\n      following,\n      captureStart,\n      captureEnd,\n      hasPendingContent,\n      _line,\n      _lineStart,\n      _lineIndent,\n      _kind = state.kind,\n      _result = state.result,\n      ch;\n\n  ch = state.input.charCodeAt(state.position);\n\n  if (is_WS_OR_EOL(ch)      ||\n      is_FLOW_INDICATOR(ch) ||\n      ch === 0x23/* # */    ||\n      ch === 0x26/* & */    ||\n      ch === 0x2A/* * */    ||\n      ch === 0x21/* ! */    ||\n      ch === 0x7C/* | */    ||\n      ch === 0x3E/* > */    ||\n      ch === 0x27/* ' */    ||\n      ch === 0x22/* \" */    ||\n      ch === 0x25/* % */    ||\n      ch === 0x40/* @ */    ||\n      ch === 0x60/* ` */) {\n    return false;\n  }\n\n  if (ch === 0x3F/* ? */ || ch === 0x2D/* - */) {\n    following = state.input.charCodeAt(state.position + 1);\n\n    if (is_WS_OR_EOL(following) ||\n        withinFlowCollection && is_FLOW_INDICATOR(following)) {\n      return false;\n    }\n  }\n\n  state.kind = 'scalar';\n  state.result = '';\n  captureStart = captureEnd = state.position;\n  hasPendingContent = false;\n\n  while (ch !== 0) {\n    if (ch === 0x3A/* : */) {\n      following = state.input.charCodeAt(state.position + 1);\n\n      if (is_WS_OR_EOL(following) ||\n          withinFlowCollection && is_FLOW_INDICATOR(following)) {\n        break;\n      }\n\n    } else if (ch === 0x23/* # */) {\n      preceding = state.input.charCodeAt(state.position - 1);\n\n      if (is_WS_OR_EOL(preceding)) {\n        break;\n      }\n\n    } else if ((state.position === state.lineStart && testDocumentSeparator(state)) ||\n               withinFlowCollection && is_FLOW_INDICATOR(ch)) {\n      break;\n\n    } else if (is_EOL(ch)) {\n      _line = state.line;\n      _lineStart = state.lineStart;\n      _lineIndent = state.lineIndent;\n      skipSeparationSpace(state, false, -1);\n\n      if (state.lineIndent >= nodeIndent) {\n        hasPendingContent = true;\n        ch = state.input.charCodeAt(state.position);\n        continue;\n      } else {\n        state.position = captureEnd;\n        state.line = _line;\n        state.lineStart = _lineStart;\n        state.lineIndent = _lineIndent;\n        break;\n      }\n    }\n\n    if (hasPendingContent) {\n      captureSegment(state, captureStart, captureEnd, false);\n      writeFoldedLines(state, state.line - _line);\n      captureStart = captureEnd = state.position;\n      hasPendingContent = false;\n    }\n\n    if (!is_WHITE_SPACE(ch)) {\n      captureEnd = state.position + 1;\n    }\n\n    ch = state.input.charCodeAt(++state.position);\n  }\n\n  captureSegment(state, captureStart, captureEnd, false);\n\n  if (state.result) {\n    return true;\n  }\n\n  state.kind = _kind;\n  state.result = _result;\n  return false;\n}\n\nfunction readSingleQuotedScalar(state, nodeIndent) {\n  var ch,\n      captureStart, captureEnd;\n\n  ch = state.input.charCodeAt(state.position);\n\n  if (ch !== 0x27/* ' */) {\n    return false;\n  }\n\n  state.kind = 'scalar';\n  state.result = '';\n  state.position++;\n  captureStart = captureEnd = state.position;\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    if (ch === 0x27/* ' */) {\n      captureSegment(state, captureStart, state.position, true);\n      ch = state.input.charCodeAt(++state.position);\n\n      if (ch === 0x27/* ' */) {\n        captureStart = captureEnd = state.position;\n        state.position++;\n      } else {\n        return true;\n      }\n\n    } else if (is_EOL(ch)) {\n      captureSegment(state, captureStart, captureEnd, true);\n      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));\n      captureStart = captureEnd = state.position;\n\n    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n      throwError(state, 'unexpected end of the document within a single quoted scalar');\n\n    } else {\n      state.position++;\n      captureEnd = state.position;\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a single quoted scalar');\n}\n\nfunction readDoubleQuotedScalar(state, nodeIndent) {\n  var captureStart,\n      captureEnd,\n      hexLength,\n      hexResult,\n      tmp,\n      ch;\n\n  ch = state.input.charCodeAt(state.position);\n\n  if (ch !== 0x22/* \" */) {\n    return false;\n  }\n\n  state.kind = 'scalar';\n  state.result = '';\n  state.position++;\n  captureStart = captureEnd = state.position;\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    if (ch === 0x22/* \" */) {\n      captureSegment(state, captureStart, state.position, true);\n      state.position++;\n      return true;\n\n    } else if (ch === 0x5C/* \\ */) {\n      captureSegment(state, captureStart, state.position, true);\n      ch = state.input.charCodeAt(++state.position);\n\n      if (is_EOL(ch)) {\n        skipSeparationSpace(state, false, nodeIndent);\n\n        // TODO: rework to inline fn with no type cast?\n      } else if (ch < 256 && simpleEscapeCheck[ch]) {\n        state.result += simpleEscapeMap[ch];\n        state.position++;\n\n      } else if ((tmp = escapedHexLen(ch)) > 0) {\n        hexLength = tmp;\n        hexResult = 0;\n\n        for (; hexLength > 0; hexLength--) {\n          ch = state.input.charCodeAt(++state.position);\n\n          if ((tmp = fromHexCode(ch)) >= 0) {\n            hexResult = (hexResult << 4) + tmp;\n\n          } else {\n            throwError(state, 'expected hexadecimal character');\n          }\n        }\n\n        state.result += charFromCodepoint(hexResult);\n\n        state.position++;\n\n      } else {\n        throwError(state, 'unknown escape sequence');\n      }\n\n      captureStart = captureEnd = state.position;\n\n    } else if (is_EOL(ch)) {\n      captureSegment(state, captureStart, captureEnd, true);\n      writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));\n      captureStart = captureEnd = state.position;\n\n    } else if (state.position === state.lineStart && testDocumentSeparator(state)) {\n      throwError(state, 'unexpected end of the document within a double quoted scalar');\n\n    } else {\n      state.position++;\n      captureEnd = state.position;\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a double quoted scalar');\n}\n\nfunction readFlowCollection(state, nodeIndent) {\n  var readNext = true,\n      _line,\n      _tag     = state.tag,\n      _result,\n      _anchor  = state.anchor,\n      following,\n      terminator,\n      isPair,\n      isExplicitPair,\n      isMapping,\n      overridableKeys = {},\n      keyNode,\n      keyTag,\n      valueNode,\n      ch;\n\n  ch = state.input.charCodeAt(state.position);\n\n  if (ch === 0x5B/* [ */) {\n    terminator = 0x5D;/* ] */\n    isMapping = false;\n    _result = [];\n  } else if (ch === 0x7B/* { */) {\n    terminator = 0x7D;/* } */\n    isMapping = true;\n    _result = {};\n  } else {\n    return false;\n  }\n\n  if (state.anchor !== null) {\n    state.anchorMap[state.anchor] = _result;\n  }\n\n  ch = state.input.charCodeAt(++state.position);\n\n  while (ch !== 0) {\n    skipSeparationSpace(state, true, nodeIndent);\n\n    ch = state.input.charCodeAt(state.position);\n\n    if (ch === terminator) {\n      state.position++;\n      state.tag = _tag;\n      state.anchor = _anchor;\n      state.kind = isMapping ? 'mapping' : 'sequence';\n      state.result = _result;\n      return true;\n    } else if (!readNext) {\n      throwError(state, 'missed comma between flow collection entries');\n    }\n\n    keyTag = keyNode = valueNode = null;\n    isPair = isExplicitPair = false;\n\n    if (ch === 0x3F/* ? */) {\n      following = state.input.charCodeAt(state.position + 1);\n\n      if (is_WS_OR_EOL(following)) {\n        isPair = isExplicitPair = true;\n        state.position++;\n        skipSeparationSpace(state, true, nodeIndent);\n      }\n    }\n\n    _line = state.line;\n    composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);\n    keyTag = state.tag;\n    keyNode = state.result;\n    skipSeparationSpace(state, true, nodeIndent);\n\n    ch = state.input.charCodeAt(state.position);\n\n    if ((isExplicitPair || state.line === _line) && ch === 0x3A/* : */) {\n      isPair = true;\n      ch = state.input.charCodeAt(++state.position);\n      skipSeparationSpace(state, true, nodeIndent);\n      composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);\n      valueNode = state.result;\n    }\n\n    if (isMapping) {\n      storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode);\n    } else if (isPair) {\n      _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode));\n    } else {\n      _result.push(keyNode);\n    }\n\n    skipSeparationSpace(state, true, nodeIndent);\n\n    ch = state.input.charCodeAt(state.position);\n\n    if (ch === 0x2C/* , */) {\n      readNext = true;\n      ch = state.input.charCodeAt(++state.position);\n    } else {\n      readNext = false;\n    }\n  }\n\n  throwError(state, 'unexpected end of the stream within a flow collection');\n}\n\nfunction readBlockScalar(state, nodeIndent) {\n  var captureStart,\n      folding,\n      chomping       = CHOMPING_CLIP,\n      didReadContent = false,\n      detectedIndent = false,\n      textIndent     = nodeIndent,\n      emptyLines     = 0,\n      atMoreIndented = false,\n      tmp,\n      ch;\n\n  ch = state.input.charCodeAt(state.position);\n\n  if (ch === 0x7C/* | */) {\n    folding = false;\n  } else if (ch === 0x3E/* > */) {\n    folding = true;\n  } else {\n    return false;\n  }\n\n  state.kind = 'scalar';\n  state.result = '';\n\n  while (ch !== 0) {\n    ch = state.input.charCodeAt(++state.position);\n\n    if (ch === 0x2B/* + */ || ch === 0x2D/* - */) {\n      if (CHOMPING_CLIP === chomping) {\n        chomping = (ch === 0x2B/* + */) ? CHOMPING_KEEP : CHOMPING_STRIP;\n      } else {\n        throwError(state, 'repeat of a chomping mode identifier');\n      }\n\n    } else if ((tmp = fromDecimalCode(ch)) >= 0) {\n      if (tmp === 0) {\n        throwError(state, 'bad explicit indentation width of a block scalar; it cannot be less than one');\n      } else if (!detectedIndent) {\n        textIndent = nodeIndent + tmp - 1;\n        detectedIndent = true;\n      } else {\n        throwError(state, 'repeat of an indentation width identifier');\n      }\n\n    } else {\n      break;\n    }\n  }\n\n  if (is_WHITE_SPACE(ch)) {\n    do { ch = state.input.charCodeAt(++state.position); }\n    while (is_WHITE_SPACE(ch));\n\n    if (ch === 0x23/* # */) {\n      do { ch = state.input.charCodeAt(++state.position); }\n      while (!is_EOL(ch) && (ch !== 0));\n    }\n  }\n\n  while (ch !== 0) {\n    readLineBreak(state);\n    state.lineIndent = 0;\n\n    ch = state.input.charCodeAt(state.position);\n\n    while ((!detectedIndent || state.lineIndent < textIndent) &&\n           (ch === 0x20/* Space */)) {\n      state.lineIndent++;\n      ch = state.input.charCodeAt(++state.position);\n    }\n\n    if (!detectedIndent && state.lineIndent > textIndent) {\n      textIndent = state.lineIndent;\n    }\n\n    if (is_EOL(ch)) {\n      emptyLines++;\n      continue;\n    }\n\n    // End of the scalar.\n    if (state.lineIndent < textIndent) {\n\n      // Perform the chomping.\n      if (chomping === CHOMPING_KEEP) {\n        state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines);\n      } else if (chomping === CHOMPING_CLIP) {\n        if (didReadContent) { // i.e. only if the scalar is not empty.\n          state.result += '\\n';\n        }\n      }\n\n      // Break this `while` cycle and go to the funciton's epilogue.\n      break;\n    }\n\n    // Folded style: use fancy rules to handle line breaks.\n    if (folding) {\n\n      // Lines starting with white space characters (more-indented lines) are not folded.\n      if (is_WHITE_SPACE(ch)) {\n        atMoreIndented = true;\n        // except for the first content line (cf. Example 8.1)\n        state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines);\n\n      // End of more-indented block.\n      } else if (atMoreIndented) {\n        atMoreIndented = false;\n        state.result += common.repeat('\\n', emptyLines + 1);\n\n      // Just one line break - perceive as the same line.\n      } else if (emptyLines === 0) {\n        if (didReadContent) { // i.e. only if we have already read some scalar content.\n          state.result += ' ';\n        }\n\n      // Several line breaks - perceive as different lines.\n      } else {\n        state.result += common.repeat('\\n', emptyLines);\n      }\n\n    // Literal style: just add exact number of line breaks between content lines.\n    } else {\n      // Keep all line breaks except the header line break.\n      state.result += common.repeat('\\n', didReadContent ? 1 + emptyLines : emptyLines);\n    }\n\n    didReadContent = true;\n    detectedIndent = true;\n    emptyLines = 0;\n    captureStart = state.position;\n\n    while (!is_EOL(ch) && (ch !== 0)) {\n      ch = state.input.charCodeAt(++state.position);\n    }\n\n    captureSegment(state, captureStart, state.position, false);\n  }\n\n  return true;\n}\n\nfunction readBlockSequence(state, nodeIndent) {\n  var _line,\n      _tag      = state.tag,\n      _anchor   = state.anchor,\n      _result   = [],\n      following,\n      detected  = false,\n      ch;\n\n  if (state.anchor !== null) {\n    state.anchorMap[state.anchor] = _result;\n  }\n\n  ch = state.input.charCodeAt(state.position);\n\n  while (ch !== 0) {\n\n    if (ch !== 0x2D/* - */) {\n      break;\n    }\n\n    following = state.input.charCodeAt(state.position + 1);\n\n    if (!is_WS_OR_EOL(following)) {\n      break;\n    }\n\n    detected = true;\n    state.position++;\n\n    if (skipSeparationSpace(state, true, -1)) {\n      if (state.lineIndent <= nodeIndent) {\n        _result.push(null);\n        ch = state.input.charCodeAt(state.position);\n        continue;\n      }\n    }\n\n    _line = state.line;\n    composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);\n    _result.push(state.result);\n    skipSeparationSpace(state, true, -1);\n\n    ch = state.input.charCodeAt(state.position);\n\n    if ((state.line === _line || state.lineIndent > nodeIndent) && (ch !== 0)) {\n      throwError(state, 'bad indentation of a sequence entry');\n    } else if (state.lineIndent < nodeIndent) {\n      break;\n    }\n  }\n\n  if (detected) {\n    state.tag = _tag;\n    state.anchor = _anchor;\n    state.kind = 'sequence';\n    state.result = _result;\n    return true;\n  }\n  return false;\n}\n\nfunction readBlockMapping(state, nodeIndent, flowIndent) {\n  var following,\n      allowCompact,\n      _line,\n      _tag          = state.tag,\n      _anchor       = state.anchor,\n      _result       = {},\n      overridableKeys = {},\n      keyTag        = null,\n      keyNode       = null,\n      valueNode     = null,\n      atExplicitKey = false,\n      detected      = false,\n      ch;\n\n  if (state.anchor !== null) {\n    state.anchorMap[state.anchor] = _result;\n  }\n\n  ch = state.input.charCodeAt(state.position);\n\n  while (ch !== 0) {\n    following = state.input.charCodeAt(state.position + 1);\n    _line = state.line; // Save the current line.\n\n    //\n    // Explicit notation case. There are two separate blocks:\n    // first for the key (denoted by \"?\") and second for the value (denoted by \":\")\n    //\n    if ((ch === 0x3F/* ? */ || ch === 0x3A/* : */) && is_WS_OR_EOL(following)) {\n\n      if (ch === 0x3F/* ? */) {\n        if (atExplicitKey) {\n          storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);\n          keyTag = keyNode = valueNode = null;\n        }\n\n        detected = true;\n        atExplicitKey = true;\n        allowCompact = true;\n\n      } else if (atExplicitKey) {\n        // i.e. 0x3A/* : */ === character after the explicit key.\n        atExplicitKey = false;\n        allowCompact = true;\n\n      } else {\n        throwError(state, 'incomplete explicit mapping pair; a key node is missed');\n      }\n\n      state.position += 1;\n      ch = following;\n\n    //\n    // Implicit notation case. Flow-style node as the key first, then \":\", and the value.\n    //\n    } else if (composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {\n\n      if (state.line === _line) {\n        ch = state.input.charCodeAt(state.position);\n\n        while (is_WHITE_SPACE(ch)) {\n          ch = state.input.charCodeAt(++state.position);\n        }\n\n        if (ch === 0x3A/* : */) {\n          ch = state.input.charCodeAt(++state.position);\n\n          if (!is_WS_OR_EOL(ch)) {\n            throwError(state, 'a whitespace character is expected after the key-value separator within a block mapping');\n          }\n\n          if (atExplicitKey) {\n            storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);\n            keyTag = keyNode = valueNode = null;\n          }\n\n          detected = true;\n          atExplicitKey = false;\n          allowCompact = false;\n          keyTag = state.tag;\n          keyNode = state.result;\n\n        } else if (detected) {\n          throwError(state, 'can not read an implicit mapping pair; a colon is missed');\n\n        } else {\n          state.tag = _tag;\n          state.anchor = _anchor;\n          return true; // Keep the result of `composeNode`.\n        }\n\n      } else if (detected) {\n        throwError(state, 'can not read a block mapping entry; a multiline key may not be an implicit key');\n\n      } else {\n        state.tag = _tag;\n        state.anchor = _anchor;\n        return true; // Keep the result of `composeNode`.\n      }\n\n    } else {\n      break; // Reading is done. Go to the epilogue.\n    }\n\n    //\n    // Common reading code for both explicit and implicit notations.\n    //\n    if (state.line === _line || state.lineIndent > nodeIndent) {\n      if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {\n        if (atExplicitKey) {\n          keyNode = state.result;\n        } else {\n          valueNode = state.result;\n        }\n      }\n\n      if (!atExplicitKey) {\n        storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode);\n        keyTag = keyNode = valueNode = null;\n      }\n\n      skipSeparationSpace(state, true, -1);\n      ch = state.input.charCodeAt(state.position);\n    }\n\n    if (state.lineIndent > nodeIndent && (ch !== 0)) {\n      throwError(state, 'bad indentation of a mapping entry');\n    } else if (state.lineIndent < nodeIndent) {\n      break;\n    }\n  }\n\n  //\n  // Epilogue.\n  //\n\n  // Special case: last mapping's node contains only the key in explicit notation.\n  if (atExplicitKey) {\n    storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null);\n  }\n\n  // Expose the resulting mapping.\n  if (detected) {\n    state.tag = _tag;\n    state.anchor = _anchor;\n    state.kind = 'mapping';\n    state.result = _result;\n  }\n\n  return detected;\n}\n\nfunction readTagProperty(state) {\n  var _position,\n      isVerbatim = false,\n      isNamed    = false,\n      tagHandle,\n      tagName,\n      ch;\n\n  ch = state.input.charCodeAt(state.position);\n\n  if (ch !== 0x21/* ! */) return false;\n\n  if (state.tag !== null) {\n    throwError(state, 'duplication of a tag property');\n  }\n\n  ch = state.input.charCodeAt(++state.position);\n\n  if (ch === 0x3C/* < */) {\n    isVerbatim = true;\n    ch = state.input.charCodeAt(++state.position);\n\n  } else if (ch === 0x21/* ! */) {\n    isNamed = true;\n    tagHandle = '!!';\n    ch = state.input.charCodeAt(++state.position);\n\n  } else {\n    tagHandle = '!';\n  }\n\n  _position = state.position;\n\n  if (isVerbatim) {\n    do { ch = state.input.charCodeAt(++state.position); }\n    while (ch !== 0 && ch !== 0x3E/* > */);\n\n    if (state.position < state.length) {\n      tagName = state.input.slice(_position, state.position);\n      ch = state.input.charCodeAt(++state.position);\n    } else {\n      throwError(state, 'unexpected end of the stream within a verbatim tag');\n    }\n  } else {\n    while (ch !== 0 && !is_WS_OR_EOL(ch)) {\n\n      if (ch === 0x21/* ! */) {\n        if (!isNamed) {\n          tagHandle = state.input.slice(_position - 1, state.position + 1);\n\n          if (!PATTERN_TAG_HANDLE.test(tagHandle)) {\n            throwError(state, 'named tag handle cannot contain such characters');\n          }\n\n          isNamed = true;\n          _position = state.position + 1;\n        } else {\n          throwError(state, 'tag suffix cannot contain exclamation marks');\n        }\n      }\n\n      ch = state.input.charCodeAt(++state.position);\n    }\n\n    tagName = state.input.slice(_position, state.position);\n\n    if (PATTERN_FLOW_INDICATORS.test(tagName)) {\n      throwError(state, 'tag suffix cannot contain flow indicator characters');\n    }\n  }\n\n  if (tagName && !PATTERN_TAG_URI.test(tagName)) {\n    throwError(state, 'tag name cannot contain such characters: ' + tagName);\n  }\n\n  if (isVerbatim) {\n    state.tag = tagName;\n\n  } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {\n    state.tag = state.tagMap[tagHandle] + tagName;\n\n  } else if (tagHandle === '!') {\n    state.tag = '!' + tagName;\n\n  } else if (tagHandle === '!!') {\n    state.tag = 'tag:yaml.org,2002:' + tagName;\n\n  } else {\n    throwError(state, 'undeclared tag handle \"' + tagHandle + '\"');\n  }\n\n  return true;\n}\n\nfunction readAnchorProperty(state) {\n  var _position,\n      ch;\n\n  ch = state.input.charCodeAt(state.position);\n\n  if (ch !== 0x26/* & */) return false;\n\n  if (state.anchor !== null) {\n    throwError(state, 'duplication of an anchor property');\n  }\n\n  ch = state.input.charCodeAt(++state.position);\n  _position = state.position;\n\n  while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {\n    ch = state.input.charCodeAt(++state.position);\n  }\n\n  if (state.position === _position) {\n    throwError(state, 'name of an anchor node must contain at least one character');\n  }\n\n  state.anchor = state.input.slice(_position, state.position);\n  return true;\n}\n\nfunction readAlias(state) {\n  var _position, alias,\n      ch;\n\n  ch = state.input.charCodeAt(state.position);\n\n  if (ch !== 0x2A/* * */) return false;\n\n  ch = state.input.charCodeAt(++state.position);\n  _position = state.position;\n\n  while (ch !== 0 && !is_WS_OR_EOL(ch) && !is_FLOW_INDICATOR(ch)) {\n    ch = state.input.charCodeAt(++state.position);\n  }\n\n  if (state.position === _position) {\n    throwError(state, 'name of an alias node must contain at least one character');\n  }\n\n  alias = state.input.slice(_position, state.position);\n\n  if (!state.anchorMap.hasOwnProperty(alias)) {\n    throwError(state, 'unidentified alias \"' + alias + '\"');\n  }\n\n  state.result = state.anchorMap[alias];\n  skipSeparationSpace(state, true, -1);\n  return true;\n}\n\nfunction composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {\n  var allowBlockStyles,\n      allowBlockScalars,\n      allowBlockCollections,\n      indentStatus = 1, // 1: this>parent, 0: this=parent, -1: this<parent\n      atNewLine  = false,\n      hasContent = false,\n      typeIndex,\n      typeQuantity,\n      type,\n      flowIndent,\n      blockIndent;\n\n  if (state.listener !== null) {\n    state.listener('open', state);\n  }\n\n  state.tag    = null;\n  state.anchor = null;\n  state.kind   = null;\n  state.result = null;\n\n  allowBlockStyles = allowBlockScalars = allowBlockCollections =\n    CONTEXT_BLOCK_OUT === nodeContext ||\n    CONTEXT_BLOCK_IN  === nodeContext;\n\n  if (allowToSeek) {\n    if (skipSeparationSpace(state, true, -1)) {\n      atNewLine = true;\n\n      if (state.lineIndent > parentIndent) {\n        indentStatus = 1;\n      } else if (state.lineIndent === parentIndent) {\n        indentStatus = 0;\n      } else if (state.lineIndent < parentIndent) {\n        indentStatus = -1;\n      }\n    }\n  }\n\n  if (indentStatus === 1) {\n    while (readTagProperty(state) || readAnchorProperty(state)) {\n      if (skipSeparationSpace(state, true, -1)) {\n        atNewLine = true;\n        allowBlockCollections = allowBlockStyles;\n\n        if (state.lineIndent > parentIndent) {\n          indentStatus = 1;\n        } else if (state.lineIndent === parentIndent) {\n          indentStatus = 0;\n        } else if (state.lineIndent < parentIndent) {\n          indentStatus = -1;\n        }\n      } else {\n        allowBlockCollections = false;\n      }\n    }\n  }\n\n  if (allowBlockCollections) {\n    allowBlockCollections = atNewLine || allowCompact;\n  }\n\n  if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {\n    if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {\n      flowIndent = parentIndent;\n    } else {\n      flowIndent = parentIndent + 1;\n    }\n\n    blockIndent = state.position - state.lineStart;\n\n    if (indentStatus === 1) {\n      if (allowBlockCollections &&\n          (readBlockSequence(state, blockIndent) ||\n           readBlockMapping(state, blockIndent, flowIndent)) ||\n          readFlowCollection(state, flowIndent)) {\n        hasContent = true;\n      } else {\n        if ((allowBlockScalars && readBlockScalar(state, flowIndent)) ||\n            readSingleQuotedScalar(state, flowIndent) ||\n            readDoubleQuotedScalar(state, flowIndent)) {\n          hasContent = true;\n\n        } else if (readAlias(state)) {\n          hasContent = true;\n\n          if (state.tag !== null || state.anchor !== null) {\n            throwError(state, 'alias node should not have any properties');\n          }\n\n        } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {\n          hasContent = true;\n\n          if (state.tag === null) {\n            state.tag = '?';\n          }\n        }\n\n        if (state.anchor !== null) {\n          state.anchorMap[state.anchor] = state.result;\n        }\n      }\n    } else if (indentStatus === 0) {\n      // Special case: block sequences are allowed to have same indentation level as the parent.\n      // http://www.yaml.org/spec/1.2/spec.html#id2799784\n      hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);\n    }\n  }\n\n  if (state.tag !== null && state.tag !== '!') {\n    if (state.tag === '?') {\n      for (typeIndex = 0, typeQuantity = state.implicitTypes.length;\n           typeIndex < typeQuantity;\n           typeIndex += 1) {\n        type = state.implicitTypes[typeIndex];\n\n        // Implicit resolving is not allowed for non-scalar types, and '?'\n        // non-specific tag is only assigned to plain scalars. So, it isn't\n        // needed to check for 'kind' conformity.\n\n        if (type.resolve(state.result)) { // `state.result` updated in resolver if matched\n          state.result = type.construct(state.result);\n          state.tag = type.tag;\n          if (state.anchor !== null) {\n            state.anchorMap[state.anchor] = state.result;\n          }\n          break;\n        }\n      }\n    } else if (_hasOwnProperty.call(state.typeMap, state.tag)) {\n      type = state.typeMap[state.tag];\n\n      if (state.result !== null && type.kind !== state.kind) {\n        throwError(state, 'unacceptable node kind for !<' + state.tag + '> tag; it should be \"' + type.kind + '\", not \"' + state.kind + '\"');\n      }\n\n      if (!type.resolve(state.result)) { // `state.result` updated in resolver if matched\n        throwError(state, 'cannot resolve a node with !<' + state.tag + '> explicit tag');\n      } else {\n        state.result = type.construct(state.result);\n        if (state.anchor !== null) {\n          state.anchorMap[state.anchor] = state.result;\n        }\n      }\n    } else {\n      throwError(state, 'unknown tag !<' + state.tag + '>');\n    }\n  }\n\n  if (state.listener !== null) {\n    state.listener('close', state);\n  }\n  return state.tag !== null ||  state.anchor !== null || hasContent;\n}\n\nfunction readDocument(state) {\n  var documentStart = state.position,\n      _position,\n      directiveName,\n      directiveArgs,\n      hasDirectives = false,\n      ch;\n\n  state.version = null;\n  state.checkLineBreaks = state.legacy;\n  state.tagMap = {};\n  state.anchorMap = {};\n\n  while ((ch = state.input.charCodeAt(state.position)) !== 0) {\n    skipSeparationSpace(state, true, -1);\n\n    ch = state.input.charCodeAt(state.position);\n\n    if (state.lineIndent > 0 || ch !== 0x25/* % */) {\n      break;\n    }\n\n    hasDirectives = true;\n    ch = state.input.charCodeAt(++state.position);\n    _position = state.position;\n\n    while (ch !== 0 && !is_WS_OR_EOL(ch)) {\n      ch = state.input.charCodeAt(++state.position);\n    }\n\n    directiveName = state.input.slice(_position, state.position);\n    directiveArgs = [];\n\n    if (directiveName.length < 1) {\n      throwError(state, 'directive name must not be less than one character in length');\n    }\n\n    while (ch !== 0) {\n      while (is_WHITE_SPACE(ch)) {\n        ch = state.input.charCodeAt(++state.position);\n      }\n\n      if (ch === 0x23/* # */) {\n        do { ch = state.input.charCodeAt(++state.position); }\n        while (ch !== 0 && !is_EOL(ch));\n        break;\n      }\n\n      if (is_EOL(ch)) break;\n\n      _position = state.position;\n\n      while (ch !== 0 && !is_WS_OR_EOL(ch)) {\n        ch = state.input.charCodeAt(++state.position);\n      }\n\n      directiveArgs.push(state.input.slice(_position, state.position));\n    }\n\n    if (ch !== 0) readLineBreak(state);\n\n    if (_hasOwnProperty.call(directiveHandlers, directiveName)) {\n      directiveHandlers[directiveName](state, directiveName, directiveArgs);\n    } else {\n      throwWarning(state, 'unknown document directive \"' + directiveName + '\"');\n    }\n  }\n\n  skipSeparationSpace(state, true, -1);\n\n  if (state.lineIndent === 0 &&\n      state.input.charCodeAt(state.position)     === 0x2D/* - */ &&\n      state.input.charCodeAt(state.position + 1) === 0x2D/* - */ &&\n      state.input.charCodeAt(state.position + 2) === 0x2D/* - */) {\n    state.position += 3;\n    skipSeparationSpace(state, true, -1);\n\n  } else if (hasDirectives) {\n    throwError(state, 'directives end mark is expected');\n  }\n\n  composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);\n  skipSeparationSpace(state, true, -1);\n\n  if (state.checkLineBreaks &&\n      PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {\n    throwWarning(state, 'non-ASCII line breaks are interpreted as content');\n  }\n\n  state.documents.push(state.result);\n\n  if (state.position === state.lineStart && testDocumentSeparator(state)) {\n\n    if (state.input.charCodeAt(state.position) === 0x2E/* . */) {\n      state.position += 3;\n      skipSeparationSpace(state, true, -1);\n    }\n    return;\n  }\n\n  if (state.position < (state.length - 1)) {\n    throwError(state, 'end of the stream or a document separator is expected');\n  } else {\n    return;\n  }\n}\n\n\nfunction loadDocuments(input, options) {\n  input = String(input);\n  options = options || {};\n\n  if (input.length !== 0) {\n\n    // Add tailing `\\n` if not exists\n    if (input.charCodeAt(input.length - 1) !== 0x0A/* LF */ &&\n        input.charCodeAt(input.length - 1) !== 0x0D/* CR */) {\n      input += '\\n';\n    }\n\n    // Strip BOM\n    if (input.charCodeAt(0) === 0xFEFF) {\n      input = input.slice(1);\n    }\n  }\n\n  var state = new State(input, options);\n\n  // Use 0 as string terminator. That significantly simplifies bounds check.\n  state.input += '\\0';\n\n  while (state.input.charCodeAt(state.position) === 0x20/* Space */) {\n    state.lineIndent += 1;\n    state.position += 1;\n  }\n\n  while (state.position < (state.length - 1)) {\n    readDocument(state);\n  }\n\n  return state.documents;\n}\n\n\nfunction loadAll(input, iterator, options) {\n  var documents = loadDocuments(input, options), index, length;\n\n  for (index = 0, length = documents.length; index < length; index += 1) {\n    iterator(documents[index]);\n  }\n}\n\n\nfunction load(input, options) {\n  var documents = loadDocuments(input, options);\n\n  if (documents.length === 0) {\n    /*eslint-disable no-undefined*/\n    return undefined;\n  } else if (documents.length === 1) {\n    return documents[0];\n  }\n  throw new YAMLException('expected a single document in the stream, but found more');\n}\n\n\nfunction safeLoadAll(input, output, options) {\n  loadAll(input, output, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));\n}\n\n\nfunction safeLoad(input, options) {\n  return load(input, common.extend({ schema: DEFAULT_SAFE_SCHEMA }, options));\n}\n\n\nmodule.exports.loadAll     = loadAll;\nmodule.exports.load        = load;\nmodule.exports.safeLoadAll = safeLoadAll;\nmodule.exports.safeLoad    = safeLoad;\n\n},{\"./common\":21,\"./exception\":23,\"./mark\":25,\"./schema/default_full\":28,\"./schema/default_safe\":29}],25:[function(require,module,exports){\n'use strict';\n\n\nvar common = require('./common');\n\n\nfunction Mark(name, buffer, position, line, column) {\n  this.name     = name;\n  this.buffer   = buffer;\n  this.position = position;\n  this.line     = line;\n  this.column   = column;\n}\n\n\nMark.prototype.getSnippet = function getSnippet(indent, maxLength) {\n  var head, start, tail, end, snippet;\n\n  if (!this.buffer) return null;\n\n  indent = indent || 4;\n  maxLength = maxLength || 75;\n\n  head = '';\n  start = this.position;\n\n  while (start > 0 && '\\x00\\r\\n\\x85\\u2028\\u2029'.indexOf(this.buffer.charAt(start - 1)) === -1) {\n    start -= 1;\n    if (this.position - start > (maxLength / 2 - 1)) {\n      head = ' ... ';\n      start += 5;\n      break;\n    }\n  }\n\n  tail = '';\n  end = this.position;\n\n  while (end < this.buffer.length && '\\x00\\r\\n\\x85\\u2028\\u2029'.indexOf(this.buffer.charAt(end)) === -1) {\n    end += 1;\n    if (end - this.position > (maxLength / 2 - 1)) {\n      tail = ' ... ';\n      end -= 5;\n      break;\n    }\n  }\n\n  snippet = this.buffer.slice(start, end);\n\n  return common.repeat(' ', indent) + head + snippet + tail + '\\n' +\n         common.repeat(' ', indent + this.position - start + head.length) + '^';\n};\n\n\nMark.prototype.toString = function toString(compact) {\n  var snippet, where = '';\n\n  if (this.name) {\n    where += 'in \"' + this.name + '\" ';\n  }\n\n  where += 'at line ' + (this.line + 1) + ', column ' + (this.column + 1);\n\n  if (!compact) {\n    snippet = this.getSnippet();\n\n    if (snippet) {\n      where += ':\\n' + snippet;\n    }\n  }\n\n  return where;\n};\n\n\nmodule.exports = Mark;\n\n},{\"./common\":21}],26:[function(require,module,exports){\n'use strict';\n\n/*eslint-disable max-len*/\n\nvar common        = require('./common');\nvar YAMLException = require('./exception');\nvar Type          = require('./type');\n\n\nfunction compileList(schema, name, result) {\n  var exclude = [];\n\n  schema.include.forEach(function (includedSchema) {\n    result = compileList(includedSchema, name, result);\n  });\n\n  schema[name].forEach(function (currentType) {\n    result.forEach(function (previousType, previousIndex) {\n      if (previousType.tag === currentType.tag) {\n        exclude.push(previousIndex);\n      }\n    });\n\n    result.push(currentType);\n  });\n\n  return result.filter(function (type, index) {\n    return exclude.indexOf(index) === -1;\n  });\n}\n\n\nfunction compileMap(/* lists... */) {\n  var result = {}, index, length;\n\n  function collectType(type) {\n    result[type.tag] = type;\n  }\n\n  for (index = 0, length = arguments.length; index < length; index += 1) {\n    arguments[index].forEach(collectType);\n  }\n\n  return result;\n}\n\n\nfunction Schema(definition) {\n  this.include  = definition.include  || [];\n  this.implicit = definition.implicit || [];\n  this.explicit = definition.explicit || [];\n\n  this.implicit.forEach(function (type) {\n    if (type.loadKind && type.loadKind !== 'scalar') {\n      throw new YAMLException('There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.');\n    }\n  });\n\n  this.compiledImplicit = compileList(this, 'implicit', []);\n  this.compiledExplicit = compileList(this, 'explicit', []);\n  this.compiledTypeMap  = compileMap(this.compiledImplicit, this.compiledExplicit);\n}\n\n\nSchema.DEFAULT = null;\n\n\nSchema.create = function createSchema() {\n  var schemas, types;\n\n  switch (arguments.length) {\n    case 1:\n      schemas = Schema.DEFAULT;\n      types = arguments[0];\n      break;\n\n    case 2:\n      schemas = arguments[0];\n      types = arguments[1];\n      break;\n\n    default:\n      throw new YAMLException('Wrong number of arguments for Schema.create function');\n  }\n\n  schemas = common.toArray(schemas);\n  types = common.toArray(types);\n\n  if (!schemas.every(function (schema) { return schema instanceof Schema; })) {\n    throw new YAMLException('Specified list of super schemas (or a single Schema object) contains a non-Schema object.');\n  }\n\n  if (!types.every(function (type) { return type instanceof Type; })) {\n    throw new YAMLException('Specified list of YAML types (or a single Type object) contains a non-Type object.');\n  }\n\n  return new Schema({\n    include: schemas,\n    explicit: types\n  });\n};\n\n\nmodule.exports = Schema;\n\n},{\"./common\":21,\"./exception\":23,\"./type\":32}],27:[function(require,module,exports){\n// Standard YAML's Core schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2804923\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, Core schema has no distinctions from JSON schema is JS-YAML.\n\n\n'use strict';\n\n\nvar Schema = require('../schema');\n\n\nmodule.exports = new Schema({\n  include: [\n    require('./json')\n  ]\n});\n\n},{\"../schema\":26,\"./json\":31}],28:[function(require,module,exports){\n// JS-YAML's default schema for `load` function.\n// It is not described in the YAML specification.\n//\n// This schema is based on JS-YAML's default safe schema and includes\n// JavaScript-specific types: !!js/undefined, !!js/regexp and !!js/function.\n//\n// Also this schema is used as default base schema at `Schema.create` function.\n\n\n'use strict';\n\n\nvar Schema = require('../schema');\n\n\nmodule.exports = Schema.DEFAULT = new Schema({\n  include: [\n    require('./default_safe')\n  ],\n  explicit: [\n    require('../type/js/undefined'),\n    require('../type/js/regexp'),\n    require('../type/js/function')\n  ]\n});\n\n},{\"../schema\":26,\"../type/js/function\":37,\"../type/js/regexp\":38,\"../type/js/undefined\":39,\"./default_safe\":29}],29:[function(require,module,exports){\n// JS-YAML's default schema for `safeLoad` function.\n// It is not described in the YAML specification.\n//\n// This schema is based on standard YAML's Core schema and includes most of\n// extra types described at YAML tag repositories. (http://yaml.org/type/)\n\n\n'use strict';\n\n\nvar Schema = require('../schema');\n\n\nmodule.exports = new Schema({\n  include: [\n    require('./core')\n  ],\n  implicit: [\n    require('../type/timestamp'),\n    require('../type/merge')\n  ],\n  explicit: [\n    require('../type/binary'),\n    require('../type/omap'),\n    require('../type/pairs'),\n    require('../type/set')\n  ]\n});\n\n},{\"../schema\":26,\"../type/binary\":33,\"../type/merge\":41,\"../type/omap\":43,\"../type/pairs\":44,\"../type/set\":46,\"../type/timestamp\":48,\"./core\":27}],30:[function(require,module,exports){\n// Standard YAML's Failsafe schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2802346\n\n\n'use strict';\n\n\nvar Schema = require('../schema');\n\n\nmodule.exports = new Schema({\n  explicit: [\n    require('../type/str'),\n    require('../type/seq'),\n    require('../type/map')\n  ]\n});\n\n},{\"../schema\":26,\"../type/map\":40,\"../type/seq\":45,\"../type/str\":47}],31:[function(require,module,exports){\n// Standard YAML's JSON schema.\n// http://www.yaml.org/spec/1.2/spec.html#id2803231\n//\n// NOTE: JS-YAML does not support schema-specific tag resolution restrictions.\n// So, this schema is not such strict as defined in the YAML specification.\n// It allows numbers in binary notaion, use `Null` and `NULL` as `null`, etc.\n\n\n'use strict';\n\n\nvar Schema = require('../schema');\n\n\nmodule.exports = new Schema({\n  include: [\n    require('./failsafe')\n  ],\n  implicit: [\n    require('../type/null'),\n    require('../type/bool'),\n    require('../type/int'),\n    require('../type/float')\n  ]\n});\n\n},{\"../schema\":26,\"../type/bool\":34,\"../type/float\":35,\"../type/int\":36,\"../type/null\":42,\"./failsafe\":30}],32:[function(require,module,exports){\n'use strict';\n\nvar YAMLException = require('./exception');\n\nvar TYPE_CONSTRUCTOR_OPTIONS = [\n  'kind',\n  'resolve',\n  'construct',\n  'instanceOf',\n  'predicate',\n  'represent',\n  'defaultStyle',\n  'styleAliases'\n];\n\nvar YAML_NODE_KINDS = [\n  'scalar',\n  'sequence',\n  'mapping'\n];\n\nfunction compileStyleAliases(map) {\n  var result = {};\n\n  if (map !== null) {\n    Object.keys(map).forEach(function (style) {\n      map[style].forEach(function (alias) {\n        result[String(alias)] = style;\n      });\n    });\n  }\n\n  return result;\n}\n\nfunction Type(tag, options) {\n  options = options || {};\n\n  Object.keys(options).forEach(function (name) {\n    if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {\n      throw new YAMLException('Unknown option \"' + name + '\" is met in definition of \"' + tag + '\" YAML type.');\n    }\n  });\n\n  // TODO: Add tag format check.\n  this.tag          = tag;\n  this.kind         = options['kind']         || null;\n  this.resolve      = options['resolve']      || function () { return true; };\n  this.construct    = options['construct']    || function (data) { return data; };\n  this.instanceOf   = options['instanceOf']   || null;\n  this.predicate    = options['predicate']    || null;\n  this.represent    = options['represent']    || null;\n  this.defaultStyle = options['defaultStyle'] || null;\n  this.styleAliases = compileStyleAliases(options['styleAliases'] || null);\n\n  if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {\n    throw new YAMLException('Unknown kind \"' + this.kind + '\" is specified for \"' + tag + '\" YAML type.');\n  }\n}\n\nmodule.exports = Type;\n\n},{\"./exception\":23}],33:[function(require,module,exports){\n'use strict';\n\n/*eslint-disable no-bitwise*/\n\nvar NodeBuffer;\n\ntry {\n  // A trick for browserified version, to not include `Buffer` shim\n  var _require = require;\n  NodeBuffer = _require('buffer').Buffer;\n} catch (__) {}\n\nvar Type       = require('../type');\n\n\n// [ 64, 65, 66 ] -> [ padding, CR, LF ]\nvar BASE64_MAP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\\n\\r';\n\n\nfunction resolveYamlBinary(data) {\n  if (data === null) return false;\n\n  var code, idx, bitlen = 0, max = data.length, map = BASE64_MAP;\n\n  // Convert one by one.\n  for (idx = 0; idx < max; idx++) {\n    code = map.indexOf(data.charAt(idx));\n\n    // Skip CR/LF\n    if (code > 64) continue;\n\n    // Fail on illegal characters\n    if (code < 0) return false;\n\n    bitlen += 6;\n  }\n\n  // If there are any bits left, source was corrupted\n  return (bitlen % 8) === 0;\n}\n\nfunction constructYamlBinary(data) {\n  var idx, tailbits,\n      input = data.replace(/[\\r\\n=]/g, ''), // remove CR/LF & padding to simplify scan\n      max = input.length,\n      map = BASE64_MAP,\n      bits = 0,\n      result = [];\n\n  // Collect by 6*4 bits (3 bytes)\n\n  for (idx = 0; idx < max; idx++) {\n    if ((idx % 4 === 0) && idx) {\n      result.push((bits >> 16) & 0xFF);\n      result.push((bits >> 8) & 0xFF);\n      result.push(bits & 0xFF);\n    }\n\n    bits = (bits << 6) | map.indexOf(input.charAt(idx));\n  }\n\n  // Dump tail\n\n  tailbits = (max % 4) * 6;\n\n  if (tailbits === 0) {\n    result.push((bits >> 16) & 0xFF);\n    result.push((bits >> 8) & 0xFF);\n    result.push(bits & 0xFF);\n  } else if (tailbits === 18) {\n    result.push((bits >> 10) & 0xFF);\n    result.push((bits >> 2) & 0xFF);\n  } else if (tailbits === 12) {\n    result.push((bits >> 4) & 0xFF);\n  }\n\n  // Wrap into Buffer for NodeJS and leave Array for browser\n  if (NodeBuffer) return new NodeBuffer(result);\n\n  return result;\n}\n\nfunction representYamlBinary(object /*, style*/) {\n  var result = '', bits = 0, idx, tail,\n      max = object.length,\n      map = BASE64_MAP;\n\n  // Convert every three bytes to 4 ASCII characters.\n\n  for (idx = 0; idx < max; idx++) {\n    if ((idx % 3 === 0) && idx) {\n      result += map[(bits >> 18) & 0x3F];\n      result += map[(bits >> 12) & 0x3F];\n      result += map[(bits >> 6) & 0x3F];\n      result += map[bits & 0x3F];\n    }\n\n    bits = (bits << 8) + object[idx];\n  }\n\n  // Dump tail\n\n  tail = max % 3;\n\n  if (tail === 0) {\n    result += map[(bits >> 18) & 0x3F];\n    result += map[(bits >> 12) & 0x3F];\n    result += map[(bits >> 6) & 0x3F];\n    result += map[bits & 0x3F];\n  } else if (tail === 2) {\n    result += map[(bits >> 10) & 0x3F];\n    result += map[(bits >> 4) & 0x3F];\n    result += map[(bits << 2) & 0x3F];\n    result += map[64];\n  } else if (tail === 1) {\n    result += map[(bits >> 2) & 0x3F];\n    result += map[(bits << 4) & 0x3F];\n    result += map[64];\n    result += map[64];\n  }\n\n  return result;\n}\n\nfunction isBinary(object) {\n  return NodeBuffer && NodeBuffer.isBuffer(object);\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:binary', {\n  kind: 'scalar',\n  resolve: resolveYamlBinary,\n  construct: constructYamlBinary,\n  predicate: isBinary,\n  represent: representYamlBinary\n});\n\n},{\"../type\":32}],34:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../type');\n\nfunction resolveYamlBoolean(data) {\n  if (data === null) return false;\n\n  var max = data.length;\n\n  return (max === 4 && (data === 'true' || data === 'True' || data === 'TRUE')) ||\n         (max === 5 && (data === 'false' || data === 'False' || data === 'FALSE'));\n}\n\nfunction constructYamlBoolean(data) {\n  return data === 'true' ||\n         data === 'True' ||\n         data === 'TRUE';\n}\n\nfunction isBoolean(object) {\n  return Object.prototype.toString.call(object) === '[object Boolean]';\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:bool', {\n  kind: 'scalar',\n  resolve: resolveYamlBoolean,\n  construct: constructYamlBoolean,\n  predicate: isBoolean,\n  represent: {\n    lowercase: function (object) { return object ? 'true' : 'false'; },\n    uppercase: function (object) { return object ? 'TRUE' : 'FALSE'; },\n    camelcase: function (object) { return object ? 'True' : 'False'; }\n  },\n  defaultStyle: 'lowercase'\n});\n\n},{\"../type\":32}],35:[function(require,module,exports){\n'use strict';\n\nvar common = require('../common');\nvar Type   = require('../type');\n\nvar YAML_FLOAT_PATTERN = new RegExp(\n  '^(?:[-+]?(?:[0-9][0-9_]*)\\\\.[0-9_]*(?:[eE][-+][0-9]+)?' +\n  '|\\\\.[0-9_]+(?:[eE][-+][0-9]+)?' +\n  '|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\\\.[0-9_]*' +\n  '|[-+]?\\\\.(?:inf|Inf|INF)' +\n  '|\\\\.(?:nan|NaN|NAN))$');\n\nfunction resolveYamlFloat(data) {\n  if (data === null) return false;\n\n  if (!YAML_FLOAT_PATTERN.test(data)) return false;\n\n  return true;\n}\n\nfunction constructYamlFloat(data) {\n  var value, sign, base, digits;\n\n  value  = data.replace(/_/g, '').toLowerCase();\n  sign   = value[0] === '-' ? -1 : 1;\n  digits = [];\n\n  if ('+-'.indexOf(value[0]) >= 0) {\n    value = value.slice(1);\n  }\n\n  if (value === '.inf') {\n    return (sign === 1) ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;\n\n  } else if (value === '.nan') {\n    return NaN;\n\n  } else if (value.indexOf(':') >= 0) {\n    value.split(':').forEach(function (v) {\n      digits.unshift(parseFloat(v, 10));\n    });\n\n    value = 0.0;\n    base = 1;\n\n    digits.forEach(function (d) {\n      value += d * base;\n      base *= 60;\n    });\n\n    return sign * value;\n\n  }\n  return sign * parseFloat(value, 10);\n}\n\n\nvar SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;\n\nfunction representYamlFloat(object, style) {\n  var res;\n\n  if (isNaN(object)) {\n    switch (style) {\n      case 'lowercase': return '.nan';\n      case 'uppercase': return '.NAN';\n      case 'camelcase': return '.NaN';\n    }\n  } else if (Number.POSITIVE_INFINITY === object) {\n    switch (style) {\n      case 'lowercase': return '.inf';\n      case 'uppercase': return '.INF';\n      case 'camelcase': return '.Inf';\n    }\n  } else if (Number.NEGATIVE_INFINITY === object) {\n    switch (style) {\n      case 'lowercase': return '-.inf';\n      case 'uppercase': return '-.INF';\n      case 'camelcase': return '-.Inf';\n    }\n  } else if (common.isNegativeZero(object)) {\n    return '-0.0';\n  }\n\n  res = object.toString(10);\n\n  // JS stringifier can build scientific format without dots: 5e-100,\n  // while YAML requres dot: 5.e-100. Fix it with simple hack\n\n  return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace('e', '.e') : res;\n}\n\nfunction isFloat(object) {\n  return (Object.prototype.toString.call(object) === '[object Number]') &&\n         (object % 1 !== 0 || common.isNegativeZero(object));\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:float', {\n  kind: 'scalar',\n  resolve: resolveYamlFloat,\n  construct: constructYamlFloat,\n  predicate: isFloat,\n  represent: representYamlFloat,\n  defaultStyle: 'lowercase'\n});\n\n},{\"../common\":21,\"../type\":32}],36:[function(require,module,exports){\n'use strict';\n\nvar common = require('../common');\nvar Type   = require('../type');\n\nfunction isHexCode(c) {\n  return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */)) ||\n         ((0x41/* A */ <= c) && (c <= 0x46/* F */)) ||\n         ((0x61/* a */ <= c) && (c <= 0x66/* f */));\n}\n\nfunction isOctCode(c) {\n  return ((0x30/* 0 */ <= c) && (c <= 0x37/* 7 */));\n}\n\nfunction isDecCode(c) {\n  return ((0x30/* 0 */ <= c) && (c <= 0x39/* 9 */));\n}\n\nfunction resolveYamlInteger(data) {\n  if (data === null) return false;\n\n  var max = data.length,\n      index = 0,\n      hasDigits = false,\n      ch;\n\n  if (!max) return false;\n\n  ch = data[index];\n\n  // sign\n  if (ch === '-' || ch === '+') {\n    ch = data[++index];\n  }\n\n  if (ch === '0') {\n    // 0\n    if (index + 1 === max) return true;\n    ch = data[++index];\n\n    // base 2, base 8, base 16\n\n    if (ch === 'b') {\n      // base 2\n      index++;\n\n      for (; index < max; index++) {\n        ch = data[index];\n        if (ch === '_') continue;\n        if (ch !== '0' && ch !== '1') return false;\n        hasDigits = true;\n      }\n      return hasDigits;\n    }\n\n\n    if (ch === 'x') {\n      // base 16\n      index++;\n\n      for (; index < max; index++) {\n        ch = data[index];\n        if (ch === '_') continue;\n        if (!isHexCode(data.charCodeAt(index))) return false;\n        hasDigits = true;\n      }\n      return hasDigits;\n    }\n\n    // base 8\n    for (; index < max; index++) {\n      ch = data[index];\n      if (ch === '_') continue;\n      if (!isOctCode(data.charCodeAt(index))) return false;\n      hasDigits = true;\n    }\n    return hasDigits;\n  }\n\n  // base 10 (except 0) or base 60\n\n  for (; index < max; index++) {\n    ch = data[index];\n    if (ch === '_') continue;\n    if (ch === ':') break;\n    if (!isDecCode(data.charCodeAt(index))) {\n      return false;\n    }\n    hasDigits = true;\n  }\n\n  if (!hasDigits) return false;\n\n  // if !base60 - done;\n  if (ch !== ':') return true;\n\n  // base60 almost not used, no needs to optimize\n  return /^(:[0-5]?[0-9])+$/.test(data.slice(index));\n}\n\nfunction constructYamlInteger(data) {\n  var value = data, sign = 1, ch, base, digits = [];\n\n  if (value.indexOf('_') !== -1) {\n    value = value.replace(/_/g, '');\n  }\n\n  ch = value[0];\n\n  if (ch === '-' || ch === '+') {\n    if (ch === '-') sign = -1;\n    value = value.slice(1);\n    ch = value[0];\n  }\n\n  if (value === '0') return 0;\n\n  if (ch === '0') {\n    if (value[1] === 'b') return sign * parseInt(value.slice(2), 2);\n    if (value[1] === 'x') return sign * parseInt(value, 16);\n    return sign * parseInt(value, 8);\n  }\n\n  if (value.indexOf(':') !== -1) {\n    value.split(':').forEach(function (v) {\n      digits.unshift(parseInt(v, 10));\n    });\n\n    value = 0;\n    base = 1;\n\n    digits.forEach(function (d) {\n      value += (d * base);\n      base *= 60;\n    });\n\n    return sign * value;\n\n  }\n\n  return sign * parseInt(value, 10);\n}\n\nfunction isInteger(object) {\n  return (Object.prototype.toString.call(object)) === '[object Number]' &&\n         (object % 1 === 0 && !common.isNegativeZero(object));\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:int', {\n  kind: 'scalar',\n  resolve: resolveYamlInteger,\n  construct: constructYamlInteger,\n  predicate: isInteger,\n  represent: {\n    binary:      function (object) { return '0b' + object.toString(2); },\n    octal:       function (object) { return '0'  + object.toString(8); },\n    decimal:     function (object) { return        object.toString(10); },\n    hexadecimal: function (object) { return '0x' + object.toString(16).toUpperCase(); }\n  },\n  defaultStyle: 'decimal',\n  styleAliases: {\n    binary:      [ 2,  'bin' ],\n    octal:       [ 8,  'oct' ],\n    decimal:     [ 10, 'dec' ],\n    hexadecimal: [ 16, 'hex' ]\n  }\n});\n\n},{\"../common\":21,\"../type\":32}],37:[function(require,module,exports){\n'use strict';\n\nvar esprima;\n\n// Browserified version does not have esprima\n//\n// 1. For node.js just require module as deps\n// 2. For browser try to require mudule via external AMD system.\n//    If not found - try to fallback to window.esprima. If not\n//    found too - then fail to parse.\n//\ntry {\n  // workaround to exclude package from browserify list.\n  var _require = require;\n  esprima = _require('esprima');\n} catch (_) {\n  /*global window */\n  if (typeof window !== 'undefined') esprima = window.esprima;\n}\n\nvar Type = require('../../type');\n\nfunction resolveJavascriptFunction(data) {\n  if (data === null) return false;\n\n  try {\n    var source = '(' + data + ')',\n        ast    = esprima.parse(source, { range: true });\n\n    if (ast.type                    !== 'Program'             ||\n        ast.body.length             !== 1                     ||\n        ast.body[0].type            !== 'ExpressionStatement' ||\n        ast.body[0].expression.type !== 'FunctionExpression') {\n      return false;\n    }\n\n    return true;\n  } catch (err) {\n    return false;\n  }\n}\n\nfunction constructJavascriptFunction(data) {\n  /*jslint evil:true*/\n\n  var source = '(' + data + ')',\n      ast    = esprima.parse(source, { range: true }),\n      params = [],\n      body;\n\n  if (ast.type                    !== 'Program'             ||\n      ast.body.length             !== 1                     ||\n      ast.body[0].type            !== 'ExpressionStatement' ||\n      ast.body[0].expression.type !== 'FunctionExpression') {\n    throw new Error('Failed to resolve function');\n  }\n\n  ast.body[0].expression.params.forEach(function (param) {\n    params.push(param.name);\n  });\n\n  body = ast.body[0].expression.body.range;\n\n  // Esprima's ranges include the first '{' and the last '}' characters on\n  // function expressions. So cut them out.\n  /*eslint-disable no-new-func*/\n  return new Function(params, source.slice(body[0] + 1, body[1] - 1));\n}\n\nfunction representJavascriptFunction(object /*, style*/) {\n  return object.toString();\n}\n\nfunction isFunction(object) {\n  return Object.prototype.toString.call(object) === '[object Function]';\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:js/function', {\n  kind: 'scalar',\n  resolve: resolveJavascriptFunction,\n  construct: constructJavascriptFunction,\n  predicate: isFunction,\n  represent: representJavascriptFunction\n});\n\n},{\"../../type\":32}],38:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../../type');\n\nfunction resolveJavascriptRegExp(data) {\n  if (data === null) return false;\n  if (data.length === 0) return false;\n\n  var regexp = data,\n      tail   = /\\/([gim]*)$/.exec(data),\n      modifiers = '';\n\n  // if regexp starts with '/' it can have modifiers and must be properly closed\n  // `/foo/gim` - modifiers tail can be maximum 3 chars\n  if (regexp[0] === '/') {\n    if (tail) modifiers = tail[1];\n\n    if (modifiers.length > 3) return false;\n    // if expression starts with /, is should be properly terminated\n    if (regexp[regexp.length - modifiers.length - 1] !== '/') return false;\n  }\n\n  return true;\n}\n\nfunction constructJavascriptRegExp(data) {\n  var regexp = data,\n      tail   = /\\/([gim]*)$/.exec(data),\n      modifiers = '';\n\n  // `/foo/gim` - tail can be maximum 4 chars\n  if (regexp[0] === '/') {\n    if (tail) modifiers = tail[1];\n    regexp = regexp.slice(1, regexp.length - modifiers.length - 1);\n  }\n\n  return new RegExp(regexp, modifiers);\n}\n\nfunction representJavascriptRegExp(object /*, style*/) {\n  var result = '/' + object.source + '/';\n\n  if (object.global) result += 'g';\n  if (object.multiline) result += 'm';\n  if (object.ignoreCase) result += 'i';\n\n  return result;\n}\n\nfunction isRegExp(object) {\n  return Object.prototype.toString.call(object) === '[object RegExp]';\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:js/regexp', {\n  kind: 'scalar',\n  resolve: resolveJavascriptRegExp,\n  construct: constructJavascriptRegExp,\n  predicate: isRegExp,\n  represent: representJavascriptRegExp\n});\n\n},{\"../../type\":32}],39:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../../type');\n\nfunction resolveJavascriptUndefined() {\n  return true;\n}\n\nfunction constructJavascriptUndefined() {\n  /*eslint-disable no-undefined*/\n  return undefined;\n}\n\nfunction representJavascriptUndefined() {\n  return '';\n}\n\nfunction isUndefined(object) {\n  return typeof object === 'undefined';\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:js/undefined', {\n  kind: 'scalar',\n  resolve: resolveJavascriptUndefined,\n  construct: constructJavascriptUndefined,\n  predicate: isUndefined,\n  represent: representJavascriptUndefined\n});\n\n},{\"../../type\":32}],40:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../type');\n\nmodule.exports = new Type('tag:yaml.org,2002:map', {\n  kind: 'mapping',\n  construct: function (data) { return data !== null ? data : {}; }\n});\n\n},{\"../type\":32}],41:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../type');\n\nfunction resolveYamlMerge(data) {\n  return data === '<<' || data === null;\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:merge', {\n  kind: 'scalar',\n  resolve: resolveYamlMerge\n});\n\n},{\"../type\":32}],42:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../type');\n\nfunction resolveYamlNull(data) {\n  if (data === null) return true;\n\n  var max = data.length;\n\n  return (max === 1 && data === '~') ||\n         (max === 4 && (data === 'null' || data === 'Null' || data === 'NULL'));\n}\n\nfunction constructYamlNull() {\n  return null;\n}\n\nfunction isNull(object) {\n  return object === null;\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:null', {\n  kind: 'scalar',\n  resolve: resolveYamlNull,\n  construct: constructYamlNull,\n  predicate: isNull,\n  represent: {\n    canonical: function () { return '~';    },\n    lowercase: function () { return 'null'; },\n    uppercase: function () { return 'NULL'; },\n    camelcase: function () { return 'Null'; }\n  },\n  defaultStyle: 'lowercase'\n});\n\n},{\"../type\":32}],43:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../type');\n\nvar _hasOwnProperty = Object.prototype.hasOwnProperty;\nvar _toString       = Object.prototype.toString;\n\nfunction resolveYamlOmap(data) {\n  if (data === null) return true;\n\n  var objectKeys = [], index, length, pair, pairKey, pairHasKey,\n      object = data;\n\n  for (index = 0, length = object.length; index < length; index += 1) {\n    pair = object[index];\n    pairHasKey = false;\n\n    if (_toString.call(pair) !== '[object Object]') return false;\n\n    for (pairKey in pair) {\n      if (_hasOwnProperty.call(pair, pairKey)) {\n        if (!pairHasKey) pairHasKey = true;\n        else return false;\n      }\n    }\n\n    if (!pairHasKey) return false;\n\n    if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);\n    else return false;\n  }\n\n  return true;\n}\n\nfunction constructYamlOmap(data) {\n  return data !== null ? data : [];\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:omap', {\n  kind: 'sequence',\n  resolve: resolveYamlOmap,\n  construct: constructYamlOmap\n});\n\n},{\"../type\":32}],44:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../type');\n\nvar _toString = Object.prototype.toString;\n\nfunction resolveYamlPairs(data) {\n  if (data === null) return true;\n\n  var index, length, pair, keys, result,\n      object = data;\n\n  result = new Array(object.length);\n\n  for (index = 0, length = object.length; index < length; index += 1) {\n    pair = object[index];\n\n    if (_toString.call(pair) !== '[object Object]') return false;\n\n    keys = Object.keys(pair);\n\n    if (keys.length !== 1) return false;\n\n    result[index] = [ keys[0], pair[keys[0]] ];\n  }\n\n  return true;\n}\n\nfunction constructYamlPairs(data) {\n  if (data === null) return [];\n\n  var index, length, pair, keys, result,\n      object = data;\n\n  result = new Array(object.length);\n\n  for (index = 0, length = object.length; index < length; index += 1) {\n    pair = object[index];\n\n    keys = Object.keys(pair);\n\n    result[index] = [ keys[0], pair[keys[0]] ];\n  }\n\n  return result;\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:pairs', {\n  kind: 'sequence',\n  resolve: resolveYamlPairs,\n  construct: constructYamlPairs\n});\n\n},{\"../type\":32}],45:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../type');\n\nmodule.exports = new Type('tag:yaml.org,2002:seq', {\n  kind: 'sequence',\n  construct: function (data) { return data !== null ? data : []; }\n});\n\n},{\"../type\":32}],46:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../type');\n\nvar _hasOwnProperty = Object.prototype.hasOwnProperty;\n\nfunction resolveYamlSet(data) {\n  if (data === null) return true;\n\n  var key, object = data;\n\n  for (key in object) {\n    if (_hasOwnProperty.call(object, key)) {\n      if (object[key] !== null) return false;\n    }\n  }\n\n  return true;\n}\n\nfunction constructYamlSet(data) {\n  return data !== null ? data : {};\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:set', {\n  kind: 'mapping',\n  resolve: resolveYamlSet,\n  construct: constructYamlSet\n});\n\n},{\"../type\":32}],47:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../type');\n\nmodule.exports = new Type('tag:yaml.org,2002:str', {\n  kind: 'scalar',\n  construct: function (data) { return data !== null ? data : ''; }\n});\n\n},{\"../type\":32}],48:[function(require,module,exports){\n'use strict';\n\nvar Type = require('../type');\n\nvar YAML_DATE_REGEXP = new RegExp(\n  '^([0-9][0-9][0-9][0-9])'          + // [1] year\n  '-([0-9][0-9])'                    + // [2] month\n  '-([0-9][0-9])$');                   // [3] day\n\nvar YAML_TIMESTAMP_REGEXP = new RegExp(\n  '^([0-9][0-9][0-9][0-9])'          + // [1] year\n  '-([0-9][0-9]?)'                   + // [2] month\n  '-([0-9][0-9]?)'                   + // [3] day\n  '(?:[Tt]|[ \\\\t]+)'                 + // ...\n  '([0-9][0-9]?)'                    + // [4] hour\n  ':([0-9][0-9])'                    + // [5] minute\n  ':([0-9][0-9])'                    + // [6] second\n  '(?:\\\\.([0-9]*))?'                 + // [7] fraction\n  '(?:[ \\\\t]*(Z|([-+])([0-9][0-9]?)' + // [8] tz [9] tz_sign [10] tz_hour\n  '(?::([0-9][0-9]))?))?$');           // [11] tz_minute\n\nfunction resolveYamlTimestamp(data) {\n  if (data === null) return false;\n  if (YAML_DATE_REGEXP.exec(data) !== null) return true;\n  if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;\n  return false;\n}\n\nfunction constructYamlTimestamp(data) {\n  var match, year, month, day, hour, minute, second, fraction = 0,\n      delta = null, tz_hour, tz_minute, date;\n\n  match = YAML_DATE_REGEXP.exec(data);\n  if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);\n\n  if (match === null) throw new Error('Date resolve error');\n\n  // match: [1] year [2] month [3] day\n\n  year = +(match[1]);\n  month = +(match[2]) - 1; // JS month starts with 0\n  day = +(match[3]);\n\n  if (!match[4]) { // no hour\n    return new Date(Date.UTC(year, month, day));\n  }\n\n  // match: [4] hour [5] minute [6] second [7] fraction\n\n  hour = +(match[4]);\n  minute = +(match[5]);\n  second = +(match[6]);\n\n  if (match[7]) {\n    fraction = match[7].slice(0, 3);\n    while (fraction.length < 3) { // milli-seconds\n      fraction += '0';\n    }\n    fraction = +fraction;\n  }\n\n  // match: [8] tz [9] tz_sign [10] tz_hour [11] tz_minute\n\n  if (match[9]) {\n    tz_hour = +(match[10]);\n    tz_minute = +(match[11] || 0);\n    delta = (tz_hour * 60 + tz_minute) * 60000; // delta in mili-seconds\n    if (match[9] === '-') delta = -delta;\n  }\n\n  date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));\n\n  if (delta) date.setTime(date.getTime() - delta);\n\n  return date;\n}\n\nfunction representYamlTimestamp(object /*, style*/) {\n  return object.toISOString();\n}\n\nmodule.exports = new Type('tag:yaml.org,2002:timestamp', {\n  kind: 'scalar',\n  resolve: resolveYamlTimestamp,\n  construct: constructYamlTimestamp,\n  instanceOf: Date,\n  represent: representYamlTimestamp\n});\n\n},{\"../type\":32}],49:[function(require,module,exports){\nvar baseIndexOf = require('../internal/baseIndexOf'),\n    binaryIndex = require('../internal/binaryIndex');\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * Gets the index at which the first occurrence of `value` is found in `array`\n * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)\n * for equality comparisons. If `fromIndex` is negative, it's used as the offset\n * from the end of `array`. If `array` is sorted providing `true` for `fromIndex`\n * performs a faster binary search.\n *\n * @static\n * @memberOf _\n * @category Array\n * @param {Array} array The array to search.\n * @param {*} value The value to search for.\n * @param {boolean|number} [fromIndex=0] The index to search from or `true`\n *  to perform a binary search on a sorted array.\n * @returns {number} Returns the index of the matched value, else `-1`.\n * @example\n *\n * _.indexOf([1, 2, 1, 2], 2);\n * // => 1\n *\n * // using `fromIndex`\n * _.indexOf([1, 2, 1, 2], 2, 2);\n * // => 3\n *\n * // performing a binary search\n * _.indexOf([1, 1, 2, 2], 2, true);\n * // => 2\n */\nfunction indexOf(array, value, fromIndex) {\n  var length = array ? array.length : 0;\n  if (!length) {\n    return -1;\n  }\n  if (typeof fromIndex == 'number') {\n    fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;\n  } else if (fromIndex) {\n    var index = binaryIndex(array, value);\n    if (index < length &&\n        (value === value ? (value === array[index]) : (array[index] !== array[index]))) {\n      return index;\n    }\n    return -1;\n  }\n  return baseIndexOf(array, value, fromIndex || 0);\n}\n\nmodule.exports = indexOf;\n\n},{\"../internal/baseIndexOf\":78,\"../internal/binaryIndex\":92}],50:[function(require,module,exports){\n/**\n * Gets the last element of `array`.\n *\n * @static\n * @memberOf _\n * @category Array\n * @param {Array} array The array to query.\n * @returns {*} Returns the last element of `array`.\n * @example\n *\n * _.last([1, 2, 3]);\n * // => 3\n */\nfunction last(array) {\n  var length = array ? array.length : 0;\n  return length ? array[length - 1] : undefined;\n}\n\nmodule.exports = last;\n\n},{}],51:[function(require,module,exports){\nvar LazyWrapper = require('../internal/LazyWrapper'),\n    LodashWrapper = require('../internal/LodashWrapper'),\n    baseLodash = require('../internal/baseLodash'),\n    isArray = require('../lang/isArray'),\n    isObjectLike = require('../internal/isObjectLike'),\n    wrapperClone = require('../internal/wrapperClone');\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Creates a `lodash` object which wraps `value` to enable implicit chaining.\n * Methods that operate on and return arrays, collections, and functions can\n * be chained together. Methods that retrieve a single value or may return a\n * primitive value will automatically end the chain returning the unwrapped\n * value. Explicit chaining may be enabled using `_.chain`. The execution of\n * chained methods is lazy, that is, execution is deferred until `_#value`\n * is implicitly or explicitly called.\n *\n * Lazy evaluation allows several methods to support shortcut fusion. Shortcut\n * fusion is an optimization strategy which merge iteratee calls; this can help\n * to avoid the creation of intermediate data structures and greatly reduce the\n * number of iteratee executions.\n *\n * Chaining is supported in custom builds as long as the `_#value` method is\n * directly or indirectly included in the build.\n *\n * In addition to lodash methods, wrappers have `Array` and `String` methods.\n *\n * The wrapper `Array` methods are:\n * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`,\n * `splice`, and `unshift`\n *\n * The wrapper `String` methods are:\n * `replace` and `split`\n *\n * The wrapper methods that support shortcut fusion are:\n * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`,\n * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`,\n * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`,\n * and `where`\n *\n * The chainable wrapper methods are:\n * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`,\n * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`,\n * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`,\n * `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`,\n * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`,\n * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,\n * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,\n * `invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`,\n * `matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`,\n * `modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`,\n * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`,\n * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`,\n * `reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`,\n * `sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`,\n * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`,\n * `transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`,\n * `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith`\n *\n * The wrapper methods that are **not** chainable by default are:\n * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`,\n * `deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`,\n * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`,\n * `floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`,\n * `inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,\n * `isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`,\n * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`,\n * `isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`,\n * `last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`,\n * `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`,\n * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`,\n * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`,\n * `startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`,\n * `unescape`, `uniqueId`, `value`, and `words`\n *\n * The wrapper method `sample` will return a wrapped value when `n` is provided,\n * otherwise an unwrapped value is returned.\n *\n * @name _\n * @constructor\n * @category Chain\n * @param {*} value The value to wrap in a `lodash` instance.\n * @returns {Object} Returns the new `lodash` wrapper instance.\n * @example\n *\n * var wrapped = _([1, 2, 3]);\n *\n * // returns an unwrapped value\n * wrapped.reduce(function(total, n) {\n *   return total + n;\n * });\n * // => 6\n *\n * // returns a wrapped value\n * var squares = wrapped.map(function(n) {\n *   return n * n;\n * });\n *\n * _.isArray(squares);\n * // => false\n *\n * _.isArray(squares.value());\n * // => true\n */\nfunction lodash(value) {\n  if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {\n    if (value instanceof LodashWrapper) {\n      return value;\n    }\n    if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) {\n      return wrapperClone(value);\n    }\n  }\n  return new LodashWrapper(value);\n}\n\n// Ensure wrappers are instances of `baseLodash`.\nlodash.prototype = baseLodash.prototype;\n\nmodule.exports = lodash;\n\n},{\"../internal/LazyWrapper\":60,\"../internal/LodashWrapper\":61,\"../internal/baseLodash\":82,\"../internal/isObjectLike\":126,\"../internal/wrapperClone\":137,\"../lang/isArray\":140}],52:[function(require,module,exports){\nmodule.exports = require('./forEach');\n\n},{\"./forEach\":54}],53:[function(require,module,exports){\nvar baseEach = require('../internal/baseEach'),\n    createFind = require('../internal/createFind');\n\n/**\n * Iterates over elements of `collection`, returning the first element\n * `predicate` returns truthy for. The predicate is bound to `thisArg` and\n * invoked with three arguments: (value, index|key, collection).\n *\n * If a property name is provided for `predicate` the created `_.property`\n * style callback returns the property value of the given element.\n *\n * If a value is also provided for `thisArg` the created `_.matchesProperty`\n * style callback returns `true` for elements that have a matching property\n * value, else `false`.\n *\n * If an object is provided for `predicate` the created `_.matches` style\n * callback returns `true` for elements that have the properties of the given\n * object, else `false`.\n *\n * @static\n * @memberOf _\n * @alias detect\n * @category Collection\n * @param {Array|Object|string} collection The collection to search.\n * @param {Function|Object|string} [predicate=_.identity] The function invoked\n *  per iteration.\n * @param {*} [thisArg] The `this` binding of `predicate`.\n * @returns {*} Returns the matched element, else `undefined`.\n * @example\n *\n * var users = [\n *   { 'user': 'barney',  'age': 36, 'active': true },\n *   { 'user': 'fred',    'age': 40, 'active': false },\n *   { 'user': 'pebbles', 'age': 1,  'active': true }\n * ];\n *\n * _.result(_.find(users, function(chr) {\n *   return chr.age < 40;\n * }), 'user');\n * // => 'barney'\n *\n * // using the `_.matches` callback shorthand\n * _.result(_.find(users, { 'age': 1, 'active': true }), 'user');\n * // => 'pebbles'\n *\n * // using the `_.matchesProperty` callback shorthand\n * _.result(_.find(users, 'active', false), 'user');\n * // => 'fred'\n *\n * // using the `_.property` callback shorthand\n * _.result(_.find(users, 'active'), 'user');\n * // => 'barney'\n */\nvar find = createFind(baseEach);\n\nmodule.exports = find;\n\n},{\"../internal/baseEach\":71,\"../internal/createFind\":102}],54:[function(require,module,exports){\nvar arrayEach = require('../internal/arrayEach'),\n    baseEach = require('../internal/baseEach'),\n    createForEach = require('../internal/createForEach');\n\n/**\n * Iterates over elements of `collection` invoking `iteratee` for each element.\n * The `iteratee` is bound to `thisArg` and invoked with three arguments:\n * (value, index|key, collection). Iteratee functions may exit iteration early\n * by explicitly returning `false`.\n *\n * **Note:** As with other \"Collections\" methods, objects with a \"length\" property\n * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`\n * may be used for object iteration.\n *\n * @static\n * @memberOf _\n * @alias each\n * @category Collection\n * @param {Array|Object|string} collection The collection to iterate over.\n * @param {Function} [iteratee=_.identity] The function invoked per iteration.\n * @param {*} [thisArg] The `this` binding of `iteratee`.\n * @returns {Array|Object|string} Returns `collection`.\n * @example\n *\n * _([1, 2]).forEach(function(n) {\n *   console.log(n);\n * }).value();\n * // => logs each value from left to right and returns the array\n *\n * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) {\n *   console.log(n, key);\n * });\n * // => logs each value-key pair and returns the object (iteration order is not guaranteed)\n */\nvar forEach = createForEach(arrayEach, baseEach);\n\nmodule.exports = forEach;\n\n},{\"../internal/arrayEach\":63,\"../internal/baseEach\":71,\"../internal/createForEach\":103}],55:[function(require,module,exports){\nvar baseIndexOf = require('../internal/baseIndexOf'),\n    getLength = require('../internal/getLength'),\n    isArray = require('../lang/isArray'),\n    isIterateeCall = require('../internal/isIterateeCall'),\n    isLength = require('../internal/isLength'),\n    isString = require('../lang/isString'),\n    values = require('../object/values');\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * Checks if `target` is in `collection` using\n * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)\n * for equality comparisons. If `fromIndex` is negative, it's used as the offset\n * from the end of `collection`.\n *\n * @static\n * @memberOf _\n * @alias contains, include\n * @category Collection\n * @param {Array|Object|string} collection The collection to search.\n * @param {*} target The value to search for.\n * @param {number} [fromIndex=0] The index to search from.\n * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.\n * @returns {boolean} Returns `true` if a matching element is found, else `false`.\n * @example\n *\n * _.includes([1, 2, 3], 1);\n * // => true\n *\n * _.includes([1, 2, 3], 1, 2);\n * // => false\n *\n * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');\n * // => true\n *\n * _.includes('pebbles', 'eb');\n * // => true\n */\nfunction includes(collection, target, fromIndex, guard) {\n  var length = collection ? getLength(collection) : 0;\n  if (!isLength(length)) {\n    collection = values(collection);\n    length = collection.length;\n  }\n  if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {\n    fromIndex = 0;\n  } else {\n    fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);\n  }\n  return (typeof collection == 'string' || !isArray(collection) && isString(collection))\n    ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1)\n    : (!!length && baseIndexOf(collection, target, fromIndex) > -1);\n}\n\nmodule.exports = includes;\n\n},{\"../internal/baseIndexOf\":78,\"../internal/getLength\":112,\"../internal/isIterateeCall\":122,\"../internal/isLength\":125,\"../lang/isArray\":140,\"../lang/isString\":146,\"../object/values\":152}],56:[function(require,module,exports){\nvar arrayMap = require('../internal/arrayMap'),\n    baseCallback = require('../internal/baseCallback'),\n    baseMap = require('../internal/baseMap'),\n    isArray = require('../lang/isArray');\n\n/**\n * Creates an array of values by running each element in `collection` through\n * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three\n * arguments: (value, index|key, collection).\n *\n * If a property name is provided for `iteratee` the created `_.property`\n * style callback returns the property value of the given element.\n *\n * If a value is also provided for `thisArg` the created `_.matchesProperty`\n * style callback returns `true` for elements that have a matching property\n * value, else `false`.\n *\n * If an object is provided for `iteratee` the created `_.matches` style\n * callback returns `true` for elements that have the properties of the given\n * object, else `false`.\n *\n * Many lodash methods are guarded to work as iteratees for methods like\n * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.\n *\n * The guarded methods are:\n * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`,\n * `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`,\n * `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`,\n * `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`,\n * `sum`, `uniq`, and `words`\n *\n * @static\n * @memberOf _\n * @alias collect\n * @category Collection\n * @param {Array|Object|string} collection The collection to iterate over.\n * @param {Function|Object|string} [iteratee=_.identity] The function invoked\n *  per iteration.\n * @param {*} [thisArg] The `this` binding of `iteratee`.\n * @returns {Array} Returns the new mapped array.\n * @example\n *\n * function timesThree(n) {\n *   return n * 3;\n * }\n *\n * _.map([1, 2], timesThree);\n * // => [3, 6]\n *\n * _.map({ 'a': 1, 'b': 2 }, timesThree);\n * // => [3, 6] (iteration order is not guaranteed)\n *\n * var users = [\n *   { 'user': 'barney' },\n *   { 'user': 'fred' }\n * ];\n *\n * // using the `_.property` callback shorthand\n * _.map(users, 'user');\n * // => ['barney', 'fred']\n */\nfunction map(collection, iteratee, thisArg) {\n  var func = isArray(collection) ? arrayMap : baseMap;\n  iteratee = baseCallback(iteratee, thisArg, 3);\n  return func(collection, iteratee);\n}\n\nmodule.exports = map;\n\n},{\"../internal/arrayMap\":64,\"../internal/baseCallback\":67,\"../internal/baseMap\":83,\"../lang/isArray\":140}],57:[function(require,module,exports){\nvar getNative = require('../internal/getNative');\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeNow = getNative(Date, 'now');\n\n/**\n * Gets the number of milliseconds that have elapsed since the Unix epoch\n * (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @category Date\n * @example\n *\n * _.defer(function(stamp) {\n *   console.log(_.now() - stamp);\n * }, _.now());\n * // => logs the number of milliseconds it took for the deferred function to be invoked\n */\nvar now = nativeNow || function() {\n  return new Date().getTime();\n};\n\nmodule.exports = now;\n\n},{\"../internal/getNative\":114}],58:[function(require,module,exports){\nvar createWrapper = require('../internal/createWrapper'),\n    replaceHolders = require('../internal/replaceHolders'),\n    restParam = require('./restParam');\n\n/** Used to compose bitmasks for wrapper metadata. */\nvar BIND_FLAG = 1,\n    PARTIAL_FLAG = 32;\n\n/**\n * Creates a function that invokes `func` with the `this` binding of `thisArg`\n * and prepends any additional `_.bind` arguments to those provided to the\n * bound function.\n *\n * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,\n * may be used as a placeholder for partially applied arguments.\n *\n * **Note:** Unlike native `Function#bind` this method does not set the \"length\"\n * property of bound functions.\n *\n * @static\n * @memberOf _\n * @category Function\n * @param {Function} func The function to bind.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {...*} [partials] The arguments to be partially applied.\n * @returns {Function} Returns the new bound function.\n * @example\n *\n * var greet = function(greeting, punctuation) {\n *   return greeting + ' ' + this.user + punctuation;\n * };\n *\n * var object = { 'user': 'fred' };\n *\n * var bound = _.bind(greet, object, 'hi');\n * bound('!');\n * // => 'hi fred!'\n *\n * // using placeholders\n * var bound = _.bind(greet, object, _, '!');\n * bound('hi');\n * // => 'hi fred!'\n */\nvar bind = restParam(function(func, thisArg, partials) {\n  var bitmask = BIND_FLAG;\n  if (partials.length) {\n    var holders = replaceHolders(partials, bind.placeholder);\n    bitmask |= PARTIAL_FLAG;\n  }\n  return createWrapper(func, bitmask, thisArg, partials, holders);\n});\n\n// Assign default placeholders.\nbind.placeholder = {};\n\nmodule.exports = bind;\n\n},{\"../internal/createWrapper\":106,\"../internal/replaceHolders\":132,\"./restParam\":59}],59:[function(require,module,exports){\n/** Used as the `TypeError` message for \"Functions\" methods. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * Creates a function that invokes `func` with the `this` binding of the\n * created function and arguments from `start` and beyond provided as an array.\n *\n * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/Web/JavaScript/Reference/Functions/rest_parameters).\n *\n * @static\n * @memberOf _\n * @category Function\n * @param {Function} func The function to apply a rest parameter to.\n * @param {number} [start=func.length-1] The start position of the rest parameter.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var say = _.restParam(function(what, names) {\n *   return what + ' ' + _.initial(names).join(', ') +\n *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);\n * });\n *\n * say('hello', 'fred', 'barney', 'pebbles');\n * // => 'hello fred, barney, & pebbles'\n */\nfunction restParam(func, start) {\n  if (typeof func != 'function') {\n    throw new TypeError(FUNC_ERROR_TEXT);\n  }\n  start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);\n  return function() {\n    var args = arguments,\n        index = -1,\n        length = nativeMax(args.length - start, 0),\n        rest = Array(length);\n\n    while (++index < length) {\n      rest[index] = args[start + index];\n    }\n    switch (start) {\n      case 0: return func.call(this, rest);\n      case 1: return func.call(this, args[0], rest);\n      case 2: return func.call(this, args[0], args[1], rest);\n    }\n    var otherArgs = Array(start + 1);\n    index = -1;\n    while (++index < start) {\n      otherArgs[index] = args[index];\n    }\n    otherArgs[start] = rest;\n    return func.apply(this, otherArgs);\n  };\n}\n\nmodule.exports = restParam;\n\n},{}],60:[function(require,module,exports){\nvar baseCreate = require('./baseCreate'),\n    baseLodash = require('./baseLodash');\n\n/** Used as references for `-Infinity` and `Infinity`. */\nvar POSITIVE_INFINITY = Number.POSITIVE_INFINITY;\n\n/**\n * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.\n *\n * @private\n * @param {*} value The value to wrap.\n */\nfunction LazyWrapper(value) {\n  this.__wrapped__ = value;\n  this.__actions__ = [];\n  this.__dir__ = 1;\n  this.__filtered__ = false;\n  this.__iteratees__ = [];\n  this.__takeCount__ = POSITIVE_INFINITY;\n  this.__views__ = [];\n}\n\nLazyWrapper.prototype = baseCreate(baseLodash.prototype);\nLazyWrapper.prototype.constructor = LazyWrapper;\n\nmodule.exports = LazyWrapper;\n\n},{\"./baseCreate\":70,\"./baseLodash\":82}],61:[function(require,module,exports){\nvar baseCreate = require('./baseCreate'),\n    baseLodash = require('./baseLodash');\n\n/**\n * The base constructor for creating `lodash` wrapper objects.\n *\n * @private\n * @param {*} value The value to wrap.\n * @param {boolean} [chainAll] Enable chaining for all wrapper methods.\n * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value.\n */\nfunction LodashWrapper(value, chainAll, actions) {\n  this.__wrapped__ = value;\n  this.__actions__ = actions || [];\n  this.__chain__ = !!chainAll;\n}\n\nLodashWrapper.prototype = baseCreate(baseLodash.prototype);\nLodashWrapper.prototype.constructor = LodashWrapper;\n\nmodule.exports = LodashWrapper;\n\n},{\"./baseCreate\":70,\"./baseLodash\":82}],62:[function(require,module,exports){\n/**\n * Copies the values of `source` to `array`.\n *\n * @private\n * @param {Array} source The array to copy values from.\n * @param {Array} [array=[]] The array to copy values to.\n * @returns {Array} Returns `array`.\n */\nfunction arrayCopy(source, array) {\n  var index = -1,\n      length = source.length;\n\n  array || (array = Array(length));\n  while (++index < length) {\n    array[index] = source[index];\n  }\n  return array;\n}\n\nmodule.exports = arrayCopy;\n\n},{}],63:[function(require,module,exports){\n/**\n * A specialized version of `_.forEach` for arrays without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns `array`.\n */\nfunction arrayEach(array, iteratee) {\n  var index = -1,\n      length = array.length;\n\n  while (++index < length) {\n    if (iteratee(array[index], index, array) === false) {\n      break;\n    }\n  }\n  return array;\n}\n\nmodule.exports = arrayEach;\n\n},{}],64:[function(require,module,exports){\n/**\n * A specialized version of `_.map` for arrays without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction arrayMap(array, iteratee) {\n  var index = -1,\n      length = array.length,\n      result = Array(length);\n\n  while (++index < length) {\n    result[index] = iteratee(array[index], index, array);\n  }\n  return result;\n}\n\nmodule.exports = arrayMap;\n\n},{}],65:[function(require,module,exports){\n/**\n * A specialized version of `_.some` for arrays without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Array} array The array to iterate over.\n * @param {Function} predicate The function invoked per iteration.\n * @returns {boolean} Returns `true` if any element passes the predicate check,\n *  else `false`.\n */\nfunction arraySome(array, predicate) {\n  var index = -1,\n      length = array.length;\n\n  while (++index < length) {\n    if (predicate(array[index], index, array)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nmodule.exports = arraySome;\n\n},{}],66:[function(require,module,exports){\nvar baseCopy = require('./baseCopy'),\n    keys = require('../object/keys');\n\n/**\n * The base implementation of `_.assign` without support for argument juggling,\n * multiple sources, and `customizer` functions.\n *\n * @private\n * @param {Object} object The destination object.\n * @param {Object} source The source object.\n * @returns {Object} Returns `object`.\n */\nfunction baseAssign(object, source) {\n  return source == null\n    ? object\n    : baseCopy(source, keys(source), object);\n}\n\nmodule.exports = baseAssign;\n\n},{\"../object/keys\":149,\"./baseCopy\":69}],67:[function(require,module,exports){\nvar baseMatches = require('./baseMatches'),\n    baseMatchesProperty = require('./baseMatchesProperty'),\n    bindCallback = require('./bindCallback'),\n    identity = require('../utility/identity'),\n    property = require('../utility/property');\n\n/**\n * The base implementation of `_.callback` which supports specifying the\n * number of arguments to provide to `func`.\n *\n * @private\n * @param {*} [func=_.identity] The value to convert to a callback.\n * @param {*} [thisArg] The `this` binding of `func`.\n * @param {number} [argCount] The number of arguments to provide to `func`.\n * @returns {Function} Returns the callback.\n */\nfunction baseCallback(func, thisArg, argCount) {\n  var type = typeof func;\n  if (type == 'function') {\n    return thisArg === undefined\n      ? func\n      : bindCallback(func, thisArg, argCount);\n  }\n  if (func == null) {\n    return identity;\n  }\n  if (type == 'object') {\n    return baseMatches(func);\n  }\n  return thisArg === undefined\n    ? property(func)\n    : baseMatchesProperty(func, thisArg);\n}\n\nmodule.exports = baseCallback;\n\n},{\"../utility/identity\":154,\"../utility/property\":156,\"./baseMatches\":84,\"./baseMatchesProperty\":85,\"./bindCallback\":94}],68:[function(require,module,exports){\nvar arrayCopy = require('./arrayCopy'),\n    arrayEach = require('./arrayEach'),\n    baseAssign = require('./baseAssign'),\n    baseForOwn = require('./baseForOwn'),\n    initCloneArray = require('./initCloneArray'),\n    initCloneByTag = require('./initCloneByTag'),\n    initCloneObject = require('./initCloneObject'),\n    isArray = require('../lang/isArray'),\n    isHostObject = require('./isHostObject'),\n    isObject = require('../lang/isObject');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n    arrayTag = '[object Array]',\n    boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    errorTag = '[object Error]',\n    funcTag = '[object Function]',\n    mapTag = '[object Map]',\n    numberTag = '[object Number]',\n    objectTag = '[object Object]',\n    regexpTag = '[object RegExp]',\n    setTag = '[object Set]',\n    stringTag = '[object String]',\n    weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    float32Tag = '[object Float32Array]',\n    float64Tag = '[object Float64Array]',\n    int8Tag = '[object Int8Array]',\n    int16Tag = '[object Int16Array]',\n    int32Tag = '[object Int32Array]',\n    uint8Tag = '[object Uint8Array]',\n    uint8ClampedTag = '[object Uint8ClampedArray]',\n    uint16Tag = '[object Uint16Array]',\n    uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values supported by `_.clone`. */\nvar cloneableTags = {};\ncloneableTags[argsTag] = cloneableTags[arrayTag] =\ncloneableTags[arrayBufferTag] = cloneableTags[boolTag] =\ncloneableTags[dateTag] = cloneableTags[float32Tag] =\ncloneableTags[float64Tag] = cloneableTags[int8Tag] =\ncloneableTags[int16Tag] = cloneableTags[int32Tag] =\ncloneableTags[numberTag] = cloneableTags[objectTag] =\ncloneableTags[regexpTag] = cloneableTags[stringTag] =\ncloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =\ncloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;\ncloneableTags[errorTag] = cloneableTags[funcTag] =\ncloneableTags[mapTag] = cloneableTags[setTag] =\ncloneableTags[weakMapTag] = false;\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/**\n * The base implementation of `_.clone` without support for argument juggling\n * and `this` binding `customizer` functions.\n *\n * @private\n * @param {*} value The value to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @param {Function} [customizer] The function to customize cloning values.\n * @param {string} [key] The key of `value`.\n * @param {Object} [object] The object `value` belongs to.\n * @param {Array} [stackA=[]] Tracks traversed source objects.\n * @param {Array} [stackB=[]] Associates clones with source counterparts.\n * @returns {*} Returns the cloned value.\n */\nfunction baseClone(value, isDeep, customizer, key, object, stackA, stackB) {\n  var result;\n  if (customizer) {\n    result = object ? customizer(value, key, object) : customizer(value);\n  }\n  if (result !== undefined) {\n    return result;\n  }\n  if (!isObject(value)) {\n    return value;\n  }\n  var isArr = isArray(value);\n  if (isArr) {\n    result = initCloneArray(value);\n    if (!isDeep) {\n      return arrayCopy(value, result);\n    }\n  } else {\n    var tag = objToString.call(value),\n        isFunc = tag == funcTag;\n\n    if (tag == objectTag || tag == argsTag || (isFunc && !object)) {\n      if (isHostObject(value)) {\n        return object ? value : {};\n      }\n      result = initCloneObject(isFunc ? {} : value);\n      if (!isDeep) {\n        return baseAssign(result, value);\n      }\n    } else {\n      return cloneableTags[tag]\n        ? initCloneByTag(value, tag, isDeep)\n        : (object ? value : {});\n    }\n  }\n  // Check for circular references and return its corresponding clone.\n  stackA || (stackA = []);\n  stackB || (stackB = []);\n\n  var length = stackA.length;\n  while (length--) {\n    if (stackA[length] == value) {\n      return stackB[length];\n    }\n  }\n  // Add the source value to the stack of traversed objects and associate it with its clone.\n  stackA.push(value);\n  stackB.push(result);\n\n  // Recursively populate clone (susceptible to call stack limits).\n  (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {\n    result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);\n  });\n  return result;\n}\n\nmodule.exports = baseClone;\n\n},{\"../lang/isArray\":140,\"../lang/isObject\":144,\"./arrayCopy\":62,\"./arrayEach\":63,\"./baseAssign\":66,\"./baseForOwn\":76,\"./initCloneArray\":116,\"./initCloneByTag\":117,\"./initCloneObject\":118,\"./isHostObject\":120}],69:[function(require,module,exports){\n/**\n * Copies properties of `source` to `object`.\n *\n * @private\n * @param {Object} source The object to copy properties from.\n * @param {Array} props The property names to copy.\n * @param {Object} [object={}] The object to copy properties to.\n * @returns {Object} Returns `object`.\n */\nfunction baseCopy(source, props, object) {\n  object || (object = {});\n\n  var index = -1,\n      length = props.length;\n\n  while (++index < length) {\n    var key = props[index];\n    object[key] = source[key];\n  }\n  return object;\n}\n\nmodule.exports = baseCopy;\n\n},{}],70:[function(require,module,exports){\nvar isObject = require('../lang/isObject');\n\n/**\n * The base implementation of `_.create` without support for assigning\n * properties to the created object.\n *\n * @private\n * @param {Object} prototype The object to inherit from.\n * @returns {Object} Returns the new object.\n */\nvar baseCreate = (function() {\n  function object() {}\n  return function(prototype) {\n    if (isObject(prototype)) {\n      object.prototype = prototype;\n      var result = new object;\n      object.prototype = undefined;\n    }\n    return result || {};\n  };\n}());\n\nmodule.exports = baseCreate;\n\n},{\"../lang/isObject\":144}],71:[function(require,module,exports){\nvar baseForOwn = require('./baseForOwn'),\n    createBaseEach = require('./createBaseEach');\n\n/**\n * The base implementation of `_.forEach` without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Array|Object|string} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array|Object|string} Returns `collection`.\n */\nvar baseEach = createBaseEach(baseForOwn);\n\nmodule.exports = baseEach;\n\n},{\"./baseForOwn\":76,\"./createBaseEach\":98}],72:[function(require,module,exports){\n/**\n * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`,\n * without support for callback shorthands and `this` binding, which iterates\n * over `collection` using the provided `eachFunc`.\n *\n * @private\n * @param {Array|Object|string} collection The collection to search.\n * @param {Function} predicate The function invoked per iteration.\n * @param {Function} eachFunc The function to iterate over `collection`.\n * @param {boolean} [retKey] Specify returning the key of the found element\n *  instead of the element itself.\n * @returns {*} Returns the found element or its key, else `undefined`.\n */\nfunction baseFind(collection, predicate, eachFunc, retKey) {\n  var result;\n  eachFunc(collection, function(value, key, collection) {\n    if (predicate(value, key, collection)) {\n      result = retKey ? key : value;\n      return false;\n    }\n  });\n  return result;\n}\n\nmodule.exports = baseFind;\n\n},{}],73:[function(require,module,exports){\n/**\n * The base implementation of `_.findIndex` and `_.findLastIndex` without\n * support for callback shorthands and `this` binding.\n *\n * @private\n * @param {Array} array The array to search.\n * @param {Function} predicate The function invoked per iteration.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseFindIndex(array, predicate, fromRight) {\n  var length = array.length,\n      index = fromRight ? length : -1;\n\n  while ((fromRight ? index-- : ++index < length)) {\n    if (predicate(array[index], index, array)) {\n      return index;\n    }\n  }\n  return -1;\n}\n\nmodule.exports = baseFindIndex;\n\n},{}],74:[function(require,module,exports){\nvar createBaseFor = require('./createBaseFor');\n\n/**\n * The base implementation of `baseForIn` and `baseForOwn` which iterates\n * over `object` properties returned by `keysFunc` invoking `iteratee` for\n * each property. Iteratee functions may exit iteration early by explicitly\n * returning `false`.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {Function} keysFunc The function to get the keys of `object`.\n * @returns {Object} Returns `object`.\n */\nvar baseFor = createBaseFor();\n\nmodule.exports = baseFor;\n\n},{\"./createBaseFor\":99}],75:[function(require,module,exports){\nvar baseFor = require('./baseFor'),\n    keysIn = require('../object/keysIn');\n\n/**\n * The base implementation of `_.forIn` without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Object} Returns `object`.\n */\nfunction baseForIn(object, iteratee) {\n  return baseFor(object, iteratee, keysIn);\n}\n\nmodule.exports = baseForIn;\n\n},{\"../object/keysIn\":150,\"./baseFor\":74}],76:[function(require,module,exports){\nvar baseFor = require('./baseFor'),\n    keys = require('../object/keys');\n\n/**\n * The base implementation of `_.forOwn` without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Object} object The object to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Object} Returns `object`.\n */\nfunction baseForOwn(object, iteratee) {\n  return baseFor(object, iteratee, keys);\n}\n\nmodule.exports = baseForOwn;\n\n},{\"../object/keys\":149,\"./baseFor\":74}],77:[function(require,module,exports){\nvar toObject = require('./toObject');\n\n/**\n * The base implementation of `get` without support for string paths\n * and default values.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} path The path of the property to get.\n * @param {string} [pathKey] The key representation of path.\n * @returns {*} Returns the resolved value.\n */\nfunction baseGet(object, path, pathKey) {\n  if (object == null) {\n    return;\n  }\n  object = toObject(object);\n  if (pathKey !== undefined && pathKey in object) {\n    path = [pathKey];\n  }\n  var index = 0,\n      length = path.length;\n\n  while (object != null && index < length) {\n    object = toObject(object)[path[index++]];\n  }\n  return (index && index == length) ? object : undefined;\n}\n\nmodule.exports = baseGet;\n\n},{\"./toObject\":135}],78:[function(require,module,exports){\nvar indexOfNaN = require('./indexOfNaN');\n\n/**\n * The base implementation of `_.indexOf` without support for binary searches.\n *\n * @private\n * @param {Array} array The array to search.\n * @param {*} value The value to search for.\n * @param {number} fromIndex The index to search from.\n * @returns {number} Returns the index of the matched value, else `-1`.\n */\nfunction baseIndexOf(array, value, fromIndex) {\n  if (value !== value) {\n    return indexOfNaN(array, fromIndex);\n  }\n  var index = fromIndex - 1,\n      length = array.length;\n\n  while (++index < length) {\n    if (array[index] === value) {\n      return index;\n    }\n  }\n  return -1;\n}\n\nmodule.exports = baseIndexOf;\n\n},{\"./indexOfNaN\":115}],79:[function(require,module,exports){\nvar baseIsEqualDeep = require('./baseIsEqualDeep'),\n    isObject = require('../lang/isObject'),\n    isObjectLike = require('./isObjectLike');\n\n/**\n * The base implementation of `_.isEqual` without support for `this` binding\n * `customizer` functions.\n *\n * @private\n * @param {*} value The value to compare.\n * @param {*} other The other value to compare.\n * @param {Function} [customizer] The function to customize comparing values.\n * @param {boolean} [isLoose] Specify performing partial comparisons.\n * @param {Array} [stackA] Tracks traversed `value` objects.\n * @param {Array} [stackB] Tracks traversed `other` objects.\n * @returns {boolean} Returns `true` if the values are equivalent, else `false`.\n */\nfunction baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {\n  if (value === other) {\n    return true;\n  }\n  if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {\n    return value !== value && other !== other;\n  }\n  return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);\n}\n\nmodule.exports = baseIsEqual;\n\n},{\"../lang/isObject\":144,\"./baseIsEqualDeep\":80,\"./isObjectLike\":126}],80:[function(require,module,exports){\nvar equalArrays = require('./equalArrays'),\n    equalByTag = require('./equalByTag'),\n    equalObjects = require('./equalObjects'),\n    isArray = require('../lang/isArray'),\n    isHostObject = require('./isHostObject'),\n    isTypedArray = require('../lang/isTypedArray');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n    arrayTag = '[object Array]',\n    objectTag = '[object Object]';\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/**\n * A specialized version of `baseIsEqual` for arrays and objects which performs\n * deep comparisons and tracks traversed objects enabling objects with circular\n * references to be compared.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Function} [customizer] The function to customize comparing objects.\n * @param {boolean} [isLoose] Specify performing partial comparisons.\n * @param {Array} [stackA=[]] Tracks traversed `value` objects.\n * @param {Array} [stackB=[]] Tracks traversed `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {\n  var objIsArr = isArray(object),\n      othIsArr = isArray(other),\n      objTag = arrayTag,\n      othTag = arrayTag;\n\n  if (!objIsArr) {\n    objTag = objToString.call(object);\n    if (objTag == argsTag) {\n      objTag = objectTag;\n    } else if (objTag != objectTag) {\n      objIsArr = isTypedArray(object);\n    }\n  }\n  if (!othIsArr) {\n    othTag = objToString.call(other);\n    if (othTag == argsTag) {\n      othTag = objectTag;\n    } else if (othTag != objectTag) {\n      othIsArr = isTypedArray(other);\n    }\n  }\n  var objIsObj = objTag == objectTag && !isHostObject(object),\n      othIsObj = othTag == objectTag && !isHostObject(other),\n      isSameTag = objTag == othTag;\n\n  if (isSameTag && !(objIsArr || objIsObj)) {\n    return equalByTag(object, other, objTag);\n  }\n  if (!isLoose) {\n    var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),\n        othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');\n\n    if (objIsWrapped || othIsWrapped) {\n      return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);\n    }\n  }\n  if (!isSameTag) {\n    return false;\n  }\n  // Assume cyclic values are equal.\n  // For more information on detecting circular references see https://es5.github.io/#JO.\n  stackA || (stackA = []);\n  stackB || (stackB = []);\n\n  var length = stackA.length;\n  while (length--) {\n    if (stackA[length] == object) {\n      return stackB[length] == other;\n    }\n  }\n  // Add `object` and `other` to the stack of traversed objects.\n  stackA.push(object);\n  stackB.push(other);\n\n  var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);\n\n  stackA.pop();\n  stackB.pop();\n\n  return result;\n}\n\nmodule.exports = baseIsEqualDeep;\n\n},{\"../lang/isArray\":140,\"../lang/isTypedArray\":147,\"./equalArrays\":107,\"./equalByTag\":108,\"./equalObjects\":109,\"./isHostObject\":120}],81:[function(require,module,exports){\nvar baseIsEqual = require('./baseIsEqual'),\n    toObject = require('./toObject');\n\n/**\n * The base implementation of `_.isMatch` without support for callback\n * shorthands and `this` binding.\n *\n * @private\n * @param {Object} object The object to inspect.\n * @param {Array} matchData The propery names, values, and compare flags to match.\n * @param {Function} [customizer] The function to customize comparing objects.\n * @returns {boolean} Returns `true` if `object` is a match, else `false`.\n */\nfunction baseIsMatch(object, matchData, customizer) {\n  var index = matchData.length,\n      length = index,\n      noCustomizer = !customizer;\n\n  if (object == null) {\n    return !length;\n  }\n  object = toObject(object);\n  while (index--) {\n    var data = matchData[index];\n    if ((noCustomizer && data[2])\n          ? data[1] !== object[data[0]]\n          : !(data[0] in object)\n        ) {\n      return false;\n    }\n  }\n  while (++index < length) {\n    data = matchData[index];\n    var key = data[0],\n        objValue = object[key],\n        srcValue = data[1];\n\n    if (noCustomizer && data[2]) {\n      if (objValue === undefined && !(key in object)) {\n        return false;\n      }\n    } else {\n      var result = customizer ? customizer(objValue, srcValue, key) : undefined;\n      if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) {\n        return false;\n      }\n    }\n  }\n  return true;\n}\n\nmodule.exports = baseIsMatch;\n\n},{\"./baseIsEqual\":79,\"./toObject\":135}],82:[function(require,module,exports){\n/**\n * The function whose prototype all chaining wrappers inherit from.\n *\n * @private\n */\nfunction baseLodash() {\n  // No operation performed.\n}\n\nmodule.exports = baseLodash;\n\n},{}],83:[function(require,module,exports){\nvar baseEach = require('./baseEach'),\n    isArrayLike = require('./isArrayLike');\n\n/**\n * The base implementation of `_.map` without support for callback shorthands\n * and `this` binding.\n *\n * @private\n * @param {Array|Object|string} collection The collection to iterate over.\n * @param {Function} iteratee The function invoked per iteration.\n * @returns {Array} Returns the new mapped array.\n */\nfunction baseMap(collection, iteratee) {\n  var index = -1,\n      result = isArrayLike(collection) ? Array(collection.length) : [];\n\n  baseEach(collection, function(value, key, collection) {\n    result[++index] = iteratee(value, key, collection);\n  });\n  return result;\n}\n\nmodule.exports = baseMap;\n\n},{\"./baseEach\":71,\"./isArrayLike\":119}],84:[function(require,module,exports){\nvar baseIsMatch = require('./baseIsMatch'),\n    getMatchData = require('./getMatchData'),\n    toObject = require('./toObject');\n\n/**\n * The base implementation of `_.matches` which does not clone `source`.\n *\n * @private\n * @param {Object} source The object of property values to match.\n * @returns {Function} Returns the new function.\n */\nfunction baseMatches(source) {\n  var matchData = getMatchData(source);\n  if (matchData.length == 1 && matchData[0][2]) {\n    var key = matchData[0][0],\n        value = matchData[0][1];\n\n    return function(object) {\n      if (object == null) {\n        return false;\n      }\n      object = toObject(object);\n      return object[key] === value && (value !== undefined || (key in object));\n    };\n  }\n  return function(object) {\n    return baseIsMatch(object, matchData);\n  };\n}\n\nmodule.exports = baseMatches;\n\n},{\"./baseIsMatch\":81,\"./getMatchData\":113,\"./toObject\":135}],85:[function(require,module,exports){\nvar baseGet = require('./baseGet'),\n    baseIsEqual = require('./baseIsEqual'),\n    baseSlice = require('./baseSlice'),\n    isArray = require('../lang/isArray'),\n    isKey = require('./isKey'),\n    isStrictComparable = require('./isStrictComparable'),\n    last = require('../array/last'),\n    toObject = require('./toObject'),\n    toPath = require('./toPath');\n\n/**\n * The base implementation of `_.matchesProperty` which does not clone `srcValue`.\n *\n * @private\n * @param {string} path The path of the property to get.\n * @param {*} srcValue The value to compare.\n * @returns {Function} Returns the new function.\n */\nfunction baseMatchesProperty(path, srcValue) {\n  var isArr = isArray(path),\n      isCommon = isKey(path) && isStrictComparable(srcValue),\n      pathKey = (path + '');\n\n  path = toPath(path);\n  return function(object) {\n    if (object == null) {\n      return false;\n    }\n    var key = pathKey;\n    object = toObject(object);\n    if ((isArr || !isCommon) && !(key in object)) {\n      object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));\n      if (object == null) {\n        return false;\n      }\n      key = last(path);\n      object = toObject(object);\n    }\n    return object[key] === srcValue\n      ? (srcValue !== undefined || (key in object))\n      : baseIsEqual(srcValue, object[key], undefined, true);\n  };\n}\n\nmodule.exports = baseMatchesProperty;\n\n},{\"../array/last\":50,\"../lang/isArray\":140,\"./baseGet\":77,\"./baseIsEqual\":79,\"./baseSlice\":89,\"./isKey\":123,\"./isStrictComparable\":127,\"./toObject\":135,\"./toPath\":136}],86:[function(require,module,exports){\nvar toObject = require('./toObject');\n\n/**\n * The base implementation of `_.property` without support for deep paths.\n *\n * @private\n * @param {string} key The key of the property to get.\n * @returns {Function} Returns the new function.\n */\nfunction baseProperty(key) {\n  return function(object) {\n    return object == null ? undefined : toObject(object)[key];\n  };\n}\n\nmodule.exports = baseProperty;\n\n},{\"./toObject\":135}],87:[function(require,module,exports){\nvar baseGet = require('./baseGet'),\n    toPath = require('./toPath');\n\n/**\n * A specialized version of `baseProperty` which supports deep paths.\n *\n * @private\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new function.\n */\nfunction basePropertyDeep(path) {\n  var pathKey = (path + '');\n  path = toPath(path);\n  return function(object) {\n    return baseGet(object, path, pathKey);\n  };\n}\n\nmodule.exports = basePropertyDeep;\n\n},{\"./baseGet\":77,\"./toPath\":136}],88:[function(require,module,exports){\nvar identity = require('../utility/identity'),\n    metaMap = require('./metaMap');\n\n/**\n * The base implementation of `setData` without support for hot loop detection.\n *\n * @private\n * @param {Function} func The function to associate metadata with.\n * @param {*} data The metadata.\n * @returns {Function} Returns `func`.\n */\nvar baseSetData = !metaMap ? identity : function(func, data) {\n  metaMap.set(func, data);\n  return func;\n};\n\nmodule.exports = baseSetData;\n\n},{\"../utility/identity\":154,\"./metaMap\":129}],89:[function(require,module,exports){\n/**\n * The base implementation of `_.slice` without an iteratee call guard.\n *\n * @private\n * @param {Array} array The array to slice.\n * @param {number} [start=0] The start position.\n * @param {number} [end=array.length] The end position.\n * @returns {Array} Returns the slice of `array`.\n */\nfunction baseSlice(array, start, end) {\n  var index = -1,\n      length = array.length;\n\n  start = start == null ? 0 : (+start || 0);\n  if (start < 0) {\n    start = -start > length ? 0 : (length + start);\n  }\n  end = (end === undefined || end > length) ? length : (+end || 0);\n  if (end < 0) {\n    end += length;\n  }\n  length = start > end ? 0 : ((end - start) >>> 0);\n  start >>>= 0;\n\n  var result = Array(length);\n  while (++index < length) {\n    result[index] = array[index + start];\n  }\n  return result;\n}\n\nmodule.exports = baseSlice;\n\n},{}],90:[function(require,module,exports){\n/**\n * Converts `value` to a string if it's not one. An empty string is returned\n * for `null` or `undefined` values.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {string} Returns the string.\n */\nfunction baseToString(value) {\n  return value == null ? '' : (value + '');\n}\n\nmodule.exports = baseToString;\n\n},{}],91:[function(require,module,exports){\n/**\n * The base implementation of `_.values` and `_.valuesIn` which creates an\n * array of `object` property values corresponding to the property names\n * of `props`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {Array} props The property names to get values for.\n * @returns {Object} Returns the array of property values.\n */\nfunction baseValues(object, props) {\n  var index = -1,\n      length = props.length,\n      result = Array(length);\n\n  while (++index < length) {\n    result[index] = object[props[index]];\n  }\n  return result;\n}\n\nmodule.exports = baseValues;\n\n},{}],92:[function(require,module,exports){\nvar binaryIndexBy = require('./binaryIndexBy'),\n    identity = require('../utility/identity');\n\n/** Used as references for the maximum length and index of an array. */\nvar MAX_ARRAY_LENGTH = 4294967295,\n    HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;\n\n/**\n * Performs a binary search of `array` to determine the index at which `value`\n * should be inserted into `array` in order to maintain its sort order.\n *\n * @private\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @param {boolean} [retHighest] Specify returning the highest qualified index.\n * @returns {number} Returns the index at which `value` should be inserted\n *  into `array`.\n */\nfunction binaryIndex(array, value, retHighest) {\n  var low = 0,\n      high = array ? array.length : low;\n\n  if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {\n    while (low < high) {\n      var mid = (low + high) >>> 1,\n          computed = array[mid];\n\n      if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) {\n        low = mid + 1;\n      } else {\n        high = mid;\n      }\n    }\n    return high;\n  }\n  return binaryIndexBy(array, value, identity, retHighest);\n}\n\nmodule.exports = binaryIndex;\n\n},{\"../utility/identity\":154,\"./binaryIndexBy\":93}],93:[function(require,module,exports){\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeFloor = Math.floor,\n    nativeMin = Math.min;\n\n/** Used as references for the maximum length and index of an array. */\nvar MAX_ARRAY_LENGTH = 4294967295,\n    MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1;\n\n/**\n * This function is like `binaryIndex` except that it invokes `iteratee` for\n * `value` and each element of `array` to compute their sort ranking. The\n * iteratee is invoked with one argument; (value).\n *\n * @private\n * @param {Array} array The sorted array to inspect.\n * @param {*} value The value to evaluate.\n * @param {Function} iteratee The function invoked per iteration.\n * @param {boolean} [retHighest] Specify returning the highest qualified index.\n * @returns {number} Returns the index at which `value` should be inserted\n *  into `array`.\n */\nfunction binaryIndexBy(array, value, iteratee, retHighest) {\n  value = iteratee(value);\n\n  var low = 0,\n      high = array ? array.length : 0,\n      valIsNaN = value !== value,\n      valIsNull = value === null,\n      valIsUndef = value === undefined;\n\n  while (low < high) {\n    var mid = nativeFloor((low + high) / 2),\n        computed = iteratee(array[mid]),\n        isDef = computed !== undefined,\n        isReflexive = computed === computed;\n\n    if (valIsNaN) {\n      var setLow = isReflexive || retHighest;\n    } else if (valIsNull) {\n      setLow = isReflexive && isDef && (retHighest || computed != null);\n    } else if (valIsUndef) {\n      setLow = isReflexive && (retHighest || isDef);\n    } else if (computed == null) {\n      setLow = false;\n    } else {\n      setLow = retHighest ? (computed <= value) : (computed < value);\n    }\n    if (setLow) {\n      low = mid + 1;\n    } else {\n      high = mid;\n    }\n  }\n  return nativeMin(high, MAX_ARRAY_INDEX);\n}\n\nmodule.exports = binaryIndexBy;\n\n},{}],94:[function(require,module,exports){\nvar identity = require('../utility/identity');\n\n/**\n * A specialized version of `baseCallback` which only supports `this` binding\n * and specifying the number of arguments to provide to `func`.\n *\n * @private\n * @param {Function} func The function to bind.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {number} [argCount] The number of arguments to provide to `func`.\n * @returns {Function} Returns the callback.\n */\nfunction bindCallback(func, thisArg, argCount) {\n  if (typeof func != 'function') {\n    return identity;\n  }\n  if (thisArg === undefined) {\n    return func;\n  }\n  switch (argCount) {\n    case 1: return function(value) {\n      return func.call(thisArg, value);\n    };\n    case 3: return function(value, index, collection) {\n      return func.call(thisArg, value, index, collection);\n    };\n    case 4: return function(accumulator, value, index, collection) {\n      return func.call(thisArg, accumulator, value, index, collection);\n    };\n    case 5: return function(value, other, key, object, source) {\n      return func.call(thisArg, value, other, key, object, source);\n    };\n  }\n  return function() {\n    return func.apply(thisArg, arguments);\n  };\n}\n\nmodule.exports = bindCallback;\n\n},{\"../utility/identity\":154}],95:[function(require,module,exports){\n(function (global){\n/** Native method references. */\nvar ArrayBuffer = global.ArrayBuffer,\n    Uint8Array = global.Uint8Array;\n\n/**\n * Creates a clone of the given array buffer.\n *\n * @private\n * @param {ArrayBuffer} buffer The array buffer to clone.\n * @returns {ArrayBuffer} Returns the cloned array buffer.\n */\nfunction bufferClone(buffer) {\n  var result = new ArrayBuffer(buffer.byteLength),\n      view = new Uint8Array(result);\n\n  view.set(new Uint8Array(buffer));\n  return result;\n}\n\nmodule.exports = bufferClone;\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{}],96:[function(require,module,exports){\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * Creates an array that is the composition of partially applied arguments,\n * placeholders, and provided arguments into a single array of arguments.\n *\n * @private\n * @param {Array|Object} args The provided arguments.\n * @param {Array} partials The arguments to prepend to those provided.\n * @param {Array} holders The `partials` placeholder indexes.\n * @returns {Array} Returns the new array of composed arguments.\n */\nfunction composeArgs(args, partials, holders) {\n  var holdersLength = holders.length,\n      argsIndex = -1,\n      argsLength = nativeMax(args.length - holdersLength, 0),\n      leftIndex = -1,\n      leftLength = partials.length,\n      result = Array(leftLength + argsLength);\n\n  while (++leftIndex < leftLength) {\n    result[leftIndex] = partials[leftIndex];\n  }\n  while (++argsIndex < holdersLength) {\n    result[holders[argsIndex]] = args[argsIndex];\n  }\n  while (argsLength--) {\n    result[leftIndex++] = args[argsIndex++];\n  }\n  return result;\n}\n\nmodule.exports = composeArgs;\n\n},{}],97:[function(require,module,exports){\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * This function is like `composeArgs` except that the arguments composition\n * is tailored for `_.partialRight`.\n *\n * @private\n * @param {Array|Object} args The provided arguments.\n * @param {Array} partials The arguments to append to those provided.\n * @param {Array} holders The `partials` placeholder indexes.\n * @returns {Array} Returns the new array of composed arguments.\n */\nfunction composeArgsRight(args, partials, holders) {\n  var holdersIndex = -1,\n      holdersLength = holders.length,\n      argsIndex = -1,\n      argsLength = nativeMax(args.length - holdersLength, 0),\n      rightIndex = -1,\n      rightLength = partials.length,\n      result = Array(argsLength + rightLength);\n\n  while (++argsIndex < argsLength) {\n    result[argsIndex] = args[argsIndex];\n  }\n  var offset = argsIndex;\n  while (++rightIndex < rightLength) {\n    result[offset + rightIndex] = partials[rightIndex];\n  }\n  while (++holdersIndex < holdersLength) {\n    result[offset + holders[holdersIndex]] = args[argsIndex++];\n  }\n  return result;\n}\n\nmodule.exports = composeArgsRight;\n\n},{}],98:[function(require,module,exports){\nvar getLength = require('./getLength'),\n    isLength = require('./isLength'),\n    toObject = require('./toObject');\n\n/**\n * Creates a `baseEach` or `baseEachRight` function.\n *\n * @private\n * @param {Function} eachFunc The function to iterate over a collection.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseEach(eachFunc, fromRight) {\n  return function(collection, iteratee) {\n    var length = collection ? getLength(collection) : 0;\n    if (!isLength(length)) {\n      return eachFunc(collection, iteratee);\n    }\n    var index = fromRight ? length : -1,\n        iterable = toObject(collection);\n\n    while ((fromRight ? index-- : ++index < length)) {\n      if (iteratee(iterable[index], index, iterable) === false) {\n        break;\n      }\n    }\n    return collection;\n  };\n}\n\nmodule.exports = createBaseEach;\n\n},{\"./getLength\":112,\"./isLength\":125,\"./toObject\":135}],99:[function(require,module,exports){\nvar toObject = require('./toObject');\n\n/**\n * Creates a base function for `_.forIn` or `_.forInRight`.\n *\n * @private\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new base function.\n */\nfunction createBaseFor(fromRight) {\n  return function(object, iteratee, keysFunc) {\n    var iterable = toObject(object),\n        props = keysFunc(object),\n        length = props.length,\n        index = fromRight ? length : -1;\n\n    while ((fromRight ? index-- : ++index < length)) {\n      var key = props[index];\n      if (iteratee(iterable[key], key, iterable) === false) {\n        break;\n      }\n    }\n    return object;\n  };\n}\n\nmodule.exports = createBaseFor;\n\n},{\"./toObject\":135}],100:[function(require,module,exports){\n(function (global){\nvar createCtorWrapper = require('./createCtorWrapper');\n\n/**\n * Creates a function that wraps `func` and invokes it with the `this`\n * binding of `thisArg`.\n *\n * @private\n * @param {Function} func The function to bind.\n * @param {*} [thisArg] The `this` binding of `func`.\n * @returns {Function} Returns the new bound function.\n */\nfunction createBindWrapper(func, thisArg) {\n  var Ctor = createCtorWrapper(func);\n\n  function wrapper() {\n    var fn = (this && this !== global && this instanceof wrapper) ? Ctor : func;\n    return fn.apply(thisArg, arguments);\n  }\n  return wrapper;\n}\n\nmodule.exports = createBindWrapper;\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{\"./createCtorWrapper\":101}],101:[function(require,module,exports){\nvar baseCreate = require('./baseCreate'),\n    isObject = require('../lang/isObject');\n\n/**\n * Creates a function that produces an instance of `Ctor` regardless of\n * whether it was invoked as part of a `new` expression or by `call` or `apply`.\n *\n * @private\n * @param {Function} Ctor The constructor to wrap.\n * @returns {Function} Returns the new wrapped function.\n */\nfunction createCtorWrapper(Ctor) {\n  return function() {\n    // Use a `switch` statement to work with class constructors.\n    // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist\n    // for more details.\n    var args = arguments;\n    switch (args.length) {\n      case 0: return new Ctor;\n      case 1: return new Ctor(args[0]);\n      case 2: return new Ctor(args[0], args[1]);\n      case 3: return new Ctor(args[0], args[1], args[2]);\n      case 4: return new Ctor(args[0], args[1], args[2], args[3]);\n      case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);\n      case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);\n      case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);\n    }\n    var thisBinding = baseCreate(Ctor.prototype),\n        result = Ctor.apply(thisBinding, args);\n\n    // Mimic the constructor's `return` behavior.\n    // See https://es5.github.io/#x13.2.2 for more details.\n    return isObject(result) ? result : thisBinding;\n  };\n}\n\nmodule.exports = createCtorWrapper;\n\n},{\"../lang/isObject\":144,\"./baseCreate\":70}],102:[function(require,module,exports){\nvar baseCallback = require('./baseCallback'),\n    baseFind = require('./baseFind'),\n    baseFindIndex = require('./baseFindIndex'),\n    isArray = require('../lang/isArray');\n\n/**\n * Creates a `_.find` or `_.findLast` function.\n *\n * @private\n * @param {Function} eachFunc The function to iterate over a collection.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {Function} Returns the new find function.\n */\nfunction createFind(eachFunc, fromRight) {\n  return function(collection, predicate, thisArg) {\n    predicate = baseCallback(predicate, thisArg, 3);\n    if (isArray(collection)) {\n      var index = baseFindIndex(collection, predicate, fromRight);\n      return index > -1 ? collection[index] : undefined;\n    }\n    return baseFind(collection, predicate, eachFunc);\n  };\n}\n\nmodule.exports = createFind;\n\n},{\"../lang/isArray\":140,\"./baseCallback\":67,\"./baseFind\":72,\"./baseFindIndex\":73}],103:[function(require,module,exports){\nvar bindCallback = require('./bindCallback'),\n    isArray = require('../lang/isArray');\n\n/**\n * Creates a function for `_.forEach` or `_.forEachRight`.\n *\n * @private\n * @param {Function} arrayFunc The function to iterate over an array.\n * @param {Function} eachFunc The function to iterate over a collection.\n * @returns {Function} Returns the new each function.\n */\nfunction createForEach(arrayFunc, eachFunc) {\n  return function(collection, iteratee, thisArg) {\n    return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))\n      ? arrayFunc(collection, iteratee)\n      : eachFunc(collection, bindCallback(iteratee, thisArg, 3));\n  };\n}\n\nmodule.exports = createForEach;\n\n},{\"../lang/isArray\":140,\"./bindCallback\":94}],104:[function(require,module,exports){\n(function (global){\nvar arrayCopy = require('./arrayCopy'),\n    composeArgs = require('./composeArgs'),\n    composeArgsRight = require('./composeArgsRight'),\n    createCtorWrapper = require('./createCtorWrapper'),\n    isLaziable = require('./isLaziable'),\n    reorder = require('./reorder'),\n    replaceHolders = require('./replaceHolders'),\n    setData = require('./setData');\n\n/** Used to compose bitmasks for wrapper metadata. */\nvar BIND_FLAG = 1,\n    BIND_KEY_FLAG = 2,\n    CURRY_BOUND_FLAG = 4,\n    CURRY_FLAG = 8,\n    CURRY_RIGHT_FLAG = 16,\n    PARTIAL_FLAG = 32,\n    PARTIAL_RIGHT_FLAG = 64,\n    ARY_FLAG = 128;\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * Creates a function that wraps `func` and invokes it with optional `this`\n * binding of, partial application, and currying.\n *\n * @private\n * @param {Function|string} func The function or method name to reference.\n * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.\n * @param {*} [thisArg] The `this` binding of `func`.\n * @param {Array} [partials] The arguments to prepend to those provided to the new function.\n * @param {Array} [holders] The `partials` placeholder indexes.\n * @param {Array} [partialsRight] The arguments to append to those provided to the new function.\n * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.\n * @param {Array} [argPos] The argument positions of the new function.\n * @param {number} [ary] The arity cap of `func`.\n * @param {number} [arity] The arity of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\nfunction createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {\n  var isAry = bitmask & ARY_FLAG,\n      isBind = bitmask & BIND_FLAG,\n      isBindKey = bitmask & BIND_KEY_FLAG,\n      isCurry = bitmask & CURRY_FLAG,\n      isCurryBound = bitmask & CURRY_BOUND_FLAG,\n      isCurryRight = bitmask & CURRY_RIGHT_FLAG,\n      Ctor = isBindKey ? undefined : createCtorWrapper(func);\n\n  function wrapper() {\n    // Avoid `arguments` object use disqualifying optimizations by\n    // converting it to an array before providing it to other functions.\n    var length = arguments.length,\n        index = length,\n        args = Array(length);\n\n    while (index--) {\n      args[index] = arguments[index];\n    }\n    if (partials) {\n      args = composeArgs(args, partials, holders);\n    }\n    if (partialsRight) {\n      args = composeArgsRight(args, partialsRight, holdersRight);\n    }\n    if (isCurry || isCurryRight) {\n      var placeholder = wrapper.placeholder,\n          argsHolders = replaceHolders(args, placeholder);\n\n      length -= argsHolders.length;\n      if (length < arity) {\n        var newArgPos = argPos ? arrayCopy(argPos) : undefined,\n            newArity = nativeMax(arity - length, 0),\n            newsHolders = isCurry ? argsHolders : undefined,\n            newHoldersRight = isCurry ? undefined : argsHolders,\n            newPartials = isCurry ? args : undefined,\n            newPartialsRight = isCurry ? undefined : args;\n\n        bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);\n        bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);\n\n        if (!isCurryBound) {\n          bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);\n        }\n        var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity],\n            result = createHybridWrapper.apply(undefined, newData);\n\n        if (isLaziable(func)) {\n          setData(result, newData);\n        }\n        result.placeholder = placeholder;\n        return result;\n      }\n    }\n    var thisBinding = isBind ? thisArg : this,\n        fn = isBindKey ? thisBinding[func] : func;\n\n    if (argPos) {\n      args = reorder(args, argPos);\n    }\n    if (isAry && ary < args.length) {\n      args.length = ary;\n    }\n    if (this && this !== global && this instanceof wrapper) {\n      fn = Ctor || createCtorWrapper(func);\n    }\n    return fn.apply(thisBinding, args);\n  }\n  return wrapper;\n}\n\nmodule.exports = createHybridWrapper;\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{\"./arrayCopy\":62,\"./composeArgs\":96,\"./composeArgsRight\":97,\"./createCtorWrapper\":101,\"./isLaziable\":124,\"./reorder\":131,\"./replaceHolders\":132,\"./setData\":133}],105:[function(require,module,exports){\n(function (global){\nvar createCtorWrapper = require('./createCtorWrapper');\n\n/** Used to compose bitmasks for wrapper metadata. */\nvar BIND_FLAG = 1;\n\n/**\n * Creates a function that wraps `func` and invokes it with the optional `this`\n * binding of `thisArg` and the `partials` prepended to those provided to\n * the wrapper.\n *\n * @private\n * @param {Function} func The function to partially apply arguments to.\n * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.\n * @param {*} thisArg The `this` binding of `func`.\n * @param {Array} partials The arguments to prepend to those provided to the new function.\n * @returns {Function} Returns the new bound function.\n */\nfunction createPartialWrapper(func, bitmask, thisArg, partials) {\n  var isBind = bitmask & BIND_FLAG,\n      Ctor = createCtorWrapper(func);\n\n  function wrapper() {\n    // Avoid `arguments` object use disqualifying optimizations by\n    // converting it to an array before providing it `func`.\n    var argsIndex = -1,\n        argsLength = arguments.length,\n        leftIndex = -1,\n        leftLength = partials.length,\n        args = Array(leftLength + argsLength);\n\n    while (++leftIndex < leftLength) {\n      args[leftIndex] = partials[leftIndex];\n    }\n    while (argsLength--) {\n      args[leftIndex++] = arguments[++argsIndex];\n    }\n    var fn = (this && this !== global && this instanceof wrapper) ? Ctor : func;\n    return fn.apply(isBind ? thisArg : this, args);\n  }\n  return wrapper;\n}\n\nmodule.exports = createPartialWrapper;\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{\"./createCtorWrapper\":101}],106:[function(require,module,exports){\nvar baseSetData = require('./baseSetData'),\n    createBindWrapper = require('./createBindWrapper'),\n    createHybridWrapper = require('./createHybridWrapper'),\n    createPartialWrapper = require('./createPartialWrapper'),\n    getData = require('./getData'),\n    mergeData = require('./mergeData'),\n    setData = require('./setData');\n\n/** Used to compose bitmasks for wrapper metadata. */\nvar BIND_FLAG = 1,\n    BIND_KEY_FLAG = 2,\n    PARTIAL_FLAG = 32,\n    PARTIAL_RIGHT_FLAG = 64;\n\n/** Used as the `TypeError` message for \"Functions\" methods. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max;\n\n/**\n * Creates a function that either curries or invokes `func` with optional\n * `this` binding and partially applied arguments.\n *\n * @private\n * @param {Function|string} func The function or method name to reference.\n * @param {number} bitmask The bitmask of flags.\n *  The bitmask may be composed of the following flags:\n *     1 - `_.bind`\n *     2 - `_.bindKey`\n *     4 - `_.curry` or `_.curryRight` of a bound function\n *     8 - `_.curry`\n *    16 - `_.curryRight`\n *    32 - `_.partial`\n *    64 - `_.partialRight`\n *   128 - `_.rearg`\n *   256 - `_.ary`\n * @param {*} [thisArg] The `this` binding of `func`.\n * @param {Array} [partials] The arguments to be partially applied.\n * @param {Array} [holders] The `partials` placeholder indexes.\n * @param {Array} [argPos] The argument positions of the new function.\n * @param {number} [ary] The arity cap of `func`.\n * @param {number} [arity] The arity of `func`.\n * @returns {Function} Returns the new wrapped function.\n */\nfunction createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {\n  var isBindKey = bitmask & BIND_KEY_FLAG;\n  if (!isBindKey && typeof func != 'function') {\n    throw new TypeError(FUNC_ERROR_TEXT);\n  }\n  var length = partials ? partials.length : 0;\n  if (!length) {\n    bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);\n    partials = holders = undefined;\n  }\n  length -= (holders ? holders.length : 0);\n  if (bitmask & PARTIAL_RIGHT_FLAG) {\n    var partialsRight = partials,\n        holdersRight = holders;\n\n    partials = holders = undefined;\n  }\n  var data = isBindKey ? undefined : getData(func),\n      newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];\n\n  if (data) {\n    mergeData(newData, data);\n    bitmask = newData[1];\n    arity = newData[9];\n  }\n  newData[9] = arity == null\n    ? (isBindKey ? 0 : func.length)\n    : (nativeMax(arity - length, 0) || 0);\n\n  if (bitmask == BIND_FLAG) {\n    var result = createBindWrapper(newData[0], newData[2]);\n  } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) {\n    result = createPartialWrapper.apply(undefined, newData);\n  } else {\n    result = createHybridWrapper.apply(undefined, newData);\n  }\n  var setter = data ? baseSetData : setData;\n  return setter(result, newData);\n}\n\nmodule.exports = createWrapper;\n\n},{\"./baseSetData\":88,\"./createBindWrapper\":100,\"./createHybridWrapper\":104,\"./createPartialWrapper\":105,\"./getData\":110,\"./mergeData\":128,\"./setData\":133}],107:[function(require,module,exports){\nvar arraySome = require('./arraySome');\n\n/**\n * A specialized version of `baseIsEqualDeep` for arrays with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Array} array The array to compare.\n * @param {Array} other The other array to compare.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Function} [customizer] The function to customize comparing arrays.\n * @param {boolean} [isLoose] Specify performing partial comparisons.\n * @param {Array} [stackA] Tracks traversed `value` objects.\n * @param {Array} [stackB] Tracks traversed `other` objects.\n * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.\n */\nfunction equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {\n  var index = -1,\n      arrLength = array.length,\n      othLength = other.length;\n\n  if (arrLength != othLength && !(isLoose && othLength > arrLength)) {\n    return false;\n  }\n  // Ignore non-index properties.\n  while (++index < arrLength) {\n    var arrValue = array[index],\n        othValue = other[index],\n        result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined;\n\n    if (result !== undefined) {\n      if (result) {\n        continue;\n      }\n      return false;\n    }\n    // Recursively compare arrays (susceptible to call stack limits).\n    if (isLoose) {\n      if (!arraySome(other, function(othValue) {\n            return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);\n          })) {\n        return false;\n      }\n    } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) {\n      return false;\n    }\n  }\n  return true;\n}\n\nmodule.exports = equalArrays;\n\n},{\"./arraySome\":65}],108:[function(require,module,exports){\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    errorTag = '[object Error]',\n    numberTag = '[object Number]',\n    regexpTag = '[object RegExp]',\n    stringTag = '[object String]';\n\n/**\n * A specialized version of `baseIsEqualDeep` for comparing objects of\n * the same `toStringTag`.\n *\n * **Note:** This function only supports comparing values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {string} tag The `toStringTag` of the objects to compare.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalByTag(object, other, tag) {\n  switch (tag) {\n    case boolTag:\n    case dateTag:\n      // Coerce dates and booleans to numbers, dates to milliseconds and booleans\n      // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.\n      return +object == +other;\n\n    case errorTag:\n      return object.name == other.name && object.message == other.message;\n\n    case numberTag:\n      // Treat `NaN` vs. `NaN` as equal.\n      return (object != +object)\n        ? other != +other\n        : object == +other;\n\n    case regexpTag:\n    case stringTag:\n      // Coerce regexes to strings and treat strings primitives and string\n      // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.\n      return object == (other + '');\n  }\n  return false;\n}\n\nmodule.exports = equalByTag;\n\n},{}],109:[function(require,module,exports){\nvar keys = require('../object/keys');\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A specialized version of `baseIsEqualDeep` for objects with support for\n * partial deep comparisons.\n *\n * @private\n * @param {Object} object The object to compare.\n * @param {Object} other The other object to compare.\n * @param {Function} equalFunc The function to determine equivalents of values.\n * @param {Function} [customizer] The function to customize comparing values.\n * @param {boolean} [isLoose] Specify performing partial comparisons.\n * @param {Array} [stackA] Tracks traversed `value` objects.\n * @param {Array} [stackB] Tracks traversed `other` objects.\n * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.\n */\nfunction equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {\n  var objProps = keys(object),\n      objLength = objProps.length,\n      othProps = keys(other),\n      othLength = othProps.length;\n\n  if (objLength != othLength && !isLoose) {\n    return false;\n  }\n  var index = objLength;\n  while (index--) {\n    var key = objProps[index];\n    if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) {\n      return false;\n    }\n  }\n  var skipCtor = isLoose;\n  while (++index < objLength) {\n    key = objProps[index];\n    var objValue = object[key],\n        othValue = other[key],\n        result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined;\n\n    // Recursively compare objects (susceptible to call stack limits).\n    if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) {\n      return false;\n    }\n    skipCtor || (skipCtor = key == 'constructor');\n  }\n  if (!skipCtor) {\n    var objCtor = object.constructor,\n        othCtor = other.constructor;\n\n    // Non `Object` object instances with different constructors are not equal.\n    if (objCtor != othCtor &&\n        ('constructor' in object && 'constructor' in other) &&\n        !(typeof objCtor == 'function' && objCtor instanceof objCtor &&\n          typeof othCtor == 'function' && othCtor instanceof othCtor)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nmodule.exports = equalObjects;\n\n},{\"../object/keys\":149}],110:[function(require,module,exports){\nvar metaMap = require('./metaMap'),\n    noop = require('../utility/noop');\n\n/**\n * Gets metadata for `func`.\n *\n * @private\n * @param {Function} func The function to query.\n * @returns {*} Returns the metadata for `func`.\n */\nvar getData = !metaMap ? noop : function(func) {\n  return metaMap.get(func);\n};\n\nmodule.exports = getData;\n\n},{\"../utility/noop\":155,\"./metaMap\":129}],111:[function(require,module,exports){\nvar realNames = require('./realNames');\n\n/**\n * Gets the name of `func`.\n *\n * @private\n * @param {Function} func The function to query.\n * @returns {string} Returns the function name.\n */\nfunction getFuncName(func) {\n  var result = (func.name + ''),\n      array = realNames[result],\n      length = array ? array.length : 0;\n\n  while (length--) {\n    var data = array[length],\n        otherFunc = data.func;\n    if (otherFunc == null || otherFunc == func) {\n      return data.name;\n    }\n  }\n  return result;\n}\n\nmodule.exports = getFuncName;\n\n},{\"./realNames\":130}],112:[function(require,module,exports){\nvar baseProperty = require('./baseProperty');\n\n/**\n * Gets the \"length\" property value of `object`.\n *\n * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)\n * that affects Safari on at least iOS 8.1-8.3 ARM64.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {*} Returns the \"length\" value.\n */\nvar getLength = baseProperty('length');\n\nmodule.exports = getLength;\n\n},{\"./baseProperty\":86}],113:[function(require,module,exports){\nvar isStrictComparable = require('./isStrictComparable'),\n    pairs = require('../object/pairs');\n\n/**\n * Gets the propery names, values, and compare flags of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the match data of `object`.\n */\nfunction getMatchData(object) {\n  var result = pairs(object),\n      length = result.length;\n\n  while (length--) {\n    result[length][2] = isStrictComparable(result[length][1]);\n  }\n  return result;\n}\n\nmodule.exports = getMatchData;\n\n},{\"../object/pairs\":151,\"./isStrictComparable\":127}],114:[function(require,module,exports){\nvar isNative = require('../lang/isNative');\n\n/**\n * Gets the native function at `key` of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @param {string} key The key of the method to get.\n * @returns {*} Returns the function if it's native, else `undefined`.\n */\nfunction getNative(object, key) {\n  var value = object == null ? undefined : object[key];\n  return isNative(value) ? value : undefined;\n}\n\nmodule.exports = getNative;\n\n},{\"../lang/isNative\":143}],115:[function(require,module,exports){\n/**\n * Gets the index at which the first occurrence of `NaN` is found in `array`.\n *\n * @private\n * @param {Array} array The array to search.\n * @param {number} fromIndex The index to search from.\n * @param {boolean} [fromRight] Specify iterating from right to left.\n * @returns {number} Returns the index of the matched `NaN`, else `-1`.\n */\nfunction indexOfNaN(array, fromIndex, fromRight) {\n  var length = array.length,\n      index = fromIndex + (fromRight ? 0 : -1);\n\n  while ((fromRight ? index-- : ++index < length)) {\n    var other = array[index];\n    if (other !== other) {\n      return index;\n    }\n  }\n  return -1;\n}\n\nmodule.exports = indexOfNaN;\n\n},{}],116:[function(require,module,exports){\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Initializes an array clone.\n *\n * @private\n * @param {Array} array The array to clone.\n * @returns {Array} Returns the initialized clone.\n */\nfunction initCloneArray(array) {\n  var length = array.length,\n      result = new array.constructor(length);\n\n  // Add array properties assigned by `RegExp#exec`.\n  if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {\n    result.index = array.index;\n    result.input = array.input;\n  }\n  return result;\n}\n\nmodule.exports = initCloneArray;\n\n},{}],117:[function(require,module,exports){\n(function (global){\nvar bufferClone = require('./bufferClone');\n\n/** `Object#toString` result references. */\nvar boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    numberTag = '[object Number]',\n    regexpTag = '[object RegExp]',\n    stringTag = '[object String]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    float32Tag = '[object Float32Array]',\n    float64Tag = '[object Float64Array]',\n    int8Tag = '[object Int8Array]',\n    int16Tag = '[object Int16Array]',\n    int32Tag = '[object Int32Array]',\n    uint8Tag = '[object Uint8Array]',\n    uint8ClampedTag = '[object Uint8ClampedArray]',\n    uint16Tag = '[object Uint16Array]',\n    uint32Tag = '[object Uint32Array]';\n\n/** Used to match `RegExp` flags from their coerced string values. */\nvar reFlags = /\\w*$/;\n\n/** Native method references. */\nvar Uint8Array = global.Uint8Array;\n\n/** Used to lookup a type array constructors by `toStringTag`. */\nvar ctorByTag = {};\nctorByTag[float32Tag] = global.Float32Array;\nctorByTag[float64Tag] = global.Float64Array;\nctorByTag[int8Tag] = global.Int8Array;\nctorByTag[int16Tag] = global.Int16Array;\nctorByTag[int32Tag] = global.Int32Array;\nctorByTag[uint8Tag] = Uint8Array;\nctorByTag[uint8ClampedTag] = global.Uint8ClampedArray;\nctorByTag[uint16Tag] = global.Uint16Array;\nctorByTag[uint32Tag] = global.Uint32Array;\n\n/**\n * Initializes an object clone based on its `toStringTag`.\n *\n * **Note:** This function only supports cloning values with tags of\n * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.\n *\n * @private\n * @param {Object} object The object to clone.\n * @param {string} tag The `toStringTag` of the object to clone.\n * @param {boolean} [isDeep] Specify a deep clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneByTag(object, tag, isDeep) {\n  var Ctor = object.constructor;\n  switch (tag) {\n    case arrayBufferTag:\n      return bufferClone(object);\n\n    case boolTag:\n    case dateTag:\n      return new Ctor(+object);\n\n    case float32Tag: case float64Tag:\n    case int8Tag: case int16Tag: case int32Tag:\n    case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:\n      // Safari 5 mobile incorrectly has `Object` as the constructor of typed arrays.\n      if (Ctor instanceof Ctor) {\n        Ctor = ctorByTag[tag];\n      }\n      var buffer = object.buffer;\n      return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);\n\n    case numberTag:\n    case stringTag:\n      return new Ctor(object);\n\n    case regexpTag:\n      var result = new Ctor(object.source, reFlags.exec(object));\n      result.lastIndex = object.lastIndex;\n  }\n  return result;\n}\n\nmodule.exports = initCloneByTag;\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{\"./bufferClone\":95}],118:[function(require,module,exports){\n/**\n * Initializes an object clone.\n *\n * @private\n * @param {Object} object The object to clone.\n * @returns {Object} Returns the initialized clone.\n */\nfunction initCloneObject(object) {\n  var Ctor = object.constructor;\n  if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {\n    Ctor = Object;\n  }\n  return new Ctor;\n}\n\nmodule.exports = initCloneObject;\n\n},{}],119:[function(require,module,exports){\nvar getLength = require('./getLength'),\n    isLength = require('./isLength');\n\n/**\n * Checks if `value` is array-like.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is array-like, else `false`.\n */\nfunction isArrayLike(value) {\n  return value != null && isLength(getLength(value));\n}\n\nmodule.exports = isArrayLike;\n\n},{\"./getLength\":112,\"./isLength\":125}],120:[function(require,module,exports){\n/**\n * Checks if `value` is a host object in IE < 9.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a host object, else `false`.\n */\nvar isHostObject = (function() {\n  try {\n    Object({ 'toString': 0 } + '');\n  } catch(e) {\n    return function() { return false; };\n  }\n  return function(value) {\n    // IE < 9 presents many host objects as `Object` objects that can coerce\n    // to strings despite having improperly defined `toString` methods.\n    return typeof value.toString != 'function' && typeof (value + '') == 'string';\n  };\n}());\n\nmodule.exports = isHostObject;\n\n},{}],121:[function(require,module,exports){\n/** Used to detect unsigned integer values. */\nvar reIsUint = /^\\d+$/;\n\n/**\n * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)\n * of an array-like value.\n */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like index.\n *\n * @private\n * @param {*} value The value to check.\n * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.\n * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.\n */\nfunction isIndex(value, length) {\n  value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;\n  length = length == null ? MAX_SAFE_INTEGER : length;\n  return value > -1 && value % 1 == 0 && value < length;\n}\n\nmodule.exports = isIndex;\n\n},{}],122:[function(require,module,exports){\nvar isArrayLike = require('./isArrayLike'),\n    isIndex = require('./isIndex'),\n    isObject = require('../lang/isObject');\n\n/**\n * Checks if the provided arguments are from an iteratee call.\n *\n * @private\n * @param {*} value The potential iteratee value argument.\n * @param {*} index The potential iteratee index or key argument.\n * @param {*} object The potential iteratee object argument.\n * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.\n */\nfunction isIterateeCall(value, index, object) {\n  if (!isObject(object)) {\n    return false;\n  }\n  var type = typeof index;\n  if (type == 'number'\n      ? (isArrayLike(object) && isIndex(index, object.length))\n      : (type == 'string' && index in object)) {\n    var other = object[index];\n    return value === value ? (value === other) : (other !== other);\n  }\n  return false;\n}\n\nmodule.exports = isIterateeCall;\n\n},{\"../lang/isObject\":144,\"./isArrayLike\":119,\"./isIndex\":121}],123:[function(require,module,exports){\nvar isArray = require('../lang/isArray'),\n    toObject = require('./toObject');\n\n/** Used to match property names within property paths. */\nvar reIsDeepProp = /\\.|\\[(?:[^[\\]]*|([\"'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*?\\1)\\]/,\n    reIsPlainProp = /^\\w*$/;\n\n/**\n * Checks if `value` is a property name and not a property path.\n *\n * @private\n * @param {*} value The value to check.\n * @param {Object} [object] The object to query keys on.\n * @returns {boolean} Returns `true` if `value` is a property name, else `false`.\n */\nfunction isKey(value, object) {\n  var type = typeof value;\n  if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {\n    return true;\n  }\n  if (isArray(value)) {\n    return false;\n  }\n  var result = !reIsDeepProp.test(value);\n  return result || (object != null && value in toObject(object));\n}\n\nmodule.exports = isKey;\n\n},{\"../lang/isArray\":140,\"./toObject\":135}],124:[function(require,module,exports){\nvar LazyWrapper = require('./LazyWrapper'),\n    getData = require('./getData'),\n    getFuncName = require('./getFuncName'),\n    lodash = require('../chain/lodash');\n\n/**\n * Checks if `func` has a lazy counterpart.\n *\n * @private\n * @param {Function} func The function to check.\n * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`.\n */\nfunction isLaziable(func) {\n  var funcName = getFuncName(func),\n      other = lodash[funcName];\n\n  if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {\n    return false;\n  }\n  if (func === other) {\n    return true;\n  }\n  var data = getData(other);\n  return !!data && func === data[0];\n}\n\nmodule.exports = isLaziable;\n\n},{\"../chain/lodash\":51,\"./LazyWrapper\":60,\"./getData\":110,\"./getFuncName\":111}],125:[function(require,module,exports){\n/**\n * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)\n * of an array-like value.\n */\nvar MAX_SAFE_INTEGER = 9007199254740991;\n\n/**\n * Checks if `value` is a valid array-like length.\n *\n * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.\n */\nfunction isLength(value) {\n  return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;\n}\n\nmodule.exports = isLength;\n\n},{}],126:[function(require,module,exports){\n/**\n * Checks if `value` is object-like.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n */\nfunction isObjectLike(value) {\n  return !!value && typeof value == 'object';\n}\n\nmodule.exports = isObjectLike;\n\n},{}],127:[function(require,module,exports){\nvar isObject = require('../lang/isObject');\n\n/**\n * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.\n *\n * @private\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` if suitable for strict\n *  equality comparisons, else `false`.\n */\nfunction isStrictComparable(value) {\n  return value === value && !isObject(value);\n}\n\nmodule.exports = isStrictComparable;\n\n},{\"../lang/isObject\":144}],128:[function(require,module,exports){\nvar arrayCopy = require('./arrayCopy'),\n    composeArgs = require('./composeArgs'),\n    composeArgsRight = require('./composeArgsRight'),\n    replaceHolders = require('./replaceHolders');\n\n/** Used to compose bitmasks for wrapper metadata. */\nvar BIND_FLAG = 1,\n    CURRY_BOUND_FLAG = 4,\n    CURRY_FLAG = 8,\n    ARY_FLAG = 128,\n    REARG_FLAG = 256;\n\n/** Used as the internal argument placeholder. */\nvar PLACEHOLDER = '__lodash_placeholder__';\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeMin = Math.min;\n\n/**\n * Merges the function metadata of `source` into `data`.\n *\n * Merging metadata reduces the number of wrappers required to invoke a function.\n * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`\n * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg`\n * augment function arguments, making the order in which they are executed important,\n * preventing the merging of metadata. However, we make an exception for a safe\n * common case where curried functions have `_.ary` and or `_.rearg` applied.\n *\n * @private\n * @param {Array} data The destination metadata.\n * @param {Array} source The source metadata.\n * @returns {Array} Returns `data`.\n */\nfunction mergeData(data, source) {\n  var bitmask = data[1],\n      srcBitmask = source[1],\n      newBitmask = bitmask | srcBitmask,\n      isCommon = newBitmask < ARY_FLAG;\n\n  var isCombo =\n    (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) ||\n    (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) ||\n    (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG);\n\n  // Exit early if metadata can't be merged.\n  if (!(isCommon || isCombo)) {\n    return data;\n  }\n  // Use source `thisArg` if available.\n  if (srcBitmask & BIND_FLAG) {\n    data[2] = source[2];\n    // Set when currying a bound function.\n    newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;\n  }\n  // Compose partial arguments.\n  var value = source[3];\n  if (value) {\n    var partials = data[3];\n    data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);\n    data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);\n  }\n  // Compose partial right arguments.\n  value = source[5];\n  if (value) {\n    partials = data[5];\n    data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);\n    data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);\n  }\n  // Use source `argPos` if available.\n  value = source[7];\n  if (value) {\n    data[7] = arrayCopy(value);\n  }\n  // Use source `ary` if it's smaller.\n  if (srcBitmask & ARY_FLAG) {\n    data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);\n  }\n  // Use source `arity` if one is not provided.\n  if (data[9] == null) {\n    data[9] = source[9];\n  }\n  // Use source `func` and merge bitmasks.\n  data[0] = source[0];\n  data[1] = newBitmask;\n\n  return data;\n}\n\nmodule.exports = mergeData;\n\n},{\"./arrayCopy\":62,\"./composeArgs\":96,\"./composeArgsRight\":97,\"./replaceHolders\":132}],129:[function(require,module,exports){\n(function (global){\nvar getNative = require('./getNative');\n\n/** Native method references. */\nvar WeakMap = getNative(global, 'WeakMap');\n\n/** Used to store function metadata. */\nvar metaMap = WeakMap && new WeakMap;\n\nmodule.exports = metaMap;\n\n}).call(this,typeof global !== \"undefined\" ? global : typeof self !== \"undefined\" ? self : typeof window !== \"undefined\" ? window : {})\n\n},{\"./getNative\":114}],130:[function(require,module,exports){\n/** Used to lookup unminified function names. */\nvar realNames = {};\n\nmodule.exports = realNames;\n\n},{}],131:[function(require,module,exports){\nvar arrayCopy = require('./arrayCopy'),\n    isIndex = require('./isIndex');\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeMin = Math.min;\n\n/**\n * Reorder `array` according to the specified indexes where the element at\n * the first index is assigned as the first element, the element at\n * the second index is assigned as the second element, and so on.\n *\n * @private\n * @param {Array} array The array to reorder.\n * @param {Array} indexes The arranged array indexes.\n * @returns {Array} Returns `array`.\n */\nfunction reorder(array, indexes) {\n  var arrLength = array.length,\n      length = nativeMin(indexes.length, arrLength),\n      oldArray = arrayCopy(array);\n\n  while (length--) {\n    var index = indexes[length];\n    array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;\n  }\n  return array;\n}\n\nmodule.exports = reorder;\n\n},{\"./arrayCopy\":62,\"./isIndex\":121}],132:[function(require,module,exports){\n/** Used as the internal argument placeholder. */\nvar PLACEHOLDER = '__lodash_placeholder__';\n\n/**\n * Replaces all `placeholder` elements in `array` with an internal placeholder\n * and returns an array of their indexes.\n *\n * @private\n * @param {Array} array The array to modify.\n * @param {*} placeholder The placeholder to replace.\n * @returns {Array} Returns the new array of placeholder indexes.\n */\nfunction replaceHolders(array, placeholder) {\n  var index = -1,\n      length = array.length,\n      resIndex = -1,\n      result = [];\n\n  while (++index < length) {\n    if (array[index] === placeholder) {\n      array[index] = PLACEHOLDER;\n      result[++resIndex] = index;\n    }\n  }\n  return result;\n}\n\nmodule.exports = replaceHolders;\n\n},{}],133:[function(require,module,exports){\nvar baseSetData = require('./baseSetData'),\n    now = require('../date/now');\n\n/** Used to detect when a function becomes hot. */\nvar HOT_COUNT = 150,\n    HOT_SPAN = 16;\n\n/**\n * Sets metadata for `func`.\n *\n * **Note:** If this function becomes hot, i.e. is invoked a lot in a short\n * period of time, it will trip its breaker and transition to an identity function\n * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070)\n * for more details.\n *\n * @private\n * @param {Function} func The function to associate metadata with.\n * @param {*} data The metadata.\n * @returns {Function} Returns `func`.\n */\nvar setData = (function() {\n  var count = 0,\n      lastCalled = 0;\n\n  return function(key, value) {\n    var stamp = now(),\n        remaining = HOT_SPAN - (stamp - lastCalled);\n\n    lastCalled = stamp;\n    if (remaining > 0) {\n      if (++count >= HOT_COUNT) {\n        return key;\n      }\n    } else {\n      count = 0;\n    }\n    return baseSetData(key, value);\n  };\n}());\n\nmodule.exports = setData;\n\n},{\"../date/now\":57,\"./baseSetData\":88}],134:[function(require,module,exports){\nvar isArguments = require('../lang/isArguments'),\n    isArray = require('../lang/isArray'),\n    isIndex = require('./isIndex'),\n    isLength = require('./isLength'),\n    isString = require('../lang/isString'),\n    keysIn = require('../object/keysIn');\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * A fallback implementation of `Object.keys` which creates an array of the\n * own enumerable property names of `object`.\n *\n * @private\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n */\nfunction shimKeys(object) {\n  var props = keysIn(object),\n      propsLength = props.length,\n      length = propsLength && object.length;\n\n  var allowIndexes = !!length && isLength(length) &&\n    (isArray(object) || isArguments(object) || isString(object));\n\n  var index = -1,\n      result = [];\n\n  while (++index < propsLength) {\n    var key = props[index];\n    if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {\n      result.push(key);\n    }\n  }\n  return result;\n}\n\nmodule.exports = shimKeys;\n\n},{\"../lang/isArguments\":139,\"../lang/isArray\":140,\"../lang/isString\":146,\"../object/keysIn\":150,\"./isIndex\":121,\"./isLength\":125}],135:[function(require,module,exports){\nvar isObject = require('../lang/isObject'),\n    isString = require('../lang/isString'),\n    support = require('../support');\n\n/**\n * Converts `value` to an object if it's not one.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {Object} Returns the object.\n */\nfunction toObject(value) {\n  if (support.unindexedChars && isString(value)) {\n    var index = -1,\n        length = value.length,\n        result = Object(value);\n\n    while (++index < length) {\n      result[index] = value.charAt(index);\n    }\n    return result;\n  }\n  return isObject(value) ? value : Object(value);\n}\n\nmodule.exports = toObject;\n\n},{\"../lang/isObject\":144,\"../lang/isString\":146,\"../support\":153}],136:[function(require,module,exports){\nvar baseToString = require('./baseToString'),\n    isArray = require('../lang/isArray');\n\n/** Used to match property names within property paths. */\nvar rePropName = /[^.[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\\2)[^\\n\\\\]|\\\\.)*?)\\2)\\]/g;\n\n/** Used to match backslashes in property paths. */\nvar reEscapeChar = /\\\\(\\\\)?/g;\n\n/**\n * Converts `value` to property path array if it's not one.\n *\n * @private\n * @param {*} value The value to process.\n * @returns {Array} Returns the property path array.\n */\nfunction toPath(value) {\n  if (isArray(value)) {\n    return value;\n  }\n  var result = [];\n  baseToString(value).replace(rePropName, function(match, number, quote, string) {\n    result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));\n  });\n  return result;\n}\n\nmodule.exports = toPath;\n\n},{\"../lang/isArray\":140,\"./baseToString\":90}],137:[function(require,module,exports){\nvar LazyWrapper = require('./LazyWrapper'),\n    LodashWrapper = require('./LodashWrapper'),\n    arrayCopy = require('./arrayCopy');\n\n/**\n * Creates a clone of `wrapper`.\n *\n * @private\n * @param {Object} wrapper The wrapper to clone.\n * @returns {Object} Returns the cloned wrapper.\n */\nfunction wrapperClone(wrapper) {\n  return wrapper instanceof LazyWrapper\n    ? wrapper.clone()\n    : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__));\n}\n\nmodule.exports = wrapperClone;\n\n},{\"./LazyWrapper\":60,\"./LodashWrapper\":61,\"./arrayCopy\":62}],138:[function(require,module,exports){\nvar baseClone = require('../internal/baseClone'),\n    bindCallback = require('../internal/bindCallback');\n\n/**\n * Creates a deep clone of `value`. If `customizer` is provided it's invoked\n * to produce the cloned values. If `customizer` returns `undefined` cloning\n * is handled by the method instead. The `customizer` is bound to `thisArg`\n * and invoked with up to three argument; (value [, index|key, object]).\n *\n * **Note:** This method is loosely based on the\n * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).\n * The enumerable properties of `arguments` objects and objects created by\n * constructors other than `Object` are cloned to plain `Object` objects. An\n * empty object is returned for uncloneable values such as functions, DOM nodes,\n * Maps, Sets, and WeakMaps.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to deep clone.\n * @param {Function} [customizer] The function to customize cloning values.\n * @param {*} [thisArg] The `this` binding of `customizer`.\n * @returns {*} Returns the deep cloned value.\n * @example\n *\n * var users = [\n *   { 'user': 'barney' },\n *   { 'user': 'fred' }\n * ];\n *\n * var deep = _.cloneDeep(users);\n * deep[0] === users[0];\n * // => false\n *\n * // using a customizer callback\n * var el = _.cloneDeep(document.body, function(value) {\n *   if (_.isElement(value)) {\n *     return value.cloneNode(true);\n *   }\n * });\n *\n * el === document.body\n * // => false\n * el.nodeName\n * // => BODY\n * el.childNodes.length;\n * // => 20\n */\nfunction cloneDeep(value, customizer, thisArg) {\n  return typeof customizer == 'function'\n    ? baseClone(value, true, bindCallback(customizer, thisArg, 3))\n    : baseClone(value, true);\n}\n\nmodule.exports = cloneDeep;\n\n},{\"../internal/baseClone\":68,\"../internal/bindCallback\":94}],139:[function(require,module,exports){\nvar isArrayLike = require('../internal/isArrayLike'),\n    isObjectLike = require('../internal/isObjectLike');\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Native method references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable;\n\n/**\n * Checks if `value` is classified as an `arguments` object.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n * @example\n *\n * _.isArguments(function() { return arguments; }());\n * // => true\n *\n * _.isArguments([1, 2, 3]);\n * // => false\n */\nfunction isArguments(value) {\n  return isObjectLike(value) && isArrayLike(value) &&\n    hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');\n}\n\nmodule.exports = isArguments;\n\n},{\"../internal/isArrayLike\":119,\"../internal/isObjectLike\":126}],140:[function(require,module,exports){\nvar getNative = require('../internal/getNative'),\n    isLength = require('../internal/isLength'),\n    isObjectLike = require('../internal/isObjectLike');\n\n/** `Object#toString` result references. */\nvar arrayTag = '[object Array]';\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeIsArray = getNative(Array, 'isArray');\n\n/**\n * Checks if `value` is classified as an `Array` object.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n * @example\n *\n * _.isArray([1, 2, 3]);\n * // => true\n *\n * _.isArray(function() { return arguments; }());\n * // => false\n */\nvar isArray = nativeIsArray || function(value) {\n  return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;\n};\n\nmodule.exports = isArray;\n\n},{\"../internal/getNative\":114,\"../internal/isLength\":125,\"../internal/isObjectLike\":126}],141:[function(require,module,exports){\nvar isArguments = require('./isArguments'),\n    isArray = require('./isArray'),\n    isArrayLike = require('../internal/isArrayLike'),\n    isFunction = require('./isFunction'),\n    isObjectLike = require('../internal/isObjectLike'),\n    isString = require('./isString'),\n    keys = require('../object/keys');\n\n/**\n * Checks if `value` is empty. A value is considered empty unless it's an\n * `arguments` object, array, string, or jQuery-like collection with a length\n * greater than `0` or an object with own enumerable properties.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {Array|Object|string} value The value to inspect.\n * @returns {boolean} Returns `true` if `value` is empty, else `false`.\n * @example\n *\n * _.isEmpty(null);\n * // => true\n *\n * _.isEmpty(true);\n * // => true\n *\n * _.isEmpty(1);\n * // => true\n *\n * _.isEmpty([1, 2, 3]);\n * // => false\n *\n * _.isEmpty({ 'a': 1 });\n * // => false\n */\nfunction isEmpty(value) {\n  if (value == null) {\n    return true;\n  }\n  if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) ||\n      (isObjectLike(value) && isFunction(value.splice)))) {\n    return !value.length;\n  }\n  return !keys(value).length;\n}\n\nmodule.exports = isEmpty;\n\n},{\"../internal/isArrayLike\":119,\"../internal/isObjectLike\":126,\"../object/keys\":149,\"./isArguments\":139,\"./isArray\":140,\"./isFunction\":142,\"./isString\":146}],142:[function(require,module,exports){\nvar isObject = require('./isObject');\n\n/** `Object#toString` result references. */\nvar funcTag = '[object Function]';\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/**\n * Checks if `value` is classified as a `Function` object.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n * @example\n *\n * _.isFunction(_);\n * // => true\n *\n * _.isFunction(/abc/);\n * // => false\n */\nfunction isFunction(value) {\n  // The use of `Object#toString` avoids issues with the `typeof` operator\n  // in older versions of Chrome and Safari which return 'function' for regexes\n  // and Safari 8 which returns 'object' for typed array constructors.\n  return isObject(value) && objToString.call(value) == funcTag;\n}\n\nmodule.exports = isFunction;\n\n},{\"./isObject\":144}],143:[function(require,module,exports){\nvar isFunction = require('./isFunction'),\n    isHostObject = require('../internal/isHostObject'),\n    isObjectLike = require('../internal/isObjectLike');\n\n/** Used to detect host constructors (Safari > 5). */\nvar reIsHostCtor = /^\\[object .+?Constructor\\]$/;\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to resolve the decompiled source of functions. */\nvar fnToString = Function.prototype.toString;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/** Used to detect if a method is native. */\nvar reIsNative = RegExp('^' +\n  fnToString.call(hasOwnProperty).replace(/[\\\\^$.*+?()[\\]{}|]/g, '\\\\$&')\n  .replace(/hasOwnProperty|(function).*?(?=\\\\\\()| for .+?(?=\\\\\\])/g, '$1.*?') + '$'\n);\n\n/**\n * Checks if `value` is a native function.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a native function, else `false`.\n * @example\n *\n * _.isNative(Array.prototype.push);\n * // => true\n *\n * _.isNative(_);\n * // => false\n */\nfunction isNative(value) {\n  if (value == null) {\n    return false;\n  }\n  if (isFunction(value)) {\n    return reIsNative.test(fnToString.call(value));\n  }\n  return isObjectLike(value) && (isHostObject(value) ? reIsNative : reIsHostCtor).test(value);\n}\n\nmodule.exports = isNative;\n\n},{\"../internal/isHostObject\":120,\"../internal/isObjectLike\":126,\"./isFunction\":142}],144:[function(require,module,exports){\n/**\n * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.\n * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(1);\n * // => false\n */\nfunction isObject(value) {\n  // Avoid a V8 JIT bug in Chrome 19-20.\n  // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.\n  var type = typeof value;\n  return !!value && (type == 'object' || type == 'function');\n}\n\nmodule.exports = isObject;\n\n},{}],145:[function(require,module,exports){\nvar baseForIn = require('../internal/baseForIn'),\n    isArguments = require('./isArguments'),\n    isHostObject = require('../internal/isHostObject'),\n    isObjectLike = require('../internal/isObjectLike'),\n    support = require('../support');\n\n/** `Object#toString` result references. */\nvar objectTag = '[object Object]';\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/**\n * Checks if `value` is a plain object, that is, an object created by the\n * `Object` constructor or one with a `[[Prototype]]` of `null`.\n *\n * **Note:** This method assumes objects created by the `Object` constructor\n * have no inherited enumerable properties.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.\n * @example\n *\n * function Foo() {\n *   this.a = 1;\n * }\n *\n * _.isPlainObject(new Foo);\n * // => false\n *\n * _.isPlainObject([1, 2, 3]);\n * // => false\n *\n * _.isPlainObject({ 'x': 0, 'y': 0 });\n * // => true\n *\n * _.isPlainObject(Object.create(null));\n * // => true\n */\nfunction isPlainObject(value) {\n  var Ctor;\n\n  // Exit early for non `Object` objects.\n  if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isHostObject(value) && !isArguments(value)) ||\n      (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {\n    return false;\n  }\n  // IE < 9 iterates inherited properties before own properties. If the first\n  // iterated property is an object's own property then there are no inherited\n  // enumerable properties.\n  var result;\n  if (support.ownLast) {\n    baseForIn(value, function(subValue, key, object) {\n      result = hasOwnProperty.call(object, key);\n      return false;\n    });\n    return result !== false;\n  }\n  // In most environments an object's own properties are iterated before\n  // its inherited properties. If the last iterated property is an object's\n  // own property then there are no inherited enumerable properties.\n  baseForIn(value, function(subValue, key) {\n    result = key;\n  });\n  return result === undefined || hasOwnProperty.call(value, result);\n}\n\nmodule.exports = isPlainObject;\n\n},{\"../internal/baseForIn\":75,\"../internal/isHostObject\":120,\"../internal/isObjectLike\":126,\"../support\":153,\"./isArguments\":139}],146:[function(require,module,exports){\nvar isObjectLike = require('../internal/isObjectLike');\n\n/** `Object#toString` result references. */\nvar stringTag = '[object String]';\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/**\n * Checks if `value` is classified as a `String` primitive or object.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n * @example\n *\n * _.isString('abc');\n * // => true\n *\n * _.isString(1);\n * // => false\n */\nfunction isString(value) {\n  return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);\n}\n\nmodule.exports = isString;\n\n},{\"../internal/isObjectLike\":126}],147:[function(require,module,exports){\nvar isLength = require('../internal/isLength'),\n    isObjectLike = require('../internal/isObjectLike');\n\n/** `Object#toString` result references. */\nvar argsTag = '[object Arguments]',\n    arrayTag = '[object Array]',\n    boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    errorTag = '[object Error]',\n    funcTag = '[object Function]',\n    mapTag = '[object Map]',\n    numberTag = '[object Number]',\n    objectTag = '[object Object]',\n    regexpTag = '[object RegExp]',\n    setTag = '[object Set]',\n    stringTag = '[object String]',\n    weakMapTag = '[object WeakMap]';\n\nvar arrayBufferTag = '[object ArrayBuffer]',\n    float32Tag = '[object Float32Array]',\n    float64Tag = '[object Float64Array]',\n    int8Tag = '[object Int8Array]',\n    int16Tag = '[object Int16Array]',\n    int32Tag = '[object Int32Array]',\n    uint8Tag = '[object Uint8Array]',\n    uint8ClampedTag = '[object Uint8ClampedArray]',\n    uint16Tag = '[object Uint16Array]',\n    uint32Tag = '[object Uint32Array]';\n\n/** Used to identify `toStringTag` values of typed arrays. */\nvar typedArrayTags = {};\ntypedArrayTags[float32Tag] = typedArrayTags[float64Tag] =\ntypedArrayTags[int8Tag] = typedArrayTags[int16Tag] =\ntypedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =\ntypedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =\ntypedArrayTags[uint32Tag] = true;\ntypedArrayTags[argsTag] = typedArrayTags[arrayTag] =\ntypedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =\ntypedArrayTags[dateTag] = typedArrayTags[errorTag] =\ntypedArrayTags[funcTag] = typedArrayTags[mapTag] =\ntypedArrayTags[numberTag] = typedArrayTags[objectTag] =\ntypedArrayTags[regexpTag] = typedArrayTags[setTag] =\ntypedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;\n\n/** Used for native method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/**\n * Checks if `value` is classified as a typed array.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.\n * @example\n *\n * _.isTypedArray(new Uint8Array);\n * // => true\n *\n * _.isTypedArray([]);\n * // => false\n */\nfunction isTypedArray(value) {\n  return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];\n}\n\nmodule.exports = isTypedArray;\n\n},{\"../internal/isLength\":125,\"../internal/isObjectLike\":126}],148:[function(require,module,exports){\n/**\n * Checks if `value` is `undefined`.\n *\n * @static\n * @memberOf _\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.\n * @example\n *\n * _.isUndefined(void 0);\n * // => true\n *\n * _.isUndefined(null);\n * // => false\n */\nfunction isUndefined(value) {\n  return value === undefined;\n}\n\nmodule.exports = isUndefined;\n\n},{}],149:[function(require,module,exports){\nvar getNative = require('../internal/getNative'),\n    isArrayLike = require('../internal/isArrayLike'),\n    isObject = require('../lang/isObject'),\n    shimKeys = require('../internal/shimKeys'),\n    support = require('../support');\n\n/* Native method references for those with the same name as other `lodash` methods. */\nvar nativeKeys = getNative(Object, 'keys');\n\n/**\n * Creates an array of the own enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects. See the\n * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)\n * for more details.\n *\n * @static\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n *   this.a = 1;\n *   this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keys(new Foo);\n * // => ['a', 'b'] (iteration order is not guaranteed)\n *\n * _.keys('hi');\n * // => ['0', '1']\n */\nvar keys = !nativeKeys ? shimKeys : function(object) {\n  var Ctor = object == null ? undefined : object.constructor;\n  if ((typeof Ctor == 'function' && Ctor.prototype === object) ||\n      (typeof object == 'function' ? support.enumPrototypes : isArrayLike(object))) {\n    return shimKeys(object);\n  }\n  return isObject(object) ? nativeKeys(object) : [];\n};\n\nmodule.exports = keys;\n\n},{\"../internal/getNative\":114,\"../internal/isArrayLike\":119,\"../internal/shimKeys\":134,\"../lang/isObject\":144,\"../support\":153}],150:[function(require,module,exports){\nvar arrayEach = require('../internal/arrayEach'),\n    isArguments = require('../lang/isArguments'),\n    isArray = require('../lang/isArray'),\n    isFunction = require('../lang/isFunction'),\n    isIndex = require('../internal/isIndex'),\n    isLength = require('../internal/isLength'),\n    isObject = require('../lang/isObject'),\n    isString = require('../lang/isString'),\n    support = require('../support');\n\n/** `Object#toString` result references. */\nvar arrayTag = '[object Array]',\n    boolTag = '[object Boolean]',\n    dateTag = '[object Date]',\n    errorTag = '[object Error]',\n    funcTag = '[object Function]',\n    numberTag = '[object Number]',\n    objectTag = '[object Object]',\n    regexpTag = '[object RegExp]',\n    stringTag = '[object String]';\n\n/** Used to fix the JScript `[[DontEnum]]` bug. */\nvar shadowProps = [\n  'constructor', 'hasOwnProperty', 'isPrototypeOf', 'propertyIsEnumerable',\n  'toLocaleString', 'toString', 'valueOf'\n];\n\n/** Used for native method references. */\nvar errorProto = Error.prototype,\n    objectProto = Object.prototype,\n    stringProto = String.prototype;\n\n/** Used to check objects for own properties. */\nvar hasOwnProperty = objectProto.hasOwnProperty;\n\n/**\n * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objToString = objectProto.toString;\n\n/** Used to avoid iterating over non-enumerable properties in IE < 9. */\nvar nonEnumProps = {};\nnonEnumProps[arrayTag] = nonEnumProps[dateTag] = nonEnumProps[numberTag] = { 'constructor': true, 'toLocaleString': true, 'toString': true, 'valueOf': true };\nnonEnumProps[boolTag] = nonEnumProps[stringTag] = { 'constructor': true, 'toString': true, 'valueOf': true };\nnonEnumProps[errorTag] = nonEnumProps[funcTag] = nonEnumProps[regexpTag] = { 'constructor': true, 'toString': true };\nnonEnumProps[objectTag] = { 'constructor': true };\n\narrayEach(shadowProps, function(key) {\n  for (var tag in nonEnumProps) {\n    if (hasOwnProperty.call(nonEnumProps, tag)) {\n      var props = nonEnumProps[tag];\n      props[key] = hasOwnProperty.call(props, key);\n    }\n  }\n});\n\n/**\n * Creates an array of the own and inherited enumerable property names of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property names.\n * @example\n *\n * function Foo() {\n *   this.a = 1;\n *   this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.keysIn(new Foo);\n * // => ['a', 'b', 'c'] (iteration order is not guaranteed)\n */\nfunction keysIn(object) {\n  if (object == null) {\n    return [];\n  }\n  if (!isObject(object)) {\n    object = Object(object);\n  }\n  var length = object.length;\n\n  length = (length && isLength(length) &&\n    (isArray(object) || isArguments(object) || isString(object)) && length) || 0;\n\n  var Ctor = object.constructor,\n      index = -1,\n      proto = (isFunction(Ctor) && Ctor.prototype) || objectProto,\n      isProto = proto === object,\n      result = Array(length),\n      skipIndexes = length > 0,\n      skipErrorProps = support.enumErrorProps && (object === errorProto || object instanceof Error),\n      skipProto = support.enumPrototypes && isFunction(object);\n\n  while (++index < length) {\n    result[index] = (index + '');\n  }\n  // lodash skips the `constructor` property when it infers it's iterating\n  // over a `prototype` object because IE < 9 can't set the `[[Enumerable]]`\n  // attribute of an existing property and the `constructor` property of a\n  // prototype defaults to non-enumerable.\n  for (var key in object) {\n    if (!(skipProto && key == 'prototype') &&\n        !(skipErrorProps && (key == 'message' || key == 'name')) &&\n        !(skipIndexes && isIndex(key, length)) &&\n        !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {\n      result.push(key);\n    }\n  }\n  if (support.nonEnumShadows && object !== objectProto) {\n    var tag = object === stringProto ? stringTag : (object === errorProto ? errorTag : objToString.call(object)),\n        nonEnums = nonEnumProps[tag] || nonEnumProps[objectTag];\n\n    if (tag == objectTag) {\n      proto = objectProto;\n    }\n    length = shadowProps.length;\n    while (length--) {\n      key = shadowProps[length];\n      var nonEnum = nonEnums[key];\n      if (!(isProto && nonEnum) &&\n          (nonEnum ? hasOwnProperty.call(object, key) : object[key] !== proto[key])) {\n        result.push(key);\n      }\n    }\n  }\n  return result;\n}\n\nmodule.exports = keysIn;\n\n},{\"../internal/arrayEach\":63,\"../internal/isIndex\":121,\"../internal/isLength\":125,\"../lang/isArguments\":139,\"../lang/isArray\":140,\"../lang/isFunction\":142,\"../lang/isObject\":144,\"../lang/isString\":146,\"../support\":153}],151:[function(require,module,exports){\nvar keys = require('./keys'),\n    toObject = require('../internal/toObject');\n\n/**\n * Creates a two dimensional array of the key-value pairs for `object`,\n * e.g. `[[key1, value1], [key2, value2]]`.\n *\n * @static\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the new array of key-value pairs.\n * @example\n *\n * _.pairs({ 'barney': 36, 'fred': 40 });\n * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed)\n */\nfunction pairs(object) {\n  object = toObject(object);\n\n  var index = -1,\n      props = keys(object),\n      length = props.length,\n      result = Array(length);\n\n  while (++index < length) {\n    var key = props[index];\n    result[index] = [key, object[key]];\n  }\n  return result;\n}\n\nmodule.exports = pairs;\n\n},{\"../internal/toObject\":135,\"./keys\":149}],152:[function(require,module,exports){\nvar baseValues = require('../internal/baseValues'),\n    keys = require('./keys');\n\n/**\n * Creates an array of the own enumerable property values of `object`.\n *\n * **Note:** Non-object values are coerced to objects.\n *\n * @static\n * @memberOf _\n * @category Object\n * @param {Object} object The object to query.\n * @returns {Array} Returns the array of property values.\n * @example\n *\n * function Foo() {\n *   this.a = 1;\n *   this.b = 2;\n * }\n *\n * Foo.prototype.c = 3;\n *\n * _.values(new Foo);\n * // => [1, 2] (iteration order is not guaranteed)\n *\n * _.values('hi');\n * // => ['h', 'i']\n */\nfunction values(object) {\n  return baseValues(object, keys(object));\n}\n\nmodule.exports = values;\n\n},{\"../internal/baseValues\":91,\"./keys\":149}],153:[function(require,module,exports){\n/** Used for native method references. */\nvar arrayProto = Array.prototype,\n    errorProto = Error.prototype,\n    objectProto = Object.prototype;\n\n/** Native method references. */\nvar propertyIsEnumerable = objectProto.propertyIsEnumerable,\n    splice = arrayProto.splice;\n\n/**\n * An object environment feature flags.\n *\n * @static\n * @memberOf _\n * @type Object\n */\nvar support = {};\n\n(function(x) {\n  var Ctor = function() { this.x = x; },\n      object = { '0': x, 'length': x },\n      props = [];\n\n  Ctor.prototype = { 'valueOf': x, 'y': x };\n  for (var key in new Ctor) { props.push(key); }\n\n  /**\n   * Detect if `name` or `message` properties of `Error.prototype` are\n   * enumerable by default (IE < 9, Safari < 5.1).\n   *\n   * @memberOf _.support\n   * @type boolean\n   */\n  support.enumErrorProps = propertyIsEnumerable.call(errorProto, 'message') ||\n    propertyIsEnumerable.call(errorProto, 'name');\n\n  /**\n   * Detect if `prototype` properties are enumerable by default.\n   *\n   * Firefox < 3.6, Opera > 9.50 - Opera < 11.60, and Safari < 5.1\n   * (if the prototype or a property on the prototype has been set)\n   * incorrectly set the `[[Enumerable]]` value of a function's `prototype`\n   * property to `true`.\n   *\n   * @memberOf _.support\n   * @type boolean\n   */\n  support.enumPrototypes = propertyIsEnumerable.call(Ctor, 'prototype');\n\n  /**\n   * Detect if properties shadowing those on `Object.prototype` are non-enumerable.\n   *\n   * In IE < 9 an object's own properties, shadowing non-enumerable ones,\n   * are made non-enumerable as well (a.k.a the JScript `[[DontEnum]]` bug).\n   *\n   * @memberOf _.support\n   * @type boolean\n   */\n  support.nonEnumShadows = !/valueOf/.test(props);\n\n  /**\n   * Detect if own properties are iterated after inherited properties (IE < 9).\n   *\n   * @memberOf _.support\n   * @type boolean\n   */\n  support.ownLast = props[0] != 'x';\n\n  /**\n   * Detect if `Array#shift` and `Array#splice` augment array-like objects\n   * correctly.\n   *\n   * Firefox < 10, compatibility modes of IE 8, and IE < 9 have buggy Array\n   * `shift()` and `splice()` functions that fail to remove the last element,\n   * `value[0]`, of array-like objects even though the \"length\" property is\n   * set to `0`. The `shift()` method is buggy in compatibility modes of IE 8,\n   * while `splice()` is buggy regardless of mode in IE < 9.\n   *\n   * @memberOf _.support\n   * @type boolean\n   */\n  support.spliceObjects = (splice.call(object, 0, 1), !object[0]);\n\n  /**\n   * Detect lack of support for accessing string characters by index.\n   *\n   * IE < 8 can't access characters by index. IE 8 can only access characters\n   * by index on string literals, not string objects.\n   *\n   * @memberOf _.support\n   * @type boolean\n   */\n  support.unindexedChars = ('x'[0] + Object('x')[0]) != 'xx';\n}(1, 0));\n\nmodule.exports = support;\n\n},{}],154:[function(require,module,exports){\n/**\n * This method returns the first argument provided to it.\n *\n * @static\n * @memberOf _\n * @category Utility\n * @param {*} value Any value.\n * @returns {*} Returns `value`.\n * @example\n *\n * var object = { 'user': 'fred' };\n *\n * _.identity(object) === object;\n * // => true\n */\nfunction identity(value) {\n  return value;\n}\n\nmodule.exports = identity;\n\n},{}],155:[function(require,module,exports){\n/**\n * A no-operation function that returns `undefined` regardless of the\n * arguments it receives.\n *\n * @static\n * @memberOf _\n * @category Utility\n * @example\n *\n * var object = { 'user': 'fred' };\n *\n * _.noop(object) === undefined;\n * // => true\n */\nfunction noop() {\n  // No operation performed.\n}\n\nmodule.exports = noop;\n\n},{}],156:[function(require,module,exports){\nvar baseProperty = require('../internal/baseProperty'),\n    basePropertyDeep = require('../internal/basePropertyDeep'),\n    isKey = require('../internal/isKey');\n\n/**\n * Creates a function that returns the property value at `path` on a\n * given object.\n *\n * @static\n * @memberOf _\n * @category Utility\n * @param {Array|string} path The path of the property to get.\n * @returns {Function} Returns the new function.\n * @example\n *\n * var objects = [\n *   { 'a': { 'b': { 'c': 2 } } },\n *   { 'a': { 'b': { 'c': 1 } } }\n * ];\n *\n * _.map(objects, _.property('a.b.c'));\n * // => [2, 1]\n *\n * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');\n * // => [1, 2]\n */\nfunction property(path) {\n  return isKey(path) ? baseProperty(path) : basePropertyDeep(path);\n}\n\nmodule.exports = property;\n\n},{\"../internal/baseProperty\":86,\"../internal/basePropertyDeep\":87,\"../internal/isKey\":123}],157:[function(require,module,exports){\n(function (process){\n// vim:ts=4:sts=4:sw=4:\n/*!\n *\n * Copyright 2009-2012 Kris Kowal under the terms of the MIT\n * license found at http://github.com/kriskowal/q/raw/master/LICENSE\n *\n * With parts by Tyler Close\n * Copyright 2007-2009 Tyler Close under the terms of the MIT X license found\n * at http://www.opensource.org/licenses/mit-license.html\n * Forked at ref_send.js version: 2009-05-11\n *\n * With parts by Mark Miller\n * Copyright (C) 2011 Google Inc.\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(function (definition) {\n    \"use strict\";\n\n    // This file will function properly as a <script> tag, or a module\n    // using CommonJS and NodeJS or RequireJS module formats.  In\n    // Common/Node/RequireJS, the module exports the Q API and when\n    // executed as a simple <script>, it creates a Q global instead.\n\n    // Montage Require\n    if (typeof bootstrap === \"function\") {\n        bootstrap(\"promise\", definition);\n\n    // CommonJS\n    } else if (typeof exports === \"object\" && typeof module === \"object\") {\n        module.exports = definition();\n\n    // RequireJS\n    } else if (typeof define === \"function\" && define.amd) {\n        define(definition);\n\n    // SES (Secure EcmaScript)\n    } else if (typeof ses !== \"undefined\") {\n        if (!ses.ok()) {\n            return;\n        } else {\n            ses.makeQ = definition;\n        }\n\n    // <script>\n    } else if (typeof window !== \"undefined\" || typeof self !== \"undefined\") {\n        // Prefer window over self for add-on scripts. Use self for\n        // non-windowed contexts.\n        var global = typeof window !== \"undefined\" ? window : self;\n\n        // Get the `window` object, save the previous Q global\n        // and initialize Q as a global.\n        var previousQ = global.Q;\n        global.Q = definition();\n\n        // Add a noConflict function so Q can be removed from the\n        // global namespace.\n        global.Q.noConflict = function () {\n            global.Q = previousQ;\n            return this;\n        };\n\n    } else {\n        throw new Error(\"This environment was not anticipated by Q. Please file a bug.\");\n    }\n\n})(function () {\n\"use strict\";\n\nvar hasStacks = false;\ntry {\n    throw new Error();\n} catch (e) {\n    hasStacks = !!e.stack;\n}\n\n// All code after this point will be filtered from stack traces reported\n// by Q.\nvar qStartingLine = captureLine();\nvar qFileName;\n\n// shims\n\n// used for fallback in \"allResolved\"\nvar noop = function () {};\n\n// Use the fastest possible means to execute a task in a future turn\n// of the event loop.\nvar nextTick =(function () {\n    // linked list of tasks (single, with head node)\n    var head = {task: void 0, next: null};\n    var tail = head;\n    var flushing = false;\n    var requestTick = void 0;\n    var isNodeJS = false;\n    // queue for late tasks, used by unhandled rejection tracking\n    var laterQueue = [];\n\n    function flush() {\n        /* jshint loopfunc: true */\n        var task, domain;\n\n        while (head.next) {\n            head = head.next;\n            task = head.task;\n            head.task = void 0;\n            domain = head.domain;\n\n            if (domain) {\n                head.domain = void 0;\n                domain.enter();\n            }\n            runSingle(task, domain);\n\n        }\n        while (laterQueue.length) {\n            task = laterQueue.pop();\n            runSingle(task);\n        }\n        flushing = false;\n    }\n    // runs a single function in the async queue\n    function runSingle(task, domain) {\n        try {\n            task();\n\n        } catch (e) {\n            if (isNodeJS) {\n                // In node, uncaught exceptions are considered fatal errors.\n                // Re-throw them synchronously to interrupt flushing!\n\n                // Ensure continuation if the uncaught exception is suppressed\n                // listening \"uncaughtException\" events (as domains does).\n                // Continue in next event to avoid tick recursion.\n                if (domain) {\n                    domain.exit();\n                }\n                setTimeout(flush, 0);\n                if (domain) {\n                    domain.enter();\n                }\n\n                throw e;\n\n            } else {\n                // In browsers, uncaught exceptions are not fatal.\n                // Re-throw them asynchronously to avoid slow-downs.\n                setTimeout(function () {\n                    throw e;\n                }, 0);\n            }\n        }\n\n        if (domain) {\n            domain.exit();\n        }\n    }\n\n    nextTick = function (task) {\n        tail = tail.next = {\n            task: task,\n            domain: isNodeJS && process.domain,\n            next: null\n        };\n\n        if (!flushing) {\n            flushing = true;\n            requestTick();\n        }\n    };\n\n    if (typeof process === \"object\" &&\n        process.toString() === \"[object process]\" && process.nextTick) {\n        // Ensure Q is in a real Node environment, with a `process.nextTick`.\n        // To see through fake Node environments:\n        // * Mocha test runner - exposes a `process` global without a `nextTick`\n        // * Browserify - exposes a `process.nexTick` function that uses\n        //   `setTimeout`. In this case `setImmediate` is preferred because\n        //    it is faster. Browserify's `process.toString()` yields\n        //   \"[object Object]\", while in a real Node environment\n        //   `process.nextTick()` yields \"[object process]\".\n        isNodeJS = true;\n\n        requestTick = function () {\n            process.nextTick(flush);\n        };\n\n    } else if (typeof setImmediate === \"function\") {\n        // In IE10, Node.js 0.9+, or https://github.com/NobleJS/setImmediate\n        if (typeof window !== \"undefined\") {\n            requestTick = setImmediate.bind(window, flush);\n        } else {\n            requestTick = function () {\n                setImmediate(flush);\n            };\n        }\n\n    } else if (typeof MessageChannel !== \"undefined\") {\n        // modern browsers\n        // http://www.nonblocking.io/2011/06/windownexttick.html\n        var channel = new MessageChannel();\n        // At least Safari Version 6.0.5 (8536.30.1) intermittently cannot create\n        // working message ports the first time a page loads.\n        channel.port1.onmessage = function () {\n            requestTick = requestPortTick;\n            channel.port1.onmessage = flush;\n            flush();\n        };\n        var requestPortTick = function () {\n            // Opera requires us to provide a message payload, regardless of\n            // whether we use it.\n            channel.port2.postMessage(0);\n        };\n        requestTick = function () {\n            setTimeout(flush, 0);\n            requestPortTick();\n        };\n\n    } else {\n        // old browsers\n        requestTick = function () {\n            setTimeout(flush, 0);\n        };\n    }\n    // runs a task after all other tasks have been run\n    // this is useful for unhandled rejection tracking that needs to happen\n    // after all `then`d tasks have been run.\n    nextTick.runAfter = function (task) {\n        laterQueue.push(task);\n        if (!flushing) {\n            flushing = true;\n            requestTick();\n        }\n    };\n    return nextTick;\n})();\n\n// Attempt to make generics safe in the face of downstream\n// modifications.\n// There is no situation where this is necessary.\n// If you need a security guarantee, these primordials need to be\n// deeply frozen anyway, and if you don’t need a security guarantee,\n// this is just plain paranoid.\n// However, this **might** have the nice side-effect of reducing the size of\n// the minified code by reducing x.call() to merely x()\n// See Mark Miller’s explanation of what this does.\n// http://wiki.ecmascript.org/doku.php?id=conventions:safe_meta_programming\nvar call = Function.call;\nfunction uncurryThis(f) {\n    return function () {\n        return call.apply(f, arguments);\n    };\n}\n// This is equivalent, but slower:\n// uncurryThis = Function_bind.bind(Function_bind.call);\n// http://jsperf.com/uncurrythis\n\nvar array_slice = uncurryThis(Array.prototype.slice);\n\nvar array_reduce = uncurryThis(\n    Array.prototype.reduce || function (callback, basis) {\n        var index = 0,\n            length = this.length;\n        // concerning the initial value, if one is not provided\n        if (arguments.length === 1) {\n            // seek to the first value in the array, accounting\n            // for the possibility that is is a sparse array\n            do {\n                if (index in this) {\n                    basis = this[index++];\n                    break;\n                }\n                if (++index >= length) {\n                    throw new TypeError();\n                }\n            } while (1);\n        }\n        // reduce\n        for (; index < length; index++) {\n            // account for the possibility that the array is sparse\n            if (index in this) {\n                basis = callback(basis, this[index], index);\n            }\n        }\n        return basis;\n    }\n);\n\nvar array_indexOf = uncurryThis(\n    Array.prototype.indexOf || function (value) {\n        // not a very good shim, but good enough for our one use of it\n        for (var i = 0; i < this.length; i++) {\n            if (this[i] === value) {\n                return i;\n            }\n        }\n        return -1;\n    }\n);\n\nvar array_map = uncurryThis(\n    Array.prototype.map || function (callback, thisp) {\n        var self = this;\n        var collect = [];\n        array_reduce(self, function (undefined, value, index) {\n            collect.push(callback.call(thisp, value, index, self));\n        }, void 0);\n        return collect;\n    }\n);\n\nvar object_create = Object.create || function (prototype) {\n    function Type() { }\n    Type.prototype = prototype;\n    return new Type();\n};\n\nvar object_hasOwnProperty = uncurryThis(Object.prototype.hasOwnProperty);\n\nvar object_keys = Object.keys || function (object) {\n    var keys = [];\n    for (var key in object) {\n        if (object_hasOwnProperty(object, key)) {\n            keys.push(key);\n        }\n    }\n    return keys;\n};\n\nvar object_toString = uncurryThis(Object.prototype.toString);\n\nfunction isObject(value) {\n    return value === Object(value);\n}\n\n// generator related shims\n\n// FIXME: Remove this function once ES6 generators are in SpiderMonkey.\nfunction isStopIteration(exception) {\n    return (\n        object_toString(exception) === \"[object StopIteration]\" ||\n        exception instanceof QReturnValue\n    );\n}\n\n// FIXME: Remove this helper and Q.return once ES6 generators are in\n// SpiderMonkey.\nvar QReturnValue;\nif (typeof ReturnValue !== \"undefined\") {\n    QReturnValue = ReturnValue;\n} else {\n    QReturnValue = function (value) {\n        this.value = value;\n    };\n}\n\n// long stack traces\n\nvar STACK_JUMP_SEPARATOR = \"From previous event:\";\n\nfunction makeStackTraceLong(error, promise) {\n    // If possible, transform the error stack trace by removing Node and Q\n    // cruft, then concatenating with the stack trace of `promise`. See #57.\n    if (hasStacks &&\n        promise.stack &&\n        typeof error === \"object\" &&\n        error !== null &&\n        error.stack &&\n        error.stack.indexOf(STACK_JUMP_SEPARATOR) === -1\n    ) {\n        var stacks = [];\n        for (var p = promise; !!p; p = p.source) {\n            if (p.stack) {\n                stacks.unshift(p.stack);\n            }\n        }\n        stacks.unshift(error.stack);\n\n        var concatedStacks = stacks.join(\"\\n\" + STACK_JUMP_SEPARATOR + \"\\n\");\n        error.stack = filterStackString(concatedStacks);\n    }\n}\n\nfunction filterStackString(stackString) {\n    var lines = stackString.split(\"\\n\");\n    var desiredLines = [];\n    for (var i = 0; i < lines.length; ++i) {\n        var line = lines[i];\n\n        if (!isInternalFrame(line) && !isNodeFrame(line) && line) {\n            desiredLines.push(line);\n        }\n    }\n    return desiredLines.join(\"\\n\");\n}\n\nfunction isNodeFrame(stackLine) {\n    return stackLine.indexOf(\"(module.js:\") !== -1 ||\n           stackLine.indexOf(\"(node.js:\") !== -1;\n}\n\nfunction getFileNameAndLineNumber(stackLine) {\n    // Named functions: \"at functionName (filename:lineNumber:columnNumber)\"\n    // In IE10 function name can have spaces (\"Anonymous function\") O_o\n    var attempt1 = /at .+ \\((.+):(\\d+):(?:\\d+)\\)$/.exec(stackLine);\n    if (attempt1) {\n        return [attempt1[1], Number(attempt1[2])];\n    }\n\n    // Anonymous functions: \"at filename:lineNumber:columnNumber\"\n    var attempt2 = /at ([^ ]+):(\\d+):(?:\\d+)$/.exec(stackLine);\n    if (attempt2) {\n        return [attempt2[1], Number(attempt2[2])];\n    }\n\n    // Firefox style: \"function@filename:lineNumber or @filename:lineNumber\"\n    var attempt3 = /.*@(.+):(\\d+)$/.exec(stackLine);\n    if (attempt3) {\n        return [attempt3[1], Number(attempt3[2])];\n    }\n}\n\nfunction isInternalFrame(stackLine) {\n    var fileNameAndLineNumber = getFileNameAndLineNumber(stackLine);\n\n    if (!fileNameAndLineNumber) {\n        return false;\n    }\n\n    var fileName = fileNameAndLineNumber[0];\n    var lineNumber = fileNameAndLineNumber[1];\n\n    return fileName === qFileName &&\n        lineNumber >= qStartingLine &&\n        lineNumber <= qEndingLine;\n}\n\n// discover own file name and line number range for filtering stack\n// traces\nfunction captureLine() {\n    if (!hasStacks) {\n        return;\n    }\n\n    try {\n        throw new Error();\n    } catch (e) {\n        var lines = e.stack.split(\"\\n\");\n        var firstLine = lines[0].indexOf(\"@\") > 0 ? lines[1] : lines[2];\n        var fileNameAndLineNumber = getFileNameAndLineNumber(firstLine);\n        if (!fileNameAndLineNumber) {\n            return;\n        }\n\n        qFileName = fileNameAndLineNumber[0];\n        return fileNameAndLineNumber[1];\n    }\n}\n\nfunction deprecate(callback, name, alternative) {\n    return function () {\n        if (typeof console !== \"undefined\" &&\n            typeof console.warn === \"function\") {\n            console.warn(name + \" is deprecated, use \" + alternative +\n                         \" instead.\", new Error(\"\").stack);\n        }\n        return callback.apply(callback, arguments);\n    };\n}\n\n// end of shims\n// beginning of real work\n\n/**\n * Constructs a promise for an immediate reference, passes promises through, or\n * coerces promises from different systems.\n * @param value immediate reference or promise\n */\nfunction Q(value) {\n    // If the object is already a Promise, return it directly.  This enables\n    // the resolve function to both be used to created references from objects,\n    // but to tolerably coerce non-promises to promises.\n    if (value instanceof Promise) {\n        return value;\n    }\n\n    // assimilate thenables\n    if (isPromiseAlike(value)) {\n        return coerce(value);\n    } else {\n        return fulfill(value);\n    }\n}\nQ.resolve = Q;\n\n/**\n * Performs a task in a future turn of the event loop.\n * @param {Function} task\n */\nQ.nextTick = nextTick;\n\n/**\n * Controls whether or not long stack traces will be on\n */\nQ.longStackSupport = false;\n\n// enable long stacks if Q_DEBUG is set\nif (typeof process === \"object\" && process && process.env && process.env.Q_DEBUG) {\n    Q.longStackSupport = true;\n}\n\n/**\n * Constructs a {promise, resolve, reject} object.\n *\n * `resolve` is a callback to invoke with a more resolved value for the\n * promise. To fulfill the promise, invoke `resolve` with any value that is\n * not a thenable. To reject the promise, invoke `resolve` with a rejected\n * thenable, or invoke `reject` with the reason directly. To resolve the\n * promise to another thenable, thus putting it in the same state, invoke\n * `resolve` with that other thenable.\n */\nQ.defer = defer;\nfunction defer() {\n    // if \"messages\" is an \"Array\", that indicates that the promise has not yet\n    // been resolved.  If it is \"undefined\", it has been resolved.  Each\n    // element of the messages array is itself an array of complete arguments to\n    // forward to the resolved promise.  We coerce the resolution value to a\n    // promise using the `resolve` function because it handles both fully\n    // non-thenable values and other thenables gracefully.\n    var messages = [], progressListeners = [], resolvedPromise;\n\n    var deferred = object_create(defer.prototype);\n    var promise = object_create(Promise.prototype);\n\n    promise.promiseDispatch = function (resolve, op, operands) {\n        var args = array_slice(arguments);\n        if (messages) {\n            messages.push(args);\n            if (op === \"when\" && operands[1]) { // progress operand\n                progressListeners.push(operands[1]);\n            }\n        } else {\n            Q.nextTick(function () {\n                resolvedPromise.promiseDispatch.apply(resolvedPromise, args);\n            });\n        }\n    };\n\n    // XXX deprecated\n    promise.valueOf = function () {\n        if (messages) {\n            return promise;\n        }\n        var nearerValue = nearer(resolvedPromise);\n        if (isPromise(nearerValue)) {\n            resolvedPromise = nearerValue; // shorten chain\n        }\n        return nearerValue;\n    };\n\n    promise.inspect = function () {\n        if (!resolvedPromise) {\n            return { state: \"pending\" };\n        }\n        return resolvedPromise.inspect();\n    };\n\n    if (Q.longStackSupport && hasStacks) {\n        try {\n            throw new Error();\n        } catch (e) {\n            // NOTE: don't try to use `Error.captureStackTrace` or transfer the\n            // accessor around; that causes memory leaks as per GH-111. Just\n            // reify the stack trace as a string ASAP.\n            //\n            // At the same time, cut off the first line; it's always just\n            // \"[object Promise]\\n\", as per the `toString`.\n            promise.stack = e.stack.substring(e.stack.indexOf(\"\\n\") + 1);\n        }\n    }\n\n    // NOTE: we do the checks for `resolvedPromise` in each method, instead of\n    // consolidating them into `become`, since otherwise we'd create new\n    // promises with the lines `become(whatever(value))`. See e.g. GH-252.\n\n    function become(newPromise) {\n        resolvedPromise = newPromise;\n        promise.source = newPromise;\n\n        array_reduce(messages, function (undefined, message) {\n            Q.nextTick(function () {\n                newPromise.promiseDispatch.apply(newPromise, message);\n            });\n        }, void 0);\n\n        messages = void 0;\n        progressListeners = void 0;\n    }\n\n    deferred.promise = promise;\n    deferred.resolve = function (value) {\n        if (resolvedPromise) {\n            return;\n        }\n\n        become(Q(value));\n    };\n\n    deferred.fulfill = function (value) {\n        if (resolvedPromise) {\n            return;\n        }\n\n        become(fulfill(value));\n    };\n    deferred.reject = function (reason) {\n        if (resolvedPromise) {\n            return;\n        }\n\n        become(reject(reason));\n    };\n    deferred.notify = function (progress) {\n        if (resolvedPromise) {\n            return;\n        }\n\n        array_reduce(progressListeners, function (undefined, progressListener) {\n            Q.nextTick(function () {\n                progressListener(progress);\n            });\n        }, void 0);\n    };\n\n    return deferred;\n}\n\n/**\n * Creates a Node-style callback that will resolve or reject the deferred\n * promise.\n * @returns a nodeback\n */\ndefer.prototype.makeNodeResolver = function () {\n    var self = this;\n    return function (error, value) {\n        if (error) {\n            self.reject(error);\n        } else if (arguments.length > 2) {\n            self.resolve(array_slice(arguments, 1));\n        } else {\n            self.resolve(value);\n        }\n    };\n};\n\n/**\n * @param resolver {Function} a function that returns nothing and accepts\n * the resolve, reject, and notify functions for a deferred.\n * @returns a promise that may be resolved with the given resolve and reject\n * functions, or rejected by a thrown exception in resolver\n */\nQ.Promise = promise; // ES6\nQ.promise = promise;\nfunction promise(resolver) {\n    if (typeof resolver !== \"function\") {\n        throw new TypeError(\"resolver must be a function.\");\n    }\n    var deferred = defer();\n    try {\n        resolver(deferred.resolve, deferred.reject, deferred.notify);\n    } catch (reason) {\n        deferred.reject(reason);\n    }\n    return deferred.promise;\n}\n\npromise.race = race; // ES6\npromise.all = all; // ES6\npromise.reject = reject; // ES6\npromise.resolve = Q; // ES6\n\n// XXX experimental.  This method is a way to denote that a local value is\n// serializable and should be immediately dispatched to a remote upon request,\n// instead of passing a reference.\nQ.passByCopy = function (object) {\n    //freeze(object);\n    //passByCopies.set(object, true);\n    return object;\n};\n\nPromise.prototype.passByCopy = function () {\n    //freeze(object);\n    //passByCopies.set(object, true);\n    return this;\n};\n\n/**\n * If two promises eventually fulfill to the same value, promises that value,\n * but otherwise rejects.\n * @param x {Any*}\n * @param y {Any*}\n * @returns {Any*} a promise for x and y if they are the same, but a rejection\n * otherwise.\n *\n */\nQ.join = function (x, y) {\n    return Q(x).join(y);\n};\n\nPromise.prototype.join = function (that) {\n    return Q([this, that]).spread(function (x, y) {\n        if (x === y) {\n            // TODO: \"===\" should be Object.is or equiv\n            return x;\n        } else {\n            throw new Error(\"Can't join: not the same: \" + x + \" \" + y);\n        }\n    });\n};\n\n/**\n * Returns a promise for the first of an array of promises to become settled.\n * @param answers {Array[Any*]} promises to race\n * @returns {Any*} the first promise to be settled\n */\nQ.race = race;\nfunction race(answerPs) {\n    return promise(function (resolve, reject) {\n        // Switch to this once we can assume at least ES5\n        // answerPs.forEach(function (answerP) {\n        //     Q(answerP).then(resolve, reject);\n        // });\n        // Use this in the meantime\n        for (var i = 0, len = answerPs.length; i < len; i++) {\n            Q(answerPs[i]).then(resolve, reject);\n        }\n    });\n}\n\nPromise.prototype.race = function () {\n    return this.then(Q.race);\n};\n\n/**\n * Constructs a Promise with a promise descriptor object and optional fallback\n * function.  The descriptor contains methods like when(rejected), get(name),\n * set(name, value), post(name, args), and delete(name), which all\n * return either a value, a promise for a value, or a rejection.  The fallback\n * accepts the operation name, a resolver, and any further arguments that would\n * have been forwarded to the appropriate method above had a method been\n * provided with the proper name.  The API makes no guarantees about the nature\n * of the returned object, apart from that it is usable whereever promises are\n * bought and sold.\n */\nQ.makePromise = Promise;\nfunction Promise(descriptor, fallback, inspect) {\n    if (fallback === void 0) {\n        fallback = function (op) {\n            return reject(new Error(\n                \"Promise does not support operation: \" + op\n            ));\n        };\n    }\n    if (inspect === void 0) {\n        inspect = function () {\n            return {state: \"unknown\"};\n        };\n    }\n\n    var promise = object_create(Promise.prototype);\n\n    promise.promiseDispatch = function (resolve, op, args) {\n        var result;\n        try {\n            if (descriptor[op]) {\n                result = descriptor[op].apply(promise, args);\n            } else {\n                result = fallback.call(promise, op, args);\n            }\n        } catch (exception) {\n            result = reject(exception);\n        }\n        if (resolve) {\n            resolve(result);\n        }\n    };\n\n    promise.inspect = inspect;\n\n    // XXX deprecated `valueOf` and `exception` support\n    if (inspect) {\n        var inspected = inspect();\n        if (inspected.state === \"rejected\") {\n            promise.exception = inspected.reason;\n        }\n\n        promise.valueOf = function () {\n            var inspected = inspect();\n            if (inspected.state === \"pending\" ||\n                inspected.state === \"rejected\") {\n                return promise;\n            }\n            return inspected.value;\n        };\n    }\n\n    return promise;\n}\n\nPromise.prototype.toString = function () {\n    return \"[object Promise]\";\n};\n\nPromise.prototype.then = function (fulfilled, rejected, progressed) {\n    var self = this;\n    var deferred = defer();\n    var done = false;   // ensure the untrusted promise makes at most a\n                        // single call to one of the callbacks\n\n    function _fulfilled(value) {\n        try {\n            return typeof fulfilled === \"function\" ? fulfilled(value) : value;\n        } catch (exception) {\n            return reject(exception);\n        }\n    }\n\n    function _rejected(exception) {\n        if (typeof rejected === \"function\") {\n            makeStackTraceLong(exception, self);\n            try {\n                return rejected(exception);\n            } catch (newException) {\n                return reject(newException);\n            }\n        }\n        return reject(exception);\n    }\n\n    function _progressed(value) {\n        return typeof progressed === \"function\" ? progressed(value) : value;\n    }\n\n    Q.nextTick(function () {\n        self.promiseDispatch(function (value) {\n            if (done) {\n                return;\n            }\n            done = true;\n\n            deferred.resolve(_fulfilled(value));\n        }, \"when\", [function (exception) {\n            if (done) {\n                return;\n            }\n            done = true;\n\n            deferred.resolve(_rejected(exception));\n        }]);\n    });\n\n    // Progress propagator need to be attached in the current tick.\n    self.promiseDispatch(void 0, \"when\", [void 0, function (value) {\n        var newValue;\n        var threw = false;\n        try {\n            newValue = _progressed(value);\n        } catch (e) {\n            threw = true;\n            if (Q.onerror) {\n                Q.onerror(e);\n            } else {\n                throw e;\n            }\n        }\n\n        if (!threw) {\n            deferred.notify(newValue);\n        }\n    }]);\n\n    return deferred.promise;\n};\n\nQ.tap = function (promise, callback) {\n    return Q(promise).tap(callback);\n};\n\n/**\n * Works almost like \"finally\", but not called for rejections.\n * Original resolution value is passed through callback unaffected.\n * Callback may return a promise that will be awaited for.\n * @param {Function} callback\n * @returns {Q.Promise}\n * @example\n * doSomething()\n *   .then(...)\n *   .tap(console.log)\n *   .then(...);\n */\nPromise.prototype.tap = function (callback) {\n    callback = Q(callback);\n\n    return this.then(function (value) {\n        return callback.fcall(value).thenResolve(value);\n    });\n};\n\n/**\n * Registers an observer on a promise.\n *\n * Guarantees:\n *\n * 1. that fulfilled and rejected will be called only once.\n * 2. that either the fulfilled callback or the rejected callback will be\n *    called, but not both.\n * 3. that fulfilled and rejected will not be called in this turn.\n *\n * @param value      promise or immediate reference to observe\n * @param fulfilled  function to be called with the fulfilled value\n * @param rejected   function to be called with the rejection exception\n * @param progressed function to be called on any progress notifications\n * @return promise for the return value from the invoked callback\n */\nQ.when = when;\nfunction when(value, fulfilled, rejected, progressed) {\n    return Q(value).then(fulfilled, rejected, progressed);\n}\n\nPromise.prototype.thenResolve = function (value) {\n    return this.then(function () { return value; });\n};\n\nQ.thenResolve = function (promise, value) {\n    return Q(promise).thenResolve(value);\n};\n\nPromise.prototype.thenReject = function (reason) {\n    return this.then(function () { throw reason; });\n};\n\nQ.thenReject = function (promise, reason) {\n    return Q(promise).thenReject(reason);\n};\n\n/**\n * If an object is not a promise, it is as \"near\" as possible.\n * If a promise is rejected, it is as \"near\" as possible too.\n * If it’s a fulfilled promise, the fulfillment value is nearer.\n * If it’s a deferred promise and the deferred has been resolved, the\n * resolution is \"nearer\".\n * @param object\n * @returns most resolved (nearest) form of the object\n */\n\n// XXX should we re-do this?\nQ.nearer = nearer;\nfunction nearer(value) {\n    if (isPromise(value)) {\n        var inspected = value.inspect();\n        if (inspected.state === \"fulfilled\") {\n            return inspected.value;\n        }\n    }\n    return value;\n}\n\n/**\n * @returns whether the given object is a promise.\n * Otherwise it is a fulfilled value.\n */\nQ.isPromise = isPromise;\nfunction isPromise(object) {\n    return object instanceof Promise;\n}\n\nQ.isPromiseAlike = isPromiseAlike;\nfunction isPromiseAlike(object) {\n    return isObject(object) && typeof object.then === \"function\";\n}\n\n/**\n * @returns whether the given object is a pending promise, meaning not\n * fulfilled or rejected.\n */\nQ.isPending = isPending;\nfunction isPending(object) {\n    return isPromise(object) && object.inspect().state === \"pending\";\n}\n\nPromise.prototype.isPending = function () {\n    return this.inspect().state === \"pending\";\n};\n\n/**\n * @returns whether the given object is a value or fulfilled\n * promise.\n */\nQ.isFulfilled = isFulfilled;\nfunction isFulfilled(object) {\n    return !isPromise(object) || object.inspect().state === \"fulfilled\";\n}\n\nPromise.prototype.isFulfilled = function () {\n    return this.inspect().state === \"fulfilled\";\n};\n\n/**\n * @returns whether the given object is a rejected promise.\n */\nQ.isRejected = isRejected;\nfunction isRejected(object) {\n    return isPromise(object) && object.inspect().state === \"rejected\";\n}\n\nPromise.prototype.isRejected = function () {\n    return this.inspect().state === \"rejected\";\n};\n\n//// BEGIN UNHANDLED REJECTION TRACKING\n\n// This promise library consumes exceptions thrown in handlers so they can be\n// handled by a subsequent promise.  The exceptions get added to this array when\n// they are created, and removed when they are handled.  Note that in ES6 or\n// shimmed environments, this would naturally be a `Set`.\nvar unhandledReasons = [];\nvar unhandledRejections = [];\nvar reportedUnhandledRejections = [];\nvar trackUnhandledRejections = true;\n\nfunction resetUnhandledRejections() {\n    unhandledReasons.length = 0;\n    unhandledRejections.length = 0;\n\n    if (!trackUnhandledRejections) {\n        trackUnhandledRejections = true;\n    }\n}\n\nfunction trackRejection(promise, reason) {\n    if (!trackUnhandledRejections) {\n        return;\n    }\n    if (typeof process === \"object\" && typeof process.emit === \"function\") {\n        Q.nextTick.runAfter(function () {\n            if (array_indexOf(unhandledRejections, promise) !== -1) {\n                process.emit(\"unhandledRejection\", reason, promise);\n                reportedUnhandledRejections.push(promise);\n            }\n        });\n    }\n\n    unhandledRejections.push(promise);\n    if (reason && typeof reason.stack !== \"undefined\") {\n        unhandledReasons.push(reason.stack);\n    } else {\n        unhandledReasons.push(\"(no stack) \" + reason);\n    }\n}\n\nfunction untrackRejection(promise) {\n    if (!trackUnhandledRejections) {\n        return;\n    }\n\n    var at = array_indexOf(unhandledRejections, promise);\n    if (at !== -1) {\n        if (typeof process === \"object\" && typeof process.emit === \"function\") {\n            Q.nextTick.runAfter(function () {\n                var atReport = array_indexOf(reportedUnhandledRejections, promise);\n                if (atReport !== -1) {\n                    process.emit(\"rejectionHandled\", unhandledReasons[at], promise);\n                    reportedUnhandledRejections.splice(atReport, 1);\n                }\n            });\n        }\n        unhandledRejections.splice(at, 1);\n        unhandledReasons.splice(at, 1);\n    }\n}\n\nQ.resetUnhandledRejections = resetUnhandledRejections;\n\nQ.getUnhandledReasons = function () {\n    // Make a copy so that consumers can't interfere with our internal state.\n    return unhandledReasons.slice();\n};\n\nQ.stopUnhandledRejectionTracking = function () {\n    resetUnhandledRejections();\n    trackUnhandledRejections = false;\n};\n\nresetUnhandledRejections();\n\n//// END UNHANDLED REJECTION TRACKING\n\n/**\n * Constructs a rejected promise.\n * @param reason value describing the failure\n */\nQ.reject = reject;\nfunction reject(reason) {\n    var rejection = Promise({\n        \"when\": function (rejected) {\n            // note that the error has been handled\n            if (rejected) {\n                untrackRejection(this);\n            }\n            return rejected ? rejected(reason) : this;\n        }\n    }, function fallback() {\n        return this;\n    }, function inspect() {\n        return { state: \"rejected\", reason: reason };\n    });\n\n    // Note that the reason has not been handled.\n    trackRejection(rejection, reason);\n\n    return rejection;\n}\n\n/**\n * Constructs a fulfilled promise for an immediate reference.\n * @param value immediate reference\n */\nQ.fulfill = fulfill;\nfunction fulfill(value) {\n    return Promise({\n        \"when\": function () {\n            return value;\n        },\n        \"get\": function (name) {\n            return value[name];\n        },\n        \"set\": function (name, rhs) {\n            value[name] = rhs;\n        },\n        \"delete\": function (name) {\n            delete value[name];\n        },\n        \"post\": function (name, args) {\n            // Mark Miller proposes that post with no name should apply a\n            // promised function.\n            if (name === null || name === void 0) {\n                return value.apply(void 0, args);\n            } else {\n                return value[name].apply(value, args);\n            }\n        },\n        \"apply\": function (thisp, args) {\n            return value.apply(thisp, args);\n        },\n        \"keys\": function () {\n            return object_keys(value);\n        }\n    }, void 0, function inspect() {\n        return { state: \"fulfilled\", value: value };\n    });\n}\n\n/**\n * Converts thenables to Q promises.\n * @param promise thenable promise\n * @returns a Q promise\n */\nfunction coerce(promise) {\n    var deferred = defer();\n    Q.nextTick(function () {\n        try {\n            promise.then(deferred.resolve, deferred.reject, deferred.notify);\n        } catch (exception) {\n            deferred.reject(exception);\n        }\n    });\n    return deferred.promise;\n}\n\n/**\n * Annotates an object such that it will never be\n * transferred away from this process over any promise\n * communication channel.\n * @param object\n * @returns promise a wrapping of that object that\n * additionally responds to the \"isDef\" message\n * without a rejection.\n */\nQ.master = master;\nfunction master(object) {\n    return Promise({\n        \"isDef\": function () {}\n    }, function fallback(op, args) {\n        return dispatch(object, op, args);\n    }, function () {\n        return Q(object).inspect();\n    });\n}\n\n/**\n * Spreads the values of a promised array of arguments into the\n * fulfillment callback.\n * @param fulfilled callback that receives variadic arguments from the\n * promised array\n * @param rejected callback that receives the exception if the promise\n * is rejected.\n * @returns a promise for the return value or thrown exception of\n * either callback.\n */\nQ.spread = spread;\nfunction spread(value, fulfilled, rejected) {\n    return Q(value).spread(fulfilled, rejected);\n}\n\nPromise.prototype.spread = function (fulfilled, rejected) {\n    return this.all().then(function (array) {\n        return fulfilled.apply(void 0, array);\n    }, rejected);\n};\n\n/**\n * The async function is a decorator for generator functions, turning\n * them into asynchronous generators.  Although generators are only part\n * of the newest ECMAScript 6 drafts, this code does not cause syntax\n * errors in older engines.  This code should continue to work and will\n * in fact improve over time as the language improves.\n *\n * ES6 generators are currently part of V8 version 3.19 with the\n * --harmony-generators runtime flag enabled.  SpiderMonkey has had them\n * for longer, but under an older Python-inspired form.  This function\n * works on both kinds of generators.\n *\n * Decorates a generator function such that:\n *  - it may yield promises\n *  - execution will continue when that promise is fulfilled\n *  - the value of the yield expression will be the fulfilled value\n *  - it returns a promise for the return value (when the generator\n *    stops iterating)\n *  - the decorated function returns a promise for the return value\n *    of the generator or the first rejected promise among those\n *    yielded.\n *  - if an error is thrown in the generator, it propagates through\n *    every following yield until it is caught, or until it escapes\n *    the generator function altogether, and is translated into a\n *    rejection for the promise returned by the decorated generator.\n */\nQ.async = async;\nfunction async(makeGenerator) {\n    return function () {\n        // when verb is \"send\", arg is a value\n        // when verb is \"throw\", arg is an exception\n        function continuer(verb, arg) {\n            var result;\n\n            // Until V8 3.19 / Chromium 29 is released, SpiderMonkey is the only\n            // engine that has a deployed base of browsers that support generators.\n            // However, SM's generators use the Python-inspired semantics of\n            // outdated ES6 drafts.  We would like to support ES6, but we'd also\n            // like to make it possible to use generators in deployed browsers, so\n            // we also support Python-style generators.  At some point we can remove\n            // this block.\n\n            if (typeof StopIteration === \"undefined\") {\n                // ES6 Generators\n                try {\n                    result = generator[verb](arg);\n                } catch (exception) {\n                    return reject(exception);\n                }\n                if (result.done) {\n                    return Q(result.value);\n                } else {\n                    return when(result.value, callback, errback);\n                }\n            } else {\n                // SpiderMonkey Generators\n                // FIXME: Remove this case when SM does ES6 generators.\n                try {\n                    result = generator[verb](arg);\n                } catch (exception) {\n                    if (isStopIteration(exception)) {\n                        return Q(exception.value);\n                    } else {\n                        return reject(exception);\n                    }\n                }\n                return when(result, callback, errback);\n            }\n        }\n        var generator = makeGenerator.apply(this, arguments);\n        var callback = continuer.bind(continuer, \"next\");\n        var errback = continuer.bind(continuer, \"throw\");\n        return callback();\n    };\n}\n\n/**\n * The spawn function is a small wrapper around async that immediately\n * calls the generator and also ends the promise chain, so that any\n * unhandled errors are thrown instead of forwarded to the error\n * handler. This is useful because it's extremely common to run\n * generators at the top-level to work with libraries.\n */\nQ.spawn = spawn;\nfunction spawn(makeGenerator) {\n    Q.done(Q.async(makeGenerator)());\n}\n\n// FIXME: Remove this interface once ES6 generators are in SpiderMonkey.\n/**\n * Throws a ReturnValue exception to stop an asynchronous generator.\n *\n * This interface is a stop-gap measure to support generator return\n * values in older Firefox/SpiderMonkey.  In browsers that support ES6\n * generators like Chromium 29, just use \"return\" in your generator\n * functions.\n *\n * @param value the return value for the surrounding generator\n * @throws ReturnValue exception with the value.\n * @example\n * // ES6 style\n * Q.async(function* () {\n *      var foo = yield getFooPromise();\n *      var bar = yield getBarPromise();\n *      return foo + bar;\n * })\n * // Older SpiderMonkey style\n * Q.async(function () {\n *      var foo = yield getFooPromise();\n *      var bar = yield getBarPromise();\n *      Q.return(foo + bar);\n * })\n */\nQ[\"return\"] = _return;\nfunction _return(value) {\n    throw new QReturnValue(value);\n}\n\n/**\n * The promised function decorator ensures that any promise arguments\n * are settled and passed as values (`this` is also settled and passed\n * as a value).  It will also ensure that the result of a function is\n * always a promise.\n *\n * @example\n * var add = Q.promised(function (a, b) {\n *     return a + b;\n * });\n * add(Q(a), Q(B));\n *\n * @param {function} callback The function to decorate\n * @returns {function} a function that has been decorated.\n */\nQ.promised = promised;\nfunction promised(callback) {\n    return function () {\n        return spread([this, all(arguments)], function (self, args) {\n            return callback.apply(self, args);\n        });\n    };\n}\n\n/**\n * sends a message to a value in a future turn\n * @param object* the recipient\n * @param op the name of the message operation, e.g., \"when\",\n * @param args further arguments to be forwarded to the operation\n * @returns result {Promise} a promise for the result of the operation\n */\nQ.dispatch = dispatch;\nfunction dispatch(object, op, args) {\n    return Q(object).dispatch(op, args);\n}\n\nPromise.prototype.dispatch = function (op, args) {\n    var self = this;\n    var deferred = defer();\n    Q.nextTick(function () {\n        self.promiseDispatch(deferred.resolve, op, args);\n    });\n    return deferred.promise;\n};\n\n/**\n * Gets the value of a property in a future turn.\n * @param object    promise or immediate reference for target object\n * @param name      name of property to get\n * @return promise for the property value\n */\nQ.get = function (object, key) {\n    return Q(object).dispatch(\"get\", [key]);\n};\n\nPromise.prototype.get = function (key) {\n    return this.dispatch(\"get\", [key]);\n};\n\n/**\n * Sets the value of a property in a future turn.\n * @param object    promise or immediate reference for object object\n * @param name      name of property to set\n * @param value     new value of property\n * @return promise for the return value\n */\nQ.set = function (object, key, value) {\n    return Q(object).dispatch(\"set\", [key, value]);\n};\n\nPromise.prototype.set = function (key, value) {\n    return this.dispatch(\"set\", [key, value]);\n};\n\n/**\n * Deletes a property in a future turn.\n * @param object    promise or immediate reference for target object\n * @param name      name of property to delete\n * @return promise for the return value\n */\nQ.del = // XXX legacy\nQ[\"delete\"] = function (object, key) {\n    return Q(object).dispatch(\"delete\", [key]);\n};\n\nPromise.prototype.del = // XXX legacy\nPromise.prototype[\"delete\"] = function (key) {\n    return this.dispatch(\"delete\", [key]);\n};\n\n/**\n * Invokes a method in a future turn.\n * @param object    promise or immediate reference for target object\n * @param name      name of method to invoke\n * @param value     a value to post, typically an array of\n *                  invocation arguments for promises that\n *                  are ultimately backed with `resolve` values,\n *                  as opposed to those backed with URLs\n *                  wherein the posted value can be any\n *                  JSON serializable object.\n * @return promise for the return value\n */\n// bound locally because it is used by other methods\nQ.mapply = // XXX As proposed by \"Redsandro\"\nQ.post = function (object, name, args) {\n    return Q(object).dispatch(\"post\", [name, args]);\n};\n\nPromise.prototype.mapply = // XXX As proposed by \"Redsandro\"\nPromise.prototype.post = function (name, args) {\n    return this.dispatch(\"post\", [name, args]);\n};\n\n/**\n * Invokes a method in a future turn.\n * @param object    promise or immediate reference for target object\n * @param name      name of method to invoke\n * @param ...args   array of invocation arguments\n * @return promise for the return value\n */\nQ.send = // XXX Mark Miller's proposed parlance\nQ.mcall = // XXX As proposed by \"Redsandro\"\nQ.invoke = function (object, name /*...args*/) {\n    return Q(object).dispatch(\"post\", [name, array_slice(arguments, 2)]);\n};\n\nPromise.prototype.send = // XXX Mark Miller's proposed parlance\nPromise.prototype.mcall = // XXX As proposed by \"Redsandro\"\nPromise.prototype.invoke = function (name /*...args*/) {\n    return this.dispatch(\"post\", [name, array_slice(arguments, 1)]);\n};\n\n/**\n * Applies the promised function in a future turn.\n * @param object    promise or immediate reference for target function\n * @param args      array of application arguments\n */\nQ.fapply = function (object, args) {\n    return Q(object).dispatch(\"apply\", [void 0, args]);\n};\n\nPromise.prototype.fapply = function (args) {\n    return this.dispatch(\"apply\", [void 0, args]);\n};\n\n/**\n * Calls the promised function in a future turn.\n * @param object    promise or immediate reference for target function\n * @param ...args   array of application arguments\n */\nQ[\"try\"] =\nQ.fcall = function (object /* ...args*/) {\n    return Q(object).dispatch(\"apply\", [void 0, array_slice(arguments, 1)]);\n};\n\nPromise.prototype.fcall = function (/*...args*/) {\n    return this.dispatch(\"apply\", [void 0, array_slice(arguments)]);\n};\n\n/**\n * Binds the promised function, transforming return values into a fulfilled\n * promise and thrown errors into a rejected one.\n * @param object    promise or immediate reference for target function\n * @param ...args   array of application arguments\n */\nQ.fbind = function (object /*...args*/) {\n    var promise = Q(object);\n    var args = array_slice(arguments, 1);\n    return function fbound() {\n        return promise.dispatch(\"apply\", [\n            this,\n            args.concat(array_slice(arguments))\n        ]);\n    };\n};\nPromise.prototype.fbind = function (/*...args*/) {\n    var promise = this;\n    var args = array_slice(arguments);\n    return function fbound() {\n        return promise.dispatch(\"apply\", [\n            this,\n            args.concat(array_slice(arguments))\n        ]);\n    };\n};\n\n/**\n * Requests the names of the owned properties of a promised\n * object in a future turn.\n * @param object    promise or immediate reference for target object\n * @return promise for the keys of the eventually settled object\n */\nQ.keys = function (object) {\n    return Q(object).dispatch(\"keys\", []);\n};\n\nPromise.prototype.keys = function () {\n    return this.dispatch(\"keys\", []);\n};\n\n/**\n * Turns an array of promises into a promise for an array.  If any of\n * the promises gets rejected, the whole array is rejected immediately.\n * @param {Array*} an array (or promise for an array) of values (or\n * promises for values)\n * @returns a promise for an array of the corresponding values\n */\n// By Mark Miller\n// http://wiki.ecmascript.org/doku.php?id=strawman:concurrency&rev=1308776521#allfulfilled\nQ.all = all;\nfunction all(promises) {\n    return when(promises, function (promises) {\n        var pendingCount = 0;\n        var deferred = defer();\n        array_reduce(promises, function (undefined, promise, index) {\n            var snapshot;\n            if (\n                isPromise(promise) &&\n                (snapshot = promise.inspect()).state === \"fulfilled\"\n            ) {\n                promises[index] = snapshot.value;\n            } else {\n                ++pendingCount;\n                when(\n                    promise,\n                    function (value) {\n                        promises[index] = value;\n                        if (--pendingCount === 0) {\n                            deferred.resolve(promises);\n                        }\n                    },\n                    deferred.reject,\n                    function (progress) {\n                        deferred.notify({ index: index, value: progress });\n                    }\n                );\n            }\n        }, void 0);\n        if (pendingCount === 0) {\n            deferred.resolve(promises);\n        }\n        return deferred.promise;\n    });\n}\n\nPromise.prototype.all = function () {\n    return all(this);\n};\n\n/**\n * Returns the first resolved promise of an array. Prior rejected promises are\n * ignored.  Rejects only if all promises are rejected.\n * @param {Array*} an array containing values or promises for values\n * @returns a promise fulfilled with the value of the first resolved promise,\n * or a rejected promise if all promises are rejected.\n */\nQ.any = any;\n\nfunction any(promises) {\n    if (promises.length === 0) {\n        return Q.resolve();\n    }\n\n    var deferred = Q.defer();\n    var pendingCount = 0;\n    array_reduce(promises, function (prev, current, index) {\n        var promise = promises[index];\n\n        pendingCount++;\n\n        when(promise, onFulfilled, onRejected, onProgress);\n        function onFulfilled(result) {\n            deferred.resolve(result);\n        }\n        function onRejected() {\n            pendingCount--;\n            if (pendingCount === 0) {\n                deferred.reject(new Error(\n                    \"Can't get fulfillment value from any promise, all \" +\n                    \"promises were rejected.\"\n                ));\n            }\n        }\n        function onProgress(progress) {\n            deferred.notify({\n                index: index,\n                value: progress\n            });\n        }\n    }, undefined);\n\n    return deferred.promise;\n}\n\nPromise.prototype.any = function () {\n    return any(this);\n};\n\n/**\n * Waits for all promises to be settled, either fulfilled or\n * rejected.  This is distinct from `all` since that would stop\n * waiting at the first rejection.  The promise returned by\n * `allResolved` will never be rejected.\n * @param promises a promise for an array (or an array) of promises\n * (or values)\n * @return a promise for an array of promises\n */\nQ.allResolved = deprecate(allResolved, \"allResolved\", \"allSettled\");\nfunction allResolved(promises) {\n    return when(promises, function (promises) {\n        promises = array_map(promises, Q);\n        return when(all(array_map(promises, function (promise) {\n            return when(promise, noop, noop);\n        })), function () {\n            return promises;\n        });\n    });\n}\n\nPromise.prototype.allResolved = function () {\n    return allResolved(this);\n};\n\n/**\n * @see Promise#allSettled\n */\nQ.allSettled = allSettled;\nfunction allSettled(promises) {\n    return Q(promises).allSettled();\n}\n\n/**\n * Turns an array of promises into a promise for an array of their states (as\n * returned by `inspect`) when they have all settled.\n * @param {Array[Any*]} values an array (or promise for an array) of values (or\n * promises for values)\n * @returns {Array[State]} an array of states for the respective values.\n */\nPromise.prototype.allSettled = function () {\n    return this.then(function (promises) {\n        return all(array_map(promises, function (promise) {\n            promise = Q(promise);\n            function regardless() {\n                return promise.inspect();\n            }\n            return promise.then(regardless, regardless);\n        }));\n    });\n};\n\n/**\n * Captures the failure of a promise, giving an oportunity to recover\n * with a callback.  If the given promise is fulfilled, the returned\n * promise is fulfilled.\n * @param {Any*} promise for something\n * @param {Function} callback to fulfill the returned promise if the\n * given promise is rejected\n * @returns a promise for the return value of the callback\n */\nQ.fail = // XXX legacy\nQ[\"catch\"] = function (object, rejected) {\n    return Q(object).then(void 0, rejected);\n};\n\nPromise.prototype.fail = // XXX legacy\nPromise.prototype[\"catch\"] = function (rejected) {\n    return this.then(void 0, rejected);\n};\n\n/**\n * Attaches a listener that can respond to progress notifications from a\n * promise's originating deferred. This listener receives the exact arguments\n * passed to ``deferred.notify``.\n * @param {Any*} promise for something\n * @param {Function} callback to receive any progress notifications\n * @returns the given promise, unchanged\n */\nQ.progress = progress;\nfunction progress(object, progressed) {\n    return Q(object).then(void 0, void 0, progressed);\n}\n\nPromise.prototype.progress = function (progressed) {\n    return this.then(void 0, void 0, progressed);\n};\n\n/**\n * Provides an opportunity to observe the settling of a promise,\n * regardless of whether the promise is fulfilled or rejected.  Forwards\n * the resolution to the returned promise when the callback is done.\n * The callback can return a promise to defer completion.\n * @param {Any*} promise\n * @param {Function} callback to observe the resolution of the given\n * promise, takes no arguments.\n * @returns a promise for the resolution of the given promise when\n * ``fin`` is done.\n */\nQ.fin = // XXX legacy\nQ[\"finally\"] = function (object, callback) {\n    return Q(object)[\"finally\"](callback);\n};\n\nPromise.prototype.fin = // XXX legacy\nPromise.prototype[\"finally\"] = function (callback) {\n    callback = Q(callback);\n    return this.then(function (value) {\n        return callback.fcall().then(function () {\n            return value;\n        });\n    }, function (reason) {\n        // TODO attempt to recycle the rejection with \"this\".\n        return callback.fcall().then(function () {\n            throw reason;\n        });\n    });\n};\n\n/**\n * Terminates a chain of promises, forcing rejections to be\n * thrown as exceptions.\n * @param {Any*} promise at the end of a chain of promises\n * @returns nothing\n */\nQ.done = function (object, fulfilled, rejected, progress) {\n    return Q(object).done(fulfilled, rejected, progress);\n};\n\nPromise.prototype.done = function (fulfilled, rejected, progress) {\n    var onUnhandledError = function (error) {\n        // forward to a future turn so that ``when``\n        // does not catch it and turn it into a rejection.\n        Q.nextTick(function () {\n            makeStackTraceLong(error, promise);\n            if (Q.onerror) {\n                Q.onerror(error);\n            } else {\n                throw error;\n            }\n        });\n    };\n\n    // Avoid unnecessary `nextTick`ing via an unnecessary `when`.\n    var promise = fulfilled || rejected || progress ?\n        this.then(fulfilled, rejected, progress) :\n        this;\n\n    if (typeof process === \"object\" && process && process.domain) {\n        onUnhandledError = process.domain.bind(onUnhandledError);\n    }\n\n    promise.then(void 0, onUnhandledError);\n};\n\n/**\n * Causes a promise to be rejected if it does not get fulfilled before\n * some milliseconds time out.\n * @param {Any*} promise\n * @param {Number} milliseconds timeout\n * @param {Any*} custom error message or Error object (optional)\n * @returns a promise for the resolution of the given promise if it is\n * fulfilled before the timeout, otherwise rejected.\n */\nQ.timeout = function (object, ms, error) {\n    return Q(object).timeout(ms, error);\n};\n\nPromise.prototype.timeout = function (ms, error) {\n    var deferred = defer();\n    var timeoutId = setTimeout(function () {\n        if (!error || \"string\" === typeof error) {\n            error = new Error(error || \"Timed out after \" + ms + \" ms\");\n            error.code = \"ETIMEDOUT\";\n        }\n        deferred.reject(error);\n    }, ms);\n\n    this.then(function (value) {\n        clearTimeout(timeoutId);\n        deferred.resolve(value);\n    }, function (exception) {\n        clearTimeout(timeoutId);\n        deferred.reject(exception);\n    }, deferred.notify);\n\n    return deferred.promise;\n};\n\n/**\n * Returns a promise for the given value (or promised value), some\n * milliseconds after it resolved. Passes rejections immediately.\n * @param {Any*} promise\n * @param {Number} milliseconds\n * @returns a promise for the resolution of the given promise after milliseconds\n * time has elapsed since the resolution of the given promise.\n * If the given promise rejects, that is passed immediately.\n */\nQ.delay = function (object, timeout) {\n    if (timeout === void 0) {\n        timeout = object;\n        object = void 0;\n    }\n    return Q(object).delay(timeout);\n};\n\nPromise.prototype.delay = function (timeout) {\n    return this.then(function (value) {\n        var deferred = defer();\n        setTimeout(function () {\n            deferred.resolve(value);\n        }, timeout);\n        return deferred.promise;\n    });\n};\n\n/**\n * Passes a continuation to a Node function, which is called with the given\n * arguments provided as an array, and returns a promise.\n *\n *      Q.nfapply(FS.readFile, [__filename])\n *      .then(function (content) {\n *      })\n *\n */\nQ.nfapply = function (callback, args) {\n    return Q(callback).nfapply(args);\n};\n\nPromise.prototype.nfapply = function (args) {\n    var deferred = defer();\n    var nodeArgs = array_slice(args);\n    nodeArgs.push(deferred.makeNodeResolver());\n    this.fapply(nodeArgs).fail(deferred.reject);\n    return deferred.promise;\n};\n\n/**\n * Passes a continuation to a Node function, which is called with the given\n * arguments provided individually, and returns a promise.\n * @example\n * Q.nfcall(FS.readFile, __filename)\n * .then(function (content) {\n * })\n *\n */\nQ.nfcall = function (callback /*...args*/) {\n    var args = array_slice(arguments, 1);\n    return Q(callback).nfapply(args);\n};\n\nPromise.prototype.nfcall = function (/*...args*/) {\n    var nodeArgs = array_slice(arguments);\n    var deferred = defer();\n    nodeArgs.push(deferred.makeNodeResolver());\n    this.fapply(nodeArgs).fail(deferred.reject);\n    return deferred.promise;\n};\n\n/**\n * Wraps a NodeJS continuation passing function and returns an equivalent\n * version that returns a promise.\n * @example\n * Q.nfbind(FS.readFile, __filename)(\"utf-8\")\n * .then(console.log)\n * .done()\n */\nQ.nfbind =\nQ.denodeify = function (callback /*...args*/) {\n    var baseArgs = array_slice(arguments, 1);\n    return function () {\n        var nodeArgs = baseArgs.concat(array_slice(arguments));\n        var deferred = defer();\n        nodeArgs.push(deferred.makeNodeResolver());\n        Q(callback).fapply(nodeArgs).fail(deferred.reject);\n        return deferred.promise;\n    };\n};\n\nPromise.prototype.nfbind =\nPromise.prototype.denodeify = function (/*...args*/) {\n    var args = array_slice(arguments);\n    args.unshift(this);\n    return Q.denodeify.apply(void 0, args);\n};\n\nQ.nbind = function (callback, thisp /*...args*/) {\n    var baseArgs = array_slice(arguments, 2);\n    return function () {\n        var nodeArgs = baseArgs.concat(array_slice(arguments));\n        var deferred = defer();\n        nodeArgs.push(deferred.makeNodeResolver());\n        function bound() {\n            return callback.apply(thisp, arguments);\n        }\n        Q(bound).fapply(nodeArgs).fail(deferred.reject);\n        return deferred.promise;\n    };\n};\n\nPromise.prototype.nbind = function (/*thisp, ...args*/) {\n    var args = array_slice(arguments, 0);\n    args.unshift(this);\n    return Q.nbind.apply(void 0, args);\n};\n\n/**\n * Calls a method of a Node-style object that accepts a Node-style\n * callback with a given array of arguments, plus a provided callback.\n * @param object an object that has the named method\n * @param {String} name name of the method of object\n * @param {Array} args arguments to pass to the method; the callback\n * will be provided by Q and appended to these arguments.\n * @returns a promise for the value or error\n */\nQ.nmapply = // XXX As proposed by \"Redsandro\"\nQ.npost = function (object, name, args) {\n    return Q(object).npost(name, args);\n};\n\nPromise.prototype.nmapply = // XXX As proposed by \"Redsandro\"\nPromise.prototype.npost = function (name, args) {\n    var nodeArgs = array_slice(args || []);\n    var deferred = defer();\n    nodeArgs.push(deferred.makeNodeResolver());\n    this.dispatch(\"post\", [name, nodeArgs]).fail(deferred.reject);\n    return deferred.promise;\n};\n\n/**\n * Calls a method of a Node-style object that accepts a Node-style\n * callback, forwarding the given variadic arguments, plus a provided\n * callback argument.\n * @param object an object that has the named method\n * @param {String} name name of the method of object\n * @param ...args arguments to pass to the method; the callback will\n * be provided by Q and appended to these arguments.\n * @returns a promise for the value or error\n */\nQ.nsend = // XXX Based on Mark Miller's proposed \"send\"\nQ.nmcall = // XXX Based on \"Redsandro's\" proposal\nQ.ninvoke = function (object, name /*...args*/) {\n    var nodeArgs = array_slice(arguments, 2);\n    var deferred = defer();\n    nodeArgs.push(deferred.makeNodeResolver());\n    Q(object).dispatch(\"post\", [name, nodeArgs]).fail(deferred.reject);\n    return deferred.promise;\n};\n\nPromise.prototype.nsend = // XXX Based on Mark Miller's proposed \"send\"\nPromise.prototype.nmcall = // XXX Based on \"Redsandro's\" proposal\nPromise.prototype.ninvoke = function (name /*...args*/) {\n    var nodeArgs = array_slice(arguments, 1);\n    var deferred = defer();\n    nodeArgs.push(deferred.makeNodeResolver());\n    this.dispatch(\"post\", [name, nodeArgs]).fail(deferred.reject);\n    return deferred.promise;\n};\n\n/**\n * If a function would like to support both Node continuation-passing-style and\n * promise-returning-style, it can end its internal promise chain with\n * `nodeify(nodeback)`, forwarding the optional nodeback argument.  If the user\n * elects to use a nodeback, the result will be sent there.  If they do not\n * pass a nodeback, they will receive the result promise.\n * @param object a result (or a promise for a result)\n * @param {Function} nodeback a Node.js-style callback\n * @returns either the promise or nothing\n */\nQ.nodeify = nodeify;\nfunction nodeify(object, nodeback) {\n    return Q(object).nodeify(nodeback);\n}\n\nPromise.prototype.nodeify = function (nodeback) {\n    if (nodeback) {\n        this.then(function (value) {\n            Q.nextTick(function () {\n                nodeback(null, value);\n            });\n        }, function (error) {\n            Q.nextTick(function () {\n                nodeback(error);\n            });\n        });\n    } else {\n        return this;\n    }\n};\n\nQ.noConflict = function() {\n    throw new Error(\"Q.noConflict only works when Q is used as a global\");\n};\n\n// All code before this point will be filtered from stack traces.\nvar qEndingLine = captureLine();\n\nreturn Q;\n\n});\n\n}).call(this,require('_process'))\n\n},{\"_process\":12}],158:[function(require,module,exports){\n/**\n * Root reference for iframes.\n */\n\nvar root;\nif (typeof window !== 'undefined') { // Browser window\n  root = window;\n} else if (typeof self !== 'undefined') { // Web Worker\n  root = self;\n} else { // Other environments\n  console.warn(\"Using browser-only version of superagent in non-browser environment\");\n  root = this;\n}\n\nvar Emitter = require('emitter');\nvar requestBase = require('./request-base');\nvar isObject = require('./is-object');\n\n/**\n * Noop.\n */\n\nfunction noop(){};\n\n/**\n * Expose `request`.\n */\n\nvar request = module.exports = require('./request').bind(null, Request);\n\n/**\n * Determine XHR.\n */\n\nrequest.getXHR = function () {\n  if (root.XMLHttpRequest\n      && (!root.location || 'file:' != root.location.protocol\n          || !root.ActiveXObject)) {\n    return new XMLHttpRequest;\n  } else {\n    try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {}\n    try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {}\n    try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {}\n    try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {}\n  }\n  throw Error(\"Browser-only verison of superagent could not find XHR\");\n};\n\n/**\n * Removes leading and trailing whitespace, added to support IE.\n *\n * @param {String} s\n * @return {String}\n * @api private\n */\n\nvar trim = ''.trim\n  ? function(s) { return s.trim(); }\n  : function(s) { return s.replace(/(^\\s*|\\s*$)/g, ''); };\n\n/**\n * Serialize the given `obj`.\n *\n * @param {Object} obj\n * @return {String}\n * @api private\n */\n\nfunction serialize(obj) {\n  if (!isObject(obj)) return obj;\n  var pairs = [];\n  for (var key in obj) {\n    pushEncodedKeyValuePair(pairs, key, obj[key]);\n  }\n  return pairs.join('&');\n}\n\n/**\n * Helps 'serialize' with serializing arrays.\n * Mutates the pairs array.\n *\n * @param {Array} pairs\n * @param {String} key\n * @param {Mixed} val\n */\n\nfunction pushEncodedKeyValuePair(pairs, key, val) {\n  if (val != null) {\n    if (Array.isArray(val)) {\n      val.forEach(function(v) {\n        pushEncodedKeyValuePair(pairs, key, v);\n      });\n    } else if (isObject(val)) {\n      for(var subkey in val) {\n        pushEncodedKeyValuePair(pairs, key + '[' + subkey + ']', val[subkey]);\n      }\n    } else {\n      pairs.push(encodeURIComponent(key)\n        + '=' + encodeURIComponent(val));\n    }\n  } else if (val === null) {\n    pairs.push(encodeURIComponent(key));\n  }\n}\n\n/**\n * Expose serialization method.\n */\n\n request.serializeObject = serialize;\n\n /**\n  * Parse the given x-www-form-urlencoded `str`.\n  *\n  * @param {String} str\n  * @return {Object}\n  * @api private\n  */\n\nfunction parseString(str) {\n  var obj = {};\n  var pairs = str.split('&');\n  var pair;\n  var pos;\n\n  for (var i = 0, len = pairs.length; i < len; ++i) {\n    pair = pairs[i];\n    pos = pair.indexOf('=');\n    if (pos == -1) {\n      obj[decodeURIComponent(pair)] = '';\n    } else {\n      obj[decodeURIComponent(pair.slice(0, pos))] =\n        decodeURIComponent(pair.slice(pos + 1));\n    }\n  }\n\n  return obj;\n}\n\n/**\n * Expose parser.\n */\n\nrequest.parseString = parseString;\n\n/**\n * Default MIME type map.\n *\n *     superagent.types.xml = 'application/xml';\n *\n */\n\nrequest.types = {\n  html: 'text/html',\n  json: 'application/json',\n  xml: 'application/xml',\n  urlencoded: 'application/x-www-form-urlencoded',\n  'form': 'application/x-www-form-urlencoded',\n  'form-data': 'application/x-www-form-urlencoded'\n};\n\n/**\n * Default serialization map.\n *\n *     superagent.serialize['application/xml'] = function(obj){\n *       return 'generated xml here';\n *     };\n *\n */\n\n request.serialize = {\n   'application/x-www-form-urlencoded': serialize,\n   'application/json': JSON.stringify\n };\n\n /**\n  * Default parsers.\n  *\n  *     superagent.parse['application/xml'] = function(str){\n  *       return { object parsed from str };\n  *     };\n  *\n  */\n\nrequest.parse = {\n  'application/x-www-form-urlencoded': parseString,\n  'application/json': JSON.parse\n};\n\n/**\n * Parse the given header `str` into\n * an object containing the mapped fields.\n *\n * @param {String} str\n * @return {Object}\n * @api private\n */\n\nfunction parseHeader(str) {\n  var lines = str.split(/\\r?\\n/);\n  var fields = {};\n  var index;\n  var line;\n  var field;\n  var val;\n\n  lines.pop(); // trailing CRLF\n\n  for (var i = 0, len = lines.length; i < len; ++i) {\n    line = lines[i];\n    index = line.indexOf(':');\n    field = line.slice(0, index).toLowerCase();\n    val = trim(line.slice(index + 1));\n    fields[field] = val;\n  }\n\n  return fields;\n}\n\n/**\n * Check if `mime` is json or has +json structured syntax suffix.\n *\n * @param {String} mime\n * @return {Boolean}\n * @api private\n */\n\nfunction isJSON(mime) {\n  return /[\\/+]json\\b/.test(mime);\n}\n\n/**\n * Return the mime type for the given `str`.\n *\n * @param {String} str\n * @return {String}\n * @api private\n */\n\nfunction type(str){\n  return str.split(/ *; */).shift();\n};\n\n/**\n * Return header field parameters.\n *\n * @param {String} str\n * @return {Object}\n * @api private\n */\n\nfunction params(str){\n  return str.split(/ *; */).reduce(function(obj, str){\n    var parts = str.split(/ *= */),\n        key = parts.shift(),\n        val = parts.shift();\n\n    if (key && val) obj[key] = val;\n    return obj;\n  }, {});\n};\n\n/**\n * Initialize a new `Response` with the given `xhr`.\n *\n *  - set flags (.ok, .error, etc)\n *  - parse header\n *\n * Examples:\n *\n *  Aliasing `superagent` as `request` is nice:\n *\n *      request = superagent;\n *\n *  We can use the promise-like API, or pass callbacks:\n *\n *      request.get('/').end(function(res){});\n *      request.get('/', function(res){});\n *\n *  Sending data can be chained:\n *\n *      request\n *        .post('/user')\n *        .send({ name: 'tj' })\n *        .end(function(res){});\n *\n *  Or passed to `.send()`:\n *\n *      request\n *        .post('/user')\n *        .send({ name: 'tj' }, function(res){});\n *\n *  Or passed to `.post()`:\n *\n *      request\n *        .post('/user', { name: 'tj' })\n *        .end(function(res){});\n *\n * Or further reduced to a single call for simple cases:\n *\n *      request\n *        .post('/user', { name: 'tj' }, function(res){});\n *\n * @param {XMLHTTPRequest} xhr\n * @param {Object} options\n * @api private\n */\n\nfunction Response(req, options) {\n  options = options || {};\n  this.req = req;\n  this.xhr = this.req.xhr;\n  // responseText is accessible only if responseType is '' or 'text' and on older browsers\n  this.text = ((this.req.method !='HEAD' && (this.xhr.responseType === '' || this.xhr.responseType === 'text')) || typeof this.xhr.responseType === 'undefined')\n     ? this.xhr.responseText\n     : null;\n  this.statusText = this.req.xhr.statusText;\n  this._setStatusProperties(this.xhr.status);\n  this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders());\n  // getAllResponseHeaders sometimes falsely returns \"\" for CORS requests, but\n  // getResponseHeader still works. so we get content-type even if getting\n  // other headers fails.\n  this.header['content-type'] = this.xhr.getResponseHeader('content-type');\n  this._setHeaderProperties(this.header);\n  this.body = this.req.method != 'HEAD'\n    ? this._parseBody(this.text ? this.text : this.xhr.response)\n    : null;\n}\n\n/**\n * Get case-insensitive `field` value.\n *\n * @param {String} field\n * @return {String}\n * @api public\n */\n\nResponse.prototype.get = function(field){\n  return this.header[field.toLowerCase()];\n};\n\n/**\n * Set header related properties:\n *\n *   - `.type` the content type without params\n *\n * A response of \"Content-Type: text/plain; charset=utf-8\"\n * will provide you with a `.type` of \"text/plain\".\n *\n * @param {Object} header\n * @api private\n */\n\nResponse.prototype._setHeaderProperties = function(header){\n  // content-type\n  var ct = this.header['content-type'] || '';\n  this.type = type(ct);\n\n  // params\n  var obj = params(ct);\n  for (var key in obj) this[key] = obj[key];\n};\n\n/**\n * Parse the given body `str`.\n *\n * Used for auto-parsing of bodies. Parsers\n * are defined on the `superagent.parse` object.\n *\n * @param {String} str\n * @return {Mixed}\n * @api private\n */\n\nResponse.prototype._parseBody = function(str){\n  var parse = request.parse[this.type];\n  if (!parse && isJSON(this.type)) {\n    parse = request.parse['application/json'];\n  }\n  return parse && str && (str.length || str instanceof Object)\n    ? parse(str)\n    : null;\n};\n\n/**\n * Set flags such as `.ok` based on `status`.\n *\n * For example a 2xx response will give you a `.ok` of __true__\n * whereas 5xx will be __false__ and `.error` will be __true__. The\n * `.clientError` and `.serverError` are also available to be more\n * specific, and `.statusType` is the class of error ranging from 1..5\n * sometimes useful for mapping respond colors etc.\n *\n * \"sugar\" properties are also defined for common cases. Currently providing:\n *\n *   - .noContent\n *   - .badRequest\n *   - .unauthorized\n *   - .notAcceptable\n *   - .notFound\n *\n * @param {Number} status\n * @api private\n */\n\nResponse.prototype._setStatusProperties = function(status){\n  // handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request\n  if (status === 1223) {\n    status = 204;\n  }\n\n  var type = status / 100 | 0;\n\n  // status / class\n  this.status = this.statusCode = status;\n  this.statusType = type;\n\n  // basics\n  this.info = 1 == type;\n  this.ok = 2 == type;\n  this.clientError = 4 == type;\n  this.serverError = 5 == type;\n  this.error = (4 == type || 5 == type)\n    ? this.toError()\n    : false;\n\n  // sugar\n  this.accepted = 202 == status;\n  this.noContent = 204 == status;\n  this.badRequest = 400 == status;\n  this.unauthorized = 401 == status;\n  this.notAcceptable = 406 == status;\n  this.notFound = 404 == status;\n  this.forbidden = 403 == status;\n};\n\n/**\n * Return an `Error` representative of this response.\n *\n * @return {Error}\n * @api public\n */\n\nResponse.prototype.toError = function(){\n  var req = this.req;\n  var method = req.method;\n  var url = req.url;\n\n  var msg = 'cannot ' + method + ' ' + url + ' (' + this.status + ')';\n  var err = new Error(msg);\n  err.status = this.status;\n  err.method = method;\n  err.url = url;\n\n  return err;\n};\n\n/**\n * Expose `Response`.\n */\n\nrequest.Response = Response;\n\n/**\n * Initialize a new `Request` with the given `method` and `url`.\n *\n * @param {String} method\n * @param {String} url\n * @api public\n */\n\nfunction Request(method, url) {\n  var self = this;\n  this._query = this._query || [];\n  this.method = method;\n  this.url = url;\n  this.header = {}; // preserves header name case\n  this._header = {}; // coerces header names to lowercase\n  this.on('end', function(){\n    var err = null;\n    var res = null;\n\n    try {\n      res = new Response(self);\n    } catch(e) {\n      err = new Error('Parser is unable to parse the response');\n      err.parse = true;\n      err.original = e;\n      // issue #675: return the raw response if the response parsing fails\n      err.rawResponse = self.xhr && self.xhr.responseText ? self.xhr.responseText : null;\n      // issue #876: return the http status code if the response parsing fails\n      err.statusCode = self.xhr && self.xhr.status ? self.xhr.status : null;\n      return self.callback(err);\n    }\n\n    self.emit('response', res);\n\n    var new_err;\n    try {\n      if (res.status < 200 || res.status >= 300) {\n        new_err = new Error(res.statusText || 'Unsuccessful HTTP response');\n        new_err.original = err;\n        new_err.response = res;\n        new_err.status = res.status;\n      }\n    } catch(e) {\n      new_err = e; // #985 touching res may cause INVALID_STATE_ERR on old Android\n    }\n\n    // #1000 don't catch errors from the callback to avoid double calling it\n    if (new_err) {\n      self.callback(new_err, res);\n    } else {\n      self.callback(null, res);\n    }\n  });\n}\n\n/**\n * Mixin `Emitter` and `requestBase`.\n */\n\nEmitter(Request.prototype);\nfor (var key in requestBase) {\n  Request.prototype[key] = requestBase[key];\n}\n\n/**\n * Set Content-Type to `type`, mapping values from `request.types`.\n *\n * Examples:\n *\n *      superagent.types.xml = 'application/xml';\n *\n *      request.post('/')\n *        .type('xml')\n *        .send(xmlstring)\n *        .end(callback);\n *\n *      request.post('/')\n *        .type('application/xml')\n *        .send(xmlstring)\n *        .end(callback);\n *\n * @param {String} type\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.type = function(type){\n  this.set('Content-Type', request.types[type] || type);\n  return this;\n};\n\n/**\n * Set responseType to `val`. Presently valid responseTypes are 'blob' and\n * 'arraybuffer'.\n *\n * Examples:\n *\n *      req.get('/')\n *        .responseType('blob')\n *        .end(callback);\n *\n * @param {String} val\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.responseType = function(val){\n  this._responseType = val;\n  return this;\n};\n\n/**\n * Set Accept to `type`, mapping values from `request.types`.\n *\n * Examples:\n *\n *      superagent.types.json = 'application/json';\n *\n *      request.get('/agent')\n *        .accept('json')\n *        .end(callback);\n *\n *      request.get('/agent')\n *        .accept('application/json')\n *        .end(callback);\n *\n * @param {String} accept\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.accept = function(type){\n  this.set('Accept', request.types[type] || type);\n  return this;\n};\n\n/**\n * Set Authorization field value with `user` and `pass`.\n *\n * @param {String} user\n * @param {String} pass\n * @param {Object} options with 'type' property 'auto' or 'basic' (default 'basic')\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.auth = function(user, pass, options){\n  if (!options) {\n    options = {\n      type: 'basic'\n    }\n  }\n\n  switch (options.type) {\n    case 'basic':\n      var str = btoa(user + ':' + pass);\n      this.set('Authorization', 'Basic ' + str);\n    break;\n\n    case 'auto':\n      this.username = user;\n      this.password = pass;\n    break;\n  }\n  return this;\n};\n\n/**\n* Add query-string `val`.\n*\n* Examples:\n*\n*   request.get('/shoes')\n*     .query('size=10')\n*     .query({ color: 'blue' })\n*\n* @param {Object|String} val\n* @return {Request} for chaining\n* @api public\n*/\n\nRequest.prototype.query = function(val){\n  if ('string' != typeof val) val = serialize(val);\n  if (val) this._query.push(val);\n  return this;\n};\n\n/**\n * Queue the given `file` as an attachment to the specified `field`,\n * with optional `filename`.\n *\n * ``` js\n * request.post('/upload')\n *   .attach('content', new Blob(['<a id=\"a\"><b id=\"b\">hey!</b></a>'], { type: \"text/html\"}))\n *   .end(callback);\n * ```\n *\n * @param {String} field\n * @param {Blob|File} file\n * @param {String} filename\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.attach = function(field, file, filename){\n  this._getFormData().append(field, file, filename || file.name);\n  return this;\n};\n\nRequest.prototype._getFormData = function(){\n  if (!this._formData) {\n    this._formData = new root.FormData();\n  }\n  return this._formData;\n};\n\n/**\n * Invoke the callback with `err` and `res`\n * and handle arity check.\n *\n * @param {Error} err\n * @param {Response} res\n * @api private\n */\n\nRequest.prototype.callback = function(err, res){\n  var fn = this._callback;\n  this.clearTimeout();\n  fn(err, res);\n};\n\n/**\n * Invoke callback with x-domain error.\n *\n * @api private\n */\n\nRequest.prototype.crossDomainError = function(){\n  var err = new Error('Request has been terminated\\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.');\n  err.crossDomain = true;\n\n  err.status = this.status;\n  err.method = this.method;\n  err.url = this.url;\n\n  this.callback(err);\n};\n\n/**\n * Invoke callback with timeout error.\n *\n * @api private\n */\n\nRequest.prototype._timeoutError = function(){\n  var timeout = this._timeout;\n  var err = new Error('timeout of ' + timeout + 'ms exceeded');\n  err.timeout = timeout;\n  this.callback(err);\n};\n\n/**\n * Compose querystring to append to req.url\n *\n * @api private\n */\n\nRequest.prototype._appendQueryString = function(){\n  var query = this._query.join('&');\n  if (query) {\n    this.url += ~this.url.indexOf('?')\n      ? '&' + query\n      : '?' + query;\n  }\n};\n\n/**\n * Initiate request, invoking callback `fn(res)`\n * with an instanceof `Response`.\n *\n * @param {Function} fn\n * @return {Request} for chaining\n * @api public\n */\n\nRequest.prototype.end = function(fn){\n  var self = this;\n  var xhr = this.xhr = request.getXHR();\n  var timeout = this._timeout;\n  var data = this._formData || this._data;\n\n  // store callback\n  this._callback = fn || noop;\n\n  // state change\n  xhr.onreadystatechange = function(){\n    if (4 != xhr.readyState) return;\n\n    // In IE9, reads to any property (e.g. status) off of an aborted XHR will\n    // result in the error \"Could not complete the operation due to error c00c023f\"\n    var status;\n    try { status = xhr.status } catch(e) { status = 0; }\n\n    if (0 == status) {\n      if (self.timedout) return self._timeoutError();\n      if (self._aborted) return;\n      return self.crossDomainError();\n    }\n    self.emit('end');\n  };\n\n  // progress\n  var handleProgress = function(e){\n    if (e.total > 0) {\n      e.percent = e.loaded / e.total * 100;\n    }\n    e.direction = 'download';\n    self.emit('progress', e);\n  };\n  if (this.hasListeners('progress')) {\n    xhr.onprogress = handleProgress;\n  }\n  try {\n    if (xhr.upload && this.hasListeners('progress')) {\n      xhr.upload.onprogress = handleProgress;\n    }\n  } catch(e) {\n    // Accessing xhr.upload fails in IE from a controller worker, so just pretend it doesn't exist.\n    // Reported here:\n    // https://connect.microsoft.com/IE/feedback/details/837245/xmlhttprequest-upload-throws-invalid-argument-when-used-from-web-worker-context\n  }\n\n  // timeout\n  if (timeout && !this._timer) {\n    this._timer = setTimeout(function(){\n      self.timedout = true;\n      self.abort();\n    }, timeout);\n  }\n\n  // querystring\n  this._appendQueryString();\n\n  // initiate request\n  if (this.username && this.password) {\n    xhr.open(this.method, this.url, true, this.username, this.password);\n  } else {\n    xhr.open(this.method, this.url, true);\n  }\n\n  // CORS\n  if (this._withCredentials) xhr.withCredentials = true;\n\n  // body\n  if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !this._isHost(data)) {\n    // serialize stuff\n    var contentType = this._header['content-type'];\n    var serialize = this._serializer || request.serialize[contentType ? contentType.split(';')[0] : ''];\n    if (!serialize && isJSON(contentType)) serialize = request.serialize['application/json'];\n    if (serialize) data = serialize(data);\n  }\n\n  // set header fields\n  for (var field in this.header) {\n    if (null == this.header[field]) continue;\n    xhr.setRequestHeader(field, this.header[field]);\n  }\n\n  if (this._responseType) {\n    xhr.responseType = this._responseType;\n  }\n\n  // send stuff\n  this.emit('request', this);\n\n  // IE11 xhr.send(undefined) sends 'undefined' string as POST payload (instead of nothing)\n  // We need null here if data is undefined\n  xhr.send(typeof data !== 'undefined' ? data : null);\n  return this;\n};\n\n\n/**\n * Expose `Request`.\n */\n\nrequest.Request = Request;\n\n/**\n * GET `url` with optional callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed|Function} [data] or fn\n * @param {Function} [fn]\n * @return {Request}\n * @api public\n */\n\nrequest.get = function(url, data, fn){\n  var req = request('GET', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.query(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * HEAD `url` with optional callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed|Function} [data] or fn\n * @param {Function} [fn]\n * @return {Request}\n * @api public\n */\n\nrequest.head = function(url, data, fn){\n  var req = request('HEAD', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.send(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * OPTIONS query to `url` with optional callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed|Function} [data] or fn\n * @param {Function} [fn]\n * @return {Request}\n * @api public\n */\n\nrequest.options = function(url, data, fn){\n  var req = request('OPTIONS', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.send(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * DELETE `url` with optional callback `fn(res)`.\n *\n * @param {String} url\n * @param {Function} [fn]\n * @return {Request}\n * @api public\n */\n\nfunction del(url, fn){\n  var req = request('DELETE', url);\n  if (fn) req.end(fn);\n  return req;\n};\n\nrequest['del'] = del;\nrequest['delete'] = del;\n\n/**\n * PATCH `url` with optional `data` and callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed} [data]\n * @param {Function} [fn]\n * @return {Request}\n * @api public\n */\n\nrequest.patch = function(url, data, fn){\n  var req = request('PATCH', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.send(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * POST `url` with optional `data` and callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed} [data]\n * @param {Function} [fn]\n * @return {Request}\n * @api public\n */\n\nrequest.post = function(url, data, fn){\n  var req = request('POST', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.send(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n/**\n * PUT `url` with optional `data` and callback `fn(res)`.\n *\n * @param {String} url\n * @param {Mixed|Function} [data] or fn\n * @param {Function} [fn]\n * @return {Request}\n * @api public\n */\n\nrequest.put = function(url, data, fn){\n  var req = request('PUT', url);\n  if ('function' == typeof data) fn = data, data = null;\n  if (data) req.send(data);\n  if (fn) req.end(fn);\n  return req;\n};\n\n},{\"./is-object\":159,\"./request\":161,\"./request-base\":160,\"emitter\":162}],159:[function(require,module,exports){\n/**\n * Check if `obj` is an object.\n *\n * @param {Object} obj\n * @return {Boolean}\n * @api private\n */\n\nfunction isObject(obj) {\n  return null !== obj && 'object' === typeof obj;\n}\n\nmodule.exports = isObject;\n\n},{}],160:[function(require,module,exports){\n/**\n * Module of mixed-in functions shared between node and client code\n */\nvar isObject = require('./is-object');\n\n/**\n * Clear previous timeout.\n *\n * @return {Request} for chaining\n * @api public\n */\n\nexports.clearTimeout = function _clearTimeout(){\n  this._timeout = 0;\n  clearTimeout(this._timer);\n  return this;\n};\n\n/**\n * Override default response body parser\n *\n * This function will be called to convert incoming data into request.body\n *\n * @param {Function}\n * @api public\n */\n\nexports.parse = function parse(fn){\n  this._parser = fn;\n  return this;\n};\n\n/**\n * Override default request body serializer\n *\n * This function will be called to convert data set via .send or .attach into payload to send\n *\n * @param {Function}\n * @api public\n */\n\nexports.serialize = function serialize(fn){\n  this._serializer = fn;\n  return this;\n};\n\n/**\n * Set timeout to `ms`.\n *\n * @param {Number} ms\n * @return {Request} for chaining\n * @api public\n */\n\nexports.timeout = function timeout(ms){\n  this._timeout = ms;\n  return this;\n};\n\n/**\n * Promise support\n *\n * @param {Function} resolve\n * @param {Function} reject\n * @return {Request}\n */\n\nexports.then = function then(resolve, reject) {\n  if (!this._fullfilledPromise) {\n    var self = this;\n    this._fullfilledPromise = new Promise(function(innerResolve, innerReject){\n      self.end(function(err, res){\n        if (err) innerReject(err); else innerResolve(res);\n      });\n    });\n  }\n  return this._fullfilledPromise.then(resolve, reject);\n}\n\n/**\n * Allow for extension\n */\n\nexports.use = function use(fn) {\n  fn(this);\n  return this;\n}\n\n\n/**\n * Get request header `field`.\n * Case-insensitive.\n *\n * @param {String} field\n * @return {String}\n * @api public\n */\n\nexports.get = function(field){\n  return this._header[field.toLowerCase()];\n};\n\n/**\n * Get case-insensitive header `field` value.\n * This is a deprecated internal API. Use `.get(field)` instead.\n *\n * (getHeader is no longer used internally by the superagent code base)\n *\n * @param {String} field\n * @return {String}\n * @api private\n * @deprecated\n */\n\nexports.getHeader = exports.get;\n\n/**\n * Set header `field` to `val`, or multiple fields with one object.\n * Case-insensitive.\n *\n * Examples:\n *\n *      req.get('/')\n *        .set('Accept', 'application/json')\n *        .set('X-API-Key', 'foobar')\n *        .end(callback);\n *\n *      req.get('/')\n *        .set({ Accept: 'application/json', 'X-API-Key': 'foobar' })\n *        .end(callback);\n *\n * @param {String|Object} field\n * @param {String} val\n * @return {Request} for chaining\n * @api public\n */\n\nexports.set = function(field, val){\n  if (isObject(field)) {\n    for (var key in field) {\n      this.set(key, field[key]);\n    }\n    return this;\n  }\n  this._header[field.toLowerCase()] = val;\n  this.header[field] = val;\n  return this;\n};\n\n/**\n * Remove header `field`.\n * Case-insensitive.\n *\n * Example:\n *\n *      req.get('/')\n *        .unset('User-Agent')\n *        .end(callback);\n *\n * @param {String} field\n */\nexports.unset = function(field){\n  delete this._header[field.toLowerCase()];\n  delete this.header[field];\n  return this;\n};\n\n/**\n * Write the field `name` and `val` for \"multipart/form-data\"\n * request bodies.\n *\n * ``` js\n * request.post('/upload')\n *   .field('foo', 'bar')\n *   .end(callback);\n * ```\n *\n * @param {String} name\n * @param {String|Blob|File|Buffer|fs.ReadStream} val\n * @return {Request} for chaining\n * @api public\n */\nexports.field = function(name, val) {\n  this._getFormData().append(name, val);\n  return this;\n};\n\n/**\n * Abort the request, and clear potential timeout.\n *\n * @return {Request}\n * @api public\n */\nexports.abort = function(){\n  if (this._aborted) {\n    return this;\n  }\n  this._aborted = true;\n  this.xhr && this.xhr.abort(); // browser\n  this.req && this.req.abort(); // node\n  this.clearTimeout();\n  this.emit('abort');\n  return this;\n};\n\n/**\n * Enable transmission of cookies with x-domain requests.\n *\n * Note that for this to work the origin must not be\n * using \"Access-Control-Allow-Origin\" with a wildcard,\n * and also must set \"Access-Control-Allow-Credentials\"\n * to \"true\".\n *\n * @api public\n */\n\nexports.withCredentials = function(){\n  // This is browser-only functionality. Node side is no-op.\n  this._withCredentials = true;\n  return this;\n};\n\n/**\n * Set the max redirects to `n`. Does noting in browser XHR implementation.\n *\n * @param {Number} n\n * @return {Request} for chaining\n * @api public\n */\n\nexports.redirects = function(n){\n  this._maxRedirects = n;\n  return this;\n};\n\n/**\n * Convert to a plain javascript object (not JSON string) of scalar properties.\n * Note as this method is designed to return a useful non-this value,\n * it cannot be chained.\n *\n * @return {Object} describing method, url, and data of this request\n * @api public\n */\n\nexports.toJSON = function(){\n  return {\n    method: this.method,\n    url: this.url,\n    data: this._data,\n    headers: this._header\n  };\n};\n\n/**\n * Check if `obj` is a host object,\n * we don't want to serialize these :)\n *\n * TODO: future proof, move to compoent land\n *\n * @param {Object} obj\n * @return {Boolean}\n * @api private\n */\n\nexports._isHost = function _isHost(obj) {\n  var str = {}.toString.call(obj);\n\n  switch (str) {\n    case '[object File]':\n    case '[object Blob]':\n    case '[object FormData]':\n      return true;\n    default:\n      return false;\n  }\n}\n\n/**\n * Send `data` as the request body, defaulting the `.type()` to \"json\" when\n * an object is given.\n *\n * Examples:\n *\n *       // manual json\n *       request.post('/user')\n *         .type('json')\n *         .send('{\"name\":\"tj\"}')\n *         .end(callback)\n *\n *       // auto json\n *       request.post('/user')\n *         .send({ name: 'tj' })\n *         .end(callback)\n *\n *       // manual x-www-form-urlencoded\n *       request.post('/user')\n *         .type('form')\n *         .send('name=tj')\n *         .end(callback)\n *\n *       // auto x-www-form-urlencoded\n *       request.post('/user')\n *         .type('form')\n *         .send({ name: 'tj' })\n *         .end(callback)\n *\n *       // defaults to x-www-form-urlencoded\n *      request.post('/user')\n *        .send('name=tobi')\n *        .send('species=ferret')\n *        .end(callback)\n *\n * @param {String|Object} data\n * @return {Request} for chaining\n * @api public\n */\n\nexports.send = function(data){\n  var obj = isObject(data);\n  var type = this._header['content-type'];\n\n  // merge\n  if (obj && isObject(this._data)) {\n    for (var key in data) {\n      this._data[key] = data[key];\n    }\n  } else if ('string' == typeof data) {\n    // default to x-www-form-urlencoded\n    if (!type) this.type('form');\n    type = this._header['content-type'];\n    if ('application/x-www-form-urlencoded' == type) {\n      this._data = this._data\n        ? this._data + '&' + data\n        : data;\n    } else {\n      this._data = (this._data || '') + data;\n    }\n  } else {\n    this._data = data;\n  }\n\n  if (!obj || this._isHost(data)) return this;\n\n  // default to json\n  if (!type) this.type('json');\n  return this;\n};\n\n},{\"./is-object\":159}],161:[function(require,module,exports){\n// The node and browser modules expose versions of this with the\n// appropriate constructor function bound as first argument\n/**\n * Issue a request:\n *\n * Examples:\n *\n *    request('GET', '/users').end(callback)\n *    request('/users').end(callback)\n *    request('/users', callback)\n *\n * @param {String} method\n * @param {String|Function} url or callback\n * @return {Request}\n * @api public\n */\n\nfunction request(RequestConstructor, method, url) {\n  // callback\n  if ('function' == typeof url) {\n    return new RequestConstructor('GET', method).end(url);\n  }\n\n  // url first\n  if (2 == arguments.length) {\n    return new RequestConstructor('GET', method);\n  }\n\n  return new RequestConstructor(method, url);\n}\n\nmodule.exports = request;\n\n},{}],162:[function(require,module,exports){\n\n/**\n * Expose `Emitter`.\n */\n\nif (typeof module !== 'undefined') {\n  module.exports = Emitter;\n}\n\n/**\n * Initialize a new `Emitter`.\n *\n * @api public\n */\n\nfunction Emitter(obj) {\n  if (obj) return mixin(obj);\n};\n\n/**\n * Mixin the emitter properties.\n *\n * @param {Object} obj\n * @return {Object}\n * @api private\n */\n\nfunction mixin(obj) {\n  for (var key in Emitter.prototype) {\n    obj[key] = Emitter.prototype[key];\n  }\n  return obj;\n}\n\n/**\n * Listen on the given `event` with `fn`.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.on =\nEmitter.prototype.addEventListener = function(event, fn){\n  this._callbacks = this._callbacks || {};\n  (this._callbacks['$' + event] = this._callbacks['$' + event] || [])\n    .push(fn);\n  return this;\n};\n\n/**\n * Adds an `event` listener that will be invoked a single\n * time then automatically removed.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.once = function(event, fn){\n  function on() {\n    this.off(event, on);\n    fn.apply(this, arguments);\n  }\n\n  on.fn = fn;\n  this.on(event, on);\n  return this;\n};\n\n/**\n * Remove the given callback for `event` or all\n * registered callbacks.\n *\n * @param {String} event\n * @param {Function} fn\n * @return {Emitter}\n * @api public\n */\n\nEmitter.prototype.off =\nEmitter.prototype.removeListener =\nEmitter.prototype.removeAllListeners =\nEmitter.prototype.removeEventListener = function(event, fn){\n  this._callbacks = this._callbacks || {};\n\n  // all\n  if (0 == arguments.length) {\n    this._callbacks = {};\n    return this;\n  }\n\n  // specific event\n  var callbacks = this._callbacks['$' + event];\n  if (!callbacks) return this;\n\n  // remove all handlers\n  if (1 == arguments.length) {\n    delete this._callbacks['$' + event];\n    return this;\n  }\n\n  // remove specific handler\n  var cb;\n  for (var i = 0; i < callbacks.length; i++) {\n    cb = callbacks[i];\n    if (cb === fn || cb.fn === fn) {\n      callbacks.splice(i, 1);\n      break;\n    }\n  }\n  return this;\n};\n\n/**\n * Emit `event` with the given args.\n *\n * @param {String} event\n * @param {Mixed} ...\n * @return {Emitter}\n */\n\nEmitter.prototype.emit = function(event){\n  this._callbacks = this._callbacks || {};\n  var args = [].slice.call(arguments, 1)\n    , callbacks = this._callbacks['$' + event];\n\n  if (callbacks) {\n    callbacks = callbacks.slice(0);\n    for (var i = 0, len = callbacks.length; i < len; ++i) {\n      callbacks[i].apply(this, args);\n    }\n  }\n\n  return this;\n};\n\n/**\n * Return array of callbacks for `event`.\n *\n * @param {String} event\n * @return {Array}\n * @api public\n */\n\nEmitter.prototype.listeners = function(event){\n  this._callbacks = this._callbacks || {};\n  return this._callbacks['$' + event] || [];\n};\n\n/**\n * Check if this emitter has `event` handlers.\n *\n * @param {String} event\n * @return {Boolean}\n * @api public\n */\n\nEmitter.prototype.hasListeners = function(event){\n  return !! this.listeners(event).length;\n};\n\n},{}]},{},[1])(1)\n});\n\n\n /*global JSONEditor*/\n'use strict';\n\nwindow.SwaggerUi = Backbone.Router.extend({\n\n  dom_id: 'swagger_ui',\n\n  // Attributes\n  options: null,\n  api: null,\n  headerView: null,\n  mainView: null,\n\n  // SwaggerUi accepts all the same options as SwaggerApi\n  initialize: function(options) {\n    options = options || {};\n\n    if (options.defaultModelRendering !== 'model') {\n      options.defaultModelRendering = 'schema';\n    }\n\n    if (!options.highlightSizeThreshold) {\n      options.highlightSizeThreshold = 100000;\n    }\n\n    // Allow dom_id to be overridden\n    if (options.dom_id) {\n      this.dom_id = options.dom_id;\n      delete options.dom_id;\n    }\n\n    if (!options.supportedSubmitMethods){\n      options.supportedSubmitMethods = [\n        'get',\n        'put',\n        'post',\n        'delete',\n        'head',\n        'options',\n        'patch'\n      ];\n    }\n\n    if (typeof options.oauth2RedirectUrl === 'string') {\n      window.oAuthRedirectUrl = options.oauth2RedirectUrl;\n    }\n\n    // Create an empty div which contains the dom_id\n    if (! $('#' + this.dom_id).length){\n      $('body').append('<div id=\"' + this.dom_id + '\"></div>') ;\n    }\n\n    this.options = options;\n\n    // set marked options\n    marked.setOptions({gfm: true});\n\n    // Set the callbacks\n    var that = this;\n    this.options.success = function() { return that.render(); };\n    this.options.progress = function(d) { return that.showMessage(d); };\n    this.options.failure = function(d) { return that.onLoadFailure(d); };\n\n    // Create view to handle the header inputs\n    this.headerView = new SwaggerUi.Views.HeaderView({el: $('#header')});\n\n    // Event handler for when the baseUrl/apiKey is entered by user\n    this.headerView.on('update-swagger-ui', function(data) {\n      return that.updateSwaggerUi(data);\n    });\n\n    // JSon Editor custom theming\n     JSONEditor.defaults.iconlibs.swagger = JSONEditor.AbstractIconLib.extend({\n      mapping: {\n        collapse: 'collapse',\n        expand: 'expand'\n        },\n      icon_prefix: 'swagger-'\n      });\n\n  },\n\n  // Set an option after initializing\n  setOption: function(option, value) {\n    this.options[option] = value;\n  },\n\n  // Get the value of a previously set option\n  getOption: function(option) {\n    return this.options[option];\n  },\n\n  // Event handler for when url/key is received from user\n  updateSwaggerUi: function(data){\n    this.options.url = data.url;\n    this.load();\n  },\n\n  // Create an api and render\n  load: function(){\n    // Initialize the API object\n    if (this.mainView) {\n      this.mainView.clear();\n    }\n\n    if (this.authView) {\n      this.authView.remove();\n    }\n    var url = this.options.url;\n    if (url && url.indexOf('http') !== 0) {\n      url = this.buildUrl(window.location.href.toString(), url);\n    }\n    if(this.api) {\n      this.options.authorizations = this.api.clientAuthorizations.authz;\n    }\n    this.options.url = url;\n    this.headerView.update(url);\n\n    this.api = new SwaggerClient(this.options);\n  },\n\n  // collapse all sections\n  collapseAll: function(){\n    Docs.collapseEndpointListForResource('');\n  },\n\n  // list operations for all sections\n  listAll: function(){\n    Docs.collapseOperationsForResource('');\n  },\n\n  // expand operations for all sections\n  expandAll: function(){\n    Docs.expandOperationsForResource('');\n  },\n\n  // This is bound to success handler for SwaggerApi\n  //  so it gets called when SwaggerApi completes loading\n  render: function(){\n    var authsModel;\n    this.showMessage('Finished Loading Resource Information. Rendering Swagger UI...');\n    this.mainView = new SwaggerUi.Views.MainView({\n      model: this.api,\n      el: $('#' + this.dom_id),\n      swaggerOptions: this.options,\n      router: this\n    }).render();\n    if (!_.isEmpty(this.api.securityDefinitions)){\n      authsModel = _.map(this.api.securityDefinitions, function (auth, name) {\n        var result = {};\n        result[name] = auth;\n        return result;\n      });\n      this.authView = new SwaggerUi.Views.AuthButtonView({\n        data: SwaggerUi.utils.parseSecurityDefinitions(authsModel),\n        router: this\n      });\n      $('#auth_container').append(this.authView.render().el);\n    }\n    this.showMessage();\n    switch (this.options.docExpansion) {\n      case 'full':\n        this.expandAll(); break;\n      case 'list':\n        this.listAll(); break;\n      default:\n        break;\n    }\n    this.renderGFM();\n\n    if (this.options.onComplete){\n      this.options.onComplete(this.api, this);\n    }\n\n    setTimeout(Docs.shebang.bind(this), 100);\n  },\n\n  buildUrl: function(base, url){\n    if (url.indexOf('/') === 0) {\n      var parts = base.split('/');\n      base = parts[0] + '//' + parts[2];\n      return base + url;\n    } else {\n      var endOfPath = base.length;\n\n      if (base.indexOf('?') > -1){\n        endOfPath = Math.min(endOfPath, base.indexOf('?'));\n      }\n\n      if (base.indexOf('#') > -1){\n        endOfPath = Math.min(endOfPath, base.indexOf('#'));\n      }\n\n      base = base.substring(0, endOfPath);\n\n      if (base.indexOf('/', base.length - 1 ) !== -1){\n        return base + url;\n      }\n\n      return base + '/' + url;\n    }\n  },\n\n  // Shows message on topbar of the ui\n  showMessage: function(data){\n    if (data === undefined) {\n      data = '';\n    }\n    var $msgbar = $('#message-bar');\n    $msgbar.removeClass('message-fail');\n    $msgbar.addClass('message-success');\n    $msgbar.text(data);\n    if(window.SwaggerTranslator) {\n      window.SwaggerTranslator.translate($msgbar);\n    }\n  },\n\n  // shows message in red\n  onLoadFailure: function(data){\n    if (data === undefined) {\n      data = '';\n    }\n    $('#message-bar').removeClass('message-success');\n    $('#message-bar').addClass('message-fail');\n\n    var val = $('#message-bar').text(data);\n\n    if (this.options.onFailure) {\n      this.options.onFailure(data);\n    }\n\n    return val;\n  },\n\n  // Renders GFM for elements with 'markdown' class\n  renderGFM: function(){\n    $('.markdown').each(function(){\n      $(this).html(marked($(this).html()));\n    });\n\n    $('.propDesc', '.model-signature .description').each(function () {\n      $(this).html(marked($(this).html())).addClass('markdown');\n    });\n  }\n\n});\n\nwindow.SwaggerUi.Views = {};\nwindow.SwaggerUi.Models = {};\nwindow.SwaggerUi.Collections = {};\nwindow.SwaggerUi.partials = {};\nwindow.SwaggerUi.utils = {};\n\n// don't break backward compatibility with previous versions and warn users to upgrade their code\n(function(){\n  window.authorizations = {\n    add: function() {\n      warn('Using window.authorizations is deprecated. Please use SwaggerUi.api.clientAuthorizations.add().');\n\n      if (typeof window.swaggerUi === 'undefined') {\n        throw new TypeError('window.swaggerUi is not defined');\n      }\n\n      if (window.swaggerUi instanceof SwaggerUi) {\n        window.swaggerUi.api.clientAuthorizations.add.apply(window.swaggerUi.api.clientAuthorizations, arguments);\n      }\n    }\n  };\n\n  window.ApiKeyAuthorization = function() {\n    warn('window.ApiKeyAuthorization is deprecated. Please use SwaggerClient.ApiKeyAuthorization.');\n    SwaggerClient.ApiKeyAuthorization.apply(window, arguments);\n  };\n\n  window.PasswordAuthorization = function() {\n    warn('window.PasswordAuthorization is deprecated. Please use SwaggerClient.PasswordAuthorization.');\n    SwaggerClient.PasswordAuthorization.apply(window, arguments);\n  };\n\n  function warn(message) {\n    if ('console' in window && typeof window.console.warn === 'function') {\n      console.warn(message);\n    }\n  }\n})();\n\n\n// UMD\n(function (root, factory) {\n    if (typeof define === 'function' && define.amd) {\n        // AMD. Register as an anonymous module.\n        define(['b'], function (b) {\n            return (root.SwaggerUi = factory(b));\n        });\n    } else if (typeof exports === 'object') {\n        // Node. Does not work with strict CommonJS, but\n        // only CommonJS-like environments that support module.exports,\n        // like Node.\n        module.exports = factory(require('b'));\n    } else {\n        // Browser globals\n        root.SwaggerUi = factory(root.b);\n    }\n}(this, function () {\n    return SwaggerUi;\n}));\n\n'use strict';\n\nwindow.SwaggerUi.utils = {\n    parseSecurityDefinitions: function (security, securityDefinitions) {\n        var auths = Object.assign({}, securityDefinitions);\n        var oauth2Arr = [];\n        var authsArr = [];\n        var scopes = [];\n        var utils = window.SwaggerUi.utils;\n\n        if (!Array.isArray(security)) { return null; }\n\n        security.forEach(function (item) {\n            var singleSecurity = {};\n            var singleOauth2Security = {};\n\n            for (var key in item) {\n                if (Array.isArray(item[key])) {\n                    if (!auths[key]) { continue; }\n                    auths[key] = auths[key] || {};\n                    if (auths[key].type === 'oauth2') {\n                        singleOauth2Security[key] = Object.assign({}, auths[key]);\n                        singleOauth2Security[key].scopes = Object.assign({}, auths[key].scopes);\n                        for (var i in singleOauth2Security[key].scopes) {\n                            if (item[key].indexOf(i) < 0) {\n                                delete singleOauth2Security[key].scopes[i];\n                            }\n                        }\n                        singleOauth2Security[key].scopes = utils.parseOauth2Scopes(singleOauth2Security[key].scopes);\n                        scopes = _.merge(scopes, singleOauth2Security[key].scopes);\n                    } else {\n                        singleSecurity[key] = Object.assign({}, auths[key]);\n                    }\n                } else {\n                    if (item[key].type === 'oauth2') {\n                        singleOauth2Security[key] = Object.assign({}, item[key]);\n                        singleOauth2Security[key].scopes = utils.parseOauth2Scopes(singleOauth2Security[key].scopes);\n                        scopes = _.merge(scopes, singleOauth2Security[key].scopes);\n                    } else {\n                        singleSecurity[key] = item[key];\n                    }\n                }\n            }\n\n            if (!_.isEmpty(singleSecurity)) {\n                authsArr.push(singleSecurity);\n            }\n\n            if (!_.isEmpty(singleOauth2Security)){\n                oauth2Arr.push(singleOauth2Security);\n            }\n        });\n\n        return {\n            auths : authsArr,\n            oauth2: oauth2Arr,\n            scopes: scopes\n        };\n    },\n\n    parseOauth2Scopes: function (data) {\n        var scopes = Object.assign({}, data);\n        var result = [];\n        var key;\n\n        for (key in scopes) {\n            result.push({scope: key, description: scopes[key]});\n        }\n\n        return result;\n    },\n\n    sanitize: function(html) {\n        // Strip the script tags from the html and inline evenhandlers\n        html = html.replace(/<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi, '');\n        html = html.replace(/(on\\w+=\"[^\"]*\")*(on\\w+='[^']*')*(on\\w+=\\w*\\(\\w*\\))*/gi, '');\n\n        return html;\n    }\n};\n'use strict';\n\nSwaggerUi.Models.ApiKeyAuthModel = Backbone.Model.extend({\n    defaults: {\n        'in': '',\n        name: '',\n        title: '',\n        value: ''\n    },\n\n    initialize: function () {\n        this.on('change', this.validate);\n    },\n\n    validate: function () {\n        var valid = !!this.get('value');\n\n        this.set('valid', valid);\n\n        return valid;\n    }\n});\n'use strict';\n\nSwaggerUi.Views.ApiKeyAuthView = Backbone.View.extend({ // TODO: append this to global SwaggerUi\n\n    events: {\n        'change .input_apiKey_entry': 'apiKeyChange'\n    },\n\n    selectors: {\n        apikeyInput: '.input_apiKey_entry'\n    },\n\n    template: Handlebars.templates.apikey_auth,\n\n    initialize: function(opts) {\n        this.options = opts || {};\n        this.router = this.options.router;\n    },\n\n    render: function (){\n        this.$el.html(this.template(this.model.toJSON()));\n\n        return this;\n    },\n\n    apiKeyChange: function (e) {\n        var val = $(e.target).val();\n        if (val) {\n            this.$(this.selectors.apikeyInput).removeClass('error');\n        }\n\n        this.model.set('value', val);\n    },\n\n    isValid: function () {\n        return this.model.validate();\n    },\n\n    highlightInvalid: function () {\n        if (!this.isValid()) {\n            this.$(this.selectors.apikeyInput).addClass('error');\n        }\n    }\n\n});\n'use strict';\n\nSwaggerUi.Views.AuthButtonView = Backbone.View.extend({\n    events: {\n        'click .authorize__btn': 'authorizeBtnClick'\n    },\n\n    tpls: {\n        popup: Handlebars.templates.popup,\n        authBtn: Handlebars.templates.auth_button,\n        authBtnOperation: Handlebars.templates.auth_button_operation\n    },\n\n    initialize: function(opts) {\n        this.options = opts || {};\n        this.options.data = this.options.data || {};\n        this.isOperation = this.options.isOperation;\n        this.model = this.model || {};\n        this.router = this.options.router;\n        this.auths = this.options.data.oauth2.concat(this.options.data.auths);\n    },\n\n    render: function () {\n        var tplName = this.isOperation ? 'authBtnOperation' : 'authBtn';\n\n        this.$authEl = this.renderAuths(this.auths);\n        this.$el.html(this.tpls[tplName](this.model));\n\n        return this;\n    },\n\n    authorizeBtnClick: function (e) {\n        var authsModel;\n\n        e.preventDefault();\n\n        authsModel = {\n            title: 'Available authorizations',\n            content: this.$authEl\n        };\n\n        // The content of the popup is removed and all events unbound after clicking the 'Cancel' button of the popup.\n        // We'll have to re-render the contents before creating a new popup view.\n        this.render();\n\n        this.popup = new SwaggerUi.Views.PopupView({model: authsModel});\n        this.popup.render();\n    },\n\n    renderAuths: function (auths) {\n        var $el = $('<div>');\n        var isLogout = false;\n\n        auths.forEach(function (auth) {\n            var authView = new SwaggerUi.Views.AuthView({data: auth, router: this.router});\n            var authEl = authView.render().el;\n            $el.append(authEl);\n            if (authView.isLogout) {\n                isLogout = true;\n            }\n        }, this);\n\n        this.model.isLogout = isLogout;\n\n        return $el;\n    }\n\n});\n\n'use strict';\n\nSwaggerUi.Collections.AuthsCollection = Backbone.Collection.extend({\n    constructor: function() {\n        var args = Array.prototype.slice.call(arguments);\n\n        args[0] = this.parse(args[0]);\n\n        Backbone.Collection.apply(this, args);\n    },\n\n    add: function (model) {\n        var args = Array.prototype.slice.call(arguments);\n\n        if (Array.isArray(model)) {\n            args[0] = _.map(model, function(val) {\n                return this.handleOne(val);\n            }, this);\n        } else {\n            args[0] = this.handleOne(model);\n        }\n\n        Backbone.Collection.prototype.add.apply(this, args);\n    },\n\n    handleOne: function (model) {\n        var result = model;\n\n        if (! (model instanceof Backbone.Model) ) {\n            switch (model.type) {\n                case 'oauth2':\n                    result = new SwaggerUi.Models.Oauth2Model(model);\n                    break;\n                case 'basic':\n                    result = new SwaggerUi.Models.BasicAuthModel(model);\n                    break;\n                case 'apiKey':\n                    result = new SwaggerUi.Models.ApiKeyAuthModel(model);\n                    break;\n                default:\n                    result = new Backbone.Model(model);\n            }\n        }\n\n        return result;\n    },\n\n    isValid: function () {\n        var valid = true;\n\n        this.models.forEach(function(model) {\n            if (!model.validate()) {\n                valid = false;\n            }\n        });\n\n        return valid;\n    },\n\n    isAuthorized: function () {\n        return this.length === this.where({ isLogout: true }).length;\n    },\n\n    isPartiallyAuthorized: function () {\n        return this.where({ isLogout: true }).length > 0;\n    },\n\n    parse: function (data) {\n        var authz = {};\n\n        if(typeof window.swaggerUi !== 'undefined') {\n            authz = Object.assign({}, window.swaggerUi.api.clientAuthorizations.authz);\n        }\n\n        return _.map(data, function (auth, name) {\n            var isBasic = authz[name] && auth.type === 'basic' && authz[name].username && authz[name].password;\n\n            _.extend(auth, {\n                title: name\n            });\n\n            if (authz[name] || isBasic) {\n                _.extend(auth, {\n                    isLogout: true,\n                    value: isBasic ? undefined : authz[name].value,\n                    username: isBasic ? authz[name].username : undefined,\n                    password: isBasic ? authz[name].password : undefined,\n                    valid: true\n                });\n            }\n\n            return auth;\n        });\n    }\n});\n'use strict';\n\nSwaggerUi.Views.AuthsCollectionView = Backbone.View.extend({\n\n    initialize: function(opts) {\n        this.options = opts || {};\n        this.options.data = this.options.data || {};\n        this.router = this.options.router;\n\n        this.collection = new SwaggerUi.Collections.AuthsCollection(opts.data);\n\n        this.$innerEl = $('<div>');\n        this.authViews = [];\n    },\n\n    render: function () {\n        this.collection.each(function (auth) {\n            this.renderOneAuth(auth);\n        }, this);\n\n        this.$el.html(this.$innerEl.html() ? this.$innerEl : '');\n\n        return this;\n    },\n\n    renderOneAuth: function (authModel) {\n        var authViewEl, authView, authViewName;\n        var type = authModel.get('type');\n\n        if (type === 'apiKey') {\n            authViewName = 'ApiKeyAuthView';\n        } else if (type === 'basic' && this.$innerEl.find('.basic_auth_container').length === 0) {\n            authViewName = 'BasicAuthView';\n        } else if (type === 'oauth2') {\n            authViewName = 'Oauth2View';\n        }\n\n        if (authViewName) {\n            authView = new SwaggerUi.Views[authViewName]({model: authModel, router: this.router});\n            authViewEl = authView.render().el;\n            this.authViews.push(authView);\n        }\n\n        this.$innerEl.append(authViewEl);\n    },\n\n    highlightInvalid: function () {\n        this.authViews.forEach(function (view) {\n            view.highlightInvalid();\n        }, this);\n    }\n\n});\n\n'use strict';\n\n/* global redirect_uri:true */\n/* global clientId */\n/* global scopeSeparator */\n/* global additionalQueryStringParams */\n/* global clientSecret */\n/* global onOAuthComplete */\n/* global realm */\n/*jshint unused:false*/\n\nSwaggerUi.Views.AuthView = Backbone.View.extend({\n    events: {\n        'click .auth_submit__button': 'authorizeClick',\n        'click .auth_logout__button': 'logoutClick'\n    },\n\n    tpls: {\n        main: Handlebars.templates.auth_view\n    },\n\n    selectors: {\n        innerEl: '.auth_inner',\n        authBtn: '.auth_submit__button'\n    },\n\n    initialize: function(opts) {\n        this.options = opts || {};\n        opts.data = opts.data || {};\n        this.router = this.options.router;\n\n        this.authsCollectionView = new SwaggerUi.Views.AuthsCollectionView({data: opts.data});\n\n        this.$el.html(this.tpls.main({\n            isLogout: this.authsCollectionView.collection.isAuthorized(),\n            isAuthorized: this.authsCollectionView.collection.isPartiallyAuthorized()\n        }));\n        this.$innerEl = this.$(this.selectors.innerEl);\n        this.isLogout = this.authsCollectionView.collection.isPartiallyAuthorized();\n    },\n\n    render: function () {\n        this.$innerEl.html(this.authsCollectionView.render().el);\n\n        return this;\n    },\n\n    authorizeClick: function (e) {\n        e.preventDefault();\n        e.stopPropagation();\n\n        if (this.authsCollectionView.collection.isValid()) {\n            this.authorize();\n        } else {\n            this.authsCollectionView.highlightInvalid();\n        }\n    },\n\n    authorize: function () {\n        this.authsCollectionView.collection.forEach(function (auth) {\n            var keyAuth, basicAuth;\n            var type = auth.get('type');\n\n            if (type === 'apiKey') {\n                keyAuth = new SwaggerClient.ApiKeyAuthorization(\n                    auth.get('name'),\n                    auth.get('value'),\n                    auth.get('in')\n                );\n\n                this.router.api.clientAuthorizations.add(auth.get('title'), keyAuth);\n            } else if (type === 'basic') {\n                basicAuth = new SwaggerClient.PasswordAuthorization(auth.get('username'), auth.get('password'));\n                this.router.api.clientAuthorizations.add(auth.get('title'), basicAuth);\n            } else if (type === 'oauth2') {\n                this.handleOauth2Login(auth);\n            }\n        }, this);\n\n        this.router.load();\n    },\n\n    logoutClick: function (e) {\n        e.preventDefault();\n\n        this.authsCollectionView.collection.forEach(function (auth) {\n            window.swaggerUi.api.clientAuthorizations.remove(auth.get('title'));\n        });\n\n        this.router.load();\n    },\n\n    // taken from lib/swagger-oauth.js\n    handleOauth2Login: function (auth) {\n        var host = window.location;\n        var pathname = location.pathname.substring(0, location.pathname.lastIndexOf('/'));\n        var defaultRedirectUrl = host.protocol + '//' + host.host + pathname + '/o2c.html';\n        var redirectUrl = window.oAuthRedirectUrl || defaultRedirectUrl;\n        var url = null;\n        var scopes = _.map(auth.get('scopes'), function (scope) {\n            if(scope.checked) {\n                return scope.scope;\n            }\n        });\n        var container = window.swaggerUiAuth || (window.swaggerUiAuth = {});\n        var state, dets, ep;\n        container.OAuthSchemeKey = auth.get('title');\n\n        window.enabledScopes = scopes;\n        var flow = auth.get('flow');\n\n        /**\n         * Returns the name of the access token parameter returned by the server.\n         *\n         * @param dets\n         *     The authorisation scheme configuration.\n         * @return the name of the access token parameter\n         */\n        function getTokenName(dets) {\n            return dets.vendorExtensions['x-tokenName'] || dets.tokenName;\n        }\n\n        if(auth.get('type') === 'oauth2' && flow && (flow === 'implicit' || flow === 'accessCode')) {\n            dets = auth.attributes;\n            url = dets.authorizationUrl + '?response_type=' + (flow === 'implicit' ? 'token' : 'code');\n            container.tokenName = getTokenName(dets) || 'access_token';\n            container.tokenUrl = (flow === 'accessCode' ? dets.tokenUrl : null);\n            state = container.OAuthSchemeKey;\n        }\n        else if(auth.get('type') === 'oauth2' && flow && (flow === 'application')) {\n            dets = auth.attributes;\n            container.tokenName = getTokenName(dets) || 'access_token';\n            this.clientCredentialsFlow(scopes, dets, container.OAuthSchemeKey);\n            return;\n        }\n        else if(auth.get('type') === 'oauth2' && flow && (flow === 'password')) {\n            dets = auth.attributes;\n            container.tokenName = getTokenName(dets) || 'access_token';\n            this.passwordFlow(scopes, dets, container.OAuthSchemeKey);\n            return;\n        }\n        else if(auth.get('grantTypes')) {\n            // 1.2 support\n            var o = auth.get('grantTypes');\n            for(var t in o) {\n                if(o.hasOwnProperty(t) && t === 'implicit') {\n                    dets = o[t];\n                    ep = dets.loginEndpoint.url;\n                    url = dets.loginEndpoint.url + '?response_type=token';\n                    container.tokenName = getTokenName(dets);\n                }\n                else if (o.hasOwnProperty(t) && t === 'accessCode') {\n                    dets = o[t];\n                    ep = dets.tokenRequestEndpoint.url;\n                    url = dets.tokenRequestEndpoint.url + '?response_type=code';\n                    container.tokenName = getTokenName(dets);\n                }\n            }\n        }\n\n        redirect_uri = redirectUrl;\n\n        url += '&redirect_uri=' + encodeURIComponent(redirectUrl);\n        url += '&realm=' + encodeURIComponent(realm);\n        url += '&client_id=' + encodeURIComponent(clientId);\n        url += '&scope=' + encodeURIComponent(scopes.join(scopeSeparator));\n        url += '&state=' + encodeURIComponent(state);\n        for (var key in additionalQueryStringParams) {\n            url += '&' + key + '=' + encodeURIComponent(additionalQueryStringParams[key]);\n        }\n\n        window.open(url);\n    },\n\n    // taken from lib/swagger-oauth.js\n    clientCredentialsFlow: function (scopes, oauth, OAuthSchemeKey) {\n        this.accessTokenRequest(scopes, oauth, OAuthSchemeKey, 'client_credentials');\n    },\n\n    passwordFlow: function (scopes, oauth, OAuthSchemeKey) {\n        this.accessTokenRequest(scopes, oauth, OAuthSchemeKey, 'password', {\n            'username': oauth.username,\n            'password': oauth.password\n        });\n    },\n\n    accessTokenRequest: function (scopes, oauth, OAuthSchemeKey, grantType, params) {\n        params = $.extend({}, {\n            'scope': scopes.join(' '),\n            'grant_type': grantType\n        }, params);\n\n        var headers= {};\n\n        switch (oauth.clientAuthenticationType) {\n            case 'basic':\n                headers.Authorization = 'Basic ' + btoa(oauth.clientId + ':' + oauth.clientSecret);\n                break;\n            case 'request-body':\n                params.client_id = oauth.clientId;\n                params.client_secret = oauth.clientSecret;\n                break;\n        }\n\n        $.ajax({\n            url : oauth.tokenUrl,\n            type: 'POST',\n            data: params,\n            headers: headers,\n            success: function (data)\n            {\n                onOAuthComplete(data, OAuthSchemeKey);\n            },\n            error: function ()\n            {\n                onOAuthComplete('');\n            }\n        });\n    }\n});\n\n'use strict';\n\nSwaggerUi.Models.BasicAuthModel = Backbone.Model.extend({\n    defaults: {\n        username: '',\n        password: '',\n        title: 'basic'\n    },\n\n    initialize: function () {\n        this.on('change', this.validate);\n    },\n\n    validate: function () {\n        var valid = !!this.get('password') && !!this.get('username');\n\n        this.set('valid', valid);\n\n        return valid;\n    }\n});\n'use strict';\n\nSwaggerUi.Views.BasicAuthView = Backbone.View.extend({\n\n    initialize: function (opts) {\n        this.options = opts || {};\n        this.router = this.options.router;\n    },\n\n    events: {\n        'change .auth_input': 'inputChange'\n    },\n\n    selectors: {\n        usernameInput: '.basic_auth__username',\n        passwordInput: '.basic_auth__password'\n    },\n\n    cls: {\n        error: 'error'\n    },\n\n    template: Handlebars.templates.basic_auth,\n\n    render: function(){\n        $(this.el).html(this.template(this.model.toJSON()));\n\n        return this;\n    },\n\n    inputChange: function (e) {\n        var $el = $(e.target);\n        var val = $el.val();\n        var attr = $el.prop('name');\n\n        if (val) {\n            $el.removeClass(this.cls.error);\n        }\n\n        this.model.set(attr, val);\n    },\n\n    isValid: function () {\n        return this.model.validate();\n    },\n\n    highlightInvalid: function () {\n        if (!this.model.get('username')) {\n            this.$(this.selectors.usernameInput).addClass(this.cls.error);\n        }\n    }\n});\n\n'use strict';\n\nSwaggerUi.Views.ContentTypeView = Backbone.View.extend({\n  initialize: function() {},\n\n  render: function(){\n  \tthis.model.contentTypeId = 'ct' + Math.random();\n    $(this.el).html(Handlebars.templates.content_type(this.model));\n    return this;\n  }\n});\n'use strict';\n\nSwaggerUi.Views.HeaderView = Backbone.View.extend({\n  events: {\n    'click #show-pet-store-icon'    : 'showPetStore',\n    'click #explore'                : 'showCustom',\n    'submit #api_selector'          : 'showCustom',\n    'keyup #input_baseUrl'          : 'showCustomOnKeyup',\n    'keyup #input_apiKey'           : 'showCustomOnKeyup'\n  },\n\n  initialize: function(){},\n\n  showPetStore: function(){\n    this.trigger('update-swagger-ui', {\n      url:'http://petstore.swagger.io/v2/swagger.json'\n    });\n  },\n\n  showCustomOnKeyup: function(e){\n    if (e.keyCode === 13) {\n      this.showCustom();\n    }\n  },\n\n  showCustom: function(e){\n    if (e) {\n      e.preventDefault();\n    }\n\n    this.trigger('update-swagger-ui', {\n      url: $('#input_baseUrl').val()\n    });\n  },\n\n  update: function(url, apiKey, trigger){\n    if (trigger === undefined) {\n      trigger = false;\n    }\n\n    $('#input_baseUrl').val(url);\n\n    if (trigger) {\n      this.trigger('update-swagger-ui', {url:url});\n    }\n  }\n});\n\n'use strict';\n\nSwaggerUi.Views.MainView = Backbone.View.extend({\n  apisSorter : {\n    alpha   : function(a,b){ return a.name.localeCompare(b.name); }\n  },\n  operationsSorters : {\n    alpha   : function(a,b){ return a.path.localeCompare(b.path); },\n    method  : function(a,b){ return a.method.localeCompare(b.method); }\n  },\n  initialize: function(opts){\n    var sorterOption, sorterFn, key, value;\n    opts = opts || {};\n\n    this.router = opts.router;\n\n    // Sort APIs\n    if (opts.swaggerOptions.apisSorter) {\n      sorterOption = opts.swaggerOptions.apisSorter;\n      if (_.isFunction(sorterOption)) {\n        sorterFn = sorterOption;\n      } else {\n        sorterFn = this.apisSorter[sorterOption];\n      }\n      if (_.isFunction(sorterFn)) {\n        this.model.apisArray.sort(sorterFn);\n      }\n    }\n    // Sort operations of each API\n    if (opts.swaggerOptions.operationsSorter) {\n      sorterOption = opts.swaggerOptions.operationsSorter;\n      if (_.isFunction(sorterOption)) {\n        sorterFn = sorterOption;\n      } else {\n        sorterFn = this.operationsSorters[sorterOption];\n      }\n      if (_.isFunction(sorterFn)) {\n        for (key in this.model.apisArray) {\n          this.model.apisArray[key].operationsArray.sort(sorterFn);\n        }\n      }\n    }\n\n    // set up the UI for input\n    this.model.auths = [];\n\n    for (key in this.model.securityDefinitions) {\n      value = this.model.securityDefinitions[key];\n\n      this.model.auths.push({\n        name: key,\n        type: value.type,\n        value: value\n      });\n    }\n\n    if ('validatorUrl' in opts.swaggerOptions) {\n      // Validator URL specified explicitly\n      this.model.validatorUrl = opts.swaggerOptions.validatorUrl;\n    } else if (this.model.url.indexOf('localhost') > 0 || this.model.url.indexOf('127.0.0.1') > 0) {\n      // Localhost override\n      this.model.validatorUrl = null;\n    } else {\n      this.model.validatorUrl = '//online.swagger.io/validator';\n    }\n\n    // JSonEditor requires type='object' to be present on defined types, we add it if it's missing\n    // is there any valid case were it should not be added ?\n    var def;\n    for(def in this.model.definitions){\n      if (!this.model.definitions[def].type){\n        this.model.definitions[def].type = 'object';\n      }\n    }\n\n  },\n\n  render: function () {\n    $(this.el).html(Handlebars.templates.main(this.model));\n    this.info = this.$('.info')[0];\n\n    if (this.info) {\n      this.info.addEventListener('click', this.onLinkClick, true);\n    }\n\n    this.model.securityDefinitions = this.model.securityDefinitions || {};\n\n    // Render each resource\n\n    var resources = {};\n    var counter = 0;\n    for (var i = 0; i < this.model.apisArray.length; i++) {\n      var resource = this.model.apisArray[i];\n      var id = resource.name;\n      while (typeof resources[id] !== 'undefined') {\n        id = id + '_' + counter;\n        counter += 1;\n      }\n      resource.id = sanitizeHtml(id);\n      resources[id] = resource;\n      this.addResource(resource, this.model.auths);\n    }\n\n    $('.propWrap').hover(function onHover(){\n      $('.optionsWrapper', $(this)).show();\n    }, function offhover(){\n      $('.optionsWrapper', $(this)).hide();\n    });\n    return this;\n  },\n\n  addResource: function(resource, auths){\n    // Render a resource and add it to resources li\n    resource.id = resource.id.replace(/[^a-zA-Z\\d]/g, function(str) { return str.charCodeAt(0); });\n\n    // Make all definitions available at the root of the resource so that they can\n    // be loaded by the JSonEditor\n    resource.definitions = this.model.definitions;\n\n    var resourceView = new SwaggerUi.Views.ResourceView({\n      model: resource,\n      router: this.router,\n      tagName: 'li',\n      id: 'resource_' + resource.id,\n      className: 'resource',\n      auths: auths,\n      swaggerOptions: this.options.swaggerOptions\n    });\n    $('#resources', this.el).append(resourceView.render().el);\n  },\n\n  clear: function(){\n    $(this.el).html('');\n  },\n\n  onLinkClick: function (e) {\n    var el = e.target;\n\n    if (el.tagName === 'A' && el.href && !el.target) {\n        e.preventDefault();\n        window.open(el.href, '_blank');\n    }\n  }\n});\n\n'use strict';\n\nSwaggerUi.Models.Oauth2Model = Backbone.Model.extend({\n    defaults: {\n        scopes: {},\n        isPasswordFlow: false,\n        clientAuthenticationType: 'none'\n    },\n\n    initialize: function () {\n        if(this.attributes && this.attributes.scopes) {\n            var attributes = _.cloneDeep(this.attributes);\n            var i, scopes = [];\n            for(i in attributes.scopes) {\n                var scope = attributes.scopes[i];\n                if(typeof scope.description === 'string') {\n                    scopes[scope] = attributes.scopes[i];\n                    scopes.push(attributes.scopes[i]);\n                }\n            }\n            attributes.scopes = scopes;\n            this.attributes = attributes;\n        }\n\n        if (this.attributes && this.attributes.flow) {\n            var flow = this.attributes.flow;\n            this.set('isPasswordFlow', flow === 'password');\n            this.set('requireClientAuthentication', flow === 'application');\n            this.set('clientAuthentication', flow === 'password' || flow === 'application');\n        }\n        this.on('change', this.validate);\n    },\n\n    setScopes: function (name, val) {\n        var auth = _.extend({}, this.attributes);\n        var index = _.findIndex(auth.scopes, function(o) {\n            return o.scope === name;\n        });\n        auth.scopes[index].checked = val;\n\n        this.set(auth);\n        this.validate();\n    },\n\n    validate: function () {\n      var valid = false;\n      if (this.get('isPasswordFlow') &&\n          (!this.get('username'))) {\n          return false;\n      }\n\n      if (this.get('clientAuthenticationType') in ['basic', 'request-body'] &&\n          (!this.get('clientId'))) {\n          return false;\n      }\n\n      var scp = this.get('scopes');\n      var idx =  _.findIndex(scp, function (o) {\n         return o.checked === true;\n      });\n\n      if(scp.length > 0 && idx >= 0) {\n          valid = true;\n      }\n\n      if(scp.length === 0) {\n          valid = true;\n      }\n\n      this.set('valid', valid);\n\n      return valid;\n    }\n});\n\n'use strict';\n\nSwaggerUi.Views.Oauth2View = Backbone.View.extend({\n    events: {\n        'change .oauth-scope': 'scopeChange',\n        'change .oauth-username': 'setUsername',\n        'change .oauth-password': 'setPassword',\n        'change .oauth-client-authentication-type': 'setClientAuthenticationType',\n        'change .oauth-client-id': 'setClientId',\n        'change .oauth-client-secret': 'setClientSecret'\n    },\n\n    template: Handlebars.templates.oauth2,\n\n    cls: {\n        error: 'error'\n    },\n\n    render: function () {\n        this.$el.html(this.template(this.model.toJSON()));\n\n        return this;\n    },\n\n    scopeChange: function (e) {\n        var val = $(e.target).prop('checked');\n        var scope = $(e.target).data('scope');\n\n        this.model.setScopes(scope, val);\n    },\n\n    setUsername: function (e) {\n        var val= $(e.target).val();\n        this.model.set('username', val);\n        if (val) {\n            $(e.target).removeClass(this.cls.error);\n        }\n    },\n\n    setPassword: function (e) {\n        this.model.set('password', $(e.target).val());\n    },\n\n    setClientAuthenticationType: function (e) {\n        var type = $(e.target).val();\n        var $el = this.$el;\n        this.model.set('clientAuthenticationType', type);\n\n        switch(type) {\n            case 'none':\n                $el.find('.oauth-client-authentication').hide();\n                break;\n            case 'basic':\n            case 'request-body':\n                $el.find('.oauth-client-id').removeClass(this.cls.error);\n                $el.find('.oauth-client-authentication').show();\n                break;\n        }\n    },\n\n    setClientId: function (e) {\n        var val = $(e.target).val();\n        this.model.set('clientId', val);\n        if (val) {\n            $(e.target).removeClass(this.cls.error);\n        }\n    },\n\n    setClientSecret: function (e) {\n        this.model.set('clientSecret', $(e.target).val());\n        $(e.target).removeClass('error');\n    },\n\n    highlightInvalid: function () {\n        if (!this.model.get('username')) {\n            this.$el.find('.oauth-username').addClass(this.cls.error);\n        }\n\n        if (!this.model.get('clientId')) {\n            this.$el.find('.oauth-client-id').addClass(this.cls.error);\n        }\n    }\n});\n'use strict';\n\nSwaggerUi.Views.OperationView = Backbone.View.extend({\n  invocationUrl: null,\n\n  events: {\n    'submit .sandbox'         : 'submitOperation',\n    'click .submit'           : 'submitOperation',\n    'click .response_hider'   : 'hideResponse',\n    'click .toggleOperation'  : 'toggleOperationContent',\n    'mouseenter .api-ic'      : 'mouseEnter',\n    'dblclick .curl'          : 'selectText',\n    'change [name=responseContentType]' : 'showSnippet'\n  },\n\n  initialize: function(opts) {\n    opts = opts || {};\n    this.router = opts.router;\n    this.auths = opts.auths;\n    this.parentId = this.model.parentId;\n    this.nickname = this.model.nickname;\n    this.model.encodedParentId = encodeURIComponent(this.parentId);\n\n    if (opts.swaggerOptions) {\n      this.model.defaultRendering = opts.swaggerOptions.defaultModelRendering;\n\n      if (opts.swaggerOptions.showRequestHeaders) {\n        this.model.showRequestHeaders = true;\n      }\n\n      if (opts.swaggerOptions.showOperationIds) {\n        this.model.showOperationIds = true;\n      }\n    }\n    return this;\n  },\n\n  selectText: function(event) {\n    var doc = document,\n        text = event.target.firstChild,\n        range,\n        selection;\n    if (doc.body.createTextRange) {\n      range = document.body.createTextRange();\n      range.moveToElementText(text);\n      range.select();\n    } else if (window.getSelection) {\n      selection = window.getSelection();\n      range = document.createRange();\n      range.selectNodeContents(text);\n      selection.removeAllRanges();\n      selection.addRange(range);\n    }\n  },\n\n  mouseEnter: function(e) {\n    var elem = $(this.el).find('.content');\n    var x = e.pageX;\n    var y = e.pageY;\n    var scX = $(window).scrollLeft();\n    var scY = $(window).scrollTop();\n    var scMaxX = scX + $(window).width();\n    var scMaxY = scY + $(window).height();\n    var wd = elem.width();\n    var hgh = elem.height();\n\n    if (x + wd > scMaxX) {\n      x = scMaxX - wd;\n    }\n\n    if (x < scX) {\n      x = scX;\n    }\n\n    if (y + hgh > scMaxY) {\n      y = scMaxY - hgh;\n    }\n\n    if (y < scY) {\n      y = scY;\n    }\n\n    var pos = {};\n    pos.top = y;\n    pos.left = x;\n    elem.css(pos);\n  },\n\n  // Note: copied from CoffeeScript compiled file\n  // TODO: refactor\n  render: function() {\n    var a, auth, auths, code, contentTypeModel, isMethodSubmissionSupported, k, key, l, len, len1, len2, len3, len4, m, modelAuths, n, o, p, param, q, ref, ref1, ref2, ref3, ref4, ref5, responseContentTypeView, responseSignatureView, schema, schemaObj, scopeIndex, signatureModel, statusCode, successResponse, type, v, value, produces, isXML, isJSON;\n    isMethodSubmissionSupported = jQuery.inArray(this.model.method, this.model.supportedSubmitMethods()) >= 0;\n    if (!isMethodSubmissionSupported) {\n      this.model.isReadOnly = true;\n    }\n    this.model.description = this.model.description || this.model.notes;\n    this.model.oauth = null;\n    modelAuths = this.model.authorizations || this.model.security;\n    if (modelAuths) {\n      if (Array.isArray(modelAuths)) {\n        for (l = 0, len = modelAuths.length; l < len; l++) {\n          auths = modelAuths[l];\n          for (key in auths) {\n            for (a in this.auths) {\n              auth = this.auths[a];\n              if (key === auth.name) {\n                if (auth.type === 'oauth2') {\n                  this.model.oauth = {};\n                  this.model.oauth.scopes = [];\n                  ref1 = auth.value.scopes;\n                  for (k in ref1) {\n                    v = ref1[k];\n                    scopeIndex = auths[key].indexOf(k);\n                    if (scopeIndex >= 0) {\n                      o = {\n                        scope: k,\n                        description: v\n                      };\n                      this.model.oauth.scopes.push(o);\n                    }\n                  }\n                }\n              }\n            }\n          }\n        }\n      } else {\n        for (k in modelAuths) {\n          v = modelAuths[k];\n          if (k === 'oauth2') {\n            if (this.model.oauth === null) {\n              this.model.oauth = {};\n            }\n            if (this.model.oauth.scopes === void 0) {\n              this.model.oauth.scopes = [];\n            }\n            for (m = 0, len1 = v.length; m < len1; m++) {\n              o = v[m];\n              this.model.oauth.scopes.push(o);\n            }\n          }\n        }\n      }\n    }\n    if (typeof this.model.responses !== 'undefined') {\n      this.model.responseMessages = [];\n      ref2 = this.model.responses;\n      for (code in ref2) {\n        value = ref2[code];\n        schema = null;\n        schemaObj = this.model.responses[code].schema;\n        if (schemaObj && schemaObj.$ref) {\n          schema = schemaObj.$ref;\n          if (schema.indexOf('#/definitions/') !== -1) {\n            schema = schema.replace(/^.*#\\/definitions\\//, '');\n          }\n        }\n        this.model.responseMessages.push({\n          code: code,\n          message: value.description,\n          responseModel: schema,\n          headers: value.headers,\n          schema: schemaObj\n        });\n      }\n    }\n    if (typeof this.model.responseMessages === 'undefined') {\n      this.model.responseMessages = [];\n    }\n    signatureModel = null;\n    produces = this.model.produces;\n    isXML = this.contains(produces, 'xml');\n    isJSON = isXML ? this.contains(produces, 'json') : true;\n\n    if (this.model.successResponse) {\n      successResponse = this.model.successResponse;\n      for (key in successResponse) {\n        value = successResponse[key];\n        this.model.successCode = key;\n        if (typeof value === 'object' && typeof value.createJSONSample === 'function') {\n          this.model.successDescription = value.description;\n          this.model.headers = this.parseResponseHeaders(value.headers);\n          signatureModel = {\n            sampleJSON: isJSON ? JSON.stringify(SwaggerUi.partials.signature.createJSONSample(value), void 0, 2) : false,\n            isParam: false,\n            sampleXML: isXML ? SwaggerUi.partials.signature.createXMLSample(value.name, value.definition, value.models) : false,\n            signature: SwaggerUi.partials.signature.getModelSignature(value.name, value.definition, value.models, value.modelPropertyMacro)\n          };\n        } else {\n          signatureModel = {\n            signature: SwaggerUi.partials.signature.getPrimitiveSignature(value)\n          };\n        }\n      }\n    } else if (this.model.responseClassSignature && this.model.responseClassSignature !== 'string') {\n      signatureModel = {\n        sampleJSON: this.model.responseSampleJSON,\n        isParam: false,\n        signature: this.model.responseClassSignature\n      };\n    }\n    $(this.el).html(Handlebars.templates.operation(this.model));\n    if (signatureModel) {\n      signatureModel.defaultRendering = this.model.defaultRendering;\n      responseSignatureView = new SwaggerUi.Views.SignatureView({\n        model: signatureModel,\n        router: this.router,\n        tagName: 'div'\n      });\n      $('.model-signature', $(this.el)).append(responseSignatureView.render().el);\n    } else {\n      this.model.responseClassSignature = 'string';\n      $('.model-signature', $(this.el)).html(this.model.type);\n    }\n    contentTypeModel = {\n      isParam: false\n    };\n    contentTypeModel.consumes = this.model.consumes;\n    contentTypeModel.produces = this.model.produces;\n    ref3 = this.model.parameters;\n    for (n = 0, len2 = ref3.length; n < len2; n++) {\n      param = ref3[n];\n      type = param.type || param.dataType || '';\n      if (typeof type === 'undefined') {\n        schema = param.schema;\n        if (schema && schema.$ref) {\n          ref = schema.$ref;\n          if (ref.indexOf('#/definitions/') === 0) {\n            type = ref.substring('#/definitions/'.length);\n          } else {\n            type = ref;\n          }\n        }\n      }\n      if (type && type.toLowerCase() === 'file') {\n        if (!contentTypeModel.consumes) {\n          contentTypeModel.consumes = 'multipart/form-data';\n        }\n      }\n      param.type = type;\n    }\n    responseContentTypeView = new SwaggerUi.Views.ResponseContentTypeView({\n      model: contentTypeModel,\n      router: this.router\n    });\n    $('.response-content-type', $(this.el)).append(responseContentTypeView.render().el);\n    ref4 = this.model.parameters;\n    for (p = 0, len3 = ref4.length; p < len3; p++) {\n      param = ref4[p];\n      this.addParameter(param, contentTypeModel.consumes);\n    }\n    ref5 = this.model.responseMessages;\n    for (q = 0, len4 = ref5.length; q < len4; q++) {\n      statusCode = ref5[q];\n      statusCode.isXML = isXML;\n      statusCode.isJSON = isJSON;\n      if (!_.isUndefined(statusCode.headers)) {\n        statusCode.headers = this.parseHeadersType(statusCode.headers);\n      }\n      this.addStatusCode(statusCode);\n    }\n\n    if (Array.isArray(this.model.security)) {\n      var authsModel = SwaggerUi.utils.parseSecurityDefinitions(this.model.security, this.model.parent.securityDefinitions);\n\n      authsModel.isLogout = !_.isEmpty(this.model.clientAuthorizations.authz);\n      this.authView = new SwaggerUi.Views.AuthButtonView({\n        data: authsModel,\n        router: this.router,\n        isOperation: true,\n        model: {\n          scopes: authsModel.scopes\n        }\n      });\n      this.$('.authorize-wrapper').append(this.authView.render().el);\n    }\n\n    this.showSnippet();\n    return this;\n  },\n\n  parseHeadersType: function (headers) {\n    var map = {\n      'string': {\n        'date-time': 'dateTime',\n        'date'     : 'date'\n      }\n    };\n\n    _.forEach(headers, function (header) {\n      var value;\n      header = header || {};\n      value = map[header.type] && map[header.type][header.format];\n      if (!_.isUndefined(value)) {\n        header.type = value;\n      }\n    });\n\n    return headers;\n  },\n\n  contains: function (produces, type) {\n    return produces.filter(function (val) {\n      if (val.indexOf(type) > -1) {\n        return true;\n      }\n    }).length;\n  },\n\n  parseResponseHeaders: function (data) {\n    var HEADERS_SEPARATOR = '; ';\n    var headers = _.clone(data);\n\n    _.forEach(headers, function (header) {\n      var other = [];\n      _.forEach(header, function (value, key) {\n        var properties = ['type', 'description'];\n        if (properties.indexOf(key.toLowerCase()) === -1) {\n          other.push(key + ': ' + value);\n        }\n      });\n\n      other.join(HEADERS_SEPARATOR);\n      header.other = other;\n    });\n\n    return headers;\n  },\n\n  addParameter: function(param, consumes) {\n    // Render a parameter\n    param.consumes = consumes;\n    param.defaultRendering = this.model.defaultRendering;\n\n    // Copy this param JSON spec so that it will be available for JsonEditor\n    if(param.schema){\n      $.extend(true, param.schema, this.model.definitions[param.type]);\n      param.schema.definitions = this.model.definitions;\n      // This is required for JsonEditor to display the root properly\n      if(!param.schema.type){\n        param.schema.type = 'object';\n      }\n      // This is the title that will be used by JsonEditor for the root\n      // Since we already display the parameter's name in the Parameter column\n      // We set this to space, we can't set it to null or space otherwise JsonEditor\n      // will replace it with the text \"root\" which won't look good on screen\n      if(!param.schema.title){\n        param.schema.title = ' ';\n      }\n    }\n\n    var paramView = new SwaggerUi.Views.ParameterView({\n      model: param,\n      tagName: 'tr',\n      readOnly: this.model.isReadOnly,\n      swaggerOptions: this.options.swaggerOptions\n    });\n    $('.operation-params', $(this.el)).append(paramView.render().el);\n  },\n\n  addStatusCode: function(statusCode) {\n    // Render status codes\n    statusCode.defaultRendering = this.model.defaultRendering;\n    var statusCodeView = new SwaggerUi.Views.StatusCodeView({\n      model: statusCode,\n      tagName: 'tr',\n      router: this.router\n    });\n    $('.operation-status', $(this.el)).append(statusCodeView.render().el);\n  },\n\n  // Note: copied from CoffeeScript compiled file\n  // TODO: redactor\n  submitOperation: function(e) {\n    var error_free, form, isFileUpload, map, opts;\n    if (e !== null) {\n      e.preventDefault();\n    }\n    form = $('.sandbox', $(this.el));\n    error_free = true;\n    form.find('input.required').each(function() {\n      $(this).removeClass('error');\n      if (jQuery.trim($(this).val()) === '') {\n        $(this).addClass('error');\n        $(this).wiggle({\n          callback: (function(_this) {\n            return function() {\n              $(_this).focus();\n            };\n          })(this)\n        });\n        error_free = false;\n      }\n    });\n    form.find('textarea.required:visible').each(function() {\n      $(this).removeClass('error');\n      if (jQuery.trim($(this).val()) === '') {\n        $(this).addClass('error');\n        $(this).wiggle({\n          callback: (function(_this) {\n            return function() {\n              return $(_this).focus();\n            };\n          })(this)\n        });\n        error_free = false;\n      }\n    });\n    form.find('select.required').each(function() {\n      $(this).removeClass('error');\n      if (this.selectedIndex === -1) {\n        $(this).addClass('error');\n        $(this).wiggle({\n          callback: (function(_this) {\n            return function() {\n              $(_this).focus();\n            };\n          })(this)\n        });\n        error_free = false;\n      }\n    });\n    if (error_free) {\n      map = this.getInputMap(form);\n      isFileUpload = this.isFileUpload(form);\n      opts = {\n        parent: this\n      };\n      if (this.options.swaggerOptions) {\n        for(var key in this.options.swaggerOptions) {\n          opts[key] = this.options.swaggerOptions[key];\n        }\n      }\n\n      var pi;\n      for(pi = 0; pi < this.model.parameters.length; pi++){\n        var p = this.model.parameters[pi];\n        if( p.jsonEditor && p.jsonEditor.isEnabled()){\n          var json = p.jsonEditor.getValue();\n          map[p.name] = JSON.stringify(json);\n        }\n      }\n\n      opts.responseContentType = $('div select[name=responseContentType]', $(this.el)).val();\n      opts.requestContentType = $('div select[name=parameterContentType]', $(this.el)).val();\n      $('.response_throbber', $(this.el)).show();\n      if (isFileUpload) {\n        $('.request_url', $(this.el)).html('<pre></pre>');\n        $('.request_url pre', $(this.el)).text(this.invocationUrl);\n\n        opts.useJQuery = true;\n        map.parameterContentType = 'multipart/form-data';\n        this.map = map;\n        return this.model.execute(map, opts, this.showCompleteStatus, this.showErrorStatus, this);\n      } else {\n        this.map = map;\n        return this.model.execute(map, opts, this.showCompleteStatus, this.showErrorStatus, this);\n      }\n    }\n  },\n\n  getInputMap: function (form) {\n    var map, ref1, l, len, o, ref2, m, len1, val, ref3, n, len2;\n    map = {};\n    ref1 = form.find('input');\n    for (l = 0, len = ref1.length; l < len; l++) {\n      o = ref1[l];\n      if ((o.value !== null) && jQuery.trim(o.value).length > 0) {\n        map[o.name] = o.value;\n      }\n      if (o.type === 'file') {\n        map[o.name] = o.files[0];\n      }\n    }\n    ref2 = form.find('textarea');\n    for (m = 0, len1 = ref2.length; m < len1; m++) {\n      o = ref2[m];\n      val = this.getTextAreaValue(o);\n      if ((val !== null) && jQuery.trim(val).length > 0) {\n        map[o.name] = val;\n      }\n    }\n    ref3 = form.find('select');\n    for (n = 0, len2 = ref3.length; n < len2; n++) {\n      o = ref3[n];\n      val = this.getSelectedValue(o);\n      if ((val !== null) && jQuery.trim(val).length > 0) {\n        map[o.name] = val;\n      }\n    }\n    return map;\n  },\n\n  isFileUpload: function (form) {\n    var ref1, l, len, o;\n    var isFileUpload = false;\n    ref1 = form.find('input');\n    for (l = 0, len = ref1.length; l < len; l++) {\n      o = ref1[l];\n      if (o.type === 'file') {\n        isFileUpload = true;\n      }\n    }\n    return isFileUpload;\n  },\n\n  success: function(response, parent) {\n    parent.showCompleteStatus(response);\n  },\n\n  // wraps a jquery response as a shred response\n  wrap: function(data) {\n    var h, headerArray, headers, i, l, len, o;\n    headers = {};\n    headerArray = data.getAllResponseHeaders().split('\\r');\n    for (l = 0, len = headerArray.length; l < len; l++) {\n      i = headerArray[l];\n      h = i.match(/^([^:]*?):(.*)$/);\n      if (!h) {\n        h = [];\n      }\n      h.shift();\n      if (h[0] !== void 0 && h[1] !== void 0) {\n        headers[h[0].trim()] = h[1].trim();\n      }\n    }\n    o = {};\n    o.content = {};\n    o.content.data = data.responseText;\n    o.headers = headers;\n    o.request = {};\n    o.request.url = this.invocationUrl;\n    o.status = data.status;\n    return o;\n  },\n\n  getSelectedValue: function(select) {\n    if (!select.multiple) {\n      return select.value;\n    } else {\n      var options = [];\n      for (var l = 0, len = select.options.length; l < len; l++) {\n        var opt = select.options[l];\n        if (opt.selected) {\n          options.push(opt.value);\n        }\n      }\n      if (options.length > 0) {\n        return options;\n      } else {\n        return null;\n      }\n    }\n  },\n\n  // handler for hide response link\n  hideResponse: function(e) {\n    if (e) { e.preventDefault(); }\n    $('.response', $(this.el)).slideUp();\n    $('.response_hider', $(this.el)).fadeOut();\n  },\n\n  // Show response from server\n  showResponse: function(response) {\n    var prettyJson = JSON.stringify(response, null, '\\t').replace(/\\n/g, '<br>');\n    $('.response_body', $(this.el)).html(_.escape(prettyJson));\n  },\n\n  // Show error from server\n  showErrorStatus: function(data, parent) {\n    parent.showStatus(data);\n  },\n\n  // show the status codes\n  showCompleteStatus: function(data, parent){\n    parent.showStatus(data);\n  },\n\n  // Adapted from http://stackoverflow.com/a/2893259/454004\n  // Note: directly ported from CoffeeScript\n  // TODO: Cleanup CoffeeScript artifacts\n  formatXml: function(xml) {\n    var contexp, fn, formatted, indent, l, lastType, len, lines, ln, pad, reg, transitions, wsexp;\n    reg = /(>)(<)(\\/*)/g;\n    wsexp = /[ ]*(.*)[ ]+\\n/g;\n    contexp = /(<.+>)(.+\\n)/g;\n    xml = xml.replace(/\\r\\n/g, '\\n').replace(reg, '$1\\n$2$3').replace(wsexp, '$1\\n').replace(contexp, '$1\\n$2');\n    pad = 0;\n    formatted = '';\n    lines = xml.split('\\n');\n    indent = 0;\n    lastType = 'other';\n    transitions = {\n      'single->single': 0,\n      'single->closing': -1,\n      'single->opening': 0,\n      'single->other': 0,\n      'closing->single': 0,\n      'closing->closing': -1,\n      'closing->opening': 0,\n      'closing->other': 0,\n      'opening->single': 1,\n      'opening->closing': 0,\n      'opening->opening': 1,\n      'opening->other': 1,\n      'other->single': 0,\n      'other->closing': -1,\n      'other->opening': 0,\n      'other->other': 0\n    };\n    fn = function(ln) {\n      var fromTo, j, key, padding, type, types, value;\n      types = {\n        single: Boolean(ln.match(/<.+\\/>/)),\n        closing: Boolean(ln.match(/<\\/.+>/)),\n        opening: Boolean(ln.match(/<[^!?].*>/))\n      };\n      type = ((function() {\n        var results;\n        results = [];\n        for (key in types) {\n          value = types[key];\n          if (value) {\n            results.push(key);\n          }\n        }\n        return results;\n      })())[0];\n      type = type === void 0 ? 'other' : type;\n      fromTo = lastType + '->' + type;\n      lastType = type;\n      padding = '';\n      indent += transitions[fromTo];\n      padding = ((function() {\n        var m, ref1, results;\n        results = [];\n        for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) {\n          results.push('  ');\n        }\n        return results;\n      })()).join('');\n      if (fromTo === 'opening->closing') {\n        formatted = formatted.substr(0, formatted.length - 1) + ln + '\\n';\n      } else {\n        formatted += padding + ln + '\\n';\n      }\n    };\n    for (l = 0, len = lines.length; l < len; l++) {\n      ln = lines[l];\n      fn(ln);\n    }\n    return formatted;\n  },\n\n  // puts the response data in UI\n  showStatus: function(response) {\n    var url, content;\n    if (response.content === undefined) {\n      content = response.data;\n      url = response.url;\n    } else {\n      content = response.content.data;\n      url = response.request.url;\n    }\n    var headers = response.headers;\n    if(typeof content === 'string') {\n      content = jQuery.trim(content);\n    }\n\n    // if server is nice, and sends content-type back, we can use it\n    var contentType = null;\n    if (headers) {\n      contentType = headers['Content-Type'] || headers['content-type'];\n      if (contentType) {\n        contentType = contentType.split(';')[0].trim();\n      }\n    }\n\n    $('.response_body', $(this.el)).removeClass('json');\n    $('.response_body', $(this.el)).removeClass('xml');\n\n    var supportsAudioPlayback = function(contentType){\n      var audioElement = document.createElement('audio');\n      return !!(audioElement.canPlayType && audioElement.canPlayType(contentType).replace(/no/, ''));\n    };\n\n    var pre;\n    var code;\n    var skipHighlight = false;\n    if (!content) {\n      code = $('<code />').text('no content');\n      pre = $('<pre class=\"json\" />').append(code);\n\n      // JSON\n    } else if (\n        contentType === 'application/octet-stream' ||\n        headers['Content-Disposition'] && (/attachment/).test(headers['Content-Disposition']) ||\n        headers['content-disposition'] && (/attachment/).test(headers['content-disposition']) ||\n        headers['Content-Description'] && (/File Transfer/).test(headers['Content-Description']) ||\n        headers['content-description'] && (/File Transfer/).test(headers['content-description'])) {\n\n      if ('Blob' in window) {\n        var type = contentType || 'text/html';\n        var a = document.createElement('a');\n        var href;\n\n        if({}.toString.apply(content) === '[object Blob]') {\n          href = window.URL.createObjectURL(content);\n        }\n        else {\n          var binaryData = [];\n          binaryData.push(content);\n          href = window.URL.createObjectURL(new Blob(binaryData, {type: type}));\n        }\n        var fileName = response.url.substr(response.url.lastIndexOf('/') + 1);\n        var download = [type, fileName, href].join(':');\n\n        // Use filename from response header\n        var disposition = headers['content-disposition'] || headers['Content-Disposition'];\n        if(typeof disposition !== 'undefined') {\n          var responseFilename = /filename=([^;]*);?/.exec(disposition);\n          if(responseFilename !== null && responseFilename.length > 1) {\n            download = responseFilename[1];\n            fileName = download;\n          }\n        }\n\n        a.setAttribute('href', href);\n        a.setAttribute('download', download);\n        a.innerText = 'Download ' + fileName;\n\n        pre = $('<div/>').append(a);\n        skipHighlight = true;\n      } else {\n        pre = $('<pre class=\"json\" />').append('Download headers detected but your browser does not support downloading binary via XHR (Blob).');\n      }\n    } else if (contentType === 'application/json' || /\\+json$/.test(contentType)) {\n      var json = null;\n      try {\n        json = JSON.stringify(JSON.parse(content), null, '  ');\n      } catch (_error) {\n        json = 'can\\'t parse JSON.  Raw result:\\n\\n' + content;\n      }\n      code = $('<code />').text(json);\n      pre = $('<pre class=\"json\" />').append(code);\n\n      // XML\n    } else if (contentType === 'application/xml' || /\\+xml$/.test(contentType)) {\n      code = $('<code />').text(this.formatXml(content));\n      pre = $('<pre class=\"xml\" />').append(code);\n\n      // HTML\n    } else if (contentType === 'text/html') {\n      code = $('<code />').html(_.escape(content));\n      pre = $('<pre class=\"xml\" />').append(code);\n\n      // Plain Text\n    } else if (/text\\/plain/.test(contentType)) {\n      code = $('<code />').text(content);\n      pre = $('<pre class=\"plain\" />').append(code);\n\n      // Image\n    } else if (/^image\\//.test(contentType)) {\n      var urlCreator = window.URL || window.webkitURL;\n      var imageUrl = urlCreator.createObjectURL(content);\n\n      pre = $('<img>').attr( 'src', imageUrl);\n      // Audio\n    } else if (/^audio\\//.test(contentType) && supportsAudioPlayback(contentType)) {\n      pre = $('<audio controls>').append($('<source>').attr('src', url).attr('type', contentType));\n    } else if(headers.location || headers.Location) {\n      // Location header based redirect download\n      window.location = response.url;\n\n      // Anything else (CORS)\n    } else {\n      code = $('<code />').text(content);\n      pre = $('<pre class=\"json\" />').append(code);\n    }\n    var response_body = pre;\n    $('.request_url', $(this.el)).html('<pre></pre>');\n    $('.request_url pre', $(this.el)).text(url);\n    $('.response_code', $(this.el)).html('<pre>' + response.status + '</pre>');\n    $('.response_body', $(this.el)).html(response_body);\n    $('.response_headers', $(this.el)).html('<pre>' + _.escape(JSON.stringify(response.headers, null, '  ')).replace(/\\n/g, '<br>') + '</pre>');\n    $('.response', $(this.el)).slideDown();\n    $('.response_hider', $(this.el)).show();\n    $('.response_throbber', $(this.el)).hide();\n\n\n    // adds curl output\n    var curlCommand = this.model.asCurl(this.map, {responseContentType: contentType});\n    curlCommand = curlCommand.replace('!', '&#33;');\n    $( 'div.curl', $(this.el)).html('<pre>' + _.escape(curlCommand) + '</pre>');\n\n    // only highlight the response if response is less than threshold, default state is highlight response\n    var opts = this.options.swaggerOptions;\n\n    if (opts.showRequestHeaders) {\n      var form = $('.sandbox', $(this.el)),\n          map = this.getInputMap(form),\n          requestHeaders = this.model.getHeaderParams(map);\n      delete requestHeaders['Content-Type'];\n      $('.request_headers', $(this.el)).html('<pre>' + _.escape(JSON.stringify(requestHeaders, null, '  ')).replace(/\\n/g, '<br>') + '</pre>');\n    }\n\n    // Call user-defined hook\n    if (opts.responseHooks && opts.responseHooks[this.nickname]) {\n      opts.responseHooks[this.nickname](response, this);\n    }\n\n    var response_body_el = $('.response_body', $(this.el))[0];\n    // only highlight the response if response is less than threshold, default state is highlight response\n    if (opts.highlightSizeThreshold && typeof response.data !== 'undefined' && response.data.length > opts.highlightSizeThreshold || skipHighlight) {\n      return response_body_el;\n    } else {\n      return hljs.highlightBlock(response_body_el);\n    }\n  },\n\n  toggleOperationContent: function (event) {\n    var elem = $('#' + Docs.escapeResourceName(this.parentId + '_' + this.nickname + '_content'));\n    if (elem.is(':visible')){\n      $.bbq.pushState('#/', 2);\n      event.preventDefault();\n      Docs.collapseOperation(elem);\n    } else {\n      Docs.expandOperation(elem);\n    }\n  },\n\n  getTextAreaValue: function(textArea) {\n    var param, parsed, result, i;\n    if (textArea.value === null || jQuery.trim(textArea.value).length === 0) {\n      return null;\n    }\n    param = this.getParamByName(textArea.name);\n    if (param && param.type && param.type.toLowerCase() === 'array') {\n      parsed = textArea.value.split('\\n');\n      result = [];\n      for (i = 0; i < parsed.length; i++) {\n        if (parsed[i] !== null && jQuery.trim(parsed[i]).length > 0) {\n          result.push(parsed[i]);\n        }\n      }\n      return result.length > 0 ? result : null;\n    } else {\n      return textArea.value;\n    }\n  },\n\n  showSnippet: function () {\n    var contentTypeEl = this.$('[name=responseContentType]');\n    var xmlSnippetEl = this.$('.operation-status .snippet_xml, .response-class .snippet_xml');\n    var jsonSnippetEl = this.$('.operation-status .snippet_json, .response-class .snippet_json');\n    var contentType;\n\n    if (!contentTypeEl.length) { return; }\n    contentType = contentTypeEl.val();\n\n    if (contentType.indexOf('xml') > -1) {\n      xmlSnippetEl.show();\n      jsonSnippetEl.hide();\n    } else {\n      jsonSnippetEl.show();\n      xmlSnippetEl.hide();\n    }\n  },\n\n  getParamByName: function(name) {\n    var i;\n    if (this.model.parameters) {\n      for(i = 0; i < this.model.parameters.length; i++) {\n        if (this.model.parameters[i].name === name) {\n          return this.model.parameters[i];\n        }\n      }\n    }\n    return null;\n  }\n\n});\n\n'use strict';\n\nSwaggerUi.Views.ParameterContentTypeView = Backbone.View.extend({\n  initialize: function  () {},\n\n  render: function(){\n    this.model.parameterContentTypeId = 'pct' + Math.random();\n    $(this.el).html(Handlebars.templates.parameter_content_type(this.model));\n    return this;\n  }\n\n});\n'use strict';\n\nSwaggerUi.Views.ParameterView = Backbone.View.extend({\n  events: {\n    'change [name=parameterContentType]' : 'toggleParameterSnippet'\n  },\n\n  initialize: function(){\n    Handlebars.registerHelper('isArray', function(param, opts) {\n      var paramType = param.type && param.type.toLowerCase();\n      if (paramType === 'array' || param.allowMultiple) {\n        return opts.fn(this);\n      } else {\n        return opts.inverse(this);\n      }\n    });\n  },\n\n  render: function() {\n    var type = this.model.type || this.model.dataType;\n    var modelType = this.model.modelSignature.type;\n    var modelDefinitions = this.model.modelSignature.definitions;\n    var schema = this.model.schema || {};\n    var consumes = this.model.consumes || [];\n    var sampleJSON, signatureView;\n\n    if (typeof type === 'undefined') {\n      if (schema.$ref) {\n        var ref = schema.$ref;\n        if (ref.indexOf('#/definitions/') === 0) {\n          type = ref.substring('#/definitions/'.length);\n        } else {\n          type = ref;\n        }\n      }\n    }\n\n    this.model.type = type;\n    this.model.paramType = this.model.in || this.model.paramType;\n    this.model.isBody = this.model.paramType === 'body' || this.model.in === 'body';\n    this.model.isFile = type && type.toLowerCase() === 'file';\n\n    // Allow for default === false\n    if(typeof this.model.default === 'undefined') {\n      this.model.default = this.model.defaultValue;\n    }\n\n    this.model.hasDefault = (typeof this.model.default !== 'undefined');\n    this.model.valueId = 'm' + this.model.name + Math.random();\n\n    if (this.model.allowableValues) {\n      this.model.isList = true;\n    }\n\n    var isXML = this.contains(consumes, 'xml');\n    var isJSON = isXML ? this.contains(consumes, 'json') : true;\n    sampleJSON = SwaggerUi.partials.signature.createParameterJSONSample(modelType, modelDefinitions);\n\n    var template = this.template();\n    $(this.el).html(template(this.model));\n\n    var signatureModel = {\n      sampleJSON: isJSON ? sampleJSON : false,\n      sampleXML: sampleJSON && isXML ? SwaggerUi.partials.signature.createXMLSample('', schema, modelDefinitions, true) : false,\n      isParam: true,\n      signature: SwaggerUi.partials.signature.getParameterModelSignature(modelType, modelDefinitions),\n      defaultRendering: this.model.defaultRendering\n    };\n\n    if (sampleJSON) {\n      signatureView = new SwaggerUi.Views.SignatureView({model: signatureModel, tagName: 'div'});\n      $('.model-signature', $(this.el)).append(signatureView.render().el);\n    }\n    else {\n      $('.model-signature', $(this.el)).html(this.model.signature);\n    }\n\n    var isParam = false;\n\n    if( this.options.swaggerOptions.jsonEditor && this.model.isBody && this.model.schema){\n      var $self = $(this.el);\n      this.model.jsonEditor =\n        /* global JSONEditor */\n        new JSONEditor($('.editor_holder', $self)[0],\n                       {schema: this.model.schema, startval : this.model.default,\n                        ajax:true,\n                        disable_properties:true,\n                        disable_edit_json:true,\n                        iconlib: 'swagger' });\n      // This is so that the signature can send back the sample to the json editor\n      // TODO: SignatureView should expose an event \"onSampleClicked\" instead\n      signatureModel.jsonEditor = this.model.jsonEditor;\n      $('.body-textarea', $self).hide();\n      $('.editor_holder', $self).show();\n      $('.parameter-content-type', $self)\n        .change(function(e){\n            if(e.target.value === 'application/xml'){\n              $('.body-textarea', $self).show();\n              $('.editor_holder', $self).hide();\n              this.model.jsonEditor.disable();\n            }\n            else {\n              $('.body-textarea', $self).hide();\n              $('.editor_holder', $self).show();\n              this.model.jsonEditor.enable();\n            }\n        });\n      }\n\n\n    if (this.model.isBody) {\n      isParam = true;\n    }\n\n    var contentTypeModel = {\n      isParam: isParam\n    };\n\n    contentTypeModel.consumes = this.model.consumes;\n\n    if (isParam) {\n      var parameterContentTypeView = new SwaggerUi.Views.ParameterContentTypeView({model: contentTypeModel});\n      $('.parameter-content-type', $(this.el)).append(parameterContentTypeView.render().el);\n      this.toggleParameterSnippet();\n    }\n\n    else {\n      var responseContentTypeView = new SwaggerUi.Views.ResponseContentTypeView({model: contentTypeModel});\n      $('.response-content-type', $(this.el)).append(responseContentTypeView.render().el);\n      this.toggleResponseSnippet();\n    }\n\n    return this;\n  },\n\n  contains: function (consumes, type) {\n    return consumes.filter(function (val) {\n      if (val.indexOf(type) > -1) {\n        return true;\n      }\n    }).length;\n  },\n\n  toggleParameterSnippet: function () {\n    var contentType = this.$('[name=parameterContentType]').val();\n\n    this.toggleSnippet(contentType);\n  },\n\n  toggleResponseSnippet: function () {\n    var contentEl = this.$('[name=responseContentType]');\n\n    if (!contentEl.length) { return; }\n\n    this.toggleSnippet(contentEl.val());\n  },\n\n  toggleSnippet: function (type) {\n    type = type || '';\n    if (type.indexOf('xml') > -1) {\n      this.$('.snippet_xml').show();\n      this.$('.snippet_json').hide();\n    } else {\n      this.$('.snippet_json').show();\n      this.$('.snippet_xml').hide();\n    }\n  },\n\n  // Return an appropriate template based on if the parameter is a list, readonly, required\n  template: function(){\n    if (this.model.isList) {\n      return Handlebars.templates.param_list;\n    } else {\n      if (this.options.readOnly) {\n        if (this.model.required) {\n          return Handlebars.templates.param_readonly_required;\n        } else {\n          return Handlebars.templates.param_readonly;\n        }\n      } else {\n        if (this.model.required) {\n          return Handlebars.templates.param_required;\n        } else {\n          return Handlebars.templates.param;\n        }\n      }\n    }\n  }\n});\n\n'use strict';\n\n/* jshint -W122 */\nSwaggerUi.partials.signature = (function () {\n  // copy-pasted from swagger-js\n  var resolveSchema = function (schema) {\n    if (_.isPlainObject(schema.schema)) {\n      schema = resolveSchema(schema.schema);\n    }\n\n    return schema;\n  };\n\n  // copy-pasted from swagger-js\n  var simpleRef = function (name) {\n    if (typeof name === 'undefined') {\n      return null;\n    }\n\n    if (name.indexOf('#/definitions/') === 0) {\n      return name.substring('#/definitions/'.length);\n    } else {\n      return name;\n    }\n  };\n\n  // copy-pasted from swagger-js\n  var getInlineModel = function(inlineStr) {\n    if(/^Inline Model \\d+$/.test(inlineStr) && this.inlineModels) {\n      var id = parseInt(inlineStr.substr('Inline Model'.length).trim(),10); //\n      var model = this.inlineModels[id];\n      return model;\n    }\n    // I'm returning null here, should I rather throw an error?\n    return null;\n  };\n\n  // copy-pasted from swagger-js\n  var formatXml = function(xml) {\n    var contexp, fn, formatted, indent, l, lastType, len, lines, ln, pad, reg, transitions, wsexp;\n    reg = /(>)(<)(\\/*)/g;\n    wsexp = /[ ]*(.*)[ ]+\\n/g;\n    contexp = /(<.+>)(.+\\n)/g;\n    xml = xml.replace(reg, '$1\\n$2$3').replace(wsexp, '$1\\n').replace(contexp, '$1\\n$2');\n    pad = 0;\n    formatted = '';\n    lines = xml.split('\\n');\n    indent = 0;\n    lastType = 'other';\n    transitions = {\n      'single->single': 0,\n      'single->closing': -1,\n      'single->opening': 0,\n      'single->other': 0,\n      'closing->single': 0,\n      'closing->closing': -1,\n      'closing->opening': 0,\n      'closing->other': 0,\n      'opening->single': 1,\n      'opening->closing': 0,\n      'opening->opening': 1,\n      'opening->other': 1,\n      'other->single': 0,\n      'other->closing': -1,\n      'other->opening': 0,\n      'other->other': 0\n    };\n    fn = function(ln) {\n      var fromTo, j, key, padding, type, types, value;\n      types = {\n        single: Boolean(ln.match(/<.+\\/>/)),\n        closing: Boolean(ln.match(/<\\/.+>/)),\n        opening: Boolean(ln.match(/<[^!?].*>/))\n      };\n      type = ((function() {\n        var results;\n        results = [];\n        for (key in types) {\n          value = types[key];\n          if (value) {\n            results.push(key);\n          }\n        }\n        return results;\n      })())[0];\n      type = type === void 0 ? 'other' : type;\n      fromTo = lastType + '->' + type;\n      lastType = type;\n      padding = '';\n      indent += transitions[fromTo];\n      padding = ((function() {\n        var m, ref1, results;\n        results = [];\n        for (j = m = 0, ref1 = indent; 0 <= ref1 ? m < ref1 : m > ref1; j = 0 <= ref1 ? ++m : --m) {\n          results.push('  ');\n        }\n        return results;\n      })()).join('');\n      if (fromTo === 'opening->closing') {\n        formatted = formatted.substr(0, formatted.length - 1) + ln + '\\n';\n      } else {\n        formatted += padding + ln + '\\n';\n      }\n    };\n    for (l = 0, len = lines.length; l < len; l++) {\n      ln = lines[l];\n      fn(ln);\n    }\n    return formatted;\n  };\n\n  // copy-pasted from swagger-js\n  var getModelSignature = function (name, schema, models, modelPropertyMacro) {\n    var strongOpen = '<span class=\"strong\">';\n    var strongClose = '</span>';\n\n    var optionHtml = function (label, value) {\n      return '<tr><td class=\"optionName\">' + label + ':</td><td>' + value + '</td></tr>';\n    };\n\n\n    // Allow for ignoring the 'name' argument.... shifting the rest\n    if(_.isObject(arguments[0])) {\n      name = void 0;\n      schema = arguments[0];\n      models = arguments[1];\n      modelPropertyMacro = arguments[2];\n    }\n\n    models = models || {};\n\n    // Resolve the schema (Handle nested schemas)\n    schema = resolveSchema(schema);\n\n    // Return for empty object\n    if(_.isEmpty(schema)) {\n      return strongOpen + 'Empty' + strongClose;\n    }\n\n    // Dereference $ref from 'models'\n    if(typeof schema.$ref === 'string') {\n      name = simpleRef(schema.$ref);\n      schema = models[name];\n      if(typeof schema === 'undefined')\n      {\n        return strongOpen + name + ' is not defined!' + strongClose;\n      }\n    }\n\n    if(typeof name !== 'string') {\n      name = schema.title || 'Inline Model';\n    }\n\n    // If we are a Model object... adjust accordingly\n    if(schema.definition) {\n      schema = schema.definition;\n    }\n\n    if(typeof modelPropertyMacro !== 'function') {\n      modelPropertyMacro = function(prop){\n        return (prop || {}).default;\n      };\n    }\n\n    var references = {};\n    var seenModels = [];\n    var inlineModels = 0;\n\n    // Generate current HTML\n    var html = processModel(schema, name);\n\n    // Generate references HTML\n    while (_.keys(references).length > 0) {\n      /* jshint ignore:start */\n      _.forEach(references, function (schema, name) {\n        var seenModel = _.indexOf(seenModels, name) > -1;\n\n        delete references[name];\n\n        if (!seenModel) {\n          seenModels.push(name);\n\n          html += '<br />' + processModel(schema, name);\n        }\n      });\n      /* jshint ignore:end */\n    }\n\n    return html;\n\n\n    function addReference(schema, name, skipRef) {\n      var modelName = name;\n      var model;\n\n      if (schema.$ref) {\n        modelName = schema.title || simpleRef(schema.$ref);\n        model = models[simpleRef(schema.$ref)];\n      } else if (_.isUndefined(name)) {\n        modelName = schema.title || 'Inline Model ' + (++inlineModels);\n        model = {definition: schema};\n      }\n\n      if (skipRef !== true) {\n        references[modelName] = _.isUndefined(model) ? {} : model.definition;\n      }\n\n      return modelName;\n    }\n\n    function primitiveToHTML(schema) {\n      var html = '<span class=\"propType\">';\n      var type = schema.type || 'object';\n\n      if (schema.$ref) {\n        html += addReference(schema, simpleRef(schema.$ref));\n      } else if (type === 'object') {\n        if (!_.isUndefined(schema.properties)) {\n          html += addReference(schema);\n        } else {\n          html += 'object';\n        }\n      } else if (type === 'array') {\n        html += 'Array[';\n\n        if (_.isArray(schema.items)) {\n          html += _.map(schema.items, addReference).join(',');\n        } else if (_.isPlainObject(schema.items)) {\n          if (_.isUndefined(schema.items.$ref)) {\n            if (!_.isUndefined(schema.items.type) && _.indexOf(['array', 'object'], schema.items.type) === -1) {\n              html += schema.items.type;\n            } else {\n              html += addReference(schema.items);\n            }\n          } else {\n            html += addReference(schema.items, simpleRef(schema.items.$ref));\n          }\n        } else {\n          console.log('Array type\\'s \\'items\\' schema is not an array or an object, cannot process');\n          html += 'object';\n        }\n\n        html += ']';\n      } else {\n        html += schema.type;\n      }\n\n      html += '</span>';\n\n      return html;\n    }\n\n    function primitiveToOptionsHTML(schema, html) {\n      var options = '';\n      var type = schema.type || 'object';\n      var isArray = type === 'array';\n\n      if (!_.isUndefined(schema.description)) {\n        html += ': ' + '<span class=\"propDesc\">' + schema.description + '</span>';\n      }\n\n      if (schema.enum) {\n        html += ' = <span class=\"propVals\">[\\'' + schema.enum.join('\\', \\'') + '\\']</span>';\n      }\n\n      if (isArray) {\n        if (_.isPlainObject(schema.items) && !_.isUndefined(schema.items.type)) {\n          type = schema.items.type;\n        } else {\n          type = 'object';\n        }\n      }\n\n      if (!_.isUndefined(schema.default)) {\n        options += optionHtml('Default', schema.default);\n      }\n\n      switch (type) {\n      case 'string':\n        if (schema.minLength) {\n          options += optionHtml('Min. Length', schema.minLength);\n        }\n\n        if (schema.maxLength) {\n          options += optionHtml('Max. Length', schema.maxLength);\n        }\n\n        if (schema.pattern) {\n          options += optionHtml('Reg. Exp.', schema.pattern);\n        }\n        break;\n      case 'integer':\n      case 'number':\n        if (schema.minimum) {\n          options += optionHtml('Min. Value', schema.minimum);\n        }\n\n        if (schema.exclusiveMinimum) {\n          options += optionHtml('Exclusive Min.', 'true');\n        }\n\n        if (schema.maximum) {\n          options += optionHtml('Max. Value', schema.maximum);\n        }\n\n        if (schema.exclusiveMaximum) {\n          options += optionHtml('Exclusive Max.', 'true');\n        }\n\n        if (schema.multipleOf) {\n          options += optionHtml('Multiple Of', schema.multipleOf);\n        }\n\n        break;\n      }\n\n      if (isArray) {\n        if (schema.minItems) {\n          options += optionHtml('Min. Items', schema.minItems);\n        }\n\n        if (schema.maxItems) {\n          options += optionHtml('Max. Items', schema.maxItems);\n        }\n\n        if (schema.uniqueItems) {\n          options += optionHtml('Unique Items', 'true');\n        }\n\n        if (schema.collectionFormat) {\n          options += optionHtml('Coll. Format', schema.collectionFormat);\n        }\n      }\n\n      if (_.isUndefined(schema.items)) {\n        if (_.isArray(schema.enum)) {\n          var enumString;\n\n          if (type === 'number' || type === 'integer') {\n            enumString = schema.enum.join(', ');\n          } else {\n            enumString = '\"' + schema.enum.join('\", \"') + '\"';\n          }\n\n          options += optionHtml('Enum', enumString);\n        }\n      }\n\n      if (options.length > 0) {\n        html = '<span class=\"propWrap\">' + html + '<table class=\"optionsWrapper\"><tr><th colspan=\"2\">' + type + '</th></tr>' + options + '</table></span>';\n      }\n\n      return html;\n    }\n\n    function processModel(schema, name) {\n      var type = schema.type || 'object';\n      var isArray = schema.type === 'array';\n      var html = strongOpen + name + ' ' + (isArray ? '[' : '{') + strongClose;\n      var contents;\n\n      if (name) {\n        seenModels.push(name);\n      }\n\n      if (isArray) {\n        if (_.isArray(schema.items)) {\n          html += '<div>' + _.map(schema.items, function (item) {\n            var type = item.type || 'object';\n\n            if (_.isUndefined(item.$ref)) {\n              if (_.indexOf(['array', 'object'], type) > -1) {\n                if (type === 'object' && _.isUndefined(item.properties)) {\n                  return 'object';\n                } else {\n                  return addReference(item);\n                }\n              } else {\n                return primitiveToOptionsHTML(item, type);\n              }\n            } else {\n              return addReference(item, simpleRef(item.$ref));\n            }\n          }).join(',</div><div>');\n        } else if (_.isPlainObject(schema.items)) {\n          if (_.isUndefined(schema.items.$ref)) {\n            if (_.indexOf(['array', 'object'], schema.items.type || 'object') > -1) {\n              if ((_.isUndefined(schema.items.type) || schema.items.type === 'object') && _.isUndefined(schema.items.properties)) {\n                html += '<div>object</div>';\n              } else {\n                html += '<div>' + addReference(schema.items) + '</div>';\n              }\n            } else {\n              html += '<div>' + primitiveToOptionsHTML(schema.items, schema.items.type) + '</div>';\n            }\n          } else {\n            html += '<div>' + addReference(schema.items, simpleRef(schema.items.$ref)) + '</div>';\n          }\n        } else {\n          console.log('Array type\\'s \\'items\\' property is not an array or an object, cannot process');\n          html += '<div>object</div>';\n        }\n      } else {\n        if (schema.$ref) {\n          html += '<div>' + addReference(schema, name) + '</div>';\n        } else if (type === 'object') {\n          if (_.isPlainObject(schema.properties)) {\n            contents = _.map(schema.properties, function (property, name) {\n              var propertyIsRequired = (_.indexOf(schema.required, name) >= 0);\n              var cProperty = _.cloneDeep(property);\n\n              var requiredClass = propertyIsRequired ? 'required' : '';\n              var html = '<span class=\"propName ' + requiredClass + '\">' + name + '</span> (';\n              var model;\n\n              // Allow macro to set the default value\n              cProperty.default = modelPropertyMacro(cProperty);\n\n              // Resolve the schema (Handle nested schemas)\n              cProperty = resolveSchema(cProperty);\n\n              // We need to handle property references to primitives (Issue 339)\n              if (!_.isUndefined(cProperty.$ref)) {\n                model = models[simpleRef(cProperty.$ref)];\n\n                if (!_.isUndefined(model) && _.indexOf([undefined, 'array', 'object'], model.definition.type) === -1) {\n                  // Use referenced schema\n                  cProperty = resolveSchema(model.definition);\n                }\n              }\n\n              html += primitiveToHTML(cProperty);\n\n              if(!propertyIsRequired) {\n                html += ', <span class=\"propOptKey\">optional</span>';\n              }\n\n              if(property.readOnly) {\n                  html += ', <span class=\"propReadOnly\">read only</span>';\n              }\n\n              html += ')';\n\n              return '<div' + (property.readOnly ? ' class=\"readOnly\"' : '') + '>' + primitiveToOptionsHTML(cProperty, html);\n            }).join(',</div>');\n          }\n\n          if (contents) {\n            html += contents + '</div>';\n          }\n        } else {\n          html += '<div>' + primitiveToOptionsHTML(schema, type) + '</div>';\n        }\n      }\n\n      return html + strongOpen + (isArray ? ']' : '}') + strongClose;\n    }\n\n  };\n\n  // copy-pasted from swagger-js\n  var schemaToJSON = function (schema, models, modelsToIgnore, modelPropertyMacro) {\n    // Resolve the schema (Handle nested schemas)\n    schema = resolveSchema(schema);\n\n    if(typeof modelPropertyMacro !== 'function') {\n      modelPropertyMacro = function(prop){\n        return (prop || {}).default;\n      };\n    }\n\n    modelsToIgnore= modelsToIgnore || {};\n\n    var type = schema.type || 'object';\n    var format = schema.format;\n    var model;\n    var output;\n\n    if (!_.isUndefined(schema.example)) {\n      output = schema.example;\n    } else if (_.isUndefined(schema.items) && _.isArray(schema.enum)) {\n      output = schema.enum[0];\n    }\n\n    if (_.isUndefined(output)) {\n      if (schema.$ref) {\n        model = models[simpleRef(schema.$ref)];\n\n        if (!_.isUndefined(model)) {\n          if (_.isUndefined(modelsToIgnore[model.name])) {\n            modelsToIgnore[model.name] = model;\n            output = schemaToJSON(model.definition, models, modelsToIgnore, modelPropertyMacro);\n            delete modelsToIgnore[model.name];\n          } else {\n            if (model.type === 'array') {\n              output = [];\n            } else {\n              output = {};\n            }\n          }\n        }\n      } else if (!_.isUndefined(schema.default)) {\n        output = schema.default;\n      } else if (type === 'string') {\n        if (format === 'date-time') {\n          output = new Date().toISOString();\n        } else if (format === 'date') {\n          output = new Date().toISOString().split('T')[0];\n        } else {\n          output = 'string';\n        }\n      } else if (type === 'integer') {\n        output = 0;\n      } else if (type === 'number') {\n        output = 0.0;\n      } else if (type === 'boolean') {\n        output = true;\n      } else if (type === 'object') {\n        output = {};\n\n        _.forEach(schema.properties, function (property, name) {\n          var cProperty = _.cloneDeep(property);\n\n          // Allow macro to set the default value\n          cProperty.default = modelPropertyMacro(property);\n\n          output[name] = schemaToJSON(cProperty, models, modelsToIgnore, modelPropertyMacro);\n        });\n      } else if (type === 'array') {\n        output = [];\n\n        if (_.isArray(schema.items)) {\n          _.forEach(schema.items, function (item) {\n            output.push(schemaToJSON(item, models, modelsToIgnore, modelPropertyMacro));\n          });\n        } else if (_.isPlainObject(schema.items)) {\n          output.push(schemaToJSON(schema.items, models, modelsToIgnore, modelPropertyMacro));\n        } else if (_.isUndefined(schema.items)) {\n          output.push({});\n        } else {\n          console.log('Array type\\'s \\'items\\' property is not an array or an object, cannot process');\n        }\n      }\n    }\n\n    return output;\n  };\n\n  // copy-pasted from swagger-js\n  var createJSONSample = function (value, modelsToIgnore) {\n    modelsToIgnore = modelsToIgnore || {};\n\n    modelsToIgnore[value.name] = value;\n\n    // Response support\n    if (value.examples && _.isPlainObject(value.examples)) {\n      value = _.cloneDeep(value);\n      var keys = Object.keys(value.examples);\n\n      _.forEach(keys, function(key) {\n        if(key.indexOf('application/json') === 0) {\n          var example = value.examples[key];\n          if (_.isString(example)) {\n            example = jsyaml.safeLoad(example);\n          }\n          value.definition.example = example;\n          return schemaToJSON(value.definition, example, modelsToIgnore, value.modelPropertyMacro);\n        }\n      });\n    }\n\n    if (value.examples) {\n      value = _.cloneDeep(value);\n      var example = value.examples;\n      if (_.isString(example)) {\n        example = jsyaml.safeLoad(example);\n      }\n      value.definition.example = example;\n      return schemaToJSON(value.definition, example, modelsToIgnore, value.modelPropertyMacro);\n    }\n\n    return schemaToJSON(value.definition, value.models, modelsToIgnore, value.modelPropertyMacro);\n  };\n\n  // copy-pasted from swagger-js\n  var getParameterModelSignature = function (type, definitions) {\n      var isPrimitive, listType;\n\n      if (type instanceof Array) {\n        listType = true;\n        type = type[0];\n      }\n\n      // Convert undefined to string of 'undefined'\n      if (typeof type === 'undefined') {\n        type = 'undefined';\n        isPrimitive = true;\n\n      } else if (definitions[type]){\n        // a model def exists?\n        type = definitions[type]; /* Model */\n        isPrimitive = false;\n\n      } else if (getInlineModel(type)) {\n        type = getInlineModel(type); /* Model */\n        isPrimitive = false;\n\n      } else {\n        // We default to primitive\n        isPrimitive = true;\n      }\n\n      if (isPrimitive) {\n        if (listType) {\n          return 'Array[' + type + ']';\n        } else {\n          return type.toString();\n        }\n      } else {\n        if (listType) {\n          return 'Array[' + getModelSignature(type.name, type.definition, type.models, type.modelPropertyMacro) + ']';\n        } else {\n          return getModelSignature(type.name, type.definition, type.models, type.modelPropertyMacro);\n        }\n      }\n  };\n\n  // copy-pasted from swagger-js\n  var createParameterJSONSample = function (type, models) {\n    var listType, sampleJson, innerType;\n    models = models || {};\n\n    listType = (type instanceof Array);\n    innerType = listType ? type[0] : type;\n\n    if(models[innerType]) {\n      sampleJson = createJSONSample(models[innerType]);\n    } else if (getInlineModel(innerType)){\n      sampleJson = createJSONSample(getInlineModel(innerType)); // may return null, if type isn't correct\n    }\n\n\n    if (sampleJson) {\n      sampleJson = listType ? [sampleJson] : sampleJson;\n\n      if (typeof sampleJson === 'string') {\n        return sampleJson;\n      } else if (_.isObject(sampleJson)) {\n        var t = sampleJson;\n\n        if (sampleJson instanceof Array && sampleJson.length > 0) {\n          t = sampleJson[0];\n        }\n\n        if (t.nodeName && typeof t === 'Node') {\n          var xmlString = new XMLSerializer().serializeToString(t);\n\n          return formatXml(xmlString);\n        } else {\n          return JSON.stringify(sampleJson, null, 2);\n        }\n      } else {\n        return sampleJson;\n      }\n    }\n  };\n\n  var wrapTag = function (name, value, attrs) {\n    var str, attributes;\n\n    attrs = attrs || [];\n\n    attributes = attrs.map(function (attr) {\n      return ' ' + attr.name + '=\"' + attr.value + '\"';\n    }).join('');\n\n    if (!name) {\n      return getErrorMessage('Node name is not provided');\n    }\n\n    str = [\n      '<', name,\n      attributes,\n      '>',\n      value,\n      '</', name, '>'\n    ];\n\n    return str.join('');\n  };\n\n  // Commenting this funtion as the names are now determined beforehand and the prefix part is exposed as a separate function | https://github.com/swagger-api/swagger-ui/issues/2577\n /** var getName = function (name, xml) {\n    var result = name || '';\n\n    xml = xml || {};\n\n    if (xml.name) {\n      result = xml.name;\n    }\n\n    if (xml.prefix) {\n      result = xml.prefix + ':' + result;\n    }\n\n    return result;\n  };\n  */\n\n  var getPrefix = function (name, xml) {\n    var result = name || '';\n\n    xml = xml || {};\n\n    if (xml.prefix) {\n      result = xml.prefix + ':' + result;\n    }\n\n    return result;\n  };\n\n  var getNamespace = function (xml) {\n    var namespace = '';\n    var name = 'xmlns';\n\n    xml = xml || {};\n\n    if (xml.namespace) {\n      namespace = xml.namespace;\n    } else {\n      return namespace;\n    }\n\n    if (xml.prefix) {\n      name += ':' + xml.prefix;\n    }\n\n    return {\n      name: name,\n      value: namespace\n    };\n  };\n\n  var createArrayXML = function (descriptor) {\n    var name = descriptor.name;\n    var config = descriptor.config;\n    var definition = descriptor.definition;\n    var models = descriptor.models;\n    var value;\n    var items = definition.items;\n    var xml = definition.xml || {};\n    var namespace = getNamespace(xml);\n    var attributes = [];\n\n    if (!items) { return getErrorMessage(); }\n    var key = name;\n    // If there is a name specified for the array elements, use that for the array elements name | https://github.com/swagger-api/swagger-ui/issues/2577\n    if(items.xml && items.xml.name) {\n        key = items.xml.name;\n    }\n    value = createSchemaXML(key, items, models, config);\n    if (namespace) {\n      attributes.push(namespace);\n    }\n\n    if (xml.wrapped) {\n      value = wrapTag(name, value, attributes);\n    }\n\n    return value;\n  };\n\n  var getPrimitiveSignature = function (schema) {\n    var type, items;\n\n    schema = schema || {};\n    items = schema.items || {};\n    type = schema.type || '';\n\n    switch (type) {\n      case 'object': return 'Object is not a primitive';\n      case 'array' : return 'Array[' + (items.format || items.type) + ']';\n      default: return schema.format || type;\n    }\n  };\n\n  var createPrimitiveXML = function (descriptor) {\n    var name = descriptor.name;\n    var definition = descriptor.definition;\n    var primitivesMap = {\n      'string': {\n        'date': new Date(1).toISOString().split('T')[0],\n        'date-time' : new Date(1).toISOString(),\n        'default': 'string'\n      },\n      'integer': {\n        'default': 1\n      },\n      'number': {\n        'default': 1.1\n      },\n      'boolean': {\n        'default': true\n      }\n    };\n    var type = definition.type;\n    var format = definition.format;\n    var xml = definition.xml || {};\n    var namespace = getNamespace(xml);\n    var attributes = [];\n    var value;\n\n    if (_.keys(primitivesMap).indexOf(type) < 0) { return getErrorMessage(); }\n\n    if (_.isArray(definition.enum)){\n      value = definition.enum[0];\n    } else {\n      value = definition.example || primitivesMap[type][format] || primitivesMap[type].default;\n    }\n\n    if (xml.attribute) {\n      return {name: name, value: value};\n    }\n\n    if (namespace) {\n      attributes.push(namespace);\n    }\n\n    return wrapTag(name, value, attributes);\n  };\n\n  function createObjectXML (descriptor) {\n    var name = descriptor.name;\n    var definition = descriptor.definition;\n    var config = descriptor.config;\n    var models = descriptor.models;\n    var isParam = descriptor.config.isParam;\n    var serializedProperties;\n    var attrs = [];\n    var properties = definition.properties;\n    var additionalProperties = definition.additionalProperties;\n    var xml = definition.xml;\n    var namespace = getNamespace(xml);\n\n    if (namespace) {\n      attrs.push(namespace);\n    }\n\n    if (!properties && !additionalProperties) { return getErrorMessage(); }\n\n    properties = properties || {};\n\n    serializedProperties = _.map(properties, function (prop, key) {\n      var xml, result;\n\n      if (isParam && prop.readOnly) {\n        return '';\n      }\n\n      xml = prop.xml || {};\n      result = createSchemaXML(key, prop, models, config);\n\n      if (xml.attribute) {\n        attrs.push(result);\n        return '';\n      }\n\n      return result;\n    }).join('');\n\n    if (additionalProperties) {\n      serializedProperties += '<!-- additional elements allowed -->';\n    }\n\n    return wrapTag(name, serializedProperties, attrs);\n  }\n\n  function getInfiniteLoopMessage (name, loopTo) {\n    return wrapTag(name, '<!-- Infinite loop $ref:' + loopTo + ' -->');\n  }\n\n  function getErrorMessage (details) {\n    details = details ? ': ' + details : '';\n    return '<!-- invalid XML' + details + ' -->';\n  }\n\n  function createSchemaXML (name, definition, models, config) {\n    var $ref = _.isObject(definition) ? definition.$ref : null;\n    var output, index;\n    config = config || {};\n    config.modelsToIgnore = config.modelsToIgnore || [];\n\n    var descriptor = _.isString($ref) ? getDescriptorByRef($ref, name, models, config)\n        : getDescriptor(name, definition, models, config);\n\n    if (!descriptor) {\n      return getErrorMessage();\n    }\n\n    switch (descriptor.type) {\n      case 'array':\n        output = createArrayXML(descriptor); break;\n      case 'object':\n        output = createObjectXML(descriptor); break;\n      case 'loop':\n        output = getInfiniteLoopMessage(descriptor.name, descriptor.config.loopTo); break;\n      default:\n        output = createPrimitiveXML(descriptor);\n    }\n\n    if ($ref && descriptor.type !== 'loop') {\n      index = config.modelsToIgnore.indexOf($ref);\n      if (index > -1) {\n        config.modelsToIgnore.splice(index, 1);\n      }\n    }\n\n    return output;\n  }\n\n  function Descriptor (name, type, definition, models, config) {\n    if (arguments.length < 4) {\n      throw new Error();\n    }\n    this.config = config || {};\n    this.config.modelsToIgnore = this.config.modelsToIgnore || [];\n    // name is already set by getDescriptorByRef or getDescriptor function depending on the type. Only prefix, if present is needed to be set here | https://github.com/swagger-api/swagger-ui/issues/2577\n    this.name = getPrefix(name, definition.xml);\n    this.definition = definition;\n    this.models = models;\n    this.type = type;\n  }\n\n  function getDescriptorByRef($ref, name, models, config) {\n    var modelType = simpleRef($ref);\n    var model = models[modelType] || {};\n    var type = model.definition && model.definition.type ? model.definition.type : 'object';\n    // If model definition xml name is present, then that will be preferred over model name. This is the case of preferring XmlElement name over XmlRootElement name if XmlElement name is provided | https://github.com/swagger-api/swagger-ui/issues/2577\n    if(model.definition && model.definition.xml && model.definition.xml.name) {\n        name = name || model.definition.xml.name || model.name;\n    }\n    // else only model name will be considered for determination | https://github.com/swagger-api/swagger-ui/issues/2577\n    else {\n        name = name || model.name;\n    }\n\n    if (config.modelsToIgnore.indexOf($ref) > -1) {\n      type = 'loop';\n      config.loopTo = modelType;\n    } else {\n      config.modelsToIgnore.push($ref);\n    }\n\n    if (!model.definition) {\n      return null;\n    }\n    return new Descriptor(name, type, model.definition, models, config);\n  }\n\n  function getDescriptor (name, definition, models, config){\n    var type = definition.type || 'object';\n    // If definition xml name is present, then that will be preferred over name | https://github.com/swagger-api/swagger-ui/issues/2577\n    if(definition.xml && definition.xml.name) {\n        name = definition.xml.name || name;\n    }\n    if (!definition) {\n      return null;\n    }\n\n    return new Descriptor(name, type, definition, models, config);\n  }\n\n  function createXMLSample (name, definition, models, isParam) {\n    var prolog = '<?xml version=\"1.0\"?>';\n\n    return formatXml(prolog + createSchemaXML(name, definition, models, { isParam: isParam } ));\n  }\n\n  return {\n      getModelSignature: getModelSignature,\n      createJSONSample: createJSONSample,\n      getParameterModelSignature: getParameterModelSignature,\n      createParameterJSONSample: createParameterJSONSample,\n      createSchemaXML: createSchemaXML,\n      createXMLSample: createXMLSample,\n      getPrimitiveSignature: getPrimitiveSignature\n  };\n\n})();\n\n'use strict';\n\nSwaggerUi.Views.PopupView = Backbone.View.extend({\n    events: {\n        'click .api-popup-cancel': 'cancelClick'\n    },\n\n    template: Handlebars.templates.popup,\n    className: 'api-popup-dialog',\n\n    selectors: {\n        content: '.api-popup-content',\n        main   : '#swagger-ui-container'\n    },\n\n    initialize: function(){\n        this.$el.html(this.template(this.model));\n    },\n\n    render: function () {\n        this.$(this.selectors.content).append(this.model.content);\n        $(this.selectors.main).first().append(this.el);\n        this.showPopup();\n\n        return this;\n    },\n\n    showPopup: function () {\n        this.$el.show();\n    },\n\n    cancelClick: function () {\n        this.remove();\n    }\n\n});\n\n'use strict';\n\nSwaggerUi.Views.ResourceView = Backbone.View.extend({\n  initialize: function(opts) {\n    opts = opts || {};\n    this.router = opts.router;\n    this.auths = opts.auths;\n    if ('' === this.model.description) {\n      this.model.description = null;\n    }\n    if (this.model.description) {\n      this.model.summary = this.model.description;\n    }\n    this.number = 0;\n  },\n\n  render: function(){\n    var methods = {};\n\n\n    $(this.el).html(Handlebars.templates.resource(this.model));\n\n    // Render each operation\n    for (var i = 0; i < this.model.operationsArray.length; i++) {\n      var operation = this.model.operationsArray[i];\n      var counter = 0;\n      var id = operation.nickname;\n\n      while (typeof methods[id] !== 'undefined') {\n        id = id + '_' + counter;\n        counter += 1;\n      }\n\n      methods[id] = operation;\n\n      operation.nickname = id;\n      operation.parentId = this.model.id;\n      operation.definitions = this.model.definitions; // make Json Schema available for JSonEditor in this operation\n      this.addOperation(operation);\n    }\n\n    $('.toggleEndpointList', this.el).click(this.callDocs.bind(this, 'toggleEndpointListForResource'));\n    $('.collapseResource', this.el).click(this.callDocs.bind(this, 'collapseOperationsForResource'));\n    $('.expandResource', this.el).click(this.callDocs.bind(this, 'expandOperationsForResource'));\n\n    return this;\n  },\n\n  addOperation: function(operation) {\n\n    operation.number = this.number;\n\n    // Render an operation and add it to operations li\n    var operationView = new SwaggerUi.Views.OperationView({\n      model: operation,\n      router: this.router,\n      tagName: 'li',\n      className: 'endpoint',\n      swaggerOptions: this.options.swaggerOptions,\n      auths: this.auths\n    });\n\n    $('.endpoints', $(this.el)).append(operationView.render().el);\n\n    this.number++;\n\n  },\n  // Generic Event handler (`Docs` is global)\n\n\n  callDocs: function(fnName, e) {\n    e.preventDefault();\n    Docs[fnName](e.currentTarget.getAttribute('data-id'));\n  }\n});\n\n'use strict';\n\nSwaggerUi.Views.ResponseContentTypeView = Backbone.View.extend({\n  initialize: function(){},\n\n  render: function(){\n    this.model.responseContentTypeId = 'rct' + Math.random();\n    $(this.el).html(Handlebars.templates.response_content_type(this.model));\n    return this;\n  }\n});\n'use strict';\n\nSwaggerUi.Views.SignatureView = Backbone.View.extend({\n  events: {\n    'click a.description-link'       : 'switchToDescription',\n    'click a.snippet-link'           : 'switchToSnippet',\n    'mousedown .snippet_json'          : 'jsonSnippetMouseDown',\n    'mousedown .snippet_xml'          : 'xmlSnippetMouseDown'\n  },\n\n  initialize: function () {\n  },\n\n  render: function(){\n\n    $(this.el).html(Handlebars.templates.signature(this.model));\n\n    if (this.model.defaultRendering === 'model') {\n      this.switchToDescription();\n    } else {\n      this.switchToSnippet();\n    }\n\n    return this;\n  },\n\n  // handler for show signature\n  switchToDescription: function(e){\n    if (e) { e.preventDefault(); }\n\n    $('.snippet', $(this.el)).hide();\n    $('.description', $(this.el)).show();\n    $('.description-link', $(this.el)).addClass('selected');\n    $('.snippet-link', $(this.el)).removeClass('selected');\n  },\n\n  // handler for show sample\n  switchToSnippet: function(e){\n    if (e) { e.preventDefault(); }\n\n    $('.snippet', $(this.el)).show();\n    $('.description', $(this.el)).hide();\n    $('.snippet-link', $(this.el)).addClass('selected');\n    $('.description-link', $(this.el)).removeClass('selected');\n  },\n\n  // handler for snippet to text area\n  snippetToTextArea: function(val) {\n    var textArea = $('textarea', $(this.el.parentNode.parentNode.parentNode));\n\n    // Fix for bug in IE 10/11 which causes placeholder text to be copied to \"value\"\n    if ($.trim(textArea.val()) === '' || textArea.prop('placeholder') === textArea.val()) {\n      textArea.val(val);\n      // TODO move this code outside of the view and expose an event instead\n      if( this.model.jsonEditor && this.model.jsonEditor.isEnabled()){\n        this.model.jsonEditor.setValue(JSON.parse(this.model.sampleJSON));\n      }\n    }\n  },\n\n  jsonSnippetMouseDown: function (e) {\n    if (this.model.isParam) {\n      if (e) { e.preventDefault(); }\n\n      this.snippetToTextArea(this.model.sampleJSON);\n    }\n  },\n\n  xmlSnippetMouseDown: function (e) {\n    if (this.model.isParam) {\n      if (e) { e.preventDefault(); }\n\n      this.snippetToTextArea(this.model.sampleXML);\n    }\n  }\n});\n'use strict';\n\nSwaggerUi.Views.StatusCodeView = Backbone.View.extend({\n  initialize: function (opts) {\n    this.options = opts || {};\n    this.router = this.options.router;\n  },\n\n  render: function(){\n    var responseModel, responseModelView;\n    var value = this.router.api.models[this.model.responseModel];\n    $(this.el).html(Handlebars.templates.status_code(this.model));\n\n    if (this.router.api.models.hasOwnProperty(this.model.responseModel)) {\n      responseModel = {\n        sampleJSON: JSON.stringify(SwaggerUi.partials.signature.createJSONSample(value), void 0, 2),\n        sampleXML: this.model.isXML ? SwaggerUi.partials.signature.createXMLSample('', this.model.schema, this.router.api.models) : false,\n        isParam: false,\n        signature: SwaggerUi.partials.signature.getModelSignature(this.model.responseModel, value, this.router.api.models),\n        defaultRendering: this.model.defaultRendering\n      };\n    } else {\n      responseModel = {\n        signature: SwaggerUi.partials.signature.getPrimitiveSignature(this.model.schema)\n      };\n    }\n\n    responseModelView = new SwaggerUi.Views.SignatureView({model: responseModel, tagName: 'div'});\n    $('.model-signature', this.$el).append(responseModelView.render().el);\n    return this;\n  }\n});}).call(this);\n//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlbXBsYXRlcy5qcyIsImRvYy5qcyIsImVzNS1zaGltLmpzIiwiaGVscGVycy9oYW5kbGViYXJzLmpzIiwic2FuaXRpemUtaHRtbC5taW4uanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwiaW5kZXguanMiLCJsaWIvYXV0aC5qcyIsImxpYi9jbGllbnQuanMiLCJsaWIvaGVscGVycy5qcyIsImxpYi9odHRwLmpzIiwibGliL3Jlc29sdmVyLmpzIiwibGliL3NjaGVtYS1tYXJrdXAuanMiLCJsaWIvc3BlYy1jb252ZXJ0ZXIuanMiLCJsaWIvdHlwZXMvbW9kZWwuanMiLCJsaWIvdHlwZXMvb3BlcmF0aW9uLmpzIiwibGliL3R5cGVzL29wZXJhdGlvbkdyb3VwLmpzIiwibm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9idG9hL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2J1ZmZlci9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9idWZmZXIvbm9kZV9tb2R1bGVzL2Jhc2U2NC1qcy9saWIvYjY0LmpzIiwibm9kZV9tb2R1bGVzL2J1ZmZlci9ub2RlX21vZHVsZXMvaWVlZTc1NC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9idWZmZXIvbm9kZV9tb2R1bGVzL2lzLWFycmF5L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Nvb2tpZWphci9jb29raWVqYXIuanMiLCJub2RlX21vZHVsZXMvanMteWFtbC9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvY29tbW9uLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvZHVtcGVyLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvZXhjZXB0aW9uLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvbG9hZGVyLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvbWFyay5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sL3NjaGVtYS5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sL3NjaGVtYS9jb3JlLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvc2NoZW1hL2RlZmF1bHRfZnVsbC5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sL3NjaGVtYS9kZWZhdWx0X3NhZmUuanMiLCJub2RlX21vZHVsZXMvanMteWFtbC9saWIvanMteWFtbC9zY2hlbWEvZmFpbHNhZmUuanMiLCJub2RlX21vZHVsZXMvanMteWFtbC9saWIvanMteWFtbC9zY2hlbWEvanNvbi5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sL3R5cGUuanMiLCJub2RlX21vZHVsZXMvanMteWFtbC9saWIvanMteWFtbC90eXBlL2JpbmFyeS5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sL3R5cGUvYm9vbC5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sL3R5cGUvZmxvYXQuanMiLCJub2RlX21vZHVsZXMvanMteWFtbC9saWIvanMteWFtbC90eXBlL2ludC5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sL3R5cGUvanMvZnVuY3Rpb24uanMiLCJub2RlX21vZHVsZXMvanMteWFtbC9saWIvanMteWFtbC90eXBlL2pzL3JlZ2V4cC5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sL3R5cGUvanMvdW5kZWZpbmVkLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvdHlwZS9tYXAuanMiLCJub2RlX21vZHVsZXMvanMteWFtbC9saWIvanMteWFtbC90eXBlL21lcmdlLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvdHlwZS9udWxsLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvdHlwZS9vbWFwLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvdHlwZS9wYWlycy5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sL3R5cGUvc2VxLmpzIiwibm9kZV9tb2R1bGVzL2pzLXlhbWwvbGliL2pzLXlhbWwvdHlwZS9zZXQuanMiLCJub2RlX21vZHVsZXMvanMteWFtbC9saWIvanMteWFtbC90eXBlL3N0ci5qcyIsIm5vZGVfbW9kdWxlcy9qcy15YW1sL2xpYi9qcy15YW1sL3R5cGUvdGltZXN0YW1wLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvYXJyYXkvaW5kZXhPZi5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2FycmF5L2xhc3QuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9jaGFpbi9sb2Rhc2guanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9jb2xsZWN0aW9uL2VhY2guanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9jb2xsZWN0aW9uL2ZpbmQuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9jb2xsZWN0aW9uL2ZvckVhY2guanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9jb2xsZWN0aW9uL2luY2x1ZGVzLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvY29sbGVjdGlvbi9tYXAuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9kYXRlL25vdy5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2Z1bmN0aW9uL2JpbmQuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9mdW5jdGlvbi9yZXN0UGFyYW0uanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9MYXp5V3JhcHBlci5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL0xvZGFzaFdyYXBwZXIuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9hcnJheUNvcHkuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9hcnJheUVhY2guanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9hcnJheU1hcC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2FycmF5U29tZS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2Jhc2VBc3NpZ24uanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9iYXNlQ2FsbGJhY2suanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9iYXNlQ2xvbmUuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9iYXNlQ29weS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2Jhc2VDcmVhdGUuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9iYXNlRWFjaC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2Jhc2VGaW5kLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvYmFzZUZpbmRJbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2Jhc2VGb3IuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9iYXNlRm9ySW4uanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9iYXNlRm9yT3duLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvYmFzZUdldC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2Jhc2VJbmRleE9mLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvYmFzZUlzRXF1YWwuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9iYXNlSXNFcXVhbERlZXAuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9iYXNlSXNNYXRjaC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2Jhc2VMb2Rhc2guanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9iYXNlTWFwLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvYmFzZU1hdGNoZXMuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9iYXNlTWF0Y2hlc1Byb3BlcnR5LmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvYmFzZVByb3BlcnR5LmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvYmFzZVByb3BlcnR5RGVlcC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2Jhc2VTZXREYXRhLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvYmFzZVNsaWNlLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvYmFzZVRvU3RyaW5nLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvYmFzZVZhbHVlcy5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2JpbmFyeUluZGV4LmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvYmluYXJ5SW5kZXhCeS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2JpbmRDYWxsYmFjay5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2J1ZmZlckNsb25lLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvY29tcG9zZUFyZ3MuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9jb21wb3NlQXJnc1JpZ2h0LmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvY3JlYXRlQmFzZUVhY2guanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9jcmVhdGVCYXNlRm9yLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvY3JlYXRlQmluZFdyYXBwZXIuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9jcmVhdGVDdG9yV3JhcHBlci5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2NyZWF0ZUZpbmQuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9jcmVhdGVGb3JFYWNoLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvY3JlYXRlSHlicmlkV3JhcHBlci5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2NyZWF0ZVBhcnRpYWxXcmFwcGVyLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvY3JlYXRlV3JhcHBlci5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2VxdWFsQXJyYXlzLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvZXF1YWxCeVRhZy5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2VxdWFsT2JqZWN0cy5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2dldERhdGEuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9nZXRGdW5jTmFtZS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2dldExlbmd0aC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2dldE1hdGNoRGF0YS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2dldE5hdGl2ZS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2luZGV4T2ZOYU4uanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9pbml0Q2xvbmVBcnJheS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2luaXRDbG9uZUJ5VGFnLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvaW5pdENsb25lT2JqZWN0LmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvaXNBcnJheUxpa2UuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9pc0hvc3RPYmplY3QuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9pc0luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvaXNJdGVyYXRlZUNhbGwuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9pc0tleS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2lzTGF6aWFibGUuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9pc0xlbmd0aC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2lzT2JqZWN0TGlrZS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL2lzU3RyaWN0Q29tcGFyYWJsZS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL21lcmdlRGF0YS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL21ldGFNYXAuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9yZWFsTmFtZXMuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9yZW9yZGVyLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvcmVwbGFjZUhvbGRlcnMuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC9zZXREYXRhLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvaW50ZXJuYWwvc2hpbUtleXMuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9pbnRlcm5hbC90b09iamVjdC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL3RvUGF0aC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2ludGVybmFsL3dyYXBwZXJDbG9uZS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2xhbmcvY2xvbmVEZWVwLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvbGFuZy9pc0FyZ3VtZW50cy5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2xhbmcvaXNBcnJheS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2xhbmcvaXNFbXB0eS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2xhbmcvaXNGdW5jdGlvbi5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2xhbmcvaXNOYXRpdmUuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9sYW5nL2lzT2JqZWN0LmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvbGFuZy9pc1BsYWluT2JqZWN0LmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvbGFuZy9pc1N0cmluZy5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L2xhbmcvaXNUeXBlZEFycmF5LmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvbGFuZy9pc1VuZGVmaW5lZC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L29iamVjdC9rZXlzLmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvb2JqZWN0L2tleXNJbi5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L29iamVjdC9wYWlycy5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L29iamVjdC92YWx1ZXMuanMiLCJub2RlX21vZHVsZXMvbG9kYXNoLWNvbXBhdC9zdXBwb3J0LmpzIiwibm9kZV9tb2R1bGVzL2xvZGFzaC1jb21wYXQvdXRpbGl0eS9pZGVudGl0eS5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L3V0aWxpdHkvbm9vcC5qcyIsIm5vZGVfbW9kdWxlcy9sb2Rhc2gtY29tcGF0L3V0aWxpdHkvcHJvcGVydHkuanMiLCJub2RlX21vZHVsZXMvcS9xLmpzIiwibm9kZV9tb2R1bGVzL3N1cGVyYWdlbnQvbGliL2NsaWVudC5qcyIsIm5vZGVfbW9kdWxlcy9zdXBlcmFnZW50L2xpYi9pcy1vYmplY3QuanMiLCJub2RlX21vZHVsZXMvc3VwZXJhZ2VudC9saWIvcmVxdWVzdC1iYXNlLmpzIiwibm9kZV9tb2R1bGVzL3N1cGVyYWdlbnQvbGliL3JlcXVlc3QuanMiLCJub2RlX21vZHVsZXMvc3VwZXJhZ2VudC9ub2RlX21vZHVsZXMvY29tcG9uZW50LWVtaXR0ZXIvaW5kZXguanMiLCJTd2FnZ2VyVWkuanMiLCJ1dGlscy91dGlscy5qcyIsInZpZXcvQXBpS2V5QXV0aE1vZGVsLmpzIiwidmlldy9BcGlLZXlBdXRoVmlldy5qcyIsInZpZXcvQXV0aEJ1dHRvblZpZXcuanMiLCJ2aWV3L0F1dGhzQ29sbGVjdGlvbi5qcyIsInZpZXcvQXV0aHNDb2xsZWN0aW9uVmlldy5qcyIsInZpZXcvQXV0aFZpZXcuanMiLCJ2aWV3L0Jhc2ljQXV0aE1vZGVsLmpzIiwidmlldy9CYXNpY0F1dGhWaWV3LmpzIiwidmlldy9Db250ZW50VHlwZVZpZXcuanMiLCJ2aWV3L0hlYWRlclZpZXcuanMiLCJ2aWV3L01haW5WaWV3LmpzIiwidmlldy9PYXV0aDJNb2RlbC5qcyIsInZpZXcvT2F1dGgyVmlldy5qcyIsInZpZXcvT3BlcmF0aW9uVmlldy5qcyIsInZpZXcvUGFyYW1ldGVyQ29udGVudFR5cGVWaWV3LmpzIiwidmlldy9QYXJhbWV0ZXJWaWV3LmpzIiwidmlldy9wYXJ0aWFscy9zaWduYXR1cmUuanMiLCJ2aWV3L1BvcHVwVmlldy5qcyIsInZpZXcvUmVzb3VyY2VWaWV3LmpzIiwidmlldy9SZXNwb25zZUNvbnRlbnRUeXBlVmlldy5qcyIsInZpZXcvU2lnbmF0dXJlVmlldy5qcyIsInZpZXcvU3RhdHVzQ29kZVZpZXcuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDMXhCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUN4TUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2poRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNuR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUNOQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNySkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4WEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5NEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM29CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDanZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbHlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbGpEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDUkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNSQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3SEE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeERBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDWkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbmdFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2g5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUNuS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNsVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQy9FQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUM1Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDcEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUM5RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDckRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUM1TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDcEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNwREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2hKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUMxRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQ2xGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDbjNCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzdMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUM3OUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FDM0VBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUNWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQzNFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6InN3YWdnZXItdWkuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBqc2hpbnQgaWdub3JlOnN0YXJ0ICovIFxuIHsoZnVuY3Rpb24oKSB7XG4gIHZhciB0ZW1wbGF0ZSA9IEhhbmRsZWJhcnMudGVtcGxhdGUsIHRlbXBsYXRlcyA9IEhhbmRsZWJhcnMudGVtcGxhdGVzID0gSGFuZGxlYmFycy50ZW1wbGF0ZXMgfHwge307XG50ZW1wbGF0ZXNbJ2FwaWtleV9hdXRoJ10gPSB0ZW1wbGF0ZSh7XCIxXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiBcIiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwia2V5X2F1dGhfX3ZhbHVlXFxcIj5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnZhbHVlIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvc3Bhbj5cXG5cIjtcbn0sXCIzXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgICAgICAgICAgICAgICAgPGlucHV0IHBsYWNlaG9sZGVyPVxcXCJhcGlfa2V5XFxcIiBjbGFzcz1cXFwiYXV0aF9pbnB1dCBpbnB1dF9hcGlLZXlfZW50cnlcXFwiIG5hbWU9XFxcImFwaUtleVxcXCIgdHlwZT1cXFwidGV4dFxcXCIvPlxcblwiO1xufSxcImNvbXBpbGVyXCI6WzcsXCI+PSA0LjAuMFwiXSxcIm1haW5cIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIjxkaXYgY2xhc3M9XFxcImtleV9pbnB1dF9jb250YWluZXJcXFwiPlxcbiAgICA8aDMgY2xhc3M9XFxcImF1dGhfX3RpdGxlXFxcIj5BcGkga2V5IGF1dGhvcml6YXRpb248L2gzPlxcbiAgICA8ZGl2IGNsYXNzPVxcXCJhdXRoX19kZXNjcmlwdGlvblxcXCI+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmRlc2NyaXB0aW9uIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvZGl2PlxcbiAgICA8ZGl2PlxcbiAgICAgICAgPGRpdiBjbGFzcz1cXFwia2V5X2F1dGhfX2ZpZWxkXFxcIj5cXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwia2V5X2F1dGhfX2xhYmVsXFxcIj5uYW1lOjwvc3Bhbj5cXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwia2V5X2F1dGhfX3ZhbHVlXFxcIj5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5uYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L3NwYW4+XFxuICAgICAgICA8L2Rpdj5cXG4gICAgICAgIDxkaXYgY2xhc3M9XFxcImtleV9hdXRoX19maWVsZFxcXCI+XFxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XFxcImtleV9hdXRoX19sYWJlbFxcXCI+aW46PC9zcGFuPlxcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVxcXCJrZXlfYXV0aF9fdmFsdWVcXFwiPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwW1wiaW5cIl0gOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvc3Bhbj5cXG4gICAgICAgIDwvZGl2PlxcbiAgICAgICAgPGRpdiBjbGFzcz1cXFwia2V5X2F1dGhfX2ZpZWxkXFxcIj5cXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwia2V5X2F1dGhfX2xhYmVsXFxcIj52YWx1ZTo8L3NwYW4+XFxuXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pc0xvZ291dCA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMSwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLnByb2dyYW0oMywgZGF0YSwgMCksXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiICAgICAgICA8L2Rpdj5cXG4gICAgPC9kaXY+XFxuPC9kaXY+XFxuXCI7XG59LFwidXNlRGF0YVwiOnRydWV9KTtcbnRlbXBsYXRlc1snYXV0aF9idXR0b24nXSA9IHRlbXBsYXRlKHtcImNvbXBpbGVyXCI6WzcsXCI+PSA0LjAuMFwiXSxcIm1haW5cIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIjxhIGNsYXNzPSdhdXRob3JpemVfX2J0bicgaHJlZj1cXFwiI1xcXCI+QXV0aG9yaXplPC9hPlxcblwiO1xufSxcInVzZURhdGFcIjp0cnVlfSk7XG50ZW1wbGF0ZXNbJ2F1dGhfYnV0dG9uX29wZXJhdGlvbiddID0gdGVtcGxhdGUoe1wiMVwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgcmV0dXJuIFwiICAgICAgICBhdXRob3JpemVfX2J0bl9vcGVyYXRpb25fbG9naW5cXG5cIjtcbn0sXCIzXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgICAgICAgIGF1dGhvcml6ZV9fYnRuX29wZXJhdGlvbl9sb2dvdXRcXG5cIjtcbn0sXCI1XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiBcIiAgICAgICAgPHVsIGNsYXNzPVxcXCJhdXRob3JpemUtc2NvcGVzXFxcIj5cXG5cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzLmVhY2guY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5zY29wZXMgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVhY2hcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oNiwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiICAgICAgICA8L3VsPlxcblwiO1xufSxcIjZcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIiAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XFxcImF1dGhvcml6ZV9fc2NvcGVcXFwiIHRpdGxlPVxcXCJcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5kZXNjcmlwdGlvbiA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxcIj5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5zY29wZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9saT5cXG5cIjtcbn0sXCJjb21waWxlclwiOls3LFwiPj0gNC4wLjBcIl0sXCJtYWluXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fTtcblxuICByZXR1cm4gXCI8ZGl2IGNsYXNzPVxcXCJhdXRob3JpemVfX2J0biBhdXRob3JpemVfX2J0bl9vcGVyYXRpb25cXG5cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlzTG9nb3V0IDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgxLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIucHJvZ3JhbSgzLCBkYXRhLCAwKSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXFwiPlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuc2NvcGVzIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSg1LCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L2Rpdj5cXG5cIjtcbn0sXCJ1c2VEYXRhXCI6dHJ1ZX0pO1xudGVtcGxhdGVzWydhdXRoX3ZpZXcnXSA9IHRlbXBsYXRlKHtcIjFcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIiAgICAgICAgICAgIDxidXR0b24gdHlwZT1cXFwiYnV0dG9uXFxcIiBjbGFzcz1cXFwiYXV0aF9fYnV0dG9uIGF1dGhfc3VibWl0X19idXR0b25cXFwiIGRhdGEtc3ctdHJhbnNsYXRlPkF1dGhvcml6ZTwvYnV0dG9uPlxcblwiO1xufSxcIjNcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIiAgICAgICAgICAgIDxidXR0b24gdHlwZT1cXFwiYnV0dG9uXFxcIiBjbGFzcz1cXFwiYXV0aF9fYnV0dG9uIGF1dGhfbG9nb3V0X19idXR0b25cXFwiIGRhdGEtc3ctdHJhbnNsYXRlPkxvZ291dDwvYnV0dG9uPlxcblwiO1xufSxcImNvbXBpbGVyXCI6WzcsXCI+PSA0LjAuMFwiXSxcIm1haW5cIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9O1xuXG4gIHJldHVybiBcIjxkaXYgY2xhc3M9XFxcImF1dGhfY29udGFpbmVyXFxcIj5cXG5cXG4gICAgPGRpdiBjbGFzcz1cXFwiYXV0aF9pbm5lclxcXCI+PC9kaXY+XFxuICAgIDxkaXYgY2xhc3M9XFxcImF1dGhfc3VibWl0XFxcIj5cXG5cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzLnVubGVzcy5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaXNMb2dvdXQgOiBkZXB0aDApLHtcIm5hbWVcIjpcInVubGVzc1wiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgxLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlzQXV0aG9yaXplZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMywgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiICAgIDwvZGl2PlxcblxcbjwvZGl2PlxcblwiO1xufSxcInVzZURhdGFcIjp0cnVlfSk7XG50ZW1wbGF0ZXNbJ2Jhc2ljX2F1dGgnXSA9IHRlbXBsYXRlKHtcIjFcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIiAtIGF1dGhvcml6ZWRcIjtcbn0sXCIzXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiBcIiAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwiYmFzaWNfYXV0aF9fdmFsdWVcXFwiPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGhlbHBlcnMuaGVscGVyTWlzc2luZykuY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC51c2VybmFtZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9zcGFuPlxcblwiO1xufSxcIjVcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIiAgICAgICAgICAgICAgICA8aW5wdXQgcmVxdWlyZWQgcGxhY2Vob2xkZXI9XFxcInVzZXJuYW1lXFxcIiBjbGFzcz1cXFwiYmFzaWNfYXV0aF9fdXNlcm5hbWUgYXV0aF9pbnB1dFxcXCIgbmFtZT1cXFwidXNlcm5hbWVcXFwiIHR5cGU9XFxcInRleHRcXFwiLz5cXG5cIjtcbn0sXCI3XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgICAgICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhdXRoX2xhYmVsXFxcIj5cXG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XFxcImJhc2ljX2F1dGhfX2xhYmVsXFxcIiBkYXRhLXN3LXRyYW5zbGF0ZT5wYXNzd29yZDo8L3NwYW4+XFxuICAgICAgICAgICAgICAgIDxpbnB1dCByZXF1aXJlZCBwbGFjZWhvbGRlcj1cXFwicGFzc3dvcmRcXFwiIGNsYXNzPVxcXCJiYXNpY19hdXRoX19wYXNzd29yZCBhdXRoX2lucHV0XFxcIiBuYW1lPVxcXCJwYXNzd29yZFxcXCIgdHlwZT1cXFwicGFzc3dvcmRcXFwiLz48L2xhYmVsPlxcbiAgICAgICAgICAgIDwvZGl2PlxcblwiO1xufSxcImNvbXBpbGVyXCI6WzcsXCI+PSA0LjAuMFwiXSxcIm1haW5cIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9O1xuXG4gIHJldHVybiBcIjxkaXYgY2xhc3M9J2Jhc2ljX2F1dGhfY29udGFpbmVyJz5cXG4gICAgPGgzIGNsYXNzPVxcXCJhdXRoX190aXRsZVxcXCI+QmFzaWMgYXV0aGVudGljYXRpb25cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlzTG9nb3V0IDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgxLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L2gzPlxcbiAgICA8Zm9ybSBjbGFzcz1cXFwiYmFzaWNfaW5wdXRfY29udGFpbmVyXFxcIj5cXG4gICAgICAgIDxkaXYgY2xhc3M9XFxcImF1dGhfX2Rlc2NyaXB0aW9uXFxcIj5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZGVzY3JpcHRpb24gOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9kaXY+XFxuICAgICAgICA8ZGl2IGNsYXNzPVxcXCJhdXRoX2xhYmVsXFxcIj5cXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cXFwiYmFzaWNfYXV0aF9fbGFiZWxcXFwiIGRhdGEtc3ctdHJhbnNsYXRlPnVzZXJuYW1lOjwvc3Bhbj5cXG5cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlzTG9nb3V0IDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgzLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIucHJvZ3JhbSg1LCBkYXRhLCAwKSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCIgICAgICAgIDwvZGl2PlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnMudW5sZXNzLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pc0xvZ291dCA6IGRlcHRoMCkse1wibmFtZVwiOlwidW5sZXNzXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDcsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIiAgICA8L2Zvcm0+XFxuPC9kaXY+XFxuXCI7XG59LFwidXNlRGF0YVwiOnRydWV9KTtcbnRlbXBsYXRlc1snY29udGVudF90eXBlJ10gPSB0ZW1wbGF0ZSh7XCIxXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiAoKHN0YWNrMSA9IGhlbHBlcnMuZWFjaC5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnByb2R1Y2VzIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlYWNoXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDIsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpO1xufSxcIjJcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIlx0PG9wdGlvbiB2YWx1ZT1cXFwiXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsZGVwdGgwLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxcIj5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSxkZXB0aDAse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L29wdGlvbj5cXG5cIjtcbn0sXCI0XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgIDxvcHRpb24gdmFsdWU9XFxcImFwcGxpY2F0aW9uL2pzb25cXFwiPmFwcGxpY2F0aW9uL2pzb248L29wdGlvbj5cXG5cIjtcbn0sXCJjb21waWxlclwiOls3LFwiPj0gNC4wLjBcIl0sXCJtYWluXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCI8bGFiZWwgZGF0YS1zdy10cmFuc2xhdGUgZm9yPVxcXCJcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5jb250ZW50VHlwZUlkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXFwiPlJlc3BvbnNlIENvbnRlbnQgVHlwZTwvbGFiZWw+XFxuPHNlbGVjdCBuYW1lPVxcXCJjb250ZW50VHlwZVxcXCIgaWQ9XFxcIlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmNvbnRlbnRUeXBlSWQgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIlxcXCI+XFxuXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5wcm9kdWNlcyA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMSwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLnByb2dyYW0oNCwgZGF0YSwgMCksXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9zZWxlY3Q+XFxuXCI7XG59LFwidXNlRGF0YVwiOnRydWV9KTtcbnRlbXBsYXRlc1snbWFpbiddID0gdGVtcGxhdGUoe1wiMVwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sIGFsaWFzMj1oZWxwZXJzLmhlbHBlck1pc3Npbmc7XG5cbiAgcmV0dXJuIFwiICA8ZGl2IGNsYXNzPVxcXCJpbmZvX3RpdGxlXFxcIj5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoKHN0YWNrMSA9IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pbmZvIDogZGVwdGgwKSkgIT0gbnVsbCA/IHN0YWNrMS50aXRsZSA6IHN0YWNrMSkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L2Rpdj5cXG4gIDxkaXYgY2xhc3M9XFxcImluZm9fZGVzY3JpcHRpb24gbWFya2Rvd25cXFwiPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLCgoc3RhY2sxID0gKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmluZm8gOiBkZXB0aDApKSAhPSBudWxsID8gc3RhY2sxLmRlc2NyaXB0aW9uIDogc3RhY2sxKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvZGl2PlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZXh0ZXJuYWxEb2NzIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgyLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCIgIFwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoKHN0YWNrMSA9IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pbmZvIDogZGVwdGgwKSkgIT0gbnVsbCA/IHN0YWNrMS50ZXJtc09mU2VydmljZVVybCA6IHN0YWNrMSkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oNCwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxuICBcIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKChzdGFjazEgPSAoKHN0YWNrMSA9IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pbmZvIDogZGVwdGgwKSkgIT0gbnVsbCA/IHN0YWNrMS5jb250YWN0IDogc3RhY2sxKSkgIT0gbnVsbCA/IHN0YWNrMS5uYW1lIDogc3RhY2sxKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSg2LCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG4gIFwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoKHN0YWNrMSA9ICgoc3RhY2sxID0gKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmluZm8gOiBkZXB0aDApKSAhPSBudWxsID8gc3RhY2sxLmNvbnRhY3QgOiBzdGFjazEpKSAhPSBudWxsID8gc3RhY2sxLnVybCA6IHN0YWNrMSkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oOCwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxuICBcIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKChzdGFjazEgPSAoKHN0YWNrMSA9IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pbmZvIDogZGVwdGgwKSkgIT0gbnVsbCA/IHN0YWNrMS5jb250YWN0IDogc3RhY2sxKSkgIT0gbnVsbCA/IHN0YWNrMS5lbWFpbCA6IHN0YWNrMSkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMTAsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIlxcbiAgXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLCgoc3RhY2sxID0gKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmluZm8gOiBkZXB0aDApKSAhPSBudWxsID8gc3RhY2sxLmxpY2Vuc2UgOiBzdGFjazEpLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDEyLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG5cIjtcbn0sXCIyXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCIgIDxwPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLCgoc3RhY2sxID0gKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmV4dGVybmFsRG9jcyA6IGRlcHRoMCkpICE9IG51bGwgPyBzdGFjazEuZGVzY3JpcHRpb24gOiBzdGFjazEpLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9wPlxcbiAgPGEgaHJlZj1cXFwiXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoKHN0YWNrMSA9IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5leHRlcm5hbERvY3MgOiBkZXB0aDApKSAhPSBudWxsID8gc3RhY2sxLnVybCA6IHN0YWNrMSkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxcIiB0YXJnZXQ9XFxcIl9ibGFua1xcXCI+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoKHN0YWNrMSA9IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5leHRlcm5hbERvY3MgOiBkZXB0aDApKSAhPSBudWxsID8gc3RhY2sxLnVybCA6IHN0YWNrMSkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9hPlxcblwiO1xufSxcIjRcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuIFwiPGRpdiBjbGFzcz1cXFwiaW5mb190b3NcXFwiPjxhIHRhcmdldD1cXFwiX2JsYW5rXFxcIiBocmVmPVxcXCJcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBoZWxwZXJzLmhlbHBlck1pc3NpbmcpLmNhbGwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwoKHN0YWNrMSA9IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pbmZvIDogZGVwdGgwKSkgIT0gbnVsbCA/IHN0YWNrMS50ZXJtc09mU2VydmljZVVybCA6IHN0YWNrMSkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxcIiBkYXRhLXN3LXRyYW5zbGF0ZT5UZXJtcyBvZiBzZXJ2aWNlPC9hPjwvZGl2PlwiO1xufSxcIjZcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuIFwiPGRpdj48ZGl2IGNsYXNzPSdpbmZvX25hbWUnIHN0eWxlPVxcXCJkaXNwbGF5OiBpbmxpbmVcXFwiIGRhdGEtc3ctdHJhbnNsYXRlPkNyZWF0ZWQgYnkgPC9kaXY+IFwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGhlbHBlcnMuaGVscGVyTWlzc2luZykuY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCgoc3RhY2sxID0gKChzdGFjazEgPSAoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaW5mbyA6IGRlcHRoMCkpICE9IG51bGwgPyBzdGFjazEuY29udGFjdCA6IHN0YWNrMSkpICE9IG51bGwgPyBzdGFjazEubmFtZSA6IHN0YWNrMSkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9kaXY+XCI7XG59LFwiOFwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sIGFsaWFzMj1oZWxwZXJzLmhlbHBlck1pc3Npbmc7XG5cbiAgcmV0dXJuIFwiPGRpdiBjbGFzcz0naW5mb191cmwnIGRhdGEtc3ctdHJhbnNsYXRlPlNlZSBtb3JlIGF0IDxhIGhyZWY9XFxcIlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKChzdGFjazEgPSAoKHN0YWNrMSA9IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pbmZvIDogZGVwdGgwKSkgIT0gbnVsbCA/IHN0YWNrMS5jb250YWN0IDogc3RhY2sxKSkgIT0gbnVsbCA/IHN0YWNrMS51cmwgOiBzdGFjazEpLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIlxcXCI+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoKHN0YWNrMSA9ICgoc3RhY2sxID0gKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmluZm8gOiBkZXB0aDApKSAhPSBudWxsID8gc3RhY2sxLmNvbnRhY3QgOiBzdGFjazEpKSAhPSBudWxsID8gc3RhY2sxLnVybCA6IHN0YWNrMSkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9hPjwvZGl2PlwiO1xufSxcIjEwXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCI8ZGl2IGNsYXNzPSdpbmZvX2VtYWlsJz48YSB0YXJnZXQ9XFxcIl9wYXJlbnRcXFwiIGhyZWY9XFxcIm1haWx0bzpcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLCgoc3RhY2sxID0gKChzdGFjazEgPSAoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaW5mbyA6IGRlcHRoMCkpICE9IG51bGwgPyBzdGFjazEuY29udGFjdCA6IHN0YWNrMSkpICE9IG51bGwgPyBzdGFjazEuZW1haWwgOiBzdGFjazEpLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIj9zdWJqZWN0PVwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKChzdGFjazEgPSAoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaW5mbyA6IGRlcHRoMCkpICE9IG51bGwgPyBzdGFjazEudGl0bGUgOiBzdGFjazEpLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIlxcXCIgZGF0YS1zdy10cmFuc2xhdGU+Q29udGFjdCB0aGUgZGV2ZWxvcGVyPC9hPjwvZGl2PlwiO1xufSxcIjEyXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCI8ZGl2IGNsYXNzPSdpbmZvX2xpY2Vuc2UnPjxhIHRhcmdldD1cXFwiX2JsYW5rXFxcIiBocmVmPSdcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLCgoc3RhY2sxID0gKChzdGFjazEgPSAoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaW5mbyA6IGRlcHRoMCkpICE9IG51bGwgPyBzdGFjazEubGljZW5zZSA6IHN0YWNrMSkpICE9IG51bGwgPyBzdGFjazEudXJsIDogc3RhY2sxKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKChzdGFjazEgPSAoKHN0YWNrMSA9IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pbmZvIDogZGVwdGgwKSkgIT0gbnVsbCA/IHN0YWNrMS5saWNlbnNlIDogc3RhY2sxKSkgIT0gbnVsbCA/IHN0YWNrMS5uYW1lIDogc3RhY2sxKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L2E+PC9kaXY+XCI7XG59LFwiMTRcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuIFwiICAsIDxzcGFuIHN0eWxlPVxcXCJmb250LXZhcmlhbnQ6IHNtYWxsLWNhcHNcXFwiIGRhdGEtc3ctdHJhbnNsYXRlPmFwaSB2ZXJzaW9uPC9zcGFuPjogXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKChzdGFjazEgPSAoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaW5mbyA6IGRlcHRoMCkpICE9IG51bGwgPyBzdGFjazEudmVyc2lvbiA6IHN0YWNrMSkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxuICAgIFwiO1xufSxcIjE2XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCIgICAgPHNwYW4gc3R5bGU9XFxcImZsb2F0OnJpZ2h0XFxcIj48YSB0YXJnZXQ9XFxcIl9ibGFua1xcXCIgaHJlZj1cXFwiXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAudmFsaWRhdG9yVXJsIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCIvZGVidWc/dXJsPVwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnVybCA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxcIj48aW1nIGlkPVxcXCJ2YWxpZGF0b3JcXFwiIHNyYz1cXFwiXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAudmFsaWRhdG9yVXJsIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI/dXJsPVwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnVybCA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxcIj48L2E+XFxuICAgIDwvc3Bhbj5cXG5cIjtcbn0sXCJjb21waWxlclwiOls3LFwiPj0gNC4wLjBcIl0sXCJtYWluXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fTtcblxuICByZXR1cm4gXCI8ZGl2IGNsYXNzPSdpbmZvJyBpZD0nYXBpX2luZm8nPlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaW5mbyA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMSwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9kaXY+XFxuPGRpdiBjbGFzcz0nY29udGFpbmVyJyBpZD0ncmVzb3VyY2VzX2NvbnRhaW5lcic+XFxuICA8ZGl2IGNsYXNzPSdhdXRob3JpemUtd3JhcHBlcic+PC9kaXY+XFxuXFxuICA8dWwgaWQ9J3Jlc291cmNlcyc+PC91bD5cXG5cXG4gIDxkaXYgY2xhc3M9XFxcImZvb3RlclxcXCI+XFxuICAgIDxoNCBzdHlsZT1cXFwiY29sb3I6ICM5OTlcXFwiPlsgPHNwYW4gc3R5bGU9XFxcImZvbnQtdmFyaWFudDogc21hbGwtY2Fwc1xcXCI+YmFzZSB1cmw8L3NwYW4+OiBcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBoZWxwZXJzLmhlbHBlck1pc3NpbmcpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5iYXNlUGF0aCA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxuXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLCgoc3RhY2sxID0gKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmluZm8gOiBkZXB0aDApKSAhPSBudWxsID8gc3RhY2sxLnZlcnNpb24gOiBzdGFjazEpLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDE0LCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJdXFxuXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC52YWxpZGF0b3JVcmwgOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDE2LCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCIgICAgPC9oND5cXG4gICAgPC9kaXY+XFxuPC9kaXY+XFxuXCI7XG59LFwidXNlRGF0YVwiOnRydWV9KTtcbnRlbXBsYXRlc1snb2F1dGgyJ10gPSB0ZW1wbGF0ZSh7XCIxXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiBcIjxwPkF1dGhvcml6YXRpb24gVVJMOiBcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmF1dGhvcml6YXRpb25VcmwgOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9wPlwiO1xufSxcIjNcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuIFwiPHA+VG9rZW4gVVJMOiBcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnRva2VuVXJsIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvcD5cIjtcbn0sXCI1XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgICAgICAgIDxwPlBsZWFzZSBpbnB1dCB1c2VybmFtZSBhbmQgcGFzc3dvcmQgZm9yIHBhc3N3b3JkIGZsb3cgYXV0aG9yaXphdGlvbjwvcD5cXG4gICAgICAgIDxmaWVsZHNldD5cXG4gICAgICAgICAgICA8ZGl2PjxsYWJlbD5Vc2VybmFtZTogPGlucHV0IGNsYXNzPVxcXCJvYXV0aC11c2VybmFtZVxcXCIgdHlwZT1cXFwidGV4dFxcXCIgbmFtZT1cXFwidXNlcm5hbWVcXFwiPjwvbGFiZWw+PC9kaXY+XFxuICAgICAgICAgICAgPGRpdj48bGFiZWw+UGFzc3dvcmQ6IDxpbnB1dCBjbGFzcz1cXFwib2F1dGgtcGFzc3dvcmRcXFwiIHR5cGU9XFxcInBhc3N3b3JkXFxcIiBuYW1lPVxcXCJwYXNzd29yZFxcXCI+PC9sYWJlbD48L2Rpdj5cXG4gICAgICAgIDwvZmllbGRzZXQ+XFxuXCI7XG59LFwiN1wiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMTtcblxuICByZXR1cm4gXCIgICAgICAgIDxwPlNldHVwIGNsaWVudCBhdXRoZW50aWNhdGlvbi5cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5yZXF1aXJlQ2xpZW50QXV0aGVudGljYWl0b24gOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDgsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvcD5cXG4gICAgICAgIDxmaWVsZHNldD5cXG4gICAgICAgICAgICA8ZGl2PjxsYWJlbD5UeXBlOlxcbiAgICAgICAgICAgICAgICA8c2VsZWN0IGNsYXNzPVxcXCJvYXV0aC1jbGllbnQtYXV0aGVudGljYXRpb24tdHlwZVxcXCIgbmFtZT1cXFwiY2xpZW50LWF1dGhlbnRpY2F0aW9uLXR5cGVcXFwiPlxcbiAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cXFwibm9uZVxcXCIgc2VsZWN0ZWQ+Tm9uZSBvciBvdGhlcjwvb3B0aW9uPlxcbiAgICAgICAgICAgICAgICAgICAgPG9wdGlvbiB2YWx1ZT1cXFwiYmFzaWNcXFwiPkJhc2ljIGF1dGg8L29wdGlvbj5cXG4gICAgICAgICAgICAgICAgICAgIDxvcHRpb24gdmFsdWU9XFxcInJlcXVlc3QtYm9keVxcXCI+UmVxdWVzdCBib2R5PC9vcHRpb24+XFxuICAgICAgICAgICAgICAgIDwvc2VsZWN0PlxcbiAgICAgICAgICAgIDwvbGFiZWw+PC9kaXY+XFxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cXFwib2F1dGgtY2xpZW50LWF1dGhlbnRpY2F0aW9uXFxcIiBoaWRkZW4+XFxuICAgICAgICAgICAgICAgIDxkaXY+PGxhYmVsPkNsaWVudElkOiA8aW5wdXQgY2xhc3M9XFxcIm9hdXRoLWNsaWVudC1pZFxcXCIgdHlwZT1cXFwidGV4dFxcXCIgbmFtZT1cXFwiY2xpZW50LWlkXFxcIj48L2xhYmVsPjwvZGl2PlxcbiAgICAgICAgICAgICAgICA8ZGl2PjxsYWJlbD5TZWNyZXQ6IDxpbnB1dCBjbGFzcz1cXFwib2F1dGgtY2xpZW50LXNlY3JldFxcXCIgdHlwZT1cXFwidGV4dFxcXCIgbmFtZT1cXFwiY2xpZW50LXNlY3JldFxcXCI+PC9sYWJlbD48L2Rpdj5cXG4gICAgICAgICAgICA8L2Rpdj5cXG4gICAgICAgIDwvZmllbGRzZXQ+XFxuXCI7XG59LFwiOFwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgcmV0dXJuIFwiKFJlcXVpcmVkKVwiO1xufSxcIjEwXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCIgICAgICAgICAgICA8bGk+XFxuICAgICAgICAgICAgICAgIDxpbnB1dCBjbGFzcz1cXFwib2F1dGgtc2NvcGVcXFwiIHR5cGU9XFxcImNoZWNrYm94XFxcIiBkYXRhLXNjb3BlPVxcXCJcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5zY29wZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxcIiBvYXV0aHR5cGU9XFxcIlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLk9BdXRoU2NoZW1lS2V5IDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXFwiLz5cXG4gICAgICAgICAgICAgICAgPGxhYmVsPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnNjb3BlIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L2xhYmVsPjxici8+XFxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVxcXCJhcGktc2NvcGUtZGVzY1xcXCI+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZGVzY3JpcHRpb24gOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuT0F1dGhTY2hlbWVLZXkgOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDExLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCIgICAgICAgICAgICAgICAgPC9zcGFuPlxcbiAgICAgICAgICAgIDwvbGk+XFxuXCI7XG59LFwiMTFcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuIFwiICAgICAgICAgICAgICAgICAgICAgICAgKFwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGhlbHBlcnMuaGVscGVyTWlzc2luZykuY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5PQXV0aFNjaGVtZUtleSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiKVxcblwiO1xufSxcImNvbXBpbGVyXCI6WzcsXCI+PSA0LjAuMFwiXSxcIm1haW5cIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIjxkaXY+XFxuICAgIDxoMyBjbGFzcz1cXFwiYXV0aF9fdGl0bGVcXFwiPk9BdXRoMi4wPC9oMz5cXG4gICAgPHA+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmRlc2NyaXB0aW9uIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvcD5cXG4gICAgXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5hdXRob3JpemF0aW9uVXJsIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgxLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG4gICAgXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC50b2tlblVybCA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMywgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxuICAgIDxwPmZsb3c6IFwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmZsb3cgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvcD5cXG5cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlzUGFzc3dvcmRGbG93IDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSg1LCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmNsaWVudEF1dGhlbnRpY2F0aW9uIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSg3LCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCIgICAgPHA+PHN0cm9uZz4gXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuYXBwTmFtZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiIDwvc3Ryb25nPiBBUEkgcmVxdWlyZXMgdGhlIGZvbGxvd2luZyBzY29wZXMuIFNlbGVjdCB3aGljaCBvbmVzIHlvdSB3YW50IHRvIGdyYW50IHRvIFN3YWdnZXIgVUkuPC9wPlxcbiAgICA8cD5TY29wZXMgYXJlIHVzZWQgdG8gZ3JhbnQgYW4gYXBwbGljYXRpb24gZGlmZmVyZW50IGxldmVscyBvZiBhY2Nlc3MgdG8gZGF0YSBvbiBiZWhhbGYgb2YgdGhlIGVuZCB1c2VyLiBFYWNoIEFQSSBtYXkgZGVjbGFyZSBvbmUgb3IgbW9yZSBzY29wZXMuXFxuICAgICAgICA8YSBocmVmPVxcXCIjXFxcIj5MZWFybiBob3cgdG8gdXNlPC9hPlxcbiAgICA8L3A+XFxuICAgIDx1bCBjbGFzcz1cXFwiYXBpLXBvcHVwLXNjb3Blc1xcXCI+XFxuXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVycy5lYWNoLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5zY29wZXMgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVhY2hcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMTAsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIiAgICA8L3VsPlxcbjwvZGl2PlwiO1xufSxcInVzZURhdGFcIjp0cnVlfSk7XG50ZW1wbGF0ZXNbJ29wZXJhdGlvbiddID0gdGVtcGxhdGUoe1wiMVwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgcmV0dXJuIFwiZGVwcmVjYXRlZFwiO1xufSxcIjNcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIiAgICAgICAgICAgIDxoND48c3BhbiBkYXRhLXN3LXRyYW5zbGF0ZT5XYXJuaW5nOiBEZXByZWNhdGVkPC9zcGFuPjwvaDQ+XFxuXCI7XG59LFwiNVwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMTtcblxuICByZXR1cm4gXCIgICAgICAgIDxoND48c3BhbiBkYXRhLXN3LXRyYW5zbGF0ZT5JbXBsZW1lbnRhdGlvbiBOb3Rlczwvc3Bhbj48L2g0PlxcbiAgICAgICAgPGRpdiBjbGFzcz1cXFwibWFya2Rvd25cXFwiPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBoZWxwZXJzLmhlbHBlck1pc3NpbmcpLmNhbGwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZGVzY3JpcHRpb24gOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9kaXY+XFxuXCI7XG59LFwiN1wiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgcmV0dXJuIFwiICAgICAgICAgICAgPGRpdiBjbGFzcz0nYXV0aG9yaXplLXdyYXBwZXIgYXV0aG9yaXplLXdyYXBwZXJfb3BlcmF0aW9uJz48L2Rpdj5cXG5cIjtcbn0sXCI5XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fTtcblxuICByZXR1cm4gXCIgICAgICAgICAgPGRpdiBjbGFzcz1cXFwicmVzcG9uc2UtY2xhc3NcXFwiPlxcbiAgICAgICAgICAgIDxoND48c3BhbiBkYXRhLXN3LXRyYW5zbGF0ZT5SZXNwb25zZSBDbGFzczwvc3Bhbj4gKDxzcGFuIGRhdGEtc3ctdHJhbnNsYXRlPlN0YXR1czwvc3Bhbj4gXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuc3VjY2Vzc0NvZGUgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIik8L2g0PlxcbiAgICAgICAgICAgICAgXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5zdWNjZXNzRGVzY3JpcHRpb24gOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDEwLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG4gICAgICAgICAgICA8cD48c3BhbiBjbGFzcz1cXFwibW9kZWwtc2lnbmF0dXJlXFxcIiAvPjwvcD5cXG4gICAgICAgICAgICA8YnIvPlxcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XFxcInJlc3BvbnNlLWNvbnRlbnQtdHlwZVxcXCIgLz5cXG4gICAgICAgICAgICA8L2Rpdj5cXG5cIjtcbn0sXCIxMFwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMTtcblxuICByZXR1cm4gXCI8ZGl2IGNsYXNzPVxcXCJtYXJrZG93blxcXCI+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGhlbHBlcnMuaGVscGVyTWlzc2luZykuY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5zdWNjZXNzRGVzY3JpcHRpb24gOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9kaXY+XCI7XG59LFwiMTJcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuIFwiICAgICAgICAgIDxoNCBkYXRhLXN3LXRyYW5zbGF0ZT5IZWFkZXJzPC9oND5cXG4gICAgICAgICAgPHRhYmxlIGNsYXNzPVxcXCJoZWFkZXJzXFxcIj5cXG4gICAgICAgICAgICA8dGhlYWQ+XFxuICAgICAgICAgICAgICA8dHI+XFxuICAgICAgICAgICAgICAgIDx0aCBzdHlsZT1cXFwid2lkdGg6IDEwMHB4OyBtYXgtd2lkdGg6IDEwMHB4XFxcIiBkYXRhLXN3LXRyYW5zbGF0ZT5IZWFkZXI8L3RoPlxcbiAgICAgICAgICAgICAgICA8dGggc3R5bGU9XFxcIndpZHRoOiAzMTBweDsgbWF4LXdpZHRoOiAzMTBweFxcXCIgZGF0YS1zdy10cmFuc2xhdGU+RGVzY3JpcHRpb248L3RoPlxcbiAgICAgICAgICAgICAgICA8dGggc3R5bGU9XFxcIndpZHRoOiAyMDBweDsgbWF4LXdpZHRoOiAyMDBweFxcXCIgZGF0YS1zdy10cmFuc2xhdGU+VHlwZTwvdGg+XFxuICAgICAgICAgICAgICAgIDx0aCBzdHlsZT1cXFwid2lkdGg6IDMyMHB4OyBtYXgtd2lkdGg6IDMyMHB4XFxcIiBkYXRhLXN3LXRyYW5zbGF0ZT5PdGhlcjwvdGg+XFxuICAgICAgICAgICAgICA8L3RyPlxcbiAgICAgICAgICAgIDwvdGhlYWQ+XFxuICAgICAgICAgICAgPHRib2R5PlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnMuZWFjaC5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmhlYWRlcnMgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVhY2hcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMTMsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIiAgICAgICAgICAgIDwvdGJvZHk+XFxuICAgICAgICAgIDwvdGFibGU+XFxuXCI7XG59LFwiMTNcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGhlbHBlciwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sIGFsaWFzMj1oZWxwZXJzLmhlbHBlck1pc3Npbmc7XG5cbiAgcmV0dXJuIFwiICAgICAgICAgICAgICA8dHI+XFxuICAgICAgICAgICAgICAgIDx0ZD5cIlxuICAgICsgY29udGFpbmVyLmVzY2FwZUV4cHJlc3Npb24oKChoZWxwZXIgPSAoaGVscGVyID0gaGVscGVycy5rZXkgfHwgKGRhdGEgJiYgZGF0YS5rZXkpKSAhPSBudWxsID8gaGVscGVyIDogYWxpYXMyKSwodHlwZW9mIGhlbHBlciA9PT0gXCJmdW5jdGlvblwiID8gaGVscGVyLmNhbGwoYWxpYXMxLHtcIm5hbWVcIjpcImtleVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSA6IGhlbHBlcikpKVxuICAgICsgXCI8L3RkPlxcbiAgICAgICAgICAgICAgICA8dGQ+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmRlc2NyaXB0aW9uIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvdGQ+XFxuICAgICAgICAgICAgICAgIDx0ZD5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC50eXBlIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L3RkPlxcbiAgICAgICAgICAgICAgICA8dGQ+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAub3RoZXIgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvdGQ+XFxuICAgICAgICAgICAgICA8L3RyPlxcblwiO1xufSxcIjE1XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgICAgICAgICAgPGg0IGRhdGEtc3ctdHJhbnNsYXRlPlBhcmFtZXRlcnM8L2g0PlxcbiAgICAgICAgICA8dGFibGUgY2xhc3M9J2Z1bGx3aWR0aCBwYXJhbWV0ZXJzJz5cXG4gICAgICAgICAgPHRoZWFkPlxcbiAgICAgICAgICAgIDx0cj5cXG4gICAgICAgICAgICA8dGggc3R5bGU9XFxcIndpZHRoOiAxMDBweDsgbWF4LXdpZHRoOiAxMDBweFxcXCIgZGF0YS1zdy10cmFuc2xhdGU+UGFyYW1ldGVyPC90aD5cXG4gICAgICAgICAgICA8dGggc3R5bGU9XFxcIndpZHRoOiAzMTBweDsgbWF4LXdpZHRoOiAzMTBweFxcXCIgZGF0YS1zdy10cmFuc2xhdGU+VmFsdWU8L3RoPlxcbiAgICAgICAgICAgIDx0aCBzdHlsZT1cXFwid2lkdGg6IDIwMHB4OyBtYXgtd2lkdGg6IDIwMHB4XFxcIiBkYXRhLXN3LXRyYW5zbGF0ZT5EZXNjcmlwdGlvbjwvdGg+XFxuICAgICAgICAgICAgPHRoIHN0eWxlPVxcXCJ3aWR0aDogMTAwcHg7IG1heC13aWR0aDogMTAwcHhcXFwiIGRhdGEtc3ctdHJhbnNsYXRlPlBhcmFtZXRlciBUeXBlPC90aD5cXG4gICAgICAgICAgICA8dGggc3R5bGU9XFxcIndpZHRoOiAyMjBweDsgbWF4LXdpZHRoOiAyMzBweFxcXCIgZGF0YS1zdy10cmFuc2xhdGU+RGF0YSBUeXBlPC90aD5cXG4gICAgICAgICAgICA8L3RyPlxcbiAgICAgICAgICA8L3RoZWFkPlxcbiAgICAgICAgICA8dGJvZHkgY2xhc3M9XFxcIm9wZXJhdGlvbi1wYXJhbXNcXFwiPlxcblxcbiAgICAgICAgICA8L3Rib2R5PlxcbiAgICAgICAgICA8L3RhYmxlPlxcblwiO1xufSxcIjE3XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgICAgICAgICAgPGRpdiBzdHlsZT0nbWFyZ2luOjA7cGFkZGluZzowO2Rpc3BsYXk6aW5saW5lJz48L2Rpdj5cXG4gICAgICAgICAgPGg0IGRhdGEtc3ctdHJhbnNsYXRlPlJlc3BvbnNlIE1lc3NhZ2VzPC9oND5cXG4gICAgICAgICAgPHRhYmxlIGNsYXNzPSdmdWxsd2lkdGggcmVzcG9uc2UtbWVzc2FnZXMnPlxcbiAgICAgICAgICAgIDx0aGVhZD5cXG4gICAgICAgICAgICA8dHI+XFxuICAgICAgICAgICAgICA8dGggZGF0YS1zdy10cmFuc2xhdGU+SFRUUCBTdGF0dXMgQ29kZTwvdGg+XFxuICAgICAgICAgICAgICA8dGggZGF0YS1zdy10cmFuc2xhdGU+UmVhc29uPC90aD5cXG4gICAgICAgICAgICAgIDx0aCBkYXRhLXN3LXRyYW5zbGF0ZT5SZXNwb25zZSBNb2RlbDwvdGg+XFxuICAgICAgICAgICAgICA8dGggZGF0YS1zdy10cmFuc2xhdGU+SGVhZGVyczwvdGg+XFxuICAgICAgICAgICAgPC90cj5cXG4gICAgICAgICAgICA8L3RoZWFkPlxcbiAgICAgICAgICAgIDx0Ym9keSBjbGFzcz1cXFwib3BlcmF0aW9uLXN0YXR1c1xcXCI+XFxuICAgICAgICAgICAgPC90Ym9keT5cXG4gICAgICAgICAgPC90YWJsZT5cXG5cIjtcbn0sXCIxOVwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgcmV0dXJuIFwiXCI7XG59LFwiMjFcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIiAgICAgICAgICA8ZGl2IGNsYXNzPSdzYW5kYm94X2hlYWRlcic+XFxuICAgICAgICAgICAgPGlucHV0IGNsYXNzPSdzdWJtaXQnIHR5cGU9J3N1Ym1pdCcgdmFsdWU9J1RyeSBpdCBvdXQhJyBkYXRhLXN3LXRyYW5zbGF0ZS8+XFxuICAgICAgICAgICAgPGEgaHJlZj0nIycgY2xhc3M9J3Jlc3BvbnNlX2hpZGVyJyBzdHlsZT0nZGlzcGxheTpub25lJyBkYXRhLXN3LXRyYW5zbGF0ZT5IaWRlIFJlc3BvbnNlPC9hPlxcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPSdyZXNwb25zZV90aHJvYmJlcicgc3R5bGU9J2Rpc3BsYXk6bm9uZSc+PC9zcGFuPlxcbiAgICAgICAgICA8L2Rpdj5cXG5cIjtcbn0sXCIyM1wiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgcmV0dXJuIFwiICAgICAgICAgIDxoNCBkYXRhLXN3LXRyYW5zbGF0ZT5SZXF1ZXN0IEhlYWRlcnM8L2g0PlxcbiAgICAgICAgICA8ZGl2IGNsYXNzPSdibG9jayByZXF1ZXN0X2hlYWRlcnMnPjwvZGl2PlxcblwiO1xufSxcImNvbXBpbGVyXCI6WzcsXCI+PSA0LjAuMFwiXSxcIm1haW5cIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nLCBhbGlhczM9Y29udGFpbmVyLmVzY2FwZUV4cHJlc3Npb247XG5cbiAgcmV0dXJuIFwiICA8dWwgY2xhc3M9J29wZXJhdGlvbnMnID5cXG4gICAgPGxpIGNsYXNzPSdcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5tZXRob2QgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIiBvcGVyYXRpb24nIGlkPSdcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5wYXJlbnRJZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiX1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLm5pY2tuYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInPlxcbiAgICAgIDxkaXYgY2xhc3M9J2hlYWRpbmcnPlxcbiAgICAgICAgPGgzPlxcbiAgICAgICAgICA8c3BhbiBjbGFzcz0naHR0cF9tZXRob2QnPlxcbiAgICAgICAgICA8YSBocmVmPScjIS9cIlxuICAgICsgYWxpYXMzKChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5lbmNvZGVkUGFyZW50SWQgOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKVxuICAgICsgXCIvXCJcbiAgICArIGFsaWFzMygoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAubmlja25hbWUgOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKVxuICAgICsgXCInIGNsYXNzPVxcXCJ0b2dnbGVPcGVyYXRpb25cXFwiPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLm1ldGhvZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9hPlxcbiAgICAgICAgICA8L3NwYW4+XFxuICAgICAgICAgIDxzcGFuIGNsYXNzPSdwYXRoJz5cXG4gICAgICAgICAgPGEgaHJlZj0nIyEvXCJcbiAgICArIGFsaWFzMygoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZW5jb2RlZFBhcmVudElkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSlcbiAgICArIFwiL1wiXG4gICAgKyBhbGlhczMoKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLm5pY2tuYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSlcbiAgICArIFwiJyBjbGFzcz1cXFwidG9nZ2xlT3BlcmF0aW9uIFwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZGVwcmVjYXRlZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMSwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxcIj5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5wYXRoIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L2E+XFxuICAgICAgICAgIDwvc3Bhbj5cXG4gICAgICAgIDwvaDM+XFxuICAgICAgICA8dWwgY2xhc3M9J29wdGlvbnMnPlxcbiAgICAgICAgICA8bGk+XFxuICAgICAgICAgIDxhIGhyZWY9JyMhL1wiXG4gICAgKyBhbGlhczMoKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmVuY29kZWRQYXJlbnRJZCA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpXG4gICAgKyBcIi9cIlxuICAgICsgYWxpYXMzKChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5uaWNrbmFtZSA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpXG4gICAgKyBcIicgY2xhc3M9XFxcInRvZ2dsZU9wZXJhdGlvblxcXCI+PHNwYW4gY2xhc3M9XFxcIm1hcmtkb3duXFxcIj5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5zdW1tYXJ5IDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L3NwYW4+PC9hPlxcbiAgICAgICAgICA8L2xpPlxcbiAgICAgICAgPC91bD5cXG4gICAgICA8L2Rpdj5cXG4gICAgICA8ZGl2IGNsYXNzPSdjb250ZW50JyBpZD0nXCJcbiAgICArIGFsaWFzMygoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZW5jb2RlZFBhcmVudElkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSlcbiAgICArIFwiX1wiXG4gICAgKyBhbGlhczMoKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLm5pY2tuYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSlcbiAgICArIFwiX2NvbnRlbnQnIHN0eWxlPSdkaXNwbGF5Om5vbmUnPlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZGVwcmVjYXRlZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMywgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5kZXNjcmlwdGlvbiA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oNSwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5zZWN1cml0eSA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oNywgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC50eXBlIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSg5LCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG5cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmhlYWRlcnMgOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDEyLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG4gICAgICAgIDxmb3JtIGFjY2VwdC1jaGFyc2V0PSdVVEYtOCcgY2xhc3M9J3NhbmRib3gnPlxcbiAgICAgICAgICA8ZGl2IHN0eWxlPSdtYXJnaW46MDtwYWRkaW5nOjA7ZGlzcGxheTppbmxpbmUnPjwvZGl2PlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAucGFyYW1ldGVycyA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMTUsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAucmVzcG9uc2VNZXNzYWdlcyA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMTcsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaXNSZWFkT25seSA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMTksIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5wcm9ncmFtKDIxLCBkYXRhLCAwKSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCIgICAgICAgIDwvZm9ybT5cXG4gICAgICAgIDxkaXYgY2xhc3M9J3Jlc3BvbnNlJyBzdHlsZT0nZGlzcGxheTpub25lJz5cXG4gICAgICAgICAgPGg0IGNsYXNzPSdjdXJsJz5DdXJsPC9oND5cXG4gICAgICAgICAgPGRpdiBjbGFzcz0nYmxvY2sgY3VybCc+PC9kaXY+XFxuICAgICAgICAgIDxoNCBkYXRhLXN3LXRyYW5zbGF0ZT5SZXF1ZXN0IFVSTDwvaDQ+XFxuICAgICAgICAgIDxkaXYgY2xhc3M9J2Jsb2NrIHJlcXVlc3RfdXJsJz48L2Rpdj5cXG5cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnNob3dSZXF1ZXN0SGVhZGVycyA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMjMsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIiAgICAgICAgICA8aDQgZGF0YS1zdy10cmFuc2xhdGU+UmVzcG9uc2UgQm9keTwvaDQ+XFxuICAgICAgICAgIDxkaXYgY2xhc3M9J2Jsb2NrIHJlc3BvbnNlX2JvZHknPjwvZGl2PlxcbiAgICAgICAgICA8aDQgZGF0YS1zdy10cmFuc2xhdGU+UmVzcG9uc2UgQ29kZTwvaDQ+XFxuICAgICAgICAgIDxkaXYgY2xhc3M9J2Jsb2NrIHJlc3BvbnNlX2NvZGUnPjwvZGl2PlxcbiAgICAgICAgICA8aDQgZGF0YS1zdy10cmFuc2xhdGU+UmVzcG9uc2UgSGVhZGVyczwvaDQ+XFxuICAgICAgICAgIDxkaXYgY2xhc3M9J2Jsb2NrIHJlc3BvbnNlX2hlYWRlcnMnPjwvZGl2PlxcbiAgICAgICAgPC9kaXY+XFxuICAgICAgPC9kaXY+XFxuICAgIDwvbGk+XFxuICA8L3VsPlxcblwiO1xufSxcInVzZURhdGFcIjp0cnVlfSk7XG50ZW1wbGF0ZXNbJ3BhcmFtJ10gPSB0ZW1wbGF0ZSh7XCIxXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlzRmlsZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMiwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLnByb2dyYW0oNCwgZGF0YSwgMCksXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIik7XG59LFwiMlwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sIGFsaWFzMj1oZWxwZXJzLmhlbHBlck1pc3Npbmc7XG5cbiAgcmV0dXJuIFwiXHRcdFx0PGlucHV0IHR5cGU9XFxcImZpbGVcXFwiIG5hbWU9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLm5hbWUgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIicgaWQ9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnZhbHVlSWQgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIicvPlxcblx0XHRcdDxkaXYgY2xhc3M9XFxcInBhcmFtZXRlci1jb250ZW50LXR5cGVcXFwiIC8+XFxuXCI7XG59LFwiNFwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMTtcblxuICByZXR1cm4gKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMFtcImRlZmF1bHRcIl0gOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDUsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5wcm9ncmFtKDcsIGRhdGEsIDApLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpO1xufSxcIjVcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIlx0XHRcdFx0PGRpdiBjbGFzcz1cXFwiZWRpdG9yX2hvbGRlclxcXCI+PC9kaXY+XFxuXHRcdFx0XHQ8dGV4dGFyZWEgY2xhc3M9J2JvZHktdGV4dGFyZWEnIG5hbWU9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLm5hbWUgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIicgaWQ9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnZhbHVlSWQgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIic+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDBbXCJkZWZhdWx0XCJdIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L3RleHRhcmVhPlxcbiAgICAgICAgPGJyIC8+XFxuICAgICAgICA8ZGl2IGNsYXNzPVxcXCJwYXJhbWV0ZXItY29udGVudC10eXBlXFxcIiAvPlxcblwiO1xufSxcIjdcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIlx0XHRcdFx0PHRleHRhcmVhIGNsYXNzPSdib2R5LXRleHRhcmVhJyBuYW1lPSdcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5uYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInIGlkPSdcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC52YWx1ZUlkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInPjwvdGV4dGFyZWE+XFxuXHRcdFx0XHQ8ZGl2IGNsYXNzPVxcXCJlZGl0b3JfaG9sZGVyXFxcIj48L2Rpdj5cXG5cdFx0XHRcdDxiciAvPlxcblx0XHRcdFx0PGRpdiBjbGFzcz1cXFwicGFyYW1ldGVyLWNvbnRlbnQtdHlwZVxcXCIgLz5cXG5cIjtcbn0sXCI5XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlzRmlsZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMiwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLnByb2dyYW0oMTAsIGRhdGEsIDApLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpO1xufSxcIjEwXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiAoKHN0YWNrMSA9IChoZWxwZXJzLnJlbmRlclRleHRQYXJhbSB8fCAoZGVwdGgwICYmIGRlcHRoMC5yZW5kZXJUZXh0UGFyYW0pIHx8IGhlbHBlcnMuaGVscGVyTWlzc2luZykuY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LGRlcHRoMCx7XCJuYW1lXCI6XCJyZW5kZXJUZXh0UGFyYW1cIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMTEsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpO1xufSxcIjExXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCJcIjtcbn0sXCJjb21waWxlclwiOls3LFwiPj0gNC4wLjBcIl0sXCJtYWluXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCI8dGQgY2xhc3M9J2NvZGUnPjxsYWJlbCBmb3I9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnZhbHVlSWQgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIic+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAubmFtZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9sYWJlbD48L3RkPlxcbjx0ZD5cXG5cXG5cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlzQm9keSA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMSwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLnByb2dyYW0oOSwgZGF0YSwgMCksXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxuPC90ZD5cXG48dGQgY2xhc3M9XFxcIm1hcmtkb3duXFxcIj5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZGVzY3JpcHRpb24gOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC90ZD5cXG48dGQ+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAucGFyYW1UeXBlIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L3RkPlxcbjx0ZD5cXG5cdDxzcGFuIGNsYXNzPVxcXCJtb2RlbC1zaWduYXR1cmVcXFwiPjwvc3Bhbj5cXG48L3RkPlxcblwiO1xufSxcInVzZURhdGFcIjp0cnVlfSk7XG50ZW1wbGF0ZXNbJ3BhcmFtX2xpc3QnXSA9IHRlbXBsYXRlKHtcIjFcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIiByZXF1aXJlZFwiO1xufSxcIjNcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIiBtdWx0aXBsZT1cXFwibXVsdGlwbGVcXFwiXCI7XG59LFwiNVwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgcmV0dXJuIFwiIHJlcXVpcmVkIFwiO1xufSxcIjdcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuIFwiICAgICAgPG9wdGlvbiBcIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzLnVubGVzcy5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmhhc0RlZmF1bHQgOiBkZXB0aDApLHtcIm5hbWVcIjpcInVubGVzc1wiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSg4LCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCIgdmFsdWU9Jyc+PC9vcHRpb24+XFxuXCI7XG59LFwiOFwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgcmV0dXJuIFwiICBzZWxlY3RlZD1cXFwiXFxcIiBcIjtcbn0sXCIxMFwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sIGFsaWFzMj1oZWxwZXJzLmhlbHBlck1pc3Npbmc7XG5cbiAgcmV0dXJuIFwiXFxuICAgICAgPG9wdGlvbiBcIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlzRGVmYXVsdCA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMTEsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIiAgdmFsdWU9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC52YWx1ZSA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInPiBcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAudmFsdWUgOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiIFwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaXNEZWZhdWx0IDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgxMywgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiIDwvb3B0aW9uPlxcblxcblwiO1xufSxcIjExXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgc2VsZWN0ZWQ9XFxcIlxcXCIgIFwiO1xufSxcIjEzXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgKGRlZmF1bHQpIFwiO1xufSxcIjE1XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCI8c3Ryb25nPlwiO1xufSxcIjE3XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCI8L3N0cm9uZz5cIjtcbn0sXCJjb21waWxlclwiOls3LFwiPj0gNC4wLjBcIl0sXCJtYWluXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBoZWxwZXIsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIjx0ZCBjbGFzcz0nY29kZVwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAucmVxdWlyZWQgOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDEsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIic+PGxhYmVsIGZvcj0nXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAudmFsdWVJZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiJz5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAubmFtZSA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L2xhYmVsPjwvdGQ+XFxuPHRkPlxcbiAgPHNlbGVjdCBcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5pc0FycmF5IHx8IChkZXB0aDAgJiYgZGVwdGgwLmlzQXJyYXkpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsZGVwdGgwLHtcIm5hbWVcIjpcImlzQXJyYXlcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMywgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiIGNsYXNzPVxcXCJwYXJhbWV0ZXIgXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5yZXF1aXJlZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oNSwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxcIiBuYW1lPVxcXCJcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAubmFtZSA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXFwiIGlkPVxcXCJcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC52YWx1ZUlkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXFwiPlxcblxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnMudW5sZXNzLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5yZXF1aXJlZCA6IGRlcHRoMCkse1wibmFtZVwiOlwidW5sZXNzXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDcsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnMuZWFjaC5jYWxsKGFsaWFzMSwoKHN0YWNrMSA9IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5hbGxvd2FibGVWYWx1ZXMgOiBkZXB0aDApKSAhPSBudWxsID8gc3RhY2sxLmRlc2NyaXB0aXZlVmFsdWVzIDogc3RhY2sxKSx7XCJuYW1lXCI6XCJlYWNoXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDEwLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG4gIDwvc2VsZWN0PlxcbjwvdGQ+XFxuPHRkIGNsYXNzPVxcXCJtYXJrZG93blxcXCI+XCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5yZXF1aXJlZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMTUsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyAoKHN0YWNrMSA9ICgoaGVscGVyID0gKGhlbHBlciA9IGhlbHBlcnMuZGVzY3JpcHRpb24gfHwgKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmRlc2NyaXB0aW9uIDogZGVwdGgwKSkgIT0gbnVsbCA/IGhlbHBlciA6IGFsaWFzMiksKHR5cGVvZiBoZWxwZXIgPT09IFwiZnVuY3Rpb25cIiA/IGhlbHBlci5jYWxsKGFsaWFzMSx7XCJuYW1lXCI6XCJkZXNjcmlwdGlvblwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSA6IGhlbHBlcikpKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5yZXF1aXJlZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMTcsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvdGQ+XFxuPHRkPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnBhcmFtVHlwZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC90ZD5cXG48dGQ+PHNwYW4gY2xhc3M9XFxcIm1vZGVsLXNpZ25hdHVyZVxcXCI+PC9zcGFuPjwvdGQ+XFxuXCI7XG59LFwidXNlRGF0YVwiOnRydWV9KTtcbnRlbXBsYXRlc1sncGFyYW1fcmVhZG9ubHknXSA9IHRlbXBsYXRlKHtcIjFcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIiAgICAgICAgPHRleHRhcmVhIGNsYXNzPSdib2R5LXRleHRhcmVhJyByZWFkb25seT0ncmVhZG9ubHknIG5hbWU9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5uYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIicgaWQ9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnZhbHVlSWQgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIic+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwW1wiZGVmYXVsdFwiXSA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L3RleHRhcmVhPlxcbiAgICAgICAgPGRpdiBjbGFzcz1cXFwicGFyYW1ldGVyLWNvbnRlbnQtdHlwZVxcXCIgLz5cXG5cIjtcbn0sXCIzXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwW1wiZGVmYXVsdFwiXSA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oNCwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLnByb2dyYW0oNiwgZGF0YSwgMCksXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIik7XG59LFwiNFwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMTtcblxuICByZXR1cm4gXCIgICAgICAgICAgICBcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwW1wiZGVmYXVsdFwiXSA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG5cIjtcbn0sXCI2XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgICAgICAgICAgICAoZW1wdHkpXFxuXCI7XG59LFwiY29tcGlsZXJcIjpbNyxcIj49IDQuMC4wXCJdLFwibWFpblwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sIGFsaWFzMj1oZWxwZXJzLmhlbHBlck1pc3Npbmc7XG5cbiAgcmV0dXJuIFwiPHRkIGNsYXNzPSdjb2RlJz48bGFiZWwgZm9yPSdcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC52YWx1ZUlkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5uYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvbGFiZWw+PC90ZD5cXG48dGQ+XFxuXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pc0JvZHkgOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDEsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5wcm9ncmFtKDMsIGRhdGEsIDApLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvdGQ+XFxuPHRkIGNsYXNzPVxcXCJtYXJrZG93blxcXCI+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmRlc2NyaXB0aW9uIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvdGQ+XFxuPHRkPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnBhcmFtVHlwZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC90ZD5cXG48dGQ+PHNwYW4gY2xhc3M9XFxcIm1vZGVsLXNpZ25hdHVyZVxcXCI+PC9zcGFuPjwvdGQ+XFxuXCI7XG59LFwidXNlRGF0YVwiOnRydWV9KTtcbnRlbXBsYXRlc1sncGFyYW1fcmVhZG9ubHlfcmVxdWlyZWQnXSA9IHRlbXBsYXRlKHtcIjFcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIiAgICAgICAgPHRleHRhcmVhIGNsYXNzPSdib2R5LXRleHRhcmVhJyByZWFkb25seT0ncmVhZG9ubHknIHBsYWNlaG9sZGVyPScocmVxdWlyZWQpJyBuYW1lPSdcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAubmFtZSA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInIGlkPSdcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC52YWx1ZUlkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMFtcImRlZmF1bHRcIl0gOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC90ZXh0YXJlYT5cXG5cIjtcbn0sXCIzXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwW1wiZGVmYXVsdFwiXSA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oNCwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLnByb2dyYW0oNiwgZGF0YSwgMCksXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIik7XG59LFwiNFwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMTtcblxuICByZXR1cm4gXCIgICAgICAgICAgICBcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwW1wiZGVmYXVsdFwiXSA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG5cIjtcbn0sXCI2XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgICAgICAgICAgICAoZW1wdHkpXFxuXCI7XG59LFwiY29tcGlsZXJcIjpbNyxcIj49IDQuMC4wXCJdLFwibWFpblwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sIGFsaWFzMj1oZWxwZXJzLmhlbHBlck1pc3Npbmc7XG5cbiAgcmV0dXJuIFwiPHRkIGNsYXNzPSdjb2RlIHJlcXVpcmVkJz48bGFiZWwgZm9yPSdcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC52YWx1ZUlkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5uYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvbGFiZWw+PC90ZD5cXG48dGQ+XFxuXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pc0JvZHkgOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDEsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5wcm9ncmFtKDMsIGRhdGEsIDApLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvdGQ+XFxuPHRkIGNsYXNzPVxcXCJtYXJrZG93blxcXCI+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmRlc2NyaXB0aW9uIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvdGQ+XFxuPHRkPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnBhcmFtVHlwZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC90ZD5cXG48dGQ+PHNwYW4gY2xhc3M9XFxcIm1vZGVsLXNpZ25hdHVyZVxcXCI+PC9zcGFuPjwvdGQ+XFxuXCI7XG59LFwidXNlRGF0YVwiOnRydWV9KTtcbnRlbXBsYXRlc1sncGFyYW1fcmVxdWlyZWQnXSA9IHRlbXBsYXRlKHtcIjFcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaXNGaWxlIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgyLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIucHJvZ3JhbSg0LCBkYXRhLCAwKSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKTtcbn0sXCIyXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCJcdFx0XHQ8aW5wdXQgdHlwZT1cXFwiZmlsZVxcXCIgbmFtZT0nXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAubmFtZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiJyBpZD0nXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAudmFsdWVJZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiJy8+XFxuXCI7XG59LFwiNFwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMTtcblxuICByZXR1cm4gKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMFtcImRlZmF1bHRcIl0gOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDUsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5wcm9ncmFtKDcsIGRhdGEsIDApLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpO1xufSxcIjVcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIlx0XHRcdFx0PGRpdiBjbGFzcz1cXFwiZWRpdG9yX2hvbGRlclxcXCI+PC9kaXY+XFxuXHRcdFx0XHQ8dGV4dGFyZWEgY2xhc3M9J2JvZHktdGV4dGFyZWEgcmVxdWlyZWQnIHBsYWNlaG9sZGVyPScocmVxdWlyZWQpJyBuYW1lPSdcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAubmFtZSA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInIGlkPVxcXCJcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC52YWx1ZUlkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXFwiPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMFtcImRlZmF1bHRcIl0gOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC90ZXh0YXJlYT5cXG4gICAgICAgIDxiciAvPlxcbiAgICAgICAgPGRpdiBjbGFzcz1cXFwicGFyYW1ldGVyLWNvbnRlbnQtdHlwZVxcXCIgLz5cXG5cIjtcbn0sXCI3XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCJcdFx0XHRcdDx0ZXh0YXJlYSBjbGFzcz0nYm9keS10ZXh0YXJlYSByZXF1aXJlZCcgcGxhY2Vob2xkZXI9JyhyZXF1aXJlZCknIG5hbWU9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5uYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIicgaWQ9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnZhbHVlSWQgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIic+PC90ZXh0YXJlYT5cXG5cdFx0XHRcdDxkaXYgY2xhc3M9XFxcImVkaXRvcl9ob2xkZXJcXFwiPjwvZGl2Plxcblx0XHRcdFx0PGJyIC8+XFxuXHRcdFx0XHQ8ZGl2IGNsYXNzPVxcXCJwYXJhbWV0ZXItY29udGVudC10eXBlXFxcIiAvPlxcblwiO1xufSxcIjlcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaXNGaWxlIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgxMCwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLnByb2dyYW0oMTIsIGRhdGEsIDApLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpO1xufSxcIjEwXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCJcdFx0XHQ8aW5wdXQgY2xhc3M9J3BhcmFtZXRlciByZXF1aXJlZCcgdHlwZT0nZmlsZScgbmFtZT0nXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLm5hbWUgOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiJyBpZD0nXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAudmFsdWVJZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiJy8+XFxuXCI7XG59LFwiMTJcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuICgoc3RhY2sxID0gKGhlbHBlcnMucmVuZGVyVGV4dFBhcmFtIHx8IChkZXB0aDAgJiYgZGVwdGgwLnJlbmRlclRleHRQYXJhbSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sZGVwdGgwLHtcIm5hbWVcIjpcInJlbmRlclRleHRQYXJhbVwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgxMywgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIik7XG59LFwiMTNcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIlwiO1xufSxcImNvbXBpbGVyXCI6WzcsXCI+PSA0LjAuMFwiXSxcIm1haW5cIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LCBhbGlhczI9aGVscGVycy5oZWxwZXJNaXNzaW5nO1xuXG4gIHJldHVybiBcIjx0ZCBjbGFzcz0nY29kZSByZXF1aXJlZCc+PGxhYmVsIGZvcj0nXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAudmFsdWVJZCA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiJz5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5uYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L2xhYmVsPjwvdGQ+XFxuPHRkPlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaXNCb2R5IDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgxLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIucHJvZ3JhbSg5LCBkYXRhLCAwKSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L3RkPlxcbjx0ZD5cXG5cdDxzdHJvbmc+PHNwYW4gY2xhc3M9XFxcIm1hcmtkb3duXFxcIj5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZGVzY3JpcHRpb24gOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9zcGFuPjwvc3Ryb25nPlxcbjwvdGQ+XFxuPHRkPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnBhcmFtVHlwZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC90ZD5cXG48dGQ+PHNwYW4gY2xhc3M9XFxcIm1vZGVsLXNpZ25hdHVyZVxcXCI+PC9zcGFuPjwvdGQ+XFxuXCI7XG59LFwidXNlRGF0YVwiOnRydWV9KTtcbnRlbXBsYXRlc1sncGFyYW1ldGVyX2NvbnRlbnRfdHlwZSddID0gdGVtcGxhdGUoe1wiMVwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMTtcblxuICByZXR1cm4gKChzdGFjazEgPSBoZWxwZXJzLmVhY2guY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5jb25zdW1lcyA6IGRlcHRoMCkse1wibmFtZVwiOlwiZWFjaFwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgyLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKTtcbn0sXCIyXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCIgIDxvcHRpb24gdmFsdWU9XFxcIlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLGRlcHRoMCx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIlxcXCI+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsZGVwdGgwLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9vcHRpb24+XFxuXCI7XG59LFwiNFwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgcmV0dXJuIFwiICA8b3B0aW9uIHZhbHVlPVxcXCJhcHBsaWNhdGlvbi9qc29uXFxcIj5hcHBsaWNhdGlvbi9qc29uPC9vcHRpb24+XFxuXCI7XG59LFwiY29tcGlsZXJcIjpbNyxcIj49IDQuMC4wXCJdLFwibWFpblwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgaGVscGVyLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCI8bGFiZWwgZm9yPVxcXCJcIlxuICAgICsgY29udGFpbmVyLmVzY2FwZUV4cHJlc3Npb24oKChoZWxwZXIgPSAoaGVscGVyID0gaGVscGVycy5wYXJhbWV0ZXJDb250ZW50VHlwZUlkIHx8IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5wYXJhbWV0ZXJDb250ZW50VHlwZUlkIDogZGVwdGgwKSkgIT0gbnVsbCA/IGhlbHBlciA6IGFsaWFzMiksKHR5cGVvZiBoZWxwZXIgPT09IFwiZnVuY3Rpb25cIiA/IGhlbHBlci5jYWxsKGFsaWFzMSx7XCJuYW1lXCI6XCJwYXJhbWV0ZXJDb250ZW50VHlwZUlkXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pIDogaGVscGVyKSkpXG4gICAgKyBcIlxcXCIgZGF0YS1zdy10cmFuc2xhdGU+UGFyYW1ldGVyIGNvbnRlbnQgdHlwZTo8L2xhYmVsPlxcbjxzZWxlY3QgbmFtZT1cXFwicGFyYW1ldGVyQ29udGVudFR5cGVcXFwiIGlkPVxcXCJcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAucGFyYW1ldGVyQ29udGVudFR5cGVJZCA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXFwiPlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuY29uc3VtZXMgOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDEsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5wcm9ncmFtKDQsIGRhdGEsIDApLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvc2VsZWN0PlxcblwiO1xufSxcInVzZURhdGFcIjp0cnVlfSk7XG50ZW1wbGF0ZXNbJ3BvcHVwJ10gPSB0ZW1wbGF0ZSh7XCJjb21waWxlclwiOls3LFwiPj0gNC4wLjBcIl0sXCJtYWluXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgaGVscGVyO1xuXG4gIHJldHVybiBcIjxkaXYgY2xhc3M9XFxcImFwaS1wb3B1cC1kaWFsb2ctd3JhcHBlclxcXCI+XFxuICAgIDxkaXYgY2xhc3M9XFxcImFwaS1wb3B1cC10aXRsZVxcXCI+XCJcbiAgICArIGNvbnRhaW5lci5lc2NhcGVFeHByZXNzaW9uKCgoaGVscGVyID0gKGhlbHBlciA9IGhlbHBlcnMudGl0bGUgfHwgKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnRpdGxlIDogZGVwdGgwKSkgIT0gbnVsbCA/IGhlbHBlciA6IGhlbHBlcnMuaGVscGVyTWlzc2luZyksKHR5cGVvZiBoZWxwZXIgPT09IFwiZnVuY3Rpb25cIiA/IGhlbHBlci5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30se1wibmFtZVwiOlwidGl0bGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkgOiBoZWxwZXIpKSlcbiAgICArIFwiPC9kaXY+XFxuICAgIDxkaXYgY2xhc3M9XFxcImFwaS1wb3B1cC1jb250ZW50XFxcIj48L2Rpdj5cXG4gICAgPHAgY2xhc3M9XFxcImVycm9yLW1zZ1xcXCI+PC9wPlxcbiAgICA8ZGl2IGNsYXNzPVxcXCJhcGktcG9wdXAtYWN0aW9uc1xcXCI+XFxuICAgICAgICA8YnV0dG9uIGNsYXNzPVxcXCJhcGktcG9wdXAtY2FuY2VsIGFwaS1idXR0b24gZ3JheVxcXCIgdHlwZT1cXFwiYnV0dG9uXFxcIj5DYW5jZWw8L2J1dHRvbj5cXG4gICAgPC9kaXY+XFxuPC9kaXY+XFxuPGRpdiBjbGFzcz1cXFwiYXBpLXBvcHVwLWRpYWxvZy1zaGFkb3dcXFwiPjwvZGl2PlwiO1xufSxcInVzZURhdGFcIjp0cnVlfSk7XG50ZW1wbGF0ZXNbJ3Jlc291cmNlJ10gPSB0ZW1wbGF0ZSh7XCIxXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCIgOiBcIjtcbn0sXCIzXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxO1xuXG4gIHJldHVybiBcIiAgICA8bGk+XFxuICAgICAgPGEgaHJlZj0nXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGhlbHBlcnMuaGVscGVyTWlzc2luZykuY2FsbChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9LChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC51cmwgOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiJyBkYXRhLXN3LXRyYW5zbGF0ZT5SYXc8L2E+XFxuICAgIDwvbGk+XFxuXCI7XG59LFwiY29tcGlsZXJcIjpbNyxcIj49IDQuMC4wXCJdLFwibWFpblwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgaGVscGVyLCBvcHRpb25zLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZywgYnVmZmVyID0gXG4gIFwiPGRpdiBjbGFzcz0naGVhZGluZyc+XFxuICA8aDI+XFxuICAgIDxhIGhyZWY9JyMhL1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pZCA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCInIGNsYXNzPVxcXCJ0b2dnbGVFbmRwb2ludExpc3RcXFwiIGRhdGEtaWQ9XFxcIlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pZCA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXFwiPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5uYW1lIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvYT4gXCI7XG4gIHN0YWNrMSA9ICgoaGVscGVyID0gKGhlbHBlciA9IGhlbHBlcnMuc3VtbWFyeSB8fCAoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuc3VtbWFyeSA6IGRlcHRoMCkpICE9IG51bGwgPyBoZWxwZXIgOiBhbGlhczIpLChvcHRpb25zPXtcIm5hbWVcIjpcInN1bW1hcnlcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMSwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pLCh0eXBlb2YgaGVscGVyID09PSBcImZ1bmN0aW9uXCIgPyBoZWxwZXIuY2FsbChhbGlhczEsb3B0aW9ucykgOiBoZWxwZXIpKTtcbiAgaWYgKCFoZWxwZXJzLnN1bW1hcnkpIHsgc3RhY2sxID0gaGVscGVycy5ibG9ja0hlbHBlck1pc3NpbmcuY2FsbChkZXB0aDAsc3RhY2sxLG9wdGlvbnMpfVxuICBpZiAoc3RhY2sxICE9IG51bGwpIHsgYnVmZmVyICs9IHN0YWNrMTsgfVxuICByZXR1cm4gYnVmZmVyICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuc3VtbWFyeSA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG4gIDwvaDI+XFxuICA8dWwgY2xhc3M9J29wdGlvbnMnPlxcbiAgICA8bGk+XFxuICAgICAgPGEgaHJlZj0nIyEvXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIicgaWQ9J2VuZHBvaW50TGlzdFRvZ2dlcl9cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaWQgOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiJyBjbGFzcz1cXFwidG9nZ2xlRW5kcG9pbnRMaXN0XFxcIiBkYXRhLWlkPVxcXCJcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuaWQgOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxcIiBkYXRhLXN3LXRyYW5zbGF0ZT5TaG93L0hpZGU8L2E+XFxuICAgIDwvbGk+XFxuICAgIDxsaT5cXG4gICAgICA8YSBocmVmPScjJyBjbGFzcz1cXFwiY29sbGFwc2VSZXNvdXJjZVxcXCIgZGF0YS1pZD1cXFwiXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuc2FuaXRpemUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuc2FuaXRpemUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLmlkIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIlxcXCIgZGF0YS1zdy10cmFuc2xhdGU+XFxuICAgICAgICBMaXN0IE9wZXJhdGlvbnNcXG4gICAgICA8L2E+XFxuICAgIDwvbGk+XFxuICAgIDxsaT5cXG4gICAgICA8YSBocmVmPScjJyBjbGFzcz1cXFwiZXhwYW5kUmVzb3VyY2VcXFwiIGRhdGEtaWQ9XFxcIlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pZCA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXFwiIGRhdGEtc3ctdHJhbnNsYXRlPlxcbiAgICAgICAgRXhwYW5kIE9wZXJhdGlvbnNcXG4gICAgICA8L2E+XFxuICAgIDwvbGk+XFxuXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC51cmwgOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDMsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIiAgPC91bD5cXG48L2Rpdj5cXG48dWwgY2xhc3M9J2VuZHBvaW50cycgaWQ9J1wiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pZCA6IGRlcHRoMCkse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJfZW5kcG9pbnRfbGlzdCcgc3R5bGU9J2Rpc3BsYXk6bm9uZSc+XFxuXFxuPC91bD5cXG5cIjtcbn0sXCJ1c2VEYXRhXCI6dHJ1ZX0pO1xudGVtcGxhdGVzWydyZXNwb25zZV9jb250ZW50X3R5cGUnXSA9IHRlbXBsYXRlKHtcIjFcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazE7XG5cbiAgcmV0dXJuICgoc3RhY2sxID0gaGVscGVycy5lYWNoLmNhbGwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAucHJvZHVjZXMgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVhY2hcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMiwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIik7XG59LFwiMlwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sIGFsaWFzMj1oZWxwZXJzLmhlbHBlck1pc3Npbmc7XG5cbiAgcmV0dXJuIFwiICA8b3B0aW9uIHZhbHVlPVxcXCJcIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSxkZXB0aDAse1wibmFtZVwiOlwic2FuaXRpemVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXFwiPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLnNhbml0aXplIHx8IChkZXB0aDAgJiYgZGVwdGgwLnNhbml0aXplKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLGRlcHRoMCx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvb3B0aW9uPlxcblwiO1xufSxcIjRcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHJldHVybiBcIiAgPG9wdGlvbiB2YWx1ZT1cXFwiYXBwbGljYXRpb24vanNvblxcXCI+YXBwbGljYXRpb24vanNvbjwvb3B0aW9uPlxcblwiO1xufSxcImNvbXBpbGVyXCI6WzcsXCI+PSA0LjAuMFwiXSxcIm1haW5cIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGhlbHBlciwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sIGFsaWFzMj1oZWxwZXJzLmhlbHBlck1pc3NpbmcsIGFsaWFzMz1cImZ1bmN0aW9uXCIsIGFsaWFzND1jb250YWluZXIuZXNjYXBlRXhwcmVzc2lvbjtcblxuICByZXR1cm4gXCI8bGFiZWwgZGF0YS1zdy10cmFuc2xhdGUgZm9yPVxcXCJcIlxuICAgICsgYWxpYXM0KCgoaGVscGVyID0gKGhlbHBlciA9IGhlbHBlcnMucmVzcG9uc2VDb250ZW50VHlwZUlkIHx8IChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5yZXNwb25zZUNvbnRlbnRUeXBlSWQgOiBkZXB0aDApKSAhPSBudWxsID8gaGVscGVyIDogYWxpYXMyKSwodHlwZW9mIGhlbHBlciA9PT0gYWxpYXMzID8gaGVscGVyLmNhbGwoYWxpYXMxLHtcIm5hbWVcIjpcInJlc3BvbnNlQ29udGVudFR5cGVJZFwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSA6IGhlbHBlcikpKVxuICAgICsgXCJcXFwiPlJlc3BvbnNlIENvbnRlbnQgVHlwZTwvbGFiZWw+XFxuPHNlbGVjdCBuYW1lPVxcXCJyZXNwb25zZUNvbnRlbnRUeXBlXFxcIiBpZD1cXFwiXCJcbiAgICArIGFsaWFzNCgoKGhlbHBlciA9IChoZWxwZXIgPSBoZWxwZXJzLnJlc3BvbnNlQ29udGVudFR5cGVJZCB8fCAoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAucmVzcG9uc2VDb250ZW50VHlwZUlkIDogZGVwdGgwKSkgIT0gbnVsbCA/IGhlbHBlciA6IGFsaWFzMiksKHR5cGVvZiBoZWxwZXIgPT09IGFsaWFzMyA/IGhlbHBlci5jYWxsKGFsaWFzMSx7XCJuYW1lXCI6XCJyZXNwb25zZUNvbnRlbnRUeXBlSWRcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkgOiBoZWxwZXIpKSlcbiAgICArIFwiXFxcIj5cXG5cIlxuICAgICsgKChzdGFjazEgPSBoZWxwZXJzW1wiaWZcIl0uY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnByb2R1Y2VzIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgxLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIucHJvZ3JhbSg0LCBkYXRhLCAwKSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L3NlbGVjdD5cXG5cIjtcbn0sXCJ1c2VEYXRhXCI6dHJ1ZX0pO1xudGVtcGxhdGVzWydzaWduYXR1cmUnXSA9IHRlbXBsYXRlKHtcIjFcIjpmdW5jdGlvbihjb250YWluZXIsZGVwdGgwLGhlbHBlcnMscGFydGlhbHMsZGF0YSkge1xuICAgIHZhciBzdGFjazEsIGFsaWFzMT1kZXB0aDAgIT0gbnVsbCA/IGRlcHRoMCA6IHt9O1xuXG4gIHJldHVybiBcIlxcbjxkaXY+XFxuPHVsIGNsYXNzPVxcXCJzaWduYXR1cmUtbmF2XFxcIj5cXG4gIDxsaT48YSBjbGFzcz1cXFwiZGVzY3JpcHRpb24tbGlua1xcXCIgaHJlZj1cXFwiI1xcXCIgZGF0YS1zdy10cmFuc2xhdGU+TW9kZWw8L2E+PC9saT5cXG4gIDxsaT48YSBjbGFzcz1cXFwic25pcHBldC1saW5rXFxcIiBocmVmPVxcXCIjXFxcIiBkYXRhLXN3LXRyYW5zbGF0ZT5FeGFtcGxlIFZhbHVlPC9hPjwvbGk+XFxuPC91bD5cXG48ZGl2PlxcblxcbjxkaXYgY2xhc3M9XFxcInNpZ25hdHVyZS1jb250YWluZXJcXFwiPlxcbiAgPGRpdiBjbGFzcz1cXFwiZGVzY3JpcHRpb25cXFwiPlxcbiAgICAgIFwiXG4gICAgKyBjb250YWluZXIuZXNjYXBlRXhwcmVzc2lvbigoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuc2lnbmF0dXJlIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJzYW5pdGl6ZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSlcbiAgICArIFwiXFxuICA8L2Rpdj5cXG5cXG4gIDxkaXYgY2xhc3M9XFxcInNuaXBwZXRcXFwiPlxcblwiXG4gICAgKyAoKHN0YWNrMSA9IGhlbHBlcnNbXCJpZlwiXS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuc2FtcGxlSlNPTiA6IGRlcHRoMCkse1wibmFtZVwiOlwiaWZcIixcImhhc2hcIjp7fSxcImZuXCI6Y29udGFpbmVyLnByb2dyYW0oMiwgZGF0YSwgMCksXCJpbnZlcnNlXCI6Y29udGFpbmVyLm5vb3AsXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5zYW1wbGVYTUwgOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDUsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIiAgPC9kaXY+XFxuPC9kaXY+XFxuXCI7XG59LFwiMlwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge307XG5cbiAgcmV0dXJuIFwiICAgICAgPGRpdiBjbGFzcz1cXFwic25pcHBldF9qc29uXFxcIj5cXG4gICAgICAgIDxwcmU+PGNvZGU+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuc2FtcGxlSlNPTiA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC9jb2RlPjwvcHJlPlxcbiAgICAgICAgXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pc1BhcmFtIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgzLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG4gICAgICA8L2Rpdj5cXG5cIjtcbn0sXCIzXCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICByZXR1cm4gXCI8c21hbGwgY2xhc3M9XFxcIm5vdGljZVxcXCIgZGF0YS1zdy10cmFuc2xhdGU+PC9zbWFsbD5cIjtcbn0sXCI1XCI6ZnVuY3Rpb24oY29udGFpbmVyLGRlcHRoMCxoZWxwZXJzLHBhcnRpYWxzLGRhdGEpIHtcbiAgICB2YXIgc3RhY2sxLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fTtcblxuICByZXR1cm4gXCIgICAgPGRpdiBjbGFzcz1cXFwic25pcHBldF94bWxcXFwiPlxcbiAgICAgIDxwcmU+PGNvZGU+XCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuc2FtcGxlWE1MIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L2NvZGU+PC9wcmU+XFxuICAgICAgXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVyc1tcImlmXCJdLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5pc1BhcmFtIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJpZlwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgzLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIubm9vcCxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCJcXG4gICAgPC9kaXY+XFxuXCI7XG59LFwiN1wiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMTtcblxuICByZXR1cm4gXCIgICAgXCJcbiAgICArICgoc3RhY2sxID0gKGhlbHBlcnMuZXNjYXBlIHx8IChkZXB0aDAgJiYgZGVwdGgwLmVzY2FwZSkgfHwgaGVscGVycy5oZWxwZXJNaXNzaW5nKS5jYWxsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLnNpZ25hdHVyZSA6IGRlcHRoMCkse1wibmFtZVwiOlwiZXNjYXBlXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiXFxuXCI7XG59LFwiY29tcGlsZXJcIjpbNyxcIj49IDQuMC4wXCJdLFwibWFpblwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMTtcblxuICByZXR1cm4gKChzdGFjazEgPSAoaGVscGVycy5pZkNvbmQgfHwgKGRlcHRoMCAmJiBkZXB0aDAuaWZDb25kKSB8fCBoZWxwZXJzLmhlbHBlck1pc3NpbmcpLmNhbGwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuc2FtcGxlSlNPTiA6IGRlcHRoMCksXCJ8fFwiLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5zYW1wbGVYTUwgOiBkZXB0aDApLHtcIm5hbWVcIjpcImlmQ29uZFwiLFwiaGFzaFwiOnt9LFwiZm5cIjpjb250YWluZXIucHJvZ3JhbSgxLCBkYXRhLCAwKSxcImludmVyc2VcIjpjb250YWluZXIucHJvZ3JhbSg3LCBkYXRhLCAwKSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKTtcbn0sXCJ1c2VEYXRhXCI6dHJ1ZX0pO1xudGVtcGxhdGVzWydzdGF0dXNfY29kZSddID0gdGVtcGxhdGUoe1wiMVwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgaGVscGVyLCBhbGlhczE9ZGVwdGgwICE9IG51bGwgPyBkZXB0aDAgOiB7fSwgYWxpYXMyPWhlbHBlcnMuaGVscGVyTWlzc2luZztcblxuICByZXR1cm4gXCIgICAgICA8dHI+XFxuICAgICAgICA8dGQ+XCJcbiAgICArIGNvbnRhaW5lci5lc2NhcGVFeHByZXNzaW9uKCgoaGVscGVyID0gKGhlbHBlciA9IGhlbHBlcnMua2V5IHx8IChkYXRhICYmIGRhdGEua2V5KSkgIT0gbnVsbCA/IGhlbHBlciA6IGFsaWFzMiksKHR5cGVvZiBoZWxwZXIgPT09IFwiZnVuY3Rpb25cIiA/IGhlbHBlci5jYWxsKGFsaWFzMSx7XCJuYW1lXCI6XCJrZXlcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkgOiBoZWxwZXIpKSlcbiAgICArIFwiPC90ZD5cXG4gICAgICAgIDx0ZD5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5zYW5pdGl6ZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5zYW5pdGl6ZSkgfHwgYWxpYXMyKS5jYWxsKGFsaWFzMSwoZGVwdGgwICE9IG51bGwgPyBkZXB0aDAuZGVzY3JpcHRpb24gOiBkZXB0aDApLHtcIm5hbWVcIjpcInNhbml0aXplXCIsXCJoYXNoXCI6e30sXCJkYXRhXCI6ZGF0YX0pKSAhPSBudWxsID8gc3RhY2sxIDogXCJcIilcbiAgICArIFwiPC90ZD5cXG4gICAgICAgIDx0ZD5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC50eXBlIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L3RkPlxcbiAgICAgIDwvdHI+XFxuXCI7XG59LFwiY29tcGlsZXJcIjpbNyxcIj49IDQuMC4wXCJdLFwibWFpblwiOmZ1bmN0aW9uKGNvbnRhaW5lcixkZXB0aDAsaGVscGVycyxwYXJ0aWFscyxkYXRhKSB7XG4gICAgdmFyIHN0YWNrMSwgYWxpYXMxPWRlcHRoMCAhPSBudWxsID8gZGVwdGgwIDoge30sIGFsaWFzMj1oZWxwZXJzLmhlbHBlck1pc3Npbmc7XG5cbiAgcmV0dXJuIFwiPHRkIHdpZHRoPScxNSUnIGNsYXNzPSdjb2RlJz5cIlxuICAgICsgKChzdGFjazEgPSAoaGVscGVycy5lc2NhcGUgfHwgKGRlcHRoMCAmJiBkZXB0aDAuZXNjYXBlKSB8fCBhbGlhczIpLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5jb2RlIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlc2NhcGVcIixcImhhc2hcIjp7fSxcImRhdGFcIjpkYXRhfSkpICE9IG51bGwgPyBzdGFjazEgOiBcIlwiKVxuICAgICsgXCI8L3RkPlxcbjx0ZCBjbGFzcz1cXFwibWFya2Rvd25cXFwiPlwiXG4gICAgKyAoKHN0YWNrMSA9IChoZWxwZXJzLmVzY2FwZSB8fCAoZGVwdGgwICYmIGRlcHRoMC5lc2NhcGUpIHx8IGFsaWFzMikuY2FsbChhbGlhczEsKGRlcHRoMCAhPSBudWxsID8gZGVwdGgwLm1lc3NhZ2UgOiBkZXB0aDApLHtcIm5hbWVcIjpcImVzY2FwZVwiLFwiaGFzaFwiOnt9LFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIjwvdGQ+XFxuPHRkIHdpZHRoPSc1MCUnPjxzcGFuIGNsYXNzPVxcXCJtb2RlbC1zaWduYXR1cmVcXFwiIC8+PC90ZD5cXG48dGQgY2xhc3M9XFxcImhlYWRlcnNcXFwiPlxcbiAgPHRhYmxlPlxcbiAgICA8dGJvZHk+XFxuXCJcbiAgICArICgoc3RhY2sxID0gaGVscGVycy5lYWNoLmNhbGwoYWxpYXMxLChkZXB0aDAgIT0gbnVsbCA/IGRlcHRoMC5oZWFkZXJzIDogZGVwdGgwKSx7XCJuYW1lXCI6XCJlYWNoXCIsXCJoYXNoXCI6e30sXCJmblwiOmNvbnRhaW5lci5wcm9ncmFtKDEsIGRhdGEsIDApLFwiaW52ZXJzZVwiOmNvbnRhaW5lci5ub29wLFwiZGF0YVwiOmRhdGF9KSkgIT0gbnVsbCA/IHN0YWNrMSA6IFwiXCIpXG4gICAgKyBcIiAgICA8L3Rib2R5PlxcbiAgPC90YWJsZT5cXG48L3RkPlwiO1xufSxcInVzZURhdGFcIjp0cnVlfSk7XG59KSgpO30gXG4gLyoganNoaW50IGlnbm9yZTplbmQgKi8iLCIndXNlIHN0cmljdCc7XG5cblxuJChmdW5jdGlvbigpIHtcblxuXHQvLyBIZWxwZXIgZnVuY3Rpb24gZm9yIHZlcnRpY2FsbHkgYWxpZ25pbmcgRE9NIGVsZW1lbnRzXG5cdC8vIGh0dHA6Ly93d3cuc2VvZGVudmVyLmNvbS9zaW1wbGUtdmVydGljYWwtYWxpZ24tcGx1Z2luLWZvci1qcXVlcnkvXG5cdCQuZm4udkFsaWduID0gZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbigpe1xuXHRcdFx0dmFyIGFoID0gJCh0aGlzKS5oZWlnaHQoKTtcblx0XHRcdHZhciBwaCA9ICQodGhpcykucGFyZW50KCkuaGVpZ2h0KCk7XG5cdFx0XHR2YXIgbWggPSAocGggLSBhaCkgLyAyO1xuXHRcdFx0JCh0aGlzKS5jc3MoJ21hcmdpbi10b3AnLCBtaCk7XG5cdFx0fSk7XG5cdH07XG5cblx0JC5mbi5zdHJldGNoRm9ybXRhc3RpY0lucHV0V2lkdGhUb1BhcmVudCA9IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24oKXtcblx0XHRcdHZhciBwX3dpZHRoID0gJCh0aGlzKS5jbG9zZXN0KFwiZm9ybVwiKS5pbm5lcldpZHRoKCk7XG5cdFx0XHR2YXIgcF9wYWRkaW5nID0gcGFyc2VJbnQoJCh0aGlzKS5jbG9zZXN0KFwiZm9ybVwiKS5jc3MoJ3BhZGRpbmctbGVmdCcpICwxMCkgKyBwYXJzZUludCgkKHRoaXMpLmNsb3Nlc3QoJ2Zvcm0nKS5jc3MoJ3BhZGRpbmctcmlnaHQnKSwgMTApO1xuXHRcdFx0dmFyIHRoaXNfcGFkZGluZyA9IHBhcnNlSW50KCQodGhpcykuY3NzKCdwYWRkaW5nLWxlZnQnKSwgMTApICsgcGFyc2VJbnQoJCh0aGlzKS5jc3MoJ3BhZGRpbmctcmlnaHQnKSwgMTApO1xuXHRcdFx0JCh0aGlzKS5jc3MoJ3dpZHRoJywgcF93aWR0aCAtIHBfcGFkZGluZyAtIHRoaXNfcGFkZGluZyk7XG5cdFx0fSk7XG5cdH07XG5cblx0JCgnZm9ybS5mb3JtdGFzdGljIGxpLnN0cmluZyBpbnB1dCwgZm9ybS5mb3JtdGFzdGljIHRleHRhcmVhJykuc3RyZXRjaEZvcm10YXN0aWNJbnB1dFdpZHRoVG9QYXJlbnQoKTtcblxuXHQvLyBWZXJ0aWNhbGx5IGNlbnRlciB0aGVzZSBwYXJhZ3JhcGhzXG5cdC8vIFBhcmVudCBtYXkgbmVlZCBhIG1pbi1oZWlnaHQgZm9yIHRoaXMgdG8gd29yay4uXG5cdCQoJ3VsLmRvd25wbGF5ZWQgbGkgZGl2LmNvbnRlbnQgcCcpLnZBbGlnbigpO1xuXG5cdC8vIFdoZW4gYSBzYW5kYm94IGZvcm0gaXMgc3VibWl0dGVkLi5cblx0JChcImZvcm0uc2FuZGJveFwiKS5zdWJtaXQoZnVuY3Rpb24oKXtcblxuXHRcdHZhciBlcnJvcl9mcmVlID0gdHJ1ZTtcblxuXHRcdC8vIEN5Y2xlIHRocm91Z2ggdGhlIGZvcm1zIHJlcXVpcmVkIGlucHV0c1xuIFx0XHQkKHRoaXMpLmZpbmQoXCJpbnB1dC5yZXF1aXJlZFwiKS5lYWNoKGZ1bmN0aW9uKCkge1xuXG5cdFx0XHQvLyBSZW1vdmUgYW55IGV4aXN0aW5nIGVycm9yIHN0eWxlcyBmcm9tIHRoZSBpbnB1dFxuXHRcdFx0JCh0aGlzKS5yZW1vdmVDbGFzcygnZXJyb3InKTtcblxuXHRcdFx0Ly8gVGFjayB0aGUgZXJyb3Igc3R5bGUgb24gaWYgdGhlIGlucHV0IGlzIGVtcHR5Li5cblx0XHRcdGlmICgkKHRoaXMpLnZhbCgpID09PSAnJykge1xuXHRcdFx0XHQkKHRoaXMpLmFkZENsYXNzKCdlcnJvcicpO1xuXHRcdFx0XHQkKHRoaXMpLndpZ2dsZSgpO1xuXHRcdFx0XHRlcnJvcl9mcmVlID0gZmFsc2U7XG5cdFx0XHR9XG5cblx0XHR9KTtcblxuXHRcdHJldHVybiBlcnJvcl9mcmVlO1xuXHR9KTtcblxufSk7XG5cbmZ1bmN0aW9uIGNsaXBweUNvcGllZENhbGxiYWNrKCkge1xuICAkKCcjYXBpX2tleV9jb3BpZWQnKS5mYWRlSW4oKS5kZWxheSgxMDAwKS5mYWRlT3V0KCk7XG5cbiAgLy8gdmFyIGIgPSAkKFwiI2NsaXBweV90b29sdGlwX1wiICsgYSk7XG4gIC8vIGIubGVuZ3RoICE9IDAgJiYgKGIuYXR0cihcInRpdGxlXCIsIFwiY29waWVkIVwiKS50cmlnZ2VyKFwidGlwc3kucmVsb2FkXCIpLCBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAvLyAgIGIuYXR0cihcInRpdGxlXCIsIFwiY29weSB0byBjbGlwYm9hcmRcIilcbiAgLy8gfSxcbiAgLy8gNTAwKSlcbn1cblxuLy8gTG9nZ2luZyBmdW5jdGlvbiB0aGF0IGFjY291bnRzIGZvciBicm93c2VycyB0aGF0IGRvbid0IGhhdmUgd2luZG93LmNvbnNvbGVcbmZ1bmN0aW9uIGxvZygpe1xuICBsb2cuaGlzdG9yeSA9IGxvZy5oaXN0b3J5IHx8IFtdO1xuICBsb2cuaGlzdG9yeS5wdXNoKGFyZ3VtZW50cyk7XG4gIGlmKHRoaXMuY29uc29sZSl7XG4gICAgY29uc29sZS5sb2coIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cylbMF0gKTtcbiAgfVxufVxuXG4vLyBIYW5kbGUgYnJvd3NlcnMgdGhhdCBkbyBjb25zb2xlIGluY29ycmVjdGx5IChJRTkgYW5kIGJlbG93LCBzZWUgaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNTUzOTM3OC83OTEzKVxuaWYgKEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kICYmIGNvbnNvbGUgJiYgdHlwZW9mIGNvbnNvbGUubG9nID09PSBcIm9iamVjdFwiKSB7XG4gICAgW1xuICAgICAgXCJsb2dcIixcImluZm9cIixcIndhcm5cIixcImVycm9yXCIsXCJhc3NlcnRcIixcImRpclwiLFwiY2xlYXJcIixcInByb2ZpbGVcIixcInByb2ZpbGVFbmRcIlxuICAgIF0uZm9yRWFjaChmdW5jdGlvbiAobWV0aG9kKSB7XG4gICAgICAgIGNvbnNvbGVbbWV0aG9kXSA9IHRoaXMuYmluZChjb25zb2xlW21ldGhvZF0sIGNvbnNvbGUpO1xuICAgIH0sIEZ1bmN0aW9uLnByb3RvdHlwZS5jYWxsKTtcbn1cblxud2luZG93LkRvY3MgPSB7XG5cblx0c2hlYmFuZzogZnVuY3Rpb24oKSB7XG5cblx0XHQvLyBJZiBzaGViYW5nIGhhcyBhbiBvcGVyYXRpb24gbmlja25hbWUgaW4gaXQuLlxuXHRcdC8vIGUuZy4gL2RvY3MvIyEvd29yZHMvZ2V0X3NlYXJjaFxuXHRcdHZhciBmcmFnbWVudHMgPSAkLnBhcmFtLmZyYWdtZW50KCkuc3BsaXQoJy8nKTtcblx0XHRmcmFnbWVudHMuc2hpZnQoKTsgLy8gZ2V0IHJpZCBvZiB0aGUgYmFuZ1xuXG5cdFx0c3dpdGNoIChmcmFnbWVudHMubGVuZ3RoKSB7XG5cdFx0XHRjYXNlIDE6XG4gICAgICAgIGlmIChmcmFnbWVudHNbMF0ubGVuZ3RoID4gMCkgeyAvLyBwcmV2ZW50IG1hdGNoaW5nIFwiIy9cIlxuICAgICAgICAgIC8vIEV4cGFuZCBhbGwgb3BlcmF0aW9ucyBmb3IgdGhlIHJlc291cmNlIGFuZCBzY3JvbGwgdG8gaXRcbiAgICAgICAgICB2YXIgZG9tX2lkID0gJ3Jlc291cmNlXycgKyBmcmFnbWVudHNbMF07XG5cbiAgICAgICAgICBEb2NzLmV4cGFuZEVuZHBvaW50TGlzdEZvclJlc291cmNlKGZyYWdtZW50c1swXSk7XG4gICAgICAgICAgJChcIiNcIitkb21faWQpLnNsaWRldG8oe2hpZ2hsaWdodDogZmFsc2V9KTtcbiAgICAgICAgfVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgMjpcblx0XHRcdFx0Ly8gUmVmZXIgdG8gdGhlIGVuZHBvaW50IERPTSBlbGVtZW50LCBlLmcuICN3b3Jkc19nZXRfc2VhcmNoXG5cbiAgICAgICAgLy8gRXhwYW5kIFJlc291cmNlXG4gICAgICAgIERvY3MuZXhwYW5kRW5kcG9pbnRMaXN0Rm9yUmVzb3VyY2UoZnJhZ21lbnRzWzBdKTtcbiAgICAgICAgJChcIiNcIitkb21faWQpLnNsaWRldG8oe2hpZ2hsaWdodDogZmFsc2V9KTtcblxuICAgICAgICAgICAgLy8gRXhwYW5kIG9wZXJhdGlvblxuICAgICAgICAgICAgdmFyIGxpX2RvbV9pZCA9IGZyYWdtZW50cy5qb2luKCdfJyk7XG4gICAgICAgICAgICB2YXIgbGlfY29udGVudF9kb21faWQgPSBsaV9kb21faWQgKyBcIl9jb250ZW50XCI7XG5cblxuICAgICAgICAgICAgRG9jcy5leHBhbmRPcGVyYXRpb24oJCgnIycrbGlfY29udGVudF9kb21faWQpKTtcbiAgICAgICAgICAgICQoJyMnK2xpX2RvbV9pZCkuc2xpZGV0byh7aGlnaGxpZ2h0OiBmYWxzZX0pO1xuICAgICAgICAgICAgYnJlYWs7XG5cdFx0fVxuXHR9LFxuXG5cdHRvZ2dsZUVuZHBvaW50TGlzdEZvclJlc291cmNlOiBmdW5jdGlvbihyZXNvdXJjZSkge1xuXHRcdHZhciBlbGVtID0gJCgnbGkjcmVzb3VyY2VfJyArIERvY3MuZXNjYXBlUmVzb3VyY2VOYW1lKHJlc291cmNlKSArICcgdWwuZW5kcG9pbnRzJyk7XG5cdFx0aWYgKGVsZW0uaXMoJzp2aXNpYmxlJykpIHtcblx0XHRcdCQuYmJxLnB1c2hTdGF0ZSgnIy8nLCAyKTtcblx0XHRcdERvY3MuY29sbGFwc2VFbmRwb2ludExpc3RGb3JSZXNvdXJjZShyZXNvdXJjZSk7XG5cdFx0fSBlbHNlIHtcbiAgICAgICAgICAgICQuYmJxLnB1c2hTdGF0ZSgnIy8nICsgcmVzb3VyY2UsIDIpO1xuXHRcdFx0RG9jcy5leHBhbmRFbmRwb2ludExpc3RGb3JSZXNvdXJjZShyZXNvdXJjZSk7XG5cdFx0fVxuXHR9LFxuXG5cdC8vIEV4cGFuZCByZXNvdXJjZVxuXHRleHBhbmRFbmRwb2ludExpc3RGb3JSZXNvdXJjZTogZnVuY3Rpb24ocmVzb3VyY2UpIHtcblx0XHR2YXIgcmVzb3VyY2UgPSBEb2NzLmVzY2FwZVJlc291cmNlTmFtZShyZXNvdXJjZSk7XG5cdFx0aWYgKHJlc291cmNlID09ICcnKSB7XG5cdFx0XHQkKCcucmVzb3VyY2UgdWwuZW5kcG9pbnRzJykuc2xpZGVEb3duKCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0JCgnbGkjcmVzb3VyY2VfJyArIHJlc291cmNlKS5hZGRDbGFzcygnYWN0aXZlJyk7XG5cblx0XHR2YXIgZWxlbSA9ICQoJ2xpI3Jlc291cmNlXycgKyByZXNvdXJjZSArICcgdWwuZW5kcG9pbnRzJyk7XG5cdFx0ZWxlbS5zbGlkZURvd24oKTtcblx0fSxcblxuXHQvLyBDb2xsYXBzZSByZXNvdXJjZSBhbmQgbWFyayBhcyBleHBsaWNpdGx5IGNsb3NlZFxuXHRjb2xsYXBzZUVuZHBvaW50TGlzdEZvclJlc291cmNlOiBmdW5jdGlvbihyZXNvdXJjZSkge1xuXHRcdHZhciByZXNvdXJjZSA9IERvY3MuZXNjYXBlUmVzb3VyY2VOYW1lKHJlc291cmNlKTtcblx0XHRpZiAocmVzb3VyY2UgPT0gJycpIHtcblx0XHRcdCQoJy5yZXNvdXJjZSB1bC5lbmRwb2ludHMnKS5zbGlkZVVwKCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0JCgnbGkjcmVzb3VyY2VfJyArIHJlc291cmNlKS5yZW1vdmVDbGFzcygnYWN0aXZlJyk7XG5cblx0XHR2YXIgZWxlbSA9ICQoJ2xpI3Jlc291cmNlXycgKyByZXNvdXJjZSArICcgdWwuZW5kcG9pbnRzJyk7XG5cdFx0ZWxlbS5zbGlkZVVwKCk7XG5cdH0sXG5cblx0ZXhwYW5kT3BlcmF0aW9uc0ZvclJlc291cmNlOiBmdW5jdGlvbihyZXNvdXJjZSkge1xuXHRcdC8vIE1ha2Ugc3VyZSB0aGUgcmVzb3VyY2UgY29udGFpbmVyIGlzIG9wZW4uLlxuXHRcdERvY3MuZXhwYW5kRW5kcG9pbnRMaXN0Rm9yUmVzb3VyY2UocmVzb3VyY2UpO1xuXG5cdFx0aWYgKHJlc291cmNlID09ICcnKSB7XG5cdFx0XHQkKCcucmVzb3VyY2UgdWwuZW5kcG9pbnRzIGxpLm9wZXJhdGlvbiBkaXYuY29udGVudCcpLnNsaWRlRG93bigpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdCQoJ2xpI3Jlc291cmNlXycgKyBEb2NzLmVzY2FwZVJlc291cmNlTmFtZShyZXNvdXJjZSkgKyAnIGxpLm9wZXJhdGlvbiBkaXYuY29udGVudCcpLmVhY2goZnVuY3Rpb24oKSB7XG5cdFx0XHREb2NzLmV4cGFuZE9wZXJhdGlvbigkKHRoaXMpKTtcblx0XHR9KTtcblx0fSxcblxuXHRjb2xsYXBzZU9wZXJhdGlvbnNGb3JSZXNvdXJjZTogZnVuY3Rpb24ocmVzb3VyY2UpIHtcblx0XHQvLyBNYWtlIHN1cmUgdGhlIHJlc291cmNlIGNvbnRhaW5lciBpcyBvcGVuLi5cblx0XHREb2NzLmV4cGFuZEVuZHBvaW50TGlzdEZvclJlc291cmNlKHJlc291cmNlKTtcblxuXHRcdGlmIChyZXNvdXJjZSA9PSAnJykge1xuXHRcdFx0JCgnLnJlc291cmNlIHVsLmVuZHBvaW50cyBsaS5vcGVyYXRpb24gZGl2LmNvbnRlbnQnKS5zbGlkZVVwKCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0JCgnbGkjcmVzb3VyY2VfJyArIERvY3MuZXNjYXBlUmVzb3VyY2VOYW1lKHJlc291cmNlKSArICcgbGkub3BlcmF0aW9uIGRpdi5jb250ZW50JykuZWFjaChmdW5jdGlvbigpIHtcblx0XHRcdERvY3MuY29sbGFwc2VPcGVyYXRpb24oJCh0aGlzKSk7XG5cdFx0fSk7XG5cdH0sXG5cblx0ZXNjYXBlUmVzb3VyY2VOYW1lOiBmdW5jdGlvbihyZXNvdXJjZSkge1xuXHRcdHJldHVybiByZXNvdXJjZS5yZXBsYWNlKC9bIVwiIyQlJicoKSorLC5cXC86Ozw9Pj9AXFxbXFxcXFxcXVxcXmB7fH1+XS9nLCBcIlxcXFwkJlwiKTtcblx0fSxcblxuXHRleHBhbmRPcGVyYXRpb246IGZ1bmN0aW9uKGVsZW0pIHtcblx0XHRlbGVtLnNsaWRlRG93bigpO1xuXHR9LFxuXG5cdGNvbGxhcHNlT3BlcmF0aW9uOiBmdW5jdGlvbihlbGVtKSB7XG5cdFx0ZWxlbS5zbGlkZVVwKCk7XG5cdH1cbn07XG4iLCIvKiFcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS9lcy1zaGltcy9lczUtc2hpbVxuICogQGxpY2Vuc2UgZXM1LXNoaW0gQ29weXJpZ2h0IDIwMDktMjAxNSBieSBjb250cmlidXRvcnMsIE1JVCBMaWNlbnNlXG4gKiBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2VzLXNoaW1zL2VzNS1zaGltL2Jsb2IvbWFzdGVyL0xJQ0VOU0VcbiAqL1xuXG4vLyB2aW06IHRzPTQgc3RzPTQgc3c9NCBleHBhbmR0YWJcblxuLy8gQWRkIHNlbWljb2xvbiB0byBwcmV2ZW50IElJRkUgZnJvbSBiZWluZyBwYXNzZWQgYXMgYXJndW1lbnQgdG8gY29uY2F0ZW5hdGVkIGNvZGUuXG47XG5cbi8vIFVNRCAoVW5pdmVyc2FsIE1vZHVsZSBEZWZpbml0aW9uKVxuLy8gc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS91bWRqcy91bWQvYmxvYi9tYXN0ZXIvdGVtcGxhdGVzL3JldHVybkV4cG9ydHMuanNcbihmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSkge1xuICAgICd1c2Ugc3RyaWN0JztcblxuICAgIC8qIGdsb2JhbCBkZWZpbmUsIGV4cG9ydHMsIG1vZHVsZSAqL1xuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgLy8gQU1ELiBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlLlxuICAgICAgICBkZWZpbmUoZmFjdG9yeSk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgLy8gTm9kZS4gRG9lcyBub3Qgd29yayB3aXRoIHN0cmljdCBDb21tb25KUywgYnV0XG4gICAgICAgIC8vIG9ubHkgQ29tbW9uSlMtbGlrZSBlbnZpcm9tZW50cyB0aGF0IHN1cHBvcnQgbW9kdWxlLmV4cG9ydHMsXG4gICAgICAgIC8vIGxpa2UgTm9kZS5cbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQnJvd3NlciBnbG9iYWxzIChyb290IGlzIHdpbmRvdylcbiAgICAgICAgcm9vdC5yZXR1cm5FeHBvcnRzID0gZmFjdG9yeSgpO1xuICAgIH1cbn0odGhpcywgZnVuY3Rpb24gKCkge1xuICAgIC8qKlxuICAgICAqIEJyaW5ncyBhbiBlbnZpcm9ubWVudCBhcyBjbG9zZSB0byBFQ01BU2NyaXB0IDUgY29tcGxpYW5jZVxuICAgICAqIGFzIGlzIHBvc3NpYmxlIHdpdGggdGhlIGZhY2lsaXRpZXMgb2YgZXJzdHdoaWxlIGVuZ2luZXMuXG4gICAgICpcbiAgICAgKiBBbm5vdGF0ZWQgRVM1OiBodHRwOi8vZXM1LmdpdGh1Yi5jb20vIChzcGVjaWZpYyBsaW5rcyBiZWxvdylcbiAgICAgKiBFUzUgU3BlYzogaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL3B1YmxpY2F0aW9ucy9maWxlcy9FQ01BLVNUL0VjbWEtMjYyLnBkZlxuICAgICAqIFJlcXVpcmVkIHJlYWRpbmc6IGh0dHA6Ly9qYXZhc2NyaXB0d2VibG9nLndvcmRwcmVzcy5jb20vMjAxMS8xMi8wNS9leHRlbmRpbmctamF2YXNjcmlwdC1uYXRpdmVzL1xuICAgICAqL1xuXG4gICAgLy8gU2hvcnRjdXQgdG8gYW4gb2Z0ZW4gYWNjZXNzZWQgcHJvcGVydGllcywgaW4gb3JkZXIgdG8gYXZvaWQgbXVsdGlwbGVcbiAgICAvLyBkZXJlZmVyZW5jZSB0aGF0IGNvc3RzIHVuaXZlcnNhbGx5LiBUaGlzIGFsc28gaG9sZHMgYSByZWZlcmVuY2UgdG8ga25vd24tZ29vZFxuICAgIC8vIGZ1bmN0aW9ucy5cbiAgICB2YXIgJEFycmF5ID0gQXJyYXk7XG4gICAgdmFyIEFycmF5UHJvdG90eXBlID0gJEFycmF5LnByb3RvdHlwZTtcbiAgICB2YXIgJE9iamVjdCA9IE9iamVjdDtcbiAgICB2YXIgT2JqZWN0UHJvdG90eXBlID0gJE9iamVjdC5wcm90b3R5cGU7XG4gICAgdmFyICRGdW5jdGlvbiA9IEZ1bmN0aW9uO1xuICAgIHZhciBGdW5jdGlvblByb3RvdHlwZSA9ICRGdW5jdGlvbi5wcm90b3R5cGU7XG4gICAgdmFyICRTdHJpbmcgPSBTdHJpbmc7XG4gICAgdmFyIFN0cmluZ1Byb3RvdHlwZSA9ICRTdHJpbmcucHJvdG90eXBlO1xuICAgIHZhciAkTnVtYmVyID0gTnVtYmVyO1xuICAgIHZhciBOdW1iZXJQcm90b3R5cGUgPSAkTnVtYmVyLnByb3RvdHlwZTtcbiAgICB2YXIgYXJyYXlfc2xpY2UgPSBBcnJheVByb3RvdHlwZS5zbGljZTtcbiAgICB2YXIgYXJyYXlfc3BsaWNlID0gQXJyYXlQcm90b3R5cGUuc3BsaWNlO1xuICAgIHZhciBhcnJheV9wdXNoID0gQXJyYXlQcm90b3R5cGUucHVzaDtcbiAgICB2YXIgYXJyYXlfdW5zaGlmdCA9IEFycmF5UHJvdG90eXBlLnVuc2hpZnQ7XG4gICAgdmFyIGFycmF5X2NvbmNhdCA9IEFycmF5UHJvdG90eXBlLmNvbmNhdDtcbiAgICB2YXIgYXJyYXlfam9pbiA9IEFycmF5UHJvdG90eXBlLmpvaW47XG4gICAgdmFyIGNhbGwgPSBGdW5jdGlvblByb3RvdHlwZS5jYWxsO1xuICAgIHZhciBhcHBseSA9IEZ1bmN0aW9uUHJvdG90eXBlLmFwcGx5O1xuICAgIHZhciBtYXggPSBNYXRoLm1heDtcbiAgICB2YXIgbWluID0gTWF0aC5taW47XG5cbiAgICAvLyBIYXZpbmcgYSB0b1N0cmluZyBsb2NhbCB2YXJpYWJsZSBuYW1lIGJyZWFrcyBpbiBPcGVyYSBzbyB1c2UgdG9fc3RyaW5nLlxuICAgIHZhciB0b19zdHJpbmcgPSBPYmplY3RQcm90b3R5cGUudG9TdHJpbmc7XG5cbiAgICAvKiBnbG9iYWwgU3ltYm9sICovXG4gICAgLyogZXNsaW50LWRpc2FibGUgb25lLXZhci1kZWNsYXJhdGlvbi1wZXItbGluZSwgbm8tcmVkZWNsYXJlLCBtYXgtc3RhdGVtZW50cy1wZXItbGluZSAqL1xuICAgIHZhciBoYXNUb1N0cmluZ1RhZyA9IHR5cGVvZiBTeW1ib2wgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIFN5bWJvbC50b1N0cmluZ1RhZyA9PT0gJ3N5bWJvbCc7XG4gICAgdmFyIGlzQ2FsbGFibGU7IC8qIGlubGluZWQgZnJvbSBodHRwczovL25wbWpzLmNvbS9pcy1jYWxsYWJsZSAqLyB2YXIgZm5Ub1N0ciA9IEZ1bmN0aW9uLnByb3RvdHlwZS50b1N0cmluZywgY29uc3RydWN0b3JSZWdleCA9IC9eXFxzKmNsYXNzIC8sIGlzRVM2Q2xhc3NGbiA9IGZ1bmN0aW9uIGlzRVM2Q2xhc3NGbih2YWx1ZSkgeyB0cnkgeyB2YXIgZm5TdHIgPSBmblRvU3RyLmNhbGwodmFsdWUpOyB2YXIgc2luZ2xlU3RyaXBwZWQgPSBmblN0ci5yZXBsYWNlKC9cXC9cXC8uKlxcbi9nLCAnJyk7IHZhciBtdWx0aVN0cmlwcGVkID0gc2luZ2xlU3RyaXBwZWQucmVwbGFjZSgvXFwvXFwqWy5cXHNcXFNdKlxcKlxcLy9nLCAnJyk7IHZhciBzcGFjZVN0cmlwcGVkID0gbXVsdGlTdHJpcHBlZC5yZXBsYWNlKC9cXG4vbWcsICcgJykucmVwbGFjZSgvIHsyfS9nLCAnICcpOyByZXR1cm4gY29uc3RydWN0b3JSZWdleC50ZXN0KHNwYWNlU3RyaXBwZWQpOyB9IGNhdGNoIChlKSB7IHJldHVybiBmYWxzZTsgLyogbm90IGEgZnVuY3Rpb24gKi8gfSB9LCB0cnlGdW5jdGlvbk9iamVjdCA9IGZ1bmN0aW9uIHRyeUZ1bmN0aW9uT2JqZWN0KHZhbHVlKSB7IHRyeSB7IGlmIChpc0VTNkNsYXNzRm4odmFsdWUpKSB7IHJldHVybiBmYWxzZTsgfSBmblRvU3RyLmNhbGwodmFsdWUpOyByZXR1cm4gdHJ1ZTsgfSBjYXRjaCAoZSkgeyByZXR1cm4gZmFsc2U7IH0gfSwgZm5DbGFzcyA9ICdbb2JqZWN0IEZ1bmN0aW9uXScsIGdlbkNsYXNzID0gJ1tvYmplY3QgR2VuZXJhdG9yRnVuY3Rpb25dJywgaXNDYWxsYWJsZSA9IGZ1bmN0aW9uIGlzQ2FsbGFibGUodmFsdWUpIHsgaWYgKCF2YWx1ZSkgeyByZXR1cm4gZmFsc2U7IH0gaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnKSB7IHJldHVybiBmYWxzZTsgfSBpZiAoaGFzVG9TdHJpbmdUYWcpIHsgcmV0dXJuIHRyeUZ1bmN0aW9uT2JqZWN0KHZhbHVlKTsgfSBpZiAoaXNFUzZDbGFzc0ZuKHZhbHVlKSkgeyByZXR1cm4gZmFsc2U7IH0gdmFyIHN0ckNsYXNzID0gdG9fc3RyaW5nLmNhbGwodmFsdWUpOyByZXR1cm4gc3RyQ2xhc3MgPT09IGZuQ2xhc3MgfHwgc3RyQ2xhc3MgPT09IGdlbkNsYXNzOyB9O1xuXG4gICAgdmFyIGlzUmVnZXg7IC8qIGlubGluZWQgZnJvbSBodHRwczovL25wbWpzLmNvbS9pcy1yZWdleCAqLyB2YXIgcmVnZXhFeGVjID0gUmVnRXhwLnByb3RvdHlwZS5leGVjLCB0cnlSZWdleEV4ZWMgPSBmdW5jdGlvbiB0cnlSZWdleEV4ZWModmFsdWUpIHsgdHJ5IHsgcmVnZXhFeGVjLmNhbGwodmFsdWUpOyByZXR1cm4gdHJ1ZTsgfSBjYXRjaCAoZSkgeyByZXR1cm4gZmFsc2U7IH0gfSwgcmVnZXhDbGFzcyA9ICdbb2JqZWN0IFJlZ0V4cF0nOyBpc1JlZ2V4ID0gZnVuY3Rpb24gaXNSZWdleCh2YWx1ZSkgeyBpZiAodHlwZW9mIHZhbHVlICE9PSAnb2JqZWN0JykgeyByZXR1cm4gZmFsc2U7IH0gcmV0dXJuIGhhc1RvU3RyaW5nVGFnID8gdHJ5UmVnZXhFeGVjKHZhbHVlKSA6IHRvX3N0cmluZy5jYWxsKHZhbHVlKSA9PT0gcmVnZXhDbGFzczsgfTtcbiAgICB2YXIgaXNTdHJpbmc7IC8qIGlubGluZWQgZnJvbSBodHRwczovL25wbWpzLmNvbS9pcy1zdHJpbmcgKi8gdmFyIHN0clZhbHVlID0gU3RyaW5nLnByb3RvdHlwZS52YWx1ZU9mLCB0cnlTdHJpbmdPYmplY3QgPSBmdW5jdGlvbiB0cnlTdHJpbmdPYmplY3QodmFsdWUpIHsgdHJ5IHsgc3RyVmFsdWUuY2FsbCh2YWx1ZSk7IHJldHVybiB0cnVlOyB9IGNhdGNoIChlKSB7IHJldHVybiBmYWxzZTsgfSB9LCBzdHJpbmdDbGFzcyA9ICdbb2JqZWN0IFN0cmluZ10nOyBpc1N0cmluZyA9IGZ1bmN0aW9uIGlzU3RyaW5nKHZhbHVlKSB7IGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSB7IHJldHVybiB0cnVlOyB9IGlmICh0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnKSB7IHJldHVybiBmYWxzZTsgfSByZXR1cm4gaGFzVG9TdHJpbmdUYWcgPyB0cnlTdHJpbmdPYmplY3QodmFsdWUpIDogdG9fc3RyaW5nLmNhbGwodmFsdWUpID09PSBzdHJpbmdDbGFzczsgfTtcbiAgICAvKiBlc2xpbnQtZW5hYmxlIG9uZS12YXItZGVjbGFyYXRpb24tcGVyLWxpbmUsIG5vLXJlZGVjbGFyZSwgbWF4LXN0YXRlbWVudHMtcGVyLWxpbmUgKi9cblxuICAgIC8qIGlubGluZWQgZnJvbSBodHRwOi8vbnBtanMuY29tL2RlZmluZS1wcm9wZXJ0aWVzICovXG4gICAgdmFyIHN1cHBvcnRzRGVzY3JpcHRvcnMgPSAkT2JqZWN0LmRlZmluZVByb3BlcnR5ICYmIChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB2YXIgb2JqID0ge307XG4gICAgICAgICAgICAkT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgJ3gnLCB7IGVudW1lcmFibGU6IGZhbHNlLCB2YWx1ZTogb2JqIH0pO1xuICAgICAgICAgICAgZm9yICh2YXIgXyBpbiBvYmopIHsgLy8ganNjczppZ25vcmUgZGlzYWxsb3dVbnVzZWRWYXJpYWJsZXNcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gb2JqLnggPT09IG9iajtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyAvKiB0aGlzIGlzIEVTMyAqL1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfSgpKTtcbiAgICB2YXIgZGVmaW5lUHJvcGVydGllcyA9IChmdW5jdGlvbiAoaGFzKSB7XG4gICAgICAgIC8vIERlZmluZSBjb25maWd1cmFibGUsIHdyaXRhYmxlLCBhbmQgbm9uLWVudW1lcmFibGUgcHJvcHNcbiAgICAgICAgLy8gaWYgdGhleSBkb24ndCBleGlzdC5cbiAgICAgICAgdmFyIGRlZmluZVByb3BlcnR5O1xuICAgICAgICBpZiAoc3VwcG9ydHNEZXNjcmlwdG9ycykge1xuICAgICAgICAgICAgZGVmaW5lUHJvcGVydHkgPSBmdW5jdGlvbiAob2JqZWN0LCBuYW1lLCBtZXRob2QsIGZvcmNlQXNzaWduKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFmb3JjZUFzc2lnbiAmJiAobmFtZSBpbiBvYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgJE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmplY3QsIG5hbWUsIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlOiBtZXRob2RcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkZWZpbmVQcm9wZXJ0eSA9IGZ1bmN0aW9uIChvYmplY3QsIG5hbWUsIG1ldGhvZCwgZm9yY2VBc3NpZ24pIHtcbiAgICAgICAgICAgICAgICBpZiAoIWZvcmNlQXNzaWduICYmIChuYW1lIGluIG9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvYmplY3RbbmFtZV0gPSBtZXRob2Q7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKG9iamVjdCwgbWFwLCBmb3JjZUFzc2lnbikge1xuICAgICAgICAgICAgZm9yICh2YXIgbmFtZSBpbiBtYXApIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFzLmNhbGwobWFwLCBuYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICBkZWZpbmVQcm9wZXJ0eShvYmplY3QsIG5hbWUsIG1hcFtuYW1lXSwgZm9yY2VBc3NpZ24pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9KE9iamVjdFByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eSkpO1xuXG4gICAgLy9cbiAgICAvLyBVdGlsXG4gICAgLy8gPT09PT09XG4gICAgLy9cblxuICAgIC8qIHJlcGxhY2VhYmxlIHdpdGggaHR0cHM6Ly9ucG1qcy5jb20vcGFja2FnZS9lcy1hYnN0cmFjdCAvaGVscGVycy9pc1ByaW1pdGl2ZSAqL1xuICAgIHZhciBpc1ByaW1pdGl2ZSA9IGZ1bmN0aW9uIGlzUHJpbWl0aXZlKGlucHV0KSB7XG4gICAgICAgIHZhciB0eXBlID0gdHlwZW9mIGlucHV0O1xuICAgICAgICByZXR1cm4gaW5wdXQgPT09IG51bGwgfHwgKHR5cGUgIT09ICdvYmplY3QnICYmIHR5cGUgIT09ICdmdW5jdGlvbicpO1xuICAgIH07XG5cbiAgICB2YXIgaXNBY3R1YWxOYU4gPSAkTnVtYmVyLmlzTmFOIHx8IGZ1bmN0aW9uIGlzQWN0dWFsTmFOKHgpIHtcbiAgICAgICAgcmV0dXJuIHggIT09IHg7XG4gICAgfTtcblxuICAgIHZhciBFUyA9IHtcbiAgICAgICAgLy8gRVM1IDkuNFxuICAgICAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3g5LjRcbiAgICAgICAgLy8gaHR0cDovL2pzcGVyZi5jb20vdG8taW50ZWdlclxuICAgICAgICAvKiByZXBsYWNlYWJsZSB3aXRoIGh0dHBzOi8vbnBtanMuY29tL3BhY2thZ2UvZXMtYWJzdHJhY3QgRVM1LlRvSW50ZWdlciAqL1xuICAgICAgICBUb0ludGVnZXI6IGZ1bmN0aW9uIFRvSW50ZWdlcihudW0pIHtcbiAgICAgICAgICAgIHZhciBuID0gK251bTtcbiAgICAgICAgICAgIGlmIChpc0FjdHVhbE5hTihuKSkge1xuICAgICAgICAgICAgICAgIG4gPSAwO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChuICE9PSAwICYmIG4gIT09ICgxIC8gMCkgJiYgbiAhPT0gLSgxIC8gMCkpIHtcbiAgICAgICAgICAgICAgICBuID0gKG4gPiAwIHx8IC0xKSAqIE1hdGguZmxvb3IoTWF0aC5hYnMobikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG47XG4gICAgICAgIH0sXG5cbiAgICAgICAgLyogcmVwbGFjZWFibGUgd2l0aCBodHRwczovL25wbWpzLmNvbS9wYWNrYWdlL2VzLWFic3RyYWN0IEVTNS5Ub1ByaW1pdGl2ZSAqL1xuICAgICAgICBUb1ByaW1pdGl2ZTogZnVuY3Rpb24gVG9QcmltaXRpdmUoaW5wdXQpIHtcbiAgICAgICAgICAgIHZhciB2YWwsIHZhbHVlT2YsIHRvU3RyO1xuICAgICAgICAgICAgaWYgKGlzUHJpbWl0aXZlKGlucHV0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpbnB1dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhbHVlT2YgPSBpbnB1dC52YWx1ZU9mO1xuICAgICAgICAgICAgaWYgKGlzQ2FsbGFibGUodmFsdWVPZikpIHtcbiAgICAgICAgICAgICAgICB2YWwgPSB2YWx1ZU9mLmNhbGwoaW5wdXQpO1xuICAgICAgICAgICAgICAgIGlmIChpc1ByaW1pdGl2ZSh2YWwpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdG9TdHIgPSBpbnB1dC50b1N0cmluZztcbiAgICAgICAgICAgIGlmIChpc0NhbGxhYmxlKHRvU3RyKSkge1xuICAgICAgICAgICAgICAgIHZhbCA9IHRvU3RyLmNhbGwoaW5wdXQpO1xuICAgICAgICAgICAgICAgIGlmIChpc1ByaW1pdGl2ZSh2YWwpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigpO1xuICAgICAgICB9LFxuXG4gICAgICAgIC8vIEVTNSA5LjlcbiAgICAgICAgLy8gaHR0cDovL2VzNS5naXRodWIuY29tLyN4OS45XG4gICAgICAgIC8qIHJlcGxhY2VhYmxlIHdpdGggaHR0cHM6Ly9ucG1qcy5jb20vcGFja2FnZS9lcy1hYnN0cmFjdCBFUzUuVG9PYmplY3QgKi9cbiAgICAgICAgVG9PYmplY3Q6IGZ1bmN0aW9uIChvKSB7XG4gICAgICAgICAgICBpZiAobyA9PSBudWxsKSB7IC8vIHRoaXMgbWF0Y2hlcyBib3RoIG51bGwgYW5kIHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJjYW4ndCBjb252ZXJ0IFwiICsgbyArICcgdG8gb2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJE9iamVjdChvKTtcbiAgICAgICAgfSxcblxuICAgICAgICAvKiByZXBsYWNlYWJsZSB3aXRoIGh0dHBzOi8vbnBtanMuY29tL3BhY2thZ2UvZXMtYWJzdHJhY3QgRVM1LlRvVWludDMyICovXG4gICAgICAgIFRvVWludDMyOiBmdW5jdGlvbiBUb1VpbnQzMih4KSB7XG4gICAgICAgICAgICByZXR1cm4geCA+Pj4gMDtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvL1xuICAgIC8vIEZ1bmN0aW9uXG4gICAgLy8gPT09PT09PT1cbiAgICAvL1xuXG4gICAgLy8gRVMtNSAxNS4zLjQuNVxuICAgIC8vIGh0dHA6Ly9lczUuZ2l0aHViLmNvbS8jeDE1LjMuNC41XG5cbiAgICB2YXIgRW1wdHkgPSBmdW5jdGlvbiBFbXB0eSgpIHt9O1xuXG4gICAgZGVmaW5lUHJvcGVydGllcyhGdW5jdGlvblByb3RvdHlwZSwge1xuICAgICAgICBiaW5kOiBmdW5jdGlvbiBiaW5kKHRoYXQpIHsgLy8gLmxlbmd0aCBpcyAxXG4gICAgICAgICAgICAvLyAxLiBMZXQgVGFyZ2V0IGJlIHRoZSB0aGlzIHZhbHVlLlxuICAgICAgICAgICAgdmFyIHRhcmdldCA9IHRoaXM7XG4gICAgICAgICAgICAvLyAyLiBJZiBJc0NhbGxhYmxlKFRhcmdldCkgaXMgZmFsc2UsIHRocm93IGEgVHlwZUVycm9yIGV4Y2VwdGlvbi5cbiAgICAgICAgICAgIGlmICghaXNDYWxsYWJsZSh0YXJnZXQpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQgY2FsbGVkIG9uIGluY29tcGF0aWJsZSAnICsgdGFyZ2V0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIDMuIExldCBBIGJlIGEgbmV3IChwb3NzaWJseSBlbXB0eSkgaW50ZXJuYWwgbGlzdCBvZiBhbGwgb2YgdGhlXG4gICAgICAgICAgICAvLyAgIGFyZ3VtZW50IHZhbHVlcyBwcm92aWRlZCBhZnRlciB0aGlzQXJnIChhcmcxLCBhcmcyIGV0YyksIGluIG9yZGVyLlxuICAgICAgICAgICAgLy8gWFhYIHNsaWNlZEFyZ3Mgd2lsbCBzdGFuZCBpbiBmb3IgXCJBXCIgaWYgdXNlZFxuICAgICAgICAgICAgdmFyIGFyZ3MgPSBhcnJheV9zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7IC8vIGZvciBub3JtYWwgY2FsbFxuICAgICAgICAgICAgLy8gNC4gTGV0IEYgYmUgYSBuZXcgbmF0aXZlIEVDTUFTY3JpcHQgb2JqZWN0LlxuICAgICAgICAgICAgLy8gMTEuIFNldCB0aGUgW1tQcm90b3R5cGVdXSBpbnRlcm5hbCBwcm9wZXJ0eSBvZiBGIHRvIHRoZSBzdGFuZGFyZFxuICAgICAgICAgICAgLy8gICBidWlsdC1pbiBGdW5jdGlvbiBwcm90b3R5cGUgb2JqZWN0IGFzIHNwZWNpZmllZCBpbiAxNS4zLjMuMS5cbiAgICAgICAgICAgIC8vIDEyLiBTZXQgdGhlIFtbQ2FsbF1dIGludGVybmFsIHByb3BlcnR5IG9mIEYgYXMgZGVzY3JpYmVkIGluXG4gICAgICAgICAgICAvLyAgIDE1LjMuNC41LjEuXG4gICAgICAgICAgICAvLyAxMy4gU2V0IHRoZSBbW0NvbnN0cnVjdF1dIGludGVybmFsIHByb3BlcnR5IG9mIEYgYXMgZGVzY3JpYmVkIGluXG4gICAgICAgICAgICAvLyAgIDE1LjMuNC41LjIuXG4gICAgICAgICAgICAvLyAxNC4gU2V0IHRoZSBbW0hhc0luc3RhbmNlXV0gaW50ZXJuYWwgcHJvcGVydHkgb2YgRiBhcyBkZXNjcmliZWQgaW5cbiAgICAgICAgICAgIC8vICAgMTUuMy40LjUuMy5cbiAgICAgICAgICAgIHZhciBib3VuZDtcbiAgICAgICAgICAgIHZhciBiaW5kZXIgPSBmdW5jdGlvbiAoKSB7XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcyBpbnN0YW5jZW9mIGJvdW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIDE1LjMuNC41LjIgW1tDb25zdHJ1Y3RdXVxuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIHRoZSBbW0NvbnN0cnVjdF1dIGludGVybmFsIG1ldGhvZCBvZiBhIGZ1bmN0aW9uIG9iamVjdCxcbiAgICAgICAgICAgICAgICAgICAgLy8gRiB0aGF0IHdhcyBjcmVhdGVkIHVzaW5nIHRoZSBiaW5kIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aXRoIGFcbiAgICAgICAgICAgICAgICAgICAgLy8gbGlzdCBvZiBhcmd1bWVudHMgRXh0cmFBcmdzLCB0aGUgZm9sbG93aW5nIHN0ZXBzIGFyZSB0YWtlbjpcbiAgICAgICAgICAgICAgICAgICAgLy8gMS4gTGV0IHRhcmdldCBiZSB0aGUgdmFsdWUgb2YgRidzIFtbVGFyZ2V0RnVuY3Rpb25dXVxuICAgICAgICAgICAgICAgICAgICAvLyAgIGludGVybmFsIHByb3BlcnR5LlxuICAgICAgICAgICAgICAgICAgICAvLyAyLiBJZiB0YXJnZXQgaGFzIG5vIFtbQ29uc3RydWN0XV0gaW50ZXJuYWwgbWV0aG9kLCBhXG4gICAgICAgICAgICAgICAgICAgIC8vICAgVHlwZUVycm9yIGV4Y2VwdGlvbiBpcyB0aHJvd24uXG4gICAgICAgICAgICAgICAgICAgIC8vIDMuIExldCBib3VuZEFyZ3MgYmUgdGhlIHZhbHVlIG9mIEYncyBbW0JvdW5kQXJnc11dIGludGVybmFsXG4gICAgICAgICAgICAgICAgICAgIC8vICAgcHJvcGVydHkuXG4gICAgICAgICAgICAgICAgICAgIC8vIDQuIExldCBhcmdzIGJlIGEgbmV3IGxpc3QgY29udGFpbmluZyB0aGUgc2FtZSB2YWx1ZXMgYXMgdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vICAgbGlzdCBib3VuZEFyZ3MgaW4gdGhlIHNhbWUgb3JkZXIgZm9sbG93ZWQgYnkgdGhlIHNhbWVcbiAgICAgICAgICAgICAgICAgICAgLy8gICB2YWx1ZXMgYXMgdGhlIGxpc3QgRXh0cmFBcmdzIGluIHRoZSBzYW1lIG9yZGVyLlxuICAgICAgICAgICAgICAgICAgICAvLyA1LiBSZXR1cm4gdGhlIHJlc3VsdCBvZiBjYWxsaW5nIHRoZSBbW0NvbnN0cnVjdF1dIGludGVybmFsXG4gICAgICAgICAgICAgICAgICAgIC8vICAgbWV0aG9kIG9mIHRhcmdldCBwcm92aWRpbmcgYXJncyBhcyB0aGUgYXJndW1lbnRzLlxuXG4gICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBhcHBseS5jYWxsKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5X2NvbmNhdC5jYWxsKGFyZ3MsIGFycmF5X3NsaWNlLmNhbGwoYXJndW1lbnRzKSlcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCRPYmplY3QocmVzdWx0KSA9PT0gcmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gMTUuMy40LjUuMSBbW0NhbGxdXVxuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuIHRoZSBbW0NhbGxdXSBpbnRlcm5hbCBtZXRob2Qgb2YgYSBmdW5jdGlvbiBvYmplY3QsIEYsXG4gICAgICAgICAgICAgICAgICAgIC8vIHdoaWNoIHdhcyBjcmVhdGVkIHVzaW5nIHRoZSBiaW5kIGZ1bmN0aW9uIGlzIGNhbGxlZCB3aXRoIGFcbiAgICAgICAgICAgICAgICAgICAgLy8gdGhpcyB2YWx1ZSBhbmQgYSBsaXN0IG9mIGFyZ3VtZW50cyBFeHRyYUFyZ3MsIHRoZSBmb2xsb3dpbmdcbiAgICAgICAgICAgICAgICAgICAgLy8gc3RlcHMgYXJlIHRha2VuOlxuICAgICAgICAgICAgICAgICAgICAvLyAxLiBMZXQgYm91bmRBcmdzIGJlIHRoZSB2YWx1ZSBvZiBGJ3MgW1tCb3VuZEFyZ3NdXSBpbnRlcm5hbFxuICAgICAgICAgICAgICAgICAgICAvLyAgIHByb3BlcnR5LlxuICAgICAgICAgICAgICAgICAgICAvLyAyLiBMZXQgYm91bmRUaGlzIGJlIHRoZSB2YWx1ZSBvZiBGJ3MgW1tCb3VuZFRoaXNdXSBpbnRlcm5hbFxuICAgICAgICAgICAgICAgICAgICAvLyAgIHByb3BlcnR5LlxuICAgICAgICAgICAgICAgICAgICAvLyAzLiBMZXQgdGFyZ2V0IGJlIHRoZSB2YWx1ZSBvZiBGJ3MgW1tUYXJnZXRGdW5jdGlvbl1dIGludGVybmFsXG4gICAgICAgICAgICAgICAgICAgIC8vICAgcHJvcGVydHkuXG4gICAgICAgICAgICAgICAgICAgIC8vIDQuIExldCBhcmdzIGJlIGEgbmV3IGxpc3QgY29udGFpbmluZyB0aGUgc2FtZSB2YWx1ZXMgYXMgdGhlXG4gICAgICAgICAgICAgICAgICAgIC8vICAgbGlzdCBib3VuZEFyZ3MgaW4gdGhlIHNhbWUgb3JkZXIgZm9sbG93ZWQgYnkgdGhlIHNhbWVcbiAgICAgICAgICAgICAgICAgICAgLy8gICB2YWx1ZXMgYXMgdGhlIGxpc3QgRXh0cmFBcmdzIGluIHRoZSBzYW1lIG9yZGVyLlxuICAgICAgICAgICAgICAgICAgICAvLyA1LiBSZXR1cm4gdGhlIHJlc3VsdCBvZiBjYWxsaW5nIHRoZSBbW0NhbGxdXSBpbnRlcm5hbCBtZXRob2RcbiAgICAgICAgICAgICAgICAgICAgLy8gICBvZiB0YXJnZXQgcHJvdmlkaW5nIGJvdW5kVGhpcyBhcyB0aGUgdGhpcyB2YWx1ZSBhbmRcbiAgICAgICAgICAgICAgICAgICAgLy8gICBwcm92aWRpbmcgYXJncyBhcyB0aGUgYXJndW1lbnRzLlxuXG4gICAgICAgICAgICAgICAgICAgIC8vIGVxdWl2OiB0YXJnZXQuY2FsbCh0aGlzLCAuLi5ib3VuZEFyZ3MsIC4uLmFyZ3MpXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBhcHBseS5jYWxsKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0LFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhhdCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5X2NvbmNhdC5jYWxsKGFyZ3MsIGFycmF5X3NsaWNlLmNhbGwoYXJndW1lbnRzKSlcbiAgICAgICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gMTUuIElmIHRoZSBbW0NsYXNzXV0gaW50ZXJuYWwgcHJvcGVydHkgb2YgVGFyZ2V0IGlzIFwiRnVuY3Rpb25cIiwgdGhlblxuICAgICAgICAgICAgLy8gICAgIGEuIExldCBMIGJlIHRoZSBsZW5ndGggcHJvcGVydHkgb2YgVGFyZ2V0IG1pbnVzIHRoZSBsZW5ndGggb2YgQS5cbiAgICAgICAgICAgIC8vICAgICBiLiBTZXQgdGhlIGxlbmd0aCBvd24gcHJvcGVydHkgb2YgRiB0byBlaXRoZXIgMCBvciBMLCB3aGljaGV2ZXIgaXNcbiAgICAgICAgICAgIC8vICAgICAgIGxhcmdlci5cbiAgICAgICAgICAgIC8vIDE2LiBFbHNlIHNldCB0aGUgbGVuZ3RoIG93biBwcm9wZXJ0eSBvZiBGIHRvIDAuXG5cbiAgICAgICAgICAgIHZhciBib3VuZExlbmd0aCA9IG1heCgwLCB0YXJnZXQubGVuZ3RoIC0gYXJncy5sZW5ndGgpO1xuXG4gICAgICAgICAgICAvLyAxNy4gU2V0IHRoZSBhdHRyaWJ1dGVzIG9mIHRoZSBsZW5ndGggb3duIHByb3BlcnR5IG9mIEYgdG8gdGhlIHZhbHVlc1xuICAgICAgICAgICAgLy8gICBzcGVjaWZpZWQgaW4gMTUuMy41LjEuXG4gICAgICAgICAgICB2YXIgYm91bmRBcmdzID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGJvdW5kTGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBhcnJheV9wdXNoLmNhbGwoYm91bmRBcmdzLCAnJCcgKyBpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gWFhYIEJ1aWxkIGEgZHluYW1pYyBmdW5jdGlvbiB3aXRoIGRlc2lyZWQgYW1vdW50IG9mIGFyZ3VtZW50cyBpcyB0aGUgb25seVxuICAgICAgICAgICAgLy8gd2F5IHRvIHNldCB0aGUgbGVuZ3RoIHByb3BlcnR5IG9mIGEgZnVuY3Rpb24uXG4gICAgICAgICAgICAvLyBJbiBlbnZpcm9ubWVudHMgd2hlcmUgQ29udGVudCBTZWN1cml0eSBQb2xpY2llcyBlbmFibGVkIChDaHJvbWUgZXh0ZW5zaW9ucyxcbiAgICAgICAgICAgIC8vIGZvciBleC4pIGFsbCB1c2Ugb2YgZXZhbCBvciBGdW5jdGlvbiBjb3N0cnVjdG9yIHRocm93cyBhbiBleGNlcHRpb24uXG4gICAgICAgICAgICAvLyBIb3dldmVyIGluIGFsbCBvZiB0aGVzZSBlbnZpcm9ubWVudHMgRnVuY3Rpb24ucHJvdG90eXBlLmJpbmQgZXhpc3RzXG4gICAgICAgICAgICAvLyBhbmQgc28gdGhpcyBjb2RlIHdpbGwgbmV2ZXIgYmUgZXhlY3V0ZWQuXG4gICAgICAgICAgICBib3VuZCA9ICRGdW5jdGlvbignYmluZGVyJywgJ3JldHVybiBmdW5jdGlvbiAoJyArIGFycmF5X2pvaW4uY2FsbChib3VuZEFyZ3MsICcsJykgKyAnKXsgcmV0dXJuIGJpbmRlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOyB9JykoYmluZGVyKTtcblxuICAgICAgICAgICAgaWYgKHRhcmdldC5wcm90b3R5cGUpIHtcbiAgICAgICAgICAgICAgICBFbXB0eS5wcm90b3R5cGUgPSB0YXJnZXQucHJvdG90eXBlO1xuICAgICAgICAgICAgICAgIGJvdW5kLnByb3RvdHlwZSA9IG5ldyBFbXB0eSgpO1xuICAgICAgICAgICAgICAgIC8vIENsZWFuIHVwIGRhbmdsaW5nIHJlZmVyZW5jZXMuXG4gICAgICAgICAgICAgICAgRW1wdHkucHJvdG90eXBlID0gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVE9ET1xuICAgICAgICAgICAgLy8gMTguIFNldCB0aGUgW1tFeHRlbnNpYmxlXV0gaW50ZXJuYWwgcHJvcGVydHkgb2YgRiB0byB0cnVlLlxuXG4gICAgICAgICAgICAvLyBUT0RPXG4gICAgICAgICAgICAvLyAxOS4gTGV0IHRocm93ZXIgYmUgdGhlIFtbVGhyb3dUeXBlRXJyb3JdXSBmdW5jdGlvbiBPYmplY3QgKDEzLjIuMykuXG4gICAgICAgICAgICAvLyAyMC4gQ2FsbCB0aGUgW1tEZWZpbmVPd25Qcm9wZXJ0eV1dIGludGVybmFsIG1ldGhvZCBvZiBGIHdpdGhcbiAgICAgICAgICAgIC8vICAgYXJndW1lbnRzIFwiY2FsbGVyXCIsIFByb3BlcnR5RGVzY3JpcHRvciB7W1tHZXRdXTogdGhyb3dlciwgW1tTZXRdXTpcbiAgICAgICAgICAgIC8vICAgdGhyb3dlciwgW1tFbnVtZXJhYmxlXV06IGZhbHNlLCBbW0NvbmZpZ3VyYWJsZV1dOiBmYWxzZX0sIGFuZFxuICAgICAgICAgICAgLy8gICBmYWxzZS5cbiAgICAgICAgICAgIC8vIDIxLiBDYWxsIHRoZSBbW0RlZmluZU93blByb3BlcnR5XV0gaW50ZXJuYWwgbWV0aG9kIG9mIEYgd2l0aFxuICAgICAgICAgICAgLy8gICBhcmd1bWVudHMgXCJhcmd1bWVudHNcIiwgUHJvcGVydHlEZXNjcmlwdG9yIHtbW0dldF1dOiB0aHJvd2VyLFxuICAgICAgICAgICAgLy8gICBbW1NldF1dOiB0aHJvd2VyLCBbW0VudW1lcmFibGVdXTogZmFsc2UsIFtbQ29uZmlndXJhYmxlXV06IGZhbHNlfSxcbiAgICAgICAgICAgIC8vICAgYW5kIGZhbHNlLlxuXG4gICAgICAgICAgICAvLyBUT0RPXG4gICAgICAgICAgICAvLyBOT1RFIEZ1bmN0aW9uIG9iamVjdHMgY3JlYXRlZCB1c2luZyBGdW5jdGlvbi5wcm90b3R5cGUuYmluZCBkbyBub3RcbiAgICAgICAgICAgIC8vIGhhdmUgYSBwcm90b3R5cGUgcHJvcGVydHkgb3IgdGhlIFtbQ29kZV1dLCBbW0Zvcm1hbFBhcmFtZXRlcnNdXSwgYW5kXG4gICAgICAgICAgICAvLyBbW1Njb3BlXV0gaW50ZXJuYWwgcHJvcGVydGllcy5cbiAgICAgICAgICAgIC8vIFhYWCBjYW4ndCBkZWxldGUgcHJvdG90eXBlIGluIHB1cmUtanMuXG5cbiAgICAgICAgICAgIC8vIDIyLiBSZXR1cm4gRi5cbiAgICAgICAgICAgIHJldHVybiBib3VuZDtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gX1BsZWFzZSBub3RlOiBTaG9ydGN1dHMgYXJlIGRlZmluZWQgYWZ0ZXIgYEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kYCBhcyB3ZVxuICAgIC8vIHVzZSBpdCBpbiBkZWZpbmluZyBzaG9ydGN1dHMuXG4gICAgdmFyIG93bnMgPSBjYWxsLmJpbmQoT2JqZWN0UHJvdG90eXBlLmhhc093blByb3BlcnR5KTtcbiAgICB2YXIgdG9TdHIgPSBjYWxsLmJpbmQoT2JqZWN0UHJvdG90eXBlLnRvU3RyaW5nKTtcbiAgICB2YXIgYXJyYXlTbGljZSA9IGNhbGwuYmluZChhcnJheV9zbGljZSk7XG4gICAgdmFyIGFycmF5U2xpY2VBcHBseSA9IGFwcGx5LmJpbmQoYXJyYXlfc2xpY2UpO1xuICAgIHZhciBzdHJTbGljZSA9IGNhbGwuYmluZChTdHJpbmdQcm90b3R5cGUuc2xpY2UpO1xuICAgIHZhciBzdHJTcGxpdCA9IGNhbGwuYmluZChTdHJpbmdQcm90b3R5cGUuc3BsaXQpO1xuICAgIHZhciBzdHJJbmRleE9mID0gY2FsbC5iaW5kKFN0cmluZ1Byb3RvdHlwZS5pbmRleE9mKTtcbiAgICB2YXIgcHVzaENhbGwgPSBjYWxsLmJpbmQoYXJyYXlfcHVzaCk7XG4gICAgdmFyIGlzRW51bSA9IGNhbGwuYmluZChPYmplY3RQcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUpO1xuICAgIHZhciBhcnJheVNvcnQgPSBjYWxsLmJpbmQoQXJyYXlQcm90b3R5cGUuc29ydCk7XG5cbiAgICAvL1xuICAgIC8vIEFycmF5XG4gICAgLy8gPT09PT1cbiAgICAvL1xuXG4gICAgdmFyIGlzQXJyYXkgPSAkQXJyYXkuaXNBcnJheSB8fCBmdW5jdGlvbiBpc0FycmF5KG9iaikge1xuICAgICAgICByZXR1cm4gdG9TdHIob2JqKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbiAgICB9O1xuXG4gICAgLy8gRVM1IDE1LjQuNC4xMlxuICAgIC8vIGh0dHA6Ly9lczUuZ2l0aHViLmNvbS8jeDE1LjQuNC4xM1xuICAgIC8vIFJldHVybiBsZW4rYXJnQ291bnQuXG4gICAgLy8gW2J1Z2ZpeCwgaWVsdDhdXG4gICAgLy8gSUUgPCA4IGJ1ZzogW10udW5zaGlmdCgwKSA9PT0gdW5kZWZpbmVkIGJ1dCBzaG91bGQgYmUgXCIxXCJcbiAgICB2YXIgaGFzVW5zaGlmdFJldHVyblZhbHVlQnVnID0gW10udW5zaGlmdCgwKSAhPT0gMTtcbiAgICBkZWZpbmVQcm9wZXJ0aWVzKEFycmF5UHJvdG90eXBlLCB7XG4gICAgICAgIHVuc2hpZnQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGFycmF5X3Vuc2hpZnQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxlbmd0aDtcbiAgICAgICAgfVxuICAgIH0sIGhhc1Vuc2hpZnRSZXR1cm5WYWx1ZUJ1Zyk7XG5cbiAgICAvLyBFUzUgMTUuNC4zLjJcbiAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3gxNS40LjMuMlxuICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2lzQXJyYXlcbiAgICBkZWZpbmVQcm9wZXJ0aWVzKCRBcnJheSwgeyBpc0FycmF5OiBpc0FycmF5IH0pO1xuXG4gICAgLy8gVGhlIElzQ2FsbGFibGUoKSBjaGVjayBpbiB0aGUgQXJyYXkgZnVuY3Rpb25zXG4gICAgLy8gaGFzIGJlZW4gcmVwbGFjZWQgd2l0aCBhIHN0cmljdCBjaGVjayBvbiB0aGVcbiAgICAvLyBpbnRlcm5hbCBjbGFzcyBvZiB0aGUgb2JqZWN0IHRvIHRyYXAgY2FzZXMgd2hlcmVcbiAgICAvLyB0aGUgcHJvdmlkZWQgZnVuY3Rpb24gd2FzIGFjdHVhbGx5IGEgcmVndWxhclxuICAgIC8vIGV4cHJlc3Npb24gbGl0ZXJhbCwgd2hpY2ggaW4gVjggYW5kXG4gICAgLy8gSmF2YVNjcmlwdENvcmUgaXMgYSB0eXBlb2YgXCJmdW5jdGlvblwiLiAgT25seSBpblxuICAgIC8vIFY4IGFyZSByZWd1bGFyIGV4cHJlc3Npb24gbGl0ZXJhbHMgcGVybWl0dGVkIGFzXG4gICAgLy8gcmVkdWNlIHBhcmFtZXRlcnMsIHNvIGl0IGlzIGRlc2lyYWJsZSBpbiB0aGVcbiAgICAvLyBnZW5lcmFsIGNhc2UgZm9yIHRoZSBzaGltIHRvIG1hdGNoIHRoZSBtb3JlXG4gICAgLy8gc3RyaWN0IGFuZCBjb21tb24gYmVoYXZpb3Igb2YgcmVqZWN0aW5nIHJlZ3VsYXJcbiAgICAvLyBleHByZXNzaW9ucy5cblxuICAgIC8vIEVTNSAxNS40LjQuMThcbiAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3gxNS40LjQuMThcbiAgICAvLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9hcnJheS9mb3JFYWNoXG5cbiAgICAvLyBDaGVjayBmYWlsdXJlIG9mIGJ5LWluZGV4IGFjY2VzcyBvZiBzdHJpbmcgY2hhcmFjdGVycyAoSUUgPCA5KVxuICAgIC8vIGFuZCBmYWlsdXJlIG9mIGAwIGluIGJveGVkU3RyaW5nYCAoUmhpbm8pXG4gICAgdmFyIGJveGVkU3RyaW5nID0gJE9iamVjdCgnYScpO1xuICAgIHZhciBzcGxpdFN0cmluZyA9IGJveGVkU3RyaW5nWzBdICE9PSAnYScgfHwgISgwIGluIGJveGVkU3RyaW5nKTtcblxuICAgIHZhciBwcm9wZXJseUJveGVzQ29udGV4dCA9IGZ1bmN0aW9uIHByb3Blcmx5Qm94ZWQobWV0aG9kKSB7XG4gICAgICAgIC8vIENoZWNrIG5vZGUgMC42LjIxIGJ1ZyB3aGVyZSB0aGlyZCBwYXJhbWV0ZXIgaXMgbm90IGJveGVkXG4gICAgICAgIHZhciBwcm9wZXJseUJveGVzTm9uU3RyaWN0ID0gdHJ1ZTtcbiAgICAgICAgdmFyIHByb3Blcmx5Qm94ZXNTdHJpY3QgPSB0cnVlO1xuICAgICAgICB2YXIgdGhyZXdFeGNlcHRpb24gPSBmYWxzZTtcbiAgICAgICAgaWYgKG1ldGhvZCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBtZXRob2QuY2FsbCgnZm9vJywgZnVuY3Rpb24gKF8sIF9fLCBjb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY29udGV4dCAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb3Blcmx5Qm94ZXNOb25TdHJpY3QgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgbWV0aG9kLmNhbGwoWzFdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgICAgICd1c2Ugc3RyaWN0JztcblxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJseUJveGVzU3RyaWN0ID0gdHlwZW9mIHRoaXMgPT09ICdzdHJpbmcnO1xuICAgICAgICAgICAgICAgIH0sICd4Jyk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgdGhyZXdFeGNlcHRpb24gPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAhIW1ldGhvZCAmJiAhdGhyZXdFeGNlcHRpb24gJiYgcHJvcGVybHlCb3hlc05vblN0cmljdCAmJiBwcm9wZXJseUJveGVzU3RyaWN0O1xuICAgIH07XG5cbiAgICBkZWZpbmVQcm9wZXJ0aWVzKEFycmF5UHJvdG90eXBlLCB7XG4gICAgICAgIGZvckVhY2g6IGZ1bmN0aW9uIGZvckVhY2goY2FsbGJhY2tmbi8qLCB0aGlzQXJnKi8pIHtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSBFUy5Ub09iamVjdCh0aGlzKTtcbiAgICAgICAgICAgIHZhciBzZWxmID0gc3BsaXRTdHJpbmcgJiYgaXNTdHJpbmcodGhpcykgPyBzdHJTcGxpdCh0aGlzLCAnJykgOiBvYmplY3Q7XG4gICAgICAgICAgICB2YXIgaSA9IC0xO1xuICAgICAgICAgICAgdmFyIGxlbmd0aCA9IEVTLlRvVWludDMyKHNlbGYubGVuZ3RoKTtcbiAgICAgICAgICAgIHZhciBUO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgVCA9IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgbm8gY2FsbGJhY2sgZnVuY3Rpb24gb3IgaWYgY2FsbGJhY2sgaXMgbm90IGEgY2FsbGFibGUgZnVuY3Rpb25cbiAgICAgICAgICAgIGlmICghaXNDYWxsYWJsZShjYWxsYmFja2ZuKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FycmF5LnByb3RvdHlwZS5mb3JFYWNoIGNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB3aGlsZSAoKytpIDwgbGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgaW4gc2VsZikge1xuICAgICAgICAgICAgICAgICAgICAvLyBJbnZva2UgdGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHdpdGggY2FsbCwgcGFzc2luZyBhcmd1bWVudHM6XG4gICAgICAgICAgICAgICAgICAgIC8vIGNvbnRleHQsIHByb3BlcnR5IHZhbHVlLCBwcm9wZXJ0eSBrZXksIHRoaXNBcmcgb2JqZWN0XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgVCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrZm4oc2VsZltpXSwgaSwgb2JqZWN0KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhbGxiYWNrZm4uY2FsbChULCBzZWxmW2ldLCBpLCBvYmplY3QpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSwgIXByb3Blcmx5Qm94ZXNDb250ZXh0KEFycmF5UHJvdG90eXBlLmZvckVhY2gpKTtcblxuICAgIC8vIEVTNSAxNS40LjQuMTlcbiAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3gxNS40LjQuMTlcbiAgICAvLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9Db3JlX0phdmFTY3JpcHRfMS41X1JlZmVyZW5jZS9PYmplY3RzL0FycmF5L21hcFxuICAgIGRlZmluZVByb3BlcnRpZXMoQXJyYXlQcm90b3R5cGUsIHtcbiAgICAgICAgbWFwOiBmdW5jdGlvbiBtYXAoY2FsbGJhY2tmbi8qLCB0aGlzQXJnKi8pIHtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSBFUy5Ub09iamVjdCh0aGlzKTtcbiAgICAgICAgICAgIHZhciBzZWxmID0gc3BsaXRTdHJpbmcgJiYgaXNTdHJpbmcodGhpcykgPyBzdHJTcGxpdCh0aGlzLCAnJykgOiBvYmplY3Q7XG4gICAgICAgICAgICB2YXIgbGVuZ3RoID0gRVMuVG9VaW50MzIoc2VsZi5sZW5ndGgpO1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9ICRBcnJheShsZW5ndGgpO1xuICAgICAgICAgICAgdmFyIFQ7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICBUID0gYXJndW1lbnRzWzFdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJZiBubyBjYWxsYmFjayBmdW5jdGlvbiBvciBpZiBjYWxsYmFjayBpcyBub3QgYSBjYWxsYWJsZSBmdW5jdGlvblxuICAgICAgICAgICAgaWYgKCFpc0NhbGxhYmxlKGNhbGxiYWNrZm4pKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJyYXkucHJvdG90eXBlLm1hcCBjYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIGlmIChpIGluIHNlbGYpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBUID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2ldID0gY2FsbGJhY2tmbihzZWxmW2ldLCBpLCBvYmplY3QpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2ldID0gY2FsbGJhY2tmbi5jYWxsKFQsIHNlbGZbaV0sIGksIG9iamVjdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfSwgIXByb3Blcmx5Qm94ZXNDb250ZXh0KEFycmF5UHJvdG90eXBlLm1hcCkpO1xuXG4gICAgLy8gRVM1IDE1LjQuNC4yMFxuICAgIC8vIGh0dHA6Ly9lczUuZ2l0aHViLmNvbS8jeDE1LjQuNC4yMFxuICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL0NvcmVfSmF2YVNjcmlwdF8xLjVfUmVmZXJlbmNlL09iamVjdHMvQXJyYXkvZmlsdGVyXG4gICAgZGVmaW5lUHJvcGVydGllcyhBcnJheVByb3RvdHlwZSwge1xuICAgICAgICBmaWx0ZXI6IGZ1bmN0aW9uIGZpbHRlcihjYWxsYmFja2ZuLyosIHRoaXNBcmcqLykge1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IEVTLlRvT2JqZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIHNlbGYgPSBzcGxpdFN0cmluZyAmJiBpc1N0cmluZyh0aGlzKSA/IHN0clNwbGl0KHRoaXMsICcnKSA6IG9iamVjdDtcbiAgICAgICAgICAgIHZhciBsZW5ndGggPSBFUy5Ub1VpbnQzMihzZWxmLmxlbmd0aCk7XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgICAgICB2YXIgdmFsdWU7XG4gICAgICAgICAgICB2YXIgVDtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgIFQgPSBhcmd1bWVudHNbMV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIElmIG5vIGNhbGxiYWNrIGZ1bmN0aW9uIG9yIGlmIGNhbGxiYWNrIGlzIG5vdCBhIGNhbGxhYmxlIGZ1bmN0aW9uXG4gICAgICAgICAgICBpZiAoIWlzQ2FsbGFibGUoY2FsbGJhY2tmbikpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcnJheS5wcm90b3R5cGUuZmlsdGVyIGNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgaW4gc2VsZikge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHNlbGZbaV07XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgVCA9PT0gJ3VuZGVmaW5lZCcgPyBjYWxsYmFja2ZuKHZhbHVlLCBpLCBvYmplY3QpIDogY2FsbGJhY2tmbi5jYWxsKFQsIHZhbHVlLCBpLCBvYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwdXNoQ2FsbChyZXN1bHQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9LCAhcHJvcGVybHlCb3hlc0NvbnRleHQoQXJyYXlQcm90b3R5cGUuZmlsdGVyKSk7XG5cbiAgICAvLyBFUzUgMTUuNC40LjE2XG4gICAgLy8gaHR0cDovL2VzNS5naXRodWIuY29tLyN4MTUuNC40LjE2XG4gICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4vSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvZXZlcnlcbiAgICBkZWZpbmVQcm9wZXJ0aWVzKEFycmF5UHJvdG90eXBlLCB7XG4gICAgICAgIGV2ZXJ5OiBmdW5jdGlvbiBldmVyeShjYWxsYmFja2ZuLyosIHRoaXNBcmcqLykge1xuICAgICAgICAgICAgdmFyIG9iamVjdCA9IEVTLlRvT2JqZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIHNlbGYgPSBzcGxpdFN0cmluZyAmJiBpc1N0cmluZyh0aGlzKSA/IHN0clNwbGl0KHRoaXMsICcnKSA6IG9iamVjdDtcbiAgICAgICAgICAgIHZhciBsZW5ndGggPSBFUy5Ub1VpbnQzMihzZWxmLmxlbmd0aCk7XG4gICAgICAgICAgICB2YXIgVDtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgIFQgPSBhcmd1bWVudHNbMV07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIElmIG5vIGNhbGxiYWNrIGZ1bmN0aW9uIG9yIGlmIGNhbGxiYWNrIGlzIG5vdCBhIGNhbGxhYmxlIGZ1bmN0aW9uXG4gICAgICAgICAgICBpZiAoIWlzQ2FsbGFibGUoY2FsbGJhY2tmbikpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcnJheS5wcm90b3R5cGUuZXZlcnkgY2FsbGJhY2sgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaSBpbiBzZWxmICYmICEodHlwZW9mIFQgPT09ICd1bmRlZmluZWQnID8gY2FsbGJhY2tmbihzZWxmW2ldLCBpLCBvYmplY3QpIDogY2FsbGJhY2tmbi5jYWxsKFQsIHNlbGZbaV0sIGksIG9iamVjdCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0sICFwcm9wZXJseUJveGVzQ29udGV4dChBcnJheVByb3RvdHlwZS5ldmVyeSkpO1xuXG4gICAgLy8gRVM1IDE1LjQuNC4xN1xuICAgIC8vIGh0dHA6Ly9lczUuZ2l0aHViLmNvbS8jeDE1LjQuNC4xN1xuICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L3NvbWVcbiAgICBkZWZpbmVQcm9wZXJ0aWVzKEFycmF5UHJvdG90eXBlLCB7XG4gICAgICAgIHNvbWU6IGZ1bmN0aW9uIHNvbWUoY2FsbGJhY2tmbi8qLCB0aGlzQXJnICovKSB7XG4gICAgICAgICAgICB2YXIgb2JqZWN0ID0gRVMuVG9PYmplY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHNwbGl0U3RyaW5nICYmIGlzU3RyaW5nKHRoaXMpID8gc3RyU3BsaXQodGhpcywgJycpIDogb2JqZWN0O1xuICAgICAgICAgICAgdmFyIGxlbmd0aCA9IEVTLlRvVWludDMyKHNlbGYubGVuZ3RoKTtcbiAgICAgICAgICAgIHZhciBUO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgVCA9IGFyZ3VtZW50c1sxXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSWYgbm8gY2FsbGJhY2sgZnVuY3Rpb24gb3IgaWYgY2FsbGJhY2sgaXMgbm90IGEgY2FsbGFibGUgZnVuY3Rpb25cbiAgICAgICAgICAgIGlmICghaXNDYWxsYWJsZShjYWxsYmFja2ZuKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FycmF5LnByb3RvdHlwZS5zb21lIGNhbGxiYWNrIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgaW4gc2VsZiAmJiAodHlwZW9mIFQgPT09ICd1bmRlZmluZWQnID8gY2FsbGJhY2tmbihzZWxmW2ldLCBpLCBvYmplY3QpIDogY2FsbGJhY2tmbi5jYWxsKFQsIHNlbGZbaV0sIGksIG9iamVjdCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH0sICFwcm9wZXJseUJveGVzQ29udGV4dChBcnJheVByb3RvdHlwZS5zb21lKSk7XG5cbiAgICAvLyBFUzUgMTUuNC40LjIxXG4gICAgLy8gaHR0cDovL2VzNS5naXRodWIuY29tLyN4MTUuNC40LjIxXG4gICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4vQ29yZV9KYXZhU2NyaXB0XzEuNV9SZWZlcmVuY2UvT2JqZWN0cy9BcnJheS9yZWR1Y2VcbiAgICB2YXIgcmVkdWNlQ29lcmNlc1RvT2JqZWN0ID0gZmFsc2U7XG4gICAgaWYgKEFycmF5UHJvdG90eXBlLnJlZHVjZSkge1xuICAgICAgICByZWR1Y2VDb2VyY2VzVG9PYmplY3QgPSB0eXBlb2YgQXJyYXlQcm90b3R5cGUucmVkdWNlLmNhbGwoJ2VzNScsIGZ1bmN0aW9uIChfLCBfXywgX19fLCBsaXN0KSB7XG4gICAgICAgICAgICByZXR1cm4gbGlzdDtcbiAgICAgICAgfSkgPT09ICdvYmplY3QnO1xuICAgIH1cbiAgICBkZWZpbmVQcm9wZXJ0aWVzKEFycmF5UHJvdG90eXBlLCB7XG4gICAgICAgIHJlZHVjZTogZnVuY3Rpb24gcmVkdWNlKGNhbGxiYWNrZm4vKiwgaW5pdGlhbFZhbHVlKi8pIHtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSBFUy5Ub09iamVjdCh0aGlzKTtcbiAgICAgICAgICAgIHZhciBzZWxmID0gc3BsaXRTdHJpbmcgJiYgaXNTdHJpbmcodGhpcykgPyBzdHJTcGxpdCh0aGlzLCAnJykgOiBvYmplY3Q7XG4gICAgICAgICAgICB2YXIgbGVuZ3RoID0gRVMuVG9VaW50MzIoc2VsZi5sZW5ndGgpO1xuXG4gICAgICAgICAgICAvLyBJZiBubyBjYWxsYmFjayBmdW5jdGlvbiBvciBpZiBjYWxsYmFjayBpcyBub3QgYSBjYWxsYWJsZSBmdW5jdGlvblxuICAgICAgICAgICAgaWYgKCFpc0NhbGxhYmxlKGNhbGxiYWNrZm4pKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJyYXkucHJvdG90eXBlLnJlZHVjZSBjYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gbm8gdmFsdWUgdG8gcmV0dXJuIGlmIG5vIGluaXRpYWwgdmFsdWUgYW5kIGFuIGVtcHR5IGFycmF5XG4gICAgICAgICAgICBpZiAobGVuZ3RoID09PSAwICYmIGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWR1Y2Ugb2YgZW1wdHkgYXJyYXkgd2l0aCBubyBpbml0aWFsIHZhbHVlJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBpID0gMDtcbiAgICAgICAgICAgIHZhciByZXN1bHQ7XG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSAyKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gYXJndW1lbnRzWzFdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpIGluIHNlbGYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHNlbGZbaSsrXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgYXJyYXkgY29udGFpbnMgbm8gdmFsdWVzLCBubyBpbml0aWFsIHZhbHVlIHRvIHJldHVyblxuICAgICAgICAgICAgICAgICAgICBpZiAoKytpID49IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigncmVkdWNlIG9mIGVtcHR5IGFycmF5IHdpdGggbm8gaW5pdGlhbCB2YWx1ZScpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSB3aGlsZSAodHJ1ZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAoOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaSBpbiBzZWxmKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGNhbGxiYWNrZm4ocmVzdWx0LCBzZWxmW2ldLCBpLCBvYmplY3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuICAgIH0sICFyZWR1Y2VDb2VyY2VzVG9PYmplY3QpO1xuXG4gICAgLy8gRVM1IDE1LjQuNC4yMlxuICAgIC8vIGh0dHA6Ly9lczUuZ2l0aHViLmNvbS8jeDE1LjQuNC4yMlxuICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuL0NvcmVfSmF2YVNjcmlwdF8xLjVfUmVmZXJlbmNlL09iamVjdHMvQXJyYXkvcmVkdWNlUmlnaHRcbiAgICB2YXIgcmVkdWNlUmlnaHRDb2VyY2VzVG9PYmplY3QgPSBmYWxzZTtcbiAgICBpZiAoQXJyYXlQcm90b3R5cGUucmVkdWNlUmlnaHQpIHtcbiAgICAgICAgcmVkdWNlUmlnaHRDb2VyY2VzVG9PYmplY3QgPSB0eXBlb2YgQXJyYXlQcm90b3R5cGUucmVkdWNlUmlnaHQuY2FsbCgnZXM1JywgZnVuY3Rpb24gKF8sIF9fLCBfX18sIGxpc3QpIHtcbiAgICAgICAgICAgIHJldHVybiBsaXN0O1xuICAgICAgICB9KSA9PT0gJ29iamVjdCc7XG4gICAgfVxuICAgIGRlZmluZVByb3BlcnRpZXMoQXJyYXlQcm90b3R5cGUsIHtcbiAgICAgICAgcmVkdWNlUmlnaHQ6IGZ1bmN0aW9uIHJlZHVjZVJpZ2h0KGNhbGxiYWNrZm4vKiwgaW5pdGlhbCovKSB7XG4gICAgICAgICAgICB2YXIgb2JqZWN0ID0gRVMuVG9PYmplY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHNwbGl0U3RyaW5nICYmIGlzU3RyaW5nKHRoaXMpID8gc3RyU3BsaXQodGhpcywgJycpIDogb2JqZWN0O1xuICAgICAgICAgICAgdmFyIGxlbmd0aCA9IEVTLlRvVWludDMyKHNlbGYubGVuZ3RoKTtcblxuICAgICAgICAgICAgLy8gSWYgbm8gY2FsbGJhY2sgZnVuY3Rpb24gb3IgaWYgY2FsbGJhY2sgaXMgbm90IGEgY2FsbGFibGUgZnVuY3Rpb25cbiAgICAgICAgICAgIGlmICghaXNDYWxsYWJsZShjYWxsYmFja2ZuKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FycmF5LnByb3RvdHlwZS5yZWR1Y2VSaWdodCBjYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gbm8gdmFsdWUgdG8gcmV0dXJuIGlmIG5vIGluaXRpYWwgdmFsdWUsIGVtcHR5IGFycmF5XG4gICAgICAgICAgICBpZiAobGVuZ3RoID09PSAwICYmIGFyZ3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWR1Y2VSaWdodCBvZiBlbXB0eSBhcnJheSB3aXRoIG5vIGluaXRpYWwgdmFsdWUnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHJlc3VsdDtcbiAgICAgICAgICAgIHZhciBpID0gbGVuZ3RoIC0gMTtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID49IDIpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBhcmd1bWVudHNbMV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRvIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgaW4gc2VsZikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gc2VsZltpLS1dO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBpZiBhcnJheSBjb250YWlucyBubyB2YWx1ZXMsIG5vIGluaXRpYWwgdmFsdWUgdG8gcmV0dXJuXG4gICAgICAgICAgICAgICAgICAgIGlmICgtLWkgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdyZWR1Y2VSaWdodCBvZiBlbXB0eSBhcnJheSB3aXRoIG5vIGluaXRpYWwgdmFsdWUnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gd2hpbGUgKHRydWUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaSA8IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkbyB7XG4gICAgICAgICAgICAgICAgaWYgKGkgaW4gc2VsZikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBjYWxsYmFja2ZuKHJlc3VsdCwgc2VsZltpXSwgaSwgb2JqZWN0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IHdoaWxlIChpLS0pO1xuXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfSwgIXJlZHVjZVJpZ2h0Q29lcmNlc1RvT2JqZWN0KTtcblxuICAgIC8vIEVTNSAxNS40LjQuMTRcbiAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3gxNS40LjQuMTRcbiAgICAvLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9BcnJheS9pbmRleE9mXG4gICAgdmFyIGhhc0ZpcmVmb3gySW5kZXhPZkJ1ZyA9IEFycmF5UHJvdG90eXBlLmluZGV4T2YgJiYgWzAsIDFdLmluZGV4T2YoMSwgMikgIT09IC0xO1xuICAgIGRlZmluZVByb3BlcnRpZXMoQXJyYXlQcm90b3R5cGUsIHtcbiAgICAgICAgaW5kZXhPZjogZnVuY3Rpb24gaW5kZXhPZihzZWFyY2hFbGVtZW50LyosIGZyb21JbmRleCAqLykge1xuICAgICAgICAgICAgdmFyIHNlbGYgPSBzcGxpdFN0cmluZyAmJiBpc1N0cmluZyh0aGlzKSA/IHN0clNwbGl0KHRoaXMsICcnKSA6IEVTLlRvT2JqZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIGxlbmd0aCA9IEVTLlRvVWludDMyKHNlbGYubGVuZ3RoKTtcblxuICAgICAgICAgICAgaWYgKGxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIGkgPSAwO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgaSA9IEVTLlRvSW50ZWdlcihhcmd1bWVudHNbMV0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBoYW5kbGUgbmVnYXRpdmUgaW5kaWNlc1xuICAgICAgICAgICAgaSA9IGkgPj0gMCA/IGkgOiBtYXgoMCwgbGVuZ3RoICsgaSk7XG4gICAgICAgICAgICBmb3IgKDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgaW4gc2VsZiAmJiBzZWxmW2ldID09PSBzZWFyY2hFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfVxuICAgIH0sIGhhc0ZpcmVmb3gySW5kZXhPZkJ1Zyk7XG5cbiAgICAvLyBFUzUgMTUuNC40LjE1XG4gICAgLy8gaHR0cDovL2VzNS5naXRodWIuY29tLyN4MTUuNC40LjE1XG4gICAgLy8gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4vSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvbGFzdEluZGV4T2ZcbiAgICB2YXIgaGFzRmlyZWZveDJMYXN0SW5kZXhPZkJ1ZyA9IEFycmF5UHJvdG90eXBlLmxhc3RJbmRleE9mICYmIFswLCAxXS5sYXN0SW5kZXhPZigwLCAtMykgIT09IC0xO1xuICAgIGRlZmluZVByb3BlcnRpZXMoQXJyYXlQcm90b3R5cGUsIHtcbiAgICAgICAgbGFzdEluZGV4T2Y6IGZ1bmN0aW9uIGxhc3RJbmRleE9mKHNlYXJjaEVsZW1lbnQvKiwgZnJvbUluZGV4ICovKSB7XG4gICAgICAgICAgICB2YXIgc2VsZiA9IHNwbGl0U3RyaW5nICYmIGlzU3RyaW5nKHRoaXMpID8gc3RyU3BsaXQodGhpcywgJycpIDogRVMuVG9PYmplY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgbGVuZ3RoID0gRVMuVG9VaW50MzIoc2VsZi5sZW5ndGgpO1xuXG4gICAgICAgICAgICBpZiAobGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGkgPSBsZW5ndGggLSAxO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgaSA9IG1pbihpLCBFUy5Ub0ludGVnZXIoYXJndW1lbnRzWzFdKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBoYW5kbGUgbmVnYXRpdmUgaW5kaWNlc1xuICAgICAgICAgICAgaSA9IGkgPj0gMCA/IGkgOiBsZW5ndGggLSBNYXRoLmFicyhpKTtcbiAgICAgICAgICAgIGZvciAoOyBpID49IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIGlmIChpIGluIHNlbGYgJiYgc2VhcmNoRWxlbWVudCA9PT0gc2VsZltpXSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICB9LCBoYXNGaXJlZm94Mkxhc3RJbmRleE9mQnVnKTtcblxuICAgIC8vIEVTNSAxNS40LjQuMTJcbiAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3gxNS40LjQuMTJcbiAgICB2YXIgc3BsaWNlTm9vcFJldHVybnNFbXB0eUFycmF5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGEgPSBbMSwgMl07XG4gICAgICAgIHZhciByZXN1bHQgPSBhLnNwbGljZSgpO1xuICAgICAgICByZXR1cm4gYS5sZW5ndGggPT09IDIgJiYgaXNBcnJheShyZXN1bHQpICYmIHJlc3VsdC5sZW5ndGggPT09IDA7XG4gICAgfSgpKTtcbiAgICBkZWZpbmVQcm9wZXJ0aWVzKEFycmF5UHJvdG90eXBlLCB7XG4gICAgICAgIC8vIFNhZmFyaSA1LjAgYnVnIHdoZXJlIC5zcGxpY2UoKSByZXR1cm5zIHVuZGVmaW5lZFxuICAgICAgICBzcGxpY2U6IGZ1bmN0aW9uIHNwbGljZShzdGFydCwgZGVsZXRlQ291bnQpIHtcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXJyYXlfc3BsaWNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCAhc3BsaWNlTm9vcFJldHVybnNFbXB0eUFycmF5KTtcblxuICAgIHZhciBzcGxpY2VXb3Jrc1dpdGhFbXB0eU9iamVjdCA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvYmogPSB7fTtcbiAgICAgICAgQXJyYXlQcm90b3R5cGUuc3BsaWNlLmNhbGwob2JqLCAwLCAwLCAxKTtcbiAgICAgICAgcmV0dXJuIG9iai5sZW5ndGggPT09IDE7XG4gICAgfSgpKTtcbiAgICBkZWZpbmVQcm9wZXJ0aWVzKEFycmF5UHJvdG90eXBlLCB7XG4gICAgICAgIHNwbGljZTogZnVuY3Rpb24gc3BsaWNlKHN0YXJ0LCBkZWxldGVDb3VudCkge1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgYXJncyA9IGFyZ3VtZW50cztcbiAgICAgICAgICAgIHRoaXMubGVuZ3RoID0gbWF4KEVTLlRvSW50ZWdlcih0aGlzLmxlbmd0aCksIDApO1xuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIHR5cGVvZiBkZWxldGVDb3VudCAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICBhcmdzID0gYXJyYXlTbGljZShhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIGlmIChhcmdzLmxlbmd0aCA8IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgcHVzaENhbGwoYXJncywgdGhpcy5sZW5ndGggLSBzdGFydCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXJnc1sxXSA9IEVTLlRvSW50ZWdlcihkZWxldGVDb3VudCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGFycmF5X3NwbGljZS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICAgICAgfVxuICAgIH0sICFzcGxpY2VXb3Jrc1dpdGhFbXB0eU9iamVjdCk7XG4gICAgdmFyIHNwbGljZVdvcmtzV2l0aExhcmdlU3BhcnNlQXJyYXlzID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gUGVyIGh0dHBzOi8vZ2l0aHViLmNvbS9lcy1zaGltcy9lczUtc2hpbS9pc3N1ZXMvMjk1XG4gICAgICAgIC8vIFNhZmFyaSA3LzggYnJlYWtzIHdpdGggc3BhcnNlIGFycmF5cyBvZiBzaXplIDFlNSBvciBncmVhdGVyXG4gICAgICAgIHZhciBhcnIgPSBuZXcgJEFycmF5KDFlNSk7XG4gICAgICAgIC8vIG5vdGU6IHRoZSBpbmRleCBNVVNUIGJlIDggb3IgbGFyZ2VyIG9yIHRoZSB0ZXN0IHdpbGwgZmFsc2UgcGFzc1xuICAgICAgICBhcnJbOF0gPSAneCc7XG4gICAgICAgIGFyci5zcGxpY2UoMSwgMSk7XG4gICAgICAgIC8vIG5vdGU6IHRoaXMgdGVzdCBtdXN0IGJlIGRlZmluZWQgKmFmdGVyKiB0aGUgaW5kZXhPZiBzaGltXG4gICAgICAgIC8vIHBlciBodHRwczovL2dpdGh1Yi5jb20vZXMtc2hpbXMvZXM1LXNoaW0vaXNzdWVzLzMxM1xuICAgICAgICByZXR1cm4gYXJyLmluZGV4T2YoJ3gnKSA9PT0gNztcbiAgICB9KCkpO1xuICAgIHZhciBzcGxpY2VXb3Jrc1dpdGhTbWFsbFNwYXJzZUFycmF5cyA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIFBlciBodHRwczovL2dpdGh1Yi5jb20vZXMtc2hpbXMvZXM1LXNoaW0vaXNzdWVzLzI5NVxuICAgICAgICAvLyBPcGVyYSAxMi4xNSBicmVha3Mgb24gdGhpcywgbm8gaWRlYSB3aHkuXG4gICAgICAgIHZhciBuID0gMjU2O1xuICAgICAgICB2YXIgYXJyID0gW107XG4gICAgICAgIGFycltuXSA9ICdhJztcbiAgICAgICAgYXJyLnNwbGljZShuICsgMSwgMCwgJ2InKTtcbiAgICAgICAgcmV0dXJuIGFycltuXSA9PT0gJ2EnO1xuICAgIH0oKSk7XG4gICAgZGVmaW5lUHJvcGVydGllcyhBcnJheVByb3RvdHlwZSwge1xuICAgICAgICBzcGxpY2U6IGZ1bmN0aW9uIHNwbGljZShzdGFydCwgZGVsZXRlQ291bnQpIHtcbiAgICAgICAgICAgIHZhciBPID0gRVMuVG9PYmplY3QodGhpcyk7XG4gICAgICAgICAgICB2YXIgQSA9IFtdO1xuICAgICAgICAgICAgdmFyIGxlbiA9IEVTLlRvVWludDMyKE8ubGVuZ3RoKTtcbiAgICAgICAgICAgIHZhciByZWxhdGl2ZVN0YXJ0ID0gRVMuVG9JbnRlZ2VyKHN0YXJ0KTtcbiAgICAgICAgICAgIHZhciBhY3R1YWxTdGFydCA9IHJlbGF0aXZlU3RhcnQgPCAwID8gbWF4KChsZW4gKyByZWxhdGl2ZVN0YXJ0KSwgMCkgOiBtaW4ocmVsYXRpdmVTdGFydCwgbGVuKTtcbiAgICAgICAgICAgIHZhciBhY3R1YWxEZWxldGVDb3VudCA9IG1pbihtYXgoRVMuVG9JbnRlZ2VyKGRlbGV0ZUNvdW50KSwgMCksIGxlbiAtIGFjdHVhbFN0YXJ0KTtcblxuICAgICAgICAgICAgdmFyIGsgPSAwO1xuICAgICAgICAgICAgdmFyIGZyb207XG4gICAgICAgICAgICB3aGlsZSAoayA8IGFjdHVhbERlbGV0ZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgZnJvbSA9ICRTdHJpbmcoYWN0dWFsU3RhcnQgKyBrKTtcbiAgICAgICAgICAgICAgICBpZiAob3ducyhPLCBmcm9tKSkge1xuICAgICAgICAgICAgICAgICAgICBBW2tdID0gT1tmcm9tXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgayArPSAxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgaXRlbXMgPSBhcnJheVNsaWNlKGFyZ3VtZW50cywgMik7XG4gICAgICAgICAgICB2YXIgaXRlbUNvdW50ID0gaXRlbXMubGVuZ3RoO1xuICAgICAgICAgICAgdmFyIHRvO1xuICAgICAgICAgICAgaWYgKGl0ZW1Db3VudCA8IGFjdHVhbERlbGV0ZUNvdW50KSB7XG4gICAgICAgICAgICAgICAgayA9IGFjdHVhbFN0YXJ0O1xuICAgICAgICAgICAgICAgIHZhciBtYXhLID0gbGVuIC0gYWN0dWFsRGVsZXRlQ291bnQ7XG4gICAgICAgICAgICAgICAgd2hpbGUgKGsgPCBtYXhLKSB7XG4gICAgICAgICAgICAgICAgICAgIGZyb20gPSAkU3RyaW5nKGsgKyBhY3R1YWxEZWxldGVDb3VudCk7XG4gICAgICAgICAgICAgICAgICAgIHRvID0gJFN0cmluZyhrICsgaXRlbUNvdW50KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG93bnMoTywgZnJvbSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIE9bdG9dID0gT1tmcm9tXTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBPW3RvXTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBrICs9IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGsgPSBsZW47XG4gICAgICAgICAgICAgICAgdmFyIG1pbksgPSBsZW4gLSBhY3R1YWxEZWxldGVDb3VudCArIGl0ZW1Db3VudDtcbiAgICAgICAgICAgICAgICB3aGlsZSAoayA+IG1pbkspIHtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIE9bayAtIDFdO1xuICAgICAgICAgICAgICAgICAgICBrIC09IDE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChpdGVtQ291bnQgPiBhY3R1YWxEZWxldGVDb3VudCkge1xuICAgICAgICAgICAgICAgIGsgPSBsZW4gLSBhY3R1YWxEZWxldGVDb3VudDtcbiAgICAgICAgICAgICAgICB3aGlsZSAoayA+IGFjdHVhbFN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgICAgIGZyb20gPSAkU3RyaW5nKGsgKyBhY3R1YWxEZWxldGVDb3VudCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICB0byA9ICRTdHJpbmcoayArIGl0ZW1Db3VudCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICBpZiAob3ducyhPLCBmcm9tKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgT1t0b10gPSBPW2Zyb21dO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIE9bdG9dO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGsgLT0gMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBrID0gYWN0dWFsU3RhcnQ7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGl0ZW1zLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICAgICAgT1trXSA9IGl0ZW1zW2ldO1xuICAgICAgICAgICAgICAgIGsgKz0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIE8ubGVuZ3RoID0gbGVuIC0gYWN0dWFsRGVsZXRlQ291bnQgKyBpdGVtQ291bnQ7XG5cbiAgICAgICAgICAgIHJldHVybiBBO1xuICAgICAgICB9XG4gICAgfSwgIXNwbGljZVdvcmtzV2l0aExhcmdlU3BhcnNlQXJyYXlzIHx8ICFzcGxpY2VXb3Jrc1dpdGhTbWFsbFNwYXJzZUFycmF5cyk7XG5cbiAgICB2YXIgb3JpZ2luYWxKb2luID0gQXJyYXlQcm90b3R5cGUuam9pbjtcbiAgICB2YXIgaGFzU3RyaW5nSm9pbkJ1ZztcbiAgICB0cnkge1xuICAgICAgICBoYXNTdHJpbmdKb2luQnVnID0gQXJyYXkucHJvdG90eXBlLmpvaW4uY2FsbCgnMTIzJywgJywnKSAhPT0gJzEsMiwzJztcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGhhc1N0cmluZ0pvaW5CdWcgPSB0cnVlO1xuICAgIH1cbiAgICBpZiAoaGFzU3RyaW5nSm9pbkJ1Zykge1xuICAgICAgICBkZWZpbmVQcm9wZXJ0aWVzKEFycmF5UHJvdG90eXBlLCB7XG4gICAgICAgICAgICBqb2luOiBmdW5jdGlvbiBqb2luKHNlcGFyYXRvcikge1xuICAgICAgICAgICAgICAgIHZhciBzZXAgPSB0eXBlb2Ygc2VwYXJhdG9yID09PSAndW5kZWZpbmVkJyA/ICcsJyA6IHNlcGFyYXRvcjtcbiAgICAgICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxKb2luLmNhbGwoaXNTdHJpbmcodGhpcykgPyBzdHJTcGxpdCh0aGlzLCAnJykgOiB0aGlzLCBzZXApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBoYXNTdHJpbmdKb2luQnVnKTtcbiAgICB9XG5cbiAgICB2YXIgaGFzSm9pblVuZGVmaW5lZEJ1ZyA9IFsxLCAyXS5qb2luKHVuZGVmaW5lZCkgIT09ICcxLDInO1xuICAgIGlmIChoYXNKb2luVW5kZWZpbmVkQnVnKSB7XG4gICAgICAgIGRlZmluZVByb3BlcnRpZXMoQXJyYXlQcm90b3R5cGUsIHtcbiAgICAgICAgICAgIGpvaW46IGZ1bmN0aW9uIGpvaW4oc2VwYXJhdG9yKSB7XG4gICAgICAgICAgICAgICAgdmFyIHNlcCA9IHR5cGVvZiBzZXBhcmF0b3IgPT09ICd1bmRlZmluZWQnID8gJywnIDogc2VwYXJhdG9yO1xuICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbEpvaW4uY2FsbCh0aGlzLCBzZXApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBoYXNKb2luVW5kZWZpbmVkQnVnKTtcbiAgICB9XG5cbiAgICB2YXIgcHVzaFNoaW0gPSBmdW5jdGlvbiBwdXNoKGl0ZW0pIHtcbiAgICAgICAgdmFyIE8gPSBFUy5Ub09iamVjdCh0aGlzKTtcbiAgICAgICAgdmFyIG4gPSBFUy5Ub1VpbnQzMihPLmxlbmd0aCk7XG4gICAgICAgIHZhciBpID0gMDtcbiAgICAgICAgd2hpbGUgKGkgPCBhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICBPW24gKyBpXSA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICAgIGkgKz0gMTtcbiAgICAgICAgfVxuICAgICAgICBPLmxlbmd0aCA9IG4gKyBpO1xuICAgICAgICByZXR1cm4gbiArIGk7XG4gICAgfTtcblxuICAgIHZhciBwdXNoSXNOb3RHZW5lcmljID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG9iaiA9IHt9O1xuICAgICAgICB2YXIgcmVzdWx0ID0gQXJyYXkucHJvdG90eXBlLnB1c2guY2FsbChvYmosIHVuZGVmaW5lZCk7XG4gICAgICAgIHJldHVybiByZXN1bHQgIT09IDEgfHwgb2JqLmxlbmd0aCAhPT0gMSB8fCB0eXBlb2Ygb2JqWzBdICE9PSAndW5kZWZpbmVkJyB8fCAhb3ducyhvYmosIDApO1xuICAgIH0oKSk7XG4gICAgZGVmaW5lUHJvcGVydGllcyhBcnJheVByb3RvdHlwZSwge1xuICAgICAgICBwdXNoOiBmdW5jdGlvbiBwdXNoKGl0ZW0pIHtcbiAgICAgICAgICAgIGlmIChpc0FycmF5KHRoaXMpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFycmF5X3B1c2guYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwdXNoU2hpbS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgfSwgcHVzaElzTm90R2VuZXJpYyk7XG5cbiAgICAvLyBUaGlzIGZpeGVzIGEgdmVyeSB3ZWlyZCBidWcgaW4gT3BlcmEgMTAuNiB3aGVuIHB1c2hpbmcgYHVuZGVmaW5lZFxuICAgIHZhciBwdXNoVW5kZWZpbmVkSXNXZWlyZCA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBhcnIgPSBbXTtcbiAgICAgICAgdmFyIHJlc3VsdCA9IGFyci5wdXNoKHVuZGVmaW5lZCk7XG4gICAgICAgIHJldHVybiByZXN1bHQgIT09IDEgfHwgYXJyLmxlbmd0aCAhPT0gMSB8fCB0eXBlb2YgYXJyWzBdICE9PSAndW5kZWZpbmVkJyB8fCAhb3ducyhhcnIsIDApO1xuICAgIH0oKSk7XG4gICAgZGVmaW5lUHJvcGVydGllcyhBcnJheVByb3RvdHlwZSwgeyBwdXNoOiBwdXNoU2hpbSB9LCBwdXNoVW5kZWZpbmVkSXNXZWlyZCk7XG5cbiAgICAvLyBFUzUgMTUuMi4zLjE0XG4gICAgLy8gaHR0cDovL2VzNS5naXRodWIuaW8vI3gxNS40LjQuMTBcbiAgICAvLyBGaXggYm94ZWQgc3RyaW5nIGJ1Z1xuICAgIGRlZmluZVByb3BlcnRpZXMoQXJyYXlQcm90b3R5cGUsIHtcbiAgICAgICAgc2xpY2U6IGZ1bmN0aW9uIChzdGFydCwgZW5kKSB7XG4gICAgICAgICAgICB2YXIgYXJyID0gaXNTdHJpbmcodGhpcykgPyBzdHJTcGxpdCh0aGlzLCAnJykgOiB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIGFycmF5U2xpY2VBcHBseShhcnIsIGFyZ3VtZW50cyk7XG4gICAgICAgIH1cbiAgICB9LCBzcGxpdFN0cmluZyk7XG5cbiAgICB2YXIgc29ydElnbm9yZXNOb25GdW5jdGlvbnMgPSAoZnVuY3Rpb24gKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgWzEsIDJdLnNvcnQobnVsbCk7XG4gICAgICAgICAgICBbMSwgMl0uc29ydCh7fSk7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0oKSk7XG4gICAgdmFyIHNvcnRUaHJvd3NPblJlZ2V4ID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gdGhpcyBpcyBhIHByb2JsZW0gaW4gRmlyZWZveCA0LCBpbiB3aGljaCBgdHlwZW9mIC9hLyA9PT0gJ2Z1bmN0aW9uJ2BcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIFsxLCAyXS5zb3J0KC9hLyk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0oKSk7XG4gICAgdmFyIHNvcnRJZ25vcmVzVW5kZWZpbmVkID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgLy8gYXBwbGllcyBpbiBJRSA4LCBmb3Igb25lLlxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgWzEsIDJdLnNvcnQodW5kZWZpbmVkKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlKSB7fVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSgpKTtcbiAgICBkZWZpbmVQcm9wZXJ0aWVzKEFycmF5UHJvdG90eXBlLCB7XG4gICAgICAgIHNvcnQ6IGZ1bmN0aW9uIHNvcnQoY29tcGFyZUZuKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNvbXBhcmVGbiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYXJyYXlTb3J0KHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc0NhbGxhYmxlKGNvbXBhcmVGbikpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcnJheS5wcm90b3R5cGUuc29ydCBjYWxsYmFjayBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBhcnJheVNvcnQodGhpcywgY29tcGFyZUZuKTtcbiAgICAgICAgfVxuICAgIH0sIHNvcnRJZ25vcmVzTm9uRnVuY3Rpb25zIHx8ICFzb3J0SWdub3Jlc1VuZGVmaW5lZCB8fCAhc29ydFRocm93c09uUmVnZXgpO1xuXG4gICAgLy9cbiAgICAvLyBPYmplY3RcbiAgICAvLyA9PT09PT1cbiAgICAvL1xuXG4gICAgLy8gRVM1IDE1LjIuMy4xNFxuICAgIC8vIGh0dHA6Ly9lczUuZ2l0aHViLmNvbS8jeDE1LjIuMy4xNFxuXG4gICAgLy8gaHR0cDovL3doYXR0aGVoZWFkc2FpZC5jb20vMjAxMC8xMC9hLXNhZmVyLW9iamVjdC1rZXlzLWNvbXBhdGliaWxpdHktaW1wbGVtZW50YXRpb25cbiAgICB2YXIgaGFzRG9udEVudW1CdWcgPSAhaXNFbnVtKHsgJ3RvU3RyaW5nJzogbnVsbCB9LCAndG9TdHJpbmcnKTtcbiAgICB2YXIgaGFzUHJvdG9FbnVtQnVnID0gaXNFbnVtKGZ1bmN0aW9uICgpIHt9LCAncHJvdG90eXBlJyk7XG4gICAgdmFyIGhhc1N0cmluZ0VudW1CdWcgPSAhb3ducygneCcsICcwJyk7XG4gICAgdmFyIGVxdWFsc0NvbnN0cnVjdG9yUHJvdG90eXBlID0gZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgdmFyIGN0b3IgPSBvLmNvbnN0cnVjdG9yO1xuICAgICAgICByZXR1cm4gY3RvciAmJiBjdG9yLnByb3RvdHlwZSA9PT0gbztcbiAgICB9O1xuICAgIHZhciBibGFja2xpc3RlZEtleXMgPSB7XG4gICAgICAgICR3aW5kb3c6IHRydWUsXG4gICAgICAgICRjb25zb2xlOiB0cnVlLFxuICAgICAgICAkcGFyZW50OiB0cnVlLFxuICAgICAgICAkc2VsZjogdHJ1ZSxcbiAgICAgICAgJGZyYW1lOiB0cnVlLFxuICAgICAgICAkZnJhbWVzOiB0cnVlLFxuICAgICAgICAkZnJhbWVFbGVtZW50OiB0cnVlLFxuICAgICAgICAkd2Via2l0SW5kZXhlZERCOiB0cnVlLFxuICAgICAgICAkd2Via2l0U3RvcmFnZUluZm86IHRydWUsXG4gICAgICAgICRleHRlcm5hbDogdHJ1ZVxuICAgIH07XG4gICAgdmFyIGhhc0F1dG9tYXRpb25FcXVhbGl0eUJ1ZyA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8qIGdsb2JhbHMgd2luZG93ICovXG4gICAgICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGsgaW4gd2luZG93KSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmICghYmxhY2tsaXN0ZWRLZXlzWyckJyArIGtdICYmIG93bnMod2luZG93LCBrKSAmJiB3aW5kb3dba10gIT09IG51bGwgJiYgdHlwZW9mIHdpbmRvd1trXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgZXF1YWxzQ29uc3RydWN0b3JQcm90b3R5cGUod2luZG93W2tdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0oKSk7XG4gICAgdmFyIGVxdWFsc0NvbnN0cnVjdG9yUHJvdG90eXBlSWZOb3RCdWdneSA9IGZ1bmN0aW9uIChvYmplY3QpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnIHx8ICFoYXNBdXRvbWF0aW9uRXF1YWxpdHlCdWcpIHtcbiAgICAgICAgICAgIHJldHVybiBlcXVhbHNDb25zdHJ1Y3RvclByb3RvdHlwZShvYmplY3QpO1xuICAgICAgICB9XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXR1cm4gZXF1YWxzQ29uc3RydWN0b3JQcm90b3R5cGUob2JqZWN0KTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfTtcbiAgICB2YXIgZG9udEVudW1zID0gW1xuICAgICAgICAndG9TdHJpbmcnLFxuICAgICAgICAndG9Mb2NhbGVTdHJpbmcnLFxuICAgICAgICAndmFsdWVPZicsXG4gICAgICAgICdoYXNPd25Qcm9wZXJ0eScsXG4gICAgICAgICdpc1Byb3RvdHlwZU9mJyxcbiAgICAgICAgJ3Byb3BlcnR5SXNFbnVtZXJhYmxlJyxcbiAgICAgICAgJ2NvbnN0cnVjdG9yJ1xuICAgIF07XG4gICAgdmFyIGRvbnRFbnVtc0xlbmd0aCA9IGRvbnRFbnVtcy5sZW5ndGg7XG5cbiAgICAvLyB0YWtlbiBkaXJlY3RseSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9samhhcmIvaXMtYXJndW1lbnRzL2Jsb2IvbWFzdGVyL2luZGV4LmpzXG4gICAgLy8gY2FuIGJlIHJlcGxhY2VkIHdpdGggcmVxdWlyZSgnaXMtYXJndW1lbnRzJykgaWYgd2UgZXZlciB1c2UgYSBidWlsZCBwcm9jZXNzIGluc3RlYWRcbiAgICB2YXIgaXNTdGFuZGFyZEFyZ3VtZW50cyA9IGZ1bmN0aW9uIGlzQXJndW1lbnRzKHZhbHVlKSB7XG4gICAgICAgIHJldHVybiB0b1N0cih2YWx1ZSkgPT09ICdbb2JqZWN0IEFyZ3VtZW50c10nO1xuICAgIH07XG4gICAgdmFyIGlzTGVnYWN5QXJndW1lbnRzID0gZnVuY3Rpb24gaXNBcmd1bWVudHModmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlICE9PSBudWxsICYmXG4gICAgICAgICAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmXG4gICAgICAgICAgICB0eXBlb2YgdmFsdWUubGVuZ3RoID09PSAnbnVtYmVyJyAmJlxuICAgICAgICAgICAgdmFsdWUubGVuZ3RoID49IDAgJiZcbiAgICAgICAgICAgICFpc0FycmF5KHZhbHVlKSAmJlxuICAgICAgICAgICAgaXNDYWxsYWJsZSh2YWx1ZS5jYWxsZWUpO1xuICAgIH07XG4gICAgdmFyIGlzQXJndW1lbnRzID0gaXNTdGFuZGFyZEFyZ3VtZW50cyhhcmd1bWVudHMpID8gaXNTdGFuZGFyZEFyZ3VtZW50cyA6IGlzTGVnYWN5QXJndW1lbnRzO1xuXG4gICAgZGVmaW5lUHJvcGVydGllcygkT2JqZWN0LCB7XG4gICAgICAgIGtleXM6IGZ1bmN0aW9uIGtleXMob2JqZWN0KSB7XG4gICAgICAgICAgICB2YXIgaXNGbiA9IGlzQ2FsbGFibGUob2JqZWN0KTtcbiAgICAgICAgICAgIHZhciBpc0FyZ3MgPSBpc0FyZ3VtZW50cyhvYmplY3QpO1xuICAgICAgICAgICAgdmFyIGlzT2JqZWN0ID0gb2JqZWN0ICE9PSBudWxsICYmIHR5cGVvZiBvYmplY3QgPT09ICdvYmplY3QnO1xuICAgICAgICAgICAgdmFyIGlzU3RyID0gaXNPYmplY3QgJiYgaXNTdHJpbmcob2JqZWN0KTtcblxuICAgICAgICAgICAgaWYgKCFpc09iamVjdCAmJiAhaXNGbiAmJiAhaXNBcmdzKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignT2JqZWN0LmtleXMgY2FsbGVkIG9uIGEgbm9uLW9iamVjdCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgdGhlS2V5cyA9IFtdO1xuICAgICAgICAgICAgdmFyIHNraXBQcm90byA9IGhhc1Byb3RvRW51bUJ1ZyAmJiBpc0ZuO1xuICAgICAgICAgICAgaWYgKChpc1N0ciAmJiBoYXNTdHJpbmdFbnVtQnVnKSB8fCBpc0FyZ3MpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9iamVjdC5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgICAgICBwdXNoQ2FsbCh0aGVLZXlzLCAkU3RyaW5nKGkpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaXNBcmdzKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgbmFtZSBpbiBvYmplY3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEoc2tpcFByb3RvICYmIG5hbWUgPT09ICdwcm90b3R5cGUnKSAmJiBvd25zKG9iamVjdCwgbmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1c2hDYWxsKHRoZUtleXMsICRTdHJpbmcobmFtZSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaGFzRG9udEVudW1CdWcpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2tpcENvbnN0cnVjdG9yID0gZXF1YWxzQ29uc3RydWN0b3JQcm90b3R5cGVJZk5vdEJ1Z2d5KG9iamVjdCk7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBkb250RW51bXNMZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZG9udEVudW0gPSBkb250RW51bXNbal07XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHNraXBDb25zdHJ1Y3RvciAmJiBkb250RW51bSA9PT0gJ2NvbnN0cnVjdG9yJykgJiYgb3ducyhvYmplY3QsIGRvbnRFbnVtKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcHVzaENhbGwodGhlS2V5cywgZG9udEVudW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoZUtleXM7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHZhciBrZXlzV29ya3NXaXRoQXJndW1lbnRzID0gJE9iamVjdC5rZXlzICYmIChmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIFNhZmFyaSA1LjAgYnVnXG4gICAgICAgIHJldHVybiAkT2JqZWN0LmtleXMoYXJndW1lbnRzKS5sZW5ndGggPT09IDI7XG4gICAgfSgxLCAyKSk7XG4gICAgdmFyIGtleXNIYXNBcmd1bWVudHNMZW5ndGhCdWcgPSAkT2JqZWN0LmtleXMgJiYgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGFyZ0tleXMgPSAkT2JqZWN0LmtleXMoYXJndW1lbnRzKTtcbiAgICAgICAgcmV0dXJuIGFyZ3VtZW50cy5sZW5ndGggIT09IDEgfHwgYXJnS2V5cy5sZW5ndGggIT09IDEgfHwgYXJnS2V5c1swXSAhPT0gMTtcbiAgICB9KDEpKTtcbiAgICB2YXIgb3JpZ2luYWxLZXlzID0gJE9iamVjdC5rZXlzO1xuICAgIGRlZmluZVByb3BlcnRpZXMoJE9iamVjdCwge1xuICAgICAgICBrZXlzOiBmdW5jdGlvbiBrZXlzKG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKGlzQXJndW1lbnRzKG9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb3JpZ2luYWxLZXlzKGFycmF5U2xpY2Uob2JqZWN0KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBvcmlnaW5hbEtleXMob2JqZWN0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sICFrZXlzV29ya3NXaXRoQXJndW1lbnRzIHx8IGtleXNIYXNBcmd1bWVudHNMZW5ndGhCdWcpO1xuXG4gICAgLy9cbiAgICAvLyBEYXRlXG4gICAgLy8gPT09PVxuICAgIC8vXG5cbiAgICB2YXIgaGFzTmVnYXRpdmVNb250aFllYXJCdWcgPSBuZXcgRGF0ZSgtMzUwOTgyNzMyOTYwMDI5MikuZ2V0VVRDTW9udGgoKSAhPT0gMDtcbiAgICB2YXIgYU5lZ2F0aXZlVGVzdERhdGUgPSBuZXcgRGF0ZSgtMTUwOTg0MjI4OTYwMDI5Mik7XG4gICAgdmFyIGFQb3NpdGl2ZVRlc3REYXRlID0gbmV3IERhdGUoMTQ0OTY2MjQwMDAwMCk7XG4gICAgdmFyIGhhc1RvVVRDU3RyaW5nRm9ybWF0QnVnID0gYU5lZ2F0aXZlVGVzdERhdGUudG9VVENTdHJpbmcoKSAhPT0gJ01vbiwgMDEgSmFuIC00NTg3NSAxMTo1OTo1OSBHTVQnO1xuICAgIHZhciBoYXNUb0RhdGVTdHJpbmdGb3JtYXRCdWc7XG4gICAgdmFyIGhhc1RvU3RyaW5nRm9ybWF0QnVnO1xuICAgIHZhciB0aW1lWm9uZU9mZnNldCA9IGFOZWdhdGl2ZVRlc3REYXRlLmdldFRpbWV6b25lT2Zmc2V0KCk7XG4gICAgaWYgKHRpbWVab25lT2Zmc2V0IDwgLTcyMCkge1xuICAgICAgICBoYXNUb0RhdGVTdHJpbmdGb3JtYXRCdWcgPSBhTmVnYXRpdmVUZXN0RGF0ZS50b0RhdGVTdHJpbmcoKSAhPT0gJ1R1ZSBKYW4gMDIgLTQ1ODc1JztcbiAgICAgICAgaGFzVG9TdHJpbmdGb3JtYXRCdWcgPSAhKC9eVGh1IERlYyAxMCAyMDE1IFxcZFxcZDpcXGRcXGQ6XFxkXFxkIEdNVFstXFwrXVxcZFxcZFxcZFxcZCg/OiB8JCkvKS50ZXN0KGFQb3NpdGl2ZVRlc3REYXRlLnRvU3RyaW5nKCkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhhc1RvRGF0ZVN0cmluZ0Zvcm1hdEJ1ZyA9IGFOZWdhdGl2ZVRlc3REYXRlLnRvRGF0ZVN0cmluZygpICE9PSAnTW9uIEphbiAwMSAtNDU4NzUnO1xuICAgICAgICBoYXNUb1N0cmluZ0Zvcm1hdEJ1ZyA9ICEoL15XZWQgRGVjIDA5IDIwMTUgXFxkXFxkOlxcZFxcZDpcXGRcXGQgR01UWy1cXCtdXFxkXFxkXFxkXFxkKD86IHwkKS8pLnRlc3QoYVBvc2l0aXZlVGVzdERhdGUudG9TdHJpbmcoKSk7XG4gICAgfVxuXG4gICAgdmFyIG9yaWdpbmFsR2V0RnVsbFllYXIgPSBjYWxsLmJpbmQoRGF0ZS5wcm90b3R5cGUuZ2V0RnVsbFllYXIpO1xuICAgIHZhciBvcmlnaW5hbEdldE1vbnRoID0gY2FsbC5iaW5kKERhdGUucHJvdG90eXBlLmdldE1vbnRoKTtcbiAgICB2YXIgb3JpZ2luYWxHZXREYXRlID0gY2FsbC5iaW5kKERhdGUucHJvdG90eXBlLmdldERhdGUpO1xuICAgIHZhciBvcmlnaW5hbEdldFVUQ0Z1bGxZZWFyID0gY2FsbC5iaW5kKERhdGUucHJvdG90eXBlLmdldFVUQ0Z1bGxZZWFyKTtcbiAgICB2YXIgb3JpZ2luYWxHZXRVVENNb250aCA9IGNhbGwuYmluZChEYXRlLnByb3RvdHlwZS5nZXRVVENNb250aCk7XG4gICAgdmFyIG9yaWdpbmFsR2V0VVRDRGF0ZSA9IGNhbGwuYmluZChEYXRlLnByb3RvdHlwZS5nZXRVVENEYXRlKTtcbiAgICB2YXIgb3JpZ2luYWxHZXRVVENEYXkgPSBjYWxsLmJpbmQoRGF0ZS5wcm90b3R5cGUuZ2V0VVRDRGF5KTtcbiAgICB2YXIgb3JpZ2luYWxHZXRVVENIb3VycyA9IGNhbGwuYmluZChEYXRlLnByb3RvdHlwZS5nZXRVVENIb3Vycyk7XG4gICAgdmFyIG9yaWdpbmFsR2V0VVRDTWludXRlcyA9IGNhbGwuYmluZChEYXRlLnByb3RvdHlwZS5nZXRVVENNaW51dGVzKTtcbiAgICB2YXIgb3JpZ2luYWxHZXRVVENTZWNvbmRzID0gY2FsbC5iaW5kKERhdGUucHJvdG90eXBlLmdldFVUQ1NlY29uZHMpO1xuICAgIHZhciBvcmlnaW5hbEdldFVUQ01pbGxpc2Vjb25kcyA9IGNhbGwuYmluZChEYXRlLnByb3RvdHlwZS5nZXRVVENNaWxsaXNlY29uZHMpO1xuICAgIHZhciBkYXlOYW1lID0gWydTdW4nLCAnTW9uJywgJ1R1ZScsICdXZWQnLCAnVGh1JywgJ0ZyaScsICdTYXQnXTtcbiAgICB2YXIgbW9udGhOYW1lID0gWydKYW4nLCAnRmViJywgJ01hcicsICdBcHInLCAnTWF5JywgJ0p1bicsICdKdWwnLCAnQXVnJywgJ1NlcCcsICdPY3QnLCAnTm92JywgJ0RlYyddO1xuICAgIHZhciBkYXlzSW5Nb250aCA9IGZ1bmN0aW9uIGRheXNJbk1vbnRoKG1vbnRoLCB5ZWFyKSB7XG4gICAgICAgIHJldHVybiBvcmlnaW5hbEdldERhdGUobmV3IERhdGUoeWVhciwgbW9udGgsIDApKTtcbiAgICB9O1xuXG4gICAgZGVmaW5lUHJvcGVydGllcyhEYXRlLnByb3RvdHlwZSwge1xuICAgICAgICBnZXRGdWxsWWVhcjogZnVuY3Rpb24gZ2V0RnVsbFllYXIoKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMgfHwgISh0aGlzIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0aGlzIGlzIG5vdCBhIERhdGUgb2JqZWN0LicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHllYXIgPSBvcmlnaW5hbEdldEZ1bGxZZWFyKHRoaXMpO1xuICAgICAgICAgICAgaWYgKHllYXIgPCAwICYmIG9yaWdpbmFsR2V0TW9udGgodGhpcykgPiAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB5ZWFyICsgMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB5ZWFyO1xuICAgICAgICB9LFxuICAgICAgICBnZXRNb250aDogZnVuY3Rpb24gZ2V0TW9udGgoKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMgfHwgISh0aGlzIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0aGlzIGlzIG5vdCBhIERhdGUgb2JqZWN0LicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHllYXIgPSBvcmlnaW5hbEdldEZ1bGxZZWFyKHRoaXMpO1xuICAgICAgICAgICAgdmFyIG1vbnRoID0gb3JpZ2luYWxHZXRNb250aCh0aGlzKTtcbiAgICAgICAgICAgIGlmICh5ZWFyIDwgMCAmJiBtb250aCA+IDExKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbW9udGg7XG4gICAgICAgIH0sXG4gICAgICAgIGdldERhdGU6IGZ1bmN0aW9uIGdldERhdGUoKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMgfHwgISh0aGlzIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0aGlzIGlzIG5vdCBhIERhdGUgb2JqZWN0LicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHllYXIgPSBvcmlnaW5hbEdldEZ1bGxZZWFyKHRoaXMpO1xuICAgICAgICAgICAgdmFyIG1vbnRoID0gb3JpZ2luYWxHZXRNb250aCh0aGlzKTtcbiAgICAgICAgICAgIHZhciBkYXRlID0gb3JpZ2luYWxHZXREYXRlKHRoaXMpO1xuICAgICAgICAgICAgaWYgKHllYXIgPCAwICYmIG1vbnRoID4gMTEpIHtcbiAgICAgICAgICAgICAgICBpZiAobW9udGggPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXRlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZGF5cyA9IGRheXNJbk1vbnRoKDAsIHllYXIgKyAxKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gKGRheXMgLSBkYXRlKSArIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0VVRDRnVsbFllYXI6IGZ1bmN0aW9uIGdldFVUQ0Z1bGxZZWFyKCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzIHx8ICEodGhpcyBpbnN0YW5jZW9mIERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndGhpcyBpcyBub3QgYSBEYXRlIG9iamVjdC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB5ZWFyID0gb3JpZ2luYWxHZXRVVENGdWxsWWVhcih0aGlzKTtcbiAgICAgICAgICAgIGlmICh5ZWFyIDwgMCAmJiBvcmlnaW5hbEdldFVUQ01vbnRoKHRoaXMpID4gMTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geWVhciArIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4geWVhcjtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0VVRDTW9udGg6IGZ1bmN0aW9uIGdldFVUQ01vbnRoKCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzIHx8ICEodGhpcyBpbnN0YW5jZW9mIERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndGhpcyBpcyBub3QgYSBEYXRlIG9iamVjdC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB5ZWFyID0gb3JpZ2luYWxHZXRVVENGdWxsWWVhcih0aGlzKTtcbiAgICAgICAgICAgIHZhciBtb250aCA9IG9yaWdpbmFsR2V0VVRDTW9udGgodGhpcyk7XG4gICAgICAgICAgICBpZiAoeWVhciA8IDAgJiYgbW9udGggPiAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG1vbnRoO1xuICAgICAgICB9LFxuICAgICAgICBnZXRVVENEYXRlOiBmdW5jdGlvbiBnZXRVVENEYXRlKCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzIHx8ICEodGhpcyBpbnN0YW5jZW9mIERhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndGhpcyBpcyBub3QgYSBEYXRlIG9iamVjdC4nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB5ZWFyID0gb3JpZ2luYWxHZXRVVENGdWxsWWVhcih0aGlzKTtcbiAgICAgICAgICAgIHZhciBtb250aCA9IG9yaWdpbmFsR2V0VVRDTW9udGgodGhpcyk7XG4gICAgICAgICAgICB2YXIgZGF0ZSA9IG9yaWdpbmFsR2V0VVRDRGF0ZSh0aGlzKTtcbiAgICAgICAgICAgIGlmICh5ZWFyIDwgMCAmJiBtb250aCA+IDExKSB7XG4gICAgICAgICAgICAgICAgaWYgKG1vbnRoID09PSAxMikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdmFyIGRheXMgPSBkYXlzSW5Nb250aCgwLCB5ZWFyICsgMSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChkYXlzIC0gZGF0ZSkgKyAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGRhdGU7XG4gICAgICAgIH1cbiAgICB9LCBoYXNOZWdhdGl2ZU1vbnRoWWVhckJ1Zyk7XG5cbiAgICBkZWZpbmVQcm9wZXJ0aWVzKERhdGUucHJvdG90eXBlLCB7XG4gICAgICAgIHRvVVRDU3RyaW5nOiBmdW5jdGlvbiB0b1VUQ1N0cmluZygpIHtcbiAgICAgICAgICAgIGlmICghdGhpcyB8fCAhKHRoaXMgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3RoaXMgaXMgbm90IGEgRGF0ZSBvYmplY3QuJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZGF5ID0gb3JpZ2luYWxHZXRVVENEYXkodGhpcyk7XG4gICAgICAgICAgICB2YXIgZGF0ZSA9IG9yaWdpbmFsR2V0VVRDRGF0ZSh0aGlzKTtcbiAgICAgICAgICAgIHZhciBtb250aCA9IG9yaWdpbmFsR2V0VVRDTW9udGgodGhpcyk7XG4gICAgICAgICAgICB2YXIgeWVhciA9IG9yaWdpbmFsR2V0VVRDRnVsbFllYXIodGhpcyk7XG4gICAgICAgICAgICB2YXIgaG91ciA9IG9yaWdpbmFsR2V0VVRDSG91cnModGhpcyk7XG4gICAgICAgICAgICB2YXIgbWludXRlID0gb3JpZ2luYWxHZXRVVENNaW51dGVzKHRoaXMpO1xuICAgICAgICAgICAgdmFyIHNlY29uZCA9IG9yaWdpbmFsR2V0VVRDU2Vjb25kcyh0aGlzKTtcbiAgICAgICAgICAgIHJldHVybiBkYXlOYW1lW2RheV0gKyAnLCAnICtcbiAgICAgICAgICAgICAgICAoZGF0ZSA8IDEwID8gJzAnICsgZGF0ZSA6IGRhdGUpICsgJyAnICtcbiAgICAgICAgICAgICAgICBtb250aE5hbWVbbW9udGhdICsgJyAnICtcbiAgICAgICAgICAgICAgICB5ZWFyICsgJyAnICtcbiAgICAgICAgICAgICAgICAoaG91ciA8IDEwID8gJzAnICsgaG91ciA6IGhvdXIpICsgJzonICtcbiAgICAgICAgICAgICAgICAobWludXRlIDwgMTAgPyAnMCcgKyBtaW51dGUgOiBtaW51dGUpICsgJzonICtcbiAgICAgICAgICAgICAgICAoc2Vjb25kIDwgMTAgPyAnMCcgKyBzZWNvbmQgOiBzZWNvbmQpICsgJyBHTVQnO1xuICAgICAgICB9XG4gICAgfSwgaGFzTmVnYXRpdmVNb250aFllYXJCdWcgfHwgaGFzVG9VVENTdHJpbmdGb3JtYXRCdWcpO1xuXG4gICAgLy8gT3BlcmEgMTIgaGFzIGAsYFxuICAgIGRlZmluZVByb3BlcnRpZXMoRGF0ZS5wcm90b3R5cGUsIHtcbiAgICAgICAgdG9EYXRlU3RyaW5nOiBmdW5jdGlvbiB0b0RhdGVTdHJpbmcoKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMgfHwgISh0aGlzIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0aGlzIGlzIG5vdCBhIERhdGUgb2JqZWN0LicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGRheSA9IHRoaXMuZ2V0RGF5KCk7XG4gICAgICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuZ2V0RGF0ZSgpO1xuICAgICAgICAgICAgdmFyIG1vbnRoID0gdGhpcy5nZXRNb250aCgpO1xuICAgICAgICAgICAgdmFyIHllYXIgPSB0aGlzLmdldEZ1bGxZZWFyKCk7XG4gICAgICAgICAgICByZXR1cm4gZGF5TmFtZVtkYXldICsgJyAnICtcbiAgICAgICAgICAgICAgICBtb250aE5hbWVbbW9udGhdICsgJyAnICtcbiAgICAgICAgICAgICAgICAoZGF0ZSA8IDEwID8gJzAnICsgZGF0ZSA6IGRhdGUpICsgJyAnICtcbiAgICAgICAgICAgICAgICB5ZWFyO1xuICAgICAgICB9XG4gICAgfSwgaGFzTmVnYXRpdmVNb250aFllYXJCdWcgfHwgaGFzVG9EYXRlU3RyaW5nRm9ybWF0QnVnKTtcblxuICAgIC8vIGNhbid0IHVzZSBkZWZpbmVQcm9wZXJ0aWVzIGhlcmUgYmVjYXVzZSBvZiB0b1N0cmluZyBlbnVtZXJhdGlvbiBpc3N1ZSBpbiBJRSA8PSA4XG4gICAgaWYgKGhhc05lZ2F0aXZlTW9udGhZZWFyQnVnIHx8IGhhc1RvU3RyaW5nRm9ybWF0QnVnKSB7XG4gICAgICAgIERhdGUucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMgfHwgISh0aGlzIGluc3RhbmNlb2YgRGF0ZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0aGlzIGlzIG5vdCBhIERhdGUgb2JqZWN0LicpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIGRheSA9IHRoaXMuZ2V0RGF5KCk7XG4gICAgICAgICAgICB2YXIgZGF0ZSA9IHRoaXMuZ2V0RGF0ZSgpO1xuICAgICAgICAgICAgdmFyIG1vbnRoID0gdGhpcy5nZXRNb250aCgpO1xuICAgICAgICAgICAgdmFyIHllYXIgPSB0aGlzLmdldEZ1bGxZZWFyKCk7XG4gICAgICAgICAgICB2YXIgaG91ciA9IHRoaXMuZ2V0SG91cnMoKTtcbiAgICAgICAgICAgIHZhciBtaW51dGUgPSB0aGlzLmdldE1pbnV0ZXMoKTtcbiAgICAgICAgICAgIHZhciBzZWNvbmQgPSB0aGlzLmdldFNlY29uZHMoKTtcbiAgICAgICAgICAgIHZhciB0aW1lem9uZU9mZnNldCA9IHRoaXMuZ2V0VGltZXpvbmVPZmZzZXQoKTtcbiAgICAgICAgICAgIHZhciBob3Vyc09mZnNldCA9IE1hdGguZmxvb3IoTWF0aC5hYnModGltZXpvbmVPZmZzZXQpIC8gNjApO1xuICAgICAgICAgICAgdmFyIG1pbnV0ZXNPZmZzZXQgPSBNYXRoLmZsb29yKE1hdGguYWJzKHRpbWV6b25lT2Zmc2V0KSAlIDYwKTtcbiAgICAgICAgICAgIHJldHVybiBkYXlOYW1lW2RheV0gKyAnICcgK1xuICAgICAgICAgICAgICAgIG1vbnRoTmFtZVttb250aF0gKyAnICcgK1xuICAgICAgICAgICAgICAgIChkYXRlIDwgMTAgPyAnMCcgKyBkYXRlIDogZGF0ZSkgKyAnICcgK1xuICAgICAgICAgICAgICAgIHllYXIgKyAnICcgK1xuICAgICAgICAgICAgICAgIChob3VyIDwgMTAgPyAnMCcgKyBob3VyIDogaG91cikgKyAnOicgK1xuICAgICAgICAgICAgICAgIChtaW51dGUgPCAxMCA/ICcwJyArIG1pbnV0ZSA6IG1pbnV0ZSkgKyAnOicgK1xuICAgICAgICAgICAgICAgIChzZWNvbmQgPCAxMCA/ICcwJyArIHNlY29uZCA6IHNlY29uZCkgKyAnIEdNVCcgK1xuICAgICAgICAgICAgICAgICh0aW1lem9uZU9mZnNldCA+IDAgPyAnLScgOiAnKycpICtcbiAgICAgICAgICAgICAgICAoaG91cnNPZmZzZXQgPCAxMCA/ICcwJyArIGhvdXJzT2Zmc2V0IDogaG91cnNPZmZzZXQpICtcbiAgICAgICAgICAgICAgICAobWludXRlc09mZnNldCA8IDEwID8gJzAnICsgbWludXRlc09mZnNldCA6IG1pbnV0ZXNPZmZzZXQpO1xuICAgICAgICB9O1xuICAgICAgICBpZiAoc3VwcG9ydHNEZXNjcmlwdG9ycykge1xuICAgICAgICAgICAgJE9iamVjdC5kZWZpbmVQcm9wZXJ0eShEYXRlLnByb3RvdHlwZSwgJ3RvU3RyaW5nJywge1xuICAgICAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB3cml0YWJsZTogdHJ1ZVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBFUzUgMTUuOS41LjQzXG4gICAgLy8gaHR0cDovL2VzNS5naXRodWIuY29tLyN4MTUuOS41LjQzXG4gICAgLy8gVGhpcyBmdW5jdGlvbiByZXR1cm5zIGEgU3RyaW5nIHZhbHVlIHJlcHJlc2VudCB0aGUgaW5zdGFuY2UgaW4gdGltZVxuICAgIC8vIHJlcHJlc2VudGVkIGJ5IHRoaXMgRGF0ZSBvYmplY3QuIFRoZSBmb3JtYXQgb2YgdGhlIFN0cmluZyBpcyB0aGUgRGF0ZSBUaW1lXG4gICAgLy8gc3RyaW5nIGZvcm1hdCBkZWZpbmVkIGluIDE1LjkuMS4xNS4gQWxsIGZpZWxkcyBhcmUgcHJlc2VudCBpbiB0aGUgU3RyaW5nLlxuICAgIC8vIFRoZSB0aW1lIHpvbmUgaXMgYWx3YXlzIFVUQywgZGVub3RlZCBieSB0aGUgc3VmZml4IFouIElmIHRoZSB0aW1lIHZhbHVlIG9mXG4gICAgLy8gdGhpcyBvYmplY3QgaXMgbm90IGEgZmluaXRlIE51bWJlciBhIFJhbmdlRXJyb3IgZXhjZXB0aW9uIGlzIHRocm93bi5cbiAgICB2YXIgbmVnYXRpdmVEYXRlID0gLTYyMTk4NzU1MjAwMDAwO1xuICAgIHZhciBuZWdhdGl2ZVllYXJTdHJpbmcgPSAnLTAwMDAwMSc7XG4gICAgdmFyIGhhc05lZ2F0aXZlRGF0ZUJ1ZyA9IERhdGUucHJvdG90eXBlLnRvSVNPU3RyaW5nICYmIG5ldyBEYXRlKG5lZ2F0aXZlRGF0ZSkudG9JU09TdHJpbmcoKS5pbmRleE9mKG5lZ2F0aXZlWWVhclN0cmluZykgPT09IC0xO1xuICAgIHZhciBoYXNTYWZhcmk1MURhdGVCdWcgPSBEYXRlLnByb3RvdHlwZS50b0lTT1N0cmluZyAmJiBuZXcgRGF0ZSgtMSkudG9JU09TdHJpbmcoKSAhPT0gJzE5NjktMTItMzFUMjM6NTk6NTkuOTk5Wic7XG5cbiAgICB2YXIgZ2V0VGltZSA9IGNhbGwuYmluZChEYXRlLnByb3RvdHlwZS5nZXRUaW1lKTtcblxuICAgIGRlZmluZVByb3BlcnRpZXMoRGF0ZS5wcm90b3R5cGUsIHtcbiAgICAgICAgdG9JU09TdHJpbmc6IGZ1bmN0aW9uIHRvSVNPU3RyaW5nKCkge1xuICAgICAgICAgICAgaWYgKCFpc0Zpbml0ZSh0aGlzKSB8fCAhaXNGaW5pdGUoZ2V0VGltZSh0aGlzKSkpIHtcbiAgICAgICAgICAgICAgICAvLyBBZG9wZSBQaG90b3Nob3AgcmVxdWlyZXMgdGhlIHNlY29uZCBjaGVjay5cbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignRGF0ZS5wcm90b3R5cGUudG9JU09TdHJpbmcgY2FsbGVkIG9uIG5vbi1maW5pdGUgdmFsdWUuJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciB5ZWFyID0gb3JpZ2luYWxHZXRVVENGdWxsWWVhcih0aGlzKTtcblxuICAgICAgICAgICAgdmFyIG1vbnRoID0gb3JpZ2luYWxHZXRVVENNb250aCh0aGlzKTtcbiAgICAgICAgICAgIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZXMtc2hpbXMvZXM1LXNoaW0vaXNzdWVzLzExMVxuICAgICAgICAgICAgeWVhciArPSBNYXRoLmZsb29yKG1vbnRoIC8gMTIpO1xuICAgICAgICAgICAgbW9udGggPSAobW9udGggJSAxMiArIDEyKSAlIDEyO1xuXG4gICAgICAgICAgICAvLyB0aGUgZGF0ZSB0aW1lIHN0cmluZyBmb3JtYXQgaXMgc3BlY2lmaWVkIGluIDE1LjkuMS4xNS5cbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBbbW9udGggKyAxLCBvcmlnaW5hbEdldFVUQ0RhdGUodGhpcyksIG9yaWdpbmFsR2V0VVRDSG91cnModGhpcyksIG9yaWdpbmFsR2V0VVRDTWludXRlcyh0aGlzKSwgb3JpZ2luYWxHZXRVVENTZWNvbmRzKHRoaXMpXTtcbiAgICAgICAgICAgIHllYXIgPSAoXG4gICAgICAgICAgICAgICAgKHllYXIgPCAwID8gJy0nIDogKHllYXIgPiA5OTk5ID8gJysnIDogJycpKSArXG4gICAgICAgICAgICAgICAgc3RyU2xpY2UoJzAwMDAwJyArIE1hdGguYWJzKHllYXIpLCAoMCA8PSB5ZWFyICYmIHllYXIgPD0gOTk5OSkgPyAtNCA6IC02KVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXN1bHQubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAvLyBwYWQgbW9udGhzLCBkYXlzLCBob3VycywgbWludXRlcywgYW5kIHNlY29uZHMgdG8gaGF2ZSB0d28gZGlnaXRzLlxuICAgICAgICAgICAgICAgIHJlc3VsdFtpXSA9IHN0clNsaWNlKCcwMCcgKyByZXN1bHRbaV0sIC0yKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHBhZCBtaWxsaXNlY29uZHMgdG8gaGF2ZSB0aHJlZSBkaWdpdHMuXG4gICAgICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgICAgIHllYXIgKyAnLScgKyBhcnJheVNsaWNlKHJlc3VsdCwgMCwgMikuam9pbignLScpICtcbiAgICAgICAgICAgICAgICAnVCcgKyBhcnJheVNsaWNlKHJlc3VsdCwgMikuam9pbignOicpICsgJy4nICtcbiAgICAgICAgICAgICAgICBzdHJTbGljZSgnMDAwJyArIG9yaWdpbmFsR2V0VVRDTWlsbGlzZWNvbmRzKHRoaXMpLCAtMykgKyAnWidcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9LCBoYXNOZWdhdGl2ZURhdGVCdWcgfHwgaGFzU2FmYXJpNTFEYXRlQnVnKTtcblxuICAgIC8vIEVTNSAxNS45LjUuNDRcbiAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3gxNS45LjUuNDRcbiAgICAvLyBUaGlzIGZ1bmN0aW9uIHByb3ZpZGVzIGEgU3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgRGF0ZSBvYmplY3QgZm9yIHVzZSBieVxuICAgIC8vIEpTT04uc3RyaW5naWZ5ICgxNS4xMi4zKS5cbiAgICB2YXIgZGF0ZVRvSlNPTklzU3VwcG9ydGVkID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiBEYXRlLnByb3RvdHlwZS50b0pTT04gJiZcbiAgICAgICAgICAgICAgICBuZXcgRGF0ZShOYU4pLnRvSlNPTigpID09PSBudWxsICYmXG4gICAgICAgICAgICAgICAgbmV3IERhdGUobmVnYXRpdmVEYXRlKS50b0pTT04oKS5pbmRleE9mKG5lZ2F0aXZlWWVhclN0cmluZykgIT09IC0xICYmXG4gICAgICAgICAgICAgICAgRGF0ZS5wcm90b3R5cGUudG9KU09OLmNhbGwoeyAvLyBnZW5lcmljXG4gICAgICAgICAgICAgICAgICAgIHRvSVNPU3RyaW5nOiBmdW5jdGlvbiAoKSB7IHJldHVybiB0cnVlOyB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH0oKSk7XG4gICAgaWYgKCFkYXRlVG9KU09OSXNTdXBwb3J0ZWQpIHtcbiAgICAgICAgRGF0ZS5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OKGtleSkge1xuICAgICAgICAgICAgLy8gV2hlbiB0aGUgdG9KU09OIG1ldGhvZCBpcyBjYWxsZWQgd2l0aCBhcmd1bWVudCBrZXksIHRoZSBmb2xsb3dpbmdcbiAgICAgICAgICAgIC8vIHN0ZXBzIGFyZSB0YWtlbjpcblxuICAgICAgICAgICAgLy8gMS4gIExldCBPIGJlIHRoZSByZXN1bHQgb2YgY2FsbGluZyBUb09iamVjdCwgZ2l2aW5nIGl0IHRoZSB0aGlzXG4gICAgICAgICAgICAvLyB2YWx1ZSBhcyBpdHMgYXJndW1lbnQuXG4gICAgICAgICAgICAvLyAyLiBMZXQgdHYgYmUgRVMuVG9QcmltaXRpdmUoTywgaGludCBOdW1iZXIpLlxuICAgICAgICAgICAgdmFyIE8gPSAkT2JqZWN0KHRoaXMpO1xuICAgICAgICAgICAgdmFyIHR2ID0gRVMuVG9QcmltaXRpdmUoTyk7XG4gICAgICAgICAgICAvLyAzLiBJZiB0diBpcyBhIE51bWJlciBhbmQgaXMgbm90IGZpbml0ZSwgcmV0dXJuIG51bGwuXG4gICAgICAgICAgICBpZiAodHlwZW9mIHR2ID09PSAnbnVtYmVyJyAmJiAhaXNGaW5pdGUodHYpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyA0LiBMZXQgdG9JU08gYmUgdGhlIHJlc3VsdCBvZiBjYWxsaW5nIHRoZSBbW0dldF1dIGludGVybmFsIG1ldGhvZCBvZlxuICAgICAgICAgICAgLy8gTyB3aXRoIGFyZ3VtZW50IFwidG9JU09TdHJpbmdcIi5cbiAgICAgICAgICAgIHZhciB0b0lTTyA9IE8udG9JU09TdHJpbmc7XG4gICAgICAgICAgICAvLyA1LiBJZiBJc0NhbGxhYmxlKHRvSVNPKSBpcyBmYWxzZSwgdGhyb3cgYSBUeXBlRXJyb3IgZXhjZXB0aW9uLlxuICAgICAgICAgICAgaWYgKCFpc0NhbGxhYmxlKHRvSVNPKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3RvSVNPU3RyaW5nIHByb3BlcnR5IGlzIG5vdCBjYWxsYWJsZScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gNi4gUmV0dXJuIHRoZSByZXN1bHQgb2YgY2FsbGluZyB0aGUgW1tDYWxsXV0gaW50ZXJuYWwgbWV0aG9kIG9mXG4gICAgICAgICAgICAvLyAgdG9JU08gd2l0aCBPIGFzIHRoZSB0aGlzIHZhbHVlIGFuZCBhbiBlbXB0eSBhcmd1bWVudCBsaXN0LlxuICAgICAgICAgICAgcmV0dXJuIHRvSVNPLmNhbGwoTyk7XG5cbiAgICAgICAgICAgIC8vIE5PVEUgMSBUaGUgYXJndW1lbnQgaXMgaWdub3JlZC5cblxuICAgICAgICAgICAgLy8gTk9URSAyIFRoZSB0b0pTT04gZnVuY3Rpb24gaXMgaW50ZW50aW9uYWxseSBnZW5lcmljOyBpdCBkb2VzIG5vdFxuICAgICAgICAgICAgLy8gcmVxdWlyZSB0aGF0IGl0cyB0aGlzIHZhbHVlIGJlIGEgRGF0ZSBvYmplY3QuIFRoZXJlZm9yZSwgaXQgY2FuIGJlXG4gICAgICAgICAgICAvLyB0cmFuc2ZlcnJlZCB0byBvdGhlciBraW5kcyBvZiBvYmplY3RzIGZvciB1c2UgYXMgYSBtZXRob2QuIEhvd2V2ZXIsXG4gICAgICAgICAgICAvLyBpdCBkb2VzIHJlcXVpcmUgdGhhdCBhbnkgc3VjaCBvYmplY3QgaGF2ZSBhIHRvSVNPU3RyaW5nIG1ldGhvZC4gQW5cbiAgICAgICAgICAgIC8vIG9iamVjdCBpcyBmcmVlIHRvIHVzZSB0aGUgYXJndW1lbnQga2V5IHRvIGZpbHRlciBpdHNcbiAgICAgICAgICAgIC8vIHN0cmluZ2lmaWNhdGlvbi5cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBFUzUgMTUuOS40LjJcbiAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3gxNS45LjQuMlxuICAgIC8vIGJhc2VkIG9uIHdvcmsgc2hhcmVkIGJ5IERhbmllbCBGcmllc2VuIChkYW50bWFuKVxuICAgIC8vIGh0dHA6Ly9naXN0LmdpdGh1Yi5jb20vMzAzMjQ5XG4gICAgdmFyIHN1cHBvcnRzRXh0ZW5kZWRZZWFycyA9IERhdGUucGFyc2UoJyswMzM2NTgtMDktMjdUMDE6NDY6NDAuMDAwWicpID09PSAxZTE1O1xuICAgIHZhciBhY2NlcHRzSW52YWxpZERhdGVzID0gIWlzTmFOKERhdGUucGFyc2UoJzIwMTItMDQtMDRUMjQ6MDA6MDAuNTAwWicpKSB8fCAhaXNOYU4oRGF0ZS5wYXJzZSgnMjAxMi0xMS0zMVQyMzo1OTo1OS4wMDBaJykpIHx8ICFpc05hTihEYXRlLnBhcnNlKCcyMDEyLTEyLTMxVDIzOjU5OjYwLjAwMFonKSk7XG4gICAgdmFyIGRvZXNOb3RQYXJzZVkyS05ld1llYXIgPSBpc05hTihEYXRlLnBhcnNlKCcyMDAwLTAxLTAxVDAwOjAwOjAwLjAwMFonKSk7XG4gICAgaWYgKGRvZXNOb3RQYXJzZVkyS05ld1llYXIgfHwgYWNjZXB0c0ludmFsaWREYXRlcyB8fCAhc3VwcG9ydHNFeHRlbmRlZFllYXJzKSB7XG4gICAgICAgIC8vIFhYWCBnbG9iYWwgYXNzaWdubWVudCB3b24ndCB3b3JrIGluIGVtYmVkZGluZ3MgdGhhdCB1c2VcbiAgICAgICAgLy8gYW4gYWx0ZXJuYXRlIG9iamVjdCBmb3IgdGhlIGNvbnRleHQuXG4gICAgICAgIC8qIGdsb2JhbCBEYXRlOiB0cnVlICovXG4gICAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLXVuZGVmICovXG4gICAgICAgIHZhciBtYXhTYWZlVW5zaWduZWQzMkJpdCA9IE1hdGgucG93KDIsIDMxKSAtIDE7XG4gICAgICAgIHZhciBoYXNTYWZhcmlTaWduZWRJbnRCdWcgPSBpc0FjdHVhbE5hTihuZXcgRGF0ZSgxOTcwLCAwLCAxLCAwLCAwLCAwLCBtYXhTYWZlVW5zaWduZWQzMkJpdCArIDEpLmdldFRpbWUoKSk7XG4gICAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWltcGxpY2l0LWdsb2JhbHMgKi9cbiAgICAgICAgRGF0ZSA9IChmdW5jdGlvbiAoTmF0aXZlRGF0ZSkge1xuICAgICAgICAvKiBlc2xpbnQtZW5hYmxlIG5vLWltcGxpY2l0LWdsb2JhbHMgKi9cbiAgICAgICAgLyogZXNsaW50LWVuYWJsZSBuby11bmRlZiAqL1xuICAgICAgICAgICAgLy8gRGF0ZS5sZW5ndGggPT09IDdcbiAgICAgICAgICAgIHZhciBEYXRlU2hpbSA9IGZ1bmN0aW9uIERhdGUoWSwgTSwgRCwgaCwgbSwgcywgbXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgZGF0ZTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcyBpbnN0YW5jZW9mIE5hdGl2ZURhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNlY29uZHMgPSBzO1xuICAgICAgICAgICAgICAgICAgICB2YXIgbWlsbGlzID0gbXM7XG4gICAgICAgICAgICAgICAgICAgIGlmIChoYXNTYWZhcmlTaWduZWRJbnRCdWcgJiYgbGVuZ3RoID49IDcgJiYgbXMgPiBtYXhTYWZlVW5zaWduZWQzMkJpdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gd29yayBhcm91bmQgYSBTYWZhcmkgOC85IGJ1ZyB3aGVyZSBpdCB0cmVhdHMgdGhlIHNlY29uZHMgYXMgc2lnbmVkXG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbXNUb1NoaWZ0ID0gTWF0aC5mbG9vcihtcyAvIG1heFNhZmVVbnNpZ25lZDMyQml0KSAqIG1heFNhZmVVbnNpZ25lZDMyQml0O1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHNUb1NoaWZ0ID0gTWF0aC5mbG9vcihtc1RvU2hpZnQgLyAxZTMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2Vjb25kcyArPSBzVG9TaGlmdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbGxpcyAtPSBzVG9TaGlmdCAqIDFlMztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBkYXRlID0gbGVuZ3RoID09PSAxICYmICRTdHJpbmcoWSkgPT09IFkgPyAvLyBpc1N0cmluZyhZKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgZXhwbGljaXRseSBwYXNzIGl0IHRocm91Z2ggcGFyc2U6XG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgTmF0aXZlRGF0ZShEYXRlU2hpbS5wYXJzZShZKSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2UgaGF2ZSB0byBtYW51YWxseSBtYWtlIGNhbGxzIGRlcGVuZGluZyBvbiBhcmd1bWVudFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gbGVuZ3RoIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aCA+PSA3ID8gbmV3IE5hdGl2ZURhdGUoWSwgTSwgRCwgaCwgbSwgc2Vjb25kcywgbWlsbGlzKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGggPj0gNiA/IG5ldyBOYXRpdmVEYXRlKFksIE0sIEQsIGgsIG0sIHNlY29uZHMpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aCA+PSA1ID8gbmV3IE5hdGl2ZURhdGUoWSwgTSwgRCwgaCwgbSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoID49IDQgPyBuZXcgTmF0aXZlRGF0ZShZLCBNLCBELCBoKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICBsZW5ndGggPj0gMyA/IG5ldyBOYXRpdmVEYXRlKFksIE0sIEQpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlbmd0aCA+PSAyID8gbmV3IE5hdGl2ZURhdGUoWSwgTSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoID49IDEgPyBuZXcgTmF0aXZlRGF0ZShZIGluc3RhbmNlb2YgTmF0aXZlRGF0ZSA/ICtZIDogWSkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgTmF0aXZlRGF0ZSgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGUgPSBOYXRpdmVEYXRlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICghaXNQcmltaXRpdmUoZGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUHJldmVudCBtaXh1cHMgd2l0aCB1bmZpeGVkIERhdGUgb2JqZWN0XG4gICAgICAgICAgICAgICAgICAgIGRlZmluZVByb3BlcnRpZXMoZGF0ZSwgeyBjb25zdHJ1Y3RvcjogRGF0ZVNoaW0gfSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBkYXRlO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gMTUuOS4xLjE1IERhdGUgVGltZSBTdHJpbmcgRm9ybWF0LlxuICAgICAgICAgICAgdmFyIGlzb0RhdGVFeHByZXNzaW9uID0gbmV3IFJlZ0V4cCgnXicgK1xuICAgICAgICAgICAgICAgICcoXFxcXGR7NH18WystXVxcXFxkezZ9KScgKyAvLyBmb3VyLWRpZ2l0IHllYXIgY2FwdHVyZSBvciBzaWduICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDYtZGlnaXQgZXh0ZW5kZWQgeWVhclxuICAgICAgICAgICAgICAgICcoPzotKFxcXFxkezJ9KScgKyAvLyBvcHRpb25hbCBtb250aCBjYXB0dXJlXG4gICAgICAgICAgICAgICAgJyg/Oi0oXFxcXGR7Mn0pJyArIC8vIG9wdGlvbmFsIGRheSBjYXB0dXJlXG4gICAgICAgICAgICAgICAgJyg/OicgKyAvLyBjYXB0dXJlIGhvdXJzOm1pbnV0ZXM6c2Vjb25kcy5taWxsaXNlY29uZHNcbiAgICAgICAgICAgICAgICAgICAgJ1QoXFxcXGR7Mn0pJyArIC8vIGhvdXJzIGNhcHR1cmVcbiAgICAgICAgICAgICAgICAgICAgJzooXFxcXGR7Mn0pJyArIC8vIG1pbnV0ZXMgY2FwdHVyZVxuICAgICAgICAgICAgICAgICAgICAnKD86JyArIC8vIG9wdGlvbmFsIDpzZWNvbmRzLm1pbGxpc2Vjb25kc1xuICAgICAgICAgICAgICAgICAgICAgICAgJzooXFxcXGR7Mn0pJyArIC8vIHNlY29uZHMgY2FwdHVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgJyg/OihcXFxcLlxcXFxkezEsfSkpPycgKyAvLyBtaWxsaXNlY29uZHMgY2FwdHVyZVxuICAgICAgICAgICAgICAgICAgICAnKT8nICtcbiAgICAgICAgICAgICAgICAnKCcgKyAvLyBjYXB0dXJlIFVUQyBvZmZzZXQgY29tcG9uZW50XG4gICAgICAgICAgICAgICAgICAgICdafCcgKyAvLyBVVEMgY2FwdHVyZVxuICAgICAgICAgICAgICAgICAgICAnKD86JyArIC8vIG9mZnNldCBzcGVjaWZpZXIgKy8taG91cnM6bWludXRlc1xuICAgICAgICAgICAgICAgICAgICAgICAgJyhbLStdKScgKyAvLyBzaWduIGNhcHR1cmVcbiAgICAgICAgICAgICAgICAgICAgICAgICcoXFxcXGR7Mn0pJyArIC8vIGhvdXJzIG9mZnNldCBjYXB0dXJlXG4gICAgICAgICAgICAgICAgICAgICAgICAnOihcXFxcZHsyfSknICsgLy8gbWludXRlcyBvZmZzZXQgY2FwdHVyZVxuICAgICAgICAgICAgICAgICAgICAnKScgK1xuICAgICAgICAgICAgICAgICcpPyk/KT8pPycgK1xuICAgICAgICAgICAgJyQnKTtcblxuICAgICAgICAgICAgdmFyIG1vbnRocyA9IFswLCAzMSwgNTksIDkwLCAxMjAsIDE1MSwgMTgxLCAyMTIsIDI0MywgMjczLCAzMDQsIDMzNCwgMzY1XTtcblxuICAgICAgICAgICAgdmFyIGRheUZyb21Nb250aCA9IGZ1bmN0aW9uIGRheUZyb21Nb250aCh5ZWFyLCBtb250aCkge1xuICAgICAgICAgICAgICAgIHZhciB0ID0gbW9udGggPiAxID8gMSA6IDA7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgbW9udGhzW21vbnRoXSArXG4gICAgICAgICAgICAgICAgICAgIE1hdGguZmxvb3IoKHllYXIgLSAxOTY5ICsgdCkgLyA0KSAtXG4gICAgICAgICAgICAgICAgICAgIE1hdGguZmxvb3IoKHllYXIgLSAxOTAxICsgdCkgLyAxMDApICtcbiAgICAgICAgICAgICAgICAgICAgTWF0aC5mbG9vcigoeWVhciAtIDE2MDEgKyB0KSAvIDQwMCkgK1xuICAgICAgICAgICAgICAgICAgICAzNjUgKiAoeWVhciAtIDE5NzApXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHZhciB0b1VUQyA9IGZ1bmN0aW9uIHRvVVRDKHQpIHtcbiAgICAgICAgICAgICAgICB2YXIgcyA9IDA7XG4gICAgICAgICAgICAgICAgdmFyIG1zID0gdDtcbiAgICAgICAgICAgICAgICBpZiAoaGFzU2FmYXJpU2lnbmVkSW50QnVnICYmIG1zID4gbWF4U2FmZVVuc2lnbmVkMzJCaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gd29yayBhcm91bmQgYSBTYWZhcmkgOC85IGJ1ZyB3aGVyZSBpdCB0cmVhdHMgdGhlIHNlY29uZHMgYXMgc2lnbmVkXG4gICAgICAgICAgICAgICAgICAgIHZhciBtc1RvU2hpZnQgPSBNYXRoLmZsb29yKG1zIC8gbWF4U2FmZVVuc2lnbmVkMzJCaXQpICogbWF4U2FmZVVuc2lnbmVkMzJCaXQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzVG9TaGlmdCA9IE1hdGguZmxvb3IobXNUb1NoaWZ0IC8gMWUzKTtcbiAgICAgICAgICAgICAgICAgICAgcyArPSBzVG9TaGlmdDtcbiAgICAgICAgICAgICAgICAgICAgbXMgLT0gc1RvU2hpZnQgKiAxZTM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiAkTnVtYmVyKG5ldyBOYXRpdmVEYXRlKDE5NzAsIDAsIDEsIDAsIDAsIHMsIG1zKSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvLyBDb3B5IGFueSBjdXN0b20gbWV0aG9kcyBhIDNyZCBwYXJ0eSBsaWJyYXJ5IG1heSBoYXZlIGFkZGVkXG4gICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gTmF0aXZlRGF0ZSkge1xuICAgICAgICAgICAgICAgIGlmIChvd25zKE5hdGl2ZURhdGUsIGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgRGF0ZVNoaW1ba2V5XSA9IE5hdGl2ZURhdGVba2V5XTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENvcHkgXCJuYXRpdmVcIiBtZXRob2RzIGV4cGxpY2l0bHk7IHRoZXkgbWF5IGJlIG5vbi1lbnVtZXJhYmxlXG4gICAgICAgICAgICBkZWZpbmVQcm9wZXJ0aWVzKERhdGVTaGltLCB7XG4gICAgICAgICAgICAgICAgbm93OiBOYXRpdmVEYXRlLm5vdyxcbiAgICAgICAgICAgICAgICBVVEM6IE5hdGl2ZURhdGUuVVRDXG4gICAgICAgICAgICB9LCB0cnVlKTtcbiAgICAgICAgICAgIERhdGVTaGltLnByb3RvdHlwZSA9IE5hdGl2ZURhdGUucHJvdG90eXBlO1xuICAgICAgICAgICAgZGVmaW5lUHJvcGVydGllcyhEYXRlU2hpbS5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgICAgICBjb25zdHJ1Y3RvcjogRGF0ZVNoaW1cbiAgICAgICAgICAgIH0sIHRydWUpO1xuXG4gICAgICAgICAgICAvLyBVcGdyYWRlIERhdGUucGFyc2UgdG8gaGFuZGxlIHNpbXBsaWZpZWQgSVNPIDg2MDEgc3RyaW5nc1xuICAgICAgICAgICAgdmFyIHBhcnNlU2hpbSA9IGZ1bmN0aW9uIHBhcnNlKHN0cmluZykge1xuICAgICAgICAgICAgICAgIHZhciBtYXRjaCA9IGlzb0RhdGVFeHByZXNzaW9uLmV4ZWMoc3RyaW5nKTtcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gcGFyc2UgbW9udGhzLCBkYXlzLCBob3VycywgbWludXRlcywgc2Vjb25kcywgYW5kIG1pbGxpc2Vjb25kc1xuICAgICAgICAgICAgICAgICAgICAvLyBwcm92aWRlIGRlZmF1bHQgdmFsdWVzIGlmIG5lY2Vzc2FyeVxuICAgICAgICAgICAgICAgICAgICAvLyBwYXJzZSB0aGUgVVRDIG9mZnNldCBjb21wb25lbnRcbiAgICAgICAgICAgICAgICAgICAgdmFyIHllYXIgPSAkTnVtYmVyKG1hdGNoWzFdKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vbnRoID0gJE51bWJlcihtYXRjaFsyXSB8fCAxKSAtIDEsXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXkgPSAkTnVtYmVyKG1hdGNoWzNdIHx8IDEpIC0gMSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGhvdXIgPSAkTnVtYmVyKG1hdGNoWzRdIHx8IDApLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWludXRlID0gJE51bWJlcihtYXRjaFs1XSB8fCAwKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNlY29uZCA9ICROdW1iZXIobWF0Y2hbNl0gfHwgMCksXG4gICAgICAgICAgICAgICAgICAgICAgICBtaWxsaXNlY29uZCA9IE1hdGguZmxvb3IoJE51bWJlcihtYXRjaFs3XSB8fCAwKSAqIDEwMDApLFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2hlbiB0aW1lIHpvbmUgaXMgbWlzc2VkLCBsb2NhbCBvZmZzZXQgc2hvdWxkIGJlIHVzZWRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIChFUyA1LjEgYnVnKVxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gc2VlIGh0dHBzOi8vYnVncy5lY21hc2NyaXB0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MTEyXG4gICAgICAgICAgICAgICAgICAgICAgICBpc0xvY2FsVGltZSA9IEJvb2xlYW4obWF0Y2hbNF0gJiYgIW1hdGNoWzhdKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpZ25PZmZzZXQgPSBtYXRjaFs5XSA9PT0gJy0nID8gMSA6IC0xLFxuICAgICAgICAgICAgICAgICAgICAgICAgaG91ck9mZnNldCA9ICROdW1iZXIobWF0Y2hbMTBdIHx8IDApLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWludXRlT2Zmc2V0ID0gJE51bWJlcihtYXRjaFsxMV0gfHwgMCksXG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIHZhciBoYXNNaW51dGVzT3JTZWNvbmRzT3JNaWxsaXNlY29uZHMgPSBtaW51dGUgPiAwIHx8IHNlY29uZCA+IDAgfHwgbWlsbGlzZWNvbmQgPiAwO1xuICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICBob3VyIDwgKGhhc01pbnV0ZXNPclNlY29uZHNPck1pbGxpc2Vjb25kcyA/IDI0IDogMjUpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBtaW51dGUgPCA2MCAmJiBzZWNvbmQgPCA2MCAmJiBtaWxsaXNlY29uZCA8IDEwMDAgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIG1vbnRoID4gLTEgJiYgbW9udGggPCAxMiAmJiBob3VyT2Zmc2V0IDwgMjQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pbnV0ZU9mZnNldCA8IDYwICYmIC8vIGRldGVjdCBpbnZhbGlkIG9mZnNldHNcbiAgICAgICAgICAgICAgICAgICAgICAgIGRheSA+IC0xICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXkgPCAoZGF5RnJvbU1vbnRoKHllYXIsIG1vbnRoICsgMSkgLSBkYXlGcm9tTW9udGgoeWVhciwgbW9udGgpKVxuICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGF5RnJvbU1vbnRoKHllYXIsIG1vbnRoKSArIGRheSkgKiAyNCArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG91ciArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaG91ck9mZnNldCAqIHNpZ25PZmZzZXRcbiAgICAgICAgICAgICAgICAgICAgICAgICkgKiA2MDtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAocmVzdWx0ICsgbWludXRlICsgbWludXRlT2Zmc2V0ICogc2lnbk9mZnNldCkgKiA2MCArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Vjb25kXG4gICAgICAgICAgICAgICAgICAgICAgICApICogMTAwMCArIG1pbGxpc2Vjb25kO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTG9jYWxUaW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gdG9VVEMocmVzdWx0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgtOC42NGUxNSA8PSByZXN1bHQgJiYgcmVzdWx0IDw9IDguNjRlMTUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBOYXRpdmVEYXRlLnBhcnNlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZGVmaW5lUHJvcGVydGllcyhEYXRlU2hpbSwgeyBwYXJzZTogcGFyc2VTaGltIH0pO1xuXG4gICAgICAgICAgICByZXR1cm4gRGF0ZVNoaW07XG4gICAgICAgIH0oRGF0ZSkpO1xuICAgICAgICAvKiBnbG9iYWwgRGF0ZTogZmFsc2UgKi9cbiAgICB9XG5cbiAgICAvLyBFUzUgMTUuOS40LjRcbiAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3gxNS45LjQuNFxuICAgIGlmICghRGF0ZS5ub3cpIHtcbiAgICAgICAgRGF0ZS5ub3cgPSBmdW5jdGlvbiBub3coKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy9cbiAgICAvLyBOdW1iZXJcbiAgICAvLyA9PT09PT1cbiAgICAvL1xuXG4gICAgLy8gRVM1LjEgMTUuNy40LjVcbiAgICAvLyBodHRwOi8vZXM1LmdpdGh1Yi5jb20vI3gxNS43LjQuNVxuICAgIHZhciBoYXNUb0ZpeGVkQnVncyA9IE51bWJlclByb3RvdHlwZS50b0ZpeGVkICYmIChcbiAgICAgICgwLjAwMDA4KS50b0ZpeGVkKDMpICE9PSAnMC4wMDAnIHx8XG4gICAgICAoMC45KS50b0ZpeGVkKDApICE9PSAnMScgfHxcbiAgICAgICgxLjI1NSkudG9GaXhlZCgyKSAhPT0gJzEuMjUnIHx8XG4gICAgICAoMTAwMDAwMDAwMDAwMDAwMDEyOCkudG9GaXhlZCgwKSAhPT0gJzEwMDAwMDAwMDAwMDAwMDAxMjgnXG4gICAgKTtcblxuICAgIHZhciB0b0ZpeGVkSGVscGVycyA9IHtcbiAgICAgICAgYmFzZTogMWU3LFxuICAgICAgICBzaXplOiA2LFxuICAgICAgICBkYXRhOiBbMCwgMCwgMCwgMCwgMCwgMF0sXG4gICAgICAgIG11bHRpcGx5OiBmdW5jdGlvbiBtdWx0aXBseShuLCBjKSB7XG4gICAgICAgICAgICB2YXIgaSA9IC0xO1xuICAgICAgICAgICAgdmFyIGMyID0gYztcbiAgICAgICAgICAgIHdoaWxlICgrK2kgPCB0b0ZpeGVkSGVscGVycy5zaXplKSB7XG4gICAgICAgICAgICAgICAgYzIgKz0gbiAqIHRvRml4ZWRIZWxwZXJzLmRhdGFbaV07XG4gICAgICAgICAgICAgICAgdG9GaXhlZEhlbHBlcnMuZGF0YVtpXSA9IGMyICUgdG9GaXhlZEhlbHBlcnMuYmFzZTtcbiAgICAgICAgICAgICAgICBjMiA9IE1hdGguZmxvb3IoYzIgLyB0b0ZpeGVkSGVscGVycy5iYXNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZGl2aWRlOiBmdW5jdGlvbiBkaXZpZGUobikge1xuICAgICAgICAgICAgdmFyIGkgPSB0b0ZpeGVkSGVscGVycy5zaXplO1xuICAgICAgICAgICAgdmFyIGMgPSAwO1xuICAgICAgICAgICAgd2hpbGUgKC0taSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgYyArPSB0b0ZpeGVkSGVscGVycy5kYXRhW2ldO1xuICAgICAgICAgICAgICAgIHRvRml4ZWRIZWxwZXJzLmRhdGFbaV0gPSBNYXRoLmZsb29yKGMgLyBuKTtcbiAgICAgICAgICAgICAgICBjID0gKGMgJSBuKSAqIHRvRml4ZWRIZWxwZXJzLmJhc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIG51bVRvU3RyaW5nOiBmdW5jdGlvbiBudW1Ub1N0cmluZygpIHtcbiAgICAgICAgICAgIHZhciBpID0gdG9GaXhlZEhlbHBlcnMuc2l6ZTtcbiAgICAgICAgICAgIHZhciBzID0gJyc7XG4gICAgICAgICAgICB3aGlsZSAoLS1pID49IDApIHtcbiAgICAgICAgICAgICAgICBpZiAocyAhPT0gJycgfHwgaSA9PT0gMCB8fCB0b0ZpeGVkSGVscGVycy5kYXRhW2ldICE9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0ID0gJFN0cmluZyh0b0ZpeGVkSGVscGVycy5kYXRhW2ldKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHMgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzID0gdDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHMgKz0gc3RyU2xpY2UoJzAwMDAwMDAnLCAwLCA3IC0gdC5sZW5ndGgpICsgdDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzO1xuICAgICAgICB9LFxuICAgICAgICBwb3c6IGZ1bmN0aW9uIHBvdyh4LCBuLCBhY2MpIHtcbiAgICAgICAgICAgIHJldHVybiAobiA9PT0gMCA/IGFjYyA6IChuICUgMiA9PT0gMSA/IHBvdyh4LCBuIC0gMSwgYWNjICogeCkgOiBwb3coeCAqIHgsIG4gLyAyLCBhY2MpKSk7XG4gICAgICAgIH0sXG4gICAgICAgIGxvZzogZnVuY3Rpb24gbG9nKHgpIHtcbiAgICAgICAgICAgIHZhciBuID0gMDtcbiAgICAgICAgICAgIHZhciB4MiA9IHg7XG4gICAgICAgICAgICB3aGlsZSAoeDIgPj0gNDA5Nikge1xuICAgICAgICAgICAgICAgIG4gKz0gMTI7XG4gICAgICAgICAgICAgICAgeDIgLz0gNDA5NjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdoaWxlICh4MiA+PSAyKSB7XG4gICAgICAgICAgICAgICAgbiArPSAxO1xuICAgICAgICAgICAgICAgIHgyIC89IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbjtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgdG9GaXhlZFNoaW0gPSBmdW5jdGlvbiB0b0ZpeGVkKGZyYWN0aW9uRGlnaXRzKSB7XG4gICAgICAgIHZhciBmLCB4LCBzLCBtLCBlLCB6LCBqLCBrO1xuXG4gICAgICAgIC8vIFRlc3QgZm9yIE5hTiBhbmQgcm91bmQgZnJhY3Rpb25EaWdpdHMgZG93blxuICAgICAgICBmID0gJE51bWJlcihmcmFjdGlvbkRpZ2l0cyk7XG4gICAgICAgIGYgPSBpc0FjdHVhbE5hTihmKSA/IDAgOiBNYXRoLmZsb29yKGYpO1xuXG4gICAgICAgIGlmIChmIDwgMCB8fCBmID4gMjApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdOdW1iZXIudG9GaXhlZCBjYWxsZWQgd2l0aCBpbnZhbGlkIG51bWJlciBvZiBkZWNpbWFscycpO1xuICAgICAgICB9XG5cbiAgICAgICAgeCA9ICROdW1iZXIodGhpcyk7XG5cbiAgICAgICAgaWYgKGlzQWN0dWFsTmFOKHgpKSB7XG4gICAgICAgICAgICByZXR1cm4gJ05hTic7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBpdCBpcyB0b28gYmlnIG9yIHNtYWxsLCByZXR1cm4gdGhlIHN0cmluZyB2YWx1ZSBvZiB0aGUgbnVtYmVyXG4gICAgICAgIGlmICh4IDw9IC0xZTIxIHx8IHggPj0gMWUyMSkge1xuICAgICAgICAgICAgcmV0dXJuICRTdHJpbmcoeCk7XG4gICAgICAgIH1cblxuICAgICAgICBzID0gJyc7XG5cbiAgICAgICAgaWYgKHggPCAwKSB7XG4gICAgICAgICAgICBzID0gJy0nO1xuICAgICAgICAgICAgeCA9IC14O1xuICAgICAgICB9XG5cbiAgICAgICAgbSA9ICcwJztcblxuICAgICAgICBpZiAoeCA+IDFlLTIxKSB7XG4gICAgICAgICAgICAvLyAxZS0yMSA8IHggPCAxZTIxXG4gICAgICAgICAgICAvLyAtNzAgPCBsb2cyKHgpIDwgNzBcbiAgICAgICAgICAgIGUgPSB0b0ZpeGVkSGVscGVycy5sb2coeCAqIHRvRml4ZWRIZWxwZXJzLnBvdygyLCA2OSwgMSkpIC0gNjk7XG4gICAgICAgICAgICB6ID0gKGUgPCAwID8geCAqIHRvRml4ZWRIZWxwZXJzLnBvdygyLCAtZSwgMSkgOiB4IC8gdG9GaXhlZEhlbHBlcnMucG93KDIsIGUsIDEpKTtcbiAgICAgICAgICAgIHogKj0gMHgxMDAwMDAwMDAwMDAwMDsgLy8gTWF0aC5wb3coMiwgNTIpO1xuICAgICAgICAgICAgZSA9IDUyIC0gZTtcblxuICAgICAgICAgICAgLy8gLTE4IDwgZSA8IDEyMlxuICAgICAgICAgICAgLy8geCA9IHogLyAyIF4gZVxuICAgICAgICAgICAgaWYgKGUgPiAwKSB7XG4gICAgICAgICAgICAgICAgdG9GaXhlZEhlbHBlcnMubXVsdGlwbHkoMCwgeik7XG4gICAgICAgICAgICAgICAgaiA9IGY7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAoaiA+PSA3KSB7XG4gICAgICAgICAgICAgICAgICAgIHRvRml4ZWRIZWxwZXJzLm11bHRpcGx5KDFlNywgMCk7XG4gICAgICAgICAgICAgICAgICAgIGogLT0gNztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0b0ZpeGVkSGVscGVycy5tdWx0aXBseSh0b0ZpeGVkSGVscGVycy5wb3coMTAsIGosIDEpLCAwKTtcbiAgICAgICAgICAgICAgICBqID0gZSAtIDE7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAoaiA+PSAyMykge1xuICAgICAgICAgICAgICAgICAgICB0b0ZpeGVkSGVscGVycy5kaXZpZGUoMSA8PCAyMyk7XG4gICAgICAgICAgICAgICAgICAgIGogLT0gMjM7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdG9GaXhlZEhlbHBlcnMuZGl2aWRlKDEgPDwgaik7XG4gICAgICAgICAgICAgICAgdG9GaXhlZEhlbHBlcnMubXVsdGlwbHkoMSwgMSk7XG4gICAgICAgICAgICAgICAgdG9GaXhlZEhlbHBlcnMuZGl2aWRlKDIpO1xuICAgICAgICAgICAgICAgIG0gPSB0b0ZpeGVkSGVscGVycy5udW1Ub1N0cmluZygpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0b0ZpeGVkSGVscGVycy5tdWx0aXBseSgwLCB6KTtcbiAgICAgICAgICAgICAgICB0b0ZpeGVkSGVscGVycy5tdWx0aXBseSgxIDw8ICgtZSksIDApO1xuICAgICAgICAgICAgICAgIG0gPSB0b0ZpeGVkSGVscGVycy5udW1Ub1N0cmluZygpICsgc3RyU2xpY2UoJzAuMDAwMDAwMDAwMDAwMDAwMDAwMDAnLCAyLCAyICsgZik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZiA+IDApIHtcbiAgICAgICAgICAgIGsgPSBtLmxlbmd0aDtcblxuICAgICAgICAgICAgaWYgKGsgPD0gZikge1xuICAgICAgICAgICAgICAgIG0gPSBzICsgc3RyU2xpY2UoJzAuMDAwMDAwMDAwMDAwMDAwMDAwMCcsIDAsIGYgLSBrICsgMikgKyBtO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtID0gcyArIHN0clNsaWNlKG0sIDAsIGsgLSBmKSArICcuJyArIHN0clNsaWNlKG0sIGsgLSBmKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG0gPSBzICsgbTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtO1xuICAgIH07XG4gICAgZGVmaW5lUHJvcGVydGllcyhOdW1iZXJQcm90b3R5cGUsIHsgdG9GaXhlZDogdG9GaXhlZFNoaW0gfSwgaGFzVG9GaXhlZEJ1Z3MpO1xuXG4gICAgdmFyIGhhc1RvUHJlY2lzaW9uVW5kZWZpbmVkQnVnID0gKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJldHVybiAxLjAudG9QcmVjaXNpb24odW5kZWZpbmVkKSA9PT0gJzEnO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0oKSk7XG4gICAgdmFyIG9yaWdpbmFsVG9QcmVjaXNpb24gPSBOdW1iZXJQcm90b3R5cGUudG9QcmVjaXNpb247XG4gICAgZGVmaW5lUHJvcGVydGllcyhOdW1iZXJQcm90b3R5cGUsIHtcbiAgICAgICAgdG9QcmVjaXNpb246IGZ1bmN0aW9uIHRvUHJlY2lzaW9uKHByZWNpc2lvbikge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBwcmVjaXNpb24gPT09ICd1bmRlZmluZWQnID8gb3JpZ2luYWxUb1ByZWNpc2lvbi5jYWxsKHRoaXMpIDogb3JpZ2luYWxUb1ByZWNpc2lvbi5jYWxsKHRoaXMsIHByZWNpc2lvbik7XG4gICAgICAgIH1cbiAgICB9LCBoYXNUb1ByZWNpc2lvblVuZGVmaW5lZEJ1Zyk7XG5cbiAgICAvL1xuICAgIC8vIFN0cmluZ1xuICAgIC8vID09PT09PVxuICAgIC8vXG5cbiAgICAvLyBFUzUgMTUuNS40LjE0XG4gICAgLy8gaHR0cDovL2VzNS5naXRodWIuY29tLyN4MTUuNS40LjE0XG5cbiAgICAvLyBbYnVnZml4LCBJRSBsdCA5LCBmaXJlZm94IDQsIEtvbnF1ZXJvciwgT3BlcmEsIG9ic2N1cmUgYnJvd3NlcnNdXG4gICAgLy8gTWFueSBicm93c2VycyBkbyBub3Qgc3BsaXQgcHJvcGVybHkgd2l0aCByZWd1bGFyIGV4cHJlc3Npb25zIG9yIHRoZXlcbiAgICAvLyBkbyBub3QgcGVyZm9ybSB0aGUgc3BsaXQgY29ycmVjdGx5IHVuZGVyIG9ic2N1cmUgY29uZGl0aW9ucy5cbiAgICAvLyBTZWUgaHR0cDovL2Jsb2cuc3RldmVubGV2aXRoYW4uY29tL2FyY2hpdmVzL2Nyb3NzLWJyb3dzZXItc3BsaXRcbiAgICAvLyBJJ3ZlIHRlc3RlZCBpbiBtYW55IGJyb3dzZXJzIGFuZCB0aGlzIHNlZW1zIHRvIGNvdmVyIHRoZSBkZXZpYW50IG9uZXM6XG4gICAgLy8gICAgJ2FiJy5zcGxpdCgvKD86YWIpKi8pIHNob3VsZCBiZSBbXCJcIiwgXCJcIl0sIG5vdCBbXCJcIl1cbiAgICAvLyAgICAnLicuc3BsaXQoLyguPykoLj8pLykgc2hvdWxkIGJlIFtcIlwiLCBcIi5cIiwgXCJcIiwgXCJcIl0sIG5vdCBbXCJcIiwgXCJcIl1cbiAgICAvLyAgICAndGVzc3QnLnNwbGl0KC8ocykqLykgc2hvdWxkIGJlIFtcInRcIiwgdW5kZWZpbmVkLCBcImVcIiwgXCJzXCIsIFwidFwiXSwgbm90XG4gICAgLy8gICAgICAgW3VuZGVmaW5lZCwgXCJ0XCIsIHVuZGVmaW5lZCwgXCJlXCIsIC4uLl1cbiAgICAvLyAgICAnJy5zcGxpdCgvLj8vKSBzaG91bGQgYmUgW10sIG5vdCBbXCJcIl1cbiAgICAvLyAgICAnLicuc3BsaXQoLygpKCkvKSBzaG91bGQgYmUgW1wiLlwiXSwgbm90IFtcIlwiLCBcIlwiLCBcIi5cIl1cblxuICAgIGlmIChcbiAgICAgICAgJ2FiJy5zcGxpdCgvKD86YWIpKi8pLmxlbmd0aCAhPT0gMiB8fFxuICAgICAgICAnLicuc3BsaXQoLyguPykoLj8pLykubGVuZ3RoICE9PSA0IHx8XG4gICAgICAgICd0ZXNzdCcuc3BsaXQoLyhzKSovKVsxXSA9PT0gJ3QnIHx8XG4gICAgICAgICd0ZXN0Jy5zcGxpdCgvKD86KS8sIC0xKS5sZW5ndGggIT09IDQgfHxcbiAgICAgICAgJycuc3BsaXQoLy4/LykubGVuZ3RoIHx8XG4gICAgICAgICcuJy5zcGxpdCgvKCkoKS8pLmxlbmd0aCA+IDFcbiAgICApIHtcbiAgICAgICAgKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjb21wbGlhbnRFeGVjTnBjZyA9IHR5cGVvZiAoLygpPz8vKS5leGVjKCcnKVsxXSA9PT0gJ3VuZGVmaW5lZCc7IC8vIE5QQ0c6IG5vbnBhcnRpY2lwYXRpbmcgY2FwdHVyaW5nIGdyb3VwXG4gICAgICAgICAgICB2YXIgbWF4U2FmZTMyQml0SW50ID0gTWF0aC5wb3coMiwgMzIpIC0gMTtcblxuICAgICAgICAgICAgU3RyaW5nUHJvdG90eXBlLnNwbGl0ID0gZnVuY3Rpb24gKHNlcGFyYXRvciwgbGltaXQpIHtcbiAgICAgICAgICAgICAgICB2YXIgc3RyaW5nID0gU3RyaW5nKHRoaXMpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc2VwYXJhdG9yID09PSAndW5kZWZpbmVkJyAmJiBsaW1pdCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgYHNlcGFyYXRvcmAgaXMgbm90IGEgcmVnZXgsIHVzZSBuYXRpdmUgc3BsaXRcbiAgICAgICAgICAgICAgICBpZiAoIWlzUmVnZXgoc2VwYXJhdG9yKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gc3RyU3BsaXQodGhpcywgc2VwYXJhdG9yLCBsaW1pdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFyIG91dHB1dCA9IFtdO1xuICAgICAgICAgICAgICAgIHZhciBmbGFncyA9IChzZXBhcmF0b3IuaWdub3JlQ2FzZSA/ICdpJyA6ICcnKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHNlcGFyYXRvci5tdWx0aWxpbmUgPyAnbScgOiAnJykgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXBhcmF0b3IudW5pY29kZSA/ICd1JyA6ICcnKSArIC8vIGluIEVTNlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZXBhcmF0b3Iuc3RpY2t5ID8gJ3knIDogJycpLCAvLyBGaXJlZm94IDMrIGFuZCBFUzZcbiAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IDAsXG4gICAgICAgICAgICAgICAgICAgIC8vIE1ha2UgYGdsb2JhbGAgYW5kIGF2b2lkIGBsYXN0SW5kZXhgIGlzc3VlcyBieSB3b3JraW5nIHdpdGggYSBjb3B5XG4gICAgICAgICAgICAgICAgICAgIHNlcGFyYXRvcjIsIG1hdGNoLCBsYXN0SW5kZXgsIGxhc3RMZW5ndGg7XG4gICAgICAgICAgICAgICAgdmFyIHNlcGFyYXRvckNvcHkgPSBuZXcgUmVnRXhwKHNlcGFyYXRvci5zb3VyY2UsIGZsYWdzICsgJ2cnKTtcbiAgICAgICAgICAgICAgICBpZiAoIWNvbXBsaWFudEV4ZWNOcGNnKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIERvZXNuJ3QgbmVlZCBmbGFncyBneSwgYnV0IHRoZXkgZG9uJ3QgaHVydFxuICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3IyID0gbmV3IFJlZ0V4cCgnXicgKyBzZXBhcmF0b3JDb3B5LnNvdXJjZSArICckKD8hXFxcXHMpJywgZmxhZ3MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvKiBWYWx1ZXMgZm9yIGBsaW1pdGAsIHBlciB0aGUgc3BlYzpcbiAgICAgICAgICAgICAgICAgKiBJZiB1bmRlZmluZWQ6IDQyOTQ5NjcyOTUgLy8gbWF4U2FmZTMyQml0SW50XG4gICAgICAgICAgICAgICAgICogSWYgMCwgSW5maW5pdHksIG9yIE5hTjogMFxuICAgICAgICAgICAgICAgICAqIElmIHBvc2l0aXZlIG51bWJlcjogbGltaXQgPSBNYXRoLmZsb29yKGxpbWl0KTsgaWYgKGxpbWl0ID4gNDI5NDk2NzI5NSkgbGltaXQgLT0gNDI5NDk2NzI5NjtcbiAgICAgICAgICAgICAgICAgKiBJZiBuZWdhdGl2ZSBudW1iZXI6IDQyOTQ5NjcyOTYgLSBNYXRoLmZsb29yKE1hdGguYWJzKGxpbWl0KSlcbiAgICAgICAgICAgICAgICAgKiBJZiBvdGhlcjogVHlwZS1jb252ZXJ0LCB0aGVuIHVzZSB0aGUgYWJvdmUgcnVsZXNcbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICB2YXIgc3BsaXRMaW1pdCA9IHR5cGVvZiBsaW1pdCA9PT0gJ3VuZGVmaW5lZCcgPyBtYXhTYWZlMzJCaXRJbnQgOiBFUy5Ub1VpbnQzMihsaW1pdCk7XG4gICAgICAgICAgICAgICAgbWF0Y2ggPSBzZXBhcmF0b3JDb3B5LmV4ZWMoc3RyaW5nKTtcbiAgICAgICAgICAgICAgICB3aGlsZSAobWF0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYHNlcGFyYXRvckNvcHkubGFzdEluZGV4YCBpcyBub3QgcmVsaWFibGUgY3Jvc3MtYnJvd3NlclxuICAgICAgICAgICAgICAgICAgICBsYXN0SW5kZXggPSBtYXRjaC5pbmRleCArIG1hdGNoWzBdLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RJbmRleCA+IGxhc3RMYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1c2hDYWxsKG91dHB1dCwgc3RyU2xpY2Uoc3RyaW5nLCBsYXN0TGFzdEluZGV4LCBtYXRjaC5pbmRleCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gRml4IGJyb3dzZXJzIHdob3NlIGBleGVjYCBtZXRob2RzIGRvbid0IGNvbnNpc3RlbnRseSByZXR1cm4gYHVuZGVmaW5lZGAgZm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBub25wYXJ0aWNpcGF0aW5nIGNhcHR1cmluZyBncm91cHNcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghY29tcGxpYW50RXhlY05wY2cgJiYgbWF0Y2gubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qIGVzbGludC1kaXNhYmxlIG5vLWxvb3AtZnVuYyAqL1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoWzBdLnJlcGxhY2Uoc2VwYXJhdG9yMiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGggLSAyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgYXJndW1lbnRzW2ldID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoW2ldID0gdm9pZCAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLyogZXNsaW50LWVuYWJsZSBuby1sb29wLWZ1bmMgKi9cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaC5sZW5ndGggPiAxICYmIG1hdGNoLmluZGV4IDwgc3RyaW5nLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFycmF5X3B1c2guYXBwbHkob3V0cHV0LCBhcnJheVNsaWNlKG1hdGNoLCAxKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXN0TGVuZ3RoID0gbWF0Y2hbMF0ubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdExhc3RJbmRleCA9IGxhc3RJbmRleDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvdXRwdXQubGVuZ3RoID49IHNwbGl0TGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoc2VwYXJhdG9yQ29weS5sYXN0SW5kZXggPT09IG1hdGNoLmluZGV4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXBhcmF0b3JDb3B5Lmxhc3RJbmRleCsrOyAvLyBBdm9pZCBhbiBpbmZpbml0ZSBsb29wXG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgbWF0Y2ggPSBzZXBhcmF0b3JDb3B5LmV4ZWMoc3RyaW5nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGxhc3RMYXN0SW5kZXggPT09IHN0cmluZy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RMZW5ndGggfHwgIXNlcGFyYXRvckNvcHkudGVzdCgnJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHB1c2hDYWxsKG91dHB1dCwgJycpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcHVzaENhbGwob3V0cHV0LCBzdHJTbGljZShzdHJpbmcsIGxhc3RMYXN0SW5kZXgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG91dHB1dC5sZW5ndGggPiBzcGxpdExpbWl0ID8gYXJyYXlTbGljZShvdXRwdXQsIDAsIHNwbGl0TGltaXQpIDogb3V0cHV0O1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfSgpKTtcblxuICAgIC8vIFtidWdmaXgsIGNocm9tZV1cbiAgICAvLyBJZiBzZXBhcmF0b3IgaXMgdW5kZWZpbmVkLCB0aGVuIHRoZSByZXN1bHQgYXJyYXkgY29udGFpbnMganVzdCBvbmUgU3RyaW5nLFxuICAgIC8vIHdoaWNoIGlzIHRoZSB0aGlzIHZhbHVlIChjb252ZXJ0ZWQgdG8gYSBTdHJpbmcpLiBJZiBsaW1pdCBpcyBub3QgdW5kZWZpbmVkLFxuICAgIC8vIHRoZW4gdGhlIG91dHB1dCBhcnJheSBpcyB0cnVuY2F0ZWQgc28gdGhhdCBpdCBjb250YWlucyBubyBtb3JlIHRoYW4gbGltaXRcbiAgICAvLyBlbGVtZW50cy5cbiAgICAvLyBcIjBcIi5zcGxpdCh1bmRlZmluZWQsIDApIC0+IFtdXG4gICAgfSBlbHNlIGlmICgnMCcuc3BsaXQodm9pZCAwLCAwKS5sZW5ndGgpIHtcbiAgICAgICAgU3RyaW5nUHJvdG90eXBlLnNwbGl0ID0gZnVuY3Rpb24gc3BsaXQoc2VwYXJhdG9yLCBsaW1pdCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBzZXBhcmF0b3IgPT09ICd1bmRlZmluZWQnICYmIGxpbWl0ID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0clNwbGl0KHRoaXMsIHNlcGFyYXRvciwgbGltaXQpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBzdHJfcmVwbGFjZSA9IFN0cmluZ1Byb3RvdHlwZS5yZXBsYWNlO1xuICAgIHZhciByZXBsYWNlUmVwb3J0c0dyb3Vwc0NvcnJlY3RseSA9IChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBncm91cHMgPSBbXTtcbiAgICAgICAgJ3gnLnJlcGxhY2UoL3goLik/L2csIGZ1bmN0aW9uIChtYXRjaCwgZ3JvdXApIHtcbiAgICAgICAgICAgIHB1c2hDYWxsKGdyb3VwcywgZ3JvdXApO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIGdyb3Vwcy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGdyb3Vwc1swXSA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgfSgpKTtcblxuICAgIGlmICghcmVwbGFjZVJlcG9ydHNHcm91cHNDb3JyZWN0bHkpIHtcbiAgICAgICAgU3RyaW5nUHJvdG90eXBlLnJlcGxhY2UgPSBmdW5jdGlvbiByZXBsYWNlKHNlYXJjaFZhbHVlLCByZXBsYWNlVmFsdWUpIHtcbiAgICAgICAgICAgIHZhciBpc0ZuID0gaXNDYWxsYWJsZShyZXBsYWNlVmFsdWUpO1xuICAgICAgICAgICAgdmFyIGhhc0NhcHR1cmluZ0dyb3VwcyA9IGlzUmVnZXgoc2VhcmNoVmFsdWUpICYmICgvXFwpWyo/XS8pLnRlc3Qoc2VhcmNoVmFsdWUuc291cmNlKTtcbiAgICAgICAgICAgIGlmICghaXNGbiB8fCAhaGFzQ2FwdHVyaW5nR3JvdXBzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0cl9yZXBsYWNlLmNhbGwodGhpcywgc2VhcmNoVmFsdWUsIHJlcGxhY2VWYWx1ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciB3cmFwcGVkUmVwbGFjZVZhbHVlID0gZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICB2YXIgb3JpZ2luYWxMYXN0SW5kZXggPSBzZWFyY2hWYWx1ZS5sYXN0SW5kZXg7XG4gICAgICAgICAgICAgICAgICAgIHNlYXJjaFZhbHVlLmxhc3RJbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhcmdzID0gc2VhcmNoVmFsdWUuZXhlYyhtYXRjaCkgfHwgW107XG4gICAgICAgICAgICAgICAgICAgIHNlYXJjaFZhbHVlLmxhc3RJbmRleCA9IG9yaWdpbmFsTGFzdEluZGV4O1xuICAgICAgICAgICAgICAgICAgICBwdXNoQ2FsbChhcmdzLCBhcmd1bWVudHNbbGVuZ3RoIC0gMl0sIGFyZ3VtZW50c1tsZW5ndGggLSAxXSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXBsYWNlVmFsdWUuYXBwbHkodGhpcywgYXJncyk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3RyX3JlcGxhY2UuY2FsbCh0aGlzLCBzZWFyY2hWYWx1ZSwgd3JhcHBlZFJlcGxhY2VWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gRUNNQS0yNjIsIDNyZCBCLjIuM1xuICAgIC8vIE5vdCBhbiBFQ01BU2NyaXB0IHN0YW5kYXJkLCBhbHRob3VnaCBFQ01BU2NyaXB0IDNyZCBFZGl0aW9uIGhhcyBhXG4gICAgLy8gbm9uLW5vcm1hdGl2ZSBzZWN0aW9uIHN1Z2dlc3RpbmcgdW5pZm9ybSBzZW1hbnRpY3MgYW5kIGl0IHNob3VsZCBiZVxuICAgIC8vIG5vcm1hbGl6ZWQgYWNyb3NzIGFsbCBicm93c2Vyc1xuICAgIC8vIFtidWdmaXgsIElFIGx0IDldIElFIDwgOSBzdWJzdHIoKSB3aXRoIG5lZ2F0aXZlIHZhbHVlIG5vdCB3b3JraW5nIGluIElFXG4gICAgdmFyIHN0cmluZ19zdWJzdHIgPSBTdHJpbmdQcm90b3R5cGUuc3Vic3RyO1xuICAgIHZhciBoYXNOZWdhdGl2ZVN1YnN0ckJ1ZyA9ICcnLnN1YnN0ciAmJiAnMGInLnN1YnN0cigtMSkgIT09ICdiJztcbiAgICBkZWZpbmVQcm9wZXJ0aWVzKFN0cmluZ1Byb3RvdHlwZSwge1xuICAgICAgICBzdWJzdHI6IGZ1bmN0aW9uIHN1YnN0cihzdGFydCwgbGVuZ3RoKSB7XG4gICAgICAgICAgICB2YXIgbm9ybWFsaXplZFN0YXJ0ID0gc3RhcnQ7XG4gICAgICAgICAgICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgICAgICAgICAgICAgbm9ybWFsaXplZFN0YXJ0ID0gbWF4KHRoaXMubGVuZ3RoICsgc3RhcnQsIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0cmluZ19zdWJzdHIuY2FsbCh0aGlzLCBub3JtYWxpemVkU3RhcnQsIGxlbmd0aCk7XG4gICAgICAgIH1cbiAgICB9LCBoYXNOZWdhdGl2ZVN1YnN0ckJ1Zyk7XG5cbiAgICAvLyBFUzUgMTUuNS40LjIwXG4gICAgLy8gd2hpdGVzcGFjZSBmcm9tOiBodHRwOi8vZXM1LmdpdGh1Yi5pby8jeDE1LjUuNC4yMFxuICAgIHZhciB3cyA9ICdcXHgwOVxceDBBXFx4MEJcXHgwQ1xceDBEXFx4MjBcXHhBMFxcdTE2ODBcXHUxODBFXFx1MjAwMFxcdTIwMDFcXHUyMDAyXFx1MjAwMycgK1xuICAgICAgICAnXFx1MjAwNFxcdTIwMDVcXHUyMDA2XFx1MjAwN1xcdTIwMDhcXHUyMDA5XFx1MjAwQVxcdTIwMkZcXHUyMDVGXFx1MzAwMFxcdTIwMjgnICtcbiAgICAgICAgJ1xcdTIwMjlcXHVGRUZGJztcbiAgICB2YXIgemVyb1dpZHRoID0gJ1xcdTIwMGInO1xuICAgIHZhciB3c1JlZ2V4Q2hhcnMgPSAnWycgKyB3cyArICddJztcbiAgICB2YXIgdHJpbUJlZ2luUmVnZXhwID0gbmV3IFJlZ0V4cCgnXicgKyB3c1JlZ2V4Q2hhcnMgKyB3c1JlZ2V4Q2hhcnMgKyAnKicpO1xuICAgIHZhciB0cmltRW5kUmVnZXhwID0gbmV3IFJlZ0V4cCh3c1JlZ2V4Q2hhcnMgKyB3c1JlZ2V4Q2hhcnMgKyAnKiQnKTtcbiAgICB2YXIgaGFzVHJpbVdoaXRlc3BhY2VCdWcgPSBTdHJpbmdQcm90b3R5cGUudHJpbSAmJiAod3MudHJpbSgpIHx8ICF6ZXJvV2lkdGgudHJpbSgpKTtcbiAgICBkZWZpbmVQcm9wZXJ0aWVzKFN0cmluZ1Byb3RvdHlwZSwge1xuICAgICAgICAvLyBodHRwOi8vYmxvZy5zdGV2ZW5sZXZpdGhhbi5jb20vYXJjaGl2ZXMvZmFzdGVyLXRyaW0tamF2YXNjcmlwdFxuICAgICAgICAvLyBodHRwOi8vcGVyZmVjdGlvbmtpbGxzLmNvbS93aGl0ZXNwYWNlLWRldmlhdGlvbnMvXG4gICAgICAgIHRyaW06IGZ1bmN0aW9uIHRyaW0oKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHRoaXMgPT09ICd1bmRlZmluZWQnIHx8IHRoaXMgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiY2FuJ3QgY29udmVydCBcIiArIHRoaXMgKyAnIHRvIG9iamVjdCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuICRTdHJpbmcodGhpcykucmVwbGFjZSh0cmltQmVnaW5SZWdleHAsICcnKS5yZXBsYWNlKHRyaW1FbmRSZWdleHAsICcnKTtcbiAgICAgICAgfVxuICAgIH0sIGhhc1RyaW1XaGl0ZXNwYWNlQnVnKTtcbiAgICB2YXIgdHJpbSA9IGNhbGwuYmluZChTdHJpbmcucHJvdG90eXBlLnRyaW0pO1xuXG4gICAgdmFyIGhhc0xhc3RJbmRleEJ1ZyA9IFN0cmluZ1Byb3RvdHlwZS5sYXN0SW5kZXhPZiAmJiAnYWJj44GC44GEJy5sYXN0SW5kZXhPZign44GC44GEJywgMikgIT09IC0xO1xuICAgIGRlZmluZVByb3BlcnRpZXMoU3RyaW5nUHJvdG90eXBlLCB7XG4gICAgICAgIGxhc3RJbmRleE9mOiBmdW5jdGlvbiBsYXN0SW5kZXhPZihzZWFyY2hTdHJpbmcpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcyA9PT0gJ3VuZGVmaW5lZCcgfHwgdGhpcyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJjYW4ndCBjb252ZXJ0IFwiICsgdGhpcyArICcgdG8gb2JqZWN0Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgUyA9ICRTdHJpbmcodGhpcyk7XG4gICAgICAgICAgICB2YXIgc2VhcmNoU3RyID0gJFN0cmluZyhzZWFyY2hTdHJpbmcpO1xuICAgICAgICAgICAgdmFyIG51bVBvcyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxID8gJE51bWJlcihhcmd1bWVudHNbMV0pIDogTmFOO1xuICAgICAgICAgICAgdmFyIHBvcyA9IGlzQWN0dWFsTmFOKG51bVBvcykgPyBJbmZpbml0eSA6IEVTLlRvSW50ZWdlcihudW1Qb3MpO1xuICAgICAgICAgICAgdmFyIHN0YXJ0ID0gbWluKG1heChwb3MsIDApLCBTLmxlbmd0aCk7XG4gICAgICAgICAgICB2YXIgc2VhcmNoTGVuID0gc2VhcmNoU3RyLmxlbmd0aDtcbiAgICAgICAgICAgIHZhciBrID0gc3RhcnQgKyBzZWFyY2hMZW47XG4gICAgICAgICAgICB3aGlsZSAoayA+IDApIHtcbiAgICAgICAgICAgICAgICBrID0gbWF4KDAsIGsgLSBzZWFyY2hMZW4pO1xuICAgICAgICAgICAgICAgIHZhciBpbmRleCA9IHN0ckluZGV4T2Yoc3RyU2xpY2UoUywgaywgc3RhcnQgKyBzZWFyY2hMZW4pLCBzZWFyY2hTdHIpO1xuICAgICAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGsgKyBpbmRleDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICB9LCBoYXNMYXN0SW5kZXhCdWcpO1xuXG4gICAgdmFyIG9yaWdpbmFsTGFzdEluZGV4T2YgPSBTdHJpbmdQcm90b3R5cGUubGFzdEluZGV4T2Y7XG4gICAgZGVmaW5lUHJvcGVydGllcyhTdHJpbmdQcm90b3R5cGUsIHtcbiAgICAgICAgbGFzdEluZGV4T2Y6IGZ1bmN0aW9uIGxhc3RJbmRleE9mKHNlYXJjaFN0cmluZykge1xuICAgICAgICAgICAgcmV0dXJuIG9yaWdpbmFsTGFzdEluZGV4T2YuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfVxuICAgIH0sIFN0cmluZ1Byb3RvdHlwZS5sYXN0SW5kZXhPZi5sZW5ndGggIT09IDEpO1xuXG4gICAgLy8gRVMtNSAxNS4xLjIuMlxuICAgIC8qIGVzbGludC1kaXNhYmxlIHJhZGl4ICovXG4gICAgaWYgKHBhcnNlSW50KHdzICsgJzA4JykgIT09IDggfHwgcGFyc2VJbnQod3MgKyAnMHgxNicpICE9PSAyMikge1xuICAgIC8qIGVzbGludC1lbmFibGUgcmFkaXggKi9cbiAgICAgICAgLyogZ2xvYmFsIHBhcnNlSW50OiB0cnVlICovXG4gICAgICAgIHBhcnNlSW50ID0gKGZ1bmN0aW9uIChvcmlnUGFyc2VJbnQpIHtcbiAgICAgICAgICAgIHZhciBoZXhSZWdleCA9IC9eW1xcLStdPzBbeFhdLztcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBwYXJzZUludChzdHIsIHJhZGl4KSB7XG4gICAgICAgICAgICAgICAgdmFyIHN0cmluZyA9IHRyaW0oU3RyaW5nKHN0cikpO1xuICAgICAgICAgICAgICAgIHZhciBkZWZhdWx0ZWRSYWRpeCA9ICROdW1iZXIocmFkaXgpIHx8IChoZXhSZWdleC50ZXN0KHN0cmluZykgPyAxNiA6IDEwKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gb3JpZ1BhcnNlSW50KHN0cmluZywgZGVmYXVsdGVkUmFkaXgpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfShwYXJzZUludCkpO1xuICAgIH1cblxuICAgIC8vIGh0dHBzOi8vZXM1LmdpdGh1Yi5pby8jeDE1LjEuMi4zXG4gICAgaWYgKDEgLyBwYXJzZUZsb2F0KCctMCcpICE9PSAtSW5maW5pdHkpIHtcbiAgICAgICAgLyogZ2xvYmFsIHBhcnNlRmxvYXQ6IHRydWUgKi9cbiAgICAgICAgcGFyc2VGbG9hdCA9IChmdW5jdGlvbiAob3JpZ1BhcnNlRmxvYXQpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBwYXJzZUZsb2F0KHN0cmluZykge1xuICAgICAgICAgICAgICAgIHZhciBpbnB1dFN0cmluZyA9IHRyaW0oU3RyaW5nKHN0cmluZykpO1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBvcmlnUGFyc2VGbG9hdChpbnB1dFN0cmluZyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCA9PT0gMCAmJiBzdHJTbGljZShpbnB1dFN0cmluZywgMCwgMSkgPT09ICctJyA/IC0wIDogcmVzdWx0O1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfShwYXJzZUZsb2F0KSk7XG4gICAgfVxuXG4gICAgaWYgKFN0cmluZyhuZXcgUmFuZ2VFcnJvcigndGVzdCcpKSAhPT0gJ1JhbmdlRXJyb3I6IHRlc3QnKSB7XG4gICAgICAgIHZhciBlcnJvclRvU3RyaW5nU2hpbSA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzID09PSAndW5kZWZpbmVkJyB8fCB0aGlzID09PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcImNhbid0IGNvbnZlcnQgXCIgKyB0aGlzICsgJyB0byBvYmplY3QnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBuYW1lID0gdGhpcy5uYW1lO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBuYW1lID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIG5hbWUgPSAnRXJyb3InO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBuYW1lID0gJFN0cmluZyhuYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBtc2cgPSB0aGlzLm1lc3NhZ2U7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG1zZyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICBtc2cgPSAnJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG1zZyAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBtc2cgPSAkU3RyaW5nKG1zZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW5hbWUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbXNnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFtc2cpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmFtZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuYW1lICsgJzogJyArIG1zZztcbiAgICAgICAgfTtcbiAgICAgICAgLy8gY2FuJ3QgdXNlIGRlZmluZVByb3BlcnRpZXMgaGVyZSBiZWNhdXNlIG9mIHRvU3RyaW5nIGVudW1lcmF0aW9uIGlzc3VlIGluIElFIDw9IDhcbiAgICAgICAgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nID0gZXJyb3JUb1N0cmluZ1NoaW07XG4gICAgfVxuXG4gICAgaWYgKHN1cHBvcnRzRGVzY3JpcHRvcnMpIHtcbiAgICAgICAgdmFyIGVuc3VyZU5vbkVudW1lcmFibGUgPSBmdW5jdGlvbiAob2JqLCBwcm9wKSB7XG4gICAgICAgICAgICBpZiAoaXNFbnVtKG9iaiwgcHJvcCkpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3Iob2JqLCBwcm9wKTtcbiAgICAgICAgICAgICAgICBpZiAoZGVzYy5jb25maWd1cmFibGUpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVzYy5lbnVtZXJhYmxlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIHByb3AsIGRlc2MpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgZW5zdXJlTm9uRW51bWVyYWJsZShFcnJvci5wcm90b3R5cGUsICdtZXNzYWdlJyk7XG4gICAgICAgIGlmIChFcnJvci5wcm90b3R5cGUubWVzc2FnZSAhPT0gJycpIHtcbiAgICAgICAgICAgIEVycm9yLnByb3RvdHlwZS5tZXNzYWdlID0gJyc7XG4gICAgICAgIH1cbiAgICAgICAgZW5zdXJlTm9uRW51bWVyYWJsZShFcnJvci5wcm90b3R5cGUsICduYW1lJyk7XG4gICAgfVxuXG4gICAgaWYgKFN0cmluZygvYS9taWcpICE9PSAnL2EvZ2ltJykge1xuICAgICAgICB2YXIgcmVnZXhUb1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgdmFyIHN0ciA9ICcvJyArIHRoaXMuc291cmNlICsgJy8nO1xuICAgICAgICAgICAgaWYgKHRoaXMuZ2xvYmFsKSB7XG4gICAgICAgICAgICAgICAgc3RyICs9ICdnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aGlzLmlnbm9yZUNhc2UpIHtcbiAgICAgICAgICAgICAgICBzdHIgKz0gJ2knO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRoaXMubXVsdGlsaW5lKSB7XG4gICAgICAgICAgICAgICAgc3RyICs9ICdtJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzdHI7XG4gICAgICAgIH07XG4gICAgICAgIC8vIGNhbid0IHVzZSBkZWZpbmVQcm9wZXJ0aWVzIGhlcmUgYmVjYXVzZSBvZiB0b1N0cmluZyBlbnVtZXJhdGlvbiBpc3N1ZSBpbiBJRSA8PSA4XG4gICAgICAgIFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcgPSByZWdleFRvU3RyaW5nO1xuICAgIH1cbn0pKTtcbiIsIid1c2Ugc3RyaWN0Jztcbi8qanNsaW50IGVxZXE6IHRydWUqL1xuXG5IYW5kbGViYXJzLnJlZ2lzdGVySGVscGVyKCdzYW5pdGl6ZScsIGZ1bmN0aW9uICh0ZXh0KSB7XG4gICAgdmFyIHJlc3VsdDtcblxuICAgIGlmICh0ZXh0ID09PSB1bmRlZmluZWQpIHsgcmV0dXJuICcnOyB9XG5cbiAgICByZXN1bHQgPSBzYW5pdGl6ZUh0bWwodGV4dCwge1xuICAgICAgICBhbGxvd2VkVGFnczogWyAnZGl2JywgJ3NwYW4nLCAnYicsICdpJywgJ2VtJywgJ3N0cm9uZycsICdhJywgJ2JyJywgJ3RhYmxlJywgJ3Rib2R5JywgJ3RyJywgJ3RoJywgJ3RkJyBdLFxuICAgICAgICBhbGxvd2VkQXR0cmlidXRlczoge1xuICAgICAgICAgICAgJ2Rpdic6IFsgJ2NsYXNzJyBdLFxuICAgICAgICAgICAgJ3NwYW4nOiBbICdjbGFzcycgXSxcbiAgICAgICAgICAgICd0YWJsZSc6IFsgJ2NsYXNzJyBdLFxuICAgICAgICAgICAgJ3RkJzogWyAnY2xhc3MnIF0sXG4gICAgICAgICAgICAndGgnOiBbICdjb2xzcGFuJyBdLFxuICAgICAgICAgICAgJ2EnOiBbICdocmVmJyBdXG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBuZXcgSGFuZGxlYmFycy5TYWZlU3RyaW5nKHJlc3VsdCk7XG59KTtcblxuSGFuZGxlYmFycy5yZWdpc3RlckhlbHBlcigncmVuZGVyVGV4dFBhcmFtJywgZnVuY3Rpb24ocGFyYW0pIHtcbiAgICB2YXIgcmVzdWx0LCB0eXBlID0gJ3RleHQnLCBpZEF0dCA9ICcnO1xuICAgIHZhciBwYXJhbVR5cGUgPSBwYXJhbS50eXBlIHx8IHBhcmFtLnNjaGVtYSAmJiBwYXJhbS5zY2hlbWEudHlwZSB8fCAnJztcbiAgICB2YXIgaXNBcnJheSA9IHBhcmFtVHlwZS50b0xvd2VyQ2FzZSgpID09PSAnYXJyYXknIHx8IHBhcmFtLmFsbG93TXVsdGlwbGU7XG4gICAgdmFyIGRlZmF1bHRWYWx1ZSA9IGlzQXJyYXkgJiYgQXJyYXkuaXNBcnJheShwYXJhbS5kZWZhdWx0KSA/IHBhcmFtLmRlZmF1bHQuam9pbignXFxuJykgOiBwYXJhbS5kZWZhdWx0O1xuICAgIHZhciBuYW1lID0gSGFuZGxlYmFycy5VdGlscy5lc2NhcGVFeHByZXNzaW9uKHBhcmFtLm5hbWUpO1xuICAgIHZhciB2YWx1ZUlkID0gSGFuZGxlYmFycy5VdGlscy5lc2NhcGVFeHByZXNzaW9uKHBhcmFtLnZhbHVlSWQpO1xuICAgIHBhcmFtVHlwZSA9IEhhbmRsZWJhcnMuVXRpbHMuZXNjYXBlRXhwcmVzc2lvbihwYXJhbVR5cGUpO1xuXG4gICAgdmFyIGRhdGFWZW5kb3JFeHRlbnNpb25zID0gT2JqZWN0LmtleXMocGFyYW0pLmZpbHRlcihmdW5jdGlvbihwcm9wZXJ0eSkge1xuICAgICAgICAvLyBmaWx0ZXIgWC1kYXRhLSBwcm9wZXJ0aWVzXG4gICAgICAgIHJldHVybiBwcm9wZXJ0eS5tYXRjaCgvXlgtZGF0YS0vaSkgIT09IG51bGw7XG4gICAgfSkucmVkdWNlKGZ1bmN0aW9uKHJlc3VsdCwgcHJvcGVydHkpIHtcbiAgICAgICAgLy8gcmVtb3ZlIFgtIGZyb20gcHJvcGVydHkgbmFtZSwgc28gaXQgcmVzdWx0cyBpbiBodG1sIGF0dHJpYnV0ZXMgbGlrZSBkYXRhLWZvbz0nYmFyJ1xuICAgICAgICByZXR1cm4gcmVzdWx0ICs9ICcgJyArIHByb3BlcnR5LnN1YnN0cmluZygyLCBwcm9wZXJ0eS5sZW5ndGgpICsgJz1cXCcnICsgcGFyYW1bcHJvcGVydHldICsgJ1xcJyc7XG4gICAgfSwgJycpO1xuXG4gICAgaWYocGFyYW0uZm9ybWF0ICYmIHBhcmFtLmZvcm1hdCA9PT0gJ3Bhc3N3b3JkJykge1xuICAgICAgICB0eXBlID0gJ3Bhc3N3b3JkJztcbiAgICB9XG5cbiAgICBpZih2YWx1ZUlkKSB7XG4gICAgICAgIGlkQXR0ID0gJyBpZD1cXCcnICsgdmFsdWVJZCArICdcXCcnO1xuICAgIH1cblxuICAgIGlmIChkZWZhdWx0VmFsdWUpIHtcbiAgICAgIGRlZmF1bHRWYWx1ZSA9IHNhbml0aXplSHRtbChkZWZhdWx0VmFsdWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWZhdWx0VmFsdWUgPSAnJztcbiAgICB9XG5cbiAgICBpZihpc0FycmF5KSB7XG4gICAgICAgIHJlc3VsdCA9ICc8dGV4dGFyZWEgY2xhc3M9XFwnYm9keS10ZXh0YXJlYScgKyAocGFyYW0ucmVxdWlyZWQgPyAnIHJlcXVpcmVkJyA6ICcnKSArICdcXCcgbmFtZT1cXCcnICsgbmFtZSArICdcXCcnICsgaWRBdHQgKyBkYXRhVmVuZG9yRXh0ZW5zaW9ucztcbiAgICAgICAgcmVzdWx0ICs9ICcgcGxhY2Vob2xkZXI9XFwnUHJvdmlkZSBtdWx0aXBsZSB2YWx1ZXMgaW4gbmV3IGxpbmVzJyArIChwYXJhbS5yZXF1aXJlZCA/ICcgKGF0IGxlYXN0IG9uZSByZXF1aXJlZCkuJyA6ICcuJykgKyAnXFwnPic7XG4gICAgICAgIHJlc3VsdCArPSBkZWZhdWx0VmFsdWUgKyAnPC90ZXh0YXJlYT4nO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHZhciBwYXJhbWV0ZXJDbGFzcyA9ICdwYXJhbWV0ZXInO1xuICAgICAgICBpZihwYXJhbS5yZXF1aXJlZCkge1xuICAgICAgICAgIHBhcmFtZXRlckNsYXNzICs9ICcgcmVxdWlyZWQnO1xuICAgICAgICB9XG4gICAgICAgIHJlc3VsdCA9ICc8aW5wdXQgY2xhc3M9XFwnJyArIHBhcmFtZXRlckNsYXNzICsgJ1xcJyBtaW5sZW5ndGg9XFwnJyArIChwYXJhbS5yZXF1aXJlZCA/IDEgOiAwKSArICdcXCcnO1xuICAgICAgICByZXN1bHQgKz0gJyBuYW1lPVxcJycgKyBuYW1lICsnXFwnIHBsYWNlaG9sZGVyPVxcJycgKyAocGFyYW0ucmVxdWlyZWQgPyAnKHJlcXVpcmVkKScgOiAnJykgKyAnXFwnJyArIGlkQXR0ICsgZGF0YVZlbmRvckV4dGVuc2lvbnM7XG4gICAgICAgIHJlc3VsdCArPSAnIHR5cGU9XFwnJyArIHR5cGUgKyAnXFwnIHZhbHVlPVxcJycgKyBkZWZhdWx0VmFsdWUgKyAnXFwnLz4nO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IEhhbmRsZWJhcnMuU2FmZVN0cmluZyhyZXN1bHQpO1xufSk7XG5cbkhhbmRsZWJhcnMucmVnaXN0ZXJIZWxwZXIoJ2lmQ29uZCcsIGZ1bmN0aW9uICh2MSwgb3BlcmF0b3IsIHYyLCBvcHRpb25zKSB7XG5cbiAgICBzd2l0Y2ggKG9wZXJhdG9yKSB7XG4gICAgICAgIGNhc2UgJz09JzpcbiAgICAgICAgICAgIHJldHVybiAodjEgPT0gdjIpID8gb3B0aW9ucy5mbih0aGlzKSA6IG9wdGlvbnMuaW52ZXJzZSh0aGlzKTtcbiAgICAgICAgY2FzZSAnPT09JzpcbiAgICAgICAgICAgIHJldHVybiAodjEgPT09IHYyKSA/IG9wdGlvbnMuZm4odGhpcykgOiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgICAgIGNhc2UgJzwnOlxuICAgICAgICAgICAgcmV0dXJuICh2MSA8IHYyKSA/IG9wdGlvbnMuZm4odGhpcykgOiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgICAgIGNhc2UgJzw9JzpcbiAgICAgICAgICAgIHJldHVybiAodjEgPD0gdjIpID8gb3B0aW9ucy5mbih0aGlzKSA6IG9wdGlvbnMuaW52ZXJzZSh0aGlzKTtcbiAgICAgICAgY2FzZSAnPic6XG4gICAgICAgICAgICByZXR1cm4gKHYxID4gdjIpID8gb3B0aW9ucy5mbih0aGlzKSA6IG9wdGlvbnMuaW52ZXJzZSh0aGlzKTtcbiAgICAgICAgY2FzZSAnPj0nOlxuICAgICAgICAgICAgcmV0dXJuICh2MSA+PSB2MikgPyBvcHRpb25zLmZuKHRoaXMpIDogb3B0aW9ucy5pbnZlcnNlKHRoaXMpO1xuICAgICAgICBjYXNlICcmJic6XG4gICAgICAgICAgICByZXR1cm4gKHYxICYmIHYyKSA/IG9wdGlvbnMuZm4odGhpcykgOiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgICAgIGNhc2UgJ3x8JzpcbiAgICAgICAgICAgIHJldHVybiAodjEgfHwgdjIpID8gb3B0aW9ucy5mbih0aGlzKSA6IG9wdGlvbnMuaW52ZXJzZSh0aGlzKTtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmludmVyc2UodGhpcyk7XG4gICAgfVxufSk7XG5cbkhhbmRsZWJhcnMucmVnaXN0ZXJIZWxwZXIoJ2VzY2FwZScsIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIHZhciB0ZXh0ID0gSGFuZGxlYmFycy5VdGlscy5lc2NhcGVFeHByZXNzaW9uKHZhbHVlKTtcblxuICAgIHJldHVybiBuZXcgSGFuZGxlYmFycy5TYWZlU3RyaW5nKHRleHQpO1xufSk7XG4iLCIoZnVuY3Rpb24oZil7aWYodHlwZW9mIGV4cG9ydHM9PT1cIm9iamVjdFwiJiZ0eXBlb2YgbW9kdWxlIT09XCJ1bmRlZmluZWRcIil7bW9kdWxlLmV4cG9ydHM9ZigpfWVsc2UgaWYodHlwZW9mIGRlZmluZT09PVwiZnVuY3Rpb25cIiYmZGVmaW5lLmFtZCl7ZGVmaW5lKFtdLGYpfWVsc2V7dmFyIGc7aWYodHlwZW9mIHdpbmRvdyE9PVwidW5kZWZpbmVkXCIpe2c9d2luZG93fWVsc2UgaWYodHlwZW9mIGdsb2JhbCE9PVwidW5kZWZpbmVkXCIpe2c9Z2xvYmFsfWVsc2UgaWYodHlwZW9mIHNlbGYhPT1cInVuZGVmaW5lZFwiKXtnPXNlbGZ9ZWxzZXtnPXRoaXN9Zy5zYW5pdGl6ZUh0bWw9ZigpfX0pKGZ1bmN0aW9uKCl7dmFyIGRlZmluZSxtb2R1bGUsZXhwb3J0cztyZXR1cm4gZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KHsxOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXt2YXIgaHRtbHBhcnNlcj1yZXF1aXJlKFwiaHRtbHBhcnNlcjJcIik7dmFyIGV4dGVuZD1yZXF1aXJlKFwieHRlbmRcIik7dmFyIHF1b3RlUmVnZXhwPXJlcXVpcmUoXCJyZWdleHAtcXVvdGVcIik7ZnVuY3Rpb24gZWFjaChvYmosY2Ipe2lmKG9iailPYmplY3Qua2V5cyhvYmopLmZvckVhY2goZnVuY3Rpb24oa2V5KXtjYihvYmpba2V5XSxrZXkpfSl9ZnVuY3Rpb24gaGFzKG9iaixrZXkpe3JldHVybnt9Lmhhc093blByb3BlcnR5LmNhbGwob2JqLGtleSl9bW9kdWxlLmV4cG9ydHM9c2FuaXRpemVIdG1sO2Z1bmN0aW9uIHNhbml0aXplSHRtbChodG1sLG9wdGlvbnMsX3JlY3Vyc2luZyl7dmFyIHJlc3VsdD1cIlwiO2Z1bmN0aW9uIEZyYW1lKHRhZyxhdHRyaWJzKXt2YXIgdGhhdD10aGlzO3RoaXMudGFnPXRhZzt0aGlzLmF0dHJpYnM9YXR0cmlic3x8e307dGhpcy50YWdQb3NpdGlvbj1yZXN1bHQubGVuZ3RoO3RoaXMudGV4dD1cIlwiO3RoaXMudXBkYXRlUGFyZW50Tm9kZVRleHQ9ZnVuY3Rpb24oKXtpZihzdGFjay5sZW5ndGgpe3ZhciBwYXJlbnRGcmFtZT1zdGFja1tzdGFjay5sZW5ndGgtMV07cGFyZW50RnJhbWUudGV4dCs9dGhhdC50ZXh0fX19aWYoIW9wdGlvbnMpe29wdGlvbnM9c2FuaXRpemVIdG1sLmRlZmF1bHRzO29wdGlvbnMucGFyc2VyPWh0bWxQYXJzZXJEZWZhdWx0c31lbHNle29wdGlvbnM9ZXh0ZW5kKHNhbml0aXplSHRtbC5kZWZhdWx0cyxvcHRpb25zKTtpZihvcHRpb25zLnBhcnNlcil7b3B0aW9ucy5wYXJzZXI9ZXh0ZW5kKGh0bWxQYXJzZXJEZWZhdWx0cyxvcHRpb25zLnBhcnNlcil9ZWxzZXtvcHRpb25zLnBhcnNlcj1odG1sUGFyc2VyRGVmYXVsdHN9fXZhciBub25UZXh0VGFnc0FycmF5PW9wdGlvbnMubm9uVGV4dFRhZ3N8fFtcInNjcmlwdFwiLFwic3R5bGVcIixcInRleHRhcmVhXCJdO3ZhciBhbGxvd2VkQXR0cmlidXRlc01hcDt2YXIgYWxsb3dlZEF0dHJpYnV0ZXNHbG9iTWFwO2lmKG9wdGlvbnMuYWxsb3dlZEF0dHJpYnV0ZXMpe2FsbG93ZWRBdHRyaWJ1dGVzTWFwPXt9O2FsbG93ZWRBdHRyaWJ1dGVzR2xvYk1hcD17fTtlYWNoKG9wdGlvbnMuYWxsb3dlZEF0dHJpYnV0ZXMsZnVuY3Rpb24oYXR0cmlidXRlcyx0YWcpe2FsbG93ZWRBdHRyaWJ1dGVzTWFwW3RhZ109W107dmFyIGdsb2JSZWdleD1bXTthdHRyaWJ1dGVzLmZvckVhY2goZnVuY3Rpb24obmFtZSl7aWYobmFtZS5pbmRleE9mKFwiKlwiKT49MCl7Z2xvYlJlZ2V4LnB1c2gocXVvdGVSZWdleHAobmFtZSkucmVwbGFjZSgvXFxcXFxcKi9nLFwiLipcIikpfWVsc2V7YWxsb3dlZEF0dHJpYnV0ZXNNYXBbdGFnXS5wdXNoKG5hbWUpfX0pO2FsbG93ZWRBdHRyaWJ1dGVzR2xvYk1hcFt0YWddPW5ldyBSZWdFeHAoXCJeKFwiK2dsb2JSZWdleC5qb2luKFwifFwiKStcIikkXCIpfSl9dmFyIGFsbG93ZWRDbGFzc2VzTWFwPXt9O2VhY2gob3B0aW9ucy5hbGxvd2VkQ2xhc3NlcyxmdW5jdGlvbihjbGFzc2VzLHRhZyl7aWYoYWxsb3dlZEF0dHJpYnV0ZXNNYXApe2lmKCFoYXMoYWxsb3dlZEF0dHJpYnV0ZXNNYXAsdGFnKSl7YWxsb3dlZEF0dHJpYnV0ZXNNYXBbdGFnXT1bXX1hbGxvd2VkQXR0cmlidXRlc01hcFt0YWddLnB1c2goXCJjbGFzc1wiKX1hbGxvd2VkQ2xhc3Nlc01hcFt0YWddPWNsYXNzZXN9KTt2YXIgdHJhbnNmb3JtVGFnc01hcD17fTt2YXIgdHJhbnNmb3JtVGFnc0FsbDtlYWNoKG9wdGlvbnMudHJhbnNmb3JtVGFncyxmdW5jdGlvbih0cmFuc2Zvcm0sdGFnKXt2YXIgdHJhbnNGdW47aWYodHlwZW9mIHRyYW5zZm9ybT09PVwiZnVuY3Rpb25cIil7dHJhbnNGdW49dHJhbnNmb3JtfWVsc2UgaWYodHlwZW9mIHRyYW5zZm9ybT09PVwic3RyaW5nXCIpe3RyYW5zRnVuPXNhbml0aXplSHRtbC5zaW1wbGVUcmFuc2Zvcm0odHJhbnNmb3JtKX1pZih0YWc9PT1cIipcIil7dHJhbnNmb3JtVGFnc0FsbD10cmFuc0Z1bn1lbHNle3RyYW5zZm9ybVRhZ3NNYXBbdGFnXT10cmFuc0Z1bn19KTt2YXIgZGVwdGg9MDt2YXIgc3RhY2s9W107dmFyIHNraXBNYXA9e307dmFyIHRyYW5zZm9ybU1hcD17fTt2YXIgc2tpcFRleHQ9ZmFsc2U7dmFyIHNraXBUZXh0RGVwdGg9MDt2YXIgcGFyc2VyPW5ldyBodG1scGFyc2VyLlBhcnNlcih7b25vcGVudGFnOmZ1bmN0aW9uKG5hbWUsYXR0cmlicyl7aWYoc2tpcFRleHQpe3NraXBUZXh0RGVwdGgrKztyZXR1cm59dmFyIGZyYW1lPW5ldyBGcmFtZShuYW1lLGF0dHJpYnMpO3N0YWNrLnB1c2goZnJhbWUpO3ZhciBza2lwPWZhbHNlO3ZhciBoYXNUZXh0PWZyYW1lLnRleHQ/dHJ1ZTpmYWxzZTt2YXIgdHJhbnNmb3JtZWRUYWc7aWYoaGFzKHRyYW5zZm9ybVRhZ3NNYXAsbmFtZSkpe3RyYW5zZm9ybWVkVGFnPXRyYW5zZm9ybVRhZ3NNYXBbbmFtZV0obmFtZSxhdHRyaWJzKTtmcmFtZS5hdHRyaWJzPWF0dHJpYnM9dHJhbnNmb3JtZWRUYWcuYXR0cmlicztpZih0cmFuc2Zvcm1lZFRhZy50ZXh0IT09dW5kZWZpbmVkKXtmcmFtZS5pbm5lclRleHQ9dHJhbnNmb3JtZWRUYWcudGV4dH1pZihuYW1lIT09dHJhbnNmb3JtZWRUYWcudGFnTmFtZSl7ZnJhbWUubmFtZT1uYW1lPXRyYW5zZm9ybWVkVGFnLnRhZ05hbWU7dHJhbnNmb3JtTWFwW2RlcHRoXT10cmFuc2Zvcm1lZFRhZy50YWdOYW1lfX1pZih0cmFuc2Zvcm1UYWdzQWxsKXt0cmFuc2Zvcm1lZFRhZz10cmFuc2Zvcm1UYWdzQWxsKG5hbWUsYXR0cmlicyk7ZnJhbWUuYXR0cmlicz1hdHRyaWJzPXRyYW5zZm9ybWVkVGFnLmF0dHJpYnM7aWYobmFtZSE9PXRyYW5zZm9ybWVkVGFnLnRhZ05hbWUpe2ZyYW1lLm5hbWU9bmFtZT10cmFuc2Zvcm1lZFRhZy50YWdOYW1lO3RyYW5zZm9ybU1hcFtkZXB0aF09dHJhbnNmb3JtZWRUYWcudGFnTmFtZX19aWYob3B0aW9ucy5hbGxvd2VkVGFncyYmb3B0aW9ucy5hbGxvd2VkVGFncy5pbmRleE9mKG5hbWUpPT09LTEpe3NraXA9dHJ1ZTtpZihub25UZXh0VGFnc0FycmF5LmluZGV4T2YobmFtZSkhPT0tMSl7c2tpcFRleHQ9dHJ1ZTtza2lwVGV4dERlcHRoPTF9c2tpcE1hcFtkZXB0aF09dHJ1ZX1kZXB0aCsrO2lmKHNraXApe3JldHVybn1yZXN1bHQrPVwiPFwiK25hbWU7aWYoIWFsbG93ZWRBdHRyaWJ1dGVzTWFwfHxoYXMoYWxsb3dlZEF0dHJpYnV0ZXNNYXAsbmFtZSl8fGFsbG93ZWRBdHRyaWJ1dGVzTWFwW1wiKlwiXSl7ZWFjaChhdHRyaWJzLGZ1bmN0aW9uKHZhbHVlLGEpe2lmKCFhbGxvd2VkQXR0cmlidXRlc01hcHx8aGFzKGFsbG93ZWRBdHRyaWJ1dGVzTWFwLG5hbWUpJiZhbGxvd2VkQXR0cmlidXRlc01hcFtuYW1lXS5pbmRleE9mKGEpIT09LTF8fGFsbG93ZWRBdHRyaWJ1dGVzTWFwW1wiKlwiXSYmYWxsb3dlZEF0dHJpYnV0ZXNNYXBbXCIqXCJdLmluZGV4T2YoYSkhPT0tMXx8aGFzKGFsbG93ZWRBdHRyaWJ1dGVzR2xvYk1hcCxuYW1lKSYmYWxsb3dlZEF0dHJpYnV0ZXNHbG9iTWFwW25hbWVdLnRlc3QoYSl8fGFsbG93ZWRBdHRyaWJ1dGVzR2xvYk1hcFtcIipcIl0mJmFsbG93ZWRBdHRyaWJ1dGVzR2xvYk1hcFtcIipcIl0udGVzdChhKSl7aWYoYT09PVwiaHJlZlwifHxhPT09XCJzcmNcIil7aWYobmF1Z2h0eUhyZWYobmFtZSx2YWx1ZSkpe2RlbGV0ZSBmcmFtZS5hdHRyaWJzW2FdO3JldHVybn19aWYoYT09PVwiY2xhc3NcIil7dmFsdWU9ZmlsdGVyQ2xhc3Nlcyh2YWx1ZSxhbGxvd2VkQ2xhc3Nlc01hcFtuYW1lXSk7aWYoIXZhbHVlLmxlbmd0aCl7ZGVsZXRlIGZyYW1lLmF0dHJpYnNbYV07cmV0dXJufX1yZXN1bHQrPVwiIFwiK2E7aWYodmFsdWUubGVuZ3RoKXtyZXN1bHQrPSc9XCInK2VzY2FwZUh0bWwodmFsdWUpKydcIid9fWVsc2V7ZGVsZXRlIGZyYW1lLmF0dHJpYnNbYV19fSl9aWYob3B0aW9ucy5zZWxmQ2xvc2luZy5pbmRleE9mKG5hbWUpIT09LTEpe3Jlc3VsdCs9XCIgLz5cIn1lbHNle3Jlc3VsdCs9XCI+XCI7aWYoZnJhbWUuaW5uZXJUZXh0JiYhaGFzVGV4dCYmIW9wdGlvbnMudGV4dEZpbHRlcil7cmVzdWx0Kz1mcmFtZS5pbm5lclRleHR9fX0sb250ZXh0OmZ1bmN0aW9uKHRleHQpe2lmKHNraXBUZXh0KXtyZXR1cm59dmFyIGxhc3RGcmFtZT1zdGFja1tzdGFjay5sZW5ndGgtMV07dmFyIHRhZztpZihsYXN0RnJhbWUpe3RhZz1sYXN0RnJhbWUudGFnO3RleHQ9bGFzdEZyYW1lLmlubmVyVGV4dCE9PXVuZGVmaW5lZD9sYXN0RnJhbWUuaW5uZXJUZXh0OnRleHR9aWYodGFnPT09XCJzY3JpcHRcInx8dGFnPT09XCJzdHlsZVwiKXtyZXN1bHQrPXRleHR9ZWxzZXt2YXIgZXNjYXBlZD1lc2NhcGVIdG1sKHRleHQpO2lmKG9wdGlvbnMudGV4dEZpbHRlcil7cmVzdWx0Kz1vcHRpb25zLnRleHRGaWx0ZXIoZXNjYXBlZCl9ZWxzZXtyZXN1bHQrPWVzY2FwZWR9fWlmKHN0YWNrLmxlbmd0aCl7dmFyIGZyYW1lPXN0YWNrW3N0YWNrLmxlbmd0aC0xXTtmcmFtZS50ZXh0Kz10ZXh0fX0sb25jbG9zZXRhZzpmdW5jdGlvbihuYW1lKXtpZihza2lwVGV4dCl7c2tpcFRleHREZXB0aC0tO2lmKCFza2lwVGV4dERlcHRoKXtza2lwVGV4dD1mYWxzZX1lbHNle3JldHVybn19dmFyIGZyYW1lPXN0YWNrLnBvcCgpO2lmKCFmcmFtZSl7cmV0dXJufXNraXBUZXh0PWZhbHNlO2RlcHRoLS07aWYoc2tpcE1hcFtkZXB0aF0pe2RlbGV0ZSBza2lwTWFwW2RlcHRoXTtmcmFtZS51cGRhdGVQYXJlbnROb2RlVGV4dCgpO3JldHVybn1pZih0cmFuc2Zvcm1NYXBbZGVwdGhdKXtuYW1lPXRyYW5zZm9ybU1hcFtkZXB0aF07ZGVsZXRlIHRyYW5zZm9ybU1hcFtkZXB0aF19aWYob3B0aW9ucy5leGNsdXNpdmVGaWx0ZXImJm9wdGlvbnMuZXhjbHVzaXZlRmlsdGVyKGZyYW1lKSl7cmVzdWx0PXJlc3VsdC5zdWJzdHIoMCxmcmFtZS50YWdQb3NpdGlvbik7cmV0dXJufWZyYW1lLnVwZGF0ZVBhcmVudE5vZGVUZXh0KCk7aWYob3B0aW9ucy5zZWxmQ2xvc2luZy5pbmRleE9mKG5hbWUpIT09LTEpe3JldHVybn1yZXN1bHQrPVwiPC9cIituYW1lK1wiPlwifX0sb3B0aW9ucy5wYXJzZXIpO3BhcnNlci53cml0ZShodG1sKTtwYXJzZXIuZW5kKCk7cmV0dXJuIHJlc3VsdDtmdW5jdGlvbiBlc2NhcGVIdG1sKHMpe2lmKHR5cGVvZiBzIT09XCJzdHJpbmdcIil7cz1zK1wiXCJ9cmV0dXJuIHMucmVwbGFjZSgvXFwmL2csXCImYW1wO1wiKS5yZXBsYWNlKC88L2csXCImbHQ7XCIpLnJlcGxhY2UoL1xcPi9nLFwiJmd0O1wiKS5yZXBsYWNlKC9cXFwiL2csXCImcXVvdDtcIil9ZnVuY3Rpb24gbmF1Z2h0eUhyZWYobmFtZSxocmVmKXtocmVmPWhyZWYucmVwbGFjZSgvW1xceDAwLVxceDIwXSsvZyxcIlwiKTtocmVmPWhyZWYucmVwbGFjZSgvPFxcIVxcLVxcLS4qP1xcLVxcLVxcPi9nLFwiXCIpO3ZhciBtYXRjaGVzPWhyZWYubWF0Y2goL14oW2EtekEtWl0rKVxcOi8pO2lmKCFtYXRjaGVzKXtyZXR1cm4gZmFsc2V9dmFyIHNjaGVtZT1tYXRjaGVzWzFdLnRvTG93ZXJDYXNlKCk7aWYoaGFzKG9wdGlvbnMuYWxsb3dlZFNjaGVtZXNCeVRhZyxuYW1lKSl7cmV0dXJuIG9wdGlvbnMuYWxsb3dlZFNjaGVtZXNCeVRhZ1tuYW1lXS5pbmRleE9mKHNjaGVtZSk9PT0tMX1yZXR1cm4hb3B0aW9ucy5hbGxvd2VkU2NoZW1lc3x8b3B0aW9ucy5hbGxvd2VkU2NoZW1lcy5pbmRleE9mKHNjaGVtZSk9PT0tMX1mdW5jdGlvbiBmaWx0ZXJDbGFzc2VzKGNsYXNzZXMsYWxsb3dlZCl7aWYoIWFsbG93ZWQpe3JldHVybiBjbGFzc2VzfWNsYXNzZXM9Y2xhc3Nlcy5zcGxpdCgvXFxzKy8pO3JldHVybiBjbGFzc2VzLmZpbHRlcihmdW5jdGlvbihjbHNzKXtyZXR1cm4gYWxsb3dlZC5pbmRleE9mKGNsc3MpIT09LTF9KS5qb2luKFwiIFwiKX19dmFyIGh0bWxQYXJzZXJEZWZhdWx0cz17ZGVjb2RlRW50aXRpZXM6dHJ1ZX07c2FuaXRpemVIdG1sLmRlZmF1bHRzPXthbGxvd2VkVGFnczpbXCJoM1wiLFwiaDRcIixcImg1XCIsXCJoNlwiLFwiYmxvY2txdW90ZVwiLFwicFwiLFwiYVwiLFwidWxcIixcIm9sXCIsXCJubFwiLFwibGlcIixcImJcIixcImlcIixcInN0cm9uZ1wiLFwiZW1cIixcInN0cmlrZVwiLFwiY29kZVwiLFwiaHJcIixcImJyXCIsXCJkaXZcIixcInRhYmxlXCIsXCJ0aGVhZFwiLFwiY2FwdGlvblwiLFwidGJvZHlcIixcInRyXCIsXCJ0aFwiLFwidGRcIixcInByZVwiXSxhbGxvd2VkQXR0cmlidXRlczp7YTpbXCJocmVmXCIsXCJuYW1lXCIsXCJ0YXJnZXRcIl0saW1nOltcInNyY1wiXX0sc2VsZkNsb3Npbmc6W1wiaW1nXCIsXCJiclwiLFwiaHJcIixcImFyZWFcIixcImJhc2VcIixcImJhc2Vmb250XCIsXCJpbnB1dFwiLFwibGlua1wiLFwibWV0YVwiXSxhbGxvd2VkU2NoZW1lczpbXCJodHRwXCIsXCJodHRwc1wiLFwiZnRwXCIsXCJtYWlsdG9cIl0sYWxsb3dlZFNjaGVtZXNCeVRhZzp7fX07c2FuaXRpemVIdG1sLnNpbXBsZVRyYW5zZm9ybT1mdW5jdGlvbihuZXdUYWdOYW1lLG5ld0F0dHJpYnMsbWVyZ2Upe21lcmdlPW1lcmdlPT09dW5kZWZpbmVkP3RydWU6bWVyZ2U7bmV3QXR0cmlicz1uZXdBdHRyaWJzfHx7fTtyZXR1cm4gZnVuY3Rpb24odGFnTmFtZSxhdHRyaWJzKXt2YXIgYXR0cmliO2lmKG1lcmdlKXtmb3IoYXR0cmliIGluIG5ld0F0dHJpYnMpe2F0dHJpYnNbYXR0cmliXT1uZXdBdHRyaWJzW2F0dHJpYl19fWVsc2V7YXR0cmlicz1uZXdBdHRyaWJzfXJldHVybnt0YWdOYW1lOm5ld1RhZ05hbWUsYXR0cmliczphdHRyaWJzfX19fSx7aHRtbHBhcnNlcjI6MzYsXCJyZWdleHAtcXVvdGVcIjo1NCx4dGVuZDo1OH1dLDI6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe1widXNlIHN0cmljdFwiO2V4cG9ydHMudG9CeXRlQXJyYXk9dG9CeXRlQXJyYXk7ZXhwb3J0cy5mcm9tQnl0ZUFycmF5PWZyb21CeXRlQXJyYXk7dmFyIGxvb2t1cD1bXTt2YXIgcmV2TG9va3VwPVtdO3ZhciBBcnI9dHlwZW9mIFVpbnQ4QXJyYXkhPT1cInVuZGVmaW5lZFwiP1VpbnQ4QXJyYXk6QXJyYXk7ZnVuY3Rpb24gaW5pdCgpe3ZhciBjb2RlPVwiQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrL1wiO2Zvcih2YXIgaT0wLGxlbj1jb2RlLmxlbmd0aDtpPGxlbjsrK2kpe2xvb2t1cFtpXT1jb2RlW2ldO3Jldkxvb2t1cFtjb2RlLmNoYXJDb2RlQXQoaSldPWl9cmV2TG9va3VwW1wiLVwiLmNoYXJDb2RlQXQoMCldPTYyO3Jldkxvb2t1cFtcIl9cIi5jaGFyQ29kZUF0KDApXT02M31pbml0KCk7ZnVuY3Rpb24gdG9CeXRlQXJyYXkoYjY0KXt2YXIgaSxqLGwsdG1wLHBsYWNlSG9sZGVycyxhcnI7dmFyIGxlbj1iNjQubGVuZ3RoO2lmKGxlbiU0PjApe3Rocm93IG5ldyBFcnJvcihcIkludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDRcIil9cGxhY2VIb2xkZXJzPWI2NFtsZW4tMl09PT1cIj1cIj8yOmI2NFtsZW4tMV09PT1cIj1cIj8xOjA7YXJyPW5ldyBBcnIobGVuKjMvNC1wbGFjZUhvbGRlcnMpO2w9cGxhY2VIb2xkZXJzPjA/bGVuLTQ6bGVuO3ZhciBMPTA7Zm9yKGk9MCxqPTA7aTxsO2krPTQsais9Myl7dG1wPXJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV08PDE4fHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKzEpXTw8MTJ8cmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkrMildPDw2fHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKzMpXTthcnJbTCsrXT10bXA+PjE2JjI1NTthcnJbTCsrXT10bXA+PjgmMjU1O2FycltMKytdPXRtcCYyNTV9aWYocGxhY2VIb2xkZXJzPT09Mil7dG1wPXJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV08PDJ8cmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkrMSldPj40O2FycltMKytdPXRtcCYyNTV9ZWxzZSBpZihwbGFjZUhvbGRlcnM9PT0xKXt0bXA9cmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXTw8MTB8cmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkrMSldPDw0fHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKzIpXT4+MjthcnJbTCsrXT10bXA+PjgmMjU1O2FycltMKytdPXRtcCYyNTV9cmV0dXJuIGFycn1mdW5jdGlvbiB0cmlwbGV0VG9CYXNlNjQobnVtKXtyZXR1cm4gbG9va3VwW251bT4+MTgmNjNdK2xvb2t1cFtudW0+PjEyJjYzXStsb29rdXBbbnVtPj42JjYzXStsb29rdXBbbnVtJjYzXX1mdW5jdGlvbiBlbmNvZGVDaHVuayh1aW50OCxzdGFydCxlbmQpe3ZhciB0bXA7dmFyIG91dHB1dD1bXTtmb3IodmFyIGk9c3RhcnQ7aTxlbmQ7aSs9Myl7dG1wPSh1aW50OFtpXTw8MTYpKyh1aW50OFtpKzFdPDw4KSt1aW50OFtpKzJdO291dHB1dC5wdXNoKHRyaXBsZXRUb0Jhc2U2NCh0bXApKX1yZXR1cm4gb3V0cHV0LmpvaW4oXCJcIil9ZnVuY3Rpb24gZnJvbUJ5dGVBcnJheSh1aW50OCl7dmFyIHRtcDt2YXIgbGVuPXVpbnQ4Lmxlbmd0aDt2YXIgZXh0cmFCeXRlcz1sZW4lMzt2YXIgb3V0cHV0PVwiXCI7dmFyIHBhcnRzPVtdO3ZhciBtYXhDaHVua0xlbmd0aD0xNjM4Mztmb3IodmFyIGk9MCxsZW4yPWxlbi1leHRyYUJ5dGVzO2k8bGVuMjtpKz1tYXhDaHVua0xlbmd0aCl7cGFydHMucHVzaChlbmNvZGVDaHVuayh1aW50OCxpLGkrbWF4Q2h1bmtMZW5ndGg+bGVuMj9sZW4yOmkrbWF4Q2h1bmtMZW5ndGgpKX1pZihleHRyYUJ5dGVzPT09MSl7dG1wPXVpbnQ4W2xlbi0xXTtvdXRwdXQrPWxvb2t1cFt0bXA+PjJdO291dHB1dCs9bG9va3VwW3RtcDw8NCY2M107b3V0cHV0Kz1cIj09XCJ9ZWxzZSBpZihleHRyYUJ5dGVzPT09Mil7dG1wPSh1aW50OFtsZW4tMl08PDgpK3VpbnQ4W2xlbi0xXTtvdXRwdXQrPWxvb2t1cFt0bXA+PjEwXTtvdXRwdXQrPWxvb2t1cFt0bXA+PjQmNjNdO291dHB1dCs9bG9va3VwW3RtcDw8MiY2M107b3V0cHV0Kz1cIj1cIn1wYXJ0cy5wdXNoKG91dHB1dCk7cmV0dXJuIHBhcnRzLmpvaW4oXCJcIil9fSx7fV0sMzpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7fSx7fV0sNDpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7KGZ1bmN0aW9uKGdsb2JhbCl7XCJ1c2Ugc3RyaWN0XCI7dmFyIGJ1ZmZlcj1yZXF1aXJlKFwiYnVmZmVyXCIpO3ZhciBCdWZmZXI9YnVmZmVyLkJ1ZmZlcjt2YXIgU2xvd0J1ZmZlcj1idWZmZXIuU2xvd0J1ZmZlcjt2YXIgTUFYX0xFTj1idWZmZXIua01heExlbmd0aHx8MjE0NzQ4MzY0NztleHBvcnRzLmFsbG9jPWZ1bmN0aW9uIGFsbG9jKHNpemUsZmlsbCxlbmNvZGluZyl7aWYodHlwZW9mIEJ1ZmZlci5hbGxvYz09PVwiZnVuY3Rpb25cIil7cmV0dXJuIEJ1ZmZlci5hbGxvYyhzaXplLGZpbGwsZW5jb2RpbmcpfWlmKHR5cGVvZiBlbmNvZGluZz09PVwibnVtYmVyXCIpe3Rocm93IG5ldyBUeXBlRXJyb3IoXCJlbmNvZGluZyBtdXN0IG5vdCBiZSBudW1iZXJcIil9aWYodHlwZW9mIHNpemUhPT1cIm51bWJlclwiKXt0aHJvdyBuZXcgVHlwZUVycm9yKFwic2l6ZSBtdXN0IGJlIGEgbnVtYmVyXCIpfWlmKHNpemU+TUFYX0xFTil7dGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJzaXplIGlzIHRvbyBsYXJnZVwiKX12YXIgZW5jPWVuY29kaW5nO3ZhciBfZmlsbD1maWxsO2lmKF9maWxsPT09dW5kZWZpbmVkKXtlbmM9dW5kZWZpbmVkO19maWxsPTB9dmFyIGJ1Zj1uZXcgQnVmZmVyKHNpemUpO2lmKHR5cGVvZiBfZmlsbD09PVwic3RyaW5nXCIpe3ZhciBmaWxsQnVmPW5ldyBCdWZmZXIoX2ZpbGwsZW5jKTt2YXIgZmxlbj1maWxsQnVmLmxlbmd0aDt2YXIgaT0tMTt3aGlsZSgrK2k8c2l6ZSl7YnVmW2ldPWZpbGxCdWZbaSVmbGVuXX19ZWxzZXtidWYuZmlsbChfZmlsbCl9cmV0dXJuIGJ1Zn07ZXhwb3J0cy5hbGxvY1Vuc2FmZT1mdW5jdGlvbiBhbGxvY1Vuc2FmZShzaXplKXtpZih0eXBlb2YgQnVmZmVyLmFsbG9jVW5zYWZlPT09XCJmdW5jdGlvblwiKXtyZXR1cm4gQnVmZmVyLmFsbG9jVW5zYWZlKHNpemUpfWlmKHR5cGVvZiBzaXplIT09XCJudW1iZXJcIil7dGhyb3cgbmV3IFR5cGVFcnJvcihcInNpemUgbXVzdCBiZSBhIG51bWJlclwiKX1pZihzaXplPk1BWF9MRU4pe3Rocm93IG5ldyBSYW5nZUVycm9yKFwic2l6ZSBpcyB0b28gbGFyZ2VcIil9cmV0dXJuIG5ldyBCdWZmZXIoc2l6ZSl9O2V4cG9ydHMuZnJvbT1mdW5jdGlvbiBmcm9tKHZhbHVlLGVuY29kaW5nT3JPZmZzZXQsbGVuZ3RoKXtpZih0eXBlb2YgQnVmZmVyLmZyb209PT1cImZ1bmN0aW9uXCImJighZ2xvYmFsLlVpbnQ4QXJyYXl8fFVpbnQ4QXJyYXkuZnJvbSE9PUJ1ZmZlci5mcm9tKSl7cmV0dXJuIEJ1ZmZlci5mcm9tKHZhbHVlLGVuY29kaW5nT3JPZmZzZXQsbGVuZ3RoKX1pZih0eXBlb2YgdmFsdWU9PT1cIm51bWJlclwiKXt0aHJvdyBuZXcgVHlwZUVycm9yKCdcInZhbHVlXCIgYXJndW1lbnQgbXVzdCBub3QgYmUgYSBudW1iZXInKX1pZih0eXBlb2YgdmFsdWU9PT1cInN0cmluZ1wiKXtyZXR1cm4gbmV3IEJ1ZmZlcih2YWx1ZSxlbmNvZGluZ09yT2Zmc2V0KX1pZih0eXBlb2YgQXJyYXlCdWZmZXIhPT1cInVuZGVmaW5lZFwiJiZ2YWx1ZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKXt2YXIgb2Zmc2V0PWVuY29kaW5nT3JPZmZzZXQ7aWYoYXJndW1lbnRzLmxlbmd0aD09PTEpe3JldHVybiBuZXcgQnVmZmVyKHZhbHVlKX1pZih0eXBlb2Ygb2Zmc2V0PT09XCJ1bmRlZmluZWRcIil7b2Zmc2V0PTB9dmFyIGxlbj1sZW5ndGg7aWYodHlwZW9mIGxlbj09PVwidW5kZWZpbmVkXCIpe2xlbj12YWx1ZS5ieXRlTGVuZ3RoLW9mZnNldH1pZihvZmZzZXQ+PXZhbHVlLmJ5dGVMZW5ndGgpe3Rocm93IG5ldyBSYW5nZUVycm9yKFwiJ29mZnNldCcgaXMgb3V0IG9mIGJvdW5kc1wiKX1pZihsZW4+dmFsdWUuYnl0ZUxlbmd0aC1vZmZzZXQpe3Rocm93IG5ldyBSYW5nZUVycm9yKFwiJ2xlbmd0aCcgaXMgb3V0IG9mIGJvdW5kc1wiKX1yZXR1cm4gbmV3IEJ1ZmZlcih2YWx1ZS5zbGljZShvZmZzZXQsb2Zmc2V0K2xlbikpfWlmKEJ1ZmZlci5pc0J1ZmZlcih2YWx1ZSkpe3ZhciBvdXQ9bmV3IEJ1ZmZlcih2YWx1ZS5sZW5ndGgpO3ZhbHVlLmNvcHkob3V0LDAsMCx2YWx1ZS5sZW5ndGgpO3JldHVybiBvdXR9aWYodmFsdWUpe2lmKEFycmF5LmlzQXJyYXkodmFsdWUpfHx0eXBlb2YgQXJyYXlCdWZmZXIhPT1cInVuZGVmaW5lZFwiJiZ2YWx1ZS5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcnx8XCJsZW5ndGhcImluIHZhbHVlKXtyZXR1cm4gbmV3IEJ1ZmZlcih2YWx1ZSl9aWYodmFsdWUudHlwZT09PVwiQnVmZmVyXCImJkFycmF5LmlzQXJyYXkodmFsdWUuZGF0YSkpe3JldHVybiBuZXcgQnVmZmVyKHZhbHVlLmRhdGEpfX10aHJvdyBuZXcgVHlwZUVycm9yKFwiRmlyc3QgYXJndW1lbnQgbXVzdCBiZSBhIHN0cmluZywgQnVmZmVyLCBcIitcIkFycmF5QnVmZmVyLCBBcnJheSwgb3IgYXJyYXktbGlrZSBvYmplY3QuXCIpfTtleHBvcnRzLmFsbG9jVW5zYWZlU2xvdz1mdW5jdGlvbiBhbGxvY1Vuc2FmZVNsb3coc2l6ZSl7aWYodHlwZW9mIEJ1ZmZlci5hbGxvY1Vuc2FmZVNsb3c9PT1cImZ1bmN0aW9uXCIpe3JldHVybiBCdWZmZXIuYWxsb2NVbnNhZmVTbG93KHNpemUpfWlmKHR5cGVvZiBzaXplIT09XCJudW1iZXJcIil7dGhyb3cgbmV3IFR5cGVFcnJvcihcInNpemUgbXVzdCBiZSBhIG51bWJlclwiKX1pZihzaXplPj1NQVhfTEVOKXt0aHJvdyBuZXcgUmFuZ2VFcnJvcihcInNpemUgaXMgdG9vIGxhcmdlXCIpfXJldHVybiBuZXcgU2xvd0J1ZmZlcihzaXplKX19KS5jYWxsKHRoaXMsdHlwZW9mIGdsb2JhbCE9PVwidW5kZWZpbmVkXCI/Z2xvYmFsOnR5cGVvZiBzZWxmIT09XCJ1bmRlZmluZWRcIj9zZWxmOnR5cGVvZiB3aW5kb3chPT1cInVuZGVmaW5lZFwiP3dpbmRvdzp7fSl9LHtidWZmZXI6NX1dLDU6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpeyhmdW5jdGlvbihnbG9iYWwpe1widXNlIHN0cmljdFwiO3ZhciBiYXNlNjQ9cmVxdWlyZShcImJhc2U2NC1qc1wiKTt2YXIgaWVlZTc1ND1yZXF1aXJlKFwiaWVlZTc1NFwiKTt2YXIgaXNBcnJheT1yZXF1aXJlKFwiaXNhcnJheVwiKTtleHBvcnRzLkJ1ZmZlcj1CdWZmZXI7ZXhwb3J0cy5TbG93QnVmZmVyPVNsb3dCdWZmZXI7ZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFUz01MDtCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVD1nbG9iYWwuVFlQRURfQVJSQVlfU1VQUE9SVCE9PXVuZGVmaW5lZD9nbG9iYWwuVFlQRURfQVJSQVlfU1VQUE9SVDp0eXBlZEFycmF5U3VwcG9ydCgpO2V4cG9ydHMua01heExlbmd0aD1rTWF4TGVuZ3RoKCk7ZnVuY3Rpb24gdHlwZWRBcnJheVN1cHBvcnQoKXt0cnl7dmFyIGFycj1uZXcgVWludDhBcnJheSgxKTthcnIuX19wcm90b19fPXtfX3Byb3RvX186VWludDhBcnJheS5wcm90b3R5cGUsZm9vOmZ1bmN0aW9uKCl7cmV0dXJuIDQyfX07cmV0dXJuIGFyci5mb28oKT09PTQyJiZ0eXBlb2YgYXJyLnN1YmFycmF5PT09XCJmdW5jdGlvblwiJiZhcnIuc3ViYXJyYXkoMSwxKS5ieXRlTGVuZ3RoPT09MH1jYXRjaChlKXtyZXR1cm4gZmFsc2V9fWZ1bmN0aW9uIGtNYXhMZW5ndGgoKXtyZXR1cm4gQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQ/MjE0NzQ4MzY0NzoxMDczNzQxODIzfWZ1bmN0aW9uIGNyZWF0ZUJ1ZmZlcih0aGF0LGxlbmd0aCl7aWYoa01heExlbmd0aCgpPGxlbmd0aCl7dGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJJbnZhbGlkIHR5cGVkIGFycmF5IGxlbmd0aFwiKX1pZihCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCl7dGhhdD1uZXcgVWludDhBcnJheShsZW5ndGgpO3RoYXQuX19wcm90b19fPUJ1ZmZlci5wcm90b3R5cGV9ZWxzZXtpZih0aGF0PT09bnVsbCl7dGhhdD1uZXcgQnVmZmVyKGxlbmd0aCl9dGhhdC5sZW5ndGg9bGVuZ3RofXJldHVybiB0aGF0fWZ1bmN0aW9uIEJ1ZmZlcihhcmcsZW5jb2RpbmdPck9mZnNldCxsZW5ndGgpe2lmKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCYmISh0aGlzIGluc3RhbmNlb2YgQnVmZmVyKSl7cmV0dXJuIG5ldyBCdWZmZXIoYXJnLGVuY29kaW5nT3JPZmZzZXQsbGVuZ3RoKX1pZih0eXBlb2YgYXJnPT09XCJudW1iZXJcIil7aWYodHlwZW9mIGVuY29kaW5nT3JPZmZzZXQ9PT1cInN0cmluZ1wiKXt0aHJvdyBuZXcgRXJyb3IoXCJJZiBlbmNvZGluZyBpcyBzcGVjaWZpZWQgdGhlbiB0aGUgZmlyc3QgYXJndW1lbnQgbXVzdCBiZSBhIHN0cmluZ1wiKX1yZXR1cm4gYWxsb2NVbnNhZmUodGhpcyxhcmcpfXJldHVybiBmcm9tKHRoaXMsYXJnLGVuY29kaW5nT3JPZmZzZXQsbGVuZ3RoKX1CdWZmZXIucG9vbFNpemU9ODE5MjtCdWZmZXIuX2F1Z21lbnQ9ZnVuY3Rpb24oYXJyKXthcnIuX19wcm90b19fPUJ1ZmZlci5wcm90b3R5cGU7cmV0dXJuIGFycn07ZnVuY3Rpb24gZnJvbSh0aGF0LHZhbHVlLGVuY29kaW5nT3JPZmZzZXQsbGVuZ3RoKXtpZih0eXBlb2YgdmFsdWU9PT1cIm51bWJlclwiKXt0aHJvdyBuZXcgVHlwZUVycm9yKCdcInZhbHVlXCIgYXJndW1lbnQgbXVzdCBub3QgYmUgYSBudW1iZXInKX1pZih0eXBlb2YgQXJyYXlCdWZmZXIhPT1cInVuZGVmaW5lZFwiJiZ2YWx1ZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKXtyZXR1cm4gZnJvbUFycmF5QnVmZmVyKHRoYXQsdmFsdWUsZW5jb2RpbmdPck9mZnNldCxsZW5ndGgpfWlmKHR5cGVvZiB2YWx1ZT09PVwic3RyaW5nXCIpe3JldHVybiBmcm9tU3RyaW5nKHRoYXQsdmFsdWUsZW5jb2RpbmdPck9mZnNldCl9cmV0dXJuIGZyb21PYmplY3QodGhhdCx2YWx1ZSl9QnVmZmVyLmZyb209ZnVuY3Rpb24odmFsdWUsZW5jb2RpbmdPck9mZnNldCxsZW5ndGgpe3JldHVybiBmcm9tKG51bGwsdmFsdWUsZW5jb2RpbmdPck9mZnNldCxsZW5ndGgpfTtpZihCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCl7QnVmZmVyLnByb3RvdHlwZS5fX3Byb3RvX189VWludDhBcnJheS5wcm90b3R5cGU7QnVmZmVyLl9fcHJvdG9fXz1VaW50OEFycmF5O2lmKHR5cGVvZiBTeW1ib2whPT1cInVuZGVmaW5lZFwiJiZTeW1ib2wuc3BlY2llcyYmQnVmZmVyW1N5bWJvbC5zcGVjaWVzXT09PUJ1ZmZlcil7T2JqZWN0LmRlZmluZVByb3BlcnR5KEJ1ZmZlcixTeW1ib2wuc3BlY2llcyx7dmFsdWU6bnVsbCxjb25maWd1cmFibGU6dHJ1ZX0pfX1mdW5jdGlvbiBhc3NlcnRTaXplKHNpemUpe2lmKHR5cGVvZiBzaXplIT09XCJudW1iZXJcIil7dGhyb3cgbmV3IFR5cGVFcnJvcignXCJzaXplXCIgYXJndW1lbnQgbXVzdCBiZSBhIG51bWJlcicpfWVsc2UgaWYoc2l6ZTwwKXt0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJzaXplXCIgYXJndW1lbnQgbXVzdCBub3QgYmUgbmVnYXRpdmUnKX19ZnVuY3Rpb24gYWxsb2ModGhhdCxzaXplLGZpbGwsZW5jb2Rpbmcpe2Fzc2VydFNpemUoc2l6ZSk7aWYoc2l6ZTw9MCl7cmV0dXJuIGNyZWF0ZUJ1ZmZlcih0aGF0LHNpemUpfWlmKGZpbGwhPT11bmRlZmluZWQpe3JldHVybiB0eXBlb2YgZW5jb2Rpbmc9PT1cInN0cmluZ1wiP2NyZWF0ZUJ1ZmZlcih0aGF0LHNpemUpLmZpbGwoZmlsbCxlbmNvZGluZyk6Y3JlYXRlQnVmZmVyKHRoYXQsc2l6ZSkuZmlsbChmaWxsKX1yZXR1cm4gY3JlYXRlQnVmZmVyKHRoYXQsc2l6ZSl9QnVmZmVyLmFsbG9jPWZ1bmN0aW9uKHNpemUsZmlsbCxlbmNvZGluZyl7cmV0dXJuIGFsbG9jKG51bGwsc2l6ZSxmaWxsLGVuY29kaW5nKX07ZnVuY3Rpb24gYWxsb2NVbnNhZmUodGhhdCxzaXplKXthc3NlcnRTaXplKHNpemUpO3RoYXQ9Y3JlYXRlQnVmZmVyKHRoYXQsc2l6ZTwwPzA6Y2hlY2tlZChzaXplKXwwKTtpZighQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpe2Zvcih2YXIgaT0wO2k8c2l6ZTsrK2kpe3RoYXRbaV09MH19cmV0dXJuIHRoYXR9QnVmZmVyLmFsbG9jVW5zYWZlPWZ1bmN0aW9uKHNpemUpe3JldHVybiBhbGxvY1Vuc2FmZShudWxsLHNpemUpfTtCdWZmZXIuYWxsb2NVbnNhZmVTbG93PWZ1bmN0aW9uKHNpemUpe3JldHVybiBhbGxvY1Vuc2FmZShudWxsLHNpemUpfTtmdW5jdGlvbiBmcm9tU3RyaW5nKHRoYXQsc3RyaW5nLGVuY29kaW5nKXtpZih0eXBlb2YgZW5jb2RpbmchPT1cInN0cmluZ1wifHxlbmNvZGluZz09PVwiXCIpe2VuY29kaW5nPVwidXRmOFwifWlmKCFCdWZmZXIuaXNFbmNvZGluZyhlbmNvZGluZykpe3Rocm93IG5ldyBUeXBlRXJyb3IoJ1wiZW5jb2RpbmdcIiBtdXN0IGJlIGEgdmFsaWQgc3RyaW5nIGVuY29kaW5nJyl9dmFyIGxlbmd0aD1ieXRlTGVuZ3RoKHN0cmluZyxlbmNvZGluZyl8MDt0aGF0PWNyZWF0ZUJ1ZmZlcih0aGF0LGxlbmd0aCk7dmFyIGFjdHVhbD10aGF0LndyaXRlKHN0cmluZyxlbmNvZGluZyk7aWYoYWN0dWFsIT09bGVuZ3RoKXt0aGF0PXRoYXQuc2xpY2UoMCxhY3R1YWwpfXJldHVybiB0aGF0fWZ1bmN0aW9uIGZyb21BcnJheUxpa2UodGhhdCxhcnJheSl7dmFyIGxlbmd0aD1hcnJheS5sZW5ndGg8MD8wOmNoZWNrZWQoYXJyYXkubGVuZ3RoKXwwO3RoYXQ9Y3JlYXRlQnVmZmVyKHRoYXQsbGVuZ3RoKTtmb3IodmFyIGk9MDtpPGxlbmd0aDtpKz0xKXt0aGF0W2ldPWFycmF5W2ldJjI1NX1yZXR1cm4gdGhhdH1mdW5jdGlvbiBmcm9tQXJyYXlCdWZmZXIodGhhdCxhcnJheSxieXRlT2Zmc2V0LGxlbmd0aCl7YXJyYXkuYnl0ZUxlbmd0aDtpZihieXRlT2Zmc2V0PDB8fGFycmF5LmJ5dGVMZW5ndGg8Ynl0ZU9mZnNldCl7dGhyb3cgbmV3IFJhbmdlRXJyb3IoXCInb2Zmc2V0JyBpcyBvdXQgb2YgYm91bmRzXCIpfWlmKGFycmF5LmJ5dGVMZW5ndGg8Ynl0ZU9mZnNldCsobGVuZ3RofHwwKSl7dGhyb3cgbmV3IFJhbmdlRXJyb3IoXCInbGVuZ3RoJyBpcyBvdXQgb2YgYm91bmRzXCIpfWlmKGJ5dGVPZmZzZXQ9PT11bmRlZmluZWQmJmxlbmd0aD09PXVuZGVmaW5lZCl7YXJyYXk9bmV3IFVpbnQ4QXJyYXkoYXJyYXkpfWVsc2UgaWYobGVuZ3RoPT09dW5kZWZpbmVkKXthcnJheT1uZXcgVWludDhBcnJheShhcnJheSxieXRlT2Zmc2V0KX1lbHNle2FycmF5PW5ldyBVaW50OEFycmF5KGFycmF5LGJ5dGVPZmZzZXQsbGVuZ3RoKX1pZihCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCl7dGhhdD1hcnJheTt0aGF0Ll9fcHJvdG9fXz1CdWZmZXIucHJvdG90eXBlfWVsc2V7dGhhdD1mcm9tQXJyYXlMaWtlKHRoYXQsYXJyYXkpfXJldHVybiB0aGF0fWZ1bmN0aW9uIGZyb21PYmplY3QodGhhdCxvYmope2lmKEJ1ZmZlci5pc0J1ZmZlcihvYmopKXt2YXIgbGVuPWNoZWNrZWQob2JqLmxlbmd0aCl8MDt0aGF0PWNyZWF0ZUJ1ZmZlcih0aGF0LGxlbik7aWYodGhhdC5sZW5ndGg9PT0wKXtyZXR1cm4gdGhhdH1vYmouY29weSh0aGF0LDAsMCxsZW4pO3JldHVybiB0aGF0fWlmKG9iail7aWYodHlwZW9mIEFycmF5QnVmZmVyIT09XCJ1bmRlZmluZWRcIiYmb2JqLmJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyfHxcImxlbmd0aFwiaW4gb2JqKXtpZih0eXBlb2Ygb2JqLmxlbmd0aCE9PVwibnVtYmVyXCJ8fGlzbmFuKG9iai5sZW5ndGgpKXtyZXR1cm4gY3JlYXRlQnVmZmVyKHRoYXQsMCl9cmV0dXJuIGZyb21BcnJheUxpa2UodGhhdCxvYmopfWlmKG9iai50eXBlPT09XCJCdWZmZXJcIiYmaXNBcnJheShvYmouZGF0YSkpe3JldHVybiBmcm9tQXJyYXlMaWtlKHRoYXQsb2JqLmRhdGEpfX10aHJvdyBuZXcgVHlwZUVycm9yKFwiRmlyc3QgYXJndW1lbnQgbXVzdCBiZSBhIHN0cmluZywgQnVmZmVyLCBBcnJheUJ1ZmZlciwgQXJyYXksIG9yIGFycmF5LWxpa2Ugb2JqZWN0LlwiKX1mdW5jdGlvbiBjaGVja2VkKGxlbmd0aCl7aWYobGVuZ3RoPj1rTWF4TGVuZ3RoKCkpe3Rocm93IG5ldyBSYW5nZUVycm9yKFwiQXR0ZW1wdCB0byBhbGxvY2F0ZSBCdWZmZXIgbGFyZ2VyIHRoYW4gbWF4aW11bSBcIitcInNpemU6IDB4XCIra01heExlbmd0aCgpLnRvU3RyaW5nKDE2KStcIiBieXRlc1wiKX1yZXR1cm4gbGVuZ3RofDB9ZnVuY3Rpb24gU2xvd0J1ZmZlcihsZW5ndGgpe2lmKCtsZW5ndGghPWxlbmd0aCl7bGVuZ3RoPTB9cmV0dXJuIEJ1ZmZlci5hbGxvYygrbGVuZ3RoKX1CdWZmZXIuaXNCdWZmZXI9ZnVuY3Rpb24gaXNCdWZmZXIoYil7cmV0dXJuISEoYiE9bnVsbCYmYi5faXNCdWZmZXIpfTtCdWZmZXIuY29tcGFyZT1mdW5jdGlvbiBjb21wYXJlKGEsYil7aWYoIUJ1ZmZlci5pc0J1ZmZlcihhKXx8IUJ1ZmZlci5pc0J1ZmZlcihiKSl7dGhyb3cgbmV3IFR5cGVFcnJvcihcIkFyZ3VtZW50cyBtdXN0IGJlIEJ1ZmZlcnNcIil9aWYoYT09PWIpcmV0dXJuIDA7dmFyIHg9YS5sZW5ndGg7dmFyIHk9Yi5sZW5ndGg7Zm9yKHZhciBpPTAsbGVuPU1hdGgubWluKHgseSk7aTxsZW47KytpKXtpZihhW2ldIT09YltpXSl7eD1hW2ldO3k9YltpXTticmVha319aWYoeDx5KXJldHVybi0xO2lmKHk8eClyZXR1cm4gMTtyZXR1cm4gMH07QnVmZmVyLmlzRW5jb2Rpbmc9ZnVuY3Rpb24gaXNFbmNvZGluZyhlbmNvZGluZyl7c3dpdGNoKFN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKSl7Y2FzZVwiaGV4XCI6Y2FzZVwidXRmOFwiOmNhc2VcInV0Zi04XCI6Y2FzZVwiYXNjaWlcIjpjYXNlXCJsYXRpbjFcIjpjYXNlXCJiaW5hcnlcIjpjYXNlXCJiYXNlNjRcIjpjYXNlXCJ1Y3MyXCI6Y2FzZVwidWNzLTJcIjpjYXNlXCJ1dGYxNmxlXCI6Y2FzZVwidXRmLTE2bGVcIjpyZXR1cm4gdHJ1ZTtkZWZhdWx0OnJldHVybiBmYWxzZX19O0J1ZmZlci5jb25jYXQ9ZnVuY3Rpb24gY29uY2F0KGxpc3QsbGVuZ3RoKXtpZighaXNBcnJheShsaXN0KSl7dGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0XCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJyl9aWYobGlzdC5sZW5ndGg9PT0wKXtyZXR1cm4gQnVmZmVyLmFsbG9jKDApfXZhciBpO2lmKGxlbmd0aD09PXVuZGVmaW5lZCl7bGVuZ3RoPTA7Zm9yKGk9MDtpPGxpc3QubGVuZ3RoOysraSl7bGVuZ3RoKz1saXN0W2ldLmxlbmd0aH19dmFyIGJ1ZmZlcj1CdWZmZXIuYWxsb2NVbnNhZmUobGVuZ3RoKTt2YXIgcG9zPTA7Zm9yKGk9MDtpPGxpc3QubGVuZ3RoOysraSl7dmFyIGJ1Zj1saXN0W2ldO2lmKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSl7dGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0XCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJyl9YnVmLmNvcHkoYnVmZmVyLHBvcyk7cG9zKz1idWYubGVuZ3RofXJldHVybiBidWZmZXJ9O2Z1bmN0aW9uIGJ5dGVMZW5ndGgoc3RyaW5nLGVuY29kaW5nKXtpZihCdWZmZXIuaXNCdWZmZXIoc3RyaW5nKSl7cmV0dXJuIHN0cmluZy5sZW5ndGh9aWYodHlwZW9mIEFycmF5QnVmZmVyIT09XCJ1bmRlZmluZWRcIiYmdHlwZW9mIEFycmF5QnVmZmVyLmlzVmlldz09PVwiZnVuY3Rpb25cIiYmKEFycmF5QnVmZmVyLmlzVmlldyhzdHJpbmcpfHxzdHJpbmcgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikpe3JldHVybiBzdHJpbmcuYnl0ZUxlbmd0aH1pZih0eXBlb2Ygc3RyaW5nIT09XCJzdHJpbmdcIil7c3RyaW5nPVwiXCIrc3RyaW5nfXZhciBsZW49c3RyaW5nLmxlbmd0aDtpZihsZW49PT0wKXJldHVybiAwO3ZhciBsb3dlcmVkQ2FzZT1mYWxzZTtmb3IoOzspe3N3aXRjaChlbmNvZGluZyl7Y2FzZVwiYXNjaWlcIjpjYXNlXCJsYXRpbjFcIjpjYXNlXCJiaW5hcnlcIjpyZXR1cm4gbGVuO2Nhc2VcInV0ZjhcIjpjYXNlXCJ1dGYtOFwiOmNhc2UgdW5kZWZpbmVkOnJldHVybiB1dGY4VG9CeXRlcyhzdHJpbmcpLmxlbmd0aDtjYXNlXCJ1Y3MyXCI6Y2FzZVwidWNzLTJcIjpjYXNlXCJ1dGYxNmxlXCI6Y2FzZVwidXRmLTE2bGVcIjpyZXR1cm4gbGVuKjI7Y2FzZVwiaGV4XCI6cmV0dXJuIGxlbj4+PjE7Y2FzZVwiYmFzZTY0XCI6cmV0dXJuIGJhc2U2NFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGg7ZGVmYXVsdDppZihsb3dlcmVkQ2FzZSlyZXR1cm4gdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGg7ZW5jb2Rpbmc9KFwiXCIrZW5jb2RpbmcpLnRvTG93ZXJDYXNlKCk7bG93ZXJlZENhc2U9dHJ1ZX19fUJ1ZmZlci5ieXRlTGVuZ3RoPWJ5dGVMZW5ndGg7ZnVuY3Rpb24gc2xvd1RvU3RyaW5nKGVuY29kaW5nLHN0YXJ0LGVuZCl7dmFyIGxvd2VyZWRDYXNlPWZhbHNlO2lmKHN0YXJ0PT09dW5kZWZpbmVkfHxzdGFydDwwKXtzdGFydD0wfWlmKHN0YXJ0PnRoaXMubGVuZ3RoKXtyZXR1cm5cIlwifWlmKGVuZD09PXVuZGVmaW5lZHx8ZW5kPnRoaXMubGVuZ3RoKXtlbmQ9dGhpcy5sZW5ndGh9aWYoZW5kPD0wKXtyZXR1cm5cIlwifWVuZD4+Pj0wO3N0YXJ0Pj4+PTA7aWYoZW5kPD1zdGFydCl7cmV0dXJuXCJcIn1pZighZW5jb2RpbmcpZW5jb2Rpbmc9XCJ1dGY4XCI7d2hpbGUodHJ1ZSl7c3dpdGNoKGVuY29kaW5nKXtjYXNlXCJoZXhcIjpyZXR1cm4gaGV4U2xpY2UodGhpcyxzdGFydCxlbmQpO2Nhc2VcInV0ZjhcIjpjYXNlXCJ1dGYtOFwiOnJldHVybiB1dGY4U2xpY2UodGhpcyxzdGFydCxlbmQpO2Nhc2VcImFzY2lpXCI6cmV0dXJuIGFzY2lpU2xpY2UodGhpcyxzdGFydCxlbmQpO2Nhc2VcImxhdGluMVwiOmNhc2VcImJpbmFyeVwiOnJldHVybiBsYXRpbjFTbGljZSh0aGlzLHN0YXJ0LGVuZCk7Y2FzZVwiYmFzZTY0XCI6cmV0dXJuIGJhc2U2NFNsaWNlKHRoaXMsc3RhcnQsZW5kKTtjYXNlXCJ1Y3MyXCI6Y2FzZVwidWNzLTJcIjpjYXNlXCJ1dGYxNmxlXCI6Y2FzZVwidXRmLTE2bGVcIjpyZXR1cm4gdXRmMTZsZVNsaWNlKHRoaXMsc3RhcnQsZW5kKTtkZWZhdWx0OmlmKGxvd2VyZWRDYXNlKXRocm93IG5ldyBUeXBlRXJyb3IoXCJVbmtub3duIGVuY29kaW5nOiBcIitlbmNvZGluZyk7ZW5jb2Rpbmc9KGVuY29kaW5nK1wiXCIpLnRvTG93ZXJDYXNlKCk7bG93ZXJlZENhc2U9dHJ1ZX19fUJ1ZmZlci5wcm90b3R5cGUuX2lzQnVmZmVyPXRydWU7ZnVuY3Rpb24gc3dhcChiLG4sbSl7dmFyIGk9YltuXTtiW25dPWJbbV07YlttXT1pfUJ1ZmZlci5wcm90b3R5cGUuc3dhcDE2PWZ1bmN0aW9uIHN3YXAxNigpe3ZhciBsZW49dGhpcy5sZW5ndGg7aWYobGVuJTIhPT0wKXt0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIkJ1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAxNi1iaXRzXCIpfWZvcih2YXIgaT0wO2k8bGVuO2krPTIpe3N3YXAodGhpcyxpLGkrMSl9cmV0dXJuIHRoaXN9O0J1ZmZlci5wcm90b3R5cGUuc3dhcDMyPWZ1bmN0aW9uIHN3YXAzMigpe3ZhciBsZW49dGhpcy5sZW5ndGg7aWYobGVuJTQhPT0wKXt0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIkJ1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAzMi1iaXRzXCIpfWZvcih2YXIgaT0wO2k8bGVuO2krPTQpe3N3YXAodGhpcyxpLGkrMyk7c3dhcCh0aGlzLGkrMSxpKzIpfXJldHVybiB0aGlzfTtCdWZmZXIucHJvdG90eXBlLnN3YXA2ND1mdW5jdGlvbiBzd2FwNjQoKXt2YXIgbGVuPXRoaXMubGVuZ3RoO2lmKGxlbiU4IT09MCl7dGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNjQtYml0c1wiKX1mb3IodmFyIGk9MDtpPGxlbjtpKz04KXtzd2FwKHRoaXMsaSxpKzcpO3N3YXAodGhpcyxpKzEsaSs2KTtzd2FwKHRoaXMsaSsyLGkrNSk7c3dhcCh0aGlzLGkrMyxpKzQpfXJldHVybiB0aGlzfTtCdWZmZXIucHJvdG90eXBlLnRvU3RyaW5nPWZ1bmN0aW9uIHRvU3RyaW5nKCl7dmFyIGxlbmd0aD10aGlzLmxlbmd0aHwwO2lmKGxlbmd0aD09PTApcmV0dXJuXCJcIjtpZihhcmd1bWVudHMubGVuZ3RoPT09MClyZXR1cm4gdXRmOFNsaWNlKHRoaXMsMCxsZW5ndGgpO3JldHVybiBzbG93VG9TdHJpbmcuYXBwbHkodGhpcyxhcmd1bWVudHMpfTtCdWZmZXIucHJvdG90eXBlLmVxdWFscz1mdW5jdGlvbiBlcXVhbHMoYil7aWYoIUJ1ZmZlci5pc0J1ZmZlcihiKSl0aHJvdyBuZXcgVHlwZUVycm9yKFwiQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlclwiKTtpZih0aGlzPT09YilyZXR1cm4gdHJ1ZTtyZXR1cm4gQnVmZmVyLmNvbXBhcmUodGhpcyxiKT09PTB9O0J1ZmZlci5wcm90b3R5cGUuaW5zcGVjdD1mdW5jdGlvbiBpbnNwZWN0KCl7dmFyIHN0cj1cIlwiO3ZhciBtYXg9ZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFUztpZih0aGlzLmxlbmd0aD4wKXtzdHI9dGhpcy50b1N0cmluZyhcImhleFwiLDAsbWF4KS5tYXRjaCgvLnsyfS9nKS5qb2luKFwiIFwiKTtpZih0aGlzLmxlbmd0aD5tYXgpc3RyKz1cIiAuLi4gXCJ9cmV0dXJuXCI8QnVmZmVyIFwiK3N0citcIj5cIn07QnVmZmVyLnByb3RvdHlwZS5jb21wYXJlPWZ1bmN0aW9uIGNvbXBhcmUodGFyZ2V0LHN0YXJ0LGVuZCx0aGlzU3RhcnQsdGhpc0VuZCl7aWYoIUJ1ZmZlci5pc0J1ZmZlcih0YXJnZXQpKXt0aHJvdyBuZXcgVHlwZUVycm9yKFwiQXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlclwiKX1pZihzdGFydD09PXVuZGVmaW5lZCl7c3RhcnQ9MH1pZihlbmQ9PT11bmRlZmluZWQpe2VuZD10YXJnZXQ/dGFyZ2V0Lmxlbmd0aDowfWlmKHRoaXNTdGFydD09PXVuZGVmaW5lZCl7dGhpc1N0YXJ0PTB9aWYodGhpc0VuZD09PXVuZGVmaW5lZCl7dGhpc0VuZD10aGlzLmxlbmd0aH1pZihzdGFydDwwfHxlbmQ+dGFyZ2V0Lmxlbmd0aHx8dGhpc1N0YXJ0PDB8fHRoaXNFbmQ+dGhpcy5sZW5ndGgpe3Rocm93IG5ldyBSYW5nZUVycm9yKFwib3V0IG9mIHJhbmdlIGluZGV4XCIpfWlmKHRoaXNTdGFydD49dGhpc0VuZCYmc3RhcnQ+PWVuZCl7cmV0dXJuIDB9aWYodGhpc1N0YXJ0Pj10aGlzRW5kKXtyZXR1cm4tMX1pZihzdGFydD49ZW5kKXtyZXR1cm4gMX1zdGFydD4+Pj0wO2VuZD4+Pj0wO3RoaXNTdGFydD4+Pj0wO3RoaXNFbmQ+Pj49MDtpZih0aGlzPT09dGFyZ2V0KXJldHVybiAwO3ZhciB4PXRoaXNFbmQtdGhpc1N0YXJ0O3ZhciB5PWVuZC1zdGFydDt2YXIgbGVuPU1hdGgubWluKHgseSk7dmFyIHRoaXNDb3B5PXRoaXMuc2xpY2UodGhpc1N0YXJ0LHRoaXNFbmQpO3ZhciB0YXJnZXRDb3B5PXRhcmdldC5zbGljZShzdGFydCxlbmQpO2Zvcih2YXIgaT0wO2k8bGVuOysraSl7aWYodGhpc0NvcHlbaV0hPT10YXJnZXRDb3B5W2ldKXt4PXRoaXNDb3B5W2ldO3k9dGFyZ2V0Q29weVtpXTticmVha319aWYoeDx5KXJldHVybi0xO2lmKHk8eClyZXR1cm4gMTtyZXR1cm4gMH07ZnVuY3Rpb24gYmlkaXJlY3Rpb25hbEluZGV4T2YoYnVmZmVyLHZhbCxieXRlT2Zmc2V0LGVuY29kaW5nLGRpcil7aWYoYnVmZmVyLmxlbmd0aD09PTApcmV0dXJuLTE7aWYodHlwZW9mIGJ5dGVPZmZzZXQ9PT1cInN0cmluZ1wiKXtlbmNvZGluZz1ieXRlT2Zmc2V0O2J5dGVPZmZzZXQ9MH1lbHNlIGlmKGJ5dGVPZmZzZXQ+MjE0NzQ4MzY0Nyl7Ynl0ZU9mZnNldD0yMTQ3NDgzNjQ3fWVsc2UgaWYoYnl0ZU9mZnNldDwtMjE0NzQ4MzY0OCl7Ynl0ZU9mZnNldD0tMjE0NzQ4MzY0OH1ieXRlT2Zmc2V0PStieXRlT2Zmc2V0O2lmKGlzTmFOKGJ5dGVPZmZzZXQpKXtieXRlT2Zmc2V0PWRpcj8wOmJ1ZmZlci5sZW5ndGgtMX1pZihieXRlT2Zmc2V0PDApYnl0ZU9mZnNldD1idWZmZXIubGVuZ3RoK2J5dGVPZmZzZXQ7aWYoYnl0ZU9mZnNldD49YnVmZmVyLmxlbmd0aCl7aWYoZGlyKXJldHVybi0xO2Vsc2UgYnl0ZU9mZnNldD1idWZmZXIubGVuZ3RoLTF9ZWxzZSBpZihieXRlT2Zmc2V0PDApe2lmKGRpcilieXRlT2Zmc2V0PTA7ZWxzZSByZXR1cm4tMX1pZih0eXBlb2YgdmFsPT09XCJzdHJpbmdcIil7dmFsPUJ1ZmZlci5mcm9tKHZhbCxlbmNvZGluZyl9aWYoQnVmZmVyLmlzQnVmZmVyKHZhbCkpe2lmKHZhbC5sZW5ndGg9PT0wKXtyZXR1cm4tMX1yZXR1cm4gYXJyYXlJbmRleE9mKGJ1ZmZlcix2YWwsYnl0ZU9mZnNldCxlbmNvZGluZyxkaXIpfWVsc2UgaWYodHlwZW9mIHZhbD09PVwibnVtYmVyXCIpe3ZhbD12YWwmMjU1O2lmKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUJiZ0eXBlb2YgVWludDhBcnJheS5wcm90b3R5cGUuaW5kZXhPZj09PVwiZnVuY3Rpb25cIil7aWYoZGlyKXtyZXR1cm4gVWludDhBcnJheS5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKGJ1ZmZlcix2YWwsYnl0ZU9mZnNldCl9ZWxzZXtyZXR1cm4gVWludDhBcnJheS5wcm90b3R5cGUubGFzdEluZGV4T2YuY2FsbChidWZmZXIsdmFsLGJ5dGVPZmZzZXQpfX1yZXR1cm4gYXJyYXlJbmRleE9mKGJ1ZmZlcixbdmFsXSxieXRlT2Zmc2V0LGVuY29kaW5nLGRpcil9dGhyb3cgbmV3IFR5cGVFcnJvcihcInZhbCBtdXN0IGJlIHN0cmluZywgbnVtYmVyIG9yIEJ1ZmZlclwiKX1mdW5jdGlvbiBhcnJheUluZGV4T2YoYXJyLHZhbCxieXRlT2Zmc2V0LGVuY29kaW5nLGRpcil7dmFyIGluZGV4U2l6ZT0xO3ZhciBhcnJMZW5ndGg9YXJyLmxlbmd0aDt2YXIgdmFsTGVuZ3RoPXZhbC5sZW5ndGg7aWYoZW5jb2RpbmchPT11bmRlZmluZWQpe2VuY29kaW5nPVN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKTtpZihlbmNvZGluZz09PVwidWNzMlwifHxlbmNvZGluZz09PVwidWNzLTJcInx8ZW5jb2Rpbmc9PT1cInV0ZjE2bGVcInx8ZW5jb2Rpbmc9PT1cInV0Zi0xNmxlXCIpe2lmKGFyci5sZW5ndGg8Mnx8dmFsLmxlbmd0aDwyKXtyZXR1cm4tMX1pbmRleFNpemU9MjthcnJMZW5ndGgvPTI7dmFsTGVuZ3RoLz0yO2J5dGVPZmZzZXQvPTJ9fWZ1bmN0aW9uIHJlYWQoYnVmLGkpe2lmKGluZGV4U2l6ZT09PTEpe3JldHVybiBidWZbaV19ZWxzZXtyZXR1cm4gYnVmLnJlYWRVSW50MTZCRShpKmluZGV4U2l6ZSl9fXZhciBpO2lmKGRpcil7dmFyIGZvdW5kSW5kZXg9LTE7Zm9yKGk9Ynl0ZU9mZnNldDtpPGFyckxlbmd0aDtpKyspe2lmKHJlYWQoYXJyLGkpPT09cmVhZCh2YWwsZm91bmRJbmRleD09PS0xPzA6aS1mb3VuZEluZGV4KSl7aWYoZm91bmRJbmRleD09PS0xKWZvdW5kSW5kZXg9aTtpZihpLWZvdW5kSW5kZXgrMT09PXZhbExlbmd0aClyZXR1cm4gZm91bmRJbmRleCppbmRleFNpemV9ZWxzZXtpZihmb3VuZEluZGV4IT09LTEpaS09aS1mb3VuZEluZGV4O2ZvdW5kSW5kZXg9LTF9fX1lbHNle2lmKGJ5dGVPZmZzZXQrdmFsTGVuZ3RoPmFyckxlbmd0aClieXRlT2Zmc2V0PWFyckxlbmd0aC12YWxMZW5ndGg7Zm9yKGk9Ynl0ZU9mZnNldDtpPj0wO2ktLSl7dmFyIGZvdW5kPXRydWU7Zm9yKHZhciBqPTA7ajx2YWxMZW5ndGg7aisrKXtpZihyZWFkKGFycixpK2opIT09cmVhZCh2YWwsaikpe2ZvdW5kPWZhbHNlO2JyZWFrfX1pZihmb3VuZClyZXR1cm4gaX19cmV0dXJuLTF9QnVmZmVyLnByb3RvdHlwZS5pbmNsdWRlcz1mdW5jdGlvbiBpbmNsdWRlcyh2YWwsYnl0ZU9mZnNldCxlbmNvZGluZyl7cmV0dXJuIHRoaXMuaW5kZXhPZih2YWwsYnl0ZU9mZnNldCxlbmNvZGluZykhPT0tMX07QnVmZmVyLnByb3RvdHlwZS5pbmRleE9mPWZ1bmN0aW9uIGluZGV4T2YodmFsLGJ5dGVPZmZzZXQsZW5jb2Rpbmcpe3JldHVybiBiaWRpcmVjdGlvbmFsSW5kZXhPZih0aGlzLHZhbCxieXRlT2Zmc2V0LGVuY29kaW5nLHRydWUpfTtCdWZmZXIucHJvdG90eXBlLmxhc3RJbmRleE9mPWZ1bmN0aW9uIGxhc3RJbmRleE9mKHZhbCxieXRlT2Zmc2V0LGVuY29kaW5nKXtyZXR1cm4gYmlkaXJlY3Rpb25hbEluZGV4T2YodGhpcyx2YWwsYnl0ZU9mZnNldCxlbmNvZGluZyxmYWxzZSl9O2Z1bmN0aW9uIGhleFdyaXRlKGJ1ZixzdHJpbmcsb2Zmc2V0LGxlbmd0aCl7b2Zmc2V0PU51bWJlcihvZmZzZXQpfHwwO3ZhciByZW1haW5pbmc9YnVmLmxlbmd0aC1vZmZzZXQ7aWYoIWxlbmd0aCl7bGVuZ3RoPXJlbWFpbmluZ31lbHNle2xlbmd0aD1OdW1iZXIobGVuZ3RoKTtpZihsZW5ndGg+cmVtYWluaW5nKXtsZW5ndGg9cmVtYWluaW5nfX12YXIgc3RyTGVuPXN0cmluZy5sZW5ndGg7aWYoc3RyTGVuJTIhPT0wKXRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGhleCBzdHJpbmdcIik7aWYobGVuZ3RoPnN0ckxlbi8yKXtsZW5ndGg9c3RyTGVuLzJ9Zm9yKHZhciBpPTA7aTxsZW5ndGg7KytpKXt2YXIgcGFyc2VkPXBhcnNlSW50KHN0cmluZy5zdWJzdHIoaSoyLDIpLDE2KTtpZihpc05hTihwYXJzZWQpKXJldHVybiBpO2J1ZltvZmZzZXQraV09cGFyc2VkfXJldHVybiBpfWZ1bmN0aW9uIHV0ZjhXcml0ZShidWYsc3RyaW5nLG9mZnNldCxsZW5ndGgpe3JldHVybiBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZyxidWYubGVuZ3RoLW9mZnNldCksYnVmLG9mZnNldCxsZW5ndGgpfWZ1bmN0aW9uIGFzY2lpV3JpdGUoYnVmLHN0cmluZyxvZmZzZXQsbGVuZ3RoKXtyZXR1cm4gYmxpdEJ1ZmZlcihhc2NpaVRvQnl0ZXMoc3RyaW5nKSxidWYsb2Zmc2V0LGxlbmd0aCl9ZnVuY3Rpb24gbGF0aW4xV3JpdGUoYnVmLHN0cmluZyxvZmZzZXQsbGVuZ3RoKXtyZXR1cm4gYXNjaWlXcml0ZShidWYsc3RyaW5nLG9mZnNldCxsZW5ndGgpfWZ1bmN0aW9uIGJhc2U2NFdyaXRlKGJ1ZixzdHJpbmcsb2Zmc2V0LGxlbmd0aCl7cmV0dXJuIGJsaXRCdWZmZXIoYmFzZTY0VG9CeXRlcyhzdHJpbmcpLGJ1ZixvZmZzZXQsbGVuZ3RoKX1mdW5jdGlvbiB1Y3MyV3JpdGUoYnVmLHN0cmluZyxvZmZzZXQsbGVuZ3RoKXtyZXR1cm4gYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcsYnVmLmxlbmd0aC1vZmZzZXQpLGJ1ZixvZmZzZXQsbGVuZ3RoKX1CdWZmZXIucHJvdG90eXBlLndyaXRlPWZ1bmN0aW9uIHdyaXRlKHN0cmluZyxvZmZzZXQsbGVuZ3RoLGVuY29kaW5nKXtpZihvZmZzZXQ9PT11bmRlZmluZWQpe2VuY29kaW5nPVwidXRmOFwiO2xlbmd0aD10aGlzLmxlbmd0aDtvZmZzZXQ9MH1lbHNlIGlmKGxlbmd0aD09PXVuZGVmaW5lZCYmdHlwZW9mIG9mZnNldD09PVwic3RyaW5nXCIpe2VuY29kaW5nPW9mZnNldDtsZW5ndGg9dGhpcy5sZW5ndGg7b2Zmc2V0PTB9ZWxzZSBpZihpc0Zpbml0ZShvZmZzZXQpKXtvZmZzZXQ9b2Zmc2V0fDA7aWYoaXNGaW5pdGUobGVuZ3RoKSl7bGVuZ3RoPWxlbmd0aHwwO2lmKGVuY29kaW5nPT09dW5kZWZpbmVkKWVuY29kaW5nPVwidXRmOFwifWVsc2V7ZW5jb2Rpbmc9bGVuZ3RoO2xlbmd0aD11bmRlZmluZWR9fWVsc2V7dGhyb3cgbmV3IEVycm9yKFwiQnVmZmVyLndyaXRlKHN0cmluZywgZW5jb2RpbmcsIG9mZnNldFssIGxlbmd0aF0pIGlzIG5vIGxvbmdlciBzdXBwb3J0ZWRcIil9dmFyIHJlbWFpbmluZz10aGlzLmxlbmd0aC1vZmZzZXQ7aWYobGVuZ3RoPT09dW5kZWZpbmVkfHxsZW5ndGg+cmVtYWluaW5nKWxlbmd0aD1yZW1haW5pbmc7aWYoc3RyaW5nLmxlbmd0aD4wJiYobGVuZ3RoPDB8fG9mZnNldDwwKXx8b2Zmc2V0PnRoaXMubGVuZ3RoKXt0aHJvdyBuZXcgUmFuZ2VFcnJvcihcIkF0dGVtcHQgdG8gd3JpdGUgb3V0c2lkZSBidWZmZXIgYm91bmRzXCIpfWlmKCFlbmNvZGluZyllbmNvZGluZz1cInV0ZjhcIjt2YXIgbG93ZXJlZENhc2U9ZmFsc2U7Zm9yKDs7KXtzd2l0Y2goZW5jb2Rpbmcpe2Nhc2VcImhleFwiOnJldHVybiBoZXhXcml0ZSh0aGlzLHN0cmluZyxvZmZzZXQsbGVuZ3RoKTtjYXNlXCJ1dGY4XCI6Y2FzZVwidXRmLThcIjpyZXR1cm4gdXRmOFdyaXRlKHRoaXMsc3RyaW5nLG9mZnNldCxsZW5ndGgpO2Nhc2VcImFzY2lpXCI6cmV0dXJuIGFzY2lpV3JpdGUodGhpcyxzdHJpbmcsb2Zmc2V0LGxlbmd0aCk7Y2FzZVwibGF0aW4xXCI6Y2FzZVwiYmluYXJ5XCI6cmV0dXJuIGxhdGluMVdyaXRlKHRoaXMsc3RyaW5nLG9mZnNldCxsZW5ndGgpO2Nhc2VcImJhc2U2NFwiOnJldHVybiBiYXNlNjRXcml0ZSh0aGlzLHN0cmluZyxvZmZzZXQsbGVuZ3RoKTtjYXNlXCJ1Y3MyXCI6Y2FzZVwidWNzLTJcIjpjYXNlXCJ1dGYxNmxlXCI6Y2FzZVwidXRmLTE2bGVcIjpyZXR1cm4gdWNzMldyaXRlKHRoaXMsc3RyaW5nLG9mZnNldCxsZW5ndGgpO2RlZmF1bHQ6aWYobG93ZXJlZENhc2UpdGhyb3cgbmV3IFR5cGVFcnJvcihcIlVua25vd24gZW5jb2Rpbmc6IFwiK2VuY29kaW5nKTtlbmNvZGluZz0oXCJcIitlbmNvZGluZykudG9Mb3dlckNhc2UoKTtsb3dlcmVkQ2FzZT10cnVlfX19O0J1ZmZlci5wcm90b3R5cGUudG9KU09OPWZ1bmN0aW9uIHRvSlNPTigpe3JldHVybnt0eXBlOlwiQnVmZmVyXCIsZGF0YTpBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLl9hcnJ8fHRoaXMsMCl9fTtmdW5jdGlvbiBiYXNlNjRTbGljZShidWYsc3RhcnQsZW5kKXtpZihzdGFydD09PTAmJmVuZD09PWJ1Zi5sZW5ndGgpe3JldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYpfWVsc2V7cmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1Zi5zbGljZShzdGFydCxlbmQpKX19ZnVuY3Rpb24gdXRmOFNsaWNlKGJ1ZixzdGFydCxlbmQpe2VuZD1NYXRoLm1pbihidWYubGVuZ3RoLGVuZCk7dmFyIHJlcz1bXTt2YXIgaT1zdGFydDt3aGlsZShpPGVuZCl7dmFyIGZpcnN0Qnl0ZT1idWZbaV07dmFyIGNvZGVQb2ludD1udWxsO3ZhciBieXRlc1BlclNlcXVlbmNlPWZpcnN0Qnl0ZT4yMzk/NDpmaXJzdEJ5dGU+MjIzPzM6Zmlyc3RCeXRlPjE5MT8yOjE7aWYoaStieXRlc1BlclNlcXVlbmNlPD1lbmQpe3ZhciBzZWNvbmRCeXRlLHRoaXJkQnl0ZSxmb3VydGhCeXRlLHRlbXBDb2RlUG9pbnQ7c3dpdGNoKGJ5dGVzUGVyU2VxdWVuY2Upe2Nhc2UgMTppZihmaXJzdEJ5dGU8MTI4KXtjb2RlUG9pbnQ9Zmlyc3RCeXRlfWJyZWFrO2Nhc2UgMjpzZWNvbmRCeXRlPWJ1ZltpKzFdO2lmKChzZWNvbmRCeXRlJjE5Mik9PT0xMjgpe3RlbXBDb2RlUG9pbnQ9KGZpcnN0Qnl0ZSYzMSk8PDZ8c2Vjb25kQnl0ZSY2MztpZih0ZW1wQ29kZVBvaW50PjEyNyl7Y29kZVBvaW50PXRlbXBDb2RlUG9pbnR9fWJyZWFrO2Nhc2UgMzpzZWNvbmRCeXRlPWJ1ZltpKzFdO3RoaXJkQnl0ZT1idWZbaSsyXTtpZigoc2Vjb25kQnl0ZSYxOTIpPT09MTI4JiYodGhpcmRCeXRlJjE5Mik9PT0xMjgpe3RlbXBDb2RlUG9pbnQ9KGZpcnN0Qnl0ZSYxNSk8PDEyfChzZWNvbmRCeXRlJjYzKTw8Nnx0aGlyZEJ5dGUmNjM7aWYodGVtcENvZGVQb2ludD4yMDQ3JiYodGVtcENvZGVQb2ludDw1NTI5Nnx8dGVtcENvZGVQb2ludD41NzM0Mykpe2NvZGVQb2ludD10ZW1wQ29kZVBvaW50fX1icmVhaztjYXNlIDQ6c2Vjb25kQnl0ZT1idWZbaSsxXTt0aGlyZEJ5dGU9YnVmW2krMl07Zm91cnRoQnl0ZT1idWZbaSszXTtpZigoc2Vjb25kQnl0ZSYxOTIpPT09MTI4JiYodGhpcmRCeXRlJjE5Mik9PT0xMjgmJihmb3VydGhCeXRlJjE5Mik9PT0xMjgpe3RlbXBDb2RlUG9pbnQ9KGZpcnN0Qnl0ZSYxNSk8PDE4fChzZWNvbmRCeXRlJjYzKTw8MTJ8KHRoaXJkQnl0ZSY2Myk8PDZ8Zm91cnRoQnl0ZSY2MztpZih0ZW1wQ29kZVBvaW50PjY1NTM1JiZ0ZW1wQ29kZVBvaW50PDExMTQxMTIpe2NvZGVQb2ludD10ZW1wQ29kZVBvaW50fX19fWlmKGNvZGVQb2ludD09PW51bGwpe2NvZGVQb2ludD02NTUzMztieXRlc1BlclNlcXVlbmNlPTF9ZWxzZSBpZihjb2RlUG9pbnQ+NjU1MzUpe2NvZGVQb2ludC09NjU1MzY7cmVzLnB1c2goY29kZVBvaW50Pj4+MTAmMTAyM3w1NTI5Nik7Y29kZVBvaW50PTU2MzIwfGNvZGVQb2ludCYxMDIzfXJlcy5wdXNoKGNvZGVQb2ludCk7aSs9Ynl0ZXNQZXJTZXF1ZW5jZX1yZXR1cm4gZGVjb2RlQ29kZVBvaW50c0FycmF5KHJlcyl9dmFyIE1BWF9BUkdVTUVOVFNfTEVOR1RIPTQwOTY7ZnVuY3Rpb24gZGVjb2RlQ29kZVBvaW50c0FycmF5KGNvZGVQb2ludHMpe3ZhciBsZW49Y29kZVBvaW50cy5sZW5ndGg7aWYobGVuPD1NQVhfQVJHVU1FTlRTX0xFTkdUSCl7cmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLGNvZGVQb2ludHMpfXZhciByZXM9XCJcIjt2YXIgaT0wO3doaWxlKGk8bGVuKXtyZXMrPVN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLGNvZGVQb2ludHMuc2xpY2UoaSxpKz1NQVhfQVJHVU1FTlRTX0xFTkdUSCkpfXJldHVybiByZXN9ZnVuY3Rpb24gYXNjaWlTbGljZShidWYsc3RhcnQsZW5kKXt2YXIgcmV0PVwiXCI7ZW5kPU1hdGgubWluKGJ1Zi5sZW5ndGgsZW5kKTtmb3IodmFyIGk9c3RhcnQ7aTxlbmQ7KytpKXtyZXQrPVN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldJjEyNyl9cmV0dXJuIHJldH1mdW5jdGlvbiBsYXRpbjFTbGljZShidWYsc3RhcnQsZW5kKXt2YXIgcmV0PVwiXCI7ZW5kPU1hdGgubWluKGJ1Zi5sZW5ndGgsZW5kKTtmb3IodmFyIGk9c3RhcnQ7aTxlbmQ7KytpKXtyZXQrPVN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKX1yZXR1cm4gcmV0fWZ1bmN0aW9uIGhleFNsaWNlKGJ1ZixzdGFydCxlbmQpe3ZhciBsZW49YnVmLmxlbmd0aDtpZighc3RhcnR8fHN0YXJ0PDApc3RhcnQ9MDtpZighZW5kfHxlbmQ8MHx8ZW5kPmxlbillbmQ9bGVuO3ZhciBvdXQ9XCJcIjtmb3IodmFyIGk9c3RhcnQ7aTxlbmQ7KytpKXtvdXQrPXRvSGV4KGJ1ZltpXSl9cmV0dXJuIG91dH1mdW5jdGlvbiB1dGYxNmxlU2xpY2UoYnVmLHN0YXJ0LGVuZCl7dmFyIGJ5dGVzPWJ1Zi5zbGljZShzdGFydCxlbmQpO3ZhciByZXM9XCJcIjtmb3IodmFyIGk9MDtpPGJ5dGVzLmxlbmd0aDtpKz0yKXtyZXMrPVN0cmluZy5mcm9tQ2hhckNvZGUoYnl0ZXNbaV0rYnl0ZXNbaSsxXSoyNTYpfXJldHVybiByZXN9QnVmZmVyLnByb3RvdHlwZS5zbGljZT1mdW5jdGlvbiBzbGljZShzdGFydCxlbmQpe3ZhciBsZW49dGhpcy5sZW5ndGg7c3RhcnQ9fn5zdGFydDtlbmQ9ZW5kPT09dW5kZWZpbmVkP2xlbjp+fmVuZDtpZihzdGFydDwwKXtzdGFydCs9bGVuO2lmKHN0YXJ0PDApc3RhcnQ9MH1lbHNlIGlmKHN0YXJ0Pmxlbil7c3RhcnQ9bGVufWlmKGVuZDwwKXtlbmQrPWxlbjtpZihlbmQ8MCllbmQ9MH1lbHNlIGlmKGVuZD5sZW4pe2VuZD1sZW59aWYoZW5kPHN0YXJ0KWVuZD1zdGFydDt2YXIgbmV3QnVmO2lmKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKXtuZXdCdWY9dGhpcy5zdWJhcnJheShzdGFydCxlbmQpO25ld0J1Zi5fX3Byb3RvX189QnVmZmVyLnByb3RvdHlwZX1lbHNle3ZhciBzbGljZUxlbj1lbmQtc3RhcnQ7bmV3QnVmPW5ldyBCdWZmZXIoc2xpY2VMZW4sdW5kZWZpbmVkKTtmb3IodmFyIGk9MDtpPHNsaWNlTGVuOysraSl7bmV3QnVmW2ldPXRoaXNbaStzdGFydF19fXJldHVybiBuZXdCdWZ9O2Z1bmN0aW9uIGNoZWNrT2Zmc2V0KG9mZnNldCxleHQsbGVuZ3RoKXtpZihvZmZzZXQlMSE9PTB8fG9mZnNldDwwKXRocm93IG5ldyBSYW5nZUVycm9yKFwib2Zmc2V0IGlzIG5vdCB1aW50XCIpO2lmKG9mZnNldCtleHQ+bGVuZ3RoKXRocm93IG5ldyBSYW5nZUVycm9yKFwiVHJ5aW5nIHRvIGFjY2VzcyBiZXlvbmQgYnVmZmVyIGxlbmd0aFwiKX1CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50TEU9ZnVuY3Rpb24gcmVhZFVJbnRMRShvZmZzZXQsYnl0ZUxlbmd0aCxub0Fzc2VydCl7b2Zmc2V0PW9mZnNldHwwO2J5dGVMZW5ndGg9Ynl0ZUxlbmd0aHwwO2lmKCFub0Fzc2VydCljaGVja09mZnNldChvZmZzZXQsYnl0ZUxlbmd0aCx0aGlzLmxlbmd0aCk7dmFyIHZhbD10aGlzW29mZnNldF07dmFyIG11bD0xO3ZhciBpPTA7d2hpbGUoKytpPGJ5dGVMZW5ndGgmJihtdWwqPTI1Nikpe3ZhbCs9dGhpc1tvZmZzZXQraV0qbXVsfXJldHVybiB2YWx9O0J1ZmZlci5wcm90b3R5cGUucmVhZFVJbnRCRT1mdW5jdGlvbiByZWFkVUludEJFKG9mZnNldCxieXRlTGVuZ3RoLG5vQXNzZXJ0KXtvZmZzZXQ9b2Zmc2V0fDA7Ynl0ZUxlbmd0aD1ieXRlTGVuZ3RofDA7aWYoIW5vQXNzZXJ0KXtjaGVja09mZnNldChvZmZzZXQsYnl0ZUxlbmd0aCx0aGlzLmxlbmd0aCl9dmFyIHZhbD10aGlzW29mZnNldCstLWJ5dGVMZW5ndGhdO3ZhciBtdWw9MTt3aGlsZShieXRlTGVuZ3RoPjAmJihtdWwqPTI1Nikpe3ZhbCs9dGhpc1tvZmZzZXQrLS1ieXRlTGVuZ3RoXSptdWx9cmV0dXJuIHZhbH07QnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDg9ZnVuY3Rpb24gcmVhZFVJbnQ4KG9mZnNldCxub0Fzc2VydCl7aWYoIW5vQXNzZXJ0KWNoZWNrT2Zmc2V0KG9mZnNldCwxLHRoaXMubGVuZ3RoKTtyZXR1cm4gdGhpc1tvZmZzZXRdfTtCdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZMRT1mdW5jdGlvbiByZWFkVUludDE2TEUob2Zmc2V0LG5vQXNzZXJ0KXtpZighbm9Bc3NlcnQpY2hlY2tPZmZzZXQob2Zmc2V0LDIsdGhpcy5sZW5ndGgpO3JldHVybiB0aGlzW29mZnNldF18dGhpc1tvZmZzZXQrMV08PDh9O0J1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkJFPWZ1bmN0aW9uIHJlYWRVSW50MTZCRShvZmZzZXQsbm9Bc3NlcnQpe2lmKCFub0Fzc2VydCljaGVja09mZnNldChvZmZzZXQsMix0aGlzLmxlbmd0aCk7cmV0dXJuIHRoaXNbb2Zmc2V0XTw8OHx0aGlzW29mZnNldCsxXX07QnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyTEU9ZnVuY3Rpb24gcmVhZFVJbnQzMkxFKG9mZnNldCxub0Fzc2VydCl7aWYoIW5vQXNzZXJ0KWNoZWNrT2Zmc2V0KG9mZnNldCw0LHRoaXMubGVuZ3RoKTtyZXR1cm4odGhpc1tvZmZzZXRdfHRoaXNbb2Zmc2V0KzFdPDw4fHRoaXNbb2Zmc2V0KzJdPDwxNikrdGhpc1tvZmZzZXQrM10qMTY3NzcyMTZ9O0J1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkJFPWZ1bmN0aW9uIHJlYWRVSW50MzJCRShvZmZzZXQsbm9Bc3NlcnQpe2lmKCFub0Fzc2VydCljaGVja09mZnNldChvZmZzZXQsNCx0aGlzLmxlbmd0aCk7cmV0dXJuIHRoaXNbb2Zmc2V0XSoxNjc3NzIxNisodGhpc1tvZmZzZXQrMV08PDE2fHRoaXNbb2Zmc2V0KzJdPDw4fHRoaXNbb2Zmc2V0KzNdKX07QnVmZmVyLnByb3RvdHlwZS5yZWFkSW50TEU9ZnVuY3Rpb24gcmVhZEludExFKG9mZnNldCxieXRlTGVuZ3RoLG5vQXNzZXJ0KXtvZmZzZXQ9b2Zmc2V0fDA7Ynl0ZUxlbmd0aD1ieXRlTGVuZ3RofDA7aWYoIW5vQXNzZXJ0KWNoZWNrT2Zmc2V0KG9mZnNldCxieXRlTGVuZ3RoLHRoaXMubGVuZ3RoKTt2YXIgdmFsPXRoaXNbb2Zmc2V0XTt2YXIgbXVsPTE7dmFyIGk9MDt3aGlsZSgrK2k8Ynl0ZUxlbmd0aCYmKG11bCo9MjU2KSl7dmFsKz10aGlzW29mZnNldCtpXSptdWx9bXVsKj0xMjg7aWYodmFsPj1tdWwpdmFsLT1NYXRoLnBvdygyLDgqYnl0ZUxlbmd0aCk7cmV0dXJuIHZhbH07QnVmZmVyLnByb3RvdHlwZS5yZWFkSW50QkU9ZnVuY3Rpb24gcmVhZEludEJFKG9mZnNldCxieXRlTGVuZ3RoLG5vQXNzZXJ0KXtvZmZzZXQ9b2Zmc2V0fDA7Ynl0ZUxlbmd0aD1ieXRlTGVuZ3RofDA7aWYoIW5vQXNzZXJ0KWNoZWNrT2Zmc2V0KG9mZnNldCxieXRlTGVuZ3RoLHRoaXMubGVuZ3RoKTtcbnZhciBpPWJ5dGVMZW5ndGg7dmFyIG11bD0xO3ZhciB2YWw9dGhpc1tvZmZzZXQrLS1pXTt3aGlsZShpPjAmJihtdWwqPTI1Nikpe3ZhbCs9dGhpc1tvZmZzZXQrLS1pXSptdWx9bXVsKj0xMjg7aWYodmFsPj1tdWwpdmFsLT1NYXRoLnBvdygyLDgqYnl0ZUxlbmd0aCk7cmV0dXJuIHZhbH07QnVmZmVyLnByb3RvdHlwZS5yZWFkSW50OD1mdW5jdGlvbiByZWFkSW50OChvZmZzZXQsbm9Bc3NlcnQpe2lmKCFub0Fzc2VydCljaGVja09mZnNldChvZmZzZXQsMSx0aGlzLmxlbmd0aCk7aWYoISh0aGlzW29mZnNldF0mMTI4KSlyZXR1cm4gdGhpc1tvZmZzZXRdO3JldHVybigyNTUtdGhpc1tvZmZzZXRdKzEpKi0xfTtCdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkxFPWZ1bmN0aW9uIHJlYWRJbnQxNkxFKG9mZnNldCxub0Fzc2VydCl7aWYoIW5vQXNzZXJ0KWNoZWNrT2Zmc2V0KG9mZnNldCwyLHRoaXMubGVuZ3RoKTt2YXIgdmFsPXRoaXNbb2Zmc2V0XXx0aGlzW29mZnNldCsxXTw8ODtyZXR1cm4gdmFsJjMyNzY4P3ZhbHw0Mjk0OTAxNzYwOnZhbH07QnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZCRT1mdW5jdGlvbiByZWFkSW50MTZCRShvZmZzZXQsbm9Bc3NlcnQpe2lmKCFub0Fzc2VydCljaGVja09mZnNldChvZmZzZXQsMix0aGlzLmxlbmd0aCk7dmFyIHZhbD10aGlzW29mZnNldCsxXXx0aGlzW29mZnNldF08PDg7cmV0dXJuIHZhbCYzMjc2OD92YWx8NDI5NDkwMTc2MDp2YWx9O0J1ZmZlci5wcm90b3R5cGUucmVhZEludDMyTEU9ZnVuY3Rpb24gcmVhZEludDMyTEUob2Zmc2V0LG5vQXNzZXJ0KXtpZighbm9Bc3NlcnQpY2hlY2tPZmZzZXQob2Zmc2V0LDQsdGhpcy5sZW5ndGgpO3JldHVybiB0aGlzW29mZnNldF18dGhpc1tvZmZzZXQrMV08PDh8dGhpc1tvZmZzZXQrMl08PDE2fHRoaXNbb2Zmc2V0KzNdPDwyNH07QnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJCRT1mdW5jdGlvbiByZWFkSW50MzJCRShvZmZzZXQsbm9Bc3NlcnQpe2lmKCFub0Fzc2VydCljaGVja09mZnNldChvZmZzZXQsNCx0aGlzLmxlbmd0aCk7cmV0dXJuIHRoaXNbb2Zmc2V0XTw8MjR8dGhpc1tvZmZzZXQrMV08PDE2fHRoaXNbb2Zmc2V0KzJdPDw4fHRoaXNbb2Zmc2V0KzNdfTtCdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdExFPWZ1bmN0aW9uIHJlYWRGbG9hdExFKG9mZnNldCxub0Fzc2VydCl7aWYoIW5vQXNzZXJ0KWNoZWNrT2Zmc2V0KG9mZnNldCw0LHRoaXMubGVuZ3RoKTtyZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsb2Zmc2V0LHRydWUsMjMsNCl9O0J1ZmZlci5wcm90b3R5cGUucmVhZEZsb2F0QkU9ZnVuY3Rpb24gcmVhZEZsb2F0QkUob2Zmc2V0LG5vQXNzZXJ0KXtpZighbm9Bc3NlcnQpY2hlY2tPZmZzZXQob2Zmc2V0LDQsdGhpcy5sZW5ndGgpO3JldHVybiBpZWVlNzU0LnJlYWQodGhpcyxvZmZzZXQsZmFsc2UsMjMsNCl9O0J1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUxFPWZ1bmN0aW9uIHJlYWREb3VibGVMRShvZmZzZXQsbm9Bc3NlcnQpe2lmKCFub0Fzc2VydCljaGVja09mZnNldChvZmZzZXQsOCx0aGlzLmxlbmd0aCk7cmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLG9mZnNldCx0cnVlLDUyLDgpfTtCdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVCRT1mdW5jdGlvbiByZWFkRG91YmxlQkUob2Zmc2V0LG5vQXNzZXJ0KXtpZighbm9Bc3NlcnQpY2hlY2tPZmZzZXQob2Zmc2V0LDgsdGhpcy5sZW5ndGgpO3JldHVybiBpZWVlNzU0LnJlYWQodGhpcyxvZmZzZXQsZmFsc2UsNTIsOCl9O2Z1bmN0aW9uIGNoZWNrSW50KGJ1Zix2YWx1ZSxvZmZzZXQsZXh0LG1heCxtaW4pe2lmKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSl0aHJvdyBuZXcgVHlwZUVycm9yKCdcImJ1ZmZlclwiIGFyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXIgaW5zdGFuY2UnKTtpZih2YWx1ZT5tYXh8fHZhbHVlPG1pbil0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJ2YWx1ZVwiIGFyZ3VtZW50IGlzIG91dCBvZiBib3VuZHMnKTtpZihvZmZzZXQrZXh0PmJ1Zi5sZW5ndGgpdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJJbmRleCBvdXQgb2YgcmFuZ2VcIil9QnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnRMRT1mdW5jdGlvbiB3cml0ZVVJbnRMRSh2YWx1ZSxvZmZzZXQsYnl0ZUxlbmd0aCxub0Fzc2VydCl7dmFsdWU9K3ZhbHVlO29mZnNldD1vZmZzZXR8MDtieXRlTGVuZ3RoPWJ5dGVMZW5ndGh8MDtpZighbm9Bc3NlcnQpe3ZhciBtYXhCeXRlcz1NYXRoLnBvdygyLDgqYnl0ZUxlbmd0aCktMTtjaGVja0ludCh0aGlzLHZhbHVlLG9mZnNldCxieXRlTGVuZ3RoLG1heEJ5dGVzLDApfXZhciBtdWw9MTt2YXIgaT0wO3RoaXNbb2Zmc2V0XT12YWx1ZSYyNTU7d2hpbGUoKytpPGJ5dGVMZW5ndGgmJihtdWwqPTI1Nikpe3RoaXNbb2Zmc2V0K2ldPXZhbHVlL211bCYyNTV9cmV0dXJuIG9mZnNldCtieXRlTGVuZ3RofTtCdWZmZXIucHJvdG90eXBlLndyaXRlVUludEJFPWZ1bmN0aW9uIHdyaXRlVUludEJFKHZhbHVlLG9mZnNldCxieXRlTGVuZ3RoLG5vQXNzZXJ0KXt2YWx1ZT0rdmFsdWU7b2Zmc2V0PW9mZnNldHwwO2J5dGVMZW5ndGg9Ynl0ZUxlbmd0aHwwO2lmKCFub0Fzc2VydCl7dmFyIG1heEJ5dGVzPU1hdGgucG93KDIsOCpieXRlTGVuZ3RoKS0xO2NoZWNrSW50KHRoaXMsdmFsdWUsb2Zmc2V0LGJ5dGVMZW5ndGgsbWF4Qnl0ZXMsMCl9dmFyIGk9Ynl0ZUxlbmd0aC0xO3ZhciBtdWw9MTt0aGlzW29mZnNldCtpXT12YWx1ZSYyNTU7d2hpbGUoLS1pPj0wJiYobXVsKj0yNTYpKXt0aGlzW29mZnNldCtpXT12YWx1ZS9tdWwmMjU1fXJldHVybiBvZmZzZXQrYnl0ZUxlbmd0aH07QnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQ4PWZ1bmN0aW9uIHdyaXRlVUludDgodmFsdWUsb2Zmc2V0LG5vQXNzZXJ0KXt2YWx1ZT0rdmFsdWU7b2Zmc2V0PW9mZnNldHwwO2lmKCFub0Fzc2VydCljaGVja0ludCh0aGlzLHZhbHVlLG9mZnNldCwxLDI1NSwwKTtpZighQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpdmFsdWU9TWF0aC5mbG9vcih2YWx1ZSk7dGhpc1tvZmZzZXRdPXZhbHVlJjI1NTtyZXR1cm4gb2Zmc2V0KzF9O2Z1bmN0aW9uIG9iamVjdFdyaXRlVUludDE2KGJ1Zix2YWx1ZSxvZmZzZXQsbGl0dGxlRW5kaWFuKXtpZih2YWx1ZTwwKXZhbHVlPTY1NTM1K3ZhbHVlKzE7Zm9yKHZhciBpPTAsaj1NYXRoLm1pbihidWYubGVuZ3RoLW9mZnNldCwyKTtpPGo7KytpKXtidWZbb2Zmc2V0K2ldPSh2YWx1ZSYyNTU8PDgqKGxpdHRsZUVuZGlhbj9pOjEtaSkpPj4+KGxpdHRsZUVuZGlhbj9pOjEtaSkqOH19QnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkxFPWZ1bmN0aW9uIHdyaXRlVUludDE2TEUodmFsdWUsb2Zmc2V0LG5vQXNzZXJ0KXt2YWx1ZT0rdmFsdWU7b2Zmc2V0PW9mZnNldHwwO2lmKCFub0Fzc2VydCljaGVja0ludCh0aGlzLHZhbHVlLG9mZnNldCwyLDY1NTM1LDApO2lmKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKXt0aGlzW29mZnNldF09dmFsdWUmMjU1O3RoaXNbb2Zmc2V0KzFdPXZhbHVlPj4+OH1lbHNle29iamVjdFdyaXRlVUludDE2KHRoaXMsdmFsdWUsb2Zmc2V0LHRydWUpfXJldHVybiBvZmZzZXQrMn07QnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkJFPWZ1bmN0aW9uIHdyaXRlVUludDE2QkUodmFsdWUsb2Zmc2V0LG5vQXNzZXJ0KXt2YWx1ZT0rdmFsdWU7b2Zmc2V0PW9mZnNldHwwO2lmKCFub0Fzc2VydCljaGVja0ludCh0aGlzLHZhbHVlLG9mZnNldCwyLDY1NTM1LDApO2lmKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKXt0aGlzW29mZnNldF09dmFsdWU+Pj44O3RoaXNbb2Zmc2V0KzFdPXZhbHVlJjI1NX1lbHNle29iamVjdFdyaXRlVUludDE2KHRoaXMsdmFsdWUsb2Zmc2V0LGZhbHNlKX1yZXR1cm4gb2Zmc2V0KzJ9O2Z1bmN0aW9uIG9iamVjdFdyaXRlVUludDMyKGJ1Zix2YWx1ZSxvZmZzZXQsbGl0dGxlRW5kaWFuKXtpZih2YWx1ZTwwKXZhbHVlPTQyOTQ5NjcyOTUrdmFsdWUrMTtmb3IodmFyIGk9MCxqPU1hdGgubWluKGJ1Zi5sZW5ndGgtb2Zmc2V0LDQpO2k8ajsrK2kpe2J1ZltvZmZzZXQraV09dmFsdWU+Pj4obGl0dGxlRW5kaWFuP2k6My1pKSo4JjI1NX19QnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFPWZ1bmN0aW9uIHdyaXRlVUludDMyTEUodmFsdWUsb2Zmc2V0LG5vQXNzZXJ0KXt2YWx1ZT0rdmFsdWU7b2Zmc2V0PW9mZnNldHwwO2lmKCFub0Fzc2VydCljaGVja0ludCh0aGlzLHZhbHVlLG9mZnNldCw0LDQyOTQ5NjcyOTUsMCk7aWYoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpe3RoaXNbb2Zmc2V0KzNdPXZhbHVlPj4+MjQ7dGhpc1tvZmZzZXQrMl09dmFsdWU+Pj4xNjt0aGlzW29mZnNldCsxXT12YWx1ZT4+Pjg7dGhpc1tvZmZzZXRdPXZhbHVlJjI1NX1lbHNle29iamVjdFdyaXRlVUludDMyKHRoaXMsdmFsdWUsb2Zmc2V0LHRydWUpfXJldHVybiBvZmZzZXQrNH07QnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkJFPWZ1bmN0aW9uIHdyaXRlVUludDMyQkUodmFsdWUsb2Zmc2V0LG5vQXNzZXJ0KXt2YWx1ZT0rdmFsdWU7b2Zmc2V0PW9mZnNldHwwO2lmKCFub0Fzc2VydCljaGVja0ludCh0aGlzLHZhbHVlLG9mZnNldCw0LDQyOTQ5NjcyOTUsMCk7aWYoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpe3RoaXNbb2Zmc2V0XT12YWx1ZT4+PjI0O3RoaXNbb2Zmc2V0KzFdPXZhbHVlPj4+MTY7dGhpc1tvZmZzZXQrMl09dmFsdWU+Pj44O3RoaXNbb2Zmc2V0KzNdPXZhbHVlJjI1NX1lbHNle29iamVjdFdyaXRlVUludDMyKHRoaXMsdmFsdWUsb2Zmc2V0LGZhbHNlKX1yZXR1cm4gb2Zmc2V0KzR9O0J1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRMRT1mdW5jdGlvbiB3cml0ZUludExFKHZhbHVlLG9mZnNldCxieXRlTGVuZ3RoLG5vQXNzZXJ0KXt2YWx1ZT0rdmFsdWU7b2Zmc2V0PW9mZnNldHwwO2lmKCFub0Fzc2VydCl7dmFyIGxpbWl0PU1hdGgucG93KDIsOCpieXRlTGVuZ3RoLTEpO2NoZWNrSW50KHRoaXMsdmFsdWUsb2Zmc2V0LGJ5dGVMZW5ndGgsbGltaXQtMSwtbGltaXQpfXZhciBpPTA7dmFyIG11bD0xO3ZhciBzdWI9MDt0aGlzW29mZnNldF09dmFsdWUmMjU1O3doaWxlKCsraTxieXRlTGVuZ3RoJiYobXVsKj0yNTYpKXtpZih2YWx1ZTwwJiZzdWI9PT0wJiZ0aGlzW29mZnNldCtpLTFdIT09MCl7c3ViPTF9dGhpc1tvZmZzZXQraV09KHZhbHVlL211bD4+MCktc3ViJjI1NX1yZXR1cm4gb2Zmc2V0K2J5dGVMZW5ndGh9O0J1ZmZlci5wcm90b3R5cGUud3JpdGVJbnRCRT1mdW5jdGlvbiB3cml0ZUludEJFKHZhbHVlLG9mZnNldCxieXRlTGVuZ3RoLG5vQXNzZXJ0KXt2YWx1ZT0rdmFsdWU7b2Zmc2V0PW9mZnNldHwwO2lmKCFub0Fzc2VydCl7dmFyIGxpbWl0PU1hdGgucG93KDIsOCpieXRlTGVuZ3RoLTEpO2NoZWNrSW50KHRoaXMsdmFsdWUsb2Zmc2V0LGJ5dGVMZW5ndGgsbGltaXQtMSwtbGltaXQpfXZhciBpPWJ5dGVMZW5ndGgtMTt2YXIgbXVsPTE7dmFyIHN1Yj0wO3RoaXNbb2Zmc2V0K2ldPXZhbHVlJjI1NTt3aGlsZSgtLWk+PTAmJihtdWwqPTI1Nikpe2lmKHZhbHVlPDAmJnN1Yj09PTAmJnRoaXNbb2Zmc2V0K2krMV0hPT0wKXtzdWI9MX10aGlzW29mZnNldCtpXT0odmFsdWUvbXVsPj4wKS1zdWImMjU1fXJldHVybiBvZmZzZXQrYnl0ZUxlbmd0aH07QnVmZmVyLnByb3RvdHlwZS53cml0ZUludDg9ZnVuY3Rpb24gd3JpdGVJbnQ4KHZhbHVlLG9mZnNldCxub0Fzc2VydCl7dmFsdWU9K3ZhbHVlO29mZnNldD1vZmZzZXR8MDtpZighbm9Bc3NlcnQpY2hlY2tJbnQodGhpcyx2YWx1ZSxvZmZzZXQsMSwxMjcsLTEyOCk7aWYoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKXZhbHVlPU1hdGguZmxvb3IodmFsdWUpO2lmKHZhbHVlPDApdmFsdWU9MjU1K3ZhbHVlKzE7dGhpc1tvZmZzZXRdPXZhbHVlJjI1NTtyZXR1cm4gb2Zmc2V0KzF9O0J1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkxFPWZ1bmN0aW9uIHdyaXRlSW50MTZMRSh2YWx1ZSxvZmZzZXQsbm9Bc3NlcnQpe3ZhbHVlPSt2YWx1ZTtvZmZzZXQ9b2Zmc2V0fDA7aWYoIW5vQXNzZXJ0KWNoZWNrSW50KHRoaXMsdmFsdWUsb2Zmc2V0LDIsMzI3NjcsLTMyNzY4KTtpZihCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCl7dGhpc1tvZmZzZXRdPXZhbHVlJjI1NTt0aGlzW29mZnNldCsxXT12YWx1ZT4+Pjh9ZWxzZXtvYmplY3RXcml0ZVVJbnQxNih0aGlzLHZhbHVlLG9mZnNldCx0cnVlKX1yZXR1cm4gb2Zmc2V0KzJ9O0J1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkJFPWZ1bmN0aW9uIHdyaXRlSW50MTZCRSh2YWx1ZSxvZmZzZXQsbm9Bc3NlcnQpe3ZhbHVlPSt2YWx1ZTtvZmZzZXQ9b2Zmc2V0fDA7aWYoIW5vQXNzZXJ0KWNoZWNrSW50KHRoaXMsdmFsdWUsb2Zmc2V0LDIsMzI3NjcsLTMyNzY4KTtpZihCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCl7dGhpc1tvZmZzZXRdPXZhbHVlPj4+ODt0aGlzW29mZnNldCsxXT12YWx1ZSYyNTV9ZWxzZXtvYmplY3RXcml0ZVVJbnQxNih0aGlzLHZhbHVlLG9mZnNldCxmYWxzZSl9cmV0dXJuIG9mZnNldCsyfTtCdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJMRT1mdW5jdGlvbiB3cml0ZUludDMyTEUodmFsdWUsb2Zmc2V0LG5vQXNzZXJ0KXt2YWx1ZT0rdmFsdWU7b2Zmc2V0PW9mZnNldHwwO2lmKCFub0Fzc2VydCljaGVja0ludCh0aGlzLHZhbHVlLG9mZnNldCw0LDIxNDc0ODM2NDcsLTIxNDc0ODM2NDgpO2lmKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKXt0aGlzW29mZnNldF09dmFsdWUmMjU1O3RoaXNbb2Zmc2V0KzFdPXZhbHVlPj4+ODt0aGlzW29mZnNldCsyXT12YWx1ZT4+PjE2O3RoaXNbb2Zmc2V0KzNdPXZhbHVlPj4+MjR9ZWxzZXtvYmplY3RXcml0ZVVJbnQzMih0aGlzLHZhbHVlLG9mZnNldCx0cnVlKX1yZXR1cm4gb2Zmc2V0KzR9O0J1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkJFPWZ1bmN0aW9uIHdyaXRlSW50MzJCRSh2YWx1ZSxvZmZzZXQsbm9Bc3NlcnQpe3ZhbHVlPSt2YWx1ZTtvZmZzZXQ9b2Zmc2V0fDA7aWYoIW5vQXNzZXJ0KWNoZWNrSW50KHRoaXMsdmFsdWUsb2Zmc2V0LDQsMjE0NzQ4MzY0NywtMjE0NzQ4MzY0OCk7aWYodmFsdWU8MCl2YWx1ZT00Mjk0OTY3Mjk1K3ZhbHVlKzE7aWYoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpe3RoaXNbb2Zmc2V0XT12YWx1ZT4+PjI0O3RoaXNbb2Zmc2V0KzFdPXZhbHVlPj4+MTY7dGhpc1tvZmZzZXQrMl09dmFsdWU+Pj44O3RoaXNbb2Zmc2V0KzNdPXZhbHVlJjI1NX1lbHNle29iamVjdFdyaXRlVUludDMyKHRoaXMsdmFsdWUsb2Zmc2V0LGZhbHNlKX1yZXR1cm4gb2Zmc2V0KzR9O2Z1bmN0aW9uIGNoZWNrSUVFRTc1NChidWYsdmFsdWUsb2Zmc2V0LGV4dCxtYXgsbWluKXtpZihvZmZzZXQrZXh0PmJ1Zi5sZW5ndGgpdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJJbmRleCBvdXQgb2YgcmFuZ2VcIik7aWYob2Zmc2V0PDApdGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJJbmRleCBvdXQgb2YgcmFuZ2VcIil9ZnVuY3Rpb24gd3JpdGVGbG9hdChidWYsdmFsdWUsb2Zmc2V0LGxpdHRsZUVuZGlhbixub0Fzc2VydCl7aWYoIW5vQXNzZXJ0KXtjaGVja0lFRUU3NTQoYnVmLHZhbHVlLG9mZnNldCw0LDMuNDAyODIzNDY2Mzg1Mjg4NmUzOCwtMy40MDI4MjM0NjYzODUyODg2ZTM4KX1pZWVlNzU0LndyaXRlKGJ1Zix2YWx1ZSxvZmZzZXQsbGl0dGxlRW5kaWFuLDIzLDQpO3JldHVybiBvZmZzZXQrNH1CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRMRT1mdW5jdGlvbiB3cml0ZUZsb2F0TEUodmFsdWUsb2Zmc2V0LG5vQXNzZXJ0KXtyZXR1cm4gd3JpdGVGbG9hdCh0aGlzLHZhbHVlLG9mZnNldCx0cnVlLG5vQXNzZXJ0KX07QnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0QkU9ZnVuY3Rpb24gd3JpdGVGbG9hdEJFKHZhbHVlLG9mZnNldCxub0Fzc2VydCl7cmV0dXJuIHdyaXRlRmxvYXQodGhpcyx2YWx1ZSxvZmZzZXQsZmFsc2Usbm9Bc3NlcnQpfTtmdW5jdGlvbiB3cml0ZURvdWJsZShidWYsdmFsdWUsb2Zmc2V0LGxpdHRsZUVuZGlhbixub0Fzc2VydCl7aWYoIW5vQXNzZXJ0KXtjaGVja0lFRUU3NTQoYnVmLHZhbHVlLG9mZnNldCw4LDEuNzk3NjkzMTM0ODYyMzE1N2UzMDgsLTEuNzk3NjkzMTM0ODYyMzE1N2UzMDgpfWllZWU3NTQud3JpdGUoYnVmLHZhbHVlLG9mZnNldCxsaXR0bGVFbmRpYW4sNTIsOCk7cmV0dXJuIG9mZnNldCs4fUJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVMRT1mdW5jdGlvbiB3cml0ZURvdWJsZUxFKHZhbHVlLG9mZnNldCxub0Fzc2VydCl7cmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsdmFsdWUsb2Zmc2V0LHRydWUsbm9Bc3NlcnQpfTtCdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkU9ZnVuY3Rpb24gd3JpdGVEb3VibGVCRSh2YWx1ZSxvZmZzZXQsbm9Bc3NlcnQpe3JldHVybiB3cml0ZURvdWJsZSh0aGlzLHZhbHVlLG9mZnNldCxmYWxzZSxub0Fzc2VydCl9O0J1ZmZlci5wcm90b3R5cGUuY29weT1mdW5jdGlvbiBjb3B5KHRhcmdldCx0YXJnZXRTdGFydCxzdGFydCxlbmQpe2lmKCFzdGFydClzdGFydD0wO2lmKCFlbmQmJmVuZCE9PTApZW5kPXRoaXMubGVuZ3RoO2lmKHRhcmdldFN0YXJ0Pj10YXJnZXQubGVuZ3RoKXRhcmdldFN0YXJ0PXRhcmdldC5sZW5ndGg7aWYoIXRhcmdldFN0YXJ0KXRhcmdldFN0YXJ0PTA7aWYoZW5kPjAmJmVuZDxzdGFydCllbmQ9c3RhcnQ7aWYoZW5kPT09c3RhcnQpcmV0dXJuIDA7aWYodGFyZ2V0Lmxlbmd0aD09PTB8fHRoaXMubGVuZ3RoPT09MClyZXR1cm4gMDtpZih0YXJnZXRTdGFydDwwKXt0aHJvdyBuZXcgUmFuZ2VFcnJvcihcInRhcmdldFN0YXJ0IG91dCBvZiBib3VuZHNcIil9aWYoc3RhcnQ8MHx8c3RhcnQ+PXRoaXMubGVuZ3RoKXRocm93IG5ldyBSYW5nZUVycm9yKFwic291cmNlU3RhcnQgb3V0IG9mIGJvdW5kc1wiKTtpZihlbmQ8MCl0aHJvdyBuZXcgUmFuZ2VFcnJvcihcInNvdXJjZUVuZCBvdXQgb2YgYm91bmRzXCIpO2lmKGVuZD50aGlzLmxlbmd0aCllbmQ9dGhpcy5sZW5ndGg7aWYodGFyZ2V0Lmxlbmd0aC10YXJnZXRTdGFydDxlbmQtc3RhcnQpe2VuZD10YXJnZXQubGVuZ3RoLXRhcmdldFN0YXJ0K3N0YXJ0fXZhciBsZW49ZW5kLXN0YXJ0O3ZhciBpO2lmKHRoaXM9PT10YXJnZXQmJnN0YXJ0PHRhcmdldFN0YXJ0JiZ0YXJnZXRTdGFydDxlbmQpe2ZvcihpPWxlbi0xO2k+PTA7LS1pKXt0YXJnZXRbaSt0YXJnZXRTdGFydF09dGhpc1tpK3N0YXJ0XX19ZWxzZSBpZihsZW48MWUzfHwhQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpe2ZvcihpPTA7aTxsZW47KytpKXt0YXJnZXRbaSt0YXJnZXRTdGFydF09dGhpc1tpK3N0YXJ0XX19ZWxzZXtVaW50OEFycmF5LnByb3RvdHlwZS5zZXQuY2FsbCh0YXJnZXQsdGhpcy5zdWJhcnJheShzdGFydCxzdGFydCtsZW4pLHRhcmdldFN0YXJ0KX1yZXR1cm4gbGVufTtCdWZmZXIucHJvdG90eXBlLmZpbGw9ZnVuY3Rpb24gZmlsbCh2YWwsc3RhcnQsZW5kLGVuY29kaW5nKXtpZih0eXBlb2YgdmFsPT09XCJzdHJpbmdcIil7aWYodHlwZW9mIHN0YXJ0PT09XCJzdHJpbmdcIil7ZW5jb2Rpbmc9c3RhcnQ7c3RhcnQ9MDtlbmQ9dGhpcy5sZW5ndGh9ZWxzZSBpZih0eXBlb2YgZW5kPT09XCJzdHJpbmdcIil7ZW5jb2Rpbmc9ZW5kO2VuZD10aGlzLmxlbmd0aH1pZih2YWwubGVuZ3RoPT09MSl7dmFyIGNvZGU9dmFsLmNoYXJDb2RlQXQoMCk7aWYoY29kZTwyNTYpe3ZhbD1jb2RlfX1pZihlbmNvZGluZyE9PXVuZGVmaW5lZCYmdHlwZW9mIGVuY29kaW5nIT09XCJzdHJpbmdcIil7dGhyb3cgbmV3IFR5cGVFcnJvcihcImVuY29kaW5nIG11c3QgYmUgYSBzdHJpbmdcIil9aWYodHlwZW9mIGVuY29kaW5nPT09XCJzdHJpbmdcIiYmIUJ1ZmZlci5pc0VuY29kaW5nKGVuY29kaW5nKSl7dGhyb3cgbmV3IFR5cGVFcnJvcihcIlVua25vd24gZW5jb2Rpbmc6IFwiK2VuY29kaW5nKX19ZWxzZSBpZih0eXBlb2YgdmFsPT09XCJudW1iZXJcIil7dmFsPXZhbCYyNTV9aWYoc3RhcnQ8MHx8dGhpcy5sZW5ndGg8c3RhcnR8fHRoaXMubGVuZ3RoPGVuZCl7dGhyb3cgbmV3IFJhbmdlRXJyb3IoXCJPdXQgb2YgcmFuZ2UgaW5kZXhcIil9aWYoZW5kPD1zdGFydCl7cmV0dXJuIHRoaXN9c3RhcnQ9c3RhcnQ+Pj4wO2VuZD1lbmQ9PT11bmRlZmluZWQ/dGhpcy5sZW5ndGg6ZW5kPj4+MDtpZighdmFsKXZhbD0wO3ZhciBpO2lmKHR5cGVvZiB2YWw9PT1cIm51bWJlclwiKXtmb3IoaT1zdGFydDtpPGVuZDsrK2kpe3RoaXNbaV09dmFsfX1lbHNle3ZhciBieXRlcz1CdWZmZXIuaXNCdWZmZXIodmFsKT92YWw6dXRmOFRvQnl0ZXMobmV3IEJ1ZmZlcih2YWwsZW5jb2RpbmcpLnRvU3RyaW5nKCkpO3ZhciBsZW49Ynl0ZXMubGVuZ3RoO2ZvcihpPTA7aTxlbmQtc3RhcnQ7KytpKXt0aGlzW2krc3RhcnRdPWJ5dGVzW2klbGVuXX19cmV0dXJuIHRoaXN9O3ZhciBJTlZBTElEX0JBU0U2NF9SRT0vW14rXFwvMC05QS1aYS16LV9dL2c7ZnVuY3Rpb24gYmFzZTY0Y2xlYW4oc3RyKXtzdHI9c3RyaW5ndHJpbShzdHIpLnJlcGxhY2UoSU5WQUxJRF9CQVNFNjRfUkUsXCJcIik7aWYoc3RyLmxlbmd0aDwyKXJldHVyblwiXCI7d2hpbGUoc3RyLmxlbmd0aCU0IT09MCl7c3RyPXN0citcIj1cIn1yZXR1cm4gc3RyfWZ1bmN0aW9uIHN0cmluZ3RyaW0oc3RyKXtpZihzdHIudHJpbSlyZXR1cm4gc3RyLnRyaW0oKTtyZXR1cm4gc3RyLnJlcGxhY2UoL15cXHMrfFxccyskL2csXCJcIil9ZnVuY3Rpb24gdG9IZXgobil7aWYobjwxNilyZXR1cm5cIjBcIituLnRvU3RyaW5nKDE2KTtyZXR1cm4gbi50b1N0cmluZygxNil9ZnVuY3Rpb24gdXRmOFRvQnl0ZXMoc3RyaW5nLHVuaXRzKXt1bml0cz11bml0c3x8SW5maW5pdHk7dmFyIGNvZGVQb2ludDt2YXIgbGVuZ3RoPXN0cmluZy5sZW5ndGg7dmFyIGxlYWRTdXJyb2dhdGU9bnVsbDt2YXIgYnl0ZXM9W107Zm9yKHZhciBpPTA7aTxsZW5ndGg7KytpKXtjb2RlUG9pbnQ9c3RyaW5nLmNoYXJDb2RlQXQoaSk7aWYoY29kZVBvaW50PjU1Mjk1JiZjb2RlUG9pbnQ8NTczNDQpe2lmKCFsZWFkU3Vycm9nYXRlKXtpZihjb2RlUG9pbnQ+NTYzMTkpe2lmKCh1bml0cy09Myk+LTEpYnl0ZXMucHVzaCgyMzksMTkxLDE4OSk7Y29udGludWV9ZWxzZSBpZihpKzE9PT1sZW5ndGgpe2lmKCh1bml0cy09Myk+LTEpYnl0ZXMucHVzaCgyMzksMTkxLDE4OSk7Y29udGludWV9bGVhZFN1cnJvZ2F0ZT1jb2RlUG9pbnQ7Y29udGludWV9aWYoY29kZVBvaW50PDU2MzIwKXtpZigodW5pdHMtPTMpPi0xKWJ5dGVzLnB1c2goMjM5LDE5MSwxODkpO2xlYWRTdXJyb2dhdGU9Y29kZVBvaW50O2NvbnRpbnVlfWNvZGVQb2ludD0obGVhZFN1cnJvZ2F0ZS01NTI5Njw8MTB8Y29kZVBvaW50LTU2MzIwKSs2NTUzNn1lbHNlIGlmKGxlYWRTdXJyb2dhdGUpe2lmKCh1bml0cy09Myk+LTEpYnl0ZXMucHVzaCgyMzksMTkxLDE4OSl9bGVhZFN1cnJvZ2F0ZT1udWxsO2lmKGNvZGVQb2ludDwxMjgpe2lmKCh1bml0cy09MSk8MClicmVhaztieXRlcy5wdXNoKGNvZGVQb2ludCl9ZWxzZSBpZihjb2RlUG9pbnQ8MjA0OCl7aWYoKHVuaXRzLT0yKTwwKWJyZWFrO2J5dGVzLnB1c2goY29kZVBvaW50Pj42fDE5Mixjb2RlUG9pbnQmNjN8MTI4KX1lbHNlIGlmKGNvZGVQb2ludDw2NTUzNil7aWYoKHVuaXRzLT0zKTwwKWJyZWFrO2J5dGVzLnB1c2goY29kZVBvaW50Pj4xMnwyMjQsY29kZVBvaW50Pj42JjYzfDEyOCxjb2RlUG9pbnQmNjN8MTI4KX1lbHNlIGlmKGNvZGVQb2ludDwxMTE0MTEyKXtpZigodW5pdHMtPTQpPDApYnJlYWs7Ynl0ZXMucHVzaChjb2RlUG9pbnQ+PjE4fDI0MCxjb2RlUG9pbnQ+PjEyJjYzfDEyOCxjb2RlUG9pbnQ+PjYmNjN8MTI4LGNvZGVQb2ludCY2M3wxMjgpfWVsc2V7dGhyb3cgbmV3IEVycm9yKFwiSW52YWxpZCBjb2RlIHBvaW50XCIpfX1yZXR1cm4gYnl0ZXN9ZnVuY3Rpb24gYXNjaWlUb0J5dGVzKHN0cil7dmFyIGJ5dGVBcnJheT1bXTtmb3IodmFyIGk9MDtpPHN0ci5sZW5ndGg7KytpKXtieXRlQXJyYXkucHVzaChzdHIuY2hhckNvZGVBdChpKSYyNTUpfXJldHVybiBieXRlQXJyYXl9ZnVuY3Rpb24gdXRmMTZsZVRvQnl0ZXMoc3RyLHVuaXRzKXt2YXIgYyxoaSxsbzt2YXIgYnl0ZUFycmF5PVtdO2Zvcih2YXIgaT0wO2k8c3RyLmxlbmd0aDsrK2kpe2lmKCh1bml0cy09Mik8MClicmVhaztjPXN0ci5jaGFyQ29kZUF0KGkpO2hpPWM+Pjg7bG89YyUyNTY7Ynl0ZUFycmF5LnB1c2gobG8pO2J5dGVBcnJheS5wdXNoKGhpKX1yZXR1cm4gYnl0ZUFycmF5fWZ1bmN0aW9uIGJhc2U2NFRvQnl0ZXMoc3RyKXtyZXR1cm4gYmFzZTY0LnRvQnl0ZUFycmF5KGJhc2U2NGNsZWFuKHN0cikpfWZ1bmN0aW9uIGJsaXRCdWZmZXIoc3JjLGRzdCxvZmZzZXQsbGVuZ3RoKXtmb3IodmFyIGk9MDtpPGxlbmd0aDsrK2kpe2lmKGkrb2Zmc2V0Pj1kc3QubGVuZ3RofHxpPj1zcmMubGVuZ3RoKWJyZWFrO2RzdFtpK29mZnNldF09c3JjW2ldfXJldHVybiBpfWZ1bmN0aW9uIGlzbmFuKHZhbCl7cmV0dXJuIHZhbCE9PXZhbH19KS5jYWxsKHRoaXMsdHlwZW9mIGdsb2JhbCE9PVwidW5kZWZpbmVkXCI/Z2xvYmFsOnR5cGVvZiBzZWxmIT09XCJ1bmRlZmluZWRcIj9zZWxmOnR5cGVvZiB3aW5kb3chPT1cInVuZGVmaW5lZFwiP3dpbmRvdzp7fSl9LHtcImJhc2U2NC1qc1wiOjIsaWVlZTc1NDozNyxpc2FycmF5OjQwfV0sNjpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7KGZ1bmN0aW9uKEJ1ZmZlcil7ZnVuY3Rpb24gaXNBcnJheShhcmcpe2lmKEFycmF5LmlzQXJyYXkpe3JldHVybiBBcnJheS5pc0FycmF5KGFyZyl9cmV0dXJuIG9iamVjdFRvU3RyaW5nKGFyZyk9PT1cIltvYmplY3QgQXJyYXldXCJ9ZXhwb3J0cy5pc0FycmF5PWlzQXJyYXk7ZnVuY3Rpb24gaXNCb29sZWFuKGFyZyl7cmV0dXJuIHR5cGVvZiBhcmc9PT1cImJvb2xlYW5cIn1leHBvcnRzLmlzQm9vbGVhbj1pc0Jvb2xlYW47ZnVuY3Rpb24gaXNOdWxsKGFyZyl7cmV0dXJuIGFyZz09PW51bGx9ZXhwb3J0cy5pc051bGw9aXNOdWxsO2Z1bmN0aW9uIGlzTnVsbE9yVW5kZWZpbmVkKGFyZyl7cmV0dXJuIGFyZz09bnVsbH1leHBvcnRzLmlzTnVsbE9yVW5kZWZpbmVkPWlzTnVsbE9yVW5kZWZpbmVkO2Z1bmN0aW9uIGlzTnVtYmVyKGFyZyl7cmV0dXJuIHR5cGVvZiBhcmc9PT1cIm51bWJlclwifWV4cG9ydHMuaXNOdW1iZXI9aXNOdW1iZXI7ZnVuY3Rpb24gaXNTdHJpbmcoYXJnKXtyZXR1cm4gdHlwZW9mIGFyZz09PVwic3RyaW5nXCJ9ZXhwb3J0cy5pc1N0cmluZz1pc1N0cmluZztmdW5jdGlvbiBpc1N5bWJvbChhcmcpe3JldHVybiB0eXBlb2YgYXJnPT09XCJzeW1ib2xcIn1leHBvcnRzLmlzU3ltYm9sPWlzU3ltYm9sO2Z1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZyl7cmV0dXJuIGFyZz09PXZvaWQgMH1leHBvcnRzLmlzVW5kZWZpbmVkPWlzVW5kZWZpbmVkO2Z1bmN0aW9uIGlzUmVnRXhwKHJlKXtyZXR1cm4gb2JqZWN0VG9TdHJpbmcocmUpPT09XCJbb2JqZWN0IFJlZ0V4cF1cIn1leHBvcnRzLmlzUmVnRXhwPWlzUmVnRXhwO2Z1bmN0aW9uIGlzT2JqZWN0KGFyZyl7cmV0dXJuIHR5cGVvZiBhcmc9PT1cIm9iamVjdFwiJiZhcmchPT1udWxsfWV4cG9ydHMuaXNPYmplY3Q9aXNPYmplY3Q7ZnVuY3Rpb24gaXNEYXRlKGQpe3JldHVybiBvYmplY3RUb1N0cmluZyhkKT09PVwiW29iamVjdCBEYXRlXVwifWV4cG9ydHMuaXNEYXRlPWlzRGF0ZTtmdW5jdGlvbiBpc0Vycm9yKGUpe3JldHVybiBvYmplY3RUb1N0cmluZyhlKT09PVwiW29iamVjdCBFcnJvcl1cInx8ZSBpbnN0YW5jZW9mIEVycm9yfWV4cG9ydHMuaXNFcnJvcj1pc0Vycm9yO2Z1bmN0aW9uIGlzRnVuY3Rpb24oYXJnKXtyZXR1cm4gdHlwZW9mIGFyZz09PVwiZnVuY3Rpb25cIn1leHBvcnRzLmlzRnVuY3Rpb249aXNGdW5jdGlvbjtmdW5jdGlvbiBpc1ByaW1pdGl2ZShhcmcpe3JldHVybiBhcmc9PT1udWxsfHx0eXBlb2YgYXJnPT09XCJib29sZWFuXCJ8fHR5cGVvZiBhcmc9PT1cIm51bWJlclwifHx0eXBlb2YgYXJnPT09XCJzdHJpbmdcInx8dHlwZW9mIGFyZz09PVwic3ltYm9sXCJ8fHR5cGVvZiBhcmc9PT1cInVuZGVmaW5lZFwifWV4cG9ydHMuaXNQcmltaXRpdmU9aXNQcmltaXRpdmU7ZXhwb3J0cy5pc0J1ZmZlcj1CdWZmZXIuaXNCdWZmZXI7ZnVuY3Rpb24gb2JqZWN0VG9TdHJpbmcobyl7cmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKX19KS5jYWxsKHRoaXMse2lzQnVmZmVyOnJlcXVpcmUoXCIuLi8uLi9pcy1idWZmZXIvaW5kZXguanNcIil9KX0se1wiLi4vLi4vaXMtYnVmZmVyL2luZGV4LmpzXCI6Mzl9XSw3OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXt2YXIgRWxlbWVudFR5cGU9cmVxdWlyZShcImRvbWVsZW1lbnR0eXBlXCIpO3ZhciBlbnRpdGllcz1yZXF1aXJlKFwiZW50aXRpZXNcIik7dmFyIGJvb2xlYW5BdHRyaWJ1dGVzPXtfX3Byb3RvX186bnVsbCxhbGxvd2Z1bGxzY3JlZW46dHJ1ZSxhc3luYzp0cnVlLGF1dG9mb2N1czp0cnVlLGF1dG9wbGF5OnRydWUsY2hlY2tlZDp0cnVlLGNvbnRyb2xzOnRydWUsZGVmYXVsdDp0cnVlLGRlZmVyOnRydWUsZGlzYWJsZWQ6dHJ1ZSxoaWRkZW46dHJ1ZSxpc21hcDp0cnVlLGxvb3A6dHJ1ZSxtdWx0aXBsZTp0cnVlLG11dGVkOnRydWUsb3Blbjp0cnVlLHJlYWRvbmx5OnRydWUscmVxdWlyZWQ6dHJ1ZSxyZXZlcnNlZDp0cnVlLHNjb3BlZDp0cnVlLHNlYW1sZXNzOnRydWUsc2VsZWN0ZWQ6dHJ1ZSx0eXBlbXVzdG1hdGNoOnRydWV9O3ZhciB1bmVuY29kZWRFbGVtZW50cz17X19wcm90b19fOm51bGwsc3R5bGU6dHJ1ZSxzY3JpcHQ6dHJ1ZSx4bXA6dHJ1ZSxpZnJhbWU6dHJ1ZSxub2VtYmVkOnRydWUsbm9mcmFtZXM6dHJ1ZSxwbGFpbnRleHQ6dHJ1ZSxub3NjcmlwdDp0cnVlfTtmdW5jdGlvbiBmb3JtYXRBdHRycyhhdHRyaWJ1dGVzLG9wdHMpe2lmKCFhdHRyaWJ1dGVzKXJldHVybjt2YXIgb3V0cHV0PVwiXCIsdmFsdWU7Zm9yKHZhciBrZXkgaW4gYXR0cmlidXRlcyl7dmFsdWU9YXR0cmlidXRlc1trZXldO2lmKG91dHB1dCl7b3V0cHV0Kz1cIiBcIn1pZighdmFsdWUmJmJvb2xlYW5BdHRyaWJ1dGVzW2tleV0pe291dHB1dCs9a2V5fWVsc2V7b3V0cHV0Kz1rZXkrJz1cIicrKG9wdHMuZGVjb2RlRW50aXRpZXM/ZW50aXRpZXMuZW5jb2RlWE1MKHZhbHVlKTp2YWx1ZSkrJ1wiJ319cmV0dXJuIG91dHB1dH12YXIgc2luZ2xlVGFnPXtfX3Byb3RvX186bnVsbCxhcmVhOnRydWUsYmFzZTp0cnVlLGJhc2Vmb250OnRydWUsYnI6dHJ1ZSxjb2w6dHJ1ZSxjb21tYW5kOnRydWUsZW1iZWQ6dHJ1ZSxmcmFtZTp0cnVlLGhyOnRydWUsaW1nOnRydWUsaW5wdXQ6dHJ1ZSxpc2luZGV4OnRydWUsa2V5Z2VuOnRydWUsbGluazp0cnVlLG1ldGE6dHJ1ZSxwYXJhbTp0cnVlLHNvdXJjZTp0cnVlLHRyYWNrOnRydWUsd2JyOnRydWV9O3ZhciByZW5kZXI9bW9kdWxlLmV4cG9ydHM9ZnVuY3Rpb24oZG9tLG9wdHMpe2lmKCFBcnJheS5pc0FycmF5KGRvbSkmJiFkb20uY2hlZXJpbylkb209W2RvbV07b3B0cz1vcHRzfHx7fTt2YXIgb3V0cHV0PVwiXCI7Zm9yKHZhciBpPTA7aTxkb20ubGVuZ3RoO2krKyl7dmFyIGVsZW09ZG9tW2ldO2lmKGVsZW0udHlwZT09PVwicm9vdFwiKW91dHB1dCs9cmVuZGVyKGVsZW0uY2hpbGRyZW4sb3B0cyk7ZWxzZSBpZihFbGVtZW50VHlwZS5pc1RhZyhlbGVtKSlvdXRwdXQrPXJlbmRlclRhZyhlbGVtLG9wdHMpO2Vsc2UgaWYoZWxlbS50eXBlPT09RWxlbWVudFR5cGUuRGlyZWN0aXZlKW91dHB1dCs9cmVuZGVyRGlyZWN0aXZlKGVsZW0pO2Vsc2UgaWYoZWxlbS50eXBlPT09RWxlbWVudFR5cGUuQ29tbWVudClvdXRwdXQrPXJlbmRlckNvbW1lbnQoZWxlbSk7ZWxzZSBpZihlbGVtLnR5cGU9PT1FbGVtZW50VHlwZS5DREFUQSlvdXRwdXQrPXJlbmRlckNkYXRhKGVsZW0pO2Vsc2Ugb3V0cHV0Kz1yZW5kZXJUZXh0KGVsZW0sb3B0cyl9cmV0dXJuIG91dHB1dH07ZnVuY3Rpb24gcmVuZGVyVGFnKGVsZW0sb3B0cyl7aWYoZWxlbS5uYW1lPT09XCJzdmdcIilvcHRzPXtkZWNvZGVFbnRpdGllczpvcHRzLmRlY29kZUVudGl0aWVzLHhtbE1vZGU6dHJ1ZX07dmFyIHRhZz1cIjxcIitlbGVtLm5hbWUsYXR0cmlicz1mb3JtYXRBdHRycyhlbGVtLmF0dHJpYnMsb3B0cyk7aWYoYXR0cmlicyl7dGFnKz1cIiBcIithdHRyaWJzfWlmKG9wdHMueG1sTW9kZSYmKCFlbGVtLmNoaWxkcmVufHxlbGVtLmNoaWxkcmVuLmxlbmd0aD09PTApKXt0YWcrPVwiLz5cIn1lbHNle3RhZys9XCI+XCI7aWYoZWxlbS5jaGlsZHJlbil7dGFnKz1yZW5kZXIoZWxlbS5jaGlsZHJlbixvcHRzKX1pZighc2luZ2xlVGFnW2VsZW0ubmFtZV18fG9wdHMueG1sTW9kZSl7dGFnKz1cIjwvXCIrZWxlbS5uYW1lK1wiPlwifX1yZXR1cm4gdGFnfWZ1bmN0aW9uIHJlbmRlckRpcmVjdGl2ZShlbGVtKXtyZXR1cm5cIjxcIitlbGVtLmRhdGErXCI+XCJ9ZnVuY3Rpb24gcmVuZGVyVGV4dChlbGVtLG9wdHMpe3ZhciBkYXRhPWVsZW0uZGF0YXx8XCJcIjtpZihvcHRzLmRlY29kZUVudGl0aWVzJiYhKGVsZW0ucGFyZW50JiZlbGVtLnBhcmVudC5uYW1lIGluIHVuZW5jb2RlZEVsZW1lbnRzKSl7ZGF0YT1lbnRpdGllcy5lbmNvZGVYTUwoZGF0YSl9cmV0dXJuIGRhdGF9ZnVuY3Rpb24gcmVuZGVyQ2RhdGEoZWxlbSl7cmV0dXJuXCI8IVtDREFUQVtcIitlbGVtLmNoaWxkcmVuWzBdLmRhdGErXCJdXT5cIn1mdW5jdGlvbiByZW5kZXJDb21tZW50KGVsZW0pe3JldHVyblwiPCEtLVwiK2VsZW0uZGF0YStcIi0tPlwifX0se2RvbWVsZW1lbnR0eXBlOjgsZW50aXRpZXM6MjB9XSw4OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXttb2R1bGUuZXhwb3J0cz17VGV4dDpcInRleHRcIixEaXJlY3RpdmU6XCJkaXJlY3RpdmVcIixDb21tZW50OlwiY29tbWVudFwiLFNjcmlwdDpcInNjcmlwdFwiLFN0eWxlOlwic3R5bGVcIixUYWc6XCJ0YWdcIixDREFUQTpcImNkYXRhXCIsaXNUYWc6ZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGVsZW0udHlwZT09PVwidGFnXCJ8fGVsZW0udHlwZT09PVwic2NyaXB0XCJ8fGVsZW0udHlwZT09PVwic3R5bGVcIn19fSx7fV0sOTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7bW9kdWxlLmV4cG9ydHM9e1RleHQ6XCJ0ZXh0XCIsRGlyZWN0aXZlOlwiZGlyZWN0aXZlXCIsQ29tbWVudDpcImNvbW1lbnRcIixTY3JpcHQ6XCJzY3JpcHRcIixTdHlsZTpcInN0eWxlXCIsVGFnOlwidGFnXCIsQ0RBVEE6XCJjZGF0YVwiLERvY3R5cGU6XCJkb2N0eXBlXCIsaXNUYWc6ZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGVsZW0udHlwZT09PVwidGFnXCJ8fGVsZW0udHlwZT09PVwic2NyaXB0XCJ8fGVsZW0udHlwZT09PVwic3R5bGVcIn19fSx7fV0sMTA6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe3ZhciBFbGVtZW50VHlwZT1yZXF1aXJlKFwiZG9tZWxlbWVudHR5cGVcIik7dmFyIHJlX3doaXRlc3BhY2U9L1xccysvZzt2YXIgTm9kZVByb3RvdHlwZT1yZXF1aXJlKFwiLi9saWIvbm9kZVwiKTt2YXIgRWxlbWVudFByb3RvdHlwZT1yZXF1aXJlKFwiLi9saWIvZWxlbWVudFwiKTtmdW5jdGlvbiBEb21IYW5kbGVyKGNhbGxiYWNrLG9wdGlvbnMsZWxlbWVudENCKXtpZih0eXBlb2YgY2FsbGJhY2s9PT1cIm9iamVjdFwiKXtlbGVtZW50Q0I9b3B0aW9ucztvcHRpb25zPWNhbGxiYWNrO2NhbGxiYWNrPW51bGx9ZWxzZSBpZih0eXBlb2Ygb3B0aW9ucz09PVwiZnVuY3Rpb25cIil7ZWxlbWVudENCPW9wdGlvbnM7b3B0aW9ucz1kZWZhdWx0T3B0c310aGlzLl9jYWxsYmFjaz1jYWxsYmFjazt0aGlzLl9vcHRpb25zPW9wdGlvbnN8fGRlZmF1bHRPcHRzO3RoaXMuX2VsZW1lbnRDQj1lbGVtZW50Q0I7dGhpcy5kb209W107dGhpcy5fZG9uZT1mYWxzZTt0aGlzLl90YWdTdGFjaz1bXTt0aGlzLl9wYXJzZXI9dGhpcy5fcGFyc2VyfHxudWxsfXZhciBkZWZhdWx0T3B0cz17bm9ybWFsaXplV2hpdGVzcGFjZTpmYWxzZSx3aXRoU3RhcnRJbmRpY2VzOmZhbHNlfTtEb21IYW5kbGVyLnByb3RvdHlwZS5vbnBhcnNlcmluaXQ9ZnVuY3Rpb24ocGFyc2VyKXt0aGlzLl9wYXJzZXI9cGFyc2VyfTtEb21IYW5kbGVyLnByb3RvdHlwZS5vbnJlc2V0PWZ1bmN0aW9uKCl7RG9tSGFuZGxlci5jYWxsKHRoaXMsdGhpcy5fY2FsbGJhY2ssdGhpcy5fb3B0aW9ucyx0aGlzLl9lbGVtZW50Q0IpfTtEb21IYW5kbGVyLnByb3RvdHlwZS5vbmVuZD1mdW5jdGlvbigpe2lmKHRoaXMuX2RvbmUpcmV0dXJuO3RoaXMuX2RvbmU9dHJ1ZTt0aGlzLl9wYXJzZXI9bnVsbDt0aGlzLl9oYW5kbGVDYWxsYmFjayhudWxsKX07RG9tSGFuZGxlci5wcm90b3R5cGUuX2hhbmRsZUNhbGxiYWNrPURvbUhhbmRsZXIucHJvdG90eXBlLm9uZXJyb3I9ZnVuY3Rpb24oZXJyb3Ipe2lmKHR5cGVvZiB0aGlzLl9jYWxsYmFjaz09PVwiZnVuY3Rpb25cIil7dGhpcy5fY2FsbGJhY2soZXJyb3IsdGhpcy5kb20pfWVsc2V7aWYoZXJyb3IpdGhyb3cgZXJyb3J9fTtEb21IYW5kbGVyLnByb3RvdHlwZS5vbmNsb3NldGFnPWZ1bmN0aW9uKCl7dmFyIGVsZW09dGhpcy5fdGFnU3RhY2sucG9wKCk7aWYodGhpcy5fZWxlbWVudENCKXRoaXMuX2VsZW1lbnRDQihlbGVtKX07RG9tSGFuZGxlci5wcm90b3R5cGUuX2FkZERvbUVsZW1lbnQ9ZnVuY3Rpb24oZWxlbWVudCl7dmFyIHBhcmVudD10aGlzLl90YWdTdGFja1t0aGlzLl90YWdTdGFjay5sZW5ndGgtMV07dmFyIHNpYmxpbmdzPXBhcmVudD9wYXJlbnQuY2hpbGRyZW46dGhpcy5kb207dmFyIHByZXZpb3VzU2libGluZz1zaWJsaW5nc1tzaWJsaW5ncy5sZW5ndGgtMV07ZWxlbWVudC5uZXh0PW51bGw7aWYodGhpcy5fb3B0aW9ucy53aXRoU3RhcnRJbmRpY2VzKXtlbGVtZW50LnN0YXJ0SW5kZXg9dGhpcy5fcGFyc2VyLnN0YXJ0SW5kZXh9aWYodGhpcy5fb3B0aW9ucy53aXRoRG9tTHZsMSl7ZWxlbWVudC5fX3Byb3RvX189ZWxlbWVudC50eXBlPT09XCJ0YWdcIj9FbGVtZW50UHJvdG90eXBlOk5vZGVQcm90b3R5cGV9aWYocHJldmlvdXNTaWJsaW5nKXtlbGVtZW50LnByZXY9cHJldmlvdXNTaWJsaW5nO3ByZXZpb3VzU2libGluZy5uZXh0PWVsZW1lbnR9ZWxzZXtlbGVtZW50LnByZXY9bnVsbH1zaWJsaW5ncy5wdXNoKGVsZW1lbnQpO2VsZW1lbnQucGFyZW50PXBhcmVudHx8bnVsbH07RG9tSGFuZGxlci5wcm90b3R5cGUub25vcGVudGFnPWZ1bmN0aW9uKG5hbWUsYXR0cmlicyl7dmFyIGVsZW1lbnQ9e3R5cGU6bmFtZT09PVwic2NyaXB0XCI/RWxlbWVudFR5cGUuU2NyaXB0Om5hbWU9PT1cInN0eWxlXCI/RWxlbWVudFR5cGUuU3R5bGU6RWxlbWVudFR5cGUuVGFnLG5hbWU6bmFtZSxhdHRyaWJzOmF0dHJpYnMsY2hpbGRyZW46W119O3RoaXMuX2FkZERvbUVsZW1lbnQoZWxlbWVudCk7dGhpcy5fdGFnU3RhY2sucHVzaChlbGVtZW50KX07RG9tSGFuZGxlci5wcm90b3R5cGUub250ZXh0PWZ1bmN0aW9uKGRhdGEpe3ZhciBub3JtYWxpemU9dGhpcy5fb3B0aW9ucy5ub3JtYWxpemVXaGl0ZXNwYWNlfHx0aGlzLl9vcHRpb25zLmlnbm9yZVdoaXRlc3BhY2U7dmFyIGxhc3RUYWc7aWYoIXRoaXMuX3RhZ1N0YWNrLmxlbmd0aCYmdGhpcy5kb20ubGVuZ3RoJiYobGFzdFRhZz10aGlzLmRvbVt0aGlzLmRvbS5sZW5ndGgtMV0pLnR5cGU9PT1FbGVtZW50VHlwZS5UZXh0KXtpZihub3JtYWxpemUpe2xhc3RUYWcuZGF0YT0obGFzdFRhZy5kYXRhK2RhdGEpLnJlcGxhY2UocmVfd2hpdGVzcGFjZSxcIiBcIil9ZWxzZXtsYXN0VGFnLmRhdGErPWRhdGF9fWVsc2V7aWYodGhpcy5fdGFnU3RhY2subGVuZ3RoJiYobGFzdFRhZz10aGlzLl90YWdTdGFja1t0aGlzLl90YWdTdGFjay5sZW5ndGgtMV0pJiYobGFzdFRhZz1sYXN0VGFnLmNoaWxkcmVuW2xhc3RUYWcuY2hpbGRyZW4ubGVuZ3RoLTFdKSYmbGFzdFRhZy50eXBlPT09RWxlbWVudFR5cGUuVGV4dCl7aWYobm9ybWFsaXplKXtsYXN0VGFnLmRhdGE9KGxhc3RUYWcuZGF0YStkYXRhKS5yZXBsYWNlKHJlX3doaXRlc3BhY2UsXCIgXCIpfWVsc2V7bGFzdFRhZy5kYXRhKz1kYXRhfX1lbHNle2lmKG5vcm1hbGl6ZSl7ZGF0YT1kYXRhLnJlcGxhY2UocmVfd2hpdGVzcGFjZSxcIiBcIil9dGhpcy5fYWRkRG9tRWxlbWVudCh7ZGF0YTpkYXRhLHR5cGU6RWxlbWVudFR5cGUuVGV4dH0pfX19O0RvbUhhbmRsZXIucHJvdG90eXBlLm9uY29tbWVudD1mdW5jdGlvbihkYXRhKXt2YXIgbGFzdFRhZz10aGlzLl90YWdTdGFja1t0aGlzLl90YWdTdGFjay5sZW5ndGgtMV07aWYobGFzdFRhZyYmbGFzdFRhZy50eXBlPT09RWxlbWVudFR5cGUuQ29tbWVudCl7bGFzdFRhZy5kYXRhKz1kYXRhO3JldHVybn12YXIgZWxlbWVudD17ZGF0YTpkYXRhLHR5cGU6RWxlbWVudFR5cGUuQ29tbWVudH07dGhpcy5fYWRkRG9tRWxlbWVudChlbGVtZW50KTt0aGlzLl90YWdTdGFjay5wdXNoKGVsZW1lbnQpfTtEb21IYW5kbGVyLnByb3RvdHlwZS5vbmNkYXRhc3RhcnQ9ZnVuY3Rpb24oKXt2YXIgZWxlbWVudD17Y2hpbGRyZW46W3tkYXRhOlwiXCIsdHlwZTpFbGVtZW50VHlwZS5UZXh0fV0sdHlwZTpFbGVtZW50VHlwZS5DREFUQX07dGhpcy5fYWRkRG9tRWxlbWVudChlbGVtZW50KTt0aGlzLl90YWdTdGFjay5wdXNoKGVsZW1lbnQpfTtEb21IYW5kbGVyLnByb3RvdHlwZS5vbmNvbW1lbnRlbmQ9RG9tSGFuZGxlci5wcm90b3R5cGUub25jZGF0YWVuZD1mdW5jdGlvbigpe3RoaXMuX3RhZ1N0YWNrLnBvcCgpfTtEb21IYW5kbGVyLnByb3RvdHlwZS5vbnByb2Nlc3NpbmdpbnN0cnVjdGlvbj1mdW5jdGlvbihuYW1lLGRhdGEpe3RoaXMuX2FkZERvbUVsZW1lbnQoe25hbWU6bmFtZSxkYXRhOmRhdGEsdHlwZTpFbGVtZW50VHlwZS5EaXJlY3RpdmV9KX07bW9kdWxlLmV4cG9ydHM9RG9tSGFuZGxlcn0se1wiLi9saWIvZWxlbWVudFwiOjExLFwiLi9saWIvbm9kZVwiOjEyLGRvbWVsZW1lbnR0eXBlOjl9XSwxMTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7dmFyIE5vZGVQcm90b3R5cGU9cmVxdWlyZShcIi4vbm9kZVwiKTt2YXIgRWxlbWVudFByb3RvdHlwZT1tb2R1bGUuZXhwb3J0cz1PYmplY3QuY3JlYXRlKE5vZGVQcm90b3R5cGUpO3ZhciBkb21MdmwxPXt0YWdOYW1lOlwibmFtZVwifTtPYmplY3Qua2V5cyhkb21MdmwxKS5mb3JFYWNoKGZ1bmN0aW9uKGtleSl7dmFyIHNob3J0aGFuZD1kb21MdmwxW2tleV07T2JqZWN0LmRlZmluZVByb3BlcnR5KEVsZW1lbnRQcm90b3R5cGUsa2V5LHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc1tzaG9ydGhhbmRdfHxudWxsfSxzZXQ6ZnVuY3Rpb24odmFsKXt0aGlzW3Nob3J0aGFuZF09dmFsO3JldHVybiB2YWx9fSl9KX0se1wiLi9ub2RlXCI6MTJ9XSwxMjpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7dmFyIE5vZGVQcm90b3R5cGU9bW9kdWxlLmV4cG9ydHM9e2dldCBmaXJzdENoaWxkKCl7dmFyIGNoaWxkcmVuPXRoaXMuY2hpbGRyZW47cmV0dXJuIGNoaWxkcmVuJiZjaGlsZHJlblswXXx8bnVsbH0sZ2V0IGxhc3RDaGlsZCgpe3ZhciBjaGlsZHJlbj10aGlzLmNoaWxkcmVuO3JldHVybiBjaGlsZHJlbiYmY2hpbGRyZW5bY2hpbGRyZW4ubGVuZ3RoLTFdfHxudWxsfSxnZXQgbm9kZVR5cGUoKXtyZXR1cm4gbm9kZVR5cGVzW3RoaXMudHlwZV18fG5vZGVUeXBlcy5lbGVtZW50fX07dmFyIGRvbUx2bDE9e3RhZ05hbWU6XCJuYW1lXCIsY2hpbGROb2RlczpcImNoaWxkcmVuXCIscGFyZW50Tm9kZTpcInBhcmVudFwiLHByZXZpb3VzU2libGluZzpcInByZXZcIixuZXh0U2libGluZzpcIm5leHRcIixub2RlVmFsdWU6XCJkYXRhXCJ9O3ZhciBub2RlVHlwZXM9e2VsZW1lbnQ6MSx0ZXh0OjMsY2RhdGE6NCxjb21tZW50Ojh9O09iamVjdC5rZXlzKGRvbUx2bDEpLmZvckVhY2goZnVuY3Rpb24oa2V5KXt2YXIgc2hvcnRoYW5kPWRvbUx2bDFba2V5XTtPYmplY3QuZGVmaW5lUHJvcGVydHkoTm9kZVByb3RvdHlwZSxrZXkse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzW3Nob3J0aGFuZF18fG51bGx9LHNldDpmdW5jdGlvbih2YWwpe3RoaXNbc2hvcnRoYW5kXT12YWw7cmV0dXJuIHZhbH19KX0pfSx7fV0sMTM6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe3ZhciBEb21VdGlscz1tb2R1bGUuZXhwb3J0cztbcmVxdWlyZShcIi4vbGliL3N0cmluZ2lmeVwiKSxyZXF1aXJlKFwiLi9saWIvdHJhdmVyc2FsXCIpLHJlcXVpcmUoXCIuL2xpYi9tYW5pcHVsYXRpb25cIikscmVxdWlyZShcIi4vbGliL3F1ZXJ5aW5nXCIpLHJlcXVpcmUoXCIuL2xpYi9sZWdhY3lcIikscmVxdWlyZShcIi4vbGliL2hlbHBlcnNcIildLmZvckVhY2goZnVuY3Rpb24oZXh0KXtPYmplY3Qua2V5cyhleHQpLmZvckVhY2goZnVuY3Rpb24oa2V5KXtEb21VdGlsc1trZXldPWV4dFtrZXldLmJpbmQoRG9tVXRpbHMpfSl9KX0se1wiLi9saWIvaGVscGVyc1wiOjE0LFwiLi9saWIvbGVnYWN5XCI6MTUsXCIuL2xpYi9tYW5pcHVsYXRpb25cIjoxNixcIi4vbGliL3F1ZXJ5aW5nXCI6MTcsXCIuL2xpYi9zdHJpbmdpZnlcIjoxOCxcIi4vbGliL3RyYXZlcnNhbFwiOjE5fV0sMTQ6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe2V4cG9ydHMucmVtb3ZlU3Vic2V0cz1mdW5jdGlvbihub2Rlcyl7dmFyIGlkeD1ub2Rlcy5sZW5ndGgsbm9kZSxhbmNlc3RvcixyZXBsYWNlO3doaWxlKC0taWR4Pi0xKXtub2RlPWFuY2VzdG9yPW5vZGVzW2lkeF07bm9kZXNbaWR4XT1udWxsO3JlcGxhY2U9dHJ1ZTt3aGlsZShhbmNlc3Rvcil7aWYobm9kZXMuaW5kZXhPZihhbmNlc3Rvcik+LTEpe3JlcGxhY2U9ZmFsc2U7bm9kZXMuc3BsaWNlKGlkeCwxKTticmVha31hbmNlc3Rvcj1hbmNlc3Rvci5wYXJlbnR9aWYocmVwbGFjZSl7bm9kZXNbaWR4XT1ub2RlfX1yZXR1cm4gbm9kZXN9O3ZhciBQT1NJVElPTj17RElTQ09OTkVDVEVEOjEsUFJFQ0VESU5HOjIsRk9MTE9XSU5HOjQsQ09OVEFJTlM6OCxDT05UQUlORURfQlk6MTZ9O3ZhciBjb21wYXJlUG9zPWV4cG9ydHMuY29tcGFyZURvY3VtZW50UG9zaXRpb249ZnVuY3Rpb24obm9kZUEsbm9kZUIpe3ZhciBhUGFyZW50cz1bXTt2YXIgYlBhcmVudHM9W107dmFyIGN1cnJlbnQsc2hhcmVkUGFyZW50LHNpYmxpbmdzLGFTaWJsaW5nLGJTaWJsaW5nLGlkeDtpZihub2RlQT09PW5vZGVCKXtyZXR1cm4gMH1jdXJyZW50PW5vZGVBO3doaWxlKGN1cnJlbnQpe2FQYXJlbnRzLnVuc2hpZnQoY3VycmVudCk7Y3VycmVudD1jdXJyZW50LnBhcmVudH1jdXJyZW50PW5vZGVCO3doaWxlKGN1cnJlbnQpe2JQYXJlbnRzLnVuc2hpZnQoY3VycmVudCk7Y3VycmVudD1jdXJyZW50LnBhcmVudH1pZHg9MDt3aGlsZShhUGFyZW50c1tpZHhdPT09YlBhcmVudHNbaWR4XSl7aWR4Kyt9aWYoaWR4PT09MCl7cmV0dXJuIFBPU0lUSU9OLkRJU0NPTk5FQ1RFRH1zaGFyZWRQYXJlbnQ9YVBhcmVudHNbaWR4LTFdO3NpYmxpbmdzPXNoYXJlZFBhcmVudC5jaGlsZHJlbjthU2libGluZz1hUGFyZW50c1tpZHhdO2JTaWJsaW5nPWJQYXJlbnRzW2lkeF07aWYoc2libGluZ3MuaW5kZXhPZihhU2libGluZyk+c2libGluZ3MuaW5kZXhPZihiU2libGluZykpe2lmKHNoYXJlZFBhcmVudD09PW5vZGVCKXtyZXR1cm4gUE9TSVRJT04uRk9MTE9XSU5HfFBPU0lUSU9OLkNPTlRBSU5FRF9CWX1yZXR1cm4gUE9TSVRJT04uRk9MTE9XSU5HfWVsc2V7aWYoc2hhcmVkUGFyZW50PT09bm9kZUEpe3JldHVybiBQT1NJVElPTi5QUkVDRURJTkd8UE9TSVRJT04uQ09OVEFJTlN9cmV0dXJuIFBPU0lUSU9OLlBSRUNFRElOR319O2V4cG9ydHMudW5pcXVlU29ydD1mdW5jdGlvbihub2Rlcyl7dmFyIGlkeD1ub2Rlcy5sZW5ndGgsbm9kZSxwb3NpdGlvbjtub2Rlcz1ub2Rlcy5zbGljZSgpO3doaWxlKC0taWR4Pi0xKXtub2RlPW5vZGVzW2lkeF07cG9zaXRpb249bm9kZXMuaW5kZXhPZihub2RlKTtpZihwb3NpdGlvbj4tMSYmcG9zaXRpb248aWR4KXtub2Rlcy5zcGxpY2UoaWR4LDEpfX1ub2Rlcy5zb3J0KGZ1bmN0aW9uKGEsYil7dmFyIHJlbGF0aXZlPWNvbXBhcmVQb3MoYSxiKTtpZihyZWxhdGl2ZSZQT1NJVElPTi5QUkVDRURJTkcpe3JldHVybi0xfWVsc2UgaWYocmVsYXRpdmUmUE9TSVRJT04uRk9MTE9XSU5HKXtyZXR1cm4gMX1yZXR1cm4gMH0pO3JldHVybiBub2Rlc319LHt9XSwxNTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7dmFyIEVsZW1lbnRUeXBlPXJlcXVpcmUoXCJkb21lbGVtZW50dHlwZVwiKTt2YXIgaXNUYWc9ZXhwb3J0cy5pc1RhZz1FbGVtZW50VHlwZS5pc1RhZztleHBvcnRzLnRlc3RFbGVtZW50PWZ1bmN0aW9uKG9wdGlvbnMsZWxlbWVudCl7Zm9yKHZhciBrZXkgaW4gb3B0aW9ucyl7aWYoIW9wdGlvbnMuaGFzT3duUHJvcGVydHkoa2V5KSk7ZWxzZSBpZihrZXk9PT1cInRhZ19uYW1lXCIpe2lmKCFpc1RhZyhlbGVtZW50KXx8IW9wdGlvbnMudGFnX25hbWUoZWxlbWVudC5uYW1lKSl7cmV0dXJuIGZhbHNlfX1lbHNlIGlmKGtleT09PVwidGFnX3R5cGVcIil7aWYoIW9wdGlvbnMudGFnX3R5cGUoZWxlbWVudC50eXBlKSlyZXR1cm4gZmFsc2V9ZWxzZSBpZihrZXk9PT1cInRhZ19jb250YWluc1wiKXtpZihpc1RhZyhlbGVtZW50KXx8IW9wdGlvbnMudGFnX2NvbnRhaW5zKGVsZW1lbnQuZGF0YSkpe3JldHVybiBmYWxzZX19ZWxzZSBpZighZWxlbWVudC5hdHRyaWJzfHwhb3B0aW9uc1trZXldKGVsZW1lbnQuYXR0cmlic1trZXldKSl7cmV0dXJuIGZhbHNlfX1yZXR1cm4gdHJ1ZX07dmFyIENoZWNrcz17dGFnX25hbWU6ZnVuY3Rpb24obmFtZSl7aWYodHlwZW9mIG5hbWU9PT1cImZ1bmN0aW9uXCIpe3JldHVybiBmdW5jdGlvbihlbGVtKXtyZXR1cm4gaXNUYWcoZWxlbSkmJm5hbWUoZWxlbS5uYW1lKX19ZWxzZSBpZihuYW1lPT09XCIqXCIpe3JldHVybiBpc1RhZ31lbHNle3JldHVybiBmdW5jdGlvbihlbGVtKXtyZXR1cm4gaXNUYWcoZWxlbSkmJmVsZW0ubmFtZT09PW5hbWV9fX0sdGFnX3R5cGU6ZnVuY3Rpb24odHlwZSl7aWYodHlwZW9mIHR5cGU9PT1cImZ1bmN0aW9uXCIpe3JldHVybiBmdW5jdGlvbihlbGVtKXtyZXR1cm4gdHlwZShlbGVtLnR5cGUpfX1lbHNle3JldHVybiBmdW5jdGlvbihlbGVtKXtyZXR1cm4gZWxlbS50eXBlPT09dHlwZX19fSx0YWdfY29udGFpbnM6ZnVuY3Rpb24oZGF0YSl7aWYodHlwZW9mIGRhdGE9PT1cImZ1bmN0aW9uXCIpe3JldHVybiBmdW5jdGlvbihlbGVtKXtyZXR1cm4haXNUYWcoZWxlbSkmJmRhdGEoZWxlbS5kYXRhKX19ZWxzZXtyZXR1cm4gZnVuY3Rpb24oZWxlbSl7cmV0dXJuIWlzVGFnKGVsZW0pJiZlbGVtLmRhdGE9PT1kYXRhfX19fTtmdW5jdGlvbiBnZXRBdHRyaWJDaGVjayhhdHRyaWIsdmFsdWUpe2lmKHR5cGVvZiB2YWx1ZT09PVwiZnVuY3Rpb25cIil7cmV0dXJuIGZ1bmN0aW9uKGVsZW0pe3JldHVybiBlbGVtLmF0dHJpYnMmJnZhbHVlKGVsZW0uYXR0cmlic1thdHRyaWJdKX19ZWxzZXtyZXR1cm4gZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGVsZW0uYXR0cmlicyYmZWxlbS5hdHRyaWJzW2F0dHJpYl09PT12YWx1ZX19fWZ1bmN0aW9uIGNvbWJpbmVGdW5jcyhhLGIpe3JldHVybiBmdW5jdGlvbihlbGVtKXtyZXR1cm4gYShlbGVtKXx8YihlbGVtKX19ZXhwb3J0cy5nZXRFbGVtZW50cz1mdW5jdGlvbihvcHRpb25zLGVsZW1lbnQscmVjdXJzZSxsaW1pdCl7dmFyIGZ1bmNzPU9iamVjdC5rZXlzKG9wdGlvbnMpLm1hcChmdW5jdGlvbihrZXkpe3ZhciB2YWx1ZT1vcHRpb25zW2tleV07cmV0dXJuIGtleSBpbiBDaGVja3M/Q2hlY2tzW2tleV0odmFsdWUpOmdldEF0dHJpYkNoZWNrKGtleSx2YWx1ZSl9KTtyZXR1cm4gZnVuY3MubGVuZ3RoPT09MD9bXTp0aGlzLmZpbHRlcihmdW5jcy5yZWR1Y2UoY29tYmluZUZ1bmNzKSxlbGVtZW50LHJlY3Vyc2UsbGltaXQpfTtleHBvcnRzLmdldEVsZW1lbnRCeUlkPWZ1bmN0aW9uKGlkLGVsZW1lbnQscmVjdXJzZSl7aWYoIUFycmF5LmlzQXJyYXkoZWxlbWVudCkpZWxlbWVudD1bZWxlbWVudF07cmV0dXJuIHRoaXMuZmluZE9uZShnZXRBdHRyaWJDaGVjayhcImlkXCIsaWQpLGVsZW1lbnQscmVjdXJzZSE9PWZhbHNlKX07ZXhwb3J0cy5nZXRFbGVtZW50c0J5VGFnTmFtZT1mdW5jdGlvbihuYW1lLGVsZW1lbnQscmVjdXJzZSxsaW1pdCl7cmV0dXJuIHRoaXMuZmlsdGVyKENoZWNrcy50YWdfbmFtZShuYW1lKSxlbGVtZW50LHJlY3Vyc2UsbGltaXQpfTtleHBvcnRzLmdldEVsZW1lbnRzQnlUYWdUeXBlPWZ1bmN0aW9uKHR5cGUsZWxlbWVudCxyZWN1cnNlLGxpbWl0KXtyZXR1cm4gdGhpcy5maWx0ZXIoQ2hlY2tzLnRhZ190eXBlKHR5cGUpLGVsZW1lbnQscmVjdXJzZSxsaW1pdCl9fSx7ZG9tZWxlbWVudHR5cGU6OX1dLDE2OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtleHBvcnRzLnJlbW92ZUVsZW1lbnQ9ZnVuY3Rpb24oZWxlbSl7aWYoZWxlbS5wcmV2KWVsZW0ucHJldi5uZXh0PWVsZW0ubmV4dDtpZihlbGVtLm5leHQpZWxlbS5uZXh0LnByZXY9ZWxlbS5wcmV2O2lmKGVsZW0ucGFyZW50KXt2YXIgY2hpbGRzPWVsZW0ucGFyZW50LmNoaWxkcmVuO2NoaWxkcy5zcGxpY2UoY2hpbGRzLmxhc3RJbmRleE9mKGVsZW0pLDEpfX07ZXhwb3J0cy5yZXBsYWNlRWxlbWVudD1mdW5jdGlvbihlbGVtLHJlcGxhY2VtZW50KXt2YXIgcHJldj1yZXBsYWNlbWVudC5wcmV2PWVsZW0ucHJldjtpZihwcmV2KXtwcmV2Lm5leHQ9cmVwbGFjZW1lbnR9dmFyIG5leHQ9cmVwbGFjZW1lbnQubmV4dD1lbGVtLm5leHQ7aWYobmV4dCl7bmV4dC5wcmV2PXJlcGxhY2VtZW50fXZhciBwYXJlbnQ9cmVwbGFjZW1lbnQucGFyZW50PWVsZW0ucGFyZW50O2lmKHBhcmVudCl7dmFyIGNoaWxkcz1wYXJlbnQuY2hpbGRyZW47Y2hpbGRzW2NoaWxkcy5sYXN0SW5kZXhPZihlbGVtKV09cmVwbGFjZW1lbnR9fTtleHBvcnRzLmFwcGVuZENoaWxkPWZ1bmN0aW9uKGVsZW0sY2hpbGQpe2NoaWxkLnBhcmVudD1lbGVtO2lmKGVsZW0uY2hpbGRyZW4ucHVzaChjaGlsZCkhPT0xKXt2YXIgc2libGluZz1lbGVtLmNoaWxkcmVuW2VsZW0uY2hpbGRyZW4ubGVuZ3RoLTJdO3NpYmxpbmcubmV4dD1jaGlsZDtjaGlsZC5wcmV2PXNpYmxpbmc7Y2hpbGQubmV4dD1udWxsfX07ZXhwb3J0cy5hcHBlbmQ9ZnVuY3Rpb24oZWxlbSxuZXh0KXt2YXIgcGFyZW50PWVsZW0ucGFyZW50LGN1cnJOZXh0PWVsZW0ubmV4dDtuZXh0Lm5leHQ9Y3Vyck5leHQ7bmV4dC5wcmV2PWVsZW07ZWxlbS5uZXh0PW5leHQ7bmV4dC5wYXJlbnQ9cGFyZW50O2lmKGN1cnJOZXh0KXtjdXJyTmV4dC5wcmV2PW5leHQ7aWYocGFyZW50KXt2YXIgY2hpbGRzPXBhcmVudC5jaGlsZHJlbjtjaGlsZHMuc3BsaWNlKGNoaWxkcy5sYXN0SW5kZXhPZihjdXJyTmV4dCksMCxuZXh0KX19ZWxzZSBpZihwYXJlbnQpe3BhcmVudC5jaGlsZHJlbi5wdXNoKG5leHQpfX07ZXhwb3J0cy5wcmVwZW5kPWZ1bmN0aW9uKGVsZW0scHJldil7dmFyIHBhcmVudD1lbGVtLnBhcmVudDtpZihwYXJlbnQpe3ZhciBjaGlsZHM9cGFyZW50LmNoaWxkcmVuO2NoaWxkcy5zcGxpY2UoY2hpbGRzLmxhc3RJbmRleE9mKGVsZW0pLDAscHJldil9aWYoZWxlbS5wcmV2KXtlbGVtLnByZXYubmV4dD1wcmV2fXByZXYucGFyZW50PXBhcmVudDtwcmV2LnByZXY9ZWxlbS5wcmV2O3ByZXYubmV4dD1lbGVtO2VsZW0ucHJldj1wcmV2fX0se31dLDE3OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXt2YXIgaXNUYWc9cmVxdWlyZShcImRvbWVsZW1lbnR0eXBlXCIpLmlzVGFnO21vZHVsZS5leHBvcnRzPXtmaWx0ZXI6ZmlsdGVyLGZpbmQ6ZmluZCxmaW5kT25lQ2hpbGQ6ZmluZE9uZUNoaWxkLGZpbmRPbmU6ZmluZE9uZSxleGlzdHNPbmU6ZXhpc3RzT25lLGZpbmRBbGw6ZmluZEFsbH07ZnVuY3Rpb24gZmlsdGVyKHRlc3QsZWxlbWVudCxyZWN1cnNlLGxpbWl0KXtpZighQXJyYXkuaXNBcnJheShlbGVtZW50KSllbGVtZW50PVtlbGVtZW50XTtpZih0eXBlb2YgbGltaXQhPT1cIm51bWJlclwifHwhaXNGaW5pdGUobGltaXQpKXtsaW1pdD1JbmZpbml0eX1yZXR1cm4gZmluZCh0ZXN0LGVsZW1lbnQscmVjdXJzZSE9PWZhbHNlLGxpbWl0KX1mdW5jdGlvbiBmaW5kKHRlc3QsZWxlbXMscmVjdXJzZSxsaW1pdCl7dmFyIHJlc3VsdD1bXSxjaGlsZHM7Zm9yKHZhciBpPTAsaj1lbGVtcy5sZW5ndGg7aTxqO2krKyl7aWYodGVzdChlbGVtc1tpXSkpe3Jlc3VsdC5wdXNoKGVsZW1zW2ldKTtpZigtLWxpbWl0PD0wKWJyZWFrfWNoaWxkcz1lbGVtc1tpXS5jaGlsZHJlbjtpZihyZWN1cnNlJiZjaGlsZHMmJmNoaWxkcy5sZW5ndGg+MCl7Y2hpbGRzPWZpbmQodGVzdCxjaGlsZHMscmVjdXJzZSxsaW1pdCk7cmVzdWx0PXJlc3VsdC5jb25jYXQoY2hpbGRzKTtsaW1pdC09Y2hpbGRzLmxlbmd0aDtpZihsaW1pdDw9MClicmVha319cmV0dXJuIHJlc3VsdH1mdW5jdGlvbiBmaW5kT25lQ2hpbGQodGVzdCxlbGVtcyl7Zm9yKHZhciBpPTAsbD1lbGVtcy5sZW5ndGg7aTxsO2krKyl7aWYodGVzdChlbGVtc1tpXSkpcmV0dXJuIGVsZW1zW2ldfXJldHVybiBudWxsfWZ1bmN0aW9uIGZpbmRPbmUodGVzdCxlbGVtcyl7dmFyIGVsZW09bnVsbDtmb3IodmFyIGk9MCxsPWVsZW1zLmxlbmd0aDtpPGwmJiFlbGVtO2krKyl7aWYoIWlzVGFnKGVsZW1zW2ldKSl7Y29udGludWV9ZWxzZSBpZih0ZXN0KGVsZW1zW2ldKSl7ZWxlbT1lbGVtc1tpXX1lbHNlIGlmKGVsZW1zW2ldLmNoaWxkcmVuLmxlbmd0aD4wKXtlbGVtPWZpbmRPbmUodGVzdCxlbGVtc1tpXS5jaGlsZHJlbil9fXJldHVybiBlbGVtfWZ1bmN0aW9uIGV4aXN0c09uZSh0ZXN0LGVsZW1zKXtmb3IodmFyIGk9MCxsPWVsZW1zLmxlbmd0aDtpPGw7aSsrKXtpZihpc1RhZyhlbGVtc1tpXSkmJih0ZXN0KGVsZW1zW2ldKXx8ZWxlbXNbaV0uY2hpbGRyZW4ubGVuZ3RoPjAmJmV4aXN0c09uZSh0ZXN0LGVsZW1zW2ldLmNoaWxkcmVuKSkpe3JldHVybiB0cnVlfX1yZXR1cm4gZmFsc2V9ZnVuY3Rpb24gZmluZEFsbCh0ZXN0LGVsZW1zKXt2YXIgcmVzdWx0PVtdO2Zvcih2YXIgaT0wLGo9ZWxlbXMubGVuZ3RoO2k8ajtpKyspe2lmKCFpc1RhZyhlbGVtc1tpXSkpY29udGludWU7aWYodGVzdChlbGVtc1tpXSkpcmVzdWx0LnB1c2goZWxlbXNbaV0pO2lmKGVsZW1zW2ldLmNoaWxkcmVuLmxlbmd0aD4wKXtyZXN1bHQ9cmVzdWx0LmNvbmNhdChmaW5kQWxsKHRlc3QsZWxlbXNbaV0uY2hpbGRyZW4pKX19cmV0dXJuIHJlc3VsdH19LHtkb21lbGVtZW50dHlwZTo5fV0sMTg6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe3ZhciBFbGVtZW50VHlwZT1yZXF1aXJlKFwiZG9tZWxlbWVudHR5cGVcIiksZ2V0T3V0ZXJIVE1MPXJlcXVpcmUoXCJkb20tc2VyaWFsaXplclwiKSxpc1RhZz1FbGVtZW50VHlwZS5pc1RhZzttb2R1bGUuZXhwb3J0cz17Z2V0SW5uZXJIVE1MOmdldElubmVySFRNTCxnZXRPdXRlckhUTUw6Z2V0T3V0ZXJIVE1MLGdldFRleHQ6Z2V0VGV4dH07ZnVuY3Rpb24gZ2V0SW5uZXJIVE1MKGVsZW0sb3B0cyl7cmV0dXJuIGVsZW0uY2hpbGRyZW4/ZWxlbS5jaGlsZHJlbi5tYXAoZnVuY3Rpb24oZWxlbSl7cmV0dXJuIGdldE91dGVySFRNTChlbGVtLG9wdHMpfSkuam9pbihcIlwiKTpcIlwifWZ1bmN0aW9uIGdldFRleHQoZWxlbSl7aWYoQXJyYXkuaXNBcnJheShlbGVtKSlyZXR1cm4gZWxlbS5tYXAoZ2V0VGV4dCkuam9pbihcIlwiKTtpZihpc1RhZyhlbGVtKXx8ZWxlbS50eXBlPT09RWxlbWVudFR5cGUuQ0RBVEEpcmV0dXJuIGdldFRleHQoZWxlbS5jaGlsZHJlbik7aWYoZWxlbS50eXBlPT09RWxlbWVudFR5cGUuVGV4dClyZXR1cm4gZWxlbS5kYXRhO3JldHVyblwiXCJ9fSx7XCJkb20tc2VyaWFsaXplclwiOjcsZG9tZWxlbWVudHR5cGU6OX1dLDE5OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXt2YXIgZ2V0Q2hpbGRyZW49ZXhwb3J0cy5nZXRDaGlsZHJlbj1mdW5jdGlvbihlbGVtKXtyZXR1cm4gZWxlbS5jaGlsZHJlbn07dmFyIGdldFBhcmVudD1leHBvcnRzLmdldFBhcmVudD1mdW5jdGlvbihlbGVtKXtyZXR1cm4gZWxlbS5wYXJlbnR9O2V4cG9ydHMuZ2V0U2libGluZ3M9ZnVuY3Rpb24oZWxlbSl7dmFyIHBhcmVudD1nZXRQYXJlbnQoZWxlbSk7cmV0dXJuIHBhcmVudD9nZXRDaGlsZHJlbihwYXJlbnQpOltlbGVtXX07ZXhwb3J0cy5nZXRBdHRyaWJ1dGVWYWx1ZT1mdW5jdGlvbihlbGVtLG5hbWUpe3JldHVybiBlbGVtLmF0dHJpYnMmJmVsZW0uYXR0cmlic1tuYW1lXX07ZXhwb3J0cy5oYXNBdHRyaWI9ZnVuY3Rpb24oZWxlbSxuYW1lKXtyZXR1cm4hIWVsZW0uYXR0cmlicyYmaGFzT3duUHJvcGVydHkuY2FsbChlbGVtLmF0dHJpYnMsbmFtZSl9O2V4cG9ydHMuZ2V0TmFtZT1mdW5jdGlvbihlbGVtKXtyZXR1cm4gZWxlbS5uYW1lfX0se31dLDIwOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXt2YXIgZW5jb2RlPXJlcXVpcmUoXCIuL2xpYi9lbmNvZGUuanNcIiksZGVjb2RlPXJlcXVpcmUoXCIuL2xpYi9kZWNvZGUuanNcIik7ZXhwb3J0cy5kZWNvZGU9ZnVuY3Rpb24oZGF0YSxsZXZlbCl7cmV0dXJuKCFsZXZlbHx8bGV2ZWw8PTA/ZGVjb2RlLlhNTDpkZWNvZGUuSFRNTCkoZGF0YSl9O2V4cG9ydHMuZGVjb2RlU3RyaWN0PWZ1bmN0aW9uKGRhdGEsbGV2ZWwpe3JldHVybighbGV2ZWx8fGxldmVsPD0wP2RlY29kZS5YTUw6ZGVjb2RlLkhUTUxTdHJpY3QpKGRhdGEpfTtleHBvcnRzLmVuY29kZT1mdW5jdGlvbihkYXRhLGxldmVsKXtyZXR1cm4oIWxldmVsfHxsZXZlbDw9MD9lbmNvZGUuWE1MOmVuY29kZS5IVE1MKShkYXRhKX07ZXhwb3J0cy5lbmNvZGVYTUw9ZW5jb2RlLlhNTDtleHBvcnRzLmVuY29kZUhUTUw0PWV4cG9ydHMuZW5jb2RlSFRNTDU9ZXhwb3J0cy5lbmNvZGVIVE1MPWVuY29kZS5IVE1MO2V4cG9ydHMuZGVjb2RlWE1MPWV4cG9ydHMuZGVjb2RlWE1MU3RyaWN0PWRlY29kZS5YTUw7ZXhwb3J0cy5kZWNvZGVIVE1MND1leHBvcnRzLmRlY29kZUhUTUw1PWV4cG9ydHMuZGVjb2RlSFRNTD1kZWNvZGUuSFRNTDtleHBvcnRzLmRlY29kZUhUTUw0U3RyaWN0PWV4cG9ydHMuZGVjb2RlSFRNTDVTdHJpY3Q9ZXhwb3J0cy5kZWNvZGVIVE1MU3RyaWN0PWRlY29kZS5IVE1MU3RyaWN0O2V4cG9ydHMuZXNjYXBlPWVuY29kZS5lc2NhcGV9LHtcIi4vbGliL2RlY29kZS5qc1wiOjIxLFwiLi9saWIvZW5jb2RlLmpzXCI6MjN9XSwyMTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7dmFyIGVudGl0eU1hcD1yZXF1aXJlKFwiLi4vbWFwcy9lbnRpdGllcy5qc29uXCIpLGxlZ2FjeU1hcD1yZXF1aXJlKFwiLi4vbWFwcy9sZWdhY3kuanNvblwiKSx4bWxNYXA9cmVxdWlyZShcIi4uL21hcHMveG1sLmpzb25cIiksZGVjb2RlQ29kZVBvaW50PXJlcXVpcmUoXCIuL2RlY29kZV9jb2RlcG9pbnQuanNcIik7dmFyIGRlY29kZVhNTFN0cmljdD1nZXRTdHJpY3REZWNvZGVyKHhtbE1hcCksZGVjb2RlSFRNTFN0cmljdD1nZXRTdHJpY3REZWNvZGVyKGVudGl0eU1hcCk7ZnVuY3Rpb24gZ2V0U3RyaWN0RGVjb2RlcihtYXApe3ZhciBrZXlzPU9iamVjdC5rZXlzKG1hcCkuam9pbihcInxcIikscmVwbGFjZT1nZXRSZXBsYWNlcihtYXApO2tleXMrPVwifCNbeFhdW1xcXFxkYS1mQS1GXSt8I1xcXFxkK1wiO3ZhciByZT1uZXcgUmVnRXhwKFwiJig/OlwiK2tleXMrXCIpO1wiLFwiZ1wiKTtyZXR1cm4gZnVuY3Rpb24oc3RyKXtyZXR1cm4gU3RyaW5nKHN0cikucmVwbGFjZShyZSxyZXBsYWNlKX19dmFyIGRlY29kZUhUTUw9ZnVuY3Rpb24oKXt2YXIgbGVnYWN5PU9iamVjdC5rZXlzKGxlZ2FjeU1hcCkuc29ydChzb3J0ZXIpO3ZhciBrZXlzPU9iamVjdC5rZXlzKGVudGl0eU1hcCkuc29ydChzb3J0ZXIpO2Zvcih2YXIgaT0wLGo9MDtpPGtleXMubGVuZ3RoO2krKyl7aWYobGVnYWN5W2pdPT09a2V5c1tpXSl7a2V5c1tpXSs9XCI7P1wiO2orK31lbHNle2tleXNbaV0rPVwiO1wifX12YXIgcmU9bmV3IFJlZ0V4cChcIiYoPzpcIitrZXlzLmpvaW4oXCJ8XCIpK1wifCNbeFhdW1xcXFxkYS1mQS1GXSs7P3wjXFxcXGQrOz8pXCIsXCJnXCIpLHJlcGxhY2U9Z2V0UmVwbGFjZXIoZW50aXR5TWFwKTtmdW5jdGlvbiByZXBsYWNlcihzdHIpe2lmKHN0ci5zdWJzdHIoLTEpIT09XCI7XCIpc3RyKz1cIjtcIjtyZXR1cm4gcmVwbGFjZShzdHIpfXJldHVybiBmdW5jdGlvbihzdHIpe3JldHVybiBTdHJpbmcoc3RyKS5yZXBsYWNlKHJlLHJlcGxhY2VyKX19KCk7ZnVuY3Rpb24gc29ydGVyKGEsYil7cmV0dXJuIGE8Yj8xOi0xfWZ1bmN0aW9uIGdldFJlcGxhY2VyKG1hcCl7cmV0dXJuIGZ1bmN0aW9uIHJlcGxhY2Uoc3RyKXtpZihzdHIuY2hhckF0KDEpPT09XCIjXCIpe2lmKHN0ci5jaGFyQXQoMik9PT1cIlhcInx8c3RyLmNoYXJBdCgyKT09PVwieFwiKXtyZXR1cm4gZGVjb2RlQ29kZVBvaW50KHBhcnNlSW50KHN0ci5zdWJzdHIoMyksMTYpKX1yZXR1cm4gZGVjb2RlQ29kZVBvaW50KHBhcnNlSW50KHN0ci5zdWJzdHIoMiksMTApKX1yZXR1cm4gbWFwW3N0ci5zbGljZSgxLC0xKV07XG59fW1vZHVsZS5leHBvcnRzPXtYTUw6ZGVjb2RlWE1MU3RyaWN0LEhUTUw6ZGVjb2RlSFRNTCxIVE1MU3RyaWN0OmRlY29kZUhUTUxTdHJpY3R9fSx7XCIuLi9tYXBzL2VudGl0aWVzLmpzb25cIjoyNSxcIi4uL21hcHMvbGVnYWN5Lmpzb25cIjoyNixcIi4uL21hcHMveG1sLmpzb25cIjoyNyxcIi4vZGVjb2RlX2NvZGVwb2ludC5qc1wiOjIyfV0sMjI6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe3ZhciBkZWNvZGVNYXA9cmVxdWlyZShcIi4uL21hcHMvZGVjb2RlLmpzb25cIik7bW9kdWxlLmV4cG9ydHM9ZGVjb2RlQ29kZVBvaW50O2Z1bmN0aW9uIGRlY29kZUNvZGVQb2ludChjb2RlUG9pbnQpe2lmKGNvZGVQb2ludD49NTUyOTYmJmNvZGVQb2ludDw9NTczNDN8fGNvZGVQb2ludD4xMTE0MTExKXtyZXR1cm5cIu+/vVwifWlmKGNvZGVQb2ludCBpbiBkZWNvZGVNYXApe2NvZGVQb2ludD1kZWNvZGVNYXBbY29kZVBvaW50XX12YXIgb3V0cHV0PVwiXCI7aWYoY29kZVBvaW50PjY1NTM1KXtjb2RlUG9pbnQtPTY1NTM2O291dHB1dCs9U3RyaW5nLmZyb21DaGFyQ29kZShjb2RlUG9pbnQ+Pj4xMCYxMDIzfDU1Mjk2KTtjb2RlUG9pbnQ9NTYzMjB8Y29kZVBvaW50JjEwMjN9b3V0cHV0Kz1TdHJpbmcuZnJvbUNoYXJDb2RlKGNvZGVQb2ludCk7cmV0dXJuIG91dHB1dH19LHtcIi4uL21hcHMvZGVjb2RlLmpzb25cIjoyNH1dLDIzOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXt2YXIgaW52ZXJzZVhNTD1nZXRJbnZlcnNlT2JqKHJlcXVpcmUoXCIuLi9tYXBzL3htbC5qc29uXCIpKSx4bWxSZXBsYWNlcj1nZXRJbnZlcnNlUmVwbGFjZXIoaW52ZXJzZVhNTCk7ZXhwb3J0cy5YTUw9Z2V0SW52ZXJzZShpbnZlcnNlWE1MLHhtbFJlcGxhY2VyKTt2YXIgaW52ZXJzZUhUTUw9Z2V0SW52ZXJzZU9iaihyZXF1aXJlKFwiLi4vbWFwcy9lbnRpdGllcy5qc29uXCIpKSxodG1sUmVwbGFjZXI9Z2V0SW52ZXJzZVJlcGxhY2VyKGludmVyc2VIVE1MKTtleHBvcnRzLkhUTUw9Z2V0SW52ZXJzZShpbnZlcnNlSFRNTCxodG1sUmVwbGFjZXIpO2Z1bmN0aW9uIGdldEludmVyc2VPYmoob2JqKXtyZXR1cm4gT2JqZWN0LmtleXMob2JqKS5zb3J0KCkucmVkdWNlKGZ1bmN0aW9uKGludmVyc2UsbmFtZSl7aW52ZXJzZVtvYmpbbmFtZV1dPVwiJlwiK25hbWUrXCI7XCI7cmV0dXJuIGludmVyc2V9LHt9KX1mdW5jdGlvbiBnZXRJbnZlcnNlUmVwbGFjZXIoaW52ZXJzZSl7dmFyIHNpbmdsZT1bXSxtdWx0aXBsZT1bXTtPYmplY3Qua2V5cyhpbnZlcnNlKS5mb3JFYWNoKGZ1bmN0aW9uKGspe2lmKGsubGVuZ3RoPT09MSl7c2luZ2xlLnB1c2goXCJcXFxcXCIrayl9ZWxzZXttdWx0aXBsZS5wdXNoKGspfX0pO211bHRpcGxlLnVuc2hpZnQoXCJbXCIrc2luZ2xlLmpvaW4oXCJcIikrXCJdXCIpO3JldHVybiBuZXcgUmVnRXhwKG11bHRpcGxlLmpvaW4oXCJ8XCIpLFwiZ1wiKX12YXIgcmVfbm9uQVNDSUk9L1teXFwwLVxceDdGXS9nLHJlX2FzdHJhbFN5bWJvbHM9L1tcXHVEODAwLVxcdURCRkZdW1xcdURDMDAtXFx1REZGRl0vZztmdW5jdGlvbiBzaW5nbGVDaGFyUmVwbGFjZXIoYyl7cmV0dXJuXCImI3hcIitjLmNoYXJDb2RlQXQoMCkudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCkrXCI7XCJ9ZnVuY3Rpb24gYXN0cmFsUmVwbGFjZXIoYyl7dmFyIGhpZ2g9Yy5jaGFyQ29kZUF0KDApO3ZhciBsb3c9Yy5jaGFyQ29kZUF0KDEpO3ZhciBjb2RlUG9pbnQ9KGhpZ2gtNTUyOTYpKjEwMjQrbG93LTU2MzIwKzY1NTM2O3JldHVyblwiJiN4XCIrY29kZVBvaW50LnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpK1wiO1wifWZ1bmN0aW9uIGdldEludmVyc2UoaW52ZXJzZSxyZSl7ZnVuY3Rpb24gZnVuYyhuYW1lKXtyZXR1cm4gaW52ZXJzZVtuYW1lXX1yZXR1cm4gZnVuY3Rpb24oZGF0YSl7cmV0dXJuIGRhdGEucmVwbGFjZShyZSxmdW5jKS5yZXBsYWNlKHJlX2FzdHJhbFN5bWJvbHMsYXN0cmFsUmVwbGFjZXIpLnJlcGxhY2UocmVfbm9uQVNDSUksc2luZ2xlQ2hhclJlcGxhY2VyKX19dmFyIHJlX3htbENoYXJzPWdldEludmVyc2VSZXBsYWNlcihpbnZlcnNlWE1MKTtmdW5jdGlvbiBlc2NhcGVYTUwoZGF0YSl7cmV0dXJuIGRhdGEucmVwbGFjZShyZV94bWxDaGFycyxzaW5nbGVDaGFyUmVwbGFjZXIpLnJlcGxhY2UocmVfYXN0cmFsU3ltYm9scyxhc3RyYWxSZXBsYWNlcikucmVwbGFjZShyZV9ub25BU0NJSSxzaW5nbGVDaGFyUmVwbGFjZXIpfWV4cG9ydHMuZXNjYXBlPWVzY2FwZVhNTH0se1wiLi4vbWFwcy9lbnRpdGllcy5qc29uXCI6MjUsXCIuLi9tYXBzL3htbC5qc29uXCI6Mjd9XSwyNDpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7bW9kdWxlLmV4cG9ydHM9ezA6NjU1MzMsMTI4OjgzNjQsMTMwOjgyMTgsMTMxOjQwMiwxMzI6ODIyMiwxMzM6ODIzMCwxMzQ6ODIyNCwxMzU6ODIyNSwxMzY6NzEwLDEzNzo4MjQwLDEzODozNTIsMTM5OjgyNDksMTQwOjMzOCwxNDI6MzgxLDE0NTo4MjE2LDE0Njo4MjE3LDE0Nzo4MjIwLDE0ODo4MjIxLDE0OTo4MjI2LDE1MDo4MjExLDE1MTo4MjEyLDE1Mjo3MzIsMTUzOjg0ODIsMTU0OjM1MywxNTU6ODI1MCwxNTY6MzM5LDE1ODozODIsMTU5OjM3Nn19LHt9XSwyNTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7bW9kdWxlLmV4cG9ydHM9e0FhY3V0ZTpcIsOBXCIsYWFjdXRlOlwiw6FcIixBYnJldmU6XCLEglwiLGFicmV2ZTpcIsSDXCIsYWM6XCLiiL5cIixhY2Q6XCLiiL9cIixhY0U6XCLiiL7Ms1wiLEFjaXJjOlwiw4JcIixhY2lyYzpcIsOiXCIsYWN1dGU6XCLCtFwiLEFjeTpcItCQXCIsYWN5Olwi0LBcIixBRWxpZzpcIsOGXCIsYWVsaWc6XCLDplwiLGFmOlwi4oGhXCIsQWZyOlwi8J2UhFwiLGFmcjpcIvCdlJ5cIixBZ3JhdmU6XCLDgFwiLGFncmF2ZTpcIsOgXCIsYWxlZnN5bTpcIuKEtVwiLGFsZXBoOlwi4oS1XCIsQWxwaGE6XCLOkVwiLGFscGhhOlwizrFcIixBbWFjcjpcIsSAXCIsYW1hY3I6XCLEgVwiLGFtYWxnOlwi4qi/XCIsYW1wOlwiJlwiLEFNUDpcIiZcIixhbmRhbmQ6XCLiqZVcIixBbmQ6XCLiqZNcIixhbmQ6XCLiiKdcIixhbmRkOlwi4qmcXCIsYW5kc2xvcGU6XCLiqZhcIixhbmR2Olwi4qmaXCIsYW5nOlwi4oigXCIsYW5nZTpcIuKmpFwiLGFuZ2xlOlwi4oigXCIsYW5nbXNkYWE6XCLipqhcIixhbmdtc2RhYjpcIuKmqVwiLGFuZ21zZGFjOlwi4qaqXCIsYW5nbXNkYWQ6XCLipqtcIixhbmdtc2RhZTpcIuKmrFwiLGFuZ21zZGFmOlwi4qatXCIsYW5nbXNkYWc6XCLipq5cIixhbmdtc2RhaDpcIuKmr1wiLGFuZ21zZDpcIuKIoVwiLGFuZ3J0Olwi4oifXCIsYW5ncnR2YjpcIuKKvlwiLGFuZ3J0dmJkOlwi4qadXCIsYW5nc3BoOlwi4oiiXCIsYW5nc3Q6XCLDhVwiLGFuZ3phcnI6XCLijbxcIixBb2dvbjpcIsSEXCIsYW9nb246XCLEhVwiLEFvcGY6XCLwnZS4XCIsYW9wZjpcIvCdlZJcIixhcGFjaXI6XCLiqa9cIixhcDpcIuKJiFwiLGFwRTpcIuKpsFwiLGFwZTpcIuKJilwiLGFwaWQ6XCLiiYtcIixhcG9zOlwiJ1wiLEFwcGx5RnVuY3Rpb246XCLigaFcIixhcHByb3g6XCLiiYhcIixhcHByb3hlcTpcIuKJilwiLEFyaW5nOlwiw4VcIixhcmluZzpcIsOlXCIsQXNjcjpcIvCdkpxcIixhc2NyOlwi8J2StlwiLEFzc2lnbjpcIuKJlFwiLGFzdDpcIipcIixhc3ltcDpcIuKJiFwiLGFzeW1wZXE6XCLiiY1cIixBdGlsZGU6XCLDg1wiLGF0aWxkZTpcIsOjXCIsQXVtbDpcIsOEXCIsYXVtbDpcIsOkXCIsYXdjb25pbnQ6XCLiiLNcIixhd2ludDpcIuKokVwiLGJhY2tjb25nOlwi4omMXCIsYmFja2Vwc2lsb246XCLPtlwiLGJhY2twcmltZTpcIuKAtVwiLGJhY2tzaW06XCLiiL1cIixiYWNrc2ltZXE6XCLii41cIixCYWNrc2xhc2g6XCLiiJZcIixCYXJ2Olwi4qunXCIsYmFydmVlOlwi4oq9XCIsYmFyd2VkOlwi4oyFXCIsQmFyd2VkOlwi4oyGXCIsYmFyd2VkZ2U6XCLijIVcIixiYnJrOlwi4o61XCIsYmJya3Ricms6XCLijrZcIixiY29uZzpcIuKJjFwiLEJjeTpcItCRXCIsYmN5Olwi0LFcIixiZHF1bzpcIuKAnlwiLGJlY2F1czpcIuKItVwiLGJlY2F1c2U6XCLiiLVcIixCZWNhdXNlOlwi4oi1XCIsYmVtcHR5djpcIuKmsFwiLGJlcHNpOlwiz7ZcIixiZXJub3U6XCLihKxcIixCZXJub3VsbGlzOlwi4oSsXCIsQmV0YTpcIs6SXCIsYmV0YTpcIs6yXCIsYmV0aDpcIuKEtlwiLGJldHdlZW46XCLiiaxcIixCZnI6XCLwnZSFXCIsYmZyOlwi8J2Un1wiLGJpZ2NhcDpcIuKLglwiLGJpZ2NpcmM6XCLil69cIixiaWdjdXA6XCLii4NcIixiaWdvZG90Olwi4qiAXCIsYmlnb3BsdXM6XCLiqIFcIixiaWdvdGltZXM6XCLiqIJcIixiaWdzcWN1cDpcIuKohlwiLGJpZ3N0YXI6XCLimIVcIixiaWd0cmlhbmdsZWRvd246XCLilr1cIixiaWd0cmlhbmdsZXVwOlwi4pazXCIsYmlndXBsdXM6XCLiqIRcIixiaWd2ZWU6XCLii4FcIixiaWd3ZWRnZTpcIuKLgFwiLGJrYXJvdzpcIuKkjVwiLGJsYWNrbG96ZW5nZTpcIuKnq1wiLGJsYWNrc3F1YXJlOlwi4paqXCIsYmxhY2t0cmlhbmdsZTpcIuKWtFwiLGJsYWNrdHJpYW5nbGVkb3duOlwi4pa+XCIsYmxhY2t0cmlhbmdsZWxlZnQ6XCLil4JcIixibGFja3RyaWFuZ2xlcmlnaHQ6XCLilrhcIixibGFuazpcIuKQo1wiLGJsazEyOlwi4paSXCIsYmxrMTQ6XCLilpFcIixibGszNDpcIuKWk1wiLGJsb2NrOlwi4paIXCIsYm5lOlwiPeKDpVwiLGJuZXF1aXY6XCLiiaHig6VcIixiTm90Olwi4qutXCIsYm5vdDpcIuKMkFwiLEJvcGY6XCLwnZS5XCIsYm9wZjpcIvCdlZNcIixib3Q6XCLiiqVcIixib3R0b206XCLiiqVcIixib3d0aWU6XCLii4hcIixib3hib3g6XCLip4lcIixib3hkbDpcIuKUkFwiLGJveGRMOlwi4pWVXCIsYm94RGw6XCLilZZcIixib3hETDpcIuKVl1wiLGJveGRyOlwi4pSMXCIsYm94ZFI6XCLilZJcIixib3hEcjpcIuKVk1wiLGJveERSOlwi4pWUXCIsYm94aDpcIuKUgFwiLGJveEg6XCLilZBcIixib3hoZDpcIuKUrFwiLGJveEhkOlwi4pWkXCIsYm94aEQ6XCLilaVcIixib3hIRDpcIuKVplwiLGJveGh1Olwi4pS0XCIsYm94SHU6XCLiladcIixib3hoVTpcIuKVqFwiLGJveEhVOlwi4pWpXCIsYm94bWludXM6XCLiip9cIixib3hwbHVzOlwi4oqeXCIsYm94dGltZXM6XCLiiqBcIixib3h1bDpcIuKUmFwiLGJveHVMOlwi4pWbXCIsYm94VWw6XCLilZxcIixib3hVTDpcIuKVnVwiLGJveHVyOlwi4pSUXCIsYm94dVI6XCLilZhcIixib3hVcjpcIuKVmVwiLGJveFVSOlwi4pWaXCIsYm94djpcIuKUglwiLGJveFY6XCLilZFcIixib3h2aDpcIuKUvFwiLGJveHZIOlwi4pWqXCIsYm94Vmg6XCLilatcIixib3hWSDpcIuKVrFwiLGJveHZsOlwi4pSkXCIsYm94dkw6XCLilaFcIixib3hWbDpcIuKVolwiLGJveFZMOlwi4pWjXCIsYm94dnI6XCLilJxcIixib3h2UjpcIuKVnlwiLGJveFZyOlwi4pWfXCIsYm94VlI6XCLilaBcIixicHJpbWU6XCLigLVcIixicmV2ZTpcIsuYXCIsQnJldmU6XCLLmFwiLGJydmJhcjpcIsKmXCIsYnNjcjpcIvCdkrdcIixCc2NyOlwi4oSsXCIsYnNlbWk6XCLigY9cIixic2ltOlwi4oi9XCIsYnNpbWU6XCLii41cIixic29sYjpcIuKnhVwiLGJzb2w6XCJcXFxcXCIsYnNvbGhzdWI6XCLin4hcIixidWxsOlwi4oCiXCIsYnVsbGV0Olwi4oCiXCIsYnVtcDpcIuKJjlwiLGJ1bXBFOlwi4qquXCIsYnVtcGU6XCLiiY9cIixCdW1wZXE6XCLiiY5cIixidW1wZXE6XCLiiY9cIixDYWN1dGU6XCLEhlwiLGNhY3V0ZTpcIsSHXCIsY2FwYW5kOlwi4qmEXCIsY2FwYnJjdXA6XCLiqYlcIixjYXBjYXA6XCLiqYtcIixjYXA6XCLiiKlcIixDYXA6XCLii5JcIixjYXBjdXA6XCLiqYdcIixjYXBkb3Q6XCLiqYBcIixDYXBpdGFsRGlmZmVyZW50aWFsRDpcIuKFhVwiLGNhcHM6XCLiiKnvuIBcIixjYXJldDpcIuKBgVwiLGNhcm9uOlwiy4dcIixDYXlsZXlzOlwi4oStXCIsY2NhcHM6XCLiqY1cIixDY2Fyb246XCLEjFwiLGNjYXJvbjpcIsSNXCIsQ2NlZGlsOlwiw4dcIixjY2VkaWw6XCLDp1wiLENjaXJjOlwixIhcIixjY2lyYzpcIsSJXCIsQ2NvbmludDpcIuKIsFwiLGNjdXBzOlwi4qmMXCIsY2N1cHNzbTpcIuKpkFwiLENkb3Q6XCLEilwiLGNkb3Q6XCLEi1wiLGNlZGlsOlwiwrhcIixDZWRpbGxhOlwiwrhcIixjZW1wdHl2Olwi4qayXCIsY2VudDpcIsKiXCIsY2VudGVyZG90OlwiwrdcIixDZW50ZXJEb3Q6XCLCt1wiLGNmcjpcIvCdlKBcIixDZnI6XCLihK1cIixDSGN5Olwi0KdcIixjaGN5Olwi0YdcIixjaGVjazpcIuKck1wiLGNoZWNrbWFyazpcIuKck1wiLENoaTpcIs6nXCIsY2hpOlwiz4dcIixjaXJjOlwiy4ZcIixjaXJjZXE6XCLiiZdcIixjaXJjbGVhcnJvd2xlZnQ6XCLihrpcIixjaXJjbGVhcnJvd3JpZ2h0Olwi4oa7XCIsY2lyY2xlZGFzdDpcIuKKm1wiLGNpcmNsZWRjaXJjOlwi4oqaXCIsY2lyY2xlZGRhc2g6XCLiip1cIixDaXJjbGVEb3Q6XCLiiplcIixjaXJjbGVkUjpcIsKuXCIsY2lyY2xlZFM6XCLik4hcIixDaXJjbGVNaW51czpcIuKKllwiLENpcmNsZVBsdXM6XCLiipVcIixDaXJjbGVUaW1lczpcIuKKl1wiLGNpcjpcIuKXi1wiLGNpckU6XCLip4NcIixjaXJlOlwi4omXXCIsY2lyZm5pbnQ6XCLiqJBcIixjaXJtaWQ6XCLiq69cIixjaXJzY2lyOlwi4qeCXCIsQ2xvY2t3aXNlQ29udG91ckludGVncmFsOlwi4oiyXCIsQ2xvc2VDdXJseURvdWJsZVF1b3RlOlwi4oCdXCIsQ2xvc2VDdXJseVF1b3RlOlwi4oCZXCIsY2x1YnM6XCLimaNcIixjbHVic3VpdDpcIuKZo1wiLGNvbG9uOlwiOlwiLENvbG9uOlwi4oi3XCIsQ29sb25lOlwi4qm0XCIsY29sb25lOlwi4omUXCIsY29sb25lcTpcIuKJlFwiLGNvbW1hOlwiLFwiLGNvbW1hdDpcIkBcIixjb21wOlwi4oiBXCIsY29tcGZuOlwi4oiYXCIsY29tcGxlbWVudDpcIuKIgVwiLGNvbXBsZXhlczpcIuKEglwiLGNvbmc6XCLiiYVcIixjb25nZG90Olwi4qmtXCIsQ29uZ3J1ZW50Olwi4omhXCIsY29uaW50Olwi4oiuXCIsQ29uaW50Olwi4oivXCIsQ29udG91ckludGVncmFsOlwi4oiuXCIsY29wZjpcIvCdlZRcIixDb3BmOlwi4oSCXCIsY29wcm9kOlwi4oiQXCIsQ29wcm9kdWN0Olwi4oiQXCIsY29weTpcIsKpXCIsQ09QWTpcIsKpXCIsY29weXNyOlwi4oSXXCIsQ291bnRlckNsb2Nrd2lzZUNvbnRvdXJJbnRlZ3JhbDpcIuKIs1wiLGNyYXJyOlwi4oa1XCIsY3Jvc3M6XCLinJdcIixDcm9zczpcIuKor1wiLENzY3I6XCLwnZKeXCIsY3NjcjpcIvCdkrhcIixjc3ViOlwi4quPXCIsY3N1YmU6XCLiq5FcIixjc3VwOlwi4quQXCIsY3N1cGU6XCLiq5JcIixjdGRvdDpcIuKLr1wiLGN1ZGFycmw6XCLipLhcIixjdWRhcnJyOlwi4qS1XCIsY3VlcHI6XCLii55cIixjdWVzYzpcIuKLn1wiLGN1bGFycjpcIuKGtlwiLGN1bGFycnA6XCLipL1cIixjdXBicmNhcDpcIuKpiFwiLGN1cGNhcDpcIuKphlwiLEN1cENhcDpcIuKJjVwiLGN1cDpcIuKIqlwiLEN1cDpcIuKLk1wiLGN1cGN1cDpcIuKpilwiLGN1cGRvdDpcIuKKjVwiLGN1cG9yOlwi4qmFXCIsY3VwczpcIuKIqu+4gFwiLGN1cmFycjpcIuKGt1wiLGN1cmFycm06XCLipLxcIixjdXJseWVxcHJlYzpcIuKLnlwiLGN1cmx5ZXFzdWNjOlwi4oufXCIsY3VybHl2ZWU6XCLii45cIixjdXJseXdlZGdlOlwi4ouPXCIsY3VycmVuOlwiwqRcIixjdXJ2ZWFycm93bGVmdDpcIuKGtlwiLGN1cnZlYXJyb3dyaWdodDpcIuKGt1wiLGN1dmVlOlwi4ouOXCIsY3V3ZWQ6XCLii49cIixjd2NvbmludDpcIuKIslwiLGN3aW50Olwi4oixXCIsY3lsY3R5Olwi4oytXCIsZGFnZ2VyOlwi4oCgXCIsRGFnZ2VyOlwi4oChXCIsZGFsZXRoOlwi4oS4XCIsZGFycjpcIuKGk1wiLERhcnI6XCLihqFcIixkQXJyOlwi4oeTXCIsZGFzaDpcIuKAkFwiLERhc2h2Olwi4qukXCIsZGFzaHY6XCLiiqNcIixkYmthcm93Olwi4qSPXCIsZGJsYWM6XCLLnVwiLERjYXJvbjpcIsSOXCIsZGNhcm9uOlwixI9cIixEY3k6XCLQlFwiLGRjeTpcItC0XCIsZGRhZ2dlcjpcIuKAoVwiLGRkYXJyOlwi4oeKXCIsREQ6XCLihYVcIixkZDpcIuKFhlwiLEREb3RyYWhkOlwi4qSRXCIsZGRvdHNlcTpcIuKpt1wiLGRlZzpcIsKwXCIsRGVsOlwi4oiHXCIsRGVsdGE6XCLOlFwiLGRlbHRhOlwizrRcIixkZW1wdHl2Olwi4qaxXCIsZGZpc2h0Olwi4qW/XCIsRGZyOlwi8J2Uh1wiLGRmcjpcIvCdlKFcIixkSGFyOlwi4qWlXCIsZGhhcmw6XCLih4NcIixkaGFycjpcIuKHglwiLERpYWNyaXRpY2FsQWN1dGU6XCLCtFwiLERpYWNyaXRpY2FsRG90Olwiy5lcIixEaWFjcml0aWNhbERvdWJsZUFjdXRlOlwiy51cIixEaWFjcml0aWNhbEdyYXZlOlwiYFwiLERpYWNyaXRpY2FsVGlsZGU6XCLLnFwiLGRpYW06XCLii4RcIixkaWFtb25kOlwi4ouEXCIsRGlhbW9uZDpcIuKLhFwiLGRpYW1vbmRzdWl0Olwi4pmmXCIsZGlhbXM6XCLimaZcIixkaWU6XCLCqFwiLERpZmZlcmVudGlhbEQ6XCLihYZcIixkaWdhbW1hOlwiz51cIixkaXNpbjpcIuKLslwiLGRpdjpcIsO3XCIsZGl2aWRlOlwiw7dcIixkaXZpZGVvbnRpbWVzOlwi4ouHXCIsZGl2b254Olwi4ouHXCIsREpjeTpcItCCXCIsZGpjeTpcItGSXCIsZGxjb3JuOlwi4oyeXCIsZGxjcm9wOlwi4oyNXCIsZG9sbGFyOlwiJFwiLERvcGY6XCLwnZS7XCIsZG9wZjpcIvCdlZVcIixEb3Q6XCLCqFwiLGRvdDpcIsuZXCIsRG90RG90Olwi4oOcXCIsZG90ZXE6XCLiiZBcIixkb3RlcWRvdDpcIuKJkVwiLERvdEVxdWFsOlwi4omQXCIsZG90bWludXM6XCLiiLhcIixkb3RwbHVzOlwi4oiUXCIsZG90c3F1YXJlOlwi4oqhXCIsZG91YmxlYmFyd2VkZ2U6XCLijIZcIixEb3VibGVDb250b3VySW50ZWdyYWw6XCLiiK9cIixEb3VibGVEb3Q6XCLCqFwiLERvdWJsZURvd25BcnJvdzpcIuKHk1wiLERvdWJsZUxlZnRBcnJvdzpcIuKHkFwiLERvdWJsZUxlZnRSaWdodEFycm93Olwi4oeUXCIsRG91YmxlTGVmdFRlZTpcIuKrpFwiLERvdWJsZUxvbmdMZWZ0QXJyb3c6XCLin7hcIixEb3VibGVMb25nTGVmdFJpZ2h0QXJyb3c6XCLin7pcIixEb3VibGVMb25nUmlnaHRBcnJvdzpcIuKfuVwiLERvdWJsZVJpZ2h0QXJyb3c6XCLih5JcIixEb3VibGVSaWdodFRlZTpcIuKKqFwiLERvdWJsZVVwQXJyb3c6XCLih5FcIixEb3VibGVVcERvd25BcnJvdzpcIuKHlVwiLERvdWJsZVZlcnRpY2FsQmFyOlwi4oilXCIsRG93bkFycm93QmFyOlwi4qSTXCIsZG93bmFycm93Olwi4oaTXCIsRG93bkFycm93Olwi4oaTXCIsRG93bmFycm93Olwi4oeTXCIsRG93bkFycm93VXBBcnJvdzpcIuKHtVwiLERvd25CcmV2ZTpcIsyRXCIsZG93bmRvd25hcnJvd3M6XCLih4pcIixkb3duaGFycG9vbmxlZnQ6XCLih4NcIixkb3duaGFycG9vbnJpZ2h0Olwi4oeCXCIsRG93bkxlZnRSaWdodFZlY3RvcjpcIuKlkFwiLERvd25MZWZ0VGVlVmVjdG9yOlwi4qWeXCIsRG93bkxlZnRWZWN0b3JCYXI6XCLipZZcIixEb3duTGVmdFZlY3RvcjpcIuKGvVwiLERvd25SaWdodFRlZVZlY3RvcjpcIuKln1wiLERvd25SaWdodFZlY3RvckJhcjpcIuKll1wiLERvd25SaWdodFZlY3RvcjpcIuKHgVwiLERvd25UZWVBcnJvdzpcIuKGp1wiLERvd25UZWU6XCLiiqRcIixkcmJrYXJvdzpcIuKkkFwiLGRyY29ybjpcIuKMn1wiLGRyY3JvcDpcIuKMjFwiLERzY3I6XCLwnZKfXCIsZHNjcjpcIvCdkrlcIixEU2N5Olwi0IVcIixkc2N5Olwi0ZVcIixkc29sOlwi4qe2XCIsRHN0cm9rOlwixJBcIixkc3Ryb2s6XCLEkVwiLGR0ZG90Olwi4ouxXCIsZHRyaTpcIuKWv1wiLGR0cmlmOlwi4pa+XCIsZHVhcnI6XCLih7VcIixkdWhhcjpcIuKlr1wiLGR3YW5nbGU6XCLipqZcIixEWmN5Olwi0I9cIixkemN5Olwi0Z9cIixkemlncmFycjpcIuKfv1wiLEVhY3V0ZTpcIsOJXCIsZWFjdXRlOlwiw6lcIixlYXN0ZXI6XCLiqa5cIixFY2Fyb246XCLEmlwiLGVjYXJvbjpcIsSbXCIsRWNpcmM6XCLDilwiLGVjaXJjOlwiw6pcIixlY2lyOlwi4omWXCIsZWNvbG9uOlwi4omVXCIsRWN5Olwi0K1cIixlY3k6XCLRjVwiLGVERG90Olwi4qm3XCIsRWRvdDpcIsSWXCIsZWRvdDpcIsSXXCIsZURvdDpcIuKJkVwiLGVlOlwi4oWHXCIsZWZEb3Q6XCLiiZJcIixFZnI6XCLwnZSIXCIsZWZyOlwi8J2UolwiLGVnOlwi4qqaXCIsRWdyYXZlOlwiw4hcIixlZ3JhdmU6XCLDqFwiLGVnczpcIuKqllwiLGVnc2RvdDpcIuKqmFwiLGVsOlwi4qqZXCIsRWxlbWVudDpcIuKIiFwiLGVsaW50ZXJzOlwi4o+nXCIsZWxsOlwi4oSTXCIsZWxzOlwi4qqVXCIsZWxzZG90Olwi4qqXXCIsRW1hY3I6XCLEklwiLGVtYWNyOlwixJNcIixlbXB0eTpcIuKIhVwiLGVtcHR5c2V0Olwi4oiFXCIsRW1wdHlTbWFsbFNxdWFyZTpcIuKXu1wiLGVtcHR5djpcIuKIhVwiLEVtcHR5VmVyeVNtYWxsU3F1YXJlOlwi4parXCIsZW1zcDEzOlwi4oCEXCIsZW1zcDE0Olwi4oCFXCIsZW1zcDpcIuKAg1wiLEVORzpcIsWKXCIsZW5nOlwixYtcIixlbnNwOlwi4oCCXCIsRW9nb246XCLEmFwiLGVvZ29uOlwixJlcIixFb3BmOlwi8J2UvFwiLGVvcGY6XCLwnZWWXCIsZXBhcjpcIuKLlVwiLGVwYXJzbDpcIuKno1wiLGVwbHVzOlwi4qmxXCIsZXBzaTpcIs61XCIsRXBzaWxvbjpcIs6VXCIsZXBzaWxvbjpcIs61XCIsZXBzaXY6XCLPtVwiLGVxY2lyYzpcIuKJllwiLGVxY29sb246XCLiiZVcIixlcXNpbTpcIuKJglwiLGVxc2xhbnRndHI6XCLiqpZcIixlcXNsYW50bGVzczpcIuKqlVwiLEVxdWFsOlwi4qm1XCIsZXF1YWxzOlwiPVwiLEVxdWFsVGlsZGU6XCLiiYJcIixlcXVlc3Q6XCLiiZ9cIixFcXVpbGlicml1bTpcIuKHjFwiLGVxdWl2Olwi4omhXCIsZXF1aXZERDpcIuKpuFwiLGVxdnBhcnNsOlwi4qelXCIsZXJhcnI6XCLipbFcIixlckRvdDpcIuKJk1wiLGVzY3I6XCLihK9cIixFc2NyOlwi4oSwXCIsZXNkb3Q6XCLiiZBcIixFc2ltOlwi4qmzXCIsZXNpbTpcIuKJglwiLEV0YTpcIs6XXCIsZXRhOlwizrdcIixFVEg6XCLDkFwiLGV0aDpcIsOwXCIsRXVtbDpcIsOLXCIsZXVtbDpcIsOrXCIsZXVybzpcIuKCrFwiLGV4Y2w6XCIhXCIsZXhpc3Q6XCLiiINcIixFeGlzdHM6XCLiiINcIixleHBlY3RhdGlvbjpcIuKEsFwiLGV4cG9uZW50aWFsZTpcIuKFh1wiLEV4cG9uZW50aWFsRTpcIuKFh1wiLGZhbGxpbmdkb3RzZXE6XCLiiZJcIixGY3k6XCLQpFwiLGZjeTpcItGEXCIsZmVtYWxlOlwi4pmAXCIsZmZpbGlnOlwi76yDXCIsZmZsaWc6XCLvrIBcIixmZmxsaWc6XCLvrIRcIixGZnI6XCLwnZSJXCIsZmZyOlwi8J2Uo1wiLGZpbGlnOlwi76yBXCIsRmlsbGVkU21hbGxTcXVhcmU6XCLil7xcIixGaWxsZWRWZXJ5U21hbGxTcXVhcmU6XCLilqpcIixmamxpZzpcImZqXCIsZmxhdDpcIuKZrVwiLGZsbGlnOlwi76yCXCIsZmx0bnM6XCLilrFcIixmbm9mOlwixpJcIixGb3BmOlwi8J2UvVwiLGZvcGY6XCLwnZWXXCIsZm9yYWxsOlwi4oiAXCIsRm9yQWxsOlwi4oiAXCIsZm9yazpcIuKLlFwiLGZvcmt2Olwi4quZXCIsRm91cmllcnRyZjpcIuKEsVwiLGZwYXJ0aW50Olwi4qiNXCIsZnJhYzEyOlwiwr1cIixmcmFjMTM6XCLihZNcIixmcmFjMTQ6XCLCvFwiLGZyYWMxNTpcIuKFlVwiLGZyYWMxNjpcIuKFmVwiLGZyYWMxODpcIuKFm1wiLGZyYWMyMzpcIuKFlFwiLGZyYWMyNTpcIuKFllwiLGZyYWMzNDpcIsK+XCIsZnJhYzM1Olwi4oWXXCIsZnJhYzM4Olwi4oWcXCIsZnJhYzQ1Olwi4oWYXCIsZnJhYzU2Olwi4oWaXCIsZnJhYzU4Olwi4oWdXCIsZnJhYzc4Olwi4oWeXCIsZnJhc2w6XCLigYRcIixmcm93bjpcIuKMolwiLGZzY3I6XCLwnZK7XCIsRnNjcjpcIuKEsVwiLGdhY3V0ZTpcIse1XCIsR2FtbWE6XCLOk1wiLGdhbW1hOlwizrNcIixHYW1tYWQ6XCLPnFwiLGdhbW1hZDpcIs+dXCIsZ2FwOlwi4qqGXCIsR2JyZXZlOlwixJ5cIixnYnJldmU6XCLEn1wiLEdjZWRpbDpcIsSiXCIsR2NpcmM6XCLEnFwiLGdjaXJjOlwixJ1cIixHY3k6XCLQk1wiLGdjeTpcItCzXCIsR2RvdDpcIsSgXCIsZ2RvdDpcIsShXCIsZ2U6XCLiiaVcIixnRTpcIuKJp1wiLGdFbDpcIuKqjFwiLGdlbDpcIuKLm1wiLGdlcTpcIuKJpVwiLGdlcXE6XCLiiadcIixnZXFzbGFudDpcIuKpvlwiLGdlc2NjOlwi4qqpXCIsZ2VzOlwi4qm+XCIsZ2VzZG90Olwi4qqAXCIsZ2VzZG90bzpcIuKqglwiLGdlc2RvdG9sOlwi4qqEXCIsZ2VzbDpcIuKLm++4gFwiLGdlc2xlczpcIuKqlFwiLEdmcjpcIvCdlIpcIixnZnI6XCLwnZSkXCIsZ2c6XCLiiatcIixHZzpcIuKLmVwiLGdnZzpcIuKLmVwiLGdpbWVsOlwi4oS3XCIsR0pjeTpcItCDXCIsZ2pjeTpcItGTXCIsZ2xhOlwi4qqlXCIsZ2w6XCLiibdcIixnbEU6XCLiqpJcIixnbGo6XCLiqqRcIixnbmFwOlwi4qqKXCIsZ25hcHByb3g6XCLiqopcIixnbmU6XCLiqohcIixnbkU6XCLiialcIixnbmVxOlwi4qqIXCIsZ25lcXE6XCLiialcIixnbnNpbTpcIuKLp1wiLEdvcGY6XCLwnZS+XCIsZ29wZjpcIvCdlZhcIixncmF2ZTpcImBcIixHcmVhdGVyRXF1YWw6XCLiiaVcIixHcmVhdGVyRXF1YWxMZXNzOlwi4oubXCIsR3JlYXRlckZ1bGxFcXVhbDpcIuKJp1wiLEdyZWF0ZXJHcmVhdGVyOlwi4qqiXCIsR3JlYXRlckxlc3M6XCLiibdcIixHcmVhdGVyU2xhbnRFcXVhbDpcIuKpvlwiLEdyZWF0ZXJUaWxkZTpcIuKJs1wiLEdzY3I6XCLwnZKiXCIsZ3NjcjpcIuKEilwiLGdzaW06XCLiibNcIixnc2ltZTpcIuKqjlwiLGdzaW1sOlwi4qqQXCIsZ3RjYzpcIuKqp1wiLGd0Y2lyOlwi4qm6XCIsZ3Q6XCI+XCIsR1Q6XCI+XCIsR3Q6XCLiiatcIixndGRvdDpcIuKLl1wiLGd0bFBhcjpcIuKmlVwiLGd0cXVlc3Q6XCLiqbxcIixndHJhcHByb3g6XCLiqoZcIixndHJhcnI6XCLipbhcIixndHJkb3Q6XCLii5dcIixndHJlcWxlc3M6XCLii5tcIixndHJlcXFsZXNzOlwi4qqMXCIsZ3RybGVzczpcIuKJt1wiLGd0cnNpbTpcIuKJs1wiLGd2ZXJ0bmVxcTpcIuKJqe+4gFwiLGd2bkU6XCLiianvuIBcIixIYWNlazpcIsuHXCIsaGFpcnNwOlwi4oCKXCIsaGFsZjpcIsK9XCIsaGFtaWx0Olwi4oSLXCIsSEFSRGN5Olwi0KpcIixoYXJkY3k6XCLRilwiLGhhcnJjaXI6XCLipYhcIixoYXJyOlwi4oaUXCIsaEFycjpcIuKHlFwiLGhhcnJ3Olwi4oatXCIsSGF0OlwiXlwiLGhiYXI6XCLihI9cIixIY2lyYzpcIsSkXCIsaGNpcmM6XCLEpVwiLGhlYXJ0czpcIuKZpVwiLGhlYXJ0c3VpdDpcIuKZpVwiLGhlbGxpcDpcIuKAplwiLGhlcmNvbjpcIuKKuVwiLGhmcjpcIvCdlKVcIixIZnI6XCLihIxcIixIaWxiZXJ0U3BhY2U6XCLihItcIixoa3NlYXJvdzpcIuKkpVwiLGhrc3dhcm93Olwi4qSmXCIsaG9hcnI6XCLih79cIixob210aHQ6XCLiiLtcIixob29rbGVmdGFycm93Olwi4oapXCIsaG9va3JpZ2h0YXJyb3c6XCLihqpcIixob3BmOlwi8J2VmVwiLEhvcGY6XCLihI1cIixob3JiYXI6XCLigJVcIixIb3Jpem9udGFsTGluZTpcIuKUgFwiLGhzY3I6XCLwnZK9XCIsSHNjcjpcIuKEi1wiLGhzbGFzaDpcIuKEj1wiLEhzdHJvazpcIsSmXCIsaHN0cm9rOlwixKdcIixIdW1wRG93bkh1bXA6XCLiiY5cIixIdW1wRXF1YWw6XCLiiY9cIixoeWJ1bGw6XCLigYNcIixoeXBoZW46XCLigJBcIixJYWN1dGU6XCLDjVwiLGlhY3V0ZTpcIsOtXCIsaWM6XCLigaNcIixJY2lyYzpcIsOOXCIsaWNpcmM6XCLDrlwiLEljeTpcItCYXCIsaWN5Olwi0LhcIixJZG90OlwixLBcIixJRWN5Olwi0JVcIixpZWN5Olwi0LVcIixpZXhjbDpcIsKhXCIsaWZmOlwi4oeUXCIsaWZyOlwi8J2UplwiLElmcjpcIuKEkVwiLElncmF2ZTpcIsOMXCIsaWdyYXZlOlwiw6xcIixpaTpcIuKFiFwiLGlpaWludDpcIuKojFwiLGlpaW50Olwi4oitXCIsaWluZmluOlwi4qecXCIsaWlvdGE6XCLihKlcIixJSmxpZzpcIsSyXCIsaWpsaWc6XCLEs1wiLEltYWNyOlwixKpcIixpbWFjcjpcIsSrXCIsaW1hZ2U6XCLihJFcIixJbWFnaW5hcnlJOlwi4oWIXCIsaW1hZ2xpbmU6XCLihJBcIixpbWFncGFydDpcIuKEkVwiLGltYXRoOlwixLFcIixJbTpcIuKEkVwiLGltb2Y6XCLiirdcIixpbXBlZDpcIsa1XCIsSW1wbGllczpcIuKHklwiLGluY2FyZTpcIuKEhVwiLGluOlwi4oiIXCIsaW5maW46XCLiiJ5cIixpbmZpbnRpZTpcIuKnnVwiLGlub2RvdDpcIsSxXCIsaW50Y2FsOlwi4oq6XCIsaW50Olwi4oirXCIsSW50Olwi4oisXCIsaW50ZWdlcnM6XCLihKRcIixJbnRlZ3JhbDpcIuKIq1wiLGludGVyY2FsOlwi4oq6XCIsSW50ZXJzZWN0aW9uOlwi4ouCXCIsaW50bGFyaGs6XCLiqJdcIixpbnRwcm9kOlwi4qi8XCIsSW52aXNpYmxlQ29tbWE6XCLigaNcIixJbnZpc2libGVUaW1lczpcIuKBolwiLElPY3k6XCLQgVwiLGlvY3k6XCLRkVwiLElvZ29uOlwixK5cIixpb2dvbjpcIsSvXCIsSW9wZjpcIvCdlYBcIixpb3BmOlwi8J2VmlwiLElvdGE6XCLOmVwiLGlvdGE6XCLOuVwiLGlwcm9kOlwi4qi8XCIsaXF1ZXN0Olwiwr9cIixpc2NyOlwi8J2SvlwiLElzY3I6XCLihJBcIixpc2luOlwi4oiIXCIsaXNpbmRvdDpcIuKLtVwiLGlzaW5FOlwi4ou5XCIsaXNpbnM6XCLii7RcIixpc2luc3Y6XCLii7NcIixpc2ludjpcIuKIiFwiLGl0Olwi4oGiXCIsSXRpbGRlOlwixKhcIixpdGlsZGU6XCLEqVwiLEl1a2N5Olwi0IZcIixpdWtjeTpcItGWXCIsSXVtbDpcIsOPXCIsaXVtbDpcIsOvXCIsSmNpcmM6XCLEtFwiLGpjaXJjOlwixLVcIixKY3k6XCLQmVwiLGpjeTpcItC5XCIsSmZyOlwi8J2UjVwiLGpmcjpcIvCdlKdcIixqbWF0aDpcIsi3XCIsSm9wZjpcIvCdlYFcIixqb3BmOlwi8J2Vm1wiLEpzY3I6XCLwnZKlXCIsanNjcjpcIvCdkr9cIixKc2VyY3k6XCLQiFwiLGpzZXJjeTpcItGYXCIsSnVrY3k6XCLQhFwiLGp1a2N5Olwi0ZRcIixLYXBwYTpcIs6aXCIsa2FwcGE6XCLOulwiLGthcHBhdjpcIs+wXCIsS2NlZGlsOlwixLZcIixrY2VkaWw6XCLEt1wiLEtjeTpcItCaXCIsa2N5Olwi0LpcIixLZnI6XCLwnZSOXCIsa2ZyOlwi8J2UqFwiLGtncmVlbjpcIsS4XCIsS0hjeTpcItClXCIsa2hjeTpcItGFXCIsS0pjeTpcItCMXCIsa2pjeTpcItGcXCIsS29wZjpcIvCdlYJcIixrb3BmOlwi8J2VnFwiLEtzY3I6XCLwnZKmXCIsa3NjcjpcIvCdk4BcIixsQWFycjpcIuKHmlwiLExhY3V0ZTpcIsS5XCIsbGFjdXRlOlwixLpcIixsYWVtcHR5djpcIuKmtFwiLGxhZ3JhbjpcIuKEklwiLExhbWJkYTpcIs6bXCIsbGFtYmRhOlwizrtcIixsYW5nOlwi4p+oXCIsTGFuZzpcIuKfqlwiLGxhbmdkOlwi4qaRXCIsbGFuZ2xlOlwi4p+oXCIsbGFwOlwi4qqFXCIsTGFwbGFjZXRyZjpcIuKEklwiLGxhcXVvOlwiwqtcIixsYXJyYjpcIuKHpFwiLGxhcnJiZnM6XCLipJ9cIixsYXJyOlwi4oaQXCIsTGFycjpcIuKGnlwiLGxBcnI6XCLih5BcIixsYXJyZnM6XCLipJ1cIixsYXJyaGs6XCLihqlcIixsYXJybHA6XCLihqtcIixsYXJycGw6XCLipLlcIixsYXJyc2ltOlwi4qWzXCIsbGFycnRsOlwi4oaiXCIsbGF0YWlsOlwi4qSZXCIsbEF0YWlsOlwi4qSbXCIsbGF0Olwi4qqrXCIsbGF0ZTpcIuKqrVwiLGxhdGVzOlwi4qqt77iAXCIsbGJhcnI6XCLipIxcIixsQmFycjpcIuKkjlwiLGxiYnJrOlwi4p2yXCIsbGJyYWNlOlwie1wiLGxicmFjazpcIltcIixsYnJrZTpcIuKmi1wiLGxicmtzbGQ6XCLipo9cIixsYnJrc2x1Olwi4qaNXCIsTGNhcm9uOlwixL1cIixsY2Fyb246XCLEvlwiLExjZWRpbDpcIsS7XCIsbGNlZGlsOlwixLxcIixsY2VpbDpcIuKMiFwiLGxjdWI6XCJ7XCIsTGN5Olwi0JtcIixsY3k6XCLQu1wiLGxkY2E6XCLipLZcIixsZHF1bzpcIuKAnFwiLGxkcXVvcjpcIuKAnlwiLGxkcmRoYXI6XCLipadcIixsZHJ1c2hhcjpcIuKli1wiLGxkc2g6XCLihrJcIixsZTpcIuKJpFwiLGxFOlwi4ommXCIsTGVmdEFuZ2xlQnJhY2tldDpcIuKfqFwiLExlZnRBcnJvd0JhcjpcIuKHpFwiLGxlZnRhcnJvdzpcIuKGkFwiLExlZnRBcnJvdzpcIuKGkFwiLExlZnRhcnJvdzpcIuKHkFwiLExlZnRBcnJvd1JpZ2h0QXJyb3c6XCLih4ZcIixsZWZ0YXJyb3d0YWlsOlwi4oaiXCIsTGVmdENlaWxpbmc6XCLijIhcIixMZWZ0RG91YmxlQnJhY2tldDpcIuKfplwiLExlZnREb3duVGVlVmVjdG9yOlwi4qWhXCIsTGVmdERvd25WZWN0b3JCYXI6XCLipZlcIixMZWZ0RG93blZlY3RvcjpcIuKHg1wiLExlZnRGbG9vcjpcIuKMilwiLGxlZnRoYXJwb29uZG93bjpcIuKGvVwiLGxlZnRoYXJwb29udXA6XCLihrxcIixsZWZ0bGVmdGFycm93czpcIuKHh1wiLGxlZnRyaWdodGFycm93Olwi4oaUXCIsTGVmdFJpZ2h0QXJyb3c6XCLihpRcIixMZWZ0cmlnaHRhcnJvdzpcIuKHlFwiLGxlZnRyaWdodGFycm93czpcIuKHhlwiLGxlZnRyaWdodGhhcnBvb25zOlwi4oeLXCIsbGVmdHJpZ2h0c3F1aWdhcnJvdzpcIuKGrVwiLExlZnRSaWdodFZlY3RvcjpcIuKljlwiLExlZnRUZWVBcnJvdzpcIuKGpFwiLExlZnRUZWU6XCLiiqNcIixMZWZ0VGVlVmVjdG9yOlwi4qWaXCIsbGVmdHRocmVldGltZXM6XCLii4tcIixMZWZ0VHJpYW5nbGVCYXI6XCLip49cIixMZWZ0VHJpYW5nbGU6XCLiirJcIixMZWZ0VHJpYW5nbGVFcXVhbDpcIuKKtFwiLExlZnRVcERvd25WZWN0b3I6XCLipZFcIixMZWZ0VXBUZWVWZWN0b3I6XCLipaBcIixMZWZ0VXBWZWN0b3JCYXI6XCLipZhcIixMZWZ0VXBWZWN0b3I6XCLihr9cIixMZWZ0VmVjdG9yQmFyOlwi4qWSXCIsTGVmdFZlY3RvcjpcIuKGvFwiLGxFZzpcIuKqi1wiLGxlZzpcIuKLmlwiLGxlcTpcIuKJpFwiLGxlcXE6XCLiiaZcIixsZXFzbGFudDpcIuKpvVwiLGxlc2NjOlwi4qqoXCIsbGVzOlwi4qm9XCIsbGVzZG90Olwi4qm/XCIsbGVzZG90bzpcIuKqgVwiLGxlc2RvdG9yOlwi4qqDXCIsbGVzZzpcIuKLmu+4gFwiLGxlc2dlczpcIuKqk1wiLGxlc3NhcHByb3g6XCLiqoVcIixsZXNzZG90Olwi4ouWXCIsbGVzc2VxZ3RyOlwi4ouaXCIsbGVzc2VxcWd0cjpcIuKqi1wiLExlc3NFcXVhbEdyZWF0ZXI6XCLii5pcIixMZXNzRnVsbEVxdWFsOlwi4ommXCIsTGVzc0dyZWF0ZXI6XCLiibZcIixsZXNzZ3RyOlwi4om2XCIsTGVzc0xlc3M6XCLiqqFcIixsZXNzc2ltOlwi4omyXCIsTGVzc1NsYW50RXF1YWw6XCLiqb1cIixMZXNzVGlsZGU6XCLiibJcIixsZmlzaHQ6XCLipbxcIixsZmxvb3I6XCLijIpcIixMZnI6XCLwnZSPXCIsbGZyOlwi8J2UqVwiLGxnOlwi4om2XCIsbGdFOlwi4qqRXCIsbEhhcjpcIuKlolwiLGxoYXJkOlwi4oa9XCIsbGhhcnU6XCLihrxcIixsaGFydWw6XCLipapcIixsaGJsazpcIuKWhFwiLExKY3k6XCLQiVwiLGxqY3k6XCLRmVwiLGxsYXJyOlwi4oeHXCIsbGw6XCLiiapcIixMbDpcIuKLmFwiLGxsY29ybmVyOlwi4oyeXCIsTGxlZnRhcnJvdzpcIuKHmlwiLGxsaGFyZDpcIuKlq1wiLGxsdHJpOlwi4pe6XCIsTG1pZG90OlwixL9cIixsbWlkb3Q6XCLFgFwiLGxtb3VzdGFjaGU6XCLijrBcIixsbW91c3Q6XCLijrBcIixsbmFwOlwi4qqJXCIsbG5hcHByb3g6XCLiqolcIixsbmU6XCLiqodcIixsbkU6XCLiiahcIixsbmVxOlwi4qqHXCIsbG5lcXE6XCLiiahcIixsbnNpbTpcIuKLplwiLGxvYW5nOlwi4p+sXCIsbG9hcnI6XCLih71cIixsb2JyazpcIuKfplwiLGxvbmdsZWZ0YXJyb3c6XCLin7VcIixMb25nTGVmdEFycm93Olwi4p+1XCIsTG9uZ2xlZnRhcnJvdzpcIuKfuFwiLGxvbmdsZWZ0cmlnaHRhcnJvdzpcIuKft1wiLExvbmdMZWZ0UmlnaHRBcnJvdzpcIuKft1wiLExvbmdsZWZ0cmlnaHRhcnJvdzpcIuKfulwiLGxvbmdtYXBzdG86XCLin7xcIixsb25ncmlnaHRhcnJvdzpcIuKftlwiLExvbmdSaWdodEFycm93Olwi4p+2XCIsTG9uZ3JpZ2h0YXJyb3c6XCLin7lcIixsb29wYXJyb3dsZWZ0Olwi4oarXCIsbG9vcGFycm93cmlnaHQ6XCLihqxcIixsb3BhcjpcIuKmhVwiLExvcGY6XCLwnZWDXCIsbG9wZjpcIvCdlZ1cIixsb3BsdXM6XCLiqK1cIixsb3RpbWVzOlwi4qi0XCIsbG93YXN0Olwi4oiXXCIsbG93YmFyOlwiX1wiLExvd2VyTGVmdEFycm93Olwi4oaZXCIsTG93ZXJSaWdodEFycm93Olwi4oaYXCIsbG96Olwi4peKXCIsbG96ZW5nZTpcIuKXilwiLGxvemY6XCLip6tcIixscGFyOlwiKFwiLGxwYXJsdDpcIuKmk1wiLGxyYXJyOlwi4oeGXCIsbHJjb3JuZXI6XCLijJ9cIixscmhhcjpcIuKHi1wiLGxyaGFyZDpcIuKlrVwiLGxybTpcIuKAjlwiLGxydHJpOlwi4oq/XCIsbHNhcXVvOlwi4oC5XCIsbHNjcjpcIvCdk4FcIixMc2NyOlwi4oSSXCIsbHNoOlwi4oawXCIsTHNoOlwi4oawXCIsbHNpbTpcIuKJslwiLGxzaW1lOlwi4qqNXCIsbHNpbWc6XCLiqo9cIixsc3FiOlwiW1wiLGxzcXVvOlwi4oCYXCIsbHNxdW9yOlwi4oCaXCIsTHN0cm9rOlwixYFcIixsc3Ryb2s6XCLFglwiLGx0Y2M6XCLiqqZcIixsdGNpcjpcIuKpuVwiLGx0OlwiPFwiLExUOlwiPFwiLEx0Olwi4omqXCIsbHRkb3Q6XCLii5ZcIixsdGhyZWU6XCLii4tcIixsdGltZXM6XCLii4lcIixsdGxhcnI6XCLipbZcIixsdHF1ZXN0Olwi4qm7XCIsbHRyaTpcIuKXg1wiLGx0cmllOlwi4oq0XCIsbHRyaWY6XCLil4JcIixsdHJQYXI6XCLippZcIixsdXJkc2hhcjpcIuKlilwiLGx1cnVoYXI6XCLipaZcIixsdmVydG5lcXE6XCLiiajvuIBcIixsdm5FOlwi4omo77iAXCIsbWFjcjpcIsKvXCIsbWFsZTpcIuKZglwiLG1hbHQ6XCLinKBcIixtYWx0ZXNlOlwi4pygXCIsTWFwOlwi4qSFXCIsbWFwOlwi4oamXCIsbWFwc3RvOlwi4oamXCIsbWFwc3RvZG93bjpcIuKGp1wiLG1hcHN0b2xlZnQ6XCLihqRcIixtYXBzdG91cDpcIuKGpVwiLG1hcmtlcjpcIuKWrlwiLG1jb21tYTpcIuKoqVwiLE1jeTpcItCcXCIsbWN5Olwi0LxcIixtZGFzaDpcIuKAlFwiLG1ERG90Olwi4oi6XCIsbWVhc3VyZWRhbmdsZTpcIuKIoVwiLE1lZGl1bVNwYWNlOlwi4oGfXCIsTWVsbGludHJmOlwi4oSzXCIsTWZyOlwi8J2UkFwiLG1mcjpcIvCdlKpcIixtaG86XCLihKdcIixtaWNybzpcIsK1XCIsbWlkYXN0OlwiKlwiLG1pZGNpcjpcIuKrsFwiLG1pZDpcIuKIo1wiLG1pZGRvdDpcIsK3XCIsbWludXNiOlwi4oqfXCIsbWludXM6XCLiiJJcIixtaW51c2Q6XCLiiLhcIixtaW51c2R1Olwi4qiqXCIsTWludXNQbHVzOlwi4oiTXCIsbWxjcDpcIuKrm1wiLG1sZHI6XCLigKZcIixtbnBsdXM6XCLiiJNcIixtb2RlbHM6XCLiiqdcIixNb3BmOlwi8J2VhFwiLG1vcGY6XCLwnZWeXCIsbXA6XCLiiJNcIixtc2NyOlwi8J2TglwiLE1zY3I6XCLihLNcIixtc3Rwb3M6XCLiiL5cIixNdTpcIs6cXCIsbXU6XCLOvFwiLG11bHRpbWFwOlwi4oq4XCIsbXVtYXA6XCLiirhcIixuYWJsYTpcIuKIh1wiLE5hY3V0ZTpcIsWDXCIsbmFjdXRlOlwixYRcIixuYW5nOlwi4oig4oOSXCIsbmFwOlwi4omJXCIsbmFwRTpcIuKpsMy4XCIsbmFwaWQ6XCLiiYvMuFwiLG5hcG9zOlwixYlcIixuYXBwcm94Olwi4omJXCIsbmF0dXJhbDpcIuKZrlwiLG5hdHVyYWxzOlwi4oSVXCIsbmF0dXI6XCLima5cIixuYnNwOlwiwqBcIixuYnVtcDpcIuKJjsy4XCIsbmJ1bXBlOlwi4omPzLhcIixuY2FwOlwi4qmDXCIsTmNhcm9uOlwixYdcIixuY2Fyb246XCLFiFwiLE5jZWRpbDpcIsWFXCIsbmNlZGlsOlwixYZcIixuY29uZzpcIuKJh1wiLG5jb25nZG90Olwi4qmtzLhcIixuY3VwOlwi4qmCXCIsTmN5Olwi0J1cIixuY3k6XCLQvVwiLG5kYXNoOlwi4oCTXCIsbmVhcmhrOlwi4qSkXCIsbmVhcnI6XCLihpdcIixuZUFycjpcIuKHl1wiLG5lYXJyb3c6XCLihpdcIixuZTpcIuKJoFwiLG5lZG90Olwi4omQzLhcIixOZWdhdGl2ZU1lZGl1bVNwYWNlOlwi4oCLXCIsTmVnYXRpdmVUaGlja1NwYWNlOlwi4oCLXCIsTmVnYXRpdmVUaGluU3BhY2U6XCLigItcIixOZWdhdGl2ZVZlcnlUaGluU3BhY2U6XCLigItcIixuZXF1aXY6XCLiiaJcIixuZXNlYXI6XCLipKhcIixuZXNpbTpcIuKJgsy4XCIsTmVzdGVkR3JlYXRlckdyZWF0ZXI6XCLiiatcIixOZXN0ZWRMZXNzTGVzczpcIuKJqlwiLE5ld0xpbmU6XCJcXG5cIixuZXhpc3Q6XCLiiIRcIixuZXhpc3RzOlwi4oiEXCIsTmZyOlwi8J2UkVwiLG5mcjpcIvCdlKtcIixuZ0U6XCLiiafMuFwiLG5nZTpcIuKJsVwiLG5nZXE6XCLiibFcIixuZ2VxcTpcIuKJp8y4XCIsbmdlcXNsYW50Olwi4qm+zLhcIixuZ2VzOlwi4qm+zLhcIixuR2c6XCLii5nMuFwiLG5nc2ltOlwi4om1XCIsbkd0Olwi4omr4oOSXCIsbmd0Olwi4omvXCIsbmd0cjpcIuKJr1wiLG5HdHY6XCLiiavMuFwiLG5oYXJyOlwi4oauXCIsbmhBcnI6XCLih45cIixuaHBhcjpcIuKrslwiLG5pOlwi4oiLXCIsbmlzOlwi4ou8XCIsbmlzZDpcIuKLulwiLG5pdjpcIuKIi1wiLE5KY3k6XCLQilwiLG5qY3k6XCLRmlwiLG5sYXJyOlwi4oaaXCIsbmxBcnI6XCLih41cIixubGRyOlwi4oClXCIsbmxFOlwi4ommzLhcIixubGU6XCLiibBcIixubGVmdGFycm93Olwi4oaaXCIsbkxlZnRhcnJvdzpcIuKHjVwiLG5sZWZ0cmlnaHRhcnJvdzpcIuKGrlwiLG5MZWZ0cmlnaHRhcnJvdzpcIuKHjlwiLG5sZXE6XCLiibBcIixubGVxcTpcIuKJpsy4XCIsbmxlcXNsYW50Olwi4qm9zLhcIixubGVzOlwi4qm9zLhcIixubGVzczpcIuKJrlwiLG5MbDpcIuKLmMy4XCIsbmxzaW06XCLiibRcIixuTHQ6XCLiiarig5JcIixubHQ6XCLiia5cIixubHRyaTpcIuKLqlwiLG5sdHJpZTpcIuKLrFwiLG5MdHY6XCLiiarMuFwiLG5taWQ6XCLiiKRcIixOb0JyZWFrOlwi4oGgXCIsTm9uQnJlYWtpbmdTcGFjZTpcIsKgXCIsbm9wZjpcIvCdlZ9cIixOb3BmOlwi4oSVXCIsTm90Olwi4qusXCIsbm90OlwiwqxcIixOb3RDb25ncnVlbnQ6XCLiiaJcIixOb3RDdXBDYXA6XCLiia1cIixOb3REb3VibGVWZXJ0aWNhbEJhcjpcIuKIplwiLE5vdEVsZW1lbnQ6XCLiiIlcIixOb3RFcXVhbDpcIuKJoFwiLE5vdEVxdWFsVGlsZGU6XCLiiYLMuFwiLE5vdEV4aXN0czpcIuKIhFwiLE5vdEdyZWF0ZXI6XCLiia9cIixOb3RHcmVhdGVyRXF1YWw6XCLiibFcIixOb3RHcmVhdGVyRnVsbEVxdWFsOlwi4omnzLhcIixOb3RHcmVhdGVyR3JlYXRlcjpcIuKJq8y4XCIsTm90R3JlYXRlckxlc3M6XCLiiblcIixOb3RHcmVhdGVyU2xhbnRFcXVhbDpcIuKpvsy4XCIsTm90R3JlYXRlclRpbGRlOlwi4om1XCIsTm90SHVtcERvd25IdW1wOlwi4omOzLhcIixOb3RIdW1wRXF1YWw6XCLiiY/MuFwiLG5vdGluOlwi4oiJXCIsbm90aW5kb3Q6XCLii7XMuFwiLG5vdGluRTpcIuKLucy4XCIsbm90aW52YTpcIuKIiVwiLG5vdGludmI6XCLii7dcIixub3RpbnZjOlwi4ou2XCIsTm90TGVmdFRyaWFuZ2xlQmFyOlwi4qePzLhcIixOb3RMZWZ0VHJpYW5nbGU6XCLii6pcIixOb3RMZWZ0VHJpYW5nbGVFcXVhbDpcIuKLrFwiLE5vdExlc3M6XCLiia5cIixOb3RMZXNzRXF1YWw6XCLiibBcIixOb3RMZXNzR3JlYXRlcjpcIuKJuFwiLE5vdExlc3NMZXNzOlwi4omqzLhcIixOb3RMZXNzU2xhbnRFcXVhbDpcIuKpvcy4XCIsTm90TGVzc1RpbGRlOlwi4om0XCIsTm90TmVzdGVkR3JlYXRlckdyZWF0ZXI6XCLiqqLMuFwiLE5vdE5lc3RlZExlc3NMZXNzOlwi4qqhzLhcIixub3RuaTpcIuKIjFwiLG5vdG5pdmE6XCLiiIxcIixub3RuaXZiOlwi4ou+XCIsbm90bml2YzpcIuKLvVwiLE5vdFByZWNlZGVzOlwi4oqAXCIsTm90UHJlY2VkZXNFcXVhbDpcIuKqr8y4XCIsTm90UHJlY2VkZXNTbGFudEVxdWFsOlwi4ougXCIsTm90UmV2ZXJzZUVsZW1lbnQ6XCLiiIxcIixOb3RSaWdodFRyaWFuZ2xlQmFyOlwi4qeQzLhcIixOb3RSaWdodFRyaWFuZ2xlOlwi4ourXCIsTm90UmlnaHRUcmlhbmdsZUVxdWFsOlwi4outXCIsTm90U3F1YXJlU3Vic2V0Olwi4oqPzLhcIixOb3RTcXVhcmVTdWJzZXRFcXVhbDpcIuKLolwiLE5vdFNxdWFyZVN1cGVyc2V0Olwi4oqQzLhcIixOb3RTcXVhcmVTdXBlcnNldEVxdWFsOlwi4oujXCIsTm90U3Vic2V0Olwi4oqC4oOSXCIsTm90U3Vic2V0RXF1YWw6XCLiiohcIixOb3RTdWNjZWVkczpcIuKKgVwiLE5vdFN1Y2NlZWRzRXF1YWw6XCLiqrDMuFwiLE5vdFN1Y2NlZWRzU2xhbnRFcXVhbDpcIuKLoVwiLE5vdFN1Y2NlZWRzVGlsZGU6XCLiib/MuFwiLE5vdFN1cGVyc2V0Olwi4oqD4oOSXCIsTm90U3VwZXJzZXRFcXVhbDpcIuKKiVwiLE5vdFRpbGRlOlwi4omBXCIsTm90VGlsZGVFcXVhbDpcIuKJhFwiLE5vdFRpbGRlRnVsbEVxdWFsOlwi4omHXCIsTm90VGlsZGVUaWxkZTpcIuKJiVwiLE5vdFZlcnRpY2FsQmFyOlwi4oikXCIsbnBhcmFsbGVsOlwi4oimXCIsbnBhcjpcIuKIplwiLG5wYXJzbDpcIuKrveKDpVwiLG5wYXJ0Olwi4oiCzLhcIixucG9saW50Olwi4qiUXCIsbnByOlwi4oqAXCIsbnByY3VlOlwi4ougXCIsbnByZWM6XCLiioBcIixucHJlY2VxOlwi4qqvzLhcIixucHJlOlwi4qqvzLhcIixucmFycmM6XCLipLPMuFwiLG5yYXJyOlwi4oabXCIsbnJBcnI6XCLih49cIixucmFycnc6XCLihp3MuFwiLG5yaWdodGFycm93Olwi4oabXCIsblJpZ2h0YXJyb3c6XCLih49cIixucnRyaTpcIuKLq1wiLG5ydHJpZTpcIuKLrVwiLG5zYzpcIuKKgVwiLG5zY2N1ZTpcIuKLoVwiLG5zY2U6XCLiqrDMuFwiLE5zY3I6XCLwnZKpXCIsbnNjcjpcIvCdk4NcIixuc2hvcnRtaWQ6XCLiiKRcIixuc2hvcnRwYXJhbGxlbDpcIuKIplwiLG5zaW06XCLiiYFcIixuc2ltZTpcIuKJhFwiLG5zaW1lcTpcIuKJhFwiLG5zbWlkOlwi4oikXCIsbnNwYXI6XCLiiKZcIixuc3FzdWJlOlwi4ouiXCIsbnNxc3VwZTpcIuKLo1wiLG5zdWI6XCLiioRcIixuc3ViRTpcIuKrhcy4XCIsbnN1YmU6XCLiiohcIixuc3Vic2V0Olwi4oqC4oOSXCIsbnN1YnNldGVxOlwi4oqIXCIsbnN1YnNldGVxcTpcIuKrhcy4XCIsbnN1Y2M6XCLiioFcIixuc3VjY2VxOlwi4qqwzLhcIixuc3VwOlwi4oqFXCIsbnN1cEU6XCLiq4bMuFwiLG5zdXBlOlwi4oqJXCIsbnN1cHNldDpcIuKKg+KDklwiLG5zdXBzZXRlcTpcIuKKiVwiLG5zdXBzZXRlcXE6XCLiq4bMuFwiLG50Z2w6XCLiiblcIixOdGlsZGU6XCLDkVwiLG50aWxkZTpcIsOxXCIsbnRsZzpcIuKJuFwiLG50cmlhbmdsZWxlZnQ6XCLii6pcIixudHJpYW5nbGVsZWZ0ZXE6XCLii6xcIixudHJpYW5nbGVyaWdodDpcIuKLq1wiLG50cmlhbmdsZXJpZ2h0ZXE6XCLii61cIixOdTpcIs6dXCIsbnU6XCLOvVwiLG51bTpcIiNcIixudW1lcm86XCLihJZcIixudW1zcDpcIuKAh1wiLG52YXA6XCLiiY3ig5JcIixudmRhc2g6XCLiiqxcIixudkRhc2g6XCLiiq1cIixuVmRhc2g6XCLiiq5cIixuVkRhc2g6XCLiiq9cIixudmdlOlwi4oml4oOSXCIsbnZndDpcIj7ig5JcIixudkhhcnI6XCLipIRcIixudmluZmluOlwi4qeeXCIsbnZsQXJyOlwi4qSCXCIsbnZsZTpcIuKJpOKDklwiLG52bHQ6XCI84oOSXCIsbnZsdHJpZTpcIuKKtOKDklwiLG52ckFycjpcIuKkg1wiLG52cnRyaWU6XCLiirXig5JcIixudnNpbTpcIuKIvOKDklwiLG53YXJoazpcIuKko1wiLG53YXJyOlwi4oaWXCIsbndBcnI6XCLih5ZcIixud2Fycm93Olwi4oaWXCIsbnduZWFyOlwi4qSnXCIsT2FjdXRlOlwiw5NcIixvYWN1dGU6XCLDs1wiLG9hc3Q6XCLiiptcIixPY2lyYzpcIsOUXCIsb2NpcmM6XCLDtFwiLG9jaXI6XCLiippcIixPY3k6XCLQnlwiLG9jeTpcItC+XCIsb2Rhc2g6XCLiip1cIixPZGJsYWM6XCLFkFwiLG9kYmxhYzpcIsWRXCIsb2RpdjpcIuKouFwiLG9kb3Q6XCLiiplcIixvZHNvbGQ6XCLiprxcIixPRWxpZzpcIsWSXCIsb2VsaWc6XCLFk1wiLG9mY2lyOlwi4qa/XCIsT2ZyOlwi8J2UklwiLG9mcjpcIvCdlKxcIixvZ29uOlwiy5tcIixPZ3JhdmU6XCLDklwiLG9ncmF2ZTpcIsOyXCIsb2d0Olwi4qeBXCIsb2hiYXI6XCLiprVcIixvaG06XCLOqVwiLG9pbnQ6XCLiiK5cIixvbGFycjpcIuKGulwiLG9sY2lyOlwi4qa+XCIsb2xjcm9zczpcIuKmu1wiLG9saW5lOlwi4oC+XCIsb2x0Olwi4qeAXCIsT21hY3I6XCLFjFwiLG9tYWNyOlwixY1cIixPbWVnYTpcIs6pXCIsb21lZ2E6XCLPiVwiLE9taWNyb246XCLOn1wiLG9taWNyb246XCLOv1wiLG9taWQ6XCLiprZcIixvbWludXM6XCLiipZcIixPb3BmOlwi8J2VhlwiLG9vcGY6XCLwnZWgXCIsb3BhcjpcIuKmt1wiLE9wZW5DdXJseURvdWJsZVF1b3RlOlwi4oCcXCIsT3BlbkN1cmx5UXVvdGU6XCLigJhcIixvcGVycDpcIuKmuVwiLG9wbHVzOlwi4oqVXCIsb3JhcnI6XCLihrtcIixPcjpcIuKplFwiLG9yOlwi4oioXCIsb3JkOlwi4qmdXCIsb3JkZXI6XCLihLRcIixvcmRlcm9mOlwi4oS0XCIsb3JkZjpcIsKqXCIsb3JkbTpcIsK6XCIsb3JpZ29mOlwi4oq2XCIsb3JvcjpcIuKpllwiLG9yc2xvcGU6XCLiqZdcIixvcnY6XCLiqZtcIixvUzpcIuKTiFwiLE9zY3I6XCLwnZKqXCIsb3NjcjpcIuKEtFwiLE9zbGFzaDpcIsOYXCIsb3NsYXNoOlwiw7hcIixvc29sOlwi4oqYXCIsT3RpbGRlOlwiw5VcIixvdGlsZGU6XCLDtVwiLG90aW1lc2FzOlwi4qi2XCIsT3RpbWVzOlwi4qi3XCIsb3RpbWVzOlwi4oqXXCIsT3VtbDpcIsOWXCIsb3VtbDpcIsO2XCIsb3ZiYXI6XCLijL1cIixPdmVyQmFyOlwi4oC+XCIsT3ZlckJyYWNlOlwi4o+eXCIsT3ZlckJyYWNrZXQ6XCLijrRcIixPdmVyUGFyZW50aGVzaXM6XCLij5xcIixwYXJhOlwiwrZcIixwYXJhbGxlbDpcIuKIpVwiLHBhcjpcIuKIpVwiLHBhcnNpbTpcIuKrs1wiLHBhcnNsOlwi4qu9XCIscGFydDpcIuKIglwiLFBhcnRpYWxEOlwi4oiCXCIsUGN5Olwi0J9cIixwY3k6XCLQv1wiLHBlcmNudDpcIiVcIixwZXJpb2Q6XCIuXCIscGVybWlsOlwi4oCwXCIscGVycDpcIuKKpVwiLHBlcnRlbms6XCLigLFcIixQZnI6XCLwnZSTXCIscGZyOlwi8J2UrVwiLFBoaTpcIs6mXCIscGhpOlwiz4ZcIixwaGl2Olwiz5VcIixwaG1tYXQ6XCLihLNcIixwaG9uZTpcIuKYjlwiLFBpOlwizqBcIixwaTpcIs+AXCIscGl0Y2hmb3JrOlwi4ouUXCIscGl2Olwiz5ZcIixwbGFuY2s6XCLihI9cIixwbGFuY2toOlwi4oSOXCIscGxhbmt2Olwi4oSPXCIscGx1c2FjaXI6XCLiqKNcIixwbHVzYjpcIuKKnlwiLHBsdXNjaXI6XCLiqKJcIixwbHVzOlwiK1wiLHBsdXNkbzpcIuKIlFwiLHBsdXNkdTpcIuKopVwiLHBsdXNlOlwi4qmyXCIsUGx1c01pbnVzOlwiwrFcIixwbHVzbW46XCLCsVwiLHBsdXNzaW06XCLiqKZcIixwbHVzdHdvOlwi4qinXCIscG06XCLCsVwiLFBvaW5jYXJlcGxhbmU6XCLihIxcIixwb2ludGludDpcIuKolVwiLHBvcGY6XCLwnZWhXCIsUG9wZjpcIuKEmVwiLHBvdW5kOlwiwqNcIixwcmFwOlwi4qq3XCIsUHI6XCLiqrtcIixwcjpcIuKJulwiLHByY3VlOlwi4om8XCIscHJlY2FwcHJveDpcIuKqt1wiLHByZWM6XCLiibpcIixwcmVjY3VybHllcTpcIuKJvFwiLFByZWNlZGVzOlwi4om6XCIsUHJlY2VkZXNFcXVhbDpcIuKqr1wiLFByZWNlZGVzU2xhbnRFcXVhbDpcIuKJvFwiLFByZWNlZGVzVGlsZGU6XCLiib5cIixwcmVjZXE6XCLiqq9cIixwcmVjbmFwcHJveDpcIuKquVwiLHByZWNuZXFxOlwi4qq1XCIscHJlY25zaW06XCLii6hcIixwcmU6XCLiqq9cIixwckU6XCLiqrNcIixwcmVjc2ltOlwi4om+XCIscHJpbWU6XCLigLJcIixQcmltZTpcIuKAs1wiLHByaW1lczpcIuKEmVwiLHBybmFwOlwi4qq5XCIscHJuRTpcIuKqtVwiLHBybnNpbTpcIuKLqFwiLHByb2Q6XCLiiI9cIixQcm9kdWN0Olwi4oiPXCIscHJvZmFsYXI6XCLijK5cIixwcm9mbGluZTpcIuKMklwiLHByb2ZzdXJmOlwi4oyTXCIscHJvcDpcIuKInVwiLFByb3BvcnRpb25hbDpcIuKInVwiLFByb3BvcnRpb246XCLiiLdcIixwcm9wdG86XCLiiJ1cIixwcnNpbTpcIuKJvlwiLHBydXJlbDpcIuKKsFwiLFBzY3I6XCLwnZKrXCIscHNjcjpcIvCdk4VcIixQc2k6XCLOqFwiLHBzaTpcIs+IXCIscHVuY3NwOlwi4oCIXCIsUWZyOlwi8J2UlFwiLHFmcjpcIvCdlK5cIixxaW50Olwi4qiMXCIscW9wZjpcIvCdlaJcIixRb3BmOlwi4oSaXCIscXByaW1lOlwi4oGXXCIsUXNjcjpcIvCdkqxcIixxc2NyOlwi8J2ThlwiLHF1YXRlcm5pb25zOlwi4oSNXCIscXVhdGludDpcIuKollwiLHF1ZXN0OlwiP1wiLHF1ZXN0ZXE6XCLiiZ9cIixxdW90OidcIicsUVVPVDonXCInLHJBYXJyOlwi4oebXCIscmFjZTpcIuKIvcyxXCIsUmFjdXRlOlwixZRcIixyYWN1dGU6XCLFlVwiLHJhZGljOlwi4oiaXCIscmFlbXB0eXY6XCLiprNcIixyYW5nOlwi4p+pXCIsUmFuZzpcIuKfq1wiLHJhbmdkOlwi4qaSXCIscmFuZ2U6XCLipqVcIixyYW5nbGU6XCLin6lcIixyYXF1bzpcIsK7XCIscmFycmFwOlwi4qW1XCIscmFycmI6XCLih6VcIixyYXJyYmZzOlwi4qSgXCIscmFycmM6XCLipLNcIixyYXJyOlwi4oaSXCIsUmFycjpcIuKGoFwiLHJBcnI6XCLih5JcIixyYXJyZnM6XCLipJ5cIixyYXJyaGs6XCLihqpcIixyYXJybHA6XCLihqxcIixyYXJycGw6XCLipYVcIixyYXJyc2ltOlwi4qW0XCIsUmFycnRsOlwi4qSWXCIscmFycnRsOlwi4oajXCIscmFycnc6XCLihp1cIixyYXRhaWw6XCLipJpcIixyQXRhaWw6XCLipJxcIixyYXRpbzpcIuKItlwiLHJhdGlvbmFsczpcIuKEmlwiLHJiYXJyOlwi4qSNXCIsckJhcnI6XCLipI9cIixSQmFycjpcIuKkkFwiLHJiYnJrOlwi4p2zXCIscmJyYWNlOlwifVwiLHJicmFjazpcIl1cIixyYnJrZTpcIuKmjFwiLHJicmtzbGQ6XCLipo5cIixyYnJrc2x1Olwi4qaQXCIsUmNhcm9uOlwixZhcIixyY2Fyb246XCLFmVwiLFJjZWRpbDpcIsWWXCIscmNlZGlsOlwixZdcIixyY2VpbDpcIuKMiVwiLHJjdWI6XCJ9XCIsUmN5Olwi0KBcIixyY3k6XCLRgFwiLHJkY2E6XCLipLdcIixyZGxkaGFyOlwi4qWpXCIscmRxdW86XCLigJ1cIixyZHF1b3I6XCLigJ1cIixyZHNoOlwi4oazXCIscmVhbDpcIuKEnFwiLHJlYWxpbmU6XCLihJtcIixyZWFscGFydDpcIuKEnFwiLHJlYWxzOlwi4oSdXCIsUmU6XCLihJxcIixyZWN0Olwi4patXCIscmVnOlwiwq5cIixSRUc6XCLCrlwiLFJldmVyc2VFbGVtZW50Olwi4oiLXCIsUmV2ZXJzZUVxdWlsaWJyaXVtOlwi4oeLXCIsUmV2ZXJzZVVwRXF1aWxpYnJpdW06XCLipa9cIixyZmlzaHQ6XCLipb1cIixyZmxvb3I6XCLijItcIixyZnI6XCLwnZSvXCIsUmZyOlwi4oScXCIsckhhcjpcIuKlpFwiLHJoYXJkOlwi4oeBXCIscmhhcnU6XCLih4BcIixyaGFydWw6XCLipaxcIixSaG86XCLOoVwiLHJobzpcIs+BXCIscmhvdjpcIs+xXCIsUmlnaHRBbmdsZUJyYWNrZXQ6XCLin6lcIixSaWdodEFycm93QmFyOlwi4oelXCIscmlnaHRhcnJvdzpcIuKGklwiLFJpZ2h0QXJyb3c6XCLihpJcIixSaWdodGFycm93Olwi4oeSXCIsUmlnaHRBcnJvd0xlZnRBcnJvdzpcIuKHhFwiLHJpZ2h0YXJyb3d0YWlsOlwi4oajXCIsUmlnaHRDZWlsaW5nOlwi4oyJXCIsUmlnaHREb3VibGVCcmFja2V0Olwi4p+nXCIsUmlnaHREb3duVGVlVmVjdG9yOlwi4qWdXCIsUmlnaHREb3duVmVjdG9yQmFyOlwi4qWVXCIsUmlnaHREb3duVmVjdG9yOlwi4oeCXCIsUmlnaHRGbG9vcjpcIuKMi1wiLHJpZ2h0aGFycG9vbmRvd246XCLih4FcIixyaWdodGhhcnBvb251cDpcIuKHgFwiLHJpZ2h0bGVmdGFycm93czpcIuKHhFwiLHJpZ2h0bGVmdGhhcnBvb25zOlwi4oeMXCIscmlnaHRyaWdodGFycm93czpcIuKHiVwiLHJpZ2h0c3F1aWdhcnJvdzpcIuKGnVwiLFJpZ2h0VGVlQXJyb3c6XCLihqZcIixSaWdodFRlZTpcIuKKolwiLFJpZ2h0VGVlVmVjdG9yOlwi4qWbXCIscmlnaHR0aHJlZXRpbWVzOlwi4ouMXCIsUmlnaHRUcmlhbmdsZUJhcjpcIuKnkFwiLFJpZ2h0VHJpYW5nbGU6XCLiirNcIixSaWdodFRyaWFuZ2xlRXF1YWw6XCLiirVcIixSaWdodFVwRG93blZlY3RvcjpcIuKlj1wiLFJpZ2h0VXBUZWVWZWN0b3I6XCLipZxcIixSaWdodFVwVmVjdG9yQmFyOlwi4qWUXCIsUmlnaHRVcFZlY3RvcjpcIuKGvlwiLFJpZ2h0VmVjdG9yQmFyOlwi4qWTXCIsUmlnaHRWZWN0b3I6XCLih4BcIixyaW5nOlwiy5pcIixyaXNpbmdkb3RzZXE6XCLiiZNcIixybGFycjpcIuKHhFwiLHJsaGFyOlwi4oeMXCIscmxtOlwi4oCPXCIscm1vdXN0YWNoZTpcIuKOsVwiLHJtb3VzdDpcIuKOsVwiLHJubWlkOlwi4quuXCIscm9hbmc6XCLin61cIixyb2FycjpcIuKHvlwiLHJvYnJrOlwi4p+nXCIscm9wYXI6XCLipoZcIixyb3BmOlwi8J2Vo1wiLFJvcGY6XCLihJ1cIixyb3BsdXM6XCLiqK5cIixyb3RpbWVzOlwi4qi1XCIsUm91bmRJbXBsaWVzOlwi4qWwXCIscnBhcjpcIilcIixycGFyZ3Q6XCLippRcIixycHBvbGludDpcIuKoklwiLHJyYXJyOlwi4oeJXCIsUnJpZ2h0YXJyb3c6XCLih5tcIixyc2FxdW86XCLigLpcIixyc2NyOlwi8J2Th1wiLFJzY3I6XCLihJtcIixyc2g6XCLihrFcIixSc2g6XCLihrFcIixyc3FiOlwiXVwiLHJzcXVvOlwi4oCZXCIscnNxdW9yOlwi4oCZXCIscnRocmVlOlwi4ouMXCIscnRpbWVzOlwi4ouKXCIscnRyaTpcIuKWuVwiLHJ0cmllOlwi4oq1XCIscnRyaWY6XCLilrhcIixydHJpbHRyaTpcIuKnjlwiLFJ1bGVEZWxheWVkOlwi4qe0XCIscnVsdWhhcjpcIuKlqFwiLHJ4Olwi4oSeXCIsU2FjdXRlOlwixZpcIixzYWN1dGU6XCLFm1wiLHNicXVvOlwi4oCaXCIsc2NhcDpcIuKquFwiLFNjYXJvbjpcIsWgXCIsc2Nhcm9uOlwixaFcIixTYzpcIuKqvFwiLHNjOlwi4om7XCIsc2NjdWU6XCLiib1cIixzY2U6XCLiqrBcIixzY0U6XCLiqrRcIixTY2VkaWw6XCLFnlwiLHNjZWRpbDpcIsWfXCIsU2NpcmM6XCLFnFwiLHNjaXJjOlwixZ1cIixzY25hcDpcIuKqulwiLHNjbkU6XCLiqrZcIixzY25zaW06XCLii6lcIixzY3BvbGludDpcIuKok1wiLHNjc2ltOlwi4om/XCIsU2N5Olwi0KFcIixzY3k6XCLRgVwiLHNkb3RiOlwi4oqhXCIsc2RvdDpcIuKLhVwiLHNkb3RlOlwi4qmmXCIsc2VhcmhrOlwi4qSlXCIsc2VhcnI6XCLihphcIixzZUFycjpcIuKHmFwiLHNlYXJyb3c6XCLihphcIixzZWN0OlwiwqdcIixzZW1pOlwiO1wiLHNlc3dhcjpcIuKkqVwiLHNldG1pbnVzOlwi4oiWXCIsc2V0bW46XCLiiJZcIixzZXh0Olwi4py2XCIsU2ZyOlwi8J2UllwiLHNmcjpcIvCdlLBcIixzZnJvd246XCLijKJcIixzaGFycDpcIuKZr1wiLFNIQ0hjeTpcItCpXCIsc2hjaGN5Olwi0YlcIixTSGN5Olwi0KhcIixzaGN5Olwi0YhcIixTaG9ydERvd25BcnJvdzpcIuKGk1wiLFNob3J0TGVmdEFycm93Olwi4oaQXCIsc2hvcnRtaWQ6XCLiiKNcIixzaG9ydHBhcmFsbGVsOlwi4oilXCIsU2hvcnRSaWdodEFycm93Olwi4oaSXCIsU2hvcnRVcEFycm93Olwi4oaRXCIsc2h5Olwiwq1cIixTaWdtYTpcIs6jXCIsc2lnbWE6XCLPg1wiLHNpZ21hZjpcIs+CXCIsc2lnbWF2Olwiz4JcIixzaW06XCLiiLxcIixzaW1kb3Q6XCLiqapcIixzaW1lOlwi4omDXCIsc2ltZXE6XCLiiYNcIixzaW1nOlwi4qqeXCIsc2ltZ0U6XCLiqqBcIixzaW1sOlwi4qqdXCIsc2ltbEU6XCLiqp9cIixzaW1uZTpcIuKJhlwiLHNpbXBsdXM6XCLiqKRcIixzaW1yYXJyOlwi4qWyXCIsc2xhcnI6XCLihpBcIixTbWFsbENpcmNsZTpcIuKImFwiLHNtYWxsc2V0bWludXM6XCLiiJZcIixzbWFzaHA6XCLiqLNcIixzbWVwYXJzbDpcIuKnpFwiLHNtaWQ6XCLiiKNcIixzbWlsZTpcIuKMo1wiLHNtdDpcIuKqqlwiLHNtdGU6XCLiqqxcIixzbXRlczpcIuKqrO+4gFwiLFNPRlRjeTpcItCsXCIsc29mdGN5Olwi0YxcIixzb2xiYXI6XCLijL9cIixzb2xiOlwi4qeEXCIsc29sOlwiL1wiLFNvcGY6XCLwnZWKXCIsc29wZjpcIvCdlaRcIixzcGFkZXM6XCLimaBcIixzcGFkZXN1aXQ6XCLimaBcIixzcGFyOlwi4oilXCIsc3FjYXA6XCLiipNcIixzcWNhcHM6XCLiipPvuIBcIixzcWN1cDpcIuKKlFwiLHNxY3VwczpcIuKKlO+4gFwiLFNxcnQ6XCLiiJpcIixzcXN1YjpcIuKKj1wiLHNxc3ViZTpcIuKKkVwiLHNxc3Vic2V0Olwi4oqPXCIsc3FzdWJzZXRlcTpcIuKKkVwiLHNxc3VwOlwi4oqQXCIsc3FzdXBlOlwi4oqSXCIsc3FzdXBzZXQ6XCLiipBcIixzcXN1cHNldGVxOlwi4oqSXCIsc3F1YXJlOlwi4pahXCIsU3F1YXJlOlwi4pahXCIsU3F1YXJlSW50ZXJzZWN0aW9uOlwi4oqTXCIsU3F1YXJlU3Vic2V0Olwi4oqPXCIsU3F1YXJlU3Vic2V0RXF1YWw6XCLiipFcIixTcXVhcmVTdXBlcnNldDpcIuKKkFwiLFNxdWFyZVN1cGVyc2V0RXF1YWw6XCLiipJcIixTcXVhcmVVbmlvbjpcIuKKlFwiLHNxdWFyZjpcIuKWqlwiLHNxdTpcIuKWoVwiLHNxdWY6XCLilqpcIixzcmFycjpcIuKGklwiLFNzY3I6XCLwnZKuXCIsc3NjcjpcIvCdk4hcIixzc2V0bW46XCLiiJZcIixzc21pbGU6XCLijKNcIixzc3RhcmY6XCLii4ZcIixTdGFyOlwi4ouGXCIsc3RhcjpcIuKYhlwiLHN0YXJmOlwi4piFXCIsc3RyYWlnaHRlcHNpbG9uOlwiz7VcIixzdHJhaWdodHBoaTpcIs+VXCIsc3RybnM6XCLCr1wiLHN1YjpcIuKKglwiLFN1YjpcIuKLkFwiLHN1YmRvdDpcIuKqvVwiLHN1YkU6XCLiq4VcIixzdWJlOlwi4oqGXCIsc3ViZWRvdDpcIuKrg1wiLHN1Ym11bHQ6XCLiq4FcIixzdWJuRTpcIuKri1wiLHN1Ym5lOlwi4oqKXCIsc3VicGx1czpcIuKqv1wiLHN1YnJhcnI6XCLipblcIixzdWJzZXQ6XCLiioJcIixTdWJzZXQ6XCLii5BcIixzdWJzZXRlcTpcIuKKhlwiLHN1YnNldGVxcTpcIuKrhVwiLFN1YnNldEVxdWFsOlwi4oqGXCIsc3Vic2V0bmVxOlwi4oqKXCIsc3Vic2V0bmVxcTpcIuKri1wiLHN1YnNpbTpcIuKrh1wiLHN1YnN1YjpcIuKrlVwiLHN1YnN1cDpcIuKrk1wiLHN1Y2NhcHByb3g6XCLiqrhcIixzdWNjOlwi4om7XCIsc3VjY2N1cmx5ZXE6XCLiib1cIixTdWNjZWVkczpcIuKJu1wiLFN1Y2NlZWRzRXF1YWw6XCLiqrBcIixTdWNjZWVkc1NsYW50RXF1YWw6XCLiib1cIixTdWNjZWVkc1RpbGRlOlwi4om/XCIsc3VjY2VxOlwi4qqwXCIsc3VjY25hcHByb3g6XCLiqrpcIixzdWNjbmVxcTpcIuKqtlwiLHN1Y2Nuc2ltOlwi4oupXCIsc3VjY3NpbTpcIuKJv1wiLFN1Y2hUaGF0Olwi4oiLXCIsc3VtOlwi4oiRXCIsU3VtOlwi4oiRXCIsc3VuZzpcIuKZqlwiLHN1cDE6XCLCuVwiLHN1cDI6XCLCslwiLHN1cDM6XCLCs1wiLHN1cDpcIuKKg1wiLFN1cDpcIuKLkVwiLHN1cGRvdDpcIuKqvlwiLHN1cGRzdWI6XCLiq5hcIixzdXBFOlwi4quGXCIsc3VwZTpcIuKKh1wiLHN1cGVkb3Q6XCLiq4RcIixTdXBlcnNldDpcIuKKg1wiLFN1cGVyc2V0RXF1YWw6XCLiiodcIixzdXBoc29sOlwi4p+JXCIsc3VwaHN1YjpcIuKrl1wiLHN1cGxhcnI6XCLipbtcIixzdXBtdWx0Olwi4quCXCIsc3VwbkU6XCLiq4xcIixzdXBuZTpcIuKKi1wiLHN1cHBsdXM6XCLiq4BcIixzdXBzZXQ6XCLiioNcIixTdXBzZXQ6XCLii5FcIixzdXBzZXRlcTpcIuKKh1wiLHN1cHNldGVxcTpcIuKrhlwiLHN1cHNldG5lcTpcIuKKi1wiLHN1cHNldG5lcXE6XCLiq4xcIixzdXBzaW06XCLiq4hcIixzdXBzdWI6XCLiq5RcIixzdXBzdXA6XCLiq5ZcIixzd2FyaGs6XCLipKZcIixzd2FycjpcIuKGmVwiLHN3QXJyOlwi4oeZXCIsc3dhcnJvdzpcIuKGmVwiLHN3bndhcjpcIuKkqlwiLHN6bGlnOlwiw59cIixUYWI6XCJcXHRcIix0YXJnZXQ6XCLijJZcIixUYXU6XCLOpFwiLHRhdTpcIs+EXCIsdGJyazpcIuKOtFwiLFRjYXJvbjpcIsWkXCIsdGNhcm9uOlwixaVcIixUY2VkaWw6XCLFolwiLHRjZWRpbDpcIsWjXCIsVGN5Olwi0KJcIix0Y3k6XCLRglwiLHRkb3Q6XCLig5tcIix0ZWxyZWM6XCLijJVcIixUZnI6XCLwnZSXXCIsdGZyOlwi8J2UsVwiLHRoZXJlNDpcIuKItFwiLHRoZXJlZm9yZTpcIuKItFwiLFRoZXJlZm9yZTpcIuKItFwiLFRoZXRhOlwizphcIix0aGV0YTpcIs64XCIsdGhldGFzeW06XCLPkVwiLHRoZXRhdjpcIs+RXCIsdGhpY2thcHByb3g6XCLiiYhcIix0aGlja3NpbTpcIuKIvFwiLFRoaWNrU3BhY2U6XCLigZ/igIpcIixUaGluU3BhY2U6XCLigIlcIix0aGluc3A6XCLigIlcIix0aGthcDpcIuKJiFwiLHRoa3NpbTpcIuKIvFwiLFRIT1JOOlwiw55cIix0aG9ybjpcIsO+XCIsdGlsZGU6XCLLnFwiLFRpbGRlOlwi4oi8XCIsVGlsZGVFcXVhbDpcIuKJg1wiLFRpbGRlRnVsbEVxdWFsOlwi4omFXCIsVGlsZGVUaWxkZTpcIuKJiFwiLHRpbWVzYmFyOlwi4qixXCIsdGltZXNiOlwi4oqgXCIsdGltZXM6XCLDl1wiLHRpbWVzZDpcIuKosFwiLHRpbnQ6XCLiiK1cIix0b2VhOlwi4qSoXCIsdG9wYm90Olwi4oy2XCIsdG9wY2lyOlwi4quxXCIsdG9wOlwi4oqkXCIsVG9wZjpcIvCdlYtcIix0b3BmOlwi8J2VpVwiLHRvcGZvcms6XCLiq5pcIix0b3NhOlwi4qSpXCIsdHByaW1lOlwi4oC0XCIsdHJhZGU6XCLihKJcIixUUkFERTpcIuKEolwiLHRyaWFuZ2xlOlwi4pa1XCIsdHJpYW5nbGVkb3duOlwi4pa/XCIsdHJpYW5nbGVsZWZ0Olwi4peDXCIsdHJpYW5nbGVsZWZ0ZXE6XCLiirRcIix0cmlhbmdsZXE6XCLiiZxcIix0cmlhbmdsZXJpZ2h0Olwi4pa5XCIsdHJpYW5nbGVyaWdodGVxOlwi4oq1XCIsdHJpZG90Olwi4pesXCIsdHJpZTpcIuKJnFwiLHRyaW1pbnVzOlwi4qi6XCIsVHJpcGxlRG90Olwi4oObXCIsdHJpcGx1czpcIuKouVwiLHRyaXNiOlwi4qeNXCIsdHJpdGltZTpcIuKou1wiLHRycGV6aXVtOlwi4o+iXCIsVHNjcjpcIvCdkq9cIix0c2NyOlwi8J2TiVwiLFRTY3k6XCLQplwiLHRzY3k6XCLRhlwiLFRTSGN5Olwi0ItcIix0c2hjeTpcItGbXCIsVHN0cm9rOlwixaZcIix0c3Ryb2s6XCLFp1wiLHR3aXh0Olwi4omsXCIsdHdvaGVhZGxlZnRhcnJvdzpcIuKGnlwiLHR3b2hlYWRyaWdodGFycm93Olwi4oagXCIsVWFjdXRlOlwiw5pcIix1YWN1dGU6XCLDulwiLHVhcnI6XCLihpFcIixVYXJyOlwi4oafXCIsdUFycjpcIuKHkVwiLFVhcnJvY2lyOlwi4qWJXCIsVWJyY3k6XCLQjlwiLHVicmN5Olwi0Z5cIixVYnJldmU6XCLFrFwiLHVicmV2ZTpcIsWtXCIsVWNpcmM6XCLDm1wiLHVjaXJjOlwiw7tcIixVY3k6XCLQo1wiLHVjeTpcItGDXCIsdWRhcnI6XCLih4VcIixVZGJsYWM6XCLFsFwiLHVkYmxhYzpcIsWxXCIsdWRoYXI6XCLipa5cIix1ZmlzaHQ6XCLipb5cIixVZnI6XCLwnZSYXCIsdWZyOlwi8J2UslwiLFVncmF2ZTpcIsOZXCIsdWdyYXZlOlwiw7lcIix1SGFyOlwi4qWjXCIsdWhhcmw6XCLihr9cIix1aGFycjpcIuKGvlwiLHVoYmxrOlwi4paAXCIsdWxjb3JuOlwi4oycXCIsdWxjb3JuZXI6XCLijJxcIix1bGNyb3A6XCLijI9cIix1bHRyaTpcIuKXuFwiLFVtYWNyOlwixapcIix1bWFjcjpcIsWrXCIsdW1sOlwiwqhcIixVbmRlckJhcjpcIl9cIixVbmRlckJyYWNlOlwi4o+fXCIsVW5kZXJCcmFja2V0Olwi4o61XCIsVW5kZXJQYXJlbnRoZXNpczpcIuKPnVwiLFVuaW9uOlwi4ouDXCIsVW5pb25QbHVzOlwi4oqOXCIsVW9nb246XCLFslwiLHVvZ29uOlwixbNcIixVb3BmOlwi8J2VjFwiLHVvcGY6XCLwnZWmXCIsVXBBcnJvd0JhcjpcIuKkklwiLHVwYXJyb3c6XCLihpFcIixVcEFycm93Olwi4oaRXCIsVXBhcnJvdzpcIuKHkVwiLFVwQXJyb3dEb3duQXJyb3c6XCLih4VcIix1cGRvd25hcnJvdzpcIuKGlVwiLFVwRG93bkFycm93Olwi4oaVXCIsVXBkb3duYXJyb3c6XCLih5VcIixVcEVxdWlsaWJyaXVtOlwi4qWuXCIsdXBoYXJwb29ubGVmdDpcIuKGv1wiLHVwaGFycG9vbnJpZ2h0Olwi4oa+XCIsdXBsdXM6XCLiio5cIixVcHBlckxlZnRBcnJvdzpcIuKGllwiLFVwcGVyUmlnaHRBcnJvdzpcIuKGl1wiLHVwc2k6XCLPhVwiLFVwc2k6XCLPklwiLHVwc2loOlwiz5JcIixVcHNpbG9uOlwizqVcIix1cHNpbG9uOlwiz4VcIixVcFRlZUFycm93Olwi4oalXCIsVXBUZWU6XCLiiqVcIix1cHVwYXJyb3dzOlwi4oeIXCIsdXJjb3JuOlwi4oydXCIsdXJjb3JuZXI6XCLijJ1cIix1cmNyb3A6XCLijI5cIixVcmluZzpcIsWuXCIsdXJpbmc6XCLFr1wiLHVydHJpOlwi4pe5XCIsVXNjcjpcIvCdkrBcIix1c2NyOlwi8J2TilwiLHV0ZG90Olwi4ouwXCIsVXRpbGRlOlwixahcIix1dGlsZGU6XCLFqVwiLHV0cmk6XCLilrVcIix1dHJpZjpcIuKWtFwiLHV1YXJyOlwi4oeIXCIsVXVtbDpcIsOcXCIsdXVtbDpcIsO8XCIsdXdhbmdsZTpcIuKmp1wiLHZhbmdydDpcIuKmnFwiLHZhcmVwc2lsb246XCLPtVwiLHZhcmthcHBhOlwiz7BcIix2YXJub3RoaW5nOlwi4oiFXCIsdmFycGhpOlwiz5VcIix2YXJwaTpcIs+WXCIsdmFycHJvcHRvOlwi4oidXCIsdmFycjpcIuKGlVwiLHZBcnI6XCLih5VcIix2YXJyaG86XCLPsVwiLHZhcnNpZ21hOlwiz4JcIix2YXJzdWJzZXRuZXE6XCLiiorvuIBcIix2YXJzdWJzZXRuZXFxOlwi4quL77iAXCIsdmFyc3Vwc2V0bmVxOlwi4oqL77iAXCIsdmFyc3Vwc2V0bmVxcTpcIuKrjO+4gFwiLHZhcnRoZXRhOlwiz5FcIix2YXJ0cmlhbmdsZWxlZnQ6XCLiirJcIix2YXJ0cmlhbmdsZXJpZ2h0Olwi4oqzXCIsdkJhcjpcIuKrqFwiLFZiYXI6XCLiq6tcIix2QmFydjpcIuKrqVwiLFZjeTpcItCSXCIsdmN5Olwi0LJcIix2ZGFzaDpcIuKKolwiLHZEYXNoOlwi4oqoXCIsVmRhc2g6XCLiiqlcIixWRGFzaDpcIuKKq1wiLFZkYXNobDpcIuKrplwiLHZlZWJhcjpcIuKKu1wiLHZlZTpcIuKIqFwiLFZlZTpcIuKLgVwiLHZlZWVxOlwi4omaXCIsdmVsbGlwOlwi4ouuXCIsdmVyYmFyOlwifFwiLFZlcmJhcjpcIuKAllwiLHZlcnQ6XCJ8XCIsVmVydDpcIuKAllwiLFZlcnRpY2FsQmFyOlwi4oijXCIsVmVydGljYWxMaW5lOlwifFwiLFZlcnRpY2FsU2VwYXJhdG9yOlwi4p2YXCIsVmVydGljYWxUaWxkZTpcIuKJgFwiLFZlcnlUaGluU3BhY2U6XCLigIpcIixWZnI6XCLwnZSZXCIsdmZyOlwi8J2Us1wiLHZsdHJpOlwi4oqyXCIsdm5zdWI6XCLiioLig5JcIix2bnN1cDpcIuKKg+KDklwiLFZvcGY6XCLwnZWNXCIsdm9wZjpcIvCdladcIix2cHJvcDpcIuKInVwiLHZydHJpOlwi4oqzXCIsVnNjcjpcIvCdkrFcIix2c2NyOlwi8J2Ti1wiLHZzdWJuRTpcIuKri++4gFwiLHZzdWJuZTpcIuKKiu+4gFwiLHZzdXBuRTpcIuKrjO+4gFwiLHZzdXBuZTpcIuKKi++4gFwiLFZ2ZGFzaDpcIuKKqlwiLHZ6aWd6YWc6XCLipppcIixXY2lyYzpcIsW0XCIsd2NpcmM6XCLFtVwiLHdlZGJhcjpcIuKpn1wiLHdlZGdlOlwi4oinXCIsV2VkZ2U6XCLii4BcIix3ZWRnZXE6XCLiiZlcIix3ZWllcnA6XCLihJhcIixXZnI6XCLwnZSaXCIsd2ZyOlwi8J2UtFwiLFdvcGY6XCLwnZWOXCIsd29wZjpcIvCdlahcIix3cDpcIuKEmFwiLHdyOlwi4omAXCIsd3JlYXRoOlwi4omAXCIsV3NjcjpcIvCdkrJcIix3c2NyOlwi8J2TjFwiLHhjYXA6XCLii4JcIix4Y2lyYzpcIuKXr1wiLHhjdXA6XCLii4NcIix4ZHRyaTpcIuKWvVwiLFhmcjpcIvCdlJtcIix4ZnI6XCLwnZS1XCIseGhhcnI6XCLin7dcIix4aEFycjpcIuKfulwiLFhpOlwizp5cIix4aTpcIs6+XCIseGxhcnI6XCLin7VcIix4bEFycjpcIuKfuFwiLHhtYXA6XCLin7xcIix4bmlzOlwi4ou7XCIseG9kb3Q6XCLiqIBcIixYb3BmOlwi8J2Vj1wiLHhvcGY6XCLwnZWpXCIseG9wbHVzOlwi4qiBXCIseG90aW1lOlwi4qiCXCIseHJhcnI6XCLin7ZcIix4ckFycjpcIuKfuVwiLFhzY3I6XCLwnZKzXCIseHNjcjpcIvCdk41cIix4c3FjdXA6XCLiqIZcIix4dXBsdXM6XCLiqIRcIix4dXRyaTpcIuKWs1wiLHh2ZWU6XCLii4FcIix4d2VkZ2U6XCLii4BcIixZYWN1dGU6XCLDnVwiLHlhY3V0ZTpcIsO9XCIsWUFjeTpcItCvXCIseWFjeTpcItGPXCIsWWNpcmM6XCLFtlwiLHljaXJjOlwixbdcIixZY3k6XCLQq1wiLHljeTpcItGLXCIseWVuOlwiwqVcIixZZnI6XCLwnZScXCIseWZyOlwi8J2UtlwiLFlJY3k6XCLQh1wiLHlpY3k6XCLRl1wiLFlvcGY6XCLwnZWQXCIseW9wZjpcIvCdlapcIixZc2NyOlwi8J2StFwiLHlzY3I6XCLwnZOOXCIsWVVjeTpcItCuXCIseXVjeTpcItGOXCIseXVtbDpcIsO/XCIsWXVtbDpcIsW4XCIsWmFjdXRlOlwixblcIix6YWN1dGU6XCLFulwiLFpjYXJvbjpcIsW9XCIsemNhcm9uOlwixb5cIixaY3k6XCLQl1wiLHpjeTpcItC3XCIsWmRvdDpcIsW7XCIsemRvdDpcIsW8XCIsemVldHJmOlwi4oSoXCIsWmVyb1dpZHRoU3BhY2U6XCLigItcIixaZXRhOlwizpZcIix6ZXRhOlwizrZcIix6ZnI6XCLwnZS3XCIsWmZyOlwi4oSoXCIsWkhjeTpcItCWXCIsemhjeTpcItC2XCIsemlncmFycjpcIuKHnVwiLHpvcGY6XCLwnZWrXCIsWm9wZjpcIuKEpFwiLFpzY3I6XCLwnZK1XCIsenNjcjpcIvCdk49cIix6d2o6XCLigI1cIix6d25qOlwi4oCMXCJ9fSx7fV0sMjY6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe21vZHVsZS5leHBvcnRzPXtBYWN1dGU6XCLDgVwiLGFhY3V0ZTpcIsOhXCIsQWNpcmM6XCLDglwiLGFjaXJjOlwiw6JcIixhY3V0ZTpcIsK0XCIsQUVsaWc6XCLDhlwiLGFlbGlnOlwiw6ZcIixBZ3JhdmU6XCLDgFwiLGFncmF2ZTpcIsOgXCIsYW1wOlwiJlwiLEFNUDpcIiZcIixBcmluZzpcIsOFXCIsYXJpbmc6XCLDpVwiLEF0aWxkZTpcIsODXCIsYXRpbGRlOlwiw6NcIixBdW1sOlwiw4RcIixhdW1sOlwiw6RcIixicnZiYXI6XCLCplwiLENjZWRpbDpcIsOHXCIsY2NlZGlsOlwiw6dcIixjZWRpbDpcIsK4XCIsY2VudDpcIsKiXCIsY29weTpcIsKpXCIsQ09QWTpcIsKpXCIsY3VycmVuOlwiwqRcIixkZWc6XCLCsFwiLGRpdmlkZTpcIsO3XCIsRWFjdXRlOlwiw4lcIixlYWN1dGU6XCLDqVwiLEVjaXJjOlwiw4pcIixlY2lyYzpcIsOqXCIsRWdyYXZlOlwiw4hcIixlZ3JhdmU6XCLDqFwiLEVUSDpcIsOQXCIsZXRoOlwiw7BcIixFdW1sOlwiw4tcIixldW1sOlwiw6tcIixmcmFjMTI6XCLCvVwiLGZyYWMxNDpcIsK8XCIsZnJhYzM0Olwiwr5cIixndDpcIj5cIixHVDpcIj5cIixJYWN1dGU6XCLDjVwiLGlhY3V0ZTpcIsOtXCIsSWNpcmM6XCLDjlwiLGljaXJjOlwiw65cIixpZXhjbDpcIsKhXCIsSWdyYXZlOlwiw4xcIixpZ3JhdmU6XCLDrFwiLGlxdWVzdDpcIsK/XCIsSXVtbDpcIsOPXCIsaXVtbDpcIsOvXCIsbGFxdW86XCLCq1wiLGx0OlwiPFwiLExUOlwiPFwiLG1hY3I6XCLCr1wiLG1pY3JvOlwiwrVcIixtaWRkb3Q6XCLCt1wiLG5ic3A6XCLCoFwiLG5vdDpcIsKsXCIsTnRpbGRlOlwiw5FcIixudGlsZGU6XCLDsVwiLE9hY3V0ZTpcIsOTXCIsb2FjdXRlOlwiw7NcIixPY2lyYzpcIsOUXCIsb2NpcmM6XCLDtFwiLE9ncmF2ZTpcIsOSXCIsb2dyYXZlOlwiw7JcIixvcmRmOlwiwqpcIixvcmRtOlwiwrpcIixPc2xhc2g6XCLDmFwiLG9zbGFzaDpcIsO4XCIsT3RpbGRlOlwiw5VcIixvdGlsZGU6XCLDtVwiLE91bWw6XCLDllwiLG91bWw6XCLDtlwiLHBhcmE6XCLCtlwiLHBsdXNtbjpcIsKxXCIscG91bmQ6XCLCo1wiLHF1b3Q6J1wiJyxRVU9UOidcIicscmFxdW86XCLCu1wiLHJlZzpcIsKuXCIsUkVHOlwiwq5cIixzZWN0OlwiwqdcIixzaHk6XCLCrVwiLHN1cDE6XCLCuVwiLHN1cDI6XCLCslwiLHN1cDM6XCLCs1wiLHN6bGlnOlwiw59cIixUSE9STjpcIsOeXCIsdGhvcm46XCLDvlwiLHRpbWVzOlwiw5dcIixVYWN1dGU6XCLDmlwiLHVhY3V0ZTpcIsO6XCIsVWNpcmM6XCLDm1wiLHVjaXJjOlwiw7tcIixVZ3JhdmU6XCLDmVwiLHVncmF2ZTpcIsO5XCIsdW1sOlwiwqhcIixVdW1sOlwiw5xcIix1dW1sOlwiw7xcIixZYWN1dGU6XCLDnVwiLHlhY3V0ZTpcIsO9XCIseWVuOlwiwqVcIix5dW1sOlwiw79cIn19LHt9XSwyNzpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7bW9kdWxlLmV4cG9ydHM9e2FtcDpcIiZcIixhcG9zOlwiJ1wiLGd0OlwiPlwiLGx0OlwiPFwiLHF1b3Q6J1wiJ319LHt9XSwyODpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7ZnVuY3Rpb24gRXZlbnRFbWl0dGVyKCl7dGhpcy5fZXZlbnRzPXRoaXMuX2V2ZW50c3x8e307dGhpcy5fbWF4TGlzdGVuZXJzPXRoaXMuX21heExpc3RlbmVyc3x8dW5kZWZpbmVkfW1vZHVsZS5leHBvcnRzPUV2ZW50RW1pdHRlcjtFdmVudEVtaXR0ZXIuRXZlbnRFbWl0dGVyPUV2ZW50RW1pdHRlcjtFdmVudEVtaXR0ZXIucHJvdG90eXBlLl9ldmVudHM9dW5kZWZpbmVkO0V2ZW50RW1pdHRlci5wcm90b3R5cGUuX21heExpc3RlbmVycz11bmRlZmluZWQ7RXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnM9MTA7RXZlbnRFbWl0dGVyLnByb3RvdHlwZS5zZXRNYXhMaXN0ZW5lcnM9ZnVuY3Rpb24obil7aWYoIWlzTnVtYmVyKG4pfHxuPDB8fGlzTmFOKG4pKXRocm93IFR5cGVFcnJvcihcIm4gbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlclwiKTt0aGlzLl9tYXhMaXN0ZW5lcnM9bjtyZXR1cm4gdGhpc307RXZlbnRFbWl0dGVyLnByb3RvdHlwZS5lbWl0PWZ1bmN0aW9uKHR5cGUpe3ZhciBlcixoYW5kbGVyLGxlbixhcmdzLGksbGlzdGVuZXJzO2lmKCF0aGlzLl9ldmVudHMpdGhpcy5fZXZlbnRzPXt9O2lmKHR5cGU9PT1cImVycm9yXCIpe2lmKCF0aGlzLl9ldmVudHMuZXJyb3J8fGlzT2JqZWN0KHRoaXMuX2V2ZW50cy5lcnJvcikmJiF0aGlzLl9ldmVudHMuZXJyb3IubGVuZ3RoKXtlcj1hcmd1bWVudHNbMV07aWYoZXIgaW5zdGFuY2VvZiBFcnJvcil7dGhyb3cgZXJ9ZWxzZXt2YXIgZXJyPW5ldyBFcnJvcignVW5jYXVnaHQsIHVuc3BlY2lmaWVkIFwiZXJyb3JcIiBldmVudC4gKCcrZXIrXCIpXCIpO2Vyci5jb250ZXh0PWVyO3Rocm93IGVycn19fWhhbmRsZXI9dGhpcy5fZXZlbnRzW3R5cGVdO2lmKGlzVW5kZWZpbmVkKGhhbmRsZXIpKXJldHVybiBmYWxzZTtpZihpc0Z1bmN0aW9uKGhhbmRsZXIpKXtzd2l0Y2goYXJndW1lbnRzLmxlbmd0aCl7Y2FzZSAxOmhhbmRsZXIuY2FsbCh0aGlzKTticmVhaztjYXNlIDI6aGFuZGxlci5jYWxsKHRoaXMsYXJndW1lbnRzWzFdKTticmVhaztjYXNlIDM6aGFuZGxlci5jYWxsKHRoaXMsYXJndW1lbnRzWzFdLGFyZ3VtZW50c1syXSk7YnJlYWs7ZGVmYXVsdDphcmdzPUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywxKTtoYW5kbGVyLmFwcGx5KHRoaXMsYXJncyl9fWVsc2UgaWYoaXNPYmplY3QoaGFuZGxlcikpe2FyZ3M9QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLDEpO2xpc3RlbmVycz1oYW5kbGVyLnNsaWNlKCk7bGVuPWxpc3RlbmVycy5sZW5ndGg7Zm9yKGk9MDtpPGxlbjtpKyspbGlzdGVuZXJzW2ldLmFwcGx5KHRoaXMsYXJncyl9cmV0dXJuIHRydWV9O0V2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXI9ZnVuY3Rpb24odHlwZSxsaXN0ZW5lcil7dmFyIG07aWYoIWlzRnVuY3Rpb24obGlzdGVuZXIpKXRocm93IFR5cGVFcnJvcihcImxpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvblwiKTtpZighdGhpcy5fZXZlbnRzKXRoaXMuX2V2ZW50cz17fTtpZih0aGlzLl9ldmVudHMubmV3TGlzdGVuZXIpdGhpcy5lbWl0KFwibmV3TGlzdGVuZXJcIix0eXBlLGlzRnVuY3Rpb24obGlzdGVuZXIubGlzdGVuZXIpP2xpc3RlbmVyLmxpc3RlbmVyOmxpc3RlbmVyKTtpZighdGhpcy5fZXZlbnRzW3R5cGVdKXRoaXMuX2V2ZW50c1t0eXBlXT1saXN0ZW5lcjtlbHNlIGlmKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkpdGhpcy5fZXZlbnRzW3R5cGVdLnB1c2gobGlzdGVuZXIpO2Vsc2UgdGhpcy5fZXZlbnRzW3R5cGVdPVt0aGlzLl9ldmVudHNbdHlwZV0sbGlzdGVuZXJdO2lmKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkmJiF0aGlzLl9ldmVudHNbdHlwZV0ud2FybmVkKXtpZighaXNVbmRlZmluZWQodGhpcy5fbWF4TGlzdGVuZXJzKSl7bT10aGlzLl9tYXhMaXN0ZW5lcnN9ZWxzZXttPUV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzfWlmKG0mJm0+MCYmdGhpcy5fZXZlbnRzW3R5cGVdLmxlbmd0aD5tKXt0aGlzLl9ldmVudHNbdHlwZV0ud2FybmVkPXRydWU7Y29uc29sZS5lcnJvcihcIihub2RlKSB3YXJuaW5nOiBwb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5IFwiK1wibGVhayBkZXRlY3RlZC4gJWQgbGlzdGVuZXJzIGFkZGVkLiBcIitcIlVzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvIGluY3JlYXNlIGxpbWl0LlwiLHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGgpO2lmKHR5cGVvZiBjb25zb2xlLnRyYWNlPT09XCJmdW5jdGlvblwiKXtjb25zb2xlLnRyYWNlKCl9fX1yZXR1cm4gdGhpc307RXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbj1FdmVudEVtaXR0ZXIucHJvdG90eXBlLmFkZExpc3RlbmVyO0V2ZW50RW1pdHRlci5wcm90b3R5cGUub25jZT1mdW5jdGlvbih0eXBlLGxpc3RlbmVyKXtpZighaXNGdW5jdGlvbihsaXN0ZW5lcikpdGhyb3cgVHlwZUVycm9yKFwibGlzdGVuZXIgbXVzdCBiZSBhIGZ1bmN0aW9uXCIpO3ZhciBmaXJlZD1mYWxzZTtmdW5jdGlvbiBnKCl7dGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLGcpO2lmKCFmaXJlZCl7ZmlyZWQ9dHJ1ZTtsaXN0ZW5lci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9fWcubGlzdGVuZXI9bGlzdGVuZXI7dGhpcy5vbih0eXBlLGcpO3JldHVybiB0aGlzfTtFdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyPWZ1bmN0aW9uKHR5cGUsbGlzdGVuZXIpe3ZhciBsaXN0LHBvc2l0aW9uLGxlbmd0aCxpO2lmKCFpc0Z1bmN0aW9uKGxpc3RlbmVyKSl0aHJvdyBUeXBlRXJyb3IoXCJsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb25cIik7aWYoIXRoaXMuX2V2ZW50c3x8IXRoaXMuX2V2ZW50c1t0eXBlXSlyZXR1cm4gdGhpcztsaXN0PXRoaXMuX2V2ZW50c1t0eXBlXTtsZW5ndGg9bGlzdC5sZW5ndGg7cG9zaXRpb249LTE7aWYobGlzdD09PWxpc3RlbmVyfHxpc0Z1bmN0aW9uKGxpc3QubGlzdGVuZXIpJiZsaXN0Lmxpc3RlbmVyPT09bGlzdGVuZXIpe2RlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07aWYodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKXRoaXMuZW1pdChcInJlbW92ZUxpc3RlbmVyXCIsdHlwZSxsaXN0ZW5lcil9ZWxzZSBpZihpc09iamVjdChsaXN0KSl7Zm9yKGk9bGVuZ3RoO2ktLSA+MDspe2lmKGxpc3RbaV09PT1saXN0ZW5lcnx8bGlzdFtpXS5saXN0ZW5lciYmbGlzdFtpXS5saXN0ZW5lcj09PWxpc3RlbmVyKXtwb3NpdGlvbj1pO2JyZWFrfX1pZihwb3NpdGlvbjwwKXJldHVybiB0aGlzO2lmKGxpc3QubGVuZ3RoPT09MSl7bGlzdC5sZW5ndGg9MDtkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdfWVsc2V7bGlzdC5zcGxpY2UocG9zaXRpb24sMSk7XG59aWYodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKXRoaXMuZW1pdChcInJlbW92ZUxpc3RlbmVyXCIsdHlwZSxsaXN0ZW5lcil9cmV0dXJuIHRoaXN9O0V2ZW50RW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzPWZ1bmN0aW9uKHR5cGUpe3ZhciBrZXksbGlzdGVuZXJzO2lmKCF0aGlzLl9ldmVudHMpcmV0dXJuIHRoaXM7aWYoIXRoaXMuX2V2ZW50cy5yZW1vdmVMaXN0ZW5lcil7aWYoYXJndW1lbnRzLmxlbmd0aD09PTApdGhpcy5fZXZlbnRzPXt9O2Vsc2UgaWYodGhpcy5fZXZlbnRzW3R5cGVdKWRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07cmV0dXJuIHRoaXN9aWYoYXJndW1lbnRzLmxlbmd0aD09PTApe2ZvcihrZXkgaW4gdGhpcy5fZXZlbnRzKXtpZihrZXk9PT1cInJlbW92ZUxpc3RlbmVyXCIpY29udGludWU7dGhpcy5yZW1vdmVBbGxMaXN0ZW5lcnMoa2V5KX10aGlzLnJlbW92ZUFsbExpc3RlbmVycyhcInJlbW92ZUxpc3RlbmVyXCIpO3RoaXMuX2V2ZW50cz17fTtyZXR1cm4gdGhpc31saXN0ZW5lcnM9dGhpcy5fZXZlbnRzW3R5cGVdO2lmKGlzRnVuY3Rpb24obGlzdGVuZXJzKSl7dGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLGxpc3RlbmVycyl9ZWxzZSBpZihsaXN0ZW5lcnMpe3doaWxlKGxpc3RlbmVycy5sZW5ndGgpdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLGxpc3RlbmVyc1tsaXN0ZW5lcnMubGVuZ3RoLTFdKX1kZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO3JldHVybiB0aGlzfTtFdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVycz1mdW5jdGlvbih0eXBlKXt2YXIgcmV0O2lmKCF0aGlzLl9ldmVudHN8fCF0aGlzLl9ldmVudHNbdHlwZV0pcmV0PVtdO2Vsc2UgaWYoaXNGdW5jdGlvbih0aGlzLl9ldmVudHNbdHlwZV0pKXJldD1bdGhpcy5fZXZlbnRzW3R5cGVdXTtlbHNlIHJldD10aGlzLl9ldmVudHNbdHlwZV0uc2xpY2UoKTtyZXR1cm4gcmV0fTtFdmVudEVtaXR0ZXIucHJvdG90eXBlLmxpc3RlbmVyQ291bnQ9ZnVuY3Rpb24odHlwZSl7aWYodGhpcy5fZXZlbnRzKXt2YXIgZXZsaXN0ZW5lcj10aGlzLl9ldmVudHNbdHlwZV07aWYoaXNGdW5jdGlvbihldmxpc3RlbmVyKSlyZXR1cm4gMTtlbHNlIGlmKGV2bGlzdGVuZXIpcmV0dXJuIGV2bGlzdGVuZXIubGVuZ3RofXJldHVybiAwfTtFdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudD1mdW5jdGlvbihlbWl0dGVyLHR5cGUpe3JldHVybiBlbWl0dGVyLmxpc3RlbmVyQ291bnQodHlwZSl9O2Z1bmN0aW9uIGlzRnVuY3Rpb24oYXJnKXtyZXR1cm4gdHlwZW9mIGFyZz09PVwiZnVuY3Rpb25cIn1mdW5jdGlvbiBpc051bWJlcihhcmcpe3JldHVybiB0eXBlb2YgYXJnPT09XCJudW1iZXJcIn1mdW5jdGlvbiBpc09iamVjdChhcmcpe3JldHVybiB0eXBlb2YgYXJnPT09XCJvYmplY3RcIiYmYXJnIT09bnVsbH1mdW5jdGlvbiBpc1VuZGVmaW5lZChhcmcpe3JldHVybiBhcmc9PT12b2lkIDB9fSx7fV0sMjk6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe21vZHVsZS5leHBvcnRzPUNvbGxlY3RpbmdIYW5kbGVyO2Z1bmN0aW9uIENvbGxlY3RpbmdIYW5kbGVyKGNicyl7dGhpcy5fY2JzPWNic3x8e307dGhpcy5ldmVudHM9W119dmFyIEVWRU5UUz1yZXF1aXJlKFwiLi9cIikuRVZFTlRTO09iamVjdC5rZXlzKEVWRU5UUykuZm9yRWFjaChmdW5jdGlvbihuYW1lKXtpZihFVkVOVFNbbmFtZV09PT0wKXtuYW1lPVwib25cIituYW1lO0NvbGxlY3RpbmdIYW5kbGVyLnByb3RvdHlwZVtuYW1lXT1mdW5jdGlvbigpe3RoaXMuZXZlbnRzLnB1c2goW25hbWVdKTtpZih0aGlzLl9jYnNbbmFtZV0pdGhpcy5fY2JzW25hbWVdKCl9fWVsc2UgaWYoRVZFTlRTW25hbWVdPT09MSl7bmFtZT1cIm9uXCIrbmFtZTtDb2xsZWN0aW5nSGFuZGxlci5wcm90b3R5cGVbbmFtZV09ZnVuY3Rpb24oYSl7dGhpcy5ldmVudHMucHVzaChbbmFtZSxhXSk7aWYodGhpcy5fY2JzW25hbWVdKXRoaXMuX2Nic1tuYW1lXShhKX19ZWxzZSBpZihFVkVOVFNbbmFtZV09PT0yKXtuYW1lPVwib25cIituYW1lO0NvbGxlY3RpbmdIYW5kbGVyLnByb3RvdHlwZVtuYW1lXT1mdW5jdGlvbihhLGIpe3RoaXMuZXZlbnRzLnB1c2goW25hbWUsYSxiXSk7aWYodGhpcy5fY2JzW25hbWVdKXRoaXMuX2Nic1tuYW1lXShhLGIpfX1lbHNle3Rocm93IEVycm9yKFwid3JvbmcgbnVtYmVyIG9mIGFyZ3VtZW50c1wiKX19KTtDb2xsZWN0aW5nSGFuZGxlci5wcm90b3R5cGUub25yZXNldD1mdW5jdGlvbigpe3RoaXMuZXZlbnRzPVtdO2lmKHRoaXMuX2Nicy5vbnJlc2V0KXRoaXMuX2Nicy5vbnJlc2V0KCl9O0NvbGxlY3RpbmdIYW5kbGVyLnByb3RvdHlwZS5yZXN0YXJ0PWZ1bmN0aW9uKCl7aWYodGhpcy5fY2JzLm9ucmVzZXQpdGhpcy5fY2JzLm9ucmVzZXQoKTtmb3IodmFyIGk9MCxsZW49dGhpcy5ldmVudHMubGVuZ3RoO2k8bGVuO2krKyl7aWYodGhpcy5fY2JzW3RoaXMuZXZlbnRzW2ldWzBdXSl7dmFyIG51bT10aGlzLmV2ZW50c1tpXS5sZW5ndGg7aWYobnVtPT09MSl7dGhpcy5fY2JzW3RoaXMuZXZlbnRzW2ldWzBdXSgpfWVsc2UgaWYobnVtPT09Mil7dGhpcy5fY2JzW3RoaXMuZXZlbnRzW2ldWzBdXSh0aGlzLmV2ZW50c1tpXVsxXSl9ZWxzZXt0aGlzLl9jYnNbdGhpcy5ldmVudHNbaV1bMF1dKHRoaXMuZXZlbnRzW2ldWzFdLHRoaXMuZXZlbnRzW2ldWzJdKX19fX19LHtcIi4vXCI6MzZ9XSwzMDpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7dmFyIGluZGV4PXJlcXVpcmUoXCIuL2luZGV4LmpzXCIpLERvbUhhbmRsZXI9aW5kZXguRG9tSGFuZGxlcixEb21VdGlscz1pbmRleC5Eb21VdGlscztmdW5jdGlvbiBGZWVkSGFuZGxlcihjYWxsYmFjayxvcHRpb25zKXt0aGlzLmluaXQoY2FsbGJhY2ssb3B0aW9ucyl9cmVxdWlyZShcImluaGVyaXRzXCIpKEZlZWRIYW5kbGVyLERvbUhhbmRsZXIpO0ZlZWRIYW5kbGVyLnByb3RvdHlwZS5pbml0PURvbUhhbmRsZXI7ZnVuY3Rpb24gZ2V0RWxlbWVudHMod2hhdCx3aGVyZSl7cmV0dXJuIERvbVV0aWxzLmdldEVsZW1lbnRzQnlUYWdOYW1lKHdoYXQsd2hlcmUsdHJ1ZSl9ZnVuY3Rpb24gZ2V0T25lRWxlbWVudCh3aGF0LHdoZXJlKXtyZXR1cm4gRG9tVXRpbHMuZ2V0RWxlbWVudHNCeVRhZ05hbWUod2hhdCx3aGVyZSx0cnVlLDEpWzBdfWZ1bmN0aW9uIGZldGNoKHdoYXQsd2hlcmUscmVjdXJzZSl7cmV0dXJuIERvbVV0aWxzLmdldFRleHQoRG9tVXRpbHMuZ2V0RWxlbWVudHNCeVRhZ05hbWUod2hhdCx3aGVyZSxyZWN1cnNlLDEpKS50cmltKCl9ZnVuY3Rpb24gYWRkQ29uZGl0aW9uYWxseShvYmoscHJvcCx3aGF0LHdoZXJlLHJlY3Vyc2Upe3ZhciB0bXA9ZmV0Y2god2hhdCx3aGVyZSxyZWN1cnNlKTtpZih0bXApb2JqW3Byb3BdPXRtcH12YXIgaXNWYWxpZEZlZWQ9ZnVuY3Rpb24odmFsdWUpe3JldHVybiB2YWx1ZT09PVwicnNzXCJ8fHZhbHVlPT09XCJmZWVkXCJ8fHZhbHVlPT09XCJyZGY6UkRGXCJ9O0ZlZWRIYW5kbGVyLnByb3RvdHlwZS5vbmVuZD1mdW5jdGlvbigpe3ZhciBmZWVkPXt9LGZlZWRSb290PWdldE9uZUVsZW1lbnQoaXNWYWxpZEZlZWQsdGhpcy5kb20pLHRtcCxjaGlsZHM7aWYoZmVlZFJvb3Qpe2lmKGZlZWRSb290Lm5hbWU9PT1cImZlZWRcIil7Y2hpbGRzPWZlZWRSb290LmNoaWxkcmVuO2ZlZWQudHlwZT1cImF0b21cIjthZGRDb25kaXRpb25hbGx5KGZlZWQsXCJpZFwiLFwiaWRcIixjaGlsZHMpO2FkZENvbmRpdGlvbmFsbHkoZmVlZCxcInRpdGxlXCIsXCJ0aXRsZVwiLGNoaWxkcyk7aWYoKHRtcD1nZXRPbmVFbGVtZW50KFwibGlua1wiLGNoaWxkcykpJiYodG1wPXRtcC5hdHRyaWJzKSYmKHRtcD10bXAuaHJlZikpZmVlZC5saW5rPXRtcDthZGRDb25kaXRpb25hbGx5KGZlZWQsXCJkZXNjcmlwdGlvblwiLFwic3VidGl0bGVcIixjaGlsZHMpO2lmKHRtcD1mZXRjaChcInVwZGF0ZWRcIixjaGlsZHMpKWZlZWQudXBkYXRlZD1uZXcgRGF0ZSh0bXApO2FkZENvbmRpdGlvbmFsbHkoZmVlZCxcImF1dGhvclwiLFwiZW1haWxcIixjaGlsZHMsdHJ1ZSk7ZmVlZC5pdGVtcz1nZXRFbGVtZW50cyhcImVudHJ5XCIsY2hpbGRzKS5tYXAoZnVuY3Rpb24oaXRlbSl7dmFyIGVudHJ5PXt9LHRtcDtpdGVtPWl0ZW0uY2hpbGRyZW47YWRkQ29uZGl0aW9uYWxseShlbnRyeSxcImlkXCIsXCJpZFwiLGl0ZW0pO2FkZENvbmRpdGlvbmFsbHkoZW50cnksXCJ0aXRsZVwiLFwidGl0bGVcIixpdGVtKTtpZigodG1wPWdldE9uZUVsZW1lbnQoXCJsaW5rXCIsaXRlbSkpJiYodG1wPXRtcC5hdHRyaWJzKSYmKHRtcD10bXAuaHJlZikpZW50cnkubGluaz10bXA7aWYodG1wPWZldGNoKFwic3VtbWFyeVwiLGl0ZW0pfHxmZXRjaChcImNvbnRlbnRcIixpdGVtKSllbnRyeS5kZXNjcmlwdGlvbj10bXA7aWYodG1wPWZldGNoKFwidXBkYXRlZFwiLGl0ZW0pKWVudHJ5LnB1YkRhdGU9bmV3IERhdGUodG1wKTtyZXR1cm4gZW50cnl9KX1lbHNle2NoaWxkcz1nZXRPbmVFbGVtZW50KFwiY2hhbm5lbFwiLGZlZWRSb290LmNoaWxkcmVuKS5jaGlsZHJlbjtmZWVkLnR5cGU9ZmVlZFJvb3QubmFtZS5zdWJzdHIoMCwzKTtmZWVkLmlkPVwiXCI7YWRkQ29uZGl0aW9uYWxseShmZWVkLFwidGl0bGVcIixcInRpdGxlXCIsY2hpbGRzKTthZGRDb25kaXRpb25hbGx5KGZlZWQsXCJsaW5rXCIsXCJsaW5rXCIsY2hpbGRzKTthZGRDb25kaXRpb25hbGx5KGZlZWQsXCJkZXNjcmlwdGlvblwiLFwiZGVzY3JpcHRpb25cIixjaGlsZHMpO2lmKHRtcD1mZXRjaChcImxhc3RCdWlsZERhdGVcIixjaGlsZHMpKWZlZWQudXBkYXRlZD1uZXcgRGF0ZSh0bXApO2FkZENvbmRpdGlvbmFsbHkoZmVlZCxcImF1dGhvclwiLFwibWFuYWdpbmdFZGl0b3JcIixjaGlsZHMsdHJ1ZSk7ZmVlZC5pdGVtcz1nZXRFbGVtZW50cyhcIml0ZW1cIixmZWVkUm9vdC5jaGlsZHJlbikubWFwKGZ1bmN0aW9uKGl0ZW0pe3ZhciBlbnRyeT17fSx0bXA7aXRlbT1pdGVtLmNoaWxkcmVuO2FkZENvbmRpdGlvbmFsbHkoZW50cnksXCJpZFwiLFwiZ3VpZFwiLGl0ZW0pO2FkZENvbmRpdGlvbmFsbHkoZW50cnksXCJ0aXRsZVwiLFwidGl0bGVcIixpdGVtKTthZGRDb25kaXRpb25hbGx5KGVudHJ5LFwibGlua1wiLFwibGlua1wiLGl0ZW0pO2FkZENvbmRpdGlvbmFsbHkoZW50cnksXCJkZXNjcmlwdGlvblwiLFwiZGVzY3JpcHRpb25cIixpdGVtKTtpZih0bXA9ZmV0Y2goXCJwdWJEYXRlXCIsaXRlbSkpZW50cnkucHViRGF0ZT1uZXcgRGF0ZSh0bXApO3JldHVybiBlbnRyeX0pfX10aGlzLmRvbT1mZWVkO0RvbUhhbmRsZXIucHJvdG90eXBlLl9oYW5kbGVDYWxsYmFjay5jYWxsKHRoaXMsZmVlZFJvb3Q/bnVsbDpFcnJvcihcImNvdWxkbid0IGZpbmQgcm9vdCBvZiBmZWVkXCIpKX07bW9kdWxlLmV4cG9ydHM9RmVlZEhhbmRsZXJ9LHtcIi4vaW5kZXguanNcIjozNixpbmhlcml0czozOH1dLDMxOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXt2YXIgVG9rZW5pemVyPXJlcXVpcmUoXCIuL1Rva2VuaXplci5qc1wiKTt2YXIgZm9ybVRhZ3M9e2lucHV0OnRydWUsb3B0aW9uOnRydWUsb3B0Z3JvdXA6dHJ1ZSxzZWxlY3Q6dHJ1ZSxidXR0b246dHJ1ZSxkYXRhbGlzdDp0cnVlLHRleHRhcmVhOnRydWV9O3ZhciBvcGVuSW1wbGllc0Nsb3NlPXt0cjp7dHI6dHJ1ZSx0aDp0cnVlLHRkOnRydWV9LHRoOnt0aDp0cnVlfSx0ZDp7dGhlYWQ6dHJ1ZSx0aDp0cnVlLHRkOnRydWV9LGJvZHk6e2hlYWQ6dHJ1ZSxsaW5rOnRydWUsc2NyaXB0OnRydWV9LGxpOntsaTp0cnVlfSxwOntwOnRydWV9LGgxOntwOnRydWV9LGgyOntwOnRydWV9LGgzOntwOnRydWV9LGg0OntwOnRydWV9LGg1OntwOnRydWV9LGg2OntwOnRydWV9LHNlbGVjdDpmb3JtVGFncyxpbnB1dDpmb3JtVGFncyxvdXRwdXQ6Zm9ybVRhZ3MsYnV0dG9uOmZvcm1UYWdzLGRhdGFsaXN0OmZvcm1UYWdzLHRleHRhcmVhOmZvcm1UYWdzLG9wdGlvbjp7b3B0aW9uOnRydWV9LG9wdGdyb3VwOntvcHRncm91cDp0cnVlfX07dmFyIHZvaWRFbGVtZW50cz17X19wcm90b19fOm51bGwsYXJlYTp0cnVlLGJhc2U6dHJ1ZSxiYXNlZm9udDp0cnVlLGJyOnRydWUsY29sOnRydWUsY29tbWFuZDp0cnVlLGVtYmVkOnRydWUsZnJhbWU6dHJ1ZSxocjp0cnVlLGltZzp0cnVlLGlucHV0OnRydWUsaXNpbmRleDp0cnVlLGtleWdlbjp0cnVlLGxpbms6dHJ1ZSxtZXRhOnRydWUscGFyYW06dHJ1ZSxzb3VyY2U6dHJ1ZSx0cmFjazp0cnVlLHdicjp0cnVlLHBhdGg6dHJ1ZSxjaXJjbGU6dHJ1ZSxlbGxpcHNlOnRydWUsbGluZTp0cnVlLHJlY3Q6dHJ1ZSx1c2U6dHJ1ZSxzdG9wOnRydWUscG9seWxpbmU6dHJ1ZSxwb2x5Z29uOnRydWV9O3ZhciByZV9uYW1lRW5kPS9cXHN8XFwvLztmdW5jdGlvbiBQYXJzZXIoY2JzLG9wdGlvbnMpe3RoaXMuX29wdGlvbnM9b3B0aW9uc3x8e307dGhpcy5fY2JzPWNic3x8e307dGhpcy5fdGFnbmFtZT1cIlwiO3RoaXMuX2F0dHJpYm5hbWU9XCJcIjt0aGlzLl9hdHRyaWJ2YWx1ZT1cIlwiO3RoaXMuX2F0dHJpYnM9bnVsbDt0aGlzLl9zdGFjaz1bXTt0aGlzLnN0YXJ0SW5kZXg9MDt0aGlzLmVuZEluZGV4PW51bGw7dGhpcy5fbG93ZXJDYXNlVGFnTmFtZXM9XCJsb3dlckNhc2VUYWdzXCJpbiB0aGlzLl9vcHRpb25zPyEhdGhpcy5fb3B0aW9ucy5sb3dlckNhc2VUYWdzOiF0aGlzLl9vcHRpb25zLnhtbE1vZGU7dGhpcy5fbG93ZXJDYXNlQXR0cmlidXRlTmFtZXM9XCJsb3dlckNhc2VBdHRyaWJ1dGVOYW1lc1wiaW4gdGhpcy5fb3B0aW9ucz8hIXRoaXMuX29wdGlvbnMubG93ZXJDYXNlQXR0cmlidXRlTmFtZXM6IXRoaXMuX29wdGlvbnMueG1sTW9kZTtpZih0aGlzLl9vcHRpb25zLlRva2VuaXplcil7VG9rZW5pemVyPXRoaXMuX29wdGlvbnMuVG9rZW5pemVyfXRoaXMuX3Rva2VuaXplcj1uZXcgVG9rZW5pemVyKHRoaXMuX29wdGlvbnMsdGhpcyk7aWYodGhpcy5fY2JzLm9ucGFyc2VyaW5pdCl0aGlzLl9jYnMub25wYXJzZXJpbml0KHRoaXMpfXJlcXVpcmUoXCJpbmhlcml0c1wiKShQYXJzZXIscmVxdWlyZShcImV2ZW50c1wiKS5FdmVudEVtaXR0ZXIpO1BhcnNlci5wcm90b3R5cGUuX3VwZGF0ZVBvc2l0aW9uPWZ1bmN0aW9uKGluaXRpYWxPZmZzZXQpe2lmKHRoaXMuZW5kSW5kZXg9PT1udWxsKXtpZih0aGlzLl90b2tlbml6ZXIuX3NlY3Rpb25TdGFydDw9aW5pdGlhbE9mZnNldCl7dGhpcy5zdGFydEluZGV4PTB9ZWxzZXt0aGlzLnN0YXJ0SW5kZXg9dGhpcy5fdG9rZW5pemVyLl9zZWN0aW9uU3RhcnQtaW5pdGlhbE9mZnNldH19ZWxzZSB0aGlzLnN0YXJ0SW5kZXg9dGhpcy5lbmRJbmRleCsxO3RoaXMuZW5kSW5kZXg9dGhpcy5fdG9rZW5pemVyLmdldEFic29sdXRlSW5kZXgoKX07UGFyc2VyLnByb3RvdHlwZS5vbnRleHQ9ZnVuY3Rpb24oZGF0YSl7dGhpcy5fdXBkYXRlUG9zaXRpb24oMSk7dGhpcy5lbmRJbmRleC0tO2lmKHRoaXMuX2Nicy5vbnRleHQpdGhpcy5fY2JzLm9udGV4dChkYXRhKX07UGFyc2VyLnByb3RvdHlwZS5vbm9wZW50YWduYW1lPWZ1bmN0aW9uKG5hbWUpe2lmKHRoaXMuX2xvd2VyQ2FzZVRhZ05hbWVzKXtuYW1lPW5hbWUudG9Mb3dlckNhc2UoKX10aGlzLl90YWduYW1lPW5hbWU7aWYoIXRoaXMuX29wdGlvbnMueG1sTW9kZSYmbmFtZSBpbiBvcGVuSW1wbGllc0Nsb3NlKXtmb3IodmFyIGVsOyhlbD10aGlzLl9zdGFja1t0aGlzLl9zdGFjay5sZW5ndGgtMV0paW4gb3BlbkltcGxpZXNDbG9zZVtuYW1lXTt0aGlzLm9uY2xvc2V0YWcoZWwpKTt9aWYodGhpcy5fb3B0aW9ucy54bWxNb2RlfHwhKG5hbWUgaW4gdm9pZEVsZW1lbnRzKSl7dGhpcy5fc3RhY2sucHVzaChuYW1lKX1pZih0aGlzLl9jYnMub25vcGVudGFnbmFtZSl0aGlzLl9jYnMub25vcGVudGFnbmFtZShuYW1lKTtpZih0aGlzLl9jYnMub25vcGVudGFnKXRoaXMuX2F0dHJpYnM9e319O1BhcnNlci5wcm90b3R5cGUub25vcGVudGFnZW5kPWZ1bmN0aW9uKCl7dGhpcy5fdXBkYXRlUG9zaXRpb24oMSk7aWYodGhpcy5fYXR0cmlicyl7aWYodGhpcy5fY2JzLm9ub3BlbnRhZyl0aGlzLl9jYnMub25vcGVudGFnKHRoaXMuX3RhZ25hbWUsdGhpcy5fYXR0cmlicyk7dGhpcy5fYXR0cmlicz1udWxsfWlmKCF0aGlzLl9vcHRpb25zLnhtbE1vZGUmJnRoaXMuX2Nicy5vbmNsb3NldGFnJiZ0aGlzLl90YWduYW1lIGluIHZvaWRFbGVtZW50cyl7dGhpcy5fY2JzLm9uY2xvc2V0YWcodGhpcy5fdGFnbmFtZSl9dGhpcy5fdGFnbmFtZT1cIlwifTtQYXJzZXIucHJvdG90eXBlLm9uY2xvc2V0YWc9ZnVuY3Rpb24obmFtZSl7dGhpcy5fdXBkYXRlUG9zaXRpb24oMSk7aWYodGhpcy5fbG93ZXJDYXNlVGFnTmFtZXMpe25hbWU9bmFtZS50b0xvd2VyQ2FzZSgpfWlmKHRoaXMuX3N0YWNrLmxlbmd0aCYmKCEobmFtZSBpbiB2b2lkRWxlbWVudHMpfHx0aGlzLl9vcHRpb25zLnhtbE1vZGUpKXt2YXIgcG9zPXRoaXMuX3N0YWNrLmxhc3RJbmRleE9mKG5hbWUpO2lmKHBvcyE9PS0xKXtpZih0aGlzLl9jYnMub25jbG9zZXRhZyl7cG9zPXRoaXMuX3N0YWNrLmxlbmd0aC1wb3M7d2hpbGUocG9zLS0pdGhpcy5fY2JzLm9uY2xvc2V0YWcodGhpcy5fc3RhY2sucG9wKCkpfWVsc2UgdGhpcy5fc3RhY2subGVuZ3RoPXBvc31lbHNlIGlmKG5hbWU9PT1cInBcIiYmIXRoaXMuX29wdGlvbnMueG1sTW9kZSl7dGhpcy5vbm9wZW50YWduYW1lKG5hbWUpO3RoaXMuX2Nsb3NlQ3VycmVudFRhZygpfX1lbHNlIGlmKCF0aGlzLl9vcHRpb25zLnhtbE1vZGUmJihuYW1lPT09XCJiclwifHxuYW1lPT09XCJwXCIpKXt0aGlzLm9ub3BlbnRhZ25hbWUobmFtZSk7dGhpcy5fY2xvc2VDdXJyZW50VGFnKCl9fTtQYXJzZXIucHJvdG90eXBlLm9uc2VsZmNsb3Npbmd0YWc9ZnVuY3Rpb24oKXtpZih0aGlzLl9vcHRpb25zLnhtbE1vZGV8fHRoaXMuX29wdGlvbnMucmVjb2duaXplU2VsZkNsb3Npbmcpe3RoaXMuX2Nsb3NlQ3VycmVudFRhZygpfWVsc2V7dGhpcy5vbm9wZW50YWdlbmQoKX19O1BhcnNlci5wcm90b3R5cGUuX2Nsb3NlQ3VycmVudFRhZz1mdW5jdGlvbigpe3ZhciBuYW1lPXRoaXMuX3RhZ25hbWU7dGhpcy5vbm9wZW50YWdlbmQoKTtpZih0aGlzLl9zdGFja1t0aGlzLl9zdGFjay5sZW5ndGgtMV09PT1uYW1lKXtpZih0aGlzLl9jYnMub25jbG9zZXRhZyl7dGhpcy5fY2JzLm9uY2xvc2V0YWcobmFtZSl9dGhpcy5fc3RhY2sucG9wKCl9fTtQYXJzZXIucHJvdG90eXBlLm9uYXR0cmlibmFtZT1mdW5jdGlvbihuYW1lKXtpZih0aGlzLl9sb3dlckNhc2VBdHRyaWJ1dGVOYW1lcyl7bmFtZT1uYW1lLnRvTG93ZXJDYXNlKCl9dGhpcy5fYXR0cmlibmFtZT1uYW1lfTtQYXJzZXIucHJvdG90eXBlLm9uYXR0cmliZGF0YT1mdW5jdGlvbih2YWx1ZSl7dGhpcy5fYXR0cmlidmFsdWUrPXZhbHVlfTtQYXJzZXIucHJvdG90eXBlLm9uYXR0cmliZW5kPWZ1bmN0aW9uKCl7aWYodGhpcy5fY2JzLm9uYXR0cmlidXRlKXRoaXMuX2Nicy5vbmF0dHJpYnV0ZSh0aGlzLl9hdHRyaWJuYW1lLHRoaXMuX2F0dHJpYnZhbHVlKTtpZih0aGlzLl9hdHRyaWJzJiYhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHRoaXMuX2F0dHJpYnMsdGhpcy5fYXR0cmlibmFtZSkpe3RoaXMuX2F0dHJpYnNbdGhpcy5fYXR0cmlibmFtZV09dGhpcy5fYXR0cmlidmFsdWV9dGhpcy5fYXR0cmlibmFtZT1cIlwiO3RoaXMuX2F0dHJpYnZhbHVlPVwiXCJ9O1BhcnNlci5wcm90b3R5cGUuX2dldEluc3RydWN0aW9uTmFtZT1mdW5jdGlvbih2YWx1ZSl7dmFyIGlkeD12YWx1ZS5zZWFyY2gocmVfbmFtZUVuZCksbmFtZT1pZHg8MD92YWx1ZTp2YWx1ZS5zdWJzdHIoMCxpZHgpO2lmKHRoaXMuX2xvd2VyQ2FzZVRhZ05hbWVzKXtuYW1lPW5hbWUudG9Mb3dlckNhc2UoKX1yZXR1cm4gbmFtZX07UGFyc2VyLnByb3RvdHlwZS5vbmRlY2xhcmF0aW9uPWZ1bmN0aW9uKHZhbHVlKXtpZih0aGlzLl9jYnMub25wcm9jZXNzaW5naW5zdHJ1Y3Rpb24pe3ZhciBuYW1lPXRoaXMuX2dldEluc3RydWN0aW9uTmFtZSh2YWx1ZSk7dGhpcy5fY2JzLm9ucHJvY2Vzc2luZ2luc3RydWN0aW9uKFwiIVwiK25hbWUsXCIhXCIrdmFsdWUpfX07UGFyc2VyLnByb3RvdHlwZS5vbnByb2Nlc3NpbmdpbnN0cnVjdGlvbj1mdW5jdGlvbih2YWx1ZSl7aWYodGhpcy5fY2JzLm9ucHJvY2Vzc2luZ2luc3RydWN0aW9uKXt2YXIgbmFtZT10aGlzLl9nZXRJbnN0cnVjdGlvbk5hbWUodmFsdWUpO3RoaXMuX2Nicy5vbnByb2Nlc3NpbmdpbnN0cnVjdGlvbihcIj9cIituYW1lLFwiP1wiK3ZhbHVlKX19O1BhcnNlci5wcm90b3R5cGUub25jb21tZW50PWZ1bmN0aW9uKHZhbHVlKXt0aGlzLl91cGRhdGVQb3NpdGlvbig0KTtpZih0aGlzLl9jYnMub25jb21tZW50KXRoaXMuX2Nicy5vbmNvbW1lbnQodmFsdWUpO2lmKHRoaXMuX2Nicy5vbmNvbW1lbnRlbmQpdGhpcy5fY2JzLm9uY29tbWVudGVuZCgpfTtQYXJzZXIucHJvdG90eXBlLm9uY2RhdGE9ZnVuY3Rpb24odmFsdWUpe3RoaXMuX3VwZGF0ZVBvc2l0aW9uKDEpO2lmKHRoaXMuX29wdGlvbnMueG1sTW9kZXx8dGhpcy5fb3B0aW9ucy5yZWNvZ25pemVDREFUQSl7aWYodGhpcy5fY2JzLm9uY2RhdGFzdGFydCl0aGlzLl9jYnMub25jZGF0YXN0YXJ0KCk7aWYodGhpcy5fY2JzLm9udGV4dCl0aGlzLl9jYnMub250ZXh0KHZhbHVlKTtpZih0aGlzLl9jYnMub25jZGF0YWVuZCl0aGlzLl9jYnMub25jZGF0YWVuZCgpfWVsc2V7dGhpcy5vbmNvbW1lbnQoXCJbQ0RBVEFbXCIrdmFsdWUrXCJdXVwiKX19O1BhcnNlci5wcm90b3R5cGUub25lcnJvcj1mdW5jdGlvbihlcnIpe2lmKHRoaXMuX2Nicy5vbmVycm9yKXRoaXMuX2Nicy5vbmVycm9yKGVycil9O1BhcnNlci5wcm90b3R5cGUub25lbmQ9ZnVuY3Rpb24oKXtpZih0aGlzLl9jYnMub25jbG9zZXRhZyl7Zm9yKHZhciBpPXRoaXMuX3N0YWNrLmxlbmd0aDtpPjA7dGhpcy5fY2JzLm9uY2xvc2V0YWcodGhpcy5fc3RhY2tbLS1pXSkpO31pZih0aGlzLl9jYnMub25lbmQpdGhpcy5fY2JzLm9uZW5kKCl9O1BhcnNlci5wcm90b3R5cGUucmVzZXQ9ZnVuY3Rpb24oKXtpZih0aGlzLl9jYnMub25yZXNldCl0aGlzLl9jYnMub25yZXNldCgpO3RoaXMuX3Rva2VuaXplci5yZXNldCgpO3RoaXMuX3RhZ25hbWU9XCJcIjt0aGlzLl9hdHRyaWJuYW1lPVwiXCI7dGhpcy5fYXR0cmlicz1udWxsO3RoaXMuX3N0YWNrPVtdO2lmKHRoaXMuX2Nicy5vbnBhcnNlcmluaXQpdGhpcy5fY2JzLm9ucGFyc2VyaW5pdCh0aGlzKX07UGFyc2VyLnByb3RvdHlwZS5wYXJzZUNvbXBsZXRlPWZ1bmN0aW9uKGRhdGEpe3RoaXMucmVzZXQoKTt0aGlzLmVuZChkYXRhKX07UGFyc2VyLnByb3RvdHlwZS53cml0ZT1mdW5jdGlvbihjaHVuayl7dGhpcy5fdG9rZW5pemVyLndyaXRlKGNodW5rKX07UGFyc2VyLnByb3RvdHlwZS5lbmQ9ZnVuY3Rpb24oY2h1bmspe3RoaXMuX3Rva2VuaXplci5lbmQoY2h1bmspfTtQYXJzZXIucHJvdG90eXBlLnBhdXNlPWZ1bmN0aW9uKCl7dGhpcy5fdG9rZW5pemVyLnBhdXNlKCl9O1BhcnNlci5wcm90b3R5cGUucmVzdW1lPWZ1bmN0aW9uKCl7dGhpcy5fdG9rZW5pemVyLnJlc3VtZSgpfTtQYXJzZXIucHJvdG90eXBlLnBhcnNlQ2h1bms9UGFyc2VyLnByb3RvdHlwZS53cml0ZTtQYXJzZXIucHJvdG90eXBlLmRvbmU9UGFyc2VyLnByb3RvdHlwZS5lbmQ7bW9kdWxlLmV4cG9ydHM9UGFyc2VyfSx7XCIuL1Rva2VuaXplci5qc1wiOjM0LGV2ZW50czoyOCxpbmhlcml0czozOH1dLDMyOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXttb2R1bGUuZXhwb3J0cz1Qcm94eUhhbmRsZXI7ZnVuY3Rpb24gUHJveHlIYW5kbGVyKGNicyl7dGhpcy5fY2JzPWNic3x8e319dmFyIEVWRU5UUz1yZXF1aXJlKFwiLi9cIikuRVZFTlRTO09iamVjdC5rZXlzKEVWRU5UUykuZm9yRWFjaChmdW5jdGlvbihuYW1lKXtpZihFVkVOVFNbbmFtZV09PT0wKXtuYW1lPVwib25cIituYW1lO1Byb3h5SGFuZGxlci5wcm90b3R5cGVbbmFtZV09ZnVuY3Rpb24oKXtpZih0aGlzLl9jYnNbbmFtZV0pdGhpcy5fY2JzW25hbWVdKCl9fWVsc2UgaWYoRVZFTlRTW25hbWVdPT09MSl7bmFtZT1cIm9uXCIrbmFtZTtQcm94eUhhbmRsZXIucHJvdG90eXBlW25hbWVdPWZ1bmN0aW9uKGEpe2lmKHRoaXMuX2Nic1tuYW1lXSl0aGlzLl9jYnNbbmFtZV0oYSl9fWVsc2UgaWYoRVZFTlRTW25hbWVdPT09Mil7bmFtZT1cIm9uXCIrbmFtZTtQcm94eUhhbmRsZXIucHJvdG90eXBlW25hbWVdPWZ1bmN0aW9uKGEsYil7aWYodGhpcy5fY2JzW25hbWVdKXRoaXMuX2Nic1tuYW1lXShhLGIpfX1lbHNle3Rocm93IEVycm9yKFwid3JvbmcgbnVtYmVyIG9mIGFyZ3VtZW50c1wiKX19KX0se1wiLi9cIjozNn1dLDMzOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXttb2R1bGUuZXhwb3J0cz1TdHJlYW07dmFyIFBhcnNlcj1yZXF1aXJlKFwiLi9Xcml0YWJsZVN0cmVhbS5qc1wiKTtmdW5jdGlvbiBTdHJlYW0ob3B0aW9ucyl7UGFyc2VyLmNhbGwodGhpcyxuZXcgQ2JzKHRoaXMpLG9wdGlvbnMpfXJlcXVpcmUoXCJpbmhlcml0c1wiKShTdHJlYW0sUGFyc2VyKTtTdHJlYW0ucHJvdG90eXBlLnJlYWRhYmxlPXRydWU7ZnVuY3Rpb24gQ2JzKHNjb3BlKXt0aGlzLnNjb3BlPXNjb3BlfXZhciBFVkVOVFM9cmVxdWlyZShcIi4uL1wiKS5FVkVOVFM7T2JqZWN0LmtleXMoRVZFTlRTKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpe2lmKEVWRU5UU1tuYW1lXT09PTApe0Nicy5wcm90b3R5cGVbXCJvblwiK25hbWVdPWZ1bmN0aW9uKCl7dGhpcy5zY29wZS5lbWl0KG5hbWUpfX1lbHNlIGlmKEVWRU5UU1tuYW1lXT09PTEpe0Nicy5wcm90b3R5cGVbXCJvblwiK25hbWVdPWZ1bmN0aW9uKGEpe3RoaXMuc2NvcGUuZW1pdChuYW1lLGEpfX1lbHNlIGlmKEVWRU5UU1tuYW1lXT09PTIpe0Nicy5wcm90b3R5cGVbXCJvblwiK25hbWVdPWZ1bmN0aW9uKGEsYil7dGhpcy5zY29wZS5lbWl0KG5hbWUsYSxiKX19ZWxzZXt0aHJvdyBFcnJvcihcIndyb25nIG51bWJlciBvZiBhcmd1bWVudHMhXCIpfX0pfSx7XCIuLi9cIjozNixcIi4vV3JpdGFibGVTdHJlYW0uanNcIjozNSxpbmhlcml0czozOH1dLDM0OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXttb2R1bGUuZXhwb3J0cz1Ub2tlbml6ZXI7dmFyIGRlY29kZUNvZGVQb2ludD1yZXF1aXJlKFwiZW50aXRpZXMvbGliL2RlY29kZV9jb2RlcG9pbnQuanNcIiksZW50aXR5TWFwPXJlcXVpcmUoXCJlbnRpdGllcy9tYXBzL2VudGl0aWVzLmpzb25cIiksbGVnYWN5TWFwPXJlcXVpcmUoXCJlbnRpdGllcy9tYXBzL2xlZ2FjeS5qc29uXCIpLHhtbE1hcD1yZXF1aXJlKFwiZW50aXRpZXMvbWFwcy94bWwuanNvblwiKSxpPTAsVEVYVD1pKyssQkVGT1JFX1RBR19OQU1FPWkrKyxJTl9UQUdfTkFNRT1pKyssSU5fU0VMRl9DTE9TSU5HX1RBRz1pKyssQkVGT1JFX0NMT1NJTkdfVEFHX05BTUU9aSsrLElOX0NMT1NJTkdfVEFHX05BTUU9aSsrLEFGVEVSX0NMT1NJTkdfVEFHX05BTUU9aSsrLEJFRk9SRV9BVFRSSUJVVEVfTkFNRT1pKyssSU5fQVRUUklCVVRFX05BTUU9aSsrLEFGVEVSX0FUVFJJQlVURV9OQU1FPWkrKyxCRUZPUkVfQVRUUklCVVRFX1ZBTFVFPWkrKyxJTl9BVFRSSUJVVEVfVkFMVUVfRFE9aSsrLElOX0FUVFJJQlVURV9WQUxVRV9TUT1pKyssSU5fQVRUUklCVVRFX1ZBTFVFX05RPWkrKyxCRUZPUkVfREVDTEFSQVRJT049aSsrLElOX0RFQ0xBUkFUSU9OPWkrKyxJTl9QUk9DRVNTSU5HX0lOU1RSVUNUSU9OPWkrKyxCRUZPUkVfQ09NTUVOVD1pKyssSU5fQ09NTUVOVD1pKyssQUZURVJfQ09NTUVOVF8xPWkrKyxBRlRFUl9DT01NRU5UXzI9aSsrLEJFRk9SRV9DREFUQV8xPWkrKyxCRUZPUkVfQ0RBVEFfMj1pKyssQkVGT1JFX0NEQVRBXzM9aSsrLEJFRk9SRV9DREFUQV80PWkrKyxCRUZPUkVfQ0RBVEFfNT1pKyssQkVGT1JFX0NEQVRBXzY9aSsrLElOX0NEQVRBPWkrKyxBRlRFUl9DREFUQV8xPWkrKyxBRlRFUl9DREFUQV8yPWkrKyxCRUZPUkVfU1BFQ0lBTD1pKyssQkVGT1JFX1NQRUNJQUxfRU5EPWkrKyxCRUZPUkVfU0NSSVBUXzE9aSsrLEJFRk9SRV9TQ1JJUFRfMj1pKyssQkVGT1JFX1NDUklQVF8zPWkrKyxCRUZPUkVfU0NSSVBUXzQ9aSsrLEJFRk9SRV9TQ1JJUFRfNT1pKyssQUZURVJfU0NSSVBUXzE9aSsrLEFGVEVSX1NDUklQVF8yPWkrKyxBRlRFUl9TQ1JJUFRfMz1pKyssQUZURVJfU0NSSVBUXzQ9aSsrLEFGVEVSX1NDUklQVF81PWkrKyxCRUZPUkVfU1RZTEVfMT1pKyssQkVGT1JFX1NUWUxFXzI9aSsrLEJFRk9SRV9TVFlMRV8zPWkrKyxCRUZPUkVfU1RZTEVfND1pKyssQUZURVJfU1RZTEVfMT1pKyssQUZURVJfU1RZTEVfMj1pKyssQUZURVJfU1RZTEVfMz1pKyssQUZURVJfU1RZTEVfND1pKyssQkVGT1JFX0VOVElUWT1pKyssQkVGT1JFX05VTUVSSUNfRU5USVRZPWkrKyxJTl9OQU1FRF9FTlRJVFk9aSsrLElOX05VTUVSSUNfRU5USVRZPWkrKyxJTl9IRVhfRU5USVRZPWkrKyxqPTAsU1BFQ0lBTF9OT05FPWorKyxTUEVDSUFMX1NDUklQVD1qKyssU1BFQ0lBTF9TVFlMRT1qKys7ZnVuY3Rpb24gd2hpdGVzcGFjZShjKXtyZXR1cm4gYz09PVwiIFwifHxjPT09XCJcXG5cInx8Yz09PVwiXFx0XCJ8fGM9PT1cIlxcZlwifHxjPT09XCJcXHJcIn1mdW5jdGlvbiBjaGFyYWN0ZXJTdGF0ZShjaGFyLFNVQ0NFU1Mpe3JldHVybiBmdW5jdGlvbihjKXtpZihjPT09Y2hhcil0aGlzLl9zdGF0ZT1TVUNDRVNTfX1mdW5jdGlvbiBpZkVsc2VTdGF0ZSh1cHBlcixTVUNDRVNTLEZBSUxVUkUpe3ZhciBsb3dlcj11cHBlci50b0xvd2VyQ2FzZSgpO2lmKHVwcGVyPT09bG93ZXIpe3JldHVybiBmdW5jdGlvbihjKXtpZihjPT09bG93ZXIpe3RoaXMuX3N0YXRlPVNVQ0NFU1N9ZWxzZXt0aGlzLl9zdGF0ZT1GQUlMVVJFO3RoaXMuX2luZGV4LS19fX1lbHNle3JldHVybiBmdW5jdGlvbihjKXtpZihjPT09bG93ZXJ8fGM9PT11cHBlcil7dGhpcy5fc3RhdGU9U1VDQ0VTU31lbHNle3RoaXMuX3N0YXRlPUZBSUxVUkU7dGhpcy5faW5kZXgtLX19fX1mdW5jdGlvbiBjb25zdW1lU3BlY2lhbE5hbWVDaGFyKHVwcGVyLE5FWFRfU1RBVEUpe3ZhciBsb3dlcj11cHBlci50b0xvd2VyQ2FzZSgpO3JldHVybiBmdW5jdGlvbihjKXtpZihjPT09bG93ZXJ8fGM9PT11cHBlcil7dGhpcy5fc3RhdGU9TkVYVF9TVEFURX1lbHNle3RoaXMuX3N0YXRlPUlOX1RBR19OQU1FO3RoaXMuX2luZGV4LS19fX1mdW5jdGlvbiBUb2tlbml6ZXIob3B0aW9ucyxjYnMpe3RoaXMuX3N0YXRlPVRFWFQ7dGhpcy5fYnVmZmVyPVwiXCI7dGhpcy5fc2VjdGlvblN0YXJ0PTA7dGhpcy5faW5kZXg9MDt0aGlzLl9idWZmZXJPZmZzZXQ9MDt0aGlzLl9iYXNlU3RhdGU9VEVYVDt0aGlzLl9zcGVjaWFsPVNQRUNJQUxfTk9ORTt0aGlzLl9jYnM9Y2JzO3RoaXMuX3J1bm5pbmc9dHJ1ZTt0aGlzLl9lbmRlZD1mYWxzZTt0aGlzLl94bWxNb2RlPSEhKG9wdGlvbnMmJm9wdGlvbnMueG1sTW9kZSk7dGhpcy5fZGVjb2RlRW50aXRpZXM9ISEob3B0aW9ucyYmb3B0aW9ucy5kZWNvZGVFbnRpdGllcyl9VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVUZXh0PWZ1bmN0aW9uKGMpe2lmKGM9PT1cIjxcIil7aWYodGhpcy5faW5kZXg+dGhpcy5fc2VjdGlvblN0YXJ0KXt0aGlzLl9jYnMub250ZXh0KHRoaXMuX2dldFNlY3Rpb24oKSl9dGhpcy5fc3RhdGU9QkVGT1JFX1RBR19OQU1FO3RoaXMuX3NlY3Rpb25TdGFydD10aGlzLl9pbmRleH1lbHNlIGlmKHRoaXMuX2RlY29kZUVudGl0aWVzJiZ0aGlzLl9zcGVjaWFsPT09U1BFQ0lBTF9OT05FJiZjPT09XCImXCIpe2lmKHRoaXMuX2luZGV4PnRoaXMuX3NlY3Rpb25TdGFydCl7dGhpcy5fY2JzLm9udGV4dCh0aGlzLl9nZXRTZWN0aW9uKCkpfXRoaXMuX2Jhc2VTdGF0ZT1URVhUO3RoaXMuX3N0YXRlPUJFRk9SRV9FTlRJVFk7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4fX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVUYWdOYW1lPWZ1bmN0aW9uKGMpe2lmKGM9PT1cIi9cIil7dGhpcy5fc3RhdGU9QkVGT1JFX0NMT1NJTkdfVEFHX05BTUV9ZWxzZSBpZihjPT09XCI8XCIpe3RoaXMuX2Nicy5vbnRleHQodGhpcy5fZ2V0U2VjdGlvbigpKTt0aGlzLl9zZWN0aW9uU3RhcnQ9dGhpcy5faW5kZXh9ZWxzZSBpZihjPT09XCI+XCJ8fHRoaXMuX3NwZWNpYWwhPT1TUEVDSUFMX05PTkV8fHdoaXRlc3BhY2UoYykpe3RoaXMuX3N0YXRlPVRFWFR9ZWxzZSBpZihjPT09XCIhXCIpe3RoaXMuX3N0YXRlPUJFRk9SRV9ERUNMQVJBVElPTjt0aGlzLl9zZWN0aW9uU3RhcnQ9dGhpcy5faW5kZXgrMX1lbHNlIGlmKGM9PT1cIj9cIil7dGhpcy5fc3RhdGU9SU5fUFJPQ0VTU0lOR19JTlNUUlVDVElPTjt0aGlzLl9zZWN0aW9uU3RhcnQ9dGhpcy5faW5kZXgrMX1lbHNle3RoaXMuX3N0YXRlPSF0aGlzLl94bWxNb2RlJiYoYz09PVwic1wifHxjPT09XCJTXCIpP0JFRk9SRV9TUEVDSUFMOklOX1RBR19OQU1FO3RoaXMuX3NlY3Rpb25TdGFydD10aGlzLl9pbmRleH19O1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlSW5UYWdOYW1lPWZ1bmN0aW9uKGMpe2lmKGM9PT1cIi9cInx8Yz09PVwiPlwifHx3aGl0ZXNwYWNlKGMpKXt0aGlzLl9lbWl0VG9rZW4oXCJvbm9wZW50YWduYW1lXCIpO3RoaXMuX3N0YXRlPUJFRk9SRV9BVFRSSUJVVEVfTkFNRTt0aGlzLl9pbmRleC0tfX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVDbG9zZWluZ1RhZ05hbWU9ZnVuY3Rpb24oYyl7aWYod2hpdGVzcGFjZShjKSk7ZWxzZSBpZihjPT09XCI+XCIpe3RoaXMuX3N0YXRlPVRFWFR9ZWxzZSBpZih0aGlzLl9zcGVjaWFsIT09U1BFQ0lBTF9OT05FKXtpZihjPT09XCJzXCJ8fGM9PT1cIlNcIil7dGhpcy5fc3RhdGU9QkVGT1JFX1NQRUNJQUxfRU5EfWVsc2V7dGhpcy5fc3RhdGU9VEVYVDt0aGlzLl9pbmRleC0tfX1lbHNle3RoaXMuX3N0YXRlPUlOX0NMT1NJTkdfVEFHX05BTUU7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4fX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVJbkNsb3NlaW5nVGFnTmFtZT1mdW5jdGlvbihjKXtpZihjPT09XCI+XCJ8fHdoaXRlc3BhY2UoYykpe3RoaXMuX2VtaXRUb2tlbihcIm9uY2xvc2V0YWdcIik7dGhpcy5fc3RhdGU9QUZURVJfQ0xPU0lOR19UQUdfTkFNRTt0aGlzLl9pbmRleC0tfX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVBZnRlckNsb3NlaW5nVGFnTmFtZT1mdW5jdGlvbihjKXtpZihjPT09XCI+XCIpe3RoaXMuX3N0YXRlPVRFWFQ7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4KzF9fTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUJlZm9yZUF0dHJpYnV0ZU5hbWU9ZnVuY3Rpb24oYyl7aWYoYz09PVwiPlwiKXt0aGlzLl9jYnMub25vcGVudGFnZW5kKCk7dGhpcy5fc3RhdGU9VEVYVDt0aGlzLl9zZWN0aW9uU3RhcnQ9dGhpcy5faW5kZXgrMX1lbHNlIGlmKGM9PT1cIi9cIil7dGhpcy5fc3RhdGU9SU5fU0VMRl9DTE9TSU5HX1RBR31lbHNlIGlmKCF3aGl0ZXNwYWNlKGMpKXt0aGlzLl9zdGF0ZT1JTl9BVFRSSUJVVEVfTkFNRTt0aGlzLl9zZWN0aW9uU3RhcnQ9dGhpcy5faW5kZXh9fTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUluU2VsZkNsb3NpbmdUYWc9ZnVuY3Rpb24oYyl7aWYoYz09PVwiPlwiKXt0aGlzLl9jYnMub25zZWxmY2xvc2luZ3RhZygpO3RoaXMuX3N0YXRlPVRFWFQ7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4KzF9ZWxzZSBpZighd2hpdGVzcGFjZShjKSl7dGhpcy5fc3RhdGU9QkVGT1JFX0FUVFJJQlVURV9OQU1FO3RoaXMuX2luZGV4LS19fTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUluQXR0cmlidXRlTmFtZT1mdW5jdGlvbihjKXtpZihjPT09XCI9XCJ8fGM9PT1cIi9cInx8Yz09PVwiPlwifHx3aGl0ZXNwYWNlKGMpKXt0aGlzLl9jYnMub25hdHRyaWJuYW1lKHRoaXMuX2dldFNlY3Rpb24oKSk7dGhpcy5fc2VjdGlvblN0YXJ0PS0xO3RoaXMuX3N0YXRlPUFGVEVSX0FUVFJJQlVURV9OQU1FO3RoaXMuX2luZGV4LS19fTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUFmdGVyQXR0cmlidXRlTmFtZT1mdW5jdGlvbihjKXtpZihjPT09XCI9XCIpe3RoaXMuX3N0YXRlPUJFRk9SRV9BVFRSSUJVVEVfVkFMVUV9ZWxzZSBpZihjPT09XCIvXCJ8fGM9PT1cIj5cIil7dGhpcy5fY2JzLm9uYXR0cmliZW5kKCk7dGhpcy5fc3RhdGU9QkVGT1JFX0FUVFJJQlVURV9OQU1FO3RoaXMuX2luZGV4LS19ZWxzZSBpZighd2hpdGVzcGFjZShjKSl7dGhpcy5fY2JzLm9uYXR0cmliZW5kKCk7dGhpcy5fc3RhdGU9SU5fQVRUUklCVVRFX05BTUU7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4fX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVBdHRyaWJ1dGVWYWx1ZT1mdW5jdGlvbihjKXtpZihjPT09J1wiJyl7dGhpcy5fc3RhdGU9SU5fQVRUUklCVVRFX1ZBTFVFX0RRO3RoaXMuX3NlY3Rpb25TdGFydD10aGlzLl9pbmRleCsxfWVsc2UgaWYoYz09PVwiJ1wiKXt0aGlzLl9zdGF0ZT1JTl9BVFRSSUJVVEVfVkFMVUVfU1E7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4KzF9ZWxzZSBpZighd2hpdGVzcGFjZShjKSl7dGhpcy5fc3RhdGU9SU5fQVRUUklCVVRFX1ZBTFVFX05RO3RoaXMuX3NlY3Rpb25TdGFydD10aGlzLl9pbmRleDt0aGlzLl9pbmRleC0tfX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVJbkF0dHJpYnV0ZVZhbHVlRG91YmxlUXVvdGVzPWZ1bmN0aW9uKGMpe2lmKGM9PT0nXCInKXt0aGlzLl9lbWl0VG9rZW4oXCJvbmF0dHJpYmRhdGFcIik7dGhpcy5fY2JzLm9uYXR0cmliZW5kKCk7dGhpcy5fc3RhdGU9QkVGT1JFX0FUVFJJQlVURV9OQU1FfWVsc2UgaWYodGhpcy5fZGVjb2RlRW50aXRpZXMmJmM9PT1cIiZcIil7dGhpcy5fZW1pdFRva2VuKFwib25hdHRyaWJkYXRhXCIpO3RoaXMuX2Jhc2VTdGF0ZT10aGlzLl9zdGF0ZTt0aGlzLl9zdGF0ZT1CRUZPUkVfRU5USVRZO3RoaXMuX3NlY3Rpb25TdGFydD10aGlzLl9pbmRleH19O1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlSW5BdHRyaWJ1dGVWYWx1ZVNpbmdsZVF1b3Rlcz1mdW5jdGlvbihjKXtpZihjPT09XCInXCIpe3RoaXMuX2VtaXRUb2tlbihcIm9uYXR0cmliZGF0YVwiKTt0aGlzLl9jYnMub25hdHRyaWJlbmQoKTt0aGlzLl9zdGF0ZT1CRUZPUkVfQVRUUklCVVRFX05BTUV9ZWxzZSBpZih0aGlzLl9kZWNvZGVFbnRpdGllcyYmYz09PVwiJlwiKXt0aGlzLl9lbWl0VG9rZW4oXCJvbmF0dHJpYmRhdGFcIik7dGhpcy5fYmFzZVN0YXRlPXRoaXMuX3N0YXRlO3RoaXMuX3N0YXRlPUJFRk9SRV9FTlRJVFk7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4fX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVJbkF0dHJpYnV0ZVZhbHVlTm9RdW90ZXM9ZnVuY3Rpb24oYyl7aWYod2hpdGVzcGFjZShjKXx8Yz09PVwiPlwiKXt0aGlzLl9lbWl0VG9rZW4oXCJvbmF0dHJpYmRhdGFcIik7dGhpcy5fY2JzLm9uYXR0cmliZW5kKCk7dGhpcy5fc3RhdGU9QkVGT1JFX0FUVFJJQlVURV9OQU1FO3RoaXMuX2luZGV4LS19ZWxzZSBpZih0aGlzLl9kZWNvZGVFbnRpdGllcyYmYz09PVwiJlwiKXt0aGlzLl9lbWl0VG9rZW4oXCJvbmF0dHJpYmRhdGFcIik7dGhpcy5fYmFzZVN0YXRlPXRoaXMuX3N0YXRlO3RoaXMuX3N0YXRlPUJFRk9SRV9FTlRJVFk7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4fX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVEZWNsYXJhdGlvbj1mdW5jdGlvbihjKXt0aGlzLl9zdGF0ZT1jPT09XCJbXCI/QkVGT1JFX0NEQVRBXzE6Yz09PVwiLVwiP0JFRk9SRV9DT01NRU5UOklOX0RFQ0xBUkFUSU9OfTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUluRGVjbGFyYXRpb249ZnVuY3Rpb24oYyl7aWYoYz09PVwiPlwiKXt0aGlzLl9jYnMub25kZWNsYXJhdGlvbih0aGlzLl9nZXRTZWN0aW9uKCkpO3RoaXMuX3N0YXRlPVRFWFQ7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4KzF9fTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUluUHJvY2Vzc2luZ0luc3RydWN0aW9uPWZ1bmN0aW9uKGMpe2lmKGM9PT1cIj5cIil7dGhpcy5fY2JzLm9ucHJvY2Vzc2luZ2luc3RydWN0aW9uKHRoaXMuX2dldFNlY3Rpb24oKSk7dGhpcy5fc3RhdGU9VEVYVDt0aGlzLl9zZWN0aW9uU3RhcnQ9dGhpcy5faW5kZXgrMX19O1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQmVmb3JlQ29tbWVudD1mdW5jdGlvbihjKXtpZihjPT09XCItXCIpe3RoaXMuX3N0YXRlPUlOX0NPTU1FTlQ7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4KzF9ZWxzZXt0aGlzLl9zdGF0ZT1JTl9ERUNMQVJBVElPTn19O1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlSW5Db21tZW50PWZ1bmN0aW9uKGMpe2lmKGM9PT1cIi1cIil0aGlzLl9zdGF0ZT1BRlRFUl9DT01NRU5UXzF9O1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQWZ0ZXJDb21tZW50MT1mdW5jdGlvbihjKXtpZihjPT09XCItXCIpe3RoaXMuX3N0YXRlPUFGVEVSX0NPTU1FTlRfMn1lbHNle3RoaXMuX3N0YXRlPUlOX0NPTU1FTlR9fTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUFmdGVyQ29tbWVudDI9ZnVuY3Rpb24oYyl7aWYoYz09PVwiPlwiKXt0aGlzLl9jYnMub25jb21tZW50KHRoaXMuX2J1ZmZlci5zdWJzdHJpbmcodGhpcy5fc2VjdGlvblN0YXJ0LHRoaXMuX2luZGV4LTIpKTt0aGlzLl9zdGF0ZT1URVhUO3RoaXMuX3NlY3Rpb25TdGFydD10aGlzLl9pbmRleCsxfWVsc2UgaWYoYyE9PVwiLVwiKXt0aGlzLl9zdGF0ZT1JTl9DT01NRU5UfX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVDZGF0YTE9aWZFbHNlU3RhdGUoXCJDXCIsQkVGT1JFX0NEQVRBXzIsSU5fREVDTEFSQVRJT04pO1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQmVmb3JlQ2RhdGEyPWlmRWxzZVN0YXRlKFwiRFwiLEJFRk9SRV9DREFUQV8zLElOX0RFQ0xBUkFUSU9OKTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUJlZm9yZUNkYXRhMz1pZkVsc2VTdGF0ZShcIkFcIixCRUZPUkVfQ0RBVEFfNCxJTl9ERUNMQVJBVElPTik7VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVDZGF0YTQ9aWZFbHNlU3RhdGUoXCJUXCIsQkVGT1JFX0NEQVRBXzUsSU5fREVDTEFSQVRJT04pO1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQmVmb3JlQ2RhdGE1PWlmRWxzZVN0YXRlKFwiQVwiLEJFRk9SRV9DREFUQV82LElOX0RFQ0xBUkFUSU9OKTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUJlZm9yZUNkYXRhNj1mdW5jdGlvbihjKXtpZihjPT09XCJbXCIpe3RoaXMuX3N0YXRlPUlOX0NEQVRBO3RoaXMuX3NlY3Rpb25TdGFydD10aGlzLl9pbmRleCsxfWVsc2V7dGhpcy5fc3RhdGU9SU5fREVDTEFSQVRJT047dGhpcy5faW5kZXgtLX19O1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlSW5DZGF0YT1mdW5jdGlvbihjKXtpZihjPT09XCJdXCIpdGhpcy5fc3RhdGU9QUZURVJfQ0RBVEFfMX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVBZnRlckNkYXRhMT1jaGFyYWN0ZXJTdGF0ZShcIl1cIixBRlRFUl9DREFUQV8yKTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUFmdGVyQ2RhdGEyPWZ1bmN0aW9uKGMpe2lmKGM9PT1cIj5cIil7dGhpcy5fY2JzLm9uY2RhdGEodGhpcy5fYnVmZmVyLnN1YnN0cmluZyh0aGlzLl9zZWN0aW9uU3RhcnQsdGhpcy5faW5kZXgtMikpO3RoaXMuX3N0YXRlPVRFWFQ7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4KzF9ZWxzZSBpZihjIT09XCJdXCIpe3RoaXMuX3N0YXRlPUlOX0NEQVRBfX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVTcGVjaWFsPWZ1bmN0aW9uKGMpe2lmKGM9PT1cImNcInx8Yz09PVwiQ1wiKXt0aGlzLl9zdGF0ZT1CRUZPUkVfU0NSSVBUXzF9ZWxzZSBpZihjPT09XCJ0XCJ8fGM9PT1cIlRcIil7dGhpcy5fc3RhdGU9QkVGT1JFX1NUWUxFXzF9ZWxzZXt0aGlzLl9zdGF0ZT1JTl9UQUdfTkFNRTt0aGlzLl9pbmRleC0tfX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVTcGVjaWFsRW5kPWZ1bmN0aW9uKGMpe2lmKHRoaXMuX3NwZWNpYWw9PT1TUEVDSUFMX1NDUklQVCYmKGM9PT1cImNcInx8Yz09PVwiQ1wiKSl7dGhpcy5fc3RhdGU9QUZURVJfU0NSSVBUXzF9ZWxzZSBpZih0aGlzLl9zcGVjaWFsPT09U1BFQ0lBTF9TVFlMRSYmKGM9PT1cInRcInx8Yz09PVwiVFwiKSl7dGhpcy5fc3RhdGU9QUZURVJfU1RZTEVfMX1lbHNlIHRoaXMuX3N0YXRlPVRFWFR9O1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQmVmb3JlU2NyaXB0MT1jb25zdW1lU3BlY2lhbE5hbWVDaGFyKFwiUlwiLEJFRk9SRV9TQ1JJUFRfMik7VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVTY3JpcHQyPWNvbnN1bWVTcGVjaWFsTmFtZUNoYXIoXCJJXCIsQkVGT1JFX1NDUklQVF8zKTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUJlZm9yZVNjcmlwdDM9Y29uc3VtZVNwZWNpYWxOYW1lQ2hhcihcIlBcIixCRUZPUkVfU0NSSVBUXzQpO1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQmVmb3JlU2NyaXB0ND1jb25zdW1lU3BlY2lhbE5hbWVDaGFyKFwiVFwiLEJFRk9SRV9TQ1JJUFRfNSk7VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVTY3JpcHQ1PWZ1bmN0aW9uKGMpe2lmKGM9PT1cIi9cInx8Yz09PVwiPlwifHx3aGl0ZXNwYWNlKGMpKXt0aGlzLl9zcGVjaWFsPVNQRUNJQUxfU0NSSVBUfXRoaXMuX3N0YXRlPUlOX1RBR19OQU1FO3RoaXMuX2luZGV4LS19O1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQWZ0ZXJTY3JpcHQxPWlmRWxzZVN0YXRlKFwiUlwiLEFGVEVSX1NDUklQVF8yLFRFWFQpO1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQWZ0ZXJTY3JpcHQyPWlmRWxzZVN0YXRlKFwiSVwiLEFGVEVSX1NDUklQVF8zLFRFWFQpO1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQWZ0ZXJTY3JpcHQzPWlmRWxzZVN0YXRlKFwiUFwiLEFGVEVSX1NDUklQVF80LFRFWFQpO1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQWZ0ZXJTY3JpcHQ0PWlmRWxzZVN0YXRlKFwiVFwiLEFGVEVSX1NDUklQVF81LFRFWFQpO1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQWZ0ZXJTY3JpcHQ1PWZ1bmN0aW9uKGMpe2lmKGM9PT1cIj5cInx8d2hpdGVzcGFjZShjKSl7dGhpcy5fc3BlY2lhbD1TUEVDSUFMX05PTkU7dGhpcy5fc3RhdGU9SU5fQ0xPU0lOR19UQUdfTkFNRTt0aGlzLl9zZWN0aW9uU3RhcnQ9dGhpcy5faW5kZXgtNjt0aGlzLl9pbmRleC0tfWVsc2UgdGhpcy5fc3RhdGU9VEVYVH07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVTdHlsZTE9Y29uc3VtZVNwZWNpYWxOYW1lQ2hhcihcIllcIixCRUZPUkVfU1RZTEVfMik7VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVTdHlsZTI9Y29uc3VtZVNwZWNpYWxOYW1lQ2hhcihcIkxcIixCRUZPUkVfU1RZTEVfMyk7VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVTdHlsZTM9Y29uc3VtZVNwZWNpYWxOYW1lQ2hhcihcIkVcIixCRUZPUkVfU1RZTEVfNCk7VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVTdHlsZTQ9ZnVuY3Rpb24oYyl7aWYoYz09PVwiL1wifHxjPT09XCI+XCJ8fHdoaXRlc3BhY2UoYykpe3RoaXMuX3NwZWNpYWw9U1BFQ0lBTF9TVFlMRX10aGlzLl9zdGF0ZT1JTl9UQUdfTkFNRTt0aGlzLl9pbmRleC0tfTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUFmdGVyU3R5bGUxPWlmRWxzZVN0YXRlKFwiWVwiLEFGVEVSX1NUWUxFXzIsVEVYVCk7VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVBZnRlclN0eWxlMj1pZkVsc2VTdGF0ZShcIkxcIixBRlRFUl9TVFlMRV8zLFRFWFQpO1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlQWZ0ZXJTdHlsZTM9aWZFbHNlU3RhdGUoXCJFXCIsQUZURVJfU1RZTEVfNCxURVhUKTtUb2tlbml6ZXIucHJvdG90eXBlLl9zdGF0ZUFmdGVyU3R5bGU0PWZ1bmN0aW9uKGMpe2lmKGM9PT1cIj5cInx8d2hpdGVzcGFjZShjKSl7dGhpcy5fc3BlY2lhbD1TUEVDSUFMX05PTkU7dGhpcy5fc3RhdGU9SU5fQ0xPU0lOR19UQUdfTkFNRTt0aGlzLl9zZWN0aW9uU3RhcnQ9dGhpcy5faW5kZXgtNTt0aGlzLl9pbmRleC0tfWVsc2UgdGhpcy5fc3RhdGU9VEVYVH07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVFbnRpdHk9aWZFbHNlU3RhdGUoXCIjXCIsQkVGT1JFX05VTUVSSUNfRU5USVRZLElOX05BTUVEX0VOVElUWSk7VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVCZWZvcmVOdW1lcmljRW50aXR5PWlmRWxzZVN0YXRlKFwiWFwiLElOX0hFWF9FTlRJVFksSU5fTlVNRVJJQ19FTlRJVFkpO1Rva2VuaXplci5wcm90b3R5cGUuX3BhcnNlTmFtZWRFbnRpdHlTdHJpY3Q9ZnVuY3Rpb24oKXtpZih0aGlzLl9zZWN0aW9uU3RhcnQrMTx0aGlzLl9pbmRleCl7dmFyIGVudGl0eT10aGlzLl9idWZmZXIuc3Vic3RyaW5nKHRoaXMuX3NlY3Rpb25TdGFydCsxLHRoaXMuX2luZGV4KSxtYXA9dGhpcy5feG1sTW9kZT94bWxNYXA6ZW50aXR5TWFwO2lmKG1hcC5oYXNPd25Qcm9wZXJ0eShlbnRpdHkpKXt0aGlzLl9lbWl0UGFydGlhbChtYXBbZW50aXR5XSk7dGhpcy5fc2VjdGlvblN0YXJ0PXRoaXMuX2luZGV4KzF9fX07VG9rZW5pemVyLnByb3RvdHlwZS5fcGFyc2VMZWdhY3lFbnRpdHk9ZnVuY3Rpb24oKXt2YXIgc3RhcnQ9dGhpcy5fc2VjdGlvblN0YXJ0KzEsbGltaXQ9dGhpcy5faW5kZXgtc3RhcnQ7aWYobGltaXQ+NilsaW1pdD02O3doaWxlKGxpbWl0Pj0yKXt2YXIgZW50aXR5PXRoaXMuX2J1ZmZlci5zdWJzdHIoc3RhcnQsbGltaXQpO2lmKGxlZ2FjeU1hcC5oYXNPd25Qcm9wZXJ0eShlbnRpdHkpKXt0aGlzLl9lbWl0UGFydGlhbChsZWdhY3lNYXBbZW50aXR5XSk7dGhpcy5fc2VjdGlvblN0YXJ0Kz1saW1pdCsxO3JldHVybn1lbHNle2xpbWl0LS19fX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVJbk5hbWVkRW50aXR5PWZ1bmN0aW9uKGMpe2lmKGM9PT1cIjtcIil7dGhpcy5fcGFyc2VOYW1lZEVudGl0eVN0cmljdCgpO2lmKHRoaXMuX3NlY3Rpb25TdGFydCsxPHRoaXMuX2luZGV4JiYhdGhpcy5feG1sTW9kZSl7dGhpcy5fcGFyc2VMZWdhY3lFbnRpdHkoKX10aGlzLl9zdGF0ZT10aGlzLl9iYXNlU3RhdGV9ZWxzZSBpZigoYzxcImFcInx8Yz5cInpcIikmJihjPFwiQVwifHxjPlwiWlwiKSYmKGM8XCIwXCJ8fGM+XCI5XCIpKXtpZih0aGlzLl94bWxNb2RlKTtlbHNlIGlmKHRoaXMuX3NlY3Rpb25TdGFydCsxPT09dGhpcy5faW5kZXgpO2Vsc2UgaWYodGhpcy5fYmFzZVN0YXRlIT09VEVYVCl7aWYoYyE9PVwiPVwiKXt0aGlzLl9wYXJzZU5hbWVkRW50aXR5U3RyaWN0KCl9fWVsc2V7dGhpcy5fcGFyc2VMZWdhY3lFbnRpdHkoKX10aGlzLl9zdGF0ZT10aGlzLl9iYXNlU3RhdGU7dGhpcy5faW5kZXgtLX19O1Rva2VuaXplci5wcm90b3R5cGUuX2RlY29kZU51bWVyaWNFbnRpdHk9ZnVuY3Rpb24ob2Zmc2V0LGJhc2Upe3ZhciBzZWN0aW9uU3RhcnQ9dGhpcy5fc2VjdGlvblN0YXJ0K29mZnNldDtpZihzZWN0aW9uU3RhcnQhPT10aGlzLl9pbmRleCl7dmFyIGVudGl0eT10aGlzLl9idWZmZXIuc3Vic3RyaW5nKHNlY3Rpb25TdGFydCx0aGlzLl9pbmRleCk7dmFyIHBhcnNlZD1wYXJzZUludChlbnRpdHksYmFzZSk7dGhpcy5fZW1pdFBhcnRpYWwoZGVjb2RlQ29kZVBvaW50KHBhcnNlZCkpO3RoaXMuX3NlY3Rpb25TdGFydD10aGlzLl9pbmRleH1lbHNle3RoaXMuX3NlY3Rpb25TdGFydC0tfXRoaXMuX3N0YXRlPXRoaXMuX2Jhc2VTdGF0ZX07VG9rZW5pemVyLnByb3RvdHlwZS5fc3RhdGVJbk51bWVyaWNFbnRpdHk9ZnVuY3Rpb24oYyl7aWYoYz09PVwiO1wiKXt0aGlzLl9kZWNvZGVOdW1lcmljRW50aXR5KDIsMTApO3RoaXMuX3NlY3Rpb25TdGFydCsrfWVsc2UgaWYoYzxcIjBcInx8Yz5cIjlcIil7aWYoIXRoaXMuX3htbE1vZGUpe3RoaXMuX2RlY29kZU51bWVyaWNFbnRpdHkoMiwxMCl9ZWxzZXt0aGlzLl9zdGF0ZT10aGlzLl9iYXNlU3RhdGV9dGhpcy5faW5kZXgtLX19O1Rva2VuaXplci5wcm90b3R5cGUuX3N0YXRlSW5IZXhFbnRpdHk9ZnVuY3Rpb24oYyl7aWYoYz09PVwiO1wiKXt0aGlzLl9kZWNvZGVOdW1lcmljRW50aXR5KDMsMTYpO3RoaXMuX3NlY3Rpb25TdGFydCsrfWVsc2UgaWYoKGM8XCJhXCJ8fGM+XCJmXCIpJiYoYzxcIkFcInx8Yz5cIkZcIikmJihjPFwiMFwifHxjPlwiOVwiKSl7aWYoIXRoaXMuX3htbE1vZGUpe3RoaXMuX2RlY29kZU51bWVyaWNFbnRpdHkoMywxNil9ZWxzZXt0aGlzLl9zdGF0ZT10aGlzLl9iYXNlU3RhdGV9dGhpcy5faW5kZXgtLX19O1Rva2VuaXplci5wcm90b3R5cGUuX2NsZWFudXA9ZnVuY3Rpb24oKXtpZih0aGlzLl9zZWN0aW9uU3RhcnQ8MCl7dGhpcy5fYnVmZmVyPVwiXCI7dGhpcy5faW5kZXg9MDt0aGlzLl9idWZmZXJPZmZzZXQrPXRoaXMuX2luZGV4fWVsc2UgaWYodGhpcy5fcnVubmluZyl7aWYodGhpcy5fc3RhdGU9PT1URVhUKXtpZih0aGlzLl9zZWN0aW9uU3RhcnQhPT10aGlzLl9pbmRleCl7dGhpcy5fY2JzLm9udGV4dCh0aGlzLl9idWZmZXIuc3Vic3RyKHRoaXMuX3NlY3Rpb25TdGFydCkpfXRoaXMuX2J1ZmZlcj1cIlwiO3RoaXMuX2J1ZmZlck9mZnNldCs9dGhpcy5faW5kZXg7dGhpcy5faW5kZXg9MH1lbHNlIGlmKHRoaXMuX3NlY3Rpb25TdGFydD09PXRoaXMuX2luZGV4KXt0aGlzLl9idWZmZXI9XCJcIjt0aGlzLl9idWZmZXJPZmZzZXQrPXRoaXMuX2luZGV4O3RoaXMuX2luZGV4PTB9ZWxzZXt0aGlzLl9idWZmZXI9dGhpcy5fYnVmZmVyLnN1YnN0cih0aGlzLl9zZWN0aW9uU3RhcnQpO3RoaXMuX2luZGV4LT10aGlzLl9zZWN0aW9uU3RhcnQ7dGhpcy5fYnVmZmVyT2Zmc2V0Kz10aGlzLl9zZWN0aW9uU3RhcnR9dGhpcy5fc2VjdGlvblN0YXJ0PTB9fTtUb2tlbml6ZXIucHJvdG90eXBlLndyaXRlPWZ1bmN0aW9uKGNodW5rKXtpZih0aGlzLl9lbmRlZCl0aGlzLl9jYnMub25lcnJvcihFcnJvcihcIi53cml0ZSgpIGFmdGVyIGRvbmUhXCIpKTt0aGlzLl9idWZmZXIrPWNodW5rO3RoaXMuX3BhcnNlKCl9O1Rva2VuaXplci5wcm90b3R5cGUuX3BhcnNlPWZ1bmN0aW9uKCl7d2hpbGUodGhpcy5faW5kZXg8dGhpcy5fYnVmZmVyLmxlbmd0aCYmdGhpcy5fcnVubmluZyl7dmFyIGM9dGhpcy5fYnVmZmVyLmNoYXJBdCh0aGlzLl9pbmRleCk7aWYodGhpcy5fc3RhdGU9PT1URVhUKXt0aGlzLl9zdGF0ZVRleHQoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUJFRk9SRV9UQUdfTkFNRSl7dGhpcy5fc3RhdGVCZWZvcmVUYWdOYW1lKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1JTl9UQUdfTkFNRSl7dGhpcy5fc3RhdGVJblRhZ05hbWUoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUJFRk9SRV9DTE9TSU5HX1RBR19OQU1FKXt0aGlzLl9zdGF0ZUJlZm9yZUNsb3NlaW5nVGFnTmFtZShjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09SU5fQ0xPU0lOR19UQUdfTkFNRSl7dGhpcy5fc3RhdGVJbkNsb3NlaW5nVGFnTmFtZShjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QUZURVJfQ0xPU0lOR19UQUdfTkFNRSl7dGhpcy5fc3RhdGVBZnRlckNsb3NlaW5nVGFnTmFtZShjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09SU5fU0VMRl9DTE9TSU5HX1RBRyl7dGhpcy5fc3RhdGVJblNlbGZDbG9zaW5nVGFnKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1CRUZPUkVfQVRUUklCVVRFX05BTUUpe3RoaXMuX3N0YXRlQmVmb3JlQXR0cmlidXRlTmFtZShjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09SU5fQVRUUklCVVRFX05BTUUpe3RoaXMuX3N0YXRlSW5BdHRyaWJ1dGVOYW1lKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1BRlRFUl9BVFRSSUJVVEVfTkFNRSl7dGhpcy5fc3RhdGVBZnRlckF0dHJpYnV0ZU5hbWUoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUJFRk9SRV9BVFRSSUJVVEVfVkFMVUUpe3RoaXMuX3N0YXRlQmVmb3JlQXR0cmlidXRlVmFsdWUoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUlOX0FUVFJJQlVURV9WQUxVRV9EUSl7dGhpcy5fc3RhdGVJbkF0dHJpYnV0ZVZhbHVlRG91YmxlUXVvdGVzKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1JTl9BVFRSSUJVVEVfVkFMVUVfU1Epe3RoaXMuX3N0YXRlSW5BdHRyaWJ1dGVWYWx1ZVNpbmdsZVF1b3RlcyhjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09SU5fQVRUUklCVVRFX1ZBTFVFX05RKXt0aGlzLl9zdGF0ZUluQXR0cmlidXRlVmFsdWVOb1F1b3RlcyhjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QkVGT1JFX0RFQ0xBUkFUSU9OKXt0aGlzLl9zdGF0ZUJlZm9yZURlY2xhcmF0aW9uKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1JTl9ERUNMQVJBVElPTil7dGhpcy5fc3RhdGVJbkRlY2xhcmF0aW9uKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1JTl9QUk9DRVNTSU5HX0lOU1RSVUNUSU9OKXt0aGlzLl9zdGF0ZUluUHJvY2Vzc2luZ0luc3RydWN0aW9uKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1CRUZPUkVfQ09NTUVOVCl7dGhpcy5fc3RhdGVCZWZvcmVDb21tZW50KGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1JTl9DT01NRU5UKXt0aGlzLl9zdGF0ZUluQ29tbWVudChjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QUZURVJfQ09NTUVOVF8xKXt0aGlzLl9zdGF0ZUFmdGVyQ29tbWVudDEoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUFGVEVSX0NPTU1FTlRfMil7dGhpcy5fc3RhdGVBZnRlckNvbW1lbnQyKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1CRUZPUkVfQ0RBVEFfMSl7dGhpcy5fc3RhdGVCZWZvcmVDZGF0YTEoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUJFRk9SRV9DREFUQV8yKXt0aGlzLl9zdGF0ZUJlZm9yZUNkYXRhMihjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QkVGT1JFX0NEQVRBXzMpe3RoaXMuX3N0YXRlQmVmb3JlQ2RhdGEzKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1CRUZPUkVfQ0RBVEFfNCl7dGhpcy5fc3RhdGVCZWZvcmVDZGF0YTQoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUJFRk9SRV9DREFUQV81KXt0aGlzLl9zdGF0ZUJlZm9yZUNkYXRhNShjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QkVGT1JFX0NEQVRBXzYpe3RoaXMuX3N0YXRlQmVmb3JlQ2RhdGE2KGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1JTl9DREFUQSl7dGhpcy5fc3RhdGVJbkNkYXRhKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1BRlRFUl9DREFUQV8xKXt0aGlzLl9zdGF0ZUFmdGVyQ2RhdGExKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1BRlRFUl9DREFUQV8yKXt0aGlzLl9zdGF0ZUFmdGVyQ2RhdGEyKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1CRUZPUkVfU1BFQ0lBTCl7dGhpcy5fc3RhdGVCZWZvcmVTcGVjaWFsKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1CRUZPUkVfU1BFQ0lBTF9FTkQpe3RoaXMuX3N0YXRlQmVmb3JlU3BlY2lhbEVuZChjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QkVGT1JFX1NDUklQVF8xKXt0aGlzLl9zdGF0ZUJlZm9yZVNjcmlwdDEoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUJFRk9SRV9TQ1JJUFRfMil7dGhpcy5fc3RhdGVCZWZvcmVTY3JpcHQyKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1CRUZPUkVfU0NSSVBUXzMpe3RoaXMuX3N0YXRlQmVmb3JlU2NyaXB0MyhjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QkVGT1JFX1NDUklQVF80KXt0aGlzLl9zdGF0ZUJlZm9yZVNjcmlwdDQoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUJFRk9SRV9TQ1JJUFRfNSl7dGhpcy5fc3RhdGVCZWZvcmVTY3JpcHQ1KGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1BRlRFUl9TQ1JJUFRfMSl7dGhpcy5fc3RhdGVBZnRlclNjcmlwdDEoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUFGVEVSX1NDUklQVF8yKXt0aGlzLl9zdGF0ZUFmdGVyU2NyaXB0MihjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QUZURVJfU0NSSVBUXzMpe3RoaXMuX3N0YXRlQWZ0ZXJTY3JpcHQzKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1BRlRFUl9TQ1JJUFRfNCl7dGhpcy5fc3RhdGVBZnRlclNjcmlwdDQoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUFGVEVSX1NDUklQVF81KXt0aGlzLl9zdGF0ZUFmdGVyU2NyaXB0NShjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QkVGT1JFX1NUWUxFXzEpe3RoaXMuX3N0YXRlQmVmb3JlU3R5bGUxKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1CRUZPUkVfU1RZTEVfMil7dGhpcy5fc3RhdGVCZWZvcmVTdHlsZTIoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUJFRk9SRV9TVFlMRV8zKXt0aGlzLl9zdGF0ZUJlZm9yZVN0eWxlMyhjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QkVGT1JFX1NUWUxFXzQpe3RoaXMuX3N0YXRlQmVmb3JlU3R5bGU0KGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1BRlRFUl9TVFlMRV8xKXt0aGlzLl9zdGF0ZUFmdGVyU3R5bGUxKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1BRlRFUl9TVFlMRV8yKXt0aGlzLl9zdGF0ZUFmdGVyU3R5bGUyKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1BRlRFUl9TVFlMRV8zKXt0aGlzLl9zdGF0ZUFmdGVyU3R5bGUzKGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1BRlRFUl9TVFlMRV80KXt0aGlzLl9zdGF0ZUFmdGVyU3R5bGU0KGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1CRUZPUkVfRU5USVRZKXt0aGlzLl9zdGF0ZUJlZm9yZUVudGl0eShjKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09QkVGT1JFX05VTUVSSUNfRU5USVRZKXt0aGlzLl9zdGF0ZUJlZm9yZU51bWVyaWNFbnRpdHkoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUlOX05BTUVEX0VOVElUWSl7dGhpcy5fc3RhdGVJbk5hbWVkRW50aXR5KGMpfWVsc2UgaWYodGhpcy5fc3RhdGU9PT1JTl9OVU1FUklDX0VOVElUWSl7dGhpcy5fc3RhdGVJbk51bWVyaWNFbnRpdHkoYyl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUlOX0hFWF9FTlRJVFkpe3RoaXMuX3N0YXRlSW5IZXhFbnRpdHkoYyl9ZWxzZXt0aGlzLl9jYnMub25lcnJvcihFcnJvcihcInVua25vd24gX3N0YXRlXCIpLHRoaXMuX3N0YXRlKX10aGlzLl9pbmRleCsrfXRoaXMuX2NsZWFudXAoKX07VG9rZW5pemVyLnByb3RvdHlwZS5wYXVzZT1mdW5jdGlvbigpe3RoaXMuX3J1bm5pbmc9ZmFsc2V9O1Rva2VuaXplci5wcm90b3R5cGUucmVzdW1lPWZ1bmN0aW9uKCl7dGhpcy5fcnVubmluZz10cnVlO2lmKHRoaXMuX2luZGV4PHRoaXMuX2J1ZmZlci5sZW5ndGgpe3RoaXMuX3BhcnNlKCl9aWYodGhpcy5fZW5kZWQpe3RoaXMuX2ZpbmlzaCgpfX07VG9rZW5pemVyLnByb3RvdHlwZS5lbmQ9ZnVuY3Rpb24oY2h1bmspe2lmKHRoaXMuX2VuZGVkKXRoaXMuX2Nicy5vbmVycm9yKEVycm9yKFwiLmVuZCgpIGFmdGVyIGRvbmUhXCIpKTtpZihjaHVuayl0aGlzLndyaXRlKGNodW5rKTt0aGlzLl9lbmRlZD10cnVlO2lmKHRoaXMuX3J1bm5pbmcpdGhpcy5fZmluaXNoKCl9O1Rva2VuaXplci5wcm90b3R5cGUuX2ZpbmlzaD1mdW5jdGlvbigpe2lmKHRoaXMuX3NlY3Rpb25TdGFydDx0aGlzLl9pbmRleCl7dGhpcy5faGFuZGxlVHJhaWxpbmdEYXRhKCl9dGhpcy5fY2JzLm9uZW5kKCl9O1Rva2VuaXplci5wcm90b3R5cGUuX2hhbmRsZVRyYWlsaW5nRGF0YT1mdW5jdGlvbigpe3ZhciBkYXRhPXRoaXMuX2J1ZmZlci5zdWJzdHIodGhpcy5fc2VjdGlvblN0YXJ0KTtpZih0aGlzLl9zdGF0ZT09PUlOX0NEQVRBfHx0aGlzLl9zdGF0ZT09PUFGVEVSX0NEQVRBXzF8fHRoaXMuX3N0YXRlPT09QUZURVJfQ0RBVEFfMil7dGhpcy5fY2JzLm9uY2RhdGEoZGF0YSl9ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUlOX0NPTU1FTlR8fHRoaXMuX3N0YXRlPT09QUZURVJfQ09NTUVOVF8xfHx0aGlzLl9zdGF0ZT09PUFGVEVSX0NPTU1FTlRfMil7dGhpcy5fY2JzLm9uY29tbWVudChkYXRhKX1lbHNlIGlmKHRoaXMuX3N0YXRlPT09SU5fTkFNRURfRU5USVRZJiYhdGhpcy5feG1sTW9kZSl7dGhpcy5fcGFyc2VMZWdhY3lFbnRpdHkoKTtpZih0aGlzLl9zZWN0aW9uU3RhcnQ8dGhpcy5faW5kZXgpe3RoaXMuX3N0YXRlPXRoaXMuX2Jhc2VTdGF0ZTt0aGlzLl9oYW5kbGVUcmFpbGluZ0RhdGEoKX19ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUlOX05VTUVSSUNfRU5USVRZJiYhdGhpcy5feG1sTW9kZSl7dGhpcy5fZGVjb2RlTnVtZXJpY0VudGl0eSgyLDEwKTtpZih0aGlzLl9zZWN0aW9uU3RhcnQ8dGhpcy5faW5kZXgpe3RoaXMuX3N0YXRlPXRoaXMuX2Jhc2VTdGF0ZTt0aGlzLl9oYW5kbGVUcmFpbGluZ0RhdGEoKX19ZWxzZSBpZih0aGlzLl9zdGF0ZT09PUlOX0hFWF9FTlRJVFkmJiF0aGlzLl94bWxNb2RlKXt0aGlzLl9kZWNvZGVOdW1lcmljRW50aXR5KDMsMTYpO2lmKHRoaXMuX3NlY3Rpb25TdGFydDx0aGlzLl9pbmRleCl7dGhpcy5fc3RhdGU9dGhpcy5fYmFzZVN0YXRlO3RoaXMuX2hhbmRsZVRyYWlsaW5nRGF0YSgpfX1lbHNlIGlmKHRoaXMuX3N0YXRlIT09SU5fVEFHX05BTUUmJnRoaXMuX3N0YXRlIT09QkVGT1JFX0FUVFJJQlVURV9OQU1FJiZ0aGlzLl9zdGF0ZSE9PUJFRk9SRV9BVFRSSUJVVEVfVkFMVUUmJnRoaXMuX3N0YXRlIT09QUZURVJfQVRUUklCVVRFX05BTUUmJnRoaXMuX3N0YXRlIT09SU5fQVRUUklCVVRFX05BTUUmJnRoaXMuX3N0YXRlIT09SU5fQVRUUklCVVRFX1ZBTFVFX1NRJiZ0aGlzLl9zdGF0ZSE9PUlOX0FUVFJJQlVURV9WQUxVRV9EUSYmdGhpcy5fc3RhdGUhPT1JTl9BVFRSSUJVVEVfVkFMVUVfTlEmJnRoaXMuX3N0YXRlIT09SU5fQ0xPU0lOR19UQUdfTkFNRSl7XG50aGlzLl9jYnMub250ZXh0KGRhdGEpfX07VG9rZW5pemVyLnByb3RvdHlwZS5yZXNldD1mdW5jdGlvbigpe1Rva2VuaXplci5jYWxsKHRoaXMse3htbE1vZGU6dGhpcy5feG1sTW9kZSxkZWNvZGVFbnRpdGllczp0aGlzLl9kZWNvZGVFbnRpdGllc30sdGhpcy5fY2JzKX07VG9rZW5pemVyLnByb3RvdHlwZS5nZXRBYnNvbHV0ZUluZGV4PWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuX2J1ZmZlck9mZnNldCt0aGlzLl9pbmRleH07VG9rZW5pemVyLnByb3RvdHlwZS5fZ2V0U2VjdGlvbj1mdW5jdGlvbigpe3JldHVybiB0aGlzLl9idWZmZXIuc3Vic3RyaW5nKHRoaXMuX3NlY3Rpb25TdGFydCx0aGlzLl9pbmRleCl9O1Rva2VuaXplci5wcm90b3R5cGUuX2VtaXRUb2tlbj1mdW5jdGlvbihuYW1lKXt0aGlzLl9jYnNbbmFtZV0odGhpcy5fZ2V0U2VjdGlvbigpKTt0aGlzLl9zZWN0aW9uU3RhcnQ9LTF9O1Rva2VuaXplci5wcm90b3R5cGUuX2VtaXRQYXJ0aWFsPWZ1bmN0aW9uKHZhbHVlKXtpZih0aGlzLl9iYXNlU3RhdGUhPT1URVhUKXt0aGlzLl9jYnMub25hdHRyaWJkYXRhKHZhbHVlKX1lbHNle3RoaXMuX2Nicy5vbnRleHQodmFsdWUpfX19LHtcImVudGl0aWVzL2xpYi9kZWNvZGVfY29kZXBvaW50LmpzXCI6MjIsXCJlbnRpdGllcy9tYXBzL2VudGl0aWVzLmpzb25cIjoyNSxcImVudGl0aWVzL21hcHMvbGVnYWN5Lmpzb25cIjoyNixcImVudGl0aWVzL21hcHMveG1sLmpzb25cIjoyN31dLDM1OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXttb2R1bGUuZXhwb3J0cz1TdHJlYW07dmFyIFBhcnNlcj1yZXF1aXJlKFwiLi9QYXJzZXIuanNcIiksV3JpdGFibGVTdHJlYW09cmVxdWlyZShcInN0cmVhbVwiKS5Xcml0YWJsZXx8cmVxdWlyZShcInJlYWRhYmxlLXN0cmVhbVwiKS5Xcml0YWJsZSxTdHJpbmdEZWNvZGVyPXJlcXVpcmUoXCJzdHJpbmdfZGVjb2RlclwiKS5TdHJpbmdEZWNvZGVyLEJ1ZmZlcj1yZXF1aXJlKFwiYnVmZmVyXCIpLkJ1ZmZlcjtmdW5jdGlvbiBTdHJlYW0oY2JzLG9wdGlvbnMpe3ZhciBwYXJzZXI9dGhpcy5fcGFyc2VyPW5ldyBQYXJzZXIoY2JzLG9wdGlvbnMpO3ZhciBkZWNvZGVyPXRoaXMuX2RlY29kZXI9bmV3IFN0cmluZ0RlY29kZXI7V3JpdGFibGVTdHJlYW0uY2FsbCh0aGlzLHtkZWNvZGVTdHJpbmdzOmZhbHNlfSk7dGhpcy5vbmNlKFwiZmluaXNoXCIsZnVuY3Rpb24oKXtwYXJzZXIuZW5kKGRlY29kZXIuZW5kKCkpfSl9cmVxdWlyZShcImluaGVyaXRzXCIpKFN0cmVhbSxXcml0YWJsZVN0cmVhbSk7V3JpdGFibGVTdHJlYW0ucHJvdG90eXBlLl93cml0ZT1mdW5jdGlvbihjaHVuayxlbmNvZGluZyxjYil7aWYoY2h1bmsgaW5zdGFuY2VvZiBCdWZmZXIpY2h1bms9dGhpcy5fZGVjb2Rlci53cml0ZShjaHVuayk7dGhpcy5fcGFyc2VyLndyaXRlKGNodW5rKTtjYigpfX0se1wiLi9QYXJzZXIuanNcIjozMSxidWZmZXI6NSxpbmhlcml0czozOCxcInJlYWRhYmxlLXN0cmVhbVwiOjMsc3RyZWFtOjU1LHN0cmluZ19kZWNvZGVyOjU2fV0sMzY6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe3ZhciBQYXJzZXI9cmVxdWlyZShcIi4vUGFyc2VyLmpzXCIpLERvbUhhbmRsZXI9cmVxdWlyZShcImRvbWhhbmRsZXJcIik7ZnVuY3Rpb24gZGVmaW5lUHJvcChuYW1lLHZhbHVlKXtkZWxldGUgbW9kdWxlLmV4cG9ydHNbbmFtZV07bW9kdWxlLmV4cG9ydHNbbmFtZV09dmFsdWU7cmV0dXJuIHZhbHVlfW1vZHVsZS5leHBvcnRzPXtQYXJzZXI6UGFyc2VyLFRva2VuaXplcjpyZXF1aXJlKFwiLi9Ub2tlbml6ZXIuanNcIiksRWxlbWVudFR5cGU6cmVxdWlyZShcImRvbWVsZW1lbnR0eXBlXCIpLERvbUhhbmRsZXI6RG9tSGFuZGxlcixnZXQgRmVlZEhhbmRsZXIoKXtyZXR1cm4gZGVmaW5lUHJvcChcIkZlZWRIYW5kbGVyXCIscmVxdWlyZShcIi4vRmVlZEhhbmRsZXIuanNcIikpfSxnZXQgU3RyZWFtKCl7cmV0dXJuIGRlZmluZVByb3AoXCJTdHJlYW1cIixyZXF1aXJlKFwiLi9TdHJlYW0uanNcIikpfSxnZXQgV3JpdGFibGVTdHJlYW0oKXtyZXR1cm4gZGVmaW5lUHJvcChcIldyaXRhYmxlU3RyZWFtXCIscmVxdWlyZShcIi4vV3JpdGFibGVTdHJlYW0uanNcIikpfSxnZXQgUHJveHlIYW5kbGVyKCl7cmV0dXJuIGRlZmluZVByb3AoXCJQcm94eUhhbmRsZXJcIixyZXF1aXJlKFwiLi9Qcm94eUhhbmRsZXIuanNcIikpfSxnZXQgRG9tVXRpbHMoKXtyZXR1cm4gZGVmaW5lUHJvcChcIkRvbVV0aWxzXCIscmVxdWlyZShcImRvbXV0aWxzXCIpKX0sZ2V0IENvbGxlY3RpbmdIYW5kbGVyKCl7cmV0dXJuIGRlZmluZVByb3AoXCJDb2xsZWN0aW5nSGFuZGxlclwiLHJlcXVpcmUoXCIuL0NvbGxlY3RpbmdIYW5kbGVyLmpzXCIpKX0sRGVmYXVsdEhhbmRsZXI6RG9tSGFuZGxlcixnZXQgUnNzSGFuZGxlcigpe3JldHVybiBkZWZpbmVQcm9wKFwiUnNzSGFuZGxlclwiLHRoaXMuRmVlZEhhbmRsZXIpfSxwYXJzZURPTTpmdW5jdGlvbihkYXRhLG9wdGlvbnMpe3ZhciBoYW5kbGVyPW5ldyBEb21IYW5kbGVyKG9wdGlvbnMpO25ldyBQYXJzZXIoaGFuZGxlcixvcHRpb25zKS5lbmQoZGF0YSk7cmV0dXJuIGhhbmRsZXIuZG9tfSxwYXJzZUZlZWQ6ZnVuY3Rpb24oZmVlZCxvcHRpb25zKXt2YXIgaGFuZGxlcj1uZXcgbW9kdWxlLmV4cG9ydHMuRmVlZEhhbmRsZXIob3B0aW9ucyk7bmV3IFBhcnNlcihoYW5kbGVyLG9wdGlvbnMpLmVuZChmZWVkKTtyZXR1cm4gaGFuZGxlci5kb219LGNyZWF0ZURvbVN0cmVhbTpmdW5jdGlvbihjYixvcHRpb25zLGVsZW1lbnRDYil7dmFyIGhhbmRsZXI9bmV3IERvbUhhbmRsZXIoY2Isb3B0aW9ucyxlbGVtZW50Q2IpO3JldHVybiBuZXcgUGFyc2VyKGhhbmRsZXIsb3B0aW9ucyl9LEVWRU5UUzp7YXR0cmlidXRlOjIsY2RhdGFzdGFydDowLGNkYXRhZW5kOjAsdGV4dDoxLHByb2Nlc3NpbmdpbnN0cnVjdGlvbjoyLGNvbW1lbnQ6MSxjb21tZW50ZW5kOjAsY2xvc2V0YWc6MSxvcGVudGFnOjIsb3BlbnRhZ25hbWU6MSxlcnJvcjoxLGVuZDowfX19LHtcIi4vQ29sbGVjdGluZ0hhbmRsZXIuanNcIjoyOSxcIi4vRmVlZEhhbmRsZXIuanNcIjozMCxcIi4vUGFyc2VyLmpzXCI6MzEsXCIuL1Byb3h5SGFuZGxlci5qc1wiOjMyLFwiLi9TdHJlYW0uanNcIjozMyxcIi4vVG9rZW5pemVyLmpzXCI6MzQsXCIuL1dyaXRhYmxlU3RyZWFtLmpzXCI6MzUsZG9tZWxlbWVudHR5cGU6OSxkb21oYW5kbGVyOjEwLGRvbXV0aWxzOjEzfV0sMzc6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe2V4cG9ydHMucmVhZD1mdW5jdGlvbihidWZmZXIsb2Zmc2V0LGlzTEUsbUxlbixuQnl0ZXMpe3ZhciBlLG07dmFyIGVMZW49bkJ5dGVzKjgtbUxlbi0xO3ZhciBlTWF4PSgxPDxlTGVuKS0xO3ZhciBlQmlhcz1lTWF4Pj4xO3ZhciBuQml0cz0tNzt2YXIgaT1pc0xFP25CeXRlcy0xOjA7dmFyIGQ9aXNMRT8tMToxO3ZhciBzPWJ1ZmZlcltvZmZzZXQraV07aSs9ZDtlPXMmKDE8PC1uQml0cyktMTtzPj49LW5CaXRzO25CaXRzKz1lTGVuO2Zvcig7bkJpdHM+MDtlPWUqMjU2K2J1ZmZlcltvZmZzZXQraV0saSs9ZCxuQml0cy09OCl7fW09ZSYoMTw8LW5CaXRzKS0xO2U+Pj0tbkJpdHM7bkJpdHMrPW1MZW47Zm9yKDtuQml0cz4wO209bSoyNTYrYnVmZmVyW29mZnNldCtpXSxpKz1kLG5CaXRzLT04KXt9aWYoZT09PTApe2U9MS1lQmlhc31lbHNlIGlmKGU9PT1lTWF4KXtyZXR1cm4gbT9OYU46KHM/LTE6MSkqSW5maW5pdHl9ZWxzZXttPW0rTWF0aC5wb3coMixtTGVuKTtlPWUtZUJpYXN9cmV0dXJuKHM/LTE6MSkqbSpNYXRoLnBvdygyLGUtbUxlbil9O2V4cG9ydHMud3JpdGU9ZnVuY3Rpb24oYnVmZmVyLHZhbHVlLG9mZnNldCxpc0xFLG1MZW4sbkJ5dGVzKXt2YXIgZSxtLGM7dmFyIGVMZW49bkJ5dGVzKjgtbUxlbi0xO3ZhciBlTWF4PSgxPDxlTGVuKS0xO3ZhciBlQmlhcz1lTWF4Pj4xO3ZhciBydD1tTGVuPT09MjM/TWF0aC5wb3coMiwtMjQpLU1hdGgucG93KDIsLTc3KTowO3ZhciBpPWlzTEU/MDpuQnl0ZXMtMTt2YXIgZD1pc0xFPzE6LTE7dmFyIHM9dmFsdWU8MHx8dmFsdWU9PT0wJiYxL3ZhbHVlPDA/MTowO3ZhbHVlPU1hdGguYWJzKHZhbHVlKTtpZihpc05hTih2YWx1ZSl8fHZhbHVlPT09SW5maW5pdHkpe209aXNOYU4odmFsdWUpPzE6MDtlPWVNYXh9ZWxzZXtlPU1hdGguZmxvb3IoTWF0aC5sb2codmFsdWUpL01hdGguTE4yKTtpZih2YWx1ZSooYz1NYXRoLnBvdygyLC1lKSk8MSl7ZS0tO2MqPTJ9aWYoZStlQmlhcz49MSl7dmFsdWUrPXJ0L2N9ZWxzZXt2YWx1ZSs9cnQqTWF0aC5wb3coMiwxLWVCaWFzKX1pZih2YWx1ZSpjPj0yKXtlKys7Yy89Mn1pZihlK2VCaWFzPj1lTWF4KXttPTA7ZT1lTWF4fWVsc2UgaWYoZStlQmlhcz49MSl7bT0odmFsdWUqYy0xKSpNYXRoLnBvdygyLG1MZW4pO2U9ZStlQmlhc31lbHNle209dmFsdWUqTWF0aC5wb3coMixlQmlhcy0xKSpNYXRoLnBvdygyLG1MZW4pO2U9MH19Zm9yKDttTGVuPj04O2J1ZmZlcltvZmZzZXQraV09bSYyNTUsaSs9ZCxtLz0yNTYsbUxlbi09OCl7fWU9ZTw8bUxlbnxtO2VMZW4rPW1MZW47Zm9yKDtlTGVuPjA7YnVmZmVyW29mZnNldCtpXT1lJjI1NSxpKz1kLGUvPTI1NixlTGVuLT04KXt9YnVmZmVyW29mZnNldCtpLWRdfD1zKjEyOH19LHt9XSwzODpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7aWYodHlwZW9mIE9iamVjdC5jcmVhdGU9PT1cImZ1bmN0aW9uXCIpe21vZHVsZS5leHBvcnRzPWZ1bmN0aW9uIGluaGVyaXRzKGN0b3Isc3VwZXJDdG9yKXtjdG9yLnN1cGVyXz1zdXBlckN0b3I7Y3Rvci5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShzdXBlckN0b3IucHJvdG90eXBlLHtjb25zdHJ1Y3Rvcjp7dmFsdWU6Y3RvcixlbnVtZXJhYmxlOmZhbHNlLHdyaXRhYmxlOnRydWUsY29uZmlndXJhYmxlOnRydWV9fSl9fWVsc2V7bW9kdWxlLmV4cG9ydHM9ZnVuY3Rpb24gaW5oZXJpdHMoY3RvcixzdXBlckN0b3Ipe2N0b3Iuc3VwZXJfPXN1cGVyQ3Rvcjt2YXIgVGVtcEN0b3I9ZnVuY3Rpb24oKXt9O1RlbXBDdG9yLnByb3RvdHlwZT1zdXBlckN0b3IucHJvdG90eXBlO2N0b3IucHJvdG90eXBlPW5ldyBUZW1wQ3RvcjtjdG9yLnByb3RvdHlwZS5jb25zdHJ1Y3Rvcj1jdG9yfX19LHt9XSwzOTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7bW9kdWxlLmV4cG9ydHM9ZnVuY3Rpb24ob2JqKXtyZXR1cm4gb2JqIT1udWxsJiYoaXNCdWZmZXIob2JqKXx8aXNTbG93QnVmZmVyKG9iail8fCEhb2JqLl9pc0J1ZmZlcil9O2Z1bmN0aW9uIGlzQnVmZmVyKG9iail7cmV0dXJuISFvYmouY29uc3RydWN0b3ImJnR5cGVvZiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXI9PT1cImZ1bmN0aW9uXCImJm9iai5jb25zdHJ1Y3Rvci5pc0J1ZmZlcihvYmopfWZ1bmN0aW9uIGlzU2xvd0J1ZmZlcihvYmope3JldHVybiB0eXBlb2Ygb2JqLnJlYWRGbG9hdExFPT09XCJmdW5jdGlvblwiJiZ0eXBlb2Ygb2JqLnNsaWNlPT09XCJmdW5jdGlvblwiJiZpc0J1ZmZlcihvYmouc2xpY2UoMCwwKSl9fSx7fV0sNDA6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe3ZhciB0b1N0cmluZz17fS50b1N0cmluZzttb2R1bGUuZXhwb3J0cz1BcnJheS5pc0FycmF5fHxmdW5jdGlvbihhcnIpe3JldHVybiB0b1N0cmluZy5jYWxsKGFycik9PVwiW29iamVjdCBBcnJheV1cIn19LHt9XSw0MTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7KGZ1bmN0aW9uKHByb2Nlc3Mpe1widXNlIHN0cmljdFwiO2lmKCFwcm9jZXNzLnZlcnNpb258fHByb2Nlc3MudmVyc2lvbi5pbmRleE9mKFwidjAuXCIpPT09MHx8cHJvY2Vzcy52ZXJzaW9uLmluZGV4T2YoXCJ2MS5cIik9PT0wJiZwcm9jZXNzLnZlcnNpb24uaW5kZXhPZihcInYxLjguXCIpIT09MCl7bW9kdWxlLmV4cG9ydHM9bmV4dFRpY2t9ZWxzZXttb2R1bGUuZXhwb3J0cz1wcm9jZXNzLm5leHRUaWNrfWZ1bmN0aW9uIG5leHRUaWNrKGZuLGFyZzEsYXJnMixhcmczKXtpZih0eXBlb2YgZm4hPT1cImZ1bmN0aW9uXCIpe3Rocm93IG5ldyBUeXBlRXJyb3IoJ1wiY2FsbGJhY2tcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKX12YXIgbGVuPWFyZ3VtZW50cy5sZW5ndGg7dmFyIGFyZ3MsaTtzd2l0Y2gobGVuKXtjYXNlIDA6Y2FzZSAxOnJldHVybiBwcm9jZXNzLm5leHRUaWNrKGZuKTtjYXNlIDI6cmV0dXJuIHByb2Nlc3MubmV4dFRpY2soZnVuY3Rpb24gYWZ0ZXJUaWNrT25lKCl7Zm4uY2FsbChudWxsLGFyZzEpfSk7Y2FzZSAzOnJldHVybiBwcm9jZXNzLm5leHRUaWNrKGZ1bmN0aW9uIGFmdGVyVGlja1R3bygpe2ZuLmNhbGwobnVsbCxhcmcxLGFyZzIpfSk7Y2FzZSA0OnJldHVybiBwcm9jZXNzLm5leHRUaWNrKGZ1bmN0aW9uIGFmdGVyVGlja1RocmVlKCl7Zm4uY2FsbChudWxsLGFyZzEsYXJnMixhcmczKX0pO2RlZmF1bHQ6YXJncz1uZXcgQXJyYXkobGVuLTEpO2k9MDt3aGlsZShpPGFyZ3MubGVuZ3RoKXthcmdzW2krK109YXJndW1lbnRzW2ldfXJldHVybiBwcm9jZXNzLm5leHRUaWNrKGZ1bmN0aW9uIGFmdGVyVGljaygpe2ZuLmFwcGx5KG51bGwsYXJncyl9KX19fSkuY2FsbCh0aGlzLHJlcXVpcmUoXCJfcHJvY2Vzc1wiKSl9LHtfcHJvY2Vzczo0Mn1dLDQyOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXt2YXIgcHJvY2Vzcz1tb2R1bGUuZXhwb3J0cz17fTt2YXIgY2FjaGVkU2V0VGltZW91dDt2YXIgY2FjaGVkQ2xlYXJUaW1lb3V0O2Z1bmN0aW9uIGRlZmF1bHRTZXRUaW1vdXQoKXt0aHJvdyBuZXcgRXJyb3IoXCJzZXRUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkXCIpfWZ1bmN0aW9uIGRlZmF1bHRDbGVhclRpbWVvdXQoKXt0aHJvdyBuZXcgRXJyb3IoXCJjbGVhclRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWRcIil9KGZ1bmN0aW9uKCl7dHJ5e2lmKHR5cGVvZiBzZXRUaW1lb3V0PT09XCJmdW5jdGlvblwiKXtjYWNoZWRTZXRUaW1lb3V0PXNldFRpbWVvdXR9ZWxzZXtjYWNoZWRTZXRUaW1lb3V0PWRlZmF1bHRTZXRUaW1vdXR9fWNhdGNoKGUpe2NhY2hlZFNldFRpbWVvdXQ9ZGVmYXVsdFNldFRpbW91dH10cnl7aWYodHlwZW9mIGNsZWFyVGltZW91dD09PVwiZnVuY3Rpb25cIil7Y2FjaGVkQ2xlYXJUaW1lb3V0PWNsZWFyVGltZW91dH1lbHNle2NhY2hlZENsZWFyVGltZW91dD1kZWZhdWx0Q2xlYXJUaW1lb3V0fX1jYXRjaChlKXtjYWNoZWRDbGVhclRpbWVvdXQ9ZGVmYXVsdENsZWFyVGltZW91dH19KSgpO2Z1bmN0aW9uIHJ1blRpbWVvdXQoZnVuKXtpZihjYWNoZWRTZXRUaW1lb3V0PT09c2V0VGltZW91dCl7cmV0dXJuIHNldFRpbWVvdXQoZnVuLDApfWlmKChjYWNoZWRTZXRUaW1lb3V0PT09ZGVmYXVsdFNldFRpbW91dHx8IWNhY2hlZFNldFRpbWVvdXQpJiZzZXRUaW1lb3V0KXtjYWNoZWRTZXRUaW1lb3V0PXNldFRpbWVvdXQ7cmV0dXJuIHNldFRpbWVvdXQoZnVuLDApfXRyeXtyZXR1cm4gY2FjaGVkU2V0VGltZW91dChmdW4sMCl9Y2F0Y2goZSl7dHJ5e3JldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwobnVsbCxmdW4sMCl9Y2F0Y2goZSl7cmV0dXJuIGNhY2hlZFNldFRpbWVvdXQuY2FsbCh0aGlzLGZ1biwwKX19fWZ1bmN0aW9uIHJ1bkNsZWFyVGltZW91dChtYXJrZXIpe2lmKGNhY2hlZENsZWFyVGltZW91dD09PWNsZWFyVGltZW91dCl7cmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpfWlmKChjYWNoZWRDbGVhclRpbWVvdXQ9PT1kZWZhdWx0Q2xlYXJUaW1lb3V0fHwhY2FjaGVkQ2xlYXJUaW1lb3V0KSYmY2xlYXJUaW1lb3V0KXtjYWNoZWRDbGVhclRpbWVvdXQ9Y2xlYXJUaW1lb3V0O3JldHVybiBjbGVhclRpbWVvdXQobWFya2VyKX10cnl7cmV0dXJuIGNhY2hlZENsZWFyVGltZW91dChtYXJrZXIpfWNhdGNoKGUpe3RyeXtyZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0LmNhbGwobnVsbCxtYXJrZXIpfWNhdGNoKGUpe3JldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbCh0aGlzLG1hcmtlcil9fX12YXIgcXVldWU9W107dmFyIGRyYWluaW5nPWZhbHNlO3ZhciBjdXJyZW50UXVldWU7dmFyIHF1ZXVlSW5kZXg9LTE7ZnVuY3Rpb24gY2xlYW5VcE5leHRUaWNrKCl7aWYoIWRyYWluaW5nfHwhY3VycmVudFF1ZXVlKXtyZXR1cm59ZHJhaW5pbmc9ZmFsc2U7aWYoY3VycmVudFF1ZXVlLmxlbmd0aCl7cXVldWU9Y3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSl9ZWxzZXtxdWV1ZUluZGV4PS0xfWlmKHF1ZXVlLmxlbmd0aCl7ZHJhaW5RdWV1ZSgpfX1mdW5jdGlvbiBkcmFpblF1ZXVlKCl7aWYoZHJhaW5pbmcpe3JldHVybn12YXIgdGltZW91dD1ydW5UaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7ZHJhaW5pbmc9dHJ1ZTt2YXIgbGVuPXF1ZXVlLmxlbmd0aDt3aGlsZShsZW4pe2N1cnJlbnRRdWV1ZT1xdWV1ZTtxdWV1ZT1bXTt3aGlsZSgrK3F1ZXVlSW5kZXg8bGVuKXtpZihjdXJyZW50UXVldWUpe2N1cnJlbnRRdWV1ZVtxdWV1ZUluZGV4XS5ydW4oKX19cXVldWVJbmRleD0tMTtsZW49cXVldWUubGVuZ3RofWN1cnJlbnRRdWV1ZT1udWxsO2RyYWluaW5nPWZhbHNlO3J1bkNsZWFyVGltZW91dCh0aW1lb3V0KX1wcm9jZXNzLm5leHRUaWNrPWZ1bmN0aW9uKGZ1bil7dmFyIGFyZ3M9bmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGgtMSk7aWYoYXJndW1lbnRzLmxlbmd0aD4xKXtmb3IodmFyIGk9MTtpPGFyZ3VtZW50cy5sZW5ndGg7aSsrKXthcmdzW2ktMV09YXJndW1lbnRzW2ldfX1xdWV1ZS5wdXNoKG5ldyBJdGVtKGZ1bixhcmdzKSk7aWYocXVldWUubGVuZ3RoPT09MSYmIWRyYWluaW5nKXtydW5UaW1lb3V0KGRyYWluUXVldWUpfX07ZnVuY3Rpb24gSXRlbShmdW4sYXJyYXkpe3RoaXMuZnVuPWZ1bjt0aGlzLmFycmF5PWFycmF5fUl0ZW0ucHJvdG90eXBlLnJ1bj1mdW5jdGlvbigpe3RoaXMuZnVuLmFwcGx5KG51bGwsdGhpcy5hcnJheSl9O3Byb2Nlc3MudGl0bGU9XCJicm93c2VyXCI7cHJvY2Vzcy5icm93c2VyPXRydWU7cHJvY2Vzcy5lbnY9e307cHJvY2Vzcy5hcmd2PVtdO3Byb2Nlc3MudmVyc2lvbj1cIlwiO3Byb2Nlc3MudmVyc2lvbnM9e307ZnVuY3Rpb24gbm9vcCgpe31wcm9jZXNzLm9uPW5vb3A7cHJvY2Vzcy5hZGRMaXN0ZW5lcj1ub29wO3Byb2Nlc3Mub25jZT1ub29wO3Byb2Nlc3Mub2ZmPW5vb3A7cHJvY2Vzcy5yZW1vdmVMaXN0ZW5lcj1ub29wO3Byb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzPW5vb3A7cHJvY2Vzcy5lbWl0PW5vb3A7cHJvY2Vzcy5iaW5kaW5nPWZ1bmN0aW9uKG5hbWUpe3Rocm93IG5ldyBFcnJvcihcInByb2Nlc3MuYmluZGluZyBpcyBub3Qgc3VwcG9ydGVkXCIpfTtwcm9jZXNzLmN3ZD1mdW5jdGlvbigpe3JldHVyblwiL1wifTtwcm9jZXNzLmNoZGlyPWZ1bmN0aW9uKGRpcil7dGhyb3cgbmV3IEVycm9yKFwicHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkXCIpfTtwcm9jZXNzLnVtYXNrPWZ1bmN0aW9uKCl7cmV0dXJuIDB9fSx7fV0sNDM6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe21vZHVsZS5leHBvcnRzPXJlcXVpcmUoXCIuL2xpYi9fc3RyZWFtX2R1cGxleC5qc1wiKX0se1wiLi9saWIvX3N0cmVhbV9kdXBsZXguanNcIjo0NH1dLDQ0OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcInVzZSBzdHJpY3RcIjt2YXIgb2JqZWN0S2V5cz1PYmplY3Qua2V5c3x8ZnVuY3Rpb24ob2JqKXt2YXIga2V5cz1bXTtmb3IodmFyIGtleSBpbiBvYmope2tleXMucHVzaChrZXkpfXJldHVybiBrZXlzfTttb2R1bGUuZXhwb3J0cz1EdXBsZXg7dmFyIHByb2Nlc3NOZXh0VGljaz1yZXF1aXJlKFwicHJvY2Vzcy1uZXh0aWNrLWFyZ3NcIik7dmFyIHV0aWw9cmVxdWlyZShcImNvcmUtdXRpbC1pc1wiKTt1dGlsLmluaGVyaXRzPXJlcXVpcmUoXCJpbmhlcml0c1wiKTt2YXIgUmVhZGFibGU9cmVxdWlyZShcIi4vX3N0cmVhbV9yZWFkYWJsZVwiKTt2YXIgV3JpdGFibGU9cmVxdWlyZShcIi4vX3N0cmVhbV93cml0YWJsZVwiKTt1dGlsLmluaGVyaXRzKER1cGxleCxSZWFkYWJsZSk7dmFyIGtleXM9b2JqZWN0S2V5cyhXcml0YWJsZS5wcm90b3R5cGUpO2Zvcih2YXIgdj0wO3Y8a2V5cy5sZW5ndGg7disrKXt2YXIgbWV0aG9kPWtleXNbdl07aWYoIUR1cGxleC5wcm90b3R5cGVbbWV0aG9kXSlEdXBsZXgucHJvdG90eXBlW21ldGhvZF09V3JpdGFibGUucHJvdG90eXBlW21ldGhvZF19ZnVuY3Rpb24gRHVwbGV4KG9wdGlvbnMpe2lmKCEodGhpcyBpbnN0YW5jZW9mIER1cGxleCkpcmV0dXJuIG5ldyBEdXBsZXgob3B0aW9ucyk7UmVhZGFibGUuY2FsbCh0aGlzLG9wdGlvbnMpO1dyaXRhYmxlLmNhbGwodGhpcyxvcHRpb25zKTtpZihvcHRpb25zJiZvcHRpb25zLnJlYWRhYmxlPT09ZmFsc2UpdGhpcy5yZWFkYWJsZT1mYWxzZTtpZihvcHRpb25zJiZvcHRpb25zLndyaXRhYmxlPT09ZmFsc2UpdGhpcy53cml0YWJsZT1mYWxzZTt0aGlzLmFsbG93SGFsZk9wZW49dHJ1ZTtpZihvcHRpb25zJiZvcHRpb25zLmFsbG93SGFsZk9wZW49PT1mYWxzZSl0aGlzLmFsbG93SGFsZk9wZW49ZmFsc2U7dGhpcy5vbmNlKFwiZW5kXCIsb25lbmQpfWZ1bmN0aW9uIG9uZW5kKCl7aWYodGhpcy5hbGxvd0hhbGZPcGVufHx0aGlzLl93cml0YWJsZVN0YXRlLmVuZGVkKXJldHVybjtwcm9jZXNzTmV4dFRpY2sob25FbmROVCx0aGlzKX1mdW5jdGlvbiBvbkVuZE5UKHNlbGYpe3NlbGYuZW5kKCl9ZnVuY3Rpb24gZm9yRWFjaCh4cyxmKXtmb3IodmFyIGk9MCxsPXhzLmxlbmd0aDtpPGw7aSsrKXtmKHhzW2ldLGkpfX19LHtcIi4vX3N0cmVhbV9yZWFkYWJsZVwiOjQ2LFwiLi9fc3RyZWFtX3dyaXRhYmxlXCI6NDgsXCJjb3JlLXV0aWwtaXNcIjo2LGluaGVyaXRzOjM4LFwicHJvY2Vzcy1uZXh0aWNrLWFyZ3NcIjo0MX1dLDQ1OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcInVzZSBzdHJpY3RcIjttb2R1bGUuZXhwb3J0cz1QYXNzVGhyb3VnaDt2YXIgVHJhbnNmb3JtPXJlcXVpcmUoXCIuL19zdHJlYW1fdHJhbnNmb3JtXCIpO3ZhciB1dGlsPXJlcXVpcmUoXCJjb3JlLXV0aWwtaXNcIik7dXRpbC5pbmhlcml0cz1yZXF1aXJlKFwiaW5oZXJpdHNcIik7dXRpbC5pbmhlcml0cyhQYXNzVGhyb3VnaCxUcmFuc2Zvcm0pO2Z1bmN0aW9uIFBhc3NUaHJvdWdoKG9wdGlvbnMpe2lmKCEodGhpcyBpbnN0YW5jZW9mIFBhc3NUaHJvdWdoKSlyZXR1cm4gbmV3IFBhc3NUaHJvdWdoKG9wdGlvbnMpO1RyYW5zZm9ybS5jYWxsKHRoaXMsb3B0aW9ucyl9UGFzc1Rocm91Z2gucHJvdG90eXBlLl90cmFuc2Zvcm09ZnVuY3Rpb24oY2h1bmssZW5jb2RpbmcsY2Ipe2NiKG51bGwsY2h1bmspfX0se1wiLi9fc3RyZWFtX3RyYW5zZm9ybVwiOjQ3LFwiY29yZS11dGlsLWlzXCI6Nixpbmhlcml0czozOH1dLDQ2OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXsoZnVuY3Rpb24ocHJvY2Vzcyl7XCJ1c2Ugc3RyaWN0XCI7bW9kdWxlLmV4cG9ydHM9UmVhZGFibGU7dmFyIHByb2Nlc3NOZXh0VGljaz1yZXF1aXJlKFwicHJvY2Vzcy1uZXh0aWNrLWFyZ3NcIik7dmFyIGlzQXJyYXk9cmVxdWlyZShcImlzYXJyYXlcIik7UmVhZGFibGUuUmVhZGFibGVTdGF0ZT1SZWFkYWJsZVN0YXRlO3ZhciBFRT1yZXF1aXJlKFwiZXZlbnRzXCIpLkV2ZW50RW1pdHRlcjt2YXIgRUVsaXN0ZW5lckNvdW50PWZ1bmN0aW9uKGVtaXR0ZXIsdHlwZSl7cmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJzKHR5cGUpLmxlbmd0aH07dmFyIFN0cmVhbTsoZnVuY3Rpb24oKXt0cnl7U3RyZWFtPXJlcXVpcmUoXCJzdFwiK1wicmVhbVwiKX1jYXRjaChfKXt9ZmluYWxseXtpZighU3RyZWFtKVN0cmVhbT1yZXF1aXJlKFwiZXZlbnRzXCIpLkV2ZW50RW1pdHRlcn19KSgpO3ZhciBCdWZmZXI9cmVxdWlyZShcImJ1ZmZlclwiKS5CdWZmZXI7dmFyIGJ1ZmZlclNoaW09cmVxdWlyZShcImJ1ZmZlci1zaGltc1wiKTt2YXIgdXRpbD1yZXF1aXJlKFwiY29yZS11dGlsLWlzXCIpO3V0aWwuaW5oZXJpdHM9cmVxdWlyZShcImluaGVyaXRzXCIpO3ZhciBkZWJ1Z1V0aWw9cmVxdWlyZShcInV0aWxcIik7dmFyIGRlYnVnPXZvaWQgMDtpZihkZWJ1Z1V0aWwmJmRlYnVnVXRpbC5kZWJ1Z2xvZyl7ZGVidWc9ZGVidWdVdGlsLmRlYnVnbG9nKFwic3RyZWFtXCIpfWVsc2V7ZGVidWc9ZnVuY3Rpb24oKXt9fXZhciBCdWZmZXJMaXN0PXJlcXVpcmUoXCIuL2ludGVybmFsL3N0cmVhbXMvQnVmZmVyTGlzdFwiKTt2YXIgU3RyaW5nRGVjb2Rlcjt1dGlsLmluaGVyaXRzKFJlYWRhYmxlLFN0cmVhbSk7ZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKGVtaXR0ZXIsZXZlbnQsZm4pe2lmKHR5cGVvZiBlbWl0dGVyLnByZXBlbmRMaXN0ZW5lcj09PVwiZnVuY3Rpb25cIil7cmV0dXJuIGVtaXR0ZXIucHJlcGVuZExpc3RlbmVyKGV2ZW50LGZuKX1lbHNle2lmKCFlbWl0dGVyLl9ldmVudHN8fCFlbWl0dGVyLl9ldmVudHNbZXZlbnRdKWVtaXR0ZXIub24oZXZlbnQsZm4pO2Vsc2UgaWYoaXNBcnJheShlbWl0dGVyLl9ldmVudHNbZXZlbnRdKSllbWl0dGVyLl9ldmVudHNbZXZlbnRdLnVuc2hpZnQoZm4pO2Vsc2UgZW1pdHRlci5fZXZlbnRzW2V2ZW50XT1bZm4sZW1pdHRlci5fZXZlbnRzW2V2ZW50XV19fXZhciBEdXBsZXg7ZnVuY3Rpb24gUmVhZGFibGVTdGF0ZShvcHRpb25zLHN0cmVhbSl7RHVwbGV4PUR1cGxleHx8cmVxdWlyZShcIi4vX3N0cmVhbV9kdXBsZXhcIik7b3B0aW9ucz1vcHRpb25zfHx7fTt0aGlzLm9iamVjdE1vZGU9ISFvcHRpb25zLm9iamVjdE1vZGU7aWYoc3RyZWFtIGluc3RhbmNlb2YgRHVwbGV4KXRoaXMub2JqZWN0TW9kZT10aGlzLm9iamVjdE1vZGV8fCEhb3B0aW9ucy5yZWFkYWJsZU9iamVjdE1vZGU7dmFyIGh3bT1vcHRpb25zLmhpZ2hXYXRlck1hcms7dmFyIGRlZmF1bHRId209dGhpcy5vYmplY3RNb2RlPzE2OjE2KjEwMjQ7dGhpcy5oaWdoV2F0ZXJNYXJrPWh3bXx8aHdtPT09MD9od206ZGVmYXVsdEh3bTt0aGlzLmhpZ2hXYXRlck1hcms9fn50aGlzLmhpZ2hXYXRlck1hcms7dGhpcy5idWZmZXI9bmV3IEJ1ZmZlckxpc3Q7dGhpcy5sZW5ndGg9MDt0aGlzLnBpcGVzPW51bGw7dGhpcy5waXBlc0NvdW50PTA7dGhpcy5mbG93aW5nPW51bGw7dGhpcy5lbmRlZD1mYWxzZTt0aGlzLmVuZEVtaXR0ZWQ9ZmFsc2U7dGhpcy5yZWFkaW5nPWZhbHNlO3RoaXMuc3luYz10cnVlO3RoaXMubmVlZFJlYWRhYmxlPWZhbHNlO3RoaXMuZW1pdHRlZFJlYWRhYmxlPWZhbHNlO3RoaXMucmVhZGFibGVMaXN0ZW5pbmc9ZmFsc2U7dGhpcy5yZXN1bWVTY2hlZHVsZWQ9ZmFsc2U7dGhpcy5kZWZhdWx0RW5jb2Rpbmc9b3B0aW9ucy5kZWZhdWx0RW5jb2Rpbmd8fFwidXRmOFwiO3RoaXMucmFuT3V0PWZhbHNlO3RoaXMuYXdhaXREcmFpbj0wO3RoaXMucmVhZGluZ01vcmU9ZmFsc2U7dGhpcy5kZWNvZGVyPW51bGw7dGhpcy5lbmNvZGluZz1udWxsO2lmKG9wdGlvbnMuZW5jb2Rpbmcpe2lmKCFTdHJpbmdEZWNvZGVyKVN0cmluZ0RlY29kZXI9cmVxdWlyZShcInN0cmluZ19kZWNvZGVyL1wiKS5TdHJpbmdEZWNvZGVyO3RoaXMuZGVjb2Rlcj1uZXcgU3RyaW5nRGVjb2RlcihvcHRpb25zLmVuY29kaW5nKTt0aGlzLmVuY29kaW5nPW9wdGlvbnMuZW5jb2Rpbmd9fXZhciBEdXBsZXg7ZnVuY3Rpb24gUmVhZGFibGUob3B0aW9ucyl7RHVwbGV4PUR1cGxleHx8cmVxdWlyZShcIi4vX3N0cmVhbV9kdXBsZXhcIik7aWYoISh0aGlzIGluc3RhbmNlb2YgUmVhZGFibGUpKXJldHVybiBuZXcgUmVhZGFibGUob3B0aW9ucyk7dGhpcy5fcmVhZGFibGVTdGF0ZT1uZXcgUmVhZGFibGVTdGF0ZShvcHRpb25zLHRoaXMpO3RoaXMucmVhZGFibGU9dHJ1ZTtpZihvcHRpb25zJiZ0eXBlb2Ygb3B0aW9ucy5yZWFkPT09XCJmdW5jdGlvblwiKXRoaXMuX3JlYWQ9b3B0aW9ucy5yZWFkO1N0cmVhbS5jYWxsKHRoaXMpfVJlYWRhYmxlLnByb3RvdHlwZS5wdXNoPWZ1bmN0aW9uKGNodW5rLGVuY29kaW5nKXt2YXIgc3RhdGU9dGhpcy5fcmVhZGFibGVTdGF0ZTtpZighc3RhdGUub2JqZWN0TW9kZSYmdHlwZW9mIGNodW5rPT09XCJzdHJpbmdcIil7ZW5jb2Rpbmc9ZW5jb2Rpbmd8fHN0YXRlLmRlZmF1bHRFbmNvZGluZztpZihlbmNvZGluZyE9PXN0YXRlLmVuY29kaW5nKXtjaHVuaz1idWZmZXJTaGltLmZyb20oY2h1bmssZW5jb2RpbmcpO2VuY29kaW5nPVwiXCJ9fXJldHVybiByZWFkYWJsZUFkZENodW5rKHRoaXMsc3RhdGUsY2h1bmssZW5jb2RpbmcsZmFsc2UpfTtSZWFkYWJsZS5wcm90b3R5cGUudW5zaGlmdD1mdW5jdGlvbihjaHVuayl7dmFyIHN0YXRlPXRoaXMuX3JlYWRhYmxlU3RhdGU7cmV0dXJuIHJlYWRhYmxlQWRkQ2h1bmsodGhpcyxzdGF0ZSxjaHVuayxcIlwiLHRydWUpfTtSZWFkYWJsZS5wcm90b3R5cGUuaXNQYXVzZWQ9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5fcmVhZGFibGVTdGF0ZS5mbG93aW5nPT09ZmFsc2V9O2Z1bmN0aW9uIHJlYWRhYmxlQWRkQ2h1bmsoc3RyZWFtLHN0YXRlLGNodW5rLGVuY29kaW5nLGFkZFRvRnJvbnQpe3ZhciBlcj1jaHVua0ludmFsaWQoc3RhdGUsY2h1bmspO2lmKGVyKXtzdHJlYW0uZW1pdChcImVycm9yXCIsZXIpfWVsc2UgaWYoY2h1bms9PT1udWxsKXtzdGF0ZS5yZWFkaW5nPWZhbHNlO29uRW9mQ2h1bmsoc3RyZWFtLHN0YXRlKX1lbHNlIGlmKHN0YXRlLm9iamVjdE1vZGV8fGNodW5rJiZjaHVuay5sZW5ndGg+MCl7aWYoc3RhdGUuZW5kZWQmJiFhZGRUb0Zyb250KXt2YXIgZT1uZXcgRXJyb3IoXCJzdHJlYW0ucHVzaCgpIGFmdGVyIEVPRlwiKTtzdHJlYW0uZW1pdChcImVycm9yXCIsZSl9ZWxzZSBpZihzdGF0ZS5lbmRFbWl0dGVkJiZhZGRUb0Zyb250KXt2YXIgX2U9bmV3IEVycm9yKFwic3RyZWFtLnVuc2hpZnQoKSBhZnRlciBlbmQgZXZlbnRcIik7c3RyZWFtLmVtaXQoXCJlcnJvclwiLF9lKX1lbHNle3ZhciBza2lwQWRkO2lmKHN0YXRlLmRlY29kZXImJiFhZGRUb0Zyb250JiYhZW5jb2Rpbmcpe2NodW5rPXN0YXRlLmRlY29kZXIud3JpdGUoY2h1bmspO3NraXBBZGQ9IXN0YXRlLm9iamVjdE1vZGUmJmNodW5rLmxlbmd0aD09PTB9aWYoIWFkZFRvRnJvbnQpc3RhdGUucmVhZGluZz1mYWxzZTtpZighc2tpcEFkZCl7aWYoc3RhdGUuZmxvd2luZyYmc3RhdGUubGVuZ3RoPT09MCYmIXN0YXRlLnN5bmMpe3N0cmVhbS5lbWl0KFwiZGF0YVwiLGNodW5rKTtzdHJlYW0ucmVhZCgwKX1lbHNle3N0YXRlLmxlbmd0aCs9c3RhdGUub2JqZWN0TW9kZT8xOmNodW5rLmxlbmd0aDtpZihhZGRUb0Zyb250KXN0YXRlLmJ1ZmZlci51bnNoaWZ0KGNodW5rKTtlbHNlIHN0YXRlLmJ1ZmZlci5wdXNoKGNodW5rKTtpZihzdGF0ZS5uZWVkUmVhZGFibGUpZW1pdFJlYWRhYmxlKHN0cmVhbSl9fW1heWJlUmVhZE1vcmUoc3RyZWFtLHN0YXRlKX19ZWxzZSBpZighYWRkVG9Gcm9udCl7c3RhdGUucmVhZGluZz1mYWxzZX1yZXR1cm4gbmVlZE1vcmVEYXRhKHN0YXRlKX1mdW5jdGlvbiBuZWVkTW9yZURhdGEoc3RhdGUpe3JldHVybiFzdGF0ZS5lbmRlZCYmKHN0YXRlLm5lZWRSZWFkYWJsZXx8c3RhdGUubGVuZ3RoPHN0YXRlLmhpZ2hXYXRlck1hcmt8fHN0YXRlLmxlbmd0aD09PTApfVJlYWRhYmxlLnByb3RvdHlwZS5zZXRFbmNvZGluZz1mdW5jdGlvbihlbmMpe2lmKCFTdHJpbmdEZWNvZGVyKVN0cmluZ0RlY29kZXI9cmVxdWlyZShcInN0cmluZ19kZWNvZGVyL1wiKS5TdHJpbmdEZWNvZGVyO3RoaXMuX3JlYWRhYmxlU3RhdGUuZGVjb2Rlcj1uZXcgU3RyaW5nRGVjb2RlcihlbmMpO3RoaXMuX3JlYWRhYmxlU3RhdGUuZW5jb2Rpbmc9ZW5jO3JldHVybiB0aGlzfTt2YXIgTUFYX0hXTT04Mzg4NjA4O2Z1bmN0aW9uIGNvbXB1dGVOZXdIaWdoV2F0ZXJNYXJrKG4pe2lmKG4+PU1BWF9IV00pe249TUFYX0hXTX1lbHNle24tLTtufD1uPj4+MTtufD1uPj4+MjtufD1uPj4+NDtufD1uPj4+ODtufD1uPj4+MTY7bisrfXJldHVybiBufWZ1bmN0aW9uIGhvd011Y2hUb1JlYWQobixzdGF0ZSl7aWYobjw9MHx8c3RhdGUubGVuZ3RoPT09MCYmc3RhdGUuZW5kZWQpcmV0dXJuIDA7aWYoc3RhdGUub2JqZWN0TW9kZSlyZXR1cm4gMTtpZihuIT09bil7aWYoc3RhdGUuZmxvd2luZyYmc3RhdGUubGVuZ3RoKXJldHVybiBzdGF0ZS5idWZmZXIuaGVhZC5kYXRhLmxlbmd0aDtlbHNlIHJldHVybiBzdGF0ZS5sZW5ndGh9aWYobj5zdGF0ZS5oaWdoV2F0ZXJNYXJrKXN0YXRlLmhpZ2hXYXRlck1hcms9Y29tcHV0ZU5ld0hpZ2hXYXRlck1hcmsobik7aWYobjw9c3RhdGUubGVuZ3RoKXJldHVybiBuO2lmKCFzdGF0ZS5lbmRlZCl7c3RhdGUubmVlZFJlYWRhYmxlPXRydWU7cmV0dXJuIDB9cmV0dXJuIHN0YXRlLmxlbmd0aH1SZWFkYWJsZS5wcm90b3R5cGUucmVhZD1mdW5jdGlvbihuKXtkZWJ1ZyhcInJlYWRcIixuKTtuPXBhcnNlSW50KG4sMTApO3ZhciBzdGF0ZT10aGlzLl9yZWFkYWJsZVN0YXRlO3ZhciBuT3JpZz1uO2lmKG4hPT0wKXN0YXRlLmVtaXR0ZWRSZWFkYWJsZT1mYWxzZTtpZihuPT09MCYmc3RhdGUubmVlZFJlYWRhYmxlJiYoc3RhdGUubGVuZ3RoPj1zdGF0ZS5oaWdoV2F0ZXJNYXJrfHxzdGF0ZS5lbmRlZCkpe2RlYnVnKFwicmVhZDogZW1pdFJlYWRhYmxlXCIsc3RhdGUubGVuZ3RoLHN0YXRlLmVuZGVkKTtpZihzdGF0ZS5sZW5ndGg9PT0wJiZzdGF0ZS5lbmRlZCllbmRSZWFkYWJsZSh0aGlzKTtlbHNlIGVtaXRSZWFkYWJsZSh0aGlzKTtyZXR1cm4gbnVsbH1uPWhvd011Y2hUb1JlYWQobixzdGF0ZSk7aWYobj09PTAmJnN0YXRlLmVuZGVkKXtpZihzdGF0ZS5sZW5ndGg9PT0wKWVuZFJlYWRhYmxlKHRoaXMpO3JldHVybiBudWxsfXZhciBkb1JlYWQ9c3RhdGUubmVlZFJlYWRhYmxlO2RlYnVnKFwibmVlZCByZWFkYWJsZVwiLGRvUmVhZCk7aWYoc3RhdGUubGVuZ3RoPT09MHx8c3RhdGUubGVuZ3RoLW48c3RhdGUuaGlnaFdhdGVyTWFyayl7ZG9SZWFkPXRydWU7ZGVidWcoXCJsZW5ndGggbGVzcyB0aGFuIHdhdGVybWFya1wiLGRvUmVhZCl9aWYoc3RhdGUuZW5kZWR8fHN0YXRlLnJlYWRpbmcpe2RvUmVhZD1mYWxzZTtkZWJ1ZyhcInJlYWRpbmcgb3IgZW5kZWRcIixkb1JlYWQpfWVsc2UgaWYoZG9SZWFkKXtkZWJ1ZyhcImRvIHJlYWRcIik7c3RhdGUucmVhZGluZz10cnVlO3N0YXRlLnN5bmM9dHJ1ZTtpZihzdGF0ZS5sZW5ndGg9PT0wKXN0YXRlLm5lZWRSZWFkYWJsZT10cnVlO3RoaXMuX3JlYWQoc3RhdGUuaGlnaFdhdGVyTWFyayk7c3RhdGUuc3luYz1mYWxzZTtpZighc3RhdGUucmVhZGluZyluPWhvd011Y2hUb1JlYWQobk9yaWcsc3RhdGUpfXZhciByZXQ7aWYobj4wKXJldD1mcm9tTGlzdChuLHN0YXRlKTtlbHNlIHJldD1udWxsO2lmKHJldD09PW51bGwpe3N0YXRlLm5lZWRSZWFkYWJsZT10cnVlO249MH1lbHNle3N0YXRlLmxlbmd0aC09bn1pZihzdGF0ZS5sZW5ndGg9PT0wKXtpZighc3RhdGUuZW5kZWQpc3RhdGUubmVlZFJlYWRhYmxlPXRydWU7aWYobk9yaWchPT1uJiZzdGF0ZS5lbmRlZCllbmRSZWFkYWJsZSh0aGlzKX1pZihyZXQhPT1udWxsKXRoaXMuZW1pdChcImRhdGFcIixyZXQpO3JldHVybiByZXR9O2Z1bmN0aW9uIGNodW5rSW52YWxpZChzdGF0ZSxjaHVuayl7dmFyIGVyPW51bGw7aWYoIUJ1ZmZlci5pc0J1ZmZlcihjaHVuaykmJnR5cGVvZiBjaHVuayE9PVwic3RyaW5nXCImJmNodW5rIT09bnVsbCYmY2h1bmshPT11bmRlZmluZWQmJiFzdGF0ZS5vYmplY3RNb2RlKXtlcj1uZXcgVHlwZUVycm9yKFwiSW52YWxpZCBub24tc3RyaW5nL2J1ZmZlciBjaHVua1wiKX1yZXR1cm4gZXJ9ZnVuY3Rpb24gb25Fb2ZDaHVuayhzdHJlYW0sc3RhdGUpe2lmKHN0YXRlLmVuZGVkKXJldHVybjtpZihzdGF0ZS5kZWNvZGVyKXt2YXIgY2h1bms9c3RhdGUuZGVjb2Rlci5lbmQoKTtpZihjaHVuayYmY2h1bmsubGVuZ3RoKXtzdGF0ZS5idWZmZXIucHVzaChjaHVuayk7c3RhdGUubGVuZ3RoKz1zdGF0ZS5vYmplY3RNb2RlPzE6Y2h1bmsubGVuZ3RofX1zdGF0ZS5lbmRlZD10cnVlO2VtaXRSZWFkYWJsZShzdHJlYW0pfWZ1bmN0aW9uIGVtaXRSZWFkYWJsZShzdHJlYW0pe3ZhciBzdGF0ZT1zdHJlYW0uX3JlYWRhYmxlU3RhdGU7c3RhdGUubmVlZFJlYWRhYmxlPWZhbHNlO2lmKCFzdGF0ZS5lbWl0dGVkUmVhZGFibGUpe2RlYnVnKFwiZW1pdFJlYWRhYmxlXCIsc3RhdGUuZmxvd2luZyk7c3RhdGUuZW1pdHRlZFJlYWRhYmxlPXRydWU7aWYoc3RhdGUuc3luYylwcm9jZXNzTmV4dFRpY2soZW1pdFJlYWRhYmxlXyxzdHJlYW0pO2Vsc2UgZW1pdFJlYWRhYmxlXyhzdHJlYW0pfX1mdW5jdGlvbiBlbWl0UmVhZGFibGVfKHN0cmVhbSl7ZGVidWcoXCJlbWl0IHJlYWRhYmxlXCIpO3N0cmVhbS5lbWl0KFwicmVhZGFibGVcIik7ZmxvdyhzdHJlYW0pfWZ1bmN0aW9uIG1heWJlUmVhZE1vcmUoc3RyZWFtLHN0YXRlKXtpZighc3RhdGUucmVhZGluZ01vcmUpe3N0YXRlLnJlYWRpbmdNb3JlPXRydWU7cHJvY2Vzc05leHRUaWNrKG1heWJlUmVhZE1vcmVfLHN0cmVhbSxzdGF0ZSl9fWZ1bmN0aW9uIG1heWJlUmVhZE1vcmVfKHN0cmVhbSxzdGF0ZSl7dmFyIGxlbj1zdGF0ZS5sZW5ndGg7d2hpbGUoIXN0YXRlLnJlYWRpbmcmJiFzdGF0ZS5mbG93aW5nJiYhc3RhdGUuZW5kZWQmJnN0YXRlLmxlbmd0aDxzdGF0ZS5oaWdoV2F0ZXJNYXJrKXtkZWJ1ZyhcIm1heWJlUmVhZE1vcmUgcmVhZCAwXCIpO3N0cmVhbS5yZWFkKDApO2lmKGxlbj09PXN0YXRlLmxlbmd0aClicmVhaztlbHNlIGxlbj1zdGF0ZS5sZW5ndGh9c3RhdGUucmVhZGluZ01vcmU9ZmFsc2V9UmVhZGFibGUucHJvdG90eXBlLl9yZWFkPWZ1bmN0aW9uKG4pe3RoaXMuZW1pdChcImVycm9yXCIsbmV3IEVycm9yKFwibm90IGltcGxlbWVudGVkXCIpKX07UmVhZGFibGUucHJvdG90eXBlLnBpcGU9ZnVuY3Rpb24oZGVzdCxwaXBlT3B0cyl7dmFyIHNyYz10aGlzO3ZhciBzdGF0ZT10aGlzLl9yZWFkYWJsZVN0YXRlO3N3aXRjaChzdGF0ZS5waXBlc0NvdW50KXtjYXNlIDA6c3RhdGUucGlwZXM9ZGVzdDticmVhaztjYXNlIDE6c3RhdGUucGlwZXM9W3N0YXRlLnBpcGVzLGRlc3RdO2JyZWFrO2RlZmF1bHQ6c3RhdGUucGlwZXMucHVzaChkZXN0KTticmVha31zdGF0ZS5waXBlc0NvdW50Kz0xO2RlYnVnKFwicGlwZSBjb3VudD0lZCBvcHRzPSVqXCIsc3RhdGUucGlwZXNDb3VudCxwaXBlT3B0cyk7dmFyIGRvRW5kPSghcGlwZU9wdHN8fHBpcGVPcHRzLmVuZCE9PWZhbHNlKSYmZGVzdCE9PXByb2Nlc3Muc3Rkb3V0JiZkZXN0IT09cHJvY2Vzcy5zdGRlcnI7dmFyIGVuZEZuPWRvRW5kP29uZW5kOmNsZWFudXA7aWYoc3RhdGUuZW5kRW1pdHRlZClwcm9jZXNzTmV4dFRpY2soZW5kRm4pO2Vsc2Ugc3JjLm9uY2UoXCJlbmRcIixlbmRGbik7ZGVzdC5vbihcInVucGlwZVwiLG9udW5waXBlKTtmdW5jdGlvbiBvbnVucGlwZShyZWFkYWJsZSl7ZGVidWcoXCJvbnVucGlwZVwiKTtpZihyZWFkYWJsZT09PXNyYyl7Y2xlYW51cCgpfX1mdW5jdGlvbiBvbmVuZCgpe2RlYnVnKFwib25lbmRcIik7ZGVzdC5lbmQoKX12YXIgb25kcmFpbj1waXBlT25EcmFpbihzcmMpO2Rlc3Qub24oXCJkcmFpblwiLG9uZHJhaW4pO3ZhciBjbGVhbmVkVXA9ZmFsc2U7ZnVuY3Rpb24gY2xlYW51cCgpe2RlYnVnKFwiY2xlYW51cFwiKTtkZXN0LnJlbW92ZUxpc3RlbmVyKFwiY2xvc2VcIixvbmNsb3NlKTtkZXN0LnJlbW92ZUxpc3RlbmVyKFwiZmluaXNoXCIsb25maW5pc2gpO2Rlc3QucmVtb3ZlTGlzdGVuZXIoXCJkcmFpblwiLG9uZHJhaW4pO2Rlc3QucmVtb3ZlTGlzdGVuZXIoXCJlcnJvclwiLG9uZXJyb3IpO2Rlc3QucmVtb3ZlTGlzdGVuZXIoXCJ1bnBpcGVcIixvbnVucGlwZSk7c3JjLnJlbW92ZUxpc3RlbmVyKFwiZW5kXCIsb25lbmQpO3NyYy5yZW1vdmVMaXN0ZW5lcihcImVuZFwiLGNsZWFudXApO3NyYy5yZW1vdmVMaXN0ZW5lcihcImRhdGFcIixvbmRhdGEpO2NsZWFuZWRVcD10cnVlO2lmKHN0YXRlLmF3YWl0RHJhaW4mJighZGVzdC5fd3JpdGFibGVTdGF0ZXx8ZGVzdC5fd3JpdGFibGVTdGF0ZS5uZWVkRHJhaW4pKW9uZHJhaW4oKX12YXIgaW5jcmVhc2VkQXdhaXREcmFpbj1mYWxzZTtzcmMub24oXCJkYXRhXCIsb25kYXRhKTtmdW5jdGlvbiBvbmRhdGEoY2h1bmspe2RlYnVnKFwib25kYXRhXCIpO2luY3JlYXNlZEF3YWl0RHJhaW49ZmFsc2U7dmFyIHJldD1kZXN0LndyaXRlKGNodW5rKTtpZihmYWxzZT09PXJldCYmIWluY3JlYXNlZEF3YWl0RHJhaW4pe2lmKChzdGF0ZS5waXBlc0NvdW50PT09MSYmc3RhdGUucGlwZXM9PT1kZXN0fHxzdGF0ZS5waXBlc0NvdW50PjEmJmluZGV4T2Yoc3RhdGUucGlwZXMsZGVzdCkhPT0tMSkmJiFjbGVhbmVkVXApe2RlYnVnKFwiZmFsc2Ugd3JpdGUgcmVzcG9uc2UsIHBhdXNlXCIsc3JjLl9yZWFkYWJsZVN0YXRlLmF3YWl0RHJhaW4pO3NyYy5fcmVhZGFibGVTdGF0ZS5hd2FpdERyYWluKys7aW5jcmVhc2VkQXdhaXREcmFpbj10cnVlfXNyYy5wYXVzZSgpfX1mdW5jdGlvbiBvbmVycm9yKGVyKXtkZWJ1ZyhcIm9uZXJyb3JcIixlcik7dW5waXBlKCk7ZGVzdC5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsb25lcnJvcik7aWYoRUVsaXN0ZW5lckNvdW50KGRlc3QsXCJlcnJvclwiKT09PTApZGVzdC5lbWl0KFwiZXJyb3JcIixlcil9cHJlcGVuZExpc3RlbmVyKGRlc3QsXCJlcnJvclwiLG9uZXJyb3IpO2Z1bmN0aW9uIG9uY2xvc2UoKXtkZXN0LnJlbW92ZUxpc3RlbmVyKFwiZmluaXNoXCIsb25maW5pc2gpO3VucGlwZSgpfWRlc3Qub25jZShcImNsb3NlXCIsb25jbG9zZSk7ZnVuY3Rpb24gb25maW5pc2goKXtkZWJ1ZyhcIm9uZmluaXNoXCIpO2Rlc3QucmVtb3ZlTGlzdGVuZXIoXCJjbG9zZVwiLG9uY2xvc2UpO3VucGlwZSgpfWRlc3Qub25jZShcImZpbmlzaFwiLG9uZmluaXNoKTtmdW5jdGlvbiB1bnBpcGUoKXtkZWJ1ZyhcInVucGlwZVwiKTtzcmMudW5waXBlKGRlc3QpfWRlc3QuZW1pdChcInBpcGVcIixzcmMpO2lmKCFzdGF0ZS5mbG93aW5nKXtkZWJ1ZyhcInBpcGUgcmVzdW1lXCIpO3NyYy5yZXN1bWUoKX1yZXR1cm4gZGVzdH07ZnVuY3Rpb24gcGlwZU9uRHJhaW4oc3JjKXtyZXR1cm4gZnVuY3Rpb24oKXt2YXIgc3RhdGU9c3JjLl9yZWFkYWJsZVN0YXRlO2RlYnVnKFwicGlwZU9uRHJhaW5cIixzdGF0ZS5hd2FpdERyYWluKTtpZihzdGF0ZS5hd2FpdERyYWluKXN0YXRlLmF3YWl0RHJhaW4tLTtpZihzdGF0ZS5hd2FpdERyYWluPT09MCYmRUVsaXN0ZW5lckNvdW50KHNyYyxcImRhdGFcIikpe3N0YXRlLmZsb3dpbmc9dHJ1ZTtmbG93KHNyYyl9fX1SZWFkYWJsZS5wcm90b3R5cGUudW5waXBlPWZ1bmN0aW9uKGRlc3Qpe3ZhciBzdGF0ZT10aGlzLl9yZWFkYWJsZVN0YXRlO2lmKHN0YXRlLnBpcGVzQ291bnQ9PT0wKXJldHVybiB0aGlzO2lmKHN0YXRlLnBpcGVzQ291bnQ9PT0xKXtpZihkZXN0JiZkZXN0IT09c3RhdGUucGlwZXMpcmV0dXJuIHRoaXM7aWYoIWRlc3QpZGVzdD1zdGF0ZS5waXBlcztzdGF0ZS5waXBlcz1udWxsO3N0YXRlLnBpcGVzQ291bnQ9MDtzdGF0ZS5mbG93aW5nPWZhbHNlO2lmKGRlc3QpZGVzdC5lbWl0KFwidW5waXBlXCIsdGhpcyk7cmV0dXJuIHRoaXN9aWYoIWRlc3Qpe3ZhciBkZXN0cz1zdGF0ZS5waXBlczt2YXIgbGVuPXN0YXRlLnBpcGVzQ291bnQ7c3RhdGUucGlwZXM9bnVsbDtzdGF0ZS5waXBlc0NvdW50PTA7c3RhdGUuZmxvd2luZz1mYWxzZTtmb3IodmFyIF9pPTA7X2k8bGVuO19pKyspe2Rlc3RzW19pXS5lbWl0KFwidW5waXBlXCIsdGhpcyl9cmV0dXJuIHRoaXN9dmFyIGk9aW5kZXhPZihzdGF0ZS5waXBlcyxkZXN0KTtpZihpPT09LTEpcmV0dXJuIHRoaXM7c3RhdGUucGlwZXMuc3BsaWNlKGksMSk7c3RhdGUucGlwZXNDb3VudC09MTtpZihzdGF0ZS5waXBlc0NvdW50PT09MSlzdGF0ZS5waXBlcz1zdGF0ZS5waXBlc1swXTtkZXN0LmVtaXQoXCJ1bnBpcGVcIix0aGlzKTtyZXR1cm4gdGhpc307UmVhZGFibGUucHJvdG90eXBlLm9uPWZ1bmN0aW9uKGV2LGZuKXt2YXIgcmVzPVN0cmVhbS5wcm90b3R5cGUub24uY2FsbCh0aGlzLGV2LGZuKTtpZihldj09PVwiZGF0YVwiKXtpZih0aGlzLl9yZWFkYWJsZVN0YXRlLmZsb3dpbmchPT1mYWxzZSl0aGlzLnJlc3VtZSgpfWVsc2UgaWYoZXY9PT1cInJlYWRhYmxlXCIpe3ZhciBzdGF0ZT10aGlzLl9yZWFkYWJsZVN0YXRlO2lmKCFzdGF0ZS5lbmRFbWl0dGVkJiYhc3RhdGUucmVhZGFibGVMaXN0ZW5pbmcpe3N0YXRlLnJlYWRhYmxlTGlzdGVuaW5nPXN0YXRlLm5lZWRSZWFkYWJsZT10cnVlO3N0YXRlLmVtaXR0ZWRSZWFkYWJsZT1mYWxzZTtpZighc3RhdGUucmVhZGluZyl7cHJvY2Vzc05leHRUaWNrKG5SZWFkaW5nTmV4dFRpY2ssdGhpcyl9ZWxzZSBpZihzdGF0ZS5sZW5ndGgpe2VtaXRSZWFkYWJsZSh0aGlzLHN0YXRlKX19fXJldHVybiByZXN9O1JlYWRhYmxlLnByb3RvdHlwZS5hZGRMaXN0ZW5lcj1SZWFkYWJsZS5wcm90b3R5cGUub247ZnVuY3Rpb24gblJlYWRpbmdOZXh0VGljayhzZWxmKXtkZWJ1ZyhcInJlYWRhYmxlIG5leHR0aWNrIHJlYWQgMFwiKTtzZWxmLnJlYWQoMCl9UmVhZGFibGUucHJvdG90eXBlLnJlc3VtZT1mdW5jdGlvbigpe3ZhciBzdGF0ZT10aGlzLl9yZWFkYWJsZVN0YXRlO2lmKCFzdGF0ZS5mbG93aW5nKXtkZWJ1ZyhcInJlc3VtZVwiKTtzdGF0ZS5mbG93aW5nPXRydWU7cmVzdW1lKHRoaXMsc3RhdGUpfXJldHVybiB0aGlzfTtmdW5jdGlvbiByZXN1bWUoc3RyZWFtLHN0YXRlKXtpZighc3RhdGUucmVzdW1lU2NoZWR1bGVkKXtzdGF0ZS5yZXN1bWVTY2hlZHVsZWQ9dHJ1ZTtwcm9jZXNzTmV4dFRpY2socmVzdW1lXyxzdHJlYW0sc3RhdGUpfX1mdW5jdGlvbiByZXN1bWVfKHN0cmVhbSxzdGF0ZSl7aWYoIXN0YXRlLnJlYWRpbmcpe2RlYnVnKFwicmVzdW1lIHJlYWQgMFwiKTtzdHJlYW0ucmVhZCgwKX1zdGF0ZS5yZXN1bWVTY2hlZHVsZWQ9ZmFsc2U7c3RhdGUuYXdhaXREcmFpbj0wO3N0cmVhbS5lbWl0KFwicmVzdW1lXCIpO2Zsb3coc3RyZWFtKTtpZihzdGF0ZS5mbG93aW5nJiYhc3RhdGUucmVhZGluZylzdHJlYW0ucmVhZCgwKX1SZWFkYWJsZS5wcm90b3R5cGUucGF1c2U9ZnVuY3Rpb24oKXtkZWJ1ZyhcImNhbGwgcGF1c2UgZmxvd2luZz0lalwiLHRoaXMuX3JlYWRhYmxlU3RhdGUuZmxvd2luZyk7aWYoZmFsc2UhPT10aGlzLl9yZWFkYWJsZVN0YXRlLmZsb3dpbmcpe2RlYnVnKFwicGF1c2VcIik7dGhpcy5fcmVhZGFibGVTdGF0ZS5mbG93aW5nPWZhbHNlO3RoaXMuZW1pdChcInBhdXNlXCIpfXJldHVybiB0aGlzfTtmdW5jdGlvbiBmbG93KHN0cmVhbSl7dmFyIHN0YXRlPXN0cmVhbS5fcmVhZGFibGVTdGF0ZTtkZWJ1ZyhcImZsb3dcIixzdGF0ZS5mbG93aW5nKTt3aGlsZShzdGF0ZS5mbG93aW5nJiZzdHJlYW0ucmVhZCgpIT09bnVsbCl7fX1SZWFkYWJsZS5wcm90b3R5cGUud3JhcD1mdW5jdGlvbihzdHJlYW0pe3ZhciBzdGF0ZT10aGlzLl9yZWFkYWJsZVN0YXRlO3ZhciBwYXVzZWQ9ZmFsc2U7dmFyIHNlbGY9dGhpcztzdHJlYW0ub24oXCJlbmRcIixmdW5jdGlvbigpe2RlYnVnKFwid3JhcHBlZCBlbmRcIik7aWYoc3RhdGUuZGVjb2RlciYmIXN0YXRlLmVuZGVkKXt2YXIgY2h1bms9c3RhdGUuZGVjb2Rlci5lbmQoKTtpZihjaHVuayYmY2h1bmsubGVuZ3RoKXNlbGYucHVzaChjaHVuayl9c2VsZi5wdXNoKG51bGwpfSk7c3RyZWFtLm9uKFwiZGF0YVwiLGZ1bmN0aW9uKGNodW5rKXtkZWJ1ZyhcIndyYXBwZWQgZGF0YVwiKTtpZihzdGF0ZS5kZWNvZGVyKWNodW5rPXN0YXRlLmRlY29kZXIud3JpdGUoY2h1bmspO2lmKHN0YXRlLm9iamVjdE1vZGUmJihjaHVuaz09PW51bGx8fGNodW5rPT09dW5kZWZpbmVkKSlyZXR1cm47ZWxzZSBpZighc3RhdGUub2JqZWN0TW9kZSYmKCFjaHVua3x8IWNodW5rLmxlbmd0aCkpcmV0dXJuO3ZhciByZXQ9c2VsZi5wdXNoKGNodW5rKTtpZighcmV0KXtwYXVzZWQ9dHJ1ZTtzdHJlYW0ucGF1c2UoKX19KTtmb3IodmFyIGkgaW4gc3RyZWFtKXtpZih0aGlzW2ldPT09dW5kZWZpbmVkJiZ0eXBlb2Ygc3RyZWFtW2ldPT09XCJmdW5jdGlvblwiKXt0aGlzW2ldPWZ1bmN0aW9uKG1ldGhvZCl7cmV0dXJuIGZ1bmN0aW9uKCl7cmV0dXJuIHN0cmVhbVttZXRob2RdLmFwcGx5KHN0cmVhbSxhcmd1bWVudHMpfX0oaSl9fXZhciBldmVudHM9W1wiZXJyb3JcIixcImNsb3NlXCIsXCJkZXN0cm95XCIsXCJwYXVzZVwiLFwicmVzdW1lXCJdO2ZvckVhY2goZXZlbnRzLGZ1bmN0aW9uKGV2KXtzdHJlYW0ub24oZXYsc2VsZi5lbWl0LmJpbmQoc2VsZixldikpfSk7c2VsZi5fcmVhZD1mdW5jdGlvbihuKXtkZWJ1ZyhcIndyYXBwZWQgX3JlYWRcIixuKTtpZihwYXVzZWQpe3BhdXNlZD1mYWxzZTtzdHJlYW0ucmVzdW1lKCl9fTtyZXR1cm4gc2VsZn07UmVhZGFibGUuX2Zyb21MaXN0PWZyb21MaXN0O2Z1bmN0aW9uIGZyb21MaXN0KG4sc3RhdGUpe2lmKHN0YXRlLmxlbmd0aD09PTApcmV0dXJuIG51bGw7dmFyIHJldDtpZihzdGF0ZS5vYmplY3RNb2RlKXJldD1zdGF0ZS5idWZmZXIuc2hpZnQoKTtlbHNlIGlmKCFufHxuPj1zdGF0ZS5sZW5ndGgpe2lmKHN0YXRlLmRlY29kZXIpcmV0PXN0YXRlLmJ1ZmZlci5qb2luKFwiXCIpO2Vsc2UgaWYoc3RhdGUuYnVmZmVyLmxlbmd0aD09PTEpcmV0PXN0YXRlLmJ1ZmZlci5oZWFkLmRhdGE7ZWxzZSByZXQ9c3RhdGUuYnVmZmVyLmNvbmNhdChzdGF0ZS5sZW5ndGgpO3N0YXRlLmJ1ZmZlci5jbGVhcigpfWVsc2V7cmV0PWZyb21MaXN0UGFydGlhbChuLHN0YXRlLmJ1ZmZlcixzdGF0ZS5kZWNvZGVyKX1yZXR1cm4gcmV0fWZ1bmN0aW9uIGZyb21MaXN0UGFydGlhbChuLGxpc3QsaGFzU3RyaW5ncyl7dmFyIHJldDtpZihuPGxpc3QuaGVhZC5kYXRhLmxlbmd0aCl7cmV0PWxpc3QuaGVhZC5kYXRhLnNsaWNlKDAsbik7bGlzdC5oZWFkLmRhdGE9bGlzdC5oZWFkLmRhdGEuc2xpY2Uobil9ZWxzZSBpZihuPT09bGlzdC5oZWFkLmRhdGEubGVuZ3RoKXtyZXQ9bGlzdC5zaGlmdCgpfWVsc2V7cmV0PWhhc1N0cmluZ3M/Y29weUZyb21CdWZmZXJTdHJpbmcobixsaXN0KTpjb3B5RnJvbUJ1ZmZlcihuLGxpc3QpfXJldHVybiByZXR9ZnVuY3Rpb24gY29weUZyb21CdWZmZXJTdHJpbmcobixsaXN0KXt2YXIgcD1saXN0LmhlYWQ7dmFyIGM9MTt2YXIgcmV0PXAuZGF0YTtuLT1yZXQubGVuZ3RoO3doaWxlKHA9cC5uZXh0KXt2YXIgc3RyPXAuZGF0YTt2YXIgbmI9bj5zdHIubGVuZ3RoP3N0ci5sZW5ndGg6bjtpZihuYj09PXN0ci5sZW5ndGgpcmV0Kz1zdHI7ZWxzZSByZXQrPXN0ci5zbGljZSgwLG4pO24tPW5iO2lmKG49PT0wKXtpZihuYj09PXN0ci5sZW5ndGgpeysrYztpZihwLm5leHQpbGlzdC5oZWFkPXAubmV4dDtlbHNlIGxpc3QuaGVhZD1saXN0LnRhaWw9bnVsbH1lbHNle2xpc3QuaGVhZD1wO3AuZGF0YT1zdHIuc2xpY2UobmIpfWJyZWFrfSsrY31saXN0Lmxlbmd0aC09YztyZXR1cm4gcmV0fWZ1bmN0aW9uIGNvcHlGcm9tQnVmZmVyKG4sbGlzdCl7dmFyIHJldD1idWZmZXJTaGltLmFsbG9jVW5zYWZlKG4pO3ZhciBwPWxpc3QuaGVhZDt2YXIgYz0xO3AuZGF0YS5jb3B5KHJldCk7bi09cC5kYXRhLmxlbmd0aDt3aGlsZShwPXAubmV4dCl7dmFyIGJ1Zj1wLmRhdGE7dmFyIG5iPW4+YnVmLmxlbmd0aD9idWYubGVuZ3RoOm47YnVmLmNvcHkocmV0LHJldC5sZW5ndGgtbiwwLG5iKTtuLT1uYjtpZihuPT09MCl7aWYobmI9PT1idWYubGVuZ3RoKXsrK2M7aWYocC5uZXh0KWxpc3QuaGVhZD1wLm5leHQ7ZWxzZSBsaXN0LmhlYWQ9bGlzdC50YWlsPW51bGx9ZWxzZXtsaXN0LmhlYWQ9cDtwLmRhdGE9YnVmLnNsaWNlKG5iKX1icmVha30rK2N9bGlzdC5sZW5ndGgtPWM7cmV0dXJuIHJldH1mdW5jdGlvbiBlbmRSZWFkYWJsZShzdHJlYW0pe3ZhciBzdGF0ZT1zdHJlYW0uX3JlYWRhYmxlU3RhdGU7aWYoc3RhdGUubGVuZ3RoPjApdGhyb3cgbmV3IEVycm9yKCdcImVuZFJlYWRhYmxlKClcIiBjYWxsZWQgb24gbm9uLWVtcHR5IHN0cmVhbScpO2lmKCFzdGF0ZS5lbmRFbWl0dGVkKXtzdGF0ZS5lbmRlZD10cnVlO3Byb2Nlc3NOZXh0VGljayhlbmRSZWFkYWJsZU5ULHN0YXRlLHN0cmVhbSl9fWZ1bmN0aW9uIGVuZFJlYWRhYmxlTlQoc3RhdGUsc3RyZWFtKXtpZighc3RhdGUuZW5kRW1pdHRlZCYmc3RhdGUubGVuZ3RoPT09MCl7c3RhdGUuZW5kRW1pdHRlZD10cnVlO3N0cmVhbS5yZWFkYWJsZT1mYWxzZTtzdHJlYW0uZW1pdChcImVuZFwiKX19ZnVuY3Rpb24gZm9yRWFjaCh4cyxmKXtmb3IodmFyIGk9MCxsPXhzLmxlbmd0aDtpPGw7aSsrKXtmKHhzW2ldLGkpfX1mdW5jdGlvbiBpbmRleE9mKHhzLHgpe2Zvcih2YXIgaT0wLGw9eHMubGVuZ3RoO2k8bDtpKyspe2lmKHhzW2ldPT09eClyZXR1cm4gaX1yZXR1cm4tMX19KS5jYWxsKHRoaXMscmVxdWlyZShcIl9wcm9jZXNzXCIpKX0se1wiLi9fc3RyZWFtX2R1cGxleFwiOjQ0LFwiLi9pbnRlcm5hbC9zdHJlYW1zL0J1ZmZlckxpc3RcIjo0OSxfcHJvY2Vzczo0MixidWZmZXI6NSxcImJ1ZmZlci1zaGltc1wiOjQsXCJjb3JlLXV0aWwtaXNcIjo2LGV2ZW50czoyOCxpbmhlcml0czozOCxpc2FycmF5OjQwLFwicHJvY2Vzcy1uZXh0aWNrLWFyZ3NcIjo0MSxcInN0cmluZ19kZWNvZGVyL1wiOjU2LHV0aWw6M31dLDQ3OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcInVzZSBzdHJpY3RcIjttb2R1bGUuZXhwb3J0cz1UcmFuc2Zvcm07dmFyIER1cGxleD1yZXF1aXJlKFwiLi9fc3RyZWFtX2R1cGxleFwiKTt2YXIgdXRpbD1yZXF1aXJlKFwiY29yZS11dGlsLWlzXCIpO3V0aWwuaW5oZXJpdHM9cmVxdWlyZShcImluaGVyaXRzXCIpO3V0aWwuaW5oZXJpdHMoVHJhbnNmb3JtLER1cGxleCk7ZnVuY3Rpb24gVHJhbnNmb3JtU3RhdGUoc3RyZWFtKXt0aGlzLmFmdGVyVHJhbnNmb3JtPWZ1bmN0aW9uKGVyLGRhdGEpe3JldHVybiBhZnRlclRyYW5zZm9ybShzdHJlYW0sZXIsZGF0YSl9O3RoaXMubmVlZFRyYW5zZm9ybT1mYWxzZTt0aGlzLnRyYW5zZm9ybWluZz1mYWxzZTt0aGlzLndyaXRlY2I9bnVsbDt0aGlzLndyaXRlY2h1bms9bnVsbDt0aGlzLndyaXRlZW5jb2Rpbmc9bnVsbH1mdW5jdGlvbiBhZnRlclRyYW5zZm9ybShzdHJlYW0sZXIsZGF0YSl7dmFyIHRzPXN0cmVhbS5fdHJhbnNmb3JtU3RhdGU7dHMudHJhbnNmb3JtaW5nPWZhbHNlO3ZhciBjYj10cy53cml0ZWNiO2lmKCFjYilyZXR1cm4gc3RyZWFtLmVtaXQoXCJlcnJvclwiLG5ldyBFcnJvcihcIm5vIHdyaXRlY2IgaW4gVHJhbnNmb3JtIGNsYXNzXCIpKTt0cy53cml0ZWNodW5rPW51bGw7dHMud3JpdGVjYj1udWxsO2lmKGRhdGEhPT1udWxsJiZkYXRhIT09dW5kZWZpbmVkKXN0cmVhbS5wdXNoKGRhdGEpO2NiKGVyKTt2YXIgcnM9c3RyZWFtLl9yZWFkYWJsZVN0YXRlO3JzLnJlYWRpbmc9ZmFsc2U7aWYocnMubmVlZFJlYWRhYmxlfHxycy5sZW5ndGg8cnMuaGlnaFdhdGVyTWFyayl7c3RyZWFtLl9yZWFkKHJzLmhpZ2hXYXRlck1hcmspfX1mdW5jdGlvbiBUcmFuc2Zvcm0ob3B0aW9ucyl7aWYoISh0aGlzIGluc3RhbmNlb2YgVHJhbnNmb3JtKSlyZXR1cm4gbmV3IFRyYW5zZm9ybShvcHRpb25zKTtEdXBsZXguY2FsbCh0aGlzLG9wdGlvbnMpO3RoaXMuX3RyYW5zZm9ybVN0YXRlPW5ldyBUcmFuc2Zvcm1TdGF0ZSh0aGlzKTt2YXIgc3RyZWFtPXRoaXM7dGhpcy5fcmVhZGFibGVTdGF0ZS5uZWVkUmVhZGFibGU9dHJ1ZTt0aGlzLl9yZWFkYWJsZVN0YXRlLnN5bmM9ZmFsc2U7aWYob3B0aW9ucyl7aWYodHlwZW9mIG9wdGlvbnMudHJhbnNmb3JtPT09XCJmdW5jdGlvblwiKXRoaXMuX3RyYW5zZm9ybT1vcHRpb25zLnRyYW5zZm9ybTtpZih0eXBlb2Ygb3B0aW9ucy5mbHVzaD09PVwiZnVuY3Rpb25cIil0aGlzLl9mbHVzaD1vcHRpb25zLmZsdXNofXRoaXMub25jZShcInByZWZpbmlzaFwiLGZ1bmN0aW9uKCl7aWYodHlwZW9mIHRoaXMuX2ZsdXNoPT09XCJmdW5jdGlvblwiKXRoaXMuX2ZsdXNoKGZ1bmN0aW9uKGVyKXtkb25lKHN0cmVhbSxlcil9KTtlbHNlIGRvbmUoc3RyZWFtKX0pfVRyYW5zZm9ybS5wcm90b3R5cGUucHVzaD1mdW5jdGlvbihjaHVuayxlbmNvZGluZyl7dGhpcy5fdHJhbnNmb3JtU3RhdGUubmVlZFRyYW5zZm9ybT1mYWxzZTtyZXR1cm4gRHVwbGV4LnByb3RvdHlwZS5wdXNoLmNhbGwodGhpcyxjaHVuayxlbmNvZGluZyl9O1RyYW5zZm9ybS5wcm90b3R5cGUuX3RyYW5zZm9ybT1mdW5jdGlvbihjaHVuayxlbmNvZGluZyxjYil7dGhyb3cgbmV3IEVycm9yKFwiTm90IGltcGxlbWVudGVkXCIpfTtUcmFuc2Zvcm0ucHJvdG90eXBlLl93cml0ZT1mdW5jdGlvbihjaHVuayxlbmNvZGluZyxjYil7dmFyIHRzPXRoaXMuX3RyYW5zZm9ybVN0YXRlO3RzLndyaXRlY2I9Y2I7dHMud3JpdGVjaHVuaz1jaHVuazt0cy53cml0ZWVuY29kaW5nPWVuY29kaW5nO2lmKCF0cy50cmFuc2Zvcm1pbmcpe3ZhciBycz10aGlzLl9yZWFkYWJsZVN0YXRlO2lmKHRzLm5lZWRUcmFuc2Zvcm18fHJzLm5lZWRSZWFkYWJsZXx8cnMubGVuZ3RoPHJzLmhpZ2hXYXRlck1hcmspdGhpcy5fcmVhZChycy5oaWdoV2F0ZXJNYXJrKX19O1RyYW5zZm9ybS5wcm90b3R5cGUuX3JlYWQ9ZnVuY3Rpb24obil7dmFyIHRzPXRoaXMuX3RyYW5zZm9ybVN0YXRlO2lmKHRzLndyaXRlY2h1bmshPT1udWxsJiZ0cy53cml0ZWNiJiYhdHMudHJhbnNmb3JtaW5nKXt0cy50cmFuc2Zvcm1pbmc9dHJ1ZTt0aGlzLl90cmFuc2Zvcm0odHMud3JpdGVjaHVuayx0cy53cml0ZWVuY29kaW5nLHRzLmFmdGVyVHJhbnNmb3JtKX1lbHNle3RzLm5lZWRUcmFuc2Zvcm09dHJ1ZX19O2Z1bmN0aW9uIGRvbmUoc3RyZWFtLGVyKXtpZihlcilyZXR1cm4gc3RyZWFtLmVtaXQoXCJlcnJvclwiLGVyKTt2YXIgd3M9c3RyZWFtLl93cml0YWJsZVN0YXRlO3ZhciB0cz1zdHJlYW0uX3RyYW5zZm9ybVN0YXRlO2lmKHdzLmxlbmd0aCl0aHJvdyBuZXcgRXJyb3IoXCJDYWxsaW5nIHRyYW5zZm9ybSBkb25lIHdoZW4gd3MubGVuZ3RoICE9IDBcIik7aWYodHMudHJhbnNmb3JtaW5nKXRocm93IG5ldyBFcnJvcihcIkNhbGxpbmcgdHJhbnNmb3JtIGRvbmUgd2hlbiBzdGlsbCB0cmFuc2Zvcm1pbmdcIik7cmV0dXJuIHN0cmVhbS5wdXNoKG51bGwpfX0se1wiLi9fc3RyZWFtX2R1cGxleFwiOjQ0LFwiY29yZS11dGlsLWlzXCI6Nixpbmhlcml0czozOH1dLDQ4OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXsoZnVuY3Rpb24ocHJvY2Vzcyl7XCJ1c2Ugc3RyaWN0XCI7bW9kdWxlLmV4cG9ydHM9V3JpdGFibGU7dmFyIHByb2Nlc3NOZXh0VGljaz1yZXF1aXJlKFwicHJvY2Vzcy1uZXh0aWNrLWFyZ3NcIik7dmFyIGFzeW5jV3JpdGU9IXByb2Nlc3MuYnJvd3NlciYmW1widjAuMTBcIixcInYwLjkuXCJdLmluZGV4T2YocHJvY2Vzcy52ZXJzaW9uLnNsaWNlKDAsNSkpPi0xP3NldEltbWVkaWF0ZTpwcm9jZXNzTmV4dFRpY2s7V3JpdGFibGUuV3JpdGFibGVTdGF0ZT1Xcml0YWJsZVN0YXRlO3ZhciB1dGlsPXJlcXVpcmUoXCJjb3JlLXV0aWwtaXNcIik7dXRpbC5pbmhlcml0cz1yZXF1aXJlKFwiaW5oZXJpdHNcIik7dmFyIGludGVybmFsVXRpbD17ZGVwcmVjYXRlOnJlcXVpcmUoXCJ1dGlsLWRlcHJlY2F0ZVwiKX07dmFyIFN0cmVhbTsoZnVuY3Rpb24oKXt0cnl7U3RyZWFtPXJlcXVpcmUoXCJzdFwiK1wicmVhbVwiKX1jYXRjaChfKXt9ZmluYWxseXtpZighU3RyZWFtKVN0cmVhbT1yZXF1aXJlKFwiZXZlbnRzXCIpLkV2ZW50RW1pdHRlcn19KSgpO3ZhciBCdWZmZXI9cmVxdWlyZShcImJ1ZmZlclwiKS5CdWZmZXI7dmFyIGJ1ZmZlclNoaW09cmVxdWlyZShcImJ1ZmZlci1zaGltc1wiKTt1dGlsLmluaGVyaXRzKFdyaXRhYmxlLFN0cmVhbSk7ZnVuY3Rpb24gbm9wKCl7fWZ1bmN0aW9uIFdyaXRlUmVxKGNodW5rLGVuY29kaW5nLGNiKXt0aGlzLmNodW5rPWNodW5rO3RoaXMuZW5jb2Rpbmc9ZW5jb2Rpbmc7dGhpcy5jYWxsYmFjaz1jYjt0aGlzLm5leHQ9bnVsbH12YXIgRHVwbGV4O2Z1bmN0aW9uIFdyaXRhYmxlU3RhdGUob3B0aW9ucyxzdHJlYW0pe0R1cGxleD1EdXBsZXh8fHJlcXVpcmUoXCIuL19zdHJlYW1fZHVwbGV4XCIpO29wdGlvbnM9b3B0aW9uc3x8e307dGhpcy5vYmplY3RNb2RlPSEhb3B0aW9ucy5vYmplY3RNb2RlO2lmKHN0cmVhbSBpbnN0YW5jZW9mIER1cGxleCl0aGlzLm9iamVjdE1vZGU9dGhpcy5vYmplY3RNb2RlfHwhIW9wdGlvbnMud3JpdGFibGVPYmplY3RNb2RlO3ZhciBod209b3B0aW9ucy5oaWdoV2F0ZXJNYXJrO3ZhciBkZWZhdWx0SHdtPXRoaXMub2JqZWN0TW9kZT8xNjoxNioxMDI0O3RoaXMuaGlnaFdhdGVyTWFyaz1od218fGh3bT09PTA/aHdtOmRlZmF1bHRId207dGhpcy5oaWdoV2F0ZXJNYXJrPX5+dGhpcy5oaWdoV2F0ZXJNYXJrO3RoaXMubmVlZERyYWluPWZhbHNlO3RoaXMuZW5kaW5nPWZhbHNlO3RoaXMuZW5kZWQ9ZmFsc2U7dGhpcy5maW5pc2hlZD1mYWxzZTt2YXIgbm9EZWNvZGU9b3B0aW9ucy5kZWNvZGVTdHJpbmdzPT09ZmFsc2U7dGhpcy5kZWNvZGVTdHJpbmdzPSFub0RlY29kZTt0aGlzLmRlZmF1bHRFbmNvZGluZz1vcHRpb25zLmRlZmF1bHRFbmNvZGluZ3x8XCJ1dGY4XCI7dGhpcy5sZW5ndGg9MDt0aGlzLndyaXRpbmc9ZmFsc2U7dGhpcy5jb3JrZWQ9MDt0aGlzLnN5bmM9dHJ1ZTt0aGlzLmJ1ZmZlclByb2Nlc3Npbmc9ZmFsc2U7dGhpcy5vbndyaXRlPWZ1bmN0aW9uKGVyKXtvbndyaXRlKHN0cmVhbSxlcil9O3RoaXMud3JpdGVjYj1udWxsO3RoaXMud3JpdGVsZW49MDt0aGlzLmJ1ZmZlcmVkUmVxdWVzdD1udWxsO3RoaXMubGFzdEJ1ZmZlcmVkUmVxdWVzdD1udWxsO3RoaXMucGVuZGluZ2NiPTA7dGhpcy5wcmVmaW5pc2hlZD1mYWxzZTt0aGlzLmVycm9yRW1pdHRlZD1mYWxzZTt0aGlzLmJ1ZmZlcmVkUmVxdWVzdENvdW50PTA7dGhpcy5jb3JrZWRSZXF1ZXN0c0ZyZWU9bmV3IENvcmtlZFJlcXVlc3QodGhpcyl9V3JpdGFibGVTdGF0ZS5wcm90b3R5cGUuZ2V0QnVmZmVyPWZ1bmN0aW9uIHdyaXRhYmxlU3RhdGVHZXRCdWZmZXIoKXt2YXIgY3VycmVudD10aGlzLmJ1ZmZlcmVkUmVxdWVzdDt2YXIgb3V0PVtdO3doaWxlKGN1cnJlbnQpe291dC5wdXNoKGN1cnJlbnQpO2N1cnJlbnQ9Y3VycmVudC5uZXh0fXJldHVybiBvdXR9OyhmdW5jdGlvbigpe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkoV3JpdGFibGVTdGF0ZS5wcm90b3R5cGUsXCJidWZmZXJcIix7Z2V0OmludGVybmFsVXRpbC5kZXByZWNhdGUoZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5nZXRCdWZmZXIoKX0sXCJfd3JpdGFibGVTdGF0ZS5idWZmZXIgaXMgZGVwcmVjYXRlZC4gVXNlIF93cml0YWJsZVN0YXRlLmdldEJ1ZmZlciBcIitcImluc3RlYWQuXCIpfSl9Y2F0Y2goXyl7fX0pKCk7dmFyIER1cGxleDtmdW5jdGlvbiBXcml0YWJsZShvcHRpb25zKXtEdXBsZXg9RHVwbGV4fHxyZXF1aXJlKFwiLi9fc3RyZWFtX2R1cGxleFwiKTtpZighKHRoaXMgaW5zdGFuY2VvZiBXcml0YWJsZSkmJiEodGhpcyBpbnN0YW5jZW9mIER1cGxleCkpcmV0dXJuIG5ldyBXcml0YWJsZShvcHRpb25zKTt0aGlzLl93cml0YWJsZVN0YXRlPW5ldyBXcml0YWJsZVN0YXRlKG9wdGlvbnMsdGhpcyk7dGhpcy53cml0YWJsZT10cnVlO2lmKG9wdGlvbnMpe2lmKHR5cGVvZiBvcHRpb25zLndyaXRlPT09XCJmdW5jdGlvblwiKXRoaXMuX3dyaXRlPW9wdGlvbnMud3JpdGU7aWYodHlwZW9mIG9wdGlvbnMud3JpdGV2PT09XCJmdW5jdGlvblwiKXRoaXMuX3dyaXRldj1vcHRpb25zLndyaXRldn1TdHJlYW0uY2FsbCh0aGlzKX1Xcml0YWJsZS5wcm90b3R5cGUucGlwZT1mdW5jdGlvbigpe3RoaXMuZW1pdChcImVycm9yXCIsbmV3IEVycm9yKFwiQ2Fubm90IHBpcGUsIG5vdCByZWFkYWJsZVwiKSl9O2Z1bmN0aW9uIHdyaXRlQWZ0ZXJFbmQoc3RyZWFtLGNiKXt2YXIgZXI9bmV3IEVycm9yKFwid3JpdGUgYWZ0ZXIgZW5kXCIpO3N0cmVhbS5lbWl0KFwiZXJyb3JcIixlcik7cHJvY2Vzc05leHRUaWNrKGNiLGVyKX1mdW5jdGlvbiB2YWxpZENodW5rKHN0cmVhbSxzdGF0ZSxjaHVuayxjYil7dmFyIHZhbGlkPXRydWU7dmFyIGVyPWZhbHNlO2lmKGNodW5rPT09bnVsbCl7ZXI9bmV3IFR5cGVFcnJvcihcIk1heSBub3Qgd3JpdGUgbnVsbCB2YWx1ZXMgdG8gc3RyZWFtXCIpfWVsc2UgaWYoIUJ1ZmZlci5pc0J1ZmZlcihjaHVuaykmJnR5cGVvZiBjaHVuayE9PVwic3RyaW5nXCImJmNodW5rIT09dW5kZWZpbmVkJiYhc3RhdGUub2JqZWN0TW9kZSl7ZXI9bmV3IFR5cGVFcnJvcihcIkludmFsaWQgbm9uLXN0cmluZy9idWZmZXIgY2h1bmtcIil9aWYoZXIpe3N0cmVhbS5lbWl0KFwiZXJyb3JcIixlcik7cHJvY2Vzc05leHRUaWNrKGNiLGVyKTt2YWxpZD1mYWxzZX1yZXR1cm4gdmFsaWR9V3JpdGFibGUucHJvdG90eXBlLndyaXRlPWZ1bmN0aW9uKGNodW5rLGVuY29kaW5nLGNiKXt2YXIgc3RhdGU9dGhpcy5fd3JpdGFibGVTdGF0ZTt2YXIgcmV0PWZhbHNlO2lmKHR5cGVvZiBlbmNvZGluZz09PVwiZnVuY3Rpb25cIil7Y2I9ZW5jb2Rpbmc7ZW5jb2Rpbmc9bnVsbH1pZihCdWZmZXIuaXNCdWZmZXIoY2h1bmspKWVuY29kaW5nPVwiYnVmZmVyXCI7ZWxzZSBpZighZW5jb2RpbmcpZW5jb2Rpbmc9c3RhdGUuZGVmYXVsdEVuY29kaW5nO2lmKHR5cGVvZiBjYiE9PVwiZnVuY3Rpb25cIiljYj1ub3A7aWYoc3RhdGUuZW5kZWQpd3JpdGVBZnRlckVuZCh0aGlzLGNiKTtlbHNlIGlmKHZhbGlkQ2h1bmsodGhpcyxzdGF0ZSxjaHVuayxjYikpe1xuc3RhdGUucGVuZGluZ2NiKys7cmV0PXdyaXRlT3JCdWZmZXIodGhpcyxzdGF0ZSxjaHVuayxlbmNvZGluZyxjYil9cmV0dXJuIHJldH07V3JpdGFibGUucHJvdG90eXBlLmNvcms9ZnVuY3Rpb24oKXt2YXIgc3RhdGU9dGhpcy5fd3JpdGFibGVTdGF0ZTtzdGF0ZS5jb3JrZWQrK307V3JpdGFibGUucHJvdG90eXBlLnVuY29yaz1mdW5jdGlvbigpe3ZhciBzdGF0ZT10aGlzLl93cml0YWJsZVN0YXRlO2lmKHN0YXRlLmNvcmtlZCl7c3RhdGUuY29ya2VkLS07aWYoIXN0YXRlLndyaXRpbmcmJiFzdGF0ZS5jb3JrZWQmJiFzdGF0ZS5maW5pc2hlZCYmIXN0YXRlLmJ1ZmZlclByb2Nlc3NpbmcmJnN0YXRlLmJ1ZmZlcmVkUmVxdWVzdCljbGVhckJ1ZmZlcih0aGlzLHN0YXRlKX19O1dyaXRhYmxlLnByb3RvdHlwZS5zZXREZWZhdWx0RW5jb2Rpbmc9ZnVuY3Rpb24gc2V0RGVmYXVsdEVuY29kaW5nKGVuY29kaW5nKXtpZih0eXBlb2YgZW5jb2Rpbmc9PT1cInN0cmluZ1wiKWVuY29kaW5nPWVuY29kaW5nLnRvTG93ZXJDYXNlKCk7aWYoIShbXCJoZXhcIixcInV0ZjhcIixcInV0Zi04XCIsXCJhc2NpaVwiLFwiYmluYXJ5XCIsXCJiYXNlNjRcIixcInVjczJcIixcInVjcy0yXCIsXCJ1dGYxNmxlXCIsXCJ1dGYtMTZsZVwiLFwicmF3XCJdLmluZGV4T2YoKGVuY29kaW5nK1wiXCIpLnRvTG93ZXJDYXNlKCkpPi0xKSl0aHJvdyBuZXcgVHlwZUVycm9yKFwiVW5rbm93biBlbmNvZGluZzogXCIrZW5jb2RpbmcpO3RoaXMuX3dyaXRhYmxlU3RhdGUuZGVmYXVsdEVuY29kaW5nPWVuY29kaW5nO3JldHVybiB0aGlzfTtmdW5jdGlvbiBkZWNvZGVDaHVuayhzdGF0ZSxjaHVuayxlbmNvZGluZyl7aWYoIXN0YXRlLm9iamVjdE1vZGUmJnN0YXRlLmRlY29kZVN0cmluZ3MhPT1mYWxzZSYmdHlwZW9mIGNodW5rPT09XCJzdHJpbmdcIil7Y2h1bms9YnVmZmVyU2hpbS5mcm9tKGNodW5rLGVuY29kaW5nKX1yZXR1cm4gY2h1bmt9ZnVuY3Rpb24gd3JpdGVPckJ1ZmZlcihzdHJlYW0sc3RhdGUsY2h1bmssZW5jb2RpbmcsY2Ipe2NodW5rPWRlY29kZUNodW5rKHN0YXRlLGNodW5rLGVuY29kaW5nKTtpZihCdWZmZXIuaXNCdWZmZXIoY2h1bmspKWVuY29kaW5nPVwiYnVmZmVyXCI7dmFyIGxlbj1zdGF0ZS5vYmplY3RNb2RlPzE6Y2h1bmsubGVuZ3RoO3N0YXRlLmxlbmd0aCs9bGVuO3ZhciByZXQ9c3RhdGUubGVuZ3RoPHN0YXRlLmhpZ2hXYXRlck1hcms7aWYoIXJldClzdGF0ZS5uZWVkRHJhaW49dHJ1ZTtpZihzdGF0ZS53cml0aW5nfHxzdGF0ZS5jb3JrZWQpe3ZhciBsYXN0PXN0YXRlLmxhc3RCdWZmZXJlZFJlcXVlc3Q7c3RhdGUubGFzdEJ1ZmZlcmVkUmVxdWVzdD1uZXcgV3JpdGVSZXEoY2h1bmssZW5jb2RpbmcsY2IpO2lmKGxhc3Qpe2xhc3QubmV4dD1zdGF0ZS5sYXN0QnVmZmVyZWRSZXF1ZXN0fWVsc2V7c3RhdGUuYnVmZmVyZWRSZXF1ZXN0PXN0YXRlLmxhc3RCdWZmZXJlZFJlcXVlc3R9c3RhdGUuYnVmZmVyZWRSZXF1ZXN0Q291bnQrPTF9ZWxzZXtkb1dyaXRlKHN0cmVhbSxzdGF0ZSxmYWxzZSxsZW4sY2h1bmssZW5jb2RpbmcsY2IpfXJldHVybiByZXR9ZnVuY3Rpb24gZG9Xcml0ZShzdHJlYW0sc3RhdGUsd3JpdGV2LGxlbixjaHVuayxlbmNvZGluZyxjYil7c3RhdGUud3JpdGVsZW49bGVuO3N0YXRlLndyaXRlY2I9Y2I7c3RhdGUud3JpdGluZz10cnVlO3N0YXRlLnN5bmM9dHJ1ZTtpZih3cml0ZXYpc3RyZWFtLl93cml0ZXYoY2h1bmssc3RhdGUub253cml0ZSk7ZWxzZSBzdHJlYW0uX3dyaXRlKGNodW5rLGVuY29kaW5nLHN0YXRlLm9ud3JpdGUpO3N0YXRlLnN5bmM9ZmFsc2V9ZnVuY3Rpb24gb253cml0ZUVycm9yKHN0cmVhbSxzdGF0ZSxzeW5jLGVyLGNiKXstLXN0YXRlLnBlbmRpbmdjYjtpZihzeW5jKXByb2Nlc3NOZXh0VGljayhjYixlcik7ZWxzZSBjYihlcik7c3RyZWFtLl93cml0YWJsZVN0YXRlLmVycm9yRW1pdHRlZD10cnVlO3N0cmVhbS5lbWl0KFwiZXJyb3JcIixlcil9ZnVuY3Rpb24gb253cml0ZVN0YXRlVXBkYXRlKHN0YXRlKXtzdGF0ZS53cml0aW5nPWZhbHNlO3N0YXRlLndyaXRlY2I9bnVsbDtzdGF0ZS5sZW5ndGgtPXN0YXRlLndyaXRlbGVuO3N0YXRlLndyaXRlbGVuPTB9ZnVuY3Rpb24gb253cml0ZShzdHJlYW0sZXIpe3ZhciBzdGF0ZT1zdHJlYW0uX3dyaXRhYmxlU3RhdGU7dmFyIHN5bmM9c3RhdGUuc3luYzt2YXIgY2I9c3RhdGUud3JpdGVjYjtvbndyaXRlU3RhdGVVcGRhdGUoc3RhdGUpO2lmKGVyKW9ud3JpdGVFcnJvcihzdHJlYW0sc3RhdGUsc3luYyxlcixjYik7ZWxzZXt2YXIgZmluaXNoZWQ9bmVlZEZpbmlzaChzdGF0ZSk7aWYoIWZpbmlzaGVkJiYhc3RhdGUuY29ya2VkJiYhc3RhdGUuYnVmZmVyUHJvY2Vzc2luZyYmc3RhdGUuYnVmZmVyZWRSZXF1ZXN0KXtjbGVhckJ1ZmZlcihzdHJlYW0sc3RhdGUpfWlmKHN5bmMpe2FzeW5jV3JpdGUoYWZ0ZXJXcml0ZSxzdHJlYW0sc3RhdGUsZmluaXNoZWQsY2IpfWVsc2V7YWZ0ZXJXcml0ZShzdHJlYW0sc3RhdGUsZmluaXNoZWQsY2IpfX19ZnVuY3Rpb24gYWZ0ZXJXcml0ZShzdHJlYW0sc3RhdGUsZmluaXNoZWQsY2Ipe2lmKCFmaW5pc2hlZClvbndyaXRlRHJhaW4oc3RyZWFtLHN0YXRlKTtzdGF0ZS5wZW5kaW5nY2ItLTtjYigpO2ZpbmlzaE1heWJlKHN0cmVhbSxzdGF0ZSl9ZnVuY3Rpb24gb253cml0ZURyYWluKHN0cmVhbSxzdGF0ZSl7aWYoc3RhdGUubGVuZ3RoPT09MCYmc3RhdGUubmVlZERyYWluKXtzdGF0ZS5uZWVkRHJhaW49ZmFsc2U7c3RyZWFtLmVtaXQoXCJkcmFpblwiKX19ZnVuY3Rpb24gY2xlYXJCdWZmZXIoc3RyZWFtLHN0YXRlKXtzdGF0ZS5idWZmZXJQcm9jZXNzaW5nPXRydWU7dmFyIGVudHJ5PXN0YXRlLmJ1ZmZlcmVkUmVxdWVzdDtpZihzdHJlYW0uX3dyaXRldiYmZW50cnkmJmVudHJ5Lm5leHQpe3ZhciBsPXN0YXRlLmJ1ZmZlcmVkUmVxdWVzdENvdW50O3ZhciBidWZmZXI9bmV3IEFycmF5KGwpO3ZhciBob2xkZXI9c3RhdGUuY29ya2VkUmVxdWVzdHNGcmVlO2hvbGRlci5lbnRyeT1lbnRyeTt2YXIgY291bnQ9MDt3aGlsZShlbnRyeSl7YnVmZmVyW2NvdW50XT1lbnRyeTtlbnRyeT1lbnRyeS5uZXh0O2NvdW50Kz0xfWRvV3JpdGUoc3RyZWFtLHN0YXRlLHRydWUsc3RhdGUubGVuZ3RoLGJ1ZmZlcixcIlwiLGhvbGRlci5maW5pc2gpO3N0YXRlLnBlbmRpbmdjYisrO3N0YXRlLmxhc3RCdWZmZXJlZFJlcXVlc3Q9bnVsbDtpZihob2xkZXIubmV4dCl7c3RhdGUuY29ya2VkUmVxdWVzdHNGcmVlPWhvbGRlci5uZXh0O2hvbGRlci5uZXh0PW51bGx9ZWxzZXtzdGF0ZS5jb3JrZWRSZXF1ZXN0c0ZyZWU9bmV3IENvcmtlZFJlcXVlc3Qoc3RhdGUpfX1lbHNle3doaWxlKGVudHJ5KXt2YXIgY2h1bms9ZW50cnkuY2h1bms7dmFyIGVuY29kaW5nPWVudHJ5LmVuY29kaW5nO3ZhciBjYj1lbnRyeS5jYWxsYmFjazt2YXIgbGVuPXN0YXRlLm9iamVjdE1vZGU/MTpjaHVuay5sZW5ndGg7ZG9Xcml0ZShzdHJlYW0sc3RhdGUsZmFsc2UsbGVuLGNodW5rLGVuY29kaW5nLGNiKTtlbnRyeT1lbnRyeS5uZXh0O2lmKHN0YXRlLndyaXRpbmcpe2JyZWFrfX1pZihlbnRyeT09PW51bGwpc3RhdGUubGFzdEJ1ZmZlcmVkUmVxdWVzdD1udWxsfXN0YXRlLmJ1ZmZlcmVkUmVxdWVzdENvdW50PTA7c3RhdGUuYnVmZmVyZWRSZXF1ZXN0PWVudHJ5O3N0YXRlLmJ1ZmZlclByb2Nlc3Npbmc9ZmFsc2V9V3JpdGFibGUucHJvdG90eXBlLl93cml0ZT1mdW5jdGlvbihjaHVuayxlbmNvZGluZyxjYil7Y2IobmV3IEVycm9yKFwibm90IGltcGxlbWVudGVkXCIpKX07V3JpdGFibGUucHJvdG90eXBlLl93cml0ZXY9bnVsbDtXcml0YWJsZS5wcm90b3R5cGUuZW5kPWZ1bmN0aW9uKGNodW5rLGVuY29kaW5nLGNiKXt2YXIgc3RhdGU9dGhpcy5fd3JpdGFibGVTdGF0ZTtpZih0eXBlb2YgY2h1bms9PT1cImZ1bmN0aW9uXCIpe2NiPWNodW5rO2NodW5rPW51bGw7ZW5jb2Rpbmc9bnVsbH1lbHNlIGlmKHR5cGVvZiBlbmNvZGluZz09PVwiZnVuY3Rpb25cIil7Y2I9ZW5jb2Rpbmc7ZW5jb2Rpbmc9bnVsbH1pZihjaHVuayE9PW51bGwmJmNodW5rIT09dW5kZWZpbmVkKXRoaXMud3JpdGUoY2h1bmssZW5jb2RpbmcpO2lmKHN0YXRlLmNvcmtlZCl7c3RhdGUuY29ya2VkPTE7dGhpcy51bmNvcmsoKX1pZighc3RhdGUuZW5kaW5nJiYhc3RhdGUuZmluaXNoZWQpZW5kV3JpdGFibGUodGhpcyxzdGF0ZSxjYil9O2Z1bmN0aW9uIG5lZWRGaW5pc2goc3RhdGUpe3JldHVybiBzdGF0ZS5lbmRpbmcmJnN0YXRlLmxlbmd0aD09PTAmJnN0YXRlLmJ1ZmZlcmVkUmVxdWVzdD09PW51bGwmJiFzdGF0ZS5maW5pc2hlZCYmIXN0YXRlLndyaXRpbmd9ZnVuY3Rpb24gcHJlZmluaXNoKHN0cmVhbSxzdGF0ZSl7aWYoIXN0YXRlLnByZWZpbmlzaGVkKXtzdGF0ZS5wcmVmaW5pc2hlZD10cnVlO3N0cmVhbS5lbWl0KFwicHJlZmluaXNoXCIpfX1mdW5jdGlvbiBmaW5pc2hNYXliZShzdHJlYW0sc3RhdGUpe3ZhciBuZWVkPW5lZWRGaW5pc2goc3RhdGUpO2lmKG5lZWQpe2lmKHN0YXRlLnBlbmRpbmdjYj09PTApe3ByZWZpbmlzaChzdHJlYW0sc3RhdGUpO3N0YXRlLmZpbmlzaGVkPXRydWU7c3RyZWFtLmVtaXQoXCJmaW5pc2hcIil9ZWxzZXtwcmVmaW5pc2goc3RyZWFtLHN0YXRlKX19cmV0dXJuIG5lZWR9ZnVuY3Rpb24gZW5kV3JpdGFibGUoc3RyZWFtLHN0YXRlLGNiKXtzdGF0ZS5lbmRpbmc9dHJ1ZTtmaW5pc2hNYXliZShzdHJlYW0sc3RhdGUpO2lmKGNiKXtpZihzdGF0ZS5maW5pc2hlZClwcm9jZXNzTmV4dFRpY2soY2IpO2Vsc2Ugc3RyZWFtLm9uY2UoXCJmaW5pc2hcIixjYil9c3RhdGUuZW5kZWQ9dHJ1ZTtzdHJlYW0ud3JpdGFibGU9ZmFsc2V9ZnVuY3Rpb24gQ29ya2VkUmVxdWVzdChzdGF0ZSl7dmFyIF90aGlzPXRoaXM7dGhpcy5uZXh0PW51bGw7dGhpcy5lbnRyeT1udWxsO3RoaXMuZmluaXNoPWZ1bmN0aW9uKGVycil7dmFyIGVudHJ5PV90aGlzLmVudHJ5O190aGlzLmVudHJ5PW51bGw7d2hpbGUoZW50cnkpe3ZhciBjYj1lbnRyeS5jYWxsYmFjaztzdGF0ZS5wZW5kaW5nY2ItLTtjYihlcnIpO2VudHJ5PWVudHJ5Lm5leHR9aWYoc3RhdGUuY29ya2VkUmVxdWVzdHNGcmVlKXtzdGF0ZS5jb3JrZWRSZXF1ZXN0c0ZyZWUubmV4dD1fdGhpc31lbHNle3N0YXRlLmNvcmtlZFJlcXVlc3RzRnJlZT1fdGhpc319fX0pLmNhbGwodGhpcyxyZXF1aXJlKFwiX3Byb2Nlc3NcIikpfSx7XCIuL19zdHJlYW1fZHVwbGV4XCI6NDQsX3Byb2Nlc3M6NDIsYnVmZmVyOjUsXCJidWZmZXItc2hpbXNcIjo0LFwiY29yZS11dGlsLWlzXCI6NixldmVudHM6MjgsaW5oZXJpdHM6MzgsXCJwcm9jZXNzLW5leHRpY2stYXJnc1wiOjQxLFwidXRpbC1kZXByZWNhdGVcIjo1N31dLDQ5OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXtcInVzZSBzdHJpY3RcIjt2YXIgQnVmZmVyPXJlcXVpcmUoXCJidWZmZXJcIikuQnVmZmVyO3ZhciBidWZmZXJTaGltPXJlcXVpcmUoXCJidWZmZXItc2hpbXNcIik7bW9kdWxlLmV4cG9ydHM9QnVmZmVyTGlzdDtmdW5jdGlvbiBCdWZmZXJMaXN0KCl7dGhpcy5oZWFkPW51bGw7dGhpcy50YWlsPW51bGw7dGhpcy5sZW5ndGg9MH1CdWZmZXJMaXN0LnByb3RvdHlwZS5wdXNoPWZ1bmN0aW9uKHYpe3ZhciBlbnRyeT17ZGF0YTp2LG5leHQ6bnVsbH07aWYodGhpcy5sZW5ndGg+MCl0aGlzLnRhaWwubmV4dD1lbnRyeTtlbHNlIHRoaXMuaGVhZD1lbnRyeTt0aGlzLnRhaWw9ZW50cnk7Kyt0aGlzLmxlbmd0aH07QnVmZmVyTGlzdC5wcm90b3R5cGUudW5zaGlmdD1mdW5jdGlvbih2KXt2YXIgZW50cnk9e2RhdGE6dixuZXh0OnRoaXMuaGVhZH07aWYodGhpcy5sZW5ndGg9PT0wKXRoaXMudGFpbD1lbnRyeTt0aGlzLmhlYWQ9ZW50cnk7Kyt0aGlzLmxlbmd0aH07QnVmZmVyTGlzdC5wcm90b3R5cGUuc2hpZnQ9ZnVuY3Rpb24oKXtpZih0aGlzLmxlbmd0aD09PTApcmV0dXJuO3ZhciByZXQ9dGhpcy5oZWFkLmRhdGE7aWYodGhpcy5sZW5ndGg9PT0xKXRoaXMuaGVhZD10aGlzLnRhaWw9bnVsbDtlbHNlIHRoaXMuaGVhZD10aGlzLmhlYWQubmV4dDstLXRoaXMubGVuZ3RoO3JldHVybiByZXR9O0J1ZmZlckxpc3QucHJvdG90eXBlLmNsZWFyPWZ1bmN0aW9uKCl7dGhpcy5oZWFkPXRoaXMudGFpbD1udWxsO3RoaXMubGVuZ3RoPTB9O0J1ZmZlckxpc3QucHJvdG90eXBlLmpvaW49ZnVuY3Rpb24ocyl7aWYodGhpcy5sZW5ndGg9PT0wKXJldHVyblwiXCI7dmFyIHA9dGhpcy5oZWFkO3ZhciByZXQ9XCJcIitwLmRhdGE7d2hpbGUocD1wLm5leHQpe3JldCs9cytwLmRhdGF9cmV0dXJuIHJldH07QnVmZmVyTGlzdC5wcm90b3R5cGUuY29uY2F0PWZ1bmN0aW9uKG4pe2lmKHRoaXMubGVuZ3RoPT09MClyZXR1cm4gYnVmZmVyU2hpbS5hbGxvYygwKTtpZih0aGlzLmxlbmd0aD09PTEpcmV0dXJuIHRoaXMuaGVhZC5kYXRhO3ZhciByZXQ9YnVmZmVyU2hpbS5hbGxvY1Vuc2FmZShuPj4+MCk7dmFyIHA9dGhpcy5oZWFkO3ZhciBpPTA7d2hpbGUocCl7cC5kYXRhLmNvcHkocmV0LGkpO2krPXAuZGF0YS5sZW5ndGg7cD1wLm5leHR9cmV0dXJuIHJldH19LHtidWZmZXI6NSxcImJ1ZmZlci1zaGltc1wiOjR9XSw1MDpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7bW9kdWxlLmV4cG9ydHM9cmVxdWlyZShcIi4vbGliL19zdHJlYW1fcGFzc3Rocm91Z2guanNcIil9LHtcIi4vbGliL19zdHJlYW1fcGFzc3Rocm91Z2guanNcIjo0NX1dLDUxOltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXsoZnVuY3Rpb24ocHJvY2Vzcyl7dmFyIFN0cmVhbT1mdW5jdGlvbigpe3RyeXtyZXR1cm4gcmVxdWlyZShcInN0XCIrXCJyZWFtXCIpfWNhdGNoKF8pe319KCk7ZXhwb3J0cz1tb2R1bGUuZXhwb3J0cz1yZXF1aXJlKFwiLi9saWIvX3N0cmVhbV9yZWFkYWJsZS5qc1wiKTtleHBvcnRzLlN0cmVhbT1TdHJlYW18fGV4cG9ydHM7ZXhwb3J0cy5SZWFkYWJsZT1leHBvcnRzO2V4cG9ydHMuV3JpdGFibGU9cmVxdWlyZShcIi4vbGliL19zdHJlYW1fd3JpdGFibGUuanNcIik7ZXhwb3J0cy5EdXBsZXg9cmVxdWlyZShcIi4vbGliL19zdHJlYW1fZHVwbGV4LmpzXCIpO2V4cG9ydHMuVHJhbnNmb3JtPXJlcXVpcmUoXCIuL2xpYi9fc3RyZWFtX3RyYW5zZm9ybS5qc1wiKTtleHBvcnRzLlBhc3NUaHJvdWdoPXJlcXVpcmUoXCIuL2xpYi9fc3RyZWFtX3Bhc3N0aHJvdWdoLmpzXCIpO2lmKCFwcm9jZXNzLmJyb3dzZXImJnByb2Nlc3MuZW52LlJFQURBQkxFX1NUUkVBTT09PVwiZGlzYWJsZVwiJiZTdHJlYW0pe21vZHVsZS5leHBvcnRzPVN0cmVhbX19KS5jYWxsKHRoaXMscmVxdWlyZShcIl9wcm9jZXNzXCIpKX0se1wiLi9saWIvX3N0cmVhbV9kdXBsZXguanNcIjo0NCxcIi4vbGliL19zdHJlYW1fcGFzc3Rocm91Z2guanNcIjo0NSxcIi4vbGliL19zdHJlYW1fcmVhZGFibGUuanNcIjo0NixcIi4vbGliL19zdHJlYW1fdHJhbnNmb3JtLmpzXCI6NDcsXCIuL2xpYi9fc3RyZWFtX3dyaXRhYmxlLmpzXCI6NDgsX3Byb2Nlc3M6NDJ9XSw1MjpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7bW9kdWxlLmV4cG9ydHM9cmVxdWlyZShcIi4vbGliL19zdHJlYW1fdHJhbnNmb3JtLmpzXCIpfSx7XCIuL2xpYi9fc3RyZWFtX3RyYW5zZm9ybS5qc1wiOjQ3fV0sNTM6W2Z1bmN0aW9uKHJlcXVpcmUsbW9kdWxlLGV4cG9ydHMpe21vZHVsZS5leHBvcnRzPXJlcXVpcmUoXCIuL2xpYi9fc3RyZWFtX3dyaXRhYmxlLmpzXCIpfSx7XCIuL2xpYi9fc3RyZWFtX3dyaXRhYmxlLmpzXCI6NDh9XSw1NDpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7bW9kdWxlLmV4cG9ydHM9ZnVuY3Rpb24oc3RyaW5nKXtyZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1stXFxcXF4kKis/LigpfFtcXF17fV0vZyxcIlxcXFwkJlwiKX19LHt9XSw1NTpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7bW9kdWxlLmV4cG9ydHM9U3RyZWFtO3ZhciBFRT1yZXF1aXJlKFwiZXZlbnRzXCIpLkV2ZW50RW1pdHRlcjt2YXIgaW5oZXJpdHM9cmVxdWlyZShcImluaGVyaXRzXCIpO2luaGVyaXRzKFN0cmVhbSxFRSk7U3RyZWFtLlJlYWRhYmxlPXJlcXVpcmUoXCJyZWFkYWJsZS1zdHJlYW0vcmVhZGFibGUuanNcIik7U3RyZWFtLldyaXRhYmxlPXJlcXVpcmUoXCJyZWFkYWJsZS1zdHJlYW0vd3JpdGFibGUuanNcIik7U3RyZWFtLkR1cGxleD1yZXF1aXJlKFwicmVhZGFibGUtc3RyZWFtL2R1cGxleC5qc1wiKTtTdHJlYW0uVHJhbnNmb3JtPXJlcXVpcmUoXCJyZWFkYWJsZS1zdHJlYW0vdHJhbnNmb3JtLmpzXCIpO1N0cmVhbS5QYXNzVGhyb3VnaD1yZXF1aXJlKFwicmVhZGFibGUtc3RyZWFtL3Bhc3N0aHJvdWdoLmpzXCIpO1N0cmVhbS5TdHJlYW09U3RyZWFtO2Z1bmN0aW9uIFN0cmVhbSgpe0VFLmNhbGwodGhpcyl9U3RyZWFtLnByb3RvdHlwZS5waXBlPWZ1bmN0aW9uKGRlc3Qsb3B0aW9ucyl7dmFyIHNvdXJjZT10aGlzO2Z1bmN0aW9uIG9uZGF0YShjaHVuayl7aWYoZGVzdC53cml0YWJsZSl7aWYoZmFsc2U9PT1kZXN0LndyaXRlKGNodW5rKSYmc291cmNlLnBhdXNlKXtzb3VyY2UucGF1c2UoKX19fXNvdXJjZS5vbihcImRhdGFcIixvbmRhdGEpO2Z1bmN0aW9uIG9uZHJhaW4oKXtpZihzb3VyY2UucmVhZGFibGUmJnNvdXJjZS5yZXN1bWUpe3NvdXJjZS5yZXN1bWUoKX19ZGVzdC5vbihcImRyYWluXCIsb25kcmFpbik7aWYoIWRlc3QuX2lzU3RkaW8mJighb3B0aW9uc3x8b3B0aW9ucy5lbmQhPT1mYWxzZSkpe3NvdXJjZS5vbihcImVuZFwiLG9uZW5kKTtzb3VyY2Uub24oXCJjbG9zZVwiLG9uY2xvc2UpfXZhciBkaWRPbkVuZD1mYWxzZTtmdW5jdGlvbiBvbmVuZCgpe2lmKGRpZE9uRW5kKXJldHVybjtkaWRPbkVuZD10cnVlO2Rlc3QuZW5kKCl9ZnVuY3Rpb24gb25jbG9zZSgpe2lmKGRpZE9uRW5kKXJldHVybjtkaWRPbkVuZD10cnVlO2lmKHR5cGVvZiBkZXN0LmRlc3Ryb3k9PT1cImZ1bmN0aW9uXCIpZGVzdC5kZXN0cm95KCl9ZnVuY3Rpb24gb25lcnJvcihlcil7Y2xlYW51cCgpO2lmKEVFLmxpc3RlbmVyQ291bnQodGhpcyxcImVycm9yXCIpPT09MCl7dGhyb3cgZXJ9fXNvdXJjZS5vbihcImVycm9yXCIsb25lcnJvcik7ZGVzdC5vbihcImVycm9yXCIsb25lcnJvcik7ZnVuY3Rpb24gY2xlYW51cCgpe3NvdXJjZS5yZW1vdmVMaXN0ZW5lcihcImRhdGFcIixvbmRhdGEpO2Rlc3QucmVtb3ZlTGlzdGVuZXIoXCJkcmFpblwiLG9uZHJhaW4pO3NvdXJjZS5yZW1vdmVMaXN0ZW5lcihcImVuZFwiLG9uZW5kKTtzb3VyY2UucmVtb3ZlTGlzdGVuZXIoXCJjbG9zZVwiLG9uY2xvc2UpO3NvdXJjZS5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsb25lcnJvcik7ZGVzdC5yZW1vdmVMaXN0ZW5lcihcImVycm9yXCIsb25lcnJvcik7c291cmNlLnJlbW92ZUxpc3RlbmVyKFwiZW5kXCIsY2xlYW51cCk7c291cmNlLnJlbW92ZUxpc3RlbmVyKFwiY2xvc2VcIixjbGVhbnVwKTtkZXN0LnJlbW92ZUxpc3RlbmVyKFwiY2xvc2VcIixjbGVhbnVwKX1zb3VyY2Uub24oXCJlbmRcIixjbGVhbnVwKTtzb3VyY2Uub24oXCJjbG9zZVwiLGNsZWFudXApO2Rlc3Qub24oXCJjbG9zZVwiLGNsZWFudXApO2Rlc3QuZW1pdChcInBpcGVcIixzb3VyY2UpO3JldHVybiBkZXN0fX0se2V2ZW50czoyOCxpbmhlcml0czozOCxcInJlYWRhYmxlLXN0cmVhbS9kdXBsZXguanNcIjo0MyxcInJlYWRhYmxlLXN0cmVhbS9wYXNzdGhyb3VnaC5qc1wiOjUwLFwicmVhZGFibGUtc3RyZWFtL3JlYWRhYmxlLmpzXCI6NTEsXCJyZWFkYWJsZS1zdHJlYW0vdHJhbnNmb3JtLmpzXCI6NTIsXCJyZWFkYWJsZS1zdHJlYW0vd3JpdGFibGUuanNcIjo1M31dLDU2OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXt2YXIgQnVmZmVyPXJlcXVpcmUoXCJidWZmZXJcIikuQnVmZmVyO3ZhciBpc0J1ZmZlckVuY29kaW5nPUJ1ZmZlci5pc0VuY29kaW5nfHxmdW5jdGlvbihlbmNvZGluZyl7c3dpdGNoKGVuY29kaW5nJiZlbmNvZGluZy50b0xvd2VyQ2FzZSgpKXtjYXNlXCJoZXhcIjpjYXNlXCJ1dGY4XCI6Y2FzZVwidXRmLThcIjpjYXNlXCJhc2NpaVwiOmNhc2VcImJpbmFyeVwiOmNhc2VcImJhc2U2NFwiOmNhc2VcInVjczJcIjpjYXNlXCJ1Y3MtMlwiOmNhc2VcInV0ZjE2bGVcIjpjYXNlXCJ1dGYtMTZsZVwiOmNhc2VcInJhd1wiOnJldHVybiB0cnVlO2RlZmF1bHQ6cmV0dXJuIGZhbHNlfX07ZnVuY3Rpb24gYXNzZXJ0RW5jb2RpbmcoZW5jb2Rpbmcpe2lmKGVuY29kaW5nJiYhaXNCdWZmZXJFbmNvZGluZyhlbmNvZGluZykpe3Rocm93IG5ldyBFcnJvcihcIlVua25vd24gZW5jb2Rpbmc6IFwiK2VuY29kaW5nKX19dmFyIFN0cmluZ0RlY29kZXI9ZXhwb3J0cy5TdHJpbmdEZWNvZGVyPWZ1bmN0aW9uKGVuY29kaW5nKXt0aGlzLmVuY29kaW5nPShlbmNvZGluZ3x8XCJ1dGY4XCIpLnRvTG93ZXJDYXNlKCkucmVwbGFjZSgvWy1fXS8sXCJcIik7YXNzZXJ0RW5jb2RpbmcoZW5jb2RpbmcpO3N3aXRjaCh0aGlzLmVuY29kaW5nKXtjYXNlXCJ1dGY4XCI6dGhpcy5zdXJyb2dhdGVTaXplPTM7YnJlYWs7Y2FzZVwidWNzMlwiOmNhc2VcInV0ZjE2bGVcIjp0aGlzLnN1cnJvZ2F0ZVNpemU9Mjt0aGlzLmRldGVjdEluY29tcGxldGVDaGFyPXV0ZjE2RGV0ZWN0SW5jb21wbGV0ZUNoYXI7YnJlYWs7Y2FzZVwiYmFzZTY0XCI6dGhpcy5zdXJyb2dhdGVTaXplPTM7dGhpcy5kZXRlY3RJbmNvbXBsZXRlQ2hhcj1iYXNlNjREZXRlY3RJbmNvbXBsZXRlQ2hhcjticmVhaztkZWZhdWx0OnRoaXMud3JpdGU9cGFzc1Rocm91Z2hXcml0ZTtyZXR1cm59dGhpcy5jaGFyQnVmZmVyPW5ldyBCdWZmZXIoNik7dGhpcy5jaGFyUmVjZWl2ZWQ9MDt0aGlzLmNoYXJMZW5ndGg9MH07U3RyaW5nRGVjb2Rlci5wcm90b3R5cGUud3JpdGU9ZnVuY3Rpb24oYnVmZmVyKXt2YXIgY2hhclN0cj1cIlwiO3doaWxlKHRoaXMuY2hhckxlbmd0aCl7dmFyIGF2YWlsYWJsZT1idWZmZXIubGVuZ3RoPj10aGlzLmNoYXJMZW5ndGgtdGhpcy5jaGFyUmVjZWl2ZWQ/dGhpcy5jaGFyTGVuZ3RoLXRoaXMuY2hhclJlY2VpdmVkOmJ1ZmZlci5sZW5ndGg7YnVmZmVyLmNvcHkodGhpcy5jaGFyQnVmZmVyLHRoaXMuY2hhclJlY2VpdmVkLDAsYXZhaWxhYmxlKTt0aGlzLmNoYXJSZWNlaXZlZCs9YXZhaWxhYmxlO2lmKHRoaXMuY2hhclJlY2VpdmVkPHRoaXMuY2hhckxlbmd0aCl7cmV0dXJuXCJcIn1idWZmZXI9YnVmZmVyLnNsaWNlKGF2YWlsYWJsZSxidWZmZXIubGVuZ3RoKTtjaGFyU3RyPXRoaXMuY2hhckJ1ZmZlci5zbGljZSgwLHRoaXMuY2hhckxlbmd0aCkudG9TdHJpbmcodGhpcy5lbmNvZGluZyk7dmFyIGNoYXJDb2RlPWNoYXJTdHIuY2hhckNvZGVBdChjaGFyU3RyLmxlbmd0aC0xKTtpZihjaGFyQ29kZT49NTUyOTYmJmNoYXJDb2RlPD01NjMxOSl7dGhpcy5jaGFyTGVuZ3RoKz10aGlzLnN1cnJvZ2F0ZVNpemU7Y2hhclN0cj1cIlwiO2NvbnRpbnVlfXRoaXMuY2hhclJlY2VpdmVkPXRoaXMuY2hhckxlbmd0aD0wO2lmKGJ1ZmZlci5sZW5ndGg9PT0wKXtyZXR1cm4gY2hhclN0cn1icmVha310aGlzLmRldGVjdEluY29tcGxldGVDaGFyKGJ1ZmZlcik7dmFyIGVuZD1idWZmZXIubGVuZ3RoO2lmKHRoaXMuY2hhckxlbmd0aCl7YnVmZmVyLmNvcHkodGhpcy5jaGFyQnVmZmVyLDAsYnVmZmVyLmxlbmd0aC10aGlzLmNoYXJSZWNlaXZlZCxlbmQpO2VuZC09dGhpcy5jaGFyUmVjZWl2ZWR9Y2hhclN0cis9YnVmZmVyLnRvU3RyaW5nKHRoaXMuZW5jb2RpbmcsMCxlbmQpO3ZhciBlbmQ9Y2hhclN0ci5sZW5ndGgtMTt2YXIgY2hhckNvZGU9Y2hhclN0ci5jaGFyQ29kZUF0KGVuZCk7aWYoY2hhckNvZGU+PTU1Mjk2JiZjaGFyQ29kZTw9NTYzMTkpe3ZhciBzaXplPXRoaXMuc3Vycm9nYXRlU2l6ZTt0aGlzLmNoYXJMZW5ndGgrPXNpemU7dGhpcy5jaGFyUmVjZWl2ZWQrPXNpemU7dGhpcy5jaGFyQnVmZmVyLmNvcHkodGhpcy5jaGFyQnVmZmVyLHNpemUsMCxzaXplKTtidWZmZXIuY29weSh0aGlzLmNoYXJCdWZmZXIsMCwwLHNpemUpO3JldHVybiBjaGFyU3RyLnN1YnN0cmluZygwLGVuZCl9cmV0dXJuIGNoYXJTdHJ9O1N0cmluZ0RlY29kZXIucHJvdG90eXBlLmRldGVjdEluY29tcGxldGVDaGFyPWZ1bmN0aW9uKGJ1ZmZlcil7dmFyIGk9YnVmZmVyLmxlbmd0aD49Mz8zOmJ1ZmZlci5sZW5ndGg7Zm9yKDtpPjA7aS0tKXt2YXIgYz1idWZmZXJbYnVmZmVyLmxlbmd0aC1pXTtpZihpPT0xJiZjPj41PT02KXt0aGlzLmNoYXJMZW5ndGg9MjticmVha31pZihpPD0yJiZjPj40PT0xNCl7dGhpcy5jaGFyTGVuZ3RoPTM7YnJlYWt9aWYoaTw9MyYmYz4+Mz09MzApe3RoaXMuY2hhckxlbmd0aD00O2JyZWFrfX10aGlzLmNoYXJSZWNlaXZlZD1pfTtTdHJpbmdEZWNvZGVyLnByb3RvdHlwZS5lbmQ9ZnVuY3Rpb24oYnVmZmVyKXt2YXIgcmVzPVwiXCI7aWYoYnVmZmVyJiZidWZmZXIubGVuZ3RoKXJlcz10aGlzLndyaXRlKGJ1ZmZlcik7aWYodGhpcy5jaGFyUmVjZWl2ZWQpe3ZhciBjcj10aGlzLmNoYXJSZWNlaXZlZDt2YXIgYnVmPXRoaXMuY2hhckJ1ZmZlcjt2YXIgZW5jPXRoaXMuZW5jb2Rpbmc7cmVzKz1idWYuc2xpY2UoMCxjcikudG9TdHJpbmcoZW5jKX1yZXR1cm4gcmVzfTtmdW5jdGlvbiBwYXNzVGhyb3VnaFdyaXRlKGJ1ZmZlcil7cmV0dXJuIGJ1ZmZlci50b1N0cmluZyh0aGlzLmVuY29kaW5nKX1mdW5jdGlvbiB1dGYxNkRldGVjdEluY29tcGxldGVDaGFyKGJ1ZmZlcil7dGhpcy5jaGFyUmVjZWl2ZWQ9YnVmZmVyLmxlbmd0aCUyO3RoaXMuY2hhckxlbmd0aD10aGlzLmNoYXJSZWNlaXZlZD8yOjB9ZnVuY3Rpb24gYmFzZTY0RGV0ZWN0SW5jb21wbGV0ZUNoYXIoYnVmZmVyKXt0aGlzLmNoYXJSZWNlaXZlZD1idWZmZXIubGVuZ3RoJTM7dGhpcy5jaGFyTGVuZ3RoPXRoaXMuY2hhclJlY2VpdmVkPzM6MH19LHtidWZmZXI6NX1dLDU3OltmdW5jdGlvbihyZXF1aXJlLG1vZHVsZSxleHBvcnRzKXsoZnVuY3Rpb24oZ2xvYmFsKXttb2R1bGUuZXhwb3J0cz1kZXByZWNhdGU7ZnVuY3Rpb24gZGVwcmVjYXRlKGZuLG1zZyl7aWYoY29uZmlnKFwibm9EZXByZWNhdGlvblwiKSl7cmV0dXJuIGZufXZhciB3YXJuZWQ9ZmFsc2U7ZnVuY3Rpb24gZGVwcmVjYXRlZCgpe2lmKCF3YXJuZWQpe2lmKGNvbmZpZyhcInRocm93RGVwcmVjYXRpb25cIikpe3Rocm93IG5ldyBFcnJvcihtc2cpfWVsc2UgaWYoY29uZmlnKFwidHJhY2VEZXByZWNhdGlvblwiKSl7Y29uc29sZS50cmFjZShtc2cpfWVsc2V7Y29uc29sZS53YXJuKG1zZyl9d2FybmVkPXRydWV9cmV0dXJuIGZuLmFwcGx5KHRoaXMsYXJndW1lbnRzKX1yZXR1cm4gZGVwcmVjYXRlZH1mdW5jdGlvbiBjb25maWcobmFtZSl7dHJ5e2lmKCFnbG9iYWwubG9jYWxTdG9yYWdlKXJldHVybiBmYWxzZX1jYXRjaChfKXtyZXR1cm4gZmFsc2V9dmFyIHZhbD1nbG9iYWwubG9jYWxTdG9yYWdlW25hbWVdO2lmKG51bGw9PXZhbClyZXR1cm4gZmFsc2U7cmV0dXJuIFN0cmluZyh2YWwpLnRvTG93ZXJDYXNlKCk9PT1cInRydWVcIn19KS5jYWxsKHRoaXMsdHlwZW9mIGdsb2JhbCE9PVwidW5kZWZpbmVkXCI/Z2xvYmFsOnR5cGVvZiBzZWxmIT09XCJ1bmRlZmluZWRcIj9zZWxmOnR5cGVvZiB3aW5kb3chPT1cInVuZGVmaW5lZFwiP3dpbmRvdzp7fSl9LHt9XSw1ODpbZnVuY3Rpb24ocmVxdWlyZSxtb2R1bGUsZXhwb3J0cyl7bW9kdWxlLmV4cG9ydHM9ZXh0ZW5kO3ZhciBoYXNPd25Qcm9wZXJ0eT1PYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5O2Z1bmN0aW9uIGV4dGVuZCgpe3ZhciB0YXJnZXQ9e307Zm9yKHZhciBpPTA7aTxhcmd1bWVudHMubGVuZ3RoO2krKyl7dmFyIHNvdXJjZT1hcmd1bWVudHNbaV07Zm9yKHZhciBrZXkgaW4gc291cmNlKXtpZihoYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSxrZXkpKXt0YXJnZXRba2V5XT1zb3VyY2Vba2V5XX19fXJldHVybiB0YXJnZXR9fSx7fV19LHt9LFsxXSkoMSl9KTtcbiIsIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dmFyIGY9bmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKTt0aHJvdyBmLmNvZGU9XCJNT0RVTEVfTk9UX0ZPVU5EXCIsZn12YXIgbD1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwobC5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxsLGwuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXV0aCA9IHJlcXVpcmUoJy4vbGliL2F1dGgnKTtcbnZhciBoZWxwZXJzID0gcmVxdWlyZSgnLi9saWIvaGVscGVycycpO1xudmFyIFN3YWdnZXJDbGllbnQgPSByZXF1aXJlKCcuL2xpYi9jbGllbnQnKTtcbnZhciBkZXByZWNhdGlvbldyYXBwZXIgPSBmdW5jdGlvbiAodXJsLCBvcHRpb25zKSB7XG4gIGhlbHBlcnMubG9nKCdUaGlzIGlzIGRlcHJlY2F0ZWQsIHVzZSBcIm5ldyBTd2FnZ2VyQ2xpZW50XCIgaW5zdGVhZC4nKTtcblxuICByZXR1cm4gbmV3IFN3YWdnZXJDbGllbnQodXJsLCBvcHRpb25zKTtcbn07XG5cbi8qIEhlcmUgZm9yIElFOCBTdXBwb3J0ICovXG5pZiAoIUFycmF5LnByb3RvdHlwZS5pbmRleE9mKSB7XG4gIEFycmF5LnByb3RvdHlwZS5pbmRleE9mID0gZnVuY3Rpb24ob2JqLCBzdGFydCkge1xuICAgIGZvciAodmFyIGkgPSAoc3RhcnQgfHwgMCksIGogPSB0aGlzLmxlbmd0aDsgaSA8IGo7IGkrKykge1xuICAgICAgaWYgKHRoaXNbaV0gPT09IG9iaikgeyByZXR1cm4gaTsgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH07XG59XG5cbi8qIEhlcmUgZm9yIElFOCBTdXBwb3J0ICovXG5pZiAoIVN0cmluZy5wcm90b3R5cGUudHJpbSkge1xuICBTdHJpbmcucHJvdG90eXBlLnRyaW0gPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMucmVwbGFjZSgvXlxccyt8XFxzKyQvZywgJycpO1xuICB9O1xufVxuXG4vKiBIZXJlIGZvciBub2RlIDEwLnggc3VwcG9ydCAqL1xuaWYgKCFTdHJpbmcucHJvdG90eXBlLmVuZHNXaXRoKSB7XG4gIFN0cmluZy5wcm90b3R5cGUuZW5kc1dpdGggPSBmdW5jdGlvbihzdWZmaXgpIHtcbiAgICByZXR1cm4gdGhpcy5pbmRleE9mKHN1ZmZpeCwgdGhpcy5sZW5ndGggLSBzdWZmaXgubGVuZ3RoKSAhPT0gLTE7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gU3dhZ2dlckNsaWVudDtcblxuU3dhZ2dlckNsaWVudC5BcGlLZXlBdXRob3JpemF0aW9uID0gYXV0aC5BcGlLZXlBdXRob3JpemF0aW9uO1xuU3dhZ2dlckNsaWVudC5QYXNzd29yZEF1dGhvcml6YXRpb24gPSBhdXRoLlBhc3N3b3JkQXV0aG9yaXphdGlvbjtcblN3YWdnZXJDbGllbnQuQ29va2llQXV0aG9yaXphdGlvbiA9IGF1dGguQ29va2llQXV0aG9yaXphdGlvbjtcblN3YWdnZXJDbGllbnQuU3dhZ2dlckFwaSA9IGRlcHJlY2F0aW9uV3JhcHBlcjtcblN3YWdnZXJDbGllbnQuU3dhZ2dlckNsaWVudCA9IGRlcHJlY2F0aW9uV3JhcHBlcjtcblN3YWdnZXJDbGllbnQuU2NoZW1hTWFya3VwID0gcmVxdWlyZSgnLi9saWIvc2NoZW1hLW1hcmt1cCcpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4vaGVscGVycycpO1xudmFyIGJ0b2EgPSByZXF1aXJlKCdidG9hJyk7IC8vIGpzaGludCBpZ25vcmU6bGluZVxudmFyIENvb2tpZUphciA9IHJlcXVpcmUoJ2Nvb2tpZWphcicpLkNvb2tpZUphcjtcbnZhciBfID0ge1xuICBlYWNoOiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2NvbGxlY3Rpb24vZWFjaCcpLFxuICBpbmNsdWRlczogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9jb2xsZWN0aW9uL2luY2x1ZGVzJyksXG4gIGlzT2JqZWN0OiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvaXNPYmplY3QnKSxcbiAgaXNBcnJheTogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9sYW5nL2lzQXJyYXknKVxufTtcblxuLyoqXG4gKiBTd2FnZ2VyQXV0aG9yaXphdGlvbnMgYXBwbGllcyB0aGUgY29ycmVjdCBhdXRob3JpemF0aW9uIHRvIGFuIG9wZXJhdGlvbiBiZWluZyBleGVjdXRlZFxuICovXG52YXIgU3dhZ2dlckF1dGhvcml6YXRpb25zID0gbW9kdWxlLmV4cG9ydHMuU3dhZ2dlckF1dGhvcml6YXRpb25zID0gZnVuY3Rpb24gKGF1dGh6KSB7XG4gIHRoaXMuYXV0aHogPSBhdXRoeiB8fCB7fTtcbn07XG5cbi8qKlxuICogQWRkIGF1dGhzIHRvIHRoZSBoYXNoXG4gKiBXaWxsIG92ZXJ3cml0ZSBhbnkgZXhpc3RpbmdcbiAqXG4gKi9cblN3YWdnZXJBdXRob3JpemF0aW9ucy5wcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gKG5hbWUsIGF1dGgpIHtcbiAgaWYoXy5pc09iamVjdChuYW1lKSkge1xuICAgIGZvciAodmFyIGtleSBpbiBuYW1lKSB7XG4gICAgICB0aGlzLmF1dGh6W2tleV0gPSBuYW1lW2tleV07XG4gICAgfVxuICB9IGVsc2UgaWYodHlwZW9mIG5hbWUgPT09ICdzdHJpbmcnICl7XG4gICAgdGhpcy5hdXRoeltuYW1lXSA9IGF1dGg7XG4gIH1cblxuICByZXR1cm4gYXV0aDtcbn07XG5cblN3YWdnZXJBdXRob3JpemF0aW9ucy5wcm90b3R5cGUucmVtb3ZlID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgcmV0dXJuIGRlbGV0ZSB0aGlzLmF1dGh6W25hbWVdO1xufTtcblxuU3dhZ2dlckF1dGhvcml6YXRpb25zLnByb3RvdHlwZS5hcHBseSA9IGZ1bmN0aW9uIChvYmosIHNlY3VyaXRpZXMpIHtcbiAgdmFyIHN0YXR1cyA9IHRydWU7XG4gIHZhciBhcHBseUFsbCA9ICFzZWN1cml0aWVzO1xuICB2YXIgZmxhdHRlbmVkU2VjdXJpdGllcyA9IFtdO1xuXG4gIC8vIGZhdm9yIHRoZSBvYmplY3QtbGV2ZWwgYXV0aG9yaXphdGlvbnMgb3ZlciBnbG9iYWxcbiAgdmFyIGF1dGh6ID0gb2JqLmNsaWVudEF1dGhvcml6YXRpb25zIHx8IHRoaXMuYXV0aHo7XG5cbiAgLy8gU2VjdXJpdGllcyBjb3VsZCBiZSBbIHt9IF1cbiAgXy5lYWNoKHNlY3VyaXRpZXMsIGZ1bmN0aW9uIChvYmosIGtleSkge1xuXG4gICAgLy8gTWFrZSBzdXJlIHdlIGFjY291bnQgZm9yIHNlY3VyaXRpZXMgYmVpbmcgWyBzdHIgXVxuICAgIGlmKHR5cGVvZiBrZXkgPT09ICdzdHJpbmcnKSB7XG4gICAgICBmbGF0dGVuZWRTZWN1cml0aWVzLnB1c2goa2V5KTtcbiAgICB9XG5cbiAgICAvLyBGbGF0dGVuIGtleXMgaW4gdG8gb3VyIGFycmF5XG4gICAgXy5lYWNoKG9iaiwgZnVuY3Rpb24gKHZhbCwga2V5KSB7XG4gICAgICBmbGF0dGVuZWRTZWN1cml0aWVzLnB1c2goa2V5KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgXy5lYWNoKGF1dGh6LCBmdW5jdGlvbiAoYXV0aCwgYXV0aE5hbWUpIHtcbiAgICBpZihhcHBseUFsbCB8fCBfLmluY2x1ZGVzKGZsYXR0ZW5lZFNlY3VyaXRpZXMsIGF1dGhOYW1lKSkge1xuICAgICAgdmFyIG5ld1N0YXR1cyA9IGF1dGguYXBwbHkob2JqKTtcbiAgICAgIHN0YXR1cyA9IHN0YXR1cyAmJiAhIW5ld1N0YXR1czsgLy8gbG9naWNhbCBPUnMgcmVnYXJkaW5nIHN0YXR1c1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIHN0YXR1cztcbn07XG5cbi8qKlxuICogQXBpS2V5QXV0aG9yaXphdGlvbiBhbGxvd3MgYSBxdWVyeSBwYXJhbSBvciBoZWFkZXIgdG8gYmUgaW5qZWN0ZWRcbiAqL1xudmFyIEFwaUtleUF1dGhvcml6YXRpb24gPSBtb2R1bGUuZXhwb3J0cy5BcGlLZXlBdXRob3JpemF0aW9uID0gZnVuY3Rpb24gKG5hbWUsIHZhbHVlLCB0eXBlKSB7XG4gIHRoaXMubmFtZSA9IG5hbWU7XG4gIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgdGhpcy50eXBlID0gdHlwZTtcbn07XG5cbkFwaUtleUF1dGhvcml6YXRpb24ucHJvdG90eXBlLmFwcGx5ID0gZnVuY3Rpb24gKG9iaikge1xuICBpZiAodGhpcy50eXBlID09PSAncXVlcnknKSB7XG4gICAgLy8gc2VlIGlmIGFscmVhZHkgYXBwbGllZC4gIElmIHNvLCBkb24ndCBkbyBpdCBhZ2FpblxuXG4gICAgdmFyIHFwO1xuICAgIGlmIChvYmoudXJsLmluZGV4T2YoJz8nKSA+IDApIHtcbiAgICAgIHFwID0gb2JqLnVybC5zdWJzdHJpbmcob2JqLnVybC5pbmRleE9mKCc/JykgKyAxKTtcbiAgICAgIHZhciBwYXJ0cyA9IHFwLnNwbGl0KCcmJyk7XG4gICAgICBpZihwYXJ0cyAmJiBwYXJ0cy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBwYXJ0cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciBrdiA9IHBhcnRzW2ldLnNwbGl0KCc9Jyk7XG4gICAgICAgICAgaWYoa3YgJiYga3YubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgaWYgKGt2WzBdID09PSB0aGlzLm5hbWUpIHtcbiAgICAgICAgICAgICAgLy8gc2tpcCBpdFxuICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG9iai51cmwuaW5kZXhPZignPycpID4gMCkge1xuICAgICAgb2JqLnVybCA9IG9iai51cmwgKyAnJicgKyB0aGlzLm5hbWUgKyAnPScgKyB0aGlzLnZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICBvYmoudXJsID0gb2JqLnVybCArICc/JyArIHRoaXMubmFtZSArICc9JyArIHRoaXMudmFsdWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSBpZiAodGhpcy50eXBlID09PSAnaGVhZGVyJykge1xuICAgIGlmKHR5cGVvZiBvYmouaGVhZGVyc1t0aGlzLm5hbWVdID09PSAndW5kZWZpbmVkJykge1xuICAgICAgb2JqLmhlYWRlcnNbdGhpcy5uYW1lXSA9IHRoaXMudmFsdWU7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn07XG5cbnZhciBDb29raWVBdXRob3JpemF0aW9uID0gbW9kdWxlLmV4cG9ydHMuQ29va2llQXV0aG9yaXphdGlvbiA9IGZ1bmN0aW9uIChjb29raWUpIHtcbiAgdGhpcy5jb29raWUgPSBjb29raWU7XG59O1xuXG5Db29raWVBdXRob3JpemF0aW9uLnByb3RvdHlwZS5hcHBseSA9IGZ1bmN0aW9uIChvYmopIHtcbiAgb2JqLmNvb2tpZUphciA9IG9iai5jb29raWVKYXIgfHwgbmV3IENvb2tpZUphcigpO1xuICBvYmouY29va2llSmFyLnNldENvb2tpZSh0aGlzLmNvb2tpZSk7XG5cbiAgcmV0dXJuIHRydWU7XG59O1xuXG4vKipcbiAqIFBhc3N3b3JkIEF1dGhvcml6YXRpb24gaXMgYSBiYXNpYyBhdXRoIGltcGxlbWVudGF0aW9uXG4gKi9cbnZhciBQYXNzd29yZEF1dGhvcml6YXRpb24gPSBtb2R1bGUuZXhwb3J0cy5QYXNzd29yZEF1dGhvcml6YXRpb24gPSBmdW5jdGlvbiAodXNlcm5hbWUsIHBhc3N3b3JkKSB7XG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAzKSB7XG4gICAgaGVscGVycy5sb2coJ1Bhc3N3b3JkQXV0aG9yaXphdGlvbjogdGhlIFxcJ25hbWVcXCcgYXJndW1lbnQgaGFzIGJlZW4gcmVtb3ZlZCwgcGFzcyBvbmx5IHVzZXJuYW1lIGFuZCBwYXNzd29yZCcpO1xuICAgIHVzZXJuYW1lID0gYXJndW1lbnRzWzFdO1xuICAgIHBhc3N3b3JkID0gYXJndW1lbnRzWzJdO1xuICB9XG4gIHRoaXMudXNlcm5hbWUgPSB1c2VybmFtZTtcbiAgdGhpcy5wYXNzd29yZCA9IHBhc3N3b3JkO1xufTtcblxuUGFzc3dvcmRBdXRob3JpemF0aW9uLnByb3RvdHlwZS5hcHBseSA9IGZ1bmN0aW9uIChvYmopIHtcbiAgaWYodHlwZW9mIG9iai5oZWFkZXJzLkF1dGhvcml6YXRpb24gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgb2JqLmhlYWRlcnMuQXV0aG9yaXphdGlvbiA9ICdCYXNpYyAnICsgYnRvYSh0aGlzLnVzZXJuYW1lICsgJzonICsgdGhpcy5wYXNzd29yZCk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0ge1xuICBiaW5kOiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2Z1bmN0aW9uL2JpbmQnKSxcbiAgY2xvbmVEZWVwOiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvY2xvbmVEZWVwJyksXG4gIGZpbmQ6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvY29sbGVjdGlvbi9maW5kJyksXG4gIGZvckVhY2g6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvY29sbGVjdGlvbi9mb3JFYWNoJyksXG4gIGluZGV4T2Y6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvYXJyYXkvaW5kZXhPZicpLFxuICBpc0FycmF5OiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvaXNBcnJheScpLFxuICBpc09iamVjdDogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9sYW5nL2lzT2JqZWN0JyksXG4gIGlzRnVuY3Rpb246IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvbGFuZy9pc0Z1bmN0aW9uJyksXG4gIGlzUGxhaW5PYmplY3Q6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvbGFuZy9pc1BsYWluT2JqZWN0JyksXG4gIGlzVW5kZWZpbmVkOiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvaXNVbmRlZmluZWQnKVxufTtcbnZhciBhdXRoID0gcmVxdWlyZSgnLi9hdXRoJyk7XG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4vaGVscGVycycpO1xudmFyIE1vZGVsID0gcmVxdWlyZSgnLi90eXBlcy9tb2RlbCcpO1xudmFyIE9wZXJhdGlvbiA9IHJlcXVpcmUoJy4vdHlwZXMvb3BlcmF0aW9uJyk7XG52YXIgT3BlcmF0aW9uR3JvdXAgPSByZXF1aXJlKCcuL3R5cGVzL29wZXJhdGlvbkdyb3VwJyk7XG52YXIgUmVzb2x2ZXIgPSByZXF1aXJlKCcuL3Jlc29sdmVyJyk7XG52YXIgU3dhZ2dlckh0dHAgPSByZXF1aXJlKCcuL2h0dHAnKTtcbnZhciBTd2FnZ2VyU3BlY0NvbnZlcnRlciA9IHJlcXVpcmUoJy4vc3BlYy1jb252ZXJ0ZXInKTtcbnZhciBRID0gcmVxdWlyZSgncScpO1xuXG4vLyBXZSBoYXZlIHRvIGtlZXAgdHJhY2sgb2YgdGhlIGZ1bmN0aW9uL3Byb3BlcnR5IG5hbWVzIHRvIGF2b2lkIGNvbGxpc2lvbnMgZm9yIHRhZyBuYW1lcyB3aGljaCBhcmUgdXNlZCB0byBhbGxvdyB0aGVcbi8vIGZvbGxvd2luZyB1c2FnZTogJ2NsaWVudC57dGFnTmFtZX0nXG52YXIgcmVzZXJ2ZWRDbGllbnRUYWdzID0gW1xuICAnYXBpcycsXG4gICdhdXRob3JpemF0aW9uU2NoZW1lJyxcbiAgJ2F1dGhvcml6YXRpb25zJyxcbiAgJ2Jhc2VQYXRoJyxcbiAgJ2J1aWxkJyxcbiAgJ2J1aWxkRnJvbTFfMVNwZWMnLFxuICAnYnVpbGRGcm9tMV8yU3BlYycsXG4gICdidWlsZEZyb21TcGVjJyxcbiAgJ2NsaWVudEF1dGhvcml6YXRpb25zJyxcbiAgJ2NvbnZlcnRJbmZvJyxcbiAgJ2RlYnVnJyxcbiAgJ2RlZmF1bHRFcnJvckNhbGxiYWNrJyxcbiAgJ2RlZmF1bHRTdWNjZXNzQ2FsbGJhY2snLFxuICAnZW5hYmxlQ29va2llcycsXG4gICdmYWlsJyxcbiAgJ2ZhaWx1cmUnLFxuICAnZmluaXNoJyxcbiAgJ2hlbHAnLFxuICAnaG9zdCcsXG4gICdpZEZyb21PcCcsXG4gICdpbmZvJyxcbiAgJ2luaXRpYWxpemUnLFxuICAnaXNCdWlsdCcsXG4gICdpc1ZhbGlkJyxcbiAgJ21vZGVsUHJvcGVydHlNYWNybycsXG4gICdtb2RlbHMnLFxuICAnbW9kZWxzQXJyYXknLFxuICAnb3B0aW9ucycsXG4gICdwYXJhbWV0ZXJNYWNybycsXG4gICdwYXJzZVVyaScsXG4gICdwcm9ncmVzcycsXG4gICdyZXNvdXJjZUNvdW50JyxcbiAgJ3NhbXBsZU1vZGVscycsXG4gICdzZWxmUmVmbGVjdCcsXG4gICdzZXRDb25zb2xpZGF0ZWRNb2RlbHMnLFxuICAnc3BlYycsXG4gICdzdXBwb3J0ZWRTdWJtaXRNZXRob2RzJyxcbiAgJ3N3YWdnZXJSZXF1ZXN0SGVhZGVycycsXG4gICd0YWdGcm9tTGFiZWwnLFxuICAndGl0bGUnLFxuICAndXJsJyxcbiAgJ3VzZUpRdWVyeScsXG4gICdqcXVlcnlBamF4Q2FjaGUnXG5dO1xuLy8gV2UgaGF2ZSB0byBrZWVwIHRyYWNrIG9mIHRoZSBmdW5jdGlvbi9wcm9wZXJ0eSBuYW1lcyB0byBhdm9pZCBjb2xsaXNpb25zIGZvciB0YWcgbmFtZXMgd2hpY2ggYXJlIHVzZWQgdG8gYWxsb3cgdGhlXG4vLyBmb2xsb3dpbmcgdXNhZ2U6ICdjbGllbnQuYXBpcy57dGFnTmFtZX0nXG52YXIgcmVzZXJ2ZWRBcGlUYWdzID0gW1xuICAnYXBpcycsXG4gICdhc0N1cmwnLFxuICAnZGVzY3JpcHRpb24nLFxuICAnZXh0ZXJuYWxEb2NzJyxcbiAgJ2hlbHAnLFxuICAnbGFiZWwnLFxuICAnbmFtZScsXG4gICdvcGVyYXRpb24nLFxuICAnb3BlcmF0aW9ucycsXG4gICdvcGVyYXRpb25zQXJyYXknLFxuICAncGF0aCcsXG4gICd0YWcnXG5dO1xudmFyIHN1cHBvcnRlZE9wZXJhdGlvbk1ldGhvZHMgPSBbJ2RlbGV0ZScsICdnZXQnLCAnaGVhZCcsICdvcHRpb25zJywgJ3BhdGNoJywgJ3Bvc3QnLCAncHV0J107XG52YXIgU3dhZ2dlckNsaWVudCA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKHVybCwgb3B0aW9ucykge1xuICB0aGlzLmF1dGhvcml6YXRpb25zID0gbnVsbDtcbiAgdGhpcy5hdXRob3JpemF0aW9uU2NoZW1lID0gbnVsbDtcbiAgdGhpcy5iYXNlUGF0aCA9IG51bGw7XG4gIHRoaXMuZGVidWcgPSBmYWxzZTtcbiAgdGhpcy5lbmFibGVDb29raWVzID0gZmFsc2U7XG4gIHRoaXMuaW5mbyA9IG51bGw7XG4gIHRoaXMuaXNCdWlsdCA9IGZhbHNlO1xuICB0aGlzLmlzVmFsaWQgPSBmYWxzZTtcbiAgdGhpcy5tb2RlbHNBcnJheSA9IFtdO1xuICB0aGlzLnJlc291cmNlQ291bnQgPSAwO1xuICB0aGlzLnVybCA9IG51bGw7XG4gIHRoaXMudXNlSlF1ZXJ5ID0gZmFsc2U7XG4gIHRoaXMuanF1ZXJ5QWpheENhY2hlID0gZmFsc2U7XG4gIHRoaXMuc3dhZ2dlck9iamVjdCA9IHt9O1xuICB0aGlzLmRlZmVycmVkQ2xpZW50ID0gdW5kZWZpbmVkO1xuXG4gIHRoaXMuY2xpZW50QXV0aG9yaXphdGlvbnMgPSBuZXcgYXV0aC5Td2FnZ2VyQXV0aG9yaXphdGlvbnMoKTtcblxuICBpZiAodHlwZW9mIHVybCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gdGhpcy5pbml0aWFsaXplKHVybCwgb3B0aW9ucyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLmluaXRpYWxpemUgPSBmdW5jdGlvbiAodXJsLCBvcHRpb25zKSB7XG4gIHRoaXMubW9kZWxzID0ge307XG4gIHRoaXMuc2FtcGxlTW9kZWxzID0ge307XG5cbiAgaWYgKHR5cGVvZiB1cmwgPT09ICdzdHJpbmcnKSB7XG4gICAgdGhpcy51cmwgPSB1cmw7XG4gIH0gZWxzZSBpZiAoXy5pc09iamVjdCh1cmwpKSB7XG4gICAgb3B0aW9ucyA9IHVybDtcbiAgICB0aGlzLnVybCA9IG9wdGlvbnMudXJsO1xuICB9XG5cbiAgaWYodGhpcy51cmwgJiYgdGhpcy51cmwuaW5kZXhPZignaHR0cDonKSA9PT0gLTEgJiYgdGhpcy51cmwuaW5kZXhPZignaHR0cHM6JykgPT09IC0xKSB7XG4gICAgLy8gbm8gcHJvdG9jb2wsIHNvIHdlIGNhbiBvbmx5IHVzZSB3aW5kb3cgaWYgaXQgZXhpc3RzXG4gICAgaWYodHlwZW9mKHdpbmRvdykgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZih3aW5kb3cubG9jYXRpb24pICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy51cmwgPSB3aW5kb3cubG9jYXRpb24ub3JpZ2luICsgdGhpcy51cmw7XG4gICAgfVxuICB9XG5cbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIHRoaXMuY2xpZW50QXV0aG9yaXphdGlvbnMuYWRkKG9wdGlvbnMuYXV0aG9yaXphdGlvbnMpO1xuICB0aGlzLnN3YWdnZXJSZXF1ZXN0SGVhZGVycyA9IG9wdGlvbnMuc3dhZ2dlclJlcXVlc3RIZWFkZXJzIHx8ICdhcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ9dXRmLTgsKi8qJztcbiAgdGhpcy5kZWZhdWx0U3VjY2Vzc0NhbGxiYWNrID0gb3B0aW9ucy5kZWZhdWx0U3VjY2Vzc0NhbGxiYWNrIHx8IG51bGw7XG4gIHRoaXMuZGVmYXVsdEVycm9yQ2FsbGJhY2sgPSBvcHRpb25zLmRlZmF1bHRFcnJvckNhbGxiYWNrIHx8IG51bGw7XG4gIHRoaXMubW9kZWxQcm9wZXJ0eU1hY3JvID0gb3B0aW9ucy5tb2RlbFByb3BlcnR5TWFjcm8gfHwgbnVsbDtcbiAgdGhpcy5jb25uZWN0aW9uQWdlbnQgPSBvcHRpb25zLmNvbm5lY3Rpb25BZ2VudCB8fCBudWxsO1xuICB0aGlzLnBhcmFtZXRlck1hY3JvID0gb3B0aW9ucy5wYXJhbWV0ZXJNYWNybyB8fCBudWxsO1xuICB0aGlzLnVzZVByb21pc2UgPSBvcHRpb25zLnVzZVByb21pc2UgfHwgbnVsbDtcblxuICAvLyBvcGVyYXRpb24gcmVxdWVzdCB0aW1lb3V0IGRlZmF1bHRcbiAgdGhpcy50aW1lb3V0ID0gb3B0aW9ucy50aW1lb3V0IHx8IG51bGw7XG4gIC8vIGRlZmF1bHQgdG8gcmVxdWVzdCB0aW1lb3V0IHdoZW4gbm90IHNwZWNpZmllZFxuICB0aGlzLmZldGNoU3BlY1RpbWVvdXQgPSB0eXBlb2Ygb3B0aW9ucy5mZXRjaFNwZWNUaW1lb3V0ICE9PSAndW5kZWZpbmVkJyA/XG4gICAgICBvcHRpb25zLmZldGNoU3BlY1RpbWVvdXQgOiBvcHRpb25zLnRpbWVvdXQgfHwgbnVsbDtcblxuICBpZih0aGlzLnVzZVByb21pc2UpIHtcbiAgICB0aGlzLmRlZmVycmVkQ2xpZW50ID0gUS5kZWZlcigpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBvcHRpb25zLnN1Y2Nlc3MgPT09ICdmdW5jdGlvbicpIHtcbiAgICB0aGlzLnN1Y2Nlc3MgPSBvcHRpb25zLnN1Y2Nlc3M7XG4gIH1cbiAgaWYgKG9wdGlvbnMudXNlSlF1ZXJ5KSB7XG4gICAgdGhpcy51c2VKUXVlcnkgPSBvcHRpb25zLnVzZUpRdWVyeTtcbiAgfVxuXG4gIGlmIChvcHRpb25zLmpxdWVyeUFqYXhDYWNoZSkge1xuICAgIHRoaXMuanF1ZXJ5QWpheENhY2hlID0gb3B0aW9ucy5qcXVlcnlBamF4Q2FjaGU7XG4gIH1cblxuICBpZiAob3B0aW9ucy5lbmFibGVDb29raWVzKSB7XG4gICAgdGhpcy5lbmFibGVDb29raWVzID0gb3B0aW9ucy5lbmFibGVDb29raWVzO1xuICB9XG5cbiAgdGhpcy5vcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICAvLyBtYXliZSBkb24ndCBuZWVkIHRoaXM/XG4gIHRoaXMub3B0aW9ucy50aW1lb3V0ID0gdGhpcy50aW1lb3V0O1xuICB0aGlzLm9wdGlvbnMuZmV0Y2hTcGVjVGltZW91dCA9IHRoaXMuZmV0Y2hTcGVjVGltZW91dDtcblxuICB0aGlzLnN1cHBvcnRlZFN1Ym1pdE1ldGhvZHMgPSBvcHRpb25zLnN1cHBvcnRlZFN1Ym1pdE1ldGhvZHMgfHwgW107XG4gIHRoaXMuZmFpbHVyZSA9IG9wdGlvbnMuZmFpbHVyZSB8fCBmdW5jdGlvbiAoZXJyKSB7IHRocm93IGVycjsgfTtcbiAgdGhpcy5wcm9ncmVzcyA9IG9wdGlvbnMucHJvZ3Jlc3MgfHwgZnVuY3Rpb24gKCkge307XG4gIHRoaXMuc3BlYyA9IF8uY2xvbmVEZWVwKG9wdGlvbnMuc3BlYyk7IC8vIENsb25lIHNvIHdlIGRvIG5vdCBhbHRlciB0aGUgcHJvdmlkZWQgZG9jdW1lbnRcblxuICBpZiAob3B0aW9ucy5zY2hlbWUpIHtcbiAgICB0aGlzLnNjaGVtZSA9IG9wdGlvbnMuc2NoZW1lO1xuICB9XG5cbiAgaWYgKHRoaXMudXNlUHJvbWlzZSB8fCB0eXBlb2Ygb3B0aW9ucy5zdWNjZXNzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgdGhpcy5yZWFkeSA9IHRydWU7XG4gICAgcmV0dXJuIHRoaXMuYnVpbGQoKTtcbiAgfVxufTtcblxuU3dhZ2dlckNsaWVudC5wcm90b3R5cGUuYnVpbGQgPSBmdW5jdGlvbiAobW9jaykge1xuICBpZiAodGhpcy5pc0J1aWx0KSB7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgaWYgKHRoaXMuc3BlYykge1xuICAgIHRoaXMucHJvZ3Jlc3MoJ2ZldGNoaW5nIHJlc291cmNlIGxpc3Q7IFBsZWFzZSB3YWl0LicpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMucHJvZ3Jlc3MoJ2ZldGNoaW5nIHJlc291cmNlIGxpc3Q6ICcgKyB0aGlzLnVybCArICc7IFBsZWFzZSB3YWl0LicpO1xuICB9XG5cbiAgdmFyIG9iaiA9IHtcbiAgICB1c2VKUXVlcnk6IHRoaXMudXNlSlF1ZXJ5LFxuICAgIGpxdWVyeUFqYXhDYWNoZTogdGhpcy5qcXVlcnlBamF4Q2FjaGUsXG4gICAgY29ubmVjdGlvbkFnZW50OiB0aGlzLmNvbm5lY3Rpb25BZ2VudCxcbiAgICBlbmFibGVDb29raWVzOiB0aGlzLmVuYWJsZUNvb2tpZXMsXG4gICAgdXJsOiB0aGlzLnVybCxcbiAgICBtZXRob2Q6ICdnZXQnLFxuICAgIGhlYWRlcnM6IHtcbiAgICAgIGFjY2VwdDogdGhpcy5zd2FnZ2VyUmVxdWVzdEhlYWRlcnNcbiAgICB9LFxuICAgIG9uOiB7XG4gICAgICBlcnJvcjogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgIGlmIChzZWxmICYmIHNlbGYudXJsICYmIHNlbGYudXJsLnN1YnN0cmluZygwLCA0KSAhPT0gJ2h0dHAnKSB7XG4gICAgICAgICAgcmV0dXJuIHNlbGYuZmFpbCgnUGxlYXNlIHNwZWNpZnkgdGhlIHByb3RvY29sIGZvciAnICsgc2VsZi51cmwpO1xuICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLmVyck9iaiAmJiAocmVzcG9uc2UuZXJyT2JqLmNvZGUgPT09ICdFQ09OTkFCT1JURUQnIHx8IHJlc3BvbnNlLmVyck9iai5tZXNzYWdlLmluZGV4T2YoJ3RpbWVvdXQnKSAhPT0gLTEpKSB7XG4gICAgICAgICAgcmV0dXJuIHNlbGYuZmFpbCgnUmVxdWVzdCB0aW1lZCBvdXQgYWZ0ZXIgJyArIHNlbGYuZmV0Y2hTcGVjVGltZW91dCArICdtcycpO1xuICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gMCkge1xuICAgICAgICAgIHJldHVybiBzZWxmLmZhaWwoJ0NhblxcJ3QgcmVhZCBmcm9tIHNlcnZlci4gIEl0IG1heSBub3QgaGF2ZSB0aGUgYXBwcm9wcmlhdGUgYWNjZXNzLWNvbnRyb2wtb3JpZ2luIHNldHRpbmdzLicpO1xuICAgICAgICB9IGVsc2UgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PT0gNDA0KSB7XG4gICAgICAgICAgcmV0dXJuIHNlbGYuZmFpbCgnQ2FuXFwndCByZWFkIHN3YWdnZXIgSlNPTiBmcm9tICcgKyBzZWxmLnVybCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHNlbGYuZmFpbChyZXNwb25zZS5zdGF0dXMgKyAnIDogJyArIHJlc3BvbnNlLnN0YXR1c1RleHQgKyAnICcgKyBzZWxmLnVybCk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICByZXNwb25zZTogZnVuY3Rpb24gKHJlc3ApIHtcblxuICAgICAgICB2YXIgcmVzcG9uc2VPYmogPSByZXNwLm9iajtcbiAgICAgICAgaWYoIXJlc3BvbnNlT2JqKSB7XG4gICAgICAgICAgcmV0dXJuIHNlbGYuZmFpbCgnZmFpbGVkIHRvIHBhcnNlIEpTT04vWUFNTCByZXNwb25zZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgc2VsZi5zd2FnZ2VyVmVyc2lvbiA9IHJlc3BvbnNlT2JqLnN3YWdnZXJWZXJzaW9uO1xuICAgICAgICBzZWxmLnN3YWdnZXJPYmplY3QgPSByZXNwb25zZU9iajtcblxuICAgICAgICBpZiAocmVzcG9uc2VPYmouc3dhZ2dlciAmJiBwYXJzZUludChyZXNwb25zZU9iai5zd2FnZ2VyKSA9PT0gMikge1xuICAgICAgICAgIHNlbGYuc3dhZ2dlclZlcnNpb24gPSByZXNwb25zZU9iai5zd2FnZ2VyO1xuXG4gICAgICAgICAgbmV3IFJlc29sdmVyKCkucmVzb2x2ZShyZXNwb25zZU9iaiwgc2VsZi51cmwsIHNlbGYuYnVpbGRGcm9tU3BlYywgc2VsZik7XG5cbiAgICAgICAgICBzZWxmLmlzVmFsaWQgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciBjb252ZXJ0ZXIgPSBuZXcgU3dhZ2dlclNwZWNDb252ZXJ0ZXIoKTtcbiAgICAgICAgICBzZWxmLm9sZFN3YWdnZXJPYmplY3QgPSBzZWxmLnN3YWdnZXJPYmplY3Q7XG5cbiAgICAgICAgICBjb252ZXJ0ZXIuc2V0RG9jdW1lbnRhdGlvbkxvY2F0aW9uKHNlbGYudXJsKTtcbiAgICAgICAgICBjb252ZXJ0ZXIuY29udmVydChyZXNwb25zZU9iaiwgc2VsZi5jbGllbnRBdXRob3JpemF0aW9ucywgc2VsZi5vcHRpb25zLCBmdW5jdGlvbihzcGVjKSB7XG4gICAgICAgICAgICBzZWxmLnN3YWdnZXJPYmplY3QgPSBzcGVjO1xuICAgICAgICAgICAgbmV3IFJlc29sdmVyKCkucmVzb2x2ZShzcGVjLCBzZWxmLnVybCwgc2VsZi5idWlsZEZyb21TcGVjLCBzZWxmKTtcbiAgICAgICAgICAgIHNlbGYuaXNWYWxpZCA9IHRydWU7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgLy8gb25seSBzZXQgdGltZW91dCB3aGVuIHNwZWNpZmllZFxuICBpZiAodGhpcy5mZXRjaFNwZWNUaW1lb3V0KSB7XG4gICAgb2JqLnRpbWVvdXQgPSB0aGlzLmZldGNoU3BlY1RpbWVvdXQ7XG4gIH1cblxuICBpZiAodGhpcy5zcGVjICYmIHR5cGVvZiB0aGlzLnNwZWMgPT09ICdvYmplY3QnKSB7XG4gICAgc2VsZi5zd2FnZ2VyT2JqZWN0ID0gdGhpcy5zcGVjO1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgbmV3IFJlc29sdmVyKCkucmVzb2x2ZShzZWxmLnNwZWMsIHNlbGYudXJsLCBzZWxmLmJ1aWxkRnJvbVNwZWMsIHNlbGYpO1xuICAgIH0sIDEwKTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLmNsaWVudEF1dGhvcml6YXRpb25zLmFwcGx5KG9iaik7XG5cbiAgICBpZiAobW9jaykge1xuICAgICAgcmV0dXJuIG9iajtcbiAgICB9XG5cbiAgICBuZXcgU3dhZ2dlckh0dHAoKS5leGVjdXRlKG9iaiwgdGhpcy5vcHRpb25zKTtcbiAgfVxuXG4gIHJldHVybiAodGhpcy51c2VQcm9taXNlKSA/IHRoaXMuZGVmZXJyZWRDbGllbnQucHJvbWlzZSA6IHRoaXM7XG59O1xuXG5Td2FnZ2VyQ2xpZW50LnByb3RvdHlwZS5idWlsZEZyb21TcGVjID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gIGlmICh0aGlzLmlzQnVpbHQpIHtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIHRoaXMuYXBpcyA9IHt9O1xuICB0aGlzLmFwaXNBcnJheSA9IFtdO1xuICB0aGlzLmJhc2VQYXRoID0gcmVzcG9uc2UuYmFzZVBhdGggfHwgJyc7XG4gIHRoaXMuY29uc3VtZXMgPSByZXNwb25zZS5jb25zdW1lcztcbiAgdGhpcy5ob3N0ID0gcmVzcG9uc2UuaG9zdCB8fCAnJztcbiAgdGhpcy5pbmZvID0gcmVzcG9uc2UuaW5mbyB8fCB7fTtcbiAgdGhpcy5wcm9kdWNlcyA9IHJlc3BvbnNlLnByb2R1Y2VzO1xuICB0aGlzLnNjaGVtZXMgPSByZXNwb25zZS5zY2hlbWVzIHx8IFtdO1xuICB0aGlzLnNlY3VyaXR5RGVmaW5pdGlvbnMgPSBfLmNsb25lRGVlcChyZXNwb25zZS5zZWN1cml0eURlZmluaXRpb25zKTtcbiAgdGhpcy5zZWN1cml0eSA9IHJlc3BvbnNlLnNlY3VyaXR5O1xuICB0aGlzLnRpdGxlID0gcmVzcG9uc2UudGl0bGUgfHwgJyc7XG5cbiAgdmFyIGtleSwgZGVmaW5lZFRhZ3MgPSB7fSwgaywgbG9jYXRpb24sIHNlbGYgPSB0aGlzLCBpO1xuXG4gIGlmIChyZXNwb25zZS5leHRlcm5hbERvY3MpIHtcbiAgICB0aGlzLmV4dGVybmFsRG9jcyA9IHJlc3BvbnNlLmV4dGVybmFsRG9jcztcbiAgfVxuXG4gIC8vIGxlZ2FjeSBzdXBwb3J0XG4gIHRoaXMuYXV0aFNjaGVtZXMgPSB0aGlzLnNlY3VyaXR5RGVmaW5pdGlvbnM7XG5cbiAgaWYodGhpcy5zZWN1cml0eURlZmluaXRpb25zKSB7XG4gICAgZm9yKGtleSBpbiB0aGlzLnNlY3VyaXR5RGVmaW5pdGlvbnMpIHtcbiAgICAgIHZhciBzZWN1cml0eURlZmluaXRpb24gPSB0aGlzLnNlY3VyaXR5RGVmaW5pdGlvbnNba2V5XTtcbiAgICAgIHNlY3VyaXR5RGVmaW5pdGlvbi52ZW5kb3JFeHRlbnNpb25zID0ge307XG4gICAgICBmb3IodmFyIGV4dCBpbiBzZWN1cml0eURlZmluaXRpb24pIHtcbiAgICAgICAgaGVscGVycy5leHRyYWN0RXh0ZW5zaW9ucyhleHQsIHNlY3VyaXR5RGVmaW5pdGlvbik7XG4gICAgICAgIGlmIChleHQgPT09ICdzY29wZXMnKSB7XG4gICAgICAgICAgdmFyIHNjb3BlcyA9IHNlY3VyaXR5RGVmaW5pdGlvbltleHRdO1xuICAgICAgICAgIGlmKHR5cGVvZiBzY29wZXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBzY29wZXMudmVuZG9yRXh0ZW5zaW9ucyA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgcyBpbiBzY29wZXMpIHtcbiAgICAgICAgICAgICAgaGVscGVycy5leHRyYWN0RXh0ZW5zaW9ucyhzLCBzY29wZXMpO1xuICAgICAgICAgICAgICBpZihzLmluZGV4T2YoJ3gtJykgPT09IDApIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgc2NvcGVzW3NdO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKEFycmF5LmlzQXJyYXkocmVzcG9uc2UudGFncykpIHtcbiAgICBkZWZpbmVkVGFncyA9IHt9O1xuXG4gICAgZm9yIChrID0gMDsgayA8IHJlc3BvbnNlLnRhZ3MubGVuZ3RoOyBrKyspIHtcbiAgICAgIHZhciB0ID0gXy5jbG9uZURlZXAocmVzcG9uc2UudGFnc1trXSk7XG4gICAgICBkZWZpbmVkVGFnc1t0Lm5hbWVdID0gdDtcbiAgICAgIGZvcihpIGluIHQpIHtcbiAgICAgICAgaWYoaSA9PT0gJ2V4dGVybmFsRG9jcycgJiYgdHlwZW9mIHRbaV0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgZm9yKHZhciBqIGluIHRbaV0pIHtcbiAgICAgICAgICAgIGhlbHBlcnMuZXh0cmFjdEV4dGVuc2lvbnMoaiwgdFtpXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGhlbHBlcnMuZXh0cmFjdEV4dGVuc2lvbnMoaSwgdCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cblxuICBpZiAodHlwZW9mIHRoaXMudXJsID09PSAnc3RyaW5nJykge1xuICAgIGxvY2F0aW9uID0gdGhpcy5wYXJzZVVyaSh0aGlzLnVybCk7XG4gICAgaWYgKHR5cGVvZiB0aGlzLnNjaGVtZSA9PT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mIHRoaXMuc2NoZW1lcyA9PT0gJ3VuZGVmaW5lZCcgfHwgdGhpcy5zY2hlbWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaWYgKHR5cGVvZiBsb2NhdGlvbiAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mKGxvY2F0aW9uLnNjaGVtZSkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRoaXMuc2NoZW1lID0gbG9jYXRpb24uc2NoZW1lO1xuICAgICAgfVxuICAgICAgaWYodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mKHdpbmRvdy5sb2NhdGlvbikgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIC8vIHVzZSB0aGUgd2luZG93IHNjaGVtZVxuICAgICAgICB0aGlzLnNjaGVtZSA9IHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbC5yZXBsYWNlKCc6JywnJyk7XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5zY2hlbWUgPSBsb2NhdGlvbi5zY2hlbWUgfHwgJ2h0dHAnO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgdHlwZW9mKHdpbmRvdy5sb2NhdGlvbikgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbC5pbmRleE9mKCdjaHJvbWUtZXh0ZW5zaW9uJykgPT09IDApIHtcblx0XHQvLyBpZiBpdCBpcyBjaHJvbWUgc3dhZ2dlciB1aSBleHRlbnNpb24gc2NoZW1lIHRoZW4gbGV0IHN3YWdnZXIgZG9jIHVybCBzY2hlbWUgZGVjaWRlIHRoZSBwcm90b2NvbFxuXHRcdHRoaXMuc2NoZW1lID0gbG9jYXRpb24uc2NoZW1lO1xuXHR9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLnNjaGVtZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGlmKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHR5cGVvZih3aW5kb3cubG9jYXRpb24pICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICB2YXIgc2NoZW1lID0gd2luZG93LmxvY2F0aW9uLnByb3RvY29sLnJlcGxhY2UoJzonLCcnKTtcbiAgICAgICAgaWYoc2NoZW1lID09PSAnaHR0cHMnICYmIHRoaXMuc2NoZW1lcy5pbmRleE9mKHNjaGVtZSkgPT09IC0xKSB7XG4gICAgICAgICAgLy8gY2FuJ3QgY2FsbCBodHRwIGZyb20gaHR0cHMgc2VydmVkIHBhZ2UgaW4gYSBicm93c2VyIVxuICAgICAgICAgIGhlbHBlcnMubG9nKCdDYW5ub3QgY2FsbCBhIGh0dHAgc2VydmVyIGZyb20gaHR0cHMgaW5zaWRlIGEgYnJvd3NlciEnKTtcbiAgICAgICAgICB0aGlzLnNjaGVtZSA9ICdodHRwJztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKHRoaXMuc2NoZW1lcy5pbmRleE9mKHNjaGVtZSkgIT09IC0xKSB7XG4gICAgICAgICAgdGhpcy5zY2hlbWUgPSBzY2hlbWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgaWYodGhpcy5zY2hlbWVzLmluZGV4T2YoJ2h0dHBzJykgIT09IC0xKSB7XG4gICAgICAgICAgICB0aGlzLnNjaGVtZSA9ICdodHRwcyc7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zY2hlbWUgPSAnaHR0cCc7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgdGhpcy5zY2hlbWUgPSB0aGlzLnNjaGVtZXNbMF0gfHwgbG9jYXRpb24uc2NoZW1lO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0eXBlb2YgdGhpcy5ob3N0ID09PSAndW5kZWZpbmVkJyB8fCB0aGlzLmhvc3QgPT09ICcnKSB7XG4gICAgICB0aGlzLmhvc3QgPSBsb2NhdGlvbi5ob3N0O1xuXG4gICAgICBpZiAobG9jYXRpb24ucG9ydCkge1xuICAgICAgICB0aGlzLmhvc3QgPSB0aGlzLmhvc3QgKyAnOicgKyBsb2NhdGlvbi5wb3J0O1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBlbHNlIHtcbiAgICBpZiAodHlwZW9mIHRoaXMuc2NoZW1lcyA9PT0gJ3VuZGVmaW5lZCcgfHwgdGhpcy5zY2hlbWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5zY2hlbWUgPSAnaHR0cCc7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGVvZiB0aGlzLnNjaGVtZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRoaXMuc2NoZW1lID0gdGhpcy5zY2hlbWVzWzBdO1xuICAgIH1cbiAgfVxuXG4gIHRoaXMuZGVmaW5pdGlvbnMgPSByZXNwb25zZS5kZWZpbml0aW9ucztcblxuICBmb3IgKGtleSBpbiB0aGlzLmRlZmluaXRpb25zKSB7XG4gICAgdmFyIG1vZGVsID0gbmV3IE1vZGVsKGtleSwgdGhpcy5kZWZpbml0aW9uc1trZXldLCB0aGlzLm1vZGVscywgdGhpcy5tb2RlbFByb3BlcnR5TWFjcm8pO1xuXG4gICAgaWYgKG1vZGVsKSB7XG4gICAgICB0aGlzLm1vZGVsc1trZXldID0gbW9kZWw7XG4gICAgfVxuICB9XG5cbiAgLy8gZ2V0IHBhdGhzLCBjcmVhdGUgZnVuY3Rpb25zIGZvciBlYWNoIG9wZXJhdGlvbklkXG5cbiAgLy8gQmluZCBoZWxwIHRvICdjbGllbnQuYXBpcydcbiAgc2VsZi5hcGlzLmhlbHAgPSBfLmJpbmQoc2VsZi5oZWxwLCBzZWxmKTtcblxuICBfLmZvckVhY2gocmVzcG9uc2UucGF0aHMsIGZ1bmN0aW9uIChwYXRoT2JqLCBwYXRoKSB7XG4gICAgLy8gT25seSBwcm9jZXNzIGEgcGF0aCBpZiBpdCdzIGFuIG9iamVjdFxuICAgIGlmICghXy5pc1BsYWluT2JqZWN0KHBhdGhPYmopKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgXy5mb3JFYWNoKHN1cHBvcnRlZE9wZXJhdGlvbk1ldGhvZHMsIGZ1bmN0aW9uIChtZXRob2QpIHtcbiAgICAgIHZhciBvcGVyYXRpb24gPSBwYXRoT2JqW21ldGhvZF07XG5cbiAgICAgIGlmIChfLmlzVW5kZWZpbmVkKG9wZXJhdGlvbikpIHtcbiAgICAgICAgLy8gT3BlcmF0aW9uIGRvZXMgbm90IGV4aXN0XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gZWxzZSBpZiAoIV8uaXNQbGFpbk9iamVjdChvcGVyYXRpb24pKSB7XG4gICAgICAgIC8vIE9wZXJhdGlvbiBleGlzdHMgYnV0IGl0IGlzIG5vdCBhbiBPcGVyYXRpb24gT2JqZWN0LiAgU2luY2UgdGhpcyBpcyBpbnZhbGlkLCBsb2cgaXQuXG4gICAgICAgIGhlbHBlcnMubG9nKCdUaGUgXFwnJyArIG1ldGhvZCArICdcXCcgb3BlcmF0aW9uIGZvciBcXCcnICsgcGF0aCArICdcXCcgcGF0aCBpcyBub3QgYW4gT3BlcmF0aW9uIE9iamVjdCcpO1xuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIHRhZ3MgPSBvcGVyYXRpb24udGFncztcblxuICAgICAgaWYgKF8uaXNVbmRlZmluZWQodGFncykgfHwgIV8uaXNBcnJheSh0YWdzKSB8fCB0YWdzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICB0YWdzID0gb3BlcmF0aW9uLnRhZ3MgPSBbICdkZWZhdWx0JyBdO1xuICAgICAgfVxuXG4gICAgICB2YXIgb3BlcmF0aW9uSWQgPSBzZWxmLmlkRnJvbU9wKHBhdGgsIG1ldGhvZCwgb3BlcmF0aW9uKTtcblxuICAgICAgdmFyIG9wZXJhdGlvbk9iamVjdCA9IG5ldyBPcGVyYXRpb24oc2VsZixcbiAgICAgICAgb3BlcmF0aW9uLnNjaGVtZSxcbiAgICAgICAgb3BlcmF0aW9uSWQsXG4gICAgICAgIG1ldGhvZCxcbiAgICAgICAgcGF0aCxcbiAgICAgICAgb3BlcmF0aW9uLFxuICAgICAgICBzZWxmLmRlZmluaXRpb25zLFxuICAgICAgICBzZWxmLm1vZGVscyxcbiAgICAgICAgc2VsZi5jbGllbnRBdXRob3JpemF0aW9ucyk7XG5cbiAgICAgIG9wZXJhdGlvbk9iamVjdC5jb25uZWN0aW9uQWdlbnQgPSBzZWxmLmNvbm5lY3Rpb25BZ2VudDtcbiAgICAgIG9wZXJhdGlvbk9iamVjdC52ZW5kb3JFeHRlbnNpb25zID0ge307XG4gICAgICBmb3IoaSBpbiBvcGVyYXRpb24pIHtcbiAgICAgICAgaGVscGVycy5leHRyYWN0RXh0ZW5zaW9ucyhpLCBvcGVyYXRpb25PYmplY3QsIG9wZXJhdGlvbltpXSk7XG4gICAgICB9XG4gICAgICBvcGVyYXRpb25PYmplY3QuZXh0ZXJuYWxEb2NzID0gb3BlcmF0aW9uLmV4dGVybmFsRG9jcztcbiAgICAgIGlmKG9wZXJhdGlvbk9iamVjdC5leHRlcm5hbERvY3MpIHtcbiAgICAgICAgb3BlcmF0aW9uT2JqZWN0LmV4dGVybmFsRG9jcyA9IF8uY2xvbmVEZWVwKG9wZXJhdGlvbk9iamVjdC5leHRlcm5hbERvY3MpO1xuICAgICAgICBvcGVyYXRpb25PYmplY3QuZXh0ZXJuYWxEb2NzLnZlbmRvckV4dGVuc2lvbnMgPSB7fTtcbiAgICAgICAgZm9yKGkgaW4gb3BlcmF0aW9uT2JqZWN0LmV4dGVybmFsRG9jcykge1xuICAgICAgICAgIGhlbHBlcnMuZXh0cmFjdEV4dGVuc2lvbnMoaSwgb3BlcmF0aW9uT2JqZWN0LmV4dGVybmFsRG9jcyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gYmluZCBzZWxmIG9wZXJhdGlvbidzIGV4ZWN1dGUgY29tbWFuZCB0byB0aGUgYXBpXG4gICAgICBfLmZvckVhY2godGFncywgZnVuY3Rpb24gKHRhZykge1xuICAgICAgICB2YXIgY2xpZW50UHJvcGVydHkgPSBfLmluZGV4T2YocmVzZXJ2ZWRDbGllbnRUYWdzLCB0YWcpID4gLTEgPyAnXycgKyB0YWcgOiB0YWc7XG4gICAgICAgIHZhciBhcGlQcm9wZXJ0eSA9IF8uaW5kZXhPZihyZXNlcnZlZEFwaVRhZ3MsIHRhZykgPiAtMSA/ICdfJyArIHRhZyA6IHRhZztcbiAgICAgICAgdmFyIG9wZXJhdGlvbkdyb3VwID0gc2VsZltjbGllbnRQcm9wZXJ0eV07XG5cbiAgICAgICAgaWYgKGNsaWVudFByb3BlcnR5ICE9PSB0YWcpIHtcbiAgICAgICAgICBoZWxwZXJzLmxvZygnVGhlIFxcJycgKyB0YWcgKyAnXFwnIHRhZyBjb25mbGljdHMgd2l0aCBhIFN3YWdnZXJDbGllbnQgZnVuY3Rpb24vcHJvcGVydHkgbmFtZS4gIFVzZSBcXCdjbGllbnQuJyArXG4gICAgICAgICAgICAgICAgICAgICAgY2xpZW50UHJvcGVydHkgKyAnXFwnIG9yIFxcJ2NsaWVudC5hcGlzLicgKyB0YWcgKyAnXFwnIGluc3RlYWQgb2YgXFwnY2xpZW50LicgKyB0YWcgKyAnXFwnLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFwaVByb3BlcnR5ICE9PSB0YWcpIHtcbiAgICAgICAgICBoZWxwZXJzLmxvZygnVGhlIFxcJycgKyB0YWcgKyAnXFwnIHRhZyBjb25mbGljdHMgd2l0aCBhIFN3YWdnZXJDbGllbnQgb3BlcmF0aW9uIGZ1bmN0aW9uL3Byb3BlcnR5IG5hbWUuICBVc2UgJyArXG4gICAgICAgICAgICAgICAgICAgICAgJ1xcJ2NsaWVudC5hcGlzLicgKyBhcGlQcm9wZXJ0eSArICdcXCcgaW5zdGVhZCBvZiBcXCdjbGllbnQuYXBpcy4nICsgdGFnICsgJ1xcJy4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChfLmluZGV4T2YocmVzZXJ2ZWRBcGlUYWdzLCBvcGVyYXRpb25JZCkgPiAtMSkge1xuICAgICAgICAgIGhlbHBlcnMubG9nKCdUaGUgXFwnJyArIG9wZXJhdGlvbklkICsgJ1xcJyBvcGVyYXRpb25JZCBjb25mbGljdHMgd2l0aCBhIFN3YWdnZXJDbGllbnQgb3BlcmF0aW9uICcgK1xuICAgICAgICAgICAgICAgICAgICAgICdmdW5jdGlvbi9wcm9wZXJ0eSBuYW1lLiAgVXNlIFxcJ2NsaWVudC5hcGlzLicgKyBhcGlQcm9wZXJ0eSArICcuXycgKyBvcGVyYXRpb25JZCArXG4gICAgICAgICAgICAgICAgICAgICAgJ1xcJyBpbnN0ZWFkIG9mIFxcJ2NsaWVudC5hcGlzLicgKyBhcGlQcm9wZXJ0eSArICcuJyArIG9wZXJhdGlvbklkICsgJ1xcJy4nKTtcblxuICAgICAgICAgIG9wZXJhdGlvbklkID0gJ18nICsgb3BlcmF0aW9uSWQ7XG4gICAgICAgICAgb3BlcmF0aW9uT2JqZWN0Lm5pY2tuYW1lID0gb3BlcmF0aW9uSWQ7IC8vIFNvICdjbGllbnQuYXBpcy5bdGFnXS5vcGVyYXRpb25JZC5oZWxwKCkgd29ya3MgcHJvcGVybHlcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChfLmlzVW5kZWZpbmVkKG9wZXJhdGlvbkdyb3VwKSkge1xuICAgICAgICAgIG9wZXJhdGlvbkdyb3VwID0gc2VsZltjbGllbnRQcm9wZXJ0eV0gPSBzZWxmLmFwaXNbYXBpUHJvcGVydHldID0ge307XG5cbiAgICAgICAgICBvcGVyYXRpb25Hcm91cC5vcGVyYXRpb25zID0ge307XG4gICAgICAgICAgb3BlcmF0aW9uR3JvdXAubGFiZWwgPSBhcGlQcm9wZXJ0eTtcbiAgICAgICAgICBvcGVyYXRpb25Hcm91cC5hcGlzID0ge307XG5cbiAgICAgICAgICB2YXIgdGFnRGVmID0gZGVmaW5lZFRhZ3NbdGFnXTtcblxuICAgICAgICAgIGlmICghXy5pc1VuZGVmaW5lZCh0YWdEZWYpKSB7XG4gICAgICAgICAgICBvcGVyYXRpb25Hcm91cC5kZXNjcmlwdGlvbiA9IHRhZ0RlZi5kZXNjcmlwdGlvbjtcbiAgICAgICAgICAgIG9wZXJhdGlvbkdyb3VwLmV4dGVybmFsRG9jcyA9IHRhZ0RlZi5leHRlcm5hbERvY3M7XG4gICAgICAgICAgICBvcGVyYXRpb25Hcm91cC52ZW5kb3JFeHRlbnNpb25zID0gdGFnRGVmLnZlbmRvckV4dGVuc2lvbnM7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgc2VsZltjbGllbnRQcm9wZXJ0eV0uaGVscCA9IF8uYmluZChzZWxmLmhlbHAsIG9wZXJhdGlvbkdyb3VwKTtcbiAgICAgICAgICBzZWxmLmFwaXNBcnJheS5wdXNoKG5ldyBPcGVyYXRpb25Hcm91cCh0YWcsIG9wZXJhdGlvbkdyb3VwLmRlc2NyaXB0aW9uLCBvcGVyYXRpb25Hcm91cC5leHRlcm5hbERvY3MsIG9wZXJhdGlvbk9iamVjdCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgb3BlcmF0aW9uSWQgPSBzZWxmLm1ha2VVbmlxdWVPcGVyYXRpb25JZChvcGVyYXRpb25JZCwgc2VsZi5hcGlzW2FwaVByb3BlcnR5XSk7XG5cbiAgICAgICAgLy8gQmluZCB0YWcgaGVscFxuICAgICAgICBpZiAoIV8uaXNGdW5jdGlvbihvcGVyYXRpb25Hcm91cC5oZWxwKSkge1xuICAgICAgICAgIG9wZXJhdGlvbkdyb3VwLmhlbHAgPSBfLmJpbmQoc2VsZi5oZWxwLCBvcGVyYXRpb25Hcm91cCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBiaW5kIHRvIHRoZSBhcGlzIG9iamVjdFxuICAgICAgICBzZWxmLmFwaXNbYXBpUHJvcGVydHldW29wZXJhdGlvbklkXSA9IG9wZXJhdGlvbkdyb3VwW29wZXJhdGlvbklkXSA9IF8uYmluZChvcGVyYXRpb25PYmplY3QuZXhlY3V0ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVyYXRpb25PYmplY3QpO1xuICAgICAgICBzZWxmLmFwaXNbYXBpUHJvcGVydHldW29wZXJhdGlvbklkXS5oZWxwID0gb3BlcmF0aW9uR3JvdXBbb3BlcmF0aW9uSWRdLmhlbHAgPSBfLmJpbmQob3BlcmF0aW9uT2JqZWN0LmhlbHAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcGVyYXRpb25PYmplY3QpO1xuICAgICAgICBzZWxmLmFwaXNbYXBpUHJvcGVydHldW29wZXJhdGlvbklkXS5hc0N1cmwgPSBvcGVyYXRpb25Hcm91cFtvcGVyYXRpb25JZF0uYXNDdXJsID0gXy5iaW5kKG9wZXJhdGlvbk9iamVjdC5hc0N1cmwsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BlcmF0aW9uT2JqZWN0KTtcblxuICAgICAgICBvcGVyYXRpb25Hcm91cC5hcGlzW29wZXJhdGlvbklkXSA9IG9wZXJhdGlvbkdyb3VwLm9wZXJhdGlvbnNbb3BlcmF0aW9uSWRdID0gb3BlcmF0aW9uT2JqZWN0O1xuXG4gICAgICAgIC8vIGxlZ2FjeSBVSSBmZWF0dXJlXG4gICAgICAgIHZhciBhcGkgPSBfLmZpbmQoc2VsZi5hcGlzQXJyYXksIGZ1bmN0aW9uIChhcGkpIHtcbiAgICAgICAgICByZXR1cm4gYXBpLnRhZyA9PT0gdGFnO1xuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoYXBpKSB7XG4gICAgICAgICAgYXBpLm9wZXJhdGlvbnNBcnJheS5wdXNoKG9wZXJhdGlvbk9iamVjdCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICAvLyBzb3J0IHRoZSBhcGlzQXJyYXkgYWNjb3JkaW5nIHRvIHRoZSB0YWdzXG4gIHZhciBzb3J0ZWRBcGlzID0gW107XG4gIF8uZm9yRWFjaChPYmplY3Qua2V5cyhkZWZpbmVkVGFncyksIGZ1bmN0aW9uICh0YWcpIHtcbiAgICB2YXIgcG9zO1xuICAgIGZvcihwb3MgaW4gc2VsZi5hcGlzQXJyYXkpIHtcbiAgICAgIHZhciBfYXBpID0gc2VsZi5hcGlzQXJyYXlbcG9zXTtcbiAgICAgIGlmKF9hcGkgJiYgdGFnID09PSBfYXBpLm5hbWUpIHtcbiAgICAgICAgc29ydGVkQXBpcy5wdXNoKF9hcGkpO1xuICAgICAgICBzZWxmLmFwaXNBcnJheVtwb3NdID0gbnVsbDtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xuICAvLyBhZGQgYW55dGhpbmcgbGVmdFxuICBfLmZvckVhY2goc2VsZi5hcGlzQXJyYXksIGZ1bmN0aW9uIChhcGkpIHtcbiAgICBpZihhcGkpIHtcbiAgICAgIHNvcnRlZEFwaXMucHVzaChhcGkpO1xuICAgIH1cbiAgfSk7XG4gIHNlbGYuYXBpc0FycmF5ID0gc29ydGVkQXBpcztcblxuICBfLmZvckVhY2gocmVzcG9uc2UuZGVmaW5pdGlvbnMsIGZ1bmN0aW9uIChkZWZpbml0aW9uT2JqLCBkZWZpbml0aW9uKSB7XG4gICAgZGVmaW5pdGlvbk9iai5pZCA9IGRlZmluaXRpb24udG9Mb3dlckNhc2UoKTtcbiAgICBkZWZpbml0aW9uT2JqLm5hbWUgPSBkZWZpbml0aW9uO1xuICAgIHNlbGYubW9kZWxzQXJyYXkucHVzaChkZWZpbml0aW9uT2JqKTtcbiAgfSk7XG5cbiAgdGhpcy5pc0J1aWx0ID0gdHJ1ZTtcblxuICBpZiAodGhpcy51c2VQcm9taXNlKSB7XG4gICAgdGhpcy5pc1ZhbGlkID0gdHJ1ZTtcbiAgICB0aGlzLmlzQnVpbHQgPSB0cnVlO1xuICAgIHRoaXMuZGVmZXJyZWRDbGllbnQucmVzb2x2ZSh0aGlzKTtcblxuICAgIHJldHVybiB0aGlzLmRlZmVycmVkQ2xpZW50LnByb21pc2U7XG4gIH1cblxuICBpZiAodGhpcy5zdWNjZXNzKSB7XG4gICAgdGhpcy5zdWNjZXNzKCk7XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLm1ha2VVbmlxdWVPcGVyYXRpb25JZCA9IGZ1bmN0aW9uKG9wZXJhdGlvbklkLCBhcGkpIHtcbiAgdmFyIGNvdW50ID0gMDtcbiAgdmFyIG5hbWUgPSBvcGVyYXRpb25JZDtcblxuICAvLyBtYWtlIHVuaXF1ZSBhY3Jvc3MgdGhpcyBvcGVyYXRpb24gZ3JvdXBcbiAgd2hpbGUodHJ1ZSkge1xuICAgIHZhciBtYXRjaGVkID0gZmFsc2U7XG4gICAgXy5mb3JFYWNoKGFwaS5vcGVyYXRpb25zLCBmdW5jdGlvbiAob3BlcmF0aW9uKSB7XG4gICAgICBpZihvcGVyYXRpb24ubmlja25hbWUgPT09IG5hbWUpIHtcbiAgICAgICAgbWF0Y2hlZCA9IHRydWU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYoIW1hdGNoZWQpIHtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH1cbiAgICBuYW1lID0gb3BlcmF0aW9uSWQgKyAnXycgKyBjb3VudDtcbiAgICBjb3VudCArKztcbiAgfVxuXG4gIHJldHVybiBvcGVyYXRpb25JZDtcbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLnBhcnNlVXJpID0gZnVuY3Rpb24gKHVyaSkge1xuICB2YXIgdXJsUGFyc2VSRSA9IC9eKCgoKFteOlxcLyNcXD9dKzopPyg/OihcXC9cXC8pKCg/OigoW146QFxcLyNcXD9dKykoPzpcXDooW146QFxcLyNcXD9dKykpPylAKT8oKFteOlxcLyNcXD9cXF1cXFtdK3xcXFtbXlxcL1xcXUAjP10rXFxdKSg/OlxcOihbMC05XSspKT8pKT8pPyk/KChcXC8/KD86W15cXC9cXD8jXStcXC8rKSopKFteXFw/I10qKSkpPyhcXD9bXiNdKyk/KSgjLiopPy87XG4gIHZhciBwYXJ0cyA9IHVybFBhcnNlUkUuZXhlYyh1cmkpO1xuXG4gIHJldHVybiB7XG4gICAgc2NoZW1lOiBwYXJ0c1s0XSA/IHBhcnRzWzRdLnJlcGxhY2UoJzonLCcnKSA6IHVuZGVmaW5lZCxcbiAgICBob3N0OiBwYXJ0c1sxMV0sXG4gICAgcG9ydDogcGFydHNbMTJdLFxuICAgIHBhdGg6IHBhcnRzWzE1XVxuICB9O1xufTtcblxuU3dhZ2dlckNsaWVudC5wcm90b3R5cGUuaGVscCA9IGZ1bmN0aW9uIChkb250UHJpbnQpIHtcbiAgdmFyIG91dHB1dCA9ICcnO1xuXG4gIGlmICh0aGlzIGluc3RhbmNlb2YgU3dhZ2dlckNsaWVudCkge1xuICAgIF8uZm9yRWFjaCh0aGlzLmFwaXMsIGZ1bmN0aW9uIChhcGksIG5hbWUpIHtcbiAgICAgIGlmIChfLmlzUGxhaW5PYmplY3QoYXBpKSkge1xuICAgICAgICBvdXRwdXQgKz0gJ29wZXJhdGlvbnMgZm9yIHRoZSBcXCcnICsgbmFtZSArICdcXCcgdGFnXFxuJztcblxuICAgICAgICBfLmZvckVhY2goYXBpLm9wZXJhdGlvbnMsIGZ1bmN0aW9uIChvcGVyYXRpb24sIG5hbWUpIHtcbiAgICAgICAgICBvdXRwdXQgKz0gJyAgKiAnICsgbmFtZSArICc6ICcgKyBvcGVyYXRpb24uc3VtbWFyeSArICdcXG4nO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSBlbHNlIGlmICh0aGlzIGluc3RhbmNlb2YgT3BlcmF0aW9uR3JvdXAgfHwgXy5pc1BsYWluT2JqZWN0KHRoaXMpKSB7XG4gICAgb3V0cHV0ICs9ICdvcGVyYXRpb25zIGZvciB0aGUgXFwnJyArIHRoaXMubGFiZWwgKyAnXFwnIHRhZ1xcbic7XG5cbiAgICBfLmZvckVhY2godGhpcy5hcGlzLCBmdW5jdGlvbiAob3BlcmF0aW9uLCBuYW1lKSB7XG4gICAgICBvdXRwdXQgKz0gJyAgKiAnICsgbmFtZSArICc6ICcgKyBvcGVyYXRpb24uc3VtbWFyeSArICdcXG4nO1xuICAgIH0pO1xuICB9XG5cbiAgaWYgKGRvbnRQcmludCkge1xuICAgIHJldHVybiBvdXRwdXQ7XG4gIH0gZWxzZSB7XG4gICAgaGVscGVycy5sb2cob3V0cHV0KTtcblxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH1cbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLnRhZ0Zyb21MYWJlbCA9IGZ1bmN0aW9uIChsYWJlbCkge1xuICByZXR1cm4gbGFiZWw7XG59O1xuXG5Td2FnZ2VyQ2xpZW50LnByb3RvdHlwZS5pZEZyb21PcCA9IGZ1bmN0aW9uIChwYXRoLCBodHRwTWV0aG9kLCBvcCkge1xuICBpZighb3AgfHwgIW9wLm9wZXJhdGlvbklkKSB7XG4gICAgb3AgPSBvcCB8fCB7fTtcbiAgICBvcC5vcGVyYXRpb25JZCA9IGh0dHBNZXRob2QgKyAnXycgKyBwYXRoO1xuICB9XG4gIHZhciBvcElkID0gb3Aub3BlcmF0aW9uSWQucmVwbGFjZSgvW1xccyFAIyQlXiYqKClfKz1cXFt7XFxdfTs6PD58LlxcLz8sXFxcXCdcIlwiLV0vZywgJ18nKSB8fCAocGF0aC5zdWJzdHJpbmcoMSkgKyAnXycgKyBodHRwTWV0aG9kKTtcblxuICBvcElkID0gb3BJZC5yZXBsYWNlKC8oKF8pezIsfSkvZywgJ18nKTtcbiAgb3BJZCA9IG9wSWQucmVwbGFjZSgvXihfKSovZywgJycpO1xuICBvcElkID0gb3BJZC5yZXBsYWNlKC8oW19dKSokL2csICcnKTtcblxuICByZXR1cm4gb3BJZDtcbn07XG5cblN3YWdnZXJDbGllbnQucHJvdG90eXBlLnNldEhvc3QgPSBmdW5jdGlvbiAoaG9zdCkge1xuICB0aGlzLmhvc3QgPSBob3N0O1xuXG4gIGlmKHRoaXMuYXBpcykge1xuICAgIF8uZm9yRWFjaCh0aGlzLmFwaXMsIGZ1bmN0aW9uKGFwaSkge1xuICAgICAgaWYoYXBpLm9wZXJhdGlvbnMpIHtcbiAgICAgICAgXy5mb3JFYWNoKGFwaS5vcGVyYXRpb25zLCBmdW5jdGlvbihvcGVyYXRpb24pIHtcbiAgICAgICAgICBvcGVyYXRpb24uaG9zdCA9IGhvc3Q7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59O1xuXG5Td2FnZ2VyQ2xpZW50LnByb3RvdHlwZS5zZXRCYXNlUGF0aCA9IGZ1bmN0aW9uIChiYXNlUGF0aCkge1xuICB0aGlzLmJhc2VQYXRoID0gYmFzZVBhdGg7XG5cbiAgaWYodGhpcy5hcGlzKSB7XG4gICAgXy5mb3JFYWNoKHRoaXMuYXBpcywgZnVuY3Rpb24oYXBpKSB7XG4gICAgICBpZihhcGkub3BlcmF0aW9ucykge1xuICAgICAgICBfLmZvckVhY2goYXBpLm9wZXJhdGlvbnMsIGZ1bmN0aW9uKG9wZXJhdGlvbikge1xuICAgICAgICAgIG9wZXJhdGlvbi5iYXNlUGF0aCA9IGJhc2VQYXRoO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxufTtcblxuU3dhZ2dlckNsaWVudC5wcm90b3R5cGUuc2V0U2NoZW1lcyA9IGZ1bmN0aW9uIChzY2hlbWVzKSB7XG4gIHRoaXMuc2NoZW1lcyA9IHNjaGVtZXM7XG5cbiAgaWYoc2NoZW1lcyAmJiBzY2hlbWVzLmxlbmd0aCA+IDApIHtcbiAgICBpZih0aGlzLmFwaXMpIHtcbiAgICAgIF8uZm9yRWFjaCh0aGlzLmFwaXMsIGZ1bmN0aW9uIChhcGkpIHtcbiAgICAgICAgaWYgKGFwaS5vcGVyYXRpb25zKSB7XG4gICAgICAgICAgXy5mb3JFYWNoKGFwaS5vcGVyYXRpb25zLCBmdW5jdGlvbiAob3BlcmF0aW9uKSB7XG4gICAgICAgICAgICBvcGVyYXRpb24uc2NoZW1lID0gc2NoZW1lc1swXTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuICB9XG59O1xuXG5Td2FnZ2VyQ2xpZW50LnByb3RvdHlwZS5mYWlsID0gZnVuY3Rpb24gKG1lc3NhZ2UpIHtcbiAgaWYgKHRoaXMudXNlUHJvbWlzZSkge1xuICAgIHRoaXMuZGVmZXJyZWRDbGllbnQucmVqZWN0KG1lc3NhZ2UpO1xuICAgIHJldHVybiB0aGlzLmRlZmVycmVkQ2xpZW50LnByb21pc2U7XG4gIH0gZWxzZSB7XG4gICAgaWYgKHRoaXMuZmFpbHVyZSkge1xuICAgICAgdGhpcy5mYWlsdXJlKG1lc3NhZ2UpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuZmFpbHVyZShtZXNzYWdlKTtcbiAgICB9XG4gIH1cbn07XG4iLCIoZnVuY3Rpb24gKHByb2Nlc3Mpe1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgXyA9IHtcbiAgaXNQbGFpbk9iamVjdDogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9sYW5nL2lzUGxhaW5PYmplY3QnKSxcbiAgaW5kZXhPZjogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9hcnJheS9pbmRleE9mJylcbn07XG5cbm1vZHVsZS5leHBvcnRzLl9fYmluZCA9IGZ1bmN0aW9uIChmbiwgbWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCl7XG4gICAgcmV0dXJuIGZuLmFwcGx5KG1lLCBhcmd1bWVudHMpO1xuICB9O1xufTtcblxudmFyIGxvZyA9IG1vZHVsZS5leHBvcnRzLmxvZyA9IGZ1bmN0aW9uKCkge1xuICAvLyBPbmx5IGxvZyBpZiBhdmFpbGFibGUgYW5kIHdlJ3JlIG5vdCB0ZXN0aW5nXG4gIGlmIChjb25zb2xlICYmIHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAndGVzdCcpIHtcbiAgICBjb25zb2xlLmxvZyhBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpWzBdKTtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMuZmFpbCA9IGZ1bmN0aW9uIChtZXNzYWdlKSB7XG4gIGxvZyhtZXNzYWdlKTtcbn07XG5cbm1vZHVsZS5leHBvcnRzLm9wdGlvbkh0bWwgPSBmdW5jdGlvbiAobGFiZWwsIHZhbHVlKSB7XG4gIHJldHVybiAnPHRyPjx0ZCBjbGFzcz1cIm9wdGlvbk5hbWVcIj4nICsgbGFiZWwgKyAnOjwvdGQ+PHRkPicgKyB2YWx1ZSArICc8L3RkPjwvdHI+Jztcbn07XG5cbnZhciByZXNvbHZlU2NoZW1hID0gbW9kdWxlLmV4cG9ydHMucmVzb2x2ZVNjaGVtYSA9IGZ1bmN0aW9uIChzY2hlbWEpIHtcbiAgaWYgKF8uaXNQbGFpbk9iamVjdChzY2hlbWEuc2NoZW1hKSkge1xuICAgIHNjaGVtYSA9IHJlc29sdmVTY2hlbWEoc2NoZW1hLnNjaGVtYSk7XG4gIH1cblxuICByZXR1cm4gc2NoZW1hO1xufTtcblxubW9kdWxlLmV4cG9ydHMuc2ltcGxlUmVmID0gZnVuY3Rpb24gKG5hbWUpIHtcbiAgaWYgKHR5cGVvZiBuYW1lID09PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgaWYgKG5hbWUuaW5kZXhPZignIy9kZWZpbml0aW9ucy8nKSA9PT0gMCkge1xuICAgIHJldHVybiBuYW1lLnN1YnN0cmluZygnIy9kZWZpbml0aW9ucy8nLmxlbmd0aCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG5hbWU7XG4gIH1cbn07XG5cbi8qKlxuICogaGVscGVyIHRvIHJlbW92ZSBleHRlbnNpb25zIGFuZCBhZGQgdGhlbSB0byBhbiBvYmplY3RcbiAqXG4gKiBAcGFyYW0ga2V5bmFtZVxuICogQHBhcmFtIG9ialxuICovXG5tb2R1bGUuZXhwb3J0cy5leHRyYWN0RXh0ZW5zaW9ucyA9IGZ1bmN0aW9uIChrZXluYW1lLCBvYmosIHZhbHVlKSB7XG4gIGlmKCFrZXluYW1lIHx8ICFvYmopIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAodHlwZW9mIGtleW5hbWUgPT09ICdzdHJpbmcnICYmIGtleW5hbWUuaW5kZXhPZigneC0nKSA9PT0gMCkge1xuICAgIG9iai52ZW5kb3JFeHRlbnNpb25zID0gb2JqLnZlbmRvckV4dGVuc2lvbnMgfHwge307XG4gICAgaWYodmFsdWUpIHtcbiAgICAgIG9iai52ZW5kb3JFeHRlbnNpb25zW2tleW5hbWVdID0gdmFsdWU7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgb2JqLnZlbmRvckV4dGVuc2lvbnNba2V5bmFtZV0gPSBvYmpba2V5bmFtZV07XG4gICAgfVxuICB9XG59O1xufSkuY2FsbCh0aGlzLHJlcXVpcmUoJ19wcm9jZXNzJykpXG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldDp1dGYtODtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5b1pXeHdaWEp6TG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN1FVRkJRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRWlMQ0ptYVd4bElqb2laMlZ1WlhKaGRHVmtMbXB6SWl3aWMyOTFjbU5sVW05dmRDSTZJaUlzSW5OdmRYSmpaWE5EYjI1MFpXNTBJanBiSWlkMWMyVWdjM1J5YVdOMEp6dGNibHh1ZG1GeUlGOGdQU0I3WEc0Z0lHbHpVR3hoYVc1UFltcGxZM1E2SUhKbGNYVnBjbVVvSjJ4dlpHRnphQzFqYjIxd1lYUXZiR0Z1Wnk5cGMxQnNZV2x1VDJKcVpXTjBKeWtzWEc0Z0lHbHVaR1Y0VDJZNklISmxjWFZwY21Vb0oyeHZaR0Z6YUMxamIyMXdZWFF2WVhKeVlYa3ZhVzVrWlhoUFppY3BYRzU5TzF4dVhHNXRiMlIxYkdVdVpYaHdiM0owY3k1ZlgySnBibVFnUFNCbWRXNWpkR2x2YmlBb1ptNHNJRzFsS1NCN1hHNGdJSEpsZEhWeWJpQm1kVzVqZEdsdmJpZ3BlMXh1SUNBZ0lISmxkSFZ5YmlCbWJpNWhjSEJzZVNodFpTd2dZWEpuZFcxbGJuUnpLVHRjYmlBZ2ZUdGNibjA3WEc1Y2JuWmhjaUJzYjJjZ1BTQnRiMlIxYkdVdVpYaHdiM0owY3k1c2IyY2dQU0JtZFc1amRHbHZiaWdwSUh0Y2JpQWdMeThnVDI1c2VTQnNiMmNnYVdZZ1lYWmhhV3hoWW14bElHRnVaQ0IzWlNkeVpTQnViM1FnZEdWemRHbHVaMXh1SUNCcFppQW9ZMjl1YzI5c1pTQW1KaUJ3Y205alpYTnpMbVZ1ZGk1T1QwUkZYMFZPVmlBaFBUMGdKM1JsYzNRbktTQjdYRzRnSUNBZ1kyOXVjMjlzWlM1c2IyY29RWEp5WVhrdWNISnZkRzkwZVhCbExuTnNhV05sTG1OaGJHd29ZWEpuZFcxbGJuUnpLVnN3WFNrN1hHNGdJSDFjYm4wN1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SekxtWmhhV3dnUFNCbWRXNWpkR2x2YmlBb2JXVnpjMkZuWlNrZ2UxeHVJQ0JzYjJjb2JXVnpjMkZuWlNrN1hHNTlPMXh1WEc1dGIyUjFiR1V1Wlhod2IzSjBjeTV2Y0hScGIyNUlkRzFzSUQwZ1puVnVZM1JwYjI0Z0tHeGhZbVZzTENCMllXeDFaU2tnZTF4dUlDQnlaWFIxY200Z0p6eDBjajQ4ZEdRZ1kyeGhjM005WENKdmNIUnBiMjVPWVcxbFhDSStKeUFySUd4aFltVnNJQ3NnSnpvOEwzUmtQangwWkQ0bklDc2dkbUZzZFdVZ0t5QW5QQzkwWkQ0OEwzUnlQaWM3WEc1OU8xeHVYRzUyWVhJZ2NtVnpiMngyWlZOamFHVnRZU0E5SUcxdlpIVnNaUzVsZUhCdmNuUnpMbkpsYzI5c2RtVlRZMmhsYldFZ1BTQm1kVzVqZEdsdmJpQW9jMk5vWlcxaEtTQjdYRzRnSUdsbUlDaGZMbWx6VUd4aGFXNVBZbXBsWTNRb2MyTm9aVzFoTG5OamFHVnRZU2twSUh0Y2JpQWdJQ0J6WTJobGJXRWdQU0J5WlhOdmJIWmxVMk5vWlcxaEtITmphR1Z0WVM1elkyaGxiV0VwTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUhOamFHVnRZVHRjYm4wN1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SekxuTnBiWEJzWlZKbFppQTlJR1oxYm1OMGFXOXVJQ2h1WVcxbEtTQjdYRzRnSUdsbUlDaDBlWEJsYjJZZ2JtRnRaU0E5UFQwZ0ozVnVaR1ZtYVc1bFpDY3BJSHRjYmlBZ0lDQnlaWFIxY200Z2JuVnNiRHRjYmlBZ2ZWeHVYRzRnSUdsbUlDaHVZVzFsTG1sdVpHVjRUMllvSnlNdlpHVm1hVzVwZEdsdmJuTXZKeWtnUFQwOUlEQXBJSHRjYmlBZ0lDQnlaWFIxY200Z2JtRnRaUzV6ZFdKemRISnBibWNvSnlNdlpHVm1hVzVwZEdsdmJuTXZKeTVzWlc1bmRHZ3BPMXh1SUNCOUlHVnNjMlVnZTF4dUlDQWdJSEpsZEhWeWJpQnVZVzFsTzF4dUlDQjlYRzU5TzF4dVhHNHZLaXBjYmlBcUlHaGxiSEJsY2lCMGJ5QnlaVzF2ZG1VZ1pYaDBaVzV6YVc5dWN5QmhibVFnWVdSa0lIUm9aVzBnZEc4Z1lXNGdiMkpxWldOMFhHNGdLbHh1SUNvZ1FIQmhjbUZ0SUd0bGVXNWhiV1ZjYmlBcUlFQndZWEpoYlNCdlltcGNiaUFxTDF4dWJXOWtkV3hsTG1WNGNHOXlkSE11WlhoMGNtRmpkRVY0ZEdWdWMybHZibk1nUFNCbWRXNWpkR2x2YmlBb2EyVjVibUZ0WlN3Z2IySnFMQ0IyWVd4MVpTa2dlMXh1SUNCcFppZ2hhMlY1Ym1GdFpTQjhmQ0FoYjJKcUtTQjdYRzRnSUNBZ2NtVjBkWEp1TzF4dUlDQjlYRzVjYmlBZ2FXWWdLSFI1Y0dWdlppQnJaWGx1WVcxbElEMDlQU0FuYzNSeWFXNW5KeUFtSmlCclpYbHVZVzFsTG1sdVpHVjRUMllvSjNndEp5a2dQVDA5SURBcElIdGNiaUFnSUNCdlltb3VkbVZ1Wkc5eVJYaDBaVzV6YVc5dWN5QTlJRzlpYWk1MlpXNWtiM0pGZUhSbGJuTnBiMjV6SUh4OElIdDlPMXh1SUNBZ0lHbG1LSFpoYkhWbEtTQjdYRzRnSUNBZ0lDQnZZbW91ZG1WdVpHOXlSWGgwWlc1emFXOXVjMXRyWlhsdVlXMWxYU0E5SUhaaGJIVmxPMXh1SUNBZ0lIMWNiaUFnSUNCbGJITmxJSHRjYmlBZ0lDQWdJRzlpYWk1MlpXNWtiM0pGZUhSbGJuTnBiMjV6VzJ0bGVXNWhiV1ZkSUQwZ2IySnFXMnRsZVc1aGJXVmRPMXh1SUNBZ0lIMWNiaUFnZlZ4dWZUc2lYWDA9IiwiKGZ1bmN0aW9uIChCdWZmZXIpe1xuJ3VzZSBzdHJpY3QnO1xuXG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4vaGVscGVycycpO1xudmFyIHJlcXVlc3QgPSByZXF1aXJlKCdzdXBlcmFnZW50Jyk7XG52YXIganN5YW1sID0gcmVxdWlyZSgnanMteWFtbCcpO1xudmFyIF8gPSB7XG4gIGlzT2JqZWN0OiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvaXNPYmplY3QnKSxcbiAga2V5czogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9vYmplY3Qva2V5cycpXG59O1xuXG4vKlxuICogSlF1ZXJ5SHR0cENsaWVudCBpcyBhIGxpZ2h0LXdlaWdodCwgbm9kZSBvciBicm93c2VyIEhUVFAgY2xpZW50XG4gKi9cbnZhciBKUXVlcnlIdHRwQ2xpZW50ID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLnR5cGUgPSAnSlF1ZXJ5SHR0cENsaWVudCc7XG59O1xuXG4vKlxuICogU3VwZXJhZ2VudEh0dHBDbGllbnQgaXMgYSBsaWdodC13ZWlnaHQsIG5vZGUgb3IgYnJvd3NlciBIVFRQIGNsaWVudFxuICovXG52YXIgU3VwZXJhZ2VudEh0dHBDbGllbnQgPSBmdW5jdGlvbiAoKSB7XG4gIHRoaXMudHlwZSA9ICdTdXBlcmFnZW50SHR0cENsaWVudCc7XG59O1xuXG4vKipcbiAqIFN3YWdnZXJIdHRwIGlzIGEgd3JhcHBlciBmb3IgZXhlY3V0aW5nIHJlcXVlc3RzXG4gKi9cbnZhciBTd2FnZ2VySHR0cCA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge307XG5cblN3YWdnZXJIdHRwLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKG9iaiwgb3B0cykge1xuICB2YXIgY2xpZW50O1xuXG4gIGlmKG9wdHMgJiYgb3B0cy5jbGllbnQpIHtcbiAgICBjbGllbnQgPSBvcHRzLmNsaWVudDtcbiAgfVxuICBlbHNlIHtcbiAgICBjbGllbnQgPSBuZXcgU3VwZXJhZ2VudEh0dHBDbGllbnQob3B0cyk7XG4gIH1cbiAgY2xpZW50Lm9wdHMgPSBvcHRzIHx8IHt9O1xuXG4gIGlmIChvcHRzICYmIG9wdHMucmVxdWVzdEFnZW50KSB7XG4gICAgcmVxdWVzdCA9IG9wdHMucmVxdWVzdEFnZW50O1xuICB9XG5cbiAgLy8gbGVnYWN5IHN1cHBvcnRcbiAgdmFyIGhhc0pRdWVyeSA9IGZhbHNlO1xuICBpZih0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgIGlmKHR5cGVvZiB3aW5kb3cualF1ZXJ5ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgaGFzSlF1ZXJ5ID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgLy8gT1BUSU9OUyBzdXBwb3J0XG4gIGlmKG9iai5tZXRob2QudG9Mb3dlckNhc2UoKSA9PT0gJ29wdGlvbnMnICYmIGNsaWVudC50eXBlID09PSAnU3VwZXJhZ2VudEh0dHBDbGllbnQnKSB7XG4gICAgbG9nKCdmb3JjaW5nIGpRdWVyeSBhcyBPUFRJT05TIGFyZSBub3Qgc3VwcG9ydGVkIGJ5IFN1cGVyQWdlbnQnKTtcbiAgICBvYmoudXNlSlF1ZXJ5ID0gdHJ1ZTtcbiAgfVxuICBpZih0aGlzLmlzSW50ZXJuZXRFeHBsb3JlcigpICYmIChvYmoudXNlSlF1ZXJ5ID09PSBmYWxzZSB8fCAhaGFzSlF1ZXJ5ICkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vuc3VwcG9ydGVkIGNvbmZpZ3VyYXRpb24hIEpRdWVyeSBpcyByZXF1aXJlZCBidXQgbm90IGF2YWlsYWJsZScpO1xuICB9XG4gIGlmICgob2JqICYmIG9iai51c2VKUXVlcnkgPT09IHRydWUpIHx8IHRoaXMuaXNJbnRlcm5ldEV4cGxvcmVyKCkgJiYgaGFzSlF1ZXJ5KSB7XG4gICAgY2xpZW50ID0gbmV3IEpRdWVyeUh0dHBDbGllbnQob3B0cyk7XG4gIH1cblxuICB2YXIgc3VjY2VzcyA9IG9iai5vbi5yZXNwb25zZTtcbiAgdmFyIGVycm9yID0gb2JqLm9uLmVycm9yO1xuXG4gIHZhciByZXF1ZXN0SW50ZXJjZXB0b3IgPSBmdW5jdGlvbihkYXRhKSB7XG4gICAgaWYob3B0cyAmJiBvcHRzLnJlcXVlc3RJbnRlcmNlcHRvcikge1xuICAgICAgZGF0YSA9IG9wdHMucmVxdWVzdEludGVyY2VwdG9yLmFwcGx5KGRhdGEpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0YTtcbiAgfTtcblxuICB2YXIgcmVzcG9uc2VJbnRlcmNlcHRvciA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICBpZihvcHRzICYmIG9wdHMucmVzcG9uc2VJbnRlcmNlcHRvcikge1xuICAgICAgZGF0YSA9IG9wdHMucmVzcG9uc2VJbnRlcmNlcHRvci5hcHBseShkYXRhLCBbb2JqXSk7XG4gICAgfVxuICAgIHJldHVybiBzdWNjZXNzKGRhdGEpO1xuICB9O1xuXG4gIHZhciBlcnJvckludGVyY2VwdG9yID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIGlmKG9wdHMgJiYgb3B0cy5yZXNwb25zZUludGVyY2VwdG9yKSB7XG4gICAgICBkYXRhID0gb3B0cy5yZXNwb25zZUludGVyY2VwdG9yLmFwcGx5KGRhdGEsIFtvYmpdKTtcbiAgICB9XG4gICAgZXJyb3IoZGF0YSk7XG4gIH07XG5cbiAgb2JqLm9uLmVycm9yID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIGVycm9ySW50ZXJjZXB0b3IoZGF0YSk7XG4gIH07XG5cbiAgb2JqLm9uLnJlc3BvbnNlID0gZnVuY3Rpb24oZGF0YSkge1xuICAgIGlmKGRhdGEgJiYgZGF0YS5zdGF0dXMgPj0gNDAwKSB7XG4gICAgICBlcnJvckludGVyY2VwdG9yKGRhdGEpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHJlc3BvbnNlSW50ZXJjZXB0b3IoZGF0YSk7XG4gICAgfVxuICB9O1xuXG4gIGlmIChfLmlzT2JqZWN0KG9iaikgJiYgXy5pc09iamVjdChvYmouYm9keSkpIHtcbiAgICAvLyBzcGVjaWFsIHByb2Nlc3NpbmcgZm9yIGZpbGUgdXBsb2FkcyB2aWEganF1ZXJ5XG4gICAgaWYgKG9iai5ib2R5LnR5cGUgJiYgb2JqLmJvZHkudHlwZSA9PT0gJ2Zvcm1EYXRhJyl7XG4gICAgICBpZihvcHRzLnVzZUpRdWVyeSkge1xuICAgICAgICBvYmouY29udGVudFR5cGUgPSBmYWxzZTtcbiAgICAgICAgb2JqLnByb2Nlc3NEYXRhID0gZmFsc2U7XG4gICAgICAgIGRlbGV0ZSBvYmouaGVhZGVyc1snQ29udGVudC1UeXBlJ107XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgb2JqID0gcmVxdWVzdEludGVyY2VwdG9yKG9iaikgfHwgb2JqO1xuICBpZiAob2JqLmJlZm9yZVNlbmQpIHtcbiAgICBvYmouYmVmb3JlU2VuZChmdW5jdGlvbihfb2JqKSB7XG4gICAgICBjbGllbnQuZXhlY3V0ZShfb2JqIHx8IG9iaik7XG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgY2xpZW50LmV4ZWN1dGUob2JqKTtcbiAgfVxuXG4gIHJldHVybiAob2JqLmRlZmVycmVkKSA/IG9iai5kZWZlcnJlZC5wcm9taXNlIDogb2JqO1xufTtcblxuU3dhZ2dlckh0dHAucHJvdG90eXBlLmlzSW50ZXJuZXRFeHBsb3JlciA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGRldGVjdGVkSUUgPSBmYWxzZTtcblxuICBpZiAodHlwZW9mIG5hdmlnYXRvciAhPT0gJ3VuZGVmaW5lZCcgJiYgbmF2aWdhdG9yLnVzZXJBZ2VudCkge1xuICAgIHZhciBuYXYgPSBuYXZpZ2F0b3IudXNlckFnZW50LnRvTG93ZXJDYXNlKCk7XG5cbiAgICBpZiAobmF2LmluZGV4T2YoJ21zaWUnKSAhPT0gLTEpIHtcbiAgICAgIHZhciB2ZXJzaW9uID0gcGFyc2VJbnQobmF2LnNwbGl0KCdtc2llJylbMV0pO1xuXG4gICAgICBpZiAodmVyc2lvbiA8PSA4KSB7XG4gICAgICAgIGRldGVjdGVkSUUgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBkZXRlY3RlZElFO1xufTtcblxuSlF1ZXJ5SHR0cENsaWVudC5wcm90b3R5cGUuZXhlY3V0ZSA9IGZ1bmN0aW9uIChvYmopIHtcbiAgdmFyIGpxID0gdGhpcy5qUXVlcnkgfHwgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5qUXVlcnkpO1xuICB2YXIgY2IgPSBvYmoub247XG4gIHZhciByZXF1ZXN0ID0gb2JqO1xuXG4gIGlmKHR5cGVvZiBqcSA9PT0gJ3VuZGVmaW5lZCcgfHwganEgPT09IGZhbHNlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdVbnN1cHBvcnRlZCBjb25maWd1cmF0aW9uISBKUXVlcnkgaXMgcmVxdWlyZWQgYnV0IG5vdCBhdmFpbGFibGUnKTtcbiAgfVxuXG4gIG9iai50eXBlID0gb2JqLm1ldGhvZDtcbiAgb2JqLmNhY2hlID0gb2JqLmpxdWVyeUFqYXhDYWNoZTtcbiAgb2JqLmRhdGEgPSBvYmouYm9keTtcbiAgZGVsZXRlIG9iai5qcXVlcnlBamF4Q2FjaGU7XG4gIGRlbGV0ZSBvYmoudXNlSlF1ZXJ5O1xuICBkZWxldGUgb2JqLmJvZHk7XG5cbiAgb2JqLmNvbXBsZXRlID0gZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgdmFyIGhlYWRlcnMgPSB7fTtcbiAgICB2YXIgaGVhZGVyQXJyYXkgPSByZXNwb25zZS5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKS5zcGxpdCgnXFxuJyk7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGhlYWRlckFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgdG9TcGxpdCA9IGhlYWRlckFycmF5W2ldLnRyaW0oKTtcblxuICAgICAgaWYgKHRvU3BsaXQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB2YXIgc2VwYXJhdG9yID0gdG9TcGxpdC5pbmRleE9mKCc6Jyk7XG5cbiAgICAgIGlmIChzZXBhcmF0b3IgPT09IC0xKSB7XG4gICAgICAgIC8vIE5hbWUgYnV0IG5vIHZhbHVlIGluIHRoZSBoZWFkZXJcbiAgICAgICAgaGVhZGVyc1t0b1NwbGl0XSA9IG51bGw7XG5cbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIHZhciBuYW1lID0gdG9TcGxpdC5zdWJzdHJpbmcoMCwgc2VwYXJhdG9yKS50cmltKCk7XG4gICAgICB2YXIgdmFsdWUgPSB0b1NwbGl0LnN1YnN0cmluZyhzZXBhcmF0b3IgKyAxKS50cmltKCk7XG5cbiAgICAgIGhlYWRlcnNbbmFtZV0gPSB2YWx1ZTtcbiAgICB9XG5cbiAgICB2YXIgb3V0ID0ge1xuICAgICAgdXJsOiByZXF1ZXN0LnVybCxcbiAgICAgIG1ldGhvZDogcmVxdWVzdC5tZXRob2QsXG4gICAgICBzdGF0dXM6IHJlc3BvbnNlLnN0YXR1cyxcbiAgICAgIHN0YXR1c1RleHQ6IHJlc3BvbnNlLnN0YXR1c1RleHQsXG4gICAgICBkYXRhOiByZXNwb25zZS5yZXNwb25zZVRleHQsXG4gICAgICBoZWFkZXJzOiBoZWFkZXJzXG4gICAgfTtcblxuICAgIHRyeSB7XG4gICAgICB2YXIgcG9zc2libGVPYmogPSAgcmVzcG9uc2UucmVzcG9uc2VKU09OIHx8IGpzeWFtbC5zYWZlTG9hZChyZXNwb25zZS5yZXNwb25zZVRleHQpO1xuICAgICAgb3V0Lm9iaiA9ICh0eXBlb2YgcG9zc2libGVPYmogPT09ICdzdHJpbmcnKSA/IHt9IDogcG9zc2libGVPYmo7XG4gICAgfSBjYXRjaCAoZXgpIHtcbiAgICAgIC8vIGRvIG5vdCBzZXQgb3V0Lm9ialxuICAgICAgaGVscGVycy5sb2coJ3VuYWJsZSB0byBwYXJzZSBKU09OL1lBTUwgY29udGVudCcpO1xuICAgIH1cblxuICAgIC8vIEkgY2FuIHRocm93LCBvciBwYXJzZSBudWxsP1xuICAgIG91dC5vYmogPSBvdXQub2JqIHx8IG51bGw7XG5cbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID49IDIwMCAmJiByZXNwb25zZS5zdGF0dXMgPCAzMDApIHtcbiAgICAgIGNiLnJlc3BvbnNlKG91dCk7XG4gICAgfSBlbHNlIGlmIChyZXNwb25zZS5zdGF0dXMgPT09IDAgfHwgKHJlc3BvbnNlLnN0YXR1cyA+PSA0MDAgJiYgcmVzcG9uc2Uuc3RhdHVzIDwgNTk5KSkge1xuICAgICAgY2IuZXJyb3Iob3V0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNiLnJlc3BvbnNlKG91dCk7XG4gICAgfVxuICB9O1xuXG4gIGpxLnN1cHBvcnQuY29ycyA9IHRydWU7XG5cbiAgcmV0dXJuIGpxLmFqYXgob2JqKTtcbn07XG5cblN1cGVyYWdlbnRIdHRwQ2xpZW50LnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKG9iaikge1xuICB2YXIgbWV0aG9kID0gb2JqLm1ldGhvZC50b0xvd2VyQ2FzZSgpO1xuICB2YXIgdGltZW91dCA9IG9iai50aW1lb3V0O1xuXG4gIGlmIChtZXRob2QgPT09ICdkZWxldGUnKSB7XG4gICAgbWV0aG9kID0gJ2RlbCc7XG4gIH1cbiAgdmFyIGhlYWRlcnMgPSBvYmouaGVhZGVycyB8fCB7fTtcblxuICB2YXIgciA9IHJlcXVlc3RbbWV0aG9kXShvYmoudXJsKTtcblxuICBpZiAob2JqLmNvbm5lY3Rpb25BZ2VudCkge1xuICAgIHIuYWdlbnQob2JqLmNvbm5lY3Rpb25BZ2VudCk7XG4gIH1cblxuICBpZiAodGltZW91dCkge1xuICAgIHIudGltZW91dCh0aW1lb3V0KTtcbiAgfVxuXG4gIGlmIChvYmouZW5hYmxlQ29va2llcykge1xuICAgIHIud2l0aENyZWRlbnRpYWxzKCk7XG4gIH1cblxuICB2YXIgYWNjZXB0ID0gb2JqLmhlYWRlcnMuQWNjZXB0O1xuXG4gIGlmKHRoaXMuYmluYXJ5UmVxdWVzdChhY2NlcHQpKSB7XG4gICAgci5vbigncmVxdWVzdCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmKHRoaXMueGhyKSB7XG4gICAgICAgIHRoaXMueGhyLnJlc3BvbnNlVHlwZSA9ICdibG9iJztcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGlmKG9iai5ib2R5KSB7XG4gICAgaWYoXy5pc09iamVjdChvYmouYm9keSkpIHtcbiAgICAgIHZhciBjb250ZW50VHlwZSA9IG9iai5oZWFkZXJzWydDb250ZW50LVR5cGUnXSB8fCAnJztcbiAgICAgIGlmIChjb250ZW50VHlwZS5pbmRleE9mKCdtdWx0aXBhcnQvZm9ybS1kYXRhJykgPT09IDApIHtcbiAgICAgICAgZGVsZXRlIGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddO1xuICAgICAgICBpZih7fS50b1N0cmluZy5hcHBseShvYmouYm9keSkgPT09ICdbb2JqZWN0IEZvcm1EYXRhXScpIHtcbiAgICAgICAgICByLnNlbmQob2JqLmJvZHkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHZhciBrZXluYW1lLCB2YWx1ZSwgdjtcbiAgICAgICAgICBmb3IgKGtleW5hbWUgaW4gb2JqLmJvZHkpIHtcbiAgICAgICAgICAgIHZhbHVlID0gb2JqLmJvZHlba2V5bmFtZV07XG4gICAgICAgICAgICBpZihBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgICAgICBmb3IodiBpbiB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHIuZmllbGQoa2V5bmFtZSwgdik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICByLmZpZWxkKGtleW5hbWUsIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsc2UgaWYgKF8uaXNPYmplY3Qob2JqLmJvZHkpKSB7XG4gICAgICAgIC8vIG5vbiBtdWx0aXBhcnQvZm9ybS1kYXRhXG4gICAgICAgIG9iai5ib2R5ID0gSlNPTi5zdHJpbmdpZnkob2JqLmJvZHkpO1xuICAgICAgICByLnNlbmQob2JqLmJvZHkpO1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHIuc2VuZChvYmouYm9keSk7XG4gICAgfVxuICB9XG5cbiAgdmFyIG5hbWU7XG4gIGZvciAobmFtZSBpbiBoZWFkZXJzKSB7XG4gICAgci5zZXQobmFtZSwgaGVhZGVyc1tuYW1lXSk7XG4gIH1cblxuICBpZih0eXBlb2Ygci5idWZmZXIgPT09ICdmdW5jdGlvbicpIHtcbiAgICByLmJ1ZmZlcigpOyAvLyBmb3JjZSBzdXBlcmFnZW50IHRvIHBvcHVsYXRlIHJlcy50ZXh0IHdpdGggdGhlIHJhdyByZXNwb25zZSBkYXRhXG4gIH1cblxuICByLmVuZChmdW5jdGlvbiAoZXJyLCByZXMpIHtcbiAgICByZXMgPSByZXMgfHwge1xuICAgICAgc3RhdHVzOiAwLFxuICAgICAgaGVhZGVyczoge2Vycm9yOiAnbm8gcmVzcG9uc2UgZnJvbSBzZXJ2ZXInfVxuICAgIH07XG4gICAgdmFyIHJlc3BvbnNlID0ge1xuICAgICAgdXJsOiBvYmoudXJsLFxuICAgICAgbWV0aG9kOiBvYmoubWV0aG9kLFxuICAgICAgaGVhZGVyczogcmVzLmhlYWRlcnNcbiAgICB9O1xuICAgIHZhciBjYjtcblxuICAgIGlmICghZXJyICYmIHJlcy5lcnJvcikge1xuICAgICAgZXJyID0gcmVzLmVycm9yO1xuICAgIH1cblxuICAgIGlmIChlcnIgJiYgb2JqLm9uICYmIG9iai5vbi5lcnJvcikge1xuICAgICAgcmVzcG9uc2UuZXJyT2JqID0gZXJyO1xuICAgICAgcmVzcG9uc2Uuc3RhdHVzID0gcmVzID8gcmVzLnN0YXR1cyA6IDUwMDtcbiAgICAgIHJlc3BvbnNlLnN0YXR1c1RleHQgPSByZXMgPyByZXMudGV4dCA6IGVyci5tZXNzYWdlO1xuICAgICAgaWYgKHJlcy5oZWFkZXJzICYmIHJlcy5oZWFkZXJzWydjb250ZW50LXR5cGUnXSkge1xuICAgICAgICBpZiAocmVzLmhlYWRlcnNbJ2NvbnRlbnQtdHlwZSddLmluZGV4T2YoJ2FwcGxpY2F0aW9uL2pzb24nKSA+PSAwKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJlc3BvbnNlLm9iaiA9IEpTT04ucGFyc2UocmVzcG9uc2Uuc3RhdHVzVGV4dCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXNwb25zZS5vYmogPSBudWxsO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY2IgPSBvYmoub24uZXJyb3I7XG4gICAgfSBlbHNlIGlmIChyZXMgJiYgb2JqLm9uICYmIG9iai5vbi5yZXNwb25zZSkge1xuICAgICAgdmFyIHBvc3NpYmxlT2JqO1xuXG4gICAgICAvLyBBbHJlYWR5IHBhcnNlZCBieSBieSBzdXBlcmFnZW50P1xuICAgICAgaWYgKHJlcy5ib2R5ICYmIF8ua2V5cyhyZXMuYm9keSkubGVuZ3RoID4gMCkge1xuICAgICAgICBwb3NzaWJsZU9iaiA9IHJlcy5ib2R5O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBwb3NzaWJsZU9iaiA9IGpzeWFtbC5zYWZlTG9hZChyZXMudGV4dCk7XG4gICAgICAgICAgLy8gY2FuIHBhcnNlIGludG8gYSBzdHJpbmcuLi4gd2hpY2ggd2UgZG9uJ3QgbmVlZCBydW5uaW5nIGFyb3VuZCBpbiB0aGUgc3lzdGVtXG4gICAgICAgICAgcG9zc2libGVPYmogPSAodHlwZW9mIHBvc3NpYmxlT2JqID09PSAnc3RyaW5nJykgPyBudWxsIDogcG9zc2libGVPYmo7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBoZWxwZXJzLmxvZygnY2Fubm90IHBhcnNlIEpTT04vWUFNTCBjb250ZW50Jyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gbnVsbCBtZWFucyB3ZSBjYW4ndCBwYXJzZSBpbnRvIG9iamVjdFxuICAgICAgaWYodHlwZW9mIEJ1ZmZlciA9PT0gJ2Z1bmN0aW9uJyAmJiBCdWZmZXIuaXNCdWZmZXIocG9zc2libGVPYmopKSB7XG4gICAgICAgIHJlc3BvbnNlLmRhdGEgPSBwb3NzaWJsZU9iajtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICByZXNwb25zZS5vYmogPSAodHlwZW9mIHBvc3NpYmxlT2JqID09PSAnb2JqZWN0JykgPyBwb3NzaWJsZU9iaiA6IG51bGw7XG4gICAgICB9XG5cbiAgICAgIHJlc3BvbnNlLnN0YXR1cyA9IHJlcy5zdGF0dXM7XG4gICAgICByZXNwb25zZS5zdGF0dXNUZXh0ID0gcmVzLnRleHQ7XG4gICAgICBjYiA9IG9iai5vbi5yZXNwb25zZTtcbiAgICB9XG4gICAgaWYgKHJlcy54aHIgJiYgcmVzLnhoci5yZXNwb25zZSkge1xuICAgICAgcmVzcG9uc2UuZGF0YSA9IHJlcy54aHIucmVzcG9uc2U7XG4gICAgfVxuICAgIGVsc2UgaWYoIXJlc3BvbnNlLmRhdGEpIHtcbiAgICAgIHJlc3BvbnNlLmRhdGEgPSByZXNwb25zZS5zdGF0dXNUZXh0O1xuICAgIH1cblxuICAgIGlmIChjYikge1xuICAgICAgY2IocmVzcG9uc2UpO1xuICAgIH1cbiAgfSk7XG59O1xuXG5TdXBlcmFnZW50SHR0cENsaWVudC5wcm90b3R5cGUuIGJpbmFyeVJlcXVlc3QgPSBmdW5jdGlvbiAoYWNjZXB0KSB7XG4gIGlmKCFhY2NlcHQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuICgvXmltYWdlL2kpLnRlc3QoYWNjZXB0KVxuICAgIHx8ICgvXmFwcGxpY2F0aW9uXFwvcGRmLykudGVzdChhY2NlcHQpXG4gICAgfHwgKC9eYXBwbGljYXRpb25cXC9vY3RldC1zdHJlYW0vKS50ZXN0KGFjY2VwdCk7XG59O1xuXG59KS5jYWxsKHRoaXMscmVxdWlyZShcImJ1ZmZlclwiKS5CdWZmZXIpXG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldDp1dGYtODtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbXhwWWk5b2RIUndMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGQlFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJJaXdpWm1sc1pTSTZJbWRsYm1WeVlYUmxaQzVxY3lJc0luTnZkWEpqWlZKdmIzUWlPaUlpTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lJbmRYTmxJSE4wY21samRDYzdYRzVjYm5aaGNpQm9aV3h3WlhKeklEMGdjbVZ4ZFdseVpTZ25MaTlvWld4d1pYSnpKeWs3WEc1MllYSWdjbVZ4ZFdWemRDQTlJSEpsY1hWcGNtVW9KM04xY0dWeVlXZGxiblFuS1R0Y2JuWmhjaUJxYzNsaGJXd2dQU0J5WlhGMWFYSmxLQ2RxY3kxNVlXMXNKeWs3WEc1MllYSWdYeUE5SUh0Y2JpQWdhWE5QWW1wbFkzUTZJSEpsY1hWcGNtVW9KMnh2WkdGemFDMWpiMjF3WVhRdmJHRnVaeTlwYzA5aWFtVmpkQ2NwTEZ4dUlDQnJaWGx6T2lCeVpYRjFhWEpsS0Nkc2IyUmhjMmd0WTI5dGNHRjBMMjlpYW1WamRDOXJaWGx6SnlsY2JuMDdYRzVjYmk4cVhHNGdLaUJLVVhWbGNubElkSFJ3UTJ4cFpXNTBJR2x6SUdFZ2JHbG5hSFF0ZDJWcFoyaDBMQ0J1YjJSbElHOXlJR0p5YjNkelpYSWdTRlJVVUNCamJHbGxiblJjYmlBcUwxeHVkbUZ5SUVwUmRXVnllVWgwZEhCRGJHbGxiblFnUFNCbWRXNWpkR2x2YmlBb0tTQjdYRzRnSUhSb2FYTXVkSGx3WlNBOUlDZEtVWFZsY25sSWRIUndRMnhwWlc1MEp6dGNibjA3WEc1Y2JpOHFYRzRnS2lCVGRYQmxjbUZuWlc1MFNIUjBjRU5zYVdWdWRDQnBjeUJoSUd4cFoyaDBMWGRsYVdkb2RDd2dibTlrWlNCdmNpQmljbTkzYzJWeUlFaFVWRkFnWTJ4cFpXNTBYRzRnS2k5Y2JuWmhjaUJUZFhCbGNtRm5aVzUwU0hSMGNFTnNhV1Z1ZENBOUlHWjFibU4wYVc5dUlDZ3BJSHRjYmlBZ2RHaHBjeTUwZVhCbElEMGdKMU4xY0dWeVlXZGxiblJJZEhSd1EyeHBaVzUwSnp0Y2JuMDdYRzVjYmk4cUtseHVJQ29nVTNkaFoyZGxja2gwZEhBZ2FYTWdZU0IzY21Gd2NHVnlJR1p2Y2lCbGVHVmpkWFJwYm1jZ2NtVnhkV1Z6ZEhOY2JpQXFMMXh1ZG1GeUlGTjNZV2RuWlhKSWRIUndJRDBnYlc5a2RXeGxMbVY0Y0c5eWRITWdQU0JtZFc1amRHbHZiaUFvS1NCN2ZUdGNibHh1VTNkaFoyZGxja2gwZEhBdWNISnZkRzkwZVhCbExtVjRaV04xZEdVZ1BTQm1kVzVqZEdsdmJpQW9iMkpxTENCdmNIUnpLU0I3WEc0Z0lIWmhjaUJqYkdsbGJuUTdYRzVjYmlBZ2FXWW9iM0IwY3lBbUppQnZjSFJ6TG1Oc2FXVnVkQ2tnZTF4dUlDQWdJR05zYVdWdWRDQTlJRzl3ZEhNdVkyeHBaVzUwTzF4dUlDQjlYRzRnSUdWc2MyVWdlMXh1SUNBZ0lHTnNhV1Z1ZENBOUlHNWxkeUJUZFhCbGNtRm5aVzUwU0hSMGNFTnNhV1Z1ZENodmNIUnpLVHRjYmlBZ2ZWeHVJQ0JqYkdsbGJuUXViM0IwY3lBOUlHOXdkSE1nZkh3Z2UzMDdYRzVjYmlBZ2FXWWdLRzl3ZEhNZ0ppWWdiM0IwY3k1eVpYRjFaWE4wUVdkbGJuUXBJSHRjYmlBZ0lDQnlaWEYxWlhOMElEMGdiM0IwY3k1eVpYRjFaWE4wUVdkbGJuUTdYRzRnSUgxY2JseHVJQ0F2THlCc1pXZGhZM2tnYzNWd2NHOXlkRnh1SUNCMllYSWdhR0Z6U2xGMVpYSjVJRDBnWm1Gc2MyVTdYRzRnSUdsbUtIUjVjR1Z2WmlCM2FXNWtiM2NnSVQwOUlDZDFibVJsWm1sdVpXUW5LU0I3WEc0Z0lDQWdhV1lvZEhsd1pXOW1JSGRwYm1SdmR5NXFVWFZsY25rZ0lUMDlJQ2QxYm1SbFptbHVaV1FuS1NCN1hHNGdJQ0FnSUNCb1lYTktVWFZsY25rZ1BTQjBjblZsTzF4dUlDQWdJSDFjYmlBZ2ZWeHVJQ0F2THlCUFVGUkpUMDVUSUhOMWNIQnZjblJjYmlBZ2FXWW9iMkpxTG0xbGRHaHZaQzUwYjB4dmQyVnlRMkZ6WlNncElEMDlQU0FuYjNCMGFXOXVjeWNnSmlZZ1kyeHBaVzUwTG5SNWNHVWdQVDA5SUNkVGRYQmxjbUZuWlc1MFNIUjBjRU5zYVdWdWRDY3BJSHRjYmlBZ0lDQnNiMmNvSjJadmNtTnBibWNnYWxGMVpYSjVJR0Z6SUU5UVZFbFBUbE1nWVhKbElHNXZkQ0J6ZFhCd2IzSjBaV1FnWW5rZ1UzVndaWEpCWjJWdWRDY3BPMXh1SUNBZ0lHOWlhaTUxYzJWS1VYVmxjbmtnUFNCMGNuVmxPMXh1SUNCOVhHNGdJR2xtS0hSb2FYTXVhWE5KYm5SbGNtNWxkRVY0Y0d4dmNtVnlLQ2tnSmlZZ0tHOWlhaTUxYzJWS1VYVmxjbmtnUFQwOUlHWmhiSE5sSUh4OElDRm9ZWE5LVVhWbGNua2dLU2tnZTF4dUlDQWdJSFJvY205M0lHNWxkeUJGY25KdmNpZ25WVzV6ZFhCd2IzSjBaV1FnWTI5dVptbG5kWEpoZEdsdmJpRWdTbEYxWlhKNUlHbHpJSEpsY1hWcGNtVmtJR0oxZENCdWIzUWdZWFpoYVd4aFlteGxKeWs3WEc0Z0lIMWNiaUFnYVdZZ0tDaHZZbW9nSmlZZ2IySnFMblZ6WlVwUmRXVnllU0E5UFQwZ2RISjFaU2tnZkh3Z2RHaHBjeTVwYzBsdWRHVnlibVYwUlhod2JHOXlaWElvS1NBbUppQm9ZWE5LVVhWbGNua3BJSHRjYmlBZ0lDQmpiR2xsYm5RZ1BTQnVaWGNnU2xGMVpYSjVTSFIwY0VOc2FXVnVkQ2h2Y0hSektUdGNiaUFnZlZ4dVhHNGdJSFpoY2lCemRXTmpaWE56SUQwZ2IySnFMbTl1TG5KbGMzQnZibk5sTzF4dUlDQjJZWElnWlhKeWIzSWdQU0J2WW1vdWIyNHVaWEp5YjNJN1hHNWNiaUFnZG1GeUlISmxjWFZsYzNSSmJuUmxjbU5sY0hSdmNpQTlJR1oxYm1OMGFXOXVLR1JoZEdFcElIdGNiaUFnSUNCcFppaHZjSFJ6SUNZbUlHOXdkSE11Y21WeGRXVnpkRWx1ZEdWeVkyVndkRzl5S1NCN1hHNGdJQ0FnSUNCa1lYUmhJRDBnYjNCMGN5NXlaWEYxWlhOMFNXNTBaWEpqWlhCMGIzSXVZWEJ3Ykhrb1pHRjBZU2s3WEc0Z0lDQWdmVnh1SUNBZ0lISmxkSFZ5YmlCa1lYUmhPMXh1SUNCOU8xeHVYRzRnSUhaaGNpQnlaWE53YjI1elpVbHVkR1Z5WTJWd2RHOXlJRDBnWm5WdVkzUnBiMjRvWkdGMFlTa2dlMXh1SUNBZ0lHbG1LRzl3ZEhNZ0ppWWdiM0IwY3k1eVpYTndiMjV6WlVsdWRHVnlZMlZ3ZEc5eUtTQjdYRzRnSUNBZ0lDQmtZWFJoSUQwZ2IzQjBjeTV5WlhOd2IyNXpaVWx1ZEdWeVkyVndkRzl5TG1Gd2NHeDVLR1JoZEdFc0lGdHZZbXBkS1R0Y2JpQWdJQ0I5WEc0Z0lDQWdjbVYwZFhKdUlITjFZMk5sYzNNb1pHRjBZU2s3WEc0Z0lIMDdYRzVjYmlBZ2RtRnlJR1Z5Y205eVNXNTBaWEpqWlhCMGIzSWdQU0JtZFc1amRHbHZiaWhrWVhSaEtTQjdYRzRnSUNBZ2FXWW9iM0IwY3lBbUppQnZjSFJ6TG5KbGMzQnZibk5sU1c1MFpYSmpaWEIwYjNJcElIdGNiaUFnSUNBZ0lHUmhkR0VnUFNCdmNIUnpMbkpsYzNCdmJuTmxTVzUwWlhKalpYQjBiM0l1WVhCd2JIa29aR0YwWVN3Z1cyOWlhbDBwTzF4dUlDQWdJSDFjYmlBZ0lDQmxjbkp2Y2loa1lYUmhLVHRjYmlBZ2ZUdGNibHh1SUNCdlltb3ViMjR1WlhKeWIzSWdQU0JtZFc1amRHbHZiaWhrWVhSaEtTQjdYRzRnSUNBZ1pYSnliM0pKYm5SbGNtTmxjSFJ2Y2loa1lYUmhLVHRjYmlBZ2ZUdGNibHh1SUNCdlltb3ViMjR1Y21WemNHOXVjMlVnUFNCbWRXNWpkR2x2Ymloa1lYUmhLU0I3WEc0Z0lDQWdhV1lvWkdGMFlTQW1KaUJrWVhSaExuTjBZWFIxY3lBK1BTQTBNREFwSUh0Y2JpQWdJQ0FnSUdWeWNtOXlTVzUwWlhKalpYQjBiM0lvWkdGMFlTazdYRzRnSUNBZ2ZWeHVJQ0FnSUdWc2MyVWdlMXh1SUNBZ0lDQWdjbVZ6Y0c5dWMyVkpiblJsY21ObGNIUnZjaWhrWVhSaEtUdGNiaUFnSUNCOVhHNGdJSDA3WEc1Y2JpQWdhV1lnS0Y4dWFYTlBZbXBsWTNRb2IySnFLU0FtSmlCZkxtbHpUMkpxWldOMEtHOWlhaTVpYjJSNUtTa2dlMXh1SUNBZ0lDOHZJSE53WldOcFlXd2djSEp2WTJWemMybHVaeUJtYjNJZ1ptbHNaU0IxY0d4dllXUnpJSFpwWVNCcWNYVmxjbmxjYmlBZ0lDQnBaaUFvYjJKcUxtSnZaSGt1ZEhsd1pTQW1KaUJ2WW1vdVltOWtlUzUwZVhCbElEMDlQU0FuWm05eWJVUmhkR0VuS1h0Y2JpQWdJQ0FnSUdsbUtHOXdkSE11ZFhObFNsRjFaWEo1S1NCN1hHNGdJQ0FnSUNBZ0lHOWlhaTVqYjI1MFpXNTBWSGx3WlNBOUlHWmhiSE5sTzF4dUlDQWdJQ0FnSUNCdlltb3VjSEp2WTJWemMwUmhkR0VnUFNCbVlXeHpaVHRjYmlBZ0lDQWdJQ0FnWkdWc1pYUmxJRzlpYWk1b1pXRmtaWEp6V3lkRGIyNTBaVzUwTFZSNWNHVW5YVHRjYmlBZ0lDQWdJSDFjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0J2WW1vZ1BTQnlaWEYxWlhOMFNXNTBaWEpqWlhCMGIzSW9iMkpxS1NCOGZDQnZZbW83WEc0Z0lHbG1JQ2h2WW1vdVltVm1iM0psVTJWdVpDa2dlMXh1SUNBZ0lHOWlhaTVpWldadmNtVlRaVzVrS0daMWJtTjBhVzl1S0Y5dlltb3BJSHRjYmlBZ0lDQWdJR05zYVdWdWRDNWxlR1ZqZFhSbEtGOXZZbW9nZkh3Z2IySnFLVHRjYmlBZ0lDQjlLVHRjYmlBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0JqYkdsbGJuUXVaWGhsWTNWMFpTaHZZbW9wTzF4dUlDQjlYRzVjYmlBZ2NtVjBkWEp1SUNodlltb3VaR1ZtWlhKeVpXUXBJRDhnYjJKcUxtUmxabVZ5Y21Wa0xuQnliMjFwYzJVZ09pQnZZbW83WEc1OU8xeHVYRzVUZDJGbloyVnlTSFIwY0M1d2NtOTBiM1I1Y0dVdWFYTkpiblJsY201bGRFVjRjR3h2Y21WeUlEMGdablZ1WTNScGIyNGdLQ2tnZTF4dUlDQjJZWElnWkdWMFpXTjBaV1JKUlNBOUlHWmhiSE5sTzF4dVhHNGdJR2xtSUNoMGVYQmxiMllnYm1GMmFXZGhkRzl5SUNFOVBTQW5kVzVrWldacGJtVmtKeUFtSmlCdVlYWnBaMkYwYjNJdWRYTmxja0ZuWlc1MEtTQjdYRzRnSUNBZ2RtRnlJRzVoZGlBOUlHNWhkbWxuWVhSdmNpNTFjMlZ5UVdkbGJuUXVkRzlNYjNkbGNrTmhjMlVvS1R0Y2JseHVJQ0FnSUdsbUlDaHVZWFl1YVc1a1pYaFBaaWduYlhOcFpTY3BJQ0U5UFNBdE1Ta2dlMXh1SUNBZ0lDQWdkbUZ5SUhabGNuTnBiMjRnUFNCd1lYSnpaVWx1ZENodVlYWXVjM0JzYVhRb0oyMXphV1VuS1ZzeFhTazdYRzVjYmlBZ0lDQWdJR2xtSUNoMlpYSnphVzl1SUR3OUlEZ3BJSHRjYmlBZ0lDQWdJQ0FnWkdWMFpXTjBaV1JKUlNBOUlIUnlkV1U3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1SUNCOVhHNWNiaUFnY21WMGRYSnVJR1JsZEdWamRHVmtTVVU3WEc1OU8xeHVYRzVLVVhWbGNubElkSFJ3UTJ4cFpXNTBMbkJ5YjNSdmRIbHdaUzVsZUdWamRYUmxJRDBnWm5WdVkzUnBiMjRnS0c5aWFpa2dlMXh1SUNCMllYSWdhbkVnUFNCMGFHbHpMbXBSZFdWeWVTQjhmQ0FvZEhsd1pXOW1JSGRwYm1SdmR5QWhQVDBnSjNWdVpHVm1hVzVsWkNjZ0ppWWdkMmx1Wkc5M0xtcFJkV1Z5ZVNrN1hHNGdJSFpoY2lCallpQTlJRzlpYWk1dmJqdGNiaUFnZG1GeUlISmxjWFZsYzNRZ1BTQnZZbW83WEc1Y2JpQWdhV1lvZEhsd1pXOW1JR3B4SUQwOVBTQW5kVzVrWldacGJtVmtKeUI4ZkNCcWNTQTlQVDBnWm1Gc2MyVXBJSHRjYmlBZ0lDQjBhSEp2ZHlCdVpYY2dSWEp5YjNJb0oxVnVjM1Z3Y0c5eWRHVmtJR052Ym1acFozVnlZWFJwYjI0aElFcFJkV1Z5ZVNCcGN5QnlaWEYxYVhKbFpDQmlkWFFnYm05MElHRjJZV2xzWVdKc1pTY3BPMXh1SUNCOVhHNWNiaUFnYjJKcUxuUjVjR1VnUFNCdlltb3ViV1YwYUc5a08xeHVJQ0J2WW1vdVkyRmphR1VnUFNCdlltb3VhbkYxWlhKNVFXcGhlRU5oWTJobE8xeHVJQ0J2WW1vdVpHRjBZU0E5SUc5aWFpNWliMlI1TzF4dUlDQmtaV3hsZEdVZ2IySnFMbXB4ZFdWeWVVRnFZWGhEWVdOb1pUdGNiaUFnWkdWc1pYUmxJRzlpYWk1MWMyVktVWFZsY25rN1hHNGdJR1JsYkdWMFpTQnZZbW91WW05a2VUdGNibHh1SUNCdlltb3VZMjl0Y0d4bGRHVWdQU0JtZFc1amRHbHZiaUFvY21WemNHOXVjMlVwSUh0Y2JpQWdJQ0IyWVhJZ2FHVmhaR1Z5Y3lBOUlIdDlPMXh1SUNBZ0lIWmhjaUJvWldGa1pYSkJjbkpoZVNBOUlISmxjM0J2Ym5ObExtZGxkRUZzYkZKbGMzQnZibk5sU0dWaFpHVnljeWdwTG5Od2JHbDBLQ2RjWEc0bktUdGNibHh1SUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3T3lCcElEd2dhR1ZoWkdWeVFYSnlZWGt1YkdWdVozUm9PeUJwS3lzcElIdGNiaUFnSUNBZ0lIWmhjaUIwYjFOd2JHbDBJRDBnYUdWaFpHVnlRWEp5WVhsYmFWMHVkSEpwYlNncE8xeHVYRzRnSUNBZ0lDQnBaaUFvZEc5VGNHeHBkQzVzWlc1bmRHZ2dQVDA5SURBcElIdGNiaUFnSUNBZ0lDQWdZMjl1ZEdsdWRXVTdYRzRnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJSFpoY2lCelpYQmhjbUYwYjNJZ1BTQjBiMU53YkdsMExtbHVaR1Y0VDJZb0p6b25LVHRjYmx4dUlDQWdJQ0FnYVdZZ0tITmxjR0Z5WVhSdmNpQTlQVDBnTFRFcElIdGNiaUFnSUNBZ0lDQWdMeThnVG1GdFpTQmlkWFFnYm04Z2RtRnNkV1VnYVc0Z2RHaGxJR2hsWVdSbGNseHVJQ0FnSUNBZ0lDQm9aV0ZrWlhKelczUnZVM0JzYVhSZElEMGdiblZzYkR0Y2JseHVJQ0FnSUNBZ0lDQmpiMjUwYVc1MVpUdGNiaUFnSUNBZ0lIMWNibHh1SUNBZ0lDQWdkbUZ5SUc1aGJXVWdQU0IwYjFOd2JHbDBMbk4xWW5OMGNtbHVaeWd3TENCelpYQmhjbUYwYjNJcExuUnlhVzBvS1R0Y2JpQWdJQ0FnSUhaaGNpQjJZV3gxWlNBOUlIUnZVM0JzYVhRdWMzVmljM1J5YVc1bktITmxjR0Z5WVhSdmNpQXJJREVwTG5SeWFXMG9LVHRjYmx4dUlDQWdJQ0FnYUdWaFpHVnljMXR1WVcxbFhTQTlJSFpoYkhWbE8xeHVJQ0FnSUgxY2JseHVJQ0FnSUhaaGNpQnZkWFFnUFNCN1hHNGdJQ0FnSUNCMWNtdzZJSEpsY1hWbGMzUXVkWEpzTEZ4dUlDQWdJQ0FnYldWMGFHOWtPaUJ5WlhGMVpYTjBMbTFsZEdodlpDeGNiaUFnSUNBZ0lITjBZWFIxY3pvZ2NtVnpjRzl1YzJVdWMzUmhkSFZ6TEZ4dUlDQWdJQ0FnYzNSaGRIVnpWR1Y0ZERvZ2NtVnpjRzl1YzJVdWMzUmhkSFZ6VkdWNGRDeGNiaUFnSUNBZ0lHUmhkR0U2SUhKbGMzQnZibk5sTG5KbGMzQnZibk5sVkdWNGRDeGNiaUFnSUNBZ0lHaGxZV1JsY25NNklHaGxZV1JsY25OY2JpQWdJQ0I5TzF4dVhHNGdJQ0FnZEhKNUlIdGNiaUFnSUNBZ0lIWmhjaUJ3YjNOemFXSnNaVTlpYWlBOUlDQnlaWE53YjI1elpTNXlaWE53YjI1elpVcFRUMDRnZkh3Z2FuTjVZVzFzTG5OaFptVk1iMkZrS0hKbGMzQnZibk5sTG5KbGMzQnZibk5sVkdWNGRDazdYRzRnSUNBZ0lDQnZkWFF1YjJKcUlEMGdLSFI1Y0dWdlppQndiM056YVdKc1pVOWlhaUE5UFQwZ0ozTjBjbWx1WnljcElEOGdlMzBnT2lCd2IzTnphV0pzWlU5aWFqdGNiaUFnSUNCOUlHTmhkR05vSUNobGVDa2dlMXh1SUNBZ0lDQWdMeThnWkc4Z2JtOTBJSE5sZENCdmRYUXViMkpxWEc0Z0lDQWdJQ0JvWld4d1pYSnpMbXh2WnlnbmRXNWhZbXhsSUhSdklIQmhjbk5sSUVwVFQwNHZXVUZOVENCamIyNTBaVzUwSnlrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1NTQmpZVzRnZEdoeWIzY3NJRzl5SUhCaGNuTmxJRzUxYkd3L1hHNGdJQ0FnYjNWMExtOWlhaUE5SUc5MWRDNXZZbW9nZkh3Z2JuVnNiRHRjYmx4dUlDQWdJR2xtSUNoeVpYTndiMjV6WlM1emRHRjBkWE1nUGowZ01qQXdJQ1ltSUhKbGMzQnZibk5sTG5OMFlYUjFjeUE4SURNd01Da2dlMXh1SUNBZ0lDQWdZMkl1Y21WemNHOXVjMlVvYjNWMEtUdGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tISmxjM0J2Ym5ObExuTjBZWFIxY3lBOVBUMGdNQ0I4ZkNBb2NtVnpjRzl1YzJVdWMzUmhkSFZ6SUQ0OUlEUXdNQ0FtSmlCeVpYTndiMjV6WlM1emRHRjBkWE1nUENBMU9Ua3BLU0I3WEc0Z0lDQWdJQ0JqWWk1bGNuSnZjaWh2ZFhRcE8xeHVJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0J5WlhSMWNtNGdZMkl1Y21WemNHOXVjMlVvYjNWMEtUdGNiaUFnSUNCOVhHNGdJSDA3WEc1Y2JpQWdhbkV1YzNWd2NHOXlkQzVqYjNKeklEMGdkSEoxWlR0Y2JseHVJQ0J5WlhSMWNtNGdhbkV1WVdwaGVDaHZZbW9wTzF4dWZUdGNibHh1VTNWd1pYSmhaMlZ1ZEVoMGRIQkRiR2xsYm5RdWNISnZkRzkwZVhCbExtVjRaV04xZEdVZ1BTQm1kVzVqZEdsdmJpQW9iMkpxS1NCN1hHNGdJSFpoY2lCdFpYUm9iMlFnUFNCdlltb3ViV1YwYUc5a0xuUnZURzkzWlhKRFlYTmxLQ2s3WEc0Z0lIWmhjaUIwYVcxbGIzVjBJRDBnYjJKcUxuUnBiV1Z2ZFhRN1hHNWNiaUFnYVdZZ0tHMWxkR2h2WkNBOVBUMGdKMlJsYkdWMFpTY3BJSHRjYmlBZ0lDQnRaWFJvYjJRZ1BTQW5aR1ZzSnp0Y2JpQWdmVnh1SUNCMllYSWdhR1ZoWkdWeWN5QTlJRzlpYWk1b1pXRmtaWEp6SUh4OElIdDlPMXh1WEc0Z0lIWmhjaUJ5SUQwZ2NtVnhkV1Z6ZEZ0dFpYUm9iMlJkS0c5aWFpNTFjbXdwTzF4dVhHNGdJR2xtSUNodlltb3VZMjl1Ym1WamRHbHZia0ZuWlc1MEtTQjdYRzRnSUNBZ2NpNWhaMlZ1ZENodlltb3VZMjl1Ym1WamRHbHZia0ZuWlc1MEtUdGNiaUFnZlZ4dVhHNGdJR2xtSUNoMGFXMWxiM1YwS1NCN1hHNGdJQ0FnY2k1MGFXMWxiM1YwS0hScGJXVnZkWFFwTzF4dUlDQjlYRzVjYmlBZ2FXWWdLRzlpYWk1bGJtRmliR1ZEYjI5cmFXVnpLU0I3WEc0Z0lDQWdjaTUzYVhSb1EzSmxaR1Z1ZEdsaGJITW9LVHRjYmlBZ2ZWeHVYRzRnSUhaaGNpQmhZMk5sY0hRZ1BTQnZZbW91YUdWaFpHVnljeTVCWTJObGNIUTdYRzVjYmlBZ2FXWW9kR2hwY3k1aWFXNWhjbmxTWlhGMVpYTjBLR0ZqWTJWd2RDa3BJSHRjYmlBZ0lDQnlMbTl1S0NkeVpYRjFaWE4wSnl3Z1puVnVZM1JwYjI0Z0tDa2dlMXh1SUNBZ0lDQWdhV1lvZEdocGN5NTRhSElwSUh0Y2JpQWdJQ0FnSUNBZ2RHaHBjeTU0YUhJdWNtVnpjRzl1YzJWVWVYQmxJRDBnSjJKc2IySW5PMXh1SUNBZ0lDQWdmVnh1SUNBZ0lIMHBPMXh1SUNCOVhHNWNiaUFnYVdZb2IySnFMbUp2WkhrcElIdGNiaUFnSUNCcFppaGZMbWx6VDJKcVpXTjBLRzlpYWk1aWIyUjVLU2tnZTF4dUlDQWdJQ0FnZG1GeUlHTnZiblJsYm5SVWVYQmxJRDBnYjJKcUxtaGxZV1JsY25OYkowTnZiblJsYm5RdFZIbHdaU2RkSUh4OElDY25PMXh1SUNBZ0lDQWdhV1lnS0dOdmJuUmxiblJVZVhCbExtbHVaR1Y0VDJZb0oyMTFiSFJwY0dGeWRDOW1iM0p0TFdSaGRHRW5LU0E5UFQwZ01Da2dlMXh1SUNBZ0lDQWdJQ0JrWld4bGRHVWdhR1ZoWkdWeWMxc25RMjl1ZEdWdWRDMVVlWEJsSjEwN1hHNGdJQ0FnSUNBZ0lHbG1LSHQ5TG5SdlUzUnlhVzVuTG1Gd2NHeDVLRzlpYWk1aWIyUjVLU0E5UFQwZ0oxdHZZbXBsWTNRZ1JtOXliVVJoZEdGZEp5a2dlMXh1SUNBZ0lDQWdJQ0FnSUhJdWMyVnVaQ2h2WW1vdVltOWtlU2s3WEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUNBZ2RtRnlJR3RsZVc1aGJXVXNJSFpoYkhWbExDQjJPMXh1SUNBZ0lDQWdJQ0FnSUdadmNpQW9hMlY1Ym1GdFpTQnBiaUJ2WW1vdVltOWtlU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdkbUZzZFdVZ1BTQnZZbW91WW05a2VWdHJaWGx1WVcxbFhUdGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUtFRnljbUY1TG1selFYSnlZWGtvZG1Gc2RXVXBLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJR1p2Y2loMklHbHVJSFpoYkhWbEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdjaTVtYVdWc1pDaHJaWGx1WVcxbExDQjJLVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnWld4elpTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lISXVabWxsYkdRb2EyVjVibUZ0WlN3Z2RtRnNkV1VwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ1pXeHpaU0JwWmlBb1h5NXBjMDlpYW1WamRDaHZZbW91WW05a2VTa3BJSHRjYmlBZ0lDQWdJQ0FnTHk4Z2JtOXVJRzExYkhScGNHRnlkQzltYjNKdExXUmhkR0ZjYmlBZ0lDQWdJQ0FnYjJKcUxtSnZaSGtnUFNCS1UwOU9Mbk4wY21sdVoybG1lU2h2WW1vdVltOWtlU2s3WEc0Z0lDQWdJQ0FnSUhJdWMyVnVaQ2h2WW1vdVltOWtlU2s3WEc0Z0lDQWdJQ0I5WEc0Z0lDQWdmVnh1SUNBZ0lHVnNjMlVnZTF4dUlDQWdJQ0FnY2k1elpXNWtLRzlpYWk1aWIyUjVLVHRjYmlBZ0lDQjlYRzRnSUgxY2JseHVJQ0IyWVhJZ2JtRnRaVHRjYmlBZ1ptOXlJQ2h1WVcxbElHbHVJR2hsWVdSbGNuTXBJSHRjYmlBZ0lDQnlMbk5sZENodVlXMWxMQ0JvWldGa1pYSnpXMjVoYldWZEtUdGNiaUFnZlZ4dVhHNGdJR2xtS0hSNWNHVnZaaUJ5TG1KMVptWmxjaUE5UFQwZ0oyWjFibU4wYVc5dUp5a2dlMXh1SUNBZ0lISXVZblZtWm1WeUtDazdJQzh2SUdadmNtTmxJSE4xY0dWeVlXZGxiblFnZEc4Z2NHOXdkV3hoZEdVZ2NtVnpMblJsZUhRZ2QybDBhQ0IwYUdVZ2NtRjNJSEpsYzNCdmJuTmxJR1JoZEdGY2JpQWdmVnh1WEc0Z0lISXVaVzVrS0daMWJtTjBhVzl1SUNobGNuSXNJSEpsY3lrZ2UxeHVJQ0FnSUhKbGN5QTlJSEpsY3lCOGZDQjdYRzRnSUNBZ0lDQnpkR0YwZFhNNklEQXNYRzRnSUNBZ0lDQm9aV0ZrWlhKek9pQjdaWEp5YjNJNklDZHVieUJ5WlhOd2IyNXpaU0JtY205dElITmxjblpsY2lkOVhHNGdJQ0FnZlR0Y2JpQWdJQ0IyWVhJZ2NtVnpjRzl1YzJVZ1BTQjdYRzRnSUNBZ0lDQjFjbXc2SUc5aWFpNTFjbXdzWEc0Z0lDQWdJQ0J0WlhSb2IyUTZJRzlpYWk1dFpYUm9iMlFzWEc0Z0lDQWdJQ0JvWldGa1pYSnpPaUJ5WlhNdWFHVmhaR1Z5YzF4dUlDQWdJSDA3WEc0Z0lDQWdkbUZ5SUdOaU8xeHVYRzRnSUNBZ2FXWWdLQ0ZsY25JZ0ppWWdjbVZ6TG1WeWNtOXlLU0I3WEc0Z0lDQWdJQ0JsY25JZ1BTQnlaWE11WlhKeWIzSTdYRzRnSUNBZ2ZWeHVYRzRnSUNBZ2FXWWdLR1Z5Y2lBbUppQnZZbW91YjI0Z0ppWWdiMkpxTG05dUxtVnljbTl5S1NCN1hHNGdJQ0FnSUNCeVpYTndiMjV6WlM1bGNuSlBZbW9nUFNCbGNuSTdYRzRnSUNBZ0lDQnlaWE53YjI1elpTNXpkR0YwZFhNZ1BTQnlaWE1nUHlCeVpYTXVjM1JoZEhWeklEb2dOVEF3TzF4dUlDQWdJQ0FnY21WemNHOXVjMlV1YzNSaGRIVnpWR1Y0ZENBOUlISmxjeUEvSUhKbGN5NTBaWGgwSURvZ1pYSnlMbTFsYzNOaFoyVTdYRzRnSUNBZ0lDQnBaaUFvY21WekxtaGxZV1JsY25NZ0ppWWdjbVZ6TG1obFlXUmxjbk5iSjJOdmJuUmxiblF0ZEhsd1pTZGRLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaHlaWE11YUdWaFpHVnljMXNuWTI5dWRHVnVkQzEwZVhCbEoxMHVhVzVrWlhoUFppZ25ZWEJ3YkdsallYUnBiMjR2YW5OdmJpY3BJRDQ5SURBcElIdGNiaUFnSUNBZ0lDQWdJQ0IwY25rZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WemNHOXVjMlV1YjJKcUlEMGdTbE5QVGk1d1lYSnpaU2h5WlhOd2IyNXpaUzV6ZEdGMGRYTlVaWGgwS1R0Y2JpQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnWTJGMFkyZ2dLR1VwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsYzNCdmJuTmxMbTlpYWlBOUlHNTFiR3c3WEc0Z0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQjlYRzRnSUNBZ0lDQmpZaUE5SUc5aWFpNXZiaTVsY25KdmNqdGNiaUFnSUNCOUlHVnNjMlVnYVdZZ0tISmxjeUFtSmlCdlltb3ViMjRnSmlZZ2IySnFMbTl1TG5KbGMzQnZibk5sS1NCN1hHNGdJQ0FnSUNCMllYSWdjRzl6YzJsaWJHVlBZbW83WEc1Y2JpQWdJQ0FnSUM4dklFRnNjbVZoWkhrZ2NHRnljMlZrSUdKNUlHSjVJSE4xY0dWeVlXZGxiblEvWEc0Z0lDQWdJQ0JwWmlBb2NtVnpMbUp2WkhrZ0ppWWdYeTVyWlhsektISmxjeTVpYjJSNUtTNXNaVzVuZEdnZ1BpQXdLU0I3WEc0Z0lDQWdJQ0FnSUhCdmMzTnBZbXhsVDJKcUlEMGdjbVZ6TG1KdlpIazdYRzRnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNBZ0lIQnZjM05wWW14bFQySnFJRDBnYW5ONVlXMXNMbk5oWm1WTWIyRmtLSEpsY3k1MFpYaDBLVHRjYmlBZ0lDQWdJQ0FnSUNBdkx5QmpZVzRnY0dGeWMyVWdhVzUwYnlCaElITjBjbWx1Wnk0dUxpQjNhR2xqYUNCM1pTQmtiMjRuZENCdVpXVmtJSEoxYm01cGJtY2dZWEp2ZFc1a0lHbHVJSFJvWlNCemVYTjBaVzFjYmlBZ0lDQWdJQ0FnSUNCd2IzTnphV0pzWlU5aWFpQTlJQ2gwZVhCbGIyWWdjRzl6YzJsaWJHVlBZbW9nUFQwOUlDZHpkSEpwYm1jbktTQS9JRzUxYkd3Z09pQndiM056YVdKc1pVOWlhanRjYmlBZ0lDQWdJQ0FnZlNCallYUmphQ0FvWlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJR2hsYkhCbGNuTXViRzluS0NkallXNXViM1FnY0dGeWMyVWdTbE5QVGk5WlFVMU1JR052Ym5SbGJuUW5LVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnZlZ4dVhHNGdJQ0FnSUNBdkx5QnVkV3hzSUcxbFlXNXpJSGRsSUdOaGJpZDBJSEJoY25ObElHbHVkRzhnYjJKcVpXTjBYRzRnSUNBZ0lDQnBaaWgwZVhCbGIyWWdRblZtWm1WeUlEMDlQU0FuWm5WdVkzUnBiMjRuSUNZbUlFSjFabVpsY2k1cGMwSjFabVpsY2lod2IzTnphV0pzWlU5aWFpa3BJSHRjYmlBZ0lDQWdJQ0FnY21WemNHOXVjMlV1WkdGMFlTQTlJSEJ2YzNOcFlteGxUMkpxTzF4dUlDQWdJQ0FnZlZ4dUlDQWdJQ0FnWld4elpTQjdYRzRnSUNBZ0lDQWdJSEpsYzNCdmJuTmxMbTlpYWlBOUlDaDBlWEJsYjJZZ2NHOXpjMmxpYkdWUFltb2dQVDA5SUNkdlltcGxZM1FuS1NBL0lIQnZjM05wWW14bFQySnFJRG9nYm5Wc2JEdGNiaUFnSUNBZ0lIMWNibHh1SUNBZ0lDQWdjbVZ6Y0c5dWMyVXVjM1JoZEhWeklEMGdjbVZ6TG5OMFlYUjFjenRjYmlBZ0lDQWdJSEpsYzNCdmJuTmxMbk4wWVhSMWMxUmxlSFFnUFNCeVpYTXVkR1Y0ZER0Y2JpQWdJQ0FnSUdOaUlEMGdiMkpxTG05dUxuSmxjM0J2Ym5ObE8xeHVJQ0FnSUgxY2JpQWdJQ0JwWmlBb2NtVnpMbmhvY2lBbUppQnlaWE11ZUdoeUxuSmxjM0J2Ym5ObEtTQjdYRzRnSUNBZ0lDQnlaWE53YjI1elpTNWtZWFJoSUQwZ2NtVnpMbmhvY2k1eVpYTndiMjV6WlR0Y2JpQWdJQ0I5WEc0Z0lDQWdaV3h6WlNCcFppZ2hjbVZ6Y0c5dWMyVXVaR0YwWVNrZ2UxeHVJQ0FnSUNBZ2NtVnpjRzl1YzJVdVpHRjBZU0E5SUhKbGMzQnZibk5sTG5OMFlYUjFjMVJsZUhRN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnYVdZZ0tHTmlLU0I3WEc0Z0lDQWdJQ0JqWWloeVpYTndiMjV6WlNrN1hHNGdJQ0FnZlZ4dUlDQjlLVHRjYm4wN1hHNWNibE4xY0dWeVlXZGxiblJJZEhSd1EyeHBaVzUwTG5CeWIzUnZkSGx3WlM0Z1ltbHVZWEo1VW1WeGRXVnpkQ0E5SUdaMWJtTjBhVzl1SUNoaFkyTmxjSFFwSUh0Y2JpQWdhV1lvSVdGalkyVndkQ2tnZTF4dUlDQWdJSEpsZEhWeWJpQm1ZV3h6WlR0Y2JpQWdmVnh1SUNCeVpYUjFjbTRnS0M5ZWFXMWhaMlV2YVNrdWRHVnpkQ2hoWTJObGNIUXBYRzRnSUNBZ2ZId2dLQzllWVhCd2JHbGpZWFJwYjI1Y1hDOXdaR1l2S1M1MFpYTjBLR0ZqWTJWd2RDbGNiaUFnSUNCOGZDQW9MMTVoY0hCc2FXTmhkR2x2Ymx4Y0wyOWpkR1YwTFhOMGNtVmhiUzhwTG5SbGMzUW9ZV05qWlhCMEtUdGNibjA3WEc0aVhYMD0iLCIndXNlIHN0cmljdCc7XG5cbnZhciBTd2FnZ2VySHR0cCA9IHJlcXVpcmUoJy4vaHR0cCcpO1xudmFyIF8gPSB7XG4gIGlzT2JqZWN0OiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvaXNPYmplY3QnKSxcbiAgY2xvbmVEZWVwOiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvY2xvbmVEZWVwJyksXG4gIGlzQXJyYXk6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvbGFuZy9pc0FycmF5JyksXG4gIGlzU3RyaW5nOiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvaXNTdHJpbmcnKVxufTtcblxuXG4vKipcbiAqIFJlc29sdmVzIGEgc3BlYydzIHJlbW90ZSByZWZlcmVuY2VzXG4gKi9cbnZhciBSZXNvbHZlciA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmZhaWxlZFVybHMgPSBbXTtcbiAgdGhpcy5yZXNvbHZlckNhY2hlID0ge307XG4gIHRoaXMucGVuZGluZ1VybHMgPSB7fTtcbn07XG5cblJlc29sdmVyLnByb3RvdHlwZS5wcm9jZXNzQWxsT2YgPSBmdW5jdGlvbihyb290LCBuYW1lLCBkZWZpbml0aW9uLCByZXNvbHV0aW9uVGFibGUsIHVucmVzb2x2ZWRSZWZzLCBzcGVjKSB7XG4gIHZhciBpLCBsb2NhdGlvbiwgcHJvcGVydHk7XG5cbiAgZGVmaW5pdGlvblsneC1yZXNvbHZlZC1mcm9tJ10gPSBbICcjL2RlZmluaXRpb25zLycgKyBuYW1lIF07XG4gIHZhciBhbGxPZiA9IGRlZmluaXRpb24uYWxsT2Y7XG4gIC8vIHRoZSByZWZzIGdvIGZpcnN0XG4gIGFsbE9mLnNvcnQoZnVuY3Rpb24oYSwgYikge1xuICAgIGlmKGEuJHJlZiAmJiBiLiRyZWYpIHsgcmV0dXJuIDA7IH1cbiAgICBlbHNlIGlmKGEuJHJlZikgeyByZXR1cm4gLTE7IH1cbiAgICBlbHNlIHsgcmV0dXJuIDE7IH1cbiAgfSk7XG4gIGZvciAoaSA9IDA7IGkgPCBhbGxPZi5sZW5ndGg7IGkrKykge1xuICAgIHByb3BlcnR5ID0gYWxsT2ZbaV07XG4gICAgbG9jYXRpb24gPSAnL2RlZmluaXRpb25zLycgKyBuYW1lICsgJy9hbGxPZic7XG4gICAgdGhpcy5yZXNvbHZlSW5saW5lKHJvb3QsIHNwZWMsIHByb3BlcnR5LCByZXNvbHV0aW9uVGFibGUsIHVucmVzb2x2ZWRSZWZzLCBsb2NhdGlvbik7XG4gIH1cbn07XG5cblJlc29sdmVyLnByb3RvdHlwZS5yZXNvbHZlID0gZnVuY3Rpb24gKHNwZWMsIGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgdGhpcy5zcGVjID0gc3BlYztcbiAgdmFyIHJvb3QgPSBhcmcxLCBjYWxsYmFjayA9IGFyZzIsIHNjb3BlID0gYXJnMywgb3B0cyA9IHt9LCBsb2NhdGlvbiwgaTtcbiAgaWYodHlwZW9mIGFyZzEgPT09ICdmdW5jdGlvbicpIHtcbiAgICByb290ID0gbnVsbDtcbiAgICBjYWxsYmFjayA9IGFyZzE7XG4gICAgc2NvcGUgPSBhcmcyO1xuICB9XG4gIHZhciBfcm9vdCA9IHJvb3QsIG1vZGVsTmFtZTtcbiAgdGhpcy5zY29wZSA9IChzY29wZSB8fCB0aGlzKTtcbiAgdGhpcy5pdGVyYXRpb24gPSB0aGlzLml0ZXJhdGlvbiB8fCAwO1xuXG4gIGlmKHRoaXMuc2NvcGUub3B0aW9ucyAmJiB0aGlzLnNjb3BlLm9wdGlvbnMucmVxdWVzdEludGVyY2VwdG9yKXtcbiAgICBvcHRzLnJlcXVlc3RJbnRlcmNlcHRvciA9IHRoaXMuc2NvcGUub3B0aW9ucy5yZXF1ZXN0SW50ZXJjZXB0b3I7XG4gIH1cblxuICBpZih0aGlzLnNjb3BlLm9wdGlvbnMgJiYgdGhpcy5zY29wZS5vcHRpb25zLnJlc3BvbnNlSW50ZXJjZXB0b3Ipe1xuICAgIG9wdHMucmVzcG9uc2VJbnRlcmNlcHRvciA9IHRoaXMuc2NvcGUub3B0aW9ucy5yZXNwb25zZUludGVyY2VwdG9yO1xuICB9XG5cbiAgdmFyIG5hbWUsIHBhdGgsIHByb3BlcnR5LCBwcm9wZXJ0eU5hbWUsIHBhcmFtZXRlciwgZG9uZSwgY291bnRlcjtcbiAgdmFyIHByb2Nlc3NlZENhbGxzID0gMCwgcmVzb2x2ZWRSZWZzID0ge30sIHVucmVzb2x2ZWRSZWZzID0ge307XG4gIHZhciByZXNvbHV0aW9uVGFibGUgPSBbXTsgLy8gc3RvcmUgb2JqZWN0cyBmb3IgZGVyZWZlcmVuY2luZ1xuXG4gIHNwZWMuZGVmaW5pdGlvbnMgPSBzcGVjLmRlZmluaXRpb25zIHx8IHt9O1xuICAvLyBkZWZpbml0aW9uc1xuICBmb3IgKG5hbWUgaW4gc3BlYy5kZWZpbml0aW9ucykge1xuICAgIHZhciBkZWZpbml0aW9uID0gc3BlYy5kZWZpbml0aW9uc1tuYW1lXTtcbiAgICBpZihkZWZpbml0aW9uLiRyZWYpIHtcbiAgICAgIHRoaXMucmVzb2x2ZUlubGluZShyb290LCBzcGVjLCBkZWZpbml0aW9uLCByZXNvbHV0aW9uVGFibGUsIHVucmVzb2x2ZWRSZWZzLCBkZWZpbml0aW9uKTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICBmb3IgKHByb3BlcnR5TmFtZSBpbiBkZWZpbml0aW9uLnByb3BlcnRpZXMpIHtcbiAgICAgICAgcHJvcGVydHkgPSBkZWZpbml0aW9uLnByb3BlcnRpZXNbcHJvcGVydHlOYW1lXTtcbiAgICAgICAgaWYgKF8uaXNBcnJheShwcm9wZXJ0eS5hbGxPZikpIHtcbiAgICAgICAgICB0aGlzLnByb2Nlc3NBbGxPZihyb290LCBuYW1lLCBwcm9wZXJ0eSwgcmVzb2x1dGlvblRhYmxlLCB1bnJlc29sdmVkUmVmcywgc3BlYyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdGhpcy5yZXNvbHZlVG8ocm9vdCwgcHJvcGVydHksIHJlc29sdXRpb25UYWJsZSwgJy9kZWZpbml0aW9ucycpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChkZWZpbml0aW9uLmFsbE9mKSB7XG4gICAgICAgIHRoaXMucHJvY2Vzc0FsbE9mKHJvb3QsIG5hbWUsIGRlZmluaXRpb24sIHJlc29sdXRpb25UYWJsZSwgdW5yZXNvbHZlZFJlZnMsIHNwZWMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIHNoYXJlZCBwYXJhbWV0ZXJzXG4gIHNwZWMucGFyYW1ldGVycyA9IHNwZWMucGFyYW1ldGVycyB8fCB7fTtcbiAgZm9yKG5hbWUgaW4gc3BlYy5wYXJhbWV0ZXJzKSB7XG4gICAgcGFyYW1ldGVyID0gc3BlYy5wYXJhbWV0ZXJzW25hbWVdO1xuICAgIGlmIChwYXJhbWV0ZXIuaW4gPT09ICdib2R5JyAmJiBwYXJhbWV0ZXIuc2NoZW1hKSB7XG4gICAgICBpZihfLmlzQXJyYXkocGFyYW1ldGVyLnNjaGVtYS5hbGxPZikpIHtcbiAgICAgICAgLy8gbW92ZSB0byBhIGRlZmluaXRpb25cbiAgICAgICAgbW9kZWxOYW1lID0gJ2lubGluZV9tb2RlbCc7XG4gICAgICAgIHZhciBfbmFtZSA9IG1vZGVsTmFtZTtcbiAgICAgICAgZG9uZSA9IGZhbHNlOyBjb3VudGVyID0gMDtcbiAgICAgICAgd2hpbGUoIWRvbmUpIHtcbiAgICAgICAgICBpZih0eXBlb2Ygc3BlYy5kZWZpbml0aW9uc1tfbmFtZV0gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfbmFtZSA9IG1vZGVsTmFtZSArICdfJyArIGNvdW50ZXI7XG4gICAgICAgICAgY291bnRlciArKztcbiAgICAgICAgfVxuICAgICAgICBzcGVjLmRlZmluaXRpb25zW19uYW1lXSA9IHsgYWxsT2Y6IHBhcmFtZXRlci5zY2hlbWEuYWxsT2YgfTtcbiAgICAgICAgZGVsZXRlIHBhcmFtZXRlci5zY2hlbWEuYWxsT2Y7XG4gICAgICAgIHBhcmFtZXRlci5zY2hlbWEuJHJlZiA9ICcjL2RlZmluaXRpb25zLycgKyBfbmFtZTtcbiAgICAgICAgdGhpcy5wcm9jZXNzQWxsT2Yocm9vdCwgX25hbWUsIHNwZWMuZGVmaW5pdGlvbnNbX25hbWVdLCByZXNvbHV0aW9uVGFibGUsIHVucmVzb2x2ZWRSZWZzLCBzcGVjKTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICB0aGlzLnJlc29sdmVUbyhyb290LCBwYXJhbWV0ZXIuc2NoZW1hLCByZXNvbHV0aW9uVGFibGUsIGxvY2F0aW9uKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocGFyYW1ldGVyLiRyZWYpIHtcbiAgICAgIC8vIHBhcmFtZXRlciByZWZlcmVuY2VcbiAgICAgIHRoaXMucmVzb2x2ZUlubGluZShyb290LCBzcGVjLCBwYXJhbWV0ZXIsIHJlc29sdXRpb25UYWJsZSwgdW5yZXNvbHZlZFJlZnMsIHBhcmFtZXRlci4kcmVmKTtcbiAgICB9XG4gIH1cblxuICAvLyBvcGVyYXRpb25zXG4gIGZvciAobmFtZSBpbiBzcGVjLnBhdGhzKSB7XG4gICAgdmFyIG1ldGhvZCwgb3BlcmF0aW9uLCByZXNwb25zZUNvZGU7XG4gICAgcGF0aCA9IHNwZWMucGF0aHNbbmFtZV07XG5cbiAgICBpZih0eXBlb2YgcGF0aCA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGZvciAobWV0aG9kIGluIHBhdGgpIHtcbiAgICAgICAgLy8gb3BlcmF0aW9uIHJlZmVyZW5jZVxuICAgICAgICBpZiAobWV0aG9kID09PSAnJHJlZicpIHtcbiAgICAgICAgICAvLyBsb2NhdGlvbiA9IHBhdGhbbWV0aG9kXTtcbiAgICAgICAgICBsb2NhdGlvbiA9ICcvcGF0aHMnICsgbmFtZTtcbiAgICAgICAgICB0aGlzLnJlc29sdmVJbmxpbmUocm9vdCwgc3BlYywgcGF0aCwgcmVzb2x1dGlvblRhYmxlLCB1bnJlc29sdmVkUmVmcywgbG9jYXRpb24pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIG9wZXJhdGlvbiA9IHBhdGhbbWV0aG9kXTtcbiAgICAgICAgICB2YXIgc2hhcmVkUGFyYW1ldGVycyA9IHBhdGgucGFyYW1ldGVycyB8fCBbXTtcbiAgICAgICAgICB2YXIgcGFyYW1ldGVycyA9IG9wZXJhdGlvbi5wYXJhbWV0ZXJzIHx8IFtdO1xuXG4gICAgICAgICAgc2hhcmVkUGFyYW1ldGVycy5mb3JFYWNoKGZ1bmN0aW9uKHBhcmFtZXRlcikge1xuICAgICAgICAgICAgcGFyYW1ldGVycy51bnNoaWZ0KHBhcmFtZXRlcik7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICBpZiAobWV0aG9kICE9PSAncGFyYW1ldGVycycgJiYgXy5pc09iamVjdChvcGVyYXRpb24pKSB7XG4gICAgICAgICAgICBvcGVyYXRpb24ucGFyYW1ldGVycyA9IG9wZXJhdGlvbi5wYXJhbWV0ZXJzIHx8IHBhcmFtZXRlcnM7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZm9yIChpIGluIHBhcmFtZXRlcnMpIHtcbiAgICAgICAgICAgIHBhcmFtZXRlciA9IHBhcmFtZXRlcnNbaV07XG4gICAgICAgICAgICBsb2NhdGlvbiA9ICcvcGF0aHMnICsgbmFtZSArICcvJyArIG1ldGhvZCArICcvcGFyYW1ldGVycyc7XG5cbiAgICAgICAgICAgIGlmIChwYXJhbWV0ZXIuaW4gPT09ICdib2R5JyAmJiBwYXJhbWV0ZXIuc2NoZW1hKSB7XG4gICAgICAgICAgICAgIGlmIChfLmlzQXJyYXkocGFyYW1ldGVyLnNjaGVtYS5hbGxPZikpIHtcbiAgICAgICAgICAgICAgICAvLyBtb3ZlIHRvIGEgZGVmaW5pdGlvblxuICAgICAgICAgICAgICAgIG1vZGVsTmFtZSA9ICdpbmxpbmVfbW9kZWwnO1xuICAgICAgICAgICAgICAgIG5hbWUgPSBtb2RlbE5hbWU7XG4gICAgICAgICAgICAgICAgZG9uZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGNvdW50ZXIgPSAwO1xuICAgICAgICAgICAgICAgIHdoaWxlICghZG9uZSkge1xuICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBzcGVjLmRlZmluaXRpb25zW25hbWVdID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICBuYW1lID0gbW9kZWxOYW1lICsgJ18nICsgY291bnRlcjtcbiAgICAgICAgICAgICAgICAgIGNvdW50ZXIrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3BlYy5kZWZpbml0aW9uc1tuYW1lXSA9IHthbGxPZjogcGFyYW1ldGVyLnNjaGVtYS5hbGxPZn07XG4gICAgICAgICAgICAgICAgZGVsZXRlIHBhcmFtZXRlci5zY2hlbWEuYWxsT2Y7XG4gICAgICAgICAgICAgICAgcGFyYW1ldGVyLnNjaGVtYS4kcmVmID0gJyMvZGVmaW5pdGlvbnMvJyArIG5hbWU7XG4gICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzQWxsT2Yocm9vdCwgbmFtZSwgc3BlYy5kZWZpbml0aW9uc1tuYW1lXSwgcmVzb2x1dGlvblRhYmxlLCB1bnJlc29sdmVkUmVmcywgc3BlYyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvbHZlVG8ocm9vdCwgcGFyYW1ldGVyLnNjaGVtYSwgcmVzb2x1dGlvblRhYmxlLCBsb2NhdGlvbik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHBhcmFtZXRlci4kcmVmKSB7XG4gICAgICAgICAgICAgIC8vIHBhcmFtZXRlciByZWZlcmVuY2VcbiAgICAgICAgICAgICAgdGhpcy5yZXNvbHZlSW5saW5lKHJvb3QsIHNwZWMsIHBhcmFtZXRlciwgcmVzb2x1dGlvblRhYmxlLCB1bnJlc29sdmVkUmVmcywgcGFyYW1ldGVyLiRyZWYpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGZvciAocmVzcG9uc2VDb2RlIGluIG9wZXJhdGlvbi5yZXNwb25zZXMpIHtcbiAgICAgICAgICAgIHZhciByZXNwb25zZSA9IG9wZXJhdGlvbi5yZXNwb25zZXNbcmVzcG9uc2VDb2RlXTtcbiAgICAgICAgICAgIGxvY2F0aW9uID0gJy9wYXRocycgKyBuYW1lICsgJy8nICsgbWV0aG9kICsgJy9yZXNwb25zZXMvJyArIHJlc3BvbnNlQ29kZTtcblxuICAgICAgICAgICAgaWYgKF8uaXNPYmplY3QocmVzcG9uc2UpKSB7XG4gICAgICAgICAgICAgIGlmIChyZXNwb25zZS4kcmVmKSB7XG4gICAgICAgICAgICAgICAgLy8gcmVzcG9uc2UgcmVmZXJlbmNlXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNvbHZlSW5saW5lKHJvb3QsIHNwZWMsIHJlc3BvbnNlLCByZXNvbHV0aW9uVGFibGUsIHVucmVzb2x2ZWRSZWZzLCBsb2NhdGlvbik7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgaWYgKHJlc3BvbnNlLnNjaGVtYSkge1xuICAgICAgICAgICAgICAgIHZhciByZXNwb25zZU9iaiA9IHJlc3BvbnNlO1xuICAgICAgICAgICAgICAgIGlmIChfLmlzQXJyYXkocmVzcG9uc2VPYmouc2NoZW1hLmFsbE9mKSkge1xuICAgICAgICAgICAgICAgICAgLy8gbW92ZSB0byBhIGRlZmluaXRpb25cbiAgICAgICAgICAgICAgICAgIG1vZGVsTmFtZSA9ICdpbmxpbmVfbW9kZWwnO1xuICAgICAgICAgICAgICAgICAgbmFtZSA9IG1vZGVsTmFtZTtcbiAgICAgICAgICAgICAgICAgIGRvbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgIGNvdW50ZXIgPSAwO1xuICAgICAgICAgICAgICAgICAgd2hpbGUgKCFkb25lKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygc3BlYy5kZWZpbml0aW9uc1tuYW1lXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICBkb25lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBuYW1lID0gbW9kZWxOYW1lICsgJ18nICsgY291bnRlcjtcbiAgICAgICAgICAgICAgICAgICAgY291bnRlcisrO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgc3BlYy5kZWZpbml0aW9uc1tuYW1lXSA9IHthbGxPZjogcmVzcG9uc2VPYmouc2NoZW1hLmFsbE9mfTtcbiAgICAgICAgICAgICAgICAgIGRlbGV0ZSByZXNwb25zZU9iai5zY2hlbWEuYWxsT2Y7XG4gICAgICAgICAgICAgICAgICBkZWxldGUgcmVzcG9uc2VPYmouc2NoZW1hLnR5cGU7XG4gICAgICAgICAgICAgICAgICByZXNwb25zZU9iai5zY2hlbWEuJHJlZiA9ICcjL2RlZmluaXRpb25zLycgKyBuYW1lO1xuICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzQWxsT2Yocm9vdCwgbmFtZSwgc3BlYy5kZWZpbml0aW9uc1tuYW1lXSwgcmVzb2x1dGlvblRhYmxlLCB1bnJlc29sdmVkUmVmcywgc3BlYyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKCdhcnJheScgPT09IHJlc3BvbnNlT2JqLnNjaGVtYS50eXBlKSB7XG4gICAgICAgICAgICAgICAgICBpZiAocmVzcG9uc2VPYmouc2NoZW1hLml0ZW1zICYmIHJlc3BvbnNlT2JqLnNjaGVtYS5pdGVtcy4kcmVmKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHJlc3BvbnNlIHJlZmVyZW5jZVxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlc29sdmVJbmxpbmUocm9vdCwgc3BlYywgcmVzcG9uc2VPYmouc2NoZW1hLml0ZW1zLCByZXNvbHV0aW9uVGFibGUsIHVucmVzb2x2ZWRSZWZzLCBsb2NhdGlvbik7XG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgdGhpcy5yZXNvbHZlVG8ocm9vdCwgcmVzcG9uc2Uuc2NoZW1hLCByZXNvbHV0aW9uVGFibGUsIGxvY2F0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIC8vIGNsZWFyIHRoZW0gb3V0IHRvIGF2b2lkIG11bHRpcGxlIHJlc29sdXRpb25zXG4gICAgICBwYXRoLnBhcmFtZXRlcnMgPSBbXTtcbiAgICB9XG4gIH1cblxuICB2YXIgZXhwZWN0ZWRDYWxscyA9IDAsIHRvUmVzb2x2ZSA9IFtdO1xuICAvLyBpZiB0aGUgcm9vdCBpcyBzYW1lIGFzIG9ialtpXS5yb290IHdlIGNhbiByZXNvbHZlIGxvY2FsbHlcbiAgdmFyIGFsbCA9IHJlc29sdXRpb25UYWJsZTtcblxuICB2YXIgcGFydHM7XG4gIGZvcihpID0gMDsgaSA8IGFsbC5sZW5ndGg7IGkrKykge1xuICAgIHZhciBhID0gYWxsW2ldO1xuICAgIGlmKHJvb3QgPT09IGEucm9vdCkge1xuICAgICAgaWYoYS5yZXNvbHZlQXMgPT09ICdyZWYnKSB7XG4gICAgICAgIC8vIHJlc29sdmUgYW55IHBhdGggd2Fsa2luZ1xuICAgICAgICB2YXIgam9pbmVkID0gKChhLnJvb3QgfHwgJycpICsgJy8nICsgYS5rZXkpLnNwbGl0KCcvJyk7XG4gICAgICAgIHZhciBub3JtYWxpemVkID0gW107XG4gICAgICAgIHZhciB1cmwgPSAnJztcbiAgICAgICAgdmFyIGs7XG5cbiAgICAgICAgaWYoYS5rZXkuaW5kZXhPZignLi4vJykgPj0gMCkge1xuICAgICAgICAgIGZvcih2YXIgaiA9IDA7IGogPCBqb2luZWQubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgIGlmKGpvaW5lZFtqXSA9PT0gJy4uJykge1xuICAgICAgICAgICAgICBub3JtYWxpemVkID0gbm9ybWFsaXplZC5zbGljZSgwLCBub3JtYWxpemVkLmxlbmd0aC0xKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICBub3JtYWxpemVkLnB1c2goam9pbmVkW2pdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgZm9yKGsgPSAwOyBrIDwgbm9ybWFsaXplZC5sZW5ndGg7IGsgKyspIHtcbiAgICAgICAgICAgIGlmKGsgPiAwKSB7XG4gICAgICAgICAgICAgIHVybCArPSAnLyc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB1cmwgKz0gbm9ybWFsaXplZFtrXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gd2Ugbm93IGhhdmUgdG8gcmVtb3RlIHJlc29sdmUgdGhpcyBiZWNhdXNlIHRoZSBwYXRoIGhhcyBjaGFuZ2VkXG4gICAgICAgICAgYS5yb290ID0gdXJsO1xuICAgICAgICAgIHRvUmVzb2x2ZS5wdXNoKGEpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIHBhcnRzID0gYS5rZXkuc3BsaXQoJyMnKTtcbiAgICAgICAgICBpZihwYXJ0cy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgIGlmKHBhcnRzWzBdLmluZGV4T2YoJ2h0dHA6JykgPT09IDAgfHwgcGFydHNbMF0uaW5kZXhPZignaHR0cHM6JykgPT09IDApIHtcbiAgICAgICAgICAgICAgYS5yb290ID0gcGFydHNbMF07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsb2NhdGlvbiA9IHBhcnRzWzFdLnNwbGl0KCcvJyk7XG4gICAgICAgICAgICB2YXIgcjtcbiAgICAgICAgICAgIHZhciBzID0gc3BlYztcbiAgICAgICAgICAgIGZvcihrID0gMDsgayA8IGxvY2F0aW9uLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgIHZhciBwYXJ0ID0gbG9jYXRpb25ba107XG4gICAgICAgICAgICAgIGlmKHBhcnQgIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgcyA9IHNbcGFydF07XG4gICAgICAgICAgICAgICAgaWYodHlwZW9mIHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICByID0gcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICByID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYociA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAvLyBtdXN0IHJlc29sdmUgdGhpcyB0b29cbiAgICAgICAgICAgICAgdG9SZXNvbHZlLnB1c2goYSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBlbHNlIHtcbiAgICAgICAgaWYgKGEucmVzb2x2ZUFzID09PSAnaW5saW5lJykge1xuICAgICAgICAgIGlmKGEua2V5ICYmIGEua2V5LmluZGV4T2YoJyMnKSA9PT0gLTEgJiYgYS5rZXkuY2hhckF0KDApICE9PSAnLycpIHtcbiAgICAgICAgICAgIC8vIGhhbmRsZSByZWxhdGl2ZSBzY2hlbWFcbiAgICAgICAgICAgIHBhcnRzID0gYS5yb290LnNwbGl0KCcvJyk7XG4gICAgICAgICAgICBsb2NhdGlvbiA9ICcnO1xuICAgICAgICAgICAgZm9yKGkgPSAwOyBpIDwgcGFydHMubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgICAgICAgIGxvY2F0aW9uICs9IHBhcnRzW2ldICsgJy8nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbG9jYXRpb24gKz0gYS5rZXk7XG4gICAgICAgICAgICBhLnJvb3QgPSBsb2NhdGlvbjtcbiAgICAgICAgICAgIGEubG9jYXRpb24gPSAnJztcbiAgICAgICAgICB9XG4gICAgICAgICAgdG9SZXNvbHZlLnB1c2goYSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICB0b1Jlc29sdmUucHVzaChhKTtcbiAgICB9XG4gIH1cbiAgZXhwZWN0ZWRDYWxscyA9IHRvUmVzb2x2ZS5sZW5ndGg7XG5cbiAgLy8gcmVzb2x2ZSBhbnl0aGluZyB0aGF0IGlzIGxvY2FsXG5cbiAgdmFyIGxvY2sgPSB7fTtcbiAgZm9yKHZhciBpaSA9IDA7IGlpIDwgdG9SZXNvbHZlLmxlbmd0aDsgaWkrKykge1xuICAgIChmdW5jdGlvbihpdGVtLCBzcGVjLCBzZWxmLCBsb2NrLCBpaSkge1xuICAgICAgaWYoIWl0ZW0ucm9vdCB8fCBpdGVtLnJvb3QgPT09IHJvb3QpIHtcbiAgICAgICAgLy8gbG9jYWwgcmVzb2x2ZVxuICAgICAgICBzZWxmLnJlc29sdmVJdGVtKHNwZWMsIF9yb290LCByZXNvbHV0aW9uVGFibGUsIHJlc29sdmVkUmVmcywgdW5yZXNvbHZlZFJlZnMsIGl0ZW0pO1xuICAgICAgICBwcm9jZXNzZWRDYWxscyArPSAxO1xuXG4gICAgICAgIGlmKHByb2Nlc3NlZENhbGxzID09PSBleHBlY3RlZENhbGxzKSB7XG4gICAgICAgICAgc2VsZi5maW5pc2goc3BlYywgcm9vdCwgcmVzb2x1dGlvblRhYmxlLCByZXNvbHZlZFJlZnMsIHVucmVzb2x2ZWRSZWZzLCBjYWxsYmFjaywgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGVsc2UgaWYoc2VsZi5mYWlsZWRVcmxzLmluZGV4T2YoaXRlbS5yb290KSA9PT0gLTEpIHtcbiAgICAgICAgdmFyIG9iaiA9IHtcbiAgICAgICAgICB1c2VKUXVlcnk6IGZhbHNlLCAgLy8gVE9ET1xuICAgICAgICAgIHVybDogaXRlbS5yb290LFxuICAgICAgICAgIG1ldGhvZDogJ2dldCcsXG4gICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgYWNjZXB0OiBzZWxmLnNjb3BlLnN3YWdnZXJSZXF1ZXN0SGVhZGVycyB8fCAnYXBwbGljYXRpb24vanNvbidcbiAgICAgICAgICB9LFxuICAgICAgICAgIG9uOiB7XG4gICAgICAgICAgICBlcnJvcjogZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgIHByb2Nlc3NlZENhbGxzICs9IDE7XG4gICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdmYWlsZWQgdXJsOiAnICsgb2JqLnVybCk7XG4gICAgICAgICAgICAgIHNlbGYuZmFpbGVkVXJscy5wdXNoKG9iai51cmwpO1xuICAgICAgICAgICAgICBpZiAobG9jaykge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSBsb2NrW2l0ZW0ucm9vdF07XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgdW5yZXNvbHZlZFJlZnNbaXRlbS5rZXldID0ge1xuICAgICAgICAgICAgICAgIHJvb3Q6IGl0ZW0ucm9vdCxcbiAgICAgICAgICAgICAgICBsb2NhdGlvbjogaXRlbS5sb2NhdGlvblxuICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgIGlmIChwcm9jZXNzZWRDYWxscyA9PT0gZXhwZWN0ZWRDYWxscykge1xuICAgICAgICAgICAgICAgIHNlbGYuZmluaXNoKHNwZWMsIF9yb290LCByZXNvbHV0aW9uVGFibGUsIHJlc29sdmVkUmVmcywgdW5yZXNvbHZlZFJlZnMsIGNhbGxiYWNrKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgIC8vIGpzaGludCBpZ25vcmU6bGluZVxuICAgICAgICAgICAgcmVzcG9uc2U6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICAgICAgICB2YXIgc3dhZ2dlciA9IHJlc3BvbnNlLm9iajtcbiAgICAgICAgICAgICAgaWYgKGxvY2spIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgbG9ja1tpdGVtLnJvb3RdO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGlmIChzZWxmLnJlc29sdmVyQ2FjaGUpIHtcbiAgICAgICAgICAgICAgICBzZWxmLnJlc29sdmVyQ2FjaGVbaXRlbS5yb290XSA9IHN3YWdnZXI7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgc2VsZi5yZXNvbHZlSXRlbShzd2FnZ2VyLCBpdGVtLnJvb3QsIHJlc29sdXRpb25UYWJsZSwgcmVzb2x2ZWRSZWZzLCB1bnJlc29sdmVkUmVmcywgaXRlbSk7XG4gICAgICAgICAgICAgIHByb2Nlc3NlZENhbGxzICs9IDE7XG5cbiAgICAgICAgICAgICAgaWYgKHByb2Nlc3NlZENhbGxzID09PSBleHBlY3RlZENhbGxzKSB7XG4gICAgICAgICAgICAgICAgc2VsZi5maW5pc2goc3BlYywgX3Jvb3QsIHJlc29sdXRpb25UYWJsZSwgcmVzb2x2ZWRSZWZzLCB1bnJlc29sdmVkUmVmcywgY2FsbGJhY2spO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSAvLyBqc2hpbnQgaWdub3JlOmxpbmVcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBhcHBseSB0aW1lb3V0IG9ubHkgd2hlbiBzcGVjaWZpZWRcbiAgICAgICAgaWYgKHNjb3BlICYmIHNjb3BlLmZldGNoU3BlY1RpbWVvdXQpIHtcbiAgICAgICAgICBvYmoudGltZW91dCA9IHNjb3BlLmZldGNoU3BlY1RpbWVvdXQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2NvcGUgJiYgc2NvcGUuY2xpZW50QXV0aG9yaXphdGlvbnMpIHtcbiAgICAgICAgICBzY29wZS5jbGllbnRBdXRob3JpemF0aW9ucy5hcHBseShvYmopO1xuICAgICAgICB9XG5cbiAgICAgICAgKGZ1bmN0aW9uIHdhaXRGb3JVbmxvY2soKSB7XG4gICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgIGlmIChsb2NrW29iai51cmxdKSB7XG4gICAgICAgICAgICAgIHdhaXRGb3JVbmxvY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICB2YXIgY2FjaGVkID0gc2VsZi5yZXNvbHZlckNhY2hlW29iai51cmxdO1xuICAgICAgICAgICAgICBpZiAoXy5pc09iamVjdChjYWNoZWQpKSB7XG4gICAgICAgICAgICAgICAgb2JqLm9uLnJlc3BvbnNlKHtvYmo6IGNhY2hlZH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGxvY2tbb2JqLnVybF0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIG5ldyBTd2FnZ2VySHR0cCgpLmV4ZWN1dGUob2JqLCBvcHRzKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sIDApO1xuICAgICAgICB9KSgpO1xuICAgICAgfVxuXG4gICAgICBlbHNlIHtcbiAgICAgICAgcHJvY2Vzc2VkQ2FsbHMgKz0gMTtcbiAgICAgICAgdW5yZXNvbHZlZFJlZnNbaXRlbS5rZXldID0ge1xuICAgICAgICAgIHJvb3Q6IGl0ZW0ucm9vdCxcbiAgICAgICAgICBsb2NhdGlvbjogaXRlbS5sb2NhdGlvblxuICAgICAgICB9O1xuICAgICAgICBpZiAocHJvY2Vzc2VkQ2FsbHMgPT09IGV4cGVjdGVkQ2FsbHMpIHtcbiAgICAgICAgICBzZWxmLmZpbmlzaChzcGVjLCBfcm9vdCwgcmVzb2x1dGlvblRhYmxlLCByZXNvbHZlZFJlZnMsIHVucmVzb2x2ZWRSZWZzLCBjYWxsYmFjayk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KHRvUmVzb2x2ZVtpaV0sIHNwZWMsIHRoaXMsIGxvY2ssIGlpKSk7XG4gIH1cblxuICBpZiAoT2JqZWN0LmtleXModG9SZXNvbHZlKS5sZW5ndGggPT09IDApIHtcbiAgICB0aGlzLmZpbmlzaChzcGVjLCBfcm9vdCwgcmVzb2x1dGlvblRhYmxlLCByZXNvbHZlZFJlZnMsIHVucmVzb2x2ZWRSZWZzLCBjYWxsYmFjayk7XG4gIH1cbn07XG5cblJlc29sdmVyLnByb3RvdHlwZS5yZXNvbHZlSXRlbSA9IGZ1bmN0aW9uKHNwZWMsIHJvb3QsIHJlc29sdXRpb25UYWJsZSwgcmVzb2x2ZWRSZWZzLCB1bnJlc29sdmVkUmVmcywgaXRlbSkge1xuICB2YXIgcGF0aCA9IGl0ZW0ubG9jYXRpb247XG4gIHZhciBsb2NhdGlvbiA9IHNwZWMsIHBhcnRzID0gcGF0aC5zcGxpdCgnLycpO1xuICBpZihwYXRoICE9PSAnJykge1xuICAgIGZvciAodmFyIGogPSAwOyBqIDwgcGFydHMubGVuZ3RoOyBqKyspIHtcbiAgICAgIHZhciBzZWdtZW50ID0gcGFydHNbal07XG4gICAgICBpZiAoc2VnbWVudC5pbmRleE9mKCd+MScpICE9PSAtMSkge1xuICAgICAgICBzZWdtZW50ID0gcGFydHNbal0ucmVwbGFjZSgvfjAvZywgJ34nKS5yZXBsYWNlKC9+MS9nLCAnLycpO1xuICAgICAgICBpZiAoc2VnbWVudC5jaGFyQXQoMCkgIT09ICcvJykge1xuICAgICAgICAgIHNlZ21lbnQgPSAnLycgKyBzZWdtZW50O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIGxvY2F0aW9uID09PSAndW5kZWZpbmVkJyB8fCBsb2NhdGlvbiA9PT0gbnVsbCkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGlmIChzZWdtZW50ID09PSAnJyAmJiBqID09PSAocGFydHMubGVuZ3RoIC0gMSkgJiYgcGFydHMubGVuZ3RoID4gMSkge1xuICAgICAgICBsb2NhdGlvbiA9IG51bGw7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgICAgaWYgKHNlZ21lbnQubGVuZ3RoID4gMCkge1xuICAgICAgICBsb2NhdGlvbiA9IGxvY2F0aW9uW3NlZ21lbnRdO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICB2YXIgcmVzb2x2ZWQgPSBpdGVtLmtleTtcbiAgcGFydHMgPSBpdGVtLmtleS5zcGxpdCgnLycpO1xuICB2YXIgcmVzb2x2ZWROYW1lID0gcGFydHNbcGFydHMubGVuZ3RoLTFdO1xuXG4gIGlmKHJlc29sdmVkTmFtZS5pbmRleE9mKCcjJykgPj0gMCkge1xuICAgIHJlc29sdmVkTmFtZSA9IHJlc29sdmVkTmFtZS5zcGxpdCgnIycpWzFdO1xuICB9XG5cbiAgaWYgKGxvY2F0aW9uICE9PSBudWxsICYmIHR5cGVvZiBsb2NhdGlvbiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXNvbHZlZFJlZnNbcmVzb2x2ZWRdID0ge1xuICAgICAgbmFtZTogcmVzb2x2ZWROYW1lLFxuICAgICAgb2JqOiBsb2NhdGlvbixcbiAgICAgIGtleTogaXRlbS5rZXksXG4gICAgICByb290OiBpdGVtLnJvb3RcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIHVucmVzb2x2ZWRSZWZzW3Jlc29sdmVkXSA9IHtcbiAgICAgIHJvb3Q6IGl0ZW0ucm9vdCxcbiAgICAgIGxvY2F0aW9uOiBpdGVtLmxvY2F0aW9uXG4gICAgfTtcbiAgfVxufTtcblxuUmVzb2x2ZXIucHJvdG90eXBlLmZpbmlzaCA9IGZ1bmN0aW9uIChzcGVjLCByb290LCByZXNvbHV0aW9uVGFibGUsIHJlc29sdmVkUmVmcywgdW5yZXNvbHZlZFJlZnMsIGNhbGxiYWNrLCBsb2NhbFJlc29sdmUpIHtcbiAgLy8gd2FsayByZXNvbHV0aW9uIHRhYmxlIGFuZCByZXBsYWNlIHdpdGggcmVzb2x2ZWQgcmVmc1xuICB2YXIgcmVmLCBhYnM7XG4gIGZvciAocmVmIGluIHJlc29sdXRpb25UYWJsZSkge1xuICAgIHZhciBpdGVtID0gcmVzb2x1dGlvblRhYmxlW3JlZl07XG5cbiAgICB2YXIga2V5ID0gaXRlbS5rZXk7XG4gICAgdmFyIHJlc29sdmVkVG8gPSByZXNvbHZlZFJlZnNba2V5XTtcbiAgICBpZiAocmVzb2x2ZWRUbykge1xuICAgICAgc3BlYy5kZWZpbml0aW9ucyA9IHNwZWMuZGVmaW5pdGlvbnMgfHwge307XG4gICAgICBpZiAoaXRlbS5yZXNvbHZlQXMgPT09ICdyZWYnKSB7XG4gICAgICAgIGlmIChsb2NhbFJlc29sdmUgIT09IHRydWUpIHtcbiAgICAgICAgICAvLyBkb24ndCByZXRhaW4gcm9vdCBmb3IgbG9jYWwgZGVmaW5pdGlvbnNcbiAgICAgICAgICBmb3IgKGtleSBpbiByZXNvbHZlZFRvLm9iaikge1xuICAgICAgICAgICAgYWJzID0gdGhpcy5yZXRhaW5Sb290KGtleSwgcmVzb2x2ZWRUby5vYmpba2V5XSwgaXRlbS5yb290KTtcbiAgICAgICAgICAgIHJlc29sdmVkVG8ub2JqW2tleV0gPSBhYnM7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHNwZWMuZGVmaW5pdGlvbnNbcmVzb2x2ZWRUby5uYW1lXSA9IHJlc29sdmVkVG8ub2JqO1xuICAgICAgICBpdGVtLm9iai4kcmVmID0gJyMvZGVmaW5pdGlvbnMvJyArIHJlc29sdmVkVG8ubmFtZTtcbiAgICAgIH0gZWxzZSBpZiAoaXRlbS5yZXNvbHZlQXMgPT09ICdpbmxpbmUnKSB7XG4gICAgICAgIHZhciB0YXJnZXRPYmogPSBpdGVtLm9iajtcbiAgICAgICAgdGFyZ2V0T2JqWyd4LXJlc29sdmVkLWZyb20nXSA9IFsgaXRlbS5rZXkgXTtcbiAgICAgICAgZGVsZXRlIHRhcmdldE9iai4kcmVmO1xuXG4gICAgICAgIGZvciAoa2V5IGluIHJlc29sdmVkVG8ub2JqKSB7XG4gICAgICAgICAgYWJzID0gcmVzb2x2ZWRUby5vYmpba2V5XTtcblxuICAgICAgICAgIGlmIChsb2NhbFJlc29sdmUgIT09IHRydWUpIHtcbiAgICAgICAgICAgIC8vIGRvbid0IHJldGFpbiByb290IGZvciBsb2NhbCBkZWZpbml0aW9uc1xuICAgICAgICAgICAgYWJzID0gdGhpcy5yZXRhaW5Sb290KGtleSwgcmVzb2x2ZWRUby5vYmpba2V5XSwgaXRlbS5yb290KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGFyZ2V0T2JqW2tleV0gPSBhYnM7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgdmFyIGV4aXN0aW5nVW5yZXNvbHZlZCA9IHRoaXMuY291bnRVbnJlc29sdmVkUmVmcyhzcGVjKTtcblxuICBpZihleGlzdGluZ1VucmVzb2x2ZWQgPT09IDAgfHwgdGhpcy5pdGVyYXRpb24gPiA1KSB7XG4gICAgdGhpcy5yZXNvbHZlQWxsT2Yoc3BlYy5kZWZpbml0aW9ucyk7XG4gICAgdGhpcy5yZXNvbHZlckNhY2hlID0gbnVsbDtcbiAgICBjYWxsYmFjay5jYWxsKHRoaXMuc2NvcGUsIHNwZWMsIHVucmVzb2x2ZWRSZWZzKTtcbiAgfVxuICBlbHNlIHtcbiAgICB0aGlzLml0ZXJhdGlvbiArPSAxO1xuICAgIHRoaXMucmVzb2x2ZShzcGVjLCByb290LCBjYWxsYmFjaywgdGhpcy5zY29wZSk7XG4gIH1cbn07XG5cblJlc29sdmVyLnByb3RvdHlwZS5jb3VudFVucmVzb2x2ZWRSZWZzID0gZnVuY3Rpb24oc3BlYykge1xuICB2YXIgaTtcbiAgdmFyIHJlZnMgPSB0aGlzLmdldFJlZnMoc3BlYyk7XG4gIHZhciBrZXlzID0gW107XG4gIHZhciB1bnJlc29sdmVkS2V5cyA9IFtdO1xuICBmb3IoaSBpbiByZWZzKSB7XG4gICAgaWYoaS5pbmRleE9mKCcjJykgPT09IDApIHtcbiAgICAgIGtleXMucHVzaChpLnN1YnN0cmluZygxKSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgdW5yZXNvbHZlZEtleXMucHVzaChpKTtcbiAgICB9XG4gIH1cblxuICAvLyB2ZXJpZnkgcG9zc2libGUga2V5c1xuICBmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBwYXJ0ID0ga2V5c1tpXTtcbiAgICB2YXIgcGFydHMgPSBwYXJ0LnNwbGl0KCcvJyk7XG4gICAgdmFyIG9iaiA9IHNwZWM7XG5cbiAgICBmb3IgKHZhciBrID0gMDsgayA8IHBhcnRzLmxlbmd0aDsgaysrKSB7XG4gICAgICB2YXIga2V5ID0gcGFydHNba107XG4gICAgICBpZihrZXkgIT09ICcnKSB7XG4gICAgICAgIG9iaiA9IG9ialtrZXldO1xuICAgICAgICBpZih0eXBlb2Ygb2JqID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHVucmVzb2x2ZWRLZXlzLnB1c2gocGFydCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHVucmVzb2x2ZWRLZXlzLmxlbmd0aDtcbn07XG5cblJlc29sdmVyLnByb3RvdHlwZS5nZXRSZWZzID0gZnVuY3Rpb24oc3BlYywgb2JqKSB7XG4gIG9iaiA9IG9iaiB8fCBzcGVjO1xuICB2YXIgb3V0cHV0ID0ge307XG4gIGZvcih2YXIga2V5IGluIG9iaikge1xuICAgIGlmICghb2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICB2YXIgaXRlbSA9IG9ialtrZXldO1xuICAgIGlmKGtleSA9PT0gJyRyZWYnICYmIHR5cGVvZiBpdGVtID09PSAnc3RyaW5nJykge1xuICAgICAgb3V0cHV0W2l0ZW1dID0gbnVsbDtcbiAgICB9XG4gICAgZWxzZSBpZihfLmlzT2JqZWN0KGl0ZW0pKSB7XG4gICAgICB2YXIgbyA9IHRoaXMuZ2V0UmVmcyhpdGVtKTtcbiAgICAgIGZvcih2YXIgayBpbiBvKSB7XG4gICAgICAgIG91dHB1dFtrXSA9IG51bGw7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBvdXRwdXQ7XG59O1xuXG5mdW5jdGlvbiBzcGxpdFVybCh1cmwpIHtcbiAgdmFyIHJlc3VsdCA9IHt9O1xuICB2YXIgcHJvdG8gPSAvW2Etel0rOlxcL1xcLy9pLmV4ZWModXJsKTtcbiAgaWYgKHByb3RvKSB7XG4gICAgcmVzdWx0LnByb3RvID0gcHJvdG9bMF0uc2xpY2UoMCwgLTMpO1xuICAgIHVybCA9IHVybC5zbGljZShyZXN1bHQucHJvdG8ubGVuZ3RoICsgMSk7XG4gIH1cbiAgaWYgKHVybC5zbGljZSgwLCAyKSA9PT0gJy8vJykge1xuICAgIHJlc3VsdC5kb21haW4gPSB1cmwuc2xpY2UoMikuc3BsaXQoJy8nKVswXTtcbiAgICB1cmwgPSB1cmwuc2xpY2UoMiArIHJlc3VsdC5kb21haW4ubGVuZ3RoKTtcbiAgfVxuICB2YXIgcCA9IHVybC5zcGxpdCgnIycpO1xuICBpZiAocFswXS5sZW5ndGgpIHtcbiAgICByZXN1bHQucGF0aCA9IHBbMF07XG4gIH1cbiAgaWYgKHAubGVuZ3RoID4gMSkge1xuICAgIHJlc3VsdC5mcmFnbWVudCA9IHAuc2xpY2UoMSkuam9pbignIycpO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIHVuc3BsaXRVcmwodXJsKSB7XG4gIHZhciByZXN1bHQgPSB1cmwucGF0aDtcbiAgaWYgKHJlc3VsdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmVzdWx0ID0gJyc7XG4gIH1cbiAgaWYgKHVybC5mcmFnbWVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmVzdWx0ICs9ICcjJyArIHVybC5mcmFnbWVudDtcbiAgfVxuICBpZiAodXJsLmRvbWFpbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKHJlc3VsdC5zbGljZSgwLCAxKSA9PT0gJy8nKSB7XG4gICAgICByZXN1bHQgPSByZXN1bHQuc2xpY2UoMSk7XG4gICAgfVxuICAgIHJlc3VsdCA9ICcvLycgKyB1cmwuZG9tYWluICsgJy8nICsgcmVzdWx0O1xuICAgIGlmICh1cmwucHJvdG8gIT09IHVuZGVmaW5lZCkge1xuICAgICAgcmVzdWx0ID0gdXJsLnByb3RvICsgJzonICsgcmVzdWx0O1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBqb2luVXJsKGJhc2UsIHJlbCkge1xuICB2YXIgcmVsc3AgPSBzcGxpdFVybChyZWwpO1xuICBpZiAocmVsc3AuZG9tYWluICE9PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gcmVsO1xuICB9XG4gIHZhciByZXN1bHQgPSBzcGxpdFVybChiYXNlKTtcbiAgaWYgKHJlbHNwLnBhdGggPT09IHVuZGVmaW5lZCkge1xuICAgIC8vIGNoYW5nZSBvbmx5IGZyYWdtZW50IHBhcnRcbiAgICByZXN1bHQuZnJhZ21lbnQgPSByZWxzcC5mcmFnbWVudDtcbiAgfSBlbHNlIGlmIChyZWxzcC5wYXRoLnNsaWNlKDAsIDEpID09PSAnLycpIHtcbiAgICAvLyByZWxhdGl2ZSB0byBkb21haW5cbiAgICByZXN1bHQucGF0aCA9IHJlbHNwLnBhdGg7XG4gICAgcmVzdWx0LmZyYWdtZW50ID0gcmVsc3AuZnJhZ21lbnQ7XG4gIH0gZWxzZSB7XG4gICAgLy8gcmVsYXRpdmUgdG8gcGF0aFxuICAgIHZhciBwYXRoID0gcmVzdWx0LnBhdGggPT09IHVuZGVmaW5lZCA/IFtdIDogcmVzdWx0LnBhdGguc3BsaXQoJy8nKTtcbiAgICB2YXIgcmVscGF0aCA9IHJlbHNwLnBhdGguc3BsaXQoJy8nKTtcbiAgICBpZiAocGF0aC5sZW5ndGgpIHtcbiAgICAgIHBhdGgucG9wKCk7XG4gICAgfVxuICAgIHdoaWxlIChyZWxwYXRoWzBdID09PSAnLi4nIHx8IHJlbHBhdGhbMF0gPT09ICcuJykge1xuICAgICAgaWYgKHJlbHBhdGhbMF0gPT09ICcuLicpIHtcbiAgICAgICAgcGF0aC5wb3AoKTtcbiAgICAgIH1cbiAgICAgIHJlbHBhdGguc2hpZnQoKTtcbiAgICB9XG4gICAgcmVzdWx0LnBhdGggPSBwYXRoLmNvbmNhdChyZWxwYXRoKS5qb2luKCcvJyk7XG4gICAgcmVzdWx0LmZyYWdtZW50ID0gcmVsc3AuZnJhZ21lbnQ7XG4gIH1cbiAgcmV0dXJuIHVuc3BsaXRVcmwocmVzdWx0KTtcbn1cblxuUmVzb2x2ZXIucHJvdG90eXBlLnJldGFpblJvb3QgPSBmdW5jdGlvbihvcmlnS2V5LCBvYmosIHJvb3QpIHtcbiAgLy8gd2FsayBvYmplY3QgYW5kIGxvb2sgZm9yIHJlbGF0aXZlICRyZWZzXG4gIGlmKF8uaXNPYmplY3Qob2JqKSkge1xuICAgIGZvcih2YXIga2V5IGluIG9iaikge1xuICAgICAgdmFyIGl0ZW0gPSBvYmpba2V5XTtcbiAgICAgIGlmIChrZXkgPT09ICckcmVmJyAmJiB0eXBlb2YgaXRlbSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgb2JqW2tleV0gPSBqb2luVXJsKHJvb3QsIGl0ZW0pO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAoXy5pc09iamVjdChpdGVtKSkge1xuICAgICAgICB0aGlzLnJldGFpblJvb3Qoa2V5LCBpdGVtLCByb290KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZWxzZSBpZihfLmlzU3RyaW5nKG9iaikgJiYgb3JpZ0tleSA9PT0gJyRyZWYnKSB7XG4gICAgb2JqID0gam9pblVybChyb290LCBvYmopO1xuICB9XG4gIHJldHVybiBvYmo7XG59O1xuXG4vKipcbiAqIGltbWVkaWF0ZWx5IGluLWxpbmVzIGxvY2FsIHJlZnMsIHF1ZXVlcyByZW1vdGUgcmVmc1xuICogZm9yIGlubGluZSByZXNvbHV0aW9uXG4gKi9cblJlc29sdmVyLnByb3RvdHlwZS5yZXNvbHZlSW5saW5lID0gZnVuY3Rpb24gKHJvb3QsIHNwZWMsIHByb3BlcnR5LCByZXNvbHV0aW9uVGFibGUsIHVucmVzb2x2ZWRSZWZzLCBsb2NhdGlvbikge1xuICB2YXIga2V5ID0gcHJvcGVydHkuJHJlZiwgcmVmID0gcHJvcGVydHkuJHJlZiwgaSwgcCwgcDIsIHJzO1xuICB2YXIgcm9vdFRyaW1tZWQgPSBmYWxzZTtcblxuICByb290ID0gcm9vdCB8fCAnJzsgLy8gR3VhcmQgYWdhaW5zdCAuc3BsaXQuIEBmZWhndXksIHlvdSdsbCBuZWVkIHRvIGNoZWNrIGlmIHRoaXMgbG9naWMgZml0c1xuICAvLyBNb3JlIGltcG9yYW50bHkgaXMgaG93IGRvIHdlIGdyYWNlZnVsbHkgaGFuZGxlIHJlbGF0aXZlIHVybHMsIHdoZW4gcHJvdmlkZWQganVzdCBhICdzcGVjJywgbm90IGEgJ3VybCcgP1xuXG4gIGlmIChyZWYpIHtcbiAgICBpZihyZWYuaW5kZXhPZignLi4vJykgPT09IDApIHtcbiAgICAgIC8vIHJlc2V0IHJvb3RcbiAgICAgIHAgPSByZWYuc3BsaXQoJy4uLycpO1xuICAgICAgcDIgPSByb290LnNwbGl0KCcvJyk7XG4gICAgICByZWYgPSAnJztcbiAgICAgIGZvcihpID0gMDsgaSA8IHAubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYocFtpXSA9PT0gJycpIHtcbiAgICAgICAgICBwMiA9IHAyLnNsaWNlKDAsIHAyLmxlbmd0aC0xKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICByZWYgKz0gcFtpXTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcm9vdCA9ICcnO1xuICAgICAgZm9yKGkgPSAwOyBpIDwgcDIubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgIGlmKGkgPiAwKSB7IHJvb3QgKz0gJy8nOyB9XG4gICAgICAgIHJvb3QgKz0gcDJbaV07XG4gICAgICB9XG4gICAgICByb290VHJpbW1lZCA9IHRydWU7XG4gICAgfVxuICAgIGlmKHJlZi5pbmRleE9mKCcjJykgPj0gMCkge1xuICAgICAgaWYocmVmLmluZGV4T2YoJy8nKSA9PT0gMCkge1xuICAgICAgICBycyA9IHJlZi5zcGxpdCgnIycpO1xuICAgICAgICBwICA9IHJvb3Quc3BsaXQoJy8vJyk7XG4gICAgICAgIHAyID0gcFsxXS5zcGxpdCgnLycpO1xuICAgICAgICByb290ID0gcFswXSArICcvLycgKyBwMlswXSArIHJzWzBdO1xuICAgICAgICBsb2NhdGlvbiA9IHJzWzFdO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIHJzID0gcmVmLnNwbGl0KCcjJyk7XG4gICAgICAgIGlmKHJzWzBdICE9PSAnJykge1xuICAgICAgICAgIHAyID0gcm9vdC5zcGxpdCgnLycpO1xuICAgICAgICAgIHAyID0gcDIuc2xpY2UoMCwgcDIubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgaWYoIXJvb3RUcmltbWVkKSB7XG4gICAgICAgICAgICByb290ID0gJyc7XG4gICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IHAyLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgIGlmKGsgPiAwKSB7IHJvb3QgKz0gJy8nOyB9XG4gICAgICAgICAgICAgIHJvb3QgKz0gcDJba107XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJvb3QgKz0gJy8nICsgcmVmLnNwbGl0KCcjJylbMF07XG4gICAgICAgIH1cbiAgICAgICAgbG9jYXRpb24gPSByc1sxXTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHJlZi5pbmRleE9mKCdodHRwOicpID09PSAwIHx8IHJlZi5pbmRleE9mKCdodHRwczonKSA9PT0gMCkge1xuICAgICAgaWYocmVmLmluZGV4T2YoJyMnKSA+PSAwKSB7XG4gICAgICAgIHJvb3QgPSByZWYuc3BsaXQoJyMnKVswXTtcbiAgICAgICAgbG9jYXRpb24gPSByZWYuc3BsaXQoJyMnKVsxXTtcbiAgICAgIH1cbiAgICAgIGVsc2Uge1xuICAgICAgICByb290ID0gcmVmO1xuICAgICAgICBsb2NhdGlvbiA9ICcnO1xuICAgICAgfVxuICAgICAgcmVzb2x1dGlvblRhYmxlLnB1c2goe29iajogcHJvcGVydHksIHJlc29sdmVBczogJ2lubGluZScsIHJvb3Q6IHJvb3QsIGtleToga2V5LCBsb2NhdGlvbjogbG9jYXRpb259KTtcbiAgICB9IGVsc2UgaWYgKHJlZi5pbmRleE9mKCcjJykgPT09IDApIHtcbiAgICAgIGxvY2F0aW9uID0gcmVmLnNwbGl0KCcjJylbMV07XG4gICAgICByZXNvbHV0aW9uVGFibGUucHVzaCh7b2JqOiBwcm9wZXJ0eSwgcmVzb2x2ZUFzOiAnaW5saW5lJywgcm9vdDogcm9vdCwga2V5OiBrZXksIGxvY2F0aW9uOiBsb2NhdGlvbn0pO1xuICAgIH0gZWxzZSBpZiAocmVmLmluZGV4T2YoJy8nKSA9PT0gMCAmJiByZWYuaW5kZXhPZignIycpID09PSAtMSkge1xuICAgICAgbG9jYXRpb24gPSByZWY7XG4gICAgICB2YXIgbWF0Y2hlcyA9IHJvb3QubWF0Y2goL15odHRwcz9cXDpcXC9cXC8oW15cXC8/I10rKSg/OltcXC8/I118JCkvaSk7XG4gICAgICBpZihtYXRjaGVzKSB7XG4gICAgICAgIHJvb3QgPSBtYXRjaGVzWzBdICsgcmVmLnN1YnN0cmluZygxKTtcbiAgICAgICAgbG9jYXRpb24gPSAnJztcbiAgICAgIH1cbiAgICAgIHJlc29sdXRpb25UYWJsZS5wdXNoKHtvYmo6IHByb3BlcnR5LCByZXNvbHZlQXM6ICdpbmxpbmUnLCByb290OiByb290LCBrZXk6IGtleSwgbG9jYXRpb246IGxvY2F0aW9ufSk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgcmVzb2x1dGlvblRhYmxlLnB1c2goe29iajogcHJvcGVydHksIHJlc29sdmVBczogJ2lubGluZScsIHJvb3Q6IHJvb3QsIGtleToga2V5LCBsb2NhdGlvbjogbG9jYXRpb259KTtcbiAgICB9XG4gIH1cbiAgZWxzZSBpZiAocHJvcGVydHkudHlwZSA9PT0gJ2FycmF5Jykge1xuICAgIHRoaXMucmVzb2x2ZVRvKHJvb3QsIHByb3BlcnR5Lml0ZW1zLCByZXNvbHV0aW9uVGFibGUsIGxvY2F0aW9uKTtcbiAgfVxufTtcblxuUmVzb2x2ZXIucHJvdG90eXBlLnJlc29sdmVUbyA9IGZ1bmN0aW9uIChyb290LCBwcm9wZXJ0eSwgcmVzb2x1dGlvblRhYmxlLCBsb2NhdGlvbikge1xuICB2YXIgc3AsIGk7XG4gIHZhciByZWYgPSBwcm9wZXJ0eS4kcmVmO1xuICB2YXIgbHJvb3QgPSByb290O1xuICBpZiAoKHR5cGVvZiByZWYgIT09ICd1bmRlZmluZWQnKSAmJiAocmVmICE9PSBudWxsKSkge1xuICAgIGlmKHJlZi5pbmRleE9mKCcjJykgPj0gMCkge1xuICAgICAgdmFyIHBhcnRzID0gcmVmLnNwbGl0KCcjJyk7XG5cbiAgICAgIC8vICMvZGVmaW5pdGlvbnMvZm9vXG4gICAgICAvLyBmb28uanNvbiMvYmFyXG4gICAgICBpZihwYXJ0c1swXSAmJiByZWYuaW5kZXhPZignLycpID09PSAwKSB7XG5cbiAgICAgIH1cbiAgICAgIGVsc2UgaWYocGFydHNbMF0gJiYgKHBhcnRzWzBdLmluZGV4T2YoJ2h0dHA6JykgPT09IDAgfHwgcGFydHNbMF0uaW5kZXhPZignaHR0cHM6JykgPT09IDApKSB7XG4gICAgICAgIGxyb290ID0gcGFydHNbMF07XG4gICAgICAgIHJlZiA9IHBhcnRzWzFdO1xuICAgICAgfVxuICAgICAgZWxzZSBpZihwYXJ0c1swXSAmJiBwYXJ0c1swXS5sZW5ndGggPiAwKSB7XG4gICAgICAgIC8vIHJlbGF0aXZlIGZpbGVcbiAgICAgICAgc3AgPSByb290LnNwbGl0KCcvJyk7XG4gICAgICAgIGxyb290ID0gJyc7XG4gICAgICAgIGZvcihpID0gMDsgaSA8IHNwLmxlbmd0aCAtIDE7IGkrKykge1xuICAgICAgICAgIGxyb290ICs9IHNwW2ldICsgJy8nO1xuICAgICAgICB9XG4gICAgICAgIGxyb290ICs9IHBhcnRzWzBdO1xuICAgICAgfVxuICAgICAgZWxzZSB7XG5cbiAgICAgIH1cblxuICAgICAgbG9jYXRpb24gPSBwYXJ0c1sxXTtcbiAgICB9XG4gICAgZWxzZSBpZiAocmVmLmluZGV4T2YoJ2h0dHA6JykgPT09IDAgfHwgcmVmLmluZGV4T2YoJ2h0dHBzOicpID09PSAwKSB7XG4gICAgICBscm9vdCA9IHJlZjtcbiAgICAgIGxvY2F0aW9uID0gJyc7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgLy8gcmVsYXRpdmUgZmlsZVxuICAgICAgc3AgPSByb290LnNwbGl0KCcvJyk7XG4gICAgICBscm9vdCA9ICcnO1xuICAgICAgZm9yKGkgPSAwOyBpIDwgc3AubGVuZ3RoIC0gMTsgaSsrKSB7XG4gICAgICAgIGxyb290ICs9IHNwW2ldICsgJy8nO1xuICAgICAgfVxuICAgICAgbHJvb3QgKz0gcmVmO1xuICAgICAgbG9jYXRpb24gPSAnJztcbiAgICB9XG4gICAgcmVzb2x1dGlvblRhYmxlLnB1c2goe1xuICAgICAgb2JqOiBwcm9wZXJ0eSwgcmVzb2x2ZUFzOiAncmVmJywgcm9vdDogbHJvb3QsIGtleTogcmVmLCBsb2NhdGlvbjogbG9jYXRpb25cbiAgICB9KTtcbiAgfSBlbHNlIGlmIChwcm9wZXJ0eS50eXBlID09PSAnYXJyYXknKSB7XG4gICAgdmFyIGl0ZW1zID0gcHJvcGVydHkuaXRlbXM7XG4gICAgdGhpcy5yZXNvbHZlVG8ocm9vdCwgaXRlbXMsIHJlc29sdXRpb25UYWJsZSwgbG9jYXRpb24pO1xuICB9IGVsc2Uge1xuICAgIGlmKHByb3BlcnR5ICYmIChwcm9wZXJ0eS5wcm9wZXJ0aWVzIHx8IHByb3BlcnR5LmFkZGl0aW9uYWxQcm9wZXJ0aWVzKSkge1xuICAgICAgdmFyIG5hbWUgPSB0aGlzLnVuaXF1ZU5hbWUoJ2lubGluZV9tb2RlbCcpO1xuICAgICAgaWYgKHByb3BlcnR5LnRpdGxlKSB7XG4gICAgICAgIG5hbWUgPSB0aGlzLnVuaXF1ZU5hbWUocHJvcGVydHkudGl0bGUpO1xuICAgICAgfVxuICAgICAgZGVsZXRlIHByb3BlcnR5LnRpdGxlO1xuICAgICAgdGhpcy5zcGVjLmRlZmluaXRpb25zW25hbWVdID0gXy5jbG9uZURlZXAocHJvcGVydHkpO1xuICAgICAgcHJvcGVydHkuJHJlZiA9ICcjL2RlZmluaXRpb25zLycgKyBuYW1lO1xuICAgICAgZGVsZXRlIHByb3BlcnR5LnR5cGU7XG4gICAgICBkZWxldGUgcHJvcGVydHkucHJvcGVydGllcztcbiAgICB9XG4gIH1cbn07XG5cblJlc29sdmVyLnByb3RvdHlwZS51bmlxdWVOYW1lID0gZnVuY3Rpb24oYmFzZSkge1xuICB2YXIgbmFtZSA9IGJhc2U7XG4gIHZhciBjb3VudCA9IDA7XG4gIHdoaWxlKHRydWUpIHtcbiAgICBpZighXy5pc09iamVjdCh0aGlzLnNwZWMuZGVmaW5pdGlvbnNbbmFtZV0pKSB7XG4gICAgICByZXR1cm4gbmFtZTtcbiAgICB9XG4gICAgbmFtZSA9IGJhc2UgKyAnXycgKyBjb3VudDtcbiAgICBjb3VudCsrO1xuICB9XG59O1xuXG5SZXNvbHZlci5wcm90b3R5cGUucmVzb2x2ZUFsbE9mID0gZnVuY3Rpb24oc3BlYywgb2JqLCBkZXB0aCkge1xuICBkZXB0aCA9IGRlcHRoIHx8IDA7XG4gIG9iaiA9IG9iaiB8fCBzcGVjO1xuICB2YXIgbmFtZTtcbiAgZm9yKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgaWYgKCFvYmouaGFzT3duUHJvcGVydHkoa2V5KSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHZhciBpdGVtID0gb2JqW2tleV07XG4gICAgaWYoaXRlbSA9PT0gbnVsbCkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignU3dhZ2dlciAyLjAgZG9lcyBub3Qgc3VwcG9ydCBudWxsIHR5cGVzICgnICsgb2JqICsgJykuICBTZWUgaHR0cHM6Ly9naXRodWIuY29tL3N3YWdnZXItYXBpL3N3YWdnZXItc3BlYy9pc3N1ZXMvMjI5LicpO1xuICAgIH1cbiAgICBpZih0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHRoaXMucmVzb2x2ZUFsbE9mKHNwZWMsIGl0ZW0sIGRlcHRoICsgMSk7XG4gICAgfVxuICAgIGlmKGl0ZW0gJiYgdHlwZW9mIGl0ZW0uYWxsT2YgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB2YXIgYWxsT2YgPSBpdGVtLmFsbE9mO1xuICAgICAgaWYoXy5pc0FycmF5KGFsbE9mKSkge1xuICAgICAgICB2YXIgb3V0cHV0ID0gXy5jbG9uZURlZXAoaXRlbSk7XG4gICAgICAgIGRlbGV0ZSBvdXRwdXQuYWxsT2Y7XG5cbiAgICAgICAgb3V0cHV0Wyd4LWNvbXBvc2VkJ10gPSB0cnVlO1xuICAgICAgICBpZiAodHlwZW9mIGl0ZW1bJ3gtcmVzb2x2ZWQtZnJvbSddICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIG91dHB1dFsneC1yZXNvbHZlZC1mcm9tJ10gPSBpdGVtWyd4LXJlc29sdmVkLWZyb20nXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCBhbGxPZi5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciBjb21wb25lbnQgPSBhbGxPZltpXTtcbiAgICAgICAgICB2YXIgc291cmNlID0gJ3NlbGYnO1xuICAgICAgICAgIGlmKHR5cGVvZiBjb21wb25lbnRbJ3gtcmVzb2x2ZWQtZnJvbSddICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgc291cmNlID0gY29tcG9uZW50Wyd4LXJlc29sdmVkLWZyb20nXVswXTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBmb3IodmFyIHBhcnQgaW4gY29tcG9uZW50KSB7XG4gICAgICAgICAgICBpZighb3V0cHV0Lmhhc093blByb3BlcnR5KHBhcnQpKSB7XG4gICAgICAgICAgICAgIG91dHB1dFtwYXJ0XSA9IF8uY2xvbmVEZWVwKGNvbXBvbmVudFtwYXJ0XSk7XG4gICAgICAgICAgICAgIGlmKHBhcnQgPT09ICdwcm9wZXJ0aWVzJykge1xuICAgICAgICAgICAgICAgIGZvcihuYW1lIGluIG91dHB1dFtwYXJ0XSkge1xuICAgICAgICAgICAgICAgICAgb3V0cHV0W3BhcnRdW25hbWVdWyd4LXJlc29sdmVkLWZyb20nXSA9IHNvdXJjZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICBpZihwYXJ0ID09PSAncHJvcGVydGllcycpIHtcbiAgICAgICAgICAgICAgICB2YXIgcHJvcGVydGllcyA9IGNvbXBvbmVudFtwYXJ0XTtcbiAgICAgICAgICAgICAgICBmb3IobmFtZSBpbiBwcm9wZXJ0aWVzKSB7XG4gICAgICAgICAgICAgICAgICBvdXRwdXQucHJvcGVydGllc1tuYW1lXSA9IF8uY2xvbmVEZWVwKHByb3BlcnRpZXNbbmFtZV0pO1xuICAgICAgICAgICAgICAgICAgdmFyIHJlc29sdmVkRnJvbSA9IHByb3BlcnRpZXNbbmFtZV1bJ3gtcmVzb2x2ZWQtZnJvbSddO1xuICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiByZXNvbHZlZEZyb20gPT09ICd1bmRlZmluZWQnIHx8IHJlc29sdmVkRnJvbSA9PT0gJ3NlbGYnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmVkRnJvbSA9IHNvdXJjZTtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIG91dHB1dC5wcm9wZXJ0aWVzW25hbWVdWyd4LXJlc29sdmVkLWZyb20nXSA9IHJlc29sdmVkRnJvbTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWxzZSBpZihwYXJ0ID09PSAncmVxdWlyZWQnKSB7XG4gICAgICAgICAgICAgICAgLy8gbWVyZ2UgJiBkZWR1cCB0aGUgcmVxdWlyZWQgYXJyYXlcbiAgICAgICAgICAgICAgICB2YXIgYSA9IG91dHB1dC5yZXF1aXJlZC5jb25jYXQoY29tcG9uZW50W3BhcnRdKTtcbiAgICAgICAgICAgICAgICBmb3IodmFyIGsgPSAwOyBrIDwgYS5sZW5ndGg7ICsraykge1xuICAgICAgICAgICAgICAgICAgZm9yKHZhciBqID0gayArIDE7IGogPCBhLmxlbmd0aDsgKytqKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmKGFba10gPT09IGFbal0pIHsgYS5zcGxpY2Uoai0tLCAxKTsgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBvdXRwdXQucmVxdWlyZWQgPSBhO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGVsc2UgaWYocGFydCA9PT0gJ3gtcmVzb2x2ZWQtZnJvbScpIHtcbiAgICAgICAgICAgICAgICBvdXRwdXRbJ3gtcmVzb2x2ZWQtZnJvbSddLnB1c2goc291cmNlKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBuZWVkIHRvIG1lcmdlIHRoaXMgcHJvcGVydHlcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnd2hhdCB0byBkbyB3aXRoICcgKyBwYXJ0KVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIG9ialtrZXldID0gb3V0cHV0O1xuICAgICAgfVxuICAgIH1cbiAgfVxufTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIEhlbHBlcnMgPSByZXF1aXJlKCcuL2hlbHBlcnMnKTtcblxudmFyIF8gPSB7XG4gIGlzUGxhaW5PYmplY3Q6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvbGFuZy9pc1BsYWluT2JqZWN0JyksXG4gIGlzVW5kZWZpbmVkOiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvaXNVbmRlZmluZWQnKSxcbiAgaXNBcnJheTogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9sYW5nL2lzQXJyYXknKSxcbiAgaXNPYmplY3Q6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvbGFuZy9pc09iamVjdCcpLFxuICBpc0VtcHR5OiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvaXNFbXB0eScpLFxuICBtYXA6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvY29sbGVjdGlvbi9tYXAnKSxcbiAgaW5kZXhPZjogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9hcnJheS9pbmRleE9mJyksXG4gIGNsb25lRGVlcDogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9sYW5nL2Nsb25lRGVlcCcpLFxuICBrZXlzOiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L29iamVjdC9rZXlzJyksXG4gIGZvckVhY2g6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvY29sbGVjdGlvbi9mb3JFYWNoJylcbn07XG5cbnZhciBvcHRpb25IdG1sID0gbW9kdWxlLmV4cG9ydHMub3B0aW9uSHRtbCA9IGZ1bmN0aW9uICAobGFiZWwsIHZhbHVlKSB7XG4gIHJldHVybiAnPHRyPjx0ZCBjbGFzcz1cIm9wdGlvbk5hbWVcIj4nICsgbGFiZWwgKyAnOjwvdGQ+PHRkPicgKyB2YWx1ZSArICc8L3RkPjwvdHI+Jztcbn07XG5cbm1vZHVsZS5leHBvcnRzLnR5cGVGcm9tSnNvblNjaGVtYSA9IGZ1bmN0aW9uICh0eXBlLCBmb3JtYXQpIHtcbiAgdmFyIHN0cjtcblxuICBpZiAodHlwZSA9PT0gJ2ludGVnZXInICYmIGZvcm1hdCA9PT0gJ2ludDMyJykge1xuICAgIHN0ciA9ICdpbnRlZ2VyJztcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnaW50ZWdlcicgJiYgZm9ybWF0ID09PSAnaW50NjQnKSB7XG4gICAgc3RyID0gJ2xvbmcnO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdpbnRlZ2VyJyAmJiB0eXBlb2YgZm9ybWF0ID09PSAndW5kZWZpbmVkJykge1xuICAgIHN0ciA9ICdsb25nJztcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJyAmJiBmb3JtYXQgPT09ICdkYXRlLXRpbWUnKSB7XG4gICAgc3RyID0gJ2RhdGUtdGltZSc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycgJiYgZm9ybWF0ID09PSAnZGF0ZScpIHtcbiAgICBzdHIgPSAnZGF0ZSc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ251bWJlcicgJiYgZm9ybWF0ID09PSAnZmxvYXQnKSB7XG4gICAgc3RyID0gJ2Zsb2F0JztcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJyAmJiBmb3JtYXQgPT09ICdkb3VibGUnKSB7XG4gICAgc3RyID0gJ2RvdWJsZSc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ251bWJlcicgJiYgdHlwZW9mIGZvcm1hdCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBzdHIgPSAnZG91YmxlJztcbiAgfSBlbHNlIGlmICh0eXBlID09PSAnYm9vbGVhbicpIHtcbiAgICBzdHIgPSAnYm9vbGVhbic7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICBzdHIgPSAnc3RyaW5nJztcbiAgfVxuXG4gIHJldHVybiBzdHI7XG59O1xuXG52YXIgZ2V0U3RyaW5nU2lnbmF0dXJlID0gbW9kdWxlLmV4cG9ydHMuZ2V0U3RyaW5nU2lnbmF0dXJlID0gZnVuY3Rpb24gKG9iaiwgYmFzZUNvbXBvbmVudCkge1xuICB2YXIgc3RyID0gJyc7XG5cbiAgaWYgKHR5cGVvZiBvYmouJHJlZiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBzdHIgKz0gSGVscGVycy5zaW1wbGVSZWYob2JqLiRyZWYpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBvYmoudHlwZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBzdHIgKz0gJ29iamVjdCc7XG4gIH0gZWxzZSBpZiAob2JqLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICBpZiAoYmFzZUNvbXBvbmVudCkge1xuICAgICAgc3RyICs9IGdldFN0cmluZ1NpZ25hdHVyZSgob2JqLml0ZW1zIHx8IG9iai4kcmVmIHx8IHt9KSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciArPSAnQXJyYXlbJztcbiAgICAgIHN0ciArPSBnZXRTdHJpbmdTaWduYXR1cmUoKG9iai5pdGVtcyB8fCBvYmouJHJlZiB8fCB7fSkpO1xuICAgICAgc3RyICs9ICddJztcbiAgICB9XG4gIH0gZWxzZSBpZiAob2JqLnR5cGUgPT09ICdpbnRlZ2VyJyAmJiBvYmouZm9ybWF0ID09PSAnaW50MzInKSB7XG4gICAgc3RyICs9ICdpbnRlZ2VyJztcbiAgfSBlbHNlIGlmIChvYmoudHlwZSA9PT0gJ2ludGVnZXInICYmIG9iai5mb3JtYXQgPT09ICdpbnQ2NCcpIHtcbiAgICBzdHIgKz0gJ2xvbmcnO1xuICB9IGVsc2UgaWYgKG9iai50eXBlID09PSAnaW50ZWdlcicgJiYgdHlwZW9mIG9iai5mb3JtYXQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgc3RyICs9ICdsb25nJztcbiAgfSBlbHNlIGlmIChvYmoudHlwZSA9PT0gJ3N0cmluZycgJiYgb2JqLmZvcm1hdCA9PT0gJ2RhdGUtdGltZScpIHtcbiAgICBzdHIgKz0gJ2RhdGUtdGltZSc7XG4gIH0gZWxzZSBpZiAob2JqLnR5cGUgPT09ICdzdHJpbmcnICYmIG9iai5mb3JtYXQgPT09ICdkYXRlJykge1xuICAgIHN0ciArPSAnZGF0ZSc7XG4gIH0gZWxzZSBpZiAob2JqLnR5cGUgPT09ICdzdHJpbmcnICYmIHR5cGVvZiBvYmouZm9ybWF0ID09PSAndW5kZWZpbmVkJykge1xuICAgIHN0ciArPSAnc3RyaW5nJztcbiAgfSBlbHNlIGlmIChvYmoudHlwZSA9PT0gJ251bWJlcicgJiYgb2JqLmZvcm1hdCA9PT0gJ2Zsb2F0Jykge1xuICAgIHN0ciArPSAnZmxvYXQnO1xuICB9IGVsc2UgaWYgKG9iai50eXBlID09PSAnbnVtYmVyJyAmJiBvYmouZm9ybWF0ID09PSAnZG91YmxlJykge1xuICAgIHN0ciArPSAnZG91YmxlJztcbiAgfSBlbHNlIGlmIChvYmoudHlwZSA9PT0gJ251bWJlcicgJiYgdHlwZW9mIG9iai5mb3JtYXQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgc3RyICs9ICdkb3VibGUnO1xuICB9IGVsc2UgaWYgKG9iai50eXBlID09PSAnYm9vbGVhbicpIHtcbiAgICBzdHIgKz0gJ2Jvb2xlYW4nO1xuICB9IGVsc2UgaWYgKG9iai4kcmVmKSB7XG4gICAgc3RyICs9IEhlbHBlcnMuc2ltcGxlUmVmKG9iai4kcmVmKTtcbiAgfSBlbHNlIHtcbiAgICBzdHIgKz0gb2JqLnR5cGU7XG4gIH1cblxuICByZXR1cm4gc3RyO1xufTtcblxudmFyIHNjaGVtYVRvSlNPTiA9IG1vZHVsZS5leHBvcnRzLnNjaGVtYVRvSlNPTiA9IGZ1bmN0aW9uIChzY2hlbWEsIG1vZGVscywgbW9kZWxzVG9JZ25vcmUsIG1vZGVsUHJvcGVydHlNYWNybykge1xuICAvLyBSZXNvbHZlIHRoZSBzY2hlbWEgKEhhbmRsZSBuZXN0ZWQgc2NoZW1hcylcbiAgc2NoZW1hID0gSGVscGVycy5yZXNvbHZlU2NoZW1hKHNjaGVtYSk7XG5cbiAgaWYodHlwZW9mIG1vZGVsUHJvcGVydHlNYWNybyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIG1vZGVsUHJvcGVydHlNYWNybyA9IGZ1bmN0aW9uKHByb3Ape1xuICAgICAgcmV0dXJuIChwcm9wIHx8IHt9KS5kZWZhdWx0O1xuICAgIH07XG4gIH1cblxuICBtb2RlbHNUb0lnbm9yZT0gbW9kZWxzVG9JZ25vcmUgfHwge307XG5cbiAgdmFyIHR5cGUgPSBzY2hlbWEudHlwZSB8fCAnb2JqZWN0JztcbiAgdmFyIGZvcm1hdCA9IHNjaGVtYS5mb3JtYXQ7XG4gIHZhciBtb2RlbDtcbiAgdmFyIG91dHB1dDtcblxuICBpZiAoIV8uaXNVbmRlZmluZWQoc2NoZW1hLmV4YW1wbGUpKSB7XG4gICAgb3V0cHV0ID0gc2NoZW1hLmV4YW1wbGU7XG4gIH0gZWxzZSBpZiAoXy5pc1VuZGVmaW5lZChzY2hlbWEuaXRlbXMpICYmIF8uaXNBcnJheShzY2hlbWEuZW51bSkpIHtcbiAgICBvdXRwdXQgPSBzY2hlbWEuZW51bVswXTtcbiAgfVxuXG4gIGlmIChfLmlzVW5kZWZpbmVkKG91dHB1dCkpIHtcbiAgICBpZiAoc2NoZW1hLiRyZWYpIHtcbiAgICAgIG1vZGVsID0gbW9kZWxzW0hlbHBlcnMuc2ltcGxlUmVmKHNjaGVtYS4kcmVmKV07XG5cbiAgICAgIGlmICghXy5pc1VuZGVmaW5lZChtb2RlbCkpIHtcbiAgICAgICAgaWYgKF8uaXNVbmRlZmluZWQobW9kZWxzVG9JZ25vcmVbbW9kZWwubmFtZV0pKSB7XG4gICAgICAgICAgbW9kZWxzVG9JZ25vcmVbbW9kZWwubmFtZV0gPSBtb2RlbDtcbiAgICAgICAgICBvdXRwdXQgPSBzY2hlbWFUb0pTT04obW9kZWwuZGVmaW5pdGlvbiwgbW9kZWxzLCBtb2RlbHNUb0lnbm9yZSwgbW9kZWxQcm9wZXJ0eU1hY3JvKTtcbiAgICAgICAgICBkZWxldGUgbW9kZWxzVG9JZ25vcmVbbW9kZWwubmFtZV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKG1vZGVsLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgICAgIG91dHB1dCA9IFtdO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvdXRwdXQgPSB7fTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKCFfLmlzVW5kZWZpbmVkKHNjaGVtYS5kZWZhdWx0KSkge1xuICAgICAgb3V0cHV0ID0gc2NoZW1hLmRlZmF1bHQ7XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgaWYgKGZvcm1hdCA9PT0gJ2RhdGUtdGltZScpIHtcbiAgICAgICAgb3V0cHV0ID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xuICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09ICdkYXRlJykge1xuICAgICAgICBvdXRwdXQgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkuc3BsaXQoJ1QnKVswXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG91dHB1dCA9ICdzdHJpbmcnO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2ludGVnZXInKSB7XG4gICAgICBvdXRwdXQgPSAwO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIG91dHB1dCA9IDAuMDtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdib29sZWFuJykge1xuICAgICAgb3V0cHV0ID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICBvdXRwdXQgPSB7fTtcblxuICAgICAgXy5mb3JFYWNoKHNjaGVtYS5wcm9wZXJ0aWVzLCBmdW5jdGlvbiAocHJvcGVydHksIG5hbWUpIHtcbiAgICAgICAgdmFyIGNQcm9wZXJ0eSA9IF8uY2xvbmVEZWVwKHByb3BlcnR5KTtcblxuICAgICAgICAvLyBBbGxvdyBtYWNybyB0byBzZXQgdGhlIGRlZmF1bHQgdmFsdWVcbiAgICAgICAgY1Byb3BlcnR5LmRlZmF1bHQgPSBtb2RlbFByb3BlcnR5TWFjcm8ocHJvcGVydHkpO1xuXG4gICAgICAgIG91dHB1dFtuYW1lXSA9IHNjaGVtYVRvSlNPTihjUHJvcGVydHksIG1vZGVscywgbW9kZWxzVG9JZ25vcmUsIG1vZGVsUHJvcGVydHlNYWNybyk7XG4gICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgIG91dHB1dCA9IFtdO1xuXG4gICAgICBpZiAoXy5pc0FycmF5KHNjaGVtYS5pdGVtcykpIHtcbiAgICAgICAgXy5mb3JFYWNoKHNjaGVtYS5pdGVtcywgZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICAgICAgICBvdXRwdXQucHVzaChzY2hlbWFUb0pTT04oaXRlbSwgbW9kZWxzLCBtb2RlbHNUb0lnbm9yZSwgbW9kZWxQcm9wZXJ0eU1hY3JvKSk7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChfLmlzUGxhaW5PYmplY3Qoc2NoZW1hLml0ZW1zKSkge1xuICAgICAgICBvdXRwdXQucHVzaChzY2hlbWFUb0pTT04oc2NoZW1hLml0ZW1zLCBtb2RlbHMsIG1vZGVsc1RvSWdub3JlLCBtb2RlbFByb3BlcnR5TWFjcm8pKTtcbiAgICAgIH0gZWxzZSBpZiAoXy5pc1VuZGVmaW5lZChzY2hlbWEuaXRlbXMpKSB7XG4gICAgICAgIG91dHB1dC5wdXNoKHt9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIEhlbHBlcnMubG9nKCdBcnJheSB0eXBlXFwncyBcXCdpdGVtc1xcJyBwcm9wZXJ0eSBpcyBub3QgYW4gYXJyYXkgb3IgYW4gb2JqZWN0LCBjYW5ub3QgcHJvY2VzcycpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBvdXRwdXQ7XG59O1xuXG5tb2R1bGUuZXhwb3J0cy5zY2hlbWFUb0hUTUwgPWZ1bmN0aW9uIChuYW1lLCBzY2hlbWEsIG1vZGVscywgbW9kZWxQcm9wZXJ0eU1hY3JvKSB7XG4gIHZhciBzdHJvbmdPcGVuID0gJzxzcGFuIGNsYXNzPVwic3Ryb25nXCI+JztcbiAgdmFyIHN0cm9uZ0Nsb3NlID0gJzwvc3Bhbj4nO1xuXG4gIC8vIEFsbG93IGZvciBpZ25vcmluZyB0aGUgJ25hbWUnIGFyZ3VtZW50Li4uLiBzaGlmdGluZyB0aGUgcmVzdFxuICBpZihfLmlzT2JqZWN0KGFyZ3VtZW50c1swXSkpIHtcbiAgICBuYW1lID0gdm9pZCAwO1xuICAgIHNjaGVtYSA9IGFyZ3VtZW50c1swXTtcbiAgICBtb2RlbHMgPSBhcmd1bWVudHNbMV07XG4gICAgbW9kZWxQcm9wZXJ0eU1hY3JvID0gYXJndW1lbnRzWzJdO1xuICB9XG5cbiAgbW9kZWxzID0gbW9kZWxzIHx8IHt9O1xuXG4gIC8vIFJlc29sdmUgdGhlIHNjaGVtYSAoSGFuZGxlIG5lc3RlZCBzY2hlbWFzKVxuICBzY2hlbWEgPSBIZWxwZXJzLnJlc29sdmVTY2hlbWEoc2NoZW1hKTtcblxuICAvLyBSZXR1cm4gZm9yIGVtcHR5IG9iamVjdFxuICBpZihfLmlzRW1wdHkoc2NoZW1hKSkge1xuICAgIHJldHVybiBzdHJvbmdPcGVuICsgJ0VtcHR5JyArIHN0cm9uZ0Nsb3NlO1xuICB9XG5cbiAgLy8gRGVyZWZlcmVuY2UgJHJlZiBmcm9tICdtb2RlbHMnXG4gIGlmKHR5cGVvZiBzY2hlbWEuJHJlZiA9PT0gJ3N0cmluZycpIHtcbiAgICBuYW1lID0gSGVscGVycy5zaW1wbGVSZWYoc2NoZW1hLiRyZWYpO1xuICAgIHNjaGVtYSA9IG1vZGVsc1tuYW1lXTtcbiAgICBpZih0eXBlb2Ygc2NoZW1hID09PSAndW5kZWZpbmVkJylcbiAgICB7XG4gICAgICByZXR1cm4gc3Ryb25nT3BlbiArIG5hbWUgKyAnIGlzIG5vdCBkZWZpbmVkIScgKyBzdHJvbmdDbG9zZTtcbiAgICB9XG4gIH1cblxuICBpZih0eXBlb2YgbmFtZSAhPT0gJ3N0cmluZycpIHtcbiAgICBuYW1lID0gc2NoZW1hLnRpdGxlIHx8ICdJbmxpbmUgTW9kZWwnO1xuICB9XG5cbiAgLy8gSWYgd2UgYXJlIGEgTW9kZWwgb2JqZWN0Li4uIGFkanVzdCBhY2NvcmRpbmdseVxuICBpZihzY2hlbWEuZGVmaW5pdGlvbikge1xuICAgIHNjaGVtYSA9IHNjaGVtYS5kZWZpbml0aW9uO1xuICB9XG5cbiAgaWYodHlwZW9mIG1vZGVsUHJvcGVydHlNYWNybyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIG1vZGVsUHJvcGVydHlNYWNybyA9IGZ1bmN0aW9uKHByb3Ape1xuICAgICAgcmV0dXJuIChwcm9wIHx8IHt9KS5kZWZhdWx0O1xuICAgIH07XG4gIH1cblxuICB2YXIgcmVmZXJlbmNlcyA9IHt9O1xuICB2YXIgc2Vlbk1vZGVscyA9IFtdO1xuICB2YXIgaW5saW5lTW9kZWxzID0gMDtcblxuXG5cbiAgLy8gR2VuZXJhdGUgY3VycmVudCBIVE1MXG4gIHZhciBodG1sID0gcHJvY2Vzc01vZGVsKHNjaGVtYSwgbmFtZSk7XG5cbiAgLy8gR2VuZXJhdGUgcmVmZXJlbmNlcyBIVE1MXG4gIHdoaWxlIChfLmtleXMocmVmZXJlbmNlcykubGVuZ3RoID4gMCkge1xuICAgIC8qIGpzaGludCBpZ25vcmU6c3RhcnQgKi9cbiAgICBfLmZvckVhY2gocmVmZXJlbmNlcywgZnVuY3Rpb24gKHNjaGVtYSwgbmFtZSkge1xuICAgICAgdmFyIHNlZW5Nb2RlbCA9IF8uaW5kZXhPZihzZWVuTW9kZWxzLCBuYW1lKSA+IC0xO1xuXG4gICAgICBkZWxldGUgcmVmZXJlbmNlc1tuYW1lXTtcblxuICAgICAgaWYgKCFzZWVuTW9kZWwpIHtcbiAgICAgICAgc2Vlbk1vZGVscy5wdXNoKG5hbWUpO1xuXG4gICAgICAgIGh0bWwgKz0gJzxiciAvPicgKyBwcm9jZXNzTW9kZWwoc2NoZW1hLCBuYW1lKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICAvKiBqc2hpbnQgaWdub3JlOmVuZCAqL1xuICB9XG5cbiAgcmV0dXJuIGh0bWw7XG5cbiAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG5cbiAgZnVuY3Rpb24gYWRkUmVmZXJlbmNlKHNjaGVtYSwgbmFtZSwgc2tpcFJlZikge1xuICAgIHZhciBtb2RlbE5hbWUgPSBuYW1lO1xuICAgIHZhciBtb2RlbDtcblxuICAgIGlmIChzY2hlbWEuJHJlZikge1xuICAgICAgbW9kZWxOYW1lID0gc2NoZW1hLnRpdGxlIHx8IEhlbHBlcnMuc2ltcGxlUmVmKHNjaGVtYS4kcmVmKTtcbiAgICAgIG1vZGVsID0gbW9kZWxzW21vZGVsTmFtZV07XG4gICAgfSBlbHNlIGlmIChfLmlzVW5kZWZpbmVkKG5hbWUpKSB7XG4gICAgICBtb2RlbE5hbWUgPSBzY2hlbWEudGl0bGUgfHwgJ0lubGluZSBNb2RlbCAnICsgKCsraW5saW5lTW9kZWxzKTtcbiAgICAgIG1vZGVsID0ge2RlZmluaXRpb246IHNjaGVtYX07XG4gICAgfVxuXG4gICAgaWYgKHNraXBSZWYgIT09IHRydWUpIHtcbiAgICAgIHJlZmVyZW5jZXNbbW9kZWxOYW1lXSA9IF8uaXNVbmRlZmluZWQobW9kZWwpID8ge30gOiBtb2RlbC5kZWZpbml0aW9uO1xuICAgIH1cblxuICAgIHJldHVybiBtb2RlbE5hbWU7XG4gIH1cblxuICBmdW5jdGlvbiBwcmltaXRpdmVUb0hUTUwoc2NoZW1hKSB7XG4gICAgdmFyIGh0bWwgPSAnPHNwYW4gY2xhc3M9XCJwcm9wVHlwZVwiPic7XG4gICAgdmFyIHR5cGUgPSBzY2hlbWEudHlwZSB8fCAnb2JqZWN0JztcblxuICAgIGlmIChzY2hlbWEuJHJlZikge1xuICAgICAgaHRtbCArPSBhZGRSZWZlcmVuY2Uoc2NoZW1hLCBIZWxwZXJzLnNpbXBsZVJlZihzY2hlbWEuJHJlZikpO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGlmICghXy5pc1VuZGVmaW5lZChzY2hlbWEucHJvcGVydGllcykpIHtcbiAgICAgICAgaHRtbCArPSBhZGRSZWZlcmVuY2Uoc2NoZW1hKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGh0bWwgKz0gJ29iamVjdCc7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnYXJyYXknKSB7XG4gICAgICBodG1sICs9ICdBcnJheVsnO1xuXG4gICAgICBpZiAoXy5pc0FycmF5KHNjaGVtYS5pdGVtcykpIHtcbiAgICAgICAgaHRtbCArPSBfLm1hcChzY2hlbWEuaXRlbXMsIGFkZFJlZmVyZW5jZSkuam9pbignLCcpO1xuICAgICAgfSBlbHNlIGlmIChfLmlzUGxhaW5PYmplY3Qoc2NoZW1hLml0ZW1zKSkge1xuICAgICAgICBpZiAoXy5pc1VuZGVmaW5lZChzY2hlbWEuaXRlbXMuJHJlZikpIHtcbiAgICAgICAgICBpZiAoIV8uaXNVbmRlZmluZWQoc2NoZW1hLml0ZW1zLnR5cGUpICYmIF8uaW5kZXhPZihbJ2FycmF5JywgJ29iamVjdCddLCBzY2hlbWEuaXRlbXMudHlwZSkgPT09IC0xKSB7XG4gICAgICAgICAgICBodG1sICs9IHNjaGVtYS5pdGVtcy50eXBlO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBodG1sICs9IGFkZFJlZmVyZW5jZShzY2hlbWEuaXRlbXMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBodG1sICs9IGFkZFJlZmVyZW5jZShzY2hlbWEuaXRlbXMsIEhlbHBlcnMuc2ltcGxlUmVmKHNjaGVtYS5pdGVtcy4kcmVmKSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIEhlbHBlcnMubG9nKCdBcnJheSB0eXBlXFwncyBcXCdpdGVtc1xcJyBzY2hlbWEgaXMgbm90IGFuIGFycmF5IG9yIGFuIG9iamVjdCwgY2Fubm90IHByb2Nlc3MnKTtcbiAgICAgICAgaHRtbCArPSAnb2JqZWN0JztcbiAgICAgIH1cblxuICAgICAgaHRtbCArPSAnXSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGh0bWwgKz0gc2NoZW1hLnR5cGU7XG4gICAgfVxuXG4gICAgaHRtbCArPSAnPC9zcGFuPic7XG5cbiAgICByZXR1cm4gaHRtbDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHByaW1pdGl2ZVRvT3B0aW9uc0hUTUwoc2NoZW1hLCBodG1sKSB7XG4gICAgdmFyIG9wdGlvbnMgPSAnJztcbiAgICB2YXIgdHlwZSA9IHNjaGVtYS50eXBlIHx8ICdvYmplY3QnO1xuICAgIHZhciBpc0FycmF5ID0gdHlwZSA9PT0gJ2FycmF5JztcblxuICAgIGlmIChpc0FycmF5KSB7XG4gICAgICBpZiAoXy5pc1BsYWluT2JqZWN0KHNjaGVtYS5pdGVtcykgJiYgIV8uaXNVbmRlZmluZWQoc2NoZW1hLml0ZW1zLnR5cGUpKSB7XG4gICAgICAgIHR5cGUgPSBzY2hlbWEuaXRlbXMudHlwZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHR5cGUgPSAnb2JqZWN0JztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIV8uaXNVbmRlZmluZWQoc2NoZW1hLmRlZmF1bHQpKSB7XG4gICAgICBvcHRpb25zICs9IG9wdGlvbkh0bWwoJ0RlZmF1bHQnLCBzY2hlbWEuZGVmYXVsdCk7XG4gICAgfVxuXG4gICAgc3dpdGNoICh0eXBlKSB7XG4gICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgIGlmIChzY2hlbWEubWluTGVuZ3RoKSB7XG4gICAgICAgIG9wdGlvbnMgKz0gb3B0aW9uSHRtbCgnTWluLiBMZW5ndGgnLCBzY2hlbWEubWluTGVuZ3RoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNjaGVtYS5tYXhMZW5ndGgpIHtcbiAgICAgICAgb3B0aW9ucyArPSBvcHRpb25IdG1sKCdNYXguIExlbmd0aCcsIHNjaGVtYS5tYXhMZW5ndGgpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2NoZW1hLnBhdHRlcm4pIHtcbiAgICAgICAgb3B0aW9ucyArPSBvcHRpb25IdG1sKCdSZWcuIEV4cC4nLCBzY2hlbWEucGF0dGVybik7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICBjYXNlICdpbnRlZ2VyJzpcbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgaWYgKHNjaGVtYS5taW5pbXVtKSB7XG4gICAgICAgIG9wdGlvbnMgKz0gb3B0aW9uSHRtbCgnTWluLiBWYWx1ZScsIHNjaGVtYS5taW5pbXVtKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNjaGVtYS5leGNsdXNpdmVNaW5pbXVtKSB7XG4gICAgICAgIG9wdGlvbnMgKz0gb3B0aW9uSHRtbCgnRXhjbHVzaXZlIE1pbi4nLCAndHJ1ZScpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2NoZW1hLm1heGltdW0pIHtcbiAgICAgICAgb3B0aW9ucyArPSBvcHRpb25IdG1sKCdNYXguIFZhbHVlJywgc2NoZW1hLm1heGltdW0pO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2NoZW1hLmV4Y2x1c2l2ZU1heGltdW0pIHtcbiAgICAgICAgb3B0aW9ucyArPSBvcHRpb25IdG1sKCdFeGNsdXNpdmUgTWF4LicsICd0cnVlJyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzY2hlbWEubXVsdGlwbGVPZikge1xuICAgICAgICBvcHRpb25zICs9IG9wdGlvbkh0bWwoJ011bHRpcGxlIE9mJywgc2NoZW1hLm11bHRpcGxlT2YpO1xuICAgICAgfVxuXG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBpZiAoaXNBcnJheSkge1xuICAgICAgaWYgKHNjaGVtYS5taW5JdGVtcykge1xuICAgICAgICBvcHRpb25zICs9IG9wdGlvbkh0bWwoJ01pbi4gSXRlbXMnLCBzY2hlbWEubWluSXRlbXMpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2NoZW1hLm1heEl0ZW1zKSB7XG4gICAgICAgIG9wdGlvbnMgKz0gb3B0aW9uSHRtbCgnTWF4LiBJdGVtcycsIHNjaGVtYS5tYXhJdGVtcyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzY2hlbWEudW5pcXVlSXRlbXMpIHtcbiAgICAgICAgb3B0aW9ucyArPSBvcHRpb25IdG1sKCdVbmlxdWUgSXRlbXMnLCAndHJ1ZScpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc2NoZW1hLmNvbGxlY3Rpb25Gb3JtYXQpIHtcbiAgICAgICAgb3B0aW9ucyArPSBvcHRpb25IdG1sKCdDb2xsLiBGb3JtYXQnLCBzY2hlbWEuY29sbGVjdGlvbkZvcm1hdCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKF8uaXNVbmRlZmluZWQoc2NoZW1hLml0ZW1zKSkge1xuICAgICAgaWYgKF8uaXNBcnJheShzY2hlbWEuZW51bSkpIHtcbiAgICAgICAgdmFyIGVudW1TdHJpbmc7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09ICdudW1iZXInIHx8IHR5cGUgPT09ICdpbnRlZ2VyJykge1xuICAgICAgICAgIGVudW1TdHJpbmcgPSBzY2hlbWEuZW51bS5qb2luKCcsICcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVudW1TdHJpbmcgPSAnXCInICsgc2NoZW1hLmVudW0uam9pbignXCIsIFwiJykgKyAnXCInO1xuICAgICAgICB9XG5cbiAgICAgICAgb3B0aW9ucyArPSBvcHRpb25IdG1sKCdFbnVtJywgZW51bVN0cmluZyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgaHRtbCA9ICc8c3BhbiBjbGFzcz1cInByb3BXcmFwXCI+JyArIGh0bWwgKyAnPHRhYmxlIGNsYXNzPVwib3B0aW9uc1dyYXBwZXJcIj48dHI+PHRoIGNvbHNwYW49XCIyXCI+JyArIHR5cGUgKyAnPC90aD48L3RyPicgKyBvcHRpb25zICsgJzwvdGFibGU+PC9zcGFuPic7XG4gICAgfVxuXG4gICAgcmV0dXJuIGh0bWw7XG4gIH1cblxuICBmdW5jdGlvbiBwcm9jZXNzTW9kZWwoc2NoZW1hLCBuYW1lKSB7XG4gICAgdmFyIHR5cGUgPSBzY2hlbWEudHlwZSB8fCAnb2JqZWN0JztcbiAgICB2YXIgaXNBcnJheSA9IHNjaGVtYS50eXBlID09PSAnYXJyYXknO1xuICAgIHZhciBodG1sID0gc3Ryb25nT3BlbiArIG5hbWUgKyAnICcgKyAoaXNBcnJheSA/ICdbJyA6ICd7JykgKyBzdHJvbmdDbG9zZTtcblxuICAgIGlmIChuYW1lKSB7XG4gICAgICBzZWVuTW9kZWxzLnB1c2gobmFtZSk7XG4gICAgfVxuXG4gICAgaWYgKGlzQXJyYXkpIHtcbiAgICAgIGlmIChfLmlzQXJyYXkoc2NoZW1hLml0ZW1zKSkge1xuICAgICAgICBodG1sICs9ICc8ZGl2PicgKyBfLm1hcChzY2hlbWEuaXRlbXMsIGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgICAgdmFyIHR5cGUgPSBpdGVtLnR5cGUgfHwgJ29iamVjdCc7XG5cbiAgICAgICAgICBpZiAoXy5pc1VuZGVmaW5lZChpdGVtLiRyZWYpKSB7XG4gICAgICAgICAgICBpZiAoXy5pbmRleE9mKFsnYXJyYXknLCAnb2JqZWN0J10sIHR5cGUpID4gLTEpIHtcbiAgICAgICAgICAgICAgaWYgKHR5cGUgPT09ICdvYmplY3QnICYmIF8uaXNVbmRlZmluZWQoaXRlbS5wcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnb2JqZWN0JztcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWRkUmVmZXJlbmNlKGl0ZW0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gcHJpbWl0aXZlVG9PcHRpb25zSFRNTChpdGVtLCB0eXBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGFkZFJlZmVyZW5jZShpdGVtLCBIZWxwZXJzLnNpbXBsZVJlZihpdGVtLiRyZWYpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pLmpvaW4oJyw8L2Rpdj48ZGl2PicpO1xuICAgICAgfSBlbHNlIGlmIChfLmlzUGxhaW5PYmplY3Qoc2NoZW1hLml0ZW1zKSkge1xuICAgICAgICBpZiAoXy5pc1VuZGVmaW5lZChzY2hlbWEuaXRlbXMuJHJlZikpIHtcbiAgICAgICAgICBpZiAoXy5pbmRleE9mKFsnYXJyYXknLCAnb2JqZWN0J10sIHNjaGVtYS5pdGVtcy50eXBlIHx8ICdvYmplY3QnKSA+IC0xKSB7XG4gICAgICAgICAgICBpZiAoKF8uaXNVbmRlZmluZWQoc2NoZW1hLml0ZW1zLnR5cGUpIHx8IHNjaGVtYS5pdGVtcy50eXBlID09PSAnb2JqZWN0JykgJiYgXy5pc1VuZGVmaW5lZChzY2hlbWEuaXRlbXMucHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgaHRtbCArPSAnPGRpdj5vYmplY3Q8L2Rpdj4nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaHRtbCArPSAnPGRpdj4nICsgYWRkUmVmZXJlbmNlKHNjaGVtYS5pdGVtcykgKyAnPC9kaXY+JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaHRtbCArPSAnPGRpdj4nICsgcHJpbWl0aXZlVG9PcHRpb25zSFRNTChzY2hlbWEuaXRlbXMsIHNjaGVtYS5pdGVtcy50eXBlKSArICc8L2Rpdj4nO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBodG1sICs9ICc8ZGl2PicgKyBhZGRSZWZlcmVuY2Uoc2NoZW1hLml0ZW1zLCBIZWxwZXJzLnNpbXBsZVJlZihzY2hlbWEuaXRlbXMuJHJlZikpICsgJzwvZGl2Pic7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIEhlbHBlcnMubG9nKCdBcnJheSB0eXBlXFwncyBcXCdpdGVtc1xcJyBwcm9wZXJ0eSBpcyBub3QgYW4gYXJyYXkgb3IgYW4gb2JqZWN0LCBjYW5ub3QgcHJvY2VzcycpO1xuICAgICAgICBodG1sICs9ICc8ZGl2Pm9iamVjdDwvZGl2Pic7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChzY2hlbWEuJHJlZikge1xuICAgICAgICBodG1sICs9ICc8ZGl2PicgKyBhZGRSZWZlcmVuY2Uoc2NoZW1hLCBuYW1lKSArICc8L2Rpdj4nO1xuICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgICBpZiAoXy5pc1BsYWluT2JqZWN0KHNjaGVtYS5wcm9wZXJ0aWVzKSkge1xuICAgICAgICAgIHZhciBjb250ZW50cyA9IF8ubWFwKHNjaGVtYS5wcm9wZXJ0aWVzLCBmdW5jdGlvbiAocHJvcGVydHksIG5hbWUpIHtcbiAgICAgICAgICAgIHZhciBwcm9wZXJ0eUlzUmVxdWlyZWQgPSAoXy5pbmRleE9mKHNjaGVtYS5yZXF1aXJlZCwgbmFtZSkgPj0gMCk7XG4gICAgICAgICAgICB2YXIgY1Byb3BlcnR5ID0gXy5jbG9uZURlZXAocHJvcGVydHkpO1xuXG4gICAgICAgICAgICB2YXIgcmVxdWlyZWRDbGFzcyA9IHByb3BlcnR5SXNSZXF1aXJlZCA/ICdyZXF1aXJlZCcgOiAnJztcbiAgICAgICAgICAgIHZhciBodG1sID0gJzxzcGFuIGNsYXNzPVwicHJvcE5hbWUgJyArIHJlcXVpcmVkQ2xhc3MgKyAnXCI+JyArIG5hbWUgKyAnPC9zcGFuPiAoJztcbiAgICAgICAgICAgIHZhciBtb2RlbDtcbiAgICAgICAgICAgIHZhciBwcm9wRGVzY3JpcHRpb247XG5cbiAgICAgICAgICAgIC8vIEFsbG93IG1hY3JvIHRvIHNldCB0aGUgZGVmYXVsdCB2YWx1ZVxuICAgICAgICAgICAgY1Byb3BlcnR5LmRlZmF1bHQgPSBtb2RlbFByb3BlcnR5TWFjcm8oY1Byb3BlcnR5KTtcblxuICAgICAgICAgICAgLy8gUmVzb2x2ZSB0aGUgc2NoZW1hIChIYW5kbGUgbmVzdGVkIHNjaGVtYXMpXG4gICAgICAgICAgICBjUHJvcGVydHkgPSBIZWxwZXJzLnJlc29sdmVTY2hlbWEoY1Byb3BlcnR5KTtcblxuICAgICAgICAgICAgcHJvcERlc2NyaXB0aW9uID0gcHJvcGVydHkuZGVzY3JpcHRpb24gfHwgY1Byb3BlcnR5LmRlc2NyaXB0aW9uO1xuXG4gICAgICAgICAgICAvLyBXZSBuZWVkIHRvIGhhbmRsZSBwcm9wZXJ0eSByZWZlcmVuY2VzIHRvIHByaW1pdGl2ZXMgKElzc3VlIDMzOSlcbiAgICAgICAgICAgIGlmICghXy5pc1VuZGVmaW5lZChjUHJvcGVydHkuJHJlZikpIHtcbiAgICAgICAgICAgICAgbW9kZWwgPSBtb2RlbHNbSGVscGVycy5zaW1wbGVSZWYoY1Byb3BlcnR5LiRyZWYpXTtcblxuICAgICAgICAgICAgICBpZiAoIV8uaXNVbmRlZmluZWQobW9kZWwpICYmIF8uaW5kZXhPZihbdW5kZWZpbmVkLCAnYXJyYXknLCAnb2JqZWN0J10sIG1vZGVsLmRlZmluaXRpb24udHlwZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgLy8gVXNlIHJlZmVyZW5jZWQgc2NoZW1hXG4gICAgICAgICAgICAgICAgY1Byb3BlcnR5ID0gSGVscGVycy5yZXNvbHZlU2NoZW1hKG1vZGVsLmRlZmluaXRpb24pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGh0bWwgKz0gcHJpbWl0aXZlVG9IVE1MKGNQcm9wZXJ0eSk7XG5cbiAgICAgICAgICAgIGlmKCFwcm9wZXJ0eUlzUmVxdWlyZWQpIHtcbiAgICAgICAgICAgICAgaHRtbCArPSAnLCA8c3BhbiBjbGFzcz1cInByb3BPcHRLZXlcIj5vcHRpb25hbDwvc3Bhbj4nO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZihwcm9wZXJ0eS5yZWFkT25seSkge1xuICAgICAgICAgICAgICAgIGh0bWwgKz0gJywgPHNwYW4gY2xhc3M9XCJwcm9wUmVhZE9ubHlcIj5yZWFkIG9ubHk8L3NwYW4+JztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaHRtbCArPSAnKSc7XG5cbiAgICAgICAgICAgIGlmICghXy5pc1VuZGVmaW5lZChwcm9wRGVzY3JpcHRpb24pKSB7XG4gICAgICAgICAgICAgIGh0bWwgKz0gJzogJyArICc8c3BhbiBjbGFzcz1cInByb3BEZXNjXCI+JyArIHByb3BEZXNjcmlwdGlvbiArICc8L3NwYW4+JztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNQcm9wZXJ0eS5lbnVtKSB7XG4gICAgICAgICAgICAgIGh0bWwgKz0gJyA9IDxzcGFuIGNsYXNzPVwicHJvcFZhbHNcIj5bXFwnJyArIGNQcm9wZXJ0eS5lbnVtLmpvaW4oJ1xcJywgXFwnJykgKyAnXFwnXTwvc3Bhbj4nO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gJzxkaXYnICsgKHByb3BlcnR5LnJlYWRPbmx5ID8gJyBjbGFzcz1cInJlYWRPbmx5XCInIDogJycpICsgJz4nICsgcHJpbWl0aXZlVG9PcHRpb25zSFRNTChjUHJvcGVydHksIGh0bWwpO1xuICAgICAgICAgIH0pLmpvaW4oJyw8L2Rpdj4nKTtcblxuICAgICAgICAgIGlmIChjb250ZW50cykge1xuICAgICAgICAgICAgaHRtbCArPSBjb250ZW50cyArICc8L2Rpdj4nO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaHRtbCArPSAnPGRpdj4nICsgcHJpbWl0aXZlVG9PcHRpb25zSFRNTChzY2hlbWEsIHR5cGUpICsgJzwvZGl2Pic7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGh0bWwgKyBzdHJvbmdPcGVuICsgKGlzQXJyYXkgPyAnXScgOiAnfScpICsgc3Ryb25nQ2xvc2U7XG4gIH1cbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgU3dhZ2dlckh0dHAgPSByZXF1aXJlKCcuL2h0dHAnKTtcbnZhciBfID0ge1xuICBpc09iamVjdDogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9sYW5nL2lzT2JqZWN0Jylcbn07XG5cbnZhciBTd2FnZ2VyU3BlY0NvbnZlcnRlciA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLmVycm9ycyA9IFtdO1xuICB0aGlzLndhcm5pbmdzID0gW107XG4gIHRoaXMubW9kZWxNYXAgPSB7fTtcbn07XG5cblN3YWdnZXJTcGVjQ29udmVydGVyLnByb3RvdHlwZS5zZXREb2N1bWVudGF0aW9uTG9jYXRpb24gPSBmdW5jdGlvbiAobG9jYXRpb24pIHtcbiAgdGhpcy5kb2NMb2NhdGlvbiA9IGxvY2F0aW9uO1xufTtcblxuLyoqXG4gKiBjb252ZXJ0cyBhIHJlc291cmNlIGxpc3RpbmcgT1IgYXBpIGRlY2xhcmF0aW9uXG4gKiovXG5Td2FnZ2VyU3BlY0NvbnZlcnRlci5wcm90b3R5cGUuY29udmVydCA9IGZ1bmN0aW9uIChvYmosIGNsaWVudEF1dGhvcml6YXRpb25zLCBvcHRzLCBjYWxsYmFjaykge1xuICAvLyBub3QgYSB2YWxpZCBzcGVjXG4gIGlmKCFvYmogfHwgIUFycmF5LmlzQXJyYXkob2JqLmFwaXMpKSB7XG4gICAgcmV0dXJuIHRoaXMuZmluaXNoKGNhbGxiYWNrLCBudWxsKTtcbiAgfVxuICB0aGlzLmNsaWVudEF1dGhvcml6YXRpb25zID0gY2xpZW50QXV0aG9yaXphdGlvbnM7XG5cbiAgLy8gY3JlYXRlIGEgbmV3IHN3YWdnZXIgb2JqZWN0IHRvIHJldHVyblxuICB2YXIgc3dhZ2dlciA9IHsgc3dhZ2dlcjogJzIuMCcgfTtcblxuICBzd2FnZ2VyLm9yaWdpbmFsVmVyc2lvbiA9IG9iai5zd2FnZ2VyVmVyc2lvbjtcblxuICAvLyBhZGQgdGhlIGluZm9cbiAgdGhpcy5hcGlJbmZvKG9iaiwgc3dhZ2dlcik7XG5cbiAgLy8gYWRkIHNlY3VyaXR5IGRlZmluaXRpb25zXG4gIHRoaXMuc2VjdXJpdHlEZWZpbml0aW9ucyhvYmosIHN3YWdnZXIpO1xuXG4gIC8vIHRha2UgYmFzZVBhdGggaW50byBhY2NvdW50XG4gIGlmIChvYmouYmFzZVBhdGgpIHtcbiAgICB0aGlzLnNldERvY3VtZW50YXRpb25Mb2NhdGlvbihvYmouYmFzZVBhdGgpO1xuICB9XG5cbiAgLy8gc2VlIGlmIHRoaXMgaXMgYSBzaW5nbGUtZmlsZSBzd2FnZ2VyIGRlZmluaXRpb25cbiAgdmFyIGlzU2luZ2xlRmlsZVN3YWdnZXIgPSBmYWxzZTtcbiAgdmFyIGk7XG4gIGZvcihpID0gMDsgaSA8IG9iai5hcGlzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGFwaSA9IG9iai5hcGlzW2ldO1xuICAgIGlmKEFycmF5LmlzQXJyYXkoYXBpLm9wZXJhdGlvbnMpKSB7XG4gICAgICBpc1NpbmdsZUZpbGVTd2FnZ2VyID0gdHJ1ZTtcbiAgICB9XG4gIH1cbiAgaWYoaXNTaW5nbGVGaWxlU3dhZ2dlcikge1xuICAgIHRoaXMuZGVjbGFyYXRpb24ob2JqLCBzd2FnZ2VyKTtcbiAgICB0aGlzLmZpbmlzaChjYWxsYmFjaywgc3dhZ2dlcik7XG4gIH1cbiAgZWxzZSB7XG4gICAgdGhpcy5yZXNvdXJjZUxpc3Rpbmcob2JqLCBzd2FnZ2VyLCBvcHRzLCBjYWxsYmFjayk7XG4gIH1cbn07XG5cblN3YWdnZXJTcGVjQ29udmVydGVyLnByb3RvdHlwZS5kZWNsYXJhdGlvbiA9IGZ1bmN0aW9uKG9iaiwgc3dhZ2dlcikge1xuICB2YXIgbmFtZSwgaSwgcCwgcG9zO1xuICBpZighb2JqLmFwaXMpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAob2JqLmJhc2VQYXRoLmluZGV4T2YoJ2h0dHA6Ly8nKSA9PT0gMCkge1xuICAgIHAgPSBvYmouYmFzZVBhdGguc3Vic3RyaW5nKCdodHRwOi8vJy5sZW5ndGgpO1xuICAgIHBvcyA9IHAuaW5kZXhPZignLycpO1xuICAgIGlmIChwb3MgPiAwKSB7XG4gICAgICBzd2FnZ2VyLmhvc3QgPSBwLnN1YnN0cmluZygwLCBwb3MpO1xuICAgICAgc3dhZ2dlci5iYXNlUGF0aCA9IHAuc3Vic3RyaW5nKHBvcyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgc3dhZ2dlci5ob3N0ID0gcDtcbiAgICAgIHN3YWdnZXIuYmFzZVBhdGggPSAnLyc7XG4gICAgfVxuICB9IGVsc2UgaWYgKG9iai5iYXNlUGF0aC5pbmRleE9mKCdodHRwczovLycpID09PSAwKSB7XG4gICAgcCA9IG9iai5iYXNlUGF0aC5zdWJzdHJpbmcoJ2h0dHBzOi8vJy5sZW5ndGgpO1xuICAgIHBvcyA9IHAuaW5kZXhPZignLycpO1xuICAgIGlmIChwb3MgPiAwKSB7XG4gICAgICBzd2FnZ2VyLmhvc3QgPSBwLnN1YnN0cmluZygwLCBwb3MpO1xuICAgICAgc3dhZ2dlci5iYXNlUGF0aCA9IHAuc3Vic3RyaW5nKHBvcyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgc3dhZ2dlci5ob3N0ID0gcDtcbiAgICAgIHN3YWdnZXIuYmFzZVBhdGggPSAnLyc7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHN3YWdnZXIuYmFzZVBhdGggPSBvYmouYmFzZVBhdGg7XG4gIH1cblxuICB2YXIgcmVzb3VyY2VMZXZlbEF1dGg7XG4gIGlmKG9iai5hdXRob3JpemF0aW9ucykge1xuICAgIHJlc291cmNlTGV2ZWxBdXRoID0gb2JqLmF1dGhvcml6YXRpb25zO1xuICB9XG4gIGlmKG9iai5jb25zdW1lcykge1xuICAgIHN3YWdnZXIuY29uc3VtZXMgPSBvYmouY29uc3VtZXM7XG4gIH1cbiAgaWYob2JqLnByb2R1Y2VzKSB7XG4gICAgc3dhZ2dlci5wcm9kdWNlcyA9IG9iai5wcm9kdWNlcztcbiAgfVxuXG4gIC8vIGJ1aWxkIGEgbWFwcGluZyBvZiBpZCB0byBuYW1lIGZvciAxLjAgbW9kZWwgcmVzb2x1dGlvbnNcbiAgaWYoXy5pc09iamVjdChvYmopKSB7XG4gICAgZm9yKG5hbWUgaW4gb2JqLm1vZGVscykge1xuICAgICAgdmFyIGV4aXN0aW5nTW9kZWwgPSBvYmoubW9kZWxzW25hbWVdO1xuICAgICAgdmFyIGtleSA9IChleGlzdGluZ01vZGVsLmlkIHx8IG5hbWUpO1xuICAgICAgdGhpcy5tb2RlbE1hcFtrZXldID0gbmFtZTtcbiAgICB9XG4gIH1cblxuICBmb3IoaSA9IDA7IGkgPCBvYmouYXBpcy5sZW5ndGg7IGkrKykge1xuICAgIHZhciBhcGkgPSBvYmouYXBpc1tpXTtcbiAgICB2YXIgcGF0aCA9IGFwaS5wYXRoO1xuICAgIHZhciBvcGVyYXRpb25zID0gYXBpLm9wZXJhdGlvbnM7XG4gICAgdGhpcy5vcGVyYXRpb25zKHBhdGgsIG9iai5yZXNvdXJjZVBhdGgsIG9wZXJhdGlvbnMsIHJlc291cmNlTGV2ZWxBdXRoLCBzd2FnZ2VyKTtcbiAgfVxuXG4gIHZhciBtb2RlbHMgPSBvYmoubW9kZWxzIHx8IHt9O1xuICB0aGlzLm1vZGVscyhtb2RlbHMsIHN3YWdnZXIpO1xufTtcblxuU3dhZ2dlclNwZWNDb252ZXJ0ZXIucHJvdG90eXBlLm1vZGVscyA9IGZ1bmN0aW9uKG9iaiwgc3dhZ2dlcikge1xuICBpZighXy5pc09iamVjdChvYmopKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBuYW1lO1xuXG4gIHN3YWdnZXIuZGVmaW5pdGlvbnMgPSBzd2FnZ2VyLmRlZmluaXRpb25zIHx8IHt9O1xuICBmb3IobmFtZSBpbiBvYmopIHtcbiAgICB2YXIgZXhpc3RpbmdNb2RlbCA9IG9ialtuYW1lXTtcbiAgICB2YXIgX3JlcXVpcmVkID0gW107XG4gICAgdmFyIHNjaGVtYSA9IHsgcHJvcGVydGllczoge319O1xuICAgIHZhciBwcm9wZXJ0eU5hbWU7XG4gICAgZm9yKHByb3BlcnR5TmFtZSBpbiBleGlzdGluZ01vZGVsLnByb3BlcnRpZXMpIHtcbiAgICAgIHZhciBleGlzdGluZ1Byb3BlcnR5ID0gZXhpc3RpbmdNb2RlbC5wcm9wZXJ0aWVzW3Byb3BlcnR5TmFtZV07XG4gICAgICB2YXIgcHJvcGVydHkgPSB7fTtcbiAgICAgIHRoaXMuZGF0YVR5cGUoZXhpc3RpbmdQcm9wZXJ0eSwgcHJvcGVydHkpO1xuICAgICAgaWYoZXhpc3RpbmdQcm9wZXJ0eS5kZXNjcmlwdGlvbikge1xuICAgICAgICBwcm9wZXJ0eS5kZXNjcmlwdGlvbiA9IGV4aXN0aW5nUHJvcGVydHkuZGVzY3JpcHRpb247XG4gICAgICB9XG4gICAgICBpZihleGlzdGluZ1Byb3BlcnR5WydlbnVtJ10pIHtcbiAgICAgICAgcHJvcGVydHlbJ2VudW0nXSA9IGV4aXN0aW5nUHJvcGVydHlbJ2VudW0nXTtcbiAgICAgIH1cbiAgICAgIGlmKHR5cGVvZiBleGlzdGluZ1Byb3BlcnR5LnJlcXVpcmVkID09PSAnYm9vbGVhbicgJiYgZXhpc3RpbmdQcm9wZXJ0eS5yZXF1aXJlZCA9PT0gdHJ1ZSkge1xuICAgICAgICBfcmVxdWlyZWQucHVzaChwcm9wZXJ0eU5hbWUpO1xuICAgICAgfVxuICAgICAgaWYodHlwZW9mIGV4aXN0aW5nUHJvcGVydHkucmVxdWlyZWQgPT09ICdzdHJpbmcnICYmIGV4aXN0aW5nUHJvcGVydHkucmVxdWlyZWQgPT09ICd0cnVlJykge1xuICAgICAgICBfcmVxdWlyZWQucHVzaChwcm9wZXJ0eU5hbWUpO1xuICAgICAgfVxuICAgICAgc2NoZW1hLnByb3BlcnRpZXNbcHJvcGVydHlOYW1lXSA9IHByb3BlcnR5O1xuICAgIH1cbiAgICBpZihfcmVxdWlyZWQubGVuZ3RoID4gMCkge1xuICAgICAgc2NoZW1hLnJlcXVpcmVkID0gX3JlcXVpcmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICBzY2hlbWEucmVxdWlyZWQgPSBleGlzdGluZ01vZGVsLnJlcXVpcmVkO1xuICAgIH1cbiAgICBzd2FnZ2VyLmRlZmluaXRpb25zW25hbWVdID0gc2NoZW1hO1xuICB9XG59O1xuXG5Td2FnZ2VyU3BlY0NvbnZlcnRlci5wcm90b3R5cGUuZXh0cmFjdFRhZyA9IGZ1bmN0aW9uKHJlc291cmNlUGF0aCkge1xuICB2YXIgcGF0aFN0cmluZyA9IHJlc291cmNlUGF0aCB8fCAnZGVmYXVsdCc7XG4gIGlmKHBhdGhTdHJpbmcuaW5kZXhPZignaHR0cDonKSA9PT0gMCB8fCBwYXRoU3RyaW5nLmluZGV4T2YoJ2h0dHBzOicpID09PSAwKSB7XG4gICAgcGF0aFN0cmluZyA9IHBhdGhTdHJpbmcuc3BsaXQoWycvJ10pO1xuICAgIHBhdGhTdHJpbmcgPSBwYXRoU3RyaW5nW3BhdGhTdHJpbmcubGVuZ3RoIC0xXS5zdWJzdHJpbmcoKTtcbiAgfVxuICBpZihwYXRoU3RyaW5nLmVuZHNXaXRoKCcuanNvbicpKSB7XG4gICAgcGF0aFN0cmluZyA9IHBhdGhTdHJpbmcuc3Vic3RyaW5nKDAsIHBhdGhTdHJpbmcubGVuZ3RoIC0gJy5qc29uJy5sZW5ndGgpO1xuICB9XG4gIHJldHVybiBwYXRoU3RyaW5nLnJlcGxhY2UoJy8nLCcnKTtcbn07XG5cblN3YWdnZXJTcGVjQ29udmVydGVyLnByb3RvdHlwZS5vcGVyYXRpb25zID0gZnVuY3Rpb24ocGF0aCwgcmVzb3VyY2VQYXRoLCBvYmosIHJlc291cmNlTGV2ZWxBdXRoLCBzd2FnZ2VyKSB7XG4gIGlmKCFBcnJheS5pc0FycmF5KG9iaikpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIGk7XG5cbiAgaWYoIXN3YWdnZXIucGF0aHMpIHtcbiAgICBzd2FnZ2VyLnBhdGhzID0ge307XG4gIH1cblxuICB2YXIgcGF0aE9iaiA9IHN3YWdnZXIucGF0aHNbcGF0aF0gfHwge307XG4gIHZhciB0YWcgPSB0aGlzLmV4dHJhY3RUYWcocmVzb3VyY2VQYXRoKTtcbiAgc3dhZ2dlci50YWdzID0gc3dhZ2dlci50YWdzIHx8IFtdO1xuICB2YXIgbWF0Y2hlZCA9IGZhbHNlO1xuICBmb3IoaSA9IDA7IGkgPCBzd2FnZ2VyLnRhZ3MubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgdGFnT2JqZWN0ID0gc3dhZ2dlci50YWdzW2ldO1xuICAgIGlmKHRhZ09iamVjdC5uYW1lID09PSB0YWcpIHtcbiAgICAgIG1hdGNoZWQgPSB0cnVlO1xuICAgIH1cbiAgfVxuICBpZighbWF0Y2hlZCkge1xuICAgIHN3YWdnZXIudGFncy5wdXNoKHtuYW1lOiB0YWd9KTtcbiAgfVxuXG4gIGZvcihpID0gMDsgaSA8IG9iai5sZW5ndGg7IGkrKykge1xuICAgIHZhciBleGlzdGluZ09wZXJhdGlvbiA9IG9ialtpXTtcbiAgICB2YXIgbWV0aG9kID0gKGV4aXN0aW5nT3BlcmF0aW9uLm1ldGhvZCB8fCBleGlzdGluZ09wZXJhdGlvbi5odHRwTWV0aG9kKS50b0xvd2VyQ2FzZSgpO1xuICAgIHZhciBvcGVyYXRpb24gPSB7dGFnczogW3RhZ119O1xuICAgIHZhciBleGlzdGluZ0F1dGhvcml6YXRpb25zID0gZXhpc3RpbmdPcGVyYXRpb24uYXV0aG9yaXphdGlvbnM7XG5cbiAgICBpZihleGlzdGluZ0F1dGhvcml6YXRpb25zICYmIE9iamVjdC5rZXlzKGV4aXN0aW5nQXV0aG9yaXphdGlvbnMpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgZXhpc3RpbmdBdXRob3JpemF0aW9ucyA9IHJlc291cmNlTGV2ZWxBdXRoO1xuICAgIH1cblxuICAgIGlmKHR5cGVvZiBleGlzdGluZ0F1dGhvcml6YXRpb25zICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdmFyIHNjb3Blc09iamVjdDtcbiAgICAgIGZvcih2YXIga2V5IGluIGV4aXN0aW5nQXV0aG9yaXphdGlvbnMpIHtcbiAgICAgICAgb3BlcmF0aW9uLnNlY3VyaXR5ID0gb3BlcmF0aW9uLnNlY3VyaXR5IHx8IFtdO1xuICAgICAgICB2YXIgc2NvcGVzID0gZXhpc3RpbmdBdXRob3JpemF0aW9uc1trZXldO1xuICAgICAgICBpZihzY29wZXMpIHtcbiAgICAgICAgICB2YXIgc2VjdXJpdHlTY29wZXMgPSBbXTtcbiAgICAgICAgICBmb3IodmFyIGogaW4gc2NvcGVzKSB7XG4gICAgICAgICAgICBzZWN1cml0eVNjb3Blcy5wdXNoKHNjb3Blc1tqXS5zY29wZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIHNjb3Blc09iamVjdCA9IHt9O1xuICAgICAgICAgIHNjb3Blc09iamVjdFtrZXldID0gc2VjdXJpdHlTY29wZXM7XG4gICAgICAgICAgb3BlcmF0aW9uLnNlY3VyaXR5LnB1c2goc2NvcGVzT2JqZWN0KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBzY29wZXNPYmplY3QgPSB7fTtcbiAgICAgICAgICBzY29wZXNPYmplY3Rba2V5XSA9IFtdO1xuICAgICAgICAgIG9wZXJhdGlvbi5zZWN1cml0eS5wdXNoKHNjb3Blc09iamVjdCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZihleGlzdGluZ09wZXJhdGlvbi5jb25zdW1lcykge1xuICAgICAgb3BlcmF0aW9uLmNvbnN1bWVzID0gZXhpc3RpbmdPcGVyYXRpb24uY29uc3VtZXM7XG4gICAgfVxuICAgIGVsc2UgaWYoc3dhZ2dlci5jb25zdW1lcykge1xuICAgICAgb3BlcmF0aW9uLmNvbnN1bWVzID0gc3dhZ2dlci5jb25zdW1lcztcbiAgICB9XG4gICAgaWYoZXhpc3RpbmdPcGVyYXRpb24ucHJvZHVjZXMpIHtcbiAgICAgIG9wZXJhdGlvbi5wcm9kdWNlcyA9IGV4aXN0aW5nT3BlcmF0aW9uLnByb2R1Y2VzO1xuICAgIH1cbiAgICBlbHNlIGlmKHN3YWdnZXIucHJvZHVjZXMpIHtcbiAgICAgIG9wZXJhdGlvbi5wcm9kdWNlcyA9IHN3YWdnZXIucHJvZHVjZXM7XG4gICAgfVxuICAgIGlmKGV4aXN0aW5nT3BlcmF0aW9uLnN1bW1hcnkpIHtcbiAgICAgIG9wZXJhdGlvbi5zdW1tYXJ5ID0gZXhpc3RpbmdPcGVyYXRpb24uc3VtbWFyeTtcbiAgICB9XG4gICAgaWYoZXhpc3RpbmdPcGVyYXRpb24ubm90ZXMpIHtcbiAgICAgIG9wZXJhdGlvbi5kZXNjcmlwdGlvbiA9IGV4aXN0aW5nT3BlcmF0aW9uLm5vdGVzO1xuICAgIH1cbiAgICBpZihleGlzdGluZ09wZXJhdGlvbi5uaWNrbmFtZSkge1xuICAgICAgb3BlcmF0aW9uLm9wZXJhdGlvbklkID0gZXhpc3RpbmdPcGVyYXRpb24ubmlja25hbWU7XG4gICAgfVxuICAgIGlmKGV4aXN0aW5nT3BlcmF0aW9uLmRlcHJlY2F0ZWQpIHtcbiAgICAgIG9wZXJhdGlvbi5kZXByZWNhdGVkID0gZXhpc3RpbmdPcGVyYXRpb24uZGVwcmVjYXRlZDtcbiAgICB9XG5cbiAgICB0aGlzLmF1dGhvcml6YXRpb25zKGV4aXN0aW5nQXV0aG9yaXphdGlvbnMsIHN3YWdnZXIpO1xuICAgIHRoaXMucGFyYW1ldGVycyhvcGVyYXRpb24sIGV4aXN0aW5nT3BlcmF0aW9uLnBhcmFtZXRlcnMsIHN3YWdnZXIpO1xuICAgIHRoaXMucmVzcG9uc2VNZXNzYWdlcyhvcGVyYXRpb24sIGV4aXN0aW5nT3BlcmF0aW9uLCBzd2FnZ2VyKTtcblxuICAgIHBhdGhPYmpbbWV0aG9kXSA9IG9wZXJhdGlvbjtcbiAgfVxuXG4gIHN3YWdnZXIucGF0aHNbcGF0aF0gPSBwYXRoT2JqO1xufTtcblxuU3dhZ2dlclNwZWNDb252ZXJ0ZXIucHJvdG90eXBlLnJlc3BvbnNlTWVzc2FnZXMgPSBmdW5jdGlvbihvcGVyYXRpb24sIGV4aXN0aW5nT3BlcmF0aW9uKSB7XG4gIGlmKCFfLmlzT2JqZWN0KGV4aXN0aW5nT3BlcmF0aW9uKSkge1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBidWlsZCBkZWZhdWx0IHJlc3BvbnNlIGZyb20gdGhlIG9wZXJhdGlvbiAoMS54KVxuICB2YXIgZGVmYXVsdFJlc3BvbnNlID0ge307XG4gIHRoaXMuZGF0YVR5cGUoZXhpc3RpbmdPcGVyYXRpb24sIGRlZmF1bHRSZXNwb25zZSk7XG4gIC8vIFRPRE86IGxvb2sgaW50byB0aGUgcmVhbCBwcm9ibGVtIG9mIHJlbmRlcmluZyByZXNwb25zZXMgaW4gc3dhZ2dlci11aVxuICAvLyAuLi4uc2hvdWxkIHJlcG9uc2VUeXBlIGhhdmUgYW4gaW1wbGljaXQgc2NoZW1hP1xuICBpZighZGVmYXVsdFJlc3BvbnNlLnNjaGVtYSAmJiBkZWZhdWx0UmVzcG9uc2UudHlwZSkge1xuICAgIGRlZmF1bHRSZXNwb25zZSA9IHtzY2hlbWE6IGRlZmF1bHRSZXNwb25zZX07XG4gIH1cblxuICBvcGVyYXRpb24ucmVzcG9uc2VzID0gb3BlcmF0aW9uLnJlc3BvbnNlcyB8fCB7fTtcblxuICAvLyBncmFiIGZyb20gcmVzcG9uc2VNZXNzYWdlcyAoMS4yKVxuICB2YXIgaGFzMjAwID0gZmFsc2U7XG4gIGlmKEFycmF5LmlzQXJyYXkoZXhpc3RpbmdPcGVyYXRpb24ucmVzcG9uc2VNZXNzYWdlcykpIHtcbiAgICB2YXIgaTtcbiAgICB2YXIgZXhpc3RpbmdSZXNwb25zZXMgPSBleGlzdGluZ09wZXJhdGlvbi5yZXNwb25zZU1lc3NhZ2VzO1xuICAgIGZvcihpID0gMDsgaSA8IGV4aXN0aW5nUmVzcG9uc2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgZXhpc3RpbmdSZXNwb25zZSA9IGV4aXN0aW5nUmVzcG9uc2VzW2ldO1xuICAgICAgdmFyIHJlc3BvbnNlID0geyBkZXNjcmlwdGlvbjogZXhpc3RpbmdSZXNwb25zZS5tZXNzYWdlIH07XG4gICAgICBpZihleGlzdGluZ1Jlc3BvbnNlLmNvZGUgPT09IDIwMCkge1xuICAgICAgICBoYXMyMDAgPSB0cnVlO1xuICAgICAgfVxuICAgICAgLy8gQ29udmVydCByZXNwb25zZU1vZGVsIC0+IHNjaGVtYXskcmVmOiByZXNwb25zZU1vZGVsfVxuICAgICAgaWYoZXhpc3RpbmdSZXNwb25zZS5yZXNwb25zZU1vZGVsKSB7XG4gICAgICAgIHJlc3BvbnNlLnNjaGVtYSA9IHsnJHJlZic6ICcjL2RlZmluaXRpb25zLycgKyBleGlzdGluZ1Jlc3BvbnNlLnJlc3BvbnNlTW9kZWx9O1xuICAgICAgfVxuICAgICAgb3BlcmF0aW9uLnJlc3BvbnNlc1snJyArIGV4aXN0aW5nUmVzcG9uc2UuY29kZV0gPSByZXNwb25zZTtcbiAgICB9XG4gIH1cblxuICBpZihoYXMyMDApIHtcbiAgICBvcGVyYXRpb24ucmVzcG9uc2VzWydkZWZhdWx0J10gPSBkZWZhdWx0UmVzcG9uc2U7XG4gIH1cbiAgZWxzZSB7XG4gICAgb3BlcmF0aW9uLnJlc3BvbnNlc1snMjAwJ10gPSBkZWZhdWx0UmVzcG9uc2U7XG4gIH1cbn07XG5cblN3YWdnZXJTcGVjQ29udmVydGVyLnByb3RvdHlwZS5hdXRob3JpemF0aW9ucyA9IGZ1bmN0aW9uKG9iaikge1xuICAvLyBUT0RPXG4gIGlmKCFfLmlzT2JqZWN0KG9iaikpIHtcbiAgICByZXR1cm47XG4gIH1cbn07XG5cblN3YWdnZXJTcGVjQ29udmVydGVyLnByb3RvdHlwZS5wYXJhbWV0ZXJzID0gZnVuY3Rpb24ob3BlcmF0aW9uLCBvYmopIHtcbiAgaWYoIUFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgaTtcbiAgZm9yKGkgPSAwOyBpIDwgb2JqLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGV4aXN0aW5nUGFyYW1ldGVyID0gb2JqW2ldO1xuICAgIHZhciBwYXJhbWV0ZXIgPSB7fTtcbiAgICBwYXJhbWV0ZXIubmFtZSA9IGV4aXN0aW5nUGFyYW1ldGVyLm5hbWU7XG4gICAgcGFyYW1ldGVyLmRlc2NyaXB0aW9uID0gZXhpc3RpbmdQYXJhbWV0ZXIuZGVzY3JpcHRpb247XG4gICAgcGFyYW1ldGVyLnJlcXVpcmVkID0gZXhpc3RpbmdQYXJhbWV0ZXIucmVxdWlyZWQ7XG4gICAgcGFyYW1ldGVyLmluID0gZXhpc3RpbmdQYXJhbWV0ZXIucGFyYW1UeXBlO1xuXG4gICAgLy8gcGVyICMxNjhcbiAgICBpZihwYXJhbWV0ZXIuaW4gPT09ICdib2R5Jykge1xuICAgICAgcGFyYW1ldGVyLm5hbWUgPSAnYm9keSc7XG4gICAgfVxuICAgIGlmKHBhcmFtZXRlci5pbiA9PT0gJ2Zvcm0nKSB7XG4gICAgICBwYXJhbWV0ZXIuaW4gPSAnZm9ybURhdGEnO1xuICAgIH1cblxuICAgIGlmKGV4aXN0aW5nUGFyYW1ldGVyLmVudW0pIHtcbiAgICAgIHBhcmFtZXRlci5lbnVtID0gZXhpc3RpbmdQYXJhbWV0ZXIuZW51bTtcbiAgICB9XG5cbiAgICBpZihleGlzdGluZ1BhcmFtZXRlci5hbGxvd011bHRpcGxlID09PSB0cnVlIHx8IGV4aXN0aW5nUGFyYW1ldGVyLmFsbG93TXVsdGlwbGUgPT09ICd0cnVlJykge1xuICAgICAgdmFyIGlubmVyVHlwZSA9IHt9O1xuICAgICAgdGhpcy5kYXRhVHlwZShleGlzdGluZ1BhcmFtZXRlciwgaW5uZXJUeXBlKTtcbiAgICAgIHBhcmFtZXRlci50eXBlID0gJ2FycmF5JztcbiAgICAgIHBhcmFtZXRlci5pdGVtcyA9IGlubmVyVHlwZTtcblxuICAgICAgaWYoZXhpc3RpbmdQYXJhbWV0ZXIuYWxsb3dhYmxlVmFsdWVzKSB7XG4gICAgICAgIHZhciBhdiA9IGV4aXN0aW5nUGFyYW1ldGVyLmFsbG93YWJsZVZhbHVlcztcbiAgICAgICAgaWYoYXYudmFsdWVUeXBlID09PSAnTElTVCcpIHtcbiAgICAgICAgICBwYXJhbWV0ZXJbJ2VudW0nXSA9IGF2LnZhbHVlcztcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuZGF0YVR5cGUoZXhpc3RpbmdQYXJhbWV0ZXIsIHBhcmFtZXRlcik7XG4gICAgfVxuICAgIGlmKHR5cGVvZiBleGlzdGluZ1BhcmFtZXRlci5kZWZhdWx0VmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBwYXJhbWV0ZXIuZGVmYXVsdCA9IGV4aXN0aW5nUGFyYW1ldGVyLmRlZmF1bHRWYWx1ZTtcbiAgICB9XG5cbiAgICBvcGVyYXRpb24ucGFyYW1ldGVycyA9IG9wZXJhdGlvbi5wYXJhbWV0ZXJzIHx8IFtdO1xuICAgIG9wZXJhdGlvbi5wYXJhbWV0ZXJzLnB1c2gocGFyYW1ldGVyKTtcbiAgfVxufTtcblxuU3dhZ2dlclNwZWNDb252ZXJ0ZXIucHJvdG90eXBlLmRhdGFUeXBlID0gZnVuY3Rpb24oc291cmNlLCB0YXJnZXQpIHtcbiAgaWYoIV8uaXNPYmplY3Qoc291cmNlKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmKHNvdXJjZS5taW5pbXVtKSB7XG4gICAgdGFyZ2V0Lm1pbmltdW0gPSBzb3VyY2UubWluaW11bTtcbiAgfVxuICBpZihzb3VyY2UubWF4aW11bSkge1xuICAgIHRhcmdldC5tYXhpbXVtID0gc291cmNlLm1heGltdW07XG4gIH1cbiAgaWYgKHNvdXJjZS5mb3JtYXQpIHtcbiAgICB0YXJnZXQuZm9ybWF0ID0gc291cmNlLmZvcm1hdDtcbiAgfVxuXG4gIC8vIGRlZmF1bHQgY2FuIGJlICdmYWxzZSdcbiAgaWYodHlwZW9mIHNvdXJjZS5kZWZhdWx0VmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgdGFyZ2V0LmRlZmF1bHQgPSBzb3VyY2UuZGVmYXVsdFZhbHVlO1xuICB9XG5cbiAgdmFyIGpzb25TY2hlbWFUeXBlID0gdGhpcy50b0pzb25TY2hlbWEoc291cmNlKTtcbiAgaWYoanNvblNjaGVtYVR5cGUpIHtcbiAgICB0YXJnZXQgPSB0YXJnZXQgfHwge307XG4gICAgaWYoanNvblNjaGVtYVR5cGUudHlwZSkge1xuICAgICAgdGFyZ2V0LnR5cGUgPSBqc29uU2NoZW1hVHlwZS50eXBlO1xuICAgIH1cbiAgICBpZihqc29uU2NoZW1hVHlwZS5mb3JtYXQpIHtcbiAgICAgIHRhcmdldC5mb3JtYXQgPSBqc29uU2NoZW1hVHlwZS5mb3JtYXQ7XG4gICAgfVxuICAgIGlmKGpzb25TY2hlbWFUeXBlLiRyZWYpIHtcbiAgICAgIHRhcmdldC5zY2hlbWEgPSB7JHJlZjoganNvblNjaGVtYVR5cGUuJHJlZn07XG4gICAgfVxuICAgIGlmKGpzb25TY2hlbWFUeXBlLml0ZW1zKSB7XG4gICAgICB0YXJnZXQuaXRlbXMgPSBqc29uU2NoZW1hVHlwZS5pdGVtcztcbiAgICB9XG4gIH1cbn07XG5cblN3YWdnZXJTcGVjQ29udmVydGVyLnByb3RvdHlwZS50b0pzb25TY2hlbWEgPSBmdW5jdGlvbihzb3VyY2UpIHtcbiAgaWYoIXNvdXJjZSkge1xuICAgIHJldHVybiAnb2JqZWN0JztcbiAgfVxuICB2YXIgZGV0ZWN0ZWRUeXBlID0gKHNvdXJjZS50eXBlIHx8IHNvdXJjZS5kYXRhVHlwZSB8fCBzb3VyY2UucmVzcG9uc2VDbGFzcyB8fCAnJyk7XG4gIHZhciBsY1R5cGUgPSBkZXRlY3RlZFR5cGUudG9Mb3dlckNhc2UoKTtcbiAgdmFyIGZvcm1hdCA9IChzb3VyY2UuZm9ybWF0IHx8ICcnKS50b0xvd2VyQ2FzZSgpO1xuXG4gIGlmKGxjVHlwZS5pbmRleE9mKCdsaXN0WycpID09PSAwKSB7XG4gICAgdmFyIGlubmVyVHlwZSA9IGRldGVjdGVkVHlwZS5zdWJzdHJpbmcoNSwgZGV0ZWN0ZWRUeXBlLmxlbmd0aCAtIDEpO1xuICAgIHZhciBqc29uVHlwZSA9IHRoaXMudG9Kc29uU2NoZW1hKHt0eXBlOiBpbm5lclR5cGV9KTtcbiAgICByZXR1cm4ge3R5cGU6ICdhcnJheScsIGl0ZW1zOiBqc29uVHlwZX07XG4gIH0gZWxzZSBpZihsY1R5cGUgPT09ICdpbnQnIHx8IChsY1R5cGUgPT09ICdpbnRlZ2VyJyAmJiBmb3JtYXQgPT09ICdpbnQzMicpKSB7XG4gICAge3JldHVybiB7dHlwZTogJ2ludGVnZXInLCBmb3JtYXQ6ICdpbnQzMid9O31cbiAgfSBlbHNlIGlmKGxjVHlwZSA9PT0gJ2xvbmcnIHx8IChsY1R5cGUgPT09ICdpbnRlZ2VyJyAmJiBmb3JtYXQgPT09ICdpbnQ2NCcpKSB7XG4gICAge3JldHVybiB7dHlwZTogJ2ludGVnZXInLCBmb3JtYXQ6ICdpbnQ2NCd9O31cbiAgfSBlbHNlIGlmKGxjVHlwZSA9PT0gJ2ludGVnZXInKSB7XG4gICAge3JldHVybiB7dHlwZTogJ2ludGVnZXInLCBmb3JtYXQ6ICdpbnQ2NCd9O31cbiAgfSBlbHNlIGlmKGxjVHlwZSA9PT0gJ2Zsb2F0JyB8fCAobGNUeXBlID09PSAnbnVtYmVyJyAmJiBmb3JtYXQgPT09ICdmbG9hdCcpKSB7XG4gICAge3JldHVybiB7dHlwZTogJ251bWJlcicsIGZvcm1hdDogJ2Zsb2F0J307fVxuICB9IGVsc2UgaWYobGNUeXBlID09PSAnZG91YmxlJyB8fCAobGNUeXBlID09PSAnbnVtYmVyJyAmJiBmb3JtYXQgPT09ICdkb3VibGUnKSkge1xuICAgIHtyZXR1cm4ge3R5cGU6ICdudW1iZXInLCBmb3JtYXQ6ICdkb3VibGUnfTt9XG4gIH0gZWxzZSBpZigobGNUeXBlID09PSAnc3RyaW5nJyAmJiBmb3JtYXQgPT09ICdkYXRlLXRpbWUnKSB8fCAobGNUeXBlID09PSAnZGF0ZScpKSB7XG4gICAge3JldHVybiB7dHlwZTogJ3N0cmluZycsIGZvcm1hdDogJ2RhdGUtdGltZSd9O31cbiAgfSBlbHNlIGlmKGxjVHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICB7cmV0dXJuIHt0eXBlOiAnc3RyaW5nJ307fVxuICB9IGVsc2UgaWYobGNUeXBlID09PSAnZmlsZScpIHtcbiAgICB7cmV0dXJuIHt0eXBlOiAnZmlsZSd9O31cbiAgfSBlbHNlIGlmKGxjVHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAge3JldHVybiB7dHlwZTogJ2Jvb2xlYW4nfTt9XG4gIH0gZWxzZSBpZihsY1R5cGUgPT09ICdib29sZWFuJykge1xuICAgIHtyZXR1cm4ge3R5cGU6ICdib29sZWFuJ307fVxuICB9IGVsc2UgaWYobGNUeXBlID09PSAnYXJyYXknIHx8IGxjVHlwZSA9PT0gJ2xpc3QnKSB7XG4gICAgaWYoc291cmNlLml0ZW1zKSB7XG4gICAgICB2YXIgaXQgPSB0aGlzLnRvSnNvblNjaGVtYShzb3VyY2UuaXRlbXMpO1xuICAgICAgcmV0dXJuIHt0eXBlOiAnYXJyYXknLCBpdGVtczogaXR9O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHJldHVybiB7dHlwZTogJ2FycmF5JywgaXRlbXM6IHt0eXBlOiAnb2JqZWN0J319O1xuICAgIH1cbiAgfSBlbHNlIGlmKHNvdXJjZS4kcmVmKSB7XG4gICAgcmV0dXJuIHskcmVmOiB0aGlzLm1vZGVsTWFwW3NvdXJjZS4kcmVmXSA/ICcjL2RlZmluaXRpb25zLycgKyB0aGlzLm1vZGVsTWFwW3NvdXJjZS4kcmVmXSA6IHNvdXJjZS4kcmVmfTtcbiAgfSBlbHNlIGlmKGxjVHlwZSA9PT0gJ3ZvaWQnIHx8IGxjVHlwZSA9PT0gJycpIHtcbiAgICB7cmV0dXJuIHt9O31cbiAgfSBlbHNlIGlmICh0aGlzLm1vZGVsTWFwW3NvdXJjZS50eXBlXSkge1xuICAgIC8vIElmIHRoaXMgYSBtb2RlbCB1c2luZyBgdHlwZWAgaW5zdGVhZCBvZiBgJHJlZmAsIHRoYXQncyBmaW5lLlxuICAgIHJldHVybiB7JHJlZjogJyMvZGVmaW5pdGlvbnMvJyArIHRoaXMubW9kZWxNYXBbc291cmNlLnR5cGVdfTtcbiAgfSBlbHNlIHtcbiAgICAvLyBVbmtub3duIG1vZGVsIHR5cGUgb3IgJ29iamVjdCcsIHBhc3MgaXQgYWxvbmcuXG4gICAgcmV0dXJuIHt0eXBlOiBzb3VyY2UudHlwZX07XG4gIH1cbn07XG5cblN3YWdnZXJTcGVjQ29udmVydGVyLnByb3RvdHlwZS5yZXNvdXJjZUxpc3RpbmcgPSBmdW5jdGlvbihvYmosIHN3YWdnZXIsIG9wdHMsIGNhbGxiYWNrKSB7XG4gIHZhciBpO1xuICB2YXIgcHJvY2Vzc2VkQ291bnQgPSAwOyAgIC8vIGpzaGludCBpZ25vcmU6bGluZVxuICB2YXIgc2VsZiA9IHRoaXM7ICAgICAgICAgIC8vIGpzaGludCBpZ25vcmU6bGluZVxuICB2YXIgZXhwZWN0ZWRDb3VudCA9IG9iai5hcGlzLmxlbmd0aDtcbiAgdmFyIF9zd2FnZ2VyID0gc3dhZ2dlcjsgICAvLyBqc2hpbnQgaWdub3JlOmxpbmVcbiAgdmFyIF9vcHRzID0ge307XG5cbiAgaWYob3B0cyAmJiBvcHRzLnJlcXVlc3RJbnRlcmNlcHRvcil7XG4gICAgX29wdHMucmVxdWVzdEludGVyY2VwdG9yID0gb3B0cy5yZXF1ZXN0SW50ZXJjZXB0b3I7XG4gIH1cblxuICBpZihvcHRzICYmIG9wdHMucmVzcG9uc2VJbnRlcmNlcHRvcil7XG4gICAgX29wdHMucmVzcG9uc2VJbnRlcmNlcHRvciA9IG9wdHMucmVzcG9uc2VJbnRlcmNlcHRvcjtcbiAgfVxuXG4gIHZhciBzd2FnZ2VyUmVxdWVzdEhlYWRlcnMgPSAnYXBwbGljYXRpb24vanNvbic7XG5cbiAgaWYob3B0cyAmJiBvcHRzLnN3YWdnZXJSZXF1ZXN0SGVhZGVycykge1xuICAgIHN3YWdnZXJSZXF1ZXN0SGVhZGVycyA9IG9wdHMuc3dhZ2dlclJlcXVlc3RIZWFkZXJzO1xuICB9XG5cbiAgaWYoZXhwZWN0ZWRDb3VudCA9PT0gMCkge1xuICAgIHRoaXMuZmluaXNoKGNhbGxiYWNrLCBzd2FnZ2VyKTtcbiAgfVxuXG4gIGZvcihpID0gMDsgaSA8IGV4cGVjdGVkQ291bnQ7IGkrKykge1xuICAgIHZhciBhcGkgPSBvYmouYXBpc1tpXTtcbiAgICB2YXIgcGF0aCA9IGFwaS5wYXRoO1xuICAgIHZhciBhYnNvbHV0ZVBhdGggPSB0aGlzLmdldEFic29sdXRlUGF0aChvYmouc3dhZ2dlclZlcnNpb24sIHRoaXMuZG9jTG9jYXRpb24sIHBhdGgpO1xuXG4gICAgaWYoYXBpLmRlc2NyaXB0aW9uKSB7XG4gICAgICBzd2FnZ2VyLnRhZ3MgPSBzd2FnZ2VyLnRhZ3MgfHwgW107XG4gICAgICBzd2FnZ2VyLnRhZ3MucHVzaCh7XG4gICAgICAgIG5hbWUgOiB0aGlzLmV4dHJhY3RUYWcoYXBpLnBhdGgpLFxuICAgICAgICBkZXNjcmlwdGlvbiA6IGFwaS5kZXNjcmlwdGlvbiB8fCAnJ1xuICAgICAgfSk7XG4gICAgfVxuICAgIHZhciBodHRwID0ge1xuICAgICAgdXJsOiBhYnNvbHV0ZVBhdGgsXG4gICAgICBoZWFkZXJzOiB7IGFjY2VwdDogc3dhZ2dlclJlcXVlc3RIZWFkZXJzIH0sXG4gICAgICBvbjoge30sXG4gICAgICBtZXRob2Q6ICdnZXQnLFxuICAgICAgdGltZW91dDogb3B0cy50aW1lb3V0XG4gICAgfTtcbiAgICAvKiBqc2hpbnQgaWdub3JlOnN0YXJ0ICovXG4gICAgaHR0cC5vbi5yZXNwb25zZSA9IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgIHByb2Nlc3NlZENvdW50ICs9IDE7XG4gICAgICB2YXIgb2JqID0gZGF0YS5vYmo7XG4gICAgICBpZihvYmopIHtcbiAgICAgICAgc2VsZi5kZWNsYXJhdGlvbihvYmosIF9zd2FnZ2VyKTtcbiAgICAgIH1cbiAgICAgIGlmKHByb2Nlc3NlZENvdW50ID09PSBleHBlY3RlZENvdW50KSB7XG4gICAgICAgIHNlbGYuZmluaXNoKGNhbGxiYWNrLCBfc3dhZ2dlcik7XG4gICAgICB9XG4gICAgfTtcbiAgICBodHRwLm9uLmVycm9yID0gZnVuY3Rpb24oZGF0YSkge1xuICAgICAgY29uc29sZS5lcnJvcihkYXRhKTtcbiAgICAgIHByb2Nlc3NlZENvdW50ICs9IDE7XG4gICAgICBpZihwcm9jZXNzZWRDb3VudCA9PT0gZXhwZWN0ZWRDb3VudCkge1xuICAgICAgICBzZWxmLmZpbmlzaChjYWxsYmFjaywgX3N3YWdnZXIpO1xuICAgICAgfVxuICAgIH07XG4gICAgLyoganNoaW50IGlnbm9yZTplbmQgKi9cblxuICAgIGlmKHRoaXMuY2xpZW50QXV0aG9yaXphdGlvbnMgJiYgdHlwZW9mIHRoaXMuY2xpZW50QXV0aG9yaXphdGlvbnMuYXBwbHkgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRoaXMuY2xpZW50QXV0aG9yaXphdGlvbnMuYXBwbHkoaHR0cCk7XG4gICAgfVxuXG4gICAgbmV3IFN3YWdnZXJIdHRwKCkuZXhlY3V0ZShodHRwLCBfb3B0cyk7XG4gIH1cbn07XG5cblN3YWdnZXJTcGVjQ29udmVydGVyLnByb3RvdHlwZS5nZXRBYnNvbHV0ZVBhdGggPSBmdW5jdGlvbih2ZXJzaW9uLCBkb2NMb2NhdGlvbiwgcGF0aCkgIHtcbiAgaWYodmVyc2lvbiA9PT0gJzEuMCcpIHtcbiAgICBpZihkb2NMb2NhdGlvbi5lbmRzV2l0aCgnLmpzb24nKSkge1xuICAgICAgLy8gZ2V0IHJvb3QgcGF0aFxuICAgICAgdmFyIHBvcyA9IGRvY0xvY2F0aW9uLmxhc3RJbmRleE9mKCcvJyk7XG4gICAgICBpZihwb3MgPiAwKSB7XG4gICAgICAgIGRvY0xvY2F0aW9uID0gZG9jTG9jYXRpb24uc3Vic3RyaW5nKDAsIHBvcyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdmFyIGxvY2F0aW9uID0gZG9jTG9jYXRpb247XG4gIGlmKHBhdGguaW5kZXhPZignaHR0cDonKSA9PT0gMCB8fCBwYXRoLmluZGV4T2YoJ2h0dHBzOicpID09PSAwKSB7XG4gICAgbG9jYXRpb24gPSBwYXRoO1xuICB9XG4gIGVsc2Uge1xuICAgIGlmKGRvY0xvY2F0aW9uLmVuZHNXaXRoKCcvJykpIHtcbiAgICAgIGxvY2F0aW9uID0gZG9jTG9jYXRpb24uc3Vic3RyaW5nKDAsIGRvY0xvY2F0aW9uLmxlbmd0aCAtIDEpO1xuICAgIH1cbiAgICBsb2NhdGlvbiArPSBwYXRoO1xuICB9XG4gIGxvY2F0aW9uID0gbG9jYXRpb24ucmVwbGFjZSgne2Zvcm1hdH0nLCAnanNvbicpO1xuICByZXR1cm4gbG9jYXRpb247XG59O1xuXG5Td2FnZ2VyU3BlY0NvbnZlcnRlci5wcm90b3R5cGUuc2VjdXJpdHlEZWZpbml0aW9ucyA9IGZ1bmN0aW9uKG9iaiwgc3dhZ2dlcikge1xuICBpZihvYmouYXV0aG9yaXphdGlvbnMpIHtcbiAgICB2YXIgbmFtZTtcbiAgICBmb3IobmFtZSBpbiBvYmouYXV0aG9yaXphdGlvbnMpIHtcbiAgICAgIHZhciBpc1ZhbGlkID0gZmFsc2U7XG4gICAgICB2YXIgc2VjdXJpdHlEZWZpbml0aW9uID0ge1xuICAgICAgICB2ZW5kb3JFeHRlbnNpb25zOiB7fVxuICAgICAgfTtcbiAgICAgIHZhciBkZWZpbml0aW9uID0gb2JqLmF1dGhvcml6YXRpb25zW25hbWVdO1xuICAgICAgaWYoZGVmaW5pdGlvbi50eXBlID09PSAnYXBpS2V5Jykge1xuICAgICAgICBzZWN1cml0eURlZmluaXRpb24udHlwZSA9ICdhcGlLZXknO1xuICAgICAgICBzZWN1cml0eURlZmluaXRpb24uaW4gPSBkZWZpbml0aW9uLnBhc3NBcztcbiAgICAgICAgc2VjdXJpdHlEZWZpbml0aW9uLm5hbWUgPSBkZWZpbml0aW9uLmtleW5hbWUgfHwgbmFtZTtcbiAgICAgICAgaXNWYWxpZCA9IHRydWU7XG4gICAgICB9XG4gICAgICBlbHNlIGlmKGRlZmluaXRpb24udHlwZSA9PT0gJ2Jhc2ljQXV0aCcpIHtcbiAgICAgICAgc2VjdXJpdHlEZWZpbml0aW9uLnR5cGUgPSAnYmFzaWNBdXRoJztcbiAgICAgICAgaXNWYWxpZCA9IHRydWU7XG4gICAgICB9XG4gICAgICBlbHNlIGlmKGRlZmluaXRpb24udHlwZSA9PT0gJ29hdXRoMicpIHtcbiAgICAgICAgdmFyIGV4aXN0aW5nU2NvcGVzID0gZGVmaW5pdGlvbi5zY29wZXMgfHwgW107XG4gICAgICAgIHZhciBzY29wZXMgPSB7fTtcbiAgICAgICAgdmFyIGk7XG4gICAgICAgIGZvcihpIGluIGV4aXN0aW5nU2NvcGVzKSB7XG4gICAgICAgICAgdmFyIHNjb3BlID0gZXhpc3RpbmdTY29wZXNbaV07XG4gICAgICAgICAgc2NvcGVzW3Njb3BlLnNjb3BlXSA9IHNjb3BlLmRlc2NyaXB0aW9uO1xuICAgICAgICB9XG4gICAgICAgIHNlY3VyaXR5RGVmaW5pdGlvbi50eXBlID0gJ29hdXRoMic7XG4gICAgICAgIGlmKGkgPiAwKSB7XG4gICAgICAgICAgc2VjdXJpdHlEZWZpbml0aW9uLnNjb3BlcyA9IHNjb3BlcztcbiAgICAgICAgfVxuICAgICAgICBpZihkZWZpbml0aW9uLmdyYW50VHlwZXMpIHtcbiAgICAgICAgICBpZihkZWZpbml0aW9uLmdyYW50VHlwZXMuaW1wbGljaXQpIHtcbiAgICAgICAgICAgIHZhciBpbXBsaWNpdCA9IGRlZmluaXRpb24uZ3JhbnRUeXBlcy5pbXBsaWNpdDtcbiAgICAgICAgICAgIHNlY3VyaXR5RGVmaW5pdGlvbi5mbG93ID0gJ2ltcGxpY2l0JztcbiAgICAgICAgICAgIHNlY3VyaXR5RGVmaW5pdGlvbi5hdXRob3JpemF0aW9uVXJsID0gaW1wbGljaXQubG9naW5FbmRwb2ludDtcbiAgICAgICAgICAgIGlzVmFsaWQgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICAvKiBqc2hpbnQgaWdub3JlOnN0YXJ0ICovXG4gICAgICAgICAgaWYoZGVmaW5pdGlvbi5ncmFudFR5cGVzWydhdXRob3JpemF0aW9uX2NvZGUnXSkge1xuICAgICAgICAgICAgaWYoIXNlY3VyaXR5RGVmaW5pdGlvbi5mbG93KSB7XG4gICAgICAgICAgICAgIC8vIGNhbm5vdCBzZXQgaWYgZmxvdyBpcyBhbHJlYWR5IGRlZmluZWRcbiAgICAgICAgICAgICAgdmFyIGF1dGhDb2RlID0gZGVmaW5pdGlvbi5ncmFudFR5cGVzWydhdXRob3JpemF0aW9uX2NvZGUnXTtcbiAgICAgICAgICAgICAgc2VjdXJpdHlEZWZpbml0aW9uLmZsb3cgPSAnYWNjZXNzQ29kZSc7XG4gICAgICAgICAgICAgIHNlY3VyaXR5RGVmaW5pdGlvbi5hdXRob3JpemF0aW9uVXJsID0gYXV0aENvZGUudG9rZW5SZXF1ZXN0RW5kcG9pbnQudXJsO1xuICAgICAgICAgICAgICBzZWN1cml0eURlZmluaXRpb24udG9rZW5VcmwgPSBhdXRoQ29kZS50b2tlbkVuZHBvaW50LnVybDtcbiAgICAgICAgICAgICAgaXNWYWxpZCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIC8qIGpzaGludCBpZ25vcmU6ZW5kICovXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmKGlzVmFsaWQpIHtcbiAgICAgICAgc3dhZ2dlci5zZWN1cml0eURlZmluaXRpb25zID0gc3dhZ2dlci5zZWN1cml0eURlZmluaXRpb25zIHx8IHt9O1xuICAgICAgICBzd2FnZ2VyLnNlY3VyaXR5RGVmaW5pdGlvbnNbbmFtZV0gPSBzZWN1cml0eURlZmluaXRpb247XG4gICAgICB9XG4gICAgfVxuICB9XG59O1xuXG5Td2FnZ2VyU3BlY0NvbnZlcnRlci5wcm90b3R5cGUuYXBpSW5mbyA9IGZ1bmN0aW9uKG9iaiwgc3dhZ2dlcikge1xuICAvLyBpbmZvIHNlY3Rpb25cbiAgaWYob2JqLmluZm8pIHtcbiAgICB2YXIgaW5mbyA9IG9iai5pbmZvO1xuICAgIHN3YWdnZXIuaW5mbyA9IHt9O1xuXG4gICAgaWYoaW5mby5jb250YWN0KSB7XG4gICAgICBzd2FnZ2VyLmluZm8uY29udGFjdCA9IHt9O1xuICAgICAgc3dhZ2dlci5pbmZvLmNvbnRhY3QuZW1haWwgPSBpbmZvLmNvbnRhY3Q7XG4gICAgfVxuICAgIGlmKGluZm8uZGVzY3JpcHRpb24pIHtcbiAgICAgIHN3YWdnZXIuaW5mby5kZXNjcmlwdGlvbiA9IGluZm8uZGVzY3JpcHRpb247XG4gICAgfVxuICAgIGlmKGluZm8udGl0bGUpIHtcbiAgICAgIHN3YWdnZXIuaW5mby50aXRsZSA9IGluZm8udGl0bGU7XG4gICAgfVxuICAgIGlmKGluZm8udGVybXNPZlNlcnZpY2VVcmwpIHtcbiAgICAgIHN3YWdnZXIuaW5mby50ZXJtc09mU2VydmljZSA9IGluZm8udGVybXNPZlNlcnZpY2VVcmw7XG4gICAgfVxuICAgIGlmKGluZm8ubGljZW5zZSB8fCBpbmZvLmxpY2Vuc2VVcmwpIHtcbiAgICAgIHN3YWdnZXIubGljZW5zZSA9IHt9O1xuICAgICAgaWYoaW5mby5saWNlbnNlKSB7XG4gICAgICAgIHN3YWdnZXIubGljZW5zZS5uYW1lID0gaW5mby5saWNlbnNlO1xuICAgICAgfVxuICAgICAgaWYoaW5mby5saWNlbnNlVXJsKSB7XG4gICAgICAgIHN3YWdnZXIubGljZW5zZS51cmwgPSBpbmZvLmxpY2Vuc2VVcmw7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIHRoaXMud2FybmluZ3MucHVzaCgnbWlzc2luZyBpbmZvIHNlY3Rpb24nKTtcbiAgfVxufTtcblxuU3dhZ2dlclNwZWNDb252ZXJ0ZXIucHJvdG90eXBlLmZpbmlzaCA9IGZ1bmN0aW9uIChjYWxsYmFjaywgb2JqKSB7XG4gIGNhbGxiYWNrKG9iaik7XG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgbG9nID0gcmVxdWlyZSgnLi4vaGVscGVycycpLmxvZztcbnZhciBfID0ge1xuICBpc1BsYWluT2JqZWN0OiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvaXNQbGFpbk9iamVjdCcpLFxuICBpc1N0cmluZzogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9sYW5nL2lzU3RyaW5nJyksXG59O1xuXG52YXIgU2NoZW1hTWFya3VwID0gcmVxdWlyZSgnLi4vc2NoZW1hLW1hcmt1cC5qcycpO1xudmFyIGpzeWFtbCA9IHJlcXVpcmUoJ2pzLXlhbWwnKTtcblxudmFyIE1vZGVsID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAobmFtZSwgZGVmaW5pdGlvbiwgbW9kZWxzLCBtb2RlbFByb3BlcnR5TWFjcm8pIHtcbiAgdGhpcy5kZWZpbml0aW9uID0gZGVmaW5pdGlvbiB8fCB7fTtcbiAgdGhpcy5pc0FycmF5ID0gZGVmaW5pdGlvbi50eXBlID09PSAnYXJyYXknO1xuICB0aGlzLm1vZGVscyA9IG1vZGVscyB8fCB7fTtcbiAgdGhpcy5uYW1lID0gbmFtZSB8fCBkZWZpbml0aW9uLnRpdGxlIHx8ICdJbmxpbmUgTW9kZWwnO1xuICB0aGlzLm1vZGVsUHJvcGVydHlNYWNybyA9IG1vZGVsUHJvcGVydHlNYWNybyB8fCBmdW5jdGlvbiAocHJvcGVydHkpIHtcbiAgICByZXR1cm4gcHJvcGVydHkuZGVmYXVsdDtcbiAgfTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbi8vIE5vdGUhICBUaGlzIGZ1bmN0aW9uIHdpbGwgYmUgcmVtb3ZlZCBpbiAyLjIueCFcbk1vZGVsLnByb3RvdHlwZS5jcmVhdGVKU09OU2FtcGxlID0gTW9kZWwucHJvdG90eXBlLmdldFNhbXBsZVZhbHVlID0gZnVuY3Rpb24gKG1vZGVsc1RvSWdub3JlKSB7XG4gIG1vZGVsc1RvSWdub3JlID0gbW9kZWxzVG9JZ25vcmUgfHwge307XG5cbiAgbW9kZWxzVG9JZ25vcmVbdGhpcy5uYW1lXSA9IHRoaXM7XG5cbiAgLy8gUmVzcG9uc2Ugc3VwcG9ydFxuICBpZiAodGhpcy5leGFtcGxlcyAmJiBfLmlzUGxhaW5PYmplY3QodGhpcy5leGFtcGxlcykgJiYgdGhpcy5leGFtcGxlc1snYXBwbGljYXRpb24vanNvbiddKSB7XG4gICAgdGhpcy5kZWZpbml0aW9uLmV4YW1wbGUgPSB0aGlzLmV4YW1wbGVzWydhcHBsaWNhdGlvbi9qc29uJ107XG5cbiAgICBpZiAoXy5pc1N0cmluZyh0aGlzLmRlZmluaXRpb24uZXhhbXBsZSkpIHtcbiAgICAgIHRoaXMuZGVmaW5pdGlvbi5leGFtcGxlID0ganN5YW1sLnNhZmVMb2FkKHRoaXMuZGVmaW5pdGlvbi5leGFtcGxlKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoIXRoaXMuZGVmaW5pdGlvbi5leGFtcGxlKSB7XG4gICAgdGhpcy5kZWZpbml0aW9uLmV4YW1wbGUgPSB0aGlzLmV4YW1wbGVzO1xuICB9XG5cbiAgcmV0dXJuIFNjaGVtYU1hcmt1cC5zY2hlbWFUb0pTT04odGhpcy5kZWZpbml0aW9uLCB0aGlzLm1vZGVscywgbW9kZWxzVG9JZ25vcmUsIHRoaXMubW9kZWxQcm9wZXJ0eU1hY3JvKTtcbn07XG5cbk1vZGVsLnByb3RvdHlwZS5nZXRNb2NrU2lnbmF0dXJlID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gU2NoZW1hTWFya3VwLnNjaGVtYVRvSFRNTCh0aGlzLm5hbWUsIHRoaXMuZGVmaW5pdGlvbiwgdGhpcy5tb2RlbHMsIHRoaXMubW9kZWxQcm9wZXJ0eU1hY3JvKTtcbn07XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBfID0ge1xuICBjbG9uZURlZXA6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvbGFuZy9jbG9uZURlZXAnKSxcbiAgaXNVbmRlZmluZWQ6IHJlcXVpcmUoJ2xvZGFzaC1jb21wYXQvbGFuZy9pc1VuZGVmaW5lZCcpLFxuICBpc0VtcHR5OiByZXF1aXJlKCdsb2Rhc2gtY29tcGF0L2xhbmcvaXNFbXB0eScpLFxuICBpc09iamVjdDogcmVxdWlyZSgnbG9kYXNoLWNvbXBhdC9sYW5nL2lzT2JqZWN0Jylcbn07XG52YXIgaGVscGVycyA9IHJlcXVpcmUoJy4uL2hlbHBlcnMnKTtcbnZhciBNb2RlbCA9IHJlcXVpcmUoJy4vbW9kZWwnKTtcbnZhciBTd2FnZ2VySHR0cCA9IHJlcXVpcmUoJy4uL2h0dHAnKTtcbnZhciBRID0gcmVxdWlyZSgncScpO1xuXG52YXIgT3BlcmF0aW9uID0gbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocGFyZW50LCBzY2hlbWUsIG9wZXJhdGlvbklkLCBodHRwTWV0aG9kLCBwYXRoLCBhcmdzLCBkZWZpbml0aW9ucywgbW9kZWxzLCBjbGllbnRBdXRob3JpemF0aW9ucykge1xuICB2YXIgZXJyb3JzID0gW107XG5cbiAgcGFyZW50ID0gcGFyZW50IHx8IHt9O1xuICBhcmdzID0gYXJncyB8fCB7fTtcblxuICBpZihwYXJlbnQgJiYgcGFyZW50Lm9wdGlvbnMpIHtcbiAgICB0aGlzLmNsaWVudCA9IHBhcmVudC5vcHRpb25zLmNsaWVudCB8fCBudWxsO1xuICAgIHRoaXMucmVxdWVzdEludGVyY2VwdG9yID0gcGFyZW50Lm9wdGlvbnMucmVxdWVzdEludGVyY2VwdG9yIHx8IG51bGw7XG4gICAgdGhpcy5yZXNwb25zZUludGVyY2VwdG9yID0gcGFyZW50Lm9wdGlvbnMucmVzcG9uc2VJbnRlcmNlcHRvciB8fCBudWxsO1xuICAgIHRoaXMucmVxdWVzdEFnZW50ID0gcGFyZW50Lm9wdGlvbnMucmVxdWVzdEFnZW50O1xuICB9XG4gIHRoaXMuYXV0aG9yaXphdGlvbnMgPSBhcmdzLnNlY3VyaXR5O1xuICB0aGlzLmJhc2VQYXRoID0gcGFyZW50LmJhc2VQYXRoIHx8ICcvJztcbiAgdGhpcy5jbGllbnRBdXRob3JpemF0aW9ucyA9IGNsaWVudEF1dGhvcml6YXRpb25zO1xuICB0aGlzLmNvbnN1bWVzID0gYXJncy5jb25zdW1lcyB8fCBwYXJlbnQuY29uc3VtZXMgfHwgWydhcHBsaWNhdGlvbi9qc29uJ107XG4gIHRoaXMucHJvZHVjZXMgPSBhcmdzLnByb2R1Y2VzIHx8IHBhcmVudC5wcm9kdWNlcyB8fCBbJ2FwcGxpY2F0aW9uL2pzb24nXTtcbiAgdGhpcy5kZXByZWNhdGVkID0gYXJncy5kZXByZWNhdGVkO1xuICB0aGlzLmRlc2NyaXB0aW9uID0gYXJncy5kZXNjcmlwdGlvbjtcbiAgdGhpcy5ob3N0ID0gcGFyZW50Lmhvc3Q7XG4gIHRoaXMubWV0aG9kID0gKGh0dHBNZXRob2QgfHwgZXJyb3JzLnB1c2goJ09wZXJhdGlvbiAnICsgb3BlcmF0aW9uSWQgKyAnIGlzIG1pc3NpbmcgbWV0aG9kLicpKTtcbiAgdGhpcy5tb2RlbHMgPSBtb2RlbHMgfHwge307XG4gIHRoaXMubmlja25hbWUgPSAob3BlcmF0aW9uSWQgfHwgZXJyb3JzLnB1c2goJ09wZXJhdGlvbnMgbXVzdCBoYXZlIGEgbmlja25hbWUuJykpO1xuICB0aGlzLm9wZXJhdGlvbiA9IGFyZ3M7XG4gIHRoaXMub3BlcmF0aW9ucyA9IHt9O1xuICB0aGlzLnBhcmFtZXRlcnMgPSBhcmdzICE9PSBudWxsID8gKGFyZ3MucGFyYW1ldGVycyB8fCBbXSkgOiB7fTtcbiAgdGhpcy5wYXJlbnQgPSBwYXJlbnQ7XG4gIHRoaXMucGF0aCA9IChwYXRoIHx8IGVycm9ycy5wdXNoKCdPcGVyYXRpb24gJyArIHRoaXMubmlja25hbWUgKyAnIGlzIG1pc3NpbmcgcGF0aC4nKSk7XG4gIHRoaXMucmVzcG9uc2VzID0gKGFyZ3MucmVzcG9uc2VzIHx8IHt9KTtcbiAgdGhpcy5zY2hlbWUgPSBzY2hlbWUgfHwgcGFyZW50LnNjaGVtZSB8fCAnaHR0cCc7XG4gIHRoaXMuc2NoZW1lcyA9IGFyZ3Muc2NoZW1lcyB8fCBwYXJlbnQuc2NoZW1lcztcbiAgdGhpcy5zZWN1cml0eSA9IGFyZ3Muc2VjdXJpdHkgfHwgcGFyZW50LnNlY3VyaXR5O1xuICB0aGlzLnN1bW1hcnkgPSBhcmdzLnN1bW1hcnkgfHwgJyc7XG4gIHRoaXMudGltZW91dCA9IHBhcmVudC50aW1lb3V0O1xuICB0aGlzLnR5cGUgPSBudWxsO1xuICB0aGlzLnVzZUpRdWVyeSA9IHBhcmVudC51c2VKUXVlcnk7XG4gIHRoaXMuanF1ZXJ5QWpheENhY2hlID0gcGFyZW50LmpxdWVyeUFqYXhDYWNoZTtcbiAgdGhpcy5lbmFibGVDb29raWVzID0gcGFyZW50LmVuYWJsZUNvb2tpZXM7XG5cbiAgdmFyIGtleTtcblxuICBpZighdGhpcy5ob3N0KSB7XG4gICAgaWYodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRoaXMuaG9zdCA9IHdpbmRvdy5sb2NhdGlvbi5ob3N0O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRoaXMuaG9zdCA9ICdsb2NhbGhvc3QnO1xuICAgIH1cbiAgfVxuICB0aGlzLnBhcmFtZXRlck1hY3JvID0gcGFyZW50LnBhcmFtZXRlck1hY3JvIHx8IGZ1bmN0aW9uIChvcGVyYXRpb24sIHBhcmFtZXRlcikge1xuICAgIHJldHVybiBwYXJhbWV0ZXIuZGVmYXVsdDtcbiAgfTtcblxuICB0aGlzLmlubGluZU1vZGVscyA9IFtdO1xuXG4gIGlmKHRoaXMuYmFzZVBhdGggIT09ICcvJyAmJiB0aGlzLmJhc2VQYXRoLnNsaWNlKC0xKSA9PT0gJy8nKSB7XG4gICAgdGhpcy5iYXNlUGF0aCA9IHRoaXMuYmFzZVBhdGguc2xpY2UoMCwgLTEpO1xuICB9XG5cbiAgaWYgKHR5cGVvZiB0aGlzLmRlcHJlY2F0ZWQgPT09ICdzdHJpbmcnKSB7XG4gICAgc3dpdGNoKHRoaXMuZGVwcmVjYXRlZC50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICBjYXNlICd0cnVlJzogY2FzZSAneWVzJzogY2FzZSAnMSc6IHtcbiAgICAgICAgdGhpcy5kZXByZWNhdGVkID0gdHJ1ZTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGNhc2UgJ2ZhbHNlJzogY2FzZSAnbm8nOiBjYXNlICcwJzogY2FzZSBudWxsOiB7XG4gICAgICAgIHRoaXMuZGVwcmVjYXRlZCA9IGZhbHNlO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgICAgZGVmYXVsdDogdGhpcy5kZXByZWNhdGVkID0gQm9vbGVhbih0aGlzLmRlcHJlY2F0ZWQpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBpLCBtb2RlbDtcblxuICBpZiAoZGVmaW5pdGlvbnMpIHtcbiAgICAvLyBhZGQgdG8gZ2xvYmFsIG1vZGVsc1xuICAgIGZvciAoa2V5IGluIGRlZmluaXRpb25zKSB7XG4gICAgICBtb2RlbCA9IG5ldyBNb2RlbChrZXksIGRlZmluaXRpb25zW2tleV0sIHRoaXMubW9kZWxzLCBwYXJlbnQubW9kZWxQcm9wZXJ0eU1hY3JvKTtcblxuICAgICAgaWYgKG1vZGVsKSB7XG4gICAgICAgIHRoaXMubW9kZWxzW2tleV0gPSBtb2RlbDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZWxzZSB7XG4gICAgZGVmaW5pdGlvbnMgPSB7fTtcbiAgfVxuXG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnBhcmFtZXRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgZCwgcGFyYW0gPSB0aGlzLnBhcmFtZXRlcnNbaV07XG5cbiAgICAvLyBBbGxvdyBtYWNybyB0byBzZXQgdGhlIGRlZmF1bHQgdmFsdWVcbiAgICBwYXJhbS5kZWZhdWx0ID0gdGhpcy5wYXJhbWV0ZXJNYWNybyh0aGlzLCBwYXJhbSk7XG5cbiAgICBpZiAocGFyYW0udHlwZSA9PT0gJ2FycmF5Jykge1xuICAgICAgcGFyYW0uaXNMaXN0ID0gdHJ1ZTtcbiAgICAgIHBhcmFtLmFsbG93TXVsdGlwbGUgPSB0cnVlO1xuICAgIH1cblxuICAgIHZhciBpbm5lclR5cGUgPSB0aGlzLmdldFR5cGUocGFyYW0pO1xuXG4gICAgaWYgKGlubmVyVHlwZSAmJiBpbm5lclR5cGUudG9TdHJpbmcoKS50b0xvd2VyQ2FzZSgpID09PSAnYm9vbGVhbicpIHtcbiAgICAgIHBhcmFtLmFsbG93YWJsZVZhbHVlcyA9IHt9O1xuICAgICAgcGFyYW0uaXNMaXN0ID0gdHJ1ZTtcbiAgICAgIHBhcmFtWydlbnVtJ10gPSBbdHJ1ZSwgZmFsc2VdOyAvLyB1c2UgYWN0dWFsIHByaW1pdGl2ZXNcbiAgICB9XG5cbiAgICBmb3Ioa2V5IGluIHBhcmFtKSB7XG4gICAgICBoZWxwZXJzLmV4dHJhY3RFeHRlbnNpb25zKGtleSwgcGFyYW0pO1xuICAgIH1cbiAgICBpZih0eXBlb2YgcGFyYW1bJ3gtZXhhbXBsZSddICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgZCA9IHBhcmFtWyd4LWV4YW1wbGUnXTtcbiAgICAgIHBhcmFtLmRlZmF1bHQgPSBkO1xuICAgIH1cbiAgICBpZihwYXJhbVsneC1leGFtcGxlcyddKSB7XG4gICAgICBkID0gcGFyYW1bJ3gtZXhhbXBsZXMnXS5kZWZhdWx0O1xuICAgICAgaWYodHlwZW9mIGQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHBhcmFtLmRlZmF1bHQgPSBkO1xuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBlbnVtVmFsdWVzID0gcGFyYW1bJ2VudW0nXSB8fCAocGFyYW0uaXRlbXMgJiYgcGFyYW0uaXRlbXNbJ2VudW0nXSk7XG5cbiAgICBpZiAodHlwZW9mIGVudW1WYWx1ZXMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB2YXIgaWQ7XG5cbiAgICAgIHBhcmFtLmFsbG93YWJsZVZhbHVlcyA9IHt9O1xuICAgICAgcGFyYW0uYWxsb3dhYmxlVmFsdWVzLnZhbHVlcyA9IFtdO1xuICAgICAgcGFyYW0uYWxsb3dhYmxlVmFsdWVzLmRlc2NyaXB0aXZlVmFsdWVzID0gW107XG5cbiAgICAgIGZvciAoaWQgPSAwOyBpZCA8IGVudW1WYWx1ZXMubGVuZ3RoOyBpZCsrKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IGVudW1WYWx1ZXNbaWRdO1xuICAgICAgICB2YXIgaXNEZWZhdWx0ID0gKHZhbHVlID09PSBwYXJhbS5kZWZhdWx0IHx8IHZhbHVlKycnID09PSBwYXJhbS5kZWZhdWx0KTtcblxuICAgICAgICBwYXJhbS5hbGxvd2FibGVWYWx1ZXMudmFsdWVzLnB1c2godmFsdWUpO1xuICAgICAgICAvLyBBbHdheXMgaGF2ZSBzdHJpbmcgZm9yIGRlc2NyaXB0aXZlIHZhbHVlcy4uLi5cbiAgICAgICAgcGFyYW0uYWxsb3dhYmxlVmFsdWVzLmRlc2NyaXB0aXZlVmFsdWVzLnB1c2goe3ZhbHVlIDogdmFsdWUrJycsIGlzRGVmYXVsdDogaXNEZWZhdWx0fSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHBhcmFtLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgIGlubmVyVHlwZSA9IFtpbm5lclR5cGVdO1xuXG4gICAgICBpZiAodHlwZW9mIHBhcmFtLmFsbG93YWJsZVZhbHVlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgLy8gY2FuJ3Qgc2hvdyBhcyBhIGxpc3QgaWYgbm8gdmFsdWVzIHRvIHNlbGVjdCBmcm9tXG4gICAgICAgIGRlbGV0ZSBwYXJhbS5pc0xpc3Q7XG4gICAgICAgIGRlbGV0ZSBwYXJhbS5hbGxvd011bHRpcGxlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHBhcmFtLm1vZGVsU2lnbmF0dXJlID0ge3R5cGU6IGlubmVyVHlwZSwgZGVmaW5pdGlvbnM6IHRoaXMubW9kZWxzfTtcbiAgICBwYXJhbS5zaWduYXR1cmUgPSB0aGlzLmdldE1vZGVsU2lnbmF0dXJlKGlubmVyVHlwZSwgdGhpcy5tb2RlbHMpLnRvU3RyaW5nKCk7XG4gICAgcGFyYW0uc2FtcGxlSlNPTiA9IHRoaXMuZ2V0TW9kZWxTYW1wbGVKU09OKGlubmVyVHlwZSwgdGhpcy5tb2RlbHMpO1xuICAgIHBhcmFtLnJlc3BvbnNlQ2xhc3NTaWduYXR1cmUgPSBwYXJhbS5zaWduYXR1cmU7XG4gIH1cblxuICB2YXIga2V5bmFtZSwgZGVmYXVsdFJlc3BvbnNlQ29kZSwgcmVzcG9uc2UsIHJlc3BvbnNlcyA9IHRoaXMucmVzcG9uc2VzO1xuXG4gIGlmIChyZXNwb25zZXNbJzIwMCddKSB7XG4gICAgcmVzcG9uc2UgPSByZXNwb25zZXNbJzIwMCddO1xuICAgIGRlZmF1bHRSZXNwb25zZUNvZGUgPSAnMjAwJztcbiAgfSBlbHNlIGlmIChyZXNwb25zZXNbJzIwMSddKSB7XG4gICAgcmVzcG9uc2UgPSByZXNwb25zZXNbJzIwMSddO1xuICAgIGRlZmF1bHRSZXNwb25zZUNvZGUgPSAnMjAxJztcbiAgfSBlbHNlIGlmIChyZXNwb25zZXNbJzIwMiddKSB7XG4gICAgcmVzcG9uc2UgPSByZXNwb25zZXNbJzIwMiddO1xuICAgIGRlZmF1bHRSZXNwb25zZUNvZGUgPSAnMjAyJztcbiAgfSBlbHNlIGlmIChyZXNwb25zZXNbJzIwMyddKSB7XG4gICAgcmVzcG9uc2UgPSByZXNwb25zZXNbJzIwMyddO1xuICAgIGRlZmF1bHRSZXNwb25zZUNvZGUgPSAnMjAzJztcbiAgfSBlbHNlIGlmIChyZXNwb25zZXNbJzIwNCddKSB7XG4gICAgcmVzcG9uc2UgPSByZXNwb25zZXNbJzIwNCddO1xuICAgIGRlZmF1bHRSZXNwb25zZUNvZGUgPSAnMjA0JztcbiAgfSBlbHNlIGlmIChyZXNwb25zZXNbJzIwNSddKSB7XG4gICAgcmVzcG9uc2UgPSByZXNwb25zZXNbJzIwNSddO1xuICAgIGRlZmF1bHRSZXNwb25zZUNvZGUgPSAnMjA1JztcbiAgfSBlbHNlIGlmIChyZXNwb25zZXNbJzIwNiddKSB7XG4gICAgcmVzcG9uc2UgPSByZXNwb25zZXNbJzIwNiddO1xuICAgIGRlZmF1bHRSZXNwb25zZUNvZGUgPSAnMjA2JztcbiAgfSBlbHNlIGlmIChyZXNwb25zZXNbJ2RlZmF1bHQnXSkge1xuICAgIHJlc3BvbnNlID0gcmVzcG9uc2VzWydkZWZhdWx0J107XG4gICAgZGVmYXVsdFJlc3BvbnNlQ29kZSA9ICdkZWZhdWx0JztcbiAgfVxuXG4gIGZvcihrZXluYW1lIGluIHJlc3BvbnNlcykge1xuICAgIGhlbHBlcnMuZXh0cmFjdEV4dGVuc2lvbnMoa2V5bmFtZSwgcmVzcG9uc2VzKTtcbiAgICBpZih0eXBlb2Yga2V5bmFtZSA9PT0gJ3N0cmluZycgJiYga2V5bmFtZS5pbmRleE9mKCd4LScpID09PSAtMSkge1xuICAgICAgdmFyIHJlc3BvbnNlT2JqZWN0ID0gcmVzcG9uc2VzW2tleW5hbWVdO1xuICAgICAgaWYodHlwZW9mIHJlc3BvbnNlT2JqZWN0ID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgcmVzcG9uc2VPYmplY3QuaGVhZGVycyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgdmFyIGhlYWRlcnMgPSByZXNwb25zZU9iamVjdC5oZWFkZXJzO1xuICAgICAgICBmb3IodmFyIGhlYWRlck5hbWUgaW4gaGVhZGVycykge1xuICAgICAgICAgIHZhciBoZWFkZXIgPSBoZWFkZXJzW2hlYWRlck5hbWVdO1xuICAgICAgICAgIGlmKHR5cGVvZiBoZWFkZXIgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICBmb3IodmFyIGhlYWRlcktleSBpbiBoZWFkZXIpIHtcbiAgICAgICAgICAgICAgaGVscGVycy5leHRyYWN0RXh0ZW5zaW9ucyhoZWFkZXJLZXksIGhlYWRlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKHJlc3BvbnNlKSB7XG4gICAgZm9yKGtleW5hbWUgaW4gcmVzcG9uc2UpIHtcbiAgICAgIGhlbHBlcnMuZXh0cmFjdEV4dGVuc2lvbnMoa2V5bmFtZSwgcmVzcG9uc2UpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChyZXNwb25zZSAmJiByZXNwb25zZS5zY2hlbWEpIHtcbiAgICB2YXIgcmVzb2x2ZWRNb2RlbCA9IHRoaXMucmVzb2x2ZU1vZGVsKHJlc3BvbnNlLnNjaGVtYSwgZGVmaW5pdGlvbnMpO1xuICAgIHZhciBzdWNjZXNzUmVzcG9uc2U7XG5cbiAgICBkZWxldGUgcmVzcG9uc2VzW2RlZmF1bHRSZXNwb25zZUNvZGVdO1xuXG4gICAgaWYgKHJlc29sdmVkTW9kZWwpIHtcbiAgICAgIHRoaXMuc3VjY2Vzc1Jlc3BvbnNlID0ge307XG4gICAgICBzdWNjZXNzUmVzcG9uc2UgPSB0aGlzLnN1Y2Nlc3NSZXNwb25zZVtkZWZhdWx0UmVzcG9uc2VDb2RlXSA9IHJlc29sdmVkTW9kZWw7XG4gICAgfSBlbHNlIGlmICghcmVzcG9uc2Uuc2NoZW1hLnR5cGUgfHwgcmVzcG9uc2Uuc2NoZW1hLnR5cGUgPT09ICdvYmplY3QnIHx8IHJlc3BvbnNlLnNjaGVtYS50eXBlID09PSAnYXJyYXknKSB7XG4gICAgICAvLyBJbmxpbmUgbW9kZWxcbiAgICAgIHRoaXMuc3VjY2Vzc1Jlc3BvbnNlID0ge307XG4gICAgICBzdWNjZXNzUmVzcG9uc2UgPSB0aGlzLnN1Y2Nlc3NSZXNwb25zZVtkZWZhdWx0UmVzcG9uc2VDb2RlXSA9IG5ldyBNb2RlbCh1bmRlZmluZWQsIHJlc3BvbnNlLnNjaGVtYSB8fCB7fSwgdGhpcy5tb2RlbHMsIHBhcmVudC5tb2RlbFByb3BlcnR5TWFjcm8pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBQcmltaXRpdmVcbiAgICAgIHRoaXMuc3VjY2Vzc1Jlc3BvbnNlID0ge307XG4gICAgICBzdWNjZXNzUmVzcG9uc2UgPSB0aGlzLnN1Y2Nlc3NSZXNwb25zZVtkZWZhdWx0UmVzcG9uc2VDb2RlXSA9IHJlc3BvbnNlLnNjaGVtYTtcbiAgICB9XG5cbiAgICBpZiAoc3VjY2Vzc1Jlc3BvbnNlKSB7XG4gICAgICBzdWNjZXNzUmVzcG9uc2UudmVuZG9yRXh0ZW5zaW9ucyA9IHJlc3BvbnNlLnZlbmRvckV4dGVuc2lvbnM7XG4gICAgICAvLyBBdHRhY2ggcmVzcG9uc2UgcHJvcGVydGllc1xuICAgICAgaWYgKHJlc3BvbnNlLmRlc2NyaXB0aW9uKSB7XG4gICAgICAgIHN1Y2Nlc3NSZXNwb25zZS5kZXNjcmlwdGlvbiA9IHJlc3BvbnNlLmRlc2NyaXB0aW9uO1xuICAgICAgfVxuXG4gICAgICBpZiAocmVzcG9uc2UuZXhhbXBsZXMpIHtcbiAgICAgICAgc3VjY2Vzc1Jlc3BvbnNlLmV4YW1wbGVzID0gcmVzcG9uc2UuZXhhbXBsZXM7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzKSB7XG4gICAgICAgIHN1Y2Nlc3NSZXNwb25zZS5oZWFkZXJzID0gcmVzcG9uc2UuaGVhZGVycztcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLnR5cGUgPSByZXNwb25zZTtcbiAgfVxuXG4gIGlmIChlcnJvcnMubGVuZ3RoID4gMCkge1xuICAgIGlmICh0aGlzLnJlc291cmNlICYmIHRoaXMucmVzb3VyY2UuYXBpICYmIHRoaXMucmVzb3VyY2UuYXBpLmZhaWwpIHtcbiAgICAgIHRoaXMucmVzb3VyY2UuYXBpLmZhaWwoZXJyb3JzKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGhpcztcbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUuaXNEZWZhdWx0QXJyYXlJdGVtVmFsdWUgPSBmdW5jdGlvbih2YWx1ZSwgcGFyYW0pIHtcbiAgaWYgKHBhcmFtLmRlZmF1bHQgJiYgQXJyYXkuaXNBcnJheShwYXJhbS5kZWZhdWx0KSkge1xuICAgIHJldHVybiBwYXJhbS5kZWZhdWx0LmluZGV4T2YodmFsdWUpICE9PSAtMTtcbiAgfVxuICByZXR1cm4gdmFsdWUgPT09IHBhcmFtLmRlZmF1bHQ7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLmdldFR5cGUgPSBmdW5jdGlvbiAocGFyYW0pIHtcbiAgdmFyIHR5cGUgPSBwYXJhbS50eXBlO1xuICB2YXIgZm9ybWF0ID0gcGFyYW0uZm9ybWF0O1xuICB2YXIgaXNBcnJheSA9IGZhbHNlO1xuICB2YXIgc3RyO1xuXG4gIGlmICh0eXBlID09PSAnaW50ZWdlcicgJiYgZm9ybWF0ID09PSAnaW50MzInKSB7XG4gICAgc3RyID0gJ2ludGVnZXInO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdpbnRlZ2VyJyAmJiBmb3JtYXQgPT09ICdpbnQ2NCcpIHtcbiAgICBzdHIgPSAnbG9uZyc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2ludGVnZXInKSB7XG4gICAgc3RyID0gJ2ludGVnZXInO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKGZvcm1hdCA9PT0gJ2RhdGUtdGltZScpIHtcbiAgICAgIHN0ciA9ICdkYXRlLXRpbWUnO1xuICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSAnZGF0ZScpIHtcbiAgICAgIHN0ciA9ICdkYXRlJztcbiAgICB9IGVsc2Uge1xuICAgICAgc3RyID0gJ3N0cmluZyc7XG4gICAgfVxuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdudW1iZXInICYmIGZvcm1hdCA9PT0gJ2Zsb2F0Jykge1xuICAgIHN0ciA9ICdmbG9hdCc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ251bWJlcicgJiYgZm9ybWF0ID09PSAnZG91YmxlJykge1xuICAgIHN0ciA9ICdkb3VibGUnO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgc3RyID0gJ2RvdWJsZSc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgc3RyID0gJ2Jvb2xlYW4nO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICdhcnJheScpIHtcbiAgICBpc0FycmF5ID0gdHJ1ZTtcblxuICAgIGlmIChwYXJhbS5pdGVtcykge1xuICAgICAgc3RyID0gdGhpcy5nZXRUeXBlKHBhcmFtLml0ZW1zKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2ZpbGUnKSB7XG4gICAgc3RyID0gJ2ZpbGUnO1xuICB9XG5cbiAgaWYgKHBhcmFtLiRyZWYpIHtcbiAgICBzdHIgPSBoZWxwZXJzLnNpbXBsZVJlZihwYXJhbS4kcmVmKTtcbiAgfVxuXG4gIHZhciBzY2hlbWEgPSBwYXJhbS5zY2hlbWE7XG5cbiAgaWYgKHNjaGVtYSkge1xuICAgIHZhciByZWYgPSBzY2hlbWEuJHJlZjtcblxuICAgIGlmIChyZWYpIHtcbiAgICAgIHJlZiA9IGhlbHBlcnMuc2ltcGxlUmVmKHJlZik7XG5cbiAgICAgIGlmIChpc0FycmF5KSB7XG4gICAgICAgIHJldHVybiBbIHJlZiBdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHJlZjtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSWYgaW5saW5lIHNjaGVtYSwgd2UgYWRkIGl0IG91ciBpbnRlcmFsIGhhc2ggLT4gd2hpY2ggZ2l2ZXMgdXMgaXQncyBJRCAoaW50KVxuICAgICAgaWYoc2NoZW1hLnR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZElubGluZU1vZGVsKHNjaGVtYSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5nZXRUeXBlKHNjaGVtYSk7XG4gICAgfVxuICB9XG4gIGlmIChpc0FycmF5KSB7XG4gICAgcmV0dXJuIFsgc3RyIF07XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHN0cjtcbiAgfVxufTtcblxuLyoqXG4gKiBhZGRzIGFuIGlubGluZSBzY2hlbWEgKG1vZGVsKSB0byBhIGhhc2gsIHdoZXJlIHdlIGNhbiByZWYgaXQgbGF0ZXJcbiAqIEBwYXJhbSB7b2JqZWN0fSBzY2hlbWEgYSBzY2hlbWFcbiAqIEByZXR1cm4ge251bWJlcn0gdGhlIElEIG9mIHRoZSBzY2hlbWEgYmVpbmcgYWRkZWQsIG9yIG51bGxcbiAqKi9cbk9wZXJhdGlvbi5wcm90b3R5cGUuYWRkSW5saW5lTW9kZWwgPSBmdW5jdGlvbiAoc2NoZW1hKSB7XG4gIHZhciBsZW4gPSB0aGlzLmlubGluZU1vZGVscy5sZW5ndGg7XG4gIHZhciBtb2RlbCA9IHRoaXMucmVzb2x2ZU1vZGVsKHNjaGVtYSwge30pO1xuICBpZihtb2RlbCkge1xuICAgIHRoaXMuaW5saW5lTW9kZWxzLnB1c2gobW9kZWwpO1xuICAgIHJldHVybiAnSW5saW5lIE1vZGVsICcrbGVuOyAvLyByZXR1cm4gc3RyaW5nIHJlZiBvZiB0aGUgaW5saW5lIG1vZGVsICh1c2VkIHdpdGggI2dldElubGluZU1vZGVsKVxuICB9XG4gIHJldHVybiBudWxsOyAvLyByZXBvcnQgZXJyb3JzP1xufTtcblxuLyoqXG4gKiBnZXRzIHRoZSBpbnRlcm5hbCByZWYgdG8gYW4gaW5saW5lIG1vZGVsXG4gKiBAcGFyYW0ge3N0cmluZ30gaW5saW5lX3N0ciBhIHN0cmluZyByZWZlcmVuY2UgdG8gYW4gaW5saW5lIG1vZGVsXG4gKiBAcmV0dXJuIHtNb2RlbH0gdGhlIG1vZGVsIGJlaW5nIHJlZmVyZW5jZWQuIE9yIG51bGxcbiAqKi9cbk9wZXJhdGlvbi5wcm90b3R5cGUuZ2V0SW5saW5lTW9kZWwgPSBmdW5jdGlvbihpbmxpbmVTdHIpIHtcbiAgaWYoL15JbmxpbmUgTW9kZWwgXFxkKyQvLnRlc3QoaW5saW5lU3RyKSkge1xuICAgIHZhciBpZCA9IHBhcnNlSW50KGlubGluZVN0ci5zdWJzdHIoJ0lubGluZSBNb2RlbCcubGVuZ3RoKS50cmltKCksMTApOyAvL1xuICAgIHZhciBtb2RlbCA9IHRoaXMuaW5saW5lTW9kZWxzW2lkXTtcbiAgICByZXR1cm4gbW9kZWw7XG4gIH1cbiAgLy8gSSdtIHJldHVybmluZyBudWxsIGhlcmUsIHNob3VsZCBJIHJhdGhlciB0aHJvdyBhbiBlcnJvcj9cbiAgcmV0dXJuIG51bGw7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLnJlc29sdmVNb2RlbCA9IGZ1bmN0aW9uIChzY2hlbWEsIGRlZmluaXRpb25zKSB7XG4gIGlmICh0eXBlb2Ygc2NoZW1hLiRyZWYgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgdmFyIHJlZiA9IHNjaGVtYS4kcmVmO1xuXG4gICAgaWYgKHJlZi5pbmRleE9mKCcjL2RlZmluaXRpb25zLycpID09PSAwKSB7XG4gICAgICByZWYgPSByZWYuc3Vic3RyaW5nKCcjL2RlZmluaXRpb25zLycubGVuZ3RoKTtcbiAgICB9XG5cbiAgICBpZiAoZGVmaW5pdGlvbnNbcmVmXSkge1xuICAgICAgcmV0dXJuIG5ldyBNb2RlbChyZWYsIGRlZmluaXRpb25zW3JlZl0sIHRoaXMubW9kZWxzLCB0aGlzLnBhcmVudC5tb2RlbFByb3BlcnR5TWFjcm8pO1xuICAgIH1cbiAgLy8gc2NoZW1hIG11c3QgYXQgbGVhc3QgYmUgYW4gb2JqZWN0IHRvIGdldCByZXNvbHZlZCB0byBhbiBpbmxpbmUgTW9kZWxcbiAgfSBlbHNlIGlmIChzY2hlbWEgJiYgdHlwZW9mIHNjaGVtYSA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgICAgIChzY2hlbWEudHlwZSA9PT0gJ29iamVjdCcgfHwgXy5pc1VuZGVmaW5lZChzY2hlbWEudHlwZSkpKSB7XG4gICAgcmV0dXJuIG5ldyBNb2RlbCh1bmRlZmluZWQsIHNjaGVtYSwgdGhpcy5tb2RlbHMsIHRoaXMucGFyZW50Lm1vZGVsUHJvcGVydHlNYWNybyk7XG4gIH1cblxuICByZXR1cm4gbnVsbDtcbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUuaGVscCA9IGZ1bmN0aW9uIChkb250UHJpbnQpIHtcbiAgdmFyIG91dCA9IHRoaXMubmlja25hbWUgKyAnOiAnICsgdGhpcy5zdW1tYXJ5ICsgJ1xcbic7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLnBhcmFtZXRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFyYW0gPSB0aGlzLnBhcmFtZXRlcnNbaV07XG4gICAgdmFyIHR5cGVJbmZvID0gcGFyYW0uc2lnbmF0dXJlO1xuXG4gICAgb3V0ICs9ICdcXG4gICogJyArIHBhcmFtLm5hbWUgKyAnICgnICsgdHlwZUluZm8gKyAnKTogJyArIHBhcmFtLmRlc2NyaXB0aW9uO1xuICB9XG5cbiAgaWYgKHR5cGVvZiBkb250UHJpbnQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgaGVscGVycy5sb2cob3V0KTtcbiAgfVxuXG4gIHJldHVybiBvdXQ7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLmdldE1vZGVsU2lnbmF0dXJlID0gZnVuY3Rpb24gKHR5cGUsIGRlZmluaXRpb25zKSB7XG4gIHZhciBpc1ByaW1pdGl2ZSwgbGlzdFR5cGU7XG5cbiAgaWYgKHR5cGUgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgIGxpc3RUeXBlID0gdHJ1ZTtcbiAgICB0eXBlID0gdHlwZVswXTtcbiAgfVxuXG4gIC8vIENvbnZlcnQgdW5kZWZpbmVkIHRvIHN0cmluZyBvZiAndW5kZWZpbmVkJ1xuICBpZiAodHlwZW9mIHR5cGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdHlwZSA9ICd1bmRlZmluZWQnO1xuICAgIGlzUHJpbWl0aXZlID0gdHJ1ZTtcblxuICB9IGVsc2UgaWYgKGRlZmluaXRpb25zW3R5cGVdKXtcbiAgICAvLyBhIG1vZGVsIGRlZiBleGlzdHM/XG4gICAgdHlwZSA9IGRlZmluaXRpb25zW3R5cGVdOyAvKiBNb2RlbCAqL1xuICAgIGlzUHJpbWl0aXZlID0gZmFsc2U7XG5cbiAgfSBlbHNlIGlmICh0aGlzLmdldElubGluZU1vZGVsKHR5cGUpKSB7XG4gICAgdHlwZSA9IHRoaXMuZ2V0SW5saW5lTW9kZWwodHlwZSk7IC8qIE1vZGVsICovXG4gICAgaXNQcmltaXRpdmUgPSBmYWxzZTtcblxuICB9IGVsc2Uge1xuICAgIC8vIFdlIGRlZmF1bHQgdG8gcHJpbWl0aXZlXG4gICAgaXNQcmltaXRpdmUgPSB0cnVlO1xuICB9XG5cbiAgaWYgKGlzUHJpbWl0aXZlKSB7XG4gICAgaWYgKGxpc3RUeXBlKSB7XG4gICAgICByZXR1cm4gJ0FycmF5WycgKyB0eXBlICsgJ10nO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdHlwZS50b1N0cmluZygpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAobGlzdFR5cGUpIHtcbiAgICAgIHJldHVybiAnQXJyYXlbJyArIHR5cGUuZ2V0TW9ja1NpZ25hdHVyZSgpICsgJ10nO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdHlwZS5nZXRNb2NrU2lnbmF0dXJlKCk7XG4gICAgfVxuICB9XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLnN1cHBvcnRIZWFkZXJQYXJhbXMgPSBmdW5jdGlvbiAoKSB7XG4gIHJldHVybiB0cnVlO1xufTtcblxuT3BlcmF0aW9uLnByb3RvdHlwZS5zdXBwb3J0ZWRTdWJtaXRNZXRob2RzID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5wYXJlbnQuc3VwcG9ydGVkU3VibWl0TWV0aG9kcztcbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUuZ2V0SGVhZGVyUGFyYW1zID0gZnVuY3Rpb24gKGFyZ3MpIHtcbiAgdmFyIGhlYWRlcnMgPSB0aGlzLnNldENvbnRlbnRUeXBlcyhhcmdzLCB7fSk7XG4gIHZhciBoZWFkZXJQYXJhbXNCeUxvd2VyQ2FzZSA9IHt9O1xuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5wYXJhbWV0ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHBhcmFtID0gdGhpcy5wYXJhbWV0ZXJzW2ldO1xuXG4gICAgaWYgKHBhcmFtLmluID09PSAnaGVhZGVyJykge1xuICAgICAgaGVhZGVyUGFyYW1zQnlMb3dlckNhc2VbcGFyYW0ubmFtZS50b0xvd2VyQ2FzZSgpXSA9IHBhcmFtO1xuICAgIH1cbiAgfVxuXG4gIGZvciAodmFyIGFyZyBpbiBhcmdzKSB7XG4gICAgdmFyIGhlYWRlclBhcmFtID0gaGVhZGVyUGFyYW1zQnlMb3dlckNhc2VbYXJnLnRvTG93ZXJDYXNlKCldO1xuICAgIGlmICh0eXBlb2YgaGVhZGVyUGFyYW0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB2YXIgdmFsdWUgPSBhcmdzW2FyZ107XG5cbiAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICB9XG5cbiAgICAgIGhlYWRlcnNbaGVhZGVyUGFyYW0ubmFtZV0gPSB2YWx1ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gaGVhZGVycztcbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUudXJsaWZ5ID0gZnVuY3Rpb24gKGFyZ3MsIG1hc2tQYXNzd29yZHMpIHtcbiAgdmFyIGZvcm1QYXJhbXMgPSB7fTtcbiAgdmFyIHJlcXVlc3RVcmwgPSB0aGlzLnBhdGgucmVwbGFjZSgvIy4qLywgJycpOyAvLyByZW1vdmUgVVJMIGZyYWdtZW50XG4gIHZhciBxdWVyeXN0cmluZyA9ICcnOyAvLyBncmFiIHBhcmFtcyBmcm9tIHRoZSBhcmdzLCBidWlsZCB0aGUgcXVlcnlzdHJpbmcgYWxvbmcgdGhlIHdheVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5wYXJhbWV0ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHBhcmFtID0gdGhpcy5wYXJhbWV0ZXJzW2ldO1xuXG4gICAgaWYgKHR5cGVvZiBhcmdzW3BhcmFtLm5hbWVdICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdmFyIGlzUGFzc3dvcmQ7XG4gICAgICBpZihwYXJhbS50eXBlID09PSAnc3RyaW5nJyAmJiBwYXJhbS5mb3JtYXQgPT09ICdwYXNzd29yZCcgJiYgbWFza1Bhc3N3b3Jkcykge1xuICAgICAgICBpc1Bhc3N3b3JkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHBhcmFtLmluID09PSAncGF0aCcpIHtcbiAgICAgICAgdmFyIHJlZyA9IG5ldyBSZWdFeHAoJ1xceycgKyBwYXJhbS5uYW1lICsgJ1xcfScsICdnaScpO1xuICAgICAgICB2YXIgdmFsdWUgPSBhcmdzW3BhcmFtLm5hbWVdO1xuXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgIHZhbHVlID0gdGhpcy5lbmNvZGVQYXRoQ29sbGVjdGlvbihwYXJhbS5jb2xsZWN0aW9uRm9ybWF0LCBwYXJhbS5uYW1lLCB2YWx1ZSwgaXNQYXNzd29yZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYoKHR5cGVvZihwYXJhbVsneC1lc2NhcGUnXSkgPT09ICd1bmRlZmluZWQnKSB8fCAocGFyYW1bJ3gtZXNjYXBlJ10gPT09IHRydWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMuZW5jb2RlUGF0aFBhcmFtKHZhbHVlLCBpc1Bhc3N3b3JkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXF1ZXN0VXJsID0gcmVxdWVzdFVybC5yZXBsYWNlKHJlZywgdmFsdWUpO1xuICAgICAgfSBlbHNlIGlmIChwYXJhbS5pbiA9PT0gJ3F1ZXJ5JyAmJiB0eXBlb2YgYXJnc1twYXJhbS5uYW1lXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgaWYgKHF1ZXJ5c3RyaW5nID09PSAnJyAmJiByZXF1ZXN0VXJsLmluZGV4T2YoJz8nKSA8IDApIHtcbiAgICAgICAgICBxdWVyeXN0cmluZyArPSAnPyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcXVlcnlzdHJpbmcgKz0gJyYnO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBwYXJhbS5jb2xsZWN0aW9uRm9ybWF0ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgIHZhciBxcCA9IGFyZ3NbcGFyYW0ubmFtZV07XG5cbiAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShxcCkpIHtcbiAgICAgICAgICAgIHF1ZXJ5c3RyaW5nICs9IHRoaXMuZW5jb2RlUXVlcnlDb2xsZWN0aW9uKHBhcmFtLmNvbGxlY3Rpb25Gb3JtYXQsIHBhcmFtLm5hbWUsIHFwLCBpc1Bhc3N3b3JkKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcXVlcnlzdHJpbmcgKz0gdGhpcy5lbmNvZGVRdWVyeUtleShwYXJhbS5uYW1lKSArICc9JyArIHRoaXMuZW5jb2RlUXVlcnlQYXJhbShhcmdzW3BhcmFtLm5hbWVdLCBpc1Bhc3N3b3JkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcXVlcnlzdHJpbmcgKz0gdGhpcy5lbmNvZGVRdWVyeUtleShwYXJhbS5uYW1lKSArICc9JyArIHRoaXMuZW5jb2RlUXVlcnlQYXJhbShhcmdzW3BhcmFtLm5hbWVdLCBpc1Bhc3N3b3JkKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChwYXJhbS5pbiA9PT0gJ2Zvcm1EYXRhJykge1xuICAgICAgICBmb3JtUGFyYW1zW3BhcmFtLm5hbWVdID0gYXJnc1twYXJhbS5uYW1lXTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYocGFyYW0uaW4gPT09ICdxdWVyeScgJiYgdHlwZW9mIGFyZ3NbcGFyYW0ubmFtZV0gPT09ICd1bmRlZmluZWQnICYmIHBhcmFtLmFsbG93RW1wdHlWYWx1ZSA9PT0gdHJ1ZSkge1xuICAgICAgaWYgKHF1ZXJ5c3RyaW5nID09PSAnJyAmJiByZXF1ZXN0VXJsLmluZGV4T2YoJz8nKSA8IDApIHtcbiAgICAgICAgcXVlcnlzdHJpbmcgKz0gJz8nO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcXVlcnlzdHJpbmcgKz0gJyYnO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIHBhcmFtLmNvbGxlY3Rpb25Gb3JtYXQgIT09ICd1bmRlZmluZWQnIHx8IHBhcmFtLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgdmFyIHFwO1xuICAgICAgICB2YXIgY29sbGVjdGlvbkZvcm1hdCA9IHBhcmFtLmNvbGxlY3Rpb25Gb3JtYXQgfHwgJ211bHRpJztcblxuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShxcCkpIHtcbiAgICAgICAgICBxdWVyeXN0cmluZyArPSB0aGlzLmVuY29kZVF1ZXJ5Q29sbGVjdGlvbihjb2xsZWN0aW9uRm9ybWF0LCBwYXJhbS5uYW1lLCBxcCwgaXNQYXNzd29yZCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcXVlcnlzdHJpbmcgKz0gdGhpcy5lbmNvZGVRdWVyeUNvbGxlY3Rpb24oY29sbGVjdGlvbkZvcm1hdCwgcGFyYW0ubmFtZSwgW3FwXSwgaXNQYXNzd29yZCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXJ5c3RyaW5nICs9IHRoaXMuZW5jb2RlUXVlcnlLZXkocGFyYW0ubmFtZSkgKyAnPScgKyB0aGlzLmVuY29kZVF1ZXJ5UGFyYW0oJycsIGlzUGFzc3dvcmQpO1xuICAgICAgfVxuXG4gICAgfVxuICB9XG4gIHZhciB1cmwgPSB0aGlzLnNjaGVtZSArICc6Ly8nICsgdGhpcy5ob3N0O1xuXG4gIGlmICh0aGlzLmJhc2VQYXRoICE9PSAnLycpIHtcbiAgICB1cmwgKz0gdGhpcy5iYXNlUGF0aDtcbiAgfVxuICByZXR1cm4gdXJsICsgcmVxdWVzdFVybCArIHF1ZXJ5c3RyaW5nO1xufTtcblxuT3BlcmF0aW9uLnByb3RvdHlwZS5nZXRNaXNzaW5nUGFyYW1zID0gZnVuY3Rpb24gKGFyZ3MpIHtcbiAgdmFyIG1pc3NpbmdQYXJhbXMgPSBbXTsgLy8gY2hlY2sgcmVxdWlyZWQgcGFyYW1zLCB0cmFjayB0aGUgb25lcyB0aGF0IGFyZSBtaXNzaW5nXG4gIHZhciBpO1xuXG4gIGZvciAoaSA9IDA7IGkgPCB0aGlzLnBhcmFtZXRlcnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgcGFyYW0gPSB0aGlzLnBhcmFtZXRlcnNbaV07XG5cbiAgICBpZiAocGFyYW0ucmVxdWlyZWQgPT09IHRydWUpIHtcbiAgICAgIGlmICh0eXBlb2YgYXJnc1twYXJhbS5uYW1lXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgbWlzc2luZ1BhcmFtcyA9IHBhcmFtLm5hbWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG1pc3NpbmdQYXJhbXM7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLmdldEJvZHkgPSBmdW5jdGlvbiAoaGVhZGVycywgYXJncywgb3B0cykge1xuICB2YXIgZm9ybVBhcmFtcyA9IHt9LCBoYXNGb3JtUGFyYW1zLCBwYXJhbSwgYm9keSwga2V5LCB2YWx1ZSwgaGFzQm9keSA9IGZhbHNlO1xuXG4gIC8vIGxvb2sgYXQgZWFjaCBwYXJhbSBhbmQgcHV0IGZvcm0gcGFyYW1zIGluIGFuIG9iamVjdFxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMucGFyYW1ldGVycy5sZW5ndGg7IGkrKykge1xuICAgIHBhcmFtID0gdGhpcy5wYXJhbWV0ZXJzW2ldO1xuICAgIGlmICh0eXBlb2YgYXJnc1twYXJhbS5uYW1lXSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHZhciBpc1Bhc3N3b3JkO1xuICAgICAgaWYocGFyYW0udHlwZSA9PT0gJ3N0cmluZycgJiYgcGFyYW0uZm9ybWF0ID09PSAncGFzc3dvcmQnKSB7XG4gICAgICAgIGlzUGFzc3dvcmQgPSAncGFzc3dvcmQnO1xuICAgICAgfVxuICAgICAgaWYgKHBhcmFtLmluID09PSAnYm9keScpIHtcbiAgICAgICAgYm9keSA9IGFyZ3NbcGFyYW0ubmFtZV07XG4gICAgICB9IGVsc2UgaWYgKHBhcmFtLmluID09PSAnZm9ybURhdGEnKSB7XG4gICAgICAgIGZvcm1QYXJhbXNbcGFyYW0ubmFtZV0gPSB7XG4gICAgICAgICAgcGFyYW06IHBhcmFtLFxuICAgICAgICAgIHZhbHVlOiBhcmdzW3BhcmFtLm5hbWVdLFxuICAgICAgICAgIHBhc3N3b3JkOiBpc1Bhc3N3b3JkXG4gICAgICAgIH07XG4gICAgICAgIGhhc0Zvcm1QYXJhbXMgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIGlmKHBhcmFtLmluID09PSAnYm9keScpIHtcbiAgICAgICAgaGFzQm9keSA9IHRydWU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gaWYgYm9keSBpcyBudWxsIGFuZCBoYXNCb2R5IGlzIHRydWUsIEFORCBhIEpTT04gYm9keSBpcyByZXF1ZXN0ZWQsIHNlbmQgZW1wdHkge31cbiAgaWYoaGFzQm9keSAmJiB0eXBlb2YgYm9keSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICB2YXIgY29udGVudFR5cGUgPSBoZWFkZXJzWydDb250ZW50LVR5cGUnXTtcbiAgICBpZihjb250ZW50VHlwZSAmJiBjb250ZW50VHlwZS5pbmRleE9mKCdhcHBsaWNhdGlvbi9qc29uJykgPT09IDApIHtcbiAgICAgIGJvZHkgPSAne30nO1xuICAgIH1cbiAgfVxuXG4gIHZhciBpc011bHRpUGFydCA9IGZhbHNlO1xuICBpZihoZWFkZXJzWydDb250ZW50LVR5cGUnXSAmJiBoZWFkZXJzWydDb250ZW50LVR5cGUnXS5pbmRleE9mKCdtdWx0aXBhcnQvZm9ybS1kYXRhJykgPj0gMCkge1xuICAgIGlzTXVsdGlQYXJ0ID0gdHJ1ZTtcbiAgfVxuXG4gIC8vIGhhbmRsZSBmb3JtIHBhcmFtc1xuICBpZiAoaGFzRm9ybVBhcmFtcyAmJiAhaXNNdWx0aVBhcnQpIHtcbiAgICB2YXIgZW5jb2RlZCA9ICcnO1xuXG4gICAgZm9yIChrZXkgaW4gZm9ybVBhcmFtcykge1xuICAgICAgcGFyYW0gPSBmb3JtUGFyYW1zW2tleV0ucGFyYW07XG4gICAgICB2YWx1ZSA9IGZvcm1QYXJhbXNba2V5XS52YWx1ZTtcbiAgICAgIHZhciBwYXNzd29yZDtcblxuICAgICAgaWYob3B0cyAmJiBvcHRzLm1hc2tQYXNzd29yZHMpIHtcbiAgICAgICAgcGFzc3dvcmQgPSBmb3JtUGFyYW1zW2tleV0ucGFzc3dvcmQ7XG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgICAgICAgIGlmIChlbmNvZGVkICE9PSAnJykge1xuICAgICAgICAgICAgZW5jb2RlZCArPSAnJic7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVuY29kZWQgKz0gdGhpcy5lbmNvZGVRdWVyeUNvbGxlY3Rpb24ocGFyYW0uY29sbGVjdGlvbkZvcm1hdCwga2V5LCB2YWx1ZSwgcGFzc3dvcmQpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgIGlmIChlbmNvZGVkICE9PSAnJykge1xuICAgICAgICAgICAgZW5jb2RlZCArPSAnJic7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZW5jb2RlZCArPSBlbmNvZGVVUklDb21wb25lbnQoa2V5KSArICc9JyArIG1hc2soZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKSwgcGFzc3dvcmQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgYm9keSA9IGVuY29kZWQ7XG4gIH0gZWxzZSBpZiAoaXNNdWx0aVBhcnQpIHtcbiAgICB2YXIgYm9keVBhcmFtO1xuICAgIGlmICh0eXBlb2YgRm9ybURhdGEgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGJvZHlQYXJhbSA9IG5ldyBGb3JtRGF0YSgpO1xuXG4gICAgICBib2R5UGFyYW0udHlwZSA9ICdmb3JtRGF0YSc7XG5cbiAgICAgIGZvciAoa2V5IGluIGZvcm1QYXJhbXMpIHtcbiAgICAgICAgcGFyYW0gPSBmb3JtUGFyYW1zW2tleV0ucGFyYW07XG4gICAgICAgIHZhbHVlID0gYXJnc1trZXldO1xuXG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgaWYoe30udG9TdHJpbmcuYXBwbHkodmFsdWUpID09PSAnW29iamVjdCBGaWxlXScpIHtcbiAgICAgICAgICAgIGJvZHlQYXJhbS5hcHBlbmQoa2V5LCB2YWx1ZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsc2UgaWYgKHZhbHVlLnR5cGUgPT09ICdmaWxlJyAmJiB2YWx1ZS52YWx1ZSkge1xuICAgICAgICAgICAgYm9keVBhcmFtLmFwcGVuZChrZXksIHZhbHVlLnZhbHVlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICAgICAgICAgIGlmKHBhcmFtLmNvbGxlY3Rpb25Gb3JtYXQgPT09ICdtdWx0aScpIHtcbiAgICAgICAgICAgICAgICBib2R5UGFyYW0uZGVsZXRlKGtleSk7XG4gICAgICAgICAgICAgICAgZm9yKHZhciB2IGluIHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICBib2R5UGFyYW0uYXBwZW5kKGtleSwgdmFsdWVbdl0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBib2R5UGFyYW0uYXBwZW5kKGtleSwgdGhpcy5lbmNvZGVRdWVyeUNvbGxlY3Rpb24ocGFyYW0uY29sbGVjdGlvbkZvcm1hdCwga2V5LCB2YWx1ZSkuc3BsaXQoJz0nKS5zbGljZSgxKS5qb2luKCc9JykpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgYm9keVBhcmFtLmFwcGVuZChrZXksIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGJvZHkgPSBib2R5UGFyYW07XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgYm9keVBhcmFtID0ge307XG4gICAgICBmb3IgKGtleSBpbiBmb3JtUGFyYW1zKSB7XG4gICAgICAgIHZhbHVlID0gYXJnc1trZXldO1xuICAgICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgICB2YXIgZGVsaW1ldGVyO1xuICAgICAgICAgIHZhciBmb3JtYXQgPSBwYXJhbS5jb2xsZWN0aW9uRm9ybWF0IHx8ICdtdWx0aSc7XG4gICAgICAgICAgaWYoZm9ybWF0ID09PSAnc3N2Jykge1xuICAgICAgICAgICAgZGVsaW1ldGVyID0gJyAnO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmKGZvcm1hdCA9PT0gJ3BpcGVzJykge1xuICAgICAgICAgICAgZGVsaW1ldGVyID0gJ3wnO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmKGZvcm1hdCA9PT0gJ3RzdicpIHtcbiAgICAgICAgICAgIGRlbGltZXRlciA9ICdcXHQnO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIGlmKGZvcm1hdCA9PT0gJ211bHRpJykge1xuICAgICAgICAgICAgYm9keVBhcmFtW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRlbGltZXRlciA9ICcsJztcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFyIGRhdGE7XG4gICAgICAgICAgdmFsdWUuZm9yRWFjaChmdW5jdGlvbih2KSB7XG4gICAgICAgICAgICBpZihkYXRhKSB7XG4gICAgICAgICAgICAgIGRhdGEgKz0gZGVsaW1ldGVyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgIGRhdGEgPSAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRhdGEgKz0gdjtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBib2R5UGFyYW1ba2V5XSA9IGRhdGE7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgYm9keVBhcmFtW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgYm9keSA9IGJvZHlQYXJhbTtcbiAgICB9XG4gICAgaGVhZGVyc1snQ29udGVudC1UeXBlJ10gPSAnbXVsdGlwYXJ0L2Zvcm0tZGF0YSc7XG4gIH1cblxuICByZXR1cm4gYm9keTtcbn07XG5cbi8qKlxuICogZ2V0cyBzYW1wbGUgcmVzcG9uc2UgZm9yIGEgc2luZ2xlIG9wZXJhdGlvblxuICoqL1xuT3BlcmF0aW9uLnByb3RvdHlwZS5nZXRNb2RlbFNhbXBsZUpTT04gPSBmdW5jdGlvbiAodHlwZSwgbW9kZWxzKSB7XG4gIHZhciBsaXN0VHlwZSwgc2FtcGxlSnNvbiwgaW5uZXJUeXBlO1xuICBtb2RlbHMgPSBtb2RlbHMgfHwge307XG5cbiAgbGlzdFR5cGUgPSAodHlwZSBpbnN0YW5jZW9mIEFycmF5KTtcbiAgaW5uZXJUeXBlID0gbGlzdFR5cGUgPyB0eXBlWzBdIDogdHlwZTtcblxuICBpZihtb2RlbHNbaW5uZXJUeXBlXSkge1xuICAgIHNhbXBsZUpzb24gPSBtb2RlbHNbaW5uZXJUeXBlXS5jcmVhdGVKU09OU2FtcGxlKCk7XG4gIH0gZWxzZSBpZiAodGhpcy5nZXRJbmxpbmVNb2RlbChpbm5lclR5cGUpKXtcbiAgICBzYW1wbGVKc29uID0gdGhpcy5nZXRJbmxpbmVNb2RlbChpbm5lclR5cGUpLmNyZWF0ZUpTT05TYW1wbGUoKTsgLy8gbWF5IHJldHVybiBudWxsLCBpZiB0eXBlIGlzbid0IGNvcnJlY3RcbiAgfVxuXG5cbiAgaWYgKHNhbXBsZUpzb24pIHtcbiAgICBzYW1wbGVKc29uID0gbGlzdFR5cGUgPyBbc2FtcGxlSnNvbl0gOiBzYW1wbGVKc29uO1xuXG4gICAgaWYgKHR5cGVvZiBzYW1wbGVKc29uID09PSAnc3RyaW5nJykge1xuICAgICAgcmV0dXJuIHNhbXBsZUpzb247XG4gICAgfSBlbHNlIGlmIChfLmlzT2JqZWN0KHNhbXBsZUpzb24pKSB7XG4gICAgICB2YXIgdCA9IHNhbXBsZUpzb247XG5cbiAgICAgIGlmIChzYW1wbGVKc29uIGluc3RhbmNlb2YgQXJyYXkgJiYgc2FtcGxlSnNvbi5sZW5ndGggPiAwKSB7XG4gICAgICAgIHQgPSBzYW1wbGVKc29uWzBdO1xuICAgICAgfVxuXG4gICAgICBpZiAodC5ub2RlTmFtZSAmJiB0eXBlb2YgdCA9PT0gJ05vZGUnKSB7XG4gICAgICAgIHZhciB4bWxTdHJpbmcgPSBuZXcgWE1MU2VyaWFsaXplcigpLnNlcmlhbGl6ZVRvU3RyaW5nKHQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1hdFhtbCh4bWxTdHJpbmcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHNhbXBsZUpzb24sIG51bGwsIDIpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gc2FtcGxlSnNvbjtcbiAgICB9XG4gIH1cbn07XG5cbi8qKlxuICogbGVnYWN5IGJpbmRpbmdcbiAqKi9cbk9wZXJhdGlvbi5wcm90b3R5cGUuZG8gPSBmdW5jdGlvbiAoYXJncywgb3B0cywgY2FsbGJhY2ssIGVycm9yLCBwYXJlbnQpIHtcbiAgcmV0dXJuIHRoaXMuZXhlY3V0ZShhcmdzLCBvcHRzLCBjYWxsYmFjaywgZXJyb3IsIHBhcmVudCk7XG59O1xuXG4vKipcbiAqIGV4ZWN1dGVzIGFuIG9wZXJhdGlvblxuICoqL1xuT3BlcmF0aW9uLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKGFyZzEsIGFyZzIsIGFyZzMsIGFyZzQsIHBhcmVudCkge1xuICB2YXIgYXJncyA9IGFyZzEgfHwge307XG4gIHZhciBvcHRzID0ge30sIHN1Y2Nlc3MsIGVycm9yLCBkZWZlcnJlZCwgdGltZW91dDtcblxuICBpZiAoXy5pc09iamVjdChhcmcyKSkge1xuICAgIG9wdHMgPSBhcmcyO1xuICAgIHN1Y2Nlc3MgPSBhcmczO1xuICAgIGVycm9yID0gYXJnNDtcbiAgfVxuXG4gIHRpbWVvdXQgPSB0eXBlb2Ygb3B0cy50aW1lb3V0ICE9PSAndW5kZWZpbmVkJyA/IG9wdHMudGltZW91dCA6IHRoaXMudGltZW91dDtcblxuICBpZih0aGlzLmNsaWVudCkge1xuICAgIG9wdHMuY2xpZW50ID0gdGhpcy5jbGllbnQ7XG4gIH1cblxuICBpZih0aGlzLnJlcXVlc3RBZ2VudCkge1xuICAgIG9wdHMucmVxdWVzdEFnZW50ID0gdGhpcy5yZXF1ZXN0QWdlbnQ7XG4gIH1cblxuICAvLyBhZGQgdGhlIHJlcXVlc3QgaW50ZXJjZXB0b3IgZnJvbSBwYXJlbnQsIGlmIG5vbmUgc2VudCBmcm9tIGNsaWVudFxuICBpZighb3B0cy5yZXF1ZXN0SW50ZXJjZXB0b3IgJiYgdGhpcy5yZXF1ZXN0SW50ZXJjZXB0b3IgKSB7XG4gICAgb3B0cy5yZXF1ZXN0SW50ZXJjZXB0b3IgPSB0aGlzLnJlcXVlc3RJbnRlcmNlcHRvciA7XG4gIH1cblxuICBpZighb3B0cy5yZXNwb25zZUludGVyY2VwdG9yICYmIHRoaXMucmVzcG9uc2VJbnRlcmNlcHRvcikge1xuICAgIG9wdHMucmVzcG9uc2VJbnRlcmNlcHRvciA9IHRoaXMucmVzcG9uc2VJbnRlcmNlcHRvcjtcbiAgfVxuXG4gIGlmICh0eXBlb2YgYXJnMiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHN1Y2Nlc3MgPSBhcmcyO1xuICAgIGVycm9yID0gYXJnMztcbiAgfVxuXG4gIGlmICh0aGlzLnBhcmVudC51c2VQcm9taXNlKSB7XG4gICAgZGVmZXJyZWQgPSBRLmRlZmVyKCk7XG4gIH0gZWxzZSB7XG4gICAgc3VjY2VzcyA9IChzdWNjZXNzIHx8IHRoaXMucGFyZW50LmRlZmF1bHRTdWNjZXNzQ2FsbGJhY2sgfHwgaGVscGVycy5sb2cpO1xuICAgIGVycm9yID0gKGVycm9yIHx8IHRoaXMucGFyZW50LmRlZmF1bHRFcnJvckNhbGxiYWNrIHx8IGhlbHBlcnMubG9nKTtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygb3B0cy51c2VKUXVlcnkgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgb3B0cy51c2VKUXVlcnkgPSB0aGlzLnVzZUpRdWVyeTtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygb3B0cy5qcXVlcnlBamF4Q2FjaGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgb3B0cy5qcXVlcnlBamF4Q2FjaGUgPSB0aGlzLmpxdWVyeUFqYXhDYWNoZTtcbiAgfVxuXG4gIGlmICh0eXBlb2Ygb3B0cy5lbmFibGVDb29raWVzID09PSAndW5kZWZpbmVkJykge1xuICAgIG9wdHMuZW5hYmxlQ29va2llcyA9IHRoaXMuZW5hYmxlQ29va2llcztcbiAgfVxuXG4gIHZhciBtaXNzaW5nUGFyYW1zID0gdGhpcy5nZXRNaXNzaW5nUGFyYW1zKGFyZ3MpO1xuXG4gIGlmIChtaXNzaW5nUGFyYW1zLmxlbmd0aCA+IDApIHtcbiAgICB2YXIgbWVzc2FnZSA9ICdtaXNzaW5nIHJlcXVpcmVkIHBhcmFtczogJyArIG1pc3NpbmdQYXJhbXM7XG5cbiAgICBoZWxwZXJzLmZhaWwobWVzc2FnZSk7XG5cbiAgICBpZiAodGhpcy5wYXJlbnQudXNlUHJvbWlzZSkge1xuICAgICAgZGVmZXJyZWQucmVqZWN0KG1lc3NhZ2UpO1xuICAgICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVycm9yKG1lc3NhZ2UsIHBhcmVudCk7XG4gICAgICByZXR1cm4ge307XG4gICAgfVxuICB9XG5cbiAgdmFyIGFsbEhlYWRlcnMgPSB0aGlzLmdldEhlYWRlclBhcmFtcyhhcmdzKTtcbiAgdmFyIGNvbnRlbnRUeXBlSGVhZGVycyA9IHRoaXMuc2V0Q29udGVudFR5cGVzKGFyZ3MsIG9wdHMpO1xuICB2YXIgaGVhZGVycyA9IHt9LCBhdHRybmFtZTtcblxuICBmb3IgKGF0dHJuYW1lIGluIGFsbEhlYWRlcnMpIHsgaGVhZGVyc1thdHRybmFtZV0gPSBhbGxIZWFkZXJzW2F0dHJuYW1lXTsgfVxuICBmb3IgKGF0dHJuYW1lIGluIGNvbnRlbnRUeXBlSGVhZGVycykgeyBoZWFkZXJzW2F0dHJuYW1lXSA9IGNvbnRlbnRUeXBlSGVhZGVyc1thdHRybmFtZV07IH1cblxuICB2YXIgYm9keSA9IHRoaXMuZ2V0Qm9keShjb250ZW50VHlwZUhlYWRlcnMsIGFyZ3MsIG9wdHMpO1xuICB2YXIgdXJsID0gdGhpcy51cmxpZnkoYXJncywgb3B0cy5tYXNrUGFzc3dvcmRzKTtcblxuICBpZih1cmwuaW5kZXhPZignLntmb3JtYXR9JykgPiAwKSB7XG4gICAgaWYoaGVhZGVycykge1xuICAgICAgdmFyIGZvcm1hdCA9IGhlYWRlcnMuQWNjZXB0IHx8IGhlYWRlcnMuYWNjZXB0O1xuICAgICAgaWYoZm9ybWF0ICYmIGZvcm1hdC5pbmRleE9mKCdqc29uJykgPiAwKSB7XG4gICAgICAgIHVybCA9IHVybC5yZXBsYWNlKCcue2Zvcm1hdH0nLCAnLmpzb24nKTtcbiAgICAgIH1cbiAgICAgIGVsc2UgaWYoZm9ybWF0ICYmIGZvcm1hdC5pbmRleE9mKCd4bWwnKSA+IDApIHtcbiAgICAgICAgdXJsID0gdXJsLnJlcGxhY2UoJy57Zm9ybWF0fScsICcueG1sJyk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdmFyIG9iaiA9IHtcbiAgICB1cmw6IHVybCxcbiAgICBtZXRob2Q6IHRoaXMubWV0aG9kLnRvVXBwZXJDYXNlKCksXG4gICAgYm9keTogYm9keSxcbiAgICBlbmFibGVDb29raWVzOiBvcHRzLmVuYWJsZUNvb2tpZXMsXG4gICAgdXNlSlF1ZXJ5OiBvcHRzLnVzZUpRdWVyeSxcbiAgICBqcXVlcnlBamF4Q2FjaGU6IG9wdHMuanF1ZXJ5QWpheENhY2hlLFxuICAgIGRlZmVycmVkOiBkZWZlcnJlZCxcbiAgICBoZWFkZXJzOiBoZWFkZXJzLFxuICAgIGNsaWVudEF1dGhvcml6YXRpb25zOiBvcHRzLmNsaWVudEF1dGhvcml6YXRpb25zLFxuICAgIG9wZXJhdGlvbjogdGhpcyxcbiAgICBjb25uZWN0aW9uQWdlbnQ6IHRoaXMuY29ubmVjdGlvbkFnZW50LFxuICAgIG9uOiB7XG4gICAgICByZXNwb25zZTogZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICAgIGlmIChkZWZlcnJlZCkge1xuICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUocmVzcG9uc2UpO1xuICAgICAgICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBzdWNjZXNzKHJlc3BvbnNlLCBwYXJlbnQpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZXJyb3I6IGZ1bmN0aW9uIChyZXNwb25zZSkge1xuICAgICAgICBpZiAoZGVmZXJyZWQpIHtcbiAgICAgICAgICBkZWZlcnJlZC5yZWplY3QocmVzcG9uc2UpO1xuICAgICAgICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBlcnJvcihyZXNwb25zZSwgcGFyZW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICBpZiAodGltZW91dCkge1xuICAgIG9iai50aW1lb3V0ID0gdGltZW91dDtcbiAgfVxuXG4gIHRoaXMuY2xpZW50QXV0aG9yaXphdGlvbnMuYXBwbHkob2JqLCB0aGlzLm9wZXJhdGlvbi5zZWN1cml0eSk7XG4gIGlmIChvcHRzLm1vY2sgPT09IHRydWUpIHtcbiAgICBpZihvcHRzLnJlcXVlc3RJbnRlcmNlcHRvcikge1xuICAgICAgb3B0cy5yZXF1ZXN0SW50ZXJjZXB0b3IuYXBwbHkob2JqKTtcbiAgICB9XG4gICAgcmV0dXJuIG9iajtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbmV3IFN3YWdnZXJIdHRwKCkuZXhlY3V0ZShvYmosIG9wdHMpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBpdGVtQnlQcmlvcml0eShjb2wsIGl0ZW1Qcmlvcml0eSkge1xuXG4gIC8vIE5vIHByaW9yaXRpZXM/IHJldHVybiBmaXJzdC4uLlxuICBpZihfLmlzRW1wdHkoaXRlbVByaW9yaXR5KSkge1xuICAgIHJldHVybiBjb2xbMF07XG4gIH1cblxuICBmb3IgKHZhciBpID0gMCwgbGVuID0gaXRlbVByaW9yaXR5Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgaWYoY29sLmluZGV4T2YoaXRlbVByaW9yaXR5W2ldKSA+IC0xKSB7XG4gICAgICByZXR1cm4gaXRlbVByaW9yaXR5W2ldO1xuICAgIH1cbiAgfVxuXG4gIC8vIE90aGVyd2lzZSByZXR1cm4gZmlyc3RcbiAgcmV0dXJuIGNvbFswXTtcbn1cblxuT3BlcmF0aW9uLnByb3RvdHlwZS5zZXRDb250ZW50VHlwZXMgPSBmdW5jdGlvbiAoYXJncywgb3B0cykge1xuICAvLyBkZWZhdWx0IHR5cGVcbiAgdmFyIGFsbERlZmluZWRQYXJhbXMgPSB0aGlzLnBhcmFtZXRlcnM7XG4gIHZhciBib2R5O1xuICB2YXIgY29uc3VtZXMgPSBhcmdzLnBhcmFtZXRlckNvbnRlbnRUeXBlIHx8IGl0ZW1CeVByaW9yaXR5KHRoaXMuY29uc3VtZXMsIFsnYXBwbGljYXRpb24vanNvbicsICdhcHBsaWNhdGlvbi95YW1sJ10pO1xuICB2YXIgYWNjZXB0cyA9IG9wdHMucmVzcG9uc2VDb250ZW50VHlwZSB8fCBpdGVtQnlQcmlvcml0eSh0aGlzLnByb2R1Y2VzLCBbJ2FwcGxpY2F0aW9uL2pzb24nLCAnYXBwbGljYXRpb24veWFtbCddKTtcbiAgdmFyIGRlZmluZWRGaWxlUGFyYW1zID0gW107XG4gIHZhciBkZWZpbmVkRm9ybVBhcmFtcyA9IFtdO1xuICB2YXIgaGVhZGVycyA9IHt9O1xuICB2YXIgaTtcblxuICAvLyBnZXQgcGFyYW1zIGZyb20gdGhlIG9wZXJhdGlvbiBhbmQgc2V0IHRoZW0gaW4gZGVmaW5lZEZpbGVQYXJhbXMsIGRlZmluZWRGb3JtUGFyYW1zLCBoZWFkZXJzXG4gIGZvciAoaSA9IDA7IGkgPCBhbGxEZWZpbmVkUGFyYW1zLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHBhcmFtID0gYWxsRGVmaW5lZFBhcmFtc1tpXTtcblxuICAgIGlmIChwYXJhbS5pbiA9PT0gJ2Zvcm1EYXRhJykge1xuICAgICAgaWYgKHBhcmFtLnR5cGUgPT09ICdmaWxlJykge1xuICAgICAgICBkZWZpbmVkRmlsZVBhcmFtcy5wdXNoKHBhcmFtKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRlZmluZWRGb3JtUGFyYW1zLnB1c2gocGFyYW0pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAocGFyYW0uaW4gPT09ICdoZWFkZXInICYmIG9wdHMpIHtcbiAgICAgIHZhciBrZXkgPSBwYXJhbS5uYW1lO1xuICAgICAgdmFyIGhlYWRlclZhbHVlID0gb3B0c1twYXJhbS5uYW1lXTtcblxuICAgICAgaWYgKHR5cGVvZiBvcHRzW3BhcmFtLm5hbWVdICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBoZWFkZXJzW2tleV0gPSBoZWFkZXJWYWx1ZTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHBhcmFtLmluID09PSAnYm9keScgJiYgdHlwZW9mIGFyZ3NbcGFyYW0ubmFtZV0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICBib2R5ID0gYXJnc1twYXJhbS5uYW1lXTtcbiAgICB9XG4gIH1cblxuICAvLyBpZiB0aGVyZSdzIGEgYm9keSwgbmVlZCB0byBzZXQgdGhlIGNvbnN1bWVzIGhlYWRlciB2aWEgcmVxdWVzdENvbnRlbnRUeXBlXG4gIHZhciBoYXNCb2R5ID0gYm9keSB8fCBkZWZpbmVkRmlsZVBhcmFtcy5sZW5ndGggfHwgZGVmaW5lZEZvcm1QYXJhbXMubGVuZ3RoO1xuICBpZiAodGhpcy5tZXRob2QgPT09ICdwb3N0JyB8fCB0aGlzLm1ldGhvZCA9PT0gJ3B1dCcgfHwgdGhpcy5tZXRob2QgPT09ICdwYXRjaCcgfHxcbiAgICAgICgodGhpcy5tZXRob2QgPT09ICdkZWxldGUnIHx8IHRoaXMubWV0aG9kID09PSAnZ2V0JykgJiYgaGFzQm9keSkpIHtcbiAgICBpZiAob3B0cy5yZXF1ZXN0Q29udGVudFR5cGUpIHtcbiAgICAgIGNvbnN1bWVzID0gb3B0cy5yZXF1ZXN0Q29udGVudFR5cGU7XG4gICAgfVxuICAgIC8vIGlmIGFueSBmb3JtIHBhcmFtcywgY29udGVudCB0eXBlIG11c3QgYmUgc2V0XG4gICAgaWYgKGRlZmluZWRGb3JtUGFyYW1zLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN1bWVzID0gdW5kZWZpbmVkO1xuICAgICAgaWYgKG9wdHMucmVxdWVzdENvbnRlbnRUeXBlKSB7ICAgICAgICAgICAgIC8vIG92ZXJyaWRlIGlmIHNldFxuICAgICAgICBjb25zdW1lcyA9IG9wdHMucmVxdWVzdENvbnRlbnRUeXBlO1xuICAgICAgfSBlbHNlIGlmIChkZWZpbmVkRmlsZVBhcmFtcy5sZW5ndGggPiAwKSB7IC8vIGlmIGEgZmlsZSwgbXVzdCBiZSBtdWx0aXBhcnQvZm9ybS1kYXRhXG4gICAgICAgIGNvbnN1bWVzID0gJ211bHRpcGFydC9mb3JtLWRhdGEnO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKHRoaXMuY29uc3VtZXMgJiYgdGhpcy5jb25zdW1lcy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgLy8gdXNlIHRoZSBjb25zdW1lcyBzZXR0aW5nXG4gICAgICAgICAgZm9yKHZhciBjIGluIHRoaXMuY29uc3VtZXMpIHtcbiAgICAgICAgICAgIHZhciBjaGsgPSB0aGlzLmNvbnN1bWVzW2NdO1xuICAgICAgICAgICAgaWYoY2hrLmluZGV4T2YoJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcpID09PSAwIHx8IGNoay5pbmRleE9mKCdtdWx0aXBhcnQvZm9ybS1kYXRhJykgPT09IDApIHtcbiAgICAgICAgICAgICAgY29uc3VtZXMgPSBjaGs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZih0eXBlb2YgY29uc3VtZXMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIC8vIGRlZmF1bHQgdG8geC13d3ctZnJvbS11cmxlbmNvZGVkXG4gICAgICAgIGNvbnN1bWVzID0gJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCc7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGVsc2Uge1xuICAgIGNvbnN1bWVzID0gbnVsbDtcbiAgfVxuXG4gIGlmIChjb25zdW1lcyAmJiB0aGlzLmNvbnN1bWVzKSB7XG4gICAgaWYgKHRoaXMuY29uc3VtZXMuaW5kZXhPZihjb25zdW1lcykgPT09IC0xKSB7XG4gICAgICBoZWxwZXJzLmxvZygnc2VydmVyIGRvZXNuXFwndCBjb25zdW1lICcgKyBjb25zdW1lcyArICcsIHRyeSAnICsgSlNPTi5zdHJpbmdpZnkodGhpcy5jb25zdW1lcykpO1xuICAgIH1cbiAgfVxuXG4gIGlmICghdGhpcy5tYXRjaGVzQWNjZXB0KGFjY2VwdHMpKSB7XG4gICAgaGVscGVycy5sb2coJ3NlcnZlciBjYW5cXCd0IHByb2R1Y2UgJyArIGFjY2VwdHMpO1xuICB9XG5cbiAgaWYgKChjb25zdW1lcyAmJiBib2R5ICE9PSAnJykgfHwgKGNvbnN1bWVzID09PSAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJykpIHtcbiAgICBoZWFkZXJzWydDb250ZW50LVR5cGUnXSA9IGNvbnN1bWVzO1xuICB9XG4gIGVsc2UgaWYodGhpcy5jb25zdW1lcyAmJiB0aGlzLmNvbnN1bWVzLmxlbmd0aCA+IDAgJiYgdGhpcy5jb25zdW1lc1swXSA9PT0gJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcpIHtcbiAgICBoZWFkZXJzWydDb250ZW50LVR5cGUnXSA9IHRoaXMuY29uc3VtZXNbMF07XG4gIH1cblxuICBpZiAoYWNjZXB0cykge1xuICAgIGhlYWRlcnMuQWNjZXB0ID0gYWNjZXB0cztcbiAgfVxuXG4gIHJldHVybiBoZWFkZXJzO1xufTtcblxuLyoqXG4gKiBSZXR1cm5zIHRydWUgaWYgdGhlIHJlcXVlc3QgYWNjZXB0cyBoZWFkZXIgbWF0Y2hlcyBhbnl0aGluZyBpbiB0aGlzLnByb2R1Y2VzLlxuICogIElmIHRoaXMucHJvZHVjZXMgY29udGFpbnMgKiAvICosIGlnbm9yZSB0aGUgYWNjZXB0IGhlYWRlci5cbiAqIEBwYXJhbSB7c3RyaW5nPX0gYWNjZXB0cyBUaGUgY2xpZW50IHJlcXVlc3QgYWNjZXB0IGhlYWRlci5cbiAqIEByZXR1cm4ge2Jvb2xlYW59XG4gKi9cbk9wZXJhdGlvbi5wcm90b3R5cGUubWF0Y2hlc0FjY2VwdCA9IGZ1bmN0aW9uKGFjY2VwdHMpIHtcbiAgLy8gbm8gYWNjZXB0cyBvciBwcm9kdWNlcywgbm8gcHJvYmxlbSFcbiAgaWYgKCFhY2NlcHRzIHx8ICF0aGlzLnByb2R1Y2VzKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgcmV0dXJuIHRoaXMucHJvZHVjZXMuaW5kZXhPZihhY2NlcHRzKSAhPT0gLTEgfHwgdGhpcy5wcm9kdWNlcy5pbmRleE9mKCcqLyonKSAhPT0gLTE7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLmFzQ3VybCA9IGZ1bmN0aW9uIChhcmdzMSwgYXJnczIpIHtcbiAgdmFyIG9wdHMgPSB7bW9jazogdHJ1ZSwgbWFza1Bhc3N3b3JkczogdHJ1ZX07XG4gIGlmICh0eXBlb2YgYXJnczIgPT09ICdvYmplY3QnKSB7XG4gICAgZm9yICh2YXIgYXJnS2V5IGluIGFyZ3MyKSB7XG4gICAgICBvcHRzW2FyZ0tleV0gPSBhcmdzMlthcmdLZXldO1xuICAgIH1cbiAgfVxuICB2YXIgb2JqID0gdGhpcy5leGVjdXRlKGFyZ3MxLCBvcHRzKTtcblxuICB0aGlzLmNsaWVudEF1dGhvcml6YXRpb25zLmFwcGx5KG9iaiwgdGhpcy5vcGVyYXRpb24uc2VjdXJpdHkpO1xuXG4gIHZhciByZXN1bHRzID0gW107XG5cbiAgcmVzdWx0cy5wdXNoKCctWCAnICsgdGhpcy5tZXRob2QudG9VcHBlckNhc2UoKSk7XG5cbiAgaWYgKHR5cGVvZiBvYmouaGVhZGVycyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICB2YXIga2V5O1xuXG4gICAgZm9yIChrZXkgaW4gb2JqLmhlYWRlcnMpIHtcbiAgICAgIHZhciB2YWx1ZSA9IG9iai5oZWFkZXJzW2tleV07XG4gICAgICBpZih0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKXtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC9cXCcvZywgJ1xcXFx1MDAyNycpO1xuICAgICAgfVxuICAgICAgcmVzdWx0cy5wdXNoKCctLWhlYWRlciBcXCcnICsga2V5ICsgJzogJyArIHZhbHVlICsgJ1xcJycpO1xuICAgIH1cbiAgfVxuICB2YXIgaXNGb3JtRGF0YSA9IGZhbHNlO1xuICB2YXIgaXNNdWx0aXBhcnQgPSBmYWxzZTtcblxuICB2YXIgdHlwZSA9IG9iai5oZWFkZXJzWydDb250ZW50LVR5cGUnXTtcbiAgaWYodHlwZSAmJiB0eXBlLmluZGV4T2YoJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCcpID09PSAwKSB7XG4gICAgaXNGb3JtRGF0YSA9IHRydWU7XG4gIH1cbiAgZWxzZSBpZiAodHlwZSAmJiB0eXBlLmluZGV4T2YoJ211bHRpcGFydC9mb3JtLWRhdGEnKSA9PT0gMCkge1xuICAgIGlzRm9ybURhdGEgPSB0cnVlO1xuICAgIGlzTXVsdGlwYXJ0ID0gdHJ1ZTtcbiAgfVxuXG4gIGlmIChvYmouYm9keSkge1xuICAgIHZhciBib2R5O1xuICAgIGlmIChfLmlzT2JqZWN0KG9iai5ib2R5KSkge1xuICAgICAgaWYoaXNNdWx0aXBhcnQpIHtcbiAgICAgICAgaXNNdWx0aXBhcnQgPSB0cnVlO1xuICAgICAgICAvLyBhZGQgdGhlIGZvcm0gZGF0YVxuICAgICAgICBmb3IodmFyIGkgPSAwOyBpIDwgdGhpcy5wYXJhbWV0ZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgdmFyIHBhcmFtZXRlciA9IHRoaXMucGFyYW1ldGVyc1tpXTtcbiAgICAgICAgICBpZihwYXJhbWV0ZXIuaW4gPT09ICdmb3JtRGF0YScpIHtcbiAgICAgICAgICAgIGlmICghYm9keSkge1xuICAgICAgICAgICAgICBib2R5ID0gJyc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHZhciBwYXJhbVZhbHVlO1xuICAgICAgICAgICAgaWYodHlwZW9mIEZvcm1EYXRhID09PSAnZnVuY3Rpb24nICYmIG9iai5ib2R5IGluc3RhbmNlb2YgRm9ybURhdGEpIHtcbiAgICAgICAgICAgICAgcGFyYW1WYWx1ZSA9IG9iai5ib2R5LmdldEFsbChwYXJhbWV0ZXIubmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgcGFyYW1WYWx1ZSA9IG9iai5ib2R5W3BhcmFtZXRlci5uYW1lXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChwYXJhbVZhbHVlKSB7XG4gICAgICAgICAgICAgIGlmIChwYXJhbWV0ZXIudHlwZSA9PT0gJ2ZpbGUnKSB7XG4gICAgICAgICAgICAgICAgaWYocGFyYW1WYWx1ZS5uYW1lKSB7XG4gICAgICAgICAgICAgICAgICBib2R5ICs9ICctRiAnICsgcGFyYW1ldGVyLm5hbWUgKyAnPUBcIicgKyBwYXJhbVZhbHVlLm5hbWUgKyAnXCIgJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkocGFyYW1WYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgIGlmKHBhcmFtZXRlci5jb2xsZWN0aW9uRm9ybWF0ID09PSAnbXVsdGknKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvcih2YXIgdiBpbiBwYXJhbVZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgYm9keSArPSAnLUYgJyArIHRoaXMuZW5jb2RlUXVlcnlLZXkocGFyYW1ldGVyLm5hbWUpICsgJz0nICsgbWFzayhwYXJhbVZhbHVlW3ZdLCBwYXJhbWV0ZXIuZm9ybWF0KSArICcgJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGJvZHkgKz0gJy1GICcgKyB0aGlzLmVuY29kZVF1ZXJ5Q29sbGVjdGlvbihwYXJhbWV0ZXIuY29sbGVjdGlvbkZvcm1hdCwgcGFyYW1ldGVyLm5hbWUsIG1hc2socGFyYW1WYWx1ZSwgcGFyYW1ldGVyLmZvcm1hdCkpICsgJyAnO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICBib2R5ICs9ICctRiAnICsgdGhpcy5lbmNvZGVRdWVyeUtleShwYXJhbWV0ZXIubmFtZSkgKyAnPScgKyBtYXNrKHBhcmFtVmFsdWUsIHBhcmFtZXRlci5mb3JtYXQpICsgJyAnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYoIWJvZHkpIHtcbiAgICAgICAgYm9keSA9IEpTT04uc3RyaW5naWZ5KG9iai5ib2R5KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYm9keSA9IG9iai5ib2R5O1xuICAgIH1cbiAgICAvLyBlc2NhcGUgQCA9PiAlNDAsICcgPT4gJTI3XG4gICAgYm9keSA9IGJvZHkucmVwbGFjZSgvXFwnL2csICclMjcnKS5yZXBsYWNlKC9cXG4vZywgJyBcXFxcIFxcbiAnKTtcblxuICAgIGlmKCFpc0Zvcm1EYXRhKSB7XG4gICAgICAvLyBlc2NhcGUgJiA9PiAlMjZcbiAgICAgIGJvZHkgPSBib2R5LnJlcGxhY2UoLyYvZywgJyUyNicpO1xuICAgIH1cbiAgICBpZihpc011bHRpcGFydCkge1xuICAgICAgcmVzdWx0cy5wdXNoKGJvZHkpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHJlc3VsdHMucHVzaCgnLWQgXFwnJyArIGJvZHkucmVwbGFjZSgvQC9nLCAnJTQwJykgKyAnXFwnJyk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuICdjdXJsICcgKyAocmVzdWx0cy5qb2luKCcgJykpICsgJyBcXCcnICsgb2JqLnVybCArICdcXCcnO1xufTtcblxuT3BlcmF0aW9uLnByb3RvdHlwZS5lbmNvZGVQYXRoQ29sbGVjdGlvbiA9IGZ1bmN0aW9uICh0eXBlLCBuYW1lLCB2YWx1ZSwgbWFza1Bhc3N3b3Jkcykge1xuICB2YXIgZW5jb2RlZCA9ICcnO1xuICB2YXIgaTtcbiAgdmFyIHNlcGFyYXRvciA9ICcnO1xuXG4gIGlmICh0eXBlID09PSAnc3N2Jykge1xuICAgIHNlcGFyYXRvciA9ICclMjAnO1xuICB9IGVsc2UgaWYgKHR5cGUgPT09ICd0c3YnKSB7XG4gICAgc2VwYXJhdG9yID0gJyUwOSc7XG4gIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3BpcGVzJykge1xuICAgIHNlcGFyYXRvciA9ICd8JztcbiAgfSBlbHNlIHtcbiAgICBzZXBhcmF0b3IgPSAnLCc7XG4gIH1cblxuICBmb3IgKGkgPSAwOyBpIDwgdmFsdWUubGVuZ3RoOyBpKyspIHtcbiAgICBpZiAoaSA9PT0gMCkge1xuICAgICAgZW5jb2RlZCA9IHRoaXMuZW5jb2RlUXVlcnlQYXJhbSh2YWx1ZVtpXSwgbWFza1Bhc3N3b3Jkcyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVuY29kZWQgKz0gc2VwYXJhdG9yICsgdGhpcy5lbmNvZGVRdWVyeVBhcmFtKHZhbHVlW2ldLCBtYXNrUGFzc3dvcmRzKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZW5jb2RlZDtcbn07XG5cbk9wZXJhdGlvbi5wcm90b3R5cGUuZW5jb2RlUXVlcnlDb2xsZWN0aW9uID0gZnVuY3Rpb24gKHR5cGUsIG5hbWUsIHZhbHVlLCBtYXNrUGFzc3dvcmRzKSB7XG4gIHZhciBlbmNvZGVkID0gJyc7XG4gIHZhciBpO1xuXG4gIHR5cGUgPSB0eXBlIHx8ICdkZWZhdWx0JztcbiAgaWYgKHR5cGUgPT09ICdkZWZhdWx0JyB8fCB0eXBlID09PSAnbXVsdGknKSB7XG4gICAgZm9yIChpID0gMDsgaSA8IHZhbHVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoaSA+IDApIHtlbmNvZGVkICs9ICcmJzt9XG5cbiAgICAgIGVuY29kZWQgKz0gdGhpcy5lbmNvZGVRdWVyeUtleShuYW1lKSArICc9JyArIG1hc2sodGhpcy5lbmNvZGVRdWVyeVBhcmFtKHZhbHVlW2ldKSwgbWFza1Bhc3N3b3Jkcyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhciBzZXBhcmF0b3IgPSAnJztcblxuICAgIGlmICh0eXBlID09PSAnY3N2Jykge1xuICAgICAgc2VwYXJhdG9yID0gJywnO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3NzdicpIHtcbiAgICAgIHNlcGFyYXRvciA9ICclMjAnO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3RzdicpIHtcbiAgICAgIHNlcGFyYXRvciA9ICclMDknO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ3BpcGVzJykge1xuICAgICAgc2VwYXJhdG9yID0gJ3wnO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2JyYWNrZXRzJykge1xuICAgICAgZm9yIChpID0gMDsgaSA8IHZhbHVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChpICE9PSAwKSB7XG4gICAgICAgICAgZW5jb2RlZCArPSAnJic7XG4gICAgICAgIH1cbiAgICAgICAgZW5jb2RlZCArPSB0aGlzLmVuY29kZVF1ZXJ5S2V5KG5hbWUpICsgJ1tdPScgKyBtYXNrKHRoaXMuZW5jb2RlUXVlcnlQYXJhbSh2YWx1ZVtpXSksIG1hc2tQYXNzd29yZHMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzZXBhcmF0b3IgIT09ICcnKSB7XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgdmFsdWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaWYgKGkgPT09IDApIHtcbiAgICAgICAgICBlbmNvZGVkID0gdGhpcy5lbmNvZGVRdWVyeUtleShuYW1lKSArICc9JyArIHRoaXMuZW5jb2RlUXVlcnlQYXJhbSh2YWx1ZVtpXSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZW5jb2RlZCArPSBzZXBhcmF0b3IgKyB0aGlzLmVuY29kZVF1ZXJ5UGFyYW0odmFsdWVbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGVuY29kZWQ7XG59O1xuXG5PcGVyYXRpb24ucHJvdG90eXBlLmVuY29kZVF1ZXJ5S2V5ID0gZnVuY3Rpb24gKGFyZykge1xuICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KGFyZylcbiAgICAgIC5yZXBsYWNlKCclNUInLCdbJykucmVwbGFjZSgnJTVEJywgJ10nKS5yZXBsYWNlKCclMjQnLCAnJCcpO1xufTtcblxuT3BlcmF0aW9uLnByb3RvdHlwZS5lbmNvZGVRdWVyeVBhcmFtID0gZnVuY3Rpb24gKGFyZywgbWFza1Bhc3N3b3Jkcykge1xuICBpZihtYXNrUGFzc3dvcmRzKSB7XG4gICAgcmV0dXJuIFwiKioqKioqXCI7XG4gIH1cbiAgaWYoYXJnICE9PSB1bmRlZmluZWQgJiYgYXJnICE9PSBudWxsKSB7XG4gICAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChhcmcpO1xuICB9XG4gIGVsc2Uge1xuICAgIHJldHVybiAnJztcbiAgfVxufTtcblxuLyoqXG4gKiBUT0RPIHJldmlzaXQsIG1pZ2h0IG5vdCB3YW50IHRvIGxlYXZlICcvJ1xuICoqL1xuT3BlcmF0aW9uLnByb3RvdHlwZS5lbmNvZGVQYXRoUGFyYW0gPSBmdW5jdGlvbiAocGF0aFBhcmFtLCBtYXNrUGFzc3dvcmRzKSB7XG4gIHJldHVybiBlbmNvZGVVUklDb21wb25lbnQocGF0aFBhcmFtLCBtYXNrUGFzc3dvcmRzKTtcbn07XG5cbnZhciBtYXNrID0gZnVuY3Rpb24odmFsdWUsIGZvcm1hdCkge1xuICBpZih0eXBlb2YgZm9ybWF0ID09PSAnc3RyaW5nJyAmJiBmb3JtYXQgPT09ICdwYXNzd29yZCcpIHtcbiAgICByZXR1cm4gJyoqKioqKic7XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgT3BlcmF0aW9uR3JvdXAgPSBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICh0YWcsIGRlc2NyaXB0aW9uLCBleHRlcm5hbERvY3MsIG9wZXJhdGlvbikge1xuICB0aGlzLmRlc2NyaXB0aW9uID0gZGVzY3JpcHRpb247XG4gIHRoaXMuZXh0ZXJuYWxEb2NzID0gZXh0ZXJuYWxEb2NzO1xuICB0aGlzLm5hbWUgPSB0YWc7XG4gIHRoaXMub3BlcmF0aW9uID0gb3BlcmF0aW9uO1xuICB0aGlzLm9wZXJhdGlvbnNBcnJheSA9IFtdO1xuICB0aGlzLnBhdGggPSB0YWc7XG4gIHRoaXMudGFnID0gdGFnO1xufTtcblxuT3BlcmF0aW9uR3JvdXAucHJvdG90eXBlLnNvcnQgPSBmdW5jdGlvbiAoKSB7XG5cbn07XG5cbiIsIi8vIHNoaW0gZm9yIHVzaW5nIHByb2Nlc3MgaW4gYnJvd3NlclxuXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGRyYWluaW5nID0gdHJ1ZTtcbiAgICB2YXIgY3VycmVudFF1ZXVlO1xuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB2YXIgaSA9IC0xO1xuICAgICAgICB3aGlsZSAoKytpIDwgbGVuKSB7XG4gICAgICAgICAgICBjdXJyZW50UXVldWVbaV0oKTtcbiAgICAgICAgfVxuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGRyYWluaW5nID0gZmFsc2U7XG59XG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHF1ZXVlLnB1c2goZnVuKTtcbiAgICBpZiAoIWRyYWluaW5nKSB7XG4gICAgICAgIHNldFRpbWVvdXQoZHJhaW5RdWV1ZSwgMCk7XG4gICAgfVxufTtcblxucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbi8vIFRPRE8oc2h0eWxtYW4pXG5wcm9jZXNzLmN3ZCA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuICcvJyB9O1xucHJvY2Vzcy5jaGRpciA9IGZ1bmN0aW9uIChkaXIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3Byb2Nlc3MuY2hkaXIgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcbnByb2Nlc3MudW1hc2sgPSBmdW5jdGlvbigpIHsgcmV0dXJuIDA7IH07XG4iLCIoZnVuY3Rpb24gKEJ1ZmZlcil7XG4oZnVuY3Rpb24gKCkge1xuICBcInVzZSBzdHJpY3RcIjtcblxuICBmdW5jdGlvbiBidG9hKHN0cikge1xuICAgIHZhciBidWZmZXJcbiAgICAgIDtcblxuICAgIGlmIChzdHIgaW5zdGFuY2VvZiBCdWZmZXIpIHtcbiAgICAgIGJ1ZmZlciA9IHN0cjtcbiAgICB9IGVsc2Uge1xuICAgICAgYnVmZmVyID0gbmV3IEJ1ZmZlcihzdHIudG9TdHJpbmcoKSwgJ2JpbmFyeScpO1xuICAgIH1cblxuICAgIHJldHVybiBidWZmZXIudG9TdHJpbmcoJ2Jhc2U2NCcpO1xuICB9XG5cbiAgbW9kdWxlLmV4cG9ydHMgPSBidG9hO1xufSgpKTtcblxufSkuY2FsbCh0aGlzLHJlcXVpcmUoXCJidWZmZXJcIikuQnVmZmVyKVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ6dXRmLTg7YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW01dlpHVmZiVzlrZFd4bGN5OWlkRzloTDJsdVpHVjRMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGQlFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFTSXNJbVpwYkdVaU9pSm5aVzVsY21GMFpXUXVhbk1pTENKemIzVnlZMlZTYjI5MElqb2lJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpS0daMWJtTjBhVzl1SUNncElIdGNiaUFnWENKMWMyVWdjM1J5YVdOMFhDSTdYRzVjYmlBZ1puVnVZM1JwYjI0Z1luUnZZU2h6ZEhJcElIdGNiaUFnSUNCMllYSWdZblZtWm1WeVhHNGdJQ0FnSUNBN1hHNWNiaUFnSUNCcFppQW9jM1J5SUdsdWMzUmhibU5sYjJZZ1FuVm1abVZ5S1NCN1hHNGdJQ0FnSUNCaWRXWm1aWElnUFNCemRISTdYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUdKMVptWmxjaUE5SUc1bGR5QkNkV1ptWlhJb2MzUnlMblJ2VTNSeWFXNW5LQ2tzSUNkaWFXNWhjbmtuS1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0J5WlhSMWNtNGdZblZtWm1WeUxuUnZVM1J5YVc1bktDZGlZWE5sTmpRbktUdGNiaUFnZlZ4dVhHNGdJRzF2WkhWc1pTNWxlSEJ2Y25SeklEMGdZblJ2WVR0Y2JuMG9LU2s3WEc0aVhYMD0iLCIvKiFcbiAqIFRoZSBidWZmZXIgbW9kdWxlIGZyb20gbm9kZS5qcywgZm9yIHRoZSBicm93c2VyLlxuICpcbiAqIEBhdXRob3IgICBGZXJvc3MgQWJvdWtoYWRpamVoIDxmZXJvc3NAZmVyb3NzLm9yZz4gPGh0dHA6Ly9mZXJvc3Mub3JnPlxuICogQGxpY2Vuc2UgIE1JVFxuICovXG5cbnZhciBiYXNlNjQgPSByZXF1aXJlKCdiYXNlNjQtanMnKVxudmFyIGllZWU3NTQgPSByZXF1aXJlKCdpZWVlNzU0JylcbnZhciBpc0FycmF5ID0gcmVxdWlyZSgnaXMtYXJyYXknKVxuXG5leHBvcnRzLkJ1ZmZlciA9IEJ1ZmZlclxuZXhwb3J0cy5TbG93QnVmZmVyID0gU2xvd0J1ZmZlclxuZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFUyA9IDUwXG5CdWZmZXIucG9vbFNpemUgPSA4MTkyIC8vIG5vdCB1c2VkIGJ5IHRoaXMgaW1wbGVtZW50YXRpb25cblxudmFyIHJvb3RQYXJlbnQgPSB7fVxuXG4vKipcbiAqIElmIGBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVGA6XG4gKiAgID09PSB0cnVlICAgIFVzZSBVaW50OEFycmF5IGltcGxlbWVudGF0aW9uIChmYXN0ZXN0KVxuICogICA9PT0gZmFsc2UgICBVc2UgT2JqZWN0IGltcGxlbWVudGF0aW9uIChtb3N0IGNvbXBhdGlibGUsIGV2ZW4gSUU2KVxuICpcbiAqIEJyb3dzZXJzIHRoYXQgc3VwcG9ydCB0eXBlZCBhcnJheXMgYXJlIElFIDEwKywgRmlyZWZveCA0KywgQ2hyb21lIDcrLCBTYWZhcmkgNS4xKyxcbiAqIE9wZXJhIDExLjYrLCBpT1MgNC4yKy5cbiAqXG4gKiBEdWUgdG8gdmFyaW91cyBicm93c2VyIGJ1Z3MsIHNvbWV0aW1lcyB0aGUgT2JqZWN0IGltcGxlbWVudGF0aW9uIHdpbGwgYmUgdXNlZCBldmVuXG4gKiB3aGVuIHRoZSBicm93c2VyIHN1cHBvcnRzIHR5cGVkIGFycmF5cy5cbiAqXG4gKiBOb3RlOlxuICpcbiAqICAgLSBGaXJlZm94IDQtMjkgbGFja3Mgc3VwcG9ydCBmb3IgYWRkaW5nIG5ldyBwcm9wZXJ0aWVzIHRvIGBVaW50OEFycmF5YCBpbnN0YW5jZXMsXG4gKiAgICAgU2VlOiBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD02OTU0MzguXG4gKlxuICogICAtIFNhZmFyaSA1LTcgbGFja3Mgc3VwcG9ydCBmb3IgY2hhbmdpbmcgdGhlIGBPYmplY3QucHJvdG90eXBlLmNvbnN0cnVjdG9yYCBwcm9wZXJ0eVxuICogICAgIG9uIG9iamVjdHMuXG4gKlxuICogICAtIENocm9tZSA5LTEwIGlzIG1pc3NpbmcgdGhlIGBUeXBlZEFycmF5LnByb3RvdHlwZS5zdWJhcnJheWAgZnVuY3Rpb24uXG4gKlxuICogICAtIElFMTAgaGFzIGEgYnJva2VuIGBUeXBlZEFycmF5LnByb3RvdHlwZS5zdWJhcnJheWAgZnVuY3Rpb24gd2hpY2ggcmV0dXJucyBhcnJheXMgb2ZcbiAqICAgICBpbmNvcnJlY3QgbGVuZ3RoIGluIHNvbWUgc2l0dWF0aW9ucy5cblxuICogV2UgZGV0ZWN0IHRoZXNlIGJ1Z2d5IGJyb3dzZXJzIGFuZCBzZXQgYEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUYCB0byBgZmFsc2VgIHNvIHRoZXlcbiAqIGdldCB0aGUgT2JqZWN0IGltcGxlbWVudGF0aW9uLCB3aGljaCBpcyBzbG93ZXIgYnV0IGJlaGF2ZXMgY29ycmVjdGx5LlxuICovXG5CdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCA9IChmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIEJhciAoKSB7fVxuICB0cnkge1xuICAgIHZhciBhcnIgPSBuZXcgVWludDhBcnJheSgxKVxuICAgIGFyci5mb28gPSBmdW5jdGlvbiAoKSB7IHJldHVybiA0MiB9XG4gICAgYXJyLmNvbnN0cnVjdG9yID0gQmFyXG4gICAgcmV0dXJuIGFyci5mb28oKSA9PT0gNDIgJiYgLy8gdHlwZWQgYXJyYXkgaW5zdGFuY2VzIGNhbiBiZSBhdWdtZW50ZWRcbiAgICAgICAgYXJyLmNvbnN0cnVjdG9yID09PSBCYXIgJiYgLy8gY29uc3RydWN0b3IgY2FuIGJlIHNldFxuICAgICAgICB0eXBlb2YgYXJyLnN1YmFycmF5ID09PSAnZnVuY3Rpb24nICYmIC8vIGNocm9tZSA5LTEwIGxhY2sgYHN1YmFycmF5YFxuICAgICAgICBhcnIuc3ViYXJyYXkoMSwgMSkuYnl0ZUxlbmd0aCA9PT0gMCAvLyBpZTEwIGhhcyBicm9rZW4gYHN1YmFycmF5YFxuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbn0pKClcblxuZnVuY3Rpb24ga01heExlbmd0aCAoKSB7XG4gIHJldHVybiBCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVFxuICAgID8gMHg3ZmZmZmZmZlxuICAgIDogMHgzZmZmZmZmZlxufVxuXG4vKipcbiAqIENsYXNzOiBCdWZmZXJcbiAqID09PT09PT09PT09PT1cbiAqXG4gKiBUaGUgQnVmZmVyIGNvbnN0cnVjdG9yIHJldHVybnMgaW5zdGFuY2VzIG9mIGBVaW50OEFycmF5YCB0aGF0IGFyZSBhdWdtZW50ZWRcbiAqIHdpdGggZnVuY3Rpb24gcHJvcGVydGllcyBmb3IgYWxsIHRoZSBub2RlIGBCdWZmZXJgIEFQSSBmdW5jdGlvbnMuIFdlIHVzZVxuICogYFVpbnQ4QXJyYXlgIHNvIHRoYXQgc3F1YXJlIGJyYWNrZXQgbm90YXRpb24gd29ya3MgYXMgZXhwZWN0ZWQgLS0gaXQgcmV0dXJuc1xuICogYSBzaW5nbGUgb2N0ZXQuXG4gKlxuICogQnkgYXVnbWVudGluZyB0aGUgaW5zdGFuY2VzLCB3ZSBjYW4gYXZvaWQgbW9kaWZ5aW5nIHRoZSBgVWludDhBcnJheWBcbiAqIHByb3RvdHlwZS5cbiAqL1xuZnVuY3Rpb24gQnVmZmVyIChhcmcpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEJ1ZmZlcikpIHtcbiAgICAvLyBBdm9pZCBnb2luZyB0aHJvdWdoIGFuIEFyZ3VtZW50c0FkYXB0b3JUcmFtcG9saW5lIGluIHRoZSBjb21tb24gY2FzZS5cbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHJldHVybiBuZXcgQnVmZmVyKGFyZywgYXJndW1lbnRzWzFdKVxuICAgIHJldHVybiBuZXcgQnVmZmVyKGFyZylcbiAgfVxuXG4gIHRoaXMubGVuZ3RoID0gMFxuICB0aGlzLnBhcmVudCA9IHVuZGVmaW5lZFxuXG4gIC8vIENvbW1vbiBjYXNlLlxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gZnJvbU51bWJlcih0aGlzLCBhcmcpXG4gIH1cblxuICAvLyBTbGlnaHRseSBsZXNzIGNvbW1vbiBjYXNlLlxuICBpZiAodHlwZW9mIGFyZyA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gZnJvbVN0cmluZyh0aGlzLCBhcmcsIGFyZ3VtZW50cy5sZW5ndGggPiAxID8gYXJndW1lbnRzWzFdIDogJ3V0ZjgnKVxuICB9XG5cbiAgLy8gVW51c3VhbC5cbiAgcmV0dXJuIGZyb21PYmplY3QodGhpcywgYXJnKVxufVxuXG5mdW5jdGlvbiBmcm9tTnVtYmVyICh0aGF0LCBsZW5ndGgpIHtcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aCA8IDAgPyAwIDogY2hlY2tlZChsZW5ndGgpIHwgMClcbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoYXRbaV0gPSAwXG4gICAgfVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21TdHJpbmcgKHRoYXQsIHN0cmluZywgZW5jb2RpbmcpIHtcbiAgaWYgKHR5cGVvZiBlbmNvZGluZyAhPT0gJ3N0cmluZycgfHwgZW5jb2RpbmcgPT09ICcnKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIC8vIEFzc3VtcHRpb246IGJ5dGVMZW5ndGgoKSByZXR1cm4gdmFsdWUgaXMgYWx3YXlzIDwga01heExlbmd0aC5cbiAgdmFyIGxlbmd0aCA9IGJ5dGVMZW5ndGgoc3RyaW5nLCBlbmNvZGluZykgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG5cbiAgdGhhdC53cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tT2JqZWN0ICh0aGF0LCBvYmplY3QpIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihvYmplY3QpKSByZXR1cm4gZnJvbUJ1ZmZlcih0aGF0LCBvYmplY3QpXG5cbiAgaWYgKGlzQXJyYXkob2JqZWN0KSkgcmV0dXJuIGZyb21BcnJheSh0aGF0LCBvYmplY3QpXG5cbiAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbXVzdCBzdGFydCB3aXRoIG51bWJlciwgYnVmZmVyLCBhcnJheSBvciBzdHJpbmcnKVxuICB9XG5cbiAgaWYgKHR5cGVvZiBBcnJheUJ1ZmZlciAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAob2JqZWN0LmJ1ZmZlciBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XG4gICAgICByZXR1cm4gZnJvbVR5cGVkQXJyYXkodGhhdCwgb2JqZWN0KVxuICAgIH1cbiAgICBpZiAob2JqZWN0IGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcbiAgICAgIHJldHVybiBmcm9tQXJyYXlCdWZmZXIodGhhdCwgb2JqZWN0KVxuICAgIH1cbiAgfVxuXG4gIGlmIChvYmplY3QubGVuZ3RoKSByZXR1cm4gZnJvbUFycmF5TGlrZSh0aGF0LCBvYmplY3QpXG5cbiAgcmV0dXJuIGZyb21Kc29uT2JqZWN0KHRoYXQsIG9iamVjdClcbn1cblxuZnVuY3Rpb24gZnJvbUJ1ZmZlciAodGhhdCwgYnVmZmVyKSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGJ1ZmZlci5sZW5ndGgpIHwgMFxuICB0aGF0ID0gYWxsb2NhdGUodGhhdCwgbGVuZ3RoKVxuICBidWZmZXIuY29weSh0aGF0LCAwLCAwLCBsZW5ndGgpXG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheSAodGhhdCwgYXJyYXkpIHtcbiAgdmFyIGxlbmd0aCA9IGNoZWNrZWQoYXJyYXkubGVuZ3RoKSB8IDBcbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIHRoYXRbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbi8vIER1cGxpY2F0ZSBvZiBmcm9tQXJyYXkoKSB0byBrZWVwIGZyb21BcnJheSgpIG1vbm9tb3JwaGljLlxuZnVuY3Rpb24gZnJvbVR5cGVkQXJyYXkgKHRoYXQsIGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG4gIC8vIFRydW5jYXRpbmcgdGhlIGVsZW1lbnRzIGlzIHByb2JhYmx5IG5vdCB3aGF0IHBlb3BsZSBleHBlY3QgZnJvbSB0eXBlZFxuICAvLyBhcnJheXMgd2l0aCBCWVRFU19QRVJfRUxFTUVOVCA+IDEgYnV0IGl0J3MgY29tcGF0aWJsZSB3aXRoIHRoZSBiZWhhdmlvclxuICAvLyBvZiB0aGUgb2xkIEJ1ZmZlciBjb25zdHJ1Y3Rvci5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkgKz0gMSkge1xuICAgIHRoYXRbaV0gPSBhcnJheVtpXSAmIDI1NVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUJ1ZmZlciAodGhhdCwgYXJyYXkpIHtcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gUmV0dXJuIGFuIGF1Z21lbnRlZCBgVWludDhBcnJheWAgaW5zdGFuY2UsIGZvciBiZXN0IHBlcmZvcm1hbmNlXG4gICAgYXJyYXkuYnl0ZUxlbmd0aFxuICAgIHRoYXQgPSBCdWZmZXIuX2F1Z21lbnQobmV3IFVpbnQ4QXJyYXkoYXJyYXkpKVxuICB9IGVsc2Uge1xuICAgIC8vIEZhbGxiYWNrOiBSZXR1cm4gYW4gb2JqZWN0IGluc3RhbmNlIG9mIHRoZSBCdWZmZXIgY2xhc3NcbiAgICB0aGF0ID0gZnJvbVR5cGVkQXJyYXkodGhhdCwgbmV3IFVpbnQ4QXJyYXkoYXJyYXkpKVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUxpa2UgKHRoYXQsIGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIHRoYXQgPSBhbGxvY2F0ZSh0aGF0LCBsZW5ndGgpXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICB0aGF0W2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG4vLyBEZXNlcmlhbGl6ZSB7IHR5cGU6ICdCdWZmZXInLCBkYXRhOiBbMSwyLDMsLi4uXSB9IGludG8gYSBCdWZmZXIgb2JqZWN0LlxuLy8gUmV0dXJucyBhIHplcm8tbGVuZ3RoIGJ1ZmZlciBmb3IgaW5wdXRzIHRoYXQgZG9uJ3QgY29uZm9ybSB0byB0aGUgc3BlYy5cbmZ1bmN0aW9uIGZyb21Kc29uT2JqZWN0ICh0aGF0LCBvYmplY3QpIHtcbiAgdmFyIGFycmF5XG4gIHZhciBsZW5ndGggPSAwXG5cbiAgaWYgKG9iamVjdC50eXBlID09PSAnQnVmZmVyJyAmJiBpc0FycmF5KG9iamVjdC5kYXRhKSkge1xuICAgIGFycmF5ID0gb2JqZWN0LmRhdGFcbiAgICBsZW5ndGggPSBjaGVja2VkKGFycmF5Lmxlbmd0aCkgfCAwXG4gIH1cbiAgdGhhdCA9IGFsbG9jYXRlKHRoYXQsIGxlbmd0aClcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSArPSAxKSB7XG4gICAgdGhhdFtpXSA9IGFycmF5W2ldICYgMjU1XG4gIH1cbiAgcmV0dXJuIHRoYXRcbn1cblxuZnVuY3Rpb24gYWxsb2NhdGUgKHRoYXQsIGxlbmd0aCkge1xuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAvLyBSZXR1cm4gYW4gYXVnbWVudGVkIGBVaW50OEFycmF5YCBpbnN0YW5jZSwgZm9yIGJlc3QgcGVyZm9ybWFuY2VcbiAgICB0aGF0ID0gQnVmZmVyLl9hdWdtZW50KG5ldyBVaW50OEFycmF5KGxlbmd0aCkpXG4gIH0gZWxzZSB7XG4gICAgLy8gRmFsbGJhY2s6IFJldHVybiBhbiBvYmplY3QgaW5zdGFuY2Ugb2YgdGhlIEJ1ZmZlciBjbGFzc1xuICAgIHRoYXQubGVuZ3RoID0gbGVuZ3RoXG4gICAgdGhhdC5faXNCdWZmZXIgPSB0cnVlXG4gIH1cblxuICB2YXIgZnJvbVBvb2wgPSBsZW5ndGggIT09IDAgJiYgbGVuZ3RoIDw9IEJ1ZmZlci5wb29sU2l6ZSA+Pj4gMVxuICBpZiAoZnJvbVBvb2wpIHRoYXQucGFyZW50ID0gcm9vdFBhcmVudFxuXG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGNoZWNrZWQgKGxlbmd0aCkge1xuICAvLyBOb3RlOiBjYW5ub3QgdXNlIGBsZW5ndGggPCBrTWF4TGVuZ3RoYCBoZXJlIGJlY2F1c2UgdGhhdCBmYWlscyB3aGVuXG4gIC8vIGxlbmd0aCBpcyBOYU4gKHdoaWNoIGlzIG90aGVyd2lzZSBjb2VyY2VkIHRvIHplcm8uKVxuICBpZiAobGVuZ3RoID49IGtNYXhMZW5ndGgoKSkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdBdHRlbXB0IHRvIGFsbG9jYXRlIEJ1ZmZlciBsYXJnZXIgdGhhbiBtYXhpbXVtICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgICdzaXplOiAweCcgKyBrTWF4TGVuZ3RoKCkudG9TdHJpbmcoMTYpICsgJyBieXRlcycpXG4gIH1cbiAgcmV0dXJuIGxlbmd0aCB8IDBcbn1cblxuZnVuY3Rpb24gU2xvd0J1ZmZlciAoc3ViamVjdCwgZW5jb2RpbmcpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFNsb3dCdWZmZXIpKSByZXR1cm4gbmV3IFNsb3dCdWZmZXIoc3ViamVjdCwgZW5jb2RpbmcpXG5cbiAgdmFyIGJ1ZiA9IG5ldyBCdWZmZXIoc3ViamVjdCwgZW5jb2RpbmcpXG4gIGRlbGV0ZSBidWYucGFyZW50XG4gIHJldHVybiBidWZcbn1cblxuQnVmZmVyLmlzQnVmZmVyID0gZnVuY3Rpb24gaXNCdWZmZXIgKGIpIHtcbiAgcmV0dXJuICEhKGIgIT0gbnVsbCAmJiBiLl9pc0J1ZmZlcilcbn1cblxuQnVmZmVyLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlIChhLCBiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGEpIHx8ICFCdWZmZXIuaXNCdWZmZXIoYikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudHMgbXVzdCBiZSBCdWZmZXJzJylcbiAgfVxuXG4gIGlmIChhID09PSBiKSByZXR1cm4gMFxuXG4gIHZhciB4ID0gYS5sZW5ndGhcbiAgdmFyIHkgPSBiLmxlbmd0aFxuXG4gIHZhciBpID0gMFxuICB2YXIgbGVuID0gTWF0aC5taW4oeCwgeSlcbiAgd2hpbGUgKGkgPCBsZW4pIHtcbiAgICBpZiAoYVtpXSAhPT0gYltpXSkgYnJlYWtcblxuICAgICsraVxuICB9XG5cbiAgaWYgKGkgIT09IGxlbikge1xuICAgIHggPSBhW2ldXG4gICAgeSA9IGJbaV1cbiAgfVxuXG4gIGlmICh4IDwgeSkgcmV0dXJuIC0xXG4gIGlmICh5IDwgeCkgcmV0dXJuIDFcbiAgcmV0dXJuIDBcbn1cblxuQnVmZmVyLmlzRW5jb2RpbmcgPSBmdW5jdGlvbiBpc0VuY29kaW5nIChlbmNvZGluZykge1xuICBzd2l0Y2ggKFN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKSkge1xuICAgIGNhc2UgJ2hleCc6XG4gICAgY2FzZSAndXRmOCc6XG4gICAgY2FzZSAndXRmLTgnOlxuICAgIGNhc2UgJ2FzY2lpJzpcbiAgICBjYXNlICdiaW5hcnknOlxuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgY2FzZSAncmF3JzpcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0dXJuIHRydWVcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGZhbHNlXG4gIH1cbn1cblxuQnVmZmVyLmNvbmNhdCA9IGZ1bmN0aW9uIGNvbmNhdCAobGlzdCwgbGVuZ3RoKSB7XG4gIGlmICghaXNBcnJheShsaXN0KSkgdGhyb3cgbmV3IFR5cGVFcnJvcignbGlzdCBhcmd1bWVudCBtdXN0IGJlIGFuIEFycmF5IG9mIEJ1ZmZlcnMuJylcblxuICBpZiAobGlzdC5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gbmV3IEJ1ZmZlcigwKVxuICB9XG5cbiAgdmFyIGlcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgbGVuZ3RoID0gMFxuICAgIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICBsZW5ndGggKz0gbGlzdFtpXS5sZW5ndGhcbiAgICB9XG4gIH1cblxuICB2YXIgYnVmID0gbmV3IEJ1ZmZlcihsZW5ndGgpXG4gIHZhciBwb3MgPSAwXG4gIGZvciAoaSA9IDA7IGkgPCBsaXN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGl0ZW0gPSBsaXN0W2ldXG4gICAgaXRlbS5jb3B5KGJ1ZiwgcG9zKVxuICAgIHBvcyArPSBpdGVtLmxlbmd0aFxuICB9XG4gIHJldHVybiBidWZcbn1cblxuZnVuY3Rpb24gYnl0ZUxlbmd0aCAoc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAodHlwZW9mIHN0cmluZyAhPT0gJ3N0cmluZycpIHN0cmluZyA9ICcnICsgc3RyaW5nXG5cbiAgdmFyIGxlbiA9IHN0cmluZy5sZW5ndGhcbiAgaWYgKGxlbiA9PT0gMCkgcmV0dXJuIDBcblxuICAvLyBVc2UgYSBmb3IgbG9vcCB0byBhdm9pZCByZWN1cnNpb25cbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcbiAgZm9yICg7Oykge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAvLyBEZXByZWNhdGVkXG4gICAgICBjYXNlICdyYXcnOlxuICAgICAgY2FzZSAncmF3cyc6XG4gICAgICAgIHJldHVybiBsZW5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiBsZW4gKiAyXG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gbGVuID4+PiAxXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0VG9CeXRlcyhzdHJpbmcpLmxlbmd0aFxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSByZXR1cm4gdXRmOFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGggLy8gYXNzdW1lIHV0ZjhcbiAgICAgICAgZW5jb2RpbmcgPSAoJycgKyBlbmNvZGluZykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cbkJ1ZmZlci5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aFxuXG4vLyBwcmUtc2V0IGZvciB2YWx1ZXMgdGhhdCBtYXkgZXhpc3QgaW4gdGhlIGZ1dHVyZVxuQnVmZmVyLnByb3RvdHlwZS5sZW5ndGggPSB1bmRlZmluZWRcbkJ1ZmZlci5wcm90b3R5cGUucGFyZW50ID0gdW5kZWZpbmVkXG5cbmZ1bmN0aW9uIHNsb3dUb1N0cmluZyAoZW5jb2RpbmcsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcblxuICBzdGFydCA9IHN0YXJ0IHwgMFxuICBlbmQgPSBlbmQgPT09IHVuZGVmaW5lZCB8fCBlbmQgPT09IEluZmluaXR5ID8gdGhpcy5sZW5ndGggOiBlbmQgfCAwXG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcbiAgaWYgKHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIGlmIChlbmQgPiB0aGlzLmxlbmd0aCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKGVuZCA8PSBzdGFydCkgcmV0dXJuICcnXG5cbiAgd2hpbGUgKHRydWUpIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gaGV4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiB1dGY4U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYXNjaWknOlxuICAgICAgICByZXR1cm4gYXNjaWlTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gYmluYXJ5U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1dGYxNmxlU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKGVuY29kaW5nICsgJycpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZyAoKSB7XG4gIHZhciBsZW5ndGggPSB0aGlzLmxlbmd0aCB8IDBcbiAgaWYgKGxlbmd0aCA9PT0gMCkgcmV0dXJuICcnXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIDAsIGxlbmd0aClcbiAgcmV0dXJuIHNsb3dUb1N0cmluZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24gZXF1YWxzIChiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyJylcbiAgaWYgKHRoaXMgPT09IGIpIHJldHVybiB0cnVlXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKSA9PT0gMFxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluc3BlY3QgPSBmdW5jdGlvbiBpbnNwZWN0ICgpIHtcbiAgdmFyIHN0ciA9ICcnXG4gIHZhciBtYXggPSBleHBvcnRzLklOU1BFQ1RfTUFYX0JZVEVTXG4gIGlmICh0aGlzLmxlbmd0aCA+IDApIHtcbiAgICBzdHIgPSB0aGlzLnRvU3RyaW5nKCdoZXgnLCAwLCBtYXgpLm1hdGNoKC8uezJ9L2cpLmpvaW4oJyAnKVxuICAgIGlmICh0aGlzLmxlbmd0aCA+IG1heCkgc3RyICs9ICcgLi4uICdcbiAgfVxuICByZXR1cm4gJzxCdWZmZXIgJyArIHN0ciArICc+J1xufVxuXG5CdWZmZXIucHJvdG90eXBlLmNvbXBhcmUgPSBmdW5jdGlvbiBjb21wYXJlIChiKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyJylcbiAgaWYgKHRoaXMgPT09IGIpIHJldHVybiAwXG4gIHJldHVybiBCdWZmZXIuY29tcGFyZSh0aGlzLCBiKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluZGV4T2YgPSBmdW5jdGlvbiBpbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQpIHtcbiAgaWYgKGJ5dGVPZmZzZXQgPiAweDdmZmZmZmZmKSBieXRlT2Zmc2V0ID0gMHg3ZmZmZmZmZlxuICBlbHNlIGlmIChieXRlT2Zmc2V0IDwgLTB4ODAwMDAwMDApIGJ5dGVPZmZzZXQgPSAtMHg4MDAwMDAwMFxuICBieXRlT2Zmc2V0ID4+PSAwXG5cbiAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gLTFcbiAgaWYgKGJ5dGVPZmZzZXQgPj0gdGhpcy5sZW5ndGgpIHJldHVybiAtMVxuXG4gIC8vIE5lZ2F0aXZlIG9mZnNldHMgc3RhcnQgZnJvbSB0aGUgZW5kIG9mIHRoZSBidWZmZXJcbiAgaWYgKGJ5dGVPZmZzZXQgPCAwKSBieXRlT2Zmc2V0ID0gTWF0aC5tYXgodGhpcy5sZW5ndGggKyBieXRlT2Zmc2V0LCAwKVxuXG4gIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJykge1xuICAgIGlmICh2YWwubGVuZ3RoID09PSAwKSByZXR1cm4gLTEgLy8gc3BlY2lhbCBjYXNlOiBsb29raW5nIGZvciBlbXB0eSBzdHJpbmcgYWx3YXlzIGZhaWxzXG4gICAgcmV0dXJuIFN0cmluZy5wcm90b3R5cGUuaW5kZXhPZi5jYWxsKHRoaXMsIHZhbCwgYnl0ZU9mZnNldClcbiAgfVxuICBpZiAoQnVmZmVyLmlzQnVmZmVyKHZhbCkpIHtcbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKHRoaXMsIHZhbCwgYnl0ZU9mZnNldClcbiAgfVxuICBpZiAodHlwZW9mIHZhbCA9PT0gJ251bWJlcicpIHtcbiAgICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQgJiYgVWludDhBcnJheS5wcm90b3R5cGUuaW5kZXhPZiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIFVpbnQ4QXJyYXkucHJvdG90eXBlLmluZGV4T2YuY2FsbCh0aGlzLCB2YWwsIGJ5dGVPZmZzZXQpXG4gICAgfVxuICAgIHJldHVybiBhcnJheUluZGV4T2YodGhpcywgWyB2YWwgXSwgYnl0ZU9mZnNldClcbiAgfVxuXG4gIGZ1bmN0aW9uIGFycmF5SW5kZXhPZiAoYXJyLCB2YWwsIGJ5dGVPZmZzZXQpIHtcbiAgICB2YXIgZm91bmRJbmRleCA9IC0xXG4gICAgZm9yICh2YXIgaSA9IDA7IGJ5dGVPZmZzZXQgKyBpIDwgYXJyLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoYXJyW2J5dGVPZmZzZXQgKyBpXSA9PT0gdmFsW2ZvdW5kSW5kZXggPT09IC0xID8gMCA6IGkgLSBmb3VuZEluZGV4XSkge1xuICAgICAgICBpZiAoZm91bmRJbmRleCA9PT0gLTEpIGZvdW5kSW5kZXggPSBpXG4gICAgICAgIGlmIChpIC0gZm91bmRJbmRleCArIDEgPT09IHZhbC5sZW5ndGgpIHJldHVybiBieXRlT2Zmc2V0ICsgZm91bmRJbmRleFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZm91bmRJbmRleCA9IC0xXG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAtMVxuICB9XG5cbiAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmFsIG11c3QgYmUgc3RyaW5nLCBudW1iZXIgb3IgQnVmZmVyJylcbn1cblxuLy8gYGdldGAgaXMgZGVwcmVjYXRlZFxuQnVmZmVyLnByb3RvdHlwZS5nZXQgPSBmdW5jdGlvbiBnZXQgKG9mZnNldCkge1xuICBjb25zb2xlLmxvZygnLmdldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuJylcbiAgcmV0dXJuIHRoaXMucmVhZFVJbnQ4KG9mZnNldClcbn1cblxuLy8gYHNldGAgaXMgZGVwcmVjYXRlZFxuQnVmZmVyLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiBzZXQgKHYsIG9mZnNldCkge1xuICBjb25zb2xlLmxvZygnLnNldCgpIGlzIGRlcHJlY2F0ZWQuIEFjY2VzcyB1c2luZyBhcnJheSBpbmRleGVzIGluc3RlYWQuJylcbiAgcmV0dXJuIHRoaXMud3JpdGVVSW50OCh2LCBvZmZzZXQpXG59XG5cbmZ1bmN0aW9uIGhleFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgb2Zmc2V0ID0gTnVtYmVyKG9mZnNldCkgfHwgMFxuICB2YXIgcmVtYWluaW5nID0gYnVmLmxlbmd0aCAtIG9mZnNldFxuICBpZiAoIWxlbmd0aCkge1xuICAgIGxlbmd0aCA9IHJlbWFpbmluZ1xuICB9IGVsc2Uge1xuICAgIGxlbmd0aCA9IE51bWJlcihsZW5ndGgpXG4gICAgaWYgKGxlbmd0aCA+IHJlbWFpbmluZykge1xuICAgICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gICAgfVxuICB9XG5cbiAgLy8gbXVzdCBiZSBhbiBldmVuIG51bWJlciBvZiBkaWdpdHNcbiAgdmFyIHN0ckxlbiA9IHN0cmluZy5sZW5ndGhcbiAgaWYgKHN0ckxlbiAlIDIgIT09IDApIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBoZXggc3RyaW5nJylcblxuICBpZiAobGVuZ3RoID4gc3RyTGVuIC8gMikge1xuICAgIGxlbmd0aCA9IHN0ckxlbiAvIDJcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHBhcnNlZCA9IHBhcnNlSW50KHN0cmluZy5zdWJzdHIoaSAqIDIsIDIpLCAxNilcbiAgICBpZiAoaXNOYU4ocGFyc2VkKSkgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGhleCBzdHJpbmcnKVxuICAgIGJ1ZltvZmZzZXQgKyBpXSA9IHBhcnNlZFxuICB9XG4gIHJldHVybiBpXG59XG5cbmZ1bmN0aW9uIHV0ZjhXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKHV0ZjhUb0J5dGVzKHN0cmluZywgYnVmLmxlbmd0aCAtIG9mZnNldCksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGFzY2lpV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcihhc2NpaVRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gYmluYXJ5V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYXNjaWlXcml0ZShidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGJhc2U2NFdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIoYmFzZTY0VG9CeXRlcyhzdHJpbmcpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiB1Y3MyV3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcih1dGYxNmxlVG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24gd3JpdGUgKHN0cmluZywgb2Zmc2V0LCBsZW5ndGgsIGVuY29kaW5nKSB7XG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcpXG4gIGlmIChvZmZzZXQgPT09IHVuZGVmaW5lZCkge1xuICAgIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIGVuY29kaW5nKVxuICB9IGVsc2UgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkICYmIHR5cGVvZiBvZmZzZXQgPT09ICdzdHJpbmcnKSB7XG4gICAgZW5jb2RpbmcgPSBvZmZzZXRcbiAgICBsZW5ndGggPSB0aGlzLmxlbmd0aFxuICAgIG9mZnNldCA9IDBcbiAgLy8gQnVmZmVyI3dyaXRlKHN0cmluZywgb2Zmc2V0WywgbGVuZ3RoXVssIGVuY29kaW5nXSlcbiAgfSBlbHNlIGlmIChpc0Zpbml0ZShvZmZzZXQpKSB7XG4gICAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICAgIGlmIChpc0Zpbml0ZShsZW5ndGgpKSB7XG4gICAgICBsZW5ndGggPSBsZW5ndGggfCAwXG4gICAgICBpZiAoZW5jb2RpbmcgPT09IHVuZGVmaW5lZCkgZW5jb2RpbmcgPSAndXRmOCdcbiAgICB9IGVsc2Uge1xuICAgICAgZW5jb2RpbmcgPSBsZW5ndGhcbiAgICAgIGxlbmd0aCA9IHVuZGVmaW5lZFxuICAgIH1cbiAgLy8gbGVnYWN5IHdyaXRlKHN0cmluZywgZW5jb2RpbmcsIG9mZnNldCwgbGVuZ3RoKSAtIHJlbW92ZSBpbiB2MC4xM1xuICB9IGVsc2Uge1xuICAgIHZhciBzd2FwID0gZW5jb2RpbmdcbiAgICBlbmNvZGluZyA9IG9mZnNldFxuICAgIG9mZnNldCA9IGxlbmd0aCB8IDBcbiAgICBsZW5ndGggPSBzd2FwXG4gIH1cblxuICB2YXIgcmVtYWluaW5nID0gdGhpcy5sZW5ndGggLSBvZmZzZXRcbiAgaWYgKGxlbmd0aCA9PT0gdW5kZWZpbmVkIHx8IGxlbmd0aCA+IHJlbWFpbmluZykgbGVuZ3RoID0gcmVtYWluaW5nXG5cbiAgaWYgKChzdHJpbmcubGVuZ3RoID4gMCAmJiAobGVuZ3RoIDwgMCB8fCBvZmZzZXQgPCAwKSkgfHwgb2Zmc2V0ID4gdGhpcy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignYXR0ZW1wdCB0byB3cml0ZSBvdXRzaWRlIGJ1ZmZlciBib3VuZHMnKVxuICB9XG5cbiAgaWYgKCFlbmNvZGluZykgZW5jb2RpbmcgPSAndXRmOCdcblxuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuICBmb3IgKDs7KSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGhleFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgICAgcmV0dXJuIGFzY2lpV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGJpbmFyeVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAgIC8vIFdhcm5pbmc6IG1heExlbmd0aCBub3QgdGFrZW4gaW50byBhY2NvdW50IGluIGJhc2U2NFdyaXRlXG4gICAgICAgIHJldHVybiBiYXNlNjRXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gdWNzMldyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgICAgICBlbmNvZGluZyA9ICgnJyArIGVuY29kaW5nKS50b0xvd2VyQ2FzZSgpXG4gICAgICAgIGxvd2VyZWRDYXNlID0gdHJ1ZVxuICAgIH1cbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnRvSlNPTiA9IGZ1bmN0aW9uIHRvSlNPTiAoKSB7XG4gIHJldHVybiB7XG4gICAgdHlwZTogJ0J1ZmZlcicsXG4gICAgZGF0YTogQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodGhpcy5fYXJyIHx8IHRoaXMsIDApXG4gIH1cbn1cblxuZnVuY3Rpb24gYmFzZTY0U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICBpZiAoc3RhcnQgPT09IDAgJiYgZW5kID09PSBidWYubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGJhc2U2NC5mcm9tQnl0ZUFycmF5KGJ1ZilcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmLnNsaWNlKHN0YXJ0LCBlbmQpKVxuICB9XG59XG5cbmZ1bmN0aW9uIHV0ZjhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcbiAgdmFyIHJlcyA9IFtdXG5cbiAgdmFyIGkgPSBzdGFydFxuICB3aGlsZSAoaSA8IGVuZCkge1xuICAgIHZhciBmaXJzdEJ5dGUgPSBidWZbaV1cbiAgICB2YXIgY29kZVBvaW50ID0gbnVsbFxuICAgIHZhciBieXRlc1BlclNlcXVlbmNlID0gKGZpcnN0Qnl0ZSA+IDB4RUYpID8gNFxuICAgICAgOiAoZmlyc3RCeXRlID4gMHhERikgPyAzXG4gICAgICA6IChmaXJzdEJ5dGUgPiAweEJGKSA/IDJcbiAgICAgIDogMVxuXG4gICAgaWYgKGkgKyBieXRlc1BlclNlcXVlbmNlIDw9IGVuZCkge1xuICAgICAgdmFyIHNlY29uZEJ5dGUsIHRoaXJkQnl0ZSwgZm91cnRoQnl0ZSwgdGVtcENvZGVQb2ludFxuXG4gICAgICBzd2l0Y2ggKGJ5dGVzUGVyU2VxdWVuY2UpIHtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICAgIGlmIChmaXJzdEJ5dGUgPCAweDgwKSB7XG4gICAgICAgICAgICBjb2RlUG9pbnQgPSBmaXJzdEJ5dGVcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHgxRikgPDwgMHg2IHwgKHNlY29uZEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweDdGKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGlmICgoc2Vjb25kQnl0ZSAmIDB4QzApID09PSAweDgwICYmICh0aGlyZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweEYpIDw8IDB4QyB8IChzZWNvbmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKHRoaXJkQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4N0ZGICYmICh0ZW1wQ29kZVBvaW50IDwgMHhEODAwIHx8IHRlbXBDb2RlUG9pbnQgPiAweERGRkYpKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIHNlY29uZEJ5dGUgPSBidWZbaSArIDFdXG4gICAgICAgICAgdGhpcmRCeXRlID0gYnVmW2kgKyAyXVxuICAgICAgICAgIGZvdXJ0aEJ5dGUgPSBidWZbaSArIDNdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKHRoaXJkQnl0ZSAmIDB4QzApID09PSAweDgwICYmIChmb3VydGhCeXRlICYgMHhDMCkgPT09IDB4ODApIHtcbiAgICAgICAgICAgIHRlbXBDb2RlUG9pbnQgPSAoZmlyc3RCeXRlICYgMHhGKSA8PCAweDEyIHwgKHNlY29uZEJ5dGUgJiAweDNGKSA8PCAweEMgfCAodGhpcmRCeXRlICYgMHgzRikgPDwgMHg2IHwgKGZvdXJ0aEJ5dGUgJiAweDNGKVxuICAgICAgICAgICAgaWYgKHRlbXBDb2RlUG9pbnQgPiAweEZGRkYgJiYgdGVtcENvZGVQb2ludCA8IDB4MTEwMDAwKSB7XG4gICAgICAgICAgICAgIGNvZGVQb2ludCA9IHRlbXBDb2RlUG9pbnRcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKGNvZGVQb2ludCA9PT0gbnVsbCkge1xuICAgICAgLy8gd2UgZGlkIG5vdCBnZW5lcmF0ZSBhIHZhbGlkIGNvZGVQb2ludCBzbyBpbnNlcnQgYVxuICAgICAgLy8gcmVwbGFjZW1lbnQgY2hhciAoVStGRkZEKSBhbmQgYWR2YW5jZSBvbmx5IDEgYnl0ZVxuICAgICAgY29kZVBvaW50ID0gMHhGRkZEXG4gICAgICBieXRlc1BlclNlcXVlbmNlID0gMVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50ID4gMHhGRkZGKSB7XG4gICAgICAvLyBlbmNvZGUgdG8gdXRmMTYgKHN1cnJvZ2F0ZSBwYWlyIGRhbmNlKVxuICAgICAgY29kZVBvaW50IC09IDB4MTAwMDBcbiAgICAgIHJlcy5wdXNoKGNvZGVQb2ludCA+Pj4gMTAgJiAweDNGRiB8IDB4RDgwMClcbiAgICAgIGNvZGVQb2ludCA9IDB4REMwMCB8IGNvZGVQb2ludCAmIDB4M0ZGXG4gICAgfVxuXG4gICAgcmVzLnB1c2goY29kZVBvaW50KVxuICAgIGkgKz0gYnl0ZXNQZXJTZXF1ZW5jZVxuICB9XG5cbiAgcmV0dXJuIGRlY29kZUNvZGVQb2ludHNBcnJheShyZXMpXG59XG5cbi8vIEJhc2VkIG9uIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzIyNzQ3MjcyLzY4MDc0MiwgdGhlIGJyb3dzZXIgd2l0aFxuLy8gdGhlIGxvd2VzdCBsaW1pdCBpcyBDaHJvbWUsIHdpdGggMHgxMDAwMCBhcmdzLlxuLy8gV2UgZ28gMSBtYWduaXR1ZGUgbGVzcywgZm9yIHNhZmV0eVxudmFyIE1BWF9BUkdVTUVOVFNfTEVOR1RIID0gMHgxMDAwXG5cbmZ1bmN0aW9uIGRlY29kZUNvZGVQb2ludHNBcnJheSAoY29kZVBvaW50cykge1xuICB2YXIgbGVuID0gY29kZVBvaW50cy5sZW5ndGhcbiAgaWYgKGxlbiA8PSBNQVhfQVJHVU1FTlRTX0xFTkdUSCkge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY29kZVBvaW50cykgLy8gYXZvaWQgZXh0cmEgc2xpY2UoKVxuICB9XG5cbiAgLy8gRGVjb2RlIGluIGNodW5rcyB0byBhdm9pZCBcImNhbGwgc3RhY2sgc2l6ZSBleGNlZWRlZFwiLlxuICB2YXIgcmVzID0gJydcbiAgdmFyIGkgPSAwXG4gIHdoaWxlIChpIDwgbGVuKSB7XG4gICAgcmVzICs9IFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoXG4gICAgICBTdHJpbmcsXG4gICAgICBjb2RlUG9pbnRzLnNsaWNlKGksIGkgKz0gTUFYX0FSR1VNRU5UU19MRU5HVEgpXG4gICAgKVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuZnVuY3Rpb24gYXNjaWlTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpKyspIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0gJiAweDdGKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gYmluYXJ5U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgcmV0ID0gJydcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgcmV0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoYnVmW2ldKVxuICB9XG4gIHJldHVybiByZXRcbn1cblxuZnVuY3Rpb24gaGV4U2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgbGVuID0gYnVmLmxlbmd0aFxuXG4gIGlmICghc3RhcnQgfHwgc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgfHwgZW5kIDwgMCB8fCBlbmQgPiBsZW4pIGVuZCA9IGxlblxuXG4gIHZhciBvdXQgPSAnJ1xuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgIG91dCArPSB0b0hleChidWZbaV0pXG4gIH1cbiAgcmV0dXJuIG91dFxufVxuXG5mdW5jdGlvbiB1dGYxNmxlU2xpY2UgKGJ1Ziwgc3RhcnQsIGVuZCkge1xuICB2YXIgYnl0ZXMgPSBidWYuc2xpY2Uoc3RhcnQsIGVuZClcbiAgdmFyIHJlcyA9ICcnXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpICs9IDIpIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShieXRlc1tpXSArIGJ5dGVzW2kgKyAxXSAqIDI1NilcbiAgfVxuICByZXR1cm4gcmVzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuc2xpY2UgPSBmdW5jdGlvbiBzbGljZSAoc3RhcnQsIGVuZCkge1xuICB2YXIgbGVuID0gdGhpcy5sZW5ndGhcbiAgc3RhcnQgPSB+fnN0YXJ0XG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkID8gbGVuIDogfn5lbmRcblxuICBpZiAoc3RhcnQgPCAwKSB7XG4gICAgc3RhcnQgKz0gbGVuXG4gICAgaWYgKHN0YXJ0IDwgMCkgc3RhcnQgPSAwXG4gIH0gZWxzZSBpZiAoc3RhcnQgPiBsZW4pIHtcbiAgICBzdGFydCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IDApIHtcbiAgICBlbmQgKz0gbGVuXG4gICAgaWYgKGVuZCA8IDApIGVuZCA9IDBcbiAgfSBlbHNlIGlmIChlbmQgPiBsZW4pIHtcbiAgICBlbmQgPSBsZW5cbiAgfVxuXG4gIGlmIChlbmQgPCBzdGFydCkgZW5kID0gc3RhcnRcblxuICB2YXIgbmV3QnVmXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIG5ld0J1ZiA9IEJ1ZmZlci5fYXVnbWVudCh0aGlzLnN1YmFycmF5KHN0YXJ0LCBlbmQpKVxuICB9IGVsc2Uge1xuICAgIHZhciBzbGljZUxlbiA9IGVuZCAtIHN0YXJ0XG4gICAgbmV3QnVmID0gbmV3IEJ1ZmZlcihzbGljZUxlbiwgdW5kZWZpbmVkKVxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2xpY2VMZW47IGkrKykge1xuICAgICAgbmV3QnVmW2ldID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9XG5cbiAgaWYgKG5ld0J1Zi5sZW5ndGgpIG5ld0J1Zi5wYXJlbnQgPSB0aGlzLnBhcmVudCB8fCB0aGlzXG5cbiAgcmV0dXJuIG5ld0J1ZlxufVxuXG4vKlxuICogTmVlZCB0byBtYWtlIHN1cmUgdGhhdCBidWZmZXIgaXNuJ3QgdHJ5aW5nIHRvIHdyaXRlIG91dCBvZiBib3VuZHMuXG4gKi9cbmZ1bmN0aW9uIGNoZWNrT2Zmc2V0IChvZmZzZXQsIGV4dCwgbGVuZ3RoKSB7XG4gIGlmICgob2Zmc2V0ICUgMSkgIT09IDAgfHwgb2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ29mZnNldCBpcyBub3QgdWludCcpXG4gIGlmIChvZmZzZXQgKyBleHQgPiBsZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdUcnlpbmcgdG8gYWNjZXNzIGJleW9uZCBidWZmZXIgbGVuZ3RoJylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludExFID0gZnVuY3Rpb24gcmVhZFVJbnRMRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF1cbiAgdmFyIG11bCA9IDFcbiAgdmFyIGkgPSAwXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcbiAgfVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludEJFID0gZnVuY3Rpb24gcmVhZFVJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcbiAgfVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldCArIC0tYnl0ZUxlbmd0aF1cbiAgdmFyIG11bCA9IDFcbiAgd2hpbGUgKGJ5dGVMZW5ndGggPiAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50OCA9IGZ1bmN0aW9uIHJlYWRVSW50OCAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDEsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gdGhpc1tvZmZzZXRdXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkxFID0gZnVuY3Rpb24gcmVhZFVJbnQxNkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiB0aGlzW29mZnNldF0gfCAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MTZCRSA9IGZ1bmN0aW9uIHJlYWRVSW50MTZCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCA4KSB8IHRoaXNbb2Zmc2V0ICsgMV1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyTEUgPSBmdW5jdGlvbiByZWFkVUludDMyTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKCh0aGlzW29mZnNldF0pIHxcbiAgICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAgICh0aGlzW29mZnNldCArIDJdIDw8IDE2KSkgK1xuICAgICAgKHRoaXNbb2Zmc2V0ICsgM10gKiAweDEwMDAwMDApXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQzMkJFID0gZnVuY3Rpb24gcmVhZFVJbnQzMkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gKiAweDEwMDAwMDApICtcbiAgICAoKHRoaXNbb2Zmc2V0ICsgMV0gPDwgMTYpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCA4KSB8XG4gICAgdGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50TEUgPSBmdW5jdGlvbiByZWFkSW50TEUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB3aGlsZSAoKytpIDwgYnl0ZUxlbmd0aCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIGldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50QkUgPSBmdW5jdGlvbiByZWFkSW50QkUgKG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCBieXRlTGVuZ3RoLCB0aGlzLmxlbmd0aClcblxuICB2YXIgaSA9IGJ5dGVMZW5ndGhcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1pXVxuICB3aGlsZSAoaSA+IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWldICogbXVsXG4gIH1cbiAgbXVsICo9IDB4ODBcblxuICBpZiAodmFsID49IG11bCkgdmFsIC09IE1hdGgucG93KDIsIDggKiBieXRlTGVuZ3RoKVxuXG4gIHJldHVybiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50OCA9IGZ1bmN0aW9uIHJlYWRJbnQ4IChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMSwgdGhpcy5sZW5ndGgpXG4gIGlmICghKHRoaXNbb2Zmc2V0XSAmIDB4ODApKSByZXR1cm4gKHRoaXNbb2Zmc2V0XSlcbiAgcmV0dXJuICgoMHhmZiAtIHRoaXNbb2Zmc2V0XSArIDEpICogLTEpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2TEUgPSBmdW5jdGlvbiByZWFkSW50MTZMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXRdIHwgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOClcbiAgcmV0dXJuICh2YWwgJiAweDgwMDApID8gdmFsIHwgMHhGRkZGMDAwMCA6IHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQxNkJFID0gZnVuY3Rpb24gcmVhZEludDE2QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgMV0gfCAodGhpc1tvZmZzZXRdIDw8IDgpXG4gIHJldHVybiAodmFsICYgMHg4MDAwKSA/IHZhbCB8IDB4RkZGRjAwMDAgOiB2YWxcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJMRSA9IGZ1bmN0aW9uIHJlYWRJbnQzMkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0pIHxcbiAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgMTYpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAzXSA8PCAyNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MzJCRSA9IGZ1bmN0aW9uIHJlYWRJbnQzMkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG5cbiAgcmV0dXJuICh0aGlzW29mZnNldF0gPDwgMjQpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAzXSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRMRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdExFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRmxvYXRCRSA9IGZ1bmN0aW9uIHJlYWRGbG9hdEJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgNCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCBmYWxzZSwgMjMsIDQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZERvdWJsZUxFID0gZnVuY3Rpb24gcmVhZERvdWJsZUxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgOCwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiBpZWVlNzU0LnJlYWQodGhpcywgb2Zmc2V0LCB0cnVlLCA1MiwgOClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlQkUgPSBmdW5jdGlvbiByZWFkRG91YmxlQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCA1MiwgOClcbn1cblxuZnVuY3Rpb24gY2hlY2tJbnQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihidWYpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdidWZmZXIgbXVzdCBiZSBhIEJ1ZmZlciBpbnN0YW5jZScpXG4gIGlmICh2YWx1ZSA+IG1heCB8fCB2YWx1ZSA8IG1pbikgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3ZhbHVlIGlzIG91dCBvZiBib3VuZHMnKVxuICBpZiAob2Zmc2V0ICsgZXh0ID4gYnVmLmxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpLCAwKVxuXG4gIHZhciBtdWwgPSAxXG4gIHZhciBpID0gMFxuICB0aGlzW29mZnNldF0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50QkUgPSBmdW5jdGlvbiB3cml0ZVVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpLCAwKVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aCAtIDFcbiAgdmFyIG11bCA9IDFcbiAgdGhpc1tvZmZzZXQgKyBpXSA9IHZhbHVlICYgMHhGRlxuICB3aGlsZSAoLS1pID49IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB0aGlzW29mZnNldCArIGldID0gKHZhbHVlIC8gbXVsKSAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50OCA9IGZ1bmN0aW9uIHdyaXRlVUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHhmZiwgMClcbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkgdmFsdWUgPSBNYXRoLmZsb29yKHZhbHVlKVxuICB0aGlzW29mZnNldF0gPSB2YWx1ZVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5mdW5jdGlvbiBvYmplY3RXcml0ZVVJbnQxNiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4pIHtcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmYgKyB2YWx1ZSArIDFcbiAgZm9yICh2YXIgaSA9IDAsIGogPSBNYXRoLm1pbihidWYubGVuZ3RoIC0gb2Zmc2V0LCAyKTsgaSA8IGo7IGkrKykge1xuICAgIGJ1ZltvZmZzZXQgKyBpXSA9ICh2YWx1ZSAmICgweGZmIDw8ICg4ICogKGxpdHRsZUVuZGlhbiA/IGkgOiAxIC0gaSkpKSkgPj4+XG4gICAgICAobGl0dGxlRW5kaWFuID8gaSA6IDEgLSBpKSAqIDhcbiAgfVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDE2TEUgPSBmdW5jdGlvbiB3cml0ZVVJbnQxNkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4ZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gdmFsdWVcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkJFID0gZnVuY3Rpb24gd3JpdGVVSW50MTZCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDFdID0gdmFsdWVcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgMlxufVxuXG5mdW5jdGlvbiBvYmplY3RXcml0ZVVJbnQzMiAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4pIHtcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIGZvciAodmFyIGkgPSAwLCBqID0gTWF0aC5taW4oYnVmLmxlbmd0aCAtIG9mZnNldCwgNCk7IGkgPCBqOyBpKyspIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSAodmFsdWUgPj4+IChsaXR0bGVFbmRpYW4gPyBpIDogMyAtIGkpICogOCkgJiAweGZmXG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0XSA9IHZhbHVlXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDMyQkUgPSBmdW5jdGlvbiB3cml0ZVVJbnQzMkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4ZmZmZmZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDNdID0gdmFsdWVcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50TEUgPSBmdW5jdGlvbiB3cml0ZUludExFICh2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbGltaXQgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCAtIDEpXG5cbiAgICBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBieXRlTGVuZ3RoLCBsaW1pdCAtIDEsIC1saW1pdClcbiAgfVxuXG4gIHZhciBpID0gMFxuICB2YXIgbXVsID0gMVxuICB2YXIgc3ViID0gdmFsdWUgPCAwID8gMSA6IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludEJFID0gZnVuY3Rpb24gd3JpdGVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIGxpbWl0ID0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGggLSAxKVxuXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbGltaXQgLSAxLCAtbGltaXQpXG4gIH1cblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSB2YWx1ZSA8IDAgPyAxIDogMFxuICB0aGlzW29mZnNldCArIGldID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgtLWkgPj0gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHRoaXNbb2Zmc2V0ICsgaV0gPSAoKHZhbHVlIC8gbXVsKSA+PiAwKSAtIHN1YiAmIDB4RkZcbiAgfVxuXG4gIHJldHVybiBvZmZzZXQgKyBieXRlTGVuZ3RoXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQ4ID0gZnVuY3Rpb24gd3JpdGVJbnQ4ICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDEsIDB4N2YsIC0weDgwKVxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB2YWx1ZSA9IE1hdGguZmxvb3IodmFsdWUpXG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZiArIHZhbHVlICsgMVxuICB0aGlzW29mZnNldF0gPSB2YWx1ZVxuICByZXR1cm4gb2Zmc2V0ICsgMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MTZMRSA9IGZ1bmN0aW9uIHdyaXRlSW50MTZMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweDdmZmYsIC0weDgwMDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9IHZhbHVlXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkJFID0gZnVuY3Rpb24gd3JpdGVJbnQxNkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSB2YWx1ZVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkxFID0gZnVuY3Rpb24gd3JpdGVJbnQzMkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSB2YWx1ZVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSA+Pj4gMjQpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlSW50MzJCRSA9IGZ1bmN0aW9uIHdyaXRlSW50MzJCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweDdmZmZmZmZmLCAtMHg4MDAwMDAwMClcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmZmZmZmZmICsgdmFsdWUgKyAxXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDNdID0gdmFsdWVcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSlcbiAgfVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5mdW5jdGlvbiBjaGVja0lFRUU3NTQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgZXh0LCBtYXgsIG1pbikge1xuICBpZiAodmFsdWUgPiBtYXggfHwgdmFsdWUgPCBtaW4pIHRocm93IG5ldyBSYW5nZUVycm9yKCd2YWx1ZSBpcyBvdXQgb2YgYm91bmRzJylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGJ1Zi5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdpbmRleCBvdXQgb2YgcmFuZ2UnKVxuICBpZiAob2Zmc2V0IDwgMCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2luZGV4IG91dCBvZiByYW5nZScpXG59XG5cbmZ1bmN0aW9uIHdyaXRlRmxvYXQgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgNCwgMy40MDI4MjM0NjYzODUyODg2ZSszOCwgLTMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgpXG4gIH1cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgMjMsIDQpXG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdExFID0gZnVuY3Rpb24gd3JpdGVGbG9hdExFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUZsb2F0QkUgPSBmdW5jdGlvbiB3cml0ZUZsb2F0QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZUZsb2F0KHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuZnVuY3Rpb24gd3JpdGVEb3VibGUgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgY2hlY2tJRUVFNzU0KGJ1ZiwgdmFsdWUsIG9mZnNldCwgOCwgMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgsIC0xLjc5NzY5MzEzNDg2MjMxNTdFKzMwOClcbiAgfVxuICBpZWVlNzU0LndyaXRlKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuLCA1MiwgOClcbiAgcmV0dXJuIG9mZnNldCArIDhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUxFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUsIG5vQXNzZXJ0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRG91YmxlQkUgPSBmdW5jdGlvbiB3cml0ZURvdWJsZUJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVEb3VibGUodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UsIG5vQXNzZXJ0KVxufVxuXG4vLyBjb3B5KHRhcmdldEJ1ZmZlciwgdGFyZ2V0U3RhcnQ9MCwgc291cmNlU3RhcnQ9MCwgc291cmNlRW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbiBjb3B5ICh0YXJnZXQsIHRhcmdldFN0YXJ0LCBzdGFydCwgZW5kKSB7XG4gIGlmICghc3RhcnQpIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCAmJiBlbmQgIT09IDApIGVuZCA9IHRoaXMubGVuZ3RoXG4gIGlmICh0YXJnZXRTdGFydCA+PSB0YXJnZXQubGVuZ3RoKSB0YXJnZXRTdGFydCA9IHRhcmdldC5sZW5ndGhcbiAgaWYgKCF0YXJnZXRTdGFydCkgdGFyZ2V0U3RhcnQgPSAwXG4gIGlmIChlbmQgPiAwICYmIGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIC8vIENvcHkgMCBieXRlczsgd2UncmUgZG9uZVxuICBpZiAoZW5kID09PSBzdGFydCkgcmV0dXJuIDBcbiAgaWYgKHRhcmdldC5sZW5ndGggPT09IDAgfHwgdGhpcy5sZW5ndGggPT09IDApIHJldHVybiAwXG5cbiAgLy8gRmF0YWwgZXJyb3IgY29uZGl0aW9uc1xuICBpZiAodGFyZ2V0U3RhcnQgPCAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ3RhcmdldFN0YXJ0IG91dCBvZiBib3VuZHMnKVxuICB9XG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgaWYgKGVuZCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdzb3VyY2VFbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgLy8gQXJlIHdlIG9vYj9cbiAgaWYgKGVuZCA+IHRoaXMubGVuZ3RoKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0Lmxlbmd0aCAtIHRhcmdldFN0YXJ0IDwgZW5kIC0gc3RhcnQpIHtcbiAgICBlbmQgPSB0YXJnZXQubGVuZ3RoIC0gdGFyZ2V0U3RhcnQgKyBzdGFydFxuICB9XG5cbiAgdmFyIGxlbiA9IGVuZCAtIHN0YXJ0XG4gIHZhciBpXG5cbiAgaWYgKHRoaXMgPT09IHRhcmdldCAmJiBzdGFydCA8IHRhcmdldFN0YXJ0ICYmIHRhcmdldFN0YXJ0IDwgZW5kKSB7XG4gICAgLy8gZGVzY2VuZGluZyBjb3B5IGZyb20gZW5kXG4gICAgZm9yIChpID0gbGVuIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgIHRhcmdldFtpICsgdGFyZ2V0U3RhcnRdID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9IGVsc2UgaWYgKGxlbiA8IDEwMDAgfHwgIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgLy8gYXNjZW5kaW5nIGNvcHkgZnJvbSBzdGFydFxuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgdGFyZ2V0W2kgKyB0YXJnZXRTdGFydF0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGFyZ2V0Ll9zZXQodGhpcy5zdWJhcnJheShzdGFydCwgc3RhcnQgKyBsZW4pLCB0YXJnZXRTdGFydClcbiAgfVxuXG4gIHJldHVybiBsZW5cbn1cblxuLy8gZmlsbCh2YWx1ZSwgc3RhcnQ9MCwgZW5kPWJ1ZmZlci5sZW5ndGgpXG5CdWZmZXIucHJvdG90eXBlLmZpbGwgPSBmdW5jdGlvbiBmaWxsICh2YWx1ZSwgc3RhcnQsIGVuZCkge1xuICBpZiAoIXZhbHVlKSB2YWx1ZSA9IDBcbiAgaWYgKCFzdGFydCkgc3RhcnQgPSAwXG4gIGlmICghZW5kKSBlbmQgPSB0aGlzLmxlbmd0aFxuXG4gIGlmIChlbmQgPCBzdGFydCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ2VuZCA8IHN0YXJ0JylcblxuICAvLyBGaWxsIDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVyblxuICBpZiAodGhpcy5sZW5ndGggPT09IDApIHJldHVyblxuXG4gIGlmIChzdGFydCA8IDAgfHwgc3RhcnQgPj0gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdzdGFydCBvdXQgb2YgYm91bmRzJylcbiAgaWYgKGVuZCA8IDAgfHwgZW5kID4gdGhpcy5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdlbmQgb3V0IG9mIGJvdW5kcycpXG5cbiAgdmFyIGlcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICBmb3IgKGkgPSBzdGFydDsgaSA8IGVuZDsgaSsrKSB7XG4gICAgICB0aGlzW2ldID0gdmFsdWVcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFyIGJ5dGVzID0gdXRmOFRvQnl0ZXModmFsdWUudG9TdHJpbmcoKSlcbiAgICB2YXIgbGVuID0gYnl0ZXMubGVuZ3RoXG4gICAgZm9yIChpID0gc3RhcnQ7IGkgPCBlbmQ7IGkrKykge1xuICAgICAgdGhpc1tpXSA9IGJ5dGVzW2kgJSBsZW5dXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXNcbn1cblxuLyoqXG4gKiBDcmVhdGVzIGEgbmV3IGBBcnJheUJ1ZmZlcmAgd2l0aCB0aGUgKmNvcGllZCogbWVtb3J5IG9mIHRoZSBidWZmZXIgaW5zdGFuY2UuXG4gKiBBZGRlZCBpbiBOb2RlIDAuMTIuIE9ubHkgYXZhaWxhYmxlIGluIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBBcnJheUJ1ZmZlci5cbiAqL1xuQnVmZmVyLnByb3RvdHlwZS50b0FycmF5QnVmZmVyID0gZnVuY3Rpb24gdG9BcnJheUJ1ZmZlciAoKSB7XG4gIGlmICh0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICAgIHJldHVybiAobmV3IEJ1ZmZlcih0aGlzKSkuYnVmZmVyXG4gICAgfSBlbHNlIHtcbiAgICAgIHZhciBidWYgPSBuZXcgVWludDhBcnJheSh0aGlzLmxlbmd0aClcbiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBidWYubGVuZ3RoOyBpIDwgbGVuOyBpICs9IDEpIHtcbiAgICAgICAgYnVmW2ldID0gdGhpc1tpXVxuICAgICAgfVxuICAgICAgcmV0dXJuIGJ1Zi5idWZmZXJcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQnVmZmVyLnRvQXJyYXlCdWZmZXIgbm90IHN1cHBvcnRlZCBpbiB0aGlzIGJyb3dzZXInKVxuICB9XG59XG5cbi8vIEhFTFBFUiBGVU5DVElPTlNcbi8vID09PT09PT09PT09PT09PT1cblxudmFyIEJQID0gQnVmZmVyLnByb3RvdHlwZVxuXG4vKipcbiAqIEF1Z21lbnQgYSBVaW50OEFycmF5ICppbnN0YW5jZSogKG5vdCB0aGUgVWludDhBcnJheSBjbGFzcyEpIHdpdGggQnVmZmVyIG1ldGhvZHNcbiAqL1xuQnVmZmVyLl9hdWdtZW50ID0gZnVuY3Rpb24gX2F1Z21lbnQgKGFycikge1xuICBhcnIuY29uc3RydWN0b3IgPSBCdWZmZXJcbiAgYXJyLl9pc0J1ZmZlciA9IHRydWVcblxuICAvLyBzYXZlIHJlZmVyZW5jZSB0byBvcmlnaW5hbCBVaW50OEFycmF5IHNldCBtZXRob2QgYmVmb3JlIG92ZXJ3cml0aW5nXG4gIGFyci5fc2V0ID0gYXJyLnNldFxuXG4gIC8vIGRlcHJlY2F0ZWRcbiAgYXJyLmdldCA9IEJQLmdldFxuICBhcnIuc2V0ID0gQlAuc2V0XG5cbiAgYXJyLndyaXRlID0gQlAud3JpdGVcbiAgYXJyLnRvU3RyaW5nID0gQlAudG9TdHJpbmdcbiAgYXJyLnRvTG9jYWxlU3RyaW5nID0gQlAudG9TdHJpbmdcbiAgYXJyLnRvSlNPTiA9IEJQLnRvSlNPTlxuICBhcnIuZXF1YWxzID0gQlAuZXF1YWxzXG4gIGFyci5jb21wYXJlID0gQlAuY29tcGFyZVxuICBhcnIuaW5kZXhPZiA9IEJQLmluZGV4T2ZcbiAgYXJyLmNvcHkgPSBCUC5jb3B5XG4gIGFyci5zbGljZSA9IEJQLnNsaWNlXG4gIGFyci5yZWFkVUludExFID0gQlAucmVhZFVJbnRMRVxuICBhcnIucmVhZFVJbnRCRSA9IEJQLnJlYWRVSW50QkVcbiAgYXJyLnJlYWRVSW50OCA9IEJQLnJlYWRVSW50OFxuICBhcnIucmVhZFVJbnQxNkxFID0gQlAucmVhZFVJbnQxNkxFXG4gIGFyci5yZWFkVUludDE2QkUgPSBCUC5yZWFkVUludDE2QkVcbiAgYXJyLnJlYWRVSW50MzJMRSA9IEJQLnJlYWRVSW50MzJMRVxuICBhcnIucmVhZFVJbnQzMkJFID0gQlAucmVhZFVJbnQzMkJFXG4gIGFyci5yZWFkSW50TEUgPSBCUC5yZWFkSW50TEVcbiAgYXJyLnJlYWRJbnRCRSA9IEJQLnJlYWRJbnRCRVxuICBhcnIucmVhZEludDggPSBCUC5yZWFkSW50OFxuICBhcnIucmVhZEludDE2TEUgPSBCUC5yZWFkSW50MTZMRVxuICBhcnIucmVhZEludDE2QkUgPSBCUC5yZWFkSW50MTZCRVxuICBhcnIucmVhZEludDMyTEUgPSBCUC5yZWFkSW50MzJMRVxuICBhcnIucmVhZEludDMyQkUgPSBCUC5yZWFkSW50MzJCRVxuICBhcnIucmVhZEZsb2F0TEUgPSBCUC5yZWFkRmxvYXRMRVxuICBhcnIucmVhZEZsb2F0QkUgPSBCUC5yZWFkRmxvYXRCRVxuICBhcnIucmVhZERvdWJsZUxFID0gQlAucmVhZERvdWJsZUxFXG4gIGFyci5yZWFkRG91YmxlQkUgPSBCUC5yZWFkRG91YmxlQkVcbiAgYXJyLndyaXRlVUludDggPSBCUC53cml0ZVVJbnQ4XG4gIGFyci53cml0ZVVJbnRMRSA9IEJQLndyaXRlVUludExFXG4gIGFyci53cml0ZVVJbnRCRSA9IEJQLndyaXRlVUludEJFXG4gIGFyci53cml0ZVVJbnQxNkxFID0gQlAud3JpdGVVSW50MTZMRVxuICBhcnIud3JpdGVVSW50MTZCRSA9IEJQLndyaXRlVUludDE2QkVcbiAgYXJyLndyaXRlVUludDMyTEUgPSBCUC53cml0ZVVJbnQzMkxFXG4gIGFyci53cml0ZVVJbnQzMkJFID0gQlAud3JpdGVVSW50MzJCRVxuICBhcnIud3JpdGVJbnRMRSA9IEJQLndyaXRlSW50TEVcbiAgYXJyLndyaXRlSW50QkUgPSBCUC53cml0ZUludEJFXG4gIGFyci53cml0ZUludDggPSBCUC53cml0ZUludDhcbiAgYXJyLndyaXRlSW50MTZMRSA9IEJQLndyaXRlSW50MTZMRVxuICBhcnIud3JpdGVJbnQxNkJFID0gQlAud3JpdGVJbnQxNkJFXG4gIGFyci53cml0ZUludDMyTEUgPSBCUC53cml0ZUludDMyTEVcbiAgYXJyLndyaXRlSW50MzJCRSA9IEJQLndyaXRlSW50MzJCRVxuICBhcnIud3JpdGVGbG9hdExFID0gQlAud3JpdGVGbG9hdExFXG4gIGFyci53cml0ZUZsb2F0QkUgPSBCUC53cml0ZUZsb2F0QkVcbiAgYXJyLndyaXRlRG91YmxlTEUgPSBCUC53cml0ZURvdWJsZUxFXG4gIGFyci53cml0ZURvdWJsZUJFID0gQlAud3JpdGVEb3VibGVCRVxuICBhcnIuZmlsbCA9IEJQLmZpbGxcbiAgYXJyLmluc3BlY3QgPSBCUC5pbnNwZWN0XG4gIGFyci50b0FycmF5QnVmZmVyID0gQlAudG9BcnJheUJ1ZmZlclxuXG4gIHJldHVybiBhcnJcbn1cblxudmFyIElOVkFMSURfQkFTRTY0X1JFID0gL1teK1xcLzAtOUEtWmEtei1fXS9nXG5cbmZ1bmN0aW9uIGJhc2U2NGNsZWFuIChzdHIpIHtcbiAgLy8gTm9kZSBzdHJpcHMgb3V0IGludmFsaWQgY2hhcmFjdGVycyBsaWtlIFxcbiBhbmQgXFx0IGZyb20gdGhlIHN0cmluZywgYmFzZTY0LWpzIGRvZXMgbm90XG4gIHN0ciA9IHN0cmluZ3RyaW0oc3RyKS5yZXBsYWNlKElOVkFMSURfQkFTRTY0X1JFLCAnJylcbiAgLy8gTm9kZSBjb252ZXJ0cyBzdHJpbmdzIHdpdGggbGVuZ3RoIDwgMiB0byAnJ1xuICBpZiAoc3RyLmxlbmd0aCA8IDIpIHJldHVybiAnJ1xuICAvLyBOb2RlIGFsbG93cyBmb3Igbm9uLXBhZGRlZCBiYXNlNjQgc3RyaW5ncyAobWlzc2luZyB0cmFpbGluZyA9PT0pLCBiYXNlNjQtanMgZG9lcyBub3RcbiAgd2hpbGUgKHN0ci5sZW5ndGggJSA0ICE9PSAwKSB7XG4gICAgc3RyID0gc3RyICsgJz0nXG4gIH1cbiAgcmV0dXJuIHN0clxufVxuXG5mdW5jdGlvbiBzdHJpbmd0cmltIChzdHIpIHtcbiAgaWYgKHN0ci50cmltKSByZXR1cm4gc3RyLnRyaW0oKVxuICByZXR1cm4gc3RyLnJlcGxhY2UoL15cXHMrfFxccyskL2csICcnKVxufVxuXG5mdW5jdGlvbiB0b0hleCAobikge1xuICBpZiAobiA8IDE2KSByZXR1cm4gJzAnICsgbi50b1N0cmluZygxNilcbiAgcmV0dXJuIG4udG9TdHJpbmcoMTYpXG59XG5cbmZ1bmN0aW9uIHV0ZjhUb0J5dGVzIChzdHJpbmcsIHVuaXRzKSB7XG4gIHVuaXRzID0gdW5pdHMgfHwgSW5maW5pdHlcbiAgdmFyIGNvZGVQb2ludFxuICB2YXIgbGVuZ3RoID0gc3RyaW5nLmxlbmd0aFxuICB2YXIgbGVhZFN1cnJvZ2F0ZSA9IG51bGxcbiAgdmFyIGJ5dGVzID0gW11cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgY29kZVBvaW50ID0gc3RyaW5nLmNoYXJDb2RlQXQoaSlcblxuICAgIC8vIGlzIHN1cnJvZ2F0ZSBjb21wb25lbnRcbiAgICBpZiAoY29kZVBvaW50ID4gMHhEN0ZGICYmIGNvZGVQb2ludCA8IDB4RTAwMCkge1xuICAgICAgLy8gbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICghbGVhZFN1cnJvZ2F0ZSkge1xuICAgICAgICAvLyBubyBsZWFkIHlldFxuICAgICAgICBpZiAoY29kZVBvaW50ID4gMHhEQkZGKSB7XG4gICAgICAgICAgLy8gdW5leHBlY3RlZCB0cmFpbFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH0gZWxzZSBpZiAoaSArIDEgPT09IGxlbmd0aCkge1xuICAgICAgICAgIC8vIHVucGFpcmVkIGxlYWRcbiAgICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgICBjb250aW51ZVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gdmFsaWQgbGVhZFxuICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG5cbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgLy8gMiBsZWFkcyBpbiBhIHJvd1xuICAgICAgaWYgKGNvZGVQb2ludCA8IDB4REMwMCkge1xuICAgICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICAgICAgbGVhZFN1cnJvZ2F0ZSA9IGNvZGVQb2ludFxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvLyB2YWxpZCBzdXJyb2dhdGUgcGFpclxuICAgICAgY29kZVBvaW50ID0gbGVhZFN1cnJvZ2F0ZSAtIDB4RDgwMCA8PCAxMCB8IGNvZGVQb2ludCAtIDB4REMwMCB8IDB4MTAwMDBcbiAgICB9IGVsc2UgaWYgKGxlYWRTdXJyb2dhdGUpIHtcbiAgICAgIC8vIHZhbGlkIGJtcCBjaGFyLCBidXQgbGFzdCBjaGFyIHdhcyBhIGxlYWRcbiAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgIH1cblxuICAgIGxlYWRTdXJyb2dhdGUgPSBudWxsXG5cbiAgICAvLyBlbmNvZGUgdXRmOFxuICAgIGlmIChjb2RlUG9pbnQgPCAweDgwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDEpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goY29kZVBvaW50KVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHg4MDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiB8IDB4QzAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDEwMDAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDMpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgfCAweEUwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHg2ICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCAmIDB4M0YgfCAweDgwXG4gICAgICApXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPCAweDExMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSA0KSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHgxMiB8IDB4RjAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweEMgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29kZSBwb2ludCcpXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVzXG59XG5cbmZ1bmN0aW9uIGFzY2lpVG9CeXRlcyAoc3RyKSB7XG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkrKykge1xuICAgIC8vIE5vZGUncyBjb2RlIHNlZW1zIHRvIGJlIGRvaW5nIHRoaXMgYW5kIG5vdCAmIDB4N0YuLlxuICAgIGJ5dGVBcnJheS5wdXNoKHN0ci5jaGFyQ29kZUF0KGkpICYgMHhGRilcbiAgfVxuICByZXR1cm4gYnl0ZUFycmF5XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVUb0J5dGVzIChzdHIsIHVuaXRzKSB7XG4gIHZhciBjLCBoaSwgbG9cbiAgdmFyIGJ5dGVBcnJheSA9IFtdXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKCh1bml0cyAtPSAyKSA8IDApIGJyZWFrXG5cbiAgICBjID0gc3RyLmNoYXJDb2RlQXQoaSlcbiAgICBoaSA9IGMgPj4gOFxuICAgIGxvID0gYyAlIDI1NlxuICAgIGJ5dGVBcnJheS5wdXNoKGxvKVxuICAgIGJ5dGVBcnJheS5wdXNoKGhpKVxuICB9XG5cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiBiYXNlNjRUb0J5dGVzIChzdHIpIHtcbiAgcmV0dXJuIGJhc2U2NC50b0J5dGVBcnJheShiYXNlNjRjbGVhbihzdHIpKVxufVxuXG5mdW5jdGlvbiBibGl0QnVmZmVyIChzcmMsIGRzdCwgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgIGlmICgoaSArIG9mZnNldCA+PSBkc3QubGVuZ3RoKSB8fCAoaSA+PSBzcmMubGVuZ3RoKSkgYnJlYWtcbiAgICBkc3RbaSArIG9mZnNldF0gPSBzcmNbaV1cbiAgfVxuICByZXR1cm4gaVxufVxuIiwidmFyIGxvb2t1cCA9ICdBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWmFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6MDEyMzQ1Njc4OSsvJztcblxuOyhmdW5jdGlvbiAoZXhwb3J0cykge1xuXHQndXNlIHN0cmljdCc7XG5cbiAgdmFyIEFyciA9ICh0eXBlb2YgVWludDhBcnJheSAhPT0gJ3VuZGVmaW5lZCcpXG4gICAgPyBVaW50OEFycmF5XG4gICAgOiBBcnJheVxuXG5cdHZhciBQTFVTICAgPSAnKycuY2hhckNvZGVBdCgwKVxuXHR2YXIgU0xBU0ggID0gJy8nLmNoYXJDb2RlQXQoMClcblx0dmFyIE5VTUJFUiA9ICcwJy5jaGFyQ29kZUF0KDApXG5cdHZhciBMT1dFUiAgPSAnYScuY2hhckNvZGVBdCgwKVxuXHR2YXIgVVBQRVIgID0gJ0EnLmNoYXJDb2RlQXQoMClcblx0dmFyIFBMVVNfVVJMX1NBRkUgPSAnLScuY2hhckNvZGVBdCgwKVxuXHR2YXIgU0xBU0hfVVJMX1NBRkUgPSAnXycuY2hhckNvZGVBdCgwKVxuXG5cdGZ1bmN0aW9uIGRlY29kZSAoZWx0KSB7XG5cdFx0dmFyIGNvZGUgPSBlbHQuY2hhckNvZGVBdCgwKVxuXHRcdGlmIChjb2RlID09PSBQTFVTIHx8XG5cdFx0ICAgIGNvZGUgPT09IFBMVVNfVVJMX1NBRkUpXG5cdFx0XHRyZXR1cm4gNjIgLy8gJysnXG5cdFx0aWYgKGNvZGUgPT09IFNMQVNIIHx8XG5cdFx0ICAgIGNvZGUgPT09IFNMQVNIX1VSTF9TQUZFKVxuXHRcdFx0cmV0dXJuIDYzIC8vICcvJ1xuXHRcdGlmIChjb2RlIDwgTlVNQkVSKVxuXHRcdFx0cmV0dXJuIC0xIC8vbm8gbWF0Y2hcblx0XHRpZiAoY29kZSA8IE5VTUJFUiArIDEwKVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBOVU1CRVIgKyAyNiArIDI2XG5cdFx0aWYgKGNvZGUgPCBVUFBFUiArIDI2KVxuXHRcdFx0cmV0dXJuIGNvZGUgLSBVUFBFUlxuXHRcdGlmIChjb2RlIDwgTE9XRVIgKyAyNilcblx0XHRcdHJldHVybiBjb2RlIC0gTE9XRVIgKyAyNlxuXHR9XG5cblx0ZnVuY3Rpb24gYjY0VG9CeXRlQXJyYXkgKGI2NCkge1xuXHRcdHZhciBpLCBqLCBsLCB0bXAsIHBsYWNlSG9sZGVycywgYXJyXG5cblx0XHRpZiAoYjY0Lmxlbmd0aCAlIDQgPiAwKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQnKVxuXHRcdH1cblxuXHRcdC8vIHRoZSBudW1iZXIgb2YgZXF1YWwgc2lnbnMgKHBsYWNlIGhvbGRlcnMpXG5cdFx0Ly8gaWYgdGhlcmUgYXJlIHR3byBwbGFjZWhvbGRlcnMsIHRoYW4gdGhlIHR3byBjaGFyYWN0ZXJzIGJlZm9yZSBpdFxuXHRcdC8vIHJlcHJlc2VudCBvbmUgYnl0ZVxuXHRcdC8vIGlmIHRoZXJlIGlzIG9ubHkgb25lLCB0aGVuIHRoZSB0aHJlZSBjaGFyYWN0ZXJzIGJlZm9yZSBpdCByZXByZXNlbnQgMiBieXRlc1xuXHRcdC8vIHRoaXMgaXMganVzdCBhIGNoZWFwIGhhY2sgdG8gbm90IGRvIGluZGV4T2YgdHdpY2Vcblx0XHR2YXIgbGVuID0gYjY0Lmxlbmd0aFxuXHRcdHBsYWNlSG9sZGVycyA9ICc9JyA9PT0gYjY0LmNoYXJBdChsZW4gLSAyKSA/IDIgOiAnPScgPT09IGI2NC5jaGFyQXQobGVuIC0gMSkgPyAxIDogMFxuXG5cdFx0Ly8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXG5cdFx0YXJyID0gbmV3IEFycihiNjQubGVuZ3RoICogMyAvIDQgLSBwbGFjZUhvbGRlcnMpXG5cblx0XHQvLyBpZiB0aGVyZSBhcmUgcGxhY2Vob2xkZXJzLCBvbmx5IGdldCB1cCB0byB0aGUgbGFzdCBjb21wbGV0ZSA0IGNoYXJzXG5cdFx0bCA9IHBsYWNlSG9sZGVycyA+IDAgPyBiNjQubGVuZ3RoIC0gNCA6IGI2NC5sZW5ndGhcblxuXHRcdHZhciBMID0gMFxuXG5cdFx0ZnVuY3Rpb24gcHVzaCAodikge1xuXHRcdFx0YXJyW0wrK10gPSB2XG5cdFx0fVxuXG5cdFx0Zm9yIChpID0gMCwgaiA9IDA7IGkgPCBsOyBpICs9IDQsIGogKz0gMykge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAxOCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA8PCAxMikgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDIpKSA8PCA2KSB8IGRlY29kZShiNjQuY2hhckF0KGkgKyAzKSlcblx0XHRcdHB1c2goKHRtcCAmIDB4RkYwMDAwKSA+PiAxNilcblx0XHRcdHB1c2goKHRtcCAmIDB4RkYwMCkgPj4gOClcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9XG5cblx0XHRpZiAocGxhY2VIb2xkZXJzID09PSAyKSB7XG5cdFx0XHR0bXAgPSAoZGVjb2RlKGI2NC5jaGFyQXQoaSkpIDw8IDIpIHwgKGRlY29kZShiNjQuY2hhckF0KGkgKyAxKSkgPj4gNClcblx0XHRcdHB1c2godG1wICYgMHhGRilcblx0XHR9IGVsc2UgaWYgKHBsYWNlSG9sZGVycyA9PT0gMSkge1xuXHRcdFx0dG1wID0gKGRlY29kZShiNjQuY2hhckF0KGkpKSA8PCAxMCkgfCAoZGVjb2RlKGI2NC5jaGFyQXQoaSArIDEpKSA8PCA0KSB8IChkZWNvZGUoYjY0LmNoYXJBdChpICsgMikpID4+IDIpXG5cdFx0XHRwdXNoKCh0bXAgPj4gOCkgJiAweEZGKVxuXHRcdFx0cHVzaCh0bXAgJiAweEZGKVxuXHRcdH1cblxuXHRcdHJldHVybiBhcnJcblx0fVxuXG5cdGZ1bmN0aW9uIHVpbnQ4VG9CYXNlNjQgKHVpbnQ4KSB7XG5cdFx0dmFyIGksXG5cdFx0XHRleHRyYUJ5dGVzID0gdWludDgubGVuZ3RoICUgMywgLy8gaWYgd2UgaGF2ZSAxIGJ5dGUgbGVmdCwgcGFkIDIgYnl0ZXNcblx0XHRcdG91dHB1dCA9IFwiXCIsXG5cdFx0XHR0ZW1wLCBsZW5ndGhcblxuXHRcdGZ1bmN0aW9uIGVuY29kZSAobnVtKSB7XG5cdFx0XHRyZXR1cm4gbG9va3VwLmNoYXJBdChudW0pXG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gdHJpcGxldFRvQmFzZTY0IChudW0pIHtcblx0XHRcdHJldHVybiBlbmNvZGUobnVtID4+IDE4ICYgMHgzRikgKyBlbmNvZGUobnVtID4+IDEyICYgMHgzRikgKyBlbmNvZGUobnVtID4+IDYgJiAweDNGKSArIGVuY29kZShudW0gJiAweDNGKVxuXHRcdH1cblxuXHRcdC8vIGdvIHRocm91Z2ggdGhlIGFycmF5IGV2ZXJ5IHRocmVlIGJ5dGVzLCB3ZSdsbCBkZWFsIHdpdGggdHJhaWxpbmcgc3R1ZmYgbGF0ZXJcblx0XHRmb3IgKGkgPSAwLCBsZW5ndGggPSB1aW50OC5sZW5ndGggLSBleHRyYUJ5dGVzOyBpIDwgbGVuZ3RoOyBpICs9IDMpIHtcblx0XHRcdHRlbXAgPSAodWludDhbaV0gPDwgMTYpICsgKHVpbnQ4W2kgKyAxXSA8PCA4KSArICh1aW50OFtpICsgMl0pXG5cdFx0XHRvdXRwdXQgKz0gdHJpcGxldFRvQmFzZTY0KHRlbXApXG5cdFx0fVxuXG5cdFx0Ly8gcGFkIHRoZSBlbmQgd2l0aCB6ZXJvcywgYnV0IG1ha2Ugc3VyZSB0byBub3QgZm9yZ2V0IHRoZSBleHRyYSBieXRlc1xuXHRcdHN3aXRjaCAoZXh0cmFCeXRlcykge1xuXHRcdFx0Y2FzZSAxOlxuXHRcdFx0XHR0ZW1wID0gdWludDhbdWludDgubGVuZ3RoIC0gMV1cblx0XHRcdFx0b3V0cHV0ICs9IGVuY29kZSh0ZW1wID4+IDIpXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPDwgNCkgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gJz09J1xuXHRcdFx0XHRicmVha1xuXHRcdFx0Y2FzZSAyOlxuXHRcdFx0XHR0ZW1wID0gKHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDJdIDw8IDgpICsgKHVpbnQ4W3VpbnQ4Lmxlbmd0aCAtIDFdKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKHRlbXAgPj4gMTApXG5cdFx0XHRcdG91dHB1dCArPSBlbmNvZGUoKHRlbXAgPj4gNCkgJiAweDNGKVxuXHRcdFx0XHRvdXRwdXQgKz0gZW5jb2RlKCh0ZW1wIDw8IDIpICYgMHgzRilcblx0XHRcdFx0b3V0cHV0ICs9ICc9J1xuXHRcdFx0XHRicmVha1xuXHRcdH1cblxuXHRcdHJldHVybiBvdXRwdXRcblx0fVxuXG5cdGV4cG9ydHMudG9CeXRlQXJyYXkgPSBiNjRUb0J5dGVBcnJheVxuXHRleHBvcnRzLmZyb21CeXRlQXJyYXkgPSB1aW50OFRvQmFzZTY0XG59KHR5cGVvZiBleHBvcnRzID09PSAndW5kZWZpbmVkJyA/ICh0aGlzLmJhc2U2NGpzID0ge30pIDogZXhwb3J0cykpXG4iLCJleHBvcnRzLnJlYWQgPSBmdW5jdGlvbiAoYnVmZmVyLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbVxuICB2YXIgZUxlbiA9IG5CeXRlcyAqIDggLSBtTGVuIC0gMVxuICB2YXIgZU1heCA9ICgxIDw8IGVMZW4pIC0gMVxuICB2YXIgZUJpYXMgPSBlTWF4ID4+IDFcbiAgdmFyIG5CaXRzID0gLTdcbiAgdmFyIGkgPSBpc0xFID8gKG5CeXRlcyAtIDEpIDogMFxuICB2YXIgZCA9IGlzTEUgPyAtMSA6IDFcbiAgdmFyIHMgPSBidWZmZXJbb2Zmc2V0ICsgaV1cblxuICBpICs9IGRcblxuICBlID0gcyAmICgoMSA8PCAoLW5CaXRzKSkgLSAxKVxuICBzID4+PSAoLW5CaXRzKVxuICBuQml0cyArPSBlTGVuXG4gIGZvciAoOyBuQml0cyA+IDA7IGUgPSBlICogMjU2ICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgZSA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gbUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gbSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxuXG4gIGlmIChlID09PSAwKSB7XG4gICAgZSA9IDEgLSBlQmlhc1xuICB9IGVsc2UgaWYgKGUgPT09IGVNYXgpIHtcbiAgICByZXR1cm4gbSA/IE5hTiA6ICgocyA/IC0xIDogMSkgKiBJbmZpbml0eSlcbiAgfSBlbHNlIHtcbiAgICBtID0gbSArIE1hdGgucG93KDIsIG1MZW4pXG4gICAgZSA9IGUgLSBlQmlhc1xuICB9XG4gIHJldHVybiAocyA/IC0xIDogMSkgKiBtICogTWF0aC5wb3coMiwgZSAtIG1MZW4pXG59XG5cbmV4cG9ydHMud3JpdGUgPSBmdW5jdGlvbiAoYnVmZmVyLCB2YWx1ZSwgb2Zmc2V0LCBpc0xFLCBtTGVuLCBuQnl0ZXMpIHtcbiAgdmFyIGUsIG0sIGNcbiAgdmFyIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBydCA9IChtTGVuID09PSAyMyA/IE1hdGgucG93KDIsIC0yNCkgLSBNYXRoLnBvdygyLCAtNzcpIDogMClcbiAgdmFyIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKVxuICB2YXIgZCA9IGlzTEUgPyAxIDogLTFcbiAgdmFyIHMgPSB2YWx1ZSA8IDAgfHwgKHZhbHVlID09PSAwICYmIDEgLyB2YWx1ZSA8IDApID8gMSA6IDBcblxuICB2YWx1ZSA9IE1hdGguYWJzKHZhbHVlKVxuXG4gIGlmIChpc05hTih2YWx1ZSkgfHwgdmFsdWUgPT09IEluZmluaXR5KSB7XG4gICAgbSA9IGlzTmFOKHZhbHVlKSA/IDEgOiAwXG4gICAgZSA9IGVNYXhcbiAgfSBlbHNlIHtcbiAgICBlID0gTWF0aC5mbG9vcihNYXRoLmxvZyh2YWx1ZSkgLyBNYXRoLkxOMilcbiAgICBpZiAodmFsdWUgKiAoYyA9IE1hdGgucG93KDIsIC1lKSkgPCAxKSB7XG4gICAgICBlLS1cbiAgICAgIGMgKj0gMlxuICAgIH1cbiAgICBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIHZhbHVlICs9IHJ0IC8gY1xuICAgIH0gZWxzZSB7XG4gICAgICB2YWx1ZSArPSBydCAqIE1hdGgucG93KDIsIDEgLSBlQmlhcylcbiAgICB9XG4gICAgaWYgKHZhbHVlICogYyA+PSAyKSB7XG4gICAgICBlKytcbiAgICAgIGMgLz0gMlxuICAgIH1cblxuICAgIGlmIChlICsgZUJpYXMgPj0gZU1heCkge1xuICAgICAgbSA9IDBcbiAgICAgIGUgPSBlTWF4XG4gICAgfSBlbHNlIGlmIChlICsgZUJpYXMgPj0gMSkge1xuICAgICAgbSA9ICh2YWx1ZSAqIGMgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gZSArIGVCaWFzXG4gICAgfSBlbHNlIHtcbiAgICAgIG0gPSB2YWx1ZSAqIE1hdGgucG93KDIsIGVCaWFzIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IDBcbiAgICB9XG4gIH1cblxuICBmb3IgKDsgbUxlbiA+PSA4OyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBtICYgMHhmZiwgaSArPSBkLCBtIC89IDI1NiwgbUxlbiAtPSA4KSB7fVxuXG4gIGUgPSAoZSA8PCBtTGVuKSB8IG1cbiAgZUxlbiArPSBtTGVuXG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCkge31cblxuICBidWZmZXJbb2Zmc2V0ICsgaSAtIGRdIHw9IHMgKiAxMjhcbn1cbiIsIlxuLyoqXG4gKiBpc0FycmF5XG4gKi9cblxudmFyIGlzQXJyYXkgPSBBcnJheS5pc0FycmF5O1xuXG4vKipcbiAqIHRvU3RyaW5nXG4gKi9cblxudmFyIHN0ciA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7XG5cbi8qKlxuICogV2hldGhlciBvciBub3QgdGhlIGdpdmVuIGB2YWxgXG4gKiBpcyBhbiBhcnJheS5cbiAqXG4gKiBleGFtcGxlOlxuICpcbiAqICAgICAgICBpc0FycmF5KFtdKTtcbiAqICAgICAgICAvLyA+IHRydWVcbiAqICAgICAgICBpc0FycmF5KGFyZ3VtZW50cyk7XG4gKiAgICAgICAgLy8gPiBmYWxzZVxuICogICAgICAgIGlzQXJyYXkoJycpO1xuICogICAgICAgIC8vID4gZmFsc2VcbiAqXG4gKiBAcGFyYW0ge21peGVkfSB2YWxcbiAqIEByZXR1cm4ge2Jvb2x9XG4gKi9cblxubW9kdWxlLmV4cG9ydHMgPSBpc0FycmF5IHx8IGZ1bmN0aW9uICh2YWwpIHtcbiAgcmV0dXJuICEhIHZhbCAmJiAnW29iamVjdCBBcnJheV0nID09IHN0ci5jYWxsKHZhbCk7XG59O1xuIiwiLyoganNoaW50IG5vZGU6IHRydWUgKi9cbihmdW5jdGlvbiAoKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICBmdW5jdGlvbiBDb29raWVBY2Nlc3NJbmZvKGRvbWFpbiwgcGF0aCwgc2VjdXJlLCBzY3JpcHQpIHtcbiAgICAgICAgaWYgKHRoaXMgaW5zdGFuY2VvZiBDb29raWVBY2Nlc3NJbmZvKSB7XG4gICAgICAgICAgICB0aGlzLmRvbWFpbiA9IGRvbWFpbiB8fCB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnBhdGggPSBwYXRoIHx8IFwiL1wiO1xuICAgICAgICAgICAgdGhpcy5zZWN1cmUgPSAhIXNlY3VyZTtcbiAgICAgICAgICAgIHRoaXMuc2NyaXB0ID0gISFzY3JpcHQ7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IENvb2tpZUFjY2Vzc0luZm8oZG9tYWluLCBwYXRoLCBzZWN1cmUsIHNjcmlwdCk7XG4gICAgfVxuICAgIGV4cG9ydHMuQ29va2llQWNjZXNzSW5mbyA9IENvb2tpZUFjY2Vzc0luZm87XG5cbiAgICBmdW5jdGlvbiBDb29raWUoY29va2llc3RyLCByZXF1ZXN0X2RvbWFpbiwgcmVxdWVzdF9wYXRoKSB7XG4gICAgICAgIGlmIChjb29raWVzdHIgaW5zdGFuY2VvZiBDb29raWUpIHtcbiAgICAgICAgICAgIHJldHVybiBjb29raWVzdHI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMgaW5zdGFuY2VvZiBDb29raWUpIHtcbiAgICAgICAgICAgIHRoaXMubmFtZSA9IG51bGw7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHRoaXMuZXhwaXJhdGlvbl9kYXRlID0gSW5maW5pdHk7XG4gICAgICAgICAgICB0aGlzLnBhdGggPSBTdHJpbmcocmVxdWVzdF9wYXRoIHx8IFwiL1wiKTtcbiAgICAgICAgICAgIHRoaXMuZXhwbGljaXRfcGF0aCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5kb21haW4gPSByZXF1ZXN0X2RvbWFpbiB8fCBudWxsO1xuICAgICAgICAgICAgdGhpcy5leHBsaWNpdF9kb21haW4gPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuc2VjdXJlID0gZmFsc2U7IC8vaG93IHRvIGRlZmluZSBkZWZhdWx0P1xuICAgICAgICAgICAgdGhpcy5ub3NjcmlwdCA9IGZhbHNlOyAvL2h0dHBvbmx5XG4gICAgICAgICAgICBpZiAoY29va2llc3RyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5wYXJzZShjb29raWVzdHIsIHJlcXVlc3RfZG9tYWluLCByZXF1ZXN0X3BhdGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBDb29raWUoY29va2llc3RyLCByZXF1ZXN0X2RvbWFpbiwgcmVxdWVzdF9wYXRoKTtcbiAgICB9XG4gICAgZXhwb3J0cy5Db29raWUgPSBDb29raWU7XG5cbiAgICBDb29raWUucHJvdG90eXBlLnRvU3RyaW5nID0gZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgICAgIHZhciBzdHIgPSBbdGhpcy5uYW1lICsgXCI9XCIgKyB0aGlzLnZhbHVlXTtcbiAgICAgICAgaWYgKHRoaXMuZXhwaXJhdGlvbl9kYXRlICE9PSBJbmZpbml0eSkge1xuICAgICAgICAgICAgc3RyLnB1c2goXCJleHBpcmVzPVwiICsgKG5ldyBEYXRlKHRoaXMuZXhwaXJhdGlvbl9kYXRlKSkudG9HTVRTdHJpbmcoKSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZG9tYWluKSB7XG4gICAgICAgICAgICBzdHIucHVzaChcImRvbWFpbj1cIiArIHRoaXMuZG9tYWluKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5wYXRoKSB7XG4gICAgICAgICAgICBzdHIucHVzaChcInBhdGg9XCIgKyB0aGlzLnBhdGgpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnNlY3VyZSkge1xuICAgICAgICAgICAgc3RyLnB1c2goXCJzZWN1cmVcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMubm9zY3JpcHQpIHtcbiAgICAgICAgICAgIHN0ci5wdXNoKFwiaHR0cG9ubHlcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN0ci5qb2luKFwiOyBcIik7XG4gICAgfTtcblxuICAgIENvb2tpZS5wcm90b3R5cGUudG9WYWx1ZVN0cmluZyA9IGZ1bmN0aW9uIHRvVmFsdWVTdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm5hbWUgKyBcIj1cIiArIHRoaXMudmFsdWU7XG4gICAgfTtcblxuICAgIHZhciBjb29raWVfc3RyX3NwbGl0dGVyID0gL1s6XSg/PVxccypbYS16QS1aMC05X1xcLV0rXFxzKls9XSkvZztcbiAgICBDb29raWUucHJvdG90eXBlLnBhcnNlID0gZnVuY3Rpb24gcGFyc2Uoc3RyLCByZXF1ZXN0X2RvbWFpbiwgcmVxdWVzdF9wYXRoKSB7XG4gICAgICAgIGlmICh0aGlzIGluc3RhbmNlb2YgQ29va2llKSB7XG4gICAgICAgICAgICB2YXIgcGFydHMgPSBzdHIuc3BsaXQoXCI7XCIpLmZpbHRlcihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICEhdmFsdWU7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgcGFpciA9IHBhcnRzWzBdLm1hdGNoKC8oW149XSspPShbXFxzXFxTXSopLyksXG4gICAgICAgICAgICAgICAga2V5ID0gcGFpclsxXSxcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHBhaXJbMl0sXG4gICAgICAgICAgICAgICAgaTtcbiAgICAgICAgICAgIHRoaXMubmFtZSA9IGtleTtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcblxuICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8IHBhcnRzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgcGFpciA9IHBhcnRzW2ldLm1hdGNoKC8oW149XSspKD86PShbXFxzXFxTXSopKT8vKTtcbiAgICAgICAgICAgICAgICBrZXkgPSBwYWlyWzFdLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIHZhbHVlID0gcGFpclsyXTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICAgICAgICAgIGNhc2UgXCJodHRwb25seVwiOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLm5vc2NyaXB0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBcImV4cGlyZXNcIjpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5leHBpcmF0aW9uX2RhdGUgPSB2YWx1ZSA/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTnVtYmVyKERhdGUucGFyc2UodmFsdWUpKSA6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5maW5pdHk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJwYXRoXCI6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucGF0aCA9IHZhbHVlID9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZS50cmltKCkgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiXCI7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXhwbGljaXRfcGF0aCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJkb21haW5cIjpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kb21haW4gPSB2YWx1ZSA/XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUudHJpbSgpIDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIlwiO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV4cGxpY2l0X2RvbWFpbiA9ICEhdGhpcy5kb21haW47XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgXCJzZWN1cmVcIjpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWN1cmUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5leHBsaWNpdF9wYXRoKSB7XG4gICAgICAgICAgICAgICB0aGlzLnBhdGggPSByZXF1ZXN0X3BhdGggfHwgXCIvXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRoaXMuZXhwbGljaXRfZG9tYWluKSB7XG4gICAgICAgICAgICAgICB0aGlzLmRvbWFpbiA9IHJlcXVlc3RfZG9tYWluO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IENvb2tpZSgpLnBhcnNlKHN0ciwgcmVxdWVzdF9kb21haW4sIHJlcXVlc3RfcGF0aCk7XG4gICAgfTtcblxuICAgIENvb2tpZS5wcm90b3R5cGUubWF0Y2hlcyA9IGZ1bmN0aW9uIG1hdGNoZXMoYWNjZXNzX2luZm8pIHtcbiAgICAgICAgaWYgKHRoaXMubm9zY3JpcHQgJiYgYWNjZXNzX2luZm8uc2NyaXB0IHx8XG4gICAgICAgICAgICAgICAgdGhpcy5zZWN1cmUgJiYgIWFjY2Vzc19pbmZvLnNlY3VyZSB8fFxuICAgICAgICAgICAgICAgICF0aGlzLmNvbGxpZGVzV2l0aChhY2Nlc3NfaW5mbykpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuXG4gICAgQ29va2llLnByb3RvdHlwZS5jb2xsaWRlc1dpdGggPSBmdW5jdGlvbiBjb2xsaWRlc1dpdGgoYWNjZXNzX2luZm8pIHtcbiAgICAgICAgaWYgKCh0aGlzLnBhdGggJiYgIWFjY2Vzc19pbmZvLnBhdGgpIHx8ICh0aGlzLmRvbWFpbiAmJiAhYWNjZXNzX2luZm8uZG9tYWluKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLnBhdGggJiYgYWNjZXNzX2luZm8ucGF0aC5pbmRleE9mKHRoaXMucGF0aCkgIT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5leHBsaWNpdF9wYXRoICYmIGFjY2Vzc19pbmZvLnBhdGguaW5kZXhPZiggdGhpcy5wYXRoICkgIT09IDApIHtcbiAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhY2Nlc3NfZG9tYWluID0gYWNjZXNzX2luZm8uZG9tYWluICYmIGFjY2Vzc19pbmZvLmRvbWFpbi5yZXBsYWNlKC9eW1xcLl0vLCcnKTtcbiAgICAgICAgdmFyIGNvb2tpZV9kb21haW4gPSB0aGlzLmRvbWFpbiAmJiB0aGlzLmRvbWFpbi5yZXBsYWNlKC9eW1xcLl0vLCcnKTtcbiAgICAgICAgaWYgKGNvb2tpZV9kb21haW4gPT09IGFjY2Vzc19kb21haW4pIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjb29raWVfZG9tYWluKSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuZXhwbGljaXRfZG9tYWluKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyB3ZSBhbHJlYWR5IGNoZWNrZWQgaWYgdGhlIGRvbWFpbnMgd2VyZSBleGFjdGx5IHRoZSBzYW1lXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgd2lsZGNhcmQgPSBhY2Nlc3NfZG9tYWluLmluZGV4T2YoY29va2llX2RvbWFpbik7XG4gICAgICAgICAgICBpZiAod2lsZGNhcmQgPT09IC0xIHx8IHdpbGRjYXJkICE9PSBhY2Nlc3NfZG9tYWluLmxlbmd0aCAtIGNvb2tpZV9kb21haW4ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfTtcblxuICAgIGZ1bmN0aW9uIENvb2tpZUphcigpIHtcbiAgICAgICAgdmFyIGNvb2tpZXMsIGNvb2tpZXNfbGlzdCwgY29sbGlkYWJsZV9jb29raWU7XG4gICAgICAgIGlmICh0aGlzIGluc3RhbmNlb2YgQ29va2llSmFyKSB7XG4gICAgICAgICAgICBjb29raWVzID0gT2JqZWN0LmNyZWF0ZShudWxsKTsgLy9uYW1lOiBbQ29va2llXVxuXG4gICAgICAgICAgICB0aGlzLnNldENvb2tpZSA9IGZ1bmN0aW9uIHNldENvb2tpZShjb29raWUsIHJlcXVlc3RfZG9tYWluLCByZXF1ZXN0X3BhdGgpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVtb3ZlLCBpO1xuICAgICAgICAgICAgICAgIGNvb2tpZSA9IG5ldyBDb29raWUoY29va2llLCByZXF1ZXN0X2RvbWFpbiwgcmVxdWVzdF9wYXRoKTtcbiAgICAgICAgICAgICAgICAvL0RlbGV0ZSB0aGUgY29va2llIGlmIHRoZSBzZXQgaXMgcGFzdCB0aGUgY3VycmVudCB0aW1lXG4gICAgICAgICAgICAgICAgcmVtb3ZlID0gY29va2llLmV4cGlyYXRpb25fZGF0ZSA8PSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAgIGlmIChjb29raWVzW2Nvb2tpZS5uYW1lXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvb2tpZXNfbGlzdCA9IGNvb2tpZXNbY29va2llLm5hbWVdO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29va2llc19saXN0Lmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xsaWRhYmxlX2Nvb2tpZSA9IGNvb2tpZXNfbGlzdFtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb2xsaWRhYmxlX2Nvb2tpZS5jb2xsaWRlc1dpdGgoY29va2llKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29va2llc19saXN0LnNwbGljZShpLCAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvb2tpZXNfbGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBjb29raWVzW2Nvb2tpZS5uYW1lXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvb2tpZXNfbGlzdFtpXSA9IGNvb2tpZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29va2llO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW1vdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb29raWVzX2xpc3QucHVzaChjb29raWUpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29va2llO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocmVtb3ZlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29va2llc1tjb29raWUubmFtZV0gPSBbY29va2llXTtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29va2llc1tjb29raWUubmFtZV07XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgLy9yZXR1cm5zIGEgY29va2llXG4gICAgICAgICAgICB0aGlzLmdldENvb2tpZSA9IGZ1bmN0aW9uIGdldENvb2tpZShjb29raWVfbmFtZSwgYWNjZXNzX2luZm8pIHtcbiAgICAgICAgICAgICAgICB2YXIgY29va2llLCBpO1xuICAgICAgICAgICAgICAgIGNvb2tpZXNfbGlzdCA9IGNvb2tpZXNbY29va2llX25hbWVdO1xuICAgICAgICAgICAgICAgIGlmICghY29va2llc19saXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvb2tpZXNfbGlzdC5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICBjb29raWUgPSBjb29raWVzX2xpc3RbaV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb29raWUuZXhwaXJhdGlvbl9kYXRlIDw9IERhdGUubm93KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb29raWVzX2xpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGNvb2tpZXNbY29va2llLm5hbWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAoY29va2llLm1hdGNoZXMoYWNjZXNzX2luZm8pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gY29va2llO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIC8vcmV0dXJucyBhIGxpc3Qgb2YgY29va2llc1xuICAgICAgICAgICAgdGhpcy5nZXRDb29raWVzID0gZnVuY3Rpb24gZ2V0Q29va2llcyhhY2Nlc3NfaW5mbykge1xuICAgICAgICAgICAgICAgIHZhciBtYXRjaGVzID0gW10sIGNvb2tpZV9uYW1lLCBjb29raWU7XG4gICAgICAgICAgICAgICAgZm9yIChjb29raWVfbmFtZSBpbiBjb29raWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvb2tpZSA9IHRoaXMuZ2V0Q29va2llKGNvb2tpZV9uYW1lLCBhY2Nlc3NfaW5mbyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChjb29raWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hdGNoZXMucHVzaChjb29raWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1hdGNoZXMudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZygpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXMuam9pbihcIjpcIik7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBtYXRjaGVzLnRvVmFsdWVTdHJpbmcgPSBmdW5jdGlvbiB0b1ZhbHVlU3RyaW5nKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbWF0Y2hlcy5tYXAoZnVuY3Rpb24gKGMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBjLnRvVmFsdWVTdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgfSkuam9pbignOycpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXM7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IENvb2tpZUphcigpO1xuICAgIH1cbiAgICBleHBvcnRzLkNvb2tpZUphciA9IENvb2tpZUphcjtcblxuICAgIC8vcmV0dXJucyBsaXN0IG9mIGNvb2tpZXMgdGhhdCB3ZXJlIHNldCBjb3JyZWN0bHkuIENvb2tpZXMgdGhhdCBhcmUgZXhwaXJlZCBhbmQgcmVtb3ZlZCBhcmUgbm90IHJldHVybmVkLlxuICAgIENvb2tpZUphci5wcm90b3R5cGUuc2V0Q29va2llcyA9IGZ1bmN0aW9uIHNldENvb2tpZXMoY29va2llcywgcmVxdWVzdF9kb21haW4sIHJlcXVlc3RfcGF0aCkge1xuICAgICAgICBjb29raWVzID0gQXJyYXkuaXNBcnJheShjb29raWVzKSA/XG4gICAgICAgICAgICAgICAgY29va2llcyA6XG4gICAgICAgICAgICAgICAgY29va2llcy5zcGxpdChjb29raWVfc3RyX3NwbGl0dGVyKTtcbiAgICAgICAgdmFyIHN1Y2Nlc3NmdWwgPSBbXSxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICBjb29raWU7XG4gICAgICAgIGNvb2tpZXMgPSBjb29raWVzLm1hcChmdW5jdGlvbihpdGVtKXtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQ29va2llKGl0ZW0sIHJlcXVlc3RfZG9tYWluLCByZXF1ZXN0X3BhdGgpO1xuICAgICAgICB9KTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGNvb2tpZXMubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGNvb2tpZSA9IGNvb2tpZXNbaV07XG4gICAgICAgICAgICBpZiAodGhpcy5zZXRDb29raWUoY29va2llLCByZXF1ZXN0X2RvbWFpbiwgcmVxdWVzdF9wYXRoKSkge1xuICAgICAgICAgICAgICAgIHN1Y2Nlc3NmdWwucHVzaChjb29raWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdWNjZXNzZnVsO1xuICAgIH07XG59KCkpO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciB5YW1sID0gcmVxdWlyZSgnLi9saWIvanMteWFtbC5qcycpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0geWFtbDtcbiIsIid1c2Ugc3RyaWN0JztcblxuXG52YXIgbG9hZGVyID0gcmVxdWlyZSgnLi9qcy15YW1sL2xvYWRlcicpO1xudmFyIGR1bXBlciA9IHJlcXVpcmUoJy4vanMteWFtbC9kdW1wZXInKTtcblxuXG5mdW5jdGlvbiBkZXByZWNhdGVkKG5hbWUpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0Z1bmN0aW9uICcgKyBuYW1lICsgJyBpcyBkZXByZWNhdGVkIGFuZCBjYW5ub3QgYmUgdXNlZC4nKTtcbiAgfTtcbn1cblxuXG5tb2R1bGUuZXhwb3J0cy5UeXBlICAgICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9qcy15YW1sL3R5cGUnKTtcbm1vZHVsZS5leHBvcnRzLlNjaGVtYSAgICAgICAgICAgICAgPSByZXF1aXJlKCcuL2pzLXlhbWwvc2NoZW1hJyk7XG5tb2R1bGUuZXhwb3J0cy5GQUlMU0FGRV9TQ0hFTUEgICAgID0gcmVxdWlyZSgnLi9qcy15YW1sL3NjaGVtYS9mYWlsc2FmZScpO1xubW9kdWxlLmV4cG9ydHMuSlNPTl9TQ0hFTUEgICAgICAgICA9IHJlcXVpcmUoJy4vanMteWFtbC9zY2hlbWEvanNvbicpO1xubW9kdWxlLmV4cG9ydHMuQ09SRV9TQ0hFTUEgICAgICAgICA9IHJlcXVpcmUoJy4vanMteWFtbC9zY2hlbWEvY29yZScpO1xubW9kdWxlLmV4cG9ydHMuREVGQVVMVF9TQUZFX1NDSEVNQSA9IHJlcXVpcmUoJy4vanMteWFtbC9zY2hlbWEvZGVmYXVsdF9zYWZlJyk7XG5tb2R1bGUuZXhwb3J0cy5ERUZBVUxUX0ZVTExfU0NIRU1BID0gcmVxdWlyZSgnLi9qcy15YW1sL3NjaGVtYS9kZWZhdWx0X2Z1bGwnKTtcbm1vZHVsZS5leHBvcnRzLmxvYWQgICAgICAgICAgICAgICAgPSBsb2FkZXIubG9hZDtcbm1vZHVsZS5leHBvcnRzLmxvYWRBbGwgICAgICAgICAgICAgPSBsb2FkZXIubG9hZEFsbDtcbm1vZHVsZS5leHBvcnRzLnNhZmVMb2FkICAgICAgICAgICAgPSBsb2FkZXIuc2FmZUxvYWQ7XG5tb2R1bGUuZXhwb3J0cy5zYWZlTG9hZEFsbCAgICAgICAgID0gbG9hZGVyLnNhZmVMb2FkQWxsO1xubW9kdWxlLmV4cG9ydHMuZHVtcCAgICAgICAgICAgICAgICA9IGR1bXBlci5kdW1wO1xubW9kdWxlLmV4cG9ydHMuc2FmZUR1bXAgICAgICAgICAgICA9IGR1bXBlci5zYWZlRHVtcDtcbm1vZHVsZS5leHBvcnRzLllBTUxFeGNlcHRpb24gICAgICAgPSByZXF1aXJlKCcuL2pzLXlhbWwvZXhjZXB0aW9uJyk7XG5cbi8vIERlcHJlY2F0ZWQgc2NoZW1hIG5hbWVzIGZyb20gSlMtWUFNTCAyLjAueFxubW9kdWxlLmV4cG9ydHMuTUlOSU1BTF9TQ0hFTUEgPSByZXF1aXJlKCcuL2pzLXlhbWwvc2NoZW1hL2ZhaWxzYWZlJyk7XG5tb2R1bGUuZXhwb3J0cy5TQUZFX1NDSEVNQSAgICA9IHJlcXVpcmUoJy4vanMteWFtbC9zY2hlbWEvZGVmYXVsdF9zYWZlJyk7XG5tb2R1bGUuZXhwb3J0cy5ERUZBVUxUX1NDSEVNQSA9IHJlcXVpcmUoJy4vanMteWFtbC9zY2hlbWEvZGVmYXVsdF9mdWxsJyk7XG5cbi8vIERlcHJlY2F0ZWQgZnVuY3Rpb25zIGZyb20gSlMtWUFNTCAxLngueFxubW9kdWxlLmV4cG9ydHMuc2NhbiAgICAgICAgICAgPSBkZXByZWNhdGVkKCdzY2FuJyk7XG5tb2R1bGUuZXhwb3J0cy5wYXJzZSAgICAgICAgICA9IGRlcHJlY2F0ZWQoJ3BhcnNlJyk7XG5tb2R1bGUuZXhwb3J0cy5jb21wb3NlICAgICAgICA9IGRlcHJlY2F0ZWQoJ2NvbXBvc2UnKTtcbm1vZHVsZS5leHBvcnRzLmFkZENvbnN0cnVjdG9yID0gZGVwcmVjYXRlZCgnYWRkQ29uc3RydWN0b3InKTtcbiIsIid1c2Ugc3RyaWN0JztcblxuXG5mdW5jdGlvbiBpc05vdGhpbmcoc3ViamVjdCkge1xuICByZXR1cm4gKHR5cGVvZiBzdWJqZWN0ID09PSAndW5kZWZpbmVkJykgfHwgKHN1YmplY3QgPT09IG51bGwpO1xufVxuXG5cbmZ1bmN0aW9uIGlzT2JqZWN0KHN1YmplY3QpIHtcbiAgcmV0dXJuICh0eXBlb2Ygc3ViamVjdCA9PT0gJ29iamVjdCcpICYmIChzdWJqZWN0ICE9PSBudWxsKTtcbn1cblxuXG5mdW5jdGlvbiB0b0FycmF5KHNlcXVlbmNlKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KHNlcXVlbmNlKSkgcmV0dXJuIHNlcXVlbmNlO1xuICBlbHNlIGlmIChpc05vdGhpbmcoc2VxdWVuY2UpKSByZXR1cm4gW107XG5cbiAgcmV0dXJuIFsgc2VxdWVuY2UgXTtcbn1cblxuXG5mdW5jdGlvbiBleHRlbmQodGFyZ2V0LCBzb3VyY2UpIHtcbiAgdmFyIGluZGV4LCBsZW5ndGgsIGtleSwgc291cmNlS2V5cztcblxuICBpZiAoc291cmNlKSB7XG4gICAgc291cmNlS2V5cyA9IE9iamVjdC5rZXlzKHNvdXJjZSk7XG5cbiAgICBmb3IgKGluZGV4ID0gMCwgbGVuZ3RoID0gc291cmNlS2V5cy5sZW5ndGg7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgICBrZXkgPSBzb3VyY2VLZXlzW2luZGV4XTtcbiAgICAgIHRhcmdldFtrZXldID0gc291cmNlW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuXG5mdW5jdGlvbiByZXBlYXQoc3RyaW5nLCBjb3VudCkge1xuICB2YXIgcmVzdWx0ID0gJycsIGN5Y2xlO1xuXG4gIGZvciAoY3ljbGUgPSAwOyBjeWNsZSA8IGNvdW50OyBjeWNsZSArPSAxKSB7XG4gICAgcmVzdWx0ICs9IHN0cmluZztcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cblxuZnVuY3Rpb24gaXNOZWdhdGl2ZVplcm8obnVtYmVyKSB7XG4gIHJldHVybiAobnVtYmVyID09PSAwKSAmJiAoTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZID09PSAxIC8gbnVtYmVyKTtcbn1cblxuXG5tb2R1bGUuZXhwb3J0cy5pc05vdGhpbmcgICAgICA9IGlzTm90aGluZztcbm1vZHVsZS5leHBvcnRzLmlzT2JqZWN0ICAgICAgID0gaXNPYmplY3Q7XG5tb2R1bGUuZXhwb3J0cy50b0FycmF5ICAgICAgICA9IHRvQXJyYXk7XG5tb2R1bGUuZXhwb3J0cy5yZXBlYXQgICAgICAgICA9IHJlcGVhdDtcbm1vZHVsZS5leHBvcnRzLmlzTmVnYXRpdmVaZXJvID0gaXNOZWdhdGl2ZVplcm87XG5tb2R1bGUuZXhwb3J0cy5leHRlbmQgICAgICAgICA9IGV4dGVuZDtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyplc2xpbnQtZGlzYWJsZSBuby11c2UtYmVmb3JlLWRlZmluZSovXG5cbnZhciBjb21tb24gICAgICAgICAgICAgID0gcmVxdWlyZSgnLi9jb21tb24nKTtcbnZhciBZQU1MRXhjZXB0aW9uICAgICAgID0gcmVxdWlyZSgnLi9leGNlcHRpb24nKTtcbnZhciBERUZBVUxUX0ZVTExfU0NIRU1BID0gcmVxdWlyZSgnLi9zY2hlbWEvZGVmYXVsdF9mdWxsJyk7XG52YXIgREVGQVVMVF9TQUZFX1NDSEVNQSA9IHJlcXVpcmUoJy4vc2NoZW1hL2RlZmF1bHRfc2FmZScpO1xuXG52YXIgX3RvU3RyaW5nICAgICAgID0gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztcbnZhciBfaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5O1xuXG52YXIgQ0hBUl9UQUIgICAgICAgICAgICAgICAgICA9IDB4MDk7IC8qIFRhYiAqL1xudmFyIENIQVJfTElORV9GRUVEICAgICAgICAgICAgPSAweDBBOyAvKiBMRiAqL1xudmFyIENIQVJfU1BBQ0UgICAgICAgICAgICAgICAgPSAweDIwOyAvKiBTcGFjZSAqL1xudmFyIENIQVJfRVhDTEFNQVRJT04gICAgICAgICAgPSAweDIxOyAvKiAhICovXG52YXIgQ0hBUl9ET1VCTEVfUVVPVEUgICAgICAgICA9IDB4MjI7IC8qIFwiICovXG52YXIgQ0hBUl9TSEFSUCAgICAgICAgICAgICAgICA9IDB4MjM7IC8qICMgKi9cbnZhciBDSEFSX1BFUkNFTlQgICAgICAgICAgICAgID0gMHgyNTsgLyogJSAqL1xudmFyIENIQVJfQU1QRVJTQU5EICAgICAgICAgICAgPSAweDI2OyAvKiAmICovXG52YXIgQ0hBUl9TSU5HTEVfUVVPVEUgICAgICAgICA9IDB4Mjc7IC8qICcgKi9cbnZhciBDSEFSX0FTVEVSSVNLICAgICAgICAgICAgID0gMHgyQTsgLyogKiAqL1xudmFyIENIQVJfQ09NTUEgICAgICAgICAgICAgICAgPSAweDJDOyAvKiAsICovXG52YXIgQ0hBUl9NSU5VUyAgICAgICAgICAgICAgICA9IDB4MkQ7IC8qIC0gKi9cbnZhciBDSEFSX0NPTE9OICAgICAgICAgICAgICAgID0gMHgzQTsgLyogOiAqL1xudmFyIENIQVJfR1JFQVRFUl9USEFOICAgICAgICAgPSAweDNFOyAvKiA+ICovXG52YXIgQ0hBUl9RVUVTVElPTiAgICAgICAgICAgICA9IDB4M0Y7IC8qID8gKi9cbnZhciBDSEFSX0NPTU1FUkNJQUxfQVQgICAgICAgID0gMHg0MDsgLyogQCAqL1xudmFyIENIQVJfTEVGVF9TUVVBUkVfQlJBQ0tFVCAgPSAweDVCOyAvKiBbICovXG52YXIgQ0hBUl9SSUdIVF9TUVVBUkVfQlJBQ0tFVCA9IDB4NUQ7IC8qIF0gKi9cbnZhciBDSEFSX0dSQVZFX0FDQ0VOVCAgICAgICAgID0gMHg2MDsgLyogYCAqL1xudmFyIENIQVJfTEVGVF9DVVJMWV9CUkFDS0VUICAgPSAweDdCOyAvKiB7ICovXG52YXIgQ0hBUl9WRVJUSUNBTF9MSU5FICAgICAgICA9IDB4N0M7IC8qIHwgKi9cbnZhciBDSEFSX1JJR0hUX0NVUkxZX0JSQUNLRVQgID0gMHg3RDsgLyogfSAqL1xuXG52YXIgRVNDQVBFX1NFUVVFTkNFUyA9IHt9O1xuXG5FU0NBUEVfU0VRVUVOQ0VTWzB4MDBdICAgPSAnXFxcXDAnO1xuRVNDQVBFX1NFUVVFTkNFU1sweDA3XSAgID0gJ1xcXFxhJztcbkVTQ0FQRV9TRVFVRU5DRVNbMHgwOF0gICA9ICdcXFxcYic7XG5FU0NBUEVfU0VRVUVOQ0VTWzB4MDldICAgPSAnXFxcXHQnO1xuRVNDQVBFX1NFUVVFTkNFU1sweDBBXSAgID0gJ1xcXFxuJztcbkVTQ0FQRV9TRVFVRU5DRVNbMHgwQl0gICA9ICdcXFxcdic7XG5FU0NBUEVfU0VRVUVOQ0VTWzB4MENdICAgPSAnXFxcXGYnO1xuRVNDQVBFX1NFUVVFTkNFU1sweDBEXSAgID0gJ1xcXFxyJztcbkVTQ0FQRV9TRVFVRU5DRVNbMHgxQl0gICA9ICdcXFxcZSc7XG5FU0NBUEVfU0VRVUVOQ0VTWzB4MjJdICAgPSAnXFxcXFwiJztcbkVTQ0FQRV9TRVFVRU5DRVNbMHg1Q10gICA9ICdcXFxcXFxcXCc7XG5FU0NBUEVfU0VRVUVOQ0VTWzB4ODVdICAgPSAnXFxcXE4nO1xuRVNDQVBFX1NFUVVFTkNFU1sweEEwXSAgID0gJ1xcXFxfJztcbkVTQ0FQRV9TRVFVRU5DRVNbMHgyMDI4XSA9ICdcXFxcTCc7XG5FU0NBUEVfU0VRVUVOQ0VTWzB4MjAyOV0gPSAnXFxcXFAnO1xuXG52YXIgREVQUkVDQVRFRF9CT09MRUFOU19TWU5UQVggPSBbXG4gICd5JywgJ1knLCAneWVzJywgJ1llcycsICdZRVMnLCAnb24nLCAnT24nLCAnT04nLFxuICAnbicsICdOJywgJ25vJywgJ05vJywgJ05PJywgJ29mZicsICdPZmYnLCAnT0ZGJ1xuXTtcblxuZnVuY3Rpb24gY29tcGlsZVN0eWxlTWFwKHNjaGVtYSwgbWFwKSB7XG4gIHZhciByZXN1bHQsIGtleXMsIGluZGV4LCBsZW5ndGgsIHRhZywgc3R5bGUsIHR5cGU7XG5cbiAgaWYgKG1hcCA9PT0gbnVsbCkgcmV0dXJuIHt9O1xuXG4gIHJlc3VsdCA9IHt9O1xuICBrZXlzID0gT2JqZWN0LmtleXMobWFwKTtcblxuICBmb3IgKGluZGV4ID0gMCwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgdGFnID0ga2V5c1tpbmRleF07XG4gICAgc3R5bGUgPSBTdHJpbmcobWFwW3RhZ10pO1xuXG4gICAgaWYgKHRhZy5zbGljZSgwLCAyKSA9PT0gJyEhJykge1xuICAgICAgdGFnID0gJ3RhZzp5YW1sLm9yZywyMDAyOicgKyB0YWcuc2xpY2UoMik7XG4gICAgfVxuXG4gICAgdHlwZSA9IHNjaGVtYS5jb21waWxlZFR5cGVNYXBbdGFnXTtcblxuICAgIGlmICh0eXBlICYmIF9oYXNPd25Qcm9wZXJ0eS5jYWxsKHR5cGUuc3R5bGVBbGlhc2VzLCBzdHlsZSkpIHtcbiAgICAgIHN0eWxlID0gdHlwZS5zdHlsZUFsaWFzZXNbc3R5bGVdO1xuICAgIH1cblxuICAgIHJlc3VsdFt0YWddID0gc3R5bGU7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBlbmNvZGVIZXgoY2hhcmFjdGVyKSB7XG4gIHZhciBzdHJpbmcsIGhhbmRsZSwgbGVuZ3RoO1xuXG4gIHN0cmluZyA9IGNoYXJhY3Rlci50b1N0cmluZygxNikudG9VcHBlckNhc2UoKTtcblxuICBpZiAoY2hhcmFjdGVyIDw9IDB4RkYpIHtcbiAgICBoYW5kbGUgPSAneCc7XG4gICAgbGVuZ3RoID0gMjtcbiAgfSBlbHNlIGlmIChjaGFyYWN0ZXIgPD0gMHhGRkZGKSB7XG4gICAgaGFuZGxlID0gJ3UnO1xuICAgIGxlbmd0aCA9IDQ7XG4gIH0gZWxzZSBpZiAoY2hhcmFjdGVyIDw9IDB4RkZGRkZGRkYpIHtcbiAgICBoYW5kbGUgPSAnVSc7XG4gICAgbGVuZ3RoID0gODtcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgWUFNTEV4Y2VwdGlvbignY29kZSBwb2ludCB3aXRoaW4gYSBzdHJpbmcgbWF5IG5vdCBiZSBncmVhdGVyIHRoYW4gMHhGRkZGRkZGRicpO1xuICB9XG5cbiAgcmV0dXJuICdcXFxcJyArIGhhbmRsZSArIGNvbW1vbi5yZXBlYXQoJzAnLCBsZW5ndGggLSBzdHJpbmcubGVuZ3RoKSArIHN0cmluZztcbn1cblxuZnVuY3Rpb24gU3RhdGUob3B0aW9ucykge1xuICB0aGlzLnNjaGVtYSAgICAgICA9IG9wdGlvbnNbJ3NjaGVtYSddIHx8IERFRkFVTFRfRlVMTF9TQ0hFTUE7XG4gIHRoaXMuaW5kZW50ICAgICAgID0gTWF0aC5tYXgoMSwgKG9wdGlvbnNbJ2luZGVudCddIHx8IDIpKTtcbiAgdGhpcy5za2lwSW52YWxpZCAgPSBvcHRpb25zWydza2lwSW52YWxpZCddIHx8IGZhbHNlO1xuICB0aGlzLmZsb3dMZXZlbCAgICA9IChjb21tb24uaXNOb3RoaW5nKG9wdGlvbnNbJ2Zsb3dMZXZlbCddKSA/IC0xIDogb3B0aW9uc1snZmxvd0xldmVsJ10pO1xuICB0aGlzLnN0eWxlTWFwICAgICA9IGNvbXBpbGVTdHlsZU1hcCh0aGlzLnNjaGVtYSwgb3B0aW9uc1snc3R5bGVzJ10gfHwgbnVsbCk7XG4gIHRoaXMuc29ydEtleXMgICAgID0gb3B0aW9uc1snc29ydEtleXMnXSB8fCBmYWxzZTtcbiAgdGhpcy5saW5lV2lkdGggICAgPSBvcHRpb25zWydsaW5lV2lkdGgnXSB8fCA4MDtcbiAgdGhpcy5ub1JlZnMgICAgICAgPSBvcHRpb25zWydub1JlZnMnXSB8fCBmYWxzZTtcbiAgdGhpcy5ub0NvbXBhdE1vZGUgPSBvcHRpb25zWydub0NvbXBhdE1vZGUnXSB8fCBmYWxzZTtcblxuICB0aGlzLmltcGxpY2l0VHlwZXMgPSB0aGlzLnNjaGVtYS5jb21waWxlZEltcGxpY2l0O1xuICB0aGlzLmV4cGxpY2l0VHlwZXMgPSB0aGlzLnNjaGVtYS5jb21waWxlZEV4cGxpY2l0O1xuXG4gIHRoaXMudGFnID0gbnVsbDtcbiAgdGhpcy5yZXN1bHQgPSAnJztcblxuICB0aGlzLmR1cGxpY2F0ZXMgPSBbXTtcbiAgdGhpcy51c2VkRHVwbGljYXRlcyA9IG51bGw7XG59XG5cbi8vIEluZGVudHMgZXZlcnkgbGluZSBpbiBhIHN0cmluZy4gRW1wdHkgbGluZXMgKFxcbiBvbmx5KSBhcmUgbm90IGluZGVudGVkLlxuZnVuY3Rpb24gaW5kZW50U3RyaW5nKHN0cmluZywgc3BhY2VzKSB7XG4gIHZhciBpbmQgPSBjb21tb24ucmVwZWF0KCcgJywgc3BhY2VzKSxcbiAgICAgIHBvc2l0aW9uID0gMCxcbiAgICAgIG5leHQgPSAtMSxcbiAgICAgIHJlc3VsdCA9ICcnLFxuICAgICAgbGluZSxcbiAgICAgIGxlbmd0aCA9IHN0cmluZy5sZW5ndGg7XG5cbiAgd2hpbGUgKHBvc2l0aW9uIDwgbGVuZ3RoKSB7XG4gICAgbmV4dCA9IHN0cmluZy5pbmRleE9mKCdcXG4nLCBwb3NpdGlvbik7XG4gICAgaWYgKG5leHQgPT09IC0xKSB7XG4gICAgICBsaW5lID0gc3RyaW5nLnNsaWNlKHBvc2l0aW9uKTtcbiAgICAgIHBvc2l0aW9uID0gbGVuZ3RoO1xuICAgIH0gZWxzZSB7XG4gICAgICBsaW5lID0gc3RyaW5nLnNsaWNlKHBvc2l0aW9uLCBuZXh0ICsgMSk7XG4gICAgICBwb3NpdGlvbiA9IG5leHQgKyAxO1xuICAgIH1cblxuICAgIGlmIChsaW5lLmxlbmd0aCAmJiBsaW5lICE9PSAnXFxuJykgcmVzdWx0ICs9IGluZDtcblxuICAgIHJlc3VsdCArPSBsaW5lO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gZ2VuZXJhdGVOZXh0TGluZShzdGF0ZSwgbGV2ZWwpIHtcbiAgcmV0dXJuICdcXG4nICsgY29tbW9uLnJlcGVhdCgnICcsIHN0YXRlLmluZGVudCAqIGxldmVsKTtcbn1cblxuZnVuY3Rpb24gdGVzdEltcGxpY2l0UmVzb2x2aW5nKHN0YXRlLCBzdHIpIHtcbiAgdmFyIGluZGV4LCBsZW5ndGgsIHR5cGU7XG5cbiAgZm9yIChpbmRleCA9IDAsIGxlbmd0aCA9IHN0YXRlLmltcGxpY2l0VHlwZXMubGVuZ3RoOyBpbmRleCA8IGxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgIHR5cGUgPSBzdGF0ZS5pbXBsaWNpdFR5cGVzW2luZGV4XTtcblxuICAgIGlmICh0eXBlLnJlc29sdmUoc3RyKSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vLyBbMzNdIHMtd2hpdGUgOjo9IHMtc3BhY2UgfCBzLXRhYlxuZnVuY3Rpb24gaXNXaGl0ZXNwYWNlKGMpIHtcbiAgcmV0dXJuIGMgPT09IENIQVJfU1BBQ0UgfHwgYyA9PT0gQ0hBUl9UQUI7XG59XG5cbi8vIFJldHVybnMgdHJ1ZSBpZiB0aGUgY2hhcmFjdGVyIGNhbiBiZSBwcmludGVkIHdpdGhvdXQgZXNjYXBpbmcuXG4vLyBGcm9tIFlBTUwgMS4yOiBcImFueSBhbGxvd2VkIGNoYXJhY3RlcnMga25vd24gdG8gYmUgbm9uLXByaW50YWJsZVxuLy8gc2hvdWxkIGFsc28gYmUgZXNjYXBlZC4gW0hvd2V2ZXIsXSBUaGlzIGlzbuKAmXQgbWFuZGF0b3J5XCJcbi8vIERlcml2ZWQgZnJvbSBuYi1jaGFyIC0gXFx0IC0gI3g4NSAtICN4QTAgLSAjeDIwMjggLSAjeDIwMjkuXG5mdW5jdGlvbiBpc1ByaW50YWJsZShjKSB7XG4gIHJldHVybiAgKDB4MDAwMjAgPD0gYyAmJiBjIDw9IDB4MDAwMDdFKVxuICAgICAgfHwgKCgweDAwMEExIDw9IGMgJiYgYyA8PSAweDAwRDdGRikgJiYgYyAhPT0gMHgyMDI4ICYmIGMgIT09IDB4MjAyOSlcbiAgICAgIHx8ICgoMHgwRTAwMCA8PSBjICYmIGMgPD0gMHgwMEZGRkQpICYmIGMgIT09IDB4RkVGRiAvKiBCT00gKi8pXG4gICAgICB8fCAgKDB4MTAwMDAgPD0gYyAmJiBjIDw9IDB4MTBGRkZGKTtcbn1cblxuLy8gU2ltcGxpZmllZCB0ZXN0IGZvciB2YWx1ZXMgYWxsb3dlZCBhZnRlciB0aGUgZmlyc3QgY2hhcmFjdGVyIGluIHBsYWluIHN0eWxlLlxuZnVuY3Rpb24gaXNQbGFpblNhZmUoYykge1xuICAvLyBVc2VzIGEgc3Vic2V0IG9mIG5iLWNoYXIgLSBjLWZsb3ctaW5kaWNhdG9yIC0gXCI6XCIgLSBcIiNcIlxuICAvLyB3aGVyZSBuYi1jaGFyIDo6PSBjLXByaW50YWJsZSAtIGItY2hhciAtIGMtYnl0ZS1vcmRlci1tYXJrLlxuICByZXR1cm4gaXNQcmludGFibGUoYykgJiYgYyAhPT0gMHhGRUZGXG4gICAgLy8gLSBjLWZsb3ctaW5kaWNhdG9yXG4gICAgJiYgYyAhPT0gQ0hBUl9DT01NQVxuICAgICYmIGMgIT09IENIQVJfTEVGVF9TUVVBUkVfQlJBQ0tFVFxuICAgICYmIGMgIT09IENIQVJfUklHSFRfU1FVQVJFX0JSQUNLRVRcbiAgICAmJiBjICE9PSBDSEFSX0xFRlRfQ1VSTFlfQlJBQ0tFVFxuICAgICYmIGMgIT09IENIQVJfUklHSFRfQ1VSTFlfQlJBQ0tFVFxuICAgIC8vIC0gXCI6XCIgLSBcIiNcIlxuICAgICYmIGMgIT09IENIQVJfQ09MT05cbiAgICAmJiBjICE9PSBDSEFSX1NIQVJQO1xufVxuXG4vLyBTaW1wbGlmaWVkIHRlc3QgZm9yIHZhbHVlcyBhbGxvd2VkIGFzIHRoZSBmaXJzdCBjaGFyYWN0ZXIgaW4gcGxhaW4gc3R5bGUuXG5mdW5jdGlvbiBpc1BsYWluU2FmZUZpcnN0KGMpIHtcbiAgLy8gVXNlcyBhIHN1YnNldCBvZiBucy1jaGFyIC0gYy1pbmRpY2F0b3JcbiAgLy8gd2hlcmUgbnMtY2hhciA9IG5iLWNoYXIgLSBzLXdoaXRlLlxuICByZXR1cm4gaXNQcmludGFibGUoYykgJiYgYyAhPT0gMHhGRUZGXG4gICAgJiYgIWlzV2hpdGVzcGFjZShjKSAvLyAtIHMtd2hpdGVcbiAgICAvLyAtIChjLWluZGljYXRvciA6Oj1cbiAgICAvLyDigJwt4oCdIHwg4oCcP+KAnSB8IOKAnDrigJ0gfCDigJws4oCdIHwg4oCcW+KAnSB8IOKAnF3igJ0gfCDigJx74oCdIHwg4oCcfeKAnVxuICAgICYmIGMgIT09IENIQVJfTUlOVVNcbiAgICAmJiBjICE9PSBDSEFSX1FVRVNUSU9OXG4gICAgJiYgYyAhPT0gQ0hBUl9DT0xPTlxuICAgICYmIGMgIT09IENIQVJfQ09NTUFcbiAgICAmJiBjICE9PSBDSEFSX0xFRlRfU1FVQVJFX0JSQUNLRVRcbiAgICAmJiBjICE9PSBDSEFSX1JJR0hUX1NRVUFSRV9CUkFDS0VUXG4gICAgJiYgYyAhPT0gQ0hBUl9MRUZUX0NVUkxZX0JSQUNLRVRcbiAgICAmJiBjICE9PSBDSEFSX1JJR0hUX0NVUkxZX0JSQUNLRVRcbiAgICAvLyB8IOKAnCPigJ0gfCDigJwm4oCdIHwg4oCcKuKAnSB8IOKAnCHigJ0gfCDigJx84oCdIHwg4oCcPuKAnSB8IOKAnCfigJ0gfCDigJxcIuKAnVxuICAgICYmIGMgIT09IENIQVJfU0hBUlBcbiAgICAmJiBjICE9PSBDSEFSX0FNUEVSU0FORFxuICAgICYmIGMgIT09IENIQVJfQVNURVJJU0tcbiAgICAmJiBjICE9PSBDSEFSX0VYQ0xBTUFUSU9OXG4gICAgJiYgYyAhPT0gQ0hBUl9WRVJUSUNBTF9MSU5FXG4gICAgJiYgYyAhPT0gQ0hBUl9HUkVBVEVSX1RIQU5cbiAgICAmJiBjICE9PSBDSEFSX1NJTkdMRV9RVU9URVxuICAgICYmIGMgIT09IENIQVJfRE9VQkxFX1FVT1RFXG4gICAgLy8gfCDigJwl4oCdIHwg4oCcQOKAnSB8IOKAnGDigJ0pXG4gICAgJiYgYyAhPT0gQ0hBUl9QRVJDRU5UXG4gICAgJiYgYyAhPT0gQ0hBUl9DT01NRVJDSUFMX0FUXG4gICAgJiYgYyAhPT0gQ0hBUl9HUkFWRV9BQ0NFTlQ7XG59XG5cbnZhciBTVFlMRV9QTEFJTiAgID0gMSxcbiAgICBTVFlMRV9TSU5HTEUgID0gMixcbiAgICBTVFlMRV9MSVRFUkFMID0gMyxcbiAgICBTVFlMRV9GT0xERUQgID0gNCxcbiAgICBTVFlMRV9ET1VCTEUgID0gNTtcblxuLy8gRGV0ZXJtaW5lcyB3aGljaCBzY2FsYXIgc3R5bGVzIGFyZSBwb3NzaWJsZSBhbmQgcmV0dXJucyB0aGUgcHJlZmVycmVkIHN0eWxlLlxuLy8gbGluZVdpZHRoID0gLTEgPT4gbm8gbGltaXQuXG4vLyBQcmUtY29uZGl0aW9uczogc3RyLmxlbmd0aCA+IDAuXG4vLyBQb3N0LWNvbmRpdGlvbnM6XG4vLyAgICBTVFlMRV9QTEFJTiBvciBTVFlMRV9TSU5HTEUgPT4gbm8gXFxuIGFyZSBpbiB0aGUgc3RyaW5nLlxuLy8gICAgU1RZTEVfTElURVJBTCA9PiBubyBsaW5lcyBhcmUgc3VpdGFibGUgZm9yIGZvbGRpbmcgKG9yIGxpbmVXaWR0aCBpcyAtMSkuXG4vLyAgICBTVFlMRV9GT0xERUQgPT4gYSBsaW5lID4gbGluZVdpZHRoIGFuZCBjYW4gYmUgZm9sZGVkIChhbmQgbGluZVdpZHRoICE9IC0xKS5cbmZ1bmN0aW9uIGNob29zZVNjYWxhclN0eWxlKHN0cmluZywgc2luZ2xlTGluZU9ubHksIGluZGVudFBlckxldmVsLCBsaW5lV2lkdGgsIHRlc3RBbWJpZ3VvdXNUeXBlKSB7XG4gIHZhciBpO1xuICB2YXIgY2hhcjtcbiAgdmFyIGhhc0xpbmVCcmVhayA9IGZhbHNlO1xuICB2YXIgaGFzRm9sZGFibGVMaW5lID0gZmFsc2U7IC8vIG9ubHkgY2hlY2tlZCBpZiBzaG91bGRUcmFja1dpZHRoXG4gIHZhciBzaG91bGRUcmFja1dpZHRoID0gbGluZVdpZHRoICE9PSAtMTtcbiAgdmFyIHByZXZpb3VzTGluZUJyZWFrID0gLTE7IC8vIGNvdW50IHRoZSBmaXJzdCBsaW5lIGNvcnJlY3RseVxuICB2YXIgcGxhaW4gPSBpc1BsYWluU2FmZUZpcnN0KHN0cmluZy5jaGFyQ29kZUF0KDApKVxuICAgICAgICAgICYmICFpc1doaXRlc3BhY2Uoc3RyaW5nLmNoYXJDb2RlQXQoc3RyaW5nLmxlbmd0aCAtIDEpKTtcblxuICBpZiAoc2luZ2xlTGluZU9ubHkpIHtcbiAgICAvLyBDYXNlOiBubyBibG9jayBzdHlsZXMuXG4gICAgLy8gQ2hlY2sgZm9yIGRpc2FsbG93ZWQgY2hhcmFjdGVycyB0byBydWxlIG91dCBwbGFpbiBhbmQgc2luZ2xlLlxuICAgIGZvciAoaSA9IDA7IGkgPCBzdHJpbmcubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNoYXIgPSBzdHJpbmcuY2hhckNvZGVBdChpKTtcbiAgICAgIGlmICghaXNQcmludGFibGUoY2hhcikpIHtcbiAgICAgICAgcmV0dXJuIFNUWUxFX0RPVUJMRTtcbiAgICAgIH1cbiAgICAgIHBsYWluID0gcGxhaW4gJiYgaXNQbGFpblNhZmUoY2hhcik7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIENhc2U6IGJsb2NrIHN0eWxlcyBwZXJtaXR0ZWQuXG4gICAgZm9yIChpID0gMDsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgICAgY2hhciA9IHN0cmluZy5jaGFyQ29kZUF0KGkpO1xuICAgICAgaWYgKGNoYXIgPT09IENIQVJfTElORV9GRUVEKSB7XG4gICAgICAgIGhhc0xpbmVCcmVhayA9IHRydWU7XG4gICAgICAgIC8vIENoZWNrIGlmIGFueSBsaW5lIGNhbiBiZSBmb2xkZWQuXG4gICAgICAgIGlmIChzaG91bGRUcmFja1dpZHRoKSB7XG4gICAgICAgICAgaGFzRm9sZGFibGVMaW5lID0gaGFzRm9sZGFibGVMaW5lIHx8XG4gICAgICAgICAgICAvLyBGb2xkYWJsZSBsaW5lID0gdG9vIGxvbmcsIGFuZCBub3QgbW9yZS1pbmRlbnRlZC5cbiAgICAgICAgICAgIChpIC0gcHJldmlvdXNMaW5lQnJlYWsgLSAxID4gbGluZVdpZHRoICYmXG4gICAgICAgICAgICAgc3RyaW5nW3ByZXZpb3VzTGluZUJyZWFrICsgMV0gIT09ICcgJyk7XG4gICAgICAgICAgcHJldmlvdXNMaW5lQnJlYWsgPSBpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKCFpc1ByaW50YWJsZShjaGFyKSkge1xuICAgICAgICByZXR1cm4gU1RZTEVfRE9VQkxFO1xuICAgICAgfVxuICAgICAgcGxhaW4gPSBwbGFpbiAmJiBpc1BsYWluU2FmZShjaGFyKTtcbiAgICB9XG4gICAgLy8gaW4gY2FzZSB0aGUgZW5kIGlzIG1pc3NpbmcgYSBcXG5cbiAgICBoYXNGb2xkYWJsZUxpbmUgPSBoYXNGb2xkYWJsZUxpbmUgfHwgKHNob3VsZFRyYWNrV2lkdGggJiZcbiAgICAgIChpIC0gcHJldmlvdXNMaW5lQnJlYWsgLSAxID4gbGluZVdpZHRoICYmXG4gICAgICAgc3RyaW5nW3ByZXZpb3VzTGluZUJyZWFrICsgMV0gIT09ICcgJykpO1xuICB9XG4gIC8vIEFsdGhvdWdoIGV2ZXJ5IHN0eWxlIGNhbiByZXByZXNlbnQgXFxuIHdpdGhvdXQgZXNjYXBpbmcsIHByZWZlciBibG9jayBzdHlsZXNcbiAgLy8gZm9yIG11bHRpbGluZSwgc2luY2UgdGhleSdyZSBtb3JlIHJlYWRhYmxlIGFuZCB0aGV5IGRvbid0IGFkZCBlbXB0eSBsaW5lcy5cbiAgLy8gQWxzbyBwcmVmZXIgZm9sZGluZyBhIHN1cGVyLWxvbmcgbGluZS5cbiAgaWYgKCFoYXNMaW5lQnJlYWsgJiYgIWhhc0ZvbGRhYmxlTGluZSkge1xuICAgIC8vIFN0cmluZ3MgaW50ZXJwcmV0YWJsZSBhcyBhbm90aGVyIHR5cGUgaGF2ZSB0byBiZSBxdW90ZWQ7XG4gICAgLy8gZS5nLiB0aGUgc3RyaW5nICd0cnVlJyB2cy4gdGhlIGJvb2xlYW4gdHJ1ZS5cbiAgICByZXR1cm4gcGxhaW4gJiYgIXRlc3RBbWJpZ3VvdXNUeXBlKHN0cmluZylcbiAgICAgID8gU1RZTEVfUExBSU4gOiBTVFlMRV9TSU5HTEU7XG4gIH1cbiAgLy8gRWRnZSBjYXNlOiBibG9jayBpbmRlbnRhdGlvbiBpbmRpY2F0b3IgY2FuIG9ubHkgaGF2ZSBvbmUgZGlnaXQuXG4gIGlmIChzdHJpbmdbMF0gPT09ICcgJyAmJiBpbmRlbnRQZXJMZXZlbCA+IDkpIHtcbiAgICByZXR1cm4gU1RZTEVfRE9VQkxFO1xuICB9XG4gIC8vIEF0IHRoaXMgcG9pbnQgd2Uga25vdyBibG9jayBzdHlsZXMgYXJlIHZhbGlkLlxuICAvLyBQcmVmZXIgbGl0ZXJhbCBzdHlsZSB1bmxlc3Mgd2Ugd2FudCB0byBmb2xkLlxuICByZXR1cm4gaGFzRm9sZGFibGVMaW5lID8gU1RZTEVfRk9MREVEIDogU1RZTEVfTElURVJBTDtcbn1cblxuLy8gTm90ZTogbGluZSBicmVha2luZy9mb2xkaW5nIGlzIGltcGxlbWVudGVkIGZvciBvbmx5IHRoZSBmb2xkZWQgc3R5bGUuXG4vLyBOQi4gV2UgZHJvcCB0aGUgbGFzdCB0cmFpbGluZyBuZXdsaW5lIChpZiBhbnkpIG9mIGEgcmV0dXJuZWQgYmxvY2sgc2NhbGFyXG4vLyAgc2luY2UgdGhlIGR1bXBlciBhZGRzIGl0cyBvd24gbmV3bGluZS4gVGhpcyBhbHdheXMgd29ya3M6XG4vLyAgICDigKIgTm8gZW5kaW5nIG5ld2xpbmUgPT4gdW5hZmZlY3RlZDsgYWxyZWFkeSB1c2luZyBzdHJpcCBcIi1cIiBjaG9tcGluZy5cbi8vICAgIOKAoiBFbmRpbmcgbmV3bGluZSAgICA9PiByZW1vdmVkIHRoZW4gcmVzdG9yZWQuXG4vLyAgSW1wb3J0YW50bHksIHRoaXMga2VlcHMgdGhlIFwiK1wiIGNob21wIGluZGljYXRvciBmcm9tIGdhaW5pbmcgYW4gZXh0cmEgbGluZS5cbmZ1bmN0aW9uIHdyaXRlU2NhbGFyKHN0YXRlLCBzdHJpbmcsIGxldmVsLCBpc2tleSkge1xuICBzdGF0ZS5kdW1wID0gKGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoc3RyaW5nLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIFwiJydcIjtcbiAgICB9XG4gICAgaWYgKCFzdGF0ZS5ub0NvbXBhdE1vZGUgJiZcbiAgICAgICAgREVQUkVDQVRFRF9CT09MRUFOU19TWU5UQVguaW5kZXhPZihzdHJpbmcpICE9PSAtMSkge1xuICAgICAgcmV0dXJuIFwiJ1wiICsgc3RyaW5nICsgXCInXCI7XG4gICAgfVxuXG4gICAgdmFyIGluZGVudCA9IHN0YXRlLmluZGVudCAqIE1hdGgubWF4KDEsIGxldmVsKTsgLy8gbm8gMC1pbmRlbnQgc2NhbGFyc1xuICAgIC8vIEFzIGluZGVudGF0aW9uIGdldHMgZGVlcGVyLCBsZXQgdGhlIHdpZHRoIGRlY3JlYXNlIG1vbm90b25pY2FsbHlcbiAgICAvLyB0byB0aGUgbG93ZXIgYm91bmQgbWluKHN0YXRlLmxpbmVXaWR0aCwgNDApLlxuICAgIC8vIE5vdGUgdGhhdCB0aGlzIGltcGxpZXNcbiAgICAvLyAgc3RhdGUubGluZVdpZHRoIOKJpCA0MCArIHN0YXRlLmluZGVudDogd2lkdGggaXMgZml4ZWQgYXQgdGhlIGxvd2VyIGJvdW5kLlxuICAgIC8vICBzdGF0ZS5saW5lV2lkdGggPiA0MCArIHN0YXRlLmluZGVudDogd2lkdGggZGVjcmVhc2VzIHVudGlsIHRoZSBsb3dlciBib3VuZC5cbiAgICAvLyBUaGlzIGJlaGF2ZXMgYmV0dGVyIHRoYW4gYSBjb25zdGFudCBtaW5pbXVtIHdpZHRoIHdoaWNoIGRpc2FsbG93cyBuYXJyb3dlciBvcHRpb25zLFxuICAgIC8vIG9yIGFuIGluZGVudCB0aHJlc2hvbGQgd2hpY2ggY2F1c2VzIHRoZSB3aWR0aCB0byBzdWRkZW5seSBpbmNyZWFzZS5cbiAgICB2YXIgbGluZVdpZHRoID0gc3RhdGUubGluZVdpZHRoID09PSAtMVxuICAgICAgPyAtMSA6IE1hdGgubWF4KE1hdGgubWluKHN0YXRlLmxpbmVXaWR0aCwgNDApLCBzdGF0ZS5saW5lV2lkdGggLSBpbmRlbnQpO1xuXG4gICAgLy8gV2l0aG91dCBrbm93aW5nIGlmIGtleXMgYXJlIGltcGxpY2l0L2V4cGxpY2l0LCBhc3N1bWUgaW1wbGljaXQgZm9yIHNhZmV0eS5cbiAgICB2YXIgc2luZ2xlTGluZU9ubHkgPSBpc2tleVxuICAgICAgLy8gTm8gYmxvY2sgc3R5bGVzIGluIGZsb3cgbW9kZS5cbiAgICAgIHx8IChzdGF0ZS5mbG93TGV2ZWwgPiAtMSAmJiBsZXZlbCA+PSBzdGF0ZS5mbG93TGV2ZWwpO1xuICAgIGZ1bmN0aW9uIHRlc3RBbWJpZ3VpdHkoc3RyaW5nKSB7XG4gICAgICByZXR1cm4gdGVzdEltcGxpY2l0UmVzb2x2aW5nKHN0YXRlLCBzdHJpbmcpO1xuICAgIH1cblxuICAgIHN3aXRjaCAoY2hvb3NlU2NhbGFyU3R5bGUoc3RyaW5nLCBzaW5nbGVMaW5lT25seSwgc3RhdGUuaW5kZW50LCBsaW5lV2lkdGgsIHRlc3RBbWJpZ3VpdHkpKSB7XG4gICAgICBjYXNlIFNUWUxFX1BMQUlOOlxuICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgY2FzZSBTVFlMRV9TSU5HTEU6XG4gICAgICAgIHJldHVybiBcIidcIiArIHN0cmluZy5yZXBsYWNlKC8nL2csIFwiJydcIikgKyBcIidcIjtcbiAgICAgIGNhc2UgU1RZTEVfTElURVJBTDpcbiAgICAgICAgcmV0dXJuICd8JyArIGJsb2NrSGVhZGVyKHN0cmluZywgc3RhdGUuaW5kZW50KVxuICAgICAgICAgICsgZHJvcEVuZGluZ05ld2xpbmUoaW5kZW50U3RyaW5nKHN0cmluZywgaW5kZW50KSk7XG4gICAgICBjYXNlIFNUWUxFX0ZPTERFRDpcbiAgICAgICAgcmV0dXJuICc+JyArIGJsb2NrSGVhZGVyKHN0cmluZywgc3RhdGUuaW5kZW50KVxuICAgICAgICAgICsgZHJvcEVuZGluZ05ld2xpbmUoaW5kZW50U3RyaW5nKGZvbGRTdHJpbmcoc3RyaW5nLCBsaW5lV2lkdGgpLCBpbmRlbnQpKTtcbiAgICAgIGNhc2UgU1RZTEVfRE9VQkxFOlxuICAgICAgICByZXR1cm4gJ1wiJyArIGVzY2FwZVN0cmluZyhzdHJpbmcsIGxpbmVXaWR0aCkgKyAnXCInO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IFlBTUxFeGNlcHRpb24oJ2ltcG9zc2libGUgZXJyb3I6IGludmFsaWQgc2NhbGFyIHN0eWxlJyk7XG4gICAgfVxuICB9KCkpO1xufVxuXG4vLyBQcmUtY29uZGl0aW9uczogc3RyaW5nIGlzIHZhbGlkIGZvciBhIGJsb2NrIHNjYWxhciwgMSA8PSBpbmRlbnRQZXJMZXZlbCA8PSA5LlxuZnVuY3Rpb24gYmxvY2tIZWFkZXIoc3RyaW5nLCBpbmRlbnRQZXJMZXZlbCkge1xuICB2YXIgaW5kZW50SW5kaWNhdG9yID0gKHN0cmluZ1swXSA9PT0gJyAnKSA/IFN0cmluZyhpbmRlbnRQZXJMZXZlbCkgOiAnJztcblxuICAvLyBub3RlIHRoZSBzcGVjaWFsIGNhc2U6IHRoZSBzdHJpbmcgJ1xcbicgY291bnRzIGFzIGEgXCJ0cmFpbGluZ1wiIGVtcHR5IGxpbmUuXG4gIHZhciBjbGlwID0gICAgICAgICAgc3RyaW5nW3N0cmluZy5sZW5ndGggLSAxXSA9PT0gJ1xcbic7XG4gIHZhciBrZWVwID0gY2xpcCAmJiAoc3RyaW5nW3N0cmluZy5sZW5ndGggLSAyXSA9PT0gJ1xcbicgfHwgc3RyaW5nID09PSAnXFxuJyk7XG4gIHZhciBjaG9tcCA9IGtlZXAgPyAnKycgOiAoY2xpcCA/ICcnIDogJy0nKTtcblxuICByZXR1cm4gaW5kZW50SW5kaWNhdG9yICsgY2hvbXAgKyAnXFxuJztcbn1cblxuLy8gKFNlZSB0aGUgbm90ZSBmb3Igd3JpdGVTY2FsYXIuKVxuZnVuY3Rpb24gZHJvcEVuZGluZ05ld2xpbmUoc3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmdbc3RyaW5nLmxlbmd0aCAtIDFdID09PSAnXFxuJyA/IHN0cmluZy5zbGljZSgwLCAtMSkgOiBzdHJpbmc7XG59XG5cbi8vIE5vdGU6IGEgbG9uZyBsaW5lIHdpdGhvdXQgYSBzdWl0YWJsZSBicmVhayBwb2ludCB3aWxsIGV4Y2VlZCB0aGUgd2lkdGggbGltaXQuXG4vLyBQcmUtY29uZGl0aW9uczogZXZlcnkgY2hhciBpbiBzdHIgaXNQcmludGFibGUsIHN0ci5sZW5ndGggPiAwLCB3aWR0aCA+IDAuXG5mdW5jdGlvbiBmb2xkU3RyaW5nKHN0cmluZywgd2lkdGgpIHtcbiAgLy8gSW4gZm9sZGVkIHN0eWxlLCAkayQgY29uc2VjdXRpdmUgbmV3bGluZXMgb3V0cHV0IGFzICRrKzEkIG5ld2xpbmVz4oCUXG4gIC8vIHVubGVzcyB0aGV5J3JlIGJlZm9yZSBvciBhZnRlciBhIG1vcmUtaW5kZW50ZWQgbGluZSwgb3IgYXQgdGhlIHZlcnlcbiAgLy8gYmVnaW5uaW5nIG9yIGVuZCwgaW4gd2hpY2ggY2FzZSAkayQgbWFwcyB0byAkayQuXG4gIC8vIFRoZXJlZm9yZSwgcGFyc2UgZWFjaCBjaHVuayBhcyBuZXdsaW5lKHMpIGZvbGxvd2VkIGJ5IGEgY29udGVudCBsaW5lLlxuICB2YXIgbGluZVJlID0gLyhcXG4rKShbXlxcbl0qKS9nO1xuXG4gIC8vIGZpcnN0IGxpbmUgKHBvc3NpYmx5IGFuIGVtcHR5IGxpbmUpXG4gIHZhciByZXN1bHQgPSAoZnVuY3Rpb24gKCkge1xuICAgIHZhciBuZXh0TEYgPSBzdHJpbmcuaW5kZXhPZignXFxuJyk7XG4gICAgbmV4dExGID0gbmV4dExGICE9PSAtMSA/IG5leHRMRiA6IHN0cmluZy5sZW5ndGg7XG4gICAgbGluZVJlLmxhc3RJbmRleCA9IG5leHRMRjtcbiAgICByZXR1cm4gZm9sZExpbmUoc3RyaW5nLnNsaWNlKDAsIG5leHRMRiksIHdpZHRoKTtcbiAgfSgpKTtcbiAgLy8gSWYgd2UgaGF2ZW4ndCByZWFjaGVkIHRoZSBmaXJzdCBjb250ZW50IGxpbmUgeWV0LCBkb24ndCBhZGQgYW4gZXh0cmEgXFxuLlxuICB2YXIgcHJldk1vcmVJbmRlbnRlZCA9IHN0cmluZ1swXSA9PT0gJ1xcbicgfHwgc3RyaW5nWzBdID09PSAnICc7XG4gIHZhciBtb3JlSW5kZW50ZWQ7XG5cbiAgLy8gcmVzdCBvZiB0aGUgbGluZXNcbiAgdmFyIG1hdGNoO1xuICB3aGlsZSAoKG1hdGNoID0gbGluZVJlLmV4ZWMoc3RyaW5nKSkpIHtcbiAgICB2YXIgcHJlZml4ID0gbWF0Y2hbMV0sIGxpbmUgPSBtYXRjaFsyXTtcbiAgICBtb3JlSW5kZW50ZWQgPSAobGluZVswXSA9PT0gJyAnKTtcbiAgICByZXN1bHQgKz0gcHJlZml4XG4gICAgICArICghcHJldk1vcmVJbmRlbnRlZCAmJiAhbW9yZUluZGVudGVkICYmIGxpbmUgIT09ICcnXG4gICAgICAgID8gJ1xcbicgOiAnJylcbiAgICAgICsgZm9sZExpbmUobGluZSwgd2lkdGgpO1xuICAgIHByZXZNb3JlSW5kZW50ZWQgPSBtb3JlSW5kZW50ZWQ7XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG4vLyBHcmVlZHkgbGluZSBicmVha2luZy5cbi8vIFBpY2tzIHRoZSBsb25nZXN0IGxpbmUgdW5kZXIgdGhlIGxpbWl0IGVhY2ggdGltZSxcbi8vIG90aGVyd2lzZSBzZXR0bGVzIGZvciB0aGUgc2hvcnRlc3QgbGluZSBvdmVyIHRoZSBsaW1pdC5cbi8vIE5CLiBNb3JlLWluZGVudGVkIGxpbmVzICpjYW5ub3QqIGJlIGZvbGRlZCwgYXMgdGhhdCB3b3VsZCBhZGQgYW4gZXh0cmEgXFxuLlxuZnVuY3Rpb24gZm9sZExpbmUobGluZSwgd2lkdGgpIHtcbiAgaWYgKGxpbmUgPT09ICcnIHx8IGxpbmVbMF0gPT09ICcgJykgcmV0dXJuIGxpbmU7XG5cbiAgLy8gU2luY2UgYSBtb3JlLWluZGVudGVkIGxpbmUgYWRkcyBhIFxcbiwgYnJlYWtzIGNhbid0IGJlIGZvbGxvd2VkIGJ5IGEgc3BhY2UuXG4gIHZhciBicmVha1JlID0gLyBbXiBdL2c7IC8vIG5vdGU6IHRoZSBtYXRjaCBpbmRleCB3aWxsIGFsd2F5cyBiZSA8PSBsZW5ndGgtMi5cbiAgdmFyIG1hdGNoO1xuICAvLyBzdGFydCBpcyBhbiBpbmNsdXNpdmUgaW5kZXguIGVuZCwgY3VyciwgYW5kIG5leHQgYXJlIGV4Y2x1c2l2ZS5cbiAgdmFyIHN0YXJ0ID0gMCwgZW5kLCBjdXJyID0gMCwgbmV4dCA9IDA7XG4gIHZhciByZXN1bHQgPSAnJztcblxuICAvLyBJbnZhcmlhbnRzOiAwIDw9IHN0YXJ0IDw9IGxlbmd0aC0xLlxuICAvLyAgIDAgPD0gY3VyciA8PSBuZXh0IDw9IG1heCgwLCBsZW5ndGgtMikuIGN1cnIgLSBzdGFydCA8PSB3aWR0aC5cbiAgLy8gSW5zaWRlIHRoZSBsb29wOlxuICAvLyAgIEEgbWF0Y2ggaW1wbGllcyBsZW5ndGggPj0gMiwgc28gY3VyciBhbmQgbmV4dCBhcmUgPD0gbGVuZ3RoLTIuXG4gIHdoaWxlICgobWF0Y2ggPSBicmVha1JlLmV4ZWMobGluZSkpKSB7XG4gICAgbmV4dCA9IG1hdGNoLmluZGV4O1xuICAgIC8vIG1haW50YWluIGludmFyaWFudDogY3VyciAtIHN0YXJ0IDw9IHdpZHRoXG4gICAgaWYgKG5leHQgLSBzdGFydCA+IHdpZHRoKSB7XG4gICAgICBlbmQgPSAoY3VyciA+IHN0YXJ0KSA/IGN1cnIgOiBuZXh0OyAvLyBkZXJpdmUgZW5kIDw9IGxlbmd0aC0yXG4gICAgICByZXN1bHQgKz0gJ1xcbicgKyBsaW5lLnNsaWNlKHN0YXJ0LCBlbmQpO1xuICAgICAgLy8gc2tpcCB0aGUgc3BhY2UgdGhhdCB3YXMgb3V0cHV0IGFzIFxcblxuICAgICAgc3RhcnQgPSBlbmQgKyAxOyAgICAgICAgICAgICAgICAgICAgLy8gZGVyaXZlIHN0YXJ0IDw9IGxlbmd0aC0xXG4gICAgfVxuICAgIGN1cnIgPSBuZXh0O1xuICB9XG5cbiAgLy8gQnkgdGhlIGludmFyaWFudHMsIHN0YXJ0IDw9IGxlbmd0aC0xLCBzbyB0aGVyZSBpcyBzb21ldGhpbmcgbGVmdCBvdmVyLlxuICAvLyBJdCBpcyBlaXRoZXIgdGhlIHdob2xlIHN0cmluZyBvciBhIHBhcnQgc3RhcnRpbmcgZnJvbSBub24td2hpdGVzcGFjZS5cbiAgcmVzdWx0ICs9ICdcXG4nO1xuICAvLyBJbnNlcnQgYSBicmVhayBpZiB0aGUgcmVtYWluZGVyIGlzIHRvbyBsb25nIGFuZCB0aGVyZSBpcyBhIGJyZWFrIGF2YWlsYWJsZS5cbiAgaWYgKGxpbmUubGVuZ3RoIC0gc3RhcnQgPiB3aWR0aCAmJiBjdXJyID4gc3RhcnQpIHtcbiAgICByZXN1bHQgKz0gbGluZS5zbGljZShzdGFydCwgY3VycikgKyAnXFxuJyArIGxpbmUuc2xpY2UoY3VyciArIDEpO1xuICB9IGVsc2Uge1xuICAgIHJlc3VsdCArPSBsaW5lLnNsaWNlKHN0YXJ0KTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQuc2xpY2UoMSk7IC8vIGRyb3AgZXh0cmEgXFxuIGpvaW5lclxufVxuXG4vLyBFc2NhcGVzIGEgZG91YmxlLXF1b3RlZCBzdHJpbmcuXG5mdW5jdGlvbiBlc2NhcGVTdHJpbmcoc3RyaW5nKSB7XG4gIHZhciByZXN1bHQgPSAnJztcbiAgdmFyIGNoYXI7XG4gIHZhciBlc2NhcGVTZXE7XG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHJpbmcubGVuZ3RoOyBpKyspIHtcbiAgICBjaGFyID0gc3RyaW5nLmNoYXJDb2RlQXQoaSk7XG4gICAgZXNjYXBlU2VxID0gRVNDQVBFX1NFUVVFTkNFU1tjaGFyXTtcbiAgICByZXN1bHQgKz0gIWVzY2FwZVNlcSAmJiBpc1ByaW50YWJsZShjaGFyKVxuICAgICAgPyBzdHJpbmdbaV1cbiAgICAgIDogZXNjYXBlU2VxIHx8IGVuY29kZUhleChjaGFyKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIHdyaXRlRmxvd1NlcXVlbmNlKHN0YXRlLCBsZXZlbCwgb2JqZWN0KSB7XG4gIHZhciBfcmVzdWx0ID0gJycsXG4gICAgICBfdGFnICAgID0gc3RhdGUudGFnLFxuICAgICAgaW5kZXgsXG4gICAgICBsZW5ndGg7XG5cbiAgZm9yIChpbmRleCA9IDAsIGxlbmd0aCA9IG9iamVjdC5sZW5ndGg7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgLy8gV3JpdGUgb25seSB2YWxpZCBlbGVtZW50cy5cbiAgICBpZiAod3JpdGVOb2RlKHN0YXRlLCBsZXZlbCwgb2JqZWN0W2luZGV4XSwgZmFsc2UsIGZhbHNlKSkge1xuICAgICAgaWYgKGluZGV4ICE9PSAwKSBfcmVzdWx0ICs9ICcsICc7XG4gICAgICBfcmVzdWx0ICs9IHN0YXRlLmR1bXA7XG4gICAgfVxuICB9XG5cbiAgc3RhdGUudGFnID0gX3RhZztcbiAgc3RhdGUuZHVtcCA9ICdbJyArIF9yZXN1bHQgKyAnXSc7XG59XG5cbmZ1bmN0aW9uIHdyaXRlQmxvY2tTZXF1ZW5jZShzdGF0ZSwgbGV2ZWwsIG9iamVjdCwgY29tcGFjdCkge1xuICB2YXIgX3Jlc3VsdCA9ICcnLFxuICAgICAgX3RhZyAgICA9IHN0YXRlLnRhZyxcbiAgICAgIGluZGV4LFxuICAgICAgbGVuZ3RoO1xuXG4gIGZvciAoaW5kZXggPSAwLCBsZW5ndGggPSBvYmplY3QubGVuZ3RoOyBpbmRleCA8IGxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgIC8vIFdyaXRlIG9ubHkgdmFsaWQgZWxlbWVudHMuXG4gICAgaWYgKHdyaXRlTm9kZShzdGF0ZSwgbGV2ZWwgKyAxLCBvYmplY3RbaW5kZXhdLCB0cnVlLCB0cnVlKSkge1xuICAgICAgaWYgKCFjb21wYWN0IHx8IGluZGV4ICE9PSAwKSB7XG4gICAgICAgIF9yZXN1bHQgKz0gZ2VuZXJhdGVOZXh0TGluZShzdGF0ZSwgbGV2ZWwpO1xuICAgICAgfVxuICAgICAgX3Jlc3VsdCArPSAnLSAnICsgc3RhdGUuZHVtcDtcbiAgICB9XG4gIH1cblxuICBzdGF0ZS50YWcgPSBfdGFnO1xuICBzdGF0ZS5kdW1wID0gX3Jlc3VsdCB8fCAnW10nOyAvLyBFbXB0eSBzZXF1ZW5jZSBpZiBubyB2YWxpZCB2YWx1ZXMuXG59XG5cbmZ1bmN0aW9uIHdyaXRlRmxvd01hcHBpbmcoc3RhdGUsIGxldmVsLCBvYmplY3QpIHtcbiAgdmFyIF9yZXN1bHQgICAgICAgPSAnJyxcbiAgICAgIF90YWcgICAgICAgICAgPSBzdGF0ZS50YWcsXG4gICAgICBvYmplY3RLZXlMaXN0ID0gT2JqZWN0LmtleXMob2JqZWN0KSxcbiAgICAgIGluZGV4LFxuICAgICAgbGVuZ3RoLFxuICAgICAgb2JqZWN0S2V5LFxuICAgICAgb2JqZWN0VmFsdWUsXG4gICAgICBwYWlyQnVmZmVyO1xuXG4gIGZvciAoaW5kZXggPSAwLCBsZW5ndGggPSBvYmplY3RLZXlMaXN0Lmxlbmd0aDsgaW5kZXggPCBsZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICBwYWlyQnVmZmVyID0gJyc7XG5cbiAgICBpZiAoaW5kZXggIT09IDApIHBhaXJCdWZmZXIgKz0gJywgJztcblxuICAgIG9iamVjdEtleSA9IG9iamVjdEtleUxpc3RbaW5kZXhdO1xuICAgIG9iamVjdFZhbHVlID0gb2JqZWN0W29iamVjdEtleV07XG5cbiAgICBpZiAoIXdyaXRlTm9kZShzdGF0ZSwgbGV2ZWwsIG9iamVjdEtleSwgZmFsc2UsIGZhbHNlKSkge1xuICAgICAgY29udGludWU7IC8vIFNraXAgdGhpcyBwYWlyIGJlY2F1c2Ugb2YgaW52YWxpZCBrZXk7XG4gICAgfVxuXG4gICAgaWYgKHN0YXRlLmR1bXAubGVuZ3RoID4gMTAyNCkgcGFpckJ1ZmZlciArPSAnPyAnO1xuXG4gICAgcGFpckJ1ZmZlciArPSBzdGF0ZS5kdW1wICsgJzogJztcblxuICAgIGlmICghd3JpdGVOb2RlKHN0YXRlLCBsZXZlbCwgb2JqZWN0VmFsdWUsIGZhbHNlLCBmYWxzZSkpIHtcbiAgICAgIGNvbnRpbnVlOyAvLyBTa2lwIHRoaXMgcGFpciBiZWNhdXNlIG9mIGludmFsaWQgdmFsdWUuXG4gICAgfVxuXG4gICAgcGFpckJ1ZmZlciArPSBzdGF0ZS5kdW1wO1xuXG4gICAgLy8gQm90aCBrZXkgYW5kIHZhbHVlIGFyZSB2YWxpZC5cbiAgICBfcmVzdWx0ICs9IHBhaXJCdWZmZXI7XG4gIH1cblxuICBzdGF0ZS50YWcgPSBfdGFnO1xuICBzdGF0ZS5kdW1wID0gJ3snICsgX3Jlc3VsdCArICd9Jztcbn1cblxuZnVuY3Rpb24gd3JpdGVCbG9ja01hcHBpbmcoc3RhdGUsIGxldmVsLCBvYmplY3QsIGNvbXBhY3QpIHtcbiAgdmFyIF9yZXN1bHQgICAgICAgPSAnJyxcbiAgICAgIF90YWcgICAgICAgICAgPSBzdGF0ZS50YWcsXG4gICAgICBvYmplY3RLZXlMaXN0ID0gT2JqZWN0LmtleXMob2JqZWN0KSxcbiAgICAgIGluZGV4LFxuICAgICAgbGVuZ3RoLFxuICAgICAgb2JqZWN0S2V5LFxuICAgICAgb2JqZWN0VmFsdWUsXG4gICAgICBleHBsaWNpdFBhaXIsXG4gICAgICBwYWlyQnVmZmVyO1xuXG4gIC8vIEFsbG93IHNvcnRpbmcga2V5cyBzbyB0aGF0IHRoZSBvdXRwdXQgZmlsZSBpcyBkZXRlcm1pbmlzdGljXG4gIGlmIChzdGF0ZS5zb3J0S2V5cyA9PT0gdHJ1ZSkge1xuICAgIC8vIERlZmF1bHQgc29ydGluZ1xuICAgIG9iamVjdEtleUxpc3Quc29ydCgpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBzdGF0ZS5zb3J0S2V5cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIC8vIEN1c3RvbSBzb3J0IGZ1bmN0aW9uXG4gICAgb2JqZWN0S2V5TGlzdC5zb3J0KHN0YXRlLnNvcnRLZXlzKTtcbiAgfSBlbHNlIGlmIChzdGF0ZS5zb3J0S2V5cykge1xuICAgIC8vIFNvbWV0aGluZyBpcyB3cm9uZ1xuICAgIHRocm93IG5ldyBZQU1MRXhjZXB0aW9uKCdzb3J0S2V5cyBtdXN0IGJlIGEgYm9vbGVhbiBvciBhIGZ1bmN0aW9uJyk7XG4gIH1cblxuICBmb3IgKGluZGV4ID0gMCwgbGVuZ3RoID0gb2JqZWN0S2V5TGlzdC5sZW5ndGg7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgcGFpckJ1ZmZlciA9ICcnO1xuXG4gICAgaWYgKCFjb21wYWN0IHx8IGluZGV4ICE9PSAwKSB7XG4gICAgICBwYWlyQnVmZmVyICs9IGdlbmVyYXRlTmV4dExpbmUoc3RhdGUsIGxldmVsKTtcbiAgICB9XG5cbiAgICBvYmplY3RLZXkgPSBvYmplY3RLZXlMaXN0W2luZGV4XTtcbiAgICBvYmplY3RWYWx1ZSA9IG9iamVjdFtvYmplY3RLZXldO1xuXG4gICAgaWYgKCF3cml0ZU5vZGUoc3RhdGUsIGxldmVsICsgMSwgb2JqZWN0S2V5LCB0cnVlLCB0cnVlLCB0cnVlKSkge1xuICAgICAgY29udGludWU7IC8vIFNraXAgdGhpcyBwYWlyIGJlY2F1c2Ugb2YgaW52YWxpZCBrZXkuXG4gICAgfVxuXG4gICAgZXhwbGljaXRQYWlyID0gKHN0YXRlLnRhZyAhPT0gbnVsbCAmJiBzdGF0ZS50YWcgIT09ICc/JykgfHxcbiAgICAgICAgICAgICAgICAgICAoc3RhdGUuZHVtcCAmJiBzdGF0ZS5kdW1wLmxlbmd0aCA+IDEwMjQpO1xuXG4gICAgaWYgKGV4cGxpY2l0UGFpcikge1xuICAgICAgaWYgKHN0YXRlLmR1bXAgJiYgQ0hBUl9MSU5FX0ZFRUQgPT09IHN0YXRlLmR1bXAuY2hhckNvZGVBdCgwKSkge1xuICAgICAgICBwYWlyQnVmZmVyICs9ICc/JztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHBhaXJCdWZmZXIgKz0gJz8gJztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwYWlyQnVmZmVyICs9IHN0YXRlLmR1bXA7XG5cbiAgICBpZiAoZXhwbGljaXRQYWlyKSB7XG4gICAgICBwYWlyQnVmZmVyICs9IGdlbmVyYXRlTmV4dExpbmUoc3RhdGUsIGxldmVsKTtcbiAgICB9XG5cbiAgICBpZiAoIXdyaXRlTm9kZShzdGF0ZSwgbGV2ZWwgKyAxLCBvYmplY3RWYWx1ZSwgdHJ1ZSwgZXhwbGljaXRQYWlyKSkge1xuICAgICAgY29udGludWU7IC8vIFNraXAgdGhpcyBwYWlyIGJlY2F1c2Ugb2YgaW52YWxpZCB2YWx1ZS5cbiAgICB9XG5cbiAgICBpZiAoc3RhdGUuZHVtcCAmJiBDSEFSX0xJTkVfRkVFRCA9PT0gc3RhdGUuZHVtcC5jaGFyQ29kZUF0KDApKSB7XG4gICAgICBwYWlyQnVmZmVyICs9ICc6JztcbiAgICB9IGVsc2Uge1xuICAgICAgcGFpckJ1ZmZlciArPSAnOiAnO1xuICAgIH1cblxuICAgIHBhaXJCdWZmZXIgKz0gc3RhdGUuZHVtcDtcblxuICAgIC8vIEJvdGgga2V5IGFuZCB2YWx1ZSBhcmUgdmFsaWQuXG4gICAgX3Jlc3VsdCArPSBwYWlyQnVmZmVyO1xuICB9XG5cbiAgc3RhdGUudGFnID0gX3RhZztcbiAgc3RhdGUuZHVtcCA9IF9yZXN1bHQgfHwgJ3t9JzsgLy8gRW1wdHkgbWFwcGluZyBpZiBubyB2YWxpZCBwYWlycy5cbn1cblxuZnVuY3Rpb24gZGV0ZWN0VHlwZShzdGF0ZSwgb2JqZWN0LCBleHBsaWNpdCkge1xuICB2YXIgX3Jlc3VsdCwgdHlwZUxpc3QsIGluZGV4LCBsZW5ndGgsIHR5cGUsIHN0eWxlO1xuXG4gIHR5cGVMaXN0ID0gZXhwbGljaXQgPyBzdGF0ZS5leHBsaWNpdFR5cGVzIDogc3RhdGUuaW1wbGljaXRUeXBlcztcblxuICBmb3IgKGluZGV4ID0gMCwgbGVuZ3RoID0gdHlwZUxpc3QubGVuZ3RoOyBpbmRleCA8IGxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgIHR5cGUgPSB0eXBlTGlzdFtpbmRleF07XG5cbiAgICBpZiAoKHR5cGUuaW5zdGFuY2VPZiAgfHwgdHlwZS5wcmVkaWNhdGUpICYmXG4gICAgICAgICghdHlwZS5pbnN0YW5jZU9mIHx8ICgodHlwZW9mIG9iamVjdCA9PT0gJ29iamVjdCcpICYmIChvYmplY3QgaW5zdGFuY2VvZiB0eXBlLmluc3RhbmNlT2YpKSkgJiZcbiAgICAgICAgKCF0eXBlLnByZWRpY2F0ZSAgfHwgdHlwZS5wcmVkaWNhdGUob2JqZWN0KSkpIHtcblxuICAgICAgc3RhdGUudGFnID0gZXhwbGljaXQgPyB0eXBlLnRhZyA6ICc/JztcblxuICAgICAgaWYgKHR5cGUucmVwcmVzZW50KSB7XG4gICAgICAgIHN0eWxlID0gc3RhdGUuc3R5bGVNYXBbdHlwZS50YWddIHx8IHR5cGUuZGVmYXVsdFN0eWxlO1xuXG4gICAgICAgIGlmIChfdG9TdHJpbmcuY2FsbCh0eXBlLnJlcHJlc2VudCkgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXScpIHtcbiAgICAgICAgICBfcmVzdWx0ID0gdHlwZS5yZXByZXNlbnQob2JqZWN0LCBzdHlsZSk7XG4gICAgICAgIH0gZWxzZSBpZiAoX2hhc093blByb3BlcnR5LmNhbGwodHlwZS5yZXByZXNlbnQsIHN0eWxlKSkge1xuICAgICAgICAgIF9yZXN1bHQgPSB0eXBlLnJlcHJlc2VudFtzdHlsZV0ob2JqZWN0LCBzdHlsZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFlBTUxFeGNlcHRpb24oJyE8JyArIHR5cGUudGFnICsgJz4gdGFnIHJlc29sdmVyIGFjY2VwdHMgbm90IFwiJyArIHN0eWxlICsgJ1wiIHN0eWxlJyk7XG4gICAgICAgIH1cblxuICAgICAgICBzdGF0ZS5kdW1wID0gX3Jlc3VsdDtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG4vLyBTZXJpYWxpemVzIGBvYmplY3RgIGFuZCB3cml0ZXMgaXQgdG8gZ2xvYmFsIGByZXN1bHRgLlxuLy8gUmV0dXJucyB0cnVlIG9uIHN1Y2Nlc3MsIG9yIGZhbHNlIG9uIGludmFsaWQgb2JqZWN0LlxuLy9cbmZ1bmN0aW9uIHdyaXRlTm9kZShzdGF0ZSwgbGV2ZWwsIG9iamVjdCwgYmxvY2ssIGNvbXBhY3QsIGlza2V5KSB7XG4gIHN0YXRlLnRhZyA9IG51bGw7XG4gIHN0YXRlLmR1bXAgPSBvYmplY3Q7XG5cbiAgaWYgKCFkZXRlY3RUeXBlKHN0YXRlLCBvYmplY3QsIGZhbHNlKSkge1xuICAgIGRldGVjdFR5cGUoc3RhdGUsIG9iamVjdCwgdHJ1ZSk7XG4gIH1cblxuICB2YXIgdHlwZSA9IF90b1N0cmluZy5jYWxsKHN0YXRlLmR1bXApO1xuXG4gIGlmIChibG9jaykge1xuICAgIGJsb2NrID0gKHN0YXRlLmZsb3dMZXZlbCA8IDAgfHwgc3RhdGUuZmxvd0xldmVsID4gbGV2ZWwpO1xuICB9XG5cbiAgdmFyIG9iamVjdE9yQXJyYXkgPSB0eXBlID09PSAnW29iamVjdCBPYmplY3RdJyB8fCB0eXBlID09PSAnW29iamVjdCBBcnJheV0nLFxuICAgICAgZHVwbGljYXRlSW5kZXgsXG4gICAgICBkdXBsaWNhdGU7XG5cbiAgaWYgKG9iamVjdE9yQXJyYXkpIHtcbiAgICBkdXBsaWNhdGVJbmRleCA9IHN0YXRlLmR1cGxpY2F0ZXMuaW5kZXhPZihvYmplY3QpO1xuICAgIGR1cGxpY2F0ZSA9IGR1cGxpY2F0ZUluZGV4ICE9PSAtMTtcbiAgfVxuXG4gIGlmICgoc3RhdGUudGFnICE9PSBudWxsICYmIHN0YXRlLnRhZyAhPT0gJz8nKSB8fCBkdXBsaWNhdGUgfHwgKHN0YXRlLmluZGVudCAhPT0gMiAmJiBsZXZlbCA+IDApKSB7XG4gICAgY29tcGFjdCA9IGZhbHNlO1xuICB9XG5cbiAgaWYgKGR1cGxpY2F0ZSAmJiBzdGF0ZS51c2VkRHVwbGljYXRlc1tkdXBsaWNhdGVJbmRleF0pIHtcbiAgICBzdGF0ZS5kdW1wID0gJypyZWZfJyArIGR1cGxpY2F0ZUluZGV4O1xuICB9IGVsc2Uge1xuICAgIGlmIChvYmplY3RPckFycmF5ICYmIGR1cGxpY2F0ZSAmJiAhc3RhdGUudXNlZER1cGxpY2F0ZXNbZHVwbGljYXRlSW5kZXhdKSB7XG4gICAgICBzdGF0ZS51c2VkRHVwbGljYXRlc1tkdXBsaWNhdGVJbmRleF0gPSB0cnVlO1xuICAgIH1cbiAgICBpZiAodHlwZSA9PT0gJ1tvYmplY3QgT2JqZWN0XScpIHtcbiAgICAgIGlmIChibG9jayAmJiAoT2JqZWN0LmtleXMoc3RhdGUuZHVtcCkubGVuZ3RoICE9PSAwKSkge1xuICAgICAgICB3cml0ZUJsb2NrTWFwcGluZyhzdGF0ZSwgbGV2ZWwsIHN0YXRlLmR1bXAsIGNvbXBhY3QpO1xuICAgICAgICBpZiAoZHVwbGljYXRlKSB7XG4gICAgICAgICAgc3RhdGUuZHVtcCA9ICcmcmVmXycgKyBkdXBsaWNhdGVJbmRleCArIHN0YXRlLmR1bXA7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHdyaXRlRmxvd01hcHBpbmcoc3RhdGUsIGxldmVsLCBzdGF0ZS5kdW1wKTtcbiAgICAgICAgaWYgKGR1cGxpY2F0ZSkge1xuICAgICAgICAgIHN0YXRlLmR1bXAgPSAnJnJlZl8nICsgZHVwbGljYXRlSW5kZXggKyAnICcgKyBzdGF0ZS5kdW1wO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmICh0eXBlID09PSAnW29iamVjdCBBcnJheV0nKSB7XG4gICAgICBpZiAoYmxvY2sgJiYgKHN0YXRlLmR1bXAubGVuZ3RoICE9PSAwKSkge1xuICAgICAgICB3cml0ZUJsb2NrU2VxdWVuY2Uoc3RhdGUsIGxldmVsLCBzdGF0ZS5kdW1wLCBjb21wYWN0KTtcbiAgICAgICAgaWYgKGR1cGxpY2F0ZSkge1xuICAgICAgICAgIHN0YXRlLmR1bXAgPSAnJnJlZl8nICsgZHVwbGljYXRlSW5kZXggKyBzdGF0ZS5kdW1wO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB3cml0ZUZsb3dTZXF1ZW5jZShzdGF0ZSwgbGV2ZWwsIHN0YXRlLmR1bXApO1xuICAgICAgICBpZiAoZHVwbGljYXRlKSB7XG4gICAgICAgICAgc3RhdGUuZHVtcCA9ICcmcmVmXycgKyBkdXBsaWNhdGVJbmRleCArICcgJyArIHN0YXRlLmR1bXA7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdbb2JqZWN0IFN0cmluZ10nKSB7XG4gICAgICBpZiAoc3RhdGUudGFnICE9PSAnPycpIHtcbiAgICAgICAgd3JpdGVTY2FsYXIoc3RhdGUsIHN0YXRlLmR1bXAsIGxldmVsLCBpc2tleSk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChzdGF0ZS5za2lwSW52YWxpZCkgcmV0dXJuIGZhbHNlO1xuICAgICAgdGhyb3cgbmV3IFlBTUxFeGNlcHRpb24oJ3VuYWNjZXB0YWJsZSBraW5kIG9mIGFuIG9iamVjdCB0byBkdW1wICcgKyB0eXBlKTtcbiAgICB9XG5cbiAgICBpZiAoc3RhdGUudGFnICE9PSBudWxsICYmIHN0YXRlLnRhZyAhPT0gJz8nKSB7XG4gICAgICBzdGF0ZS5kdW1wID0gJyE8JyArIHN0YXRlLnRhZyArICc+ICcgKyBzdGF0ZS5kdW1wO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBnZXREdXBsaWNhdGVSZWZlcmVuY2VzKG9iamVjdCwgc3RhdGUpIHtcbiAgdmFyIG9iamVjdHMgPSBbXSxcbiAgICAgIGR1cGxpY2F0ZXNJbmRleGVzID0gW10sXG4gICAgICBpbmRleCxcbiAgICAgIGxlbmd0aDtcblxuICBpbnNwZWN0Tm9kZShvYmplY3QsIG9iamVjdHMsIGR1cGxpY2F0ZXNJbmRleGVzKTtcblxuICBmb3IgKGluZGV4ID0gMCwgbGVuZ3RoID0gZHVwbGljYXRlc0luZGV4ZXMubGVuZ3RoOyBpbmRleCA8IGxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgIHN0YXRlLmR1cGxpY2F0ZXMucHVzaChvYmplY3RzW2R1cGxpY2F0ZXNJbmRleGVzW2luZGV4XV0pO1xuICB9XG4gIHN0YXRlLnVzZWREdXBsaWNhdGVzID0gbmV3IEFycmF5KGxlbmd0aCk7XG59XG5cbmZ1bmN0aW9uIGluc3BlY3ROb2RlKG9iamVjdCwgb2JqZWN0cywgZHVwbGljYXRlc0luZGV4ZXMpIHtcbiAgdmFyIG9iamVjdEtleUxpc3QsXG4gICAgICBpbmRleCxcbiAgICAgIGxlbmd0aDtcblxuICBpZiAob2JqZWN0ICE9PSBudWxsICYmIHR5cGVvZiBvYmplY3QgPT09ICdvYmplY3QnKSB7XG4gICAgaW5kZXggPSBvYmplY3RzLmluZGV4T2Yob2JqZWN0KTtcbiAgICBpZiAoaW5kZXggIT09IC0xKSB7XG4gICAgICBpZiAoZHVwbGljYXRlc0luZGV4ZXMuaW5kZXhPZihpbmRleCkgPT09IC0xKSB7XG4gICAgICAgIGR1cGxpY2F0ZXNJbmRleGVzLnB1c2goaW5kZXgpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBvYmplY3RzLnB1c2gob2JqZWN0KTtcblxuICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqZWN0KSkge1xuICAgICAgICBmb3IgKGluZGV4ID0gMCwgbGVuZ3RoID0gb2JqZWN0Lmxlbmd0aDsgaW5kZXggPCBsZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgICAgICBpbnNwZWN0Tm9kZShvYmplY3RbaW5kZXhdLCBvYmplY3RzLCBkdXBsaWNhdGVzSW5kZXhlcyk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9iamVjdEtleUxpc3QgPSBPYmplY3Qua2V5cyhvYmplY3QpO1xuXG4gICAgICAgIGZvciAoaW5kZXggPSAwLCBsZW5ndGggPSBvYmplY3RLZXlMaXN0Lmxlbmd0aDsgaW5kZXggPCBsZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICAgICAgICBpbnNwZWN0Tm9kZShvYmplY3Rbb2JqZWN0S2V5TGlzdFtpbmRleF1dLCBvYmplY3RzLCBkdXBsaWNhdGVzSW5kZXhlcyk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZHVtcChpbnB1dCwgb3B0aW9ucykge1xuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICB2YXIgc3RhdGUgPSBuZXcgU3RhdGUob3B0aW9ucyk7XG5cbiAgaWYgKCFzdGF0ZS5ub1JlZnMpIGdldER1cGxpY2F0ZVJlZmVyZW5jZXMoaW5wdXQsIHN0YXRlKTtcblxuICBpZiAod3JpdGVOb2RlKHN0YXRlLCAwLCBpbnB1dCwgdHJ1ZSwgdHJ1ZSkpIHJldHVybiBzdGF0ZS5kdW1wICsgJ1xcbic7XG5cbiAgcmV0dXJuICcnO1xufVxuXG5mdW5jdGlvbiBzYWZlRHVtcChpbnB1dCwgb3B0aW9ucykge1xuICByZXR1cm4gZHVtcChpbnB1dCwgY29tbW9uLmV4dGVuZCh7IHNjaGVtYTogREVGQVVMVF9TQUZFX1NDSEVNQSB9LCBvcHRpb25zKSk7XG59XG5cbm1vZHVsZS5leHBvcnRzLmR1bXAgICAgID0gZHVtcDtcbm1vZHVsZS5leHBvcnRzLnNhZmVEdW1wID0gc2FmZUR1bXA7XG4iLCIvLyBZQU1MIGVycm9yIGNsYXNzLiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzg0NTg5ODRcbi8vXG4ndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIFlBTUxFeGNlcHRpb24ocmVhc29uLCBtYXJrKSB7XG4gIC8vIFN1cGVyIGNvbnN0cnVjdG9yXG4gIEVycm9yLmNhbGwodGhpcyk7XG5cbiAgLy8gSW5jbHVkZSBzdGFjayB0cmFjZSBpbiBlcnJvciBvYmplY3RcbiAgaWYgKEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKSB7XG4gICAgLy8gQ2hyb21lIGFuZCBOb2RlSlNcbiAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCB0aGlzLmNvbnN0cnVjdG9yKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBGRiwgSUUgMTArIGFuZCBTYWZhcmkgNisuIEZhbGxiYWNrIGZvciBvdGhlcnNcbiAgICB0aGlzLnN0YWNrID0gKG5ldyBFcnJvcigpKS5zdGFjayB8fCAnJztcbiAgfVxuXG4gIHRoaXMubmFtZSA9ICdZQU1MRXhjZXB0aW9uJztcbiAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gIHRoaXMubWFyayA9IG1hcms7XG4gIHRoaXMubWVzc2FnZSA9ICh0aGlzLnJlYXNvbiB8fCAnKHVua25vd24gcmVhc29uKScpICsgKHRoaXMubWFyayA/ICcgJyArIHRoaXMubWFyay50b1N0cmluZygpIDogJycpO1xufVxuXG5cbi8vIEluaGVyaXQgZnJvbSBFcnJvclxuWUFNTEV4Y2VwdGlvbi5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEVycm9yLnByb3RvdHlwZSk7XG5ZQU1MRXhjZXB0aW9uLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IFlBTUxFeGNlcHRpb247XG5cblxuWUFNTEV4Y2VwdGlvbi5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiB0b1N0cmluZyhjb21wYWN0KSB7XG4gIHZhciByZXN1bHQgPSB0aGlzLm5hbWUgKyAnOiAnO1xuXG4gIHJlc3VsdCArPSB0aGlzLnJlYXNvbiB8fCAnKHVua25vd24gcmVhc29uKSc7XG5cbiAgaWYgKCFjb21wYWN0ICYmIHRoaXMubWFyaykge1xuICAgIHJlc3VsdCArPSAnICcgKyB0aGlzLm1hcmsudG9TdHJpbmcoKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5cbm1vZHVsZS5leHBvcnRzID0gWUFNTEV4Y2VwdGlvbjtcbiIsIid1c2Ugc3RyaWN0JztcblxuLyplc2xpbnQtZGlzYWJsZSBtYXgtbGVuLG5vLXVzZS1iZWZvcmUtZGVmaW5lKi9cblxudmFyIGNvbW1vbiAgICAgICAgICAgICAgPSByZXF1aXJlKCcuL2NvbW1vbicpO1xudmFyIFlBTUxFeGNlcHRpb24gICAgICAgPSByZXF1aXJlKCcuL2V4Y2VwdGlvbicpO1xudmFyIE1hcmsgICAgICAgICAgICAgICAgPSByZXF1aXJlKCcuL21hcmsnKTtcbnZhciBERUZBVUxUX1NBRkVfU0NIRU1BID0gcmVxdWlyZSgnLi9zY2hlbWEvZGVmYXVsdF9zYWZlJyk7XG52YXIgREVGQVVMVF9GVUxMX1NDSEVNQSA9IHJlcXVpcmUoJy4vc2NoZW1hL2RlZmF1bHRfZnVsbCcpO1xuXG5cbnZhciBfaGFzT3duUHJvcGVydHkgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5O1xuXG5cbnZhciBDT05URVhUX0ZMT1dfSU4gICA9IDE7XG52YXIgQ09OVEVYVF9GTE9XX09VVCAgPSAyO1xudmFyIENPTlRFWFRfQkxPQ0tfSU4gID0gMztcbnZhciBDT05URVhUX0JMT0NLX09VVCA9IDQ7XG5cblxudmFyIENIT01QSU5HX0NMSVAgID0gMTtcbnZhciBDSE9NUElOR19TVFJJUCA9IDI7XG52YXIgQ0hPTVBJTkdfS0VFUCAgPSAzO1xuXG5cbnZhciBQQVRURVJOX05PTl9QUklOVEFCTEUgICAgICAgICA9IC9bXFx4MDAtXFx4MDhcXHgwQlxceDBDXFx4MEUtXFx4MUZcXHg3Ri1cXHg4NFxceDg2LVxceDlGXFx1RkZGRVxcdUZGRkZdfFtcXHVEODAwLVxcdURCRkZdKD8hW1xcdURDMDAtXFx1REZGRl0pfCg/OlteXFx1RDgwMC1cXHVEQkZGXXxeKVtcXHVEQzAwLVxcdURGRkZdLztcbnZhciBQQVRURVJOX05PTl9BU0NJSV9MSU5FX0JSRUFLUyA9IC9bXFx4ODVcXHUyMDI4XFx1MjAyOV0vO1xudmFyIFBBVFRFUk5fRkxPV19JTkRJQ0FUT1JTICAgICAgID0gL1ssXFxbXFxdXFx7XFx9XS87XG52YXIgUEFUVEVSTl9UQUdfSEFORExFICAgICAgICAgICAgPSAvXig/OiF8ISF8IVthLXpcXC1dKyEpJC9pO1xudmFyIFBBVFRFUk5fVEFHX1VSSSAgICAgICAgICAgICAgID0gL14oPzohfFteLFxcW1xcXVxce1xcfV0pKD86JVswLTlhLWZdezJ9fFswLTlhLXpcXC0jO1xcL1xcPzpAJj1cXCtcXCQsX1xcLiF+XFwqJ1xcKFxcKVxcW1xcXV0pKiQvaTtcblxuXG5mdW5jdGlvbiBpc19FT0woYykge1xuICByZXR1cm4gKGMgPT09IDB4MEEvKiBMRiAqLykgfHwgKGMgPT09IDB4MEQvKiBDUiAqLyk7XG59XG5cbmZ1bmN0aW9uIGlzX1dISVRFX1NQQUNFKGMpIHtcbiAgcmV0dXJuIChjID09PSAweDA5LyogVGFiICovKSB8fCAoYyA9PT0gMHgyMC8qIFNwYWNlICovKTtcbn1cblxuZnVuY3Rpb24gaXNfV1NfT1JfRU9MKGMpIHtcbiAgcmV0dXJuIChjID09PSAweDA5LyogVGFiICovKSB8fFxuICAgICAgICAgKGMgPT09IDB4MjAvKiBTcGFjZSAqLykgfHxcbiAgICAgICAgIChjID09PSAweDBBLyogTEYgKi8pIHx8XG4gICAgICAgICAoYyA9PT0gMHgwRC8qIENSICovKTtcbn1cblxuZnVuY3Rpb24gaXNfRkxPV19JTkRJQ0FUT1IoYykge1xuICByZXR1cm4gYyA9PT0gMHgyQy8qICwgKi8gfHxcbiAgICAgICAgIGMgPT09IDB4NUIvKiBbICovIHx8XG4gICAgICAgICBjID09PSAweDVELyogXSAqLyB8fFxuICAgICAgICAgYyA9PT0gMHg3Qi8qIHsgKi8gfHxcbiAgICAgICAgIGMgPT09IDB4N0QvKiB9ICovO1xufVxuXG5mdW5jdGlvbiBmcm9tSGV4Q29kZShjKSB7XG4gIHZhciBsYztcblxuICBpZiAoKDB4MzAvKiAwICovIDw9IGMpICYmIChjIDw9IDB4MzkvKiA5ICovKSkge1xuICAgIHJldHVybiBjIC0gMHgzMDtcbiAgfVxuXG4gIC8qZXNsaW50LWRpc2FibGUgbm8tYml0d2lzZSovXG4gIGxjID0gYyB8IDB4MjA7XG5cbiAgaWYgKCgweDYxLyogYSAqLyA8PSBsYykgJiYgKGxjIDw9IDB4NjYvKiBmICovKSkge1xuICAgIHJldHVybiBsYyAtIDB4NjEgKyAxMDtcbiAgfVxuXG4gIHJldHVybiAtMTtcbn1cblxuZnVuY3Rpb24gZXNjYXBlZEhleExlbihjKSB7XG4gIGlmIChjID09PSAweDc4LyogeCAqLykgeyByZXR1cm4gMjsgfVxuICBpZiAoYyA9PT0gMHg3NS8qIHUgKi8pIHsgcmV0dXJuIDQ7IH1cbiAgaWYgKGMgPT09IDB4NTUvKiBVICovKSB7IHJldHVybiA4OyB9XG4gIHJldHVybiAwO1xufVxuXG5mdW5jdGlvbiBmcm9tRGVjaW1hbENvZGUoYykge1xuICBpZiAoKDB4MzAvKiAwICovIDw9IGMpICYmIChjIDw9IDB4MzkvKiA5ICovKSkge1xuICAgIHJldHVybiBjIC0gMHgzMDtcbiAgfVxuXG4gIHJldHVybiAtMTtcbn1cblxuZnVuY3Rpb24gc2ltcGxlRXNjYXBlU2VxdWVuY2UoYykge1xuICByZXR1cm4gKGMgPT09IDB4MzAvKiAwICovKSA/ICdcXHgwMCcgOlxuICAgICAgICAoYyA9PT0gMHg2MS8qIGEgKi8pID8gJ1xceDA3JyA6XG4gICAgICAgIChjID09PSAweDYyLyogYiAqLykgPyAnXFx4MDgnIDpcbiAgICAgICAgKGMgPT09IDB4NzQvKiB0ICovKSA/ICdcXHgwOScgOlxuICAgICAgICAoYyA9PT0gMHgwOS8qIFRhYiAqLykgPyAnXFx4MDknIDpcbiAgICAgICAgKGMgPT09IDB4NkUvKiBuICovKSA/ICdcXHgwQScgOlxuICAgICAgICAoYyA9PT0gMHg3Ni8qIHYgKi8pID8gJ1xceDBCJyA6XG4gICAgICAgIChjID09PSAweDY2LyogZiAqLykgPyAnXFx4MEMnIDpcbiAgICAgICAgKGMgPT09IDB4NzIvKiByICovKSA/ICdcXHgwRCcgOlxuICAgICAgICAoYyA9PT0gMHg2NS8qIGUgKi8pID8gJ1xceDFCJyA6XG4gICAgICAgIChjID09PSAweDIwLyogU3BhY2UgKi8pID8gJyAnIDpcbiAgICAgICAgKGMgPT09IDB4MjIvKiBcIiAqLykgPyAnXFx4MjInIDpcbiAgICAgICAgKGMgPT09IDB4MkYvKiAvICovKSA/ICcvJyA6XG4gICAgICAgIChjID09PSAweDVDLyogXFwgKi8pID8gJ1xceDVDJyA6XG4gICAgICAgIChjID09PSAweDRFLyogTiAqLykgPyAnXFx4ODUnIDpcbiAgICAgICAgKGMgPT09IDB4NUYvKiBfICovKSA/ICdcXHhBMCcgOlxuICAgICAgICAoYyA9PT0gMHg0Qy8qIEwgKi8pID8gJ1xcdTIwMjgnIDpcbiAgICAgICAgKGMgPT09IDB4NTAvKiBQICovKSA/ICdcXHUyMDI5JyA6ICcnO1xufVxuXG5mdW5jdGlvbiBjaGFyRnJvbUNvZGVwb2ludChjKSB7XG4gIGlmIChjIDw9IDB4RkZGRikge1xuICAgIHJldHVybiBTdHJpbmcuZnJvbUNoYXJDb2RlKGMpO1xuICB9XG4gIC8vIEVuY29kZSBVVEYtMTYgc3Vycm9nYXRlIHBhaXJcbiAgLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVVRGLTE2I0NvZGVfcG9pbnRzX1UuMkIwMTAwMDBfdG9fVS4yQjEwRkZGRlxuICByZXR1cm4gU3RyaW5nLmZyb21DaGFyQ29kZSgoKGMgLSAweDAxMDAwMCkgPj4gMTApICsgMHhEODAwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoKGMgLSAweDAxMDAwMCkgJiAweDAzRkYpICsgMHhEQzAwKTtcbn1cblxudmFyIHNpbXBsZUVzY2FwZUNoZWNrID0gbmV3IEFycmF5KDI1Nik7IC8vIGludGVnZXIsIGZvciBmYXN0IGFjY2Vzc1xudmFyIHNpbXBsZUVzY2FwZU1hcCA9IG5ldyBBcnJheSgyNTYpO1xuZm9yICh2YXIgaSA9IDA7IGkgPCAyNTY7IGkrKykge1xuICBzaW1wbGVFc2NhcGVDaGVja1tpXSA9IHNpbXBsZUVzY2FwZVNlcXVlbmNlKGkpID8gMSA6IDA7XG4gIHNpbXBsZUVzY2FwZU1hcFtpXSA9IHNpbXBsZUVzY2FwZVNlcXVlbmNlKGkpO1xufVxuXG5cbmZ1bmN0aW9uIFN0YXRlKGlucHV0LCBvcHRpb25zKSB7XG4gIHRoaXMuaW5wdXQgPSBpbnB1dDtcblxuICB0aGlzLmZpbGVuYW1lICA9IG9wdGlvbnNbJ2ZpbGVuYW1lJ10gIHx8IG51bGw7XG4gIHRoaXMuc2NoZW1hICAgID0gb3B0aW9uc1snc2NoZW1hJ10gICAgfHwgREVGQVVMVF9GVUxMX1NDSEVNQTtcbiAgdGhpcy5vbldhcm5pbmcgPSBvcHRpb25zWydvbldhcm5pbmcnXSB8fCBudWxsO1xuICB0aGlzLmxlZ2FjeSAgICA9IG9wdGlvbnNbJ2xlZ2FjeSddICAgIHx8IGZhbHNlO1xuICB0aGlzLmpzb24gICAgICA9IG9wdGlvbnNbJ2pzb24nXSAgICAgIHx8IGZhbHNlO1xuICB0aGlzLmxpc3RlbmVyICA9IG9wdGlvbnNbJ2xpc3RlbmVyJ10gIHx8IG51bGw7XG5cbiAgdGhpcy5pbXBsaWNpdFR5cGVzID0gdGhpcy5zY2hlbWEuY29tcGlsZWRJbXBsaWNpdDtcbiAgdGhpcy50eXBlTWFwICAgICAgID0gdGhpcy5zY2hlbWEuY29tcGlsZWRUeXBlTWFwO1xuXG4gIHRoaXMubGVuZ3RoICAgICA9IGlucHV0Lmxlbmd0aDtcbiAgdGhpcy5wb3NpdGlvbiAgID0gMDtcbiAgdGhpcy5saW5lICAgICAgID0gMDtcbiAgdGhpcy5saW5lU3RhcnQgID0gMDtcbiAgdGhpcy5saW5lSW5kZW50ID0gMDtcblxuICB0aGlzLmRvY3VtZW50cyA9IFtdO1xuXG4gIC8qXG4gIHRoaXMudmVyc2lvbjtcbiAgdGhpcy5jaGVja0xpbmVCcmVha3M7XG4gIHRoaXMudGFnTWFwO1xuICB0aGlzLmFuY2hvck1hcDtcbiAgdGhpcy50YWc7XG4gIHRoaXMuYW5jaG9yO1xuICB0aGlzLmtpbmQ7XG4gIHRoaXMucmVzdWx0OyovXG5cbn1cblxuXG5mdW5jdGlvbiBnZW5lcmF0ZUVycm9yKHN0YXRlLCBtZXNzYWdlKSB7XG4gIHJldHVybiBuZXcgWUFNTEV4Y2VwdGlvbihcbiAgICBtZXNzYWdlLFxuICAgIG5ldyBNYXJrKHN0YXRlLmZpbGVuYW1lLCBzdGF0ZS5pbnB1dCwgc3RhdGUucG9zaXRpb24sIHN0YXRlLmxpbmUsIChzdGF0ZS5wb3NpdGlvbiAtIHN0YXRlLmxpbmVTdGFydCkpKTtcbn1cblxuZnVuY3Rpb24gdGhyb3dFcnJvcihzdGF0ZSwgbWVzc2FnZSkge1xuICB0aHJvdyBnZW5lcmF0ZUVycm9yKHN0YXRlLCBtZXNzYWdlKTtcbn1cblxuZnVuY3Rpb24gdGhyb3dXYXJuaW5nKHN0YXRlLCBtZXNzYWdlKSB7XG4gIGlmIChzdGF0ZS5vbldhcm5pbmcpIHtcbiAgICBzdGF0ZS5vbldhcm5pbmcuY2FsbChudWxsLCBnZW5lcmF0ZUVycm9yKHN0YXRlLCBtZXNzYWdlKSk7XG4gIH1cbn1cblxuXG52YXIgZGlyZWN0aXZlSGFuZGxlcnMgPSB7XG5cbiAgWUFNTDogZnVuY3Rpb24gaGFuZGxlWWFtbERpcmVjdGl2ZShzdGF0ZSwgbmFtZSwgYXJncykge1xuXG4gICAgdmFyIG1hdGNoLCBtYWpvciwgbWlub3I7XG5cbiAgICBpZiAoc3RhdGUudmVyc2lvbiAhPT0gbnVsbCkge1xuICAgICAgdGhyb3dFcnJvcihzdGF0ZSwgJ2R1cGxpY2F0aW9uIG9mICVZQU1MIGRpcmVjdGl2ZScpO1xuICAgIH1cblxuICAgIGlmIChhcmdzLmxlbmd0aCAhPT0gMSkge1xuICAgICAgdGhyb3dFcnJvcihzdGF0ZSwgJ1lBTUwgZGlyZWN0aXZlIGFjY2VwdHMgZXhhY3RseSBvbmUgYXJndW1lbnQnKTtcbiAgICB9XG5cbiAgICBtYXRjaCA9IC9eKFswLTldKylcXC4oWzAtOV0rKSQvLmV4ZWMoYXJnc1swXSk7XG5cbiAgICBpZiAobWF0Y2ggPT09IG51bGwpIHtcbiAgICAgIHRocm93RXJyb3Ioc3RhdGUsICdpbGwtZm9ybWVkIGFyZ3VtZW50IG9mIHRoZSBZQU1MIGRpcmVjdGl2ZScpO1xuICAgIH1cblxuICAgIG1ham9yID0gcGFyc2VJbnQobWF0Y2hbMV0sIDEwKTtcbiAgICBtaW5vciA9IHBhcnNlSW50KG1hdGNoWzJdLCAxMCk7XG5cbiAgICBpZiAobWFqb3IgIT09IDEpIHtcbiAgICAgIHRocm93RXJyb3Ioc3RhdGUsICd1bmFjY2VwdGFibGUgWUFNTCB2ZXJzaW9uIG9mIHRoZSBkb2N1bWVudCcpO1xuICAgIH1cblxuICAgIHN0YXRlLnZlcnNpb24gPSBhcmdzWzBdO1xuICAgIHN0YXRlLmNoZWNrTGluZUJyZWFrcyA9IChtaW5vciA8IDIpO1xuXG4gICAgaWYgKG1pbm9yICE9PSAxICYmIG1pbm9yICE9PSAyKSB7XG4gICAgICB0aHJvd1dhcm5pbmcoc3RhdGUsICd1bnN1cHBvcnRlZCBZQU1MIHZlcnNpb24gb2YgdGhlIGRvY3VtZW50Jyk7XG4gICAgfVxuICB9LFxuXG4gIFRBRzogZnVuY3Rpb24gaGFuZGxlVGFnRGlyZWN0aXZlKHN0YXRlLCBuYW1lLCBhcmdzKSB7XG5cbiAgICB2YXIgaGFuZGxlLCBwcmVmaXg7XG5cbiAgICBpZiAoYXJncy5sZW5ndGggIT09IDIpIHtcbiAgICAgIHRocm93RXJyb3Ioc3RhdGUsICdUQUcgZGlyZWN0aXZlIGFjY2VwdHMgZXhhY3RseSB0d28gYXJndW1lbnRzJyk7XG4gICAgfVxuXG4gICAgaGFuZGxlID0gYXJnc1swXTtcbiAgICBwcmVmaXggPSBhcmdzWzFdO1xuXG4gICAgaWYgKCFQQVRURVJOX1RBR19IQU5ETEUudGVzdChoYW5kbGUpKSB7XG4gICAgICB0aHJvd0Vycm9yKHN0YXRlLCAnaWxsLWZvcm1lZCB0YWcgaGFuZGxlIChmaXJzdCBhcmd1bWVudCkgb2YgdGhlIFRBRyBkaXJlY3RpdmUnKTtcbiAgICB9XG5cbiAgICBpZiAoX2hhc093blByb3BlcnR5LmNhbGwoc3RhdGUudGFnTWFwLCBoYW5kbGUpKSB7XG4gICAgICB0aHJvd0Vycm9yKHN0YXRlLCAndGhlcmUgaXMgYSBwcmV2aW91c2x5IGRlY2xhcmVkIHN1ZmZpeCBmb3IgXCInICsgaGFuZGxlICsgJ1wiIHRhZyBoYW5kbGUnKTtcbiAgICB9XG5cbiAgICBpZiAoIVBBVFRFUk5fVEFHX1VSSS50ZXN0KHByZWZpeCkpIHtcbiAgICAgIHRocm93RXJyb3Ioc3RhdGUsICdpbGwtZm9ybWVkIHRhZyBwcmVmaXggKHNlY29uZCBhcmd1bWVudCkgb2YgdGhlIFRBRyBkaXJlY3RpdmUnKTtcbiAgICB9XG5cbiAgICBzdGF0ZS50YWdNYXBbaGFuZGxlXSA9IHByZWZpeDtcbiAgfVxufTtcblxuXG5mdW5jdGlvbiBjYXB0dXJlU2VnbWVudChzdGF0ZSwgc3RhcnQsIGVuZCwgY2hlY2tKc29uKSB7XG4gIHZhciBfcG9zaXRpb24sIF9sZW5ndGgsIF9jaGFyYWN0ZXIsIF9yZXN1bHQ7XG5cbiAgaWYgKHN0YXJ0IDwgZW5kKSB7XG4gICAgX3Jlc3VsdCA9IHN0YXRlLmlucHV0LnNsaWNlKHN0YXJ0LCBlbmQpO1xuXG4gICAgaWYgKGNoZWNrSnNvbikge1xuICAgICAgZm9yIChfcG9zaXRpb24gPSAwLCBfbGVuZ3RoID0gX3Jlc3VsdC5sZW5ndGg7XG4gICAgICAgICAgIF9wb3NpdGlvbiA8IF9sZW5ndGg7XG4gICAgICAgICAgIF9wb3NpdGlvbiArPSAxKSB7XG4gICAgICAgIF9jaGFyYWN0ZXIgPSBfcmVzdWx0LmNoYXJDb2RlQXQoX3Bvc2l0aW9uKTtcbiAgICAgICAgaWYgKCEoX2NoYXJhY3RlciA9PT0gMHgwOSB8fFxuICAgICAgICAgICAgICAoMHgyMCA8PSBfY2hhcmFjdGVyICYmIF9jaGFyYWN0ZXIgPD0gMHgxMEZGRkYpKSkge1xuICAgICAgICAgIHRocm93RXJyb3Ioc3RhdGUsICdleHBlY3RlZCB2YWxpZCBKU09OIGNoYXJhY3RlcicpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChQQVRURVJOX05PTl9QUklOVEFCTEUudGVzdChfcmVzdWx0KSkge1xuICAgICAgdGhyb3dFcnJvcihzdGF0ZSwgJ3RoZSBzdHJlYW0gY29udGFpbnMgbm9uLXByaW50YWJsZSBjaGFyYWN0ZXJzJyk7XG4gICAgfVxuXG4gICAgc3RhdGUucmVzdWx0ICs9IF9yZXN1bHQ7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWVyZ2VNYXBwaW5ncyhzdGF0ZSwgZGVzdGluYXRpb24sIHNvdXJjZSwgb3ZlcnJpZGFibGVLZXlzKSB7XG4gIHZhciBzb3VyY2VLZXlzLCBrZXksIGluZGV4LCBxdWFudGl0eTtcblxuICBpZiAoIWNvbW1vbi5pc09iamVjdChzb3VyY2UpKSB7XG4gICAgdGhyb3dFcnJvcihzdGF0ZSwgJ2Nhbm5vdCBtZXJnZSBtYXBwaW5nczsgdGhlIHByb3ZpZGVkIHNvdXJjZSBvYmplY3QgaXMgdW5hY2NlcHRhYmxlJyk7XG4gIH1cblxuICBzb3VyY2VLZXlzID0gT2JqZWN0LmtleXMoc291cmNlKTtcblxuICBmb3IgKGluZGV4ID0gMCwgcXVhbnRpdHkgPSBzb3VyY2VLZXlzLmxlbmd0aDsgaW5kZXggPCBxdWFudGl0eTsgaW5kZXggKz0gMSkge1xuICAgIGtleSA9IHNvdXJjZUtleXNbaW5kZXhdO1xuXG4gICAgaWYgKCFfaGFzT3duUHJvcGVydHkuY2FsbChkZXN0aW5hdGlvbiwga2V5KSkge1xuICAgICAgZGVzdGluYXRpb25ba2V5XSA9IHNvdXJjZVtrZXldO1xuICAgICAgb3ZlcnJpZGFibGVLZXlzW2tleV0gPSB0cnVlO1xuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBzdG9yZU1hcHBpbmdQYWlyKHN0YXRlLCBfcmVzdWx0LCBvdmVycmlkYWJsZUtleXMsIGtleVRhZywga2V5Tm9kZSwgdmFsdWVOb2RlKSB7XG4gIHZhciBpbmRleCwgcXVhbnRpdHk7XG5cbiAga2V5Tm9kZSA9IFN0cmluZyhrZXlOb2RlKTtcblxuICBpZiAoX3Jlc3VsdCA9PT0gbnVsbCkge1xuICAgIF9yZXN1bHQgPSB7fTtcbiAgfVxuXG4gIGlmIChrZXlUYWcgPT09ICd0YWc6eWFtbC5vcmcsMjAwMjptZXJnZScpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZU5vZGUpKSB7XG4gICAgICBmb3IgKGluZGV4ID0gMCwgcXVhbnRpdHkgPSB2YWx1ZU5vZGUubGVuZ3RoOyBpbmRleCA8IHF1YW50aXR5OyBpbmRleCArPSAxKSB7XG4gICAgICAgIG1lcmdlTWFwcGluZ3Moc3RhdGUsIF9yZXN1bHQsIHZhbHVlTm9kZVtpbmRleF0sIG92ZXJyaWRhYmxlS2V5cyk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIG1lcmdlTWFwcGluZ3Moc3RhdGUsIF9yZXN1bHQsIHZhbHVlTm9kZSwgb3ZlcnJpZGFibGVLZXlzKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaWYgKCFzdGF0ZS5qc29uICYmXG4gICAgICAgICFfaGFzT3duUHJvcGVydHkuY2FsbChvdmVycmlkYWJsZUtleXMsIGtleU5vZGUpICYmXG4gICAgICAgIF9oYXNPd25Qcm9wZXJ0eS5jYWxsKF9yZXN1bHQsIGtleU5vZGUpKSB7XG4gICAgICB0aHJvd0Vycm9yKHN0YXRlLCAnZHVwbGljYXRlZCBtYXBwaW5nIGtleScpO1xuICAgIH1cbiAgICBfcmVzdWx0W2tleU5vZGVdID0gdmFsdWVOb2RlO1xuICAgIGRlbGV0ZSBvdmVycmlkYWJsZUtleXNba2V5Tm9kZV07XG4gIH1cblxuICByZXR1cm4gX3Jlc3VsdDtcbn1cblxuZnVuY3Rpb24gcmVhZExpbmVCcmVhayhzdGF0ZSkge1xuICB2YXIgY2g7XG5cbiAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcblxuICBpZiAoY2ggPT09IDB4MEEvKiBMRiAqLykge1xuICAgIHN0YXRlLnBvc2l0aW9uKys7XG4gIH0gZWxzZSBpZiAoY2ggPT09IDB4MEQvKiBDUiAqLykge1xuICAgIHN0YXRlLnBvc2l0aW9uKys7XG4gICAgaWYgKHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24pID09PSAweDBBLyogTEYgKi8pIHtcbiAgICAgIHN0YXRlLnBvc2l0aW9uKys7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRocm93RXJyb3Ioc3RhdGUsICdhIGxpbmUgYnJlYWsgaXMgZXhwZWN0ZWQnKTtcbiAgfVxuXG4gIHN0YXRlLmxpbmUgKz0gMTtcbiAgc3RhdGUubGluZVN0YXJ0ID0gc3RhdGUucG9zaXRpb247XG59XG5cbmZ1bmN0aW9uIHNraXBTZXBhcmF0aW9uU3BhY2Uoc3RhdGUsIGFsbG93Q29tbWVudHMsIGNoZWNrSW5kZW50KSB7XG4gIHZhciBsaW5lQnJlYWtzID0gMCxcbiAgICAgIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbik7XG5cbiAgd2hpbGUgKGNoICE9PSAwKSB7XG4gICAgd2hpbGUgKGlzX1dISVRFX1NQQUNFKGNoKSkge1xuICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuICAgIH1cblxuICAgIGlmIChhbGxvd0NvbW1lbnRzICYmIGNoID09PSAweDIzLyogIyAqLykge1xuICAgICAgZG8ge1xuICAgICAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG4gICAgICB9IHdoaWxlIChjaCAhPT0gMHgwQS8qIExGICovICYmIGNoICE9PSAweDBELyogQ1IgKi8gJiYgY2ggIT09IDApO1xuICAgIH1cblxuICAgIGlmIChpc19FT0woY2gpKSB7XG4gICAgICByZWFkTGluZUJyZWFrKHN0YXRlKTtcblxuICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcbiAgICAgIGxpbmVCcmVha3MrKztcbiAgICAgIHN0YXRlLmxpbmVJbmRlbnQgPSAwO1xuXG4gICAgICB3aGlsZSAoY2ggPT09IDB4MjAvKiBTcGFjZSAqLykge1xuICAgICAgICBzdGF0ZS5saW5lSW5kZW50Kys7XG4gICAgICAgIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdCgrK3N0YXRlLnBvc2l0aW9uKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgaWYgKGNoZWNrSW5kZW50ICE9PSAtMSAmJiBsaW5lQnJlYWtzICE9PSAwICYmIHN0YXRlLmxpbmVJbmRlbnQgPCBjaGVja0luZGVudCkge1xuICAgIHRocm93V2FybmluZyhzdGF0ZSwgJ2RlZmljaWVudCBpbmRlbnRhdGlvbicpO1xuICB9XG5cbiAgcmV0dXJuIGxpbmVCcmVha3M7XG59XG5cbmZ1bmN0aW9uIHRlc3REb2N1bWVudFNlcGFyYXRvcihzdGF0ZSkge1xuICB2YXIgX3Bvc2l0aW9uID0gc3RhdGUucG9zaXRpb24sXG4gICAgICBjaDtcblxuICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoX3Bvc2l0aW9uKTtcblxuICAvLyBDb25kaXRpb24gc3RhdGUucG9zaXRpb24gPT09IHN0YXRlLmxpbmVTdGFydCBpcyB0ZXN0ZWRcbiAgLy8gaW4gcGFyZW50IG9uIGVhY2ggY2FsbCwgZm9yIGVmZmljaWVuY3kuIE5vIG5lZWRzIHRvIHRlc3QgaGVyZSBhZ2Fpbi5cbiAgaWYgKChjaCA9PT0gMHgyRC8qIC0gKi8gfHwgY2ggPT09IDB4MkUvKiAuICovKSAmJlxuICAgICAgY2ggPT09IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoX3Bvc2l0aW9uICsgMSkgJiZcbiAgICAgIGNoID09PSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KF9wb3NpdGlvbiArIDIpKSB7XG5cbiAgICBfcG9zaXRpb24gKz0gMztcblxuICAgIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChfcG9zaXRpb24pO1xuXG4gICAgaWYgKGNoID09PSAwIHx8IGlzX1dTX09SX0VPTChjaCkpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gd3JpdGVGb2xkZWRMaW5lcyhzdGF0ZSwgY291bnQpIHtcbiAgaWYgKGNvdW50ID09PSAxKSB7XG4gICAgc3RhdGUucmVzdWx0ICs9ICcgJztcbiAgfSBlbHNlIGlmIChjb3VudCA+IDEpIHtcbiAgICBzdGF0ZS5yZXN1bHQgKz0gY29tbW9uLnJlcGVhdCgnXFxuJywgY291bnQgLSAxKTtcbiAgfVxufVxuXG5cbmZ1bmN0aW9uIHJlYWRQbGFpblNjYWxhcihzdGF0ZSwgbm9kZUluZGVudCwgd2l0aGluRmxvd0NvbGxlY3Rpb24pIHtcbiAgdmFyIHByZWNlZGluZyxcbiAgICAgIGZvbGxvd2luZyxcbiAgICAgIGNhcHR1cmVTdGFydCxcbiAgICAgIGNhcHR1cmVFbmQsXG4gICAgICBoYXNQZW5kaW5nQ29udGVudCxcbiAgICAgIF9saW5lLFxuICAgICAgX2xpbmVTdGFydCxcbiAgICAgIF9saW5lSW5kZW50LFxuICAgICAgX2tpbmQgPSBzdGF0ZS5raW5kLFxuICAgICAgX3Jlc3VsdCA9IHN0YXRlLnJlc3VsdCxcbiAgICAgIGNoO1xuXG4gIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbik7XG5cbiAgaWYgKGlzX1dTX09SX0VPTChjaCkgICAgICB8fFxuICAgICAgaXNfRkxPV19JTkRJQ0FUT1IoY2gpIHx8XG4gICAgICBjaCA9PT0gMHgyMy8qICMgKi8gICAgfHxcbiAgICAgIGNoID09PSAweDI2LyogJiAqLyAgICB8fFxuICAgICAgY2ggPT09IDB4MkEvKiAqICovICAgIHx8XG4gICAgICBjaCA9PT0gMHgyMS8qICEgKi8gICAgfHxcbiAgICAgIGNoID09PSAweDdDLyogfCAqLyAgICB8fFxuICAgICAgY2ggPT09IDB4M0UvKiA+ICovICAgIHx8XG4gICAgICBjaCA9PT0gMHgyNy8qICcgKi8gICAgfHxcbiAgICAgIGNoID09PSAweDIyLyogXCIgKi8gICAgfHxcbiAgICAgIGNoID09PSAweDI1LyogJSAqLyAgICB8fFxuICAgICAgY2ggPT09IDB4NDAvKiBAICovICAgIHx8XG4gICAgICBjaCA9PT0gMHg2MC8qIGAgKi8pIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoY2ggPT09IDB4M0YvKiA/ICovIHx8IGNoID09PSAweDJELyogLSAqLykge1xuICAgIGZvbGxvd2luZyA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24gKyAxKTtcblxuICAgIGlmIChpc19XU19PUl9FT0woZm9sbG93aW5nKSB8fFxuICAgICAgICB3aXRoaW5GbG93Q29sbGVjdGlvbiAmJiBpc19GTE9XX0lORElDQVRPUihmb2xsb3dpbmcpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgc3RhdGUua2luZCA9ICdzY2FsYXInO1xuICBzdGF0ZS5yZXN1bHQgPSAnJztcbiAgY2FwdHVyZVN0YXJ0ID0gY2FwdHVyZUVuZCA9IHN0YXRlLnBvc2l0aW9uO1xuICBoYXNQZW5kaW5nQ29udGVudCA9IGZhbHNlO1xuXG4gIHdoaWxlIChjaCAhPT0gMCkge1xuICAgIGlmIChjaCA9PT0gMHgzQS8qIDogKi8pIHtcbiAgICAgIGZvbGxvd2luZyA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24gKyAxKTtcblxuICAgICAgaWYgKGlzX1dTX09SX0VPTChmb2xsb3dpbmcpIHx8XG4gICAgICAgICAgd2l0aGluRmxvd0NvbGxlY3Rpb24gJiYgaXNfRkxPV19JTkRJQ0FUT1IoZm9sbG93aW5nKSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4MjMvKiAjICovKSB7XG4gICAgICBwcmVjZWRpbmcgPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uIC0gMSk7XG5cbiAgICAgIGlmIChpc19XU19PUl9FT0wocHJlY2VkaW5nKSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgIH0gZWxzZSBpZiAoKHN0YXRlLnBvc2l0aW9uID09PSBzdGF0ZS5saW5lU3RhcnQgJiYgdGVzdERvY3VtZW50U2VwYXJhdG9yKHN0YXRlKSkgfHxcbiAgICAgICAgICAgICAgIHdpdGhpbkZsb3dDb2xsZWN0aW9uICYmIGlzX0ZMT1dfSU5ESUNBVE9SKGNoKSkge1xuICAgICAgYnJlYWs7XG5cbiAgICB9IGVsc2UgaWYgKGlzX0VPTChjaCkpIHtcbiAgICAgIF9saW5lID0gc3RhdGUubGluZTtcbiAgICAgIF9saW5lU3RhcnQgPSBzdGF0ZS5saW5lU3RhcnQ7XG4gICAgICBfbGluZUluZGVudCA9IHN0YXRlLmxpbmVJbmRlbnQ7XG4gICAgICBza2lwU2VwYXJhdGlvblNwYWNlKHN0YXRlLCBmYWxzZSwgLTEpO1xuXG4gICAgICBpZiAoc3RhdGUubGluZUluZGVudCA+PSBub2RlSW5kZW50KSB7XG4gICAgICAgIGhhc1BlbmRpbmdDb250ZW50ID0gdHJ1ZTtcbiAgICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzdGF0ZS5wb3NpdGlvbiA9IGNhcHR1cmVFbmQ7XG4gICAgICAgIHN0YXRlLmxpbmUgPSBfbGluZTtcbiAgICAgICAgc3RhdGUubGluZVN0YXJ0ID0gX2xpbmVTdGFydDtcbiAgICAgICAgc3RhdGUubGluZUluZGVudCA9IF9saW5lSW5kZW50O1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaGFzUGVuZGluZ0NvbnRlbnQpIHtcbiAgICAgIGNhcHR1cmVTZWdtZW50KHN0YXRlLCBjYXB0dXJlU3RhcnQsIGNhcHR1cmVFbmQsIGZhbHNlKTtcbiAgICAgIHdyaXRlRm9sZGVkTGluZXMoc3RhdGUsIHN0YXRlLmxpbmUgLSBfbGluZSk7XG4gICAgICBjYXB0dXJlU3RhcnQgPSBjYXB0dXJlRW5kID0gc3RhdGUucG9zaXRpb247XG4gICAgICBoYXNQZW5kaW5nQ29udGVudCA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghaXNfV0hJVEVfU1BBQ0UoY2gpKSB7XG4gICAgICBjYXB0dXJlRW5kID0gc3RhdGUucG9zaXRpb24gKyAxO1xuICAgIH1cblxuICAgIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdCgrK3N0YXRlLnBvc2l0aW9uKTtcbiAgfVxuXG4gIGNhcHR1cmVTZWdtZW50KHN0YXRlLCBjYXB0dXJlU3RhcnQsIGNhcHR1cmVFbmQsIGZhbHNlKTtcblxuICBpZiAoc3RhdGUucmVzdWx0KSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBzdGF0ZS5raW5kID0gX2tpbmQ7XG4gIHN0YXRlLnJlc3VsdCA9IF9yZXN1bHQ7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gcmVhZFNpbmdsZVF1b3RlZFNjYWxhcihzdGF0ZSwgbm9kZUluZGVudCkge1xuICB2YXIgY2gsXG4gICAgICBjYXB0dXJlU3RhcnQsIGNhcHR1cmVFbmQ7XG5cbiAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcblxuICBpZiAoY2ggIT09IDB4MjcvKiAnICovKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgc3RhdGUua2luZCA9ICdzY2FsYXInO1xuICBzdGF0ZS5yZXN1bHQgPSAnJztcbiAgc3RhdGUucG9zaXRpb24rKztcbiAgY2FwdHVyZVN0YXJ0ID0gY2FwdHVyZUVuZCA9IHN0YXRlLnBvc2l0aW9uO1xuXG4gIHdoaWxlICgoY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKSkgIT09IDApIHtcbiAgICBpZiAoY2ggPT09IDB4MjcvKiAnICovKSB7XG4gICAgICBjYXB0dXJlU2VnbWVudChzdGF0ZSwgY2FwdHVyZVN0YXJ0LCBzdGF0ZS5wb3NpdGlvbiwgdHJ1ZSk7XG4gICAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG5cbiAgICAgIGlmIChjaCA9PT0gMHgyNy8qICcgKi8pIHtcbiAgICAgICAgY2FwdHVyZVN0YXJ0ID0gY2FwdHVyZUVuZCA9IHN0YXRlLnBvc2l0aW9uO1xuICAgICAgICBzdGF0ZS5wb3NpdGlvbisrO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICB9IGVsc2UgaWYgKGlzX0VPTChjaCkpIHtcbiAgICAgIGNhcHR1cmVTZWdtZW50KHN0YXRlLCBjYXB0dXJlU3RhcnQsIGNhcHR1cmVFbmQsIHRydWUpO1xuICAgICAgd3JpdGVGb2xkZWRMaW5lcyhzdGF0ZSwgc2tpcFNlcGFyYXRpb25TcGFjZShzdGF0ZSwgZmFsc2UsIG5vZGVJbmRlbnQpKTtcbiAgICAgIGNhcHR1cmVTdGFydCA9IGNhcHR1cmVFbmQgPSBzdGF0ZS5wb3NpdGlvbjtcblxuICAgIH0gZWxzZSBpZiAoc3RhdGUucG9zaXRpb24gPT09IHN0YXRlLmxpbmVTdGFydCAmJiB0ZXN0RG9jdW1lbnRTZXBhcmF0b3Ioc3RhdGUpKSB7XG4gICAgICB0aHJvd0Vycm9yKHN0YXRlLCAndW5leHBlY3RlZCBlbmQgb2YgdGhlIGRvY3VtZW50IHdpdGhpbiBhIHNpbmdsZSBxdW90ZWQgc2NhbGFyJyk7XG5cbiAgICB9IGVsc2Uge1xuICAgICAgc3RhdGUucG9zaXRpb24rKztcbiAgICAgIGNhcHR1cmVFbmQgPSBzdGF0ZS5wb3NpdGlvbjtcbiAgICB9XG4gIH1cblxuICB0aHJvd0Vycm9yKHN0YXRlLCAndW5leHBlY3RlZCBlbmQgb2YgdGhlIHN0cmVhbSB3aXRoaW4gYSBzaW5nbGUgcXVvdGVkIHNjYWxhcicpO1xufVxuXG5mdW5jdGlvbiByZWFkRG91YmxlUXVvdGVkU2NhbGFyKHN0YXRlLCBub2RlSW5kZW50KSB7XG4gIHZhciBjYXB0dXJlU3RhcnQsXG4gICAgICBjYXB0dXJlRW5kLFxuICAgICAgaGV4TGVuZ3RoLFxuICAgICAgaGV4UmVzdWx0LFxuICAgICAgdG1wLFxuICAgICAgY2g7XG5cbiAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcblxuICBpZiAoY2ggIT09IDB4MjIvKiBcIiAqLykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHN0YXRlLmtpbmQgPSAnc2NhbGFyJztcbiAgc3RhdGUucmVzdWx0ID0gJyc7XG4gIHN0YXRlLnBvc2l0aW9uKys7XG4gIGNhcHR1cmVTdGFydCA9IGNhcHR1cmVFbmQgPSBzdGF0ZS5wb3NpdGlvbjtcblxuICB3aGlsZSAoKGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbikpICE9PSAwKSB7XG4gICAgaWYgKGNoID09PSAweDIyLyogXCIgKi8pIHtcbiAgICAgIGNhcHR1cmVTZWdtZW50KHN0YXRlLCBjYXB0dXJlU3RhcnQsIHN0YXRlLnBvc2l0aW9uLCB0cnVlKTtcbiAgICAgIHN0YXRlLnBvc2l0aW9uKys7XG4gICAgICByZXR1cm4gdHJ1ZTtcblxuICAgIH0gZWxzZSBpZiAoY2ggPT09IDB4NUMvKiBcXCAqLykge1xuICAgICAgY2FwdHVyZVNlZ21lbnQoc3RhdGUsIGNhcHR1cmVTdGFydCwgc3RhdGUucG9zaXRpb24sIHRydWUpO1xuICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuXG4gICAgICBpZiAoaXNfRU9MKGNoKSkge1xuICAgICAgICBza2lwU2VwYXJhdGlvblNwYWNlKHN0YXRlLCBmYWxzZSwgbm9kZUluZGVudCk7XG5cbiAgICAgICAgLy8gVE9ETzogcmV3b3JrIHRvIGlubGluZSBmbiB3aXRoIG5vIHR5cGUgY2FzdD9cbiAgICAgIH0gZWxzZSBpZiAoY2ggPCAyNTYgJiYgc2ltcGxlRXNjYXBlQ2hlY2tbY2hdKSB7XG4gICAgICAgIHN0YXRlLnJlc3VsdCArPSBzaW1wbGVFc2NhcGVNYXBbY2hdO1xuICAgICAgICBzdGF0ZS5wb3NpdGlvbisrO1xuXG4gICAgICB9IGVsc2UgaWYgKCh0bXAgPSBlc2NhcGVkSGV4TGVuKGNoKSkgPiAwKSB7XG4gICAgICAgIGhleExlbmd0aCA9IHRtcDtcbiAgICAgICAgaGV4UmVzdWx0ID0gMDtcblxuICAgICAgICBmb3IgKDsgaGV4TGVuZ3RoID4gMDsgaGV4TGVuZ3RoLS0pIHtcbiAgICAgICAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG5cbiAgICAgICAgICBpZiAoKHRtcCA9IGZyb21IZXhDb2RlKGNoKSkgPj0gMCkge1xuICAgICAgICAgICAgaGV4UmVzdWx0ID0gKGhleFJlc3VsdCA8PCA0KSArIHRtcDtcblxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvd0Vycm9yKHN0YXRlLCAnZXhwZWN0ZWQgaGV4YWRlY2ltYWwgY2hhcmFjdGVyJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc3RhdGUucmVzdWx0ICs9IGNoYXJGcm9tQ29kZXBvaW50KGhleFJlc3VsdCk7XG5cbiAgICAgICAgc3RhdGUucG9zaXRpb24rKztcblxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3dFcnJvcihzdGF0ZSwgJ3Vua25vd24gZXNjYXBlIHNlcXVlbmNlJyk7XG4gICAgICB9XG5cbiAgICAgIGNhcHR1cmVTdGFydCA9IGNhcHR1cmVFbmQgPSBzdGF0ZS5wb3NpdGlvbjtcblxuICAgIH0gZWxzZSBpZiAoaXNfRU9MKGNoKSkge1xuICAgICAgY2FwdHVyZVNlZ21lbnQoc3RhdGUsIGNhcHR1cmVTdGFydCwgY2FwdHVyZUVuZCwgdHJ1ZSk7XG4gICAgICB3cml0ZUZvbGRlZExpbmVzKHN0YXRlLCBza2lwU2VwYXJhdGlvblNwYWNlKHN0YXRlLCBmYWxzZSwgbm9kZUluZGVudCkpO1xuICAgICAgY2FwdHVyZVN0YXJ0ID0gY2FwdHVyZUVuZCA9IHN0YXRlLnBvc2l0aW9uO1xuXG4gICAgfSBlbHNlIGlmIChzdGF0ZS5wb3NpdGlvbiA9PT0gc3RhdGUubGluZVN0YXJ0ICYmIHRlc3REb2N1bWVudFNlcGFyYXRvcihzdGF0ZSkpIHtcbiAgICAgIHRocm93RXJyb3Ioc3RhdGUsICd1bmV4cGVjdGVkIGVuZCBvZiB0aGUgZG9jdW1lbnQgd2l0aGluIGEgZG91YmxlIHF1b3RlZCBzY2FsYXInKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICBzdGF0ZS5wb3NpdGlvbisrO1xuICAgICAgY2FwdHVyZUVuZCA9IHN0YXRlLnBvc2l0aW9uO1xuICAgIH1cbiAgfVxuXG4gIHRocm93RXJyb3Ioc3RhdGUsICd1bmV4cGVjdGVkIGVuZCBvZiB0aGUgc3RyZWFtIHdpdGhpbiBhIGRvdWJsZSBxdW90ZWQgc2NhbGFyJyk7XG59XG5cbmZ1bmN0aW9uIHJlYWRGbG93Q29sbGVjdGlvbihzdGF0ZSwgbm9kZUluZGVudCkge1xuICB2YXIgcmVhZE5leHQgPSB0cnVlLFxuICAgICAgX2xpbmUsXG4gICAgICBfdGFnICAgICA9IHN0YXRlLnRhZyxcbiAgICAgIF9yZXN1bHQsXG4gICAgICBfYW5jaG9yICA9IHN0YXRlLmFuY2hvcixcbiAgICAgIGZvbGxvd2luZyxcbiAgICAgIHRlcm1pbmF0b3IsXG4gICAgICBpc1BhaXIsXG4gICAgICBpc0V4cGxpY2l0UGFpcixcbiAgICAgIGlzTWFwcGluZyxcbiAgICAgIG92ZXJyaWRhYmxlS2V5cyA9IHt9LFxuICAgICAga2V5Tm9kZSxcbiAgICAgIGtleVRhZyxcbiAgICAgIHZhbHVlTm9kZSxcbiAgICAgIGNoO1xuXG4gIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbik7XG5cbiAgaWYgKGNoID09PSAweDVCLyogWyAqLykge1xuICAgIHRlcm1pbmF0b3IgPSAweDVEOy8qIF0gKi9cbiAgICBpc01hcHBpbmcgPSBmYWxzZTtcbiAgICBfcmVzdWx0ID0gW107XG4gIH0gZWxzZSBpZiAoY2ggPT09IDB4N0IvKiB7ICovKSB7XG4gICAgdGVybWluYXRvciA9IDB4N0Q7LyogfSAqL1xuICAgIGlzTWFwcGluZyA9IHRydWU7XG4gICAgX3Jlc3VsdCA9IHt9O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIGlmIChzdGF0ZS5hbmNob3IgIT09IG51bGwpIHtcbiAgICBzdGF0ZS5hbmNob3JNYXBbc3RhdGUuYW5jaG9yXSA9IF9yZXN1bHQ7XG4gIH1cblxuICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG5cbiAgd2hpbGUgKGNoICE9PSAwKSB7XG4gICAgc2tpcFNlcGFyYXRpb25TcGFjZShzdGF0ZSwgdHJ1ZSwgbm9kZUluZGVudCk7XG5cbiAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24pO1xuXG4gICAgaWYgKGNoID09PSB0ZXJtaW5hdG9yKSB7XG4gICAgICBzdGF0ZS5wb3NpdGlvbisrO1xuICAgICAgc3RhdGUudGFnID0gX3RhZztcbiAgICAgIHN0YXRlLmFuY2hvciA9IF9hbmNob3I7XG4gICAgICBzdGF0ZS5raW5kID0gaXNNYXBwaW5nID8gJ21hcHBpbmcnIDogJ3NlcXVlbmNlJztcbiAgICAgIHN0YXRlLnJlc3VsdCA9IF9yZXN1bHQ7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKCFyZWFkTmV4dCkge1xuICAgICAgdGhyb3dFcnJvcihzdGF0ZSwgJ21pc3NlZCBjb21tYSBiZXR3ZWVuIGZsb3cgY29sbGVjdGlvbiBlbnRyaWVzJyk7XG4gICAgfVxuXG4gICAga2V5VGFnID0ga2V5Tm9kZSA9IHZhbHVlTm9kZSA9IG51bGw7XG4gICAgaXNQYWlyID0gaXNFeHBsaWNpdFBhaXIgPSBmYWxzZTtcblxuICAgIGlmIChjaCA9PT0gMHgzRi8qID8gKi8pIHtcbiAgICAgIGZvbGxvd2luZyA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24gKyAxKTtcblxuICAgICAgaWYgKGlzX1dTX09SX0VPTChmb2xsb3dpbmcpKSB7XG4gICAgICAgIGlzUGFpciA9IGlzRXhwbGljaXRQYWlyID0gdHJ1ZTtcbiAgICAgICAgc3RhdGUucG9zaXRpb24rKztcbiAgICAgICAgc2tpcFNlcGFyYXRpb25TcGFjZShzdGF0ZSwgdHJ1ZSwgbm9kZUluZGVudCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgX2xpbmUgPSBzdGF0ZS5saW5lO1xuICAgIGNvbXBvc2VOb2RlKHN0YXRlLCBub2RlSW5kZW50LCBDT05URVhUX0ZMT1dfSU4sIGZhbHNlLCB0cnVlKTtcbiAgICBrZXlUYWcgPSBzdGF0ZS50YWc7XG4gICAga2V5Tm9kZSA9IHN0YXRlLnJlc3VsdDtcbiAgICBza2lwU2VwYXJhdGlvblNwYWNlKHN0YXRlLCB0cnVlLCBub2RlSW5kZW50KTtcblxuICAgIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbik7XG5cbiAgICBpZiAoKGlzRXhwbGljaXRQYWlyIHx8IHN0YXRlLmxpbmUgPT09IF9saW5lKSAmJiBjaCA9PT0gMHgzQS8qIDogKi8pIHtcbiAgICAgIGlzUGFpciA9IHRydWU7XG4gICAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG4gICAgICBza2lwU2VwYXJhdGlvblNwYWNlKHN0YXRlLCB0cnVlLCBub2RlSW5kZW50KTtcbiAgICAgIGNvbXBvc2VOb2RlKHN0YXRlLCBub2RlSW5kZW50LCBDT05URVhUX0ZMT1dfSU4sIGZhbHNlLCB0cnVlKTtcbiAgICAgIHZhbHVlTm9kZSA9IHN0YXRlLnJlc3VsdDtcbiAgICB9XG5cbiAgICBpZiAoaXNNYXBwaW5nKSB7XG4gICAgICBzdG9yZU1hcHBpbmdQYWlyKHN0YXRlLCBfcmVzdWx0LCBvdmVycmlkYWJsZUtleXMsIGtleVRhZywga2V5Tm9kZSwgdmFsdWVOb2RlKTtcbiAgICB9IGVsc2UgaWYgKGlzUGFpcikge1xuICAgICAgX3Jlc3VsdC5wdXNoKHN0b3JlTWFwcGluZ1BhaXIoc3RhdGUsIG51bGwsIG92ZXJyaWRhYmxlS2V5cywga2V5VGFnLCBrZXlOb2RlLCB2YWx1ZU5vZGUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgX3Jlc3VsdC5wdXNoKGtleU5vZGUpO1xuICAgIH1cblxuICAgIHNraXBTZXBhcmF0aW9uU3BhY2Uoc3RhdGUsIHRydWUsIG5vZGVJbmRlbnQpO1xuXG4gICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcblxuICAgIGlmIChjaCA9PT0gMHgyQy8qICwgKi8pIHtcbiAgICAgIHJlYWROZXh0ID0gdHJ1ZTtcbiAgICAgIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdCgrK3N0YXRlLnBvc2l0aW9uKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVhZE5leHQgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICB0aHJvd0Vycm9yKHN0YXRlLCAndW5leHBlY3RlZCBlbmQgb2YgdGhlIHN0cmVhbSB3aXRoaW4gYSBmbG93IGNvbGxlY3Rpb24nKTtcbn1cblxuZnVuY3Rpb24gcmVhZEJsb2NrU2NhbGFyKHN0YXRlLCBub2RlSW5kZW50KSB7XG4gIHZhciBjYXB0dXJlU3RhcnQsXG4gICAgICBmb2xkaW5nLFxuICAgICAgY2hvbXBpbmcgICAgICAgPSBDSE9NUElOR19DTElQLFxuICAgICAgZGlkUmVhZENvbnRlbnQgPSBmYWxzZSxcbiAgICAgIGRldGVjdGVkSW5kZW50ID0gZmFsc2UsXG4gICAgICB0ZXh0SW5kZW50ICAgICA9IG5vZGVJbmRlbnQsXG4gICAgICBlbXB0eUxpbmVzICAgICA9IDAsXG4gICAgICBhdE1vcmVJbmRlbnRlZCA9IGZhbHNlLFxuICAgICAgdG1wLFxuICAgICAgY2g7XG5cbiAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcblxuICBpZiAoY2ggPT09IDB4N0MvKiB8ICovKSB7XG4gICAgZm9sZGluZyA9IGZhbHNlO1xuICB9IGVsc2UgaWYgKGNoID09PSAweDNFLyogPiAqLykge1xuICAgIGZvbGRpbmcgPSB0cnVlO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHN0YXRlLmtpbmQgPSAnc2NhbGFyJztcbiAgc3RhdGUucmVzdWx0ID0gJyc7XG5cbiAgd2hpbGUgKGNoICE9PSAwKSB7XG4gICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuXG4gICAgaWYgKGNoID09PSAweDJCLyogKyAqLyB8fCBjaCA9PT0gMHgyRC8qIC0gKi8pIHtcbiAgICAgIGlmIChDSE9NUElOR19DTElQID09PSBjaG9tcGluZykge1xuICAgICAgICBjaG9tcGluZyA9IChjaCA9PT0gMHgyQi8qICsgKi8pID8gQ0hPTVBJTkdfS0VFUCA6IENIT01QSU5HX1NUUklQO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3dFcnJvcihzdGF0ZSwgJ3JlcGVhdCBvZiBhIGNob21waW5nIG1vZGUgaWRlbnRpZmllcicpO1xuICAgICAgfVxuXG4gICAgfSBlbHNlIGlmICgodG1wID0gZnJvbURlY2ltYWxDb2RlKGNoKSkgPj0gMCkge1xuICAgICAgaWYgKHRtcCA9PT0gMCkge1xuICAgICAgICB0aHJvd0Vycm9yKHN0YXRlLCAnYmFkIGV4cGxpY2l0IGluZGVudGF0aW9uIHdpZHRoIG9mIGEgYmxvY2sgc2NhbGFyOyBpdCBjYW5ub3QgYmUgbGVzcyB0aGFuIG9uZScpO1xuICAgICAgfSBlbHNlIGlmICghZGV0ZWN0ZWRJbmRlbnQpIHtcbiAgICAgICAgdGV4dEluZGVudCA9IG5vZGVJbmRlbnQgKyB0bXAgLSAxO1xuICAgICAgICBkZXRlY3RlZEluZGVudCA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvd0Vycm9yKHN0YXRlLCAncmVwZWF0IG9mIGFuIGluZGVudGF0aW9uIHdpZHRoIGlkZW50aWZpZXInKTtcbiAgICAgIH1cblxuICAgIH0gZWxzZSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cblxuICBpZiAoaXNfV0hJVEVfU1BBQ0UoY2gpKSB7XG4gICAgZG8geyBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7IH1cbiAgICB3aGlsZSAoaXNfV0hJVEVfU1BBQ0UoY2gpKTtcblxuICAgIGlmIChjaCA9PT0gMHgyMy8qICMgKi8pIHtcbiAgICAgIGRvIHsgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pOyB9XG4gICAgICB3aGlsZSAoIWlzX0VPTChjaCkgJiYgKGNoICE9PSAwKSk7XG4gICAgfVxuICB9XG5cbiAgd2hpbGUgKGNoICE9PSAwKSB7XG4gICAgcmVhZExpbmVCcmVhayhzdGF0ZSk7XG4gICAgc3RhdGUubGluZUluZGVudCA9IDA7XG5cbiAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24pO1xuXG4gICAgd2hpbGUgKCghZGV0ZWN0ZWRJbmRlbnQgfHwgc3RhdGUubGluZUluZGVudCA8IHRleHRJbmRlbnQpICYmXG4gICAgICAgICAgIChjaCA9PT0gMHgyMC8qIFNwYWNlICovKSkge1xuICAgICAgc3RhdGUubGluZUluZGVudCsrO1xuICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuICAgIH1cblxuICAgIGlmICghZGV0ZWN0ZWRJbmRlbnQgJiYgc3RhdGUubGluZUluZGVudCA+IHRleHRJbmRlbnQpIHtcbiAgICAgIHRleHRJbmRlbnQgPSBzdGF0ZS5saW5lSW5kZW50O1xuICAgIH1cblxuICAgIGlmIChpc19FT0woY2gpKSB7XG4gICAgICBlbXB0eUxpbmVzKys7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICAvLyBFbmQgb2YgdGhlIHNjYWxhci5cbiAgICBpZiAoc3RhdGUubGluZUluZGVudCA8IHRleHRJbmRlbnQpIHtcblxuICAgICAgLy8gUGVyZm9ybSB0aGUgY2hvbXBpbmcuXG4gICAgICBpZiAoY2hvbXBpbmcgPT09IENIT01QSU5HX0tFRVApIHtcbiAgICAgICAgc3RhdGUucmVzdWx0ICs9IGNvbW1vbi5yZXBlYXQoJ1xcbicsIGRpZFJlYWRDb250ZW50ID8gMSArIGVtcHR5TGluZXMgOiBlbXB0eUxpbmVzKTtcbiAgICAgIH0gZWxzZSBpZiAoY2hvbXBpbmcgPT09IENIT01QSU5HX0NMSVApIHtcbiAgICAgICAgaWYgKGRpZFJlYWRDb250ZW50KSB7IC8vIGkuZS4gb25seSBpZiB0aGUgc2NhbGFyIGlzIG5vdCBlbXB0eS5cbiAgICAgICAgICBzdGF0ZS5yZXN1bHQgKz0gJ1xcbic7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gQnJlYWsgdGhpcyBgd2hpbGVgIGN5Y2xlIGFuZCBnbyB0byB0aGUgZnVuY2l0b24ncyBlcGlsb2d1ZS5cbiAgICAgIGJyZWFrO1xuICAgIH1cblxuICAgIC8vIEZvbGRlZCBzdHlsZTogdXNlIGZhbmN5IHJ1bGVzIHRvIGhhbmRsZSBsaW5lIGJyZWFrcy5cbiAgICBpZiAoZm9sZGluZykge1xuXG4gICAgICAvLyBMaW5lcyBzdGFydGluZyB3aXRoIHdoaXRlIHNwYWNlIGNoYXJhY3RlcnMgKG1vcmUtaW5kZW50ZWQgbGluZXMpIGFyZSBub3QgZm9sZGVkLlxuICAgICAgaWYgKGlzX1dISVRFX1NQQUNFKGNoKSkge1xuICAgICAgICBhdE1vcmVJbmRlbnRlZCA9IHRydWU7XG4gICAgICAgIC8vIGV4Y2VwdCBmb3IgdGhlIGZpcnN0IGNvbnRlbnQgbGluZSAoY2YuIEV4YW1wbGUgOC4xKVxuICAgICAgICBzdGF0ZS5yZXN1bHQgKz0gY29tbW9uLnJlcGVhdCgnXFxuJywgZGlkUmVhZENvbnRlbnQgPyAxICsgZW1wdHlMaW5lcyA6IGVtcHR5TGluZXMpO1xuXG4gICAgICAvLyBFbmQgb2YgbW9yZS1pbmRlbnRlZCBibG9jay5cbiAgICAgIH0gZWxzZSBpZiAoYXRNb3JlSW5kZW50ZWQpIHtcbiAgICAgICAgYXRNb3JlSW5kZW50ZWQgPSBmYWxzZTtcbiAgICAgICAgc3RhdGUucmVzdWx0ICs9IGNvbW1vbi5yZXBlYXQoJ1xcbicsIGVtcHR5TGluZXMgKyAxKTtcblxuICAgICAgLy8gSnVzdCBvbmUgbGluZSBicmVhayAtIHBlcmNlaXZlIGFzIHRoZSBzYW1lIGxpbmUuXG4gICAgICB9IGVsc2UgaWYgKGVtcHR5TGluZXMgPT09IDApIHtcbiAgICAgICAgaWYgKGRpZFJlYWRDb250ZW50KSB7IC8vIGkuZS4gb25seSBpZiB3ZSBoYXZlIGFscmVhZHkgcmVhZCBzb21lIHNjYWxhciBjb250ZW50LlxuICAgICAgICAgIHN0YXRlLnJlc3VsdCArPSAnICc7XG4gICAgICAgIH1cblxuICAgICAgLy8gU2V2ZXJhbCBsaW5lIGJyZWFrcyAtIHBlcmNlaXZlIGFzIGRpZmZlcmVudCBsaW5lcy5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0YXRlLnJlc3VsdCArPSBjb21tb24ucmVwZWF0KCdcXG4nLCBlbXB0eUxpbmVzKTtcbiAgICAgIH1cblxuICAgIC8vIExpdGVyYWwgc3R5bGU6IGp1c3QgYWRkIGV4YWN0IG51bWJlciBvZiBsaW5lIGJyZWFrcyBiZXR3ZWVuIGNvbnRlbnQgbGluZXMuXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEtlZXAgYWxsIGxpbmUgYnJlYWtzIGV4Y2VwdCB0aGUgaGVhZGVyIGxpbmUgYnJlYWsuXG4gICAgICBzdGF0ZS5yZXN1bHQgKz0gY29tbW9uLnJlcGVhdCgnXFxuJywgZGlkUmVhZENvbnRlbnQgPyAxICsgZW1wdHlMaW5lcyA6IGVtcHR5TGluZXMpO1xuICAgIH1cblxuICAgIGRpZFJlYWRDb250ZW50ID0gdHJ1ZTtcbiAgICBkZXRlY3RlZEluZGVudCA9IHRydWU7XG4gICAgZW1wdHlMaW5lcyA9IDA7XG4gICAgY2FwdHVyZVN0YXJ0ID0gc3RhdGUucG9zaXRpb247XG5cbiAgICB3aGlsZSAoIWlzX0VPTChjaCkgJiYgKGNoICE9PSAwKSkge1xuICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuICAgIH1cblxuICAgIGNhcHR1cmVTZWdtZW50KHN0YXRlLCBjYXB0dXJlU3RhcnQsIHN0YXRlLnBvc2l0aW9uLCBmYWxzZSk7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gcmVhZEJsb2NrU2VxdWVuY2Uoc3RhdGUsIG5vZGVJbmRlbnQpIHtcbiAgdmFyIF9saW5lLFxuICAgICAgX3RhZyAgICAgID0gc3RhdGUudGFnLFxuICAgICAgX2FuY2hvciAgID0gc3RhdGUuYW5jaG9yLFxuICAgICAgX3Jlc3VsdCAgID0gW10sXG4gICAgICBmb2xsb3dpbmcsXG4gICAgICBkZXRlY3RlZCAgPSBmYWxzZSxcbiAgICAgIGNoO1xuXG4gIGlmIChzdGF0ZS5hbmNob3IgIT09IG51bGwpIHtcbiAgICBzdGF0ZS5hbmNob3JNYXBbc3RhdGUuYW5jaG9yXSA9IF9yZXN1bHQ7XG4gIH1cblxuICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24pO1xuXG4gIHdoaWxlIChjaCAhPT0gMCkge1xuXG4gICAgaWYgKGNoICE9PSAweDJELyogLSAqLykge1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgZm9sbG93aW5nID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbiArIDEpO1xuXG4gICAgaWYgKCFpc19XU19PUl9FT0woZm9sbG93aW5nKSkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgZGV0ZWN0ZWQgPSB0cnVlO1xuICAgIHN0YXRlLnBvc2l0aW9uKys7XG5cbiAgICBpZiAoc2tpcFNlcGFyYXRpb25TcGFjZShzdGF0ZSwgdHJ1ZSwgLTEpKSB7XG4gICAgICBpZiAoc3RhdGUubGluZUluZGVudCA8PSBub2RlSW5kZW50KSB7XG4gICAgICAgIF9yZXN1bHQucHVzaChudWxsKTtcbiAgICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgX2xpbmUgPSBzdGF0ZS5saW5lO1xuICAgIGNvbXBvc2VOb2RlKHN0YXRlLCBub2RlSW5kZW50LCBDT05URVhUX0JMT0NLX0lOLCBmYWxzZSwgdHJ1ZSk7XG4gICAgX3Jlc3VsdC5wdXNoKHN0YXRlLnJlc3VsdCk7XG4gICAgc2tpcFNlcGFyYXRpb25TcGFjZShzdGF0ZSwgdHJ1ZSwgLTEpO1xuXG4gICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcblxuICAgIGlmICgoc3RhdGUubGluZSA9PT0gX2xpbmUgfHwgc3RhdGUubGluZUluZGVudCA+IG5vZGVJbmRlbnQpICYmIChjaCAhPT0gMCkpIHtcbiAgICAgIHRocm93RXJyb3Ioc3RhdGUsICdiYWQgaW5kZW50YXRpb24gb2YgYSBzZXF1ZW5jZSBlbnRyeScpO1xuICAgIH0gZWxzZSBpZiAoc3RhdGUubGluZUluZGVudCA8IG5vZGVJbmRlbnQpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIGlmIChkZXRlY3RlZCkge1xuICAgIHN0YXRlLnRhZyA9IF90YWc7XG4gICAgc3RhdGUuYW5jaG9yID0gX2FuY2hvcjtcbiAgICBzdGF0ZS5raW5kID0gJ3NlcXVlbmNlJztcbiAgICBzdGF0ZS5yZXN1bHQgPSBfcmVzdWx0O1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gcmVhZEJsb2NrTWFwcGluZyhzdGF0ZSwgbm9kZUluZGVudCwgZmxvd0luZGVudCkge1xuICB2YXIgZm9sbG93aW5nLFxuICAgICAgYWxsb3dDb21wYWN0LFxuICAgICAgX2xpbmUsXG4gICAgICBfdGFnICAgICAgICAgID0gc3RhdGUudGFnLFxuICAgICAgX2FuY2hvciAgICAgICA9IHN0YXRlLmFuY2hvcixcbiAgICAgIF9yZXN1bHQgICAgICAgPSB7fSxcbiAgICAgIG92ZXJyaWRhYmxlS2V5cyA9IHt9LFxuICAgICAga2V5VGFnICAgICAgICA9IG51bGwsXG4gICAgICBrZXlOb2RlICAgICAgID0gbnVsbCxcbiAgICAgIHZhbHVlTm9kZSAgICAgPSBudWxsLFxuICAgICAgYXRFeHBsaWNpdEtleSA9IGZhbHNlLFxuICAgICAgZGV0ZWN0ZWQgICAgICA9IGZhbHNlLFxuICAgICAgY2g7XG5cbiAgaWYgKHN0YXRlLmFuY2hvciAhPT0gbnVsbCkge1xuICAgIHN0YXRlLmFuY2hvck1hcFtzdGF0ZS5hbmNob3JdID0gX3Jlc3VsdDtcbiAgfVxuXG4gIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbik7XG5cbiAgd2hpbGUgKGNoICE9PSAwKSB7XG4gICAgZm9sbG93aW5nID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbiArIDEpO1xuICAgIF9saW5lID0gc3RhdGUubGluZTsgLy8gU2F2ZSB0aGUgY3VycmVudCBsaW5lLlxuXG4gICAgLy9cbiAgICAvLyBFeHBsaWNpdCBub3RhdGlvbiBjYXNlLiBUaGVyZSBhcmUgdHdvIHNlcGFyYXRlIGJsb2NrczpcbiAgICAvLyBmaXJzdCBmb3IgdGhlIGtleSAoZGVub3RlZCBieSBcIj9cIikgYW5kIHNlY29uZCBmb3IgdGhlIHZhbHVlIChkZW5vdGVkIGJ5IFwiOlwiKVxuICAgIC8vXG4gICAgaWYgKChjaCA9PT0gMHgzRi8qID8gKi8gfHwgY2ggPT09IDB4M0EvKiA6ICovKSAmJiBpc19XU19PUl9FT0woZm9sbG93aW5nKSkge1xuXG4gICAgICBpZiAoY2ggPT09IDB4M0YvKiA/ICovKSB7XG4gICAgICAgIGlmIChhdEV4cGxpY2l0S2V5KSB7XG4gICAgICAgICAgc3RvcmVNYXBwaW5nUGFpcihzdGF0ZSwgX3Jlc3VsdCwgb3ZlcnJpZGFibGVLZXlzLCBrZXlUYWcsIGtleU5vZGUsIG51bGwpO1xuICAgICAgICAgIGtleVRhZyA9IGtleU5vZGUgPSB2YWx1ZU5vZGUgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgZGV0ZWN0ZWQgPSB0cnVlO1xuICAgICAgICBhdEV4cGxpY2l0S2V5ID0gdHJ1ZTtcbiAgICAgICAgYWxsb3dDb21wYWN0ID0gdHJ1ZTtcblxuICAgICAgfSBlbHNlIGlmIChhdEV4cGxpY2l0S2V5KSB7XG4gICAgICAgIC8vIGkuZS4gMHgzQS8qIDogKi8gPT09IGNoYXJhY3RlciBhZnRlciB0aGUgZXhwbGljaXQga2V5LlxuICAgICAgICBhdEV4cGxpY2l0S2V5ID0gZmFsc2U7XG4gICAgICAgIGFsbG93Q29tcGFjdCA9IHRydWU7XG5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93RXJyb3Ioc3RhdGUsICdpbmNvbXBsZXRlIGV4cGxpY2l0IG1hcHBpbmcgcGFpcjsgYSBrZXkgbm9kZSBpcyBtaXNzZWQnKTtcbiAgICAgIH1cblxuICAgICAgc3RhdGUucG9zaXRpb24gKz0gMTtcbiAgICAgIGNoID0gZm9sbG93aW5nO1xuXG4gICAgLy9cbiAgICAvLyBJbXBsaWNpdCBub3RhdGlvbiBjYXNlLiBGbG93LXN0eWxlIG5vZGUgYXMgdGhlIGtleSBmaXJzdCwgdGhlbiBcIjpcIiwgYW5kIHRoZSB2YWx1ZS5cbiAgICAvL1xuICAgIH0gZWxzZSBpZiAoY29tcG9zZU5vZGUoc3RhdGUsIGZsb3dJbmRlbnQsIENPTlRFWFRfRkxPV19PVVQsIGZhbHNlLCB0cnVlKSkge1xuXG4gICAgICBpZiAoc3RhdGUubGluZSA9PT0gX2xpbmUpIHtcbiAgICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcblxuICAgICAgICB3aGlsZSAoaXNfV0hJVEVfU1BBQ0UoY2gpKSB7XG4gICAgICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNoID09PSAweDNBLyogOiAqLykge1xuICAgICAgICAgIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdCgrK3N0YXRlLnBvc2l0aW9uKTtcblxuICAgICAgICAgIGlmICghaXNfV1NfT1JfRU9MKGNoKSkge1xuICAgICAgICAgICAgdGhyb3dFcnJvcihzdGF0ZSwgJ2Egd2hpdGVzcGFjZSBjaGFyYWN0ZXIgaXMgZXhwZWN0ZWQgYWZ0ZXIgdGhlIGtleS12YWx1ZSBzZXBhcmF0b3Igd2l0aGluIGEgYmxvY2sgbWFwcGluZycpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChhdEV4cGxpY2l0S2V5KSB7XG4gICAgICAgICAgICBzdG9yZU1hcHBpbmdQYWlyKHN0YXRlLCBfcmVzdWx0LCBvdmVycmlkYWJsZUtleXMsIGtleVRhZywga2V5Tm9kZSwgbnVsbCk7XG4gICAgICAgICAgICBrZXlUYWcgPSBrZXlOb2RlID0gdmFsdWVOb2RlID0gbnVsbDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBkZXRlY3RlZCA9IHRydWU7XG4gICAgICAgICAgYXRFeHBsaWNpdEtleSA9IGZhbHNlO1xuICAgICAgICAgIGFsbG93Q29tcGFjdCA9IGZhbHNlO1xuICAgICAgICAgIGtleVRhZyA9IHN0YXRlLnRhZztcbiAgICAgICAgICBrZXlOb2RlID0gc3RhdGUucmVzdWx0O1xuXG4gICAgICAgIH0gZWxzZSBpZiAoZGV0ZWN0ZWQpIHtcbiAgICAgICAgICB0aHJvd0Vycm9yKHN0YXRlLCAnY2FuIG5vdCByZWFkIGFuIGltcGxpY2l0IG1hcHBpbmcgcGFpcjsgYSBjb2xvbiBpcyBtaXNzZWQnKTtcblxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0YXRlLnRhZyA9IF90YWc7XG4gICAgICAgICAgc3RhdGUuYW5jaG9yID0gX2FuY2hvcjtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTsgLy8gS2VlcCB0aGUgcmVzdWx0IG9mIGBjb21wb3NlTm9kZWAuXG4gICAgICAgIH1cblxuICAgICAgfSBlbHNlIGlmIChkZXRlY3RlZCkge1xuICAgICAgICB0aHJvd0Vycm9yKHN0YXRlLCAnY2FuIG5vdCByZWFkIGEgYmxvY2sgbWFwcGluZyBlbnRyeTsgYSBtdWx0aWxpbmUga2V5IG1heSBub3QgYmUgYW4gaW1wbGljaXQga2V5Jyk7XG5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0YXRlLnRhZyA9IF90YWc7XG4gICAgICAgIHN0YXRlLmFuY2hvciA9IF9hbmNob3I7XG4gICAgICAgIHJldHVybiB0cnVlOyAvLyBLZWVwIHRoZSByZXN1bHQgb2YgYGNvbXBvc2VOb2RlYC5cbiAgICAgIH1cblxuICAgIH0gZWxzZSB7XG4gICAgICBicmVhazsgLy8gUmVhZGluZyBpcyBkb25lLiBHbyB0byB0aGUgZXBpbG9ndWUuXG4gICAgfVxuXG4gICAgLy9cbiAgICAvLyBDb21tb24gcmVhZGluZyBjb2RlIGZvciBib3RoIGV4cGxpY2l0IGFuZCBpbXBsaWNpdCBub3RhdGlvbnMuXG4gICAgLy9cbiAgICBpZiAoc3RhdGUubGluZSA9PT0gX2xpbmUgfHwgc3RhdGUubGluZUluZGVudCA+IG5vZGVJbmRlbnQpIHtcbiAgICAgIGlmIChjb21wb3NlTm9kZShzdGF0ZSwgbm9kZUluZGVudCwgQ09OVEVYVF9CTE9DS19PVVQsIHRydWUsIGFsbG93Q29tcGFjdCkpIHtcbiAgICAgICAgaWYgKGF0RXhwbGljaXRLZXkpIHtcbiAgICAgICAgICBrZXlOb2RlID0gc3RhdGUucmVzdWx0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhbHVlTm9kZSA9IHN0YXRlLnJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoIWF0RXhwbGljaXRLZXkpIHtcbiAgICAgICAgc3RvcmVNYXBwaW5nUGFpcihzdGF0ZSwgX3Jlc3VsdCwgb3ZlcnJpZGFibGVLZXlzLCBrZXlUYWcsIGtleU5vZGUsIHZhbHVlTm9kZSk7XG4gICAgICAgIGtleVRhZyA9IGtleU5vZGUgPSB2YWx1ZU5vZGUgPSBudWxsO1xuICAgICAgfVxuXG4gICAgICBza2lwU2VwYXJhdGlvblNwYWNlKHN0YXRlLCB0cnVlLCAtMSk7XG4gICAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24pO1xuICAgIH1cblxuICAgIGlmIChzdGF0ZS5saW5lSW5kZW50ID4gbm9kZUluZGVudCAmJiAoY2ggIT09IDApKSB7XG4gICAgICB0aHJvd0Vycm9yKHN0YXRlLCAnYmFkIGluZGVudGF0aW9uIG9mIGEgbWFwcGluZyBlbnRyeScpO1xuICAgIH0gZWxzZSBpZiAoc3RhdGUubGluZUluZGVudCA8IG5vZGVJbmRlbnQpIHtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIC8vXG4gIC8vIEVwaWxvZ3VlLlxuICAvL1xuXG4gIC8vIFNwZWNpYWwgY2FzZTogbGFzdCBtYXBwaW5nJ3Mgbm9kZSBjb250YWlucyBvbmx5IHRoZSBrZXkgaW4gZXhwbGljaXQgbm90YXRpb24uXG4gIGlmIChhdEV4cGxpY2l0S2V5KSB7XG4gICAgc3RvcmVNYXBwaW5nUGFpcihzdGF0ZSwgX3Jlc3VsdCwgb3ZlcnJpZGFibGVLZXlzLCBrZXlUYWcsIGtleU5vZGUsIG51bGwpO1xuICB9XG5cbiAgLy8gRXhwb3NlIHRoZSByZXN1bHRpbmcgbWFwcGluZy5cbiAgaWYgKGRldGVjdGVkKSB7XG4gICAgc3RhdGUudGFnID0gX3RhZztcbiAgICBzdGF0ZS5hbmNob3IgPSBfYW5jaG9yO1xuICAgIHN0YXRlLmtpbmQgPSAnbWFwcGluZyc7XG4gICAgc3RhdGUucmVzdWx0ID0gX3Jlc3VsdDtcbiAgfVxuXG4gIHJldHVybiBkZXRlY3RlZDtcbn1cblxuZnVuY3Rpb24gcmVhZFRhZ1Byb3BlcnR5KHN0YXRlKSB7XG4gIHZhciBfcG9zaXRpb24sXG4gICAgICBpc1ZlcmJhdGltID0gZmFsc2UsXG4gICAgICBpc05hbWVkICAgID0gZmFsc2UsXG4gICAgICB0YWdIYW5kbGUsXG4gICAgICB0YWdOYW1lLFxuICAgICAgY2g7XG5cbiAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKTtcblxuICBpZiAoY2ggIT09IDB4MjEvKiAhICovKSByZXR1cm4gZmFsc2U7XG5cbiAgaWYgKHN0YXRlLnRhZyAhPT0gbnVsbCkge1xuICAgIHRocm93RXJyb3Ioc3RhdGUsICdkdXBsaWNhdGlvbiBvZiBhIHRhZyBwcm9wZXJ0eScpO1xuICB9XG5cbiAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuXG4gIGlmIChjaCA9PT0gMHgzQy8qIDwgKi8pIHtcbiAgICBpc1ZlcmJhdGltID0gdHJ1ZTtcbiAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG5cbiAgfSBlbHNlIGlmIChjaCA9PT0gMHgyMS8qICEgKi8pIHtcbiAgICBpc05hbWVkID0gdHJ1ZTtcbiAgICB0YWdIYW5kbGUgPSAnISEnO1xuICAgIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdCgrK3N0YXRlLnBvc2l0aW9uKTtcblxuICB9IGVsc2Uge1xuICAgIHRhZ0hhbmRsZSA9ICchJztcbiAgfVxuXG4gIF9wb3NpdGlvbiA9IHN0YXRlLnBvc2l0aW9uO1xuXG4gIGlmIChpc1ZlcmJhdGltKSB7XG4gICAgZG8geyBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7IH1cbiAgICB3aGlsZSAoY2ggIT09IDAgJiYgY2ggIT09IDB4M0UvKiA+ICovKTtcblxuICAgIGlmIChzdGF0ZS5wb3NpdGlvbiA8IHN0YXRlLmxlbmd0aCkge1xuICAgICAgdGFnTmFtZSA9IHN0YXRlLmlucHV0LnNsaWNlKF9wb3NpdGlvbiwgc3RhdGUucG9zaXRpb24pO1xuICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvd0Vycm9yKHN0YXRlLCAndW5leHBlY3RlZCBlbmQgb2YgdGhlIHN0cmVhbSB3aXRoaW4gYSB2ZXJiYXRpbSB0YWcnKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgd2hpbGUgKGNoICE9PSAwICYmICFpc19XU19PUl9FT0woY2gpKSB7XG5cbiAgICAgIGlmIChjaCA9PT0gMHgyMS8qICEgKi8pIHtcbiAgICAgICAgaWYgKCFpc05hbWVkKSB7XG4gICAgICAgICAgdGFnSGFuZGxlID0gc3RhdGUuaW5wdXQuc2xpY2UoX3Bvc2l0aW9uIC0gMSwgc3RhdGUucG9zaXRpb24gKyAxKTtcblxuICAgICAgICAgIGlmICghUEFUVEVSTl9UQUdfSEFORExFLnRlc3QodGFnSGFuZGxlKSkge1xuICAgICAgICAgICAgdGhyb3dFcnJvcihzdGF0ZSwgJ25hbWVkIHRhZyBoYW5kbGUgY2Fubm90IGNvbnRhaW4gc3VjaCBjaGFyYWN0ZXJzJyk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaXNOYW1lZCA9IHRydWU7XG4gICAgICAgICAgX3Bvc2l0aW9uID0gc3RhdGUucG9zaXRpb24gKyAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93RXJyb3Ioc3RhdGUsICd0YWcgc3VmZml4IGNhbm5vdCBjb250YWluIGV4Y2xhbWF0aW9uIG1hcmtzJyk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuICAgIH1cblxuICAgIHRhZ05hbWUgPSBzdGF0ZS5pbnB1dC5zbGljZShfcG9zaXRpb24sIHN0YXRlLnBvc2l0aW9uKTtcblxuICAgIGlmIChQQVRURVJOX0ZMT1dfSU5ESUNBVE9SUy50ZXN0KHRhZ05hbWUpKSB7XG4gICAgICB0aHJvd0Vycm9yKHN0YXRlLCAndGFnIHN1ZmZpeCBjYW5ub3QgY29udGFpbiBmbG93IGluZGljYXRvciBjaGFyYWN0ZXJzJyk7XG4gICAgfVxuICB9XG5cbiAgaWYgKHRhZ05hbWUgJiYgIVBBVFRFUk5fVEFHX1VSSS50ZXN0KHRhZ05hbWUpKSB7XG4gICAgdGhyb3dFcnJvcihzdGF0ZSwgJ3RhZyBuYW1lIGNhbm5vdCBjb250YWluIHN1Y2ggY2hhcmFjdGVyczogJyArIHRhZ05hbWUpO1xuICB9XG5cbiAgaWYgKGlzVmVyYmF0aW0pIHtcbiAgICBzdGF0ZS50YWcgPSB0YWdOYW1lO1xuXG4gIH0gZWxzZSBpZiAoX2hhc093blByb3BlcnR5LmNhbGwoc3RhdGUudGFnTWFwLCB0YWdIYW5kbGUpKSB7XG4gICAgc3RhdGUudGFnID0gc3RhdGUudGFnTWFwW3RhZ0hhbmRsZV0gKyB0YWdOYW1lO1xuXG4gIH0gZWxzZSBpZiAodGFnSGFuZGxlID09PSAnIScpIHtcbiAgICBzdGF0ZS50YWcgPSAnIScgKyB0YWdOYW1lO1xuXG4gIH0gZWxzZSBpZiAodGFnSGFuZGxlID09PSAnISEnKSB7XG4gICAgc3RhdGUudGFnID0gJ3RhZzp5YW1sLm9yZywyMDAyOicgKyB0YWdOYW1lO1xuXG4gIH0gZWxzZSB7XG4gICAgdGhyb3dFcnJvcihzdGF0ZSwgJ3VuZGVjbGFyZWQgdGFnIGhhbmRsZSBcIicgKyB0YWdIYW5kbGUgKyAnXCInKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiByZWFkQW5jaG9yUHJvcGVydHkoc3RhdGUpIHtcbiAgdmFyIF9wb3NpdGlvbixcbiAgICAgIGNoO1xuXG4gIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbik7XG5cbiAgaWYgKGNoICE9PSAweDI2LyogJiAqLykgcmV0dXJuIGZhbHNlO1xuXG4gIGlmIChzdGF0ZS5hbmNob3IgIT09IG51bGwpIHtcbiAgICB0aHJvd0Vycm9yKHN0YXRlLCAnZHVwbGljYXRpb24gb2YgYW4gYW5jaG9yIHByb3BlcnR5Jyk7XG4gIH1cblxuICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG4gIF9wb3NpdGlvbiA9IHN0YXRlLnBvc2l0aW9uO1xuXG4gIHdoaWxlIChjaCAhPT0gMCAmJiAhaXNfV1NfT1JfRU9MKGNoKSAmJiAhaXNfRkxPV19JTkRJQ0FUT1IoY2gpKSB7XG4gICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuICB9XG5cbiAgaWYgKHN0YXRlLnBvc2l0aW9uID09PSBfcG9zaXRpb24pIHtcbiAgICB0aHJvd0Vycm9yKHN0YXRlLCAnbmFtZSBvZiBhbiBhbmNob3Igbm9kZSBtdXN0IGNvbnRhaW4gYXQgbGVhc3Qgb25lIGNoYXJhY3RlcicpO1xuICB9XG5cbiAgc3RhdGUuYW5jaG9yID0gc3RhdGUuaW5wdXQuc2xpY2UoX3Bvc2l0aW9uLCBzdGF0ZS5wb3NpdGlvbik7XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiByZWFkQWxpYXMoc3RhdGUpIHtcbiAgdmFyIF9wb3NpdGlvbiwgYWxpYXMsXG4gICAgICBjaDtcblxuICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24pO1xuXG4gIGlmIChjaCAhPT0gMHgyQS8qICogKi8pIHJldHVybiBmYWxzZTtcblxuICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG4gIF9wb3NpdGlvbiA9IHN0YXRlLnBvc2l0aW9uO1xuXG4gIHdoaWxlIChjaCAhPT0gMCAmJiAhaXNfV1NfT1JfRU9MKGNoKSAmJiAhaXNfRkxPV19JTkRJQ0FUT1IoY2gpKSB7XG4gICAgY2ggPSBzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KCsrc3RhdGUucG9zaXRpb24pO1xuICB9XG5cbiAgaWYgKHN0YXRlLnBvc2l0aW9uID09PSBfcG9zaXRpb24pIHtcbiAgICB0aHJvd0Vycm9yKHN0YXRlLCAnbmFtZSBvZiBhbiBhbGlhcyBub2RlIG11c3QgY29udGFpbiBhdCBsZWFzdCBvbmUgY2hhcmFjdGVyJyk7XG4gIH1cblxuICBhbGlhcyA9IHN0YXRlLmlucHV0LnNsaWNlKF9wb3NpdGlvbiwgc3RhdGUucG9zaXRpb24pO1xuXG4gIGlmICghc3RhdGUuYW5jaG9yTWFwLmhhc093blByb3BlcnR5KGFsaWFzKSkge1xuICAgIHRocm93RXJyb3Ioc3RhdGUsICd1bmlkZW50aWZpZWQgYWxpYXMgXCInICsgYWxpYXMgKyAnXCInKTtcbiAgfVxuXG4gIHN0YXRlLnJlc3VsdCA9IHN0YXRlLmFuY2hvck1hcFthbGlhc107XG4gIHNraXBTZXBhcmF0aW9uU3BhY2Uoc3RhdGUsIHRydWUsIC0xKTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGNvbXBvc2VOb2RlKHN0YXRlLCBwYXJlbnRJbmRlbnQsIG5vZGVDb250ZXh0LCBhbGxvd1RvU2VlaywgYWxsb3dDb21wYWN0KSB7XG4gIHZhciBhbGxvd0Jsb2NrU3R5bGVzLFxuICAgICAgYWxsb3dCbG9ja1NjYWxhcnMsXG4gICAgICBhbGxvd0Jsb2NrQ29sbGVjdGlvbnMsXG4gICAgICBpbmRlbnRTdGF0dXMgPSAxLCAvLyAxOiB0aGlzPnBhcmVudCwgMDogdGhpcz1wYXJlbnQsIC0xOiB0aGlzPHBhcmVudFxuICAgICAgYXROZXdMaW5lICA9IGZhbHNlLFxuICAgICAgaGFzQ29udGVudCA9IGZhbHNlLFxuICAgICAgdHlwZUluZGV4LFxuICAgICAgdHlwZVF1YW50aXR5LFxuICAgICAgdHlwZSxcbiAgICAgIGZsb3dJbmRlbnQsXG4gICAgICBibG9ja0luZGVudDtcblxuICBpZiAoc3RhdGUubGlzdGVuZXIgIT09IG51bGwpIHtcbiAgICBzdGF0ZS5saXN0ZW5lcignb3BlbicsIHN0YXRlKTtcbiAgfVxuXG4gIHN0YXRlLnRhZyAgICA9IG51bGw7XG4gIHN0YXRlLmFuY2hvciA9IG51bGw7XG4gIHN0YXRlLmtpbmQgICA9IG51bGw7XG4gIHN0YXRlLnJlc3VsdCA9IG51bGw7XG5cbiAgYWxsb3dCbG9ja1N0eWxlcyA9IGFsbG93QmxvY2tTY2FsYXJzID0gYWxsb3dCbG9ja0NvbGxlY3Rpb25zID1cbiAgICBDT05URVhUX0JMT0NLX09VVCA9PT0gbm9kZUNvbnRleHQgfHxcbiAgICBDT05URVhUX0JMT0NLX0lOICA9PT0gbm9kZUNvbnRleHQ7XG5cbiAgaWYgKGFsbG93VG9TZWVrKSB7XG4gICAgaWYgKHNraXBTZXBhcmF0aW9uU3BhY2Uoc3RhdGUsIHRydWUsIC0xKSkge1xuICAgICAgYXROZXdMaW5lID0gdHJ1ZTtcblxuICAgICAgaWYgKHN0YXRlLmxpbmVJbmRlbnQgPiBwYXJlbnRJbmRlbnQpIHtcbiAgICAgICAgaW5kZW50U3RhdHVzID0gMTtcbiAgICAgIH0gZWxzZSBpZiAoc3RhdGUubGluZUluZGVudCA9PT0gcGFyZW50SW5kZW50KSB7XG4gICAgICAgIGluZGVudFN0YXR1cyA9IDA7XG4gICAgICB9IGVsc2UgaWYgKHN0YXRlLmxpbmVJbmRlbnQgPCBwYXJlbnRJbmRlbnQpIHtcbiAgICAgICAgaW5kZW50U3RhdHVzID0gLTE7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaWYgKGluZGVudFN0YXR1cyA9PT0gMSkge1xuICAgIHdoaWxlIChyZWFkVGFnUHJvcGVydHkoc3RhdGUpIHx8IHJlYWRBbmNob3JQcm9wZXJ0eShzdGF0ZSkpIHtcbiAgICAgIGlmIChza2lwU2VwYXJhdGlvblNwYWNlKHN0YXRlLCB0cnVlLCAtMSkpIHtcbiAgICAgICAgYXROZXdMaW5lID0gdHJ1ZTtcbiAgICAgICAgYWxsb3dCbG9ja0NvbGxlY3Rpb25zID0gYWxsb3dCbG9ja1N0eWxlcztcblxuICAgICAgICBpZiAoc3RhdGUubGluZUluZGVudCA+IHBhcmVudEluZGVudCkge1xuICAgICAgICAgIGluZGVudFN0YXR1cyA9IDE7XG4gICAgICAgIH0gZWxzZSBpZiAoc3RhdGUubGluZUluZGVudCA9PT0gcGFyZW50SW5kZW50KSB7XG4gICAgICAgICAgaW5kZW50U3RhdHVzID0gMDtcbiAgICAgICAgfSBlbHNlIGlmIChzdGF0ZS5saW5lSW5kZW50IDwgcGFyZW50SW5kZW50KSB7XG4gICAgICAgICAgaW5kZW50U3RhdHVzID0gLTE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFsbG93QmxvY2tDb2xsZWN0aW9ucyA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmIChhbGxvd0Jsb2NrQ29sbGVjdGlvbnMpIHtcbiAgICBhbGxvd0Jsb2NrQ29sbGVjdGlvbnMgPSBhdE5ld0xpbmUgfHwgYWxsb3dDb21wYWN0O1xuICB9XG5cbiAgaWYgKGluZGVudFN0YXR1cyA9PT0gMSB8fCBDT05URVhUX0JMT0NLX09VVCA9PT0gbm9kZUNvbnRleHQpIHtcbiAgICBpZiAoQ09OVEVYVF9GTE9XX0lOID09PSBub2RlQ29udGV4dCB8fCBDT05URVhUX0ZMT1dfT1VUID09PSBub2RlQ29udGV4dCkge1xuICAgICAgZmxvd0luZGVudCA9IHBhcmVudEluZGVudDtcbiAgICB9IGVsc2Uge1xuICAgICAgZmxvd0luZGVudCA9IHBhcmVudEluZGVudCArIDE7XG4gICAgfVxuXG4gICAgYmxvY2tJbmRlbnQgPSBzdGF0ZS5wb3NpdGlvbiAtIHN0YXRlLmxpbmVTdGFydDtcblxuICAgIGlmIChpbmRlbnRTdGF0dXMgPT09IDEpIHtcbiAgICAgIGlmIChhbGxvd0Jsb2NrQ29sbGVjdGlvbnMgJiZcbiAgICAgICAgICAocmVhZEJsb2NrU2VxdWVuY2Uoc3RhdGUsIGJsb2NrSW5kZW50KSB8fFxuICAgICAgICAgICByZWFkQmxvY2tNYXBwaW5nKHN0YXRlLCBibG9ja0luZGVudCwgZmxvd0luZGVudCkpIHx8XG4gICAgICAgICAgcmVhZEZsb3dDb2xsZWN0aW9uKHN0YXRlLCBmbG93SW5kZW50KSkge1xuICAgICAgICBoYXNDb250ZW50ID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICgoYWxsb3dCbG9ja1NjYWxhcnMgJiYgcmVhZEJsb2NrU2NhbGFyKHN0YXRlLCBmbG93SW5kZW50KSkgfHxcbiAgICAgICAgICAgIHJlYWRTaW5nbGVRdW90ZWRTY2FsYXIoc3RhdGUsIGZsb3dJbmRlbnQpIHx8XG4gICAgICAgICAgICByZWFkRG91YmxlUXVvdGVkU2NhbGFyKHN0YXRlLCBmbG93SW5kZW50KSkge1xuICAgICAgICAgIGhhc0NvbnRlbnQgPSB0cnVlO1xuXG4gICAgICAgIH0gZWxzZSBpZiAocmVhZEFsaWFzKHN0YXRlKSkge1xuICAgICAgICAgIGhhc0NvbnRlbnQgPSB0cnVlO1xuXG4gICAgICAgICAgaWYgKHN0YXRlLnRhZyAhPT0gbnVsbCB8fCBzdGF0ZS5hbmNob3IgIT09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93RXJyb3Ioc3RhdGUsICdhbGlhcyBub2RlIHNob3VsZCBub3QgaGF2ZSBhbnkgcHJvcGVydGllcycpO1xuICAgICAgICAgIH1cblxuICAgICAgICB9IGVsc2UgaWYgKHJlYWRQbGFpblNjYWxhcihzdGF0ZSwgZmxvd0luZGVudCwgQ09OVEVYVF9GTE9XX0lOID09PSBub2RlQ29udGV4dCkpIHtcbiAgICAgICAgICBoYXNDb250ZW50ID0gdHJ1ZTtcblxuICAgICAgICAgIGlmIChzdGF0ZS50YWcgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHN0YXRlLnRhZyA9ICc/JztcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RhdGUuYW5jaG9yICE9PSBudWxsKSB7XG4gICAgICAgICAgc3RhdGUuYW5jaG9yTWFwW3N0YXRlLmFuY2hvcl0gPSBzdGF0ZS5yZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGluZGVudFN0YXR1cyA9PT0gMCkge1xuICAgICAgLy8gU3BlY2lhbCBjYXNlOiBibG9jayBzZXF1ZW5jZXMgYXJlIGFsbG93ZWQgdG8gaGF2ZSBzYW1lIGluZGVudGF0aW9uIGxldmVsIGFzIHRoZSBwYXJlbnQuXG4gICAgICAvLyBodHRwOi8vd3d3LnlhbWwub3JnL3NwZWMvMS4yL3NwZWMuaHRtbCNpZDI3OTk3ODRcbiAgICAgIGhhc0NvbnRlbnQgPSBhbGxvd0Jsb2NrQ29sbGVjdGlvbnMgJiYgcmVhZEJsb2NrU2VxdWVuY2Uoc3RhdGUsIGJsb2NrSW5kZW50KTtcbiAgICB9XG4gIH1cblxuICBpZiAoc3RhdGUudGFnICE9PSBudWxsICYmIHN0YXRlLnRhZyAhPT0gJyEnKSB7XG4gICAgaWYgKHN0YXRlLnRhZyA9PT0gJz8nKSB7XG4gICAgICBmb3IgKHR5cGVJbmRleCA9IDAsIHR5cGVRdWFudGl0eSA9IHN0YXRlLmltcGxpY2l0VHlwZXMubGVuZ3RoO1xuICAgICAgICAgICB0eXBlSW5kZXggPCB0eXBlUXVhbnRpdHk7XG4gICAgICAgICAgIHR5cGVJbmRleCArPSAxKSB7XG4gICAgICAgIHR5cGUgPSBzdGF0ZS5pbXBsaWNpdFR5cGVzW3R5cGVJbmRleF07XG5cbiAgICAgICAgLy8gSW1wbGljaXQgcmVzb2x2aW5nIGlzIG5vdCBhbGxvd2VkIGZvciBub24tc2NhbGFyIHR5cGVzLCBhbmQgJz8nXG4gICAgICAgIC8vIG5vbi1zcGVjaWZpYyB0YWcgaXMgb25seSBhc3NpZ25lZCB0byBwbGFpbiBzY2FsYXJzLiBTbywgaXQgaXNuJ3RcbiAgICAgICAgLy8gbmVlZGVkIHRvIGNoZWNrIGZvciAna2luZCcgY29uZm9ybWl0eS5cblxuICAgICAgICBpZiAodHlwZS5yZXNvbHZlKHN0YXRlLnJlc3VsdCkpIHsgLy8gYHN0YXRlLnJlc3VsdGAgdXBkYXRlZCBpbiByZXNvbHZlciBpZiBtYXRjaGVkXG4gICAgICAgICAgc3RhdGUucmVzdWx0ID0gdHlwZS5jb25zdHJ1Y3Qoc3RhdGUucmVzdWx0KTtcbiAgICAgICAgICBzdGF0ZS50YWcgPSB0eXBlLnRhZztcbiAgICAgICAgICBpZiAoc3RhdGUuYW5jaG9yICE9PSBudWxsKSB7XG4gICAgICAgICAgICBzdGF0ZS5hbmNob3JNYXBbc3RhdGUuYW5jaG9yXSA9IHN0YXRlLnJlc3VsdDtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKF9oYXNPd25Qcm9wZXJ0eS5jYWxsKHN0YXRlLnR5cGVNYXAsIHN0YXRlLnRhZykpIHtcbiAgICAgIHR5cGUgPSBzdGF0ZS50eXBlTWFwW3N0YXRlLnRhZ107XG5cbiAgICAgIGlmIChzdGF0ZS5yZXN1bHQgIT09IG51bGwgJiYgdHlwZS5raW5kICE9PSBzdGF0ZS5raW5kKSB7XG4gICAgICAgIHRocm93RXJyb3Ioc3RhdGUsICd1bmFjY2VwdGFibGUgbm9kZSBraW5kIGZvciAhPCcgKyBzdGF0ZS50YWcgKyAnPiB0YWc7IGl0IHNob3VsZCBiZSBcIicgKyB0eXBlLmtpbmQgKyAnXCIsIG5vdCBcIicgKyBzdGF0ZS5raW5kICsgJ1wiJyk7XG4gICAgICB9XG5cbiAgICAgIGlmICghdHlwZS5yZXNvbHZlKHN0YXRlLnJlc3VsdCkpIHsgLy8gYHN0YXRlLnJlc3VsdGAgdXBkYXRlZCBpbiByZXNvbHZlciBpZiBtYXRjaGVkXG4gICAgICAgIHRocm93RXJyb3Ioc3RhdGUsICdjYW5ub3QgcmVzb2x2ZSBhIG5vZGUgd2l0aCAhPCcgKyBzdGF0ZS50YWcgKyAnPiBleHBsaWNpdCB0YWcnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0YXRlLnJlc3VsdCA9IHR5cGUuY29uc3RydWN0KHN0YXRlLnJlc3VsdCk7XG4gICAgICAgIGlmIChzdGF0ZS5hbmNob3IgIT09IG51bGwpIHtcbiAgICAgICAgICBzdGF0ZS5hbmNob3JNYXBbc3RhdGUuYW5jaG9yXSA9IHN0YXRlLnJlc3VsdDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvd0Vycm9yKHN0YXRlLCAndW5rbm93biB0YWcgITwnICsgc3RhdGUudGFnICsgJz4nKTtcbiAgICB9XG4gIH1cblxuICBpZiAoc3RhdGUubGlzdGVuZXIgIT09IG51bGwpIHtcbiAgICBzdGF0ZS5saXN0ZW5lcignY2xvc2UnLCBzdGF0ZSk7XG4gIH1cbiAgcmV0dXJuIHN0YXRlLnRhZyAhPT0gbnVsbCB8fCAgc3RhdGUuYW5jaG9yICE9PSBudWxsIHx8IGhhc0NvbnRlbnQ7XG59XG5cbmZ1bmN0aW9uIHJlYWREb2N1bWVudChzdGF0ZSkge1xuICB2YXIgZG9jdW1lbnRTdGFydCA9IHN0YXRlLnBvc2l0aW9uLFxuICAgICAgX3Bvc2l0aW9uLFxuICAgICAgZGlyZWN0aXZlTmFtZSxcbiAgICAgIGRpcmVjdGl2ZUFyZ3MsXG4gICAgICBoYXNEaXJlY3RpdmVzID0gZmFsc2UsXG4gICAgICBjaDtcblxuICBzdGF0ZS52ZXJzaW9uID0gbnVsbDtcbiAgc3RhdGUuY2hlY2tMaW5lQnJlYWtzID0gc3RhdGUubGVnYWN5O1xuICBzdGF0ZS50YWdNYXAgPSB7fTtcbiAgc3RhdGUuYW5jaG9yTWFwID0ge307XG5cbiAgd2hpbGUgKChjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24pKSAhPT0gMCkge1xuICAgIHNraXBTZXBhcmF0aW9uU3BhY2Uoc3RhdGUsIHRydWUsIC0xKTtcblxuICAgIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbik7XG5cbiAgICBpZiAoc3RhdGUubGluZUluZGVudCA+IDAgfHwgY2ggIT09IDB4MjUvKiAlICovKSB7XG4gICAgICBicmVhaztcbiAgICB9XG5cbiAgICBoYXNEaXJlY3RpdmVzID0gdHJ1ZTtcbiAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG4gICAgX3Bvc2l0aW9uID0gc3RhdGUucG9zaXRpb247XG5cbiAgICB3aGlsZSAoY2ggIT09IDAgJiYgIWlzX1dTX09SX0VPTChjaCkpIHtcbiAgICAgIGNoID0gc3RhdGUuaW5wdXQuY2hhckNvZGVBdCgrK3N0YXRlLnBvc2l0aW9uKTtcbiAgICB9XG5cbiAgICBkaXJlY3RpdmVOYW1lID0gc3RhdGUuaW5wdXQuc2xpY2UoX3Bvc2l0aW9uLCBzdGF0ZS5wb3NpdGlvbik7XG4gICAgZGlyZWN0aXZlQXJncyA9IFtdO1xuXG4gICAgaWYgKGRpcmVjdGl2ZU5hbWUubGVuZ3RoIDwgMSkge1xuICAgICAgdGhyb3dFcnJvcihzdGF0ZSwgJ2RpcmVjdGl2ZSBuYW1lIG11c3Qgbm90IGJlIGxlc3MgdGhhbiBvbmUgY2hhcmFjdGVyIGluIGxlbmd0aCcpO1xuICAgIH1cblxuICAgIHdoaWxlIChjaCAhPT0gMCkge1xuICAgICAgd2hpbGUgKGlzX1dISVRFX1NQQUNFKGNoKSkge1xuICAgICAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaCA9PT0gMHgyMy8qICMgKi8pIHtcbiAgICAgICAgZG8geyBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7IH1cbiAgICAgICAgd2hpbGUgKGNoICE9PSAwICYmICFpc19FT0woY2gpKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGlmIChpc19FT0woY2gpKSBicmVhaztcblxuICAgICAgX3Bvc2l0aW9uID0gc3RhdGUucG9zaXRpb247XG5cbiAgICAgIHdoaWxlIChjaCAhPT0gMCAmJiAhaXNfV1NfT1JfRU9MKGNoKSkge1xuICAgICAgICBjaCA9IHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoKytzdGF0ZS5wb3NpdGlvbik7XG4gICAgICB9XG5cbiAgICAgIGRpcmVjdGl2ZUFyZ3MucHVzaChzdGF0ZS5pbnB1dC5zbGljZShfcG9zaXRpb24sIHN0YXRlLnBvc2l0aW9uKSk7XG4gICAgfVxuXG4gICAgaWYgKGNoICE9PSAwKSByZWFkTGluZUJyZWFrKHN0YXRlKTtcblxuICAgIGlmIChfaGFzT3duUHJvcGVydHkuY2FsbChkaXJlY3RpdmVIYW5kbGVycywgZGlyZWN0aXZlTmFtZSkpIHtcbiAgICAgIGRpcmVjdGl2ZUhhbmRsZXJzW2RpcmVjdGl2ZU5hbWVdKHN0YXRlLCBkaXJlY3RpdmVOYW1lLCBkaXJlY3RpdmVBcmdzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3dXYXJuaW5nKHN0YXRlLCAndW5rbm93biBkb2N1bWVudCBkaXJlY3RpdmUgXCInICsgZGlyZWN0aXZlTmFtZSArICdcIicpO1xuICAgIH1cbiAgfVxuXG4gIHNraXBTZXBhcmF0aW9uU3BhY2Uoc3RhdGUsIHRydWUsIC0xKTtcblxuICBpZiAoc3RhdGUubGluZUluZGVudCA9PT0gMCAmJlxuICAgICAgc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbikgICAgID09PSAweDJELyogLSAqLyAmJlxuICAgICAgc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbiArIDEpID09PSAweDJELyogLSAqLyAmJlxuICAgICAgc3RhdGUuaW5wdXQuY2hhckNvZGVBdChzdGF0ZS5wb3NpdGlvbiArIDIpID09PSAweDJELyogLSAqLykge1xuICAgIHN0YXRlLnBvc2l0aW9uICs9IDM7XG4gICAgc2tpcFNlcGFyYXRpb25TcGFjZShzdGF0ZSwgdHJ1ZSwgLTEpO1xuXG4gIH0gZWxzZSBpZiAoaGFzRGlyZWN0aXZlcykge1xuICAgIHRocm93RXJyb3Ioc3RhdGUsICdkaXJlY3RpdmVzIGVuZCBtYXJrIGlzIGV4cGVjdGVkJyk7XG4gIH1cblxuICBjb21wb3NlTm9kZShzdGF0ZSwgc3RhdGUubGluZUluZGVudCAtIDEsIENPTlRFWFRfQkxPQ0tfT1VULCBmYWxzZSwgdHJ1ZSk7XG4gIHNraXBTZXBhcmF0aW9uU3BhY2Uoc3RhdGUsIHRydWUsIC0xKTtcblxuICBpZiAoc3RhdGUuY2hlY2tMaW5lQnJlYWtzICYmXG4gICAgICBQQVRURVJOX05PTl9BU0NJSV9MSU5FX0JSRUFLUy50ZXN0KHN0YXRlLmlucHV0LnNsaWNlKGRvY3VtZW50U3RhcnQsIHN0YXRlLnBvc2l0aW9uKSkpIHtcbiAgICB0aHJvd1dhcm5pbmcoc3RhdGUsICdub24tQVNDSUkgbGluZSBicmVha3MgYXJlIGludGVycHJldGVkIGFzIGNvbnRlbnQnKTtcbiAgfVxuXG4gIHN0YXRlLmRvY3VtZW50cy5wdXNoKHN0YXRlLnJlc3VsdCk7XG5cbiAgaWYgKHN0YXRlLnBvc2l0aW9uID09PSBzdGF0ZS5saW5lU3RhcnQgJiYgdGVzdERvY3VtZW50U2VwYXJhdG9yKHN0YXRlKSkge1xuXG4gICAgaWYgKHN0YXRlLmlucHV0LmNoYXJDb2RlQXQoc3RhdGUucG9zaXRpb24pID09PSAweDJFLyogLiAqLykge1xuICAgICAgc3RhdGUucG9zaXRpb24gKz0gMztcbiAgICAgIHNraXBTZXBhcmF0aW9uU3BhY2Uoc3RhdGUsIHRydWUsIC0xKTtcbiAgICB9XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKHN0YXRlLnBvc2l0aW9uIDwgKHN0YXRlLmxlbmd0aCAtIDEpKSB7XG4gICAgdGhyb3dFcnJvcihzdGF0ZSwgJ2VuZCBvZiB0aGUgc3RyZWFtIG9yIGEgZG9jdW1lbnQgc2VwYXJhdG9yIGlzIGV4cGVjdGVkJyk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuO1xuICB9XG59XG5cblxuZnVuY3Rpb24gbG9hZERvY3VtZW50cyhpbnB1dCwgb3B0aW9ucykge1xuICBpbnB1dCA9IFN0cmluZyhpbnB1dCk7XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIGlmIChpbnB1dC5sZW5ndGggIT09IDApIHtcblxuICAgIC8vIEFkZCB0YWlsaW5nIGBcXG5gIGlmIG5vdCBleGlzdHNcbiAgICBpZiAoaW5wdXQuY2hhckNvZGVBdChpbnB1dC5sZW5ndGggLSAxKSAhPT0gMHgwQS8qIExGICovICYmXG4gICAgICAgIGlucHV0LmNoYXJDb2RlQXQoaW5wdXQubGVuZ3RoIC0gMSkgIT09IDB4MEQvKiBDUiAqLykge1xuICAgICAgaW5wdXQgKz0gJ1xcbic7XG4gICAgfVxuXG4gICAgLy8gU3RyaXAgQk9NXG4gICAgaWYgKGlucHV0LmNoYXJDb2RlQXQoMCkgPT09IDB4RkVGRikge1xuICAgICAgaW5wdXQgPSBpbnB1dC5zbGljZSgxKTtcbiAgICB9XG4gIH1cblxuICB2YXIgc3RhdGUgPSBuZXcgU3RhdGUoaW5wdXQsIG9wdGlvbnMpO1xuXG4gIC8vIFVzZSAwIGFzIHN0cmluZyB0ZXJtaW5hdG9yLiBUaGF0IHNpZ25pZmljYW50bHkgc2ltcGxpZmllcyBib3VuZHMgY2hlY2suXG4gIHN0YXRlLmlucHV0ICs9ICdcXDAnO1xuXG4gIHdoaWxlIChzdGF0ZS5pbnB1dC5jaGFyQ29kZUF0KHN0YXRlLnBvc2l0aW9uKSA9PT0gMHgyMC8qIFNwYWNlICovKSB7XG4gICAgc3RhdGUubGluZUluZGVudCArPSAxO1xuICAgIHN0YXRlLnBvc2l0aW9uICs9IDE7XG4gIH1cblxuICB3aGlsZSAoc3RhdGUucG9zaXRpb24gPCAoc3RhdGUubGVuZ3RoIC0gMSkpIHtcbiAgICByZWFkRG9jdW1lbnQoc3RhdGUpO1xuICB9XG5cbiAgcmV0dXJuIHN0YXRlLmRvY3VtZW50cztcbn1cblxuXG5mdW5jdGlvbiBsb2FkQWxsKGlucHV0LCBpdGVyYXRvciwgb3B0aW9ucykge1xuICB2YXIgZG9jdW1lbnRzID0gbG9hZERvY3VtZW50cyhpbnB1dCwgb3B0aW9ucyksIGluZGV4LCBsZW5ndGg7XG5cbiAgZm9yIChpbmRleCA9IDAsIGxlbmd0aCA9IGRvY3VtZW50cy5sZW5ndGg7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgaXRlcmF0b3IoZG9jdW1lbnRzW2luZGV4XSk7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBsb2FkKGlucHV0LCBvcHRpb25zKSB7XG4gIHZhciBkb2N1bWVudHMgPSBsb2FkRG9jdW1lbnRzKGlucHV0LCBvcHRpb25zKTtcblxuICBpZiAoZG9jdW1lbnRzLmxlbmd0aCA9PT0gMCkge1xuICAgIC8qZXNsaW50LWRpc2FibGUgbm8tdW5kZWZpbmVkKi9cbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9IGVsc2UgaWYgKGRvY3VtZW50cy5sZW5ndGggPT09IDEpIHtcbiAgICByZXR1cm4gZG9jdW1lbnRzWzBdO1xuICB9XG4gIHRocm93IG5ldyBZQU1MRXhjZXB0aW9uKCdleHBlY3RlZCBhIHNpbmdsZSBkb2N1bWVudCBpbiB0aGUgc3RyZWFtLCBidXQgZm91bmQgbW9yZScpO1xufVxuXG5cbmZ1bmN0aW9uIHNhZmVMb2FkQWxsKGlucHV0LCBvdXRwdXQsIG9wdGlvbnMpIHtcbiAgbG9hZEFsbChpbnB1dCwgb3V0cHV0LCBjb21tb24uZXh0ZW5kKHsgc2NoZW1hOiBERUZBVUxUX1NBRkVfU0NIRU1BIH0sIG9wdGlvbnMpKTtcbn1cblxuXG5mdW5jdGlvbiBzYWZlTG9hZChpbnB1dCwgb3B0aW9ucykge1xuICByZXR1cm4gbG9hZChpbnB1dCwgY29tbW9uLmV4dGVuZCh7IHNjaGVtYTogREVGQVVMVF9TQUZFX1NDSEVNQSB9LCBvcHRpb25zKSk7XG59XG5cblxubW9kdWxlLmV4cG9ydHMubG9hZEFsbCAgICAgPSBsb2FkQWxsO1xubW9kdWxlLmV4cG9ydHMubG9hZCAgICAgICAgPSBsb2FkO1xubW9kdWxlLmV4cG9ydHMuc2FmZUxvYWRBbGwgPSBzYWZlTG9hZEFsbDtcbm1vZHVsZS5leHBvcnRzLnNhZmVMb2FkICAgID0gc2FmZUxvYWQ7XG4iLCIndXNlIHN0cmljdCc7XG5cblxudmFyIGNvbW1vbiA9IHJlcXVpcmUoJy4vY29tbW9uJyk7XG5cblxuZnVuY3Rpb24gTWFyayhuYW1lLCBidWZmZXIsIHBvc2l0aW9uLCBsaW5lLCBjb2x1bW4pIHtcbiAgdGhpcy5uYW1lICAgICA9IG5hbWU7XG4gIHRoaXMuYnVmZmVyICAgPSBidWZmZXI7XG4gIHRoaXMucG9zaXRpb24gPSBwb3NpdGlvbjtcbiAgdGhpcy5saW5lICAgICA9IGxpbmU7XG4gIHRoaXMuY29sdW1uICAgPSBjb2x1bW47XG59XG5cblxuTWFyay5wcm90b3R5cGUuZ2V0U25pcHBldCA9IGZ1bmN0aW9uIGdldFNuaXBwZXQoaW5kZW50LCBtYXhMZW5ndGgpIHtcbiAgdmFyIGhlYWQsIHN0YXJ0LCB0YWlsLCBlbmQsIHNuaXBwZXQ7XG5cbiAgaWYgKCF0aGlzLmJ1ZmZlcikgcmV0dXJuIG51bGw7XG5cbiAgaW5kZW50ID0gaW5kZW50IHx8IDQ7XG4gIG1heExlbmd0aCA9IG1heExlbmd0aCB8fCA3NTtcblxuICBoZWFkID0gJyc7XG4gIHN0YXJ0ID0gdGhpcy5wb3NpdGlvbjtcblxuICB3aGlsZSAoc3RhcnQgPiAwICYmICdcXHgwMFxcclxcblxceDg1XFx1MjAyOFxcdTIwMjknLmluZGV4T2YodGhpcy5idWZmZXIuY2hhckF0KHN0YXJ0IC0gMSkpID09PSAtMSkge1xuICAgIHN0YXJ0IC09IDE7XG4gICAgaWYgKHRoaXMucG9zaXRpb24gLSBzdGFydCA+IChtYXhMZW5ndGggLyAyIC0gMSkpIHtcbiAgICAgIGhlYWQgPSAnIC4uLiAnO1xuICAgICAgc3RhcnQgKz0gNTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHRhaWwgPSAnJztcbiAgZW5kID0gdGhpcy5wb3NpdGlvbjtcblxuICB3aGlsZSAoZW5kIDwgdGhpcy5idWZmZXIubGVuZ3RoICYmICdcXHgwMFxcclxcblxceDg1XFx1MjAyOFxcdTIwMjknLmluZGV4T2YodGhpcy5idWZmZXIuY2hhckF0KGVuZCkpID09PSAtMSkge1xuICAgIGVuZCArPSAxO1xuICAgIGlmIChlbmQgLSB0aGlzLnBvc2l0aW9uID4gKG1heExlbmd0aCAvIDIgLSAxKSkge1xuICAgICAgdGFpbCA9ICcgLi4uICc7XG4gICAgICBlbmQgLT0gNTtcbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHNuaXBwZXQgPSB0aGlzLmJ1ZmZlci5zbGljZShzdGFydCwgZW5kKTtcblxuICByZXR1cm4gY29tbW9uLnJlcGVhdCgnICcsIGluZGVudCkgKyBoZWFkICsgc25pcHBldCArIHRhaWwgKyAnXFxuJyArXG4gICAgICAgICBjb21tb24ucmVwZWF0KCcgJywgaW5kZW50ICsgdGhpcy5wb3NpdGlvbiAtIHN0YXJ0ICsgaGVhZC5sZW5ndGgpICsgJ14nO1xufTtcblxuXG5NYXJrLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKGNvbXBhY3QpIHtcbiAgdmFyIHNuaXBwZXQsIHdoZXJlID0gJyc7XG5cbiAgaWYgKHRoaXMubmFtZSkge1xuICAgIHdoZXJlICs9ICdpbiBcIicgKyB0aGlzLm5hbWUgKyAnXCIgJztcbiAgfVxuXG4gIHdoZXJlICs9ICdhdCBsaW5lICcgKyAodGhpcy5saW5lICsgMSkgKyAnLCBjb2x1bW4gJyArICh0aGlzLmNvbHVtbiArIDEpO1xuXG4gIGlmICghY29tcGFjdCkge1xuICAgIHNuaXBwZXQgPSB0aGlzLmdldFNuaXBwZXQoKTtcblxuICAgIGlmIChzbmlwcGV0KSB7XG4gICAgICB3aGVyZSArPSAnOlxcbicgKyBzbmlwcGV0O1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB3aGVyZTtcbn07XG5cblxubW9kdWxlLmV4cG9ydHMgPSBNYXJrO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKmVzbGludC1kaXNhYmxlIG1heC1sZW4qL1xuXG52YXIgY29tbW9uICAgICAgICA9IHJlcXVpcmUoJy4vY29tbW9uJyk7XG52YXIgWUFNTEV4Y2VwdGlvbiA9IHJlcXVpcmUoJy4vZXhjZXB0aW9uJyk7XG52YXIgVHlwZSAgICAgICAgICA9IHJlcXVpcmUoJy4vdHlwZScpO1xuXG5cbmZ1bmN0aW9uIGNvbXBpbGVMaXN0KHNjaGVtYSwgbmFtZSwgcmVzdWx0KSB7XG4gIHZhciBleGNsdWRlID0gW107XG5cbiAgc2NoZW1hLmluY2x1ZGUuZm9yRWFjaChmdW5jdGlvbiAoaW5jbHVkZWRTY2hlbWEpIHtcbiAgICByZXN1bHQgPSBjb21waWxlTGlzdChpbmNsdWRlZFNjaGVtYSwgbmFtZSwgcmVzdWx0KTtcbiAgfSk7XG5cbiAgc2NoZW1hW25hbWVdLmZvckVhY2goZnVuY3Rpb24gKGN1cnJlbnRUeXBlKSB7XG4gICAgcmVzdWx0LmZvckVhY2goZnVuY3Rpb24gKHByZXZpb3VzVHlwZSwgcHJldmlvdXNJbmRleCkge1xuICAgICAgaWYgKHByZXZpb3VzVHlwZS50YWcgPT09IGN1cnJlbnRUeXBlLnRhZykge1xuICAgICAgICBleGNsdWRlLnB1c2gocHJldmlvdXNJbmRleCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXN1bHQucHVzaChjdXJyZW50VHlwZSk7XG4gIH0pO1xuXG4gIHJldHVybiByZXN1bHQuZmlsdGVyKGZ1bmN0aW9uICh0eXBlLCBpbmRleCkge1xuICAgIHJldHVybiBleGNsdWRlLmluZGV4T2YoaW5kZXgpID09PSAtMTtcbiAgfSk7XG59XG5cblxuZnVuY3Rpb24gY29tcGlsZU1hcCgvKiBsaXN0cy4uLiAqLykge1xuICB2YXIgcmVzdWx0ID0ge30sIGluZGV4LCBsZW5ndGg7XG5cbiAgZnVuY3Rpb24gY29sbGVjdFR5cGUodHlwZSkge1xuICAgIHJlc3VsdFt0eXBlLnRhZ10gPSB0eXBlO1xuICB9XG5cbiAgZm9yIChpbmRleCA9IDAsIGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGg7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgYXJndW1lbnRzW2luZGV4XS5mb3JFYWNoKGNvbGxlY3RUeXBlKTtcbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cblxuZnVuY3Rpb24gU2NoZW1hKGRlZmluaXRpb24pIHtcbiAgdGhpcy5pbmNsdWRlICA9IGRlZmluaXRpb24uaW5jbHVkZSAgfHwgW107XG4gIHRoaXMuaW1wbGljaXQgPSBkZWZpbml0aW9uLmltcGxpY2l0IHx8IFtdO1xuICB0aGlzLmV4cGxpY2l0ID0gZGVmaW5pdGlvbi5leHBsaWNpdCB8fCBbXTtcblxuICB0aGlzLmltcGxpY2l0LmZvckVhY2goZnVuY3Rpb24gKHR5cGUpIHtcbiAgICBpZiAodHlwZS5sb2FkS2luZCAmJiB0eXBlLmxvYWRLaW5kICE9PSAnc2NhbGFyJykge1xuICAgICAgdGhyb3cgbmV3IFlBTUxFeGNlcHRpb24oJ1RoZXJlIGlzIGEgbm9uLXNjYWxhciB0eXBlIGluIHRoZSBpbXBsaWNpdCBsaXN0IG9mIGEgc2NoZW1hLiBJbXBsaWNpdCByZXNvbHZpbmcgb2Ygc3VjaCB0eXBlcyBpcyBub3Qgc3VwcG9ydGVkLicpO1xuICAgIH1cbiAgfSk7XG5cbiAgdGhpcy5jb21waWxlZEltcGxpY2l0ID0gY29tcGlsZUxpc3QodGhpcywgJ2ltcGxpY2l0JywgW10pO1xuICB0aGlzLmNvbXBpbGVkRXhwbGljaXQgPSBjb21waWxlTGlzdCh0aGlzLCAnZXhwbGljaXQnLCBbXSk7XG4gIHRoaXMuY29tcGlsZWRUeXBlTWFwICA9IGNvbXBpbGVNYXAodGhpcy5jb21waWxlZEltcGxpY2l0LCB0aGlzLmNvbXBpbGVkRXhwbGljaXQpO1xufVxuXG5cblNjaGVtYS5ERUZBVUxUID0gbnVsbDtcblxuXG5TY2hlbWEuY3JlYXRlID0gZnVuY3Rpb24gY3JlYXRlU2NoZW1hKCkge1xuICB2YXIgc2NoZW1hcywgdHlwZXM7XG5cbiAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgY2FzZSAxOlxuICAgICAgc2NoZW1hcyA9IFNjaGVtYS5ERUZBVUxUO1xuICAgICAgdHlwZXMgPSBhcmd1bWVudHNbMF07XG4gICAgICBicmVhaztcblxuICAgIGNhc2UgMjpcbiAgICAgIHNjaGVtYXMgPSBhcmd1bWVudHNbMF07XG4gICAgICB0eXBlcyA9IGFyZ3VtZW50c1sxXTtcbiAgICAgIGJyZWFrO1xuXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBZQU1MRXhjZXB0aW9uKCdXcm9uZyBudW1iZXIgb2YgYXJndW1lbnRzIGZvciBTY2hlbWEuY3JlYXRlIGZ1bmN0aW9uJyk7XG4gIH1cblxuICBzY2hlbWFzID0gY29tbW9uLnRvQXJyYXkoc2NoZW1hcyk7XG4gIHR5cGVzID0gY29tbW9uLnRvQXJyYXkodHlwZXMpO1xuXG4gIGlmICghc2NoZW1hcy5ldmVyeShmdW5jdGlvbiAoc2NoZW1hKSB7IHJldHVybiBzY2hlbWEgaW5zdGFuY2VvZiBTY2hlbWE7IH0pKSB7XG4gICAgdGhyb3cgbmV3IFlBTUxFeGNlcHRpb24oJ1NwZWNpZmllZCBsaXN0IG9mIHN1cGVyIHNjaGVtYXMgKG9yIGEgc2luZ2xlIFNjaGVtYSBvYmplY3QpIGNvbnRhaW5zIGEgbm9uLVNjaGVtYSBvYmplY3QuJyk7XG4gIH1cblxuICBpZiAoIXR5cGVzLmV2ZXJ5KGZ1bmN0aW9uICh0eXBlKSB7IHJldHVybiB0eXBlIGluc3RhbmNlb2YgVHlwZTsgfSkpIHtcbiAgICB0aHJvdyBuZXcgWUFNTEV4Y2VwdGlvbignU3BlY2lmaWVkIGxpc3Qgb2YgWUFNTCB0eXBlcyAob3IgYSBzaW5nbGUgVHlwZSBvYmplY3QpIGNvbnRhaW5zIGEgbm9uLVR5cGUgb2JqZWN0LicpO1xuICB9XG5cbiAgcmV0dXJuIG5ldyBTY2hlbWEoe1xuICAgIGluY2x1ZGU6IHNjaGVtYXMsXG4gICAgZXhwbGljaXQ6IHR5cGVzXG4gIH0pO1xufTtcblxuXG5tb2R1bGUuZXhwb3J0cyA9IFNjaGVtYTtcbiIsIi8vIFN0YW5kYXJkIFlBTUwncyBDb3JlIHNjaGVtYS5cbi8vIGh0dHA6Ly93d3cueWFtbC5vcmcvc3BlYy8xLjIvc3BlYy5odG1sI2lkMjgwNDkyM1xuLy9cbi8vIE5PVEU6IEpTLVlBTUwgZG9lcyBub3Qgc3VwcG9ydCBzY2hlbWEtc3BlY2lmaWMgdGFnIHJlc29sdXRpb24gcmVzdHJpY3Rpb25zLlxuLy8gU28sIENvcmUgc2NoZW1hIGhhcyBubyBkaXN0aW5jdGlvbnMgZnJvbSBKU09OIHNjaGVtYSBpcyBKUy1ZQU1MLlxuXG5cbid1c2Ugc3RyaWN0JztcblxuXG52YXIgU2NoZW1hID0gcmVxdWlyZSgnLi4vc2NoZW1hJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBuZXcgU2NoZW1hKHtcbiAgaW5jbHVkZTogW1xuICAgIHJlcXVpcmUoJy4vanNvbicpXG4gIF1cbn0pO1xuIiwiLy8gSlMtWUFNTCdzIGRlZmF1bHQgc2NoZW1hIGZvciBgbG9hZGAgZnVuY3Rpb24uXG4vLyBJdCBpcyBub3QgZGVzY3JpYmVkIGluIHRoZSBZQU1MIHNwZWNpZmljYXRpb24uXG4vL1xuLy8gVGhpcyBzY2hlbWEgaXMgYmFzZWQgb24gSlMtWUFNTCdzIGRlZmF1bHQgc2FmZSBzY2hlbWEgYW5kIGluY2x1ZGVzXG4vLyBKYXZhU2NyaXB0LXNwZWNpZmljIHR5cGVzOiAhIWpzL3VuZGVmaW5lZCwgISFqcy9yZWdleHAgYW5kICEhanMvZnVuY3Rpb24uXG4vL1xuLy8gQWxzbyB0aGlzIHNjaGVtYSBpcyB1c2VkIGFzIGRlZmF1bHQgYmFzZSBzY2hlbWEgYXQgYFNjaGVtYS5jcmVhdGVgIGZ1bmN0aW9uLlxuXG5cbid1c2Ugc3RyaWN0JztcblxuXG52YXIgU2NoZW1hID0gcmVxdWlyZSgnLi4vc2NoZW1hJyk7XG5cblxubW9kdWxlLmV4cG9ydHMgPSBTY2hlbWEuREVGQVVMVCA9IG5ldyBTY2hlbWEoe1xuICBpbmNsdWRlOiBbXG4gICAgcmVxdWlyZSgnLi9kZWZhdWx0X3NhZmUnKVxuICBdLFxuICBleHBsaWNpdDogW1xuICAgIHJlcXVpcmUoJy4uL3R5cGUvanMvdW5kZWZpbmVkJyksXG4gICAgcmVxdWlyZSgnLi4vdHlwZS9qcy9yZWdleHAnKSxcbiAgICByZXF1aXJlKCcuLi90eXBlL2pzL2Z1bmN0aW9uJylcbiAgXVxufSk7XG4iLCIvLyBKUy1ZQU1MJ3MgZGVmYXVsdCBzY2hlbWEgZm9yIGBzYWZlTG9hZGAgZnVuY3Rpb24uXG4vLyBJdCBpcyBub3QgZGVzY3JpYmVkIGluIHRoZSBZQU1MIHNwZWNpZmljYXRpb24uXG4vL1xuLy8gVGhpcyBzY2hlbWEgaXMgYmFzZWQgb24gc3RhbmRhcmQgWUFNTCdzIENvcmUgc2NoZW1hIGFuZCBpbmNsdWRlcyBtb3N0IG9mXG4vLyBleHRyYSB0eXBlcyBkZXNjcmliZWQgYXQgWUFNTCB0YWcgcmVwb3NpdG9yeS4gKGh0dHA6Ly95YW1sLm9yZy90eXBlLylcblxuXG4ndXNlIHN0cmljdCc7XG5cblxudmFyIFNjaGVtYSA9IHJlcXVpcmUoJy4uL3NjaGVtYScpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFNjaGVtYSh7XG4gIGluY2x1ZGU6IFtcbiAgICByZXF1aXJlKCcuL2NvcmUnKVxuICBdLFxuICBpbXBsaWNpdDogW1xuICAgIHJlcXVpcmUoJy4uL3R5cGUvdGltZXN0YW1wJyksXG4gICAgcmVxdWlyZSgnLi4vdHlwZS9tZXJnZScpXG4gIF0sXG4gIGV4cGxpY2l0OiBbXG4gICAgcmVxdWlyZSgnLi4vdHlwZS9iaW5hcnknKSxcbiAgICByZXF1aXJlKCcuLi90eXBlL29tYXAnKSxcbiAgICByZXF1aXJlKCcuLi90eXBlL3BhaXJzJyksXG4gICAgcmVxdWlyZSgnLi4vdHlwZS9zZXQnKVxuICBdXG59KTtcbiIsIi8vIFN0YW5kYXJkIFlBTUwncyBGYWlsc2FmZSBzY2hlbWEuXG4vLyBodHRwOi8vd3d3LnlhbWwub3JnL3NwZWMvMS4yL3NwZWMuaHRtbCNpZDI4MDIzNDZcblxuXG4ndXNlIHN0cmljdCc7XG5cblxudmFyIFNjaGVtYSA9IHJlcXVpcmUoJy4uL3NjaGVtYScpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFNjaGVtYSh7XG4gIGV4cGxpY2l0OiBbXG4gICAgcmVxdWlyZSgnLi4vdHlwZS9zdHInKSxcbiAgICByZXF1aXJlKCcuLi90eXBlL3NlcScpLFxuICAgIHJlcXVpcmUoJy4uL3R5cGUvbWFwJylcbiAgXVxufSk7XG4iLCIvLyBTdGFuZGFyZCBZQU1MJ3MgSlNPTiBzY2hlbWEuXG4vLyBodHRwOi8vd3d3LnlhbWwub3JnL3NwZWMvMS4yL3NwZWMuaHRtbCNpZDI4MDMyMzFcbi8vXG4vLyBOT1RFOiBKUy1ZQU1MIGRvZXMgbm90IHN1cHBvcnQgc2NoZW1hLXNwZWNpZmljIHRhZyByZXNvbHV0aW9uIHJlc3RyaWN0aW9ucy5cbi8vIFNvLCB0aGlzIHNjaGVtYSBpcyBub3Qgc3VjaCBzdHJpY3QgYXMgZGVmaW5lZCBpbiB0aGUgWUFNTCBzcGVjaWZpY2F0aW9uLlxuLy8gSXQgYWxsb3dzIG51bWJlcnMgaW4gYmluYXJ5IG5vdGFpb24sIHVzZSBgTnVsbGAgYW5kIGBOVUxMYCBhcyBgbnVsbGAsIGV0Yy5cblxuXG4ndXNlIHN0cmljdCc7XG5cblxudmFyIFNjaGVtYSA9IHJlcXVpcmUoJy4uL3NjaGVtYScpO1xuXG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFNjaGVtYSh7XG4gIGluY2x1ZGU6IFtcbiAgICByZXF1aXJlKCcuL2ZhaWxzYWZlJylcbiAgXSxcbiAgaW1wbGljaXQ6IFtcbiAgICByZXF1aXJlKCcuLi90eXBlL251bGwnKSxcbiAgICByZXF1aXJlKCcuLi90eXBlL2Jvb2wnKSxcbiAgICByZXF1aXJlKCcuLi90eXBlL2ludCcpLFxuICAgIHJlcXVpcmUoJy4uL3R5cGUvZmxvYXQnKVxuICBdXG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFlBTUxFeGNlcHRpb24gPSByZXF1aXJlKCcuL2V4Y2VwdGlvbicpO1xuXG52YXIgVFlQRV9DT05TVFJVQ1RPUl9PUFRJT05TID0gW1xuICAna2luZCcsXG4gICdyZXNvbHZlJyxcbiAgJ2NvbnN0cnVjdCcsXG4gICdpbnN0YW5jZU9mJyxcbiAgJ3ByZWRpY2F0ZScsXG4gICdyZXByZXNlbnQnLFxuICAnZGVmYXVsdFN0eWxlJyxcbiAgJ3N0eWxlQWxpYXNlcydcbl07XG5cbnZhciBZQU1MX05PREVfS0lORFMgPSBbXG4gICdzY2FsYXInLFxuICAnc2VxdWVuY2UnLFxuICAnbWFwcGluZydcbl07XG5cbmZ1bmN0aW9uIGNvbXBpbGVTdHlsZUFsaWFzZXMobWFwKSB7XG4gIHZhciByZXN1bHQgPSB7fTtcblxuICBpZiAobWFwICE9PSBudWxsKSB7XG4gICAgT2JqZWN0LmtleXMobWFwKS5mb3JFYWNoKGZ1bmN0aW9uIChzdHlsZSkge1xuICAgICAgbWFwW3N0eWxlXS5mb3JFYWNoKGZ1bmN0aW9uIChhbGlhcykge1xuICAgICAgICByZXN1bHRbU3RyaW5nKGFsaWFzKV0gPSBzdHlsZTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gVHlwZSh0YWcsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgT2JqZWN0LmtleXMob3B0aW9ucykuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgIGlmIChUWVBFX0NPTlNUUlVDVE9SX09QVElPTlMuaW5kZXhPZihuYW1lKSA9PT0gLTEpIHtcbiAgICAgIHRocm93IG5ldyBZQU1MRXhjZXB0aW9uKCdVbmtub3duIG9wdGlvbiBcIicgKyBuYW1lICsgJ1wiIGlzIG1ldCBpbiBkZWZpbml0aW9uIG9mIFwiJyArIHRhZyArICdcIiBZQU1MIHR5cGUuJyk7XG4gICAgfVxuICB9KTtcblxuICAvLyBUT0RPOiBBZGQgdGFnIGZvcm1hdCBjaGVjay5cbiAgdGhpcy50YWcgICAgICAgICAgPSB0YWc7XG4gIHRoaXMua2luZCAgICAgICAgID0gb3B0aW9uc1sna2luZCddICAgICAgICAgfHwgbnVsbDtcbiAgdGhpcy5yZXNvbHZlICAgICAgPSBvcHRpb25zWydyZXNvbHZlJ10gICAgICB8fCBmdW5jdGlvbiAoKSB7IHJldHVybiB0cnVlOyB9O1xuICB0aGlzLmNvbnN0cnVjdCAgICA9IG9wdGlvbnNbJ2NvbnN0cnVjdCddICAgIHx8IGZ1bmN0aW9uIChkYXRhKSB7IHJldHVybiBkYXRhOyB9O1xuICB0aGlzLmluc3RhbmNlT2YgICA9IG9wdGlvbnNbJ2luc3RhbmNlT2YnXSAgIHx8IG51bGw7XG4gIHRoaXMucHJlZGljYXRlICAgID0gb3B0aW9uc1sncHJlZGljYXRlJ10gICAgfHwgbnVsbDtcbiAgdGhpcy5yZXByZXNlbnQgICAgPSBvcHRpb25zWydyZXByZXNlbnQnXSAgICB8fCBudWxsO1xuICB0aGlzLmRlZmF1bHRTdHlsZSA9IG9wdGlvbnNbJ2RlZmF1bHRTdHlsZSddIHx8IG51bGw7XG4gIHRoaXMuc3R5bGVBbGlhc2VzID0gY29tcGlsZVN0eWxlQWxpYXNlcyhvcHRpb25zWydzdHlsZUFsaWFzZXMnXSB8fCBudWxsKTtcblxuICBpZiAoWUFNTF9OT0RFX0tJTkRTLmluZGV4T2YodGhpcy5raW5kKSA9PT0gLTEpIHtcbiAgICB0aHJvdyBuZXcgWUFNTEV4Y2VwdGlvbignVW5rbm93biBraW5kIFwiJyArIHRoaXMua2luZCArICdcIiBpcyBzcGVjaWZpZWQgZm9yIFwiJyArIHRhZyArICdcIiBZQU1MIHR5cGUuJyk7XG4gIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBUeXBlO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKmVzbGludC1kaXNhYmxlIG5vLWJpdHdpc2UqL1xuXG52YXIgTm9kZUJ1ZmZlcjtcblxudHJ5IHtcbiAgLy8gQSB0cmljayBmb3IgYnJvd3NlcmlmaWVkIHZlcnNpb24sIHRvIG5vdCBpbmNsdWRlIGBCdWZmZXJgIHNoaW1cbiAgdmFyIF9yZXF1aXJlID0gcmVxdWlyZTtcbiAgTm9kZUJ1ZmZlciA9IF9yZXF1aXJlKCdidWZmZXInKS5CdWZmZXI7XG59IGNhdGNoIChfXykge31cblxudmFyIFR5cGUgICAgICAgPSByZXF1aXJlKCcuLi90eXBlJyk7XG5cblxuLy8gWyA2NCwgNjUsIDY2IF0gLT4gWyBwYWRkaW5nLCBDUiwgTEYgXVxudmFyIEJBU0U2NF9NQVAgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLz1cXG5cXHInO1xuXG5cbmZ1bmN0aW9uIHJlc29sdmVZYW1sQmluYXJ5KGRhdGEpIHtcbiAgaWYgKGRhdGEgPT09IG51bGwpIHJldHVybiBmYWxzZTtcblxuICB2YXIgY29kZSwgaWR4LCBiaXRsZW4gPSAwLCBtYXggPSBkYXRhLmxlbmd0aCwgbWFwID0gQkFTRTY0X01BUDtcblxuICAvLyBDb252ZXJ0IG9uZSBieSBvbmUuXG4gIGZvciAoaWR4ID0gMDsgaWR4IDwgbWF4OyBpZHgrKykge1xuICAgIGNvZGUgPSBtYXAuaW5kZXhPZihkYXRhLmNoYXJBdChpZHgpKTtcblxuICAgIC8vIFNraXAgQ1IvTEZcbiAgICBpZiAoY29kZSA+IDY0KSBjb250aW51ZTtcblxuICAgIC8vIEZhaWwgb24gaWxsZWdhbCBjaGFyYWN0ZXJzXG4gICAgaWYgKGNvZGUgPCAwKSByZXR1cm4gZmFsc2U7XG5cbiAgICBiaXRsZW4gKz0gNjtcbiAgfVxuXG4gIC8vIElmIHRoZXJlIGFyZSBhbnkgYml0cyBsZWZ0LCBzb3VyY2Ugd2FzIGNvcnJ1cHRlZFxuICByZXR1cm4gKGJpdGxlbiAlIDgpID09PSAwO1xufVxuXG5mdW5jdGlvbiBjb25zdHJ1Y3RZYW1sQmluYXJ5KGRhdGEpIHtcbiAgdmFyIGlkeCwgdGFpbGJpdHMsXG4gICAgICBpbnB1dCA9IGRhdGEucmVwbGFjZSgvW1xcclxcbj1dL2csICcnKSwgLy8gcmVtb3ZlIENSL0xGICYgcGFkZGluZyB0byBzaW1wbGlmeSBzY2FuXG4gICAgICBtYXggPSBpbnB1dC5sZW5ndGgsXG4gICAgICBtYXAgPSBCQVNFNjRfTUFQLFxuICAgICAgYml0cyA9IDAsXG4gICAgICByZXN1bHQgPSBbXTtcblxuICAvLyBDb2xsZWN0IGJ5IDYqNCBiaXRzICgzIGJ5dGVzKVxuXG4gIGZvciAoaWR4ID0gMDsgaWR4IDwgbWF4OyBpZHgrKykge1xuICAgIGlmICgoaWR4ICUgNCA9PT0gMCkgJiYgaWR4KSB7XG4gICAgICByZXN1bHQucHVzaCgoYml0cyA+PiAxNikgJiAweEZGKTtcbiAgICAgIHJlc3VsdC5wdXNoKChiaXRzID4+IDgpICYgMHhGRik7XG4gICAgICByZXN1bHQucHVzaChiaXRzICYgMHhGRik7XG4gICAgfVxuXG4gICAgYml0cyA9IChiaXRzIDw8IDYpIHwgbWFwLmluZGV4T2YoaW5wdXQuY2hhckF0KGlkeCkpO1xuICB9XG5cbiAgLy8gRHVtcCB0YWlsXG5cbiAgdGFpbGJpdHMgPSAobWF4ICUgNCkgKiA2O1xuXG4gIGlmICh0YWlsYml0cyA9PT0gMCkge1xuICAgIHJlc3VsdC5wdXNoKChiaXRzID4+IDE2KSAmIDB4RkYpO1xuICAgIHJlc3VsdC5wdXNoKChiaXRzID4+IDgpICYgMHhGRik7XG4gICAgcmVzdWx0LnB1c2goYml0cyAmIDB4RkYpO1xuICB9IGVsc2UgaWYgKHRhaWxiaXRzID09PSAxOCkge1xuICAgIHJlc3VsdC5wdXNoKChiaXRzID4+IDEwKSAmIDB4RkYpO1xuICAgIHJlc3VsdC5wdXNoKChiaXRzID4+IDIpICYgMHhGRik7XG4gIH0gZWxzZSBpZiAodGFpbGJpdHMgPT09IDEyKSB7XG4gICAgcmVzdWx0LnB1c2goKGJpdHMgPj4gNCkgJiAweEZGKTtcbiAgfVxuXG4gIC8vIFdyYXAgaW50byBCdWZmZXIgZm9yIE5vZGVKUyBhbmQgbGVhdmUgQXJyYXkgZm9yIGJyb3dzZXJcbiAgaWYgKE5vZGVCdWZmZXIpIHJldHVybiBuZXcgTm9kZUJ1ZmZlcihyZXN1bHQpO1xuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIHJlcHJlc2VudFlhbWxCaW5hcnkob2JqZWN0IC8qLCBzdHlsZSovKSB7XG4gIHZhciByZXN1bHQgPSAnJywgYml0cyA9IDAsIGlkeCwgdGFpbCxcbiAgICAgIG1heCA9IG9iamVjdC5sZW5ndGgsXG4gICAgICBtYXAgPSBCQVNFNjRfTUFQO1xuXG4gIC8vIENvbnZlcnQgZXZlcnkgdGhyZWUgYnl0ZXMgdG8gNCBBU0NJSSBjaGFyYWN0ZXJzLlxuXG4gIGZvciAoaWR4ID0gMDsgaWR4IDwgbWF4OyBpZHgrKykge1xuICAgIGlmICgoaWR4ICUgMyA9PT0gMCkgJiYgaWR4KSB7XG4gICAgICByZXN1bHQgKz0gbWFwWyhiaXRzID4+IDE4KSAmIDB4M0ZdO1xuICAgICAgcmVzdWx0ICs9IG1hcFsoYml0cyA+PiAxMikgJiAweDNGXTtcbiAgICAgIHJlc3VsdCArPSBtYXBbKGJpdHMgPj4gNikgJiAweDNGXTtcbiAgICAgIHJlc3VsdCArPSBtYXBbYml0cyAmIDB4M0ZdO1xuICAgIH1cblxuICAgIGJpdHMgPSAoYml0cyA8PCA4KSArIG9iamVjdFtpZHhdO1xuICB9XG5cbiAgLy8gRHVtcCB0YWlsXG5cbiAgdGFpbCA9IG1heCAlIDM7XG5cbiAgaWYgKHRhaWwgPT09IDApIHtcbiAgICByZXN1bHQgKz0gbWFwWyhiaXRzID4+IDE4KSAmIDB4M0ZdO1xuICAgIHJlc3VsdCArPSBtYXBbKGJpdHMgPj4gMTIpICYgMHgzRl07XG4gICAgcmVzdWx0ICs9IG1hcFsoYml0cyA+PiA2KSAmIDB4M0ZdO1xuICAgIHJlc3VsdCArPSBtYXBbYml0cyAmIDB4M0ZdO1xuICB9IGVsc2UgaWYgKHRhaWwgPT09IDIpIHtcbiAgICByZXN1bHQgKz0gbWFwWyhiaXRzID4+IDEwKSAmIDB4M0ZdO1xuICAgIHJlc3VsdCArPSBtYXBbKGJpdHMgPj4gNCkgJiAweDNGXTtcbiAgICByZXN1bHQgKz0gbWFwWyhiaXRzIDw8IDIpICYgMHgzRl07XG4gICAgcmVzdWx0ICs9IG1hcFs2NF07XG4gIH0gZWxzZSBpZiAodGFpbCA9PT0gMSkge1xuICAgIHJlc3VsdCArPSBtYXBbKGJpdHMgPj4gMikgJiAweDNGXTtcbiAgICByZXN1bHQgKz0gbWFwWyhiaXRzIDw8IDQpICYgMHgzRl07XG4gICAgcmVzdWx0ICs9IG1hcFs2NF07XG4gICAgcmVzdWx0ICs9IG1hcFs2NF07XG4gIH1cblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBpc0JpbmFyeShvYmplY3QpIHtcbiAgcmV0dXJuIE5vZGVCdWZmZXIgJiYgTm9kZUJ1ZmZlci5pc0J1ZmZlcihvYmplY3QpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBUeXBlKCd0YWc6eWFtbC5vcmcsMjAwMjpiaW5hcnknLCB7XG4gIGtpbmQ6ICdzY2FsYXInLFxuICByZXNvbHZlOiByZXNvbHZlWWFtbEJpbmFyeSxcbiAgY29uc3RydWN0OiBjb25zdHJ1Y3RZYW1sQmluYXJ5LFxuICBwcmVkaWNhdGU6IGlzQmluYXJ5LFxuICByZXByZXNlbnQ6IHJlcHJlc2VudFlhbWxCaW5hcnlcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgVHlwZSA9IHJlcXVpcmUoJy4uL3R5cGUnKTtcblxuZnVuY3Rpb24gcmVzb2x2ZVlhbWxCb29sZWFuKGRhdGEpIHtcbiAgaWYgKGRhdGEgPT09IG51bGwpIHJldHVybiBmYWxzZTtcblxuICB2YXIgbWF4ID0gZGF0YS5sZW5ndGg7XG5cbiAgcmV0dXJuIChtYXggPT09IDQgJiYgKGRhdGEgPT09ICd0cnVlJyB8fCBkYXRhID09PSAnVHJ1ZScgfHwgZGF0YSA9PT0gJ1RSVUUnKSkgfHxcbiAgICAgICAgIChtYXggPT09IDUgJiYgKGRhdGEgPT09ICdmYWxzZScgfHwgZGF0YSA9PT0gJ0ZhbHNlJyB8fCBkYXRhID09PSAnRkFMU0UnKSk7XG59XG5cbmZ1bmN0aW9uIGNvbnN0cnVjdFlhbWxCb29sZWFuKGRhdGEpIHtcbiAgcmV0dXJuIGRhdGEgPT09ICd0cnVlJyB8fFxuICAgICAgICAgZGF0YSA9PT0gJ1RydWUnIHx8XG4gICAgICAgICBkYXRhID09PSAnVFJVRSc7XG59XG5cbmZ1bmN0aW9uIGlzQm9vbGVhbihvYmplY3QpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmplY3QpID09PSAnW29iamVjdCBCb29sZWFuXSc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFR5cGUoJ3RhZzp5YW1sLm9yZywyMDAyOmJvb2wnLCB7XG4gIGtpbmQ6ICdzY2FsYXInLFxuICByZXNvbHZlOiByZXNvbHZlWWFtbEJvb2xlYW4sXG4gIGNvbnN0cnVjdDogY29uc3RydWN0WWFtbEJvb2xlYW4sXG4gIHByZWRpY2F0ZTogaXNCb29sZWFuLFxuICByZXByZXNlbnQ6IHtcbiAgICBsb3dlcmNhc2U6IGZ1bmN0aW9uIChvYmplY3QpIHsgcmV0dXJuIG9iamVjdCA/ICd0cnVlJyA6ICdmYWxzZSc7IH0sXG4gICAgdXBwZXJjYXNlOiBmdW5jdGlvbiAob2JqZWN0KSB7IHJldHVybiBvYmplY3QgPyAnVFJVRScgOiAnRkFMU0UnOyB9LFxuICAgIGNhbWVsY2FzZTogZnVuY3Rpb24gKG9iamVjdCkgeyByZXR1cm4gb2JqZWN0ID8gJ1RydWUnIDogJ0ZhbHNlJzsgfVxuICB9LFxuICBkZWZhdWx0U3R5bGU6ICdsb3dlcmNhc2UnXG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGNvbW1vbiA9IHJlcXVpcmUoJy4uL2NvbW1vbicpO1xudmFyIFR5cGUgICA9IHJlcXVpcmUoJy4uL3R5cGUnKTtcblxudmFyIFlBTUxfRkxPQVRfUEFUVEVSTiA9IG5ldyBSZWdFeHAoXG4gICdeKD86Wy0rXT8oPzpbMC05XVswLTlfXSopXFxcXC5bMC05X10qKD86W2VFXVstK11bMC05XSspPycgK1xuICAnfFxcXFwuWzAtOV9dKyg/OltlRV1bLStdWzAtOV0rKT8nICtcbiAgJ3xbLStdP1swLTldWzAtOV9dKig/OjpbMC01XT9bMC05XSkrXFxcXC5bMC05X10qJyArXG4gICd8Wy0rXT9cXFxcLig/OmluZnxJbmZ8SU5GKScgK1xuICAnfFxcXFwuKD86bmFufE5hTnxOQU4pKSQnKTtcblxuZnVuY3Rpb24gcmVzb2x2ZVlhbWxGbG9hdChkYXRhKSB7XG4gIGlmIChkYXRhID09PSBudWxsKSByZXR1cm4gZmFsc2U7XG5cbiAgaWYgKCFZQU1MX0ZMT0FUX1BBVFRFUk4udGVzdChkYXRhKSkgcmV0dXJuIGZhbHNlO1xuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBjb25zdHJ1Y3RZYW1sRmxvYXQoZGF0YSkge1xuICB2YXIgdmFsdWUsIHNpZ24sIGJhc2UsIGRpZ2l0cztcblxuICB2YWx1ZSAgPSBkYXRhLnJlcGxhY2UoL18vZywgJycpLnRvTG93ZXJDYXNlKCk7XG4gIHNpZ24gICA9IHZhbHVlWzBdID09PSAnLScgPyAtMSA6IDE7XG4gIGRpZ2l0cyA9IFtdO1xuXG4gIGlmICgnKy0nLmluZGV4T2YodmFsdWVbMF0pID49IDApIHtcbiAgICB2YWx1ZSA9IHZhbHVlLnNsaWNlKDEpO1xuICB9XG5cbiAgaWYgKHZhbHVlID09PSAnLmluZicpIHtcbiAgICByZXR1cm4gKHNpZ24gPT09IDEpID8gTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZIDogTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZO1xuXG4gIH0gZWxzZSBpZiAodmFsdWUgPT09ICcubmFuJykge1xuICAgIHJldHVybiBOYU47XG5cbiAgfSBlbHNlIGlmICh2YWx1ZS5pbmRleE9mKCc6JykgPj0gMCkge1xuICAgIHZhbHVlLnNwbGl0KCc6JykuZm9yRWFjaChmdW5jdGlvbiAodikge1xuICAgICAgZGlnaXRzLnVuc2hpZnQocGFyc2VGbG9hdCh2LCAxMCkpO1xuICAgIH0pO1xuXG4gICAgdmFsdWUgPSAwLjA7XG4gICAgYmFzZSA9IDE7XG5cbiAgICBkaWdpdHMuZm9yRWFjaChmdW5jdGlvbiAoZCkge1xuICAgICAgdmFsdWUgKz0gZCAqIGJhc2U7XG4gICAgICBiYXNlICo9IDYwO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHNpZ24gKiB2YWx1ZTtcblxuICB9XG4gIHJldHVybiBzaWduICogcGFyc2VGbG9hdCh2YWx1ZSwgMTApO1xufVxuXG5cbnZhciBTQ0lFTlRJRklDX1dJVEhPVVRfRE9UID0gL15bLStdP1swLTldK2UvO1xuXG5mdW5jdGlvbiByZXByZXNlbnRZYW1sRmxvYXQob2JqZWN0LCBzdHlsZSkge1xuICB2YXIgcmVzO1xuXG4gIGlmIChpc05hTihvYmplY3QpKSB7XG4gICAgc3dpdGNoIChzdHlsZSkge1xuICAgICAgY2FzZSAnbG93ZXJjYXNlJzogcmV0dXJuICcubmFuJztcbiAgICAgIGNhc2UgJ3VwcGVyY2FzZSc6IHJldHVybiAnLk5BTic7XG4gICAgICBjYXNlICdjYW1lbGNhc2UnOiByZXR1cm4gJy5OYU4nO1xuICAgIH1cbiAgfSBlbHNlIGlmIChOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFkgPT09IG9iamVjdCkge1xuICAgIHN3aXRjaCAoc3R5bGUpIHtcbiAgICAgIGNhc2UgJ2xvd2VyY2FzZSc6IHJldHVybiAnLmluZic7XG4gICAgICBjYXNlICd1cHBlcmNhc2UnOiByZXR1cm4gJy5JTkYnO1xuICAgICAgY2FzZSAnY2FtZWxjYXNlJzogcmV0dXJuICcuSW5mJztcbiAgICB9XG4gIH0gZWxzZSBpZiAoTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZID09PSBvYmplY3QpIHtcbiAgICBzd2l0Y2ggKHN0eWxlKSB7XG4gICAgICBjYXNlICdsb3dlcmNhc2UnOiByZXR1cm4gJy0uaW5mJztcbiAgICAgIGNhc2UgJ3VwcGVyY2FzZSc6IHJldHVybiAnLS5JTkYnO1xuICAgICAgY2FzZSAnY2FtZWxjYXNlJzogcmV0dXJuICctLkluZic7XG4gICAgfVxuICB9IGVsc2UgaWYgKGNvbW1vbi5pc05lZ2F0aXZlWmVybyhvYmplY3QpKSB7XG4gICAgcmV0dXJuICctMC4wJztcbiAgfVxuXG4gIHJlcyA9IG9iamVjdC50b1N0cmluZygxMCk7XG5cbiAgLy8gSlMgc3RyaW5naWZpZXIgY2FuIGJ1aWxkIHNjaWVudGlmaWMgZm9ybWF0IHdpdGhvdXQgZG90czogNWUtMTAwLFxuICAvLyB3aGlsZSBZQU1MIHJlcXVyZXMgZG90OiA1LmUtMTAwLiBGaXggaXQgd2l0aCBzaW1wbGUgaGFja1xuXG4gIHJldHVybiBTQ0lFTlRJRklDX1dJVEhPVVRfRE9ULnRlc3QocmVzKSA/IHJlcy5yZXBsYWNlKCdlJywgJy5lJykgOiByZXM7XG59XG5cbmZ1bmN0aW9uIGlzRmxvYXQob2JqZWN0KSB7XG4gIHJldHVybiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iamVjdCkgPT09ICdbb2JqZWN0IE51bWJlcl0nKSAmJlxuICAgICAgICAgKG9iamVjdCAlIDEgIT09IDAgfHwgY29tbW9uLmlzTmVnYXRpdmVaZXJvKG9iamVjdCkpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBUeXBlKCd0YWc6eWFtbC5vcmcsMjAwMjpmbG9hdCcsIHtcbiAga2luZDogJ3NjYWxhcicsXG4gIHJlc29sdmU6IHJlc29sdmVZYW1sRmxvYXQsXG4gIGNvbnN0cnVjdDogY29uc3RydWN0WWFtbEZsb2F0LFxuICBwcmVkaWNhdGU6IGlzRmxvYXQsXG4gIHJlcHJlc2VudDogcmVwcmVzZW50WWFtbEZsb2F0LFxuICBkZWZhdWx0U3R5bGU6ICdsb3dlcmNhc2UnXG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIGNvbW1vbiA9IHJlcXVpcmUoJy4uL2NvbW1vbicpO1xudmFyIFR5cGUgICA9IHJlcXVpcmUoJy4uL3R5cGUnKTtcblxuZnVuY3Rpb24gaXNIZXhDb2RlKGMpIHtcbiAgcmV0dXJuICgoMHgzMC8qIDAgKi8gPD0gYykgJiYgKGMgPD0gMHgzOS8qIDkgKi8pKSB8fFxuICAgICAgICAgKCgweDQxLyogQSAqLyA8PSBjKSAmJiAoYyA8PSAweDQ2LyogRiAqLykpIHx8XG4gICAgICAgICAoKDB4NjEvKiBhICovIDw9IGMpICYmIChjIDw9IDB4NjYvKiBmICovKSk7XG59XG5cbmZ1bmN0aW9uIGlzT2N0Q29kZShjKSB7XG4gIHJldHVybiAoKDB4MzAvKiAwICovIDw9IGMpICYmIChjIDw9IDB4MzcvKiA3ICovKSk7XG59XG5cbmZ1bmN0aW9uIGlzRGVjQ29kZShjKSB7XG4gIHJldHVybiAoKDB4MzAvKiAwICovIDw9IGMpICYmIChjIDw9IDB4MzkvKiA5ICovKSk7XG59XG5cbmZ1bmN0aW9uIHJlc29sdmVZYW1sSW50ZWdlcihkYXRhKSB7XG4gIGlmIChkYXRhID09PSBudWxsKSByZXR1cm4gZmFsc2U7XG5cbiAgdmFyIG1heCA9IGRhdGEubGVuZ3RoLFxuICAgICAgaW5kZXggPSAwLFxuICAgICAgaGFzRGlnaXRzID0gZmFsc2UsXG4gICAgICBjaDtcblxuICBpZiAoIW1heCkgcmV0dXJuIGZhbHNlO1xuXG4gIGNoID0gZGF0YVtpbmRleF07XG5cbiAgLy8gc2lnblxuICBpZiAoY2ggPT09ICctJyB8fCBjaCA9PT0gJysnKSB7XG4gICAgY2ggPSBkYXRhWysraW5kZXhdO1xuICB9XG5cbiAgaWYgKGNoID09PSAnMCcpIHtcbiAgICAvLyAwXG4gICAgaWYgKGluZGV4ICsgMSA9PT0gbWF4KSByZXR1cm4gdHJ1ZTtcbiAgICBjaCA9IGRhdGFbKytpbmRleF07XG5cbiAgICAvLyBiYXNlIDIsIGJhc2UgOCwgYmFzZSAxNlxuXG4gICAgaWYgKGNoID09PSAnYicpIHtcbiAgICAgIC8vIGJhc2UgMlxuICAgICAgaW5kZXgrKztcblxuICAgICAgZm9yICg7IGluZGV4IDwgbWF4OyBpbmRleCsrKSB7XG4gICAgICAgIGNoID0gZGF0YVtpbmRleF07XG4gICAgICAgIGlmIChjaCA9PT0gJ18nKSBjb250aW51ZTtcbiAgICAgICAgaWYgKGNoICE9PSAnMCcgJiYgY2ggIT09ICcxJykgcmV0dXJuIGZhbHNlO1xuICAgICAgICBoYXNEaWdpdHMgPSB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGhhc0RpZ2l0cztcbiAgICB9XG5cblxuICAgIGlmIChjaCA9PT0gJ3gnKSB7XG4gICAgICAvLyBiYXNlIDE2XG4gICAgICBpbmRleCsrO1xuXG4gICAgICBmb3IgKDsgaW5kZXggPCBtYXg7IGluZGV4KyspIHtcbiAgICAgICAgY2ggPSBkYXRhW2luZGV4XTtcbiAgICAgICAgaWYgKGNoID09PSAnXycpIGNvbnRpbnVlO1xuICAgICAgICBpZiAoIWlzSGV4Q29kZShkYXRhLmNoYXJDb2RlQXQoaW5kZXgpKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICBoYXNEaWdpdHMgPSB0cnVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGhhc0RpZ2l0cztcbiAgICB9XG5cbiAgICAvLyBiYXNlIDhcbiAgICBmb3IgKDsgaW5kZXggPCBtYXg7IGluZGV4KyspIHtcbiAgICAgIGNoID0gZGF0YVtpbmRleF07XG4gICAgICBpZiAoY2ggPT09ICdfJykgY29udGludWU7XG4gICAgICBpZiAoIWlzT2N0Q29kZShkYXRhLmNoYXJDb2RlQXQoaW5kZXgpKSkgcmV0dXJuIGZhbHNlO1xuICAgICAgaGFzRGlnaXRzID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGhhc0RpZ2l0cztcbiAgfVxuXG4gIC8vIGJhc2UgMTAgKGV4Y2VwdCAwKSBvciBiYXNlIDYwXG5cbiAgZm9yICg7IGluZGV4IDwgbWF4OyBpbmRleCsrKSB7XG4gICAgY2ggPSBkYXRhW2luZGV4XTtcbiAgICBpZiAoY2ggPT09ICdfJykgY29udGludWU7XG4gICAgaWYgKGNoID09PSAnOicpIGJyZWFrO1xuICAgIGlmICghaXNEZWNDb2RlKGRhdGEuY2hhckNvZGVBdChpbmRleCkpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGhhc0RpZ2l0cyA9IHRydWU7XG4gIH1cblxuICBpZiAoIWhhc0RpZ2l0cykgcmV0dXJuIGZhbHNlO1xuXG4gIC8vIGlmICFiYXNlNjAgLSBkb25lO1xuICBpZiAoY2ggIT09ICc6JykgcmV0dXJuIHRydWU7XG5cbiAgLy8gYmFzZTYwIGFsbW9zdCBub3QgdXNlZCwgbm8gbmVlZHMgdG8gb3B0aW1pemVcbiAgcmV0dXJuIC9eKDpbMC01XT9bMC05XSkrJC8udGVzdChkYXRhLnNsaWNlKGluZGV4KSk7XG59XG5cbmZ1bmN0aW9uIGNvbnN0cnVjdFlhbWxJbnRlZ2VyKGRhdGEpIHtcbiAgdmFyIHZhbHVlID0gZGF0YSwgc2lnbiA9IDEsIGNoLCBiYXNlLCBkaWdpdHMgPSBbXTtcblxuICBpZiAodmFsdWUuaW5kZXhPZignXycpICE9PSAtMSkge1xuICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSgvXy9nLCAnJyk7XG4gIH1cblxuICBjaCA9IHZhbHVlWzBdO1xuXG4gIGlmIChjaCA9PT0gJy0nIHx8IGNoID09PSAnKycpIHtcbiAgICBpZiAoY2ggPT09ICctJykgc2lnbiA9IC0xO1xuICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoMSk7XG4gICAgY2ggPSB2YWx1ZVswXTtcbiAgfVxuXG4gIGlmICh2YWx1ZSA9PT0gJzAnKSByZXR1cm4gMDtcblxuICBpZiAoY2ggPT09ICcwJykge1xuICAgIGlmICh2YWx1ZVsxXSA9PT0gJ2InKSByZXR1cm4gc2lnbiAqIHBhcnNlSW50KHZhbHVlLnNsaWNlKDIpLCAyKTtcbiAgICBpZiAodmFsdWVbMV0gPT09ICd4JykgcmV0dXJuIHNpZ24gKiBwYXJzZUludCh2YWx1ZSwgMTYpO1xuICAgIHJldHVybiBzaWduICogcGFyc2VJbnQodmFsdWUsIDgpO1xuICB9XG5cbiAgaWYgKHZhbHVlLmluZGV4T2YoJzonKSAhPT0gLTEpIHtcbiAgICB2YWx1ZS5zcGxpdCgnOicpLmZvckVhY2goZnVuY3Rpb24gKHYpIHtcbiAgICAgIGRpZ2l0cy51bnNoaWZ0KHBhcnNlSW50KHYsIDEwKSk7XG4gICAgfSk7XG5cbiAgICB2YWx1ZSA9IDA7XG4gICAgYmFzZSA9IDE7XG5cbiAgICBkaWdpdHMuZm9yRWFjaChmdW5jdGlvbiAoZCkge1xuICAgICAgdmFsdWUgKz0gKGQgKiBiYXNlKTtcbiAgICAgIGJhc2UgKj0gNjA7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gc2lnbiAqIHZhbHVlO1xuXG4gIH1cblxuICByZXR1cm4gc2lnbiAqIHBhcnNlSW50KHZhbHVlLCAxMCk7XG59XG5cbmZ1bmN0aW9uIGlzSW50ZWdlcihvYmplY3QpIHtcbiAgcmV0dXJuIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqZWN0KSkgPT09ICdbb2JqZWN0IE51bWJlcl0nICYmXG4gICAgICAgICAob2JqZWN0ICUgMSA9PT0gMCAmJiAhY29tbW9uLmlzTmVnYXRpdmVaZXJvKG9iamVjdCkpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBUeXBlKCd0YWc6eWFtbC5vcmcsMjAwMjppbnQnLCB7XG4gIGtpbmQ6ICdzY2FsYXInLFxuICByZXNvbHZlOiByZXNvbHZlWWFtbEludGVnZXIsXG4gIGNvbnN0cnVjdDogY29uc3RydWN0WWFtbEludGVnZXIsXG4gIHByZWRpY2F0ZTogaXNJbnRlZ2VyLFxuICByZXByZXNlbnQ6IHtcbiAgICBiaW5hcnk6ICAgICAgZnVuY3Rpb24gKG9iamVjdCkgeyByZXR1cm4gJzBiJyArIG9iamVjdC50b1N0cmluZygyKTsgfSxcbiAgICBvY3RhbDogICAgICAgZnVuY3Rpb24gKG9iamVjdCkgeyByZXR1cm4gJzAnICArIG9iamVjdC50b1N0cmluZyg4KTsgfSxcbiAgICBkZWNpbWFsOiAgICAgZnVuY3Rpb24gKG9iamVjdCkgeyByZXR1cm4gICAgICAgIG9iamVjdC50b1N0cmluZygxMCk7IH0sXG4gICAgaGV4YWRlY2ltYWw6IGZ1bmN0aW9uIChvYmplY3QpIHsgcmV0dXJuICcweCcgKyBvYmplY3QudG9TdHJpbmcoMTYpLnRvVXBwZXJDYXNlKCk7IH1cbiAgfSxcbiAgZGVmYXVsdFN0eWxlOiAnZGVjaW1hbCcsXG4gIHN0eWxlQWxpYXNlczoge1xuICAgIGJpbmFyeTogICAgICBbIDIsICAnYmluJyBdLFxuICAgIG9jdGFsOiAgICAgICBbIDgsICAnb2N0JyBdLFxuICAgIGRlY2ltYWw6ICAgICBbIDEwLCAnZGVjJyBdLFxuICAgIGhleGFkZWNpbWFsOiBbIDE2LCAnaGV4JyBdXG4gIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZXNwcmltYTtcblxuLy8gQnJvd3NlcmlmaWVkIHZlcnNpb24gZG9lcyBub3QgaGF2ZSBlc3ByaW1hXG4vL1xuLy8gMS4gRm9yIG5vZGUuanMganVzdCByZXF1aXJlIG1vZHVsZSBhcyBkZXBzXG4vLyAyLiBGb3IgYnJvd3NlciB0cnkgdG8gcmVxdWlyZSBtdWR1bGUgdmlhIGV4dGVybmFsIEFNRCBzeXN0ZW0uXG4vLyAgICBJZiBub3QgZm91bmQgLSB0cnkgdG8gZmFsbGJhY2sgdG8gd2luZG93LmVzcHJpbWEuIElmIG5vdFxuLy8gICAgZm91bmQgdG9vIC0gdGhlbiBmYWlsIHRvIHBhcnNlLlxuLy9cbnRyeSB7XG4gIC8vIHdvcmthcm91bmQgdG8gZXhjbHVkZSBwYWNrYWdlIGZyb20gYnJvd3NlcmlmeSBsaXN0LlxuICB2YXIgX3JlcXVpcmUgPSByZXF1aXJlO1xuICBlc3ByaW1hID0gX3JlcXVpcmUoJ2VzcHJpbWEnKTtcbn0gY2F0Y2ggKF8pIHtcbiAgLypnbG9iYWwgd2luZG93ICovXG4gIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykgZXNwcmltYSA9IHdpbmRvdy5lc3ByaW1hO1xufVxuXG52YXIgVHlwZSA9IHJlcXVpcmUoJy4uLy4uL3R5cGUnKTtcblxuZnVuY3Rpb24gcmVzb2x2ZUphdmFzY3JpcHRGdW5jdGlvbihkYXRhKSB7XG4gIGlmIChkYXRhID09PSBudWxsKSByZXR1cm4gZmFsc2U7XG5cbiAgdHJ5IHtcbiAgICB2YXIgc291cmNlID0gJygnICsgZGF0YSArICcpJyxcbiAgICAgICAgYXN0ICAgID0gZXNwcmltYS5wYXJzZShzb3VyY2UsIHsgcmFuZ2U6IHRydWUgfSk7XG5cbiAgICBpZiAoYXN0LnR5cGUgICAgICAgICAgICAgICAgICAgICE9PSAnUHJvZ3JhbScgICAgICAgICAgICAgfHxcbiAgICAgICAgYXN0LmJvZHkubGVuZ3RoICAgICAgICAgICAgICE9PSAxICAgICAgICAgICAgICAgICAgICAgfHxcbiAgICAgICAgYXN0LmJvZHlbMF0udHlwZSAgICAgICAgICAgICE9PSAnRXhwcmVzc2lvblN0YXRlbWVudCcgfHxcbiAgICAgICAgYXN0LmJvZHlbMF0uZXhwcmVzc2lvbi50eXBlICE9PSAnRnVuY3Rpb25FeHByZXNzaW9uJykge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuZnVuY3Rpb24gY29uc3RydWN0SmF2YXNjcmlwdEZ1bmN0aW9uKGRhdGEpIHtcbiAgLypqc2xpbnQgZXZpbDp0cnVlKi9cblxuICB2YXIgc291cmNlID0gJygnICsgZGF0YSArICcpJyxcbiAgICAgIGFzdCAgICA9IGVzcHJpbWEucGFyc2Uoc291cmNlLCB7IHJhbmdlOiB0cnVlIH0pLFxuICAgICAgcGFyYW1zID0gW10sXG4gICAgICBib2R5O1xuXG4gIGlmIChhc3QudHlwZSAgICAgICAgICAgICAgICAgICAgIT09ICdQcm9ncmFtJyAgICAgICAgICAgICB8fFxuICAgICAgYXN0LmJvZHkubGVuZ3RoICAgICAgICAgICAgICE9PSAxICAgICAgICAgICAgICAgICAgICAgfHxcbiAgICAgIGFzdC5ib2R5WzBdLnR5cGUgICAgICAgICAgICAhPT0gJ0V4cHJlc3Npb25TdGF0ZW1lbnQnIHx8XG4gICAgICBhc3QuYm9keVswXS5leHByZXNzaW9uLnR5cGUgIT09ICdGdW5jdGlvbkV4cHJlc3Npb24nKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGYWlsZWQgdG8gcmVzb2x2ZSBmdW5jdGlvbicpO1xuICB9XG5cbiAgYXN0LmJvZHlbMF0uZXhwcmVzc2lvbi5wYXJhbXMuZm9yRWFjaChmdW5jdGlvbiAocGFyYW0pIHtcbiAgICBwYXJhbXMucHVzaChwYXJhbS5uYW1lKTtcbiAgfSk7XG5cbiAgYm9keSA9IGFzdC5ib2R5WzBdLmV4cHJlc3Npb24uYm9keS5yYW5nZTtcblxuICAvLyBFc3ByaW1hJ3MgcmFuZ2VzIGluY2x1ZGUgdGhlIGZpcnN0ICd7JyBhbmQgdGhlIGxhc3QgJ30nIGNoYXJhY3RlcnMgb25cbiAgLy8gZnVuY3Rpb24gZXhwcmVzc2lvbnMuIFNvIGN1dCB0aGVtIG91dC5cbiAgLyplc2xpbnQtZGlzYWJsZSBuby1uZXctZnVuYyovXG4gIHJldHVybiBuZXcgRnVuY3Rpb24ocGFyYW1zLCBzb3VyY2Uuc2xpY2UoYm9keVswXSArIDEsIGJvZHlbMV0gLSAxKSk7XG59XG5cbmZ1bmN0aW9uIHJlcHJlc2VudEphdmFzY3JpcHRGdW5jdGlvbihvYmplY3QgLyosIHN0eWxlKi8pIHtcbiAgcmV0dXJuIG9iamVjdC50b1N0cmluZygpO1xufVxuXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKG9iamVjdCkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iamVjdCkgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFR5cGUoJ3RhZzp5YW1sLm9yZywyMDAyOmpzL2Z1bmN0aW9uJywge1xuICBraW5kOiAnc2NhbGFyJyxcbiAgcmVzb2x2ZTogcmVzb2x2ZUphdmFzY3JpcHRGdW5jdGlvbixcbiAgY29uc3RydWN0OiBjb25zdHJ1Y3RKYXZhc2NyaXB0RnVuY3Rpb24sXG4gIHByZWRpY2F0ZTogaXNGdW5jdGlvbixcbiAgcmVwcmVzZW50OiByZXByZXNlbnRKYXZhc2NyaXB0RnVuY3Rpb25cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgVHlwZSA9IHJlcXVpcmUoJy4uLy4uL3R5cGUnKTtcblxuZnVuY3Rpb24gcmVzb2x2ZUphdmFzY3JpcHRSZWdFeHAoZGF0YSkge1xuICBpZiAoZGF0YSA9PT0gbnVsbCkgcmV0dXJuIGZhbHNlO1xuICBpZiAoZGF0YS5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcblxuICB2YXIgcmVnZXhwID0gZGF0YSxcbiAgICAgIHRhaWwgICA9IC9cXC8oW2dpbV0qKSQvLmV4ZWMoZGF0YSksXG4gICAgICBtb2RpZmllcnMgPSAnJztcblxuICAvLyBpZiByZWdleHAgc3RhcnRzIHdpdGggJy8nIGl0IGNhbiBoYXZlIG1vZGlmaWVycyBhbmQgbXVzdCBiZSBwcm9wZXJseSBjbG9zZWRcbiAgLy8gYC9mb28vZ2ltYCAtIG1vZGlmaWVycyB0YWlsIGNhbiBiZSBtYXhpbXVtIDMgY2hhcnNcbiAgaWYgKHJlZ2V4cFswXSA9PT0gJy8nKSB7XG4gICAgaWYgKHRhaWwpIG1vZGlmaWVycyA9IHRhaWxbMV07XG5cbiAgICBpZiAobW9kaWZpZXJzLmxlbmd0aCA+IDMpIHJldHVybiBmYWxzZTtcbiAgICAvLyBpZiBleHByZXNzaW9uIHN0YXJ0cyB3aXRoIC8sIGlzIHNob3VsZCBiZSBwcm9wZXJseSB0ZXJtaW5hdGVkXG4gICAgaWYgKHJlZ2V4cFtyZWdleHAubGVuZ3RoIC0gbW9kaWZpZXJzLmxlbmd0aCAtIDFdICE9PSAnLycpIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBjb25zdHJ1Y3RKYXZhc2NyaXB0UmVnRXhwKGRhdGEpIHtcbiAgdmFyIHJlZ2V4cCA9IGRhdGEsXG4gICAgICB0YWlsICAgPSAvXFwvKFtnaW1dKikkLy5leGVjKGRhdGEpLFxuICAgICAgbW9kaWZpZXJzID0gJyc7XG5cbiAgLy8gYC9mb28vZ2ltYCAtIHRhaWwgY2FuIGJlIG1heGltdW0gNCBjaGFyc1xuICBpZiAocmVnZXhwWzBdID09PSAnLycpIHtcbiAgICBpZiAodGFpbCkgbW9kaWZpZXJzID0gdGFpbFsxXTtcbiAgICByZWdleHAgPSByZWdleHAuc2xpY2UoMSwgcmVnZXhwLmxlbmd0aCAtIG1vZGlmaWVycy5sZW5ndGggLSAxKTtcbiAgfVxuXG4gIHJldHVybiBuZXcgUmVnRXhwKHJlZ2V4cCwgbW9kaWZpZXJzKTtcbn1cblxuZnVuY3Rpb24gcmVwcmVzZW50SmF2YXNjcmlwdFJlZ0V4cChvYmplY3QgLyosIHN0eWxlKi8pIHtcbiAgdmFyIHJlc3VsdCA9ICcvJyArIG9iamVjdC5zb3VyY2UgKyAnLyc7XG5cbiAgaWYgKG9iamVjdC5nbG9iYWwpIHJlc3VsdCArPSAnZyc7XG4gIGlmIChvYmplY3QubXVsdGlsaW5lKSByZXN1bHQgKz0gJ20nO1xuICBpZiAob2JqZWN0Lmlnbm9yZUNhc2UpIHJlc3VsdCArPSAnaSc7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gaXNSZWdFeHAob2JqZWN0KSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqZWN0KSA9PT0gJ1tvYmplY3QgUmVnRXhwXSc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFR5cGUoJ3RhZzp5YW1sLm9yZywyMDAyOmpzL3JlZ2V4cCcsIHtcbiAga2luZDogJ3NjYWxhcicsXG4gIHJlc29sdmU6IHJlc29sdmVKYXZhc2NyaXB0UmVnRXhwLFxuICBjb25zdHJ1Y3Q6IGNvbnN0cnVjdEphdmFzY3JpcHRSZWdFeHAsXG4gIHByZWRpY2F0ZTogaXNSZWdFeHAsXG4gIHJlcHJlc2VudDogcmVwcmVzZW50SmF2YXNjcmlwdFJlZ0V4cFxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBUeXBlID0gcmVxdWlyZSgnLi4vLi4vdHlwZScpO1xuXG5mdW5jdGlvbiByZXNvbHZlSmF2YXNjcmlwdFVuZGVmaW5lZCgpIHtcbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGNvbnN0cnVjdEphdmFzY3JpcHRVbmRlZmluZWQoKSB7XG4gIC8qZXNsaW50LWRpc2FibGUgbm8tdW5kZWZpbmVkKi9cbiAgcmV0dXJuIHVuZGVmaW5lZDtcbn1cblxuZnVuY3Rpb24gcmVwcmVzZW50SmF2YXNjcmlwdFVuZGVmaW5lZCgpIHtcbiAgcmV0dXJuICcnO1xufVxuXG5mdW5jdGlvbiBpc1VuZGVmaW5lZChvYmplY3QpIHtcbiAgcmV0dXJuIHR5cGVvZiBvYmplY3QgPT09ICd1bmRlZmluZWQnO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBUeXBlKCd0YWc6eWFtbC5vcmcsMjAwMjpqcy91bmRlZmluZWQnLCB7XG4gIGtpbmQ6ICdzY2FsYXInLFxuICByZXNvbHZlOiByZXNvbHZlSmF2YXNjcmlwdFVuZGVmaW5lZCxcbiAgY29uc3RydWN0OiBjb25zdHJ1Y3RKYXZhc2NyaXB0VW5kZWZpbmVkLFxuICBwcmVkaWNhdGU6IGlzVW5kZWZpbmVkLFxuICByZXByZXNlbnQ6IHJlcHJlc2VudEphdmFzY3JpcHRVbmRlZmluZWRcbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgVHlwZSA9IHJlcXVpcmUoJy4uL3R5cGUnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBuZXcgVHlwZSgndGFnOnlhbWwub3JnLDIwMDI6bWFwJywge1xuICBraW5kOiAnbWFwcGluZycsXG4gIGNvbnN0cnVjdDogZnVuY3Rpb24gKGRhdGEpIHsgcmV0dXJuIGRhdGEgIT09IG51bGwgPyBkYXRhIDoge307IH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgVHlwZSA9IHJlcXVpcmUoJy4uL3R5cGUnKTtcblxuZnVuY3Rpb24gcmVzb2x2ZVlhbWxNZXJnZShkYXRhKSB7XG4gIHJldHVybiBkYXRhID09PSAnPDwnIHx8IGRhdGEgPT09IG51bGw7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFR5cGUoJ3RhZzp5YW1sLm9yZywyMDAyOm1lcmdlJywge1xuICBraW5kOiAnc2NhbGFyJyxcbiAgcmVzb2x2ZTogcmVzb2x2ZVlhbWxNZXJnZVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBUeXBlID0gcmVxdWlyZSgnLi4vdHlwZScpO1xuXG5mdW5jdGlvbiByZXNvbHZlWWFtbE51bGwoZGF0YSkge1xuICBpZiAoZGF0YSA9PT0gbnVsbCkgcmV0dXJuIHRydWU7XG5cbiAgdmFyIG1heCA9IGRhdGEubGVuZ3RoO1xuXG4gIHJldHVybiAobWF4ID09PSAxICYmIGRhdGEgPT09ICd+JykgfHxcbiAgICAgICAgIChtYXggPT09IDQgJiYgKGRhdGEgPT09ICdudWxsJyB8fCBkYXRhID09PSAnTnVsbCcgfHwgZGF0YSA9PT0gJ05VTEwnKSk7XG59XG5cbmZ1bmN0aW9uIGNvbnN0cnVjdFlhbWxOdWxsKCkge1xuICByZXR1cm4gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNOdWxsKG9iamVjdCkge1xuICByZXR1cm4gb2JqZWN0ID09PSBudWxsO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBUeXBlKCd0YWc6eWFtbC5vcmcsMjAwMjpudWxsJywge1xuICBraW5kOiAnc2NhbGFyJyxcbiAgcmVzb2x2ZTogcmVzb2x2ZVlhbWxOdWxsLFxuICBjb25zdHJ1Y3Q6IGNvbnN0cnVjdFlhbWxOdWxsLFxuICBwcmVkaWNhdGU6IGlzTnVsbCxcbiAgcmVwcmVzZW50OiB7XG4gICAgY2Fub25pY2FsOiBmdW5jdGlvbiAoKSB7IHJldHVybiAnfic7ICAgIH0sXG4gICAgbG93ZXJjYXNlOiBmdW5jdGlvbiAoKSB7IHJldHVybiAnbnVsbCc7IH0sXG4gICAgdXBwZXJjYXNlOiBmdW5jdGlvbiAoKSB7IHJldHVybiAnTlVMTCc7IH0sXG4gICAgY2FtZWxjYXNlOiBmdW5jdGlvbiAoKSB7IHJldHVybiAnTnVsbCc7IH1cbiAgfSxcbiAgZGVmYXVsdFN0eWxlOiAnbG93ZXJjYXNlJ1xufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBUeXBlID0gcmVxdWlyZSgnLi4vdHlwZScpO1xuXG52YXIgX2hhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcbnZhciBfdG9TdHJpbmcgICAgICAgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG5mdW5jdGlvbiByZXNvbHZlWWFtbE9tYXAoZGF0YSkge1xuICBpZiAoZGF0YSA9PT0gbnVsbCkgcmV0dXJuIHRydWU7XG5cbiAgdmFyIG9iamVjdEtleXMgPSBbXSwgaW5kZXgsIGxlbmd0aCwgcGFpciwgcGFpcktleSwgcGFpckhhc0tleSxcbiAgICAgIG9iamVjdCA9IGRhdGE7XG5cbiAgZm9yIChpbmRleCA9IDAsIGxlbmd0aCA9IG9iamVjdC5sZW5ndGg7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCArPSAxKSB7XG4gICAgcGFpciA9IG9iamVjdFtpbmRleF07XG4gICAgcGFpckhhc0tleSA9IGZhbHNlO1xuXG4gICAgaWYgKF90b1N0cmluZy5jYWxsKHBhaXIpICE9PSAnW29iamVjdCBPYmplY3RdJykgcmV0dXJuIGZhbHNlO1xuXG4gICAgZm9yIChwYWlyS2V5IGluIHBhaXIpIHtcbiAgICAgIGlmIChfaGFzT3duUHJvcGVydHkuY2FsbChwYWlyLCBwYWlyS2V5KSkge1xuICAgICAgICBpZiAoIXBhaXJIYXNLZXkpIHBhaXJIYXNLZXkgPSB0cnVlO1xuICAgICAgICBlbHNlIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXBhaXJIYXNLZXkpIHJldHVybiBmYWxzZTtcblxuICAgIGlmIChvYmplY3RLZXlzLmluZGV4T2YocGFpcktleSkgPT09IC0xKSBvYmplY3RLZXlzLnB1c2gocGFpcktleSk7XG4gICAgZWxzZSByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gY29uc3RydWN0WWFtbE9tYXAoZGF0YSkge1xuICByZXR1cm4gZGF0YSAhPT0gbnVsbCA/IGRhdGEgOiBbXTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBuZXcgVHlwZSgndGFnOnlhbWwub3JnLDIwMDI6b21hcCcsIHtcbiAga2luZDogJ3NlcXVlbmNlJyxcbiAgcmVzb2x2ZTogcmVzb2x2ZVlhbWxPbWFwLFxuICBjb25zdHJ1Y3Q6IGNvbnN0cnVjdFlhbWxPbWFwXG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFR5cGUgPSByZXF1aXJlKCcuLi90eXBlJyk7XG5cbnZhciBfdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG5mdW5jdGlvbiByZXNvbHZlWWFtbFBhaXJzKGRhdGEpIHtcbiAgaWYgKGRhdGEgPT09IG51bGwpIHJldHVybiB0cnVlO1xuXG4gIHZhciBpbmRleCwgbGVuZ3RoLCBwYWlyLCBrZXlzLCByZXN1bHQsXG4gICAgICBvYmplY3QgPSBkYXRhO1xuXG4gIHJlc3VsdCA9IG5ldyBBcnJheShvYmplY3QubGVuZ3RoKTtcblxuICBmb3IgKGluZGV4ID0gMCwgbGVuZ3RoID0gb2JqZWN0Lmxlbmd0aDsgaW5kZXggPCBsZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICBwYWlyID0gb2JqZWN0W2luZGV4XTtcblxuICAgIGlmIChfdG9TdHJpbmcuY2FsbChwYWlyKSAhPT0gJ1tvYmplY3QgT2JqZWN0XScpIHJldHVybiBmYWxzZTtcblxuICAgIGtleXMgPSBPYmplY3Qua2V5cyhwYWlyKTtcblxuICAgIGlmIChrZXlzLmxlbmd0aCAhPT0gMSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgcmVzdWx0W2luZGV4XSA9IFsga2V5c1swXSwgcGFpcltrZXlzWzBdXSBdO1xuICB9XG5cbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIGNvbnN0cnVjdFlhbWxQYWlycyhkYXRhKSB7XG4gIGlmIChkYXRhID09PSBudWxsKSByZXR1cm4gW107XG5cbiAgdmFyIGluZGV4LCBsZW5ndGgsIHBhaXIsIGtleXMsIHJlc3VsdCxcbiAgICAgIG9iamVjdCA9IGRhdGE7XG5cbiAgcmVzdWx0ID0gbmV3IEFycmF5KG9iamVjdC5sZW5ndGgpO1xuXG4gIGZvciAoaW5kZXggPSAwLCBsZW5ndGggPSBvYmplY3QubGVuZ3RoOyBpbmRleCA8IGxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgIHBhaXIgPSBvYmplY3RbaW5kZXhdO1xuXG4gICAga2V5cyA9IE9iamVjdC5rZXlzKHBhaXIpO1xuXG4gICAgcmVzdWx0W2luZGV4XSA9IFsga2V5c1swXSwgcGFpcltrZXlzWzBdXSBdO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBuZXcgVHlwZSgndGFnOnlhbWwub3JnLDIwMDI6cGFpcnMnLCB7XG4gIGtpbmQ6ICdzZXF1ZW5jZScsXG4gIHJlc29sdmU6IHJlc29sdmVZYW1sUGFpcnMsXG4gIGNvbnN0cnVjdDogY29uc3RydWN0WWFtbFBhaXJzXG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFR5cGUgPSByZXF1aXJlKCcuLi90eXBlJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFR5cGUoJ3RhZzp5YW1sLm9yZywyMDAyOnNlcScsIHtcbiAga2luZDogJ3NlcXVlbmNlJyxcbiAgY29uc3RydWN0OiBmdW5jdGlvbiAoZGF0YSkgeyByZXR1cm4gZGF0YSAhPT0gbnVsbCA/IGRhdGEgOiBbXTsgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBUeXBlID0gcmVxdWlyZSgnLi4vdHlwZScpO1xuXG52YXIgX2hhc093blByb3BlcnR5ID0gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eTtcblxuZnVuY3Rpb24gcmVzb2x2ZVlhbWxTZXQoZGF0YSkge1xuICBpZiAoZGF0YSA9PT0gbnVsbCkgcmV0dXJuIHRydWU7XG5cbiAgdmFyIGtleSwgb2JqZWN0ID0gZGF0YTtcblxuICBmb3IgKGtleSBpbiBvYmplY3QpIHtcbiAgICBpZiAoX2hhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpKSB7XG4gICAgICBpZiAob2JqZWN0W2tleV0gIT09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gY29uc3RydWN0WWFtbFNldChkYXRhKSB7XG4gIHJldHVybiBkYXRhICE9PSBudWxsID8gZGF0YSA6IHt9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBUeXBlKCd0YWc6eWFtbC5vcmcsMjAwMjpzZXQnLCB7XG4gIGtpbmQ6ICdtYXBwaW5nJyxcbiAgcmVzb2x2ZTogcmVzb2x2ZVlhbWxTZXQsXG4gIGNvbnN0cnVjdDogY29uc3RydWN0WWFtbFNldFxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbnZhciBUeXBlID0gcmVxdWlyZSgnLi4vdHlwZScpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5ldyBUeXBlKCd0YWc6eWFtbC5vcmcsMjAwMjpzdHInLCB7XG4gIGtpbmQ6ICdzY2FsYXInLFxuICBjb25zdHJ1Y3Q6IGZ1bmN0aW9uIChkYXRhKSB7IHJldHVybiBkYXRhICE9PSBudWxsID8gZGF0YSA6ICcnOyB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxudmFyIFR5cGUgPSByZXF1aXJlKCcuLi90eXBlJyk7XG5cbnZhciBZQU1MX0RBVEVfUkVHRVhQID0gbmV3IFJlZ0V4cChcbiAgJ14oWzAtOV1bMC05XVswLTldWzAtOV0pJyAgICAgICAgICArIC8vIFsxXSB5ZWFyXG4gICctKFswLTldWzAtOV0pJyAgICAgICAgICAgICAgICAgICAgKyAvLyBbMl0gbW9udGhcbiAgJy0oWzAtOV1bMC05XSkkJyk7ICAgICAgICAgICAgICAgICAgIC8vIFszXSBkYXlcblxudmFyIFlBTUxfVElNRVNUQU1QX1JFR0VYUCA9IG5ldyBSZWdFeHAoXG4gICdeKFswLTldWzAtOV1bMC05XVswLTldKScgICAgICAgICAgKyAvLyBbMV0geWVhclxuICAnLShbMC05XVswLTldPyknICAgICAgICAgICAgICAgICAgICsgLy8gWzJdIG1vbnRoXG4gICctKFswLTldWzAtOV0/KScgICAgICAgICAgICAgICAgICAgKyAvLyBbM10gZGF5XG4gICcoPzpbVHRdfFsgXFxcXHRdKyknICAgICAgICAgICAgICAgICArIC8vIC4uLlxuICAnKFswLTldWzAtOV0/KScgICAgICAgICAgICAgICAgICAgICsgLy8gWzRdIGhvdXJcbiAgJzooWzAtOV1bMC05XSknICAgICAgICAgICAgICAgICAgICArIC8vIFs1XSBtaW51dGVcbiAgJzooWzAtOV1bMC05XSknICAgICAgICAgICAgICAgICAgICArIC8vIFs2XSBzZWNvbmRcbiAgJyg/OlxcXFwuKFswLTldKikpPycgICAgICAgICAgICAgICAgICsgLy8gWzddIGZyYWN0aW9uXG4gICcoPzpbIFxcXFx0XSooWnwoWy0rXSkoWzAtOV1bMC05XT8pJyArIC8vIFs4XSB0eiBbOV0gdHpfc2lnbiBbMTBdIHR6X2hvdXJcbiAgJyg/OjooWzAtOV1bMC05XSkpPykpPyQnKTsgICAgICAgICAgIC8vIFsxMV0gdHpfbWludXRlXG5cbmZ1bmN0aW9uIHJlc29sdmVZYW1sVGltZXN0YW1wKGRhdGEpIHtcbiAgaWYgKGRhdGEgPT09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgaWYgKFlBTUxfREFURV9SRUdFWFAuZXhlYyhkYXRhKSAhPT0gbnVsbCkgcmV0dXJuIHRydWU7XG4gIGlmIChZQU1MX1RJTUVTVEFNUF9SRUdFWFAuZXhlYyhkYXRhKSAhPT0gbnVsbCkgcmV0dXJuIHRydWU7XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gY29uc3RydWN0WWFtbFRpbWVzdGFtcChkYXRhKSB7XG4gIHZhciBtYXRjaCwgeWVhciwgbW9udGgsIGRheSwgaG91ciwgbWludXRlLCBzZWNvbmQsIGZyYWN0aW9uID0gMCxcbiAgICAgIGRlbHRhID0gbnVsbCwgdHpfaG91ciwgdHpfbWludXRlLCBkYXRlO1xuXG4gIG1hdGNoID0gWUFNTF9EQVRFX1JFR0VYUC5leGVjKGRhdGEpO1xuICBpZiAobWF0Y2ggPT09IG51bGwpIG1hdGNoID0gWUFNTF9USU1FU1RBTVBfUkVHRVhQLmV4ZWMoZGF0YSk7XG5cbiAgaWYgKG1hdGNoID09PSBudWxsKSB0aHJvdyBuZXcgRXJyb3IoJ0RhdGUgcmVzb2x2ZSBlcnJvcicpO1xuXG4gIC8vIG1hdGNoOiBbMV0geWVhciBbMl0gbW9udGggWzNdIGRheVxuXG4gIHllYXIgPSArKG1hdGNoWzFdKTtcbiAgbW9udGggPSArKG1hdGNoWzJdKSAtIDE7IC8vIEpTIG1vbnRoIHN0YXJ0cyB3aXRoIDBcbiAgZGF5ID0gKyhtYXRjaFszXSk7XG5cbiAgaWYgKCFtYXRjaFs0XSkgeyAvLyBubyBob3VyXG4gICAgcmV0dXJuIG5ldyBEYXRlKERhdGUuVVRDKHllYXIsIG1vbnRoLCBkYXkpKTtcbiAgfVxuXG4gIC8vIG1hdGNoOiBbNF0gaG91ciBbNV0gbWludXRlIFs2XSBzZWNvbmQgWzddIGZyYWN0aW9uXG5cbiAgaG91ciA9ICsobWF0Y2hbNF0pO1xuICBtaW51dGUgPSArKG1hdGNoWzVdKTtcbiAgc2Vjb25kID0gKyhtYXRjaFs2XSk7XG5cbiAgaWYgKG1hdGNoWzddKSB7XG4gICAgZnJhY3Rpb24gPSBtYXRjaFs3XS5zbGljZSgwLCAzKTtcbiAgICB3aGlsZSAoZnJhY3Rpb24ubGVuZ3RoIDwgMykgeyAvLyBtaWxsaS1zZWNvbmRzXG4gICAgICBmcmFjdGlvbiArPSAnMCc7XG4gICAgfVxuICAgIGZyYWN0aW9uID0gK2ZyYWN0aW9uO1xuICB9XG5cbiAgLy8gbWF0Y2g6IFs4XSB0eiBbOV0gdHpfc2lnbiBbMTBdIHR6X2hvdXIgWzExXSB0el9taW51dGVcblxuICBpZiAobWF0Y2hbOV0pIHtcbiAgICB0el9ob3VyID0gKyhtYXRjaFsxMF0pO1xuICAgIHR6X21pbnV0ZSA9ICsobWF0Y2hbMTFdIHx8IDApO1xuICAgIGRlbHRhID0gKHR6X2hvdXIgKiA2MCArIHR6X21pbnV0ZSkgKiA2MDAwMDsgLy8gZGVsdGEgaW4gbWlsaS1zZWNvbmRzXG4gICAgaWYgKG1hdGNoWzldID09PSAnLScpIGRlbHRhID0gLWRlbHRhO1xuICB9XG5cbiAgZGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDKHllYXIsIG1vbnRoLCBkYXksIGhvdXIsIG1pbnV0ZSwgc2Vjb25kLCBmcmFjdGlvbikpO1xuXG4gIGlmIChkZWx0YSkgZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpIC0gZGVsdGEpO1xuXG4gIHJldHVybiBkYXRlO1xufVxuXG5mdW5jdGlvbiByZXByZXNlbnRZYW1sVGltZXN0YW1wKG9iamVjdCAvKiwgc3R5bGUqLykge1xuICByZXR1cm4gb2JqZWN0LnRvSVNPU3RyaW5nKCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbmV3IFR5cGUoJ3RhZzp5YW1sLm9yZywyMDAyOnRpbWVzdGFtcCcsIHtcbiAga2luZDogJ3NjYWxhcicsXG4gIHJlc29sdmU6IHJlc29sdmVZYW1sVGltZXN0YW1wLFxuICBjb25zdHJ1Y3Q6IGNvbnN0cnVjdFlhbWxUaW1lc3RhbXAsXG4gIGluc3RhbmNlT2Y6IERhdGUsXG4gIHJlcHJlc2VudDogcmVwcmVzZW50WWFtbFRpbWVzdGFtcFxufSk7XG4iLCJ2YXIgYmFzZUluZGV4T2YgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9iYXNlSW5kZXhPZicpLFxuICAgIGJpbmFyeUluZGV4ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvYmluYXJ5SW5kZXgnKTtcblxuLyogTmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVNYXggPSBNYXRoLm1heDtcblxuLyoqXG4gKiBHZXRzIHRoZSBpbmRleCBhdCB3aGljaCB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBgdmFsdWVgIGlzIGZvdW5kIGluIGBhcnJheWBcbiAqIHVzaW5nIFtgU2FtZVZhbHVlWmVyb2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXNhbWV2YWx1ZXplcm8pXG4gKiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuIElmIGBmcm9tSW5kZXhgIGlzIG5lZ2F0aXZlLCBpdCdzIHVzZWQgYXMgdGhlIG9mZnNldFxuICogZnJvbSB0aGUgZW5kIG9mIGBhcnJheWAuIElmIGBhcnJheWAgaXMgc29ydGVkIHByb3ZpZGluZyBgdHJ1ZWAgZm9yIGBmcm9tSW5kZXhgXG4gKiBwZXJmb3JtcyBhIGZhc3RlciBiaW5hcnkgc2VhcmNoLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgQXJyYXlcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzZWFyY2guXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICogQHBhcmFtIHtib29sZWFufG51bWJlcn0gW2Zyb21JbmRleD0wXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20gb3IgYHRydWVgXG4gKiAgdG8gcGVyZm9ybSBhIGJpbmFyeSBzZWFyY2ggb24gYSBzb3J0ZWQgYXJyYXkuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmluZGV4T2YoWzEsIDIsIDEsIDJdLCAyKTtcbiAqIC8vID0+IDFcbiAqXG4gKiAvLyB1c2luZyBgZnJvbUluZGV4YFxuICogXy5pbmRleE9mKFsxLCAyLCAxLCAyXSwgMiwgMik7XG4gKiAvLyA9PiAzXG4gKlxuICogLy8gcGVyZm9ybWluZyBhIGJpbmFyeSBzZWFyY2hcbiAqIF8uaW5kZXhPZihbMSwgMSwgMiwgMl0sIDIsIHRydWUpO1xuICogLy8gPT4gMlxuICovXG5mdW5jdGlvbiBpbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4KSB7XG4gIHZhciBsZW5ndGggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDA7XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgcmV0dXJuIC0xO1xuICB9XG4gIGlmICh0eXBlb2YgZnJvbUluZGV4ID09ICdudW1iZXInKSB7XG4gICAgZnJvbUluZGV4ID0gZnJvbUluZGV4IDwgMCA/IG5hdGl2ZU1heChsZW5ndGggKyBmcm9tSW5kZXgsIDApIDogZnJvbUluZGV4O1xuICB9IGVsc2UgaWYgKGZyb21JbmRleCkge1xuICAgIHZhciBpbmRleCA9IGJpbmFyeUluZGV4KGFycmF5LCB2YWx1ZSk7XG4gICAgaWYgKGluZGV4IDwgbGVuZ3RoICYmXG4gICAgICAgICh2YWx1ZSA9PT0gdmFsdWUgPyAodmFsdWUgPT09IGFycmF5W2luZGV4XSkgOiAoYXJyYXlbaW5kZXhdICE9PSBhcnJheVtpbmRleF0pKSkge1xuICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH1cbiAgcmV0dXJuIGJhc2VJbmRleE9mKGFycmF5LCB2YWx1ZSwgZnJvbUluZGV4IHx8IDApO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGluZGV4T2Y7XG4iLCIvKipcbiAqIEdldHMgdGhlIGxhc3QgZWxlbWVudCBvZiBgYXJyYXlgLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgQXJyYXlcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBsYXN0IGVsZW1lbnQgb2YgYGFycmF5YC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5sYXN0KFsxLCAyLCAzXSk7XG4gKiAvLyA9PiAzXG4gKi9cbmZ1bmN0aW9uIGxhc3QoYXJyYXkpIHtcbiAgdmFyIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcbiAgcmV0dXJuIGxlbmd0aCA/IGFycmF5W2xlbmd0aCAtIDFdIDogdW5kZWZpbmVkO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGxhc3Q7XG4iLCJ2YXIgTGF6eVdyYXBwZXIgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9MYXp5V3JhcHBlcicpLFxuICAgIExvZGFzaFdyYXBwZXIgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9Mb2Rhc2hXcmFwcGVyJyksXG4gICAgYmFzZUxvZGFzaCA9IHJlcXVpcmUoJy4uL2ludGVybmFsL2Jhc2VMb2Rhc2gnKSxcbiAgICBpc0FycmF5ID0gcmVxdWlyZSgnLi4vbGFuZy9pc0FycmF5JyksXG4gICAgaXNPYmplY3RMaWtlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvaXNPYmplY3RMaWtlJyksXG4gICAgd3JhcHBlckNsb25lID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvd3JhcHBlckNsb25lJyk7XG5cbi8qKiBVc2VkIGZvciBuYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBgbG9kYXNoYCBvYmplY3Qgd2hpY2ggd3JhcHMgYHZhbHVlYCB0byBlbmFibGUgaW1wbGljaXQgY2hhaW5pbmcuXG4gKiBNZXRob2RzIHRoYXQgb3BlcmF0ZSBvbiBhbmQgcmV0dXJuIGFycmF5cywgY29sbGVjdGlvbnMsIGFuZCBmdW5jdGlvbnMgY2FuXG4gKiBiZSBjaGFpbmVkIHRvZ2V0aGVyLiBNZXRob2RzIHRoYXQgcmV0cmlldmUgYSBzaW5nbGUgdmFsdWUgb3IgbWF5IHJldHVybiBhXG4gKiBwcmltaXRpdmUgdmFsdWUgd2lsbCBhdXRvbWF0aWNhbGx5IGVuZCB0aGUgY2hhaW4gcmV0dXJuaW5nIHRoZSB1bndyYXBwZWRcbiAqIHZhbHVlLiBFeHBsaWNpdCBjaGFpbmluZyBtYXkgYmUgZW5hYmxlZCB1c2luZyBgXy5jaGFpbmAuIFRoZSBleGVjdXRpb24gb2ZcbiAqIGNoYWluZWQgbWV0aG9kcyBpcyBsYXp5LCB0aGF0IGlzLCBleGVjdXRpb24gaXMgZGVmZXJyZWQgdW50aWwgYF8jdmFsdWVgXG4gKiBpcyBpbXBsaWNpdGx5IG9yIGV4cGxpY2l0bHkgY2FsbGVkLlxuICpcbiAqIExhenkgZXZhbHVhdGlvbiBhbGxvd3Mgc2V2ZXJhbCBtZXRob2RzIHRvIHN1cHBvcnQgc2hvcnRjdXQgZnVzaW9uLiBTaG9ydGN1dFxuICogZnVzaW9uIGlzIGFuIG9wdGltaXphdGlvbiBzdHJhdGVneSB3aGljaCBtZXJnZSBpdGVyYXRlZSBjYWxsczsgdGhpcyBjYW4gaGVscFxuICogdG8gYXZvaWQgdGhlIGNyZWF0aW9uIG9mIGludGVybWVkaWF0ZSBkYXRhIHN0cnVjdHVyZXMgYW5kIGdyZWF0bHkgcmVkdWNlIHRoZVxuICogbnVtYmVyIG9mIGl0ZXJhdGVlIGV4ZWN1dGlvbnMuXG4gKlxuICogQ2hhaW5pbmcgaXMgc3VwcG9ydGVkIGluIGN1c3RvbSBidWlsZHMgYXMgbG9uZyBhcyB0aGUgYF8jdmFsdWVgIG1ldGhvZCBpc1xuICogZGlyZWN0bHkgb3IgaW5kaXJlY3RseSBpbmNsdWRlZCBpbiB0aGUgYnVpbGQuXG4gKlxuICogSW4gYWRkaXRpb24gdG8gbG9kYXNoIG1ldGhvZHMsIHdyYXBwZXJzIGhhdmUgYEFycmF5YCBhbmQgYFN0cmluZ2AgbWV0aG9kcy5cbiAqXG4gKiBUaGUgd3JhcHBlciBgQXJyYXlgIG1ldGhvZHMgYXJlOlxuICogYGNvbmNhdGAsIGBqb2luYCwgYHBvcGAsIGBwdXNoYCwgYHJldmVyc2VgLCBgc2hpZnRgLCBgc2xpY2VgLCBgc29ydGAsXG4gKiBgc3BsaWNlYCwgYW5kIGB1bnNoaWZ0YFxuICpcbiAqIFRoZSB3cmFwcGVyIGBTdHJpbmdgIG1ldGhvZHMgYXJlOlxuICogYHJlcGxhY2VgIGFuZCBgc3BsaXRgXG4gKlxuICogVGhlIHdyYXBwZXIgbWV0aG9kcyB0aGF0IHN1cHBvcnQgc2hvcnRjdXQgZnVzaW9uIGFyZTpcbiAqIGBjb21wYWN0YCwgYGRyb3BgLCBgZHJvcFJpZ2h0YCwgYGRyb3BSaWdodFdoaWxlYCwgYGRyb3BXaGlsZWAsIGBmaWx0ZXJgLFxuICogYGZpcnN0YCwgYGluaXRpYWxgLCBgbGFzdGAsIGBtYXBgLCBgcGx1Y2tgLCBgcmVqZWN0YCwgYHJlc3RgLCBgcmV2ZXJzZWAsXG4gKiBgc2xpY2VgLCBgdGFrZWAsIGB0YWtlUmlnaHRgLCBgdGFrZVJpZ2h0V2hpbGVgLCBgdGFrZVdoaWxlYCwgYHRvQXJyYXlgLFxuICogYW5kIGB3aGVyZWBcbiAqXG4gKiBUaGUgY2hhaW5hYmxlIHdyYXBwZXIgbWV0aG9kcyBhcmU6XG4gKiBgYWZ0ZXJgLCBgYXJ5YCwgYGFzc2lnbmAsIGBhdGAsIGBiZWZvcmVgLCBgYmluZGAsIGBiaW5kQWxsYCwgYGJpbmRLZXlgLFxuICogYGNhbGxiYWNrYCwgYGNoYWluYCwgYGNodW5rYCwgYGNvbW1pdGAsIGBjb21wYWN0YCwgYGNvbmNhdGAsIGBjb25zdGFudGAsXG4gKiBgY291bnRCeWAsIGBjcmVhdGVgLCBgY3VycnlgLCBgZGVib3VuY2VgLCBgZGVmYXVsdHNgLCBgZGVmYXVsdHNEZWVwYCxcbiAqIGBkZWZlcmAsIGBkZWxheWAsIGBkaWZmZXJlbmNlYCwgYGRyb3BgLCBgZHJvcFJpZ2h0YCwgYGRyb3BSaWdodFdoaWxlYCxcbiAqIGBkcm9wV2hpbGVgLCBgZmlsbGAsIGBmaWx0ZXJgLCBgZmxhdHRlbmAsIGBmbGF0dGVuRGVlcGAsIGBmbG93YCwgYGZsb3dSaWdodGAsXG4gKiBgZm9yRWFjaGAsIGBmb3JFYWNoUmlnaHRgLCBgZm9ySW5gLCBgZm9ySW5SaWdodGAsIGBmb3JPd25gLCBgZm9yT3duUmlnaHRgLFxuICogYGZ1bmN0aW9uc2AsIGBncm91cEJ5YCwgYGluZGV4QnlgLCBgaW5pdGlhbGAsIGBpbnRlcnNlY3Rpb25gLCBgaW52ZXJ0YCxcbiAqIGBpbnZva2VgLCBga2V5c2AsIGBrZXlzSW5gLCBgbWFwYCwgYG1hcEtleXNgLCBgbWFwVmFsdWVzYCwgYG1hdGNoZXNgLFxuICogYG1hdGNoZXNQcm9wZXJ0eWAsIGBtZW1vaXplYCwgYG1lcmdlYCwgYG1ldGhvZGAsIGBtZXRob2RPZmAsIGBtaXhpbmAsXG4gKiBgbW9kQXJnc2AsIGBuZWdhdGVgLCBgb21pdGAsIGBvbmNlYCwgYHBhaXJzYCwgYHBhcnRpYWxgLCBgcGFydGlhbFJpZ2h0YCxcbiAqIGBwYXJ0aXRpb25gLCBgcGlja2AsIGBwbGFudGAsIGBwbHVja2AsIGBwcm9wZXJ0eWAsIGBwcm9wZXJ0eU9mYCwgYHB1bGxgLFxuICogYHB1bGxBdGAsIGBwdXNoYCwgYHJhbmdlYCwgYHJlYXJnYCwgYHJlamVjdGAsIGByZW1vdmVgLCBgcmVzdGAsIGByZXN0UGFyYW1gLFxuICogYHJldmVyc2VgLCBgc2V0YCwgYHNodWZmbGVgLCBgc2xpY2VgLCBgc29ydGAsIGBzb3J0QnlgLCBgc29ydEJ5QWxsYCxcbiAqIGBzb3J0QnlPcmRlcmAsIGBzcGxpY2VgLCBgc3ByZWFkYCwgYHRha2VgLCBgdGFrZVJpZ2h0YCwgYHRha2VSaWdodFdoaWxlYCxcbiAqIGB0YWtlV2hpbGVgLCBgdGFwYCwgYHRocm90dGxlYCwgYHRocnVgLCBgdGltZXNgLCBgdG9BcnJheWAsIGB0b1BsYWluT2JqZWN0YCxcbiAqIGB0cmFuc2Zvcm1gLCBgdW5pb25gLCBgdW5pcWAsIGB1bnNoaWZ0YCwgYHVuemlwYCwgYHVuemlwV2l0aGAsIGB2YWx1ZXNgLFxuICogYHZhbHVlc0luYCwgYHdoZXJlYCwgYHdpdGhvdXRgLCBgd3JhcGAsIGB4b3JgLCBgemlwYCwgYHppcE9iamVjdGAsIGB6aXBXaXRoYFxuICpcbiAqIFRoZSB3cmFwcGVyIG1ldGhvZHMgdGhhdCBhcmUgKipub3QqKiBjaGFpbmFibGUgYnkgZGVmYXVsdCBhcmU6XG4gKiBgYWRkYCwgYGF0dGVtcHRgLCBgY2FtZWxDYXNlYCwgYGNhcGl0YWxpemVgLCBgY2VpbGAsIGBjbG9uZWAsIGBjbG9uZURlZXBgLFxuICogYGRlYnVycmAsIGBlbmRzV2l0aGAsIGBlc2NhcGVgLCBgZXNjYXBlUmVnRXhwYCwgYGV2ZXJ5YCwgYGZpbmRgLCBgZmluZEluZGV4YCxcbiAqIGBmaW5kS2V5YCwgYGZpbmRMYXN0YCwgYGZpbmRMYXN0SW5kZXhgLCBgZmluZExhc3RLZXlgLCBgZmluZFdoZXJlYCwgYGZpcnN0YCxcbiAqIGBmbG9vcmAsIGBnZXRgLCBgZ3RgLCBgZ3RlYCwgYGhhc2AsIGBpZGVudGl0eWAsIGBpbmNsdWRlc2AsIGBpbmRleE9mYCxcbiAqIGBpblJhbmdlYCwgYGlzQXJndW1lbnRzYCwgYGlzQXJyYXlgLCBgaXNCb29sZWFuYCwgYGlzRGF0ZWAsIGBpc0VsZW1lbnRgLFxuICogYGlzRW1wdHlgLCBgaXNFcXVhbGAsIGBpc0Vycm9yYCwgYGlzRmluaXRlYCBgaXNGdW5jdGlvbmAsIGBpc01hdGNoYCxcbiAqIGBpc05hdGl2ZWAsIGBpc05hTmAsIGBpc051bGxgLCBgaXNOdW1iZXJgLCBgaXNPYmplY3RgLCBgaXNQbGFpbk9iamVjdGAsXG4gKiBgaXNSZWdFeHBgLCBgaXNTdHJpbmdgLCBgaXNVbmRlZmluZWRgLCBgaXNUeXBlZEFycmF5YCwgYGpvaW5gLCBga2ViYWJDYXNlYCxcbiAqIGBsYXN0YCwgYGxhc3RJbmRleE9mYCwgYGx0YCwgYGx0ZWAsIGBtYXhgLCBgbWluYCwgYG5vQ29uZmxpY3RgLCBgbm9vcGAsXG4gKiBgbm93YCwgYHBhZGAsIGBwYWRMZWZ0YCwgYHBhZFJpZ2h0YCwgYHBhcnNlSW50YCwgYHBvcGAsIGByYW5kb21gLCBgcmVkdWNlYCxcbiAqIGByZWR1Y2VSaWdodGAsIGByZXBlYXRgLCBgcmVzdWx0YCwgYHJvdW5kYCwgYHJ1bkluQ29udGV4dGAsIGBzaGlmdGAsIGBzaXplYCxcbiAqIGBzbmFrZUNhc2VgLCBgc29tZWAsIGBzb3J0ZWRJbmRleGAsIGBzb3J0ZWRMYXN0SW5kZXhgLCBgc3RhcnRDYXNlYCxcbiAqIGBzdGFydHNXaXRoYCwgYHN1bWAsIGB0ZW1wbGF0ZWAsIGB0cmltYCwgYHRyaW1MZWZ0YCwgYHRyaW1SaWdodGAsIGB0cnVuY2AsXG4gKiBgdW5lc2NhcGVgLCBgdW5pcXVlSWRgLCBgdmFsdWVgLCBhbmQgYHdvcmRzYFxuICpcbiAqIFRoZSB3cmFwcGVyIG1ldGhvZCBgc2FtcGxlYCB3aWxsIHJldHVybiBhIHdyYXBwZWQgdmFsdWUgd2hlbiBgbmAgaXMgcHJvdmlkZWQsXG4gKiBvdGhlcndpc2UgYW4gdW53cmFwcGVkIHZhbHVlIGlzIHJldHVybmVkLlxuICpcbiAqIEBuYW1lIF9cbiAqIEBjb25zdHJ1Y3RvclxuICogQGNhdGVnb3J5IENoYWluXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB3cmFwIGluIGEgYGxvZGFzaGAgaW5zdGFuY2UuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgYGxvZGFzaGAgd3JhcHBlciBpbnN0YW5jZS5cbiAqIEBleGFtcGxlXG4gKlxuICogdmFyIHdyYXBwZWQgPSBfKFsxLCAyLCAzXSk7XG4gKlxuICogLy8gcmV0dXJucyBhbiB1bndyYXBwZWQgdmFsdWVcbiAqIHdyYXBwZWQucmVkdWNlKGZ1bmN0aW9uKHRvdGFsLCBuKSB7XG4gKiAgIHJldHVybiB0b3RhbCArIG47XG4gKiB9KTtcbiAqIC8vID0+IDZcbiAqXG4gKiAvLyByZXR1cm5zIGEgd3JhcHBlZCB2YWx1ZVxuICogdmFyIHNxdWFyZXMgPSB3cmFwcGVkLm1hcChmdW5jdGlvbihuKSB7XG4gKiAgIHJldHVybiBuICogbjtcbiAqIH0pO1xuICpcbiAqIF8uaXNBcnJheShzcXVhcmVzKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc0FycmF5KHNxdWFyZXMudmFsdWUoKSk7XG4gKiAvLyA9PiB0cnVlXG4gKi9cbmZ1bmN0aW9uIGxvZGFzaCh2YWx1ZSkge1xuICBpZiAoaXNPYmplY3RMaWtlKHZhbHVlKSAmJiAhaXNBcnJheSh2YWx1ZSkgJiYgISh2YWx1ZSBpbnN0YW5jZW9mIExhenlXcmFwcGVyKSkge1xuICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIExvZGFzaFdyYXBwZXIpIHtcbiAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG4gICAgaWYgKGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsICdfX2NoYWluX18nKSAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCAnX193cmFwcGVkX18nKSkge1xuICAgICAgcmV0dXJuIHdyYXBwZXJDbG9uZSh2YWx1ZSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBuZXcgTG9kYXNoV3JhcHBlcih2YWx1ZSk7XG59XG5cbi8vIEVuc3VyZSB3cmFwcGVycyBhcmUgaW5zdGFuY2VzIG9mIGBiYXNlTG9kYXNoYC5cbmxvZGFzaC5wcm90b3R5cGUgPSBiYXNlTG9kYXNoLnByb3RvdHlwZTtcblxubW9kdWxlLmV4cG9ydHMgPSBsb2Rhc2g7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vZm9yRWFjaCcpO1xuIiwidmFyIGJhc2VFYWNoID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvYmFzZUVhY2gnKSxcbiAgICBjcmVhdGVGaW5kID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvY3JlYXRlRmluZCcpO1xuXG4vKipcbiAqIEl0ZXJhdGVzIG92ZXIgZWxlbWVudHMgb2YgYGNvbGxlY3Rpb25gLCByZXR1cm5pbmcgdGhlIGZpcnN0IGVsZW1lbnRcbiAqIGBwcmVkaWNhdGVgIHJldHVybnMgdHJ1dGh5IGZvci4gVGhlIHByZWRpY2F0ZSBpcyBib3VuZCB0byBgdGhpc0FyZ2AgYW5kXG4gKiBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOiAodmFsdWUsIGluZGV4fGtleSwgY29sbGVjdGlvbikuXG4gKlxuICogSWYgYSBwcm9wZXJ0eSBuYW1lIGlzIHByb3ZpZGVkIGZvciBgcHJlZGljYXRlYCB0aGUgY3JlYXRlZCBgXy5wcm9wZXJ0eWBcbiAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICpcbiAqIElmIGEgdmFsdWUgaXMgYWxzbyBwcm92aWRlZCBmb3IgYHRoaXNBcmdgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNQcm9wZXJ0eWBcbiAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgYSBtYXRjaGluZyBwcm9wZXJ0eVxuICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAqXG4gKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGBwcmVkaWNhdGVgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNgIHN0eWxlXG4gKiBjYWxsYmFjayByZXR1cm5zIGB0cnVlYCBmb3IgZWxlbWVudHMgdGhhdCBoYXZlIHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSBnaXZlblxuICogb2JqZWN0LCBlbHNlIGBmYWxzZWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBhbGlhcyBkZXRlY3RcbiAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2VhcmNoLlxuICogQHBhcmFtIHtGdW5jdGlvbnxPYmplY3R8c3RyaW5nfSBbcHJlZGljYXRlPV8uaWRlbnRpdHldIFRoZSBmdW5jdGlvbiBpbnZva2VkXG4gKiAgcGVyIGl0ZXJhdGlvbi5cbiAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgcHJlZGljYXRlYC5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBtYXRjaGVkIGVsZW1lbnQsIGVsc2UgYHVuZGVmaW5lZGAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIHZhciB1c2VycyA9IFtcbiAqICAgeyAndXNlcic6ICdiYXJuZXknLCAgJ2FnZSc6IDM2LCAnYWN0aXZlJzogdHJ1ZSB9LFxuICogICB7ICd1c2VyJzogJ2ZyZWQnLCAgICAnYWdlJzogNDAsICdhY3RpdmUnOiBmYWxzZSB9LFxuICogICB7ICd1c2VyJzogJ3BlYmJsZXMnLCAnYWdlJzogMSwgICdhY3RpdmUnOiB0cnVlIH1cbiAqIF07XG4gKlxuICogXy5yZXN1bHQoXy5maW5kKHVzZXJzLCBmdW5jdGlvbihjaHIpIHtcbiAqICAgcmV0dXJuIGNoci5hZ2UgPCA0MDtcbiAqIH0pLCAndXNlcicpO1xuICogLy8gPT4gJ2Jhcm5leSdcbiAqXG4gKiAvLyB1c2luZyB0aGUgYF8ubWF0Y2hlc2AgY2FsbGJhY2sgc2hvcnRoYW5kXG4gKiBfLnJlc3VsdChfLmZpbmQodXNlcnMsIHsgJ2FnZSc6IDEsICdhY3RpdmUnOiB0cnVlIH0pLCAndXNlcicpO1xuICogLy8gPT4gJ3BlYmJsZXMnXG4gKlxuICogLy8gdXNpbmcgdGhlIGBfLm1hdGNoZXNQcm9wZXJ0eWAgY2FsbGJhY2sgc2hvcnRoYW5kXG4gKiBfLnJlc3VsdChfLmZpbmQodXNlcnMsICdhY3RpdmUnLCBmYWxzZSksICd1c2VyJyk7XG4gKiAvLyA9PiAnZnJlZCdcbiAqXG4gKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICogXy5yZXN1bHQoXy5maW5kKHVzZXJzLCAnYWN0aXZlJyksICd1c2VyJyk7XG4gKiAvLyA9PiAnYmFybmV5J1xuICovXG52YXIgZmluZCA9IGNyZWF0ZUZpbmQoYmFzZUVhY2gpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZpbmQ7XG4iLCJ2YXIgYXJyYXlFYWNoID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvYXJyYXlFYWNoJyksXG4gICAgYmFzZUVhY2ggPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9iYXNlRWFjaCcpLFxuICAgIGNyZWF0ZUZvckVhY2ggPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9jcmVhdGVGb3JFYWNoJyk7XG5cbi8qKlxuICogSXRlcmF0ZXMgb3ZlciBlbGVtZW50cyBvZiBgY29sbGVjdGlvbmAgaW52b2tpbmcgYGl0ZXJhdGVlYCBmb3IgZWFjaCBlbGVtZW50LlxuICogVGhlIGBpdGVyYXRlZWAgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWUgYXJndW1lbnRzOlxuICogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLiBJdGVyYXRlZSBmdW5jdGlvbnMgbWF5IGV4aXQgaXRlcmF0aW9uIGVhcmx5XG4gKiBieSBleHBsaWNpdGx5IHJldHVybmluZyBgZmFsc2VgLlxuICpcbiAqICoqTm90ZToqKiBBcyB3aXRoIG90aGVyIFwiQ29sbGVjdGlvbnNcIiBtZXRob2RzLCBvYmplY3RzIHdpdGggYSBcImxlbmd0aFwiIHByb3BlcnR5XG4gKiBhcmUgaXRlcmF0ZWQgbGlrZSBhcnJheXMuIFRvIGF2b2lkIHRoaXMgYmVoYXZpb3IgYF8uZm9ySW5gIG9yIGBfLmZvck93bmBcbiAqIG1heSBiZSB1c2VkIGZvciBvYmplY3QgaXRlcmF0aW9uLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAYWxpYXMgZWFjaFxuICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbaXRlcmF0ZWU9Xy5pZGVudGl0eV0gVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgaXRlcmF0ZWVgLlxuICogQHJldHVybnMge0FycmF5fE9iamVjdHxzdHJpbmd9IFJldHVybnMgYGNvbGxlY3Rpb25gLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfKFsxLCAyXSkuZm9yRWFjaChmdW5jdGlvbihuKSB7XG4gKiAgIGNvbnNvbGUubG9nKG4pO1xuICogfSkudmFsdWUoKTtcbiAqIC8vID0+IGxvZ3MgZWFjaCB2YWx1ZSBmcm9tIGxlZnQgdG8gcmlnaHQgYW5kIHJldHVybnMgdGhlIGFycmF5XG4gKlxuICogXy5mb3JFYWNoKHsgJ2EnOiAxLCAnYic6IDIgfSwgZnVuY3Rpb24obiwga2V5KSB7XG4gKiAgIGNvbnNvbGUubG9nKG4sIGtleSk7XG4gKiB9KTtcbiAqIC8vID0+IGxvZ3MgZWFjaCB2YWx1ZS1rZXkgcGFpciBhbmQgcmV0dXJucyB0aGUgb2JqZWN0IChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gKi9cbnZhciBmb3JFYWNoID0gY3JlYXRlRm9yRWFjaChhcnJheUVhY2gsIGJhc2VFYWNoKTtcblxubW9kdWxlLmV4cG9ydHMgPSBmb3JFYWNoO1xuIiwidmFyIGJhc2VJbmRleE9mID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvYmFzZUluZGV4T2YnKSxcbiAgICBnZXRMZW5ndGggPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9nZXRMZW5ndGgnKSxcbiAgICBpc0FycmF5ID0gcmVxdWlyZSgnLi4vbGFuZy9pc0FycmF5JyksXG4gICAgaXNJdGVyYXRlZUNhbGwgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9pc0l0ZXJhdGVlQ2FsbCcpLFxuICAgIGlzTGVuZ3RoID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvaXNMZW5ndGgnKSxcbiAgICBpc1N0cmluZyA9IHJlcXVpcmUoJy4uL2xhbmcvaXNTdHJpbmcnKSxcbiAgICB2YWx1ZXMgPSByZXF1aXJlKCcuLi9vYmplY3QvdmFsdWVzJyk7XG5cbi8qIE5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlTWF4ID0gTWF0aC5tYXg7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB0YXJnZXRgIGlzIGluIGBjb2xsZWN0aW9uYCB1c2luZ1xuICogW2BTYW1lVmFsdWVaZXJvYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtc2FtZXZhbHVlemVybylcbiAqIGZvciBlcXVhbGl0eSBjb21wYXJpc29ucy4gSWYgYGZyb21JbmRleGAgaXMgbmVnYXRpdmUsIGl0J3MgdXNlZCBhcyB0aGUgb2Zmc2V0XG4gKiBmcm9tIHRoZSBlbmQgb2YgYGNvbGxlY3Rpb25gLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAYWxpYXMgY29udGFpbnMsIGluY2x1ZGVcbiAqIEBjYXRlZ29yeSBDb2xsZWN0aW9uXG4gKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gc2VhcmNoLlxuICogQHBhcmFtIHsqfSB0YXJnZXQgVGhlIHZhbHVlIHRvIHNlYXJjaCBmb3IuXG4gKiBAcGFyYW0ge251bWJlcn0gW2Zyb21JbmRleD0wXSBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gKiBAcGFyYW0tIHtPYmplY3R9IFtndWFyZF0gRW5hYmxlcyB1c2UgYXMgYSBjYWxsYmFjayBmb3IgZnVuY3Rpb25zIGxpa2UgYF8ucmVkdWNlYC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBhIG1hdGNoaW5nIGVsZW1lbnQgaXMgZm91bmQsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pbmNsdWRlcyhbMSwgMiwgM10sIDEpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaW5jbHVkZXMoWzEsIDIsIDNdLCAxLCAyKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pbmNsdWRlcyh7ICd1c2VyJzogJ2ZyZWQnLCAnYWdlJzogNDAgfSwgJ2ZyZWQnKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmluY2x1ZGVzKCdwZWJibGVzJywgJ2ViJyk7XG4gKiAvLyA9PiB0cnVlXG4gKi9cbmZ1bmN0aW9uIGluY2x1ZGVzKGNvbGxlY3Rpb24sIHRhcmdldCwgZnJvbUluZGV4LCBndWFyZCkge1xuICB2YXIgbGVuZ3RoID0gY29sbGVjdGlvbiA/IGdldExlbmd0aChjb2xsZWN0aW9uKSA6IDA7XG4gIGlmICghaXNMZW5ndGgobGVuZ3RoKSkge1xuICAgIGNvbGxlY3Rpb24gPSB2YWx1ZXMoY29sbGVjdGlvbik7XG4gICAgbGVuZ3RoID0gY29sbGVjdGlvbi5sZW5ndGg7XG4gIH1cbiAgaWYgKHR5cGVvZiBmcm9tSW5kZXggIT0gJ251bWJlcicgfHwgKGd1YXJkICYmIGlzSXRlcmF0ZWVDYWxsKHRhcmdldCwgZnJvbUluZGV4LCBndWFyZCkpKSB7XG4gICAgZnJvbUluZGV4ID0gMDtcbiAgfSBlbHNlIHtcbiAgICBmcm9tSW5kZXggPSBmcm9tSW5kZXggPCAwID8gbmF0aXZlTWF4KGxlbmd0aCArIGZyb21JbmRleCwgMCkgOiAoZnJvbUluZGV4IHx8IDApO1xuICB9XG4gIHJldHVybiAodHlwZW9mIGNvbGxlY3Rpb24gPT0gJ3N0cmluZycgfHwgIWlzQXJyYXkoY29sbGVjdGlvbikgJiYgaXNTdHJpbmcoY29sbGVjdGlvbikpXG4gICAgPyAoZnJvbUluZGV4IDw9IGxlbmd0aCAmJiBjb2xsZWN0aW9uLmluZGV4T2YodGFyZ2V0LCBmcm9tSW5kZXgpID4gLTEpXG4gICAgOiAoISFsZW5ndGggJiYgYmFzZUluZGV4T2YoY29sbGVjdGlvbiwgdGFyZ2V0LCBmcm9tSW5kZXgpID4gLTEpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGluY2x1ZGVzO1xuIiwidmFyIGFycmF5TWFwID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvYXJyYXlNYXAnKSxcbiAgICBiYXNlQ2FsbGJhY2sgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9iYXNlQ2FsbGJhY2snKSxcbiAgICBiYXNlTWFwID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvYmFzZU1hcCcpLFxuICAgIGlzQXJyYXkgPSByZXF1aXJlKCcuLi9sYW5nL2lzQXJyYXknKTtcblxuLyoqXG4gKiBDcmVhdGVzIGFuIGFycmF5IG9mIHZhbHVlcyBieSBydW5uaW5nIGVhY2ggZWxlbWVudCBpbiBgY29sbGVjdGlvbmAgdGhyb3VnaFxuICogYGl0ZXJhdGVlYC4gVGhlIGBpdGVyYXRlZWAgaXMgYm91bmQgdG8gYHRoaXNBcmdgIGFuZCBpbnZva2VkIHdpdGggdGhyZWVcbiAqIGFyZ3VtZW50czogKHZhbHVlLCBpbmRleHxrZXksIGNvbGxlY3Rpb24pLlxuICpcbiAqIElmIGEgcHJvcGVydHkgbmFtZSBpcyBwcm92aWRlZCBmb3IgYGl0ZXJhdGVlYCB0aGUgY3JlYXRlZCBgXy5wcm9wZXJ0eWBcbiAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlIG9mIHRoZSBnaXZlbiBlbGVtZW50LlxuICpcbiAqIElmIGEgdmFsdWUgaXMgYWxzbyBwcm92aWRlZCBmb3IgYHRoaXNBcmdgIHRoZSBjcmVhdGVkIGBfLm1hdGNoZXNQcm9wZXJ0eWBcbiAqIHN0eWxlIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgYSBtYXRjaGluZyBwcm9wZXJ0eVxuICogdmFsdWUsIGVsc2UgYGZhbHNlYC5cbiAqXG4gKiBJZiBhbiBvYmplY3QgaXMgcHJvdmlkZWQgZm9yIGBpdGVyYXRlZWAgdGhlIGNyZWF0ZWQgYF8ubWF0Y2hlc2Agc3R5bGVcbiAqIGNhbGxiYWNrIHJldHVybnMgYHRydWVgIGZvciBlbGVtZW50cyB0aGF0IGhhdmUgdGhlIHByb3BlcnRpZXMgb2YgdGhlIGdpdmVuXG4gKiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAqXG4gKiBNYW55IGxvZGFzaCBtZXRob2RzIGFyZSBndWFyZGVkIHRvIHdvcmsgYXMgaXRlcmF0ZWVzIGZvciBtZXRob2RzIGxpa2VcbiAqIGBfLmV2ZXJ5YCwgYF8uZmlsdGVyYCwgYF8ubWFwYCwgYF8ubWFwVmFsdWVzYCwgYF8ucmVqZWN0YCwgYW5kIGBfLnNvbWVgLlxuICpcbiAqIFRoZSBndWFyZGVkIG1ldGhvZHMgYXJlOlxuICogYGFyeWAsIGBjYWxsYmFja2AsIGBjaHVua2AsIGBjbG9uZWAsIGBjcmVhdGVgLCBgY3VycnlgLCBgY3VycnlSaWdodGAsXG4gKiBgZHJvcGAsIGBkcm9wUmlnaHRgLCBgZXZlcnlgLCBgZmlsbGAsIGBmbGF0dGVuYCwgYGludmVydGAsIGBtYXhgLCBgbWluYCxcbiAqIGBwYXJzZUludGAsIGBzbGljZWAsIGBzb3J0QnlgLCBgdGFrZWAsIGB0YWtlUmlnaHRgLCBgdGVtcGxhdGVgLCBgdHJpbWAsXG4gKiBgdHJpbUxlZnRgLCBgdHJpbVJpZ2h0YCwgYHRydW5jYCwgYHJhbmRvbWAsIGByYW5nZWAsIGBzYW1wbGVgLCBgc29tZWAsXG4gKiBgc3VtYCwgYHVuaXFgLCBhbmQgYHdvcmRzYFxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAYWxpYXMgY29sbGVjdFxuICogQGNhdGVnb3J5IENvbGxlY3Rpb25cbiAqIEBwYXJhbSB7QXJyYXl8T2JqZWN0fHN0cmluZ30gY29sbGVjdGlvbiBUaGUgY29sbGVjdGlvbiB0byBpdGVyYXRlIG92ZXIuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufE9iamVjdHxzdHJpbmd9IFtpdGVyYXRlZT1fLmlkZW50aXR5XSBUaGUgZnVuY3Rpb24gaW52b2tlZFxuICogIHBlciBpdGVyYXRpb24uXG4gKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGl0ZXJhdGVlYC5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBhcnJheS5cbiAqIEBleGFtcGxlXG4gKlxuICogZnVuY3Rpb24gdGltZXNUaHJlZShuKSB7XG4gKiAgIHJldHVybiBuICogMztcbiAqIH1cbiAqXG4gKiBfLm1hcChbMSwgMl0sIHRpbWVzVGhyZWUpO1xuICogLy8gPT4gWzMsIDZdXG4gKlxuICogXy5tYXAoeyAnYSc6IDEsICdiJzogMiB9LCB0aW1lc1RocmVlKTtcbiAqIC8vID0+IFszLCA2XSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICpcbiAqIHZhciB1c2VycyA9IFtcbiAqICAgeyAndXNlcic6ICdiYXJuZXknIH0sXG4gKiAgIHsgJ3VzZXInOiAnZnJlZCcgfVxuICogXTtcbiAqXG4gKiAvLyB1c2luZyB0aGUgYF8ucHJvcGVydHlgIGNhbGxiYWNrIHNob3J0aGFuZFxuICogXy5tYXAodXNlcnMsICd1c2VyJyk7XG4gKiAvLyA9PiBbJ2Jhcm5leScsICdmcmVkJ11cbiAqL1xuZnVuY3Rpb24gbWFwKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCB0aGlzQXJnKSB7XG4gIHZhciBmdW5jID0gaXNBcnJheShjb2xsZWN0aW9uKSA/IGFycmF5TWFwIDogYmFzZU1hcDtcbiAgaXRlcmF0ZWUgPSBiYXNlQ2FsbGJhY2soaXRlcmF0ZWUsIHRoaXNBcmcsIDMpO1xuICByZXR1cm4gZnVuYyhjb2xsZWN0aW9uLCBpdGVyYXRlZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gbWFwO1xuIiwidmFyIGdldE5hdGl2ZSA9IHJlcXVpcmUoJy4uL2ludGVybmFsL2dldE5hdGl2ZScpO1xuXG4vKiBOYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xudmFyIG5hdGl2ZU5vdyA9IGdldE5hdGl2ZShEYXRlLCAnbm93Jyk7XG5cbi8qKlxuICogR2V0cyB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0aGF0IGhhdmUgZWxhcHNlZCBzaW5jZSB0aGUgVW5peCBlcG9jaFxuICogKDEgSmFudWFyeSAxOTcwIDAwOjAwOjAwIFVUQykuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBjYXRlZ29yeSBEYXRlXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uZGVmZXIoZnVuY3Rpb24oc3RhbXApIHtcbiAqICAgY29uc29sZS5sb2coXy5ub3coKSAtIHN0YW1wKTtcbiAqIH0sIF8ubm93KCkpO1xuICogLy8gPT4gbG9ncyB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBpdCB0b29rIGZvciB0aGUgZGVmZXJyZWQgZnVuY3Rpb24gdG8gYmUgaW52b2tlZFxuICovXG52YXIgbm93ID0gbmF0aXZlTm93IHx8IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IG5vdztcbiIsInZhciBjcmVhdGVXcmFwcGVyID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvY3JlYXRlV3JhcHBlcicpLFxuICAgIHJlcGxhY2VIb2xkZXJzID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvcmVwbGFjZUhvbGRlcnMnKSxcbiAgICByZXN0UGFyYW0gPSByZXF1aXJlKCcuL3Jlc3RQYXJhbScpO1xuXG4vKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciB3cmFwcGVyIG1ldGFkYXRhLiAqL1xudmFyIEJJTkRfRkxBRyA9IDEsXG4gICAgUEFSVElBTF9GTEFHID0gMzI7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgaW52b2tlcyBgZnVuY2Agd2l0aCB0aGUgYHRoaXNgIGJpbmRpbmcgb2YgYHRoaXNBcmdgXG4gKiBhbmQgcHJlcGVuZHMgYW55IGFkZGl0aW9uYWwgYF8uYmluZGAgYXJndW1lbnRzIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZVxuICogYm91bmQgZnVuY3Rpb24uXG4gKlxuICogVGhlIGBfLmJpbmQucGxhY2Vob2xkZXJgIHZhbHVlLCB3aGljaCBkZWZhdWx0cyB0byBgX2AgaW4gbW9ub2xpdGhpYyBidWlsZHMsXG4gKiBtYXkgYmUgdXNlZCBhcyBhIHBsYWNlaG9sZGVyIGZvciBwYXJ0aWFsbHkgYXBwbGllZCBhcmd1bWVudHMuXG4gKlxuICogKipOb3RlOioqIFVubGlrZSBuYXRpdmUgYEZ1bmN0aW9uI2JpbmRgIHRoaXMgbWV0aG9kIGRvZXMgbm90IHNldCB0aGUgXCJsZW5ndGhcIlxuICogcHJvcGVydHkgb2YgYm91bmQgZnVuY3Rpb25zLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGJpbmQuXG4gKiBAcGFyYW0geyp9IHRoaXNBcmcgVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAqIEBwYXJhbSB7Li4uKn0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYm91bmQgZnVuY3Rpb24uXG4gKiBAZXhhbXBsZVxuICpcbiAqIHZhciBncmVldCA9IGZ1bmN0aW9uKGdyZWV0aW5nLCBwdW5jdHVhdGlvbikge1xuICogICByZXR1cm4gZ3JlZXRpbmcgKyAnICcgKyB0aGlzLnVzZXIgKyBwdW5jdHVhdGlvbjtcbiAqIH07XG4gKlxuICogdmFyIG9iamVjdCA9IHsgJ3VzZXInOiAnZnJlZCcgfTtcbiAqXG4gKiB2YXIgYm91bmQgPSBfLmJpbmQoZ3JlZXQsIG9iamVjdCwgJ2hpJyk7XG4gKiBib3VuZCgnIScpO1xuICogLy8gPT4gJ2hpIGZyZWQhJ1xuICpcbiAqIC8vIHVzaW5nIHBsYWNlaG9sZGVyc1xuICogdmFyIGJvdW5kID0gXy5iaW5kKGdyZWV0LCBvYmplY3QsIF8sICchJyk7XG4gKiBib3VuZCgnaGknKTtcbiAqIC8vID0+ICdoaSBmcmVkISdcbiAqL1xudmFyIGJpbmQgPSByZXN0UGFyYW0oZnVuY3Rpb24oZnVuYywgdGhpc0FyZywgcGFydGlhbHMpIHtcbiAgdmFyIGJpdG1hc2sgPSBCSU5EX0ZMQUc7XG4gIGlmIChwYXJ0aWFscy5sZW5ndGgpIHtcbiAgICB2YXIgaG9sZGVycyA9IHJlcGxhY2VIb2xkZXJzKHBhcnRpYWxzLCBiaW5kLnBsYWNlaG9sZGVyKTtcbiAgICBiaXRtYXNrIHw9IFBBUlRJQUxfRkxBRztcbiAgfVxuICByZXR1cm4gY3JlYXRlV3JhcHBlcihmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscywgaG9sZGVycyk7XG59KTtcblxuLy8gQXNzaWduIGRlZmF1bHQgcGxhY2Vob2xkZXJzLlxuYmluZC5wbGFjZWhvbGRlciA9IHt9O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGJpbmQ7XG4iLCIvKiogVXNlZCBhcyB0aGUgYFR5cGVFcnJvcmAgbWVzc2FnZSBmb3IgXCJGdW5jdGlvbnNcIiBtZXRob2RzLiAqL1xudmFyIEZVTkNfRVJST1JfVEVYVCA9ICdFeHBlY3RlZCBhIGZ1bmN0aW9uJztcblxuLyogTmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVNYXggPSBNYXRoLm1heDtcblxuLyoqXG4gKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBpbnZva2VzIGBmdW5jYCB3aXRoIHRoZSBgdGhpc2AgYmluZGluZyBvZiB0aGVcbiAqIGNyZWF0ZWQgZnVuY3Rpb24gYW5kIGFyZ3VtZW50cyBmcm9tIGBzdGFydGAgYW5kIGJleW9uZCBwcm92aWRlZCBhcyBhbiBhcnJheS5cbiAqXG4gKiAqKk5vdGU6KiogVGhpcyBtZXRob2QgaXMgYmFzZWQgb24gdGhlIFtyZXN0IHBhcmFtZXRlcl0oaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0Z1bmN0aW9ucy9yZXN0X3BhcmFtZXRlcnMpLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFwcGx5IGEgcmVzdCBwYXJhbWV0ZXIgdG8uXG4gKiBAcGFyYW0ge251bWJlcn0gW3N0YXJ0PWZ1bmMubGVuZ3RoLTFdIFRoZSBzdGFydCBwb3NpdGlvbiBvZiB0aGUgcmVzdCBwYXJhbWV0ZXIuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAqIEBleGFtcGxlXG4gKlxuICogdmFyIHNheSA9IF8ucmVzdFBhcmFtKGZ1bmN0aW9uKHdoYXQsIG5hbWVzKSB7XG4gKiAgIHJldHVybiB3aGF0ICsgJyAnICsgXy5pbml0aWFsKG5hbWVzKS5qb2luKCcsICcpICtcbiAqICAgICAoXy5zaXplKG5hbWVzKSA+IDEgPyAnLCAmICcgOiAnJykgKyBfLmxhc3QobmFtZXMpO1xuICogfSk7XG4gKlxuICogc2F5KCdoZWxsbycsICdmcmVkJywgJ2Jhcm5leScsICdwZWJibGVzJyk7XG4gKiAvLyA9PiAnaGVsbG8gZnJlZCwgYmFybmV5LCAmIHBlYmJsZXMnXG4gKi9cbmZ1bmN0aW9uIHJlc3RQYXJhbShmdW5jLCBzdGFydCkge1xuICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgfVxuICBzdGFydCA9IG5hdGl2ZU1heChzdGFydCA9PT0gdW5kZWZpbmVkID8gKGZ1bmMubGVuZ3RoIC0gMSkgOiAoK3N0YXJ0IHx8IDApLCAwKTtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHZhciBhcmdzID0gYXJndW1lbnRzLFxuICAgICAgICBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSBuYXRpdmVNYXgoYXJncy5sZW5ndGggLSBzdGFydCwgMCksXG4gICAgICAgIHJlc3QgPSBBcnJheShsZW5ndGgpO1xuXG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgIHJlc3RbaW5kZXhdID0gYXJnc1tzdGFydCArIGluZGV4XTtcbiAgICB9XG4gICAgc3dpdGNoIChzdGFydCkge1xuICAgICAgY2FzZSAwOiByZXR1cm4gZnVuYy5jYWxsKHRoaXMsIHJlc3QpO1xuICAgICAgY2FzZSAxOiByZXR1cm4gZnVuYy5jYWxsKHRoaXMsIGFyZ3NbMF0sIHJlc3QpO1xuICAgICAgY2FzZSAyOiByZXR1cm4gZnVuYy5jYWxsKHRoaXMsIGFyZ3NbMF0sIGFyZ3NbMV0sIHJlc3QpO1xuICAgIH1cbiAgICB2YXIgb3RoZXJBcmdzID0gQXJyYXkoc3RhcnQgKyAxKTtcbiAgICBpbmRleCA9IC0xO1xuICAgIHdoaWxlICgrK2luZGV4IDwgc3RhcnQpIHtcbiAgICAgIG90aGVyQXJnc1tpbmRleF0gPSBhcmdzW2luZGV4XTtcbiAgICB9XG4gICAgb3RoZXJBcmdzW3N0YXJ0XSA9IHJlc3Q7XG4gICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgb3RoZXJBcmdzKTtcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSByZXN0UGFyYW07XG4iLCJ2YXIgYmFzZUNyZWF0ZSA9IHJlcXVpcmUoJy4vYmFzZUNyZWF0ZScpLFxuICAgIGJhc2VMb2Rhc2ggPSByZXF1aXJlKCcuL2Jhc2VMb2Rhc2gnKTtcblxuLyoqIFVzZWQgYXMgcmVmZXJlbmNlcyBmb3IgYC1JbmZpbml0eWAgYW5kIGBJbmZpbml0eWAuICovXG52YXIgUE9TSVRJVkVfSU5GSU5JVFkgPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGxhenkgd3JhcHBlciBvYmplY3Qgd2hpY2ggd3JhcHMgYHZhbHVlYCB0byBlbmFibGUgbGF6eSBldmFsdWF0aW9uLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB3cmFwLlxuICovXG5mdW5jdGlvbiBMYXp5V3JhcHBlcih2YWx1ZSkge1xuICB0aGlzLl9fd3JhcHBlZF9fID0gdmFsdWU7XG4gIHRoaXMuX19hY3Rpb25zX18gPSBbXTtcbiAgdGhpcy5fX2Rpcl9fID0gMTtcbiAgdGhpcy5fX2ZpbHRlcmVkX18gPSBmYWxzZTtcbiAgdGhpcy5fX2l0ZXJhdGVlc19fID0gW107XG4gIHRoaXMuX190YWtlQ291bnRfXyA9IFBPU0lUSVZFX0lORklOSVRZO1xuICB0aGlzLl9fdmlld3NfXyA9IFtdO1xufVxuXG5MYXp5V3JhcHBlci5wcm90b3R5cGUgPSBiYXNlQ3JlYXRlKGJhc2VMb2Rhc2gucHJvdG90eXBlKTtcbkxhenlXcmFwcGVyLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IExhenlXcmFwcGVyO1xuXG5tb2R1bGUuZXhwb3J0cyA9IExhenlXcmFwcGVyO1xuIiwidmFyIGJhc2VDcmVhdGUgPSByZXF1aXJlKCcuL2Jhc2VDcmVhdGUnKSxcbiAgICBiYXNlTG9kYXNoID0gcmVxdWlyZSgnLi9iYXNlTG9kYXNoJyk7XG5cbi8qKlxuICogVGhlIGJhc2UgY29uc3RydWN0b3IgZm9yIGNyZWF0aW5nIGBsb2Rhc2hgIHdyYXBwZXIgb2JqZWN0cy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gd3JhcC5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2NoYWluQWxsXSBFbmFibGUgY2hhaW5pbmcgZm9yIGFsbCB3cmFwcGVyIG1ldGhvZHMuXG4gKiBAcGFyYW0ge0FycmF5fSBbYWN0aW9ucz1bXV0gQWN0aW9ucyB0byBwZWZvcm0gdG8gcmVzb2x2ZSB0aGUgdW53cmFwcGVkIHZhbHVlLlxuICovXG5mdW5jdGlvbiBMb2Rhc2hXcmFwcGVyKHZhbHVlLCBjaGFpbkFsbCwgYWN0aW9ucykge1xuICB0aGlzLl9fd3JhcHBlZF9fID0gdmFsdWU7XG4gIHRoaXMuX19hY3Rpb25zX18gPSBhY3Rpb25zIHx8IFtdO1xuICB0aGlzLl9fY2hhaW5fXyA9ICEhY2hhaW5BbGw7XG59XG5cbkxvZGFzaFdyYXBwZXIucHJvdG90eXBlID0gYmFzZUNyZWF0ZShiYXNlTG9kYXNoLnByb3RvdHlwZSk7XG5Mb2Rhc2hXcmFwcGVyLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IExvZGFzaFdyYXBwZXI7XG5cbm1vZHVsZS5leHBvcnRzID0gTG9kYXNoV3JhcHBlcjtcbiIsIi8qKlxuICogQ29waWVzIHRoZSB2YWx1ZXMgb2YgYHNvdXJjZWAgdG8gYGFycmF5YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gc291cmNlIFRoZSBhcnJheSB0byBjb3B5IHZhbHVlcyBmcm9tLlxuICogQHBhcmFtIHtBcnJheX0gW2FycmF5PVtdXSBUaGUgYXJyYXkgdG8gY29weSB2YWx1ZXMgdG8uXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGFycmF5YC5cbiAqL1xuZnVuY3Rpb24gYXJyYXlDb3B5KHNvdXJjZSwgYXJyYXkpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICBsZW5ndGggPSBzb3VyY2UubGVuZ3RoO1xuXG4gIGFycmF5IHx8IChhcnJheSA9IEFycmF5KGxlbmd0aCkpO1xuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIGFycmF5W2luZGV4XSA9IHNvdXJjZVtpbmRleF07XG4gIH1cbiAgcmV0dXJuIGFycmF5O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGFycmF5Q29weTtcbiIsIi8qKlxuICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBfLmZvckVhY2hgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICogc2hvcnRoYW5kcyBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gKi9cbmZ1bmN0aW9uIGFycmF5RWFjaChhcnJheSwgaXRlcmF0ZWUpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICBpZiAoaXRlcmF0ZWUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpID09PSBmYWxzZSkge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHJldHVybiBhcnJheTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBhcnJheUVhY2g7XG4iLCIvKipcbiAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgXy5tYXBgIGZvciBhcnJheXMgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICogc2hvcnRoYW5kcyBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBpdGVyYXRlIG92ZXIuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgbWFwcGVkIGFycmF5LlxuICovXG5mdW5jdGlvbiBhcnJheU1hcChhcnJheSwgaXRlcmF0ZWUpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgcmVzdWx0W2luZGV4XSA9IGl0ZXJhdGVlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGFycmF5TWFwO1xuIiwiLyoqXG4gKiBBIHNwZWNpYWxpemVkIHZlcnNpb24gb2YgYF8uc29tZWAgZm9yIGFycmF5cyB3aXRob3V0IHN1cHBvcnQgZm9yIGNhbGxiYWNrXG4gKiBzaG9ydGhhbmRzIGFuZCBgdGhpc2AgYmluZGluZy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIGl0ZXJhdGUgb3Zlci5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGFueSBlbGVtZW50IHBhc3NlcyB0aGUgcHJlZGljYXRlIGNoZWNrLFxuICogIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gYXJyYXlTb21lKGFycmF5LCBwcmVkaWNhdGUpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG5cbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICBpZiAocHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBhcnJheVNvbWU7XG4iLCJ2YXIgYmFzZUNvcHkgPSByZXF1aXJlKCcuL2Jhc2VDb3B5JyksXG4gICAga2V5cyA9IHJlcXVpcmUoJy4uL29iamVjdC9rZXlzJyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uYXNzaWduYCB3aXRob3V0IHN1cHBvcnQgZm9yIGFyZ3VtZW50IGp1Z2dsaW5nLFxuICogbXVsdGlwbGUgc291cmNlcywgYW5kIGBjdXN0b21pemVyYCBmdW5jdGlvbnMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIGRlc3RpbmF0aW9uIG9iamVjdC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIHNvdXJjZSBvYmplY3QuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIGBvYmplY3RgLlxuICovXG5mdW5jdGlvbiBiYXNlQXNzaWduKG9iamVjdCwgc291cmNlKSB7XG4gIHJldHVybiBzb3VyY2UgPT0gbnVsbFxuICAgID8gb2JqZWN0XG4gICAgOiBiYXNlQ29weShzb3VyY2UsIGtleXMoc291cmNlKSwgb2JqZWN0KTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlQXNzaWduO1xuIiwidmFyIGJhc2VNYXRjaGVzID0gcmVxdWlyZSgnLi9iYXNlTWF0Y2hlcycpLFxuICAgIGJhc2VNYXRjaGVzUHJvcGVydHkgPSByZXF1aXJlKCcuL2Jhc2VNYXRjaGVzUHJvcGVydHknKSxcbiAgICBiaW5kQ2FsbGJhY2sgPSByZXF1aXJlKCcuL2JpbmRDYWxsYmFjaycpLFxuICAgIGlkZW50aXR5ID0gcmVxdWlyZSgnLi4vdXRpbGl0eS9pZGVudGl0eScpLFxuICAgIHByb3BlcnR5ID0gcmVxdWlyZSgnLi4vdXRpbGl0eS9wcm9wZXJ0eScpO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmNhbGxiYWNrYCB3aGljaCBzdXBwb3J0cyBzcGVjaWZ5aW5nIHRoZVxuICogbnVtYmVyIG9mIGFyZ3VtZW50cyB0byBwcm92aWRlIHRvIGBmdW5jYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSBbZnVuYz1fLmlkZW50aXR5XSBUaGUgdmFsdWUgdG8gY29udmVydCB0byBhIGNhbGxiYWNrLlxuICogQHBhcmFtIHsqfSBbdGhpc0FyZ10gVGhlIGB0aGlzYCBiaW5kaW5nIG9mIGBmdW5jYC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbYXJnQ291bnRdIFRoZSBudW1iZXIgb2YgYXJndW1lbnRzIHRvIHByb3ZpZGUgdG8gYGZ1bmNgLlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBjYWxsYmFjay5cbiAqL1xuZnVuY3Rpb24gYmFzZUNhbGxiYWNrKGZ1bmMsIHRoaXNBcmcsIGFyZ0NvdW50KSB7XG4gIHZhciB0eXBlID0gdHlwZW9mIGZ1bmM7XG4gIGlmICh0eXBlID09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gdGhpc0FyZyA9PT0gdW5kZWZpbmVkXG4gICAgICA/IGZ1bmNcbiAgICAgIDogYmluZENhbGxiYWNrKGZ1bmMsIHRoaXNBcmcsIGFyZ0NvdW50KTtcbiAgfVxuICBpZiAoZnVuYyA9PSBudWxsKSB7XG4gICAgcmV0dXJuIGlkZW50aXR5O1xuICB9XG4gIGlmICh0eXBlID09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIGJhc2VNYXRjaGVzKGZ1bmMpO1xuICB9XG4gIHJldHVybiB0aGlzQXJnID09PSB1bmRlZmluZWRcbiAgICA/IHByb3BlcnR5KGZ1bmMpXG4gICAgOiBiYXNlTWF0Y2hlc1Byb3BlcnR5KGZ1bmMsIHRoaXNBcmcpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VDYWxsYmFjaztcbiIsInZhciBhcnJheUNvcHkgPSByZXF1aXJlKCcuL2FycmF5Q29weScpLFxuICAgIGFycmF5RWFjaCA9IHJlcXVpcmUoJy4vYXJyYXlFYWNoJyksXG4gICAgYmFzZUFzc2lnbiA9IHJlcXVpcmUoJy4vYmFzZUFzc2lnbicpLFxuICAgIGJhc2VGb3JPd24gPSByZXF1aXJlKCcuL2Jhc2VGb3JPd24nKSxcbiAgICBpbml0Q2xvbmVBcnJheSA9IHJlcXVpcmUoJy4vaW5pdENsb25lQXJyYXknKSxcbiAgICBpbml0Q2xvbmVCeVRhZyA9IHJlcXVpcmUoJy4vaW5pdENsb25lQnlUYWcnKSxcbiAgICBpbml0Q2xvbmVPYmplY3QgPSByZXF1aXJlKCcuL2luaXRDbG9uZU9iamVjdCcpLFxuICAgIGlzQXJyYXkgPSByZXF1aXJlKCcuLi9sYW5nL2lzQXJyYXknKSxcbiAgICBpc0hvc3RPYmplY3QgPSByZXF1aXJlKCcuL2lzSG9zdE9iamVjdCcpLFxuICAgIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi4vbGFuZy9pc09iamVjdCcpO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgYXJnc1RhZyA9ICdbb2JqZWN0IEFyZ3VtZW50c10nLFxuICAgIGFycmF5VGFnID0gJ1tvYmplY3QgQXJyYXldJyxcbiAgICBib29sVGFnID0gJ1tvYmplY3QgQm9vbGVhbl0nLFxuICAgIGRhdGVUYWcgPSAnW29iamVjdCBEYXRlXScsXG4gICAgZXJyb3JUYWcgPSAnW29iamVjdCBFcnJvcl0nLFxuICAgIGZ1bmNUYWcgPSAnW29iamVjdCBGdW5jdGlvbl0nLFxuICAgIG1hcFRhZyA9ICdbb2JqZWN0IE1hcF0nLFxuICAgIG51bWJlclRhZyA9ICdbb2JqZWN0IE51bWJlcl0nLFxuICAgIG9iamVjdFRhZyA9ICdbb2JqZWN0IE9iamVjdF0nLFxuICAgIHJlZ2V4cFRhZyA9ICdbb2JqZWN0IFJlZ0V4cF0nLFxuICAgIHNldFRhZyA9ICdbb2JqZWN0IFNldF0nLFxuICAgIHN0cmluZ1RhZyA9ICdbb2JqZWN0IFN0cmluZ10nLFxuICAgIHdlYWtNYXBUYWcgPSAnW29iamVjdCBXZWFrTWFwXSc7XG5cbnZhciBhcnJheUJ1ZmZlclRhZyA9ICdbb2JqZWN0IEFycmF5QnVmZmVyXScsXG4gICAgZmxvYXQzMlRhZyA9ICdbb2JqZWN0IEZsb2F0MzJBcnJheV0nLFxuICAgIGZsb2F0NjRUYWcgPSAnW29iamVjdCBGbG9hdDY0QXJyYXldJyxcbiAgICBpbnQ4VGFnID0gJ1tvYmplY3QgSW50OEFycmF5XScsXG4gICAgaW50MTZUYWcgPSAnW29iamVjdCBJbnQxNkFycmF5XScsXG4gICAgaW50MzJUYWcgPSAnW29iamVjdCBJbnQzMkFycmF5XScsXG4gICAgdWludDhUYWcgPSAnW29iamVjdCBVaW50OEFycmF5XScsXG4gICAgdWludDhDbGFtcGVkVGFnID0gJ1tvYmplY3QgVWludDhDbGFtcGVkQXJyYXldJyxcbiAgICB1aW50MTZUYWcgPSAnW29iamVjdCBVaW50MTZBcnJheV0nLFxuICAgIHVpbnQzMlRhZyA9ICdbb2JqZWN0IFVpbnQzMkFycmF5XSc7XG5cbi8qKiBVc2VkIHRvIGlkZW50aWZ5IGB0b1N0cmluZ1RhZ2AgdmFsdWVzIHN1cHBvcnRlZCBieSBgXy5jbG9uZWAuICovXG52YXIgY2xvbmVhYmxlVGFncyA9IHt9O1xuY2xvbmVhYmxlVGFnc1thcmdzVGFnXSA9IGNsb25lYWJsZVRhZ3NbYXJyYXlUYWddID1cbmNsb25lYWJsZVRhZ3NbYXJyYXlCdWZmZXJUYWddID0gY2xvbmVhYmxlVGFnc1tib29sVGFnXSA9XG5jbG9uZWFibGVUYWdzW2RhdGVUYWddID0gY2xvbmVhYmxlVGFnc1tmbG9hdDMyVGFnXSA9XG5jbG9uZWFibGVUYWdzW2Zsb2F0NjRUYWddID0gY2xvbmVhYmxlVGFnc1tpbnQ4VGFnXSA9XG5jbG9uZWFibGVUYWdzW2ludDE2VGFnXSA9IGNsb25lYWJsZVRhZ3NbaW50MzJUYWddID1cbmNsb25lYWJsZVRhZ3NbbnVtYmVyVGFnXSA9IGNsb25lYWJsZVRhZ3Nbb2JqZWN0VGFnXSA9XG5jbG9uZWFibGVUYWdzW3JlZ2V4cFRhZ10gPSBjbG9uZWFibGVUYWdzW3N0cmluZ1RhZ10gPVxuY2xvbmVhYmxlVGFnc1t1aW50OFRhZ10gPSBjbG9uZWFibGVUYWdzW3VpbnQ4Q2xhbXBlZFRhZ10gPVxuY2xvbmVhYmxlVGFnc1t1aW50MTZUYWddID0gY2xvbmVhYmxlVGFnc1t1aW50MzJUYWddID0gdHJ1ZTtcbmNsb25lYWJsZVRhZ3NbZXJyb3JUYWddID0gY2xvbmVhYmxlVGFnc1tmdW5jVGFnXSA9XG5jbG9uZWFibGVUYWdzW21hcFRhZ10gPSBjbG9uZWFibGVUYWdzW3NldFRhZ10gPVxuY2xvbmVhYmxlVGFnc1t3ZWFrTWFwVGFnXSA9IGZhbHNlO1xuXG4vKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqXG4gKiBVc2VkIHRvIHJlc29sdmUgdGhlIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICogb2YgdmFsdWVzLlxuICovXG52YXIgb2JqVG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5jbG9uZWAgd2l0aG91dCBzdXBwb3J0IGZvciBhcmd1bWVudCBqdWdnbGluZ1xuICogYW5kIGB0aGlzYCBiaW5kaW5nIGBjdXN0b21pemVyYCBmdW5jdGlvbnMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNsb25lLlxuICogQHBhcmFtIHtib29sZWFufSBbaXNEZWVwXSBTcGVjaWZ5IGEgZGVlcCBjbG9uZS5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtjdXN0b21pemVyXSBUaGUgZnVuY3Rpb24gdG8gY3VzdG9taXplIGNsb25pbmcgdmFsdWVzLlxuICogQHBhcmFtIHtzdHJpbmd9IFtrZXldIFRoZSBrZXkgb2YgYHZhbHVlYC5cbiAqIEBwYXJhbSB7T2JqZWN0fSBbb2JqZWN0XSBUaGUgb2JqZWN0IGB2YWx1ZWAgYmVsb25ncyB0by5cbiAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0E9W11dIFRyYWNrcyB0cmF2ZXJzZWQgc291cmNlIG9iamVjdHMuXG4gKiBAcGFyYW0ge0FycmF5fSBbc3RhY2tCPVtdXSBBc3NvY2lhdGVzIGNsb25lcyB3aXRoIHNvdXJjZSBjb3VudGVycGFydHMuXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgY2xvbmVkIHZhbHVlLlxuICovXG5mdW5jdGlvbiBiYXNlQ2xvbmUodmFsdWUsIGlzRGVlcCwgY3VzdG9taXplciwga2V5LCBvYmplY3QsIHN0YWNrQSwgc3RhY2tCKSB7XG4gIHZhciByZXN1bHQ7XG4gIGlmIChjdXN0b21pemVyKSB7XG4gICAgcmVzdWx0ID0gb2JqZWN0ID8gY3VzdG9taXplcih2YWx1ZSwga2V5LCBvYmplY3QpIDogY3VzdG9taXplcih2YWx1ZSk7XG4gIH1cbiAgaWYgKHJlc3VsdCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuICBpZiAoIWlzT2JqZWN0KHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuICB2YXIgaXNBcnIgPSBpc0FycmF5KHZhbHVlKTtcbiAgaWYgKGlzQXJyKSB7XG4gICAgcmVzdWx0ID0gaW5pdENsb25lQXJyYXkodmFsdWUpO1xuICAgIGlmICghaXNEZWVwKSB7XG4gICAgICByZXR1cm4gYXJyYXlDb3B5KHZhbHVlLCByZXN1bHQpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgdGFnID0gb2JqVG9TdHJpbmcuY2FsbCh2YWx1ZSksXG4gICAgICAgIGlzRnVuYyA9IHRhZyA9PSBmdW5jVGFnO1xuXG4gICAgaWYgKHRhZyA9PSBvYmplY3RUYWcgfHwgdGFnID09IGFyZ3NUYWcgfHwgKGlzRnVuYyAmJiAhb2JqZWN0KSkge1xuICAgICAgaWYgKGlzSG9zdE9iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIG9iamVjdCA/IHZhbHVlIDoge307XG4gICAgICB9XG4gICAgICByZXN1bHQgPSBpbml0Q2xvbmVPYmplY3QoaXNGdW5jID8ge30gOiB2YWx1ZSk7XG4gICAgICBpZiAoIWlzRGVlcCkge1xuICAgICAgICByZXR1cm4gYmFzZUFzc2lnbihyZXN1bHQsIHZhbHVlKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNsb25lYWJsZVRhZ3NbdGFnXVxuICAgICAgICA/IGluaXRDbG9uZUJ5VGFnKHZhbHVlLCB0YWcsIGlzRGVlcClcbiAgICAgICAgOiAob2JqZWN0ID8gdmFsdWUgOiB7fSk7XG4gICAgfVxuICB9XG4gIC8vIENoZWNrIGZvciBjaXJjdWxhciByZWZlcmVuY2VzIGFuZCByZXR1cm4gaXRzIGNvcnJlc3BvbmRpbmcgY2xvbmUuXG4gIHN0YWNrQSB8fCAoc3RhY2tBID0gW10pO1xuICBzdGFja0IgfHwgKHN0YWNrQiA9IFtdKTtcblxuICB2YXIgbGVuZ3RoID0gc3RhY2tBLmxlbmd0aDtcbiAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgaWYgKHN0YWNrQVtsZW5ndGhdID09IHZhbHVlKSB7XG4gICAgICByZXR1cm4gc3RhY2tCW2xlbmd0aF07XG4gICAgfVxuICB9XG4gIC8vIEFkZCB0aGUgc291cmNlIHZhbHVlIHRvIHRoZSBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cyBhbmQgYXNzb2NpYXRlIGl0IHdpdGggaXRzIGNsb25lLlxuICBzdGFja0EucHVzaCh2YWx1ZSk7XG4gIHN0YWNrQi5wdXNoKHJlc3VsdCk7XG5cbiAgLy8gUmVjdXJzaXZlbHkgcG9wdWxhdGUgY2xvbmUgKHN1c2NlcHRpYmxlIHRvIGNhbGwgc3RhY2sgbGltaXRzKS5cbiAgKGlzQXJyID8gYXJyYXlFYWNoIDogYmFzZUZvck93bikodmFsdWUsIGZ1bmN0aW9uKHN1YlZhbHVlLCBrZXkpIHtcbiAgICByZXN1bHRba2V5XSA9IGJhc2VDbG9uZShzdWJWYWx1ZSwgaXNEZWVwLCBjdXN0b21pemVyLCBrZXksIHZhbHVlLCBzdGFja0EsIHN0YWNrQik7XG4gIH0pO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VDbG9uZTtcbiIsIi8qKlxuICogQ29waWVzIHByb3BlcnRpZXMgb2YgYHNvdXJjZWAgdG8gYG9iamVjdGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCB0byBjb3B5IHByb3BlcnRpZXMgZnJvbS5cbiAqIEBwYXJhbSB7QXJyYXl9IHByb3BzIFRoZSBwcm9wZXJ0eSBuYW1lcyB0byBjb3B5LlxuICogQHBhcmFtIHtPYmplY3R9IFtvYmplY3Q9e31dIFRoZSBvYmplY3QgdG8gY29weSBwcm9wZXJ0aWVzIHRvLlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAqL1xuZnVuY3Rpb24gYmFzZUNvcHkoc291cmNlLCBwcm9wcywgb2JqZWN0KSB7XG4gIG9iamVjdCB8fCAob2JqZWN0ID0ge30pO1xuXG4gIHZhciBpbmRleCA9IC0xLFxuICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG4gIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgdmFyIGtleSA9IHByb3BzW2luZGV4XTtcbiAgICBvYmplY3Rba2V5XSA9IHNvdXJjZVtrZXldO1xuICB9XG4gIHJldHVybiBvYmplY3Q7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUNvcHk7XG4iLCJ2YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9sYW5nL2lzT2JqZWN0Jyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uY3JlYXRlYCB3aXRob3V0IHN1cHBvcnQgZm9yIGFzc2lnbmluZ1xuICogcHJvcGVydGllcyB0byB0aGUgY3JlYXRlZCBvYmplY3QuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBwcm90b3R5cGUgVGhlIG9iamVjdCB0byBpbmhlcml0IGZyb20uXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBuZXcgb2JqZWN0LlxuICovXG52YXIgYmFzZUNyZWF0ZSA9IChmdW5jdGlvbigpIHtcbiAgZnVuY3Rpb24gb2JqZWN0KCkge31cbiAgcmV0dXJuIGZ1bmN0aW9uKHByb3RvdHlwZSkge1xuICAgIGlmIChpc09iamVjdChwcm90b3R5cGUpKSB7XG4gICAgICBvYmplY3QucHJvdG90eXBlID0gcHJvdG90eXBlO1xuICAgICAgdmFyIHJlc3VsdCA9IG5ldyBvYmplY3Q7XG4gICAgICBvYmplY3QucHJvdG90eXBlID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0IHx8IHt9O1xuICB9O1xufSgpKTtcblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlQ3JlYXRlO1xuIiwidmFyIGJhc2VGb3JPd24gPSByZXF1aXJlKCcuL2Jhc2VGb3JPd24nKSxcbiAgICBjcmVhdGVCYXNlRWFjaCA9IHJlcXVpcmUoJy4vY3JlYXRlQmFzZUVhY2gnKTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mb3JFYWNoYCB3aXRob3V0IHN1cHBvcnQgZm9yIGNhbGxiYWNrXG4gKiBzaG9ydGhhbmRzIGFuZCBgdGhpc2AgYmluZGluZy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIGl0ZXJhdGUgb3Zlci5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGl0ZXJhdGVlIFRoZSBmdW5jdGlvbiBpbnZva2VkIHBlciBpdGVyYXRpb24uXG4gKiBAcmV0dXJucyB7QXJyYXl8T2JqZWN0fHN0cmluZ30gUmV0dXJucyBgY29sbGVjdGlvbmAuXG4gKi9cbnZhciBiYXNlRWFjaCA9IGNyZWF0ZUJhc2VFYWNoKGJhc2VGb3JPd24pO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VFYWNoO1xuIiwiLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5maW5kYCwgYF8uZmluZExhc3RgLCBgXy5maW5kS2V5YCwgYW5kIGBfLmZpbmRMYXN0S2V5YCxcbiAqIHdpdGhvdXQgc3VwcG9ydCBmb3IgY2FsbGJhY2sgc2hvcnRoYW5kcyBhbmQgYHRoaXNgIGJpbmRpbmcsIHdoaWNoIGl0ZXJhdGVzXG4gKiBvdmVyIGBjb2xsZWN0aW9uYCB1c2luZyB0aGUgcHJvdmlkZWQgYGVhY2hGdW5jYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSBjb2xsZWN0aW9uIFRoZSBjb2xsZWN0aW9uIHRvIHNlYXJjaC5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IHByZWRpY2F0ZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZWFjaEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciBgY29sbGVjdGlvbmAuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtyZXRLZXldIFNwZWNpZnkgcmV0dXJuaW5nIHRoZSBrZXkgb2YgdGhlIGZvdW5kIGVsZW1lbnRcbiAqICBpbnN0ZWFkIG9mIHRoZSBlbGVtZW50IGl0c2VsZi5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBmb3VuZCBlbGVtZW50IG9yIGl0cyBrZXksIGVsc2UgYHVuZGVmaW5lZGAuXG4gKi9cbmZ1bmN0aW9uIGJhc2VGaW5kKGNvbGxlY3Rpb24sIHByZWRpY2F0ZSwgZWFjaEZ1bmMsIHJldEtleSkge1xuICB2YXIgcmVzdWx0O1xuICBlYWNoRnVuYyhjb2xsZWN0aW9uLCBmdW5jdGlvbih2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSB7XG4gICAgaWYgKHByZWRpY2F0ZSh2YWx1ZSwga2V5LCBjb2xsZWN0aW9uKSkge1xuICAgICAgcmVzdWx0ID0gcmV0S2V5ID8ga2V5IDogdmFsdWU7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlRmluZDtcbiIsIi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uZmluZEluZGV4YCBhbmQgYF8uZmluZExhc3RJbmRleGAgd2l0aG91dFxuICogc3VwcG9ydCBmb3IgY2FsbGJhY2sgc2hvcnRoYW5kcyBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzZWFyY2guXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBwcmVkaWNhdGUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIG1hdGNoZWQgdmFsdWUsIGVsc2UgYC0xYC5cbiAqL1xuZnVuY3Rpb24gYmFzZUZpbmRJbmRleChhcnJheSwgcHJlZGljYXRlLCBmcm9tUmlnaHQpIHtcbiAgdmFyIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgIGluZGV4ID0gZnJvbVJpZ2h0ID8gbGVuZ3RoIDogLTE7XG5cbiAgd2hpbGUgKChmcm9tUmlnaHQgPyBpbmRleC0tIDogKytpbmRleCA8IGxlbmd0aCkpIHtcbiAgICBpZiAocHJlZGljYXRlKGFycmF5W2luZGV4XSwgaW5kZXgsIGFycmF5KSkge1xuICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cbiAgfVxuICByZXR1cm4gLTE7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUZpbmRJbmRleDtcbiIsInZhciBjcmVhdGVCYXNlRm9yID0gcmVxdWlyZSgnLi9jcmVhdGVCYXNlRm9yJyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGJhc2VGb3JJbmAgYW5kIGBiYXNlRm9yT3duYCB3aGljaCBpdGVyYXRlc1xuICogb3ZlciBgb2JqZWN0YCBwcm9wZXJ0aWVzIHJldHVybmVkIGJ5IGBrZXlzRnVuY2AgaW52b2tpbmcgYGl0ZXJhdGVlYCBmb3JcbiAqIGVhY2ggcHJvcGVydHkuIEl0ZXJhdGVlIGZ1bmN0aW9ucyBtYXkgZXhpdCBpdGVyYXRpb24gZWFybHkgYnkgZXhwbGljaXRseVxuICogcmV0dXJuaW5nIGBmYWxzZWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHBhcmFtIHtGdW5jdGlvbn0ga2V5c0Z1bmMgVGhlIGZ1bmN0aW9uIHRvIGdldCB0aGUga2V5cyBvZiBgb2JqZWN0YC5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgYG9iamVjdGAuXG4gKi9cbnZhciBiYXNlRm9yID0gY3JlYXRlQmFzZUZvcigpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VGb3I7XG4iLCJ2YXIgYmFzZUZvciA9IHJlcXVpcmUoJy4vYmFzZUZvcicpLFxuICAgIGtleXNJbiA9IHJlcXVpcmUoJy4uL29iamVjdC9rZXlzSW4nKTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5mb3JJbmAgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICogc2hvcnRoYW5kcyBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAqL1xuZnVuY3Rpb24gYmFzZUZvckluKG9iamVjdCwgaXRlcmF0ZWUpIHtcbiAgcmV0dXJuIGJhc2VGb3Iob2JqZWN0LCBpdGVyYXRlZSwga2V5c0luKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlRm9ySW47XG4iLCJ2YXIgYmFzZUZvciA9IHJlcXVpcmUoJy4vYmFzZUZvcicpLFxuICAgIGtleXMgPSByZXF1aXJlKCcuLi9vYmplY3Qva2V5cycpO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLmZvck93bmAgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICogc2hvcnRoYW5kcyBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpdGVyYXRlIG92ZXIuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyBgb2JqZWN0YC5cbiAqL1xuZnVuY3Rpb24gYmFzZUZvck93bihvYmplY3QsIGl0ZXJhdGVlKSB7XG4gIHJldHVybiBiYXNlRm9yKG9iamVjdCwgaXRlcmF0ZWUsIGtleXMpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VGb3JPd247XG4iLCJ2YXIgdG9PYmplY3QgPSByZXF1aXJlKCcuL3RvT2JqZWN0Jyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYGdldGAgd2l0aG91dCBzdXBwb3J0IGZvciBzdHJpbmcgcGF0aHNcbiAqIGFuZCBkZWZhdWx0IHZhbHVlcy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHBhcmFtIHtBcnJheX0gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICogQHBhcmFtIHtzdHJpbmd9IFtwYXRoS2V5XSBUaGUga2V5IHJlcHJlc2VudGF0aW9uIG9mIHBhdGguXG4gKiBAcmV0dXJucyB7Kn0gUmV0dXJucyB0aGUgcmVzb2x2ZWQgdmFsdWUuXG4gKi9cbmZ1bmN0aW9uIGJhc2VHZXQob2JqZWN0LCBwYXRoLCBwYXRoS2V5KSB7XG4gIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgIHJldHVybjtcbiAgfVxuICBvYmplY3QgPSB0b09iamVjdChvYmplY3QpO1xuICBpZiAocGF0aEtleSAhPT0gdW5kZWZpbmVkICYmIHBhdGhLZXkgaW4gb2JqZWN0KSB7XG4gICAgcGF0aCA9IFtwYXRoS2V5XTtcbiAgfVxuICB2YXIgaW5kZXggPSAwLFxuICAgICAgbGVuZ3RoID0gcGF0aC5sZW5ndGg7XG5cbiAgd2hpbGUgKG9iamVjdCAhPSBudWxsICYmIGluZGV4IDwgbGVuZ3RoKSB7XG4gICAgb2JqZWN0ID0gdG9PYmplY3Qob2JqZWN0KVtwYXRoW2luZGV4KytdXTtcbiAgfVxuICByZXR1cm4gKGluZGV4ICYmIGluZGV4ID09IGxlbmd0aCkgPyBvYmplY3QgOiB1bmRlZmluZWQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUdldDtcbiIsInZhciBpbmRleE9mTmFOID0gcmVxdWlyZSgnLi9pbmRleE9mTmFOJyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaW5kZXhPZmAgd2l0aG91dCBzdXBwb3J0IGZvciBiaW5hcnkgc2VhcmNoZXMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBzZWFyY2guXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBzZWFyY2ggZm9yLlxuICogQHBhcmFtIHtudW1iZXJ9IGZyb21JbmRleCBUaGUgaW5kZXggdG8gc2VhcmNoIGZyb20uXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCB2YWx1ZSwgZWxzZSBgLTFgLlxuICovXG5mdW5jdGlvbiBiYXNlSW5kZXhPZihhcnJheSwgdmFsdWUsIGZyb21JbmRleCkge1xuICBpZiAodmFsdWUgIT09IHZhbHVlKSB7XG4gICAgcmV0dXJuIGluZGV4T2ZOYU4oYXJyYXksIGZyb21JbmRleCk7XG4gIH1cbiAgdmFyIGluZGV4ID0gZnJvbUluZGV4IC0gMSxcbiAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIGlmIChhcnJheVtpbmRleF0gPT09IHZhbHVlKSB7XG4gICAgICByZXR1cm4gaW5kZXg7XG4gICAgfVxuICB9XG4gIHJldHVybiAtMTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlSW5kZXhPZjtcbiIsInZhciBiYXNlSXNFcXVhbERlZXAgPSByZXF1aXJlKCcuL2Jhc2VJc0VxdWFsRGVlcCcpLFxuICAgIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi4vbGFuZy9pc09iamVjdCcpLFxuICAgIGlzT2JqZWN0TGlrZSA9IHJlcXVpcmUoJy4vaXNPYmplY3RMaWtlJyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNFcXVhbGAgd2l0aG91dCBzdXBwb3J0IGZvciBgdGhpc2AgYmluZGluZ1xuICogYGN1c3RvbWl6ZXJgIGZ1bmN0aW9ucy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7Kn0gb3RoZXIgVGhlIG90aGVyIHZhbHVlIHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbY3VzdG9taXplcl0gVGhlIGZ1bmN0aW9uIHRvIGN1c3RvbWl6ZSBjb21wYXJpbmcgdmFsdWVzLlxuICogQHBhcmFtIHtib29sZWFufSBbaXNMb29zZV0gU3BlY2lmeSBwZXJmb3JtaW5nIHBhcnRpYWwgY29tcGFyaXNvbnMuXG4gKiBAcGFyYW0ge0FycmF5fSBbc3RhY2tBXSBUcmFja3MgdHJhdmVyc2VkIGB2YWx1ZWAgb2JqZWN0cy5cbiAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0JdIFRyYWNrcyB0cmF2ZXJzZWQgYG90aGVyYCBvYmplY3RzLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHRoZSB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gYmFzZUlzRXF1YWwodmFsdWUsIG90aGVyLCBjdXN0b21pemVyLCBpc0xvb3NlLCBzdGFja0EsIHN0YWNrQikge1xuICBpZiAodmFsdWUgPT09IG90aGVyKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKHZhbHVlID09IG51bGwgfHwgb3RoZXIgPT0gbnVsbCB8fCAoIWlzT2JqZWN0KHZhbHVlKSAmJiAhaXNPYmplY3RMaWtlKG90aGVyKSkpIHtcbiAgICByZXR1cm4gdmFsdWUgIT09IHZhbHVlICYmIG90aGVyICE9PSBvdGhlcjtcbiAgfVxuICByZXR1cm4gYmFzZUlzRXF1YWxEZWVwKHZhbHVlLCBvdGhlciwgYmFzZUlzRXF1YWwsIGN1c3RvbWl6ZXIsIGlzTG9vc2UsIHN0YWNrQSwgc3RhY2tCKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlSXNFcXVhbDtcbiIsInZhciBlcXVhbEFycmF5cyA9IHJlcXVpcmUoJy4vZXF1YWxBcnJheXMnKSxcbiAgICBlcXVhbEJ5VGFnID0gcmVxdWlyZSgnLi9lcXVhbEJ5VGFnJyksXG4gICAgZXF1YWxPYmplY3RzID0gcmVxdWlyZSgnLi9lcXVhbE9iamVjdHMnKSxcbiAgICBpc0FycmF5ID0gcmVxdWlyZSgnLi4vbGFuZy9pc0FycmF5JyksXG4gICAgaXNIb3N0T2JqZWN0ID0gcmVxdWlyZSgnLi9pc0hvc3RPYmplY3QnKSxcbiAgICBpc1R5cGVkQXJyYXkgPSByZXF1aXJlKCcuLi9sYW5nL2lzVHlwZWRBcnJheScpO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgYXJnc1RhZyA9ICdbb2JqZWN0IEFyZ3VtZW50c10nLFxuICAgIGFycmF5VGFnID0gJ1tvYmplY3QgQXJyYXldJyxcbiAgICBvYmplY3RUYWcgPSAnW29iamVjdCBPYmplY3RdJztcblxuLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogVXNlZCB0byByZXNvbHZlIHRoZSBbYHRvU3RyaW5nVGFnYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZylcbiAqIG9mIHZhbHVlcy5cbiAqL1xudmFyIG9ialRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbi8qKlxuICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlSXNFcXVhbGAgZm9yIGFycmF5cyBhbmQgb2JqZWN0cyB3aGljaCBwZXJmb3Jtc1xuICogZGVlcCBjb21wYXJpc29ucyBhbmQgdHJhY2tzIHRyYXZlcnNlZCBvYmplY3RzIGVuYWJsaW5nIG9iamVjdHMgd2l0aCBjaXJjdWxhclxuICogcmVmZXJlbmNlcyB0byBiZSBjb21wYXJlZC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge09iamVjdH0gb3RoZXIgVGhlIG90aGVyIG9iamVjdCB0byBjb21wYXJlLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaW5nIG9iamVjdHMuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtpc0xvb3NlXSBTcGVjaWZ5IHBlcmZvcm1pbmcgcGFydGlhbCBjb21wYXJpc29ucy5cbiAqIEBwYXJhbSB7QXJyYXl9IFtzdGFja0E9W11dIFRyYWNrcyB0cmF2ZXJzZWQgYHZhbHVlYCBvYmplY3RzLlxuICogQHBhcmFtIHtBcnJheX0gW3N0YWNrQj1bXV0gVHJhY2tzIHRyYXZlcnNlZCBgb3RoZXJgIG9iamVjdHMuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgdGhlIG9iamVjdHMgYXJlIGVxdWl2YWxlbnQsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gYmFzZUlzRXF1YWxEZWVwKG9iamVjdCwgb3RoZXIsIGVxdWFsRnVuYywgY3VzdG9taXplciwgaXNMb29zZSwgc3RhY2tBLCBzdGFja0IpIHtcbiAgdmFyIG9iaklzQXJyID0gaXNBcnJheShvYmplY3QpLFxuICAgICAgb3RoSXNBcnIgPSBpc0FycmF5KG90aGVyKSxcbiAgICAgIG9ialRhZyA9IGFycmF5VGFnLFxuICAgICAgb3RoVGFnID0gYXJyYXlUYWc7XG5cbiAgaWYgKCFvYmpJc0Fycikge1xuICAgIG9ialRhZyA9IG9ialRvU3RyaW5nLmNhbGwob2JqZWN0KTtcbiAgICBpZiAob2JqVGFnID09IGFyZ3NUYWcpIHtcbiAgICAgIG9ialRhZyA9IG9iamVjdFRhZztcbiAgICB9IGVsc2UgaWYgKG9ialRhZyAhPSBvYmplY3RUYWcpIHtcbiAgICAgIG9iaklzQXJyID0gaXNUeXBlZEFycmF5KG9iamVjdCk7XG4gICAgfVxuICB9XG4gIGlmICghb3RoSXNBcnIpIHtcbiAgICBvdGhUYWcgPSBvYmpUb1N0cmluZy5jYWxsKG90aGVyKTtcbiAgICBpZiAob3RoVGFnID09IGFyZ3NUYWcpIHtcbiAgICAgIG90aFRhZyA9IG9iamVjdFRhZztcbiAgICB9IGVsc2UgaWYgKG90aFRhZyAhPSBvYmplY3RUYWcpIHtcbiAgICAgIG90aElzQXJyID0gaXNUeXBlZEFycmF5KG90aGVyKTtcbiAgICB9XG4gIH1cbiAgdmFyIG9iaklzT2JqID0gb2JqVGFnID09IG9iamVjdFRhZyAmJiAhaXNIb3N0T2JqZWN0KG9iamVjdCksXG4gICAgICBvdGhJc09iaiA9IG90aFRhZyA9PSBvYmplY3RUYWcgJiYgIWlzSG9zdE9iamVjdChvdGhlciksXG4gICAgICBpc1NhbWVUYWcgPSBvYmpUYWcgPT0gb3RoVGFnO1xuXG4gIGlmIChpc1NhbWVUYWcgJiYgIShvYmpJc0FyciB8fCBvYmpJc09iaikpIHtcbiAgICByZXR1cm4gZXF1YWxCeVRhZyhvYmplY3QsIG90aGVyLCBvYmpUYWcpO1xuICB9XG4gIGlmICghaXNMb29zZSkge1xuICAgIHZhciBvYmpJc1dyYXBwZWQgPSBvYmpJc09iaiAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgJ19fd3JhcHBlZF9fJyksXG4gICAgICAgIG90aElzV3JhcHBlZCA9IG90aElzT2JqICYmIGhhc093blByb3BlcnR5LmNhbGwob3RoZXIsICdfX3dyYXBwZWRfXycpO1xuXG4gICAgaWYgKG9iaklzV3JhcHBlZCB8fCBvdGhJc1dyYXBwZWQpIHtcbiAgICAgIHJldHVybiBlcXVhbEZ1bmMob2JqSXNXcmFwcGVkID8gb2JqZWN0LnZhbHVlKCkgOiBvYmplY3QsIG90aElzV3JhcHBlZCA/IG90aGVyLnZhbHVlKCkgOiBvdGhlciwgY3VzdG9taXplciwgaXNMb29zZSwgc3RhY2tBLCBzdGFja0IpO1xuICAgIH1cbiAgfVxuICBpZiAoIWlzU2FtZVRhZykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBBc3N1bWUgY3ljbGljIHZhbHVlcyBhcmUgZXF1YWwuXG4gIC8vIEZvciBtb3JlIGluZm9ybWF0aW9uIG9uIGRldGVjdGluZyBjaXJjdWxhciByZWZlcmVuY2VzIHNlZSBodHRwczovL2VzNS5naXRodWIuaW8vI0pPLlxuICBzdGFja0EgfHwgKHN0YWNrQSA9IFtdKTtcbiAgc3RhY2tCIHx8IChzdGFja0IgPSBbXSk7XG5cbiAgdmFyIGxlbmd0aCA9IHN0YWNrQS5sZW5ndGg7XG4gIHdoaWxlIChsZW5ndGgtLSkge1xuICAgIGlmIChzdGFja0FbbGVuZ3RoXSA9PSBvYmplY3QpIHtcbiAgICAgIHJldHVybiBzdGFja0JbbGVuZ3RoXSA9PSBvdGhlcjtcbiAgICB9XG4gIH1cbiAgLy8gQWRkIGBvYmplY3RgIGFuZCBgb3RoZXJgIHRvIHRoZSBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cy5cbiAgc3RhY2tBLnB1c2gob2JqZWN0KTtcbiAgc3RhY2tCLnB1c2gob3RoZXIpO1xuXG4gIHZhciByZXN1bHQgPSAob2JqSXNBcnIgPyBlcXVhbEFycmF5cyA6IGVxdWFsT2JqZWN0cykob2JqZWN0LCBvdGhlciwgZXF1YWxGdW5jLCBjdXN0b21pemVyLCBpc0xvb3NlLCBzdGFja0EsIHN0YWNrQik7XG5cbiAgc3RhY2tBLnBvcCgpO1xuICBzdGFja0IucG9wKCk7XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlSXNFcXVhbERlZXA7XG4iLCJ2YXIgYmFzZUlzRXF1YWwgPSByZXF1aXJlKCcuL2Jhc2VJc0VxdWFsJyksXG4gICAgdG9PYmplY3QgPSByZXF1aXJlKCcuL3RvT2JqZWN0Jyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uaXNNYXRjaGAgd2l0aG91dCBzdXBwb3J0IGZvciBjYWxsYmFja1xuICogc2hvcnRoYW5kcyBhbmQgYHRoaXNgIGJpbmRpbmcuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBpbnNwZWN0LlxuICogQHBhcmFtIHtBcnJheX0gbWF0Y2hEYXRhIFRoZSBwcm9wZXJ5IG5hbWVzLCB2YWx1ZXMsIGFuZCBjb21wYXJlIGZsYWdzIHRvIG1hdGNoLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaW5nIG9iamVjdHMuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYG9iamVjdGAgaXMgYSBtYXRjaCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBiYXNlSXNNYXRjaChvYmplY3QsIG1hdGNoRGF0YSwgY3VzdG9taXplcikge1xuICB2YXIgaW5kZXggPSBtYXRjaERhdGEubGVuZ3RoLFxuICAgICAgbGVuZ3RoID0gaW5kZXgsXG4gICAgICBub0N1c3RvbWl6ZXIgPSAhY3VzdG9taXplcjtcblxuICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICByZXR1cm4gIWxlbmd0aDtcbiAgfVxuICBvYmplY3QgPSB0b09iamVjdChvYmplY3QpO1xuICB3aGlsZSAoaW5kZXgtLSkge1xuICAgIHZhciBkYXRhID0gbWF0Y2hEYXRhW2luZGV4XTtcbiAgICBpZiAoKG5vQ3VzdG9taXplciAmJiBkYXRhWzJdKVxuICAgICAgICAgID8gZGF0YVsxXSAhPT0gb2JqZWN0W2RhdGFbMF1dXG4gICAgICAgICAgOiAhKGRhdGFbMF0gaW4gb2JqZWN0KVxuICAgICAgICApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICBkYXRhID0gbWF0Y2hEYXRhW2luZGV4XTtcbiAgICB2YXIga2V5ID0gZGF0YVswXSxcbiAgICAgICAgb2JqVmFsdWUgPSBvYmplY3Rba2V5XSxcbiAgICAgICAgc3JjVmFsdWUgPSBkYXRhWzFdO1xuXG4gICAgaWYgKG5vQ3VzdG9taXplciAmJiBkYXRhWzJdKSB7XG4gICAgICBpZiAob2JqVmFsdWUgPT09IHVuZGVmaW5lZCAmJiAhKGtleSBpbiBvYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHJlc3VsdCA9IGN1c3RvbWl6ZXIgPyBjdXN0b21pemVyKG9ialZhbHVlLCBzcmNWYWx1ZSwga2V5KSA6IHVuZGVmaW5lZDtcbiAgICAgIGlmICghKHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gYmFzZUlzRXF1YWwoc3JjVmFsdWUsIG9ialZhbHVlLCBjdXN0b21pemVyLCB0cnVlKSA6IHJlc3VsdCkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlSXNNYXRjaDtcbiIsIi8qKlxuICogVGhlIGZ1bmN0aW9uIHdob3NlIHByb3RvdHlwZSBhbGwgY2hhaW5pbmcgd3JhcHBlcnMgaW5oZXJpdCBmcm9tLlxuICpcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIGJhc2VMb2Rhc2goKSB7XG4gIC8vIE5vIG9wZXJhdGlvbiBwZXJmb3JtZWQuXG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZUxvZGFzaDtcbiIsInZhciBiYXNlRWFjaCA9IHJlcXVpcmUoJy4vYmFzZUVhY2gnKSxcbiAgICBpc0FycmF5TGlrZSA9IHJlcXVpcmUoJy4vaXNBcnJheUxpa2UnKTtcblxuLyoqXG4gKiBUaGUgYmFzZSBpbXBsZW1lbnRhdGlvbiBvZiBgXy5tYXBgIHdpdGhvdXQgc3VwcG9ydCBmb3IgY2FsbGJhY2sgc2hvcnRoYW5kc1xuICogYW5kIGB0aGlzYCBiaW5kaW5nLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5fE9iamVjdHxzdHJpbmd9IGNvbGxlY3Rpb24gVGhlIGNvbGxlY3Rpb24gdG8gaXRlcmF0ZSBvdmVyLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gaXRlcmF0ZWUgVGhlIGZ1bmN0aW9uIGludm9rZWQgcGVyIGl0ZXJhdGlvbi5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IG1hcHBlZCBhcnJheS5cbiAqL1xuZnVuY3Rpb24gYmFzZU1hcChjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIHJlc3VsdCA9IGlzQXJyYXlMaWtlKGNvbGxlY3Rpb24pID8gQXJyYXkoY29sbGVjdGlvbi5sZW5ndGgpIDogW107XG5cbiAgYmFzZUVhY2goY29sbGVjdGlvbiwgZnVuY3Rpb24odmFsdWUsIGtleSwgY29sbGVjdGlvbikge1xuICAgIHJlc3VsdFsrK2luZGV4XSA9IGl0ZXJhdGVlKHZhbHVlLCBrZXksIGNvbGxlY3Rpb24pO1xuICB9KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlTWFwO1xuIiwidmFyIGJhc2VJc01hdGNoID0gcmVxdWlyZSgnLi9iYXNlSXNNYXRjaCcpLFxuICAgIGdldE1hdGNoRGF0YSA9IHJlcXVpcmUoJy4vZ2V0TWF0Y2hEYXRhJyksXG4gICAgdG9PYmplY3QgPSByZXF1aXJlKCcuL3RvT2JqZWN0Jyk7XG5cbi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8ubWF0Y2hlc2Agd2hpY2ggZG9lcyBub3QgY2xvbmUgYHNvdXJjZWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBzb3VyY2UgVGhlIG9iamVjdCBvZiBwcm9wZXJ0eSB2YWx1ZXMgdG8gbWF0Y2guXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gYmFzZU1hdGNoZXMoc291cmNlKSB7XG4gIHZhciBtYXRjaERhdGEgPSBnZXRNYXRjaERhdGEoc291cmNlKTtcbiAgaWYgKG1hdGNoRGF0YS5sZW5ndGggPT0gMSAmJiBtYXRjaERhdGFbMF1bMl0pIHtcbiAgICB2YXIga2V5ID0gbWF0Y2hEYXRhWzBdWzBdLFxuICAgICAgICB2YWx1ZSA9IG1hdGNoRGF0YVswXVsxXTtcblxuICAgIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBvYmplY3QgPSB0b09iamVjdChvYmplY3QpO1xuICAgICAgcmV0dXJuIG9iamVjdFtrZXldID09PSB2YWx1ZSAmJiAodmFsdWUgIT09IHVuZGVmaW5lZCB8fCAoa2V5IGluIG9iamVjdCkpO1xuICAgIH07XG4gIH1cbiAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgIHJldHVybiBiYXNlSXNNYXRjaChvYmplY3QsIG1hdGNoRGF0YSk7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZU1hdGNoZXM7XG4iLCJ2YXIgYmFzZUdldCA9IHJlcXVpcmUoJy4vYmFzZUdldCcpLFxuICAgIGJhc2VJc0VxdWFsID0gcmVxdWlyZSgnLi9iYXNlSXNFcXVhbCcpLFxuICAgIGJhc2VTbGljZSA9IHJlcXVpcmUoJy4vYmFzZVNsaWNlJyksXG4gICAgaXNBcnJheSA9IHJlcXVpcmUoJy4uL2xhbmcvaXNBcnJheScpLFxuICAgIGlzS2V5ID0gcmVxdWlyZSgnLi9pc0tleScpLFxuICAgIGlzU3RyaWN0Q29tcGFyYWJsZSA9IHJlcXVpcmUoJy4vaXNTdHJpY3RDb21wYXJhYmxlJyksXG4gICAgbGFzdCA9IHJlcXVpcmUoJy4uL2FycmF5L2xhc3QnKSxcbiAgICB0b09iamVjdCA9IHJlcXVpcmUoJy4vdG9PYmplY3QnKSxcbiAgICB0b1BhdGggPSByZXF1aXJlKCcuL3RvUGF0aCcpO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLm1hdGNoZXNQcm9wZXJ0eWAgd2hpY2ggZG9lcyBub3QgY2xvbmUgYHNyY1ZhbHVlYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtzdHJpbmd9IHBhdGggVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5IHRvIGdldC5cbiAqIEBwYXJhbSB7Kn0gc3JjVmFsdWUgVGhlIHZhbHVlIHRvIGNvbXBhcmUuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gYmFzZU1hdGNoZXNQcm9wZXJ0eShwYXRoLCBzcmNWYWx1ZSkge1xuICB2YXIgaXNBcnIgPSBpc0FycmF5KHBhdGgpLFxuICAgICAgaXNDb21tb24gPSBpc0tleShwYXRoKSAmJiBpc1N0cmljdENvbXBhcmFibGUoc3JjVmFsdWUpLFxuICAgICAgcGF0aEtleSA9IChwYXRoICsgJycpO1xuXG4gIHBhdGggPSB0b1BhdGgocGF0aCk7XG4gIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICBpZiAob2JqZWN0ID09IG51bGwpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgdmFyIGtleSA9IHBhdGhLZXk7XG4gICAgb2JqZWN0ID0gdG9PYmplY3Qob2JqZWN0KTtcbiAgICBpZiAoKGlzQXJyIHx8ICFpc0NvbW1vbikgJiYgIShrZXkgaW4gb2JqZWN0KSkge1xuICAgICAgb2JqZWN0ID0gcGF0aC5sZW5ndGggPT0gMSA/IG9iamVjdCA6IGJhc2VHZXQob2JqZWN0LCBiYXNlU2xpY2UocGF0aCwgMCwgLTEpKTtcbiAgICAgIGlmIChvYmplY3QgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICBrZXkgPSBsYXN0KHBhdGgpO1xuICAgICAgb2JqZWN0ID0gdG9PYmplY3Qob2JqZWN0KTtcbiAgICB9XG4gICAgcmV0dXJuIG9iamVjdFtrZXldID09PSBzcmNWYWx1ZVxuICAgICAgPyAoc3JjVmFsdWUgIT09IHVuZGVmaW5lZCB8fCAoa2V5IGluIG9iamVjdCkpXG4gICAgICA6IGJhc2VJc0VxdWFsKHNyY1ZhbHVlLCBvYmplY3Rba2V5XSwgdW5kZWZpbmVkLCB0cnVlKTtcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlTWF0Y2hlc1Byb3BlcnR5O1xuIiwidmFyIHRvT2JqZWN0ID0gcmVxdWlyZSgnLi90b09iamVjdCcpO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBfLnByb3BlcnR5YCB3aXRob3V0IHN1cHBvcnQgZm9yIGRlZXAgcGF0aHMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7c3RyaW5nfSBrZXkgVGhlIGtleSBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIGJhc2VQcm9wZXJ0eShrZXkpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKG9iamVjdCkge1xuICAgIHJldHVybiBvYmplY3QgPT0gbnVsbCA/IHVuZGVmaW5lZCA6IHRvT2JqZWN0KG9iamVjdClba2V5XTtcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlUHJvcGVydHk7XG4iLCJ2YXIgYmFzZUdldCA9IHJlcXVpcmUoJy4vYmFzZUdldCcpLFxuICAgIHRvUGF0aCA9IHJlcXVpcmUoJy4vdG9QYXRoJyk7XG5cbi8qKlxuICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlUHJvcGVydHlgIHdoaWNoIHN1cHBvcnRzIGRlZXAgcGF0aHMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl8c3RyaW5nfSBwYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eSB0byBnZXQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gYmFzZVByb3BlcnR5RGVlcChwYXRoKSB7XG4gIHZhciBwYXRoS2V5ID0gKHBhdGggKyAnJyk7XG4gIHBhdGggPSB0b1BhdGgocGF0aCk7XG4gIHJldHVybiBmdW5jdGlvbihvYmplY3QpIHtcbiAgICByZXR1cm4gYmFzZUdldChvYmplY3QsIHBhdGgsIHBhdGhLZXkpO1xuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VQcm9wZXJ0eURlZXA7XG4iLCJ2YXIgaWRlbnRpdHkgPSByZXF1aXJlKCcuLi91dGlsaXR5L2lkZW50aXR5JyksXG4gICAgbWV0YU1hcCA9IHJlcXVpcmUoJy4vbWV0YU1hcCcpO1xuXG4vKipcbiAqIFRoZSBiYXNlIGltcGxlbWVudGF0aW9uIG9mIGBzZXREYXRhYCB3aXRob3V0IHN1cHBvcnQgZm9yIGhvdCBsb29wIGRldGVjdGlvbi5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gYXNzb2NpYXRlIG1ldGFkYXRhIHdpdGguXG4gKiBAcGFyYW0geyp9IGRhdGEgVGhlIG1ldGFkYXRhLlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIGBmdW5jYC5cbiAqL1xudmFyIGJhc2VTZXREYXRhID0gIW1ldGFNYXAgPyBpZGVudGl0eSA6IGZ1bmN0aW9uKGZ1bmMsIGRhdGEpIHtcbiAgbWV0YU1hcC5zZXQoZnVuYywgZGF0YSk7XG4gIHJldHVybiBmdW5jO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBiYXNlU2V0RGF0YTtcbiIsIi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8uc2xpY2VgIHdpdGhvdXQgYW4gaXRlcmF0ZWUgY2FsbCBndWFyZC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNsaWNlLlxuICogQHBhcmFtIHtudW1iZXJ9IFtzdGFydD0wXSBUaGUgc3RhcnQgcG9zaXRpb24uXG4gKiBAcGFyYW0ge251bWJlcn0gW2VuZD1hcnJheS5sZW5ndGhdIFRoZSBlbmQgcG9zaXRpb24uXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIHNsaWNlIG9mIGBhcnJheWAuXG4gKi9cbmZ1bmN0aW9uIGJhc2VTbGljZShhcnJheSwgc3RhcnQsIGVuZCkge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcblxuICBzdGFydCA9IHN0YXJ0ID09IG51bGwgPyAwIDogKCtzdGFydCB8fCAwKTtcbiAgaWYgKHN0YXJ0IDwgMCkge1xuICAgIHN0YXJ0ID0gLXN0YXJ0ID4gbGVuZ3RoID8gMCA6IChsZW5ndGggKyBzdGFydCk7XG4gIH1cbiAgZW5kID0gKGVuZCA9PT0gdW5kZWZpbmVkIHx8IGVuZCA+IGxlbmd0aCkgPyBsZW5ndGggOiAoK2VuZCB8fCAwKTtcbiAgaWYgKGVuZCA8IDApIHtcbiAgICBlbmQgKz0gbGVuZ3RoO1xuICB9XG4gIGxlbmd0aCA9IHN0YXJ0ID4gZW5kID8gMCA6ICgoZW5kIC0gc3RhcnQpID4+PiAwKTtcbiAgc3RhcnQgPj4+PSAwO1xuXG4gIHZhciByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIHJlc3VsdFtpbmRleF0gPSBhcnJheVtpbmRleCArIHN0YXJ0XTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VTbGljZTtcbiIsIi8qKlxuICogQ29udmVydHMgYHZhbHVlYCB0byBhIHN0cmluZyBpZiBpdCdzIG5vdCBvbmUuIEFuIGVtcHR5IHN0cmluZyBpcyByZXR1cm5lZFxuICogZm9yIGBudWxsYCBvciBgdW5kZWZpbmVkYCB2YWx1ZXMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb2Nlc3MuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBzdHJpbmcuXG4gKi9cbmZ1bmN0aW9uIGJhc2VUb1N0cmluZyh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT0gbnVsbCA/ICcnIDogKHZhbHVlICsgJycpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2VUb1N0cmluZztcbiIsIi8qKlxuICogVGhlIGJhc2UgaW1wbGVtZW50YXRpb24gb2YgYF8udmFsdWVzYCBhbmQgYF8udmFsdWVzSW5gIHdoaWNoIGNyZWF0ZXMgYW5cbiAqIGFycmF5IG9mIGBvYmplY3RgIHByb3BlcnR5IHZhbHVlcyBjb3JyZXNwb25kaW5nIHRvIHRoZSBwcm9wZXJ0eSBuYW1lc1xuICogb2YgYHByb3BzYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHBhcmFtIHtBcnJheX0gcHJvcHMgVGhlIHByb3BlcnR5IG5hbWVzIHRvIGdldCB2YWx1ZXMgZm9yLlxuICogQHJldHVybnMge09iamVjdH0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgdmFsdWVzLlxuICovXG5mdW5jdGlvbiBiYXNlVmFsdWVzKG9iamVjdCwgcHJvcHMpIHtcbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICBsZW5ndGggPSBwcm9wcy5sZW5ndGgsXG4gICAgICByZXN1bHQgPSBBcnJheShsZW5ndGgpO1xuXG4gIHdoaWxlICgrK2luZGV4IDwgbGVuZ3RoKSB7XG4gICAgcmVzdWx0W2luZGV4XSA9IG9iamVjdFtwcm9wc1tpbmRleF1dO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmFzZVZhbHVlcztcbiIsInZhciBiaW5hcnlJbmRleEJ5ID0gcmVxdWlyZSgnLi9iaW5hcnlJbmRleEJ5JyksXG4gICAgaWRlbnRpdHkgPSByZXF1aXJlKCcuLi91dGlsaXR5L2lkZW50aXR5Jyk7XG5cbi8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIHRoZSBtYXhpbXVtIGxlbmd0aCBhbmQgaW5kZXggb2YgYW4gYXJyYXkuICovXG52YXIgTUFYX0FSUkFZX0xFTkdUSCA9IDQyOTQ5NjcyOTUsXG4gICAgSEFMRl9NQVhfQVJSQVlfTEVOR1RIID0gTUFYX0FSUkFZX0xFTkdUSCA+Pj4gMTtcblxuLyoqXG4gKiBQZXJmb3JtcyBhIGJpbmFyeSBzZWFyY2ggb2YgYGFycmF5YCB0byBkZXRlcm1pbmUgdGhlIGluZGV4IGF0IHdoaWNoIGB2YWx1ZWBcbiAqIHNob3VsZCBiZSBpbnNlcnRlZCBpbnRvIGBhcnJheWAgaW4gb3JkZXIgdG8gbWFpbnRhaW4gaXRzIHNvcnQgb3JkZXIuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBzb3J0ZWQgYXJyYXkgdG8gaW5zcGVjdC5cbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGV2YWx1YXRlLlxuICogQHBhcmFtIHtib29sZWFufSBbcmV0SGlnaGVzdF0gU3BlY2lmeSByZXR1cm5pbmcgdGhlIGhpZ2hlc3QgcXVhbGlmaWVkIGluZGV4LlxuICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAqICBpbnRvIGBhcnJheWAuXG4gKi9cbmZ1bmN0aW9uIGJpbmFyeUluZGV4KGFycmF5LCB2YWx1ZSwgcmV0SGlnaGVzdCkge1xuICB2YXIgbG93ID0gMCxcbiAgICAgIGhpZ2ggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IGxvdztcblxuICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInICYmIHZhbHVlID09PSB2YWx1ZSAmJiBoaWdoIDw9IEhBTEZfTUFYX0FSUkFZX0xFTkdUSCkge1xuICAgIHdoaWxlIChsb3cgPCBoaWdoKSB7XG4gICAgICB2YXIgbWlkID0gKGxvdyArIGhpZ2gpID4+PiAxLFxuICAgICAgICAgIGNvbXB1dGVkID0gYXJyYXlbbWlkXTtcblxuICAgICAgaWYgKChyZXRIaWdoZXN0ID8gKGNvbXB1dGVkIDw9IHZhbHVlKSA6IChjb21wdXRlZCA8IHZhbHVlKSkgJiYgY29tcHV0ZWQgIT09IG51bGwpIHtcbiAgICAgICAgbG93ID0gbWlkICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGhpZ2ggPSBtaWQ7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBoaWdoO1xuICB9XG4gIHJldHVybiBiaW5hcnlJbmRleEJ5KGFycmF5LCB2YWx1ZSwgaWRlbnRpdHksIHJldEhpZ2hlc3QpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJpbmFyeUluZGV4O1xuIiwiLyogTmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVGbG9vciA9IE1hdGguZmxvb3IsXG4gICAgbmF0aXZlTWluID0gTWF0aC5taW47XG5cbi8qKiBVc2VkIGFzIHJlZmVyZW5jZXMgZm9yIHRoZSBtYXhpbXVtIGxlbmd0aCBhbmQgaW5kZXggb2YgYW4gYXJyYXkuICovXG52YXIgTUFYX0FSUkFZX0xFTkdUSCA9IDQyOTQ5NjcyOTUsXG4gICAgTUFYX0FSUkFZX0lOREVYID0gTUFYX0FSUkFZX0xFTkdUSCAtIDE7XG5cbi8qKlxuICogVGhpcyBmdW5jdGlvbiBpcyBsaWtlIGBiaW5hcnlJbmRleGAgZXhjZXB0IHRoYXQgaXQgaW52b2tlcyBgaXRlcmF0ZWVgIGZvclxuICogYHZhbHVlYCBhbmQgZWFjaCBlbGVtZW50IG9mIGBhcnJheWAgdG8gY29tcHV0ZSB0aGVpciBzb3J0IHJhbmtpbmcuIFRoZVxuICogaXRlcmF0ZWUgaXMgaW52b2tlZCB3aXRoIG9uZSBhcmd1bWVudDsgKHZhbHVlKS5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIHNvcnRlZCBhcnJheSB0byBpbnNwZWN0LlxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gZXZhbHVhdGUuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBpdGVyYXRlZSBUaGUgZnVuY3Rpb24gaW52b2tlZCBwZXIgaXRlcmF0aW9uLlxuICogQHBhcmFtIHtib29sZWFufSBbcmV0SGlnaGVzdF0gU3BlY2lmeSByZXR1cm5pbmcgdGhlIGhpZ2hlc3QgcXVhbGlmaWVkIGluZGV4LlxuICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgaW5kZXggYXQgd2hpY2ggYHZhbHVlYCBzaG91bGQgYmUgaW5zZXJ0ZWRcbiAqICBpbnRvIGBhcnJheWAuXG4gKi9cbmZ1bmN0aW9uIGJpbmFyeUluZGV4QnkoYXJyYXksIHZhbHVlLCBpdGVyYXRlZSwgcmV0SGlnaGVzdCkge1xuICB2YWx1ZSA9IGl0ZXJhdGVlKHZhbHVlKTtcblxuICB2YXIgbG93ID0gMCxcbiAgICAgIGhpZ2ggPSBhcnJheSA/IGFycmF5Lmxlbmd0aCA6IDAsXG4gICAgICB2YWxJc05hTiA9IHZhbHVlICE9PSB2YWx1ZSxcbiAgICAgIHZhbElzTnVsbCA9IHZhbHVlID09PSBudWxsLFxuICAgICAgdmFsSXNVbmRlZiA9IHZhbHVlID09PSB1bmRlZmluZWQ7XG5cbiAgd2hpbGUgKGxvdyA8IGhpZ2gpIHtcbiAgICB2YXIgbWlkID0gbmF0aXZlRmxvb3IoKGxvdyArIGhpZ2gpIC8gMiksXG4gICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUoYXJyYXlbbWlkXSksXG4gICAgICAgIGlzRGVmID0gY29tcHV0ZWQgIT09IHVuZGVmaW5lZCxcbiAgICAgICAgaXNSZWZsZXhpdmUgPSBjb21wdXRlZCA9PT0gY29tcHV0ZWQ7XG5cbiAgICBpZiAodmFsSXNOYU4pIHtcbiAgICAgIHZhciBzZXRMb3cgPSBpc1JlZmxleGl2ZSB8fCByZXRIaWdoZXN0O1xuICAgIH0gZWxzZSBpZiAodmFsSXNOdWxsKSB7XG4gICAgICBzZXRMb3cgPSBpc1JlZmxleGl2ZSAmJiBpc0RlZiAmJiAocmV0SGlnaGVzdCB8fCBjb21wdXRlZCAhPSBudWxsKTtcbiAgICB9IGVsc2UgaWYgKHZhbElzVW5kZWYpIHtcbiAgICAgIHNldExvdyA9IGlzUmVmbGV4aXZlICYmIChyZXRIaWdoZXN0IHx8IGlzRGVmKTtcbiAgICB9IGVsc2UgaWYgKGNvbXB1dGVkID09IG51bGwpIHtcbiAgICAgIHNldExvdyA9IGZhbHNlO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZXRMb3cgPSByZXRIaWdoZXN0ID8gKGNvbXB1dGVkIDw9IHZhbHVlKSA6IChjb21wdXRlZCA8IHZhbHVlKTtcbiAgICB9XG4gICAgaWYgKHNldExvdykge1xuICAgICAgbG93ID0gbWlkICsgMTtcbiAgICB9IGVsc2Uge1xuICAgICAgaGlnaCA9IG1pZDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG5hdGl2ZU1pbihoaWdoLCBNQVhfQVJSQVlfSU5ERVgpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGJpbmFyeUluZGV4Qnk7XG4iLCJ2YXIgaWRlbnRpdHkgPSByZXF1aXJlKCcuLi91dGlsaXR5L2lkZW50aXR5Jyk7XG5cbi8qKlxuICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlQ2FsbGJhY2tgIHdoaWNoIG9ubHkgc3VwcG9ydHMgYHRoaXNgIGJpbmRpbmdcbiAqIGFuZCBzcGVjaWZ5aW5nIHRoZSBudW1iZXIgb2YgYXJndW1lbnRzIHRvIHByb3ZpZGUgdG8gYGZ1bmNgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBiaW5kLlxuICogQHBhcmFtIHsqfSB0aGlzQXJnIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gKiBAcGFyYW0ge251bWJlcn0gW2FyZ0NvdW50XSBUaGUgbnVtYmVyIG9mIGFyZ3VtZW50cyB0byBwcm92aWRlIHRvIGBmdW5jYC5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgY2FsbGJhY2suXG4gKi9cbmZ1bmN0aW9uIGJpbmRDYWxsYmFjayhmdW5jLCB0aGlzQXJnLCBhcmdDb3VudCkge1xuICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBpZGVudGl0eTtcbiAgfVxuICBpZiAodGhpc0FyZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIGZ1bmM7XG4gIH1cbiAgc3dpdGNoIChhcmdDb3VudCkge1xuICAgIGNhc2UgMTogcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICByZXR1cm4gZnVuYy5jYWxsKHRoaXNBcmcsIHZhbHVlKTtcbiAgICB9O1xuICAgIGNhc2UgMzogcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCB2YWx1ZSwgaW5kZXgsIGNvbGxlY3Rpb24pO1xuICAgIH07XG4gICAgY2FzZSA0OiByZXR1cm4gZnVuY3Rpb24oYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikge1xuICAgICAgcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCBhY2N1bXVsYXRvciwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTtcbiAgICB9O1xuICAgIGNhc2UgNTogcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBvdGhlciwga2V5LCBvYmplY3QsIHNvdXJjZSkge1xuICAgICAgcmV0dXJuIGZ1bmMuY2FsbCh0aGlzQXJnLCB2YWx1ZSwgb3RoZXIsIGtleSwgb2JqZWN0LCBzb3VyY2UpO1xuICAgIH07XG4gIH1cbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBmdW5jLmFwcGx5KHRoaXNBcmcsIGFyZ3VtZW50cyk7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gYmluZENhbGxiYWNrO1xuIiwiKGZ1bmN0aW9uIChnbG9iYWwpe1xuLyoqIE5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBBcnJheUJ1ZmZlciA9IGdsb2JhbC5BcnJheUJ1ZmZlcixcbiAgICBVaW50OEFycmF5ID0gZ2xvYmFsLlVpbnQ4QXJyYXk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGNsb25lIG9mIHRoZSBnaXZlbiBhcnJheSBidWZmZXIuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXlCdWZmZXJ9IGJ1ZmZlciBUaGUgYXJyYXkgYnVmZmVyIHRvIGNsb25lLlxuICogQHJldHVybnMge0FycmF5QnVmZmVyfSBSZXR1cm5zIHRoZSBjbG9uZWQgYXJyYXkgYnVmZmVyLlxuICovXG5mdW5jdGlvbiBidWZmZXJDbG9uZShidWZmZXIpIHtcbiAgdmFyIHJlc3VsdCA9IG5ldyBBcnJheUJ1ZmZlcihidWZmZXIuYnl0ZUxlbmd0aCksXG4gICAgICB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkocmVzdWx0KTtcblxuICB2aWV3LnNldChuZXcgVWludDhBcnJheShidWZmZXIpKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBidWZmZXJDbG9uZTtcblxufSkuY2FsbCh0aGlzLHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pXG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldDp1dGYtODtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbTV2WkdWZmJXOWtkV3hsY3k5c2IyUmhjMmd0WTI5dGNHRjBMMmx1ZEdWeWJtRnNMMkoxWm1abGNrTnNiMjVsTG1weklsMHNJbTVoYldWeklqcGJYU3dpYldGd2NHbHVaM01pT2lJN1FVRkJRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEVpTENKbWFXeGxJam9pWjJWdVpYSmhkR1ZrTG1weklpd2ljMjkxY21ObFVtOXZkQ0k2SWlJc0luTnZkWEpqWlhORGIyNTBaVzUwSWpwYklpOHFLaUJPWVhScGRtVWdiV1YwYUc5a0lISmxabVZ5Wlc1alpYTXVJQ292WEc1MllYSWdRWEp5WVhsQ2RXWm1aWElnUFNCbmJHOWlZV3d1UVhKeVlYbENkV1ptWlhJc1hHNGdJQ0FnVldsdWREaEJjbkpoZVNBOUlHZHNiMkpoYkM1VmFXNTBPRUZ5Y21GNU8xeHVYRzR2S2lwY2JpQXFJRU55WldGMFpYTWdZU0JqYkc5dVpTQnZaaUIwYUdVZ1oybDJaVzRnWVhKeVlYa2dZblZtWm1WeUxseHVJQ3BjYmlBcUlFQndjbWwyWVhSbFhHNGdLaUJBY0dGeVlXMGdlMEZ5Y21GNVFuVm1abVZ5ZlNCaWRXWm1aWElnVkdobElHRnljbUY1SUdKMVptWmxjaUIwYnlCamJHOXVaUzVjYmlBcUlFQnlaWFIxY201eklIdEJjbkpoZVVKMVptWmxjbjBnVW1WMGRYSnVjeUIwYUdVZ1kyeHZibVZrSUdGeWNtRjVJR0oxWm1abGNpNWNiaUFxTDF4dVpuVnVZM1JwYjI0Z1luVm1abVZ5UTJ4dmJtVW9ZblZtWm1WeUtTQjdYRzRnSUhaaGNpQnlaWE4xYkhRZ1BTQnVaWGNnUVhKeVlYbENkV1ptWlhJb1luVm1abVZ5TG1KNWRHVk1aVzVuZEdncExGeHVJQ0FnSUNBZ2RtbGxkeUE5SUc1bGR5QlZhVzUwT0VGeWNtRjVLSEpsYzNWc2RDazdYRzVjYmlBZ2RtbGxkeTV6WlhRb2JtVjNJRlZwYm5RNFFYSnlZWGtvWW5WbVptVnlLU2s3WEc0Z0lISmxkSFZ5YmlCeVpYTjFiSFE3WEc1OVhHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdZblZtWm1WeVEyeHZibVU3WEc0aVhYMD0iLCIvKiBOYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xudmFyIG5hdGl2ZU1heCA9IE1hdGgubWF4O1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXJyYXkgdGhhdCBpcyB0aGUgY29tcG9zaXRpb24gb2YgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLFxuICogcGxhY2Vob2xkZXJzLCBhbmQgcHJvdmlkZWQgYXJndW1lbnRzIGludG8gYSBzaW5nbGUgYXJyYXkgb2YgYXJndW1lbnRzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5fE9iamVjdH0gYXJncyBUaGUgcHJvdmlkZWQgYXJndW1lbnRzLlxuICogQHBhcmFtIHtBcnJheX0gcGFydGlhbHMgVGhlIGFyZ3VtZW50cyB0byBwcmVwZW5kIHRvIHRob3NlIHByb3ZpZGVkLlxuICogQHBhcmFtIHtBcnJheX0gaG9sZGVycyBUaGUgYHBhcnRpYWxzYCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgY29tcG9zZWQgYXJndW1lbnRzLlxuICovXG5mdW5jdGlvbiBjb21wb3NlQXJncyhhcmdzLCBwYXJ0aWFscywgaG9sZGVycykge1xuICB2YXIgaG9sZGVyc0xlbmd0aCA9IGhvbGRlcnMubGVuZ3RoLFxuICAgICAgYXJnc0luZGV4ID0gLTEsXG4gICAgICBhcmdzTGVuZ3RoID0gbmF0aXZlTWF4KGFyZ3MubGVuZ3RoIC0gaG9sZGVyc0xlbmd0aCwgMCksXG4gICAgICBsZWZ0SW5kZXggPSAtMSxcbiAgICAgIGxlZnRMZW5ndGggPSBwYXJ0aWFscy5sZW5ndGgsXG4gICAgICByZXN1bHQgPSBBcnJheShsZWZ0TGVuZ3RoICsgYXJnc0xlbmd0aCk7XG5cbiAgd2hpbGUgKCsrbGVmdEluZGV4IDwgbGVmdExlbmd0aCkge1xuICAgIHJlc3VsdFtsZWZ0SW5kZXhdID0gcGFydGlhbHNbbGVmdEluZGV4XTtcbiAgfVxuICB3aGlsZSAoKythcmdzSW5kZXggPCBob2xkZXJzTGVuZ3RoKSB7XG4gICAgcmVzdWx0W2hvbGRlcnNbYXJnc0luZGV4XV0gPSBhcmdzW2FyZ3NJbmRleF07XG4gIH1cbiAgd2hpbGUgKGFyZ3NMZW5ndGgtLSkge1xuICAgIHJlc3VsdFtsZWZ0SW5kZXgrK10gPSBhcmdzW2FyZ3NJbmRleCsrXTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNvbXBvc2VBcmdzO1xuIiwiLyogTmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVNYXggPSBNYXRoLm1heDtcblxuLyoqXG4gKiBUaGlzIGZ1bmN0aW9uIGlzIGxpa2UgYGNvbXBvc2VBcmdzYCBleGNlcHQgdGhhdCB0aGUgYXJndW1lbnRzIGNvbXBvc2l0aW9uXG4gKiBpcyB0YWlsb3JlZCBmb3IgYF8ucGFydGlhbFJpZ2h0YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheXxPYmplY3R9IGFyZ3MgVGhlIHByb3ZpZGVkIGFyZ3VtZW50cy5cbiAqIEBwYXJhbSB7QXJyYXl9IHBhcnRpYWxzIFRoZSBhcmd1bWVudHMgdG8gYXBwZW5kIHRvIHRob3NlIHByb3ZpZGVkLlxuICogQHBhcmFtIHtBcnJheX0gaG9sZGVycyBUaGUgYHBhcnRpYWxzYCBwbGFjZWhvbGRlciBpbmRleGVzLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBuZXcgYXJyYXkgb2YgY29tcG9zZWQgYXJndW1lbnRzLlxuICovXG5mdW5jdGlvbiBjb21wb3NlQXJnc1JpZ2h0KGFyZ3MsIHBhcnRpYWxzLCBob2xkZXJzKSB7XG4gIHZhciBob2xkZXJzSW5kZXggPSAtMSxcbiAgICAgIGhvbGRlcnNMZW5ndGggPSBob2xkZXJzLmxlbmd0aCxcbiAgICAgIGFyZ3NJbmRleCA9IC0xLFxuICAgICAgYXJnc0xlbmd0aCA9IG5hdGl2ZU1heChhcmdzLmxlbmd0aCAtIGhvbGRlcnNMZW5ndGgsIDApLFxuICAgICAgcmlnaHRJbmRleCA9IC0xLFxuICAgICAgcmlnaHRMZW5ndGggPSBwYXJ0aWFscy5sZW5ndGgsXG4gICAgICByZXN1bHQgPSBBcnJheShhcmdzTGVuZ3RoICsgcmlnaHRMZW5ndGgpO1xuXG4gIHdoaWxlICgrK2FyZ3NJbmRleCA8IGFyZ3NMZW5ndGgpIHtcbiAgICByZXN1bHRbYXJnc0luZGV4XSA9IGFyZ3NbYXJnc0luZGV4XTtcbiAgfVxuICB2YXIgb2Zmc2V0ID0gYXJnc0luZGV4O1xuICB3aGlsZSAoKytyaWdodEluZGV4IDwgcmlnaHRMZW5ndGgpIHtcbiAgICByZXN1bHRbb2Zmc2V0ICsgcmlnaHRJbmRleF0gPSBwYXJ0aWFsc1tyaWdodEluZGV4XTtcbiAgfVxuICB3aGlsZSAoKytob2xkZXJzSW5kZXggPCBob2xkZXJzTGVuZ3RoKSB7XG4gICAgcmVzdWx0W29mZnNldCArIGhvbGRlcnNbaG9sZGVyc0luZGV4XV0gPSBhcmdzW2FyZ3NJbmRleCsrXTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNvbXBvc2VBcmdzUmlnaHQ7XG4iLCJ2YXIgZ2V0TGVuZ3RoID0gcmVxdWlyZSgnLi9nZXRMZW5ndGgnKSxcbiAgICBpc0xlbmd0aCA9IHJlcXVpcmUoJy4vaXNMZW5ndGgnKSxcbiAgICB0b09iamVjdCA9IHJlcXVpcmUoJy4vdG9PYmplY3QnKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgYGJhc2VFYWNoYCBvciBgYmFzZUVhY2hSaWdodGAgZnVuY3Rpb24uXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGVhY2hGdW5jIFRoZSBmdW5jdGlvbiB0byBpdGVyYXRlIG92ZXIgYSBjb2xsZWN0aW9uLlxuICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBiYXNlIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBjcmVhdGVCYXNlRWFjaChlYWNoRnVuYywgZnJvbVJpZ2h0KSB7XG4gIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBpdGVyYXRlZSkge1xuICAgIHZhciBsZW5ndGggPSBjb2xsZWN0aW9uID8gZ2V0TGVuZ3RoKGNvbGxlY3Rpb24pIDogMDtcbiAgICBpZiAoIWlzTGVuZ3RoKGxlbmd0aCkpIHtcbiAgICAgIHJldHVybiBlYWNoRnVuYyhjb2xsZWN0aW9uLCBpdGVyYXRlZSk7XG4gICAgfVxuICAgIHZhciBpbmRleCA9IGZyb21SaWdodCA/IGxlbmd0aCA6IC0xLFxuICAgICAgICBpdGVyYWJsZSA9IHRvT2JqZWN0KGNvbGxlY3Rpb24pO1xuXG4gICAgd2hpbGUgKChmcm9tUmlnaHQgPyBpbmRleC0tIDogKytpbmRleCA8IGxlbmd0aCkpIHtcbiAgICAgIGlmIChpdGVyYXRlZShpdGVyYWJsZVtpbmRleF0sIGluZGV4LCBpdGVyYWJsZSkgPT09IGZhbHNlKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gY29sbGVjdGlvbjtcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCYXNlRWFjaDtcbiIsInZhciB0b09iamVjdCA9IHJlcXVpcmUoJy4vdG9PYmplY3QnKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgYmFzZSBmdW5jdGlvbiBmb3IgYF8uZm9ySW5gIG9yIGBfLmZvckluUmlnaHRgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtmcm9tUmlnaHRdIFNwZWNpZnkgaXRlcmF0aW5nIGZyb20gcmlnaHQgdG8gbGVmdC5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGJhc2UgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUJhc2VGb3IoZnJvbVJpZ2h0KSB7XG4gIHJldHVybiBmdW5jdGlvbihvYmplY3QsIGl0ZXJhdGVlLCBrZXlzRnVuYykge1xuICAgIHZhciBpdGVyYWJsZSA9IHRvT2JqZWN0KG9iamVjdCksXG4gICAgICAgIHByb3BzID0ga2V5c0Z1bmMob2JqZWN0KSxcbiAgICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoLFxuICAgICAgICBpbmRleCA9IGZyb21SaWdodCA/IGxlbmd0aCA6IC0xO1xuXG4gICAgd2hpbGUgKChmcm9tUmlnaHQgPyBpbmRleC0tIDogKytpbmRleCA8IGxlbmd0aCkpIHtcbiAgICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF07XG4gICAgICBpZiAoaXRlcmF0ZWUoaXRlcmFibGVba2V5XSwga2V5LCBpdGVyYWJsZSkgPT09IGZhbHNlKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gb2JqZWN0O1xuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUJhc2VGb3I7XG4iLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG52YXIgY3JlYXRlQ3RvcldyYXBwZXIgPSByZXF1aXJlKCcuL2NyZWF0ZUN0b3JXcmFwcGVyJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgd3JhcHMgYGZ1bmNgIGFuZCBpbnZva2VzIGl0IHdpdGggdGhlIGB0aGlzYFxuICogYmluZGluZyBvZiBgdGhpc0FyZ2AuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGJpbmQuXG4gKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgYm91bmQgZnVuY3Rpb24uXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUJpbmRXcmFwcGVyKGZ1bmMsIHRoaXNBcmcpIHtcbiAgdmFyIEN0b3IgPSBjcmVhdGVDdG9yV3JhcHBlcihmdW5jKTtcblxuICBmdW5jdGlvbiB3cmFwcGVyKCkge1xuICAgIHZhciBmbiA9ICh0aGlzICYmIHRoaXMgIT09IGdsb2JhbCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikgPyBDdG9yIDogZnVuYztcbiAgICByZXR1cm4gZm4uYXBwbHkodGhpc0FyZywgYXJndW1lbnRzKTtcbiAgfVxuICByZXR1cm4gd3JhcHBlcjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVCaW5kV3JhcHBlcjtcblxufSkuY2FsbCh0aGlzLHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pXG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldDp1dGYtODtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbTV2WkdWZmJXOWtkV3hsY3k5c2IyUmhjMmd0WTI5dGNHRjBMMmx1ZEdWeWJtRnNMMk55WldGMFpVSnBibVJYY21Gd2NHVnlMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGQlFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJJaXdpWm1sc1pTSTZJbWRsYm1WeVlYUmxaQzVxY3lJc0luTnZkWEpqWlZKdmIzUWlPaUlpTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKMllYSWdZM0psWVhSbFEzUnZjbGR5WVhCd1pYSWdQU0J5WlhGMWFYSmxLQ2N1TDJOeVpXRjBaVU4wYjNKWGNtRndjR1Z5SnlrN1hHNWNiaThxS2x4dUlDb2dRM0psWVhSbGN5QmhJR1oxYm1OMGFXOXVJSFJvWVhRZ2QzSmhjSE1nWUdaMWJtTmdJR0Z1WkNCcGJuWnZhMlZ6SUdsMElIZHBkR2dnZEdobElHQjBhR2x6WUZ4dUlDb2dZbWx1WkdsdVp5QnZaaUJnZEdocGMwRnlaMkF1WEc0Z0tseHVJQ29nUUhCeWFYWmhkR1ZjYmlBcUlFQndZWEpoYlNCN1JuVnVZM1JwYjI1OUlHWjFibU1nVkdobElHWjFibU4wYVc5dUlIUnZJR0pwYm1RdVhHNGdLaUJBY0dGeVlXMGdleXA5SUZ0MGFHbHpRWEpuWFNCVWFHVWdZSFJvYVhOZ0lHSnBibVJwYm1jZ2IyWWdZR1oxYm1OZ0xseHVJQ29nUUhKbGRIVnlibk1nZTBaMWJtTjBhVzl1ZlNCU1pYUjFjbTV6SUhSb1pTQnVaWGNnWW05MWJtUWdablZ1WTNScGIyNHVYRzRnS2k5Y2JtWjFibU4wYVc5dUlHTnlaV0YwWlVKcGJtUlhjbUZ3Y0dWeUtHWjFibU1zSUhSb2FYTkJjbWNwSUh0Y2JpQWdkbUZ5SUVOMGIzSWdQU0JqY21WaGRHVkRkRzl5VjNKaGNIQmxjaWhtZFc1aktUdGNibHh1SUNCbWRXNWpkR2x2YmlCM2NtRndjR1Z5S0NrZ2UxeHVJQ0FnSUhaaGNpQm1iaUE5SUNoMGFHbHpJQ1ltSUhSb2FYTWdJVDA5SUdkc2IySmhiQ0FtSmlCMGFHbHpJR2x1YzNSaGJtTmxiMllnZDNKaGNIQmxjaWtnUHlCRGRHOXlJRG9nWm5WdVl6dGNiaUFnSUNCeVpYUjFjbTRnWm00dVlYQndiSGtvZEdocGMwRnlaeXdnWVhKbmRXMWxiblJ6S1R0Y2JpQWdmVnh1SUNCeVpYUjFjbTRnZDNKaGNIQmxjanRjYm4xY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmpjbVZoZEdWQ2FXNWtWM0poY0hCbGNqdGNiaUpkZlE9PSIsInZhciBiYXNlQ3JlYXRlID0gcmVxdWlyZSgnLi9iYXNlQ3JlYXRlJyksXG4gICAgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9sYW5nL2lzT2JqZWN0Jyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgcHJvZHVjZXMgYW4gaW5zdGFuY2Ugb2YgYEN0b3JgIHJlZ2FyZGxlc3Mgb2ZcbiAqIHdoZXRoZXIgaXQgd2FzIGludm9rZWQgYXMgcGFydCBvZiBhIGBuZXdgIGV4cHJlc3Npb24gb3IgYnkgYGNhbGxgIG9yIGBhcHBseWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IEN0b3IgVGhlIGNvbnN0cnVjdG9yIHRvIHdyYXAuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBjcmVhdGVDdG9yV3JhcHBlcihDdG9yKSB7XG4gIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAvLyBVc2UgYSBgc3dpdGNoYCBzdGF0ZW1lbnQgdG8gd29yayB3aXRoIGNsYXNzIGNvbnN0cnVjdG9ycy5cbiAgICAvLyBTZWUgaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtZWNtYXNjcmlwdC1mdW5jdGlvbi1vYmplY3RzLWNhbGwtdGhpc2FyZ3VtZW50LWFyZ3VtZW50c2xpc3RcbiAgICAvLyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgIHZhciBhcmdzID0gYXJndW1lbnRzO1xuICAgIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcbiAgICAgIGNhc2UgMDogcmV0dXJuIG5ldyBDdG9yO1xuICAgICAgY2FzZSAxOiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSk7XG4gICAgICBjYXNlIDI6IHJldHVybiBuZXcgQ3RvcihhcmdzWzBdLCBhcmdzWzFdKTtcbiAgICAgIGNhc2UgMzogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0pO1xuICAgICAgY2FzZSA0OiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSk7XG4gICAgICBjYXNlIDU6IHJldHVybiBuZXcgQ3RvcihhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdLCBhcmdzWzNdLCBhcmdzWzRdKTtcbiAgICAgIGNhc2UgNjogcmV0dXJuIG5ldyBDdG9yKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0sIGFyZ3NbM10sIGFyZ3NbNF0sIGFyZ3NbNV0pO1xuICAgICAgY2FzZSA3OiByZXR1cm4gbmV3IEN0b3IoYXJnc1swXSwgYXJnc1sxXSwgYXJnc1syXSwgYXJnc1szXSwgYXJnc1s0XSwgYXJnc1s1XSwgYXJnc1s2XSk7XG4gICAgfVxuICAgIHZhciB0aGlzQmluZGluZyA9IGJhc2VDcmVhdGUoQ3Rvci5wcm90b3R5cGUpLFxuICAgICAgICByZXN1bHQgPSBDdG9yLmFwcGx5KHRoaXNCaW5kaW5nLCBhcmdzKTtcblxuICAgIC8vIE1pbWljIHRoZSBjb25zdHJ1Y3RvcidzIGByZXR1cm5gIGJlaGF2aW9yLlxuICAgIC8vIFNlZSBodHRwczovL2VzNS5naXRodWIuaW8vI3gxMy4yLjIgZm9yIG1vcmUgZGV0YWlscy5cbiAgICByZXR1cm4gaXNPYmplY3QocmVzdWx0KSA/IHJlc3VsdCA6IHRoaXNCaW5kaW5nO1xuICB9O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUN0b3JXcmFwcGVyO1xuIiwidmFyIGJhc2VDYWxsYmFjayA9IHJlcXVpcmUoJy4vYmFzZUNhbGxiYWNrJyksXG4gICAgYmFzZUZpbmQgPSByZXF1aXJlKCcuL2Jhc2VGaW5kJyksXG4gICAgYmFzZUZpbmRJbmRleCA9IHJlcXVpcmUoJy4vYmFzZUZpbmRJbmRleCcpLFxuICAgIGlzQXJyYXkgPSByZXF1aXJlKCcuLi9sYW5nL2lzQXJyYXknKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgYF8uZmluZGAgb3IgYF8uZmluZExhc3RgIGZ1bmN0aW9uLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBlYWNoRnVuYyBUaGUgZnVuY3Rpb24gdG8gaXRlcmF0ZSBvdmVyIGEgY29sbGVjdGlvbi5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2Zyb21SaWdodF0gU3BlY2lmeSBpdGVyYXRpbmcgZnJvbSByaWdodCB0byBsZWZ0LlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZmluZCBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlRmluZChlYWNoRnVuYywgZnJvbVJpZ2h0KSB7XG4gIHJldHVybiBmdW5jdGlvbihjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIHRoaXNBcmcpIHtcbiAgICBwcmVkaWNhdGUgPSBiYXNlQ2FsbGJhY2socHJlZGljYXRlLCB0aGlzQXJnLCAzKTtcbiAgICBpZiAoaXNBcnJheShjb2xsZWN0aW9uKSkge1xuICAgICAgdmFyIGluZGV4ID0gYmFzZUZpbmRJbmRleChjb2xsZWN0aW9uLCBwcmVkaWNhdGUsIGZyb21SaWdodCk7XG4gICAgICByZXR1cm4gaW5kZXggPiAtMSA/IGNvbGxlY3Rpb25baW5kZXhdIDogdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gYmFzZUZpbmQoY29sbGVjdGlvbiwgcHJlZGljYXRlLCBlYWNoRnVuYyk7XG4gIH07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlRmluZDtcbiIsInZhciBiaW5kQ2FsbGJhY2sgPSByZXF1aXJlKCcuL2JpbmRDYWxsYmFjaycpLFxuICAgIGlzQXJyYXkgPSByZXF1aXJlKCcuLi9sYW5nL2lzQXJyYXknKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgZnVuY3Rpb24gZm9yIGBfLmZvckVhY2hgIG9yIGBfLmZvckVhY2hSaWdodGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGFycmF5RnVuYyBUaGUgZnVuY3Rpb24gdG8gaXRlcmF0ZSBvdmVyIGFuIGFycmF5LlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZWFjaEZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGl0ZXJhdGUgb3ZlciBhIGNvbGxlY3Rpb24uXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBlYWNoIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBjcmVhdGVGb3JFYWNoKGFycmF5RnVuYywgZWFjaEZ1bmMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKGNvbGxlY3Rpb24sIGl0ZXJhdGVlLCB0aGlzQXJnKSB7XG4gICAgcmV0dXJuICh0eXBlb2YgaXRlcmF0ZWUgPT0gJ2Z1bmN0aW9uJyAmJiB0aGlzQXJnID09PSB1bmRlZmluZWQgJiYgaXNBcnJheShjb2xsZWN0aW9uKSlcbiAgICAgID8gYXJyYXlGdW5jKGNvbGxlY3Rpb24sIGl0ZXJhdGVlKVxuICAgICAgOiBlYWNoRnVuYyhjb2xsZWN0aW9uLCBiaW5kQ2FsbGJhY2soaXRlcmF0ZWUsIHRoaXNBcmcsIDMpKTtcbiAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVGb3JFYWNoO1xuIiwiKGZ1bmN0aW9uIChnbG9iYWwpe1xudmFyIGFycmF5Q29weSA9IHJlcXVpcmUoJy4vYXJyYXlDb3B5JyksXG4gICAgY29tcG9zZUFyZ3MgPSByZXF1aXJlKCcuL2NvbXBvc2VBcmdzJyksXG4gICAgY29tcG9zZUFyZ3NSaWdodCA9IHJlcXVpcmUoJy4vY29tcG9zZUFyZ3NSaWdodCcpLFxuICAgIGNyZWF0ZUN0b3JXcmFwcGVyID0gcmVxdWlyZSgnLi9jcmVhdGVDdG9yV3JhcHBlcicpLFxuICAgIGlzTGF6aWFibGUgPSByZXF1aXJlKCcuL2lzTGF6aWFibGUnKSxcbiAgICByZW9yZGVyID0gcmVxdWlyZSgnLi9yZW9yZGVyJyksXG4gICAgcmVwbGFjZUhvbGRlcnMgPSByZXF1aXJlKCcuL3JlcGxhY2VIb2xkZXJzJyksXG4gICAgc2V0RGF0YSA9IHJlcXVpcmUoJy4vc2V0RGF0YScpO1xuXG4vKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciB3cmFwcGVyIG1ldGFkYXRhLiAqL1xudmFyIEJJTkRfRkxBRyA9IDEsXG4gICAgQklORF9LRVlfRkxBRyA9IDIsXG4gICAgQ1VSUllfQk9VTkRfRkxBRyA9IDQsXG4gICAgQ1VSUllfRkxBRyA9IDgsXG4gICAgQ1VSUllfUklHSFRfRkxBRyA9IDE2LFxuICAgIFBBUlRJQUxfRkxBRyA9IDMyLFxuICAgIFBBUlRJQUxfUklHSFRfRkxBRyA9IDY0LFxuICAgIEFSWV9GTEFHID0gMTI4O1xuXG4vKiBOYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xudmFyIG5hdGl2ZU1heCA9IE1hdGgubWF4O1xuXG4vKipcbiAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHdyYXBzIGBmdW5jYCBhbmQgaW52b2tlcyBpdCB3aXRoIG9wdGlvbmFsIGB0aGlzYFxuICogYmluZGluZyBvZiwgcGFydGlhbCBhcHBsaWNhdGlvbiwgYW5kIGN1cnJ5aW5nLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gZnVuYyBUaGUgZnVuY3Rpb24gb3IgbWV0aG9kIG5hbWUgdG8gcmVmZXJlbmNlLlxuICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgb2YgZmxhZ3MuIFNlZSBgY3JlYXRlV3JhcHBlcmAgZm9yIG1vcmUgZGV0YWlscy5cbiAqIEBwYXJhbSB7Kn0gW3RoaXNBcmddIFRoZSBgdGhpc2AgYmluZGluZyBvZiBgZnVuY2AuXG4gKiBAcGFyYW0ge0FycmF5fSBbcGFydGlhbHNdIFRoZSBhcmd1bWVudHMgdG8gcHJlcGVuZCB0byB0aG9zZSBwcm92aWRlZCB0byB0aGUgbmV3IGZ1bmN0aW9uLlxuICogQHBhcmFtIHtBcnJheX0gW2hvbGRlcnNdIFRoZSBgcGFydGlhbHNgIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gKiBAcGFyYW0ge0FycmF5fSBbcGFydGlhbHNSaWdodF0gVGhlIGFyZ3VtZW50cyB0byBhcHBlbmQgdG8gdGhvc2UgcHJvdmlkZWQgdG8gdGhlIG5ldyBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7QXJyYXl9IFtob2xkZXJzUmlnaHRdIFRoZSBgcGFydGlhbHNSaWdodGAgcGxhY2Vob2xkZXIgaW5kZXhlcy5cbiAqIEBwYXJhbSB7QXJyYXl9IFthcmdQb3NdIFRoZSBhcmd1bWVudCBwb3NpdGlvbnMgb2YgdGhlIG5ldyBmdW5jdGlvbi5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbYXJ5XSBUaGUgYXJpdHkgY2FwIG9mIGBmdW5jYC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbYXJpdHldIFRoZSBhcml0eSBvZiBgZnVuY2AuXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyB3cmFwcGVkIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiBjcmVhdGVIeWJyaWRXcmFwcGVyKGZ1bmMsIGJpdG1hc2ssIHRoaXNBcmcsIHBhcnRpYWxzLCBob2xkZXJzLCBwYXJ0aWFsc1JpZ2h0LCBob2xkZXJzUmlnaHQsIGFyZ1BvcywgYXJ5LCBhcml0eSkge1xuICB2YXIgaXNBcnkgPSBiaXRtYXNrICYgQVJZX0ZMQUcsXG4gICAgICBpc0JpbmQgPSBiaXRtYXNrICYgQklORF9GTEFHLFxuICAgICAgaXNCaW5kS2V5ID0gYml0bWFzayAmIEJJTkRfS0VZX0ZMQUcsXG4gICAgICBpc0N1cnJ5ID0gYml0bWFzayAmIENVUlJZX0ZMQUcsXG4gICAgICBpc0N1cnJ5Qm91bmQgPSBiaXRtYXNrICYgQ1VSUllfQk9VTkRfRkxBRyxcbiAgICAgIGlzQ3VycnlSaWdodCA9IGJpdG1hc2sgJiBDVVJSWV9SSUdIVF9GTEFHLFxuICAgICAgQ3RvciA9IGlzQmluZEtleSA/IHVuZGVmaW5lZCA6IGNyZWF0ZUN0b3JXcmFwcGVyKGZ1bmMpO1xuXG4gIGZ1bmN0aW9uIHdyYXBwZXIoKSB7XG4gICAgLy8gQXZvaWQgYGFyZ3VtZW50c2Agb2JqZWN0IHVzZSBkaXNxdWFsaWZ5aW5nIG9wdGltaXphdGlvbnMgYnlcbiAgICAvLyBjb252ZXJ0aW5nIGl0IHRvIGFuIGFycmF5IGJlZm9yZSBwcm92aWRpbmcgaXQgdG8gb3RoZXIgZnVuY3Rpb25zLlxuICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoLFxuICAgICAgICBpbmRleCA9IGxlbmd0aCxcbiAgICAgICAgYXJncyA9IEFycmF5KGxlbmd0aCk7XG5cbiAgICB3aGlsZSAoaW5kZXgtLSkge1xuICAgICAgYXJnc1tpbmRleF0gPSBhcmd1bWVudHNbaW5kZXhdO1xuICAgIH1cbiAgICBpZiAocGFydGlhbHMpIHtcbiAgICAgIGFyZ3MgPSBjb21wb3NlQXJncyhhcmdzLCBwYXJ0aWFscywgaG9sZGVycyk7XG4gICAgfVxuICAgIGlmIChwYXJ0aWFsc1JpZ2h0KSB7XG4gICAgICBhcmdzID0gY29tcG9zZUFyZ3NSaWdodChhcmdzLCBwYXJ0aWFsc1JpZ2h0LCBob2xkZXJzUmlnaHQpO1xuICAgIH1cbiAgICBpZiAoaXNDdXJyeSB8fCBpc0N1cnJ5UmlnaHQpIHtcbiAgICAgIHZhciBwbGFjZWhvbGRlciA9IHdyYXBwZXIucGxhY2Vob2xkZXIsXG4gICAgICAgICAgYXJnc0hvbGRlcnMgPSByZXBsYWNlSG9sZGVycyhhcmdzLCBwbGFjZWhvbGRlcik7XG5cbiAgICAgIGxlbmd0aCAtPSBhcmdzSG9sZGVycy5sZW5ndGg7XG4gICAgICBpZiAobGVuZ3RoIDwgYXJpdHkpIHtcbiAgICAgICAgdmFyIG5ld0FyZ1BvcyA9IGFyZ1BvcyA/IGFycmF5Q29weShhcmdQb3MpIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgbmV3QXJpdHkgPSBuYXRpdmVNYXgoYXJpdHkgLSBsZW5ndGgsIDApLFxuICAgICAgICAgICAgbmV3c0hvbGRlcnMgPSBpc0N1cnJ5ID8gYXJnc0hvbGRlcnMgOiB1bmRlZmluZWQsXG4gICAgICAgICAgICBuZXdIb2xkZXJzUmlnaHQgPSBpc0N1cnJ5ID8gdW5kZWZpbmVkIDogYXJnc0hvbGRlcnMsXG4gICAgICAgICAgICBuZXdQYXJ0aWFscyA9IGlzQ3VycnkgPyBhcmdzIDogdW5kZWZpbmVkLFxuICAgICAgICAgICAgbmV3UGFydGlhbHNSaWdodCA9IGlzQ3VycnkgPyB1bmRlZmluZWQgOiBhcmdzO1xuXG4gICAgICAgIGJpdG1hc2sgfD0gKGlzQ3VycnkgPyBQQVJUSUFMX0ZMQUcgOiBQQVJUSUFMX1JJR0hUX0ZMQUcpO1xuICAgICAgICBiaXRtYXNrICY9IH4oaXNDdXJyeSA/IFBBUlRJQUxfUklHSFRfRkxBRyA6IFBBUlRJQUxfRkxBRyk7XG5cbiAgICAgICAgaWYgKCFpc0N1cnJ5Qm91bmQpIHtcbiAgICAgICAgICBiaXRtYXNrICY9IH4oQklORF9GTEFHIHwgQklORF9LRVlfRkxBRyk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG5ld0RhdGEgPSBbZnVuYywgYml0bWFzaywgdGhpc0FyZywgbmV3UGFydGlhbHMsIG5ld3NIb2xkZXJzLCBuZXdQYXJ0aWFsc1JpZ2h0LCBuZXdIb2xkZXJzUmlnaHQsIG5ld0FyZ1BvcywgYXJ5LCBuZXdBcml0eV0sXG4gICAgICAgICAgICByZXN1bHQgPSBjcmVhdGVIeWJyaWRXcmFwcGVyLmFwcGx5KHVuZGVmaW5lZCwgbmV3RGF0YSk7XG5cbiAgICAgICAgaWYgKGlzTGF6aWFibGUoZnVuYykpIHtcbiAgICAgICAgICBzZXREYXRhKHJlc3VsdCwgbmV3RGF0YSk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzdWx0LnBsYWNlaG9sZGVyID0gcGxhY2Vob2xkZXI7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuICAgIHZhciB0aGlzQmluZGluZyA9IGlzQmluZCA/IHRoaXNBcmcgOiB0aGlzLFxuICAgICAgICBmbiA9IGlzQmluZEtleSA/IHRoaXNCaW5kaW5nW2Z1bmNdIDogZnVuYztcblxuICAgIGlmIChhcmdQb3MpIHtcbiAgICAgIGFyZ3MgPSByZW9yZGVyKGFyZ3MsIGFyZ1Bvcyk7XG4gICAgfVxuICAgIGlmIChpc0FyeSAmJiBhcnkgPCBhcmdzLmxlbmd0aCkge1xuICAgICAgYXJncy5sZW5ndGggPSBhcnk7XG4gICAgfVxuICAgIGlmICh0aGlzICYmIHRoaXMgIT09IGdsb2JhbCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikge1xuICAgICAgZm4gPSBDdG9yIHx8IGNyZWF0ZUN0b3JXcmFwcGVyKGZ1bmMpO1xuICAgIH1cbiAgICByZXR1cm4gZm4uYXBwbHkodGhpc0JpbmRpbmcsIGFyZ3MpO1xuICB9XG4gIHJldHVybiB3cmFwcGVyO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZUh5YnJpZFdyYXBwZXI7XG5cbn0pLmNhbGwodGhpcyx0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ6dXRmLTg7YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW01dlpHVmZiVzlrZFd4bGN5OXNiMlJoYzJndFkyOXRjR0YwTDJsdWRHVnlibUZzTDJOeVpXRjBaVWg1WW5KcFpGZHlZWEJ3WlhJdWFuTWlYU3dpYm1GdFpYTWlPbHRkTENKdFlYQndhVzVuY3lJNklqdEJRVUZCTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJJaXdpWm1sc1pTSTZJbWRsYm1WeVlYUmxaQzVxY3lJc0luTnZkWEpqWlZKdmIzUWlPaUlpTENKemIzVnlZMlZ6UTI5dWRHVnVkQ0k2V3lKMllYSWdZWEp5WVhsRGIzQjVJRDBnY21WeGRXbHlaU2duTGk5aGNuSmhlVU52Y0hrbktTeGNiaUFnSUNCamIyMXdiM05sUVhKbmN5QTlJSEpsY1hWcGNtVW9KeTR2WTI5dGNHOXpaVUZ5WjNNbktTeGNiaUFnSUNCamIyMXdiM05sUVhKbmMxSnBaMmgwSUQwZ2NtVnhkV2x5WlNnbkxpOWpiMjF3YjNObFFYSm5jMUpwWjJoMEp5a3NYRzRnSUNBZ1kzSmxZWFJsUTNSdmNsZHlZWEJ3WlhJZ1BTQnlaWEYxYVhKbEtDY3VMMk55WldGMFpVTjBiM0pYY21Gd2NHVnlKeWtzWEc0Z0lDQWdhWE5NWVhwcFlXSnNaU0E5SUhKbGNYVnBjbVVvSnk0dmFYTk1ZWHBwWVdKc1pTY3BMRnh1SUNBZ0lISmxiM0prWlhJZ1BTQnlaWEYxYVhKbEtDY3VMM0psYjNKa1pYSW5LU3hjYmlBZ0lDQnlaWEJzWVdObFNHOXNaR1Z5Y3lBOUlISmxjWFZwY21Vb0p5NHZjbVZ3YkdGalpVaHZiR1JsY25NbktTeGNiaUFnSUNCelpYUkVZWFJoSUQwZ2NtVnhkV2x5WlNnbkxpOXpaWFJFWVhSaEp5azdYRzVjYmk4cUtpQlZjMlZrSUhSdklHTnZiWEJ2YzJVZ1ltbDBiV0Z6YTNNZ1ptOXlJSGR5WVhCd1pYSWdiV1YwWVdSaGRHRXVJQ292WEc1MllYSWdRa2xPUkY5R1RFRkhJRDBnTVN4Y2JpQWdJQ0JDU1U1RVgwdEZXVjlHVEVGSElEMGdNaXhjYmlBZ0lDQkRWVkpTV1Y5Q1QxVk9SRjlHVEVGSElEMGdOQ3hjYmlBZ0lDQkRWVkpTV1Y5R1RFRkhJRDBnT0N4Y2JpQWdJQ0JEVlZKU1dWOVNTVWRJVkY5R1RFRkhJRDBnTVRZc1hHNGdJQ0FnVUVGU1ZFbEJURjlHVEVGSElEMGdNeklzWEc0Z0lDQWdVRUZTVkVsQlRGOVNTVWRJVkY5R1RFRkhJRDBnTmpRc1hHNGdJQ0FnUVZKWlgwWk1RVWNnUFNBeE1qZzdYRzVjYmk4cUlFNWhkR2wyWlNCdFpYUm9iMlFnY21WbVpYSmxibU5sY3lCbWIzSWdkR2h2YzJVZ2QybDBhQ0IwYUdVZ2MyRnRaU0J1WVcxbElHRnpJRzkwYUdWeUlHQnNiMlJoYzJoZ0lHMWxkR2h2WkhNdUlDb3ZYRzUyWVhJZ2JtRjBhWFpsVFdGNElEMGdUV0YwYUM1dFlYZzdYRzVjYmk4cUtseHVJQ29nUTNKbFlYUmxjeUJoSUdaMWJtTjBhVzl1SUhSb1lYUWdkM0poY0hNZ1lHWjFibU5nSUdGdVpDQnBiblp2YTJWeklHbDBJSGRwZEdnZ2IzQjBhVzl1WVd3Z1lIUm9hWE5nWEc0Z0tpQmlhVzVrYVc1bklHOW1MQ0J3WVhKMGFXRnNJR0Z3Y0d4cFkyRjBhVzl1TENCaGJtUWdZM1Z5Y25scGJtY3VYRzRnS2x4dUlDb2dRSEJ5YVhaaGRHVmNiaUFxSUVCd1lYSmhiU0I3Um5WdVkzUnBiMjU4YzNSeWFXNW5mU0JtZFc1aklGUm9aU0JtZFc1amRHbHZiaUJ2Y2lCdFpYUm9iMlFnYm1GdFpTQjBieUJ5WldabGNtVnVZMlV1WEc0Z0tpQkFjR0Z5WVcwZ2UyNTFiV0psY24wZ1ltbDBiV0Z6YXlCVWFHVWdZbWwwYldGemF5QnZaaUJtYkdGbmN5NGdVMlZsSUdCamNtVmhkR1ZYY21Gd2NHVnlZQ0JtYjNJZ2JXOXlaU0JrWlhSaGFXeHpMbHh1SUNvZ1FIQmhjbUZ0SUhzcWZTQmJkR2hwYzBGeVoxMGdWR2hsSUdCMGFHbHpZQ0JpYVc1a2FXNW5JRzltSUdCbWRXNWpZQzVjYmlBcUlFQndZWEpoYlNCN1FYSnlZWGw5SUZ0d1lYSjBhV0ZzYzEwZ1ZHaGxJR0Z5WjNWdFpXNTBjeUIwYnlCd2NtVndaVzVrSUhSdklIUm9iM05sSUhCeWIzWnBaR1ZrSUhSdklIUm9aU0J1WlhjZ1puVnVZM1JwYjI0dVhHNGdLaUJBY0dGeVlXMGdlMEZ5Y21GNWZTQmJhRzlzWkdWeWMxMGdWR2hsSUdCd1lYSjBhV0ZzYzJBZ2NHeGhZMlZvYjJ4a1pYSWdhVzVrWlhobGN5NWNiaUFxSUVCd1lYSmhiU0I3UVhKeVlYbDlJRnR3WVhKMGFXRnNjMUpwWjJoMFhTQlVhR1VnWVhKbmRXMWxiblJ6SUhSdklHRndjR1Z1WkNCMGJ5QjBhRzl6WlNCd2NtOTJhV1JsWkNCMGJ5QjBhR1VnYm1WM0lHWjFibU4wYVc5dUxseHVJQ29nUUhCaGNtRnRJSHRCY25KaGVYMGdXMmh2YkdSbGNuTlNhV2RvZEYwZ1ZHaGxJR0J3WVhKMGFXRnNjMUpwWjJoMFlDQndiR0ZqWldodmJHUmxjaUJwYm1SbGVHVnpMbHh1SUNvZ1FIQmhjbUZ0SUh0QmNuSmhlWDBnVzJGeVoxQnZjMTBnVkdobElHRnlaM1Z0Wlc1MElIQnZjMmwwYVc5dWN5QnZaaUIwYUdVZ2JtVjNJR1oxYm1OMGFXOXVMbHh1SUNvZ1FIQmhjbUZ0SUh0dWRXMWlaWEo5SUZ0aGNubGRJRlJvWlNCaGNtbDBlU0JqWVhBZ2IyWWdZR1oxYm1OZ0xseHVJQ29nUUhCaGNtRnRJSHR1ZFcxaVpYSjlJRnRoY21sMGVWMGdWR2hsSUdGeWFYUjVJRzltSUdCbWRXNWpZQzVjYmlBcUlFQnlaWFIxY201eklIdEdkVzVqZEdsdmJuMGdVbVYwZFhKdWN5QjBhR1VnYm1WM0lIZHlZWEJ3WldRZ1puVnVZM1JwYjI0dVhHNGdLaTljYm1aMWJtTjBhVzl1SUdOeVpXRjBaVWg1WW5KcFpGZHlZWEJ3WlhJb1puVnVZeXdnWW1sMGJXRnpheXdnZEdocGMwRnlaeXdnY0dGeWRHbGhiSE1zSUdodmJHUmxjbk1zSUhCaGNuUnBZV3h6VW1sbmFIUXNJR2h2YkdSbGNuTlNhV2RvZEN3Z1lYSm5VRzl6TENCaGNua3NJR0Z5YVhSNUtTQjdYRzRnSUhaaGNpQnBjMEZ5ZVNBOUlHSnBkRzFoYzJzZ0ppQkJVbGxmUmt4QlJ5eGNiaUFnSUNBZ0lHbHpRbWx1WkNBOUlHSnBkRzFoYzJzZ0ppQkNTVTVFWDBaTVFVY3NYRzRnSUNBZ0lDQnBjMEpwYm1STFpYa2dQU0JpYVhSdFlYTnJJQ1lnUWtsT1JGOUxSVmxmUmt4QlJ5eGNiaUFnSUNBZ0lHbHpRM1Z5Y25rZ1BTQmlhWFJ0WVhOcklDWWdRMVZTVWxsZlJreEJSeXhjYmlBZ0lDQWdJR2x6UTNWeWNubENiM1Z1WkNBOUlHSnBkRzFoYzJzZ0ppQkRWVkpTV1Y5Q1QxVk9SRjlHVEVGSExGeHVJQ0FnSUNBZ2FYTkRkWEp5ZVZKcFoyaDBJRDBnWW1sMGJXRnpheUFtSUVOVlVsSlpYMUpKUjBoVVgwWk1RVWNzWEc0Z0lDQWdJQ0JEZEc5eUlEMGdhWE5DYVc1a1MyVjVJRDhnZFc1a1pXWnBibVZrSURvZ1kzSmxZWFJsUTNSdmNsZHlZWEJ3WlhJb1puVnVZeWs3WEc1Y2JpQWdablZ1WTNScGIyNGdkM0poY0hCbGNpZ3BJSHRjYmlBZ0lDQXZMeUJCZG05cFpDQmdZWEpuZFcxbGJuUnpZQ0J2WW1wbFkzUWdkWE5sSUdScGMzRjFZV3hwWm5scGJtY2diM0IwYVcxcGVtRjBhVzl1Y3lCaWVWeHVJQ0FnSUM4dklHTnZiblpsY25ScGJtY2dhWFFnZEc4Z1lXNGdZWEp5WVhrZ1ltVm1iM0psSUhCeWIzWnBaR2x1WnlCcGRDQjBieUJ2ZEdobGNpQm1kVzVqZEdsdmJuTXVYRzRnSUNBZ2RtRnlJR3hsYm1kMGFDQTlJR0Z5WjNWdFpXNTBjeTVzWlc1bmRHZ3NYRzRnSUNBZ0lDQWdJR2x1WkdWNElEMGdiR1Z1WjNSb0xGeHVJQ0FnSUNBZ0lDQmhjbWR6SUQwZ1FYSnlZWGtvYkdWdVozUm9LVHRjYmx4dUlDQWdJSGRvYVd4bElDaHBibVJsZUMwdEtTQjdYRzRnSUNBZ0lDQmhjbWR6VzJsdVpHVjRYU0E5SUdGeVozVnRaVzUwYzF0cGJtUmxlRjA3WEc0Z0lDQWdmVnh1SUNBZ0lHbG1JQ2h3WVhKMGFXRnNjeWtnZTF4dUlDQWdJQ0FnWVhKbmN5QTlJR052YlhCdmMyVkJjbWR6S0dGeVozTXNJSEJoY25ScFlXeHpMQ0JvYjJ4a1pYSnpLVHRjYmlBZ0lDQjlYRzRnSUNBZ2FXWWdLSEJoY25ScFlXeHpVbWxuYUhRcElIdGNiaUFnSUNBZ0lHRnlaM01nUFNCamIyMXdiM05sUVhKbmMxSnBaMmgwS0dGeVozTXNJSEJoY25ScFlXeHpVbWxuYUhRc0lHaHZiR1JsY25OU2FXZG9kQ2s3WEc0Z0lDQWdmVnh1SUNBZ0lHbG1JQ2hwYzBOMWNuSjVJSHg4SUdselEzVnljbmxTYVdkb2RDa2dlMXh1SUNBZ0lDQWdkbUZ5SUhCc1lXTmxhRzlzWkdWeUlEMGdkM0poY0hCbGNpNXdiR0ZqWldodmJHUmxjaXhjYmlBZ0lDQWdJQ0FnSUNCaGNtZHpTRzlzWkdWeWN5QTlJSEpsY0d4aFkyVkliMnhrWlhKektHRnlaM01zSUhCc1lXTmxhRzlzWkdWeUtUdGNibHh1SUNBZ0lDQWdiR1Z1WjNSb0lDMDlJR0Z5WjNOSWIyeGtaWEp6TG14bGJtZDBhRHRjYmlBZ0lDQWdJR2xtSUNoc1pXNW5kR2dnUENCaGNtbDBlU2tnZTF4dUlDQWdJQ0FnSUNCMllYSWdibVYzUVhKblVHOXpJRDBnWVhKblVHOXpJRDhnWVhKeVlYbERiM0I1S0dGeVoxQnZjeWtnT2lCMWJtUmxabWx1WldRc1hHNGdJQ0FnSUNBZ0lDQWdJQ0J1WlhkQmNtbDBlU0E5SUc1aGRHbDJaVTFoZUNoaGNtbDBlU0F0SUd4bGJtZDBhQ3dnTUNrc1hHNGdJQ0FnSUNBZ0lDQWdJQ0J1WlhkelNHOXNaR1Z5Y3lBOUlHbHpRM1Z5Y25rZ1B5QmhjbWR6U0c5c1pHVnljeUE2SUhWdVpHVm1hVzVsWkN4Y2JpQWdJQ0FnSUNBZ0lDQWdJRzVsZDBodmJHUmxjbk5TYVdkb2RDQTlJR2x6UTNWeWNua2dQeUIxYm1SbFptbHVaV1FnT2lCaGNtZHpTRzlzWkdWeWN5eGNiaUFnSUNBZ0lDQWdJQ0FnSUc1bGQxQmhjblJwWVd4eklEMGdhWE5EZFhKeWVTQS9JR0Z5WjNNZ09pQjFibVJsWm1sdVpXUXNYRzRnSUNBZ0lDQWdJQ0FnSUNCdVpYZFFZWEowYVdGc2MxSnBaMmgwSUQwZ2FYTkRkWEp5ZVNBL0lIVnVaR1ZtYVc1bFpDQTZJR0Z5WjNNN1hHNWNiaUFnSUNBZ0lDQWdZbWwwYldGemF5QjhQU0FvYVhORGRYSnllU0EvSUZCQlVsUkpRVXhmUmt4QlJ5QTZJRkJCVWxSSlFVeGZVa2xIU0ZSZlJreEJSeWs3WEc0Z0lDQWdJQ0FnSUdKcGRHMWhjMnNnSmowZ2ZpaHBjME4xY25KNUlEOGdVRUZTVkVsQlRGOVNTVWRJVkY5R1RFRkhJRG9nVUVGU1ZFbEJURjlHVEVGSEtUdGNibHh1SUNBZ0lDQWdJQ0JwWmlBb0lXbHpRM1Z5Y25sQ2IzVnVaQ2tnZTF4dUlDQWdJQ0FnSUNBZ0lHSnBkRzFoYzJzZ0pqMGdmaWhDU1U1RVgwWk1RVWNnZkNCQ1NVNUVYMHRGV1Y5R1RFRkhLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCMllYSWdibVYzUkdGMFlTQTlJRnRtZFc1akxDQmlhWFJ0WVhOckxDQjBhR2x6UVhKbkxDQnVaWGRRWVhKMGFXRnNjeXdnYm1WM2MwaHZiR1JsY25Nc0lHNWxkMUJoY25ScFlXeHpVbWxuYUhRc0lHNWxkMGh2YkdSbGNuTlNhV2RvZEN3Z2JtVjNRWEpuVUc5ekxDQmhjbmtzSUc1bGQwRnlhWFI1WFN4Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsYzNWc2RDQTlJR055WldGMFpVaDVZbkpwWkZkeVlYQndaWEl1WVhCd2JIa29kVzVrWldacGJtVmtMQ0J1WlhkRVlYUmhLVHRjYmx4dUlDQWdJQ0FnSUNCcFppQW9hWE5NWVhwcFlXSnNaU2htZFc1aktTa2dlMXh1SUNBZ0lDQWdJQ0FnSUhObGRFUmhkR0VvY21WemRXeDBMQ0J1WlhkRVlYUmhLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCeVpYTjFiSFF1Y0d4aFkyVm9iMnhrWlhJZ1BTQndiR0ZqWldodmJHUmxjanRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJSEpsYzNWc2REdGNiaUFnSUNBZ0lIMWNiaUFnSUNCOVhHNGdJQ0FnZG1GeUlIUm9hWE5DYVc1a2FXNW5JRDBnYVhOQ2FXNWtJRDhnZEdocGMwRnlaeUE2SUhSb2FYTXNYRzRnSUNBZ0lDQWdJR1p1SUQwZ2FYTkNhVzVrUzJWNUlEOGdkR2hwYzBKcGJtUnBibWRiWm5WdVkxMGdPaUJtZFc1ak8xeHVYRzRnSUNBZ2FXWWdLR0Z5WjFCdmN5a2dlMXh1SUNBZ0lDQWdZWEpuY3lBOUlISmxiM0prWlhJb1lYSm5jeXdnWVhKblVHOXpLVHRjYmlBZ0lDQjlYRzRnSUNBZ2FXWWdLR2x6UVhKNUlDWW1JR0Z5ZVNBOElHRnlaM011YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0JoY21kekxteGxibWQwYUNBOUlHRnllVHRjYmlBZ0lDQjlYRzRnSUNBZ2FXWWdLSFJvYVhNZ0ppWWdkR2hwY3lBaFBUMGdaMnh2WW1Gc0lDWW1JSFJvYVhNZ2FXNXpkR0Z1WTJWdlppQjNjbUZ3Y0dWeUtTQjdYRzRnSUNBZ0lDQm1iaUE5SUVOMGIzSWdmSHdnWTNKbFlYUmxRM1J2Y2xkeVlYQndaWElvWm5WdVl5azdYRzRnSUNBZ2ZWeHVJQ0FnSUhKbGRIVnliaUJtYmk1aGNIQnNlU2gwYUdselFtbHVaR2x1Wnl3Z1lYSm5jeWs3WEc0Z0lIMWNiaUFnY21WMGRYSnVJSGR5WVhCd1pYSTdYRzU5WEc1Y2JtMXZaSFZzWlM1bGVIQnZjblJ6SUQwZ1kzSmxZWFJsU0hsaWNtbGtWM0poY0hCbGNqdGNiaUpkZlE9PSIsIihmdW5jdGlvbiAoZ2xvYmFsKXtcbnZhciBjcmVhdGVDdG9yV3JhcHBlciA9IHJlcXVpcmUoJy4vY3JlYXRlQ3RvcldyYXBwZXInKTtcblxuLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3Igd3JhcHBlciBtZXRhZGF0YS4gKi9cbnZhciBCSU5EX0ZMQUcgPSAxO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHdyYXBzIGBmdW5jYCBhbmQgaW52b2tlcyBpdCB3aXRoIHRoZSBvcHRpb25hbCBgdGhpc2BcbiAqIGJpbmRpbmcgb2YgYHRoaXNBcmdgIGFuZCB0aGUgYHBhcnRpYWxzYCBwcmVwZW5kZWQgdG8gdGhvc2UgcHJvdmlkZWQgdG9cbiAqIHRoZSB3cmFwcGVyLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBwYXJ0aWFsbHkgYXBwbHkgYXJndW1lbnRzIHRvLlxuICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgb2YgZmxhZ3MuIFNlZSBgY3JlYXRlV3JhcHBlcmAgZm9yIG1vcmUgZGV0YWlscy5cbiAqIEBwYXJhbSB7Kn0gdGhpc0FyZyBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICogQHBhcmFtIHtBcnJheX0gcGFydGlhbHMgVGhlIGFyZ3VtZW50cyB0byBwcmVwZW5kIHRvIHRob3NlIHByb3ZpZGVkIHRvIHRoZSBuZXcgZnVuY3Rpb24uXG4gKiBAcmV0dXJucyB7RnVuY3Rpb259IFJldHVybnMgdGhlIG5ldyBib3VuZCBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlUGFydGlhbFdyYXBwZXIoZnVuYywgYml0bWFzaywgdGhpc0FyZywgcGFydGlhbHMpIHtcbiAgdmFyIGlzQmluZCA9IGJpdG1hc2sgJiBCSU5EX0ZMQUcsXG4gICAgICBDdG9yID0gY3JlYXRlQ3RvcldyYXBwZXIoZnVuYyk7XG5cbiAgZnVuY3Rpb24gd3JhcHBlcigpIHtcbiAgICAvLyBBdm9pZCBgYXJndW1lbnRzYCBvYmplY3QgdXNlIGRpc3F1YWxpZnlpbmcgb3B0aW1pemF0aW9ucyBieVxuICAgIC8vIGNvbnZlcnRpbmcgaXQgdG8gYW4gYXJyYXkgYmVmb3JlIHByb3ZpZGluZyBpdCBgZnVuY2AuXG4gICAgdmFyIGFyZ3NJbmRleCA9IC0xLFxuICAgICAgICBhcmdzTGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aCxcbiAgICAgICAgbGVmdEluZGV4ID0gLTEsXG4gICAgICAgIGxlZnRMZW5ndGggPSBwYXJ0aWFscy5sZW5ndGgsXG4gICAgICAgIGFyZ3MgPSBBcnJheShsZWZ0TGVuZ3RoICsgYXJnc0xlbmd0aCk7XG5cbiAgICB3aGlsZSAoKytsZWZ0SW5kZXggPCBsZWZ0TGVuZ3RoKSB7XG4gICAgICBhcmdzW2xlZnRJbmRleF0gPSBwYXJ0aWFsc1tsZWZ0SW5kZXhdO1xuICAgIH1cbiAgICB3aGlsZSAoYXJnc0xlbmd0aC0tKSB7XG4gICAgICBhcmdzW2xlZnRJbmRleCsrXSA9IGFyZ3VtZW50c1srK2FyZ3NJbmRleF07XG4gICAgfVxuICAgIHZhciBmbiA9ICh0aGlzICYmIHRoaXMgIT09IGdsb2JhbCAmJiB0aGlzIGluc3RhbmNlb2Ygd3JhcHBlcikgPyBDdG9yIDogZnVuYztcbiAgICByZXR1cm4gZm4uYXBwbHkoaXNCaW5kID8gdGhpc0FyZyA6IHRoaXMsIGFyZ3MpO1xuICB9XG4gIHJldHVybiB3cmFwcGVyO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGNyZWF0ZVBhcnRpYWxXcmFwcGVyO1xuXG59KS5jYWxsKHRoaXMsdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSlcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtjaGFyc2V0OnV0Zi04O2Jhc2U2NCxleUoyWlhKemFXOXVJam96TENKemIzVnlZMlZ6SWpwYkltNXZaR1ZmYlc5a2RXeGxjeTlzYjJSaGMyZ3RZMjl0Y0dGMEwybHVkR1Z5Ym1Gc0wyTnlaV0YwWlZCaGNuUnBZV3hYY21Gd2NHVnlMbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGQlFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQklpd2labWxzWlNJNkltZGxibVZ5WVhSbFpDNXFjeUlzSW5OdmRYSmpaVkp2YjNRaU9pSWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUoyWVhJZ1kzSmxZWFJsUTNSdmNsZHlZWEJ3WlhJZ1BTQnlaWEYxYVhKbEtDY3VMMk55WldGMFpVTjBiM0pYY21Gd2NHVnlKeWs3WEc1Y2JpOHFLaUJWYzJWa0lIUnZJR052YlhCdmMyVWdZbWwwYldGemEzTWdabTl5SUhkeVlYQndaWElnYldWMFlXUmhkR0V1SUNvdlhHNTJZWElnUWtsT1JGOUdURUZISUQwZ01UdGNibHh1THlvcVhHNGdLaUJEY21WaGRHVnpJR0VnWm5WdVkzUnBiMjRnZEdoaGRDQjNjbUZ3Y3lCZ1puVnVZMkFnWVc1a0lHbHVkbTlyWlhNZ2FYUWdkMmwwYUNCMGFHVWdiM0IwYVc5dVlXd2dZSFJvYVhOZ1hHNGdLaUJpYVc1a2FXNW5JRzltSUdCMGFHbHpRWEpuWUNCaGJtUWdkR2hsSUdCd1lYSjBhV0ZzYzJBZ2NISmxjR1Z1WkdWa0lIUnZJSFJvYjNObElIQnliM1pwWkdWa0lIUnZYRzRnS2lCMGFHVWdkM0poY0hCbGNpNWNiaUFxWEc0Z0tpQkFjSEpwZG1GMFpWeHVJQ29nUUhCaGNtRnRJSHRHZFc1amRHbHZibjBnWm5WdVl5QlVhR1VnWm5WdVkzUnBiMjRnZEc4Z2NHRnlkR2xoYkd4NUlHRndjR3g1SUdGeVozVnRaVzUwY3lCMGJ5NWNiaUFxSUVCd1lYSmhiU0I3Ym5WdFltVnlmU0JpYVhSdFlYTnJJRlJvWlNCaWFYUnRZWE5ySUc5bUlHWnNZV2R6TGlCVFpXVWdZR055WldGMFpWZHlZWEJ3WlhKZ0lHWnZjaUJ0YjNKbElHUmxkR0ZwYkhNdVhHNGdLaUJBY0dGeVlXMGdleXA5SUhSb2FYTkJjbWNnVkdobElHQjBhR2x6WUNCaWFXNWthVzVuSUc5bUlHQm1kVzVqWUM1Y2JpQXFJRUJ3WVhKaGJTQjdRWEp5WVhsOUlIQmhjblJwWVd4eklGUm9aU0JoY21kMWJXVnVkSE1nZEc4Z2NISmxjR1Z1WkNCMGJ5QjBhRzl6WlNCd2NtOTJhV1JsWkNCMGJ5QjBhR1VnYm1WM0lHWjFibU4wYVc5dUxseHVJQ29nUUhKbGRIVnlibk1nZTBaMWJtTjBhVzl1ZlNCU1pYUjFjbTV6SUhSb1pTQnVaWGNnWW05MWJtUWdablZ1WTNScGIyNHVYRzRnS2k5Y2JtWjFibU4wYVc5dUlHTnlaV0YwWlZCaGNuUnBZV3hYY21Gd2NHVnlLR1oxYm1Nc0lHSnBkRzFoYzJzc0lIUm9hWE5CY21jc0lIQmhjblJwWVd4ektTQjdYRzRnSUhaaGNpQnBjMEpwYm1RZ1BTQmlhWFJ0WVhOcklDWWdRa2xPUkY5R1RFRkhMRnh1SUNBZ0lDQWdRM1J2Y2lBOUlHTnlaV0YwWlVOMGIzSlhjbUZ3Y0dWeUtHWjFibU1wTzF4dVhHNGdJR1oxYm1OMGFXOXVJSGR5WVhCd1pYSW9LU0I3WEc0Z0lDQWdMeThnUVhadmFXUWdZR0Z5WjNWdFpXNTBjMkFnYjJKcVpXTjBJSFZ6WlNCa2FYTnhkV0ZzYVdaNWFXNW5JRzl3ZEdsdGFYcGhkR2x2Ym5NZ1lubGNiaUFnSUNBdkx5QmpiMjUyWlhKMGFXNW5JR2wwSUhSdklHRnVJR0Z5Y21GNUlHSmxabTl5WlNCd2NtOTJhV1JwYm1jZ2FYUWdZR1oxYm1OZ0xseHVJQ0FnSUhaaGNpQmhjbWR6U1c1a1pYZ2dQU0F0TVN4Y2JpQWdJQ0FnSUNBZ1lYSm5jMHhsYm1kMGFDQTlJR0Z5WjNWdFpXNTBjeTVzWlc1bmRHZ3NYRzRnSUNBZ0lDQWdJR3hsWm5SSmJtUmxlQ0E5SUMweExGeHVJQ0FnSUNBZ0lDQnNaV1owVEdWdVozUm9JRDBnY0dGeWRHbGhiSE11YkdWdVozUm9MRnh1SUNBZ0lDQWdJQ0JoY21keklEMGdRWEp5WVhrb2JHVm1kRXhsYm1kMGFDQXJJR0Z5WjNOTVpXNW5kR2dwTzF4dVhHNGdJQ0FnZDJocGJHVWdLQ3NyYkdWbWRFbHVaR1Y0SUR3Z2JHVm1kRXhsYm1kMGFDa2dlMXh1SUNBZ0lDQWdZWEpuYzF0c1pXWjBTVzVrWlhoZElEMGdjR0Z5ZEdsaGJITmJiR1ZtZEVsdVpHVjRYVHRjYmlBZ0lDQjlYRzRnSUNBZ2QyaHBiR1VnS0dGeVozTk1aVzVuZEdndExTa2dlMXh1SUNBZ0lDQWdZWEpuYzF0c1pXWjBTVzVrWlhncksxMGdQU0JoY21kMWJXVnVkSE5iS3l0aGNtZHpTVzVrWlhoZE8xeHVJQ0FnSUgxY2JpQWdJQ0IyWVhJZ1ptNGdQU0FvZEdocGN5QW1KaUIwYUdseklDRTlQU0JuYkc5aVlXd2dKaVlnZEdocGN5QnBibk4wWVc1alpXOW1JSGR5WVhCd1pYSXBJRDhnUTNSdmNpQTZJR1oxYm1NN1hHNGdJQ0FnY21WMGRYSnVJR1p1TG1Gd2NHeDVLR2x6UW1sdVpDQS9JSFJvYVhOQmNtY2dPaUIwYUdsekxDQmhjbWR6S1R0Y2JpQWdmVnh1SUNCeVpYUjFjbTRnZDNKaGNIQmxjanRjYm4xY2JseHViVzlrZFd4bExtVjRjRzl5ZEhNZ1BTQmpjbVZoZEdWUVlYSjBhV0ZzVjNKaGNIQmxjanRjYmlKZGZRPT0iLCJ2YXIgYmFzZVNldERhdGEgPSByZXF1aXJlKCcuL2Jhc2VTZXREYXRhJyksXG4gICAgY3JlYXRlQmluZFdyYXBwZXIgPSByZXF1aXJlKCcuL2NyZWF0ZUJpbmRXcmFwcGVyJyksXG4gICAgY3JlYXRlSHlicmlkV3JhcHBlciA9IHJlcXVpcmUoJy4vY3JlYXRlSHlicmlkV3JhcHBlcicpLFxuICAgIGNyZWF0ZVBhcnRpYWxXcmFwcGVyID0gcmVxdWlyZSgnLi9jcmVhdGVQYXJ0aWFsV3JhcHBlcicpLFxuICAgIGdldERhdGEgPSByZXF1aXJlKCcuL2dldERhdGEnKSxcbiAgICBtZXJnZURhdGEgPSByZXF1aXJlKCcuL21lcmdlRGF0YScpLFxuICAgIHNldERhdGEgPSByZXF1aXJlKCcuL3NldERhdGEnKTtcblxuLyoqIFVzZWQgdG8gY29tcG9zZSBiaXRtYXNrcyBmb3Igd3JhcHBlciBtZXRhZGF0YS4gKi9cbnZhciBCSU5EX0ZMQUcgPSAxLFxuICAgIEJJTkRfS0VZX0ZMQUcgPSAyLFxuICAgIFBBUlRJQUxfRkxBRyA9IDMyLFxuICAgIFBBUlRJQUxfUklHSFRfRkxBRyA9IDY0O1xuXG4vKiogVXNlZCBhcyB0aGUgYFR5cGVFcnJvcmAgbWVzc2FnZSBmb3IgXCJGdW5jdGlvbnNcIiBtZXRob2RzLiAqL1xudmFyIEZVTkNfRVJST1JfVEVYVCA9ICdFeHBlY3RlZCBhIGZ1bmN0aW9uJztcblxuLyogTmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVNYXggPSBNYXRoLm1heDtcblxuLyoqXG4gKiBDcmVhdGVzIGEgZnVuY3Rpb24gdGhhdCBlaXRoZXIgY3VycmllcyBvciBpbnZva2VzIGBmdW5jYCB3aXRoIG9wdGlvbmFsXG4gKiBgdGhpc2AgYmluZGluZyBhbmQgcGFydGlhbGx5IGFwcGxpZWQgYXJndW1lbnRzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufHN0cmluZ30gZnVuYyBUaGUgZnVuY3Rpb24gb3IgbWV0aG9kIG5hbWUgdG8gcmVmZXJlbmNlLlxuICogQHBhcmFtIHtudW1iZXJ9IGJpdG1hc2sgVGhlIGJpdG1hc2sgb2YgZmxhZ3MuXG4gKiAgVGhlIGJpdG1hc2sgbWF5IGJlIGNvbXBvc2VkIG9mIHRoZSBmb2xsb3dpbmcgZmxhZ3M6XG4gKiAgICAgMSAtIGBfLmJpbmRgXG4gKiAgICAgMiAtIGBfLmJpbmRLZXlgXG4gKiAgICAgNCAtIGBfLmN1cnJ5YCBvciBgXy5jdXJyeVJpZ2h0YCBvZiBhIGJvdW5kIGZ1bmN0aW9uXG4gKiAgICAgOCAtIGBfLmN1cnJ5YFxuICogICAgMTYgLSBgXy5jdXJyeVJpZ2h0YFxuICogICAgMzIgLSBgXy5wYXJ0aWFsYFxuICogICAgNjQgLSBgXy5wYXJ0aWFsUmlnaHRgXG4gKiAgIDEyOCAtIGBfLnJlYXJnYFxuICogICAyNTYgLSBgXy5hcnlgXG4gKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGZ1bmNgLlxuICogQHBhcmFtIHtBcnJheX0gW3BhcnRpYWxzXSBUaGUgYXJndW1lbnRzIHRvIGJlIHBhcnRpYWxseSBhcHBsaWVkLlxuICogQHBhcmFtIHtBcnJheX0gW2hvbGRlcnNdIFRoZSBgcGFydGlhbHNgIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gKiBAcGFyYW0ge0FycmF5fSBbYXJnUG9zXSBUaGUgYXJndW1lbnQgcG9zaXRpb25zIG9mIHRoZSBuZXcgZnVuY3Rpb24uXG4gKiBAcGFyYW0ge251bWJlcn0gW2FyeV0gVGhlIGFyaXR5IGNhcCBvZiBgZnVuY2AuXG4gKiBAcGFyYW0ge251bWJlcn0gW2FyaXR5XSBUaGUgYXJpdHkgb2YgYGZ1bmNgLlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgd3JhcHBlZCBmdW5jdGlvbi5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlV3JhcHBlcihmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscywgaG9sZGVycywgYXJnUG9zLCBhcnksIGFyaXR5KSB7XG4gIHZhciBpc0JpbmRLZXkgPSBiaXRtYXNrICYgQklORF9LRVlfRkxBRztcbiAgaWYgKCFpc0JpbmRLZXkgJiYgdHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgfVxuICB2YXIgbGVuZ3RoID0gcGFydGlhbHMgPyBwYXJ0aWFscy5sZW5ndGggOiAwO1xuICBpZiAoIWxlbmd0aCkge1xuICAgIGJpdG1hc2sgJj0gfihQQVJUSUFMX0ZMQUcgfCBQQVJUSUFMX1JJR0hUX0ZMQUcpO1xuICAgIHBhcnRpYWxzID0gaG9sZGVycyA9IHVuZGVmaW5lZDtcbiAgfVxuICBsZW5ndGggLT0gKGhvbGRlcnMgPyBob2xkZXJzLmxlbmd0aCA6IDApO1xuICBpZiAoYml0bWFzayAmIFBBUlRJQUxfUklHSFRfRkxBRykge1xuICAgIHZhciBwYXJ0aWFsc1JpZ2h0ID0gcGFydGlhbHMsXG4gICAgICAgIGhvbGRlcnNSaWdodCA9IGhvbGRlcnM7XG5cbiAgICBwYXJ0aWFscyA9IGhvbGRlcnMgPSB1bmRlZmluZWQ7XG4gIH1cbiAgdmFyIGRhdGEgPSBpc0JpbmRLZXkgPyB1bmRlZmluZWQgOiBnZXREYXRhKGZ1bmMpLFxuICAgICAgbmV3RGF0YSA9IFtmdW5jLCBiaXRtYXNrLCB0aGlzQXJnLCBwYXJ0aWFscywgaG9sZGVycywgcGFydGlhbHNSaWdodCwgaG9sZGVyc1JpZ2h0LCBhcmdQb3MsIGFyeSwgYXJpdHldO1xuXG4gIGlmIChkYXRhKSB7XG4gICAgbWVyZ2VEYXRhKG5ld0RhdGEsIGRhdGEpO1xuICAgIGJpdG1hc2sgPSBuZXdEYXRhWzFdO1xuICAgIGFyaXR5ID0gbmV3RGF0YVs5XTtcbiAgfVxuICBuZXdEYXRhWzldID0gYXJpdHkgPT0gbnVsbFxuICAgID8gKGlzQmluZEtleSA/IDAgOiBmdW5jLmxlbmd0aClcbiAgICA6IChuYXRpdmVNYXgoYXJpdHkgLSBsZW5ndGgsIDApIHx8IDApO1xuXG4gIGlmIChiaXRtYXNrID09IEJJTkRfRkxBRykge1xuICAgIHZhciByZXN1bHQgPSBjcmVhdGVCaW5kV3JhcHBlcihuZXdEYXRhWzBdLCBuZXdEYXRhWzJdKTtcbiAgfSBlbHNlIGlmICgoYml0bWFzayA9PSBQQVJUSUFMX0ZMQUcgfHwgYml0bWFzayA9PSAoQklORF9GTEFHIHwgUEFSVElBTF9GTEFHKSkgJiYgIW5ld0RhdGFbNF0ubGVuZ3RoKSB7XG4gICAgcmVzdWx0ID0gY3JlYXRlUGFydGlhbFdyYXBwZXIuYXBwbHkodW5kZWZpbmVkLCBuZXdEYXRhKTtcbiAgfSBlbHNlIHtcbiAgICByZXN1bHQgPSBjcmVhdGVIeWJyaWRXcmFwcGVyLmFwcGx5KHVuZGVmaW5lZCwgbmV3RGF0YSk7XG4gIH1cbiAgdmFyIHNldHRlciA9IGRhdGEgPyBiYXNlU2V0RGF0YSA6IHNldERhdGE7XG4gIHJldHVybiBzZXR0ZXIocmVzdWx0LCBuZXdEYXRhKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVXcmFwcGVyO1xuIiwidmFyIGFycmF5U29tZSA9IHJlcXVpcmUoJy4vYXJyYXlTb21lJyk7XG5cbi8qKlxuICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlSXNFcXVhbERlZXBgIGZvciBhcnJheXMgd2l0aCBzdXBwb3J0IGZvclxuICogcGFydGlhbCBkZWVwIGNvbXBhcmlzb25zLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7QXJyYXl9IG90aGVyIFRoZSBvdGhlciBhcnJheSB0byBjb21wYXJlLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaW5nIGFycmF5cy5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzTG9vc2VdIFNwZWNpZnkgcGVyZm9ybWluZyBwYXJ0aWFsIGNvbXBhcmlzb25zLlxuICogQHBhcmFtIHtBcnJheX0gW3N0YWNrQV0gVHJhY2tzIHRyYXZlcnNlZCBgdmFsdWVgIG9iamVjdHMuXG4gKiBAcGFyYW0ge0FycmF5fSBbc3RhY2tCXSBUcmFja3MgdHJhdmVyc2VkIGBvdGhlcmAgb2JqZWN0cy5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYXJyYXlzIGFyZSBlcXVpdmFsZW50LCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGVxdWFsQXJyYXlzKGFycmF5LCBvdGhlciwgZXF1YWxGdW5jLCBjdXN0b21pemVyLCBpc0xvb3NlLCBzdGFja0EsIHN0YWNrQikge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGFyckxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgIG90aExlbmd0aCA9IG90aGVyLmxlbmd0aDtcblxuICBpZiAoYXJyTGVuZ3RoICE9IG90aExlbmd0aCAmJiAhKGlzTG9vc2UgJiYgb3RoTGVuZ3RoID4gYXJyTGVuZ3RoKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICAvLyBJZ25vcmUgbm9uLWluZGV4IHByb3BlcnRpZXMuXG4gIHdoaWxlICgrK2luZGV4IDwgYXJyTGVuZ3RoKSB7XG4gICAgdmFyIGFyclZhbHVlID0gYXJyYXlbaW5kZXhdLFxuICAgICAgICBvdGhWYWx1ZSA9IG90aGVyW2luZGV4XSxcbiAgICAgICAgcmVzdWx0ID0gY3VzdG9taXplciA/IGN1c3RvbWl6ZXIoaXNMb29zZSA/IG90aFZhbHVlIDogYXJyVmFsdWUsIGlzTG9vc2UgPyBhcnJWYWx1ZSA6IG90aFZhbHVlLCBpbmRleCkgOiB1bmRlZmluZWQ7XG5cbiAgICBpZiAocmVzdWx0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgYXJyYXlzIChzdXNjZXB0aWJsZSB0byBjYWxsIHN0YWNrIGxpbWl0cykuXG4gICAgaWYgKGlzTG9vc2UpIHtcbiAgICAgIGlmICghYXJyYXlTb21lKG90aGVyLCBmdW5jdGlvbihvdGhWYWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGFyclZhbHVlID09PSBvdGhWYWx1ZSB8fCBlcXVhbEZ1bmMoYXJyVmFsdWUsIG90aFZhbHVlLCBjdXN0b21pemVyLCBpc0xvb3NlLCBzdGFja0EsIHN0YWNrQik7XG4gICAgICAgICAgfSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoIShhcnJWYWx1ZSA9PT0gb3RoVmFsdWUgfHwgZXF1YWxGdW5jKGFyclZhbHVlLCBvdGhWYWx1ZSwgY3VzdG9taXplciwgaXNMb29zZSwgc3RhY2tBLCBzdGFja0IpKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBlcXVhbEFycmF5cztcbiIsIi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBib29sVGFnID0gJ1tvYmplY3QgQm9vbGVhbl0nLFxuICAgIGRhdGVUYWcgPSAnW29iamVjdCBEYXRlXScsXG4gICAgZXJyb3JUYWcgPSAnW29iamVjdCBFcnJvcl0nLFxuICAgIG51bWJlclRhZyA9ICdbb2JqZWN0IE51bWJlcl0nLFxuICAgIHJlZ2V4cFRhZyA9ICdbb2JqZWN0IFJlZ0V4cF0nLFxuICAgIHN0cmluZ1RhZyA9ICdbb2JqZWN0IFN0cmluZ10nO1xuXG4vKipcbiAqIEEgc3BlY2lhbGl6ZWQgdmVyc2lvbiBvZiBgYmFzZUlzRXF1YWxEZWVwYCBmb3IgY29tcGFyaW5nIG9iamVjdHMgb2ZcbiAqIHRoZSBzYW1lIGB0b1N0cmluZ1RhZ2AuXG4gKlxuICogKipOb3RlOioqIFRoaXMgZnVuY3Rpb24gb25seSBzdXBwb3J0cyBjb21wYXJpbmcgdmFsdWVzIHdpdGggdGFncyBvZlxuICogYEJvb2xlYW5gLCBgRGF0ZWAsIGBFcnJvcmAsIGBOdW1iZXJgLCBgUmVnRXhwYCwgb3IgYFN0cmluZ2AuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjb21wYXJlLlxuICogQHBhcmFtIHtPYmplY3R9IG90aGVyIFRoZSBvdGhlciBvYmplY3QgdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgVGhlIGB0b1N0cmluZ1RhZ2Agb2YgdGhlIG9iamVjdHMgdG8gY29tcGFyZS5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBlcXVhbEJ5VGFnKG9iamVjdCwgb3RoZXIsIHRhZykge1xuICBzd2l0Y2ggKHRhZykge1xuICAgIGNhc2UgYm9vbFRhZzpcbiAgICBjYXNlIGRhdGVUYWc6XG4gICAgICAvLyBDb2VyY2UgZGF0ZXMgYW5kIGJvb2xlYW5zIHRvIG51bWJlcnMsIGRhdGVzIHRvIG1pbGxpc2Vjb25kcyBhbmQgYm9vbGVhbnNcbiAgICAgIC8vIHRvIGAxYCBvciBgMGAgdHJlYXRpbmcgaW52YWxpZCBkYXRlcyBjb2VyY2VkIHRvIGBOYU5gIGFzIG5vdCBlcXVhbC5cbiAgICAgIHJldHVybiArb2JqZWN0ID09ICtvdGhlcjtcblxuICAgIGNhc2UgZXJyb3JUYWc6XG4gICAgICByZXR1cm4gb2JqZWN0Lm5hbWUgPT0gb3RoZXIubmFtZSAmJiBvYmplY3QubWVzc2FnZSA9PSBvdGhlci5tZXNzYWdlO1xuXG4gICAgY2FzZSBudW1iZXJUYWc6XG4gICAgICAvLyBUcmVhdCBgTmFOYCB2cy4gYE5hTmAgYXMgZXF1YWwuXG4gICAgICByZXR1cm4gKG9iamVjdCAhPSArb2JqZWN0KVxuICAgICAgICA/IG90aGVyICE9ICtvdGhlclxuICAgICAgICA6IG9iamVjdCA9PSArb3RoZXI7XG5cbiAgICBjYXNlIHJlZ2V4cFRhZzpcbiAgICBjYXNlIHN0cmluZ1RhZzpcbiAgICAgIC8vIENvZXJjZSByZWdleGVzIHRvIHN0cmluZ3MgYW5kIHRyZWF0IHN0cmluZ3MgcHJpbWl0aXZlcyBhbmQgc3RyaW5nXG4gICAgICAvLyBvYmplY3RzIGFzIGVxdWFsLiBTZWUgaHR0cHM6Ly9lczUuZ2l0aHViLmlvLyN4MTUuMTAuNi40IGZvciBtb3JlIGRldGFpbHMuXG4gICAgICByZXR1cm4gb2JqZWN0ID09IChvdGhlciArICcnKTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZXF1YWxCeVRhZztcbiIsInZhciBrZXlzID0gcmVxdWlyZSgnLi4vb2JqZWN0L2tleXMnKTtcblxuLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogQSBzcGVjaWFsaXplZCB2ZXJzaW9uIG9mIGBiYXNlSXNFcXVhbERlZXBgIGZvciBvYmplY3RzIHdpdGggc3VwcG9ydCBmb3JcbiAqIHBhcnRpYWwgZGVlcCBjb21wYXJpc29ucy5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIGNvbXBhcmUuXG4gKiBAcGFyYW0ge09iamVjdH0gb3RoZXIgVGhlIG90aGVyIG9iamVjdCB0byBjb21wYXJlLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gZXF1YWxGdW5jIFRoZSBmdW5jdGlvbiB0byBkZXRlcm1pbmUgZXF1aXZhbGVudHMgb2YgdmFsdWVzLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY29tcGFyaW5nIHZhbHVlcy5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzTG9vc2VdIFNwZWNpZnkgcGVyZm9ybWluZyBwYXJ0aWFsIGNvbXBhcmlzb25zLlxuICogQHBhcmFtIHtBcnJheX0gW3N0YWNrQV0gVHJhY2tzIHRyYXZlcnNlZCBgdmFsdWVgIG9iamVjdHMuXG4gKiBAcGFyYW0ge0FycmF5fSBbc3RhY2tCXSBUcmFja3MgdHJhdmVyc2VkIGBvdGhlcmAgb2JqZWN0cy5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgb2JqZWN0cyBhcmUgZXF1aXZhbGVudCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBlcXVhbE9iamVjdHMob2JqZWN0LCBvdGhlciwgZXF1YWxGdW5jLCBjdXN0b21pemVyLCBpc0xvb3NlLCBzdGFja0EsIHN0YWNrQikge1xuICB2YXIgb2JqUHJvcHMgPSBrZXlzKG9iamVjdCksXG4gICAgICBvYmpMZW5ndGggPSBvYmpQcm9wcy5sZW5ndGgsXG4gICAgICBvdGhQcm9wcyA9IGtleXMob3RoZXIpLFxuICAgICAgb3RoTGVuZ3RoID0gb3RoUHJvcHMubGVuZ3RoO1xuXG4gIGlmIChvYmpMZW5ndGggIT0gb3RoTGVuZ3RoICYmICFpc0xvb3NlKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHZhciBpbmRleCA9IG9iakxlbmd0aDtcbiAgd2hpbGUgKGluZGV4LS0pIHtcbiAgICB2YXIga2V5ID0gb2JqUHJvcHNbaW5kZXhdO1xuICAgIGlmICghKGlzTG9vc2UgPyBrZXkgaW4gb3RoZXIgOiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG90aGVyLCBrZXkpKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICB2YXIgc2tpcEN0b3IgPSBpc0xvb3NlO1xuICB3aGlsZSAoKytpbmRleCA8IG9iakxlbmd0aCkge1xuICAgIGtleSA9IG9ialByb3BzW2luZGV4XTtcbiAgICB2YXIgb2JqVmFsdWUgPSBvYmplY3Rba2V5XSxcbiAgICAgICAgb3RoVmFsdWUgPSBvdGhlcltrZXldLFxuICAgICAgICByZXN1bHQgPSBjdXN0b21pemVyID8gY3VzdG9taXplcihpc0xvb3NlID8gb3RoVmFsdWUgOiBvYmpWYWx1ZSwgaXNMb29zZT8gb2JqVmFsdWUgOiBvdGhWYWx1ZSwga2V5KSA6IHVuZGVmaW5lZDtcblxuICAgIC8vIFJlY3Vyc2l2ZWx5IGNvbXBhcmUgb2JqZWN0cyAoc3VzY2VwdGlibGUgdG8gY2FsbCBzdGFjayBsaW1pdHMpLlxuICAgIGlmICghKHJlc3VsdCA9PT0gdW5kZWZpbmVkID8gZXF1YWxGdW5jKG9ialZhbHVlLCBvdGhWYWx1ZSwgY3VzdG9taXplciwgaXNMb29zZSwgc3RhY2tBLCBzdGFja0IpIDogcmVzdWx0KSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBza2lwQ3RvciB8fCAoc2tpcEN0b3IgPSBrZXkgPT0gJ2NvbnN0cnVjdG9yJyk7XG4gIH1cbiAgaWYgKCFza2lwQ3Rvcikge1xuICAgIHZhciBvYmpDdG9yID0gb2JqZWN0LmNvbnN0cnVjdG9yLFxuICAgICAgICBvdGhDdG9yID0gb3RoZXIuY29uc3RydWN0b3I7XG5cbiAgICAvLyBOb24gYE9iamVjdGAgb2JqZWN0IGluc3RhbmNlcyB3aXRoIGRpZmZlcmVudCBjb25zdHJ1Y3RvcnMgYXJlIG5vdCBlcXVhbC5cbiAgICBpZiAob2JqQ3RvciAhPSBvdGhDdG9yICYmXG4gICAgICAgICgnY29uc3RydWN0b3InIGluIG9iamVjdCAmJiAnY29uc3RydWN0b3InIGluIG90aGVyKSAmJlxuICAgICAgICAhKHR5cGVvZiBvYmpDdG9yID09ICdmdW5jdGlvbicgJiYgb2JqQ3RvciBpbnN0YW5jZW9mIG9iakN0b3IgJiZcbiAgICAgICAgICB0eXBlb2Ygb3RoQ3RvciA9PSAnZnVuY3Rpb24nICYmIG90aEN0b3IgaW5zdGFuY2VvZiBvdGhDdG9yKSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBlcXVhbE9iamVjdHM7XG4iLCJ2YXIgbWV0YU1hcCA9IHJlcXVpcmUoJy4vbWV0YU1hcCcpLFxuICAgIG5vb3AgPSByZXF1aXJlKCcuLi91dGlsaXR5L25vb3AnKTtcblxuLyoqXG4gKiBHZXRzIG1ldGFkYXRhIGZvciBgZnVuY2AuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIHF1ZXJ5LlxuICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIG1ldGFkYXRhIGZvciBgZnVuY2AuXG4gKi9cbnZhciBnZXREYXRhID0gIW1ldGFNYXAgPyBub29wIDogZnVuY3Rpb24oZnVuYykge1xuICByZXR1cm4gbWV0YU1hcC5nZXQoZnVuYyk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGdldERhdGE7XG4iLCJ2YXIgcmVhbE5hbWVzID0gcmVxdWlyZSgnLi9yZWFsTmFtZXMnKTtcblxuLyoqXG4gKiBHZXRzIHRoZSBuYW1lIG9mIGBmdW5jYC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gZnVuYyBUaGUgZnVuY3Rpb24gdG8gcXVlcnkuXG4gKiBAcmV0dXJucyB7c3RyaW5nfSBSZXR1cm5zIHRoZSBmdW5jdGlvbiBuYW1lLlxuICovXG5mdW5jdGlvbiBnZXRGdW5jTmFtZShmdW5jKSB7XG4gIHZhciByZXN1bHQgPSAoZnVuYy5uYW1lICsgJycpLFxuICAgICAgYXJyYXkgPSByZWFsTmFtZXNbcmVzdWx0XSxcbiAgICAgIGxlbmd0aCA9IGFycmF5ID8gYXJyYXkubGVuZ3RoIDogMDtcblxuICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICB2YXIgZGF0YSA9IGFycmF5W2xlbmd0aF0sXG4gICAgICAgIG90aGVyRnVuYyA9IGRhdGEuZnVuYztcbiAgICBpZiAob3RoZXJGdW5jID09IG51bGwgfHwgb3RoZXJGdW5jID09IGZ1bmMpIHtcbiAgICAgIHJldHVybiBkYXRhLm5hbWU7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0RnVuY05hbWU7XG4iLCJ2YXIgYmFzZVByb3BlcnR5ID0gcmVxdWlyZSgnLi9iYXNlUHJvcGVydHknKTtcblxuLyoqXG4gKiBHZXRzIHRoZSBcImxlbmd0aFwiIHByb3BlcnR5IHZhbHVlIG9mIGBvYmplY3RgLlxuICpcbiAqICoqTm90ZToqKiBUaGlzIGZ1bmN0aW9uIGlzIHVzZWQgdG8gYXZvaWQgYSBbSklUIGJ1Z10oaHR0cHM6Ly9idWdzLndlYmtpdC5vcmcvc2hvd19idWcuY2dpP2lkPTE0Mjc5MilcbiAqIHRoYXQgYWZmZWN0cyBTYWZhcmkgb24gYXQgbGVhc3QgaU9TIDguMS04LjMgQVJNNjQuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIHRoZSBcImxlbmd0aFwiIHZhbHVlLlxuICovXG52YXIgZ2V0TGVuZ3RoID0gYmFzZVByb3BlcnR5KCdsZW5ndGgnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBnZXRMZW5ndGg7XG4iLCJ2YXIgaXNTdHJpY3RDb21wYXJhYmxlID0gcmVxdWlyZSgnLi9pc1N0cmljdENvbXBhcmFibGUnKSxcbiAgICBwYWlycyA9IHJlcXVpcmUoJy4uL29iamVjdC9wYWlycycpO1xuXG4vKipcbiAqIEdldHMgdGhlIHByb3BlcnkgbmFtZXMsIHZhbHVlcywgYW5kIGNvbXBhcmUgZmxhZ3Mgb2YgYG9iamVjdGAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbWF0Y2ggZGF0YSBvZiBgb2JqZWN0YC5cbiAqL1xuZnVuY3Rpb24gZ2V0TWF0Y2hEYXRhKG9iamVjdCkge1xuICB2YXIgcmVzdWx0ID0gcGFpcnMob2JqZWN0KSxcbiAgICAgIGxlbmd0aCA9IHJlc3VsdC5sZW5ndGg7XG5cbiAgd2hpbGUgKGxlbmd0aC0tKSB7XG4gICAgcmVzdWx0W2xlbmd0aF1bMl0gPSBpc1N0cmljdENvbXBhcmFibGUocmVzdWx0W2xlbmd0aF1bMV0pO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gZ2V0TWF0Y2hEYXRhO1xuIiwidmFyIGlzTmF0aXZlID0gcmVxdWlyZSgnLi4vbGFuZy9pc05hdGl2ZScpO1xuXG4vKipcbiAqIEdldHMgdGhlIG5hdGl2ZSBmdW5jdGlvbiBhdCBga2V5YCBvZiBgb2JqZWN0YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHBhcmFtIHtzdHJpbmd9IGtleSBUaGUga2V5IG9mIHRoZSBtZXRob2QgdG8gZ2V0LlxuICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGZ1bmN0aW9uIGlmIGl0J3MgbmF0aXZlLCBlbHNlIGB1bmRlZmluZWRgLlxuICovXG5mdW5jdGlvbiBnZXROYXRpdmUob2JqZWN0LCBrZXkpIHtcbiAgdmFyIHZhbHVlID0gb2JqZWN0ID09IG51bGwgPyB1bmRlZmluZWQgOiBvYmplY3Rba2V5XTtcbiAgcmV0dXJuIGlzTmF0aXZlKHZhbHVlKSA/IHZhbHVlIDogdW5kZWZpbmVkO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGdldE5hdGl2ZTtcbiIsIi8qKlxuICogR2V0cyB0aGUgaW5kZXggYXQgd2hpY2ggdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgYE5hTmAgaXMgZm91bmQgaW4gYGFycmF5YC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHNlYXJjaC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBmcm9tSW5kZXggVGhlIGluZGV4IHRvIHNlYXJjaCBmcm9tLlxuICogQHBhcmFtIHtib29sZWFufSBbZnJvbVJpZ2h0XSBTcGVjaWZ5IGl0ZXJhdGluZyBmcm9tIHJpZ2h0IHRvIGxlZnQuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgbWF0Y2hlZCBgTmFOYCwgZWxzZSBgLTFgLlxuICovXG5mdW5jdGlvbiBpbmRleE9mTmFOKGFycmF5LCBmcm9tSW5kZXgsIGZyb21SaWdodCkge1xuICB2YXIgbGVuZ3RoID0gYXJyYXkubGVuZ3RoLFxuICAgICAgaW5kZXggPSBmcm9tSW5kZXggKyAoZnJvbVJpZ2h0ID8gMCA6IC0xKTtcblxuICB3aGlsZSAoKGZyb21SaWdodCA/IGluZGV4LS0gOiArK2luZGV4IDwgbGVuZ3RoKSkge1xuICAgIHZhciBvdGhlciA9IGFycmF5W2luZGV4XTtcbiAgICBpZiAob3RoZXIgIT09IG90aGVyKSB7XG4gICAgICByZXR1cm4gaW5kZXg7XG4gICAgfVxuICB9XG4gIHJldHVybiAtMTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpbmRleE9mTmFOO1xuIiwiLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogSW5pdGlhbGl6ZXMgYW4gYXJyYXkgY2xvbmUuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGFycmF5IFRoZSBhcnJheSB0byBjbG9uZS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgaW5pdGlhbGl6ZWQgY2xvbmUuXG4gKi9cbmZ1bmN0aW9uIGluaXRDbG9uZUFycmF5KGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGgsXG4gICAgICByZXN1bHQgPSBuZXcgYXJyYXkuY29uc3RydWN0b3IobGVuZ3RoKTtcblxuICAvLyBBZGQgYXJyYXkgcHJvcGVydGllcyBhc3NpZ25lZCBieSBgUmVnRXhwI2V4ZWNgLlxuICBpZiAobGVuZ3RoICYmIHR5cGVvZiBhcnJheVswXSA9PSAnc3RyaW5nJyAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKGFycmF5LCAnaW5kZXgnKSkge1xuICAgIHJlc3VsdC5pbmRleCA9IGFycmF5LmluZGV4O1xuICAgIHJlc3VsdC5pbnB1dCA9IGFycmF5LmlucHV0O1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaW5pdENsb25lQXJyYXk7XG4iLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG52YXIgYnVmZmVyQ2xvbmUgPSByZXF1aXJlKCcuL2J1ZmZlckNsb25lJyk7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBib29sVGFnID0gJ1tvYmplY3QgQm9vbGVhbl0nLFxuICAgIGRhdGVUYWcgPSAnW29iamVjdCBEYXRlXScsXG4gICAgbnVtYmVyVGFnID0gJ1tvYmplY3QgTnVtYmVyXScsXG4gICAgcmVnZXhwVGFnID0gJ1tvYmplY3QgUmVnRXhwXScsXG4gICAgc3RyaW5nVGFnID0gJ1tvYmplY3QgU3RyaW5nXSc7XG5cbnZhciBhcnJheUJ1ZmZlclRhZyA9ICdbb2JqZWN0IEFycmF5QnVmZmVyXScsXG4gICAgZmxvYXQzMlRhZyA9ICdbb2JqZWN0IEZsb2F0MzJBcnJheV0nLFxuICAgIGZsb2F0NjRUYWcgPSAnW29iamVjdCBGbG9hdDY0QXJyYXldJyxcbiAgICBpbnQ4VGFnID0gJ1tvYmplY3QgSW50OEFycmF5XScsXG4gICAgaW50MTZUYWcgPSAnW29iamVjdCBJbnQxNkFycmF5XScsXG4gICAgaW50MzJUYWcgPSAnW29iamVjdCBJbnQzMkFycmF5XScsXG4gICAgdWludDhUYWcgPSAnW29iamVjdCBVaW50OEFycmF5XScsXG4gICAgdWludDhDbGFtcGVkVGFnID0gJ1tvYmplY3QgVWludDhDbGFtcGVkQXJyYXldJyxcbiAgICB1aW50MTZUYWcgPSAnW29iamVjdCBVaW50MTZBcnJheV0nLFxuICAgIHVpbnQzMlRhZyA9ICdbb2JqZWN0IFVpbnQzMkFycmF5XSc7XG5cbi8qKiBVc2VkIHRvIG1hdGNoIGBSZWdFeHBgIGZsYWdzIGZyb20gdGhlaXIgY29lcmNlZCBzdHJpbmcgdmFsdWVzLiAqL1xudmFyIHJlRmxhZ3MgPSAvXFx3KiQvO1xuXG4vKiogTmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIFVpbnQ4QXJyYXkgPSBnbG9iYWwuVWludDhBcnJheTtcblxuLyoqIFVzZWQgdG8gbG9va3VwIGEgdHlwZSBhcnJheSBjb25zdHJ1Y3RvcnMgYnkgYHRvU3RyaW5nVGFnYC4gKi9cbnZhciBjdG9yQnlUYWcgPSB7fTtcbmN0b3JCeVRhZ1tmbG9hdDMyVGFnXSA9IGdsb2JhbC5GbG9hdDMyQXJyYXk7XG5jdG9yQnlUYWdbZmxvYXQ2NFRhZ10gPSBnbG9iYWwuRmxvYXQ2NEFycmF5O1xuY3RvckJ5VGFnW2ludDhUYWddID0gZ2xvYmFsLkludDhBcnJheTtcbmN0b3JCeVRhZ1tpbnQxNlRhZ10gPSBnbG9iYWwuSW50MTZBcnJheTtcbmN0b3JCeVRhZ1tpbnQzMlRhZ10gPSBnbG9iYWwuSW50MzJBcnJheTtcbmN0b3JCeVRhZ1t1aW50OFRhZ10gPSBVaW50OEFycmF5O1xuY3RvckJ5VGFnW3VpbnQ4Q2xhbXBlZFRhZ10gPSBnbG9iYWwuVWludDhDbGFtcGVkQXJyYXk7XG5jdG9yQnlUYWdbdWludDE2VGFnXSA9IGdsb2JhbC5VaW50MTZBcnJheTtcbmN0b3JCeVRhZ1t1aW50MzJUYWddID0gZ2xvYmFsLlVpbnQzMkFycmF5O1xuXG4vKipcbiAqIEluaXRpYWxpemVzIGFuIG9iamVjdCBjbG9uZSBiYXNlZCBvbiBpdHMgYHRvU3RyaW5nVGFnYC5cbiAqXG4gKiAqKk5vdGU6KiogVGhpcyBmdW5jdGlvbiBvbmx5IHN1cHBvcnRzIGNsb25pbmcgdmFsdWVzIHdpdGggdGFncyBvZlxuICogYEJvb2xlYW5gLCBgRGF0ZWAsIGBFcnJvcmAsIGBOdW1iZXJgLCBgUmVnRXhwYCwgb3IgYFN0cmluZ2AuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBjbG9uZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSB0YWcgVGhlIGB0b1N0cmluZ1RhZ2Agb2YgdGhlIG9iamVjdCB0byBjbG9uZS5cbiAqIEBwYXJhbSB7Ym9vbGVhbn0gW2lzRGVlcF0gU3BlY2lmeSBhIGRlZXAgY2xvbmUuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAqL1xuZnVuY3Rpb24gaW5pdENsb25lQnlUYWcob2JqZWN0LCB0YWcsIGlzRGVlcCkge1xuICB2YXIgQ3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcjtcbiAgc3dpdGNoICh0YWcpIHtcbiAgICBjYXNlIGFycmF5QnVmZmVyVGFnOlxuICAgICAgcmV0dXJuIGJ1ZmZlckNsb25lKG9iamVjdCk7XG5cbiAgICBjYXNlIGJvb2xUYWc6XG4gICAgY2FzZSBkYXRlVGFnOlxuICAgICAgcmV0dXJuIG5ldyBDdG9yKCtvYmplY3QpO1xuXG4gICAgY2FzZSBmbG9hdDMyVGFnOiBjYXNlIGZsb2F0NjRUYWc6XG4gICAgY2FzZSBpbnQ4VGFnOiBjYXNlIGludDE2VGFnOiBjYXNlIGludDMyVGFnOlxuICAgIGNhc2UgdWludDhUYWc6IGNhc2UgdWludDhDbGFtcGVkVGFnOiBjYXNlIHVpbnQxNlRhZzogY2FzZSB1aW50MzJUYWc6XG4gICAgICAvLyBTYWZhcmkgNSBtb2JpbGUgaW5jb3JyZWN0bHkgaGFzIGBPYmplY3RgIGFzIHRoZSBjb25zdHJ1Y3RvciBvZiB0eXBlZCBhcnJheXMuXG4gICAgICBpZiAoQ3RvciBpbnN0YW5jZW9mIEN0b3IpIHtcbiAgICAgICAgQ3RvciA9IGN0b3JCeVRhZ1t0YWddO1xuICAgICAgfVxuICAgICAgdmFyIGJ1ZmZlciA9IG9iamVjdC5idWZmZXI7XG4gICAgICByZXR1cm4gbmV3IEN0b3IoaXNEZWVwID8gYnVmZmVyQ2xvbmUoYnVmZmVyKSA6IGJ1ZmZlciwgb2JqZWN0LmJ5dGVPZmZzZXQsIG9iamVjdC5sZW5ndGgpO1xuXG4gICAgY2FzZSBudW1iZXJUYWc6XG4gICAgY2FzZSBzdHJpbmdUYWc6XG4gICAgICByZXR1cm4gbmV3IEN0b3Iob2JqZWN0KTtcblxuICAgIGNhc2UgcmVnZXhwVGFnOlxuICAgICAgdmFyIHJlc3VsdCA9IG5ldyBDdG9yKG9iamVjdC5zb3VyY2UsIHJlRmxhZ3MuZXhlYyhvYmplY3QpKTtcbiAgICAgIHJlc3VsdC5sYXN0SW5kZXggPSBvYmplY3QubGFzdEluZGV4O1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaW5pdENsb25lQnlUYWc7XG5cbn0pLmNhbGwodGhpcyx0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ6dXRmLTg7YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW01dlpHVmZiVzlrZFd4bGN5OXNiMlJoYzJndFkyOXRjR0YwTDJsdWRHVnlibUZzTDJsdWFYUkRiRzl1WlVKNVZHRm5MbXB6SWwwc0ltNWhiV1Z6SWpwYlhTd2liV0Z3Y0dsdVozTWlPaUk3UVVGQlFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CSWl3aVptbHNaU0k2SW1kbGJtVnlZWFJsWkM1cWN5SXNJbk52ZFhKalpWSnZiM1FpT2lJaUxDSnpiM1Z5WTJWelEyOXVkR1Z1ZENJNld5SjJZWElnWW5WbVptVnlRMnh2Ym1VZ1BTQnlaWEYxYVhKbEtDY3VMMkoxWm1abGNrTnNiMjVsSnlrN1hHNWNiaThxS2lCZ1QySnFaV04wSTNSdlUzUnlhVzVuWUNCeVpYTjFiSFFnY21WbVpYSmxibU5sY3k0Z0tpOWNiblpoY2lCaWIyOXNWR0ZuSUQwZ0oxdHZZbXBsWTNRZ1FtOXZiR1ZoYmwwbkxGeHVJQ0FnSUdSaGRHVlVZV2NnUFNBblcyOWlhbVZqZENCRVlYUmxYU2NzWEc0Z0lDQWdiblZ0WW1WeVZHRm5JRDBnSjF0dlltcGxZM1FnVG5WdFltVnlYU2NzWEc0Z0lDQWdjbVZuWlhod1ZHRm5JRDBnSjF0dlltcGxZM1FnVW1WblJYaHdYU2NzWEc0Z0lDQWdjM1J5YVc1blZHRm5JRDBnSjF0dlltcGxZM1FnVTNSeWFXNW5YU2M3WEc1Y2JuWmhjaUJoY25KaGVVSjFabVpsY2xSaFp5QTlJQ2RiYjJKcVpXTjBJRUZ5Y21GNVFuVm1abVZ5WFNjc1hHNGdJQ0FnWm14dllYUXpNbFJoWnlBOUlDZGJiMkpxWldOMElFWnNiMkYwTXpKQmNuSmhlVjBuTEZ4dUlDQWdJR1pzYjJGME5qUlVZV2NnUFNBblcyOWlhbVZqZENCR2JHOWhkRFkwUVhKeVlYbGRKeXhjYmlBZ0lDQnBiblE0VkdGbklEMGdKMXR2WW1wbFkzUWdTVzUwT0VGeWNtRjVYU2NzWEc0Z0lDQWdhVzUwTVRaVVlXY2dQU0FuVzI5aWFtVmpkQ0JKYm5ReE5rRnljbUY1WFNjc1hHNGdJQ0FnYVc1ME16SlVZV2NnUFNBblcyOWlhbVZqZENCSmJuUXpNa0Z5Y21GNVhTY3NYRzRnSUNBZ2RXbHVkRGhVWVdjZ1BTQW5XMjlpYW1WamRDQlZhVzUwT0VGeWNtRjVYU2NzWEc0Z0lDQWdkV2x1ZERoRGJHRnRjR1ZrVkdGbklEMGdKMXR2WW1wbFkzUWdWV2x1ZERoRGJHRnRjR1ZrUVhKeVlYbGRKeXhjYmlBZ0lDQjFhVzUwTVRaVVlXY2dQU0FuVzI5aWFtVmpkQ0JWYVc1ME1UWkJjbkpoZVYwbkxGeHVJQ0FnSUhWcGJuUXpNbFJoWnlBOUlDZGJiMkpxWldOMElGVnBiblF6TWtGeWNtRjVYU2M3WEc1Y2JpOHFLaUJWYzJWa0lIUnZJRzFoZEdOb0lHQlNaV2RGZUhCZ0lHWnNZV2R6SUdaeWIyMGdkR2hsYVhJZ1kyOWxjbU5sWkNCemRISnBibWNnZG1Gc2RXVnpMaUFxTDF4dWRtRnlJSEpsUm14aFozTWdQU0F2WEZ4M0tpUXZPMXh1WEc0dktpb2dUbUYwYVhabElHMWxkR2h2WkNCeVpXWmxjbVZ1WTJWekxpQXFMMXh1ZG1GeUlGVnBiblE0UVhKeVlYa2dQU0JuYkc5aVlXd3VWV2x1ZERoQmNuSmhlVHRjYmx4dUx5b3FJRlZ6WldRZ2RHOGdiRzl2YTNWd0lHRWdkSGx3WlNCaGNuSmhlU0JqYjI1emRISjFZM1J2Y25NZ1lua2dZSFJ2VTNSeWFXNW5WR0ZuWUM0Z0tpOWNiblpoY2lCamRHOXlRbmxVWVdjZ1BTQjdmVHRjYm1OMGIzSkNlVlJoWjF0bWJHOWhkRE15VkdGblhTQTlJR2RzYjJKaGJDNUdiRzloZERNeVFYSnlZWGs3WEc1amRHOXlRbmxVWVdkYlpteHZZWFEyTkZSaFoxMGdQU0JuYkc5aVlXd3VSbXh2WVhRMk5FRnljbUY1TzF4dVkzUnZja0o1VkdGblcybHVkRGhVWVdkZElEMGdaMnh2WW1Gc0xrbHVkRGhCY25KaGVUdGNibU4wYjNKQ2VWUmhaMXRwYm5ReE5sUmhaMTBnUFNCbmJHOWlZV3d1U1c1ME1UWkJjbkpoZVR0Y2JtTjBiM0pDZVZSaFoxdHBiblF6TWxSaFoxMGdQU0JuYkc5aVlXd3VTVzUwTXpKQmNuSmhlVHRjYm1OMGIzSkNlVlJoWjF0MWFXNTBPRlJoWjEwZ1BTQlZhVzUwT0VGeWNtRjVPMXh1WTNSdmNrSjVWR0ZuVzNWcGJuUTRRMnhoYlhCbFpGUmhaMTBnUFNCbmJHOWlZV3d1VldsdWREaERiR0Z0Y0dWa1FYSnlZWGs3WEc1amRHOXlRbmxVWVdkYmRXbHVkREUyVkdGblhTQTlJR2RzYjJKaGJDNVZhVzUwTVRaQmNuSmhlVHRjYm1OMGIzSkNlVlJoWjF0MWFXNTBNekpVWVdkZElEMGdaMnh2WW1Gc0xsVnBiblF6TWtGeWNtRjVPMXh1WEc0dktpcGNiaUFxSUVsdWFYUnBZV3hwZW1WeklHRnVJRzlpYW1WamRDQmpiRzl1WlNCaVlYTmxaQ0J2YmlCcGRITWdZSFJ2VTNSeWFXNW5WR0ZuWUM1Y2JpQXFYRzRnS2lBcUtrNXZkR1U2S2lvZ1ZHaHBjeUJtZFc1amRHbHZiaUJ2Ym14NUlITjFjSEJ2Y25SeklHTnNiMjVwYm1jZ2RtRnNkV1Z6SUhkcGRHZ2dkR0ZuY3lCdlpseHVJQ29nWUVKdmIyeGxZVzVnTENCZ1JHRjBaV0FzSUdCRmNuSnZjbUFzSUdCT2RXMWlaWEpnTENCZ1VtVm5SWGh3WUN3Z2IzSWdZRk4wY21sdVoyQXVYRzRnS2x4dUlDb2dRSEJ5YVhaaGRHVmNiaUFxSUVCd1lYSmhiU0I3VDJKcVpXTjBmU0J2WW1wbFkzUWdWR2hsSUc5aWFtVmpkQ0IwYnlCamJHOXVaUzVjYmlBcUlFQndZWEpoYlNCN2MzUnlhVzVuZlNCMFlXY2dWR2hsSUdCMGIxTjBjbWx1WjFSaFoyQWdiMllnZEdobElHOWlhbVZqZENCMGJ5QmpiRzl1WlM1Y2JpQXFJRUJ3WVhKaGJTQjdZbTl2YkdWaGJuMGdXMmx6UkdWbGNGMGdVM0JsWTJsbWVTQmhJR1JsWlhBZ1kyeHZibVV1WEc0Z0tpQkFjbVYwZFhKdWN5QjdUMkpxWldOMGZTQlNaWFIxY201eklIUm9aU0JwYm1sMGFXRnNhWHBsWkNCamJHOXVaUzVjYmlBcUwxeHVablZ1WTNScGIyNGdhVzVwZEVOc2IyNWxRbmxVWVdjb2IySnFaV04wTENCMFlXY3NJR2x6UkdWbGNDa2dlMXh1SUNCMllYSWdRM1J2Y2lBOUlHOWlhbVZqZEM1amIyNXpkSEoxWTNSdmNqdGNiaUFnYzNkcGRHTm9JQ2gwWVdjcElIdGNiaUFnSUNCallYTmxJR0Z5Y21GNVFuVm1abVZ5VkdGbk9seHVJQ0FnSUNBZ2NtVjBkWEp1SUdKMVptWmxja05zYjI1bEtHOWlhbVZqZENrN1hHNWNiaUFnSUNCallYTmxJR0p2YjJ4VVlXYzZYRzRnSUNBZ1kyRnpaU0JrWVhSbFZHRm5PbHh1SUNBZ0lDQWdjbVYwZFhKdUlHNWxkeUJEZEc5eUtDdHZZbXBsWTNRcE8xeHVYRzRnSUNBZ1kyRnpaU0JtYkc5aGRETXlWR0ZuT2lCallYTmxJR1pzYjJGME5qUlVZV2M2WEc0Z0lDQWdZMkZ6WlNCcGJuUTRWR0ZuT2lCallYTmxJR2x1ZERFMlZHRm5PaUJqWVhObElHbHVkRE15VkdGbk9seHVJQ0FnSUdOaGMyVWdkV2x1ZERoVVlXYzZJR05oYzJVZ2RXbHVkRGhEYkdGdGNHVmtWR0ZuT2lCallYTmxJSFZwYm5ReE5sUmhaem9nWTJGelpTQjFhVzUwTXpKVVlXYzZYRzRnSUNBZ0lDQXZMeUJUWVdaaGNta2dOU0J0YjJKcGJHVWdhVzVqYjNKeVpXTjBiSGtnYUdGeklHQlBZbXBsWTNSZ0lHRnpJSFJvWlNCamIyNXpkSEoxWTNSdmNpQnZaaUIwZVhCbFpDQmhjbkpoZVhNdVhHNGdJQ0FnSUNCcFppQW9RM1J2Y2lCcGJuTjBZVzVqWlc5bUlFTjBiM0lwSUh0Y2JpQWdJQ0FnSUNBZ1EzUnZjaUE5SUdOMGIzSkNlVlJoWjF0MFlXZGRPMXh1SUNBZ0lDQWdmVnh1SUNBZ0lDQWdkbUZ5SUdKMVptWmxjaUE5SUc5aWFtVmpkQzVpZFdabVpYSTdYRzRnSUNBZ0lDQnlaWFIxY200Z2JtVjNJRU4wYjNJb2FYTkVaV1Z3SUQ4Z1luVm1abVZ5UTJ4dmJtVW9ZblZtWm1WeUtTQTZJR0oxWm1abGNpd2diMkpxWldOMExtSjVkR1ZQWm1aelpYUXNJRzlpYW1WamRDNXNaVzVuZEdncE8xeHVYRzRnSUNBZ1kyRnpaU0J1ZFcxaVpYSlVZV2M2WEc0Z0lDQWdZMkZ6WlNCemRISnBibWRVWVdjNlhHNGdJQ0FnSUNCeVpYUjFjbTRnYm1WM0lFTjBiM0lvYjJKcVpXTjBLVHRjYmx4dUlDQWdJR05oYzJVZ2NtVm5aWGh3VkdGbk9seHVJQ0FnSUNBZ2RtRnlJSEpsYzNWc2RDQTlJRzVsZHlCRGRHOXlLRzlpYW1WamRDNXpiM1Z5WTJVc0lISmxSbXhoWjNNdVpYaGxZeWh2WW1wbFkzUXBLVHRjYmlBZ0lDQWdJSEpsYzNWc2RDNXNZWE4wU1c1a1pYZ2dQU0J2WW1wbFkzUXViR0Z6ZEVsdVpHVjRPMXh1SUNCOVhHNGdJSEpsZEhWeWJpQnlaWE4xYkhRN1hHNTlYRzVjYm0xdlpIVnNaUzVsZUhCdmNuUnpJRDBnYVc1cGRFTnNiMjVsUW5sVVlXYzdYRzRpWFgwPSIsIi8qKlxuICogSW5pdGlhbGl6ZXMgYW4gb2JqZWN0IGNsb25lLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gY2xvbmUuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBpbml0aWFsaXplZCBjbG9uZS5cbiAqL1xuZnVuY3Rpb24gaW5pdENsb25lT2JqZWN0KG9iamVjdCkge1xuICB2YXIgQ3RvciA9IG9iamVjdC5jb25zdHJ1Y3RvcjtcbiAgaWYgKCEodHlwZW9mIEN0b3IgPT0gJ2Z1bmN0aW9uJyAmJiBDdG9yIGluc3RhbmNlb2YgQ3RvcikpIHtcbiAgICBDdG9yID0gT2JqZWN0O1xuICB9XG4gIHJldHVybiBuZXcgQ3Rvcjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpbml0Q2xvbmVPYmplY3Q7XG4iLCJ2YXIgZ2V0TGVuZ3RoID0gcmVxdWlyZSgnLi9nZXRMZW5ndGgnKSxcbiAgICBpc0xlbmd0aCA9IHJlcXVpcmUoJy4vaXNMZW5ndGgnKTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhcnJheS1saWtlLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFycmF5LWxpa2UsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gaXNBcnJheUxpa2UodmFsdWUpIHtcbiAgcmV0dXJuIHZhbHVlICE9IG51bGwgJiYgaXNMZW5ndGgoZ2V0TGVuZ3RoKHZhbHVlKSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNBcnJheUxpa2U7XG4iLCIvKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgaG9zdCBvYmplY3QgaW4gSUUgPCA5LlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGEgaG9zdCBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAqL1xudmFyIGlzSG9zdE9iamVjdCA9IChmdW5jdGlvbigpIHtcbiAgdHJ5IHtcbiAgICBPYmplY3QoeyAndG9TdHJpbmcnOiAwIH0gKyAnJyk7XG4gIH0gY2F0Y2goZSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHsgcmV0dXJuIGZhbHNlOyB9O1xuICB9XG4gIHJldHVybiBmdW5jdGlvbih2YWx1ZSkge1xuICAgIC8vIElFIDwgOSBwcmVzZW50cyBtYW55IGhvc3Qgb2JqZWN0cyBhcyBgT2JqZWN0YCBvYmplY3RzIHRoYXQgY2FuIGNvZXJjZVxuICAgIC8vIHRvIHN0cmluZ3MgZGVzcGl0ZSBoYXZpbmcgaW1wcm9wZXJseSBkZWZpbmVkIGB0b1N0cmluZ2AgbWV0aG9kcy5cbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlLnRvU3RyaW5nICE9ICdmdW5jdGlvbicgJiYgdHlwZW9mICh2YWx1ZSArICcnKSA9PSAnc3RyaW5nJztcbiAgfTtcbn0oKSk7XG5cbm1vZHVsZS5leHBvcnRzID0gaXNIb3N0T2JqZWN0O1xuIiwiLyoqIFVzZWQgdG8gZGV0ZWN0IHVuc2lnbmVkIGludGVnZXIgdmFsdWVzLiAqL1xudmFyIHJlSXNVaW50ID0gL15cXGQrJC87XG5cbi8qKlxuICogVXNlZCBhcyB0aGUgW21heGltdW0gbGVuZ3RoXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1udW1iZXIubWF4X3NhZmVfaW50ZWdlcilcbiAqIG9mIGFuIGFycmF5LWxpa2UgdmFsdWUuXG4gKi9cbnZhciBNQVhfU0FGRV9JTlRFR0VSID0gOTAwNzE5OTI1NDc0MDk5MTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHZhbGlkIGFycmF5LWxpa2UgaW5kZXguXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHBhcmFtIHtudW1iZXJ9IFtsZW5ndGg9TUFYX1NBRkVfSU5URUdFUl0gVGhlIHVwcGVyIGJvdW5kcyBvZiBhIHZhbGlkIGluZGV4LlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBpbmRleCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBpc0luZGV4KHZhbHVlLCBsZW5ndGgpIHtcbiAgdmFsdWUgPSAodHlwZW9mIHZhbHVlID09ICdudW1iZXInIHx8IHJlSXNVaW50LnRlc3QodmFsdWUpKSA/ICt2YWx1ZSA6IC0xO1xuICBsZW5ndGggPSBsZW5ndGggPT0gbnVsbCA/IE1BWF9TQUZFX0lOVEVHRVIgOiBsZW5ndGg7XG4gIHJldHVybiB2YWx1ZSA+IC0xICYmIHZhbHVlICUgMSA9PSAwICYmIHZhbHVlIDwgbGVuZ3RoO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzSW5kZXg7XG4iLCJ2YXIgaXNBcnJheUxpa2UgPSByZXF1aXJlKCcuL2lzQXJyYXlMaWtlJyksXG4gICAgaXNJbmRleCA9IHJlcXVpcmUoJy4vaXNJbmRleCcpLFxuICAgIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi4vbGFuZy9pc09iamVjdCcpO1xuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgcHJvdmlkZWQgYXJndW1lbnRzIGFyZSBmcm9tIGFuIGl0ZXJhdGVlIGNhbGwuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHBvdGVudGlhbCBpdGVyYXRlZSB2YWx1ZSBhcmd1bWVudC5cbiAqIEBwYXJhbSB7Kn0gaW5kZXggVGhlIHBvdGVudGlhbCBpdGVyYXRlZSBpbmRleCBvciBrZXkgYXJndW1lbnQuXG4gKiBAcGFyYW0geyp9IG9iamVjdCBUaGUgcG90ZW50aWFsIGl0ZXJhdGVlIG9iamVjdCBhcmd1bWVudC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiB0aGUgYXJndW1lbnRzIGFyZSBmcm9tIGFuIGl0ZXJhdGVlIGNhbGwsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gaXNJdGVyYXRlZUNhbGwodmFsdWUsIGluZGV4LCBvYmplY3QpIHtcbiAgaWYgKCFpc09iamVjdChvYmplY3QpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHZhciB0eXBlID0gdHlwZW9mIGluZGV4O1xuICBpZiAodHlwZSA9PSAnbnVtYmVyJ1xuICAgICAgPyAoaXNBcnJheUxpa2Uob2JqZWN0KSAmJiBpc0luZGV4KGluZGV4LCBvYmplY3QubGVuZ3RoKSlcbiAgICAgIDogKHR5cGUgPT0gJ3N0cmluZycgJiYgaW5kZXggaW4gb2JqZWN0KSkge1xuICAgIHZhciBvdGhlciA9IG9iamVjdFtpbmRleF07XG4gICAgcmV0dXJuIHZhbHVlID09PSB2YWx1ZSA/ICh2YWx1ZSA9PT0gb3RoZXIpIDogKG90aGVyICE9PSBvdGhlcik7XG4gIH1cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzSXRlcmF0ZWVDYWxsO1xuIiwidmFyIGlzQXJyYXkgPSByZXF1aXJlKCcuLi9sYW5nL2lzQXJyYXknKSxcbiAgICB0b09iamVjdCA9IHJlcXVpcmUoJy4vdG9PYmplY3QnKTtcblxuLyoqIFVzZWQgdG8gbWF0Y2ggcHJvcGVydHkgbmFtZXMgd2l0aGluIHByb3BlcnR5IHBhdGhzLiAqL1xudmFyIHJlSXNEZWVwUHJvcCA9IC9cXC58XFxbKD86W15bXFxdXSp8KFtcIiddKSg/Oig/IVxcMSlbXlxcblxcXFxdfFxcXFwuKSo/XFwxKVxcXS8sXG4gICAgcmVJc1BsYWluUHJvcCA9IC9eXFx3KiQvO1xuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGEgcHJvcGVydHkgbmFtZSBhbmQgbm90IGEgcHJvcGVydHkgcGF0aC5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcGFyYW0ge09iamVjdH0gW29iamVjdF0gVGhlIG9iamVjdCB0byBxdWVyeSBrZXlzIG9uLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBwcm9wZXJ0eSBuYW1lLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGlzS2V5KHZhbHVlLCBvYmplY3QpIHtcbiAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gIGlmICgodHlwZSA9PSAnc3RyaW5nJyAmJiByZUlzUGxhaW5Qcm9wLnRlc3QodmFsdWUpKSB8fCB0eXBlID09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHZhciByZXN1bHQgPSAhcmVJc0RlZXBQcm9wLnRlc3QodmFsdWUpO1xuICByZXR1cm4gcmVzdWx0IHx8IChvYmplY3QgIT0gbnVsbCAmJiB2YWx1ZSBpbiB0b09iamVjdChvYmplY3QpKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc0tleTtcbiIsInZhciBMYXp5V3JhcHBlciA9IHJlcXVpcmUoJy4vTGF6eVdyYXBwZXInKSxcbiAgICBnZXREYXRhID0gcmVxdWlyZSgnLi9nZXREYXRhJyksXG4gICAgZ2V0RnVuY05hbWUgPSByZXF1aXJlKCcuL2dldEZ1bmNOYW1lJyksXG4gICAgbG9kYXNoID0gcmVxdWlyZSgnLi4vY2hhaW4vbG9kYXNoJyk7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGBmdW5jYCBoYXMgYSBsYXp5IGNvdW50ZXJwYXJ0LlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmdW5jIFRoZSBmdW5jdGlvbiB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgZnVuY2AgaGFzIGEgbGF6eSBjb3VudGVycGFydCwgZWxzZSBgZmFsc2VgLlxuICovXG5mdW5jdGlvbiBpc0xhemlhYmxlKGZ1bmMpIHtcbiAgdmFyIGZ1bmNOYW1lID0gZ2V0RnVuY05hbWUoZnVuYyksXG4gICAgICBvdGhlciA9IGxvZGFzaFtmdW5jTmFtZV07XG5cbiAgaWYgKHR5cGVvZiBvdGhlciAhPSAnZnVuY3Rpb24nIHx8ICEoZnVuY05hbWUgaW4gTGF6eVdyYXBwZXIucHJvdG90eXBlKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoZnVuYyA9PT0gb3RoZXIpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICB2YXIgZGF0YSA9IGdldERhdGEob3RoZXIpO1xuICByZXR1cm4gISFkYXRhICYmIGZ1bmMgPT09IGRhdGFbMF07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNMYXppYWJsZTtcbiIsIi8qKlxuICogVXNlZCBhcyB0aGUgW21heGltdW0gbGVuZ3RoXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1udW1iZXIubWF4X3NhZmVfaW50ZWdlcilcbiAqIG9mIGFuIGFycmF5LWxpa2UgdmFsdWUuXG4gKi9cbnZhciBNQVhfU0FGRV9JTlRFR0VSID0gOTAwNzE5OTI1NDc0MDk5MTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHZhbGlkIGFycmF5LWxpa2UgbGVuZ3RoLlxuICpcbiAqICoqTm90ZToqKiBUaGlzIGZ1bmN0aW9uIGlzIGJhc2VkIG9uIFtgVG9MZW5ndGhgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy10b2xlbmd0aCkuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSB2YWxpZCBsZW5ndGgsIGVsc2UgYGZhbHNlYC5cbiAqL1xuZnVuY3Rpb24gaXNMZW5ndGgodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnbnVtYmVyJyAmJiB2YWx1ZSA+IC0xICYmIHZhbHVlICUgMSA9PSAwICYmIHZhbHVlIDw9IE1BWF9TQUZFX0lOVEVHRVI7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNMZW5ndGg7XG4iLCIvKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIG9iamVjdC1saWtlLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGlzT2JqZWN0TGlrZSh2YWx1ZSkge1xuICByZXR1cm4gISF2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNPYmplY3RMaWtlO1xuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi4vbGFuZy9pc09iamVjdCcpO1xuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHN1aXRhYmxlIGZvciBzdHJpY3QgZXF1YWxpdHkgY29tcGFyaXNvbnMsIGkuZS4gYD09PWAuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaWYgc3VpdGFibGUgZm9yIHN0cmljdFxuICogIGVxdWFsaXR5IGNvbXBhcmlzb25zLCBlbHNlIGBmYWxzZWAuXG4gKi9cbmZ1bmN0aW9uIGlzU3RyaWN0Q29tcGFyYWJsZSh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IHZhbHVlICYmICFpc09iamVjdCh2YWx1ZSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNTdHJpY3RDb21wYXJhYmxlO1xuIiwidmFyIGFycmF5Q29weSA9IHJlcXVpcmUoJy4vYXJyYXlDb3B5JyksXG4gICAgY29tcG9zZUFyZ3MgPSByZXF1aXJlKCcuL2NvbXBvc2VBcmdzJyksXG4gICAgY29tcG9zZUFyZ3NSaWdodCA9IHJlcXVpcmUoJy4vY29tcG9zZUFyZ3NSaWdodCcpLFxuICAgIHJlcGxhY2VIb2xkZXJzID0gcmVxdWlyZSgnLi9yZXBsYWNlSG9sZGVycycpO1xuXG4vKiogVXNlZCB0byBjb21wb3NlIGJpdG1hc2tzIGZvciB3cmFwcGVyIG1ldGFkYXRhLiAqL1xudmFyIEJJTkRfRkxBRyA9IDEsXG4gICAgQ1VSUllfQk9VTkRfRkxBRyA9IDQsXG4gICAgQ1VSUllfRkxBRyA9IDgsXG4gICAgQVJZX0ZMQUcgPSAxMjgsXG4gICAgUkVBUkdfRkxBRyA9IDI1NjtcblxuLyoqIFVzZWQgYXMgdGhlIGludGVybmFsIGFyZ3VtZW50IHBsYWNlaG9sZGVyLiAqL1xudmFyIFBMQUNFSE9MREVSID0gJ19fbG9kYXNoX3BsYWNlaG9sZGVyX18nO1xuXG4vKiBOYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMgZm9yIHRob3NlIHdpdGggdGhlIHNhbWUgbmFtZSBhcyBvdGhlciBgbG9kYXNoYCBtZXRob2RzLiAqL1xudmFyIG5hdGl2ZU1pbiA9IE1hdGgubWluO1xuXG4vKipcbiAqIE1lcmdlcyB0aGUgZnVuY3Rpb24gbWV0YWRhdGEgb2YgYHNvdXJjZWAgaW50byBgZGF0YWAuXG4gKlxuICogTWVyZ2luZyBtZXRhZGF0YSByZWR1Y2VzIHRoZSBudW1iZXIgb2Ygd3JhcHBlcnMgcmVxdWlyZWQgdG8gaW52b2tlIGEgZnVuY3Rpb24uXG4gKiBUaGlzIGlzIHBvc3NpYmxlIGJlY2F1c2UgbWV0aG9kcyBsaWtlIGBfLmJpbmRgLCBgXy5jdXJyeWAsIGFuZCBgXy5wYXJ0aWFsYFxuICogbWF5IGJlIGFwcGxpZWQgcmVnYXJkbGVzcyBvZiBleGVjdXRpb24gb3JkZXIuIE1ldGhvZHMgbGlrZSBgXy5hcnlgIGFuZCBgXy5yZWFyZ2BcbiAqIGF1Z21lbnQgZnVuY3Rpb24gYXJndW1lbnRzLCBtYWtpbmcgdGhlIG9yZGVyIGluIHdoaWNoIHRoZXkgYXJlIGV4ZWN1dGVkIGltcG9ydGFudCxcbiAqIHByZXZlbnRpbmcgdGhlIG1lcmdpbmcgb2YgbWV0YWRhdGEuIEhvd2V2ZXIsIHdlIG1ha2UgYW4gZXhjZXB0aW9uIGZvciBhIHNhZmVcbiAqIGNvbW1vbiBjYXNlIHdoZXJlIGN1cnJpZWQgZnVuY3Rpb25zIGhhdmUgYF8uYXJ5YCBhbmQgb3IgYF8ucmVhcmdgIGFwcGxpZWQuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7QXJyYXl9IGRhdGEgVGhlIGRlc3RpbmF0aW9uIG1ldGFkYXRhLlxuICogQHBhcmFtIHtBcnJheX0gc291cmNlIFRoZSBzb3VyY2UgbWV0YWRhdGEuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgYGRhdGFgLlxuICovXG5mdW5jdGlvbiBtZXJnZURhdGEoZGF0YSwgc291cmNlKSB7XG4gIHZhciBiaXRtYXNrID0gZGF0YVsxXSxcbiAgICAgIHNyY0JpdG1hc2sgPSBzb3VyY2VbMV0sXG4gICAgICBuZXdCaXRtYXNrID0gYml0bWFzayB8IHNyY0JpdG1hc2ssXG4gICAgICBpc0NvbW1vbiA9IG5ld0JpdG1hc2sgPCBBUllfRkxBRztcblxuICB2YXIgaXNDb21ibyA9XG4gICAgKHNyY0JpdG1hc2sgPT0gQVJZX0ZMQUcgJiYgYml0bWFzayA9PSBDVVJSWV9GTEFHKSB8fFxuICAgIChzcmNCaXRtYXNrID09IEFSWV9GTEFHICYmIGJpdG1hc2sgPT0gUkVBUkdfRkxBRyAmJiBkYXRhWzddLmxlbmd0aCA8PSBzb3VyY2VbOF0pIHx8XG4gICAgKHNyY0JpdG1hc2sgPT0gKEFSWV9GTEFHIHwgUkVBUkdfRkxBRykgJiYgYml0bWFzayA9PSBDVVJSWV9GTEFHKTtcblxuICAvLyBFeGl0IGVhcmx5IGlmIG1ldGFkYXRhIGNhbid0IGJlIG1lcmdlZC5cbiAgaWYgKCEoaXNDb21tb24gfHwgaXNDb21ibykpIHtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuICAvLyBVc2Ugc291cmNlIGB0aGlzQXJnYCBpZiBhdmFpbGFibGUuXG4gIGlmIChzcmNCaXRtYXNrICYgQklORF9GTEFHKSB7XG4gICAgZGF0YVsyXSA9IHNvdXJjZVsyXTtcbiAgICAvLyBTZXQgd2hlbiBjdXJyeWluZyBhIGJvdW5kIGZ1bmN0aW9uLlxuICAgIG5ld0JpdG1hc2sgfD0gKGJpdG1hc2sgJiBCSU5EX0ZMQUcpID8gMCA6IENVUlJZX0JPVU5EX0ZMQUc7XG4gIH1cbiAgLy8gQ29tcG9zZSBwYXJ0aWFsIGFyZ3VtZW50cy5cbiAgdmFyIHZhbHVlID0gc291cmNlWzNdO1xuICBpZiAodmFsdWUpIHtcbiAgICB2YXIgcGFydGlhbHMgPSBkYXRhWzNdO1xuICAgIGRhdGFbM10gPSBwYXJ0aWFscyA/IGNvbXBvc2VBcmdzKHBhcnRpYWxzLCB2YWx1ZSwgc291cmNlWzRdKSA6IGFycmF5Q29weSh2YWx1ZSk7XG4gICAgZGF0YVs0XSA9IHBhcnRpYWxzID8gcmVwbGFjZUhvbGRlcnMoZGF0YVszXSwgUExBQ0VIT0xERVIpIDogYXJyYXlDb3B5KHNvdXJjZVs0XSk7XG4gIH1cbiAgLy8gQ29tcG9zZSBwYXJ0aWFsIHJpZ2h0IGFyZ3VtZW50cy5cbiAgdmFsdWUgPSBzb3VyY2VbNV07XG4gIGlmICh2YWx1ZSkge1xuICAgIHBhcnRpYWxzID0gZGF0YVs1XTtcbiAgICBkYXRhWzVdID0gcGFydGlhbHMgPyBjb21wb3NlQXJnc1JpZ2h0KHBhcnRpYWxzLCB2YWx1ZSwgc291cmNlWzZdKSA6IGFycmF5Q29weSh2YWx1ZSk7XG4gICAgZGF0YVs2XSA9IHBhcnRpYWxzID8gcmVwbGFjZUhvbGRlcnMoZGF0YVs1XSwgUExBQ0VIT0xERVIpIDogYXJyYXlDb3B5KHNvdXJjZVs2XSk7XG4gIH1cbiAgLy8gVXNlIHNvdXJjZSBgYXJnUG9zYCBpZiBhdmFpbGFibGUuXG4gIHZhbHVlID0gc291cmNlWzddO1xuICBpZiAodmFsdWUpIHtcbiAgICBkYXRhWzddID0gYXJyYXlDb3B5KHZhbHVlKTtcbiAgfVxuICAvLyBVc2Ugc291cmNlIGBhcnlgIGlmIGl0J3Mgc21hbGxlci5cbiAgaWYgKHNyY0JpdG1hc2sgJiBBUllfRkxBRykge1xuICAgIGRhdGFbOF0gPSBkYXRhWzhdID09IG51bGwgPyBzb3VyY2VbOF0gOiBuYXRpdmVNaW4oZGF0YVs4XSwgc291cmNlWzhdKTtcbiAgfVxuICAvLyBVc2Ugc291cmNlIGBhcml0eWAgaWYgb25lIGlzIG5vdCBwcm92aWRlZC5cbiAgaWYgKGRhdGFbOV0gPT0gbnVsbCkge1xuICAgIGRhdGFbOV0gPSBzb3VyY2VbOV07XG4gIH1cbiAgLy8gVXNlIHNvdXJjZSBgZnVuY2AgYW5kIG1lcmdlIGJpdG1hc2tzLlxuICBkYXRhWzBdID0gc291cmNlWzBdO1xuICBkYXRhWzFdID0gbmV3Qml0bWFzaztcblxuICByZXR1cm4gZGF0YTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBtZXJnZURhdGE7XG4iLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG52YXIgZ2V0TmF0aXZlID0gcmVxdWlyZSgnLi9nZXROYXRpdmUnKTtcblxuLyoqIE5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBXZWFrTWFwID0gZ2V0TmF0aXZlKGdsb2JhbCwgJ1dlYWtNYXAnKTtcblxuLyoqIFVzZWQgdG8gc3RvcmUgZnVuY3Rpb24gbWV0YWRhdGEuICovXG52YXIgbWV0YU1hcCA9IFdlYWtNYXAgJiYgbmV3IFdlYWtNYXA7XG5cbm1vZHVsZS5leHBvcnRzID0gbWV0YU1hcDtcblxufSkuY2FsbCh0aGlzLHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygc2VsZiAhPT0gXCJ1bmRlZmluZWRcIiA/IHNlbGYgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDoge30pXG4vLyMgc291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldDp1dGYtODtiYXNlNjQsZXlKMlpYSnphVzl1SWpvekxDSnpiM1Z5WTJWeklqcGJJbTV2WkdWZmJXOWtkV3hsY3k5c2IyUmhjMmd0WTI5dGNHRjBMMmx1ZEdWeWJtRnNMMjFsZEdGTllYQXVhbk1pWFN3aWJtRnRaWE1pT2x0ZExDSnRZWEJ3YVc1bmN5STZJanRCUVVGQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQklpd2labWxzWlNJNkltZGxibVZ5WVhSbFpDNXFjeUlzSW5OdmRYSmpaVkp2YjNRaU9pSWlMQ0p6YjNWeVkyVnpRMjl1ZEdWdWRDSTZXeUoyWVhJZ1oyVjBUbUYwYVhabElEMGdjbVZ4ZFdseVpTZ25MaTluWlhST1lYUnBkbVVuS1R0Y2JseHVMeW9xSUU1aGRHbDJaU0J0WlhSb2IyUWdjbVZtWlhKbGJtTmxjeTRnS2k5Y2JuWmhjaUJYWldGclRXRndJRDBnWjJWMFRtRjBhWFpsS0dkc2IySmhiQ3dnSjFkbFlXdE5ZWEFuS1R0Y2JseHVMeW9xSUZWelpXUWdkRzhnYzNSdmNtVWdablZ1WTNScGIyNGdiV1YwWVdSaGRHRXVJQ292WEc1MllYSWdiV1YwWVUxaGNDQTlJRmRsWVd0TllYQWdKaVlnYm1WM0lGZGxZV3ROWVhBN1hHNWNibTF2WkhWc1pTNWxlSEJ2Y25SeklEMGdiV1YwWVUxaGNEdGNiaUpkZlE9PSIsIi8qKiBVc2VkIHRvIGxvb2t1cCB1bm1pbmlmaWVkIGZ1bmN0aW9uIG5hbWVzLiAqL1xudmFyIHJlYWxOYW1lcyA9IHt9O1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlYWxOYW1lcztcbiIsInZhciBhcnJheUNvcHkgPSByZXF1aXJlKCcuL2FycmF5Q29weScpLFxuICAgIGlzSW5kZXggPSByZXF1aXJlKCcuL2lzSW5kZXgnKTtcblxuLyogTmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzIGZvciB0aG9zZSB3aXRoIHRoZSBzYW1lIG5hbWUgYXMgb3RoZXIgYGxvZGFzaGAgbWV0aG9kcy4gKi9cbnZhciBuYXRpdmVNaW4gPSBNYXRoLm1pbjtcblxuLyoqXG4gKiBSZW9yZGVyIGBhcnJheWAgYWNjb3JkaW5nIHRvIHRoZSBzcGVjaWZpZWQgaW5kZXhlcyB3aGVyZSB0aGUgZWxlbWVudCBhdFxuICogdGhlIGZpcnN0IGluZGV4IGlzIGFzc2lnbmVkIGFzIHRoZSBmaXJzdCBlbGVtZW50LCB0aGUgZWxlbWVudCBhdFxuICogdGhlIHNlY29uZCBpbmRleCBpcyBhc3NpZ25lZCBhcyB0aGUgc2Vjb25kIGVsZW1lbnQsIGFuZCBzbyBvbi5cbiAqXG4gKiBAcHJpdmF0ZVxuICogQHBhcmFtIHtBcnJheX0gYXJyYXkgVGhlIGFycmF5IHRvIHJlb3JkZXIuXG4gKiBAcGFyYW0ge0FycmF5fSBpbmRleGVzIFRoZSBhcnJhbmdlZCBhcnJheSBpbmRleGVzLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIGBhcnJheWAuXG4gKi9cbmZ1bmN0aW9uIHJlb3JkZXIoYXJyYXksIGluZGV4ZXMpIHtcbiAgdmFyIGFyckxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgIGxlbmd0aCA9IG5hdGl2ZU1pbihpbmRleGVzLmxlbmd0aCwgYXJyTGVuZ3RoKSxcbiAgICAgIG9sZEFycmF5ID0gYXJyYXlDb3B5KGFycmF5KTtcblxuICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICB2YXIgaW5kZXggPSBpbmRleGVzW2xlbmd0aF07XG4gICAgYXJyYXlbbGVuZ3RoXSA9IGlzSW5kZXgoaW5kZXgsIGFyckxlbmd0aCkgPyBvbGRBcnJheVtpbmRleF0gOiB1bmRlZmluZWQ7XG4gIH1cbiAgcmV0dXJuIGFycmF5O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHJlb3JkZXI7XG4iLCIvKiogVXNlZCBhcyB0aGUgaW50ZXJuYWwgYXJndW1lbnQgcGxhY2Vob2xkZXIuICovXG52YXIgUExBQ0VIT0xERVIgPSAnX19sb2Rhc2hfcGxhY2Vob2xkZXJfXyc7XG5cbi8qKlxuICogUmVwbGFjZXMgYWxsIGBwbGFjZWhvbGRlcmAgZWxlbWVudHMgaW4gYGFycmF5YCB3aXRoIGFuIGludGVybmFsIHBsYWNlaG9sZGVyXG4gKiBhbmQgcmV0dXJucyBhbiBhcnJheSBvZiB0aGVpciBpbmRleGVzLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge0FycmF5fSBhcnJheSBUaGUgYXJyYXkgdG8gbW9kaWZ5LlxuICogQHBhcmFtIHsqfSBwbGFjZWhvbGRlciBUaGUgcGxhY2Vob2xkZXIgdG8gcmVwbGFjZS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIHBsYWNlaG9sZGVyIGluZGV4ZXMuXG4gKi9cbmZ1bmN0aW9uIHJlcGxhY2VIb2xkZXJzKGFycmF5LCBwbGFjZWhvbGRlcikge1xuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIGxlbmd0aCA9IGFycmF5Lmxlbmd0aCxcbiAgICAgIHJlc0luZGV4ID0gLTEsXG4gICAgICByZXN1bHQgPSBbXTtcblxuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIGlmIChhcnJheVtpbmRleF0gPT09IHBsYWNlaG9sZGVyKSB7XG4gICAgICBhcnJheVtpbmRleF0gPSBQTEFDRUhPTERFUjtcbiAgICAgIHJlc3VsdFsrK3Jlc0luZGV4XSA9IGluZGV4O1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcGxhY2VIb2xkZXJzO1xuIiwidmFyIGJhc2VTZXREYXRhID0gcmVxdWlyZSgnLi9iYXNlU2V0RGF0YScpLFxuICAgIG5vdyA9IHJlcXVpcmUoJy4uL2RhdGUvbm93Jyk7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCB3aGVuIGEgZnVuY3Rpb24gYmVjb21lcyBob3QuICovXG52YXIgSE9UX0NPVU5UID0gMTUwLFxuICAgIEhPVF9TUEFOID0gMTY7XG5cbi8qKlxuICogU2V0cyBtZXRhZGF0YSBmb3IgYGZ1bmNgLlxuICpcbiAqICoqTm90ZToqKiBJZiB0aGlzIGZ1bmN0aW9uIGJlY29tZXMgaG90LCBpLmUuIGlzIGludm9rZWQgYSBsb3QgaW4gYSBzaG9ydFxuICogcGVyaW9kIG9mIHRpbWUsIGl0IHdpbGwgdHJpcCBpdHMgYnJlYWtlciBhbmQgdHJhbnNpdGlvbiB0byBhbiBpZGVudGl0eSBmdW5jdGlvblxuICogdG8gYXZvaWQgZ2FyYmFnZSBjb2xsZWN0aW9uIHBhdXNlcyBpbiBWOC4gU2VlIFtWOCBpc3N1ZSAyMDcwXShodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL3Y4L2lzc3Vlcy9kZXRhaWw/aWQ9MjA3MClcbiAqIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGFzc29jaWF0ZSBtZXRhZGF0YSB3aXRoLlxuICogQHBhcmFtIHsqfSBkYXRhIFRoZSBtZXRhZGF0YS5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyBgZnVuY2AuXG4gKi9cbnZhciBzZXREYXRhID0gKGZ1bmN0aW9uKCkge1xuICB2YXIgY291bnQgPSAwLFxuICAgICAgbGFzdENhbGxlZCA9IDA7XG5cbiAgcmV0dXJuIGZ1bmN0aW9uKGtleSwgdmFsdWUpIHtcbiAgICB2YXIgc3RhbXAgPSBub3coKSxcbiAgICAgICAgcmVtYWluaW5nID0gSE9UX1NQQU4gLSAoc3RhbXAgLSBsYXN0Q2FsbGVkKTtcblxuICAgIGxhc3RDYWxsZWQgPSBzdGFtcDtcbiAgICBpZiAocmVtYWluaW5nID4gMCkge1xuICAgICAgaWYgKCsrY291bnQgPj0gSE9UX0NPVU5UKSB7XG4gICAgICAgIHJldHVybiBrZXk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvdW50ID0gMDtcbiAgICB9XG4gICAgcmV0dXJuIGJhc2VTZXREYXRhKGtleSwgdmFsdWUpO1xuICB9O1xufSgpKTtcblxubW9kdWxlLmV4cG9ydHMgPSBzZXREYXRhO1xuIiwidmFyIGlzQXJndW1lbnRzID0gcmVxdWlyZSgnLi4vbGFuZy9pc0FyZ3VtZW50cycpLFxuICAgIGlzQXJyYXkgPSByZXF1aXJlKCcuLi9sYW5nL2lzQXJyYXknKSxcbiAgICBpc0luZGV4ID0gcmVxdWlyZSgnLi9pc0luZGV4JyksXG4gICAgaXNMZW5ndGggPSByZXF1aXJlKCcuL2lzTGVuZ3RoJyksXG4gICAgaXNTdHJpbmcgPSByZXF1aXJlKCcuLi9sYW5nL2lzU3RyaW5nJyksXG4gICAga2V5c0luID0gcmVxdWlyZSgnLi4vb2JqZWN0L2tleXNJbicpO1xuXG4vKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBBIGZhbGxiYWNrIGltcGxlbWVudGF0aW9uIG9mIGBPYmplY3Qua2V5c2Agd2hpY2ggY3JlYXRlcyBhbiBhcnJheSBvZiB0aGVcbiAqIG93biBlbnVtZXJhYmxlIHByb3BlcnR5IG5hbWVzIG9mIGBvYmplY3RgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqZWN0IFRoZSBvYmplY3QgdG8gcXVlcnkuXG4gKiBAcmV0dXJucyB7QXJyYXl9IFJldHVybnMgdGhlIGFycmF5IG9mIHByb3BlcnR5IG5hbWVzLlxuICovXG5mdW5jdGlvbiBzaGltS2V5cyhvYmplY3QpIHtcbiAgdmFyIHByb3BzID0ga2V5c0luKG9iamVjdCksXG4gICAgICBwcm9wc0xlbmd0aCA9IHByb3BzLmxlbmd0aCxcbiAgICAgIGxlbmd0aCA9IHByb3BzTGVuZ3RoICYmIG9iamVjdC5sZW5ndGg7XG5cbiAgdmFyIGFsbG93SW5kZXhlcyA9ICEhbGVuZ3RoICYmIGlzTGVuZ3RoKGxlbmd0aCkgJiZcbiAgICAoaXNBcnJheShvYmplY3QpIHx8IGlzQXJndW1lbnRzKG9iamVjdCkgfHwgaXNTdHJpbmcob2JqZWN0KSk7XG5cbiAgdmFyIGluZGV4ID0gLTEsXG4gICAgICByZXN1bHQgPSBbXTtcblxuICB3aGlsZSAoKytpbmRleCA8IHByb3BzTGVuZ3RoKSB7XG4gICAgdmFyIGtleSA9IHByb3BzW2luZGV4XTtcbiAgICBpZiAoKGFsbG93SW5kZXhlcyAmJiBpc0luZGV4KGtleSwgbGVuZ3RoKSkgfHwgaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIGtleSkpIHtcbiAgICAgIHJlc3VsdC5wdXNoKGtleSk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gc2hpbUtleXM7XG4iLCJ2YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9sYW5nL2lzT2JqZWN0JyksXG4gICAgaXNTdHJpbmcgPSByZXF1aXJlKCcuLi9sYW5nL2lzU3RyaW5nJyksXG4gICAgc3VwcG9ydCA9IHJlcXVpcmUoJy4uL3N1cHBvcnQnKTtcblxuLyoqXG4gKiBDb252ZXJ0cyBgdmFsdWVgIHRvIGFuIG9iamVjdCBpZiBpdCdzIG5vdCBvbmUuXG4gKlxuICogQHByaXZhdGVcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIHByb2Nlc3MuXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBvYmplY3QuXG4gKi9cbmZ1bmN0aW9uIHRvT2JqZWN0KHZhbHVlKSB7XG4gIGlmIChzdXBwb3J0LnVuaW5kZXhlZENoYXJzICYmIGlzU3RyaW5nKHZhbHVlKSkge1xuICAgIHZhciBpbmRleCA9IC0xLFxuICAgICAgICBsZW5ndGggPSB2YWx1ZS5sZW5ndGgsXG4gICAgICAgIHJlc3VsdCA9IE9iamVjdCh2YWx1ZSk7XG5cbiAgICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgICAgcmVzdWx0W2luZGV4XSA9IHZhbHVlLmNoYXJBdChpbmRleCk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cbiAgcmV0dXJuIGlzT2JqZWN0KHZhbHVlKSA/IHZhbHVlIDogT2JqZWN0KHZhbHVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB0b09iamVjdDtcbiIsInZhciBiYXNlVG9TdHJpbmcgPSByZXF1aXJlKCcuL2Jhc2VUb1N0cmluZycpLFxuICAgIGlzQXJyYXkgPSByZXF1aXJlKCcuLi9sYW5nL2lzQXJyYXknKTtcblxuLyoqIFVzZWQgdG8gbWF0Y2ggcHJvcGVydHkgbmFtZXMgd2l0aGluIHByb3BlcnR5IHBhdGhzLiAqL1xudmFyIHJlUHJvcE5hbWUgPSAvW14uW1xcXV0rfFxcWyg/OigtP1xcZCsoPzpcXC5cXGQrKT8pfChbXCInXSkoKD86KD8hXFwyKVteXFxuXFxcXF18XFxcXC4pKj8pXFwyKVxcXS9nO1xuXG4vKiogVXNlZCB0byBtYXRjaCBiYWNrc2xhc2hlcyBpbiBwcm9wZXJ0eSBwYXRocy4gKi9cbnZhciByZUVzY2FwZUNoYXIgPSAvXFxcXChcXFxcKT8vZztcblxuLyoqXG4gKiBDb252ZXJ0cyBgdmFsdWVgIHRvIHByb3BlcnR5IHBhdGggYXJyYXkgaWYgaXQncyBub3Qgb25lLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBwcm9jZXNzLlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBwcm9wZXJ0eSBwYXRoIGFycmF5LlxuICovXG5mdW5jdGlvbiB0b1BhdGgodmFsdWUpIHtcbiAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG4gIHZhciByZXN1bHQgPSBbXTtcbiAgYmFzZVRvU3RyaW5nKHZhbHVlKS5yZXBsYWNlKHJlUHJvcE5hbWUsIGZ1bmN0aW9uKG1hdGNoLCBudW1iZXIsIHF1b3RlLCBzdHJpbmcpIHtcbiAgICByZXN1bHQucHVzaChxdW90ZSA/IHN0cmluZy5yZXBsYWNlKHJlRXNjYXBlQ2hhciwgJyQxJykgOiAobnVtYmVyIHx8IG1hdGNoKSk7XG4gIH0pO1xuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHRvUGF0aDtcbiIsInZhciBMYXp5V3JhcHBlciA9IHJlcXVpcmUoJy4vTGF6eVdyYXBwZXInKSxcbiAgICBMb2Rhc2hXcmFwcGVyID0gcmVxdWlyZSgnLi9Mb2Rhc2hXcmFwcGVyJyksXG4gICAgYXJyYXlDb3B5ID0gcmVxdWlyZSgnLi9hcnJheUNvcHknKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgY2xvbmUgb2YgYHdyYXBwZXJgLlxuICpcbiAqIEBwcml2YXRlXG4gKiBAcGFyYW0ge09iamVjdH0gd3JhcHBlciBUaGUgd3JhcHBlciB0byBjbG9uZS5cbiAqIEByZXR1cm5zIHtPYmplY3R9IFJldHVybnMgdGhlIGNsb25lZCB3cmFwcGVyLlxuICovXG5mdW5jdGlvbiB3cmFwcGVyQ2xvbmUod3JhcHBlcikge1xuICByZXR1cm4gd3JhcHBlciBpbnN0YW5jZW9mIExhenlXcmFwcGVyXG4gICAgPyB3cmFwcGVyLmNsb25lKClcbiAgICA6IG5ldyBMb2Rhc2hXcmFwcGVyKHdyYXBwZXIuX193cmFwcGVkX18sIHdyYXBwZXIuX19jaGFpbl9fLCBhcnJheUNvcHkod3JhcHBlci5fX2FjdGlvbnNfXykpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHdyYXBwZXJDbG9uZTtcbiIsInZhciBiYXNlQ2xvbmUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9iYXNlQ2xvbmUnKSxcbiAgICBiaW5kQ2FsbGJhY2sgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9iaW5kQ2FsbGJhY2snKTtcblxuLyoqXG4gKiBDcmVhdGVzIGEgZGVlcCBjbG9uZSBvZiBgdmFsdWVgLiBJZiBgY3VzdG9taXplcmAgaXMgcHJvdmlkZWQgaXQncyBpbnZva2VkXG4gKiB0byBwcm9kdWNlIHRoZSBjbG9uZWQgdmFsdWVzLiBJZiBgY3VzdG9taXplcmAgcmV0dXJucyBgdW5kZWZpbmVkYCBjbG9uaW5nXG4gKiBpcyBoYW5kbGVkIGJ5IHRoZSBtZXRob2QgaW5zdGVhZC4gVGhlIGBjdXN0b21pemVyYCBpcyBib3VuZCB0byBgdGhpc0FyZ2BcbiAqIGFuZCBpbnZva2VkIHdpdGggdXAgdG8gdGhyZWUgYXJndW1lbnQ7ICh2YWx1ZSBbLCBpbmRleHxrZXksIG9iamVjdF0pLlxuICpcbiAqICoqTm90ZToqKiBUaGlzIG1ldGhvZCBpcyBsb29zZWx5IGJhc2VkIG9uIHRoZVxuICogW3N0cnVjdHVyZWQgY2xvbmUgYWxnb3JpdGhtXShodHRwOi8vd3d3LnczLm9yZy9UUi9odG1sNS9pbmZyYXN0cnVjdHVyZS5odG1sI2ludGVybmFsLXN0cnVjdHVyZWQtY2xvbmluZy1hbGdvcml0aG0pLlxuICogVGhlIGVudW1lcmFibGUgcHJvcGVydGllcyBvZiBgYXJndW1lbnRzYCBvYmplY3RzIGFuZCBvYmplY3RzIGNyZWF0ZWQgYnlcbiAqIGNvbnN0cnVjdG9ycyBvdGhlciB0aGFuIGBPYmplY3RgIGFyZSBjbG9uZWQgdG8gcGxhaW4gYE9iamVjdGAgb2JqZWN0cy4gQW5cbiAqIGVtcHR5IG9iamVjdCBpcyByZXR1cm5lZCBmb3IgdW5jbG9uZWFibGUgdmFsdWVzIHN1Y2ggYXMgZnVuY3Rpb25zLCBET00gbm9kZXMsXG4gKiBNYXBzLCBTZXRzLCBhbmQgV2Vha01hcHMuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBkZWVwIGNsb25lLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gW2N1c3RvbWl6ZXJdIFRoZSBmdW5jdGlvbiB0byBjdXN0b21pemUgY2xvbmluZyB2YWx1ZXMuXG4gKiBAcGFyYW0geyp9IFt0aGlzQXJnXSBUaGUgYHRoaXNgIGJpbmRpbmcgb2YgYGN1c3RvbWl6ZXJgLlxuICogQHJldHVybnMgeyp9IFJldHVybnMgdGhlIGRlZXAgY2xvbmVkIHZhbHVlLlxuICogQGV4YW1wbGVcbiAqXG4gKiB2YXIgdXNlcnMgPSBbXG4gKiAgIHsgJ3VzZXInOiAnYmFybmV5JyB9LFxuICogICB7ICd1c2VyJzogJ2ZyZWQnIH1cbiAqIF07XG4gKlxuICogdmFyIGRlZXAgPSBfLmNsb25lRGVlcCh1c2Vycyk7XG4gKiBkZWVwWzBdID09PSB1c2Vyc1swXTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogLy8gdXNpbmcgYSBjdXN0b21pemVyIGNhbGxiYWNrXG4gKiB2YXIgZWwgPSBfLmNsb25lRGVlcChkb2N1bWVudC5ib2R5LCBmdW5jdGlvbih2YWx1ZSkge1xuICogICBpZiAoXy5pc0VsZW1lbnQodmFsdWUpKSB7XG4gKiAgICAgcmV0dXJuIHZhbHVlLmNsb25lTm9kZSh0cnVlKTtcbiAqICAgfVxuICogfSk7XG4gKlxuICogZWwgPT09IGRvY3VtZW50LmJvZHlcbiAqIC8vID0+IGZhbHNlXG4gKiBlbC5ub2RlTmFtZVxuICogLy8gPT4gQk9EWVxuICogZWwuY2hpbGROb2Rlcy5sZW5ndGg7XG4gKiAvLyA9PiAyMFxuICovXG5mdW5jdGlvbiBjbG9uZURlZXAodmFsdWUsIGN1c3RvbWl6ZXIsIHRoaXNBcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBjdXN0b21pemVyID09ICdmdW5jdGlvbidcbiAgICA/IGJhc2VDbG9uZSh2YWx1ZSwgdHJ1ZSwgYmluZENhbGxiYWNrKGN1c3RvbWl6ZXIsIHRoaXNBcmcsIDMpKVxuICAgIDogYmFzZUNsb25lKHZhbHVlLCB0cnVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBjbG9uZURlZXA7XG4iLCJ2YXIgaXNBcnJheUxpa2UgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9pc0FycmF5TGlrZScpLFxuICAgIGlzT2JqZWN0TGlrZSA9IHJlcXVpcmUoJy4uL2ludGVybmFsL2lzT2JqZWN0TGlrZScpO1xuXG4vKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqIE5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBwcm9wZXJ0eUlzRW51bWVyYWJsZSA9IG9iamVjdFByb3RvLnByb3BlcnR5SXNFbnVtZXJhYmxlO1xuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYW4gYGFyZ3VtZW50c2Agb2JqZWN0LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzQXJndW1lbnRzKGZ1bmN0aW9uKCkgeyByZXR1cm4gYXJndW1lbnRzOyB9KCkpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNBcmd1bWVudHMoWzEsIDIsIDNdKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzQXJndW1lbnRzKHZhbHVlKSB7XG4gIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGlzQXJyYXlMaWtlKHZhbHVlKSAmJlxuICAgIGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsICdjYWxsZWUnKSAmJiAhcHJvcGVydHlJc0VudW1lcmFibGUuY2FsbCh2YWx1ZSwgJ2NhbGxlZScpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGlzQXJndW1lbnRzO1xuIiwidmFyIGdldE5hdGl2ZSA9IHJlcXVpcmUoJy4uL2ludGVybmFsL2dldE5hdGl2ZScpLFxuICAgIGlzTGVuZ3RoID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvaXNMZW5ndGgnKSxcbiAgICBpc09iamVjdExpa2UgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9pc09iamVjdExpa2UnKTtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIGFycmF5VGFnID0gJ1tvYmplY3QgQXJyYXldJztcblxuLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKlxuICogVXNlZCB0byByZXNvbHZlIHRoZSBbYHRvU3RyaW5nVGFnYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZylcbiAqIG9mIHZhbHVlcy5cbiAqL1xudmFyIG9ialRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbi8qIE5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlSXNBcnJheSA9IGdldE5hdGl2ZShBcnJheSwgJ2lzQXJyYXknKTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGFuIGBBcnJheWAgb2JqZWN0LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzQXJyYXkoWzEsIDIsIDNdKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzQXJyYXkoZnVuY3Rpb24oKSB7IHJldHVybiBhcmd1bWVudHM7IH0oKSk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG52YXIgaXNBcnJheSA9IG5hdGl2ZUlzQXJyYXkgfHwgZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgaXNMZW5ndGgodmFsdWUubGVuZ3RoKSAmJiBvYmpUb1N0cmluZy5jYWxsKHZhbHVlKSA9PSBhcnJheVRhZztcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gaXNBcnJheTtcbiIsInZhciBpc0FyZ3VtZW50cyA9IHJlcXVpcmUoJy4vaXNBcmd1bWVudHMnKSxcbiAgICBpc0FycmF5ID0gcmVxdWlyZSgnLi9pc0FycmF5JyksXG4gICAgaXNBcnJheUxpa2UgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9pc0FycmF5TGlrZScpLFxuICAgIGlzRnVuY3Rpb24gPSByZXF1aXJlKCcuL2lzRnVuY3Rpb24nKSxcbiAgICBpc09iamVjdExpa2UgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9pc09iamVjdExpa2UnKSxcbiAgICBpc1N0cmluZyA9IHJlcXVpcmUoJy4vaXNTdHJpbmcnKSxcbiAgICBrZXlzID0gcmVxdWlyZSgnLi4vb2JqZWN0L2tleXMnKTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBlbXB0eS4gQSB2YWx1ZSBpcyBjb25zaWRlcmVkIGVtcHR5IHVubGVzcyBpdCdzIGFuXG4gKiBgYXJndW1lbnRzYCBvYmplY3QsIGFycmF5LCBzdHJpbmcsIG9yIGpRdWVyeS1saWtlIGNvbGxlY3Rpb24gd2l0aCBhIGxlbmd0aFxuICogZ3JlYXRlciB0aGFuIGAwYCBvciBhbiBvYmplY3Qgd2l0aCBvd24gZW51bWVyYWJsZSBwcm9wZXJ0aWVzLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHtBcnJheXxPYmplY3R8c3RyaW5nfSB2YWx1ZSBUaGUgdmFsdWUgdG8gaW5zcGVjdC5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGVtcHR5LCBlbHNlIGBmYWxzZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIF8uaXNFbXB0eShudWxsKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzRW1wdHkodHJ1ZSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc0VtcHR5KDEpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNFbXB0eShbMSwgMiwgM10pO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzRW1wdHkoeyAnYSc6IDEgfSk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0VtcHR5KHZhbHVlKSB7XG4gIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKGlzQXJyYXlMaWtlKHZhbHVlKSAmJiAoaXNBcnJheSh2YWx1ZSkgfHwgaXNTdHJpbmcodmFsdWUpIHx8IGlzQXJndW1lbnRzKHZhbHVlKSB8fFxuICAgICAgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgaXNGdW5jdGlvbih2YWx1ZS5zcGxpY2UpKSkpIHtcbiAgICByZXR1cm4gIXZhbHVlLmxlbmd0aDtcbiAgfVxuICByZXR1cm4gIWtleXModmFsdWUpLmxlbmd0aDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc0VtcHR5O1xuIiwidmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9pc09iamVjdCcpO1xuXG4vKiogYE9iamVjdCN0b1N0cmluZ2AgcmVzdWx0IHJlZmVyZW5jZXMuICovXG52YXIgZnVuY1RhZyA9ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG5cbi8qKiBVc2VkIGZvciBuYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgb2JqZWN0UHJvdG8gPSBPYmplY3QucHJvdG90eXBlO1xuXG4vKipcbiAqIFVzZWQgdG8gcmVzb2x2ZSB0aGUgW2B0b1N0cmluZ1RhZ2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmcpXG4gKiBvZiB2YWx1ZXMuXG4gKi9cbnZhciBvYmpUb1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIGNsYXNzaWZpZWQgYXMgYSBgRnVuY3Rpb25gIG9iamVjdC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc0Z1bmN0aW9uKF8pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNGdW5jdGlvbigvYWJjLyk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc0Z1bmN0aW9uKHZhbHVlKSB7XG4gIC8vIFRoZSB1c2Ugb2YgYE9iamVjdCN0b1N0cmluZ2AgYXZvaWRzIGlzc3VlcyB3aXRoIHRoZSBgdHlwZW9mYCBvcGVyYXRvclxuICAvLyBpbiBvbGRlciB2ZXJzaW9ucyBvZiBDaHJvbWUgYW5kIFNhZmFyaSB3aGljaCByZXR1cm4gJ2Z1bmN0aW9uJyBmb3IgcmVnZXhlc1xuICAvLyBhbmQgU2FmYXJpIDggd2hpY2ggcmV0dXJucyAnb2JqZWN0JyBmb3IgdHlwZWQgYXJyYXkgY29uc3RydWN0b3JzLlxuICByZXR1cm4gaXNPYmplY3QodmFsdWUpICYmIG9ialRvU3RyaW5nLmNhbGwodmFsdWUpID09IGZ1bmNUYWc7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNGdW5jdGlvbjtcbiIsInZhciBpc0Z1bmN0aW9uID0gcmVxdWlyZSgnLi9pc0Z1bmN0aW9uJyksXG4gICAgaXNIb3N0T2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvaXNIb3N0T2JqZWN0JyksXG4gICAgaXNPYmplY3RMaWtlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvaXNPYmplY3RMaWtlJyk7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBob3N0IGNvbnN0cnVjdG9ycyAoU2FmYXJpID4gNSkuICovXG52YXIgcmVJc0hvc3RDdG9yID0gL15cXFtvYmplY3QgLis/Q29uc3RydWN0b3JcXF0kLztcblxuLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIHJlc29sdmUgdGhlIGRlY29tcGlsZWQgc291cmNlIG9mIGZ1bmN0aW9ucy4gKi9cbnZhciBmblRvU3RyaW5nID0gRnVuY3Rpb24ucHJvdG90eXBlLnRvU3RyaW5nO1xuXG4vKiogVXNlZCB0byBjaGVjayBvYmplY3RzIGZvciBvd24gcHJvcGVydGllcy4gKi9cbnZhciBoYXNPd25Qcm9wZXJ0eSA9IG9iamVjdFByb3RvLmhhc093blByb3BlcnR5O1xuXG4vKiogVXNlZCB0byBkZXRlY3QgaWYgYSBtZXRob2QgaXMgbmF0aXZlLiAqL1xudmFyIHJlSXNOYXRpdmUgPSBSZWdFeHAoJ14nICtcbiAgZm5Ub1N0cmluZy5jYWxsKGhhc093blByb3BlcnR5KS5yZXBsYWNlKC9bXFxcXF4kLiorPygpW1xcXXt9fF0vZywgJ1xcXFwkJicpXG4gIC5yZXBsYWNlKC9oYXNPd25Qcm9wZXJ0eXwoZnVuY3Rpb24pLio/KD89XFxcXFxcKCl8IGZvciAuKz8oPz1cXFxcXFxdKS9nLCAnJDEuKj8nKSArICckJ1xuKTtcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIG5hdGl2ZSBmdW5jdGlvbi5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBuYXRpdmUgZnVuY3Rpb24sIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc05hdGl2ZShBcnJheS5wcm90b3R5cGUucHVzaCk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc05hdGl2ZShfKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzTmF0aXZlKHZhbHVlKSB7XG4gIGlmICh2YWx1ZSA9PSBudWxsKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChpc0Z1bmN0aW9uKHZhbHVlKSkge1xuICAgIHJldHVybiByZUlzTmF0aXZlLnRlc3QoZm5Ub1N0cmluZy5jYWxsKHZhbHVlKSk7XG4gIH1cbiAgcmV0dXJuIGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgKGlzSG9zdE9iamVjdCh2YWx1ZSkgPyByZUlzTmF0aXZlIDogcmVJc0hvc3RDdG9yKS50ZXN0KHZhbHVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc05hdGl2ZTtcbiIsIi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgdGhlIFtsYW5ndWFnZSB0eXBlXShodHRwczovL2VzNS5naXRodWIuaW8vI3g4KSBvZiBgT2JqZWN0YC5cbiAqIChlLmcuIGFycmF5cywgZnVuY3Rpb25zLCBvYmplY3RzLCByZWdleGVzLCBgbmV3IE51bWJlcigwKWAsIGFuZCBgbmV3IFN0cmluZygnJylgKVxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhbiBvYmplY3QsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc09iamVjdCh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChbMSwgMiwgM10pO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QoMSk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICAvLyBBdm9pZCBhIFY4IEpJVCBidWcgaW4gQ2hyb21lIDE5LTIwLlxuICAvLyBTZWUgaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC92OC9pc3N1ZXMvZGV0YWlsP2lkPTIyOTEgZm9yIG1vcmUgZGV0YWlscy5cbiAgdmFyIHR5cGUgPSB0eXBlb2YgdmFsdWU7XG4gIHJldHVybiAhIXZhbHVlICYmICh0eXBlID09ICdvYmplY3QnIHx8IHR5cGUgPT0gJ2Z1bmN0aW9uJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNPYmplY3Q7XG4iLCJ2YXIgYmFzZUZvckluID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvYmFzZUZvckluJyksXG4gICAgaXNBcmd1bWVudHMgPSByZXF1aXJlKCcuL2lzQXJndW1lbnRzJyksXG4gICAgaXNIb3N0T2JqZWN0ID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvaXNIb3N0T2JqZWN0JyksXG4gICAgaXNPYmplY3RMaWtlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvaXNPYmplY3RMaWtlJyksXG4gICAgc3VwcG9ydCA9IHJlcXVpcmUoJy4uL3N1cHBvcnQnKTtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFRhZyA9ICdbb2JqZWN0IE9iamVjdF0nO1xuXG4vKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIFVzZWQgdG8gY2hlY2sgb2JqZWN0cyBmb3Igb3duIHByb3BlcnRpZXMuICovXG52YXIgaGFzT3duUHJvcGVydHkgPSBvYmplY3RQcm90by5oYXNPd25Qcm9wZXJ0eTtcblxuLyoqXG4gKiBVc2VkIHRvIHJlc29sdmUgdGhlIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICogb2YgdmFsdWVzLlxuICovXG52YXIgb2JqVG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBhIHBsYWluIG9iamVjdCwgdGhhdCBpcywgYW4gb2JqZWN0IGNyZWF0ZWQgYnkgdGhlXG4gKiBgT2JqZWN0YCBjb25zdHJ1Y3RvciBvciBvbmUgd2l0aCBhIGBbW1Byb3RvdHlwZV1dYCBvZiBgbnVsbGAuXG4gKlxuICogKipOb3RlOioqIFRoaXMgbWV0aG9kIGFzc3VtZXMgb2JqZWN0cyBjcmVhdGVkIGJ5IHRoZSBgT2JqZWN0YCBjb25zdHJ1Y3RvclxuICogaGF2ZSBubyBpbmhlcml0ZWQgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBhIHBsYWluIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBmdW5jdGlvbiBGb28oKSB7XG4gKiAgIHRoaXMuYSA9IDE7XG4gKiB9XG4gKlxuICogXy5pc1BsYWluT2JqZWN0KG5ldyBGb28pO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzUGxhaW5PYmplY3QoWzEsIDIsIDNdKTtcbiAqIC8vID0+IGZhbHNlXG4gKlxuICogXy5pc1BsYWluT2JqZWN0KHsgJ3gnOiAwLCAneSc6IDAgfSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc1BsYWluT2JqZWN0KE9iamVjdC5jcmVhdGUobnVsbCkpO1xuICogLy8gPT4gdHJ1ZVxuICovXG5mdW5jdGlvbiBpc1BsYWluT2JqZWN0KHZhbHVlKSB7XG4gIHZhciBDdG9yO1xuXG4gIC8vIEV4aXQgZWFybHkgZm9yIG5vbiBgT2JqZWN0YCBvYmplY3RzLlxuICBpZiAoIShpc09iamVjdExpa2UodmFsdWUpICYmIG9ialRvU3RyaW5nLmNhbGwodmFsdWUpID09IG9iamVjdFRhZyAmJiAhaXNIb3N0T2JqZWN0KHZhbHVlKSAmJiAhaXNBcmd1bWVudHModmFsdWUpKSB8fFxuICAgICAgKCFoYXNPd25Qcm9wZXJ0eS5jYWxsKHZhbHVlLCAnY29uc3RydWN0b3InKSAmJiAoQ3RvciA9IHZhbHVlLmNvbnN0cnVjdG9yLCB0eXBlb2YgQ3RvciA9PSAnZnVuY3Rpb24nICYmICEoQ3RvciBpbnN0YW5jZW9mIEN0b3IpKSkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgLy8gSUUgPCA5IGl0ZXJhdGVzIGluaGVyaXRlZCBwcm9wZXJ0aWVzIGJlZm9yZSBvd24gcHJvcGVydGllcy4gSWYgdGhlIGZpcnN0XG4gIC8vIGl0ZXJhdGVkIHByb3BlcnR5IGlzIGFuIG9iamVjdCdzIG93biBwcm9wZXJ0eSB0aGVuIHRoZXJlIGFyZSBubyBpbmhlcml0ZWRcbiAgLy8gZW51bWVyYWJsZSBwcm9wZXJ0aWVzLlxuICB2YXIgcmVzdWx0O1xuICBpZiAoc3VwcG9ydC5vd25MYXN0KSB7XG4gICAgYmFzZUZvckluKHZhbHVlLCBmdW5jdGlvbihzdWJWYWx1ZSwga2V5LCBvYmplY3QpIHtcbiAgICAgIHJlc3VsdCA9IGhhc093blByb3BlcnR5LmNhbGwob2JqZWN0LCBrZXkpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0pO1xuICAgIHJldHVybiByZXN1bHQgIT09IGZhbHNlO1xuICB9XG4gIC8vIEluIG1vc3QgZW52aXJvbm1lbnRzIGFuIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzIGFyZSBpdGVyYXRlZCBiZWZvcmVcbiAgLy8gaXRzIGluaGVyaXRlZCBwcm9wZXJ0aWVzLiBJZiB0aGUgbGFzdCBpdGVyYXRlZCBwcm9wZXJ0eSBpcyBhbiBvYmplY3Qnc1xuICAvLyBvd24gcHJvcGVydHkgdGhlbiB0aGVyZSBhcmUgbm8gaW5oZXJpdGVkIGVudW1lcmFibGUgcHJvcGVydGllcy5cbiAgYmFzZUZvckluKHZhbHVlLCBmdW5jdGlvbihzdWJWYWx1ZSwga2V5KSB7XG4gICAgcmVzdWx0ID0ga2V5O1xuICB9KTtcbiAgcmV0dXJuIHJlc3VsdCA9PT0gdW5kZWZpbmVkIHx8IGhhc093blByb3BlcnR5LmNhbGwodmFsdWUsIHJlc3VsdCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNQbGFpbk9iamVjdDtcbiIsInZhciBpc09iamVjdExpa2UgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9pc09iamVjdExpa2UnKTtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIHN0cmluZ1RhZyA9ICdbb2JqZWN0IFN0cmluZ10nO1xuXG4vKiogVXNlZCBmb3IgbmF0aXZlIG1ldGhvZCByZWZlcmVuY2VzLiAqL1xudmFyIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqXG4gKiBVc2VkIHRvIHJlc29sdmUgdGhlIFtgdG9TdHJpbmdUYWdgXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1vYmplY3QucHJvdG90eXBlLnRvc3RyaW5nKVxuICogb2YgdmFsdWVzLlxuICovXG52YXIgb2JqVG9TdHJpbmcgPSBvYmplY3RQcm90by50b1N0cmluZztcblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBjbGFzc2lmaWVkIGFzIGEgYFN0cmluZ2AgcHJpbWl0aXZlIG9yIG9iamVjdC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgY29ycmVjdGx5IGNsYXNzaWZpZWQsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc1N0cmluZygnYWJjJyk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc1N0cmluZygxKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzU3RyaW5nKHZhbHVlKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT0gJ3N0cmluZycgfHwgKGlzT2JqZWN0TGlrZSh2YWx1ZSkgJiYgb2JqVG9TdHJpbmcuY2FsbCh2YWx1ZSkgPT0gc3RyaW5nVGFnKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc1N0cmluZztcbiIsInZhciBpc0xlbmd0aCA9IHJlcXVpcmUoJy4uL2ludGVybmFsL2lzTGVuZ3RoJyksXG4gICAgaXNPYmplY3RMaWtlID0gcmVxdWlyZSgnLi4vaW50ZXJuYWwvaXNPYmplY3RMaWtlJyk7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBhcmdzVGFnID0gJ1tvYmplY3QgQXJndW1lbnRzXScsXG4gICAgYXJyYXlUYWcgPSAnW29iamVjdCBBcnJheV0nLFxuICAgIGJvb2xUYWcgPSAnW29iamVjdCBCb29sZWFuXScsXG4gICAgZGF0ZVRhZyA9ICdbb2JqZWN0IERhdGVdJyxcbiAgICBlcnJvclRhZyA9ICdbb2JqZWN0IEVycm9yXScsXG4gICAgZnVuY1RhZyA9ICdbb2JqZWN0IEZ1bmN0aW9uXScsXG4gICAgbWFwVGFnID0gJ1tvYmplY3QgTWFwXScsXG4gICAgbnVtYmVyVGFnID0gJ1tvYmplY3QgTnVtYmVyXScsXG4gICAgb2JqZWN0VGFnID0gJ1tvYmplY3QgT2JqZWN0XScsXG4gICAgcmVnZXhwVGFnID0gJ1tvYmplY3QgUmVnRXhwXScsXG4gICAgc2V0VGFnID0gJ1tvYmplY3QgU2V0XScsXG4gICAgc3RyaW5nVGFnID0gJ1tvYmplY3QgU3RyaW5nXScsXG4gICAgd2Vha01hcFRhZyA9ICdbb2JqZWN0IFdlYWtNYXBdJztcblxudmFyIGFycmF5QnVmZmVyVGFnID0gJ1tvYmplY3QgQXJyYXlCdWZmZXJdJyxcbiAgICBmbG9hdDMyVGFnID0gJ1tvYmplY3QgRmxvYXQzMkFycmF5XScsXG4gICAgZmxvYXQ2NFRhZyA9ICdbb2JqZWN0IEZsb2F0NjRBcnJheV0nLFxuICAgIGludDhUYWcgPSAnW29iamVjdCBJbnQ4QXJyYXldJyxcbiAgICBpbnQxNlRhZyA9ICdbb2JqZWN0IEludDE2QXJyYXldJyxcbiAgICBpbnQzMlRhZyA9ICdbb2JqZWN0IEludDMyQXJyYXldJyxcbiAgICB1aW50OFRhZyA9ICdbb2JqZWN0IFVpbnQ4QXJyYXldJyxcbiAgICB1aW50OENsYW1wZWRUYWcgPSAnW29iamVjdCBVaW50OENsYW1wZWRBcnJheV0nLFxuICAgIHVpbnQxNlRhZyA9ICdbb2JqZWN0IFVpbnQxNkFycmF5XScsXG4gICAgdWludDMyVGFnID0gJ1tvYmplY3QgVWludDMyQXJyYXldJztcblxuLyoqIFVzZWQgdG8gaWRlbnRpZnkgYHRvU3RyaW5nVGFnYCB2YWx1ZXMgb2YgdHlwZWQgYXJyYXlzLiAqL1xudmFyIHR5cGVkQXJyYXlUYWdzID0ge307XG50eXBlZEFycmF5VGFnc1tmbG9hdDMyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Zsb2F0NjRUYWddID1cbnR5cGVkQXJyYXlUYWdzW2ludDhUYWddID0gdHlwZWRBcnJheVRhZ3NbaW50MTZUYWddID1cbnR5cGVkQXJyYXlUYWdzW2ludDMyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW3VpbnQ4VGFnXSA9XG50eXBlZEFycmF5VGFnc1t1aW50OENsYW1wZWRUYWddID0gdHlwZWRBcnJheVRhZ3NbdWludDE2VGFnXSA9XG50eXBlZEFycmF5VGFnc1t1aW50MzJUYWddID0gdHJ1ZTtcbnR5cGVkQXJyYXlUYWdzW2FyZ3NUYWddID0gdHlwZWRBcnJheVRhZ3NbYXJyYXlUYWddID1cbnR5cGVkQXJyYXlUYWdzW2FycmF5QnVmZmVyVGFnXSA9IHR5cGVkQXJyYXlUYWdzW2Jvb2xUYWddID1cbnR5cGVkQXJyYXlUYWdzW2RhdGVUYWddID0gdHlwZWRBcnJheVRhZ3NbZXJyb3JUYWddID1cbnR5cGVkQXJyYXlUYWdzW2Z1bmNUYWddID0gdHlwZWRBcnJheVRhZ3NbbWFwVGFnXSA9XG50eXBlZEFycmF5VGFnc1tudW1iZXJUYWddID0gdHlwZWRBcnJheVRhZ3Nbb2JqZWN0VGFnXSA9XG50eXBlZEFycmF5VGFnc1tyZWdleHBUYWddID0gdHlwZWRBcnJheVRhZ3Nbc2V0VGFnXSA9XG50eXBlZEFycmF5VGFnc1tzdHJpbmdUYWddID0gdHlwZWRBcnJheVRhZ3Nbd2Vha01hcFRhZ10gPSBmYWxzZTtcblxuLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKlxuICogVXNlZCB0byByZXNvbHZlIHRoZSBbYHRvU3RyaW5nVGFnYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZylcbiAqIG9mIHZhbHVlcy5cbiAqL1xudmFyIG9ialRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIHR5cGVkIGFycmF5LlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBjb3JyZWN0bHkgY2xhc3NpZmllZCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzVHlwZWRBcnJheShuZXcgVWludDhBcnJheSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc1R5cGVkQXJyYXkoW10pO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNUeXBlZEFycmF5KHZhbHVlKSB7XG4gIHJldHVybiBpc09iamVjdExpa2UodmFsdWUpICYmIGlzTGVuZ3RoKHZhbHVlLmxlbmd0aCkgJiYgISF0eXBlZEFycmF5VGFnc1tvYmpUb1N0cmluZy5jYWxsKHZhbHVlKV07XG59XG5cbm1vZHVsZS5leHBvcnRzID0gaXNUeXBlZEFycmF5O1xuIiwiLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBgdW5kZWZpbmVkYC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYHVuZGVmaW5lZGAsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc1VuZGVmaW5lZCh2b2lkIDApO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNVbmRlZmluZWQobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc1VuZGVmaW5lZCh2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUgPT09IHVuZGVmaW5lZDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc1VuZGVmaW5lZDtcbiIsInZhciBnZXROYXRpdmUgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9nZXROYXRpdmUnKSxcbiAgICBpc0FycmF5TGlrZSA9IHJlcXVpcmUoJy4uL2ludGVybmFsL2lzQXJyYXlMaWtlJyksXG4gICAgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9sYW5nL2lzT2JqZWN0JyksXG4gICAgc2hpbUtleXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9zaGltS2V5cycpLFxuICAgIHN1cHBvcnQgPSByZXF1aXJlKCcuLi9zdXBwb3J0Jyk7XG5cbi8qIE5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlS2V5cyA9IGdldE5hdGl2ZShPYmplY3QsICdrZXlzJyk7XG5cbi8qKlxuICogQ3JlYXRlcyBhbiBhcnJheSBvZiB0aGUgb3duIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgb2YgYG9iamVjdGAuXG4gKlxuICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuIFNlZSB0aGVcbiAqIFtFUyBzcGVjXShodHRwOi8vZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi82LjAvI3NlYy1vYmplY3Qua2V5cylcbiAqIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBjYXRlZ29yeSBPYmplY3RcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gKiBAZXhhbXBsZVxuICpcbiAqIGZ1bmN0aW9uIEZvbygpIHtcbiAqICAgdGhpcy5hID0gMTtcbiAqICAgdGhpcy5iID0gMjtcbiAqIH1cbiAqXG4gKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICpcbiAqIF8ua2V5cyhuZXcgRm9vKTtcbiAqIC8vID0+IFsnYScsICdiJ10gKGl0ZXJhdGlvbiBvcmRlciBpcyBub3QgZ3VhcmFudGVlZClcbiAqXG4gKiBfLmtleXMoJ2hpJyk7XG4gKiAvLyA9PiBbJzAnLCAnMSddXG4gKi9cbnZhciBrZXlzID0gIW5hdGl2ZUtleXMgPyBzaGltS2V5cyA6IGZ1bmN0aW9uKG9iamVjdCkge1xuICB2YXIgQ3RvciA9IG9iamVjdCA9PSBudWxsID8gdW5kZWZpbmVkIDogb2JqZWN0LmNvbnN0cnVjdG9yO1xuICBpZiAoKHR5cGVvZiBDdG9yID09ICdmdW5jdGlvbicgJiYgQ3Rvci5wcm90b3R5cGUgPT09IG9iamVjdCkgfHxcbiAgICAgICh0eXBlb2Ygb2JqZWN0ID09ICdmdW5jdGlvbicgPyBzdXBwb3J0LmVudW1Qcm90b3R5cGVzIDogaXNBcnJheUxpa2Uob2JqZWN0KSkpIHtcbiAgICByZXR1cm4gc2hpbUtleXMob2JqZWN0KTtcbiAgfVxuICByZXR1cm4gaXNPYmplY3Qob2JqZWN0KSA/IG5hdGl2ZUtleXMob2JqZWN0KSA6IFtdO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBrZXlzO1xuIiwidmFyIGFycmF5RWFjaCA9IHJlcXVpcmUoJy4uL2ludGVybmFsL2FycmF5RWFjaCcpLFxuICAgIGlzQXJndW1lbnRzID0gcmVxdWlyZSgnLi4vbGFuZy9pc0FyZ3VtZW50cycpLFxuICAgIGlzQXJyYXkgPSByZXF1aXJlKCcuLi9sYW5nL2lzQXJyYXknKSxcbiAgICBpc0Z1bmN0aW9uID0gcmVxdWlyZSgnLi4vbGFuZy9pc0Z1bmN0aW9uJyksXG4gICAgaXNJbmRleCA9IHJlcXVpcmUoJy4uL2ludGVybmFsL2lzSW5kZXgnKSxcbiAgICBpc0xlbmd0aCA9IHJlcXVpcmUoJy4uL2ludGVybmFsL2lzTGVuZ3RoJyksXG4gICAgaXNPYmplY3QgPSByZXF1aXJlKCcuLi9sYW5nL2lzT2JqZWN0JyksXG4gICAgaXNTdHJpbmcgPSByZXF1aXJlKCcuLi9sYW5nL2lzU3RyaW5nJyksXG4gICAgc3VwcG9ydCA9IHJlcXVpcmUoJy4uL3N1cHBvcnQnKTtcblxuLyoqIGBPYmplY3QjdG9TdHJpbmdgIHJlc3VsdCByZWZlcmVuY2VzLiAqL1xudmFyIGFycmF5VGFnID0gJ1tvYmplY3QgQXJyYXldJyxcbiAgICBib29sVGFnID0gJ1tvYmplY3QgQm9vbGVhbl0nLFxuICAgIGRhdGVUYWcgPSAnW29iamVjdCBEYXRlXScsXG4gICAgZXJyb3JUYWcgPSAnW29iamVjdCBFcnJvcl0nLFxuICAgIGZ1bmNUYWcgPSAnW29iamVjdCBGdW5jdGlvbl0nLFxuICAgIG51bWJlclRhZyA9ICdbb2JqZWN0IE51bWJlcl0nLFxuICAgIG9iamVjdFRhZyA9ICdbb2JqZWN0IE9iamVjdF0nLFxuICAgIHJlZ2V4cFRhZyA9ICdbb2JqZWN0IFJlZ0V4cF0nLFxuICAgIHN0cmluZ1RhZyA9ICdbb2JqZWN0IFN0cmluZ10nO1xuXG4vKiogVXNlZCB0byBmaXggdGhlIEpTY3JpcHQgYFtbRG9udEVudW1dXWAgYnVnLiAqL1xudmFyIHNoYWRvd1Byb3BzID0gW1xuICAnY29uc3RydWN0b3InLCAnaGFzT3duUHJvcGVydHknLCAnaXNQcm90b3R5cGVPZicsICdwcm9wZXJ0eUlzRW51bWVyYWJsZScsXG4gICd0b0xvY2FsZVN0cmluZycsICd0b1N0cmluZycsICd2YWx1ZU9mJ1xuXTtcblxuLyoqIFVzZWQgZm9yIG5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBlcnJvclByb3RvID0gRXJyb3IucHJvdG90eXBlLFxuICAgIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZSxcbiAgICBzdHJpbmdQcm90byA9IFN0cmluZy5wcm90b3R5cGU7XG5cbi8qKiBVc2VkIHRvIGNoZWNrIG9iamVjdHMgZm9yIG93biBwcm9wZXJ0aWVzLiAqL1xudmFyIGhhc093blByb3BlcnR5ID0gb2JqZWN0UHJvdG8uaGFzT3duUHJvcGVydHk7XG5cbi8qKlxuICogVXNlZCB0byByZXNvbHZlIHRoZSBbYHRvU3RyaW5nVGFnYF0oaHR0cDovL2VjbWEtaW50ZXJuYXRpb25hbC5vcmcvZWNtYS0yNjIvNi4wLyNzZWMtb2JqZWN0LnByb3RvdHlwZS50b3N0cmluZylcbiAqIG9mIHZhbHVlcy5cbiAqL1xudmFyIG9ialRvU3RyaW5nID0gb2JqZWN0UHJvdG8udG9TdHJpbmc7XG5cbi8qKiBVc2VkIHRvIGF2b2lkIGl0ZXJhdGluZyBvdmVyIG5vbi1lbnVtZXJhYmxlIHByb3BlcnRpZXMgaW4gSUUgPCA5LiAqL1xudmFyIG5vbkVudW1Qcm9wcyA9IHt9O1xubm9uRW51bVByb3BzW2FycmF5VGFnXSA9IG5vbkVudW1Qcm9wc1tkYXRlVGFnXSA9IG5vbkVudW1Qcm9wc1tudW1iZXJUYWddID0geyAnY29uc3RydWN0b3InOiB0cnVlLCAndG9Mb2NhbGVTdHJpbmcnOiB0cnVlLCAndG9TdHJpbmcnOiB0cnVlLCAndmFsdWVPZic6IHRydWUgfTtcbm5vbkVudW1Qcm9wc1tib29sVGFnXSA9IG5vbkVudW1Qcm9wc1tzdHJpbmdUYWddID0geyAnY29uc3RydWN0b3InOiB0cnVlLCAndG9TdHJpbmcnOiB0cnVlLCAndmFsdWVPZic6IHRydWUgfTtcbm5vbkVudW1Qcm9wc1tlcnJvclRhZ10gPSBub25FbnVtUHJvcHNbZnVuY1RhZ10gPSBub25FbnVtUHJvcHNbcmVnZXhwVGFnXSA9IHsgJ2NvbnN0cnVjdG9yJzogdHJ1ZSwgJ3RvU3RyaW5nJzogdHJ1ZSB9O1xubm9uRW51bVByb3BzW29iamVjdFRhZ10gPSB7ICdjb25zdHJ1Y3Rvcic6IHRydWUgfTtcblxuYXJyYXlFYWNoKHNoYWRvd1Byb3BzLCBmdW5jdGlvbihrZXkpIHtcbiAgZm9yICh2YXIgdGFnIGluIG5vbkVudW1Qcm9wcykge1xuICAgIGlmIChoYXNPd25Qcm9wZXJ0eS5jYWxsKG5vbkVudW1Qcm9wcywgdGFnKSkge1xuICAgICAgdmFyIHByb3BzID0gbm9uRW51bVByb3BzW3RhZ107XG4gICAgICBwcm9wc1trZXldID0gaGFzT3duUHJvcGVydHkuY2FsbChwcm9wcywga2V5KTtcbiAgICB9XG4gIH1cbn0pO1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBhbmQgaW5oZXJpdGVkIGVudW1lcmFibGUgcHJvcGVydHkgbmFtZXMgb2YgYG9iamVjdGAuXG4gKlxuICogKipOb3RlOioqIE5vbi1vYmplY3QgdmFsdWVzIGFyZSBjb2VyY2VkIHRvIG9iamVjdHMuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBjYXRlZ29yeSBPYmplY3RcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgYXJyYXkgb2YgcHJvcGVydHkgbmFtZXMuXG4gKiBAZXhhbXBsZVxuICpcbiAqIGZ1bmN0aW9uIEZvbygpIHtcbiAqICAgdGhpcy5hID0gMTtcbiAqICAgdGhpcy5iID0gMjtcbiAqIH1cbiAqXG4gKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICpcbiAqIF8ua2V5c0luKG5ldyBGb28pO1xuICogLy8gPT4gWydhJywgJ2InLCAnYyddIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gKi9cbmZ1bmN0aW9uIGtleXNJbihvYmplY3QpIHtcbiAgaWYgKG9iamVjdCA9PSBudWxsKSB7XG4gICAgcmV0dXJuIFtdO1xuICB9XG4gIGlmICghaXNPYmplY3Qob2JqZWN0KSkge1xuICAgIG9iamVjdCA9IE9iamVjdChvYmplY3QpO1xuICB9XG4gIHZhciBsZW5ndGggPSBvYmplY3QubGVuZ3RoO1xuXG4gIGxlbmd0aCA9IChsZW5ndGggJiYgaXNMZW5ndGgobGVuZ3RoKSAmJlxuICAgIChpc0FycmF5KG9iamVjdCkgfHwgaXNBcmd1bWVudHMob2JqZWN0KSB8fCBpc1N0cmluZyhvYmplY3QpKSAmJiBsZW5ndGgpIHx8IDA7XG5cbiAgdmFyIEN0b3IgPSBvYmplY3QuY29uc3RydWN0b3IsXG4gICAgICBpbmRleCA9IC0xLFxuICAgICAgcHJvdG8gPSAoaXNGdW5jdGlvbihDdG9yKSAmJiBDdG9yLnByb3RvdHlwZSkgfHwgb2JqZWN0UHJvdG8sXG4gICAgICBpc1Byb3RvID0gcHJvdG8gPT09IG9iamVjdCxcbiAgICAgIHJlc3VsdCA9IEFycmF5KGxlbmd0aCksXG4gICAgICBza2lwSW5kZXhlcyA9IGxlbmd0aCA+IDAsXG4gICAgICBza2lwRXJyb3JQcm9wcyA9IHN1cHBvcnQuZW51bUVycm9yUHJvcHMgJiYgKG9iamVjdCA9PT0gZXJyb3JQcm90byB8fCBvYmplY3QgaW5zdGFuY2VvZiBFcnJvciksXG4gICAgICBza2lwUHJvdG8gPSBzdXBwb3J0LmVudW1Qcm90b3R5cGVzICYmIGlzRnVuY3Rpb24ob2JqZWN0KTtcblxuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIHJlc3VsdFtpbmRleF0gPSAoaW5kZXggKyAnJyk7XG4gIH1cbiAgLy8gbG9kYXNoIHNraXBzIHRoZSBgY29uc3RydWN0b3JgIHByb3BlcnR5IHdoZW4gaXQgaW5mZXJzIGl0J3MgaXRlcmF0aW5nXG4gIC8vIG92ZXIgYSBgcHJvdG90eXBlYCBvYmplY3QgYmVjYXVzZSBJRSA8IDkgY2FuJ3Qgc2V0IHRoZSBgW1tFbnVtZXJhYmxlXV1gXG4gIC8vIGF0dHJpYnV0ZSBvZiBhbiBleGlzdGluZyBwcm9wZXJ0eSBhbmQgdGhlIGBjb25zdHJ1Y3RvcmAgcHJvcGVydHkgb2YgYVxuICAvLyBwcm90b3R5cGUgZGVmYXVsdHMgdG8gbm9uLWVudW1lcmFibGUuXG4gIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICBpZiAoIShza2lwUHJvdG8gJiYga2V5ID09ICdwcm90b3R5cGUnKSAmJlxuICAgICAgICAhKHNraXBFcnJvclByb3BzICYmIChrZXkgPT0gJ21lc3NhZ2UnIHx8IGtleSA9PSAnbmFtZScpKSAmJlxuICAgICAgICAhKHNraXBJbmRleGVzICYmIGlzSW5kZXgoa2V5LCBsZW5ndGgpKSAmJlxuICAgICAgICAhKGtleSA9PSAnY29uc3RydWN0b3InICYmIChpc1Byb3RvIHx8ICFoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSkpKSB7XG4gICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgIH1cbiAgfVxuICBpZiAoc3VwcG9ydC5ub25FbnVtU2hhZG93cyAmJiBvYmplY3QgIT09IG9iamVjdFByb3RvKSB7XG4gICAgdmFyIHRhZyA9IG9iamVjdCA9PT0gc3RyaW5nUHJvdG8gPyBzdHJpbmdUYWcgOiAob2JqZWN0ID09PSBlcnJvclByb3RvID8gZXJyb3JUYWcgOiBvYmpUb1N0cmluZy5jYWxsKG9iamVjdCkpLFxuICAgICAgICBub25FbnVtcyA9IG5vbkVudW1Qcm9wc1t0YWddIHx8IG5vbkVudW1Qcm9wc1tvYmplY3RUYWddO1xuXG4gICAgaWYgKHRhZyA9PSBvYmplY3RUYWcpIHtcbiAgICAgIHByb3RvID0gb2JqZWN0UHJvdG87XG4gICAgfVxuICAgIGxlbmd0aCA9IHNoYWRvd1Byb3BzLmxlbmd0aDtcbiAgICB3aGlsZSAobGVuZ3RoLS0pIHtcbiAgICAgIGtleSA9IHNoYWRvd1Byb3BzW2xlbmd0aF07XG4gICAgICB2YXIgbm9uRW51bSA9IG5vbkVudW1zW2tleV07XG4gICAgICBpZiAoIShpc1Byb3RvICYmIG5vbkVudW0pICYmXG4gICAgICAgICAgKG5vbkVudW0gPyBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwga2V5KSA6IG9iamVjdFtrZXldICE9PSBwcm90b1trZXldKSkge1xuICAgICAgICByZXN1bHQucHVzaChrZXkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGtleXNJbjtcbiIsInZhciBrZXlzID0gcmVxdWlyZSgnLi9rZXlzJyksXG4gICAgdG9PYmplY3QgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC90b09iamVjdCcpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSB0d28gZGltZW5zaW9uYWwgYXJyYXkgb2YgdGhlIGtleS12YWx1ZSBwYWlycyBmb3IgYG9iamVjdGAsXG4gKiBlLmcuIGBbW2tleTEsIHZhbHVlMV0sIFtrZXkyLCB2YWx1ZTJdXWAuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBjYXRlZ29yeSBPYmplY3RcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmplY3QgVGhlIG9iamVjdCB0byBxdWVyeS5cbiAqIEByZXR1cm5zIHtBcnJheX0gUmV0dXJucyB0aGUgbmV3IGFycmF5IG9mIGtleS12YWx1ZSBwYWlycy5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5wYWlycyh7ICdiYXJuZXknOiAzNiwgJ2ZyZWQnOiA0MCB9KTtcbiAqIC8vID0+IFtbJ2Jhcm5leScsIDM2XSwgWydmcmVkJywgNDBdXSAoaXRlcmF0aW9uIG9yZGVyIGlzIG5vdCBndWFyYW50ZWVkKVxuICovXG5mdW5jdGlvbiBwYWlycyhvYmplY3QpIHtcbiAgb2JqZWN0ID0gdG9PYmplY3Qob2JqZWN0KTtcblxuICB2YXIgaW5kZXggPSAtMSxcbiAgICAgIHByb3BzID0ga2V5cyhvYmplY3QpLFxuICAgICAgbGVuZ3RoID0gcHJvcHMubGVuZ3RoLFxuICAgICAgcmVzdWx0ID0gQXJyYXkobGVuZ3RoKTtcblxuICB3aGlsZSAoKytpbmRleCA8IGxlbmd0aCkge1xuICAgIHZhciBrZXkgPSBwcm9wc1tpbmRleF07XG4gICAgcmVzdWx0W2luZGV4XSA9IFtrZXksIG9iamVjdFtrZXldXTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHBhaXJzO1xuIiwidmFyIGJhc2VWYWx1ZXMgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9iYXNlVmFsdWVzJyksXG4gICAga2V5cyA9IHJlcXVpcmUoJy4va2V5cycpO1xuXG4vKipcbiAqIENyZWF0ZXMgYW4gYXJyYXkgb2YgdGhlIG93biBlbnVtZXJhYmxlIHByb3BlcnR5IHZhbHVlcyBvZiBgb2JqZWN0YC5cbiAqXG4gKiAqKk5vdGU6KiogTm9uLW9iamVjdCB2YWx1ZXMgYXJlIGNvZXJjZWQgdG8gb2JqZWN0cy5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQGNhdGVnb3J5IE9iamVjdFxuICogQHBhcmFtIHtPYmplY3R9IG9iamVjdCBUaGUgb2JqZWN0IHRvIHF1ZXJ5LlxuICogQHJldHVybnMge0FycmF5fSBSZXR1cm5zIHRoZSBhcnJheSBvZiBwcm9wZXJ0eSB2YWx1ZXMuXG4gKiBAZXhhbXBsZVxuICpcbiAqIGZ1bmN0aW9uIEZvbygpIHtcbiAqICAgdGhpcy5hID0gMTtcbiAqICAgdGhpcy5iID0gMjtcbiAqIH1cbiAqXG4gKiBGb28ucHJvdG90eXBlLmMgPSAzO1xuICpcbiAqIF8udmFsdWVzKG5ldyBGb28pO1xuICogLy8gPT4gWzEsIDJdIChpdGVyYXRpb24gb3JkZXIgaXMgbm90IGd1YXJhbnRlZWQpXG4gKlxuICogXy52YWx1ZXMoJ2hpJyk7XG4gKiAvLyA9PiBbJ2gnLCAnaSddXG4gKi9cbmZ1bmN0aW9uIHZhbHVlcyhvYmplY3QpIHtcbiAgcmV0dXJuIGJhc2VWYWx1ZXMob2JqZWN0LCBrZXlzKG9iamVjdCkpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHZhbHVlcztcbiIsIi8qKiBVc2VkIGZvciBuYXRpdmUgbWV0aG9kIHJlZmVyZW5jZXMuICovXG52YXIgYXJyYXlQcm90byA9IEFycmF5LnByb3RvdHlwZSxcbiAgICBlcnJvclByb3RvID0gRXJyb3IucHJvdG90eXBlLFxuICAgIG9iamVjdFByb3RvID0gT2JqZWN0LnByb3RvdHlwZTtcblxuLyoqIE5hdGl2ZSBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBwcm9wZXJ0eUlzRW51bWVyYWJsZSA9IG9iamVjdFByb3RvLnByb3BlcnR5SXNFbnVtZXJhYmxlLFxuICAgIHNwbGljZSA9IGFycmF5UHJvdG8uc3BsaWNlO1xuXG4vKipcbiAqIEFuIG9iamVjdCBlbnZpcm9ubWVudCBmZWF0dXJlIGZsYWdzLlxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAdHlwZSBPYmplY3RcbiAqL1xudmFyIHN1cHBvcnQgPSB7fTtcblxuKGZ1bmN0aW9uKHgpIHtcbiAgdmFyIEN0b3IgPSBmdW5jdGlvbigpIHsgdGhpcy54ID0geDsgfSxcbiAgICAgIG9iamVjdCA9IHsgJzAnOiB4LCAnbGVuZ3RoJzogeCB9LFxuICAgICAgcHJvcHMgPSBbXTtcblxuICBDdG9yLnByb3RvdHlwZSA9IHsgJ3ZhbHVlT2YnOiB4LCAneSc6IHggfTtcbiAgZm9yICh2YXIga2V5IGluIG5ldyBDdG9yKSB7IHByb3BzLnB1c2goa2V5KTsgfVxuXG4gIC8qKlxuICAgKiBEZXRlY3QgaWYgYG5hbWVgIG9yIGBtZXNzYWdlYCBwcm9wZXJ0aWVzIG9mIGBFcnJvci5wcm90b3R5cGVgIGFyZVxuICAgKiBlbnVtZXJhYmxlIGJ5IGRlZmF1bHQgKElFIDwgOSwgU2FmYXJpIDwgNS4xKS5cbiAgICpcbiAgICogQG1lbWJlck9mIF8uc3VwcG9ydFxuICAgKiBAdHlwZSBib29sZWFuXG4gICAqL1xuICBzdXBwb3J0LmVudW1FcnJvclByb3BzID0gcHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChlcnJvclByb3RvLCAnbWVzc2FnZScpIHx8XG4gICAgcHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChlcnJvclByb3RvLCAnbmFtZScpO1xuXG4gIC8qKlxuICAgKiBEZXRlY3QgaWYgYHByb3RvdHlwZWAgcHJvcGVydGllcyBhcmUgZW51bWVyYWJsZSBieSBkZWZhdWx0LlxuICAgKlxuICAgKiBGaXJlZm94IDwgMy42LCBPcGVyYSA+IDkuNTAgLSBPcGVyYSA8IDExLjYwLCBhbmQgU2FmYXJpIDwgNS4xXG4gICAqIChpZiB0aGUgcHJvdG90eXBlIG9yIGEgcHJvcGVydHkgb24gdGhlIHByb3RvdHlwZSBoYXMgYmVlbiBzZXQpXG4gICAqIGluY29ycmVjdGx5IHNldCB0aGUgYFtbRW51bWVyYWJsZV1dYCB2YWx1ZSBvZiBhIGZ1bmN0aW9uJ3MgYHByb3RvdHlwZWBcbiAgICogcHJvcGVydHkgdG8gYHRydWVgLlxuICAgKlxuICAgKiBAbWVtYmVyT2YgXy5zdXBwb3J0XG4gICAqIEB0eXBlIGJvb2xlYW5cbiAgICovXG4gIHN1cHBvcnQuZW51bVByb3RvdHlwZXMgPSBwcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKEN0b3IsICdwcm90b3R5cGUnKTtcblxuICAvKipcbiAgICogRGV0ZWN0IGlmIHByb3BlcnRpZXMgc2hhZG93aW5nIHRob3NlIG9uIGBPYmplY3QucHJvdG90eXBlYCBhcmUgbm9uLWVudW1lcmFibGUuXG4gICAqXG4gICAqIEluIElFIDwgOSBhbiBvYmplY3QncyBvd24gcHJvcGVydGllcywgc2hhZG93aW5nIG5vbi1lbnVtZXJhYmxlIG9uZXMsXG4gICAqIGFyZSBtYWRlIG5vbi1lbnVtZXJhYmxlIGFzIHdlbGwgKGEuay5hIHRoZSBKU2NyaXB0IGBbW0RvbnRFbnVtXV1gIGJ1ZykuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBfLnN1cHBvcnRcbiAgICogQHR5cGUgYm9vbGVhblxuICAgKi9cbiAgc3VwcG9ydC5ub25FbnVtU2hhZG93cyA9ICEvdmFsdWVPZi8udGVzdChwcm9wcyk7XG5cbiAgLyoqXG4gICAqIERldGVjdCBpZiBvd24gcHJvcGVydGllcyBhcmUgaXRlcmF0ZWQgYWZ0ZXIgaW5oZXJpdGVkIHByb3BlcnRpZXMgKElFIDwgOSkuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBfLnN1cHBvcnRcbiAgICogQHR5cGUgYm9vbGVhblxuICAgKi9cbiAgc3VwcG9ydC5vd25MYXN0ID0gcHJvcHNbMF0gIT0gJ3gnO1xuXG4gIC8qKlxuICAgKiBEZXRlY3QgaWYgYEFycmF5I3NoaWZ0YCBhbmQgYEFycmF5I3NwbGljZWAgYXVnbWVudCBhcnJheS1saWtlIG9iamVjdHNcbiAgICogY29ycmVjdGx5LlxuICAgKlxuICAgKiBGaXJlZm94IDwgMTAsIGNvbXBhdGliaWxpdHkgbW9kZXMgb2YgSUUgOCwgYW5kIElFIDwgOSBoYXZlIGJ1Z2d5IEFycmF5XG4gICAqIGBzaGlmdCgpYCBhbmQgYHNwbGljZSgpYCBmdW5jdGlvbnMgdGhhdCBmYWlsIHRvIHJlbW92ZSB0aGUgbGFzdCBlbGVtZW50LFxuICAgKiBgdmFsdWVbMF1gLCBvZiBhcnJheS1saWtlIG9iamVjdHMgZXZlbiB0aG91Z2ggdGhlIFwibGVuZ3RoXCIgcHJvcGVydHkgaXNcbiAgICogc2V0IHRvIGAwYC4gVGhlIGBzaGlmdCgpYCBtZXRob2QgaXMgYnVnZ3kgaW4gY29tcGF0aWJpbGl0eSBtb2RlcyBvZiBJRSA4LFxuICAgKiB3aGlsZSBgc3BsaWNlKClgIGlzIGJ1Z2d5IHJlZ2FyZGxlc3Mgb2YgbW9kZSBpbiBJRSA8IDkuXG4gICAqXG4gICAqIEBtZW1iZXJPZiBfLnN1cHBvcnRcbiAgICogQHR5cGUgYm9vbGVhblxuICAgKi9cbiAgc3VwcG9ydC5zcGxpY2VPYmplY3RzID0gKHNwbGljZS5jYWxsKG9iamVjdCwgMCwgMSksICFvYmplY3RbMF0pO1xuXG4gIC8qKlxuICAgKiBEZXRlY3QgbGFjayBvZiBzdXBwb3J0IGZvciBhY2Nlc3Npbmcgc3RyaW5nIGNoYXJhY3RlcnMgYnkgaW5kZXguXG4gICAqXG4gICAqIElFIDwgOCBjYW4ndCBhY2Nlc3MgY2hhcmFjdGVycyBieSBpbmRleC4gSUUgOCBjYW4gb25seSBhY2Nlc3MgY2hhcmFjdGVyc1xuICAgKiBieSBpbmRleCBvbiBzdHJpbmcgbGl0ZXJhbHMsIG5vdCBzdHJpbmcgb2JqZWN0cy5cbiAgICpcbiAgICogQG1lbWJlck9mIF8uc3VwcG9ydFxuICAgKiBAdHlwZSBib29sZWFuXG4gICAqL1xuICBzdXBwb3J0LnVuaW5kZXhlZENoYXJzID0gKCd4J1swXSArIE9iamVjdCgneCcpWzBdKSAhPSAneHgnO1xufSgxLCAwKSk7XG5cbm1vZHVsZS5leHBvcnRzID0gc3VwcG9ydDtcbiIsIi8qKlxuICogVGhpcyBtZXRob2QgcmV0dXJucyB0aGUgZmlyc3QgYXJndW1lbnQgcHJvdmlkZWQgdG8gaXQuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBjYXRlZ29yeSBVdGlsaXR5XG4gKiBAcGFyYW0geyp9IHZhbHVlIEFueSB2YWx1ZS5cbiAqIEByZXR1cm5zIHsqfSBSZXR1cm5zIGB2YWx1ZWAuXG4gKiBAZXhhbXBsZVxuICpcbiAqIHZhciBvYmplY3QgPSB7ICd1c2VyJzogJ2ZyZWQnIH07XG4gKlxuICogXy5pZGVudGl0eShvYmplY3QpID09PSBvYmplY3Q7XG4gKiAvLyA9PiB0cnVlXG4gKi9cbmZ1bmN0aW9uIGlkZW50aXR5KHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpZGVudGl0eTtcbiIsIi8qKlxuICogQSBuby1vcGVyYXRpb24gZnVuY3Rpb24gdGhhdCByZXR1cm5zIGB1bmRlZmluZWRgIHJlZ2FyZGxlc3Mgb2YgdGhlXG4gKiBhcmd1bWVudHMgaXQgcmVjZWl2ZXMuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBjYXRlZ29yeSBVdGlsaXR5XG4gKiBAZXhhbXBsZVxuICpcbiAqIHZhciBvYmplY3QgPSB7ICd1c2VyJzogJ2ZyZWQnIH07XG4gKlxuICogXy5ub29wKG9iamVjdCkgPT09IHVuZGVmaW5lZDtcbiAqIC8vID0+IHRydWVcbiAqL1xuZnVuY3Rpb24gbm9vcCgpIHtcbiAgLy8gTm8gb3BlcmF0aW9uIHBlcmZvcm1lZC5cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBub29wO1xuIiwidmFyIGJhc2VQcm9wZXJ0eSA9IHJlcXVpcmUoJy4uL2ludGVybmFsL2Jhc2VQcm9wZXJ0eScpLFxuICAgIGJhc2VQcm9wZXJ0eURlZXAgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9iYXNlUHJvcGVydHlEZWVwJyksXG4gICAgaXNLZXkgPSByZXF1aXJlKCcuLi9pbnRlcm5hbC9pc0tleScpO1xuXG4vKipcbiAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgdGhlIHByb3BlcnR5IHZhbHVlIGF0IGBwYXRoYCBvbiBhXG4gKiBnaXZlbiBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBjYXRlZ29yeSBVdGlsaXR5XG4gKiBAcGFyYW0ge0FycmF5fHN0cmluZ30gcGF0aCBUaGUgcGF0aCBvZiB0aGUgcHJvcGVydHkgdG8gZ2V0LlxuICogQHJldHVybnMge0Z1bmN0aW9ufSBSZXR1cm5zIHRoZSBuZXcgZnVuY3Rpb24uXG4gKiBAZXhhbXBsZVxuICpcbiAqIHZhciBvYmplY3RzID0gW1xuICogICB7ICdhJzogeyAnYic6IHsgJ2MnOiAyIH0gfSB9LFxuICogICB7ICdhJzogeyAnYic6IHsgJ2MnOiAxIH0gfSB9XG4gKiBdO1xuICpcbiAqIF8ubWFwKG9iamVjdHMsIF8ucHJvcGVydHkoJ2EuYi5jJykpO1xuICogLy8gPT4gWzIsIDFdXG4gKlxuICogXy5wbHVjayhfLnNvcnRCeShvYmplY3RzLCBfLnByb3BlcnR5KFsnYScsICdiJywgJ2MnXSkpLCAnYS5iLmMnKTtcbiAqIC8vID0+IFsxLCAyXVxuICovXG5mdW5jdGlvbiBwcm9wZXJ0eShwYXRoKSB7XG4gIHJldHVybiBpc0tleShwYXRoKSA/IGJhc2VQcm9wZXJ0eShwYXRoKSA6IGJhc2VQcm9wZXJ0eURlZXAocGF0aCk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gcHJvcGVydHk7XG4iLCIoZnVuY3Rpb24gKHByb2Nlc3Mpe1xuLy8gdmltOnRzPTQ6c3RzPTQ6c3c9NDpcbi8qIVxuICpcbiAqIENvcHlyaWdodCAyMDA5LTIwMTIgS3JpcyBLb3dhbCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIE1JVFxuICogbGljZW5zZSBmb3VuZCBhdCBodHRwOi8vZ2l0aHViLmNvbS9rcmlza293YWwvcS9yYXcvbWFzdGVyL0xJQ0VOU0VcbiAqXG4gKiBXaXRoIHBhcnRzIGJ5IFR5bGVyIENsb3NlXG4gKiBDb3B5cmlnaHQgMjAwNy0yMDA5IFR5bGVyIENsb3NlIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgTUlUIFggbGljZW5zZSBmb3VuZFxuICogYXQgaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZS5odG1sXG4gKiBGb3JrZWQgYXQgcmVmX3NlbmQuanMgdmVyc2lvbjogMjAwOS0wNS0xMVxuICpcbiAqIFdpdGggcGFydHMgYnkgTWFyayBNaWxsZXJcbiAqIENvcHlyaWdodCAoQykgMjAxMSBHb29nbGUgSW5jLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICpcbiAqL1xuXG4oZnVuY3Rpb24gKGRlZmluaXRpb24pIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIC8vIFRoaXMgZmlsZSB3aWxsIGZ1bmN0aW9uIHByb3Blcmx5IGFzIGEgPHNjcmlwdD4gdGFnLCBvciBhIG1vZHVsZVxuICAgIC8vIHVzaW5nIENvbW1vbkpTIGFuZCBOb2RlSlMgb3IgUmVxdWlyZUpTIG1vZHVsZSBmb3JtYXRzLiAgSW5cbiAgICAvLyBDb21tb24vTm9kZS9SZXF1aXJlSlMsIHRoZSBtb2R1bGUgZXhwb3J0cyB0aGUgUSBBUEkgYW5kIHdoZW5cbiAgICAvLyBleGVjdXRlZCBhcyBhIHNpbXBsZSA8c2NyaXB0PiwgaXQgY3JlYXRlcyBhIFEgZ2xvYmFsIGluc3RlYWQuXG5cbiAgICAvLyBNb250YWdlIFJlcXVpcmVcbiAgICBpZiAodHlwZW9mIGJvb3RzdHJhcCA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgIGJvb3RzdHJhcChcInByb21pc2VcIiwgZGVmaW5pdGlvbik7XG5cbiAgICAvLyBDb21tb25KU1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGV4cG9ydHMgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICBtb2R1bGUuZXhwb3J0cyA9IGRlZmluaXRpb24oKTtcblxuICAgIC8vIFJlcXVpcmVKU1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcbiAgICAgICAgZGVmaW5lKGRlZmluaXRpb24pO1xuXG4gICAgLy8gU0VTIChTZWN1cmUgRWNtYVNjcmlwdClcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBzZXMgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgaWYgKCFzZXMub2soKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VzLm1ha2VRID0gZGVmaW5pdGlvbjtcbiAgICAgICAgfVxuXG4gICAgLy8gPHNjcmlwdD5cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgfHwgdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgLy8gUHJlZmVyIHdpbmRvdyBvdmVyIHNlbGYgZm9yIGFkZC1vbiBzY3JpcHRzLiBVc2Ugc2VsZiBmb3JcbiAgICAgICAgLy8gbm9uLXdpbmRvd2VkIGNvbnRleHRzLlxuICAgICAgICB2YXIgZ2xvYmFsID0gdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHNlbGY7XG5cbiAgICAgICAgLy8gR2V0IHRoZSBgd2luZG93YCBvYmplY3QsIHNhdmUgdGhlIHByZXZpb3VzIFEgZ2xvYmFsXG4gICAgICAgIC8vIGFuZCBpbml0aWFsaXplIFEgYXMgYSBnbG9iYWwuXG4gICAgICAgIHZhciBwcmV2aW91c1EgPSBnbG9iYWwuUTtcbiAgICAgICAgZ2xvYmFsLlEgPSBkZWZpbml0aW9uKCk7XG5cbiAgICAgICAgLy8gQWRkIGEgbm9Db25mbGljdCBmdW5jdGlvbiBzbyBRIGNhbiBiZSByZW1vdmVkIGZyb20gdGhlXG4gICAgICAgIC8vIGdsb2JhbCBuYW1lc3BhY2UuXG4gICAgICAgIGdsb2JhbC5RLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBnbG9iYWwuUSA9IHByZXZpb3VzUTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9O1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhpcyBlbnZpcm9ubWVudCB3YXMgbm90IGFudGljaXBhdGVkIGJ5IFEuIFBsZWFzZSBmaWxlIGEgYnVnLlwiKTtcbiAgICB9XG5cbn0pKGZ1bmN0aW9uICgpIHtcblwidXNlIHN0cmljdFwiO1xuXG52YXIgaGFzU3RhY2tzID0gZmFsc2U7XG50cnkge1xuICAgIHRocm93IG5ldyBFcnJvcigpO1xufSBjYXRjaCAoZSkge1xuICAgIGhhc1N0YWNrcyA9ICEhZS5zdGFjaztcbn1cblxuLy8gQWxsIGNvZGUgYWZ0ZXIgdGhpcyBwb2ludCB3aWxsIGJlIGZpbHRlcmVkIGZyb20gc3RhY2sgdHJhY2VzIHJlcG9ydGVkXG4vLyBieSBRLlxudmFyIHFTdGFydGluZ0xpbmUgPSBjYXB0dXJlTGluZSgpO1xudmFyIHFGaWxlTmFtZTtcblxuLy8gc2hpbXNcblxuLy8gdXNlZCBmb3IgZmFsbGJhY2sgaW4gXCJhbGxSZXNvbHZlZFwiXG52YXIgbm9vcCA9IGZ1bmN0aW9uICgpIHt9O1xuXG4vLyBVc2UgdGhlIGZhc3Rlc3QgcG9zc2libGUgbWVhbnMgdG8gZXhlY3V0ZSBhIHRhc2sgaW4gYSBmdXR1cmUgdHVyblxuLy8gb2YgdGhlIGV2ZW50IGxvb3AuXG52YXIgbmV4dFRpY2sgPShmdW5jdGlvbiAoKSB7XG4gICAgLy8gbGlua2VkIGxpc3Qgb2YgdGFza3MgKHNpbmdsZSwgd2l0aCBoZWFkIG5vZGUpXG4gICAgdmFyIGhlYWQgPSB7dGFzazogdm9pZCAwLCBuZXh0OiBudWxsfTtcbiAgICB2YXIgdGFpbCA9IGhlYWQ7XG4gICAgdmFyIGZsdXNoaW5nID0gZmFsc2U7XG4gICAgdmFyIHJlcXVlc3RUaWNrID0gdm9pZCAwO1xuICAgIHZhciBpc05vZGVKUyA9IGZhbHNlO1xuICAgIC8vIHF1ZXVlIGZvciBsYXRlIHRhc2tzLCB1c2VkIGJ5IHVuaGFuZGxlZCByZWplY3Rpb24gdHJhY2tpbmdcbiAgICB2YXIgbGF0ZXJRdWV1ZSA9IFtdO1xuXG4gICAgZnVuY3Rpb24gZmx1c2goKSB7XG4gICAgICAgIC8qIGpzaGludCBsb29wZnVuYzogdHJ1ZSAqL1xuICAgICAgICB2YXIgdGFzaywgZG9tYWluO1xuXG4gICAgICAgIHdoaWxlIChoZWFkLm5leHQpIHtcbiAgICAgICAgICAgIGhlYWQgPSBoZWFkLm5leHQ7XG4gICAgICAgICAgICB0YXNrID0gaGVhZC50YXNrO1xuICAgICAgICAgICAgaGVhZC50YXNrID0gdm9pZCAwO1xuICAgICAgICAgICAgZG9tYWluID0gaGVhZC5kb21haW47XG5cbiAgICAgICAgICAgIGlmIChkb21haW4pIHtcbiAgICAgICAgICAgICAgICBoZWFkLmRvbWFpbiA9IHZvaWQgMDtcbiAgICAgICAgICAgICAgICBkb21haW4uZW50ZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJ1blNpbmdsZSh0YXNrLCBkb21haW4pO1xuXG4gICAgICAgIH1cbiAgICAgICAgd2hpbGUgKGxhdGVyUXVldWUubGVuZ3RoKSB7XG4gICAgICAgICAgICB0YXNrID0gbGF0ZXJRdWV1ZS5wb3AoKTtcbiAgICAgICAgICAgIHJ1blNpbmdsZSh0YXNrKTtcbiAgICAgICAgfVxuICAgICAgICBmbHVzaGluZyA9IGZhbHNlO1xuICAgIH1cbiAgICAvLyBydW5zIGEgc2luZ2xlIGZ1bmN0aW9uIGluIHRoZSBhc3luYyBxdWV1ZVxuICAgIGZ1bmN0aW9uIHJ1blNpbmdsZSh0YXNrLCBkb21haW4pIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRhc2soKTtcblxuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICBpZiAoaXNOb2RlSlMpIHtcbiAgICAgICAgICAgICAgICAvLyBJbiBub2RlLCB1bmNhdWdodCBleGNlcHRpb25zIGFyZSBjb25zaWRlcmVkIGZhdGFsIGVycm9ycy5cbiAgICAgICAgICAgICAgICAvLyBSZS10aHJvdyB0aGVtIHN5bmNocm9ub3VzbHkgdG8gaW50ZXJydXB0IGZsdXNoaW5nIVxuXG4gICAgICAgICAgICAgICAgLy8gRW5zdXJlIGNvbnRpbnVhdGlvbiBpZiB0aGUgdW5jYXVnaHQgZXhjZXB0aW9uIGlzIHN1cHByZXNzZWRcbiAgICAgICAgICAgICAgICAvLyBsaXN0ZW5pbmcgXCJ1bmNhdWdodEV4Y2VwdGlvblwiIGV2ZW50cyAoYXMgZG9tYWlucyBkb2VzKS5cbiAgICAgICAgICAgICAgICAvLyBDb250aW51ZSBpbiBuZXh0IGV2ZW50IHRvIGF2b2lkIHRpY2sgcmVjdXJzaW9uLlxuICAgICAgICAgICAgICAgIGlmIChkb21haW4pIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tYWluLmV4aXQoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc2V0VGltZW91dChmbHVzaCwgMCk7XG4gICAgICAgICAgICAgICAgaWYgKGRvbWFpbikge1xuICAgICAgICAgICAgICAgICAgICBkb21haW4uZW50ZXIoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aHJvdyBlO1xuXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIEluIGJyb3dzZXJzLCB1bmNhdWdodCBleGNlcHRpb25zIGFyZSBub3QgZmF0YWwuXG4gICAgICAgICAgICAgICAgLy8gUmUtdGhyb3cgdGhlbSBhc3luY2hyb25vdXNseSB0byBhdm9pZCBzbG93LWRvd25zLlxuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICAgICAgICAgIH0sIDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRvbWFpbikge1xuICAgICAgICAgICAgZG9tYWluLmV4aXQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG5leHRUaWNrID0gZnVuY3Rpb24gKHRhc2spIHtcbiAgICAgICAgdGFpbCA9IHRhaWwubmV4dCA9IHtcbiAgICAgICAgICAgIHRhc2s6IHRhc2ssXG4gICAgICAgICAgICBkb21haW46IGlzTm9kZUpTICYmIHByb2Nlc3MuZG9tYWluLFxuICAgICAgICAgICAgbmV4dDogbnVsbFxuICAgICAgICB9O1xuXG4gICAgICAgIGlmICghZmx1c2hpbmcpIHtcbiAgICAgICAgICAgIGZsdXNoaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIHJlcXVlc3RUaWNrKCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgaWYgKHR5cGVvZiBwcm9jZXNzID09PSBcIm9iamVjdFwiICYmXG4gICAgICAgIHByb2Nlc3MudG9TdHJpbmcoKSA9PT0gXCJbb2JqZWN0IHByb2Nlc3NdXCIgJiYgcHJvY2Vzcy5uZXh0VGljaykge1xuICAgICAgICAvLyBFbnN1cmUgUSBpcyBpbiBhIHJlYWwgTm9kZSBlbnZpcm9ubWVudCwgd2l0aCBhIGBwcm9jZXNzLm5leHRUaWNrYC5cbiAgICAgICAgLy8gVG8gc2VlIHRocm91Z2ggZmFrZSBOb2RlIGVudmlyb25tZW50czpcbiAgICAgICAgLy8gKiBNb2NoYSB0ZXN0IHJ1bm5lciAtIGV4cG9zZXMgYSBgcHJvY2Vzc2AgZ2xvYmFsIHdpdGhvdXQgYSBgbmV4dFRpY2tgXG4gICAgICAgIC8vICogQnJvd3NlcmlmeSAtIGV4cG9zZXMgYSBgcHJvY2Vzcy5uZXhUaWNrYCBmdW5jdGlvbiB0aGF0IHVzZXNcbiAgICAgICAgLy8gICBgc2V0VGltZW91dGAuIEluIHRoaXMgY2FzZSBgc2V0SW1tZWRpYXRlYCBpcyBwcmVmZXJyZWQgYmVjYXVzZVxuICAgICAgICAvLyAgICBpdCBpcyBmYXN0ZXIuIEJyb3dzZXJpZnkncyBgcHJvY2Vzcy50b1N0cmluZygpYCB5aWVsZHNcbiAgICAgICAgLy8gICBcIltvYmplY3QgT2JqZWN0XVwiLCB3aGlsZSBpbiBhIHJlYWwgTm9kZSBlbnZpcm9ubWVudFxuICAgICAgICAvLyAgIGBwcm9jZXNzLm5leHRUaWNrKClgIHlpZWxkcyBcIltvYmplY3QgcHJvY2Vzc11cIi5cbiAgICAgICAgaXNOb2RlSlMgPSB0cnVlO1xuXG4gICAgICAgIHJlcXVlc3RUaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcHJvY2Vzcy5uZXh0VGljayhmbHVzaCk7XG4gICAgICAgIH07XG5cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBzZXRJbW1lZGlhdGUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAvLyBJbiBJRTEwLCBOb2RlLmpzIDAuOSssIG9yIGh0dHBzOi8vZ2l0aHViLmNvbS9Ob2JsZUpTL3NldEltbWVkaWF0ZVxuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgcmVxdWVzdFRpY2sgPSBzZXRJbW1lZGlhdGUuYmluZCh3aW5kb3csIGZsdXNoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlcXVlc3RUaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHNldEltbWVkaWF0ZShmbHVzaCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBNZXNzYWdlQ2hhbm5lbCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAvLyBtb2Rlcm4gYnJvd3NlcnNcbiAgICAgICAgLy8gaHR0cDovL3d3dy5ub25ibG9ja2luZy5pby8yMDExLzA2L3dpbmRvd25leHR0aWNrLmh0bWxcbiAgICAgICAgdmFyIGNoYW5uZWwgPSBuZXcgTWVzc2FnZUNoYW5uZWwoKTtcbiAgICAgICAgLy8gQXQgbGVhc3QgU2FmYXJpIFZlcnNpb24gNi4wLjUgKDg1MzYuMzAuMSkgaW50ZXJtaXR0ZW50bHkgY2Fubm90IGNyZWF0ZVxuICAgICAgICAvLyB3b3JraW5nIG1lc3NhZ2UgcG9ydHMgdGhlIGZpcnN0IHRpbWUgYSBwYWdlIGxvYWRzLlxuICAgICAgICBjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJlcXVlc3RUaWNrID0gcmVxdWVzdFBvcnRUaWNrO1xuICAgICAgICAgICAgY2hhbm5lbC5wb3J0MS5vbm1lc3NhZ2UgPSBmbHVzaDtcbiAgICAgICAgICAgIGZsdXNoKCk7XG4gICAgICAgIH07XG4gICAgICAgIHZhciByZXF1ZXN0UG9ydFRpY2sgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyBPcGVyYSByZXF1aXJlcyB1cyB0byBwcm92aWRlIGEgbWVzc2FnZSBwYXlsb2FkLCByZWdhcmRsZXNzIG9mXG4gICAgICAgICAgICAvLyB3aGV0aGVyIHdlIHVzZSBpdC5cbiAgICAgICAgICAgIGNoYW5uZWwucG9ydDIucG9zdE1lc3NhZ2UoMCk7XG4gICAgICAgIH07XG4gICAgICAgIHJlcXVlc3RUaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc2V0VGltZW91dChmbHVzaCwgMCk7XG4gICAgICAgICAgICByZXF1ZXN0UG9ydFRpY2soKTtcbiAgICAgICAgfTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIG9sZCBicm93c2Vyc1xuICAgICAgICByZXF1ZXN0VGljayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoZmx1c2gsIDApO1xuICAgICAgICB9O1xuICAgIH1cbiAgICAvLyBydW5zIGEgdGFzayBhZnRlciBhbGwgb3RoZXIgdGFza3MgaGF2ZSBiZWVuIHJ1blxuICAgIC8vIHRoaXMgaXMgdXNlZnVsIGZvciB1bmhhbmRsZWQgcmVqZWN0aW9uIHRyYWNraW5nIHRoYXQgbmVlZHMgdG8gaGFwcGVuXG4gICAgLy8gYWZ0ZXIgYWxsIGB0aGVuYGQgdGFza3MgaGF2ZSBiZWVuIHJ1bi5cbiAgICBuZXh0VGljay5ydW5BZnRlciA9IGZ1bmN0aW9uICh0YXNrKSB7XG4gICAgICAgIGxhdGVyUXVldWUucHVzaCh0YXNrKTtcbiAgICAgICAgaWYgKCFmbHVzaGluZykge1xuICAgICAgICAgICAgZmx1c2hpbmcgPSB0cnVlO1xuICAgICAgICAgICAgcmVxdWVzdFRpY2soKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIG5leHRUaWNrO1xufSkoKTtcblxuLy8gQXR0ZW1wdCB0byBtYWtlIGdlbmVyaWNzIHNhZmUgaW4gdGhlIGZhY2Ugb2YgZG93bnN0cmVhbVxuLy8gbW9kaWZpY2F0aW9ucy5cbi8vIFRoZXJlIGlzIG5vIHNpdHVhdGlvbiB3aGVyZSB0aGlzIGlzIG5lY2Vzc2FyeS5cbi8vIElmIHlvdSBuZWVkIGEgc2VjdXJpdHkgZ3VhcmFudGVlLCB0aGVzZSBwcmltb3JkaWFscyBuZWVkIHRvIGJlXG4vLyBkZWVwbHkgZnJvemVuIGFueXdheSwgYW5kIGlmIHlvdSBkb27igJl0IG5lZWQgYSBzZWN1cml0eSBndWFyYW50ZWUsXG4vLyB0aGlzIGlzIGp1c3QgcGxhaW4gcGFyYW5vaWQuXG4vLyBIb3dldmVyLCB0aGlzICoqbWlnaHQqKiBoYXZlIHRoZSBuaWNlIHNpZGUtZWZmZWN0IG9mIHJlZHVjaW5nIHRoZSBzaXplIG9mXG4vLyB0aGUgbWluaWZpZWQgY29kZSBieSByZWR1Y2luZyB4LmNhbGwoKSB0byBtZXJlbHkgeCgpXG4vLyBTZWUgTWFyayBNaWxsZXLigJlzIGV4cGxhbmF0aW9uIG9mIHdoYXQgdGhpcyBkb2VzLlxuLy8gaHR0cDovL3dpa2kuZWNtYXNjcmlwdC5vcmcvZG9rdS5waHA/aWQ9Y29udmVudGlvbnM6c2FmZV9tZXRhX3Byb2dyYW1taW5nXG52YXIgY2FsbCA9IEZ1bmN0aW9uLmNhbGw7XG5mdW5jdGlvbiB1bmN1cnJ5VGhpcyhmKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIGNhbGwuYXBwbHkoZiwgYXJndW1lbnRzKTtcbiAgICB9O1xufVxuLy8gVGhpcyBpcyBlcXVpdmFsZW50LCBidXQgc2xvd2VyOlxuLy8gdW5jdXJyeVRoaXMgPSBGdW5jdGlvbl9iaW5kLmJpbmQoRnVuY3Rpb25fYmluZC5jYWxsKTtcbi8vIGh0dHA6Ly9qc3BlcmYuY29tL3VuY3Vycnl0aGlzXG5cbnZhciBhcnJheV9zbGljZSA9IHVuY3VycnlUaGlzKEFycmF5LnByb3RvdHlwZS5zbGljZSk7XG5cbnZhciBhcnJheV9yZWR1Y2UgPSB1bmN1cnJ5VGhpcyhcbiAgICBBcnJheS5wcm90b3R5cGUucmVkdWNlIHx8IGZ1bmN0aW9uIChjYWxsYmFjaywgYmFzaXMpIHtcbiAgICAgICAgdmFyIGluZGV4ID0gMCxcbiAgICAgICAgICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoO1xuICAgICAgICAvLyBjb25jZXJuaW5nIHRoZSBpbml0aWFsIHZhbHVlLCBpZiBvbmUgaXMgbm90IHByb3ZpZGVkXG4gICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAvLyBzZWVrIHRvIHRoZSBmaXJzdCB2YWx1ZSBpbiB0aGUgYXJyYXksIGFjY291bnRpbmdcbiAgICAgICAgICAgIC8vIGZvciB0aGUgcG9zc2liaWxpdHkgdGhhdCBpcyBpcyBhIHNwYXJzZSBhcnJheVxuICAgICAgICAgICAgZG8ge1xuICAgICAgICAgICAgICAgIGlmIChpbmRleCBpbiB0aGlzKSB7XG4gICAgICAgICAgICAgICAgICAgIGJhc2lzID0gdGhpc1tpbmRleCsrXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmICgrK2luZGV4ID49IGxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSB3aGlsZSAoMSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVkdWNlXG4gICAgICAgIGZvciAoOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgICAgICAgICAgLy8gYWNjb3VudCBmb3IgdGhlIHBvc3NpYmlsaXR5IHRoYXQgdGhlIGFycmF5IGlzIHNwYXJzZVxuICAgICAgICAgICAgaWYgKGluZGV4IGluIHRoaXMpIHtcbiAgICAgICAgICAgICAgICBiYXNpcyA9IGNhbGxiYWNrKGJhc2lzLCB0aGlzW2luZGV4XSwgaW5kZXgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBiYXNpcztcbiAgICB9XG4pO1xuXG52YXIgYXJyYXlfaW5kZXhPZiA9IHVuY3VycnlUaGlzKFxuICAgIEFycmF5LnByb3RvdHlwZS5pbmRleE9mIHx8IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAvLyBub3QgYSB2ZXJ5IGdvb2Qgc2hpbSwgYnV0IGdvb2QgZW5vdWdoIGZvciBvdXIgb25lIHVzZSBvZiBpdFxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0aGlzW2ldID09PSB2YWx1ZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAtMTtcbiAgICB9XG4pO1xuXG52YXIgYXJyYXlfbWFwID0gdW5jdXJyeVRoaXMoXG4gICAgQXJyYXkucHJvdG90eXBlLm1hcCB8fCBmdW5jdGlvbiAoY2FsbGJhY2ssIHRoaXNwKSB7XG4gICAgICAgIHZhciBzZWxmID0gdGhpcztcbiAgICAgICAgdmFyIGNvbGxlY3QgPSBbXTtcbiAgICAgICAgYXJyYXlfcmVkdWNlKHNlbGYsIGZ1bmN0aW9uICh1bmRlZmluZWQsIHZhbHVlLCBpbmRleCkge1xuICAgICAgICAgICAgY29sbGVjdC5wdXNoKGNhbGxiYWNrLmNhbGwodGhpc3AsIHZhbHVlLCBpbmRleCwgc2VsZikpO1xuICAgICAgICB9LCB2b2lkIDApO1xuICAgICAgICByZXR1cm4gY29sbGVjdDtcbiAgICB9XG4pO1xuXG52YXIgb2JqZWN0X2NyZWF0ZSA9IE9iamVjdC5jcmVhdGUgfHwgZnVuY3Rpb24gKHByb3RvdHlwZSkge1xuICAgIGZ1bmN0aW9uIFR5cGUoKSB7IH1cbiAgICBUeXBlLnByb3RvdHlwZSA9IHByb3RvdHlwZTtcbiAgICByZXR1cm4gbmV3IFR5cGUoKTtcbn07XG5cbnZhciBvYmplY3RfaGFzT3duUHJvcGVydHkgPSB1bmN1cnJ5VGhpcyhPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5KTtcblxudmFyIG9iamVjdF9rZXlzID0gT2JqZWN0LmtleXMgfHwgZnVuY3Rpb24gKG9iamVjdCkge1xuICAgIHZhciBrZXlzID0gW107XG4gICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgICBpZiAob2JqZWN0X2hhc093blByb3BlcnR5KG9iamVjdCwga2V5KSkge1xuICAgICAgICAgICAga2V5cy5wdXNoKGtleSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGtleXM7XG59O1xuXG52YXIgb2JqZWN0X3RvU3RyaW5nID0gdW5jdXJyeVRoaXMoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZyk7XG5cbmZ1bmN0aW9uIGlzT2JqZWN0KHZhbHVlKSB7XG4gICAgcmV0dXJuIHZhbHVlID09PSBPYmplY3QodmFsdWUpO1xufVxuXG4vLyBnZW5lcmF0b3IgcmVsYXRlZCBzaGltc1xuXG4vLyBGSVhNRTogUmVtb3ZlIHRoaXMgZnVuY3Rpb24gb25jZSBFUzYgZ2VuZXJhdG9ycyBhcmUgaW4gU3BpZGVyTW9ua2V5LlxuZnVuY3Rpb24gaXNTdG9wSXRlcmF0aW9uKGV4Y2VwdGlvbikge1xuICAgIHJldHVybiAoXG4gICAgICAgIG9iamVjdF90b1N0cmluZyhleGNlcHRpb24pID09PSBcIltvYmplY3QgU3RvcEl0ZXJhdGlvbl1cIiB8fFxuICAgICAgICBleGNlcHRpb24gaW5zdGFuY2VvZiBRUmV0dXJuVmFsdWVcbiAgICApO1xufVxuXG4vLyBGSVhNRTogUmVtb3ZlIHRoaXMgaGVscGVyIGFuZCBRLnJldHVybiBvbmNlIEVTNiBnZW5lcmF0b3JzIGFyZSBpblxuLy8gU3BpZGVyTW9ua2V5LlxudmFyIFFSZXR1cm5WYWx1ZTtcbmlmICh0eXBlb2YgUmV0dXJuVmFsdWUgIT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICBRUmV0dXJuVmFsdWUgPSBSZXR1cm5WYWx1ZTtcbn0gZWxzZSB7XG4gICAgUVJldHVyblZhbHVlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB9O1xufVxuXG4vLyBsb25nIHN0YWNrIHRyYWNlc1xuXG52YXIgU1RBQ0tfSlVNUF9TRVBBUkFUT1IgPSBcIkZyb20gcHJldmlvdXMgZXZlbnQ6XCI7XG5cbmZ1bmN0aW9uIG1ha2VTdGFja1RyYWNlTG9uZyhlcnJvciwgcHJvbWlzZSkge1xuICAgIC8vIElmIHBvc3NpYmxlLCB0cmFuc2Zvcm0gdGhlIGVycm9yIHN0YWNrIHRyYWNlIGJ5IHJlbW92aW5nIE5vZGUgYW5kIFFcbiAgICAvLyBjcnVmdCwgdGhlbiBjb25jYXRlbmF0aW5nIHdpdGggdGhlIHN0YWNrIHRyYWNlIG9mIGBwcm9taXNlYC4gU2VlICM1Ny5cbiAgICBpZiAoaGFzU3RhY2tzICYmXG4gICAgICAgIHByb21pc2Uuc3RhY2sgJiZcbiAgICAgICAgdHlwZW9mIGVycm9yID09PSBcIm9iamVjdFwiICYmXG4gICAgICAgIGVycm9yICE9PSBudWxsICYmXG4gICAgICAgIGVycm9yLnN0YWNrICYmXG4gICAgICAgIGVycm9yLnN0YWNrLmluZGV4T2YoU1RBQ0tfSlVNUF9TRVBBUkFUT1IpID09PSAtMVxuICAgICkge1xuICAgICAgICB2YXIgc3RhY2tzID0gW107XG4gICAgICAgIGZvciAodmFyIHAgPSBwcm9taXNlOyAhIXA7IHAgPSBwLnNvdXJjZSkge1xuICAgICAgICAgICAgaWYgKHAuc3RhY2spIHtcbiAgICAgICAgICAgICAgICBzdGFja3MudW5zaGlmdChwLnN0YWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdGFja3MudW5zaGlmdChlcnJvci5zdGFjayk7XG5cbiAgICAgICAgdmFyIGNvbmNhdGVkU3RhY2tzID0gc3RhY2tzLmpvaW4oXCJcXG5cIiArIFNUQUNLX0pVTVBfU0VQQVJBVE9SICsgXCJcXG5cIik7XG4gICAgICAgIGVycm9yLnN0YWNrID0gZmlsdGVyU3RhY2tTdHJpbmcoY29uY2F0ZWRTdGFja3MpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZmlsdGVyU3RhY2tTdHJpbmcoc3RhY2tTdHJpbmcpIHtcbiAgICB2YXIgbGluZXMgPSBzdGFja1N0cmluZy5zcGxpdChcIlxcblwiKTtcbiAgICB2YXIgZGVzaXJlZExpbmVzID0gW107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsaW5lcy5sZW5ndGg7ICsraSkge1xuICAgICAgICB2YXIgbGluZSA9IGxpbmVzW2ldO1xuXG4gICAgICAgIGlmICghaXNJbnRlcm5hbEZyYW1lKGxpbmUpICYmICFpc05vZGVGcmFtZShsaW5lKSAmJiBsaW5lKSB7XG4gICAgICAgICAgICBkZXNpcmVkTGluZXMucHVzaChsaW5lKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZGVzaXJlZExpbmVzLmpvaW4oXCJcXG5cIik7XG59XG5cbmZ1bmN0aW9uIGlzTm9kZUZyYW1lKHN0YWNrTGluZSkge1xuICAgIHJldHVybiBzdGFja0xpbmUuaW5kZXhPZihcIihtb2R1bGUuanM6XCIpICE9PSAtMSB8fFxuICAgICAgICAgICBzdGFja0xpbmUuaW5kZXhPZihcIihub2RlLmpzOlwiKSAhPT0gLTE7XG59XG5cbmZ1bmN0aW9uIGdldEZpbGVOYW1lQW5kTGluZU51bWJlcihzdGFja0xpbmUpIHtcbiAgICAvLyBOYW1lZCBmdW5jdGlvbnM6IFwiYXQgZnVuY3Rpb25OYW1lIChmaWxlbmFtZTpsaW5lTnVtYmVyOmNvbHVtbk51bWJlcilcIlxuICAgIC8vIEluIElFMTAgZnVuY3Rpb24gbmFtZSBjYW4gaGF2ZSBzcGFjZXMgKFwiQW5vbnltb3VzIGZ1bmN0aW9uXCIpIE9fb1xuICAgIHZhciBhdHRlbXB0MSA9IC9hdCAuKyBcXCgoLispOihcXGQrKTooPzpcXGQrKVxcKSQvLmV4ZWMoc3RhY2tMaW5lKTtcbiAgICBpZiAoYXR0ZW1wdDEpIHtcbiAgICAgICAgcmV0dXJuIFthdHRlbXB0MVsxXSwgTnVtYmVyKGF0dGVtcHQxWzJdKV07XG4gICAgfVxuXG4gICAgLy8gQW5vbnltb3VzIGZ1bmN0aW9uczogXCJhdCBmaWxlbmFtZTpsaW5lTnVtYmVyOmNvbHVtbk51bWJlclwiXG4gICAgdmFyIGF0dGVtcHQyID0gL2F0IChbXiBdKyk6KFxcZCspOig/OlxcZCspJC8uZXhlYyhzdGFja0xpbmUpO1xuICAgIGlmIChhdHRlbXB0Mikge1xuICAgICAgICByZXR1cm4gW2F0dGVtcHQyWzFdLCBOdW1iZXIoYXR0ZW1wdDJbMl0pXTtcbiAgICB9XG5cbiAgICAvLyBGaXJlZm94IHN0eWxlOiBcImZ1bmN0aW9uQGZpbGVuYW1lOmxpbmVOdW1iZXIgb3IgQGZpbGVuYW1lOmxpbmVOdW1iZXJcIlxuICAgIHZhciBhdHRlbXB0MyA9IC8uKkAoLispOihcXGQrKSQvLmV4ZWMoc3RhY2tMaW5lKTtcbiAgICBpZiAoYXR0ZW1wdDMpIHtcbiAgICAgICAgcmV0dXJuIFthdHRlbXB0M1sxXSwgTnVtYmVyKGF0dGVtcHQzWzJdKV07XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpc0ludGVybmFsRnJhbWUoc3RhY2tMaW5lKSB7XG4gICAgdmFyIGZpbGVOYW1lQW5kTGluZU51bWJlciA9IGdldEZpbGVOYW1lQW5kTGluZU51bWJlcihzdGFja0xpbmUpO1xuXG4gICAgaWYgKCFmaWxlTmFtZUFuZExpbmVOdW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHZhciBmaWxlTmFtZSA9IGZpbGVOYW1lQW5kTGluZU51bWJlclswXTtcbiAgICB2YXIgbGluZU51bWJlciA9IGZpbGVOYW1lQW5kTGluZU51bWJlclsxXTtcblxuICAgIHJldHVybiBmaWxlTmFtZSA9PT0gcUZpbGVOYW1lICYmXG4gICAgICAgIGxpbmVOdW1iZXIgPj0gcVN0YXJ0aW5nTGluZSAmJlxuICAgICAgICBsaW5lTnVtYmVyIDw9IHFFbmRpbmdMaW5lO1xufVxuXG4vLyBkaXNjb3ZlciBvd24gZmlsZSBuYW1lIGFuZCBsaW5lIG51bWJlciByYW5nZSBmb3IgZmlsdGVyaW5nIHN0YWNrXG4vLyB0cmFjZXNcbmZ1bmN0aW9uIGNhcHR1cmVMaW5lKCkge1xuICAgIGlmICghaGFzU3RhY2tzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHZhciBsaW5lcyA9IGUuc3RhY2suc3BsaXQoXCJcXG5cIik7XG4gICAgICAgIHZhciBmaXJzdExpbmUgPSBsaW5lc1swXS5pbmRleE9mKFwiQFwiKSA+IDAgPyBsaW5lc1sxXSA6IGxpbmVzWzJdO1xuICAgICAgICB2YXIgZmlsZU5hbWVBbmRMaW5lTnVtYmVyID0gZ2V0RmlsZU5hbWVBbmRMaW5lTnVtYmVyKGZpcnN0TGluZSk7XG4gICAgICAgIGlmICghZmlsZU5hbWVBbmRMaW5lTnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBxRmlsZU5hbWUgPSBmaWxlTmFtZUFuZExpbmVOdW1iZXJbMF07XG4gICAgICAgIHJldHVybiBmaWxlTmFtZUFuZExpbmVOdW1iZXJbMV07XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkZXByZWNhdGUoY2FsbGJhY2ssIG5hbWUsIGFsdGVybmF0aXZlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBjb25zb2xlICE9PSBcInVuZGVmaW5lZFwiICYmXG4gICAgICAgICAgICB0eXBlb2YgY29uc29sZS53YXJuID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIGNvbnNvbGUud2FybihuYW1lICsgXCIgaXMgZGVwcmVjYXRlZCwgdXNlIFwiICsgYWx0ZXJuYXRpdmUgK1xuICAgICAgICAgICAgICAgICAgICAgICAgIFwiIGluc3RlYWQuXCIsIG5ldyBFcnJvcihcIlwiKS5zdGFjayk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrLmFwcGx5KGNhbGxiYWNrLCBhcmd1bWVudHMpO1xuICAgIH07XG59XG5cbi8vIGVuZCBvZiBzaGltc1xuLy8gYmVnaW5uaW5nIG9mIHJlYWwgd29ya1xuXG4vKipcbiAqIENvbnN0cnVjdHMgYSBwcm9taXNlIGZvciBhbiBpbW1lZGlhdGUgcmVmZXJlbmNlLCBwYXNzZXMgcHJvbWlzZXMgdGhyb3VnaCwgb3JcbiAqIGNvZXJjZXMgcHJvbWlzZXMgZnJvbSBkaWZmZXJlbnQgc3lzdGVtcy5cbiAqIEBwYXJhbSB2YWx1ZSBpbW1lZGlhdGUgcmVmZXJlbmNlIG9yIHByb21pc2VcbiAqL1xuZnVuY3Rpb24gUSh2YWx1ZSkge1xuICAgIC8vIElmIHRoZSBvYmplY3QgaXMgYWxyZWFkeSBhIFByb21pc2UsIHJldHVybiBpdCBkaXJlY3RseS4gIFRoaXMgZW5hYmxlc1xuICAgIC8vIHRoZSByZXNvbHZlIGZ1bmN0aW9uIHRvIGJvdGggYmUgdXNlZCB0byBjcmVhdGVkIHJlZmVyZW5jZXMgZnJvbSBvYmplY3RzLFxuICAgIC8vIGJ1dCB0byB0b2xlcmFibHkgY29lcmNlIG5vbi1wcm9taXNlcyB0byBwcm9taXNlcy5cbiAgICBpZiAodmFsdWUgaW5zdGFuY2VvZiBQcm9taXNlKSB7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvLyBhc3NpbWlsYXRlIHRoZW5hYmxlc1xuICAgIGlmIChpc1Byb21pc2VBbGlrZSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGNvZXJjZSh2YWx1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGZ1bGZpbGwodmFsdWUpO1xuICAgIH1cbn1cblEucmVzb2x2ZSA9IFE7XG5cbi8qKlxuICogUGVyZm9ybXMgYSB0YXNrIGluIGEgZnV0dXJlIHR1cm4gb2YgdGhlIGV2ZW50IGxvb3AuXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSB0YXNrXG4gKi9cblEubmV4dFRpY2sgPSBuZXh0VGljaztcblxuLyoqXG4gKiBDb250cm9scyB3aGV0aGVyIG9yIG5vdCBsb25nIHN0YWNrIHRyYWNlcyB3aWxsIGJlIG9uXG4gKi9cblEubG9uZ1N0YWNrU3VwcG9ydCA9IGZhbHNlO1xuXG4vLyBlbmFibGUgbG9uZyBzdGFja3MgaWYgUV9ERUJVRyBpcyBzZXRcbmlmICh0eXBlb2YgcHJvY2VzcyA9PT0gXCJvYmplY3RcIiAmJiBwcm9jZXNzICYmIHByb2Nlc3MuZW52ICYmIHByb2Nlc3MuZW52LlFfREVCVUcpIHtcbiAgICBRLmxvbmdTdGFja1N1cHBvcnQgPSB0cnVlO1xufVxuXG4vKipcbiAqIENvbnN0cnVjdHMgYSB7cHJvbWlzZSwgcmVzb2x2ZSwgcmVqZWN0fSBvYmplY3QuXG4gKlxuICogYHJlc29sdmVgIGlzIGEgY2FsbGJhY2sgdG8gaW52b2tlIHdpdGggYSBtb3JlIHJlc29sdmVkIHZhbHVlIGZvciB0aGVcbiAqIHByb21pc2UuIFRvIGZ1bGZpbGwgdGhlIHByb21pc2UsIGludm9rZSBgcmVzb2x2ZWAgd2l0aCBhbnkgdmFsdWUgdGhhdCBpc1xuICogbm90IGEgdGhlbmFibGUuIFRvIHJlamVjdCB0aGUgcHJvbWlzZSwgaW52b2tlIGByZXNvbHZlYCB3aXRoIGEgcmVqZWN0ZWRcbiAqIHRoZW5hYmxlLCBvciBpbnZva2UgYHJlamVjdGAgd2l0aCB0aGUgcmVhc29uIGRpcmVjdGx5LiBUbyByZXNvbHZlIHRoZVxuICogcHJvbWlzZSB0byBhbm90aGVyIHRoZW5hYmxlLCB0aHVzIHB1dHRpbmcgaXQgaW4gdGhlIHNhbWUgc3RhdGUsIGludm9rZVxuICogYHJlc29sdmVgIHdpdGggdGhhdCBvdGhlciB0aGVuYWJsZS5cbiAqL1xuUS5kZWZlciA9IGRlZmVyO1xuZnVuY3Rpb24gZGVmZXIoKSB7XG4gICAgLy8gaWYgXCJtZXNzYWdlc1wiIGlzIGFuIFwiQXJyYXlcIiwgdGhhdCBpbmRpY2F0ZXMgdGhhdCB0aGUgcHJvbWlzZSBoYXMgbm90IHlldFxuICAgIC8vIGJlZW4gcmVzb2x2ZWQuICBJZiBpdCBpcyBcInVuZGVmaW5lZFwiLCBpdCBoYXMgYmVlbiByZXNvbHZlZC4gIEVhY2hcbiAgICAvLyBlbGVtZW50IG9mIHRoZSBtZXNzYWdlcyBhcnJheSBpcyBpdHNlbGYgYW4gYXJyYXkgb2YgY29tcGxldGUgYXJndW1lbnRzIHRvXG4gICAgLy8gZm9yd2FyZCB0byB0aGUgcmVzb2x2ZWQgcHJvbWlzZS4gIFdlIGNvZXJjZSB0aGUgcmVzb2x1dGlvbiB2YWx1ZSB0byBhXG4gICAgLy8gcHJvbWlzZSB1c2luZyB0aGUgYHJlc29sdmVgIGZ1bmN0aW9uIGJlY2F1c2UgaXQgaGFuZGxlcyBib3RoIGZ1bGx5XG4gICAgLy8gbm9uLXRoZW5hYmxlIHZhbHVlcyBhbmQgb3RoZXIgdGhlbmFibGVzIGdyYWNlZnVsbHkuXG4gICAgdmFyIG1lc3NhZ2VzID0gW10sIHByb2dyZXNzTGlzdGVuZXJzID0gW10sIHJlc29sdmVkUHJvbWlzZTtcblxuICAgIHZhciBkZWZlcnJlZCA9IG9iamVjdF9jcmVhdGUoZGVmZXIucHJvdG90eXBlKTtcbiAgICB2YXIgcHJvbWlzZSA9IG9iamVjdF9jcmVhdGUoUHJvbWlzZS5wcm90b3R5cGUpO1xuXG4gICAgcHJvbWlzZS5wcm9taXNlRGlzcGF0Y2ggPSBmdW5jdGlvbiAocmVzb2x2ZSwgb3AsIG9wZXJhbmRzKSB7XG4gICAgICAgIHZhciBhcmdzID0gYXJyYXlfc2xpY2UoYXJndW1lbnRzKTtcbiAgICAgICAgaWYgKG1lc3NhZ2VzKSB7XG4gICAgICAgICAgICBtZXNzYWdlcy5wdXNoKGFyZ3MpO1xuICAgICAgICAgICAgaWYgKG9wID09PSBcIndoZW5cIiAmJiBvcGVyYW5kc1sxXSkgeyAvLyBwcm9ncmVzcyBvcGVyYW5kXG4gICAgICAgICAgICAgICAgcHJvZ3Jlc3NMaXN0ZW5lcnMucHVzaChvcGVyYW5kc1sxXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBRLm5leHRUaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXNvbHZlZFByb21pc2UucHJvbWlzZURpc3BhdGNoLmFwcGx5KHJlc29sdmVkUHJvbWlzZSwgYXJncyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICAvLyBYWFggZGVwcmVjYXRlZFxuICAgIHByb21pc2UudmFsdWVPZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKG1lc3NhZ2VzKSB7XG4gICAgICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbmVhcmVyVmFsdWUgPSBuZWFyZXIocmVzb2x2ZWRQcm9taXNlKTtcbiAgICAgICAgaWYgKGlzUHJvbWlzZShuZWFyZXJWYWx1ZSkpIHtcbiAgICAgICAgICAgIHJlc29sdmVkUHJvbWlzZSA9IG5lYXJlclZhbHVlOyAvLyBzaG9ydGVuIGNoYWluXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5lYXJlclZhbHVlO1xuICAgIH07XG5cbiAgICBwcm9taXNlLmluc3BlY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghcmVzb2x2ZWRQcm9taXNlKSB7XG4gICAgICAgICAgICByZXR1cm4geyBzdGF0ZTogXCJwZW5kaW5nXCIgfTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzb2x2ZWRQcm9taXNlLmluc3BlY3QoKTtcbiAgICB9O1xuXG4gICAgaWYgKFEubG9uZ1N0YWNrU3VwcG9ydCAmJiBoYXNTdGFja3MpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAvLyBOT1RFOiBkb24ndCB0cnkgdG8gdXNlIGBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZWAgb3IgdHJhbnNmZXIgdGhlXG4gICAgICAgICAgICAvLyBhY2Nlc3NvciBhcm91bmQ7IHRoYXQgY2F1c2VzIG1lbW9yeSBsZWFrcyBhcyBwZXIgR0gtMTExLiBKdXN0XG4gICAgICAgICAgICAvLyByZWlmeSB0aGUgc3RhY2sgdHJhY2UgYXMgYSBzdHJpbmcgQVNBUC5cbiAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAvLyBBdCB0aGUgc2FtZSB0aW1lLCBjdXQgb2ZmIHRoZSBmaXJzdCBsaW5lOyBpdCdzIGFsd2F5cyBqdXN0XG4gICAgICAgICAgICAvLyBcIltvYmplY3QgUHJvbWlzZV1cXG5cIiwgYXMgcGVyIHRoZSBgdG9TdHJpbmdgLlxuICAgICAgICAgICAgcHJvbWlzZS5zdGFjayA9IGUuc3RhY2suc3Vic3RyaW5nKGUuc3RhY2suaW5kZXhPZihcIlxcblwiKSArIDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTk9URTogd2UgZG8gdGhlIGNoZWNrcyBmb3IgYHJlc29sdmVkUHJvbWlzZWAgaW4gZWFjaCBtZXRob2QsIGluc3RlYWQgb2ZcbiAgICAvLyBjb25zb2xpZGF0aW5nIHRoZW0gaW50byBgYmVjb21lYCwgc2luY2Ugb3RoZXJ3aXNlIHdlJ2QgY3JlYXRlIG5ld1xuICAgIC8vIHByb21pc2VzIHdpdGggdGhlIGxpbmVzIGBiZWNvbWUod2hhdGV2ZXIodmFsdWUpKWAuIFNlZSBlLmcuIEdILTI1Mi5cblxuICAgIGZ1bmN0aW9uIGJlY29tZShuZXdQcm9taXNlKSB7XG4gICAgICAgIHJlc29sdmVkUHJvbWlzZSA9IG5ld1Byb21pc2U7XG4gICAgICAgIHByb21pc2Uuc291cmNlID0gbmV3UHJvbWlzZTtcblxuICAgICAgICBhcnJheV9yZWR1Y2UobWVzc2FnZXMsIGZ1bmN0aW9uICh1bmRlZmluZWQsIG1lc3NhZ2UpIHtcbiAgICAgICAgICAgIFEubmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIG5ld1Byb21pc2UucHJvbWlzZURpc3BhdGNoLmFwcGx5KG5ld1Byb21pc2UsIG1lc3NhZ2UpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0sIHZvaWQgMCk7XG5cbiAgICAgICAgbWVzc2FnZXMgPSB2b2lkIDA7XG4gICAgICAgIHByb2dyZXNzTGlzdGVuZXJzID0gdm9pZCAwO1xuICAgIH1cblxuICAgIGRlZmVycmVkLnByb21pc2UgPSBwcm9taXNlO1xuICAgIGRlZmVycmVkLnJlc29sdmUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgaWYgKHJlc29sdmVkUHJvbWlzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgYmVjb21lKFEodmFsdWUpKTtcbiAgICB9O1xuXG4gICAgZGVmZXJyZWQuZnVsZmlsbCA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBpZiAocmVzb2x2ZWRQcm9taXNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBiZWNvbWUoZnVsZmlsbCh2YWx1ZSkpO1xuICAgIH07XG4gICAgZGVmZXJyZWQucmVqZWN0ID0gZnVuY3Rpb24gKHJlYXNvbikge1xuICAgICAgICBpZiAocmVzb2x2ZWRQcm9taXNlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBiZWNvbWUocmVqZWN0KHJlYXNvbikpO1xuICAgIH07XG4gICAgZGVmZXJyZWQubm90aWZ5ID0gZnVuY3Rpb24gKHByb2dyZXNzKSB7XG4gICAgICAgIGlmIChyZXNvbHZlZFByb21pc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGFycmF5X3JlZHVjZShwcm9ncmVzc0xpc3RlbmVycywgZnVuY3Rpb24gKHVuZGVmaW5lZCwgcHJvZ3Jlc3NMaXN0ZW5lcikge1xuICAgICAgICAgICAgUS5uZXh0VGljayhmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcHJvZ3Jlc3NMaXN0ZW5lcihwcm9ncmVzcyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSwgdm9pZCAwKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGRlZmVycmVkO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBOb2RlLXN0eWxlIGNhbGxiYWNrIHRoYXQgd2lsbCByZXNvbHZlIG9yIHJlamVjdCB0aGUgZGVmZXJyZWRcbiAqIHByb21pc2UuXG4gKiBAcmV0dXJucyBhIG5vZGViYWNrXG4gKi9cbmRlZmVyLnByb3RvdHlwZS5tYWtlTm9kZVJlc29sdmVyID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICByZXR1cm4gZnVuY3Rpb24gKGVycm9yLCB2YWx1ZSkge1xuICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgIHNlbGYucmVqZWN0KGVycm9yKTtcbiAgICAgICAgfSBlbHNlIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMikge1xuICAgICAgICAgICAgc2VsZi5yZXNvbHZlKGFycmF5X3NsaWNlKGFyZ3VtZW50cywgMSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2VsZi5yZXNvbHZlKHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH07XG59O1xuXG4vKipcbiAqIEBwYXJhbSByZXNvbHZlciB7RnVuY3Rpb259IGEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIG5vdGhpbmcgYW5kIGFjY2VwdHNcbiAqIHRoZSByZXNvbHZlLCByZWplY3QsIGFuZCBub3RpZnkgZnVuY3Rpb25zIGZvciBhIGRlZmVycmVkLlxuICogQHJldHVybnMgYSBwcm9taXNlIHRoYXQgbWF5IGJlIHJlc29sdmVkIHdpdGggdGhlIGdpdmVuIHJlc29sdmUgYW5kIHJlamVjdFxuICogZnVuY3Rpb25zLCBvciByZWplY3RlZCBieSBhIHRocm93biBleGNlcHRpb24gaW4gcmVzb2x2ZXJcbiAqL1xuUS5Qcm9taXNlID0gcHJvbWlzZTsgLy8gRVM2XG5RLnByb21pc2UgPSBwcm9taXNlO1xuZnVuY3Rpb24gcHJvbWlzZShyZXNvbHZlcikge1xuICAgIGlmICh0eXBlb2YgcmVzb2x2ZXIgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwicmVzb2x2ZXIgbXVzdCBiZSBhIGZ1bmN0aW9uLlwiKTtcbiAgICB9XG4gICAgdmFyIGRlZmVycmVkID0gZGVmZXIoKTtcbiAgICB0cnkge1xuICAgICAgICByZXNvbHZlcihkZWZlcnJlZC5yZXNvbHZlLCBkZWZlcnJlZC5yZWplY3QsIGRlZmVycmVkLm5vdGlmeSk7XG4gICAgfSBjYXRjaCAocmVhc29uKSB7XG4gICAgICAgIGRlZmVycmVkLnJlamVjdChyZWFzb24pO1xuICAgIH1cbiAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZTtcbn1cblxucHJvbWlzZS5yYWNlID0gcmFjZTsgLy8gRVM2XG5wcm9taXNlLmFsbCA9IGFsbDsgLy8gRVM2XG5wcm9taXNlLnJlamVjdCA9IHJlamVjdDsgLy8gRVM2XG5wcm9taXNlLnJlc29sdmUgPSBROyAvLyBFUzZcblxuLy8gWFhYIGV4cGVyaW1lbnRhbC4gIFRoaXMgbWV0aG9kIGlzIGEgd2F5IHRvIGRlbm90ZSB0aGF0IGEgbG9jYWwgdmFsdWUgaXNcbi8vIHNlcmlhbGl6YWJsZSBhbmQgc2hvdWxkIGJlIGltbWVkaWF0ZWx5IGRpc3BhdGNoZWQgdG8gYSByZW1vdGUgdXBvbiByZXF1ZXN0LFxuLy8gaW5zdGVhZCBvZiBwYXNzaW5nIGEgcmVmZXJlbmNlLlxuUS5wYXNzQnlDb3B5ID0gZnVuY3Rpb24gKG9iamVjdCkge1xuICAgIC8vZnJlZXplKG9iamVjdCk7XG4gICAgLy9wYXNzQnlDb3BpZXMuc2V0KG9iamVjdCwgdHJ1ZSk7XG4gICAgcmV0dXJuIG9iamVjdDtcbn07XG5cblByb21pc2UucHJvdG90eXBlLnBhc3NCeUNvcHkgPSBmdW5jdGlvbiAoKSB7XG4gICAgLy9mcmVlemUob2JqZWN0KTtcbiAgICAvL3Bhc3NCeUNvcGllcy5zZXQob2JqZWN0LCB0cnVlKTtcbiAgICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogSWYgdHdvIHByb21pc2VzIGV2ZW50dWFsbHkgZnVsZmlsbCB0byB0aGUgc2FtZSB2YWx1ZSwgcHJvbWlzZXMgdGhhdCB2YWx1ZSxcbiAqIGJ1dCBvdGhlcndpc2UgcmVqZWN0cy5cbiAqIEBwYXJhbSB4IHtBbnkqfVxuICogQHBhcmFtIHkge0FueSp9XG4gKiBAcmV0dXJucyB7QW55Kn0gYSBwcm9taXNlIGZvciB4IGFuZCB5IGlmIHRoZXkgYXJlIHRoZSBzYW1lLCBidXQgYSByZWplY3Rpb25cbiAqIG90aGVyd2lzZS5cbiAqXG4gKi9cblEuam9pbiA9IGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgcmV0dXJuIFEoeCkuam9pbih5KTtcbn07XG5cblByb21pc2UucHJvdG90eXBlLmpvaW4gPSBmdW5jdGlvbiAodGhhdCkge1xuICAgIHJldHVybiBRKFt0aGlzLCB0aGF0XSkuc3ByZWFkKGZ1bmN0aW9uICh4LCB5KSB7XG4gICAgICAgIGlmICh4ID09PSB5KSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBcIj09PVwiIHNob3VsZCBiZSBPYmplY3QuaXMgb3IgZXF1aXZcbiAgICAgICAgICAgIHJldHVybiB4O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2FuJ3Qgam9pbjogbm90IHRoZSBzYW1lOiBcIiArIHggKyBcIiBcIiArIHkpO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBwcm9taXNlIGZvciB0aGUgZmlyc3Qgb2YgYW4gYXJyYXkgb2YgcHJvbWlzZXMgdG8gYmVjb21lIHNldHRsZWQuXG4gKiBAcGFyYW0gYW5zd2VycyB7QXJyYXlbQW55Kl19IHByb21pc2VzIHRvIHJhY2VcbiAqIEByZXR1cm5zIHtBbnkqfSB0aGUgZmlyc3QgcHJvbWlzZSB0byBiZSBzZXR0bGVkXG4gKi9cblEucmFjZSA9IHJhY2U7XG5mdW5jdGlvbiByYWNlKGFuc3dlclBzKSB7XG4gICAgcmV0dXJuIHByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAvLyBTd2l0Y2ggdG8gdGhpcyBvbmNlIHdlIGNhbiBhc3N1bWUgYXQgbGVhc3QgRVM1XG4gICAgICAgIC8vIGFuc3dlclBzLmZvckVhY2goZnVuY3Rpb24gKGFuc3dlclApIHtcbiAgICAgICAgLy8gICAgIFEoYW5zd2VyUCkudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAvLyB9KTtcbiAgICAgICAgLy8gVXNlIHRoaXMgaW4gdGhlIG1lYW50aW1lXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBhbnN3ZXJQcy5sZW5ndGg7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgUShhbnN3ZXJQc1tpXSkudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cblByb21pc2UucHJvdG90eXBlLnJhY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMudGhlbihRLnJhY2UpO1xufTtcblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGEgUHJvbWlzZSB3aXRoIGEgcHJvbWlzZSBkZXNjcmlwdG9yIG9iamVjdCBhbmQgb3B0aW9uYWwgZmFsbGJhY2tcbiAqIGZ1bmN0aW9uLiAgVGhlIGRlc2NyaXB0b3IgY29udGFpbnMgbWV0aG9kcyBsaWtlIHdoZW4ocmVqZWN0ZWQpLCBnZXQobmFtZSksXG4gKiBzZXQobmFtZSwgdmFsdWUpLCBwb3N0KG5hbWUsIGFyZ3MpLCBhbmQgZGVsZXRlKG5hbWUpLCB3aGljaCBhbGxcbiAqIHJldHVybiBlaXRoZXIgYSB2YWx1ZSwgYSBwcm9taXNlIGZvciBhIHZhbHVlLCBvciBhIHJlamVjdGlvbi4gIFRoZSBmYWxsYmFja1xuICogYWNjZXB0cyB0aGUgb3BlcmF0aW9uIG5hbWUsIGEgcmVzb2x2ZXIsIGFuZCBhbnkgZnVydGhlciBhcmd1bWVudHMgdGhhdCB3b3VsZFxuICogaGF2ZSBiZWVuIGZvcndhcmRlZCB0byB0aGUgYXBwcm9wcmlhdGUgbWV0aG9kIGFib3ZlIGhhZCBhIG1ldGhvZCBiZWVuXG4gKiBwcm92aWRlZCB3aXRoIHRoZSBwcm9wZXIgbmFtZS4gIFRoZSBBUEkgbWFrZXMgbm8gZ3VhcmFudGVlcyBhYm91dCB0aGUgbmF0dXJlXG4gKiBvZiB0aGUgcmV0dXJuZWQgb2JqZWN0LCBhcGFydCBmcm9tIHRoYXQgaXQgaXMgdXNhYmxlIHdoZXJlZXZlciBwcm9taXNlcyBhcmVcbiAqIGJvdWdodCBhbmQgc29sZC5cbiAqL1xuUS5tYWtlUHJvbWlzZSA9IFByb21pc2U7XG5mdW5jdGlvbiBQcm9taXNlKGRlc2NyaXB0b3IsIGZhbGxiYWNrLCBpbnNwZWN0KSB7XG4gICAgaWYgKGZhbGxiYWNrID09PSB2b2lkIDApIHtcbiAgICAgICAgZmFsbGJhY2sgPSBmdW5jdGlvbiAob3ApIHtcbiAgICAgICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKFxuICAgICAgICAgICAgICAgIFwiUHJvbWlzZSBkb2VzIG5vdCBzdXBwb3J0IG9wZXJhdGlvbjogXCIgKyBvcFxuICAgICAgICAgICAgKSk7XG4gICAgICAgIH07XG4gICAgfVxuICAgIGlmIChpbnNwZWN0ID09PSB2b2lkIDApIHtcbiAgICAgICAgaW5zcGVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB7c3RhdGU6IFwidW5rbm93blwifTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgcHJvbWlzZSA9IG9iamVjdF9jcmVhdGUoUHJvbWlzZS5wcm90b3R5cGUpO1xuXG4gICAgcHJvbWlzZS5wcm9taXNlRGlzcGF0Y2ggPSBmdW5jdGlvbiAocmVzb2x2ZSwgb3AsIGFyZ3MpIHtcbiAgICAgICAgdmFyIHJlc3VsdDtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmIChkZXNjcmlwdG9yW29wXSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGRlc2NyaXB0b3Jbb3BdLmFwcGx5KHByb21pc2UsIGFyZ3MpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBmYWxsYmFjay5jYWxsKHByb21pc2UsIG9wLCBhcmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBjYXRjaCAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICByZXN1bHQgPSByZWplY3QoZXhjZXB0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAocmVzb2x2ZSkge1xuICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHQpO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHByb21pc2UuaW5zcGVjdCA9IGluc3BlY3Q7XG5cbiAgICAvLyBYWFggZGVwcmVjYXRlZCBgdmFsdWVPZmAgYW5kIGBleGNlcHRpb25gIHN1cHBvcnRcbiAgICBpZiAoaW5zcGVjdCkge1xuICAgICAgICB2YXIgaW5zcGVjdGVkID0gaW5zcGVjdCgpO1xuICAgICAgICBpZiAoaW5zcGVjdGVkLnN0YXRlID09PSBcInJlamVjdGVkXCIpIHtcbiAgICAgICAgICAgIHByb21pc2UuZXhjZXB0aW9uID0gaW5zcGVjdGVkLnJlYXNvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIHByb21pc2UudmFsdWVPZiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBpbnNwZWN0ZWQgPSBpbnNwZWN0KCk7XG4gICAgICAgICAgICBpZiAoaW5zcGVjdGVkLnN0YXRlID09PSBcInBlbmRpbmdcIiB8fFxuICAgICAgICAgICAgICAgIGluc3BlY3RlZC5zdGF0ZSA9PT0gXCJyZWplY3RlZFwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaW5zcGVjdGVkLnZhbHVlO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiBwcm9taXNlO1xufVxuXG5Qcm9taXNlLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gXCJbb2JqZWN0IFByb21pc2VdXCI7XG59O1xuXG5Qcm9taXNlLnByb3RvdHlwZS50aGVuID0gZnVuY3Rpb24gKGZ1bGZpbGxlZCwgcmVqZWN0ZWQsIHByb2dyZXNzZWQpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdmFyIGRlZmVycmVkID0gZGVmZXIoKTtcbiAgICB2YXIgZG9uZSA9IGZhbHNlOyAgIC8vIGVuc3VyZSB0aGUgdW50cnVzdGVkIHByb21pc2UgbWFrZXMgYXQgbW9zdCBhXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBzaW5nbGUgY2FsbCB0byBvbmUgb2YgdGhlIGNhbGxiYWNrc1xuXG4gICAgZnVuY3Rpb24gX2Z1bGZpbGxlZCh2YWx1ZSkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBmdWxmaWxsZWQgPT09IFwiZnVuY3Rpb25cIiA/IGZ1bGZpbGxlZCh2YWx1ZSkgOiB2YWx1ZTtcbiAgICAgICAgfSBjYXRjaCAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVqZWN0KGV4Y2VwdGlvbik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBfcmVqZWN0ZWQoZXhjZXB0aW9uKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcmVqZWN0ZWQgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgbWFrZVN0YWNrVHJhY2VMb25nKGV4Y2VwdGlvbiwgc2VsZik7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZWplY3RlZChleGNlcHRpb24pO1xuICAgICAgICAgICAgfSBjYXRjaCAobmV3RXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChuZXdFeGNlcHRpb24pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZWplY3QoZXhjZXB0aW9uKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBfcHJvZ3Jlc3NlZCh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHByb2dyZXNzZWQgPT09IFwiZnVuY3Rpb25cIiA/IHByb2dyZXNzZWQodmFsdWUpIDogdmFsdWU7XG4gICAgfVxuXG4gICAgUS5uZXh0VGljayhmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNlbGYucHJvbWlzZURpc3BhdGNoKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICAgICAgaWYgKGRvbmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkb25lID0gdHJ1ZTtcblxuICAgICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZShfZnVsZmlsbGVkKHZhbHVlKSk7XG4gICAgICAgIH0sIFwid2hlblwiLCBbZnVuY3Rpb24gKGV4Y2VwdGlvbikge1xuICAgICAgICAgICAgaWYgKGRvbmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkb25lID0gdHJ1ZTtcblxuICAgICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZShfcmVqZWN0ZWQoZXhjZXB0aW9uKSk7XG4gICAgICAgIH1dKTtcbiAgICB9KTtcblxuICAgIC8vIFByb2dyZXNzIHByb3BhZ2F0b3IgbmVlZCB0byBiZSBhdHRhY2hlZCBpbiB0aGUgY3VycmVudCB0aWNrLlxuICAgIHNlbGYucHJvbWlzZURpc3BhdGNoKHZvaWQgMCwgXCJ3aGVuXCIsIFt2b2lkIDAsIGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB2YXIgbmV3VmFsdWU7XG4gICAgICAgIHZhciB0aHJldyA9IGZhbHNlO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgbmV3VmFsdWUgPSBfcHJvZ3Jlc3NlZCh2YWx1ZSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHRocmV3ID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmIChRLm9uZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBRLm9uZXJyb3IoZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRocmV3KSB7XG4gICAgICAgICAgICBkZWZlcnJlZC5ub3RpZnkobmV3VmFsdWUpO1xuICAgICAgICB9XG4gICAgfV0pO1xuXG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG59O1xuXG5RLnRhcCA9IGZ1bmN0aW9uIChwcm9taXNlLCBjYWxsYmFjaykge1xuICAgIHJldHVybiBRKHByb21pc2UpLnRhcChjYWxsYmFjayk7XG59O1xuXG4vKipcbiAqIFdvcmtzIGFsbW9zdCBsaWtlIFwiZmluYWxseVwiLCBidXQgbm90IGNhbGxlZCBmb3IgcmVqZWN0aW9ucy5cbiAqIE9yaWdpbmFsIHJlc29sdXRpb24gdmFsdWUgaXMgcGFzc2VkIHRocm91Z2ggY2FsbGJhY2sgdW5hZmZlY3RlZC5cbiAqIENhbGxiYWNrIG1heSByZXR1cm4gYSBwcm9taXNlIHRoYXQgd2lsbCBiZSBhd2FpdGVkIGZvci5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGNhbGxiYWNrXG4gKiBAcmV0dXJucyB7US5Qcm9taXNlfVxuICogQGV4YW1wbGVcbiAqIGRvU29tZXRoaW5nKClcbiAqICAgLnRoZW4oLi4uKVxuICogICAudGFwKGNvbnNvbGUubG9nKVxuICogICAudGhlbiguLi4pO1xuICovXG5Qcm9taXNlLnByb3RvdHlwZS50YXAgPSBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICBjYWxsYmFjayA9IFEoY2FsbGJhY2spO1xuXG4gICAgcmV0dXJuIHRoaXMudGhlbihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrLmZjYWxsKHZhbHVlKS50aGVuUmVzb2x2ZSh2YWx1ZSk7XG4gICAgfSk7XG59O1xuXG4vKipcbiAqIFJlZ2lzdGVycyBhbiBvYnNlcnZlciBvbiBhIHByb21pc2UuXG4gKlxuICogR3VhcmFudGVlczpcbiAqXG4gKiAxLiB0aGF0IGZ1bGZpbGxlZCBhbmQgcmVqZWN0ZWQgd2lsbCBiZSBjYWxsZWQgb25seSBvbmNlLlxuICogMi4gdGhhdCBlaXRoZXIgdGhlIGZ1bGZpbGxlZCBjYWxsYmFjayBvciB0aGUgcmVqZWN0ZWQgY2FsbGJhY2sgd2lsbCBiZVxuICogICAgY2FsbGVkLCBidXQgbm90IGJvdGguXG4gKiAzLiB0aGF0IGZ1bGZpbGxlZCBhbmQgcmVqZWN0ZWQgd2lsbCBub3QgYmUgY2FsbGVkIGluIHRoaXMgdHVybi5cbiAqXG4gKiBAcGFyYW0gdmFsdWUgICAgICBwcm9taXNlIG9yIGltbWVkaWF0ZSByZWZlcmVuY2UgdG8gb2JzZXJ2ZVxuICogQHBhcmFtIGZ1bGZpbGxlZCAgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdpdGggdGhlIGZ1bGZpbGxlZCB2YWx1ZVxuICogQHBhcmFtIHJlamVjdGVkICAgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdpdGggdGhlIHJlamVjdGlvbiBleGNlcHRpb25cbiAqIEBwYXJhbSBwcm9ncmVzc2VkIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCBvbiBhbnkgcHJvZ3Jlc3Mgbm90aWZpY2F0aW9uc1xuICogQHJldHVybiBwcm9taXNlIGZvciB0aGUgcmV0dXJuIHZhbHVlIGZyb20gdGhlIGludm9rZWQgY2FsbGJhY2tcbiAqL1xuUS53aGVuID0gd2hlbjtcbmZ1bmN0aW9uIHdoZW4odmFsdWUsIGZ1bGZpbGxlZCwgcmVqZWN0ZWQsIHByb2dyZXNzZWQpIHtcbiAgICByZXR1cm4gUSh2YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkLCBwcm9ncmVzc2VkKTtcbn1cblxuUHJvbWlzZS5wcm90b3R5cGUudGhlblJlc29sdmUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICByZXR1cm4gdGhpcy50aGVuKGZ1bmN0aW9uICgpIHsgcmV0dXJuIHZhbHVlOyB9KTtcbn07XG5cblEudGhlblJlc29sdmUgPSBmdW5jdGlvbiAocHJvbWlzZSwgdmFsdWUpIHtcbiAgICByZXR1cm4gUShwcm9taXNlKS50aGVuUmVzb2x2ZSh2YWx1ZSk7XG59O1xuXG5Qcm9taXNlLnByb3RvdHlwZS50aGVuUmVqZWN0ID0gZnVuY3Rpb24gKHJlYXNvbikge1xuICAgIHJldHVybiB0aGlzLnRoZW4oZnVuY3Rpb24gKCkgeyB0aHJvdyByZWFzb247IH0pO1xufTtcblxuUS50aGVuUmVqZWN0ID0gZnVuY3Rpb24gKHByb21pc2UsIHJlYXNvbikge1xuICAgIHJldHVybiBRKHByb21pc2UpLnRoZW5SZWplY3QocmVhc29uKTtcbn07XG5cbi8qKlxuICogSWYgYW4gb2JqZWN0IGlzIG5vdCBhIHByb21pc2UsIGl0IGlzIGFzIFwibmVhclwiIGFzIHBvc3NpYmxlLlxuICogSWYgYSBwcm9taXNlIGlzIHJlamVjdGVkLCBpdCBpcyBhcyBcIm5lYXJcIiBhcyBwb3NzaWJsZSB0b28uXG4gKiBJZiBpdOKAmXMgYSBmdWxmaWxsZWQgcHJvbWlzZSwgdGhlIGZ1bGZpbGxtZW50IHZhbHVlIGlzIG5lYXJlci5cbiAqIElmIGl04oCZcyBhIGRlZmVycmVkIHByb21pc2UgYW5kIHRoZSBkZWZlcnJlZCBoYXMgYmVlbiByZXNvbHZlZCwgdGhlXG4gKiByZXNvbHV0aW9uIGlzIFwibmVhcmVyXCIuXG4gKiBAcGFyYW0gb2JqZWN0XG4gKiBAcmV0dXJucyBtb3N0IHJlc29sdmVkIChuZWFyZXN0KSBmb3JtIG9mIHRoZSBvYmplY3RcbiAqL1xuXG4vLyBYWFggc2hvdWxkIHdlIHJlLWRvIHRoaXM/XG5RLm5lYXJlciA9IG5lYXJlcjtcbmZ1bmN0aW9uIG5lYXJlcih2YWx1ZSkge1xuICAgIGlmIChpc1Byb21pc2UodmFsdWUpKSB7XG4gICAgICAgIHZhciBpbnNwZWN0ZWQgPSB2YWx1ZS5pbnNwZWN0KCk7XG4gICAgICAgIGlmIChpbnNwZWN0ZWQuc3RhdGUgPT09IFwiZnVsZmlsbGVkXCIpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnNwZWN0ZWQudmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuXG4vKipcbiAqIEByZXR1cm5zIHdoZXRoZXIgdGhlIGdpdmVuIG9iamVjdCBpcyBhIHByb21pc2UuXG4gKiBPdGhlcndpc2UgaXQgaXMgYSBmdWxmaWxsZWQgdmFsdWUuXG4gKi9cblEuaXNQcm9taXNlID0gaXNQcm9taXNlO1xuZnVuY3Rpb24gaXNQcm9taXNlKG9iamVjdCkge1xuICAgIHJldHVybiBvYmplY3QgaW5zdGFuY2VvZiBQcm9taXNlO1xufVxuXG5RLmlzUHJvbWlzZUFsaWtlID0gaXNQcm9taXNlQWxpa2U7XG5mdW5jdGlvbiBpc1Byb21pc2VBbGlrZShvYmplY3QpIHtcbiAgICByZXR1cm4gaXNPYmplY3Qob2JqZWN0KSAmJiB0eXBlb2Ygb2JqZWN0LnRoZW4gPT09IFwiZnVuY3Rpb25cIjtcbn1cblxuLyoqXG4gKiBAcmV0dXJucyB3aGV0aGVyIHRoZSBnaXZlbiBvYmplY3QgaXMgYSBwZW5kaW5nIHByb21pc2UsIG1lYW5pbmcgbm90XG4gKiBmdWxmaWxsZWQgb3IgcmVqZWN0ZWQuXG4gKi9cblEuaXNQZW5kaW5nID0gaXNQZW5kaW5nO1xuZnVuY3Rpb24gaXNQZW5kaW5nKG9iamVjdCkge1xuICAgIHJldHVybiBpc1Byb21pc2Uob2JqZWN0KSAmJiBvYmplY3QuaW5zcGVjdCgpLnN0YXRlID09PSBcInBlbmRpbmdcIjtcbn1cblxuUHJvbWlzZS5wcm90b3R5cGUuaXNQZW5kaW5nID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmluc3BlY3QoKS5zdGF0ZSA9PT0gXCJwZW5kaW5nXCI7XG59O1xuXG4vKipcbiAqIEByZXR1cm5zIHdoZXRoZXIgdGhlIGdpdmVuIG9iamVjdCBpcyBhIHZhbHVlIG9yIGZ1bGZpbGxlZFxuICogcHJvbWlzZS5cbiAqL1xuUS5pc0Z1bGZpbGxlZCA9IGlzRnVsZmlsbGVkO1xuZnVuY3Rpb24gaXNGdWxmaWxsZWQob2JqZWN0KSB7XG4gICAgcmV0dXJuICFpc1Byb21pc2Uob2JqZWN0KSB8fCBvYmplY3QuaW5zcGVjdCgpLnN0YXRlID09PSBcImZ1bGZpbGxlZFwiO1xufVxuXG5Qcm9taXNlLnByb3RvdHlwZS5pc0Z1bGZpbGxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5pbnNwZWN0KCkuc3RhdGUgPT09IFwiZnVsZmlsbGVkXCI7XG59O1xuXG4vKipcbiAqIEByZXR1cm5zIHdoZXRoZXIgdGhlIGdpdmVuIG9iamVjdCBpcyBhIHJlamVjdGVkIHByb21pc2UuXG4gKi9cblEuaXNSZWplY3RlZCA9IGlzUmVqZWN0ZWQ7XG5mdW5jdGlvbiBpc1JlamVjdGVkKG9iamVjdCkge1xuICAgIHJldHVybiBpc1Byb21pc2Uob2JqZWN0KSAmJiBvYmplY3QuaW5zcGVjdCgpLnN0YXRlID09PSBcInJlamVjdGVkXCI7XG59XG5cblByb21pc2UucHJvdG90eXBlLmlzUmVqZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuaW5zcGVjdCgpLnN0YXRlID09PSBcInJlamVjdGVkXCI7XG59O1xuXG4vLy8vIEJFR0lOIFVOSEFORExFRCBSRUpFQ1RJT04gVFJBQ0tJTkdcblxuLy8gVGhpcyBwcm9taXNlIGxpYnJhcnkgY29uc3VtZXMgZXhjZXB0aW9ucyB0aHJvd24gaW4gaGFuZGxlcnMgc28gdGhleSBjYW4gYmVcbi8vIGhhbmRsZWQgYnkgYSBzdWJzZXF1ZW50IHByb21pc2UuICBUaGUgZXhjZXB0aW9ucyBnZXQgYWRkZWQgdG8gdGhpcyBhcnJheSB3aGVuXG4vLyB0aGV5IGFyZSBjcmVhdGVkLCBhbmQgcmVtb3ZlZCB3aGVuIHRoZXkgYXJlIGhhbmRsZWQuICBOb3RlIHRoYXQgaW4gRVM2IG9yXG4vLyBzaGltbWVkIGVudmlyb25tZW50cywgdGhpcyB3b3VsZCBuYXR1cmFsbHkgYmUgYSBgU2V0YC5cbnZhciB1bmhhbmRsZWRSZWFzb25zID0gW107XG52YXIgdW5oYW5kbGVkUmVqZWN0aW9ucyA9IFtdO1xudmFyIHJlcG9ydGVkVW5oYW5kbGVkUmVqZWN0aW9ucyA9IFtdO1xudmFyIHRyYWNrVW5oYW5kbGVkUmVqZWN0aW9ucyA9IHRydWU7XG5cbmZ1bmN0aW9uIHJlc2V0VW5oYW5kbGVkUmVqZWN0aW9ucygpIHtcbiAgICB1bmhhbmRsZWRSZWFzb25zLmxlbmd0aCA9IDA7XG4gICAgdW5oYW5kbGVkUmVqZWN0aW9ucy5sZW5ndGggPSAwO1xuXG4gICAgaWYgKCF0cmFja1VuaGFuZGxlZFJlamVjdGlvbnMpIHtcbiAgICAgICAgdHJhY2tVbmhhbmRsZWRSZWplY3Rpb25zID0gdHJ1ZTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHRyYWNrUmVqZWN0aW9uKHByb21pc2UsIHJlYXNvbikge1xuICAgIGlmICghdHJhY2tVbmhhbmRsZWRSZWplY3Rpb25zKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBwcm9jZXNzID09PSBcIm9iamVjdFwiICYmIHR5cGVvZiBwcm9jZXNzLmVtaXQgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBRLm5leHRUaWNrLnJ1bkFmdGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmIChhcnJheV9pbmRleE9mKHVuaGFuZGxlZFJlamVjdGlvbnMsIHByb21pc2UpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHByb2Nlc3MuZW1pdChcInVuaGFuZGxlZFJlamVjdGlvblwiLCByZWFzb24sIHByb21pc2UpO1xuICAgICAgICAgICAgICAgIHJlcG9ydGVkVW5oYW5kbGVkUmVqZWN0aW9ucy5wdXNoKHByb21pc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB1bmhhbmRsZWRSZWplY3Rpb25zLnB1c2gocHJvbWlzZSk7XG4gICAgaWYgKHJlYXNvbiAmJiB0eXBlb2YgcmVhc29uLnN0YWNrICE9PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIHVuaGFuZGxlZFJlYXNvbnMucHVzaChyZWFzb24uc3RhY2spO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHVuaGFuZGxlZFJlYXNvbnMucHVzaChcIihubyBzdGFjaykgXCIgKyByZWFzb24pO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdW50cmFja1JlamVjdGlvbihwcm9taXNlKSB7XG4gICAgaWYgKCF0cmFja1VuaGFuZGxlZFJlamVjdGlvbnMpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBhdCA9IGFycmF5X2luZGV4T2YodW5oYW5kbGVkUmVqZWN0aW9ucywgcHJvbWlzZSk7XG4gICAgaWYgKGF0ICE9PSAtMSkge1xuICAgICAgICBpZiAodHlwZW9mIHByb2Nlc3MgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIHByb2Nlc3MuZW1pdCA9PT0gXCJmdW5jdGlvblwiKSB7XG4gICAgICAgICAgICBRLm5leHRUaWNrLnJ1bkFmdGVyKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXRSZXBvcnQgPSBhcnJheV9pbmRleE9mKHJlcG9ydGVkVW5oYW5kbGVkUmVqZWN0aW9ucywgcHJvbWlzZSk7XG4gICAgICAgICAgICAgICAgaWYgKGF0UmVwb3J0ICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBwcm9jZXNzLmVtaXQoXCJyZWplY3Rpb25IYW5kbGVkXCIsIHVuaGFuZGxlZFJlYXNvbnNbYXRdLCBwcm9taXNlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVwb3J0ZWRVbmhhbmRsZWRSZWplY3Rpb25zLnNwbGljZShhdFJlcG9ydCwgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgdW5oYW5kbGVkUmVqZWN0aW9ucy5zcGxpY2UoYXQsIDEpO1xuICAgICAgICB1bmhhbmRsZWRSZWFzb25zLnNwbGljZShhdCwgMSk7XG4gICAgfVxufVxuXG5RLnJlc2V0VW5oYW5kbGVkUmVqZWN0aW9ucyA9IHJlc2V0VW5oYW5kbGVkUmVqZWN0aW9ucztcblxuUS5nZXRVbmhhbmRsZWRSZWFzb25zID0gZnVuY3Rpb24gKCkge1xuICAgIC8vIE1ha2UgYSBjb3B5IHNvIHRoYXQgY29uc3VtZXJzIGNhbid0IGludGVyZmVyZSB3aXRoIG91ciBpbnRlcm5hbCBzdGF0ZS5cbiAgICByZXR1cm4gdW5oYW5kbGVkUmVhc29ucy5zbGljZSgpO1xufTtcblxuUS5zdG9wVW5oYW5kbGVkUmVqZWN0aW9uVHJhY2tpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmVzZXRVbmhhbmRsZWRSZWplY3Rpb25zKCk7XG4gICAgdHJhY2tVbmhhbmRsZWRSZWplY3Rpb25zID0gZmFsc2U7XG59O1xuXG5yZXNldFVuaGFuZGxlZFJlamVjdGlvbnMoKTtcblxuLy8vLyBFTkQgVU5IQU5ETEVEIFJFSkVDVElPTiBUUkFDS0lOR1xuXG4vKipcbiAqIENvbnN0cnVjdHMgYSByZWplY3RlZCBwcm9taXNlLlxuICogQHBhcmFtIHJlYXNvbiB2YWx1ZSBkZXNjcmliaW5nIHRoZSBmYWlsdXJlXG4gKi9cblEucmVqZWN0ID0gcmVqZWN0O1xuZnVuY3Rpb24gcmVqZWN0KHJlYXNvbikge1xuICAgIHZhciByZWplY3Rpb24gPSBQcm9taXNlKHtcbiAgICAgICAgXCJ3aGVuXCI6IGZ1bmN0aW9uIChyZWplY3RlZCkge1xuICAgICAgICAgICAgLy8gbm90ZSB0aGF0IHRoZSBlcnJvciBoYXMgYmVlbiBoYW5kbGVkXG4gICAgICAgICAgICBpZiAocmVqZWN0ZWQpIHtcbiAgICAgICAgICAgICAgICB1bnRyYWNrUmVqZWN0aW9uKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlamVjdGVkID8gcmVqZWN0ZWQocmVhc29uKSA6IHRoaXM7XG4gICAgICAgIH1cbiAgICB9LCBmdW5jdGlvbiBmYWxsYmFjaygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSwgZnVuY3Rpb24gaW5zcGVjdCgpIHtcbiAgICAgICAgcmV0dXJuIHsgc3RhdGU6IFwicmVqZWN0ZWRcIiwgcmVhc29uOiByZWFzb24gfTtcbiAgICB9KTtcblxuICAgIC8vIE5vdGUgdGhhdCB0aGUgcmVhc29uIGhhcyBub3QgYmVlbiBoYW5kbGVkLlxuICAgIHRyYWNrUmVqZWN0aW9uKHJlamVjdGlvbiwgcmVhc29uKTtcblxuICAgIHJldHVybiByZWplY3Rpb247XG59XG5cbi8qKlxuICogQ29uc3RydWN0cyBhIGZ1bGZpbGxlZCBwcm9taXNlIGZvciBhbiBpbW1lZGlhdGUgcmVmZXJlbmNlLlxuICogQHBhcmFtIHZhbHVlIGltbWVkaWF0ZSByZWZlcmVuY2VcbiAqL1xuUS5mdWxmaWxsID0gZnVsZmlsbDtcbmZ1bmN0aW9uIGZ1bGZpbGwodmFsdWUpIHtcbiAgICByZXR1cm4gUHJvbWlzZSh7XG4gICAgICAgIFwid2hlblwiOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH0sXG4gICAgICAgIFwiZ2V0XCI6IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWVbbmFtZV07XG4gICAgICAgIH0sXG4gICAgICAgIFwic2V0XCI6IGZ1bmN0aW9uIChuYW1lLCByaHMpIHtcbiAgICAgICAgICAgIHZhbHVlW25hbWVdID0gcmhzO1xuICAgICAgICB9LFxuICAgICAgICBcImRlbGV0ZVwiOiBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgICAgZGVsZXRlIHZhbHVlW25hbWVdO1xuICAgICAgICB9LFxuICAgICAgICBcInBvc3RcIjogZnVuY3Rpb24gKG5hbWUsIGFyZ3MpIHtcbiAgICAgICAgICAgIC8vIE1hcmsgTWlsbGVyIHByb3Bvc2VzIHRoYXQgcG9zdCB3aXRoIG5vIG5hbWUgc2hvdWxkIGFwcGx5IGFcbiAgICAgICAgICAgIC8vIHByb21pc2VkIGZ1bmN0aW9uLlxuICAgICAgICAgICAgaWYgKG5hbWUgPT09IG51bGwgfHwgbmFtZSA9PT0gdm9pZCAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlLmFwcGx5KHZvaWQgMCwgYXJncyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZVtuYW1lXS5hcHBseSh2YWx1ZSwgYXJncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFwiYXBwbHlcIjogZnVuY3Rpb24gKHRoaXNwLCBhcmdzKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWUuYXBwbHkodGhpc3AsIGFyZ3MpO1xuICAgICAgICB9LFxuICAgICAgICBcImtleXNcIjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdF9rZXlzKHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH0sIHZvaWQgMCwgZnVuY3Rpb24gaW5zcGVjdCgpIHtcbiAgICAgICAgcmV0dXJuIHsgc3RhdGU6IFwiZnVsZmlsbGVkXCIsIHZhbHVlOiB2YWx1ZSB9O1xuICAgIH0pO1xufVxuXG4vKipcbiAqIENvbnZlcnRzIHRoZW5hYmxlcyB0byBRIHByb21pc2VzLlxuICogQHBhcmFtIHByb21pc2UgdGhlbmFibGUgcHJvbWlzZVxuICogQHJldHVybnMgYSBRIHByb21pc2VcbiAqL1xuZnVuY3Rpb24gY29lcmNlKHByb21pc2UpIHtcbiAgICB2YXIgZGVmZXJyZWQgPSBkZWZlcigpO1xuICAgIFEubmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcHJvbWlzZS50aGVuKGRlZmVycmVkLnJlc29sdmUsIGRlZmVycmVkLnJlamVjdCwgZGVmZXJyZWQubm90aWZ5KTtcbiAgICAgICAgfSBjYXRjaCAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICBkZWZlcnJlZC5yZWplY3QoZXhjZXB0aW9uKTtcbiAgICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlO1xufVxuXG4vKipcbiAqIEFubm90YXRlcyBhbiBvYmplY3Qgc3VjaCB0aGF0IGl0IHdpbGwgbmV2ZXIgYmVcbiAqIHRyYW5zZmVycmVkIGF3YXkgZnJvbSB0aGlzIHByb2Nlc3Mgb3ZlciBhbnkgcHJvbWlzZVxuICogY29tbXVuaWNhdGlvbiBjaGFubmVsLlxuICogQHBhcmFtIG9iamVjdFxuICogQHJldHVybnMgcHJvbWlzZSBhIHdyYXBwaW5nIG9mIHRoYXQgb2JqZWN0IHRoYXRcbiAqIGFkZGl0aW9uYWxseSByZXNwb25kcyB0byB0aGUgXCJpc0RlZlwiIG1lc3NhZ2VcbiAqIHdpdGhvdXQgYSByZWplY3Rpb24uXG4gKi9cblEubWFzdGVyID0gbWFzdGVyO1xuZnVuY3Rpb24gbWFzdGVyKG9iamVjdCkge1xuICAgIHJldHVybiBQcm9taXNlKHtcbiAgICAgICAgXCJpc0RlZlwiOiBmdW5jdGlvbiAoKSB7fVxuICAgIH0sIGZ1bmN0aW9uIGZhbGxiYWNrKG9wLCBhcmdzKSB7XG4gICAgICAgIHJldHVybiBkaXNwYXRjaChvYmplY3QsIG9wLCBhcmdzKTtcbiAgICB9LCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBRKG9iamVjdCkuaW5zcGVjdCgpO1xuICAgIH0pO1xufVxuXG4vKipcbiAqIFNwcmVhZHMgdGhlIHZhbHVlcyBvZiBhIHByb21pc2VkIGFycmF5IG9mIGFyZ3VtZW50cyBpbnRvIHRoZVxuICogZnVsZmlsbG1lbnQgY2FsbGJhY2suXG4gKiBAcGFyYW0gZnVsZmlsbGVkIGNhbGxiYWNrIHRoYXQgcmVjZWl2ZXMgdmFyaWFkaWMgYXJndW1lbnRzIGZyb20gdGhlXG4gKiBwcm9taXNlZCBhcnJheVxuICogQHBhcmFtIHJlamVjdGVkIGNhbGxiYWNrIHRoYXQgcmVjZWl2ZXMgdGhlIGV4Y2VwdGlvbiBpZiB0aGUgcHJvbWlzZVxuICogaXMgcmVqZWN0ZWQuXG4gKiBAcmV0dXJucyBhIHByb21pc2UgZm9yIHRoZSByZXR1cm4gdmFsdWUgb3IgdGhyb3duIGV4Y2VwdGlvbiBvZlxuICogZWl0aGVyIGNhbGxiYWNrLlxuICovXG5RLnNwcmVhZCA9IHNwcmVhZDtcbmZ1bmN0aW9uIHNwcmVhZCh2YWx1ZSwgZnVsZmlsbGVkLCByZWplY3RlZCkge1xuICAgIHJldHVybiBRKHZhbHVlKS5zcHJlYWQoZnVsZmlsbGVkLCByZWplY3RlZCk7XG59XG5cblByb21pc2UucHJvdG90eXBlLnNwcmVhZCA9IGZ1bmN0aW9uIChmdWxmaWxsZWQsIHJlamVjdGVkKSB7XG4gICAgcmV0dXJuIHRoaXMuYWxsKCkudGhlbihmdW5jdGlvbiAoYXJyYXkpIHtcbiAgICAgICAgcmV0dXJuIGZ1bGZpbGxlZC5hcHBseSh2b2lkIDAsIGFycmF5KTtcbiAgICB9LCByZWplY3RlZCk7XG59O1xuXG4vKipcbiAqIFRoZSBhc3luYyBmdW5jdGlvbiBpcyBhIGRlY29yYXRvciBmb3IgZ2VuZXJhdG9yIGZ1bmN0aW9ucywgdHVybmluZ1xuICogdGhlbSBpbnRvIGFzeW5jaHJvbm91cyBnZW5lcmF0b3JzLiAgQWx0aG91Z2ggZ2VuZXJhdG9ycyBhcmUgb25seSBwYXJ0XG4gKiBvZiB0aGUgbmV3ZXN0IEVDTUFTY3JpcHQgNiBkcmFmdHMsIHRoaXMgY29kZSBkb2VzIG5vdCBjYXVzZSBzeW50YXhcbiAqIGVycm9ycyBpbiBvbGRlciBlbmdpbmVzLiAgVGhpcyBjb2RlIHNob3VsZCBjb250aW51ZSB0byB3b3JrIGFuZCB3aWxsXG4gKiBpbiBmYWN0IGltcHJvdmUgb3ZlciB0aW1lIGFzIHRoZSBsYW5ndWFnZSBpbXByb3Zlcy5cbiAqXG4gKiBFUzYgZ2VuZXJhdG9ycyBhcmUgY3VycmVudGx5IHBhcnQgb2YgVjggdmVyc2lvbiAzLjE5IHdpdGggdGhlXG4gKiAtLWhhcm1vbnktZ2VuZXJhdG9ycyBydW50aW1lIGZsYWcgZW5hYmxlZC4gIFNwaWRlck1vbmtleSBoYXMgaGFkIHRoZW1cbiAqIGZvciBsb25nZXIsIGJ1dCB1bmRlciBhbiBvbGRlciBQeXRob24taW5zcGlyZWQgZm9ybS4gIFRoaXMgZnVuY3Rpb25cbiAqIHdvcmtzIG9uIGJvdGgga2luZHMgb2YgZ2VuZXJhdG9ycy5cbiAqXG4gKiBEZWNvcmF0ZXMgYSBnZW5lcmF0b3IgZnVuY3Rpb24gc3VjaCB0aGF0OlxuICogIC0gaXQgbWF5IHlpZWxkIHByb21pc2VzXG4gKiAgLSBleGVjdXRpb24gd2lsbCBjb250aW51ZSB3aGVuIHRoYXQgcHJvbWlzZSBpcyBmdWxmaWxsZWRcbiAqICAtIHRoZSB2YWx1ZSBvZiB0aGUgeWllbGQgZXhwcmVzc2lvbiB3aWxsIGJlIHRoZSBmdWxmaWxsZWQgdmFsdWVcbiAqICAtIGl0IHJldHVybnMgYSBwcm9taXNlIGZvciB0aGUgcmV0dXJuIHZhbHVlICh3aGVuIHRoZSBnZW5lcmF0b3JcbiAqICAgIHN0b3BzIGl0ZXJhdGluZylcbiAqICAtIHRoZSBkZWNvcmF0ZWQgZnVuY3Rpb24gcmV0dXJucyBhIHByb21pc2UgZm9yIHRoZSByZXR1cm4gdmFsdWVcbiAqICAgIG9mIHRoZSBnZW5lcmF0b3Igb3IgdGhlIGZpcnN0IHJlamVjdGVkIHByb21pc2UgYW1vbmcgdGhvc2VcbiAqICAgIHlpZWxkZWQuXG4gKiAgLSBpZiBhbiBlcnJvciBpcyB0aHJvd24gaW4gdGhlIGdlbmVyYXRvciwgaXQgcHJvcGFnYXRlcyB0aHJvdWdoXG4gKiAgICBldmVyeSBmb2xsb3dpbmcgeWllbGQgdW50aWwgaXQgaXMgY2F1Z2h0LCBvciB1bnRpbCBpdCBlc2NhcGVzXG4gKiAgICB0aGUgZ2VuZXJhdG9yIGZ1bmN0aW9uIGFsdG9nZXRoZXIsIGFuZCBpcyB0cmFuc2xhdGVkIGludG8gYVxuICogICAgcmVqZWN0aW9uIGZvciB0aGUgcHJvbWlzZSByZXR1cm5lZCBieSB0aGUgZGVjb3JhdGVkIGdlbmVyYXRvci5cbiAqL1xuUS5hc3luYyA9IGFzeW5jO1xuZnVuY3Rpb24gYXN5bmMobWFrZUdlbmVyYXRvcikge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIHdoZW4gdmVyYiBpcyBcInNlbmRcIiwgYXJnIGlzIGEgdmFsdWVcbiAgICAgICAgLy8gd2hlbiB2ZXJiIGlzIFwidGhyb3dcIiwgYXJnIGlzIGFuIGV4Y2VwdGlvblxuICAgICAgICBmdW5jdGlvbiBjb250aW51ZXIodmVyYiwgYXJnKSB7XG4gICAgICAgICAgICB2YXIgcmVzdWx0O1xuXG4gICAgICAgICAgICAvLyBVbnRpbCBWOCAzLjE5IC8gQ2hyb21pdW0gMjkgaXMgcmVsZWFzZWQsIFNwaWRlck1vbmtleSBpcyB0aGUgb25seVxuICAgICAgICAgICAgLy8gZW5naW5lIHRoYXQgaGFzIGEgZGVwbG95ZWQgYmFzZSBvZiBicm93c2VycyB0aGF0IHN1cHBvcnQgZ2VuZXJhdG9ycy5cbiAgICAgICAgICAgIC8vIEhvd2V2ZXIsIFNNJ3MgZ2VuZXJhdG9ycyB1c2UgdGhlIFB5dGhvbi1pbnNwaXJlZCBzZW1hbnRpY3Mgb2ZcbiAgICAgICAgICAgIC8vIG91dGRhdGVkIEVTNiBkcmFmdHMuICBXZSB3b3VsZCBsaWtlIHRvIHN1cHBvcnQgRVM2LCBidXQgd2UnZCBhbHNvXG4gICAgICAgICAgICAvLyBsaWtlIHRvIG1ha2UgaXQgcG9zc2libGUgdG8gdXNlIGdlbmVyYXRvcnMgaW4gZGVwbG95ZWQgYnJvd3NlcnMsIHNvXG4gICAgICAgICAgICAvLyB3ZSBhbHNvIHN1cHBvcnQgUHl0aG9uLXN0eWxlIGdlbmVyYXRvcnMuICBBdCBzb21lIHBvaW50IHdlIGNhbiByZW1vdmVcbiAgICAgICAgICAgIC8vIHRoaXMgYmxvY2suXG5cbiAgICAgICAgICAgIGlmICh0eXBlb2YgU3RvcEl0ZXJhdGlvbiA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgICAgICAgICAgIC8vIEVTNiBHZW5lcmF0b3JzXG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gZ2VuZXJhdG9yW3ZlcmJdKGFyZyk7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZWplY3QoZXhjZXB0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHJlc3VsdC5kb25lKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBRKHJlc3VsdC52YWx1ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdoZW4ocmVzdWx0LnZhbHVlLCBjYWxsYmFjaywgZXJyYmFjayk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBTcGlkZXJNb25rZXkgR2VuZXJhdG9yc1xuICAgICAgICAgICAgICAgIC8vIEZJWE1FOiBSZW1vdmUgdGhpcyBjYXNlIHdoZW4gU00gZG9lcyBFUzYgZ2VuZXJhdG9ycy5cbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBnZW5lcmF0b3JbdmVyYl0oYXJnKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChleGNlcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzU3RvcEl0ZXJhdGlvbihleGNlcHRpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gUShleGNlcHRpb24udmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlamVjdChleGNlcHRpb24pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB3aGVuKHJlc3VsdCwgY2FsbGJhY2ssIGVycmJhY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBnZW5lcmF0b3IgPSBtYWtlR2VuZXJhdG9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gICAgICAgIHZhciBjYWxsYmFjayA9IGNvbnRpbnVlci5iaW5kKGNvbnRpbnVlciwgXCJuZXh0XCIpO1xuICAgICAgICB2YXIgZXJyYmFjayA9IGNvbnRpbnVlci5iaW5kKGNvbnRpbnVlciwgXCJ0aHJvd1wiKTtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgfTtcbn1cblxuLyoqXG4gKiBUaGUgc3Bhd24gZnVuY3Rpb24gaXMgYSBzbWFsbCB3cmFwcGVyIGFyb3VuZCBhc3luYyB0aGF0IGltbWVkaWF0ZWx5XG4gKiBjYWxscyB0aGUgZ2VuZXJhdG9yIGFuZCBhbHNvIGVuZHMgdGhlIHByb21pc2UgY2hhaW4sIHNvIHRoYXQgYW55XG4gKiB1bmhhbmRsZWQgZXJyb3JzIGFyZSB0aHJvd24gaW5zdGVhZCBvZiBmb3J3YXJkZWQgdG8gdGhlIGVycm9yXG4gKiBoYW5kbGVyLiBUaGlzIGlzIHVzZWZ1bCBiZWNhdXNlIGl0J3MgZXh0cmVtZWx5IGNvbW1vbiB0byBydW5cbiAqIGdlbmVyYXRvcnMgYXQgdGhlIHRvcC1sZXZlbCB0byB3b3JrIHdpdGggbGlicmFyaWVzLlxuICovXG5RLnNwYXduID0gc3Bhd247XG5mdW5jdGlvbiBzcGF3bihtYWtlR2VuZXJhdG9yKSB7XG4gICAgUS5kb25lKFEuYXN5bmMobWFrZUdlbmVyYXRvcikoKSk7XG59XG5cbi8vIEZJWE1FOiBSZW1vdmUgdGhpcyBpbnRlcmZhY2Ugb25jZSBFUzYgZ2VuZXJhdG9ycyBhcmUgaW4gU3BpZGVyTW9ua2V5LlxuLyoqXG4gKiBUaHJvd3MgYSBSZXR1cm5WYWx1ZSBleGNlcHRpb24gdG8gc3RvcCBhbiBhc3luY2hyb25vdXMgZ2VuZXJhdG9yLlxuICpcbiAqIFRoaXMgaW50ZXJmYWNlIGlzIGEgc3RvcC1nYXAgbWVhc3VyZSB0byBzdXBwb3J0IGdlbmVyYXRvciByZXR1cm5cbiAqIHZhbHVlcyBpbiBvbGRlciBGaXJlZm94L1NwaWRlck1vbmtleS4gIEluIGJyb3dzZXJzIHRoYXQgc3VwcG9ydCBFUzZcbiAqIGdlbmVyYXRvcnMgbGlrZSBDaHJvbWl1bSAyOSwganVzdCB1c2UgXCJyZXR1cm5cIiBpbiB5b3VyIGdlbmVyYXRvclxuICogZnVuY3Rpb25zLlxuICpcbiAqIEBwYXJhbSB2YWx1ZSB0aGUgcmV0dXJuIHZhbHVlIGZvciB0aGUgc3Vycm91bmRpbmcgZ2VuZXJhdG9yXG4gKiBAdGhyb3dzIFJldHVyblZhbHVlIGV4Y2VwdGlvbiB3aXRoIHRoZSB2YWx1ZS5cbiAqIEBleGFtcGxlXG4gKiAvLyBFUzYgc3R5bGVcbiAqIFEuYXN5bmMoZnVuY3Rpb24qICgpIHtcbiAqICAgICAgdmFyIGZvbyA9IHlpZWxkIGdldEZvb1Byb21pc2UoKTtcbiAqICAgICAgdmFyIGJhciA9IHlpZWxkIGdldEJhclByb21pc2UoKTtcbiAqICAgICAgcmV0dXJuIGZvbyArIGJhcjtcbiAqIH0pXG4gKiAvLyBPbGRlciBTcGlkZXJNb25rZXkgc3R5bGVcbiAqIFEuYXN5bmMoZnVuY3Rpb24gKCkge1xuICogICAgICB2YXIgZm9vID0geWllbGQgZ2V0Rm9vUHJvbWlzZSgpO1xuICogICAgICB2YXIgYmFyID0geWllbGQgZ2V0QmFyUHJvbWlzZSgpO1xuICogICAgICBRLnJldHVybihmb28gKyBiYXIpO1xuICogfSlcbiAqL1xuUVtcInJldHVyblwiXSA9IF9yZXR1cm47XG5mdW5jdGlvbiBfcmV0dXJuKHZhbHVlKSB7XG4gICAgdGhyb3cgbmV3IFFSZXR1cm5WYWx1ZSh2YWx1ZSk7XG59XG5cbi8qKlxuICogVGhlIHByb21pc2VkIGZ1bmN0aW9uIGRlY29yYXRvciBlbnN1cmVzIHRoYXQgYW55IHByb21pc2UgYXJndW1lbnRzXG4gKiBhcmUgc2V0dGxlZCBhbmQgcGFzc2VkIGFzIHZhbHVlcyAoYHRoaXNgIGlzIGFsc28gc2V0dGxlZCBhbmQgcGFzc2VkXG4gKiBhcyBhIHZhbHVlKS4gIEl0IHdpbGwgYWxzbyBlbnN1cmUgdGhhdCB0aGUgcmVzdWx0IG9mIGEgZnVuY3Rpb24gaXNcbiAqIGFsd2F5cyBhIHByb21pc2UuXG4gKlxuICogQGV4YW1wbGVcbiAqIHZhciBhZGQgPSBRLnByb21pc2VkKGZ1bmN0aW9uIChhLCBiKSB7XG4gKiAgICAgcmV0dXJuIGEgKyBiO1xuICogfSk7XG4gKiBhZGQoUShhKSwgUShCKSk7XG4gKlxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGRlY29yYXRlXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IGEgZnVuY3Rpb24gdGhhdCBoYXMgYmVlbiBkZWNvcmF0ZWQuXG4gKi9cblEucHJvbWlzZWQgPSBwcm9taXNlZDtcbmZ1bmN0aW9uIHByb21pc2VkKGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHNwcmVhZChbdGhpcywgYWxsKGFyZ3VtZW50cyldLCBmdW5jdGlvbiAoc2VsZiwgYXJncykge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrLmFwcGx5KHNlbGYsIGFyZ3MpO1xuICAgICAgICB9KTtcbiAgICB9O1xufVxuXG4vKipcbiAqIHNlbmRzIGEgbWVzc2FnZSB0byBhIHZhbHVlIGluIGEgZnV0dXJlIHR1cm5cbiAqIEBwYXJhbSBvYmplY3QqIHRoZSByZWNpcGllbnRcbiAqIEBwYXJhbSBvcCB0aGUgbmFtZSBvZiB0aGUgbWVzc2FnZSBvcGVyYXRpb24sIGUuZy4sIFwid2hlblwiLFxuICogQHBhcmFtIGFyZ3MgZnVydGhlciBhcmd1bWVudHMgdG8gYmUgZm9yd2FyZGVkIHRvIHRoZSBvcGVyYXRpb25cbiAqIEByZXR1cm5zIHJlc3VsdCB7UHJvbWlzZX0gYSBwcm9taXNlIGZvciB0aGUgcmVzdWx0IG9mIHRoZSBvcGVyYXRpb25cbiAqL1xuUS5kaXNwYXRjaCA9IGRpc3BhdGNoO1xuZnVuY3Rpb24gZGlzcGF0Y2gob2JqZWN0LCBvcCwgYXJncykge1xuICAgIHJldHVybiBRKG9iamVjdCkuZGlzcGF0Y2gob3AsIGFyZ3MpO1xufVxuXG5Qcm9taXNlLnByb3RvdHlwZS5kaXNwYXRjaCA9IGZ1bmN0aW9uIChvcCwgYXJncykge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICB2YXIgZGVmZXJyZWQgPSBkZWZlcigpO1xuICAgIFEubmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICBzZWxmLnByb21pc2VEaXNwYXRjaChkZWZlcnJlZC5yZXNvbHZlLCBvcCwgYXJncyk7XG4gICAgfSk7XG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG59O1xuXG4vKipcbiAqIEdldHMgdGhlIHZhbHVlIG9mIGEgcHJvcGVydHkgaW4gYSBmdXR1cmUgdHVybi5cbiAqIEBwYXJhbSBvYmplY3QgICAgcHJvbWlzZSBvciBpbW1lZGlhdGUgcmVmZXJlbmNlIGZvciB0YXJnZXQgb2JqZWN0XG4gKiBAcGFyYW0gbmFtZSAgICAgIG5hbWUgb2YgcHJvcGVydHkgdG8gZ2V0XG4gKiBAcmV0dXJuIHByb21pc2UgZm9yIHRoZSBwcm9wZXJ0eSB2YWx1ZVxuICovXG5RLmdldCA9IGZ1bmN0aW9uIChvYmplY3QsIGtleSkge1xuICAgIHJldHVybiBRKG9iamVjdCkuZGlzcGF0Y2goXCJnZXRcIiwgW2tleV0pO1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiB0aGlzLmRpc3BhdGNoKFwiZ2V0XCIsIFtrZXldKTtcbn07XG5cbi8qKlxuICogU2V0cyB0aGUgdmFsdWUgb2YgYSBwcm9wZXJ0eSBpbiBhIGZ1dHVyZSB0dXJuLlxuICogQHBhcmFtIG9iamVjdCAgICBwcm9taXNlIG9yIGltbWVkaWF0ZSByZWZlcmVuY2UgZm9yIG9iamVjdCBvYmplY3RcbiAqIEBwYXJhbSBuYW1lICAgICAgbmFtZSBvZiBwcm9wZXJ0eSB0byBzZXRcbiAqIEBwYXJhbSB2YWx1ZSAgICAgbmV3IHZhbHVlIG9mIHByb3BlcnR5XG4gKiBAcmV0dXJuIHByb21pc2UgZm9yIHRoZSByZXR1cm4gdmFsdWVcbiAqL1xuUS5zZXQgPSBmdW5jdGlvbiAob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gICAgcmV0dXJuIFEob2JqZWN0KS5kaXNwYXRjaChcInNldFwiLCBba2V5LCB2YWx1ZV0pO1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKGtleSwgdmFsdWUpIHtcbiAgICByZXR1cm4gdGhpcy5kaXNwYXRjaChcInNldFwiLCBba2V5LCB2YWx1ZV0pO1xufTtcblxuLyoqXG4gKiBEZWxldGVzIGEgcHJvcGVydHkgaW4gYSBmdXR1cmUgdHVybi5cbiAqIEBwYXJhbSBvYmplY3QgICAgcHJvbWlzZSBvciBpbW1lZGlhdGUgcmVmZXJlbmNlIGZvciB0YXJnZXQgb2JqZWN0XG4gKiBAcGFyYW0gbmFtZSAgICAgIG5hbWUgb2YgcHJvcGVydHkgdG8gZGVsZXRlXG4gKiBAcmV0dXJuIHByb21pc2UgZm9yIHRoZSByZXR1cm4gdmFsdWVcbiAqL1xuUS5kZWwgPSAvLyBYWFggbGVnYWN5XG5RW1wiZGVsZXRlXCJdID0gZnVuY3Rpb24gKG9iamVjdCwga2V5KSB7XG4gICAgcmV0dXJuIFEob2JqZWN0KS5kaXNwYXRjaChcImRlbGV0ZVwiLCBba2V5XSk7XG59O1xuXG5Qcm9taXNlLnByb3RvdHlwZS5kZWwgPSAvLyBYWFggbGVnYWN5XG5Qcm9taXNlLnByb3RvdHlwZVtcImRlbGV0ZVwiXSA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4gdGhpcy5kaXNwYXRjaChcImRlbGV0ZVwiLCBba2V5XSk7XG59O1xuXG4vKipcbiAqIEludm9rZXMgYSBtZXRob2QgaW4gYSBmdXR1cmUgdHVybi5cbiAqIEBwYXJhbSBvYmplY3QgICAgcHJvbWlzZSBvciBpbW1lZGlhdGUgcmVmZXJlbmNlIGZvciB0YXJnZXQgb2JqZWN0XG4gKiBAcGFyYW0gbmFtZSAgICAgIG5hbWUgb2YgbWV0aG9kIHRvIGludm9rZVxuICogQHBhcmFtIHZhbHVlICAgICBhIHZhbHVlIHRvIHBvc3QsIHR5cGljYWxseSBhbiBhcnJheSBvZlxuICogICAgICAgICAgICAgICAgICBpbnZvY2F0aW9uIGFyZ3VtZW50cyBmb3IgcHJvbWlzZXMgdGhhdFxuICogICAgICAgICAgICAgICAgICBhcmUgdWx0aW1hdGVseSBiYWNrZWQgd2l0aCBgcmVzb2x2ZWAgdmFsdWVzLFxuICogICAgICAgICAgICAgICAgICBhcyBvcHBvc2VkIHRvIHRob3NlIGJhY2tlZCB3aXRoIFVSTHNcbiAqICAgICAgICAgICAgICAgICAgd2hlcmVpbiB0aGUgcG9zdGVkIHZhbHVlIGNhbiBiZSBhbnlcbiAqICAgICAgICAgICAgICAgICAgSlNPTiBzZXJpYWxpemFibGUgb2JqZWN0LlxuICogQHJldHVybiBwcm9taXNlIGZvciB0aGUgcmV0dXJuIHZhbHVlXG4gKi9cbi8vIGJvdW5kIGxvY2FsbHkgYmVjYXVzZSBpdCBpcyB1c2VkIGJ5IG90aGVyIG1ldGhvZHNcblEubWFwcGx5ID0gLy8gWFhYIEFzIHByb3Bvc2VkIGJ5IFwiUmVkc2FuZHJvXCJcblEucG9zdCA9IGZ1bmN0aW9uIChvYmplY3QsIG5hbWUsIGFyZ3MpIHtcbiAgICByZXR1cm4gUShvYmplY3QpLmRpc3BhdGNoKFwicG9zdFwiLCBbbmFtZSwgYXJnc10pO1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUubWFwcGx5ID0gLy8gWFhYIEFzIHByb3Bvc2VkIGJ5IFwiUmVkc2FuZHJvXCJcblByb21pc2UucHJvdG90eXBlLnBvc3QgPSBmdW5jdGlvbiAobmFtZSwgYXJncykge1xuICAgIHJldHVybiB0aGlzLmRpc3BhdGNoKFwicG9zdFwiLCBbbmFtZSwgYXJnc10pO1xufTtcblxuLyoqXG4gKiBJbnZva2VzIGEgbWV0aG9kIGluIGEgZnV0dXJlIHR1cm4uXG4gKiBAcGFyYW0gb2JqZWN0ICAgIHByb21pc2Ugb3IgaW1tZWRpYXRlIHJlZmVyZW5jZSBmb3IgdGFyZ2V0IG9iamVjdFxuICogQHBhcmFtIG5hbWUgICAgICBuYW1lIG9mIG1ldGhvZCB0byBpbnZva2VcbiAqIEBwYXJhbSAuLi5hcmdzICAgYXJyYXkgb2YgaW52b2NhdGlvbiBhcmd1bWVudHNcbiAqIEByZXR1cm4gcHJvbWlzZSBmb3IgdGhlIHJldHVybiB2YWx1ZVxuICovXG5RLnNlbmQgPSAvLyBYWFggTWFyayBNaWxsZXIncyBwcm9wb3NlZCBwYXJsYW5jZVxuUS5tY2FsbCA9IC8vIFhYWCBBcyBwcm9wb3NlZCBieSBcIlJlZHNhbmRyb1wiXG5RLmludm9rZSA9IGZ1bmN0aW9uIChvYmplY3QsIG5hbWUgLyouLi5hcmdzKi8pIHtcbiAgICByZXR1cm4gUShvYmplY3QpLmRpc3BhdGNoKFwicG9zdFwiLCBbbmFtZSwgYXJyYXlfc2xpY2UoYXJndW1lbnRzLCAyKV0pO1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUuc2VuZCA9IC8vIFhYWCBNYXJrIE1pbGxlcidzIHByb3Bvc2VkIHBhcmxhbmNlXG5Qcm9taXNlLnByb3RvdHlwZS5tY2FsbCA9IC8vIFhYWCBBcyBwcm9wb3NlZCBieSBcIlJlZHNhbmRyb1wiXG5Qcm9taXNlLnByb3RvdHlwZS5pbnZva2UgPSBmdW5jdGlvbiAobmFtZSAvKi4uLmFyZ3MqLykge1xuICAgIHJldHVybiB0aGlzLmRpc3BhdGNoKFwicG9zdFwiLCBbbmFtZSwgYXJyYXlfc2xpY2UoYXJndW1lbnRzLCAxKV0pO1xufTtcblxuLyoqXG4gKiBBcHBsaWVzIHRoZSBwcm9taXNlZCBmdW5jdGlvbiBpbiBhIGZ1dHVyZSB0dXJuLlxuICogQHBhcmFtIG9iamVjdCAgICBwcm9taXNlIG9yIGltbWVkaWF0ZSByZWZlcmVuY2UgZm9yIHRhcmdldCBmdW5jdGlvblxuICogQHBhcmFtIGFyZ3MgICAgICBhcnJheSBvZiBhcHBsaWNhdGlvbiBhcmd1bWVudHNcbiAqL1xuUS5mYXBwbHkgPSBmdW5jdGlvbiAob2JqZWN0LCBhcmdzKSB7XG4gICAgcmV0dXJuIFEob2JqZWN0KS5kaXNwYXRjaChcImFwcGx5XCIsIFt2b2lkIDAsIGFyZ3NdKTtcbn07XG5cblByb21pc2UucHJvdG90eXBlLmZhcHBseSA9IGZ1bmN0aW9uIChhcmdzKSB7XG4gICAgcmV0dXJuIHRoaXMuZGlzcGF0Y2goXCJhcHBseVwiLCBbdm9pZCAwLCBhcmdzXSk7XG59O1xuXG4vKipcbiAqIENhbGxzIHRoZSBwcm9taXNlZCBmdW5jdGlvbiBpbiBhIGZ1dHVyZSB0dXJuLlxuICogQHBhcmFtIG9iamVjdCAgICBwcm9taXNlIG9yIGltbWVkaWF0ZSByZWZlcmVuY2UgZm9yIHRhcmdldCBmdW5jdGlvblxuICogQHBhcmFtIC4uLmFyZ3MgICBhcnJheSBvZiBhcHBsaWNhdGlvbiBhcmd1bWVudHNcbiAqL1xuUVtcInRyeVwiXSA9XG5RLmZjYWxsID0gZnVuY3Rpb24gKG9iamVjdCAvKiAuLi5hcmdzKi8pIHtcbiAgICByZXR1cm4gUShvYmplY3QpLmRpc3BhdGNoKFwiYXBwbHlcIiwgW3ZvaWQgMCwgYXJyYXlfc2xpY2UoYXJndW1lbnRzLCAxKV0pO1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUuZmNhbGwgPSBmdW5jdGlvbiAoLyouLi5hcmdzKi8pIHtcbiAgICByZXR1cm4gdGhpcy5kaXNwYXRjaChcImFwcGx5XCIsIFt2b2lkIDAsIGFycmF5X3NsaWNlKGFyZ3VtZW50cyldKTtcbn07XG5cbi8qKlxuICogQmluZHMgdGhlIHByb21pc2VkIGZ1bmN0aW9uLCB0cmFuc2Zvcm1pbmcgcmV0dXJuIHZhbHVlcyBpbnRvIGEgZnVsZmlsbGVkXG4gKiBwcm9taXNlIGFuZCB0aHJvd24gZXJyb3JzIGludG8gYSByZWplY3RlZCBvbmUuXG4gKiBAcGFyYW0gb2JqZWN0ICAgIHByb21pc2Ugb3IgaW1tZWRpYXRlIHJlZmVyZW5jZSBmb3IgdGFyZ2V0IGZ1bmN0aW9uXG4gKiBAcGFyYW0gLi4uYXJncyAgIGFycmF5IG9mIGFwcGxpY2F0aW9uIGFyZ3VtZW50c1xuICovXG5RLmZiaW5kID0gZnVuY3Rpb24gKG9iamVjdCAvKi4uLmFyZ3MqLykge1xuICAgIHZhciBwcm9taXNlID0gUShvYmplY3QpO1xuICAgIHZhciBhcmdzID0gYXJyYXlfc2xpY2UoYXJndW1lbnRzLCAxKTtcbiAgICByZXR1cm4gZnVuY3Rpb24gZmJvdW5kKCkge1xuICAgICAgICByZXR1cm4gcHJvbWlzZS5kaXNwYXRjaChcImFwcGx5XCIsIFtcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICBhcmdzLmNvbmNhdChhcnJheV9zbGljZShhcmd1bWVudHMpKVxuICAgICAgICBdKTtcbiAgICB9O1xufTtcblByb21pc2UucHJvdG90eXBlLmZiaW5kID0gZnVuY3Rpb24gKC8qLi4uYXJncyovKSB7XG4gICAgdmFyIHByb21pc2UgPSB0aGlzO1xuICAgIHZhciBhcmdzID0gYXJyYXlfc2xpY2UoYXJndW1lbnRzKTtcbiAgICByZXR1cm4gZnVuY3Rpb24gZmJvdW5kKCkge1xuICAgICAgICByZXR1cm4gcHJvbWlzZS5kaXNwYXRjaChcImFwcGx5XCIsIFtcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICBhcmdzLmNvbmNhdChhcnJheV9zbGljZShhcmd1bWVudHMpKVxuICAgICAgICBdKTtcbiAgICB9O1xufTtcblxuLyoqXG4gKiBSZXF1ZXN0cyB0aGUgbmFtZXMgb2YgdGhlIG93bmVkIHByb3BlcnRpZXMgb2YgYSBwcm9taXNlZFxuICogb2JqZWN0IGluIGEgZnV0dXJlIHR1cm4uXG4gKiBAcGFyYW0gb2JqZWN0ICAgIHByb21pc2Ugb3IgaW1tZWRpYXRlIHJlZmVyZW5jZSBmb3IgdGFyZ2V0IG9iamVjdFxuICogQHJldHVybiBwcm9taXNlIGZvciB0aGUga2V5cyBvZiB0aGUgZXZlbnR1YWxseSBzZXR0bGVkIG9iamVjdFxuICovXG5RLmtleXMgPSBmdW5jdGlvbiAob2JqZWN0KSB7XG4gICAgcmV0dXJuIFEob2JqZWN0KS5kaXNwYXRjaChcImtleXNcIiwgW10pO1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUua2V5cyA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5kaXNwYXRjaChcImtleXNcIiwgW10pO1xufTtcblxuLyoqXG4gKiBUdXJucyBhbiBhcnJheSBvZiBwcm9taXNlcyBpbnRvIGEgcHJvbWlzZSBmb3IgYW4gYXJyYXkuICBJZiBhbnkgb2ZcbiAqIHRoZSBwcm9taXNlcyBnZXRzIHJlamVjdGVkLCB0aGUgd2hvbGUgYXJyYXkgaXMgcmVqZWN0ZWQgaW1tZWRpYXRlbHkuXG4gKiBAcGFyYW0ge0FycmF5Kn0gYW4gYXJyYXkgKG9yIHByb21pc2UgZm9yIGFuIGFycmF5KSBvZiB2YWx1ZXMgKG9yXG4gKiBwcm9taXNlcyBmb3IgdmFsdWVzKVxuICogQHJldHVybnMgYSBwcm9taXNlIGZvciBhbiBhcnJheSBvZiB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXNcbiAqL1xuLy8gQnkgTWFyayBNaWxsZXJcbi8vIGh0dHA6Ly93aWtpLmVjbWFzY3JpcHQub3JnL2Rva3UucGhwP2lkPXN0cmF3bWFuOmNvbmN1cnJlbmN5JnJldj0xMzA4Nzc2NTIxI2FsbGZ1bGZpbGxlZFxuUS5hbGwgPSBhbGw7XG5mdW5jdGlvbiBhbGwocHJvbWlzZXMpIHtcbiAgICByZXR1cm4gd2hlbihwcm9taXNlcywgZnVuY3Rpb24gKHByb21pc2VzKSB7XG4gICAgICAgIHZhciBwZW5kaW5nQ291bnQgPSAwO1xuICAgICAgICB2YXIgZGVmZXJyZWQgPSBkZWZlcigpO1xuICAgICAgICBhcnJheV9yZWR1Y2UocHJvbWlzZXMsIGZ1bmN0aW9uICh1bmRlZmluZWQsIHByb21pc2UsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgc25hcHNob3Q7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgaXNQcm9taXNlKHByb21pc2UpICYmXG4gICAgICAgICAgICAgICAgKHNuYXBzaG90ID0gcHJvbWlzZS5pbnNwZWN0KCkpLnN0YXRlID09PSBcImZ1bGZpbGxlZFwiXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBwcm9taXNlc1tpbmRleF0gPSBzbmFwc2hvdC52YWx1ZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgKytwZW5kaW5nQ291bnQ7XG4gICAgICAgICAgICAgICAgd2hlbihcbiAgICAgICAgICAgICAgICAgICAgcHJvbWlzZSxcbiAgICAgICAgICAgICAgICAgICAgZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwcm9taXNlc1tpbmRleF0gPSB2YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgtLXBlbmRpbmdDb3VudCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUocHJvbWlzZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBkZWZlcnJlZC5yZWplY3QsXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uIChwcm9ncmVzcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmZXJyZWQubm90aWZ5KHsgaW5kZXg6IGluZGV4LCB2YWx1ZTogcHJvZ3Jlc3MgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCB2b2lkIDApO1xuICAgICAgICBpZiAocGVuZGluZ0NvdW50ID09PSAwKSB7XG4gICAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHByb21pc2VzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZTtcbiAgICB9KTtcbn1cblxuUHJvbWlzZS5wcm90b3R5cGUuYWxsID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBhbGwodGhpcyk7XG59O1xuXG4vKipcbiAqIFJldHVybnMgdGhlIGZpcnN0IHJlc29sdmVkIHByb21pc2Ugb2YgYW4gYXJyYXkuIFByaW9yIHJlamVjdGVkIHByb21pc2VzIGFyZVxuICogaWdub3JlZC4gIFJlamVjdHMgb25seSBpZiBhbGwgcHJvbWlzZXMgYXJlIHJlamVjdGVkLlxuICogQHBhcmFtIHtBcnJheSp9IGFuIGFycmF5IGNvbnRhaW5pbmcgdmFsdWVzIG9yIHByb21pc2VzIGZvciB2YWx1ZXNcbiAqIEByZXR1cm5zIGEgcHJvbWlzZSBmdWxmaWxsZWQgd2l0aCB0aGUgdmFsdWUgb2YgdGhlIGZpcnN0IHJlc29sdmVkIHByb21pc2UsXG4gKiBvciBhIHJlamVjdGVkIHByb21pc2UgaWYgYWxsIHByb21pc2VzIGFyZSByZWplY3RlZC5cbiAqL1xuUS5hbnkgPSBhbnk7XG5cbmZ1bmN0aW9uIGFueShwcm9taXNlcykge1xuICAgIGlmIChwcm9taXNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIFEucmVzb2x2ZSgpO1xuICAgIH1cblxuICAgIHZhciBkZWZlcnJlZCA9IFEuZGVmZXIoKTtcbiAgICB2YXIgcGVuZGluZ0NvdW50ID0gMDtcbiAgICBhcnJheV9yZWR1Y2UocHJvbWlzZXMsIGZ1bmN0aW9uIChwcmV2LCBjdXJyZW50LCBpbmRleCkge1xuICAgICAgICB2YXIgcHJvbWlzZSA9IHByb21pc2VzW2luZGV4XTtcblxuICAgICAgICBwZW5kaW5nQ291bnQrKztcblxuICAgICAgICB3aGVuKHByb21pc2UsIG9uRnVsZmlsbGVkLCBvblJlamVjdGVkLCBvblByb2dyZXNzKTtcbiAgICAgICAgZnVuY3Rpb24gb25GdWxmaWxsZWQocmVzdWx0KSB7XG4gICAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHJlc3VsdCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gb25SZWplY3RlZCgpIHtcbiAgICAgICAgICAgIHBlbmRpbmdDb3VudC0tO1xuICAgICAgICAgICAgaWYgKHBlbmRpbmdDb3VudCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIGRlZmVycmVkLnJlamVjdChuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgIFwiQ2FuJ3QgZ2V0IGZ1bGZpbGxtZW50IHZhbHVlIGZyb20gYW55IHByb21pc2UsIGFsbCBcIiArXG4gICAgICAgICAgICAgICAgICAgIFwicHJvbWlzZXMgd2VyZSByZWplY3RlZC5cIlxuICAgICAgICAgICAgICAgICkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIG9uUHJvZ3Jlc3MocHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgIGRlZmVycmVkLm5vdGlmeSh7XG4gICAgICAgICAgICAgICAgaW5kZXg6IGluZGV4LFxuICAgICAgICAgICAgICAgIHZhbHVlOiBwcm9ncmVzc1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9LCB1bmRlZmluZWQpO1xuXG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG59XG5cblByb21pc2UucHJvdG90eXBlLmFueSA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gYW55KHRoaXMpO1xufTtcblxuLyoqXG4gKiBXYWl0cyBmb3IgYWxsIHByb21pc2VzIHRvIGJlIHNldHRsZWQsIGVpdGhlciBmdWxmaWxsZWQgb3JcbiAqIHJlamVjdGVkLiAgVGhpcyBpcyBkaXN0aW5jdCBmcm9tIGBhbGxgIHNpbmNlIHRoYXQgd291bGQgc3RvcFxuICogd2FpdGluZyBhdCB0aGUgZmlyc3QgcmVqZWN0aW9uLiAgVGhlIHByb21pc2UgcmV0dXJuZWQgYnlcbiAqIGBhbGxSZXNvbHZlZGAgd2lsbCBuZXZlciBiZSByZWplY3RlZC5cbiAqIEBwYXJhbSBwcm9taXNlcyBhIHByb21pc2UgZm9yIGFuIGFycmF5IChvciBhbiBhcnJheSkgb2YgcHJvbWlzZXNcbiAqIChvciB2YWx1ZXMpXG4gKiBAcmV0dXJuIGEgcHJvbWlzZSBmb3IgYW4gYXJyYXkgb2YgcHJvbWlzZXNcbiAqL1xuUS5hbGxSZXNvbHZlZCA9IGRlcHJlY2F0ZShhbGxSZXNvbHZlZCwgXCJhbGxSZXNvbHZlZFwiLCBcImFsbFNldHRsZWRcIik7XG5mdW5jdGlvbiBhbGxSZXNvbHZlZChwcm9taXNlcykge1xuICAgIHJldHVybiB3aGVuKHByb21pc2VzLCBmdW5jdGlvbiAocHJvbWlzZXMpIHtcbiAgICAgICAgcHJvbWlzZXMgPSBhcnJheV9tYXAocHJvbWlzZXMsIFEpO1xuICAgICAgICByZXR1cm4gd2hlbihhbGwoYXJyYXlfbWFwKHByb21pc2VzLCBmdW5jdGlvbiAocHJvbWlzZSkge1xuICAgICAgICAgICAgcmV0dXJuIHdoZW4ocHJvbWlzZSwgbm9vcCwgbm9vcCk7XG4gICAgICAgIH0pKSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHByb21pc2VzO1xuICAgICAgICB9KTtcbiAgICB9KTtcbn1cblxuUHJvbWlzZS5wcm90b3R5cGUuYWxsUmVzb2x2ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIGFsbFJlc29sdmVkKHRoaXMpO1xufTtcblxuLyoqXG4gKiBAc2VlIFByb21pc2UjYWxsU2V0dGxlZFxuICovXG5RLmFsbFNldHRsZWQgPSBhbGxTZXR0bGVkO1xuZnVuY3Rpb24gYWxsU2V0dGxlZChwcm9taXNlcykge1xuICAgIHJldHVybiBRKHByb21pc2VzKS5hbGxTZXR0bGVkKCk7XG59XG5cbi8qKlxuICogVHVybnMgYW4gYXJyYXkgb2YgcHJvbWlzZXMgaW50byBhIHByb21pc2UgZm9yIGFuIGFycmF5IG9mIHRoZWlyIHN0YXRlcyAoYXNcbiAqIHJldHVybmVkIGJ5IGBpbnNwZWN0YCkgd2hlbiB0aGV5IGhhdmUgYWxsIHNldHRsZWQuXG4gKiBAcGFyYW0ge0FycmF5W0FueSpdfSB2YWx1ZXMgYW4gYXJyYXkgKG9yIHByb21pc2UgZm9yIGFuIGFycmF5KSBvZiB2YWx1ZXMgKG9yXG4gKiBwcm9taXNlcyBmb3IgdmFsdWVzKVxuICogQHJldHVybnMge0FycmF5W1N0YXRlXX0gYW4gYXJyYXkgb2Ygc3RhdGVzIGZvciB0aGUgcmVzcGVjdGl2ZSB2YWx1ZXMuXG4gKi9cblByb21pc2UucHJvdG90eXBlLmFsbFNldHRsZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMudGhlbihmdW5jdGlvbiAocHJvbWlzZXMpIHtcbiAgICAgICAgcmV0dXJuIGFsbChhcnJheV9tYXAocHJvbWlzZXMsIGZ1bmN0aW9uIChwcm9taXNlKSB7XG4gICAgICAgICAgICBwcm9taXNlID0gUShwcm9taXNlKTtcbiAgICAgICAgICAgIGZ1bmN0aW9uIHJlZ2FyZGxlc3MoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByb21pc2UuaW5zcGVjdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHByb21pc2UudGhlbihyZWdhcmRsZXNzLCByZWdhcmRsZXNzKTtcbiAgICAgICAgfSkpO1xuICAgIH0pO1xufTtcblxuLyoqXG4gKiBDYXB0dXJlcyB0aGUgZmFpbHVyZSBvZiBhIHByb21pc2UsIGdpdmluZyBhbiBvcG9ydHVuaXR5IHRvIHJlY292ZXJcbiAqIHdpdGggYSBjYWxsYmFjay4gIElmIHRoZSBnaXZlbiBwcm9taXNlIGlzIGZ1bGZpbGxlZCwgdGhlIHJldHVybmVkXG4gKiBwcm9taXNlIGlzIGZ1bGZpbGxlZC5cbiAqIEBwYXJhbSB7QW55Kn0gcHJvbWlzZSBmb3Igc29tZXRoaW5nXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayB0byBmdWxmaWxsIHRoZSByZXR1cm5lZCBwcm9taXNlIGlmIHRoZVxuICogZ2l2ZW4gcHJvbWlzZSBpcyByZWplY3RlZFxuICogQHJldHVybnMgYSBwcm9taXNlIGZvciB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBjYWxsYmFja1xuICovXG5RLmZhaWwgPSAvLyBYWFggbGVnYWN5XG5RW1wiY2F0Y2hcIl0gPSBmdW5jdGlvbiAob2JqZWN0LCByZWplY3RlZCkge1xuICAgIHJldHVybiBRKG9iamVjdCkudGhlbih2b2lkIDAsIHJlamVjdGVkKTtcbn07XG5cblByb21pc2UucHJvdG90eXBlLmZhaWwgPSAvLyBYWFggbGVnYWN5XG5Qcm9taXNlLnByb3RvdHlwZVtcImNhdGNoXCJdID0gZnVuY3Rpb24gKHJlamVjdGVkKSB7XG4gICAgcmV0dXJuIHRoaXMudGhlbih2b2lkIDAsIHJlamVjdGVkKTtcbn07XG5cbi8qKlxuICogQXR0YWNoZXMgYSBsaXN0ZW5lciB0aGF0IGNhbiByZXNwb25kIHRvIHByb2dyZXNzIG5vdGlmaWNhdGlvbnMgZnJvbSBhXG4gKiBwcm9taXNlJ3Mgb3JpZ2luYXRpbmcgZGVmZXJyZWQuIFRoaXMgbGlzdGVuZXIgcmVjZWl2ZXMgdGhlIGV4YWN0IGFyZ3VtZW50c1xuICogcGFzc2VkIHRvIGBgZGVmZXJyZWQubm90aWZ5YGAuXG4gKiBAcGFyYW0ge0FueSp9IHByb21pc2UgZm9yIHNvbWV0aGluZ1xuICogQHBhcmFtIHtGdW5jdGlvbn0gY2FsbGJhY2sgdG8gcmVjZWl2ZSBhbnkgcHJvZ3Jlc3Mgbm90aWZpY2F0aW9uc1xuICogQHJldHVybnMgdGhlIGdpdmVuIHByb21pc2UsIHVuY2hhbmdlZFxuICovXG5RLnByb2dyZXNzID0gcHJvZ3Jlc3M7XG5mdW5jdGlvbiBwcm9ncmVzcyhvYmplY3QsIHByb2dyZXNzZWQpIHtcbiAgICByZXR1cm4gUShvYmplY3QpLnRoZW4odm9pZCAwLCB2b2lkIDAsIHByb2dyZXNzZWQpO1xufVxuXG5Qcm9taXNlLnByb3RvdHlwZS5wcm9ncmVzcyA9IGZ1bmN0aW9uIChwcm9ncmVzc2VkKSB7XG4gICAgcmV0dXJuIHRoaXMudGhlbih2b2lkIDAsIHZvaWQgMCwgcHJvZ3Jlc3NlZCk7XG59O1xuXG4vKipcbiAqIFByb3ZpZGVzIGFuIG9wcG9ydHVuaXR5IHRvIG9ic2VydmUgdGhlIHNldHRsaW5nIG9mIGEgcHJvbWlzZSxcbiAqIHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGUgcHJvbWlzZSBpcyBmdWxmaWxsZWQgb3IgcmVqZWN0ZWQuICBGb3J3YXJkc1xuICogdGhlIHJlc29sdXRpb24gdG8gdGhlIHJldHVybmVkIHByb21pc2Ugd2hlbiB0aGUgY2FsbGJhY2sgaXMgZG9uZS5cbiAqIFRoZSBjYWxsYmFjayBjYW4gcmV0dXJuIGEgcHJvbWlzZSB0byBkZWZlciBjb21wbGV0aW9uLlxuICogQHBhcmFtIHtBbnkqfSBwcm9taXNlXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBjYWxsYmFjayB0byBvYnNlcnZlIHRoZSByZXNvbHV0aW9uIG9mIHRoZSBnaXZlblxuICogcHJvbWlzZSwgdGFrZXMgbm8gYXJndW1lbnRzLlxuICogQHJldHVybnMgYSBwcm9taXNlIGZvciB0aGUgcmVzb2x1dGlvbiBvZiB0aGUgZ2l2ZW4gcHJvbWlzZSB3aGVuXG4gKiBgYGZpbmBgIGlzIGRvbmUuXG4gKi9cblEuZmluID0gLy8gWFhYIGxlZ2FjeVxuUVtcImZpbmFsbHlcIl0gPSBmdW5jdGlvbiAob2JqZWN0LCBjYWxsYmFjaykge1xuICAgIHJldHVybiBRKG9iamVjdClbXCJmaW5hbGx5XCJdKGNhbGxiYWNrKTtcbn07XG5cblByb21pc2UucHJvdG90eXBlLmZpbiA9IC8vIFhYWCBsZWdhY3lcblByb21pc2UucHJvdG90eXBlW1wiZmluYWxseVwiXSA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIGNhbGxiYWNrID0gUShjYWxsYmFjayk7XG4gICAgcmV0dXJuIHRoaXMudGhlbihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrLmZjYWxsKCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH0pO1xuICAgIH0sIGZ1bmN0aW9uIChyZWFzb24pIHtcbiAgICAgICAgLy8gVE9ETyBhdHRlbXB0IHRvIHJlY3ljbGUgdGhlIHJlamVjdGlvbiB3aXRoIFwidGhpc1wiLlxuICAgICAgICByZXR1cm4gY2FsbGJhY2suZmNhbGwoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRocm93IHJlYXNvbjtcbiAgICAgICAgfSk7XG4gICAgfSk7XG59O1xuXG4vKipcbiAqIFRlcm1pbmF0ZXMgYSBjaGFpbiBvZiBwcm9taXNlcywgZm9yY2luZyByZWplY3Rpb25zIHRvIGJlXG4gKiB0aHJvd24gYXMgZXhjZXB0aW9ucy5cbiAqIEBwYXJhbSB7QW55Kn0gcHJvbWlzZSBhdCB0aGUgZW5kIG9mIGEgY2hhaW4gb2YgcHJvbWlzZXNcbiAqIEByZXR1cm5zIG5vdGhpbmdcbiAqL1xuUS5kb25lID0gZnVuY3Rpb24gKG9iamVjdCwgZnVsZmlsbGVkLCByZWplY3RlZCwgcHJvZ3Jlc3MpIHtcbiAgICByZXR1cm4gUShvYmplY3QpLmRvbmUoZnVsZmlsbGVkLCByZWplY3RlZCwgcHJvZ3Jlc3MpO1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUuZG9uZSA9IGZ1bmN0aW9uIChmdWxmaWxsZWQsIHJlamVjdGVkLCBwcm9ncmVzcykge1xuICAgIHZhciBvblVuaGFuZGxlZEVycm9yID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgIC8vIGZvcndhcmQgdG8gYSBmdXR1cmUgdHVybiBzbyB0aGF0IGBgd2hlbmBgXG4gICAgICAgIC8vIGRvZXMgbm90IGNhdGNoIGl0IGFuZCB0dXJuIGl0IGludG8gYSByZWplY3Rpb24uXG4gICAgICAgIFEubmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgbWFrZVN0YWNrVHJhY2VMb25nKGVycm9yLCBwcm9taXNlKTtcbiAgICAgICAgICAgIGlmIChRLm9uZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBRLm9uZXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8vIEF2b2lkIHVubmVjZXNzYXJ5IGBuZXh0VGlja2BpbmcgdmlhIGFuIHVubmVjZXNzYXJ5IGB3aGVuYC5cbiAgICB2YXIgcHJvbWlzZSA9IGZ1bGZpbGxlZCB8fCByZWplY3RlZCB8fCBwcm9ncmVzcyA/XG4gICAgICAgIHRoaXMudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkLCBwcm9ncmVzcykgOlxuICAgICAgICB0aGlzO1xuXG4gICAgaWYgKHR5cGVvZiBwcm9jZXNzID09PSBcIm9iamVjdFwiICYmIHByb2Nlc3MgJiYgcHJvY2Vzcy5kb21haW4pIHtcbiAgICAgICAgb25VbmhhbmRsZWRFcnJvciA9IHByb2Nlc3MuZG9tYWluLmJpbmQob25VbmhhbmRsZWRFcnJvcik7XG4gICAgfVxuXG4gICAgcHJvbWlzZS50aGVuKHZvaWQgMCwgb25VbmhhbmRsZWRFcnJvcik7XG59O1xuXG4vKipcbiAqIENhdXNlcyBhIHByb21pc2UgdG8gYmUgcmVqZWN0ZWQgaWYgaXQgZG9lcyBub3QgZ2V0IGZ1bGZpbGxlZCBiZWZvcmVcbiAqIHNvbWUgbWlsbGlzZWNvbmRzIHRpbWUgb3V0LlxuICogQHBhcmFtIHtBbnkqfSBwcm9taXNlXG4gKiBAcGFyYW0ge051bWJlcn0gbWlsbGlzZWNvbmRzIHRpbWVvdXRcbiAqIEBwYXJhbSB7QW55Kn0gY3VzdG9tIGVycm9yIG1lc3NhZ2Ugb3IgRXJyb3Igb2JqZWN0IChvcHRpb25hbClcbiAqIEByZXR1cm5zIGEgcHJvbWlzZSBmb3IgdGhlIHJlc29sdXRpb24gb2YgdGhlIGdpdmVuIHByb21pc2UgaWYgaXQgaXNcbiAqIGZ1bGZpbGxlZCBiZWZvcmUgdGhlIHRpbWVvdXQsIG90aGVyd2lzZSByZWplY3RlZC5cbiAqL1xuUS50aW1lb3V0ID0gZnVuY3Rpb24gKG9iamVjdCwgbXMsIGVycm9yKSB7XG4gICAgcmV0dXJuIFEob2JqZWN0KS50aW1lb3V0KG1zLCBlcnJvcik7XG59O1xuXG5Qcm9taXNlLnByb3RvdHlwZS50aW1lb3V0ID0gZnVuY3Rpb24gKG1zLCBlcnJvcikge1xuICAgIHZhciBkZWZlcnJlZCA9IGRlZmVyKCk7XG4gICAgdmFyIHRpbWVvdXRJZCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIWVycm9yIHx8IFwic3RyaW5nXCIgPT09IHR5cGVvZiBlcnJvcikge1xuICAgICAgICAgICAgZXJyb3IgPSBuZXcgRXJyb3IoZXJyb3IgfHwgXCJUaW1lZCBvdXQgYWZ0ZXIgXCIgKyBtcyArIFwiIG1zXCIpO1xuICAgICAgICAgICAgZXJyb3IuY29kZSA9IFwiRVRJTUVET1VUXCI7XG4gICAgICAgIH1cbiAgICAgICAgZGVmZXJyZWQucmVqZWN0KGVycm9yKTtcbiAgICB9LCBtcyk7XG5cbiAgICB0aGlzLnRoZW4oZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpO1xuICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKHZhbHVlKTtcbiAgICB9LCBmdW5jdGlvbiAoZXhjZXB0aW9uKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0SWQpO1xuICAgICAgICBkZWZlcnJlZC5yZWplY3QoZXhjZXB0aW9uKTtcbiAgICB9LCBkZWZlcnJlZC5ub3RpZnkpO1xuXG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG59O1xuXG4vKipcbiAqIFJldHVybnMgYSBwcm9taXNlIGZvciB0aGUgZ2l2ZW4gdmFsdWUgKG9yIHByb21pc2VkIHZhbHVlKSwgc29tZVxuICogbWlsbGlzZWNvbmRzIGFmdGVyIGl0IHJlc29sdmVkLiBQYXNzZXMgcmVqZWN0aW9ucyBpbW1lZGlhdGVseS5cbiAqIEBwYXJhbSB7QW55Kn0gcHJvbWlzZVxuICogQHBhcmFtIHtOdW1iZXJ9IG1pbGxpc2Vjb25kc1xuICogQHJldHVybnMgYSBwcm9taXNlIGZvciB0aGUgcmVzb2x1dGlvbiBvZiB0aGUgZ2l2ZW4gcHJvbWlzZSBhZnRlciBtaWxsaXNlY29uZHNcbiAqIHRpbWUgaGFzIGVsYXBzZWQgc2luY2UgdGhlIHJlc29sdXRpb24gb2YgdGhlIGdpdmVuIHByb21pc2UuXG4gKiBJZiB0aGUgZ2l2ZW4gcHJvbWlzZSByZWplY3RzLCB0aGF0IGlzIHBhc3NlZCBpbW1lZGlhdGVseS5cbiAqL1xuUS5kZWxheSA9IGZ1bmN0aW9uIChvYmplY3QsIHRpbWVvdXQpIHtcbiAgICBpZiAodGltZW91dCA9PT0gdm9pZCAwKSB7XG4gICAgICAgIHRpbWVvdXQgPSBvYmplY3Q7XG4gICAgICAgIG9iamVjdCA9IHZvaWQgMDtcbiAgICB9XG4gICAgcmV0dXJuIFEob2JqZWN0KS5kZWxheSh0aW1lb3V0KTtcbn07XG5cblByb21pc2UucHJvdG90eXBlLmRlbGF5ID0gZnVuY3Rpb24gKHRpbWVvdXQpIHtcbiAgICByZXR1cm4gdGhpcy50aGVuKGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB2YXIgZGVmZXJyZWQgPSBkZWZlcigpO1xuICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUodmFsdWUpO1xuICAgICAgICB9LCB0aW1lb3V0KTtcbiAgICAgICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG4gICAgfSk7XG59O1xuXG4vKipcbiAqIFBhc3NlcyBhIGNvbnRpbnVhdGlvbiB0byBhIE5vZGUgZnVuY3Rpb24sIHdoaWNoIGlzIGNhbGxlZCB3aXRoIHRoZSBnaXZlblxuICogYXJndW1lbnRzIHByb3ZpZGVkIGFzIGFuIGFycmF5LCBhbmQgcmV0dXJucyBhIHByb21pc2UuXG4gKlxuICogICAgICBRLm5mYXBwbHkoRlMucmVhZEZpbGUsIFtfX2ZpbGVuYW1lXSlcbiAqICAgICAgLnRoZW4oZnVuY3Rpb24gKGNvbnRlbnQpIHtcbiAqICAgICAgfSlcbiAqXG4gKi9cblEubmZhcHBseSA9IGZ1bmN0aW9uIChjYWxsYmFjaywgYXJncykge1xuICAgIHJldHVybiBRKGNhbGxiYWNrKS5uZmFwcGx5KGFyZ3MpO1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUubmZhcHBseSA9IGZ1bmN0aW9uIChhcmdzKSB7XG4gICAgdmFyIGRlZmVycmVkID0gZGVmZXIoKTtcbiAgICB2YXIgbm9kZUFyZ3MgPSBhcnJheV9zbGljZShhcmdzKTtcbiAgICBub2RlQXJncy5wdXNoKGRlZmVycmVkLm1ha2VOb2RlUmVzb2x2ZXIoKSk7XG4gICAgdGhpcy5mYXBwbHkobm9kZUFyZ3MpLmZhaWwoZGVmZXJyZWQucmVqZWN0KTtcbiAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZTtcbn07XG5cbi8qKlxuICogUGFzc2VzIGEgY29udGludWF0aW9uIHRvIGEgTm9kZSBmdW5jdGlvbiwgd2hpY2ggaXMgY2FsbGVkIHdpdGggdGhlIGdpdmVuXG4gKiBhcmd1bWVudHMgcHJvdmlkZWQgaW5kaXZpZHVhbGx5LCBhbmQgcmV0dXJucyBhIHByb21pc2UuXG4gKiBAZXhhbXBsZVxuICogUS5uZmNhbGwoRlMucmVhZEZpbGUsIF9fZmlsZW5hbWUpXG4gKiAudGhlbihmdW5jdGlvbiAoY29udGVudCkge1xuICogfSlcbiAqXG4gKi9cblEubmZjYWxsID0gZnVuY3Rpb24gKGNhbGxiYWNrIC8qLi4uYXJncyovKSB7XG4gICAgdmFyIGFyZ3MgPSBhcnJheV9zbGljZShhcmd1bWVudHMsIDEpO1xuICAgIHJldHVybiBRKGNhbGxiYWNrKS5uZmFwcGx5KGFyZ3MpO1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUubmZjYWxsID0gZnVuY3Rpb24gKC8qLi4uYXJncyovKSB7XG4gICAgdmFyIG5vZGVBcmdzID0gYXJyYXlfc2xpY2UoYXJndW1lbnRzKTtcbiAgICB2YXIgZGVmZXJyZWQgPSBkZWZlcigpO1xuICAgIG5vZGVBcmdzLnB1c2goZGVmZXJyZWQubWFrZU5vZGVSZXNvbHZlcigpKTtcbiAgICB0aGlzLmZhcHBseShub2RlQXJncykuZmFpbChkZWZlcnJlZC5yZWplY3QpO1xuICAgIHJldHVybiBkZWZlcnJlZC5wcm9taXNlO1xufTtcblxuLyoqXG4gKiBXcmFwcyBhIE5vZGVKUyBjb250aW51YXRpb24gcGFzc2luZyBmdW5jdGlvbiBhbmQgcmV0dXJucyBhbiBlcXVpdmFsZW50XG4gKiB2ZXJzaW9uIHRoYXQgcmV0dXJucyBhIHByb21pc2UuXG4gKiBAZXhhbXBsZVxuICogUS5uZmJpbmQoRlMucmVhZEZpbGUsIF9fZmlsZW5hbWUpKFwidXRmLThcIilcbiAqIC50aGVuKGNvbnNvbGUubG9nKVxuICogLmRvbmUoKVxuICovXG5RLm5mYmluZCA9XG5RLmRlbm9kZWlmeSA9IGZ1bmN0aW9uIChjYWxsYmFjayAvKi4uLmFyZ3MqLykge1xuICAgIHZhciBiYXNlQXJncyA9IGFycmF5X3NsaWNlKGFyZ3VtZW50cywgMSk7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5vZGVBcmdzID0gYmFzZUFyZ3MuY29uY2F0KGFycmF5X3NsaWNlKGFyZ3VtZW50cykpO1xuICAgICAgICB2YXIgZGVmZXJyZWQgPSBkZWZlcigpO1xuICAgICAgICBub2RlQXJncy5wdXNoKGRlZmVycmVkLm1ha2VOb2RlUmVzb2x2ZXIoKSk7XG4gICAgICAgIFEoY2FsbGJhY2spLmZhcHBseShub2RlQXJncykuZmFpbChkZWZlcnJlZC5yZWplY3QpO1xuICAgICAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZTtcbiAgICB9O1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUubmZiaW5kID1cblByb21pc2UucHJvdG90eXBlLmRlbm9kZWlmeSA9IGZ1bmN0aW9uICgvKi4uLmFyZ3MqLykge1xuICAgIHZhciBhcmdzID0gYXJyYXlfc2xpY2UoYXJndW1lbnRzKTtcbiAgICBhcmdzLnVuc2hpZnQodGhpcyk7XG4gICAgcmV0dXJuIFEuZGVub2RlaWZ5LmFwcGx5KHZvaWQgMCwgYXJncyk7XG59O1xuXG5RLm5iaW5kID0gZnVuY3Rpb24gKGNhbGxiYWNrLCB0aGlzcCAvKi4uLmFyZ3MqLykge1xuICAgIHZhciBiYXNlQXJncyA9IGFycmF5X3NsaWNlKGFyZ3VtZW50cywgMik7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG5vZGVBcmdzID0gYmFzZUFyZ3MuY29uY2F0KGFycmF5X3NsaWNlKGFyZ3VtZW50cykpO1xuICAgICAgICB2YXIgZGVmZXJyZWQgPSBkZWZlcigpO1xuICAgICAgICBub2RlQXJncy5wdXNoKGRlZmVycmVkLm1ha2VOb2RlUmVzb2x2ZXIoKSk7XG4gICAgICAgIGZ1bmN0aW9uIGJvdW5kKCkge1xuICAgICAgICAgICAgcmV0dXJuIGNhbGxiYWNrLmFwcGx5KHRoaXNwLCBhcmd1bWVudHMpO1xuICAgICAgICB9XG4gICAgICAgIFEoYm91bmQpLmZhcHBseShub2RlQXJncykuZmFpbChkZWZlcnJlZC5yZWplY3QpO1xuICAgICAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZTtcbiAgICB9O1xufTtcblxuUHJvbWlzZS5wcm90b3R5cGUubmJpbmQgPSBmdW5jdGlvbiAoLyp0aGlzcCwgLi4uYXJncyovKSB7XG4gICAgdmFyIGFyZ3MgPSBhcnJheV9zbGljZShhcmd1bWVudHMsIDApO1xuICAgIGFyZ3MudW5zaGlmdCh0aGlzKTtcbiAgICByZXR1cm4gUS5uYmluZC5hcHBseSh2b2lkIDAsIGFyZ3MpO1xufTtcblxuLyoqXG4gKiBDYWxscyBhIG1ldGhvZCBvZiBhIE5vZGUtc3R5bGUgb2JqZWN0IHRoYXQgYWNjZXB0cyBhIE5vZGUtc3R5bGVcbiAqIGNhbGxiYWNrIHdpdGggYSBnaXZlbiBhcnJheSBvZiBhcmd1bWVudHMsIHBsdXMgYSBwcm92aWRlZCBjYWxsYmFjay5cbiAqIEBwYXJhbSBvYmplY3QgYW4gb2JqZWN0IHRoYXQgaGFzIHRoZSBuYW1lZCBtZXRob2RcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIG5hbWUgb2YgdGhlIG1ldGhvZCBvZiBvYmplY3RcbiAqIEBwYXJhbSB7QXJyYXl9IGFyZ3MgYXJndW1lbnRzIHRvIHBhc3MgdG8gdGhlIG1ldGhvZDsgdGhlIGNhbGxiYWNrXG4gKiB3aWxsIGJlIHByb3ZpZGVkIGJ5IFEgYW5kIGFwcGVuZGVkIHRvIHRoZXNlIGFyZ3VtZW50cy5cbiAqIEByZXR1cm5zIGEgcHJvbWlzZSBmb3IgdGhlIHZhbHVlIG9yIGVycm9yXG4gKi9cblEubm1hcHBseSA9IC8vIFhYWCBBcyBwcm9wb3NlZCBieSBcIlJlZHNhbmRyb1wiXG5RLm5wb3N0ID0gZnVuY3Rpb24gKG9iamVjdCwgbmFtZSwgYXJncykge1xuICAgIHJldHVybiBRKG9iamVjdCkubnBvc3QobmFtZSwgYXJncyk7XG59O1xuXG5Qcm9taXNlLnByb3RvdHlwZS5ubWFwcGx5ID0gLy8gWFhYIEFzIHByb3Bvc2VkIGJ5IFwiUmVkc2FuZHJvXCJcblByb21pc2UucHJvdG90eXBlLm5wb3N0ID0gZnVuY3Rpb24gKG5hbWUsIGFyZ3MpIHtcbiAgICB2YXIgbm9kZUFyZ3MgPSBhcnJheV9zbGljZShhcmdzIHx8IFtdKTtcbiAgICB2YXIgZGVmZXJyZWQgPSBkZWZlcigpO1xuICAgIG5vZGVBcmdzLnB1c2goZGVmZXJyZWQubWFrZU5vZGVSZXNvbHZlcigpKTtcbiAgICB0aGlzLmRpc3BhdGNoKFwicG9zdFwiLCBbbmFtZSwgbm9kZUFyZ3NdKS5mYWlsKGRlZmVycmVkLnJlamVjdCk7XG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG59O1xuXG4vKipcbiAqIENhbGxzIGEgbWV0aG9kIG9mIGEgTm9kZS1zdHlsZSBvYmplY3QgdGhhdCBhY2NlcHRzIGEgTm9kZS1zdHlsZVxuICogY2FsbGJhY2ssIGZvcndhcmRpbmcgdGhlIGdpdmVuIHZhcmlhZGljIGFyZ3VtZW50cywgcGx1cyBhIHByb3ZpZGVkXG4gKiBjYWxsYmFjayBhcmd1bWVudC5cbiAqIEBwYXJhbSBvYmplY3QgYW4gb2JqZWN0IHRoYXQgaGFzIHRoZSBuYW1lZCBtZXRob2RcbiAqIEBwYXJhbSB7U3RyaW5nfSBuYW1lIG5hbWUgb2YgdGhlIG1ldGhvZCBvZiBvYmplY3RcbiAqIEBwYXJhbSAuLi5hcmdzIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2Q7IHRoZSBjYWxsYmFjayB3aWxsXG4gKiBiZSBwcm92aWRlZCBieSBRIGFuZCBhcHBlbmRlZCB0byB0aGVzZSBhcmd1bWVudHMuXG4gKiBAcmV0dXJucyBhIHByb21pc2UgZm9yIHRoZSB2YWx1ZSBvciBlcnJvclxuICovXG5RLm5zZW5kID0gLy8gWFhYIEJhc2VkIG9uIE1hcmsgTWlsbGVyJ3MgcHJvcG9zZWQgXCJzZW5kXCJcblEubm1jYWxsID0gLy8gWFhYIEJhc2VkIG9uIFwiUmVkc2FuZHJvJ3NcIiBwcm9wb3NhbFxuUS5uaW52b2tlID0gZnVuY3Rpb24gKG9iamVjdCwgbmFtZSAvKi4uLmFyZ3MqLykge1xuICAgIHZhciBub2RlQXJncyA9IGFycmF5X3NsaWNlKGFyZ3VtZW50cywgMik7XG4gICAgdmFyIGRlZmVycmVkID0gZGVmZXIoKTtcbiAgICBub2RlQXJncy5wdXNoKGRlZmVycmVkLm1ha2VOb2RlUmVzb2x2ZXIoKSk7XG4gICAgUShvYmplY3QpLmRpc3BhdGNoKFwicG9zdFwiLCBbbmFtZSwgbm9kZUFyZ3NdKS5mYWlsKGRlZmVycmVkLnJlamVjdCk7XG4gICAgcmV0dXJuIGRlZmVycmVkLnByb21pc2U7XG59O1xuXG5Qcm9taXNlLnByb3RvdHlwZS5uc2VuZCA9IC8vIFhYWCBCYXNlZCBvbiBNYXJrIE1pbGxlcidzIHByb3Bvc2VkIFwic2VuZFwiXG5Qcm9taXNlLnByb3RvdHlwZS5ubWNhbGwgPSAvLyBYWFggQmFzZWQgb24gXCJSZWRzYW5kcm8nc1wiIHByb3Bvc2FsXG5Qcm9taXNlLnByb3RvdHlwZS5uaW52b2tlID0gZnVuY3Rpb24gKG5hbWUgLyouLi5hcmdzKi8pIHtcbiAgICB2YXIgbm9kZUFyZ3MgPSBhcnJheV9zbGljZShhcmd1bWVudHMsIDEpO1xuICAgIHZhciBkZWZlcnJlZCA9IGRlZmVyKCk7XG4gICAgbm9kZUFyZ3MucHVzaChkZWZlcnJlZC5tYWtlTm9kZVJlc29sdmVyKCkpO1xuICAgIHRoaXMuZGlzcGF0Y2goXCJwb3N0XCIsIFtuYW1lLCBub2RlQXJnc10pLmZhaWwoZGVmZXJyZWQucmVqZWN0KTtcbiAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZTtcbn07XG5cbi8qKlxuICogSWYgYSBmdW5jdGlvbiB3b3VsZCBsaWtlIHRvIHN1cHBvcnQgYm90aCBOb2RlIGNvbnRpbnVhdGlvbi1wYXNzaW5nLXN0eWxlIGFuZFxuICogcHJvbWlzZS1yZXR1cm5pbmctc3R5bGUsIGl0IGNhbiBlbmQgaXRzIGludGVybmFsIHByb21pc2UgY2hhaW4gd2l0aFxuICogYG5vZGVpZnkobm9kZWJhY2spYCwgZm9yd2FyZGluZyB0aGUgb3B0aW9uYWwgbm9kZWJhY2sgYXJndW1lbnQuICBJZiB0aGUgdXNlclxuICogZWxlY3RzIHRvIHVzZSBhIG5vZGViYWNrLCB0aGUgcmVzdWx0IHdpbGwgYmUgc2VudCB0aGVyZS4gIElmIHRoZXkgZG8gbm90XG4gKiBwYXNzIGEgbm9kZWJhY2ssIHRoZXkgd2lsbCByZWNlaXZlIHRoZSByZXN1bHQgcHJvbWlzZS5cbiAqIEBwYXJhbSBvYmplY3QgYSByZXN1bHQgKG9yIGEgcHJvbWlzZSBmb3IgYSByZXN1bHQpXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBub2RlYmFjayBhIE5vZGUuanMtc3R5bGUgY2FsbGJhY2tcbiAqIEByZXR1cm5zIGVpdGhlciB0aGUgcHJvbWlzZSBvciBub3RoaW5nXG4gKi9cblEubm9kZWlmeSA9IG5vZGVpZnk7XG5mdW5jdGlvbiBub2RlaWZ5KG9iamVjdCwgbm9kZWJhY2spIHtcbiAgICByZXR1cm4gUShvYmplY3QpLm5vZGVpZnkobm9kZWJhY2spO1xufVxuXG5Qcm9taXNlLnByb3RvdHlwZS5ub2RlaWZ5ID0gZnVuY3Rpb24gKG5vZGViYWNrKSB7XG4gICAgaWYgKG5vZGViYWNrKSB7XG4gICAgICAgIHRoaXMudGhlbihmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgIFEubmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIG5vZGViYWNrKG51bGwsIHZhbHVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9LCBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgIFEubmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIG5vZGViYWNrKGVycm9yKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG59O1xuXG5RLm5vQ29uZmxpY3QgPSBmdW5jdGlvbigpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJRLm5vQ29uZmxpY3Qgb25seSB3b3JrcyB3aGVuIFEgaXMgdXNlZCBhcyBhIGdsb2JhbFwiKTtcbn07XG5cbi8vIEFsbCBjb2RlIGJlZm9yZSB0aGlzIHBvaW50IHdpbGwgYmUgZmlsdGVyZWQgZnJvbSBzdGFjayB0cmFjZXMuXG52YXIgcUVuZGluZ0xpbmUgPSBjYXB0dXJlTGluZSgpO1xuXG5yZXR1cm4gUTtcblxufSk7XG5cbn0pLmNhbGwodGhpcyxyZXF1aXJlKCdfcHJvY2VzcycpKVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9ZGF0YTphcHBsaWNhdGlvbi9qc29uO2NoYXJzZXQ6dXRmLTg7YmFzZTY0LGV5SjJaWEp6YVc5dUlqb3pMQ0p6YjNWeVkyVnpJanBiSW01dlpHVmZiVzlrZFd4bGN5OXhMM0V1YW5NaVhTd2libUZ0WlhNaU9sdGRMQ0p0WVhCd2FXNW5jeUk2SWp0QlFVRkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFUdEJRVU5CTzBGQlEwRTdRVUZEUVR0QlFVTkJPMEZCUTBFN1FVRkRRVHRCUVVOQk8wRkJRMEU3UVVGRFFTSXNJbVpwYkdVaU9pSm5aVzVsY21GMFpXUXVhbk1pTENKemIzVnlZMlZTYjI5MElqb2lJaXdpYzI5MWNtTmxjME52Ym5SbGJuUWlPbHNpTHk4Z2RtbHRPblJ6UFRRNmMzUnpQVFE2YzNjOU5EcGNiaThxSVZ4dUlDcGNiaUFxSUVOdmNIbHlhV2RvZENBeU1EQTVMVEl3TVRJZ1MzSnBjeUJMYjNkaGJDQjFibVJsY2lCMGFHVWdkR1Z5YlhNZ2IyWWdkR2hsSUUxSlZGeHVJQ29nYkdsalpXNXpaU0JtYjNWdVpDQmhkQ0JvZEhSd09pOHZaMmwwYUhWaUxtTnZiUzlyY21semEyOTNZV3d2Y1M5eVlYY3ZiV0Z6ZEdWeUwweEpRMFZPVTBWY2JpQXFYRzRnS2lCWGFYUm9JSEJoY25SeklHSjVJRlI1YkdWeUlFTnNiM05sWEc0Z0tpQkRiM0I1Y21sbmFIUWdNakF3TnkweU1EQTVJRlI1YkdWeUlFTnNiM05sSUhWdVpHVnlJSFJvWlNCMFpYSnRjeUJ2WmlCMGFHVWdUVWxVSUZnZ2JHbGpaVzV6WlNCbWIzVnVaRnh1SUNvZ1lYUWdhSFIwY0RvdkwzZDNkeTV2Y0dWdWMyOTFjbU5sTG05eVp5OXNhV05sYm5ObGN5OXRhWFF0YkdsalpXNXpaUzVvZEcxc1hHNGdLaUJHYjNKclpXUWdZWFFnY21WbVgzTmxibVF1YW5NZ2RtVnljMmx2YmpvZ01qQXdPUzB3TlMweE1WeHVJQ3BjYmlBcUlGZHBkR2dnY0dGeWRITWdZbmtnVFdGeWF5Qk5hV3hzWlhKY2JpQXFJRU52Y0hseWFXZG9kQ0FvUXlrZ01qQXhNU0JIYjI5bmJHVWdTVzVqTGx4dUlDcGNiaUFxSUV4cFkyVnVjMlZrSUhWdVpHVnlJSFJvWlNCQmNHRmphR1VnVEdsalpXNXpaU3dnVm1WeWMybHZiaUF5TGpBZ0tIUm9aU0JjSWt4cFkyVnVjMlZjSWlrN1hHNGdLaUI1YjNVZ2JXRjVJRzV2ZENCMWMyVWdkR2hwY3lCbWFXeGxJR1Y0WTJWd2RDQnBiaUJqYjIxd2JHbGhibU5sSUhkcGRHZ2dkR2hsSUV4cFkyVnVjMlV1WEc0Z0tpQlpiM1VnYldGNUlHOWlkR0ZwYmlCaElHTnZjSGtnYjJZZ2RHaGxJRXhwWTJWdWMyVWdZWFJjYmlBcVhHNGdLaUJvZEhSd09pOHZkM2QzTG1Gd1lXTm9aUzV2Y21jdmJHbGpaVzV6WlhNdlRFbERSVTVUUlMweUxqQmNiaUFxWEc0Z0tpQlZibXhsYzNNZ2NtVnhkV2x5WldRZ1lua2dZWEJ3YkdsallXSnNaU0JzWVhjZ2IzSWdZV2R5WldWa0lIUnZJR2x1SUhkeWFYUnBibWNzSUhOdlpuUjNZWEpsWEc0Z0tpQmthWE4wY21saWRYUmxaQ0IxYm1SbGNpQjBhR1VnVEdsalpXNXpaU0JwY3lCa2FYTjBjbWxpZFhSbFpDQnZiaUJoYmlCY0lrRlRJRWxUWENJZ1FrRlRTVk1zWEc0Z0tpQlhTVlJJVDFWVUlGZEJVbEpCVGxSSlJWTWdUMUlnUTA5T1JFbFVTVTlPVXlCUFJpQkJUbGtnUzBsT1JDd2daV2wwYUdWeUlHVjRjSEpsYzNNZ2IzSWdhVzF3YkdsbFpDNWNiaUFxSUZObFpTQjBhR1VnVEdsalpXNXpaU0JtYjNJZ2RHaGxJSE53WldOcFptbGpJR3hoYm1kMVlXZGxJR2R2ZG1WeWJtbHVaeUJ3WlhKdGFYTnphVzl1Y3lCaGJtUmNiaUFxSUd4cGJXbDBZWFJwYjI1eklIVnVaR1Z5SUhSb1pTQk1hV05sYm5ObExseHVJQ3BjYmlBcUwxeHVYRzRvWm5WdVkzUnBiMjRnS0dSbFptbHVhWFJwYjI0cElIdGNiaUFnSUNCY0luVnpaU0J6ZEhKcFkzUmNJanRjYmx4dUlDQWdJQzh2SUZSb2FYTWdabWxzWlNCM2FXeHNJR1oxYm1OMGFXOXVJSEJ5YjNCbGNteDVJR0Z6SUdFZ1BITmpjbWx3ZEQ0Z2RHRm5MQ0J2Y2lCaElHMXZaSFZzWlZ4dUlDQWdJQzh2SUhWemFXNW5JRU52YlcxdmJrcFRJR0Z1WkNCT2IyUmxTbE1nYjNJZ1VtVnhkV2x5WlVwVElHMXZaSFZzWlNCbWIzSnRZWFJ6TGlBZ1NXNWNiaUFnSUNBdkx5QkRiMjF0YjI0dlRtOWtaUzlTWlhGMWFYSmxTbE1zSUhSb1pTQnRiMlIxYkdVZ1pYaHdiM0owY3lCMGFHVWdVU0JCVUVrZ1lXNWtJSGRvWlc1Y2JpQWdJQ0F2THlCbGVHVmpkWFJsWkNCaGN5QmhJSE5wYlhCc1pTQThjMk55YVhCMFBpd2dhWFFnWTNKbFlYUmxjeUJoSUZFZ1oyeHZZbUZzSUdsdWMzUmxZV1F1WEc1Y2JpQWdJQ0F2THlCTmIyNTBZV2RsSUZKbGNYVnBjbVZjYmlBZ0lDQnBaaUFvZEhsd1pXOW1JR0p2YjNSemRISmhjQ0E5UFQwZ1hDSm1kVzVqZEdsdmJsd2lLU0I3WEc0Z0lDQWdJQ0FnSUdKdmIzUnpkSEpoY0NoY0luQnliMjFwYzJWY0lpd2daR1ZtYVc1cGRHbHZiaWs3WEc1Y2JpQWdJQ0F2THlCRGIyMXRiMjVLVTF4dUlDQWdJSDBnWld4elpTQnBaaUFvZEhsd1pXOW1JR1Y0Y0c5eWRITWdQVDA5SUZ3aWIySnFaV04wWENJZ0ppWWdkSGx3Wlc5bUlHMXZaSFZzWlNBOVBUMGdYQ0p2WW1wbFkzUmNJaWtnZTF4dUlDQWdJQ0FnSUNCdGIyUjFiR1V1Wlhod2IzSjBjeUE5SUdSbFptbHVhWFJwYjI0b0tUdGNibHh1SUNBZ0lDOHZJRkpsY1hWcGNtVktVMXh1SUNBZ0lIMGdaV3h6WlNCcFppQW9kSGx3Wlc5bUlHUmxabWx1WlNBOVBUMGdYQ0ptZFc1amRHbHZibHdpSUNZbUlHUmxabWx1WlM1aGJXUXBJSHRjYmlBZ0lDQWdJQ0FnWkdWbWFXNWxLR1JsWm1sdWFYUnBiMjRwTzF4dVhHNGdJQ0FnTHk4Z1UwVlRJQ2hUWldOMWNtVWdSV050WVZOamNtbHdkQ2xjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLSFI1Y0dWdlppQnpaWE1nSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lwSUh0Y2JpQWdJQ0FnSUNBZ2FXWWdLQ0Z6WlhNdWIyc29LU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjbVYwZFhKdU8xeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYzJWekxtMWhhMlZSSUQwZ1pHVm1hVzVwZEdsdmJqdGNiaUFnSUNBZ0lDQWdmVnh1WEc0Z0lDQWdMeThnUEhOamNtbHdkRDVjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLSFI1Y0dWdlppQjNhVzVrYjNjZ0lUMDlJRndpZFc1a1pXWnBibVZrWENJZ2ZId2dkSGx3Wlc5bUlITmxiR1lnSVQwOUlGd2lkVzVrWldacGJtVmtYQ0lwSUh0Y2JpQWdJQ0FnSUNBZ0x5OGdVSEpsWm1WeUlIZHBibVJ2ZHlCdmRtVnlJSE5sYkdZZ1ptOXlJR0ZrWkMxdmJpQnpZM0pwY0hSekxpQlZjMlVnYzJWc1ppQm1iM0pjYmlBZ0lDQWdJQ0FnTHk4Z2JtOXVMWGRwYm1SdmQyVmtJR052Ym5SbGVIUnpMbHh1SUNBZ0lDQWdJQ0IyWVhJZ1oyeHZZbUZzSUQwZ2RIbHdaVzltSUhkcGJtUnZkeUFoUFQwZ1hDSjFibVJsWm1sdVpXUmNJaUEvSUhkcGJtUnZkeUE2SUhObGJHWTdYRzVjYmlBZ0lDQWdJQ0FnTHk4Z1IyVjBJSFJvWlNCZ2QybHVaRzkzWUNCdlltcGxZM1FzSUhOaGRtVWdkR2hsSUhCeVpYWnBiM1Z6SUZFZ1oyeHZZbUZzWEc0Z0lDQWdJQ0FnSUM4dklHRnVaQ0JwYm1sMGFXRnNhWHBsSUZFZ1lYTWdZU0JuYkc5aVlXd3VYRzRnSUNBZ0lDQWdJSFpoY2lCd2NtVjJhVzkxYzFFZ1BTQm5iRzlpWVd3dVVUdGNiaUFnSUNBZ0lDQWdaMnh2WW1Gc0xsRWdQU0JrWldacGJtbDBhVzl1S0NrN1hHNWNiaUFnSUNBZ0lDQWdMeThnUVdSa0lHRWdibTlEYjI1bWJHbGpkQ0JtZFc1amRHbHZiaUJ6YnlCUklHTmhiaUJpWlNCeVpXMXZkbVZrSUdaeWIyMGdkR2hsWEc0Z0lDQWdJQ0FnSUM4dklHZHNiMkpoYkNCdVlXMWxjM0JoWTJVdVhHNGdJQ0FnSUNBZ0lHZHNiMkpoYkM1UkxtNXZRMjl1Wm14cFkzUWdQU0JtZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JuYkc5aVlXd3VVU0E5SUhCeVpYWnBiM1Z6VVR0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQjBhR2x6TzF4dUlDQWdJQ0FnSUNCOU8xeHVYRzRnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ2RHaHliM2NnYm1WM0lFVnljbTl5S0Z3aVZHaHBjeUJsYm5acGNtOXViV1Z1ZENCM1lYTWdibTkwSUdGdWRHbGphWEJoZEdWa0lHSjVJRkV1SUZCc1pXRnpaU0JtYVd4bElHRWdZblZuTGx3aUtUdGNiaUFnSUNCOVhHNWNibjBwS0daMWJtTjBhVzl1SUNncElIdGNibHdpZFhObElITjBjbWxqZEZ3aU8xeHVYRzUyWVhJZ2FHRnpVM1JoWTJ0eklEMGdabUZzYzJVN1hHNTBjbmtnZTF4dUlDQWdJSFJvY205M0lHNWxkeUJGY25KdmNpZ3BPMXh1ZlNCallYUmphQ0FvWlNrZ2UxeHVJQ0FnSUdoaGMxTjBZV05yY3lBOUlDRWhaUzV6ZEdGamF6dGNibjFjYmx4dUx5OGdRV3hzSUdOdlpHVWdZV1owWlhJZ2RHaHBjeUJ3YjJsdWRDQjNhV3hzSUdKbElHWnBiSFJsY21Wa0lHWnliMjBnYzNSaFkyc2dkSEpoWTJWeklISmxjRzl5ZEdWa1hHNHZMeUJpZVNCUkxseHVkbUZ5SUhGVGRHRnlkR2x1WjB4cGJtVWdQU0JqWVhCMGRYSmxUR2x1WlNncE8xeHVkbUZ5SUhGR2FXeGxUbUZ0WlR0Y2JseHVMeThnYzJocGJYTmNibHh1THk4Z2RYTmxaQ0JtYjNJZ1ptRnNiR0poWTJzZ2FXNGdYQ0poYkd4U1pYTnZiSFpsWkZ3aVhHNTJZWElnYm05dmNDQTlJR1oxYm1OMGFXOXVJQ2dwSUh0OU8xeHVYRzR2THlCVmMyVWdkR2hsSUdaaGMzUmxjM1FnY0c5emMybGliR1VnYldWaGJuTWdkRzhnWlhobFkzVjBaU0JoSUhSaGMyc2dhVzRnWVNCbWRYUjFjbVVnZEhWeWJseHVMeThnYjJZZ2RHaGxJR1YyWlc1MElHeHZiM0F1WEc1MllYSWdibVY0ZEZScFkyc2dQU2htZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnTHk4Z2JHbHVhMlZrSUd4cGMzUWdiMllnZEdGemEzTWdLSE5wYm1kc1pTd2dkMmwwYUNCb1pXRmtJRzV2WkdVcFhHNGdJQ0FnZG1GeUlHaGxZV1FnUFNCN2RHRnphem9nZG05cFpDQXdMQ0J1WlhoME9pQnVkV3hzZlR0Y2JpQWdJQ0IyWVhJZ2RHRnBiQ0E5SUdobFlXUTdYRzRnSUNBZ2RtRnlJR1pzZFhOb2FXNW5JRDBnWm1Gc2MyVTdYRzRnSUNBZ2RtRnlJSEpsY1hWbGMzUlVhV05ySUQwZ2RtOXBaQ0F3TzF4dUlDQWdJSFpoY2lCcGMwNXZaR1ZLVXlBOUlHWmhiSE5sTzF4dUlDQWdJQzh2SUhGMVpYVmxJR1p2Y2lCc1lYUmxJSFJoYzJ0ekxDQjFjMlZrSUdKNUlIVnVhR0Z1Wkd4bFpDQnlaV3BsWTNScGIyNGdkSEpoWTJ0cGJtZGNiaUFnSUNCMllYSWdiR0YwWlhKUmRXVjFaU0E5SUZ0ZE8xeHVYRzRnSUNBZ1puVnVZM1JwYjI0Z1pteDFjMmdvS1NCN1hHNGdJQ0FnSUNBZ0lDOHFJR3B6YUdsdWRDQnNiMjl3Wm5WdVl6b2dkSEoxWlNBcUwxeHVJQ0FnSUNBZ0lDQjJZWElnZEdGemF5d2daRzl0WVdsdU8xeHVYRzRnSUNBZ0lDQWdJSGRvYVd4bElDaG9aV0ZrTG01bGVIUXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHaGxZV1FnUFNCb1pXRmtMbTVsZUhRN1hHNGdJQ0FnSUNBZ0lDQWdJQ0IwWVhOcklEMGdhR1ZoWkM1MFlYTnJPMXh1SUNBZ0lDQWdJQ0FnSUNBZ2FHVmhaQzUwWVhOcklEMGdkbTlwWkNBd08xeHVJQ0FnSUNBZ0lDQWdJQ0FnWkc5dFlXbHVJRDBnYUdWaFpDNWtiMjFoYVc0N1hHNWNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaGtiMjFoYVc0cElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQm9aV0ZrTG1SdmJXRnBiaUE5SUhadmFXUWdNRHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JrYjIxaGFXNHVaVzUwWlhJb0tUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ0lDQWdJSEoxYmxOcGJtZHNaU2gwWVhOckxDQmtiMjFoYVc0cE8xeHVYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnZDJocGJHVWdLR3hoZEdWeVVYVmxkV1V1YkdWdVozUm9LU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjBZWE5ySUQwZ2JHRjBaWEpSZFdWMVpTNXdiM0FvS1R0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEoxYmxOcGJtZHNaU2gwWVhOcktUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0JtYkhWemFHbHVaeUE5SUdaaGJITmxPMXh1SUNBZ0lIMWNiaUFnSUNBdkx5QnlkVzV6SUdFZ2MybHVaMnhsSUdaMWJtTjBhVzl1SUdsdUlIUm9aU0JoYzNsdVl5QnhkV1YxWlZ4dUlDQWdJR1oxYm1OMGFXOXVJSEoxYmxOcGJtZHNaU2gwWVhOckxDQmtiMjFoYVc0cElIdGNiaUFnSUNBZ0lDQWdkSEo1SUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFJoYzJzb0tUdGNibHh1SUNBZ0lDQWdJQ0I5SUdOaGRHTm9JQ2hsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb2FYTk9iMlJsU2xNcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJKYmlCdWIyUmxMQ0IxYm1OaGRXZG9kQ0JsZUdObGNIUnBiMjV6SUdGeVpTQmpiMjV6YVdSbGNtVmtJR1poZEdGc0lHVnljbTl5Y3k1Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QlNaUzEwYUhKdmR5QjBhR1Z0SUhONWJtTm9jbTl1YjNWemJIa2dkRzhnYVc1MFpYSnlkWEIwSUdac2RYTm9hVzVuSVZ4dVhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0x5OGdSVzV6ZFhKbElHTnZiblJwYm5WaGRHbHZiaUJwWmlCMGFHVWdkVzVqWVhWbmFIUWdaWGhqWlhCMGFXOXVJR2x6SUhOMWNIQnlaWE56WldSY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBdkx5QnNhWE4wWlc1cGJtY2dYQ0oxYm1OaGRXZG9kRVY0WTJWd2RHbHZibHdpSUdWMlpXNTBjeUFvWVhNZ1pHOXRZV2x1Y3lCa2IyVnpLUzVjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0F2THlCRGIyNTBhVzUxWlNCcGJpQnVaWGgwSUdWMlpXNTBJSFJ2SUdGMmIybGtJSFJwWTJzZ2NtVmpkWEp6YVc5dUxseHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2hrYjIxaGFXNHBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1pHOXRZV2x1TG1WNGFYUW9LVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnYzJWMFZHbHRaVzkxZENobWJIVnphQ3dnTUNrN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR1J2YldGcGJpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCa2IyMWhhVzR1Wlc1MFpYSW9LVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5WEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMGFISnZkeUJsTzF4dVhHNGdJQ0FnSUNBZ0lDQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUVsdUlHSnliM2R6WlhKekxDQjFibU5oZFdkb2RDQmxlR05sY0hScGIyNXpJR0Z5WlNCdWIzUWdabUYwWVd3dVhHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0x5OGdVbVV0ZEdoeWIzY2dkR2hsYlNCaGMzbHVZMmh5YjI1dmRYTnNlU0IwYnlCaGRtOXBaQ0J6Ykc5M0xXUnZkMjV6TGx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhObGRGUnBiV1Z2ZFhRb1puVnVZM1JwYjI0Z0tDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMGFISnZkeUJsTzF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUgwc0lEQXBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQWdJQ0FnYVdZZ0tHUnZiV0ZwYmlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnWkc5dFlXbHVMbVY0YVhRb0tUdGNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lIMWNibHh1SUNBZ0lHNWxlSFJVYVdOcklEMGdablZ1WTNScGIyNGdLSFJoYzJzcElIdGNiaUFnSUNBZ0lDQWdkR0ZwYkNBOUlIUmhhV3d1Ym1WNGRDQTlJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIUmhjMnM2SUhSaGMyc3NYRzRnSUNBZ0lDQWdJQ0FnSUNCa2IyMWhhVzQ2SUdselRtOWtaVXBUSUNZbUlIQnliMk5sYzNNdVpHOXRZV2x1TEZ4dUlDQWdJQ0FnSUNBZ0lDQWdibVY0ZERvZ2JuVnNiRnh1SUNBZ0lDQWdJQ0I5TzF4dVhHNGdJQ0FnSUNBZ0lHbG1JQ2doWm14MWMyaHBibWNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR1pzZFhOb2FXNW5JRDBnZEhKMVpUdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGNYVmxjM1JVYVdOcktDazdYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlPMXh1WEc0Z0lDQWdhV1lnS0hSNWNHVnZaaUJ3Y205alpYTnpJRDA5UFNCY0ltOWlhbVZqZEZ3aUlDWW1YRzRnSUNBZ0lDQWdJSEJ5YjJObGMzTXVkRzlUZEhKcGJtY29LU0E5UFQwZ1hDSmJiMkpxWldOMElIQnliMk5sYzNOZFhDSWdKaVlnY0hKdlkyVnpjeTV1WlhoMFZHbGpheWtnZTF4dUlDQWdJQ0FnSUNBdkx5QkZibk4xY21VZ1VTQnBjeUJwYmlCaElISmxZV3dnVG05a1pTQmxiblpwY205dWJXVnVkQ3dnZDJsMGFDQmhJR0J3Y205alpYTnpMbTVsZUhSVWFXTnJZQzVjYmlBZ0lDQWdJQ0FnTHk4Z1ZHOGdjMlZsSUhSb2NtOTFaMmdnWm1GclpTQk9iMlJsSUdWdWRtbHliMjV0Wlc1MGN6cGNiaUFnSUNBZ0lDQWdMeThnS2lCTmIyTm9ZU0IwWlhOMElISjFibTVsY2lBdElHVjRjRzl6WlhNZ1lTQmdjSEp2WTJWemMyQWdaMnh2WW1Gc0lIZHBkR2h2ZFhRZ1lTQmdibVY0ZEZScFkydGdYRzRnSUNBZ0lDQWdJQzh2SUNvZ1FuSnZkM05sY21sbWVTQXRJR1Y0Y0c5elpYTWdZU0JnY0hKdlkyVnpjeTV1WlhoVWFXTnJZQ0JtZFc1amRHbHZiaUIwYUdGMElIVnpaWE5jYmlBZ0lDQWdJQ0FnTHk4Z0lDQmdjMlYwVkdsdFpXOTFkR0F1SUVsdUlIUm9hWE1nWTJGelpTQmdjMlYwU1cxdFpXUnBZWFJsWUNCcGN5QndjbVZtWlhKeVpXUWdZbVZqWVhWelpWeHVJQ0FnSUNBZ0lDQXZMeUFnSUNCcGRDQnBjeUJtWVhOMFpYSXVJRUp5YjNkelpYSnBabmtuY3lCZ2NISnZZMlZ6Y3k1MGIxTjBjbWx1WnlncFlDQjVhV1ZzWkhOY2JpQWdJQ0FnSUNBZ0x5OGdJQ0JjSWx0dlltcGxZM1FnVDJKcVpXTjBYVndpTENCM2FHbHNaU0JwYmlCaElISmxZV3dnVG05a1pTQmxiblpwY205dWJXVnVkRnh1SUNBZ0lDQWdJQ0F2THlBZ0lHQndjbTlqWlhOekxtNWxlSFJVYVdOcktDbGdJSGxwWld4a2N5QmNJbHR2WW1wbFkzUWdjSEp2WTJWemMxMWNJaTVjYmlBZ0lDQWdJQ0FnYVhOT2IyUmxTbE1nUFNCMGNuVmxPMXh1WEc0Z0lDQWdJQ0FnSUhKbGNYVmxjM1JVYVdOcklEMGdablZ1WTNScGIyNGdLQ2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjSEp2WTJWemN5NXVaWGgwVkdsamF5aG1iSFZ6YUNrN1hHNGdJQ0FnSUNBZ0lIMDdYRzVjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLSFI1Y0dWdlppQnpaWFJKYlcxbFpHbGhkR1VnUFQwOUlGd2lablZ1WTNScGIyNWNJaWtnZTF4dUlDQWdJQ0FnSUNBdkx5QkpiaUJKUlRFd0xDQk9iMlJsTG1weklEQXVPU3NzSUc5eUlHaDBkSEJ6T2k4dloybDBhSFZpTG1OdmJTOU9iMkpzWlVwVEwzTmxkRWx0YldWa2FXRjBaVnh1SUNBZ0lDQWdJQ0JwWmlBb2RIbHdaVzltSUhkcGJtUnZkeUFoUFQwZ1hDSjFibVJsWm1sdVpXUmNJaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjbVZ4ZFdWemRGUnBZMnNnUFNCelpYUkpiVzFsWkdsaGRHVXVZbWx1WkNoM2FXNWtiM2NzSUdac2RYTm9LVHRjYmlBZ0lDQWdJQ0FnZlNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxjWFZsYzNSVWFXTnJJRDBnWm5WdVkzUnBiMjRnS0NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lITmxkRWx0YldWa2FXRjBaU2htYkhWemFDazdYRzRnSUNBZ0lDQWdJQ0FnSUNCOU8xeHVJQ0FnSUNBZ0lDQjlYRzVjYmlBZ0lDQjlJR1ZzYzJVZ2FXWWdLSFI1Y0dWdlppQk5aWE56WVdkbFEyaGhibTVsYkNBaFBUMGdYQ0oxYm1SbFptbHVaV1JjSWlrZ2UxeHVJQ0FnSUNBZ0lDQXZMeUJ0YjJSbGNtNGdZbkp2ZDNObGNuTmNiaUFnSUNBZ0lDQWdMeThnYUhSMGNEb3ZMM2QzZHk1dWIyNWliRzlqYTJsdVp5NXBieTh5TURFeEx6QTJMM2RwYm1SdmQyNWxlSFIwYVdOckxtaDBiV3hjYmlBZ0lDQWdJQ0FnZG1GeUlHTm9ZVzV1Wld3Z1BTQnVaWGNnVFdWemMyRm5aVU5vWVc1dVpXd29LVHRjYmlBZ0lDQWdJQ0FnTHk4Z1FYUWdiR1ZoYzNRZ1UyRm1ZWEpwSUZabGNuTnBiMjRnTmk0d0xqVWdLRGcxTXpZdU16QXVNU2tnYVc1MFpYSnRhWFIwWlc1MGJIa2dZMkZ1Ym05MElHTnlaV0YwWlZ4dUlDQWdJQ0FnSUNBdkx5QjNiM0pyYVc1bklHMWxjM05oWjJVZ2NHOXlkSE1nZEdobElHWnBjbk4wSUhScGJXVWdZU0J3WVdkbElHeHZZV1J6TGx4dUlDQWdJQ0FnSUNCamFHRnVibVZzTG5CdmNuUXhMbTl1YldWemMyRm5aU0E5SUdaMWJtTjBhVzl1SUNncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGNYVmxjM1JVYVdOcklEMGdjbVZ4ZFdWemRGQnZjblJVYVdOck8xeHVJQ0FnSUNBZ0lDQWdJQ0FnWTJoaGJtNWxiQzV3YjNKME1TNXZibTFsYzNOaFoyVWdQU0JtYkhWemFEdGNiaUFnSUNBZ0lDQWdJQ0FnSUdac2RYTm9LQ2s3WEc0Z0lDQWdJQ0FnSUgwN1hHNGdJQ0FnSUNBZ0lIWmhjaUJ5WlhGMVpYTjBVRzl5ZEZScFkyc2dQU0JtZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0F2THlCUGNHVnlZU0J5WlhGMWFYSmxjeUIxY3lCMGJ5QndjbTkyYVdSbElHRWdiV1Z6YzJGblpTQndZWGxzYjJGa0xDQnlaV2RoY21Sc1pYTnpJRzltWEc0Z0lDQWdJQ0FnSUNBZ0lDQXZMeUIzYUdWMGFHVnlJSGRsSUhWelpTQnBkQzVjYmlBZ0lDQWdJQ0FnSUNBZ0lHTm9ZVzV1Wld3dWNHOXlkREl1Y0c5emRFMWxjM05oWjJVb01DazdYRzRnSUNBZ0lDQWdJSDA3WEc0Z0lDQWdJQ0FnSUhKbGNYVmxjM1JVYVdOcklEMGdablZ1WTNScGIyNGdLQ2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjMlYwVkdsdFpXOTFkQ2htYkhWemFDd2dNQ2s3WEc0Z0lDQWdJQ0FnSUNBZ0lDQnlaWEYxWlhOMFVHOXlkRlJwWTJzb0tUdGNiaUFnSUNBZ0lDQWdmVHRjYmx4dUlDQWdJSDBnWld4elpTQjdYRzRnSUNBZ0lDQWdJQzh2SUc5c1pDQmljbTkzYzJWeWMxeHVJQ0FnSUNBZ0lDQnlaWEYxWlhOMFZHbGpheUE5SUdaMWJtTjBhVzl1SUNncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhObGRGUnBiV1Z2ZFhRb1pteDFjMmdzSURBcE8xeHVJQ0FnSUNBZ0lDQjlPMXh1SUNBZ0lIMWNiaUFnSUNBdkx5QnlkVzV6SUdFZ2RHRnpheUJoWm5SbGNpQmhiR3dnYjNSb1pYSWdkR0Z6YTNNZ2FHRjJaU0JpWldWdUlISjFibHh1SUNBZ0lDOHZJSFJvYVhNZ2FYTWdkWE5sWm5Wc0lHWnZjaUIxYm1oaGJtUnNaV1FnY21WcVpXTjBhVzl1SUhSeVlXTnJhVzVuSUhSb1lYUWdibVZsWkhNZ2RHOGdhR0Z3Y0dWdVhHNGdJQ0FnTHk4Z1lXWjBaWElnWVd4c0lHQjBhR1Z1WUdRZ2RHRnphM01nYUdGMlpTQmlaV1Z1SUhKMWJpNWNiaUFnSUNCdVpYaDBWR2xqYXk1eWRXNUJablJsY2lBOUlHWjFibU4wYVc5dUlDaDBZWE5yS1NCN1hHNGdJQ0FnSUNBZ0lHeGhkR1Z5VVhWbGRXVXVjSFZ6YUNoMFlYTnJLVHRjYmlBZ0lDQWdJQ0FnYVdZZ0tDRm1iSFZ6YUdsdVp5a2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pteDFjMmhwYm1jZ1BTQjBjblZsTzF4dUlDQWdJQ0FnSUNBZ0lDQWdjbVZ4ZFdWemRGUnBZMnNvS1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUgwN1hHNGdJQ0FnY21WMGRYSnVJRzVsZUhSVWFXTnJPMXh1ZlNrb0tUdGNibHh1THk4Z1FYUjBaVzF3ZENCMGJ5QnRZV3RsSUdkbGJtVnlhV056SUhOaFptVWdhVzRnZEdobElHWmhZMlVnYjJZZ1pHOTNibk4wY21WaGJWeHVMeThnYlc5a2FXWnBZMkYwYVc5dWN5NWNiaTh2SUZSb1pYSmxJR2x6SUc1dklITnBkSFZoZEdsdmJpQjNhR1Z5WlNCMGFHbHpJR2x6SUc1bFkyVnpjMkZ5ZVM1Y2JpOHZJRWxtSUhsdmRTQnVaV1ZrSUdFZ2MyVmpkWEpwZEhrZ1ozVmhjbUZ1ZEdWbExDQjBhR1Z6WlNCd2NtbHRiM0prYVdGc2N5QnVaV1ZrSUhSdklHSmxYRzR2THlCa1pXVndiSGtnWm5KdmVtVnVJR0Z1ZVhkaGVTd2dZVzVrSUdsbUlIbHZkU0JrYjI3aWdKbDBJRzVsWldRZ1lTQnpaV04xY21sMGVTQm5kV0Z5WVc1MFpXVXNYRzR2THlCMGFHbHpJR2x6SUdwMWMzUWdjR3hoYVc0Z2NHRnlZVzV2YVdRdVhHNHZMeUJJYjNkbGRtVnlMQ0IwYUdseklDb3FiV2xuYUhRcUtpQm9ZWFpsSUhSb1pTQnVhV05sSUhOcFpHVXRaV1ptWldOMElHOW1JSEpsWkhWamFXNW5JSFJvWlNCemFYcGxJRzltWEc0dkx5QjBhR1VnYldsdWFXWnBaV1FnWTI5a1pTQmllU0J5WldSMVkybHVaeUI0TG1OaGJHd29LU0IwYnlCdFpYSmxiSGtnZUNncFhHNHZMeUJUWldVZ1RXRnlheUJOYVd4c1pYTGlnSmx6SUdWNGNHeGhibUYwYVc5dUlHOW1JSGRvWVhRZ2RHaHBjeUJrYjJWekxseHVMeThnYUhSMGNEb3ZMM2RwYTJrdVpXTnRZWE5qY21sd2RDNXZjbWN2Wkc5cmRTNXdhSEEvYVdROVkyOXVkbVZ1ZEdsdmJuTTZjMkZtWlY5dFpYUmhYM0J5YjJkeVlXMXRhVzVuWEc1MllYSWdZMkZzYkNBOUlFWjFibU4wYVc5dUxtTmhiR3c3WEc1bWRXNWpkR2x2YmlCMWJtTjFjbko1VkdocGN5aG1LU0I3WEc0Z0lDQWdjbVYwZFhKdUlHWjFibU4wYVc5dUlDZ3BJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJR05oYkd3dVlYQndiSGtvWml3Z1lYSm5kVzFsYm5SektUdGNiaUFnSUNCOU8xeHVmVnh1THk4Z1ZHaHBjeUJwY3lCbGNYVnBkbUZzWlc1MExDQmlkWFFnYzJ4dmQyVnlPbHh1THk4Z2RXNWpkWEp5ZVZSb2FYTWdQU0JHZFc1amRHbHZibDlpYVc1a0xtSnBibVFvUm5WdVkzUnBiMjVmWW1sdVpDNWpZV3hzS1R0Y2JpOHZJR2gwZEhBNkx5OXFjM0JsY21ZdVkyOXRMM1Z1WTNWeWNubDBhR2x6WEc1Y2JuWmhjaUJoY25KaGVWOXpiR2xqWlNBOUlIVnVZM1Z5Y25sVWFHbHpLRUZ5Y21GNUxuQnliM1J2ZEhsd1pTNXpiR2xqWlNrN1hHNWNiblpoY2lCaGNuSmhlVjl5WldSMVkyVWdQU0IxYm1OMWNuSjVWR2hwY3loY2JpQWdJQ0JCY25KaGVTNXdjbTkwYjNSNWNHVXVjbVZrZFdObElIeDhJR1oxYm1OMGFXOXVJQ2hqWVd4c1ltRmpheXdnWW1GemFYTXBJSHRjYmlBZ0lDQWdJQ0FnZG1GeUlHbHVaR1Y0SUQwZ01DeGNiaUFnSUNBZ0lDQWdJQ0FnSUd4bGJtZDBhQ0E5SUhSb2FYTXViR1Z1WjNSb08xeHVJQ0FnSUNBZ0lDQXZMeUJqYjI1alpYSnVhVzVuSUhSb1pTQnBibWwwYVdGc0lIWmhiSFZsTENCcFppQnZibVVnYVhNZ2JtOTBJSEJ5YjNacFpHVmtYRzRnSUNBZ0lDQWdJR2xtSUNoaGNtZDFiV1Z1ZEhNdWJHVnVaM1JvSUQwOVBTQXhLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQXZMeUJ6WldWcklIUnZJSFJvWlNCbWFYSnpkQ0IyWVd4MVpTQnBiaUIwYUdVZ1lYSnlZWGtzSUdGalkyOTFiblJwYm1kY2JpQWdJQ0FnSUNBZ0lDQWdJQzh2SUdadmNpQjBhR1VnY0c5emMybGlhV3hwZEhrZ2RHaGhkQ0JwY3lCcGN5QmhJSE53WVhKelpTQmhjbkpoZVZ4dUlDQWdJQ0FnSUNBZ0lDQWdaRzhnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdsbUlDaHBibVJsZUNCcGJpQjBhR2x6S1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR0poYzJseklEMGdkR2hwYzF0cGJtUmxlQ3NyWFR0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdZbkpsWVdzN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2dySzJsdVpHVjRJRDQ5SUd4bGJtZDBhQ2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjBhSEp2ZHlCdVpYY2dWSGx3WlVWeWNtOXlLQ2s3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmU0IzYUdsc1pTQW9NU2s3WEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ0x5OGdjbVZrZFdObFhHNGdJQ0FnSUNBZ0lHWnZjaUFvT3lCcGJtUmxlQ0E4SUd4bGJtZDBhRHNnYVc1a1pYZ3JLeWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdMeThnWVdOamIzVnVkQ0JtYjNJZ2RHaGxJSEJ2YzNOcFltbHNhWFI1SUhSb1lYUWdkR2hsSUdGeWNtRjVJR2x6SUhOd1lYSnpaVnh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR2x1WkdWNElHbHVJSFJvYVhNcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmlZWE5wY3lBOUlHTmhiR3hpWVdOcktHSmhjMmx6TENCMGFHbHpXMmx1WkdWNFhTd2dhVzVrWlhncE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCaVlYTnBjenRjYmlBZ0lDQjlYRzRwTzF4dVhHNTJZWElnWVhKeVlYbGZhVzVrWlhoUFppQTlJSFZ1WTNWeWNubFVhR2x6S0Z4dUlDQWdJRUZ5Y21GNUxuQnliM1J2ZEhsd1pTNXBibVJsZUU5bUlIeDhJR1oxYm1OMGFXOXVJQ2gyWVd4MVpTa2dlMXh1SUNBZ0lDQWdJQ0F2THlCdWIzUWdZU0IyWlhKNUlHZHZiMlFnYzJocGJTd2dZblYwSUdkdmIyUWdaVzV2ZFdkb0lHWnZjaUJ2ZFhJZ2IyNWxJSFZ6WlNCdlppQnBkRnh1SUNBZ0lDQWdJQ0JtYjNJZ0tIWmhjaUJwSUQwZ01Ec2dhU0E4SUhSb2FYTXViR1Z1WjNSb095QnBLeXNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR2xtSUNoMGFHbHpXMmxkSUQwOVBTQjJZV3gxWlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlBdE1UdGNiaUFnSUNCOVhHNHBPMXh1WEc1MllYSWdZWEp5WVhsZmJXRndJRDBnZFc1amRYSnllVlJvYVhNb1hHNGdJQ0FnUVhKeVlYa3VjSEp2ZEc5MGVYQmxMbTFoY0NCOGZDQm1kVzVqZEdsdmJpQW9ZMkZzYkdKaFkyc3NJSFJvYVhOd0tTQjdYRzRnSUNBZ0lDQWdJSFpoY2lCelpXeG1JRDBnZEdocGN6dGNiaUFnSUNBZ0lDQWdkbUZ5SUdOdmJHeGxZM1FnUFNCYlhUdGNiaUFnSUNBZ0lDQWdZWEp5WVhsZmNtVmtkV05sS0hObGJHWXNJR1oxYm1OMGFXOXVJQ2gxYm1SbFptbHVaV1FzSUhaaGJIVmxMQ0JwYm1SbGVDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1kyOXNiR1ZqZEM1d2RYTm9LR05oYkd4aVlXTnJMbU5oYkd3b2RHaHBjM0FzSUhaaGJIVmxMQ0JwYm1SbGVDd2djMlZzWmlrcE8xeHVJQ0FnSUNBZ0lDQjlMQ0IyYjJsa0lEQXBPMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdZMjlzYkdWamREdGNiaUFnSUNCOVhHNHBPMXh1WEc1MllYSWdiMkpxWldOMFgyTnlaV0YwWlNBOUlFOWlhbVZqZEM1amNtVmhkR1VnZkh3Z1puVnVZM1JwYjI0Z0tIQnliM1J2ZEhsd1pTa2dlMXh1SUNBZ0lHWjFibU4wYVc5dUlGUjVjR1VvS1NCN0lIMWNiaUFnSUNCVWVYQmxMbkJ5YjNSdmRIbHdaU0E5SUhCeWIzUnZkSGx3WlR0Y2JpQWdJQ0J5WlhSMWNtNGdibVYzSUZSNWNHVW9LVHRjYm4wN1hHNWNiblpoY2lCdlltcGxZM1JmYUdGelQzZHVVSEp2Y0dWeWRIa2dQU0IxYm1OMWNuSjVWR2hwY3loUFltcGxZM1F1Y0hKdmRHOTBlWEJsTG1oaGMwOTNibEJ5YjNCbGNuUjVLVHRjYmx4dWRtRnlJRzlpYW1WamRGOXJaWGx6SUQwZ1QySnFaV04wTG10bGVYTWdmSHdnWm5WdVkzUnBiMjRnS0c5aWFtVmpkQ2tnZTF4dUlDQWdJSFpoY2lCclpYbHpJRDBnVzEwN1hHNGdJQ0FnWm05eUlDaDJZWElnYTJWNUlHbHVJRzlpYW1WamRDa2dlMXh1SUNBZ0lDQWdJQ0JwWmlBb2IySnFaV04wWDJoaGMwOTNibEJ5YjNCbGNuUjVLRzlpYW1WamRDd2dhMlY1S1NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYTJWNWN5NXdkWE5vS0d0bGVTazdYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzRnSUNBZ2NtVjBkWEp1SUd0bGVYTTdYRzU5TzF4dVhHNTJZWElnYjJKcVpXTjBYM1J2VTNSeWFXNW5JRDBnZFc1amRYSnllVlJvYVhNb1QySnFaV04wTG5CeWIzUnZkSGx3WlM1MGIxTjBjbWx1WnlrN1hHNWNibVoxYm1OMGFXOXVJR2x6VDJKcVpXTjBLSFpoYkhWbEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUhaaGJIVmxJRDA5UFNCUFltcGxZM1FvZG1Gc2RXVXBPMXh1ZlZ4dVhHNHZMeUJuWlc1bGNtRjBiM0lnY21Wc1lYUmxaQ0J6YUdsdGMxeHVYRzR2THlCR1NWaE5SVG9nVW1WdGIzWmxJSFJvYVhNZ1puVnVZM1JwYjI0Z2IyNWpaU0JGVXpZZ1oyVnVaWEpoZEc5eWN5QmhjbVVnYVc0Z1UzQnBaR1Z5VFc5dWEyVjVMbHh1Wm5WdVkzUnBiMjRnYVhOVGRHOXdTWFJsY21GMGFXOXVLR1Y0WTJWd2RHbHZiaWtnZTF4dUlDQWdJSEpsZEhWeWJpQW9YRzRnSUNBZ0lDQWdJRzlpYW1WamRGOTBiMU4wY21sdVp5aGxlR05sY0hScGIyNHBJRDA5UFNCY0lsdHZZbXBsWTNRZ1UzUnZjRWwwWlhKaGRHbHZibDFjSWlCOGZGeHVJQ0FnSUNBZ0lDQmxlR05sY0hScGIyNGdhVzV6ZEdGdVkyVnZaaUJSVW1WMGRYSnVWbUZzZFdWY2JpQWdJQ0FwTzF4dWZWeHVYRzR2THlCR1NWaE5SVG9nVW1WdGIzWmxJSFJvYVhNZ2FHVnNjR1Z5SUdGdVpDQlJMbkpsZEhWeWJpQnZibU5sSUVWVE5pQm5aVzVsY21GMGIzSnpJR0Z5WlNCcGJseHVMeThnVTNCcFpHVnlUVzl1YTJWNUxseHVkbUZ5SUZGU1pYUjFjbTVXWVd4MVpUdGNibWxtSUNoMGVYQmxiMllnVW1WMGRYSnVWbUZzZFdVZ0lUMDlJRndpZFc1a1pXWnBibVZrWENJcElIdGNiaUFnSUNCUlVtVjBkWEp1Vm1Gc2RXVWdQU0JTWlhSMWNtNVdZV3gxWlR0Y2JuMGdaV3h6WlNCN1hHNGdJQ0FnVVZKbGRIVnlibFpoYkhWbElEMGdablZ1WTNScGIyNGdLSFpoYkhWbEtTQjdYRzRnSUNBZ0lDQWdJSFJvYVhNdWRtRnNkV1VnUFNCMllXeDFaVHRjYmlBZ0lDQjlPMXh1ZlZ4dVhHNHZMeUJzYjI1bklITjBZV05ySUhSeVlXTmxjMXh1WEc1MllYSWdVMVJCUTB0ZlNsVk5VRjlUUlZCQlVrRlVUMUlnUFNCY0lrWnliMjBnY0hKbGRtbHZkWE1nWlhabGJuUTZYQ0k3WEc1Y2JtWjFibU4wYVc5dUlHMWhhMlZUZEdGamExUnlZV05sVEc5dVp5aGxjbkp2Y2l3Z2NISnZiV2x6WlNrZ2UxeHVJQ0FnSUM4dklFbG1JSEJ2YzNOcFlteGxMQ0IwY21GdWMyWnZjbTBnZEdobElHVnljbTl5SUhOMFlXTnJJSFJ5WVdObElHSjVJSEpsYlc5MmFXNW5JRTV2WkdVZ1lXNWtJRkZjYmlBZ0lDQXZMeUJqY25WbWRDd2dkR2hsYmlCamIyNWpZWFJsYm1GMGFXNW5JSGRwZEdnZ2RHaGxJSE4wWVdOcklIUnlZV05sSUc5bUlHQndjbTl0YVhObFlDNGdVMlZsSUNNMU55NWNiaUFnSUNCcFppQW9hR0Z6VTNSaFkydHpJQ1ltWEc0Z0lDQWdJQ0FnSUhCeWIyMXBjMlV1YzNSaFkyc2dKaVpjYmlBZ0lDQWdJQ0FnZEhsd1pXOW1JR1Z5Y205eUlEMDlQU0JjSW05aWFtVmpkRndpSUNZbVhHNGdJQ0FnSUNBZ0lHVnljbTl5SUNFOVBTQnVkV3hzSUNZbVhHNGdJQ0FnSUNBZ0lHVnljbTl5TG5OMFlXTnJJQ1ltWEc0Z0lDQWdJQ0FnSUdWeWNtOXlMbk4wWVdOckxtbHVaR1Y0VDJZb1UxUkJRMHRmU2xWTlVGOVRSVkJCVWtGVVQxSXBJRDA5UFNBdE1WeHVJQ0FnSUNrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnYzNSaFkydHpJRDBnVzEwN1hHNGdJQ0FnSUNBZ0lHWnZjaUFvZG1GeUlIQWdQU0J3Y205dGFYTmxPeUFoSVhBN0lIQWdQU0J3TG5OdmRYSmpaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdhV1lnS0hBdWMzUmhZMnNwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCemRHRmphM011ZFc1emFHbG1kQ2h3TG5OMFlXTnJLVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0J6ZEdGamEzTXVkVzV6YUdsbWRDaGxjbkp2Y2k1emRHRmpheWs3WEc1Y2JpQWdJQ0FnSUNBZ2RtRnlJR052Ym1OaGRHVmtVM1JoWTJ0eklEMGdjM1JoWTJ0ekxtcHZhVzRvWENKY1hHNWNJaUFySUZOVVFVTkxYMHBWVFZCZlUwVlFRVkpCVkU5U0lDc2dYQ0pjWEc1Y0lpazdYRzRnSUNBZ0lDQWdJR1Z5Y205eUxuTjBZV05ySUQwZ1ptbHNkR1Z5VTNSaFkydFRkSEpwYm1jb1kyOXVZMkYwWldSVGRHRmphM01wTzF4dUlDQWdJSDFjYm4xY2JseHVablZ1WTNScGIyNGdabWxzZEdWeVUzUmhZMnRUZEhKcGJtY29jM1JoWTJ0VGRISnBibWNwSUh0Y2JpQWdJQ0IyWVhJZ2JHbHVaWE1nUFNCemRHRmphMU4wY21sdVp5NXpjR3hwZENoY0lseGNibHdpS1R0Y2JpQWdJQ0IyWVhJZ1pHVnphWEpsWkV4cGJtVnpJRDBnVzEwN1hHNGdJQ0FnWm05eUlDaDJZWElnYVNBOUlEQTdJR2tnUENCc2FXNWxjeTVzWlc1bmRHZzdJQ3NyYVNrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnYkdsdVpTQTlJR3hwYm1WelcybGRPMXh1WEc0Z0lDQWdJQ0FnSUdsbUlDZ2hhWE5KYm5SbGNtNWhiRVp5WVcxbEtHeHBibVVwSUNZbUlDRnBjMDV2WkdWR2NtRnRaU2hzYVc1bEtTQW1KaUJzYVc1bEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCa1pYTnBjbVZrVEdsdVpYTXVjSFZ6YUNoc2FXNWxLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDFjYmlBZ0lDQnlaWFIxY200Z1pHVnphWEpsWkV4cGJtVnpMbXB2YVc0b1hDSmNYRzVjSWlrN1hHNTlYRzVjYm1aMWJtTjBhVzl1SUdselRtOWtaVVp5WVcxbEtITjBZV05yVEdsdVpTa2dlMXh1SUNBZ0lISmxkSFZ5YmlCemRHRmphMHhwYm1VdWFXNWtaWGhQWmloY0lpaHRiMlIxYkdVdWFuTTZYQ0lwSUNFOVBTQXRNU0I4ZkZ4dUlDQWdJQ0FnSUNBZ0lDQnpkR0ZqYTB4cGJtVXVhVzVrWlhoUFppaGNJaWh1YjJSbExtcHpPbHdpS1NBaFBUMGdMVEU3WEc1OVhHNWNibVoxYm1OMGFXOXVJR2RsZEVacGJHVk9ZVzFsUVc1a1RHbHVaVTUxYldKbGNpaHpkR0ZqYTB4cGJtVXBJSHRjYmlBZ0lDQXZMeUJPWVcxbFpDQm1kVzVqZEdsdmJuTTZJRndpWVhRZ1puVnVZM1JwYjI1T1lXMWxJQ2htYVd4bGJtRnRaVHBzYVc1bFRuVnRZbVZ5T21OdmJIVnRiazUxYldKbGNpbGNJbHh1SUNBZ0lDOHZJRWx1SUVsRk1UQWdablZ1WTNScGIyNGdibUZ0WlNCallXNGdhR0YyWlNCemNHRmpaWE1nS0Z3aVFXNXZibmx0YjNWeklHWjFibU4wYVc5dVhDSXBJRTlmYjF4dUlDQWdJSFpoY2lCaGRIUmxiWEIwTVNBOUlDOWhkQ0F1S3lCY1hDZ29MaXNwT2loY1hHUXJLVG9vUHpwY1hHUXJLVnhjS1NRdkxtVjRaV01vYzNSaFkydE1hVzVsS1R0Y2JpQWdJQ0JwWmlBb1lYUjBaVzF3ZERFcElIdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlGdGhkSFJsYlhCME1Wc3hYU3dnVG5WdFltVnlLR0YwZEdWdGNIUXhXekpkS1YwN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnTHk4Z1FXNXZibmx0YjNWeklHWjFibU4wYVc5dWN6b2dYQ0poZENCbWFXeGxibUZ0WlRwc2FXNWxUblZ0WW1WeU9tTnZiSFZ0Yms1MWJXSmxjbHdpWEc0Z0lDQWdkbUZ5SUdGMGRHVnRjSFF5SUQwZ0wyRjBJQ2hiWGlCZEt5azZLRnhjWkNzcE9pZy9PbHhjWkNzcEpDOHVaWGhsWXloemRHRmphMHhwYm1VcE8xeHVJQ0FnSUdsbUlDaGhkSFJsYlhCME1pa2dlMXh1SUNBZ0lDQWdJQ0J5WlhSMWNtNGdXMkYwZEdWdGNIUXlXekZkTENCT2RXMWlaWElvWVhSMFpXMXdkREpiTWwwcFhUdGNiaUFnSUNCOVhHNWNiaUFnSUNBdkx5QkdhWEpsWm05NElITjBlV3hsT2lCY0ltWjFibU4wYVc5dVFHWnBiR1Z1WVcxbE9teHBibVZPZFcxaVpYSWdiM0lnUUdacGJHVnVZVzFsT214cGJtVk9kVzFpWlhKY0lseHVJQ0FnSUhaaGNpQmhkSFJsYlhCME15QTlJQzh1S2tBb0xpc3BPaWhjWEdRcktTUXZMbVY0WldNb2MzUmhZMnRNYVc1bEtUdGNiaUFnSUNCcFppQW9ZWFIwWlcxd2RETXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRnRoZEhSbGJYQjBNMXN4WFN3Z1RuVnRZbVZ5S0dGMGRHVnRjSFF6V3pKZEtWMDdYRzRnSUNBZ2ZWeHVmVnh1WEc1bWRXNWpkR2x2YmlCcGMwbHVkR1Z5Ym1Gc1JuSmhiV1VvYzNSaFkydE1hVzVsS1NCN1hHNGdJQ0FnZG1GeUlHWnBiR1ZPWVcxbFFXNWtUR2x1WlU1MWJXSmxjaUE5SUdkbGRFWnBiR1ZPWVcxbFFXNWtUR2x1WlU1MWJXSmxjaWh6ZEdGamEweHBibVVwTzF4dVhHNGdJQ0FnYVdZZ0tDRm1hV3hsVG1GdFpVRnVaRXhwYm1WT2RXMWlaWElwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUdaaGJITmxPMXh1SUNBZ0lIMWNibHh1SUNBZ0lIWmhjaUJtYVd4bFRtRnRaU0E5SUdacGJHVk9ZVzFsUVc1a1RHbHVaVTUxYldKbGNsc3dYVHRjYmlBZ0lDQjJZWElnYkdsdVpVNTFiV0psY2lBOUlHWnBiR1ZPWVcxbFFXNWtUR2x1WlU1MWJXSmxjbHN4WFR0Y2JseHVJQ0FnSUhKbGRIVnliaUJtYVd4bFRtRnRaU0E5UFQwZ2NVWnBiR1ZPWVcxbElDWW1YRzRnSUNBZ0lDQWdJR3hwYm1WT2RXMWlaWElnUGowZ2NWTjBZWEowYVc1blRHbHVaU0FtSmx4dUlDQWdJQ0FnSUNCc2FXNWxUblZ0WW1WeUlEdzlJSEZGYm1ScGJtZE1hVzVsTzF4dWZWeHVYRzR2THlCa2FYTmpiM1psY2lCdmQyNGdabWxzWlNCdVlXMWxJR0Z1WkNCc2FXNWxJRzUxYldKbGNpQnlZVzVuWlNCbWIzSWdabWxzZEdWeWFXNW5JSE4wWVdOclhHNHZMeUIwY21GalpYTmNibVoxYm1OMGFXOXVJR05oY0hSMWNtVk1hVzVsS0NrZ2UxeHVJQ0FnSUdsbUlDZ2hhR0Z6VTNSaFkydHpLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlYRzVjYmlBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNCMGFISnZkeUJ1WlhjZ1JYSnliM0lvS1R0Y2JpQWdJQ0I5SUdOaGRHTm9JQ2hsS1NCN1hHNGdJQ0FnSUNBZ0lIWmhjaUJzYVc1bGN5QTlJR1V1YzNSaFkyc3VjM0JzYVhRb1hDSmNYRzVjSWlrN1hHNGdJQ0FnSUNBZ0lIWmhjaUJtYVhKemRFeHBibVVnUFNCc2FXNWxjMXN3WFM1cGJtUmxlRTltS0Z3aVFGd2lLU0ErSURBZ1B5QnNhVzVsYzFzeFhTQTZJR3hwYm1Weld6SmRPMXh1SUNBZ0lDQWdJQ0IyWVhJZ1ptbHNaVTVoYldWQmJtUk1hVzVsVG5WdFltVnlJRDBnWjJWMFJtbHNaVTVoYldWQmJtUk1hVzVsVG5WdFltVnlLR1pwY25OMFRHbHVaU2s3WEc0Z0lDQWdJQ0FnSUdsbUlDZ2habWxzWlU1aGJXVkJibVJNYVc1bFRuVnRZbVZ5S1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNDdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCeFJtbHNaVTVoYldVZ1BTQm1hV3hsVG1GdFpVRnVaRXhwYm1WT2RXMWlaWEpiTUYwN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCbWFXeGxUbUZ0WlVGdVpFeHBibVZPZFcxaVpYSmJNVjA3WEc0Z0lDQWdmVnh1ZlZ4dVhHNW1kVzVqZEdsdmJpQmtaWEJ5WldOaGRHVW9ZMkZzYkdKaFkyc3NJRzVoYldVc0lHRnNkR1Z5Ym1GMGFYWmxLU0I3WEc0Z0lDQWdjbVYwZFhKdUlHWjFibU4wYVc5dUlDZ3BJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tIUjVjR1Z2WmlCamIyNXpiMnhsSUNFOVBTQmNJblZ1WkdWbWFXNWxaRndpSUNZbVhHNGdJQ0FnSUNBZ0lDQWdJQ0IwZVhCbGIyWWdZMjl1YzI5c1pTNTNZWEp1SUQwOVBTQmNJbVoxYm1OMGFXOXVYQ0lwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJR052Ym5OdmJHVXVkMkZ5YmlodVlXMWxJQ3NnWENJZ2FYTWdaR1Z3Y21WallYUmxaQ3dnZFhObElGd2lJQ3NnWVd4MFpYSnVZWFJwZG1VZ0sxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lGd2lJR2x1YzNSbFlXUXVYQ0lzSUc1bGR5QkZjbkp2Y2loY0lsd2lLUzV6ZEdGamF5azdYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJR05oYkd4aVlXTnJMbUZ3Y0d4NUtHTmhiR3hpWVdOckxDQmhjbWQxYldWdWRITXBPMXh1SUNBZ0lIMDdYRzU5WEc1Y2JpOHZJR1Z1WkNCdlppQnphR2x0YzF4dUx5OGdZbVZuYVc1dWFXNW5JRzltSUhKbFlXd2dkMjl5YTF4dVhHNHZLaXBjYmlBcUlFTnZibk4wY25WamRITWdZU0J3Y205dGFYTmxJR1p2Y2lCaGJpQnBiVzFsWkdsaGRHVWdjbVZtWlhKbGJtTmxMQ0J3WVhOelpYTWdjSEp2YldselpYTWdkR2h5YjNWbmFDd2diM0pjYmlBcUlHTnZaWEpqWlhNZ2NISnZiV2x6WlhNZ1puSnZiU0JrYVdabVpYSmxiblFnYzNsemRHVnRjeTVjYmlBcUlFQndZWEpoYlNCMllXeDFaU0JwYlcxbFpHbGhkR1VnY21WbVpYSmxibU5sSUc5eUlIQnliMjFwYzJWY2JpQXFMMXh1Wm5WdVkzUnBiMjRnVVNoMllXeDFaU2tnZTF4dUlDQWdJQzh2SUVsbUlIUm9aU0J2WW1wbFkzUWdhWE1nWVd4eVpXRmtlU0JoSUZCeWIyMXBjMlVzSUhKbGRIVnliaUJwZENCa2FYSmxZM1JzZVM0Z0lGUm9hWE1nWlc1aFlteGxjMXh1SUNBZ0lDOHZJSFJvWlNCeVpYTnZiSFpsSUdaMWJtTjBhVzl1SUhSdklHSnZkR2dnWW1VZ2RYTmxaQ0IwYnlCamNtVmhkR1ZrSUhKbFptVnlaVzVqWlhNZ1puSnZiU0J2WW1wbFkzUnpMRnh1SUNBZ0lDOHZJR0oxZENCMGJ5QjBiMnhsY21GaWJIa2dZMjlsY21ObElHNXZiaTF3Y205dGFYTmxjeUIwYnlCd2NtOXRhWE5sY3k1Y2JpQWdJQ0JwWmlBb2RtRnNkV1VnYVc1emRHRnVZMlZ2WmlCUWNtOXRhWE5sS1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCMllXeDFaVHRjYmlBZ0lDQjlYRzVjYmlBZ0lDQXZMeUJoYzNOcGJXbHNZWFJsSUhSb1pXNWhZbXhsYzF4dUlDQWdJR2xtSUNocGMxQnliMjFwYzJWQmJHbHJaU2gyWVd4MVpTa3BJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJR052WlhKalpTaDJZV3gxWlNrN1hHNGdJQ0FnZlNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJR1oxYkdacGJHd29kbUZzZFdVcE8xeHVJQ0FnSUgxY2JuMWNibEV1Y21WemIyeDJaU0E5SUZFN1hHNWNiaThxS2x4dUlDb2dVR1Z5Wm05eWJYTWdZU0IwWVhOcklHbHVJR0VnWm5WMGRYSmxJSFIxY200Z2IyWWdkR2hsSUdWMlpXNTBJR3h2YjNBdVhHNGdLaUJBY0dGeVlXMGdlMFoxYm1OMGFXOXVmU0IwWVhOclhHNGdLaTljYmxFdWJtVjRkRlJwWTJzZ1BTQnVaWGgwVkdsamF6dGNibHh1THlvcVhHNGdLaUJEYjI1MGNtOXNjeUIzYUdWMGFHVnlJRzl5SUc1dmRDQnNiMjVuSUhOMFlXTnJJSFJ5WVdObGN5QjNhV3hzSUdKbElHOXVYRzRnS2k5Y2JsRXViRzl1WjFOMFlXTnJVM1Z3Y0c5eWRDQTlJR1poYkhObE8xeHVYRzR2THlCbGJtRmliR1VnYkc5dVp5QnpkR0ZqYTNNZ2FXWWdVVjlFUlVKVlJ5QnBjeUJ6WlhSY2JtbG1JQ2gwZVhCbGIyWWdjSEp2WTJWemN5QTlQVDBnWENKdlltcGxZM1JjSWlBbUppQndjbTlqWlhOeklDWW1JSEJ5YjJObGMzTXVaVzUySUNZbUlIQnliMk5sYzNNdVpXNTJMbEZmUkVWQ1ZVY3BJSHRjYmlBZ0lDQlJMbXh2Ym1kVGRHRmphMU4xY0hCdmNuUWdQU0IwY25WbE8xeHVmVnh1WEc0dktpcGNiaUFxSUVOdmJuTjBjblZqZEhNZ1lTQjdjSEp2YldselpTd2djbVZ6YjJ4MlpTd2djbVZxWldOMGZTQnZZbXBsWTNRdVhHNGdLbHh1SUNvZ1lISmxjMjlzZG1WZ0lHbHpJR0VnWTJGc2JHSmhZMnNnZEc4Z2FXNTJiMnRsSUhkcGRHZ2dZU0J0YjNKbElISmxjMjlzZG1Wa0lIWmhiSFZsSUdadmNpQjBhR1ZjYmlBcUlIQnliMjFwYzJVdUlGUnZJR1oxYkdacGJHd2dkR2hsSUhCeWIyMXBjMlVzSUdsdWRtOXJaU0JnY21WemIyeDJaV0FnZDJsMGFDQmhibmtnZG1Gc2RXVWdkR2hoZENCcGMxeHVJQ29nYm05MElHRWdkR2hsYm1GaWJHVXVJRlJ2SUhKbGFtVmpkQ0IwYUdVZ2NISnZiV2x6WlN3Z2FXNTJiMnRsSUdCeVpYTnZiSFpsWUNCM2FYUm9JR0VnY21WcVpXTjBaV1JjYmlBcUlIUm9aVzVoWW14bExDQnZjaUJwYm5admEyVWdZSEpsYW1WamRHQWdkMmwwYUNCMGFHVWdjbVZoYzI5dUlHUnBjbVZqZEd4NUxpQlVieUJ5WlhOdmJIWmxJSFJvWlZ4dUlDb2djSEp2YldselpTQjBieUJoYm05MGFHVnlJSFJvWlc1aFlteGxMQ0IwYUhWeklIQjFkSFJwYm1jZ2FYUWdhVzRnZEdobElITmhiV1VnYzNSaGRHVXNJR2x1ZG05clpWeHVJQ29nWUhKbGMyOXNkbVZnSUhkcGRHZ2dkR2hoZENCdmRHaGxjaUIwYUdWdVlXSnNaUzVjYmlBcUwxeHVVUzVrWldabGNpQTlJR1JsWm1WeU8xeHVablZ1WTNScGIyNGdaR1ZtWlhJb0tTQjdYRzRnSUNBZ0x5OGdhV1lnWENKdFpYTnpZV2RsYzF3aUlHbHpJR0Z1SUZ3aVFYSnlZWGxjSWl3Z2RHaGhkQ0JwYm1ScFkyRjBaWE1nZEdoaGRDQjBhR1VnY0hKdmJXbHpaU0JvWVhNZ2JtOTBJSGxsZEZ4dUlDQWdJQzh2SUdKbFpXNGdjbVZ6YjJ4MlpXUXVJQ0JKWmlCcGRDQnBjeUJjSW5WdVpHVm1hVzVsWkZ3aUxDQnBkQ0JvWVhNZ1ltVmxiaUJ5WlhOdmJIWmxaQzRnSUVWaFkyaGNiaUFnSUNBdkx5QmxiR1Z0Wlc1MElHOW1JSFJvWlNCdFpYTnpZV2RsY3lCaGNuSmhlU0JwY3lCcGRITmxiR1lnWVc0Z1lYSnlZWGtnYjJZZ1kyOXRjR3hsZEdVZ1lYSm5kVzFsYm5SeklIUnZYRzRnSUNBZ0x5OGdabTl5ZDJGeVpDQjBieUIwYUdVZ2NtVnpiMngyWldRZ2NISnZiV2x6WlM0Z0lGZGxJR052WlhKalpTQjBhR1VnY21WemIyeDFkR2x2YmlCMllXeDFaU0IwYnlCaFhHNGdJQ0FnTHk4Z2NISnZiV2x6WlNCMWMybHVaeUIwYUdVZ1lISmxjMjlzZG1WZ0lHWjFibU4wYVc5dUlHSmxZMkYxYzJVZ2FYUWdhR0Z1Wkd4bGN5QmliM1JvSUdaMWJHeDVYRzRnSUNBZ0x5OGdibTl1TFhSb1pXNWhZbXhsSUhaaGJIVmxjeUJoYm1RZ2IzUm9aWElnZEdobGJtRmliR1Z6SUdkeVlXTmxablZzYkhrdVhHNGdJQ0FnZG1GeUlHMWxjM05oWjJWeklEMGdXMTBzSUhCeWIyZHlaWE56VEdsemRHVnVaWEp6SUQwZ1cxMHNJSEpsYzI5c2RtVmtVSEp2YldselpUdGNibHh1SUNBZ0lIWmhjaUJrWldabGNuSmxaQ0E5SUc5aWFtVmpkRjlqY21WaGRHVW9aR1ZtWlhJdWNISnZkRzkwZVhCbEtUdGNiaUFnSUNCMllYSWdjSEp2YldselpTQTlJRzlpYW1WamRGOWpjbVZoZEdVb1VISnZiV2x6WlM1d2NtOTBiM1I1Y0dVcE8xeHVYRzRnSUNBZ2NISnZiV2x6WlM1d2NtOXRhWE5sUkdsemNHRjBZMmdnUFNCbWRXNWpkR2x2YmlBb2NtVnpiMngyWlN3Z2IzQXNJRzl3WlhKaGJtUnpLU0I3WEc0Z0lDQWdJQ0FnSUhaaGNpQmhjbWR6SUQwZ1lYSnlZWGxmYzJ4cFkyVW9ZWEpuZFcxbGJuUnpLVHRjYmlBZ0lDQWdJQ0FnYVdZZ0tHMWxjM05oWjJWektTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCdFpYTnpZV2RsY3k1d2RYTm9LR0Z5WjNNcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnYVdZZ0tHOXdJRDA5UFNCY0luZG9aVzVjSWlBbUppQnZjR1Z5WVc1a2Mxc3hYU2tnZXlBdkx5QndjbTluY21WemN5QnZjR1Z5WVc1a1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NISnZaM0psYzNOTWFYTjBaVzVsY25NdWNIVnphQ2h2Y0dWeVlXNWtjMXN4WFNrN1hHNGdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQlJMbTVsZUhSVWFXTnJLR1oxYm1OMGFXOXVJQ2dwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeVpYTnZiSFpsWkZCeWIyMXBjMlV1Y0hKdmJXbHpaVVJwYzNCaGRHTm9MbUZ3Y0d4NUtISmxjMjlzZG1Wa1VISnZiV2x6WlN3Z1lYSm5jeWs3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDA3WEc1Y2JpQWdJQ0F2THlCWVdGZ2daR1Z3Y21WallYUmxaRnh1SUNBZ0lIQnliMjFwYzJVdWRtRnNkV1ZQWmlBOUlHWjFibU4wYVc5dUlDZ3BJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tHMWxjM05oWjJWektTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnY0hKdmJXbHpaVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCMllYSWdibVZoY21WeVZtRnNkV1VnUFNCdVpXRnlaWElvY21WemIyeDJaV1JRY205dGFYTmxLVHRjYmlBZ0lDQWdJQ0FnYVdZZ0tHbHpVSEp2YldselpTaHVaV0Z5WlhKV1lXeDFaU2twSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsYzI5c2RtVmtVSEp2YldselpTQTlJRzVsWVhKbGNsWmhiSFZsT3lBdkx5QnphRzl5ZEdWdUlHTm9ZV2x1WEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUc1bFlYSmxjbFpoYkhWbE8xeHVJQ0FnSUgwN1hHNWNiaUFnSUNCd2NtOXRhWE5sTG1sdWMzQmxZM1FnUFNCbWRXNWpkR2x2YmlBb0tTQjdYRzRnSUNBZ0lDQWdJR2xtSUNnaGNtVnpiMngyWldSUWNtOXRhWE5sS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdleUJ6ZEdGMFpUb2dYQ0p3Wlc1a2FXNW5YQ0lnZlR0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2NtVnpiMngyWldSUWNtOXRhWE5sTG1sdWMzQmxZM1FvS1R0Y2JpQWdJQ0I5TzF4dVhHNGdJQ0FnYVdZZ0tGRXViRzl1WjFOMFlXTnJVM1Z3Y0c5eWRDQW1KaUJvWVhOVGRHRmphM01wSUh0Y2JpQWdJQ0FnSUNBZ2RISjVJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIUm9jbTkzSUc1bGR5QkZjbkp2Y2lncE8xeHVJQ0FnSUNBZ0lDQjlJR05oZEdOb0lDaGxLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQXZMeUJPVDFSRk9pQmtiMjRuZENCMGNua2dkRzhnZFhObElHQkZjbkp2Y2k1allYQjBkWEpsVTNSaFkydFVjbUZqWldBZ2IzSWdkSEpoYm5ObVpYSWdkR2hsWEc0Z0lDQWdJQ0FnSUNBZ0lDQXZMeUJoWTJObGMzTnZjaUJoY205MWJtUTdJSFJvWVhRZ1kyRjFjMlZ6SUcxbGJXOXllU0JzWldGcmN5QmhjeUJ3WlhJZ1IwZ3RNVEV4TGlCS2RYTjBYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5QnlaV2xtZVNCMGFHVWdjM1JoWTJzZ2RISmhZMlVnWVhNZ1lTQnpkSEpwYm1jZ1FWTkJVQzVjYmlBZ0lDQWdJQ0FnSUNBZ0lDOHZYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5QkJkQ0IwYUdVZ2MyRnRaU0IwYVcxbExDQmpkWFFnYjJabUlIUm9aU0JtYVhKemRDQnNhVzVsT3lCcGRDZHpJR0ZzZDJGNWN5QnFkWE4wWEc0Z0lDQWdJQ0FnSUNBZ0lDQXZMeUJjSWx0dlltcGxZM1FnVUhKdmJXbHpaVjFjWEc1Y0lpd2dZWE1nY0dWeUlIUm9aU0JnZEc5VGRISnBibWRnTGx4dUlDQWdJQ0FnSUNBZ0lDQWdjSEp2YldselpTNXpkR0ZqYXlBOUlHVXVjM1JoWTJzdWMzVmljM1J5YVc1bktHVXVjM1JoWTJzdWFXNWtaWGhQWmloY0lseGNibHdpS1NBcklERXBPMXh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdmVnh1WEc0Z0lDQWdMeThnVGs5VVJUb2dkMlVnWkc4Z2RHaGxJR05vWldOcmN5Qm1iM0lnWUhKbGMyOXNkbVZrVUhKdmJXbHpaV0FnYVc0Z1pXRmphQ0J0WlhSb2IyUXNJR2x1YzNSbFlXUWdiMlpjYmlBZ0lDQXZMeUJqYjI1emIyeHBaR0YwYVc1bklIUm9aVzBnYVc1MGJ5QmdZbVZqYjIxbFlDd2djMmx1WTJVZ2IzUm9aWEozYVhObElIZGxKMlFnWTNKbFlYUmxJRzVsZDF4dUlDQWdJQzh2SUhCeWIyMXBjMlZ6SUhkcGRHZ2dkR2hsSUd4cGJtVnpJR0JpWldOdmJXVW9kMmhoZEdWMlpYSW9kbUZzZFdVcEtXQXVJRk5sWlNCbExtY3VJRWRJTFRJMU1pNWNibHh1SUNBZ0lHWjFibU4wYVc5dUlHSmxZMjl0WlNodVpYZFFjbTl0YVhObEtTQjdYRzRnSUNBZ0lDQWdJSEpsYzI5c2RtVmtVSEp2YldselpTQTlJRzVsZDFCeWIyMXBjMlU3WEc0Z0lDQWdJQ0FnSUhCeWIyMXBjMlV1YzI5MWNtTmxJRDBnYm1WM1VISnZiV2x6WlR0Y2JseHVJQ0FnSUNBZ0lDQmhjbkpoZVY5eVpXUjFZMlVvYldWemMyRm5aWE1zSUdaMWJtTjBhVzl1SUNoMWJtUmxabWx1WldRc0lHMWxjM05oWjJVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUZFdWJtVjRkRlJwWTJzb1puVnVZM1JwYjI0Z0tDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzVsZDFCeWIyMXBjMlV1Y0hKdmJXbHpaVVJwYzNCaGRHTm9MbUZ3Y0d4NUtHNWxkMUJ5YjIxcGMyVXNJRzFsYzNOaFoyVXBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTazdYRzRnSUNBZ0lDQWdJSDBzSUhadmFXUWdNQ2s3WEc1Y2JpQWdJQ0FnSUNBZ2JXVnpjMkZuWlhNZ1BTQjJiMmxrSURBN1hHNGdJQ0FnSUNBZ0lIQnliMmR5WlhOelRHbHpkR1Z1WlhKeklEMGdkbTlwWkNBd08xeHVJQ0FnSUgxY2JseHVJQ0FnSUdSbFptVnljbVZrTG5CeWIyMXBjMlVnUFNCd2NtOXRhWE5sTzF4dUlDQWdJR1JsWm1WeWNtVmtMbkpsYzI5c2RtVWdQU0JtZFc1amRHbHZiaUFvZG1Gc2RXVXBJSHRjYmlBZ0lDQWdJQ0FnYVdZZ0tISmxjMjlzZG1Wa1VISnZiV2x6WlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVPMXh1SUNBZ0lDQWdJQ0I5WEc1Y2JpQWdJQ0FnSUNBZ1ltVmpiMjFsS0ZFb2RtRnNkV1VwS1R0Y2JpQWdJQ0I5TzF4dVhHNGdJQ0FnWkdWbVpYSnlaV1F1Wm5Wc1ptbHNiQ0E5SUdaMWJtTjBhVzl1SUNoMllXeDFaU2tnZTF4dUlDQWdJQ0FnSUNCcFppQW9jbVZ6YjJ4MlpXUlFjbTl0YVhObEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTQ3WEc0Z0lDQWdJQ0FnSUgxY2JseHVJQ0FnSUNBZ0lDQmlaV052YldVb1puVnNabWxzYkNoMllXeDFaU2twTzF4dUlDQWdJSDA3WEc0Z0lDQWdaR1ZtWlhKeVpXUXVjbVZxWldOMElEMGdablZ1WTNScGIyNGdLSEpsWVhOdmJpa2dlMXh1SUNBZ0lDQWdJQ0JwWmlBb2NtVnpiMngyWldSUWNtOXRhWE5sS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNDdYRzRnSUNBZ0lDQWdJSDFjYmx4dUlDQWdJQ0FnSUNCaVpXTnZiV1VvY21WcVpXTjBLSEpsWVhOdmJpa3BPMXh1SUNBZ0lIMDdYRzRnSUNBZ1pHVm1aWEp5WldRdWJtOTBhV1o1SUQwZ1puVnVZM1JwYjI0Z0tIQnliMmR5WlhOektTQjdYRzRnSUNBZ0lDQWdJR2xtSUNoeVpYTnZiSFpsWkZCeWIyMXBjMlVwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJqdGNiaUFnSUNBZ0lDQWdmVnh1WEc0Z0lDQWdJQ0FnSUdGeWNtRjVYM0psWkhWalpTaHdjbTluY21WemMweHBjM1JsYm1WeWN5d2dablZ1WTNScGIyNGdLSFZ1WkdWbWFXNWxaQ3dnY0hKdlozSmxjM05NYVhOMFpXNWxjaWtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdVUzV1WlhoMFZHbGpheWhtZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NISnZaM0psYzNOTWFYTjBaVzVsY2lod2NtOW5jbVZ6Y3lrN1hHNGdJQ0FnSUNBZ0lDQWdJQ0I5S1R0Y2JpQWdJQ0FnSUNBZ2ZTd2dkbTlwWkNBd0tUdGNiaUFnSUNCOU8xeHVYRzRnSUNBZ2NtVjBkWEp1SUdSbFptVnljbVZrTzF4dWZWeHVYRzR2S2lwY2JpQXFJRU55WldGMFpYTWdZU0JPYjJSbExYTjBlV3hsSUdOaGJHeGlZV05ySUhSb1lYUWdkMmxzYkNCeVpYTnZiSFpsSUc5eUlISmxhbVZqZENCMGFHVWdaR1ZtWlhKeVpXUmNiaUFxSUhCeWIyMXBjMlV1WEc0Z0tpQkFjbVYwZFhKdWN5QmhJRzV2WkdWaVlXTnJYRzRnS2k5Y2JtUmxabVZ5TG5CeWIzUnZkSGx3WlM1dFlXdGxUbTlrWlZKbGMyOXNkbVZ5SUQwZ1puVnVZM1JwYjI0Z0tDa2dlMXh1SUNBZ0lIWmhjaUJ6Wld4bUlEMGdkR2hwY3p0Y2JpQWdJQ0J5WlhSMWNtNGdablZ1WTNScGIyNGdLR1Z5Y205eUxDQjJZV3gxWlNrZ2UxeHVJQ0FnSUNBZ0lDQnBaaUFvWlhKeWIzSXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lITmxiR1l1Y21WcVpXTjBLR1Z5Y205eUtUdGNiaUFnSUNBZ0lDQWdmU0JsYkhObElHbG1JQ2hoY21kMWJXVnVkSE11YkdWdVozUm9JRDRnTWlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYzJWc1ppNXlaWE52YkhabEtHRnljbUY1WDNOc2FXTmxLR0Z5WjNWdFpXNTBjeXdnTVNrcE8xeHVJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYzJWc1ppNXlaWE52YkhabEtIWmhiSFZsS1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUgwN1hHNTlPMXh1WEc0dktpcGNiaUFxSUVCd1lYSmhiU0J5WlhOdmJIWmxjaUI3Um5WdVkzUnBiMjU5SUdFZ1puVnVZM1JwYjI0Z2RHaGhkQ0J5WlhSMWNtNXpJRzV2ZEdocGJtY2dZVzVrSUdGalkyVndkSE5jYmlBcUlIUm9aU0J5WlhOdmJIWmxMQ0J5WldwbFkzUXNJR0Z1WkNCdWIzUnBabmtnWm5WdVkzUnBiMjV6SUdadmNpQmhJR1JsWm1WeWNtVmtMbHh1SUNvZ1FISmxkSFZ5Ym5NZ1lTQndjbTl0YVhObElIUm9ZWFFnYldGNUlHSmxJSEpsYzI5c2RtVmtJSGRwZEdnZ2RHaGxJR2RwZG1WdUlISmxjMjlzZG1VZ1lXNWtJSEpsYW1WamRGeHVJQ29nWm5WdVkzUnBiMjV6TENCdmNpQnlaV3BsWTNSbFpDQmllU0JoSUhSb2NtOTNiaUJsZUdObGNIUnBiMjRnYVc0Z2NtVnpiMngyWlhKY2JpQXFMMXh1VVM1UWNtOXRhWE5sSUQwZ2NISnZiV2x6WlRzZ0x5OGdSVk0yWEc1UkxuQnliMjFwYzJVZ1BTQndjbTl0YVhObE8xeHVablZ1WTNScGIyNGdjSEp2YldselpTaHlaWE52YkhabGNpa2dlMXh1SUNBZ0lHbG1JQ2gwZVhCbGIyWWdjbVZ6YjJ4MlpYSWdJVDA5SUZ3aVpuVnVZM1JwYjI1Y0lpa2dlMXh1SUNBZ0lDQWdJQ0IwYUhKdmR5QnVaWGNnVkhsd1pVVnljbTl5S0Z3aWNtVnpiMngyWlhJZ2JYVnpkQ0JpWlNCaElHWjFibU4wYVc5dUxsd2lLVHRjYmlBZ0lDQjlYRzRnSUNBZ2RtRnlJR1JsWm1WeWNtVmtJRDBnWkdWbVpYSW9LVHRjYmlBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNCeVpYTnZiSFpsY2loa1pXWmxjbkpsWkM1eVpYTnZiSFpsTENCa1pXWmxjbkpsWkM1eVpXcGxZM1FzSUdSbFptVnljbVZrTG01dmRHbG1lU2s3WEc0Z0lDQWdmU0JqWVhSamFDQW9jbVZoYzI5dUtTQjdYRzRnSUNBZ0lDQWdJR1JsWm1WeWNtVmtMbkpsYW1WamRDaHlaV0Z6YjI0cE8xeHVJQ0FnSUgxY2JpQWdJQ0J5WlhSMWNtNGdaR1ZtWlhKeVpXUXVjSEp2YldselpUdGNibjFjYmx4dWNISnZiV2x6WlM1eVlXTmxJRDBnY21GalpUc2dMeThnUlZNMlhHNXdjbTl0YVhObExtRnNiQ0E5SUdGc2JEc2dMeThnUlZNMlhHNXdjbTl0YVhObExuSmxhbVZqZENBOUlISmxhbVZqZERzZ0x5OGdSVk0yWEc1d2NtOXRhWE5sTG5KbGMyOXNkbVVnUFNCUk95QXZMeUJGVXpaY2JseHVMeThnV0ZoWUlHVjRjR1Z5YVcxbGJuUmhiQzRnSUZSb2FYTWdiV1YwYUc5a0lHbHpJR0VnZDJGNUlIUnZJR1JsYm05MFpTQjBhR0YwSUdFZ2JHOWpZV3dnZG1Gc2RXVWdhWE5jYmk4dklITmxjbWxoYkdsNllXSnNaU0JoYm1RZ2MyaHZkV3hrSUdKbElHbHRiV1ZrYVdGMFpXeDVJR1JwYzNCaGRHTm9aV1FnZEc4Z1lTQnlaVzF2ZEdVZ2RYQnZiaUJ5WlhGMVpYTjBMRnh1THk4Z2FXNXpkR1ZoWkNCdlppQndZWE56YVc1bklHRWdjbVZtWlhKbGJtTmxMbHh1VVM1d1lYTnpRbmxEYjNCNUlEMGdablZ1WTNScGIyNGdLRzlpYW1WamRDa2dlMXh1SUNBZ0lDOHZabkpsWlhwbEtHOWlhbVZqZENrN1hHNGdJQ0FnTHk5d1lYTnpRbmxEYjNCcFpYTXVjMlYwS0c5aWFtVmpkQ3dnZEhKMVpTazdYRzRnSUNBZ2NtVjBkWEp1SUc5aWFtVmpkRHRjYm4wN1hHNWNibEJ5YjIxcGMyVXVjSEp2ZEc5MGVYQmxMbkJoYzNOQ2VVTnZjSGtnUFNCbWRXNWpkR2x2YmlBb0tTQjdYRzRnSUNBZ0x5OW1jbVZsZW1Vb2IySnFaV04wS1R0Y2JpQWdJQ0F2TDNCaGMzTkNlVU52Y0dsbGN5NXpaWFFvYjJKcVpXTjBMQ0IwY25WbEtUdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN6dGNibjA3WEc1Y2JpOHFLbHh1SUNvZ1NXWWdkSGR2SUhCeWIyMXBjMlZ6SUdWMlpXNTBkV0ZzYkhrZ1puVnNabWxzYkNCMGJ5QjBhR1VnYzJGdFpTQjJZV3gxWlN3Z2NISnZiV2x6WlhNZ2RHaGhkQ0IyWVd4MVpTeGNiaUFxSUdKMWRDQnZkR2hsY25kcGMyVWdjbVZxWldOMGN5NWNiaUFxSUVCd1lYSmhiU0I0SUh0QmJua3FmVnh1SUNvZ1FIQmhjbUZ0SUhrZ2UwRnVlU3A5WEc0Z0tpQkFjbVYwZFhKdWN5QjdRVzU1S24wZ1lTQndjbTl0YVhObElHWnZjaUI0SUdGdVpDQjVJR2xtSUhSb1pYa2dZWEpsSUhSb1pTQnpZVzFsTENCaWRYUWdZU0J5WldwbFkzUnBiMjVjYmlBcUlHOTBhR1Z5ZDJselpTNWNiaUFxWEc0Z0tpOWNibEV1YW05cGJpQTlJR1oxYm1OMGFXOXVJQ2g0TENCNUtTQjdYRzRnSUNBZ2NtVjBkWEp1SUZFb2VDa3VhbTlwYmloNUtUdGNibjA3WEc1Y2JsQnliMjFwYzJVdWNISnZkRzkwZVhCbExtcHZhVzRnUFNCbWRXNWpkR2x2YmlBb2RHaGhkQ2tnZTF4dUlDQWdJSEpsZEhWeWJpQlJLRnQwYUdsekxDQjBhR0YwWFNrdWMzQnlaV0ZrS0daMWJtTjBhVzl1SUNoNExDQjVLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaDRJRDA5UFNCNUtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5QlVUMFJQT2lCY0lqMDlQVndpSUhOb2IzVnNaQ0JpWlNCUFltcGxZM1F1YVhNZ2IzSWdaWEYxYVhaY2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQjRPMXh1SUNBZ0lDQWdJQ0I5SUdWc2MyVWdlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2RHaHliM2NnYm1WM0lFVnljbTl5S0Z3aVEyRnVKM1FnYW05cGJqb2dibTkwSUhSb1pTQnpZVzFsT2lCY0lpQXJJSGdnS3lCY0lpQmNJaUFySUhrcE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZTazdYRzU5TzF4dVhHNHZLaXBjYmlBcUlGSmxkSFZ5Ym5NZ1lTQndjbTl0YVhObElHWnZjaUIwYUdVZ1ptbHljM1FnYjJZZ1lXNGdZWEp5WVhrZ2IyWWdjSEp2YldselpYTWdkRzhnWW1WamIyMWxJSE5sZEhSc1pXUXVYRzRnS2lCQWNHRnlZVzBnWVc1emQyVnljeUI3UVhKeVlYbGJRVzU1S2wxOUlIQnliMjFwYzJWeklIUnZJSEpoWTJWY2JpQXFJRUJ5WlhSMWNtNXpJSHRCYm5rcWZTQjBhR1VnWm1seWMzUWdjSEp2YldselpTQjBieUJpWlNCelpYUjBiR1ZrWEc0Z0tpOWNibEV1Y21GalpTQTlJSEpoWTJVN1hHNW1kVzVqZEdsdmJpQnlZV05sS0dGdWMzZGxjbEJ6S1NCN1hHNGdJQ0FnY21WMGRYSnVJSEJ5YjIxcGMyVW9ablZ1WTNScGIyNGdLSEpsYzI5c2RtVXNJSEpsYW1WamRDa2dlMXh1SUNBZ0lDQWdJQ0F2THlCVGQybDBZMmdnZEc4Z2RHaHBjeUJ2Ym1ObElIZGxJR05oYmlCaGMzTjFiV1VnWVhRZ2JHVmhjM1FnUlZNMVhHNGdJQ0FnSUNBZ0lDOHZJR0Z1YzNkbGNsQnpMbVp2Y2tWaFkyZ29ablZ1WTNScGIyNGdLR0Z1YzNkbGNsQXBJSHRjYmlBZ0lDQWdJQ0FnTHk4Z0lDQWdJRkVvWVc1emQyVnlVQ2t1ZEdobGJpaHlaWE52YkhabExDQnlaV3BsWTNRcE8xeHVJQ0FnSUNBZ0lDQXZMeUI5S1R0Y2JpQWdJQ0FnSUNBZ0x5OGdWWE5sSUhSb2FYTWdhVzRnZEdobElHMWxZVzUwYVcxbFhHNGdJQ0FnSUNBZ0lHWnZjaUFvZG1GeUlHa2dQU0F3TENCc1pXNGdQU0JoYm5OM1pYSlFjeTVzWlc1bmRHZzdJR2tnUENCc1pXNDdJR2tyS3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnVVNoaGJuTjNaWEpRYzF0cFhTa3VkR2hsYmloeVpYTnZiSFpsTENCeVpXcGxZM1FwTzF4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnZlNrN1hHNTlYRzVjYmxCeWIyMXBjMlV1Y0hKdmRHOTBlWEJsTG5KaFkyVWdQU0JtZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnY21WMGRYSnVJSFJvYVhNdWRHaGxiaWhSTG5KaFkyVXBPMXh1ZlR0Y2JseHVMeW9xWEc0Z0tpQkRiMjV6ZEhKMVkzUnpJR0VnVUhKdmJXbHpaU0IzYVhSb0lHRWdjSEp2YldselpTQmtaWE5qY21sd2RHOXlJRzlpYW1WamRDQmhibVFnYjNCMGFXOXVZV3dnWm1Gc2JHSmhZMnRjYmlBcUlHWjFibU4wYVc5dUxpQWdWR2hsSUdSbGMyTnlhWEIwYjNJZ1kyOXVkR0ZwYm5NZ2JXVjBhRzlrY3lCc2FXdGxJSGRvWlc0b2NtVnFaV04wWldRcExDQm5aWFFvYm1GdFpTa3NYRzRnS2lCelpYUW9ibUZ0WlN3Z2RtRnNkV1VwTENCd2IzTjBLRzVoYldVc0lHRnlaM01wTENCaGJtUWdaR1ZzWlhSbEtHNWhiV1VwTENCM2FHbGphQ0JoYkd4Y2JpQXFJSEpsZEhWeWJpQmxhWFJvWlhJZ1lTQjJZV3gxWlN3Z1lTQndjbTl0YVhObElHWnZjaUJoSUhaaGJIVmxMQ0J2Y2lCaElISmxhbVZqZEdsdmJpNGdJRlJvWlNCbVlXeHNZbUZqYTF4dUlDb2dZV05qWlhCMGN5QjBhR1VnYjNCbGNtRjBhVzl1SUc1aGJXVXNJR0VnY21WemIyeDJaWElzSUdGdVpDQmhibmtnWm5WeWRHaGxjaUJoY21kMWJXVnVkSE1nZEdoaGRDQjNiM1ZzWkZ4dUlDb2dhR0YyWlNCaVpXVnVJR1p2Y25kaGNtUmxaQ0IwYnlCMGFHVWdZWEJ3Y205d2NtbGhkR1VnYldWMGFHOWtJR0ZpYjNabElHaGhaQ0JoSUcxbGRHaHZaQ0JpWldWdVhHNGdLaUJ3Y205MmFXUmxaQ0IzYVhSb0lIUm9aU0J3Y205d1pYSWdibUZ0WlM0Z0lGUm9aU0JCVUVrZ2JXRnJaWE1nYm04Z1ozVmhjbUZ1ZEdWbGN5QmhZbTkxZENCMGFHVWdibUYwZFhKbFhHNGdLaUJ2WmlCMGFHVWdjbVYwZFhKdVpXUWdiMkpxWldOMExDQmhjR0Z5ZENCbWNtOXRJSFJvWVhRZ2FYUWdhWE1nZFhOaFlteGxJSGRvWlhKbFpYWmxjaUJ3Y205dGFYTmxjeUJoY21WY2JpQXFJR0p2ZFdkb2RDQmhibVFnYzI5c1pDNWNiaUFxTDF4dVVTNXRZV3RsVUhKdmJXbHpaU0E5SUZCeWIyMXBjMlU3WEc1bWRXNWpkR2x2YmlCUWNtOXRhWE5sS0dSbGMyTnlhWEIwYjNJc0lHWmhiR3hpWVdOckxDQnBibk53WldOMEtTQjdYRzRnSUNBZ2FXWWdLR1poYkd4aVlXTnJJRDA5UFNCMmIybGtJREFwSUh0Y2JpQWdJQ0FnSUNBZ1ptRnNiR0poWTJzZ1BTQm1kVzVqZEdsdmJpQW9iM0FwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnlaV3BsWTNRb2JtVjNJRVZ5Y205eUtGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lGd2lVSEp2YldselpTQmtiMlZ6SUc1dmRDQnpkWEJ3YjNKMElHOXdaWEpoZEdsdmJqb2dYQ0lnS3lCdmNGeHVJQ0FnSUNBZ0lDQWdJQ0FnS1NrN1hHNGdJQ0FnSUNBZ0lIMDdYRzRnSUNBZ2ZWeHVJQ0FnSUdsbUlDaHBibk53WldOMElEMDlQU0IyYjJsa0lEQXBJSHRjYmlBZ0lDQWdJQ0FnYVc1emNHVmpkQ0E5SUdaMWJtTjBhVzl1SUNncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUI3YzNSaGRHVTZJRndpZFc1cmJtOTNibHdpZlR0Y2JpQWdJQ0FnSUNBZ2ZUdGNiaUFnSUNCOVhHNWNiaUFnSUNCMllYSWdjSEp2YldselpTQTlJRzlpYW1WamRGOWpjbVZoZEdVb1VISnZiV2x6WlM1d2NtOTBiM1I1Y0dVcE8xeHVYRzRnSUNBZ2NISnZiV2x6WlM1d2NtOXRhWE5sUkdsemNHRjBZMmdnUFNCbWRXNWpkR2x2YmlBb2NtVnpiMngyWlN3Z2IzQXNJR0Z5WjNNcElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUhKbGMzVnNkRHRjYmlBZ0lDQWdJQ0FnZEhKNUlIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaGtaWE5qY21sd2RHOXlXMjl3WFNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lISmxjM1ZzZENBOUlHUmxjMk55YVhCMGIzSmJiM0JkTG1Gd2NHeDVLSEJ5YjIxcGMyVXNJR0Z5WjNNcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnZlNCbGJITmxJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J5WlhOMWJIUWdQU0JtWVd4c1ltRmpheTVqWVd4c0tIQnliMjFwYzJVc0lHOXdMQ0JoY21kektUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTQmpZWFJqYUNBb1pYaGpaWEIwYVc5dUtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYTjFiSFFnUFNCeVpXcGxZM1FvWlhoalpYQjBhVzl1S1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQnBaaUFvY21WemIyeDJaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdjbVZ6YjJ4MlpTaHlaWE4xYkhRcE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZUdGNibHh1SUNBZ0lIQnliMjFwYzJVdWFXNXpjR1ZqZENBOUlHbHVjM0JsWTNRN1hHNWNiaUFnSUNBdkx5QllXRmdnWkdWd2NtVmpZWFJsWkNCZ2RtRnNkV1ZQWm1BZ1lXNWtJR0JsZUdObGNIUnBiMjVnSUhOMWNIQnZjblJjYmlBZ0lDQnBaaUFvYVc1emNHVmpkQ2tnZTF4dUlDQWdJQ0FnSUNCMllYSWdhVzV6Y0dWamRHVmtJRDBnYVc1emNHVmpkQ2dwTzF4dUlDQWdJQ0FnSUNCcFppQW9hVzV6Y0dWamRHVmtMbk4wWVhSbElEMDlQU0JjSW5KbGFtVmpkR1ZrWENJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhCeWIyMXBjMlV1WlhoalpYQjBhVzl1SUQwZ2FXNXpjR1ZqZEdWa0xuSmxZWE52Ymp0Y2JpQWdJQ0FnSUNBZ2ZWeHVYRzRnSUNBZ0lDQWdJSEJ5YjIxcGMyVXVkbUZzZFdWUFppQTlJR1oxYm1OMGFXOXVJQ2dwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFpoY2lCcGJuTndaV04wWldRZ1BTQnBibk53WldOMEtDazdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9hVzV6Y0dWamRHVmtMbk4wWVhSbElEMDlQU0JjSW5CbGJtUnBibWRjSWlCOGZGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbHVjM0JsWTNSbFpDNXpkR0YwWlNBOVBUMGdYQ0p5WldwbFkzUmxaRndpS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhCeWIyMXBjMlU3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnYVc1emNHVmpkR1ZrTG5aaGJIVmxPMXh1SUNBZ0lDQWdJQ0I5TzF4dUlDQWdJSDFjYmx4dUlDQWdJSEpsZEhWeWJpQndjbTl0YVhObE8xeHVmVnh1WEc1UWNtOXRhWE5sTG5CeWIzUnZkSGx3WlM1MGIxTjBjbWx1WnlBOUlHWjFibU4wYVc5dUlDZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z1hDSmJiMkpxWldOMElGQnliMjFwYzJWZFhDSTdYRzU5TzF4dVhHNVFjbTl0YVhObExuQnliM1J2ZEhsd1pTNTBhR1Z1SUQwZ1puVnVZM1JwYjI0Z0tHWjFiR1pwYkd4bFpDd2djbVZxWldOMFpXUXNJSEJ5YjJkeVpYTnpaV1FwSUh0Y2JpQWdJQ0IyWVhJZ2MyVnNaaUE5SUhSb2FYTTdYRzRnSUNBZ2RtRnlJR1JsWm1WeWNtVmtJRDBnWkdWbVpYSW9LVHRjYmlBZ0lDQjJZWElnWkc5dVpTQTlJR1poYkhObE95QWdJQzh2SUdWdWMzVnlaU0IwYUdVZ2RXNTBjblZ6ZEdWa0lIQnliMjFwYzJVZ2JXRnJaWE1nWVhRZ2JXOXpkQ0JoWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0F2THlCemFXNW5iR1VnWTJGc2JDQjBieUJ2Ym1VZ2IyWWdkR2hsSUdOaGJHeGlZV05yYzF4dVhHNGdJQ0FnWm5WdVkzUnBiMjRnWDJaMWJHWnBiR3hsWkNoMllXeDFaU2tnZTF4dUlDQWdJQ0FnSUNCMGNua2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhSNWNHVnZaaUJtZFd4bWFXeHNaV1FnUFQwOUlGd2lablZ1WTNScGIyNWNJaUEvSUdaMWJHWnBiR3hsWkNoMllXeDFaU2tnT2lCMllXeDFaVHRjYmlBZ0lDQWdJQ0FnZlNCallYUmphQ0FvWlhoalpYQjBhVzl1S1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdjbVZxWldOMEtHVjRZMlZ3ZEdsdmJpazdYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQjlYRzVjYmlBZ0lDQm1kVzVqZEdsdmJpQmZjbVZxWldOMFpXUW9aWGhqWlhCMGFXOXVLU0I3WEc0Z0lDQWdJQ0FnSUdsbUlDaDBlWEJsYjJZZ2NtVnFaV04wWldRZ1BUMDlJRndpWm5WdVkzUnBiMjVjSWlrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnYldGclpWTjBZV05yVkhKaFkyVk1iMjVuS0dWNFkyVndkR2x2Yml3Z2MyVnNaaWs3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJ5WldwbFkzUmxaQ2hsZUdObGNIUnBiMjRwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JqWVhSamFDQW9ibVYzUlhoalpYQjBhVzl1S1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKbGFtVmpkQ2h1WlhkRmVHTmxjSFJwYjI0cE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCeVpXcGxZM1FvWlhoalpYQjBhVzl1S1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0JtZFc1amRHbHZiaUJmY0hKdlozSmxjM05sWkNoMllXeDFaU2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZEhsd1pXOW1JSEJ5YjJkeVpYTnpaV1FnUFQwOUlGd2lablZ1WTNScGIyNWNJaUEvSUhCeWIyZHlaWE56WldRb2RtRnNkV1VwSURvZ2RtRnNkV1U3WEc0Z0lDQWdmVnh1WEc0Z0lDQWdVUzV1WlhoMFZHbGpheWhtZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnSUNBZ0lITmxiR1l1Y0hKdmJXbHpaVVJwYzNCaGRHTm9LR1oxYm1OMGFXOXVJQ2gyWVd4MVpTa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR1J2Ym1VcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnlaWFIxY200N1hHNGdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQmtiMjVsSUQwZ2RISjFaVHRjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdaR1ZtWlhKeVpXUXVjbVZ6YjJ4MlpTaGZablZzWm1sc2JHVmtLSFpoYkhWbEtTazdYRzRnSUNBZ0lDQWdJSDBzSUZ3aWQyaGxibHdpTENCYlpuVnVZM1JwYjI0Z0tHVjRZMlZ3ZEdsdmJpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR1J2Ym1VcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnlaWFIxY200N1hHNGdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUNBZ0lDQmtiMjVsSUQwZ2RISjFaVHRjYmx4dUlDQWdJQ0FnSUNBZ0lDQWdaR1ZtWlhKeVpXUXVjbVZ6YjJ4MlpTaGZjbVZxWldOMFpXUW9aWGhqWlhCMGFXOXVLU2s3WEc0Z0lDQWdJQ0FnSUgxZEtUdGNiaUFnSUNCOUtUdGNibHh1SUNBZ0lDOHZJRkJ5YjJkeVpYTnpJSEJ5YjNCaFoyRjBiM0lnYm1WbFpDQjBieUJpWlNCaGRIUmhZMmhsWkNCcGJpQjBhR1VnWTNWeWNtVnVkQ0IwYVdOckxseHVJQ0FnSUhObGJHWXVjSEp2YldselpVUnBjM0JoZEdOb0tIWnZhV1FnTUN3Z1hDSjNhR1Z1WENJc0lGdDJiMmxrSURBc0lHWjFibU4wYVc5dUlDaDJZV3gxWlNrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnYm1WM1ZtRnNkV1U3WEc0Z0lDQWdJQ0FnSUhaaGNpQjBhSEpsZHlBOUlHWmhiSE5sTzF4dUlDQWdJQ0FnSUNCMGNua2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2JtVjNWbUZzZFdVZ1BTQmZjSEp2WjNKbGMzTmxaQ2gyWVd4MVpTazdYRzRnSUNBZ0lDQWdJSDBnWTJGMFkyZ2dLR1VwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFJvY21WM0lEMGdkSEoxWlR0Y2JpQWdJQ0FnSUNBZ0lDQWdJR2xtSUNoUkxtOXVaWEp5YjNJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQlJMbTl1WlhKeWIzSW9aU2s3WEc0Z0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIUm9jbTkzSUdVN1hHNGdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUgxY2JseHVJQ0FnSUNBZ0lDQnBaaUFvSVhSb2NtVjNLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQmtaV1psY25KbFpDNXViM1JwWm5rb2JtVjNWbUZzZFdVcE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ2ZWMHBPMXh1WEc0Z0lDQWdjbVYwZFhKdUlHUmxabVZ5Y21Wa0xuQnliMjFwYzJVN1hHNTlPMXh1WEc1UkxuUmhjQ0E5SUdaMWJtTjBhVzl1SUNod2NtOXRhWE5sTENCallXeHNZbUZqYXlrZ2UxeHVJQ0FnSUhKbGRIVnliaUJSS0hCeWIyMXBjMlVwTG5SaGNDaGpZV3hzWW1GamF5azdYRzU5TzF4dVhHNHZLaXBjYmlBcUlGZHZjbXR6SUdGc2JXOXpkQ0JzYVd0bElGd2labWx1WVd4c2VWd2lMQ0JpZFhRZ2JtOTBJR05oYkd4bFpDQm1iM0lnY21WcVpXTjBhVzl1Y3k1Y2JpQXFJRTl5YVdkcGJtRnNJSEpsYzI5c2RYUnBiMjRnZG1Gc2RXVWdhWE1nY0dGemMyVmtJSFJvY205MVoyZ2dZMkZzYkdKaFkyc2dkVzVoWm1abFkzUmxaQzVjYmlBcUlFTmhiR3hpWVdOcklHMWhlU0J5WlhSMWNtNGdZU0J3Y205dGFYTmxJSFJvWVhRZ2QybHNiQ0JpWlNCaGQyRnBkR1ZrSUdadmNpNWNiaUFxSUVCd1lYSmhiU0I3Um5WdVkzUnBiMjU5SUdOaGJHeGlZV05yWEc0Z0tpQkFjbVYwZFhKdWN5QjdVUzVRY205dGFYTmxmVnh1SUNvZ1FHVjRZVzF3YkdWY2JpQXFJR1J2VTI5dFpYUm9hVzVuS0NsY2JpQXFJQ0FnTG5Sb1pXNG9MaTR1S1Z4dUlDb2dJQ0F1ZEdGd0tHTnZibk52YkdVdWJHOW5LVnh1SUNvZ0lDQXVkR2hsYmlndUxpNHBPMXh1SUNvdlhHNVFjbTl0YVhObExuQnliM1J2ZEhsd1pTNTBZWEFnUFNCbWRXNWpkR2x2YmlBb1kyRnNiR0poWTJzcElIdGNiaUFnSUNCallXeHNZbUZqYXlBOUlGRW9ZMkZzYkdKaFkyc3BPMXh1WEc0Z0lDQWdjbVYwZFhKdUlIUm9hWE11ZEdobGJpaG1kVzVqZEdsdmJpQW9kbUZzZFdVcElIdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlHTmhiR3hpWVdOckxtWmpZV3hzS0haaGJIVmxLUzUwYUdWdVVtVnpiMngyWlNoMllXeDFaU2s3WEc0Z0lDQWdmU2s3WEc1OU8xeHVYRzR2S2lwY2JpQXFJRkpsWjJsemRHVnljeUJoYmlCdlluTmxjblpsY2lCdmJpQmhJSEJ5YjIxcGMyVXVYRzRnS2x4dUlDb2dSM1ZoY21GdWRHVmxjenBjYmlBcVhHNGdLaUF4TGlCMGFHRjBJR1oxYkdacGJHeGxaQ0JoYm1RZ2NtVnFaV04wWldRZ2QybHNiQ0JpWlNCallXeHNaV1FnYjI1c2VTQnZibU5sTGx4dUlDb2dNaTRnZEdoaGRDQmxhWFJvWlhJZ2RHaGxJR1oxYkdacGJHeGxaQ0JqWVd4c1ltRmpheUJ2Y2lCMGFHVWdjbVZxWldOMFpXUWdZMkZzYkdKaFkyc2dkMmxzYkNCaVpWeHVJQ29nSUNBZ1kyRnNiR1ZrTENCaWRYUWdibTkwSUdKdmRHZ3VYRzRnS2lBekxpQjBhR0YwSUdaMWJHWnBiR3hsWkNCaGJtUWdjbVZxWldOMFpXUWdkMmxzYkNCdWIzUWdZbVVnWTJGc2JHVmtJR2x1SUhSb2FYTWdkSFZ5Ymk1Y2JpQXFYRzRnS2lCQWNHRnlZVzBnZG1Gc2RXVWdJQ0FnSUNCd2NtOXRhWE5sSUc5eUlHbHRiV1ZrYVdGMFpTQnlaV1psY21WdVkyVWdkRzhnYjJKelpYSjJaVnh1SUNvZ1FIQmhjbUZ0SUdaMWJHWnBiR3hsWkNBZ1puVnVZM1JwYjI0Z2RHOGdZbVVnWTJGc2JHVmtJSGRwZEdnZ2RHaGxJR1oxYkdacGJHeGxaQ0IyWVd4MVpWeHVJQ29nUUhCaGNtRnRJSEpsYW1WamRHVmtJQ0FnWm5WdVkzUnBiMjRnZEc4Z1ltVWdZMkZzYkdWa0lIZHBkR2dnZEdobElISmxhbVZqZEdsdmJpQmxlR05sY0hScGIyNWNiaUFxSUVCd1lYSmhiU0J3Y205bmNtVnpjMlZrSUdaMWJtTjBhVzl1SUhSdklHSmxJR05oYkd4bFpDQnZiaUJoYm5rZ2NISnZaM0psYzNNZ2JtOTBhV1pwWTJGMGFXOXVjMXh1SUNvZ1FISmxkSFZ5YmlCd2NtOXRhWE5sSUdadmNpQjBhR1VnY21WMGRYSnVJSFpoYkhWbElHWnliMjBnZEdobElHbHVkbTlyWldRZ1kyRnNiR0poWTJ0Y2JpQXFMMXh1VVM1M2FHVnVJRDBnZDJobGJqdGNibVoxYm1OMGFXOXVJSGRvWlc0b2RtRnNkV1VzSUdaMWJHWnBiR3hsWkN3Z2NtVnFaV04wWldRc0lIQnliMmR5WlhOelpXUXBJSHRjYmlBZ0lDQnlaWFIxY200Z1VTaDJZV3gxWlNrdWRHaGxiaWhtZFd4bWFXeHNaV1FzSUhKbGFtVmpkR1ZrTENCd2NtOW5jbVZ6YzJWa0tUdGNibjFjYmx4dVVISnZiV2x6WlM1d2NtOTBiM1I1Y0dVdWRHaGxibEpsYzI5c2RtVWdQU0JtZFc1amRHbHZiaUFvZG1Gc2RXVXBJSHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTUwYUdWdUtHWjFibU4wYVc5dUlDZ3BJSHNnY21WMGRYSnVJSFpoYkhWbE95QjlLVHRjYm4wN1hHNWNibEV1ZEdobGJsSmxjMjlzZG1VZ1BTQm1kVzVqZEdsdmJpQW9jSEp2YldselpTd2dkbUZzZFdVcElIdGNiaUFnSUNCeVpYUjFjbTRnVVNod2NtOXRhWE5sS1M1MGFHVnVVbVZ6YjJ4MlpTaDJZV3gxWlNrN1hHNTlPMXh1WEc1UWNtOXRhWE5sTG5CeWIzUnZkSGx3WlM1MGFHVnVVbVZxWldOMElEMGdablZ1WTNScGIyNGdLSEpsWVhOdmJpa2dlMXh1SUNBZ0lISmxkSFZ5YmlCMGFHbHpMblJvWlc0b1puVnVZM1JwYjI0Z0tDa2dleUIwYUhKdmR5QnlaV0Z6YjI0N0lIMHBPMXh1ZlR0Y2JseHVVUzUwYUdWdVVtVnFaV04wSUQwZ1puVnVZM1JwYjI0Z0tIQnliMjFwYzJVc0lISmxZWE52YmlrZ2UxeHVJQ0FnSUhKbGRIVnliaUJSS0hCeWIyMXBjMlVwTG5Sb1pXNVNaV3BsWTNRb2NtVmhjMjl1S1R0Y2JuMDdYRzVjYmk4cUtseHVJQ29nU1dZZ1lXNGdiMkpxWldOMElHbHpJRzV2ZENCaElIQnliMjFwYzJVc0lHbDBJR2x6SUdGeklGd2libVZoY2x3aUlHRnpJSEJ2YzNOcFlteGxMbHh1SUNvZ1NXWWdZU0J3Y205dGFYTmxJR2x6SUhKbGFtVmpkR1ZrTENCcGRDQnBjeUJoY3lCY0ltNWxZWEpjSWlCaGN5QndiM056YVdKc1pTQjBiMjh1WEc0Z0tpQkpaaUJwZE9LQW1YTWdZU0JtZFd4bWFXeHNaV1FnY0hKdmJXbHpaU3dnZEdobElHWjFiR1pwYkd4dFpXNTBJSFpoYkhWbElHbHpJRzVsWVhKbGNpNWNiaUFxSUVsbUlHbDA0b0NaY3lCaElHUmxabVZ5Y21Wa0lIQnliMjFwYzJVZ1lXNWtJSFJvWlNCa1pXWmxjbkpsWkNCb1lYTWdZbVZsYmlCeVpYTnZiSFpsWkN3Z2RHaGxYRzRnS2lCeVpYTnZiSFYwYVc5dUlHbHpJRndpYm1WaGNtVnlYQ0l1WEc0Z0tpQkFjR0Z5WVcwZ2IySnFaV04wWEc0Z0tpQkFjbVYwZFhKdWN5QnRiM04wSUhKbGMyOXNkbVZrSUNodVpXRnlaWE4wS1NCbWIzSnRJRzltSUhSb1pTQnZZbXBsWTNSY2JpQXFMMXh1WEc0dkx5QllXRmdnYzJodmRXeGtJSGRsSUhKbExXUnZJSFJvYVhNL1hHNVJMbTVsWVhKbGNpQTlJRzVsWVhKbGNqdGNibVoxYm1OMGFXOXVJRzVsWVhKbGNpaDJZV3gxWlNrZ2UxeHVJQ0FnSUdsbUlDaHBjMUJ5YjIxcGMyVW9kbUZzZFdVcEtTQjdYRzRnSUNBZ0lDQWdJSFpoY2lCcGJuTndaV04wWldRZ1BTQjJZV3gxWlM1cGJuTndaV04wS0NrN1hHNGdJQ0FnSUNBZ0lHbG1JQ2hwYm5Od1pXTjBaV1F1YzNSaGRHVWdQVDA5SUZ3aVpuVnNabWxzYkdWa1hDSXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lISmxkSFZ5YmlCcGJuTndaV04wWldRdWRtRnNkV1U3WEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0I5WEc0Z0lDQWdjbVYwZFhKdUlIWmhiSFZsTzF4dWZWeHVYRzR2S2lwY2JpQXFJRUJ5WlhSMWNtNXpJSGRvWlhSb1pYSWdkR2hsSUdkcGRtVnVJRzlpYW1WamRDQnBjeUJoSUhCeWIyMXBjMlV1WEc0Z0tpQlBkR2hsY25kcGMyVWdhWFFnYVhNZ1lTQm1kV3htYVd4c1pXUWdkbUZzZFdVdVhHNGdLaTljYmxFdWFYTlFjbTl0YVhObElEMGdhWE5RY205dGFYTmxPMXh1Wm5WdVkzUnBiMjRnYVhOUWNtOXRhWE5sS0c5aWFtVmpkQ2tnZTF4dUlDQWdJSEpsZEhWeWJpQnZZbXBsWTNRZ2FXNXpkR0Z1WTJWdlppQlFjbTl0YVhObE8xeHVmVnh1WEc1UkxtbHpVSEp2YldselpVRnNhV3RsSUQwZ2FYTlFjbTl0YVhObFFXeHBhMlU3WEc1bWRXNWpkR2x2YmlCcGMxQnliMjFwYzJWQmJHbHJaU2h2WW1wbFkzUXBJSHRjYmlBZ0lDQnlaWFIxY200Z2FYTlBZbXBsWTNRb2IySnFaV04wS1NBbUppQjBlWEJsYjJZZ2IySnFaV04wTG5Sb1pXNGdQVDA5SUZ3aVpuVnVZM1JwYjI1Y0lqdGNibjFjYmx4dUx5b3FYRzRnS2lCQWNtVjBkWEp1Y3lCM2FHVjBhR1Z5SUhSb1pTQm5hWFpsYmlCdlltcGxZM1FnYVhNZ1lTQndaVzVrYVc1bklIQnliMjFwYzJVc0lHMWxZVzVwYm1jZ2JtOTBYRzRnS2lCbWRXeG1hV3hzWldRZ2IzSWdjbVZxWldOMFpXUXVYRzRnS2k5Y2JsRXVhWE5RWlc1a2FXNW5JRDBnYVhOUVpXNWthVzVuTzF4dVpuVnVZM1JwYjI0Z2FYTlFaVzVrYVc1bktHOWlhbVZqZENrZ2UxeHVJQ0FnSUhKbGRIVnliaUJwYzFCeWIyMXBjMlVvYjJKcVpXTjBLU0FtSmlCdlltcGxZM1F1YVc1emNHVmpkQ2dwTG5OMFlYUmxJRDA5UFNCY0luQmxibVJwYm1kY0lqdGNibjFjYmx4dVVISnZiV2x6WlM1d2NtOTBiM1I1Y0dVdWFYTlFaVzVrYVc1bklEMGdablZ1WTNScGIyNGdLQ2tnZTF4dUlDQWdJSEpsZEhWeWJpQjBhR2x6TG1sdWMzQmxZM1FvS1M1emRHRjBaU0E5UFQwZ1hDSndaVzVrYVc1blhDSTdYRzU5TzF4dVhHNHZLaXBjYmlBcUlFQnlaWFIxY201eklIZG9aWFJvWlhJZ2RHaGxJR2RwZG1WdUlHOWlhbVZqZENCcGN5QmhJSFpoYkhWbElHOXlJR1oxYkdacGJHeGxaRnh1SUNvZ2NISnZiV2x6WlM1Y2JpQXFMMXh1VVM1cGMwWjFiR1pwYkd4bFpDQTlJR2x6Um5Wc1ptbHNiR1ZrTzF4dVpuVnVZM1JwYjI0Z2FYTkdkV3htYVd4c1pXUW9iMkpxWldOMEtTQjdYRzRnSUNBZ2NtVjBkWEp1SUNGcGMxQnliMjFwYzJVb2IySnFaV04wS1NCOGZDQnZZbXBsWTNRdWFXNXpjR1ZqZENncExuTjBZWFJsSUQwOVBTQmNJbVoxYkdacGJHeGxaRndpTzF4dWZWeHVYRzVRY205dGFYTmxMbkJ5YjNSdmRIbHdaUzVwYzBaMWJHWnBiR3hsWkNBOUlHWjFibU4wYVc5dUlDZ3BJSHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVwYm5Od1pXTjBLQ2t1YzNSaGRHVWdQVDA5SUZ3aVpuVnNabWxzYkdWa1hDSTdYRzU5TzF4dVhHNHZLaXBjYmlBcUlFQnlaWFIxY201eklIZG9aWFJvWlhJZ2RHaGxJR2RwZG1WdUlHOWlhbVZqZENCcGN5QmhJSEpsYW1WamRHVmtJSEJ5YjIxcGMyVXVYRzRnS2k5Y2JsRXVhWE5TWldwbFkzUmxaQ0E5SUdselVtVnFaV04wWldRN1hHNW1kVzVqZEdsdmJpQnBjMUpsYW1WamRHVmtLRzlpYW1WamRDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCcGMxQnliMjFwYzJVb2IySnFaV04wS1NBbUppQnZZbXBsWTNRdWFXNXpjR1ZqZENncExuTjBZWFJsSUQwOVBTQmNJbkpsYW1WamRHVmtYQ0k3WEc1OVhHNWNibEJ5YjIxcGMyVXVjSEp2ZEc5MGVYQmxMbWx6VW1WcVpXTjBaV1FnUFNCbWRXNWpkR2x2YmlBb0tTQjdYRzRnSUNBZ2NtVjBkWEp1SUhSb2FYTXVhVzV6Y0dWamRDZ3BMbk4wWVhSbElEMDlQU0JjSW5KbGFtVmpkR1ZrWENJN1hHNTlPMXh1WEc0dkx5OHZJRUpGUjBsT0lGVk9TRUZPUkV4RlJDQlNSVXBGUTFSSlQwNGdWRkpCUTB0SlRrZGNibHh1THk4Z1ZHaHBjeUJ3Y205dGFYTmxJR3hwWW5KaGNua2dZMjl1YzNWdFpYTWdaWGhqWlhCMGFXOXVjeUIwYUhKdmQyNGdhVzRnYUdGdVpHeGxjbk1nYzI4Z2RHaGxlU0JqWVc0Z1ltVmNiaTh2SUdoaGJtUnNaV1FnWW5rZ1lTQnpkV0p6WlhGMVpXNTBJSEJ5YjIxcGMyVXVJQ0JVYUdVZ1pYaGpaWEIwYVc5dWN5Qm5aWFFnWVdSa1pXUWdkRzhnZEdocGN5QmhjbkpoZVNCM2FHVnVYRzR2THlCMGFHVjVJR0Z5WlNCamNtVmhkR1ZrTENCaGJtUWdjbVZ0YjNabFpDQjNhR1Z1SUhSb1pYa2dZWEpsSUdoaGJtUnNaV1F1SUNCT2IzUmxJSFJvWVhRZ2FXNGdSVk0ySUc5eVhHNHZMeUJ6YUdsdGJXVmtJR1Z1ZG1seWIyNXRaVzUwY3l3Z2RHaHBjeUIzYjNWc1pDQnVZWFIxY21Gc2JIa2dZbVVnWVNCZ1UyVjBZQzVjYm5aaGNpQjFibWhoYm1Sc1pXUlNaV0Z6YjI1eklEMGdXMTA3WEc1MllYSWdkVzVvWVc1a2JHVmtVbVZxWldOMGFXOXVjeUE5SUZ0ZE8xeHVkbUZ5SUhKbGNHOXlkR1ZrVlc1b1lXNWtiR1ZrVW1WcVpXTjBhVzl1Y3lBOUlGdGRPMXh1ZG1GeUlIUnlZV05yVlc1b1lXNWtiR1ZrVW1WcVpXTjBhVzl1Y3lBOUlIUnlkV1U3WEc1Y2JtWjFibU4wYVc5dUlISmxjMlYwVlc1b1lXNWtiR1ZrVW1WcVpXTjBhVzl1Y3lncElIdGNiaUFnSUNCMWJtaGhibVJzWldSU1pXRnpiMjV6TG14bGJtZDBhQ0E5SURBN1hHNGdJQ0FnZFc1b1lXNWtiR1ZrVW1WcVpXTjBhVzl1Y3k1c1pXNW5kR2dnUFNBd08xeHVYRzRnSUNBZ2FXWWdLQ0YwY21GamExVnVhR0Z1Wkd4bFpGSmxhbVZqZEdsdmJuTXBJSHRjYmlBZ0lDQWdJQ0FnZEhKaFkydFZibWhoYm1Sc1pXUlNaV3BsWTNScGIyNXpJRDBnZEhKMVpUdGNiaUFnSUNCOVhHNTlYRzVjYm1aMWJtTjBhVzl1SUhSeVlXTnJVbVZxWldOMGFXOXVLSEJ5YjIxcGMyVXNJSEpsWVhOdmJpa2dlMXh1SUNBZ0lHbG1JQ2doZEhKaFkydFZibWhoYm1Sc1pXUlNaV3BsWTNScGIyNXpLU0I3WEc0Z0lDQWdJQ0FnSUhKbGRIVnlianRjYmlBZ0lDQjlYRzRnSUNBZ2FXWWdLSFI1Y0dWdlppQndjbTlqWlhOeklEMDlQU0JjSW05aWFtVmpkRndpSUNZbUlIUjVjR1Z2WmlCd2NtOWpaWE56TG1WdGFYUWdQVDA5SUZ3aVpuVnVZM1JwYjI1Y0lpa2dlMXh1SUNBZ0lDQWdJQ0JSTG01bGVIUlVhV05yTG5KMWJrRm1kR1Z5S0daMWJtTjBhVzl1SUNncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaGhjbkpoZVY5cGJtUmxlRTltS0hWdWFHRnVaR3hsWkZKbGFtVmpkR2x2Ym5Nc0lIQnliMjFwYzJVcElDRTlQU0F0TVNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIQnliMk5sYzNNdVpXMXBkQ2hjSW5WdWFHRnVaR3hsWkZKbGFtVmpkR2x2Ymx3aUxDQnlaV0Z6YjI0c0lIQnliMjFwYzJVcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lISmxjRzl5ZEdWa1ZXNW9ZVzVrYkdWa1VtVnFaV04wYVc5dWN5NXdkWE5vS0hCeWIyMXBjMlVwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5S1R0Y2JpQWdJQ0I5WEc1Y2JpQWdJQ0IxYm1oaGJtUnNaV1JTWldwbFkzUnBiMjV6TG5CMWMyZ29jSEp2YldselpTazdYRzRnSUNBZ2FXWWdLSEpsWVhOdmJpQW1KaUIwZVhCbGIyWWdjbVZoYzI5dUxuTjBZV05ySUNFOVBTQmNJblZ1WkdWbWFXNWxaRndpS1NCN1hHNGdJQ0FnSUNBZ0lIVnVhR0Z1Wkd4bFpGSmxZWE52Ym5NdWNIVnphQ2h5WldGemIyNHVjM1JoWTJzcE8xeHVJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUhWdWFHRnVaR3hsWkZKbFlYTnZibk11Y0hWemFDaGNJaWh1YnlCemRHRmpheWtnWENJZ0t5QnlaV0Z6YjI0cE8xeHVJQ0FnSUgxY2JuMWNibHh1Wm5WdVkzUnBiMjRnZFc1MGNtRmphMUpsYW1WamRHbHZiaWh3Y205dGFYTmxLU0I3WEc0Z0lDQWdhV1lnS0NGMGNtRmphMVZ1YUdGdVpHeGxaRkpsYW1WamRHbHZibk1wSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1TzF4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCaGRDQTlJR0Z5Y21GNVgybHVaR1Y0VDJZb2RXNW9ZVzVrYkdWa1VtVnFaV04wYVc5dWN5d2djSEp2YldselpTazdYRzRnSUNBZ2FXWWdLR0YwSUNFOVBTQXRNU2tnZTF4dUlDQWdJQ0FnSUNCcFppQW9kSGx3Wlc5bUlIQnliMk5sYzNNZ1BUMDlJRndpYjJKcVpXTjBYQ0lnSmlZZ2RIbHdaVzltSUhCeWIyTmxjM011WlcxcGRDQTlQVDBnWENKbWRXNWpkR2x2Ymx3aUtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCUkxtNWxlSFJVYVdOckxuSjFia0ZtZEdWeUtHWjFibU4wYVc5dUlDZ3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0IyWVhJZ1lYUlNaWEJ2Y25RZ1BTQmhjbkpoZVY5cGJtUmxlRTltS0hKbGNHOXlkR1ZrVlc1b1lXNWtiR1ZrVW1WcVpXTjBhVzl1Y3l3Z2NISnZiV2x6WlNrN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLR0YwVW1Wd2IzSjBJQ0U5UFNBdE1Ta2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCd2NtOWpaWE56TG1WdGFYUW9YQ0p5WldwbFkzUnBiMjVJWVc1a2JHVmtYQ0lzSUhWdWFHRnVaR3hsWkZKbFlYTnZibk5iWVhSZExDQndjbTl0YVhObEtUdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnY21Wd2IzSjBaV1JWYm1oaGJtUnNaV1JTWldwbFkzUnBiMjV6TG5Od2JHbGpaU2hoZEZKbGNHOXlkQ3dnTVNrN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnZlNrN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdkVzVvWVc1a2JHVmtVbVZxWldOMGFXOXVjeTV6Y0d4cFkyVW9ZWFFzSURFcE8xeHVJQ0FnSUNBZ0lDQjFibWhoYm1Sc1pXUlNaV0Z6YjI1ekxuTndiR2xqWlNoaGRDd2dNU2s3WEc0Z0lDQWdmVnh1ZlZ4dVhHNVJMbkpsYzJWMFZXNW9ZVzVrYkdWa1VtVnFaV04wYVc5dWN5QTlJSEpsYzJWMFZXNW9ZVzVrYkdWa1VtVnFaV04wYVc5dWN6dGNibHh1VVM1blpYUlZibWhoYm1Sc1pXUlNaV0Z6YjI1eklEMGdablZ1WTNScGIyNGdLQ2tnZTF4dUlDQWdJQzh2SUUxaGEyVWdZU0JqYjNCNUlITnZJSFJvWVhRZ1kyOXVjM1Z0WlhKeklHTmhiaWQwSUdsdWRHVnlabVZ5WlNCM2FYUm9JRzkxY2lCcGJuUmxjbTVoYkNCemRHRjBaUzVjYmlBZ0lDQnlaWFIxY200Z2RXNW9ZVzVrYkdWa1VtVmhjMjl1Y3k1emJHbGpaU2dwTzF4dWZUdGNibHh1VVM1emRHOXdWVzVvWVc1a2JHVmtVbVZxWldOMGFXOXVWSEpoWTJ0cGJtY2dQU0JtZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnY21WelpYUlZibWhoYm1Sc1pXUlNaV3BsWTNScGIyNXpLQ2s3WEc0Z0lDQWdkSEpoWTJ0VmJtaGhibVJzWldSU1pXcGxZM1JwYjI1eklEMGdabUZzYzJVN1hHNTlPMXh1WEc1eVpYTmxkRlZ1YUdGdVpHeGxaRkpsYW1WamRHbHZibk1vS1R0Y2JseHVMeTh2THlCRlRrUWdWVTVJUVU1RVRFVkVJRkpGU2tWRFZFbFBUaUJVVWtGRFMwbE9SMXh1WEc0dktpcGNiaUFxSUVOdmJuTjBjblZqZEhNZ1lTQnlaV3BsWTNSbFpDQndjbTl0YVhObExseHVJQ29nUUhCaGNtRnRJSEpsWVhOdmJpQjJZV3gxWlNCa1pYTmpjbWxpYVc1bklIUm9aU0JtWVdsc2RYSmxYRzRnS2k5Y2JsRXVjbVZxWldOMElEMGdjbVZxWldOME8xeHVablZ1WTNScGIyNGdjbVZxWldOMEtISmxZWE52YmlrZ2UxeHVJQ0FnSUhaaGNpQnlaV3BsWTNScGIyNGdQU0JRY205dGFYTmxLSHRjYmlBZ0lDQWdJQ0FnWENKM2FHVnVYQ0k2SUdaMWJtTjBhVzl1SUNoeVpXcGxZM1JsWkNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnTHk4Z2JtOTBaU0IwYUdGMElIUm9aU0JsY25KdmNpQm9ZWE1nWW1WbGJpQm9ZVzVrYkdWa1hHNGdJQ0FnSUNBZ0lDQWdJQ0JwWmlBb2NtVnFaV04wWldRcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjFiblJ5WVdOclVtVnFaV04wYVc5dUtIUm9hWE1wTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKbGFtVmpkR1ZrSUQ4Z2NtVnFaV04wWldRb2NtVmhjMjl1S1NBNklIUm9hWE03WEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0I5TENCbWRXNWpkR2x2YmlCbVlXeHNZbUZqYXlncElIdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlIUm9hWE03WEc0Z0lDQWdmU3dnWm5WdVkzUnBiMjRnYVc1emNHVmpkQ2dwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhzZ2MzUmhkR1U2SUZ3aWNtVnFaV04wWldSY0lpd2djbVZoYzI5dU9pQnlaV0Z6YjI0Z2ZUdGNiaUFnSUNCOUtUdGNibHh1SUNBZ0lDOHZJRTV2ZEdVZ2RHaGhkQ0IwYUdVZ2NtVmhjMjl1SUdoaGN5QnViM1FnWW1WbGJpQm9ZVzVrYkdWa0xseHVJQ0FnSUhSeVlXTnJVbVZxWldOMGFXOXVLSEpsYW1WamRHbHZiaXdnY21WaGMyOXVLVHRjYmx4dUlDQWdJSEpsZEhWeWJpQnlaV3BsWTNScGIyNDdYRzU5WEc1Y2JpOHFLbHh1SUNvZ1EyOXVjM1J5ZFdOMGN5QmhJR1oxYkdacGJHeGxaQ0J3Y205dGFYTmxJR1p2Y2lCaGJpQnBiVzFsWkdsaGRHVWdjbVZtWlhKbGJtTmxMbHh1SUNvZ1FIQmhjbUZ0SUhaaGJIVmxJR2x0YldWa2FXRjBaU0J5WldabGNtVnVZMlZjYmlBcUwxeHVVUzVtZFd4bWFXeHNJRDBnWm5Wc1ptbHNiRHRjYm1aMWJtTjBhVzl1SUdaMWJHWnBiR3dvZG1Gc2RXVXBJSHRjYmlBZ0lDQnlaWFIxY200Z1VISnZiV2x6WlNoN1hHNGdJQ0FnSUNBZ0lGd2lkMmhsYmx3aU9pQm1kVzVqZEdsdmJpQW9LU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQnlaWFIxY200Z2RtRnNkV1U3WEc0Z0lDQWdJQ0FnSUgwc1hHNGdJQ0FnSUNBZ0lGd2laMlYwWENJNklHWjFibU4wYVc5dUlDaHVZVzFsS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdkbUZzZFdWYmJtRnRaVjA3WEc0Z0lDQWdJQ0FnSUgwc1hHNGdJQ0FnSUNBZ0lGd2ljMlYwWENJNklHWjFibU4wYVc5dUlDaHVZVzFsTENCeWFITXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIWmhiSFZsVzI1aGJXVmRJRDBnY21oek8xeHVJQ0FnSUNBZ0lDQjlMRnh1SUNBZ0lDQWdJQ0JjSW1SbGJHVjBaVndpT2lCbWRXNWpkR2x2YmlBb2JtRnRaU2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdaR1ZzWlhSbElIWmhiSFZsVzI1aGJXVmRPMXh1SUNBZ0lDQWdJQ0I5TEZ4dUlDQWdJQ0FnSUNCY0luQnZjM1JjSWpvZ1puVnVZM1JwYjI0Z0tHNWhiV1VzSUdGeVozTXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDOHZJRTFoY21zZ1RXbHNiR1Z5SUhCeWIzQnZjMlZ6SUhSb1lYUWdjRzl6ZENCM2FYUm9JRzV2SUc1aGJXVWdjMmh2ZFd4a0lHRndjR3g1SUdGY2JpQWdJQ0FnSUNBZ0lDQWdJQzh2SUhCeWIyMXBjMlZrSUdaMWJtTjBhVzl1TGx4dUlDQWdJQ0FnSUNBZ0lDQWdhV1lnS0c1aGJXVWdQVDA5SUc1MWJHd2dmSHdnYm1GdFpTQTlQVDBnZG05cFpDQXdLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSFpoYkhWbExtRndjR3g1S0hadmFXUWdNQ3dnWVhKbmN5azdYRzRnSUNBZ0lDQWdJQ0FnSUNCOUlHVnNjMlVnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUIyWVd4MVpWdHVZVzFsWFM1aGNIQnNlU2gyWVd4MVpTd2dZWEpuY3lrN1hHNGdJQ0FnSUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUgwc1hHNGdJQ0FnSUNBZ0lGd2lZWEJ3YkhsY0lqb2dablZ1WTNScGIyNGdLSFJvYVhOd0xDQmhjbWR6S1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdkbUZzZFdVdVlYQndiSGtvZEdocGMzQXNJR0Z5WjNNcE8xeHVJQ0FnSUNBZ0lDQjlMRnh1SUNBZ0lDQWdJQ0JjSW10bGVYTmNJam9nWm5WdVkzUnBiMjRnS0NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJRzlpYW1WamRGOXJaWGx6S0haaGJIVmxLVHRjYmlBZ0lDQWdJQ0FnZlZ4dUlDQWdJSDBzSUhadmFXUWdNQ3dnWm5WdVkzUnBiMjRnYVc1emNHVmpkQ2dwSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUhzZ2MzUmhkR1U2SUZ3aVpuVnNabWxzYkdWa1hDSXNJSFpoYkhWbE9pQjJZV3gxWlNCOU8xeHVJQ0FnSUgwcE8xeHVmVnh1WEc0dktpcGNiaUFxSUVOdmJuWmxjblJ6SUhSb1pXNWhZbXhsY3lCMGJ5QlJJSEJ5YjIxcGMyVnpMbHh1SUNvZ1FIQmhjbUZ0SUhCeWIyMXBjMlVnZEdobGJtRmliR1VnY0hKdmJXbHpaVnh1SUNvZ1FISmxkSFZ5Ym5NZ1lTQlJJSEJ5YjIxcGMyVmNiaUFxTDF4dVpuVnVZM1JwYjI0Z1kyOWxjbU5sS0hCeWIyMXBjMlVwSUh0Y2JpQWdJQ0IyWVhJZ1pHVm1aWEp5WldRZ1BTQmtaV1psY2lncE8xeHVJQ0FnSUZFdWJtVjRkRlJwWTJzb1puVnVZM1JwYjI0Z0tDa2dlMXh1SUNBZ0lDQWdJQ0IwY25rZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY0hKdmJXbHpaUzUwYUdWdUtHUmxabVZ5Y21Wa0xuSmxjMjlzZG1Vc0lHUmxabVZ5Y21Wa0xuSmxhbVZqZEN3Z1pHVm1aWEp5WldRdWJtOTBhV1o1S1R0Y2JpQWdJQ0FnSUNBZ2ZTQmpZWFJqYUNBb1pYaGpaWEIwYVc5dUtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCa1pXWmxjbkpsWkM1eVpXcGxZM1FvWlhoalpYQjBhVzl1S1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUgwcE8xeHVJQ0FnSUhKbGRIVnliaUJrWldabGNuSmxaQzV3Y205dGFYTmxPMXh1ZlZ4dVhHNHZLaXBjYmlBcUlFRnVibTkwWVhSbGN5QmhiaUJ2WW1wbFkzUWdjM1ZqYUNCMGFHRjBJR2wwSUhkcGJHd2dibVYyWlhJZ1ltVmNiaUFxSUhSeVlXNXpabVZ5Y21Wa0lHRjNZWGtnWm5KdmJTQjBhR2x6SUhCeWIyTmxjM01nYjNabGNpQmhibmtnY0hKdmJXbHpaVnh1SUNvZ1kyOXRiWFZ1YVdOaGRHbHZiaUJqYUdGdWJtVnNMbHh1SUNvZ1FIQmhjbUZ0SUc5aWFtVmpkRnh1SUNvZ1FISmxkSFZ5Ym5NZ2NISnZiV2x6WlNCaElIZHlZWEJ3YVc1bklHOW1JSFJvWVhRZ2IySnFaV04wSUhSb1lYUmNiaUFxSUdGa1pHbDBhVzl1WVd4c2VTQnlaWE53YjI1a2N5QjBieUIwYUdVZ1hDSnBjMFJsWmx3aUlHMWxjM05oWjJWY2JpQXFJSGRwZEdodmRYUWdZU0J5WldwbFkzUnBiMjR1WEc0Z0tpOWNibEV1YldGemRHVnlJRDBnYldGemRHVnlPMXh1Wm5WdVkzUnBiMjRnYldGemRHVnlLRzlpYW1WamRDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCUWNtOXRhWE5sS0h0Y2JpQWdJQ0FnSUNBZ1hDSnBjMFJsWmx3aU9pQm1kVzVqZEdsdmJpQW9LU0I3ZlZ4dUlDQWdJSDBzSUdaMWJtTjBhVzl1SUdaaGJHeGlZV05yS0c5d0xDQmhjbWR6S1NCN1hHNGdJQ0FnSUNBZ0lISmxkSFZ5YmlCa2FYTndZWFJqYUNodlltcGxZM1FzSUc5d0xDQmhjbWR6S1R0Y2JpQWdJQ0I5TENCbWRXNWpkR2x2YmlBb0tTQjdYRzRnSUNBZ0lDQWdJSEpsZEhWeWJpQlJLRzlpYW1WamRDa3VhVzV6Y0dWamRDZ3BPMXh1SUNBZ0lIMHBPMXh1ZlZ4dVhHNHZLaXBjYmlBcUlGTndjbVZoWkhNZ2RHaGxJSFpoYkhWbGN5QnZaaUJoSUhCeWIyMXBjMlZrSUdGeWNtRjVJRzltSUdGeVozVnRaVzUwY3lCcGJuUnZJSFJvWlZ4dUlDb2dablZzWm1sc2JHMWxiblFnWTJGc2JHSmhZMnN1WEc0Z0tpQkFjR0Z5WVcwZ1puVnNabWxzYkdWa0lHTmhiR3hpWVdOcklIUm9ZWFFnY21WalpXbDJaWE1nZG1GeWFXRmthV01nWVhKbmRXMWxiblJ6SUdaeWIyMGdkR2hsWEc0Z0tpQndjbTl0YVhObFpDQmhjbkpoZVZ4dUlDb2dRSEJoY21GdElISmxhbVZqZEdWa0lHTmhiR3hpWVdOcklIUm9ZWFFnY21WalpXbDJaWE1nZEdobElHVjRZMlZ3ZEdsdmJpQnBaaUIwYUdVZ2NISnZiV2x6WlZ4dUlDb2dhWE1nY21WcVpXTjBaV1F1WEc0Z0tpQkFjbVYwZFhKdWN5QmhJSEJ5YjIxcGMyVWdabTl5SUhSb1pTQnlaWFIxY200Z2RtRnNkV1VnYjNJZ2RHaHliM2R1SUdWNFkyVndkR2x2YmlCdlpseHVJQ29nWldsMGFHVnlJR05oYkd4aVlXTnJMbHh1SUNvdlhHNVJMbk53Y21WaFpDQTlJSE53Y21WaFpEdGNibVoxYm1OMGFXOXVJSE53Y21WaFpDaDJZV3gxWlN3Z1puVnNabWxzYkdWa0xDQnlaV3BsWTNSbFpDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCUktIWmhiSFZsS1M1emNISmxZV1FvWm5Wc1ptbHNiR1ZrTENCeVpXcGxZM1JsWkNrN1hHNTlYRzVjYmxCeWIyMXBjMlV1Y0hKdmRHOTBlWEJsTG5Od2NtVmhaQ0E5SUdaMWJtTjBhVzl1SUNobWRXeG1hV3hzWldRc0lISmxhbVZqZEdWa0tTQjdYRzRnSUNBZ2NtVjBkWEp1SUhSb2FYTXVZV3hzS0NrdWRHaGxiaWhtZFc1amRHbHZiaUFvWVhKeVlYa3BJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJR1oxYkdacGJHeGxaQzVoY0hCc2VTaDJiMmxrSURBc0lHRnljbUY1S1R0Y2JpQWdJQ0I5TENCeVpXcGxZM1JsWkNrN1hHNTlPMXh1WEc0dktpcGNiaUFxSUZSb1pTQmhjM2x1WXlCbWRXNWpkR2x2YmlCcGN5QmhJR1JsWTI5eVlYUnZjaUJtYjNJZ1oyVnVaWEpoZEc5eUlHWjFibU4wYVc5dWN5d2dkSFZ5Ym1sdVoxeHVJQ29nZEdobGJTQnBiblJ2SUdGemVXNWphSEp2Ym05MWN5Qm5aVzVsY21GMGIzSnpMaUFnUVd4MGFHOTFaMmdnWjJWdVpYSmhkRzl5Y3lCaGNtVWdiMjVzZVNCd1lYSjBYRzRnS2lCdlppQjBhR1VnYm1WM1pYTjBJRVZEVFVGVFkzSnBjSFFnTmlCa2NtRm1kSE1zSUhSb2FYTWdZMjlrWlNCa2IyVnpJRzV2ZENCallYVnpaU0J6ZVc1MFlYaGNiaUFxSUdWeWNtOXljeUJwYmlCdmJHUmxjaUJsYm1kcGJtVnpMaUFnVkdocGN5QmpiMlJsSUhOb2IzVnNaQ0JqYjI1MGFXNTFaU0IwYnlCM2IzSnJJR0Z1WkNCM2FXeHNYRzRnS2lCcGJpQm1ZV04wSUdsdGNISnZkbVVnYjNabGNpQjBhVzFsSUdGeklIUm9aU0JzWVc1bmRXRm5aU0JwYlhCeWIzWmxjeTVjYmlBcVhHNGdLaUJGVXpZZ1oyVnVaWEpoZEc5eWN5QmhjbVVnWTNWeWNtVnVkR3g1SUhCaGNuUWdiMllnVmpnZ2RtVnljMmx2YmlBekxqRTVJSGRwZEdnZ2RHaGxYRzRnS2lBdExXaGhjbTF2Ym5rdFoyVnVaWEpoZEc5eWN5QnlkVzUwYVcxbElHWnNZV2NnWlc1aFlteGxaQzRnSUZOd2FXUmxjazF2Ym10bGVTQm9ZWE1nYUdGa0lIUm9aVzFjYmlBcUlHWnZjaUJzYjI1blpYSXNJR0oxZENCMWJtUmxjaUJoYmlCdmJHUmxjaUJRZVhSb2IyNHRhVzV6Y0dseVpXUWdabTl5YlM0Z0lGUm9hWE1nWm5WdVkzUnBiMjVjYmlBcUlIZHZjbXR6SUc5dUlHSnZkR2dnYTJsdVpITWdiMllnWjJWdVpYSmhkRzl5Y3k1Y2JpQXFYRzRnS2lCRVpXTnZjbUYwWlhNZ1lTQm5aVzVsY21GMGIzSWdablZ1WTNScGIyNGdjM1ZqYUNCMGFHRjBPbHh1SUNvZ0lDMGdhWFFnYldGNUlIbHBaV3hrSUhCeWIyMXBjMlZ6WEc0Z0tpQWdMU0JsZUdWamRYUnBiMjRnZDJsc2JDQmpiMjUwYVc1MVpTQjNhR1Z1SUhSb1lYUWdjSEp2YldselpTQnBjeUJtZFd4bWFXeHNaV1JjYmlBcUlDQXRJSFJvWlNCMllXeDFaU0J2WmlCMGFHVWdlV2xsYkdRZ1pYaHdjbVZ6YzJsdmJpQjNhV3hzSUdKbElIUm9aU0JtZFd4bWFXeHNaV1FnZG1Gc2RXVmNiaUFxSUNBdElHbDBJSEpsZEhWeWJuTWdZU0J3Y205dGFYTmxJR1p2Y2lCMGFHVWdjbVYwZFhKdUlIWmhiSFZsSUNoM2FHVnVJSFJvWlNCblpXNWxjbUYwYjNKY2JpQXFJQ0FnSUhOMGIzQnpJR2wwWlhKaGRHbHVaeWxjYmlBcUlDQXRJSFJvWlNCa1pXTnZjbUYwWldRZ1puVnVZM1JwYjI0Z2NtVjBkWEp1Y3lCaElIQnliMjFwYzJVZ1ptOXlJSFJvWlNCeVpYUjFjbTRnZG1Gc2RXVmNiaUFxSUNBZ0lHOW1JSFJvWlNCblpXNWxjbUYwYjNJZ2IzSWdkR2hsSUdacGNuTjBJSEpsYW1WamRHVmtJSEJ5YjIxcGMyVWdZVzF2Ym1jZ2RHaHZjMlZjYmlBcUlDQWdJSGxwWld4a1pXUXVYRzRnS2lBZ0xTQnBaaUJoYmlCbGNuSnZjaUJwY3lCMGFISnZkMjRnYVc0Z2RHaGxJR2RsYm1WeVlYUnZjaXdnYVhRZ2NISnZjR0ZuWVhSbGN5QjBhSEp2ZFdkb1hHNGdLaUFnSUNCbGRtVnllU0JtYjJ4c2IzZHBibWNnZVdsbGJHUWdkVzUwYVd3Z2FYUWdhWE1nWTJGMVoyaDBMQ0J2Y2lCMWJuUnBiQ0JwZENCbGMyTmhjR1Z6WEc0Z0tpQWdJQ0IwYUdVZ1oyVnVaWEpoZEc5eUlHWjFibU4wYVc5dUlHRnNkRzluWlhSb1pYSXNJR0Z1WkNCcGN5QjBjbUZ1YzJ4aGRHVmtJR2x1ZEc4Z1lWeHVJQ29nSUNBZ2NtVnFaV04wYVc5dUlHWnZjaUIwYUdVZ2NISnZiV2x6WlNCeVpYUjFjbTVsWkNCaWVTQjBhR1VnWkdWamIzSmhkR1ZrSUdkbGJtVnlZWFJ2Y2k1Y2JpQXFMMXh1VVM1aGMzbHVZeUE5SUdGemVXNWpPMXh1Wm5WdVkzUnBiMjRnWVhONWJtTW9iV0ZyWlVkbGJtVnlZWFJ2Y2lrZ2UxeHVJQ0FnSUhKbGRIVnliaUJtZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnSUNBZ0lDOHZJSGRvWlc0Z2RtVnlZaUJwY3lCY0luTmxibVJjSWl3Z1lYSm5JR2x6SUdFZ2RtRnNkV1ZjYmlBZ0lDQWdJQ0FnTHk4Z2QyaGxiaUIyWlhKaUlHbHpJRndpZEdoeWIzZGNJaXdnWVhKbklHbHpJR0Z1SUdWNFkyVndkR2x2Ymx4dUlDQWdJQ0FnSUNCbWRXNWpkR2x2YmlCamIyNTBhVzUxWlhJb2RtVnlZaXdnWVhKbktTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCMllYSWdjbVZ6ZFd4ME8xeHVYRzRnSUNBZ0lDQWdJQ0FnSUNBdkx5QlZiblJwYkNCV09DQXpMakU1SUM4Z1EyaHliMjFwZFcwZ01qa2dhWE1nY21Wc1pXRnpaV1FzSUZOd2FXUmxjazF2Ym10bGVTQnBjeUIwYUdVZ2IyNXNlVnh1SUNBZ0lDQWdJQ0FnSUNBZ0x5OGdaVzVuYVc1bElIUm9ZWFFnYUdGeklHRWdaR1Z3Ykc5NVpXUWdZbUZ6WlNCdlppQmljbTkzYzJWeWN5QjBhR0YwSUhOMWNIQnZjblFnWjJWdVpYSmhkRzl5Y3k1Y2JpQWdJQ0FnSUNBZ0lDQWdJQzh2SUVodmQyVjJaWElzSUZOTkozTWdaMlZ1WlhKaGRHOXljeUIxYzJVZ2RHaGxJRkI1ZEdodmJpMXBibk53YVhKbFpDQnpaVzFoYm5ScFkzTWdiMlpjYmlBZ0lDQWdJQ0FnSUNBZ0lDOHZJRzkxZEdSaGRHVmtJRVZUTmlCa2NtRm1kSE11SUNCWFpTQjNiM1ZzWkNCc2FXdGxJSFJ2SUhOMWNIQnZjblFnUlZNMkxDQmlkWFFnZDJVblpDQmhiSE52WEc0Z0lDQWdJQ0FnSUNBZ0lDQXZMeUJzYVd0bElIUnZJRzFoYTJVZ2FYUWdjRzl6YzJsaWJHVWdkRzhnZFhObElHZGxibVZ5WVhSdmNuTWdhVzRnWkdWd2JHOTVaV1FnWW5KdmQzTmxjbk1zSUhOdlhHNGdJQ0FnSUNBZ0lDQWdJQ0F2THlCM1pTQmhiSE52SUhOMWNIQnZjblFnVUhsMGFHOXVMWE4wZVd4bElHZGxibVZ5WVhSdmNuTXVJQ0JCZENCemIyMWxJSEJ2YVc1MElIZGxJR05oYmlCeVpXMXZkbVZjYmlBZ0lDQWdJQ0FnSUNBZ0lDOHZJSFJvYVhNZ1lteHZZMnN1WEc1Y2JpQWdJQ0FnSUNBZ0lDQWdJR2xtSUNoMGVYQmxiMllnVTNSdmNFbDBaWEpoZEdsdmJpQTlQVDBnWENKMWJtUmxabWx1WldSY0lpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQzh2SUVWVE5pQkhaVzVsY21GMGIzSnpYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkSEo1SUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdjbVZ6ZFd4MElEMGdaMlZ1WlhKaGRHOXlXM1psY21KZEtHRnlaeWs3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZlNCallYUmphQ0FvWlhoalpYQjBhVzl1S1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQnlaV3BsWTNRb1pYaGpaWEIwYVc5dUtUdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhV1lnS0hKbGMzVnNkQzVrYjI1bEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUhKbGRIVnliaUJSS0hKbGMzVnNkQzUyWVd4MVpTazdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSGRvWlc0b2NtVnpkV3gwTG5aaGJIVmxMQ0JqWVd4c1ltRmpheXdnWlhKeVltRmpheWs3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNBZ0lDQWdmU0JsYkhObElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXZMeUJUY0dsa1pYSk5iMjVyWlhrZ1IyVnVaWEpoZEc5eWMxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDOHZJRVpKV0UxRk9pQlNaVzF2ZG1VZ2RHaHBjeUJqWVhObElIZG9aVzRnVTAwZ1pHOWxjeUJGVXpZZ1oyVnVaWEpoZEc5eWN5NWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjBjbmtnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQnlaWE4xYkhRZ1BTQm5aVzVsY21GMGIzSmJkbVZ5WWwwb1lYSm5LVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0I5SUdOaGRHTm9JQ2hsZUdObGNIUnBiMjRwSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhV1lnS0dselUzUnZjRWwwWlhKaGRHbHZiaWhsZUdObGNIUnBiMjRwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCeVpYUjFjbTRnVVNobGVHTmxjSFJwYjI0dWRtRnNkV1VwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhKbGFtVmpkQ2hsZUdObGNIUnBiMjRwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSEpsZEhWeWJpQjNhR1Z1S0hKbGMzVnNkQ3dnWTJGc2JHSmhZMnNzSUdWeWNtSmhZMnNwTzF4dUlDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0I5WEc0Z0lDQWdJQ0FnSUhaaGNpQm5aVzVsY21GMGIzSWdQU0J0WVd0bFIyVnVaWEpoZEc5eUxtRndjR3g1S0hSb2FYTXNJR0Z5WjNWdFpXNTBjeWs3WEc0Z0lDQWdJQ0FnSUhaaGNpQmpZV3hzWW1GamF5QTlJR052Ym5ScGJuVmxjaTVpYVc1a0tHTnZiblJwYm5WbGNpd2dYQ0p1WlhoMFhDSXBPMXh1SUNBZ0lDQWdJQ0IyWVhJZ1pYSnlZbUZqYXlBOUlHTnZiblJwYm5WbGNpNWlhVzVrS0dOdmJuUnBiblZsY2l3Z1hDSjBhSEp2ZDF3aUtUdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlHTmhiR3hpWVdOcktDazdYRzRnSUNBZ2ZUdGNibjFjYmx4dUx5b3FYRzRnS2lCVWFHVWdjM0JoZDI0Z1puVnVZM1JwYjI0Z2FYTWdZU0J6YldGc2JDQjNjbUZ3Y0dWeUlHRnliM1Z1WkNCaGMzbHVZeUIwYUdGMElHbHRiV1ZrYVdGMFpXeDVYRzRnS2lCallXeHNjeUIwYUdVZ1oyVnVaWEpoZEc5eUlHRnVaQ0JoYkhOdklHVnVaSE1nZEdobElIQnliMjFwYzJVZ1kyaGhhVzRzSUhOdklIUm9ZWFFnWVc1NVhHNGdLaUIxYm1oaGJtUnNaV1FnWlhKeWIzSnpJR0Z5WlNCMGFISnZkMjRnYVc1emRHVmhaQ0J2WmlCbWIzSjNZWEprWldRZ2RHOGdkR2hsSUdWeWNtOXlYRzRnS2lCb1lXNWtiR1Z5TGlCVWFHbHpJR2x6SUhWelpXWjFiQ0JpWldOaGRYTmxJR2wwSjNNZ1pYaDBjbVZ0Wld4NUlHTnZiVzF2YmlCMGJ5QnlkVzVjYmlBcUlHZGxibVZ5WVhSdmNuTWdZWFFnZEdobElIUnZjQzFzWlhabGJDQjBieUIzYjNKcklIZHBkR2dnYkdsaWNtRnlhV1Z6TGx4dUlDb3ZYRzVSTG5Od1lYZHVJRDBnYzNCaGQyNDdYRzVtZFc1amRHbHZiaUJ6Y0dGM2JpaHRZV3RsUjJWdVpYSmhkRzl5S1NCN1hHNGdJQ0FnVVM1a2IyNWxLRkV1WVhONWJtTW9iV0ZyWlVkbGJtVnlZWFJ2Y2lrb0tTazdYRzU5WEc1Y2JpOHZJRVpKV0UxRk9pQlNaVzF2ZG1VZ2RHaHBjeUJwYm5SbGNtWmhZMlVnYjI1alpTQkZVellnWjJWdVpYSmhkRzl5Y3lCaGNtVWdhVzRnVTNCcFpHVnlUVzl1YTJWNUxseHVMeW9xWEc0Z0tpQlVhSEp2ZDNNZ1lTQlNaWFIxY201V1lXeDFaU0JsZUdObGNIUnBiMjRnZEc4Z2MzUnZjQ0JoYmlCaGMzbHVZMmh5YjI1dmRYTWdaMlZ1WlhKaGRHOXlMbHh1SUNwY2JpQXFJRlJvYVhNZ2FXNTBaWEptWVdObElHbHpJR0VnYzNSdmNDMW5ZWEFnYldWaGMzVnlaU0IwYnlCemRYQndiM0owSUdkbGJtVnlZWFJ2Y2lCeVpYUjFjbTVjYmlBcUlIWmhiSFZsY3lCcGJpQnZiR1JsY2lCR2FYSmxabTk0TDFOd2FXUmxjazF2Ym10bGVTNGdJRWx1SUdKeWIzZHpaWEp6SUhSb1lYUWdjM1Z3Y0c5eWRDQkZVelpjYmlBcUlHZGxibVZ5WVhSdmNuTWdiR2xyWlNCRGFISnZiV2wxYlNBeU9Td2dhblZ6ZENCMWMyVWdYQ0p5WlhSMWNtNWNJaUJwYmlCNWIzVnlJR2RsYm1WeVlYUnZjbHh1SUNvZ1puVnVZM1JwYjI1ekxseHVJQ3BjYmlBcUlFQndZWEpoYlNCMllXeDFaU0IwYUdVZ2NtVjBkWEp1SUhaaGJIVmxJR1p2Y2lCMGFHVWdjM1Z5Y205MWJtUnBibWNnWjJWdVpYSmhkRzl5WEc0Z0tpQkFkR2h5YjNkeklGSmxkSFZ5YmxaaGJIVmxJR1Y0WTJWd2RHbHZiaUIzYVhSb0lIUm9aU0IyWVd4MVpTNWNiaUFxSUVCbGVHRnRjR3hsWEc0Z0tpQXZMeUJGVXpZZ2MzUjViR1ZjYmlBcUlGRXVZWE41Ym1Nb1puVnVZM1JwYjI0cUlDZ3BJSHRjYmlBcUlDQWdJQ0FnZG1GeUlHWnZieUE5SUhscFpXeGtJR2RsZEVadmIxQnliMjFwYzJVb0tUdGNiaUFxSUNBZ0lDQWdkbUZ5SUdKaGNpQTlJSGxwWld4a0lHZGxkRUpoY2xCeWIyMXBjMlVvS1R0Y2JpQXFJQ0FnSUNBZ2NtVjBkWEp1SUdadmJ5QXJJR0poY2p0Y2JpQXFJSDBwWEc0Z0tpQXZMeUJQYkdSbGNpQlRjR2xrWlhKTmIyNXJaWGtnYzNSNWJHVmNiaUFxSUZFdVlYTjVibU1vWm5WdVkzUnBiMjRnS0NrZ2UxeHVJQ29nSUNBZ0lDQjJZWElnWm05dklEMGdlV2xsYkdRZ1oyVjBSbTl2VUhKdmJXbHpaU2dwTzF4dUlDb2dJQ0FnSUNCMllYSWdZbUZ5SUQwZ2VXbGxiR1FnWjJWMFFtRnlVSEp2YldselpTZ3BPMXh1SUNvZ0lDQWdJQ0JSTG5KbGRIVnliaWhtYjI4Z0t5QmlZWElwTzF4dUlDb2dmU2xjYmlBcUwxeHVVVnRjSW5KbGRIVnlibHdpWFNBOUlGOXlaWFIxY200N1hHNW1kVzVqZEdsdmJpQmZjbVYwZFhKdUtIWmhiSFZsS1NCN1hHNGdJQ0FnZEdoeWIzY2dibVYzSUZGU1pYUjFjbTVXWVd4MVpTaDJZV3gxWlNrN1hHNTlYRzVjYmk4cUtseHVJQ29nVkdobElIQnliMjFwYzJWa0lHWjFibU4wYVc5dUlHUmxZMjl5WVhSdmNpQmxibk4xY21WeklIUm9ZWFFnWVc1NUlIQnliMjFwYzJVZ1lYSm5kVzFsYm5SelhHNGdLaUJoY21VZ2MyVjBkR3hsWkNCaGJtUWdjR0Z6YzJWa0lHRnpJSFpoYkhWbGN5QW9ZSFJvYVhOZ0lHbHpJR0ZzYzI4Z2MyVjBkR3hsWkNCaGJtUWdjR0Z6YzJWa1hHNGdLaUJoY3lCaElIWmhiSFZsS1M0Z0lFbDBJSGRwYkd3Z1lXeHpieUJsYm5OMWNtVWdkR2hoZENCMGFHVWdjbVZ6ZFd4MElHOW1JR0VnWm5WdVkzUnBiMjRnYVhOY2JpQXFJR0ZzZDJGNWN5QmhJSEJ5YjIxcGMyVXVYRzRnS2x4dUlDb2dRR1Y0WVcxd2JHVmNiaUFxSUhaaGNpQmhaR1FnUFNCUkxuQnliMjFwYzJWa0tHWjFibU4wYVc5dUlDaGhMQ0JpS1NCN1hHNGdLaUFnSUNBZ2NtVjBkWEp1SUdFZ0t5QmlPMXh1SUNvZ2ZTazdYRzRnS2lCaFpHUW9VU2hoS1N3Z1VTaENLU2s3WEc0Z0tseHVJQ29nUUhCaGNtRnRJSHRtZFc1amRHbHZibjBnWTJGc2JHSmhZMnNnVkdobElHWjFibU4wYVc5dUlIUnZJR1JsWTI5eVlYUmxYRzRnS2lCQWNtVjBkWEp1Y3lCN1puVnVZM1JwYjI1OUlHRWdablZ1WTNScGIyNGdkR2hoZENCb1lYTWdZbVZsYmlCa1pXTnZjbUYwWldRdVhHNGdLaTljYmxFdWNISnZiV2x6WldRZ1BTQndjbTl0YVhObFpEdGNibVoxYm1OMGFXOXVJSEJ5YjIxcGMyVmtLR05oYkd4aVlXTnJLU0I3WEc0Z0lDQWdjbVYwZFhKdUlHWjFibU4wYVc5dUlDZ3BJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJSE53Y21WaFpDaGJkR2hwY3l3Z1lXeHNLR0Z5WjNWdFpXNTBjeWxkTENCbWRXNWpkR2x2YmlBb2MyVnNaaXdnWVhKbmN5a2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUdOaGJHeGlZV05yTG1Gd2NHeDVLSE5sYkdZc0lHRnlaM01wTzF4dUlDQWdJQ0FnSUNCOUtUdGNiaUFnSUNCOU8xeHVmVnh1WEc0dktpcGNiaUFxSUhObGJtUnpJR0VnYldWemMyRm5aU0IwYnlCaElIWmhiSFZsSUdsdUlHRWdablYwZFhKbElIUjFjbTVjYmlBcUlFQndZWEpoYlNCdlltcGxZM1FxSUhSb1pTQnlaV05wY0dsbGJuUmNiaUFxSUVCd1lYSmhiU0J2Y0NCMGFHVWdibUZ0WlNCdlppQjBhR1VnYldWemMyRm5aU0J2Y0dWeVlYUnBiMjRzSUdVdVp5NHNJRndpZDJobGJsd2lMRnh1SUNvZ1FIQmhjbUZ0SUdGeVozTWdablZ5ZEdobGNpQmhjbWQxYldWdWRITWdkRzhnWW1VZ1ptOXlkMkZ5WkdWa0lIUnZJSFJvWlNCdmNHVnlZWFJwYjI1Y2JpQXFJRUJ5WlhSMWNtNXpJSEpsYzNWc2RDQjdVSEp2YldselpYMGdZU0J3Y205dGFYTmxJR1p2Y2lCMGFHVWdjbVZ6ZFd4MElHOW1JSFJvWlNCdmNHVnlZWFJwYjI1Y2JpQXFMMXh1VVM1a2FYTndZWFJqYUNBOUlHUnBjM0JoZEdOb08xeHVablZ1WTNScGIyNGdaR2x6Y0dGMFkyZ29iMkpxWldOMExDQnZjQ3dnWVhKbmN5a2dlMXh1SUNBZ0lISmxkSFZ5YmlCUktHOWlhbVZqZENrdVpHbHpjR0YwWTJnb2IzQXNJR0Z5WjNNcE8xeHVmVnh1WEc1UWNtOXRhWE5sTG5CeWIzUnZkSGx3WlM1a2FYTndZWFJqYUNBOUlHWjFibU4wYVc5dUlDaHZjQ3dnWVhKbmN5a2dlMXh1SUNBZ0lIWmhjaUJ6Wld4bUlEMGdkR2hwY3p0Y2JpQWdJQ0IyWVhJZ1pHVm1aWEp5WldRZ1BTQmtaV1psY2lncE8xeHVJQ0FnSUZFdWJtVjRkRlJwWTJzb1puVnVZM1JwYjI0Z0tDa2dlMXh1SUNBZ0lDQWdJQ0J6Wld4bUxuQnliMjFwYzJWRWFYTndZWFJqYUNoa1pXWmxjbkpsWkM1eVpYTnZiSFpsTENCdmNDd2dZWEpuY3lrN1hHNGdJQ0FnZlNrN1hHNGdJQ0FnY21WMGRYSnVJR1JsWm1WeWNtVmtMbkJ5YjIxcGMyVTdYRzU5TzF4dVhHNHZLaXBjYmlBcUlFZGxkSE1nZEdobElIWmhiSFZsSUc5bUlHRWdjSEp2Y0dWeWRIa2dhVzRnWVNCbWRYUjFjbVVnZEhWeWJpNWNiaUFxSUVCd1lYSmhiU0J2WW1wbFkzUWdJQ0FnY0hKdmJXbHpaU0J2Y2lCcGJXMWxaR2xoZEdVZ2NtVm1aWEpsYm1ObElHWnZjaUIwWVhKblpYUWdiMkpxWldOMFhHNGdLaUJBY0dGeVlXMGdibUZ0WlNBZ0lDQWdJRzVoYldVZ2IyWWdjSEp2Y0dWeWRIa2dkRzhnWjJWMFhHNGdLaUJBY21WMGRYSnVJSEJ5YjIxcGMyVWdabTl5SUhSb1pTQndjbTl3WlhKMGVTQjJZV3gxWlZ4dUlDb3ZYRzVSTG1kbGRDQTlJR1oxYm1OMGFXOXVJQ2h2WW1wbFkzUXNJR3RsZVNrZ2UxeHVJQ0FnSUhKbGRIVnliaUJSS0c5aWFtVmpkQ2t1WkdsemNHRjBZMmdvWENKblpYUmNJaXdnVzJ0bGVWMHBPMXh1ZlR0Y2JseHVVSEp2YldselpTNXdjbTkwYjNSNWNHVXVaMlYwSUQwZ1puVnVZM1JwYjI0Z0tHdGxlU2tnZTF4dUlDQWdJSEpsZEhWeWJpQjBhR2x6TG1ScGMzQmhkR05vS0Z3aVoyVjBYQ0lzSUZ0clpYbGRLVHRjYm4wN1hHNWNiaThxS2x4dUlDb2dVMlYwY3lCMGFHVWdkbUZzZFdVZ2IyWWdZU0J3Y205d1pYSjBlU0JwYmlCaElHWjFkSFZ5WlNCMGRYSnVMbHh1SUNvZ1FIQmhjbUZ0SUc5aWFtVmpkQ0FnSUNCd2NtOXRhWE5sSUc5eUlHbHRiV1ZrYVdGMFpTQnlaV1psY21WdVkyVWdabTl5SUc5aWFtVmpkQ0J2WW1wbFkzUmNiaUFxSUVCd1lYSmhiU0J1WVcxbElDQWdJQ0FnYm1GdFpTQnZaaUJ3Y205d1pYSjBlU0IwYnlCelpYUmNiaUFxSUVCd1lYSmhiU0IyWVd4MVpTQWdJQ0FnYm1WM0lIWmhiSFZsSUc5bUlIQnliM0JsY25SNVhHNGdLaUJBY21WMGRYSnVJSEJ5YjIxcGMyVWdabTl5SUhSb1pTQnlaWFIxY200Z2RtRnNkV1ZjYmlBcUwxeHVVUzV6WlhRZ1BTQm1kVzVqZEdsdmJpQW9iMkpxWldOMExDQnJaWGtzSUhaaGJIVmxLU0I3WEc0Z0lDQWdjbVYwZFhKdUlGRW9iMkpxWldOMEtTNWthWE53WVhSamFDaGNJbk5sZEZ3aUxDQmJhMlY1TENCMllXeDFaVjBwTzF4dWZUdGNibHh1VUhKdmJXbHpaUzV3Y205MGIzUjVjR1V1YzJWMElEMGdablZ1WTNScGIyNGdLR3RsZVN3Z2RtRnNkV1VwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1a2FYTndZWFJqYUNoY0luTmxkRndpTENCYmEyVjVMQ0IyWVd4MVpWMHBPMXh1ZlR0Y2JseHVMeW9xWEc0Z0tpQkVaV3hsZEdWeklHRWdjSEp2Y0dWeWRIa2dhVzRnWVNCbWRYUjFjbVVnZEhWeWJpNWNiaUFxSUVCd1lYSmhiU0J2WW1wbFkzUWdJQ0FnY0hKdmJXbHpaU0J2Y2lCcGJXMWxaR2xoZEdVZ2NtVm1aWEpsYm1ObElHWnZjaUIwWVhKblpYUWdiMkpxWldOMFhHNGdLaUJBY0dGeVlXMGdibUZ0WlNBZ0lDQWdJRzVoYldVZ2IyWWdjSEp2Y0dWeWRIa2dkRzhnWkdWc1pYUmxYRzRnS2lCQWNtVjBkWEp1SUhCeWIyMXBjMlVnWm05eUlIUm9aU0J5WlhSMWNtNGdkbUZzZFdWY2JpQXFMMXh1VVM1a1pXd2dQU0F2THlCWVdGZ2diR1ZuWVdONVhHNVJXMXdpWkdWc1pYUmxYQ0pkSUQwZ1puVnVZM1JwYjI0Z0tHOWlhbVZqZEN3Z2EyVjVLU0I3WEc0Z0lDQWdjbVYwZFhKdUlGRW9iMkpxWldOMEtTNWthWE53WVhSamFDaGNJbVJsYkdWMFpWd2lMQ0JiYTJWNVhTazdYRzU5TzF4dVhHNVFjbTl0YVhObExuQnliM1J2ZEhsd1pTNWtaV3dnUFNBdkx5QllXRmdnYkdWbllXTjVYRzVRY205dGFYTmxMbkJ5YjNSdmRIbHdaVnRjSW1SbGJHVjBaVndpWFNBOUlHWjFibU4wYVc5dUlDaHJaWGtwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdkR2hwY3k1a2FYTndZWFJqYUNoY0ltUmxiR1YwWlZ3aUxDQmJhMlY1WFNrN1hHNTlPMXh1WEc0dktpcGNiaUFxSUVsdWRtOXJaWE1nWVNCdFpYUm9iMlFnYVc0Z1lTQm1kWFIxY21VZ2RIVnliaTVjYmlBcUlFQndZWEpoYlNCdlltcGxZM1FnSUNBZ2NISnZiV2x6WlNCdmNpQnBiVzFsWkdsaGRHVWdjbVZtWlhKbGJtTmxJR1p2Y2lCMFlYSm5aWFFnYjJKcVpXTjBYRzRnS2lCQWNHRnlZVzBnYm1GdFpTQWdJQ0FnSUc1aGJXVWdiMllnYldWMGFHOWtJSFJ2SUdsdWRtOXJaVnh1SUNvZ1FIQmhjbUZ0SUhaaGJIVmxJQ0FnSUNCaElIWmhiSFZsSUhSdklIQnZjM1FzSUhSNWNHbGpZV3hzZVNCaGJpQmhjbkpoZVNCdlpseHVJQ29nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JwYm5adlkyRjBhVzl1SUdGeVozVnRaVzUwY3lCbWIzSWdjSEp2YldselpYTWdkR2hoZEZ4dUlDb2dJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQmhjbVVnZFd4MGFXMWhkR1ZzZVNCaVlXTnJaV1FnZDJsMGFDQmdjbVZ6YjJ4MlpXQWdkbUZzZFdWekxGeHVJQ29nSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JoY3lCdmNIQnZjMlZrSUhSdklIUm9iM05sSUdKaFkydGxaQ0IzYVhSb0lGVlNUSE5jYmlBcUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2QyaGxjbVZwYmlCMGFHVWdjRzl6ZEdWa0lIWmhiSFZsSUdOaGJpQmlaU0JoYm5sY2JpQXFJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdTbE5QVGlCelpYSnBZV3hwZW1GaWJHVWdiMkpxWldOMExseHVJQ29nUUhKbGRIVnliaUJ3Y205dGFYTmxJR1p2Y2lCMGFHVWdjbVYwZFhKdUlIWmhiSFZsWEc0Z0tpOWNiaTh2SUdKdmRXNWtJR3h2WTJGc2JIa2dZbVZqWVhWelpTQnBkQ0JwY3lCMWMyVmtJR0o1SUc5MGFHVnlJRzFsZEdodlpITmNibEV1YldGd2NHeDVJRDBnTHk4Z1dGaFlJRUZ6SUhCeWIzQnZjMlZrSUdKNUlGd2lVbVZrYzJGdVpISnZYQ0pjYmxFdWNHOXpkQ0E5SUdaMWJtTjBhVzl1SUNodlltcGxZM1FzSUc1aGJXVXNJR0Z5WjNNcElIdGNiaUFnSUNCeVpYUjFjbTRnVVNodlltcGxZM1FwTG1ScGMzQmhkR05vS0Z3aWNHOXpkRndpTENCYmJtRnRaU3dnWVhKbmMxMHBPMXh1ZlR0Y2JseHVVSEp2YldselpTNXdjbTkwYjNSNWNHVXViV0Z3Y0d4NUlEMGdMeThnV0ZoWUlFRnpJSEJ5YjNCdmMyVmtJR0o1SUZ3aVVtVmtjMkZ1WkhKdlhDSmNibEJ5YjIxcGMyVXVjSEp2ZEc5MGVYQmxMbkJ2YzNRZ1BTQm1kVzVqZEdsdmJpQW9ibUZ0WlN3Z1lYSm5jeWtnZTF4dUlDQWdJSEpsZEhWeWJpQjBhR2x6TG1ScGMzQmhkR05vS0Z3aWNHOXpkRndpTENCYmJtRnRaU3dnWVhKbmMxMHBPMXh1ZlR0Y2JseHVMeW9xWEc0Z0tpQkpiblp2YTJWeklHRWdiV1YwYUc5a0lHbHVJR0VnWm5WMGRYSmxJSFIxY200dVhHNGdLaUJBY0dGeVlXMGdiMkpxWldOMElDQWdJSEJ5YjIxcGMyVWdiM0lnYVcxdFpXUnBZWFJsSUhKbFptVnlaVzVqWlNCbWIzSWdkR0Z5WjJWMElHOWlhbVZqZEZ4dUlDb2dRSEJoY21GdElHNWhiV1VnSUNBZ0lDQnVZVzFsSUc5bUlHMWxkR2h2WkNCMGJ5QnBiblp2YTJWY2JpQXFJRUJ3WVhKaGJTQXVMaTVoY21keklDQWdZWEp5WVhrZ2IyWWdhVzUyYjJOaGRHbHZiaUJoY21kMWJXVnVkSE5jYmlBcUlFQnlaWFIxY200Z2NISnZiV2x6WlNCbWIzSWdkR2hsSUhKbGRIVnliaUIyWVd4MVpWeHVJQ292WEc1UkxuTmxibVFnUFNBdkx5QllXRmdnVFdGeWF5Qk5hV3hzWlhJbmN5QndjbTl3YjNObFpDQndZWEpzWVc1alpWeHVVUzV0WTJGc2JDQTlJQzh2SUZoWVdDQkJjeUJ3Y205d2IzTmxaQ0JpZVNCY0lsSmxaSE5oYm1SeWIxd2lYRzVSTG1sdWRtOXJaU0E5SUdaMWJtTjBhVzl1SUNodlltcGxZM1FzSUc1aGJXVWdMeW91TGk1aGNtZHpLaThwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdVU2h2WW1wbFkzUXBMbVJwYzNCaGRHTm9LRndpY0c5emRGd2lMQ0JiYm1GdFpTd2dZWEp5WVhsZmMyeHBZMlVvWVhKbmRXMWxiblJ6TENBeUtWMHBPMXh1ZlR0Y2JseHVVSEp2YldselpTNXdjbTkwYjNSNWNHVXVjMlZ1WkNBOUlDOHZJRmhZV0NCTllYSnJJRTFwYkd4bGNpZHpJSEJ5YjNCdmMyVmtJSEJoY214aGJtTmxYRzVRY205dGFYTmxMbkJ5YjNSdmRIbHdaUzV0WTJGc2JDQTlJQzh2SUZoWVdDQkJjeUJ3Y205d2IzTmxaQ0JpZVNCY0lsSmxaSE5oYm1SeWIxd2lYRzVRY205dGFYTmxMbkJ5YjNSdmRIbHdaUzVwYm5admEyVWdQU0JtZFc1amRHbHZiaUFvYm1GdFpTQXZLaTR1TG1GeVozTXFMeWtnZTF4dUlDQWdJSEpsZEhWeWJpQjBhR2x6TG1ScGMzQmhkR05vS0Z3aWNHOXpkRndpTENCYmJtRnRaU3dnWVhKeVlYbGZjMnhwWTJVb1lYSm5kVzFsYm5SekxDQXhLVjBwTzF4dWZUdGNibHh1THlvcVhHNGdLaUJCY0hCc2FXVnpJSFJvWlNCd2NtOXRhWE5sWkNCbWRXNWpkR2x2YmlCcGJpQmhJR1oxZEhWeVpTQjBkWEp1TGx4dUlDb2dRSEJoY21GdElHOWlhbVZqZENBZ0lDQndjbTl0YVhObElHOXlJR2x0YldWa2FXRjBaU0J5WldabGNtVnVZMlVnWm05eUlIUmhjbWRsZENCbWRXNWpkR2x2Ymx4dUlDb2dRSEJoY21GdElHRnlaM01nSUNBZ0lDQmhjbkpoZVNCdlppQmhjSEJzYVdOaGRHbHZiaUJoY21kMWJXVnVkSE5jYmlBcUwxeHVVUzVtWVhCd2JIa2dQU0JtZFc1amRHbHZiaUFvYjJKcVpXTjBMQ0JoY21kektTQjdYRzRnSUNBZ2NtVjBkWEp1SUZFb2IySnFaV04wS1M1a2FYTndZWFJqYUNoY0ltRndjR3g1WENJc0lGdDJiMmxrSURBc0lHRnlaM05kS1R0Y2JuMDdYRzVjYmxCeWIyMXBjMlV1Y0hKdmRHOTBlWEJsTG1aaGNIQnNlU0E5SUdaMWJtTjBhVzl1SUNoaGNtZHpLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIUm9hWE11WkdsemNHRjBZMmdvWENKaGNIQnNlVndpTENCYmRtOXBaQ0F3TENCaGNtZHpYU2s3WEc1OU8xeHVYRzR2S2lwY2JpQXFJRU5oYkd4eklIUm9aU0J3Y205dGFYTmxaQ0JtZFc1amRHbHZiaUJwYmlCaElHWjFkSFZ5WlNCMGRYSnVMbHh1SUNvZ1FIQmhjbUZ0SUc5aWFtVmpkQ0FnSUNCd2NtOXRhWE5sSUc5eUlHbHRiV1ZrYVdGMFpTQnlaV1psY21WdVkyVWdabTl5SUhSaGNtZGxkQ0JtZFc1amRHbHZibHh1SUNvZ1FIQmhjbUZ0SUM0dUxtRnlaM01nSUNCaGNuSmhlU0J2WmlCaGNIQnNhV05oZEdsdmJpQmhjbWQxYldWdWRITmNiaUFxTDF4dVVWdGNJblJ5ZVZ3aVhTQTlYRzVSTG1aallXeHNJRDBnWm5WdVkzUnBiMjRnS0c5aWFtVmpkQ0F2S2lBdUxpNWhjbWR6S2k4cElIdGNiaUFnSUNCeVpYUjFjbTRnVVNodlltcGxZM1FwTG1ScGMzQmhkR05vS0Z3aVlYQndiSGxjSWl3Z1czWnZhV1FnTUN3Z1lYSnlZWGxmYzJ4cFkyVW9ZWEpuZFcxbGJuUnpMQ0F4S1YwcE8xeHVmVHRjYmx4dVVISnZiV2x6WlM1d2NtOTBiM1I1Y0dVdVptTmhiR3dnUFNCbWRXNWpkR2x2YmlBb0x5b3VMaTVoY21kektpOHBJSHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTVrYVhOd1lYUmphQ2hjSW1Gd2NHeDVYQ0lzSUZ0MmIybGtJREFzSUdGeWNtRjVYM05zYVdObEtHRnlaM1Z0Wlc1MGN5bGRLVHRjYm4wN1hHNWNiaThxS2x4dUlDb2dRbWx1WkhNZ2RHaGxJSEJ5YjIxcGMyVmtJR1oxYm1OMGFXOXVMQ0IwY21GdWMyWnZjbTFwYm1jZ2NtVjBkWEp1SUhaaGJIVmxjeUJwYm5SdklHRWdablZzWm1sc2JHVmtYRzRnS2lCd2NtOXRhWE5sSUdGdVpDQjBhSEp2ZDI0Z1pYSnliM0p6SUdsdWRHOGdZU0J5WldwbFkzUmxaQ0J2Ym1VdVhHNGdLaUJBY0dGeVlXMGdiMkpxWldOMElDQWdJSEJ5YjIxcGMyVWdiM0lnYVcxdFpXUnBZWFJsSUhKbFptVnlaVzVqWlNCbWIzSWdkR0Z5WjJWMElHWjFibU4wYVc5dVhHNGdLaUJBY0dGeVlXMGdMaTR1WVhKbmN5QWdJR0Z5Y21GNUlHOW1JR0Z3Y0d4cFkyRjBhVzl1SUdGeVozVnRaVzUwYzF4dUlDb3ZYRzVSTG1aaWFXNWtJRDBnWm5WdVkzUnBiMjRnS0c5aWFtVmpkQ0F2S2k0dUxtRnlaM01xTHlrZ2UxeHVJQ0FnSUhaaGNpQndjbTl0YVhObElEMGdVU2h2WW1wbFkzUXBPMXh1SUNBZ0lIWmhjaUJoY21keklEMGdZWEp5WVhsZmMyeHBZMlVvWVhKbmRXMWxiblJ6TENBeEtUdGNiaUFnSUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRnWm1KdmRXNWtLQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnY0hKdmJXbHpaUzVrYVhOd1lYUmphQ2hjSW1Gd2NHeDVYQ0lzSUZ0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFJvYVhNc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY21kekxtTnZibU5oZENoaGNuSmhlVjl6YkdsalpTaGhjbWQxYldWdWRITXBLVnh1SUNBZ0lDQWdJQ0JkS1R0Y2JpQWdJQ0I5TzF4dWZUdGNibEJ5YjIxcGMyVXVjSEp2ZEc5MGVYQmxMbVppYVc1a0lEMGdablZ1WTNScGIyNGdLQzhxTGk0dVlYSm5jeW92S1NCN1hHNGdJQ0FnZG1GeUlIQnliMjFwYzJVZ1BTQjBhR2x6TzF4dUlDQWdJSFpoY2lCaGNtZHpJRDBnWVhKeVlYbGZjMnhwWTJVb1lYSm5kVzFsYm5SektUdGNiaUFnSUNCeVpYUjFjbTRnWm5WdVkzUnBiMjRnWm1KdmRXNWtLQ2tnZTF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnY0hKdmJXbHpaUzVrYVhOd1lYUmphQ2hjSW1Gd2NHeDVYQ0lzSUZ0Y2JpQWdJQ0FnSUNBZ0lDQWdJSFJvYVhNc1hHNGdJQ0FnSUNBZ0lDQWdJQ0JoY21kekxtTnZibU5oZENoaGNuSmhlVjl6YkdsalpTaGhjbWQxYldWdWRITXBLVnh1SUNBZ0lDQWdJQ0JkS1R0Y2JpQWdJQ0I5TzF4dWZUdGNibHh1THlvcVhHNGdLaUJTWlhGMVpYTjBjeUIwYUdVZ2JtRnRaWE1nYjJZZ2RHaGxJRzkzYm1Wa0lIQnliM0JsY25ScFpYTWdiMllnWVNCd2NtOXRhWE5sWkZ4dUlDb2diMkpxWldOMElHbHVJR0VnWm5WMGRYSmxJSFIxY200dVhHNGdLaUJBY0dGeVlXMGdiMkpxWldOMElDQWdJSEJ5YjIxcGMyVWdiM0lnYVcxdFpXUnBZWFJsSUhKbFptVnlaVzVqWlNCbWIzSWdkR0Z5WjJWMElHOWlhbVZqZEZ4dUlDb2dRSEpsZEhWeWJpQndjbTl0YVhObElHWnZjaUIwYUdVZ2EyVjVjeUJ2WmlCMGFHVWdaWFpsYm5SMVlXeHNlU0J6WlhSMGJHVmtJRzlpYW1WamRGeHVJQ292WEc1UkxtdGxlWE1nUFNCbWRXNWpkR2x2YmlBb2IySnFaV04wS1NCN1hHNGdJQ0FnY21WMGRYSnVJRkVvYjJKcVpXTjBLUzVrYVhOd1lYUmphQ2hjSW10bGVYTmNJaXdnVzEwcE8xeHVmVHRjYmx4dVVISnZiV2x6WlM1d2NtOTBiM1I1Y0dVdWEyVjVjeUE5SUdaMWJtTjBhVzl1SUNncElIdGNiaUFnSUNCeVpYUjFjbTRnZEdocGN5NWthWE53WVhSamFDaGNJbXRsZVhOY0lpd2dXMTBwTzF4dWZUdGNibHh1THlvcVhHNGdLaUJVZFhKdWN5QmhiaUJoY25KaGVTQnZaaUJ3Y205dGFYTmxjeUJwYm5SdklHRWdjSEp2YldselpTQm1iM0lnWVc0Z1lYSnlZWGt1SUNCSlppQmhibmtnYjJaY2JpQXFJSFJvWlNCd2NtOXRhWE5sY3lCblpYUnpJSEpsYW1WamRHVmtMQ0IwYUdVZ2QyaHZiR1VnWVhKeVlYa2dhWE1nY21WcVpXTjBaV1FnYVcxdFpXUnBZWFJsYkhrdVhHNGdLaUJBY0dGeVlXMGdlMEZ5Y21GNUtuMGdZVzRnWVhKeVlYa2dLRzl5SUhCeWIyMXBjMlVnWm05eUlHRnVJR0Z5Y21GNUtTQnZaaUIyWVd4MVpYTWdLRzl5WEc0Z0tpQndjbTl0YVhObGN5Qm1iM0lnZG1Gc2RXVnpLVnh1SUNvZ1FISmxkSFZ5Ym5NZ1lTQndjbTl0YVhObElHWnZjaUJoYmlCaGNuSmhlU0J2WmlCMGFHVWdZMjl5Y21WemNHOXVaR2x1WnlCMllXeDFaWE5jYmlBcUwxeHVMeThnUW5rZ1RXRnlheUJOYVd4c1pYSmNiaTh2SUdoMGRIQTZMeTkzYVd0cExtVmpiV0Z6WTNKcGNIUXViM0puTDJSdmEzVXVjR2h3UDJsa1BYTjBjbUYzYldGdU9tTnZibU4xY25KbGJtTjVKbkpsZGoweE16QTROemMyTlRJeEkyRnNiR1oxYkdacGJHeGxaRnh1VVM1aGJHd2dQU0JoYkd3N1hHNW1kVzVqZEdsdmJpQmhiR3dvY0hKdmJXbHpaWE1wSUh0Y2JpQWdJQ0J5WlhSMWNtNGdkMmhsYmlod2NtOXRhWE5sY3l3Z1puVnVZM1JwYjI0Z0tIQnliMjFwYzJWektTQjdYRzRnSUNBZ0lDQWdJSFpoY2lCd1pXNWthVzVuUTI5MWJuUWdQU0F3TzF4dUlDQWdJQ0FnSUNCMllYSWdaR1ZtWlhKeVpXUWdQU0JrWldabGNpZ3BPMXh1SUNBZ0lDQWdJQ0JoY25KaGVWOXlaV1IxWTJVb2NISnZiV2x6WlhNc0lHWjFibU4wYVc5dUlDaDFibVJsWm1sdVpXUXNJSEJ5YjIxcGMyVXNJR2x1WkdWNEtTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCMllYSWdjMjVoY0hOb2IzUTdYRzRnSUNBZ0lDQWdJQ0FnSUNCcFppQW9YRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdhWE5RY205dGFYTmxLSEJ5YjIxcGMyVXBJQ1ltWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnS0hOdVlYQnphRzkwSUQwZ2NISnZiV2x6WlM1cGJuTndaV04wS0NrcExuTjBZWFJsSUQwOVBTQmNJbVoxYkdacGJHeGxaRndpWEc0Z0lDQWdJQ0FnSUNBZ0lDQXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J3Y205dGFYTmxjMXRwYm1SbGVGMGdQU0J6Ym1Gd2MyaHZkQzUyWVd4MVpUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgwZ1pXeHpaU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnS3l0d1pXNWthVzVuUTI5MWJuUTdYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdkMmhsYmloY2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdjSEp2YldselpTeGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnWm5WdVkzUnBiMjRnS0haaGJIVmxLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0J3Y205dGFYTmxjMXRwYm1SbGVGMGdQU0IyWVd4MVpUdGNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lHbG1JQ2d0TFhCbGJtUnBibWREYjNWdWRDQTlQVDBnTUNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJR1JsWm1WeWNtVmtMbkpsYzI5c2RtVW9jSEp2YldselpYTXBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdmVnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCOUxGeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JrWldabGNuSmxaQzV5WldwbFkzUXNYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdaMWJtTjBhVzl1SUNod2NtOW5jbVZ6Y3lrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ1pHVm1aWEp5WldRdWJtOTBhV1o1S0hzZ2FXNWtaWGc2SUdsdVpHVjRMQ0IyWVd4MVpUb2djSEp2WjNKbGMzTWdmU2s3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lIMWNiaUFnSUNBZ0lDQWdJQ0FnSUNBZ0lDQXBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQjlMQ0IyYjJsa0lEQXBPMXh1SUNBZ0lDQWdJQ0JwWmlBb2NHVnVaR2x1WjBOdmRXNTBJRDA5UFNBd0tTQjdYRzRnSUNBZ0lDQWdJQ0FnSUNCa1pXWmxjbkpsWkM1eVpYTnZiSFpsS0hCeWIyMXBjMlZ6S1R0Y2JpQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z1pHVm1aWEp5WldRdWNISnZiV2x6WlR0Y2JpQWdJQ0I5S1R0Y2JuMWNibHh1VUhKdmJXbHpaUzV3Y205MGIzUjVjR1V1WVd4c0lEMGdablZ1WTNScGIyNGdLQ2tnZTF4dUlDQWdJSEpsZEhWeWJpQmhiR3dvZEdocGN5azdYRzU5TzF4dVhHNHZLaXBjYmlBcUlGSmxkSFZ5Ym5NZ2RHaGxJR1pwY25OMElISmxjMjlzZG1Wa0lIQnliMjFwYzJVZ2IyWWdZVzRnWVhKeVlYa3VJRkJ5YVc5eUlISmxhbVZqZEdWa0lIQnliMjFwYzJWeklHRnlaVnh1SUNvZ2FXZHViM0psWkM0Z0lGSmxhbVZqZEhNZ2IyNXNlU0JwWmlCaGJHd2djSEp2YldselpYTWdZWEpsSUhKbGFtVmpkR1ZrTGx4dUlDb2dRSEJoY21GdElIdEJjbkpoZVNwOUlHRnVJR0Z5Y21GNUlHTnZiblJoYVc1cGJtY2dkbUZzZFdWeklHOXlJSEJ5YjIxcGMyVnpJR1p2Y2lCMllXeDFaWE5jYmlBcUlFQnlaWFIxY201eklHRWdjSEp2YldselpTQm1kV3htYVd4c1pXUWdkMmwwYUNCMGFHVWdkbUZzZFdVZ2IyWWdkR2hsSUdacGNuTjBJSEpsYzI5c2RtVmtJSEJ5YjIxcGMyVXNYRzRnS2lCdmNpQmhJSEpsYW1WamRHVmtJSEJ5YjIxcGMyVWdhV1lnWVd4c0lIQnliMjFwYzJWeklHRnlaU0J5WldwbFkzUmxaQzVjYmlBcUwxeHVVUzVoYm5rZ1BTQmhibms3WEc1Y2JtWjFibU4wYVc5dUlHRnVlU2h3Y205dGFYTmxjeWtnZTF4dUlDQWdJR2xtSUNod2NtOXRhWE5sY3k1c1pXNW5kR2dnUFQwOUlEQXBJSHRjYmlBZ0lDQWdJQ0FnY21WMGRYSnVJRkV1Y21WemIyeDJaU2dwTzF4dUlDQWdJSDFjYmx4dUlDQWdJSFpoY2lCa1pXWmxjbkpsWkNBOUlGRXVaR1ZtWlhJb0tUdGNiaUFnSUNCMllYSWdjR1Z1WkdsdVowTnZkVzUwSUQwZ01EdGNiaUFnSUNCaGNuSmhlVjl5WldSMVkyVW9jSEp2YldselpYTXNJR1oxYm1OMGFXOXVJQ2h3Y21WMkxDQmpkWEp5Wlc1MExDQnBibVJsZUNrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnY0hKdmJXbHpaU0E5SUhCeWIyMXBjMlZ6VzJsdVpHVjRYVHRjYmx4dUlDQWdJQ0FnSUNCd1pXNWthVzVuUTI5MWJuUXJLenRjYmx4dUlDQWdJQ0FnSUNCM2FHVnVLSEJ5YjIxcGMyVXNJRzl1Um5Wc1ptbHNiR1ZrTENCdmJsSmxhbVZqZEdWa0xDQnZibEJ5YjJkeVpYTnpLVHRjYmlBZ0lDQWdJQ0FnWm5WdVkzUnBiMjRnYjI1R2RXeG1hV3hzWldRb2NtVnpkV3gwS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0JrWldabGNuSmxaQzV5WlhOdmJIWmxLSEpsYzNWc2RDazdYRzRnSUNBZ0lDQWdJSDFjYmlBZ0lDQWdJQ0FnWm5WdVkzUnBiMjRnYjI1U1pXcGxZM1JsWkNncElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUhCbGJtUnBibWREYjNWdWRDMHRPMXh1SUNBZ0lDQWdJQ0FnSUNBZ2FXWWdLSEJsYm1ScGJtZERiM1Z1ZENBOVBUMGdNQ2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUdSbFptVnljbVZrTG5KbGFtVmpkQ2h1WlhjZ1JYSnliM0lvWEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ0lGd2lRMkZ1SjNRZ1oyVjBJR1oxYkdacGJHeHRaVzUwSUhaaGJIVmxJR1p5YjIwZ1lXNTVJSEJ5YjIxcGMyVXNJR0ZzYkNCY0lpQXJYRzRnSUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUZ3aWNISnZiV2x6WlhNZ2QyVnlaU0J5WldwbFkzUmxaQzVjSWx4dUlDQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNrcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnZlZ4dUlDQWdJQ0FnSUNCOVhHNGdJQ0FnSUNBZ0lHWjFibU4wYVc5dUlHOXVVSEp2WjNKbGMzTW9jSEp2WjNKbGMzTXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHUmxabVZ5Y21Wa0xtNXZkR2xtZVNoN1hHNGdJQ0FnSUNBZ0lDQWdJQ0FnSUNBZ2FXNWtaWGc2SUdsdVpHVjRMRnh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJSFpoYkhWbE9pQndjbTluY21WemMxeHVJQ0FnSUNBZ0lDQWdJQ0FnZlNrN1hHNGdJQ0FnSUNBZ0lIMWNiaUFnSUNCOUxDQjFibVJsWm1sdVpXUXBPMXh1WEc0Z0lDQWdjbVYwZFhKdUlHUmxabVZ5Y21Wa0xuQnliMjFwYzJVN1hHNTlYRzVjYmxCeWIyMXBjMlV1Y0hKdmRHOTBlWEJsTG1GdWVTQTlJR1oxYm1OMGFXOXVJQ2dwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdZVzU1S0hSb2FYTXBPMXh1ZlR0Y2JseHVMeW9xWEc0Z0tpQlhZV2wwY3lCbWIzSWdZV3hzSUhCeWIyMXBjMlZ6SUhSdklHSmxJSE5sZEhSc1pXUXNJR1ZwZEdobGNpQm1kV3htYVd4c1pXUWdiM0pjYmlBcUlISmxhbVZqZEdWa0xpQWdWR2hwY3lCcGN5QmthWE4wYVc1amRDQm1jbTl0SUdCaGJHeGdJSE5wYm1ObElIUm9ZWFFnZDI5MWJHUWdjM1J2Y0Z4dUlDb2dkMkZwZEdsdVp5QmhkQ0IwYUdVZ1ptbHljM1FnY21WcVpXTjBhVzl1TGlBZ1ZHaGxJSEJ5YjIxcGMyVWdjbVYwZFhKdVpXUWdZbmxjYmlBcUlHQmhiR3hTWlhOdmJIWmxaR0FnZDJsc2JDQnVaWFpsY2lCaVpTQnlaV3BsWTNSbFpDNWNiaUFxSUVCd1lYSmhiU0J3Y205dGFYTmxjeUJoSUhCeWIyMXBjMlVnWm05eUlHRnVJR0Z5Y21GNUlDaHZjaUJoYmlCaGNuSmhlU2tnYjJZZ2NISnZiV2x6WlhOY2JpQXFJQ2h2Y2lCMllXeDFaWE1wWEc0Z0tpQkFjbVYwZFhKdUlHRWdjSEp2YldselpTQm1iM0lnWVc0Z1lYSnlZWGtnYjJZZ2NISnZiV2x6WlhOY2JpQXFMMXh1VVM1aGJHeFNaWE52YkhabFpDQTlJR1JsY0hKbFkyRjBaU2hoYkd4U1pYTnZiSFpsWkN3Z1hDSmhiR3hTWlhOdmJIWmxaRndpTENCY0ltRnNiRk5sZEhSc1pXUmNJaWs3WEc1bWRXNWpkR2x2YmlCaGJHeFNaWE52YkhabFpDaHdjbTl0YVhObGN5a2dlMXh1SUNBZ0lISmxkSFZ5YmlCM2FHVnVLSEJ5YjIxcGMyVnpMQ0JtZFc1amRHbHZiaUFvY0hKdmJXbHpaWE1wSUh0Y2JpQWdJQ0FnSUNBZ2NISnZiV2x6WlhNZ1BTQmhjbkpoZVY5dFlYQW9jSEp2YldselpYTXNJRkVwTzF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnZDJobGJpaGhiR3dvWVhKeVlYbGZiV0Z3S0hCeWIyMXBjMlZ6TENCbWRXNWpkR2x2YmlBb2NISnZiV2x6WlNrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSGRvWlc0b2NISnZiV2x6WlN3Z2JtOXZjQ3dnYm05dmNDazdYRzRnSUNBZ0lDQWdJSDBwS1N3Z1puVnVZM1JwYjI0Z0tDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ2NtVjBkWEp1SUhCeWIyMXBjMlZ6TzF4dUlDQWdJQ0FnSUNCOUtUdGNiaUFnSUNCOUtUdGNibjFjYmx4dVVISnZiV2x6WlM1d2NtOTBiM1I1Y0dVdVlXeHNVbVZ6YjJ4MlpXUWdQU0JtZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnY21WMGRYSnVJR0ZzYkZKbGMyOXNkbVZrS0hSb2FYTXBPMXh1ZlR0Y2JseHVMeW9xWEc0Z0tpQkFjMlZsSUZCeWIyMXBjMlVqWVd4c1UyVjBkR3hsWkZ4dUlDb3ZYRzVSTG1Gc2JGTmxkSFJzWldRZ1BTQmhiR3hUWlhSMGJHVmtPMXh1Wm5WdVkzUnBiMjRnWVd4c1UyVjBkR3hsWkNod2NtOXRhWE5sY3lrZ2UxeHVJQ0FnSUhKbGRIVnliaUJSS0hCeWIyMXBjMlZ6S1M1aGJHeFRaWFIwYkdWa0tDazdYRzU5WEc1Y2JpOHFLbHh1SUNvZ1ZIVnlibk1nWVc0Z1lYSnlZWGtnYjJZZ2NISnZiV2x6WlhNZ2FXNTBieUJoSUhCeWIyMXBjMlVnWm05eUlHRnVJR0Z5Y21GNUlHOW1JSFJvWldseUlITjBZWFJsY3lBb1lYTmNiaUFxSUhKbGRIVnlibVZrSUdKNUlHQnBibk53WldOMFlDa2dkMmhsYmlCMGFHVjVJR2hoZG1VZ1lXeHNJSE5sZEhSc1pXUXVYRzRnS2lCQWNHRnlZVzBnZTBGeWNtRjVXMEZ1ZVNwZGZTQjJZV3gxWlhNZ1lXNGdZWEp5WVhrZ0tHOXlJSEJ5YjIxcGMyVWdabTl5SUdGdUlHRnljbUY1S1NCdlppQjJZV3gxWlhNZ0tHOXlYRzRnS2lCd2NtOXRhWE5sY3lCbWIzSWdkbUZzZFdWektWeHVJQ29nUUhKbGRIVnlibk1nZTBGeWNtRjVXMU4wWVhSbFhYMGdZVzRnWVhKeVlYa2diMllnYzNSaGRHVnpJR1p2Y2lCMGFHVWdjbVZ6Y0dWamRHbDJaU0IyWVd4MVpYTXVYRzRnS2k5Y2JsQnliMjFwYzJVdWNISnZkRzkwZVhCbExtRnNiRk5sZEhSc1pXUWdQU0JtZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnY21WMGRYSnVJSFJvYVhNdWRHaGxiaWhtZFc1amRHbHZiaUFvY0hKdmJXbHpaWE1wSUh0Y2JpQWdJQ0FnSUNBZ2NtVjBkWEp1SUdGc2JDaGhjbkpoZVY5dFlYQW9jSEp2YldselpYTXNJR1oxYm1OMGFXOXVJQ2h3Y205dGFYTmxLU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQndjbTl0YVhObElEMGdVU2h3Y205dGFYTmxLVHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHWjFibU4wYVc5dUlISmxaMkZ5Wkd4bGMzTW9LU0I3WEc0Z0lDQWdJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSEJ5YjIxcGMyVXVhVzV6Y0dWamRDZ3BPMXh1SUNBZ0lDQWdJQ0FnSUNBZ2ZWeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJSEJ5YjIxcGMyVXVkR2hsYmloeVpXZGhjbVJzWlhOekxDQnlaV2RoY21Sc1pYTnpLVHRjYmlBZ0lDQWdJQ0FnZlNrcE8xeHVJQ0FnSUgwcE8xeHVmVHRjYmx4dUx5b3FYRzRnS2lCRFlYQjBkWEpsY3lCMGFHVWdabUZwYkhWeVpTQnZaaUJoSUhCeWIyMXBjMlVzSUdkcGRtbHVaeUJoYmlCdmNHOXlkSFZ1YVhSNUlIUnZJSEpsWTI5MlpYSmNiaUFxSUhkcGRHZ2dZU0JqWVd4c1ltRmpheTRnSUVsbUlIUm9aU0JuYVhabGJpQndjbTl0YVhObElHbHpJR1oxYkdacGJHeGxaQ3dnZEdobElISmxkSFZ5Ym1Wa1hHNGdLaUJ3Y205dGFYTmxJR2x6SUdaMWJHWnBiR3hsWkM1Y2JpQXFJRUJ3WVhKaGJTQjdRVzU1S24wZ2NISnZiV2x6WlNCbWIzSWdjMjl0WlhSb2FXNW5YRzRnS2lCQWNHRnlZVzBnZTBaMWJtTjBhVzl1ZlNCallXeHNZbUZqYXlCMGJ5Qm1kV3htYVd4c0lIUm9aU0J5WlhSMWNtNWxaQ0J3Y205dGFYTmxJR2xtSUhSb1pWeHVJQ29nWjJsMlpXNGdjSEp2YldselpTQnBjeUJ5WldwbFkzUmxaRnh1SUNvZ1FISmxkSFZ5Ym5NZ1lTQndjbTl0YVhObElHWnZjaUIwYUdVZ2NtVjBkWEp1SUhaaGJIVmxJRzltSUhSb1pTQmpZV3hzWW1GamExeHVJQ292WEc1UkxtWmhhV3dnUFNBdkx5QllXRmdnYkdWbllXTjVYRzVSVzF3aVkyRjBZMmhjSWwwZ1BTQm1kVzVqZEdsdmJpQW9iMkpxWldOMExDQnlaV3BsWTNSbFpDa2dlMXh1SUNBZ0lISmxkSFZ5YmlCUktHOWlhbVZqZENrdWRHaGxiaWgyYjJsa0lEQXNJSEpsYW1WamRHVmtLVHRjYm4wN1hHNWNibEJ5YjIxcGMyVXVjSEp2ZEc5MGVYQmxMbVpoYVd3Z1BTQXZMeUJZV0ZnZ2JHVm5ZV041WEc1UWNtOXRhWE5sTG5CeWIzUnZkSGx3WlZ0Y0ltTmhkR05vWENKZElEMGdablZ1WTNScGIyNGdLSEpsYW1WamRHVmtLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIUm9hWE11ZEdobGJpaDJiMmxrSURBc0lISmxhbVZqZEdWa0tUdGNibjA3WEc1Y2JpOHFLbHh1SUNvZ1FYUjBZV05vWlhNZ1lTQnNhWE4wWlc1bGNpQjBhR0YwSUdOaGJpQnlaWE53YjI1a0lIUnZJSEJ5YjJkeVpYTnpJRzV2ZEdsbWFXTmhkR2x2Ym5NZ1puSnZiU0JoWEc0Z0tpQndjbTl0YVhObEozTWdiM0pwWjJsdVlYUnBibWNnWkdWbVpYSnlaV1F1SUZSb2FYTWdiR2x6ZEdWdVpYSWdjbVZqWldsMlpYTWdkR2hsSUdWNFlXTjBJR0Z5WjNWdFpXNTBjMXh1SUNvZ2NHRnpjMlZrSUhSdklHQmdaR1ZtWlhKeVpXUXVibTkwYVdaNVlHQXVYRzRnS2lCQWNHRnlZVzBnZTBGdWVTcDlJSEJ5YjIxcGMyVWdabTl5SUhOdmJXVjBhR2x1WjF4dUlDb2dRSEJoY21GdElIdEdkVzVqZEdsdmJuMGdZMkZzYkdKaFkyc2dkRzhnY21WalpXbDJaU0JoYm5rZ2NISnZaM0psYzNNZ2JtOTBhV1pwWTJGMGFXOXVjMXh1SUNvZ1FISmxkSFZ5Ym5NZ2RHaGxJR2RwZG1WdUlIQnliMjFwYzJVc0lIVnVZMmhoYm1kbFpGeHVJQ292WEc1UkxuQnliMmR5WlhOeklEMGdjSEp2WjNKbGMzTTdYRzVtZFc1amRHbHZiaUJ3Y205bmNtVnpjeWh2WW1wbFkzUXNJSEJ5YjJkeVpYTnpaV1FwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdVU2h2WW1wbFkzUXBMblJvWlc0b2RtOXBaQ0F3TENCMmIybGtJREFzSUhCeWIyZHlaWE56WldRcE8xeHVmVnh1WEc1UWNtOXRhWE5sTG5CeWIzUnZkSGx3WlM1d2NtOW5jbVZ6Y3lBOUlHWjFibU4wYVc5dUlDaHdjbTluY21WemMyVmtLU0I3WEc0Z0lDQWdjbVYwZFhKdUlIUm9hWE11ZEdobGJpaDJiMmxrSURBc0lIWnZhV1FnTUN3Z2NISnZaM0psYzNObFpDazdYRzU5TzF4dVhHNHZLaXBjYmlBcUlGQnliM1pwWkdWeklHRnVJRzl3Y0c5eWRIVnVhWFI1SUhSdklHOWljMlZ5ZG1VZ2RHaGxJSE5sZEhSc2FXNW5JRzltSUdFZ2NISnZiV2x6WlN4Y2JpQXFJSEpsWjJGeVpHeGxjM01nYjJZZ2QyaGxkR2hsY2lCMGFHVWdjSEp2YldselpTQnBjeUJtZFd4bWFXeHNaV1FnYjNJZ2NtVnFaV04wWldRdUlDQkdiM0ozWVhKa2MxeHVJQ29nZEdobElISmxjMjlzZFhScGIyNGdkRzhnZEdobElISmxkSFZ5Ym1Wa0lIQnliMjFwYzJVZ2QyaGxiaUIwYUdVZ1kyRnNiR0poWTJzZ2FYTWdaRzl1WlM1Y2JpQXFJRlJvWlNCallXeHNZbUZqYXlCallXNGdjbVYwZFhKdUlHRWdjSEp2YldselpTQjBieUJrWldabGNpQmpiMjF3YkdWMGFXOXVMbHh1SUNvZ1FIQmhjbUZ0SUh0QmJua3FmU0J3Y205dGFYTmxYRzRnS2lCQWNHRnlZVzBnZTBaMWJtTjBhVzl1ZlNCallXeHNZbUZqYXlCMGJ5QnZZbk5sY25abElIUm9aU0J5WlhOdmJIVjBhVzl1SUc5bUlIUm9aU0JuYVhabGJseHVJQ29nY0hKdmJXbHpaU3dnZEdGclpYTWdibThnWVhKbmRXMWxiblJ6TGx4dUlDb2dRSEpsZEhWeWJuTWdZU0J3Y205dGFYTmxJR1p2Y2lCMGFHVWdjbVZ6YjJ4MWRHbHZiaUJ2WmlCMGFHVWdaMmwyWlc0Z2NISnZiV2x6WlNCM2FHVnVYRzRnS2lCZ1lHWnBibUJnSUdseklHUnZibVV1WEc0Z0tpOWNibEV1Wm1sdUlEMGdMeThnV0ZoWUlHeGxaMkZqZVZ4dVVWdGNJbVpwYm1Gc2JIbGNJbDBnUFNCbWRXNWpkR2x2YmlBb2IySnFaV04wTENCallXeHNZbUZqYXlrZ2UxeHVJQ0FnSUhKbGRIVnliaUJSS0c5aWFtVmpkQ2xiWENKbWFXNWhiR3g1WENKZEtHTmhiR3hpWVdOcktUdGNibjA3WEc1Y2JsQnliMjFwYzJVdWNISnZkRzkwZVhCbExtWnBiaUE5SUM4dklGaFlXQ0JzWldkaFkzbGNibEJ5YjIxcGMyVXVjSEp2ZEc5MGVYQmxXMXdpWm1sdVlXeHNlVndpWFNBOUlHWjFibU4wYVc5dUlDaGpZV3hzWW1GamF5a2dlMXh1SUNBZ0lHTmhiR3hpWVdOcklEMGdVU2hqWVd4c1ltRmpheWs3WEc0Z0lDQWdjbVYwZFhKdUlIUm9hWE11ZEdobGJpaG1kVzVqZEdsdmJpQW9kbUZzZFdVcElIdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlHTmhiR3hpWVdOckxtWmpZV3hzS0NrdWRHaGxiaWhtZFc1amRHbHZiaUFvS1NCN1hHNGdJQ0FnSUNBZ0lDQWdJQ0J5WlhSMWNtNGdkbUZzZFdVN1hHNGdJQ0FnSUNBZ0lIMHBPMXh1SUNBZ0lIMHNJR1oxYm1OMGFXOXVJQ2h5WldGemIyNHBJSHRjYmlBZ0lDQWdJQ0FnTHk4Z1ZFOUVUeUJoZEhSbGJYQjBJSFJ2SUhKbFkzbGpiR1VnZEdobElISmxhbVZqZEdsdmJpQjNhWFJvSUZ3aWRHaHBjMXdpTGx4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWTJGc2JHSmhZMnN1Wm1OaGJHd29LUzUwYUdWdUtHWjFibU4wYVc5dUlDZ3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lIUm9jbTkzSUhKbFlYTnZianRjYmlBZ0lDQWdJQ0FnZlNrN1hHNGdJQ0FnZlNrN1hHNTlPMXh1WEc0dktpcGNiaUFxSUZSbGNtMXBibUYwWlhNZ1lTQmphR0ZwYmlCdlppQndjbTl0YVhObGN5d2dabTl5WTJsdVp5QnlaV3BsWTNScGIyNXpJSFJ2SUdKbFhHNGdLaUIwYUhKdmQyNGdZWE1nWlhoalpYQjBhVzl1Y3k1Y2JpQXFJRUJ3WVhKaGJTQjdRVzU1S24wZ2NISnZiV2x6WlNCaGRDQjBhR1VnWlc1a0lHOW1JR0VnWTJoaGFXNGdiMllnY0hKdmJXbHpaWE5jYmlBcUlFQnlaWFIxY201eklHNXZkR2hwYm1kY2JpQXFMMXh1VVM1a2IyNWxJRDBnWm5WdVkzUnBiMjRnS0c5aWFtVmpkQ3dnWm5Wc1ptbHNiR1ZrTENCeVpXcGxZM1JsWkN3Z2NISnZaM0psYzNNcElIdGNiaUFnSUNCeVpYUjFjbTRnVVNodlltcGxZM1FwTG1SdmJtVW9ablZzWm1sc2JHVmtMQ0J5WldwbFkzUmxaQ3dnY0hKdlozSmxjM01wTzF4dWZUdGNibHh1VUhKdmJXbHpaUzV3Y205MGIzUjVjR1V1Wkc5dVpTQTlJR1oxYm1OMGFXOXVJQ2htZFd4bWFXeHNaV1FzSUhKbGFtVmpkR1ZrTENCd2NtOW5jbVZ6Y3lrZ2UxeHVJQ0FnSUhaaGNpQnZibFZ1YUdGdVpHeGxaRVZ5Y205eUlEMGdablZ1WTNScGIyNGdLR1Z5Y205eUtTQjdYRzRnSUNBZ0lDQWdJQzh2SUdadmNuZGhjbVFnZEc4Z1lTQm1kWFIxY21VZ2RIVnliaUJ6YnlCMGFHRjBJR0JnZDJobGJtQmdYRzRnSUNBZ0lDQWdJQzh2SUdSdlpYTWdibTkwSUdOaGRHTm9JR2wwSUdGdVpDQjBkWEp1SUdsMElHbHVkRzhnWVNCeVpXcGxZM1JwYjI0dVhHNGdJQ0FnSUNBZ0lGRXVibVY0ZEZScFkyc29ablZ1WTNScGIyNGdLQ2tnZTF4dUlDQWdJQ0FnSUNBZ0lDQWdiV0ZyWlZOMFlXTnJWSEpoWTJWTWIyNW5LR1Z5Y205eUxDQndjbTl0YVhObEtUdGNiaUFnSUNBZ0lDQWdJQ0FnSUdsbUlDaFJMbTl1WlhKeWIzSXBJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lDQWdJQ0JSTG05dVpYSnliM0lvWlhKeWIzSXBPMXh1SUNBZ0lDQWdJQ0FnSUNBZ2ZTQmxiSE5sSUh0Y2JpQWdJQ0FnSUNBZ0lDQWdJQ0FnSUNCMGFISnZkeUJsY25KdmNqdGNiaUFnSUNBZ0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ2ZTazdYRzRnSUNBZ2ZUdGNibHh1SUNBZ0lDOHZJRUYyYjJsa0lIVnVibVZqWlhOellYSjVJR0J1WlhoMFZHbGphMkJwYm1jZ2RtbGhJR0Z1SUhWdWJtVmpaWE56WVhKNUlHQjNhR1Z1WUM1Y2JpQWdJQ0IyWVhJZ2NISnZiV2x6WlNBOUlHWjFiR1pwYkd4bFpDQjhmQ0J5WldwbFkzUmxaQ0I4ZkNCd2NtOW5jbVZ6Y3lBL1hHNGdJQ0FnSUNBZ0lIUm9hWE11ZEdobGJpaG1kV3htYVd4c1pXUXNJSEpsYW1WamRHVmtMQ0J3Y205bmNtVnpjeWtnT2x4dUlDQWdJQ0FnSUNCMGFHbHpPMXh1WEc0Z0lDQWdhV1lnS0hSNWNHVnZaaUJ3Y205alpYTnpJRDA5UFNCY0ltOWlhbVZqZEZ3aUlDWW1JSEJ5YjJObGMzTWdKaVlnY0hKdlkyVnpjeTVrYjIxaGFXNHBJSHRjYmlBZ0lDQWdJQ0FnYjI1VmJtaGhibVJzWldSRmNuSnZjaUE5SUhCeWIyTmxjM011Wkc5dFlXbHVMbUpwYm1Rb2IyNVZibWhoYm1Sc1pXUkZjbkp2Y2lrN1hHNGdJQ0FnZlZ4dVhHNGdJQ0FnY0hKdmJXbHpaUzUwYUdWdUtIWnZhV1FnTUN3Z2IyNVZibWhoYm1Sc1pXUkZjbkp2Y2lrN1hHNTlPMXh1WEc0dktpcGNiaUFxSUVOaGRYTmxjeUJoSUhCeWIyMXBjMlVnZEc4Z1ltVWdjbVZxWldOMFpXUWdhV1lnYVhRZ1pHOWxjeUJ1YjNRZ1oyVjBJR1oxYkdacGJHeGxaQ0JpWldadmNtVmNiaUFxSUhOdmJXVWdiV2xzYkdselpXTnZibVJ6SUhScGJXVWdiM1YwTGx4dUlDb2dRSEJoY21GdElIdEJibmtxZlNCd2NtOXRhWE5sWEc0Z0tpQkFjR0Z5WVcwZ2UwNTFiV0psY24wZ2JXbHNiR2x6WldOdmJtUnpJSFJwYldWdmRYUmNiaUFxSUVCd1lYSmhiU0I3UVc1NUtuMGdZM1Z6ZEc5dElHVnljbTl5SUcxbGMzTmhaMlVnYjNJZ1JYSnliM0lnYjJKcVpXTjBJQ2h2Y0hScGIyNWhiQ2xjYmlBcUlFQnlaWFIxY201eklHRWdjSEp2YldselpTQm1iM0lnZEdobElISmxjMjlzZFhScGIyNGdiMllnZEdobElHZHBkbVZ1SUhCeWIyMXBjMlVnYVdZZ2FYUWdhWE5jYmlBcUlHWjFiR1pwYkd4bFpDQmlaV1p2Y21VZ2RHaGxJSFJwYldWdmRYUXNJRzkwYUdWeWQybHpaU0J5WldwbFkzUmxaQzVjYmlBcUwxeHVVUzUwYVcxbGIzVjBJRDBnWm5WdVkzUnBiMjRnS0c5aWFtVmpkQ3dnYlhNc0lHVnljbTl5S1NCN1hHNGdJQ0FnY21WMGRYSnVJRkVvYjJKcVpXTjBLUzUwYVcxbGIzVjBLRzF6TENCbGNuSnZjaWs3WEc1OU8xeHVYRzVRY205dGFYTmxMbkJ5YjNSdmRIbHdaUzUwYVcxbGIzVjBJRDBnWm5WdVkzUnBiMjRnS0cxekxDQmxjbkp2Y2lrZ2UxeHVJQ0FnSUhaaGNpQmtaV1psY25KbFpDQTlJR1JsWm1WeUtDazdYRzRnSUNBZ2RtRnlJSFJwYldWdmRYUkpaQ0E5SUhObGRGUnBiV1Z2ZFhRb1puVnVZM1JwYjI0Z0tDa2dlMXh1SUNBZ0lDQWdJQ0JwWmlBb0lXVnljbTl5SUh4OElGd2ljM1J5YVc1blhDSWdQVDA5SUhSNWNHVnZaaUJsY25KdmNpa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ1pYSnliM0lnUFNCdVpYY2dSWEp5YjNJb1pYSnliM0lnZkh3Z1hDSlVhVzFsWkNCdmRYUWdZV1owWlhJZ1hDSWdLeUJ0Y3lBcklGd2lJRzF6WENJcE8xeHVJQ0FnSUNBZ0lDQWdJQ0FnWlhKeWIzSXVZMjlrWlNBOUlGd2lSVlJKVFVWRVQxVlVYQ0k3WEc0Z0lDQWdJQ0FnSUgxY2JpQWdJQ0FnSUNBZ1pHVm1aWEp5WldRdWNtVnFaV04wS0dWeWNtOXlLVHRjYmlBZ0lDQjlMQ0J0Y3lrN1hHNWNiaUFnSUNCMGFHbHpMblJvWlc0b1puVnVZM1JwYjI0Z0tIWmhiSFZsS1NCN1hHNGdJQ0FnSUNBZ0lHTnNaV0Z5VkdsdFpXOTFkQ2gwYVcxbGIzVjBTV1FwTzF4dUlDQWdJQ0FnSUNCa1pXWmxjbkpsWkM1eVpYTnZiSFpsS0haaGJIVmxLVHRjYmlBZ0lDQjlMQ0JtZFc1amRHbHZiaUFvWlhoalpYQjBhVzl1S1NCN1hHNGdJQ0FnSUNBZ0lHTnNaV0Z5VkdsdFpXOTFkQ2gwYVcxbGIzVjBTV1FwTzF4dUlDQWdJQ0FnSUNCa1pXWmxjbkpsWkM1eVpXcGxZM1FvWlhoalpYQjBhVzl1S1R0Y2JpQWdJQ0I5TENCa1pXWmxjbkpsWkM1dWIzUnBabmtwTzF4dVhHNGdJQ0FnY21WMGRYSnVJR1JsWm1WeWNtVmtMbkJ5YjIxcGMyVTdYRzU5TzF4dVhHNHZLaXBjYmlBcUlGSmxkSFZ5Ym5NZ1lTQndjbTl0YVhObElHWnZjaUIwYUdVZ1oybDJaVzRnZG1Gc2RXVWdLRzl5SUhCeWIyMXBjMlZrSUhaaGJIVmxLU3dnYzI5dFpWeHVJQ29nYldsc2JHbHpaV052Ym1SeklHRm1kR1Z5SUdsMElISmxjMjlzZG1Wa0xpQlFZWE56WlhNZ2NtVnFaV04wYVc5dWN5QnBiVzFsWkdsaGRHVnNlUzVjYmlBcUlFQndZWEpoYlNCN1FXNTVLbjBnY0hKdmJXbHpaVnh1SUNvZ1FIQmhjbUZ0SUh0T2RXMWlaWEo5SUcxcGJHeHBjMlZqYjI1a2MxeHVJQ29nUUhKbGRIVnlibk1nWVNCd2NtOXRhWE5sSUdadmNpQjBhR1VnY21WemIyeDFkR2x2YmlCdlppQjBhR1VnWjJsMlpXNGdjSEp2YldselpTQmhablJsY2lCdGFXeHNhWE5sWTI5dVpITmNiaUFxSUhScGJXVWdhR0Z6SUdWc1lYQnpaV1FnYzJsdVkyVWdkR2hsSUhKbGMyOXNkWFJwYjI0Z2IyWWdkR2hsSUdkcGRtVnVJSEJ5YjIxcGMyVXVYRzRnS2lCSlppQjBhR1VnWjJsMlpXNGdjSEp2YldselpTQnlaV3BsWTNSekxDQjBhR0YwSUdseklIQmhjM05sWkNCcGJXMWxaR2xoZEdWc2VTNWNiaUFxTDF4dVVTNWtaV3hoZVNBOUlHWjFibU4wYVc5dUlDaHZZbXBsWTNRc0lIUnBiV1Z2ZFhRcElIdGNiaUFnSUNCcFppQW9kR2x0Wlc5MWRDQTlQVDBnZG05cFpDQXdLU0I3WEc0Z0lDQWdJQ0FnSUhScGJXVnZkWFFnUFNCdlltcGxZM1E3WEc0Z0lDQWdJQ0FnSUc5aWFtVmpkQ0E5SUhadmFXUWdNRHRjYmlBZ0lDQjlYRzRnSUNBZ2NtVjBkWEp1SUZFb2IySnFaV04wS1M1a1pXeGhlU2gwYVcxbGIzVjBLVHRjYm4wN1hHNWNibEJ5YjIxcGMyVXVjSEp2ZEc5MGVYQmxMbVJsYkdGNUlEMGdablZ1WTNScGIyNGdLSFJwYldWdmRYUXBJSHRjYmlBZ0lDQnlaWFIxY200Z2RHaHBjeTUwYUdWdUtHWjFibU4wYVc5dUlDaDJZV3gxWlNrZ2UxeHVJQ0FnSUNBZ0lDQjJZWElnWkdWbVpYSnlaV1FnUFNCa1pXWmxjaWdwTzF4dUlDQWdJQ0FnSUNCelpYUlVhVzFsYjNWMEtHWjFibU4wYVc5dUlDZ3BJSHRjYmlBZ0lDQWdJQ0FnSUNBZ0lHUmxabVZ5Y21Wa0xuSmxjMjlzZG1Vb2RtRnNkV1VwTzF4dUlDQWdJQ0FnSUNCOUxDQjBhVzFsYjNWMEtUdGNiaUFnSUNBZ0lDQWdjbVYwZFhKdUlHUmxabVZ5Y21Wa0xuQnliMjFwYzJVN1hHNGdJQ0FnZlNrN1hHNTlPMXh1WEc0dktpcGNiaUFxSUZCaGMzTmxjeUJoSUdOdmJuUnBiblZoZEdsdmJpQjBieUJoSUU1dlpHVWdablZ1WTNScGIyNHNJSGRvYVdOb0lHbHpJR05oYkd4bFpDQjNhWFJvSUhSb1pTQm5hWFpsYmx4dUlDb2dZWEpuZFcxbGJuUnpJSEJ5YjNacFpHVmtJR0Z6SUdGdUlHRnljbUY1TENCaGJtUWdjbVYwZFhKdWN5QmhJSEJ5YjIxcGMyVXVYRzRnS2x4dUlDb2dJQ0FnSUNCUkxtNW1ZWEJ3Ykhrb1JsTXVjbVZoWkVacGJHVXNJRnRmWDJacGJHVnVZVzFsWFNsY2JpQXFJQ0FnSUNBZ0xuUm9aVzRvWm5WdVkzUnBiMjRnS0dOdmJuUmxiblFwSUh0Y2JpQXFJQ0FnSUNBZ2ZTbGNiaUFxWEc0Z0tpOWNibEV1Ym1aaGNIQnNlU0E5SUdaMWJtTjBhVzl1SUNoallXeHNZbUZqYXl3Z1lYSm5jeWtnZTF4dUlDQWdJSEpsZEhWeWJpQlJLR05oYkd4aVlXTnJLUzV1Wm1Gd2NHeDVLR0Z5WjNNcE8xeHVmVHRjYmx4dVVISnZiV2x6WlM1d2NtOTBiM1I1Y0dVdWJtWmhjSEJzZVNBOUlHWjFibU4wYVc5dUlDaGhjbWR6S1NCN1hHNGdJQ0FnZG1GeUlHUmxabVZ5Y21Wa0lEMGdaR1ZtWlhJb0tUdGNiaUFnSUNCMllYSWdibTlrWlVGeVozTWdQU0JoY25KaGVWOXpiR2xqWlNoaGNtZHpLVHRjYmlBZ0lDQnViMlJsUVhKbmN5NXdkWE5vS0dSbFptVnljbVZrTG0xaGEyVk9iMlJsVW1WemIyeDJaWElvS1NrN1hHNGdJQ0FnZEdocGN5NW1ZWEJ3Ykhrb2JtOWtaVUZ5WjNNcExtWmhhV3dvWkdWbVpYSnlaV1F1Y21WcVpXTjBLVHRjYmlBZ0lDQnlaWFIxY200Z1pHVm1aWEp5WldRdWNISnZiV2x6WlR0Y2JuMDdYRzVjYmk4cUtseHVJQ29nVUdGemMyVnpJR0VnWTI5dWRHbHVkV0YwYVc5dUlIUnZJR0VnVG05a1pTQm1kVzVqZEdsdmJpd2dkMmhwWTJnZ2FYTWdZMkZzYkdWa0lIZHBkR2dnZEdobElHZHBkbVZ1WEc0Z0tpQmhjbWQxYldWdWRITWdjSEp2ZG1sa1pXUWdhVzVrYVhacFpIVmhiR3g1TENCaGJtUWdjbVYwZFhKdWN5QmhJSEJ5YjIxcGMyVXVYRzRnS2lCQVpYaGhiWEJzWlZ4dUlDb2dVUzV1Wm1OaGJHd29SbE11Y21WaFpFWnBiR1VzSUY5ZlptbHNaVzVoYldVcFhHNGdLaUF1ZEdobGJpaG1kVzVqZEdsdmJpQW9ZMjl1ZEdWdWRDa2dlMXh1SUNvZ2ZTbGNiaUFxWEc0Z0tpOWNibEV1Ym1aallXeHNJRDBnWm5WdVkzUnBiMjRnS0dOaGJHeGlZV05ySUM4cUxpNHVZWEpuY3lvdktTQjdYRzRnSUNBZ2RtRnlJR0Z5WjNNZ1BTQmhjbkpoZVY5emJHbGpaU2hoY21kMWJXVnVkSE1zSURFcE8xeHVJQ0FnSUhKbGRIVnliaUJSS0dOaGJHeGlZV05yS1M1dVptRndjR3g1S0dGeVozTXBPMXh1ZlR0Y2JseHVVSEp2YldselpTNXdjbTkwYjNSNWNHVXVibVpqWVd4c0lEMGdablZ1WTNScGIyNGdLQzhxTGk0dVlYSm5jeW92S1NCN1hHNGdJQ0FnZG1GeUlHNXZaR1ZCY21keklEMGdZWEp5WVhsZmMyeHBZMlVvWVhKbmRXMWxiblJ6S1R0Y2JpQWdJQ0IyWVhJZ1pHVm1aWEp5WldRZ1BTQmtaV1psY2lncE8xeHVJQ0FnSUc1dlpHVkJjbWR6TG5CMWMyZ29aR1ZtWlhKeVpXUXViV0ZyWlU1dlpHVlNaWE52YkhabGNpZ3BLVHRjYmlBZ0lDQjBhR2x6TG1aaGNIQnNlU2h1YjJSbFFYSm5jeWt1Wm1GcGJDaGtaV1psY25KbFpDNXlaV3BsWTNRcE8xeHVJQ0FnSUhKbGRIVnliaUJrWldabGNuSmxaQzV3Y205dGFYTmxPMXh1ZlR0Y2JseHVMeW9xWEc0Z0tpQlhjbUZ3Y3lCaElFNXZaR1ZLVXlCamIyNTBhVzUxWVhScGIyNGdjR0Z6YzJsdVp5Qm1kVzVqZEdsdmJpQmhibVFnY21WMGRYSnVjeUJoYmlCbGNYVnBkbUZzWlc1MFhHNGdLaUIyWlhKemFXOXVJSFJvWVhRZ2NtVjBkWEp1Y3lCaElIQnliMjFwYzJVdVhHNGdLaUJBWlhoaGJYQnNaVnh1SUNvZ1VTNXVabUpwYm1Rb1JsTXVjbVZoWkVacGJHVXNJRjlmWm1sc1pXNWhiV1VwS0Z3aWRYUm1MVGhjSWlsY2JpQXFJQzUwYUdWdUtHTnZibk52YkdVdWJHOW5LVnh1SUNvZ0xtUnZibVVvS1Z4dUlDb3ZYRzVSTG01bVltbHVaQ0E5WEc1UkxtUmxibTlrWldsbWVTQTlJR1oxYm1OMGFXOXVJQ2hqWVd4c1ltRmpheUF2S2k0dUxtRnlaM01xTHlrZ2UxeHVJQ0FnSUhaaGNpQmlZWE5sUVhKbmN5QTlJR0Z5Y21GNVgzTnNhV05sS0dGeVozVnRaVzUwY3l3Z01TazdYRzRnSUNBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1SUNncElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUc1dlpHVkJjbWR6SUQwZ1ltRnpaVUZ5WjNNdVkyOXVZMkYwS0dGeWNtRjVYM05zYVdObEtHRnlaM1Z0Wlc1MGN5a3BPMXh1SUNBZ0lDQWdJQ0IyWVhJZ1pHVm1aWEp5WldRZ1BTQmtaV1psY2lncE8xeHVJQ0FnSUNBZ0lDQnViMlJsUVhKbmN5NXdkWE5vS0dSbFptVnljbVZrTG0xaGEyVk9iMlJsVW1WemIyeDJaWElvS1NrN1hHNGdJQ0FnSUNBZ0lGRW9ZMkZzYkdKaFkyc3BMbVpoY0hCc2VTaHViMlJsUVhKbmN5a3VabUZwYkNoa1pXWmxjbkpsWkM1eVpXcGxZM1FwTzF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWkdWbVpYSnlaV1F1Y0hKdmJXbHpaVHRjYmlBZ0lDQjlPMXh1ZlR0Y2JseHVVSEp2YldselpTNXdjbTkwYjNSNWNHVXVibVppYVc1a0lEMWNibEJ5YjIxcGMyVXVjSEp2ZEc5MGVYQmxMbVJsYm05a1pXbG1lU0E5SUdaMWJtTjBhVzl1SUNndktpNHVMbUZ5WjNNcUx5a2dlMXh1SUNBZ0lIWmhjaUJoY21keklEMGdZWEp5WVhsZmMyeHBZMlVvWVhKbmRXMWxiblJ6S1R0Y2JpQWdJQ0JoY21kekxuVnVjMmhwWm5Rb2RHaHBjeWs3WEc0Z0lDQWdjbVYwZFhKdUlGRXVaR1Z1YjJSbGFXWjVMbUZ3Y0d4NUtIWnZhV1FnTUN3Z1lYSm5jeWs3WEc1OU8xeHVYRzVSTG01aWFXNWtJRDBnWm5WdVkzUnBiMjRnS0dOaGJHeGlZV05yTENCMGFHbHpjQ0F2S2k0dUxtRnlaM01xTHlrZ2UxeHVJQ0FnSUhaaGNpQmlZWE5sUVhKbmN5QTlJR0Z5Y21GNVgzTnNhV05sS0dGeVozVnRaVzUwY3l3Z01pazdYRzRnSUNBZ2NtVjBkWEp1SUdaMWJtTjBhVzl1SUNncElIdGNiaUFnSUNBZ0lDQWdkbUZ5SUc1dlpHVkJjbWR6SUQwZ1ltRnpaVUZ5WjNNdVkyOXVZMkYwS0dGeWNtRjVYM05zYVdObEtHRnlaM1Z0Wlc1MGN5a3BPMXh1SUNBZ0lDQWdJQ0IyWVhJZ1pHVm1aWEp5WldRZ1BTQmtaV1psY2lncE8xeHVJQ0FnSUNBZ0lDQnViMlJsUVhKbmN5NXdkWE5vS0dSbFptVnljbVZrTG0xaGEyVk9iMlJsVW1WemIyeDJaWElvS1NrN1hHNGdJQ0FnSUNBZ0lHWjFibU4wYVc5dUlHSnZkVzVrS0NrZ2UxeHVJQ0FnSUNBZ0lDQWdJQ0FnY21WMGRYSnVJR05oYkd4aVlXTnJMbUZ3Y0d4NUtIUm9hWE53TENCaGNtZDFiV1Z1ZEhNcE8xeHVJQ0FnSUNBZ0lDQjlYRzRnSUNBZ0lDQWdJRkVvWW05MWJtUXBMbVpoY0hCc2VTaHViMlJsUVhKbmN5a3VabUZwYkNoa1pXWmxjbkpsWkM1eVpXcGxZM1FwTzF4dUlDQWdJQ0FnSUNCeVpYUjFjbTRnWkdWbVpYSnlaV1F1Y0hKdmJXbHpaVHRjYmlBZ0lDQjlPMXh1ZlR0Y2JseHVVSEp2YldselpTNXdjbTkwYjNSNWNHVXVibUpwYm1RZ1BTQm1kVzVqZEdsdmJpQW9MeXAwYUdsemNDd2dMaTR1WVhKbmN5b3ZLU0I3WEc0Z0lDQWdkbUZ5SUdGeVozTWdQU0JoY25KaGVWOXpiR2xqWlNoaGNtZDFiV1Z1ZEhNc0lEQXBPMXh1SUNBZ0lHRnlaM011ZFc1emFHbG1kQ2gwYUdsektUdGNiaUFnSUNCeVpYUjFjbTRnVVM1dVltbHVaQzVoY0hCc2VTaDJiMmxrSURBc0lHRnlaM01wTzF4dWZUdGNibHh1THlvcVhHNGdLaUJEWVd4c2N5QmhJRzFsZEdodlpDQnZaaUJoSUU1dlpHVXRjM1I1YkdVZ2IySnFaV04wSUhSb1lYUWdZV05qWlhCMGN5QmhJRTV2WkdVdGMzUjViR1ZjYmlBcUlHTmhiR3hpWVdOcklIZHBkR2dnWVNCbmFYWmxiaUJoY25KaGVTQnZaaUJoY21kMWJXVnVkSE1zSUhCc2RYTWdZU0J3Y205MmFXUmxaQ0JqWVd4c1ltRmpheTVjYmlBcUlFQndZWEpoYlNCdlltcGxZM1FnWVc0Z2IySnFaV04wSUhSb1lYUWdhR0Z6SUhSb1pTQnVZVzFsWkNCdFpYUm9iMlJjYmlBcUlFQndZWEpoYlNCN1UzUnlhVzVuZlNCdVlXMWxJRzVoYldVZ2IyWWdkR2hsSUcxbGRHaHZaQ0J2WmlCdlltcGxZM1JjYmlBcUlFQndZWEpoYlNCN1FYSnlZWGw5SUdGeVozTWdZWEpuZFcxbGJuUnpJSFJ2SUhCaGMzTWdkRzhnZEdobElHMWxkR2h2WkRzZ2RHaGxJR05oYkd4aVlXTnJYRzRnS2lCM2FXeHNJR0psSUhCeWIzWnBaR1ZrSUdKNUlGRWdZVzVrSUdGd2NHVnVaR1ZrSUhSdklIUm9aWE5sSUdGeVozVnRaVzUwY3k1Y2JpQXFJRUJ5WlhSMWNtNXpJR0VnY0hKdmJXbHpaU0JtYjNJZ2RHaGxJSFpoYkhWbElHOXlJR1Z5Y205eVhHNGdLaTljYmxFdWJtMWhjSEJzZVNBOUlDOHZJRmhZV0NCQmN5QndjbTl3YjNObFpDQmllU0JjSWxKbFpITmhibVJ5YjF3aVhHNVJMbTV3YjNOMElEMGdablZ1WTNScGIyNGdLRzlpYW1WamRDd2dibUZ0WlN3Z1lYSm5jeWtnZTF4dUlDQWdJSEpsZEhWeWJpQlJLRzlpYW1WamRDa3VibkJ2YzNRb2JtRnRaU3dnWVhKbmN5azdYRzU5TzF4dVhHNVFjbTl0YVhObExuQnliM1J2ZEhsd1pTNXViV0Z3Y0d4NUlEMGdMeThnV0ZoWUlFRnpJSEJ5YjNCdmMyVmtJR0o1SUZ3aVVtVmtjMkZ1WkhKdlhDSmNibEJ5YjIxcGMyVXVjSEp2ZEc5MGVYQmxMbTV3YjNOMElEMGdablZ1WTNScGIyNGdLRzVoYldVc0lHRnlaM01wSUh0Y2JpQWdJQ0IyWVhJZ2JtOWtaVUZ5WjNNZ1BTQmhjbkpoZVY5emJHbGpaU2hoY21keklIeDhJRnRkS1R0Y2JpQWdJQ0IyWVhJZ1pHVm1aWEp5WldRZ1BTQmtaV1psY2lncE8xeHVJQ0FnSUc1dlpHVkJjbWR6TG5CMWMyZ29aR1ZtWlhKeVpXUXViV0ZyWlU1dlpHVlNaWE52YkhabGNpZ3BLVHRjYmlBZ0lDQjBhR2x6TG1ScGMzQmhkR05vS0Z3aWNHOXpkRndpTENCYmJtRnRaU3dnYm05a1pVRnlaM05kS1M1bVlXbHNLR1JsWm1WeWNtVmtMbkpsYW1WamRDazdYRzRnSUNBZ2NtVjBkWEp1SUdSbFptVnljbVZrTG5CeWIyMXBjMlU3WEc1OU8xeHVYRzR2S2lwY2JpQXFJRU5oYkd4eklHRWdiV1YwYUc5a0lHOW1JR0VnVG05a1pTMXpkSGxzWlNCdlltcGxZM1FnZEdoaGRDQmhZMk5sY0hSeklHRWdUbTlrWlMxemRIbHNaVnh1SUNvZ1kyRnNiR0poWTJzc0lHWnZjbmRoY21ScGJtY2dkR2hsSUdkcGRtVnVJSFpoY21saFpHbGpJR0Z5WjNWdFpXNTBjeXdnY0d4MWN5QmhJSEJ5YjNacFpHVmtYRzRnS2lCallXeHNZbUZqYXlCaGNtZDFiV1Z1ZEM1Y2JpQXFJRUJ3WVhKaGJTQnZZbXBsWTNRZ1lXNGdiMkpxWldOMElIUm9ZWFFnYUdGeklIUm9aU0J1WVcxbFpDQnRaWFJvYjJSY2JpQXFJRUJ3WVhKaGJTQjdVM1J5YVc1bmZTQnVZVzFsSUc1aGJXVWdiMllnZEdobElHMWxkR2h2WkNCdlppQnZZbXBsWTNSY2JpQXFJRUJ3WVhKaGJTQXVMaTVoY21keklHRnlaM1Z0Wlc1MGN5QjBieUJ3WVhOeklIUnZJSFJvWlNCdFpYUm9iMlE3SUhSb1pTQmpZV3hzWW1GamF5QjNhV3hzWEc0Z0tpQmlaU0J3Y205MmFXUmxaQ0JpZVNCUklHRnVaQ0JoY0hCbGJtUmxaQ0IwYnlCMGFHVnpaU0JoY21kMWJXVnVkSE11WEc0Z0tpQkFjbVYwZFhKdWN5QmhJSEJ5YjIxcGMyVWdabTl5SUhSb1pTQjJZV3gxWlNCdmNpQmxjbkp2Y2x4dUlDb3ZYRzVSTG01elpXNWtJRDBnTHk4Z1dGaFlJRUpoYzJWa0lHOXVJRTFoY21zZ1RXbHNiR1Z5SjNNZ2NISnZjRzl6WldRZ1hDSnpaVzVrWENKY2JsRXVibTFqWVd4c0lEMGdMeThnV0ZoWUlFSmhjMlZrSUc5dUlGd2lVbVZrYzJGdVpISnZKM05jSWlCd2NtOXdiM05oYkZ4dVVTNXVhVzUyYjJ0bElEMGdablZ1WTNScGIyNGdLRzlpYW1WamRDd2dibUZ0WlNBdktpNHVMbUZ5WjNNcUx5a2dlMXh1SUNBZ0lIWmhjaUJ1YjJSbFFYSm5jeUE5SUdGeWNtRjVYM05zYVdObEtHRnlaM1Z0Wlc1MGN5d2dNaWs3WEc0Z0lDQWdkbUZ5SUdSbFptVnljbVZrSUQwZ1pHVm1aWElvS1R0Y2JpQWdJQ0J1YjJSbFFYSm5jeTV3ZFhOb0tHUmxabVZ5Y21Wa0xtMWhhMlZPYjJSbFVtVnpiMngyWlhJb0tTazdYRzRnSUNBZ1VTaHZZbXBsWTNRcExtUnBjM0JoZEdOb0tGd2ljRzl6ZEZ3aUxDQmJibUZ0WlN3Z2JtOWtaVUZ5WjNOZEtTNW1ZV2xzS0dSbFptVnljbVZrTG5KbGFtVmpkQ2s3WEc0Z0lDQWdjbVYwZFhKdUlHUmxabVZ5Y21Wa0xuQnliMjFwYzJVN1hHNTlPMXh1WEc1UWNtOXRhWE5sTG5CeWIzUnZkSGx3WlM1dWMyVnVaQ0E5SUM4dklGaFlXQ0JDWVhObFpDQnZiaUJOWVhKcklFMXBiR3hsY2lkeklIQnliM0J2YzJWa0lGd2ljMlZ1WkZ3aVhHNVFjbTl0YVhObExuQnliM1J2ZEhsd1pTNXViV05oYkd3Z1BTQXZMeUJZV0ZnZ1FtRnpaV1FnYjI0Z1hDSlNaV1J6WVc1a2NtOG5jMXdpSUhCeWIzQnZjMkZzWEc1UWNtOXRhWE5sTG5CeWIzUnZkSGx3WlM1dWFXNTJiMnRsSUQwZ1puVnVZM1JwYjI0Z0tHNWhiV1VnTHlvdUxpNWhjbWR6S2k4cElIdGNiaUFnSUNCMllYSWdibTlrWlVGeVozTWdQU0JoY25KaGVWOXpiR2xqWlNoaGNtZDFiV1Z1ZEhNc0lERXBPMXh1SUNBZ0lIWmhjaUJrWldabGNuSmxaQ0E5SUdSbFptVnlLQ2s3WEc0Z0lDQWdibTlrWlVGeVozTXVjSFZ6YUNoa1pXWmxjbkpsWkM1dFlXdGxUbTlrWlZKbGMyOXNkbVZ5S0NrcE8xeHVJQ0FnSUhSb2FYTXVaR2x6Y0dGMFkyZ29YQ0p3YjNOMFhDSXNJRnR1WVcxbExDQnViMlJsUVhKbmMxMHBMbVpoYVd3b1pHVm1aWEp5WldRdWNtVnFaV04wS1R0Y2JpQWdJQ0J5WlhSMWNtNGdaR1ZtWlhKeVpXUXVjSEp2YldselpUdGNibjA3WEc1Y2JpOHFLbHh1SUNvZ1NXWWdZU0JtZFc1amRHbHZiaUIzYjNWc1pDQnNhV3RsSUhSdklITjFjSEJ2Y25RZ1ltOTBhQ0JPYjJSbElHTnZiblJwYm5WaGRHbHZiaTF3WVhOemFXNW5MWE4wZVd4bElHRnVaRnh1SUNvZ2NISnZiV2x6WlMxeVpYUjFjbTVwYm1jdGMzUjViR1VzSUdsMElHTmhiaUJsYm1RZ2FYUnpJR2x1ZEdWeWJtRnNJSEJ5YjIxcGMyVWdZMmhoYVc0Z2QybDBhRnh1SUNvZ1lHNXZaR1ZwWm5rb2JtOWtaV0poWTJzcFlDd2dabTl5ZDJGeVpHbHVaeUIwYUdVZ2IzQjBhVzl1WVd3Z2JtOWtaV0poWTJzZ1lYSm5kVzFsYm5RdUlDQkpaaUIwYUdVZ2RYTmxjbHh1SUNvZ1pXeGxZM1J6SUhSdklIVnpaU0JoSUc1dlpHVmlZV05yTENCMGFHVWdjbVZ6ZFd4MElIZHBiR3dnWW1VZ2MyVnVkQ0IwYUdWeVpTNGdJRWxtSUhSb1pYa2daRzhnYm05MFhHNGdLaUJ3WVhOeklHRWdibTlrWldKaFkyc3NJSFJvWlhrZ2QybHNiQ0J5WldObGFYWmxJSFJvWlNCeVpYTjFiSFFnY0hKdmJXbHpaUzVjYmlBcUlFQndZWEpoYlNCdlltcGxZM1FnWVNCeVpYTjFiSFFnS0c5eUlHRWdjSEp2YldselpTQm1iM0lnWVNCeVpYTjFiSFFwWEc0Z0tpQkFjR0Z5WVcwZ2UwWjFibU4wYVc5dWZTQnViMlJsWW1GamF5QmhJRTV2WkdVdWFuTXRjM1I1YkdVZ1kyRnNiR0poWTJ0Y2JpQXFJRUJ5WlhSMWNtNXpJR1ZwZEdobGNpQjBhR1VnY0hKdmJXbHpaU0J2Y2lCdWIzUm9hVzVuWEc0Z0tpOWNibEV1Ym05a1pXbG1lU0E5SUc1dlpHVnBabms3WEc1bWRXNWpkR2x2YmlCdWIyUmxhV1o1S0c5aWFtVmpkQ3dnYm05a1pXSmhZMnNwSUh0Y2JpQWdJQ0J5WlhSMWNtNGdVU2h2WW1wbFkzUXBMbTV2WkdWcFpua29ibTlrWldKaFkyc3BPMXh1ZlZ4dVhHNVFjbTl0YVhObExuQnliM1J2ZEhsd1pTNXViMlJsYVdaNUlEMGdablZ1WTNScGIyNGdLRzV2WkdWaVlXTnJLU0I3WEc0Z0lDQWdhV1lnS0c1dlpHVmlZV05yS1NCN1hHNGdJQ0FnSUNBZ0lIUm9hWE11ZEdobGJpaG1kVzVqZEdsdmJpQW9kbUZzZFdVcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUZFdWJtVjRkRlJwWTJzb1puVnVZM1JwYjI0Z0tDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzV2WkdWaVlXTnJLRzUxYkd3c0lIWmhiSFZsS1R0Y2JpQWdJQ0FnSUNBZ0lDQWdJSDBwTzF4dUlDQWdJQ0FnSUNCOUxDQm1kVzVqZEdsdmJpQW9aWEp5YjNJcElIdGNiaUFnSUNBZ0lDQWdJQ0FnSUZFdWJtVjRkRlJwWTJzb1puVnVZM1JwYjI0Z0tDa2dlMXh1SUNBZ0lDQWdJQ0FnSUNBZ0lDQWdJRzV2WkdWaVlXTnJLR1Z5Y205eUtUdGNiaUFnSUNBZ0lDQWdJQ0FnSUgwcE8xeHVJQ0FnSUNBZ0lDQjlLVHRjYmlBZ0lDQjlJR1ZzYzJVZ2UxeHVJQ0FnSUNBZ0lDQnlaWFIxY200Z2RHaHBjenRjYmlBZ0lDQjlYRzU5TzF4dVhHNVJMbTV2UTI5dVpteHBZM1FnUFNCbWRXNWpkR2x2YmlncElIdGNiaUFnSUNCMGFISnZkeUJ1WlhjZ1JYSnliM0lvWENKUkxtNXZRMjl1Wm14cFkzUWdiMjVzZVNCM2IzSnJjeUIzYUdWdUlGRWdhWE1nZFhObFpDQmhjeUJoSUdkc2IySmhiRndpS1R0Y2JuMDdYRzVjYmk4dklFRnNiQ0JqYjJSbElHSmxabTl5WlNCMGFHbHpJSEJ2YVc1MElIZHBiR3dnWW1VZ1ptbHNkR1Z5WldRZ1puSnZiU0J6ZEdGamF5QjBjbUZqWlhNdVhHNTJZWElnY1VWdVpHbHVaMHhwYm1VZ1BTQmpZWEIwZFhKbFRHbHVaU2dwTzF4dVhHNXlaWFIxY200Z1VUdGNibHh1ZlNrN1hHNGlYWDA9IiwiLyoqXG4gKiBSb290IHJlZmVyZW5jZSBmb3IgaWZyYW1lcy5cbiAqL1xuXG52YXIgcm9vdDtcbmlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykgeyAvLyBCcm93c2VyIHdpbmRvd1xuICByb290ID0gd2luZG93O1xufSBlbHNlIGlmICh0eXBlb2Ygc2VsZiAhPT0gJ3VuZGVmaW5lZCcpIHsgLy8gV2ViIFdvcmtlclxuICByb290ID0gc2VsZjtcbn0gZWxzZSB7IC8vIE90aGVyIGVudmlyb25tZW50c1xuICBjb25zb2xlLndhcm4oXCJVc2luZyBicm93c2VyLW9ubHkgdmVyc2lvbiBvZiBzdXBlcmFnZW50IGluIG5vbi1icm93c2VyIGVudmlyb25tZW50XCIpO1xuICByb290ID0gdGhpcztcbn1cblxudmFyIEVtaXR0ZXIgPSByZXF1aXJlKCdlbWl0dGVyJyk7XG52YXIgcmVxdWVzdEJhc2UgPSByZXF1aXJlKCcuL3JlcXVlc3QtYmFzZScpO1xudmFyIGlzT2JqZWN0ID0gcmVxdWlyZSgnLi9pcy1vYmplY3QnKTtcblxuLyoqXG4gKiBOb29wLlxuICovXG5cbmZ1bmN0aW9uIG5vb3AoKXt9O1xuXG4vKipcbiAqIEV4cG9zZSBgcmVxdWVzdGAuXG4gKi9cblxudmFyIHJlcXVlc3QgPSBtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vcmVxdWVzdCcpLmJpbmQobnVsbCwgUmVxdWVzdCk7XG5cbi8qKlxuICogRGV0ZXJtaW5lIFhIUi5cbiAqL1xuXG5yZXF1ZXN0LmdldFhIUiA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKHJvb3QuWE1MSHR0cFJlcXVlc3RcbiAgICAgICYmICghcm9vdC5sb2NhdGlvbiB8fCAnZmlsZTonICE9IHJvb3QubG9jYXRpb24ucHJvdG9jb2xcbiAgICAgICAgICB8fCAhcm9vdC5BY3RpdmVYT2JqZWN0KSkge1xuICAgIHJldHVybiBuZXcgWE1MSHR0cFJlcXVlc3Q7XG4gIH0gZWxzZSB7XG4gICAgdHJ5IHsgcmV0dXJuIG5ldyBBY3RpdmVYT2JqZWN0KCdNaWNyb3NvZnQuWE1MSFRUUCcpOyB9IGNhdGNoKGUpIHt9XG4gICAgdHJ5IHsgcmV0dXJuIG5ldyBBY3RpdmVYT2JqZWN0KCdNc3htbDIuWE1MSFRUUC42LjAnKTsgfSBjYXRjaChlKSB7fVxuICAgIHRyeSB7IHJldHVybiBuZXcgQWN0aXZlWE9iamVjdCgnTXN4bWwyLlhNTEhUVFAuMy4wJyk7IH0gY2F0Y2goZSkge31cbiAgICB0cnkgeyByZXR1cm4gbmV3IEFjdGl2ZVhPYmplY3QoJ01zeG1sMi5YTUxIVFRQJyk7IH0gY2F0Y2goZSkge31cbiAgfVxuICB0aHJvdyBFcnJvcihcIkJyb3dzZXItb25seSB2ZXJpc29uIG9mIHN1cGVyYWdlbnQgY291bGQgbm90IGZpbmQgWEhSXCIpO1xufTtcblxuLyoqXG4gKiBSZW1vdmVzIGxlYWRpbmcgYW5kIHRyYWlsaW5nIHdoaXRlc3BhY2UsIGFkZGVkIHRvIHN1cHBvcnQgSUUuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHNcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbnZhciB0cmltID0gJycudHJpbVxuICA/IGZ1bmN0aW9uKHMpIHsgcmV0dXJuIHMudHJpbSgpOyB9XG4gIDogZnVuY3Rpb24ocykgeyByZXR1cm4gcy5yZXBsYWNlKC8oXlxccyp8XFxzKiQpL2csICcnKTsgfTtcblxuLyoqXG4gKiBTZXJpYWxpemUgdGhlIGdpdmVuIGBvYmpgLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmpcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cbmZ1bmN0aW9uIHNlcmlhbGl6ZShvYmopIHtcbiAgaWYgKCFpc09iamVjdChvYmopKSByZXR1cm4gb2JqO1xuICB2YXIgcGFpcnMgPSBbXTtcbiAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgIHB1c2hFbmNvZGVkS2V5VmFsdWVQYWlyKHBhaXJzLCBrZXksIG9ialtrZXldKTtcbiAgfVxuICByZXR1cm4gcGFpcnMuam9pbignJicpO1xufVxuXG4vKipcbiAqIEhlbHBzICdzZXJpYWxpemUnIHdpdGggc2VyaWFsaXppbmcgYXJyYXlzLlxuICogTXV0YXRlcyB0aGUgcGFpcnMgYXJyYXkuXG4gKlxuICogQHBhcmFtIHtBcnJheX0gcGFpcnNcbiAqIEBwYXJhbSB7U3RyaW5nfSBrZXlcbiAqIEBwYXJhbSB7TWl4ZWR9IHZhbFxuICovXG5cbmZ1bmN0aW9uIHB1c2hFbmNvZGVkS2V5VmFsdWVQYWlyKHBhaXJzLCBrZXksIHZhbCkge1xuICBpZiAodmFsICE9IG51bGwpIHtcbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWwpKSB7XG4gICAgICB2YWwuZm9yRWFjaChmdW5jdGlvbih2KSB7XG4gICAgICAgIHB1c2hFbmNvZGVkS2V5VmFsdWVQYWlyKHBhaXJzLCBrZXksIHYpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChpc09iamVjdCh2YWwpKSB7XG4gICAgICBmb3IodmFyIHN1YmtleSBpbiB2YWwpIHtcbiAgICAgICAgcHVzaEVuY29kZWRLZXlWYWx1ZVBhaXIocGFpcnMsIGtleSArICdbJyArIHN1YmtleSArICddJywgdmFsW3N1YmtleV0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBwYWlycy5wdXNoKGVuY29kZVVSSUNvbXBvbmVudChrZXkpXG4gICAgICAgICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbCkpO1xuICAgIH1cbiAgfSBlbHNlIGlmICh2YWwgPT09IG51bGwpIHtcbiAgICBwYWlycy5wdXNoKGVuY29kZVVSSUNvbXBvbmVudChrZXkpKTtcbiAgfVxufVxuXG4vKipcbiAqIEV4cG9zZSBzZXJpYWxpemF0aW9uIG1ldGhvZC5cbiAqL1xuXG4gcmVxdWVzdC5zZXJpYWxpemVPYmplY3QgPSBzZXJpYWxpemU7XG5cbiAvKipcbiAgKiBQYXJzZSB0aGUgZ2l2ZW4geC13d3ctZm9ybS11cmxlbmNvZGVkIGBzdHJgLlxuICAqXG4gICogQHBhcmFtIHtTdHJpbmd9IHN0clxuICAqIEByZXR1cm4ge09iamVjdH1cbiAgKiBAYXBpIHByaXZhdGVcbiAgKi9cblxuZnVuY3Rpb24gcGFyc2VTdHJpbmcoc3RyKSB7XG4gIHZhciBvYmogPSB7fTtcbiAgdmFyIHBhaXJzID0gc3RyLnNwbGl0KCcmJyk7XG4gIHZhciBwYWlyO1xuICB2YXIgcG9zO1xuXG4gIGZvciAodmFyIGkgPSAwLCBsZW4gPSBwYWlycy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICAgIHBhaXIgPSBwYWlyc1tpXTtcbiAgICBwb3MgPSBwYWlyLmluZGV4T2YoJz0nKTtcbiAgICBpZiAocG9zID09IC0xKSB7XG4gICAgICBvYmpbZGVjb2RlVVJJQ29tcG9uZW50KHBhaXIpXSA9ICcnO1xuICAgIH0gZWxzZSB7XG4gICAgICBvYmpbZGVjb2RlVVJJQ29tcG9uZW50KHBhaXIuc2xpY2UoMCwgcG9zKSldID1cbiAgICAgICAgZGVjb2RlVVJJQ29tcG9uZW50KHBhaXIuc2xpY2UocG9zICsgMSkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBvYmo7XG59XG5cbi8qKlxuICogRXhwb3NlIHBhcnNlci5cbiAqL1xuXG5yZXF1ZXN0LnBhcnNlU3RyaW5nID0gcGFyc2VTdHJpbmc7XG5cbi8qKlxuICogRGVmYXVsdCBNSU1FIHR5cGUgbWFwLlxuICpcbiAqICAgICBzdXBlcmFnZW50LnR5cGVzLnhtbCA9ICdhcHBsaWNhdGlvbi94bWwnO1xuICpcbiAqL1xuXG5yZXF1ZXN0LnR5cGVzID0ge1xuICBodG1sOiAndGV4dC9odG1sJyxcbiAganNvbjogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICB4bWw6ICdhcHBsaWNhdGlvbi94bWwnLFxuICB1cmxlbmNvZGVkOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyxcbiAgJ2Zvcm0nOiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyxcbiAgJ2Zvcm0tZGF0YSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnXG59O1xuXG4vKipcbiAqIERlZmF1bHQgc2VyaWFsaXphdGlvbiBtYXAuXG4gKlxuICogICAgIHN1cGVyYWdlbnQuc2VyaWFsaXplWydhcHBsaWNhdGlvbi94bWwnXSA9IGZ1bmN0aW9uKG9iail7XG4gKiAgICAgICByZXR1cm4gJ2dlbmVyYXRlZCB4bWwgaGVyZSc7XG4gKiAgICAgfTtcbiAqXG4gKi9cblxuIHJlcXVlc3Quc2VyaWFsaXplID0ge1xuICAgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCc6IHNlcmlhbGl6ZSxcbiAgICdhcHBsaWNhdGlvbi9qc29uJzogSlNPTi5zdHJpbmdpZnlcbiB9O1xuXG4gLyoqXG4gICogRGVmYXVsdCBwYXJzZXJzLlxuICAqXG4gICogICAgIHN1cGVyYWdlbnQucGFyc2VbJ2FwcGxpY2F0aW9uL3htbCddID0gZnVuY3Rpb24oc3RyKXtcbiAgKiAgICAgICByZXR1cm4geyBvYmplY3QgcGFyc2VkIGZyb20gc3RyIH07XG4gICogICAgIH07XG4gICpcbiAgKi9cblxucmVxdWVzdC5wYXJzZSA9IHtcbiAgJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCc6IHBhcnNlU3RyaW5nLFxuICAnYXBwbGljYXRpb24vanNvbic6IEpTT04ucGFyc2Vcbn07XG5cbi8qKlxuICogUGFyc2UgdGhlIGdpdmVuIGhlYWRlciBgc3RyYCBpbnRvXG4gKiBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgbWFwcGVkIGZpZWxkcy5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyXG4gKiBAcmV0dXJuIHtPYmplY3R9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBwYXJzZUhlYWRlcihzdHIpIHtcbiAgdmFyIGxpbmVzID0gc3RyLnNwbGl0KC9cXHI/XFxuLyk7XG4gIHZhciBmaWVsZHMgPSB7fTtcbiAgdmFyIGluZGV4O1xuICB2YXIgbGluZTtcbiAgdmFyIGZpZWxkO1xuICB2YXIgdmFsO1xuXG4gIGxpbmVzLnBvcCgpOyAvLyB0cmFpbGluZyBDUkxGXG5cbiAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGxpbmVzLmxlbmd0aDsgaSA8IGxlbjsgKytpKSB7XG4gICAgbGluZSA9IGxpbmVzW2ldO1xuICAgIGluZGV4ID0gbGluZS5pbmRleE9mKCc6Jyk7XG4gICAgZmllbGQgPSBsaW5lLnNsaWNlKDAsIGluZGV4KS50b0xvd2VyQ2FzZSgpO1xuICAgIHZhbCA9IHRyaW0obGluZS5zbGljZShpbmRleCArIDEpKTtcbiAgICBmaWVsZHNbZmllbGRdID0gdmFsO1xuICB9XG5cbiAgcmV0dXJuIGZpZWxkcztcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBgbWltZWAgaXMganNvbiBvciBoYXMgK2pzb24gc3RydWN0dXJlZCBzeW50YXggc3VmZml4LlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBtaW1lXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gaXNKU09OKG1pbWUpIHtcbiAgcmV0dXJuIC9bXFwvK11qc29uXFxiLy50ZXN0KG1pbWUpO1xufVxuXG4vKipcbiAqIFJldHVybiB0aGUgbWltZSB0eXBlIGZvciB0aGUgZ2l2ZW4gYHN0cmAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHN0clxuICogQHJldHVybiB7U3RyaW5nfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gdHlwZShzdHIpe1xuICByZXR1cm4gc3RyLnNwbGl0KC8gKjsgKi8pLnNoaWZ0KCk7XG59O1xuXG4vKipcbiAqIFJldHVybiBoZWFkZXIgZmllbGQgcGFyYW1ldGVycy5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gc3RyXG4gKiBAcmV0dXJuIHtPYmplY3R9XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBwYXJhbXMoc3RyKXtcbiAgcmV0dXJuIHN0ci5zcGxpdCgvICo7ICovKS5yZWR1Y2UoZnVuY3Rpb24ob2JqLCBzdHIpe1xuICAgIHZhciBwYXJ0cyA9IHN0ci5zcGxpdCgvICo9ICovKSxcbiAgICAgICAga2V5ID0gcGFydHMuc2hpZnQoKSxcbiAgICAgICAgdmFsID0gcGFydHMuc2hpZnQoKTtcblxuICAgIGlmIChrZXkgJiYgdmFsKSBvYmpba2V5XSA9IHZhbDtcbiAgICByZXR1cm4gb2JqO1xuICB9LCB7fSk7XG59O1xuXG4vKipcbiAqIEluaXRpYWxpemUgYSBuZXcgYFJlc3BvbnNlYCB3aXRoIHRoZSBnaXZlbiBgeGhyYC5cbiAqXG4gKiAgLSBzZXQgZmxhZ3MgKC5vaywgLmVycm9yLCBldGMpXG4gKiAgLSBwYXJzZSBoZWFkZXJcbiAqXG4gKiBFeGFtcGxlczpcbiAqXG4gKiAgQWxpYXNpbmcgYHN1cGVyYWdlbnRgIGFzIGByZXF1ZXN0YCBpcyBuaWNlOlxuICpcbiAqICAgICAgcmVxdWVzdCA9IHN1cGVyYWdlbnQ7XG4gKlxuICogIFdlIGNhbiB1c2UgdGhlIHByb21pc2UtbGlrZSBBUEksIG9yIHBhc3MgY2FsbGJhY2tzOlxuICpcbiAqICAgICAgcmVxdWVzdC5nZXQoJy8nKS5lbmQoZnVuY3Rpb24ocmVzKXt9KTtcbiAqICAgICAgcmVxdWVzdC5nZXQoJy8nLCBmdW5jdGlvbihyZXMpe30pO1xuICpcbiAqICBTZW5kaW5nIGRhdGEgY2FuIGJlIGNoYWluZWQ6XG4gKlxuICogICAgICByZXF1ZXN0XG4gKiAgICAgICAgLnBvc3QoJy91c2VyJylcbiAqICAgICAgICAuc2VuZCh7IG5hbWU6ICd0aicgfSlcbiAqICAgICAgICAuZW5kKGZ1bmN0aW9uKHJlcyl7fSk7XG4gKlxuICogIE9yIHBhc3NlZCB0byBgLnNlbmQoKWA6XG4gKlxuICogICAgICByZXF1ZXN0XG4gKiAgICAgICAgLnBvc3QoJy91c2VyJylcbiAqICAgICAgICAuc2VuZCh7IG5hbWU6ICd0aicgfSwgZnVuY3Rpb24ocmVzKXt9KTtcbiAqXG4gKiAgT3IgcGFzc2VkIHRvIGAucG9zdCgpYDpcbiAqXG4gKiAgICAgIHJlcXVlc3RcbiAqICAgICAgICAucG9zdCgnL3VzZXInLCB7IG5hbWU6ICd0aicgfSlcbiAqICAgICAgICAuZW5kKGZ1bmN0aW9uKHJlcyl7fSk7XG4gKlxuICogT3IgZnVydGhlciByZWR1Y2VkIHRvIGEgc2luZ2xlIGNhbGwgZm9yIHNpbXBsZSBjYXNlczpcbiAqXG4gKiAgICAgIHJlcXVlc3RcbiAqICAgICAgICAucG9zdCgnL3VzZXInLCB7IG5hbWU6ICd0aicgfSwgZnVuY3Rpb24ocmVzKXt9KTtcbiAqXG4gKiBAcGFyYW0ge1hNTEhUVFBSZXF1ZXN0fSB4aHJcbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zXG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBSZXNwb25zZShyZXEsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gIHRoaXMucmVxID0gcmVxO1xuICB0aGlzLnhociA9IHRoaXMucmVxLnhocjtcbiAgLy8gcmVzcG9uc2VUZXh0IGlzIGFjY2Vzc2libGUgb25seSBpZiByZXNwb25zZVR5cGUgaXMgJycgb3IgJ3RleHQnIGFuZCBvbiBvbGRlciBicm93c2Vyc1xuICB0aGlzLnRleHQgPSAoKHRoaXMucmVxLm1ldGhvZCAhPSdIRUFEJyAmJiAodGhpcy54aHIucmVzcG9uc2VUeXBlID09PSAnJyB8fCB0aGlzLnhoci5yZXNwb25zZVR5cGUgPT09ICd0ZXh0JykpIHx8IHR5cGVvZiB0aGlzLnhoci5yZXNwb25zZVR5cGUgPT09ICd1bmRlZmluZWQnKVxuICAgICA/IHRoaXMueGhyLnJlc3BvbnNlVGV4dFxuICAgICA6IG51bGw7XG4gIHRoaXMuc3RhdHVzVGV4dCA9IHRoaXMucmVxLnhoci5zdGF0dXNUZXh0O1xuICB0aGlzLl9zZXRTdGF0dXNQcm9wZXJ0aWVzKHRoaXMueGhyLnN0YXR1cyk7XG4gIHRoaXMuaGVhZGVyID0gdGhpcy5oZWFkZXJzID0gcGFyc2VIZWFkZXIodGhpcy54aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkpO1xuICAvLyBnZXRBbGxSZXNwb25zZUhlYWRlcnMgc29tZXRpbWVzIGZhbHNlbHkgcmV0dXJucyBcIlwiIGZvciBDT1JTIHJlcXVlc3RzLCBidXRcbiAgLy8gZ2V0UmVzcG9uc2VIZWFkZXIgc3RpbGwgd29ya3MuIHNvIHdlIGdldCBjb250ZW50LXR5cGUgZXZlbiBpZiBnZXR0aW5nXG4gIC8vIG90aGVyIGhlYWRlcnMgZmFpbHMuXG4gIHRoaXMuaGVhZGVyWydjb250ZW50LXR5cGUnXSA9IHRoaXMueGhyLmdldFJlc3BvbnNlSGVhZGVyKCdjb250ZW50LXR5cGUnKTtcbiAgdGhpcy5fc2V0SGVhZGVyUHJvcGVydGllcyh0aGlzLmhlYWRlcik7XG4gIHRoaXMuYm9keSA9IHRoaXMucmVxLm1ldGhvZCAhPSAnSEVBRCdcbiAgICA/IHRoaXMuX3BhcnNlQm9keSh0aGlzLnRleHQgPyB0aGlzLnRleHQgOiB0aGlzLnhoci5yZXNwb25zZSlcbiAgICA6IG51bGw7XG59XG5cbi8qKlxuICogR2V0IGNhc2UtaW5zZW5zaXRpdmUgYGZpZWxkYCB2YWx1ZS5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZmllbGRcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVzcG9uc2UucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uKGZpZWxkKXtcbiAgcmV0dXJuIHRoaXMuaGVhZGVyW2ZpZWxkLnRvTG93ZXJDYXNlKCldO1xufTtcblxuLyoqXG4gKiBTZXQgaGVhZGVyIHJlbGF0ZWQgcHJvcGVydGllczpcbiAqXG4gKiAgIC0gYC50eXBlYCB0aGUgY29udGVudCB0eXBlIHdpdGhvdXQgcGFyYW1zXG4gKlxuICogQSByZXNwb25zZSBvZiBcIkNvbnRlbnQtVHlwZTogdGV4dC9wbGFpbjsgY2hhcnNldD11dGYtOFwiXG4gKiB3aWxsIHByb3ZpZGUgeW91IHdpdGggYSBgLnR5cGVgIG9mIFwidGV4dC9wbGFpblwiLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBoZWFkZXJcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cblJlc3BvbnNlLnByb3RvdHlwZS5fc2V0SGVhZGVyUHJvcGVydGllcyA9IGZ1bmN0aW9uKGhlYWRlcil7XG4gIC8vIGNvbnRlbnQtdHlwZVxuICB2YXIgY3QgPSB0aGlzLmhlYWRlclsnY29udGVudC10eXBlJ10gfHwgJyc7XG4gIHRoaXMudHlwZSA9IHR5cGUoY3QpO1xuXG4gIC8vIHBhcmFtc1xuICB2YXIgb2JqID0gcGFyYW1zKGN0KTtcbiAgZm9yICh2YXIga2V5IGluIG9iaikgdGhpc1trZXldID0gb2JqW2tleV07XG59O1xuXG4vKipcbiAqIFBhcnNlIHRoZSBnaXZlbiBib2R5IGBzdHJgLlxuICpcbiAqIFVzZWQgZm9yIGF1dG8tcGFyc2luZyBvZiBib2RpZXMuIFBhcnNlcnNcbiAqIGFyZSBkZWZpbmVkIG9uIHRoZSBgc3VwZXJhZ2VudC5wYXJzZWAgb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBzdHJcbiAqIEByZXR1cm4ge01peGVkfVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuUmVzcG9uc2UucHJvdG90eXBlLl9wYXJzZUJvZHkgPSBmdW5jdGlvbihzdHIpe1xuICB2YXIgcGFyc2UgPSByZXF1ZXN0LnBhcnNlW3RoaXMudHlwZV07XG4gIGlmICghcGFyc2UgJiYgaXNKU09OKHRoaXMudHlwZSkpIHtcbiAgICBwYXJzZSA9IHJlcXVlc3QucGFyc2VbJ2FwcGxpY2F0aW9uL2pzb24nXTtcbiAgfVxuICByZXR1cm4gcGFyc2UgJiYgc3RyICYmIChzdHIubGVuZ3RoIHx8IHN0ciBpbnN0YW5jZW9mIE9iamVjdClcbiAgICA/IHBhcnNlKHN0cilcbiAgICA6IG51bGw7XG59O1xuXG4vKipcbiAqIFNldCBmbGFncyBzdWNoIGFzIGAub2tgIGJhc2VkIG9uIGBzdGF0dXNgLlxuICpcbiAqIEZvciBleGFtcGxlIGEgMnh4IHJlc3BvbnNlIHdpbGwgZ2l2ZSB5b3UgYSBgLm9rYCBvZiBfX3RydWVfX1xuICogd2hlcmVhcyA1eHggd2lsbCBiZSBfX2ZhbHNlX18gYW5kIGAuZXJyb3JgIHdpbGwgYmUgX190cnVlX18uIFRoZVxuICogYC5jbGllbnRFcnJvcmAgYW5kIGAuc2VydmVyRXJyb3JgIGFyZSBhbHNvIGF2YWlsYWJsZSB0byBiZSBtb3JlXG4gKiBzcGVjaWZpYywgYW5kIGAuc3RhdHVzVHlwZWAgaXMgdGhlIGNsYXNzIG9mIGVycm9yIHJhbmdpbmcgZnJvbSAxLi41XG4gKiBzb21ldGltZXMgdXNlZnVsIGZvciBtYXBwaW5nIHJlc3BvbmQgY29sb3JzIGV0Yy5cbiAqXG4gKiBcInN1Z2FyXCIgcHJvcGVydGllcyBhcmUgYWxzbyBkZWZpbmVkIGZvciBjb21tb24gY2FzZXMuIEN1cnJlbnRseSBwcm92aWRpbmc6XG4gKlxuICogICAtIC5ub0NvbnRlbnRcbiAqICAgLSAuYmFkUmVxdWVzdFxuICogICAtIC51bmF1dGhvcml6ZWRcbiAqICAgLSAubm90QWNjZXB0YWJsZVxuICogICAtIC5ub3RGb3VuZFxuICpcbiAqIEBwYXJhbSB7TnVtYmVyfSBzdGF0dXNcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cblJlc3BvbnNlLnByb3RvdHlwZS5fc2V0U3RhdHVzUHJvcGVydGllcyA9IGZ1bmN0aW9uKHN0YXR1cyl7XG4gIC8vIGhhbmRsZSBJRTkgYnVnOiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzEwMDQ2OTcyL21zaWUtcmV0dXJucy1zdGF0dXMtY29kZS1vZi0xMjIzLWZvci1hamF4LXJlcXVlc3RcbiAgaWYgKHN0YXR1cyA9PT0gMTIyMykge1xuICAgIHN0YXR1cyA9IDIwNDtcbiAgfVxuXG4gIHZhciB0eXBlID0gc3RhdHVzIC8gMTAwIHwgMDtcblxuICAvLyBzdGF0dXMgLyBjbGFzc1xuICB0aGlzLnN0YXR1cyA9IHRoaXMuc3RhdHVzQ29kZSA9IHN0YXR1cztcbiAgdGhpcy5zdGF0dXNUeXBlID0gdHlwZTtcblxuICAvLyBiYXNpY3NcbiAgdGhpcy5pbmZvID0gMSA9PSB0eXBlO1xuICB0aGlzLm9rID0gMiA9PSB0eXBlO1xuICB0aGlzLmNsaWVudEVycm9yID0gNCA9PSB0eXBlO1xuICB0aGlzLnNlcnZlckVycm9yID0gNSA9PSB0eXBlO1xuICB0aGlzLmVycm9yID0gKDQgPT0gdHlwZSB8fCA1ID09IHR5cGUpXG4gICAgPyB0aGlzLnRvRXJyb3IoKVxuICAgIDogZmFsc2U7XG5cbiAgLy8gc3VnYXJcbiAgdGhpcy5hY2NlcHRlZCA9IDIwMiA9PSBzdGF0dXM7XG4gIHRoaXMubm9Db250ZW50ID0gMjA0ID09IHN0YXR1cztcbiAgdGhpcy5iYWRSZXF1ZXN0ID0gNDAwID09IHN0YXR1cztcbiAgdGhpcy51bmF1dGhvcml6ZWQgPSA0MDEgPT0gc3RhdHVzO1xuICB0aGlzLm5vdEFjY2VwdGFibGUgPSA0MDYgPT0gc3RhdHVzO1xuICB0aGlzLm5vdEZvdW5kID0gNDA0ID09IHN0YXR1cztcbiAgdGhpcy5mb3JiaWRkZW4gPSA0MDMgPT0gc3RhdHVzO1xufTtcblxuLyoqXG4gKiBSZXR1cm4gYW4gYEVycm9yYCByZXByZXNlbnRhdGl2ZSBvZiB0aGlzIHJlc3BvbnNlLlxuICpcbiAqIEByZXR1cm4ge0Vycm9yfVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5SZXNwb25zZS5wcm90b3R5cGUudG9FcnJvciA9IGZ1bmN0aW9uKCl7XG4gIHZhciByZXEgPSB0aGlzLnJlcTtcbiAgdmFyIG1ldGhvZCA9IHJlcS5tZXRob2Q7XG4gIHZhciB1cmwgPSByZXEudXJsO1xuXG4gIHZhciBtc2cgPSAnY2Fubm90ICcgKyBtZXRob2QgKyAnICcgKyB1cmwgKyAnICgnICsgdGhpcy5zdGF0dXMgKyAnKSc7XG4gIHZhciBlcnIgPSBuZXcgRXJyb3IobXNnKTtcbiAgZXJyLnN0YXR1cyA9IHRoaXMuc3RhdHVzO1xuICBlcnIubWV0aG9kID0gbWV0aG9kO1xuICBlcnIudXJsID0gdXJsO1xuXG4gIHJldHVybiBlcnI7XG59O1xuXG4vKipcbiAqIEV4cG9zZSBgUmVzcG9uc2VgLlxuICovXG5cbnJlcXVlc3QuUmVzcG9uc2UgPSBSZXNwb25zZTtcblxuLyoqXG4gKiBJbml0aWFsaXplIGEgbmV3IGBSZXF1ZXN0YCB3aXRoIHRoZSBnaXZlbiBgbWV0aG9kYCBhbmQgYHVybGAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG1ldGhvZFxuICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5mdW5jdGlvbiBSZXF1ZXN0KG1ldGhvZCwgdXJsKSB7XG4gIHZhciBzZWxmID0gdGhpcztcbiAgdGhpcy5fcXVlcnkgPSB0aGlzLl9xdWVyeSB8fCBbXTtcbiAgdGhpcy5tZXRob2QgPSBtZXRob2Q7XG4gIHRoaXMudXJsID0gdXJsO1xuICB0aGlzLmhlYWRlciA9IHt9OyAvLyBwcmVzZXJ2ZXMgaGVhZGVyIG5hbWUgY2FzZVxuICB0aGlzLl9oZWFkZXIgPSB7fTsgLy8gY29lcmNlcyBoZWFkZXIgbmFtZXMgdG8gbG93ZXJjYXNlXG4gIHRoaXMub24oJ2VuZCcsIGZ1bmN0aW9uKCl7XG4gICAgdmFyIGVyciA9IG51bGw7XG4gICAgdmFyIHJlcyA9IG51bGw7XG5cbiAgICB0cnkge1xuICAgICAgcmVzID0gbmV3IFJlc3BvbnNlKHNlbGYpO1xuICAgIH0gY2F0Y2goZSkge1xuICAgICAgZXJyID0gbmV3IEVycm9yKCdQYXJzZXIgaXMgdW5hYmxlIHRvIHBhcnNlIHRoZSByZXNwb25zZScpO1xuICAgICAgZXJyLnBhcnNlID0gdHJ1ZTtcbiAgICAgIGVyci5vcmlnaW5hbCA9IGU7XG4gICAgICAvLyBpc3N1ZSAjNjc1OiByZXR1cm4gdGhlIHJhdyByZXNwb25zZSBpZiB0aGUgcmVzcG9uc2UgcGFyc2luZyBmYWlsc1xuICAgICAgZXJyLnJhd1Jlc3BvbnNlID0gc2VsZi54aHIgJiYgc2VsZi54aHIucmVzcG9uc2VUZXh0ID8gc2VsZi54aHIucmVzcG9uc2VUZXh0IDogbnVsbDtcbiAgICAgIC8vIGlzc3VlICM4NzY6IHJldHVybiB0aGUgaHR0cCBzdGF0dXMgY29kZSBpZiB0aGUgcmVzcG9uc2UgcGFyc2luZyBmYWlsc1xuICAgICAgZXJyLnN0YXR1c0NvZGUgPSBzZWxmLnhociAmJiBzZWxmLnhoci5zdGF0dXMgPyBzZWxmLnhoci5zdGF0dXMgOiBudWxsO1xuICAgICAgcmV0dXJuIHNlbGYuY2FsbGJhY2soZXJyKTtcbiAgICB9XG5cbiAgICBzZWxmLmVtaXQoJ3Jlc3BvbnNlJywgcmVzKTtcblxuICAgIHZhciBuZXdfZXJyO1xuICAgIHRyeSB7XG4gICAgICBpZiAocmVzLnN0YXR1cyA8IDIwMCB8fCByZXMuc3RhdHVzID49IDMwMCkge1xuICAgICAgICBuZXdfZXJyID0gbmV3IEVycm9yKHJlcy5zdGF0dXNUZXh0IHx8ICdVbnN1Y2Nlc3NmdWwgSFRUUCByZXNwb25zZScpO1xuICAgICAgICBuZXdfZXJyLm9yaWdpbmFsID0gZXJyO1xuICAgICAgICBuZXdfZXJyLnJlc3BvbnNlID0gcmVzO1xuICAgICAgICBuZXdfZXJyLnN0YXR1cyA9IHJlcy5zdGF0dXM7XG4gICAgICB9XG4gICAgfSBjYXRjaChlKSB7XG4gICAgICBuZXdfZXJyID0gZTsgLy8gIzk4NSB0b3VjaGluZyByZXMgbWF5IGNhdXNlIElOVkFMSURfU1RBVEVfRVJSIG9uIG9sZCBBbmRyb2lkXG4gICAgfVxuXG4gICAgLy8gIzEwMDAgZG9uJ3QgY2F0Y2ggZXJyb3JzIGZyb20gdGhlIGNhbGxiYWNrIHRvIGF2b2lkIGRvdWJsZSBjYWxsaW5nIGl0XG4gICAgaWYgKG5ld19lcnIpIHtcbiAgICAgIHNlbGYuY2FsbGJhY2sobmV3X2VyciwgcmVzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2VsZi5jYWxsYmFjayhudWxsLCByZXMpO1xuICAgIH1cbiAgfSk7XG59XG5cbi8qKlxuICogTWl4aW4gYEVtaXR0ZXJgIGFuZCBgcmVxdWVzdEJhc2VgLlxuICovXG5cbkVtaXR0ZXIoUmVxdWVzdC5wcm90b3R5cGUpO1xuZm9yICh2YXIga2V5IGluIHJlcXVlc3RCYXNlKSB7XG4gIFJlcXVlc3QucHJvdG90eXBlW2tleV0gPSByZXF1ZXN0QmFzZVtrZXldO1xufVxuXG4vKipcbiAqIFNldCBDb250ZW50LVR5cGUgdG8gYHR5cGVgLCBtYXBwaW5nIHZhbHVlcyBmcm9tIGByZXF1ZXN0LnR5cGVzYC5cbiAqXG4gKiBFeGFtcGxlczpcbiAqXG4gKiAgICAgIHN1cGVyYWdlbnQudHlwZXMueG1sID0gJ2FwcGxpY2F0aW9uL3htbCc7XG4gKlxuICogICAgICByZXF1ZXN0LnBvc3QoJy8nKVxuICogICAgICAgIC50eXBlKCd4bWwnKVxuICogICAgICAgIC5zZW5kKHhtbHN0cmluZylcbiAqICAgICAgICAuZW5kKGNhbGxiYWNrKTtcbiAqXG4gKiAgICAgIHJlcXVlc3QucG9zdCgnLycpXG4gKiAgICAgICAgLnR5cGUoJ2FwcGxpY2F0aW9uL3htbCcpXG4gKiAgICAgICAgLnNlbmQoeG1sc3RyaW5nKVxuICogICAgICAgIC5lbmQoY2FsbGJhY2spO1xuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUudHlwZSA9IGZ1bmN0aW9uKHR5cGUpe1xuICB0aGlzLnNldCgnQ29udGVudC1UeXBlJywgcmVxdWVzdC50eXBlc1t0eXBlXSB8fCB0eXBlKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCByZXNwb25zZVR5cGUgdG8gYHZhbGAuIFByZXNlbnRseSB2YWxpZCByZXNwb25zZVR5cGVzIGFyZSAnYmxvYicgYW5kXG4gKiAnYXJyYXlidWZmZXInLlxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgICAgcmVxLmdldCgnLycpXG4gKiAgICAgICAgLnJlc3BvbnNlVHlwZSgnYmxvYicpXG4gKiAgICAgICAgLmVuZChjYWxsYmFjayk7XG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHZhbFxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLnJlc3BvbnNlVHlwZSA9IGZ1bmN0aW9uKHZhbCl7XG4gIHRoaXMuX3Jlc3BvbnNlVHlwZSA9IHZhbDtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCBBY2NlcHQgdG8gYHR5cGVgLCBtYXBwaW5nIHZhbHVlcyBmcm9tIGByZXF1ZXN0LnR5cGVzYC5cbiAqXG4gKiBFeGFtcGxlczpcbiAqXG4gKiAgICAgIHN1cGVyYWdlbnQudHlwZXMuanNvbiA9ICdhcHBsaWNhdGlvbi9qc29uJztcbiAqXG4gKiAgICAgIHJlcXVlc3QuZ2V0KCcvYWdlbnQnKVxuICogICAgICAgIC5hY2NlcHQoJ2pzb24nKVxuICogICAgICAgIC5lbmQoY2FsbGJhY2spO1xuICpcbiAqICAgICAgcmVxdWVzdC5nZXQoJy9hZ2VudCcpXG4gKiAgICAgICAgLmFjY2VwdCgnYXBwbGljYXRpb24vanNvbicpXG4gKiAgICAgICAgLmVuZChjYWxsYmFjayk7XG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGFjY2VwdFxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLmFjY2VwdCA9IGZ1bmN0aW9uKHR5cGUpe1xuICB0aGlzLnNldCgnQWNjZXB0JywgcmVxdWVzdC50eXBlc1t0eXBlXSB8fCB0eXBlKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIFNldCBBdXRob3JpemF0aW9uIGZpZWxkIHZhbHVlIHdpdGggYHVzZXJgIGFuZCBgcGFzc2AuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHVzZXJcbiAqIEBwYXJhbSB7U3RyaW5nfSBwYXNzXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0aW9ucyB3aXRoICd0eXBlJyBwcm9wZXJ0eSAnYXV0bycgb3IgJ2Jhc2ljJyAoZGVmYXVsdCAnYmFzaWMnKVxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cblJlcXVlc3QucHJvdG90eXBlLmF1dGggPSBmdW5jdGlvbih1c2VyLCBwYXNzLCBvcHRpb25zKXtcbiAgaWYgKCFvcHRpb25zKSB7XG4gICAgb3B0aW9ucyA9IHtcbiAgICAgIHR5cGU6ICdiYXNpYydcbiAgICB9XG4gIH1cblxuICBzd2l0Y2ggKG9wdGlvbnMudHlwZSkge1xuICAgIGNhc2UgJ2Jhc2ljJzpcbiAgICAgIHZhciBzdHIgPSBidG9hKHVzZXIgKyAnOicgKyBwYXNzKTtcbiAgICAgIHRoaXMuc2V0KCdBdXRob3JpemF0aW9uJywgJ0Jhc2ljICcgKyBzdHIpO1xuICAgIGJyZWFrO1xuXG4gICAgY2FzZSAnYXV0byc6XG4gICAgICB0aGlzLnVzZXJuYW1lID0gdXNlcjtcbiAgICAgIHRoaXMucGFzc3dvcmQgPSBwYXNzO1xuICAgIGJyZWFrO1xuICB9XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4qIEFkZCBxdWVyeS1zdHJpbmcgYHZhbGAuXG4qXG4qIEV4YW1wbGVzOlxuKlxuKiAgIHJlcXVlc3QuZ2V0KCcvc2hvZXMnKVxuKiAgICAgLnF1ZXJ5KCdzaXplPTEwJylcbiogICAgIC5xdWVyeSh7IGNvbG9yOiAnYmx1ZScgfSlcbipcbiogQHBhcmFtIHtPYmplY3R8U3RyaW5nfSB2YWxcbiogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4qIEBhcGkgcHVibGljXG4qL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS5xdWVyeSA9IGZ1bmN0aW9uKHZhbCl7XG4gIGlmICgnc3RyaW5nJyAhPSB0eXBlb2YgdmFsKSB2YWwgPSBzZXJpYWxpemUodmFsKTtcbiAgaWYgKHZhbCkgdGhpcy5fcXVlcnkucHVzaCh2YWwpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogUXVldWUgdGhlIGdpdmVuIGBmaWxlYCBhcyBhbiBhdHRhY2htZW50IHRvIHRoZSBzcGVjaWZpZWQgYGZpZWxkYCxcbiAqIHdpdGggb3B0aW9uYWwgYGZpbGVuYW1lYC5cbiAqXG4gKiBgYGAganNcbiAqIHJlcXVlc3QucG9zdCgnL3VwbG9hZCcpXG4gKiAgIC5hdHRhY2goJ2NvbnRlbnQnLCBuZXcgQmxvYihbJzxhIGlkPVwiYVwiPjxiIGlkPVwiYlwiPmhleSE8L2I+PC9hPiddLCB7IHR5cGU6IFwidGV4dC9odG1sXCJ9KSlcbiAqICAgLmVuZChjYWxsYmFjayk7XG4gKiBgYGBcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZmllbGRcbiAqIEBwYXJhbSB7QmxvYnxGaWxlfSBmaWxlXG4gKiBAcGFyYW0ge1N0cmluZ30gZmlsZW5hbWVcbiAqIEByZXR1cm4ge1JlcXVlc3R9IGZvciBjaGFpbmluZ1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5SZXF1ZXN0LnByb3RvdHlwZS5hdHRhY2ggPSBmdW5jdGlvbihmaWVsZCwgZmlsZSwgZmlsZW5hbWUpe1xuICB0aGlzLl9nZXRGb3JtRGF0YSgpLmFwcGVuZChmaWVsZCwgZmlsZSwgZmlsZW5hbWUgfHwgZmlsZS5uYW1lKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5SZXF1ZXN0LnByb3RvdHlwZS5fZ2V0Rm9ybURhdGEgPSBmdW5jdGlvbigpe1xuICBpZiAoIXRoaXMuX2Zvcm1EYXRhKSB7XG4gICAgdGhpcy5fZm9ybURhdGEgPSBuZXcgcm9vdC5Gb3JtRGF0YSgpO1xuICB9XG4gIHJldHVybiB0aGlzLl9mb3JtRGF0YTtcbn07XG5cbi8qKlxuICogSW52b2tlIHRoZSBjYWxsYmFjayB3aXRoIGBlcnJgIGFuZCBgcmVzYFxuICogYW5kIGhhbmRsZSBhcml0eSBjaGVjay5cbiAqXG4gKiBAcGFyYW0ge0Vycm9yfSBlcnJcbiAqIEBwYXJhbSB7UmVzcG9uc2V9IHJlc1xuICogQGFwaSBwcml2YXRlXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUuY2FsbGJhY2sgPSBmdW5jdGlvbihlcnIsIHJlcyl7XG4gIHZhciBmbiA9IHRoaXMuX2NhbGxiYWNrO1xuICB0aGlzLmNsZWFyVGltZW91dCgpO1xuICBmbihlcnIsIHJlcyk7XG59O1xuXG4vKipcbiAqIEludm9rZSBjYWxsYmFjayB3aXRoIHgtZG9tYWluIGVycm9yLlxuICpcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cblJlcXVlc3QucHJvdG90eXBlLmNyb3NzRG9tYWluRXJyb3IgPSBmdW5jdGlvbigpe1xuICB2YXIgZXJyID0gbmV3IEVycm9yKCdSZXF1ZXN0IGhhcyBiZWVuIHRlcm1pbmF0ZWRcXG5Qb3NzaWJsZSBjYXVzZXM6IHRoZSBuZXR3b3JrIGlzIG9mZmxpbmUsIE9yaWdpbiBpcyBub3QgYWxsb3dlZCBieSBBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4sIHRoZSBwYWdlIGlzIGJlaW5nIHVubG9hZGVkLCBldGMuJyk7XG4gIGVyci5jcm9zc0RvbWFpbiA9IHRydWU7XG5cbiAgZXJyLnN0YXR1cyA9IHRoaXMuc3RhdHVzO1xuICBlcnIubWV0aG9kID0gdGhpcy5tZXRob2Q7XG4gIGVyci51cmwgPSB0aGlzLnVybDtcblxuICB0aGlzLmNhbGxiYWNrKGVycik7XG59O1xuXG4vKipcbiAqIEludm9rZSBjYWxsYmFjayB3aXRoIHRpbWVvdXQgZXJyb3IuXG4gKlxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUuX3RpbWVvdXRFcnJvciA9IGZ1bmN0aW9uKCl7XG4gIHZhciB0aW1lb3V0ID0gdGhpcy5fdGltZW91dDtcbiAgdmFyIGVyciA9IG5ldyBFcnJvcigndGltZW91dCBvZiAnICsgdGltZW91dCArICdtcyBleGNlZWRlZCcpO1xuICBlcnIudGltZW91dCA9IHRpbWVvdXQ7XG4gIHRoaXMuY2FsbGJhY2soZXJyKTtcbn07XG5cbi8qKlxuICogQ29tcG9zZSBxdWVyeXN0cmluZyB0byBhcHBlbmQgdG8gcmVxLnVybFxuICpcbiAqIEBhcGkgcHJpdmF0ZVxuICovXG5cblJlcXVlc3QucHJvdG90eXBlLl9hcHBlbmRRdWVyeVN0cmluZyA9IGZ1bmN0aW9uKCl7XG4gIHZhciBxdWVyeSA9IHRoaXMuX3F1ZXJ5LmpvaW4oJyYnKTtcbiAgaWYgKHF1ZXJ5KSB7XG4gICAgdGhpcy51cmwgKz0gfnRoaXMudXJsLmluZGV4T2YoJz8nKVxuICAgICAgPyAnJicgKyBxdWVyeVxuICAgICAgOiAnPycgKyBxdWVyeTtcbiAgfVxufTtcblxuLyoqXG4gKiBJbml0aWF0ZSByZXF1ZXN0LCBpbnZva2luZyBjYWxsYmFjayBgZm4ocmVzKWBcbiAqIHdpdGggYW4gaW5zdGFuY2VvZiBgUmVzcG9uc2VgLlxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuUmVxdWVzdC5wcm90b3R5cGUuZW5kID0gZnVuY3Rpb24oZm4pe1xuICB2YXIgc2VsZiA9IHRoaXM7XG4gIHZhciB4aHIgPSB0aGlzLnhociA9IHJlcXVlc3QuZ2V0WEhSKCk7XG4gIHZhciB0aW1lb3V0ID0gdGhpcy5fdGltZW91dDtcbiAgdmFyIGRhdGEgPSB0aGlzLl9mb3JtRGF0YSB8fCB0aGlzLl9kYXRhO1xuXG4gIC8vIHN0b3JlIGNhbGxiYWNrXG4gIHRoaXMuX2NhbGxiYWNrID0gZm4gfHwgbm9vcDtcblxuICAvLyBzdGF0ZSBjaGFuZ2VcbiAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCl7XG4gICAgaWYgKDQgIT0geGhyLnJlYWR5U3RhdGUpIHJldHVybjtcblxuICAgIC8vIEluIElFOSwgcmVhZHMgdG8gYW55IHByb3BlcnR5IChlLmcuIHN0YXR1cykgb2ZmIG9mIGFuIGFib3J0ZWQgWEhSIHdpbGxcbiAgICAvLyByZXN1bHQgaW4gdGhlIGVycm9yIFwiQ291bGQgbm90IGNvbXBsZXRlIHRoZSBvcGVyYXRpb24gZHVlIHRvIGVycm9yIGMwMGMwMjNmXCJcbiAgICB2YXIgc3RhdHVzO1xuICAgIHRyeSB7IHN0YXR1cyA9IHhoci5zdGF0dXMgfSBjYXRjaChlKSB7IHN0YXR1cyA9IDA7IH1cblxuICAgIGlmICgwID09IHN0YXR1cykge1xuICAgICAgaWYgKHNlbGYudGltZWRvdXQpIHJldHVybiBzZWxmLl90aW1lb3V0RXJyb3IoKTtcbiAgICAgIGlmIChzZWxmLl9hYm9ydGVkKSByZXR1cm47XG4gICAgICByZXR1cm4gc2VsZi5jcm9zc0RvbWFpbkVycm9yKCk7XG4gICAgfVxuICAgIHNlbGYuZW1pdCgnZW5kJyk7XG4gIH07XG5cbiAgLy8gcHJvZ3Jlc3NcbiAgdmFyIGhhbmRsZVByb2dyZXNzID0gZnVuY3Rpb24oZSl7XG4gICAgaWYgKGUudG90YWwgPiAwKSB7XG4gICAgICBlLnBlcmNlbnQgPSBlLmxvYWRlZCAvIGUudG90YWwgKiAxMDA7XG4gICAgfVxuICAgIGUuZGlyZWN0aW9uID0gJ2Rvd25sb2FkJztcbiAgICBzZWxmLmVtaXQoJ3Byb2dyZXNzJywgZSk7XG4gIH07XG4gIGlmICh0aGlzLmhhc0xpc3RlbmVycygncHJvZ3Jlc3MnKSkge1xuICAgIHhoci5vbnByb2dyZXNzID0gaGFuZGxlUHJvZ3Jlc3M7XG4gIH1cbiAgdHJ5IHtcbiAgICBpZiAoeGhyLnVwbG9hZCAmJiB0aGlzLmhhc0xpc3RlbmVycygncHJvZ3Jlc3MnKSkge1xuICAgICAgeGhyLnVwbG9hZC5vbnByb2dyZXNzID0gaGFuZGxlUHJvZ3Jlc3M7XG4gICAgfVxuICB9IGNhdGNoKGUpIHtcbiAgICAvLyBBY2Nlc3NpbmcgeGhyLnVwbG9hZCBmYWlscyBpbiBJRSBmcm9tIGEgd2ViIHdvcmtlciwgc28ganVzdCBwcmV0ZW5kIGl0IGRvZXNuJ3QgZXhpc3QuXG4gICAgLy8gUmVwb3J0ZWQgaGVyZTpcbiAgICAvLyBodHRwczovL2Nvbm5lY3QubWljcm9zb2Z0LmNvbS9JRS9mZWVkYmFjay9kZXRhaWxzLzgzNzI0NS94bWxodHRwcmVxdWVzdC11cGxvYWQtdGhyb3dzLWludmFsaWQtYXJndW1lbnQtd2hlbi11c2VkLWZyb20td2ViLXdvcmtlci1jb250ZXh0XG4gIH1cblxuICAvLyB0aW1lb3V0XG4gIGlmICh0aW1lb3V0ICYmICF0aGlzLl90aW1lcikge1xuICAgIHRoaXMuX3RpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgc2VsZi50aW1lZG91dCA9IHRydWU7XG4gICAgICBzZWxmLmFib3J0KCk7XG4gICAgfSwgdGltZW91dCk7XG4gIH1cblxuICAvLyBxdWVyeXN0cmluZ1xuICB0aGlzLl9hcHBlbmRRdWVyeVN0cmluZygpO1xuXG4gIC8vIGluaXRpYXRlIHJlcXVlc3RcbiAgaWYgKHRoaXMudXNlcm5hbWUgJiYgdGhpcy5wYXNzd29yZCkge1xuICAgIHhoci5vcGVuKHRoaXMubWV0aG9kLCB0aGlzLnVybCwgdHJ1ZSwgdGhpcy51c2VybmFtZSwgdGhpcy5wYXNzd29yZCk7XG4gIH0gZWxzZSB7XG4gICAgeGhyLm9wZW4odGhpcy5tZXRob2QsIHRoaXMudXJsLCB0cnVlKTtcbiAgfVxuXG4gIC8vIENPUlNcbiAgaWYgKHRoaXMuX3dpdGhDcmVkZW50aWFscykgeGhyLndpdGhDcmVkZW50aWFscyA9IHRydWU7XG5cbiAgLy8gYm9keVxuICBpZiAoJ0dFVCcgIT0gdGhpcy5tZXRob2QgJiYgJ0hFQUQnICE9IHRoaXMubWV0aG9kICYmICdzdHJpbmcnICE9IHR5cGVvZiBkYXRhICYmICF0aGlzLl9pc0hvc3QoZGF0YSkpIHtcbiAgICAvLyBzZXJpYWxpemUgc3R1ZmZcbiAgICB2YXIgY29udGVudFR5cGUgPSB0aGlzLl9oZWFkZXJbJ2NvbnRlbnQtdHlwZSddO1xuICAgIHZhciBzZXJpYWxpemUgPSB0aGlzLl9zZXJpYWxpemVyIHx8IHJlcXVlc3Quc2VyaWFsaXplW2NvbnRlbnRUeXBlID8gY29udGVudFR5cGUuc3BsaXQoJzsnKVswXSA6ICcnXTtcbiAgICBpZiAoIXNlcmlhbGl6ZSAmJiBpc0pTT04oY29udGVudFR5cGUpKSBzZXJpYWxpemUgPSByZXF1ZXN0LnNlcmlhbGl6ZVsnYXBwbGljYXRpb24vanNvbiddO1xuICAgIGlmIChzZXJpYWxpemUpIGRhdGEgPSBzZXJpYWxpemUoZGF0YSk7XG4gIH1cblxuICAvLyBzZXQgaGVhZGVyIGZpZWxkc1xuICBmb3IgKHZhciBmaWVsZCBpbiB0aGlzLmhlYWRlcikge1xuICAgIGlmIChudWxsID09IHRoaXMuaGVhZGVyW2ZpZWxkXSkgY29udGludWU7XG4gICAgeGhyLnNldFJlcXVlc3RIZWFkZXIoZmllbGQsIHRoaXMuaGVhZGVyW2ZpZWxkXSk7XG4gIH1cblxuICBpZiAodGhpcy5fcmVzcG9uc2VUeXBlKSB7XG4gICAgeGhyLnJlc3BvbnNlVHlwZSA9IHRoaXMuX3Jlc3BvbnNlVHlwZTtcbiAgfVxuXG4gIC8vIHNlbmQgc3R1ZmZcbiAgdGhpcy5lbWl0KCdyZXF1ZXN0JywgdGhpcyk7XG5cbiAgLy8gSUUxMSB4aHIuc2VuZCh1bmRlZmluZWQpIHNlbmRzICd1bmRlZmluZWQnIHN0cmluZyBhcyBQT1NUIHBheWxvYWQgKGluc3RlYWQgb2Ygbm90aGluZylcbiAgLy8gV2UgbmVlZCBudWxsIGhlcmUgaWYgZGF0YSBpcyB1bmRlZmluZWRcbiAgeGhyLnNlbmQodHlwZW9mIGRhdGEgIT09ICd1bmRlZmluZWQnID8gZGF0YSA6IG51bGwpO1xuICByZXR1cm4gdGhpcztcbn07XG5cblxuLyoqXG4gKiBFeHBvc2UgYFJlcXVlc3RgLlxuICovXG5cbnJlcXVlc3QuUmVxdWVzdCA9IFJlcXVlc3Q7XG5cbi8qKlxuICogR0VUIGB1cmxgIHdpdGggb3B0aW9uYWwgY2FsbGJhY2sgYGZuKHJlcylgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAqIEBwYXJhbSB7TWl4ZWR8RnVuY3Rpb259IFtkYXRhXSBvciBmblxuICogQHBhcmFtIHtGdW5jdGlvbn0gW2ZuXVxuICogQHJldHVybiB7UmVxdWVzdH1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxucmVxdWVzdC5nZXQgPSBmdW5jdGlvbih1cmwsIGRhdGEsIGZuKXtcbiAgdmFyIHJlcSA9IHJlcXVlc3QoJ0dFVCcsIHVybCk7XG4gIGlmICgnZnVuY3Rpb24nID09IHR5cGVvZiBkYXRhKSBmbiA9IGRhdGEsIGRhdGEgPSBudWxsO1xuICBpZiAoZGF0YSkgcmVxLnF1ZXJ5KGRhdGEpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxuLyoqXG4gKiBIRUFEIGB1cmxgIHdpdGggb3B0aW9uYWwgY2FsbGJhY2sgYGZuKHJlcylgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAqIEBwYXJhbSB7TWl4ZWR8RnVuY3Rpb259IFtkYXRhXSBvciBmblxuICogQHBhcmFtIHtGdW5jdGlvbn0gW2ZuXVxuICogQHJldHVybiB7UmVxdWVzdH1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxucmVxdWVzdC5oZWFkID0gZnVuY3Rpb24odXJsLCBkYXRhLCBmbil7XG4gIHZhciByZXEgPSByZXF1ZXN0KCdIRUFEJywgdXJsKTtcbiAgaWYgKCdmdW5jdGlvbicgPT0gdHlwZW9mIGRhdGEpIGZuID0gZGF0YSwgZGF0YSA9IG51bGw7XG4gIGlmIChkYXRhKSByZXEuc2VuZChkYXRhKTtcbiAgaWYgKGZuKSByZXEuZW5kKGZuKTtcbiAgcmV0dXJuIHJlcTtcbn07XG5cbi8qKlxuICogT1BUSU9OUyBxdWVyeSB0byBgdXJsYCB3aXRoIG9wdGlvbmFsIGNhbGxiYWNrIGBmbihyZXMpYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gdXJsXG4gKiBAcGFyYW0ge01peGVkfEZ1bmN0aW9ufSBbZGF0YV0gb3IgZm5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtmbl1cbiAqIEByZXR1cm4ge1JlcXVlc3R9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbnJlcXVlc3Qub3B0aW9ucyA9IGZ1bmN0aW9uKHVybCwgZGF0YSwgZm4pe1xuICB2YXIgcmVxID0gcmVxdWVzdCgnT1BUSU9OUycsIHVybCk7XG4gIGlmICgnZnVuY3Rpb24nID09IHR5cGVvZiBkYXRhKSBmbiA9IGRhdGEsIGRhdGEgPSBudWxsO1xuICBpZiAoZGF0YSkgcmVxLnNlbmQoZGF0YSk7XG4gIGlmIChmbikgcmVxLmVuZChmbik7XG4gIHJldHVybiByZXE7XG59O1xuXG4vKipcbiAqIERFTEVURSBgdXJsYCB3aXRoIG9wdGlvbmFsIGNhbGxiYWNrIGBmbihyZXMpYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gdXJsXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbZm5dXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5mdW5jdGlvbiBkZWwodXJsLCBmbil7XG4gIHZhciByZXEgPSByZXF1ZXN0KCdERUxFVEUnLCB1cmwpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxucmVxdWVzdFsnZGVsJ10gPSBkZWw7XG5yZXF1ZXN0WydkZWxldGUnXSA9IGRlbDtcblxuLyoqXG4gKiBQQVRDSCBgdXJsYCB3aXRoIG9wdGlvbmFsIGBkYXRhYCBhbmQgY2FsbGJhY2sgYGZuKHJlcylgLlxuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSB1cmxcbiAqIEBwYXJhbSB7TWl4ZWR9IFtkYXRhXVxuICogQHBhcmFtIHtGdW5jdGlvbn0gW2ZuXVxuICogQHJldHVybiB7UmVxdWVzdH1cbiAqIEBhcGkgcHVibGljXG4gKi9cblxucmVxdWVzdC5wYXRjaCA9IGZ1bmN0aW9uKHVybCwgZGF0YSwgZm4pe1xuICB2YXIgcmVxID0gcmVxdWVzdCgnUEFUQ0gnLCB1cmwpO1xuICBpZiAoJ2Z1bmN0aW9uJyA9PSB0eXBlb2YgZGF0YSkgZm4gPSBkYXRhLCBkYXRhID0gbnVsbDtcbiAgaWYgKGRhdGEpIHJlcS5zZW5kKGRhdGEpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxuLyoqXG4gKiBQT1NUIGB1cmxgIHdpdGggb3B0aW9uYWwgYGRhdGFgIGFuZCBjYWxsYmFjayBgZm4ocmVzKWAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IHVybFxuICogQHBhcmFtIHtNaXhlZH0gW2RhdGFdXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBbZm5dXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5yZXF1ZXN0LnBvc3QgPSBmdW5jdGlvbih1cmwsIGRhdGEsIGZuKXtcbiAgdmFyIHJlcSA9IHJlcXVlc3QoJ1BPU1QnLCB1cmwpO1xuICBpZiAoJ2Z1bmN0aW9uJyA9PSB0eXBlb2YgZGF0YSkgZm4gPSBkYXRhLCBkYXRhID0gbnVsbDtcbiAgaWYgKGRhdGEpIHJlcS5zZW5kKGRhdGEpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcblxuLyoqXG4gKiBQVVQgYHVybGAgd2l0aCBvcHRpb25hbCBgZGF0YWAgYW5kIGNhbGxiYWNrIGBmbihyZXMpYC5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gdXJsXG4gKiBAcGFyYW0ge01peGVkfEZ1bmN0aW9ufSBbZGF0YV0gb3IgZm5cbiAqIEBwYXJhbSB7RnVuY3Rpb259IFtmbl1cbiAqIEByZXR1cm4ge1JlcXVlc3R9XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbnJlcXVlc3QucHV0ID0gZnVuY3Rpb24odXJsLCBkYXRhLCBmbil7XG4gIHZhciByZXEgPSByZXF1ZXN0KCdQVVQnLCB1cmwpO1xuICBpZiAoJ2Z1bmN0aW9uJyA9PSB0eXBlb2YgZGF0YSkgZm4gPSBkYXRhLCBkYXRhID0gbnVsbDtcbiAgaWYgKGRhdGEpIHJlcS5zZW5kKGRhdGEpO1xuICBpZiAoZm4pIHJlcS5lbmQoZm4pO1xuICByZXR1cm4gcmVxO1xufTtcbiIsIi8qKlxuICogQ2hlY2sgaWYgYG9iamAgaXMgYW4gb2JqZWN0LlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmpcbiAqIEByZXR1cm4ge0Jvb2xlYW59XG4gKiBAYXBpIHByaXZhdGVcbiAqL1xuXG5mdW5jdGlvbiBpc09iamVjdChvYmopIHtcbiAgcmV0dXJuIG51bGwgIT09IG9iaiAmJiAnb2JqZWN0JyA9PT0gdHlwZW9mIG9iajtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBpc09iamVjdDtcbiIsIi8qKlxuICogTW9kdWxlIG9mIG1peGVkLWluIGZ1bmN0aW9ucyBzaGFyZWQgYmV0d2VlbiBub2RlIGFuZCBjbGllbnQgY29kZVxuICovXG52YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL2lzLW9iamVjdCcpO1xuXG4vKipcbiAqIENsZWFyIHByZXZpb3VzIHRpbWVvdXQuXG4gKlxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmV4cG9ydHMuY2xlYXJUaW1lb3V0ID0gZnVuY3Rpb24gX2NsZWFyVGltZW91dCgpe1xuICB0aGlzLl90aW1lb3V0ID0gMDtcbiAgY2xlYXJUaW1lb3V0KHRoaXMuX3RpbWVyKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIE92ZXJyaWRlIGRlZmF1bHQgcmVzcG9uc2UgYm9keSBwYXJzZXJcbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIHRvIGNvbnZlcnQgaW5jb21pbmcgZGF0YSBpbnRvIHJlcXVlc3QuYm9keVxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmV4cG9ydHMucGFyc2UgPSBmdW5jdGlvbiBwYXJzZShmbil7XG4gIHRoaXMuX3BhcnNlciA9IGZuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogT3ZlcnJpZGUgZGVmYXVsdCByZXF1ZXN0IGJvZHkgc2VyaWFsaXplclxuICpcbiAqIFRoaXMgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgdG8gY29udmVydCBkYXRhIHNldCB2aWEgLnNlbmQgb3IgLmF0dGFjaCBpbnRvIHBheWxvYWQgdG8gc2VuZFxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmV4cG9ydHMuc2VyaWFsaXplID0gZnVuY3Rpb24gc2VyaWFsaXplKGZuKXtcbiAgdGhpcy5fc2VyaWFsaXplciA9IGZuO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogU2V0IHRpbWVvdXQgdG8gYG1zYC5cbiAqXG4gKiBAcGFyYW0ge051bWJlcn0gbXNcbiAqIEByZXR1cm4ge1JlcXVlc3R9IGZvciBjaGFpbmluZ1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5leHBvcnRzLnRpbWVvdXQgPSBmdW5jdGlvbiB0aW1lb3V0KG1zKXtcbiAgdGhpcy5fdGltZW91dCA9IG1zO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogUHJvbWlzZSBzdXBwb3J0XG4gKlxuICogQHBhcmFtIHtGdW5jdGlvbn0gcmVzb2x2ZVxuICogQHBhcmFtIHtGdW5jdGlvbn0gcmVqZWN0XG4gKiBAcmV0dXJuIHtSZXF1ZXN0fVxuICovXG5cbmV4cG9ydHMudGhlbiA9IGZ1bmN0aW9uIHRoZW4ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gIGlmICghdGhpcy5fZnVsbGZpbGxlZFByb21pc2UpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG4gICAgdGhpcy5fZnVsbGZpbGxlZFByb21pc2UgPSBuZXcgUHJvbWlzZShmdW5jdGlvbihpbm5lclJlc29sdmUsIGlubmVyUmVqZWN0KXtcbiAgICAgIHNlbGYuZW5kKGZ1bmN0aW9uKGVyciwgcmVzKXtcbiAgICAgICAgaWYgKGVycikgaW5uZXJSZWplY3QoZXJyKTsgZWxzZSBpbm5lclJlc29sdmUocmVzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIHJldHVybiB0aGlzLl9mdWxsZmlsbGVkUHJvbWlzZS50aGVuKHJlc29sdmUsIHJlamVjdCk7XG59XG5cbi8qKlxuICogQWxsb3cgZm9yIGV4dGVuc2lvblxuICovXG5cbmV4cG9ydHMudXNlID0gZnVuY3Rpb24gdXNlKGZuKSB7XG4gIGZuKHRoaXMpO1xuICByZXR1cm4gdGhpcztcbn1cblxuXG4vKipcbiAqIEdldCByZXF1ZXN0IGhlYWRlciBgZmllbGRgLlxuICogQ2FzZS1pbnNlbnNpdGl2ZS5cbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gZmllbGRcbiAqIEByZXR1cm4ge1N0cmluZ31cbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZXhwb3J0cy5nZXQgPSBmdW5jdGlvbihmaWVsZCl7XG4gIHJldHVybiB0aGlzLl9oZWFkZXJbZmllbGQudG9Mb3dlckNhc2UoKV07XG59O1xuXG4vKipcbiAqIEdldCBjYXNlLWluc2Vuc2l0aXZlIGhlYWRlciBgZmllbGRgIHZhbHVlLlxuICogVGhpcyBpcyBhIGRlcHJlY2F0ZWQgaW50ZXJuYWwgQVBJLiBVc2UgYC5nZXQoZmllbGQpYCBpbnN0ZWFkLlxuICpcbiAqIChnZXRIZWFkZXIgaXMgbm8gbG9uZ2VyIHVzZWQgaW50ZXJuYWxseSBieSB0aGUgc3VwZXJhZ2VudCBjb2RlIGJhc2UpXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IGZpZWxkXG4gKiBAcmV0dXJuIHtTdHJpbmd9XG4gKiBAYXBpIHByaXZhdGVcbiAqIEBkZXByZWNhdGVkXG4gKi9cblxuZXhwb3J0cy5nZXRIZWFkZXIgPSBleHBvcnRzLmdldDtcblxuLyoqXG4gKiBTZXQgaGVhZGVyIGBmaWVsZGAgdG8gYHZhbGAsIG9yIG11bHRpcGxlIGZpZWxkcyB3aXRoIG9uZSBvYmplY3QuXG4gKiBDYXNlLWluc2Vuc2l0aXZlLlxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgICAgcmVxLmdldCgnLycpXG4gKiAgICAgICAgLnNldCgnQWNjZXB0JywgJ2FwcGxpY2F0aW9uL2pzb24nKVxuICogICAgICAgIC5zZXQoJ1gtQVBJLUtleScsICdmb29iYXInKVxuICogICAgICAgIC5lbmQoY2FsbGJhY2spO1xuICpcbiAqICAgICAgcmVxLmdldCgnLycpXG4gKiAgICAgICAgLnNldCh7IEFjY2VwdDogJ2FwcGxpY2F0aW9uL2pzb24nLCAnWC1BUEktS2V5JzogJ2Zvb2JhcicgfSlcbiAqICAgICAgICAuZW5kKGNhbGxiYWNrKTtcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R9IGZpZWxkXG4gKiBAcGFyYW0ge1N0cmluZ30gdmFsXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZXhwb3J0cy5zZXQgPSBmdW5jdGlvbihmaWVsZCwgdmFsKXtcbiAgaWYgKGlzT2JqZWN0KGZpZWxkKSkge1xuICAgIGZvciAodmFyIGtleSBpbiBmaWVsZCkge1xuICAgICAgdGhpcy5zZXQoa2V5LCBmaWVsZFtrZXldKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbiAgdGhpcy5faGVhZGVyW2ZpZWxkLnRvTG93ZXJDYXNlKCldID0gdmFsO1xuICB0aGlzLmhlYWRlcltmaWVsZF0gPSB2YWw7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBSZW1vdmUgaGVhZGVyIGBmaWVsZGAuXG4gKiBDYXNlLWluc2Vuc2l0aXZlLlxuICpcbiAqIEV4YW1wbGU6XG4gKlxuICogICAgICByZXEuZ2V0KCcvJylcbiAqICAgICAgICAudW5zZXQoJ1VzZXItQWdlbnQnKVxuICogICAgICAgIC5lbmQoY2FsbGJhY2spO1xuICpcbiAqIEBwYXJhbSB7U3RyaW5nfSBmaWVsZFxuICovXG5leHBvcnRzLnVuc2V0ID0gZnVuY3Rpb24oZmllbGQpe1xuICBkZWxldGUgdGhpcy5faGVhZGVyW2ZpZWxkLnRvTG93ZXJDYXNlKCldO1xuICBkZWxldGUgdGhpcy5oZWFkZXJbZmllbGRdO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogV3JpdGUgdGhlIGZpZWxkIGBuYW1lYCBhbmQgYHZhbGAgZm9yIFwibXVsdGlwYXJ0L2Zvcm0tZGF0YVwiXG4gKiByZXF1ZXN0IGJvZGllcy5cbiAqXG4gKiBgYGAganNcbiAqIHJlcXVlc3QucG9zdCgnL3VwbG9hZCcpXG4gKiAgIC5maWVsZCgnZm9vJywgJ2JhcicpXG4gKiAgIC5lbmQoY2FsbGJhY2spO1xuICogYGBgXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7U3RyaW5nfEJsb2J8RmlsZXxCdWZmZXJ8ZnMuUmVhZFN0cmVhbX0gdmFsXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fSBmb3IgY2hhaW5pbmdcbiAqIEBhcGkgcHVibGljXG4gKi9cbmV4cG9ydHMuZmllbGQgPSBmdW5jdGlvbihuYW1lLCB2YWwpIHtcbiAgdGhpcy5fZ2V0Rm9ybURhdGEoKS5hcHBlbmQobmFtZSwgdmFsKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vKipcbiAqIEFib3J0IHRoZSByZXF1ZXN0LCBhbmQgY2xlYXIgcG90ZW50aWFsIHRpbWVvdXQuXG4gKlxuICogQHJldHVybiB7UmVxdWVzdH1cbiAqIEBhcGkgcHVibGljXG4gKi9cbmV4cG9ydHMuYWJvcnQgPSBmdW5jdGlvbigpe1xuICBpZiAodGhpcy5fYWJvcnRlZCkge1xuICAgIHJldHVybiB0aGlzO1xuICB9XG4gIHRoaXMuX2Fib3J0ZWQgPSB0cnVlO1xuICB0aGlzLnhociAmJiB0aGlzLnhoci5hYm9ydCgpOyAvLyBicm93c2VyXG4gIHRoaXMucmVxICYmIHRoaXMucmVxLmFib3J0KCk7IC8vIG5vZGVcbiAgdGhpcy5jbGVhclRpbWVvdXQoKTtcbiAgdGhpcy5lbWl0KCdhYm9ydCcpO1xuICByZXR1cm4gdGhpcztcbn07XG5cbi8qKlxuICogRW5hYmxlIHRyYW5zbWlzc2lvbiBvZiBjb29raWVzIHdpdGggeC1kb21haW4gcmVxdWVzdHMuXG4gKlxuICogTm90ZSB0aGF0IGZvciB0aGlzIHRvIHdvcmsgdGhlIG9yaWdpbiBtdXN0IG5vdCBiZVxuICogdXNpbmcgXCJBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW5cIiB3aXRoIGEgd2lsZGNhcmQsXG4gKiBhbmQgYWxzbyBtdXN0IHNldCBcIkFjY2Vzcy1Db250cm9sLUFsbG93LUNyZWRlbnRpYWxzXCJcbiAqIHRvIFwidHJ1ZVwiLlxuICpcbiAqIEBhcGkgcHVibGljXG4gKi9cblxuZXhwb3J0cy53aXRoQ3JlZGVudGlhbHMgPSBmdW5jdGlvbigpe1xuICAvLyBUaGlzIGlzIGJyb3dzZXItb25seSBmdW5jdGlvbmFsaXR5LiBOb2RlIHNpZGUgaXMgbm8tb3AuXG4gIHRoaXMuX3dpdGhDcmVkZW50aWFscyA9IHRydWU7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBTZXQgdGhlIG1heCByZWRpcmVjdHMgdG8gYG5gLiBEb2VzIG5vdGluZyBpbiBicm93c2VyIFhIUiBpbXBsZW1lbnRhdGlvbi5cbiAqXG4gKiBAcGFyYW0ge051bWJlcn0gblxuICogQHJldHVybiB7UmVxdWVzdH0gZm9yIGNoYWluaW5nXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmV4cG9ydHMucmVkaXJlY3RzID0gZnVuY3Rpb24obil7XG4gIHRoaXMuX21heFJlZGlyZWN0cyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuLyoqXG4gKiBDb252ZXJ0IHRvIGEgcGxhaW4gamF2YXNjcmlwdCBvYmplY3QgKG5vdCBKU09OIHN0cmluZykgb2Ygc2NhbGFyIHByb3BlcnRpZXMuXG4gKiBOb3RlIGFzIHRoaXMgbWV0aG9kIGlzIGRlc2lnbmVkIHRvIHJldHVybiBhIHVzZWZ1bCBub24tdGhpcyB2YWx1ZSxcbiAqIGl0IGNhbm5vdCBiZSBjaGFpbmVkLlxuICpcbiAqIEByZXR1cm4ge09iamVjdH0gZGVzY3JpYmluZyBtZXRob2QsIHVybCwgYW5kIGRhdGEgb2YgdGhpcyByZXF1ZXN0XG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmV4cG9ydHMudG9KU09OID0gZnVuY3Rpb24oKXtcbiAgcmV0dXJuIHtcbiAgICBtZXRob2Q6IHRoaXMubWV0aG9kLFxuICAgIHVybDogdGhpcy51cmwsXG4gICAgZGF0YTogdGhpcy5fZGF0YSxcbiAgICBoZWFkZXJzOiB0aGlzLl9oZWFkZXJcbiAgfTtcbn07XG5cbi8qKlxuICogQ2hlY2sgaWYgYG9iamAgaXMgYSBob3N0IG9iamVjdCxcbiAqIHdlIGRvbid0IHdhbnQgdG8gc2VyaWFsaXplIHRoZXNlIDopXG4gKlxuICogVE9ETzogZnV0dXJlIHByb29mLCBtb3ZlIHRvIGNvbXBvZW50IGxhbmRcbiAqXG4gKiBAcGFyYW0ge09iamVjdH0gb2JqXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZXhwb3J0cy5faXNIb3N0ID0gZnVuY3Rpb24gX2lzSG9zdChvYmopIHtcbiAgdmFyIHN0ciA9IHt9LnRvU3RyaW5nLmNhbGwob2JqKTtcblxuICBzd2l0Y2ggKHN0cikge1xuICAgIGNhc2UgJ1tvYmplY3QgRmlsZV0nOlxuICAgIGNhc2UgJ1tvYmplY3QgQmxvYl0nOlxuICAgIGNhc2UgJ1tvYmplY3QgRm9ybURhdGFdJzpcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLyoqXG4gKiBTZW5kIGBkYXRhYCBhcyB0aGUgcmVxdWVzdCBib2R5LCBkZWZhdWx0aW5nIHRoZSBgLnR5cGUoKWAgdG8gXCJqc29uXCIgd2hlblxuICogYW4gb2JqZWN0IGlzIGdpdmVuLlxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgICAgIC8vIG1hbnVhbCBqc29uXG4gKiAgICAgICByZXF1ZXN0LnBvc3QoJy91c2VyJylcbiAqICAgICAgICAgLnR5cGUoJ2pzb24nKVxuICogICAgICAgICAuc2VuZCgne1wibmFtZVwiOlwidGpcIn0nKVxuICogICAgICAgICAuZW5kKGNhbGxiYWNrKVxuICpcbiAqICAgICAgIC8vIGF1dG8ganNvblxuICogICAgICAgcmVxdWVzdC5wb3N0KCcvdXNlcicpXG4gKiAgICAgICAgIC5zZW5kKHsgbmFtZTogJ3RqJyB9KVxuICogICAgICAgICAuZW5kKGNhbGxiYWNrKVxuICpcbiAqICAgICAgIC8vIG1hbnVhbCB4LXd3dy1mb3JtLXVybGVuY29kZWRcbiAqICAgICAgIHJlcXVlc3QucG9zdCgnL3VzZXInKVxuICogICAgICAgICAudHlwZSgnZm9ybScpXG4gKiAgICAgICAgIC5zZW5kKCduYW1lPXRqJylcbiAqICAgICAgICAgLmVuZChjYWxsYmFjaylcbiAqXG4gKiAgICAgICAvLyBhdXRvIHgtd3d3LWZvcm0tdXJsZW5jb2RlZFxuICogICAgICAgcmVxdWVzdC5wb3N0KCcvdXNlcicpXG4gKiAgICAgICAgIC50eXBlKCdmb3JtJylcbiAqICAgICAgICAgLnNlbmQoeyBuYW1lOiAndGonIH0pXG4gKiAgICAgICAgIC5lbmQoY2FsbGJhY2spXG4gKlxuICogICAgICAgLy8gZGVmYXVsdHMgdG8geC13d3ctZm9ybS11cmxlbmNvZGVkXG4gKiAgICAgIHJlcXVlc3QucG9zdCgnL3VzZXInKVxuICogICAgICAgIC5zZW5kKCduYW1lPXRvYmknKVxuICogICAgICAgIC5zZW5kKCdzcGVjaWVzPWZlcnJldCcpXG4gKiAgICAgICAgLmVuZChjYWxsYmFjaylcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ3xPYmplY3R9IGRhdGFcbiAqIEByZXR1cm4ge1JlcXVlc3R9IGZvciBjaGFpbmluZ1xuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5leHBvcnRzLnNlbmQgPSBmdW5jdGlvbihkYXRhKXtcbiAgdmFyIG9iaiA9IGlzT2JqZWN0KGRhdGEpO1xuICB2YXIgdHlwZSA9IHRoaXMuX2hlYWRlclsnY29udGVudC10eXBlJ107XG5cbiAgLy8gbWVyZ2VcbiAgaWYgKG9iaiAmJiBpc09iamVjdCh0aGlzLl9kYXRhKSkge1xuICAgIGZvciAodmFyIGtleSBpbiBkYXRhKSB7XG4gICAgICB0aGlzLl9kYXRhW2tleV0gPSBkYXRhW2tleV07XG4gICAgfVxuICB9IGVsc2UgaWYgKCdzdHJpbmcnID09IHR5cGVvZiBkYXRhKSB7XG4gICAgLy8gZGVmYXVsdCB0byB4LXd3dy1mb3JtLXVybGVuY29kZWRcbiAgICBpZiAoIXR5cGUpIHRoaXMudHlwZSgnZm9ybScpO1xuICAgIHR5cGUgPSB0aGlzLl9oZWFkZXJbJ2NvbnRlbnQtdHlwZSddO1xuICAgIGlmICgnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJyA9PSB0eXBlKSB7XG4gICAgICB0aGlzLl9kYXRhID0gdGhpcy5fZGF0YVxuICAgICAgICA/IHRoaXMuX2RhdGEgKyAnJicgKyBkYXRhXG4gICAgICAgIDogZGF0YTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fZGF0YSA9ICh0aGlzLl9kYXRhIHx8ICcnKSArIGRhdGE7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHRoaXMuX2RhdGEgPSBkYXRhO1xuICB9XG5cbiAgaWYgKCFvYmogfHwgdGhpcy5faXNIb3N0KGRhdGEpKSByZXR1cm4gdGhpcztcblxuICAvLyBkZWZhdWx0IHRvIGpzb25cbiAgaWYgKCF0eXBlKSB0aGlzLnR5cGUoJ2pzb24nKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuIiwiLy8gVGhlIG5vZGUgYW5kIGJyb3dzZXIgbW9kdWxlcyBleHBvc2UgdmVyc2lvbnMgb2YgdGhpcyB3aXRoIHRoZVxuLy8gYXBwcm9wcmlhdGUgY29uc3RydWN0b3IgZnVuY3Rpb24gYm91bmQgYXMgZmlyc3QgYXJndW1lbnRcbi8qKlxuICogSXNzdWUgYSByZXF1ZXN0OlxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgIHJlcXVlc3QoJ0dFVCcsICcvdXNlcnMnKS5lbmQoY2FsbGJhY2spXG4gKiAgICByZXF1ZXN0KCcvdXNlcnMnKS5lbmQoY2FsbGJhY2spXG4gKiAgICByZXF1ZXN0KCcvdXNlcnMnLCBjYWxsYmFjaylcbiAqXG4gKiBAcGFyYW0ge1N0cmluZ30gbWV0aG9kXG4gKiBAcGFyYW0ge1N0cmluZ3xGdW5jdGlvbn0gdXJsIG9yIGNhbGxiYWNrXG4gKiBAcmV0dXJuIHtSZXF1ZXN0fVxuICogQGFwaSBwdWJsaWNcbiAqL1xuXG5mdW5jdGlvbiByZXF1ZXN0KFJlcXVlc3RDb25zdHJ1Y3RvciwgbWV0aG9kLCB1cmwpIHtcbiAgLy8gY2FsbGJhY2tcbiAgaWYgKCdmdW5jdGlvbicgPT0gdHlwZW9mIHVybCkge1xuICAgIHJldHVybiBuZXcgUmVxdWVzdENvbnN0cnVjdG9yKCdHRVQnLCBtZXRob2QpLmVuZCh1cmwpO1xuICB9XG5cbiAgLy8gdXJsIGZpcnN0XG4gIGlmICgyID09IGFyZ3VtZW50cy5sZW5ndGgpIHtcbiAgICByZXR1cm4gbmV3IFJlcXVlc3RDb25zdHJ1Y3RvcignR0VUJywgbWV0aG9kKTtcbiAgfVxuXG4gIHJldHVybiBuZXcgUmVxdWVzdENvbnN0cnVjdG9yKG1ldGhvZCwgdXJsKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSByZXF1ZXN0O1xuIiwiXHJcbi8qKlxyXG4gKiBFeHBvc2UgYEVtaXR0ZXJgLlxyXG4gKi9cclxuXHJcbmlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJykge1xyXG4gIG1vZHVsZS5leHBvcnRzID0gRW1pdHRlcjtcclxufVxyXG5cclxuLyoqXHJcbiAqIEluaXRpYWxpemUgYSBuZXcgYEVtaXR0ZXJgLlxyXG4gKlxyXG4gKiBAYXBpIHB1YmxpY1xyXG4gKi9cclxuXHJcbmZ1bmN0aW9uIEVtaXR0ZXIob2JqKSB7XHJcbiAgaWYgKG9iaikgcmV0dXJuIG1peGluKG9iaik7XHJcbn07XHJcblxyXG4vKipcclxuICogTWl4aW4gdGhlIGVtaXR0ZXIgcHJvcGVydGllcy5cclxuICpcclxuICogQHBhcmFtIHtPYmplY3R9IG9ialxyXG4gKiBAcmV0dXJuIHtPYmplY3R9XHJcbiAqIEBhcGkgcHJpdmF0ZVxyXG4gKi9cclxuXHJcbmZ1bmN0aW9uIG1peGluKG9iaikge1xyXG4gIGZvciAodmFyIGtleSBpbiBFbWl0dGVyLnByb3RvdHlwZSkge1xyXG4gICAgb2JqW2tleV0gPSBFbWl0dGVyLnByb3RvdHlwZVtrZXldO1xyXG4gIH1cclxuICByZXR1cm4gb2JqO1xyXG59XHJcblxyXG4vKipcclxuICogTGlzdGVuIG9uIHRoZSBnaXZlbiBgZXZlbnRgIHdpdGggYGZuYC5cclxuICpcclxuICogQHBhcmFtIHtTdHJpbmd9IGV2ZW50XHJcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXHJcbiAqIEByZXR1cm4ge0VtaXR0ZXJ9XHJcbiAqIEBhcGkgcHVibGljXHJcbiAqL1xyXG5cclxuRW1pdHRlci5wcm90b3R5cGUub24gPVxyXG5FbWl0dGVyLnByb3RvdHlwZS5hZGRFdmVudExpc3RlbmVyID0gZnVuY3Rpb24oZXZlbnQsIGZuKXtcclxuICB0aGlzLl9jYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3MgfHwge307XHJcbiAgKHRoaXMuX2NhbGxiYWNrc1snJCcgKyBldmVudF0gPSB0aGlzLl9jYWxsYmFja3NbJyQnICsgZXZlbnRdIHx8IFtdKVxyXG4gICAgLnB1c2goZm4pO1xyXG4gIHJldHVybiB0aGlzO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIEFkZHMgYW4gYGV2ZW50YCBsaXN0ZW5lciB0aGF0IHdpbGwgYmUgaW52b2tlZCBhIHNpbmdsZVxyXG4gKiB0aW1lIHRoZW4gYXV0b21hdGljYWxseSByZW1vdmVkLlxyXG4gKlxyXG4gKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRcclxuICogQHBhcmFtIHtGdW5jdGlvbn0gZm5cclxuICogQHJldHVybiB7RW1pdHRlcn1cclxuICogQGFwaSBwdWJsaWNcclxuICovXHJcblxyXG5FbWl0dGVyLnByb3RvdHlwZS5vbmNlID0gZnVuY3Rpb24oZXZlbnQsIGZuKXtcclxuICBmdW5jdGlvbiBvbigpIHtcclxuICAgIHRoaXMub2ZmKGV2ZW50LCBvbik7XHJcbiAgICBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG4gIH1cclxuXHJcbiAgb24uZm4gPSBmbjtcclxuICB0aGlzLm9uKGV2ZW50LCBvbik7XHJcbiAgcmV0dXJuIHRoaXM7XHJcbn07XHJcblxyXG4vKipcclxuICogUmVtb3ZlIHRoZSBnaXZlbiBjYWxsYmFjayBmb3IgYGV2ZW50YCBvciBhbGxcclxuICogcmVnaXN0ZXJlZCBjYWxsYmFja3MuXHJcbiAqXHJcbiAqIEBwYXJhbSB7U3RyaW5nfSBldmVudFxyXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBmblxyXG4gKiBAcmV0dXJuIHtFbWl0dGVyfVxyXG4gKiBAYXBpIHB1YmxpY1xyXG4gKi9cclxuXHJcbkVtaXR0ZXIucHJvdG90eXBlLm9mZiA9XHJcbkVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID1cclxuRW1pdHRlci5wcm90b3R5cGUucmVtb3ZlQWxsTGlzdGVuZXJzID1cclxuRW1pdHRlci5wcm90b3R5cGUucmVtb3ZlRXZlbnRMaXN0ZW5lciA9IGZ1bmN0aW9uKGV2ZW50LCBmbil7XHJcbiAgdGhpcy5fY2FsbGJhY2tzID0gdGhpcy5fY2FsbGJhY2tzIHx8IHt9O1xyXG5cclxuICAvLyBhbGxcclxuICBpZiAoMCA9PSBhcmd1bWVudHMubGVuZ3RoKSB7XHJcbiAgICB0aGlzLl9jYWxsYmFja3MgPSB7fTtcclxuICAgIHJldHVybiB0aGlzO1xyXG4gIH1cclxuXHJcbiAgLy8gc3BlY2lmaWMgZXZlbnRcclxuICB2YXIgY2FsbGJhY2tzID0gdGhpcy5fY2FsbGJhY2tzWyckJyArIGV2ZW50XTtcclxuICBpZiAoIWNhbGxiYWNrcykgcmV0dXJuIHRoaXM7XHJcblxyXG4gIC8vIHJlbW92ZSBhbGwgaGFuZGxlcnNcclxuICBpZiAoMSA9PSBhcmd1bWVudHMubGVuZ3RoKSB7XHJcbiAgICBkZWxldGUgdGhpcy5fY2FsbGJhY2tzWyckJyArIGV2ZW50XTtcclxuICAgIHJldHVybiB0aGlzO1xyXG4gIH1cclxuXHJcbiAgLy8gcmVtb3ZlIHNwZWNpZmljIGhhbmRsZXJcclxuICB2YXIgY2I7XHJcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBjYWxsYmFja3MubGVuZ3RoOyBpKyspIHtcclxuICAgIGNiID0gY2FsbGJhY2tzW2ldO1xyXG4gICAgaWYgKGNiID09PSBmbiB8fCBjYi5mbiA9PT0gZm4pIHtcclxuICAgICAgY2FsbGJhY2tzLnNwbGljZShpLCAxKTtcclxuICAgICAgYnJlYWs7XHJcbiAgICB9XHJcbiAgfVxyXG4gIHJldHVybiB0aGlzO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIEVtaXQgYGV2ZW50YCB3aXRoIHRoZSBnaXZlbiBhcmdzLlxyXG4gKlxyXG4gKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRcclxuICogQHBhcmFtIHtNaXhlZH0gLi4uXHJcbiAqIEByZXR1cm4ge0VtaXR0ZXJ9XHJcbiAqL1xyXG5cclxuRW1pdHRlci5wcm90b3R5cGUuZW1pdCA9IGZ1bmN0aW9uKGV2ZW50KXtcclxuICB0aGlzLl9jYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3MgfHwge307XHJcbiAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSlcclxuICAgICwgY2FsbGJhY2tzID0gdGhpcy5fY2FsbGJhY2tzWyckJyArIGV2ZW50XTtcclxuXHJcbiAgaWYgKGNhbGxiYWNrcykge1xyXG4gICAgY2FsbGJhY2tzID0gY2FsbGJhY2tzLnNsaWNlKDApO1xyXG4gICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGNhbGxiYWNrcy5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xyXG4gICAgICBjYWxsYmFja3NbaV0uYXBwbHkodGhpcywgYXJncyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gdGhpcztcclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm4gYXJyYXkgb2YgY2FsbGJhY2tzIGZvciBgZXZlbnRgLlxyXG4gKlxyXG4gKiBAcGFyYW0ge1N0cmluZ30gZXZlbnRcclxuICogQHJldHVybiB7QXJyYXl9XHJcbiAqIEBhcGkgcHVibGljXHJcbiAqL1xyXG5cclxuRW1pdHRlci5wcm90b3R5cGUubGlzdGVuZXJzID0gZnVuY3Rpb24oZXZlbnQpe1xyXG4gIHRoaXMuX2NhbGxiYWNrcyA9IHRoaXMuX2NhbGxiYWNrcyB8fCB7fTtcclxuICByZXR1cm4gdGhpcy5fY2FsbGJhY2tzWyckJyArIGV2ZW50XSB8fCBbXTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBDaGVjayBpZiB0aGlzIGVtaXR0ZXIgaGFzIGBldmVudGAgaGFuZGxlcnMuXHJcbiAqXHJcbiAqIEBwYXJhbSB7U3RyaW5nfSBldmVudFxyXG4gKiBAcmV0dXJuIHtCb29sZWFufVxyXG4gKiBAYXBpIHB1YmxpY1xyXG4gKi9cclxuXHJcbkVtaXR0ZXIucHJvdG90eXBlLmhhc0xpc3RlbmVycyA9IGZ1bmN0aW9uKGV2ZW50KXtcclxuICByZXR1cm4gISEgdGhpcy5saXN0ZW5lcnMoZXZlbnQpLmxlbmd0aDtcclxufTtcclxuIiwiIC8qZ2xvYmFsIEpTT05FZGl0b3IqL1xuJ3VzZSBzdHJpY3QnO1xuXG53aW5kb3cuU3dhZ2dlclVpID0gQmFja2JvbmUuUm91dGVyLmV4dGVuZCh7XG5cbiAgZG9tX2lkOiAnc3dhZ2dlcl91aScsXG5cbiAgLy8gQXR0cmlidXRlc1xuICBvcHRpb25zOiBudWxsLFxuICBhcGk6IG51bGwsXG4gIGhlYWRlclZpZXc6IG51bGwsXG4gIG1haW5WaWV3OiBudWxsLFxuXG4gIC8vIFN3YWdnZXJVaSBhY2NlcHRzIGFsbCB0aGUgc2FtZSBvcHRpb25zIGFzIFN3YWdnZXJBcGlcbiAgaW5pdGlhbGl6ZTogZnVuY3Rpb24ob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gICAgaWYgKG9wdGlvbnMuZGVmYXVsdE1vZGVsUmVuZGVyaW5nICE9PSAnbW9kZWwnKSB7XG4gICAgICBvcHRpb25zLmRlZmF1bHRNb2RlbFJlbmRlcmluZyA9ICdzY2hlbWEnO1xuICAgIH1cblxuICAgIGlmICghb3B0aW9ucy5oaWdobGlnaHRTaXplVGhyZXNob2xkKSB7XG4gICAgICBvcHRpb25zLmhpZ2hsaWdodFNpemVUaHJlc2hvbGQgPSAxMDAwMDA7XG4gICAgfVxuXG4gICAgLy8gQWxsb3cgZG9tX2lkIHRvIGJlIG92ZXJyaWRkZW5cbiAgICBpZiAob3B0aW9ucy5kb21faWQpIHtcbiAgICAgIHRoaXMuZG9tX2lkID0gb3B0aW9ucy5kb21faWQ7XG4gICAgICBkZWxldGUgb3B0aW9ucy5kb21faWQ7XG4gICAgfVxuXG4gICAgaWYgKCFvcHRpb25zLnN1cHBvcnRlZFN1Ym1pdE1ldGhvZHMpe1xuICAgICAgb3B0aW9ucy5zdXBwb3J0ZWRTdWJtaXRNZXRob2RzID0gW1xuICAgICAgICAnZ2V0JyxcbiAgICAgICAgJ3B1dCcsXG4gICAgICAgICdwb3N0JyxcbiAgICAgICAgJ2RlbGV0ZScsXG4gICAgICAgICdoZWFkJyxcbiAgICAgICAgJ29wdGlvbnMnLFxuICAgICAgICAncGF0Y2gnXG4gICAgICBdO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5vYXV0aDJSZWRpcmVjdFVybCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHdpbmRvdy5vQXV0aFJlZGlyZWN0VXJsID0gb3B0aW9ucy5vYXV0aDJSZWRpcmVjdFVybDtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgYW4gZW1wdHkgZGl2IHdoaWNoIGNvbnRhaW5zIHRoZSBkb21faWRcbiAgICBpZiAoISAkKCcjJyArIHRoaXMuZG9tX2lkKS5sZW5ndGgpe1xuICAgICAgJCgnYm9keScpLmFwcGVuZCgnPGRpdiBpZD1cIicgKyB0aGlzLmRvbV9pZCArICdcIj48L2Rpdj4nKSA7XG4gICAgfVxuXG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcblxuICAgIC8vIHNldCBtYXJrZWQgb3B0aW9uc1xuICAgIG1hcmtlZC5zZXRPcHRpb25zKHtnZm06IHRydWV9KTtcblxuICAgIC8vIFNldCB0aGUgY2FsbGJhY2tzXG4gICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgIHRoaXMub3B0aW9ucy5zdWNjZXNzID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGF0LnJlbmRlcigpOyB9O1xuICAgIHRoaXMub3B0aW9ucy5wcm9ncmVzcyA9IGZ1bmN0aW9uKGQpIHsgcmV0dXJuIHRoYXQuc2hvd01lc3NhZ2UoZCk7IH07XG4gICAgdGhpcy5vcHRpb25zLmZhaWx1cmUgPSBmdW5jdGlvbihkKSB7IHJldHVybiB0aGF0Lm9uTG9hZEZhaWx1cmUoZCk7IH07XG5cbiAgICAvLyBDcmVhdGUgdmlldyB0byBoYW5kbGUgdGhlIGhlYWRlciBpbnB1dHNcbiAgICB0aGlzLmhlYWRlclZpZXcgPSBuZXcgU3dhZ2dlclVpLlZpZXdzLkhlYWRlclZpZXcoe2VsOiAkKCcjaGVhZGVyJyl9KTtcblxuICAgIC8vIEV2ZW50IGhhbmRsZXIgZm9yIHdoZW4gdGhlIGJhc2VVcmwvYXBpS2V5IGlzIGVudGVyZWQgYnkgdXNlclxuICAgIHRoaXMuaGVhZGVyVmlldy5vbigndXBkYXRlLXN3YWdnZXItdWknLCBmdW5jdGlvbihkYXRhKSB7XG4gICAgICByZXR1cm4gdGhhdC51cGRhdGVTd2FnZ2VyVWkoZGF0YSk7XG4gICAgfSk7XG5cbiAgICAvLyBKU29uIEVkaXRvciBjdXN0b20gdGhlbWluZ1xuICAgICBKU09ORWRpdG9yLmRlZmF1bHRzLmljb25saWJzLnN3YWdnZXIgPSBKU09ORWRpdG9yLkFic3RyYWN0SWNvbkxpYi5leHRlbmQoe1xuICAgICAgbWFwcGluZzoge1xuICAgICAgICBjb2xsYXBzZTogJ2NvbGxhcHNlJyxcbiAgICAgICAgZXhwYW5kOiAnZXhwYW5kJ1xuICAgICAgICB9LFxuICAgICAgaWNvbl9wcmVmaXg6ICdzd2FnZ2VyLSdcbiAgICAgIH0pO1xuXG4gIH0sXG5cbiAgLy8gU2V0IGFuIG9wdGlvbiBhZnRlciBpbml0aWFsaXppbmdcbiAgc2V0T3B0aW9uOiBmdW5jdGlvbihvcHRpb24sIHZhbHVlKSB7XG4gICAgdGhpcy5vcHRpb25zW29wdGlvbl0gPSB2YWx1ZTtcbiAgfSxcblxuICAvLyBHZXQgdGhlIHZhbHVlIG9mIGEgcHJldmlvdXNseSBzZXQgb3B0aW9uXG4gIGdldE9wdGlvbjogZnVuY3Rpb24ob3B0aW9uKSB7XG4gICAgcmV0dXJuIHRoaXMub3B0aW9uc1tvcHRpb25dO1xuICB9LFxuXG4gIC8vIEV2ZW50IGhhbmRsZXIgZm9yIHdoZW4gdXJsL2tleSBpcyByZWNlaXZlZCBmcm9tIHVzZXJcbiAgdXBkYXRlU3dhZ2dlclVpOiBmdW5jdGlvbihkYXRhKXtcbiAgICB0aGlzLm9wdGlvbnMudXJsID0gZGF0YS51cmw7XG4gICAgdGhpcy5sb2FkKCk7XG4gIH0sXG5cbiAgLy8gQ3JlYXRlIGFuIGFwaSBhbmQgcmVuZGVyXG4gIGxvYWQ6IGZ1bmN0aW9uKCl7XG4gICAgLy8gSW5pdGlhbGl6ZSB0aGUgQVBJIG9iamVjdFxuICAgIGlmICh0aGlzLm1haW5WaWV3KSB7XG4gICAgICB0aGlzLm1haW5WaWV3LmNsZWFyKCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYXV0aFZpZXcpIHtcbiAgICAgIHRoaXMuYXV0aFZpZXcucmVtb3ZlKCk7XG4gICAgfVxuICAgIHZhciB1cmwgPSB0aGlzLm9wdGlvbnMudXJsO1xuICAgIGlmICh1cmwgJiYgdXJsLmluZGV4T2YoJ2h0dHAnKSAhPT0gMCkge1xuICAgICAgdXJsID0gdGhpcy5idWlsZFVybCh3aW5kb3cubG9jYXRpb24uaHJlZi50b1N0cmluZygpLCB1cmwpO1xuICAgIH1cbiAgICBpZih0aGlzLmFwaSkge1xuICAgICAgdGhpcy5vcHRpb25zLmF1dGhvcml6YXRpb25zID0gdGhpcy5hcGkuY2xpZW50QXV0aG9yaXphdGlvbnMuYXV0aHo7XG4gICAgfVxuICAgIHRoaXMub3B0aW9ucy51cmwgPSB1cmw7XG4gICAgdGhpcy5oZWFkZXJWaWV3LnVwZGF0ZSh1cmwpO1xuXG4gICAgdGhpcy5hcGkgPSBuZXcgU3dhZ2dlckNsaWVudCh0aGlzLm9wdGlvbnMpO1xuICB9LFxuXG4gIC8vIGNvbGxhcHNlIGFsbCBzZWN0aW9uc1xuICBjb2xsYXBzZUFsbDogZnVuY3Rpb24oKXtcbiAgICBEb2NzLmNvbGxhcHNlRW5kcG9pbnRMaXN0Rm9yUmVzb3VyY2UoJycpO1xuICB9LFxuXG4gIC8vIGxpc3Qgb3BlcmF0aW9ucyBmb3IgYWxsIHNlY3Rpb25zXG4gIGxpc3RBbGw6IGZ1bmN0aW9uKCl7XG4gICAgRG9jcy5jb2xsYXBzZU9wZXJhdGlvbnNGb3JSZXNvdXJjZSgnJyk7XG4gIH0sXG5cbiAgLy8gZXhwYW5kIG9wZXJhdGlvbnMgZm9yIGFsbCBzZWN0aW9uc1xuICBleHBhbmRBbGw6IGZ1bmN0aW9uKCl7XG4gICAgRG9jcy5leHBhbmRPcGVyYXRpb25zRm9yUmVzb3VyY2UoJycpO1xuICB9LFxuXG4gIC8vIFRoaXMgaXMgYm91bmQgdG8gc3VjY2VzcyBoYW5kbGVyIGZvciBTd2FnZ2VyQXBpXG4gIC8vICBzbyBpdCBnZXRzIGNhbGxlZCB3aGVuIFN3YWdnZXJBcGkgY29tcGxldGVzIGxvYWRpbmdcbiAgcmVuZGVyOiBmdW5jdGlvbigpe1xuICAgIHZhciBhdXRoc01vZGVsO1xuICAgIHRoaXMuc2hvd01lc3NhZ2UoJ0ZpbmlzaGVkIExvYWRpbmcgUmVzb3VyY2UgSW5mb3JtYXRpb24uIFJlbmRlcmluZyBTd2FnZ2VyIFVJLi4uJyk7XG4gICAgdGhpcy5tYWluVmlldyA9IG5ldyBTd2FnZ2VyVWkuVmlld3MuTWFpblZpZXcoe1xuICAgICAgbW9kZWw6IHRoaXMuYXBpLFxuICAgICAgZWw6ICQoJyMnICsgdGhpcy5kb21faWQpLFxuICAgICAgc3dhZ2dlck9wdGlvbnM6IHRoaXMub3B0aW9ucyxcbiAgICAgIHJvdXRlcjogdGhpc1xuICAgIH0pLnJlbmRlcigpO1xuICAgIGlmICghXy5pc0VtcHR5KHRoaXMuYXBpLnNlY3VyaXR5RGVmaW5pdGlvbnMpKXtcbiAgICAgIGF1dGhzTW9kZWwgPSBfLm1hcCh0aGlzLmFwaS5zZWN1cml0eURlZmluaXRpb25zLCBmdW5jdGlvbiAoYXV0aCwgbmFtZSkge1xuICAgICAgICB2YXIgcmVzdWx0ID0ge307XG4gICAgICAgIHJlc3VsdFtuYW1lXSA9IGF1dGg7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9KTtcbiAgICAgIHRoaXMuYXV0aFZpZXcgPSBuZXcgU3dhZ2dlclVpLlZpZXdzLkF1dGhCdXR0b25WaWV3KHtcbiAgICAgICAgZGF0YTogU3dhZ2dlclVpLnV0aWxzLnBhcnNlU2VjdXJpdHlEZWZpbml0aW9ucyhhdXRoc01vZGVsKSxcbiAgICAgICAgcm91dGVyOiB0aGlzXG4gICAgICB9KTtcbiAgICAgICQoJyNhdXRoX2NvbnRhaW5lcicpLmFwcGVuZCh0aGlzLmF1dGhWaWV3LnJlbmRlcigpLmVsKTtcbiAgICB9XG4gICAgdGhpcy5zaG93TWVzc2FnZSgpO1xuICAgIHN3aXRjaCAodGhpcy5vcHRpb25zLmRvY0V4cGFuc2lvbikge1xuICAgICAgY2FzZSAnZnVsbCc6XG4gICAgICAgIHRoaXMuZXhwYW5kQWxsKCk7IGJyZWFrO1xuICAgICAgY2FzZSAnbGlzdCc6XG4gICAgICAgIHRoaXMubGlzdEFsbCgpOyBicmVhaztcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgICB0aGlzLnJlbmRlckdGTSgpO1xuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5vbkNvbXBsZXRlKXtcbiAgICAgIHRoaXMub3B0aW9ucy5vbkNvbXBsZXRlKHRoaXMuYXBpLCB0aGlzKTtcbiAgICB9XG5cbiAgICBzZXRUaW1lb3V0KERvY3Muc2hlYmFuZy5iaW5kKHRoaXMpLCAxMDApO1xuICB9LFxuXG4gIGJ1aWxkVXJsOiBmdW5jdGlvbihiYXNlLCB1cmwpe1xuICAgIGlmICh1cmwuaW5kZXhPZignLycpID09PSAwKSB7XG4gICAgICB2YXIgcGFydHMgPSBiYXNlLnNwbGl0KCcvJyk7XG4gICAgICBiYXNlID0gcGFydHNbMF0gKyAnLy8nICsgcGFydHNbMl07XG4gICAgICByZXR1cm4gYmFzZSArIHVybDtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIGVuZE9mUGF0aCA9IGJhc2UubGVuZ3RoO1xuXG4gICAgICBpZiAoYmFzZS5pbmRleE9mKCc/JykgPiAtMSl7XG4gICAgICAgIGVuZE9mUGF0aCA9IE1hdGgubWluKGVuZE9mUGF0aCwgYmFzZS5pbmRleE9mKCc/JykpO1xuICAgICAgfVxuXG4gICAgICBpZiAoYmFzZS5pbmRleE9mKCcjJykgPiAtMSl7XG4gICAgICAgIGVuZE9mUGF0aCA9IE1hdGgubWluKGVuZE9mUGF0aCwgYmFzZS5pbmRleE9mKCcjJykpO1xuICAgICAgfVxuXG4gICAgICBiYXNlID0gYmFzZS5zdWJzdHJpbmcoMCwgZW5kT2ZQYXRoKTtcblxuICAgICAgaWYgKGJhc2UuaW5kZXhPZignLycsIGJhc2UubGVuZ3RoIC0gMSApICE9PSAtMSl7XG4gICAgICAgIHJldHVybiBiYXNlICsgdXJsO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gYmFzZSArICcvJyArIHVybDtcbiAgICB9XG4gIH0sXG5cbiAgLy8gU2hvd3MgbWVzc2FnZSBvbiB0b3BiYXIgb2YgdGhlIHVpXG4gIHNob3dNZXNzYWdlOiBmdW5jdGlvbihkYXRhKXtcbiAgICBpZiAoZGF0YSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBkYXRhID0gJyc7XG4gICAgfVxuICAgIHZhciAkbXNnYmFyID0gJCgnI21lc3NhZ2UtYmFyJyk7XG4gICAgJG1zZ2Jhci5yZW1vdmVDbGFzcygnbWVzc2FnZS1mYWlsJyk7XG4gICAgJG1zZ2Jhci5hZGRDbGFzcygnbWVzc2FnZS1zdWNjZXNzJyk7XG4gICAgJG1zZ2Jhci50ZXh0KGRhdGEpO1xuICAgIGlmKHdpbmRvdy5Td2FnZ2VyVHJhbnNsYXRvcikge1xuICAgICAgd2luZG93LlN3YWdnZXJUcmFuc2xhdG9yLnRyYW5zbGF0ZSgkbXNnYmFyKTtcbiAgICB9XG4gIH0sXG5cbiAgLy8gc2hvd3MgbWVzc2FnZSBpbiByZWRcbiAgb25Mb2FkRmFpbHVyZTogZnVuY3Rpb24oZGF0YSl7XG4gICAgaWYgKGRhdGEgPT09IHVuZGVmaW5lZCkge1xuICAgICAgZGF0YSA9ICcnO1xuICAgIH1cbiAgICAkKCcjbWVzc2FnZS1iYXInKS5yZW1vdmVDbGFzcygnbWVzc2FnZS1zdWNjZXNzJyk7XG4gICAgJCgnI21lc3NhZ2UtYmFyJykuYWRkQ2xhc3MoJ21lc3NhZ2UtZmFpbCcpO1xuXG4gICAgdmFyIHZhbCA9ICQoJyNtZXNzYWdlLWJhcicpLnRleHQoZGF0YSk7XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLm9uRmFpbHVyZSkge1xuICAgICAgdGhpcy5vcHRpb25zLm9uRmFpbHVyZShkYXRhKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdmFsO1xuICB9LFxuXG4gIC8vIFJlbmRlcnMgR0ZNIGZvciBlbGVtZW50cyB3aXRoICdtYXJrZG93bicgY2xhc3NcbiAgcmVuZGVyR0ZNOiBmdW5jdGlvbigpe1xuICAgICQoJy5tYXJrZG93bicpLmVhY2goZnVuY3Rpb24oKXtcbiAgICAgICQodGhpcykuaHRtbChtYXJrZWQoJCh0aGlzKS5odG1sKCkpKTtcbiAgICB9KTtcblxuICAgICQoJy5wcm9wRGVzYycsICcubW9kZWwtc2lnbmF0dXJlIC5kZXNjcmlwdGlvbicpLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgJCh0aGlzKS5odG1sKG1hcmtlZCgkKHRoaXMpLmh0bWwoKSkpLmFkZENsYXNzKCdtYXJrZG93bicpO1xuICAgIH0pO1xuICB9XG5cbn0pO1xuXG53aW5kb3cuU3dhZ2dlclVpLlZpZXdzID0ge307XG53aW5kb3cuU3dhZ2dlclVpLk1vZGVscyA9IHt9O1xud2luZG93LlN3YWdnZXJVaS5Db2xsZWN0aW9ucyA9IHt9O1xud2luZG93LlN3YWdnZXJVaS5wYXJ0aWFscyA9IHt9O1xud2luZG93LlN3YWdnZXJVaS51dGlscyA9IHt9O1xuXG4vLyBkb24ndCBicmVhayBiYWNrd2FyZCBjb21wYXRpYmlsaXR5IHdpdGggcHJldmlvdXMgdmVyc2lvbnMgYW5kIHdhcm4gdXNlcnMgdG8gdXBncmFkZSB0aGVpciBjb2RlXG4oZnVuY3Rpb24oKXtcbiAgd2luZG93LmF1dGhvcml6YXRpb25zID0ge1xuICAgIGFkZDogZnVuY3Rpb24oKSB7XG4gICAgICB3YXJuKCdVc2luZyB3aW5kb3cuYXV0aG9yaXphdGlvbnMgaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBTd2FnZ2VyVWkuYXBpLmNsaWVudEF1dGhvcml6YXRpb25zLmFkZCgpLicpO1xuXG4gICAgICBpZiAodHlwZW9mIHdpbmRvdy5zd2FnZ2VyVWkgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3dpbmRvdy5zd2FnZ2VyVWkgaXMgbm90IGRlZmluZWQnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHdpbmRvdy5zd2FnZ2VyVWkgaW5zdGFuY2VvZiBTd2FnZ2VyVWkpIHtcbiAgICAgICAgd2luZG93LnN3YWdnZXJVaS5hcGkuY2xpZW50QXV0aG9yaXphdGlvbnMuYWRkLmFwcGx5KHdpbmRvdy5zd2FnZ2VyVWkuYXBpLmNsaWVudEF1dGhvcml6YXRpb25zLCBhcmd1bWVudHMpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcblxuICB3aW5kb3cuQXBpS2V5QXV0aG9yaXphdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHdhcm4oJ3dpbmRvdy5BcGlLZXlBdXRob3JpemF0aW9uIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgU3dhZ2dlckNsaWVudC5BcGlLZXlBdXRob3JpemF0aW9uLicpO1xuICAgIFN3YWdnZXJDbGllbnQuQXBpS2V5QXV0aG9yaXphdGlvbi5hcHBseSh3aW5kb3csIGFyZ3VtZW50cyk7XG4gIH07XG5cbiAgd2luZG93LlBhc3N3b3JkQXV0aG9yaXphdGlvbiA9IGZ1bmN0aW9uKCkge1xuICAgIHdhcm4oJ3dpbmRvdy5QYXNzd29yZEF1dGhvcml6YXRpb24gaXMgZGVwcmVjYXRlZC4gUGxlYXNlIHVzZSBTd2FnZ2VyQ2xpZW50LlBhc3N3b3JkQXV0aG9yaXphdGlvbi4nKTtcbiAgICBTd2FnZ2VyQ2xpZW50LlBhc3N3b3JkQXV0aG9yaXphdGlvbi5hcHBseSh3aW5kb3csIGFyZ3VtZW50cyk7XG4gIH07XG5cbiAgZnVuY3Rpb24gd2FybihtZXNzYWdlKSB7XG4gICAgaWYgKCdjb25zb2xlJyBpbiB3aW5kb3cgJiYgdHlwZW9mIHdpbmRvdy5jb25zb2xlLndhcm4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIGNvbnNvbGUud2FybihtZXNzYWdlKTtcbiAgICB9XG4gIH1cbn0pKCk7XG5cblxuLy8gVU1EXG4oZnVuY3Rpb24gKHJvb3QsIGZhY3RvcnkpIHtcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIC8vIEFNRC4gUmVnaXN0ZXIgYXMgYW4gYW5vbnltb3VzIG1vZHVsZS5cbiAgICAgICAgZGVmaW5lKFsnYiddLCBmdW5jdGlvbiAoYikge1xuICAgICAgICAgICAgcmV0dXJuIChyb290LlN3YWdnZXJVaSA9IGZhY3RvcnkoYikpO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jykge1xuICAgICAgICAvLyBOb2RlLiBEb2VzIG5vdCB3b3JrIHdpdGggc3RyaWN0IENvbW1vbkpTLCBidXRcbiAgICAgICAgLy8gb25seSBDb21tb25KUy1saWtlIGVudmlyb25tZW50cyB0aGF0IHN1cHBvcnQgbW9kdWxlLmV4cG9ydHMsXG4gICAgICAgIC8vIGxpa2UgTm9kZS5cbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoJ2InKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQnJvd3NlciBnbG9iYWxzXG4gICAgICAgIHJvb3QuU3dhZ2dlclVpID0gZmFjdG9yeShyb290LmIpO1xuICAgIH1cbn0odGhpcywgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBTd2FnZ2VyVWk7XG59KSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbndpbmRvdy5Td2FnZ2VyVWkudXRpbHMgPSB7XG4gICAgcGFyc2VTZWN1cml0eURlZmluaXRpb25zOiBmdW5jdGlvbiAoc2VjdXJpdHksIHNlY3VyaXR5RGVmaW5pdGlvbnMpIHtcbiAgICAgICAgdmFyIGF1dGhzID0gT2JqZWN0LmFzc2lnbih7fSwgc2VjdXJpdHlEZWZpbml0aW9ucyk7XG4gICAgICAgIHZhciBvYXV0aDJBcnIgPSBbXTtcbiAgICAgICAgdmFyIGF1dGhzQXJyID0gW107XG4gICAgICAgIHZhciBzY29wZXMgPSBbXTtcbiAgICAgICAgdmFyIHV0aWxzID0gd2luZG93LlN3YWdnZXJVaS51dGlscztcblxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoc2VjdXJpdHkpKSB7IHJldHVybiBudWxsOyB9XG5cbiAgICAgICAgc2VjdXJpdHkuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgICAgdmFyIHNpbmdsZVNlY3VyaXR5ID0ge307XG4gICAgICAgICAgICB2YXIgc2luZ2xlT2F1dGgyU2VjdXJpdHkgPSB7fTtcblxuICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIGl0ZW0pIHtcbiAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShpdGVtW2tleV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghYXV0aHNba2V5XSkgeyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBhdXRoc1trZXldID0gYXV0aHNba2V5XSB8fCB7fTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGF1dGhzW2tleV0udHlwZSA9PT0gJ29hdXRoMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZU9hdXRoMlNlY3VyaXR5W2tleV0gPSBPYmplY3QuYXNzaWduKHt9LCBhdXRoc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZU9hdXRoMlNlY3VyaXR5W2tleV0uc2NvcGVzID0gT2JqZWN0LmFzc2lnbih7fSwgYXV0aHNba2V5XS5zY29wZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaSBpbiBzaW5nbGVPYXV0aDJTZWN1cml0eVtrZXldLnNjb3Blcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpdGVtW2tleV0uaW5kZXhPZihpKSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHNpbmdsZU9hdXRoMlNlY3VyaXR5W2tleV0uc2NvcGVzW2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZU9hdXRoMlNlY3VyaXR5W2tleV0uc2NvcGVzID0gdXRpbHMucGFyc2VPYXV0aDJTY29wZXMoc2luZ2xlT2F1dGgyU2VjdXJpdHlba2V5XS5zY29wZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2NvcGVzID0gXy5tZXJnZShzY29wZXMsIHNpbmdsZU9hdXRoMlNlY3VyaXR5W2tleV0uc2NvcGVzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZVNlY3VyaXR5W2tleV0gPSBPYmplY3QuYXNzaWduKHt9LCBhdXRoc1trZXldKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpdGVtW2tleV0udHlwZSA9PT0gJ29hdXRoMicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNpbmdsZU9hdXRoMlNlY3VyaXR5W2tleV0gPSBPYmplY3QuYXNzaWduKHt9LCBpdGVtW2tleV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2luZ2xlT2F1dGgyU2VjdXJpdHlba2V5XS5zY29wZXMgPSB1dGlscy5wYXJzZU9hdXRoMlNjb3BlcyhzaW5nbGVPYXV0aDJTZWN1cml0eVtrZXldLnNjb3Blcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBzY29wZXMgPSBfLm1lcmdlKHNjb3Blcywgc2luZ2xlT2F1dGgyU2VjdXJpdHlba2V5XS5zY29wZXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2luZ2xlU2VjdXJpdHlba2V5XSA9IGl0ZW1ba2V5XTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFfLmlzRW1wdHkoc2luZ2xlU2VjdXJpdHkpKSB7XG4gICAgICAgICAgICAgICAgYXV0aHNBcnIucHVzaChzaW5nbGVTZWN1cml0eSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghXy5pc0VtcHR5KHNpbmdsZU9hdXRoMlNlY3VyaXR5KSl7XG4gICAgICAgICAgICAgICAgb2F1dGgyQXJyLnB1c2goc2luZ2xlT2F1dGgyU2VjdXJpdHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgYXV0aHMgOiBhdXRoc0FycixcbiAgICAgICAgICAgIG9hdXRoMjogb2F1dGgyQXJyLFxuICAgICAgICAgICAgc2NvcGVzOiBzY29wZXNcbiAgICAgICAgfTtcbiAgICB9LFxuXG4gICAgcGFyc2VPYXV0aDJTY29wZXM6IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIHZhciBzY29wZXMgPSBPYmplY3QuYXNzaWduKHt9LCBkYXRhKTtcbiAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICB2YXIga2V5O1xuXG4gICAgICAgIGZvciAoa2V5IGluIHNjb3Blcykge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2goe3Njb3BlOiBrZXksIGRlc2NyaXB0aW9uOiBzY29wZXNba2V5XX0pO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuXG4gICAgc2FuaXRpemU6IGZ1bmN0aW9uKGh0bWwpIHtcbiAgICAgICAgLy8gU3RyaXAgdGhlIHNjcmlwdCB0YWdzIGZyb20gdGhlIGh0bWwgYW5kIGlubGluZSBldmVuaGFuZGxlcnNcbiAgICAgICAgaHRtbCA9IGh0bWwucmVwbGFjZSgvPHNjcmlwdFxcYltePF0qKD86KD8hPFxcL3NjcmlwdD4pPFtePF0qKSo8XFwvc2NyaXB0Pi9naSwgJycpO1xuICAgICAgICBodG1sID0gaHRtbC5yZXBsYWNlKC8ob25cXHcrPVwiW15cIl0qXCIpKihvblxcdys9J1teJ10qJykqKG9uXFx3Kz1cXHcqXFwoXFx3KlxcKSkqL2dpLCAnJyk7XG5cbiAgICAgICAgcmV0dXJuIGh0bWw7XG4gICAgfVxufTsiLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5Nb2RlbHMuQXBpS2V5QXV0aE1vZGVsID0gQmFja2JvbmUuTW9kZWwuZXh0ZW5kKHtcbiAgICBkZWZhdWx0czoge1xuICAgICAgICAnaW4nOiAnJyxcbiAgICAgICAgbmFtZTogJycsXG4gICAgICAgIHRpdGxlOiAnJyxcbiAgICAgICAgdmFsdWU6ICcnXG4gICAgfSxcblxuICAgIGluaXRpYWxpemU6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5vbignY2hhbmdlJywgdGhpcy52YWxpZGF0ZSk7XG4gICAgfSxcblxuICAgIHZhbGlkYXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB2YWxpZCA9ICEhdGhpcy5nZXQoJ3ZhbHVlJyk7XG5cbiAgICAgICAgdGhpcy5zZXQoJ3ZhbGlkJywgdmFsaWQpO1xuXG4gICAgICAgIHJldHVybiB2YWxpZDtcbiAgICB9XG59KTsiLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5WaWV3cy5BcGlLZXlBdXRoVmlldyA9IEJhY2tib25lLlZpZXcuZXh0ZW5kKHsgLy8gVE9ETzogYXBwZW5kIHRoaXMgdG8gZ2xvYmFsIFN3YWdnZXJVaVxuXG4gICAgZXZlbnRzOiB7XG4gICAgICAgICdjaGFuZ2UgLmlucHV0X2FwaUtleV9lbnRyeSc6ICdhcGlLZXlDaGFuZ2UnXG4gICAgfSxcblxuICAgIHNlbGVjdG9yczoge1xuICAgICAgICBhcGlrZXlJbnB1dDogJy5pbnB1dF9hcGlLZXlfZW50cnknXG4gICAgfSxcblxuICAgIHRlbXBsYXRlOiBIYW5kbGViYXJzLnRlbXBsYXRlcy5hcGlrZXlfYXV0aCxcblxuICAgIGluaXRpYWxpemU6IGZ1bmN0aW9uKG9wdHMpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cyB8fCB7fTtcbiAgICAgICAgdGhpcy5yb3V0ZXIgPSB0aGlzLm9wdGlvbnMucm91dGVyO1xuICAgIH0sXG5cbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpe1xuICAgICAgICB0aGlzLiRlbC5odG1sKHRoaXMudGVtcGxhdGUodGhpcy5tb2RlbC50b0pTT04oKSkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBhcGlLZXlDaGFuZ2U6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciB2YWwgPSAkKGUudGFyZ2V0KS52YWwoKTtcbiAgICAgICAgaWYgKHZhbCkge1xuICAgICAgICAgICAgdGhpcy4kKHRoaXMuc2VsZWN0b3JzLmFwaWtleUlucHV0KS5yZW1vdmVDbGFzcygnZXJyb3InKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMubW9kZWwuc2V0KCd2YWx1ZScsIHZhbCk7XG4gICAgfSxcblxuICAgIGlzVmFsaWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubW9kZWwudmFsaWRhdGUoKTtcbiAgICB9LFxuXG4gICAgaGlnaGxpZ2h0SW52YWxpZDogZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICB0aGlzLiQodGhpcy5zZWxlY3RvcnMuYXBpa2V5SW5wdXQpLmFkZENsYXNzKCdlcnJvcicpO1xuICAgICAgICB9XG4gICAgfVxuXG59KTsiLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5WaWV3cy5BdXRoQnV0dG9uVmlldyA9IEJhY2tib25lLlZpZXcuZXh0ZW5kKHtcbiAgICBldmVudHM6IHtcbiAgICAgICAgJ2NsaWNrIC5hdXRob3JpemVfX2J0bic6ICdhdXRob3JpemVCdG5DbGljaydcbiAgICB9LFxuXG4gICAgdHBsczoge1xuICAgICAgICBwb3B1cDogSGFuZGxlYmFycy50ZW1wbGF0ZXMucG9wdXAsXG4gICAgICAgIGF1dGhCdG46IEhhbmRsZWJhcnMudGVtcGxhdGVzLmF1dGhfYnV0dG9uLFxuICAgICAgICBhdXRoQnRuT3BlcmF0aW9uOiBIYW5kbGViYXJzLnRlbXBsYXRlcy5hdXRoX2J1dHRvbl9vcGVyYXRpb25cbiAgICB9LFxuXG4gICAgaW5pdGlhbGl6ZTogZnVuY3Rpb24ob3B0cykge1xuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRzIHx8IHt9O1xuICAgICAgICB0aGlzLm9wdGlvbnMuZGF0YSA9IHRoaXMub3B0aW9ucy5kYXRhIHx8IHt9O1xuICAgICAgICB0aGlzLmlzT3BlcmF0aW9uID0gdGhpcy5vcHRpb25zLmlzT3BlcmF0aW9uO1xuICAgICAgICB0aGlzLm1vZGVsID0gdGhpcy5tb2RlbCB8fCB7fTtcbiAgICAgICAgdGhpcy5yb3V0ZXIgPSB0aGlzLm9wdGlvbnMucm91dGVyO1xuICAgICAgICB0aGlzLmF1dGhzID0gdGhpcy5vcHRpb25zLmRhdGEub2F1dGgyLmNvbmNhdCh0aGlzLm9wdGlvbnMuZGF0YS5hdXRocyk7XG4gICAgfSxcblxuICAgIHJlbmRlcjogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdHBsTmFtZSA9IHRoaXMuaXNPcGVyYXRpb24gPyAnYXV0aEJ0bk9wZXJhdGlvbicgOiAnYXV0aEJ0bic7XG5cbiAgICAgICAgdGhpcy4kYXV0aEVsID0gdGhpcy5yZW5kZXJBdXRocyh0aGlzLmF1dGhzKTtcbiAgICAgICAgdGhpcy4kZWwuaHRtbCh0aGlzLnRwbHNbdHBsTmFtZV0odGhpcy5tb2RlbCkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBhdXRob3JpemVCdG5DbGljazogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIGF1dGhzTW9kZWw7XG5cbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIGF1dGhzTW9kZWwgPSB7XG4gICAgICAgICAgICB0aXRsZTogJ0F2YWlsYWJsZSBhdXRob3JpemF0aW9ucycsXG4gICAgICAgICAgICBjb250ZW50OiB0aGlzLiRhdXRoRWxcbiAgICAgICAgfTtcblxuICAgICAgICAvLyBUaGUgY29udGVudCBvZiB0aGUgcG9wdXAgaXMgcmVtb3ZlZCBhbmQgYWxsIGV2ZW50cyB1bmJvdW5kIGFmdGVyIGNsaWNraW5nIHRoZSAnQ2FuY2VsJyBidXR0b24gb2YgdGhlIHBvcHVwLlxuICAgICAgICAvLyBXZSdsbCBoYXZlIHRvIHJlLXJlbmRlciB0aGUgY29udGVudHMgYmVmb3JlIGNyZWF0aW5nIGEgbmV3IHBvcHVwIHZpZXcuXG4gICAgICAgIHRoaXMucmVuZGVyKCk7XG5cbiAgICAgICAgdGhpcy5wb3B1cCA9IG5ldyBTd2FnZ2VyVWkuVmlld3MuUG9wdXBWaWV3KHttb2RlbDogYXV0aHNNb2RlbH0pO1xuICAgICAgICB0aGlzLnBvcHVwLnJlbmRlcigpO1xuICAgIH0sXG5cbiAgICByZW5kZXJBdXRoczogZnVuY3Rpb24gKGF1dGhzKSB7XG4gICAgICAgIHZhciAkZWwgPSAkKCc8ZGl2PicpO1xuICAgICAgICB2YXIgaXNMb2dvdXQgPSBmYWxzZTtcblxuICAgICAgICBhdXRocy5mb3JFYWNoKGZ1bmN0aW9uIChhdXRoKSB7XG4gICAgICAgICAgICB2YXIgYXV0aFZpZXcgPSBuZXcgU3dhZ2dlclVpLlZpZXdzLkF1dGhWaWV3KHtkYXRhOiBhdXRoLCByb3V0ZXI6IHRoaXMucm91dGVyfSk7XG4gICAgICAgICAgICB2YXIgYXV0aEVsID0gYXV0aFZpZXcucmVuZGVyKCkuZWw7XG4gICAgICAgICAgICAkZWwuYXBwZW5kKGF1dGhFbCk7XG4gICAgICAgICAgICBpZiAoYXV0aFZpZXcuaXNMb2dvdXQpIHtcbiAgICAgICAgICAgICAgICBpc0xvZ291dCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHRoaXMpO1xuXG4gICAgICAgIHRoaXMubW9kZWwuaXNMb2dvdXQgPSBpc0xvZ291dDtcblxuICAgICAgICByZXR1cm4gJGVsO1xuICAgIH1cblxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5Db2xsZWN0aW9ucy5BdXRoc0NvbGxlY3Rpb24gPSBCYWNrYm9uZS5Db2xsZWN0aW9uLmV4dGVuZCh7XG4gICAgY29uc3RydWN0b3I6IGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG5cbiAgICAgICAgYXJnc1swXSA9IHRoaXMucGFyc2UoYXJnc1swXSk7XG5cbiAgICAgICAgQmFja2JvbmUuQ29sbGVjdGlvbi5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9LFxuXG4gICAgYWRkOiBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAgICAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KG1vZGVsKSkge1xuICAgICAgICAgICAgYXJnc1swXSA9IF8ubWFwKG1vZGVsLCBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5oYW5kbGVPbmUodmFsKTtcbiAgICAgICAgICAgIH0sIHRoaXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXJnc1swXSA9IHRoaXMuaGFuZGxlT25lKG1vZGVsKTtcbiAgICAgICAgfVxuXG4gICAgICAgIEJhY2tib25lLkNvbGxlY3Rpb24ucHJvdG90eXBlLmFkZC5hcHBseSh0aGlzLCBhcmdzKTtcbiAgICB9LFxuXG4gICAgaGFuZGxlT25lOiBmdW5jdGlvbiAobW9kZWwpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG1vZGVsO1xuXG4gICAgICAgIGlmICghIChtb2RlbCBpbnN0YW5jZW9mIEJhY2tib25lLk1vZGVsKSApIHtcbiAgICAgICAgICAgIHN3aXRjaCAobW9kZWwudHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ29hdXRoMic6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IG5ldyBTd2FnZ2VyVWkuTW9kZWxzLk9hdXRoMk1vZGVsKG1vZGVsKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnYmFzaWMnOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBuZXcgU3dhZ2dlclVpLk1vZGVscy5CYXNpY0F1dGhNb2RlbChtb2RlbCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2FwaUtleSc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IG5ldyBTd2FnZ2VyVWkuTW9kZWxzLkFwaUtleUF1dGhNb2RlbChtb2RlbCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IG5ldyBCYWNrYm9uZS5Nb2RlbChtb2RlbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sXG5cbiAgICBpc1ZhbGlkOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB2YWxpZCA9IHRydWU7XG5cbiAgICAgICAgdGhpcy5tb2RlbHMuZm9yRWFjaChmdW5jdGlvbihtb2RlbCkge1xuICAgICAgICAgICAgaWYgKCFtb2RlbC52YWxpZGF0ZSgpKSB7XG4gICAgICAgICAgICAgICAgdmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHZhbGlkO1xuICAgIH0sXG5cbiAgICBpc0F1dGhvcml6ZWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubGVuZ3RoID09PSB0aGlzLndoZXJlKHsgaXNMb2dvdXQ6IHRydWUgfSkubGVuZ3RoO1xuICAgIH0sXG5cbiAgICBpc1BhcnRpYWxseUF1dGhvcml6ZWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMud2hlcmUoeyBpc0xvZ291dDogdHJ1ZSB9KS5sZW5ndGggPiAwO1xuICAgIH0sXG5cbiAgICBwYXJzZTogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgdmFyIGF1dGh6ID0ge307XG5cbiAgICAgICAgaWYodHlwZW9mIHdpbmRvdy5zd2FnZ2VyVWkgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBhdXRoeiA9IE9iamVjdC5hc3NpZ24oe30sIHdpbmRvdy5zd2FnZ2VyVWkuYXBpLmNsaWVudEF1dGhvcml6YXRpb25zLmF1dGh6KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBfLm1hcChkYXRhLCBmdW5jdGlvbiAoYXV0aCwgbmFtZSkge1xuICAgICAgICAgICAgdmFyIGlzQmFzaWMgPSBhdXRoeltuYW1lXSAmJiBhdXRoLnR5cGUgPT09ICdiYXNpYycgJiYgYXV0aHpbbmFtZV0udXNlcm5hbWUgJiYgYXV0aHpbbmFtZV0ucGFzc3dvcmQ7XG5cbiAgICAgICAgICAgIF8uZXh0ZW5kKGF1dGgsIHtcbiAgICAgICAgICAgICAgICB0aXRsZTogbmFtZVxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIGlmIChhdXRoeltuYW1lXSB8fCBpc0Jhc2ljKSB7XG4gICAgICAgICAgICAgICAgXy5leHRlbmQoYXV0aCwge1xuICAgICAgICAgICAgICAgICAgICBpc0xvZ291dDogdHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IGlzQmFzaWMgPyB1bmRlZmluZWQgOiBhdXRoeltuYW1lXS52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgdXNlcm5hbWU6IGlzQmFzaWMgPyBhdXRoeltuYW1lXS51c2VybmFtZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgcGFzc3dvcmQ6IGlzQmFzaWMgPyBhdXRoeltuYW1lXS5wYXNzd29yZCA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgICAgICAgICAgdmFsaWQ6IHRydWVcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGF1dGg7XG4gICAgICAgIH0pO1xuICAgIH1cbn0pOyIsIid1c2Ugc3RyaWN0JztcblxuU3dhZ2dlclVpLlZpZXdzLkF1dGhzQ29sbGVjdGlvblZpZXcgPSBCYWNrYm9uZS5WaWV3LmV4dGVuZCh7XG5cbiAgICBpbml0aWFsaXplOiBmdW5jdGlvbihvcHRzKSB7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdHMgfHwge307XG4gICAgICAgIHRoaXMub3B0aW9ucy5kYXRhID0gdGhpcy5vcHRpb25zLmRhdGEgfHwge307XG4gICAgICAgIHRoaXMucm91dGVyID0gdGhpcy5vcHRpb25zLnJvdXRlcjtcblxuICAgICAgICB0aGlzLmNvbGxlY3Rpb24gPSBuZXcgU3dhZ2dlclVpLkNvbGxlY3Rpb25zLkF1dGhzQ29sbGVjdGlvbihvcHRzLmRhdGEpO1xuXG4gICAgICAgIHRoaXMuJGlubmVyRWwgPSAkKCc8ZGl2PicpO1xuICAgICAgICB0aGlzLmF1dGhWaWV3cyA9IFtdO1xuICAgIH0sXG5cbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5jb2xsZWN0aW9uLmVhY2goZnVuY3Rpb24gKGF1dGgpIHtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyT25lQXV0aChhdXRoKTtcbiAgICAgICAgfSwgdGhpcyk7XG5cbiAgICAgICAgdGhpcy4kZWwuaHRtbCh0aGlzLiRpbm5lckVsLmh0bWwoKSA/IHRoaXMuJGlubmVyRWwgOiAnJyk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIHJlbmRlck9uZUF1dGg6IGZ1bmN0aW9uIChhdXRoTW9kZWwpIHtcbiAgICAgICAgdmFyIGF1dGhWaWV3RWwsIGF1dGhWaWV3LCBhdXRoVmlld05hbWU7XG4gICAgICAgIHZhciB0eXBlID0gYXV0aE1vZGVsLmdldCgndHlwZScpO1xuXG4gICAgICAgIGlmICh0eXBlID09PSAnYXBpS2V5Jykge1xuICAgICAgICAgICAgYXV0aFZpZXdOYW1lID0gJ0FwaUtleUF1dGhWaWV3JztcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnYmFzaWMnICYmIHRoaXMuJGlubmVyRWwuZmluZCgnLmJhc2ljX2F1dGhfY29udGFpbmVyJykubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBhdXRoVmlld05hbWUgPSAnQmFzaWNBdXRoVmlldyc7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ29hdXRoMicpIHtcbiAgICAgICAgICAgIGF1dGhWaWV3TmFtZSA9ICdPYXV0aDJWaWV3JztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhdXRoVmlld05hbWUpIHtcbiAgICAgICAgICAgIGF1dGhWaWV3ID0gbmV3IFN3YWdnZXJVaS5WaWV3c1thdXRoVmlld05hbWVdKHttb2RlbDogYXV0aE1vZGVsLCByb3V0ZXI6IHRoaXMucm91dGVyfSk7XG4gICAgICAgICAgICBhdXRoVmlld0VsID0gYXV0aFZpZXcucmVuZGVyKCkuZWw7XG4gICAgICAgICAgICB0aGlzLmF1dGhWaWV3cy5wdXNoKGF1dGhWaWV3KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuJGlubmVyRWwuYXBwZW5kKGF1dGhWaWV3RWwpO1xuICAgIH0sXG5cbiAgICBoaWdobGlnaHRJbnZhbGlkOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYXV0aFZpZXdzLmZvckVhY2goZnVuY3Rpb24gKHZpZXcpIHtcbiAgICAgICAgICAgIHZpZXcuaGlnaGxpZ2h0SW52YWxpZCgpO1xuICAgICAgICB9LCB0aGlzKTtcbiAgICB9XG5cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG4vKiBnbG9iYWwgcmVkaXJlY3RfdXJpOnRydWUgKi9cbi8qIGdsb2JhbCBjbGllbnRJZCAqL1xuLyogZ2xvYmFsIHNjb3BlU2VwYXJhdG9yICovXG4vKiBnbG9iYWwgYWRkaXRpb25hbFF1ZXJ5U3RyaW5nUGFyYW1zICovXG4vKiBnbG9iYWwgY2xpZW50U2VjcmV0ICovXG4vKiBnbG9iYWwgb25PQXV0aENvbXBsZXRlICovXG4vKiBnbG9iYWwgcmVhbG0gKi9cbi8qanNoaW50IHVudXNlZDpmYWxzZSovXG5cblN3YWdnZXJVaS5WaWV3cy5BdXRoVmlldyA9IEJhY2tib25lLlZpZXcuZXh0ZW5kKHtcbiAgICBldmVudHM6IHtcbiAgICAgICAgJ2NsaWNrIC5hdXRoX3N1Ym1pdF9fYnV0dG9uJzogJ2F1dGhvcml6ZUNsaWNrJyxcbiAgICAgICAgJ2NsaWNrIC5hdXRoX2xvZ291dF9fYnV0dG9uJzogJ2xvZ291dENsaWNrJ1xuICAgIH0sXG5cbiAgICB0cGxzOiB7XG4gICAgICAgIG1haW46IEhhbmRsZWJhcnMudGVtcGxhdGVzLmF1dGhfdmlld1xuICAgIH0sXG5cbiAgICBzZWxlY3RvcnM6IHtcbiAgICAgICAgaW5uZXJFbDogJy5hdXRoX2lubmVyJyxcbiAgICAgICAgYXV0aEJ0bjogJy5hdXRoX3N1Ym1pdF9fYnV0dG9uJ1xuICAgIH0sXG5cbiAgICBpbml0aWFsaXplOiBmdW5jdGlvbihvcHRzKSB7XG4gICAgICAgIHRoaXMub3B0aW9ucyA9IG9wdHMgfHwge307XG4gICAgICAgIG9wdHMuZGF0YSA9IG9wdHMuZGF0YSB8fCB7fTtcbiAgICAgICAgdGhpcy5yb3V0ZXIgPSB0aGlzLm9wdGlvbnMucm91dGVyO1xuXG4gICAgICAgIHRoaXMuYXV0aHNDb2xsZWN0aW9uVmlldyA9IG5ldyBTd2FnZ2VyVWkuVmlld3MuQXV0aHNDb2xsZWN0aW9uVmlldyh7ZGF0YTogb3B0cy5kYXRhfSk7XG5cbiAgICAgICAgdGhpcy4kZWwuaHRtbCh0aGlzLnRwbHMubWFpbih7XG4gICAgICAgICAgICBpc0xvZ291dDogdGhpcy5hdXRoc0NvbGxlY3Rpb25WaWV3LmNvbGxlY3Rpb24uaXNBdXRob3JpemVkKCksXG4gICAgICAgICAgICBpc0F1dGhvcml6ZWQ6IHRoaXMuYXV0aHNDb2xsZWN0aW9uVmlldy5jb2xsZWN0aW9uLmlzUGFydGlhbGx5QXV0aG9yaXplZCgpXG4gICAgICAgIH0pKTtcbiAgICAgICAgdGhpcy4kaW5uZXJFbCA9IHRoaXMuJCh0aGlzLnNlbGVjdG9ycy5pbm5lckVsKTtcbiAgICAgICAgdGhpcy5pc0xvZ291dCA9IHRoaXMuYXV0aHNDb2xsZWN0aW9uVmlldy5jb2xsZWN0aW9uLmlzUGFydGlhbGx5QXV0aG9yaXplZCgpO1xuICAgIH0sXG5cbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy4kaW5uZXJFbC5odG1sKHRoaXMuYXV0aHNDb2xsZWN0aW9uVmlldy5yZW5kZXIoKS5lbCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcblxuICAgIGF1dGhvcml6ZUNsaWNrOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgICAgaWYgKHRoaXMuYXV0aHNDb2xsZWN0aW9uVmlldy5jb2xsZWN0aW9uLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgdGhpcy5hdXRob3JpemUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuYXV0aHNDb2xsZWN0aW9uVmlldy5oaWdobGlnaHRJbnZhbGlkKCk7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgYXV0aG9yaXplOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuYXV0aHNDb2xsZWN0aW9uVmlldy5jb2xsZWN0aW9uLmZvckVhY2goZnVuY3Rpb24gKGF1dGgpIHtcbiAgICAgICAgICAgIHZhciBrZXlBdXRoLCBiYXNpY0F1dGg7XG4gICAgICAgICAgICB2YXIgdHlwZSA9IGF1dGguZ2V0KCd0eXBlJyk7XG5cbiAgICAgICAgICAgIGlmICh0eXBlID09PSAnYXBpS2V5Jykge1xuICAgICAgICAgICAgICAgIGtleUF1dGggPSBuZXcgU3dhZ2dlckNsaWVudC5BcGlLZXlBdXRob3JpemF0aW9uKFxuICAgICAgICAgICAgICAgICAgICBhdXRoLmdldCgnbmFtZScpLFxuICAgICAgICAgICAgICAgICAgICBhdXRoLmdldCgndmFsdWUnKSxcbiAgICAgICAgICAgICAgICAgICAgYXV0aC5nZXQoJ2luJylcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5yb3V0ZXIuYXBpLmNsaWVudEF1dGhvcml6YXRpb25zLmFkZChhdXRoLmdldCgndGl0bGUnKSwga2V5QXV0aCk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdiYXNpYycpIHtcbiAgICAgICAgICAgICAgICBiYXNpY0F1dGggPSBuZXcgU3dhZ2dlckNsaWVudC5QYXNzd29yZEF1dGhvcml6YXRpb24oYXV0aC5nZXQoJ3VzZXJuYW1lJyksIGF1dGguZ2V0KCdwYXNzd29yZCcpKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJvdXRlci5hcGkuY2xpZW50QXV0aG9yaXphdGlvbnMuYWRkKGF1dGguZ2V0KCd0aXRsZScpLCBiYXNpY0F1dGgpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnb2F1dGgyJykge1xuICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlT2F1dGgyTG9naW4oYXV0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIHRoaXMpO1xuXG4gICAgICAgIHRoaXMucm91dGVyLmxvYWQoKTtcbiAgICB9LFxuXG4gICAgbG9nb3V0Q2xpY2s6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICB0aGlzLmF1dGhzQ29sbGVjdGlvblZpZXcuY29sbGVjdGlvbi5mb3JFYWNoKGZ1bmN0aW9uIChhdXRoKSB7XG4gICAgICAgICAgICB3aW5kb3cuc3dhZ2dlclVpLmFwaS5jbGllbnRBdXRob3JpemF0aW9ucy5yZW1vdmUoYXV0aC5nZXQoJ3RpdGxlJykpO1xuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnJvdXRlci5sb2FkKCk7XG4gICAgfSxcblxuICAgIC8vIHRha2VuIGZyb20gbGliL3N3YWdnZXItb2F1dGguanNcbiAgICBoYW5kbGVPYXV0aDJMb2dpbjogZnVuY3Rpb24gKGF1dGgpIHtcbiAgICAgICAgdmFyIGhvc3QgPSB3aW5kb3cubG9jYXRpb247XG4gICAgICAgIHZhciBwYXRobmFtZSA9IGxvY2F0aW9uLnBhdGhuYW1lLnN1YnN0cmluZygwLCBsb2NhdGlvbi5wYXRobmFtZS5sYXN0SW5kZXhPZignLycpKTtcbiAgICAgICAgdmFyIGRlZmF1bHRSZWRpcmVjdFVybCA9IGhvc3QucHJvdG9jb2wgKyAnLy8nICsgaG9zdC5ob3N0ICsgcGF0aG5hbWUgKyAnL28yYy5odG1sJztcbiAgICAgICAgdmFyIHJlZGlyZWN0VXJsID0gd2luZG93Lm9BdXRoUmVkaXJlY3RVcmwgfHwgZGVmYXVsdFJlZGlyZWN0VXJsO1xuICAgICAgICB2YXIgdXJsID0gbnVsbDtcbiAgICAgICAgdmFyIHNjb3BlcyA9IF8ubWFwKGF1dGguZ2V0KCdzY29wZXMnKSwgZnVuY3Rpb24gKHNjb3BlKSB7XG4gICAgICAgICAgICBpZihzY29wZS5jaGVja2VkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNjb3BlLnNjb3BlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgdmFyIGNvbnRhaW5lciA9IHdpbmRvdy5zd2FnZ2VyVWlBdXRoIHx8ICh3aW5kb3cuc3dhZ2dlclVpQXV0aCA9IHt9KTtcbiAgICAgICAgdmFyIHN0YXRlLCBkZXRzLCBlcDtcbiAgICAgICAgY29udGFpbmVyLk9BdXRoU2NoZW1lS2V5ID0gYXV0aC5nZXQoJ3RpdGxlJyk7XG5cbiAgICAgICAgd2luZG93LmVuYWJsZWRTY29wZXMgPSBzY29wZXM7XG4gICAgICAgIHZhciBmbG93ID0gYXV0aC5nZXQoJ2Zsb3cnKTtcblxuICAgICAgICAvKipcbiAgICAgICAgICogUmV0dXJucyB0aGUgbmFtZSBvZiB0aGUgYWNjZXNzIHRva2VuIHBhcmFtZXRlciByZXR1cm5lZCBieSB0aGUgc2VydmVyLlxuICAgICAgICAgKlxuICAgICAgICAgKiBAcGFyYW0gZGV0c1xuICAgICAgICAgKiAgICAgVGhlIGF1dGhvcmlzYXRpb24gc2NoZW1lIGNvbmZpZ3VyYXRpb24uXG4gICAgICAgICAqIEByZXR1cm4gdGhlIG5hbWUgb2YgdGhlIGFjY2VzcyB0b2tlbiBwYXJhbWV0ZXJcbiAgICAgICAgICovXG4gICAgICAgIGZ1bmN0aW9uIGdldFRva2VuTmFtZShkZXRzKSB7XG4gICAgICAgICAgICByZXR1cm4gZGV0cy52ZW5kb3JFeHRlbnNpb25zWyd4LXRva2VuTmFtZSddIHx8IGRldHMudG9rZW5OYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYoYXV0aC5nZXQoJ3R5cGUnKSA9PT0gJ29hdXRoMicgJiYgZmxvdyAmJiAoZmxvdyA9PT0gJ2ltcGxpY2l0JyB8fCBmbG93ID09PSAnYWNjZXNzQ29kZScpKSB7XG4gICAgICAgICAgICBkZXRzID0gYXV0aC5hdHRyaWJ1dGVzO1xuICAgICAgICAgICAgdXJsID0gZGV0cy5hdXRob3JpemF0aW9uVXJsICsgJz9yZXNwb25zZV90eXBlPScgKyAoZmxvdyA9PT0gJ2ltcGxpY2l0JyA/ICd0b2tlbicgOiAnY29kZScpO1xuICAgICAgICAgICAgY29udGFpbmVyLnRva2VuTmFtZSA9IGdldFRva2VuTmFtZShkZXRzKSB8fCAnYWNjZXNzX3Rva2VuJztcbiAgICAgICAgICAgIGNvbnRhaW5lci50b2tlblVybCA9IChmbG93ID09PSAnYWNjZXNzQ29kZScgPyBkZXRzLnRva2VuVXJsIDogbnVsbCk7XG4gICAgICAgICAgICBzdGF0ZSA9IGNvbnRhaW5lci5PQXV0aFNjaGVtZUtleTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGF1dGguZ2V0KCd0eXBlJykgPT09ICdvYXV0aDInICYmIGZsb3cgJiYgKGZsb3cgPT09ICdhcHBsaWNhdGlvbicpKSB7XG4gICAgICAgICAgICBkZXRzID0gYXV0aC5hdHRyaWJ1dGVzO1xuICAgICAgICAgICAgY29udGFpbmVyLnRva2VuTmFtZSA9IGdldFRva2VuTmFtZShkZXRzKSB8fCAnYWNjZXNzX3Rva2VuJztcbiAgICAgICAgICAgIHRoaXMuY2xpZW50Q3JlZGVudGlhbHNGbG93KHNjb3BlcywgZGV0cywgY29udGFpbmVyLk9BdXRoU2NoZW1lS2V5KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGF1dGguZ2V0KCd0eXBlJykgPT09ICdvYXV0aDInICYmIGZsb3cgJiYgKGZsb3cgPT09ICdwYXNzd29yZCcpKSB7XG4gICAgICAgICAgICBkZXRzID0gYXV0aC5hdHRyaWJ1dGVzO1xuICAgICAgICAgICAgY29udGFpbmVyLnRva2VuTmFtZSA9IGdldFRva2VuTmFtZShkZXRzKSB8fCAnYWNjZXNzX3Rva2VuJztcbiAgICAgICAgICAgIHRoaXMucGFzc3dvcmRGbG93KHNjb3BlcywgZGV0cywgY29udGFpbmVyLk9BdXRoU2NoZW1lS2V5KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmKGF1dGguZ2V0KCdncmFudFR5cGVzJykpIHtcbiAgICAgICAgICAgIC8vIDEuMiBzdXBwb3J0XG4gICAgICAgICAgICB2YXIgbyA9IGF1dGguZ2V0KCdncmFudFR5cGVzJyk7XG4gICAgICAgICAgICBmb3IodmFyIHQgaW4gbykge1xuICAgICAgICAgICAgICAgIGlmKG8uaGFzT3duUHJvcGVydHkodCkgJiYgdCA9PT0gJ2ltcGxpY2l0Jykge1xuICAgICAgICAgICAgICAgICAgICBkZXRzID0gb1t0XTtcbiAgICAgICAgICAgICAgICAgICAgZXAgPSBkZXRzLmxvZ2luRW5kcG9pbnQudXJsO1xuICAgICAgICAgICAgICAgICAgICB1cmwgPSBkZXRzLmxvZ2luRW5kcG9pbnQudXJsICsgJz9yZXNwb25zZV90eXBlPXRva2VuJztcbiAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLnRva2VuTmFtZSA9IGdldFRva2VuTmFtZShkZXRzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoby5oYXNPd25Qcm9wZXJ0eSh0KSAmJiB0ID09PSAnYWNjZXNzQ29kZScpIHtcbiAgICAgICAgICAgICAgICAgICAgZGV0cyA9IG9bdF07XG4gICAgICAgICAgICAgICAgICAgIGVwID0gZGV0cy50b2tlblJlcXVlc3RFbmRwb2ludC51cmw7XG4gICAgICAgICAgICAgICAgICAgIHVybCA9IGRldHMudG9rZW5SZXF1ZXN0RW5kcG9pbnQudXJsICsgJz9yZXNwb25zZV90eXBlPWNvZGUnO1xuICAgICAgICAgICAgICAgICAgICBjb250YWluZXIudG9rZW5OYW1lID0gZ2V0VG9rZW5OYW1lKGRldHMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJlZGlyZWN0X3VyaSA9IHJlZGlyZWN0VXJsO1xuXG4gICAgICAgIHVybCArPSAnJnJlZGlyZWN0X3VyaT0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHJlZGlyZWN0VXJsKTtcbiAgICAgICAgdXJsICs9ICcmcmVhbG09JyArIGVuY29kZVVSSUNvbXBvbmVudChyZWFsbSk7XG4gICAgICAgIHVybCArPSAnJmNsaWVudF9pZD0nICsgZW5jb2RlVVJJQ29tcG9uZW50KGNsaWVudElkKTtcbiAgICAgICAgdXJsICs9ICcmc2NvcGU9JyArIGVuY29kZVVSSUNvbXBvbmVudChzY29wZXMuam9pbihzY29wZVNlcGFyYXRvcikpO1xuICAgICAgICB1cmwgKz0gJyZzdGF0ZT0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHN0YXRlKTtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIGFkZGl0aW9uYWxRdWVyeVN0cmluZ1BhcmFtcykge1xuICAgICAgICAgICAgdXJsICs9ICcmJyArIGtleSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudChhZGRpdGlvbmFsUXVlcnlTdHJpbmdQYXJhbXNba2V5XSk7XG4gICAgICAgIH1cblxuICAgICAgICB3aW5kb3cub3Blbih1cmwpO1xuICAgIH0sXG5cbiAgICAvLyB0YWtlbiBmcm9tIGxpYi9zd2FnZ2VyLW9hdXRoLmpzXG4gICAgY2xpZW50Q3JlZGVudGlhbHNGbG93OiBmdW5jdGlvbiAoc2NvcGVzLCBvYXV0aCwgT0F1dGhTY2hlbWVLZXkpIHtcbiAgICAgICAgdGhpcy5hY2Nlc3NUb2tlblJlcXVlc3Qoc2NvcGVzLCBvYXV0aCwgT0F1dGhTY2hlbWVLZXksICdjbGllbnRfY3JlZGVudGlhbHMnKTtcbiAgICB9LFxuXG4gICAgcGFzc3dvcmRGbG93OiBmdW5jdGlvbiAoc2NvcGVzLCBvYXV0aCwgT0F1dGhTY2hlbWVLZXkpIHtcbiAgICAgICAgdGhpcy5hY2Nlc3NUb2tlblJlcXVlc3Qoc2NvcGVzLCBvYXV0aCwgT0F1dGhTY2hlbWVLZXksICdwYXNzd29yZCcsIHtcbiAgICAgICAgICAgICd1c2VybmFtZSc6IG9hdXRoLnVzZXJuYW1lLFxuICAgICAgICAgICAgJ3Bhc3N3b3JkJzogb2F1dGgucGFzc3dvcmRcbiAgICAgICAgfSk7XG4gICAgfSxcblxuICAgIGFjY2Vzc1Rva2VuUmVxdWVzdDogZnVuY3Rpb24gKHNjb3Blcywgb2F1dGgsIE9BdXRoU2NoZW1lS2V5LCBncmFudFR5cGUsIHBhcmFtcykge1xuICAgICAgICBwYXJhbXMgPSAkLmV4dGVuZCh7fSwge1xuICAgICAgICAgICAgJ3Njb3BlJzogc2NvcGVzLmpvaW4oJyAnKSxcbiAgICAgICAgICAgICdncmFudF90eXBlJzogZ3JhbnRUeXBlXG4gICAgICAgIH0sIHBhcmFtcyk7XG5cbiAgICAgICAgdmFyIGhlYWRlcnM9IHt9O1xuXG4gICAgICAgIHN3aXRjaCAob2F1dGguY2xpZW50QXV0aGVudGljYXRpb25UeXBlKSB7XG4gICAgICAgICAgICBjYXNlICdiYXNpYyc6XG4gICAgICAgICAgICAgICAgaGVhZGVycy5BdXRob3JpemF0aW9uID0gJ0Jhc2ljICcgKyBidG9hKG9hdXRoLmNsaWVudElkICsgJzonICsgb2F1dGguY2xpZW50U2VjcmV0KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3JlcXVlc3QtYm9keSc6XG4gICAgICAgICAgICAgICAgcGFyYW1zLmNsaWVudF9pZCA9IG9hdXRoLmNsaWVudElkO1xuICAgICAgICAgICAgICAgIHBhcmFtcy5jbGllbnRfc2VjcmV0ID0gb2F1dGguY2xpZW50U2VjcmV0O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgJC5hamF4KHtcbiAgICAgICAgICAgIHVybCA6IG9hdXRoLnRva2VuVXJsLFxuICAgICAgICAgICAgdHlwZTogJ1BPU1QnLFxuICAgICAgICAgICAgZGF0YTogcGFyYW1zLFxuICAgICAgICAgICAgaGVhZGVyczogaGVhZGVycyxcbiAgICAgICAgICAgIHN1Y2Nlc3M6IGZ1bmN0aW9uIChkYXRhKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIG9uT0F1dGhDb21wbGV0ZShkYXRhLCBPQXV0aFNjaGVtZUtleSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXJyb3I6IGZ1bmN0aW9uICgpXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgb25PQXV0aENvbXBsZXRlKCcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5Nb2RlbHMuQmFzaWNBdXRoTW9kZWwgPSBCYWNrYm9uZS5Nb2RlbC5leHRlbmQoe1xuICAgIGRlZmF1bHRzOiB7XG4gICAgICAgIHVzZXJuYW1lOiAnJyxcbiAgICAgICAgcGFzc3dvcmQ6ICcnLFxuICAgICAgICB0aXRsZTogJ2Jhc2ljJ1xuICAgIH0sXG5cbiAgICBpbml0aWFsaXplOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMub24oJ2NoYW5nZScsIHRoaXMudmFsaWRhdGUpO1xuICAgIH0sXG5cbiAgICB2YWxpZGF0ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgdmFsaWQgPSAhIXRoaXMuZ2V0KCdwYXNzd29yZCcpICYmICEhdGhpcy5nZXQoJ3VzZXJuYW1lJyk7XG5cbiAgICAgICAgdGhpcy5zZXQoJ3ZhbGlkJywgdmFsaWQpO1xuXG4gICAgICAgIHJldHVybiB2YWxpZDtcbiAgICB9XG59KTsiLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5WaWV3cy5CYXNpY0F1dGhWaWV3ID0gQmFja2JvbmUuVmlldy5leHRlbmQoe1xuXG4gICAgaW5pdGlhbGl6ZTogZnVuY3Rpb24gKG9wdHMpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zID0gb3B0cyB8fCB7fTtcbiAgICAgICAgdGhpcy5yb3V0ZXIgPSB0aGlzLm9wdGlvbnMucm91dGVyO1xuICAgIH0sXG5cbiAgICBldmVudHM6IHtcbiAgICAgICAgJ2NoYW5nZSAuYXV0aF9pbnB1dCc6ICdpbnB1dENoYW5nZSdcbiAgICB9LFxuXG4gICAgc2VsZWN0b3JzOiB7XG4gICAgICAgIHVzZXJuYW1lSW5wdXQ6ICcuYmFzaWNfYXV0aF9fdXNlcm5hbWUnLFxuICAgICAgICBwYXNzd29yZElucHV0OiAnLmJhc2ljX2F1dGhfX3Bhc3N3b3JkJ1xuICAgIH0sXG5cbiAgICBjbHM6IHtcbiAgICAgICAgZXJyb3I6ICdlcnJvcidcbiAgICB9LFxuXG4gICAgdGVtcGxhdGU6IEhhbmRsZWJhcnMudGVtcGxhdGVzLmJhc2ljX2F1dGgsXG5cbiAgICByZW5kZXI6IGZ1bmN0aW9uKCl7XG4gICAgICAgICQodGhpcy5lbCkuaHRtbCh0aGlzLnRlbXBsYXRlKHRoaXMubW9kZWwudG9KU09OKCkpKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgaW5wdXRDaGFuZ2U6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciAkZWwgPSAkKGUudGFyZ2V0KTtcbiAgICAgICAgdmFyIHZhbCA9ICRlbC52YWwoKTtcbiAgICAgICAgdmFyIGF0dHIgPSAkZWwucHJvcCgnbmFtZScpO1xuXG4gICAgICAgIGlmICh2YWwpIHtcbiAgICAgICAgICAgICRlbC5yZW1vdmVDbGFzcyh0aGlzLmNscy5lcnJvcik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLm1vZGVsLnNldChhdHRyLCB2YWwpO1xuICAgIH0sXG5cbiAgICBpc1ZhbGlkOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1vZGVsLnZhbGlkYXRlKCk7XG4gICAgfSxcblxuICAgIGhpZ2hsaWdodEludmFsaWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1vZGVsLmdldCgndXNlcm5hbWUnKSkge1xuICAgICAgICAgICAgdGhpcy4kKHRoaXMuc2VsZWN0b3JzLnVzZXJuYW1lSW5wdXQpLmFkZENsYXNzKHRoaXMuY2xzLmVycm9yKTtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5Td2FnZ2VyVWkuVmlld3MuQ29udGVudFR5cGVWaWV3ID0gQmFja2JvbmUuVmlldy5leHRlbmQoe1xuICBpbml0aWFsaXplOiBmdW5jdGlvbigpIHt9LFxuXG4gIHJlbmRlcjogZnVuY3Rpb24oKXtcbiAgXHR0aGlzLm1vZGVsLmNvbnRlbnRUeXBlSWQgPSAnY3QnICsgTWF0aC5yYW5kb20oKTtcbiAgICAkKHRoaXMuZWwpLmh0bWwoSGFuZGxlYmFycy50ZW1wbGF0ZXMuY29udGVudF90eXBlKHRoaXMubW9kZWwpKTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxufSk7IiwiJ3VzZSBzdHJpY3QnO1xuXG5Td2FnZ2VyVWkuVmlld3MuSGVhZGVyVmlldyA9IEJhY2tib25lLlZpZXcuZXh0ZW5kKHtcbiAgZXZlbnRzOiB7XG4gICAgJ2NsaWNrICNzaG93LXBldC1zdG9yZS1pY29uJyAgICA6ICdzaG93UGV0U3RvcmUnLFxuICAgICdjbGljayAjZXhwbG9yZScgICAgICAgICAgICAgICAgOiAnc2hvd0N1c3RvbScsXG4gICAgJ3N1Ym1pdCAjYXBpX3NlbGVjdG9yJyAgICAgICAgICA6ICdzaG93Q3VzdG9tJyxcbiAgICAna2V5dXAgI2lucHV0X2Jhc2VVcmwnICAgICAgICAgIDogJ3Nob3dDdXN0b21PbktleXVwJyxcbiAgICAna2V5dXAgI2lucHV0X2FwaUtleScgICAgICAgICAgIDogJ3Nob3dDdXN0b21PbktleXVwJ1xuICB9LFxuXG4gIGluaXRpYWxpemU6IGZ1bmN0aW9uKCl7fSxcblxuICBzaG93UGV0U3RvcmU6IGZ1bmN0aW9uKCl7XG4gICAgdGhpcy50cmlnZ2VyKCd1cGRhdGUtc3dhZ2dlci11aScsIHtcbiAgICAgIHVybDonaHR0cDovL3BldHN0b3JlLnN3YWdnZXIuaW8vdjIvc3dhZ2dlci5qc29uJ1xuICAgIH0pO1xuICB9LFxuXG4gIHNob3dDdXN0b21PbktleXVwOiBmdW5jdGlvbihlKXtcbiAgICBpZiAoZS5rZXlDb2RlID09PSAxMykge1xuICAgICAgdGhpcy5zaG93Q3VzdG9tKCk7XG4gICAgfVxuICB9LFxuXG4gIHNob3dDdXN0b206IGZ1bmN0aW9uKGUpe1xuICAgIGlmIChlKSB7XG4gICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuXG4gICAgdGhpcy50cmlnZ2VyKCd1cGRhdGUtc3dhZ2dlci11aScsIHtcbiAgICAgIHVybDogJCgnI2lucHV0X2Jhc2VVcmwnKS52YWwoKVxuICAgIH0pO1xuICB9LFxuXG4gIHVwZGF0ZTogZnVuY3Rpb24odXJsLCBhcGlLZXksIHRyaWdnZXIpe1xuICAgIGlmICh0cmlnZ2VyID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHRyaWdnZXIgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAkKCcjaW5wdXRfYmFzZVVybCcpLnZhbCh1cmwpO1xuXG4gICAgaWYgKHRyaWdnZXIpIHtcbiAgICAgIHRoaXMudHJpZ2dlcigndXBkYXRlLXN3YWdnZXItdWknLCB7dXJsOnVybH0pO1xuICAgIH1cbiAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5WaWV3cy5NYWluVmlldyA9IEJhY2tib25lLlZpZXcuZXh0ZW5kKHtcbiAgYXBpc1NvcnRlciA6IHtcbiAgICBhbHBoYSAgIDogZnVuY3Rpb24oYSxiKXsgcmV0dXJuIGEubmFtZS5sb2NhbGVDb21wYXJlKGIubmFtZSk7IH1cbiAgfSxcbiAgb3BlcmF0aW9uc1NvcnRlcnMgOiB7XG4gICAgYWxwaGEgICA6IGZ1bmN0aW9uKGEsYil7IHJldHVybiBhLnBhdGgubG9jYWxlQ29tcGFyZShiLnBhdGgpOyB9LFxuICAgIG1ldGhvZCAgOiBmdW5jdGlvbihhLGIpeyByZXR1cm4gYS5tZXRob2QubG9jYWxlQ29tcGFyZShiLm1ldGhvZCk7IH1cbiAgfSxcbiAgaW5pdGlhbGl6ZTogZnVuY3Rpb24ob3B0cyl7XG4gICAgdmFyIHNvcnRlck9wdGlvbiwgc29ydGVyRm4sIGtleSwgdmFsdWU7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG5cbiAgICB0aGlzLnJvdXRlciA9IG9wdHMucm91dGVyO1xuXG4gICAgLy8gU29ydCBBUElzXG4gICAgaWYgKG9wdHMuc3dhZ2dlck9wdGlvbnMuYXBpc1NvcnRlcikge1xuICAgICAgc29ydGVyT3B0aW9uID0gb3B0cy5zd2FnZ2VyT3B0aW9ucy5hcGlzU29ydGVyO1xuICAgICAgaWYgKF8uaXNGdW5jdGlvbihzb3J0ZXJPcHRpb24pKSB7XG4gICAgICAgIHNvcnRlckZuID0gc29ydGVyT3B0aW9uO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc29ydGVyRm4gPSB0aGlzLmFwaXNTb3J0ZXJbc29ydGVyT3B0aW9uXTtcbiAgICAgIH1cbiAgICAgIGlmIChfLmlzRnVuY3Rpb24oc29ydGVyRm4pKSB7XG4gICAgICAgIHRoaXMubW9kZWwuYXBpc0FycmF5LnNvcnQoc29ydGVyRm4pO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBTb3J0IG9wZXJhdGlvbnMgb2YgZWFjaCBBUElcbiAgICBpZiAob3B0cy5zd2FnZ2VyT3B0aW9ucy5vcGVyYXRpb25zU29ydGVyKSB7XG4gICAgICBzb3J0ZXJPcHRpb24gPSBvcHRzLnN3YWdnZXJPcHRpb25zLm9wZXJhdGlvbnNTb3J0ZXI7XG4gICAgICBpZiAoXy5pc0Z1bmN0aW9uKHNvcnRlck9wdGlvbikpIHtcbiAgICAgICAgc29ydGVyRm4gPSBzb3J0ZXJPcHRpb247XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzb3J0ZXJGbiA9IHRoaXMub3BlcmF0aW9uc1NvcnRlcnNbc29ydGVyT3B0aW9uXTtcbiAgICAgIH1cbiAgICAgIGlmIChfLmlzRnVuY3Rpb24oc29ydGVyRm4pKSB7XG4gICAgICAgIGZvciAoa2V5IGluIHRoaXMubW9kZWwuYXBpc0FycmF5KSB7XG4gICAgICAgICAgdGhpcy5tb2RlbC5hcGlzQXJyYXlba2V5XS5vcGVyYXRpb25zQXJyYXkuc29ydChzb3J0ZXJGbik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBzZXQgdXAgdGhlIFVJIGZvciBpbnB1dFxuICAgIHRoaXMubW9kZWwuYXV0aHMgPSBbXTtcblxuICAgIGZvciAoa2V5IGluIHRoaXMubW9kZWwuc2VjdXJpdHlEZWZpbml0aW9ucykge1xuICAgICAgdmFsdWUgPSB0aGlzLm1vZGVsLnNlY3VyaXR5RGVmaW5pdGlvbnNba2V5XTtcblxuICAgICAgdGhpcy5tb2RlbC5hdXRocy5wdXNoKHtcbiAgICAgICAgbmFtZToga2V5LFxuICAgICAgICB0eXBlOiB2YWx1ZS50eXBlLFxuICAgICAgICB2YWx1ZTogdmFsdWVcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICgndmFsaWRhdG9yVXJsJyBpbiBvcHRzLnN3YWdnZXJPcHRpb25zKSB7XG4gICAgICAvLyBWYWxpZGF0b3IgVVJMIHNwZWNpZmllZCBleHBsaWNpdGx5XG4gICAgICB0aGlzLm1vZGVsLnZhbGlkYXRvclVybCA9IG9wdHMuc3dhZ2dlck9wdGlvbnMudmFsaWRhdG9yVXJsO1xuICAgIH0gZWxzZSBpZiAodGhpcy5tb2RlbC51cmwuaW5kZXhPZignbG9jYWxob3N0JykgPiAwIHx8IHRoaXMubW9kZWwudXJsLmluZGV4T2YoJzEyNy4wLjAuMScpID4gMCkge1xuICAgICAgLy8gTG9jYWxob3N0IG92ZXJyaWRlXG4gICAgICB0aGlzLm1vZGVsLnZhbGlkYXRvclVybCA9IG51bGw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubW9kZWwudmFsaWRhdG9yVXJsID0gJy8vb25saW5lLnN3YWdnZXIuaW8vdmFsaWRhdG9yJztcbiAgICB9XG5cbiAgICAvLyBKU29uRWRpdG9yIHJlcXVpcmVzIHR5cGU9J29iamVjdCcgdG8gYmUgcHJlc2VudCBvbiBkZWZpbmVkIHR5cGVzLCB3ZSBhZGQgaXQgaWYgaXQncyBtaXNzaW5nXG4gICAgLy8gaXMgdGhlcmUgYW55IHZhbGlkIGNhc2Ugd2VyZSBpdCBzaG91bGQgbm90IGJlIGFkZGVkID9cbiAgICB2YXIgZGVmO1xuICAgIGZvcihkZWYgaW4gdGhpcy5tb2RlbC5kZWZpbml0aW9ucyl7XG4gICAgICBpZiAoIXRoaXMubW9kZWwuZGVmaW5pdGlvbnNbZGVmXS50eXBlKXtcbiAgICAgICAgdGhpcy5tb2RlbC5kZWZpbml0aW9uc1tkZWZdLnR5cGUgPSAnb2JqZWN0JztcbiAgICAgIH1cbiAgICB9XG5cbiAgfSxcblxuICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAkKHRoaXMuZWwpLmh0bWwoSGFuZGxlYmFycy50ZW1wbGF0ZXMubWFpbih0aGlzLm1vZGVsKSk7XG4gICAgdGhpcy5pbmZvID0gdGhpcy4kKCcuaW5mbycpWzBdO1xuXG4gICAgaWYgKHRoaXMuaW5mbykge1xuICAgICAgdGhpcy5pbmZvLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgdGhpcy5vbkxpbmtDbGljaywgdHJ1ZSk7XG4gICAgfVxuXG4gICAgdGhpcy5tb2RlbC5zZWN1cml0eURlZmluaXRpb25zID0gdGhpcy5tb2RlbC5zZWN1cml0eURlZmluaXRpb25zIHx8IHt9O1xuXG4gICAgLy8gUmVuZGVyIGVhY2ggcmVzb3VyY2VcblxuICAgIHZhciByZXNvdXJjZXMgPSB7fTtcbiAgICB2YXIgY291bnRlciA9IDA7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGlzLm1vZGVsLmFwaXNBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHJlc291cmNlID0gdGhpcy5tb2RlbC5hcGlzQXJyYXlbaV07XG4gICAgICB2YXIgaWQgPSByZXNvdXJjZS5uYW1lO1xuICAgICAgd2hpbGUgKHR5cGVvZiByZXNvdXJjZXNbaWRdICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICBpZCA9IGlkICsgJ18nICsgY291bnRlcjtcbiAgICAgICAgY291bnRlciArPSAxO1xuICAgICAgfVxuICAgICAgcmVzb3VyY2UuaWQgPSBzYW5pdGl6ZUh0bWwoaWQpO1xuICAgICAgcmVzb3VyY2VzW2lkXSA9IHJlc291cmNlO1xuICAgICAgdGhpcy5hZGRSZXNvdXJjZShyZXNvdXJjZSwgdGhpcy5tb2RlbC5hdXRocyk7XG4gICAgfVxuXG4gICAgJCgnLnByb3BXcmFwJykuaG92ZXIoZnVuY3Rpb24gb25Ib3Zlcigpe1xuICAgICAgJCgnLm9wdGlvbnNXcmFwcGVyJywgJCh0aGlzKSkuc2hvdygpO1xuICAgIH0sIGZ1bmN0aW9uIG9mZmhvdmVyKCl7XG4gICAgICAkKCcub3B0aW9uc1dyYXBwZXInLCAkKHRoaXMpKS5oaWRlKCk7XG4gICAgfSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG5cbiAgYWRkUmVzb3VyY2U6IGZ1bmN0aW9uKHJlc291cmNlLCBhdXRocyl7XG4gICAgLy8gUmVuZGVyIGEgcmVzb3VyY2UgYW5kIGFkZCBpdCB0byByZXNvdXJjZXMgbGlcbiAgICByZXNvdXJjZS5pZCA9IHJlc291cmNlLmlkLnJlcGxhY2UoL1teYS16QS1aXFxkXS9nLCBmdW5jdGlvbihzdHIpIHsgcmV0dXJuIHN0ci5jaGFyQ29kZUF0KDApOyB9KTtcblxuICAgIC8vIE1ha2UgYWxsIGRlZmluaXRpb25zIGF2YWlsYWJsZSBhdCB0aGUgcm9vdCBvZiB0aGUgcmVzb3VyY2Ugc28gdGhhdCB0aGV5IGNhblxuICAgIC8vIGJlIGxvYWRlZCBieSB0aGUgSlNvbkVkaXRvclxuICAgIHJlc291cmNlLmRlZmluaXRpb25zID0gdGhpcy5tb2RlbC5kZWZpbml0aW9ucztcblxuICAgIHZhciByZXNvdXJjZVZpZXcgPSBuZXcgU3dhZ2dlclVpLlZpZXdzLlJlc291cmNlVmlldyh7XG4gICAgICBtb2RlbDogcmVzb3VyY2UsXG4gICAgICByb3V0ZXI6IHRoaXMucm91dGVyLFxuICAgICAgdGFnTmFtZTogJ2xpJyxcbiAgICAgIGlkOiAncmVzb3VyY2VfJyArIHJlc291cmNlLmlkLFxuICAgICAgY2xhc3NOYW1lOiAncmVzb3VyY2UnLFxuICAgICAgYXV0aHM6IGF1dGhzLFxuICAgICAgc3dhZ2dlck9wdGlvbnM6IHRoaXMub3B0aW9ucy5zd2FnZ2VyT3B0aW9uc1xuICAgIH0pO1xuICAgICQoJyNyZXNvdXJjZXMnLCB0aGlzLmVsKS5hcHBlbmQocmVzb3VyY2VWaWV3LnJlbmRlcigpLmVsKTtcbiAgfSxcblxuICBjbGVhcjogZnVuY3Rpb24oKXtcbiAgICAkKHRoaXMuZWwpLmh0bWwoJycpO1xuICB9LFxuXG4gIG9uTGlua0NsaWNrOiBmdW5jdGlvbiAoZSkge1xuICAgIHZhciBlbCA9IGUudGFyZ2V0O1xuXG4gICAgaWYgKGVsLnRhZ05hbWUgPT09ICdBJyAmJiBlbC5ocmVmICYmICFlbC50YXJnZXQpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB3aW5kb3cub3BlbihlbC5ocmVmLCAnX2JsYW5rJyk7XG4gICAgfVxuICB9XG59KTtcbiIsIid1c2Ugc3RyaWN0JztcblxuU3dhZ2dlclVpLk1vZGVscy5PYXV0aDJNb2RlbCA9IEJhY2tib25lLk1vZGVsLmV4dGVuZCh7XG4gICAgZGVmYXVsdHM6IHtcbiAgICAgICAgc2NvcGVzOiB7fSxcbiAgICAgICAgaXNQYXNzd29yZEZsb3c6IGZhbHNlLFxuICAgICAgICBjbGllbnRBdXRoZW50aWNhdGlvblR5cGU6ICdub25lJ1xuICAgIH0sXG5cbiAgICBpbml0aWFsaXplOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmKHRoaXMuYXR0cmlidXRlcyAmJiB0aGlzLmF0dHJpYnV0ZXMuc2NvcGVzKSB7XG4gICAgICAgICAgICB2YXIgYXR0cmlidXRlcyA9IF8uY2xvbmVEZWVwKHRoaXMuYXR0cmlidXRlcyk7XG4gICAgICAgICAgICB2YXIgaSwgc2NvcGVzID0gW107XG4gICAgICAgICAgICBmb3IoaSBpbiBhdHRyaWJ1dGVzLnNjb3Blcykge1xuICAgICAgICAgICAgICAgIHZhciBzY29wZSA9IGF0dHJpYnV0ZXMuc2NvcGVzW2ldO1xuICAgICAgICAgICAgICAgIGlmKHR5cGVvZiBzY29wZS5kZXNjcmlwdGlvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICAgICAgc2NvcGVzW3Njb3BlXSA9IGF0dHJpYnV0ZXMuc2NvcGVzW2ldO1xuICAgICAgICAgICAgICAgICAgICBzY29wZXMucHVzaChhdHRyaWJ1dGVzLnNjb3Blc1tpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXR0cmlidXRlcy5zY29wZXMgPSBzY29wZXM7XG4gICAgICAgICAgICB0aGlzLmF0dHJpYnV0ZXMgPSBhdHRyaWJ1dGVzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuYXR0cmlidXRlcyAmJiB0aGlzLmF0dHJpYnV0ZXMuZmxvdykge1xuICAgICAgICAgICAgdmFyIGZsb3cgPSB0aGlzLmF0dHJpYnV0ZXMuZmxvdztcbiAgICAgICAgICAgIHRoaXMuc2V0KCdpc1Bhc3N3b3JkRmxvdycsIGZsb3cgPT09ICdwYXNzd29yZCcpO1xuICAgICAgICAgICAgdGhpcy5zZXQoJ3JlcXVpcmVDbGllbnRBdXRoZW50aWNhdGlvbicsIGZsb3cgPT09ICdhcHBsaWNhdGlvbicpO1xuICAgICAgICAgICAgdGhpcy5zZXQoJ2NsaWVudEF1dGhlbnRpY2F0aW9uJywgZmxvdyA9PT0gJ3Bhc3N3b3JkJyB8fCBmbG93ID09PSAnYXBwbGljYXRpb24nKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm9uKCdjaGFuZ2UnLCB0aGlzLnZhbGlkYXRlKTtcbiAgICB9LFxuXG4gICAgc2V0U2NvcGVzOiBmdW5jdGlvbiAobmFtZSwgdmFsKSB7XG4gICAgICAgIHZhciBhdXRoID0gXy5leHRlbmQoe30sIHRoaXMuYXR0cmlidXRlcyk7XG4gICAgICAgIHZhciBpbmRleCA9IF8uZmluZEluZGV4KGF1dGguc2NvcGVzLCBmdW5jdGlvbihvKSB7XG4gICAgICAgICAgICByZXR1cm4gby5zY29wZSA9PT0gbmFtZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGF1dGguc2NvcGVzW2luZGV4XS5jaGVja2VkID0gdmFsO1xuXG4gICAgICAgIHRoaXMuc2V0KGF1dGgpO1xuICAgICAgICB0aGlzLnZhbGlkYXRlKCk7XG4gICAgfSxcblxuICAgIHZhbGlkYXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgdmFsaWQgPSBmYWxzZTtcbiAgICAgIGlmICh0aGlzLmdldCgnaXNQYXNzd29yZEZsb3cnKSAmJlxuICAgICAgICAgICghdGhpcy5nZXQoJ3VzZXJuYW1lJykpKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5nZXQoJ2NsaWVudEF1dGhlbnRpY2F0aW9uVHlwZScpIGluIFsnYmFzaWMnLCAncmVxdWVzdC1ib2R5J10gJiZcbiAgICAgICAgICAoIXRoaXMuZ2V0KCdjbGllbnRJZCcpKSkge1xuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgdmFyIHNjcCA9IHRoaXMuZ2V0KCdzY29wZXMnKTtcbiAgICAgIHZhciBpZHggPSAgXy5maW5kSW5kZXgoc2NwLCBmdW5jdGlvbiAobykge1xuICAgICAgICAgcmV0dXJuIG8uY2hlY2tlZCA9PT0gdHJ1ZTtcbiAgICAgIH0pO1xuXG4gICAgICBpZihzY3AubGVuZ3RoID4gMCAmJiBpZHggPj0gMCkge1xuICAgICAgICAgIHZhbGlkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYoc2NwLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIHZhbGlkID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXQoJ3ZhbGlkJywgdmFsaWQpO1xuXG4gICAgICByZXR1cm4gdmFsaWQ7XG4gICAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5WaWV3cy5PYXV0aDJWaWV3ID0gQmFja2JvbmUuVmlldy5leHRlbmQoe1xuICAgIGV2ZW50czoge1xuICAgICAgICAnY2hhbmdlIC5vYXV0aC1zY29wZSc6ICdzY29wZUNoYW5nZScsXG4gICAgICAgICdjaGFuZ2UgLm9hdXRoLXVzZXJuYW1lJzogJ3NldFVzZXJuYW1lJyxcbiAgICAgICAgJ2NoYW5nZSAub2F1dGgtcGFzc3dvcmQnOiAnc2V0UGFzc3dvcmQnLFxuICAgICAgICAnY2hhbmdlIC5vYXV0aC1jbGllbnQtYXV0aGVudGljYXRpb24tdHlwZSc6ICdzZXRDbGllbnRBdXRoZW50aWNhdGlvblR5cGUnLFxuICAgICAgICAnY2hhbmdlIC5vYXV0aC1jbGllbnQtaWQnOiAnc2V0Q2xpZW50SWQnLFxuICAgICAgICAnY2hhbmdlIC5vYXV0aC1jbGllbnQtc2VjcmV0JzogJ3NldENsaWVudFNlY3JldCdcbiAgICB9LFxuXG4gICAgdGVtcGxhdGU6IEhhbmRsZWJhcnMudGVtcGxhdGVzLm9hdXRoMixcblxuICAgIGNsczoge1xuICAgICAgICBlcnJvcjogJ2Vycm9yJ1xuICAgIH0sXG5cbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy4kZWwuaHRtbCh0aGlzLnRlbXBsYXRlKHRoaXMubW9kZWwudG9KU09OKCkpKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuXG4gICAgc2NvcGVDaGFuZ2U6IGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciB2YWwgPSAkKGUudGFyZ2V0KS5wcm9wKCdjaGVja2VkJyk7XG4gICAgICAgIHZhciBzY29wZSA9ICQoZS50YXJnZXQpLmRhdGEoJ3Njb3BlJyk7XG5cbiAgICAgICAgdGhpcy5tb2RlbC5zZXRTY29wZXMoc2NvcGUsIHZhbCk7XG4gICAgfSxcblxuICAgIHNldFVzZXJuYW1lOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICB2YXIgdmFsPSAkKGUudGFyZ2V0KS52YWwoKTtcbiAgICAgICAgdGhpcy5tb2RlbC5zZXQoJ3VzZXJuYW1lJywgdmFsKTtcbiAgICAgICAgaWYgKHZhbCkge1xuICAgICAgICAgICAgJChlLnRhcmdldCkucmVtb3ZlQ2xhc3ModGhpcy5jbHMuZXJyb3IpO1xuICAgICAgICB9XG4gICAgfSxcblxuICAgIHNldFBhc3N3b3JkOiBmdW5jdGlvbiAoZSkge1xuICAgICAgICB0aGlzLm1vZGVsLnNldCgncGFzc3dvcmQnLCAkKGUudGFyZ2V0KS52YWwoKSk7XG4gICAgfSxcblxuICAgIHNldENsaWVudEF1dGhlbnRpY2F0aW9uVHlwZTogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIHR5cGUgPSAkKGUudGFyZ2V0KS52YWwoKTtcbiAgICAgICAgdmFyICRlbCA9IHRoaXMuJGVsO1xuICAgICAgICB0aGlzLm1vZGVsLnNldCgnY2xpZW50QXV0aGVudGljYXRpb25UeXBlJywgdHlwZSk7XG5cbiAgICAgICAgc3dpdGNoKHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgJ25vbmUnOlxuICAgICAgICAgICAgICAgICRlbC5maW5kKCcub2F1dGgtY2xpZW50LWF1dGhlbnRpY2F0aW9uJykuaGlkZSgpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnYmFzaWMnOlxuICAgICAgICAgICAgY2FzZSAncmVxdWVzdC1ib2R5JzpcbiAgICAgICAgICAgICAgICAkZWwuZmluZCgnLm9hdXRoLWNsaWVudC1pZCcpLnJlbW92ZUNsYXNzKHRoaXMuY2xzLmVycm9yKTtcbiAgICAgICAgICAgICAgICAkZWwuZmluZCgnLm9hdXRoLWNsaWVudC1hdXRoZW50aWNhdGlvbicpLnNob3coKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBzZXRDbGllbnRJZDogZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgdmFyIHZhbCA9ICQoZS50YXJnZXQpLnZhbCgpO1xuICAgICAgICB0aGlzLm1vZGVsLnNldCgnY2xpZW50SWQnLCB2YWwpO1xuICAgICAgICBpZiAodmFsKSB7XG4gICAgICAgICAgICAkKGUudGFyZ2V0KS5yZW1vdmVDbGFzcyh0aGlzLmNscy5lcnJvcik7XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgc2V0Q2xpZW50U2VjcmV0OiBmdW5jdGlvbiAoZSkge1xuICAgICAgICB0aGlzLm1vZGVsLnNldCgnY2xpZW50U2VjcmV0JywgJChlLnRhcmdldCkudmFsKCkpO1xuICAgICAgICAkKGUudGFyZ2V0KS5yZW1vdmVDbGFzcygnZXJyb3InKTtcbiAgICB9LFxuXG4gICAgaGlnaGxpZ2h0SW52YWxpZDogZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMubW9kZWwuZ2V0KCd1c2VybmFtZScpKSB7XG4gICAgICAgICAgICB0aGlzLiRlbC5maW5kKCcub2F1dGgtdXNlcm5hbWUnKS5hZGRDbGFzcyh0aGlzLmNscy5lcnJvcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMubW9kZWwuZ2V0KCdjbGllbnRJZCcpKSB7XG4gICAgICAgICAgICB0aGlzLiRlbC5maW5kKCcub2F1dGgtY2xpZW50LWlkJykuYWRkQ2xhc3ModGhpcy5jbHMuZXJyb3IpO1xuICAgICAgICB9XG4gICAgfVxufSk7IiwiJ3VzZSBzdHJpY3QnO1xuXG5Td2FnZ2VyVWkuVmlld3MuT3BlcmF0aW9uVmlldyA9IEJhY2tib25lLlZpZXcuZXh0ZW5kKHtcbiAgaW52b2NhdGlvblVybDogbnVsbCxcblxuICBldmVudHM6IHtcbiAgICAnc3VibWl0IC5zYW5kYm94JyAgICAgICAgIDogJ3N1Ym1pdE9wZXJhdGlvbicsXG4gICAgJ2NsaWNrIC5zdWJtaXQnICAgICAgICAgICA6ICdzdWJtaXRPcGVyYXRpb24nLFxuICAgICdjbGljayAucmVzcG9uc2VfaGlkZXInICAgOiAnaGlkZVJlc3BvbnNlJyxcbiAgICAnY2xpY2sgLnRvZ2dsZU9wZXJhdGlvbicgIDogJ3RvZ2dsZU9wZXJhdGlvbkNvbnRlbnQnLFxuICAgICdtb3VzZWVudGVyIC5hcGktaWMnICAgICAgOiAnbW91c2VFbnRlcicsXG4gICAgJ2RibGNsaWNrIC5jdXJsJyAgICAgICAgICA6ICdzZWxlY3RUZXh0JyxcbiAgICAnY2hhbmdlIFtuYW1lPXJlc3BvbnNlQ29udGVudFR5cGVdJyA6ICdzaG93U25pcHBldCdcbiAgfSxcblxuICBpbml0aWFsaXplOiBmdW5jdGlvbihvcHRzKSB7XG4gICAgb3B0cyA9IG9wdHMgfHwge307XG4gICAgdGhpcy5yb3V0ZXIgPSBvcHRzLnJvdXRlcjtcbiAgICB0aGlzLmF1dGhzID0gb3B0cy5hdXRocztcbiAgICB0aGlzLnBhcmVudElkID0gdGhpcy5tb2RlbC5wYXJlbnRJZDtcbiAgICB0aGlzLm5pY2tuYW1lID0gdGhpcy5tb2RlbC5uaWNrbmFtZTtcbiAgICB0aGlzLm1vZGVsLmVuY29kZWRQYXJlbnRJZCA9IGVuY29kZVVSSUNvbXBvbmVudCh0aGlzLnBhcmVudElkKTtcblxuICAgIGlmIChvcHRzLnN3YWdnZXJPcHRpb25zKSB7XG4gICAgICB0aGlzLm1vZGVsLmRlZmF1bHRSZW5kZXJpbmcgPSBvcHRzLnN3YWdnZXJPcHRpb25zLmRlZmF1bHRNb2RlbFJlbmRlcmluZztcblxuICAgICAgaWYgKG9wdHMuc3dhZ2dlck9wdGlvbnMuc2hvd1JlcXVlc3RIZWFkZXJzKSB7XG4gICAgICAgIHRoaXMubW9kZWwuc2hvd1JlcXVlc3RIZWFkZXJzID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdHMuc3dhZ2dlck9wdGlvbnMuc2hvd09wZXJhdGlvbklkcykge1xuICAgICAgICB0aGlzLm1vZGVsLnNob3dPcGVyYXRpb25JZHMgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICBzZWxlY3RUZXh0OiBmdW5jdGlvbihldmVudCkge1xuICAgIHZhciBkb2MgPSBkb2N1bWVudCxcbiAgICAgICAgdGV4dCA9IGV2ZW50LnRhcmdldC5maXJzdENoaWxkLFxuICAgICAgICByYW5nZSxcbiAgICAgICAgc2VsZWN0aW9uO1xuICAgIGlmIChkb2MuYm9keS5jcmVhdGVUZXh0UmFuZ2UpIHtcbiAgICAgIHJhbmdlID0gZG9jdW1lbnQuYm9keS5jcmVhdGVUZXh0UmFuZ2UoKTtcbiAgICAgIHJhbmdlLm1vdmVUb0VsZW1lbnRUZXh0KHRleHQpO1xuICAgICAgcmFuZ2Uuc2VsZWN0KCk7XG4gICAgfSBlbHNlIGlmICh3aW5kb3cuZ2V0U2VsZWN0aW9uKSB7XG4gICAgICBzZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICByYW5nZSA9IGRvY3VtZW50LmNyZWF0ZVJhbmdlKCk7XG4gICAgICByYW5nZS5zZWxlY3ROb2RlQ29udGVudHModGV4dCk7XG4gICAgICBzZWxlY3Rpb24ucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgICBzZWxlY3Rpb24uYWRkUmFuZ2UocmFuZ2UpO1xuICAgIH1cbiAgfSxcblxuICBtb3VzZUVudGVyOiBmdW5jdGlvbihlKSB7XG4gICAgdmFyIGVsZW0gPSAkKHRoaXMuZWwpLmZpbmQoJy5jb250ZW50Jyk7XG4gICAgdmFyIHggPSBlLnBhZ2VYO1xuICAgIHZhciB5ID0gZS5wYWdlWTtcbiAgICB2YXIgc2NYID0gJCh3aW5kb3cpLnNjcm9sbExlZnQoKTtcbiAgICB2YXIgc2NZID0gJCh3aW5kb3cpLnNjcm9sbFRvcCgpO1xuICAgIHZhciBzY01heFggPSBzY1ggKyAkKHdpbmRvdykud2lkdGgoKTtcbiAgICB2YXIgc2NNYXhZID0gc2NZICsgJCh3aW5kb3cpLmhlaWdodCgpO1xuICAgIHZhciB3ZCA9IGVsZW0ud2lkdGgoKTtcbiAgICB2YXIgaGdoID0gZWxlbS5oZWlnaHQoKTtcblxuICAgIGlmICh4ICsgd2QgPiBzY01heFgpIHtcbiAgICAgIHggPSBzY01heFggLSB3ZDtcbiAgICB9XG5cbiAgICBpZiAoeCA8IHNjWCkge1xuICAgICAgeCA9IHNjWDtcbiAgICB9XG5cbiAgICBpZiAoeSArIGhnaCA+IHNjTWF4WSkge1xuICAgICAgeSA9IHNjTWF4WSAtIGhnaDtcbiAgICB9XG5cbiAgICBpZiAoeSA8IHNjWSkge1xuICAgICAgeSA9IHNjWTtcbiAgICB9XG5cbiAgICB2YXIgcG9zID0ge307XG4gICAgcG9zLnRvcCA9IHk7XG4gICAgcG9zLmxlZnQgPSB4O1xuICAgIGVsZW0uY3NzKHBvcyk7XG4gIH0sXG5cbiAgLy8gTm90ZTogY29waWVkIGZyb20gQ29mZmVlU2NyaXB0IGNvbXBpbGVkIGZpbGVcbiAgLy8gVE9ETzogcmVmYWN0b3JcbiAgcmVuZGVyOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgYSwgYXV0aCwgYXV0aHMsIGNvZGUsIGNvbnRlbnRUeXBlTW9kZWwsIGlzTWV0aG9kU3VibWlzc2lvblN1cHBvcnRlZCwgaywga2V5LCBsLCBsZW4sIGxlbjEsIGxlbjIsIGxlbjMsIGxlbjQsIG0sIG1vZGVsQXV0aHMsIG4sIG8sIHAsIHBhcmFtLCBxLCByZWYsIHJlZjEsIHJlZjIsIHJlZjMsIHJlZjQsIHJlZjUsIHJlc3BvbnNlQ29udGVudFR5cGVWaWV3LCByZXNwb25zZVNpZ25hdHVyZVZpZXcsIHNjaGVtYSwgc2NoZW1hT2JqLCBzY29wZUluZGV4LCBzaWduYXR1cmVNb2RlbCwgc3RhdHVzQ29kZSwgc3VjY2Vzc1Jlc3BvbnNlLCB0eXBlLCB2LCB2YWx1ZSwgcHJvZHVjZXMsIGlzWE1MLCBpc0pTT047XG4gICAgaXNNZXRob2RTdWJtaXNzaW9uU3VwcG9ydGVkID0galF1ZXJ5LmluQXJyYXkodGhpcy5tb2RlbC5tZXRob2QsIHRoaXMubW9kZWwuc3VwcG9ydGVkU3VibWl0TWV0aG9kcygpKSA+PSAwO1xuICAgIGlmICghaXNNZXRob2RTdWJtaXNzaW9uU3VwcG9ydGVkKSB7XG4gICAgICB0aGlzLm1vZGVsLmlzUmVhZE9ubHkgPSB0cnVlO1xuICAgIH1cbiAgICB0aGlzLm1vZGVsLmRlc2NyaXB0aW9uID0gdGhpcy5tb2RlbC5kZXNjcmlwdGlvbiB8fCB0aGlzLm1vZGVsLm5vdGVzO1xuICAgIHRoaXMubW9kZWwub2F1dGggPSBudWxsO1xuICAgIG1vZGVsQXV0aHMgPSB0aGlzLm1vZGVsLmF1dGhvcml6YXRpb25zIHx8IHRoaXMubW9kZWwuc2VjdXJpdHk7XG4gICAgaWYgKG1vZGVsQXV0aHMpIHtcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KG1vZGVsQXV0aHMpKSB7XG4gICAgICAgIGZvciAobCA9IDAsIGxlbiA9IG1vZGVsQXV0aHMubGVuZ3RoOyBsIDwgbGVuOyBsKyspIHtcbiAgICAgICAgICBhdXRocyA9IG1vZGVsQXV0aHNbbF07XG4gICAgICAgICAgZm9yIChrZXkgaW4gYXV0aHMpIHtcbiAgICAgICAgICAgIGZvciAoYSBpbiB0aGlzLmF1dGhzKSB7XG4gICAgICAgICAgICAgIGF1dGggPSB0aGlzLmF1dGhzW2FdO1xuICAgICAgICAgICAgICBpZiAoa2V5ID09PSBhdXRoLm5hbWUpIHtcbiAgICAgICAgICAgICAgICBpZiAoYXV0aC50eXBlID09PSAnb2F1dGgyJykge1xuICAgICAgICAgICAgICAgICAgdGhpcy5tb2RlbC5vYXV0aCA9IHt9O1xuICAgICAgICAgICAgICAgICAgdGhpcy5tb2RlbC5vYXV0aC5zY29wZXMgPSBbXTtcbiAgICAgICAgICAgICAgICAgIHJlZjEgPSBhdXRoLnZhbHVlLnNjb3BlcztcbiAgICAgICAgICAgICAgICAgIGZvciAoayBpbiByZWYxKSB7XG4gICAgICAgICAgICAgICAgICAgIHYgPSByZWYxW2tdO1xuICAgICAgICAgICAgICAgICAgICBzY29wZUluZGV4ID0gYXV0aHNba2V5XS5pbmRleE9mKGspO1xuICAgICAgICAgICAgICAgICAgICBpZiAoc2NvcGVJbmRleCA+PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgbyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlOiBrLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGVzY3JpcHRpb246IHZcbiAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgIHRoaXMubW9kZWwub2F1dGguc2NvcGVzLnB1c2gobyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAoayBpbiBtb2RlbEF1dGhzKSB7XG4gICAgICAgICAgdiA9IG1vZGVsQXV0aHNba107XG4gICAgICAgICAgaWYgKGsgPT09ICdvYXV0aDInKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5tb2RlbC5vYXV0aCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICB0aGlzLm1vZGVsLm9hdXRoID0ge307XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5tb2RlbC5vYXV0aC5zY29wZXMgPT09IHZvaWQgMCkge1xuICAgICAgICAgICAgICB0aGlzLm1vZGVsLm9hdXRoLnNjb3BlcyA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yIChtID0gMCwgbGVuMSA9IHYubGVuZ3RoOyBtIDwgbGVuMTsgbSsrKSB7XG4gICAgICAgICAgICAgIG8gPSB2W21dO1xuICAgICAgICAgICAgICB0aGlzLm1vZGVsLm9hdXRoLnNjb3Blcy5wdXNoKG8pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICBpZiAodHlwZW9mIHRoaXMubW9kZWwucmVzcG9uc2VzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5tb2RlbC5yZXNwb25zZU1lc3NhZ2VzID0gW107XG4gICAgICByZWYyID0gdGhpcy5tb2RlbC5yZXNwb25zZXM7XG4gICAgICBmb3IgKGNvZGUgaW4gcmVmMikge1xuICAgICAgICB2YWx1ZSA9IHJlZjJbY29kZV07XG4gICAgICAgIHNjaGVtYSA9IG51bGw7XG4gICAgICAgIHNjaGVtYU9iaiA9IHRoaXMubW9kZWwucmVzcG9uc2VzW2NvZGVdLnNjaGVtYTtcbiAgICAgICAgaWYgKHNjaGVtYU9iaiAmJiBzY2hlbWFPYmouJHJlZikge1xuICAgICAgICAgIHNjaGVtYSA9IHNjaGVtYU9iai4kcmVmO1xuICAgICAgICAgIGlmIChzY2hlbWEuaW5kZXhPZignIy9kZWZpbml0aW9ucy8nKSAhPT0gLTEpIHtcbiAgICAgICAgICAgIHNjaGVtYSA9IHNjaGVtYS5yZXBsYWNlKC9eLiojXFwvZGVmaW5pdGlvbnNcXC8vLCAnJyk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMubW9kZWwucmVzcG9uc2VNZXNzYWdlcy5wdXNoKHtcbiAgICAgICAgICBjb2RlOiBjb2RlLFxuICAgICAgICAgIG1lc3NhZ2U6IHZhbHVlLmRlc2NyaXB0aW9uLFxuICAgICAgICAgIHJlc3BvbnNlTW9kZWw6IHNjaGVtYSxcbiAgICAgICAgICBoZWFkZXJzOiB2YWx1ZS5oZWFkZXJzLFxuICAgICAgICAgIHNjaGVtYTogc2NoZW1hT2JqXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAodHlwZW9mIHRoaXMubW9kZWwucmVzcG9uc2VNZXNzYWdlcyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHRoaXMubW9kZWwucmVzcG9uc2VNZXNzYWdlcyA9IFtdO1xuICAgIH1cbiAgICBzaWduYXR1cmVNb2RlbCA9IG51bGw7XG4gICAgcHJvZHVjZXMgPSB0aGlzLm1vZGVsLnByb2R1Y2VzO1xuICAgIGlzWE1MID0gdGhpcy5jb250YWlucyhwcm9kdWNlcywgJ3htbCcpO1xuICAgIGlzSlNPTiA9IGlzWE1MID8gdGhpcy5jb250YWlucyhwcm9kdWNlcywgJ2pzb24nKSA6IHRydWU7XG5cbiAgICBpZiAodGhpcy5tb2RlbC5zdWNjZXNzUmVzcG9uc2UpIHtcbiAgICAgIHN1Y2Nlc3NSZXNwb25zZSA9IHRoaXMubW9kZWwuc3VjY2Vzc1Jlc3BvbnNlO1xuICAgICAgZm9yIChrZXkgaW4gc3VjY2Vzc1Jlc3BvbnNlKSB7XG4gICAgICAgIHZhbHVlID0gc3VjY2Vzc1Jlc3BvbnNlW2tleV07XG4gICAgICAgIHRoaXMubW9kZWwuc3VjY2Vzc0NvZGUgPSBrZXk7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHR5cGVvZiB2YWx1ZS5jcmVhdGVKU09OU2FtcGxlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgdGhpcy5tb2RlbC5zdWNjZXNzRGVzY3JpcHRpb24gPSB2YWx1ZS5kZXNjcmlwdGlvbjtcbiAgICAgICAgICB0aGlzLm1vZGVsLmhlYWRlcnMgPSB0aGlzLnBhcnNlUmVzcG9uc2VIZWFkZXJzKHZhbHVlLmhlYWRlcnMpO1xuICAgICAgICAgIHNpZ25hdHVyZU1vZGVsID0ge1xuICAgICAgICAgICAgc2FtcGxlSlNPTjogaXNKU09OID8gSlNPTi5zdHJpbmdpZnkoU3dhZ2dlclVpLnBhcnRpYWxzLnNpZ25hdHVyZS5jcmVhdGVKU09OU2FtcGxlKHZhbHVlKSwgdm9pZCAwLCAyKSA6IGZhbHNlLFxuICAgICAgICAgICAgaXNQYXJhbTogZmFsc2UsXG4gICAgICAgICAgICBzYW1wbGVYTUw6IGlzWE1MID8gU3dhZ2dlclVpLnBhcnRpYWxzLnNpZ25hdHVyZS5jcmVhdGVYTUxTYW1wbGUodmFsdWUubmFtZSwgdmFsdWUuZGVmaW5pdGlvbiwgdmFsdWUubW9kZWxzKSA6IGZhbHNlLFxuICAgICAgICAgICAgc2lnbmF0dXJlOiBTd2FnZ2VyVWkucGFydGlhbHMuc2lnbmF0dXJlLmdldE1vZGVsU2lnbmF0dXJlKHZhbHVlLm5hbWUsIHZhbHVlLmRlZmluaXRpb24sIHZhbHVlLm1vZGVscywgdmFsdWUubW9kZWxQcm9wZXJ0eU1hY3JvKVxuICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2lnbmF0dXJlTW9kZWwgPSB7XG4gICAgICAgICAgICBzaWduYXR1cmU6IFN3YWdnZXJVaS5wYXJ0aWFscy5zaWduYXR1cmUuZ2V0UHJpbWl0aXZlU2lnbmF0dXJlKHZhbHVlKVxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRoaXMubW9kZWwucmVzcG9uc2VDbGFzc1NpZ25hdHVyZSAmJiB0aGlzLm1vZGVsLnJlc3BvbnNlQ2xhc3NTaWduYXR1cmUgIT09ICdzdHJpbmcnKSB7XG4gICAgICBzaWduYXR1cmVNb2RlbCA9IHtcbiAgICAgICAgc2FtcGxlSlNPTjogdGhpcy5tb2RlbC5yZXNwb25zZVNhbXBsZUpTT04sXG4gICAgICAgIGlzUGFyYW06IGZhbHNlLFxuICAgICAgICBzaWduYXR1cmU6IHRoaXMubW9kZWwucmVzcG9uc2VDbGFzc1NpZ25hdHVyZVxuICAgICAgfTtcbiAgICB9XG4gICAgJCh0aGlzLmVsKS5odG1sKEhhbmRsZWJhcnMudGVtcGxhdGVzLm9wZXJhdGlvbih0aGlzLm1vZGVsKSk7XG4gICAgaWYgKHNpZ25hdHVyZU1vZGVsKSB7XG4gICAgICBzaWduYXR1cmVNb2RlbC5kZWZhdWx0UmVuZGVyaW5nID0gdGhpcy5tb2RlbC5kZWZhdWx0UmVuZGVyaW5nO1xuICAgICAgcmVzcG9uc2VTaWduYXR1cmVWaWV3ID0gbmV3IFN3YWdnZXJVaS5WaWV3cy5TaWduYXR1cmVWaWV3KHtcbiAgICAgICAgbW9kZWw6IHNpZ25hdHVyZU1vZGVsLFxuICAgICAgICByb3V0ZXI6IHRoaXMucm91dGVyLFxuICAgICAgICB0YWdOYW1lOiAnZGl2J1xuICAgICAgfSk7XG4gICAgICAkKCcubW9kZWwtc2lnbmF0dXJlJywgJCh0aGlzLmVsKSkuYXBwZW5kKHJlc3BvbnNlU2lnbmF0dXJlVmlldy5yZW5kZXIoKS5lbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubW9kZWwucmVzcG9uc2VDbGFzc1NpZ25hdHVyZSA9ICdzdHJpbmcnO1xuICAgICAgJCgnLm1vZGVsLXNpZ25hdHVyZScsICQodGhpcy5lbCkpLmh0bWwodGhpcy5tb2RlbC50eXBlKTtcbiAgICB9XG4gICAgY29udGVudFR5cGVNb2RlbCA9IHtcbiAgICAgIGlzUGFyYW06IGZhbHNlXG4gICAgfTtcbiAgICBjb250ZW50VHlwZU1vZGVsLmNvbnN1bWVzID0gdGhpcy5tb2RlbC5jb25zdW1lcztcbiAgICBjb250ZW50VHlwZU1vZGVsLnByb2R1Y2VzID0gdGhpcy5tb2RlbC5wcm9kdWNlcztcbiAgICByZWYzID0gdGhpcy5tb2RlbC5wYXJhbWV0ZXJzO1xuICAgIGZvciAobiA9IDAsIGxlbjIgPSByZWYzLmxlbmd0aDsgbiA8IGxlbjI7IG4rKykge1xuICAgICAgcGFyYW0gPSByZWYzW25dO1xuICAgICAgdHlwZSA9IHBhcmFtLnR5cGUgfHwgcGFyYW0uZGF0YVR5cGUgfHwgJyc7XG4gICAgICBpZiAodHlwZW9mIHR5cGUgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHNjaGVtYSA9IHBhcmFtLnNjaGVtYTtcbiAgICAgICAgaWYgKHNjaGVtYSAmJiBzY2hlbWEuJHJlZikge1xuICAgICAgICAgIHJlZiA9IHNjaGVtYS4kcmVmO1xuICAgICAgICAgIGlmIChyZWYuaW5kZXhPZignIy9kZWZpbml0aW9ucy8nKSA9PT0gMCkge1xuICAgICAgICAgICAgdHlwZSA9IHJlZi5zdWJzdHJpbmcoJyMvZGVmaW5pdGlvbnMvJy5sZW5ndGgpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0eXBlID0gcmVmO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHR5cGUgJiYgdHlwZS50b0xvd2VyQ2FzZSgpID09PSAnZmlsZScpIHtcbiAgICAgICAgaWYgKCFjb250ZW50VHlwZU1vZGVsLmNvbnN1bWVzKSB7XG4gICAgICAgICAgY29udGVudFR5cGVNb2RlbC5jb25zdW1lcyA9ICdtdWx0aXBhcnQvZm9ybS1kYXRhJztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcGFyYW0udHlwZSA9IHR5cGU7XG4gICAgfVxuICAgIHJlc3BvbnNlQ29udGVudFR5cGVWaWV3ID0gbmV3IFN3YWdnZXJVaS5WaWV3cy5SZXNwb25zZUNvbnRlbnRUeXBlVmlldyh7XG4gICAgICBtb2RlbDogY29udGVudFR5cGVNb2RlbCxcbiAgICAgIHJvdXRlcjogdGhpcy5yb3V0ZXJcbiAgICB9KTtcbiAgICAkKCcucmVzcG9uc2UtY29udGVudC10eXBlJywgJCh0aGlzLmVsKSkuYXBwZW5kKHJlc3BvbnNlQ29udGVudFR5cGVWaWV3LnJlbmRlcigpLmVsKTtcbiAgICByZWY0ID0gdGhpcy5tb2RlbC5wYXJhbWV0ZXJzO1xuICAgIGZvciAocCA9IDAsIGxlbjMgPSByZWY0Lmxlbmd0aDsgcCA8IGxlbjM7IHArKykge1xuICAgICAgcGFyYW0gPSByZWY0W3BdO1xuICAgICAgdGhpcy5hZGRQYXJhbWV0ZXIocGFyYW0sIGNvbnRlbnRUeXBlTW9kZWwuY29uc3VtZXMpO1xuICAgIH1cbiAgICByZWY1ID0gdGhpcy5tb2RlbC5yZXNwb25zZU1lc3NhZ2VzO1xuICAgIGZvciAocSA9IDAsIGxlbjQgPSByZWY1Lmxlbmd0aDsgcSA8IGxlbjQ7IHErKykge1xuICAgICAgc3RhdHVzQ29kZSA9IHJlZjVbcV07XG4gICAgICBzdGF0dXNDb2RlLmlzWE1MID0gaXNYTUw7XG4gICAgICBzdGF0dXNDb2RlLmlzSlNPTiA9IGlzSlNPTjtcbiAgICAgIGlmICghXy5pc1VuZGVmaW5lZChzdGF0dXNDb2RlLmhlYWRlcnMpKSB7XG4gICAgICAgIHN0YXR1c0NvZGUuaGVhZGVycyA9IHRoaXMucGFyc2VIZWFkZXJzVHlwZShzdGF0dXNDb2RlLmhlYWRlcnMpO1xuICAgICAgfVxuICAgICAgdGhpcy5hZGRTdGF0dXNDb2RlKHN0YXR1c0NvZGUpO1xuICAgIH1cblxuICAgIGlmIChBcnJheS5pc0FycmF5KHRoaXMubW9kZWwuc2VjdXJpdHkpKSB7XG4gICAgICB2YXIgYXV0aHNNb2RlbCA9IFN3YWdnZXJVaS51dGlscy5wYXJzZVNlY3VyaXR5RGVmaW5pdGlvbnModGhpcy5tb2RlbC5zZWN1cml0eSwgdGhpcy5tb2RlbC5wYXJlbnQuc2VjdXJpdHlEZWZpbml0aW9ucyk7XG5cbiAgICAgIGF1dGhzTW9kZWwuaXNMb2dvdXQgPSAhXy5pc0VtcHR5KHRoaXMubW9kZWwuY2xpZW50QXV0aG9yaXphdGlvbnMuYXV0aHopO1xuICAgICAgdGhpcy5hdXRoVmlldyA9IG5ldyBTd2FnZ2VyVWkuVmlld3MuQXV0aEJ1dHRvblZpZXcoe1xuICAgICAgICBkYXRhOiBhdXRoc01vZGVsLFxuICAgICAgICByb3V0ZXI6IHRoaXMucm91dGVyLFxuICAgICAgICBpc09wZXJhdGlvbjogdHJ1ZSxcbiAgICAgICAgbW9kZWw6IHtcbiAgICAgICAgICBzY29wZXM6IGF1dGhzTW9kZWwuc2NvcGVzXG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgICAgdGhpcy4kKCcuYXV0aG9yaXplLXdyYXBwZXInKS5hcHBlbmQodGhpcy5hdXRoVmlldy5yZW5kZXIoKS5lbCk7XG4gICAgfVxuXG4gICAgdGhpcy5zaG93U25pcHBldCgpO1xuICAgIHJldHVybiB0aGlzO1xuICB9LFxuXG4gIHBhcnNlSGVhZGVyc1R5cGU6IGZ1bmN0aW9uIChoZWFkZXJzKSB7XG4gICAgdmFyIG1hcCA9IHtcbiAgICAgICdzdHJpbmcnOiB7XG4gICAgICAgICdkYXRlLXRpbWUnOiAnZGF0ZVRpbWUnLFxuICAgICAgICAnZGF0ZScgICAgIDogJ2RhdGUnXG4gICAgICB9XG4gICAgfTtcblxuICAgIF8uZm9yRWFjaChoZWFkZXJzLCBmdW5jdGlvbiAoaGVhZGVyKSB7XG4gICAgICB2YXIgdmFsdWU7XG4gICAgICBoZWFkZXIgPSBoZWFkZXIgfHwge307XG4gICAgICB2YWx1ZSA9IG1hcFtoZWFkZXIudHlwZV0gJiYgbWFwW2hlYWRlci50eXBlXVtoZWFkZXIuZm9ybWF0XTtcbiAgICAgIGlmICghXy5pc1VuZGVmaW5lZCh2YWx1ZSkpIHtcbiAgICAgICAgaGVhZGVyLnR5cGUgPSB2YWx1ZTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIHJldHVybiBoZWFkZXJzO1xuICB9LFxuXG4gIGNvbnRhaW5zOiBmdW5jdGlvbiAocHJvZHVjZXMsIHR5cGUpIHtcbiAgICByZXR1cm4gcHJvZHVjZXMuZmlsdGVyKGZ1bmN0aW9uICh2YWwpIHtcbiAgICAgIGlmICh2YWwuaW5kZXhPZih0eXBlKSA+IC0xKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH0pLmxlbmd0aDtcbiAgfSxcblxuICBwYXJzZVJlc3BvbnNlSGVhZGVyczogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICB2YXIgSEVBREVSU19TRVBBUkFUT1IgPSAnOyAnO1xuICAgIHZhciBoZWFkZXJzID0gXy5jbG9uZShkYXRhKTtcblxuICAgIF8uZm9yRWFjaChoZWFkZXJzLCBmdW5jdGlvbiAoaGVhZGVyKSB7XG4gICAgICB2YXIgb3RoZXIgPSBbXTtcbiAgICAgIF8uZm9yRWFjaChoZWFkZXIsIGZ1bmN0aW9uICh2YWx1ZSwga2V5KSB7XG4gICAgICAgIHZhciBwcm9wZXJ0aWVzID0gWyd0eXBlJywgJ2Rlc2NyaXB0aW9uJ107XG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLmluZGV4T2Yoa2V5LnRvTG93ZXJDYXNlKCkpID09PSAtMSkge1xuICAgICAgICAgIG90aGVyLnB1c2goa2V5ICsgJzogJyArIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIG90aGVyLmpvaW4oSEVBREVSU19TRVBBUkFUT1IpO1xuICAgICAgaGVhZGVyLm90aGVyID0gb3RoZXI7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gaGVhZGVycztcbiAgfSxcblxuICBhZGRQYXJhbWV0ZXI6IGZ1bmN0aW9uKHBhcmFtLCBjb25zdW1lcykge1xuICAgIC8vIFJlbmRlciBhIHBhcmFtZXRlclxuICAgIHBhcmFtLmNvbnN1bWVzID0gY29uc3VtZXM7XG4gICAgcGFyYW0uZGVmYXVsdFJlbmRlcmluZyA9IHRoaXMubW9kZWwuZGVmYXVsdFJlbmRlcmluZztcblxuICAgIC8vIENvcHkgdGhpcyBwYXJhbSBKU09OIHNwZWMgc28gdGhhdCBpdCB3aWxsIGJlIGF2YWlsYWJsZSBmb3IgSnNvbkVkaXRvclxuICAgIGlmKHBhcmFtLnNjaGVtYSl7XG4gICAgICAkLmV4dGVuZCh0cnVlLCBwYXJhbS5zY2hlbWEsIHRoaXMubW9kZWwuZGVmaW5pdGlvbnNbcGFyYW0udHlwZV0pO1xuICAgICAgcGFyYW0uc2NoZW1hLmRlZmluaXRpb25zID0gdGhpcy5tb2RlbC5kZWZpbml0aW9ucztcbiAgICAgIC8vIFRoaXMgaXMgcmVxdWlyZWQgZm9yIEpzb25FZGl0b3IgdG8gZGlzcGxheSB0aGUgcm9vdCBwcm9wZXJseVxuICAgICAgaWYoIXBhcmFtLnNjaGVtYS50eXBlKXtcbiAgICAgICAgcGFyYW0uc2NoZW1hLnR5cGUgPSAnb2JqZWN0JztcbiAgICAgIH1cbiAgICAgIC8vIFRoaXMgaXMgdGhlIHRpdGxlIHRoYXQgd2lsbCBiZSB1c2VkIGJ5IEpzb25FZGl0b3IgZm9yIHRoZSByb290XG4gICAgICAvLyBTaW5jZSB3ZSBhbHJlYWR5IGRpc3BsYXkgdGhlIHBhcmFtZXRlcidzIG5hbWUgaW4gdGhlIFBhcmFtZXRlciBjb2x1bW5cbiAgICAgIC8vIFdlIHNldCB0aGlzIHRvIHNwYWNlLCB3ZSBjYW4ndCBzZXQgaXQgdG8gbnVsbCBvciBzcGFjZSBvdGhlcndpc2UgSnNvbkVkaXRvclxuICAgICAgLy8gd2lsbCByZXBsYWNlIGl0IHdpdGggdGhlIHRleHQgXCJyb290XCIgd2hpY2ggd29uJ3QgbG9vayBnb29kIG9uIHNjcmVlblxuICAgICAgaWYoIXBhcmFtLnNjaGVtYS50aXRsZSl7XG4gICAgICAgIHBhcmFtLnNjaGVtYS50aXRsZSA9ICcgJztcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgcGFyYW1WaWV3ID0gbmV3IFN3YWdnZXJVaS5WaWV3cy5QYXJhbWV0ZXJWaWV3KHtcbiAgICAgIG1vZGVsOiBwYXJhbSxcbiAgICAgIHRhZ05hbWU6ICd0cicsXG4gICAgICByZWFkT25seTogdGhpcy5tb2RlbC5pc1JlYWRPbmx5LFxuICAgICAgc3dhZ2dlck9wdGlvbnM6IHRoaXMub3B0aW9ucy5zd2FnZ2VyT3B0aW9uc1xuICAgIH0pO1xuICAgICQoJy5vcGVyYXRpb24tcGFyYW1zJywgJCh0aGlzLmVsKSkuYXBwZW5kKHBhcmFtVmlldy5yZW5kZXIoKS5lbCk7XG4gIH0sXG5cbiAgYWRkU3RhdHVzQ29kZTogZnVuY3Rpb24oc3RhdHVzQ29kZSkge1xuICAgIC8vIFJlbmRlciBzdGF0dXMgY29kZXNcbiAgICBzdGF0dXNDb2RlLmRlZmF1bHRSZW5kZXJpbmcgPSB0aGlzLm1vZGVsLmRlZmF1bHRSZW5kZXJpbmc7XG4gICAgdmFyIHN0YXR1c0NvZGVWaWV3ID0gbmV3IFN3YWdnZXJVaS5WaWV3cy5TdGF0dXNDb2RlVmlldyh7XG4gICAgICBtb2RlbDogc3RhdHVzQ29kZSxcbiAgICAgIHRhZ05hbWU6ICd0cicsXG4gICAgICByb3V0ZXI6IHRoaXMucm91dGVyXG4gICAgfSk7XG4gICAgJCgnLm9wZXJhdGlvbi1zdGF0dXMnLCAkKHRoaXMuZWwpKS5hcHBlbmQoc3RhdHVzQ29kZVZpZXcucmVuZGVyKCkuZWwpO1xuICB9LFxuXG4gIC8vIE5vdGU6IGNvcGllZCBmcm9tIENvZmZlZVNjcmlwdCBjb21waWxlZCBmaWxlXG4gIC8vIFRPRE86IHJlZGFjdG9yXG4gIHN1Ym1pdE9wZXJhdGlvbjogZnVuY3Rpb24oZSkge1xuICAgIHZhciBlcnJvcl9mcmVlLCBmb3JtLCBpc0ZpbGVVcGxvYWQsIG1hcCwgb3B0cztcbiAgICBpZiAoZSAhPT0gbnVsbCkge1xuICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgICBmb3JtID0gJCgnLnNhbmRib3gnLCAkKHRoaXMuZWwpKTtcbiAgICBlcnJvcl9mcmVlID0gdHJ1ZTtcbiAgICBmb3JtLmZpbmQoJ2lucHV0LnJlcXVpcmVkJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICQodGhpcykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICBpZiAoalF1ZXJ5LnRyaW0oJCh0aGlzKS52YWwoKSkgPT09ICcnKSB7XG4gICAgICAgICQodGhpcykuYWRkQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgICQodGhpcykud2lnZ2xlKHtcbiAgICAgICAgICBjYWxsYmFjazogKGZ1bmN0aW9uKF90aGlzKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICQoX3RoaXMpLmZvY3VzKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH0pKHRoaXMpXG4gICAgICAgIH0pO1xuICAgICAgICBlcnJvcl9mcmVlID0gZmFsc2U7XG4gICAgICB9XG4gICAgfSk7XG4gICAgZm9ybS5maW5kKCd0ZXh0YXJlYS5yZXF1aXJlZDp2aXNpYmxlJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICQodGhpcykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICBpZiAoalF1ZXJ5LnRyaW0oJCh0aGlzKS52YWwoKSkgPT09ICcnKSB7XG4gICAgICAgICQodGhpcykuYWRkQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICAgICQodGhpcykud2lnZ2xlKHtcbiAgICAgICAgICBjYWxsYmFjazogKGZ1bmN0aW9uKF90aGlzKSB7XG4gICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgIHJldHVybiAkKF90aGlzKS5mb2N1cygpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KSh0aGlzKVxuICAgICAgICB9KTtcbiAgICAgICAgZXJyb3JfZnJlZSA9IGZhbHNlO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGZvcm0uZmluZCgnc2VsZWN0LnJlcXVpcmVkJykuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICQodGhpcykucmVtb3ZlQ2xhc3MoJ2Vycm9yJyk7XG4gICAgICBpZiAodGhpcy5zZWxlY3RlZEluZGV4ID09PSAtMSkge1xuICAgICAgICAkKHRoaXMpLmFkZENsYXNzKCdlcnJvcicpO1xuICAgICAgICAkKHRoaXMpLndpZ2dsZSh7XG4gICAgICAgICAgY2FsbGJhY2s6IChmdW5jdGlvbihfdGhpcykge1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAkKF90aGlzKS5mb2N1cygpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9KSh0aGlzKVxuICAgICAgICB9KTtcbiAgICAgICAgZXJyb3JfZnJlZSA9IGZhbHNlO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChlcnJvcl9mcmVlKSB7XG4gICAgICBtYXAgPSB0aGlzLmdldElucHV0TWFwKGZvcm0pO1xuICAgICAgaXNGaWxlVXBsb2FkID0gdGhpcy5pc0ZpbGVVcGxvYWQoZm9ybSk7XG4gICAgICBvcHRzID0ge1xuICAgICAgICBwYXJlbnQ6IHRoaXNcbiAgICAgIH07XG4gICAgICBpZiAodGhpcy5vcHRpb25zLnN3YWdnZXJPcHRpb25zKSB7XG4gICAgICAgIGZvcih2YXIga2V5IGluIHRoaXMub3B0aW9ucy5zd2FnZ2VyT3B0aW9ucykge1xuICAgICAgICAgIG9wdHNba2V5XSA9IHRoaXMub3B0aW9ucy5zd2FnZ2VyT3B0aW9uc1trZXldO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHZhciBwaTtcbiAgICAgIGZvcihwaSA9IDA7IHBpIDwgdGhpcy5tb2RlbC5wYXJhbWV0ZXJzLmxlbmd0aDsgcGkrKyl7XG4gICAgICAgIHZhciBwID0gdGhpcy5tb2RlbC5wYXJhbWV0ZXJzW3BpXTtcbiAgICAgICAgaWYoIHAuanNvbkVkaXRvciAmJiBwLmpzb25FZGl0b3IuaXNFbmFibGVkKCkpe1xuICAgICAgICAgIHZhciBqc29uID0gcC5qc29uRWRpdG9yLmdldFZhbHVlKCk7XG4gICAgICAgICAgbWFwW3AubmFtZV0gPSBKU09OLnN0cmluZ2lmeShqc29uKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBvcHRzLnJlc3BvbnNlQ29udGVudFR5cGUgPSAkKCdkaXYgc2VsZWN0W25hbWU9cmVzcG9uc2VDb250ZW50VHlwZV0nLCAkKHRoaXMuZWwpKS52YWwoKTtcbiAgICAgIG9wdHMucmVxdWVzdENvbnRlbnRUeXBlID0gJCgnZGl2IHNlbGVjdFtuYW1lPXBhcmFtZXRlckNvbnRlbnRUeXBlXScsICQodGhpcy5lbCkpLnZhbCgpO1xuICAgICAgJCgnLnJlc3BvbnNlX3Rocm9iYmVyJywgJCh0aGlzLmVsKSkuc2hvdygpO1xuICAgICAgaWYgKGlzRmlsZVVwbG9hZCkge1xuICAgICAgICAkKCcucmVxdWVzdF91cmwnLCAkKHRoaXMuZWwpKS5odG1sKCc8cHJlPjwvcHJlPicpO1xuICAgICAgICAkKCcucmVxdWVzdF91cmwgcHJlJywgJCh0aGlzLmVsKSkudGV4dCh0aGlzLmludm9jYXRpb25VcmwpO1xuXG4gICAgICAgIG9wdHMudXNlSlF1ZXJ5ID0gdHJ1ZTtcbiAgICAgICAgbWFwLnBhcmFtZXRlckNvbnRlbnRUeXBlID0gJ211bHRpcGFydC9mb3JtLWRhdGEnO1xuICAgICAgICB0aGlzLm1hcCA9IG1hcDtcbiAgICAgICAgcmV0dXJuIHRoaXMubW9kZWwuZXhlY3V0ZShtYXAsIG9wdHMsIHRoaXMuc2hvd0NvbXBsZXRlU3RhdHVzLCB0aGlzLnNob3dFcnJvclN0YXR1cywgdGhpcyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm1hcCA9IG1hcDtcbiAgICAgICAgcmV0dXJuIHRoaXMubW9kZWwuZXhlY3V0ZShtYXAsIG9wdHMsIHRoaXMuc2hvd0NvbXBsZXRlU3RhdHVzLCB0aGlzLnNob3dFcnJvclN0YXR1cywgdGhpcyk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIGdldElucHV0TWFwOiBmdW5jdGlvbiAoZm9ybSkge1xuICAgIHZhciBtYXAsIHJlZjEsIGwsIGxlbiwgbywgcmVmMiwgbSwgbGVuMSwgdmFsLCByZWYzLCBuLCBsZW4yO1xuICAgIG1hcCA9IHt9O1xuICAgIHJlZjEgPSBmb3JtLmZpbmQoJ2lucHV0Jyk7XG4gICAgZm9yIChsID0gMCwgbGVuID0gcmVmMS5sZW5ndGg7IGwgPCBsZW47IGwrKykge1xuICAgICAgbyA9IHJlZjFbbF07XG4gICAgICBpZiAoKG8udmFsdWUgIT09IG51bGwpICYmIGpRdWVyeS50cmltKG8udmFsdWUpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbWFwW28ubmFtZV0gPSBvLnZhbHVlO1xuICAgICAgfVxuICAgICAgaWYgKG8udHlwZSA9PT0gJ2ZpbGUnKSB7XG4gICAgICAgIG1hcFtvLm5hbWVdID0gby5maWxlc1swXTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmVmMiA9IGZvcm0uZmluZCgndGV4dGFyZWEnKTtcbiAgICBmb3IgKG0gPSAwLCBsZW4xID0gcmVmMi5sZW5ndGg7IG0gPCBsZW4xOyBtKyspIHtcbiAgICAgIG8gPSByZWYyW21dO1xuICAgICAgdmFsID0gdGhpcy5nZXRUZXh0QXJlYVZhbHVlKG8pO1xuICAgICAgaWYgKCh2YWwgIT09IG51bGwpICYmIGpRdWVyeS50cmltKHZhbCkubGVuZ3RoID4gMCkge1xuICAgICAgICBtYXBbby5uYW1lXSA9IHZhbDtcbiAgICAgIH1cbiAgICB9XG4gICAgcmVmMyA9IGZvcm0uZmluZCgnc2VsZWN0Jyk7XG4gICAgZm9yIChuID0gMCwgbGVuMiA9IHJlZjMubGVuZ3RoOyBuIDwgbGVuMjsgbisrKSB7XG4gICAgICBvID0gcmVmM1tuXTtcbiAgICAgIHZhbCA9IHRoaXMuZ2V0U2VsZWN0ZWRWYWx1ZShvKTtcbiAgICAgIGlmICgodmFsICE9PSBudWxsKSAmJiBqUXVlcnkudHJpbSh2YWwpLmxlbmd0aCA+IDApIHtcbiAgICAgICAgbWFwW28ubmFtZV0gPSB2YWw7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBtYXA7XG4gIH0sXG5cbiAgaXNGaWxlVXBsb2FkOiBmdW5jdGlvbiAoZm9ybSkge1xuICAgIHZhciByZWYxLCBsLCBsZW4sIG87XG4gICAgdmFyIGlzRmlsZVVwbG9hZCA9IGZhbHNlO1xuICAgIHJlZjEgPSBmb3JtLmZpbmQoJ2lucHV0Jyk7XG4gICAgZm9yIChsID0gMCwgbGVuID0gcmVmMS5sZW5ndGg7IGwgPCBsZW47IGwrKykge1xuICAgICAgbyA9IHJlZjFbbF07XG4gICAgICBpZiAoby50eXBlID09PSAnZmlsZScpIHtcbiAgICAgICAgaXNGaWxlVXBsb2FkID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGlzRmlsZVVwbG9hZDtcbiAgfSxcblxuICBzdWNjZXNzOiBmdW5jdGlvbihyZXNwb25zZSwgcGFyZW50KSB7XG4gICAgcGFyZW50LnNob3dDb21wbGV0ZVN0YXR1cyhyZXNwb25zZSk7XG4gIH0sXG5cbiAgLy8gd3JhcHMgYSBqcXVlcnkgcmVzcG9uc2UgYXMgYSBzaHJlZCByZXNwb25zZVxuICB3cmFwOiBmdW5jdGlvbihkYXRhKSB7XG4gICAgdmFyIGgsIGhlYWRlckFycmF5LCBoZWFkZXJzLCBpLCBsLCBsZW4sIG87XG4gICAgaGVhZGVycyA9IHt9O1xuICAgIGhlYWRlckFycmF5ID0gZGF0YS5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKS5zcGxpdCgnXFxyJyk7XG4gICAgZm9yIChsID0gMCwgbGVuID0gaGVhZGVyQXJyYXkubGVuZ3RoOyBsIDwgbGVuOyBsKyspIHtcbiAgICAgIGkgPSBoZWFkZXJBcnJheVtsXTtcbiAgICAgIGggPSBpLm1hdGNoKC9eKFteOl0qPyk6KC4qKSQvKTtcbiAgICAgIGlmICghaCkge1xuICAgICAgICBoID0gW107XG4gICAgICB9XG4gICAgICBoLnNoaWZ0KCk7XG4gICAgICBpZiAoaFswXSAhPT0gdm9pZCAwICYmIGhbMV0gIT09IHZvaWQgMCkge1xuICAgICAgICBoZWFkZXJzW2hbMF0udHJpbSgpXSA9IGhbMV0udHJpbSgpO1xuICAgICAgfVxuICAgIH1cbiAgICBvID0ge307XG4gICAgby5jb250ZW50ID0ge307XG4gICAgby5jb250ZW50LmRhdGEgPSBkYXRhLnJlc3BvbnNlVGV4dDtcbiAgICBvLmhlYWRlcnMgPSBoZWFkZXJzO1xuICAgIG8ucmVxdWVzdCA9IHt9O1xuICAgIG8ucmVxdWVzdC51cmwgPSB0aGlzLmludm9jYXRpb25Vcmw7XG4gICAgby5zdGF0dXMgPSBkYXRhLnN0YXR1cztcbiAgICByZXR1cm4gbztcbiAgfSxcblxuICBnZXRTZWxlY3RlZFZhbHVlOiBmdW5jdGlvbihzZWxlY3QpIHtcbiAgICBpZiAoIXNlbGVjdC5tdWx0aXBsZSkge1xuICAgICAgcmV0dXJuIHNlbGVjdC52YWx1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIG9wdGlvbnMgPSBbXTtcbiAgICAgIGZvciAodmFyIGwgPSAwLCBsZW4gPSBzZWxlY3Qub3B0aW9ucy5sZW5ndGg7IGwgPCBsZW47IGwrKykge1xuICAgICAgICB2YXIgb3B0ID0gc2VsZWN0Lm9wdGlvbnNbbF07XG4gICAgICAgIGlmIChvcHQuc2VsZWN0ZWQpIHtcbiAgICAgICAgICBvcHRpb25zLnB1c2gob3B0LnZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKG9wdGlvbnMubGVuZ3RoID4gMCkge1xuICAgICAgICByZXR1cm4gb3B0aW9ucztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgfSxcblxuICAvLyBoYW5kbGVyIGZvciBoaWRlIHJlc3BvbnNlIGxpbmtcbiAgaGlkZVJlc3BvbnNlOiBmdW5jdGlvbihlKSB7XG4gICAgaWYgKGUpIHsgZS5wcmV2ZW50RGVmYXVsdCgpOyB9XG4gICAgJCgnLnJlc3BvbnNlJywgJCh0aGlzLmVsKSkuc2xpZGVVcCgpO1xuICAgICQoJy5yZXNwb25zZV9oaWRlcicsICQodGhpcy5lbCkpLmZhZGVPdXQoKTtcbiAgfSxcblxuICAvLyBTaG93IHJlc3BvbnNlIGZyb20gc2VydmVyXG4gIHNob3dSZXNwb25zZTogZnVuY3Rpb24ocmVzcG9uc2UpIHtcbiAgICB2YXIgcHJldHR5SnNvbiA9IEpTT04uc3RyaW5naWZ5KHJlc3BvbnNlLCBudWxsLCAnXFx0JykucmVwbGFjZSgvXFxuL2csICc8YnI+Jyk7XG4gICAgJCgnLnJlc3BvbnNlX2JvZHknLCAkKHRoaXMuZWwpKS5odG1sKF8uZXNjYXBlKHByZXR0eUpzb24pKTtcbiAgfSxcblxuICAvLyBTaG93IGVycm9yIGZyb20gc2VydmVyXG4gIHNob3dFcnJvclN0YXR1czogZnVuY3Rpb24oZGF0YSwgcGFyZW50KSB7XG4gICAgcGFyZW50LnNob3dTdGF0dXMoZGF0YSk7XG4gIH0sXG5cbiAgLy8gc2hvdyB0aGUgc3RhdHVzIGNvZGVzXG4gIHNob3dDb21wbGV0ZVN0YXR1czogZnVuY3Rpb24oZGF0YSwgcGFyZW50KXtcbiAgICBwYXJlbnQuc2hvd1N0YXR1cyhkYXRhKTtcbiAgfSxcblxuICAvLyBBZGFwdGVkIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMjg5MzI1OS80NTQwMDRcbiAgLy8gTm90ZTogZGlyZWN0bHkgcG9ydGVkIGZyb20gQ29mZmVlU2NyaXB0XG4gIC8vIFRPRE86IENsZWFudXAgQ29mZmVlU2NyaXB0IGFydGlmYWN0c1xuICBmb3JtYXRYbWw6IGZ1bmN0aW9uKHhtbCkge1xuICAgIHZhciBjb250ZXhwLCBmbiwgZm9ybWF0dGVkLCBpbmRlbnQsIGwsIGxhc3RUeXBlLCBsZW4sIGxpbmVzLCBsbiwgcGFkLCByZWcsIHRyYW5zaXRpb25zLCB3c2V4cDtcbiAgICByZWcgPSAvKD4pKDwpKFxcLyopL2c7XG4gICAgd3NleHAgPSAvWyBdKiguKilbIF0rXFxuL2c7XG4gICAgY29udGV4cCA9IC8oPC4rPikoLitcXG4pL2c7XG4gICAgeG1sID0geG1sLnJlcGxhY2UoL1xcclxcbi9nLCAnXFxuJykucmVwbGFjZShyZWcsICckMVxcbiQyJDMnKS5yZXBsYWNlKHdzZXhwLCAnJDFcXG4nKS5yZXBsYWNlKGNvbnRleHAsICckMVxcbiQyJyk7XG4gICAgcGFkID0gMDtcbiAgICBmb3JtYXR0ZWQgPSAnJztcbiAgICBsaW5lcyA9IHhtbC5zcGxpdCgnXFxuJyk7XG4gICAgaW5kZW50ID0gMDtcbiAgICBsYXN0VHlwZSA9ICdvdGhlcic7XG4gICAgdHJhbnNpdGlvbnMgPSB7XG4gICAgICAnc2luZ2xlLT5zaW5nbGUnOiAwLFxuICAgICAgJ3NpbmdsZS0+Y2xvc2luZyc6IC0xLFxuICAgICAgJ3NpbmdsZS0+b3BlbmluZyc6IDAsXG4gICAgICAnc2luZ2xlLT5vdGhlcic6IDAsXG4gICAgICAnY2xvc2luZy0+c2luZ2xlJzogMCxcbiAgICAgICdjbG9zaW5nLT5jbG9zaW5nJzogLTEsXG4gICAgICAnY2xvc2luZy0+b3BlbmluZyc6IDAsXG4gICAgICAnY2xvc2luZy0+b3RoZXInOiAwLFxuICAgICAgJ29wZW5pbmctPnNpbmdsZSc6IDEsXG4gICAgICAnb3BlbmluZy0+Y2xvc2luZyc6IDAsXG4gICAgICAnb3BlbmluZy0+b3BlbmluZyc6IDEsXG4gICAgICAnb3BlbmluZy0+b3RoZXInOiAxLFxuICAgICAgJ290aGVyLT5zaW5nbGUnOiAwLFxuICAgICAgJ290aGVyLT5jbG9zaW5nJzogLTEsXG4gICAgICAnb3RoZXItPm9wZW5pbmcnOiAwLFxuICAgICAgJ290aGVyLT5vdGhlcic6IDBcbiAgICB9O1xuICAgIGZuID0gZnVuY3Rpb24obG4pIHtcbiAgICAgIHZhciBmcm9tVG8sIGosIGtleSwgcGFkZGluZywgdHlwZSwgdHlwZXMsIHZhbHVlO1xuICAgICAgdHlwZXMgPSB7XG4gICAgICAgIHNpbmdsZTogQm9vbGVhbihsbi5tYXRjaCgvPC4rXFwvPi8pKSxcbiAgICAgICAgY2xvc2luZzogQm9vbGVhbihsbi5tYXRjaCgvPFxcLy4rPi8pKSxcbiAgICAgICAgb3BlbmluZzogQm9vbGVhbihsbi5tYXRjaCgvPFteIT9dLio+LykpXG4gICAgICB9O1xuICAgICAgdHlwZSA9ICgoZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciByZXN1bHRzO1xuICAgICAgICByZXN1bHRzID0gW107XG4gICAgICAgIGZvciAoa2V5IGluIHR5cGVzKSB7XG4gICAgICAgICAgdmFsdWUgPSB0eXBlc1trZXldO1xuICAgICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgICAgcmVzdWx0cy5wdXNoKGtleSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXN1bHRzO1xuICAgICAgfSkoKSlbMF07XG4gICAgICB0eXBlID0gdHlwZSA9PT0gdm9pZCAwID8gJ290aGVyJyA6IHR5cGU7XG4gICAgICBmcm9tVG8gPSBsYXN0VHlwZSArICctPicgKyB0eXBlO1xuICAgICAgbGFzdFR5cGUgPSB0eXBlO1xuICAgICAgcGFkZGluZyA9ICcnO1xuICAgICAgaW5kZW50ICs9IHRyYW5zaXRpb25zW2Zyb21Ub107XG4gICAgICBwYWRkaW5nID0gKChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIG0sIHJlZjEsIHJlc3VsdHM7XG4gICAgICAgIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgZm9yIChqID0gbSA9IDAsIHJlZjEgPSBpbmRlbnQ7IDAgPD0gcmVmMSA/IG0gPCByZWYxIDogbSA+IHJlZjE7IGogPSAwIDw9IHJlZjEgPyArK20gOiAtLW0pIHtcbiAgICAgICAgICByZXN1bHRzLnB1c2goJyAgJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgICB9KSgpKS5qb2luKCcnKTtcbiAgICAgIGlmIChmcm9tVG8gPT09ICdvcGVuaW5nLT5jbG9zaW5nJykge1xuICAgICAgICBmb3JtYXR0ZWQgPSBmb3JtYXR0ZWQuc3Vic3RyKDAsIGZvcm1hdHRlZC5sZW5ndGggLSAxKSArIGxuICsgJ1xcbic7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBmb3JtYXR0ZWQgKz0gcGFkZGluZyArIGxuICsgJ1xcbic7XG4gICAgICB9XG4gICAgfTtcbiAgICBmb3IgKGwgPSAwLCBsZW4gPSBsaW5lcy5sZW5ndGg7IGwgPCBsZW47IGwrKykge1xuICAgICAgbG4gPSBsaW5lc1tsXTtcbiAgICAgIGZuKGxuKTtcbiAgICB9XG4gICAgcmV0dXJuIGZvcm1hdHRlZDtcbiAgfSxcblxuICAvLyBwdXRzIHRoZSByZXNwb25zZSBkYXRhIGluIFVJXG4gIHNob3dTdGF0dXM6IGZ1bmN0aW9uKHJlc3BvbnNlKSB7XG4gICAgdmFyIHVybCwgY29udGVudDtcbiAgICBpZiAocmVzcG9uc2UuY29udGVudCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb250ZW50ID0gcmVzcG9uc2UuZGF0YTtcbiAgICAgIHVybCA9IHJlc3BvbnNlLnVybDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGVudCA9IHJlc3BvbnNlLmNvbnRlbnQuZGF0YTtcbiAgICAgIHVybCA9IHJlc3BvbnNlLnJlcXVlc3QudXJsO1xuICAgIH1cbiAgICB2YXIgaGVhZGVycyA9IHJlc3BvbnNlLmhlYWRlcnM7XG4gICAgaWYodHlwZW9mIGNvbnRlbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb250ZW50ID0galF1ZXJ5LnRyaW0oY29udGVudCk7XG4gICAgfVxuXG4gICAgLy8gaWYgc2VydmVyIGlzIG5pY2UsIGFuZCBzZW5kcyBjb250ZW50LXR5cGUgYmFjaywgd2UgY2FuIHVzZSBpdFxuICAgIHZhciBjb250ZW50VHlwZSA9IG51bGw7XG4gICAgaWYgKGhlYWRlcnMpIHtcbiAgICAgIGNvbnRlbnRUeXBlID0gaGVhZGVyc1snQ29udGVudC1UeXBlJ10gfHwgaGVhZGVyc1snY29udGVudC10eXBlJ107XG4gICAgICBpZiAoY29udGVudFR5cGUpIHtcbiAgICAgICAgY29udGVudFR5cGUgPSBjb250ZW50VHlwZS5zcGxpdCgnOycpWzBdLnRyaW0oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAkKCcucmVzcG9uc2VfYm9keScsICQodGhpcy5lbCkpLnJlbW92ZUNsYXNzKCdqc29uJyk7XG4gICAgJCgnLnJlc3BvbnNlX2JvZHknLCAkKHRoaXMuZWwpKS5yZW1vdmVDbGFzcygneG1sJyk7XG5cbiAgICB2YXIgc3VwcG9ydHNBdWRpb1BsYXliYWNrID0gZnVuY3Rpb24oY29udGVudFR5cGUpe1xuICAgICAgdmFyIGF1ZGlvRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2F1ZGlvJyk7XG4gICAgICByZXR1cm4gISEoYXVkaW9FbGVtZW50LmNhblBsYXlUeXBlICYmIGF1ZGlvRWxlbWVudC5jYW5QbGF5VHlwZShjb250ZW50VHlwZSkucmVwbGFjZSgvbm8vLCAnJykpO1xuICAgIH07XG5cbiAgICB2YXIgcHJlO1xuICAgIHZhciBjb2RlO1xuICAgIHZhciBza2lwSGlnaGxpZ2h0ID0gZmFsc2U7XG4gICAgaWYgKCFjb250ZW50KSB7XG4gICAgICBjb2RlID0gJCgnPGNvZGUgLz4nKS50ZXh0KCdubyBjb250ZW50Jyk7XG4gICAgICBwcmUgPSAkKCc8cHJlIGNsYXNzPVwianNvblwiIC8+JykuYXBwZW5kKGNvZGUpO1xuXG4gICAgICAvLyBKU09OXG4gICAgfSBlbHNlIGlmIChcbiAgICAgICAgY29udGVudFR5cGUgPT09ICdhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW0nIHx8XG4gICAgICAgIGhlYWRlcnNbJ0NvbnRlbnQtRGlzcG9zaXRpb24nXSAmJiAoL2F0dGFjaG1lbnQvKS50ZXN0KGhlYWRlcnNbJ0NvbnRlbnQtRGlzcG9zaXRpb24nXSkgfHxcbiAgICAgICAgaGVhZGVyc1snY29udGVudC1kaXNwb3NpdGlvbiddICYmICgvYXR0YWNobWVudC8pLnRlc3QoaGVhZGVyc1snY29udGVudC1kaXNwb3NpdGlvbiddKSB8fFxuICAgICAgICBoZWFkZXJzWydDb250ZW50LURlc2NyaXB0aW9uJ10gJiYgKC9GaWxlIFRyYW5zZmVyLykudGVzdChoZWFkZXJzWydDb250ZW50LURlc2NyaXB0aW9uJ10pIHx8XG4gICAgICAgIGhlYWRlcnNbJ2NvbnRlbnQtZGVzY3JpcHRpb24nXSAmJiAoL0ZpbGUgVHJhbnNmZXIvKS50ZXN0KGhlYWRlcnNbJ2NvbnRlbnQtZGVzY3JpcHRpb24nXSkpIHtcblxuICAgICAgaWYgKCdCbG9iJyBpbiB3aW5kb3cpIHtcbiAgICAgICAgdmFyIHR5cGUgPSBjb250ZW50VHlwZSB8fCAndGV4dC9odG1sJztcbiAgICAgICAgdmFyIGEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICAgIHZhciBocmVmO1xuXG4gICAgICAgIGlmKHt9LnRvU3RyaW5nLmFwcGx5KGNvbnRlbnQpID09PSAnW29iamVjdCBCbG9iXScpIHtcbiAgICAgICAgICBocmVmID0gd2luZG93LlVSTC5jcmVhdGVPYmplY3RVUkwoY29udGVudCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgdmFyIGJpbmFyeURhdGEgPSBbXTtcbiAgICAgICAgICBiaW5hcnlEYXRhLnB1c2goY29udGVudCk7XG4gICAgICAgICAgaHJlZiA9IHdpbmRvdy5VUkwuY3JlYXRlT2JqZWN0VVJMKG5ldyBCbG9iKGJpbmFyeURhdGEsIHt0eXBlOiB0eXBlfSkpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmaWxlTmFtZSA9IHJlc3BvbnNlLnVybC5zdWJzdHIocmVzcG9uc2UudXJsLmxhc3RJbmRleE9mKCcvJykgKyAxKTtcbiAgICAgICAgdmFyIGRvd25sb2FkID0gW3R5cGUsIGZpbGVOYW1lLCBocmVmXS5qb2luKCc6Jyk7XG5cbiAgICAgICAgLy8gVXNlIGZpbGVuYW1lIGZyb20gcmVzcG9uc2UgaGVhZGVyXG4gICAgICAgIHZhciBkaXNwb3NpdGlvbiA9IGhlYWRlcnNbJ2NvbnRlbnQtZGlzcG9zaXRpb24nXSB8fCBoZWFkZXJzWydDb250ZW50LURpc3Bvc2l0aW9uJ107XG4gICAgICAgIGlmKHR5cGVvZiBkaXNwb3NpdGlvbiAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICB2YXIgcmVzcG9uc2VGaWxlbmFtZSA9IC9maWxlbmFtZT0oW147XSopOz8vLmV4ZWMoZGlzcG9zaXRpb24pO1xuICAgICAgICAgIGlmKHJlc3BvbnNlRmlsZW5hbWUgIT09IG51bGwgJiYgcmVzcG9uc2VGaWxlbmFtZS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBkb3dubG9hZCA9IHJlc3BvbnNlRmlsZW5hbWVbMV07XG4gICAgICAgICAgICBmaWxlTmFtZSA9IGRvd25sb2FkO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGEuc2V0QXR0cmlidXRlKCdocmVmJywgaHJlZik7XG4gICAgICAgIGEuc2V0QXR0cmlidXRlKCdkb3dubG9hZCcsIGRvd25sb2FkKTtcbiAgICAgICAgYS5pbm5lclRleHQgPSAnRG93bmxvYWQgJyArIGZpbGVOYW1lO1xuXG4gICAgICAgIHByZSA9ICQoJzxkaXYvPicpLmFwcGVuZChhKTtcbiAgICAgICAgc2tpcEhpZ2hsaWdodCA9IHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwcmUgPSAkKCc8cHJlIGNsYXNzPVwianNvblwiIC8+JykuYXBwZW5kKCdEb3dubG9hZCBoZWFkZXJzIGRldGVjdGVkIGJ1dCB5b3VyIGJyb3dzZXIgZG9lcyBub3Qgc3VwcG9ydCBkb3dubG9hZGluZyBiaW5hcnkgdmlhIFhIUiAoQmxvYikuJyk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjb250ZW50VHlwZSA9PT0gJ2FwcGxpY2F0aW9uL2pzb24nIHx8IC9cXCtqc29uJC8udGVzdChjb250ZW50VHlwZSkpIHtcbiAgICAgIHZhciBqc29uID0gbnVsbDtcbiAgICAgIHRyeSB7XG4gICAgICAgIGpzb24gPSBKU09OLnN0cmluZ2lmeShKU09OLnBhcnNlKGNvbnRlbnQpLCBudWxsLCAnICAnKTtcbiAgICAgIH0gY2F0Y2ggKF9lcnJvcikge1xuICAgICAgICBqc29uID0gJ2NhblxcJ3QgcGFyc2UgSlNPTi4gIFJhdyByZXN1bHQ6XFxuXFxuJyArIGNvbnRlbnQ7XG4gICAgICB9XG4gICAgICBjb2RlID0gJCgnPGNvZGUgLz4nKS50ZXh0KGpzb24pO1xuICAgICAgcHJlID0gJCgnPHByZSBjbGFzcz1cImpzb25cIiAvPicpLmFwcGVuZChjb2RlKTtcblxuICAgICAgLy8gWE1MXG4gICAgfSBlbHNlIGlmIChjb250ZW50VHlwZSA9PT0gJ2FwcGxpY2F0aW9uL3htbCcgfHwgL1xcK3htbCQvLnRlc3QoY29udGVudFR5cGUpKSB7XG4gICAgICBjb2RlID0gJCgnPGNvZGUgLz4nKS50ZXh0KHRoaXMuZm9ybWF0WG1sKGNvbnRlbnQpKTtcbiAgICAgIHByZSA9ICQoJzxwcmUgY2xhc3M9XCJ4bWxcIiAvPicpLmFwcGVuZChjb2RlKTtcblxuICAgICAgLy8gSFRNTFxuICAgIH0gZWxzZSBpZiAoY29udGVudFR5cGUgPT09ICd0ZXh0L2h0bWwnKSB7XG4gICAgICBjb2RlID0gJCgnPGNvZGUgLz4nKS5odG1sKF8uZXNjYXBlKGNvbnRlbnQpKTtcbiAgICAgIHByZSA9ICQoJzxwcmUgY2xhc3M9XCJ4bWxcIiAvPicpLmFwcGVuZChjb2RlKTtcblxuICAgICAgLy8gUGxhaW4gVGV4dFxuICAgIH0gZWxzZSBpZiAoL3RleHRcXC9wbGFpbi8udGVzdChjb250ZW50VHlwZSkpIHtcbiAgICAgIGNvZGUgPSAkKCc8Y29kZSAvPicpLnRleHQoY29udGVudCk7XG4gICAgICBwcmUgPSAkKCc8cHJlIGNsYXNzPVwicGxhaW5cIiAvPicpLmFwcGVuZChjb2RlKTtcblxuICAgICAgLy8gSW1hZ2VcbiAgICB9IGVsc2UgaWYgKC9eaW1hZ2VcXC8vLnRlc3QoY29udGVudFR5cGUpKSB7XG4gICAgICB2YXIgdXJsQ3JlYXRvciA9IHdpbmRvdy5VUkwgfHwgd2luZG93LndlYmtpdFVSTDtcbiAgICAgIHZhciBpbWFnZVVybCA9IHVybENyZWF0b3IuY3JlYXRlT2JqZWN0VVJMKGNvbnRlbnQpO1xuXG4gICAgICBwcmUgPSAkKCc8aW1nPicpLmF0dHIoICdzcmMnLCBpbWFnZVVybCk7XG4gICAgICAvLyBBdWRpb1xuICAgIH0gZWxzZSBpZiAoL15hdWRpb1xcLy8udGVzdChjb250ZW50VHlwZSkgJiYgc3VwcG9ydHNBdWRpb1BsYXliYWNrKGNvbnRlbnRUeXBlKSkge1xuICAgICAgcHJlID0gJCgnPGF1ZGlvIGNvbnRyb2xzPicpLmFwcGVuZCgkKCc8c291cmNlPicpLmF0dHIoJ3NyYycsIHVybCkuYXR0cigndHlwZScsIGNvbnRlbnRUeXBlKSk7XG4gICAgfSBlbHNlIGlmKGhlYWRlcnMubG9jYXRpb24gfHwgaGVhZGVycy5Mb2NhdGlvbikge1xuICAgICAgLy8gTG9jYXRpb24gaGVhZGVyIGJhc2VkIHJlZGlyZWN0IGRvd25sb2FkXG4gICAgICB3aW5kb3cubG9jYXRpb24gPSByZXNwb25zZS51cmw7XG5cbiAgICAgIC8vIEFueXRoaW5nIGVsc2UgKENPUlMpXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvZGUgPSAkKCc8Y29kZSAvPicpLnRleHQoY29udGVudCk7XG4gICAgICBwcmUgPSAkKCc8cHJlIGNsYXNzPVwianNvblwiIC8+JykuYXBwZW5kKGNvZGUpO1xuICAgIH1cbiAgICB2YXIgcmVzcG9uc2VfYm9keSA9IHByZTtcbiAgICAkKCcucmVxdWVzdF91cmwnLCAkKHRoaXMuZWwpKS5odG1sKCc8cHJlPjwvcHJlPicpO1xuICAgICQoJy5yZXF1ZXN0X3VybCBwcmUnLCAkKHRoaXMuZWwpKS50ZXh0KHVybCk7XG4gICAgJCgnLnJlc3BvbnNlX2NvZGUnLCAkKHRoaXMuZWwpKS5odG1sKCc8cHJlPicgKyByZXNwb25zZS5zdGF0dXMgKyAnPC9wcmU+Jyk7XG4gICAgJCgnLnJlc3BvbnNlX2JvZHknLCAkKHRoaXMuZWwpKS5odG1sKHJlc3BvbnNlX2JvZHkpO1xuICAgICQoJy5yZXNwb25zZV9oZWFkZXJzJywgJCh0aGlzLmVsKSkuaHRtbCgnPHByZT4nICsgXy5lc2NhcGUoSlNPTi5zdHJpbmdpZnkocmVzcG9uc2UuaGVhZGVycywgbnVsbCwgJyAgJykpLnJlcGxhY2UoL1xcbi9nLCAnPGJyPicpICsgJzwvcHJlPicpO1xuICAgICQoJy5yZXNwb25zZScsICQodGhpcy5lbCkpLnNsaWRlRG93bigpO1xuICAgICQoJy5yZXNwb25zZV9oaWRlcicsICQodGhpcy5lbCkpLnNob3coKTtcbiAgICAkKCcucmVzcG9uc2VfdGhyb2JiZXInLCAkKHRoaXMuZWwpKS5oaWRlKCk7XG5cblxuICAgIC8vIGFkZHMgY3VybCBvdXRwdXRcbiAgICB2YXIgY3VybENvbW1hbmQgPSB0aGlzLm1vZGVsLmFzQ3VybCh0aGlzLm1hcCwge3Jlc3BvbnNlQ29udGVudFR5cGU6IGNvbnRlbnRUeXBlfSk7XG4gICAgY3VybENvbW1hbmQgPSBjdXJsQ29tbWFuZC5yZXBsYWNlKCchJywgJyYjMzM7Jyk7XG4gICAgJCggJ2Rpdi5jdXJsJywgJCh0aGlzLmVsKSkuaHRtbCgnPHByZT4nICsgXy5lc2NhcGUoY3VybENvbW1hbmQpICsgJzwvcHJlPicpO1xuXG4gICAgLy8gb25seSBoaWdobGlnaHQgdGhlIHJlc3BvbnNlIGlmIHJlc3BvbnNlIGlzIGxlc3MgdGhhbiB0aHJlc2hvbGQsIGRlZmF1bHQgc3RhdGUgaXMgaGlnaGxpZ2h0IHJlc3BvbnNlXG4gICAgdmFyIG9wdHMgPSB0aGlzLm9wdGlvbnMuc3dhZ2dlck9wdGlvbnM7XG5cbiAgICBpZiAob3B0cy5zaG93UmVxdWVzdEhlYWRlcnMpIHtcbiAgICAgIHZhciBmb3JtID0gJCgnLnNhbmRib3gnLCAkKHRoaXMuZWwpKSxcbiAgICAgICAgICBtYXAgPSB0aGlzLmdldElucHV0TWFwKGZvcm0pLFxuICAgICAgICAgIHJlcXVlc3RIZWFkZXJzID0gdGhpcy5tb2RlbC5nZXRIZWFkZXJQYXJhbXMobWFwKTtcbiAgICAgIGRlbGV0ZSByZXF1ZXN0SGVhZGVyc1snQ29udGVudC1UeXBlJ107XG4gICAgICAkKCcucmVxdWVzdF9oZWFkZXJzJywgJCh0aGlzLmVsKSkuaHRtbCgnPHByZT4nICsgXy5lc2NhcGUoSlNPTi5zdHJpbmdpZnkocmVxdWVzdEhlYWRlcnMsIG51bGwsICcgICcpKS5yZXBsYWNlKC9cXG4vZywgJzxicj4nKSArICc8L3ByZT4nKTtcbiAgICB9XG5cbiAgICAvLyBDYWxsIHVzZXItZGVmaW5lZCBob29rXG4gICAgaWYgKG9wdHMucmVzcG9uc2VIb29rcyAmJiBvcHRzLnJlc3BvbnNlSG9va3NbdGhpcy5uaWNrbmFtZV0pIHtcbiAgICAgIG9wdHMucmVzcG9uc2VIb29rc1t0aGlzLm5pY2tuYW1lXShyZXNwb25zZSwgdGhpcyk7XG4gICAgfVxuXG4gICAgdmFyIHJlc3BvbnNlX2JvZHlfZWwgPSAkKCcucmVzcG9uc2VfYm9keScsICQodGhpcy5lbCkpWzBdO1xuICAgIC8vIG9ubHkgaGlnaGxpZ2h0IHRoZSByZXNwb25zZSBpZiByZXNwb25zZSBpcyBsZXNzIHRoYW4gdGhyZXNob2xkLCBkZWZhdWx0IHN0YXRlIGlzIGhpZ2hsaWdodCByZXNwb25zZVxuICAgIGlmIChvcHRzLmhpZ2hsaWdodFNpemVUaHJlc2hvbGQgJiYgdHlwZW9mIHJlc3BvbnNlLmRhdGEgIT09ICd1bmRlZmluZWQnICYmIHJlc3BvbnNlLmRhdGEubGVuZ3RoID4gb3B0cy5oaWdobGlnaHRTaXplVGhyZXNob2xkIHx8IHNraXBIaWdobGlnaHQpIHtcbiAgICAgIHJldHVybiByZXNwb25zZV9ib2R5X2VsO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaGxqcy5oaWdobGlnaHRCbG9jayhyZXNwb25zZV9ib2R5X2VsKTtcbiAgICB9XG4gIH0sXG5cbiAgdG9nZ2xlT3BlcmF0aW9uQ29udGVudDogZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgdmFyIGVsZW0gPSAkKCcjJyArIERvY3MuZXNjYXBlUmVzb3VyY2VOYW1lKHRoaXMucGFyZW50SWQgKyAnXycgKyB0aGlzLm5pY2tuYW1lICsgJ19jb250ZW50JykpO1xuICAgIGlmIChlbGVtLmlzKCc6dmlzaWJsZScpKXtcbiAgICAgICQuYmJxLnB1c2hTdGF0ZSgnIy8nLCAyKTtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBEb2NzLmNvbGxhcHNlT3BlcmF0aW9uKGVsZW0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBEb2NzLmV4cGFuZE9wZXJhdGlvbihlbGVtKTtcbiAgICB9XG4gIH0sXG5cbiAgZ2V0VGV4dEFyZWFWYWx1ZTogZnVuY3Rpb24odGV4dEFyZWEpIHtcbiAgICB2YXIgcGFyYW0sIHBhcnNlZCwgcmVzdWx0LCBpO1xuICAgIGlmICh0ZXh0QXJlYS52YWx1ZSA9PT0gbnVsbCB8fCBqUXVlcnkudHJpbSh0ZXh0QXJlYS52YWx1ZSkubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcGFyYW0gPSB0aGlzLmdldFBhcmFtQnlOYW1lKHRleHRBcmVhLm5hbWUpO1xuICAgIGlmIChwYXJhbSAmJiBwYXJhbS50eXBlICYmIHBhcmFtLnR5cGUudG9Mb3dlckNhc2UoKSA9PT0gJ2FycmF5Jykge1xuICAgICAgcGFyc2VkID0gdGV4dEFyZWEudmFsdWUuc3BsaXQoJ1xcbicpO1xuICAgICAgcmVzdWx0ID0gW107XG4gICAgICBmb3IgKGkgPSAwOyBpIDwgcGFyc2VkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGlmIChwYXJzZWRbaV0gIT09IG51bGwgJiYgalF1ZXJ5LnRyaW0ocGFyc2VkW2ldKS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgcmVzdWx0LnB1c2gocGFyc2VkW2ldKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdC5sZW5ndGggPiAwID8gcmVzdWx0IDogbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRleHRBcmVhLnZhbHVlO1xuICAgIH1cbiAgfSxcblxuICBzaG93U25pcHBldDogZnVuY3Rpb24gKCkge1xuICAgIHZhciBjb250ZW50VHlwZUVsID0gdGhpcy4kKCdbbmFtZT1yZXNwb25zZUNvbnRlbnRUeXBlXScpO1xuICAgIHZhciB4bWxTbmlwcGV0RWwgPSB0aGlzLiQoJy5vcGVyYXRpb24tc3RhdHVzIC5zbmlwcGV0X3htbCwgLnJlc3BvbnNlLWNsYXNzIC5zbmlwcGV0X3htbCcpO1xuICAgIHZhciBqc29uU25pcHBldEVsID0gdGhpcy4kKCcub3BlcmF0aW9uLXN0YXR1cyAuc25pcHBldF9qc29uLCAucmVzcG9uc2UtY2xhc3MgLnNuaXBwZXRfanNvbicpO1xuICAgIHZhciBjb250ZW50VHlwZTtcblxuICAgIGlmICghY29udGVudFR5cGVFbC5sZW5ndGgpIHsgcmV0dXJuOyB9XG4gICAgY29udGVudFR5cGUgPSBjb250ZW50VHlwZUVsLnZhbCgpO1xuXG4gICAgaWYgKGNvbnRlbnRUeXBlLmluZGV4T2YoJ3htbCcpID4gLTEpIHtcbiAgICAgIHhtbFNuaXBwZXRFbC5zaG93KCk7XG4gICAgICBqc29uU25pcHBldEVsLmhpZGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAganNvblNuaXBwZXRFbC5zaG93KCk7XG4gICAgICB4bWxTbmlwcGV0RWwuaGlkZSgpO1xuICAgIH1cbiAgfSxcblxuICBnZXRQYXJhbUJ5TmFtZTogZnVuY3Rpb24obmFtZSkge1xuICAgIHZhciBpO1xuICAgIGlmICh0aGlzLm1vZGVsLnBhcmFtZXRlcnMpIHtcbiAgICAgIGZvcihpID0gMDsgaSA8IHRoaXMubW9kZWwucGFyYW1ldGVycy5sZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAodGhpcy5tb2RlbC5wYXJhbWV0ZXJzW2ldLm5hbWUgPT09IG5hbWUpIHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5tb2RlbC5wYXJhbWV0ZXJzW2ldO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5Td2FnZ2VyVWkuVmlld3MuUGFyYW1ldGVyQ29udGVudFR5cGVWaWV3ID0gQmFja2JvbmUuVmlldy5leHRlbmQoe1xuICBpbml0aWFsaXplOiBmdW5jdGlvbiAgKCkge30sXG5cbiAgcmVuZGVyOiBmdW5jdGlvbigpe1xuICAgIHRoaXMubW9kZWwucGFyYW1ldGVyQ29udGVudFR5cGVJZCA9ICdwY3QnICsgTWF0aC5yYW5kb20oKTtcbiAgICAkKHRoaXMuZWwpLmh0bWwoSGFuZGxlYmFycy50ZW1wbGF0ZXMucGFyYW1ldGVyX2NvbnRlbnRfdHlwZSh0aGlzLm1vZGVsKSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxufSk7IiwiJ3VzZSBzdHJpY3QnO1xuXG5Td2FnZ2VyVWkuVmlld3MuUGFyYW1ldGVyVmlldyA9IEJhY2tib25lLlZpZXcuZXh0ZW5kKHtcbiAgZXZlbnRzOiB7XG4gICAgJ2NoYW5nZSBbbmFtZT1wYXJhbWV0ZXJDb250ZW50VHlwZV0nIDogJ3RvZ2dsZVBhcmFtZXRlclNuaXBwZXQnXG4gIH0sXG5cbiAgaW5pdGlhbGl6ZTogZnVuY3Rpb24oKXtcbiAgICBIYW5kbGViYXJzLnJlZ2lzdGVySGVscGVyKCdpc0FycmF5JywgZnVuY3Rpb24ocGFyYW0sIG9wdHMpIHtcbiAgICAgIHZhciBwYXJhbVR5cGUgPSBwYXJhbS50eXBlICYmIHBhcmFtLnR5cGUudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmIChwYXJhbVR5cGUgPT09ICdhcnJheScgfHwgcGFyYW0uYWxsb3dNdWx0aXBsZSkge1xuICAgICAgICByZXR1cm4gb3B0cy5mbih0aGlzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBvcHRzLmludmVyc2UodGhpcyk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0sXG5cbiAgcmVuZGVyOiBmdW5jdGlvbigpIHtcbiAgICB2YXIgdHlwZSA9IHRoaXMubW9kZWwudHlwZSB8fCB0aGlzLm1vZGVsLmRhdGFUeXBlO1xuICAgIHZhciBtb2RlbFR5cGUgPSB0aGlzLm1vZGVsLm1vZGVsU2lnbmF0dXJlLnR5cGU7XG4gICAgdmFyIG1vZGVsRGVmaW5pdGlvbnMgPSB0aGlzLm1vZGVsLm1vZGVsU2lnbmF0dXJlLmRlZmluaXRpb25zO1xuICAgIHZhciBzY2hlbWEgPSB0aGlzLm1vZGVsLnNjaGVtYSB8fCB7fTtcbiAgICB2YXIgY29uc3VtZXMgPSB0aGlzLm1vZGVsLmNvbnN1bWVzIHx8IFtdO1xuICAgIHZhciBzYW1wbGVKU09OLCBzaWduYXR1cmVWaWV3O1xuXG4gICAgaWYgKHR5cGVvZiB0eXBlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgaWYgKHNjaGVtYS4kcmVmKSB7XG4gICAgICAgIHZhciByZWYgPSBzY2hlbWEuJHJlZjtcbiAgICAgICAgaWYgKHJlZi5pbmRleE9mKCcjL2RlZmluaXRpb25zLycpID09PSAwKSB7XG4gICAgICAgICAgdHlwZSA9IHJlZi5zdWJzdHJpbmcoJyMvZGVmaW5pdGlvbnMvJy5sZW5ndGgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHR5cGUgPSByZWY7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLm1vZGVsLnR5cGUgPSB0eXBlO1xuICAgIHRoaXMubW9kZWwucGFyYW1UeXBlID0gdGhpcy5tb2RlbC5pbiB8fCB0aGlzLm1vZGVsLnBhcmFtVHlwZTtcbiAgICB0aGlzLm1vZGVsLmlzQm9keSA9IHRoaXMubW9kZWwucGFyYW1UeXBlID09PSAnYm9keScgfHwgdGhpcy5tb2RlbC5pbiA9PT0gJ2JvZHknO1xuICAgIHRoaXMubW9kZWwuaXNGaWxlID0gdHlwZSAmJiB0eXBlLnRvTG93ZXJDYXNlKCkgPT09ICdmaWxlJztcblxuICAgIC8vIEFsbG93IGZvciBkZWZhdWx0ID09PSBmYWxzZVxuICAgIGlmKHR5cGVvZiB0aGlzLm1vZGVsLmRlZmF1bHQgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICB0aGlzLm1vZGVsLmRlZmF1bHQgPSB0aGlzLm1vZGVsLmRlZmF1bHRWYWx1ZTtcbiAgICB9XG5cbiAgICB0aGlzLm1vZGVsLmhhc0RlZmF1bHQgPSAodHlwZW9mIHRoaXMubW9kZWwuZGVmYXVsdCAhPT0gJ3VuZGVmaW5lZCcpO1xuICAgIHRoaXMubW9kZWwudmFsdWVJZCA9ICdtJyArIHRoaXMubW9kZWwubmFtZSArIE1hdGgucmFuZG9tKCk7XG5cbiAgICBpZiAodGhpcy5tb2RlbC5hbGxvd2FibGVWYWx1ZXMpIHtcbiAgICAgIHRoaXMubW9kZWwuaXNMaXN0ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB2YXIgaXNYTUwgPSB0aGlzLmNvbnRhaW5zKGNvbnN1bWVzLCAneG1sJyk7XG4gICAgdmFyIGlzSlNPTiA9IGlzWE1MID8gdGhpcy5jb250YWlucyhjb25zdW1lcywgJ2pzb24nKSA6IHRydWU7XG4gICAgc2FtcGxlSlNPTiA9IFN3YWdnZXJVaS5wYXJ0aWFscy5zaWduYXR1cmUuY3JlYXRlUGFyYW1ldGVySlNPTlNhbXBsZShtb2RlbFR5cGUsIG1vZGVsRGVmaW5pdGlvbnMpO1xuXG4gICAgdmFyIHRlbXBsYXRlID0gdGhpcy50ZW1wbGF0ZSgpO1xuICAgICQodGhpcy5lbCkuaHRtbCh0ZW1wbGF0ZSh0aGlzLm1vZGVsKSk7XG5cbiAgICB2YXIgc2lnbmF0dXJlTW9kZWwgPSB7XG4gICAgICBzYW1wbGVKU09OOiBpc0pTT04gPyBzYW1wbGVKU09OIDogZmFsc2UsXG4gICAgICBzYW1wbGVYTUw6IHNhbXBsZUpTT04gJiYgaXNYTUwgPyBTd2FnZ2VyVWkucGFydGlhbHMuc2lnbmF0dXJlLmNyZWF0ZVhNTFNhbXBsZSgnJywgc2NoZW1hLCBtb2RlbERlZmluaXRpb25zLCB0cnVlKSA6IGZhbHNlLFxuICAgICAgaXNQYXJhbTogdHJ1ZSxcbiAgICAgIHNpZ25hdHVyZTogU3dhZ2dlclVpLnBhcnRpYWxzLnNpZ25hdHVyZS5nZXRQYXJhbWV0ZXJNb2RlbFNpZ25hdHVyZShtb2RlbFR5cGUsIG1vZGVsRGVmaW5pdGlvbnMpLFxuICAgICAgZGVmYXVsdFJlbmRlcmluZzogdGhpcy5tb2RlbC5kZWZhdWx0UmVuZGVyaW5nXG4gICAgfTtcblxuICAgIGlmIChzYW1wbGVKU09OKSB7XG4gICAgICBzaWduYXR1cmVWaWV3ID0gbmV3IFN3YWdnZXJVaS5WaWV3cy5TaWduYXR1cmVWaWV3KHttb2RlbDogc2lnbmF0dXJlTW9kZWwsIHRhZ05hbWU6ICdkaXYnfSk7XG4gICAgICAkKCcubW9kZWwtc2lnbmF0dXJlJywgJCh0aGlzLmVsKSkuYXBwZW5kKHNpZ25hdHVyZVZpZXcucmVuZGVyKCkuZWwpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICQoJy5tb2RlbC1zaWduYXR1cmUnLCAkKHRoaXMuZWwpKS5odG1sKHRoaXMubW9kZWwuc2lnbmF0dXJlKTtcbiAgICB9XG5cbiAgICB2YXIgaXNQYXJhbSA9IGZhbHNlO1xuXG4gICAgaWYoIHRoaXMub3B0aW9ucy5zd2FnZ2VyT3B0aW9ucy5qc29uRWRpdG9yICYmIHRoaXMubW9kZWwuaXNCb2R5ICYmIHRoaXMubW9kZWwuc2NoZW1hKXtcbiAgICAgIHZhciAkc2VsZiA9ICQodGhpcy5lbCk7XG4gICAgICB0aGlzLm1vZGVsLmpzb25FZGl0b3IgPVxuICAgICAgICAvKiBnbG9iYWwgSlNPTkVkaXRvciAqL1xuICAgICAgICBuZXcgSlNPTkVkaXRvcigkKCcuZWRpdG9yX2hvbGRlcicsICRzZWxmKVswXSxcbiAgICAgICAgICAgICAgICAgICAgICAge3NjaGVtYTogdGhpcy5tb2RlbC5zY2hlbWEsIHN0YXJ0dmFsIDogdGhpcy5tb2RlbC5kZWZhdWx0LFxuICAgICAgICAgICAgICAgICAgICAgICAgYWpheDp0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGlzYWJsZV9wcm9wZXJ0aWVzOnRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICBkaXNhYmxlX2VkaXRfanNvbjp0cnVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgaWNvbmxpYjogJ3N3YWdnZXInIH0pO1xuICAgICAgLy8gVGhpcyBpcyBzbyB0aGF0IHRoZSBzaWduYXR1cmUgY2FuIHNlbmQgYmFjayB0aGUgc2FtcGxlIHRvIHRoZSBqc29uIGVkaXRvclxuICAgICAgLy8gVE9ETzogU2lnbmF0dXJlVmlldyBzaG91bGQgZXhwb3NlIGFuIGV2ZW50IFwib25TYW1wbGVDbGlja2VkXCIgaW5zdGVhZFxuICAgICAgc2lnbmF0dXJlTW9kZWwuanNvbkVkaXRvciA9IHRoaXMubW9kZWwuanNvbkVkaXRvcjtcbiAgICAgICQoJy5ib2R5LXRleHRhcmVhJywgJHNlbGYpLmhpZGUoKTtcbiAgICAgICQoJy5lZGl0b3JfaG9sZGVyJywgJHNlbGYpLnNob3coKTtcbiAgICAgICQoJy5wYXJhbWV0ZXItY29udGVudC10eXBlJywgJHNlbGYpXG4gICAgICAgIC5jaGFuZ2UoZnVuY3Rpb24oZSl7XG4gICAgICAgICAgICBpZihlLnRhcmdldC52YWx1ZSA9PT0gJ2FwcGxpY2F0aW9uL3htbCcpe1xuICAgICAgICAgICAgICAkKCcuYm9keS10ZXh0YXJlYScsICRzZWxmKS5zaG93KCk7XG4gICAgICAgICAgICAgICQoJy5lZGl0b3JfaG9sZGVyJywgJHNlbGYpLmhpZGUoKTtcbiAgICAgICAgICAgICAgdGhpcy5tb2RlbC5qc29uRWRpdG9yLmRpc2FibGUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAkKCcuYm9keS10ZXh0YXJlYScsICRzZWxmKS5oaWRlKCk7XG4gICAgICAgICAgICAgICQoJy5lZGl0b3JfaG9sZGVyJywgJHNlbGYpLnNob3coKTtcbiAgICAgICAgICAgICAgdGhpcy5tb2RlbC5qc29uRWRpdG9yLmVuYWJsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH1cblxuXG4gICAgaWYgKHRoaXMubW9kZWwuaXNCb2R5KSB7XG4gICAgICBpc1BhcmFtID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB2YXIgY29udGVudFR5cGVNb2RlbCA9IHtcbiAgICAgIGlzUGFyYW06IGlzUGFyYW1cbiAgICB9O1xuXG4gICAgY29udGVudFR5cGVNb2RlbC5jb25zdW1lcyA9IHRoaXMubW9kZWwuY29uc3VtZXM7XG5cbiAgICBpZiAoaXNQYXJhbSkge1xuICAgICAgdmFyIHBhcmFtZXRlckNvbnRlbnRUeXBlVmlldyA9IG5ldyBTd2FnZ2VyVWkuVmlld3MuUGFyYW1ldGVyQ29udGVudFR5cGVWaWV3KHttb2RlbDogY29udGVudFR5cGVNb2RlbH0pO1xuICAgICAgJCgnLnBhcmFtZXRlci1jb250ZW50LXR5cGUnLCAkKHRoaXMuZWwpKS5hcHBlbmQocGFyYW1ldGVyQ29udGVudFR5cGVWaWV3LnJlbmRlcigpLmVsKTtcbiAgICAgIHRoaXMudG9nZ2xlUGFyYW1ldGVyU25pcHBldCgpO1xuICAgIH1cblxuICAgIGVsc2Uge1xuICAgICAgdmFyIHJlc3BvbnNlQ29udGVudFR5cGVWaWV3ID0gbmV3IFN3YWdnZXJVaS5WaWV3cy5SZXNwb25zZUNvbnRlbnRUeXBlVmlldyh7bW9kZWw6IGNvbnRlbnRUeXBlTW9kZWx9KTtcbiAgICAgICQoJy5yZXNwb25zZS1jb250ZW50LXR5cGUnLCAkKHRoaXMuZWwpKS5hcHBlbmQocmVzcG9uc2VDb250ZW50VHlwZVZpZXcucmVuZGVyKCkuZWwpO1xuICAgICAgdGhpcy50b2dnbGVSZXNwb25zZVNuaXBwZXQoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICBjb250YWluczogZnVuY3Rpb24gKGNvbnN1bWVzLCB0eXBlKSB7XG4gICAgcmV0dXJuIGNvbnN1bWVzLmZpbHRlcihmdW5jdGlvbiAodmFsKSB7XG4gICAgICBpZiAodmFsLmluZGV4T2YodHlwZSkgPiAtMSkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH1cbiAgICB9KS5sZW5ndGg7XG4gIH0sXG5cbiAgdG9nZ2xlUGFyYW1ldGVyU25pcHBldDogZnVuY3Rpb24gKCkge1xuICAgIHZhciBjb250ZW50VHlwZSA9IHRoaXMuJCgnW25hbWU9cGFyYW1ldGVyQ29udGVudFR5cGVdJykudmFsKCk7XG5cbiAgICB0aGlzLnRvZ2dsZVNuaXBwZXQoY29udGVudFR5cGUpO1xuICB9LFxuXG4gIHRvZ2dsZVJlc3BvbnNlU25pcHBldDogZnVuY3Rpb24gKCkge1xuICAgIHZhciBjb250ZW50RWwgPSB0aGlzLiQoJ1tuYW1lPXJlc3BvbnNlQ29udGVudFR5cGVdJyk7XG5cbiAgICBpZiAoIWNvbnRlbnRFbC5sZW5ndGgpIHsgcmV0dXJuOyB9XG5cbiAgICB0aGlzLnRvZ2dsZVNuaXBwZXQoY29udGVudEVsLnZhbCgpKTtcbiAgfSxcblxuICB0b2dnbGVTbmlwcGV0OiBmdW5jdGlvbiAodHlwZSkge1xuICAgIHR5cGUgPSB0eXBlIHx8ICcnO1xuICAgIGlmICh0eXBlLmluZGV4T2YoJ3htbCcpID4gLTEpIHtcbiAgICAgIHRoaXMuJCgnLnNuaXBwZXRfeG1sJykuc2hvdygpO1xuICAgICAgdGhpcy4kKCcuc25pcHBldF9qc29uJykuaGlkZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLiQoJy5zbmlwcGV0X2pzb24nKS5zaG93KCk7XG4gICAgICB0aGlzLiQoJy5zbmlwcGV0X3htbCcpLmhpZGUoKTtcbiAgICB9XG4gIH0sXG5cbiAgLy8gUmV0dXJuIGFuIGFwcHJvcHJpYXRlIHRlbXBsYXRlIGJhc2VkIG9uIGlmIHRoZSBwYXJhbWV0ZXIgaXMgYSBsaXN0LCByZWFkb25seSwgcmVxdWlyZWRcbiAgdGVtcGxhdGU6IGZ1bmN0aW9uKCl7XG4gICAgaWYgKHRoaXMubW9kZWwuaXNMaXN0KSB7XG4gICAgICByZXR1cm4gSGFuZGxlYmFycy50ZW1wbGF0ZXMucGFyYW1fbGlzdDtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKHRoaXMub3B0aW9ucy5yZWFkT25seSkge1xuICAgICAgICBpZiAodGhpcy5tb2RlbC5yZXF1aXJlZCkge1xuICAgICAgICAgIHJldHVybiBIYW5kbGViYXJzLnRlbXBsYXRlcy5wYXJhbV9yZWFkb25seV9yZXF1aXJlZDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gSGFuZGxlYmFycy50ZW1wbGF0ZXMucGFyYW1fcmVhZG9ubHk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh0aGlzLm1vZGVsLnJlcXVpcmVkKSB7XG4gICAgICAgICAgcmV0dXJuIEhhbmRsZWJhcnMudGVtcGxhdGVzLnBhcmFtX3JlcXVpcmVkO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBIYW5kbGViYXJzLnRlbXBsYXRlcy5wYXJhbTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cbi8qIGpzaGludCAtVzEyMiAqL1xuU3dhZ2dlclVpLnBhcnRpYWxzLnNpZ25hdHVyZSA9IChmdW5jdGlvbiAoKSB7XG4gIC8vIGNvcHktcGFzdGVkIGZyb20gc3dhZ2dlci1qc1xuICB2YXIgcmVzb2x2ZVNjaGVtYSA9IGZ1bmN0aW9uIChzY2hlbWEpIHtcbiAgICBpZiAoXy5pc1BsYWluT2JqZWN0KHNjaGVtYS5zY2hlbWEpKSB7XG4gICAgICBzY2hlbWEgPSByZXNvbHZlU2NoZW1hKHNjaGVtYS5zY2hlbWEpO1xuICAgIH1cblxuICAgIHJldHVybiBzY2hlbWE7XG4gIH07XG5cbiAgLy8gY29weS1wYXN0ZWQgZnJvbSBzd2FnZ2VyLWpzXG4gIHZhciBzaW1wbGVSZWYgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIGlmICh0eXBlb2YgbmFtZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGlmIChuYW1lLmluZGV4T2YoJyMvZGVmaW5pdGlvbnMvJykgPT09IDApIHtcbiAgICAgIHJldHVybiBuYW1lLnN1YnN0cmluZygnIy9kZWZpbml0aW9ucy8nLmxlbmd0aCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuYW1lO1xuICAgIH1cbiAgfTtcblxuICAvLyBjb3B5LXBhc3RlZCBmcm9tIHN3YWdnZXItanNcbiAgdmFyIGdldElubGluZU1vZGVsID0gZnVuY3Rpb24oaW5saW5lU3RyKSB7XG4gICAgaWYoL15JbmxpbmUgTW9kZWwgXFxkKyQvLnRlc3QoaW5saW5lU3RyKSAmJiB0aGlzLmlubGluZU1vZGVscykge1xuICAgICAgdmFyIGlkID0gcGFyc2VJbnQoaW5saW5lU3RyLnN1YnN0cignSW5saW5lIE1vZGVsJy5sZW5ndGgpLnRyaW0oKSwxMCk7IC8vXG4gICAgICB2YXIgbW9kZWwgPSB0aGlzLmlubGluZU1vZGVsc1tpZF07XG4gICAgICByZXR1cm4gbW9kZWw7XG4gICAgfVxuICAgIC8vIEknbSByZXR1cm5pbmcgbnVsbCBoZXJlLCBzaG91bGQgSSByYXRoZXIgdGhyb3cgYW4gZXJyb3I/XG4gICAgcmV0dXJuIG51bGw7XG4gIH07XG5cbiAgLy8gY29weS1wYXN0ZWQgZnJvbSBzd2FnZ2VyLWpzXG4gIHZhciBmb3JtYXRYbWwgPSBmdW5jdGlvbih4bWwpIHtcbiAgICB2YXIgY29udGV4cCwgZm4sIGZvcm1hdHRlZCwgaW5kZW50LCBsLCBsYXN0VHlwZSwgbGVuLCBsaW5lcywgbG4sIHBhZCwgcmVnLCB0cmFuc2l0aW9ucywgd3NleHA7XG4gICAgcmVnID0gLyg+KSg8KShcXC8qKS9nO1xuICAgIHdzZXhwID0gL1sgXSooLiopWyBdK1xcbi9nO1xuICAgIGNvbnRleHAgPSAvKDwuKz4pKC4rXFxuKS9nO1xuICAgIHhtbCA9IHhtbC5yZXBsYWNlKHJlZywgJyQxXFxuJDIkMycpLnJlcGxhY2Uod3NleHAsICckMVxcbicpLnJlcGxhY2UoY29udGV4cCwgJyQxXFxuJDInKTtcbiAgICBwYWQgPSAwO1xuICAgIGZvcm1hdHRlZCA9ICcnO1xuICAgIGxpbmVzID0geG1sLnNwbGl0KCdcXG4nKTtcbiAgICBpbmRlbnQgPSAwO1xuICAgIGxhc3RUeXBlID0gJ290aGVyJztcbiAgICB0cmFuc2l0aW9ucyA9IHtcbiAgICAgICdzaW5nbGUtPnNpbmdsZSc6IDAsXG4gICAgICAnc2luZ2xlLT5jbG9zaW5nJzogLTEsXG4gICAgICAnc2luZ2xlLT5vcGVuaW5nJzogMCxcbiAgICAgICdzaW5nbGUtPm90aGVyJzogMCxcbiAgICAgICdjbG9zaW5nLT5zaW5nbGUnOiAwLFxuICAgICAgJ2Nsb3NpbmctPmNsb3NpbmcnOiAtMSxcbiAgICAgICdjbG9zaW5nLT5vcGVuaW5nJzogMCxcbiAgICAgICdjbG9zaW5nLT5vdGhlcic6IDAsXG4gICAgICAnb3BlbmluZy0+c2luZ2xlJzogMSxcbiAgICAgICdvcGVuaW5nLT5jbG9zaW5nJzogMCxcbiAgICAgICdvcGVuaW5nLT5vcGVuaW5nJzogMSxcbiAgICAgICdvcGVuaW5nLT5vdGhlcic6IDEsXG4gICAgICAnb3RoZXItPnNpbmdsZSc6IDAsXG4gICAgICAnb3RoZXItPmNsb3NpbmcnOiAtMSxcbiAgICAgICdvdGhlci0+b3BlbmluZyc6IDAsXG4gICAgICAnb3RoZXItPm90aGVyJzogMFxuICAgIH07XG4gICAgZm4gPSBmdW5jdGlvbihsbikge1xuICAgICAgdmFyIGZyb21Ubywgaiwga2V5LCBwYWRkaW5nLCB0eXBlLCB0eXBlcywgdmFsdWU7XG4gICAgICB0eXBlcyA9IHtcbiAgICAgICAgc2luZ2xlOiBCb29sZWFuKGxuLm1hdGNoKC88LitcXC8+LykpLFxuICAgICAgICBjbG9zaW5nOiBCb29sZWFuKGxuLm1hdGNoKC88XFwvLis+LykpLFxuICAgICAgICBvcGVuaW5nOiBCb29sZWFuKGxuLm1hdGNoKC88W14hP10uKj4vKSlcbiAgICAgIH07XG4gICAgICB0eXBlID0gKChmdW5jdGlvbigpIHtcbiAgICAgICAgdmFyIHJlc3VsdHM7XG4gICAgICAgIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgZm9yIChrZXkgaW4gdHlwZXMpIHtcbiAgICAgICAgICB2YWx1ZSA9IHR5cGVzW2tleV07XG4gICAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgICByZXN1bHRzLnB1c2goa2V5KTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgICB9KSgpKVswXTtcbiAgICAgIHR5cGUgPSB0eXBlID09PSB2b2lkIDAgPyAnb3RoZXInIDogdHlwZTtcbiAgICAgIGZyb21UbyA9IGxhc3RUeXBlICsgJy0+JyArIHR5cGU7XG4gICAgICBsYXN0VHlwZSA9IHR5cGU7XG4gICAgICBwYWRkaW5nID0gJyc7XG4gICAgICBpbmRlbnQgKz0gdHJhbnNpdGlvbnNbZnJvbVRvXTtcbiAgICAgIHBhZGRpbmcgPSAoKGZ1bmN0aW9uKCkge1xuICAgICAgICB2YXIgbSwgcmVmMSwgcmVzdWx0cztcbiAgICAgICAgcmVzdWx0cyA9IFtdO1xuICAgICAgICBmb3IgKGogPSBtID0gMCwgcmVmMSA9IGluZGVudDsgMCA8PSByZWYxID8gbSA8IHJlZjEgOiBtID4gcmVmMTsgaiA9IDAgPD0gcmVmMSA/ICsrbSA6IC0tbSkge1xuICAgICAgICAgIHJlc3VsdHMucHVzaCgnICAnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgIH0pKCkpLmpvaW4oJycpO1xuICAgICAgaWYgKGZyb21UbyA9PT0gJ29wZW5pbmctPmNsb3NpbmcnKSB7XG4gICAgICAgIGZvcm1hdHRlZCA9IGZvcm1hdHRlZC5zdWJzdHIoMCwgZm9ybWF0dGVkLmxlbmd0aCAtIDEpICsgbG4gKyAnXFxuJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvcm1hdHRlZCArPSBwYWRkaW5nICsgbG4gKyAnXFxuJztcbiAgICAgIH1cbiAgICB9O1xuICAgIGZvciAobCA9IDAsIGxlbiA9IGxpbmVzLmxlbmd0aDsgbCA8IGxlbjsgbCsrKSB7XG4gICAgICBsbiA9IGxpbmVzW2xdO1xuICAgICAgZm4obG4pO1xuICAgIH1cbiAgICByZXR1cm4gZm9ybWF0dGVkO1xuICB9O1xuXG4gIC8vIGNvcHktcGFzdGVkIGZyb20gc3dhZ2dlci1qc1xuICB2YXIgZ2V0TW9kZWxTaWduYXR1cmUgPSBmdW5jdGlvbiAobmFtZSwgc2NoZW1hLCBtb2RlbHMsIG1vZGVsUHJvcGVydHlNYWNybykge1xuICAgIHZhciBzdHJvbmdPcGVuID0gJzxzcGFuIGNsYXNzPVwic3Ryb25nXCI+JztcbiAgICB2YXIgc3Ryb25nQ2xvc2UgPSAnPC9zcGFuPic7XG5cbiAgICB2YXIgb3B0aW9uSHRtbCA9IGZ1bmN0aW9uIChsYWJlbCwgdmFsdWUpIHtcbiAgICAgIHJldHVybiAnPHRyPjx0ZCBjbGFzcz1cIm9wdGlvbk5hbWVcIj4nICsgbGFiZWwgKyAnOjwvdGQ+PHRkPicgKyB2YWx1ZSArICc8L3RkPjwvdHI+JztcbiAgICB9O1xuXG5cbiAgICAvLyBBbGxvdyBmb3IgaWdub3JpbmcgdGhlICduYW1lJyBhcmd1bWVudC4uLi4gc2hpZnRpbmcgdGhlIHJlc3RcbiAgICBpZihfLmlzT2JqZWN0KGFyZ3VtZW50c1swXSkpIHtcbiAgICAgIG5hbWUgPSB2b2lkIDA7XG4gICAgICBzY2hlbWEgPSBhcmd1bWVudHNbMF07XG4gICAgICBtb2RlbHMgPSBhcmd1bWVudHNbMV07XG4gICAgICBtb2RlbFByb3BlcnR5TWFjcm8gPSBhcmd1bWVudHNbMl07XG4gICAgfVxuXG4gICAgbW9kZWxzID0gbW9kZWxzIHx8IHt9O1xuXG4gICAgLy8gUmVzb2x2ZSB0aGUgc2NoZW1hIChIYW5kbGUgbmVzdGVkIHNjaGVtYXMpXG4gICAgc2NoZW1hID0gcmVzb2x2ZVNjaGVtYShzY2hlbWEpO1xuXG4gICAgLy8gUmV0dXJuIGZvciBlbXB0eSBvYmplY3RcbiAgICBpZihfLmlzRW1wdHkoc2NoZW1hKSkge1xuICAgICAgcmV0dXJuIHN0cm9uZ09wZW4gKyAnRW1wdHknICsgc3Ryb25nQ2xvc2U7XG4gICAgfVxuXG4gICAgLy8gRGVyZWZlcmVuY2UgJHJlZiBmcm9tICdtb2RlbHMnXG4gICAgaWYodHlwZW9mIHNjaGVtYS4kcmVmID09PSAnc3RyaW5nJykge1xuICAgICAgbmFtZSA9IHNpbXBsZVJlZihzY2hlbWEuJHJlZik7XG4gICAgICBzY2hlbWEgPSBtb2RlbHNbbmFtZV07XG4gICAgICBpZih0eXBlb2Ygc2NoZW1hID09PSAndW5kZWZpbmVkJylcbiAgICAgIHtcbiAgICAgICAgcmV0dXJuIHN0cm9uZ09wZW4gKyBuYW1lICsgJyBpcyBub3QgZGVmaW5lZCEnICsgc3Ryb25nQ2xvc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYodHlwZW9mIG5hbWUgIT09ICdzdHJpbmcnKSB7XG4gICAgICBuYW1lID0gc2NoZW1hLnRpdGxlIHx8ICdJbmxpbmUgTW9kZWwnO1xuICAgIH1cblxuICAgIC8vIElmIHdlIGFyZSBhIE1vZGVsIG9iamVjdC4uLiBhZGp1c3QgYWNjb3JkaW5nbHlcbiAgICBpZihzY2hlbWEuZGVmaW5pdGlvbikge1xuICAgICAgc2NoZW1hID0gc2NoZW1hLmRlZmluaXRpb247XG4gICAgfVxuXG4gICAgaWYodHlwZW9mIG1vZGVsUHJvcGVydHlNYWNybyAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgbW9kZWxQcm9wZXJ0eU1hY3JvID0gZnVuY3Rpb24ocHJvcCl7XG4gICAgICAgIHJldHVybiAocHJvcCB8fCB7fSkuZGVmYXVsdDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIHJlZmVyZW5jZXMgPSB7fTtcbiAgICB2YXIgc2Vlbk1vZGVscyA9IFtdO1xuICAgIHZhciBpbmxpbmVNb2RlbHMgPSAwO1xuXG4gICAgLy8gR2VuZXJhdGUgY3VycmVudCBIVE1MXG4gICAgdmFyIGh0bWwgPSBwcm9jZXNzTW9kZWwoc2NoZW1hLCBuYW1lKTtcblxuICAgIC8vIEdlbmVyYXRlIHJlZmVyZW5jZXMgSFRNTFxuICAgIHdoaWxlIChfLmtleXMocmVmZXJlbmNlcykubGVuZ3RoID4gMCkge1xuICAgICAgLyoganNoaW50IGlnbm9yZTpzdGFydCAqL1xuICAgICAgXy5mb3JFYWNoKHJlZmVyZW5jZXMsIGZ1bmN0aW9uIChzY2hlbWEsIG5hbWUpIHtcbiAgICAgICAgdmFyIHNlZW5Nb2RlbCA9IF8uaW5kZXhPZihzZWVuTW9kZWxzLCBuYW1lKSA+IC0xO1xuXG4gICAgICAgIGRlbGV0ZSByZWZlcmVuY2VzW25hbWVdO1xuXG4gICAgICAgIGlmICghc2Vlbk1vZGVsKSB7XG4gICAgICAgICAgc2Vlbk1vZGVscy5wdXNoKG5hbWUpO1xuXG4gICAgICAgICAgaHRtbCArPSAnPGJyIC8+JyArIHByb2Nlc3NNb2RlbChzY2hlbWEsIG5hbWUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIC8qIGpzaGludCBpZ25vcmU6ZW5kICovXG4gICAgfVxuXG4gICAgcmV0dXJuIGh0bWw7XG5cblxuICAgIGZ1bmN0aW9uIGFkZFJlZmVyZW5jZShzY2hlbWEsIG5hbWUsIHNraXBSZWYpIHtcbiAgICAgIHZhciBtb2RlbE5hbWUgPSBuYW1lO1xuICAgICAgdmFyIG1vZGVsO1xuXG4gICAgICBpZiAoc2NoZW1hLiRyZWYpIHtcbiAgICAgICAgbW9kZWxOYW1lID0gc2NoZW1hLnRpdGxlIHx8IHNpbXBsZVJlZihzY2hlbWEuJHJlZik7XG4gICAgICAgIG1vZGVsID0gbW9kZWxzW3NpbXBsZVJlZihzY2hlbWEuJHJlZildO1xuICAgICAgfSBlbHNlIGlmIChfLmlzVW5kZWZpbmVkKG5hbWUpKSB7XG4gICAgICAgIG1vZGVsTmFtZSA9IHNjaGVtYS50aXRsZSB8fCAnSW5saW5lIE1vZGVsICcgKyAoKytpbmxpbmVNb2RlbHMpO1xuICAgICAgICBtb2RlbCA9IHtkZWZpbml0aW9uOiBzY2hlbWF9O1xuICAgICAgfVxuXG4gICAgICBpZiAoc2tpcFJlZiAhPT0gdHJ1ZSkge1xuICAgICAgICByZWZlcmVuY2VzW21vZGVsTmFtZV0gPSBfLmlzVW5kZWZpbmVkKG1vZGVsKSA/IHt9IDogbW9kZWwuZGVmaW5pdGlvbjtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG1vZGVsTmFtZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwcmltaXRpdmVUb0hUTUwoc2NoZW1hKSB7XG4gICAgICB2YXIgaHRtbCA9ICc8c3BhbiBjbGFzcz1cInByb3BUeXBlXCI+JztcbiAgICAgIHZhciB0eXBlID0gc2NoZW1hLnR5cGUgfHwgJ29iamVjdCc7XG5cbiAgICAgIGlmIChzY2hlbWEuJHJlZikge1xuICAgICAgICBodG1sICs9IGFkZFJlZmVyZW5jZShzY2hlbWEsIHNpbXBsZVJlZihzY2hlbWEuJHJlZikpO1xuICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgICBpZiAoIV8uaXNVbmRlZmluZWQoc2NoZW1hLnByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgaHRtbCArPSBhZGRSZWZlcmVuY2Uoc2NoZW1hKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBodG1sICs9ICdvYmplY3QnO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgaHRtbCArPSAnQXJyYXlbJztcblxuICAgICAgICBpZiAoXy5pc0FycmF5KHNjaGVtYS5pdGVtcykpIHtcbiAgICAgICAgICBodG1sICs9IF8ubWFwKHNjaGVtYS5pdGVtcywgYWRkUmVmZXJlbmNlKS5qb2luKCcsJyk7XG4gICAgICAgIH0gZWxzZSBpZiAoXy5pc1BsYWluT2JqZWN0KHNjaGVtYS5pdGVtcykpIHtcbiAgICAgICAgICBpZiAoXy5pc1VuZGVmaW5lZChzY2hlbWEuaXRlbXMuJHJlZikpIHtcbiAgICAgICAgICAgIGlmICghXy5pc1VuZGVmaW5lZChzY2hlbWEuaXRlbXMudHlwZSkgJiYgXy5pbmRleE9mKFsnYXJyYXknLCAnb2JqZWN0J10sIHNjaGVtYS5pdGVtcy50eXBlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgaHRtbCArPSBzY2hlbWEuaXRlbXMudHlwZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIGh0bWwgKz0gYWRkUmVmZXJlbmNlKHNjaGVtYS5pdGVtcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGh0bWwgKz0gYWRkUmVmZXJlbmNlKHNjaGVtYS5pdGVtcywgc2ltcGxlUmVmKHNjaGVtYS5pdGVtcy4kcmVmKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdBcnJheSB0eXBlXFwncyBcXCdpdGVtc1xcJyBzY2hlbWEgaXMgbm90IGFuIGFycmF5IG9yIGFuIG9iamVjdCwgY2Fubm90IHByb2Nlc3MnKTtcbiAgICAgICAgICBodG1sICs9ICdvYmplY3QnO1xuICAgICAgICB9XG5cbiAgICAgICAgaHRtbCArPSAnXSc7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBodG1sICs9IHNjaGVtYS50eXBlO1xuICAgICAgfVxuXG4gICAgICBodG1sICs9ICc8L3NwYW4+JztcblxuICAgICAgcmV0dXJuIGh0bWw7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcHJpbWl0aXZlVG9PcHRpb25zSFRNTChzY2hlbWEsIGh0bWwpIHtcbiAgICAgIHZhciBvcHRpb25zID0gJyc7XG4gICAgICB2YXIgdHlwZSA9IHNjaGVtYS50eXBlIHx8ICdvYmplY3QnO1xuICAgICAgdmFyIGlzQXJyYXkgPSB0eXBlID09PSAnYXJyYXknO1xuXG4gICAgICBpZiAoIV8uaXNVbmRlZmluZWQoc2NoZW1hLmRlc2NyaXB0aW9uKSkge1xuICAgICAgICBodG1sICs9ICc6ICcgKyAnPHNwYW4gY2xhc3M9XCJwcm9wRGVzY1wiPicgKyBzY2hlbWEuZGVzY3JpcHRpb24gKyAnPC9zcGFuPic7XG4gICAgICB9XG5cbiAgICAgIGlmIChzY2hlbWEuZW51bSkge1xuICAgICAgICBodG1sICs9ICcgPSA8c3BhbiBjbGFzcz1cInByb3BWYWxzXCI+W1xcJycgKyBzY2hlbWEuZW51bS5qb2luKCdcXCcsIFxcJycpICsgJ1xcJ108L3NwYW4+JztcbiAgICAgIH1cblxuICAgICAgaWYgKGlzQXJyYXkpIHtcbiAgICAgICAgaWYgKF8uaXNQbGFpbk9iamVjdChzY2hlbWEuaXRlbXMpICYmICFfLmlzVW5kZWZpbmVkKHNjaGVtYS5pdGVtcy50eXBlKSkge1xuICAgICAgICAgIHR5cGUgPSBzY2hlbWEuaXRlbXMudHlwZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0eXBlID0gJ29iamVjdCc7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKCFfLmlzVW5kZWZpbmVkKHNjaGVtYS5kZWZhdWx0KSkge1xuICAgICAgICBvcHRpb25zICs9IG9wdGlvbkh0bWwoJ0RlZmF1bHQnLCBzY2hlbWEuZGVmYXVsdCk7XG4gICAgICB9XG5cbiAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgICAgaWYgKHNjaGVtYS5taW5MZW5ndGgpIHtcbiAgICAgICAgICBvcHRpb25zICs9IG9wdGlvbkh0bWwoJ01pbi4gTGVuZ3RoJywgc2NoZW1hLm1pbkxlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2NoZW1hLm1heExlbmd0aCkge1xuICAgICAgICAgIG9wdGlvbnMgKz0gb3B0aW9uSHRtbCgnTWF4LiBMZW5ndGgnLCBzY2hlbWEubWF4TGVuZ3RoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzY2hlbWEucGF0dGVybikge1xuICAgICAgICAgIG9wdGlvbnMgKz0gb3B0aW9uSHRtbCgnUmVnLiBFeHAuJywgc2NoZW1hLnBhdHRlcm4pO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW50ZWdlcic6XG4gICAgICBjYXNlICdudW1iZXInOlxuICAgICAgICBpZiAoc2NoZW1hLm1pbmltdW0pIHtcbiAgICAgICAgICBvcHRpb25zICs9IG9wdGlvbkh0bWwoJ01pbi4gVmFsdWUnLCBzY2hlbWEubWluaW11bSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2NoZW1hLmV4Y2x1c2l2ZU1pbmltdW0pIHtcbiAgICAgICAgICBvcHRpb25zICs9IG9wdGlvbkh0bWwoJ0V4Y2x1c2l2ZSBNaW4uJywgJ3RydWUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzY2hlbWEubWF4aW11bSkge1xuICAgICAgICAgIG9wdGlvbnMgKz0gb3B0aW9uSHRtbCgnTWF4LiBWYWx1ZScsIHNjaGVtYS5tYXhpbXVtKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzY2hlbWEuZXhjbHVzaXZlTWF4aW11bSkge1xuICAgICAgICAgIG9wdGlvbnMgKz0gb3B0aW9uSHRtbCgnRXhjbHVzaXZlIE1heC4nLCAndHJ1ZScpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNjaGVtYS5tdWx0aXBsZU9mKSB7XG4gICAgICAgICAgb3B0aW9ucyArPSBvcHRpb25IdG1sKCdNdWx0aXBsZSBPZicsIHNjaGVtYS5tdWx0aXBsZU9mKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNBcnJheSkge1xuICAgICAgICBpZiAoc2NoZW1hLm1pbkl0ZW1zKSB7XG4gICAgICAgICAgb3B0aW9ucyArPSBvcHRpb25IdG1sKCdNaW4uIEl0ZW1zJywgc2NoZW1hLm1pbkl0ZW1zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzY2hlbWEubWF4SXRlbXMpIHtcbiAgICAgICAgICBvcHRpb25zICs9IG9wdGlvbkh0bWwoJ01heC4gSXRlbXMnLCBzY2hlbWEubWF4SXRlbXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNjaGVtYS51bmlxdWVJdGVtcykge1xuICAgICAgICAgIG9wdGlvbnMgKz0gb3B0aW9uSHRtbCgnVW5pcXVlIEl0ZW1zJywgJ3RydWUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzY2hlbWEuY29sbGVjdGlvbkZvcm1hdCkge1xuICAgICAgICAgIG9wdGlvbnMgKz0gb3B0aW9uSHRtbCgnQ29sbC4gRm9ybWF0Jywgc2NoZW1hLmNvbGxlY3Rpb25Gb3JtYXQpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChfLmlzVW5kZWZpbmVkKHNjaGVtYS5pdGVtcykpIHtcbiAgICAgICAgaWYgKF8uaXNBcnJheShzY2hlbWEuZW51bSkpIHtcbiAgICAgICAgICB2YXIgZW51bVN0cmluZztcblxuICAgICAgICAgIGlmICh0eXBlID09PSAnbnVtYmVyJyB8fCB0eXBlID09PSAnaW50ZWdlcicpIHtcbiAgICAgICAgICAgIGVudW1TdHJpbmcgPSBzY2hlbWEuZW51bS5qb2luKCcsICcpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbnVtU3RyaW5nID0gJ1wiJyArIHNjaGVtYS5lbnVtLmpvaW4oJ1wiLCBcIicpICsgJ1wiJztcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBvcHRpb25zICs9IG9wdGlvbkh0bWwoJ0VudW0nLCBlbnVtU3RyaW5nKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGh0bWwgPSAnPHNwYW4gY2xhc3M9XCJwcm9wV3JhcFwiPicgKyBodG1sICsgJzx0YWJsZSBjbGFzcz1cIm9wdGlvbnNXcmFwcGVyXCI+PHRyPjx0aCBjb2xzcGFuPVwiMlwiPicgKyB0eXBlICsgJzwvdGg+PC90cj4nICsgb3B0aW9ucyArICc8L3RhYmxlPjwvc3Bhbj4nO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gaHRtbDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwcm9jZXNzTW9kZWwoc2NoZW1hLCBuYW1lKSB7XG4gICAgICB2YXIgdHlwZSA9IHNjaGVtYS50eXBlIHx8ICdvYmplY3QnO1xuICAgICAgdmFyIGlzQXJyYXkgPSBzY2hlbWEudHlwZSA9PT0gJ2FycmF5JztcbiAgICAgIHZhciBodG1sID0gc3Ryb25nT3BlbiArIG5hbWUgKyAnICcgKyAoaXNBcnJheSA/ICdbJyA6ICd7JykgKyBzdHJvbmdDbG9zZTtcbiAgICAgIHZhciBjb250ZW50cztcblxuICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgc2Vlbk1vZGVscy5wdXNoKG5hbWUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNBcnJheSkge1xuICAgICAgICBpZiAoXy5pc0FycmF5KHNjaGVtYS5pdGVtcykpIHtcbiAgICAgICAgICBodG1sICs9ICc8ZGl2PicgKyBfLm1hcChzY2hlbWEuaXRlbXMsIGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgICAgICB2YXIgdHlwZSA9IGl0ZW0udHlwZSB8fCAnb2JqZWN0JztcblxuICAgICAgICAgICAgaWYgKF8uaXNVbmRlZmluZWQoaXRlbS4kcmVmKSkge1xuICAgICAgICAgICAgICBpZiAoXy5pbmRleE9mKFsnYXJyYXknLCAnb2JqZWN0J10sIHR5cGUpID4gLTEpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZSA9PT0gJ29iamVjdCcgJiYgXy5pc1VuZGVmaW5lZChpdGVtLnByb3BlcnRpZXMpKSB7XG4gICAgICAgICAgICAgICAgICByZXR1cm4gJ29iamVjdCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBhZGRSZWZlcmVuY2UoaXRlbSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBwcmltaXRpdmVUb09wdGlvbnNIVE1MKGl0ZW0sIHR5cGUpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXR1cm4gYWRkUmVmZXJlbmNlKGl0ZW0sIHNpbXBsZVJlZihpdGVtLiRyZWYpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KS5qb2luKCcsPC9kaXY+PGRpdj4nKTtcbiAgICAgICAgfSBlbHNlIGlmIChfLmlzUGxhaW5PYmplY3Qoc2NoZW1hLml0ZW1zKSkge1xuICAgICAgICAgIGlmIChfLmlzVW5kZWZpbmVkKHNjaGVtYS5pdGVtcy4kcmVmKSkge1xuICAgICAgICAgICAgaWYgKF8uaW5kZXhPZihbJ2FycmF5JywgJ29iamVjdCddLCBzY2hlbWEuaXRlbXMudHlwZSB8fCAnb2JqZWN0JykgPiAtMSkge1xuICAgICAgICAgICAgICBpZiAoKF8uaXNVbmRlZmluZWQoc2NoZW1hLml0ZW1zLnR5cGUpIHx8IHNjaGVtYS5pdGVtcy50eXBlID09PSAnb2JqZWN0JykgJiYgXy5pc1VuZGVmaW5lZChzY2hlbWEuaXRlbXMucHJvcGVydGllcykpIHtcbiAgICAgICAgICAgICAgICBodG1sICs9ICc8ZGl2Pm9iamVjdDwvZGl2Pic7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPGRpdj4nICsgYWRkUmVmZXJlbmNlKHNjaGVtYS5pdGVtcykgKyAnPC9kaXY+JztcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgaHRtbCArPSAnPGRpdj4nICsgcHJpbWl0aXZlVG9PcHRpb25zSFRNTChzY2hlbWEuaXRlbXMsIHNjaGVtYS5pdGVtcy50eXBlKSArICc8L2Rpdj4nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBodG1sICs9ICc8ZGl2PicgKyBhZGRSZWZlcmVuY2Uoc2NoZW1hLml0ZW1zLCBzaW1wbGVSZWYoc2NoZW1hLml0ZW1zLiRyZWYpKSArICc8L2Rpdj4nO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb25zb2xlLmxvZygnQXJyYXkgdHlwZVxcJ3MgXFwnaXRlbXNcXCcgcHJvcGVydHkgaXMgbm90IGFuIGFycmF5IG9yIGFuIG9iamVjdCwgY2Fubm90IHByb2Nlc3MnKTtcbiAgICAgICAgICBodG1sICs9ICc8ZGl2Pm9iamVjdDwvZGl2Pic7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChzY2hlbWEuJHJlZikge1xuICAgICAgICAgIGh0bWwgKz0gJzxkaXY+JyArIGFkZFJlZmVyZW5jZShzY2hlbWEsIG5hbWUpICsgJzwvZGl2Pic7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBpZiAoXy5pc1BsYWluT2JqZWN0KHNjaGVtYS5wcm9wZXJ0aWVzKSkge1xuICAgICAgICAgICAgY29udGVudHMgPSBfLm1hcChzY2hlbWEucHJvcGVydGllcywgZnVuY3Rpb24gKHByb3BlcnR5LCBuYW1lKSB7XG4gICAgICAgICAgICAgIHZhciBwcm9wZXJ0eUlzUmVxdWlyZWQgPSAoXy5pbmRleE9mKHNjaGVtYS5yZXF1aXJlZCwgbmFtZSkgPj0gMCk7XG4gICAgICAgICAgICAgIHZhciBjUHJvcGVydHkgPSBfLmNsb25lRGVlcChwcm9wZXJ0eSk7XG5cbiAgICAgICAgICAgICAgdmFyIHJlcXVpcmVkQ2xhc3MgPSBwcm9wZXJ0eUlzUmVxdWlyZWQgPyAncmVxdWlyZWQnIDogJyc7XG4gICAgICAgICAgICAgIHZhciBodG1sID0gJzxzcGFuIGNsYXNzPVwicHJvcE5hbWUgJyArIHJlcXVpcmVkQ2xhc3MgKyAnXCI+JyArIG5hbWUgKyAnPC9zcGFuPiAoJztcbiAgICAgICAgICAgICAgdmFyIG1vZGVsO1xuXG4gICAgICAgICAgICAgIC8vIEFsbG93IG1hY3JvIHRvIHNldCB0aGUgZGVmYXVsdCB2YWx1ZVxuICAgICAgICAgICAgICBjUHJvcGVydHkuZGVmYXVsdCA9IG1vZGVsUHJvcGVydHlNYWNybyhjUHJvcGVydHkpO1xuXG4gICAgICAgICAgICAgIC8vIFJlc29sdmUgdGhlIHNjaGVtYSAoSGFuZGxlIG5lc3RlZCBzY2hlbWFzKVxuICAgICAgICAgICAgICBjUHJvcGVydHkgPSByZXNvbHZlU2NoZW1hKGNQcm9wZXJ0eSk7XG5cbiAgICAgICAgICAgICAgLy8gV2UgbmVlZCB0byBoYW5kbGUgcHJvcGVydHkgcmVmZXJlbmNlcyB0byBwcmltaXRpdmVzIChJc3N1ZSAzMzkpXG4gICAgICAgICAgICAgIGlmICghXy5pc1VuZGVmaW5lZChjUHJvcGVydHkuJHJlZikpIHtcbiAgICAgICAgICAgICAgICBtb2RlbCA9IG1vZGVsc1tzaW1wbGVSZWYoY1Byb3BlcnR5LiRyZWYpXTtcblxuICAgICAgICAgICAgICAgIGlmICghXy5pc1VuZGVmaW5lZChtb2RlbCkgJiYgXy5pbmRleE9mKFt1bmRlZmluZWQsICdhcnJheScsICdvYmplY3QnXSwgbW9kZWwuZGVmaW5pdGlvbi50eXBlKSA9PT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgIC8vIFVzZSByZWZlcmVuY2VkIHNjaGVtYVxuICAgICAgICAgICAgICAgICAgY1Byb3BlcnR5ID0gcmVzb2x2ZVNjaGVtYShtb2RlbC5kZWZpbml0aW9uKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBodG1sICs9IHByaW1pdGl2ZVRvSFRNTChjUHJvcGVydHkpO1xuXG4gICAgICAgICAgICAgIGlmKCFwcm9wZXJ0eUlzUmVxdWlyZWQpIHtcbiAgICAgICAgICAgICAgICBodG1sICs9ICcsIDxzcGFuIGNsYXNzPVwicHJvcE9wdEtleVwiPm9wdGlvbmFsPC9zcGFuPic7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBpZihwcm9wZXJ0eS5yZWFkT25seSkge1xuICAgICAgICAgICAgICAgICAgaHRtbCArPSAnLCA8c3BhbiBjbGFzcz1cInByb3BSZWFkT25seVwiPnJlYWQgb25seTwvc3Bhbj4nO1xuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgaHRtbCArPSAnKSc7XG5cbiAgICAgICAgICAgICAgcmV0dXJuICc8ZGl2JyArIChwcm9wZXJ0eS5yZWFkT25seSA/ICcgY2xhc3M9XCJyZWFkT25seVwiJyA6ICcnKSArICc+JyArIHByaW1pdGl2ZVRvT3B0aW9uc0hUTUwoY1Byb3BlcnR5LCBodG1sKTtcbiAgICAgICAgICAgIH0pLmpvaW4oJyw8L2Rpdj4nKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoY29udGVudHMpIHtcbiAgICAgICAgICAgIGh0bWwgKz0gY29udGVudHMgKyAnPC9kaXY+JztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaHRtbCArPSAnPGRpdj4nICsgcHJpbWl0aXZlVG9PcHRpb25zSFRNTChzY2hlbWEsIHR5cGUpICsgJzwvZGl2Pic7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGh0bWwgKyBzdHJvbmdPcGVuICsgKGlzQXJyYXkgPyAnXScgOiAnfScpICsgc3Ryb25nQ2xvc2U7XG4gICAgfVxuXG4gIH07XG5cbiAgLy8gY29weS1wYXN0ZWQgZnJvbSBzd2FnZ2VyLWpzXG4gIHZhciBzY2hlbWFUb0pTT04gPSBmdW5jdGlvbiAoc2NoZW1hLCBtb2RlbHMsIG1vZGVsc1RvSWdub3JlLCBtb2RlbFByb3BlcnR5TWFjcm8pIHtcbiAgICAvLyBSZXNvbHZlIHRoZSBzY2hlbWEgKEhhbmRsZSBuZXN0ZWQgc2NoZW1hcylcbiAgICBzY2hlbWEgPSByZXNvbHZlU2NoZW1hKHNjaGVtYSk7XG5cbiAgICBpZih0eXBlb2YgbW9kZWxQcm9wZXJ0eU1hY3JvICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICBtb2RlbFByb3BlcnR5TWFjcm8gPSBmdW5jdGlvbihwcm9wKXtcbiAgICAgICAgcmV0dXJuIChwcm9wIHx8IHt9KS5kZWZhdWx0O1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBtb2RlbHNUb0lnbm9yZT0gbW9kZWxzVG9JZ25vcmUgfHwge307XG5cbiAgICB2YXIgdHlwZSA9IHNjaGVtYS50eXBlIHx8ICdvYmplY3QnO1xuICAgIHZhciBmb3JtYXQgPSBzY2hlbWEuZm9ybWF0O1xuICAgIHZhciBtb2RlbDtcbiAgICB2YXIgb3V0cHV0O1xuXG4gICAgaWYgKCFfLmlzVW5kZWZpbmVkKHNjaGVtYS5leGFtcGxlKSkge1xuICAgICAgb3V0cHV0ID0gc2NoZW1hLmV4YW1wbGU7XG4gICAgfSBlbHNlIGlmIChfLmlzVW5kZWZpbmVkKHNjaGVtYS5pdGVtcykgJiYgXy5pc0FycmF5KHNjaGVtYS5lbnVtKSkge1xuICAgICAgb3V0cHV0ID0gc2NoZW1hLmVudW1bMF07XG4gICAgfVxuXG4gICAgaWYgKF8uaXNVbmRlZmluZWQob3V0cHV0KSkge1xuICAgICAgaWYgKHNjaGVtYS4kcmVmKSB7XG4gICAgICAgIG1vZGVsID0gbW9kZWxzW3NpbXBsZVJlZihzY2hlbWEuJHJlZildO1xuXG4gICAgICAgIGlmICghXy5pc1VuZGVmaW5lZChtb2RlbCkpIHtcbiAgICAgICAgICBpZiAoXy5pc1VuZGVmaW5lZChtb2RlbHNUb0lnbm9yZVttb2RlbC5uYW1lXSkpIHtcbiAgICAgICAgICAgIG1vZGVsc1RvSWdub3JlW21vZGVsLm5hbWVdID0gbW9kZWw7XG4gICAgICAgICAgICBvdXRwdXQgPSBzY2hlbWFUb0pTT04obW9kZWwuZGVmaW5pdGlvbiwgbW9kZWxzLCBtb2RlbHNUb0lnbm9yZSwgbW9kZWxQcm9wZXJ0eU1hY3JvKTtcbiAgICAgICAgICAgIGRlbGV0ZSBtb2RlbHNUb0lnbm9yZVttb2RlbC5uYW1lXTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKG1vZGVsLnR5cGUgPT09ICdhcnJheScpIHtcbiAgICAgICAgICAgICAgb3V0cHV0ID0gW107XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBvdXRwdXQgPSB7fTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoIV8uaXNVbmRlZmluZWQoc2NoZW1hLmRlZmF1bHQpKSB7XG4gICAgICAgIG91dHB1dCA9IHNjaGVtYS5kZWZhdWx0O1xuICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICBpZiAoZm9ybWF0ID09PSAnZGF0ZS10aW1lJykge1xuICAgICAgICAgIG91dHB1dCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcbiAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09ICdkYXRlJykge1xuICAgICAgICAgIG91dHB1dCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKS5zcGxpdCgnVCcpWzBdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG91dHB1dCA9ICdzdHJpbmcnO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdpbnRlZ2VyJykge1xuICAgICAgICBvdXRwdXQgPSAwO1xuICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnbnVtYmVyJykge1xuICAgICAgICBvdXRwdXQgPSAwLjA7XG4gICAgICB9IGVsc2UgaWYgKHR5cGUgPT09ICdib29sZWFuJykge1xuICAgICAgICBvdXRwdXQgPSB0cnVlO1xuICAgICAgfSBlbHNlIGlmICh0eXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgICBvdXRwdXQgPSB7fTtcblxuICAgICAgICBfLmZvckVhY2goc2NoZW1hLnByb3BlcnRpZXMsIGZ1bmN0aW9uIChwcm9wZXJ0eSwgbmFtZSkge1xuICAgICAgICAgIHZhciBjUHJvcGVydHkgPSBfLmNsb25lRGVlcChwcm9wZXJ0eSk7XG5cbiAgICAgICAgICAvLyBBbGxvdyBtYWNybyB0byBzZXQgdGhlIGRlZmF1bHQgdmFsdWVcbiAgICAgICAgICBjUHJvcGVydHkuZGVmYXVsdCA9IG1vZGVsUHJvcGVydHlNYWNybyhwcm9wZXJ0eSk7XG5cbiAgICAgICAgICBvdXRwdXRbbmFtZV0gPSBzY2hlbWFUb0pTT04oY1Byb3BlcnR5LCBtb2RlbHMsIG1vZGVsc1RvSWdub3JlLCBtb2RlbFByb3BlcnR5TWFjcm8pO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gJ2FycmF5Jykge1xuICAgICAgICBvdXRwdXQgPSBbXTtcblxuICAgICAgICBpZiAoXy5pc0FycmF5KHNjaGVtYS5pdGVtcykpIHtcbiAgICAgICAgICBfLmZvckVhY2goc2NoZW1hLml0ZW1zLCBmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICAgICAgb3V0cHV0LnB1c2goc2NoZW1hVG9KU09OKGl0ZW0sIG1vZGVscywgbW9kZWxzVG9JZ25vcmUsIG1vZGVsUHJvcGVydHlNYWNybykpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2UgaWYgKF8uaXNQbGFpbk9iamVjdChzY2hlbWEuaXRlbXMpKSB7XG4gICAgICAgICAgb3V0cHV0LnB1c2goc2NoZW1hVG9KU09OKHNjaGVtYS5pdGVtcywgbW9kZWxzLCBtb2RlbHNUb0lnbm9yZSwgbW9kZWxQcm9wZXJ0eU1hY3JvKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoXy5pc1VuZGVmaW5lZChzY2hlbWEuaXRlbXMpKSB7XG4gICAgICAgICAgb3V0cHV0LnB1c2goe30pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnNvbGUubG9nKCdBcnJheSB0eXBlXFwncyBcXCdpdGVtc1xcJyBwcm9wZXJ0eSBpcyBub3QgYW4gYXJyYXkgb3IgYW4gb2JqZWN0LCBjYW5ub3QgcHJvY2VzcycpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG91dHB1dDtcbiAgfTtcblxuICAvLyBjb3B5LXBhc3RlZCBmcm9tIHN3YWdnZXItanNcbiAgdmFyIGNyZWF0ZUpTT05TYW1wbGUgPSBmdW5jdGlvbiAodmFsdWUsIG1vZGVsc1RvSWdub3JlKSB7XG4gICAgbW9kZWxzVG9JZ25vcmUgPSBtb2RlbHNUb0lnbm9yZSB8fCB7fTtcblxuICAgIG1vZGVsc1RvSWdub3JlW3ZhbHVlLm5hbWVdID0gdmFsdWU7XG5cbiAgICAvLyBSZXNwb25zZSBzdXBwb3J0XG4gICAgaWYgKHZhbHVlLmV4YW1wbGVzICYmIF8uaXNQbGFpbk9iamVjdCh2YWx1ZS5leGFtcGxlcykpIHtcbiAgICAgIHZhbHVlID0gXy5jbG9uZURlZXAodmFsdWUpO1xuICAgICAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh2YWx1ZS5leGFtcGxlcyk7XG5cbiAgICAgIF8uZm9yRWFjaChrZXlzLCBmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgaWYoa2V5LmluZGV4T2YoJ2FwcGxpY2F0aW9uL2pzb24nKSA9PT0gMCkge1xuICAgICAgICAgIHZhciBleGFtcGxlID0gdmFsdWUuZXhhbXBsZXNba2V5XTtcbiAgICAgICAgICBpZiAoXy5pc1N0cmluZyhleGFtcGxlKSkge1xuICAgICAgICAgICAgZXhhbXBsZSA9IGpzeWFtbC5zYWZlTG9hZChleGFtcGxlKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdmFsdWUuZGVmaW5pdGlvbi5leGFtcGxlID0gZXhhbXBsZTtcbiAgICAgICAgICByZXR1cm4gc2NoZW1hVG9KU09OKHZhbHVlLmRlZmluaXRpb24sIGV4YW1wbGUsIG1vZGVsc1RvSWdub3JlLCB2YWx1ZS5tb2RlbFByb3BlcnR5TWFjcm8pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodmFsdWUuZXhhbXBsZXMpIHtcbiAgICAgIHZhbHVlID0gXy5jbG9uZURlZXAodmFsdWUpO1xuICAgICAgdmFyIGV4YW1wbGUgPSB2YWx1ZS5leGFtcGxlcztcbiAgICAgIGlmIChfLmlzU3RyaW5nKGV4YW1wbGUpKSB7XG4gICAgICAgIGV4YW1wbGUgPSBqc3lhbWwuc2FmZUxvYWQoZXhhbXBsZSk7XG4gICAgICB9XG4gICAgICB2YWx1ZS5kZWZpbml0aW9uLmV4YW1wbGUgPSBleGFtcGxlO1xuICAgICAgcmV0dXJuIHNjaGVtYVRvSlNPTih2YWx1ZS5kZWZpbml0aW9uLCBleGFtcGxlLCBtb2RlbHNUb0lnbm9yZSwgdmFsdWUubW9kZWxQcm9wZXJ0eU1hY3JvKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2NoZW1hVG9KU09OKHZhbHVlLmRlZmluaXRpb24sIHZhbHVlLm1vZGVscywgbW9kZWxzVG9JZ25vcmUsIHZhbHVlLm1vZGVsUHJvcGVydHlNYWNybyk7XG4gIH07XG5cbiAgLy8gY29weS1wYXN0ZWQgZnJvbSBzd2FnZ2VyLWpzXG4gIHZhciBnZXRQYXJhbWV0ZXJNb2RlbFNpZ25hdHVyZSA9IGZ1bmN0aW9uICh0eXBlLCBkZWZpbml0aW9ucykge1xuICAgICAgdmFyIGlzUHJpbWl0aXZlLCBsaXN0VHlwZTtcblxuICAgICAgaWYgKHR5cGUgaW5zdGFuY2VvZiBBcnJheSkge1xuICAgICAgICBsaXN0VHlwZSA9IHRydWU7XG4gICAgICAgIHR5cGUgPSB0eXBlWzBdO1xuICAgICAgfVxuXG4gICAgICAvLyBDb252ZXJ0IHVuZGVmaW5lZCB0byBzdHJpbmcgb2YgJ3VuZGVmaW5lZCdcbiAgICAgIGlmICh0eXBlb2YgdHlwZSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdHlwZSA9ICd1bmRlZmluZWQnO1xuICAgICAgICBpc1ByaW1pdGl2ZSA9IHRydWU7XG5cbiAgICAgIH0gZWxzZSBpZiAoZGVmaW5pdGlvbnNbdHlwZV0pe1xuICAgICAgICAvLyBhIG1vZGVsIGRlZiBleGlzdHM/XG4gICAgICAgIHR5cGUgPSBkZWZpbml0aW9uc1t0eXBlXTsgLyogTW9kZWwgKi9cbiAgICAgICAgaXNQcmltaXRpdmUgPSBmYWxzZTtcblxuICAgICAgfSBlbHNlIGlmIChnZXRJbmxpbmVNb2RlbCh0eXBlKSkge1xuICAgICAgICB0eXBlID0gZ2V0SW5saW5lTW9kZWwodHlwZSk7IC8qIE1vZGVsICovXG4gICAgICAgIGlzUHJpbWl0aXZlID0gZmFsc2U7XG5cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFdlIGRlZmF1bHQgdG8gcHJpbWl0aXZlXG4gICAgICAgIGlzUHJpbWl0aXZlID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzUHJpbWl0aXZlKSB7XG4gICAgICAgIGlmIChsaXN0VHlwZSkge1xuICAgICAgICAgIHJldHVybiAnQXJyYXlbJyArIHR5cGUgKyAnXSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHR5cGUudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGxpc3RUeXBlKSB7XG4gICAgICAgICAgcmV0dXJuICdBcnJheVsnICsgZ2V0TW9kZWxTaWduYXR1cmUodHlwZS5uYW1lLCB0eXBlLmRlZmluaXRpb24sIHR5cGUubW9kZWxzLCB0eXBlLm1vZGVsUHJvcGVydHlNYWNybykgKyAnXSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIGdldE1vZGVsU2lnbmF0dXJlKHR5cGUubmFtZSwgdHlwZS5kZWZpbml0aW9uLCB0eXBlLm1vZGVscywgdHlwZS5tb2RlbFByb3BlcnR5TWFjcm8pO1xuICAgICAgICB9XG4gICAgICB9XG4gIH07XG5cbiAgLy8gY29weS1wYXN0ZWQgZnJvbSBzd2FnZ2VyLWpzXG4gIHZhciBjcmVhdGVQYXJhbWV0ZXJKU09OU2FtcGxlID0gZnVuY3Rpb24gKHR5cGUsIG1vZGVscykge1xuICAgIHZhciBsaXN0VHlwZSwgc2FtcGxlSnNvbiwgaW5uZXJUeXBlO1xuICAgIG1vZGVscyA9IG1vZGVscyB8fCB7fTtcblxuICAgIGxpc3RUeXBlID0gKHR5cGUgaW5zdGFuY2VvZiBBcnJheSk7XG4gICAgaW5uZXJUeXBlID0gbGlzdFR5cGUgPyB0eXBlWzBdIDogdHlwZTtcblxuICAgIGlmKG1vZGVsc1tpbm5lclR5cGVdKSB7XG4gICAgICBzYW1wbGVKc29uID0gY3JlYXRlSlNPTlNhbXBsZShtb2RlbHNbaW5uZXJUeXBlXSk7XG4gICAgfSBlbHNlIGlmIChnZXRJbmxpbmVNb2RlbChpbm5lclR5cGUpKXtcbiAgICAgIHNhbXBsZUpzb24gPSBjcmVhdGVKU09OU2FtcGxlKGdldElubGluZU1vZGVsKGlubmVyVHlwZSkpOyAvLyBtYXkgcmV0dXJuIG51bGwsIGlmIHR5cGUgaXNuJ3QgY29ycmVjdFxuICAgIH1cblxuXG4gICAgaWYgKHNhbXBsZUpzb24pIHtcbiAgICAgIHNhbXBsZUpzb24gPSBsaXN0VHlwZSA/IFtzYW1wbGVKc29uXSA6IHNhbXBsZUpzb247XG5cbiAgICAgIGlmICh0eXBlb2Ygc2FtcGxlSnNvbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIHNhbXBsZUpzb247XG4gICAgICB9IGVsc2UgaWYgKF8uaXNPYmplY3Qoc2FtcGxlSnNvbikpIHtcbiAgICAgICAgdmFyIHQgPSBzYW1wbGVKc29uO1xuXG4gICAgICAgIGlmIChzYW1wbGVKc29uIGluc3RhbmNlb2YgQXJyYXkgJiYgc2FtcGxlSnNvbi5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdCA9IHNhbXBsZUpzb25bMF07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodC5ub2RlTmFtZSAmJiB0eXBlb2YgdCA9PT0gJ05vZGUnKSB7XG4gICAgICAgICAgdmFyIHhtbFN0cmluZyA9IG5ldyBYTUxTZXJpYWxpemVyKCkuc2VyaWFsaXplVG9TdHJpbmcodCk7XG5cbiAgICAgICAgICByZXR1cm4gZm9ybWF0WG1sKHhtbFN0cmluZyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHNhbXBsZUpzb24sIG51bGwsIDIpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gc2FtcGxlSnNvbjtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgdmFyIHdyYXBUYWcgPSBmdW5jdGlvbiAobmFtZSwgdmFsdWUsIGF0dHJzKSB7XG4gICAgdmFyIHN0ciwgYXR0cmlidXRlcztcblxuICAgIGF0dHJzID0gYXR0cnMgfHwgW107XG5cbiAgICBhdHRyaWJ1dGVzID0gYXR0cnMubWFwKGZ1bmN0aW9uIChhdHRyKSB7XG4gICAgICByZXR1cm4gJyAnICsgYXR0ci5uYW1lICsgJz1cIicgKyBhdHRyLnZhbHVlICsgJ1wiJztcbiAgICB9KS5qb2luKCcnKTtcblxuICAgIGlmICghbmFtZSkge1xuICAgICAgcmV0dXJuIGdldEVycm9yTWVzc2FnZSgnTm9kZSBuYW1lIGlzIG5vdCBwcm92aWRlZCcpO1xuICAgIH1cblxuICAgIHN0ciA9IFtcbiAgICAgICc8JywgbmFtZSxcbiAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICAnPicsXG4gICAgICB2YWx1ZSxcbiAgICAgICc8LycsIG5hbWUsICc+J1xuICAgIF07XG5cbiAgICByZXR1cm4gc3RyLmpvaW4oJycpO1xuICB9O1xuXG4gIC8vIENvbW1lbnRpbmcgdGhpcyBmdW50aW9uIGFzIHRoZSBuYW1lcyBhcmUgbm93IGRldGVybWluZWQgYmVmb3JlaGFuZCBhbmQgdGhlIHByZWZpeCBwYXJ0IGlzIGV4cG9zZWQgYXMgYSBzZXBhcmF0ZSBmdW5jdGlvbiB8IGh0dHBzOi8vZ2l0aHViLmNvbS9zd2FnZ2VyLWFwaS9zd2FnZ2VyLXVpL2lzc3Vlcy8yNTc3XG4gLyoqIHZhciBnZXROYW1lID0gZnVuY3Rpb24gKG5hbWUsIHhtbCkge1xuICAgIHZhciByZXN1bHQgPSBuYW1lIHx8ICcnO1xuXG4gICAgeG1sID0geG1sIHx8IHt9O1xuXG4gICAgaWYgKHhtbC5uYW1lKSB7XG4gICAgICByZXN1bHQgPSB4bWwubmFtZTtcbiAgICB9XG5cbiAgICBpZiAoeG1sLnByZWZpeCkge1xuICAgICAgcmVzdWx0ID0geG1sLnByZWZpeCArICc6JyArIHJlc3VsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuICAqL1xuICBcbiAgdmFyIGdldFByZWZpeCA9IGZ1bmN0aW9uIChuYW1lLCB4bWwpIHtcbiAgICB2YXIgcmVzdWx0ID0gbmFtZSB8fCAnJztcblxuICAgIHhtbCA9IHhtbCB8fCB7fTtcblxuICAgIGlmICh4bWwucHJlZml4KSB7XG4gICAgICByZXN1bHQgPSB4bWwucHJlZml4ICsgJzonICsgcmVzdWx0O1xuICAgIH1cblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH07XG5cbiAgdmFyIGdldE5hbWVzcGFjZSA9IGZ1bmN0aW9uICh4bWwpIHtcbiAgICB2YXIgbmFtZXNwYWNlID0gJyc7XG4gICAgdmFyIG5hbWUgPSAneG1sbnMnO1xuXG4gICAgeG1sID0geG1sIHx8IHt9O1xuXG4gICAgaWYgKHhtbC5uYW1lc3BhY2UpIHtcbiAgICAgIG5hbWVzcGFjZSA9IHhtbC5uYW1lc3BhY2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuYW1lc3BhY2U7XG4gICAgfVxuXG4gICAgaWYgKHhtbC5wcmVmaXgpIHtcbiAgICAgIG5hbWUgKz0gJzonICsgeG1sLnByZWZpeDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZTogbmFtZSxcbiAgICAgIHZhbHVlOiBuYW1lc3BhY2VcbiAgICB9O1xuICB9O1xuXG4gIHZhciBjcmVhdGVBcnJheVhNTCA9IGZ1bmN0aW9uIChkZXNjcmlwdG9yKSB7XG4gICAgdmFyIG5hbWUgPSBkZXNjcmlwdG9yLm5hbWU7XG4gICAgdmFyIGNvbmZpZyA9IGRlc2NyaXB0b3IuY29uZmlnO1xuICAgIHZhciBkZWZpbml0aW9uID0gZGVzY3JpcHRvci5kZWZpbml0aW9uO1xuICAgIHZhciBtb2RlbHMgPSBkZXNjcmlwdG9yLm1vZGVscztcbiAgICB2YXIgdmFsdWU7XG4gICAgdmFyIGl0ZW1zID0gZGVmaW5pdGlvbi5pdGVtcztcbiAgICB2YXIgeG1sID0gZGVmaW5pdGlvbi54bWwgfHwge307XG4gICAgdmFyIG5hbWVzcGFjZSA9IGdldE5hbWVzcGFjZSh4bWwpO1xuICAgIHZhciBhdHRyaWJ1dGVzID0gW107XG5cbiAgICBpZiAoIWl0ZW1zKSB7IHJldHVybiBnZXRFcnJvck1lc3NhZ2UoKTsgfVxuICAgIHZhciBrZXkgPSBuYW1lO1xuICAgIC8vIElmIHRoZXJlIGlzIGEgbmFtZSBzcGVjaWZpZWQgZm9yIHRoZSBhcnJheSBlbGVtZW50cywgdXNlIHRoYXQgZm9yIHRoZSBhcnJheSBlbGVtZW50cyBuYW1lIHwgaHR0cHM6Ly9naXRodWIuY29tL3N3YWdnZXItYXBpL3N3YWdnZXItdWkvaXNzdWVzLzI1NzdcbiAgICBpZihpdGVtcy54bWwgJiYgaXRlbXMueG1sLm5hbWUpIHtcbiAgICAgICAga2V5ID0gaXRlbXMueG1sLm5hbWU7XG4gICAgfVxuICAgIHZhbHVlID0gY3JlYXRlU2NoZW1hWE1MKGtleSwgaXRlbXMsIG1vZGVscywgY29uZmlnKTtcbiAgICBpZiAobmFtZXNwYWNlKSB7XG4gICAgICBhdHRyaWJ1dGVzLnB1c2gobmFtZXNwYWNlKTtcbiAgICB9XG5cbiAgICBpZiAoeG1sLndyYXBwZWQpIHtcbiAgICAgIHZhbHVlID0gd3JhcFRhZyhuYW1lLCB2YWx1ZSwgYXR0cmlidXRlcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHZhbHVlO1xuICB9O1xuXG4gIHZhciBnZXRQcmltaXRpdmVTaWduYXR1cmUgPSBmdW5jdGlvbiAoc2NoZW1hKSB7XG4gICAgdmFyIHR5cGUsIGl0ZW1zO1xuXG4gICAgc2NoZW1hID0gc2NoZW1hIHx8IHt9O1xuICAgIGl0ZW1zID0gc2NoZW1hLml0ZW1zIHx8IHt9O1xuICAgIHR5cGUgPSBzY2hlbWEudHlwZSB8fCAnJztcblxuICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgY2FzZSAnb2JqZWN0JzogcmV0dXJuICdPYmplY3QgaXMgbm90IGEgcHJpbWl0aXZlJztcbiAgICAgIGNhc2UgJ2FycmF5JyA6IHJldHVybiAnQXJyYXlbJyArIChpdGVtcy5mb3JtYXQgfHwgaXRlbXMudHlwZSkgKyAnXSc7XG4gICAgICBkZWZhdWx0OiByZXR1cm4gc2NoZW1hLmZvcm1hdCB8fCB0eXBlO1xuICAgIH1cbiAgfTtcblxuICB2YXIgY3JlYXRlUHJpbWl0aXZlWE1MID0gZnVuY3Rpb24gKGRlc2NyaXB0b3IpIHtcbiAgICB2YXIgbmFtZSA9IGRlc2NyaXB0b3IubmFtZTtcbiAgICB2YXIgZGVmaW5pdGlvbiA9IGRlc2NyaXB0b3IuZGVmaW5pdGlvbjtcbiAgICB2YXIgcHJpbWl0aXZlc01hcCA9IHtcbiAgICAgICdzdHJpbmcnOiB7XG4gICAgICAgICdkYXRlJzogbmV3IERhdGUoMSkudG9JU09TdHJpbmcoKS5zcGxpdCgnVCcpWzBdLFxuICAgICAgICAnZGF0ZS10aW1lJyA6IG5ldyBEYXRlKDEpLnRvSVNPU3RyaW5nKCksXG4gICAgICAgICdkZWZhdWx0JzogJ3N0cmluZydcbiAgICAgIH0sXG4gICAgICAnaW50ZWdlcic6IHtcbiAgICAgICAgJ2RlZmF1bHQnOiAxXG4gICAgICB9LFxuICAgICAgJ251bWJlcic6IHtcbiAgICAgICAgJ2RlZmF1bHQnOiAxLjFcbiAgICAgIH0sXG4gICAgICAnYm9vbGVhbic6IHtcbiAgICAgICAgJ2RlZmF1bHQnOiB0cnVlXG4gICAgICB9XG4gICAgfTtcbiAgICB2YXIgdHlwZSA9IGRlZmluaXRpb24udHlwZTtcbiAgICB2YXIgZm9ybWF0ID0gZGVmaW5pdGlvbi5mb3JtYXQ7XG4gICAgdmFyIHhtbCA9IGRlZmluaXRpb24ueG1sIHx8IHt9O1xuICAgIHZhciBuYW1lc3BhY2UgPSBnZXROYW1lc3BhY2UoeG1sKTtcbiAgICB2YXIgYXR0cmlidXRlcyA9IFtdO1xuICAgIHZhciB2YWx1ZTtcblxuICAgIGlmIChfLmtleXMocHJpbWl0aXZlc01hcCkuaW5kZXhPZih0eXBlKSA8IDApIHsgcmV0dXJuIGdldEVycm9yTWVzc2FnZSgpOyB9XG5cbiAgICBpZiAoXy5pc0FycmF5KGRlZmluaXRpb24uZW51bSkpe1xuICAgICAgdmFsdWUgPSBkZWZpbml0aW9uLmVudW1bMF07XG4gICAgfSBlbHNlIHtcbiAgICAgIHZhbHVlID0gZGVmaW5pdGlvbi5leGFtcGxlIHx8IHByaW1pdGl2ZXNNYXBbdHlwZV1bZm9ybWF0XSB8fCBwcmltaXRpdmVzTWFwW3R5cGVdLmRlZmF1bHQ7XG4gICAgfVxuXG4gICAgaWYgKHhtbC5hdHRyaWJ1dGUpIHtcbiAgICAgIHJldHVybiB7bmFtZTogbmFtZSwgdmFsdWU6IHZhbHVlfTtcbiAgICB9XG5cbiAgICBpZiAobmFtZXNwYWNlKSB7XG4gICAgICBhdHRyaWJ1dGVzLnB1c2gobmFtZXNwYWNlKTtcbiAgICB9XG5cbiAgICByZXR1cm4gd3JhcFRhZyhuYW1lLCB2YWx1ZSwgYXR0cmlidXRlcyk7XG4gIH07XG5cbiAgZnVuY3Rpb24gY3JlYXRlT2JqZWN0WE1MIChkZXNjcmlwdG9yKSB7XG4gICAgdmFyIG5hbWUgPSBkZXNjcmlwdG9yLm5hbWU7XG4gICAgdmFyIGRlZmluaXRpb24gPSBkZXNjcmlwdG9yLmRlZmluaXRpb247XG4gICAgdmFyIGNvbmZpZyA9IGRlc2NyaXB0b3IuY29uZmlnO1xuICAgIHZhciBtb2RlbHMgPSBkZXNjcmlwdG9yLm1vZGVscztcbiAgICB2YXIgaXNQYXJhbSA9IGRlc2NyaXB0b3IuY29uZmlnLmlzUGFyYW07XG4gICAgdmFyIHNlcmlhbGl6ZWRQcm9wZXJ0aWVzO1xuICAgIHZhciBhdHRycyA9IFtdO1xuICAgIHZhciBwcm9wZXJ0aWVzID0gZGVmaW5pdGlvbi5wcm9wZXJ0aWVzO1xuICAgIHZhciBhZGRpdGlvbmFsUHJvcGVydGllcyA9IGRlZmluaXRpb24uYWRkaXRpb25hbFByb3BlcnRpZXM7XG4gICAgdmFyIHhtbCA9IGRlZmluaXRpb24ueG1sO1xuICAgIHZhciBuYW1lc3BhY2UgPSBnZXROYW1lc3BhY2UoeG1sKTtcblxuICAgIGlmIChuYW1lc3BhY2UpIHtcbiAgICAgIGF0dHJzLnB1c2gobmFtZXNwYWNlKTtcbiAgICB9ICAgXG5cbiAgICBpZiAoIXByb3BlcnRpZXMgJiYgIWFkZGl0aW9uYWxQcm9wZXJ0aWVzKSB7IHJldHVybiBnZXRFcnJvck1lc3NhZ2UoKTsgfVxuXG4gICAgcHJvcGVydGllcyA9IHByb3BlcnRpZXMgfHwge307XG5cbiAgICBzZXJpYWxpemVkUHJvcGVydGllcyA9IF8ubWFwKHByb3BlcnRpZXMsIGZ1bmN0aW9uIChwcm9wLCBrZXkpIHtcbiAgICAgIHZhciB4bWwsIHJlc3VsdDtcblxuICAgICAgaWYgKGlzUGFyYW0gJiYgcHJvcC5yZWFkT25seSkge1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgICB9XG5cbiAgICAgIHhtbCA9IHByb3AueG1sIHx8IHt9O1xuICAgICAgcmVzdWx0ID0gY3JlYXRlU2NoZW1hWE1MKGtleSwgcHJvcCwgbW9kZWxzLCBjb25maWcpO1xuXG4gICAgICBpZiAoeG1sLmF0dHJpYnV0ZSkge1xuICAgICAgICBhdHRycy5wdXNoKHJlc3VsdCk7XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9KS5qb2luKCcnKTtcblxuICAgIGlmIChhZGRpdGlvbmFsUHJvcGVydGllcykge1xuICAgICAgc2VyaWFsaXplZFByb3BlcnRpZXMgKz0gJzwhLS0gYWRkaXRpb25hbCBlbGVtZW50cyBhbGxvd2VkIC0tPic7XG4gICAgfVxuXG4gICAgcmV0dXJuIHdyYXBUYWcobmFtZSwgc2VyaWFsaXplZFByb3BlcnRpZXMsIGF0dHJzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEluZmluaXRlTG9vcE1lc3NhZ2UgKG5hbWUsIGxvb3BUbykge1xuICAgIHJldHVybiB3cmFwVGFnKG5hbWUsICc8IS0tIEluZmluaXRlIGxvb3AgJHJlZjonICsgbG9vcFRvICsgJyAtLT4nKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGdldEVycm9yTWVzc2FnZSAoZGV0YWlscykge1xuICAgIGRldGFpbHMgPSBkZXRhaWxzID8gJzogJyArIGRldGFpbHMgOiAnJztcbiAgICByZXR1cm4gJzwhLS0gaW52YWxpZCBYTUwnICsgZGV0YWlscyArICcgLS0+JztcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZVNjaGVtYVhNTCAobmFtZSwgZGVmaW5pdGlvbiwgbW9kZWxzLCBjb25maWcpIHtcbiAgICB2YXIgJHJlZiA9IF8uaXNPYmplY3QoZGVmaW5pdGlvbikgPyBkZWZpbml0aW9uLiRyZWYgOiBudWxsO1xuICAgIHZhciBvdXRwdXQsIGluZGV4O1xuICAgIGNvbmZpZyA9IGNvbmZpZyB8fCB7fTtcbiAgICBjb25maWcubW9kZWxzVG9JZ25vcmUgPSBjb25maWcubW9kZWxzVG9JZ25vcmUgfHwgW107XG4gICBcbiAgICB2YXIgZGVzY3JpcHRvciA9IF8uaXNTdHJpbmcoJHJlZikgPyBnZXREZXNjcmlwdG9yQnlSZWYoJHJlZiwgbmFtZSwgbW9kZWxzLCBjb25maWcpXG4gICAgICAgIDogZ2V0RGVzY3JpcHRvcihuYW1lLCBkZWZpbml0aW9uLCBtb2RlbHMsIGNvbmZpZyk7XG4gICAgXG4gICAgaWYgKCFkZXNjcmlwdG9yKSB7XG4gICAgICByZXR1cm4gZ2V0RXJyb3JNZXNzYWdlKCk7XG4gICAgfVxuXG4gICAgc3dpdGNoIChkZXNjcmlwdG9yLnR5cGUpIHtcbiAgICAgIGNhc2UgJ2FycmF5JzpcbiAgICAgICAgb3V0cHV0ID0gY3JlYXRlQXJyYXlYTUwoZGVzY3JpcHRvcik7IGJyZWFrO1xuICAgICAgY2FzZSAnb2JqZWN0JzpcbiAgICAgICAgb3V0cHV0ID0gY3JlYXRlT2JqZWN0WE1MKGRlc2NyaXB0b3IpOyBicmVhaztcbiAgICAgIGNhc2UgJ2xvb3AnOlxuICAgICAgICBvdXRwdXQgPSBnZXRJbmZpbml0ZUxvb3BNZXNzYWdlKGRlc2NyaXB0b3IubmFtZSwgZGVzY3JpcHRvci5jb25maWcubG9vcFRvKTsgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBvdXRwdXQgPSBjcmVhdGVQcmltaXRpdmVYTUwoZGVzY3JpcHRvcik7XG4gICAgfVxuXG4gICAgaWYgKCRyZWYgJiYgZGVzY3JpcHRvci50eXBlICE9PSAnbG9vcCcpIHtcbiAgICAgIGluZGV4ID0gY29uZmlnLm1vZGVsc1RvSWdub3JlLmluZGV4T2YoJHJlZik7XG4gICAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgICBjb25maWcubW9kZWxzVG9JZ25vcmUuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0cHV0O1xuICB9XG5cbiAgZnVuY3Rpb24gRGVzY3JpcHRvciAobmFtZSwgdHlwZSwgZGVmaW5pdGlvbiwgbW9kZWxzLCBjb25maWcpIHtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigpO1xuICAgIH1cbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZyB8fCB7fTtcbiAgICB0aGlzLmNvbmZpZy5tb2RlbHNUb0lnbm9yZSA9IHRoaXMuY29uZmlnLm1vZGVsc1RvSWdub3JlIHx8IFtdO1xuICAgIC8vIG5hbWUgaXMgYWxyZWFkeSBzZXQgYnkgZ2V0RGVzY3JpcHRvckJ5UmVmIG9yIGdldERlc2NyaXB0b3IgZnVuY3Rpb24gZGVwZW5kaW5nIG9uIHRoZSB0eXBlLiBPbmx5IHByZWZpeCwgaWYgcHJlc2VudCBpcyBuZWVkZWQgdG8gYmUgc2V0IGhlcmUgfCBodHRwczovL2dpdGh1Yi5jb20vc3dhZ2dlci1hcGkvc3dhZ2dlci11aS9pc3N1ZXMvMjU3N1xuICAgIHRoaXMubmFtZSA9IGdldFByZWZpeChuYW1lLCBkZWZpbml0aW9uLnhtbCk7XG4gICAgdGhpcy5kZWZpbml0aW9uID0gZGVmaW5pdGlvbjtcbiAgICB0aGlzLm1vZGVscyA9IG1vZGVscztcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICB9XG5cbiAgZnVuY3Rpb24gZ2V0RGVzY3JpcHRvckJ5UmVmKCRyZWYsIG5hbWUsIG1vZGVscywgY29uZmlnKSB7XG4gICAgdmFyIG1vZGVsVHlwZSA9IHNpbXBsZVJlZigkcmVmKTtcbiAgICB2YXIgbW9kZWwgPSBtb2RlbHNbbW9kZWxUeXBlXSB8fCB7fTtcbiAgICB2YXIgdHlwZSA9IG1vZGVsLmRlZmluaXRpb24gJiYgbW9kZWwuZGVmaW5pdGlvbi50eXBlID8gbW9kZWwuZGVmaW5pdGlvbi50eXBlIDogJ29iamVjdCc7XG4gICAgLy8gSWYgbW9kZWwgZGVmaW5pdGlvbiB4bWwgbmFtZSBpcyBwcmVzZW50LCB0aGVuIHRoYXQgd2lsbCBiZSBwcmVmZXJyZWQgb3ZlciBtb2RlbCBuYW1lLiBUaGlzIGlzIHRoZSBjYXNlIG9mIHByZWZlcnJpbmcgWG1sRWxlbWVudCBuYW1lIG92ZXIgWG1sUm9vdEVsZW1lbnQgbmFtZSBpZiBYbWxFbGVtZW50IG5hbWUgaXMgcHJvdmlkZWQgfCBodHRwczovL2dpdGh1Yi5jb20vc3dhZ2dlci1hcGkvc3dhZ2dlci11aS9pc3N1ZXMvMjU3N1xuICAgIGlmKG1vZGVsLmRlZmluaXRpb24gJiYgbW9kZWwuZGVmaW5pdGlvbi54bWwgJiYgbW9kZWwuZGVmaW5pdGlvbi54bWwubmFtZSkge1xuICAgICAgICBuYW1lID0gbmFtZSB8fCBtb2RlbC5kZWZpbml0aW9uLnhtbC5uYW1lIHx8IG1vZGVsLm5hbWU7XG4gICAgfVxuICAgIC8vIGVsc2Ugb25seSBtb2RlbCBuYW1lIHdpbGwgYmUgY29uc2lkZXJlZCBmb3IgZGV0ZXJtaW5hdGlvbiB8IGh0dHBzOi8vZ2l0aHViLmNvbS9zd2FnZ2VyLWFwaS9zd2FnZ2VyLXVpL2lzc3Vlcy8yNTc3XG4gICAgZWxzZSB7XG4gICAgICAgIG5hbWUgPSBuYW1lIHx8IG1vZGVsLm5hbWU7XG4gICAgfVxuICAgIFxuICAgIGlmIChjb25maWcubW9kZWxzVG9JZ25vcmUuaW5kZXhPZigkcmVmKSA+IC0xKSB7XG4gICAgICB0eXBlID0gJ2xvb3AnO1xuICAgICAgY29uZmlnLmxvb3BUbyA9IG1vZGVsVHlwZTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uZmlnLm1vZGVsc1RvSWdub3JlLnB1c2goJHJlZik7XG4gICAgfVxuXG4gICAgaWYgKCFtb2RlbC5kZWZpbml0aW9uKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBEZXNjcmlwdG9yKG5hbWUsIHR5cGUsIG1vZGVsLmRlZmluaXRpb24sIG1vZGVscywgY29uZmlnKTsgICAgXG4gIH1cblxuICBmdW5jdGlvbiBnZXREZXNjcmlwdG9yIChuYW1lLCBkZWZpbml0aW9uLCBtb2RlbHMsIGNvbmZpZyl7XG4gICAgdmFyIHR5cGUgPSBkZWZpbml0aW9uLnR5cGUgfHwgJ29iamVjdCc7XG4gICAgLy8gSWYgZGVmaW5pdGlvbiB4bWwgbmFtZSBpcyBwcmVzZW50LCB0aGVuIHRoYXQgd2lsbCBiZSBwcmVmZXJyZWQgb3ZlciBuYW1lIHwgaHR0cHM6Ly9naXRodWIuY29tL3N3YWdnZXItYXBpL3N3YWdnZXItdWkvaXNzdWVzLzI1NzdcbiAgICBpZihkZWZpbml0aW9uLnhtbCAmJiBkZWZpbml0aW9uLnhtbC5uYW1lKSB7XG4gICAgICAgIG5hbWUgPSBkZWZpbml0aW9uLnhtbC5uYW1lIHx8IG5hbWU7XG4gICAgfVxuICAgIGlmICghZGVmaW5pdGlvbikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBEZXNjcmlwdG9yKG5hbWUsIHR5cGUsIGRlZmluaXRpb24sIG1vZGVscywgY29uZmlnKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNyZWF0ZVhNTFNhbXBsZSAobmFtZSwgZGVmaW5pdGlvbiwgbW9kZWxzLCBpc1BhcmFtKSB7XG4gICAgdmFyIHByb2xvZyA9ICc8P3htbCB2ZXJzaW9uPVwiMS4wXCI/Pic7XG5cbiAgICByZXR1cm4gZm9ybWF0WG1sKHByb2xvZyArIGNyZWF0ZVNjaGVtYVhNTChuYW1lLCBkZWZpbml0aW9uLCBtb2RlbHMsIHsgaXNQYXJhbTogaXNQYXJhbSB9ICkpO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICAgIGdldE1vZGVsU2lnbmF0dXJlOiBnZXRNb2RlbFNpZ25hdHVyZSxcbiAgICAgIGNyZWF0ZUpTT05TYW1wbGU6IGNyZWF0ZUpTT05TYW1wbGUsXG4gICAgICBnZXRQYXJhbWV0ZXJNb2RlbFNpZ25hdHVyZTogZ2V0UGFyYW1ldGVyTW9kZWxTaWduYXR1cmUsXG4gICAgICBjcmVhdGVQYXJhbWV0ZXJKU09OU2FtcGxlOiBjcmVhdGVQYXJhbWV0ZXJKU09OU2FtcGxlLFxuICAgICAgY3JlYXRlU2NoZW1hWE1MOiBjcmVhdGVTY2hlbWFYTUwsXG4gICAgICBjcmVhdGVYTUxTYW1wbGU6IGNyZWF0ZVhNTFNhbXBsZSxcbiAgICAgIGdldFByaW1pdGl2ZVNpZ25hdHVyZTogZ2V0UHJpbWl0aXZlU2lnbmF0dXJlXG4gIH07XG5cbn0pKCk7XG4iLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5WaWV3cy5Qb3B1cFZpZXcgPSBCYWNrYm9uZS5WaWV3LmV4dGVuZCh7XG4gICAgZXZlbnRzOiB7XG4gICAgICAgICdjbGljayAuYXBpLXBvcHVwLWNhbmNlbCc6ICdjYW5jZWxDbGljaydcbiAgICB9LFxuXG4gICAgdGVtcGxhdGU6IEhhbmRsZWJhcnMudGVtcGxhdGVzLnBvcHVwLFxuICAgIGNsYXNzTmFtZTogJ2FwaS1wb3B1cC1kaWFsb2cnLFxuXG4gICAgc2VsZWN0b3JzOiB7XG4gICAgICAgIGNvbnRlbnQ6ICcuYXBpLXBvcHVwLWNvbnRlbnQnLFxuICAgICAgICBtYWluICAgOiAnI3N3YWdnZXItdWktY29udGFpbmVyJ1xuICAgIH0sXG5cbiAgICBpbml0aWFsaXplOiBmdW5jdGlvbigpe1xuICAgICAgICB0aGlzLiRlbC5odG1sKHRoaXMudGVtcGxhdGUodGhpcy5tb2RlbCkpO1xuICAgIH0sXG5cbiAgICByZW5kZXI6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy4kKHRoaXMuc2VsZWN0b3JzLmNvbnRlbnQpLmFwcGVuZCh0aGlzLm1vZGVsLmNvbnRlbnQpO1xuICAgICAgICAkKHRoaXMuc2VsZWN0b3JzLm1haW4pLmZpcnN0KCkuYXBwZW5kKHRoaXMuZWwpO1xuICAgICAgICB0aGlzLnNob3dQb3B1cCgpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH0sXG5cbiAgICBzaG93UG9wdXA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy4kZWwuc2hvdygpO1xuICAgIH0sXG5cbiAgICBjYW5jZWxDbGljazogZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnJlbW92ZSgpO1xuICAgIH1cblxufSk7XG4iLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5WaWV3cy5SZXNvdXJjZVZpZXcgPSBCYWNrYm9uZS5WaWV3LmV4dGVuZCh7XG4gIGluaXRpYWxpemU6IGZ1bmN0aW9uKG9wdHMpIHtcbiAgICBvcHRzID0gb3B0cyB8fCB7fTtcbiAgICB0aGlzLnJvdXRlciA9IG9wdHMucm91dGVyO1xuICAgIHRoaXMuYXV0aHMgPSBvcHRzLmF1dGhzO1xuICAgIGlmICgnJyA9PT0gdGhpcy5tb2RlbC5kZXNjcmlwdGlvbikge1xuICAgICAgdGhpcy5tb2RlbC5kZXNjcmlwdGlvbiA9IG51bGw7XG4gICAgfVxuICAgIGlmICh0aGlzLm1vZGVsLmRlc2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLm1vZGVsLnN1bW1hcnkgPSB0aGlzLm1vZGVsLmRlc2NyaXB0aW9uO1xuICAgIH1cbiAgICB0aGlzLm51bWJlciA9IDA7XG4gIH0sXG5cbiAgcmVuZGVyOiBmdW5jdGlvbigpe1xuICAgIHZhciBtZXRob2RzID0ge307XG5cblxuICAgICQodGhpcy5lbCkuaHRtbChIYW5kbGViYXJzLnRlbXBsYXRlcy5yZXNvdXJjZSh0aGlzLm1vZGVsKSk7XG5cbiAgICAvLyBSZW5kZXIgZWFjaCBvcGVyYXRpb25cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubW9kZWwub3BlcmF0aW9uc0FycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgb3BlcmF0aW9uID0gdGhpcy5tb2RlbC5vcGVyYXRpb25zQXJyYXlbaV07XG4gICAgICB2YXIgY291bnRlciA9IDA7XG4gICAgICB2YXIgaWQgPSBvcGVyYXRpb24ubmlja25hbWU7XG5cbiAgICAgIHdoaWxlICh0eXBlb2YgbWV0aG9kc1tpZF0gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGlkID0gaWQgKyAnXycgKyBjb3VudGVyO1xuICAgICAgICBjb3VudGVyICs9IDE7XG4gICAgICB9XG5cbiAgICAgIG1ldGhvZHNbaWRdID0gb3BlcmF0aW9uO1xuXG4gICAgICBvcGVyYXRpb24ubmlja25hbWUgPSBpZDtcbiAgICAgIG9wZXJhdGlvbi5wYXJlbnRJZCA9IHRoaXMubW9kZWwuaWQ7XG4gICAgICBvcGVyYXRpb24uZGVmaW5pdGlvbnMgPSB0aGlzLm1vZGVsLmRlZmluaXRpb25zOyAvLyBtYWtlIEpzb24gU2NoZW1hIGF2YWlsYWJsZSBmb3IgSlNvbkVkaXRvciBpbiB0aGlzIG9wZXJhdGlvblxuICAgICAgdGhpcy5hZGRPcGVyYXRpb24ob3BlcmF0aW9uKTtcbiAgICB9XG5cbiAgICAkKCcudG9nZ2xlRW5kcG9pbnRMaXN0JywgdGhpcy5lbCkuY2xpY2sodGhpcy5jYWxsRG9jcy5iaW5kKHRoaXMsICd0b2dnbGVFbmRwb2ludExpc3RGb3JSZXNvdXJjZScpKTtcbiAgICAkKCcuY29sbGFwc2VSZXNvdXJjZScsIHRoaXMuZWwpLmNsaWNrKHRoaXMuY2FsbERvY3MuYmluZCh0aGlzLCAnY29sbGFwc2VPcGVyYXRpb25zRm9yUmVzb3VyY2UnKSk7XG4gICAgJCgnLmV4cGFuZFJlc291cmNlJywgdGhpcy5lbCkuY2xpY2sodGhpcy5jYWxsRG9jcy5iaW5kKHRoaXMsICdleHBhbmRPcGVyYXRpb25zRm9yUmVzb3VyY2UnKSk7XG5cbiAgICByZXR1cm4gdGhpcztcbiAgfSxcblxuICBhZGRPcGVyYXRpb246IGZ1bmN0aW9uKG9wZXJhdGlvbikge1xuXG4gICAgb3BlcmF0aW9uLm51bWJlciA9IHRoaXMubnVtYmVyO1xuXG4gICAgLy8gUmVuZGVyIGFuIG9wZXJhdGlvbiBhbmQgYWRkIGl0IHRvIG9wZXJhdGlvbnMgbGlcbiAgICB2YXIgb3BlcmF0aW9uVmlldyA9IG5ldyBTd2FnZ2VyVWkuVmlld3MuT3BlcmF0aW9uVmlldyh7XG4gICAgICBtb2RlbDogb3BlcmF0aW9uLFxuICAgICAgcm91dGVyOiB0aGlzLnJvdXRlcixcbiAgICAgIHRhZ05hbWU6ICdsaScsXG4gICAgICBjbGFzc05hbWU6ICdlbmRwb2ludCcsXG4gICAgICBzd2FnZ2VyT3B0aW9uczogdGhpcy5vcHRpb25zLnN3YWdnZXJPcHRpb25zLFxuICAgICAgYXV0aHM6IHRoaXMuYXV0aHNcbiAgICB9KTtcblxuICAgICQoJy5lbmRwb2ludHMnLCAkKHRoaXMuZWwpKS5hcHBlbmQob3BlcmF0aW9uVmlldy5yZW5kZXIoKS5lbCk7XG5cbiAgICB0aGlzLm51bWJlcisrO1xuXG4gIH0sXG4gIC8vIEdlbmVyaWMgRXZlbnQgaGFuZGxlciAoYERvY3NgIGlzIGdsb2JhbClcblxuXG4gIGNhbGxEb2NzOiBmdW5jdGlvbihmbk5hbWUsIGUpIHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgRG9jc1tmbk5hbWVdKGUuY3VycmVudFRhcmdldC5nZXRBdHRyaWJ1dGUoJ2RhdGEtaWQnKSk7XG4gIH1cbn0pO1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG5Td2FnZ2VyVWkuVmlld3MuUmVzcG9uc2VDb250ZW50VHlwZVZpZXcgPSBCYWNrYm9uZS5WaWV3LmV4dGVuZCh7XG4gIGluaXRpYWxpemU6IGZ1bmN0aW9uKCl7fSxcblxuICByZW5kZXI6IGZ1bmN0aW9uKCl7XG4gICAgdGhpcy5tb2RlbC5yZXNwb25zZUNvbnRlbnRUeXBlSWQgPSAncmN0JyArIE1hdGgucmFuZG9tKCk7XG4gICAgJCh0aGlzLmVsKS5odG1sKEhhbmRsZWJhcnMudGVtcGxhdGVzLnJlc3BvbnNlX2NvbnRlbnRfdHlwZSh0aGlzLm1vZGVsKSk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbn0pOyIsIid1c2Ugc3RyaWN0JztcblxuU3dhZ2dlclVpLlZpZXdzLlNpZ25hdHVyZVZpZXcgPSBCYWNrYm9uZS5WaWV3LmV4dGVuZCh7XG4gIGV2ZW50czoge1xuICAgICdjbGljayBhLmRlc2NyaXB0aW9uLWxpbmsnICAgICAgIDogJ3N3aXRjaFRvRGVzY3JpcHRpb24nLFxuICAgICdjbGljayBhLnNuaXBwZXQtbGluaycgICAgICAgICAgIDogJ3N3aXRjaFRvU25pcHBldCcsXG4gICAgJ21vdXNlZG93biAuc25pcHBldF9qc29uJyAgICAgICAgICA6ICdqc29uU25pcHBldE1vdXNlRG93bicsXG4gICAgJ21vdXNlZG93biAuc25pcHBldF94bWwnICAgICAgICAgIDogJ3htbFNuaXBwZXRNb3VzZURvd24nXG4gIH0sXG5cbiAgaW5pdGlhbGl6ZTogZnVuY3Rpb24gKCkge1xuICB9LFxuXG4gIHJlbmRlcjogZnVuY3Rpb24oKXtcblxuICAgICQodGhpcy5lbCkuaHRtbChIYW5kbGViYXJzLnRlbXBsYXRlcy5zaWduYXR1cmUodGhpcy5tb2RlbCkpO1xuXG4gICAgaWYgKHRoaXMubW9kZWwuZGVmYXVsdFJlbmRlcmluZyA9PT0gJ21vZGVsJykge1xuICAgICAgdGhpcy5zd2l0Y2hUb0Rlc2NyaXB0aW9uKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc3dpdGNoVG9TbmlwcGV0KCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH0sXG5cbiAgLy8gaGFuZGxlciBmb3Igc2hvdyBzaWduYXR1cmVcbiAgc3dpdGNoVG9EZXNjcmlwdGlvbjogZnVuY3Rpb24oZSl7XG4gICAgaWYgKGUpIHsgZS5wcmV2ZW50RGVmYXVsdCgpOyB9XG5cbiAgICAkKCcuc25pcHBldCcsICQodGhpcy5lbCkpLmhpZGUoKTtcbiAgICAkKCcuZGVzY3JpcHRpb24nLCAkKHRoaXMuZWwpKS5zaG93KCk7XG4gICAgJCgnLmRlc2NyaXB0aW9uLWxpbmsnLCAkKHRoaXMuZWwpKS5hZGRDbGFzcygnc2VsZWN0ZWQnKTtcbiAgICAkKCcuc25pcHBldC1saW5rJywgJCh0aGlzLmVsKSkucmVtb3ZlQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gIH0sXG5cbiAgLy8gaGFuZGxlciBmb3Igc2hvdyBzYW1wbGVcbiAgc3dpdGNoVG9TbmlwcGV0OiBmdW5jdGlvbihlKXtcbiAgICBpZiAoZSkgeyBlLnByZXZlbnREZWZhdWx0KCk7IH1cblxuICAgICQoJy5zbmlwcGV0JywgJCh0aGlzLmVsKSkuc2hvdygpO1xuICAgICQoJy5kZXNjcmlwdGlvbicsICQodGhpcy5lbCkpLmhpZGUoKTtcbiAgICAkKCcuc25pcHBldC1saW5rJywgJCh0aGlzLmVsKSkuYWRkQ2xhc3MoJ3NlbGVjdGVkJyk7XG4gICAgJCgnLmRlc2NyaXB0aW9uLWxpbmsnLCAkKHRoaXMuZWwpKS5yZW1vdmVDbGFzcygnc2VsZWN0ZWQnKTtcbiAgfSxcblxuICAvLyBoYW5kbGVyIGZvciBzbmlwcGV0IHRvIHRleHQgYXJlYVxuICBzbmlwcGV0VG9UZXh0QXJlYTogZnVuY3Rpb24odmFsKSB7XG4gICAgdmFyIHRleHRBcmVhID0gJCgndGV4dGFyZWEnLCAkKHRoaXMuZWwucGFyZW50Tm9kZS5wYXJlbnROb2RlLnBhcmVudE5vZGUpKTtcblxuICAgIC8vIEZpeCBmb3IgYnVnIGluIElFIDEwLzExIHdoaWNoIGNhdXNlcyBwbGFjZWhvbGRlciB0ZXh0IHRvIGJlIGNvcGllZCB0byBcInZhbHVlXCJcbiAgICBpZiAoJC50cmltKHRleHRBcmVhLnZhbCgpKSA9PT0gJycgfHwgdGV4dEFyZWEucHJvcCgncGxhY2Vob2xkZXInKSA9PT0gdGV4dEFyZWEudmFsKCkpIHtcbiAgICAgIHRleHRBcmVhLnZhbCh2YWwpO1xuICAgICAgLy8gVE9ETyBtb3ZlIHRoaXMgY29kZSBvdXRzaWRlIG9mIHRoZSB2aWV3IGFuZCBleHBvc2UgYW4gZXZlbnQgaW5zdGVhZFxuICAgICAgaWYoIHRoaXMubW9kZWwuanNvbkVkaXRvciAmJiB0aGlzLm1vZGVsLmpzb25FZGl0b3IuaXNFbmFibGVkKCkpe1xuICAgICAgICB0aGlzLm1vZGVsLmpzb25FZGl0b3Iuc2V0VmFsdWUoSlNPTi5wYXJzZSh0aGlzLm1vZGVsLnNhbXBsZUpTT04pKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sXG5cbiAganNvblNuaXBwZXRNb3VzZURvd246IGZ1bmN0aW9uIChlKSB7XG4gICAgaWYgKHRoaXMubW9kZWwuaXNQYXJhbSkge1xuICAgICAgaWYgKGUpIHsgZS5wcmV2ZW50RGVmYXVsdCgpOyB9XG5cbiAgICAgIHRoaXMuc25pcHBldFRvVGV4dEFyZWEodGhpcy5tb2RlbC5zYW1wbGVKU09OKTtcbiAgICB9XG4gIH0sXG5cbiAgeG1sU25pcHBldE1vdXNlRG93bjogZnVuY3Rpb24gKGUpIHtcbiAgICBpZiAodGhpcy5tb2RlbC5pc1BhcmFtKSB7XG4gICAgICBpZiAoZSkgeyBlLnByZXZlbnREZWZhdWx0KCk7IH1cblxuICAgICAgdGhpcy5zbmlwcGV0VG9UZXh0QXJlYSh0aGlzLm1vZGVsLnNhbXBsZVhNTCk7XG4gICAgfVxuICB9XG59KTsiLCIndXNlIHN0cmljdCc7XG5cblN3YWdnZXJVaS5WaWV3cy5TdGF0dXNDb2RlVmlldyA9IEJhY2tib25lLlZpZXcuZXh0ZW5kKHtcbiAgaW5pdGlhbGl6ZTogZnVuY3Rpb24gKG9wdHMpIHtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRzIHx8IHt9O1xuICAgIHRoaXMucm91dGVyID0gdGhpcy5vcHRpb25zLnJvdXRlcjtcbiAgfSxcblxuICByZW5kZXI6IGZ1bmN0aW9uKCl7XG4gICAgdmFyIHJlc3BvbnNlTW9kZWwsIHJlc3BvbnNlTW9kZWxWaWV3O1xuICAgIHZhciB2YWx1ZSA9IHRoaXMucm91dGVyLmFwaS5tb2RlbHNbdGhpcy5tb2RlbC5yZXNwb25zZU1vZGVsXTtcbiAgICAkKHRoaXMuZWwpLmh0bWwoSGFuZGxlYmFycy50ZW1wbGF0ZXMuc3RhdHVzX2NvZGUodGhpcy5tb2RlbCkpO1xuXG4gICAgaWYgKHRoaXMucm91dGVyLmFwaS5tb2RlbHMuaGFzT3duUHJvcGVydHkodGhpcy5tb2RlbC5yZXNwb25zZU1vZGVsKSkge1xuICAgICAgcmVzcG9uc2VNb2RlbCA9IHtcbiAgICAgICAgc2FtcGxlSlNPTjogSlNPTi5zdHJpbmdpZnkoU3dhZ2dlclVpLnBhcnRpYWxzLnNpZ25hdHVyZS5jcmVhdGVKU09OU2FtcGxlKHZhbHVlKSwgdm9pZCAwLCAyKSxcbiAgICAgICAgc2FtcGxlWE1MOiB0aGlzLm1vZGVsLmlzWE1MID8gU3dhZ2dlclVpLnBhcnRpYWxzLnNpZ25hdHVyZS5jcmVhdGVYTUxTYW1wbGUoJycsIHRoaXMubW9kZWwuc2NoZW1hLCB0aGlzLnJvdXRlci5hcGkubW9kZWxzKSA6IGZhbHNlLFxuICAgICAgICBpc1BhcmFtOiBmYWxzZSxcbiAgICAgICAgc2lnbmF0dXJlOiBTd2FnZ2VyVWkucGFydGlhbHMuc2lnbmF0dXJlLmdldE1vZGVsU2lnbmF0dXJlKHRoaXMubW9kZWwucmVzcG9uc2VNb2RlbCwgdmFsdWUsIHRoaXMucm91dGVyLmFwaS5tb2RlbHMpLFxuICAgICAgICBkZWZhdWx0UmVuZGVyaW5nOiB0aGlzLm1vZGVsLmRlZmF1bHRSZW5kZXJpbmdcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3BvbnNlTW9kZWwgPSB7XG4gICAgICAgIHNpZ25hdHVyZTogU3dhZ2dlclVpLnBhcnRpYWxzLnNpZ25hdHVyZS5nZXRQcmltaXRpdmVTaWduYXR1cmUodGhpcy5tb2RlbC5zY2hlbWEpXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJlc3BvbnNlTW9kZWxWaWV3ID0gbmV3IFN3YWdnZXJVaS5WaWV3cy5TaWduYXR1cmVWaWV3KHttb2RlbDogcmVzcG9uc2VNb2RlbCwgdGFnTmFtZTogJ2Rpdid9KTtcbiAgICAkKCcubW9kZWwtc2lnbmF0dXJlJywgdGhpcy4kZWwpLmFwcGVuZChyZXNwb25zZU1vZGVsVmlldy5yZW5kZXIoKS5lbCk7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cbn0pOyJdfQ==\n"
  },
  {
    "path": "ymall-web-api/pom.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0</modelVersion>\n\n    <parent>\n        <groupId>com.yuu</groupId>\n        <artifactId>ymall-dependencies</artifactId>\n        <version>1.0.0-SNAPSHOT</version>\n        <relativePath>../ymall-dependencies/pom.xml</relativePath>\n    </parent>\n\n    <artifactId>ymall-web-api</artifactId>\n    <packaging>war</packaging>\n\n    <name>ymall-web-api</name>\n    <description>Web Ui Api</description>\n\n    <dependencies>\n\n        <!-- Database Begin -->\n        <dependency>\n            <groupId>com.alibaba</groupId>\n            <artifactId>druid</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>mysql</groupId>\n            <artifactId>mysql-connector-java</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.mybatis</groupId>\n            <artifactId>mybatis</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.mybatis</groupId>\n            <artifactId>mybatis-spring</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-jdbc</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.github.miemiedev</groupId>\n            <artifactId>mybatis-paginator</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.github.pagehelper</groupId>\n            <artifactId>pagehelper</artifactId>\n        </dependency>\n        <!-- Database End -->\n\n        <!-- Project Begin -->\n        <dependency>\n            <groupId>com.yuu</groupId>\n            <artifactId>ymall-commons</artifactId>\n            <version>${project.parent.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>com.yuu</groupId>\n            <artifactId>ymall-domain</artifactId>\n            <version>${project.parent.version}</version>\n        </dependency>\n        <!-- Project End -->\n\n        <!-- Redis Begin -->\n        <dependency>\n            <groupId>redis.clients</groupId>\n            <artifactId>jedis</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework.data</groupId>\n            <artifactId>spring-data-redis</artifactId>\n        </dependency>\n        <!-- Redis End -->\n\n        <!-- Spring Begin -->\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-webmvc</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-aspects</artifactId>\n        </dependency>\n        <!-- Spring End -->\n\n        <!-- Servlet Begin -->\n        <dependency>\n            <groupId>javax.servlet</groupId>\n            <artifactId>javax.servlet-api</artifactId>\n            <scope>provided</scope>\n        </dependency>\n        <dependency>\n            <groupId>javax.servlet</groupId>\n            <artifactId>jstl</artifactId>\n        </dependency>\n        <!-- Servlet End -->\n\n        <!-- Shiro Begin -->\n        <dependency>\n            <groupId>org.apache.shiro</groupId>\n            <artifactId>shiro-all</artifactId>\n        </dependency>\n        <!-- Shiro End -->\n\n        <!-- Swagger2 Begin -->\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger2</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>io.springfox</groupId>\n            <artifactId>springfox-swagger-ui</artifactId>\n        </dependency>\n        <!-- Swagger2 End -->\n\n        <!-- QiNiuYun Begin -->\n        <dependency>\n            <groupId>com.qiniu</groupId>\n            <artifactId>qiniu-java-sdk</artifactId>\n            <exclusions>\n                <exclusion>\n                    <artifactId>gson</artifactId>\n                    <groupId>com.google.code.gson</groupId>\n                </exclusion>\n            </exclusions>\n        </dependency>\n        <!-- QiNiuYun End -->\n\n        <!-- Hutool Begin -->\n        <dependency>\n            <groupId>cn.hutool</groupId>\n            <artifactId>hutool-all</artifactId>\n            <version>${hutool.version}</version>\n        </dependency>\n        <!-- Hutool End -->\n\n        <!-- Mail Begin -->\n        <dependency>\n            <groupId>org.json</groupId>\n            <artifactId>json</artifactId>\n            <version>${json.version}</version>\n        </dependency>\n        <dependency>\n            <groupId>javax.mail</groupId>\n            <artifactId>mail</artifactId>\n            <version>${mail.version}</version>\n        </dependency>\n        <!-- Mail End -->\n\n        <!-- Thymeleaf Begin -->\n        <dependency>\n            <groupId>org.thymeleaf</groupId>\n            <artifactId>thymeleaf-spring4</artifactId>\n        </dependency>\n        <!-- Thymeleaf End -->\n\n        <!-- Alipay Begin -->\n        <dependency>\n            <groupId>com.alipay.sdk</groupId>\n            <artifactId>alipay-sdk-java</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>com.alipay</groupId>\n            <artifactId>alipay-trade-sdk</artifactId>\n            <version>20161215</version>\n        </dependency>\n        <dependency>\n            <groupId>commons-logging</groupId>\n            <artifactId>commons-logging</artifactId>\n        </dependency>\n        <!-- Alipay End -->\n\n        <!-- Quartz Begin -->\n        <dependency>\n            <groupId>org.quartz-scheduler</groupId>\n            <artifactId>quartz</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-context-support</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-tx</artifactId>\n        </dependency>\n        <dependency>\n            <groupId>org.springframework</groupId>\n            <artifactId>spring-web</artifactId>\n        </dependency>\n        <!-- Quartz End -->\n    </dependencies>\n\n    <build>\n        <plugins>\n            <!-- MyBatis Generator Plugin -->\n            <plugin>\n                <groupId>org.mybatis.generator</groupId>\n                <artifactId>mybatis-generator-maven-plugin</artifactId>\n                <version>1.3.2</version>\n                <configuration>\n                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>\n                    <verbose>true</verbose>\n                    <overwrite>true</overwrite>\n                </configuration>\n                <dependencies>\n                    <dependency>\n                        <groupId>mysql</groupId>\n                        <artifactId>mysql-connector-java</artifactId>\n                        <version>${mysql.version}</version>\n                    </dependency>\n                </dependencies>\n            </plugin>\n            <!-- Compiler 插件, 设定 JDK 版本 -->\n            <plugin>\n                <groupId>org.apache.maven.plugins</groupId>\n                <artifactId>maven-compiler-plugin</artifactId>\n                <configuration>\n                    <source>1.8</source>\n                    <target>1.8</target>\n                    <encoding>UTF-8</encoding>\n                    <compilerArguments>\n                        <extdirs>${project.basedir}/src/main/webapp/WEB-INF/lib</extdirs>\n                    </compilerArguments>\n                </configuration>\n            </plugin>\n        </plugins>\n    </build>\n\n</project>\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/common/config/AlipayConfig.java",
    "content": "package com.yuu.ymall.web.api.common.config;\n\n/**\n * 支付宝支付配置\n *\n * @author by Yuu\n * @classname AlipayConfig\n * @date 2019/7/6 17:14\n */\npublic class AlipayConfig {\n    /**\n     * 应用ID,您的APPID，收款账号既是您的APPID对应支付宝账号\n     */\n    public static String app_id = \"\";\n\n    /**\n     * 商户私钥，您的PKCS8格式RSA2私钥\n     */\n    public static String merchant_private_key = \"\";\n    /**\n     * 支付宝公钥,查看地址：https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥\n     */\n    public static String alipay_public_key = \"\";\n    \n    /**\n     * 服务器异步通知页面路径  需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问\n     */\n    public static String notify_url = \"http://4bjxng.natappfree.cc/order/callback\";\n\n    /**\n     * 页面跳转同步通知页面路径 需http://格式的完整路径，不能加?id=123这类自定义参数，必须外网可以正常访问\n     */\n    public static String return_url = \"http://localhost:8080/\";\n\n    /**\n     * 签名方式\n     */\n    public static String sign_type = \"RSA2\";\n\n    /**\n     * 字符编码格式\n     */\n    public static String charset = \"utf-8\";\n\n    /**\n     * 支付宝网关\n     */\n    public static String gatewayUrl = \"https://openapi.alipaydev.com/gateway.do\";\n\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/common/config/SwaggerConfiguration.java",
    "content": "package com.yuu.ymall.web.api.common.config;\n\nimport io.swagger.annotations.ApiOperation;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.ComponentScan;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.servlet.config.annotation.EnableWebMvc;\nimport springfox.documentation.builders.ApiInfoBuilder;\nimport springfox.documentation.builders.PathSelectors;\nimport springfox.documentation.builders.RequestHandlerSelectors;\nimport springfox.documentation.service.ApiInfo;\nimport springfox.documentation.service.Contact;\nimport springfox.documentation.spi.DocumentationType;\nimport springfox.documentation.spring.web.plugins.Docket;\nimport springfox.documentation.swagger2.annotations.EnableSwagger2;\n\n/**\n * @Classname Swagger2Confinguration\n * @Date 2019/5/12 11:33\n * @Created by Yuu\n */\n@Configuration  // 让 Spring 来加载该配置类\n@EnableWebMvc   // 非 Spring Boot 需启用\n@EnableSwagger2 // 启用 Swagger2\n@ComponentScan(basePackages = \"com.yuu.ymall.web.api.controller\")\npublic class SwaggerConfiguration {\n\n    public static final Logger log = LoggerFactory.getLogger(SwaggerConfiguration.class);\n\n    @Bean\n    public Docket createRestApi() {\n        log.info(\"开始加载Swagger2...\");\n        return new Docket(DocumentationType.SWAGGER_2)\n                .apiInfo(apiInfo())\n                .select()\n                // 扫描指定包中的 swagger 注解\n                //.apis(RequestHandlerSelectors.basePackage(\"com.yuu.ymall.controller.admin.controller\"))\n                // 扫描所有有注解的 api，用这种方式更灵活\n                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))\n                .paths(PathSelectors.any())\n                .build();\n    }\n\n    private ApiInfo apiInfo() {\n        return new ApiInfoBuilder()\n                .title(\"YMall API Documentation\")\n                .description(\"YMall 商城API接口\")\n                .termsOfServiceUrl(\"https://www.71yuu.com\")\n                .contact(new Contact(\"Yuu\", \"https://www.71yuu.com\", \"1225459207@qq.com\"))\n                .version(\"1.0.0\")\n                .build();\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/common/config/ThymeleafConfig.java",
    "content": "package com.yuu.ymall.web.api.common.config;\n\n\nimport org.springframework.context.ApplicationContext;\nimport org.springframework.context.ApplicationContextAware;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.web.servlet.ViewResolver;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\nimport org.thymeleaf.TemplateEngine;\nimport org.thymeleaf.spring4.SpringTemplateEngine;\nimport org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver;\nimport org.thymeleaf.spring4.view.ThymeleafViewResolver;\nimport org.thymeleaf.templatemode.TemplateMode;\nimport org.thymeleaf.templateresolver.ITemplateResolver;\n\n/**\n * @author by Yuu\n * @classname ThymeleafConfig\n * @date 2019/6/28 16:17\n */\n@Configuration\npublic class ThymeleafConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {\n\n    private ApplicationContext applicationContext;\n\n    @Override\n    public void setApplicationContext(ApplicationContext applicationContext) {\n        this.applicationContext = applicationContext;\n    }\n\n    @Bean\n    public ViewResolver viewResolver() {\n        ThymeleafViewResolver resolver = new ThymeleafViewResolver();\n        resolver.setTemplateEngine(templateEngine());\n        resolver.setCharacterEncoding(\"UTF-8\");\n        return resolver;\n    }\n\n    @Bean\n    public TemplateEngine templateEngine() {\n        SpringTemplateEngine engine = new SpringTemplateEngine();\n        engine.setEnableSpringELCompiler(true);\n        engine.setTemplateResolver(templateResolver());\n        return engine;\n    }\n\n    private ITemplateResolver templateResolver() {\n        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();\n        resolver.setApplicationContext(applicationContext);\n        resolver.setPrefix(\"/WEB-INF/templates/\");\n        resolver.setSuffix(\".html\");\n        resolver.setCharacterEncoding(\"UTF-8\");\n        resolver.setTemplateMode(TemplateMode.HTML);\n        return resolver;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/common/utils/EmailUtil.java",
    "content": "package com.yuu.ymall.web.api.common.utils;\n\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.mail.javamail.JavaMailSenderImpl;\nimport org.springframework.mail.javamail.MimeMessageHelper;\nimport org.springframework.scheduling.annotation.Async;\nimport org.springframework.stereotype.Component;\nimport org.thymeleaf.TemplateEngine;\nimport org.thymeleaf.context.Context;\n\nimport javax.mail.MessagingException;\nimport javax.mail.internet.MimeMessage;\nimport java.util.Properties;\nimport java.util.regex.Matcher;\nimport java.util.regex.Pattern;\n\n/**\n * @author by Yuu\n * @classname EmailUtil\n * @date 2019/6/28 12:37\n */\n@Component\npublic class EmailUtil {\n\n    private final static Logger log= LoggerFactory.getLogger(EmailUtil.class);\n\n    @Value(\"${EMAIL_HOST}\")\n    private String EMAIL_HOST;\n\n    @Value(\"${EMAIL_USERNAME}\")\n    private String EMAIL_USERNAME;\n\n    @Value(\"${EMAIL_PASSWORD}\")\n    private String EMAIL_PASSWORD;\n\n    @Value(\"${EMAIL_SENDER}\")\n    private String EMAIL_SENDER;\n\n    @Value(\"${SERVER_URL}\")\n    private String SERVER_URL;\n\n    @Autowired\n    private TemplateEngine templateEngine;\n\n    @Async\n    public void sendTemplateEmail(String sendTo,String title,String templateName,Object o){\n\n        JavaMailSenderImpl senderImpl = new JavaMailSenderImpl();\n\n        //设定邮箱服务器配置\n        senderImpl.setHost(EMAIL_HOST);\n        senderImpl.setUsername(EMAIL_USERNAME);\n        senderImpl.setPassword(EMAIL_PASSWORD);\n        Properties prop = new Properties();\n        //服务器进行认证\n        prop.put(\"mail.smtp.auth\", \"true\");\n        prop.put(\"mail.smtp.timeout\", \"20000\");\n        //邮箱发送服务器端口,这里设置为465端口\n        prop.setProperty(\"mail.smtp.port\", \"465\");\n        prop.setProperty(\"mail.smtp.socketFactory.port\", \"465\");\n        //qq邮箱需开启\n        prop.put(\"mail.smtp.ssl.enable\", \"true\");\n        senderImpl.setJavaMailProperties(prop);\n\n        //发送html邮件\n        MimeMessage mailMessage = senderImpl.createMimeMessage();\n        MimeMessageHelper messageHelper = null;\n        //设置邮件内容\n        try {\n            messageHelper = new MimeMessageHelper(mailMessage,true,\"utf-8\");\n\n            messageHelper.setTo(sendTo);\n            messageHelper.setFrom(EMAIL_SENDER);\n            messageHelper.setSubject(title);\n            Context context = new Context();\n            context.setVariable(\"title\",title);\n            context.setVariables(ObjectUtil.beanToMap(o));\n            //获取模板html代码\n            String content = templateEngine.process(templateName, context);\n            // true表示HTML格式的邮件\n            messageHelper.setText(content, true);\n\n        } catch (MessagingException e) {\n            e.printStackTrace();\n        }\n\n        // 发送邮件\n        senderImpl.send(mailMessage);\n        log.info(\"给\"+sendTo+\"发送邮件成功\");\n    }\n\n    /**\n     * 验证邮箱\n     *\n     * @param email\n     * @return\n     */\n    public static boolean checkEmail(String email) {\n        boolean flag = false;\n        try {\n            String check = \"^([a-z0-9A-Z]+[-|_|\\\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\\\.)+[a-zA-Z]{2,}$\";\n            Pattern regex = Pattern.compile(check);\n            Matcher matcher = regex.matcher(email);\n            flag = matcher.matches();\n        } catch (Exception e) {\n            flag = false;\n        }\n        return flag;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/common/utils/IPInfoUtil.java",
    "content": "package com.yuu.ymall.web.api.common.utils;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.net.InetAddress;\nimport java.net.UnknownHostException;\n\n/**\n * IP 信息工具类\n *\n * @Classname IPInfoUtil\n * @Date 2019/5/13 14:09\n * @Created by Yuu\n */\npublic class IPInfoUtil {\n\n    /**\n     * 获取客户端 IP 地址\n     *\n     * @param request 请求\n     * @return\n     */\n    public static String getIpAddr(HttpServletRequest request) {\n        String ip = request.getHeader(\"x-forwarded-for\");\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"Proxy-Client-IP\");\n        }\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getHeader(\"WL-Proxy-Client-IP\");\n        }\n        if (ip == null || ip.length() == 0 || \"unknown\".equalsIgnoreCase(ip)) {\n            ip = request.getRemoteAddr();\n            if (ip.equals(\"127.0.0.1\")) {\n                //根据网卡取本机配置的IP\n                InetAddress inet = null;\n                try {\n                    inet = InetAddress.getLocalHost();\n                } catch (UnknownHostException e) {\n                    e.printStackTrace();\n                }\n                ip = inet.getHostAddress();\n            }\n        }\n        // 对于通过多个代理的情况下，第一个 IP 为客户端真实 IP ，多个 IP 按照‘，’分割\n        if (ip != null && ip.length() > 15) {\n            if (ip.indexOf(\",\") > 0) {\n                ip = ip.substring(0, ip.indexOf(\",\"));\n            }\n        }\n        if(\"0:0:0:0:0:0:0:1\".equals(ip)){\n            ip=\"127.0.0.1\";\n        }\n        return ip;\n    }\n\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/common/utils/ObjectUtil.java",
    "content": "package com.yuu.ymall.web.api.common.utils;\n\nimport com.google.common.collect.Maps;\nimport com.google.gson.Gson;\nimport org.springframework.cglib.beans.BeanMap;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * @author by Yuu\n * @classname ObjectUtil\n * @date 2019/6/28 12:45\n */\npublic class ObjectUtil {\n    /**\n     * Bean 转 Map\n     * @param bean\n     * @param <T>\n     * @return\n     */\n    public static <T> Map<String, Object> beanToMap(T bean) {\n        Map<String, Object> map = Maps.newHashMap();\n        if (bean != null) {\n            BeanMap beanMap = BeanMap.create(bean);\n            for (Object key : beanMap.keySet()) {\n                map.put(key+\"\", beanMap.get(key));\n            }\n        }\n        return map;\n    }\n\n    public static String mapToStringAll(Map<String, String[]> paramMap){\n\n        if (paramMap == null) {\n            return \"\";\n        }\n        Map<String, Object> params = new HashMap<>(16);\n        for (Map.Entry<String, String[]> param : paramMap.entrySet()) {\n\n            String key = param.getKey();\n            String paramValue = (param.getValue() != null && param.getValue().length > 0 ? param.getValue()[0] : \"\");\n            params.put(key, paramValue);\n        }\n        return new Gson().toJson(params);\n    }\n\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/common/utils/QiniuUtil.java",
    "content": "package com.yuu.ymall.web.api.common.utils;\n\nimport com.google.gson.Gson;\nimport com.qiniu.common.QiniuException;\nimport com.qiniu.common.Zone;\nimport com.qiniu.http.Response;\nimport com.qiniu.storage.Configuration;\nimport com.qiniu.storage.UploadManager;\nimport com.qiniu.storage.model.DefaultPutRet;\nimport com.qiniu.util.Auth;\nimport com.qiniu.util.StringMap;\nimport com.qiniu.util.UrlSafeBase64;\nimport com.yuu.ymall.commons.execption.YmallUploadException;\nimport okhttp3.OkHttpClient;\nimport okhttp3.Request;\nimport okhttp3.RequestBody;\nimport org.apache.commons.fileupload.servlet.ServletFileUpload;\nimport org.slf4j.Logger;\nimport org.slf4j.LoggerFactory;\nimport org.springframework.web.multipart.MultipartFile;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.io.FileInputStream;\nimport java.io.IOException;\nimport java.util.Arrays;\nimport java.util.HashMap;\n\n/**\n * 七牛云图片上传工具类\n * @Classname QiniuUtil\n * @Date 2019/5/24 20:38\n * @Created by Yuu\n */\npublic class QiniuUtil {\n\n    private final static Logger log = LoggerFactory.getLogger(QiniuUtil.class);\n\n    /**\n     * 生成上传凭证，然后准备上传\n     */\n    private static String accessKey = \"\";\n    private static String secretKey = \"\";\n    private static String bucket = \"ymall\";\n    private static String origin = \"\";\n    private static Auth auth = Auth.create(accessKey, secretKey);\n\n    public static String getUpToken() {\n        return auth.uploadToken(bucket, null, 3600, new StringMap().put(\"insertOnly\", 1));\n    }\n\n    public static String qiniuBase64Upload(String data64){\n\n        String key = renamePic(\".png\");\n        Auth auth = Auth.create(accessKey, secretKey);\n        String upToken = auth.uploadToken(bucket);\n        //服务端http://up-z2.qiniup.com\n        String url = \"http://up-z2.qiniup.com/putb64/-1/key/\"+ UrlSafeBase64.encodeToString(key);\n        RequestBody rb = RequestBody.create(null, data64);\n        Request request = new Request.Builder().\n                url(url).\n                addHeader(\"Content-Type\", \"application/octet-stream\")\n                .addHeader(\"Authorization\", \"UpToken \" + getUpToken())\n                .post(rb).build();\n        OkHttpClient client = new OkHttpClient();\n        okhttp3.Response response = null;\n        try {\n            response = client.newCall(request).execute();\n        } catch (IOException e) {\n            e.printStackTrace();\n        }\n        return origin+key;\n    }\n\n    public static String base64Data(String data){\n\n        if(data==null||data.isEmpty()){\n            return \"\";\n        }\n        String base64 =data.substring(data.lastIndexOf(\",\")+1);\n        return base64;\n    }\n\n    /**\n     * 以时间戳重命名\n     * @param fileName\n     * @return\n     */\n    public static String renamePic(String fileName){\n        String extName = fileName.substring(fileName.lastIndexOf(\".\"));\n        return System.currentTimeMillis()+extName;\n    }\n\n    public static String isValidImage(HttpServletRequest request, MultipartFile file){\n        //最大文件大小\n        long maxSize = 5242880;\n        //定义允许上传的文件扩展名\n        HashMap<String, String> extMap = new HashMap<String, String>();\n        extMap.put(\"image\", \"gif,jpg,jpeg,png,bmp\");\n\n        if(!ServletFileUpload.isMultipartContent(request)){\n            return \"请选择文件\";\n        }\n\n        if(file.getSize() > maxSize){\n            return \"上传文件大小超过5MB限制\";\n        }\n        //检查扩展名\n        String fileName=file.getOriginalFilename();\n        String fileExt = fileName.substring(fileName.lastIndexOf(\".\") + 1).toLowerCase();\n        if(!Arrays.<String>asList(extMap.get(\"image\").split(\",\")).contains(fileExt)){\n            return \"上传文件扩展名是不允许的扩展名\\n只允许\" + extMap.get(\"image\") + \"格式\";\n        }\n\n        return \"valid\";\n    }\n\n    public static String checkExt(String fileName,String dirName){\n        //定义允许上传的文件扩展名\n        HashMap<String, String> extMap = new HashMap<String, String>();\n        extMap.put(\"image\", \"gif,jpg,jpeg,png,bmp\");\n        extMap.put(\"flash\", \"swf,flv\");\n        extMap.put(\"media\", \"swf,flv,mp3,wav,wma,wmv,mid,avi,mpg,asf,rm,rmvb\");\n\n        //检查扩展名\n        String fileExt = fileName.substring(fileName.lastIndexOf(\".\") + 1).toLowerCase();\n        if(!Arrays.<String>asList(extMap.get(dirName).split(\",\")).contains(fileExt)){\n            return \"上传文件扩展名是不允许的扩展名\\n只允许\" + extMap.get(dirName) + \"格式\";\n        }\n        return \"valid\";\n    }\n\n    public static void main(String[] args){\n        base64Data(\"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/2\");\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/controller/CartController.java",
    "content": "package com.yuu.ymall.web.api.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.web.api.dto.Cart;\nimport com.yuu.ymall.web.api.service.CartService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\n/**\n * 购物车视图层\n *\n * @author by Yuu\n * @classname CartController\n * @date 2019/7/3 9:08\n */\n@RestController\n@RequestMapping(\"member/cart\")\n@Api(description = \"购物车服务接口\")\npublic class CartController {\n\n    @Autowired\n    private CartService cartService;\n\n    /**\n     * 添加商品到购物车\n     *\n     * @param cart 商品\n     * @return\n     */\n    @PostMapping(\"addProduct\")\n    @ApiOperation(value = \"购物车添加商品\")\n    public BaseResult addProduct(@RequestBody Cart cart) {\n        BaseResult baseResult = cartService.addProduct(cart);\n        return baseResult;\n    }\n\n    /**\n     * 获取会员购物车列表\n     *\n     * @param userId 会员 id\n     * @return\n     */\n    @GetMapping(\"getCartList\")\n    @ApiOperation(value = \"获取购物车列表\")\n    public BaseResult getCartList(@RequestParam Long userId) {\n        BaseResult baseResult = cartService.getCartList(userId);\n        return baseResult;\n    }\n\n    /**\n     * 删除购物车商品\n     *\n     * @param userId 会员id\n     * @param productId 商品id\n     * @return\n     */\n    @PostMapping(\"delProduct\")\n    @ApiOperation(value = \"购物车删除商品\")\n    public BaseResult delProduct(@RequestBody Cart cart) {\n        BaseResult baseResult = cartService.delProduct(cart);\n        return baseResult;\n    }\n\n    /**\n     * 修改购物车商品\n     *\n     * @param cart 购物车商品\n     * @return\n     */\n    @PostMapping(\"editProduct\")\n    @ApiOperation(value = \"修改购物车商品\")\n    public BaseResult editProduct(@RequestBody Cart cart) {\n        BaseResult baseResult = cartService.editProduct(cart);\n        return baseResult;\n    }\n\n    /**\n     * 全选购物车\n     *\n     * @param cart 购物车\n     * @return\n     */\n    @PostMapping(\"editCheckAll\")\n    @ApiOperation(value = \"全选购物车\")\n    public BaseResult editCheckAll(@RequestBody Cart cart) {\n        BaseResult baseResult = cartService.editCheckAll(cart);\n        return baseResult;\n    }\n\n    /**\n     * 删除已选购物车商品\n     *\n     * @param cart 购物车\n     * @return\n     */\n    @PostMapping(\"delChecked\")\n    @ApiOperation(value = \"删除已选购物车商品\")\n    public BaseResult delCartChecked(@RequestBody Cart cart) {\n        BaseResult baseResult = cartService.delCartChecked(cart);\n        return baseResult;\n    }\n\n}\n\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/controller/GoodsController.java",
    "content": "package com.yuu.ymall.web.api.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.web.api.dto.CategoryProductPageInfo;\nimport com.yuu.ymall.web.api.repositories.ItemRepository;\nimport com.yuu.ymall.web.api.service.ContentService;\nimport com.yuu.ymall.web.api.service.ItemCatService;\nimport com.yuu.ymall.web.api.service.ProductService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.elasticsearch.core.ElasticsearchTemplate;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * @author by Yuu\n * @classname GoodsController\n * @date 2019/6/29 18:03\n */\n@RestController\n@RequestMapping(\"goods\")\n@Api(description = \"商品服务接口\")\npublic class GoodsController {\n\n    @Autowired\n    private ItemRepository itemRepository;\n\n    @Autowired\n    private ElasticsearchTemplate elasticsearchTemplate;\n\n    @Autowired\n    private ItemCatService itemCatService;\n\n    @Autowired\n    private ContentService contentService;\n\n    @Autowired\n    private ProductService productService;\n\n    /**\n     * 快速搜索\n     *\n     * @param key 搜索关键字\n     * @return\n     */\n    @GetMapping(value = \"quickSearch\")\n    @ApiOperation(\"\")\n    public BaseResult getQuickSearch(@RequestParam(defaultValue = \"\") String key) {\n        BaseResult baseResult = productService.getQuickSearch(key);\n        return BaseResult.success(baseResult);\n    }\n\n    /**\n     * 获取分类信息\n     *\n     * @return\n     */\n    @GetMapping(\"cateList\")\n    @ApiOperation(value = \"获取分类列表\")\n    public BaseResult getCateList() {\n        BaseResult baseResult = itemCatService.getCateList();\n        return baseResult;\n    }\n\n    /**\n     * 获取首页各板块内容\n     *\n     * @return\n     */\n    @GetMapping(\"home\")\n    @ApiOperation(value = \"获取首页各板块内容\")\n    public BaseResult getProductHome() {\n        BaseResult baseResult = contentService.getHome();\n        return baseResult;\n    }\n\n    /**\n     * 获取商品详情\n     *\n     * @param productId 商品 id\n     * @return\n     */\n    @GetMapping(\"productDet\")\n    @ApiOperation(value = \"获取商品详情\")\n    public BaseResult getProductDet(@RequestParam Long productId) {\n        BaseResult baseResult = productService.getProductDet(productId);\n        return baseResult;\n    }\n\n    /**\n     * 获取推荐商品模块\n     *\n     * @return\n     */\n    @GetMapping(\"recommend\")\n    @ApiOperation(value = \"获取推荐商品\")\n    public BaseResult getRecommendGoods() {\n        BaseResult baseResult = contentService.getRecommendGoods();\n        return baseResult;\n    }\n\n    /**\n     * 分页商品查询\n     *\n     * @param categoryProductPageInfo\n     * @return\n     */\n    @GetMapping(\"getCategoryGoods\")\n    @ApiOperation(value = \"所有商品\")\n    public BaseResult getCategoryProducts(CategoryProductPageInfo categoryProductPageInfo) {\n        BaseResult baseResult = productService.getByCategory(categoryProductPageInfo);\n        return baseResult;\n    }\n}\n\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/controller/MemberController.java",
    "content": "package com.yuu.ymall.web.api.controller;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.geetest.GeetestLib;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.domain.TbAddress;\nimport com.yuu.ymall.domain.TbMember;\nimport com.yuu.ymall.web.api.dto.Member;\nimport com.yuu.ymall.web.api.dto.MemberLogin;\nimport com.yuu.ymall.web.api.service.MemberService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\nimport javax.servlet.http.HttpSession;\nimport java.util.HashMap;\n\n/**\n * 前台会员控制器\n *\n * @author by Yuu\n * @classname MemberController\n * @date 2019/6/24 8:57\n */\n@RestController\n@Api(description = \"会员服务接口\")\n@RequestMapping(\"member\")\npublic class MemberController {\n\n    @Autowired\n    private MemberService memberService;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    /**\n     * 验证手机号是否存在\n     *\n     * @param phone 手机号\n     * @return\n     */\n    @GetMapping(\"checkphone/{phone}\")\n    @ApiOperation(value = \"验证手机号是存在\")\n    public BaseResult checkPhone(@PathVariable String phone) {\n        BaseResult baseResult = memberService.checkPhone(phone);\n        return baseResult;\n    }\n\n    /**\n     * 发送短信验证码\n     *\n     * @param phone 手机号\n     * @return\n     */\n    @GetMapping(\"sendsms/{phone}\")\n    @ApiOperation(value = \"发送短信验证码\")\n    public BaseResult sendSms(@PathVariable String phone) {\n        BaseResult baseResult = memberService.sendSms(phone);\n        return baseResult;\n    }\n\n    /**\n     * 会员注册\n     *\n     * @param tbMember 会员\n     * @return\n     */\n    @PostMapping(\"register\")\n    @ApiOperation(value = \"会员注册\")\n    public BaseResult register(@RequestBody TbMember tbMember) {\n        BaseResult baseResult = memberService.register(tbMember);\n        return baseResult;\n    }\n\n    /**\n     * 登录极验初始化\n     *\n     * @param request\n     * @return\n     */\n    @GetMapping(\"geetestInit\")\n    @ApiOperation(value = \"极验初始化\")\n    public String geetestInit(HttpServletRequest request) {\n        GeetestLib gtSdk = new GeetestLib(GeetestLib.id, GeetestLib.key,GeetestLib.newfailback);\n        String resStr = \"{}\";\n        //自定义参数,可选择添加\n        HashMap<String, String> param = new HashMap<String, String>();\n        // 进行验证预处理\n        int getServerStatus = gtSdk.preProcess(param);\n        resStr = gtSdk.getResponseStr();\n        return resStr;\n    }\n\n    /**\n     * 会员登录\n     *\n     * @param memberLogin 会员登录信息\n     * @return\n     */\n    @PostMapping(\"login\")\n    @ApiOperation(value = \"用户登录\")\n    public BaseResult login(@RequestBody MemberLogin memberLogin, HttpSession session) {\n        BaseResult baseResult = memberService.login(memberLogin, session);\n        return baseResult;\n    }\n\n    /**\n     * 验证会员是否登录\n     *\n     * @param token 会员本地 token\n     * @return\n     */\n    @GetMapping(\"checkLogin\")\n    @ApiOperation(value = \"验证用户是否登录\")\n    public BaseResult checkLogin(@RequestParam(defaultValue = \"\") String token, HttpSession session) {\n        // 会员信息存在 session 中\n        if (\"\".equals(token)) {\n            // 判判断 HttpSession 中是否有登录信息\n            TbMember tbMember = (TbMember) session.getAttribute(\"memberLogin\");\n            if (tbMember != null) {\n                // 用户未选择自动登录，session 中有登录信息\n                return BaseResult.success(tbMember);\n            } else {\n                return BaseResult.fail(\"用户未登录！\");\n            }\n        }\n        // 会员信息存在 Redis 中\n        BaseResult baseResult = memberService.getMemberByToken(token);\n        return baseResult;\n    }\n\n    /**\n     * 退出登录\n     *\n     * @param token 会员本地的 token\n     * @return\n     */\n    @GetMapping(\"logout\")\n    @ApiOperation(value = \"退出登录\")\n    public BaseResult logout(@RequestParam(defaultValue = \"\") String token, HttpSession session) {\n        // 从 session 中退出登录\n        if (\"\".equals(token)) {\n            session.removeAttribute(\"memberLogin\");\n            return BaseResult.success(\"退出登录成功!\");\n        }\n        // 从 Redis 中退出登录\n        BaseResult baseResult = memberService.logout(token);\n        return baseResult;\n    }\n\n    /**\n     * 验证手机号或邮箱是否存在\n     *\n     * @param account 手机号或邮箱\n     * @return\n     */\n    @GetMapping(\"checkAccount\")\n    @ApiOperation(value = \"验证手机号或邮箱是否存在\")\n    public BaseResult checkAccount(@RequestParam(defaultValue = \"\") String account) {\n        BaseResult baseResult = memberService.checkAccount(account);\n        return baseResult;\n    }\n\n    /**\n     * 会员修改密码\n     *\n     * @param account 手机号或邮箱\n     * @param password 密码\n     * @return\n     */\n    @PostMapping(\"updatePassword\")\n    @ApiOperation(value = \"会员修改密码\")\n    public BaseResult updatePassword(@RequestBody MemberLogin memberLogin) {\n        BaseResult baseResult = memberService.updatePassword(memberLogin);\n        return baseResult;\n    }\n\n    /**\n     * 忘记密码发送验证码\n     *\n     * @param account 手机号或邮箱\n     * @return\n     */\n    @GetMapping(\"forgetVerCode\")\n    @ApiOperation(value = \"会员忘记密码发送验证码\")\n    public BaseResult forgetVerCode(@RequestParam(defaultValue = \"\") String account) {\n        BaseResult baseResult = memberService.sendVerCode(account);\n        return baseResult;\n    }\n\n    /**\n     * 获取会员地址列表\n     *\n     * @param userId 会员 id\n     * @return\n     */\n    @GetMapping(\"addressList\")\n    @ApiOperation(value = \"获取会员地址列表\")\n    public BaseResult getAddressList(@RequestParam Long userId) {\n        BaseResult baseResult = memberService.getAddressList(userId);\n        return baseResult;\n    }\n\n    /**\n     * 修改会员收货地址\n     *\n     * @param tbAddress 会员地址\n     * @return\n     */\n    @PostMapping(\"addressUpdate\")\n    @ApiOperation(value = \"修改会员地址\")\n    public BaseResult addressUpdate(@RequestBody TbAddress tbAddress) {\n        BaseResult baseResult = memberService.updateAddress(tbAddress);\n        return baseResult;\n    }\n\n    /**\n     * 新增会员地址\n     *\n     * @param tbAddress 会员地址\n     * @return\n     */\n    @PostMapping(\"addressAdd\")\n    @ApiOperation(value = \"新增会员地址\")\n    public BaseResult addressAdd(@RequestBody TbAddress tbAddress) {\n        BaseResult baseResult = memberService.addAdderss(tbAddress);\n        return baseResult;\n    }\n\n    /**\n     * 删除会员地址\n     *\n     * @param id 地址 id\n     * @return\n     */\n    @PostMapping(\"addressDel\")\n    @ApiOperation(value = \"删除会员地址\")\n    public BaseResult addressDel(@RequestBody TbAddress tbAddress) {\n        BaseResult baseResult = memberService.delAddress(tbAddress.getId());\n        return baseResult;\n    }\n\n    /**\n     * 修改会员头像\n     *\n     * @return\n     */\n    @PostMapping(\"uploadImg\")\n    @ApiOperation(value = \"会员修改头像\")\n    public BaseResult uploadImg(@RequestBody Member member) {\n        BaseResult baseResult = memberService.uploadImg(member);\n        return baseResult;\n    }\n\n    /**\n     * 修改会员昵称\n     *\n     * @param member 会员数据接收对象\n     * @return\n     */\n    @PostMapping(\"updateUsername\")\n    @ApiOperation(value = \"修改会员昵称\")\n    public BaseResult updateUsername(@RequestBody Member member) {\n        BaseResult baseResult = memberService.updateUsername(member);\n        return baseResult;\n    }\n\n    /**\n     * 修改会员手机号\n     *\n     * @param member 会员数据接收对象\n     * @return\n     */\n    @PostMapping(\"updatePhone\")\n    @ApiOperation(value = \"修改会员手机号\")\n    public BaseResult updatePhone(@RequestBody Member member) {\n        BaseResult baseResult = memberService.updatePhone(member);\n        return baseResult;\n    }\n\n    /**\n     * 修改密码\n     *\n     * @param member 会员数据接收对象\n     * @return\n     */\n    @PostMapping(\"updatePass\")\n    @ApiOperation(value = \"修改密码\")\n    public BaseResult updatePassword(@RequestBody Member member) {\n            BaseResult baseResult = memberService.updatePass(member);\n        return baseResult;\n    }\n\n    /**\n     * 修改邮箱发送验证码\n     *\n     * @param email 邮箱\n     * @return\n     */\n    @GetMapping(\"sendEmailCode\")\n    @ApiOperation(value = \"修改邮箱发送验证码\")\n    public BaseResult sendEmailCode(@RequestParam String email) {\n        BaseResult baseResult = memberService.sendEmailCode(email);\n        return baseResult;\n    }\n\n    /**\n     * 验证邮箱是否存在\n     *\n     * @param email 邮箱\n     * @return\n     */\n    @GetMapping(\"checkEmail\")\n    @ApiOperation(value = \"验证邮箱是否存在\")\n    public BaseResult checkEmail(@RequestParam String email) {\n        BaseResult baseResult = memberService.checkEmail(email);\n        return baseResult;\n    }\n\n    /**\n     * 修改邮箱\n     *\n     * @param member 会员\n     * @return\n     */\n    @PostMapping(\"updateEmail\")\n    @ApiOperation(value = \"修改邮箱\")\n   public BaseResult updateEmail(@RequestBody Member member) {\n        BaseResult baseResult = memberService.updateEmail(member);\n        return baseResult;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/controller/OrderController.java",
    "content": "package com.yuu.ymall.web.api.controller;\n\nimport com.alipay.api.response.AlipayTradePrecreateResponse;\nimport com.alipay.demo.trade.model.TradeStatus;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.web.api.dto.Order;\nimport com.yuu.ymall.web.api.dto.OrderInfo;\nimport com.yuu.ymall.web.api.dto.OrderPay;\nimport com.yuu.ymall.web.api.service.OrderService;\nimport io.swagger.annotations.Api;\nimport io.swagger.annotations.ApiOperation;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.bind.annotation.*;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @author by Yuu\n * @classname OrderController\n * @date 2019/7/6 2:02\n */\n@RestController\n@RequestMapping(\"order\")\n@Api(description = \"订单服务接口\")\npublic class OrderController {\n\n    @Autowired\n    private OrderService orderService;\n\n    /**\n     * 创建订单\n     *\n     * @param orderInfo 订单信息\n     * @return\n     */\n    @PostMapping(\"addOrder\")\n    @ApiOperation(value = \"创建订单\")\n    public BaseResult addOrder(@RequestBody OrderInfo orderInfo, HttpServletRequest request) {\n        BaseResult baseResult = orderService.addOrder(orderInfo, request);\n        return baseResult;\n    }\n\n    /**\n     * 通过 id 获取订单\n     *\n     * @param orderId 订单 id\n     * @return\n     */\n    @GetMapping(\"getOrderDet\")\n    @ApiOperation(value = \"通过id获取订单详情\")\n    public BaseResult getOrderDet(@RequestParam String orderId) {\n        BaseResult baseResult = orderService.getOrderDet(orderId);\n        return baseResult;\n    }\n\n    /**\n     * 订单支付\n     *\n     * @param orderPay\n     * @return\n     */\n    @PostMapping(\"payment\")\n    @ApiOperation(value = \"订单支付\")\n    public AlipayTradePrecreateResponse payment(@RequestBody OrderPay orderPay) {\n        AlipayTradePrecreateResponse response = orderService.payment(orderPay);\n        return response;\n    }\n\n    /**\n     * 订单异步通知\n     */\n    @PostMapping(\"callback\")\n    @ApiOperation(value = \"订单异步通知\")\n    public String orderCallback(HttpServletRequest request) {\n        // 订单号\n        String orderId = request.getParameter(\"out_trade_no\");\n\n        // 交易状态\n        String tradeStatus = request.getParameter(\"trade_status\");\n\n        // 交易创建时间\n        String gmtCreate = request.getParameter(\"gmt_create\");\n\n        // 交易付款时间\n        String gmtPayment = request.getParameter(\"gmt_payment\");\n\n        // 交易结束时间\n        String gmtClose = request.getParameter(\"gmt_close\");\n\n        // 交易支付成功\n        if (\"TRADE_SUCCESS\".equals(tradeStatus)) {\n            // 修改订单状态\n            orderService.paySuccess(orderId);\n        }\n\n        return \"success\";\n    }\n\n    /**\n     * 获取订单支付状态\n     *\n     * @param orderId 订单 id\n     * @return\n     */\n    @GetMapping(\"getOrderStatus\")\n    @ApiOperation(value = \"获取订单支付状态\")\n    public TradeStatus getOrderStatus(@RequestParam String orderId) {\n        TradeStatus tradeStatus = orderService.getOrderStatus(orderId);\n        return tradeStatus;\n    }\n\n    /**\n     * 获取用户订单列表\n     *\n     * @return\n     */\n    @GetMapping(\"orderList\")\n    @ApiOperation(value = \"获取用户所有订单\")\n    public BaseResult getOrderList(@RequestParam String userId,\n                                   @RequestParam(defaultValue = \"1\") int page,\n                                   @RequestParam(defaultValue = \"5\") int size) {\n     BaseResult baseResult = orderService.getOrderList(userId, page, size);\n     return baseResult;\n    }\n\n    /**\n     * 确认收货\n     *\n     * @param orderId 订单\n     * @return\n     */\n    @PostMapping(\"confirmReceipt\")\n    @ApiOperation(value = \"确认收货\")\n    public BaseResult confirmReceipt(@RequestBody Order order) {\n        BaseResult baseResult = orderService.confirmReceipt(order);\n        return baseResult;\n    }\n\n    /**\n     * 删除订单\n     *\n     * @param order 订单\n     * @return\n     */\n    @PostMapping(\"deleteOrder\")\n    @ApiOperation(value = \"删除订单\")\n    public BaseResult deleteOrder(@RequestBody Order order) {\n        BaseResult baseResult = orderService.deleteService(order);\n        return baseResult;\n    }\n\n    /**\n     * 取消订单\n     *\n     * @param order 订单\n     * @return\n     */\n    @PostMapping(\"cancelOrder\")\n    @ApiOperation(value = \"取消订单\")\n    public BaseResult cancelOrder(@RequestBody Order order) {\n        BaseResult baseResult = orderService.cancelService(order);\n        return baseResult;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/domain/ESItem.java",
    "content": "package com.yuu.ymall.web.api.domain;\n\nimport org.springframework.data.annotation.Id;\nimport org.springframework.data.elasticsearch.annotations.Document;\nimport org.springframework.data.elasticsearch.annotations.Field;\nimport org.springframework.data.elasticsearch.annotations.FieldType;\n\n/**\n * Elasticsearch 对应实体类\n *\n * @author by Yuu\n * @classname ESItem\n * @date 2019/6/29 21:39\n */\n@Document(indexName = \"item\", type = \"itemList\", shards = 1, replicas = 0)\npublic class ESItem {\n    /**\n     * 商品 ID\n     */\n    @Id\n    private Long id;\n\n    /**\n     * 商品名称\n     */\n    @Field(type = FieldType.text, analyzer = \"ik_max_word\")\n    private String productName;\n\n    /**\n     * 商品副标题\n     */\n    @Field(type = FieldType.text, analyzer = \"ik_max_word\")\n    private String subTitle;\n\n    /**\n     * 商品 id\n     */\n    @Field(type = FieldType.Long)\n    private Long productId;\n\n    /**\n     * 分类 id\n     */\n    @Field(type = FieldType.Long)\n    private Long cid;\n\n    /**\n     * 商品售价\n     */\n    @Field(type = FieldType.Double)\n    private Double salePrice;\n\n    /**\n     * 商品大图 1 张\n     */\n    @Field(type = FieldType.keyword)\n    private String picUrl;\n\n    /**\n     * 商品销量\n     */\n    @Field(type = FieldType.Integer)\n    private Integer orderNum;\n\n    /**\n     * 商品限制购买数量\n     */\n    @Field(type = FieldType.Integer)\n    private Integer limit;\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getProductName() {\n        return productName;\n    }\n\n    public void setProductName(String productName) {\n        this.productName = productName;\n    }\n\n    public String getSubTitle() {\n        return subTitle;\n    }\n\n    public void setSubTitle(String subTitle) {\n        this.subTitle = subTitle;\n    }\n\n    public Long getProductId() {\n        return productId;\n    }\n\n    public void setProductId(Long productId) {\n        this.productId = productId;\n    }\n\n    public Long getCid() {\n        return cid;\n    }\n\n    public void setCid(Long cid) {\n        this.cid = cid;\n    }\n\n    public Double getSalePrice() {\n        return salePrice;\n    }\n\n    public void setSalePrice(Double salePrice) {\n        this.salePrice = salePrice;\n    }\n\n    public String getPicUrl() {\n        return picUrl;\n    }\n\n    public void setPicUrl(String picUrl) {\n        this.picUrl = picUrl;\n    }\n\n    public Integer getOrderNum() {\n        return orderNum;\n    }\n\n    public void setOrderNum(Integer orderNum) {\n        this.orderNum = orderNum;\n    }\n\n    public Integer getLimit() {\n        return limit;\n    }\n\n    public void setLimit(Integer limit) {\n        this.limit = limit;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/Cart.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\n\n/**\n * 购物车\n *\n * @author by Yuu\n * @classname Cart\n * @date 2019/7/3 9:10\n */\npublic class Cart implements Serializable {\n\n    /**\n     * 用户 id\n     */\n    private Long userId;\n\n    /**\n     * 商品 id\n     */\n    private Long productId;\n\n    /**\n     * 是否选中\n     */\n    private String checked;\n\n    /**\n     * 商品数量\n     */\n    private int productNum;\n\n    public Long getUserId() {\n        return userId;\n    }\n\n    public void setUserId(Long userId) {\n        this.userId = userId;\n    }\n\n    public Long getProductId() {\n        return productId;\n    }\n\n    public void setProductId(Long productId) {\n        this.productId = productId;\n    }\n\n    public String getChecked() {\n        return checked;\n    }\n\n    public void setChecked(String checked) {\n        this.checked = checked;\n    }\n\n    public int getProductNum() {\n        return productNum;\n    }\n\n    public void setProductNum(int productNum) {\n        this.productNum = productNum;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/CartProduct.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\n\n/**\n * 购物车商品\n *\n * @author by Yuu\n * @classname CartProduct\n * @date 2019/7/3 10:08\n */\npublic class CartProduct implements Serializable {\n\n    /**\n     * 商品 id\n     */\n    private Long productId;\n\n    /**\n     * 商品售价\n     */\n    private BigDecimal salePrice;\n\n    /**\n     * 商品数量\n     */\n    private int productNum;\n\n    /**\n     * 商品限制购买数量\n     */\n    private int limitNum;\n\n    /**\n     * 商品是否被选中\n     */\n    private String checked;\n\n    /**\n     * 商品名称\n     */\n    private String productName;\n\n    /**\n     * 商品图片地址\n     */\n    private String productImg;\n\n    public Long getProductId() {\n        return productId;\n    }\n\n    public void setProductId(Long productId) {\n        this.productId = productId;\n    }\n\n    public BigDecimal getSalePrice() {\n        return salePrice;\n    }\n\n    public void setSalePrice(BigDecimal salePrice) {\n        this.salePrice = salePrice;\n    }\n\n    public int getProductNum() {\n        return productNum;\n    }\n\n    public void setProductNum(int productNum) {\n        this.productNum = productNum;\n    }\n\n    public int getLimitNum() {\n        return limitNum;\n    }\n\n    public void setLimitNum(int limitNum) {\n        this.limitNum = limitNum;\n    }\n\n    public String getChecked() {\n        return checked;\n    }\n\n    public void setChecked(String checked) {\n        this.checked = checked;\n    }\n\n    public String getProductName() {\n        return productName;\n    }\n\n    public void setProductName(String productName) {\n        this.productName = productName;\n    }\n\n    public String getProductImg() {\n        return productImg;\n    }\n\n    public void setProductImg(String productImg) {\n        this.productImg = productImg;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/CateProductsResult.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport com.yuu.ymall.web.api.domain.ESItem;\n\nimport java.util.List;\n\n/**\n * 分类商品查询结果\n *\n * @author by Yuu\n * @classname CateProductsResult\n * @date 2019/7/4 10:28\n */\npublic class CateProductsResult {\n\n    /**\n     * 查询总条数\n     */\n    private long total;\n\n    /**\n     * 商品集合\n     */\n    private List<ESItem> data;\n\n    public long getTotal() {\n        return total;\n    }\n\n    public void setTotal(long total) {\n        this.total = total;\n    }\n\n    public List<ESItem> getData() {\n        return data;\n    }\n\n    public void setData(List<ESItem> data) {\n        this.data = data;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/CategoryProductPageInfo.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\n\n/**\n * 分类商品查询分页信息\n *\n * @author by Yuu\n * @classname ProductPageInfo\n * @date 2019/7/4 10:16\n */\npublic class CategoryProductPageInfo implements Serializable {\n\n    /**\n     * 当前第几页\n     */\n    private Integer page;\n\n    /**\n     * 每页显示的个数\n     */\n    private Integer size;\n\n    /**\n     * 排序条件\n     */\n    private String sort;\n\n    /**\n     * 查询条件\n     */\n    private String key;\n\n    /**\n     * 分类id\n     */\n    private Long cid;\n\n    /**\n     * 最高价格\n     */\n    private Integer priceGt;\n\n    /**\n     * 最低价格\n     */\n    private Integer priceLte;\n\n    public Integer getPage() {\n        return page;\n    }\n\n    public void setPage(Integer page) {\n        this.page = page;\n    }\n\n    public Integer getSize() {\n        return size;\n    }\n\n    public void setSize(Integer size) {\n        this.size = size;\n    }\n\n    public String getSort() {\n        return sort;\n    }\n\n    public void setSort(String sort) {\n        this.sort = sort;\n    }\n\n    public String getKey() {\n        return key;\n    }\n\n    public void setKey(String key) {\n        this.key = key;\n    }\n\n    public Long getCid() {\n        return cid;\n    }\n\n    public void setCid(Long cid) {\n        this.cid = cid;\n    }\n\n    public Integer getPriceGt() {\n        return priceGt;\n    }\n\n    public void setPriceGt(Integer priceGt) {\n        this.priceGt = priceGt;\n    }\n\n    public Integer getPriceLte() {\n        return priceLte;\n    }\n\n    public void setPriceLte(Integer priceLte) {\n        this.priceLte = priceLte;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/EmailCode.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\n/**\n * 邮箱随机验证码\n *\n * @author by Yuu\n * @classname EmailCode\n * @date 2019/6/28 19:40\n */\npublic class EmailCode {\n\n    /**\n     * 邮箱\n     */\n    private String email;\n\n    /**\n     * 随机验证码\n     */\n    private String code;\n\n    public EmailCode(String code) {\n        this.code = code;\n    }\n\n    public EmailCode(String email, String code) {\n        this.email = email;\n        this.code = code;\n    }\n\n    public String getEmail() {\n        return email;\n    }\n\n    public void setEmail(String email) {\n        this.email = email;\n    }\n\n    public String getCode() {\n        return code;\n    }\n\n    public void setCode(String code) {\n        this.code = code;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/Member.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\n\n/**\n * 接受会员操作请求\n *\n * @author by Yuu\n * @classname Member\n * @date 2019/7/8 16:08\n */\npublic class Member implements Serializable {\n\n    /**\n     * 会员 id\n     */\n    private Long userId;\n\n    /**\n     * 会员缓存 token\n     */\n    private String token;\n\n    /**\n     * 会员头像 base64\n     */\n    private String imgData;\n\n    /**\n     * 会员名称\n     */\n    private String username;\n\n    /**\n     * 会员手机号\n     */\n    private String phone;\n\n    /**\n     * 会员密码\n     */\n    private String password;\n\n    /**\n     * 会员邮箱\n     */\n    private String email;\n\n    public Long getUserId() {\n        return userId;\n    }\n\n    public void setUserId(Long userId) {\n        this.userId = userId;\n    }\n\n    public String getToken() {\n        return token;\n    }\n\n    public void setToken(String token) {\n        this.token = token;\n    }\n\n    public String getImgData() {\n        return imgData;\n    }\n\n    public void setImgData(String imgData) {\n        this.imgData = imgData;\n    }\n\n    public String getUsername() {\n        return username;\n    }\n\n    public void setUsername(String username) {\n        this.username = username;\n    }\n\n    public String getPhone() {\n        return phone;\n    }\n\n    public void setPhone(String phone) {\n        this.phone = phone;\n    }\n\n    public String getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n\n    public String getEmail() {\n        return email;\n    }\n\n    public void setEmail(String email) {\n        this.email = email;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/MemberLogin.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\n\n/**\n * 会员接受登录信息类\n *\n * @author by Yuu\n * @classname MemberLogin\n * @date 2019/6/27 9:42\n */\npublic class MemberLogin implements Serializable {\n\n    /**\n     * 账号：手机号或邮箱\n     */\n    private String account;\n\n    /**\n     * 邮箱\n     */\n    private String password;\n\n    /**\n     * 是否自动登录，否 账号信息存 session， 是 账号信息存 Redis Session\n     */\n    private Boolean auto;\n\n    public String getAccount() {\n        return account;\n    }\n\n    public void setAccount(String account) {\n        this.account = account;\n    }\n\n    public String getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n\n    public Boolean getAuto() {\n        return auto;\n    }\n\n    public void setAuto(Boolean auto) {\n        this.auto = auto;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/Order.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport com.yuu.ymall.domain.TbAddress;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\nimport java.util.List;\n\n/**\n * 订单详情\n *\n * @author by Yuu\n * @classname Order\n * @date 2019/7/6 12:10\n */\npublic class Order implements Serializable {\n\n    /**\n     * 订单id\n     */\n    private String orderId;\n\n    /**\n     * 订单所属会员 id\n     */\n    private String userId;\n\n    /**\n     * 订单总计\n     */\n    private BigDecimal orderTotal;\n\n    /**\n     * 订单地址信息\n     */\n    private TbAddress tbAddress;\n\n    /**\n     * 订单商品集合\n     */\n    private List<CartProduct> goodsList;\n\n    /**\n     * 订单状态\n     */\n    private Integer orderStatus;\n\n    /**\n     * 订单创建时间\n     */\n    private String createDate;\n\n    /**\n     * 订单发货时间\n     */\n    private String consignDate;\n\n    /**\n     * 订单关闭时间\n     */\n    private String closeDate;\n\n    /**\n     * 订单完成时间\n     */\n    private String finishDate;\n\n    /**\n     * 订单支付时间\n     */\n    private String payDate;\n\n    /**\n     * 最晚支付时间\n     */\n    private String countTime;\n\n    /**\n     * 订单物流名称\n     */\n    private String shippingName;\n\n    /**\n     * 订单物流单号\n     */\n    private String shippingCode;\n\n    public String getOrderId() {\n        return orderId;\n    }\n\n    public void setOrderId(String orderId) {\n        this.orderId = orderId;\n    }\n\n    public String getUserId() {\n        return userId;\n    }\n\n    public void setUserId(String userId) {\n        this.userId = userId;\n    }\n\n    public BigDecimal getOrderTotal() {\n        return orderTotal;\n    }\n\n    public void setOrderTotal(BigDecimal orderTotal) {\n        this.orderTotal = orderTotal;\n    }\n\n    public TbAddress getTbAddress() {\n        return tbAddress;\n    }\n\n    public void setTbAddress(TbAddress tbAddress) {\n        this.tbAddress = tbAddress;\n    }\n\n    public List<CartProduct> getGoodsList() {\n        return goodsList;\n    }\n\n    public void setGoodsList(List<CartProduct> goodsList) {\n        this.goodsList = goodsList;\n    }\n\n    public Integer getOrderStatus() {\n        return orderStatus;\n    }\n\n    public void setOrderStatus(Integer orderStatus) {\n        this.orderStatus = orderStatus;\n    }\n\n    public String getCreateDate() {\n        return createDate;\n    }\n\n    public void setCreateDate(String createDate) {\n        this.createDate = createDate;\n    }\n\n    public String getConsignDate() {\n        return consignDate;\n    }\n\n    public void setConsignDate(String consignDate) {\n        this.consignDate = consignDate;\n    }\n\n    public String getCloseDate() {\n        return closeDate;\n    }\n\n    public void setCloseDate(String closeDate) {\n        this.closeDate = closeDate;\n    }\n\n    public String getFinishDate() {\n        return finishDate;\n    }\n\n    public void setFinishDate(String finishDate) {\n        this.finishDate = finishDate;\n    }\n\n    public String getPayDate() {\n        return payDate;\n    }\n\n    public void setPayDate(String payDate) {\n        this.payDate = payDate;\n    }\n\n    public String getCountTime() {\n        return countTime;\n    }\n\n    public void setCountTime(String countTime) {\n        this.countTime = countTime;\n    }\n\n    public String getShippingName() {\n        return shippingName;\n    }\n\n    public void setShippingName(String shippingName) {\n        this.shippingName = shippingName;\n    }\n\n    public String getShippingCode() {\n        return shippingCode;\n    }\n\n    public void setShippingCode(String shippingCode) {\n        this.shippingCode = shippingCode;\n    }\n}\n\n\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/OrderInfo.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\nimport java.util.List;\n\n/**\n * 接受订单信息\n *\n * @author by Yuu\n * @classname OrderInfo\n * @date 2019/7/6 2:05\n */\npublic class OrderInfo implements Serializable {\n\n    /**\n     * 会员 id\n     */\n    private Long userId;\n\n    /**\n     * 地址 id\n     */\n    private Long addressId;\n\n    /**\n     * 电话\n     */\n    private String tel;\n\n    /**\n     * 收货人\n     */\n    private String userName;\n\n    /**\n     * 详细地址\n     */\n    private String streetName;\n\n    /**\n     * 订单总计\n     */\n    private BigDecimal orderTotal;\n\n    /**\n     * 订单商品\n     */\n    private List<CartProduct> goodsList;\n\n    public Long getUserId() {\n        return userId;\n    }\n\n    public void setUserId(Long userId) {\n        this.userId = userId;\n    }\n\n    public Long getAddressId() {\n        return addressId;\n    }\n\n    public void setAddressId(Long addressId) {\n        this.addressId = addressId;\n    }\n\n    public String getTel() {\n        return tel;\n    }\n\n    public void setTel(String tel) {\n        this.tel = tel;\n    }\n\n    public String getUserName() {\n        return userName;\n    }\n\n    public void setUserName(String userName) {\n        this.userName = userName;\n    }\n\n    public String getStreetName() {\n        return streetName;\n    }\n\n    public void setStreetName(String streetName) {\n        this.streetName = streetName;\n    }\n\n    public BigDecimal getOrderTotal() {\n        return orderTotal;\n    }\n\n    public void setOrderTotal(BigDecimal orderTotal) {\n        this.orderTotal = orderTotal;\n    }\n\n    public List<CartProduct> getGoodsList() {\n        return goodsList;\n    }\n\n    public void setGoodsList(List<CartProduct> goodsList) {\n        this.goodsList = goodsList;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/OrderPay.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\n\n/**\n * 订单支付接受请求\n *\n * @author by Yuu\n * @classname OrderPay\n * @date 2019/7/6 15:55\n */\npublic class OrderPay implements Serializable {\n\n    /**\n     * 订单 id\n     */\n    private Long orderId;\n\n    /**\n     * 订单支付总金额\n     */\n    private BigDecimal orderTotal;\n\n    /**\n     * 订单支付状态\n     */\n    private String orderStatus;\n\n    public Long getOrderId() {\n        return orderId;\n    }\n\n    public void setOrderId(Long orderId) {\n        this.orderId = orderId;\n    }\n\n    public BigDecimal getOrderTotal() {\n        return orderTotal;\n    }\n\n    public void setOrderTotal(BigDecimal orderTotal) {\n        this.orderTotal = orderTotal;\n    }\n\n    public String getOrderStatus() {\n        return orderStatus;\n    }\n\n    public void setOrderStatus(String orderStatus) {\n        this.orderStatus = orderStatus;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/PageOrder.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * 订单分页信息\n *\n * @author by Yuu\n * @classname PageOrder\n * @date 2019/7/8 0:32\n */\npublic class PageOrder implements Serializable {\n\n    /**\n     * 总条数\n     */\n    private int total;\n\n    /**\n     * 分页数据\n     */\n    private List<Order> data;\n\n    public int getTotal() {\n        return total;\n    }\n\n    public void setTotal(int total) {\n        this.total = total;\n    }\n\n    public List<Order> getData() {\n        return data;\n    }\n\n    public void setData(List<Order> data) {\n        this.data = data;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/ProductDet.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\n\n/**\n * 商品详情\n *\n * @author by Yuu\n * @classname ProductDet\n * @date 2019/7/3 19:03\n */\npublic class ProductDet implements Serializable {\n\n    /**\n     * 商品 id\n     */\n    private Long productId;\n\n    /**\n     * 商品售价\n     */\n    private BigDecimal salePrice;\n\n    /**\n     * 商品名称\n     */\n    private String productName;\n\n    /**\n     * 商品子标题\n     */\n    private String subTitle;\n\n    /**\n     * 商品限制数量\n     */\n    private Integer limitNum;\n\n    /**\n     * 商品库存数量\n     */\n    private Integer num;\n\n    /**\n     * 商品详情\n     */\n    private String detail;\n\n    /**\n     * 商品大图\n     */\n    private String productImageBig;\n\n    /**\n     * 商品小图集合\n     */\n    private String[] productImageSmall;\n\n    public Long getProductId() {\n        return productId;\n    }\n\n    public void setProductId(Long productId) {\n        this.productId = productId;\n    }\n\n    public BigDecimal getSalePrice() {\n        return salePrice;\n    }\n\n    public void setSalePrice(BigDecimal salePrice) {\n        this.salePrice = salePrice;\n    }\n\n    public String getProductName() {\n        return productName;\n    }\n\n    public void setProductName(String productName) {\n        this.productName = productName;\n    }\n\n    public String getSubTitle() {\n        return subTitle;\n    }\n\n    public void setSubTitle(String subTitle) {\n        this.subTitle = subTitle;\n    }\n\n    public Integer getLimitNum() {\n        return limitNum;\n    }\n\n    public Integer getNum() {\n        return num;\n    }\n\n    public void setNum(Integer num) {\n        this.num = num;\n    }\n\n    public void setLimitNum(Integer limitNum) {\n        this.limitNum = limitNum;\n    }\n\n    public String getDetail() {\n        return detail;\n    }\n\n    public void setDetail(String detail) {\n        this.detail = detail;\n    }\n\n    public String getProductImageBig() {\n        return productImageBig;\n    }\n\n    public void setProductImageBig(String productImageBig) {\n        this.productImageBig = productImageBig;\n    }\n\n    public String[] getProductImageSmall() {\n        return productImageSmall;\n    }\n\n    public void setProductImageSmall(String[] productImageSmall) {\n        this.productImageSmall = productImageSmall;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/TbCate.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * @author by Yuu\n * @classname TbCate\n * @date 2019/7/2 10:23\n */\npublic class TbCate implements Serializable {\n    /**\n     * 分类 id\n     */\n    private Long id;\n\n    /**\n     * 分类名称\n     */\n    private String name;\n\n    /**\n     * 分类的子分类\n     */\n    private List<TbCate> catesons;\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public List<TbCate> getCatesons() {\n        return catesons;\n    }\n\n    public void setCatesons(List<TbCate> catesons) {\n        this.catesons = catesons;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/TbPanelContentDto.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\nimport java.math.BigDecimal;\n\n/**\n * 板块内容数据传输对象\n *\n * @author by Yuu\n * @classname TbPanelContentDto\n * @date 2019/7/2 14:56\n */\npublic class TbPanelContentDto implements Serializable {\n\n    /**\n     * 板块内容 id\n     */\n    private Long id;\n\n    /**\n     * 板块内容类型，0 关联商品 1 其他链接\n     */\n    private Integer type;\n\n    /**\n     * 类型为其他链接的跳转地址\n     */\n    private String fullUrl;\n\n    /**\n     * 板块内容图片\n     */\n    private String picUrl;\n\n    /**\n     * 轮播图备用图片1\n     */\n    private String picUrl2;\n\n    /**\n     * 轮播图备用图片2\n     */\n    private String picUrl3;\n\n\n    /**\n     * 关联商品 id\n     */\n    private Long productId;\n\n    /**\n     * 关联商品售价\n     */\n    private BigDecimal salePrice;\n\n    /**\n     * 关联商品商品名称\n     */\n    private String productName;\n\n    /**\n     * 关联商品副标题\n     */\n    private String subTitle;\n\n    /**\n     * 商品限制购买数量\n     */\n    private int limit;\n\n    public Long getId() {\n        return id;\n    }\n\n    public void setId(Long id) {\n        this.id = id;\n    }\n\n    public Integer getType() {\n        return type;\n    }\n\n    public void setType(Integer type) {\n        this.type = type;\n    }\n\n    public String getFullUrl() {\n        return fullUrl;\n    }\n\n    public void setFullUrl(String fullUrl) {\n        this.fullUrl = fullUrl;\n    }\n\n    public String getPicUrl() {\n        return picUrl;\n    }\n\n    public void setPicUrl(String picUrl) {\n        this.picUrl = picUrl;\n    }\n\n    public String getPicUrl2() {\n        return picUrl2;\n    }\n\n    public void setPicUrl2(String picUrl2) {\n        this.picUrl2 = picUrl2;\n    }\n\n    public String getPicUrl3() {\n        return picUrl3;\n    }\n\n    public void setPicUrl3(String picUrl3) {\n        this.picUrl3 = picUrl3;\n    }\n\n    public Long getProductId() {\n        return productId;\n    }\n\n    public void setProductId(Long productId) {\n        this.productId = productId;\n    }\n\n    public BigDecimal getSalePrice() {\n        return salePrice;\n    }\n\n    public void setSalePrice(BigDecimal salePrice) {\n        this.salePrice = salePrice;\n    }\n\n    public String getProductName() {\n        return productName;\n    }\n\n    public void setProductName(String productName) {\n        this.productName = productName;\n    }\n\n    public String getSubTitle() {\n        return subTitle;\n    }\n\n    public void setSubTitle(String subTitle) {\n        this.subTitle = subTitle;\n    }\n\n    public int getLimit() {\n        return limit;\n    }\n\n    public void setLimit(int limit) {\n        this.limit = limit;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/TbPanelDto.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * 首页板块展示对象\n *\n * @author by Yuu\n * @classname TbPanelDto\n * @date 2019/7/2 13:57\n */\npublic class TbPanelDto implements Serializable {\n\n    /**\n     * 板块 id\n     */\n    private Integer id;\n\n    /**\n     * 板块名称\n     */\n    private String name;\n\n    /**\n     * 板块类型 0 轮播图 1 板块种类一 2 板块种类二 3 板块种类三\n     */\n    private Integer type;\n\n    /**\n     * 板块内容集合\n     */\n    private List<TbPanelContentDto> panelContentDtos;\n\n    public Integer getId() {\n        return id;\n    }\n\n    public void setId(Integer id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public Integer getType() {\n        return type;\n    }\n\n    public void setType(Integer type) {\n        this.type = type;\n    }\n\n    public List<TbPanelContentDto> getPanelContentDtos() {\n        return panelContentDtos;\n    }\n\n    public void setPanelContentDtos(List<TbPanelContentDto> panelContentDtos) {\n        this.panelContentDtos = panelContentDtos;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/dto/UploadImg.java",
    "content": "package com.yuu.ymall.web.api.dto;\n\nimport java.io.Serializable;\n\n/**\n * 头像上传接受请求对象\n *\n * @author by Yuu\n * @classname UploadImg\n * @date 2019/7/8 13:48\n */\npublic class UploadImg implements Serializable {\n\n    /**\n     * 会员 id\n     */\n    private Long userId;\n\n    /**\n     * 头像 base64 数据\n     */\n    private String imgData;\n\n    /**\n     * 会员缓存 token\n     */\n    private String token;\n\n    public Long getUserId() {\n        return userId;\n    }\n\n    public void setUserId(Long userId) {\n        this.userId = userId;\n    }\n\n    public String getImgData() {\n        return imgData;\n    }\n\n    public void setImgData(String imgData) {\n        this.imgData = imgData;\n    }\n\n    public String getToken() {\n        return token;\n    }\n\n    public void setToken(String token) {\n        this.token = token;\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/job/OrderCloseJob.java",
    "content": "package com.yuu.ymall.web.api.job;\n\nimport com.alipay.api.AlipayApiException;\nimport com.alipay.api.AlipayClient;\nimport com.alipay.api.DefaultAlipayClient;\nimport com.alipay.api.request.AlipayTradeCancelRequest;\nimport com.alipay.api.response.AlipayTradeCancelResponse;\nimport com.yuu.ymall.commons.consts.Consts;\nimport com.yuu.ymall.web.api.common.config.AlipayConfig;\nimport com.yuu.ymall.web.api.mapper.TbOrderMapper;\nimport org.quartz.Job;\nimport org.quartz.JobExecutionContext;\nimport org.quartz.JobExecutionException;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.web.context.support.SpringBeanAutowiringSupport;\n\nimport java.util.List;\n\n/**\n * 订单超时关闭任务\n *\n * @author by Yuu\n * @classname OrderCloseJob\n * @date 2019/7/7 12:25\n */\npublic class OrderCloseJob implements Job {\n\n    @Autowired\n    private TbOrderMapper tbOrderMapper;\n\n    @Override\n    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {\n        SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);\n\n        // 查询出所有已超时的订单\n        List<String> tbOrderIds = tbOrderMapper.selectOrderOutTime();\n\n        // 更新订单状态\n        for (String tbOrderId : tbOrderIds) {\n            // 更新数据库订单状态\n            tbOrderMapper.updateOrderStatus(tbOrderId, Consts.ORDER_STATUS_CLOSE);\n            // 更新关闭时间和状态\n            tbOrderMapper.updateCloseTimeAndStatus(tbOrderId);\n            // 通知支付宝订单关闭\n            AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl,AlipayConfig.app_id,AlipayConfig.merchant_private_key,\"json\",AlipayConfig.charset,AlipayConfig.alipay_public_key,AlipayConfig.sign_type);\n            AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();\n            request.setBizContent(\"{\" +\n                    \"\\\"out_trade_no\\\":\\\"\"+ tbOrderId +\"\\\",\" +\n                    \"\\\"trade_no\\\":\\\"\\\"\" +\n                    \"  }\");\n            AlipayTradeCancelResponse response = null;\n            try {\n                response = alipayClient.execute(request);\n            } catch (AlipayApiException e) {\n                e.printStackTrace();\n            }\n        }\n\n    }\n}\n\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbAddressMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbAddress;\n\nimport java.util.List;\n\npublic interface TbAddressMapper {\n    int deleteByPrimaryKey(Long id);\n\n    int insert(TbAddress record);\n\n    TbAddress selectByPrimaryKey(Long id);\n\n    List<TbAddress> selectAll();\n\n    int updateByPrimaryKey(TbAddress record);\n\n    /**\n     * 获取会员地址列表\n     *\n     * @param userId 会员 id\n     * @return\n     */\n    List<TbAddress> selectByUserId(Long userId);\n\n    /**\n     * 会员修改地址\n     *\n     * @param tbAddress 会员地址\n     */\n    int updateAddress(TbAddress tbAddress);\n\n    /**\n     * 移除默认地址\n     *\n     * @param userId 用户地址\n     */\n    int removeDefault(Long userId);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbExpressMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbExpress;\n\nimport java.util.List;\n\npublic interface TbExpressMapper {\n    int deleteByPrimaryKey(Integer id);\n\n    int insert(TbExpress record);\n\n    TbExpress selectByPrimaryKey(Integer id);\n\n    List<TbExpress> selectAll();\n\n    int updateByPrimaryKey(TbExpress record);\n}"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbItemCatMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbItemCat;\n\nimport java.util.List;\n\npublic interface TbItemCatMapper {\n    int deleteByPrimaryKey(Long id);\n\n    int insert(TbItemCat record);\n\n    TbItemCat selectByPrimaryKey(Long id);\n\n    List<TbItemCat> selectAll();\n\n    int updateByPrimaryKey(TbItemCat record);\n\n    /**\n     * 根据分级分类，获取子分类\n     *\n     * @param id 分类 id\n     * @return\n     */\n    List<TbItemCat> selectTbCatByPid(Long id);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbItemDescMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbItemDesc;\n\nimport java.util.List;\n\npublic interface TbItemDescMapper {\n    int deleteByPrimaryKey(Long itemId);\n\n    int insert(TbItemDesc record);\n\n    TbItemDesc selectByPrimaryKey(Long itemId);\n\n    List<TbItemDesc> selectAll();\n\n    int updateByPrimaryKey(TbItemDesc record);\n}"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbItemMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbItem;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\npublic interface TbItemMapper {\n    int deleteByPrimaryKey(Long id);\n\n    int insert(TbItem record);\n\n    TbItem selectByPrimaryKey(Long id);\n\n    List<TbItem> selectAll();\n\n    int updateByPrimaryKey(TbItem record);\n\n    /**\n     * 商品减少库存\n     *\n     * @param productId 商品 id\n     * @param num 商品数量\n     * @return\n     */\n    int reduceItemNum(@Param(\"productId\") Long productId, @Param(\"num\") int num);\n\n    /**\n     * 商品库存 +1\n     *\n     * @param productId 商品 id\n     * @param num 商品数量\n     * @return\n     */\n    int addItemNum(@Param(\"productId\") String productId, @Param(\"num\") int num);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbMemberMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbMember;\nimport org.apache.ibatis.annotations.Param;\n\nimport java.util.List;\n\npublic interface TbMemberMapper {\n    int deleteByPrimaryKey(Long id);\n\n    int insert(TbMember record);\n\n    TbMember selectByPrimaryKey(Long id);\n\n    List<TbMember> selectAll();\n\n    int updateByPrimaryKey(TbMember record);\n\n    /**\n     * 根据手机号查询会员\n     *\n     * @param phone 手机号\n     * @return\n     */\n    TbMember selectByPhone(String phone);\n\n    /**\n     * 会员注册\n     *\n     * @param tbMember 会员\n     */\n    void register(TbMember tbMember);\n\n    /**\n     * 根据邮箱查询会员\n     *\n     * @param email 邮箱\n     * @return\n     */\n    TbMember selectByEmail(String email);\n\n    /**\n     * 根据手机号或者邮箱查询会员\n     *\n     * @param account 手机号或邮箱\n     * @return\n     */\n    TbMember selectByPhoneOrEmail(String account);\n\n    /**\n     * 会员修改密码\n     *\n     * @param account 手机号或邮箱\n     * @param password 密码\n     * @return\n     */\n    Integer updatePassword(@Param(\"account\") String account, @Param(\"password\") String password);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbOrderItemMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbOrderItem;\n\nimport java.util.List;\n\npublic interface TbOrderItemMapper {\n    int deleteByPrimaryKey(String id);\n\n    int insert(TbOrderItem record);\n\n    TbOrderItem selectByPrimaryKey(String id);\n\n    List<TbOrderItem> selectAll();\n\n    int updateByPrimaryKey(TbOrderItem record);\n\n    /**\n     * 根据订单id，查询订单商品\n     *\n     * @param id 订单 id\n     * @return\n     */\n    List<TbOrderItem> selectByOrderId(String orderId);\n\n    /**\n     * 根据订单删除订单商品\n     *\n     * @param orderId 订单 id\n     * @return\n     */\n    int deleteByOrderId(String orderId);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbOrderMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbOrder;\nimport org.apache.ibatis.annotations.Param;\nimport org.springframework.stereotype.Repository;\n\nimport java.util.List;\n\n@Repository\npublic interface TbOrderMapper {\n    int deleteByPrimaryKey(String id);\n\n    int insert(TbOrder record);\n\n    TbOrder selectByPrimaryKey(String id);\n\n    List<TbOrder> selectAll();\n\n    int updateByPrimaryKey(TbOrder record);\n\n    /**\n     * 修改订单状态\n     *\n     * @param orderId 订单 id\n     * @param orderStatus 订单 状态\n     * @return\n     */\n    int updateOrderStatus(@Param(\"orderId\") String orderId, @Param(\"orderStatus\") Integer orderStatus);\n\n    /**\n     * 查询订单超时的订单\n     *\n     * @return\n     */\n    List<String> selectOrderOutTime();\n\n    /**\n     * 获取会员订单列表\n     *\n     * @param userId 会员 id\n     * @return\n     */\n    List<TbOrder> selectByUserId(String userId);\n\n    /**\n     * 获取会员订单总数\n     *\n     * @param userId 会员 id\n     * @return\n     */\n    int getMemberOrderCount(String userId);\n\n    /**\n     * 获取会员的订单信息\n     *\n     * @param userId 会员 id\n     * @param orderId 订单 id\n     * @return\n     */\n    TbOrder selectByUserIdAndOrderId(@Param(\"userId\") String userId, @Param(\"orderId\") String orderId);\n\n    /**\n     * 支付成功，修改支付时间和状态\n     *\n     * @param orderId 订单 id\n     * @return\n     */\n    int updatePayTimeAndStatus(String orderId);\n\n    /**\n     * 支付失败，修改关闭时间和状态\n     *\n     * @param tbOrderId 订单 id\n     * @return\n     */\n    int updateCloseTimeAndStatus(String tbOrderId);\n\n    /**\n     * 取消订单\n     *\n     * @param orderId 订单 id\n     * @return\n     */\n    int cancelOrder(String orderId);\n\n    /**\n     * 确认收货\n     *\n     * @param orderId 订单 id\n     * @return\n     */\n    int confirmReceipt(String orderId);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbOrderShippingMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbOrderShipping;\n\nimport java.util.List;\n\npublic interface TbOrderShippingMapper {\n    int deleteByPrimaryKey(String orderId);\n\n    int insert(TbOrderShipping record);\n\n    TbOrderShipping selectByPrimaryKey(String orderId);\n\n    List<TbOrderShipping> selectAll();\n\n    int updateByPrimaryKey(TbOrderShipping record);\n}"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbPanelContentMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbPanelContent;\nimport com.yuu.ymall.web.api.dto.TbPanelContentDto;\n\nimport java.util.List;\n\npublic interface TbPanelContentMapper {\n    int deleteByPrimaryKey(Integer id);\n\n    int insert(TbPanelContent record);\n\n    TbPanelContent selectByPrimaryKey(Integer id);\n\n    List<TbPanelContent> selectAll();\n\n    int updateByPrimaryKey(TbPanelContent record);\n\n    /**\n     * 根据板块 id, 获取板块内容\n     *\n     * @param id 板块 id\n     * @return\n     */\n    List<TbPanelContentDto> selectContentByPid(Integer id);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbPanelMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbPanel;\nimport com.yuu.ymall.web.api.dto.TbPanelDto;\n\nimport java.util.List;\n\npublic interface TbPanelMapper {\n    int deleteByPrimaryKey(Integer id);\n\n    int insert(TbPanel record);\n\n    TbPanel selectByPrimaryKey(Integer id);\n\n    List<TbPanelDto> selectAll();\n\n    int updateByPrimaryKey(TbPanel record);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/mapper/TbUserMapper.java",
    "content": "package com.yuu.ymall.web.api.mapper;\n\nimport com.yuu.ymall.domain.TbUser;\n\nimport java.util.List;\n\npublic interface TbUserMapper {\n    int deleteByPrimaryKey(Long id);\n\n    int insert(TbUser record);\n\n    TbUser selectByPrimaryKey(Long id);\n\n    List<TbUser> selectAll();\n\n    int updateByPrimaryKey(TbUser record);\n}"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/repositories/ItemRepository.java",
    "content": "package com.yuu.ymall.web.api.repositories;\n\nimport com.yuu.ymall.web.api.domain.ESItem;\nimport org.springframework.data.elasticsearch.repository.ElasticsearchRepository;\n\n/**\n * @author by Yuu\n * @classname ItemRepository\n * @date 2019/6/30 13:12\n */\npublic interface ItemRepository extends ElasticsearchRepository<ESItem, Long> {\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/CartService.java",
    "content": "package com.yuu.ymall.web.api.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.web.api.dto.Cart;\n\n/**\n * @author by Yuu\n * @classname CartService\n * @date 2019/7/3 9:13\n */\npublic interface CartService {\n\n    /**\n     * 购物车添加商品\n     *\n     * @param cart 购物车\n     * @return\n     */\n    BaseResult addProduct(Cart cart);\n\n    /**\n     * 获取购物车列表\n     *\n     * @param userId 会员 id\n     * @return\n     */\n    BaseResult getCartList(Long userId);\n\n    /**\n     * 购物车删除商品\n     *\n     * @param cart 购物车\n     * @return\n     */\n    BaseResult delProduct(Cart cart);\n\n    /**\n     * 修改购物车商品\n     *\n     * @param cart 购物车商品\n     * @return\n     */\n    BaseResult editProduct(Cart cart);\n\n    /**\n     * 全选购物车\n     *\n     * @param cart 购物车\n     * @return\n     */\n    BaseResult editCheckAll(Cart cart);\n\n    /**\n     * 删除购物车已选商品\n     *\n     * @param cart 购物车\n     * @return\n     */\n    BaseResult delCartChecked(Cart cart);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/ContentService.java",
    "content": "package com.yuu.ymall.web.api.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\n\n/**\n * @author by Yuu\n * @classname ContentService\n * @date 2019/7/2 13:51\n */\npublic interface ContentService {\n\n    /**\n     * 获取首页板块内容\n     *\n     * @return\n     */\n    BaseResult getHome();\n\n    /**\n     * 获取推荐商品\n     *\n     * @return\n     */\n    BaseResult getRecommendGoods();\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/ItemCatService.java",
    "content": "package com.yuu.ymall.web.api.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\n\n/**\n * @author by Yuu\n * @classname ItemCatService\n * @date 2019/7/2 10:12\n */\npublic interface ItemCatService {\n\n    /**\n     * 获取分类列表\n     *\n     * @return\n     */\n    BaseResult getCateList();\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/MemberService.java",
    "content": "package com.yuu.ymall.web.api.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.domain.TbAddress;\nimport com.yuu.ymall.domain.TbMember;\nimport com.yuu.ymall.web.api.dto.Member;\nimport com.yuu.ymall.web.api.dto.MemberLogin;\n\nimport javax.servlet.http.HttpSession;\n\n/**\n * 会员服务提供者\n *\n * @author by Yuu\n * @classname MemberService\n * @date 2019/6/24 9:04\n */\npublic interface MemberService {\n\n    /**\n     * 验证手机号是否存在\n     *\n     * @param phone\n     * @return\n     */\n    BaseResult checkPhone(String phone);\n\n    /**\n     * 发送短信\n     *\n     * @param phone 手机号\n     * @return\n     */\n    BaseResult sendSms(String phone);\n\n    /**\n     * 会员注册\n     *\n     * @param tbMember 会员\n     * @return\n     */\n    BaseResult register(TbMember tbMember);\n\n    /**\n     * 会员登录\n     *\n     * @param memberLogin 会员登录信息\n     * @param session 会话信息\n     * @return\n     */\n    BaseResult login(MemberLogin memberLogin, HttpSession session);\n\n    /**\n     * 判断缓存中是否有登录信息\n     *\n     * @param token 令牌\n     * @return\n     */\n    BaseResult getMemberByToken(String token);\n\n    /**\n     * 从 Redis 中退出登录\n     *\n     * @param token 会员本地保存的 token\n     * @return\n     */\n    BaseResult logout(String token);\n\n    /**\n     * 验证手机号或邮箱是否存在\n     *\n     * @param account 手机号或邮箱\n     * @return\n     */\n    BaseResult checkAccount(String account);\n\n    /**\n     * 会员修改密码\n     *\n     * @param memberLogin 会员信息\n     * @return\n     */\n    BaseResult updatePassword(MemberLogin memberLogin);\n\n    /**\n     * 发送验证码\n     *\n     * @param account 手机号或邮箱\n     * @return\n     */\n    BaseResult sendVerCode(String account);\n\n    /**\n     * 获取会员地址列表\n     *\n     * @param userId 会员id\n     * @return\n     */\n    BaseResult getAddressList(Long userId);\n\n    /**\n     * 修改会员地址\n     *\n     * @param tbAddress 会员地址\n     * @return\n     */\n    BaseResult updateAddress(TbAddress tbAddress);\n\n    /**\n     * 新增会员地址\n     *\n     * @param tbAddress 会员地址\n     * @return\n     */\n    BaseResult addAdderss(TbAddress tbAddress);\n\n    /**\n     * 删除会员地址\n     *\n     * @param id 会员地址 id\n     * @return\n     */\n    BaseResult delAddress(Long id);\n\n    /**\n     * 会员修改头像\n     *\n     * @param member 会员请求数据\n     * @return\n     */\n    BaseResult uploadImg(Member member);\n\n    /**\n     * 修改会员昵称\n     *\n     * @param member 会员请求数据\n     * @return\n     */\n    BaseResult updateUsername(Member member);\n\n    /**\n     * 修改会员手机号\n     *\n     * @param member 会员请求数据\n     * @return\n     */\n    BaseResult updatePhone(Member member);\n\n    /**\n     * 个人中心修改密码\n     *\n     * @param member 会员请求数据\n     * @return\n     */\n    BaseResult updatePass(Member member);\n\n    /**\n     * 发送 email 邮件\n     *\n     * @param email 邮箱\n     * @return\n     */\n    BaseResult sendEmailCode(String email);\n\n    /**\n     * 验证邮箱是否存在\n     *\n     * @param email 邮箱\n     * @return\n     */\n    BaseResult checkEmail(String email);\n\n    /**\n     * 修改邮箱\n     *\n     * @param member 会员接收数据\n     * @return\n     */\n    BaseResult updateEmail(Member member);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/OrderService.java",
    "content": "package com.yuu.ymall.web.api.service;\n\nimport com.alipay.api.response.AlipayTradePrecreateResponse;\nimport com.alipay.demo.trade.model.TradeStatus;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.web.api.dto.Order;\nimport com.yuu.ymall.web.api.dto.OrderInfo;\nimport com.yuu.ymall.web.api.dto.OrderPay;\n\nimport javax.servlet.http.HttpServletRequest;\n\n/**\n * @author by Yuu\n * @classname OrderService\n * @date 2019/7/6 2:14\n */\npublic interface OrderService {\n\n    /**\n     * 创建订单\n     *\n     * @param orderInfo 订单信息\n     * @param request 请求 ip 验证\n     * @return\n     */\n    BaseResult addOrder(OrderInfo orderInfo, HttpServletRequest request);\n\n    /**\n     * 根据订单 id 获取订单详情\n     *\n     * @param orderId 订单 id\n     * @return\n     */\n    BaseResult getOrderDet(String orderId);\n\n    /**\n     * 订单支付\n     *\n     * @param orderPay 订单支付\n     * @return\n     */\n    AlipayTradePrecreateResponse payment(OrderPay orderPay);\n\n    /**\n     * 修改订单状态\n     *\n     * @param orderId 订单 id\n     * @param orderStatus 订单状态\n     */\n    int updateOrderStatus(String orderId, Integer orderStatus);\n\n    /**\n     * 获取订单支付状态\n     *\n     * @param orderId 订单 id\n     * @return\n     */\n    TradeStatus getOrderStatus(String orderId);\n\n    /**\n     * 获取订单列表\n     *\n     * @param userId 会员 id\n     * @param page 第几页\n     * @param size 每页大小\n     * @return\n     */\n    BaseResult getOrderList(String userId, int page, int size);\n\n    /**\n     * 确认收货\n     *\n     * @param order 订单\n     * @return\n     */\n    BaseResult confirmReceipt(Order order);\n\n    /**\n     * 删除订单\n     *\n     * @param order 订单\n     * @return\n     */\n    BaseResult deleteService(Order order);\n\n    /**\n     * 支付成功\n     *\n     * @param orderId 订单 id\n     * @return\n     */\n    int paySuccess(String orderId);\n\n    /**\n     * 取消订单\n     *\n     * @param order 订单\n     * @return\n     */\n    BaseResult cancelService(Order order);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/ProductService.java",
    "content": "package com.yuu.ymall.web.api.service;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.web.api.dto.CategoryProductPageInfo;\n\n/**\n * @author by Yuu\n * @classname ProductService\n * @date 2019/7/3 18:51\n */\npublic interface ProductService {\n\n    /**\n     * 获取商品详情\n     *\n     * @param productId 商品 id\n     * @return\n     */\n    BaseResult getProductDet(Long productId);\n\n    /**\n     * 获取分类商品\n     *\n     * @param categoryProductPageInfo 分类商品查询信息\n     * @return\n     */\n    BaseResult getByCategory(CategoryProductPageInfo categoryProductPageInfo);\n\n    /**\n     * 快速搜索\n     *\n     * @param key 关键字\n     * @return\n     */\n    BaseResult getQuickSearch(String key);\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/impl/CartServiceImpl.java",
    "content": "package com.yuu.ymall.web.api.service.impl;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.commons.utils.MapperUtil;\nimport com.yuu.ymall.domain.TbItem;\nimport com.yuu.ymall.web.api.dto.Cart;\nimport com.yuu.ymall.web.api.dto.CartProduct;\nimport com.yuu.ymall.web.api.mapper.TbItemMapper;\nimport com.yuu.ymall.web.api.service.CartService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author by Yuu\n * @classname CartServiceImpl\n * @date 2019/7/3 9:13\n */\n@Service\npublic class CartServiceImpl implements CartService {\n\n    @Value(\"${CART_PRE}\")\n    private String CART_PRE;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    @Autowired\n    private TbItemMapper tbItemMapper;\n\n    @Override\n    public BaseResult addProduct(Cart cart) {\n\n        // Redis key CART:userId\n        String cartKey = CART_PRE + \":\" + cart.getUserId();\n\n        // HASH key\n        String hashKey = String.valueOf(cart.getProductId());\n\n        // 判断缓存中该会员购物车中是否有该商品\n        boolean hasHash = redisCacheManager.hasHashKye(cartKey, hashKey);\n        // 有商品，数量相加\n        if (hasHash) {\n            try {\n                String cartJson = (String) redisCacheManager.getHash(cartKey, hashKey);\n                if (cartJson != null) {\n                    CartProduct redisCartProduct = null;\n                    redisCartProduct = MapperUtil.json2pojo(cartJson, CartProduct.class);\n                    redisCartProduct.setProductNum(redisCartProduct.getProductNum() + cart.getProductNum());\n                    String redisJson = MapperUtil.obj2json(redisCartProduct);\n                    redisCacheManager.setHash(cartKey, hashKey, redisJson);\n                    return BaseResult.success(\"添加商品到购物车成功\");\n                }\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n\n        // 没有商品，新增一条\n        try {\n            TbItem tbItem = tbItemMapper.selectByPrimaryKey(cart.getProductId());\n            if (tbItem == null) {\n                return BaseResult.fail(\"要添加到的购物车的商品不存在\");\n            }\n            CartProduct cartProduct = new CartProduct();\n            cartProduct.setProductId(tbItem.getId());\n            cartProduct.setProductName(tbItem.getTitle());\n            cartProduct.setProductNum(cart.getProductNum());\n            cartProduct.setProductImg(tbItem.getImages()[0]);\n            cartProduct.setLimitNum(tbItem.getLimitNum());\n            cartProduct.setSalePrice(tbItem.getPrice());\n            cartProduct.setChecked(\"0\");\n            String redisJson = MapperUtil.obj2json(cartProduct);\n            redisCacheManager.setHash(cartKey, hashKey, redisJson);\n            return BaseResult.success(\"添加商品到购物车成功\");\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return BaseResult.fail(\"添加商品到购物车失败\");\n    }\n\n    @Override\n    public BaseResult getCartList(Long userId) {\n\n        // Redis key\n        String redisKey = CART_PRE + \":\" + userId;\n\n        // 获取会员所有购物车商品\n        Map<String, Object> cartMap = redisCacheManager.getHashByKey(redisKey);\n\n        // 封装成购物车集合\n        List<CartProduct> cartProducts = new ArrayList<>();\n        if (cartMap != null) {\n            for (String key: cartMap.keySet()) {\n                String productJson = (String) cartMap.get(key);\n                CartProduct cartProduct = new CartProduct();\n                try {\n                    cartProduct = MapperUtil.json2pojo(productJson, CartProduct.class);\n                } catch (Exception e) {\n                    e.printStackTrace();\n                    return BaseResult.fail(\"获取购物车失败\");\n                }\n                if (cartProduct != null) {\n                    cartProducts.add(cartProduct);\n                }\n            }\n        }\n\n        return BaseResult.success(cartProducts);\n    }\n\n    @Override\n    public BaseResult delProduct(Cart cart) {\n\n        // Redis key\n        String redisKey = CART_PRE + \":\" + cart.getUserId();\n\n        // Hash key\n        String hashKey = String.valueOf(cart.getProductId());\n\n        // 删除缓存\n        redisCacheManager.deleteHash(redisKey, hashKey);\n\n        return BaseResult.success(\"删除购物车商品成功\");\n    }\n\n    @Override\n    public BaseResult editProduct(Cart cart) {\n\n        // Redis key\n        String redisKey = CART_PRE + \":\" + cart.getUserId();\n\n        // Hash key\n        String hashKey = String.valueOf(cart.getProductId());\n\n        // 修改缓存\n        try {\n            String oldCartJson = (String) redisCacheManager.getHash(redisKey, hashKey);\n            CartProduct oldCartProduct = MapperUtil.json2pojo(oldCartJson, CartProduct.class);\n            oldCartProduct.setChecked(cart.getChecked());\n            oldCartProduct.setProductNum(cart.getProductNum());\n            String newCartProductJson = MapperUtil.obj2json(oldCartProduct);\n            if (newCartProductJson != null) {\n                redisCacheManager.setHash(redisKey, hashKey, newCartProductJson);\n                return BaseResult.success(\"编辑购物车商品成功\");\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n\n        return BaseResult.fail(\"编辑购物车商品失败\");\n    }\n\n    @Override\n    public BaseResult editCheckAll(Cart cart) {\n\n        // Redis key\n        String redisKey = CART_PRE + \":\" + cart.getUserId();\n\n        Map<String, Object> hashByKey = redisCacheManager.getHashByKey(redisKey);\n        for (String key : hashByKey.keySet()) {\n            String oldCartProductJson = (String) hashByKey.get(key);\n            try {\n                CartProduct cartProduct = MapperUtil.json2pojo(oldCartProductJson, CartProduct.class);\n                if (cartProduct != null) {\n                    if (\"true\".equals(cart.getChecked())) {\n                        cartProduct.setChecked(\"1\");\n                    } else {\n                        cartProduct.setChecked(\"0\");\n                    }\n                }\n                String newCartProduct = MapperUtil.obj2json(cartProduct);\n                redisCacheManager.setHash(redisKey, key, newCartProduct);\n            } catch (Exception e) {\n                e.printStackTrace();\n                return BaseResult.fail(\"购物车全选失败\");\n            }\n        }\n\n        return BaseResult.success(\"购物车全选成功\");\n    }\n\n    @Override\n    public BaseResult delCartChecked(Cart cart) {\n\n        // Redis key\n        String redisKey = CART_PRE + \":\" + cart.getUserId();\n\n        Map<String, Object> hashByKey = redisCacheManager.getHashByKey(redisKey);\n        for (String key : hashByKey.keySet()) {\n            String oldCartProductJson = (String) hashByKey.get(key);\n            try {\n                CartProduct cartProduct = MapperUtil.json2pojo(oldCartProductJson, CartProduct.class);\n                if (cartProduct != null && \"1\".equals(cartProduct.getChecked())) {\n                    redisCacheManager.deleteHash(redisKey, key);\n                }\n            } catch (Exception e) {\n                e.printStackTrace();\n                return BaseResult.fail(\"删除购物车已选商品失败\");\n            }\n        }\n\n        return BaseResult.success(\"删除购物车已选商品成功\");\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/impl/ContentServiceImpl.java",
    "content": "package com.yuu.ymall.web.api.service.impl;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.commons.utils.MapperUtil;\nimport com.yuu.ymall.domain.TbItem;\nimport com.yuu.ymall.domain.TbPanel;\nimport com.yuu.ymall.web.api.dto.TbPanelContentDto;\nimport com.yuu.ymall.web.api.dto.TbPanelDto;\nimport com.yuu.ymall.web.api.mapper.TbItemMapper;\nimport com.yuu.ymall.web.api.mapper.TbPanelContentMapper;\nimport com.yuu.ymall.web.api.mapper.TbPanelMapper;\nimport com.yuu.ymall.web.api.service.ContentService;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author by Yuu\n * @classname ContentServiceImpl\n * @date 2019/7/2 13:51\n */\n@Service\n@Transactional(readOnly = true)\npublic class ContentServiceImpl implements ContentService {\n\n    @Autowired\n    private TbPanelContentMapper tbPanelContentMapper;\n\n    @Autowired\n    private TbPanelMapper tbPanelMapper;\n\n    @Autowired\n    private TbItemMapper tbItemMapper;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    /**\n     * 首页板块内容的 key\n     */\n    @Value(\"${PRODUCT_HOME}\")\n    private String PRODUCT_HOME;\n\n    /**\n     * 推荐板块 key\n     */\n    @Value(\"${RECOMEED_PANEL}\")\n    private String RECOMEED_PANEL;\n\n    /**\n     * 推荐板块数据库 id\n     */\n    @Value(\"${RECOMEED_PANEL_ID}\")\n    private Integer RECOMEED_PANEL_ID;\n\n    @Override\n    public BaseResult getHome() {\n\n        List<TbPanelDto> tbPanelDtos = new ArrayList<>();\n\n        // 查询缓存\n        try {\n            // 有缓存从缓存读取\n            String tbPanelsJson = (String) redisCacheManager.get(PRODUCT_HOME);\n            if (tbPanelsJson != null) {\n                tbPanelDtos = MapperUtil.json2list(tbPanelsJson, TbPanelDto.class);\n                return BaseResult.success(tbPanelDtos);\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n\n        // 没有缓存从数据库中读取\n        tbPanelDtos = tbPanelMapper.selectAll();\n        for (TbPanelDto tbPanelDto : tbPanelDtos) {\n            List<TbPanelContentDto> tbPanelContents = tbPanelContentMapper.selectContentByPid(tbPanelDto.getId());\n            // 设置商品相关信息\n            for (TbPanelContentDto tbPanelContentDto : tbPanelContents) {\n                TbItem tbItem = tbItemMapper.selectByPrimaryKey(tbPanelContentDto.getProductId());\n                if (tbItem != null) {\n                    tbPanelContentDto.setSalePrice(tbItem.getPrice());\n                    tbPanelContentDto.setProductName(tbItem.getTitle());\n                    tbPanelContentDto.setSubTitle(tbItem.getSellPoint());\n                    Integer limitNum = tbItem.getLimitNum();\n                    Integer num = tbItem.getNum();\n                    if (limitNum > num) {\n                        limitNum = num;\n                    }\n                    tbPanelContentDto.setLimit(limitNum);\n                }\n            }\n            tbPanelDto.setPanelContentDtos(tbPanelContents);\n        }\n\n        // 将数据存入缓存\n        try {\n            String tbPanelsJson = MapperUtil.obj2json(tbPanelDtos);\n            redisCacheManager.set(PRODUCT_HOME, tbPanelsJson);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n\n        return BaseResult.success(tbPanelDtos);\n    }\n\n    @Override\n    public BaseResult getRecommendGoods() {\n        TbPanelDto tbPanelDto = new TbPanelDto();\n\n        // 有缓存，从缓存中共读取\n        String redisJson = (String) redisCacheManager.get(RECOMEED_PANEL);\n        if (StringUtils.isNoneBlank(redisJson)) {\n            try {\n                tbPanelDto = MapperUtil.json2pojo(redisJson, TbPanelDto.class);\n                return BaseResult.success(tbPanelDto);\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n\n        // 没有缓存，从数据库中读取\n        TbPanel tbPanel = tbPanelMapper.selectByPrimaryKey(RECOMEED_PANEL_ID);\n        if (tbPanel != null) {\n            tbPanelDto.setId(tbPanel.getId());\n            tbPanelDto.setName(tbPanel.getName());\n            tbPanelDto.setType(tbPanel.getType());\n            // 查询板块内容\n            List<TbPanelContentDto> tbPanelContentDtos = tbPanelContentMapper.selectContentByPid(tbPanel.getId());\n            // 获取商品相关信息\n            for (TbPanelContentDto tbPanelContentDto : tbPanelContentDtos) {\n                TbItem tbItem = tbItemMapper.selectByPrimaryKey(tbPanelContentDto.getProductId());\n                if (tbItem != null) {\n                    tbPanelContentDto.setProductName(tbItem.getTitle());\n                    tbPanelContentDto.setSubTitle(tbItem.getSellPoint());\n                    tbPanelContentDto.setSalePrice(tbItem.getPrice());\n                }\n            }\n\n            tbPanelDto.setPanelContentDtos(tbPanelContentDtos);\n        }\n\n        if (tbPanelDto != null) {\n            // 将结果添加至缓存\n            try {\n                String tbPanelDtoJson = MapperUtil.obj2json(tbPanelDto);\n                redisCacheManager.set(RECOMEED_PANEL, tbPanelDtoJson);\n                return BaseResult.success(tbPanelDto);\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n\n        return BaseResult.fail(\"获取推荐板块失败\");\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/impl/ItemCatServiceImpl.java",
    "content": "package com.yuu.ymall.web.api.service.impl;\n\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.commons.utils.MapperUtil;\nimport com.yuu.ymall.domain.TbItemCat;\nimport com.yuu.ymall.web.api.dto.TbCate;\nimport com.yuu.ymall.web.api.mapper.TbItemCatMapper;\nimport com.yuu.ymall.web.api.service.ItemCatService;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author by Yuu\n * @classname ItemCatServiceImpl\n * @date 2019/7/2 10:12\n */\n@Service\n@Transactional(readOnly = true)\npublic class ItemCatServiceImpl implements ItemCatService {\n\n    @Autowired\n    private TbItemCatMapper tbItemCatMapper;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    @Value(\"${HEADER_CATE}\")\n    private String HEADER_CATE;\n\n    @Override\n    public BaseResult getCateList() {\n        List<TbCate> tbCateList = new ArrayList<>();\n        // 查询缓存\n        try {\n            // 有缓存则读取\n            String json = (String) redisCacheManager.get(HEADER_CATE);\n            if (json != null) {\n                tbCateList = MapperUtil.json2list(json, TbCate.class);\n                return BaseResult.success(tbCateList);\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n\n        // 从数据库中查询\n        List<TbItemCat> tbItemCats = tbItemCatMapper.selectAll();\n        // 删除根分类，所有商品\n        tbItemCats.remove(0);\n        List<TbCate> tbCates = new ArrayList<>();\n        for (TbItemCat tbItemCat : tbItemCats) {\n            // 如果是分级分类，进行遍历设值\n            if (tbItemCat.getParentId() == 0) {\n                TbCate tbCate = new TbCate();\n                tbCate.setId(tbItemCat.getId());\n                tbCate.setName(tbItemCat.getName());\n                // 查询父分类的所有子分类\n                List<TbItemCat> tbItemCatList = tbItemCatMapper.selectTbCatByPid(tbItemCat.getId());\n                List<TbCate> tbCateSons = new ArrayList<>();\n                for (TbItemCat itemCat : tbItemCatList) {\n                    TbCate tbCateSon = new TbCate();\n                    tbCateSon.setId(itemCat.getId());\n                    tbCateSon.setName(itemCat.getName());\n                    tbCateSon.setCatesons(null);\n                    tbCateSons.add(tbCateSon);\n                }\n                tbCate.setCatesons(tbCateSons);\n                tbCates.add(tbCate);\n            }\n        }\n\n        // 把结果添加至缓存\n        try {\n            String tbCateListJson = MapperUtil.obj2json(tbCates);\n            redisCacheManager.set(HEADER_CATE, tbCateListJson);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n\n        return BaseResult.success(tbCates);\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/impl/MemberServieImpl.java",
    "content": "package com.yuu.ymall.web.api.service.impl;\n\nimport com.yuu.ymall.commons.consts.Consts;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.commons.utils.MapperUtil;\nimport com.yuu.ymall.commons.utils.SendSmsUtil;\nimport com.yuu.ymall.domain.TbAddress;\nimport com.yuu.ymall.domain.TbMember;\nimport com.yuu.ymall.web.api.common.utils.EmailUtil;\nimport com.yuu.ymall.web.api.common.utils.QiniuUtil;\nimport com.yuu.ymall.web.api.dto.EmailCode;\nimport com.yuu.ymall.web.api.dto.Member;\nimport com.yuu.ymall.web.api.dto.MemberLogin;\nimport com.yuu.ymall.web.api.mapper.TbAddressMapper;\nimport com.yuu.ymall.web.api.mapper.TbMemberMapper;\nimport com.yuu.ymall.web.api.service.MemberService;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\nimport org.springframework.util.DigestUtils;\n\nimport javax.servlet.http.HttpSession;\nimport java.util.Date;\nimport java.util.List;\nimport java.util.UUID;\nimport java.util.regex.Pattern;\n\n/**\n * @author by Yuu\n * @classname MemberServieImpl\n * @date 2019/6/24 9:05\n */\n@Service\n@Transactional(readOnly = true)\npublic class MemberServieImpl implements MemberService {\n\n    @Autowired\n    private TbMemberMapper tbMemberMapper;\n\n    @Autowired\n    private TbAddressMapper tbAddressMapper;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    @Autowired\n    private EmailUtil emailUtil;\n\n    @Value(\"${SESSION_EXPIRE}\")\n    private Integer SESSION_EXPIRE;\n\n    @Override\n    public BaseResult checkPhone(String phone) {\n        TbMember tbMember = tbMemberMapper.selectByPhone(phone);\n\n        // 手机号已存在\n        if (tbMember != null) {\n            return BaseResult.success(true);\n        }\n\n        return BaseResult.success(false);\n    }\n\n    @Override\n    public BaseResult sendSms(String phone) {\n        // 调用短信发送工具发送短信,返回验证码\n        String vercode = SendSmsUtil.sendSms(phone);\n        return BaseResult.success((Object)vercode);\n    }\n\n    @Transactional\n    @Override\n    public BaseResult register(TbMember tbMember) {\n        tbMember.setPassword(DigestUtils.md5DigestAsHex(tbMember.getPassword().getBytes()));\n        tbMember.setCreated(new Date());\n        tbMember.setUpdated(new Date());\n        tbMember.setState(Consts.MEMBER_STATUS_NORMAL);\n        tbMemberMapper.register(tbMember);\n        return BaseResult.success();\n    }\n\n    @Override\n    public BaseResult login(MemberLogin memberLogin, HttpSession session) {\n\n        // 账号\n        String account = memberLogin.getAccount();\n\n        // 手机号正则表达式\n        String phonePattern = \"1[3|4|5|7|8][0-9]\\\\d{8}\";\n\n        // 邮箱正则表达式\n        String emailPattern = \"(\\\\w-*\\\\.*)+@(\\\\w-?)+(\\\\.\\\\w{2,})+\";\n\n        // 手机号登录\n        if (Pattern.matches(phonePattern, account)) {\n            TbMember tbMember = tbMemberMapper.selectByPhone(account);\n            return verLogin(memberLogin, tbMember, session);\n        }\n\n        // 邮箱登录\n        else if (Pattern.matches(emailPattern, account)) {\n            TbMember tbMember = tbMemberMapper.selectByEmail(account);\n            return verLogin(memberLogin, tbMember, session);\n        }\n\n        // 账号格式错误\n        else {\n            return BaseResult.fail(\"账号格式错误，只能为邮箱或手机号！\");\n        }\n    }\n\n    @Override\n    public BaseResult getMemberByToken(String token) {\n        // 从 Redis 从获取登录信息\n        String json = (String) redisCacheManager.get(\"SESSION:\" + token);\n        TbMember tbMember = null;\n        try {\n            tbMember = MapperUtil.json2pojo(json, TbMember.class);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n\n        // 没有登录信息，已过期\n        if (tbMember == null) {\n            return BaseResult.fail(\"用户登录已过期！\");\n        }\n\n        // 没有过期，再次登录，重新设置过期时间\n        redisCacheManager.expire(\"SESSION:\" + token, SESSION_EXPIRE);\n        return BaseResult.success(tbMember);\n    }\n\n    @Override\n    public BaseResult logout(String token) {\n        Boolean flag = redisCacheManager.del(\"SESSION:\" + token);\n        if (!flag) {\n            return BaseResult.fail(\"退出登录失败！\");\n        }\n        return BaseResult.success(\"退出登录成功\");\n    }\n\n    @Override\n    public BaseResult checkAccount(String account) {\n        TbMember tbMember = tbMemberMapper.selectByPhoneOrEmail(account);\n        // 不存在\n        if (tbMember == null) {\n            return BaseResult.success(false);\n        }\n        // 存在\n        return BaseResult.success(true);\n    }\n\n    @Transactional\n    @Override\n    public BaseResult updatePassword(MemberLogin memberLogin) {\n\n        // 账号\n        String account = memberLogin.getAccount();\n\n        // 密码\n        String password = memberLogin.getPassword();\n\n        if (StringUtils.isBlank(account) || StringUtils.isBlank(password)) {\n            return BaseResult.fail(\"账号密码不能为空\");\n        }\n        tbMemberMapper.updatePassword(account, DigestUtils.md5DigestAsHex(password.getBytes()));\n        return BaseResult.success(\"修改会员密码成功\");\n    }\n\n    @Override\n    public BaseResult sendVerCode(String account) {\n        // 手机号正则表达式\n        String phonePattern = \"1[3|4|5|7|8][0-9]\\\\d{8}\";\n\n        // 邮箱正则表达式\n        String emailPattern = \"(\\\\w-*\\\\.*)+@(\\\\w-?)+(\\\\.\\\\w{2,})+\";\n\n        // 发送手机验证码\n        if (Pattern.matches(phonePattern, account)) {\n            // 调用短信发送工具发送短信,返回验证码\n            String vercode = SendSmsUtil.sendSms(account);\n            return BaseResult.success((Object)vercode);\n        }\n\n        // 发送邮箱验证码\n        else if (Pattern.matches(emailPattern, account)) {\n            String code = String.valueOf((int)((Math.random() * 9 + 1) * 100000));\n            EmailCode emailCode = new EmailCode(account, code);\n            emailUtil.sendTemplateEmail(account, \"【YMALL商城】找回密码\", \"reset-pass\", emailCode);\n            return BaseResult.success((Object)code);\n        }\n\n        // 账号格式错误\n        else {\n            return BaseResult.fail(\"账号格式错误，只能为邮箱或手机号！\");\n        }\n    }\n\n    @Override\n    public BaseResult getAddressList(Long userId) {\n        List<TbAddress> tbAddressList = tbAddressMapper.selectByUserId(userId);\n        // 拼接详细地址\n        for (TbAddress tbAddress : tbAddressList) {\n            String state = tbAddress.getState();\n            String city = tbAddress.getCity();\n            String district = tbAddress.getDistrict();\n            String streetName = tbAddress.getStreetName();\n            StringBuffer detailsAddress = new StringBuffer();\n            detailsAddress.append(state).append(\" \").append(city).append(\" \").append(district)\n                    .append(\" \").append(streetName);\n            tbAddress.setDetailsAddress(detailsAddress.toString());\n        }\n        return BaseResult.success(tbAddressList);\n    }\n\n    @Transactional\n    @Override\n    public BaseResult updateAddress(TbAddress tbAddress) {\n        if (tbAddress.getIsDefault()) {\n            tbAddressMapper.removeDefault(tbAddress.getUserId());\n        }\n        tbAddressMapper.updateAddress(tbAddress);\n        return BaseResult.success(\"会员修改地址成功\");\n    }\n\n    @Transactional\n    @Override\n    public BaseResult addAdderss(TbAddress tbAddress) {\n        if (tbAddress.getIsDefault()) {\n            tbAddressMapper.removeDefault(tbAddress.getUserId());\n        }\n        tbAddressMapper.insert(tbAddress);\n        return BaseResult.success(\"会员增加地址\");\n    }\n\n    @Transactional\n    @Override\n    public BaseResult delAddress(Long id) {\n        tbAddressMapper.deleteByPrimaryKey(id);\n        return BaseResult.success(\"会员删除地址成功\");\n    }\n\n    @Transactional\n    @Override\n    public BaseResult uploadImg(Member member) {\n\n        // 图片 base64\n        String imgData = member.getImgData();\n\n        // 会员 id\n        Long userId = member.getUserId();\n\n        // Redis token\n        String token = member.getToken();\n\n        // 七牛云上传图片\n        String base64 = QiniuUtil.base64Data(imgData);\n        String imgPath = QiniuUtil.qiniuBase64Upload(base64);\n\n        // 获取会员\n        TbMember tbMember = tbMemberMapper.selectByPrimaryKey(userId);\n        if (tbMember == null) {\n            return BaseResult.fail(\"获取用户信息失败\");\n        }\n\n        // 更新数据库数据\n        tbMember.setFile(imgPath);\n        tbMemberMapper.updateByPrimaryKey(tbMember);\n\n        // 更新 Redis 缓存\n        // Redis key\n        String redisKey = \"SESSION:\" + token;\n        String memberJson = null;\n        try {\n            memberJson = MapperUtil.obj2json(tbMember);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        redisCacheManager.set(redisKey, memberJson);\n\n        return BaseResult.success((Object) imgPath);\n    }\n\n    @Transactional\n    @Override\n    public BaseResult updateUsername(Member member) {\n\n        // 会员 id\n        Long userId = member.getUserId();\n\n        // Redis key\n        String token = member.getToken();\n\n        // 用户名\n        String username = member.getUsername();\n\n        // 获取会员\n        TbMember tbMember = tbMemberMapper.selectByPrimaryKey(userId);\n        if (tbMember == null) {\n            return BaseResult.fail(\"获取用户信息失败\");\n        }\n\n        // 更新数据库数据\n        tbMember.setUsername(username);\n        tbMemberMapper.updateByPrimaryKey(tbMember);\n\n        // 更新 Redis 缓存\n        // Redis key\n        String redisKey = \"SESSION:\" + token;\n        String memberJson = null;\n        try {\n            memberJson = MapperUtil.obj2json(tbMember);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        redisCacheManager.set(redisKey, memberJson);\n\n        return BaseResult.success(tbMember);\n    }\n\n    @Transactional\n    @Override\n    public BaseResult updatePhone(Member member) {\n\n        // 会员 id\n        Long userId = member.getUserId();\n\n        // Redis key\n        String token = member.getToken();\n\n        // 手机号\n        String phone = member.getPhone();\n\n        // 获取会员\n        TbMember tbMember = tbMemberMapper.selectByPrimaryKey(userId);\n        if (tbMember == null) {\n            return BaseResult.fail(\"获取用户信息失败\");\n        }\n\n        // 更新数据库数据\n        tbMember.setPhone(phone);\n        tbMemberMapper.updateByPrimaryKey(tbMember);\n\n        // 更新 Redis 缓存\n        // Redis key\n        String redisKey = \"SESSION:\" + token;\n        String memberJson = null;\n        try {\n            memberJson = MapperUtil.obj2json(tbMember);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        redisCacheManager.set(redisKey, memberJson);\n\n        return BaseResult.success(tbMember);\n    }\n\n    @Transactional\n    @Override\n    public BaseResult updatePass(Member member) {\n        // 会员 id\n        Long userId = member.getUserId();\n\n        // Redis key\n        String token = member.getToken();\n\n        // 密码\n        String password = member.getPassword();\n        String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());\n\n        // 获取会员\n        TbMember tbMember = tbMemberMapper.selectByPrimaryKey(userId);\n        if (tbMember == null) {\n            return BaseResult.fail(\"获取用户信息失败\");\n        }\n\n        // 更新数据库数据\n        tbMember.setPassword(md5Password);\n        tbMemberMapper.updateByPrimaryKey(tbMember);\n\n        // 更新 Redis 缓存\n        // Redis key\n        String redisKey = \"SESSION:\" + token;\n        String memberJson = null;\n        try {\n            memberJson = MapperUtil.obj2json(tbMember);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        redisCacheManager.set(redisKey, memberJson);\n\n        return BaseResult.success(tbMember);\n    }\n\n    @Override\n    public BaseResult sendEmailCode(String email) {\n        String code = String.valueOf((int)((Math.random() * 9 + 1) * 100000));\n        EmailCode emailCode = new EmailCode(email, code);\n        emailUtil.sendTemplateEmail(email, \"【YMALL商城】修改邮箱\", \"update-email\", emailCode);\n        return BaseResult.success((Object)code);\n    }\n\n    @Override\n    public BaseResult checkEmail(String email) {\n        TbMember tbMember = tbMemberMapper.selectByEmail(email);\n        // 邮箱存在\n        if (tbMember != null) {\n            return BaseResult.success(true);\n        }\n        // 邮箱不存在\n        return BaseResult.success(false);\n    }\n\n    @Transactional\n    @Override\n    public BaseResult updateEmail(Member member) {\n        // 会员 id\n        Long userId = member.getUserId();\n\n        // Redis key\n        String token = member.getToken();\n\n        // 邮箱\n        String email = member.getEmail();\n\n        // 获取会员\n        TbMember tbMember = tbMemberMapper.selectByPrimaryKey(userId);\n        if (tbMember == null) {\n            return BaseResult.fail(\"获取用户信息失败\");\n        }\n\n        // 更新数据库数据\n        tbMember.setEmail(email);\n        tbMemberMapper.updateByPrimaryKey(tbMember);\n\n        // 更新 Redis 缓存\n        // Redis key\n        String redisKey = \"SESSION:\" + token;\n        String memberJson = null;\n        try {\n            memberJson = MapperUtil.obj2json(tbMember);\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        redisCacheManager.set(redisKey, memberJson);\n\n        return BaseResult.success(tbMember);\n    }\n\n    /**\n     * 保存会员 session\n     *\n     * @param memberLogin 会员登录信息\n     * @param tbMember 会员\n     * @param session session\n     * @return\n     */\n    private BaseResult verLogin(MemberLogin memberLogin, TbMember tbMember, HttpSession session) {\n\n        // 获取 MD5 加密密码\n        String md5Password = DigestUtils.md5DigestAsHex(memberLogin.getPassword().getBytes());\n\n        if (tbMember != null && tbMember.getPassword().equals(md5Password)) {\n            // 判断账户状态是否正常\n            if (Consts.MEMBER_STATUS_BAN == (tbMember.getState())) {\n                return BaseResult.fail(\"您的账号已被封禁，请联系管理员进行解封！\");\n            }\n\n            // 自动登录，将登录信息保存在 Redis 中\n            if (memberLogin.getAuto()) {\n                try {\n                    String token = UUID.randomUUID().toString();\n                    tbMember.setToken(token);\n                    // 将会员登录信息，保存到 Redis\n                    redisCacheManager.set(\"SESSION:\" + token, MapperUtil.obj2json(tbMember));\n                    // 设置过期时间\n                    redisCacheManager.expire(\"SESSION:\" + token, SESSION_EXPIRE);\n                } catch (Exception e) {\n                    e.printStackTrace();\n                }\n            }\n\n            // 不自动登录，将登录信息保存在 HttpSession 中\n            else {\n                // 设置 token 为空\n                tbMember.setToken(\"\");\n                session.setAttribute(\"memberLogin\", tbMember);\n            }\n\n            return BaseResult.success(tbMember);\n        }\n\n\n\n        return BaseResult.fail(\"账号或密码错误！\");\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/impl/OrderServiceImpl.java",
    "content": "package com.yuu.ymall.web.api.service.impl;\n\nimport com.alipay.api.response.AlipayTradePrecreateResponse;\nimport com.alipay.demo.trade.config.Configs;\nimport com.alipay.demo.trade.model.TradeStatus;\nimport com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;\nimport com.alipay.demo.trade.model.builder.AlipayTradeQueryRequestBuilder;\nimport com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;\nimport com.alipay.demo.trade.model.result.AlipayF2FQueryResult;\nimport com.alipay.demo.trade.service.AlipayTradeService;\nimport com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;\nimport com.github.pagehelper.PageHelper;\nimport com.github.pagehelper.PageInfo;\nimport com.yuu.ymall.commons.consts.Consts;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.commons.utils.IDUtil;\nimport com.yuu.ymall.commons.utils.MapperUtil;\nimport com.yuu.ymall.domain.*;\nimport com.yuu.ymall.web.api.common.config.AlipayConfig;\nimport com.yuu.ymall.web.api.common.utils.IPInfoUtil;\nimport com.yuu.ymall.web.api.dto.*;\nimport com.yuu.ymall.web.api.mapper.*;\nimport com.yuu.ymall.web.api.service.OrderService;\nimport org.apache.commons.lang3.StringUtils;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.stereotype.Service;\nimport org.springframework.transaction.annotation.Transactional;\n\nimport javax.servlet.http.HttpServletRequest;\nimport java.math.BigDecimal;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Calendar;\nimport java.util.Date;\nimport java.util.List;\n\n/**\n * @author by Yuu\n * @classname OrderServiceImpl\n * @date 2019/7/6 2:14\n */\n@Service\n@Transactional(readOnly = false)\npublic class OrderServiceImpl implements OrderService {\n\n    @Value(\"${ADD_ORDER}\")\n    private String ADD_ORDER;\n\n    @Value(\"${CART_PRE}\")\n    private String CART_PRE;\n\n    @Value(\"${ORDER_PAY}\")\n    private String ORDER_PAY;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    @Autowired\n    private TbMemberMapper tbMemberMapper;\n\n    @Autowired\n    private TbOrderMapper tbOrderMapper;\n\n    @Autowired\n    private TbOrderItemMapper tbOrderItemMapper;\n\n    @Autowired\n    private TbOrderShippingMapper tbOrderShippingMapper;\n\n    @Autowired\n    private TbItemMapper tbItemMapper;\n\n    @Value(\"${PRODUCT_ITEM}\")\n    private String PRODUCT_ITEM;\n\n    @Transactional\n    @Override\n    public BaseResult addOrder(OrderInfo orderInfo, HttpServletRequest request) {\n\n        // 用户 id\n        Long userId = orderInfo.getUserId();\n\n        // 地址收货人\n        String username = orderInfo.getUserName();\n\n        // 订单商品\n        List<CartProduct> goods = orderInfo.getGoodsList();\n\n        if (userId == null || StringUtils.isBlank(username) || goods == null || goods.size() == 0) {\n            return BaseResult.fail(\"请求信息异常\");\n        }\n\n        // 请求 ip 地址\n        String ip = IPInfoUtil.getIpAddr(request);\n        if(\"0:0:0:0:0:0:0:1\".equals(ip)){\n            ip=\"127.0.0.1\";\n        }\n\n        // Redis key，防止恶意请求\n        String redisKey = ADD_ORDER + \":\" + ip;\n        String temp = (String) redisCacheManager.get(redisKey);\n        if (StringUtils.isNotBlank(temp)) {\n            return BaseResult.fail(\"您提交的太频繁了，请您稍后再试\");\n        }\n\n        TbMember tbMember = tbMemberMapper.selectByPrimaryKey(userId);\n        if (tbMember == null) {\n            return BaseResult.fail(\"获取下单用户失败\");\n        }\n\n        // 生成订单\n        TbOrder tbOrder = new TbOrder();\n        tbOrder.setId(String.valueOf(IDUtil.getRandomId()));\n        tbOrder.setUserId(userId);\n        if (StringUtils.isBlank(tbMember.getUsername())) {\n            tbOrder.setBuyerNick(tbMember.getPhone());\n        } else {\n            tbOrder.setBuyerNick(tbMember.getUsername());\n        }\n        tbOrder.setPayment(orderInfo.getOrderTotal());\n        tbOrder.setCreated(new Date());\n        tbOrder.setUpdated(new Date());\n        // 0: 未付款 1: 已付款 2: 未发货 3: 已发货 4: 交易成功 5: 交易关闭\n        tbOrder.setStatus(0);\n\n        // 添加订单\n        tbOrderMapper.insert(tbOrder);\n\n        // 生成订单信息\n        List<CartProduct> goodsList = orderInfo.getGoodsList();\n        for (CartProduct cartProduct : goodsList) {\n            TbOrderItem tbOrderItem = new TbOrderItem();\n            Long orderItemId = IDUtil.getRandomId();\n            tbOrderItem.setId(orderItemId.toString());\n            tbOrderItem.setItemId(cartProduct.getProductId().toString());\n            tbOrderItem.setOrderId(tbOrder.getId());\n            tbOrderItem.setNum(cartProduct.getProductNum());\n            tbOrderItem.setTitle(cartProduct.getProductName());\n            tbOrderItem.setPrice(cartProduct.getSalePrice());\n            tbOrderItem.setTotalFee(cartProduct.getSalePrice().multiply(BigDecimal.valueOf(cartProduct.getProductNum())));\n            tbOrderItem.setPicPath(cartProduct.getProductImg());\n            tbOrderItemMapper.insert(tbOrderItem);\n\n            // 删除会员购物车中的该商品\n            // Redis key\n            String cartProductKey = CART_PRE + \":\" + orderInfo.getUserId();\n            // Hash Key\n            String hashKey = cartProduct.getProductId().toString();\n            // 删除记录\n            redisCacheManager.deleteHash(cartProductKey, hashKey);\n        }\n\n        // 生成物流信息\n        TbOrderShipping tbOrderShipping = new TbOrderShipping();\n        tbOrderShipping.setOrderId(tbOrder.getId());\n        tbOrderShipping.setReceiverName(orderInfo.getUserName());\n        tbOrderShipping.setReceiverAddress(orderInfo.getStreetName());\n        tbOrderShipping.setReceiverPhone(orderInfo.getTel());\n        tbOrderShipping.setCreated(new Date());\n        tbOrderShipping.setUpdated(new Date());\n        tbOrderShippingMapper.insert(tbOrderShipping);\n\n        // 修改商品库存信息\n        for (CartProduct good : goods) {\n            Long productId = good.getProductId();\n            // 商品库存\n            tbItemMapper.reduceItemNum(productId, good.getProductNum());\n            // 删除 Redis 商品缓存信息\n            String redisItemKey = PRODUCT_ITEM + \":\" + productId;\n            redisCacheManager.del(redisItemKey);\n        }\n\n        // 设置 Redis ip 缓存\n        redisCacheManager.set(redisKey, \"ADD_ORDER\");\n        redisCacheManager.expire(redisKey, 60);\n        return BaseResult.success((Object)tbOrder.getId());\n    }\n\n    @Override\n    public BaseResult getOrderDet(String orderId) {\n\n        Order order = new Order();\n\n        // 获取订单信息\n        TbOrder tbOrder = tbOrderMapper.selectByPrimaryKey(orderId);\n        if (tbOrder == null) {\n            return BaseResult.fail(\"通过id获取订单详情失败\");\n        }\n\n        // 订单 id\n        order.setOrderId(tbOrder.getId());\n\n        // 会员 id\n        order.setUserId(tbOrder.getUserId().toString());\n\n        // 订单状态\n        order.setOrderStatus(tbOrder.getStatus());\n\n        // 未支付，最晚支付时间\n        if (order.getOrderStatus() == 0) {\n            Date createDate = tbOrder.getCreated();\n            Calendar calendar = Calendar.getInstance();\n            calendar.setTime(createDate);\n            calendar.add(Calendar.HOUR, 2);\n            String countTime = calendar.getTime().getTime() + \"\";\n            order.setCountTime(countTime);\n        }\n\n        // 订单创建时间\n        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n        String createDate = simpleDateFormat.format(tbOrder.getCreated());\n        order.setCreateDate(createDate);\n\n        // 订单支付时间\n        if (tbOrder.getPaymentTime() != null) {\n            String payDate = simpleDateFormat.format(tbOrder.getPaymentTime());\n            order.setPayDate(payDate);\n        }\n\n        // 订单发货时间\n        if (tbOrder.getConsignTime() != null) {\n            String consignDate = simpleDateFormat.format(tbOrder.getConsignTime());\n            order.setConsignDate(consignDate);\n        }\n\n        // 订单关闭时间\n        if (tbOrder.getCloseTime() != null) {\n            String closeDate = simpleDateFormat.format(tbOrder.getCloseTime());\n            order.setCloseDate(closeDate);\n        }\n\n        // 订单完成时间\n        if (tbOrder.getEndTime() != null && tbOrder.getStatus() == 4) {\n            String endDate = simpleDateFormat.format(tbOrder.getEndTime());\n            order.setFinishDate(endDate);\n        }\n\n        // 地址\n        TbOrderShipping tbOrderShipping = tbOrderShippingMapper.selectByPrimaryKey(tbOrder.getId());\n        TbAddress tbAddress = new TbAddress();\n        tbAddress.setUserName(tbOrderShipping.getReceiverName());\n        tbAddress.setStreetName(tbOrderShipping.getReceiverAddress());\n        tbAddress.setTel(tbOrderShipping.getReceiverPhone());\n        order.setTbAddress(tbAddress);\n\n        // 订单总计\n        order.setOrderTotal(tbOrder.getPayment());\n\n        // 订单商品列表\n        List<TbOrderItem> tbOrderItemList = tbOrderItemMapper.selectByOrderId(tbOrder.getId());\n        List<CartProduct> cartProductList = new ArrayList<>();\n        for (TbOrderItem tbOrderItem : tbOrderItemList) {\n            CartProduct cartProduct = new CartProduct();\n            cartProduct.setProductId(Long.parseLong(tbOrderItem.getItemId()));\n            cartProduct.setProductName(tbOrderItem.getTitle());\n            cartProduct.setSalePrice(tbOrderItem.getPrice());\n            cartProduct.setProductNum(tbOrderItem.getNum());\n            cartProduct.setProductImg(tbOrderItem.getPicPath());\n            cartProductList.add(cartProduct);\n        }\n\n        // 订单物流信息，如果已发货，或者交易完成查询物流信息\n        if (tbOrder.getStatus() == 3 || tbOrder.getStatus() == 4) {\n            order.setShippingName(tbOrder.getShippingName());\n            order.setShippingCode(tbOrder.getShippingCode());\n        }\n\n        order.setGoodsList(cartProductList);\n        return BaseResult.success(order);\n    }\n\n    @Transactional\n    @Override\n    public AlipayTradePrecreateResponse payment(OrderPay orderPay) {\n\n        // 一定要在创建AlipayTradeService之前设置参数\n        Configs.init(\"zfbinfo.properties\");\n        AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();\n\n        // (必填) 商户网站订单系统中唯一订单号，64个字符以内，只能包含字母、数字、下划线，\n        // 需保证商户系统端不能重复，建议通过数据库sequence生成，\n        String outTradeNo = orderPay.getOrderId().toString();\n\n        // (必填) 订单标题，粗略描述用户的支付目的。如“喜士多（浦东店）消费”\n        String subject = \"YMall\";\n\n        // (必填) 订单总金额，单位为元，不能超过1亿元\n        // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】\n        String totalAmount = orderPay.getOrderTotal().toString();\n\n        // (可选) 订单不可打折金额，可以配合商家平台配置折扣活动，如果酒水不参与打折，则将对应金额填写至此字段\n        // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】\n        String undiscountableAmount = \"\";\n\n        // 卖家支付宝账号ID，用于支持一个签约账号下支持打款到不同的收款账号，(打款到sellerId对应的支付宝账号)\n        // 如果该字段为空，则默认为与支付宝签约的商户的PID，也就是appid对应的PID\n        String sellerId = \"\";\n\n        // 订单描述，可以对交易或商品进行一个详细地描述，比如填写\"购买商品2件共15.00元\"\n        String body = \"YMall\";\n\n        // 商户操作员编号，添加此参数可以为商户操作员做销售统计\n        String operatorId = \"test_operator_id\";\n\n        // (必填) 商户门店编号，通过门店号和商家后台可以配置精准到门店的折扣信息，详询支付宝技术支持\n        String storeId = \"test_store_id\";\n\n        // 支付超时，定义为120分钟\n        String timeoutExpress = \"120m\";\n\n        AlipayTradePrecreateRequestBuilder builder =new AlipayTradePrecreateRequestBuilder()\n                .setSubject(subject)\n                .setTotalAmount(totalAmount)\n                .setOutTradeNo(outTradeNo)\n                .setUndiscountableAmount(undiscountableAmount)\n                .setSellerId(sellerId)\n                .setBody(body)\n                .setOperatorId(operatorId)\n                .setStoreId(storeId)\n                .setTimeoutExpress(timeoutExpress)\n                // 支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置\n                .setNotifyUrl(AlipayConfig.notify_url);\n\n        AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);\n        AlipayTradePrecreateResponse response = result.getResponse();\n\n        // 将订单信息保存在 redis 中\n        // redisKey\n        String redisKey = ORDER_PAY + \":\" + orderPay.getOrderId();\n        orderPay.setOrderStatus(Consts.ORDER_STATUS_NOPAY.toString());\n        try {\n            String orderPayJson = MapperUtil.obj2json(orderPay);\n            if (orderPayJson != null) {\n                redisCacheManager.set(redisKey, orderPayJson);\n                redisCacheManager.expire(redisKey, 60 * 60 * 2);\n            }\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n\n        return response;\n    }\n\n    @Transactional\n    @Override\n    public int updateOrderStatus(String orderId, Integer orderStatus) {\n\n        // 修改缓存状态\n        String redisKey = ORDER_PAY + \":\" + orderId;\n\n        // 更新缓存\n        String orderPayJson = (String) redisCacheManager.get(redisKey);\n\n        if (orderPayJson != null) {\n            try {\n                OrderPay orderPay = MapperUtil.json2pojo(orderPayJson, OrderPay.class);\n                orderPay.setOrderStatus((Consts.ORDER_STATUS_PAY).toString());\n                String newPayJson = MapperUtil.obj2json(orderPay);\n                if (newPayJson != null) {\n                    redisCacheManager.set(redisKey, newPayJson);\n                }\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n\n        return tbOrderMapper.updateOrderStatus(orderId, orderStatus);\n    }\n\n    @Override\n    public TradeStatus getOrderStatus(String orderId) {\n\n        // 一定要在创建AlipayTradeService之前设置参数\n        Configs.init(\"zfbinfo.properties\");\n\n        AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();\n\n        // (必填) 商户订单号，通过此商户订单号查询当面付的交易状态\n        String outTradeNo = orderId;\n        AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder()\n                .setOutTradeNo(outTradeNo);\n        AlipayF2FQueryResult result = tradeService.queryTradeResult(builder);\n        TradeStatus tradeStatus = result.getTradeStatus();\n        return tradeStatus;\n\n    }\n\n    @Override\n    public BaseResult getOrderList(String userId, int page, int size) {\n\n        // 设置 PageHelper\n        PageHelper.startPage(page, size);\n\n        PageOrder pageOrder = new PageOrder();\n        List<Order> orders = new ArrayList<>();\n\n        List<TbOrder> tbOrderList = tbOrderMapper.selectByUserId(userId);\n        for (TbOrder tbOrder : tbOrderList) {\n            Order order = new Order();\n            // 订单id\n            order.setOrderId(tbOrder.getId());\n            // 会员id\n            order.setUserId(tbOrder.getUserId().toString());\n            // 订单状态\n            order.setOrderStatus(tbOrder.getStatus());\n            // 创建时间\n            SimpleDateFormat simpleDateFormat = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n            String created = simpleDateFormat.format(tbOrder.getCreated());\n            order.setCreateDate(created);\n            // 订单支付时间\n            if (tbOrder.getPaymentTime() != null) {\n                String payDate = simpleDateFormat.format(tbOrder.getPaymentTime());\n                order.setPayDate(payDate);\n            }\n            // 订单发货时间\n            if (tbOrder.getConsignTime() != null) {\n                String consignDate = simpleDateFormat.format(tbOrder.getConsignTime());\n                order.setConsignDate(consignDate);\n            }\n            // 订单关闭时间\n            if (tbOrder.getCloseTime() != null) {\n                String closeDate = simpleDateFormat.format(tbOrder.getCloseTime());\n                order.setCloseDate(closeDate);\n            }\n            // 订单完成时间\n            if (tbOrder.getEndTime() != null && tbOrder.getStatus() == 4) {\n                String endDate = simpleDateFormat.format(tbOrder.getEndTime());\n                order.setFinishDate(endDate);\n            }\n            // 地址\n            TbOrderShipping tbOrderShipping = tbOrderShippingMapper.selectByPrimaryKey(tbOrder.getId());\n            TbAddress tbAddress = new TbAddress();\n            tbAddress.setUserName(tbOrderShipping.getReceiverName());\n            tbAddress.setStreetName(tbOrderShipping.getReceiverAddress());\n            tbAddress.setTel(tbOrderShipping.getReceiverPhone());\n            order.setTbAddress(tbAddress);\n            // 订单总计\n            order.setOrderTotal(tbOrder.getPayment());\n            // 订单商品列表\n            List<TbOrderItem> tbOrderItemList = tbOrderItemMapper.selectByOrderId(tbOrder.getId());\n            List<CartProduct> cartProductList = new ArrayList<>();\n            for (TbOrderItem tbOrderItem : tbOrderItemList) {\n                CartProduct cartProduct = new CartProduct();\n                cartProduct.setProductId(Long.parseLong(tbOrderItem.getItemId()));\n                cartProduct.setProductName(tbOrderItem.getTitle());\n                cartProduct.setSalePrice(tbOrderItem.getPrice());\n                cartProduct.setProductNum(tbOrderItem.getNum());\n                cartProduct.setProductImg(tbOrderItem.getPicPath());\n                cartProductList.add(cartProduct);\n            }\n            order.setGoodsList(cartProductList);\n            orders.add(order);\n        }\n\n        PageInfo<Order> pageInfo = new PageInfo<>(orders);\n        pageOrder.setTotal(tbOrderMapper.getMemberOrderCount(userId));\n        pageOrder.setData(orders);\n\n        return BaseResult.success(pageOrder);\n    }\n\n    @Transactional\n    @Override\n    public BaseResult confirmReceipt(Order order) {\n        // 会员 id\n        String userId = order.getUserId();\n\n        // 订单 id\n        String orderId = order.getOrderId();\n\n        // 请求信息为空\n        if (StringUtils.isBlank(userId) || StringUtils.isBlank(orderId)) {\n            return BaseResult.fail(\"操作异常\");\n        }\n\n        // 查询订单操作是否正常\n        TbOrder tbOrder = tbOrderMapper.selectByUserIdAndOrderId(userId, orderId);\n        if (tbOrder == null) {\n            return BaseResult.fail(\"操作异常\");\n        }\n\n        // 确认收货，修改数据库 status 字段\n        tbOrderMapper.confirmReceipt(order.getOrderId());\n        return BaseResult.success(\"确认收货成功\");\n    }\n\n    @Override\n    public BaseResult deleteService(Order order) {\n        // 会员 id\n        String userId = order.getUserId();\n\n        // 订单 id\n        String orderId = order.getOrderId();\n\n        // 请求信息为空\n        if (StringUtils.isBlank(userId) || StringUtils.isBlank(orderId)) {\n            return BaseResult.fail(\"操作异常\");\n        }\n\n        // 查询订单操作是否正常\n        TbOrder tbOrder = tbOrderMapper.selectByUserIdAndOrderId(userId, orderId);\n        if (tbOrder == null) {\n            return BaseResult.fail(\"操作异常\");\n        }\n\n        // 删除订单\n        tbOrderMapper.deleteByPrimaryKey(orderId);\n\n        // 删除订单商品\n        tbOrderItemMapper.deleteByOrderId(orderId);\n\n        // 删除订单物流信息\n        tbOrderShippingMapper.deleteByPrimaryKey(orderId);\n        return BaseResult.success(\"删除订单成功\");\n    }\n\n    @Transactional\n    @Override\n    public int paySuccess(String orderId) {\n        // 修改支付时间和状态\n        return tbOrderMapper.updatePayTimeAndStatus(orderId);\n    }\n\n    @Override\n    public BaseResult cancelService(Order order) {\n        // 修改关闭时间和状态\n        tbOrderMapper.cancelOrder(order.getOrderId());\n\n        // 修改商品库存\n        // 查询出该订单的所有商品集合\n        List<TbOrderItem> tbOrderItemList = tbOrderItemMapper.selectByOrderId(order.getOrderId());\n        for (TbOrderItem tbOrderItem : tbOrderItemList) {\n            String productId = tbOrderItem.getItemId();\n            int productNum = tbOrderItem.getNum();\n            // 增加商品库存\n            tbItemMapper.addItemNum(productId, productNum);\n            // 更新 Redis 缓存\n            String redisKey = PRODUCT_ITEM + \":\" + productId;\n            redisCacheManager.del(redisKey);\n        }\n        return BaseResult.success(\"取消订单成功\");\n    }\n\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/java/com/yuu/ymall/web/api/service/impl/ProductServiceImpl.java",
    "content": "package com.yuu.ymall.web.api.service.impl;\n\nimport com.google.common.collect.Lists;\nimport com.yuu.ymall.commons.dto.BaseResult;\nimport com.yuu.ymall.commons.redis.RedisCacheManager;\nimport com.yuu.ymall.commons.utils.MapperUtil;\nimport com.yuu.ymall.domain.TbItem;\nimport com.yuu.ymall.domain.TbItemCat;\nimport com.yuu.ymall.domain.TbItemDesc;\nimport com.yuu.ymall.web.api.domain.ESItem;\nimport com.yuu.ymall.web.api.dto.CateProductsResult;\nimport com.yuu.ymall.web.api.dto.CategoryProductPageInfo;\nimport com.yuu.ymall.web.api.dto.ProductDet;\nimport com.yuu.ymall.web.api.mapper.TbItemCatMapper;\nimport com.yuu.ymall.web.api.mapper.TbItemDescMapper;\nimport com.yuu.ymall.web.api.mapper.TbItemMapper;\nimport com.yuu.ymall.web.api.repositories.ItemRepository;\nimport com.yuu.ymall.web.api.service.ProductService;\nimport org.apache.commons.lang3.StringUtils;\nimport org.elasticsearch.action.search.SearchResponse;\nimport org.elasticsearch.index.query.QueryBuilders;\nimport org.elasticsearch.search.SearchHit;\nimport org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;\nimport org.elasticsearch.search.fetch.subphase.highlight.HighlightField;\nimport org.elasticsearch.search.sort.SortBuilders;\nimport org.elasticsearch.search.sort.SortOrder;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.PageRequest;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.elasticsearch.core.ElasticsearchTemplate;\nimport org.springframework.data.elasticsearch.core.SearchResultMapper;\nimport org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;\nimport org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;\nimport org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;\nimport org.springframework.stereotype.Service;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * @author by Yuu\n * @classname ProductServiceImpl\n * @date 2019/7/3 18:52\n */\n@Service\npublic class ProductServiceImpl implements ProductService {\n\n    @Autowired\n    private TbItemMapper tbItemMapper;\n\n    @Autowired\n    private TbItemDescMapper tbItemDescMapper;\n\n    @Autowired\n    private RedisCacheManager redisCacheManager;\n\n    @Autowired\n    private ItemRepository itemRepository;\n\n    @Autowired\n    private ElasticsearchTemplate elasticsearchTemplate;\n\n    @Autowired\n    private TbItemCatMapper tbItemCatMapper;\n\n    @Value(\"${PRODUCT_ITEM}\")\n    private String PRODUCT_ITEM;\n\n    @Value(\"${ITEM_EXPIRE}\")\n    private int ITEM_EXPIRE;\n\n    @Value(\"${CATE_PRODUCTS}\")\n    private String CATE_PRODUCTS;\n\n    @Override\n    public BaseResult getProductDet(Long productId) {\n\n        // Redis 商品详情缓存 key\n        String redisKey = PRODUCT_ITEM + \":\" + productId;\n\n        // 先查询\n        String redisJson = (String) redisCacheManager.get(redisKey);\n        if (redisJson != null) {\n            try {\n                ProductDet productDet = MapperUtil.json2pojo(redisJson, ProductDet.class);\n                // 重置商品缓存时间\n                redisCacheManager.expire(redisKey, ITEM_EXPIRE);\n                return BaseResult.success(productDet);\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n\n        // 没有缓存，从数据库中查询\n        TbItem tbItem = tbItemMapper.selectByPrimaryKey(productId);\n        if (tbItem != null) {\n            ProductDet productDet = new ProductDet();\n            productDet.setProductId(tbItem.getId());\n            productDet.setProductName(tbItem.getTitle());\n            productDet.setSubTitle(tbItem.getSellPoint());\n            productDet.setSalePrice(tbItem.getPrice());\n            if (tbItem.getLimitNum() > tbItem.getNum()) {\n                tbItem.setLimitNum(tbItem.getNum());\n            }\n            productDet.setLimitNum(tbItem.getLimitNum());\n            productDet.setNum(tbItem.getNum());\n            productDet.setProductImageBig(tbItem.getImages()[0]);\n\n            // 查询商品详情\n            TbItemDesc tbItemDesc = tbItemDescMapper.selectByPrimaryKey(productId);\n            if (tbItemDesc != null) {\n                productDet.setDetail(tbItemDesc.getItemDesc());\n            }\n\n            // 设置商品小图\n            productDet.setProductImageSmall(tbItem.getImages());\n\n            // 把结果添加至缓存中\n            try {\n                String productDetJson = MapperUtil.obj2json(productDet);\n                redisCacheManager.set(redisKey, productDetJson);\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n\n            return BaseResult.success(productDet);\n        }\n\n        return BaseResult.fail(\"获取商品详细信息失败\");\n    }\n\n    @Override\n    public BaseResult getByCategory(CategoryProductPageInfo categoryProductPageInfo) {\n\n        CateProductsResult cateProductsResult = new CateProductsResult();\n\n        // 分类 id\n        Long cid = categoryProductPageInfo.getCid();\n\n        // 查询 key\n        String key = categoryProductPageInfo.getKey();\n\n        // 排序类型 1 综合排序 2 销量排序 3 价格从低到高 4 价格从高到低\n        String sort = categoryProductPageInfo.getSort();\n\n        // 第几页\n        Integer page = categoryProductPageInfo.getPage() - 1;\n\n        // 每页大小\n        Integer size = categoryProductPageInfo.getSize();\n\n        // 最小值\n        Integer priceGt = categoryProductPageInfo.getPriceGt();\n\n        // 最大值\n        Integer priceLt = categoryProductPageInfo.getPriceLte();\n\n        // ElasticSearch 查询\n        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();\n        if (cid != null) {\n            // 查询该分类所有子分类\n            List<TbItemCat> tbItemCats = tbItemCatMapper.selectTbCatByPid(cid);\n            List<Long> cids = new ArrayList<>();\n            for (TbItemCat tbItemCat : tbItemCats) {\n                Long id = tbItemCat.getId();\n                cids.add(id);\n            }\n            cids.add(cid);\n            queryBuilder.withQuery(QueryBuilders.termsQuery(\"cid\", cids));\n        }\n        if (key != null) {\n            queryBuilder.withQuery(QueryBuilders.multiMatchQuery(key, \"productName\", \"subTitle\"));\n            queryBuilder.withHighlightFields(new HighlightBuilder.Field(\"productName\"));\n        }\n        if (priceGt != null && priceLt != null) {\n            queryBuilder.withQuery(QueryBuilders.rangeQuery(\"salePrice\").gte(priceGt).lte(priceLt));\n        }\n        if (StringUtils.isNotBlank(categoryProductPageInfo.getSort())) {\n            if (\"2\".equals(sort)) {\n                queryBuilder.withSort(SortBuilders.fieldSort(\"orderNum\").order(SortOrder.DESC));\n            } else if (\"3\".equals(sort)) {\n                queryBuilder.withSort(SortBuilders.fieldSort(\"salePrice\").order(SortOrder.ASC));\n            } else if (\"4\".equals(sort)) {\n                queryBuilder.withSort(SortBuilders.fieldSort(\"salePrice\").order(SortOrder.DESC));\n            }\n        }\n        queryBuilder.withPageable(PageRequest.of(page, size));\n\n        // 执行搜索\n        List<ESItem> esItemList = new ArrayList<>();\n        long total = 0L;\n\n        // 按关键字查询\n        if (key != null) {\n            AggregatedPage<ESItem> esItems = elasticsearchTemplate.queryForPage(queryBuilder.build(), ESItem.class, new SearchResultMapper() {\n                @Override\n                public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {\n                    List<ESItem> esItems = new ArrayList<>();\n                    for (SearchHit hit : response.getHits()) {\n                        if (response.getHits().getHits().length <= 0) {\n                            return null;\n                        }\n                        Map<String, Object> source = hit.getSource();\n                        ESItem esItem = new ESItem();\n                        Long id = (Long)source.get(\"id\");\n                        esItem.setId(id);\n                        int cid = (int) source.get(\"cid\");\n                        esItem.setCid((long)cid);\n                        Long productId = (Long) source.get(\"productId\");\n                        esItem.setProductId(productId);\n                        String subTitle = (String) source.get(\"subTitle\");\n                        esItem.setSubTitle(subTitle);\n                        Double salePrice = (Double) source.get(\"salePrice\");\n                        esItem.setSalePrice(salePrice);\n                        String picUrl = (String) source.get(\"picUrl\");\n                        esItem.setPicUrl(picUrl);\n                        int orderNum = (int) source.get(\"orderNum\");\n                        esItem.setOrderNum(orderNum);\n                        int limit = (int) source.get(\"limit\");\n                        esItem.setLimit(limit);\n                        HighlightField productName = hit.getHighlightFields().get(\"productName\");\n                        if (productName != null) {\n                            esItem.setProductName(productName.fragments()[0].toString());\n                        }\n                        esItems.add(esItem);\n                    }\n                    if (esItems.size() > 0) {\n                        return new AggregatedPageImpl<>((List<T>) esItems);\n                    }\n                    return null;\n                }\n            });\n            if (esItems != null) {\n                total = esItems.getTotalElements();\n                esItemList = esItems.getContent();\n            }\n        }\n\n        // 全部商品\n        if (StringUtils.isBlank(key) && cid == null) {\n            Iterable<ESItem> esItems = itemRepository.search(queryBuilder.build());\n            if (esItems != null) {\n                esItemList = Lists.newArrayList(esItems);\n                total = esItemList.size();\n            }\n        }\n\n        // 按分类查询\n        if (cid != null) {\n            Page<ESItem> search = itemRepository.search(queryBuilder.build());\n            if (search != null) {\n                esItemList = search.getContent();\n                total = search.getTotalElements();\n            }\n        }\n\n        cateProductsResult.setTotal(total);\n        cateProductsResult.setData(esItemList);\n\n        return BaseResult.success(cateProductsResult);\n    }\n\n    @Override\n    public BaseResult getQuickSearch(String key) {\n         // 构建查询条件\n        NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder();\n        // 添加基本查询条件\n        searchQueryBuilder.withQuery(QueryBuilders.matchQuery(\"productName\", key));\n        // 初始化分页参数\n        int page = 0;\n        int size = 5;\n        // 设置分页参数\n        searchQueryBuilder.withPageable(PageRequest.of(page, size));\n        Page<ESItem> searchs = itemRepository.search(searchQueryBuilder.build());\n        List<ESItem> esItems = searchs.getContent();\n        return BaseResult.success(esItems);\n    }\n}\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/generatorConfig.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE generatorConfiguration\n        PUBLIC \"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN\"\n        \"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd\">\n\n<generatorConfiguration>\n    <!-- 引入数据库连接配置 -->\n    <properties resource=\"ymall.properties\"/>\n\n    <context id=\"Mysql\" targetRuntime=\"MyBatis3Simple\" defaultModelType=\"flat\">\n        <property name=\"beginningDelimiter\" value=\"`\"/>\n        <property name=\"endingDelimiter\" value=\"`\"/>\n\n        <!-- 去除自动生成的注释 -->\n        <commentGenerator>\n            <property name=\"suppressAllComments\" value=\"true\" />\n        </commentGenerator>\n\n        <!-- 配置数据库连接 -->\n        <jdbcConnection\n                driverClass=\"${jdbc.driverClass}\"\n                connectionURL=\"${jdbc.connectionURL}\"\n                userId=\"${jdbc.username}\"\n                password=\"${jdbc.password}\">\n        </jdbcConnection>\n\n        <!-- 配置实体类存放路径 -->\n        <javaModelGenerator targetPackage=\"com.yuu.ymall.domain\" targetProject=\"src/main/java\"/>\n\n        <!-- 配置 XML 存放路径 -->\n        <sqlMapGenerator targetPackage=\"mapper\" targetProject=\"src/main/resources\"/>\n\n        <!-- 配置 DAO 存放路径 -->\n        <javaClientGenerator\n                targetPackage=\"com.yuu.ymall.web.api.mapper\"\n                targetProject=\"src/main/java\"\n                type=\"XMLMAPPER\"/>\n\n        <!-- 配置需要指定生成的数据库和表，% 代表所有表 -->\n        <table tableName=\"%\" enableCountByExample=\"true\" enableDeleteByExample=\"true\"\n               enableSelectByExample=\"true\" enableUpdateByExample=\"true\">\n            <!-- mysql 配置 -->\n            <generatedKey column=\"id\" sqlStatement=\"Mysql\" identity=\"true\"/>\n        </table>\n    </context>\n\n</generatorConfiguration>"
  },
  {
    "path": "ymall-web-api/src/main/resources/log4j.properties",
    "content": "log4j.rootLogger=INFO, console, file\n\nlog4j.appender.console=org.apache.log4j.ConsoleAppender\nlog4j.appender.console.layout=org.apache.log4j.PatternLayout\nlog4j.appender.console.layout.ConversionPattern=%d %p [%c] - %m%n\n\nlog4j.appender.file=org.apache.log4j.DailyRollingFileAppender\nlog4j.appender.file.File=logs/log.log\nlog4j.appender.file.layout=org.apache.log4j.PatternLayout\nlog4j.appender.A3.MaxFileSize=1024KB\nlog4j.appender.A3.MaxBackupIndex=10\nlog4j.appender.file.layout.ConversionPattern=%d %p [%c] - %m%n"
  },
  {
    "path": "ymall-web-api/src/main/resources/log4j2.properties",
    "content": "appender.console.type = Console\nappender.console.name = console\nappender.console.layout.type = PatternLayout\n\nrootLogger.level = info\nrootLogger.appenderRef.console.ref = console\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbAddressMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbAddressMapper\">\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbAddress\">\n    <id column=\"id\" jdbcType=\"BIGINT\" property=\"id\" />\n    <result column=\"user_id\" jdbcType=\"BIGINT\" property=\"userId\" />\n    <result column=\"user_name\" jdbcType=\"VARCHAR\" property=\"userName\" />\n    <result column=\"tel\" jdbcType=\"VARCHAR\" property=\"tel\" />\n    <result column=\"state\" jdbcType=\"VARCHAR\" property=\"state\" />\n    <result column=\"city\" jdbcType=\"VARCHAR\" property=\"city\" />\n    <result column=\"district\" jdbcType=\"VARCHAR\" property=\"district\" />\n    <result column=\"street_name\" jdbcType=\"VARCHAR\" property=\"streetName\" />\n    <result column=\"is_default\" jdbcType=\"BIT\" property=\"isDefault\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\">\n    delete from tb_address\n    where id = #{id,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbAddress\">\n    <selectKey keyProperty=\"id\" order=\"AFTER\" resultType=\"java.lang.Long\">\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_address (user_id, user_name, tel, state, city,  district,\n      street_name, is_default)\n    values (#{userId,jdbcType=BIGINT}, #{userName,jdbcType=VARCHAR}, #{tel,jdbcType=VARCHAR}, #{state,jdbcType=VARCHAR}, #{city,jdbcType=VARCHAR}, #{district,jdbcType=VARCHAR},\n      #{streetName,jdbcType=VARCHAR}, #{isDefault,jdbcType=BIT})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbAddress\">\n    update tb_address\n    set user_id = #{userId,jdbcType=BIGINT},\n      user_name = #{userName,jdbcType=VARCHAR},\n      tel = #{tel,jdbcType=VARCHAR},\n      state = #{state,jdbcType=VARCHAR},\n      city = #{city,jdbcType=VARCHAR} ,\n      district = #{district,jdbcType=VARCHAR} ,\n      street_name = #{streetName,jdbcType=VARCHAR},\n      is_default = #{isDefault,jdbcType=BIT}\n    where id = #{id,jdbcType=BIGINT}\n  </update>\n    <!-- 会员修改地址 -->\n    <update id=\"updateAddress\">\n        update tb_address\n        set user_name = #{userName},\n            tel = #{tel},\n            state = #{state} ,\n            city = #{city} ,\n            district = #{district},\n            street_name = #{streetName},\n            is_default = #{isDefault}\n        where id = #{id}\n    </update>\n    <select id=\"selectByPrimaryKey\" parameterType=\"java.lang.Long\" resultMap=\"BaseResultMap\">\n    select id, user_id, user_name, tel, state, city, district, street_name, is_default\n    from tb_address\n    where id = #{id,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\">\n    select id, user_id, user_name, tel, state, city, district, street_name, is_default\n    from tb_address\n  </select>\n\n    <!-- sql 片断 -->\n    <sql id=\"tbAddressBaseColumns\">\n        id,\n        user_name,\n        tel,\n        state,\n        city,\n        district,\n        street_name,\n        is_default\n    </sql>\n\n    <!-- 获取会员地址列表 -->\n    <select id=\"selectByUserId\" resultType=\"tbAddress\">\n        select <include refid=\"tbAddressBaseColumns\"/>\n        from tb_address\n        where user_id = #{userId}\n        order by is_default desc\n    </select>\n\n    <!-- 移除默认地址 -->\n    <update id=\"removeDefault\">\n      update tb_address set is_default = false where user_id = #{userId}\n    </update>\n\n\n</mapper>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbExpressMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbExpressMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbExpress\" >\n    <id column=\"id\" property=\"id\" jdbcType=\"INTEGER\" />\n    <result column=\"express_name\" property=\"expressName\" jdbcType=\"VARCHAR\" />\n    <result column=\"sort_order\" property=\"sortOrder\" jdbcType=\"INTEGER\" />\n    <result column=\"created\" property=\"created\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"updated\" property=\"updated\" jdbcType=\"TIMESTAMP\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Integer\" >\n    delete from tb_express\n    where id = #{id,jdbcType=INTEGER}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbExpress\" >\n    <selectKey resultType=\"java.lang.Integer\" keyProperty=\"id\" order=\"AFTER\" >\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_express (express_name, sort_order, created, \n      updated)\n    values (#{expressName,jdbcType=VARCHAR}, #{sortOrder,jdbcType=INTEGER}, #{created,jdbcType=TIMESTAMP}, \n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbExpress\" >\n    update tb_express\n    set express_name = #{expressName,jdbcType=VARCHAR},\n      sort_order = #{sortOrder,jdbcType=INTEGER},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=INTEGER}\n  </update>\n  <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.Integer\" >\n    select id, express_name, sort_order, created, updated\n    from tb_express\n    where id = #{id,jdbcType=INTEGER}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\" >\n    select id, express_name, sort_order, created, updated\n    from tb_express\n  </select>\n</mapper>"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbItemCatMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbItemCatMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbItemCat\" >\n    <id column=\"id\" property=\"id\" jdbcType=\"BIGINT\" />\n    <result column=\"parent_id\" property=\"parentId\" jdbcType=\"BIGINT\" />\n    <result column=\"name\" property=\"name\" jdbcType=\"VARCHAR\" />\n    <result column=\"status\" property=\"status\" jdbcType=\"INTEGER\" />\n    <result column=\"sort_order\" property=\"sortOrder\" jdbcType=\"INTEGER\" />\n    <result column=\"is_parent\" property=\"isParent\" jdbcType=\"BIT\" />\n    <result column=\"created\" property=\"created\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"updated\" property=\"updated\" jdbcType=\"TIMESTAMP\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\" >\n    delete from tb_item_cat\n    where id = #{id,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbItemCat\" >\n    <selectKey resultType=\"java.lang.Long\" keyProperty=\"id\" order=\"AFTER\" >\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_item_cat (parent_id, name, status,\n      sort_order, is_parent, created,\n      updated)\n    values (#{parentId,jdbcType=BIGINT}, #{name,jdbcType=VARCHAR}, #{status,jdbcType=INTEGER},\n      #{sortOrder,jdbcType=INTEGER}, #{isParent,jdbcType=BIT}, #{created,jdbcType=TIMESTAMP},\n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbItemCat\" >\n    update tb_item_cat\n    set parent_id = #{parentId,jdbcType=BIGINT},\n      name = #{name,jdbcType=VARCHAR},\n      status = #{status,jdbcType=INTEGER},\n      sort_order = #{sortOrder,jdbcType=INTEGER},\n      is_parent = #{isParent,jdbcType=BIT},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=BIGINT}\n  </update>\n  <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.Long\" >\n    select id, parent_id, name, status, sort_order, is_parent, created, updated\n    from tb_item_cat\n    where id = #{id,jdbcType=BIGINT}\n  </select>\n\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\" >\n    select id, parent_id, name\n    from tb_item_cat\n    where status != 0\n    order by sort_order\n  </select>\n\n    <!-- 根据分类 id, 获取所有子分类 -->\n    <select id=\"selectTbCatByPid\" resultType=\"tbItemCat\">\n        select id, name\n        from tb_item_cat\n        where parent_id = #{id}\n        order by sort_order\n    </select>\n</mapper>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbItemDescMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbItemDescMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbItemDesc\" >\n    <id column=\"item_id\" property=\"itemId\" jdbcType=\"BIGINT\" />\n    <result column=\"created\" property=\"created\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"updated\" property=\"updated\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"item_desc\" property=\"itemDesc\" jdbcType=\"LONGVARCHAR\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\" >\n    delete from tb_item_desc\n    where item_id = #{itemId,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbItemDesc\" >\n    insert into tb_item_desc (item_id, created, updated, \n      item_desc)\n    values (#{itemId,jdbcType=BIGINT}, #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP}, \n      #{itemDesc,jdbcType=LONGVARCHAR})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbItemDesc\" >\n    update tb_item_desc\n    set created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP},\n      item_desc = #{itemDesc,jdbcType=LONGVARCHAR}\n    where item_id = #{itemId,jdbcType=BIGINT}\n  </update>\n  <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.Long\" >\n    select item_id, created, updated, item_desc\n    from tb_item_desc\n    where item_id = #{itemId,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\" >\n    select item_id, created, updated, item_desc\n    from tb_item_desc\n  </select>\n</mapper>"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbItemMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbItemMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbItem\" >\n    <id column=\"id\" property=\"id\" jdbcType=\"BIGINT\" />\n    <result column=\"title\" property=\"title\" jdbcType=\"VARCHAR\" />\n    <result column=\"sell_point\" property=\"sellPoint\" jdbcType=\"VARCHAR\" />\n    <result column=\"price\" property=\"price\" jdbcType=\"DECIMAL\" />\n    <result column=\"num\" property=\"num\" jdbcType=\"INTEGER\" />\n    <result column=\"limit_num\" property=\"limitNum\" jdbcType=\"INTEGER\" />\n    <result column=\"image\" property=\"image\" jdbcType=\"VARCHAR\" />\n    <result column=\"cid\" property=\"cid\" jdbcType=\"BIGINT\" />\n    <result column=\"status\" property=\"status\" jdbcType=\"INTEGER\" />\n    <result column=\"created\" property=\"created\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"updated\" property=\"updated\" jdbcType=\"TIMESTAMP\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\" >\n    delete from tb_item\n    where id = #{id,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbItem\" >\n    <selectKey resultType=\"java.lang.Long\" keyProperty=\"id\" order=\"AFTER\" >\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_item (title, sell_point, price,\n      num, limit_num, image,\n      cid, status, created,\n      updated)\n    values (#{title,jdbcType=VARCHAR}, #{sellPoint,jdbcType=VARCHAR}, #{price,jdbcType=DECIMAL},\n      #{num,jdbcType=INTEGER}, #{limitNum,jdbcType=INTEGER}, #{image,jdbcType=VARCHAR},\n      #{cid,jdbcType=BIGINT}, #{status,jdbcType=INTEGER}, #{created,jdbcType=TIMESTAMP},\n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n    <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbItem\" >\n    update tb_item\n    set title = #{title,jdbcType=VARCHAR},\n      sell_point = #{sellPoint,jdbcType=VARCHAR},\n      price = #{price,jdbcType=DECIMAL},\n      num = #{num,jdbcType=INTEGER},\n      limit_num = #{limitNum,jdbcType=INTEGER},\n      image = #{image,jdbcType=VARCHAR},\n      cid = #{cid,jdbcType=BIGINT},\n      status = #{status,jdbcType=INTEGER},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=BIGINT}\n  </update>\n\n    <!-- 减少商品库存 -->\n    <update id=\"reduceItemNum\">\n      update tb_item\n      set num = num - #{num}\n      where id = #{productId}\n    </update>\n\n    <!-- 商品库存 +1 -->\n    <update id=\"addItemNum\">\n        update tb_item\n        set num = num + #{num}\n        where id = #{productId}\n    </update>\n\n    <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.Long\" >\n    select id, title, sell_point, price, num, limit_num, image, cid, status, created,\n    updated\n    from tb_item\n    where id = #{id,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\" >\n    select id, title, sell_point, price, num, limit_num, image, cid, status, created,\n    updated\n    from tb_item\n  </select>\n</mapper>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbMemberMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbMemberMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbMember\" >\n    <id column=\"id\" property=\"id\" jdbcType=\"BIGINT\" />\n    <result column=\"username\" property=\"username\" jdbcType=\"VARCHAR\" />\n    <result column=\"password\" property=\"password\" jdbcType=\"VARCHAR\" />\n    <result column=\"phone\" property=\"phone\" jdbcType=\"VARCHAR\" />\n    <result column=\"email\" property=\"email\" jdbcType=\"VARCHAR\" />\n    <result column=\"sex\" property=\"sex\" jdbcType=\"VARCHAR\" />\n    <result column=\"state\" property=\"state\" jdbcType=\"INTEGER\" />\n    <result column=\"file\" property=\"file\" jdbcType=\"VARCHAR\" />\n    <result column=\"description\" property=\"description\" jdbcType=\"VARCHAR\" />\n    <result column=\"created\" property=\"created\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"updated\" property=\"updated\" jdbcType=\"TIMESTAMP\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\" >\n    delete from tb_member\n    where id = #{id,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbMember\" >\n    <selectKey resultType=\"java.lang.Long\" keyProperty=\"id\" order=\"AFTER\" >\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_member (username, password, phone,\n      email, sex, state,\n      file, description, created,\n      updated)\n    values (#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{phone,jdbcType=VARCHAR},\n      #{email,jdbcType=VARCHAR}, #{sex,jdbcType=VARCHAR}, #{state,jdbcType=INTEGER},\n      #{file,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{created,jdbcType=TIMESTAMP},\n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbMember\" >\n    update tb_member\n    set username = #{username,jdbcType=VARCHAR},\n      password = #{password,jdbcType=VARCHAR},\n      phone = #{phone,jdbcType=VARCHAR},\n      email = #{email,jdbcType=VARCHAR},\n      sex = #{sex,jdbcType=VARCHAR},\n      state = #{state,jdbcType=INTEGER},\n      file = #{file,jdbcType=VARCHAR},\n      description = #{description,jdbcType=VARCHAR},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=BIGINT}\n  </update>\n\n    <!-- 会员根据手机号或邮箱修改密码 -->\n    <update id=\"updatePassword\">\n      update tb_member\n      set password = #{password}\n      where phone = #{account} OR email = #{account}\n    </update>\n\n    <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.Long\" >\n    select id, username, password, phone, email, sex, state, file, description, created,\n    updated\n    from tb_member\n    where id = #{id,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\" >\n    select id, username, password, phone, email, sex, state, file, description, created,\n    updated\n    from tb_member\n  </select>\n\n    <!-- SQL 片断 -->\n    <sql id=\"tbMemberBaseColumns\">\n        a.id,\n        a.username,\n        a.password,\n        a.phone,\n        a.email,\n        a.sex,\n        a.state,\n        a.file,\n        a.description,\n        a.created,\n        a.updated\n    </sql>\n\n    <!-- 通过手机号查询会员 -->\n    <select id=\"selectByPhone\" resultType=\"tbMember\">\n        select <include refid=\"tbMemberBaseColumns\"/>\n        from tb_member as a\n        where phone = #{phone}\n    </select>\n\n    <!-- 会员注册 -->\n    <insert id=\"register\" parameterType=\"tbMember\">\n        insert into tb_member(phone, password, state, created, updated)\n        values (#{phone}, #{password}, #{state}, #{created}, #{updated})\n    </insert>\n\n    <!-- 根据邮箱查询会员 -->\n    <select id=\"selectByEmail\" resultMap=\"BaseResultMap\">\n      select <include refid=\"tbMemberBaseColumns\"/>\n      from tb_member as a\n      where email = #{email}\n    </select>\n\n    <!-- 根据手机号或邮箱查询会员 -->\n    <select id=\"selectByPhoneOrEmail\" resultType=\"com.yuu.ymall.domain.TbMember\">\n        select <include refid=\"tbMemberBaseColumns\"/>\n        from tb_member as a\n        where phone = #{account} or email = #{account}\n    </select>\n</mapper>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbOrderItemMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbOrderItemMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbOrderItem\" >\n    <id column=\"id\" property=\"id\" jdbcType=\"VARCHAR\" />\n    <result column=\"item_id\" property=\"itemId\" jdbcType=\"VARCHAR\" />\n    <result column=\"order_id\" property=\"orderId\" jdbcType=\"VARCHAR\" />\n    <result column=\"num\" property=\"num\" jdbcType=\"INTEGER\" />\n    <result column=\"title\" property=\"title\" jdbcType=\"VARCHAR\" />\n    <result column=\"price\" property=\"price\" jdbcType=\"DECIMAL\" />\n    <result column=\"total_fee\" property=\"totalFee\" jdbcType=\"DECIMAL\" />\n    <result column=\"pic_path\" property=\"picPath\" jdbcType=\"VARCHAR\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\" >\n    delete from tb_order_item\n    where id = #{id,jdbcType=VARCHAR}\n  </delete>\n\n    <!-- 根据订单 id 删除订单商品 -->\n    <delete id=\"deleteByOrderId\">\n        delete from tb_order_item\n        where order_id = #{orderId}\n    </delete>\n\n    <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbOrderItem\" >\n    <selectKey resultType=\"java.lang.String\" keyProperty=\"id\" order=\"AFTER\" >\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_order_item (id, item_id, order_id, num,\n      title, price, total_fee,\n      pic_path)\n    values (#{id,jdbcType=VARCHAR}, #{itemId,jdbcType=VARCHAR}, #{orderId,jdbcType=VARCHAR}, #{num,jdbcType=INTEGER},\n      #{title,jdbcType=VARCHAR}, #{price,jdbcType=DECIMAL}, #{totalFee,jdbcType=DECIMAL},\n      #{picPath,jdbcType=VARCHAR})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbOrderItem\" >\n    update tb_order_item\n    set item_id = #{itemId,jdbcType=VARCHAR},\n      order_id = #{orderId,jdbcType=VARCHAR},\n      num = #{num,jdbcType=INTEGER},\n      title = #{title,jdbcType=VARCHAR},\n      price = #{price,jdbcType=DECIMAL},\n      total_fee = #{totalFee,jdbcType=DECIMAL},\n      pic_path = #{picPath,jdbcType=VARCHAR}\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n  <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.String\" >\n    select id, item_id, order_id, num, title, price, total_fee, pic_path\n    from tb_order_item\n    where id = #{id,jdbcType=VARCHAR}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\" >\n    select id, item_id, order_id, num, title, price, total_fee, pic_path\n    from tb_order_item\n  </select>\n\n    <!-- sql 片断 -->\n    <sql id=\"tbOrderItemBaseColumns\">\n        id,\n        item_id,\n        order_id,\n        num,\n        title,\n        price,\n        total_fee,\n        pic_path\n    </sql>\n    <!-- 根据订单 id,查询订单商品 -->\n    <select id=\"selectByOrderId\" resultMap=\"BaseResultMap\">\n      select <include refid=\"tbOrderItemBaseColumns\"/>\n      from tb_order_item\n      where order_id = #{orderId}\n    </select>\n</mapper>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbOrderMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbOrderMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbOrder\" >\n    <id column=\"id\" property=\"id\" jdbcType=\"VARCHAR\" />\n    <result column=\"payment\" property=\"payment\" jdbcType=\"DECIMAL\" />\n    <result column=\"payment_type\" property=\"paymentType\" jdbcType=\"INTEGER\" />\n    <result column=\"post_fee\" property=\"postFee\" jdbcType=\"DECIMAL\" />\n    <result column=\"status\" property=\"status\" jdbcType=\"INTEGER\" />\n    <result column=\"payment_time\" property=\"paymentTime\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"consign_time\" property=\"consignTime\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"end_time\" property=\"endTime\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"close_time\" property=\"closeTime\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"shipping_name\" property=\"shippingName\" jdbcType=\"VARCHAR\" />\n    <result column=\"shipping_code\" property=\"shippingCode\" jdbcType=\"VARCHAR\" />\n    <result column=\"user_id\" property=\"userId\" jdbcType=\"BIGINT\" />\n    <result column=\"buyer_message\" property=\"buyerMessage\" jdbcType=\"VARCHAR\" />\n    <result column=\"buyer_nick\" property=\"buyerNick\" jdbcType=\"VARCHAR\" />\n    <result column=\"buyer_comment\" property=\"buyerComment\" jdbcType=\"BIT\" />\n    <result column=\"created\" property=\"created\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"updated\" property=\"updated\" jdbcType=\"TIMESTAMP\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\" >\n    delete from tb_order\n    where id = #{id,jdbcType=VARCHAR}\n  </delete>\n\n    <!-- 取消订单 -->\n    <update id=\"cancelOrder\">\n        update tb_order\n        set close_time = now(), status = 5\n        where id = #{orderId}\n    </update>\n\n    <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbOrder\" >\n    insert into tb_order (id, payment, payment_type, post_fee,\n      status, payment_time, consign_time,\n      end_time, close_time, shipping_name,\n      shipping_code, user_id, buyer_message,\n      buyer_nick, buyer_comment, created,\n      updated)\n    values (#{id, jdbcType=VARCHAR}, #{payment,jdbcType=DECIMAL}, #{paymentType,jdbcType=INTEGER}, #{postFee,jdbcType=DECIMAL},\n      #{status,jdbcType=INTEGER}, #{paymentTime,jdbcType=TIMESTAMP}, #{consignTime,jdbcType=TIMESTAMP},\n      #{endTime,jdbcType=TIMESTAMP}, #{closeTime,jdbcType=TIMESTAMP}, #{shippingName,jdbcType=VARCHAR},\n      #{shippingCode,jdbcType=VARCHAR}, #{userId,jdbcType=BIGINT}, #{buyerMessage,jdbcType=VARCHAR},\n      #{buyerNick,jdbcType=VARCHAR}, #{buyerComment,jdbcType=BIT}, #{created,jdbcType=TIMESTAMP},\n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbOrder\" >\n    update tb_order\n    set payment = #{payment,jdbcType=DECIMAL},\n      payment_type = #{paymentType,jdbcType=INTEGER},\n      post_fee = #{postFee,jdbcType=DECIMAL},\n      status = #{status,jdbcType=INTEGER},\n      payment_time = #{paymentTime,jdbcType=TIMESTAMP},\n      consign_time = #{consignTime,jdbcType=TIMESTAMP},\n      end_time = #{endTime,jdbcType=TIMESTAMP},\n      close_time = #{closeTime,jdbcType=TIMESTAMP},\n      shipping_name = #{shippingName,jdbcType=VARCHAR},\n      shipping_code = #{shippingCode,jdbcType=VARCHAR},\n      user_id = #{userId,jdbcType=BIGINT},\n      buyer_message = #{buyerMessage,jdbcType=VARCHAR},\n      buyer_nick = #{buyerNick,jdbcType=VARCHAR},\n      buyer_comment = #{buyerComment,jdbcType=BIT},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=VARCHAR}\n  </update>\n\n    <!-- 修改订单状态 -->\n    <update id=\"updateOrderStatus\">\n        update tb_order\n        set status = #{orderStatus}\n        where id = #{orderId}\n    </update>\n\n    <!-- 支付成功，修改支付时间和支付状态 -->\n    <update id=\"updatePayTimeAndStatus\">\n        update tb_order\n        set payment_time = now(), status = 2\n        where id = #{orderId}\n    </update>\n\n    <!-- 支付失败，修改关闭时间和支付状态 -->\n    <update id=\"updateCloseTimeAndStatus\">\n        update tb_order\n        set close_time = now, status = 5\n        where id = #{orderId}\n    </update>\n\n    <!-- 确认收货 -->\n    <update id=\"confirmReceipt\">\n        update tb_order\n        set end_time = now(), status = 4\n        where id = #{orderId}\n    </update>\n\n    <select  id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.String\" >\n    select id, payment, payment_type, post_fee, status, payment_time, consign_time, end_time,\n    close_time, shipping_name, shipping_code, user_id, buyer_message, buyer_nick, buyer_comment,\n    created, updated\n    from tb_order\n    where id = #{id,jdbcType=VARCHAR}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\" >\n    select id, payment, payment_type, post_fee, status, payment_time, consign_time, end_time,\n    close_time, shipping_name, shipping_code, user_id, buyer_message, buyer_nick, buyer_comment,\n    created, updated\n    from tb_order\n  </select>\n\n    <!-- sql 片断 -->\n    <sql id=\"tbOrderBaseColumns\">\n        id,\n        payment,\n        payment_type,\n        post_fee,\n        status,\n        payment_time,\n        consign_time,\n        end_time,\n        close_time,\n        shipping_name,\n        shipping_code,\n        user_id,\n        buyer_message,\n        buyer_nick,\n        buyer_comment,\n        created,\n        updated\n    </sql>\n\n    <!-- 查询超时的订单 -->\n    <select id=\"selectOrderOutTime\" resultType=\"string\">\n      select id from tb_order\n      where status = 0\n      and created &lt;= subdate(now(), interval 2 hour)\n    </select>\n\n    <!-- 获取会员所有订单 -->\n    <select id=\"selectByUserId\" resultMap=\"BaseResultMap\">\n      select <include refid=\"tbOrderBaseColumns\"/>\n      from tb_order\n      where user_id = #{userId}\n      order by created desc\n    </select>\n\n    <!-- 获取会员订单总数 -->\n    <select id=\"getMemberOrderCount\" resultType=\"int\">\n      select count(*) from tb_order\n      where user_id = #{userId}\n    </select>\n\n    <!-- 获取会员的订单信息 -->\n    <select id=\"selectByUserIdAndOrderId\" resultType=\"com.yuu.ymall.domain.TbOrder\">\n        select <include refid=\"tbOrderBaseColumns\"/>\n        from tb_order\n        where user_id = #{userId} and id = #{orderId}\n    </select>\n</mapper>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbOrderShippingMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbOrderShippingMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbOrderShipping\" >\n    <id column=\"order_id\" property=\"orderId\" jdbcType=\"VARCHAR\" />\n    <result column=\"receiver_name\" property=\"receiverName\" jdbcType=\"VARCHAR\" />\n    <result column=\"receiver_phone\" property=\"receiverPhone\" jdbcType=\"VARCHAR\" />\n    <result column=\"receiver_mobile\" property=\"receiverMobile\" jdbcType=\"VARCHAR\" />\n    <result column=\"receiver_province\" property=\"receiverProvince\" jdbcType=\"VARCHAR\" />\n    <result column=\"receiver_city\" property=\"receiverCity\" jdbcType=\"VARCHAR\" />\n    <result column=\"receiver_district\" property=\"receiverDistrict\" jdbcType=\"VARCHAR\" />\n    <result column=\"receiver_address\" property=\"receiverAddress\" jdbcType=\"VARCHAR\" />\n    <result column=\"receiver_zip\" property=\"receiverZip\" jdbcType=\"VARCHAR\" />\n    <result column=\"created\" property=\"created\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"updated\" property=\"updated\" jdbcType=\"TIMESTAMP\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.String\" >\n    delete from tb_order_shipping\n    where order_id = #{orderId,jdbcType=VARCHAR}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbOrderShipping\" >\n    insert into tb_order_shipping (order_id, receiver_name, receiver_phone, receiver_address,\n      created, updated)\n    values (#{orderId,jdbcType=VARCHAR}, #{receiverName,jdbcType=VARCHAR}, #{receiverPhone,jdbcType=VARCHAR},\n      #{receiverAddress,jdbcType=VARCHAR},\n      #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbOrderShipping\" >\n    update tb_order_shipping\n    set receiver_name = #{receiverName,jdbcType=VARCHAR},\n      receiver_phone = #{receiverPhone,jdbcType=VARCHAR},\n      receiver_mobile = #{receiverMobile,jdbcType=VARCHAR},\n      receiver_province = #{receiverProvince,jdbcType=VARCHAR},\n      receiver_city = #{receiverCity,jdbcType=VARCHAR},\n      receiver_district = #{receiverDistrict,jdbcType=VARCHAR},\n      receiver_address = #{receiverAddress,jdbcType=VARCHAR},\n      receiver_zip = #{receiverZip,jdbcType=VARCHAR},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where order_id = #{orderId,jdbcType=VARCHAR}\n  </update>\n  <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.String\" >\n    select order_id, receiver_name, receiver_phone, receiver_mobile, receiver_province,\n    receiver_city, receiver_district, receiver_address, receiver_zip, created, updated\n    from tb_order_shipping\n    where order_id = #{orderId,jdbcType=VARCHAR}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\" >\n    select order_id, receiver_name, receiver_phone, receiver_mobile, receiver_province,\n    receiver_city, receiver_district, receiver_address, receiver_zip, created, updated\n    from tb_order_shipping\n  </select>\n</mapper>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbPanelContentMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbPanelContentMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbPanelContent\" >\n    <id column=\"id\" property=\"id\" jdbcType=\"INTEGER\" />\n    <result column=\"panel_id\" property=\"panelId\" jdbcType=\"INTEGER\" />\n    <result column=\"type\" property=\"type\" jdbcType=\"INTEGER\" />\n    <result column=\"product_id\" property=\"productId\" jdbcType=\"BIGINT\" />\n    <result column=\"sort_order\" property=\"sortOrder\" jdbcType=\"INTEGER\" />\n    <result column=\"full_url\" property=\"fullUrl\" jdbcType=\"VARCHAR\" />\n    <result column=\"pic_url\" property=\"picUrl\" jdbcType=\"VARCHAR\" />\n    <result column=\"pic_url2\" property=\"picUrl2\" jdbcType=\"VARCHAR\" />\n    <result column=\"pic_url3\" property=\"picUrl3\" jdbcType=\"VARCHAR\" />\n    <result column=\"created\" property=\"created\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"updated\" property=\"updated\" jdbcType=\"TIMESTAMP\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Integer\" >\n    delete from tb_panel_content\n    where id = #{id,jdbcType=INTEGER}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbPanelContent\" >\n    <selectKey resultType=\"java.lang.Integer\" keyProperty=\"id\" order=\"AFTER\" >\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_panel_content (panel_id, type, product_id,\n      sort_order, full_url, pic_url,\n      pic_url2, pic_url3, created,\n      updated)\n    values (#{panelId,jdbcType=INTEGER}, #{type,jdbcType=INTEGER}, #{productId,jdbcType=BIGINT},\n      #{sortOrder,jdbcType=INTEGER}, #{fullUrl,jdbcType=VARCHAR}, #{picUrl,jdbcType=VARCHAR},\n      #{picUrl2,jdbcType=VARCHAR}, #{picUrl3,jdbcType=VARCHAR}, #{created,jdbcType=TIMESTAMP},\n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbPanelContent\" >\n    update tb_panel_content\n    set panel_id = #{panelId,jdbcType=INTEGER},\n      type = #{type,jdbcType=INTEGER},\n      product_id = #{productId,jdbcType=BIGINT},\n      sort_order = #{sortOrder,jdbcType=INTEGER},\n      full_url = #{fullUrl,jdbcType=VARCHAR},\n      pic_url = #{picUrl,jdbcType=VARCHAR},\n      pic_url2 = #{picUrl2,jdbcType=VARCHAR},\n      pic_url3 = #{picUrl3,jdbcType=VARCHAR},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=INTEGER}\n  </update>\n  <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.Integer\" >\n    select id, panel_id, type, product_id, sort_order, full_url, pic_url, pic_url2, pic_url3,\n    created, updated\n    from tb_panel_content\n    where id = #{id,jdbcType=INTEGER}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\" >\n    select id, panel_id, type, product_id, sort_order, full_url, pic_url, pic_url2, pic_url3,\n    created, updated\n    from tb_panel_content\n  </select>\n\n    <!-- 根据板块 id，获取板块内容 -->\n    <select id=\"selectContentByPid\" resultType=\"com.yuu.ymall.web.api.dto.TbPanelContentDto\">\n      select id, type, product_id, full_Url, pic_url, pic_url2, pic_url3\n      from tb_panel_content\n      where panel_id = #{id}\n      order by sort_order\n    </select>\n</mapper>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbPanelMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbPanelMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbPanel\" >\n    <id column=\"id\" property=\"id\" jdbcType=\"INTEGER\" />\n    <result column=\"name\" property=\"name\" jdbcType=\"VARCHAR\" />\n    <result column=\"type\" property=\"type\" jdbcType=\"INTEGER\" />\n    <result column=\"sort_order\" property=\"sortOrder\" jdbcType=\"INTEGER\" />\n    <result column=\"position\" property=\"position\" jdbcType=\"INTEGER\" />\n    <result column=\"limit_num\" property=\"limitNum\" jdbcType=\"INTEGER\" />\n    <result column=\"status\" property=\"status\" jdbcType=\"INTEGER\" />\n    <result column=\"created\" property=\"created\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"updated\" property=\"updated\" jdbcType=\"TIMESTAMP\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Integer\" >\n    delete from tb_panel\n    where id = #{id,jdbcType=INTEGER}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbPanel\" >\n    <selectKey resultType=\"java.lang.Integer\" keyProperty=\"id\" order=\"AFTER\" >\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_panel (name, type, sort_order,\n      position, limit_num, status,\n      created, updated)\n    values (#{name,jdbcType=VARCHAR}, #{type,jdbcType=INTEGER}, #{sortOrder,jdbcType=INTEGER},\n      #{position,jdbcType=INTEGER}, #{limitNum,jdbcType=INTEGER}, #{status,jdbcType=INTEGER},\n      #{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbPanel\" >\n    update tb_panel\n    set name = #{name,jdbcType=VARCHAR},\n      type = #{type,jdbcType=INTEGER},\n      sort_order = #{sortOrder,jdbcType=INTEGER},\n      position = #{position,jdbcType=INTEGER},\n      limit_num = #{limitNum,jdbcType=INTEGER},\n      status = #{status,jdbcType=INTEGER},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=INTEGER}\n  </update>\n  <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.Integer\" >\n    select id, name, type, sort_order, position, limit_num, status, created, updated\n    from tb_panel\n    where id = #{id,jdbcType=INTEGER}\n  </select>\n  <select id=\"selectAll\" resultType=\"com.yuu.ymall.web.api.dto.TbPanelDto\" >\n    select id, name, type, position\n    from tb_panel\n    order by sort_order\n  </select>\n</mapper>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/mapper/TbUserMapper.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\" >\n<mapper namespace=\"com.yuu.ymall.web.api.mapper.TbUserMapper\" >\n  <resultMap id=\"BaseResultMap\" type=\"com.yuu.ymall.domain.TbUser\" >\n    <id column=\"id\" property=\"id\" jdbcType=\"BIGINT\" />\n    <result column=\"username\" property=\"username\" jdbcType=\"VARCHAR\" />\n    <result column=\"password\" property=\"password\" jdbcType=\"VARCHAR\" />\n    <result column=\"created\" property=\"created\" jdbcType=\"TIMESTAMP\" />\n    <result column=\"updated\" property=\"updated\" jdbcType=\"TIMESTAMP\" />\n  </resultMap>\n  <delete id=\"deleteByPrimaryKey\" parameterType=\"java.lang.Long\" >\n    delete from tb_user\n    where id = #{id,jdbcType=BIGINT}\n  </delete>\n  <insert id=\"insert\" parameterType=\"com.yuu.ymall.domain.TbUser\" >\n    <selectKey resultType=\"java.lang.Long\" keyProperty=\"id\" order=\"AFTER\" >\n      SELECT LAST_INSERT_ID()\n    </selectKey>\n    insert into tb_user (username, password, created, \n      updated)\n    values (#{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR}, #{created,jdbcType=TIMESTAMP}, \n      #{updated,jdbcType=TIMESTAMP})\n  </insert>\n  <update id=\"updateByPrimaryKey\" parameterType=\"com.yuu.ymall.domain.TbUser\" >\n    update tb_user\n    set username = #{username,jdbcType=VARCHAR},\n      password = #{password,jdbcType=VARCHAR},\n      created = #{created,jdbcType=TIMESTAMP},\n      updated = #{updated,jdbcType=TIMESTAMP}\n    where id = #{id,jdbcType=BIGINT}\n  </update>\n  <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\" parameterType=\"java.lang.Long\" >\n    select id, username, password, created, updated\n    from tb_user\n    where id = #{id,jdbcType=BIGINT}\n  </select>\n  <select id=\"selectAll\" resultMap=\"BaseResultMap\" >\n    select id, username, password, created, updated\n    from tb_user\n  </select>\n</mapper>"
  },
  {
    "path": "ymall-web-api/src/main/resources/mybatis-config.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE configuration PUBLIC \"-//mybatis.org//DTD Config 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-config.dtd\">\n<configuration>\n    <!-- 全局参数 -->\n    <settings>\n        <!-- 打印 SQL 语句 -->\n        <setting name=\"logImpl\" value=\"STDOUT_LOGGING\" />\n\n        <!-- 使全局的映射器启用或禁用缓存。 -->\n        <setting name=\"cacheEnabled\" value=\"false\"/>\n\n        <!-- 全局启用或禁用延迟加载。当禁用时，所有关联对象都会即时加载。 -->\n        <setting name=\"lazyLoadingEnabled\" value=\"true\"/>\n\n        <!-- 当启用时，有延迟加载属性的对象在被调用时将会完全加载任意属性。否则，每种属性将会按需要加载。 -->\n        <setting name=\"aggressiveLazyLoading\" value=\"true\"/>\n\n        <!-- 是否允许单条 SQL 返回多个数据集 (取决于驱动的兼容性) default:true -->\n        <setting name=\"multipleResultSetsEnabled\" value=\"true\"/>\n\n        <!-- 是否可以使用列的别名 (取决于驱动的兼容性) default:true -->\n        <setting name=\"useColumnLabel\" value=\"true\"/>\n\n        <!-- 允许 JDBC 生成主键。需要驱动器支持。如果设为了 true，这个设置将强制使用被生成的主键，有一些驱动器不兼容不过仍然可以执行。 default:false  -->\n        <setting name=\"useGeneratedKeys\" value=\"false\"/>\n\n        <!-- 指定 MyBatis 如何自动映射 数据基表的列 NONE：不映射 PARTIAL：部分 FULL:全部  -->\n        <setting name=\"autoMappingBehavior\" value=\"PARTIAL\"/>\n\n        <!-- 这是默认的执行类型 （SIMPLE: 简单； REUSE: 执行器可能重复使用prepared statements语句；BATCH: 执行器可以重复执行语句和批量更新） -->\n        <setting name=\"defaultExecutorType\" value=\"SIMPLE\"/>\n\n        <!-- 使用驼峰命名法转换 字段。 -->\n        <setting name=\"mapUnderscoreToCamelCase\" value=\"true\"/>\n\n        <!-- 设置本地缓存范围 session:就会有数据的共享 statement:语句范围 (这样就不会有数据的共享 ) defalut:session -->\n        <setting name=\"localCacheScope\" value=\"SESSION\"/>\n\n        <!-- 设置 JDBC 类型为空时,某些驱动程序 要指定值, default:OTHER，插入空值时不需要指定类型 -->\n        <setting name=\"jdbcTypeForNull\" value=\"NULL\"/>\n    </settings>\n\n    <plugins>\n        <plugin interceptor=\"com.github.pagehelper.PageHelper\">\n            <!--<property name=\"dialect\" value=\"mysql\"/>-->\n            <property name=\"offsetAsPageNum\" value=\"false\"/>\n            <property name=\"rowBoundsWithCount\" value=\"false\"/>\n            <property name=\"pageSizeZero\" value=\"true\"/>\n            <property name=\"reasonable\" value=\"true\"/>\n            <property name=\"supportMethodsArguments\" value=\"false\"/>\n            <property name=\"returnPageInfo\" value=\"none\"/>\n        </plugin>\n    </plugins>\n</configuration>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/resource.properties",
    "content": "# û¼ʱ7죨RedisʧЧʱ䣩\nSESSION_EXPIRE=604800\n\n## \nEMAIL_HOST=smtp.qq.com\nEMAIL_USERNAME=1225459207@qq.com\nEMAIL_PASSWORD=neahsiuyxwuvhhih\nEMAIL_SENDER=1225459207@qq.com\n\n#ǰ ʼ\nSERVER_URL=http://127.0.0.1:9999\n\n#ESIP\nES_CONNECT_IP=192.168.93.137\n\n#ڵͻ˶˿\nES_NODE_CLIENT_PORT=9300\n\n#ESȺ\nES_CLUSTER_NAME=elasticsearch\n\n#ESƷ\nITEM_INDEX=item\nITEM_TYPE=itemList\n\n# ໺ key\nHEADER_CATE=HEADER_CATE\n\n# ҳݻ key\nPRODUCT_HOME=PRODUCT_HOME\n\n# ûﳵRedis key\nCART_PRE=CART\n\n# Ʒ黺 key\nPRODUCT_ITEM=PRODUCT_ITEM\n# Ʒ黺ʱ 7\nITEM_EXPIRE=604800\n\n#ƼƷ id\nRECOMEED_PANEL_ID=6\n#ƼƷ黺 key\nRECOMEED_PANEL=RECOMEED_PANEL\n\n# Ʒ key\nCATE_PRODUCTS=CATE_PRODUCTS\n\n# \nADD_ORDER=ADD_ORDER\n# ֧Ϣ\nORDER_PAY=ORDER_PAY\n\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/spring-context-druid.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:context=\"http://www.springframework.org/schema/context\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\">\n\n    <!-- 加载配置属性文件 -->\n    <context:property-placeholder ignore-unresolvable=\"true\" location=\"classpath:*.properties\"/>\n\n    <!-- 数据源配置, 使用 Druid 数据库连接池 -->\n    <bean id=\"dataSource\" class=\"com.alibaba.druid.pool.DruidDataSource\" init-method=\"init\" destroy-method=\"close\">\n        <!-- 数据源驱动类可不写，Druid默认会自动根据URL识别DriverClass -->\n        <property name=\"driverClassName\" value=\"${jdbc.driverClass}\"/>\n\n        <!-- 基本属性 url、user、password -->\n        <property name=\"url\" value=\"${jdbc.connectionURL}\"/>\n        <property name=\"username\" value=\"${jdbc.username}\"/>\n        <property name=\"password\" value=\"${jdbc.password}\"/>\n\n        <!-- 配置初始化大小、最小、最大 -->\n        <property name=\"initialSize\" value=\"${jdbc.pool.init}\"/>\n        <property name=\"minIdle\" value=\"${jdbc.pool.minIdle}\"/>\n        <property name=\"maxActive\" value=\"${jdbc.pool.maxActive}\"/>\n\n        <!-- 配置获取连接等待超时的时间 -->\n        <property name=\"maxWait\" value=\"60000\"/>\n\n        <!-- 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒 -->\n        <property name=\"timeBetweenEvictionRunsMillis\" value=\"60000\"/>\n\n        <!-- 配置一个连接在池中最小生存的时间，单位是毫秒 -->\n        <property name=\"minEvictableIdleTimeMillis\" value=\"300000\"/>\n\n        <property name=\"validationQuery\" value=\"${jdbc.testSql}\"/>\n        <property name=\"testWhileIdle\" value=\"true\"/>\n        <property name=\"testOnBorrow\" value=\"false\"/>\n        <property name=\"testOnReturn\" value=\"false\"/>\n\n        <!-- 配置监控统计拦截的filters -->\n        <property name=\"filters\" value=\"stat\"/>\n    </bean>\n</beans>"
  },
  {
    "path": "ymall-web-api/src/main/resources/spring-context-elasticsearch.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:elasticsearch=\"http://www.springframework.org/schema/data/elasticsearch\"\n       xsi:schemaLocation=\"\n        http://www.springframework.org/schema/beans\n        http://www.springframework.org/schema/beans/spring-beans.xsd\n        http://www.springframework.org/schema/data/elasticsearch\n        http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd\n        \">\n\n    <!-- client 客户端配置 -->\n    <elasticsearch:transport-client id=\"client\"  cluster-nodes=\"192.168.93.137:9300\" cluster-name=\"elasticsearch\"/>\n\n    <!-- 扫描Dao包，自动创建实例 -->\n    <elasticsearch:repositories base-package=\"com.yuu.ymall.web.api.repositories\"/>\n\n    <!-- ElasticSearch模版对象 -->\n    <bean id=\"elasticsearchTemplate\" class=\"org.springframework.data.elasticsearch.core.ElasticsearchTemplate\">\n        <constructor-arg name=\"client\" ref=\"client\"></constructor-arg>\n    </bean>\n\n</beans>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/spring-context-mybatis.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\">\n\n    <!-- 配置 SqlSession -->\n    <bean id=\"sqlSessionFactory\" class=\"org.mybatis.spring.SqlSessionFactoryBean\">\n        <property name=\"dataSource\" ref=\"dataSource\"/>\n        <!-- 用于配置对应实体类所在的包，多个 package 之间可以用 ',' 号分割 -->\n        <property name=\"typeAliasesPackage\" value=\"com.yuu.ymall.domain\"/>\n        <!-- 用于配置对象关系映射配置文件所在目录 -->\n        <property name=\"mapperLocations\" value=\"classpath:/mapper/**/*.xml\"/>\n        <property name=\"configLocation\" value=\"classpath:/mybatis-config.xml\"></property>\n    </bean>\n\n    <!-- 扫描 Mapper -->\n    <bean class=\"org.mybatis.spring.mapper.MapperScannerConfigurer\">\n        <property name=\"basePackage\" value=\"com.yuu.ymall.web.api.mapper\" />\n    </bean>\n</beans>"
  },
  {
    "path": "ymall-web-api/src/main/resources/spring-context-redis.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:context=\"http://www.springframework.org/schema/context\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\">\n\n    <!-- 加载配置文件 -->\n    <context:property-placeholder location=\"classpath:ymall.properties\"/>\n\n    <!-- redis 数据源 -->\n    <bean id=\"poolConfig\" class=\"redis.clients.jedis.JedisPoolConfig\">\n        <!-- 最大空闲数 -->\n        <property name=\"maxIdle\" value=\"${redis.maxIdle}\"/>\n        <!-- 最大空连接数 -->\n        <property name=\"maxTotal\" value=\"${redis.maxTotal}\"/>\n        <!-- 最大等待时间 -->\n        <property name=\"maxWaitMillis\" value=\"${redis.maxWaitMillis}\"/>\n        <!-- 连接超时时是否阻塞，false 时报异常，true 阻塞直到超时，默认 true -->\n        <property name=\"blockWhenExhausted\" value=\"${redis.blockWhenExhausted}\"/>\n        <!-- 返回连接时，检查连接是否成功 -->\n        <property name=\"testOnBorrow\" value=\"${redis.testOnBorrow}\"/>\n    </bean>\n\n    <!-- spring-redis 连接池管理工厂 -->\n    <bean id=\"jedisConnectionFactory\" class=\"org.springframework.data.redis.connection.jedis.JedisConnectionFactory\">\n        <!-- IP 地址 -->\n        <property name=\"hostName\" value=\"${redis.host}\"/>\n        <!-- 端口号 -->\n        <property name=\"port\" value=\"${redis.port}\"/>\n        <!-- 超时时间，默认 2000 -->\n        <property name=\"timeout\" value=\"${reids.timeout}\"/>\n        <!-- 连接池配置引用 -->\n        <property name=\"poolConfig\" ref=\"poolConfig\"/>\n        <!-- usePool: 是否使用连接池 -->\n        <property name=\"usePool\" value=\"true\"/>\n    </bean>\n\n    <!-- redis template definition -->\n    <bean id=\"redisTemplate\" class=\"org.springframework.data.redis.core.RedisTemplate\">\n        <property name=\"connectionFactory\" ref=\"jedisConnectionFactory\" />\n        <property name=\"keySerializer\">\n            <bean class=\"org.springframework.data.redis.serializer.StringRedisSerializer\" />\n        </property>\n        <property name=\"valueSerializer\">\n            <bean class=\"org.springframework.data.redis.serializer.JdkSerializationRedisSerializer\" />\n        </property>\n        <property name=\"hashKeySerializer\">\n            <bean class=\"org.springframework.data.redis.serializer.StringRedisSerializer\" />\n        </property>\n        <property name=\"hashValueSerializer\">\n            <bean class=\"org.springframework.data.redis.serializer.JdkSerializationRedisSerializer\" />\n        </property>\n        <!--开启事务  -->\n        <property name=\"enableTransactionSupport\" value=\"true\"></property>\n    </bean>\n</beans>"
  },
  {
    "path": "ymall-web-api/src/main/resources/spring-context.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\"\n       xmlns:context=\"http://www.springframework.org/schema/context\"\n       xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:tx=\"http://www.springframework.org/schema/tx\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd\n\thttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd\">\n\n    <context:annotation-config />\n    <context:component-scan base-package=\"com.yuu.ymall.web.api, com.yuu.ymall.commons\">\n        <context:exclude-filter type=\"annotation\" expression=\"org.springframework.stereotype.Controller\" />\n    </context:component-scan>\n\n\n    <!-- 配置事务管理器 -->\n    <bean id=\"transactionManager\" class=\"org.springframework.jdbc.datasource.DataSourceTransactionManager\">\n        <property name=\"dataSource\" ref=\"dataSource\"/>\n    </bean>\n\n    <!-- 开启事务注解驱动 -->\n    <tx:annotation-driven transaction-manager=\"transactionManager\" />\n</beans>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/spring-mvc.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n       xmlns:context=\"http://www.springframework.org/schema/context\"\n       xmlns:mvc=\"http://www.springframework.org/schema/mvc\" xmlns:aop=\"http://www.springframework.org/schema/aop\"\n       xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\n        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\n        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd\">\n\n    <description>Spring MVC Configuration</description>\n\n    <!-- 加载配置属性文件 -->\n    <context:property-placeholder ignore-unresolvable=\"true\" location=\"classpath:*.properties\"/>\n\n    <!-- 使用 Annotation 自动注册 Bean,只扫描 @Controller -->\n    <context:component-scan base-package=\"com.yuu.ymall.web.api\" use-default-filters=\"false\">\n        <context:include-filter type=\"annotation\" expression=\"org.springframework.stereotype.Controller\"/>\n    </context:component-scan>\n\n    <!-- 默认的注解映射的支持 -->\n    <mvc:annotation-driven />\n\n    <!-- 定义视图文件解析 -->\n    <bean class=\"org.springframework.web.servlet.view.InternalResourceViewResolver\">\n        <property name=\"prefix\" value=\"${web.view.prefix}\"/>\n        <property name=\"suffix\" value=\"${web.view.suffix}\"/>\n    </bean>\n\n    <!-- 静态资源映射 -->\n    <mvc:resources mapping=\"/static/**\" location=\"/static/\" cache-period=\"31536000\"/>\n\n    <!-- Swagger 配置 -->\n    <mvc:resources mapping=\"/swagger-ui.html\" location=\"classpath:/META-INF/resources/*\" />\n    <mvc:resources mapping=\"/webjars/**\" location=\"classpath:/META-INF/resources/webjars/\" />\n\n    <!-- 拦截器配置 -->\n<!--    <mvc:interceptors>\n        <mvc:interceptor>\n            <mvc:mapping path=\"/**\"/>\n            <bean class=\"com.yuu.ymall.controller.admin.controller.interceptor.PermissionInterceptor\" />\n        </mvc:interceptor>\n    </mvc:interceptors>-->\n\n    <!-- 上传文件拦截，设置最大上传文件大小 10M = 10*1024*1024(B) = 10485760 bytes -->\n    <bean id=\"multipartResolver\" class=\"org.springframework.web.multipart.commons.CommonsMultipartResolver\">\n        <property name=\"maxUploadSize\" value=\"${web.maxUploadSize}\"/>\n    </bean>\n</beans>\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/ymall.properties",
    "content": "#============================#\n#==== Database settings ====#\n#============================#\n\n# JDBC\njdbc.driverClass=com.mysql.jdbc.Driver\njdbc.connectionURL=jdbc:mysql://localhost:3306/ymall?useUnicode=true&characterEncoding=utf-8&useSSL=false\njdbc.username=root\njdbc.password=123456\n\n# JDBC Pool\njdbc.pool.init=1\njdbc.pool.minIdle=3\njdbc.pool.maxActive=20\n\n# JDBC Test\njdbc.testSql=SELECT 'x' FROM DUAL\n\n#============================#\n#==== Redis settings ====#\n#============================#\nredis.host=192.168.93.137\nredis.port=6379\nredis.password=\"\nredis.maxIdle=400\nredis.maxTotal=6000\nredis.maxWaitMillis=1000\nredis.blockWhenExhausted=true\nredis.testOnBorrow=true\nreids.timeout=10000\n\n#============================#\n#==== Framework settings ====#\n#============================#\n\n# \\u89c6\\u56fe\\u6587\\u4ef6\\u5b58\\u653e\\u8def\\u5f84\nweb.view.prefix=/WEB-INF/views/\nweb.view.suffix=.jsp\n\nweb.maxUploadSize=10485760\n"
  },
  {
    "path": "ymall-web-api/src/main/resources/zfbinfo.properties",
    "content": "\n# ֧partnerIdappId\nopen_api_domain = https://openapi.alipaydev.com/gateway.do\nmcloud_api_domain = http://mcloudmonitor.com/gateway.do\npid = \nappid = \n\n# RSA˽ԿԿ֧Կ\nprivate_key = \npublic_key = \n\n#SHA1withRsaӦ֧Կ\n#alipay_public_key = \n\n#SHA256withRsaӦ֧Կ\nalipay_public_key = \n\n# ǩ: RSA->SHA1withRsa,RSA2->SHA256withRsa\nsign_type = RSA2\n# 渶ѯͲѯ룩\nmax_query_retry = 5\nquery_duration = 5000\n\n# 渶ͳ룩\nmax_cancel_retry = 3\ncancel_duration = 2000\n\n# ױ̵߳һεӳٺ͵ȼ룩\nheartbeat_delay = 5\nheartbeat_duration = 900\n"
  },
  {
    "path": "ymall-web-api/src/main/webapp/WEB-INF/templates/reset-pass.html",
    "content": "<!doctype html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\n    <title>YMALL 帐户验证</title>\n    <style media=\"all\" type=\"text/css\">\n        td, p, h1, h3, a {\n            font-family: Helvetica, Arial, sans-serif;\n        }\n\n        a {\n            color: #66c0f4;\n            text-decoration: none;\n        }\n\n        a:hover {\n            color: #66c0f4;\n            text-decoration: none;\n        }\n    </style>\n<body bgcolor=\"\" link=\"#6d93b8\" alink=\"#9DB7D0\" vlink=\"#6d93b8\"\n      style=\"font-family: Helvetica, Arial, sans-serif; font-size: 14px;\">\n    <table style=\"background-color: #ebedf0; width: 538px;\" align=\"center\" cellspacing=\"0\" cellpadding=\"0\">\n        <tbody>\n        <tr>\n            <td style=\"font-size: 24px;color: #292c33;text-align: center;height:65px;\">\n                YMALL\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <table width=\"470\" border=\"0\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\"\n                       style=\"background-color: #fff;padding-left: 5px; padding-right: 5px; padding-bottom: 10px;\">\n\n                    <tbody>\n                    <tr>\n                        <td style=\"padding-top: 32px;\">\n                        <span style=\"padding-left: 25px;padding-right: 25px;font-size: 14px;font-family: '微软雅黑','黑体',arial;color: #525866;\">\n                            ${email} 您好\n                        </span>\n                            <br>\n                        </td>\n                    </tr>\n\n                    <tr>\n                        <td style=\"padding-top: 32px;padding-left: 25px;padding-right: 25px;font-size: 14px;font-family: '微软雅黑','黑体',arial;color: #525866;\">\n                            以下是您更改 <a style=\"color: #8f98a0;\" target=\"_blank\" href=\"https://blog.csdn.net/qq_37581282\">YMALL</a>\n                            登录密码时所需的验证码：\n                        </td>\n                    </tr>\n\n                    <tr>\n                        <td style=\"padding-left: 25px;padding-top: 24px; padding-bottom: 24px;\">\n                            <div>\n                                <span style=\"font-size: 24px; color: #66c0f4; font-family: Arial, Helvetica, sans-serif; font-weight: bold;\"><span th:text=\"${code}\"></span></span>\n                                <br>\n                            </div>\n                        </td>\n                    </tr>\n\n                    <tr>\n                        <td style=\"padding-left: 25px;padding-right: 25px;font-size: 14px;font-family: '微软雅黑','黑体',arial;color: #525866;\">\n                            如果不是您本人尝试更改您的 <a style=\"color: #8f98a0;\" target=\"_blank\" href=\"https://71yuu.com/\">YMALL</a>\n                            登录凭据，请忽略此封电子邮件。有可能是其他用户输入了错误的登录信息。\n                        </td>\n                    </tr>\n\n                    <tr>\n                        <td style=\"padding-left: 25px;font-size: 16px; color: #6d7880; padding-top: 50px; padding-bottom:10px;\">\n                            <a style=\"color: #8f98a0;\" target=\"_blank\" href=\"https://71yuu.com/\">YMALL<br>https://71yuu.com/</a><br>\n                        </td>\n                    </tr>\n                    </tbody>\n                </table>\n            </td>\n        </tr>\n        <tr>\n            <td style=\" height: 65px;border-bottom: 1px solid grey;text-align:center;\">\n            </td>\n        </tr>\n        </tbody>\n    </table>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-api/src/main/webapp/WEB-INF/templates/update-email.html",
    "content": "<!doctype html>\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:th=\"http://www.thymeleaf.org\">\n<head>\n    <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n\n    <title>YMALL 修改邮箱</title>\n    <style media=\"all\" type=\"text/css\">\n        td, p, h1, h3, a {\n            font-family: Helvetica, Arial, sans-serif;\n        }\n\n        a {\n            color: #66c0f4;\n            text-decoration: none;\n        }\n\n        a:hover {\n            color: #66c0f4;\n            text-decoration: none;\n        }\n    </style>\n<body bgcolor=\"\" link=\"#6d93b8\" alink=\"#9DB7D0\" vlink=\"#6d93b8\"\n      style=\"font-family: Helvetica, Arial, sans-serif; font-size: 14px;\">\n    <table style=\"background-color: #ebedf0; width: 538px;\" align=\"center\" cellspacing=\"0\" cellpadding=\"0\">\n        <tbody>\n        <tr>\n            <td style=\"font-size: 24px;color: #292c33;text-align: center;height:65px;\">\n                YMALL\n            </td>\n        </tr>\n        <tr>\n            <td>\n                <table width=\"470\" border=\"0\" align=\"center\" cellpadding=\"0\" cellspacing=\"0\"\n                       style=\"background-color: #fff;padding-left: 5px; padding-right: 5px; padding-bottom: 10px;\">\n\n                    <tbody>\n                    <tr>\n                        <td style=\"padding-top: 32px;\">\n                        <span style=\"padding-left: 25px;padding-right: 25px;font-size: 14px;font-family: '微软雅黑','黑体',arial;color: #525866;\">\n                            <span th:text=\"${email}\"></span> 您好\n                        </span>\n                            <br>\n                        </td>\n                    </tr>\n\n                    <tr>\n                        <td style=\"padding-top: 32px;padding-left: 25px;padding-right: 25px;font-size: 14px;font-family: '微软雅黑','黑体',arial;color: #525866;\">\n                            以下是您更改 <a style=\"color: #8f98a0;\" target=\"_blank\" href=\"https://71yuu.com/\">YMALL</a>\n                            更改邮箱时所需的验证码：\n                        </td>\n                    </tr>\n\n                    <tr>\n                        <td style=\"padding-left: 25px;padding-top: 24px; padding-bottom: 24px;\">\n                            <div>\n                                <span style=\"font-size: 24px; color: #66c0f4; font-family: Arial, Helvetica, sans-serif; font-weight: bold;\"><span th:text=\"${code}\"></span></span>\n                                <br>\n                            </div>\n                        </td>\n                    </tr>\n\n                    <tr>\n                        <td style=\"padding-left: 25px;padding-right: 25px;font-size: 14px;font-family: '微软雅黑','黑体',arial;color: #525866;\">\n                            如果不是您本人尝试更改您的 <a style=\"color: #8f98a0;\" target=\"_blank\" href=\"https://71yuu.com/\">YMALL</a>\n                            登录凭据，请忽略此封电子邮件。有可能是其他用户输入了错误的登录信息。\n                        </td>\n                    </tr>\n\n                    <tr>\n                        <td style=\"padding-left: 25px;font-size: 16px; color: #6d7880; padding-top: 50px; padding-bottom:10px;\">\n                            <a style=\"color: #8f98a0;\" target=\"_blank\" href=\"https://71yuu.com/\">YMALL<br>https://71yuu.com/</a><br>\n                        </td>\n                    </tr>\n                    </tbody>\n                </table>\n            </td>\n        </tr>\n        <tr>\n            <td style=\"height: 65px;border-bottom: 1px solid grey;text-align:center;\">\n            </td>\n        </tr>\n        </tbody>\n    </table>\n</body>\n</html>\n"
  },
  {
    "path": "ymall-web-api/src/main/webapp/WEB-INF/web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd\"\n         version=\"4.0\">\n\n    <!-- 加载 Spring 容器 -->\n    <context-param>\n        <param-name>contextConfigLocation</param-name>\n        <param-value>classpath:spring-context*.xml</param-value>\n    </context-param>\n    <listener>\n        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>\n    </listener>\n\n    <!-- 解决 POST 乱码 -->\n    <filter>\n        <filter-name>encodingFilter</filter-name>\n        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>\n        <init-param>\n            <param-name>encoding</param-name>\n            <param-value>UTF-8</param-value>\n        </init-param>\n        <init-param>\n            <param-name>forceEncoding</param-name>\n            <param-value>true</param-value>\n        </init-param>\n    </filter>\n    <filter-mapping>\n        <filter-name>encodingFilter</filter-name>\n        <url-pattern>/*</url-pattern>\n    </filter-mapping>\n\n    <!-- Spring MVC 前端控制器 -->\n    <servlet>\n        <servlet-name>springServlet</servlet-name>\n        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>\n        <init-param>\n            <param-name>contextConfigLocation</param-name>\n            <param-value>classpath*:/spring-mvc.xml</param-value>\n        </init-param>\n        <load-on-startup>1</load-on-startup>\n    </servlet>\n    <servlet-mapping>\n        <servlet-name>springServlet</servlet-name>\n        <url-pattern>/</url-pattern>\n    </servlet-mapping>\n\n    <!-- Druid Servlet -->\n    <servlet>\n        <servlet-name>DruidStatView</servlet-name>\n        <servlet-class>com.alibaba.druid.support.http.StatViewServlet</servlet-class>\n    </servlet>\n    <servlet-mapping>\n        <servlet-name>DruidStatView</servlet-name>\n        <url-pattern>/druid/*</url-pattern>\n    </servlet-mapping>\n\n    <!-- Swagger2 配置 -->\n    <servlet-mapping>\n        <servlet-name>default</servlet-name>\n        <url-pattern>/swagger-ui.html</url-pattern>\n    </servlet-mapping>\n</web-app>\n"
  },
  {
    "path": "ymall-web-api/test/com/yuu/ymall/web/api/test/EsTest.java",
    "content": "package com.yuu.ymall.web.api.test;\n\nimport com.yuu.ymall.web.api.domain.ESItem;\nimport com.yuu.ymall.web.api.repositories.ItemRepository;\nimport org.elasticsearch.action.search.SearchResponse;\nimport org.elasticsearch.index.query.QueryBuilders;\nimport org.elasticsearch.search.SearchHit;\nimport org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;\nimport org.elasticsearch.search.fetch.subphase.highlight.HighlightField;\nimport org.junit.Test;\nimport org.junit.runner.RunWith;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.data.domain.Page;\nimport org.springframework.data.domain.PageRequest;\nimport org.springframework.data.domain.Pageable;\nimport org.springframework.data.elasticsearch.core.ElasticsearchTemplate;\nimport org.springframework.data.elasticsearch.core.SearchResultMapper;\nimport org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;\nimport org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;\nimport org.springframework.data.elasticsearch.core.query.NativeSearchQuery;\nimport org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;\nimport org.springframework.test.context.ContextConfiguration;\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * @author by Yuu\n * @classname EsTest\n * @date 2019/6/30 12:31\n */\n@RunWith(SpringJUnit4ClassRunner.class)\n@ContextConfiguration(\"classpath:spring-context-elasticsearch.xml\")\npublic class EsTest {\n\n    @Autowired\n    private ElasticsearchTemplate elasticsearchTemplate;\n\n    @Autowired\n    private ItemRepository itemRepository;\n\n    /**\n     * 创建索引\n     *\n     * @throws Exception\n     */\n    @Test\n    public void createIndex() throws Exception {\n        elasticsearchTemplate.createIndex(ESItem.class);\n        //System.out.println(\"创建索引和映射关系成功\");\n        //elasticsearchTemplate.putMapping(ESItem.class);\n    }\n\n    /**\n     * 新增文档\n     */\n    @Test\n    public void insertDocument() {\n        for (long i = 0l; i <= 10l; i++) {\n            ESItem esItem = new ESItem();\n            esItem.setId(i);\n            esItem.setCid(1193l);\n            esItem.setProductName(\"小米手机1\");\n            esItem.setSubTitle(\"小米手机真好1\");\n            esItem.setSalePrice(299d * i);\n            esItem.setProductId(150635087972564l);\n            esItem.setPicUrl(\"https://i.loli.net/2018/07/13/5b48ac7766d98.png\");\n            esItem.setOrderNum(100 * (int)i);\n            esItem.setLimit((int)i);\n            itemRepository.save(esItem);\n        }\n    }\n\n    /**\n     * 高亮显示\n     */\n    @Test\n    public void heiglight() {\n        NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()\n                .withQuery(QueryBuilders.termQuery(\"subTitle\", \"小米\"))\n                .withHighlightFields(new HighlightBuilder.Field(\"productName\")).build();\n        AggregatedPage<ESItem> esItems = elasticsearchTemplate.queryForPage(searchQuery, ESItem.class, new SearchResultMapper() {\n            @Override\n            public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {\n                List<ESItem> esItems = new ArrayList<>();\n                for (SearchHit hit : response.getHits()) {\n                    if (response.getHits().getHits().length <= 0) {\n                        return null;\n                    }\n                    ESItem esItem = new ESItem();\n                    HighlightField productName = hit.getHighlightFields().get(\"productName\");\n                    if (productName != null) {\n                        esItem.setProductName(productName.fragments()[0].toString());\n                    }\n                    HighlightField subTitle = hit.getHighlightFields().get(\"subTitle\");\n                    if (subTitle != null) {\n                        esItem.setSubTitle(subTitle.fragments()[0].toString());\n                    }\n                    esItems.add(esItem);\n                }\n                if (esItems.size() > 0) {\n                    return new AggregatedPageImpl<>((List<T>) esItems);\n                }\n                return null;\n            }\n        });\n        esItems.forEach(esItem -> System.out.println(esItem.getProductName()));\n    }\n\n    @Test\n    public void catePageTest() {\n        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();\n        queryBuilder.withQuery(QueryBuilders.matchQuery(\"cid\", 1193));\n        queryBuilder.withQuery(QueryBuilders.rangeQuery(\"salePrice\").gte(1).lte(3000));\n        queryBuilder.withPageable(PageRequest.of(0, 2));\n\n        // 执行搜索\n        Page<ESItem> search = elasticsearchTemplate.queryForPage(queryBuilder.build(), ESItem.class);\n        System.out.println(search.getTotalElements());\n        for (ESItem esItem : search) {\n            System.out.println(esItem.getProductName());\n        }\n    }\n\n    @Test\n    public void cateTest() {\n        // ElasticSearch 查询\n        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();\n        queryBuilder.withQuery(QueryBuilders.matchQuery(\"cid\", \"1193\"));\n       /* if (priceGt != null && priceLt != null) {\n            queryBuilder.withQuery(QueryBuilders.rangeQuery(\"price\").gt(priceGt).lt(priceLt));\n        }\n        if (StringUtils.isNotBlank(categoryProductPageInfo.getSort())) {\n            if (\"2\".equals(sort)) {\n                queryBuilder.withSort(SortBuilders.fieldSort(\"orderNum\").order(SortOrder.DESC));\n            } else if (\"3\".equals(sort)) {\n                queryBuilder.withSort(SortBuilders.fieldSort(\"price\").order(SortOrder.ASC));\n            } else if (\"4\".equals(sort)) {\n                queryBuilder.withSort(SortBuilders.fieldSort(\"price\").order(SortOrder.DESC));\n            }\n        }*/\n        queryBuilder.withPageable(PageRequest.of(0, 20));\n\n        // 执行搜索\n        Page<ESItem> search = itemRepository.search(queryBuilder.build());\n        List<ESItem> esItems = search.getContent();\n    }\n}\n"
  },
  {
    "path": "ymall-web-ui/.babelrc",
    "content": "{\n  \"presets\": [\n    [\"env\", {\n      \"modules\": false,\n      \"targets\": {\n        \"browsers\": [\"> 1%\", \"last 2 versions\", \"not ie <= 8\"]\n      }\n    }],\n    \"stage-2\"\n  ],\n  \"plugins\": [\n    \"transform-runtime\",\n    [\"component\", [\n      {\n        \"libraryName\": \"element-ui\",\n        \"styleLibraryName\": \"theme-default\"\n      }\n    ]]\n  ],\n  \"env\": {\n    \"test\": {\n      \"presets\": [\"env\", \"stage-2\"],\n      \"plugins\": [\"istanbul\"]\n    }\n  }\n}\n"
  },
  {
    "path": "ymall-web-ui/.editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 2\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n"
  },
  {
    "path": "ymall-web-ui/.eslintignore",
    "content": "build/*.js\nconfig/*.js\n"
  },
  {
    "path": "ymall-web-ui/.eslintrc.js",
    "content": "// http://eslint.org/docs/user-guide/configuring\n\nmodule.exports = {\n  root: true,\n  parser: 'babel-eslint',\n  parserOptions: {\n    sourceType: 'module'\n  },\n  env: {\n    browser: true,\n  },\n  // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style\n  extends: 'standard',\n  // required to lint *.vue files\n  plugins: [\n    'html'\n  ],\n  // add your custom rules here\n  'rules': {\n    // allow paren-less arrow functions\n    'arrow-parens': 0,\n    // allow async-await\n    'generator-star-spacing': 0,\n    // allow debugger during development\n    'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0,\n    \"no-trailing-spaces\": 1\n    // \"semi\": [2, \"always\"]\n  }\n}\n"
  },
  {
    "path": "ymall-web-ui/.gitignore",
    "content": ".DS_Store\nnode_modules/\n/dist\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Editor directories and files\n.idea\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n"
  },
  {
    "path": "ymall-web-ui/.postcssrc.js",
    "content": "// https://github.com/michael-ciniawsky/postcss-load-config\n\nmodule.exports = {\n  \"plugins\": {\n    // to edit target browsers: use \"browserlist\" field in package.json\n    \"autoprefixer\": {}\n  }\n}\n"
  },
  {
    "path": "ymall-web-ui/build/build.js",
    "content": "require('./check-versions')()\n\nprocess.env.NODE_ENV = 'production'\n\nvar ora = require('ora')\nvar rm = require('rimraf')\nvar path = require('path')\nvar chalk = require('chalk')\nvar webpack = require('webpack')\nvar config = require('../config')\nvar webpackConfig = require('./webpack.prod.conf')\n\nvar spinner = ora('building for production...')\nspinner.start()\n\nrm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {\n  if (err) throw err\n  webpack(webpackConfig, function (err, stats) {\n    spinner.stop()\n    if (err) throw err\n    process.stdout.write(stats.toString({\n      colors: true,\n      modules: false,\n      children: false,\n      chunks: false,\n      chunkModules: false\n    }) + '\\n\\n')\n\n    console.log(chalk.cyan('  Build complete.\\n'))\n    console.log(chalk.yellow(\n      '  Tip: built files are meant to be served over an HTTP server.\\n' +\n      '  Opening index.html over file:// won\\'t work.\\n'\n    ))\n  })\n})\n"
  },
  {
    "path": "ymall-web-ui/build/check-versions.js",
    "content": "var chalk = require('chalk')\nvar semver = require('semver')\nvar packageConfig = require('../package.json')\nvar shell = require('shelljs')\nfunction exec (cmd) {\n  return require('child_process').execSync(cmd).toString().trim()\n}\n\nvar versionRequirements = [\n  {\n    name: 'node',\n    currentVersion: semver.clean(process.version),\n    versionRequirement: packageConfig.engines.node\n  },\n]\n\nif (shell.which('npm')) {\n  versionRequirements.push({\n    name: 'npm',\n    currentVersion: exec('npm --version'),\n    versionRequirement: packageConfig.engines.npm\n  })\n}\n\nmodule.exports = function () {\n  var warnings = []\n  for (var i = 0; i < versionRequirements.length; i++) {\n    var mod = versionRequirements[i]\n    if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {\n      warnings.push(mod.name + ': ' +\n        chalk.red(mod.currentVersion) + ' should be ' +\n        chalk.green(mod.versionRequirement)\n      )\n    }\n  }\n\n  if (warnings.length) {\n    console.log('')\n    console.log(chalk.yellow('To use this template, you must update following to modules:'))\n    console.log()\n    for (var i = 0; i < warnings.length; i++) {\n      var warning = warnings[i]\n      console.log('  ' + warning)\n    }\n    console.log()\n    process.exit(1)\n  }\n}\n"
  },
  {
    "path": "ymall-web-ui/build/dev-client.js",
    "content": "/* eslint-disable */\nrequire('eventsource-polyfill')\nvar hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')\n\nhotClient.subscribe(function (event) {\n  if (event.action === 'reload') {\n    window.location.reload()\n  }\n})\n"
  },
  {
    "path": "ymall-web-ui/build/dev-server.js",
    "content": "require('./check-versions')()\n\nvar config = require('../config')\nif (!process.env.NODE_ENV) {\n  process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)\n}\n\nvar opn = require('opn')\nvar path = require('path')\nvar express = require('express')\nvar webpack = require('webpack')\nvar proxyMiddleware = require('http-proxy-middleware')\nvar webpackConfig = require('./webpack.dev.conf')\n\n// default port where dev server listens for incoming traffic\nvar port = process.env.PORT || config.dev.port\n// automatically open browser, if not set will be false\nvar autoOpenBrowser = !!config.dev.autoOpenBrowser\n// Define HTTP proxies to your custom API backend\n// https://github.com/chimurai/http-proxy-middleware\nvar proxyTable = config.dev.proxyTable\n\nvar app = express()\nvar compiler = webpack(webpackConfig)\n\nvar devMiddleware = require('webpack-dev-middleware')(compiler, {\n  publicPath: webpackConfig.output.publicPath,\n  quiet: true\n})\n\nvar hotMiddleware = require('webpack-hot-middleware')(compiler, {\n  log: () => {}\n})\n// force page reload when html-webpack-plugin template changes\ncompiler.plugin('compilation', function (compilation) {\n  compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {\n    hotMiddleware.publish({ action: 'reload' })\n    cb()\n  })\n})\n\n// proxy api requests\nObject.keys(proxyTable).forEach(function (context) {\n  var options = proxyTable[context]\n  if (typeof options === 'string') {\n    options = { target: options }\n  }\n  app.use(proxyMiddleware(options.filter || context, options))\n})\n\n// handle fallback for HTML5 history API\napp.use(require('connect-history-api-fallback')())\n\n// serve webpack bundle output\napp.use(devMiddleware)\n\n// enable hot-reload and state-preserving\n// compilation error display\napp.use(hotMiddleware)\n\n// serve pure static assets\nvar staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)\napp.use(staticPath, express.static('./static'))\n\nvar uri = 'http://localhost:' + port\n\nvar _resolve\nvar readyPromise = new Promise(resolve => {\n  _resolve = resolve\n})\n\nconsole.log('> Starting dev server...')\ndevMiddleware.waitUntilValid(() => {\n  console.log('> Listening at ' + uri + '\\n')\n  // when env is testing, don't need open it\n  if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {\n    opn(uri)\n  }\n  _resolve()\n})\n\nvar server = app.listen(port)\n\nmodule.exports = {\n  ready: readyPromise,\n  close: () => {\n    server.close()\n  }\n}\n"
  },
  {
    "path": "ymall-web-ui/build/utils.js",
    "content": "var path = require('path')\nvar config = require('../config')\nvar ExtractTextPlugin = require('extract-text-webpack-plugin')\n\nexports.assetsPath = function (_path) {\n  var assetsSubDirectory = process.env.NODE_ENV === 'production'\n    ? config.build.assetsSubDirectory\n    : config.dev.assetsSubDirectory\n  return path.posix.join(assetsSubDirectory, _path)\n}\n\nexports.cssLoaders = function (options) {\n  options = options || {}\n\n  var cssLoader = {\n    loader: 'css-loader',\n    options: {\n      minimize: process.env.NODE_ENV === 'production',\n      sourceMap: options.sourceMap\n    }\n  }\n\n  // generate loader string to be used with extract text plugin\n  function generateLoaders (loader, loaderOptions) {\n    var loaders = [cssLoader]\n    if (loader) {\n      loaders.push({\n        loader: loader + '-loader',\n        options: Object.assign({}, loaderOptions, {\n          sourceMap: options.sourceMap\n        })\n      })\n    }\n\n    // Extract CSS when that option is specified\n    // (which is the case during production build)\n    if (options.extract) {\n      return ExtractTextPlugin.extract({\n        use: loaders,\n        fallback: 'vue-style-loader'\n      })\n    } else {\n      return ['vue-style-loader'].concat(loaders)\n    }\n  }\n\n  // https://vue-loader.vuejs.org/en/configurations/extract-css.html\n  return {\n    css: generateLoaders(),\n    postcss: generateLoaders(),\n    less: generateLoaders('less'),\n    sass: generateLoaders('sass', { indentedSyntax: true }),\n    scss: generateLoaders('sass'),\n    stylus: generateLoaders('stylus'),\n    styl: generateLoaders('stylus')\n  }\n}\n\n// Generate loaders for standalone style files (outside of .vue)\nexports.styleLoaders = function (options) {\n  var output = []\n  var loaders = exports.cssLoaders(options)\n  for (var extension in loaders) {\n    var loader = loaders[extension]\n    output.push({\n      test: new RegExp('\\\\.' + extension + '$'),\n      use: loader\n    })\n  }\n  return output\n}\n"
  },
  {
    "path": "ymall-web-ui/build/vue-loader.conf.js",
    "content": "var utils = require('./utils')\nvar config = require('../config')\nvar isProduction = process.env.NODE_ENV === 'production'\n\nmodule.exports = {\n  loaders: utils.cssLoaders({\n    sourceMap: isProduction\n      ? config.build.productionSourceMap\n      : config.dev.cssSourceMap,\n    extract: isProduction\n  })\n}\n"
  },
  {
    "path": "ymall-web-ui/build/webpack.base.conf.js",
    "content": "var path = require('path')\nvar utils = require('./utils')\nvar config = require('../config')\nvar vueLoaderConfig = require('./vue-loader.conf')\n\nfunction resolve (dir) {\n  return path.join(__dirname, '..', dir)\n}\n\nmodule.exports = {\n  // webpack打包时排除以下js依赖 需手动加入js\n  // externals: {\n  //   'vue': 'Vue',\n  //   'vue-router': 'VueRouter',\n  //   'vuex': 'Vuex',\n  //   'axios': 'axios'\n  // },\n  entry: {\n    app: './src/main.js'\n  },\n  output: {\n    path: config.build.assetsRoot,\n    filename: '[name].js',\n    publicPath: process.env.NODE_ENV === 'production'\n      ? config.build.assetsPublicPath\n      : config.dev.assetsPublicPath\n  },\n  resolve: {\n    extensions: ['.js', '.vue', '.json'],\n    alias: {\n      '@': resolve('src'),\n      '/components': resolve('src/components'),\n      '/page': resolve('src/page'),\n      '/common': resolve('src/common'),\n      '/assets': resolve('src/assets'),\n      '/api': resolve('src/api'),\n      '/utils': resolve('src/utils')\n    }\n  },\n  module: {\n    rules: [\n      {\n        test: /\\.(js|vue)$/,\n        loader: 'eslint-loader',\n        enforce: 'pre',\n        include: [resolve('src'), resolve('test')],\n        options: {\n          formatter: require('eslint-friendly-formatter')\n        }\n      },\n      {\n        test: /\\.vue$/,\n        loader: 'vue-loader',\n        options: vueLoaderConfig\n      }, {\n        test: /\\.scss$/,\n        loaders: ['style', 'css', 'sass']\n      },\n      {\n        test: /\\.js$/,\n        loader: 'babel-loader',\n        include: [resolve('src'), resolve('test')]\n      },\n      {\n        test: /\\.(png|jpe?g|gif|svg)(\\?.*)?$/,\n        loader: 'url-loader',\n        options: {\n          limit: 10000,\n          name: utils.assetsPath('img/[name].[hash:7].[ext]')\n        }\n      },\n      {\n        test: /\\.(woff2?|eot|ttf|otf)(\\?.*)?$/,\n        loader: 'url-loader',\n        options: {\n          limit: 10000,\n          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')\n        }\n      }\n    ]\n  }\n}\n"
  },
  {
    "path": "ymall-web-ui/build/webpack.dev.conf.js",
    "content": "var utils = require('./utils')\nvar webpack = require('webpack')\nvar config = require('../config')\nvar merge = require('webpack-merge')\nvar baseWebpackConfig = require('./webpack.base.conf')\nvar HtmlWebpackPlugin = require('html-webpack-plugin')\nvar FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')\n\n// add hot-reload related code to entry chunks\nObject.keys(baseWebpackConfig.entry).forEach(function (name) {\n  baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])\n})\n\nmodule.exports = merge(baseWebpackConfig, {\n  module: {\n    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })\n  },\n  // cheap-module-eval-source-map is faster for development\n  devtool: '#cheap-module-eval-source-map',\n  plugins: [\n    new webpack.DefinePlugin({\n      'process.env': config.dev.env\n    }),\n    // https://github.com/glenjamin/webpack-hot-middleware#installation--usage\n    new webpack.HotModuleReplacementPlugin(),\n    new webpack.NoEmitOnErrorsPlugin(),\n    // https://github.com/ampedandwired/html-webpack-plugin\n    new HtmlWebpackPlugin({\n      filename: 'index.html',\n      template: 'index.html',\n      inject: true\n    }),\n    new FriendlyErrorsPlugin()\n  ]\n})\n"
  },
  {
    "path": "ymall-web-ui/build/webpack.prod.conf.js",
    "content": "var path = require('path')\nvar utils = require('./utils')\nvar webpack = require('webpack')\nvar config = require('../config')\nvar merge = require('webpack-merge')\nvar baseWebpackConfig = require('./webpack.base.conf')\nvar CopyWebpackPlugin = require('copy-webpack-plugin')\nvar HtmlWebpackPlugin = require('html-webpack-plugin')\nvar ExtractTextPlugin = require('extract-text-webpack-plugin')\nvar OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')\n\nvar env = config.build.env\n\nvar webpackConfig = merge(baseWebpackConfig, {\n  module: {\n    rules: utils.styleLoaders({\n      sourceMap: config.build.productionSourceMap,\n      extract: true\n    })\n  },\n  devtool: config.build.productionSourceMap ? '#source-map' : false,\n  output: {\n    path: config.build.assetsRoot,\n    filename: utils.assetsPath('js/[name].[chunkhash].js'),\n    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')\n  },\n  plugins: [\n    // http://vuejs.github.io/vue-loader/en/workflow/production.html\n    new webpack.DefinePlugin({\n      'process.env': env\n    }),\n    new webpack.optimize.UglifyJsPlugin({\n      compress: {\n        warnings: false\n      },\n      sourceMap: true\n    }),\n    // extract css into its own file\n    new ExtractTextPlugin({\n      filename: utils.assetsPath('css/[name].[contenthash].css')\n    }),\n    // Compress extracted CSS. We are using this plugin so that possible\n    // duplicated CSS from different components can be deduped.\n    new OptimizeCSSPlugin({\n      cssProcessorOptions: {\n        safe: true\n      }\n    }),\n    // generate dist index.html with correct asset hash for caching.\n    // you can customize output by editing /index.html\n    // see https://github.com/ampedandwired/html-webpack-plugin\n    new HtmlWebpackPlugin({\n      filename: config.build.index,\n      template: 'index.html',\n      inject: true,\n      minify: {\n        removeComments: true,\n        collapseWhitespace: true,\n        removeAttributeQuotes: true\n        // more options:\n        // https://github.com/kangax/html-minifier#options-quick-reference\n      },\n      // necessary to consistently work with multiple chunks via CommonsChunkPlugin\n\t  chunksSortMode: 'dependency'\n    }),\n    // split vendor js into its own file\n    new webpack.optimize.CommonsChunkPlugin({\n      name: 'vendor',\n      minChunks: function (module, count) {\n        // any required modules inside node_modules are extracted to vendor\n        return (\n          module.resource &&\n          /\\.js$/.test(module.resource) &&\n          module.resource.indexOf(\n            path.join(__dirname, '../node_modules')\n          ) === 0\n        )\n      }\n    }),\n    // extract webpack runtime and module manifest to its own file in order to\n    // prevent vendor hash from being updated whenever app bundle is updated\n    new webpack.optimize.CommonsChunkPlugin({\n      name: 'manifest',\n      chunks: ['vendor']\n    }),\n    // copy custom static assets\n    new CopyWebpackPlugin([\n      {\n        from: path.resolve(__dirname, '../static'),\n        to: config.build.assetsSubDirectory,\n        ignore: ['.*']\n      }\n    ])\n  ]\n})\n\nif (config.build.productionGzip) {\n  var CompressionWebpackPlugin = require('compression-webpack-plugin')\n\n  webpackConfig.plugins.push(\n    new CompressionWebpackPlugin({\n      asset: '[path].gz[query]',\n      algorithm: 'gzip',\n      test: new RegExp(\n        '\\\\.(' +\n        config.build.productionGzipExtensions.join('|') +\n        ')$'\n      ),\n      threshold: 10240,\n      minRatio: 0.8\n    })\n  )\n}\n\nif (config.build.bundleAnalyzerReport) {\n  var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin\n  webpackConfig.plugins.push(new BundleAnalyzerPlugin())\n}\n\nmodule.exports = webpackConfig\n"
  },
  {
    "path": "ymall-web-ui/config/dev.env.js",
    "content": "var merge = require('webpack-merge')\nvar prodEnv = require('./prod.env')\n\nmodule.exports = merge(prodEnv, {\n  NODE_ENV: '\"development\"'\n})\n"
  },
  {
    "path": "ymall-web-ui/config/index.js",
    "content": "  // see http://vuejs-templates.github.io/webpack for documentation.\nvar path = require('path')\n\nmodule.exports = {\n  build: {\n    env: require('./prod.env'),\n    index: path.resolve(__dirname, '../dist/index.html'),\n    assetsRoot: path.resolve(__dirname, '../dist'),\n    assetsSubDirectory: 'static',\n    assetsPublicPath: '/',\n    productionSourceMap: true,\n    // Gzip off by default as many popular static hosts such as\n    // Surge or Netlify already gzip all static assets for you.\n    // Before setting to `true`, make sure to:\n    // npm install --save-dev compression-webpack-plugin\n    productionGzip: false,\n    productionGzipExtensions: ['js', 'css'],\n    // Run the build command with an extra argument to\n    // View the bundle analyzer report after build finishes:\n    // `npm run build --report`\n    // Set to `true` or `false` to always turn it on or off\n    bundleAnalyzerReport: process.env.npm_config_report\n  },\n  dev: {\n    env: require('./dev.env'),\n    port: 9999,\n    autoOpenBrowser: true,\n    assetsSubDirectory: 'static',\n    assetsPublicPath: '/',\n    proxyTable: {\n      '/api': {\n        target: 'http://127.0.0.1:9090',\n        changeOrigin: true,\n        pathRewrite: {\n          '^/api': ''\n        }\n      }\n    },\n    // CSS Sourcemaps off by default because relative paths are \"buggy\"\n    // with this option, according to the CSS-Loader README\n    // (https://github.com/webpack/css-loader#sourcemaps)\n    // In our experience, they generally work as expected,\n    // just be aware of this issue when enabling this option.\n    cssSourceMap: false\n  }\n}\n"
  },
  {
    "path": "ymall-web-ui/config/prod.env.js",
    "content": "module.exports = {\n  NODE_ENV: '\"production\"'\n}\n"
  },
  {
    "path": "ymall-web-ui/index.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n  <meta charset=\"utf-8\">\n  <title>YMall商城</title>\n  <meta name=\"keywords\" content=\"YMall,YMall商城,YMall开源购物电商商城,Yuu\">\n  <meta name=\"description\" content=\"YMall开源电商商城 作者Yuu\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=Edge\">\n  <meta name=\"wap-font-scale\" content=\"no\">\n  <!-- <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, maximum-scale=1\"> -->\n  <link rel=\"shortcut icon \" type=\"images/x-icon\" href=\"/static/images/Y.png\">\n</head>\n<!-- <script src=\"https://cdn.bootcss.com/vue/2.5.3/vue.min.js\"></script>\n<script src=\"https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js\"></script>\n<script src=\"https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js\"></script>\n<script src=\"https://cdn.bootcss.com/axios/0.17.1/axios.min.js\"></script> -->\n<body>\n  <div id=\"app\"></div>\n  <!-- built files will be auto injected -->\n</body>\n\n</html>\n<style>\n  body{\n\tmin-width:1250px;\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/package.json",
    "content": "{\n  \"name\": \"vue-node-mall\",\n  \"version\": \"1.0.0\",\n  \"description\": \"A Vue.js project\",\n  \"author\": \"Yuu\",\n  \"private\": true,\n  \"scripts\": {\n    \"dev\": \"node build/dev-server.js\",\n    \"start\": \"node build/dev-server.js\",\n    \"build\": \"node build/build.js\",\n    \"lint\": \"eslint --ext .js,.vue src\"\n  },\n  \"dependencies\": {\n    \"axios\": \"^0.16.2\",\n    \"element-china-area-data\": \"^4.1.2\",\n    \"element-ui\": \"^1.4.13\",\n    \"geetest3\": \"^1.0.0\",\n    \"gitment\": \"0.0.3\",\n    \"qrcode\": \"^1.3.4\",\n    \"v-vuerify-next\": \"^0.2.0\",\n    \"vue\": \"^2.5.16\",\n    \"vue-area-linkage\": \"^5.1.0\",\n    \"vue-axios\": \"^2.1.4\",\n    \"vue-content-placeholders\": \"^0.2.1\",\n    \"vue-cookie\": \"^1.1.4\",\n    \"vue-cropper\": \"^0.1.7\",\n    \"vue-infinite-scroll\": \"^2.0.2\",\n    \"vue-lazyload\": \"^1.2.2\",\n    \"vue-piczoom\": \"^1.0.6\",\n    \"vue-qr\": \"^2.1.0\",\n    \"vue-router\": \"^2.8.1\",\n    \"vue2.0-zoom\": \"^2.1.1\",\n    \"vuerify\": \"^0.4.0\",\n    \"vuex\": \"^2.5.0\"\n  },\n  \"devDependencies\": {\n    \"autoprefixer\": \"^6.7.2\",\n    \"babel-core\": \"^6.22.1\",\n    \"babel-eslint\": \"^7.1.1\",\n    \"babel-loader\": \"^6.2.10\",\n    \"babel-plugin-component\": \"^0.10.1\",\n    \"babel-plugin-syntax-jsx\": \"^6.18.0\",\n    \"babel-plugin-transform-runtime\": \"^6.22.0\",\n    \"babel-plugin-transform-vue-jsx\": \"^3.7.0\",\n    \"babel-preset-env\": \"^1.6.1\",\n    \"babel-preset-stage-2\": \"^6.22.0\",\n    \"babel-register\": \"^6.22.0\",\n    \"chalk\": \"^1.1.3\",\n    \"connect-history-api-fallback\": \"^1.5.0\",\n    \"copy-webpack-plugin\": \"^4.5.1\",\n    \"css-loader\": \"^0.28.11\",\n    \"element-theme-default\": \"^1.4.13\",\n    \"eslint\": \"^3.19.0\",\n    \"eslint-config-standard\": \"^6.2.1\",\n    \"eslint-friendly-formatter\": \"^2.0.7\",\n    \"eslint-loader\": \"^1.7.1\",\n    \"eslint-plugin-html\": \"^2.0.0\",\n    \"eslint-plugin-promise\": \"^3.7.0\",\n    \"eslint-plugin-standard\": \"^2.0.1\",\n    \"eventsource-polyfill\": \"^0.9.6\",\n    \"express\": \"^4.16.3\",\n    \"extract-text-webpack-plugin\": \"^2.0.0\",\n    \"file-loader\": \"^0.11.1\",\n    \"friendly-errors-webpack-plugin\": \"^1.7.0\",\n    \"html-webpack-plugin\": \"^2.28.0\",\n    \"http-proxy-middleware\": \"^0.17.3\",\n    \"js-md5\": \"^0.7.3\",\n    \"node-sass\": \"^4.14.1\",\n    \"opn\": \"^4.0.2\",\n    \"optimize-css-assets-webpack-plugin\": \"^1.3.0\",\n    \"ora\": \"^1.4.0\",\n    \"rimraf\": \"^2.6.2\",\n    \"sass-loader\": \"^6.0.7\",\n    \"semver\": \"^5.5.0\",\n    \"shelljs\": \"^0.7.6\",\n    \"url-loader\": \"^0.5.8\",\n    \"vue-loader\": \"^12.1.0\",\n    \"vue-style-loader\": \"^3.1.2\",\n    \"vue-template-compiler\": \"^2.5.16\",\n    \"webpack\": \"^2.6.1\",\n    \"webpack-bundle-analyzer\": \"^2.11.1\",\n    \"webpack-dev-middleware\": \"^1.12.2\",\n    \"webpack-hot-middleware\": \"^2.22.0\",\n    \"webpack-merge\": \"^4.1.2\"\n  },\n  \"engines\": {\n    \"node\": \">= 4.0.0\",\n    \"npm\": \">= 3.0.0\"\n  },\n  \"browserslist\": [\n    \"> 1%\",\n    \"last 2 versions\",\n    \"not ie <= 8\"\n  ]\n}\n"
  },
  {
    "path": "ymall-web-ui/src/App.vue",
    "content": "<template>\n  <div id=\"app\">\n    <router-view class=\"main\"></router-view>\n  </div>\n</template>\n<script>\n  export default {\n    name: 'app'\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\">\n  @import \"assets/style/index.scss\";\n\n  #app {\n    height: 100%;\n  }\n\n  .main {\n    background: #ededed;;\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/api/cart.js",
    "content": "import http from './public'\n// 添加商品到购物车\nexport const addCartProduct = (params) => {\n  return http.fetchPost('/api/member/cart/addProduct', params)\n}\n// 获取购物车列表\nexport const getCartList = (params) => {\n  return http.fetchGet('/api/member/cart/getCartList', params)\n}\n// 删除购物车商品\nexport const delCartProduct = (params) => {\n  return http.fetchPost('/api/member/cart/delProduct', params)\n}\n// 修改购物车商品\nexport const editCartProduct = (params) => {\n  return http.fetchPost('/api/member/cart/editProduct', params)\n}\n// 编辑全选购物车\nexport const editCheckAll = (params) => {\n  return http.fetchPost('/api/member/cart/editCheckAll', params)\n}\n// 删除购物车已选中\nexport const delCartChecked = (params) => {\n  return http.fetchPost('/api/member/cart/delChecked', params)\n}\n"
  },
  {
    "path": "ymall-web-ui/src/api/goods.js",
    "content": "import http from './public'\n// 商品列表\nexport const getAllGoods = (params) => {\n  return http.fetchGet('/api/goods/getCategoryGoods', params)\n}\n// 商品详情\nexport const productDet = (params) => {\n  return http.fetchGet('/api/goods/productDet', params)\n}\n// 商品列表\nexport const getSearch = (params) => {\n  return http.fetchGet('/api/goods/search', params)\n}\n// 快速搜索\nexport const getQuickSearch = (params) => {\n  return http.fetchGet('/api/goods/quickSearch', params)\n}\n"
  },
  {
    "path": "ymall-web-ui/src/api/index.js",
    "content": "import http from './public'\n// 登陆\nexport const memberLogin = (params) => {\n  return http.fetchPost('/api/member/login', params)\n}\n// 极验验证码\nexport const geetest = (params) => {\n  return http.fetchGet('/api/member/geetestInit?t=' + (new Date()).getTime(), params)\n}\n// 阿里验证码\nexport const vercode = (params) => {\n  return http.fetchGet('/api/member/sendsms/' + params.phone, null)\n}\n// 验证手机号是否存在\nexport const checkPhone = (params) => {\n  return http.fetchGet('/api/member/checkphone/' + params.value, null)\n}\n// 验证邮箱是否存在\nexport const checkEmail = (params) => {\n  return http.fetchGet('/api/member/checkEmail', params)\n}\n// 验证手机号或邮箱是存在\nexport const checkAccount = (params) => {\n  return http.fetchGet('/api/member/checkAccount', params)\n}\n// 发送手机或邮箱验证码\nexport const forgetVerCode = (params) => {\n  return http.fetchGet('/api/member/forgetVerCode', params)\n}\n// 修改密码\nexport const updatePassword = (params) => {\n  return http.fetchPost('/api/member/updatePassword', params)\n}\n// 用户信息\nexport const userInfo = (params) => {\n  return http.fetchGet('/api/member/checkLogin', params)\n}\n// 注册账号\nexport const register = (params) => {\n  return http.fetchPost('/api/member/register', params)\n}\n// 首页接口\nexport const productHome = (params) => {\n  return http.fetchGet('/api/goods/home', params)\n}\n// 获取分类信息\nexport const cateList = (params) => {\n  return http.fetchGet('/api/goods/cateList', params)\n}\n// 推荐板块\nexport const recommend = (params) => {\n  return http.fetchGet('/api/goods/recommend', params)\n}\n\n"
  },
  {
    "path": "ymall-web-ui/src/api/member.js",
    "content": "import http from './public'\n// 获取会员地址列表\nexport const addressList = (params) => {\n  return http.fetchGet('/api/member/addressList', params)\n}\n// 修改会员地址\nexport const addressUpdate = (params) => {\n  return http.fetchPost('/api/member/addressUpdate', params)\n}\n// 新增会员地址\nexport const addressAdd = (params) => {\n  return http.fetchPost('/api/member/addressAdd', params)\n}\n// 删除会员地址\nexport const addressDel = (params) => {\n  return http.fetchPost('/api/member/addressDel', params)\n}\n// 会员修改头像\nexport const uploadImg = (params) => {\n  return http.fetchPost('/api/member/uploadImg', params)\n}\n// 修改会员昵称\nexport const updateUsername = (params) => {\n  return http.fetchPost('/api/member/updateUsername', params)\n}\n// 修改手机号\nexport const updatePhone = (params) => {\n  return http.fetchPost('/api/member/updatePhone', params)\n}\n// 修改密码\nexport const updatePass = (params) => {\n  return http.fetchPost('/api/member/updatePass', params)\n}\n// 退出登陆\nexport const logout = (params) => {\n  return http.fetchGet('/api/member/logout', params)\n}\n// 更改邮箱发送邮件验证\nexport const sendEmailCode = (params) => {\n  return http.fetchGet('/api/member/sendEmailCode', params)\n}\n// 修改邮箱\nexport const updateEmail = (params) => {\n  return http.fetchPost('/api/member/updateEmail', params)\n}\n"
  },
  {
    "path": "ymall-web-ui/src/api/order.js",
    "content": "import http from './public'\n// 提交订单\nexport const submitOrder = (params) => {\n  return http.fetchPost('/api/order/addOrder', params)\n}\n// 获取订单详情\nexport const getOrderDet = (params) => {\n  return http.fetchGet('/api/order/getOrderDet', params)\n}\n// 订单支付\nexport const payment = (params) => {\n  return http.fetchPost('/api/order/payment', params)\n}\n// 获取订单支付状态\nexport const getOrderStatus = (params) => {\n  return http.fetchGet('/api/order/getOrderStatus', params)\n}\n// 获取会员订单\nexport const getOrderList = (params) => {\n  return http.fetchGet('/api/order/orderList', params)\n}\n// 确认收货\nexport const confirmReceipt = (params) => {\n  return http.fetchPost('/api/order/confirmReceipt', params)\n}\n// 删除订单\nexport const deleteOrder = (params) => {\n  return http.fetchPost('/api/order/deleteOrder', params)\n}\n// 取消订单\nexport const cancelOrder = (params) => {\n  return http.fetchPost('/api/order/cancelOrder', params)\n}\n"
  },
  {
    "path": "ymall-web-ui/src/api/public.js",
    "content": "import axios from 'axios'\naxios.defaults.timeout = 30000\naxios.defaults.headers.post['Content-Type'] = 'application/x-www=form-urlencoded'\nexport default {\n  fetchGet (url, params = {}) {\n    return new Promise((resolve, reject) => {\n      axios.get(url, params).then(res => {\n        resolve(res.data)\n      }).catch(error => {\n        reject(error)\n      })\n    })\n  },\n  fetchPost (url, params = {}) {\n    return new Promise((resolve, reject) => {\n      axios.post(url, params).then(res => {\n        resolve(res.data)\n      }).catch(error => {\n        reject(error)\n      })\n    })\n  }\n}\n"
  },
  {
    "path": "ymall-web-ui/src/assets/icon/iconfont.css",
    "content": "\n@font-face {font-family: \"iconfont\";\n  src: url('iconfont.eot?t=1507378437149'); /* IE9*/\n  src: url('iconfont.eot?t=1507378437149#iefix') format('embedded-opentype'), /* IE6-IE8 */\n  url('data:application/x-font-woff;charset=utf-8;base64,d09GRgABAAAAAAvMAAsAAAAAEQwAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABHU1VCAAABCAAAADMAAABCsP6z7U9TLzIAAAE8AAAARAAAAFZW8UlpY21hcAAAAYAAAAChAAACGDcJ1AZnbHlmAAACJAAAB3IAAAoA3a2KqGhlYWQAAAmYAAAALwAAADYPHRAEaGhlYQAACcgAAAAcAAAAJAfeA4tobXR4AAAJ5AAAABQAAAAoJ+kAAGxvY2EAAAn4AAAAFgAAABYMJgjSbWF4cAAAChAAAAAdAAAAIAEeASduYW1lAAAKMAAAAUUAAAJtPlT+fXBvc3QAAAt4AAAAVAAAAG9o9X8deJxjYGRgYOBikGPQYWB0cfMJYeBgYGGAAJAMY05meiJQDMoDyrGAaQ4gZoOIAgCKIwNPAHicY2Bk/sc4gYGVgYOpk+kMAwNDP4RmfM1gxMjBwMDEwMrMgBUEpLmmMDgwVDyvZG7438AQw9zA0AwUZgTJAQAueAzveJzFkV0OgkAMhGf5U8QHA4YnjuDJPAEk3oLEJy/ERYZjwHRLTNB3bfNt0tm0u5kCyAGk4iYyILwQYPGUGqKe4hT1DHfVNS5SEvSs2LBlx5HTPCyL7kyrP7R9BPVbXt9pWq7ZCY6aW+CAUlLx1fmzCP97eh/neD62Sq6g39AXWTm2P9aO7Y+NIz/B1pGzYOfYrjk6chucHPmOeXBQrtpJLfUAAAB4nG1VW4zcVhn2f46Pjz2e8W18mZ3dGY/t7Hh3k8zu3Owk2+wlCSikSRqyTdKSFraNUKXQNkghLJckSiqhpFWFqBBFiArohdsD6hNvEYoqFAkVeIEHLqVKlQjaUsELSDxkHf4zmzQg8OX497H/y/ed//+PxCTp9jv0Cq1JVWlK6kp7pEOSBMpmiA3SgCgddMhm8CLmBa5B0ySNeBJ36E4IYsX1e9mgHShcMcGAJvSjXpZ2SArDwQKZh57fABgbr684kxMO/RqUamnzK8U+8gp4YTJhLmwtPrZl0e21qupa2XHGHOd5VWFMJUQ2DXgq8DWmlZTiNWbWvSvhNAmhPJbW9z9caY07j10ePN2YDDSACxegOt4yfrho1228ztb9qjPGrYpaq1eSTS6s3dRr1XKjfUPCgyDWa/Qq3YVYQ0TZxtD9oAl5kHv9IE8hazMD0vYgz3o4TaYevvnQCjy45/XDhy5dgktQvNyeKP4RHYlaYXQ0CoH8Hb/iP8vj6SEY/fHI4dcvh9CKjsRhGB0RPkvo87os0ZakS65Ul1rSJuR5izQnDaQljKED6QLkTQjQsQEblFZnIQ+BpYsQcOh7iRfdO1nkTZNh347svhfZEazuPk7I8d0b43SWHc6ytYkH3NNx8cxSfNp9AH6AFEm3pbt3cR2Wiqvke8X167cuXC8wNFj9UH/38QKEhcPZ+vpPxu5Lf6OWftu+bwyOLG0cF5aWyNX1pSW6JMkCHP2A3EAse6XL0rOSNBkhmCGiQUSDdprfeYsQnGcADwS8gN95G3ZgkOXDQTuJYqWB2eMq3HN9kUPDycRzRQa2d0ISt4WReRjekfI+rs8iZCHkePuuCf0Ni5il/Z4vpKRLf3rrxSAEMMuwqdPZBGUTIAzoyf+d687Pdy391i91a0OiA90qrq2qbIKpqwoH4Mrqnef9D1LqqNrq46rmUHpk/39/RQi1V9EmLW0/uL1E0c2rtSb838lf2CtPrthrZdMsr90TX9ujqKqyBz0rPFeVcTT7iFxiVc5PfkZVq7IuP4puxhU15woGJ+hnozU4Td7EnBpKB6Sj0qcwoyIDGsC7GJHIpnyYC5ozsQyeLWaGdgdAVO88LOAKDdoxMs9wSDqQjNYItZDUvlhFFrcHWc93leiuQKeKldbMd3nJ1OClCvg2fN/2dVuH6fVfqbquPt4ogW6VAI61h+znyqA9k+czyUC9pg6S6TwvVmqt1myrBU/VwnCu1SJvwkz45eNM+5em69rfPsEq5y0fwLeKE8IavBzOFC+gPRKRg1zX+cFPz01OzkG2ksFMHM8I4ZvC3t1LUILk3L5M/0i/IJWlQGpKsTQtdaQd0keRHcECdqoODO0ktTF1IkA+0irmU8pD4Glu0hxSLzAhh0hUYxoJUvKRLJLV9cnNxlRxUS/ebUzVAtjVhRi+hY/OMWf1/CedZ+P5eGWdhS+BfXb+3X1OcYa4pUqltP6BGP9DpvsgbRZXijVIG+TXnXW5uwzwHXi0uwvWv/pQ9bHzJ2yebJt019m3Q3DOLs//2doPfyk7ZQAcXiw7lYpTvtvXztG36AXsLLOIEasniXBI27MggC6I1ux7doJFl0SBoKAvMmOSDyM8ydvI9numcf/nntfK4FnkactfBEMvmn9wrZu6AbDzZ8UbmCw7/mT5P1JLfGr5IHN0csv2fbu48X7JPKWHlfW3Tf3HF9+4+MzFUTzv0CfpMnbZ1qjH5V2s3A5mnSh/X+HYADzsuz4GgeSTNV6rTA+BfPaVUxSGM5WGduzrsvLWs8/9nrNvHIcuRLNbzu154uTJJz5ybvPMJAlP5BN7ewC9vRPbTjQliv5uoL8JANyI6qKzp7EySxB+7M8CPsSYttMOiL1KXLkQMp7gDsCVNhclowQitkBsCFkuTgw5E/WBilgjLnabtAlt8Qiw7bg5HymjGQ/1hc0PTYvZOEu40p+BNN5wjsNdwRfLIqze+zJM24sw4AugYG8TN8/Fo5dkQS/fCCfDV56PJnt9PxxFEtw5cbfdCMxvB2ILYVlPNEclRtuDIBeFi5FhCdOj1ZoZWp7rupRQoqjcIkQrl52qPVMtqaY7hhyWuKoTIKo2tdmKLG8CtNLWODswm+t+vTzfOzCMpzkDypnCKprMACiF0SETFGVeUhiBUqVhMSC6FSYOoWXD8HEDYJQQYKjMaAlbtWESmRhJs6Ir6M9qVBQFrWg6l4VFwoRN1KBACCNEpZSoBAxzEkE6VrPmOBxkTijHz0zVUKdRG/fqhuW6jUaNylTdUMIo199TTOUM08Xwpb8ys6y8r5g6ecEi6IcQdA9UlrGysMc4tsE0ptq1qiBBZkwAU/E/WUn8A9u37zw9+PjO9rjCOA83Lx/d9sWlXm9rOdBVRdYq+DeROSUY0465rgnEsewwNEwMw6/P+QqQSjVu4ryqa6aOWwega6YbWklHSW9EhqEiZG+2XjGQnLFmaFsuQtF6/UWEicwwgQh1NlRlqjDNGatWOZHFhGBuvObZJUYE1yPrCBAj+6einEHM7PPMPPU7wYQY/g3PhnyyAAB4nGNgZGBgAGI7/veS8fw2Xxm4WRhA4Oq/Z6wI+n8tCwNzA5DLwcAEEgUAJNcKjwB4nGNgZGBgbvjfwBDDwgACQJKRARVwAQBHEAJzeJxjYWBgYH7JwMDCgB8DACNPAREAAAAAAHYAsAEcAd4CagLiAyoDYgUAAAB4nGNgZGBg4GKUZuBiAAEmEA/M/g/mMwAADPsBRwAAAHicZY9NTsMwEIVf+gekEqqoYIfkBWIBKP0Rq25YVGr3XXTfpk6bKokjx63UA3AejsAJOALcgDvwSCebNpbH37x5Y08A3OAHHo7fLfeRPVwyO3INF7gXrlN/EG6QX4SbaONVuEX9TdjHM6bCbXRheYPXuGL2hHdhDx18CNdwjU/hOvUv4Qb5W7iJO/wKt9Dx6sI+5l5XuI1HL/bHVi+cXqnlQcWhySKTOb+CmV7vkoWt0uqca1vEJlODoF9JU51pW91T7NdD5yIVWZOqCas6SYzKrdnq0AUb5/JRrxeJHoQm5Vhj/rbGAo5xBYUlDowxQhhkiMro6DtVZvSvsUPCXntWPc3ndFsU1P9zhQEC9M9cU7qy0nk6T4E9XxtSdXQrbsuelDSRXs1JErJCXta2VELqATZlV44RelzRiT8oZ0j/AAlabsgAAAB4nG3JSwqAMAxF0bx+rNZVFlqpEyOJQd29glPP8F5y9Mn0L8PBIyBiQMKICRkz4Rr3onqy1LBuCw83W7c1lVqlqca3N/FsRzBtkrS/m43oAU4lE+0=') format('woff'),\n  url('iconfont.ttf?t=1507378437149') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+*/\n  url('iconfont.svg?t=1507378437149#iconfont') format('svg'); /* iOS 4.1- */\n}\n\n[class^=\"el-icon\"], [class*=\" el-icon\"] {\n  font-family:\"iconfont\" !important;\n  \n  /* 以下内容参照第三方图标库本身的规则 */\n  font-size: 16px;\n  font-style:normal;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n}\n\n.el-icon-password:before { content: \"\\e613\"; }\n\n.el-icon-info:before { content: \"\\e61c\"; }\n\n.el-icon-youhui:before { content: \"\\e612\"; }\n\n.el-icon-address:before { content: \"\\e60b\"; }\n\n.el-icon-order:before { content: \"\\e693\"; }\n\n.el-icon-out:before { content: \"\\e6c9\"; }\n\n.el-icon-user:before { content: \"\\e616\"; }\n\n.el-icon-shouhou:before { content: \"\\e779\"; }\n\n"
  },
  {
    "path": "ymall-web-ui/src/assets/style/common.scss",
    "content": ".w {\n  width: 1220px;\n  margin: 0 auto;\n}\n\n.fl {\n  float: left;\n}\n\n.fr {\n  float: right;\n}\n\n.pr {\n  position: relative;\n}\n\n.pa {\n  position: absolute;\n}\n\n.active {\n  color: #c81623;\n}\n\n.clearfix:after {\n  content: '';\n  display: block;\n  clear: both;\n  line-height: 0;\n  visibility: hidden;\n}\n\n.clearfix {\n  *zoom: 1\n}\n\n.ellipsis {\n  overflow: hidden;\n  text-overflow: ellipsis;\n  white-space: nowrap;\n}\n\n// 删除按钮\n.del-btn {\n  display: block;\n  cursor: pointer;\n  width: 20px;\n  height: 20px;\n  background: url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) -50px -60px no-repeat;\n  background-size: 240px 107px;\n  text-indent: -9999em;\n  &:hover {\n    background-position: -75px -60px;\n  }\n}\n\n.layout-container {\n  min-height: 400px;\n  background: #E6E6E6;\n}\n\n.gray-box {\n  overflow: hidden;\n  background: #fff;\n  border-radius: 8px;\n  border: 1px solid #dcdcdc;\n  border-color: rgba(0, 0, 0, .14);\n  box-shadow: 0 3px 8px -6px rgba(0, 0, 0, .1);\n}\n\n\n"
  },
  {
    "path": "ymall-web-ui/src/assets/style/index.scss",
    "content": "// @import \"reset\";\n@import \"./reset.scss\";\n@import \"common\";\n"
  },
  {
    "path": "ymall-web-ui/src/assets/style/mixin.scss",
    "content": "%block-center {\n  display: flex;\n  align-items: center;\n  justify-content: center;\n}\n\n@mixin wh($w,$h:$w) {\n  width: $w;\n  height: $h;\n}\n"
  },
  {
    "path": "ymall-web-ui/src/assets/style/reset.scss",
    "content": "* {\n  padding: 0;\n  margin: 0;\n  box-sizing: border-box;\n}\n\nbody {\n  font-family: PingFang SC, Helvetica Neue, Helvetica, Arial, Hiragino Sans GB, Microsoft Yahei, \\\\5FAE\\8F6F\\96C5\\9ED1, STHeiti, \\\\534E\\6587\\7EC6\\9ED1, sans-serif;\n  color: #666;\n  font-size: 14px;\n}\n\na {\n  font-style: normal;\n  text-decoration: none;\n  color: #5079d9;\n  cursor: pointer;\n  transition: all .15s ease-out;\n  &:hover {\n    color: #6b95ea;\n  }\n}\n\nli {\n  list-style-type: none;\n}\n\ninput,\nimg,\nbutton {\n  border: none;\n  outline: none;\n}\n\nh1, h2, h3, h4, h5, h6 {\n  font-size: 100%;\n  font-weight: 400;\n}\n\ni, em {\n  font-style: normal;\n}\n\ninput[type=number], textarea {\n  -moz-appearance: textfield;\n}\n\ninput[type=number]::-webkit-inner-spin-button,\ninput[type=number]::-webkit-outer-spin-button,\ninput[type=\"submit\"],\ninput[type=\"search\"],\ninput[type=\"reset\"] {\n  -webkit-appearance: none;\n}\n::-webkit-input-placeholder { /* WebKit browsers */\n    color:    #BEBEBE;\n}\n:-moz-placeholder { /* Mozilla Firefox 4 to 18 */\n    color:    #BEBEBE;\n}\n::-moz-placeholder { /* Mozilla Firefox 19+ */\n    color:    #BEBEBE;\n}\n:-ms-input-placeholder { /* Internet Explorer 10+ */\n    color:    #BEBEBE;\n}"
  },
  {
    "path": "ymall-web-ui/src/assets/style/theme.scss",
    "content": "// 主色\n$main-col: #5079d9;\n// 头部\n$head-bgc: #1a1a1a;\n// 字体颜色\n$cc: #ccc;\n$c6: #666;\n$c9: #999;\n$c3: #333;\n$cf: #fff\n"
  },
  {
    "path": "ymall-web-ui/src/common/footer.vue",
    "content": "<template>\n  <div class=\"footer\">\n    <div class=\"container\">\n      <div class=\"copyright\">\n        <h4 class=\"content-c2\">Copyright ©2019 <a href=\"https://www.71yuu.com/\" target=\"_blank\">71yuu.com</a> All Rights Reserved.本网站设计内容大部分属锤子科技</h4>\n        <ul class=\"privacy\">\n          <li class=\"content-c1\"><a class=\"content-c0\" @click=\"open1\">法律声明</a></li>\n          <li class=\"content-c1\"><a class=\"content-c0\" @click=\"open2\">隐私条款</a></li>\n          <li class=\"content-c1\"><a class=\"content-c0\" target=\"_blank\" href=\"https://github.com/71yuu\">开发者中心</a></li>\n        </ul>\n      </div>\n    </div>\n  </div>\n</template>\n<script>\n  export default {\n    data () {\n      return {\n      }\n    },\n    methods: {\n      open1 () {\n        this.$notify.info({\n          title: '法律声明',\n          message: '不承担任何法律问题~'\n        })\n      },\n      open2 () {\n        this.$notify.info({\n          title: '隐私条款',\n          message: '您在本网站将没有任何隐私~'\n        })\n      }\n    }\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\" scoped>\n  .footer {\n    border-top: 1px solid #e6e6e6;\n    background: #fafafa;\n    margin-top: 60px;\n    height: 171px;\n    display: flex;\n    flex-direction: column;\n    align-items: center;\n    padding-top: 41px;\n    padding-left: 150px;\n  }\n\n  .container {\n    width: 1220px;\n  }\n\n  .copyright {\n    text-align: center;\n    color: #434d55;\n    font-size: 20px;\n    padding: 40px 0 0;\n    display: flex;\n    align-items: left;\n    margin:0 auto;\n  }\n\n  .privacy {\n    float: left;\n    margin: 0 0 0 12px;\n  }\n\n  .content-c0 {\n    color: #5079d9;\n    cursor: pointer;\n    text-decoration: none;\n    &:hover {\n      color: #3A5FCD;\n    }\n  }\n\n  .content-c1 {\n    float: left;\n    line-height: 12px;\n    padding: 1px 10px 0;\n    border-left: 1px solid #ccc;\n  }\n\n  .content-c2 {\n    float: left;\n    height: 15px;\n    line-height: 15px;\n    color: #757575;\n  }\n\n  .cop {\n    clear: both;\n    padding: 10px 0 0;\n    height: 15px;\n  }\n\n  .content-c3 {\n    margin-right: 20px;\n    color: #bdbdbd;\n    font-size: 12px;\n    height: 12px;\n    line-height: 1;\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/common/header.vue",
    "content": "<template>\n  <div class=\"header-box\">\n    <div>\n      <header class=\"w\">\n        <div class=\"w-box\">\n          <div class=\"nav-logo\">\n            <h1>\n              <router-link to=\"/\" title=\"YMall商城官网\">YMall商城</router-link>\n            </h1>\n          </div>\n          <div class=\"right-box\">\n            <div class=\"nav-list\">\n              <el-autocomplete\n                placeholder=\"请输入商品信息\"\n                icon=\"search\"\n                v-model=\"key\"\n                minlength=1\n                maxlength=100\n                :fetch-suggestions=\"querySearchAsync\"\n                @select=\"handleSearch\"\n                :on-icon-click=\"handleSearch\"\n                @keydown.enter.native=\"handleSearch\">\n              </el-autocomplete>\n              <router-link to=\"/goods\"><a>全部商品</a></router-link>\n            </div>\n\n            <div class=\"nav-aside\" ref=\"aside\" :class=\"{fixed:st}\">\n              <div class=\"user pr\">\n                <router-link to=\"/user\">个人中心</router-link>\n                <!--用户信息显示-->\n                <div class=\"nav-user-wrapper pa\" v-if=\"login\">\n                  <div class=\"nav-user-list\">\n                    <ul>\n                      <!--头像-->\n                      <li class=\"nav-user-avatar\">\n                        <div>\n                          <span class=\"avatar\" :style=\"{backgroundImage:'url('+userInfo.info.file+')'}\">\n                          </span>\n                        </div>\n                        <p class=\"name\">{{userInfo.info.username}}</p>\n                      </li>\n                      <li>\n                        <router-link to=\"/user/orderList\">我的订单</router-link>\n                      </li>\n                      <li>\n                        <router-link to=\"/user/information\">账号资料</router-link>\n                      </li>\n                      <li>\n                        <router-link to=\"/user/addressList\">收货地址</router-link>\n                      </li>\n                      <li>\n                        <a href=\"javascript:;\" @click=\"_logout\">退出</a>\n                      </li>\n                    </ul>\n                  </div>\n                </div>\n              </div>\n              <div class=\"shop pr\" @mouseover=\"cartShowState(true)\" @mouseout=\"cartShowState(false)\"\n                   ref=\"positionMsg\">\n                <router-link to=\"/cart\"></router-link>\n                <span class=\"cart-num\">\n                  <i class=\"num\" :class=\"{no:totalNum <= 0,move_in_cart:receiveInCart}\">{{totalNum}}</i>\n                </span>\n                <!--购物车显示块-->\n                <div class=\"nav-user-wrapper pa active\" v-show=\"showCart\">\n                  <div class=\"nav-user-list\">\n                    <div class=\"full\" v-show=\"totalNum\">\n                      <!--购物列表-->\n                      <div class=\"nav-cart-items\">\n                        <ul>\n                          <li class=\"clearfix\" v-for=\"(item,i) in cartList\" :key=\"i\">\n                            <div class=\"cart-item\">\n                              <div class=\"cart-item-inner\">\n                                <a @click=\"openProduct(item.productId)\">\n                                  <div class=\"item-thumb\">\n                                    <img :src=\"item.productImg\">\n                                  </div>\n                                  <div class=\"item-desc\">\n                                    <div class=\"cart-cell\"><h4>\n                                      <a href=\"\" v-text=\"item.productName\"></a>\n                                    </h4>\n                                      <!-- <p class=\"attrs\"><span>白色</span></p> -->\n                                      <h6><span class=\"price-icon\">¥</span><span\n                                        class=\"price-num\">{{item.salePrice}}</span><span\n                                        class=\"item-num\">x {{item.productNum}}</span>\n                                      </h6></div>\n                                  </div>\n                                </a>\n                                <div class=\"del-btn del\" @click=\"delGoods(item.productId)\">删除</div>\n                              </div>\n                            </div>\n                          </li>\n                        </ul>\n                      </div>\n                      <!--总件数-->\n                      <div class=\"nav-cart-total\"><p>共 <strong>{{totalNum}}</strong> 件商品</p> <h5>合计：<span\n                        class=\"price-icon\">¥</span><span\n                        class=\"price-num\">{{totalPrice}}</span></h5>\n                        <h6>\n                          <y-button classStyle=\"main-btn\"\n                                    style=\"height: 40px;width: 100%;margin: 0;color: #fff;font-size: 14px;line-height: 38px\"\n                                    text=\"去购物车\" @btnClick=\"toCart\"></y-button>\n                        </h6>\n                      </div>\n                    </div>\n                    <div v-show=\"!totalNum\" style=\"height: 313px;text-align: center\" class=\"cart-con\">\n                      <p>您的购物车竟然是空的!</p>\n                    </div>\n                  </div>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </header>\n      <slot name=\"nav\">\n        <div class=\"nav-sub\" :class=\"{fixed:st}\" style=\"height:70px;\">\n          <div class=\"nav-sub-wrapper\" :class=\"{fixed:st}\">\n              <el-menu style=\"background-color: #f7f7f7; width: 100%; \" mode=\"horizontal\" @select=\"handleSelect\">\n                <el-menu-item index=\"1\"><a @click=\"toHome\">首页</a></el-menu-item>\n                <el-submenu v-for=\"(cate,i) in cateList\" :index=\"i+1 + ''\" :key=\"i\" >\n                  <template slot=\"title\"><span @click=\"toCategory(cate.id)\">{{cate.name}}</span></template>\n                  <el-menu-item :index=\"i + '-' + j\" v-for=\"(cateSon,j) in cate.catesons\" @click=\"toCategory(cateSon.id)\" :key=\"j\">{{cateSon.name}}</el-menu-item>\n                </el-submenu>\n              </el-menu>\n            </div>\n        </div>\n      </slot>\n    </div>\n  </div>\n</template>\n<script>\n  import YButton from '/components/YButton'\n  import { mapMutations, mapState } from 'vuex'\n  import { getQuickSearch } from '../api/goods'\n  import { cateList } from '../api/index'\n  import { logout } from '/api/member'\n  import { getCartList, delCartProduct } from '../api/cart'\n  import { setStore, getStore, removeStore } from '../utils/storage'\n\n  export default {\n    data () {\n      return {\n        st: false,\n        // 导航栏文字样式改变\n        choosePage: -1,\n        // 搜索框的值\n        key: '',\n        // 搜索联想的值\n        searchResults: [],\n        option: 'xxxx',\n        activeIndex: '1',\n        cateList: [],\n        // 购物车位置\n        positionL: 0,\n        positionT: 0\n      }\n    },\n    methods: {\n      ...mapMutations(['INIT_BUYCART', 'ADD_ANIMATION', 'SHOW_CART', 'EDIT_CART']),\n      // 异步查询\n      querySearchAsync (queryString, cb) {\n        if (this.key === undefined) {\n          cb([])\n          return\n        }\n        this.key = this.key.trim()\n        if (this.key === '') {\n          cb([])\n          return\n        } else {\n          this.loadAll()\n          setTimeout(() => {\n            cb(this.searchResults)\n          }, 300)\n        }\n      },\n      // 搜索框提示\n      loadAll () {\n        let params = {\n          params: {\n            key: this.key\n          }\n        }\n        getQuickSearch(params).then(res => {\n          if (res.status === 200) {\n            let result = res.result.result\n            let array = []\n            for (let i = 0; i < result.length; i++) {\n              let obj = {}\n              obj.value = result[i].productName\n              array.push(obj)\n            }\n            if (array.length !== 0) {\n              this.searchResults = array\n            } else {\n              this.searchResults = []\n            }\n          }\n        })\n      },\n      // 点击搜索事件\n      handleSearch (item) {\n        this.input = item.value\n        if (this.$route.path === '/search') {\n          this.$router.push({\n            path: '/refreshsearch',\n            query: {\n              key: this.key\n            }\n          })\n        } else {\n          this.$router.push({\n            path: '/search',\n            query: {\n              key: this.key\n            }\n          })\n        }\n      },\n      // 退出登录\n      _logout () {\n        let params = {\n          params: {\n            token: this.token\n          }\n        }\n        logout(params).then(res => {\n          removeStore('token')\n          removeStore('userId')\n          removeStore('userInfo')\n          removeStore('buyCart')\n          window.location.href = '/'\n        })\n      },\n      // 去首页\n      toHome () {\n        this.key = ''\n        this.$router.push({\n          path: '/home'\n        })\n      },\n      // 控制顶部\n      navFixed () {\n        if (this.$route.path === '/goods' || this.$route.path === '/home' || this.$route.path === '/goodsDetails' || this.$route.path === '/search') {\n          var st = document.documentElement.scrollTop || document.body.scrollTop\n          st >= 100 ? this.st = true : this.st = false\n          // 计算小圆当前位置\n          let num = document.querySelector('.num')\n          this.positionL = num.getBoundingClientRect().left\n          this.positionT = num.getBoundingClientRect().top\n          this.ADD_ANIMATION({cartPositionL: this.positionL, cartPositionT: this.positionT})\n        } else {\n          return\n        }\n      },\n      // 选择事件\n      handleSelect () {\n      },\n      // 显示购物车\n      cartShowState (state) {\n        this.SHOW_CART({showCart: state})\n      },\n      // 查看商品详细信息\n      openProduct (productId) {\n        window.open('//' + window.location.host + '/goodsDetails?productId=' + productId)\n      },\n      // 删除商品\n      delGoods (productId) {\n        if (this.login) {\n          // 登录了\n          delCartProduct({userId: getStore('userId'), productId}).then(res => {\n            this.EDIT_CART({productId})\n          })\n        } else {\n          this.EDIT_CART({productId})\n        }\n      },\n      // 路由到购物车组件\n      toCart () {\n        this.$router.push({\n          path: '/cart'\n        })\n      },\n      // 获取分类信息\n      _getCateList () {\n        cateList().then(res => {\n          if (res.status === 200) {\n            this.cateList = res.result\n          }\n        })\n      },\n      // 跳转到分类商品页\n      toCategory (id) {\n        this.$router.push({\n          path: '/goods',\n          query: {\n            category: id\n          }\n        })\n      },\n      // 登录时获取一次购物车\n      _getCartList () {\n        let params = {\n          params: {\n            userId: getStore('userId')\n          }\n        }\n        getCartList(params).then(res => {\n          if (res.status === 200) {\n            setStore('buyCart', res.result)\n          }\n          // 重新初始化一次本地数据\n        }).then(this.INIT_BUYCART)\n      }\n    },\n    computed: {\n      ...mapState([\n        'cartList', 'login', 'receiveInCart', 'userInfo', 'showCart'\n      ]),\n      // 计算价格\n      totalPrice () {\n        let totalPrice = 0\n        this.cartList && this.cartList.forEach(item => {\n          totalPrice += (item.productNum * item.salePrice)\n        })\n        return totalPrice\n      },\n      // 计算数量\n      totalNum () {\n        let totalNum = 0\n        this.cartList && this.cartList.forEach(item => {\n          totalNum += (item.productNum)\n        })\n        return totalNum\n      }\n    },\n    mounted () {\n      this._getCateList()\n      this.token = getStore('token')\n      this.navFixed()\n      if (this.login) {\n        // todo // 登录获取购物车 this._getCartList()\n        this._getCartList()\n      } else {\n        this.INIT_BUYCART()\n      }\n      window.addEventListener('scroll', this.navFixed)\n      window.addEventListener('resize', this.navFixed)\n      if (typeof (this.$route.query.key) !== undefined) {\n        this.key = this.$route.query.key\n      }\n    },\n    components: {\n      YButton\n    }\n  }\n\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\">\n  @import \"../assets/style/theme\";\n  @import \"../assets/style/mixin\";\n\n  .el-submenu__title i {\n    display: none!important;\n  }\n\n  .el-menu {\n    padding-left: 17%;\n    height: 69px;\n  }\n\n  .move_in_cart {\n    animation: mymove .5s ease-in-out;\n  }\n\n  @keyframes mymove {\n    0% {\n      transform: scale(1)\n    }\n    25% {\n      transform: scale(.8)\n    }\n    50% {\n      transform: scale(1.2)\n    }\n    75% {\n      transform: scale(.9)\n    }\n    100% {\n      transform: scale(1)\n    }\n  }\n\n  @-moz-keyframes mymove {\n    0% {\n      transform: scale(1)\n    }\n    25% {\n      transform: scale(.8)\n    }\n    50% {\n      transform: scale(1.2)\n    }\n    75% {\n      transform: scale(.9)\n    }\n    100% {\n      transform: scale(1)\n    }\n  }\n\n  @-webkit-keyframes mymove {\n    0% {\n      transform: scale(1)\n    }\n    25% {\n      transform: scale(.8)\n    }\n    50% {\n      transform: scale(1.2)\n    }\n    75% {\n      transform: scale(.9)\n    }\n    100% {\n      transform: scale(1)\n    }\n  }\n\n  @-o-keyframes mymove {\n    0% {\n      transform: scale(1)\n    }\n    25% {\n      transform: scale(.8)\n    }\n    50% {\n      transform: scale(1.2)\n    }\n    75% {\n      transform: scale(.9)\n    }\n    100% {\n      transform: scale(1)\n    }\n  }\n\n  .header-box {\n    background: $head-bgc;\n    background-image: -webkit-linear-gradient(#000, #121212);\n    background-image: linear-gradient(#000, #121212);\n    width: 100%;\n\n  }\n\n  header {\n    height: 100px;\n    z-index: 30;\n    position: relative;\n  }\n\n  .w-box {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    height: 100%;\n    // position: relative;\n    h1 {\n      height: 100%;\n      display: flex;\n      align-items: center;\n      > a {\n        background: url(/static/images/global-logo-red@2x.png) no-repeat 50%;\n        background-size: cover;\n        display: block;\n        @include wh(50px, 40px);\n        text-indent: -9999px;\n        background-position: 0 0;\n      }\n    }\n    .nav-list {\n      display: flex;\n      justify-content: center;\n      align-items: center;\n      margin-right: 22px;\n      .el-autocomplete{\n        width: 305px;\n      }\n      a {\n        width: 110px;\n        color: #c8c8c8;\n        display: block;\n        font-size: 14px;\n        padding: 0 25px;\n        &:hover {\n          color: #fff;\n        }\n      }\n      a:nth-child(2){\n        // width: 5vw;\n        margin-left: -10px;\n      }\n      // a:nth-child(3){\n      //   width: 5vw;\n      // }\n    }\n    .nav-aside {\n      position: relative;\n      &:before {\n        background: #333;\n        background: hsla(0, 0%, 100%, .2);\n        content: \" \";\n        @include wh(1px, 13px);\n        overflow: hidden;\n        // position: absolute;\n        display: flex;\n        align-items: center;\n        // top: 4px;\n        left: 0;\n      }\n      &.fixed {\n        width: 262px;\n        position: fixed;\n        left: 50%;\n        top: 19px;\n        margin-left: 451px;\n        margin-top: 0;\n        z-index: 32;\n        top: -40px;\n        -webkit-transform: translate3d(0, 59px, 0);\n        transform: translate3d(0, 59px, 0);\n        -webkit-transition: -webkit-transform .3s cubic-bezier(.165, .84, .44, 1);\n        transition: transform .3s cubic-bezier(.165, .84, .44, 1);\n        .user {\n          &:hover {\n            a:before {\n              background-position: -215px 0;\n            }\n          }\n        }\n        .shop {\n          &:hover {\n            a:before {\n              background-position: -210px -22px;\n            }\n          }\n        }\n      }\n    }\n\n    .right-box {\n      display: flex;\n    }\n    .nav-aside {\n      display: flex;\n      align-items: center;\n    }\n    // 用户\n    .user {\n      margin-left: 41px;\n      width: 36px;\n      &:hover {\n        a:before {\n          background-position: -5px 0;\n        }\n        .nav-user-wrapper {\n          top: 18px;\n          visibility: visible;\n          opacity: 1;\n          -webkit-transition: opacity .15s ease-out;\n          transition: opacity .15s ease-out;\n        }\n      }\n      > a {\n        position: relative;\n        @include wh(36px, 20px);\n        display: block;\n        text-indent: -9999px;\n        &:before {\n          content: \" \";\n          position: absolute;\n          left: 8px;\n          top: 0;\n          @include wh(20px);\n          background: url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) -155px 0;\n          background-size: 240px 107px;\n          transition: none;\n        }\n\n      }\n      li + li {\n        text-align: center;\n        position: relative;\n        border-top: 1px solid #f5f5f5;\n        line-height: 44px;\n        height: 44px;\n        color: #616161;\n        font-size: 12px;\n        &:hover {\n          background: #fafafa;\n        }\n        a {\n          display: block;\n          color: #616161;\n        }\n      }\n      .nav-user-avatar {\n        > div {\n          position: relative;\n          margin: 0 auto 8px;\n          @include wh(46px);\n          text-align: center;\n          &:before {\n            content: \"\";\n            position: absolute;\n            left: 0;\n            right: 0;\n            top: 0;\n            bottom: 0;\n            border-radius: 50%;\n            box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06);\n          }\n          .avatar {\n            border-radius: 50%;\n            display: block;\n            @include wh(100%);\n            background-repeat: no-repeat;\n            background-size: contain;\n          }\n\n        }\n        .name {\n          margin-bottom: 16px;\n          font-size: 12px;\n          line-height: 1.5;\n          text-align: center;\n          color: #757575;\n        }\n      }\n      .nav-user-wrapper {\n        width: 168px;\n        transform: translate(-50%);\n        left: 50%;\n      }\n      .nav-user-list {\n        width: 168px;\n        &:before {\n          left: 50%;\n        }\n\n      }\n    }\n    .shop {\n      position: relative;\n      float: left;\n      margin-left: 21px;\n      width: 61px;\n      z-index: 99;\n      &:hover {\n        a:before {\n          content: \" \";\n          background-position: 0 -22px;\n        }\n      }\n      .nav-user-wrapper.active {\n        top: 18px;\n        visibility: visible;\n        opacity: 1;\n        -webkit-transition: opacity .15s ease-out;\n        transition: opacity .15s ease-out;\n      }\n      > a {\n        position: absolute;\n        left: 0;\n        top: 0;\n        bottom: 0;\n        display: block;\n        right: 0;\n        z-index: 1;\n        &:before {\n          display: block;\n          @include wh(30px, 100%);\n          content: \" \";\n          background: url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) 0 -22px;\n          background-size: 240px 107px;\n          background-position: -150px -22px;\n        }\n      }\n      .cart-num {\n        position: relative;\n        display: block;\n        margin-left: 31px;\n        margin-top: -1px;\n        min-width: 30px;\n        text-indent: 0;\n        line-height: 20px;\n        > i {\n          background: #eb746b;\n          background-image: -webkit-linear-gradient(#eb746b, #e25147);\n          background-image: linear-gradient(#eb746b, #e25147);\n          box-shadow: inset 0 0 1px hsla(0, 0%, 100%, .15), 0 1px 2px hsla(0, 0%, 100%, .15);\n          text-align: center;\n          font-style: normal;\n          display: inline-block;\n          @include wh(20px);\n          line-height: 20px;\n          border-radius: 10px;\n          color: #fff;\n          font-size: 12px;\n          &.no {\n            background: #969696;\n            background-image: -webkit-linear-gradient(#A4A4A4, #909090);\n            background-image: linear-gradient(#A4A4A4, #909090);\n            box-shadow: inset 0 0 1px #838383, 0 1px 2px #838383;\n          }\n        }\n\n      }\n      .nav-user-wrapper {\n        right: 0;\n        width: 360px;\n        .nav-user-list {\n          &:before {\n            right: 34px;\n          }\n        }\n      }\n      .nav-user-list {\n        padding: 0;\n        width: 100%;\n        .full {\n          border-radius: 8px;\n          overflow: hidden;\n        }\n        .nav-cart-items {\n          max-height: 363px;\n          overflow-x: hidden;\n          overflow-y: auto;\n        }\n        .cart-item {\n          height: 120px;\n          width: 100%;\n          overflow: hidden;\n          border-top: 1px solid #f0f0f0;\n          &:hover {\n            background: #fcfcfc;\n            .del {\n              display: block;\n            }\n          }\n\n        }\n        li:first-child .cart-item:first-child {\n          border-top: none;\n          border-radius: 8px 8px 0 0;\n          overflow: hidden;\n        }\n        .cart-item-inner {\n          padding: 20px;\n          position: relative;\n        }\n        .item-thumb {\n          position: relative;\n          float: left;\n          width: 80px;\n          height: 80px;\n          border-radius: 3px;\n          &:before {\n            content: \"\";\n            position: absolute;\n            left: 0;\n            right: 0;\n            top: 0;\n            bottom: 0;\n            z-index: 2;\n            border: 1px solid #f0f0f0;\n            border: 0 solid transparent;\n            box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06);\n            border-radius: 3px;\n          }\n          img {\n            display: block;\n            @include wh(80px, 80px);\n            border-radius: 3px;\n            overflow: hidden;\n          }\n        }\n        .item-desc {\n          margin-left: 98px;\n          display: table;\n          @include wh(205px, 80px);\n          h4 {\n            color: #000;\n            width: 185px;\n            overflow: hidden;\n            word-break: keep-all;\n            white-space: nowrap;\n            text-overflow: ellipsis;\n            font-size: 14px;\n            line-height: 16px;\n            margin-bottom: 10px;\n          }\n          .attrs span {\n            position: relative;\n            display: inline-block;\n            margin-right: 20px;\n            font-size: 14px;\n            line-height: 14px;\n            color: #999;\n          }\n          .attrs span:last-child {\n            margin-right: 0;\n          }\n          h6 {\n            color: #cacaca;\n            font-size: 12px;\n            line-height: 14px;\n            margin-top: 20px;\n            span {\n              display: inline-block;\n              font-weight: 700;\n              color: #cacaca;\n            }\n            .price-icon, .price-num {\n              color: #d44d44;\n            }\n            .price-num {\n              margin-left: 5px;\n              font-size: 14px;\n            }\n            .item-num {\n              margin-left: 10px;\n            }\n          }\n\n        }\n        .cart-cell {\n          display: table-cell;\n          vertical-align: middle;\n        }\n        .del {\n          display: none;\n          overflow: hidden;\n          position: absolute;\n          right: 20px;\n          top: 50%;\n          transform: translateY(-50%);\n        }\n      }\n      .nav-cart-total {\n        box-sizing: content-box;\n        position: relative;\n        padding: 20px;\n        height: 40px;\n        background: #fafafa;\n        border-top: 1px solid #f0f0f0;\n        border-radius: 0 0 8px 8px;\n        box-shadow: inset 0 -1px 0 hsla(0, 0%, 100%, .5), 0 -3px 8px rgba(0, 0, 0, .04);\n        background: -webkit-linear-gradient(#fafafa, #f5f5f5);\n        background: linear-gradient(#fafafa, #f5f5f5);\n        p {\n          margin-bottom: 4px;\n          line-height: 16px;\n          font-size: 12px;\n          color: #c1c1c1;\n        }\n        h5 {\n          line-height: 20px;\n          font-size: 14px;\n          color: #6f6f6f;\n          span {\n            font-size: 18px;\n            color: #de4037;\n            display: inline-block;\n            font-weight: 700;\n          }\n          span:first-child {\n            font-size: 12px;\n            margin-right: 5px;\n          }\n        }\n        h6 {\n          position: absolute;\n          right: 20px;\n          top: 20px;\n          width: 108px;\n        }\n      }\n    }\n  }\n\n  @media (max-height: 780px) {\n    .nav-cart-items {\n      max-height: 423px !important;\n    }\n  }\n\n  @media (max-height: 900px) {\n    .nav-cart-items {\n      max-height: 544px !important;\n    }\n  }\n\n  @media (max-height: 1080px) {\n    .nav-cart-items {\n      max-height: 620px !important;\n    }\n  }\n\n  // 用户信息弹出\n  .nav-user-wrapper {\n    position: absolute;\n    z-index: 30;\n    padding-top: 18px;\n    opacity: 0;\n    visibility: hidden;\n    top: -3000px;\n    .nav-user-list {\n      position: relative;\n      padding-top: 20px;\n      background: #fff;\n      border: 1px solid #d6d6d6;\n      border-color: rgba(0, 0, 0, .08);\n      border-radius: 8px;\n      box-shadow: 0 20px 40px rgba(0, 0, 0, .15);\n      z-index: 10;\n      &:before {\n        position: absolute;\n        content: \" \";\n        background: url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) no-repeat -49px -43px;\n        background-size: 240px 107px;\n        @include wh(20px, 8px);\n        top: -8px;\n        margin-left: -10px;\n      }\n    }\n  }\n\n  .nav-sub {\n    position: relative;\n    z-index: 20;\n    height: 90px;\n    background: #f7f7f7;\n    box-shadow: 0 2px 4px rgba(0, 0, 0, .04);\n    border-bottom: 1px solid #e1e1e1;\n    &.fixed {\n      position: fixed;\n      z-index: 21;\n      height: 60px;\n      top: 0;\n      left: 0;\n      right: 0;\n      border-bottom: 1px solid #dadada;\n      background-image: -webkit-linear-gradient(#fff, #f1f1f1);\n      background-image: linear-gradient(#fff, #f1f1f1);\n    }\n    .nav-sub-wrapper {\n      padding: 6px 0;\n      height: 90px;\n      position: relative;\n      &.fixed {\n        padding: 0;\n        height: 100%;\n        display: flex;\n        align-items: center;\n      }\n      &:after {\n        content: \" \";\n        position: absolute;\n        top: 89px;\n        left: 50%;\n        margin-left: -610px;\n        width: 1220px;\n        background: #000;\n        height: 1px;\n        display: none;\n        opacity: 0;\n        -webkit-transition: opacity .3s ease-in;\n        transition: opacity .3s ease-in;\n      }\n    }\n    .w {\n      display: flex;\n      justify-content: space-between;\n    }\n    .nav-list2 {\n      height: 28px;\n      line-height: 28px;\n      display: flex;\n      align-items: center;\n      height: 100%;\n      li:first-child {\n        padding-left: 0;\n        a {\n          padding-left: 10px;\n        }\n      }\n      li {\n        float: left;\n        padding-left: 2px;\n        a {\n          display: block;\n          padding: 0 10px;\n          color: #666;\n          &.active {\n            font-weight: bold;\n          }\n        }\n        a:hover {\n          color: #5683EA;\n        }\n      }\n      li:before {\n        content: ' ';\n        position: absolute;\n        left: 0;\n        top: 13px;\n        width: 2px;\n        height: 2px;\n        background: #bdbdbd;\n      }\n    }\n  }\n\n  .nav-sub-son {\n    position: relative;\n    z-index: 20;\n    height: 200px;\n    background: #f7f7f7;\n    box-shadow: 0 2px 4px rgba(0, 0, 0, .04);\n    border-bottom: 1px solid #e1e1e1;\n    &.fixed {\n      position: fixed;\n      z-index: 21;\n      height: 60px;\n      top: 0;\n      left: 0;\n      right: 0;\n      border-bottom: 1px solid #dadada;\n      background-image: -webkit-linear-gradient(#fff, #f1f1f1);\n      background-image: linear-gradient(#fff, #f1f1f1);\n    }\n    .nav-sub-wrapper {\n      padding: 14px 0;\n      height: 90px;\n      position: relative;\n      &.fixed {\n        padding: 0;\n        height: 100%;\n        display: flex;\n        align-items: center;\n      }\n      &:after {\n        content: \" \";\n        position: absolute;\n        top: 89px;\n        left: 50%;\n        margin-left: -610px;\n        width: 1220px;\n        background: #000;\n        height: 1px;\n        display: none;\n        opacity: 0;\n        -webkit-transition: opacity .3s ease-in;\n        transition: opacity .3s ease-in;\n      }\n    }\n    .w {\n      display: flex;\n      justify-content: space-between;\n    }\n    .nav-list2 {\n      height: 28px;\n      line-height: 28px;\n      display: flex;\n      align-items: center;\n      height: 100%;\n      li:first-child {\n        padding-left: 0;\n        a {\n          padding-left: 10px;\n        }\n      }\n      li {\n        float: left;\n        padding-left: 2px;\n        a {\n          display: block;\n          padding: 0 10px;\n          color: #666;\n          &.active {\n            font-weight: bold;\n          }\n        }\n        a:hover {\n          color: #5683EA;\n        }\n      }\n      li:before {\n        content: ' ';\n        position: absolute;\n        left: 0;\n        top: 13px;\n        width: 2px;\n        height: 2px;\n        background: #bdbdbd;\n      }\n    }\n  }\n\n  @media (min-width: 1px) {\n    .nav-sub .nav-sub-wrapper:after {\n      display: block;\n    }\n  }\n\n  .cart-con {\n    /*display: flex;*/\n    text-align: center;\n    position: relative;\n    p {\n      padding-top: 185px;\n      color: #333333;\n      font-size: 16px;\n    }\n  }\n\n  .cart-con:before {\n    position: absolute;\n    content: ' ';\n    left: 50%;\n    transform: translate(-50%, -70%);\n    top: 50%;\n    width: 76px;\n    height: 62px;\n    background: url(\"/static/images/cart-empty-new.png\") no-repeat;\n    background-size: cover;\n\n  }\n\n  .nav-goods-panel {\n    margin: 0 auto;\n    min-width: 1220px;\n    visibility: hidden;\n  }\n\n  .nav-goods-panel ul {\n    opacity: 0;\n  }\n\n  .nav-category-list {\n    display: flex;\n    justify-content: center;\n  }\n\n  .nav-category-list li {\n    padding-top: 28px;\n    min-width: 202px;\n  }\n\n  .nav-category-list li {\n    padding-top: 28px;\n    min-width: 202px;\n  }\n\n  .nav-category-item, .nav-category-item > span {\n    display: flex;\n    -webkit-transform: scaleX(-1);\n    transform: scaleX(-1);\n  }\n\n  .nav-category-item, .nav-category-item > span {\n    display: flex;\n    -webkit-transform: scaleX(-1);\n    transform: scaleX(-1);\n  }\n\n  .nav-category-item > span {\n    position: relative;\n    align-items: center;\n    -webkit-writing-mode: horizontal-tb;\n    writing-mode: horizontal-tb;\n    -webkit-writing-mode: lr-tb;\n    writing-mode: lr-tb;\n    margin: 0 0 10px 22px;\n    height: 40px;\n    white-space: nowrap;\n  }\n\n  .nav-category-item, .nav-category-item > span {\n    display: flex;\n    -webkit-transform: scaleX(-1);\n    transform: scaleX(-1);\n  }\n\n  .nav-category-list img {\n    margin-right: 10px;\n    width: 40px;\n    height: 40px;\n  }\n\n  .nav-category-item > span span {\n    display: inline-block;\n    width: 130px;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    font-weight: 700;\n    color: rgba(0,0,0,.8);\n  }\n\n  .nav-category-item a {\n    position: absolute;\n    left: 0;\n    top: 0;\n    width: 100%;\n    height: 100%;\n  }\n\n  a {\n    color: #5079d9;\n    cursor: pointer;\n    transition: all .15s ease-out;\n    text-decoration: none;\n  }\n</style>\n\n"
  },
  {
    "path": "ymall-web-ui/src/components/YButton.vue",
    "content": "<template>\n  <input :type=\"inputType\"\n         readonly\n         :class=\"classStyle\"\n         @click=\"btnClick($event)\"\n         :disabled=\"classStyle==='disabled-btn'\"\n         :value=\"text\">\n</template>\n<script>\n  export default {\n    props: {\n      text: {\n        type: [String, Number],\n        default: '一颗小按钮'\n      },\n      inputType: {\n        type: [String],\n        default: 'button'\n      },\n      classStyle: {\n        type: String,\n        default: 'default-btn'\n      }\n    },\n    methods: {\n      btnClick (event) {\n        this.$emit('btnClick', event)\n      }\n    }\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\" scoped>\n  @import \"../assets/style/theme\";\n\n  %style {\n    width: 100px;\n    height: 30px;\n    line-height: 28px;\n    vertical-align: middle;\n  }\n\n  @mixin color($a,$b,$c) {\n    border: 1px solid $a;\n    border-radius: 4px;\n    font-size: 12px;\n    color: $b;\n    background-color: $c;\n  }\n\n  input {\n    display: inline-block;\n    cursor: pointer;\n    text-align: center;\n    /*> span {*/\n    /*user-select: none;*/\n    /*display: inline-block;*/\n    /*width: 100%;*/\n    /*height: 100%;*/\n    /*}*/\n  }\n\n  /*灰色的按钮*/\n  .gray-btn {\n    border: 1px solid #d5d5d5;\n    color: #646464;\n  }\n\n  // 默认按钮\n  .default-btn {\n    @include color(#e1e1e1, #646464, #f9f9f9);\n    @extend %style;\n    background-image: -webkit-linear-gradient(top, $cf, #f9f9f9);\n    background-image: linear-gradient(180deg, $cf, #f9f9f9);\n    &:hover {\n      background-color: #eee;\n      background-image: -webkit-linear-gradient(top, #f5f5f5, #eee);\n      background-image: linear-gradient(180deg, #f5f5f5, #eee);\n    }\n  }\n\n  // 主色按钮\n  .main-btn {\n    @include color(#5c81e3, #fff, #678ee7);\n    background-image: -webkit-linear-gradient(top, #678ee7, #5078df);\n    background-image: linear-gradient(180deg, #678ee7, #5078df);\n    @extend %style;\n    &:hover {\n      background-color: #6c8cd4;\n      background-image: -webkit-linear-gradient(top, #6c8cd4, #4769c2);\n      background-image: linear-gradient(180deg, #6c8cd4, #4769c2);\n    }\n  }\n\n  // 禁用\n  .disabled-btn {\n    cursor: not-allowed;\n    @include color(#afafaf, $cf, #a9a9a9);\n    @extend %style;\n    background-image: -webkit-linear-gradient(top, #b8b8b8, #a9a9a9);\n    background-image: linear-gradient(180deg, #b8b8b8, #a9a9a9);\n  }\n\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/components/buynum.vue",
    "content": "<template>\n  <!--数量-->\n  <div class=\"item-cols-num clearfix\">\n    <div class=\"select\">\n      <span class=\"down\"\n            @click.stop.prevent=\"down()\"\n            :class=\"{'down-disabled':Num<=1}\">-\n      </span>\n      <span class=\"num\">\n        <input type=\"text\"\n                :class=\"{show:show}\"\n                v-model=\"Num>limit?limit:Num\"\n                @blur=\"blur()\"\n                maxlength=\"3\">\n                  <ul ref=\"ul\">\n                    <li v-for=\"i in numList\" :key=\"i\">{{i}}</li>\n                  </ul>\n      </span>\n      <span class=\"up\" :class=\"{'up-disabled':Num>=limit}\"\n            @click.stop.prevent=\"up()\">+</span>\n    </div>\n  </div>\n</template>\n<script>\n  export default {\n    props: {\n      num: {\n        type: [Number],\n        default: 1\n      },\n      id: {\n        type: [String, Boolean]\n      },\n      checked: {\n        type: [String, Boolean]\n      },\n      limit: {\n        type: Number,\n        default: 10\n      }\n    },\n    data () {\n      return {\n        show: true,\n        flag: true,\n        Num: this.num,\n        numList: []\n      }\n    },\n    methods: {\n      up () {\n        if (this.flag && this.Num < this.limit) {\n          this.ani('up')\n        }\n        return false\n      },\n      down () {\n        if (this.flag && this.Num > 1) {\n          this.ani('down')\n        }\n        return false\n      },\n      blur () {\n        this.Num = this.Num > this.limit ? Number(this.limit) : Number(this.Num)\n        this.$emit('edit-num', this.id, this.Num, this.checked)\n      },\n      ani (opera) {\n        this.flag = false\n        let n = this.Num\n        this.numList = [n - 1, n, n + 1]\n        let ul = this.$refs.ul\n        let ulStyle = ul.style\n        this.show = false\n        ulStyle.zIndex = '99'\n        ulStyle.transition = 'all .2s ease-out'\n        if (opera === 'up') {\n          this.Num++\n          ulStyle.transform = 'translateY(-54px)'\n        } else {\n          this.Num--\n          ulStyle.transform = `translateY(-18px)`\n        }\n        ul.addEventListener('transitionend', () => {\n          this.show = true\n          this.domInt(ulStyle)\n          this.flag = true\n        })\n        ul.addEventListener('webkitAnimationEnd', () => {\n          this.show = true\n          this.domInt(ulStyle)\n          this.flag = true\n        })\n        this.$emit('edit-num', this.Num, this.id, this.checked)\n      },\n      domInt (domStyle) {\n        domStyle.zIndex = '1'\n        domStyle.transition = 'all 0s'\n        domStyle.transform = 'translateY(-36px)' // 回到原位\n      }\n    }\n  }\n</script>\n<style lang=\"scss\" scoped>\n  .select {\n    input {\n      z-index: 10;\n      width: 36px;\n      height: 18px;\n      background-color: #fff;\n      border: none;\n      text-align: center;\n      line-height: 18px;\n      font-size: 14px;\n      padding: 0;\n      color: #666;\n      visibility: hidden;\n      position: relative;\n      border: none;\n      &.show {\n        visibility: visible;\n      }\n    }\n    ul {\n      padding: 0;\n      line-height: 18px;\n      font-size: 14px;\n      display: inline-block;\n      position: absolute;\n      left: 0;\n      list-style: none;\n      width: 36px;\n      font-family: system-ui;\n      z-index: 1;\n      transform: translateY(-36px);\n    }\n    .up.up-disabled, .up.up-disabled:hover {\n      background-position: 0 -240px !important;\n      cursor: not-allowed !important;\n    }\n  }\n\n  /*数量*/\n  .item-cols-num {\n    display: inline-block;\n  }\n\n  .select {\n    height: 40px;\n    padding-top: 4px;\n    input {\n      width: 100%;\n      text-align: center;\n    }\n    .down {\n      background-position: 0 -60px;\n    }\n    .down.down-disabled:hover {\n      background-position: 0 -300px;\n      cursor: not-allowed;\n    }\n    .down, .up {\n      background: url(../../static/images/cart-updown_8303731e15@2x.jpg) no-repeat;\n      overflow: hidden;\n      float: left;\n      width: 34px;\n      height: 37px;\n      background-size: 100% auto;\n      line-height: 40px;\n      text-indent: -9999em;\n      cursor: pointer;\n      user-select: none;\n    }\n    .num {\n      position: relative;\n      overflow: hidden;\n      text-align: center;\n      float: left;\n      width: 36px;\n      height: 18px;\n      margin: 7px 0 0;\n      border: none;\n      border-radius: 3px;\n      line-height: 18px;\n      text-align: center;\n      font-size: 14px;\n    }\n    .up {\n      margin: 0;\n      background-position: 0 0;\n      &:hover {\n        background-position: 0 -120px;\n      }\n    }\n    .down {\n      background-position: 0 -60px;\n      &:hover {\n        background-position: 0 -180px;\n      }\n    }\n  }\n\n  .down.down-disabled {\n    background-position: 0 -300px;\n    cursor: not-allowed;\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/components/countDown.vue",
    "content": "<template>\n  <span :endTime=\"endTime\" :callback=\"callback\" :endText=\"endText\">\n    <slot>\n      {{content}}\n    </slot>\n  </span>\n</template>\n<script>\nexport default {\n  data () {\n    return {\n      content: ''\n    }\n  },\n  props: {\n    endTime: {\n      type: String,\n      default: ''\n    },\n    endText: {\n      type: String,\n      default: '已结束'\n    },\n    callback: {\n      type: Function,\n      default: null\n    }\n  },\n  methods: {\n    countdowm (timestamp) {\n      let self = this\n      let timer = setInterval(function () {\n        let nowTime = new Date()\n        let t = timestamp - nowTime.getTime()\n        if (t > 0) {\n          let day = Math.floor(t / 86400000)\n          let hour = Math.floor((t / 3600000) % 24)\n          let min = Math.floor((t / 60000) % 60)\n          let sec = Math.floor((t / 1000) % 60)\n          hour = hour < 10 ? '0' + hour : hour\n          min = min < 10 ? '0' + min : min\n          sec = sec < 10 ? '0' + sec : sec\n          let format = ''\n          if (day > 0) {\n            format = `${day} 天 ${hour} 小时 ${min} 分 ${sec} 秒`\n          }\n          if (day <= 0 && hour > 0) {\n            format = `${hour} 小时 ${min} 分 ${sec} 秒`\n          }\n          if (day <= 0 && hour <= 0) {\n            format = `${min} 分 ${sec} 秒`\n          }\n          self.content = format\n        } else {\n          clearInterval(timer)\n          self.content = self.endText\n          self._callback()\n        }\n      }, 1000)\n    },\n    _callback () {\n      if (this.callback && this.callback instanceof Function) {\n        this.callback(...this)\n      }\n    }\n  },\n  created () {\n    this.countdowm(this.endTime)\n  }\n}\n</script>\n<style lang='scss' rel='stylesheet/scss' scoped>\n\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/components/mallGoods.vue",
    "content": "<template>\n  <div class=\"good-item\">\n    <div style=\"\">\n      <div class=\"good-img\">\n        <a @click=\"openProduct(msg.productId)\">\n          <img v-lazy=\"msg.picUrl\" :alt=\"msg.productName\" :key=\"msg.picUrl\">\n        </a>\n      </div>\n      <h6 class=\"good-title\" v-html=\"msg.productName\">{{msg.productName}}</h6>\n      <h3 class=\"sub-title ellipsis\">{{msg.subTitle}}</h3>\n      <div class=\"good-price pr\">\n        <div class=\"ds pa\">\n          <a @click=\"openProduct(msg.productId)\">\n            <y-button text=\"查看详情\" style=\"margin: 0 5px\"></y-button>\n          </a>\n          <y-button text=\"加入购物车\"\n                    style=\"margin: 0 5px\"\n                    @btnClick=\"addCart(msg.productId, msg.salePrice, msg.productName, msg.picUrl, msg.limit)\"\n                    classStyle=\"main-btn\">\n          </y-button>\n        </div>\n        <p><span style=\"font-size:14px\">￥</span>{{Number(msg.salePrice).toFixed(2)}}</p>\n      </div>\n    </div>\n  </div>\n</template>\n<script>\n  import YButton from './YButton'\n  import { mapState, mapMutations } from 'vuex'\n  import { addCartProduct } from '../api/cart'\n  import { getStore } from '../utils/storage'\n\n  export default {\n    props: {\n      msg: {\n        salePrice: 0,\n        limit: 10\n      }\n    },\n    data () {\n      return {}\n    },\n    methods: {\n      open (t, m) {\n        this.$notify.info({\n          title: t,\n          message: m\n        })\n      },\n      ...mapMutations(['ADD_CART', 'ADD_ANIMATION', 'SHOW_CART']),\n      // 查看详情\n      openProduct (id) {\n        // 新打开一个窗口\n        window.open('//' + window.location.host + '/goodsDetails?productId=' + id)\n      },\n      // 加入购物车\n      addCart (id, price, name, img, limit) {\n        let cart = this.cartList\n        let flag = true\n        cart.forEach(cart => {\n          if (cart.productId === id && cart.productNum >= limit) {\n            flag = false\n          }\n        })\n        if (!flag) {\n          let msg = '该商品限购' + limit + '件'\n          this.open('限购', msg)\n          return\n        }\n\n        // 动画是否在运动，先不添加\n        if (!this.showMoveImg) {\n          // 登录了直接存在会员下\n          if (this.login) {\n            addCartProduct({userId: getStore('userId'), productId: id, productNum: 1}).then(res => {\n              // 并不重新请求数据\n              this.ADD_CART({productId: id, salePrice: price, productName: name, productImg: img})\n            })\n          } else {\n            // 未登录 vuex 存\n            this.ADD_CART({productId: id, salePrice: price, productName: name, productImg: img, limitNum: limit})\n          }\n\n          // 加入购物车动画\n          var dom = event.target\n          // 获取点击的坐标\n          let elLeft = dom.getBoundingClientRect().left + (dom.offsetWidth / 2)\n          let elTop = dom.getBoundingClientRect().top + (dom.offsetHeight / 2)\n          // 需要触发\n          this.ADD_ANIMATION({moveShow: true, elLeft: elLeft, elTop: elTop, img: img})\n          if (!this.showCart) {\n            this.SHOW_CART({showCart: true})\n          }\n        }\n      }\n    },\n    computed: {\n      ...mapState(['login', 'cartList'])\n    },\n    components: {YButton}\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\" scoped>\n  @import \"../assets/style/mixin\";\n  @import \"../assets/style/theme\";\n\n  .good-item {\n    background: #fff;\n    width: 25%;\n    transition: all .5s;\n    height: 430px;\n    &:hover {\n      transform: translateY(-3px);\n      box-shadow: 1px 1px 20px #999;\n      .good-price p {\n        display: none;\n      }\n      .ds {\n        display: flex;\n      }\n    }\n    .ds {\n      @extend %block-center;\n      width: 100%;\n      display: none;\n    }\n\n    .good-img {\n      img {\n        margin: 50px auto 10px;\n        @include wh(206px);\n        display: block;\n      }\n    }\n    .good-price {\n      margin: 15px 0;\n      height: 30px;\n      text-align: center;\n      line-height: 30px;\n      color: #d44d44;\n      font-family: Arial;\n      font-size: 18px;\n      font-weight: 700;\n    }\n    .good-title {\n      line-height: 1.2;\n      font-size: 16px;\n      color: #424242;\n      margin: 0 auto;\n      padding: 0 14px;\n      text-align: center;\n      overflow: hidden;\n    }\n    h3 {\n      text-align: center;\n      line-height: 1.2;\n      font-size: 12px;\n      color: #d0d0d0;\n      padding: 10px;\n    }\n\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/components/popup.vue",
    "content": "<template>\n    <div class=\"popup\" v-if=\"open\">\n        <div class=\"mask\">\n            <div class=\"content\">\n                <div class=\"topbar\">\n                    <div class=\"dialog-tit\">\n                    <h4>{{title}}</h4>\n                    </div>\n                    <span class=\"close\" @click=\"close\">\n                        <svg t=\"1501234940517\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3014\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"20\" height=\"20\"><path d=\"M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z\" fill=\"#cdcdcd\" p-id=\"3015\"></path></svg>\n                    </span>\n                </div>\n                <div class=\"s-content\">\n                    <slot name=\"content\"></slot>\n                </div>\n\n            </div>\n        </div>\n    </div>\n</template>\n<script>\nexport default {\n  props: {\n    open: {\n      type: Boolean,\n      default: false\n    },\n    title: {\n      type: String,\n      default: '管理收货地址'\n    }\n  },\n  methods: {\n    close () {\n      this.$emit('close')\n    }\n  }\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.popup {\n    position: fixed;\n    top: 0;\n    left: 0;\n    bottom: 0;\n    right: 0;\n    z-index: 1000;\n    text-align: center;\n    transition: opacity .2s ease-in;\n    .mask {\n        display: flex;\n        justify-content: center;\n        align-items: center;\n        position: absolute;\n        width: 100%;\n        height: 100%;\n        background: rgba(0, 0, 0, .5);\n    }\n    .content {\n        width: 30%;\n        background: #fff;\n        border-radius: 10px;\n    }\n    .topbar {\n        position: relative;\n        z-index: 10;\n        overflow: hidden;\n        width: 100%;\n        height: 60px;\n        background: #F5F5F5;\n        background: linear-gradient(#FFF,#F5F5F5);\n        border-bottom: 1px solid #DCDCDC;\n        border-radius: 10px 10px 0 0;\n        box-shadow: 2px 0 5px rgba(0,0,0,.1);\n    }\n    .dialog-tit {\n        height: 60px;\n        padding: 0 15px;\n        line-height: 60px;\n         h4 {\n        text-align: center;\n        font-size: 18px;\n        font-weight: 400;\n        color: #666;\n        }\n    }\n    .s-content{\n        padding: 30px 42px;\n    }\n    .close{\n        position: absolute;\n        right: 10px;\n        top: 50%;\n        transform:translateY(-50%);\n        width: 20px;\n        height: 20px;\n        &:hover{\n            svg{\n            transition: all 1s;\n            transform: rotate(360deg);\n            transform-origin:50% 50%;\n            }\n            path{\n                fill: #8a8a8a;\n            }\n        }\n    }\n}\n</style>\n\n"
  },
  {
    "path": "ymall-web-ui/src/components/product.vue",
    "content": "<template>\n  <div class=\"item\" id=\"product.spu.id\">\n    <div class=\"img-box\">\n      <img :src=\"product.spu.sku_info[0].ali_image\" alt=\"\">\n    </div>\n    <div class=\"info\">\n      <h6 class=\"ellipsis\">{{product.spu.sku_info[0].title}}</h6>\n      <p>{{product.spu.sku_info[0].sub_title}}</p>\n    </div>\n    <p class=\"price\">\n      <i>¥</i>\n      <span>{{product.spu.price}}</span>\n    </p>\n    <ul class=\"dot-list\">\n      <li></li>\n    </ul>\n  </div>\n</template>\n<script>\n  export default {\n    props: [\n      'product'\n    ]\n  }\n</script>\n<style scoped lang=\"scss\">\n  @import \"../assets/style/mixin\";\n\n  .item {\n    position: relative;\n    height: 429px;\n    text-align: center;\n    img {\n      display: block;\n      width: 206px;\n      height: 206px;\n    }\n    .img-box {\n      @extend %block-center\n    }\n    .info {\n      width: 100%;\n      padding: 0 10px;\n      h6 {\n        overflow: hidden;\n        font-size: 16px;\n        line-height: 1.2;\n        white-space: nowrap;\n        text-overflow: ellipsis;\n        color: #424242;\n      }\n      p {\n        overflow: hidden;\n        padding-top: 7px;\n        font-size: 12px;\n        line-height: 1.2;\n        white-space: nowrap;\n        text-overflow: ellipsis;\n        color: #b2b2b2;\n      }\n    }\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/components/shelf.vue",
    "content": "<template>\n  <div class=\"gray-box\">\n    <div class=\"title\">\n      <h2>{{title}}</h2>\n      <div>\n        <slot name=\"right\"></slot>\n      </div>\n    </div>\n    <!--内容-->\n    <div>\n      <slot name=\"content\"></slot>\n    </div>\n  </div>\n</template>\n<script>\n  export default {\n    props: [\n      'title'\n    ]\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\" scoped>\n  .gray-box {\n    position: relative;\n    margin-bottom: 30px;\n    overflow: hidden;\n    background: #fff;\n    border-radius: 8px;\n    border: 1px solid #dcdcdc;\n    border-color: rgba(0, 0, 0, .14);\n    box-shadow: 0 3px 8px -6px rgba(0, 0, 0, .1);\n    .title {\n      padding-left: 30px;\n      position: relative;\n      z-index: 10;\n      height: 60px;\n      padding: 0 10px 0 24px;\n      border-bottom: 1px solid #d4d4d4;\n      border-radius: 8px 8px 0 0;\n      box-shadow: rgba(0, 0, 0, .06) 0 1px 7px;\n      background: #f3f3f3;\n      background: -webkit-linear-gradient(#fbfbfb, #ececec);\n      background: linear-gradient(#fbfbfb, #ececec);\n      line-height: 60px;\n      font-size: 18px;\n      color: #333;\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      h2 {\n        font-size: 18px;\n        font-weight: 400;\n        color: #626262;\n        display: inline-block;\n      }\n    }\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/main.js",
    "content": "import Vue from 'vue'\nimport App from './App'\nimport router from './router'\nimport store from './store/'\nimport VueLazyload from 'vue-lazyload'\nimport infiniteScroll from 'vue-infinite-scroll'\nimport VueCookie from 'vue-cookie'\n// import PicZoom from 'vue-piczoom'\nimport { userInfo } from './api'\nimport { Button, Pagination, Checkbox, Col, Menu, Submenu, MenuItem, MenuItemGroup, Icon, Autocomplete, Loading, Message, Notification, Steps, Step, Form, FormItem, Table, TableColumn, Input, Dialog, Select, Option, MessageBox, Cascader } from 'element-ui'\nimport { getStore } from './utils/storage'\nimport VueContentPlaceholders from 'vue-content-placeholders'\nVue.use(VueContentPlaceholders)\nVue.use(Button)\nVue.use(Pagination)\nVue.use(Checkbox)\nVue.use(Col)\nVue.use(Menu)\nVue.use(Submenu)\nVue.use(MenuItem)\nVue.use(MenuItemGroup)\nVue.use(Icon)\nVue.use(Autocomplete)\nVue.use(Steps)\nVue.use(Step)\nVue.use(Form)\nVue.use(FormItem)\nVue.use(Table)\nVue.use(TableColumn)\nVue.use(Input)\nVue.use(Dialog)\nVue.use(Select)\nVue.use(Option)\nVue.use(Cascader)\nVue.component(MessageBox)\nVue.use(Loading.directive)\nVue.prototype.$loading = Loading.service\nVue.prototype.$notify = Notification\nVue.prototype.$message = Message\nVue.prototype.$msgbox = MessageBox\nVue.prototype.$confirm = MessageBox.confirm\nVue.use(infiniteScroll)\nVue.use(VueCookie)\n// Vue.use(PicZoom)\nVue.use(VueLazyload, {\n  // preLoad: 1.3,\n  // error: 'dist/error.png',\n  loading: '/static/images/load.gif'\n  // attempt: 1\n})\nVue.config.productionTip = false\nconst whiteList = ['/home', '/goods', '/login', '/register', '/forgetPassword', '/goodsDetails', '/search', '/cart', '/refreshsearch', '/refreshgoods'] // 不需要登陆的页面\nrouter.beforeEach(function (to, from, next) {\n  let params = {\n    params: {\n      token: getStore('token')\n    }\n  }\n  userInfo(params).then(res => {\n    if (res.status === 500) { // 没登录\n      if (whiteList.indexOf(to.path) !== -1) { // 白名单\n        next()\n      } else {\n        next('/login')\n      }\n    } else {\n      store.commit('RECORD_USERINFO', {info: res.result})\n      if (to.path === '/login') { //  跳转到\n        next({path: '/'})\n      }\n      next()\n    }\n  })\n})\n/* eslint-disable no-new */\nnew Vue({\n  el: '#app',\n  store,\n  router,\n  render: h => h(App)\n})\n"
  },
  {
    "path": "ymall-web-ui/src/page/Cart/cart.vue",
    "content": "<template>\n  <div class=\"shopping-cart\">\n    <y-header>\n      <div slot=\"nav\"></div>\n    </y-header>\n    <div class=\"store-content page-cart\">\n      <div class=\"gray-box\">\n        <!-- 标题 -->\n        <div class=\"title\">\n          <h2>购物清单</h2>\n        </div>\n        <!-- 内容 -->\n        <div v-if=\"cartList.length\">\n          <div class=\"ui-cart\">\n            <div>\n              <!-- 标题 -->\n              <div class=\"cart-table-title\">\n                <span class=\"name\">商品信息</span>\n                <span class=\"operation\">操作</span>\n                <span class=\"subtotal\">小计</span>\n                <span class=\"num\">数量</span>\n                <span class=\"price1\">单价</span>\n              </div>\n              <!-- 列表 -->\n              <div class=\"cart-table\" v-for=\"(item, i) in cartList\" :key=\"i\">\n                <div class=\"cart-group divide pr\" :data-productid=\"item.productId\">\n                  <div class=\"cart-top-items\">\n                    <div class=\"cart-items clearfix\">\n                      <!-- 勾选 -->\n                      <div class=\"items-choose\">\n                        <span class=\"blue-checkbox-new\" :class=\"{'checkbox-on':item.checked === '1'}\"\n                              @click=\"editCart('check', item)\"></span>\n                      </div>\n                      <!-- 图片 -->\n                      <div class=\"items-thumb fl\">\n                        <img :src=\"item.productImg\" alt=\"item.productName\">\n                        <a @click=\"goodDetails(item.productId)\" :title=\"item.productName\" target=\"_blank\"></a>\n                      </div>\n                      <!-- 信息 -->\n                      <div class=\"name hide-row fl\">\n                        <div class=\"name-table\">\n                          <a @click=\"goodsDetails(item.productId)\" :title=\"item.productName\" target=\"_blank\"\n                             v-text=\"item.productName\"></a>\n                          <!-- <ul class=\"attribute\">\n                            <li>白色</li>\n                          </ul> -->\n                        </div>\n                      </div>\n                      <!-- 删除按钮 -->\n                      <div class=\"operation\">\n                        <a class=\"items-delete-btn\" @click=\"delCart(item.productId)\"></a>\n                      </div>\n                      <!-- 商品数量 -->\n                      <div>\n                        <!-- 总价格 -->\n                        <div class=\"subtotal\" style=\"font-size: 14px\">¥ {{Number(item.salePrice * item.productNum).toFixed(2)}}</div>\n                        <!-- 数量 -->\n                        <buy-num :num=\"item.productNum\"\n                                 :id=\"item.productId.toString()\"\n                                 :checked=\"item.checked\"\n                                 style=\"height: 140px;display: flex;align-items: center;justify-content: center;\"\n                                 :limit=\"item.limitNum\"\n                                 @edit-num=\"EditNum\">\n                        </buy-num>\n                        <!-- 价格 -->\n                        <div class=\"price1\">¥ {{item.salePrice}}</div>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n              </div>\n            </div>\n          </div>\n          <div class=\"cart-bottom-bg fix-bottom\">\n            <div class=\"fix-bottom-inner\">\n              <div class=\"cart-bar-operation\">\n                <div>\n                  <div class=\"choose-all\">\n                    <span :class=\"{'checkbox-on': checkAllFlag}\" class=\"blue-checkbox-new\" @click=\"editCheckAll\"></span>\n                    <span @click=\"editCheckAll\">全选</span>\n                  </div>\n                  <div class=\"delete-choose-goods\" @click=\"delChecked\">删除选中的商品</div>\n                </div>\n              </div>\n              <div class=\"shipping\">\n                <div class=\"shipping-box\">\n                  <div class=\"shipping-total shipping-num\">\n                    <h4 class=\"highlight\">已选择 <i v-text=\"checkNum\"></i> 件商品</h4>\n                    <h5>共计 <i v-text=\"totalNum\"></i> 件商品</h5>\n                  </div>\n                  <div class=\"shipping-total shipping-price\">\n                    <h4 class=\"highlight\">应付总额: <span>¥</span> <i v-text=\"Number(checkPrice).toFixed(2)\"></i> </h4>\n                    <h5 class=\"shipping-tips ng-scope\">应付总额不含运费</h5>\n                  </div>\n                </div>\n                <y-button :classStyle=\"checkNum > 0 && submit?'main-btn':'disabled-btn'\"\n                          class=\"big-main-btn\"\n                          style=\"margin: 0;width: 130px;height: 50px;line-height: 50px;font-size: 16px\"\n                          :text=\"checkoutNow\" @btnClick=\"checkout\"></y-button>\n              </div>\n            </div>\n          </div>\n        </div>\n        <div v-else style=\"padding:50px\">\n          <div class=\"cart-e\">\n          </div>\n          <p style=\"text-align: center;padding: 20px;color: #8d8d8d\">你的购物车空空如也</p>\n          <div style=\"text-align: center\">\n            <router-link to=\"/\">\n              <y-button text=\"现在选购\" style=\"width: 150px;height: 40px;line-height: 38px;color: #8d8d8d\"></y-button>\n            </router-link>\n          </div>\n        </div>\n      </div>\n    </div>\n    <y-footer></y-footer>\n  </div>\n</template>\n<script>\n  import YHeader from '/common/header'\n  import { mapState, mapMutations } from 'vuex'\n  import BuyNum from '/components/buynum'\n  import { delCartProduct, editCartProduct, editCheckAll, delCartChecked } from '/api/cart'\n  import { getStore, setStore } from '/utils/storage'\n  import YButton from '/components/YButton'\n  import YFooter from '/common/footer'\n\n  export default {\n    data () {\n      return {\n        userId: 0,\n        checked: '1',\n        cart: [],\n        checkoutNow: '现在结算',\n        submit: true,\n        delArray: []\n      }\n    },\n    computed: {\n      ...mapState(['cartList', 'login']),\n      // 全选\n      checkAllFlag () {\n        return this.checkedCount === this.cartList.length\n      },\n      // 勾选的数量\n      checkedCount () {\n        let i = 0\n        this.delArray = []\n        this.cartList && this.cartList.forEach((item, index) => {\n          if (item.checked === '1') {\n            i++\n          } else {\n            this.delArray.push(index)\n          }\n        })\n        return Number(i)\n      },\n      // 选中的商品数量\n      checkNum () {\n        let checkNum = 0\n        this.cartList && this.cartList.forEach(item => {\n          if (item.checked === '1') {\n            checkNum += (item.productNum)\n          }\n        })\n        return checkNum\n      },\n      // 计算总数量\n      totalNum () {\n        let totalNum = 0\n        this.cartList && this.cartList.forEach(item => {\n          totalNum += (item.productNum)\n        })\n        return totalNum\n      },\n      // 选中的总价格\n      checkPrice () {\n        let totalPrice = 0\n        this.cartList && this.cartList.forEach(item => {\n          if (item.checked === '1') {\n            totalPrice += (item.productNum * item.salePrice)\n          }\n        })\n        return totalPrice\n      }\n    },\n    methods: {\n      ...mapMutations(['INIT_BUYCART', 'EDIT_CART']),\n      // 删除购物车商品\n      delCart (productId) {\n        // 如果登录了，从缓存中删除\n        if (this.login) {\n          delCartProduct({userId: getStore('userId'), productId}).then(res => {\n            if (res.status === 200) {\n              this.EDIT_CART({productId})\n            }\n          })\n        } else {\n          this.EDIT_CART({productId})\n        }\n      },\n      // 编辑购物车商品数量\n      EditNum (productNum, productId, checked) {\n        this._cartEdit(productId, productNum, checked)\n      },\n      // 修改购物车\n      _cartEdit (productId, productNum, checked) {\n        // 登录了修改缓存\n        if (this.login) {\n          editCartProduct({userId: getStore('userId'), productId, checked, productNum}).then(res => {\n            if (res.status === 200) {\n              this.EDIT_CART({productId, productNum, checked})\n            }\n          })\n        } else {\n          this.EDIT_CART({productId, productNum, checked})\n        }\n      },\n      // 修改购物车\n      editCart (type, item) {\n        if (type && item) {\n          let checked = item.checked\n          let productId = item.productId\n          let productNum = item.productNum\n          // 勾选\n          if (type === 'check') {\n            let newChecked = checked === '1' ? '0' : '1'\n            item.checked = newChecked\n            this._cartEdit(productId, productNum, newChecked)\n          }\n        }\n      },\n      // 全选\n      editCheckAll () {\n        let checkAll = !this.checkAllFlag\n        // 登录了修改缓存\n        if (this.login) {\n          editCheckAll({userId: this.userId, checked: checkAll}).then(res => {\n            this.EDIT_CART({checked: checkAll})\n          })\n        } else {\n          this.EDIT_CART({checked: checkAll})\n        }\n      },\n      // 删除选中的商品\n      delChecked () {\n        let cartArr = []\n        this.delArray.forEach((index) => {\n          this.cartList.forEach((item, i) => {\n            if (i === index) {\n              cartArr.push(item)\n            }\n          })\n        })\n        setStore('buyCart', cartArr)\n        this.INIT_BUYCART()\n        if (this.login) {\n          delCartChecked({userId: this.userId}).then(res => {\n            if (res.status === 200) {\n              console.log('删除成功')\n            }\n          })\n        }\n      },\n      // 去结算\n      checkout () {\n        this.checkoutNow = '结算中...'\n        this.submit = false\n        this.$router.push({\n          path: 'checkout'\n        })\n      },\n      // 商品详情\n      goodsDetails (id) {\n        window.open(window.location.origin + '/goodsDetails?productId=' + id)\n      }\n    },\n    mounted () {\n      this.userId = getStore('userId')\n      this.cart = this.cartList\n      this.INIT_BUYCART()\n    },\n    components: {\n      YHeader,\n      BuyNum,\n      YButton,\n      YFooter\n    }\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\" scoped>\n  .store-content {\n    clear: both;\n    width: 1220px;\n    min-height: 600px;\n    padding: 0 0 25px;\n    margin: 0 auto;\n    .gray-box {\n      position: relative;\n      margin-bottom: 30px;\n      overflow: hidden;\n      background: #fff;\n      border-radius: 8px;\n      border: 1px solid #dcdcdc;\n      border-color: rgba(0, 0, 0, .14);\n      box-shadow: 0 3px 8px -6px rgba(0, 0, 0, .1);\n      .title {\n        padding-left: 30px;\n        position: relative;\n        z-index: 10;\n        height: 60px;\n        padding: 0 10px 0 24px;\n        border-bottom: 1px solid #d4d4d4;\n        border-radius: 8px 8px 0 0;\n        box-shadow: rgba(0, 0, 0, .06) 0 1px 7px;\n        background: #f3f3f3;\n        background: -webkit-linear-gradient(#fbfbfb, #ececec);\n        background: linear-gradient(#fbfbfb, #ececec);\n        line-height: 60px;\n        font-size: 18px;\n        color: #333;\n      }\n    }\n    .ui-cart {\n      padding-bottom: 91px;\n      .cart-table-title {\n        position: relative;\n        z-index: 1;\n        line-height: 38px;\n        height: 38px;\n        padding: 0 0 0 30px;\n        font-size: 12px;\n        background: #eee;\n        border-bottom: 1px solid #dbdbdb;\n        border-bottom-color: rgba(0, 0, 0, .08);\n        .name {\n          float: left;\n          text-align: left;\n        }\n        span {\n          width: 137px;\n          float: right;\n          text-align: center;\n          color: #838383;\n        }\n      }\n      .cart-group.divide {\n        .cart-items {\n          border-top: 1px dashed #eee;\n        }\n      }\n      .cart-items {\n        position: relative;\n        height: 140px;\n        margin-left: 74px;\n        /*删除*/\n        .operation {\n          padding: 58px 0 0;\n          font-size: 12px;\n          line-height: 24px;\n          .items-delete-btn {\n            background-image: url(../../../static/images/delete-btn-icon_a35bf2437e@2x.jpg);\n            &:hover {\n              background-position: 0 -36px;\n            }\n          }\n          .items-delete-btn {\n            display: block;\n            width: 24px;\n            height: 24px;\n            margin: 0 auto;\n            color: #C2C2C2;\n            background: url(../../../static/images/delete-btn-icon_a35bf2437e@2x.jpg);\n            -webkit-background-size: 100% auto;\n            background-size: 100% auto;\n            -moz-transition: none;\n            -webkit-transition: none;\n            -o-transition: none;\n            transition: none;\n          }\n        }\n        .subtotal {\n          font-weight: 700;\n        }\n        .item-cols-num,\n        .operation,\n        .price1,\n        .subtotal {\n          overflow: hidden;\n          float: right;\n          width: 137px;\n          text-align: center;\n          color: #666;\n          line-height: 140px;\n        }\n      }\n      .cart-group.divide .cart-top-items:first-child .cart-items {\n        border-top: none;\n      }\n      .items-choose {\n        position: absolute;\n        left: -74px;\n        top: 0;\n        width: 74px;\n        height: 20px;\n        padding: 60px 0 0 31px;\n        font-size: 12px;\n        color: #999;\n      }\n      .items-thumb {\n        position: relative;\n        margin-top: 30px;\n        overflow: hidden;\n        width: 80px;\n        height: 80px;\n      }\n      img {\n        width: 80px;\n        height: 80px;\n      }\n      .cart-items .items-thumb > a, .ui-cart .cart-items .items-thumb > i {\n        position: absolute;\n        left: 0;\n        right: 0;\n        top: 0;\n        bottom: 0;\n        border: 1px solid #fff;\n        border-radius: 3px;\n        border: 0 solid rgba(255, 255, 255, .1);\n        box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06);\n      }\n      .name {\n        width: 380px;\n        margin-left: 20px;\n        color: #323232;\n        display: table;\n        a {\n          color: #333;\n          font-size: 16px;\n        }\n      }\n      .name-table {\n        display: table-cell;\n        vertical-align: middle;\n        height: 140px;\n      }\n      .attribute, .name p {\n        color: #999;\n        font-size: 12px;\n        padding-top: 4px;\n        line-height: 17px;\n      }\n\n    }\n\n  }\n\n  .page-cart {\n    padding-top: 40px;\n    .fix-bottom {\n      height: 90px;\n      width: 100%;\n      position: absolute;\n      bottom: 0;\n      z-index: 1;\n      background-position: center;\n      background: #fdfdfd;\n      background: -webkit-linear-gradient(#fdfdfd, #f9f9f9);\n      background: linear-gradient(#fdfdfd, #f9f9f9);\n      border-top: 1px solid #e9e9e9;\n      box-shadow: 0 -3px 8px rgba(0, 0, 0, .04);\n      .cart-bottom-bg {\n        height: 80px;\n        /*background: url(../img/store/library/cart-wrapper-bg_4c8003c76e.jpg) repeat-x;*/\n        border-top: 1px solid #D9D9D9;\n        border-radius: 0 0 8px 8px;\n      }\n    }\n    .cart-bar-operation {\n      float: left;\n      padding: 35px 26px;\n      font-size: 12px;\n    }\n    .blue-checkbox-new {\n      float: left;\n      margin-right: 9px;\n    }\n    .choose-all, .delete-choose-goods, .selected-count {\n      float: left;\n      height: 20px;\n      line-height: 20px;\n      cursor: pointer;\n      position: relative;\n    }\n    .blue-checkbox-new, .blue-checkbox-new.checkbox-disable, .blue-checkbox-new.checkbox-on {\n      display: inline-block;\n      position: relative;\n      width: 20px;\n      height: 20px;\n      background: url(../../../static/images/checkbox-new_631a56a4f6.png) no-repeat 0 -20px;\n      cursor: pointer;\n      -moz-user-select: none;\n      -webkit-user-select: none;\n      -ms-user-select: none;\n      user-select: none;\n      vertical-align: middle;\n    }\n\n    .blue-checkbox-new.checkbox-on, .choose-checkbox-on .blue-checkbox-new {\n      background: url(../../../static/images/checkbox-new_631a56a4f6.png) no-repeat 0 0;\n    }\n    .delete-choose-goods {\n      position: relative;\n      margin-left: 21px;\n      color: #bbb;\n    }\n    .shipping {\n      float: right;\n      padding: 20px 30px;\n    }\n    .shipping-box {\n      display: inline-block;\n      padding-top: 1px;\n      margin-right: 10px;\n    }\n    .shipping-total {\n      display: inline-block;\n      border-left: 1px solid #e1e1e1;\n      padding: 0 20px;\n      .shipping-price {\n        width: 155px;\n        padding-right: 0;\n      }\n      &.shipping-num i {\n        width: 28px;\n        display: inline-block;\n        text-align: center;\n      }\n      h4 {\n        color: #323232;\n        > i {\n          font-size: 18px;\n          font-weight: 700;\n        }\n        i, span {\n          color: #d44d44;\n        }\n\n      }\n      h5 {\n        color: #959595;\n        > i {\n          font-size: 16px;\n          font-weight: 700;\n        }\n      }\n\n    }\n\n    .shipping-total.shipping-num {\n      text-align: right;\n    }\n    .shipping-total:first-child {\n      border: none;\n    }\n    .big-main-btn {\n      float: right;\n      height: 48px;\n    }\n  }\n\n  .cart-e {\n    margin: 0 auto;\n    background: url(\"/static/images/cart-empty_@2x.png\") no-repeat;\n    width: 275px;\n    height: 300px;\n    color: #8d8d8d;\n  }\n\n\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Checkout/checkout.vue",
    "content": "<template>\n  <div class=\"checkout\">\n    <y-header>\n      <div slot=\"nav\"></div>\n    </y-header>\n    <div class=\"w\" style=\"padding-top: 40px;\">\n\n      <!-- 收货地址 -->\n      <y-shelf title=\"收货信息\">\n        <div slot=\"content\">\n          <ul class=\"address-item-list clearfix\">\n            <li v-for=\"(item,i) in addList\"\n                :key=\"i\"\n                class=\"address pr\"\n                :class=\"{checked:addressId === item.id}\"\n                @click=\"chooseAddress(item.id, item.userName, item.tel, item.streetName)\">\n               <span v-if=\"addressId === item.id\" class=\"pa\">\n                 <svg viewBox=\"0 0 1473 1024\" width=\"17.34375\" height=\"12\">\n                   <path\n                     d=\"M1388.020 57.589c-15.543-15.787-37.146-25.569-61.033-25.569s-45.491 9.782-61.023 25.558l-716.054 723.618-370.578-374.571c-15.551-15.769-37.151-25.537-61.033-25.537s-45.482 9.768-61.024 25.527c-15.661 15.865-25.327 37.661-25.327 61.715 0 24.053 9.667 45.849 25.327 61.715l431.659 436.343c15.523 15.814 37.124 25.615 61.014 25.615s45.491-9.802 61.001-25.602l777.069-785.403c15.624-15.868 25.271-37.66 25.271-61.705s-9.647-45.837-25.282-61.717M1388.020 57.589z\"\n                     fill=\"#6A8FE5\" p-id=\"1025\">\n                   </path>\n                 </svg>\n               </span>\n              <p>{{item.userName}}   {{item.isDefault ? '(默认地址)' : ''}}</p>\n              <p>{{item.tel}}</p>\n              <p class=\"street-name ellipsis\">{{item.state}} {{item.city}} {{item.district}}</p>\n              <p class=\"street-name ellipsis\">{{item.streetName}}</p>\n              <div class=\"operation-section\">\n                <span class=\"update-btn\" style=\"font-size:12px\" @click=\"update(item)\">修改</span>\n                <span class=\"delete-btn\" style=\"font-size:12px\" :data-id=\"item.id\" @click=\"_addressDel(item.id)\">删除</span>\n              </div>\n            </li>\n\n            <li class=\"add-address-item\" @click=\"update()\">\n              <img src=\"../../../static/svg/jia.svg\" alt=\"\">\n              <p>使用新地址</p>\n            </li>\n          </ul>\n        </div>\n      </y-shelf>\n\n      <!-- 购物清单 -->\n      <y-shelf title=\"购物清单\">\n        <div slot=\"content\">\n          <div class=\"box-inner ui-cart\">\n            <div>\n              <!--标题-->\n              <div class=\"cart-table-title\">\n                <span class=\"name\">商品信息</span>\n                <span class=\"subtotal\">小计</span>\n                <span class=\"num\">数量</span>\n                <span class=\"price\">单价</span>\n              </div>\n              <!--列表-->\n              <div class=\"cart-table\" v-for=\"(item,i) in cartList\" :key=\"i\" v-if=\"item.checked === '1'\">\n                <div class=\"cart-group divide pr\" :data-productid=\"item.productId\">\n                  <div class=\"cart-top-items\">\n                    <div class=\"cart-items clearfix\">\n                      <!--图片-->\n                      <div class=\"items-thumb fl\">\n                        <img :alt=\"item.productName\"\n                             :src=\"item.productImg\">\n                        <a @click=\"goodsDetails(item.productId)\" :title=\"item.productName\" target=\"_blank\"></a>\n                      </div>\n                      <!--信息-->\n                      <div class=\"name hide-row fl\">\n                        <div class=\"name-table\">\n                          <a @click=\"goodsDetails(item.productId)\" :title=\"item.productName\" target=\"_blank\"\n                             v-text=\"item.productName\"></a>\n                          <!-- <ul class=\"attribute\">\n                            <li>白色</li>\n                          </ul> -->\n                        </div>\n                      </div>\n                      <!--商品数量-->\n                      <div>\n                        <!--总价格-->\n                        <div class=\"subtotal\" style=\"font-size: 14px\">¥ {{item.salePrice * item.productNum}}</div>\n                        <!--数量-->\n                        <div class=\"item-cols-num\">\n                          <span v-text=\"item.productNum\"></span>\n                        </div>\n                        <!--价格-->\n                        <div class=\"price\">¥ {{item.salePrice}}</div>\n                      </div>\n                    </div>\n                  </div>\n                </div>\n              </div>\n            </div>\n            <!-- 合计 -->\n            <div class=\"cart-bottom-bg fix-bottom\">\n              <div class=\"fix-bottom-inner\">\n                <div class=\"shipping\">\n                  <div class=\"shipping-box\" style=\"padding: 0 40px;\">\n                    <div class=\"shipping-total shipping-price\"><h4\n                      class=\"highlight\">应付总额：<em>￥{{checkPrice}}</em>\n                    </h4>\n                    </div>\n                  </div>\n                  <y-button class=\"big-main-btn\"\n                            :classStyle=\"!submit||!goods.length>0?'disabled-btn':'main-btn'\"\n                            style=\"margin: 0;width: 130px;height: 50px;line-height: 50px;font-size: 16px\"\n                            :text=\"submitOrder\"\n                            @btnClick=\"_submitOrder\">\n                  </y-button>\n                </div>\n              </div>\n            </div>\n          </div>\n        </div>\n      </y-shelf>\n\n      <!-- 新增或修改地址 -->\n      <div class=\"edit-address\" v-show=\"editAddressShow\">\n        <y-shelf :title=\"addressTxt\">\n            <span slot=\"right\">\n              <span class=\"close\" @click=\"editAddressShow=false\">\n                <svg t=\"1501234940517\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\"\n                     xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3014\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n                     width=\"20\" height=\"20\"><path\n                  d=\"M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z\"\n                  fill=\"#cdcdcd\" p-id=\"3015\"></path></svg>\n              </span>\n            </span>\n          <div slot=\"content\" class=\"content\">\n            <el-form :model=\"addressVer\" :rules=\"addressVerRules\" ref=\"addressVer\" class=\"register-form\">\n              <el-form-item prop=\"userName\">\n                <el-input v-model=\"addressVer.userName\" size=\"large\" placeholder=\"收货人姓名\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n              </el-form-item>\n              <el-form-item prop=\"phone\">\n                <el-input v-model=\"addressVer.phone\" size=\"large\" placeholder=\"手机号\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n              </el-form-item>\n              <el-form-item>\n                <el-cascader\n                  placeholder=\"请选择地址\"\n                  size=\"large\"\n                  :options=\"options\"\n                  v-model=\"selectedOptions\"\n                  @change=\"handleChange\" style=\"width:296px;\">\n                </el-cascader>\n              </el-form-item>\n              <el-form-item prop=\"streetName\">\n                <el-input v-model=\"addressVer.streetName\" size=\"large\" placeholder=\"街道地址\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n              </el-form-item>\n              <el-checkbox class=\"auto-login\" v-model=\"addressVer.isDefault\">设为默认</el-checkbox>\n            </el-form>\n\n            <div class=\"bootom-btn pa\">\n              <el-button @click=\"editAddressShow=false\" style=\"width: 140px; height: 40px;\">\n                取消\n              </el-button>\n              <el-button @click=\"save({userId:userId,id:addressVer.addressId,userName:addressVer.userName,tel:addressVer.phone,state: addressVer.state, city: addressVer.city, district: addressVer.district, streetName:addressVer.streetName,isDefault:addressVer.isDefault})\" type=\"primary\" :disabled=\"btnHighlight ? false : true\"  style=\"width: 140px; height: 40px;\">\n                确定\n              </el-button>\n            </div>\n          </div>\n        </y-shelf>\n      </div>\n\n      <!--<y-popup :open=\"popupOpen\" @close='popupOpen=false' :title=\"popupTitle\">\n        <div slot=\"content\" class=\"md\" :data-id=\"msg.addressId\">\n          <div>\n            <input type=\"text\" placeholder=\"收货人姓名\" v-model=\"msg.userName\">\n          </div>\n          <div>\n            <input type=\"number\" placeholder=\"手机号码\" v-model=\"msg.tel\">\n          </div>\n          <div>\n            <input type=\"text\" placeholder=\"收货地址\" v-model=\"msg.streetName\">\n          </div>\n          <div>\n            <el-checkbox class=\"auto-login\" v-model=\"msg.isDefault\">设为默认</el-checkbox>\n          </div>\n          <y-button text='保存'\n                    class=\"btn\"\n                    :classStyle=\"btnHighlight?'main-btn':'disabled-btn'\"\n                    @btnClick=\"save({userId:userId,id:msg.addressId,userName:msg.userName,tel:msg.tel,streetName:msg.streetName,isDefault:msg.isDefault})\">\n          </y-button>\n        </div>\n      </y-popup>-->\n    </div>\n    <y-footer></y-footer>\n  </div>\n</template>\n<script>\n  import YHeader from '/common/header'\n  import YFooter from '/common/footer'\n  import YShelf from '/components/shelf'\n  import YButton from '/components/YButton'\n  import { addressList, addressUpdate, addressAdd, addressDel } from '/api/member'\n  import { getCartList } from '/api/cart'\n  import { getStore } from '/utils/storage'\n  import YPopup from '/components/popup'\n  import { submitOrder } from '/api/order'\n  import { productDet } from '/api/goods'\n  import { regionData, CodeToText, TextToCode } from 'element-china-area-data'\n\n  export default {\n    data () {\n      // 验证收货人\n      let vUserName = (rule, value, callback) => {\n        if (!value) {\n          this.verUserName = false\n          return callback(new Error('请输入收货人姓名'))\n        }\n        this.verUserName = true\n        return callback()\n      }\n      // 验收收货手机号\n      let vPhone = (rule, value, callback) => {\n        const phoneReg = /^1[3|4|5|7|8][0-9]\\d{8}$/\n        if (!value) {\n          this.verPhone = false\n          return callback(new Error('请输入手机号'))\n        }\n        if (!phoneReg.test(value)) {\n          this.verPhone = false\n          return callback(new Error('请输入正确的手机号'))\n        }\n        this.verPhone = true\n        return callback()\n      }\n      // 验证街道\n      let vStreetName = (rule, value, callback) => {\n        if (!value) {\n          this.verStreetName = false\n          return callback(new Error('请输入街道地址'))\n        }\n        this.verStreetName = true\n        return callback()\n      }\n      return {\n        addList: [],\n        addressId: '0',\n        userName: '',\n        tel: '',\n        streetName: '',\n        userId: '',\n        addressTxt: '新增收货地址',\n        editAddressShow: false,\n        addressVer: {\n          addressId: '',\n          userName: '',\n          phone: '',\n          state: '',\n          city: '',\n          district: '',\n          streetName: '',\n          isDefault: false\n        },\n        addressVerRules: {\n          userName: [\n            {validator: vUserName, trigger: 'change, blur'}\n          ],\n          phone: [\n            {validator: vPhone, trigger: 'change, blur'}\n          ],\n          streetName: [\n            {validator: vStreetName, trigger: 'change, blur'}\n          ]\n        },\n        verUserName: false,\n        verPhone: false,\n        verStreetName: false,\n        options: regionData,\n        selectedOptions: [],\n        // 详细地址\n        detailedAddress: '',\n        cartList: [],\n        submitOrder: '提交订单',\n        submit: false,\n        orderTotal: 0,\n        goods: []\n      }\n    },\n    computed: {\n      btnHighlight () {\n        return this.verUserName && this.verPhone && this.addressVer.state && this.addressVer.city && this.addressVer.district && this.verStreetName\n      },\n      // 选中的总价格\n      checkPrice () {\n        let totalPrice = 0\n        this.cartList && this.cartList.forEach(item => {\n          if (item.checked === '1') {\n            totalPrice += (item.productNum * item.salePrice)\n          }\n        })\n        this.orderTotal = totalPrice\n        return totalPrice\n      }\n    },\n    methods: {\n      // 获取地址列表\n      _addressList () {\n        let params = {\n          params: {\n            userId: this.userId\n          }\n        }\n        addressList(params).then(res => {\n          if (res.status === 200) {\n            let data = res.result\n            if (data.length) {\n              this.addList = data\n              this.addressId = data[0].id\n              this.userName = data[0].userName\n              this.tel = data[0].tel\n              this.streetName = data[0].streetName\n              this.submit = true\n            } else {\n              this.addList = []\n              this.submit = false\n            }\n          }\n        })\n      },\n      // 选择地址\n      chooseAddress (addressId, userName, tel, streetName) {\n        this.addressId = addressId\n        this.userName = userName\n        this.tel = tel\n        this.streetName = streetName\n      },\n      // 修改地址\n      update (item) {\n        this.editAddressShow = true\n        if (item) {\n          this.addressTxt = '修改收货地址'\n          let state = TextToCode[item.state].code\n          let city = TextToCode[item.state][item.city].code\n          let district = TextToCode[item.state][item.city][item.district].code\n          this.selectedOptions.push(state, city, district)\n          this.addressVer.userName = item.userName\n          this.addressVer.phone = item.tel\n          this.addressVer.state = item.state\n          this.addressVer.city = item.city\n          this.addressVer.district = item.district\n          this.addressVer.streetName = item.streetName\n          this.addressVer.isDefault = item.isDefault\n          this.addressVer.addressId = item.id\n        } else {\n          this.addressTxt = '新增收货地址'\n          this.addressVer.userName = ''\n          this.addressVer.phone = ''\n          this.addressVer.state = ''\n          this.addressVer.city = ''\n          this.addressVer.district = ''\n          this.selectedOptions = []\n          this.addressVer.streetName = ''\n          this.addressVer.isDefault = false\n          this.addressVer.addressId = ''\n        }\n      },\n      // 修改城市选择\n      handleChange (value) {\n        console.log(this.selectedOptions)\n        let addArr = value\n        let state = CodeToText[(addArr[0])]\n        let city = CodeToText[(addArr[1])]\n        let district = CodeToText[(addArr[2])]\n        this.addressVer.state = state\n        this.addressVer.city = city\n        this.addressVer.district = district\n      },\n      // 保存\n      save (p) {\n        this.editAddressShow = false\n        console.log(p.id)\n        if (p.id) {\n          this._addressUpdate(p)\n        } else {\n          delete p.addressId\n          this._addressAdd(p)\n        }\n      },\n      // 修改地址\n      _addressUpdate (params) {\n        addressUpdate(params).then(res => {\n          this._addressList()\n        })\n      },\n      // 新增地址\n      _addressAdd (params) {\n        addressAdd(params).then(res => {\n          this._addressList()\n        })\n      },\n      // 删除地址\n      _addressDel (params) {\n        addressDel({id: params}).then(res => {\n          this._addressList()\n        })\n      },\n      // 获取购物车列表\n      _getCartList () {\n        let userId = this.userId\n        let params = {\n          params: {\n            userId: userId\n          }\n        }\n        getCartList(params).then(res => {\n          if (res.status === 200) {\n            this.cartList = res.result\n            for (let i = 0; i < this.cartList.length; i++) {\n              if (this.cartList[i].checked === '1') {\n                this.goods.push(this.cartList[i])\n              }\n            }\n          }\n        })\n      },\n      // 跳转到商品详情页\n      goodsDetails (id) {\n        window.open(window.location.origin + '/goodsDetails?productId=' + id)\n      },\n      // 错误消息提示\n      message (m) {\n        this.$message.error({\n          message: m\n        })\n      },\n      // 获取商品详情\n      _productDet (productId) {\n        productDet({params: {productId}}).then(res => {\n          let item = res.result\n          item.checked = '1'\n          item.productImg = item.productImageBig\n          item.productNum = this.num\n          item.productPrice = item.salePrice\n          this.cartList.push(item)\n          this.goods.push(item)\n        })\n      },\n      // 提交订单后跳转到付款页面\n      _submitOrder () {\n        this.submitOrder = '提交订单中...'\n        this.submit = true\n        if (this.addressId === '0') {\n          this.message('请选择收货地址')\n          this.submitOrder = '提交订单'\n          this.submit = false\n          return\n        }\n        if (this.cartList.length === 0) {\n          this.message('非法操作')\n          this.submitOrder = '提交订单'\n          this.submit = false\n          return\n        }\n        let params = {\n          userId: this.userId,\n          addressId: this.addressId,\n          tel: this.tel,\n          userName: this.userName,\n          streetName: this.streetName,\n          orderTotal: this.orderTotal,\n          goodsList: this.goods\n        }\n        submitOrder(params).then(res => {\n          if (res.status === 200) {\n            this.payment(res.result)\n          } else {\n            this.message(res.message)\n            this.submitOrder = '提交订单'\n            this.submit = false\n          }\n        })\n      },\n      // 路由到付款页面\n      payment (orderId) {\n        // 需要拿到地址 id\n        this.$router.push({\n          path: '/order/payment',\n          query: {\n            'orderId': orderId\n          }\n        })\n      }\n    },\n    created () {\n      this.userId = getStore('userId')\n      let query = this.$route.query\n      if (query.productId && query.num) {\n        this.productId = query.productId\n        this.num = query.num\n        this._productDet(this.productId)\n      } else {\n        this._getCartList()\n      }\n      this._addressList()\n    },\n    components: {\n      YHeader,\n      YFooter,\n      YShelf,\n      YPopup,\n      YButton\n    }\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\" scoped>\n  @import \"../../assets/style/mixin\";\n\n  // 修改会员地址\n  .edit-address {\n    z-index: 1999;\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    @include wh(100%);\n    background-color: rgba(0, 0, 0, .5);\n    @extend %block-center;\n    .content {\n      display: flex;\n      padding: 45px 100px 0;\n    }\n    > div {\n      box-sizing: content-box;\n      @include wh(500px, 460px);\n      margin: 0;\n    }\n    .btn {\n      width: 80px;\n      height: 30px;\n      margin-left: 10px;\n      position: relative;\n      text-align: center;\n      line-height: 30px;\n      text-shadow: rgba(255, 255, 255, .496094) 0 1px 0;\n      border: 1px solid #E6E6E6;\n      border-radius: 10px;\n      &:hover {\n      }\n      a {\n        color: #666;\n        display: block;\n        @include wh(100%);\n      }\n    }\n    input[type=file] {\n      position: absolute;\n      right: 0;\n      left: 0;\n      top: 0;\n      opacity: 0;\n      width: 80px;\n      height: 30px;\n      cursor: pointer;\n      box-sizing: border-box;\n      border: 15px solid #000;\n      overflow: hidden;\n    }\n    .edit-l {\n      width: 100px;\n      text-align: center;\n    }\n    .edit-r {\n      margin-left: 20px;\n      flex: 1;\n      > div {\n        border: 1px solid #ccc;\n        width: 320px;\n        height: 320px;\n      }\n    }\n  }\n\n  .close {\n    position: absolute;\n    right: 10px;\n    top: 0;\n    bottom: 0;\n    padding: 0 10px;\n    @extend %block-center;\n    &:hover {\n      svg {\n        transition: all 1s;\n        transform: rotate(360deg);\n        transform-origin: 50% 50%;\n      }\n      path {\n        fill: #8a8a8a;\n      }\n    }\n  }\n\n  .bootom-btn {\n    padding: 0 15px;\n    border-top: 1px solid #E6E6E6;\n    bottom: 0;\n    height: 60px;\n    right: 0;\n    left: 0;\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n  }\n\n  // 收货地址\n  .address-item-list {\n    padding: 30px 13px 0;\n    .address {\n      padding: 19px 14px 0 19px;\n      p {\n        line-height: 26px;\n      }\n    }\n    li.checked {\n      border-color: #6A8FE5;\n      position: relative;\n      background: #fff;\n      .pa {\n        right: 15px;\n        top: 18px;\n      }\n      &:hover {\n        background: #fff;\n      }\n    }\n    li {\n      position: relative;\n      overflow: hidden;\n      float: left;\n      width: 276px;\n      height: 158px;\n      margin: 0 0 30px 16px;\n      border: 1px solid #E5E5E5;\n      border-radius: 3px;\n      background: #FAFAFA;\n      line-height: 14px;\n      text-align: left;\n      word-wrap: break-word;\n      word-break: normal;\n      color: #626262;\n      cursor: pointer;\n      -moz-user-select: -moz-none;\n      -webkit-user-select: none;\n      -o-user-select: none;\n      user-select: none;\n      &:hover {\n        background: #F2F2F2;\n        .operation-section {\n          visibility: visible;\n          transform: translate(0, 0);\n        }\n      }\n      &.add-address-item {\n        text-align: center;\n        display: flex;\n        justify-content: center;\n        align-items: center;\n        flex-direction: column;\n        p {\n          margin-top: 5px;\n        }\n      }\n      .operation-section {\n        visibility: hidden;\n        position: absolute;\n        left: 0;\n        bottom: 0;\n        width: 100%;\n        height: 28px;\n        background: #E1E1E1;\n        border-top: 1px solid #E1E1E1;\n        transition: all .2s ease;\n        transform: translate(0, 29px);\n        border-top: 1px solid #E1E1E1;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        z-index: 11;\n        span {\n          background: #fff;\n          display: flex;\n          align-items: center;\n          justify-content: center;\n          flex: 1;\n          height: 100%;\n          &:hover {\n            background: #F2F2F2;\n          }\n        }\n\n        span + span {\n          border-left: 1px solid #E1E1E1;\n        }\n\n      }\n    }\n  }\n\n  .s-content {\n    .md {\n      > div {\n        text-align: left;\n        margin-bottom: 15px;\n        > input {\n          width: 100%;\n          height: 50px;\n          font-size: 18px;\n          padding: 10px 20px;\n          border: 1px solid #ccc;\n          border-radius: 6px;\n          box-shadow: 0 3px 5px -4px rgba(0, 0, 0, .4) inset, -1px 0 3px -2px rgba(0, 0, 0, .1) inset;\n          line-height: 46px;\n        }\n      }\n    }\n\n    .btn {\n      margin: 0;\n      width: 100%;\n      height: 50px;\n      font-size: 14px;\n      line-height: 48px\n    }\n  }\n\n  .ui-cart {\n    img {\n      width: 80px;\n      height: 80px;\n    }\n\n    .cart-table-title {\n      position: relative;\n      z-index: 1;\n      line-height: 38px;\n      height: 38px;\n      padding: 0 0 0 30px;\n      font-size: 12px;\n      background: #eee;\n      border-bottom: 1px solid #dbdbdb;\n      border-bottom-color: rgba(0, 0, 0, .08);\n      .name {\n        float: left;\n        text-align: left;\n      }\n      span {\n        width: 137px;\n        float: right;\n        text-align: center;\n        color: #838383;\n      }\n    }\n    .cart-group.divide {\n      .cart-items {\n        border-top: 1px dashed #eee;\n      }\n    }\n    .cart-items {\n      position: relative;\n      height: 140px;\n      margin-left: 74px;\n      .subtotal {\n        font-weight: 700;\n      }\n      .item-cols-num,\n      .price,\n      .subtotal {\n        overflow: hidden;\n        float: right;\n        width: 137px;\n        text-align: center;\n        color: #666;\n        line-height: 140px;\n      }\n      /*数量*/\n      .subtotal,\n      .item-cols-num {\n        padding-top: 50px;\n        line-height: 40px;\n      }\n      .select {\n        width: 112px;\n        height: 40px;\n        padding-top: 4px;\n        margin: 0 auto;\n        line-height: 40px;\n        .down {\n          background-position: 0 -60px;\n        }\n        .down.down-disabled:hover {\n          background-position: 0 -300px;\n          cursor: not-allowed;\n        }\n        .num {\n          position: relative;\n          overflow: hidden;\n          display: inline-block;\n          width: 36px;\n          height: 18px;\n          margin: 7px 0 0;\n          border: none;\n          border-radius: 3px;\n          line-height: 18px;\n          text-align: center;\n          font-size: 14px;\n          transition: all .2s ease-out;\n        }\n      }\n\n    }\n    .down.down-disabled {\n      background-position: 0 -300px;\n      cursor: not-allowed;\n    }\n  }\n\n  .cart-group.divide .cart-top-items:first-child .cart-items {\n    border-top: none;\n  }\n\n  .items-choose {\n    position: absolute;\n    left: -74px;\n    top: 0;\n    width: 74px;\n    height: 20px;\n    padding: 60px 0 0 31px;\n    font-size: 12px;\n    color: #999;\n  }\n\n  .items-thumb {\n    position: relative;\n    margin-top: 30px;\n    overflow: hidden;\n    width: 80px;\n    height: 80px;\n  }\n\n  .cart-items .items-thumb > a, .ui-cart .cart-items .items-thumb > i {\n    position: absolute;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    border: 1px solid #fff;\n    border-radius: 3px;\n    border: 0 solid rgba(255, 255, 255, .1);\n    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06);\n  }\n\n  .name {\n    width: 380px;\n    margin-left: 20px;\n    color: #323232;\n    display: table;\n    a {\n      color: #333;\n      font-size: 16px;\n    }\n  }\n\n  .name-table {\n    display: table-cell;\n    vertical-align: middle;\n    height: 140px;\n  }\n\n  .fix-bottom {\n    padding: 22px 29px 19px 30px;\n    height: 90px;\n    width: 100%;\n    z-index: 1;\n    background-position: center;\n    background: #fdfdfd;\n    background: -webkit-linear-gradient(#fdfdfd, #f9f9f9);\n    background: linear-gradient(#fdfdfd, #f9f9f9);\n    border-top: 1px solid #e9e9e9;\n    box-shadow: 0 -3px 8px rgba(0, 0, 0, .04);\n    .cart-bottom-bg {\n      height: 80px;\n      border-top: 1px solid #D9D9D9;\n      border-radius: 0 0 8px 8px;\n    }\n    .fix-bottom-inner {\n      height: 100%;\n      display: flex;\n      align-items: center;\n      justify-content: flex-end;\n    }\n    .shipping {\n      display: flex;\n      align-items: center;\n    }\n    em {\n      display: inline-block;\n      position: relative;\n      top: 3px;\n      margin-top: -4px;\n      font-size: 24px;\n      color: #d44d44;\n      font-weight: 700;\n    }\n  }\n\n  .attribute, .name p {\n    color: #999;\n    font-size: 12px;\n    padding-top: 4px;\n    line-height: 17px;\n  }\n\n\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Goods/goods.vue",
    "content": "<template>\n  <div class=\"goods\">\n    <!-- 查询条件 -->\n    <div class=\"nav\">\n      <div class=\"w\">\n        <a href=\"javascript:;\" :class=\"{active:sortType===1}\" @click=\"reset\">综合排序</a>\n        <a href=\"javascript:;\" :class=\"{active:sortType===2}\" @click=\"sortByOrder\">销量排序</a>\n        <a href=\"javascript:;\" :class=\"{active:sortType===3}\" @click=\"sortByPrice(3)\">价格从低到高</a>\n        <a href=\"javascript:;\" :class=\"{active:sortType===4}\" @click=\"sortByPrice(4)\">价格从高到低</a>\n        <div class=\"price-interval\">\n          <el-input type=\"number\" class=\"input\" placeholder=\"价格\" v-model=\"min\" style=\"width:83px;\"></el-input>\n          <span style=\"margin: 0 5px\"> - </span>\n          <el-input type=\"number\" placeholder=\"价格\" v-model=\"max\" style=\"width:83px;\"></el-input>\n          <!--<y-button text=\"确定\" :classStyle=\"min && max ? main-btn : default-btn\" @btnClick=\"_getAllGoods\" style=\"margin-left: 10px;\"></y-button>-->\n          <el-button type=\"primary\" @click=\"_getAllGoods\" :disabled=\"min && max && min < max ? false : true\" style=\"margin-left: 10px;\">确定</el-button>\n        </div>\n      </div>\n    </div>\n\n      <!-- 查询内容 -->\n      <div v-loading=\"loading\" element-loading-text=\"加载中...\" style=\"min-height: 35vw;\">\n        <div class=\"img-item\" v-if=\"!noResult\">\n          <!-- 商品 -->\n          <div class=\"goods-box w\">\n            <mall-goods v-for=\"(item, i) in goods\" :key=\"i\" :msg=\"item\"></mall-goods>\n          </div>\n\n          <!-- 分页 -->\n          <el-pagination\n            v-if=\"!noResult&&!error\"\n            @size-change=\"handleSizeChange\"\n            @current-change=\"handleCurrentChange\"\n            :current-page=\"currentPage\"\n            :page-sizes=\"[8, 20, 40, 80]\"\n            :page-size=\"pageSize\"\n            layout=\"total, sizes, prev, pager, next, jumper\"\n            :total=\"total\">\n          </el-pagination>\n        </div>\n        <!-- 没有结果 -->\n        <div class=\"no-info\" v-if=\"noResult\">\n          <div class=\"no-data\">\n            <img src=\"/static/images/no-search.png\">\n            <br>抱歉！暂时还没有商品\n          </div>\n          <section class=\"section\">\n            <y-shelf :title=\"recommendPanel.name\">\n              <div slot=\"content\" class=\"recommend\">\n                <mall-goods :msg=\"item\" v-for=\"(item,i) in recommendPanel.panelContentDtos\" :key=\"i\"></mall-goods>\n              </div>\n            </y-shelf>\n          </section>\n        </div>\n        <!-- 查询错误 -->\n        <div class=\"no-info\" v-if=\"error\">\n          <div class=\"no-data\">\n            <img src=\"/static/images/error.png\">\n            <br> 抱歉！出错了...\n          </div>\n          <section class=\"section\">\n            <y-shelf :title=\"recommendPanel.name\">\n              <div slot=\"content\" class=\"recommend\">\n                <mall-goods :msg=\"item\" v-for=\"(item,i) in recommendPanel.panelContentDtos\" :key=\"i\"></mall-goods>\n              </div>\n            </y-shelf>\n          </section>\n        </div>\n    </div>\n  </div>\n</template>\n<script>\n  import MallGoods from '/components/mallGoods'\n  import { recommend } from '/api/index'\n  import YShelf from '/components/shelf'\n  import { getAllGoods } from '/api/goods'\n\n  export default {\n    data () {\n      return {\n        recommendPanel: {\n          name: '',\n          panelContentDtos: []\n        },\n        error: false,\n        noResult: false,\n        loading: false,\n        total: 0,\n        goods: [],\n        pageSize: 20,\n        currentPage: 1,\n        sort: '',\n        sortType: 1,\n        min: '',\n        max: ''\n      }\n    },\n    methods: {\n      handleSizeChange (val) {\n        this.pageSize = val\n        this._getAllGoods()\n        this.loading = true\n      },\n      handleCurrentChange (val) {\n        this.currentPage = val\n        this._getAllGoods()\n        this.loading = true\n      },\n      _getAllGoods () {\n        let cid = this.$route.query.category\n        let params = {\n          params: {\n            page: this.currentPage,\n            size: this.pageSize,\n            sort: this.sort,\n            priceGt: this.min,\n            priceLte: this.max,\n            cid: cid\n          }\n        }\n        getAllGoods(params).then(res => {\n          if (res.status === 200) {\n            this.total = res.result.total\n            this.goods = res.result.data\n            this.noResult = false\n            if (this.total === 0) {\n              this.noResult = true\n            }\n            this.error = false\n          } else {\n            this.error = true\n          }\n          this.loading = false\n        })\n      },\n      // 默认排序\n      reset () {\n        this.sortType = 1\n        this.sort = 1\n        this.currentPage = 1\n        this.loading = true\n        this._getAllGoods()\n      },\n      // 销量排序\n      sortByOrder () {\n        this.sortType = 2\n        this.sort = 2\n        this.currentPage = 1\n        this.loading = true\n        this._getAllGoods()\n      },\n      // 价格排序\n      sortByPrice (v) {\n        this.sortType = v\n        this.sort = v\n        this.currentPage = 1\n        this.loading = true\n        this._getAllGoods()\n      }\n    },\n    watch: {\n      $route (to, from) {\n        if (to.fullPath.indexOf('/goods?category=') >= 0) {\n          this.cid = to.query.cid\n          this._getAllGoods()\n        }\n      }\n    },\n    mounted () {\n      this._getAllGoods()\n      recommend().then(res => {\n        if (res.status === 200) {\n          this.recommendPanel = res.result\n          this.error = false\n        } else {\n          this.error = true\n        }\n      })\n    },\n    components: {\n      MallGoods,\n      YShelf\n    }\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\" scoped>\n  @import \"../../assets/style/mixin\";\n  @import \"../../assets/style/theme\";\n\n  .nav {\n    height: 60px;\n    line-height: 60px;\n    > div {\n      display: flex;\n      align-items: center;\n      a {\n        padding: 0 15px;\n        height: 100%;\n        @extend %block-center;\n        font-size: 12px;\n        color: #999;\n        &.active {\n          color: #5683EA;\n        }\n        &:hover {\n          color: #5683EA;\n        }\n      }\n      input {\n        @include wh(80px, 30px);\n        border: 1px solid #ccc;\n      }\n      input + input {\n        margin-left: 10px;\n      }\n    }\n    .price-interval {\n      padding: 0 15px;\n      @extend %block-center;\n      input[type=number] {\n        border: 1px solid #ccc;\n        text-align: center;\n        background: none;\n        border-radius: 5px;\n      }\n    }\n  }\n\n  .goods-box {\n    > div {\n      float: left;\n      border: 1px solid #efefef;\n    }\n  }\n\n  .no-info {\n    padding: 100px 0;\n    text-align: center;\n    font-size: 30px;\n    display: flex;\n    flex-direction: column;\n    .no-data{\n      align-self: center;\n    }\n  }\n\n  .img-item{\n    display: flex;\n    flex-direction: column;\n  }\n\n  .el-pagination{\n    align-self: flex-end;\n    margin: 3vw 10vw 2vw;\n  }\n\n  .section {\n    padding-top: 8vw;\n    margin-bottom: -5vw;\n    width: 1218px;\n    align-self: center;\n  }\n\n  .recommend {\n    display: flex;\n    > div {\n      flex: 1;\n      width: 25%;\n    }\n  }\n\n\n\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Goods/goodsDetails.vue",
    "content": "<!--商品详情-->\n<template>\n  <div class=\"w store-content\">\n    <div class=\"gray-box\">\n      <div class=\"gallery-wrapper\">\n        <!-- 左边 -->\n        <div class=\"gallery\">\n          <div class=\"thumbnail\">\n            <ul>\n              <li v-for=\"(item,i) in small\" :key=\"i\" :class=\"{on:big===item}\" @click=\"big=item\">\n                <img v-lazy=\"item\" :alt=\"product.productName\">\n              </li>\n            </ul>\n          </div>\n          <!--<div class=\"thumb\">\n            <div class=\"big\" style=\"width:100%; height: 100%;\">\n              <pic-zoom :url=\"big\" :scale=\"3\" :alt=\"product.productName\"></pic-zoom>\n              &lt;!&ndash;<img :src=\"big\" :alt=\"product.productName\">&ndash;&gt;\n            </div>\n          </div>-->\n        </div>\n      </div>\n      <!-- 右边 -->\n      <div class=\"banner\">\n        <div class=\"sku-custom-title\">\n          <h4>{{product.productName}}</h4>\n          <h6>\n            <span>{{product.subTitle}}</span>\n            <span class=\"price\">\n              <em>¥</em><i>{{product.salePrice.toFixed(2)}}</i>\n            </span>\n          </h6>\n        </div>\n        <div class=\"num\">\n          <span class=\"params-name\">数量</span>\n          <buy-num @edit-num=\"editNum\" :limit=\"Number(product.limitNum)\"></buy-num>\n          <span class=\"params-name\" style=\"margin-left: 30px;\">库存</span>\n          <span class=\"params-name\">{{product.num}}</span>\n        </div>\n        <div class=\"buy\">\n          <y-button text=\"加入购物车\"\n                    @btnClick=\"addCart(product.productId, product.salePrice, product.productName, product.productImageBig)\"\n                    classStyle=\"main-btn\"\n                    style=\"width: 145px;height: 50px;line-height: 48px\"></y-button>\n          <y-button text=\"现在购买\"\n                    @btnClick=\"checkout(product.productId)\"\n                    style=\"width: 145px;height: 50px;line-height: 48px;margin-left: 10px\"></y-button>\n        </div>\n      </div>\n    </div>\n    <!-- 产品信息 -->\n    <div class=\"item-info\">\n      <y-shelf title=\"产品信息\">\n        <div slot=\"content\">\n          <div class=\"img-item\" v-if=\"productDetail\">\n            <div v-html=\"productDetail\">{{productDetail}}</div>\n          </div>\n          <div class=\"no-info\" v-else>\n            <img src=\"/static/images/no-data.png\">\n            <br>\n            该商品暂无内容数据\n          </div>\n        </div>\n      </y-shelf>\n    </div>\n  </div>\n</template>\n<script>\n  import { productDet } from '/api/goods'\n  import { mapState, mapMutations } from 'vuex'\n  import YButton from '/components/YButton'\n  import BuyNum from '/components/buynum'\n  import { addCartProduct } from '/api/cart'\n  import { getStore } from '/utils/storage'\n  import YShelf from '/components/shelf'\n\n  export default {\n    data () {\n      return {\n        // 商品信息\n        product: {\n          salePrice: 0\n        },\n        small: [],\n        big: '',\n        productNum: 1,\n        userId: '',\n        productDetail: ''\n      }\n    },\n    computed: {\n      ...mapState(['login', 'showMoveImg', 'showCart'])\n    },\n    methods: {\n      ...mapMutations(['ADD_CART', 'ADD_ANIMATION', 'SHOW_CART']),\n      // 获取商品详情\n      _productDet (productId) {\n        productDet({params: {productId}}).then(res => {\n          let result = res.result\n          this.product = result\n          this.small = result.productImageSmall\n          this.big = result.productImageBig\n          this.productDetail = result.detail\n        })\n      },\n      // 添加商品到购物车\n      addCart (id, price, name, img) {\n        // 动画是否在运动\n        if (!this.showMoveImg) {\n          // 登录了，直接存在会员中\n          if (this.login) {\n            addCartProduct({userId: this.userId, productId: id, productNum: this.productNum}).then(res => {\n              // 添加购物车到浏览器 localstoge\n              this.ADD_CART({\n                productId: id,\n                salePrice: price,\n                productName: name,\n                productImg: img,\n                productNum: this.productNum\n              })\n            })\n          } else {  // 未登录，存 vuex\n            this.ADD_CART({\n              productId: id,\n              salePrice: price,\n              productName: name,\n              productImg: img,\n              productNum: this.productNum\n            })\n          }\n        }\n        // 加入购物车动画\n        var dom = event.target\n        // 获取点击的坐标\n        let elLeft = dom.getBoundingClientRect().left + (dom.offsetWidth / 2)\n        let elTop = dom.getBoundingClientRect().top + (dom.offsetHeight / 2)\n        // 需要触发\n        this.ADD_ANIMATION({\n          moveShow: true,\n          elLeft: elLeft,\n          elTop: elTop,\n          img: img\n        })\n        if (!this.showCart) {\n          this.SHOW_CART({showCart: true})\n        }\n      },\n      // 现在购买\n      checkout (productId) {\n        this.$router.push({\n          path: '/checkout',\n          query: {productId, num: this.productNum}\n        })\n      },\n      // 数量组件回调方法\n      editNum (num) {\n        this.productNum = num\n      }\n    },\n    created () {\n      let id = this.$route.query.productId\n      this._productDet(id)\n      this.userId = getStore('userId')\n    },\n    components: {\n      YButton,\n      BuyNum,\n      YShelf\n    }\n  }\n</script>\n<style lang=\"scss\" scoped>\n  @import \"../../assets/style/mixin\";\n\n  .store-content {\n    clear: both;\n    width: 1220px;\n    min-height: 600px;\n    padding: 0 0 25px;\n    margin: 0 auto;\n  }\n\n  .gray-box {\n    display: flex;\n    padding: 60px;\n    margin: 20px 0;\n    .gallery-wrapper {\n      .gallery {\n        display: flex;\n        width: 540px;\n        .thumbnail {\n          li:first-child {\n            margin-top: 0px;\n          }\n          li {\n            @include wh(80px);\n            margin-top: 10px;\n            padding: 12px;\n            border: 1px solid #f0f0f0;\n            border: 1px solid rgba(0, 0, 0, .06);\n            border-radius: 5px;\n            cursor: pointer;\n            &.on {\n              padding: 10px;\n              border: 3px solid #ccc;\n              border: 3px solid rgba(0, 0, 0, .2);\n            }\n            img {\n              display: block;\n              @include wh(100%);\n            }\n          }\n        }\n        .thumb {\n          .big {\n            margin-left: 20px;\n          }\n          img {\n            display: block;\n            @include wh(440px)\n          }\n        }\n      }\n    }\n    // 右边\n    .banner {\n      width: 450px;\n      margin-left: 10px;\n      h4 {\n        font-size: 24px;\n        line-height: 1.25;\n        color: #000;\n        margin-bottom: 13px;\n      }\n      h6 {\n        font-size: 14px;\n        line-height: 1.5;\n        color: #bdbdbd;\n        display: flex;\n        align-items: center;\n        justify-content: space-between;\n      }\n      .sku-custom-title {\n        overflow: hidden;\n        padding: 8px 8px 18px 10px;\n        position: relative;\n      }\n      .params-name {\n        padding-right: 20px;\n        font-size: 14px;\n        color: #8d8d8d;\n        line-height: 36px;\n      }\n      .num {\n        padding: 29px 0 8px 10px;\n        border-top: 1px solid #ebebeb;\n        display: flex;\n        align-items: center;\n      }\n      .buy {\n        position: relative;\n        border-top: 1px solid #ebebeb;\n        padding: 30px 0 0 10px;\n      }\n    }\n  }\n\n  .item-info {\n\n    .gray-box {\n      padding: 0;\n      display: block;\n    }\n    .img-item {\n      width: 1220px;\n      // padding: 1vw;\n      text-align: center;\n      img {\n        width: 100%;\n        height: auto;\n        display: block;\n      }\n    }\n  }\n\n  .no-info {\n    padding: 200px 0;\n    text-align: center;\n    font-size: 30px;\n  }\n\n  .price {\n    display: block;\n    color: #d44d44;\n    font-weight: 700;\n    font-size: 16px;\n    line-height: 20px;\n    text-align: right;\n    i {\n      padding-left: 2px;\n      font-size: 24px;\n    }\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Home/home.vue",
    "content": "<template>\n  <div class=\"home\">\n\n    <div v-loading=\"loading\" element-loading-text=\"加载中...\" style=\"min-height: 35vw;\" v-if=\"!error\">\n      <div class=\"banner\" >\n        <div class=\"bg\" ref=\"bg\"\n             @mouseover=\"bgOver($refs.bg)\" @mousemove=\"bgMove($refs.bg,$event)\" @mouseout=\"bgOut($refs.bg)\">\n          <transition name=\"fade\">\n            <div v-for=\"(item, i) in banner\" v-if=\"i===mark\" :key=\"i\" style=\"position:absolute;\" @click=\"linkTo(item)\" @mouseover=\"stopTimer\" @mouseout=\"startTimer\">\n              <img v-if=\"item.picUrl\" class=\"img1\" :src=\"item.picUrl\"/>\n              <img v-if=\"item.picUrl2\"  class=\"img2 a\" :src=\"item.picUrl2\"/>\n              <img v-if=\"item.picUrl3\"  class=\"img3 b\" :src=\"item.picUrl3\"/>\n            </div>\n          </transition>\n        </div>\n        <div class=\"page\">\n          <ul class=\"dots\">\n            <li class=\"dot-active\" v-for=\"(item, i) in banner\" :class=\"{ 'dot':i!=mark }\" :key=\"i\" @click=\"change(i)\"></li>\n          </ul>\n        </div>\n      </div>\n\n      <div v-for=\"(item, i) in home\" :key=\"i\">\n\n        <div class=\"activity-panel\" v-if=\"item.type === 1\">\n          <ul class=\"box\">\n            <li class=\"content\" v-for=\"(iitem, j) in item.panelContentDtos\" :key=\"j\" @click=\"linkTo(iitem)\">\n              <img :src=\"iitem.picUrl\" class=\"i\"/>\n              <a class=\"cover-link\"></a>\n            </li>\n          </ul>\n        </div>\n\n        <section class=\"w mt30 clearfix\" v-if=\"item.type === 2\">\n          <y-shelf :title=\"item.name\">\n            <div slot=\"content\" class=\"hot\">\n              <mall-goods :msg=\"iitem\" v-for=\"(iitem,j) in item.panelContentDtos\" :key=\"j\"></mall-goods>\n            </div>\n          </y-shelf>\n        </section>\n\n        <section class=\"w mt30 clearfix\" v-if=\"item.type === 3\">\n          <y-shelf :title=\"item.name\">\n            <div slot=\"content\" class=\"floors\" >\n              <div class=\"imgbanner\" v-for=\"(iitem,j) in item.panelContentDtos\" :key=\"j\" v-if=\"iitem.type === 2 || iitem.type === 3\" @click=\"linkTo(iitem)\">\n                <img v-lazy=\"iitem.picUrl\">\n                <a class=\"cover-link\"></a>\n              </div>\n              <mall-goods :msg=\"iitem\" v-for=\"(iitem,j) in item.panelContentDtos\" :key=\"j+'key'\" v-if=\"iitem.type != 2 && iitem.type != 3\"></mall-goods>\n            </div>\n          </y-shelf>\n        </section>\n      </div>\n    </div>\n\n    <div class=\"no-info\" v-if=\"error\">\n      <div class=\"no-data\">\n        <img src=\"/static/images/error.png\">\n        <br> 抱歉！出错了...\n      </div>\n    </div>\n  </div>\n</template>\n<script>\n  import { productHome } from '/api/index.js'\n  import YShelf from '/components/shelf'\n  import mallGoods from '/components/mallGoods'\n\n  export default {\n    data () {\n      return {\n        // 默认加载中...\n        loading: true,\n        // 出现错误时显示\n        error: false,\n        // 轮播图\n        banner: [],\n        // 记录第几张轮播图\n        mark: 0,\n        // 3d\n        bgOpt: {\n          px: 0,\n          py: 0,\n          w: 0,\n          h: 0\n        },\n        // 轮播时间\n        timer: '',\n        // 板块\n        home: []\n      }\n    },\n    methods: {\n      autoPlay () {\n        this.mark++\n        if (this.mark > this.banner.length - 1) {\n          // 当遍历到最后一张图片置零\n          this.mark = 0\n        }\n      },\n      play () {\n        // 每2.5s自动切换\n        this.timer = setInterval(this.autoPlay, 2500)\n      },\n      change (i) {\n        this.mark = i\n      },\n      startTimer () {\n        this.timer = setInterval(this.autoPlay, 2500)\n      },\n      stopTimer () {\n        clearInterval(this.timer)\n      },\n      bgOver (e) {\n        this.bgOpt.px = e.offsetLeft\n        this.bgOpt.py = e.offsetTop\n        this.bgOpt.w = e.offsetWidth\n        this.bgOpt.h = e.offsetHeight\n      },\n      bgMove (dom, eve) {\n        let bgOpt = this.bgOpt\n        let X, Y\n        let mouseX = eve.pageX - bgOpt.px\n        let mouseY = eve.pageY - bgOpt.py\n        if (mouseX > bgOpt.w / 2) {\n          X = mouseX - (bgOpt.w / 2)\n        } else {\n          X = mouseX - (bgOpt.w / 2)\n        }\n        if (mouseY > bgOpt.h / 2) {\n          Y = bgOpt.h / 2 - mouseY\n        } else {\n          Y = bgOpt.h / 2 - mouseY\n        }\n        dom.style['transform'] = `rotateY(${X / 50}deg) rotateX(${Y / 50}deg)`\n        dom.style.transform = `rotateY(${X / 50}deg) rotateX(${Y / 50}deg)`\n      },\n      bgOut (dom) {\n        dom.style['transform'] = 'rotateY(0deg) rotateX(0deg)'\n        dom.style.transform = 'rotateY(0deg) rotateX(0deg)'\n      },\n      linkTo (item) {\n        if (item.type === 0 || item.type === 2) {\n          // 关联商品\n          window.open(window.location.origin + '/goodsDetails?productId=' + item.productId)\n        } else {\n          // 其他链接\n          window.open(item.fullUrl)\n        }\n      }\n    },\n    mounted () {\n      productHome().then(res => {\n        if (res.status === 500) {\n          this.error = true\n          return\n        }\n        let data = res.result\n        this.home = data\n        this.loading = false\n        for (let i = 0; i < data.length; i++) {\n          // type:0 轮播图 type:1 其他板块\n          if (data[i].type === 0) {\n            this.banner = data[i].panelContentDtos\n          }\n        }\n      })\n    },\n    created () {\n      this.play()\n    },\n    components: {\n      YShelf,\n      mallGoods\n    }\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\">\n  .home {\n    display: flex;\n    flex-direction: column;\n  }\n\n  .no-info {\n    padding: 100px 0;\n    text-align: center;\n    font-size: 30px;\n    display: flex;\n    flex-direction: column;\n    .no-data{\n      align-self: center;\n    }\n  }\n\n  .fade-enter-active, .fade-leave-active {\n    transition: opacity .5s;\n  }\n  .fade-enter, .fade-leave-to {\n    opacity: 0;\n  }\n\n  .page {\n    position: absolute;\n    width: 100%;\n    top: 470px;\n    z-index: 30;\n    .dots {\n      display: flex;\n      flex-direction: row;\n      align-items: center;\n      justify-content: center;\n      .dot-active {\n        display: inline-block;\n        width: 15px;\n        height: 15px;\n        background-color: whitesmoke;\n        border-radius: 8px;\n        margin-right: 10px;\n        cursor: pointer;\n      }\n      .dot {\n        opacity: 0.2;\n      }\n    }\n  }\n\n  .activity-panel {\n    width: 1220px;\n    margin: 0 auto;\n    .box {\n      overflow: hidden;\n      position: relative;\n      z-index: 0;\n      margin-top: 25px;\n      box-sizing: border-box;\n      border: 1px solid rgba(0,0,0,.14);\n      border-radius: 8px;\n      background: #fff;\n      box-shadow: 0 3px 8px -6px rgba(0,0,0,.1);\n    }\n    .content {\n      float: left;\n      position: relative;\n      box-sizing: border-box;\n      width: 25%;\n      height: 200px;\n      text-align: center;\n    }\n    .content ::before{\n      position: absolute;\n      top: 0;\n      left: 0;\n      z-index: 1;\n      box-sizing: border-box;\n      border-left: 1px solid #f2f2f2;\n      border-left: 1px solid rgba(0,0,0,.1);\n      width: 100%;\n      height: 100%;\n      content: \"\";\n      pointer-events: none;\n    }\n    .i {\n      width: 305px;\n      height: 200px;\n    }\n    .cover-link {\n      cursor: pointer;\n      display: block;\n      position: absolute;\n      top: 0;\n      right: 0;\n      bottom: 0;\n      left: 0;\n      z-index: 4;\n      background: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEHAAEALAAAAAABAAEAAAICTAEAOw==) repeat;\n    }\n    a {\n      color: #5079d9;\n      cursor: pointer;\n      transition: all .15s ease-out;\n      text-decoration: none;\n    }\n    a:hover {\n      box-shadow: inset 0 0 38px rgba(0,0,0,.08);\n      transition: all .15s ease;\n    }\n  }\n\n  .banner, .banner span, .banner div {\n    font-family: \"Microsoft YaHei\";\n    transition: all .3s;\n    transition-timing-function: linear;\n  }\n\n  .banner {\n    cursor: pointer;\n    perspective: 3000px;\n    position: relative;\n    z-index: 19;\n    margin: 0 auto;\n    width: 1220px;\n  }\n\n  .bg {\n    position: relative;\n    width: 1220px;\n    height: 500px;\n    margin: 20px auto;\n    background-size: 100% 100%;\n    border-radius: 10px;\n    transform-style: preserve-3d;\n    transform-origin: 50% 50%;\n    transform: rotateY(0deg) rotateX(0deg);\n    & div{\n      position: relative;\n      height: 100%;\n      width: 100%;\n    }\n  }\n\n  .img1 {\n    display: block;\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    top: 0;\n    border-radius: 10px;\n  }\n\n  .img2 {\n    display: block;\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    bottom: 5px;\n    left: 0;\n    background-size: 95% 100%;\n    border-radius: 10px;\n  }\n\n  .img3 {\n    display: block;\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    top: 0;\n    border-radius: 10px;\n  }\n\n  .a {\n    z-index: 20;\n    transform: translateZ(40px);\n  }\n\n  .b {\n    z-index: 20;\n    transform: translateZ(30px);\n  }\n\n  .c {\n    transform: translateZ(0px);\n  }\n\n  .sk_item {\n    width: 170px;\n    height: 225px;\n    padding: 0 14px 0 15px;\n    > div {\n      width: 100%;\n    }\n    a {\n      display: flex;\n      flex-direction: column;\n      justify-content: center;\n      align-items: center;\n      transition: all .3s;\n      &:hover {\n        transform: translateY(-5px);\n      }\n    }\n    img {\n      width: 130px;\n      height: 130px;\n      margin: 17px 0;\n    }\n    .sk_item_name {\n      color: #999;\n      display: block;\n      max-width: 100%;\n      _width: 100%;\n      overflow: hidden;\n      font-size: 12px;\n      text-align: left;\n      height: 32px;\n      line-height: 16px;\n      word-wrap: break-word;\n      word-break: break-all;\n    }\n    .sk_item_price {\n      padding: 3px 0;\n      height: 25px;\n    }\n    .price_new {\n      font-size: 18px;\n      font-weight: 700;\n      margin-right: 8px;\n      color: #f10214;\n    }\n    .price_origin {\n      color: #999;\n      font-size: 12px;\n    }\n  }\n\n  .box {\n    overflow: hidden;\n    position: relative;\n    z-index: 0;\n    margin-top: 29px;\n    box-sizing: border-box;\n    border: 1px solid rgba(0, 0, 0, .14);\n    border-radius: 8px;\n    background: #fff;\n    box-shadow: 0 3px 8px -6px rgba(0, 0, 0, .1);\n\n  }\n\n  ul.box {\n    display: flex;\n    li {\n      flex: 1;\n      img {\n        display: block;\n        width: 305px;\n        height: 200px;\n      }\n    }\n  }\n\n  .mt30 {\n    margin-top: 30px;\n  }\n\n  .hot {\n    display: flex;\n    > div {\n      flex: 1;\n      width: 25%;\n    }\n  }\n\n  .floors {\n    width: 100%;\n    display: flex;\n    flex-wrap: wrap;\n    align-items: center;\n    .imgbanner {\n      width: 50%;\n      height: 430px;\n      .cover-link {\n        cursor: pointer;\n        display: block;\n        position: absolute;\n        top: 60px;\n        left: 0;\n        width: 50%;\n        height: 430px;\n        z-index: 4;\n        background: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEHAAEALAAAAAABAAEAAAICTAEAOw==) repeat;\n      }\n      .cover-link:hover {\n        box-shadow: inset 0 0 38px rgba(0,0,0,.08);\n        transition: all .15s ease;\n      }\n    }\n    img {\n      display: block;\n      width: 100%;\n      height: 100%;\n    }\n  }\n\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Login/forgetPassword.vue",
    "content": "<template>\n  <div class=\"login v2\">\n    <div class=\"wrapper\">\n      <div class=\"dialog dialog-shadow\" style=\"display: block; margin-top: -236px;\">\n\n        <div class=\"registered\" v-show=\"step1\">\n          <h4>忘记密码</h4>\n          <div class=\"content\" style=\"margin-top: 20px;\">\n            <el-form :model=\"forget1\" :rules=\"forget1Rules\" ref=\"forget1\" class=\"forget-form\">\n              <el-form-item prop=\"account\">\n                <el-input v-model=\"forget1.account\" size=\"large\" placeholder=\"手机号/邮箱\" auto-complete=\"off\"></el-input>\n              </el-form-item>\n              <el-form-item>\n                <div id=\"captcha\">\n                  <p id=\"wait\">正在加载验证码...</p>\n                </div>\n              </el-form-item>\n              <el-button type=\"primary\" @click=\"forget1NextStep\" :disabled=\"verAccount ? false : true\" style=\"width: 370px; height: 48px;\">\n                下一步\n              </el-button>\n            </el-form>\n          </div>\n        </div>\n\n        <div class=\"registered\" v-show=\"step2\">\n          <h4>安全验证</h4>\n          <div class=\"content\" style=\"margin-top: 20px;\">\n            <el-form :model=\"forget2\" :rules=\"forget2Rules\" ref=\"forget2\" class=\"forget-form\">\n              <el-form-item>\n                <el-input v-model=\"forget1.account\" auto-complete=\"off\" :disabled=\"true\"></el-input>\n              </el-form-item>\n              <el-form-item >\n                <el-col :span=\"14\">\n                  <el-form-item prop=\"verCode\">\n                    <el-input v-model=\"forget2.verCode\" size=\"large\" placeholder=\"验证码\" style=\"width: 188px;\" auto-complete=\"off\"></el-input>\n                  </el-form-item>\n                </el-col>\n                <el-col :span=\"10\">\n                  <el-form-item>\n                    <el-button @click=\"sendVerCode\" type=\"primary\" size=\"large\" :disabled=\"sendAuthCode ? false : true\"  style=\"width: 154px; height: 50px;\">\n                      <span v-show=\"sendAuthCode\">获取验证码</span>\n                      <span v-show=\"!sendAuthCode\">重新发送({{authTime}})</span>\n                    </el-button>\n                  </el-form-item>\n                </el-col>\n              </el-form-item>\n              <el-button type=\"primary\" @click=\"forget2NextStep\" :disabled=\"verVerCode ? false : true\" style=\"width: 370px; height: 48px;\">\n                下一步\n              </el-button>\n            </el-form>\n          </div>\n        </div>\n\n        <div class=\"registered\" v-show=\"step3\">\n          <h4>修改密码</h4>\n          <div class=\"content\" style=\"margin-top: 20px;\">\n            <el-form :model=\"forget3\" :rules=\"forget3Rules\" ref=\"forget3\" class=\"forget-form\">\n              <el-form-item prop=\"password\">\n                <el-input type=\"password\" v-model=\"forget3.password\" placeholder=\"新密码\" auto-complete=\"off\" ></el-input>\n              </el-form-item>\n              <el-form-item prop=\"repass\">\n                <el-input type=\"password\" v-model=\"forget3.repass\" placeholder=\"确认密码\" auto-complete=\"off\"></el-input>\n              </el-form-item>\n              <el-button type=\"primary\" @click=\"_updatePassword\" :disabled=\"verPassword && verRePassword ? false : true\" style=\"width: 370px; height: 48px;\">\n                确认更改密码\n              </el-button>\n            </el-form>\n          </div>\n        </div>\n\n        <div class=\"registered\" v-show=\"step4\">\n          <h4>密码重置成功</h4>\n          <div class=\"content\" style=\"padding: 30px 40px 24px;\">\n            <div class=\"content-success\">\n              <div class=\"content-success-img\">\n                <img src=\"/static/images/success.png\"/>\n              </div>\n              <div class=\"content-success-title\">\n                <span>您的密码已经重置成功</span>\n              </div>\n              <div class=\"content-success-second\">\n                <span>{{second}} 秒后系统自动跳转</span>\n              </div>\n              <div class=\"border\"></div>\n              <div style=\"text-align: center;\">\n                <a href=\"/login\">登录</a>\n              </div>\n            </div>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n<script src=\"../../../static/geetest/gt.js\"></script>\n<script>\nimport {checkAccount, geetest, forgetVerCode, updatePassword} from '/api/index.js'\nrequire('../../../static/geetest/gt.js')\nvar captcha\nexport default {\n  data () {\n    let vAccount = async (rule, value, callback) => {\n      const phoneReg = /^1[3|4|5|7|8][0-9]\\d{8}$/\n      const emailReg = /^(\\w-*\\.*)+@(\\w-?)+(\\.\\w{2,})+$/\n      if (!value) {\n        this.verAccount = false\n        return callback(new Error('请输入手机号或邮箱'))\n      } else if (!phoneReg.test(value) && !emailReg.test(value)) {\n        this.verAccount = false\n        return callback(new Error('手机号/邮箱格式错误'))\n      }\n      let params = {\n        params: {\n          account: value\n        }\n      }\n      await checkAccount(params).then(res => {\n        if (res.result === false) {\n          this.verAccount = false\n          this.existAccount = false\n        } else {\n          this.verAccount = true\n          this.existAccount = true\n        }\n      })\n      if (!this.existAccount) {\n        return callback(new Error('手机号/邮箱不存在'))\n      }\n      return callback()\n    }\n    let vVerCode = (rule, value, callback) => {\n      let verCodeReg = /^\\d{6}$/\n      if (!verCodeReg.test(value)) {\n        this.verVerCode = false\n        return callback()\n      }\n      if (value !== this.verCode) {\n        this.verVerCode = false\n        return callback(new Error('验证码错误'))\n      }\n      this.verVerCode = true\n      return callback()\n    }\n    let vPassword = (rule, value, callback) => {\n      const passReg = /^(?![0-9]+$)(?![a-zjnnnpA-Z]+$)[0-9A-Za-z]{6,16}$/\n      if (!value) {\n        this.verPassword = false\n        return callback(new Error('请输入密码'))\n      } else if (!passReg.test(value)) {\n        this.verPassword = false\n        return callback(new Error('密码长度 6-16 位，数字字母至少包含两种'))\n      } else {\n        this.$refs.forget3.validateField('repass')\n      }\n      this.verPassword = true\n      return callback()\n    }\n    let vRepass = (rule, value, callback) => {\n      if (!value) {\n        this.verRePassword = false\n        return callback(new Error('请再次输入密码'))\n      } else if (value !== this.forget3.password) {\n        this.verRePassword = false\n        return callback(new Error('两次输入密码不一致!'))\n      }\n      this.verRePassword = true\n      return callback()\n    }\n    return {\n      forget1: {\n        account: ''\n      },\n      forget2: {\n        verCode: ''\n      },\n      forget3: {\n        password: '',\n        repass: ''\n      },\n      forget1Rules: {\n        account: [\n          {validator: vAccount, trigger: 'change,blur'}\n        ]\n      },\n      forget2Rules: {\n        verCode: [\n          {validator: vVerCode, trigger: 'change,blur'}\n        ]\n      },\n      forget3Rules: {\n        password: [\n          {validator: vPassword, trigger: 'change,blur'}\n        ],\n        repass: [\n          {validator: vRepass, trigger: 'change,blur'}\n        ]\n      },\n      verAccount: false,\n      verVerCode: false,\n      verPassword: false,\n      verRePassword: false,\n      verCode: '',\n      existAccount: false,\n      step1: true,\n      step2: false,\n      step3: false,\n      step4: false,\n      sendAuthCode: true,\n      authTime: 60,\n      second: 5\n    }\n  },\n  methods: {\n    message (m) {\n      this.$message.error({\n        message: m\n      })\n    },\n    initGeetest () {\n      geetest().then(res => {\n        this.statusKey = res.statusKey\n        window.initGeetest({\n          gt: res.gt,\n          challenge: res.challenge,\n          new_captcha: res.new_captcha,\n          offline: !res.success,\n          product: 'popup',\n          width: '100%'\n        }, function (captchaObj) {\n          captcha = captchaObj\n          captchaObj.appendTo('#captcha')\n          captchaObj.onReady(function () {\n            document.getElementById('wait').style.display = 'none'\n          })\n        })\n      })\n    },\n    forget1NextStep () {\n      let result = captcha.getValidate()\n      if (!result) {\n        this.message('请先完成验证')\n        return false\n      }\n      this.step1 = false\n      this.step2 = true\n    },\n    forget2NextStep () {\n      this.step2 = false\n      this.step3 = true\n    },\n    sendVerCode () {\n      let account = this.forget1.account\n      this.sendAuthCode = false\n      let authTimetimer = setInterval(() => {\n        this.authTime--\n        if (this.authTime <= 0) {\n          this.sendAuthCode = true\n          clearInterval(authTimetimer)\n          this.authTime = 60\n        }\n      }, 1000)\n      let params = {\n        params: {\n          account: account\n        }\n      }\n      forgetVerCode(params).then(res => {\n        console.log(res.result)\n        this.verCode = res.result\n      })\n    },\n    async _updatePassword () {\n      let account = this.forget1.account\n      let password = this.forget3.password\n      await updatePassword({\n        account,\n        password\n      }).then(res => {\n        if (res.status === 200) {\n          this.step3 = false\n          this.step4 = true\n          this.secondReuce()\n        } else {\n          this.message('请求服务器异常,请检查您的网络信息')\n        }\n      })\n    },\n    secondReuce () {\n      let secondT = setInterval(() => {\n        this.second--\n        if (this.second <= 0) {\n          clearInterval(secondT)\n          this.$router.push({\n            path: '/login'\n          })\n        }\n      }, 1000)\n    }\n  },\n  mounted () {\n    this.initGeetest()\n  }\n}\n</script>\n\n<style lang=\"scss\" rel=\"stylesheet/scss\">\n  * {\n    box-sizing: content-box;\n  }\n\n  .forget-form .el-input__inner {\n    height: 50px;\n  }\n\n  .content-success {\n    text-align: center;\n  }\n\n  .content-success-img {\n    margin-top: 15px;\n  }\n\n  .content-success-img img {\n    height: 80px;\n    width: 80px;\n  }\n\n  .content-success-title {\n    margin-top: 40px;\n    font-size: 22px;\n    color: #333;\n  }\n\n  .content-success-second {\n    margin-top: 10px;\n    color: #999;\n    line-height: 1em;\n    font-size: 14px;\n  }\n\n  .login {\n    overflow-x: hidden;\n    overflow-y: hidden;\n    .input {\n      height: 50px;\n      display: flex;\n      align-items: center;\n      input {\n        font-size: 16px;\n        width: 100%;\n        height: 100%;\n        padding: 10px 15px;\n        box-sizing: border-box;\n        border: 1px solid #ccc;\n        border-radius: 6px;\n      }\n    }\n    .wrapper {\n      background: url(/static/images/bg_9b9dcb65ff.png) repeat;\n      background-size: 100px;\n      min-height: 800px;\n      min-width: 630px;\n    }\n  }\n\n  .v2 .dialog {\n    width: 450px;\n    border: 1px solid #dadada;\n    border-radius: 10px;\n    top: 50%;\n    left: 50%;\n    margin-left: -225px;\n    position: absolute;\n    .title {\n      background: linear-gradient(#fff, #f5f5f5);\n      height: auto;\n      overflow: visible;\n      box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);\n      position: relative;\n      background-image: url(/static/images/smartisan_4ada7fecea.png);\n      background-size: 140px;\n      background-position: top center;\n      background-repeat: no-repeat;\n      height: 92px;\n      margin: 23px 0 50px;\n      padding: 75px 0 0;\n      box-shadow: none;\n      h4 {\n        padding: 0;\n        text-align: center;\n        color: #666;\n        border-bottom: 1px solid #dcdcdc;\n        -webkit-box-shadow: none;\n        -moz-box-shadow: none;\n        box-shadow: none;\n        font-weight: 700;\n        position: absolute;\n        bottom: 0;\n        width: 100%;\n        text-align: center;\n        margin: 0;\n        padding: 0;\n        border-bottom: 0;\n        -webkit-box-shadow: none;\n        -moz-box-shadow: none;\n        box-shadow: none;\n        line-height: 1em;\n        height: auto;\n        color: #333;\n        font-weight: 400;\n      }\n    }\n    .content {\n      padding: 0 40px 22px;\n      height: auto;\n      .common-form {\n        li {\n          clear: both;\n          margin-bottom: 15px;\n          position: relative;\n        }\n      }\n    }\n  }\n\n  .dialog-shadow,\n  .v2 .bbs .dialog-shadow,\n  .v2 .dialog-shadow {\n    -webkit-box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),\n    0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),\n    0 10px 20px -10px rgba(0, 0, 0, 0.04);\n    -moz-box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),\n    0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),\n    0 10px 20px -10px rgba(0, 0, 0, 0.04);\n    box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),\n    0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),\n    0 10px 20px -10px rgba(0, 0, 0, 0.04);\n  }\n\n  @media screen and (min-width: 737px),\n  screen and (-webkit-max-device-pixel-ratio: 1.9) and (max-width: 736px) and (min-device-width: 737px) {\n    .wrapper {\n      background: url(/static/images/con-bg_04f25dbf8e.jpg) repeat-x;\n      position: absolute;\n      top: 0;\n      bottom: 0;\n      left: 0;\n      right: 0;\n    }\n    .dialog {\n      background: url(/static/images/dialog-gray-bg.png) #fff bottom repeat-x;\n      border-radius: 12px;\n      display: none;\n      margin: -163px 0 0 -218px;\n      width: 436px;\n      position: fixed;\n      left: 50%;\n      top: 50%;\n    }\n    .register {\n      padding: 1px 10px 0;\n      border-right: 1px solid #ccc;\n    }\n    .border {\n      margin-top: 10px;\n      border-bottom: 1px solid #ccc;\n      margin-bottom: 10px;\n    }\n    .other {\n      margin: 20px 5px 0 0;\n      width: auto;\n      color: #bbb;\n      font-size: 12px;\n      cursor: default;\n      color: #999;\n    }\n    .footer {\n      display: flex;\n      flex-direction: row;\n    }\n    .agree {\n      margin-bottom: 30px;\n      color: #999;\n    }\n  }\n\n  .registered {\n    h4 {\n      padding: 0;\n      text-align: center;\n      color: #666;\n      border-bottom: 1px solid #dcdcdc;\n      -webkit-box-shadow: none;\n      -moz-box-shadow: none;\n      box-shadow: none;\n      font-weight: 700;\n      font-size: 20px;\n      height: 60px;\n      line-height: 60px;\n    }\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Login/login.vue",
    "content": "<template>\n  <div class=\"login v2\">\n    <div class=\"wrapper\">\n      <div class=\"dialog dialog-shadow\" style=\"display: block; margin-top: -362px;\">\n        <div class=\"title\">\n          <h4>使用 YMall 账号 登录官网</h4>\n        </div>\n        <div class=\"content\">\n          <el-form :model=\"login\" :rules=\"rules\" ref=\"login\" class=\"login-form\">\n            <el-form-item prop=\"account\">\n              <el-input v-model=\"login.account\" size=\"large\" placeholder=\"手机号/邮箱\" auto-complete=\"off\" ></el-input>\n            </el-form-item>\n            <el-form-item prop=\"password\">\n              <el-input type=\"password\" v-model=\"login.password\" size=\"large\" placeholder=\"密码\" auto-complete=\"off\" ></el-input>\n            </el-form-item>\n            <el-form-item>\n              <div id=\"captcha\">\n                <p id=\"wait\">正在加载验证码...</p>\n              </div>\n            </el-form-item>\n            <el-form-item>\n              <el-col :span=\"12\">\n                <el-checkbox class=\"auto-login\" v-model=\"login.auto\">自动登录</el-checkbox>\n              </el-col>\n              <el-col :span=\"12\" style=\"float: right;\">\n                <a href=\"javascript:;\" @click=\"toRegister\">注册 YMall 账号</a>\n                <a style=\"padding: 1px 0 0 10px\" @click=\"toForgetPassword\">忘记密码 ?</a>\n              </el-col>\n            </el-form-item>\n            <el-button type=\"primary\" @click=\"toLogin\" :disabled=\"verAccount && verPassword ? false : true\" style=\"width: 370px; height: 48px;\">{{loginTxt}}</el-button>\n            <div class=\"border\"></div>\n            <div class=\"footer\">\n              <div class=\"other\">其它账号登录：</div>\n              <a><img @click=\"open('待开发','此功能开发中...')\" style=\"height: 15px; margin-top: 22px;\" src=\"/static/images/other-login.png\"></a>\n            </div>\n          </el-form>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n<script src=\"../../../static/geetest/gt.js\"></script>\n<script>\nimport YFooter from '/common/footer'\nimport YButton from '/components/YButton'\nimport { addCartProduct } from '/api/cart.js'\nimport {memberLogin, geetest} from '/api/index.js'\nimport { setStore, getStore, removeStore } from '../../utils/storage'\nrequire('../../../static/geetest/gt.js')\nvar captcha\nexport default {\n  data () {\n    let vAccount = (rule, value, callback) => {\n      const phoneReg = /^1[3|4|5|7|8][0-9]\\d{8}$/\n      const emailReg = /^(\\w-*\\.*)+@(\\w-?)+(\\.\\w{2,})+$/\n      if (!value) {\n        this.verAccount = false\n        return callback(new Error('请输入手机号或邮箱'))\n      } else if (!phoneReg.test(value) && !emailReg.test(value)) {\n        this.verAccount = false\n        return callback(new Error('手机号/邮箱格式错误'))\n      } else {\n        this.verAccount = true\n        return callback()\n      }\n    }\n    let vPassword = (rule, value, callback) => {\n      if (!value) {\n        this.verPassword = false\n        return callback(new Error('请输入密码'))\n      } else {\n        this.verPassword = true\n        return callback()\n      }\n    }\n    return {\n      login: {\n        account: '',\n        password: '',\n        auto: true\n      },\n      rules: {\n        account: [\n          {validator: vAccount, trigger: 'change,blur'}\n        ],\n        password: [\n          {validator: vPassword, trigger: 'change,blur'}\n        ]\n      },\n      verAccount: false,\n      verPassword: false,\n      loginTxt: '登录',\n      cart: []\n    }\n  },\n  methods: {\n    message (m) {\n      this.$message.error({\n        message: m\n      })\n    },\n    open (t, m) {\n      this.$notify.info({\n        title: t,\n        message: m\n      })\n    },\n    toRegister () {\n      this.$router.push({\n        path: '/register'\n      })\n    },\n    toForgetPassword () {\n      this.$router.push({\n        path: '/forgetPassword'\n      })\n    },\n    initGeetest () {\n      geetest().then(res => {\n        window.initGeetest({\n          gt: res.gt,\n          challenge: res.challenge,\n          new_captcha: res.new_captcha,\n          offline: !res.success,\n          product: 'popup',\n          width: '100%'\n        }, function (captchaObj) {\n          captcha = captchaObj\n          captchaObj.appendTo('#captcha')\n          captchaObj.onReady(function () {\n            document.getElementById('wait').style.display = 'none'\n          })\n        })\n      })\n    },\n    autoLogin () {\n      if (this.login.auto === true) {\n        setStore('autoLogin', 'true')\n      } else {\n        setStore('autoLogin', 'false')\n      }\n    },\n    // 登录时将本地的添加到用户购物车\n    login_addCart () {\n      let cartArr = []\n      let localCart = JSON.parse(getStore('buyCart'))\n      if (localCart && localCart.length) {\n        localCart.forEach(item => {\n          cartArr.push({\n            userId: getStore('userId'),\n            productId: item.productId,\n            productNum: item.productNum\n          })\n        })\n      }\n      this.cart = cartArr\n    },\n    toLogin () {\n      this.loginTxt = '登录中...'\n      this.autoLogin()\n      let result = captcha.getValidate()\n      if (!result) {\n        this.message('请完成验证')\n        this.loginTxt = '登录'\n        return false\n      }\n      let account = this.login.account\n      let password = this.login.password\n      let auto = this.login.auto\n      memberLogin({\n        account,\n        password,\n        auto\n      }).then(res => {\n        if (res.status === 200) {\n          setStore('token', res.result.token)\n          setStore('userId', res.result.id)\n          // 登录后添加当前缓存中的购物车\n          this.login_addCart()\n          if (this.cart.length) {\n            for (let i = 0; i < this.cart.length; i++) {\n              addCartProduct(this.cart[i]).then(res => {\n              })\n            }\n            removeStore('buyCart')\n            this.$router.push({\n              path: '/'\n            })\n          }\n\n          this.$router.push({\n            path: '/'\n          })\n        } else {\n          this.loginTxt = '登录'\n          this.message(res.message)\n          captcha.reset()\n          return false\n        }\n      })\n    }\n  },\n  mounted () {\n    let autoLogin = getStore('autoLogin')\n    if (autoLogin === 'true') {\n      this.login.auto = true\n    } else if (autoLogin === 'false') {\n      this.login.auto = false\n    } else {\n      this.login.auto = true\n    }\n    this.initGeetest()\n  },\n  components: {\n    YFooter,\n    YButton\n  }\n}\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\">\n* {\n  box-sizing: content-box;\n}\n\n.login .el-input__inner {\n  height: 50px;\n}\n\n.phone-login {\n  margin-top: 20px;\n  margin-left: 125px;\n  color: #999;\n}\n\n.login {\n  overflow-x: hidden;\n  overflow-y: hidden;\n  .input {\n    height: 50px;\n    display: flex;\n    align-items: center;\n    input {\n      font-size: 16px;\n      width: 100%;\n      height: 100%;\n      padding: 10px 15px;\n      box-sizing: border-box;\n      border: 1px solid #ccc;\n      border-radius: 6px;\n    }\n  }\n  .wrapper {\n    background: url(/static/images/bg_9b9dcb65ff.png) repeat;\n    background-size: 100px;\n    min-height: 800px;\n    min-width: 630px;\n  }\n}\n\n.v2 .dialog {\n  width: 450px;\n  border: 1px solid #dadada;\n  border-radius: 10px;\n  top: 50%;\n  left: 50%;\n  margin-left: -225px;\n  position: absolute;\n  .title {\n    color: #333;\n    font-weight: 400;\n    background: linear-gradient(#fff, #f5f5f5);\n    height: auto;\n    overflow: visible;\n    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);\n    position: relative;\n    background-image: url(/static/images/smart-Y.png);\n    background-size: 140px;\n    background-position: top center;\n    background-repeat: no-repeat;\n    height: 92px;\n    margin: 23px 0 50px;\n    padding: 75px 0 0;\n    box-shadow: none;\n    h4 {\n      padding: 0;\n      text-align: center;\n      color: #666;\n      border-bottom: 1px solid #dcdcdc;\n      -webkit-box-shadow: none;\n      -moz-box-shadow: none;\n      box-shadow: none;\n      font-weight: 700;\n      position: absolute;\n      bottom: 0;\n      width: 100%;\n      text-align: center;\n      margin: 0;\n      padding: 0;\n      border-bottom: 0;\n      -webkit-box-shadow: none;\n      -moz-box-shadow: none;\n      box-shadow: none;\n      line-height: 1em;\n      height: auto;\n      color: #333;\n      font-weight: 400;\n    }\n  }\n  .content {\n    padding: 0 40px 22px;\n    height: auto;\n    .common-form {\n      li {\n        clear: both;\n        margin-bottom: 15px;\n        position: relative;\n      }\n    }\n  }\n}\n\n.dialog-shadow,\n.v2 .bbs .dialog-shadow,\n.v2 .dialog-shadow {\n  -webkit-box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),\n    0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),\n    0 10px 20px -10px rgba(0, 0, 0, 0.04);\n  -moz-box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),\n    0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),\n    0 10px 20px -10px rgba(0, 0, 0, 0.04);\n  box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),\n    0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),\n    0 10px 20px -10px rgba(0, 0, 0, 0.04);\n}\n\n@media screen and (min-width: 737px),\n  screen and (-webkit-max-device-pixel-ratio: 1.9) and (max-width: 736px) and (min-device-width: 737px) {\n  .wrapper {\n    background: url(/static/images/con-bg_04f25dbf8e.jpg) repeat-x;\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n  }\n  .dialog {\n    background: url(/static/images/dialog-gray-bg.png) #fff bottom repeat-x;\n    border-radius: 12px;\n    display: none;\n    margin: -163px 0 0 -218px;\n    width: 436px;\n    position: fixed;\n    left: 50%;\n    top: 50%;\n  }\n  .dialog .title h4 {\n    border-bottom: #d1d1d1 solid 1px;\n    box-shadow: 0 2px 6px #d1d1d1;\n    color: #666;\n    font-size: 20px;\n    height: 61px;\n    line-height: 61px;\n    padding: 0 0 0 35px;\n  }\n  .common-form li {\n    clear: both;\n    margin-bottom: 15px;\n    position: relative;\n  }\n  .auto-login {\n    position: absolute;\n    top: 0px;\n    left: 2px;\n    color: #999;\n  }\n  .register {\n    padding: 1px 10px 0;\n    border-right: 1px solid #ccc;\n  }\n  .border {\n    margin-top: 10px;\n    border-bottom: 1px solid #ccc;\n  }\n  .other {\n    margin: 20px 5px 0 0;\n    width: auto;\n    color: #bbb;\n    font-size: 12px;\n    cursor: default;\n    color: #999;\n  }\n  .footer {\n    display: flex;\n    flex-direction: row;\n  }\n  .agree {\n    margin-bottom: 30px;\n    color: #999;\n  }\n}\n\n.registered {\n  h4 {\n    padding: 0;\n    text-align: center;\n    color: #666;\n    border-bottom: 1px solid #dcdcdc;\n    -webkit-box-shadow: none;\n    -moz-box-shadow: none;\n    box-shadow: none;\n    font-weight: 700;\n    font-size: 20px;\n    height: 60px;\n    line-height: 60px;\n  }\n}\n\n#wait {\n  text-align: left;\n  color: #999;\n  margin: 0;\n}\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Login/register.vue",
    "content": "<template>\n  <div class=\"login v2\">\n    <div class=\"wrapper\">\n      <div class=\"dialog dialog-shadow\" style=\"display: block; margin-top: -318px;\">\n        <div class=\"registered\">\n          <h4>注册 YMall 账号</h4>\n          <div class=\"content\" style=\"margin-top: 20px;\">\n            <el-form :model=\"registered\" :rules=\"rules\" ref=\"registered\" class=\"register-form\">\n              <el-form-item prop=\"phone\">\n                <el-input v-model=\"registered.phone\" size=\"large\" placeholder=\"手机号\" auto-complete=\"off\" ></el-input>\n              </el-form-item>\n              <el-form-item >\n                <el-col :span=\"14\">\n                  <el-form-item prop=\"verCode\">\n                    <el-input v-model=\"registered.verCode\" size=\"large\" placeholder=\"验证码\" style=\"width: 188px;\" auto-complete=\"off\"></el-input>\n                  </el-form-item>\n                </el-col>\n                <el-col :span=\"10\">\n                  <el-form-item>\n                    <el-button @click=\"sendVerCode\" type=\"primary\" size=\"large\" :disabled=\"verPhone && sendAuthCode ? false : true\"  style=\"width: 154px; height: 50px;\">\n                      <span v-show=\"sendAuthCode\">获取验证码</span>\n                      <span v-show=\"!sendAuthCode\">重新发送({{authTime}})</span>\n                    </el-button>\n                  </el-form-item>\n                </el-col>\n              </el-form-item>\n              <el-form-item prop=\"pass\">\n                <el-input type=\"password\" v-model=\"registered.pass\" size=\"large\"  placeholder=\"密码\" auto-complete=\"off\" style=\"height: 50px;\"></el-input>\n              </el-form-item>\n              <el-form-item prop=\"pass2\">\n                <el-input type=\"password\" v-model=\"registered.pass2\" size=\"large\"  placeholder=\"确认密码\" auto-complete=\"off\" style=\"height: 50px;\"></el-input>\n              </el-form-item>\n                <el-checkbox class=\"agree\" v-model=\"agreement\">\n                  我已阅读并同意遵守\n                  <a @click=\"open('法律声明','此仅为个人练习项目，不承担任何法律问题')\">法律声明</a> 和\n                  <a @click=\"open('隐私条款','本网站将不会严格遵守有关法律法规和本隐私政策所载明的内容收集、使用您的信息')\">隐私条款</a>\n                </el-checkbox>\n                <el-button type=\"primary\" @click=\"regist\" :disabled=\"verPhone && verVerCode && verPass && verPass2 && agreement ? false : true\" style=\"width: 370px; height: 48px;\">{{registerTxt}}</el-button>\n              <div class=\"border\"></div>\n              <span class=\"agree\" style=\"margin-left: 50px;\">\n                如果您已拥有 YMall 账号，可在此\n                <a @click=\"toLogin\">登录</a>\n              </span>\n            </el-form>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</template>\n<script>\nimport YFooter from '/common/footer'\nimport YButton from '/components/YButton'\nimport {checkPhone, vercode, register} from '/api/index.js'\nexport default {\n  data () {\n    let vPhone = async (rule, value, callback) => {\n      const phoneReg = /^1[3|4|5|7|8][0-9]\\d{8}$/\n      if (!value) {\n        this.verPhone = false\n        return callback(new Error('请输入手机号'))\n      }\n      if (!phoneReg.test(value)) {\n        this.verPhone = false\n        return callback(new Error('请输入正确的手机号'))\n      }\n      await checkPhone({\n        value\n      }).then(res => {\n        if (res.result === true) {\n          this.verPhone = false\n          this.existPhone = true\n        } else {\n          this.verPhone = true\n          this.existPhone = false\n        }\n      })\n      if (this.existPhone) {\n        return callback(new Error('此手机号已注册'))\n      }\n      this.$refs.registered.validateField('verCode')\n      return callback()\n    }\n    let vVerCode = (rule, value, callback) => {\n      let phone = this.registered.phone\n      if (value !== this.verCode) {\n        this.verVerCode = false\n        return callback(new Error('验证码错误'))\n      } else if (phone !== this.codePhone) {\n        this.verVerCode = false\n        return callback(new Error('验证码错误'))\n      }\n      this.verVerCode = true\n      return callback()\n    }\n    let vPass = (rule, value, callback) => {\n      const passReg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$/\n      if (!value) {\n        this.verPass = false\n        return callback(new Error('请输入密码'))\n      } else if (!passReg.test(value)) {\n        this.verPass = false\n        return callback(new Error('密码长度 6-16 位，数字字母至少包含两种'))\n      } else {\n        this.$refs.registered.validateField('pass2')\n      }\n      this.verPass = true\n      return callback()\n    }\n    let vPass2 = (rule, value, callback) => {\n      if (!value) {\n        this.verPass2 = false\n        return callback(new Error('请再次输入密码'))\n      } else if (value !== this.registered.pass) {\n        this.verPass2 = false\n        return callback(new Error('两次输入密码不一致!'))\n      }\n      this.verPass2 = true\n      return callback()\n    }\n    return {\n      registered: {\n        phone: '',\n        verCode: '',\n        pass: '',\n        pass2: ''\n      },\n      rules: {\n        phone: [\n          {validator: vPhone, trigger: 'change,blur'}\n        ],\n        verCode: [\n          {validator: vVerCode, trigger: 'blur'}\n        ],\n        pass: [\n          {validator: vPass, trigger: 'change,blur'}\n        ],\n        pass2: [\n          {validator: vPass2, trigger: 'change,blur'}\n        ]\n      },\n      verPhone: false,\n      verVerCode: false,\n      verPass: false,\n      verPass2: false,\n      existPhone: false,\n      sendAuthCode: true,\n      authTime: 60,\n      verCode: '',\n      codePhone: '',\n      agreement: false,\n      registerTxt: '注册',\n      cart: []\n    }\n  },\n  methods: {\n    sendVerCode () {\n      let phone = this.registered.phone\n      this.sendAuthCode = false\n      let authTimetimer = setInterval(() => {\n        this.authTime--\n        if (this.authTime <= 0) {\n          this.sendAuthCode = true\n          clearInterval(authTimetimer)\n        }\n      }, 1000)\n      vercode({\n        phone\n      }).then(res => {\n        console.log(res.result)\n        this.codePhone = phone\n        this.verCode = res.result\n      })\n    },\n    regist () {\n      let phone = this.registered.phone\n      let password = this.registered.pass\n      this.registerTxt = '注册中...'\n      register({\n        phone,\n        password\n      }).then(res => {\n        if (res.status === 200) {\n          this.messageSuccess()\n          this.toLogin()\n        } else {\n          this.message(res.message)\n          this.registerTxt = '注册'\n        }\n      })\n    },\n    open (t, m) {\n      this.$notify.info({\n        title: t,\n        message: m\n      })\n    },\n    messageSuccess () {\n      this.$message({\n        message: '恭喜您，注册成功！赶紧区登录体验吧',\n        type: 'success'\n      })\n    },\n    toLogin () {\n      this.$router.push({\n        path: '/login'\n      })\n    }\n  },\n  components: {\n    YFooter,\n    YButton\n  }\n}\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\">\n* {\n  box-sizing: content-box;\n}\n\n.register-form .el-input__inner {\n  height: 50px;\n}\n\n.login {\n  overflow-x: hidden;\n  overflow-y: hidden;\n  .input {\n    height: 50px;\n    display: flex;\n    align-items: center;\n    input {\n      font-size: 16px;\n      width: 100%;\n      height: 100%;\n      padding: 10px 15px;\n      box-sizing: border-box;\n      border: 1px solid #ccc;\n      border-radius: 6px;\n    }\n  }\n  .wrapper {\n    background: url(/static/images/bg_9b9dcb65ff.png) repeat;\n    background-size: 100px;\n    min-height: 800px;\n    min-width: 630px;\n  }\n}\n\n.v2 .dialog {\n  width: 450px;\n  border: 1px solid #dadada;\n  border-radius: 10px;\n  top: 50%;\n  left: 50%;\n  margin-left: -225px;\n  position: absolute;\n  .title {\n    background: linear-gradient(#fff, #f5f5f5);\n    height: auto;\n    overflow: visible;\n    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);\n    position: relative;\n    background-image: url(/static/images/smartisan_4ada7fecea.png);\n    background-size: 140px;\n    background-position: top center;\n    background-repeat: no-repeat;\n    height: 92px;\n    margin: 23px 0 50px;\n    padding: 75px 0 0;\n    box-shadow: none;\n    h4 {\n      padding: 0;\n      text-align: center;\n      color: #666;\n      border-bottom: 1px solid #dcdcdc;\n      -webkit-box-shadow: none;\n      -moz-box-shadow: none;\n      box-shadow: none;\n      font-weight: 700;\n      position: absolute;\n      bottom: 0;\n      width: 100%;\n      text-align: center;\n      margin: 0;\n      padding: 0;\n      border-bottom: 0;\n      -webkit-box-shadow: none;\n      -moz-box-shadow: none;\n      box-shadow: none;\n      line-height: 1em;\n      height: auto;\n      color: #333;\n      font-weight: 400;\n    }\n  }\n  .content {\n    padding: 0 40px 22px;\n    height: auto;\n    .common-form {\n      li {\n        clear: both;\n        margin-bottom: 15px;\n        position: relative;\n      }\n    }\n  }\n}\n\n.dialog-shadow,\n.v2 .bbs .dialog-shadow,\n.v2 .dialog-shadow {\n  -webkit-box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),\n    0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),\n    0 10px 20px -10px rgba(0, 0, 0, 0.04);\n  -moz-box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),\n    0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),\n    0 10px 20px -10px rgba(0, 0, 0, 0.04);\n  box-shadow: 0 9px 30px -6px rgba(0, 0, 0, 0.2),\n    0 18px 20px -10px rgba(0, 0, 0, 0.04), 0 18px 20px -10px rgba(0, 0, 0, 0.04),\n    0 10px 20px -10px rgba(0, 0, 0, 0.04);\n}\n\n@media screen and (min-width: 737px),\n  screen and (-webkit-max-device-pixel-ratio: 1.9) and (max-width: 736px) and (min-device-width: 737px) {\n  .wrapper {\n    background: url(/static/images/con-bg_04f25dbf8e.jpg) repeat-x;\n    position: absolute;\n    top: 0;\n    bottom: 0;\n    left: 0;\n    right: 0;\n  }\n  .dialog {\n    background: url(/static/images/dialog-gray-bg.png) #fff bottom repeat-x;\n    border-radius: 12px;\n    display: none;\n    margin: -163px 0 0 -218px;\n    width: 436px;\n    position: fixed;\n    left: 50%;\n    top: 50%;\n  }\n  .register {\n    padding: 1px 10px 0;\n    border-right: 1px solid #ccc;\n  }\n  .border {\n    margin-top: 10px;\n    border-bottom: 1px solid #ccc;\n    margin-bottom: 10px;\n  }\n  .other {\n    margin: 20px 5px 0 0;\n    width: auto;\n    color: #bbb;\n    font-size: 12px;\n    cursor: default;\n    color: #999;\n  }\n  .footer {\n    display: flex;\n    flex-direction: row;\n  }\n  .agree {\n    margin-bottom: 30px;\n    color: #999;\n  }\n}\n\n.registered {\n  h4 {\n    padding: 0;\n    text-align: center;\n    color: #666;\n    border-bottom: 1px solid #dcdcdc;\n    -webkit-box-shadow: none;\n    -moz-box-shadow: none;\n    box-shadow: none;\n    font-weight: 700;\n    font-size: 20px;\n    height: 60px;\n    line-height: 60px;\n  }\n}\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Order/order.vue",
    "content": "<template>\n  <div>\n    <y-header>\n      <div slot=\"nav\">\n      </div>\n    </y-header>\n    <router-view style=\"margin-top: 40px;\"></router-view>\n    <y-footer></y-footer>\n  </div>\n</template>\n<script>\n  import YHeader from '/common/header'\n  import YFooter from '/common/footer'\n  export default {\n    components: {\n      YHeader,\n      YFooter\n    }\n  }\n</script>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Order/payment.vue",
    "content": "<template>\n  <div class=\"w\" style=\"padding-bottom: 50px;\">\n    <y-shelf title=\"支付订单\">\n      <div slot=\"content\">\n        <div class=\"box-inner order-info\">\n          <h3>提交订单成功，请选择支付方式</h3>\n          <p class=\"payment-detail\">请在 <span style=\"color: #d44d44; font-weight: 700;\">2 小时内 </span>完成支付，超时订单将自动取消。</p>\n          <p class=\"payment-detail\">我们将在您完成支付后的 72 小时内发货</p>\n        </div>\n        <!-- 支付方式 -->\n        <div class=\"pay-type\">\n          <div class=\"p-title\">支付方式</div>\n          <div class=\"pay-item\">\n            <div class=\"active\"><img src=\"/static/images/alipay@2x.png\" alt=\"\"></div>\n          </div>\n          <div class=\"nav-user-wrapper pa active\">\n            <div class=\"nav-user-list\">\n              <div class=\"code-viewer\">\n                <canvas id=\"msg\"></canvas>\n              </div>\n              <p class=\"tip\">请使用支付宝扫一扫</p>\n              <p class=\"tip\">扫描二维码支付</p>\n            </div>\n          </div>\n        </div>\n        <!-- 订单金额 -->\n        <div>\n          <div class=\"box-inner\">\n            <div>\n              <span>\n                订单金额：\n              </span>\n              <em><span>¥</span>{{orderTotal.toFixed(2)}}</em>\n              <span>\n                实际应付金额：\n              </span>\n              <em><span>¥</span>{{orderTotal.toFixed(2)}}</em>\n            </div>\n          </div>\n        </div>\n      </div>\n    </y-shelf>\n\n    <!-- 地址信息 -->\n    <div class=\"p-msg w\">\n      <div class=\"confirm-detail\">\n        <div class=\"info-title\">收货信息</div>\n        <p class=\"info-detail\">姓名：{{address.userName}}</p>\n        <p class=\"info-detail\">联系电话：{{address.tel}}</p>\n        <p class=\"info-detail\">详细地址：{{address.streetName}}</p></div>\n    </div>\n\n    <!-- 商品信息 -->\n    <div class=\"confirm-table-title\">\n      <span class=\"name\">商品信息</span>\n      <div>\n        <span class=\"price\">单价</span>\n        <span class=\"num\">数量</span>\n        <span class=\"subtotal\">小计</span>\n      </div>\n    </div>\n    <div class=\"confirm-goods-table\">\n      <div class=\"cart-items\" v-for=\"(item,i) in cartList\" :key=\"i\">\n        <div class=\"name\">\n          <div class=\"name-cell ellipsis\">\n            <a @click=\"goodsDetails(item.productId)\" title=\"\" target=\"_blank\">{{item.productName}}</a>\n          </div>\n        </div>\n        <div class=\"n-b\">\n          <div class=\"price\">¥ {{item.salePrice.toFixed(2)}}</div>\n          <div class=\"goods-num\">{{item.productNum}}</div>\n          <div class=\"subtotal\">\n            <div class=\"subtotal-cell\"> ¥ {{(item.salePrice * item.productNum).toFixed(2)}}<br></div>\n          </div>\n        </div>\n      </div>\n    </div>\n\n    <!-- 合计 -->\n    <div class=\"order-discount-line\">\n      <p style=\"font-size: 14px;font-weight: bolder;\"> <span style=\"padding-right:47px\">商品总计：</span>\n        <span style=\"font-size: 16px;font-weight: 500;line-height: 32px;\">¥ {{orderTotal.toFixed(2)}}</span>\n      </p>\n    </div>\n  </div>\n</template>\n<script>\n  import YShelf from '/components/shelf'\n  import { getStore } from '/utils/storage'\n  import { getOrderDet, payment, getOrderStatus } from '/api/order'\n  import QRCode from 'qrcode'\n\n  export default {\n    data () {\n      return {\n        userId: '',\n        orderId: '',\n        cartList: [],\n        address: {\n          userName: '',\n          tel: '',\n          streetName: ''\n        },\n        orderTotal: 0,\n        qrCode: '',\n        myInterval: ''\n      }\n    },\n    watch: {\n      // 通过监听获取数据\n      qrCode (val) {\n        // 获取页面的canvas\n        let msg = document.getElementById('msg')\n        // 将获取到的数据（val）画到msg（canvas）上\n        QRCode.toCanvas(msg, val, function (error) {\n          console.log(error)\n        })\n      }\n    },\n    methods: {\n      // 获取订单详情\n      _getOrderDet (orderId) {\n        let params = {\n          params: {\n            orderId: orderId\n          }\n        }\n        getOrderDet(params).then(res => {\n          if (res.status === 200) {\n            if (res.result.orderStatus === 0) {\n              console.log('订单未支付')\n              this.cartList = res.result.goodsList\n              this.address.userName = res.result.tbAddress.userName\n              this.address.tel = res.result.tbAddress.tel\n              this.address.streetName = res.result.tbAddress.streetName\n              this.orderTotal = res.result.orderTotal\n              console.log(this.orderId)\n              this.getPay()\n            } else {\n              // todo\n              this.$router.push({\n                path: '/user/orderDetail',\n                query: {\n                  orderId: orderId\n                }\n              })\n            }\n          } else {\n            this.$router.push({\n              path: '/'\n            })\n          }\n        })\n      },\n      // 商品详情\n      goodsDetails (id) {\n        window.open(window.location.origin + '/goodsDetails?productId=' + id)\n      },\n      // 获取付款二维码\n      getPay () {\n        payment({\n          orderId: this.orderId,\n          orderTotal: this.orderTotal\n        }).then(res => {\n          this.qrCode = res.qrCode\n          console.log(this.qrCode)\n          this._getOrderStatus()\n        })\n      },\n      // 获取订单支付状态\n      _getOrderStatus () {\n        let orderId = this.orderId\n        let params = {\n          params: {\n            orderId: orderId\n          }\n        }\n        this.myInterval = setInterval(() => {\n          setTimeout(() => {\n            getOrderStatus(params).then(res => {\n              console.log(res)\n              if (res === 'SUCCESS') {\n                clearInterval(this.myInterval)\n                this.$router.push({\n                  path: '/order/paysuccess',\n                  query: {\n                    orderId: orderId\n                  }\n                })\n              }\n            })\n          }, 1)\n        }, 3000)\n      }\n    },\n    created () {\n      this.userId = getStore('userId')\n      this.orderId = this.$route.query.orderId\n      let orderId = this.orderId\n      if (this.orderId) {\n        this._getOrderDet(orderId)\n      } else {\n        this.$router.push({\n          path: '/'\n        })\n      }\n    },\n    destroyed () {\n      clearInterval(this.myInterval)\n    },\n    components: {\n      YShelf,\n      QRCode\n    }\n  }\n</script>\n<style lang=\"scss\" scoped rel=\"stylesheet/scss\">\n\n  .nav-user-wrapper {\n    top: 18px;\n    visibility: visible;\n    opacity: 1;\n    -webkit-transition: opacity .15s ease-out;\n    transition: opacity .15s ease-out;\n  }\n\n  .nav-user-wrapper {\n    width: 182px;\n    transform: translate(-50%);\n    left: 50%;\n  }\n\n  .nav-user-wrapper.active {\n    top: 380px;\n    left: 235px;\n    visibility: visible;\n    opacity: 1;\n    -webkit-transition: opacity .15s ease-out;\n    transition: opacity .15s ease-out;\n  }\n\n  .nav-user-wrapper {\n    right: 0;\n    width: 360px;\n    .nav-user-list {\n      &:before {\n        right: 34px;\n      }\n    }\n  }\n\n  .nav-user-wrapper {\n    position: absolute;\n    z-index: 30;\n    padding-top: 18px;\n    opacity: 0;\n    visibility: hidden;\n    top: -3000px;\n  }\n\n  .nav-user-list {\n    width: 182px;\n    height: 250px;\n    text-align: center;\n    &:before {\n      left: 50%;\n    }\n  }\n\n  .nav-user-list .tip {\n    display: block;\n    padding-top: 8px;\n    color: #a1a1a1;\n    font-size: 12px;\n  }\n\n  .nav-user-list .code-viewer img{\n    display: block;\n    width: 133px;\n    height: 133px;\n    margin: 0 auto;\n    border: 0;\n  }\n\n  .w {\n    padding-top: 39px;\n  }\n\n  .order-info {\n    padding: 60px 0 55px;\n    color: #333;\n    background: #fff !important;\n    h3 {\n      padding-bottom: 14px;\n      line-height: 36px;\n      text-align: center;\n      font-size: 36px;\n      color: #212121;\n    }\n    .payment-detail {\n      text-align: center;\n      line-height: 24px;\n      font-size: 14px;\n      color: #999;\n    }\n  }\n\n  /*支付类型*/\n  .pay-type {\n    margin: 0 auto;\n    width: 90%;\n    padding-bottom: 30px;\n    height: 420px;\n    .p-title {\n      font-size: 18px;\n      line-height: 40px;\n      padding: 0 10px;\n      position: relative;\n      &:before {\n        content: ' ';\n        position: absolute;\n        bottom: 0;\n        left: 0;\n        right: 0;\n        border-bottom: 1px solid #ccc;\n      }\n    }\n\n  }\n\n  .pay-type {\n    .pay-item {\n      display: flex;\n      align-items: center;\n      div {\n        margin-top: 20px;\n        width: 175px;\n        height: 50px;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        border: 1px solid #E5E5E5;\n        cursor: pointer;\n        border-radius: 6px;\n        margin-right: 10px;\n        background: #FAFAFA;\n        &.active {\n          border-color: #6A8FE5;\n          background: #fff;\n        }\n        img {\n          display: block;\n          height: 34px;\n          margin: 8px auto;\n        }\n      }\n    }\n  }\n\n  .box-inner {\n    line-height: 60px;\n    background: #f9f9f9;\n    border-top: 1px solid #e5e5e5;\n    box-sizing: border-box;\n    > div {\n      display: flex;\n      justify-content: flex-end;\n      align-items: center;\n      padding: 0 20px;\n    }\n    em {\n      margin-left: 5px;\n      font-size: 24px;\n      color: #d44d44;\n      font-weight: 700;\n      margin-right: 20px;\n      span {\n        margin-right: 4px;\n        font-size: 16px;\n\n      }\n    }\n  }\n\n  .confirm-detail {\n    padding: 0 30px 25px;\n    border-top: 1px solid #d5d5d5;\n    .info-title {\n      height: 14px;\n      margin: 30px 0 17px;\n      line-height: 14px;\n      font-weight: bolder;\n      color: #333;\n    }\n    .info-detail {\n      line-height: 24px;\n      color: #666;\n    }\n  }\n\n  .confirm-table-title {\n    padding: 3px 0 0 33px;\n    border-top: 1px solid #D5D5D5;\n    line-height: 54px;\n    font-weight: bolder;\n    color: #000;\n    display: flex;\n    justify-content: space-between;\n    span {\n      display: inline-block;\n      width: 175px;\n      text-align: left;\n    }\n    .price {\n      padding-left: 80px;\n    }\n    .num {\n      padding-left: 75px;\n    }\n    .subtotal {\n      padding-left: 72px;\n    }\n  }\n\n  .confirm-goods-table {\n    border-top: 1px solid #D5D5D5;\n    .cart-items {\n      height: 80px;\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      a {\n        color: #333;\n      }\n    }\n    .n-b {\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      > div {\n        color: #626262;\n        font-weight: 700;\n        width: 175px;\n        text-align: center;\n      }\n    }\n  }\n\n  .order-discount-line {\n    padding: 22px 30px 53px;\n    border-top: 1px solid #D5D5D5;\n    line-height: 24px;\n    text-align: right;\n    font-size: 12px;\n    &:first-child {\n      line-height: 32px;\n      text-align: right;\n      font-size: 14px;\n      font-weight: bolder;\n    }\n  }\n\n  .name {\n    width: 40%;\n  }\n\n  .name-cell {\n    padding-left: 33px;\n  }\n\n  .input {\n    width:30%;\n    margin:0 0 1vw 38px;\n  }\n\n  .pay-info {\n    margin-top: -2vw;\n    text-align: center;\n  }\n\n  .money-select {\n    width: 31%;\n    padding-left: 10px;\n    margin-bottom: 1vw;\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Order/paysuccess.vue",
    "content": "<template>\n  <div class=\"w\">\n    <y-shelf title=\"支付成功\" style=\"text-align: center\">\n      <div slot=\"content\" class=\"content\">\n        <p>恭喜您支付成功<br></p>\n        <img src=\"/static/images/paysuccess.png\" style=\"margin-top: 25px; margin-bottom: 5px;\">\n        <div style=\"margin-top: 20px;\">\n            <y-button text=\"查看订单\" style=\"width: 150px;height: 50px;line-height: 48px;font-size: 20px\"\n                      classStyle=\"main-btn\" @btnClick=\"orderDetail\"></y-button>\n          <router-link to=\"/home\">\n            <y-button text=\"继续选购\" style=\"width: 150px;height: 50px;line-height: 48px;font-size: 20px\"\n                      classStyle=\"main-btn\"></y-button>\n\n          </router-link>\n        </div>\n      </div>\n    </y-shelf>\n  </div>\n</template>\n<script>\n  import YShelf from '/components/shelf'\n  import YButton from '/components/YButton'\n  export default {\n    data () {\n      return {\n        orderId: ''\n      }\n    },\n    components: {\n      YShelf,\n      YButton\n    },\n    methods: {\n      orderDetail () {\n        this.$router.push({\n          path: '/user/orderDetail',\n          query: {\n            orderId: this.orderId\n          }\n        })\n      }\n    },\n    created () {\n      this.orderId = this.$route.query.orderId\n    }\n  }\n</script>\n<style lang=\"scss\" scoped>\n  .content {\n    padding: 150px 0;\n    font-size: 30px;\n  }\n\n  .icon-success {\n    font-size: 33px;\n    color: #01b401;\n  }\n\n  span.price {\n    color: #d44d44;\n    font-weight: 700;\n    line-height: 20px;\n    text-align: right;\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Refresh/refreshsearch.vue",
    "content": "<template>\n \n</template>\n<script>\nexport default {\n  data () {\n    this.$router.push({\n      path: '/search',\n      query: {\n        key: this.$route.query.key\n      }\n    })\n    return {\n    }\n  },\n  methods: {\n  }\n}\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\" scoped>\n  \n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/Search/search.vue",
    "content": "<template>\n  <div class=\"goods\">\n    <!-- 查询条件 -->\n    <div class=\"nav\">\n      <div class=\"w\">\n        <a href=\"javascript:;\" :class=\"{active:sortType===1}\" @click=\"reset\">综合排序</a>\n        <a href=\"javascript:;\" :class=\"{active:sortType===2}\" @click=\"sortByOrder\">销量排序</a>\n        <a href=\"javascript:;\" :class=\"{active:sortType===3}\" @click=\"sortByPrice(3)\">价格从低到高</a>\n        <a href=\"javascript:;\" :class=\"{active:sortType===4}\" @click=\"sortByPrice(4)\">价格从高到低</a>\n        <div class=\"price-interval\">\n          <el-input type=\"number\" class=\"input\" placeholder=\"价格\" v-model=\"min\" style=\"width:83px;\"></el-input>\n          <span style=\"margin: 0 5px\"> - </span>\n          <el-input type=\"number\" placeholder=\"价格\" v-model=\"max\" style=\"width:100px;\"></el-input>\n          <!--<y-button text=\"确定\" :classStyle=\"min && max ? main-btn : default-btn\" @btnClick=\"_getAllGoods\" style=\"margin-left: 10px;\"></y-button>-->\n          <el-button type=\"primary\" @click=\"_getAllGoods\" :disabled=\"min && max && min < max ? false : true\" style=\"margin-left: 10px;\">确定</el-button>\n        </div>\n        <a v-if=\"searching\">拼命搜索中...</a>\n        <a v-if=\"!searching\">共为您找到 {{total}} 款商品信息</a>\n      </div>\n    </div>\n\n    <!-- 查询内容 -->\n    <div v-loading=\"loading\" element-loading-text=\"加载中...\" style=\"min-height: 35vw;\">\n      <div class=\"img-item\" v-if=\"!noResult\">\n        <!-- 商品 -->\n        <div class=\"goods-box w\">\n          <mall-goods v-for=\"(item, i) in goods\" :key=\"i\" :msg=\"item\"></mall-goods>\n        </div>\n\n        <!-- 分页 -->\n        <el-pagination\n          v-if=\"!noResult&&!error\"\n          @size-change=\"handleSizeChange\"\n          @current-change=\"handleCurrentChange\"\n          :current-page=\"currentPage\"\n          :page-sizes=\"[8, 20, 40, 80]\"\n          :page-size=\"pageSize\"\n          layout=\"total, sizes, prev, pager, next, jumper\"\n          :total=\"total\">\n        </el-pagination>\n      </div>\n      <!-- 没有结果 -->\n      <div class=\"no-info\" v-if=\"noResult\">\n        <div class=\"no-data\">\n          <img src=\"/static/images/no-search.png\">\n          <br>抱歉！暂时还没有商品\n        </div>\n        <section class=\"section\">\n          <y-shelf :title=\"recommendPanel.name\">\n            <div slot=\"content\" class=\"recommend\">\n              <mall-goods :msg=\"item\" v-for=\"(item,i) in recommendPanel.panelContentDtos\" :key=\"i\"></mall-goods>\n            </div>\n          </y-shelf>\n        </section>\n      </div>\n      <!-- 查询错误 -->\n      <div class=\"no-info\" v-if=\"error\">\n        <div class=\"no-data\">\n          <img src=\"/static/images/error.png\">\n          <br> 抱歉！出错了...\n        </div>\n        <section class=\"section\">\n          <y-shelf :title=\"recommendPanel.name\">\n            <div slot=\"content\" class=\"recommend\">\n              <mall-goods :msg=\"item\" v-for=\"(item,i) in recommendPanel.panelContentDtos\" :key=\"i\"></mall-goods>\n            </div>\n          </y-shelf>\n        </section>\n      </div>\n    </div>\n  </div>\n</template>\n<script>\n  import MallGoods from '/components/mallGoods'\n  import { recommend } from '/api/index'\n  import YShelf from '/components/shelf'\n  import { getAllGoods } from '/api/goods'\n\n  export default {\n    data () {\n      return {\n        recommendPanel: {\n          name: '',\n          panelContentDtos: []\n        },\n        error: false,\n        noResult: false,\n        loading: false,\n        total: 0,\n        goods: [],\n        pageSize: 20,\n        currentPage: 1,\n        sort: '',\n        sortType: 1,\n        min: '',\n        max: '',\n        key: '',\n        searching: true\n      }\n    },\n    methods: {\n      handleSizeChange (val) {\n        this.pageSize = val\n        this._getAllGoods()\n        this.loading = true\n      },\n      handleCurrentChange (val) {\n        this.currentPage = val\n        this._getAllGoods()\n        this.loading = true\n      },\n      _getAllGoods () {\n        let params = {\n          params: {\n            page: this.currentPage,\n            size: this.pageSize,\n            sort: this.sort,\n            priceGt: this.min,\n            priceLte: this.max,\n            key: this.key\n          }\n        }\n        getAllGoods(params).then(res => {\n          if (res.status === 200) {\n            this.total = res.result.total\n            this.goods = res.result.data\n            this.noResult = false\n            if (this.total === 0) {\n              this.noResult = true\n            }\n            this.error = false\n          } else {\n            this.error = true\n          }\n          this.searching = false\n          this.loading = false\n        })\n      },\n      // 默认排序\n      reset () {\n        this.sortType = 1\n        this.sort = 1\n        this.currentPage = 1\n        this.loading = true\n        this._getAllGoods()\n      },\n      // 销量排序\n      sortByOrder () {\n        this.sortType = 2\n        this.sort = 2\n        this.currentPage = 1\n        this.loading = true\n        this._getAllGoods()\n      },\n      // 价格排序\n      sortByPrice (v) {\n        this.sortType = v\n        this.sort = v\n        this.currentPage = 1\n        this.loading = true\n        this._getAllGoods()\n      }\n    },\n    watch: {\n      $route (to, from) {\n        if (to.fullPath.indexOf('/goods?category=') >= 0) {\n          this.cid = to.query.cid\n          this._getAllGoods()\n        }\n      }\n    },\n    mounted () {\n      this.key = this.$route.query.key\n      this._getAllGoods()\n      recommend().then(res => {\n        if (res.status === 200) {\n          this.recommendPanel = res.result\n          this.error = false\n        } else {\n          this.error = true\n        }\n      })\n    },\n    components: {\n      MallGoods,\n      YShelf\n    }\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\">\n  @import \"../../assets/style/mixin\";\n  @import \"../../assets/style/theme\";\n\n  .nav {\n    height: 60px;\n    line-height: 60px;\n    > div {\n      display: flex;\n      align-items: center;\n      a {\n        padding: 0 15px;\n        height: 100%;\n        @extend %block-center;\n        font-size: 12px;\n        color: #999;\n        &.active {\n          color: #5683EA;\n        }\n        &:hover {\n          color: #5683EA;\n        }\n      }\n      input {\n        @include wh(80px, 30px);\n        border: 1px solid #ccc;\n      }\n      input + input {\n        margin-left: 10px;\n      }\n    }\n    .price-interval {\n      padding: 0 15px;\n      @extend %block-center;\n      input[type=number] {\n        border: 1px solid #ccc;\n        text-align: center;\n        background: none;\n        border-radius: 5px;\n      }\n    }\n  }\n\n  .goods-box {\n    > div {\n      float: left;\n      border: 1px solid #efefef;\n    }\n  }\n\n  em {\n    color: #e4393c;\n  }\n\n  .no-info {\n    padding: 100px 0;\n    text-align: center;\n    font-size: 30px;\n    display: flex;\n    flex-direction: column;\n    .no-data{\n      align-self: center;\n    }\n  }\n\n  .img-item{\n    display: flex;\n    flex-direction: column;\n  }\n\n  .el-pagination{\n    align-self: flex-end;\n    margin: 3vw 10vw 2vw;\n  }\n\n  .section {\n    padding-top: 8vw;\n    margin-bottom: -5vw;\n    width: 1218px;\n    align-self: center;\n  }\n\n  .recommend {\n    display: flex;\n    > div {\n      flex: 1;\n      width: 25%;\n    }\n  }\n\n\n\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/User/children/addressList.vue",
    "content": "<template>\n  <div>\n    <y-shelf title=\"收货地址\">\n      <span slot=\"right\"><y-button text=\"添加收货地址\" style=\"margin: 0\" @btnClick=\"update()\"></y-button></span>\n      <div slot=\"content\">\n        <!--标题-->\n        <div class=\"table-title\">\n          <span class=\"name\">姓名</span> <span class=\"address\">详细地址</span> <span class=\"tel\">电话</span>\n        </div>\n        <div v-if=\"addList.length\">\n          <div class=\"address-item\" v-for=\"(item,i) in addList\" :key=\"i\">\n            <div class=\"name\">{{item.userName}}</div>\n            <div class=\"address-msg\">{{item.detailsAddress}}</div>\n            <div class=\"telephone\">{{item.tel}}</div>\n            <div class=\"defalut\">\n              <a @click=\"changeDef(item)\"\n                 href=\"javascript:;\"\n                 v-text=\"item.isDefault?'( 默认地址 )':'设为默认'\"\n                 :class=\"{'defalut-address':item.isDefault}\"></a>\n            </div>\n            <div class=\"operation\">\n              <el-button type=\"primary\" icon=\"edit\" size=\"small\"  @click=\"update(item)\"></el-button>\n              <el-button type=\"danger\" icon=\"delete\" size=\"small\" :data-id=\"item.id\" @click=\"del(item.id,i)\"></el-button>\n            </div>\n          </div>\n        </div>\n        <div v-else>\n          <div style=\"padding: 80px 0;text-align: center\">\n            <div style=\"font-size: 20px\">你还未添加收货地址</div>\n            <div style=\"margin: 20px \">\n              <y-button text=\"添加地址\" @btnClick=\"update()\"></y-button>\n            </div>\n          </div>\n        </div>\n      </div>\n    </y-shelf>\n\n    <!-- 新增或修改地址 -->\n    <div class=\"edit-address\" v-show=\"editAddressShow\">\n      <y-shelf :title=\"addressTxt\">\n            <span slot=\"right\">\n              <span class=\"close\" @click=\"editAddressShow=false\">\n                <svg t=\"1501234940517\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\"\n                     xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3014\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n                     width=\"20\" height=\"20\"><path\n                  d=\"M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z\"\n                  fill=\"#cdcdcd\" p-id=\"3015\"></path></svg>\n              </span>\n            </span>\n        <div slot=\"content\" class=\"content\">\n          <el-form :model=\"addressVer\" :rules=\"addressVerRules\" ref=\"addressVer\" class=\"register-form\">\n            <el-form-item prop=\"userName\">\n              <el-input v-model=\"addressVer.userName\" size=\"large\" placeholder=\"收货人姓名\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n            </el-form-item>\n            <el-form-item prop=\"phone\">\n              <el-input v-model=\"addressVer.phone\" size=\"large\" placeholder=\"手机号\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n            </el-form-item>\n            <el-form-item>\n              <el-cascader\n                placeholder=\"请选择地址\"\n                size=\"large\"\n                :options=\"options\"\n                v-model=\"selectedOptions\"\n                @change=\"handleChange\" style=\"width:296px;\">\n              </el-cascader>\n            </el-form-item>\n            <el-form-item prop=\"streetName\">\n              <el-input v-model=\"addressVer.streetName\" size=\"large\" placeholder=\"街道地址\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n            </el-form-item>\n            <el-checkbox class=\"auto-login\" v-model=\"addressVer.isDefault\">设为默认</el-checkbox>\n          </el-form>\n\n          <div class=\"bootom-btn pa\">\n            <el-button @click=\"editAddressShow=false\" style=\"width: 140px; height: 40px;\">\n              取消\n            </el-button>\n            <el-button @click=\"save({userId:userId,id:addressVer.addressId,userName:addressVer.userName,tel:addressVer.phone,state: addressVer.state, city: addressVer.city, district: addressVer.district, streetName:addressVer.streetName,isDefault:addressVer.isDefault})\" type=\"primary\" :disabled=\"btnHighlight ? false : true\"  style=\"width: 140px; height: 40px;\">\n              确定\n            </el-button>\n          </div>\n        </div>\n      </y-shelf>\n    </div>\n  </div>\n</template>\n<script>\n  import { addressList, addressUpdate, addressAdd, addressDel } from '/api/member'\n  import YButton from '/components/YButton'\n  import YPopup from '/components/popup'\n  import YShelf from '/components/shelf'\n  import { getStore } from '/utils/storage'\n  import { regionData, CodeToText, TextToCode } from 'element-china-area-data'\n\n  export default {\n    data () {\n      // 验证收货人\n      let vUserName = (rule, value, callback) => {\n        if (!value) {\n          this.verUserName = false\n          return callback(new Error('请输入收货人姓名'))\n        }\n        this.verUserName = true\n        return callback()\n      }\n      // 验收收货手机号\n      let vPhone = (rule, value, callback) => {\n        const phoneReg = /^1[3|4|5|7|8][0-9]\\d{8}$/\n        if (!value) {\n          this.verPhone = false\n          return callback(new Error('请输入手机号'))\n        }\n        if (!phoneReg.test(value)) {\n          this.verPhone = false\n          return callback(new Error('请输入正确的手机号'))\n        }\n        this.verPhone = true\n        return callback()\n      }\n      // 验证街道\n      let vStreetName = (rule, value, callback) => {\n        if (!value) {\n          this.verStreetName = false\n          return callback(new Error('请输入街道地址'))\n        }\n        this.verStreetName = true\n        return callback()\n      }\n      return {\n        addList: [],\n        userId: '',\n        addressTxt: '新增收货地址',\n        editAddressShow: false,\n        addressVer: {\n          addressId: '',\n          userName: '',\n          phone: '',\n          state: '',\n          city: '',\n          district: '',\n          streetName: '',\n          isDefault: false\n        },\n        addressVerRules: {\n          userName: [\n            {validator: vUserName, trigger: 'change, blur'}\n          ],\n          phone: [\n            {validator: vPhone, trigger: 'change, blur'}\n          ],\n          streetName: [\n            {validator: vStreetName, trigger: 'change, blur'}\n          ]\n        },\n        verUserName: false,\n        verPhone: false,\n        verStreetName: false,\n        options: regionData,\n        selectedOptions: [],\n        // 详细地址\n        detailedAddress: ''\n      }\n    },\n    computed: {\n      btnHighlight () {\n        return this.verUserName && this.verPhone && this.addressVer.state && this.addressVer.city && this.addressVer.district && this.verStreetName\n      }\n    },\n    methods: {\n      // 错误消息提示\n      message (m) {\n        this.$message.error({\n          message: m\n        })\n      },\n      // 获取会员地址列表\n      _addressList () {\n        let params = {\n          params: {\n            userId: this.userId\n          }\n        }\n        addressList(params).then(res => {\n          let data = res.result\n          if (data.length) {\n            this.addList = res.result\n          } else {\n            this.addList = []\n          }\n        })\n      },\n      // 更新会员地址\n      _addressUpdate (params) {\n        addressUpdate(params).then(res => {\n          this._addressList()\n        })\n      },\n      // 新增会员地址\n      _addressAdd (params) {\n        addressAdd(params).then(res => {\n          if (res.status === 200) {\n            this._addressList()\n          } else {\n            this.message(res.message)\n          }\n        })\n      },\n      // 修改默认地址\n      changeDef (item) {\n        item.userId = this.userId\n        if (!item.isDefault) {\n          item.isDefault = true\n          this._addressUpdate(item)\n        }\n        return false\n      },\n      // 保存会员地址\n      save (p) {\n        this.editAddressShow = false\n        if (p.id) {\n          this._addressUpdate(p)\n        } else {\n          delete p.id\n          this._addressAdd(p)\n        }\n      },\n      // 删除会员地址\n      del (addressId, i) {\n        addressDel({id: addressId}).then(res => {\n          if (res.status === 200) {\n            this.addList.splice(i, 1)\n          } else {\n            this.message('删除失败')\n          }\n        })\n      },\n      // 修改会员地址\n      update (item) {\n        this.editAddressShow = true\n        if (item) {\n          this.addressTxt = '修改收货地址'\n          let state = TextToCode[item.state].code\n          let city = TextToCode[item.state][item.city].code\n          let district = TextToCode[item.state][item.city][item.district].code\n          this.selectedOptions.push(state, city, district)\n          this.addressVer.userName = item.userName\n          this.addressVer.phone = item.tel\n          this.addressVer.state = item.state\n          this.addressVer.city = item.city\n          this.addressVer.district = item.district\n          this.addressVer.streetName = item.streetName\n          this.addressVer.isDefault = item.isDefault\n          this.addressVer.addressId = item.id\n        } else {\n          this.addressTxt = '新增收货地址'\n          this.addressVer.userName = ''\n          this.addressVer.phone = ''\n          this.addressVer.state = ''\n          this.addressVer.city = ''\n          this.addressVer.district = ''\n          this.selectedOptions = []\n          this.addressVer.streetName = ''\n          this.addressVer.isDefault = false\n          this.addressVer.addressId = ''\n        }\n      },\n      // 修改城市选择\n      handleChange (value) {\n        console.log(this.selectedOptions)\n        let addArr = value\n        let state = CodeToText[(addArr[0])]\n        let city = CodeToText[(addArr[1])]\n        let district = CodeToText[(addArr[2])]\n        this.addressVer.state = state\n        this.addressVer.city = city\n        this.addressVer.district = district\n      }\n    },\n    created () {\n      this.userId = getStore('userId')\n      this._addressList()\n    },\n    components: {\n      YButton,\n      YPopup,\n      YShelf\n    }\n  }\n</script>\n<style scoped lang=\"scss\">\n  @import \"../../../assets/style/mixin\";\n\n  .el-cascader-menus {\n    z-index: '9999!important';\n  }\n\n  // 修改会员地址\n  .edit-address {\n    z-index: 1999;\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    @include wh(100%);\n    background-color: rgba(0, 0, 0, .5);\n    @extend %block-center;\n    .content {\n      display: flex;\n      padding: 45px 100px 0;\n    }\n    > div {\n      box-sizing: content-box;\n      @include wh(500px, 460px);\n      margin: 0;\n    }\n    .btn {\n      width: 80px;\n      height: 30px;\n      margin-left: 10px;\n      position: relative;\n      text-align: center;\n      line-height: 30px;\n      text-shadow: rgba(255, 255, 255, .496094) 0 1px 0;\n      border: 1px solid #E6E6E6;\n      border-radius: 10px;\n      &:hover {\n      }\n      a {\n        color: #666;\n        display: block;\n        @include wh(100%);\n      }\n    }\n    input[type=file] {\n      position: absolute;\n      right: 0;\n      left: 0;\n      top: 0;\n      opacity: 0;\n      width: 80px;\n      height: 30px;\n      cursor: pointer;\n      box-sizing: border-box;\n      border: 15px solid #000;\n      overflow: hidden;\n    }\n    .edit-l {\n      width: 100px;\n      text-align: center;\n    }\n    .edit-r {\n      margin-left: 20px;\n      flex: 1;\n      > div {\n        border: 1px solid #ccc;\n        width: 320px;\n        height: 320px;\n      }\n    }\n  }\n\n  .close {\n    position: absolute;\n    right: 10px;\n    top: 0;\n    bottom: 0;\n    padding: 0 10px;\n    @extend %block-center;\n    &:hover {\n      svg {\n        transition: all 1s;\n        transform: rotate(360deg);\n        transform-origin: 50% 50%;\n      }\n      path {\n        fill: #8a8a8a;\n      }\n    }\n  }\n\n  .bootom-btn {\n    padding: 0 15px;\n    border-top: 1px solid #E6E6E6;\n    bottom: 0;\n    height: 60px;\n    right: 0;\n    left: 0;\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n  }\n\n  .table-title {\n    position: relative;\n    z-index: 1;\n    line-height: 38px;\n    height: 38px;\n    padding: 0 0 0 38px;\n    font-size: 12px;\n    background: #eee;\n    border-bottom: 1px solid #dbdbdb;\n    border-bottom-color: rgba(0, 0, 0, .08);\n    .name {\n      float: left;\n      text-align: left;\n    }\n    span {\n      width: 137px;\n      float: left;\n      text-align: center;\n      color: #838383;\n    }\n    .address {\n      margin-left: 115px;\n    }\n    .tel {\n      margin-left: 195px;\n    }\n  }\n\n  .address-item {\n    display: flex;\n    align-items: center;\n    height: 115px;\n    text-align: center;\n    .name {\n      width: 106px;\n    }\n    .address-msg {\n      flex: 1;\n    }\n    .telephone {\n      width: 160px;\n    }\n    .defalut {\n      width: 80px;\n      > a {\n        text-align: center;\n        /*display: none;*/\n      }\n    }\n    .operation {\n      width: 135px;\n      a {\n        padding: 10px 5px;\n      }\n    }\n    &:hover {\n      .defalut > a {\n        display: block;\n      }\n    }\n  }\n\n  .address-item + .address-item {\n    border-top: 1px solid #CFCFCF;\n  }\n\n  .defalut-address {\n    color: #626262;\n    display: block;\n    pointer-events: none;\n    cursor: default;\n  }\n\n  .md {\n    > div {\n      text-align: left;\n      margin-bottom: 15px;\n      > input {\n        width: 100%;\n        height: 50px;\n        font-size: 18px;\n        padding: 10px 20px;\n        border: 1px solid #ccc;\n        border-radius: 6px;\n        box-shadow: 0 3px 5px -4px rgba(0, 0, 0, .4) inset, -1px 0 3px -2px rgba(0, 0, 0, .1) inset;\n        line-height: 46px;\n      }\n    }\n  }\n\n  .btn {\n    margin: 0;\n    width: 100%;\n    height: 50px;\n    font-size: 14px;\n    line-height: 48px\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/User/children/information.vue",
    "content": "<template>\n  <div>\n    <y-shelf title=\"账户资料\">\n      <div slot=\"content\">\n        <!-- 头像 -->\n        <div class=\"avatar-box\">\n          <div class=img-box><img :src=\"userInfo.info.file\" alt=\"\"></div>\n          <div class=\"r-box\">\n            <h3 style=\"margin-left: 13px;\">修改头像</h3>\n            <y-button text=\"上传头像\" classStyle=\"main-btn\" style=\"margin: 0;\" @btnClick=\"editAvatar()\"></y-button>\n          </div>\n        </div>\n\n        <!-- 账户昵称 -->\n        <div class=\"avatar-box\">\n          <div class=\"status-box\">\n            <div class=\"safe-center-title\">\n              <h3>账户昵称</h3>\n            </div>\n            <p>{{userTxt}}</p>\n          </div>\n          <div class=\"safe-todo\">\n            <a @click=\"updateUsername\">{{userOperate}}</a>\n          </div>\n        </div>\n\n        <!-- 手机号 -->\n        <div class=\"avatar-box\">\n          <div class=\"status-box\">\n            <div class=\"safe-center-title\">\n              <h3>手机验证</h3>\n            </div>\n            <p>{{phoneTxt}}</p>\n          </div>\n          <div class=\"safe-todo\">\n            <a @click=\"updatePhone\">{{phoneOperate}}</a>\n          </div>\n        </div>\n\n        <!-- 登录密码 -->\n        <div class=\"avatar-box\">\n          <div class=\"status-box\">\n            <div class=\"safe-center-title\">\n              <h3>登录密码</h3>\n            </div>\n            <p>互联网账号存在被盗风险，建议您定期更改密码以保护账户安全。</p>\n          </div>\n          <div class=\"safe-todo\">\n            <a @click=\"openPass\">修改</a>\n          </div>\n        </div>\n\n        <!-- 邮箱 -->\n        <div class=\"avatar-box\" style=\"border: none\">\n          <div class=\"status-box\">\n            <div class=\"safe-center-title\">\n              <h3>邮箱验证</h3>\n            </div>\n            <p>{{emailTxt}}</p>\n          </div>\n          <div class=\"safe-todo\">\n            <a @click=\"openEmail\">{{emailOperate}}</a>\n          </div>\n        </div>\n\n        <!-- 修改用户名 -->\n        <div class=\"edit-nick\" v-show=\"editNickShow\">\n          <y-shelf title=\"修改昵称\">\n            <span slot=\"right\">\n              <span class=\"close\" @click=\"editNickShow=false\">\n                <svg t=\"1501234940517\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\"\n                     xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3014\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n                     width=\"20\" height=\"20\"><path\n                  d=\"M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z\"\n                  fill=\"#cdcdcd\" p-id=\"3015\"></path></svg>\n              </span>\n            </span>\n            <div slot=\"content\" class=\"content\">\n              <el-form :model=\"nickVer\" :rules=\"nickVerRules\" ref=\"nickVer\" class=\"register-form\">\n                <el-form-item prop=\"nick\">\n                  <el-input v-model=\"nickVer.nick\" size=\"large\" placeholder=\"昵称\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n                </el-form-item>\n              </el-form>\n\n              <div class=\"bootom-btn pa\">\n                <el-button @click=\"editNickShow=false\" style=\"width: 140px; height: 40px;\">\n                  取消\n                </el-button>\n                <el-button @click=\"saveUsername({userId:userId, token: token, username: nickVer.nick})\" type=\"primary\" :disabled=\"verNick ? false : true\"  style=\"width: 140px; height: 40px;\">\n                  确定\n                </el-button>\n              </div>\n            </div>\n          </y-shelf>\n        </div>\n\n        <!-- 手机号验证 -->\n        <div class=\"edit-phone\" v-show=\"verPhoneShow\">\n          <y-shelf title=\"安全验证\">\n            <span slot=\"right\">\n              <span class=\"close\" @click=\"verPhoneShow=false\">\n                <svg t=\"1501234940517\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\"\n                     xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3014\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n                     width=\"20\" height=\"20\"><path\n                  d=\"M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z\"\n                  fill=\"#cdcdcd\" p-id=\"3015\"></path></svg>\n              </span>\n            </span>\n            <div slot=\"content\" class=\"content\">\n              <el-form :model=\"Ver\" :rules=\"VerRules\" ref=\"Ver\" class=\"register-form\">\n                <el-form-item>\n                  <el-input v-model=\"this.VPhone\" size=\"large\" placeholder=\"手机号\" disabled auto-complete=\"off\" style=\"width:296px;\"></el-input>\n                </el-form-item>\n                <el-form-item >\n                  <el-col :span=\"14\">\n                    <el-form-item prop=\"verCode\">\n                      <el-input v-model=\"Ver.verCode\" size=\"large\" placeholder=\"验证码\" style=\"width: 130px;\" auto-complete=\"off\"></el-input>\n                    </el-form-item>\n                  </el-col>\n                  <el-col :span=\"10\">\n                    <el-form-item>\n                      <el-button @click=\"sendVer()\" type=\"primary\" size=\"large\" :disabled=\"sendAuthCode ? false : true\"  style=\"width: 125px; height: 50px;\">\n                        <span v-show=\"sendAuthCode\">获取验证码</span>\n                        <span v-show=\"!sendAuthCode\">重新发送({{authTime}})</span>\n                      </el-button>\n                    </el-form-item>\n                  </el-col>\n                </el-form-item>\n              </el-form>\n\n              <div class=\"bootom-btn pa\">\n                <el-button @click=\"verPhoneShow=false\" style=\"width: 140px; height: 40px;\">\n                  取消\n                </el-button>\n                <el-button @click=\"verNext\" type=\"primary\" :disabled=\"vvCode ? false : true\"  style=\"width: 140px; height: 40px;\">\n                  下一步\n                </el-button>\n              </div>\n            </div>\n          </y-shelf>\n        </div>\n\n        <!-- 修改手机号 -->\n        <div class=\"edit-phone\" v-show=\"editPhoneShow\">\n          <y-shelf title=\"修改手机号\">\n            <span slot=\"right\">\n              <span class=\"close\" @click=\"editPhoneShow=false\">\n                <svg t=\"1501234940517\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\"\n                     xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3014\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n                     width=\"20\" height=\"20\"><path\n                  d=\"M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z\"\n                  fill=\"#cdcdcd\" p-id=\"3015\"></path></svg>\n              </span>\n            </span>\n            <div slot=\"content\" class=\"content\">\n              <el-form :model=\"phoneVer\" :rules=\"phoneRules\" ref=\"phoneVer\" class=\"register-form\">\n                <el-form-item prop=\"phone\">\n                  <el-input v-model=\"phoneVer.phone\" size=\"large\" placeholder=\"手机号\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n                </el-form-item>\n                <el-form-item >\n                  <el-col :span=\"14\">\n                    <el-form-item prop=\"verCode\">\n                      <el-input v-model=\"phoneVer.verCode\" size=\"large\" placeholder=\"验证码\" style=\"width: 130px;\" auto-complete=\"off\"></el-input>\n                    </el-form-item>\n                  </el-col>\n                  <el-col :span=\"10\">\n                    <el-form-item>\n                      <el-button @click=\"sendVerCode()\" type=\"primary\" size=\"large\" :disabled=\"verPhone && sendAuth ? false : true\"  style=\"width: 125px; height: 50px;\">\n                        <span v-show=\"sendAuth\">获取验证码</span>\n                        <span v-show=\"!sendAuth\">重新发送({{sendTime}})</span>\n                      </el-button>\n                    </el-form-item>\n                  </el-col>\n                </el-form-item>\n              </el-form>\n\n              <div class=\"bootom-btn pa\">\n                <el-button @click=\"editPhoneShow=false\" style=\"width: 140px; height: 40px;\">\n                  取消\n                </el-button>\n                <el-button @click=\"succPhone({userId:userId, token: token, phone: phoneVer.phone})\" type=\"primary\" :disabled=\"verPhone && codeV ? false : true\"  style=\"width: 140px; height: 40px;\">\n                  确定\n                </el-button>\n              </div>\n            </div>\n          </y-shelf>\n        </div>\n\n        <!-- 修改密码 -->\n        <div class=\"edit-pass\" v-show=\"editPassShow\">\n          <y-shelf title=\"修改密码\">\n            <span slot=\"right\">\n              <span class=\"close\" @click=\"editPassShow=false\">\n                <svg t=\"1501234940517\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\"\n                     xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3014\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n                     width=\"20\" height=\"20\"><path\n                  d=\"M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z\"\n                  fill=\"#cdcdcd\" p-id=\"3015\"></path></svg>\n              </span>\n            </span>\n            <div slot=\"content\" class=\"content\">\n              <el-form :model=\"passVer\" :rules=\"passRules\" ref=\"passVer\" class=\"register-form\">\n                <el-form-item prop=\"oldPass\">\n                  <el-input type=\"password\" v-model=\"passVer.oldPass\" size=\"large\" placeholder=\"旧密码\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n                </el-form-item>\n                <el-form-item prop=\"newPass\">\n                  <el-input type=\"password\" v-model=\"passVer.newPass\" size=\"large\" placeholder=\"新密码\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n                </el-form-item>\n                <el-form-item prop=\"rePass\">\n                  <el-input type=\"password\" v-model=\"passVer.rePass\" size=\"large\" placeholder=\"确认密码\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n                </el-form-item>\n              </el-form>\n\n              <div class=\"bootom-btn pa\">\n                <el-button @click=\"editPassShow=false\" style=\"width: 140px; height: 40px;\">\n                  取消\n                </el-button>\n                <el-button @click=\"updatePass({userId:userId, token: token, password: passVer.newPass})\" type=\"primary\" :disabled=\"vOPass && vNPass && vRPass ? false : true\"  style=\"width: 140px; height: 40px;\">\n                  确定\n                </el-button>\n              </div>\n            </div>\n          </y-shelf>\n        </div>\n\n        <!-- 邮箱验证 -->\n        <div class=\"edit-phone\" v-show=\"verEmailOneShow\">\n          <y-shelf title=\"安全验证\">\n            <span slot=\"right\">\n              <span class=\"close\" @click=\"verEmailOneShow=false\">\n                <svg t=\"1501234940517\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\"\n                     xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3014\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n                     width=\"20\" height=\"20\"><path\n                  d=\"M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z\"\n                  fill=\"#cdcdcd\" p-id=\"3015\"></path></svg>\n              </span>\n            </span>\n            <div slot=\"content\" class=\"content\">\n              <el-form :model=\"VerEmailOne\" :rules=\"VerEmailOneRules\" ref=\"VerEmail\" class=\"register-form\">\n                <el-form-item>\n                  <el-input v-model=\"VerEmailOne.email\" size=\"large\" placeholder=\"邮箱\" disabled auto-complete=\"off\" style=\"width:296px;\"></el-input>\n                </el-form-item>\n                <el-form-item >\n                  <el-col :span=\"14\">\n                    <el-form-item prop=\"verCode\">\n                      <el-input v-model=\"VerEmailOne.verCode\" size=\"large\" placeholder=\"验证码\" style=\"width: 130px;\" auto-complete=\"off\"></el-input>\n                    </el-form-item>\n                  </el-col>\n                  <el-col :span=\"10\">\n                    <el-form-item>\n                      <el-button @click=\"sendEmailOne()\" type=\"primary\" size=\"large\" :disabled=\"sendEmailAuthCodeOne ? false : true\"  style=\"width: 125px; height: 50px;\">\n                        <span v-show=\"sendEmailAuthCodeOne\">获取验证码</span>\n                        <span v-show=\"!sendEmailAuthCodeOne\">重新发送({{authEmailOneTime}})</span>\n                      </el-button>\n                    </el-form-item>\n                  </el-col>\n                </el-form-item>\n              </el-form>\n\n              <div class=\"bootom-btn pa\">\n                <el-button @click=\"verEmailOneShow=false\" style=\"width: 140px; height: 40px;\">\n                  取消\n                </el-button>\n                <el-button @click=\"verEmailNext\" type=\"primary\" :disabled=\"vEmailOne ? false : true\"  style=\"width: 140px; height: 40px;\">\n                  下一步\n                </el-button>\n              </div>\n            </div>\n          </y-shelf>\n        </div>\n\n        <!-- 更新邮箱 -->\n        <div class=\"edit-phone\" v-show=\"verEmailTwoShow\">\n          <y-shelf title=\"安全验证\">\n            <span slot=\"right\">\n              <span class=\"close\" @click=\"verEmailTwoShow=false\">\n                <svg t=\"1501234940517\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\"\n                     xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3014\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n                     width=\"20\" height=\"20\"><path\n                  d=\"M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z\"\n                  fill=\"#cdcdcd\" p-id=\"3015\"></path></svg>\n              </span>\n            </span>\n            <div slot=\"content\" class=\"content\">\n              <el-form :model=\"VerEmailTwo\" :rules=\"VerEmailTwoRules\" ref=\"VerEmailTwo\" class=\"register-form\">\n                <el-form-item prop=\"email\">\n                  <el-input v-model=\"VerEmailTwo.email\" size=\"large\" placeholder=\"邮箱\" auto-complete=\"off\" style=\"width:296px;\"></el-input>\n                </el-form-item>\n                <el-form-item >\n                  <el-col :span=\"14\">\n                    <el-form-item prop=\"verCode\">\n                      <el-input v-model=\"VerEmailTwo.verCode\" size=\"large\" placeholder=\"验证码\" style=\"width: 130px;\" auto-complete=\"off\"></el-input>\n                    </el-form-item>\n                  </el-col>\n                  <el-col :span=\"10\">\n                    <el-form-item>\n                      <el-button @click=\"sendEmailTwo()\" type=\"primary\" size=\"large\" :disabled=\"verEmailTwoEmail & sendEmailAuthCodeTwo ? false : true\"  style=\"width: 125px; height: 50px;\">\n                        <span v-show=\"sendEmailAuthCodeTwo\">获取验证码</span>\n                        <span v-show=\"!sendEmailAuthCodeTwo\">重新发送({{authEmailTwoTime}})</span>\n                      </el-button>\n                    </el-form-item>\n                  </el-col>\n                </el-form-item>\n              </el-form>\n\n              <div class=\"bootom-btn pa\">\n                <el-button @click=\"verEmailTwoShow=false\" style=\"width: 140px; height: 40px;\">\n                  取消\n                </el-button>\n                <el-button @click=\"_updateEmail({userId:userId, token: token, email: VerEmailTwo.email})\" type=\"primary\" :disabled=\"verEmailTwoEmail & verEmailTwoCode ? false : true\"  style=\"width: 140px; height: 40px;\">\n                  确认\n                </el-button>\n              </div>\n            </div>\n          </y-shelf>\n        </div>\n\n        <!-- 上传头像 -->\n        <div class=\"edit-avatar\" v-if=\"editAvatarShow\">\n          <y-shelf title=\"设置头像\">\n            <span slot=\"right\">\n              <span class=\"close\" @click=\"editAvatarShow=false\">\n                <svg t=\"1501234940517\" class=\"icon\" style=\"\" viewBox=\"0 0 1024 1024\" version=\"1.1\"\n                     xmlns=\"http://www.w3.org/2000/svg\" p-id=\"3014\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n                     width=\"20\" height=\"20\"><path\n                  d=\"M941.576 184.248l-101.824-101.824L512 410.176 184.248 82.424 82.424 184.248 410.168 512l-327.744 327.752 101.824 101.824L512 613.824l327.752 327.752 101.824-101.824L613.832 512z\"\n                  fill=\"#cdcdcd\" p-id=\"3015\"></path></svg>\n              </span>\n            </span>\n            <div slot=\"content\" class=\"content\">\n              <div class=\"edit-l\">\n                <div style=\"width: 100px;height: 100px;border: 1px solid #ccc;margin-bottom: 20px;overflow: hidden;\">\n                  <div class=\"show-preview\"\n                       :style=\"{'width': previews.w + 'px','height': previews.h + 'px','overflow': 'hidden','zoom':option.zoom}\">\n                    <div :style=\"previews.div\">\n                      <img :src=\"option.img\"\n                           :style=\"previews.img\">\n                    </div>\n                  </div>\n                </div>\n                <div style=\"padding: 10px 0 \">头像预览</div>\n                <div class=\"btn\">\n                  <a href=\"javascript:;\">重新选择</a>\n                  <input type=\"file\" value=\"上传头像\" @change=\"upimg($event)\">\n                </div>\n              </div>\n              <div class=\"edit-r\">\n                <div>\n                  <div class=\"big\" id=\"cropper-target\" v-if=\"option.img\">\n                    <vueCropper\n                      :img=\"option.img\"\n                      @realTime=\"realTime\"\n                      ref=\"cropper\"\n                      :outputSize=\"example2.size\"\n                      :info=\"example2.info\"\n                      :canScale=\"example2.canScale\"\n                      :autoCrop=\"example2.autoCrop\"\n                      :autoCropWidth=\"example2.width\"\n                      :autoCropHeight=\"example2.height\"\n                      :fixed=\"example2.fixed\"\n                    ></vueCropper>\n                  </div>\n                </div>\n\n              </div>\n              <div class=\"bootom-btn pa\">\n                <y-button style=\"width: 140px;height: 40px;line-height: 40px\"\n                          text=\"取消\"\n                          @btnClick=\"editAvatarShow=false\">\n                </y-button>\n                <y-button style=\"width: 140px;height: 40px;line-height: 40px\"\n                          text=\"确定\"\n                          classStyle=\"main-btn\"\n                          @btnClick=\"cropper\">\n                </y-button>\n              </div>\n            </div>\n          </y-shelf>\n        </div>\n      </div>\n    </y-shelf>\n  </div>\n</template>\n<script>\n  import YButton from '/components/YButton'\n  import YPopup from '/components/popup'\n  import { uploadImg, updateUsername, updatePhone, updatePass, logout, sendEmailCode, updateEmail } from '/api/member'\n  import YShelf from '/components/shelf'\n  import vueCropper from 'vue-cropper'\n  import { mapState, mapMutations } from 'vuex'\n  import { getStore, removeStore } from '/utils/storage'\n  import { checkPhone, checkEmail, vercode } from '/api/index'\n  import md5 from 'js-md5'\n  export default {\n    data () {\n      // 验证昵称\n      let vNick = (rule, value, callback) => {\n        if (!value) {\n          this.verNick = false\n          return callback(new Error('昵称不能为空'))\n        }\n        this.verNick = true\n        return callback()\n      }\n      // 验证手机号\n      let vPhone = async (rule, value, callback) => {\n        const phoneReg = /^1[3|4|5|7|8][0-9]\\d{8}$/\n        if (!value) {\n          this.verPhone = false\n          return callback(new Error('请输入手机号'))\n        }\n        if (!phoneReg.test(value)) {\n          this.verPhone = false\n          return callback(new Error('请输入正确的手机号'))\n        }\n        await checkPhone({\n          value\n        }).then(res => {\n          if (res.result === true) {\n            this.verPhone = false\n            this.existPhone = true\n          } else {\n            this.verPhone = true\n            this.existPhone = false\n          }\n        })\n        if (this.existPhone) {\n          return callback(new Error('此手机号已注册'))\n        }\n        this.$refs.phoneVer.validateField('verCode')\n        return callback()\n      }\n      // 验证第二次验证码\n      let vVerCode = (rule, value, callback) => {\n        let phone = this.phoneVer.phone\n        if (value !== this.code) {\n          this.codeV = false\n          return callback(new Error('验证码错误'))\n        } else if (phone !== this.codePhone) {\n          this.codeV = false\n          return callback(new Error('验证码错误'))\n        }\n        this.codeV = true\n        return callback()\n      }\n      // 验证第一次验证码\n      let vCode = (rule, value, callback) => {\n        if (value !== this.verCode) {\n          this.vvCode = false\n          return callback(new Error('验证码错误'))\n        }\n        this.vvCode = true\n        return callback()\n      }\n      // 验证旧密码\n      let vOldPass = (rule, value, callback) => {\n        value = md5(value)\n        if (value !== this.userInfo.info.password) {\n          this.vOPass = false\n          return callback(new Error('旧密码错误'))\n        }\n        this.vOPass = true\n        return callback()\n      }\n      // 验证新密码\n      let vNewPass = (rule, value, callback) => {\n        const passReg = /^(?![0-9]+$)(?![a-zjnnnpA-Z]+$)[0-9A-Za-z]{6,16}$/\n        if (!value) {\n          this.vNPass = false\n          return callback(new Error('请输入密码'))\n        } else if (!passReg.test(value)) {\n          this.vNPass = false\n          return callback(new Error('密码长度 6-16 位，数字字母至少包含两种'))\n        } else {\n          this.$refs.passVer.validateField('rePass')\n        }\n        this.vNPass = true\n        return callback()\n      }\n      // 验证确认密码\n      let vRePass = (rule, value, callback) => {\n        if (!value) {\n          this.vRPass = false\n          return callback(new Error('请再次输入密码'))\n        } else if (value !== this.passVer.newPass) {\n          this.vRPass = false\n          return callback(new Error('两次输入密码不一致!'))\n        }\n        this.vRPass = true\n        return callback()\n      }\n      // 第一次安全验证邮箱\n      let vEmailOneCode = (rule, value, callback) => {\n        if (!value) {\n          this.vEmailOne = false\n          return callback(new Error('请输入验证码'))\n        } else if (value !== this.verEmailOneCode) {\n          this.vEmailOne = false\n          return callback(new Error('验证码错误'))\n        }\n        this.vEmailOne = true\n        return callback()\n      }\n      // 更改邮箱邮箱验证邮箱是否存在\n      let vEmailTwoEmail = async (rule, value, callback) => {\n        const emailReg = /^(\\w-*\\.*)+@(\\w-?)+(\\.\\w{2,})+$/\n        if (!value) {\n          this.verEmailTwoEmail = false\n          return callback(new Error('请输入邮箱'))\n        }\n        if (!emailReg.test(value)) {\n          this.verEmailTwoEmail = false\n          return callback(new Error('请输入正确的邮箱'))\n        }\n        let params = {\n          params: {\n            email: value\n          }\n        }\n        await checkEmail(params).then(res => {\n          if (res.result === true) {\n            this.verEmailTwoEmail = false\n            this.existEmail = true\n          } else {\n            this.verEmailTwoEmail = true\n            this.existEmail = false\n          }\n        })\n        if (this.existEmail) {\n          return callback(new Error('此邮箱已注册'))\n        }\n        this.$refs.VerEmailTwo.validateField('verCode')\n        return callback()\n      }\n      // 更改邮箱验证验证码\n      let vEmailTwoCode = (rule, value, callback) => {\n        let email = this.VerEmailTwo.email\n        if (value !== this.twoCode) {\n          this.verEmailTwoCode = false\n          return callback(new Error('验证码错误'))\n        } else if (email !== this.codeEmail) {\n          this.verEmailTwoCode = false\n          return callback(new Error('验证码错误'))\n        }\n        this.verEmailTwoCode = true\n        return callback()\n      }\n      return {\n        editAvatarShow: false,\n        imgSrc: '',\n        cropContext: '',\n        cropperImg: '',\n        previews: {},\n        option: {\n          img: '',\n          zoom: 0\n        },\n        example2: {\n          info: true,\n          size: 1,\n          canScale: false,\n          autoCrop: true,\n          // 只有自动截图开启 宽度高度才生效\n          autoCropWidth: 300,\n          autoCropHeight: 250,\n          // 开启宽度和高度比例\n          fixed: true\n        },\n        userId: '',\n        token: '',\n        username: '',\n        phone: '',\n        email: '',\n        userTxt: '',\n        phoneTxt: '',\n        emailTxt: '',\n        userOperate: '',\n        phoneOperate: '',\n        emailOperate: '',\n        editNickShow: false,\n        nickVer: {\n          nick: ''\n        },\n        nickVerRules: {\n          nick: [\n            {validator: vNick, trigger: 'change, blur'}\n          ]\n        },\n        popupOpen2: false,\n        popupTitle2: '',\n        sendAuthCode: true,\n        authTime: 60,\n        verVerCode: false,\n        popupOpen3: false,\n        popupTitle3: '',\n        sendAuthCode1: false,\n        authTime1: 60,\n        verPhoneShow: false,\n        VPhone: '',\n        Ver: {\n          verCode: ''\n        },\n        VerRules: {\n          verCode: [\n            {validator: vCode, trigger: 'change, blur'}\n          ]\n        },\n        verNick: false,\n        vvCode: false,\n        editPhoneShow: false,\n        phoneVer: {\n          phone: '',\n          verCode: ''\n        },\n        phoneRules: {\n          phone: [\n            {validator: vPhone, trigger: 'change,blur'}\n          ],\n          verCode: [\n            {validator: vVerCode, trigger: 'change, blur'}\n          ]\n        },\n        verPhone: false,\n        sendAuth: true,\n        sendTime: 60,\n        codeV: false,\n        code: '',\n        codePhone: '',\n        authTimetimer: '',\n        authTimer: '',\n        editPassShow: false,\n        passVer: {\n          oldPass: '',\n          newPass: '',\n          rePass: ''\n        },\n        passRules: {\n          oldPass: [\n            {validator: vOldPass, trigger: 'blur'}\n          ],\n          newPass: [\n            {validator: vNewPass, trigger: 'change,blur'}\n          ],\n          rePass: [\n            {validator: vRePass, trigger: 'change,blur'}\n          ]\n        },\n        vOPass: false,\n        vNPass: false,\n        vRPass: false,\n        verEmailOneShow: false,\n        VerEmailOne: {\n          email: '',\n          verCode: ''\n        },\n        VerEmailOneRules: {\n          verCode: [\n            {validator: vEmailOneCode, trigger: 'change,blur'}\n          ]\n        },\n        sendEmailAuthCodeOne: true,\n        authEmailOneTimer: '',\n        authEmailOneTime: 60,\n        verEmailOneCode: '',\n        vEmailOne: false,\n        verEmailTwoShow: false,\n        VerEmailTwo: {\n          email: '',\n          verCode: ''\n        },\n        VerEmailTwoRules: {\n          email: [\n            {validator: vEmailTwoEmail, trigger: 'change,blur'}\n          ],\n          verCode: [\n            {validator: vEmailTwoCode, trigger: 'change,blur'}\n          ]\n        },\n        sendEmailAuthCodeTwo: true,\n        authEmailTwoTimer: '',\n        authEmailTwoTime: 60,\n        verEmailTwoCode: false,\n        verEmailTwoEmail: false,\n        vVerCode: '',\n        twoCode: '',\n        existEmail: false,\n        codeEmail: ''\n      }\n    },\n    computed: {\n      ...mapState(['userInfo'])\n    },\n    methods: {\n      ...mapMutations([\n        'RECORD_USERINFO'\n      ]),\n      message (m) {\n        this.$message(m)\n      },\n      messageSuccess (m) {\n        this.$message({\n          message: m,\n          type: 'success'\n        })\n      },\n      messageFail (m) {\n        this.$message.error({\n          message: m\n        })\n      },\n      upimg (e) {\n        let file = e.target.files[0]\n        if (file.size > 1048576) {\n          this.messageFail('图片大小不得超过1Mb')\n          return false\n        }\n        if (!/\\.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {\n          this.messageFail('图片类型仅支持.gif,jpeg,jpg,png,bmp')\n          return false\n        }\n        var reader = new FileReader()\n        reader.readAsDataURL(file)\n        reader.onload = (e) => {\n          this.option.img = e.target.result\n        }\n      },\n      // 上传图片\n      cropper () {\n        this.message('上传中...')\n        if (this.option.img) {\n          this.$refs.cropper.getCropData((data) => {\n            this.imgSrc = data\n            uploadImg({userId: this.userId, token: this.token, imgData: data}).then(res => {\n              if (res.status === 200) {\n                let path = res.result\n                let info = this.userInfo\n                info.file = path\n                this.RECORD_USERINFO({info: info})\n                this.editAvatarShow = false\n                this.messageSuccess('上传头像成功')\n              } else {\n                this.messageFail(res.message)\n              }\n            })\n          })\n        } else {\n          this.messageFail('请先选择头像')\n        }\n      },\n      // 编辑头像\n      editAvatar () {\n        this.editAvatarShow = true\n      },\n      realTime (data) {\n        this.previews = data\n        let w = 100 / data.w\n        this.option.zoom = w\n      },\n      // 设置用户信息\n      setUserInfo () {\n        let username = this.userInfo.info.username\n        let phone = this.userInfo.info.phone\n        let email = this.userInfo.info.email\n        this.username = username\n        this.phone = phone\n        this.email = email\n        if (username === null || username === '') {\n          this.userTxt = '未设置。'\n          this.userOperate = '现在设置'\n        } else {\n          this.userTxt = username\n          this.userOperate = '修改'\n        }\n        if (phone === null || phone === '') {\n          this.phoneTxt = '未设置。'\n          this.phoneOperate = '现在绑定'\n        } else {\n          let phoneTxt = '您验证的手机：' + phone.substring(0, 3).concat('****').concat(phone.substring(7, 11))\n          this.phoneTxt = phoneTxt\n          this.phoneOperate = '修改'\n        }\n        if (email === null || email === '') {\n          this.emailTxt = '未设置。'\n          this.emailOperate = '现在绑定'\n        } else {\n          this.emailTxt = email\n          this.emailOperate = '修改'\n        }\n      },\n      // 修改用户名\n      updateUsername () {\n        this.$refs['nickVer'].resetFields()\n        let username = this.username\n        this.nickVer.nick = username\n        this.editNickShow = true\n      },\n      // 保存用户名\n      saveUsername (params) {\n        this.editNickShow = false\n        updateUsername(params).then(res => {\n          if (res.status === 200) {\n            let username = res.result.username\n            this.RECORD_USERINFO({info: res.result})\n            this.userTxt = username\n            this.username = username\n            this.messageSuccess('修改昵称成功')\n          } else {\n            this.messageFail(res.message)\n          }\n        })\n      },\n      // 发送验证码\n      sendVerCode () {\n        let phone = this.phoneVer.phone\n        this.sendAuth = false\n        this.authTimer = setInterval(() => {\n          this.sendTime--\n          if (this.sendTime <= 0) {\n            this.sendAuth = true\n            clearInterval(this.authTimer)\n          }\n        }, 1000)\n        vercode({\n          phone\n        }).then(res => {\n          this.code = res.result\n          this.codePhone = phone\n        })\n      },\n      // 发送第一次验证手机号\n      sendCode () {\n        let phone = this.phone\n        this.sendAuthCode = false\n        this.authTimetimer = setInterval(() => {\n          this.authTime--\n          if (this.authTime <= 0) {\n            this.sendAuthCode = true\n            clearInterval(this.authTimetimer)\n          }\n        }, 1000)\n        vercode({\n          phone\n        }).then(res => {\n          console.log(res.result)\n          this.verCode = res.result\n        })\n      },\n      // 修改手机号\n      updatePhone () {\n        this.$refs['Ver'].resetFields()\n        let phone = this.phone.substring(0, 3).concat('****').concat(this.phone.substring(7, 11))\n        this.vvCode = false\n        this.authTime = 60\n        this.VPhone = phone\n        this.Ver.verCode = ''\n        this.verPhoneShow = true\n        this.sendCode()\n      },\n      // 安全验证通过，下一步\n      verNext () {\n        this.$refs['phoneVer'].resetFields()\n        this.vvCode = false\n        this.Ver.verCode = ''\n        this.authTime = 60\n        this.verPhoneShow = false\n        this.editPhoneShow = true\n        clearInterval(this.authTimetimer)\n      },\n      // 向服务器发起修改手机号请求\n      succPhone (params) {\n        updatePhone(params).then(res => {\n          if (res.status === 200) {\n            let phone = res.result.phone\n            this.RECORD_USERINFO({info: res.result})\n            this.phoneVer.phone = ''\n            this.phoneVer.verCode = ''\n            this.sendAuth = true\n            this.phone = phone\n            this.phoneTxt = '您验证的手机：' + phone.substring(0, 3).concat('****').concat(phone.substring(7, 11))\n            this.editPhoneShow = false\n            clearInterval(this.authTimer)\n            this.messageSuccess('修改手机号成功')\n          } else {\n            this.editPhoneShow = false\n            this.messageFail(res.message)\n          }\n        })\n        this.sendTime = 60\n      },\n      // 打开修改密码\n      openPass () {\n        this.$refs['passVer'].resetFields()\n        this.editPassShow = false\n        this.passVer.oldPass = ''\n        this.passVer.newPass = ''\n        this.passVer.rePass = ''\n        this.vOPass = false\n        this.vNPass = false\n        this.vRPass = false\n        this.editPassShow = true\n      },\n      // 修改密码\n      updatePass (params) {\n        updatePass(params).then(res => {\n          this.editPassShow = false\n          this.passVer.oldPass = ''\n          this.passVer.newPass = ''\n          this.passVer.rePass = ''\n          this.vOPass = false\n          this.vNPass = false\n          this.vRPass = false\n          if (res.status === 200) {\n            this.RECORD_USERINFO({info: res.result})\n            this.messageSuccess('修改密码成功')\n            let params = {\n              params: {\n                token: this.token\n              }\n            }\n            logout(params).then(res => {\n              removeStore('token')\n              removeStore('userId')\n              removeStore('userInfo')\n              removeStore('buyCart')\n              window.location.href = '/login'\n            })\n          } else {\n            this.editPassShow = false\n            this.messageFail(res.message)\n          }\n        })\n      },\n      // 打开修改邮箱\n      openEmail () {\n        this.$refs['VerEmailTwo'].resetFields()\n        let email = this.userInfo.info.email\n        if (email === null || email === '') {\n          this.verEmailTwoShow = true\n          this.VerEmailTwo.email = this.userInfo.info.email\n          this.VerEmailTwo.verCode = ''\n          this.authEmailTwoTimer = ''\n          this.authEmailTwoTime = 60\n          this.verEmailTwoCode = ''\n          this.vEmailTwo = false\n          clearInterval(this.authEmailTwoTimer)\n        } else {\n          this.verEmailOneShow = true\n          this.VerEmailOne.email = this.userInfo.info.email\n          this.VerEmailOne.verCode = ''\n          this.authEmailOneTimer = ''\n          this.authEmailOneTime = 60\n          this.verEmailOneCode = ''\n          this.vEmailOne = false\n          clearInterval(this.authEmailOneTimer)\n          this.sendEmailOne()\n        }\n      },\n      // 发送第一次安全验证邮件\n      sendEmailOne () {\n        let email = this.VerEmailOne.email\n        this.sendEmailAuthCodeOne = false\n        this.authEmailOneTime = 60\n        this.authEmailOneTimer = setInterval(() => {\n          this.authEmailOneTime--\n          if (this.authEmailOneTime <= 0) {\n            this.sendEmailAuthCodeOne = true\n            clearInterval(this.authEmailOneTimer)\n            this.authTime = 60\n          }\n        }, 1000)\n        let params = {\n          params: {\n            email: email\n          }\n        }\n        sendEmailCode(params).then(res => {\n          this.verEmailOneCode = res.result\n        })\n      },\n      // 邮箱安全验证通过，下一步\n      verEmailNext () {\n        this.$refs['VerEmailTwo'].resetFields()\n        this.verEmailOneShow = false\n        this.verEmailTwoShow = true\n      },\n      // 更换邮箱第二次验证\n      sendEmailTwo () {\n        let email = this.VerEmailTwo.email\n        this.sendEmailAuthCodeTwo = false\n        this.authEmailTwoTime = 60\n        this.authEmailTwoTimer = setInterval(() => {\n          this.authEmailTwoTime--\n          if (this.authEmailTwoTime <= 0) {\n            this.sendEmailAuthCodeTwo = true\n            clearInterval(this.authEmailTwoTimer)\n            this.authEmailTwoTime = 60\n          }\n        }, 1000)\n        let params = {\n          params: {\n            email: email\n          }\n        }\n        sendEmailCode(params).then(res => {\n          this.twoCode = res.result\n          this.codeEmail = email\n        })\n      },\n      // 更换邮箱\n      _updateEmail (params) {\n        updateEmail(params).then(res => {\n          this.verEmailTwoShow = false\n          this.VerEmailTwo.email = ''\n          this.VerEmailTwo.verCode = ''\n          this.sendEmailAuthCodeTwo = false\n          this.authEmailTwoTimer = ''\n          this.authEmailTwoTime = 60\n          this.verEmailTwoCode = false\n          this.verEmailTwoEmail = false\n          this.vVerCode = ''\n          this.twoCode = ''\n          this.existEmail = false\n          this.codeEmail = ''\n          if (res.status === 200) {\n            this.RECORD_USERINFO({info: res.result})\n            this.emailTxt = res.result.email\n            this.messageSuccess('修改邮箱成功')\n          } else {\n            this.messageFail(res.message)\n          }\n        })\n      }\n    },\n    created () {\n      this.userId = getStore('userId')\n      this.token = getStore('token')\n      this.setUserInfo()\n    },\n    components: {\n      YButton,\n      YShelf,\n      vueCropper,\n      YPopup\n    }\n  }\n</script>\n<style lang=\"scss\">\n  @import \"../../../assets/style/mixin\";\n\n  .avatar-box {\n    height: 124px;\n    display: flex;\n    margin: 0 30px 30px;\n    border-bottom: #dadada solid 1px;\n    line-height: 30px;\n    display: flex;\n    align-items: center;\n    .img-box {\n      @include wh(80px);\n      border-radius: 5px;\n      overflow: hidden;\n    }\n    img {\n      display: block;\n      @include wh(100%)\n    }\n    .r-box {\n      margin-left: 20px;\n      h3 {\n        font-size: 18px;\n        font-weight: 400;\n        color: #333;\n      }\n    }\n  }\n\n  .safe-center-title {\n    font-size: 18px;\n    font-weight: 400;\n    color: #333;\n  }\n\n  .status-box {\n    position: relative;\n    height: 60px;\n    padding-bottom: 30px;\n    margin: 0 30px 30px;\n    line-height: 30px;\n  }\n\n  .status-box p {\n    clear: both;\n    width: 420px;\n    color: #999;\n    float: left;\n  }\n\n  .safe-todo {\n    position: relative;\n    left: 348px;\n    margin-top: -30px;\n    text-align: right;\n  }\n\n  .md {\n    > div {\n      text-align: left;\n      margin-bottom: 15px;\n      > input {\n        width: 100%;\n        height: 50px;\n        font-size: 18px;\n        padding: 10px 20px;\n        border: 1px solid #ccc;\n        border-radius: 6px;\n        box-shadow: 0 3px 5px -4px rgba(0, 0, 0, .4) inset, -1px 0 3px -2px rgba(0, 0, 0, .1) inset;\n        line-height: 46px;\n      }\n    }\n  }\n\n  .btn {\n    margin: 0;\n    width: 100%;\n    height: 50px;\n    font-size: 14px;\n    line-height: 48px\n  }\n\n  // 修改头像\n  .edit-avatar {\n    z-index: 9999;\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    @include wh(100%);\n    background-color: rgba(0, 0, 0, .5);\n    @extend %block-center;\n    .content {\n      display: flex;\n      padding: 45px 100px 0;\n    }\n    > div {\n      box-sizing: content-box;\n      @include wh(700px, 500px);\n      margin: 0;\n    }\n    .btn {\n      width: 80px;\n      height: 30px;\n      margin-left: 10px;\n      position: relative;\n      text-align: center;\n      line-height: 30px;\n      text-shadow: rgba(255, 255, 255, .496094) 0 1px 0;\n      border: 1px solid #E6E6E6;\n      border-radius: 10px;\n      &:hover {\n      }\n      a {\n        color: #666;\n        display: block;\n        @include wh(100%);\n      }\n    }\n    input[type=file] {\n      position: absolute;\n      right: 0;\n      left: 0;\n      top: 0;\n      opacity: 0;\n      width: 80px;\n      height: 30px;\n      cursor: pointer;\n      box-sizing: border-box;\n      border: 15px solid #000;\n      overflow: hidden;\n    }\n    .edit-l {\n      width: 100px;\n      text-align: center;\n    }\n    .edit-r {\n      margin-left: 20px;\n      flex: 1;\n      > div {\n        border: 1px solid #ccc;\n        width: 320px;\n        height: 320px;\n      }\n    }\n  }\n\n  // 修改昵称\n  .edit-nick {\n    z-index: 9999;\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    @include wh(100%);\n    background-color: rgba(0, 0, 0, .5);\n    @extend %block-center;\n    .content {\n      display: flex;\n      padding: 45px 100px 0;\n    }\n    > div {\n      box-sizing: content-box;\n      @include wh(500px, 262px);\n      margin: 0;\n    }\n    .btn {\n      width: 80px;\n      height: 30px;\n      margin-left: 10px;\n      position: relative;\n      text-align: center;\n      line-height: 30px;\n      text-shadow: rgba(255, 255, 255, .496094) 0 1px 0;\n      border: 1px solid #E6E6E6;\n      border-radius: 10px;\n      &:hover {\n      }\n      a {\n        color: #666;\n        display: block;\n        @include wh(100%);\n      }\n    }\n    input[type=file] {\n      position: absolute;\n      right: 0;\n      left: 0;\n      top: 0;\n      opacity: 0;\n      width: 80px;\n      height: 30px;\n      cursor: pointer;\n      box-sizing: border-box;\n      border: 15px solid #000;\n      overflow: hidden;\n    }\n    .edit-l {\n      width: 100px;\n      text-align: center;\n    }\n    .edit-r {\n      margin-left: 20px;\n      flex: 1;\n      > div {\n        border: 1px solid #ccc;\n        width: 320px;\n        height: 320px;\n      }\n    }\n  }\n\n  // 修改手机号\n  .edit-phone {\n    z-index: 9999;\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    @include wh(100%);\n    background-color: rgba(0, 0, 0, .5);\n    @extend %block-center;\n    .content {\n      display: flex;\n      padding: 45px 100px 0;\n    }\n    > div {\n      box-sizing: content-box;\n      @include wh(500px, 322px);\n      margin: 0;\n    }\n    .btn {\n      width: 80px;\n      height: 30px;\n      margin-left: 10px;\n      position: relative;\n      text-align: center;\n      line-height: 30px;\n      text-shadow: rgba(255, 255, 255, .496094) 0 1px 0;\n      border: 1px solid #E6E6E6;\n      border-radius: 10px;\n      &:hover {\n      }\n      a {\n        color: #666;\n        display: block;\n        @include wh(100%);\n      }\n    }\n    input[type=file] {\n      position: absolute;\n      right: 0;\n      left: 0;\n      top: 0;\n      opacity: 0;\n      width: 80px;\n      height: 30px;\n      cursor: pointer;\n      box-sizing: border-box;\n      border: 15px solid #000;\n      overflow: hidden;\n    }\n    .edit-l {\n      width: 100px;\n      text-align: center;\n    }\n    .edit-r {\n      margin-left: 20px;\n      flex: 1;\n      > div {\n        border: 1px solid #ccc;\n        width: 320px;\n        height: 320px;\n      }\n    }\n  }\n\n  // 修改密码\n  .edit-pass {\n    z-index: 9999;\n    position: fixed;\n    left: 0;\n    right: 0;\n    top: 0;\n    bottom: 0;\n    @include wh(100%);\n    background-color: rgba(0, 0, 0, .5);\n    @extend %block-center;\n    .content {\n      display: flex;\n      padding: 45px 100px 0;\n    }\n    > div {\n      box-sizing: content-box;\n      @include wh(500px, 400px);\n      margin: 0;\n    }\n    .btn {\n      width: 80px;\n      height: 30px;\n      margin-left: 10px;\n      position: relative;\n      text-align: center;\n      line-height: 30px;\n      text-shadow: rgba(255, 255, 255, .496094) 0 1px 0;\n      border: 1px solid #E6E6E6;\n      border-radius: 10px;\n      &:hover {\n      }\n      a {\n        color: #666;\n        display: block;\n        @include wh(100%);\n      }\n    }\n    input[type=file] {\n      position: absolute;\n      right: 0;\n      left: 0;\n      top: 0;\n      opacity: 0;\n      width: 80px;\n      height: 30px;\n      cursor: pointer;\n      box-sizing: border-box;\n      border: 15px solid #000;\n      overflow: hidden;\n    }\n    .edit-l {\n      width: 100px;\n      text-align: center;\n    }\n    .edit-r {\n      margin-left: 20px;\n      flex: 1;\n      > div {\n        border: 1px solid #ccc;\n        width: 320px;\n        height: 320px;\n      }\n    }\n  }\n\n  .image-container {\n    width: 100px;\n    height: 100px;\n    border: 1px solid #ccc;\n  }\n\n  .close {\n    position: absolute;\n    right: 10px;\n    top: 0;\n    bottom: 0;\n    padding: 0 10px;\n    @extend %block-center;\n    &:hover {\n      svg {\n        transition: all 1s;\n        transform: rotate(360deg);\n        transform-origin: 50% 50%;\n      }\n      path {\n        fill: #8a8a8a;\n      }\n    }\n  }\n\n  .big {\n    display: block;\n    width: 320px;\n    height: 320px;\n  }\n\n  .bootom-btn {\n    padding: 0 15px;\n    border-top: 1px solid #E6E6E6;\n    bottom: 0;\n    height: 60px;\n    right: 0;\n    left: 0;\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n  }\n\n  .register-form .el-input__inner {\n    height: 50px;\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/User/children/order.vue",
    "content": "<template>\n  <div>\n    <y-shelf title=\"我的订单\">\n      <div slot=\"content\">\n        <div v-loading=\"loading\" element-loading-text=\"加载中...\" v-if=\"orderList.length\" style=\"min-height: 10vw;\">\n          <div v-for=\"(item,i) in orderList\" :key=\"i\">\n            <div class=\"gray-sub-title cart-title\">\n              <div class=\"first\">\n                <div>\n                  <span class=\"date\" v-text=\"item.createDate\"></span>\n                  <span class=\"order-id\"> 订单号： <a @click=\"orderDetail(item.orderId)\">{{item.orderId}}</a> </span>\n                </div>\n                <div class=\"f-bc\">\n                  <span class=\"price\">单价</span>\n                  <span class=\"num\">数量</span>\n                  <span class=\"operation\">商品操作</span>\n                </div>\n              </div>\n              <div class=\"last\">\n                <span class=\"sub-total\">实付金额</span>\n                <span class=\"order-detail\"> <a @click=\"orderDetail(item.orderId)\">查看详情 ><em class=\"icon-font\"></em></a> </span>\n              </div>\n            </div>\n            <div class=\"pr\">\n              <div class=\"cart\" v-for=\"(good,j) in item.goodsList\" :key=\"j\">\n                <div class=\"cart-l\" :class=\"{bt:j>0}\">\n                  <div class=\"car-l-l\">\n                    <div class=\"img-box\"><a @click=\"goodsDetails(good.productId)\"><img :src=\"good.productImg\" alt=\"\"></a></div>\n                    <div class=\"ellipsis\"><a style=\"color: #626262;\" @click=\"goodsDetails(good.productId)\">{{good.productName}}</a></div>\n                  </div>\n                  <div class=\"cart-l-r\">\n                    <div>¥ {{Number(good.salePrice).toFixed(2)}}</div>\n                    <div class=\"num\">{{good.productNum}}</div>\n                    <div class=\"type\">\n                      <el-button style=\"margin-left:20px\" @click=\"_delOrder(item.orderId,i,item.orderStatus)\" :disabled=\"item.orderStatus === 2 ? true : false\" type=\"danger\" size=\"small\" v-if=\"j<1\" class=\"del-order\">{{getOperate(item.orderStatus)}}</el-button>\n                    </div>\n                  </div>\n                </div>\n                <div class=\"cart-r\">\n                  <span></span>\n                  <span></span>\n                </div>\n              </div>\n              <div class=\"prod-operation pa\" style=\"right: 0;top: 0;\">\n                <div class=\"total\">¥ {{item.orderTotal}}</div>\n                <div v-if=\"item.orderStatus === '0'\">\n                  <el-button @click=\"orderPayment(item.orderId)\" type=\"primary\" size=\"small\">现在付款</el-button>\n                </div>\n                <div class=\"status\" v-if=\"item.orderStatus !== '0'\"> {{getOrderStatus(item.orderStatus)}}  </div>\n              </div>\n            </div>\n          </div>\n        </div>\n        <div v-loading=\"loading\" element-loading-text=\"加载中...\" class=\"no-info\" v-else>\n          <div style=\"padding: 100px 0;text-align: center\">\n            你还未创建过订单\n          </div>\n        </div>\n      </div>\n    </y-shelf>\n    <div style=\"float:right\">\n      <el-pagination\n        @size-change=\"handleSizeChange\"\n        @current-change=\"handleCurrentChange\"\n        :current-page=\"currentPage\"\n        :page-sizes=\"[5, 10, 20, 50]\"\n        :page-size=\"pageSize\"\n        layout=\"total, sizes, prev, pager, next\"\n        :total=\"total\">\n      </el-pagination>\n    </div>\n  </div>\n</template>\n<script>\n  import YShelf from '/components/shelf'\n  import { getStore } from '/utils/storage'\n  import { getOrderList, confirmReceipt, deleteOrder } from '/api/order'\n\n  export default {\n    data () {\n      return {\n        userId: '',\n        currentPage: 1,\n        pageSize: 5,\n        orderList: '',\n        loading: true,\n        total: 0\n      }\n    },\n    methods: {\n      // 确认删除\n      confirmDelete (orderId) {\n        this.$confirm('您确认删除订单号为' + orderId + '的订单吗？此操作不可恢复', '提示', {\n          confirmButtonText: '确定',\n          cancelButtonText: '取消',\n          type: 'warning'\n        }).then(() => {\n          deleteOrder({orderId: orderId, userId: this.userId}).then(res => {\n            if (res.status === 200) {\n              this._orderList()\n              this.messageSuccess(res.message)\n            } else {\n              this.messageFail(res.message)\n            }\n          })\n        })\n      },\n      // 成功消息提示\n      messageSuccess (m) {\n        this.$message({\n          message: m,\n          type: 'success'\n        })\n      },\n      // 失败消息提示\n      messageFail (m) {\n        this.$message.error({\n          message: m\n        })\n      },\n      // 获取订单列表\n      _orderList () {\n        let params = {\n          params: {\n            userId: this.userId,\n            page: this.currentPage,\n            size: this.pageSize\n          }\n        }\n        getOrderList(params).then(res => {\n          this.orderList = res.result.data\n          this.total = res.result.total\n          this.loading = false\n        })\n      },\n      // 更改分页大小\n      handleSizeChange (val) {\n        this.pageSize = val\n        this._orderList()\n      },\n      // 更改当前页数\n      handleCurrentChange (val) {\n        this.currentPage = val\n        this._orderList()\n      },\n      // 获取订单状态\n      getOrderStatus (status) {\n        if (status === 0) {\n          return '待支付'\n        } else if (status === 1) {\n          return '已付款'\n        } else if (status === 2) {\n          return '待发货'\n        } else if (status === 3) {\n          return '已发货'\n        } else if (status === 4) {\n          return '交易成功'\n        } else if (status === 5) {\n          return '交易失败'\n        } else {\n          return '交易失败'\n        }\n      },\n      // 获取订单操作\n      getOperate (status) {\n        if (status === 0) {\n          return '去支付'\n        } else if (status === 1 || status === 2 || status === 3) {\n          return '确认收货'\n        } else if (status === 4 || status === 5) {\n          return '删除订单'\n        } else {\n          return '交易失败'\n        }\n      },\n      // 操作订单\n      _delOrder (orderId, i, status) {\n        if (status === 0) {\n          this.$router.push({\n            path: '/order/payment',\n            query: {\n              'orderId': orderId\n            }\n          })\n        } else if (status === 1 || status === 2 || status === 3) {\n          console.log('确认收货')\n          confirmReceipt({orderId: orderId, userId: this.userId}).then(res => {\n            if (res.status === 200) {\n              this._orderList()\n              this.messageSuccess(res.message)\n            } else {\n              this.messageFail(res.message)\n            }\n          })\n        } else if (status === 4 || status === 5) {\n          console.log('删除订单')\n          this.confirmDelete(orderId)\n          return '删除订单'\n        } else {\n          return '交易失败'\n        }\n      },\n      // 查看订单详情\n      goodsDetails (productId) {\n        this.$router.push({\n          path: '/goodsDetails',\n          query: {\n            productId: productId\n          }\n        })\n      },\n      // 查看详情\n      orderDetail (orderId) {\n        this.$router.push({\n          path: '/user/orderDetail',\n          query: {\n            orderId: orderId\n          }\n        })\n      }\n    },\n    created () {\n      this.userId = getStore('userId')\n      this._orderList()\n    },\n    components: {\n      YShelf\n    }\n  }\n</script>\n<style lang=\"scss\" scoped>\n  @import \"../../../assets/style/mixin\";\n\n  .gray-sub-title {\n    height: 38px;\n    padding: 0 24px;\n    background: #EEE;\n    border-top: 1px solid #DBDBDB;\n    border-bottom: 1px solid #DBDBDB;\n    line-height: 38px;\n    font-size: 12px;\n    color: #666;\n    display: flex;\n    span {\n      display: inline-block;\n      height: 100%;\n    }\n    .first {\n      display: flex;\n      justify-content: space-between;\n      flex: 1;\n      .f-bc {\n        > span {\n          width: 112px;\n          text-align: center;\n        }\n      }\n    }\n    .last {\n      width: 230px;\n      text-align: center;\n      display: flex;\n      border-left: 1px solid #ccc;\n      span {\n        flex: 1;\n      }\n    }\n  }\n\n  .bt {\n    border-top: 1px solid #EFEFEF;\n  }\n\n  .date {\n    padding-left: 0px;\n  }\n\n  .order-id {\n    margin-left: 25px;\n  }\n\n  .cart {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    padding: 0 24px;\n    &:hover {\n      .del-order {\n        display: block;\n      }\n    }\n    .del-order {\n      display: none;\n    }\n    .cart-l {\n      display: flex;\n      align-items: center;\n      flex: 1;\n      padding: 15px 0;\n      justify-content: space-between;\n      position: relative;\n      &:before {\n        position: absolute;\n        content: ' ';\n        right: -1px;\n        top: 0;\n        width: 1px;\n        background-color: #EFEFEF;\n        height: 100%;\n      }\n      .ellipsis {\n        margin-left: 20px;\n        width: 220px;\n      }\n      .img-box {\n        border: 1px solid #EBEBEB;\n      }\n      img {\n        display: block;\n        @include wh(80px);\n      }\n      .cart-l-r {\n        display: flex;\n        > div {\n          text-align: center;\n          width: 112px;\n        }\n      }\n      .car-l-l {\n        display: flex;\n        align-items: center;\n      }\n    }\n    .cart-r {\n      width: 230px;\n      display: flex;\n      span {\n        text-align: center;\n        flex: 1;\n      }\n    }\n  }\n\n  .prod-operation {\n    height: 110px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 254px;\n    div {\n      width: 100%;\n      text-align: center;\n    }\n    div:last-child {\n      padding-right: 24px;\n    }\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/User/children/orderDetail.vue",
    "content": "<template>\n  <div>\n    <y-shelf v-bind:title=\"orderTitle\">\n      <div slot=\"content\">\n        <div v-loading=\"loading\" element-loading-text=\"加载中...\" style=\"min-height: 10vw;\" v-if=\"orderList.length\">\n          <div class=\"orderStatus\" v-if=\"orderStatus !== 0 && orderStatus !== 5\">\n            <el-steps :space=\"200\" :active=\"orderStatus+1\">\n              <el-step title=\"下单\" v-bind:description=\"createTime\"></el-step>\n              <el-step title=\"付款\" v-bind:description=\"payTime\"></el-step>\n              <el-step title=\"待发货\" v-bind:description=\"noconsignTxt\"></el-step>\n              <el-step title=\"已发货\" v-bind:description=\"consignTime\"></el-step>\n              <el-step title=\"交易成功\" v-bind:description=\"finishTime\"></el-step>\n            </el-steps>\n          </div>\n          <div class=\"orderStatus-close\" v-if=\"orderStatus === 5\">\n            <el-steps :space=\"780\" :active=\"2\">\n              <el-step title=\"下单\" v-bind:description=\"createTime\"></el-step>\n              <el-step title=\"交易关闭\" v-bind:description=\"closeTime\"></el-step>\n            </el-steps>\n          </div>\n          <div class=\"status-now\" v-if=\"orderStatus === 0\" style=\"margin-top: 30px;\">\n            <ul>\n              <li class=\"status-title\"><h3>订单状态：待付款</h3></li>\n              <li class=\"button\">\n                <el-button @click=\"orderPayment(orderId)\" type=\"primary\" size=\"small\">现在付款</el-button>\n                <el-button @click=\"_cancelOrder(orderId)\" size=\"small\">取消订单</el-button>\n              </li>\n            </ul>\n            <p class=\"realtime\">\n              <span>您的付款时间还有 </span>\n              <span class=\"red\"><countDown v-if=\"countTime\" v-bind:endTime=\"countTime\" endText=\"已结束\"></countDown></span>\n              <span>，超时后订单将自动取消。</span>\n            </p>\n          </div>\n          <div class=\"status-now\" v-if=\"orderStatus === 2\">\n            <ul>\n              <li class=\"status-title\"><h3>订单状态：待发货</h3></li>\n            </ul>\n            <p class=\"realtime\">\n              <span>我们将在 72 小时内为您发货</span>\n            </p>\n          </div>\n          <div class=\"status-now\" v-if=\"orderStatus === 5\">\n            <ul>\n              <li class=\"status-title\"><h3>订单状态：已关闭</h3></li>\n            </ul>\n            <p class=\"realtime\">\n              <span>您的订单已关闭。</span>\n            </p>\n          </div>\n          <div class=\"status-now\" v-if=\"orderStatus === 4\">\n            <ul>\n              <li class=\"status-title\"><h3>订单状态：已完成</h3></li>\n            </ul>\n            <p class=\"realtime\">\n              <span>您的订单已交易成功，感谢您的惠顾！</span>\n            </p>\n          </div>\n\n          <div class=\"gray-sub-title cart-title\">\n            <div class=\"first\">\n              <div>\n                <span class=\"order-id\">商品名称</span>\n              </div>\n              <div class=\"f-bc\">\n                <span class=\"price\">单价</span>\n                <span class=\"num\">数量</span>\n                <span class=\"operation\">小计</span>\n              </div>\n            </div>\n          </div>\n          <!-- 订单商品 -->\n          <div class=\"goods-table\">\n            <div class=\"cart-items\" v-for=\"(item,i) in orderList\" :key=\"i\">\n              <a @click=\"goodsDetails(item.productId)\" class=\"img-box\"><img :src=\"item.productImg\" alt=\"\"></a>\n              <div class=\"name-cell ellipsis\">\n                <a @click=\"goodsDetails(item.productId)\" title=\"\" target=\"_blank\">{{item.productName}}</a>\n              </div>\n              <div class=\"n-b\">\n                <div class=\"price\">¥ {{Number(item.salePrice).toFixed(2)}}</div>\n                <div class=\"goods-num\">{{item.productNum}}</div>\n                <div class=\"subtotal\"> ¥ {{Number(item.salePrice * item.productNum).toFixed(2)}}</div>\n              </div>\n            </div>\n          </div>\n          <!-- 合计 -->\n          <div class=\"order-discount-line\">\n            <p style=\"font-size: 14px;font-weight: bolder;\"> <span style=\"padding-right:47px\">商品总计：</span>\n              <span style=\"font-size: 16px;font-weight: 500;line-height: 32px;\">¥ {{Number(orderTotal).toFixed(2)}}</span>\n            </p>\n            <p class=\"price-total\"><span>应付金额：</span><span class=\"price-red\">¥ {{Number(orderTotal).toFixed(2)}}</span></p>\n          </div>\n          <!-- 收货信息 -->\n          <div class=\"gray-sub-title cart-title\">\n            <div class=\"first\">\n              <div>\n                <span class=\"order-id\">收货信息</span>\n              </div>\n            </div>\n          </div>\n          <div style=\"height: 155px;padding: 20px 30px;\">\n            <p class=\"address\">姓名：{{ userName }}</p>\n            <p class=\"address\">联系电话：{{ tel }}</p>\n            <p class=\"address\">详细地址：{{ streetName }}</p>\n          </div>\n\n          <!-- 物流信息 -->\n          <div class=\"gray-sub-title cart-title\" v-if=\"orderStatus === 3 || orderStatus === 4\">\n            <div class=\"first\">\n              <div>\n                <span class=\"order-id\">物流信息</span>\n              </div>\n            </div>\n          </div>\n          <div style=\"height: 155px;padding: 20px 30px;\">\n            <p class=\"address\">物流名称：{{ shippingName }}</p>\n            <p class=\"address\">物流单号：{{ shippingCode }}</p>\n          </div>\n        </div>\n\n        <div v-loading=\"loading\" element-loading-text=\"加载中...\" v-else>\n          <div style=\"padding: 100px 0;text-align: center\">\n            获取该订单信息失败\n          </div>\n        </div>\n      </div>\n    </y-shelf>\n  </div>\n</template>\n<script>\n  import YShelf from '/components/shelf'\n  import { getStore } from '/utils/storage'\n  import { getOrderDet, cancelOrder } from '/api/order'\n  import countDown from '/components/countDown'\n\n  export default {\n    data () {\n      return {\n        userId: '',\n        orderId: '',\n        orderTitle: '',\n        loading: true,\n        orderList: [0],\n        orderStatus: 0,\n        orderTotal: 0,\n        userName: '',\n        tel: '',\n        streetName: '',\n        createTime: '',\n        closeTime: '',\n        payTime: '',\n        finishTime: '',\n        countTime: '',\n        noconsignTxt: '待发货',\n        shippingName: '',\n        shippingCode: ''\n      }\n    },\n    methods: {\n      // 成功消息提示\n      messageSuccess (m) {\n        this.$message({\n          message: m,\n          type: 'success'\n        })\n      },\n      // 失败消息提示\n      messageFail (m) {\n        this.$message.error({\n          message: m\n        })\n      },\n      // 确认删除\n      confirmCancel (orderId) {\n        this.$confirm('您确认取消订单号为' + orderId + '的订单吗？此操作不可恢复', '提示', {\n          confirmButtonText: '确定',\n          cancelButtonText: '取消',\n          type: 'warning'\n        }).then(() => {\n          cancelOrder({userId: this.userId, orderId: orderId}).then(res => {\n            if (res.status === 200) {\n              this._getOrderDet()\n            } else {\n              this.messageFail(res.message)\n            }\n          })\n        })\n      },\n      // 获取订单详情\n      _getOrderDet () {\n        let params = {\n          params: {\n            orderId: this.orderId\n          }\n        }\n        getOrderDet(params).then(res => {\n          this.orderStatus = res.result.orderStatus\n          this.orderList = res.result.goodsList\n          this.orderTotal = res.result.orderTotal\n          this.userName = res.result.tbAddress.userName\n          this.tel = res.result.tbAddress.tel\n          this.streetName = res.result.tbAddress.streetName\n          this.createTime = res.result.createDate\n          this.consignTime = res.result.consignDate\n          this.closeTime = res.result.closeDate\n          this.payTime = res.result.payDate\n          this.finishTime = res.result.finishDate\n          this.countTime = res.result.countTime\n          this.shippingName = res.result.shippingName\n          this.shippingCode = res.result.shippingCode\n          if (this.consignTime !== null) {\n            this.noconsignTxt = '订单已发货'\n          } else {\n            this.noconsignTxt = '订单未发货'\n          }\n          this.loading = false\n        })\n      },\n      // 去付款\n      orderPayment (orderId) {\n        window.open(window.location.origin + '/order/payment?orderId=' + orderId)\n      },\n      // 取消订单\n      _cancelOrder (orderId) {\n        this.confirmCancel(orderId)\n      },\n      // 商品详情\n      goodsDetails (productId) {\n        window.open(window.location.origin + '/goodsDetails?productId=' + productId)\n      }\n    },\n    created () {\n      this.userId = getStore('userId')\n      this.orderId = this.$route.query.orderId\n      this.orderTitle = '订单号：' + this.orderId\n      this._getOrderDet()\n    },\n    components: {\n      YShelf,\n      countDown\n    }\n  }\n</script>\n<style lang=\"scss\" scoped>\n  @import \"../../../assets/style/mixin\";\n\n  .orderStatus {\n    display: flex;\n    align-items: center;\n    flex-direction: row;\n    margin: 50px -150px 20px 60px;\n  }\n\n  .orderStatus-close {\n    display: flex;\n    align-items: center;\n    flex-direction: row;\n    margin: 50px -800px 20px 60px;\n  }\n\n  .status-now {\n    background: #F6F6F6;\n    border: 1px solid #dadada;\n    border-radius: 5px;\n    padding: 22px 30px 20px;\n    margin: 0 30px 30px 30px;\n    line-height: 38px;\n  }\n\n  .status-title {\n    font-size: 18px;\n    color: #666;\n  }\n\n  .button {\n    float: right;\n    margin: -37px 0 20px 0;\n  }\n\n  .realtime {\n    border-top: 1px solid #dcdcdc;\n    margin-top: 20px;\n    padding-top: 26px;\n  }\n\n  .red {\n    color: #d44d44;\n  }\n\n  .address {\n    line-height: 38px;\n    word-wrap: break-word;\n    word-spacing: normal;\n    word-break: break-all;\n    color: #626262;\n  }\n\n  .img-box {\n    border: 1px solid #EBEBEB;\n    margin-left: -80px;\n  }\n\n  img {\n    display: block;\n    @include wh(80px);\n  }\n\n  .goods-table {\n    .n-b {\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      > div {\n        color: #626262;\n        font-weight: 700;\n        width: 165px;\n        text-align: center;\n      }\n    }\n    .cart-items {\n      display: flex;\n      align-items: center;\n      justify-content: space-between;\n      height: 110px;\n      padding: 15px 0 15px 111px;\n      border-bottom: 1px solid #EFEFEF;\n      a {\n        color: #333;\n      }\n    }\n    .price {\n      padding-left: 107px;\n    }\n    .goods-num {\n      padding-left: 60px;\n    }\n  }\n\n  .order-discount-line {\n    padding: 22px 30px 20px;\n    line-height: 24px;\n    text-align: right;\n    font-size: 12px;\n    &:first-child {\n      line-height: 32px;\n      text-align: right;\n      font-size: 14px;\n      font-weight: bolder;\n    }\n  }\n\n  .gray-sub-title {\n    height: 38px;\n    padding: 0 24px;\n    background: #EEE;\n    border-top: 1px solid #DBDBDB;\n    border-bottom: 1px solid #DBDBDB;\n    line-height: 38px;\n    font-size: 12px;\n    color: #666;\n    display: flex;\n    span {\n      display: inline-block;\n      height: 100%;\n    }\n    .first {\n      display: flex;\n      justify-content: space-between;\n      flex: 1;\n      .f-bc {\n        > span {\n          width: 130px;\n          text-align: center;\n        }\n      }\n    }\n    .last {\n      width: 230px;\n      text-align: center;\n      display: flex;\n      border-left: 1px solid #ccc;\n      span {\n        flex: 1;\n      }\n    }\n  }\n\n  .bt {\n    border-top: 1px solid #EFEFEF;\n  }\n\n  .date {\n    padding-left: 0px;\n  }\n\n  .order-id {\n    margin-left: 10px;\n  }\n\n  .cart {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    padding: 0 24px;\n    &:hover {\n      .del-order {\n        display: block;\n      }\n    }\n    .del-order {\n      display: none;\n    }\n    .cart-l {\n      display: flex;\n      align-items: center;\n      flex: 1;\n      padding: 15px 0;\n      justify-content: space-between;\n      position: relative;\n      &:before {\n        position: absolute;\n        content: ' ';\n        right: -1px;\n        top: 0;\n        width: 1px;\n        background-color: #EFEFEF;\n        height: 100%;\n      }\n      .ellipsis {\n        margin-left: 20px;\n        width: 220px;\n      }\n      .img-box {\n        border: 1px solid #EBEBEB;\n      }\n      img {\n        display: block;\n        @include wh(80px);\n      }\n      .cart-l-r {\n        display: flex;\n        > div {\n          text-align: center;\n          width: 112px;\n        }\n      }\n      .car-l-l {\n        display: flex;\n        align-items: center;\n      }\n    }\n    .cart-r {\n      width: 230px;\n      display: flex;\n      span {\n        text-align: center;\n        flex: 1;\n      }\n    }\n  }\n\n  .prod-operation {\n    height: 110px;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 254px;\n    div {\n      width: 100%;\n      text-align: center;\n    }\n    div:last-child {\n      padding-right: 24px;\n    }\n  }\n\n  .price-total {\n    height: 54px;\n    line-height: 54px;\n    font-size: 18px;\n  }\n\n  .price-red {\n    font-weight: 700;\n    color: #d44d44;\n  }\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/User/user.vue",
    "content": "<template>\n  <div class=\"layout-container\">\n    <y-header>\n      <div slot=\"nav\"></div>\n    </y-header>\n    <div class=\"w\">\n      <div class=\"content\">\n        <div class=\"account-sidebar\">\n          <div class=\"avatar gray-box \">\n            <div>\n              <img :src=\"userInfo.info.file\"> <h5>\n              {{userInfo.info.username}}</h5></div>\n            <div class=\"box-inner\">\n              <ul class=\"account-nav\">\n                <li v-for=\"(item,i) in nav\" :key='i' :class=\"{current:item.name===title}\"\n                    @click=\"tab(item)\">\n                  <a href=\"javascript:;\">{{item.name}}</a></li>\n              </ul>\n            </div>\n          </div>\n        </div>\n        <div class=\"account-content\">\n          <router-view></router-view>\n        </div>\n      </div>\n    </div>\n    <y-footer></y-footer>\n\n  </div>\n\n</template>\n<script>\n  import YFooter from '/common/footer'\n  import YHeader from '/common/header'\n  import { mapState } from 'vuex'\n  export default {\n    data () {\n      return {\n        title: '我的订单',\n        nav: [\n          {name: '我的订单', path: 'orderList'},\n          {name: '账户资料', path: 'information'},\n          {name: '收货地址', path: 'addressList'}\n        ],\n        editAvatar: true\n      }\n    },\n    computed: {\n      ...mapState(['userInfo'])\n    },\n    methods: {\n      tab (e) {\n        this.$router.push({path: '/user/' + e.path})\n      }\n    },\n    created () {\n      let path = this.$route.path.split('/')[2]\n      this.nav.forEach(item => {\n        if (item.path === path) {\n          this.title = item.name\n        }\n      })\n    },\n    components: {\n      YFooter,\n      YHeader\n    },\n    watch: {\n      $route (to) {\n        let path = to.path.split('/')[2]\n        this.nav.forEach(item => {\n          if (item.path === path) {\n            this.title = item.name\n          }\n        })\n      }\n    }\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\" scoped>\n  @import \"../../assets/style/mixin\";\n\n  .w {\n    padding-top: 40px;\n  }\n\n  .content {\n    display: flex;\n    height: 100%;\n  }\n\n  .account-sidebar {\n    width: 210px;\n    border-radius: 6px;\n    .avatar {\n      padding-top: 20px;\n      border-radius: 10px;\n      text-align: center;\n      img {\n        width: 168px;\n        height: 168px;\n      }\n      h5 {\n        font-size: 18px;\n        line-height: 48px;\n        font-weight: 700;\n      }\n    }\n    .account-nav {\n      padding-top: 15px;\n      li {\n        position: relative;\n        height: 48px;\n        border-top: 1px solid #EBEBEB;\n        line-height: 48px;\n        &:hover {\n          a {\n            position: relative;\n            z-index: 1;\n            height: 50px;\n            background-color: #98AFEE;\n            line-height: 50px;\n            color: #FFF;\n          }\n\n        }\n        a {\n          display: block;\n        }\n        &.current {\n          a {\n            position: relative;\n            z-index: 1;\n            height: 50px;\n            background-color: #98AFEE;\n            line-height: 50px;\n            color: #FFF;\n          }\n        }\n\n      }\n    }\n  }\n\n  .account-content {\n    margin-left: 20px;\n    flex: 1;\n  }\n\n\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/page/index.vue",
    "content": "<template>\n  <div>\n    <y-header></y-header>\n    <router-view class=\"main\"></router-view>\n    <y-footer></y-footer>\n    <!--抛物图片-->\n    <transition @after-enter='afterEnter' @before-enter=\"beforeEnter\">\n      <!--整张图片-->\n      <div class=\"move_img\" v-if=\"showMoveImg\"\n           :style=\"{left:(cartPositionL-10) + 'px',top:(cartPositionT-10) + 'px'}\">\n        <div><img :src=\"moveImgUrl\"></div>\n      </div>\n    </transition>\n  </div>\n</template>\n<script>\n  import YHeader from '/common/header'\n  import YFooter from '/common/footer'\n  import { mapState, mapMutations } from 'vuex'\n  export default {\n    data () {\n      return {}\n    },\n    computed: {\n      ...mapState(['cartPositionT', 'cartPositionL', 'showMoveImg', 'elLeft', 'elTop', 'moveImgUrl'])\n    },\n    methods: {\n      ...mapMutations(['ADD_ANIMATION']),\n      // 监听图片进入购物车\n      listenInCart () {\n        this.ADD_ANIMATION({moveShow: false, receiveInCart: true})\n      },\n      beforeEnter (el) {\n        let elStyle = el.style\n        let elChild = el.children[0]\n        let elChildSty = elChild.style\n        elStyle.transform = `translate3d(0,${this.elTop - this.cartPositionT}px,0)`\n        elChildSty.transform = `translate3d(${-(this.cartPositionL - this.elLeft)}px,0,0) scale(1.2)`\n      },\n      afterEnter (el) {\n        let elStyle = el.style\n        let elChild = el.children[0]\n        let elChildSty = elChild.style\n        elStyle.transform = `translate3d(0,0,0)`\n        elChildSty.transform = `translate3d(0,0,0) scale(.2)`\n        elStyle.transition = 'transform .55s cubic-bezier(.29,.55,.51,1.08)'\n        elChildSty.transition = 'transform .55s linear'\n        // 动画结束\n        elChild.addEventListener('transitionend', () => {\n          this.listenInCart()\n        })\n        elChild.addEventListener('webkitAnimationEnd', () => {\n          this.listenInCart()\n        })\n      }\n    },\n    components: {\n      YHeader,\n      YFooter\n    }\n  }\n</script>\n<style lang=\"scss\" rel=\"stylesheet/scss\" scoped>\n  @import \"../assets/style/mixin\";\n\n  .main {\n    min-height: calc(100vh - 454px);\n    background: #ededed;\n    overflow: hidden;\n    width: 100%;\n  }\n\n  .bn {\n    border-style: none;\n    border-width: 0;\n    border: none;\n  }\n\n  .move_img {\n    position: fixed;\n    @include wh(40px);\n    width: 45px;\n    z-index: 29;\n    height: 45px;\n    div {\n      @extend .bn;\n    }\n    img {\n      border-radius: 50%;\n      width: 100%;\n      height: 100%;\n      display: block;\n      @extend .bn;\n    }\n  }\n\n\n</style>\n"
  },
  {
    "path": "ymall-web-ui/src/router/index.js",
    "content": "import Vue from 'vue'\nimport Router from 'vue-router'\nconst Index = () => import('/page/index.vue')\nconst Login = () => import('/page/Login/login.vue')\nconst Register = () => import('/page/Login/register.vue')\nconst forgetPassword = () => import('/page/Login/forgetPassword.vue')\nconst Home = () => import('/page/Home/home.vue')\nconst GoodS = () => import('/page/Goods/goods.vue')\nconst goodsDetails = () => import('/page/Goods/goodsDetails.vue')\nconst Cart = () => import('/page/Cart/cart.vue')\nconst order = () => import('/page/Order/order.vue')\nconst user = () => import('/page/User/user.vue')\nconst orderList = () => import('/page/User/children/order.vue')\nconst information = () => import('/page/User/children/information.vue')\nconst addressList = () => import('/page/User/children/addressList.vue')\nconst checkout = () => import('/page/Checkout/checkout.vue')\nconst payment = () => import('/page/Order/payment.vue')\nconst paysuccess = () => import('/page/Order/paysuccess.vue')\nconst Search = () => import('/page/Search/search.vue')\nconst RefreshSearch = () => import('/page/Refresh/refreshsearch.vue')\nconst orderDetail = () => import('/page/User/children/orderDetail.vue')\nVue.use(Router)\nexport default new Router({\n  mode: 'history',\n  routes: [\n    {\n      path: '/',\n      component: Index,\n      name: 'index',\n      redirect: '/home',\n      children: [\n        {path: 'home', component: Home},\n        {path: 'goods', component: GoodS},\n        {path: 'search', name: 'search', component: Search},\n        {path: 'goodsDetails', name: 'goodsDetails', component: goodsDetails}\n      ]\n    },\n    {path: '/login', name: 'login', component: Login},\n    {path: '/register', name: 'register', component: Register},\n    {path: '/forgetPassword', name: 'forgetPassword', component: forgetPassword},\n    {path: '/cart', name: 'cart', component: Cart},\n    {path: '/refreshsearch', name: 'refreshsearch', component: RefreshSearch},\n    {\n      path: '/order',\n      name: 'order',\n      component: order,\n      children: [\n        {path: 'paysuccess', name: 'paysuccess', component: paysuccess},\n        {path: 'payment', name: 'payment', component: payment}\n      ]\n    },\n    {\n      path: '/user',\n      name: 'user',\n      component: user,\n      redirect: '/user/orderList',\n      children: [\n        {path: 'orderList', name: '订单列表', component: orderList},\n        {path: 'orderDetail', name: '订单详情', component: orderDetail},\n        {path: 'information', name: '账户资料', component: information},\n        {path: 'addressList', name: '收货地址', component: addressList}\n      ]\n    },\n    {path: '/checkout', name: 'checkout', component: checkout},\n    {path: '*', redirect: '/home'}\n  ]\n})\n"
  },
  {
    "path": "ymall-web-ui/src/store/action.js",
    "content": "export default {}\n"
  },
  {
    "path": "ymall-web-ui/src/store/index.js",
    "content": "import Vue from 'vue'\nimport Vuex from 'vuex'\nimport mutations from './mutations'\nimport action from './action'\nVue.use(Vuex)\n\nconst state = {\n  login: false,   // 是否登录\n  userInfo: null, // 用户信息\n  cartList: [],   // 加入购物车列表\n  showMoveImg: false, // 显示飞入图片\n  elLeft: 0,\n  elTop: 0,\n  moveImgUrl: null,\n  cartPositionT: 0, // 购物车位置\n  cartPositionL: 0,\n  receiveInCart: false, // 是否进入购物车\n  showCart: false // 是否显示购物车\n}\n\nexport default new Vuex.Store({\n  state,\n  action,\n  mutations\n})\n"
  },
  {
    "path": "ymall-web-ui/src/store/mutation-types.js",
    "content": "export const INIT_BUYCART = 'INIT_BUYCART'\nexport const ADD_CART = 'ADD_CART'\nexport const GET_USERINFO = 'GET_USERINFO'\nexport const RECORD_USERINFO = 'RECORD_USERINFO'\nexport const ADD_ANIMATION = 'ADD_ANIMATION'\nexport const SHOW_CART = 'SHOW_CART'\nexport const REDUCE_CART = 'REDUCE_CART'\nexport const EDIT_CART = 'EDIT_CART'\n"
  },
  {
    "path": "ymall-web-ui/src/store/mutations.js",
    "content": "import {\n  INIT_BUYCART,\n  ADD_CART,\n  GET_USERINFO,\n  RECORD_USERINFO,\n  ADD_ANIMATION,\n  SHOW_CART,\n  REDUCE_CART,\n  EDIT_CART\n} from './mutation-types'\nimport { setStore, getStore } from '../utils/storage'\nexport default {\n  // 网页初始化时从本地缓存获取购物车数据\n  [INIT_BUYCART] (state) {\n    let initCart = getStore('buyCart')\n    if (initCart) {\n      state.cartList = JSON.parse(initCart)\n    }\n  },\n  // 加入购物车\n  [ADD_CART] (state, {productId, salePrice, productName, productImg, limitNum, productNum = 1}) {\n    let cart = state.cartList // 购物车\n    let flag = true\n    let goods = {\n      productId,\n      salePrice,\n      productName,\n      productImg,\n      limitNum\n    }\n    if (cart.length) {        // 有内容\n      cart.forEach(item => {\n        if (item.productId === productId) {\n          if (item.productNum >= 0) {\n            flag = false\n            item.productNum += productNum\n          }\n        }\n      })\n    }\n    if (!cart.length || flag) {\n      goods.productNum = productNum\n      goods.checked = '1'\n      cart.push(goods)\n    }\n    state.cartList = cart\n    // 存入localStorage\n    setStore('buyCart', cart)\n  },\n  // 加入购物车动画\n  [ADD_ANIMATION] (state, {moveShow, elLeft, elTop, img, cartPositionT, cartPositionL, receiveInCart}) {\n    state.showMoveImg = moveShow\n    if (elLeft) {\n      state.elLeft = elLeft\n      state.elTop = elTop\n    }\n    state.moveImgUrl = img\n    state.receiveInCart = receiveInCart\n    if (cartPositionT) {\n      state.cartPositionT = cartPositionT\n      state.cartPositionL = cartPositionL\n    }\n  },\n  // 是否显示购物车\n  [SHOW_CART] (state, {showCart}) {\n    // let timer = null\n    state.showCart = showCart\n    // clearTimeout(timer)\n    // if (showCart) {\n    //   timer = setTimeout(() => {\n    //     state.showCart = false\n    //   }, 5000)\n    // }\n  },\n  // 移除商品\n  [REDUCE_CART] (state, {productId}) {\n    let cart = state.cartList\n    cart.forEach((item, i) => {\n      if (item.productId === productId) {\n        if (item.productNum > 1) {\n          item.productNum--\n        } else {\n          cart.splice(i, 1)\n        }\n      }\n    })\n    state.cartList = cart\n    // 存入localStorage\n    setStore('buyCart', state.cartList)\n  },\n  // 修改购物车\n  [EDIT_CART] (state, {productId, productNum, checked, checkedDelete}) {\n    productId = Number(productId)\n    let cart = state.cartList\n    if (productNum) {\n      cart.forEach((item, i) => {\n        if (item.productId === productId) {\n          item.productNum = productNum\n          item.checked = checked\n        }\n      })\n    } else if (productId) {\n      cart.forEach((item, i) => {\n        console.log(productId)\n        console.log(i)\n        if (item.productId === productId) {\n          console.log('splice')\n          console.log(cart)\n          cart.splice(i, 1)\n          console.log(cart)\n        }\n      })\n    } else {\n      cart.forEach((item) => {\n        item.checked = checked ? '1' : '0'\n      })\n    }\n    state.cartList = cart\n    // 存入localStorage\n    setStore('buyCart', state.cartList)\n  },\n  // 记录用户信息\n  [RECORD_USERINFO] (state, info) {\n    state.userInfo = info\n    state.login = true\n    setStore('userInfo', info)\n  },\n  // 获取用户信息\n  [GET_USERINFO] (state, info) {\n    if (state.userInfo && (state.userInfo.username !== info.username)) {\n      return\n    }\n    if (!state.login) {\n      return\n    }\n    if (!info.message) {\n      state.userInfo = {...info}\n    } else {\n      state.userInfo = null\n    }\n  }\n}\n"
  },
  {
    "path": "ymall-web-ui/src/utils/storage.js",
    "content": "/**\n * 存储localStorage\n */\nexport const setStore = (name, content) => {\n  if (!name) return\n  if (typeof content !== 'string') {\n    content = JSON.stringify(content)\n  }\n  window.localStorage.setItem(name, content)\n}\n\n/**\n * 获取localStorage\n */\nexport const getStore = name => {\n  if (!name) return\n  return window.localStorage.getItem(name)\n}\n\n/**\n * 删除localStorage\n */\nexport const removeStore = name => {\n  if (!name) return\n  window.localStorage.removeItem(name)\n}\n"
  },
  {
    "path": "ymall-web-ui/static/.gitkeep",
    "content": ""
  },
  {
    "path": "ymall-web-ui/static/geetest/gt.js",
    "content": "/* initGeetest 1.0.0\n * 用于加载id对应的验证码库，并支持宕机模式\n * 暴露 initGeetest 进行验证码的初始化\n * 一般不需要用户进行修改\n */\n(function (global, factory) {\n    \"use strict\";\n    if (typeof module === \"object\" && typeof module.exports === \"object\") {\n        // CommonJS\n        module.exports = global.document ?\n            factory(global, true) :\n            function (w) {\n                if (!w.document) {\n                    throw new Error(\"Geetest requires a window with a document\");\n                }\n                return factory(w);\n            };\n    } else {\n        factory(global);\n    }\n})(typeof window !== \"undefined\" ? window : this, function (window, noGlobal) {\n    \"use strict\";\n    if (typeof window === 'undefined') {\n        throw new Error('Geetest requires browser environment');\n    }\n    var document = window.document;\n    var Math = window.Math;\n    var head = document.getElementsByTagName(\"head\")[0];\n\n    function _Object(obj) {\n        this._obj = obj;\n    }\n\n    _Object.prototype = {\n        _each: function (process) {\n            var _obj = this._obj;\n            for (var k in _obj) {\n                if (_obj.hasOwnProperty(k)) {\n                    process(k, _obj[k]);\n                }\n            }\n            return this;\n        }\n    };\n    function Config(config) {\n        var self = this;\n        new _Object(config)._each(function (key, value) {\n            self[key] = value;\n        });\n    }\n\n    Config.prototype = {\n        api_server: 'api.geetest.com',\n        protocol: 'http://',\n        type_path: '/gettype.php',\n        fallback_config: {\n            slide: {\n                static_servers: [\"static.geetest.com\", \"dn-staticdown.qbox.me\"],\n                type: 'slide',\n                slide: '/static/js/geetest.0.0.0.js'\n            },\n            fullpage: {\n                static_servers: [\"static.geetest.com\", \"dn-staticdown.qbox.me\"],\n                type: 'fullpage',\n                fullpage: '/static/js/fullpage.0.0.0.js'\n            }\n        },\n        _get_fallback_config: function () {\n            var self = this;\n            if (isString(self.type)) {\n                return self.fallback_config[self.type];\n            } else if (self.new_captcha) {\n                return self.fallback_config.fullpage;\n            } else {\n                return self.fallback_config.slide;\n            }\n        },\n        _extend: function (obj) {\n            var self = this;\n            new _Object(obj)._each(function (key, value) {\n                self[key] = value;\n            })\n        }\n    };\n    var isNumber = function (value) {\n        return (typeof value === 'number');\n    };\n    var isString = function (value) {\n        return (typeof value === 'string');\n    };\n    var isBoolean = function (value) {\n        return (typeof value === 'boolean');\n    };\n    var isObject = function (value) {\n        return (typeof value === 'object' && value !== null);\n    };\n    var isFunction = function (value) {\n        return (typeof value === 'function');\n    };\n    var callbacks = {};\n    var status = {};\n    var random = function () {\n        return parseInt(Math.random() * 10000) + (new Date()).valueOf();\n    };\n    var loadScript = function (url, cb) {\n        var script = document.createElement(\"script\");\n        script.charset = \"UTF-8\";\n        script.async = true;\n        script.onerror = function () {\n            cb(true);\n        };\n        var loaded = false;\n        script.onload = script.onreadystatechange = function () {\n            if (!loaded &&\n                (!script.readyState ||\n                \"loaded\" === script.readyState ||\n                \"complete\" === script.readyState)) {\n\n                loaded = true;\n                setTimeout(function () {\n                    cb(false);\n                }, 0);\n            }\n        };\n        script.src = url;\n        head.appendChild(script);\n    };\n    var normalizeDomain = function (domain) {\n        return domain.replace(/^https?:\\/\\/|\\/$/g, '');\n    };\n    var normalizePath = function (path) {\n        path = path.replace(/\\/+/g, '/');\n        if (path.indexOf('/') !== 0) {\n            path = '/' + path;\n        }\n        return path;\n    };\n    var normalizeQuery = function (query) {\n        if (!query) {\n            return '';\n        }\n        var q = '?';\n        new _Object(query)._each(function (key, value) {\n            if (isString(value) || isNumber(value) || isBoolean(value)) {\n                q = q + encodeURIComponent(key) + '=' + encodeURIComponent(value) + '&';\n            }\n        });\n        if (q === '?') {\n            q = '';\n        }\n        return q.replace(/&$/, '');\n    };\n    var makeURL = function (protocol, domain, path, query) {\n        domain = normalizeDomain(domain);\n\n        var url = normalizePath(path) + normalizeQuery(query);\n        if (domain) {\n            url = protocol + domain + url;\n        }\n\n        return url;\n    };\n    var load = function (protocol, domains, path, query, cb) {\n        var tryRequest = function (at) {\n\n            var url = makeURL(protocol, domains[at], path, query);\n            loadScript(url, function (err) {\n                if (err) {\n                    if (at >= domains.length - 1) {\n                        cb(true);\n                    } else {\n                        tryRequest(at + 1);\n                    }\n                } else {\n                    cb(false);\n                }\n            });\n        };\n        tryRequest(0);\n    };\n    var jsonp = function (domains, path, config, callback) {\n        if (isObject(config.getLib)) {\n            config._extend(config.getLib);\n            callback(config);\n            return;\n        }\n        if (config.offline) {\n            callback(config._get_fallback_config());\n            return;\n        }\n        var cb = \"geetest_\" + random();\n        window[cb] = function (data) {\n            if (data.status === 'success') {\n                callback(data.data);\n            } else if (!data.status) {\n                callback(data);\n            } else {\n                callback(config._get_fallback_config());\n            }\n            window[cb] = undefined;\n            try {\n                delete window[cb];\n            } catch (e) {\n            }\n        };\n        load(config.protocol, domains, path, {\n            gt: config.gt,\n            callback: cb\n        }, function (err) {\n            if (err) {\n                callback(config._get_fallback_config());\n            }\n        });\n    };\n    var throwError = function (errorType, config) {\n        var errors = {\n            networkError: '网络错误'\n        };\n        if (typeof config.onError === 'function') {\n            config.onError(errors[errorType]);\n        } else {\n            throw new Error(errors[errorType]);\n        }\n    };\n    var detect = function () {\n        return !!window.Geetest;\n    };\n    if (detect()) {\n        status.slide = \"loaded\";\n    }\n    var initGeetest = function (userConfig, callback) {\n        var config = new Config(userConfig);\n        if (userConfig.https) {\n            config.protocol = 'https://';\n        } else if (!userConfig.protocol) {\n            config.protocol = window.location.protocol + '//';\n        }\n        jsonp([config.api_server || config.apiserver], config.type_path, config, function (newConfig) {\n            var type = newConfig.type;\n            var init = function () {\n                config._extend(newConfig);\n                callback(new window.Geetest(config));\n            };\n            callbacks[type] = callbacks[type] || [];\n            var s = status[type] || 'init';\n            if (s === 'init') {\n                status[type] = 'loading';\n                callbacks[type].push(init);\n                load(config.protocol, newConfig.static_servers || newConfig.domains, newConfig[type] || newConfig.path, null, function (err) {\n                    if (err) {\n                        status[type] = 'fail';\n                        throwError('networkError', config);\n                    } else {\n                        status[type] = 'loaded';\n                        var cbs = callbacks[type];\n                        for (var i = 0, len = cbs.length; i < len; i = i + 1) {\n                            var cb = cbs[i];\n                            if (isFunction(cb)) {\n                                cb();\n                            }\n                        }\n                        callbacks[type] = [];\n                    }\n                });\n            } else if (s === \"loaded\") {\n                init();\n            } else if (s === \"fail\") {\n                throwError('networkError', config);\n            } else if (s === \"loading\") {\n                callbacks[type].push(init);\n            }\n        });\n    };\n    window.initGeetest = initGeetest;\n    return initGeetest;\n});\n"
  },
  {
    "path": "ymall-web-ui/static/js/3.c565d4ee71bdb3ac0105.js",
    "content": "webpackJsonp([3],{191:function(e,o,t){function A(e){t(334)}var l=t(96)(t(280),t(362),A,\"data-v-90aa0c9c\",null);e.exports=l.exports},192:function(e,o,t){function A(e){t(195)}var l=t(96)(t(193),t(196),A,\"data-v-b42a215c\",null);e.exports=l.exports},193:function(e,o,t){\"use strict\";Object.defineProperty(o,\"__esModule\",{value:!0}),o.default={props:{text:{type:[String,Number],default:\"一颗小按钮\"},inputType:{type:[String],default:\"button\"},classStyle:{type:String,default:\"default-btn\"}},methods:{btnClick:function(e){this.$emit(\"btnClick\",e)}}}},194:function(e,o,t){o=e.exports=t(163)(!0),o.push([e.i,\".default-btn[data-v-b42a215c],.disabled-btn[data-v-b42a215c],.main-btn[data-v-b42a215c]{width:100px;height:30px;line-height:28px;vertical-align:middle}input[data-v-b42a215c]{display:inline-block;cursor:pointer;text-align:center}.gray-btn[data-v-b42a215c]{border:1px solid #d5d5d5;color:#646464}.default-btn[data-v-b42a215c]{border:1px solid #e1e1e1;border-radius:4px;font-size:12px;color:#646464;background-color:#f9f9f9;background-image:linear-gradient(180deg,#fff,#f9f9f9)}.default-btn[data-v-b42a215c]:hover{background-color:#eee;background-image:linear-gradient(180deg,#f5f5f5,#eee)}.main-btn[data-v-b42a215c]{border:1px solid #5c81e3;border-radius:4px;font-size:12px;color:#fff;background-color:#678ee7;background-image:linear-gradient(180deg,#678ee7,#5078df)}.main-btn[data-v-b42a215c]:hover{background-color:#6c8cd4;background-image:linear-gradient(180deg,#6c8cd4,#4769c2)}.disabled-btn[data-v-b42a215c]{cursor:not-allowed;border:1px solid #afafaf;border-radius:4px;font-size:12px;color:#fff;background-color:#a9a9a9;background-image:linear-gradient(180deg,#b8b8b8,#a9a9a9)}\",\"\",{version:3,sources:[\"D:/桌面/YMall-front/src/components/YButton.vue\"],names:[],mappings:\"AAEA,wFACE,YAAa,AACb,YAAa,AACb,iBAAkB,AAClB,qBAAuB,CACxB,AACD,uBACE,qBAAsB,AACtB,eAAgB,AAChB,iBAAmB,CAOpB,AAGD,2BACE,yBAA0B,AAC1B,aAAe,CAChB,AACD,8BACE,yBAA0B,AAC1B,kBAAmB,AACnB,eAAgB,AAChB,cAAe,AACf,yBAA0B,AAC1B,qDAAyD,CAC1D,AACD,oCACI,sBAAuB,AACvB,qDAAyD,CAC5D,AACD,2BACE,yBAA0B,AAC1B,kBAAmB,AACnB,eAAgB,AAChB,WAAY,AACZ,yBAA0B,AAC1B,wDAA4D,CAC7D,AACD,iCACI,yBAA0B,AAC1B,wDAA4D,CAC/D,AACD,+BACE,mBAAoB,AACpB,yBAA0B,AAC1B,kBAAmB,AACnB,eAAgB,AAChB,WAAY,AACZ,yBAA0B,AAC1B,wDAA4D,CAC7D\",file:\"YButton.vue\",sourcesContent:['\\n@charset \"UTF-8\";\\n.default-btn[data-v-b42a215c], .main-btn[data-v-b42a215c], .disabled-btn[data-v-b42a215c] {\\n  width: 100px;\\n  height: 30px;\\n  line-height: 28px;\\n  vertical-align: middle;\\n}\\ninput[data-v-b42a215c] {\\n  display: inline-block;\\n  cursor: pointer;\\n  text-align: center;\\n  /*> span {*/\\n  /*user-select: none;*/\\n  /*display: inline-block;*/\\n  /*width: 100%;*/\\n  /*height: 100%;*/\\n  /*}*/\\n}\\n\\n/*灰色的按钮*/\\n.gray-btn[data-v-b42a215c] {\\n  border: 1px solid #d5d5d5;\\n  color: #646464;\\n}\\n.default-btn[data-v-b42a215c] {\\n  border: 1px solid #e1e1e1;\\n  border-radius: 4px;\\n  font-size: 12px;\\n  color: #646464;\\n  background-color: #f9f9f9;\\n  background-image: linear-gradient(180deg, #fff, #f9f9f9);\\n}\\n.default-btn[data-v-b42a215c]:hover {\\n    background-color: #eee;\\n    background-image: linear-gradient(180deg, #f5f5f5, #eee);\\n}\\n.main-btn[data-v-b42a215c] {\\n  border: 1px solid #5c81e3;\\n  border-radius: 4px;\\n  font-size: 12px;\\n  color: #fff;\\n  background-color: #678ee7;\\n  background-image: linear-gradient(180deg, #678ee7, #5078df);\\n}\\n.main-btn[data-v-b42a215c]:hover {\\n    background-color: #6c8cd4;\\n    background-image: linear-gradient(180deg, #6c8cd4, #4769c2);\\n}\\n.disabled-btn[data-v-b42a215c] {\\n  cursor: not-allowed;\\n  border: 1px solid #afafaf;\\n  border-radius: 4px;\\n  font-size: 12px;\\n  color: #fff;\\n  background-color: #a9a9a9;\\n  background-image: linear-gradient(180deg, #b8b8b8, #a9a9a9);\\n}\\n'],sourceRoot:\"\"}])},195:function(e,o,t){var A=t(194);\"string\"==typeof A&&(A=[[e.i,A,\"\"]]),A.locals&&(e.exports=A.locals);t(164)(\"1a40afec\",A,!0)},196:function(e,o){e.exports={render:function(){var e=this,o=e.$createElement;return(e._self._c||o)(\"input\",{class:e.classStyle,attrs:{type:e.inputType,readonly:\"\",disabled:\"disabled-btn\"===e.classStyle},domProps:{value:e.text},on:{click:function(o){e.btnClick(o)}}})},staticRenderFns:[]}},202:function(e,o,t){\"use strict\";t.d(o,\"s\",function(){return l}),t.d(o,\"e\",function(){return i}),t.d(o,\"g\",function(){return r}),t.d(o,\"r\",function(){return a}),t.d(o,\"q\",function(){return n}),t.d(o,\"f\",function(){return s}),t.d(o,\"i\",function(){return c}),t.d(o,\"j\",function(){return p}),t.d(o,\"k\",function(){return d}),t.d(o,\"l\",function(){return B}),t.d(o,\"m\",function(){return b}),t.d(o,\"h\",function(){return f}),t.d(o,\"o\",function(){return g}),t.d(o,\"a\",function(){return u}),t.d(o,\"b\",function(){return C}),t.d(o,\"n\",function(){return h}),t.d(o,\"p\",function(){return m}),t.d(o,\"c\",function(){return x}),t.d(o,\"d\",function(){return _});var A=t(98),l=function(e){return A.a.fetchGet(\"/goods/allGoods\",e)},i=function(e){return A.a.fetchPost(\"/member/cartList\",e)},r=function(e){return A.a.fetchPost(\"/member/addCart\",e)},a=function(e){return A.a.fetchPost(\"/member/cartEdit\",e)},n=function(e){return A.a.fetchPost(\"/member/editCheckAll\",e)},s=function(e){return A.a.fetchPost(\"/member/cartDel\",e)},c=function(e){return A.a.fetchPost(\"/member/addressList\",e)},p=function(e){return A.a.fetchPost(\"/member/updateAddress\",e)},d=function(e){return A.a.fetchPost(\"/member/addAddress\",e)},B=function(e){return A.a.fetchPost(\"/member/delAddress\",e)},b=function(e){return A.a.fetchPost(\"/member/addOrder\",e)},f=function(e){return A.a.fetchPost(\"/member/payOrder\",e)},g=function(e){return A.a.fetchGet(\"/member/orderList\",e)},u=function(e){return A.a.fetchGet(\"/member/orderDetail\",e)},C=function(e){return A.a.fetchPost(\"/member/cancelOrder\",e)},h=function(e){return A.a.fetchGet(\"/goods/productDet\",e)},m=function(e){return A.a.fetchGet(\"/member/delOrder\",e)},x=function(e){return A.a.fetchGet(\"/goods/search\",e)},_=function(e){return A.a.fetchQuickSearch(\"http://127.0.0.1:9200/item/itemList/_search?q=productName: \"+e)}},203:function(e,o,t){var A=t(1),l=t(3),i=t(43),r=t(204),a=t(11).f;e.exports=function(e){var o=l.Symbol||(l.Symbol=i?{}:A.Symbol||{});\"_\"==e.charAt(0)||e in o||a(o,e,{value:r.f(e)})}},204:function(e,o,t){o.f=t(2)},205:function(e,o,t){var A=t(106),l=t(46).concat(\"length\",\"prototype\");o.f=Object.getOwnPropertyNames||function(e){return A(e,l)}},206:function(e,o,t){\"use strict\";Object.defineProperty(o,\"__esModule\",{value:!0});var A=t(192),l=t.n(A);o.default={data:function(){return{}},methods:{open1:function(){this.$notify.info({title:\"法律声明\",message:\"此仅为个人练习开源模仿项目，仅供学习参考，承担不起任何法律问题\"})},open2:function(){this.$notify.info({title:\"隐私条款\",message:\"本网站将不会严格遵守有关法律法规和本隐私政策所载明的内容收集、使用您的信息\"})},open3:function(){this.$notify({title:\"离线帮助\",message:\"没人会帮助你，请自己靠自己\",type:\"warning\"})},open4:function(){this.$notify.info({title:\"支付方式\",message:\"支持支付宝、微信等方式捐赠\"})},open5:function(){this.$notify({title:\"送货政策\",message:\"本网站所有商品购买后不会发货，将用作捐赠\",type:\"warning\"})}},components:{YButton:l.a}}},207:function(e,o,t){o=e.exports=t(163)(!0),o.push([e.i,\".footer[data-v-dc0a64e2]{padding:50px 0 20px;border-top:1px solid #e6e6e6;background:#fafafa;margin-top:60px;height:350px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.container[data-v-dc0a64e2]{width:1220px}.siteinfo[data-v-dc0a64e2]{height:100px;padding:50px 0 130px;border-bottom:1px solid #e6e6e6;position:relative}.c0[data-v-dc0a64e2]{width:149px;line-height:1;float:left}.c1[data-v-dc0a64e2]{color:#646464;font-size:12px;padding:0 0 14px}.c2[data-v-dc0a64e2]{color:#c3c3c3;font-size:12px;padding:6px 0}.c3[data-v-dc0a64e2]{color:#969696}.c4[data-v-dc0a64e2]{position:absolute;right:0;overflow:hidden;line-height:34px}.tel[data-v-dc0a64e2]{font-size:30px;line-height:1;color:#646464;top:-2px;position:relative}.c5[data-v-dc0a64e2]{color:#646464;right:-70px;position:relative}.time[data-v-dc0a64e2]{margin-top:5px;right:-4px;position:relative}.online[data-v-dc0a64e2],.time[data-v-dc0a64e2]{clear:both;width:241px;font-size:12px;line-height:18px;color:#c3c3c3;text-align:right}.button[data-v-dc0a64e2]{width:130px;height:34px;font-size:14px;color:#5079d9;border:1px solid #dcdcdc;margin-top:8px}.copyright[data-v-dc0a64e2]{color:#434d55;font-size:12px;padding:40px 0 0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:left;-ms-flex-align:left;align-items:left}.privacy[data-v-dc0a64e2]{float:left;margin:0 0 0 12px}.content-c0[data-v-dc0a64e2]{color:#5079d9;cursor:pointer;text-decoration:none}.content-c0[data-v-dc0a64e2]:hover{color:#3a5fcd}.content-c1[data-v-dc0a64e2]{float:left;line-height:12px;padding:1px 10px 0;border-left:1px solid #ccc}.content-c2[data-v-dc0a64e2]{float:left;height:15px;line-height:15px;color:#757575}.cop[data-v-dc0a64e2]{clear:both;padding:10px 0 0;height:15px}.content-c3[data-v-dc0a64e2]{margin-right:20px;color:#bdbdbd;font-size:12px;height:12px;line-height:1}\",\"\",{version:3,sources:[\"D:/桌面/YMall-front/src/common/footer.vue\"],names:[],mappings:\"AACA,yBACE,oBAAqB,AACrB,6BAA8B,AAC9B,mBAAoB,AACpB,gBAAiB,AACjB,aAAc,AACd,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,4BAA6B,AAC7B,6BAA8B,AAC1B,0BAA2B,AACvB,sBAAuB,AAC/B,yBAA0B,AACtB,sBAAuB,AACnB,kBAAoB,CAC7B,AACD,4BACE,YAAc,CACf,AACD,2BACE,aAAc,AACd,qBAAsB,AACtB,gCAAiC,AACjC,iBAAmB,CACpB,AACD,qBACE,YAAa,AACb,cAAe,AACf,UAAY,CACb,AACD,qBACE,cAAe,AACf,eAAgB,AAChB,gBAAkB,CACnB,AACD,qBACE,cAAe,AACf,eAAgB,AAChB,aAAe,CAChB,AACD,qBACE,aAAe,CAChB,AACD,qBACE,kBAAmB,AACnB,QAAS,AACT,gBAAiB,AACjB,gBAAkB,CACnB,AACD,sBACE,eAAgB,AAChB,cAAe,AACf,cAAe,AACf,SAAU,AACV,iBAAmB,CACpB,AACD,qBACE,cAAe,AACf,YAAa,AACb,iBAAmB,CACpB,AACD,uBACE,eAAgB,AAChB,WAAY,AACZ,iBAAmB,CAOpB,AACD,gDAPE,WAAY,AACZ,YAAa,AACb,eAAgB,AAChB,iBAAkB,AAClB,cAAe,AACf,gBAAkB,CASnB,AACD,yBACE,YAAa,AACb,YAAa,AACb,eAAgB,AAChB,cAAe,AACf,yBAA0B,AAC1B,cAAgB,CACjB,AACD,4BACE,cAAe,AACf,eAAgB,AAChB,iBAAkB,AAClB,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,uBAAwB,AACpB,oBAAqB,AACjB,gBAAkB,CAC3B,AACD,0BACE,WAAY,AACZ,iBAAmB,CACpB,AACD,6BACE,cAAe,AACf,eAAgB,AAChB,oBAAsB,CACvB,AACD,mCACI,aAAe,CAClB,AACD,6BACE,WAAY,AACZ,iBAAkB,AAClB,mBAAoB,AACpB,0BAA4B,CAC7B,AACD,6BACE,WAAY,AACZ,YAAa,AACb,iBAAkB,AAClB,aAAe,CAChB,AACD,sBACE,WAAY,AACZ,iBAAkB,AAClB,WAAa,CACd,AACD,6BACE,kBAAmB,AACnB,cAAe,AACf,eAAgB,AAChB,YAAa,AACb,aAAe,CAChB\",file:\"footer.vue\",sourcesContent:[\"\\n.footer[data-v-dc0a64e2] {\\n  padding: 50px 0 20px;\\n  border-top: 1px solid #e6e6e6;\\n  background: #fafafa;\\n  margin-top: 60px;\\n  height: 350px;\\n  display: -webkit-box;\\n  display: -ms-flexbox;\\n  display: flex;\\n  -webkit-box-orient: vertical;\\n  -webkit-box-direction: normal;\\n      -ms-flex-direction: column;\\n          flex-direction: column;\\n  -webkit-box-align: center;\\n      -ms-flex-align: center;\\n          align-items: center;\\n}\\n.container[data-v-dc0a64e2] {\\n  width: 1220px;\\n}\\n.siteinfo[data-v-dc0a64e2] {\\n  height: 100px;\\n  padding: 50px 0 130px;\\n  border-bottom: 1px solid #e6e6e6;\\n  position: relative;\\n}\\n.c0[data-v-dc0a64e2] {\\n  width: 149px;\\n  line-height: 1;\\n  float: left;\\n}\\n.c1[data-v-dc0a64e2] {\\n  color: #646464;\\n  font-size: 12px;\\n  padding: 0 0 14px;\\n}\\n.c2[data-v-dc0a64e2] {\\n  color: #c3c3c3;\\n  font-size: 12px;\\n  padding: 6px 0;\\n}\\n.c3[data-v-dc0a64e2] {\\n  color: #969696;\\n}\\n.c4[data-v-dc0a64e2] {\\n  position: absolute;\\n  right: 0;\\n  overflow: hidden;\\n  line-height: 34px;\\n}\\n.tel[data-v-dc0a64e2] {\\n  font-size: 30px;\\n  line-height: 1;\\n  color: #646464;\\n  top: -2px;\\n  position: relative;\\n}\\n.c5[data-v-dc0a64e2] {\\n  color: #646464;\\n  right: -70px;\\n  position: relative;\\n}\\n.time[data-v-dc0a64e2] {\\n  margin-top: 5px;\\n  right: -4px;\\n  position: relative;\\n  clear: both;\\n  width: 241px;\\n  font-size: 12px;\\n  line-height: 18px;\\n  color: #c3c3c3;\\n  text-align: right;\\n}\\n.online[data-v-dc0a64e2] {\\n  clear: both;\\n  width: 241px;\\n  font-size: 12px;\\n  line-height: 18px;\\n  color: #c3c3c3;\\n  text-align: right;\\n}\\n.button[data-v-dc0a64e2] {\\n  width: 130px;\\n  height: 34px;\\n  font-size: 14px;\\n  color: #5079d9;\\n  border: 1px solid #dcdcdc;\\n  margin-top: 8px;\\n}\\n.copyright[data-v-dc0a64e2] {\\n  color: #434d55;\\n  font-size: 12px;\\n  padding: 40px 0 0;\\n  display: -webkit-box;\\n  display: -ms-flexbox;\\n  display: flex;\\n  -webkit-box-align: left;\\n      -ms-flex-align: left;\\n          align-items: left;\\n}\\n.privacy[data-v-dc0a64e2] {\\n  float: left;\\n  margin: 0 0 0 12px;\\n}\\n.content-c0[data-v-dc0a64e2] {\\n  color: #5079d9;\\n  cursor: pointer;\\n  text-decoration: none;\\n}\\n.content-c0[data-v-dc0a64e2]:hover {\\n    color: #3A5FCD;\\n}\\n.content-c1[data-v-dc0a64e2] {\\n  float: left;\\n  line-height: 12px;\\n  padding: 1px 10px 0;\\n  border-left: 1px solid #ccc;\\n}\\n.content-c2[data-v-dc0a64e2] {\\n  float: left;\\n  height: 15px;\\n  line-height: 15px;\\n  color: #757575;\\n}\\n.cop[data-v-dc0a64e2] {\\n  clear: both;\\n  padding: 10px 0 0;\\n  height: 15px;\\n}\\n.content-c3[data-v-dc0a64e2] {\\n  margin-right: 20px;\\n  color: #bdbdbd;\\n  font-size: 12px;\\n  height: 12px;\\n  line-height: 1;\\n}\\n\"],sourceRoot:\"\"}])},208:function(e,o,t){var A=t(207);\"string\"==typeof A&&(A=[[e.i,A,\"\"]]),A.locals&&(e.exports=A.locals);t(164)(\"68d21b77\",A,!0)},209:function(e,o,t){function A(e){t(208)}var l=t(96)(t(206),t(210),A,\"data-v-dc0a64e2\",null);e.exports=l.exports},210:function(e,o){e.exports={render:function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"div\",{staticClass:\"footer\"},[t(\"div\",{staticClass:\"container\"},[t(\"div\",{staticClass:\"siteinfo\"},[t(\"ul\",{staticClass:\"c0\"},[t(\"h3\",{staticClass:\"c1\"},[e._v(\"订单服务\")]),e._v(\" \"),t(\"ul\",[t(\"li\",{staticClass:\"c2\"},[t(\"router-link\",{attrs:{to:\"/thanks\"}},[t(\"a\",{staticClass:\"c3\"},[e._v(\"购买指南\")])])],1),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",on:{click:e.open4}},[e._v(\"支付方式\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",on:{click:e.open5}},[e._v(\"送货政策\")])])])]),e._v(\" \"),e._m(0),e._v(\" \"),e._m(1),e._v(\" \"),e._m(2),e._v(\" \"),e._m(3),e._v(\" \"),e._m(4),e._v(\" \"),t(\"ul\",{staticClass:\"c4\"},[e._m(5),e._v(\" \"),t(\"li\",{staticClass:\"time\"},[e._v(\"周一至周日 10:00-23:00（限Starrer或捐赠人联系）\")]),e._v(\" \"),t(\"li\",{staticClass:\"online\"},[t(\"y-button\",{staticClass:\"button\",attrs:{text:\"在线帮助\"},on:{btnClick:e.open3}})],1)])]),e._v(\" \"),t(\"div\",{staticClass:\"copyright\"},[t(\"h4\",{staticClass:\"content-c2\"},[e._v(\"Copyright ©2017, yuu.cn Co., Ltd. All Rights Reserved.本网站设计内容大部分属锤子科技\")]),e._v(\" \"),t(\"ul\",{staticClass:\"privacy\"},[t(\"li\",{staticClass:\"content-c1\"},[t(\"a\",{staticClass:\"content-c0\",on:{click:e.open1}},[e._v(\"法律声明\")])]),e._v(\" \"),t(\"li\",{staticClass:\"content-c1\"},[t(\"a\",{staticClass:\"content-c0\",on:{click:e.open2}},[e._v(\"隐私条款\")])]),e._v(\" \"),e._m(6)])]),e._v(\" \"),e._m(7)])])},staticRenderFns:[function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"ul\",{staticClass:\"c0\"},[t(\"h3\",{staticClass:\"c1\"},[e._v(\"服务支持\")]),e._v(\" \"),t(\"ul\",[t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"https://github.com/yuu\"}},[e._v(\"官方开源\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"https://github.com/yuu/YMall-front\"}},[e._v(\"项目前端\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"https://github.com/yuu/YMall\"}},[e._v(\"项目后端\")])])])])},function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"ul\",{staticClass:\"c0\"},[t(\"h3\",{staticClass:\"c1\"},[e._v(\"自助服务\")]),e._v(\" \"),t(\"ul\",[t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"http://blog.yuu.cn\"}},[e._v(\"个人博客\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"http://blog.yuu.cn/intro/\"}},[e._v(\"个人简介\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"https://www.bilibili.com/video/av15860053/\"}},[e._v(\"个人视频\")])])])])},function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"ul\",{staticClass:\"c0\"},[t(\"h3\",{staticClass:\"c1\"},[e._v(\"其他项目\")]),e._v(\" \"),t(\"ul\",[t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"http://xpay.yuu.cn\"}},[e._v(\"XPay支付系统\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"http://shouji.baidu.com/software/11783429.html\"}},[e._v(\"数据共享\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"https://github.com/yuu\"}},[e._v(\"待开发...\")])])])])},function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"ul\",{staticClass:\"c0\"},[t(\"h3\",{staticClass:\"c1\"},[e._v(\"友情链接\")]),e._v(\" \"),t(\"ul\",[t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"http://yucccc.com/\"}},[e._v(\"宇cccc\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"http://www.smartisan.com\"}},[e._v(\"Smartisan\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"https://cn.vuejs.org/\"}},[e._v(\"Vue\")])])])])},function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"ul\",{staticClass:\"c0\"},[t(\"h3\",{staticClass:\"c1\"},[e._v(\"关注我吧\")]),e._v(\" \"),t(\"ul\",[t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"http://wpa.qq.com/msgrd?v=3&uin=1012139570&site=qq&menu=yes\"}},[e._v(\"腾讯 QQ\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"http://weibo.com/2255094222/profile\"}},[e._v(\"新浪微博\")])]),e._v(\" \"),t(\"li\",{staticClass:\"c2\"},[t(\"a\",{staticClass:\"c3\",attrs:{target:\"_blank\",href:\"mailto:1012139570@qq.com\"}},[e._v(\"官方邮箱\")])])])])},function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"li\",{staticClass:\"tel\"},[t(\"a\",{staticClass:\"c5\",attrs:{href:\"http://wpa.qq.com/msgrd?v=3&uin=1012139570&site=qq&menu=yes\",target:\"_blank\"}},[e._v(\"1012139570\")])])},function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"li\",{staticClass:\"content-c1\"},[t(\"a\",{staticClass:\"content-c0\",attrs:{target:\"_blank\",href:\"https://github.com/yuu\"}},[e._v(\"开发者中心\")])])},function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"div\",{staticClass:\"cop\"},[t(\"a\",{staticClass:\"content-c3\",attrs:{href:\"http://www.miibeian.gov.cn/\",target:\"_blank\"}},[t(\"span\",{staticClass:\"content-c3\"},[e._v(\"蜀ICP备16030308号-1\")]),e._v(\" \"),t(\"span\",{staticClass:\"content-c3\"},[e._v(\"蜀ICP证16030308号\")])])])}]}},211:function(e,o,t){\"use strict\";Object.defineProperty(o,\"__esModule\",{value:!0});var A=t(214),l=t.n(A),i=t(99),r=t.n(i),a=t(192),n=t.n(a),s=t(100),c=(t.n(s),t(202)),p=t(42),d=t(23),B=t(227);t.n(B);o.default={data:function(){return{user:{},st:!1,cartShow:!1,positionL:0,positionT:0,timerCartShow:null,input:\"\",choosePage:1,searchResults:[],timeout:null,token:\"\"}},computed:r()({},t.i(s.mapState)([\"cartList\",\"login\",\"receiveInCart\",\"showCart\",\"userInfo\"]),{totalPrice:function(){var e=0;return this.cartList&&this.cartList.forEach(function(o){e+=o.productNum*o.salePrice}),e},totalNum:function(){var e=0;return this.cartList&&this.cartList.forEach(function(o){e+=o.productNum}),e}}),methods:r()({},t.i(s.mapMutations)([\"ADD_CART\",\"INIT_BUYCART\",\"ADD_ANIMATION\",\"SHOW_CART\",\"REDUCE_CART\",\"RECORD_USERINFO\",\"EDIT_CART\"]),{handleIconClick:function(e){\"/search\"===this.$route.path?this.$router.push({path:\"/refreshsearch\",query:{key:this.input}}):this.$router.push({path:\"/search\",query:{key:this.input}})},changePage:function(e){this.choosePage=e},loadAll:function(){var e=this;t.i(c.d)(this.input).then(function(o){var t=[],A=5;o.hits.hits.length<=5&&(A=o.hits.hits.length);for(var l=0;l<A;l++){var i={};i.value=o.hits.hits[l]._source.productName,t.push(i)}0!==t.length?e.searchResults=t:e.searchResults=[]})},querySearchAsync:function(e,o){var t=this;return void 0===this.input?void o([]):(this.input=this.input.trim(),\"\"===this.input?void o([]):(this.loadAll(),void setTimeout(function(){o(t.searchResults)},300)))},handleSelect:function(e){this.input=e.value},cartShowState:function(e){this.SHOW_CART({showCart:e})},_getCartList:function(){t.i(c.e)({userId:t.i(d.a)(\"userId\")}).then(function(e){!0===e.success&&t.i(d.b)(\"buyCart\",e.result)}).then(this.INIT_BUYCART)},delGoods:function(e){var o=this;this.login?t.i(c.f)({userId:t.i(d.a)(\"userId\"),productId:e}).then(function(t){o.EDIT_CART({productId:e})}):this.EDIT_CART({productId:e})},toCart:function(){this.$router.push({path:\"/cart\"})},navFixed:function(){if(\"/goods\"===this.$route.path||\"/home\"===this.$route.path||\"/goodsDetails\"===this.$route.path||\"/thanks\"===this.$route.path){var e=document.documentElement.scrollTop||document.body.scrollTop;this.st=e>=100;var o=document.querySelector(\".num\");this.positionL=o.getBoundingClientRect().left,this.positionT=o.getBoundingClientRect().top,this.ADD_ANIMATION({cartPositionL:this.positionL,cartPositionT:this.positionT})}},_loginOut:function(){var e={params:{token:this.token}};t.i(p.c)(e).then(function(e){t.i(d.c)(\"buyCart\"),window.location.href=\"/\"})},getPage:function(){\"/\"===this.$route.path||\"/home\"===this.$route.path?this.changePage(1):\"/goods\"===this.$route.path?this.changePage(2):\"/thanks\"===this.$route.path?this.changePage(3):this.changePage(4)}}),mounted:function(){this.token=t.i(d.a)(\"token\"),this.login?this._getCartList():this.INIT_BUYCART(),this.navFixed(),this.getPage(),window.addEventListener(\"scroll\",this.navFixed),window.addEventListener(\"resize\",this.navFixed),void 0!==l()(this.$route.query.key)&&(this.input=this.$route.query.key)},components:{YButton:n.a}}},212:function(e,o,t){e.exports={default:t(215),__esModule:!0}},213:function(e,o,t){e.exports={default:t(216),__esModule:!0}},214:function(e,o,t){\"use strict\";function A(e){return e&&e.__esModule?e:{default:e}}o.__esModule=!0;var l=t(213),i=A(l),r=t(212),a=A(r),n=\"function\"==typeof a.default&&\"symbol\"==typeof i.default?function(e){return typeof e}:function(e){return e&&\"function\"==typeof a.default&&e.constructor===a.default&&e!==a.default.prototype?\"symbol\":typeof e};o.default=\"function\"==typeof a.default&&\"symbol\"===n(i.default)?function(e){return void 0===e?\"undefined\":n(e)}:function(e){return e&&\"function\"==typeof a.default&&e.constructor===a.default&&e!==a.default.prototype?\"symbol\":void 0===e?\"undefined\":n(e)}},215:function(e,o,t){t(222),t(108),t(223),t(224),e.exports=t(3).Symbol},216:function(e,o,t){t(103),t(109),e.exports=t(204).f(\"iterator\")},217:function(e,o,t){var A=t(44),l=t(101),i=t(97);e.exports=function(e){var o=A(e),t=l.f;if(t)for(var r,a=t(e),n=i.f,s=0;a.length>s;)n.call(e,r=a[s++])&&o.push(r);return o}},218:function(e,o,t){var A=t(16);e.exports=Array.isArray||function(e){return\"Array\"==A(e)}},219:function(e,o,t){var A=t(45)(\"meta\"),l=t(12),i=t(15),r=t(11).f,a=0,n=Object.isExtensible||function(){return!0},s=!t(25)(function(){return n(Object.preventExtensions({}))}),c=function(e){r(e,A,{value:{i:\"O\"+ ++a,w:{}}})},p=function(e,o){if(!l(e))return\"symbol\"==typeof e?e:(\"string\"==typeof e?\"S\":\"P\")+e;if(!i(e,A)){if(!n(e))return\"F\";if(!o)return\"E\";c(e)}return e[A].i},d=function(e,o){if(!i(e,A)){if(!n(e))return!0;if(!o)return!1;c(e)}return e[A].w},B=function(e){return s&&b.NEED&&n(e)&&!i(e,A)&&c(e),e},b=e.exports={KEY:A,NEED:!1,fastKey:p,getWeak:d,onFreeze:B}},220:function(e,o,t){var A=t(97),l=t(41),i=t(24),r=t(102),a=t(15),n=t(104),s=Object.getOwnPropertyDescriptor;o.f=t(8)?s:function(e,o){if(e=i(e),o=r(o,!0),n)try{return s(e,o)}catch(e){}if(a(e,o))return l(!A.f.call(e,o),e[o])}},221:function(e,o,t){var A=t(24),l=t(205).f,i={}.toString,r=\"object\"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],a=function(e){try{return l(e)}catch(e){return r.slice()}};e.exports.f=function(e){return r&&\"[object Window]\"==i.call(e)?a(e):l(A(e))}},222:function(e,o,t){\"use strict\";var A=t(1),l=t(15),i=t(8),r=t(9),a=t(107),n=t(219).KEY,s=t(25),c=t(47),p=t(26),d=t(45),B=t(2),b=t(204),f=t(203),g=t(217),u=t(218),C=t(4),h=t(24),m=t(102),x=t(41),_=t(105),k=t(221),v=t(220),w=t(11),y=t(44),q=v.f,z=w.f,W=k.f,D=A.Symbol,Y=A.JSON,S=Y&&Y.stringify,U=B(\"_hidden\"),E=B(\"toPrimitive\"),Q={}.propertyIsEnumerable,O=c(\"symbol-registry\"),M=c(\"symbols\"),I=c(\"op-symbols\"),F=Object.prototype,G=\"function\"==typeof D,j=A.QObject,P=!j||!j.prototype||!j.prototype.findChild,X=i&&s(function(){return 7!=_(z({},\"a\",{get:function(){return z(this,\"a\",{value:7}).a}})).a})?function(e,o,t){var A=q(F,o);A&&delete F[o],z(e,o,t),A&&e!==F&&z(F,o,A)}:z,R=function(e){var o=M[e]=_(D.prototype);return o._k=e,o},T=G&&\"symbol\"==typeof D.iterator?function(e){return\"symbol\"==typeof e}:function(e){return e instanceof D},Z=function(e,o,t){return e===F&&Z(I,o,t),C(e),o=m(o,!0),C(t),l(M,o)?(t.enumerable?(l(e,U)&&e[U][o]&&(e[U][o]=!1),t=_(t,{enumerable:x(0,!1)})):(l(e,U)||z(e,U,x(1,{})),e[U][o]=!0),X(e,o,t)):z(e,o,t)},L=function(e,o){C(e);for(var t,A=g(o=h(o)),l=0,i=A.length;i>l;)Z(e,t=A[l++],o[t]);return e},N=function(e,o){return void 0===o?_(e):L(_(e),o)},K=function(e){var o=Q.call(this,e=m(e,!0));return!(this===F&&l(M,e)&&!l(I,e))&&(!(o||!l(this,e)||!l(M,e)||l(this,U)&&this[U][e])||o)},H=function(e,o){if(e=h(e),o=m(o,!0),e!==F||!l(M,o)||l(I,o)){var t=q(e,o);return!t||!l(M,o)||l(e,U)&&e[U][o]||(t.enumerable=!0),t}},$=function(e){for(var o,t=W(h(e)),A=[],i=0;t.length>i;)l(M,o=t[i++])||o==U||o==n||A.push(o);return A},V=function(e){for(var o,t=e===F,A=W(t?I:h(e)),i=[],r=0;A.length>r;)!l(M,o=A[r++])||t&&!l(F,o)||i.push(M[o]);return i};G||(D=function(){if(this instanceof D)throw TypeError(\"Symbol is not a constructor!\");var e=d(arguments.length>0?arguments[0]:void 0),o=function(t){this===F&&o.call(I,t),l(this,U)&&l(this[U],e)&&(this[U][e]=!1),X(this,e,x(1,t))};return i&&P&&X(F,e,{configurable:!0,set:o}),R(e)},a(D.prototype,\"toString\",function(){return this._k}),v.f=H,w.f=Z,t(205).f=k.f=$,t(97).f=K,t(101).f=V,i&&!t(43)&&a(F,\"propertyIsEnumerable\",K,!0),b.f=function(e){return R(B(e))}),r(r.G+r.W+r.F*!G,{Symbol:D});for(var J=\"hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables\".split(\",\"),ee=0;J.length>ee;)B(J[ee++]);for(var oe=y(B.store),te=0;oe.length>te;)f(oe[te++]);r(r.S+r.F*!G,\"Symbol\",{for:function(e){return l(O,e+=\"\")?O[e]:O[e]=D(e)},keyFor:function(e){if(!T(e))throw TypeError(e+\" is not a symbol!\");for(var o in O)if(O[o]===e)return o},useSetter:function(){P=!0},useSimple:function(){P=!1}}),r(r.S+r.F*!G,\"Object\",{create:N,defineProperty:Z,defineProperties:L,getOwnPropertyDescriptor:H,getOwnPropertyNames:$,getOwnPropertySymbols:V}),Y&&r(r.S+r.F*(!G||s(function(){var e=D();return\"[null]\"!=S([e])||\"{}\"!=S({a:e})||\"{}\"!=S(Object(e))})),\"JSON\",{stringify:function(e){if(void 0!==e&&!T(e)){for(var o,t,A=[e],l=1;arguments.length>l;)A.push(arguments[l++]);return o=A[1],\"function\"==typeof o&&(t=o),!t&&u(o)||(o=function(e,o){if(t&&(o=t.call(this,e,o)),!T(o))return o}),A[1]=o,S.apply(Y,A)}}}),D.prototype[E]||t(10)(D.prototype,E,D.prototype.valueOf),p(D,\"Symbol\"),p(Math,\"Math\",!0),p(A.JSON,\"JSON\",!0)},223:function(e,o,t){t(203)(\"asyncIterator\")},224:function(e,o,t){t(203)(\"observable\")},225:function(e,o,t){o=e.exports=t(163)(!0),o.push([e.i,'.el-breadcrumb:after,.el-breadcrumb:before,.el-button-group:after,.el-button-group:before,.el-form-item:after,.el-form-item:before,.el-form-item__content:after,.el-form-item__content:before{display:table;content:\"\"}.el-checkbox-button__original,.el-pagination--small .arrow.disabled,.el-table--hidden,.el-table .hidden-columns,.el-table td.is-hidden>*,.el-table th.is-hidden>*{visibility:hidden}.el-breadcrumb:after,.el-button-group:after,.el-form-item:after,.el-form-item__content:after{clear:both}.el-autocomplete-suggestion.is-loading li:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-dialog__header:after,.el-dialog__header:before{display:table;content:\"\"}.el-dialog__header:after{clear:both}@font-face{font-family:element-icons;src:url('+t(166)+') format(\"woff\"),url('+t(165)+') format(\"truetype\");font-weight:400;font-style:normal}[class*=\" el-icon-\"],[class^=el-icon-]{font-family:element-icons!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;vertical-align:baseline;display:inline-block;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-icon-arrow-down:before{content:\"\\\\E600\"}.el-icon-arrow-left:before{content:\"\\\\E601\"}.el-icon-arrow-right:before{content:\"\\\\E602\"}.el-icon-arrow-up:before{content:\"\\\\E603\"}.el-icon-caret-bottom:before{content:\"\\\\E604\"}.el-icon-caret-left:before{content:\"\\\\E605\"}.el-icon-caret-right:before{content:\"\\\\E606\"}.el-icon-caret-top:before{content:\"\\\\E607\"}.el-icon-check:before{content:\"\\\\E608\"}.el-icon-circle-check:before{content:\"\\\\E609\"}.el-icon-circle-close:before{content:\"\\\\E60A\"}.el-icon-circle-cross:before{content:\"\\\\E60B\"}.el-icon-close:before{content:\"\\\\E60C\"}.el-icon-upload:before{content:\"\\\\E60D\"}.el-icon-d-arrow-left:before{content:\"\\\\E60E\"}.el-icon-d-arrow-right:before{content:\"\\\\E60F\"}.el-icon-d-caret:before{content:\"\\\\E610\"}.el-icon-date:before{content:\"\\\\E611\"}.el-icon-delete:before{content:\"\\\\E612\"}.el-icon-document:before{content:\"\\\\E613\"}.el-icon-edit:before{content:\"\\\\E614\"}.el-icon-information:before{content:\"\\\\E615\"}.el-icon-loading:before{content:\"\\\\E616\"}.el-icon-menu:before{content:\"\\\\E617\"}.el-icon-message:before{content:\"\\\\E618\"}.el-icon-minus:before{content:\"\\\\E619\"}.el-icon-more:before{content:\"\\\\E61A\"}.el-icon-picture:before{content:\"\\\\E61B\"}.el-icon-plus:before{content:\"\\\\E61C\"}.el-icon-search:before{content:\"\\\\E61D\"}.el-icon-setting:before{content:\"\\\\E61E\"}.el-icon-share:before{content:\"\\\\E61F\"}.el-icon-star-off:before{content:\"\\\\E620\"}.el-icon-star-on:before{content:\"\\\\E621\"}.el-icon-time:before{content:\"\\\\E622\"}.el-icon-warning:before{content:\"\\\\E623\"}.el-icon-delete2:before{content:\"\\\\E624\"}.el-icon-upload2:before{content:\"\\\\E627\"}.el-icon-view:before{content:\"\\\\E626\"}.el-icon-loading{animation:rotating 1s linear infinite}.el-icon--right{margin-left:5px}.el-icon--left{margin-right:5px}@keyframes rotating{0%{transform:rotate(0)}to{transform:rotate(1turn)}}.el-pagination{white-space:nowrap;padding:2px 5px;color:#48576a}.el-pagination:after,.el-pagination:before{display:table;content:\"\"}.el-pagination:after{clear:both}.el-pagination button,.el-pagination span{display:inline-block;font-size:13px;min-width:28px;height:28px;line-height:28px;vertical-align:top;box-sizing:border-box}.el-pagination .el-select .el-input{width:110px}.el-pagination .el-select .el-input input{padding-right:25px;border-radius:2px;height:28px}.el-pagination button{border:none;padding:0 6px;background:0 0}.el-pagination button:focus{outline:0}.el-pagination button:hover{color:#20a0ff}.el-pagination button.disabled{color:#e4e4e4;background-color:#fff;cursor:not-allowed}.el-pager li,.el-pager li.btn-quicknext:hover,.el-pager li.btn-quickprev:hover{cursor:pointer}.el-pagination .btn-next,.el-pagination .btn-prev{background:50% no-repeat #fff;background-size:16px;border:1px solid #d1dbe5;cursor:pointer;margin:0;color:#97a8be}.el-pagination .btn-next .el-icon,.el-pagination .btn-prev .el-icon{display:block;font-size:12px}.el-pagination .btn-prev{border-radius:2px 0 0 2px;border-right:0}.el-pagination .btn-next{border-radius:0 2px 2px 0;border-left:0}.el-pagination--small .btn-next,.el-pagination--small .btn-prev,.el-pagination--small .el-pager li,.el-pagination--small .el-pager li:last-child{border-color:transparent;font-size:12px;line-height:22px;height:22px;min-width:22px}.el-pagination--small .el-pager li{border-radius:2px}.el-pagination__sizes{margin:0 10px 0 0}.el-pagination__sizes .el-input .el-input__inner{font-size:13px;border-color:#d1dbe5}.el-pagination__sizes .el-input .el-input__inner:hover{border-color:#20a0ff}.el-pagination__jump{margin-left:10px}.el-pagination__total{margin:0 10px}.el-pagination__rightwrapper{float:right}.el-pagination__editor{border:1px solid #d1dbe5;border-radius:2px;line-height:18px;padding:4px 2px;width:30px;text-align:center;margin:0 6px;box-sizing:border-box;transition:border .3s;-moz-appearance:textfield}.el-pager,.el-pager li{vertical-align:top;display:inline-block;margin:0}.el-pagination__editor::-webkit-inner-spin-button,.el-pagination__editor::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.el-pagination__editor:focus{outline:0;border-color:#20a0ff}.el-autocomplete-suggestion__wrap,.el-pager li{border:1px solid #d1dbe5;box-sizing:border-box}.el-pager{-moz-user-select:none;user-select:none;list-style:none;font-size:0;padding:0}.el-date-table,.el-pager,.el-radio{-webkit-user-select:none;-ms-user-select:none}.el-date-table,.el-radio,.el-time-panel{-moz-user-select:none}.el-pager li{padding:0 4px;border-right:0;background:#fff;font-size:13px;min-width:28px;height:28px;line-height:28px;text-align:center}.el-pager li:last-child{border-right:1px solid #d1dbe5}.el-pager li.btn-quicknext,.el-pager li.btn-quickprev{line-height:28px;color:#97a8be}.el-pager li.active+li{border-left:0;padding-left:5px}.el-pager li:hover{color:#20a0ff}.el-pager li.active{border-color:#20a0ff;background-color:#20a0ff;color:#fff;cursor:default}.el-dialog{position:absolute;left:50%;-ms-transform:translateX(-50%);transform:translateX(-50%);background:#fff;border-radius:2px;box-shadow:0 1px 3px rgba(0,0,0,.3);box-sizing:border-box;margin-bottom:50px}.el-dialog--tiny{width:30%}.el-dialog--small{width:50%}.el-dialog--large{width:90%}.el-dialog--full{width:100%;top:0;margin-bottom:0;height:100%;overflow:auto}.el-dialog__wrapper{top:0;right:0;bottom:0;left:0;position:fixed;overflow:auto;margin:0}.el-autocomplete,.el-dropdown{display:inline-block;position:relative}.el-dialog__header{padding:20px 20px 0}.el-dialog__headerbtn{float:right;background:0 0;border:none;outline:0;padding:0;cursor:pointer;font-size:16px}.el-dialog__headerbtn .el-dialog__close{color:#bfcbd9}.el-dialog__headerbtn:focus .el-dialog__close,.el-dialog__headerbtn:hover .el-dialog__close{color:#20a0ff}.el-dialog__title{line-height:1;font-size:16px;font-weight:700;color:#1f2d3d}.el-dialog__body{padding:30px 20px;color:#48576a;font-size:14px}.el-dialog__footer{padding:10px 20px 15px;text-align:right;box-sizing:border-box}.dialog-fade-enter-active{animation:dialog-fade-in .3s}.dialog-fade-leave-active{animation:dialog-fade-out .3s}@keyframes dialog-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}to{transform:translateZ(0);opacity:1}}@keyframes dialog-fade-out{0%{transform:translateZ(0);opacity:1}to{transform:translate3d(0,-20px,0);opacity:0}}.el-autocomplete-suggestion{margin:5px 0;box-shadow:0 0 6px 0 rgba(0,0,0,.04),0 2px 4px 0 rgba(0,0,0,.12)}.el-autocomplete-suggestion li{list-style:none;line-height:36px;padding:0 10px;margin:0;cursor:pointer;color:#48576a;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-autocomplete-suggestion li:hover{background-color:#e4e8f1}.el-autocomplete-suggestion li.highlighted{background-color:#20a0ff;color:#fff}.el-autocomplete-suggestion li:active{background-color:#0082e6}.el-autocomplete-suggestion.is-loading li:hover,.el-dropdown-menu{background-color:#fff}.el-autocomplete-suggestion li.divider{margin-top:6px;border-top:1px solid #d1dbe5}.el-autocomplete-suggestion li.divider:last-child{margin-bottom:-6px}.el-autocomplete-suggestion.is-loading li{text-align:center;height:100px;line-height:100px;font-size:20px;color:#999}.el-autocomplete-suggestion.is-loading .el-icon-loading{vertical-align:middle}.el-autocomplete-suggestion__wrap{max-height:280px;overflow:auto;background-color:#fff;padding:6px 0;border-radius:2px}.el-autocomplete-suggestion__list{margin:0;padding:0}.el-dropdown{color:#48576a;font-size:14px}.el-dropdown .el-button-group{display:block}.el-dropdown .el-button-group .el-button{float:none}.el-dropdown .el-dropdown__caret-button{padding-right:5px;padding-left:5px}.el-dropdown .el-dropdown__caret-button .el-dropdown__icon{padding-left:0}.el-dropdown__icon{font-size:12px;margin:0 3px}.el-dropdown-menu{margin:5px 0;border:1px solid #d1dbe5;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.12);padding:6px 0;z-index:10;position:absolute;top:0;left:0;min-width:100px}.el-dropdown-menu__item{list-style:none;line-height:36px;padding:0 10px;margin:0;cursor:pointer}.el-dropdown-menu__item:not(.is-disabled):hover{background-color:#e4e8f1;color:#48576a}.el-dropdown-menu__item.is-disabled{cursor:default;color:#bfcbd9;pointer-events:none}.el-dropdown-menu__item--divided{position:relative;margin-top:6px;border-top:1px solid #d1dbe5}.el-dropdown-menu__item--divided:before{content:\"\";height:6px;display:block;margin:0 -10px;background-color:#fff}.el-menu-item,.el-submenu__title{height:56px;line-height:56px;font-size:14px;color:#48576a;padding:0 20px;cursor:pointer;position:relative;transition:border-color .3s,background-color .3s,color .3s;box-sizing:border-box;white-space:nowrap}.el-menu{border-radius:2px;list-style:none;position:relative;margin:0;padding-left:0;background-color:#eef1f6}.el-menu:after,.el-menu:before{display:table;content:\"\"}.el-menu:after{clear:both}.el-menu li{list-style:none}.el-menu--dark{background-color:#324157}.el-menu--dark .el-menu-item,.el-menu--dark .el-submenu__title{color:#bfcbd9}.el-menu--dark .el-menu-item:hover,.el-menu--dark .el-submenu__title:hover{background-color:#48576a}.el-menu--dark .el-submenu .el-menu{background-color:#1f2d3d}.el-menu--dark .el-submenu .el-menu .el-menu-item:hover{background-color:#48576a}.el-menu--horizontal .el-menu-item{float:left;height:60px;line-height:60px;margin:0;cursor:pointer;position:relative;box-sizing:border-box;border-bottom:5px solid transparent}.el-menu--horizontal .el-menu-item a,.el-menu--horizontal .el-menu-item a:hover{color:inherit}.el-menu--horizontal .el-submenu{float:left;position:relative}.el-menu--horizontal .el-submenu>.el-menu{position:absolute;top:65px;left:0;border:1px solid #d1dbe5;padding:5px 0;background-color:#fff;z-index:100;min-width:100%;box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.el-menu--horizontal .el-submenu .el-submenu__title{height:60px;line-height:60px;border-bottom:5px solid transparent}.el-menu--horizontal .el-submenu .el-menu-item{background-color:#fff;float:none;height:36px;line-height:36px;padding:0 10px}.el-menu--horizontal .el-submenu .el-submenu__icon-arrow{position:static;vertical-align:middle;margin-left:5px;color:#97a8be;margin-top:-3px}.el-menu--horizontal .el-menu-item:hover,.el-menu--horizontal .el-submenu__title:hover{background-color:#eef1f6}.el-menu--horizontal>.el-menu-item:hover,.el-menu--horizontal>.el-submenu.is-active .el-submenu__title,.el-menu--horizontal>.el-submenu:hover .el-submenu__title{border-bottom:5px solid #20a0ff}.el-menu--horizontal.el-menu--dark .el-menu-item:hover,.el-menu--horizontal.el-menu--dark .el-submenu__title:hover{background-color:#324157}.el-menu--horizontal.el-menu--dark .el-submenu .el-menu-item:hover,.el-menu--horizontal.el-menu--dark .el-submenu .el-submenu-title:hover,.el-menu-item:hover{background-color:#d1dbe5}.el-menu--horizontal.el-menu--dark .el-submenu .el-menu-item,.el-menu--horizontal.el-menu--dark .el-submenu .el-submenu-title{color:#48576a}.el-menu--horizontal.el-menu--dark .el-submenu .el-menu-item.is-active,.el-menu-item.is-active{color:#20a0ff}.el-menu--collapse{width:64px}.el-menu--collapse>.el-menu-item [class^=el-icon-],.el-menu--collapse>.el-submenu>.el-submenu__title [class^=el-icon-]{margin:0;vertical-align:middle;width:24px;text-align:center}.el-menu--collapse>.el-menu-item .el-submenu__icon-arrow,.el-menu--collapse>.el-submenu>.el-submenu__title .el-submenu__icon-arrow{display:none}.el-menu--collapse>.el-menu-item span,.el-menu--collapse>.el-submenu>.el-submenu__title span{height:0;width:0;overflow:hidden;visibility:hidden;display:inline-block}.el-menu--collapse .el-submenu{position:relative}.el-menu--collapse .el-submenu .el-menu{position:absolute;margin-left:5px;top:0;left:100%;z-index:10}.el-menu--collapse .el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{-ms-transform:none;transform:none}.el-menu-item [class^=el-icon-]{margin-right:5px;width:24px;text-align:center}.el-menu-item *{vertical-align:middle}.el-menu-item:first-child{margin-left:0}.el-menu-item:last-child{margin-right:0}.el-submenu [class^=el-icon-]{vertical-align:middle;margin-right:5px;width:24px;text-align:center}.el-submenu .el-menu{background-color:#e4e8f1}.el-submenu .el-menu-item:hover,.el-submenu__title:hover{background-color:#d1dbe5}.el-submenu .el-menu-item{height:50px;line-height:50px;padding:0 45px;min-width:200px}.el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{-ms-transform:rotate(180deg);transform:rotate(180deg)}.el-submenu.is-active .el-submenu__title{border-bottom-color:#20a0ff}.el-submenu__title{position:relative}.el-submenu__title *{vertical-align:middle}.el-submenu__icon-arrow{position:absolute;top:50%;right:20px;margin-top:-7px;transition:transform .3s;font-size:12px}.el-radio,.el-radio__inner,.el-radio__input{position:relative;display:inline-block}.el-menu-item-group>ul{padding:0}.el-menu-item-group__title{padding-top:15px;line-height:normal;font-size:14px;padding-left:20px;color:#97a8be}.el-radio-button__inner,.el-radio-group,.el-radio__input{line-height:1;vertical-align:middle}.horizontal-collapse-transition .el-submenu__title .el-submenu__icon-arrow{transition:.2s;opacity:0}.el-radio{color:#1f2d3d;cursor:pointer;white-space:nowrap}.el-radio+.el-radio{margin-left:15px}.el-radio__input{white-space:nowrap;cursor:pointer;outline:0}.el-radio__input.is-focus .el-radio__inner{border-color:#20a0ff}.el-radio__input.is-checked .el-radio__inner{border-color:#20a0ff;background:#20a0ff}.el-radio__input.is-checked .el-radio__inner:after{-ms-transform:translate(-50%,-50%) scale(1);transform:translate(-50%,-50%) scale(1)}.el-radio__input.is-disabled .el-radio__inner{background-color:#eef1f6;border-color:#d1dbe5;cursor:not-allowed}.el-radio__input.is-disabled .el-radio__inner:after{cursor:not-allowed;background-color:#eef1f6}.el-radio__input.is-disabled .el-radio__inner+.el-radio__label{cursor:not-allowed}.el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:#d1dbe5;border-color:#d1dbe5}.el-radio__inner,.el-radio__input.is-disabled.is-checked .el-radio__inner:after{background-color:#fff}.el-radio__input.is-disabled+.el-radio__label{color:#bbb;cursor:not-allowed}.el-radio__inner{border:1px solid #bfcbd9;width:18px;height:18px;border-radius:50%;cursor:pointer;box-sizing:border-box}.el-radio__inner:hover{border-color:#20a0ff}.el-radio__inner:after{width:6px;height:6px;border-radius:50%;background-color:#fff;content:\"\";position:absolute;left:50%;top:50%;-ms-transform:translate(-50%,-50%) scale(0);transform:translate(-50%,-50%) scale(0);transition:transform .15s cubic-bezier(.71,-.46,.88,.6)}.el-switch__core,.el-switch__label{width:46px;height:22px;cursor:pointer}.el-radio__original{opacity:0;outline:0;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.el-radio-button,.el-radio-button__inner{position:relative;display:inline-block}.el-radio__label{font-size:14px;padding-left:5px}.el-radio-group{display:inline-block;font-size:0}.el-radio-group .el-radio{font-size:14px}.el-radio-button:first-child .el-radio-button__inner{border-left:1px solid #bfcbd9;border-radius:4px 0 0 4px;box-shadow:none!important}.el-radio-button:last-child .el-radio-button__inner{border-radius:0 4px 4px 0}.el-radio-button:first-child:last-child .el-radio-button__inner{border-radius:4px}.el-radio-button__inner{white-space:nowrap;background:#fff;border:1px solid #bfcbd9;border-left:0;color:#1f2d3d;-webkit-appearance:none;text-align:center;box-sizing:border-box;outline:0;margin:0;cursor:pointer;transition:all .3s cubic-bezier(.645,.045,.355,1);padding:10px 15px;font-size:14px;border-radius:0}.el-radio-button__inner:hover{color:#20a0ff}.el-radio-button__inner [class*=el-icon-]{line-height:.9}.el-radio-button__inner [class*=el-icon-]+span{margin-left:5px}.el-radio-button__orig-radio{opacity:0;outline:0;position:absolute;z-index:-1;left:-999px}.el-radio-button__orig-radio:checked+.el-radio-button__inner{color:#fff;background-color:#20a0ff;border-color:#20a0ff;box-shadow:-1px 0 0 0 #20a0ff}.el-radio-button__orig-radio:disabled+.el-radio-button__inner{color:#bfcbd9;cursor:not-allowed;background-image:none;background-color:#eef1f6;border-color:#d1dbe5;box-shadow:none}.el-radio-button--large .el-radio-button__inner{padding:11px 19px;font-size:16px;border-radius:0}.el-radio-button--small .el-radio-button__inner{padding:7px 9px;font-size:12px;border-radius:0}.el-radio-button--mini .el-radio-button__inner{padding:4px;font-size:12px;border-radius:0}.el-switch{display:inline-block;position:relative;font-size:14px;line-height:22px;height:22px;vertical-align:middle}.el-switch__label,.el-switch__label *{position:absolute;font-size:14px;display:inline-block}.el-switch .label-fade-enter,.el-switch .label-fade-leave-active{opacity:0}.el-switch.is-disabled .el-switch__core{border-color:#e4e8f1!important;background:#e4e8f1!important}.el-switch.is-disabled .el-switch__core span{background-color:#fbfdff!important}.el-switch.is-disabled .el-switch__core~.el-switch__label *{color:#fbfdff!important}.el-switch.is-checked .el-switch__core{border-color:#20a0ff;background-color:#20a0ff}.el-switch.is-disabled .el-switch__core,.el-switch.is-disabled .el-switch__label{cursor:not-allowed}.el-switch__label{transition:.2s;left:0;top:0}.el-switch__label *{line-height:1;top:4px;color:#fff}.el-switch__label--left i{left:6px}.el-switch__label--right i{right:6px}.el-switch__input{display:none}.el-switch__core{margin:0;display:inline-block;position:relative;border:1px solid #bfcbd9;outline:0;border-radius:12px;box-sizing:border-box;background:#bfcbd9;transition:border-color .3s,background-color .3s}.el-switch__core .el-switch__button{top:0;left:0;position:absolute;border-radius:100%;transition:transform .3s;width:16px;height:16px;background-color:#fff}.el-switch--wide .el-switch__label.el-switch__label--left span{left:10px}.el-switch--wide .el-switch__label.el-switch__label--right span{right:10px}.el-select-dropdown{position:absolute;z-index:1001;border:1px solid #d1dbe5;border-radius:2px;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);box-sizing:border-box;margin:5px 0}.el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list{padding:0}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected{color:#20a0ff;background-color:#fff}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover,.el-select-dropdown__item.hover,.el-select-dropdown__item:hover{background-color:#e4e8f1}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected:after{position:absolute;right:10px;font-family:element-icons;content:\"\\\\E608\";font-size:11px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-select-dropdown__empty{padding:10px 0;margin:0;text-align:center;color:#999;font-size:14px}.el-select-dropdown__wrap{max-height:274px}.el-select-dropdown__list{list-style:none;padding:6px 0;margin:0;box-sizing:border-box}.el-select-dropdown__item{font-size:14px;padding:8px 10px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#48576a;height:36px;line-height:1.5;box-sizing:border-box;cursor:pointer}.el-select-dropdown__item.selected{color:#fff;background-color:#20a0ff}.el-select-dropdown__item.selected.hover{background-color:#1c8de0}.el-select-dropdown__item span{line-height:1.5!important}.el-select-dropdown__item.is-disabled{color:#bfcbd9;cursor:not-allowed}.el-select-dropdown__item.is-disabled:hover{background-color:#fff}.el-select-group{margin:0;padding:0}.el-select-group .el-select-dropdown__item{padding-left:20px}.el-select-group__wrap{list-style:none;margin:0;padding:0}.el-select-group__title{padding-left:10px;font-size:12px;color:#999;height:30px;line-height:30px}.el-select{display:inline-block;position:relative}.el-select:hover .el-input__inner{border-color:#8391a5}.el-select .el-input__inner{cursor:pointer;padding-right:35px}.el-select .el-input__inner:focus{border-color:#20a0ff}.el-select .el-input .el-input__icon{font-size:12px;transition:transform .3s;line-height:16px;top:50%;cursor:pointer}.el-select .el-input .el-input__icon,.el-select .el-input .el-input__icon.is-show-close{color:#bfcbd9;-ms-transform:translateY(-50%) rotate(180deg);transform:translateY(-50%) rotate(180deg)}.el-select .el-input .el-input__icon.is-show-close{transition:0s;width:16px;height:16px;font-size:14px;right:8px;text-align:center;border-radius:100%}.el-select .el-input .el-input__icon.is-show-close:hover{color:#97a8be}.el-select .el-input .el-input__icon.is-reverse{-ms-transform:translateY(-50%);transform:translateY(-50%)}.el-select .el-input.is-disabled .el-input__inner{cursor:not-allowed}.el-select .el-input.is-disabled .el-input__inner:hover{border-color:#d1dbe5}.el-select>.el-input{display:block}.el-select .el-tag__close{margin-top:-2px}.el-select .el-tag{height:24px;line-height:24px;box-sizing:border-box;margin:3px 0 3px 6px}.el-select__input{border:none;outline:0;padding:0;margin-left:10px;color:#666;font-size:14px;vertical-align:baseline;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:28px;background-color:transparent}.el-select__input.is-mini{height:14px}.el-select__close{cursor:pointer;position:absolute;top:8px;z-index:1000;right:25px;color:#bfcbd9;line-height:18px;font-size:12px}.el-select__close:hover{color:#97a8be}.el-select__tags{position:absolute;line-height:normal;white-space:normal;z-index:1;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%)}.el-table,.el-table td,.el-table th{box-sizing:border-box;position:relative}.el-select__tag{display:inline-block;height:24px;line-height:24px;font-size:14px;border-radius:4px;color:#fff;background-color:#20a0ff}.el-select__tag .el-icon-close{font-size:12px}.el-table{overflow:hidden;width:100%;max-width:100%;background-color:#fff;border:1px solid #dfe6ec;font-size:14px;color:#1f2d3d}.el-table .el-tooltip.cell{white-space:nowrap;min-width:50px}.el-table td,.el-table th{height:40px;min-width:0;text-overflow:ellipsis;vertical-align:middle}.el-table:after,.el-table:before{content:\"\";position:absolute;background-color:#dfe6ec;z-index:1}.el-table td.is-right,.el-table th.is-right{text-align:right}.el-table td.is-left,.el-table th.is-left{text-align:left}.el-table td.is-center,.el-table th.is-center{text-align:center}.el-table td,.el-table th.is-leaf{border-bottom:1px solid #dfe6ec}.el-table td.gutter,.el-table th.gutter{width:15px;border-right-width:0;border-bottom-width:0;padding:0}.el-table .cell,.el-table th>div{padding-left:18px;padding-right:18px;box-sizing:border-box;text-overflow:ellipsis}.el-table:before{left:0;bottom:0;width:100%;height:1px}.el-table:after{top:0;right:0;width:1px;height:100%}.el-table .caret-wrapper,.el-table th>.cell{position:relative;display:inline-block;vertical-align:middle}.el-table th{white-space:nowrap;overflow:hidden;background-color:#eef1f6;text-align:left}.el-table th.is-sortable{cursor:pointer}.el-table th>div{display:inline-block;line-height:40px;overflow:hidden;white-space:nowrap}.el-table td>div{box-sizing:border-box}.el-table th.required>div:before{display:inline-block;content:\"\";width:8px;height:8px;border-radius:50%;background:#ff4d51;margin-right:5px;vertical-align:middle}.el-table th>.cell{word-wrap:normal;text-overflow:ellipsis;line-height:30px;width:100%;box-sizing:border-box}.el-table th>.cell.highlight{color:#20a0ff}.el-table .caret-wrapper{cursor:pointer;margin-left:5px;margin-top:-2px;width:16px;height:30px;overflow:visible;overflow:initial}.el-table .cell,.el-table__footer-wrapper,.el-table__header-wrapper{overflow:hidden}.el-table .sort-caret{display:inline-block;width:0;height:0;border:0;content:\"\";position:absolute;left:3px;z-index:2}.el-table .sort-caret.ascending,.el-table .sort-caret.descending{border-right:5px solid transparent;border-left:5px solid transparent}.el-table .sort-caret.ascending{top:9px;border-top:none;border-bottom:5px solid #97a8be}.el-table .sort-caret.descending{bottom:9px;border-top:5px solid #97a8be;border-bottom:none}.el-table .ascending .sort-caret.ascending{border-bottom-color:#48576a}.el-table .descending .sort-caret.descending{border-top-color:#48576a}.el-table td.gutter{width:0}.el-table .cell{white-space:normal;word-break:break-all;line-height:24px}.el-badge__content,.el-message__group p,.el-progress-bar__inner,.el-steps.is-horizontal,.el-tabs__nav,.el-tag,.el-time-spinner,.el-tree-node,.el-upload-list__item-name{white-space:nowrap}.el-table tr input[type=checkbox]{margin:0}.el-table tr{background-color:#fff}.el-table .hidden-columns{position:absolute;z-index:-1}.el-table__empty-block{position:relative;min-height:60px;text-align:center;width:100%;height:100%}.el-table__empty-text{position:absolute;left:50%;top:50%;-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#5e7382}.el-table__expand-column .cell{padding:0;text-align:center}.el-table__expand-icon{position:relative;cursor:pointer;color:#666;font-size:12px;transition:transform .2s ease-in-out;height:40px}.el-table__expand-icon>.el-icon{position:absolute;left:50%;top:50%;margin-left:-5px;margin-top:-5px}.el-table__expand-icon--expanded{-ms-transform:rotate(90deg);transform:rotate(90deg)}.el-table__expanded-cell{padding:20px 50px;background-color:#fbfdff;box-shadow:inset 0 2px 0 #f4f4f4}.el-table__expanded-cell:hover{background-color:#fbfdff!important}.el-table--fit{border-right:0;border-bottom:0}.el-table--border th,.el-table__fixed-right-patch{border-bottom:1px solid #dfe6ec}.el-table--fit td.gutter,.el-table--fit th.gutter{border-right-width:1px}.el-table--border td,.el-table--border th{border-right:1px solid #dfe6ec}.el-table__fixed,.el-table__fixed-right{position:absolute;top:0;left:0;box-shadow:1px 0 8px #d3d4d6;overflow-x:hidden}.el-table__fixed-right:before,.el-table__fixed:before{content:\"\";position:absolute;left:0;bottom:0;width:100%;height:1px;background-color:#dfe6ec;z-index:4}.el-table__fixed-right-patch{position:absolute;top:-1px;right:0;background-color:#eef1f6}.el-table__fixed-right{top:0;left:auto;right:0;box-shadow:-1px 0 8px #d3d4d6}.el-table__fixed-right .el-table__fixed-body-wrapper,.el-table__fixed-right .el-table__fixed-footer-wrapper,.el-table__fixed-right .el-table__fixed-header-wrapper{left:auto;right:0}.el-table__fixed-header-wrapper{position:absolute;left:0;top:0;z-index:3}.el-table__fixed-header-wrapper thead div{background-color:#eef1f6;color:#1f2d3d}.el-table__fixed-footer-wrapper{position:absolute;left:0;bottom:0;z-index:3}.el-table__fixed-footer-wrapper tbody td{border-top:1px solid #dfe6ec;background-color:#fbfdff;color:#1f2d3d}.el-table__fixed-body-wrapper{position:absolute;left:0;top:37px;overflow:hidden;z-index:3}.el-table__body-wrapper,.el-table__footer-wrapper,.el-table__header-wrapper{width:100%}.el-table__footer-wrapper{margin-top:-1px}.el-table__footer-wrapper td{border-top:1px solid #dfe6ec}.el-table__body,.el-table__footer,.el-table__header{table-layout:fixed}.el-table__footer-wrapper thead div,.el-table__header-wrapper thead div{background-color:#eef1f6;color:#1f2d3d}.el-table__footer-wrapper tbody td,.el-table__header-wrapper tbody td{background-color:#fbfdff;color:#1f2d3d}.el-table__body-wrapper{overflow:auto;position:relative}.el-table--striped .el-table__body tr.el-table__row--striped td{background:#fafafa;background-clip:padding-box}.el-table--striped .el-table__body tr.el-table__row--striped.current-row td{background:#edf7ff}.el-table__body tr.hover-row.current-row>td,.el-table__body tr.hover-row.el-table__row--striped.current-row>td,.el-table__body tr.hover-row.el-table__row--striped>td,.el-table__body tr.hover-row>td{background-color:#eef1f6}.el-table__body tr.current-row>td{background:#edf7ff}.el-table__column-resize-proxy{position:absolute;left:200px;top:0;bottom:0;width:0;border-left:1px solid #dfe6ec;z-index:10}.el-table__column-filter-trigger{display:inline-block;line-height:34px;margin-left:5px;cursor:pointer}.el-table__column-filter-trigger i{color:#97a8be}.el-table--enable-row-transition .el-table__body td{transition:background-color .25s ease}.el-fade-in-linear-enter-active,.el-fade-in-linear-leave-active,.fade-in-linear-enter-active,.fade-in-linear-leave-active{transition:opacity .2s linear}.el-table--enable-row-hover .el-table__body tr:hover>td{background-color:#eef1f6;background-clip:padding-box}.el-table--fluid-height .el-table__fixed,.el-table--fluid-height .el-table__fixed-right{bottom:0;overflow:hidden}.el-table-column--selection .cell{padding-left:14px;padding-right:14px}.el-table-filter{border:1px solid #d1dbe5;border-radius:2px;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.12);box-sizing:border-box;margin:2px 0}.el-table-filter__list{padding:5px 0;margin:0;list-style:none;min-width:100px}.el-table-filter__list-item{line-height:36px;padding:0 10px;cursor:pointer;font-size:14px}.el-table-filter__list-item:hover{background-color:#e4e8f1;color:#48576a}.el-table-filter__list-item.is-active{background-color:#20a0ff;color:#fff}.el-table-filter__content{min-width:100px}.el-table-filter__bottom{border-top:1px solid #d1dbe5;padding:8px}.el-table-filter__bottom button{background:0 0;border:none;color:#8391a5;cursor:pointer;font-size:14px;padding:0 3px}.el-table-filter__bottom button:hover{color:#20a0ff}.el-table-filter__bottom button:focus{outline:0}.el-table-filter__bottom button.is-disabled{color:#bfcbd9;cursor:not-allowed}.el-table-filter__checkbox-group{padding:10px}.el-table-filter__checkbox-group label.el-checkbox{display:block;margin-bottom:8px;margin-left:5px}.el-table-filter__checkbox-group .el-checkbox:last-child{margin-bottom:0}.el-date-table{font-size:12px;min-width:224px;user-select:none}.el-date-table td{width:32px;height:32px;box-sizing:border-box;text-align:center;cursor:pointer}.el-date-table td.next-month,.el-date-table td.prev-month{color:#ddd}.el-date-table td.today{color:#20a0ff;position:relative}.el-date-table td.today:before{content:\" \";position:absolute;top:0;right:0;width:0;height:0;border-top:.5em solid #20a0ff;border-left:.5em solid transparent}.el-month-table td .cell,.el-year-table td .cell{width:48px;height:32px;display:block;line-height:32px}.el-date-table td.available:hover{background-color:#e4e8f1}.el-date-table td.in-range{background-color:#d2ecff}.el-date-table td.in-range:hover{background-color:#afddff}.el-date-table td.current:not(.disabled),.el-date-table td.end-date,.el-date-table td.start-date{background-color:#20a0ff!important;color:#fff}.el-date-table td.disabled{background-color:#f4f4f4;opacity:1;cursor:not-allowed;color:#ccc}.el-fade-in-enter,.el-fade-in-leave-active,.el-fade-in-linear-enter,.el-fade-in-linear-leave,.el-fade-in-linear-leave-active,.fade-in-linear-enter,.fade-in-linear-leave,.fade-in-linear-leave-active{opacity:0}.el-date-table td.week{font-size:80%;color:#8391a5}.el-month-table,.el-year-table{font-size:12px;margin:-1px;border-collapse:collapse}.el-date-table th{padding:5px;color:#8391a5;font-weight:400}.el-date-table.is-week-mode .el-date-table__row:hover{background-color:#e4e8f1}.el-date-table.is-week-mode .el-date-table__row.current{background-color:#d2ecff}.el-month-table td{text-align:center;padding:20px 3px;cursor:pointer}.el-month-table td .cell{color:#48576a}.el-month-table td .cell:hover{background-color:#e4e8f1}.el-month-table td.disabled .cell{background-color:#f4f4f4;cursor:not-allowed;color:#ccc}.el-month-table td.current:not(.disabled) .cell{background-color:#20a0ff!important;color:#fff}.el-year-table .el-icon{color:#97a8be}.el-year-table td{text-align:center;padding:20px 3px;cursor:pointer}.el-year-table td .cell{color:#48576a}.el-year-table td .cell:hover{background-color:#e4e8f1}.el-year-table td.disabled .cell{background-color:#f4f4f4;cursor:not-allowed;color:#ccc}.el-year-table td.current:not(.disabled) .cell{background-color:#20a0ff!important;color:#fff}.el-date-range-picker{min-width:520px}.el-date-range-picker table{table-layout:fixed;width:100%}.el-date-range-picker .el-picker-panel__body{min-width:513px}.el-date-range-picker .el-picker-panel__content{margin:0}.el-date-range-picker.has-sidebar.has-time{min-width:766px}.el-date-range-picker.has-sidebar{min-width:620px}.el-date-range-picker.has-time{min-width:660px}.el-date-range-picker__header{position:relative;text-align:center;height:28px}.el-date-range-picker__header button{float:left}.el-date-range-picker__header div{font-size:14px;margin-right:50px}.el-date-range-picker__content{float:left;width:50%;box-sizing:border-box;margin:0;padding:16px}.el-date-range-picker__content.is-right .el-date-range-picker__header button{float:right}.el-date-range-picker__content.is-right .el-date-range-picker__header div{margin-left:50px;margin-right:50px}.el-date-range-picker__content.is-left{border-right:1px solid #e4e4e4}.el-date-range-picker__editors-wrap{box-sizing:border-box;display:table-cell}.el-date-range-picker__editors-wrap.is-right{text-align:right}.el-date-range-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px;display:table;width:100%;box-sizing:border-box}.el-date-range-picker__time-header>.el-icon-arrow-right{font-size:20px;vertical-align:middle;display:table-cell;color:#97a8be}.el-date-range-picker__time-picker-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-range-picker__time-picker-wrap .el-picker-panel{position:absolute;top:13px;right:0;z-index:1;background:#fff}.el-time-range-picker{min-width:354px;overflow:visible}.el-time-range-picker__content{position:relative;text-align:center;padding:10px}.el-time-range-picker__cell{box-sizing:border-box;margin:0;padding:4px 7px 7px;width:50%;display:inline-block}.el-time-range-picker__header{margin-bottom:5px;text-align:center;font-size:14px}.el-picker-panel,.el-time-range-picker__body{border-radius:2px;border:1px solid #d1dbe5}.el-picker-panel{color:#48576a;box-shadow:0 2px 6px #ccc;background:#fff;line-height:20px;margin:5px 0}.el-picker-panel__body-wrapper:after,.el-picker-panel__body:after{content:\"\";display:table;clear:both}.el-picker-panel__content{position:relative;margin:15px}.el-picker-panel__footer{border-top:1px solid #e4e4e4;padding:4px;text-align:right;background-color:#fff;position:relative}.el-picker-panel__shortcut{display:block;width:100%;border:0;background-color:transparent;line-height:28px;font-size:14px;color:#48576a;padding-left:12px;text-align:left;outline:0;cursor:pointer}.el-picker-panel__shortcut:hover{background-color:#e4e8f1}.el-picker-panel__shortcut.active{background-color:#e6f1fe;color:#20a0ff}.el-picker-panel__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.el-picker-panel__btn[disabled]{color:#ccc;cursor:not-allowed}.el-picker-panel__icon-btn{font-size:12px;color:#97a8be;border:0;background:0 0;cursor:pointer;outline:0;margin-top:3px}.el-date-picker__header-label.active,.el-date-picker__header-label:hover,.el-picker-panel__icon-btn:hover{color:#20a0ff}.el-picker-panel__link-btn{cursor:pointer;color:#20a0ff;text-decoration:none;padding:15px;font-size:12px}.el-picker-panel [slot=sidebar],.el-picker-panel__sidebar{position:absolute;top:0;bottom:0;width:110px;border-right:1px solid #e4e4e4;box-sizing:border-box;padding-top:6px;background-color:#fbfdff;overflow:auto}.el-picker-panel [slot=sidebar]+.el-picker-panel__body,.el-picker-panel__sidebar+.el-picker-panel__body{margin-left:110px}.el-date-picker{min-width:254px}.el-date-picker .el-picker-panel__content{min-width:224px}.el-date-picker table{table-layout:fixed;width:100%}.el-date-picker.has-sidebar.has-time{min-width:434px}.el-date-picker.has-sidebar{min-width:370px}.el-date-picker.has-time{min-width:324px}.el-date-picker__editor-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px;display:table;width:100%;box-sizing:border-box}.el-date-picker__header{margin:12px;text-align:center}.el-date-picker__header-label{font-size:14px;padding:0 5px;line-height:22px;text-align:center;cursor:pointer}.el-date-picker__prev-btn{float:left}.el-date-picker__next-btn{float:right}.el-date-picker__time-wrap{padding:10px;text-align:center}.el-date-picker__time-label{float:left;cursor:pointer;line-height:30px;margin-left:10px}.time-select{margin:5px 0;min-width:0}.time-select .el-picker-panel__content{max-height:200px;margin:0}.time-select-item{padding:8px 10px;font-size:14px}.time-select-item.selected:not(.disabled){background-color:#20a0ff;color:#fff}.time-select-item.selected:not(.disabled):hover{background-color:#20a0ff}.time-select-item.disabled{color:#d1dbe5;cursor:not-allowed}.time-select-item:hover{background-color:#e4e8f1;cursor:pointer}.el-fade-in-enter-active,.el-fade-in-leave-active,.el-zoom-in-center-enter-active,.el-zoom-in-center-leave-active{transition:all .3s cubic-bezier(.55,0,.1,1)}.el-zoom-in-bottom-enter-active,.el-zoom-in-bottom-leave-active,.el-zoom-in-left-enter-active,.el-zoom-in-left-leave-active,.el-zoom-in-top-enter-active,.el-zoom-in-top-leave-active{transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s}.el-zoom-in-center-enter,.el-zoom-in-center-leave-active{opacity:0;-ms-transform:scaleX(0);transform:scaleX(0)}.el-zoom-in-top-enter-active,.el-zoom-in-top-leave-active{opacity:1;-ms-transform:scaleY(1);transform:scaleY(1);-ms-transform-origin:center top;transform-origin:center top}.el-zoom-in-top-enter,.el-zoom-in-top-leave-active{opacity:0;-ms-transform:scaleY(0);transform:scaleY(0)}.el-zoom-in-bottom-enter-active,.el-zoom-in-bottom-leave-active{opacity:1;-ms-transform:scaleY(1);transform:scaleY(1);-ms-transform-origin:center bottom;transform-origin:center bottom}.el-zoom-in-bottom-enter,.el-zoom-in-bottom-leave-active{opacity:0;-ms-transform:scaleY(0);transform:scaleY(0)}.el-zoom-in-left-enter-active,.el-zoom-in-left-leave-active{opacity:1;-ms-transform:scale(1);transform:scale(1);-ms-transform-origin:top left;transform-origin:top left}.el-zoom-in-left-enter,.el-zoom-in-left-leave-active{opacity:0;-ms-transform:scale(.45);transform:scale(.45)}.collapse-transition{transition:height .3s ease-in-out,padding-top .3s ease-in-out,padding-bottom .3s ease-in-out}.horizontal-collapse-transition{transition:width .3s ease-in-out,padding-left .3s ease-in-out,padding-right .3s ease-in-out}.el-list-enter-active,.el-list-leave-active{transition:all 1s}.el-list-enter,.el-list-leave-active{opacity:0;-ms-transform:translateY(-30px);transform:translateY(-30px)}.el-opacity-transition{transition:opacity .3s cubic-bezier(.55,0,.1,1)}.el-date-editor{position:relative;display:inline-block}.el-date-editor .el-picker-panel{position:absolute;min-width:180px;box-sizing:border-box;box-shadow:0 2px 6px #ccc;background:#fff;z-index:10;top:41px}.el-date-editor.el-input{width:193px}.el-date-editor--daterange.el-input{width:220px}.el-date-editor--datetimerange.el-input{width:350px}.el-time-spinner.has-seconds .el-time-spinner__wrapper{width:33%}.el-time-spinner.has-seconds .el-time-spinner__wrapper:nth-child(2){margin-left:1%}.el-time-spinner__wrapper{max-height:190px;overflow:auto;display:inline-block;width:50%;vertical-align:top;position:relative}.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default){padding-bottom:15px}.el-time-spinner__list{padding:0;margin:0;list-style:none;text-align:center}.el-time-spinner__list:after,.el-time-spinner__list:before{content:\"\";display:block;width:100%;height:80px}.el-time-spinner__item{height:32px;line-height:32px;font-size:12px}.el-time-spinner__item:hover:not(.disabled):not(.active){background:#e4e8f1;cursor:pointer}.el-time-spinner__item.active:not(.disabled){color:#fff}.el-time-spinner__item.disabled{color:#d1dbe5;cursor:not-allowed}.el-time-panel{margin:5px 0;border:1px solid #d1dbe5;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);border-radius:2px;position:absolute;width:180px;left:0;z-index:1000;-webkit-user-select:none;-ms-user-select:none;user-select:none}.el-popover,.el-tabs--border-card{box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.el-slider__button,.el-slider__button-wrapper{-webkit-user-select:none;-moz-user-select:none}.el-time-panel__content{font-size:0;position:relative;overflow:hidden}.el-time-panel__content:after,.el-time-panel__content:before{content:\":\";top:50%;color:#fff;position:absolute;font-size:14px;margin-top:-15px;line-height:16px;background-color:#20a0ff;height:32px;z-index:-1;left:0;right:0;box-sizing:border-box;padding-top:6px;text-align:left}.el-time-panel__content:after{left:50%;margin-left:-2px}.el-time-panel__content:before{padding-left:50%;margin-right:-2px}.el-time-panel__content.has-seconds:after{left:66.66667%}.el-time-panel__content.has-seconds:before{padding-left:33.33333%}.el-time-panel__footer{border-top:1px solid #e4e4e4;padding:4px;height:36px;line-height:25px;text-align:right;box-sizing:border-box}.el-time-panel__btn{border:none;line-height:28px;padding:0 5px;margin:0 5px;cursor:pointer;background-color:transparent;outline:0;font-size:12px;color:#8391a5}.el-time-panel__btn.confirm{font-weight:800;color:#20a0ff}.el-popover{position:absolute;background:#fff;min-width:150px;border-radius:2px;border:1px solid #d1dbe5;padding:10px;z-index:2000;font-size:12px}.el-popover .popper__arrow,.el-popover .popper__arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-popover .popper__arrow{border-width:6px}.el-popover .popper__arrow:after{content:\" \";border-width:6px}.el-popover[x-placement^=top]{margin-bottom:12px}.el-popover[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#d1dbe5;border-bottom-width:0}.el-popover[x-placement^=top] .popper__arrow:after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.el-popover[x-placement^=bottom]{margin-top:12px}.el-popover[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#d1dbe5}.el-popover[x-placement^=bottom] .popper__arrow:after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.el-popover[x-placement^=right]{margin-left:12px}.el-popover[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#d1dbe5;border-left-width:0}.el-popover[x-placement^=right] .popper__arrow:after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.el-popover[x-placement^=left]{margin-right:12px}.el-popover[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#d1dbe5}.el-popover[x-placement^=left] .popper__arrow:after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.el-popover__title{color:#1f2d3d;font-size:13px;line-height:1;margin-bottom:9px}.v-modal-enter{animation:v-modal-in .2s ease}.v-modal-leave{animation:v-modal-out .2s ease forwards}@keyframes v-modal-in{0%{opacity:0}}@keyframes v-modal-out{to{opacity:0}}.v-modal{position:fixed;left:0;top:0;width:100%;height:100%;opacity:.5;background:#000}.el-message-box{text-align:left;display:inline-block;vertical-align:middle;background-color:#fff;width:420px;border-radius:3px;font-size:16px;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden}.el-message-box__wrapper{position:fixed;top:0;bottom:0;left:0;right:0;text-align:center}.el-message-box__wrapper:after{content:\"\";display:inline-block;height:100%;width:0;vertical-align:middle}.el-message-box__header{position:relative;padding:20px 20px 0}.el-message-box__headerbtn{position:absolute;top:19px;right:20px;background:0 0;border:none;outline:0;padding:0;cursor:pointer}.el-message-box__headerbtn .el-message-box__close{color:#999}.el-message-box__headerbtn:focus .el-message-box__close,.el-message-box__headerbtn:hover .el-message-box__close{color:#20a0ff}.el-message-box__content{padding:30px 20px;color:#48576a;font-size:14px;position:relative}.el-message-box__input{padding-top:15px}.el-message-box__input input.invalid,.el-message-box__input input.invalid:focus{border-color:#ff4949}.el-message-box__errormsg{color:#ff4949;font-size:12px;min-height:18px;margin-top:2px}.el-message-box__title{padding-left:0;margin-bottom:0;font-size:16px;font-weight:700;height:18px;color:#333}.el-message-box__message{margin:0}.el-message-box__message p{margin:0;line-height:1.4}.el-message-box__btns{padding:10px 20px 15px;text-align:right}.el-message-box__btns button:nth-child(2){margin-left:10px}.el-message-box__btns-reverse{-ms-flex-direction:row-reverse;flex-direction:row-reverse}.el-message-box__status{position:absolute;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%);font-size:36px!important}.el-message-box__status.el-icon-circle-check{color:#13ce66}.el-message-box__status.el-icon-information{color:#50bfff}.el-message-box__status.el-icon-warning{color:#f7ba2a}.el-message-box__status.el-icon-circle-cross{color:#ff4949}.msgbox-fade-enter-active{animation:msgbox-fade-in .3s}.msgbox-fade-leave-active{animation:msgbox-fade-out .3s}@keyframes msgbox-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}to{transform:translateZ(0);opacity:1}}@keyframes msgbox-fade-out{0%{transform:translateZ(0);opacity:1}to{transform:translate3d(0,-20px,0);opacity:0}}.el-breadcrumb{font-size:13px;line-height:1}.el-breadcrumb__separator{margin:0 8px;color:#bfcbd9}.el-breadcrumb__item{float:left}.el-breadcrumb__item:last-child .el-breadcrumb__item__inner,.el-breadcrumb__item:last-child .el-breadcrumb__item__inner:hover,.el-breadcrumb__item:last-child .el-breadcrumb__item__inner a,.el-breadcrumb__item:last-child .el-breadcrumb__item__inner a:hover{color:#97a8be;cursor:text}.el-breadcrumb__item:last-child .el-breadcrumb__separator{display:none}.el-breadcrumb__item__inner,.el-breadcrumb__item__inner a{transition:color .15s linear;color:#48576a}.el-breadcrumb__item__inner:hover,.el-breadcrumb__item__inner a:hover{color:#20a0ff;cursor:pointer}.el-form--label-left .el-form-item__label{text-align:left}.el-form--label-top .el-form-item__label{float:none;display:inline-block;text-align:left;padding:0 0 10px}.el-form--inline .el-form-item{display:inline-block;margin-right:10px;vertical-align:top}.el-form--inline .el-form-item__label{float:none;display:inline-block}.el-form--inline .el-form-item__content{display:inline-block;vertical-align:top}.el-form--inline.el-form--label-top .el-form-item__content{display:block}.el-form-item{margin-bottom:22px}.el-form-item .el-form-item{margin-bottom:0}.el-form-item.is-error .el-input-group__append .el-input__inner,.el-form-item.is-error .el-input-group__prepend .el-input__inner,.el-form-item.is-error .el-input__inner{border-color:transparent}.el-form-item.is-error .el-input__inner,.el-form-item.is-error .el-textarea__inner{border-color:#ff4949}.el-form-item.is-required .el-form-item__label:before{content:\"*\";color:#ff4949;margin-right:4px}.el-form-item__label{text-align:right;vertical-align:middle;float:left;font-size:14px;color:#48576a;line-height:1;padding:11px 12px 11px 0;box-sizing:border-box}.el-form-item__content{line-height:36px;position:relative;font-size:14px}.el-form-item__error{color:#ff4949;font-size:12px;line-height:1;padding-top:4px;position:absolute;top:100%;left:0}.el-tabs__header{border-bottom:1px solid #d1dbe5;padding:0;position:relative;margin:0 0 15px}.el-tabs__active-bar{position:absolute;bottom:0;left:0;height:3px;background-color:#20a0ff;z-index:1;transition:transform .3s cubic-bezier(.645,.045,.355,1);list-style:none}.el-tabs__new-tab{float:right;border:1px solid #d3dce6;height:18px;width:18px;line-height:18px;margin:12px 0 9px 10px;border-radius:3px;text-align:center;font-size:12px;color:#d3dce6;cursor:pointer;transition:all .15s}.el-tabs__new-tab .el-icon-plus{-ms-transform:scale(.8);transform:scale(.8)}.el-tabs__new-tab:hover{color:#20a0ff}.el-tabs__nav-wrap{overflow:hidden;margin-bottom:-1px;position:relative}.el-tabs__nav-wrap.is-scrollable{padding:0 15px}.el-tabs__nav-scroll{overflow:hidden}.el-tabs__nav-next,.el-tabs__nav-prev{position:absolute;cursor:pointer;line-height:44px;font-size:12px;color:#8391a5}.el-tabs__nav-next{right:0}.el-tabs__nav-prev{left:0}.el-tabs__nav{position:relative;transition:transform .3s;float:left}.el-tabs__item{padding:0 16px;height:42px;box-sizing:border-box;line-height:42px;display:inline-block;list-style:none;font-size:14px;color:#8391a5;position:relative}.el-tabs__item .el-icon-close{border-radius:50%;text-align:center;transition:all .3s cubic-bezier(.645,.045,.355,1);margin-left:5px}.el-tabs__item .el-icon-close:before{-ms-transform:scale(.7);transform:scale(.7);display:inline-block}.el-tabs__item .el-icon-close:hover{background-color:#97a8be;color:#fff}.el-tabs__item:hover{color:#1f2d3d;cursor:pointer}.el-tabs__item.is-disabled{color:#bbb;cursor:default}.el-tabs__item.is-active{color:#20a0ff}.el-tabs__content{overflow:hidden;position:relative}.el-tabs--card>.el-tabs__header .el-tabs__active-bar{display:none}.el-tag,.slideInLeft-transition,.slideInRight-transition{display:inline-block}.el-tabs--card>.el-tabs__header .el-tabs__item .el-icon-close{position:relative;font-size:12px;width:0;height:14px;vertical-align:middle;line-height:15px;overflow:hidden;top:-1px;right:-2px;-ms-transform-origin:100% 50%;transform-origin:100% 50%}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable .el-icon-close,.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover .el-icon-close{width:14px}.el-tabs--card>.el-tabs__header .el-tabs__item{border:1px solid transparent;transition:all .3s cubic-bezier(.645,.045,.355,1)}.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover{padding-right:9px;padding-left:9px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border:1px solid #d1dbe5;border-bottom-color:#fff;border-radius:4px 4px 0 0}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable{padding-right:16px;padding-left:16px}.el-tabs--border-card{background:#fff;border:1px solid #d1dbe5}.el-tabs--border-card>.el-tabs__content{padding:15px}.el-tabs--border-card>.el-tabs__header{background-color:#eef1f6;margin:0}.el-tabs--border-card>.el-tabs__header .el-tabs__item{transition:all .3s cubic-bezier(.645,.045,.355,1);border:1px solid transparent;border-top:0;margin-right:-1px;margin-left:-1px}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active{background-color:#fff;border-right-color:#d1dbe5;border-left-color:#d1dbe5}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active:first-child{border-left-color:#d1dbe5}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active:last-child{border-right-color:#d1dbe5}.slideInRight-enter{animation:slideInRight-enter .3s}.slideInRight-leave{position:absolute;left:0;right:0;animation:slideInRight-leave .3s}.slideInLeft-enter{animation:slideInLeft-enter .3s}.slideInLeft-leave{position:absolute;left:0;right:0;animation:slideInLeft-leave .3s}@keyframes slideInRight-enter{0%{opacity:0;transform-origin:0 0;transform:translateX(100%)}to{opacity:1;transform-origin:0 0;transform:translateX(0)}}@keyframes slideInRight-leave{0%{transform-origin:0 0;transform:translateX(0);opacity:1}to{transform-origin:0 0;transform:translateX(100%);opacity:0}}@keyframes slideInLeft-enter{0%{opacity:0;transform-origin:0 0;transform:translateX(-100%)}to{opacity:1;transform-origin:0 0;transform:translateX(0)}}@keyframes slideInLeft-leave{0%{transform-origin:0 0;transform:translateX(0);opacity:1}to{transform-origin:0 0;transform:translateX(-100%);opacity:0}}.el-tag{background-color:#8391a5;padding:0 5px;height:24px;line-height:22px;font-size:12px;color:#fff;border-radius:4px;box-sizing:border-box;border:1px solid transparent}.el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;-ms-transform:scale(.75);transform:scale(.75);height:18px;width:18px;line-height:18px;vertical-align:middle;top:-1px;right:-2px}.el-tag .el-icon-close:hover{background-color:#fff;color:#8391a5}.el-tag--gray{background-color:#e4e8f1;border-color:#e4e8f1;color:#48576a}.el-tag--gray .el-tag__close:hover{background-color:#48576a;color:#fff}.el-tag--gray.is-hit{border-color:#48576a}.el-tag--primary{background-color:rgba(32,160,255,.1);border-color:rgba(32,160,255,.2);color:#20a0ff}.el-tag--primary .el-tag__close:hover{background-color:#20a0ff;color:#fff}.el-tag--primary.is-hit{border-color:#20a0ff}.el-tag--success{background-color:rgba(18,206,102,.1);border-color:rgba(18,206,102,.2);color:#13ce66}.el-tag--success .el-tag__close:hover{background-color:#13ce66;color:#fff}.el-tag--success.is-hit{border-color:#13ce66}.el-tag--warning{background-color:rgba(247,186,41,.1);border-color:rgba(247,186,41,.2);color:#f7ba2a}.el-tag--warning .el-tag__close:hover{background-color:#f7ba2a;color:#fff}.el-tag--warning.is-hit{border-color:#f7ba2a}.el-tag--danger{background-color:rgba(255,73,73,.1);border-color:rgba(255,73,73,.2);color:#ff4949}.el-tag--danger .el-tag__close:hover{background-color:#ff4949;color:#fff}.el-tag--danger.is-hit{border-color:#ff4949}.el-tree{cursor:default;background:#fff;border:1px solid #d1dbe5}.el-tree__empty-block{position:relative;min-height:60px;text-align:center;width:100%;height:100%}.el-tree__empty-text{position:absolute;left:50%;top:50%;-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#5e7382}.el-tree-node>.el-tree-node__children{overflow:hidden;background-color:transparent}.el-tree-node.is-expanded>.el-tree-node__children{display:block}.el-tree-node__expand-icon,.el-tree-node__label,.el-tree-node__loading-icon{display:inline-block;vertical-align:middle}.el-tree-node__content{line-height:36px;height:36px;cursor:pointer}.el-tree-node__content>.el-checkbox,.el-tree-node__content>.el-tree-node__expand-icon{margin-right:8px}.el-tree-node__content>.el-checkbox{vertical-align:middle}.el-tree-node__content:hover{background:#e4e8f1}.el-tree-node__expand-icon{cursor:pointer;width:0;height:0;margin-left:10px;border:6px solid transparent;border-right-width:0;border-left-color:#97a8be;border-left-width:7px;-ms-transform:rotate(0);transform:rotate(0);transition:transform .3s ease-in-out}.el-tree-node__expand-icon:hover{border-left-color:#999}.el-tree-node__expand-icon.expanded{-ms-transform:rotate(90deg);transform:rotate(90deg)}.el-tree-node__expand-icon.is-leaf{border-color:transparent;cursor:default}.el-tree-node__label{font-size:14px}.el-tree-node__loading-icon{margin-right:4px;font-size:14px;color:#97a8be}.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content{background-color:#edf7ff}.el-alert{width:100%;padding:8px 16px;margin:0;box-sizing:border-box;border-radius:4px;position:relative;background-color:#fff;overflow:hidden;color:#fff;opacity:1;display:table;transition:opacity .2s}.el-alert .el-alert__description{color:#fff;font-size:12px;margin:5px 0 0}.el-alert--success{background-color:#13ce66}.el-alert--info{background-color:#50bfff}.el-alert--warning{background-color:#f7ba2a}.el-alert--error{background-color:#ff4949}.el-alert__content{display:table-cell;padding:0 8px}.el-alert__icon{font-size:16px;width:16px;display:table-cell;color:#fff;vertical-align:middle}.el-alert__icon.is-big{font-size:28px;width:28px}.el-alert__title{font-size:13px;line-height:18px}.el-alert__title.is-bold{font-weight:700}.el-alert__closebtn{font-size:12px;color:#fff;opacity:1;top:12px;right:15px;position:absolute;cursor:pointer}.el-alert-fade-enter,.el-alert-fade-leave-active,.el-loading-fade-enter,.el-loading-fade-leave-active,.el-notification-fade-leave-active{opacity:0}.el-alert__closebtn.is-customed{font-style:normal;font-size:13px;top:9px}.el-notification{width:330px;padding:20px;box-sizing:border-box;border-radius:2px;position:fixed;right:16px;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);transition:opacity .3s,transform .3s,right .3s,top .4s;overflow:hidden}.el-notification .el-icon-circle-check{color:#13ce66}.el-notification .el-icon-circle-cross{color:#ff4949}.el-notification .el-icon-information{color:#50bfff}.el-notification .el-icon-warning{color:#f7ba2a}.el-notification__group{margin-left:0}.el-notification__group.is-with-icon{margin-left:55px}.el-notification__title{font-weight:400;font-size:16px;color:#1f2d3d;margin:0}.el-notification__content{font-size:14px;line-height:21px;margin:10px 0 0;color:#8391a5;text-align:justify}.el-notification__icon{width:40px;height:40px;font-size:40px;float:left;position:relative;top:3px}.el-notification__closeBtn{top:20px;right:20px;position:absolute;cursor:pointer;color:#bfcbd9;font-size:14px}.el-notification__closeBtn:hover{color:#97a8be}.el-notification-fade-enter{-ms-transform:translateX(100%);transform:translateX(100%);right:0}.el-input-number{display:inline-block;width:180px;position:relative;line-height:normal}.el-input-number .el-input{display:block}.el-input-number .el-input__inner{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding-right:82px}.el-input-number.is-without-controls .el-input__inner{padding-right:10px}.el-input-number.is-disabled .el-input-number__decrease,.el-input-number.is-disabled .el-input-number__increase{border-color:#d1dbe5;color:#d1dbe5}.el-input-number.is-disabled .el-input-number__decrease:hover,.el-input-number.is-disabled .el-input-number__increase:hover{color:#d1dbe5;cursor:not-allowed}.el-input-number__decrease,.el-input-number__increase{height:auto;border-left:1px solid #bfcbd9;width:36px;line-height:34px;top:1px;text-align:center;color:#97a8be;cursor:pointer;position:absolute;z-index:1}.el-input-number__decrease:hover,.el-input-number__increase:hover{color:#20a0ff}.el-input-number__decrease:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled),.el-input-number__increase:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled){border-color:#20a0ff}.el-input-number__decrease.is-disabled,.el-input-number__increase.is-disabled{color:#d1dbe5;cursor:not-allowed}.el-input-number__increase{right:0}.el-input-number__decrease{right:37px}.el-input-number--large{width:200px}.el-input-number--large .el-input-number__decrease,.el-input-number--large .el-input-number__increase{line-height:40px;width:42px;font-size:16px}.el-input-number--large .el-input-number__decrease{right:43px}.el-input-number--large .el-input__inner{padding-right:94px}.el-input-number--small{width:130px}.el-input-number--small .el-input-number__decrease,.el-input-number--small .el-input-number__increase{line-height:28px;width:30px;font-size:13px}.el-input-number--small .el-input-number__decrease{right:31px}.el-input-number--small .el-input__inner{padding-right:70px}.el-tooltip__popper{position:absolute;border-radius:4px;padding:10px;z-index:2000;font-size:12px;line-height:1.2}.el-tooltip__popper .popper__arrow,.el-tooltip__popper .popper__arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-tooltip__popper .popper__arrow{border-width:6px}.el-tooltip__popper .popper__arrow:after{content:\" \";border-width:5px}.el-progress-bar__inner:after,.el-row:after,.el-row:before,.el-slider:after,.el-slider:before,.el-slider__button-wrapper:after,.el-upload-cover:after{content:\"\"}.el-tooltip__popper[x-placement^=top]{margin-bottom:12px}.el-tooltip__popper[x-placement^=top] .popper__arrow{bottom:-6px;border-top-color:#1f2d3d;border-bottom-width:0}.el-tooltip__popper[x-placement^=top] .popper__arrow:after{bottom:1px;margin-left:-5px;border-top-color:#1f2d3d;border-bottom-width:0}.el-tooltip__popper[x-placement^=bottom]{margin-top:12px}.el-tooltip__popper[x-placement^=bottom] .popper__arrow{top:-6px;border-top-width:0;border-bottom-color:#1f2d3d}.el-tooltip__popper[x-placement^=bottom] .popper__arrow:after{top:1px;margin-left:-5px;border-top-width:0;border-bottom-color:#1f2d3d}.el-tooltip__popper[x-placement^=right]{margin-left:12px}.el-tooltip__popper[x-placement^=right] .popper__arrow{left:-6px;border-right-color:#1f2d3d;border-left-width:0}.el-tooltip__popper[x-placement^=right] .popper__arrow:after{bottom:-5px;left:1px;border-right-color:#1f2d3d;border-left-width:0}.el-tooltip__popper[x-placement^=left]{margin-right:12px}.el-tooltip__popper[x-placement^=left] .popper__arrow{right:-6px;border-right-width:0;border-left-color:#1f2d3d}.el-tooltip__popper[x-placement^=left] .popper__arrow:after{right:1px;bottom:-5px;margin-left:-5px;border-right-width:0;border-left-color:#1f2d3d}.el-tooltip__popper.is-light{background:#fff;border:1px solid #1f2d3d}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow{border-top-color:#1f2d3d}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow:after{border-top-color:#fff}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow{border-bottom-color:#1f2d3d}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow:after{border-bottom-color:#fff}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow{border-left-color:#1f2d3d}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow:after{border-left-color:#fff}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow{border-right-color:#1f2d3d}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow:after{border-right-color:#fff}.el-tooltip__popper.is-dark{background:#1f2d3d;color:#fff}.el-slider:after,.el-slider:before{display:table}.el-slider__button-wrapper .el-tooltip,.el-slider__button-wrapper:after{display:inline-block;vertical-align:middle}.el-slider:after{clear:both}.el-slider.is-vertical{position:relative}.el-slider.is-vertical .el-slider__runway{width:4px;height:100%;margin:0 16px}.el-slider.is-vertical .el-slider__bar{width:4px;height:auto;border-radius:0 0 3px 3px}.el-slider.is-vertical .el-slider__button-wrapper{top:auto;left:-16px}.el-slider.is-vertical .el-slider__button-wrapper,.el-slider.is-vertical .el-slider__stop{-ms-transform:translateY(50%);transform:translateY(50%)}.el-slider.is-vertical.el-slider--with-input{padding-bottom:64px}.el-slider.is-vertical.el-slider--with-input .el-slider__input{overflow:visible;float:none;position:absolute;bottom:22px;width:36px;margin-top:15px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input__inner{text-align:center;padding-left:5px;padding-right:5px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{top:30px;margin-top:-1px;border:1px solid #bfcbd9;line-height:20px;box-sizing:border-box;transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease{width:18px;right:18px;border-bottom-left-radius:4px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{width:19px;border-bottom-right-radius:4px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase~.el-input .el-input__inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__increase{border-color:#8391a5}.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__increase{border-color:#20a0ff}.el-slider__runway{width:100%;height:4px;margin:16px 0;background-color:#e4e8f1;border-radius:3px;position:relative;cursor:pointer;vertical-align:middle}.el-slider__runway.show-input{margin-right:160px;width:auto}.el-slider__runway.disabled{cursor:default}.el-slider__runway.disabled .el-slider__bar,.el-slider__runway.disabled .el-slider__button{background-color:#bfcbd9}.el-slider__runway.disabled .el-slider__button-wrapper.dragging,.el-slider__runway.disabled .el-slider__button-wrapper.hover,.el-slider__runway.disabled .el-slider__button-wrapper:hover{cursor:not-allowed}.el-slider__runway.disabled .el-slider__button.dragging,.el-slider__runway.disabled .el-slider__button.hover,.el-slider__runway.disabled .el-slider__button:hover{-ms-transform:scale(1);transform:scale(1);cursor:not-allowed}.el-slider__input{float:right;margin-top:3px}.el-slider__bar{height:4px;background-color:#20a0ff;border-top-left-radius:3px;border-bottom-left-radius:3px;position:absolute}.el-slider__button-wrapper{width:36px;height:36px;position:absolute;z-index:1001;top:-16px;-ms-transform:translateX(-50%);transform:translateX(-50%);background-color:transparent;text-align:center;-ms-user-select:none;user-select:none}.el-slider__button-wrapper:after{height:100%}.el-slider__button-wrapper.hover,.el-slider__button-wrapper:hover{cursor:-webkit-grab;cursor:grab}.el-slider__button-wrapper.dragging{cursor:-webkit-grabbing;cursor:grabbing}.el-slider__button{width:12px;height:12px;background-color:#20a0ff;border-radius:50%;transition:.2s;-ms-user-select:none;user-select:none}.el-slider__button.dragging,.el-slider__button.hover,.el-slider__button:hover{-ms-transform:scale(1.5);transform:scale(1.5);background-color:#1c8de0}.el-slider__button.hover,.el-slider__button:hover{cursor:-webkit-grab;cursor:grab}.el-slider__button.dragging{cursor:-webkit-grabbing;cursor:grabbing}.el-slider__stop{position:absolute;width:4px;height:4px;border-radius:100%;background-color:#bfcbd9;-ms-transform:translateX(-50%);transform:translateX(-50%)}.el-loading-mask{position:absolute;z-index:10000;background-color:hsla(0,0%,100%,.9);margin:0;top:0;right:0;bottom:0;left:0;transition:opacity .3s}.el-loading-mask.is-fullscreen{position:fixed}.el-loading-mask.is-fullscreen .el-loading-spinner{margin-top:-25px}.el-loading-mask.is-fullscreen .el-loading-spinner .circular{width:50px;height:50px}.el-loading-spinner{top:50%;margin-top:-21px;width:100%;text-align:center;position:absolute}.el-col-pull-0,.el-col-pull-1,.el-col-pull-2,.el-col-pull-3,.el-col-pull-4,.el-col-pull-5,.el-col-pull-6,.el-col-pull-7,.el-col-pull-8,.el-col-pull-9,.el-col-pull-10,.el-col-pull-11,.el-col-pull-13,.el-col-pull-14,.el-col-pull-15,.el-col-pull-16,.el-col-pull-17,.el-col-pull-18,.el-col-pull-19,.el-col-pull-20,.el-col-pull-21,.el-col-pull-22,.el-col-pull-23,.el-col-pull-24,.el-col-push-0,.el-col-push-1,.el-col-push-2,.el-col-push-3,.el-col-push-4,.el-col-push-5,.el-col-push-6,.el-col-push-7,.el-col-push-8,.el-col-push-9,.el-col-push-10,.el-col-push-11,.el-col-push-12,.el-col-push-13,.el-col-push-14,.el-col-push-15,.el-col-push-16,.el-col-push-17,.el-col-push-18,.el-col-push-19,.el-col-push-20,.el-col-push-21,.el-col-push-22,.el-col-push-23,.el-col-push-24,.el-row{position:relative}.el-loading-spinner .el-loading-text{color:#20a0ff;margin:3px 0;font-size:14px}.el-loading-spinner .circular{width:42px;height:42px;animation:loading-rotate 2s linear infinite}.el-loading-spinner .path{animation:loading-dash 1.5s ease-in-out infinite;stroke-dasharray:90,150;stroke-dashoffset:0;stroke-width:2;stroke:#20a0ff;stroke-linecap:round}@keyframes loading-rotate{to{transform:rotate(1turn)}}@keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}to{stroke-dasharray:90,150;stroke-dashoffset:-120px}}.el-row{box-sizing:border-box}.el-row:after,.el-row:before{display:table}.el-row:after{clear:both}.el-row--flex{display:-ms-flexbox;display:flex}.el-row--flex:after,.el-row--flex:before{display:none}.el-row--flex.is-align-bottom{-ms-flex-align:end;align-items:flex-end}.el-row--flex.is-align-middle{-ms-flex-align:center;align-items:center}.el-row--flex.is-justify-space-around{-ms-flex-pack:distribute;justify-content:space-around}.el-row--flex.is-justify-space-between{-ms-flex-pack:justify;justify-content:space-between}.el-row--flex.is-justify-end{-ms-flex-pack:end;justify-content:flex-end}.el-row--flex.is-justify-center{-ms-flex-pack:center;justify-content:center}.el-col-1,.el-col-2,.el-col-3,.el-col-4,.el-col-5,.el-col-6,.el-col-7,.el-col-8,.el-col-9,.el-col-10,.el-col-11,.el-col-12,.el-col-13,.el-col-14,.el-col-15,.el-col-16,.el-col-17,.el-col-18,.el-col-19,.el-col-20,.el-col-21,.el-col-22,.el-col-23,.el-col-24{float:left;box-sizing:border-box}.el-col-0{width:0}.el-col-offset-0{margin-left:0}.el-col-pull-0{right:0}.el-col-push-0{left:0}.el-col-1{width:4.16667%}.el-col-offset-1{margin-left:4.16667%}.el-col-pull-1{right:4.16667%}.el-col-push-1{left:4.16667%}.el-col-2{width:8.33333%}.el-col-offset-2{margin-left:8.33333%}.el-col-pull-2{right:8.33333%}.el-col-push-2{left:8.33333%}.el-col-3{width:12.5%}.el-col-offset-3{margin-left:12.5%}.el-col-pull-3{right:12.5%}.el-col-push-3{left:12.5%}.el-col-4{width:16.66667%}.el-col-offset-4{margin-left:16.66667%}.el-col-pull-4{right:16.66667%}.el-col-push-4{left:16.66667%}.el-col-5{width:20.83333%}.el-col-offset-5{margin-left:20.83333%}.el-col-pull-5{right:20.83333%}.el-col-push-5{left:20.83333%}.el-col-6{width:25%}.el-col-offset-6{margin-left:25%}.el-col-pull-6{right:25%}.el-col-push-6{left:25%}.el-col-7{width:29.16667%}.el-col-offset-7{margin-left:29.16667%}.el-col-pull-7{right:29.16667%}.el-col-push-7{left:29.16667%}.el-col-8{width:33.33333%}.el-col-offset-8{margin-left:33.33333%}.el-col-pull-8{right:33.33333%}.el-col-push-8{left:33.33333%}.el-col-9{width:37.5%}.el-col-offset-9{margin-left:37.5%}.el-col-pull-9{right:37.5%}.el-col-push-9{left:37.5%}.el-col-10{width:41.66667%}.el-col-offset-10{margin-left:41.66667%}.el-col-pull-10{right:41.66667%}.el-col-push-10{left:41.66667%}.el-col-11{width:45.83333%}.el-col-offset-11{margin-left:45.83333%}.el-col-pull-11{right:45.83333%}.el-col-push-11{left:45.83333%}.el-col-12{width:50%}.el-col-offset-12{margin-left:50%}.el-col-pull-12{position:relative;right:50%}.el-col-push-12{left:50%}.el-col-13{width:54.16667%}.el-col-offset-13{margin-left:54.16667%}.el-col-pull-13{right:54.16667%}.el-col-push-13{left:54.16667%}.el-col-14{width:58.33333%}.el-col-offset-14{margin-left:58.33333%}.el-col-pull-14{right:58.33333%}.el-col-push-14{left:58.33333%}.el-col-15{width:62.5%}.el-col-offset-15{margin-left:62.5%}.el-col-pull-15{right:62.5%}.el-col-push-15{left:62.5%}.el-col-16{width:66.66667%}.el-col-offset-16{margin-left:66.66667%}.el-col-pull-16{right:66.66667%}.el-col-push-16{left:66.66667%}.el-col-17{width:70.83333%}.el-col-offset-17{margin-left:70.83333%}.el-col-pull-17{right:70.83333%}.el-col-push-17{left:70.83333%}.el-col-18{width:75%}.el-col-offset-18{margin-left:75%}.el-col-pull-18{right:75%}.el-col-push-18{left:75%}.el-col-19{width:79.16667%}.el-col-offset-19{margin-left:79.16667%}.el-col-pull-19{right:79.16667%}.el-col-push-19{left:79.16667%}.el-col-20{width:83.33333%}.el-col-offset-20{margin-left:83.33333%}.el-col-pull-20{right:83.33333%}.el-col-push-20{left:83.33333%}.el-col-21{width:87.5%}.el-col-offset-21{margin-left:87.5%}.el-col-pull-21{right:87.5%}.el-col-push-21{left:87.5%}.el-col-22{width:91.66667%}.el-col-offset-22{margin-left:91.66667%}.el-col-pull-22{right:91.66667%}.el-col-push-22{left:91.66667%}.el-col-23{width:95.83333%}.el-col-offset-23{margin-left:95.83333%}.el-col-pull-23{right:95.83333%}.el-col-push-23{left:95.83333%}.el-col-24{width:100%}.el-col-offset-24{margin-left:100%}.el-col-pull-24{right:100%}.el-col-push-24{left:100%}@media (max-width:768px){.el-col-xs-0{width:0}.el-col-xs-offset-0{margin-left:0}.el-col-xs-pull-0{position:relative;right:0}.el-col-xs-push-0{position:relative;left:0}.el-col-xs-1{width:4.16667%}.el-col-xs-offset-1{margin-left:4.16667%}.el-col-xs-pull-1{position:relative;right:4.16667%}.el-col-xs-push-1{position:relative;left:4.16667%}.el-col-xs-2{width:8.33333%}.el-col-xs-offset-2{margin-left:8.33333%}.el-col-xs-pull-2{position:relative;right:8.33333%}.el-col-xs-push-2{position:relative;left:8.33333%}.el-col-xs-3{width:12.5%}.el-col-xs-offset-3{margin-left:12.5%}.el-col-xs-pull-3{position:relative;right:12.5%}.el-col-xs-push-3{position:relative;left:12.5%}.el-col-xs-4{width:16.66667%}.el-col-xs-offset-4{margin-left:16.66667%}.el-col-xs-pull-4{position:relative;right:16.66667%}.el-col-xs-push-4{position:relative;left:16.66667%}.el-col-xs-5{width:20.83333%}.el-col-xs-offset-5{margin-left:20.83333%}.el-col-xs-pull-5{position:relative;right:20.83333%}.el-col-xs-push-5{position:relative;left:20.83333%}.el-col-xs-6{width:25%}.el-col-xs-offset-6{margin-left:25%}.el-col-xs-pull-6{position:relative;right:25%}.el-col-xs-push-6{position:relative;left:25%}.el-col-xs-7{width:29.16667%}.el-col-xs-offset-7{margin-left:29.16667%}.el-col-xs-pull-7{position:relative;right:29.16667%}.el-col-xs-push-7{position:relative;left:29.16667%}.el-col-xs-8{width:33.33333%}.el-col-xs-offset-8{margin-left:33.33333%}.el-col-xs-pull-8{position:relative;right:33.33333%}.el-col-xs-push-8{position:relative;left:33.33333%}.el-col-xs-9{width:37.5%}.el-col-xs-offset-9{margin-left:37.5%}.el-col-xs-pull-9{position:relative;right:37.5%}.el-col-xs-push-9{position:relative;left:37.5%}.el-col-xs-10{width:41.66667%}.el-col-xs-offset-10{margin-left:41.66667%}.el-col-xs-pull-10{position:relative;right:41.66667%}.el-col-xs-push-10{position:relative;left:41.66667%}.el-col-xs-11{width:45.83333%}.el-col-xs-offset-11{margin-left:45.83333%}.el-col-xs-pull-11{position:relative;right:45.83333%}.el-col-xs-push-11{position:relative;left:45.83333%}.el-col-xs-12{width:50%}.el-col-xs-offset-12{margin-left:50%}.el-col-xs-pull-12{position:relative;right:50%}.el-col-xs-push-12{position:relative;left:50%}.el-col-xs-13{width:54.16667%}.el-col-xs-offset-13{margin-left:54.16667%}.el-col-xs-pull-13{position:relative;right:54.16667%}.el-col-xs-push-13{position:relative;left:54.16667%}.el-col-xs-14{width:58.33333%}.el-col-xs-offset-14{margin-left:58.33333%}.el-col-xs-pull-14{position:relative;right:58.33333%}.el-col-xs-push-14{position:relative;left:58.33333%}.el-col-xs-15{width:62.5%}.el-col-xs-offset-15{margin-left:62.5%}.el-col-xs-pull-15{position:relative;right:62.5%}.el-col-xs-push-15{position:relative;left:62.5%}.el-col-xs-16{width:66.66667%}.el-col-xs-offset-16{margin-left:66.66667%}.el-col-xs-pull-16{position:relative;right:66.66667%}.el-col-xs-push-16{position:relative;left:66.66667%}.el-col-xs-17{width:70.83333%}.el-col-xs-offset-17{margin-left:70.83333%}.el-col-xs-pull-17{position:relative;right:70.83333%}.el-col-xs-push-17{position:relative;left:70.83333%}.el-col-xs-18{width:75%}.el-col-xs-offset-18{margin-left:75%}.el-col-xs-pull-18{position:relative;right:75%}.el-col-xs-push-18{position:relative;left:75%}.el-col-xs-19{width:79.16667%}.el-col-xs-offset-19{margin-left:79.16667%}.el-col-xs-pull-19{position:relative;right:79.16667%}.el-col-xs-push-19{position:relative;left:79.16667%}.el-col-xs-20{width:83.33333%}.el-col-xs-offset-20{margin-left:83.33333%}.el-col-xs-pull-20{position:relative;right:83.33333%}.el-col-xs-push-20{position:relative;left:83.33333%}.el-col-xs-21{width:87.5%}.el-col-xs-offset-21{margin-left:87.5%}.el-col-xs-pull-21{position:relative;right:87.5%}.el-col-xs-push-21{position:relative;left:87.5%}.el-col-xs-22{width:91.66667%}.el-col-xs-offset-22{margin-left:91.66667%}.el-col-xs-pull-22{position:relative;right:91.66667%}.el-col-xs-push-22{position:relative;left:91.66667%}.el-col-xs-23{width:95.83333%}.el-col-xs-offset-23{margin-left:95.83333%}.el-col-xs-pull-23{position:relative;right:95.83333%}.el-col-xs-push-23{position:relative;left:95.83333%}.el-col-xs-24{width:100%}.el-col-xs-offset-24{margin-left:100%}.el-col-xs-pull-24{position:relative;right:100%}.el-col-xs-push-24{position:relative;left:100%}}@media (min-width:768px){.el-col-sm-0{width:0}.el-col-sm-offset-0{margin-left:0}.el-col-sm-pull-0{position:relative;right:0}.el-col-sm-push-0{position:relative;left:0}.el-col-sm-1{width:4.16667%}.el-col-sm-offset-1{margin-left:4.16667%}.el-col-sm-pull-1{position:relative;right:4.16667%}.el-col-sm-push-1{position:relative;left:4.16667%}.el-col-sm-2{width:8.33333%}.el-col-sm-offset-2{margin-left:8.33333%}.el-col-sm-pull-2{position:relative;right:8.33333%}.el-col-sm-push-2{position:relative;left:8.33333%}.el-col-sm-3{width:12.5%}.el-col-sm-offset-3{margin-left:12.5%}.el-col-sm-pull-3{position:relative;right:12.5%}.el-col-sm-push-3{position:relative;left:12.5%}.el-col-sm-4{width:16.66667%}.el-col-sm-offset-4{margin-left:16.66667%}.el-col-sm-pull-4{position:relative;right:16.66667%}.el-col-sm-push-4{position:relative;left:16.66667%}.el-col-sm-5{width:20.83333%}.el-col-sm-offset-5{margin-left:20.83333%}.el-col-sm-pull-5{position:relative;right:20.83333%}.el-col-sm-push-5{position:relative;left:20.83333%}.el-col-sm-6{width:25%}.el-col-sm-offset-6{margin-left:25%}.el-col-sm-pull-6{position:relative;right:25%}.el-col-sm-push-6{position:relative;left:25%}.el-col-sm-7{width:29.16667%}.el-col-sm-offset-7{margin-left:29.16667%}.el-col-sm-pull-7{position:relative;right:29.16667%}.el-col-sm-push-7{position:relative;left:29.16667%}.el-col-sm-8{width:33.33333%}.el-col-sm-offset-8{margin-left:33.33333%}.el-col-sm-pull-8{position:relative;right:33.33333%}.el-col-sm-push-8{position:relative;left:33.33333%}.el-col-sm-9{width:37.5%}.el-col-sm-offset-9{margin-left:37.5%}.el-col-sm-pull-9{position:relative;right:37.5%}.el-col-sm-push-9{position:relative;left:37.5%}.el-col-sm-10{width:41.66667%}.el-col-sm-offset-10{margin-left:41.66667%}.el-col-sm-pull-10{position:relative;right:41.66667%}.el-col-sm-push-10{position:relative;left:41.66667%}.el-col-sm-11{width:45.83333%}.el-col-sm-offset-11{margin-left:45.83333%}.el-col-sm-pull-11{position:relative;right:45.83333%}.el-col-sm-push-11{position:relative;left:45.83333%}.el-col-sm-12{width:50%}.el-col-sm-offset-12{margin-left:50%}.el-col-sm-pull-12{position:relative;right:50%}.el-col-sm-push-12{position:relative;left:50%}.el-col-sm-13{width:54.16667%}.el-col-sm-offset-13{margin-left:54.16667%}.el-col-sm-pull-13{position:relative;right:54.16667%}.el-col-sm-push-13{position:relative;left:54.16667%}.el-col-sm-14{width:58.33333%}.el-col-sm-offset-14{margin-left:58.33333%}.el-col-sm-pull-14{position:relative;right:58.33333%}.el-col-sm-push-14{position:relative;left:58.33333%}.el-col-sm-15{width:62.5%}.el-col-sm-offset-15{margin-left:62.5%}.el-col-sm-pull-15{position:relative;right:62.5%}.el-col-sm-push-15{position:relative;left:62.5%}.el-col-sm-16{width:66.66667%}.el-col-sm-offset-16{margin-left:66.66667%}.el-col-sm-pull-16{position:relative;right:66.66667%}.el-col-sm-push-16{position:relative;left:66.66667%}.el-col-sm-17{width:70.83333%}.el-col-sm-offset-17{margin-left:70.83333%}.el-col-sm-pull-17{position:relative;right:70.83333%}.el-col-sm-push-17{position:relative;left:70.83333%}.el-col-sm-18{width:75%}.el-col-sm-offset-18{margin-left:75%}.el-col-sm-pull-18{position:relative;right:75%}.el-col-sm-push-18{position:relative;left:75%}.el-col-sm-19{width:79.16667%}.el-col-sm-offset-19{margin-left:79.16667%}.el-col-sm-pull-19{position:relative;right:79.16667%}.el-col-sm-push-19{position:relative;left:79.16667%}.el-col-sm-20{width:83.33333%}.el-col-sm-offset-20{margin-left:83.33333%}.el-col-sm-pull-20{position:relative;right:83.33333%}.el-col-sm-push-20{position:relative;left:83.33333%}.el-col-sm-21{width:87.5%}.el-col-sm-offset-21{margin-left:87.5%}.el-col-sm-pull-21{position:relative;right:87.5%}.el-col-sm-push-21{position:relative;left:87.5%}.el-col-sm-22{width:91.66667%}.el-col-sm-offset-22{margin-left:91.66667%}.el-col-sm-pull-22{position:relative;right:91.66667%}.el-col-sm-push-22{position:relative;left:91.66667%}.el-col-sm-23{width:95.83333%}.el-col-sm-offset-23{margin-left:95.83333%}.el-col-sm-pull-23{position:relative;right:95.83333%}.el-col-sm-push-23{position:relative;left:95.83333%}.el-col-sm-24{width:100%}.el-col-sm-offset-24{margin-left:100%}.el-col-sm-pull-24{position:relative;right:100%}.el-col-sm-push-24{position:relative;left:100%}}@media (min-width:992px){.el-col-md-0{width:0}.el-col-md-offset-0{margin-left:0}.el-col-md-pull-0{position:relative;right:0}.el-col-md-push-0{position:relative;left:0}.el-col-md-1{width:4.16667%}.el-col-md-offset-1{margin-left:4.16667%}.el-col-md-pull-1{position:relative;right:4.16667%}.el-col-md-push-1{position:relative;left:4.16667%}.el-col-md-2{width:8.33333%}.el-col-md-offset-2{margin-left:8.33333%}.el-col-md-pull-2{position:relative;right:8.33333%}.el-col-md-push-2{position:relative;left:8.33333%}.el-col-md-3{width:12.5%}.el-col-md-offset-3{margin-left:12.5%}.el-col-md-pull-3{position:relative;right:12.5%}.el-col-md-push-3{position:relative;left:12.5%}.el-col-md-4{width:16.66667%}.el-col-md-offset-4{margin-left:16.66667%}.el-col-md-pull-4{position:relative;right:16.66667%}.el-col-md-push-4{position:relative;left:16.66667%}.el-col-md-5{width:20.83333%}.el-col-md-offset-5{margin-left:20.83333%}.el-col-md-pull-5{position:relative;right:20.83333%}.el-col-md-push-5{position:relative;left:20.83333%}.el-col-md-6{width:25%}.el-col-md-offset-6{margin-left:25%}.el-col-md-pull-6{position:relative;right:25%}.el-col-md-push-6{position:relative;left:25%}.el-col-md-7{width:29.16667%}.el-col-md-offset-7{margin-left:29.16667%}.el-col-md-pull-7{position:relative;right:29.16667%}.el-col-md-push-7{position:relative;left:29.16667%}.el-col-md-8{width:33.33333%}.el-col-md-offset-8{margin-left:33.33333%}.el-col-md-pull-8{position:relative;right:33.33333%}.el-col-md-push-8{position:relative;left:33.33333%}.el-col-md-9{width:37.5%}.el-col-md-offset-9{margin-left:37.5%}.el-col-md-pull-9{position:relative;right:37.5%}.el-col-md-push-9{position:relative;left:37.5%}.el-col-md-10{width:41.66667%}.el-col-md-offset-10{margin-left:41.66667%}.el-col-md-pull-10{position:relative;right:41.66667%}.el-col-md-push-10{position:relative;left:41.66667%}.el-col-md-11{width:45.83333%}.el-col-md-offset-11{margin-left:45.83333%}.el-col-md-pull-11{position:relative;right:45.83333%}.el-col-md-push-11{position:relative;left:45.83333%}.el-col-md-12{width:50%}.el-col-md-offset-12{margin-left:50%}.el-col-md-pull-12{position:relative;right:50%}.el-col-md-push-12{position:relative;left:50%}.el-col-md-13{width:54.16667%}.el-col-md-offset-13{margin-left:54.16667%}.el-col-md-pull-13{position:relative;right:54.16667%}.el-col-md-push-13{position:relative;left:54.16667%}.el-col-md-14{width:58.33333%}.el-col-md-offset-14{margin-left:58.33333%}.el-col-md-pull-14{position:relative;right:58.33333%}.el-col-md-push-14{position:relative;left:58.33333%}.el-col-md-15{width:62.5%}.el-col-md-offset-15{margin-left:62.5%}.el-col-md-pull-15{position:relative;right:62.5%}.el-col-md-push-15{position:relative;left:62.5%}.el-col-md-16{width:66.66667%}.el-col-md-offset-16{margin-left:66.66667%}.el-col-md-pull-16{position:relative;right:66.66667%}.el-col-md-push-16{position:relative;left:66.66667%}.el-col-md-17{width:70.83333%}.el-col-md-offset-17{margin-left:70.83333%}.el-col-md-pull-17{position:relative;right:70.83333%}.el-col-md-push-17{position:relative;left:70.83333%}.el-col-md-18{width:75%}.el-col-md-offset-18{margin-left:75%}.el-col-md-pull-18{position:relative;right:75%}.el-col-md-push-18{position:relative;left:75%}.el-col-md-19{width:79.16667%}.el-col-md-offset-19{margin-left:79.16667%}.el-col-md-pull-19{position:relative;right:79.16667%}.el-col-md-push-19{position:relative;left:79.16667%}.el-col-md-20{width:83.33333%}.el-col-md-offset-20{margin-left:83.33333%}.el-col-md-pull-20{position:relative;right:83.33333%}.el-col-md-push-20{position:relative;left:83.33333%}.el-col-md-21{width:87.5%}.el-col-md-offset-21{margin-left:87.5%}.el-col-md-pull-21{position:relative;right:87.5%}.el-col-md-push-21{position:relative;left:87.5%}.el-col-md-22{width:91.66667%}.el-col-md-offset-22{margin-left:91.66667%}.el-col-md-pull-22{position:relative;right:91.66667%}.el-col-md-push-22{position:relative;left:91.66667%}.el-col-md-23{width:95.83333%}.el-col-md-offset-23{margin-left:95.83333%}.el-col-md-pull-23{position:relative;right:95.83333%}.el-col-md-push-23{position:relative;left:95.83333%}.el-col-md-24{width:100%}.el-col-md-offset-24{margin-left:100%}.el-col-md-pull-24{position:relative;right:100%}.el-col-md-push-24{position:relative;left:100%}}@media (min-width:1200px){.el-col-lg-0{width:0}.el-col-lg-offset-0{margin-left:0}.el-col-lg-pull-0{position:relative;right:0}.el-col-lg-push-0{position:relative;left:0}.el-col-lg-1{width:4.16667%}.el-col-lg-offset-1{margin-left:4.16667%}.el-col-lg-pull-1{position:relative;right:4.16667%}.el-col-lg-push-1{position:relative;left:4.16667%}.el-col-lg-2{width:8.33333%}.el-col-lg-offset-2{margin-left:8.33333%}.el-col-lg-pull-2{position:relative;right:8.33333%}.el-col-lg-push-2{position:relative;left:8.33333%}.el-col-lg-3{width:12.5%}.el-col-lg-offset-3{margin-left:12.5%}.el-col-lg-pull-3{position:relative;right:12.5%}.el-col-lg-push-3{position:relative;left:12.5%}.el-col-lg-4{width:16.66667%}.el-col-lg-offset-4{margin-left:16.66667%}.el-col-lg-pull-4{position:relative;right:16.66667%}.el-col-lg-push-4{position:relative;left:16.66667%}.el-col-lg-5{width:20.83333%}.el-col-lg-offset-5{margin-left:20.83333%}.el-col-lg-pull-5{position:relative;right:20.83333%}.el-col-lg-push-5{position:relative;left:20.83333%}.el-col-lg-6{width:25%}.el-col-lg-offset-6{margin-left:25%}.el-col-lg-pull-6{position:relative;right:25%}.el-col-lg-push-6{position:relative;left:25%}.el-col-lg-7{width:29.16667%}.el-col-lg-offset-7{margin-left:29.16667%}.el-col-lg-pull-7{position:relative;right:29.16667%}.el-col-lg-push-7{position:relative;left:29.16667%}.el-col-lg-8{width:33.33333%}.el-col-lg-offset-8{margin-left:33.33333%}.el-col-lg-pull-8{position:relative;right:33.33333%}.el-col-lg-push-8{position:relative;left:33.33333%}.el-col-lg-9{width:37.5%}.el-col-lg-offset-9{margin-left:37.5%}.el-col-lg-pull-9{position:relative;right:37.5%}.el-col-lg-push-9{position:relative;left:37.5%}.el-col-lg-10{width:41.66667%}.el-col-lg-offset-10{margin-left:41.66667%}.el-col-lg-pull-10{position:relative;right:41.66667%}.el-col-lg-push-10{position:relative;left:41.66667%}.el-col-lg-11{width:45.83333%}.el-col-lg-offset-11{margin-left:45.83333%}.el-col-lg-pull-11{position:relative;right:45.83333%}.el-col-lg-push-11{position:relative;left:45.83333%}.el-col-lg-12{width:50%}.el-col-lg-offset-12{margin-left:50%}.el-col-lg-pull-12{position:relative;right:50%}.el-col-lg-push-12{position:relative;left:50%}.el-col-lg-13{width:54.16667%}.el-col-lg-offset-13{margin-left:54.16667%}.el-col-lg-pull-13{position:relative;right:54.16667%}.el-col-lg-push-13{position:relative;left:54.16667%}.el-col-lg-14{width:58.33333%}.el-col-lg-offset-14{margin-left:58.33333%}.el-col-lg-pull-14{position:relative;right:58.33333%}.el-col-lg-push-14{position:relative;left:58.33333%}.el-col-lg-15{width:62.5%}.el-col-lg-offset-15{margin-left:62.5%}.el-col-lg-pull-15{position:relative;right:62.5%}.el-col-lg-push-15{position:relative;left:62.5%}.el-col-lg-16{width:66.66667%}.el-col-lg-offset-16{margin-left:66.66667%}.el-col-lg-pull-16{position:relative;right:66.66667%}.el-col-lg-push-16{position:relative;left:66.66667%}.el-col-lg-17{width:70.83333%}.el-col-lg-offset-17{margin-left:70.83333%}.el-col-lg-pull-17{position:relative;right:70.83333%}.el-col-lg-push-17{position:relative;left:70.83333%}.el-col-lg-18{width:75%}.el-col-lg-offset-18{margin-left:75%}.el-col-lg-pull-18{position:relative;right:75%}.el-col-lg-push-18{position:relative;left:75%}.el-col-lg-19{width:79.16667%}.el-col-lg-offset-19{margin-left:79.16667%}.el-col-lg-pull-19{position:relative;right:79.16667%}.el-col-lg-push-19{position:relative;left:79.16667%}.el-col-lg-20{width:83.33333%}.el-col-lg-offset-20{margin-left:83.33333%}.el-col-lg-pull-20{position:relative;right:83.33333%}.el-col-lg-push-20{position:relative;left:83.33333%}.el-col-lg-21{width:87.5%}.el-col-lg-offset-21{margin-left:87.5%}.el-col-lg-pull-21{position:relative;right:87.5%}.el-col-lg-push-21{position:relative;left:87.5%}.el-col-lg-22{width:91.66667%}.el-col-lg-offset-22{margin-left:91.66667%}.el-col-lg-pull-22{position:relative;right:91.66667%}.el-col-lg-push-22{position:relative;left:91.66667%}.el-col-lg-23{width:95.83333%}.el-col-lg-offset-23{margin-left:95.83333%}.el-col-lg-pull-23{position:relative;right:95.83333%}.el-col-lg-push-23{position:relative;left:95.83333%}.el-col-lg-24{width:100%}.el-col-lg-offset-24{margin-left:100%}.el-col-lg-pull-24{position:relative;right:100%}.el-col-lg-push-24{position:relative;left:100%}}.el-progress-bar__inner:after{display:inline-block;height:100%;vertical-align:middle}.el-upload{display:inline-block;text-align:center;cursor:pointer}.el-upload iframe{position:absolute;z-index:-1;top:0;left:0;opacity:0;filter:alpha(opacity=0)}.el-upload__input{display:none}.el-upload__tip{font-size:12px;color:#8391a5;margin-top:7px}.el-upload--picture-card{background-color:#fbfdff;border:1px dashed #c0ccda;border-radius:6px;box-sizing:border-box;width:148px;height:148px;cursor:pointer;line-height:146px;vertical-align:top}.el-upload--picture-card i{font-size:28px;color:#8c939d}.el-upload--picture-card:hover{border-color:#20a0ff;color:#20a0ff}.el-upload-dragger{background-color:#fff;border:1px dashed #d9d9d9;border-radius:6px;box-sizing:border-box;width:360px;height:180px;text-align:center;cursor:pointer;position:relative;overflow:hidden}.el-upload-dragger .el-upload__text{color:#97a8be;font-size:14px;text-align:center}.el-upload-dragger .el-upload__text em{color:#20a0ff;font-style:normal}.el-upload-dragger .el-icon-upload{font-size:67px;color:#97a8be;margin:40px 0 16px;line-height:50px}.el-upload-dragger+.el-upload__tip{text-align:center}.el-upload-dragger~.el-upload__files{border-top:1px solid rgba(191,203,217,.2);margin-top:7px;padding-top:5px}.el-upload-dragger:hover{border-color:#20a0ff}.el-upload-dragger.is-dragover{background-color:rgba(32,159,255,.06);border:2px dashed #20a0ff}.el-upload-list{margin:0;padding:0;list-style:none}.el-upload-list.is-disabled .el-upload-list__item:hover .el-upload-list__item-status-label{display:block}.el-upload-list__item{transition:all .5s cubic-bezier(.55,0,.1,1);font-size:14px;color:#48576a;line-height:1.8;margin-top:5px;box-sizing:border-box;border-radius:4px;width:100%;position:relative}.el-upload-list__item .el-progress-bar{margin-right:0;padding-right:0}.el-upload-list__item .el-progress{position:absolute;top:20px;width:100%}.el-upload-list__item .el-progress__text{position:absolute;top:-13px;right:0}.el-upload-list__item:first-child{margin-top:10px}.el-upload-list__item .el-icon-upload-success{color:#13ce66}.el-upload-list__item .el-icon-close{display:none;position:absolute;top:5px;right:5px;cursor:pointer;opacity:.75;color:#48576a;-ms-transform:scale(.7);transform:scale(.7)}.el-upload-list__item .el-icon-close:hover{opacity:1}.el-upload-list__item:hover{background-color:#eef1f6}.el-upload-list__item:hover .el-icon-close{display:inline-block}.el-upload-list__item:hover .el-progress__text{display:none}.el-upload-list__item.is-success .el-upload-list__item-status-label{display:block}.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#20a0ff;cursor:pointer}.el-upload-list__item.is-success:hover .el-upload-list__item-status-label{display:none}.el-upload-list__item-name{color:#48576a;display:block;margin-right:40px;overflow:hidden;padding-left:4px;text-overflow:ellipsis;transition:color .3s}.el-upload-list__item-name [class^=el-icon]{color:#97a8be;margin-right:7px;height:100%;line-height:inherit}.el-upload-list__item-status-label{position:absolute;right:5px;top:0;line-height:inherit;display:none}.el-upload-list__item-delete{position:absolute;right:10px;top:0;font-size:12px;color:#48576a;display:none}.el-upload-list__item-delete:hover{color:#20a0ff}.el-upload-list--picture-card{margin:0;display:inline;vertical-align:top}.el-upload-list--picture-card .el-upload-list__item{overflow:hidden;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;box-sizing:border-box;width:148px;height:148px;margin:0 8px 8px 0;display:inline-block}.el-upload-list--picture-card .el-upload-list__item .el-icon-check,.el-upload-list--picture-card .el-upload-list__item .el-icon-circle-check{color:#fff}.el-upload-list--picture-card .el-upload-list__item .el-icon-close,.el-upload-list--picture-card .el-upload-list__item:hover .el-upload-list__item-status-label{display:none}.el-upload-list--picture-card .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture-card .el-upload-list__item-name{display:none}.el-upload-list--picture-card .el-upload-list__item-thumbnail{width:100%;height:100%}.el-upload-list--picture-card .el-upload-list__item-status-label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;-ms-transform:rotate(45deg);transform:rotate(45deg);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.el-upload-list--picture-card .el-upload-list__item-status-label i{font-size:12px;margin-top:11px;-ms-transform:rotate(-45deg) scale(.8);transform:rotate(-45deg) scale(.8)}.el-upload-list--picture-card .el-upload-list__item-actions{position:absolute;width:100%;height:100%;left:0;top:0;cursor:default;text-align:center;color:#fff;opacity:0;font-size:20px;background-color:rgba(0,0,0,.5);transition:opacity .3s}.el-upload-list--picture-card .el-upload-list__item-actions:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-upload-list--picture-card .el-upload-list__item-actions span{display:none;cursor:pointer}.el-upload-list--picture-card .el-upload-list__item-actions span+span{margin-left:15px}.el-upload-list--picture-card .el-upload-list__item-actions .el-upload-list__item-delete{position:static;font-size:inherit;color:inherit}.el-upload-list--picture-card .el-upload-list__item-actions:hover{opacity:1}.el-upload-list--picture-card .el-upload-list__item-actions:hover span{display:inline-block}.el-upload-list--picture-card .el-progress{top:50%;left:50%;-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);bottom:auto;width:126px}.el-upload-list--picture-card .el-progress .el-progress__text{top:50%}.el-upload-list--picture .el-upload-list__item{overflow:hidden;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;box-sizing:border-box;margin-top:10px;padding:10px 10px 10px 90px;height:92px}.el-upload-list--picture .el-upload-list__item .el-icon-check,.el-upload-list--picture .el-upload-list__item .el-icon-circle-check{color:#fff}.el-upload-list--picture .el-upload-list__item:hover .el-upload-list__item-status-label{background:0 0;box-shadow:none;top:-2px;right:-12px}.el-upload-list--picture .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name{line-height:70px;margin-top:0}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name i{display:none}.el-upload-list--picture .el-upload-list__item-thumbnail{vertical-align:middle;display:inline-block;width:70px;height:70px;float:left;position:relative;z-index:1;margin-left:-80px}.el-upload-list--picture .el-upload-list__item-name{display:block;margin-top:20px}.el-upload-list--picture .el-upload-list__item-name i{font-size:70px;line-height:1;position:absolute;left:9px;top:10px}.el-upload-list--picture .el-upload-list__item-status-label{position:absolute;right:-17px;top:-7px;width:46px;height:26px;background:#13ce66;text-align:center;-ms-transform:rotate(45deg);transform:rotate(45deg);box-shadow:0 1px 1px #ccc}.el-upload-list--picture .el-upload-list__item-status-label i{font-size:12px;margin-top:12px;-ms-transform:rotate(-45deg) scale(.8);transform:rotate(-45deg) scale(.8)}.el-upload-list--picture .el-progress{position:relative;top:-7px}.el-upload-cover{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;z-index:10;cursor:default}.el-upload-cover:after{display:inline-block;height:100%;vertical-align:middle}.el-upload-cover img{display:block;width:100%;height:100%}.el-upload-cover+.el-upload__inner{opacity:0;position:relative;z-index:1}.el-upload-cover__label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;-ms-transform:rotate(45deg);transform:rotate(45deg);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.el-upload-cover__label i{font-size:12px;margin-top:11px;-ms-transform:rotate(-45deg) scale(.8);transform:rotate(-45deg) scale(.8);color:#fff}.el-upload-cover__progress{display:inline-block;vertical-align:middle;position:static;width:243px}.el-upload-cover__progress+.el-upload__inner{opacity:0}.el-upload-cover__content{position:absolute;top:0;left:0;width:100%;height:100%}.el-upload-cover__interact{position:absolute;bottom:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.72);text-align:center}.el-upload-cover__interact .btn{display:inline-block;color:#fff;font-size:14px;cursor:pointer;vertical-align:middle;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;margin-top:60px}.el-upload-cover__interact .btn span{opacity:0;transition:opacity .15s linear}.el-upload-cover__interact .btn:not(:first-child){margin-left:35px}.el-upload-cover__interact .btn:hover{-ms-transform:translateY(-13px);transform:translateY(-13px)}.el-upload-cover__interact .btn:hover span{opacity:1}.el-upload-cover__interact .btn i{color:#fff;display:block;font-size:24px;line-height:inherit;margin:0 auto 5px}.el-upload-cover__title{position:absolute;bottom:0;left:0;background-color:#fff;height:36px;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400;text-align:left;padding:0 10px;margin:0;line-height:36px;font-size:14px;color:#48576a}.el-progress{position:relative;line-height:1}.el-progress.is-exception .el-progress-bar__inner{background-color:#ff4949}.el-progress.is-exception .el-progress__text{color:#ff4949}.el-progress.is-success .el-progress-bar__inner{background-color:#13ce66}.el-progress.is-success .el-progress__text{color:#13ce66}.el-progress__text{font-size:14px;color:#48576a;display:inline-block;vertical-align:middle;margin-left:10px;line-height:1}.el-progress__text i{vertical-align:middle;display:block}.el-progress--circle{display:inline-block}.el-progress--circle .el-progress__text{position:absolute;top:50%;left:0;width:100%;text-align:center;margin:0;-ms-transform:translateY(-50%);transform:translateY(-50%)}.el-progress--circle .el-progress__text i{vertical-align:middle;display:inline-block}.el-progress--without-text .el-progress__text{display:none}.el-progress--without-text .el-progress-bar{padding-right:0;margin-right:0;display:block}.el-progress-bar,.el-progress-bar__innerText,.el-spinner{display:inline-block;vertical-align:middle}.el-progress--text-inside .el-progress-bar{padding-right:0;margin-right:0}.el-progress-bar{padding-right:50px;width:100%;margin-right:-55px;box-sizing:border-box}.el-progress-bar__outer{height:6px;border-radius:100px;background-color:#e4e8f1;overflow:hidden;position:relative;vertical-align:middle}.el-progress-bar__inner{position:absolute;left:0;top:0;height:100%;background-color:#20a0ff;text-align:right;border-radius:100px;line-height:1}.el-progress-bar__innerText{color:#fff;font-size:12px;margin:0 5px}@keyframes progress{0%{background-position:0 0}to{background-position:32px 0}}.el-time-spinner{width:100%}.el-spinner-inner{animation:rotate 2s linear infinite;width:50px;height:50px}.el-spinner-inner .path{stroke:#ececec;stroke-linecap:round;animation:dash 1.5s ease-in-out infinite}@keyframes rotate{to{transform:rotate(1turn)}}@keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}to{stroke-dasharray:90,150;stroke-dashoffset:-124}}.el-message{box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);min-width:300px;padding:10px 12px;box-sizing:border-box;border-radius:2px;position:fixed;left:50%;top:20px;-ms-transform:translateX(-50%);transform:translateX(-50%);background-color:#fff;transition:opacity .3s,transform .4s;overflow:hidden}.el-message .el-icon-circle-check{color:#13ce66}.el-message .el-icon-circle-cross{color:#ff4949}.el-message .el-icon-information{color:#50bfff}.el-message .el-icon-warning{color:#f7ba2a}.el-message__group{margin-left:38px;position:relative;height:20px;line-height:20px;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.el-message__group p{font-size:14px;margin:0 34px 0 0;color:#8391a5;text-align:justify}.el-step__head,.el-steps.is-horizontal.is-center{text-align:center}.el-message__group.is-with-icon{margin-left:0}.el-message__img{width:40px;height:40px;position:absolute;left:0;top:0}.el-message__icon{vertical-align:middle;margin-right:8px}.el-message__closeBtn{top:3px;right:0;position:absolute;cursor:pointer;color:#bfcbd9;font-size:14px}.el-message__closeBtn:hover{color:#97a8be}.el-message-fade-enter,.el-message-fade-leave-active{opacity:0;-ms-transform:translate(-50%,-100%);transform:translate(-50%,-100%)}.el-badge{position:relative;vertical-align:middle;display:inline-block}.el-badge__content{background-color:#ff4949;border-radius:10px;color:#fff;display:inline-block;font-size:12px;height:18px;line-height:18px;padding:0 6px;text-align:center;border:1px solid #fff}.el-badge__content.is-dot{width:8px;height:8px;padding:0;right:0;border-radius:50%}.el-badge__content.is-fixed{top:0;right:10px;position:absolute;-ms-transform:translateY(-50%) translateX(100%);transform:translateY(-50%) translateX(100%)}.el-rate__icon,.el-rate__item{position:relative;display:inline-block}.el-badge__content.is-fixed.is-dot{right:5px}.el-card{border:1px solid #d1dbe5;border-radius:4px;background-color:#fff;overflow:hidden;box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.el-card__header{padding:18px 20px;border-bottom:1px solid #d1dbe5;box-sizing:border-box}.el-card__body{padding:20px}.el-rate{height:20px;line-height:1}.el-rate__item{font-size:0;vertical-align:middle}.el-rate__icon{font-size:18px;margin-right:6px;color:#bfcbd9;transition:.3s}.el-rate__decimal,.el-rate__icon .path2{position:absolute;top:0;left:0}.el-rate__icon.hover{-ms-transform:scale(1.15);transform:scale(1.15)}.el-rate__decimal{display:inline-block;overflow:hidden}.el-rate__text{font-size:14px;vertical-align:middle}.el-steps{font-size:0}.el-steps>:last-child .el-step__line{display:none}.el-step.is-horizontal,.el-step.is-vertical .el-step__head,.el-step.is-vertical .el-step__main,.el-step__line{display:inline-block}.el-step{position:relative;vertical-align:top}.el-step:last-child .el-step__main{padding-right:0}.el-step.is-vertical .el-step__main{padding-left:10px}.el-step__line{position:absolute;border-color:inherit;background-color:#bfcbd9}.el-step__line.is-vertical{width:2px;box-sizing:border-box;top:32px;bottom:0;left:15px}.el-step__line.is-horizontal{top:15px;height:2px;left:32px;right:0}.el-step__line.is-icon.is-horizontal{right:4px}.el-step__line-inner{display:block;border-width:1px;border-style:solid;border-color:inherit;transition:all .15s;box-sizing:border-box;width:0;height:0}.el-step__icon{display:block;line-height:28px}.el-step__icon>*{line-height:inherit;vertical-align:middle}.el-step__head{width:28px;height:28px;border-radius:50%;background-color:transparent;line-height:28px;font-size:28px;vertical-align:top;transition:all .15s}.el-carousel__arrow,.el-carousel__button{margin:0;transition:.3s;cursor:pointer;outline:0}.el-step__head.is-finish{color:#20a0ff;border-color:#20a0ff}.el-step__head.is-error{color:#ff4949;border-color:#ff4949}.el-step__head.is-success{color:#13ce66;border-color:#13ce66}.el-step__head.is-process,.el-step__head.is-wait{color:#bfcbd9;border-color:#bfcbd9}.el-step__head.is-text{font-size:14px;border-width:2px;border-style:solid}.el-step__head.is-text.is-finish{color:#fff;background-color:#20a0ff;border-color:#20a0ff}.el-step__head.is-text.is-error{color:#fff;background-color:#ff4949;border-color:#ff4949}.el-step__head.is-text.is-success{color:#fff;background-color:#13ce66;border-color:#13ce66}.el-step__head.is-text.is-wait{color:#bfcbd9;background-color:#fff;border-color:#bfcbd9}.el-step__head.is-text.is-process{color:#fff;background-color:#bfcbd9;border-color:#bfcbd9}.el-step__main{white-space:normal;padding-right:10px;text-align:left}.el-step__title{font-size:14px;line-height:32px;display:inline-block}.el-step__title.is-finish{font-weight:700;color:#20a0ff}.el-step__title.is-error{font-weight:700;color:#ff4949}.el-step__title.is-success{font-weight:700;color:#13ce66}.el-step__title.is-wait{font-weight:400;color:#97a8be}.el-step__title.is-process{font-weight:700;color:#48576a}.el-step__description{font-size:12px;font-weight:400;line-height:14px}.el-step__description.is-finish{color:#20a0ff}.el-step__description.is-error{color:#ff4949}.el-step__description.is-success{color:#13ce66}.el-step__description.is-wait{color:#bfcbd9}.el-step__description.is-process{color:#8391a5}.el-carousel{overflow-x:hidden;position:relative}.el-carousel__container{position:relative;height:300px}.el-carousel__arrow{border:none;padding:0;width:36px;height:36px;border-radius:50%;background-color:rgba(31,45,61,.11);color:#fff;position:absolute;top:50%;z-index:10;-ms-transform:translateY(-50%);transform:translateY(-50%);text-align:center;font-size:12px}.el-carousel__arrow:hover{background-color:rgba(31,45,61,.23)}.el-carousel__arrow i{cursor:pointer}.el-carousel__arrow--left{left:16px}.el-carousel__arrow--right{right:16px}.el-carousel__indicators{position:absolute;list-style:none;bottom:0;left:50%;-ms-transform:translateX(-50%);transform:translateX(-50%);margin:0;padding:0;z-index:2}.el-carousel__indicators--outside{bottom:26px;text-align:center;position:static;-ms-transform:none;transform:none}.el-carousel__indicators--outside .el-carousel__indicator:hover button{opacity:.64}.el-carousel__indicators--outside button{background-color:#8391a5;opacity:.24}.el-carousel__indicators--labels{left:0;right:0;-ms-transform:none;transform:none;text-align:center}.el-carousel__indicators--labels .el-carousel__button{width:auto;height:auto;padding:2px 18px;font-size:12px}.el-carousel__indicators--labels .el-carousel__indicator{padding:6px 4px}.el-carousel__indicator{display:inline-block;background-color:transparent;padding:12px 4px;cursor:pointer}.el-carousel__indicator:hover button{opacity:.72}.el-carousel__indicator.is-active button{opacity:1}.el-carousel__button{display:block;opacity:.48;width:30px;height:2px;background-color:#fff;border:none;padding:0}.carousel-arrow-left-enter,.carousel-arrow-left-leave-active{-ms-transform:translateY(-50%) translateX(-10px);transform:translateY(-50%) translateX(-10px);opacity:0}.carousel-arrow-right-enter,.carousel-arrow-right-leave-active{-ms-transform:translateY(-50%) translateX(10px);transform:translateY(-50%) translateX(10px);opacity:0}.el-scrollbar{overflow:hidden;position:relative}.el-scrollbar:active .el-scrollbar__bar,.el-scrollbar:focus .el-scrollbar__bar,.el-scrollbar:hover .el-scrollbar__bar{opacity:1;transition:opacity .34s ease-out}.el-scrollbar__wrap{overflow:scroll}.el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(151,168,190,.3);transition:background-color .3s}.el-scrollbar__thumb:hover{background-color:rgba(151,168,190,.5)}.el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;transition:opacity .12s ease-out}.el-carousel__item--card,.el-carousel__item.is-animating{transition:transform .4s ease-in-out}.el-scrollbar__bar.is-horizontal{height:6px;left:2px}.el-scrollbar__bar.is-horizontal>div{height:100%}.el-scrollbar__bar.is-vertical{width:6px;top:2px}.el-scrollbar__bar.is-vertical>div{width:100%}.el-carousel__item{position:absolute;top:0;left:0;width:100%;height:100%;display:inline-block;overflow:hidden;z-index:0}.el-carousel__item.is-active{z-index:2}.el-carousel__item--card{width:50%}.el-carousel__item--card.is-in-stage{cursor:pointer;z-index:1}.el-carousel__item--card.is-active,.el-cascader-menus,.el-cascader .el-icon-circle-close{z-index:2}.el-carousel__item--card.is-in-stage.is-hover .el-carousel__mask,.el-carousel__item--card.is-in-stage:hover .el-carousel__mask{opacity:.12}.el-carousel__mask{position:absolute;width:100%;height:100%;top:0;left:0;background-color:#fff;opacity:.24;transition:.2s}.el-collapse{border:1px solid #dfe6ec;border-radius:0}.el-collapse-item:last-child{margin-bottom:-1px}.el-collapse-item.is-active>.el-collapse-item__header .el-collapse-item__header__arrow{-ms-transform:rotate(90deg);transform:rotate(90deg)}.el-collapse-item__header{height:43px;line-height:43px;padding-left:15px;background-color:#fff;color:#48576a;cursor:pointer;border-bottom:1px solid #dfe6ec;font-size:13px}.el-collapse-item__header__arrow{margin-right:8px;transition:transform .3s}.el-collapse-item__wrap{will-change:height;background-color:#fbfdff;overflow:hidden;box-sizing:border-box;border-bottom:1px solid #dfe6ec}.el-collapse-item__content{padding:10px 15px;font-size:13px;color:#1f2d3d;line-height:1.769230769230769}.el-cascader{display:inline-block;position:relative}.el-cascader .el-input,.el-cascader .el-input__inner{cursor:pointer}.el-cascader .el-input__icon{transition:none}.el-cascader .el-icon-caret-bottom{transition:transform .3s}.el-cascader .el-icon-caret-bottom.is-reverse{-ms-transform:rotate(180deg);transform:rotate(180deg)}.el-cascader.is-disabled .el-cascader__label{z-index:2;color:#bbb}.el-cascader__label{position:absolute;left:0;top:0;height:100%;line-height:36px;padding:0 25px 0 10px;color:#1f2d3d;width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;box-sizing:border-box;cursor:pointer;font-size:14px;text-align:left}.el-cascader__label span{color:#97a8be}.el-cascader--large{font-size:16px}.el-cascader--large .el-cascader__label{line-height:40px}.el-cascader--small{font-size:13px}.el-cascader--small .el-cascader__label{line-height:28px}.el-cascader-menus{white-space:nowrap;background:#fff;position:absolute;margin:5px 0;border:1px solid #d1dbe5;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04)}.el-cascader-menu{display:inline-block;vertical-align:top;height:204px;overflow:auto;border-right:1px solid #d1dbe5;background-color:#fff;box-sizing:border-box;margin:0;padding:6px 0;min-width:160px}.el-cascader-menu:last-child{border-right:0}.el-cascader-menu__item{font-size:14px;padding:8px 30px 8px 10px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#48576a;height:36px;line-height:1.5;box-sizing:border-box;cursor:pointer}.el-cascader-menu__item:hover{background-color:#e4e8f1}.el-cascader-menu__item.selected{color:#fff;background-color:#20a0ff}.el-cascader-menu__item.selected.hover{background-color:#1c8de0}.el-cascader-menu__item.is-active{color:#fff;background-color:#20a0ff}.el-cascader-menu__item.is-active:hover{background-color:#1c8de0}.el-cascader-menu__item.is-disabled{color:#bfcbd9;background-color:#fff;cursor:not-allowed}.el-cascader-menu__item.is-disabled:hover{background-color:#fff}.el-cascader-menu__item__keyword{font-weight:700}.el-cascader-menu__item--extensible:after{font-family:element-icons;content:\"\\\\E606\";font-size:12px;-ms-transform:scale(.8);transform:scale(.8);color:#bfcbd9;position:absolute;right:10px;margin-top:1px}.el-cascader-menu--flexible{height:auto;max-height:180px;overflow:auto}.el-cascader-menu--flexible .el-cascader-menu__item{overflow:visible}.el-color-hue-slider{position:relative;box-sizing:border-box;width:280px;height:12px;background-color:red;padding:0 2px}.el-color-hue-slider.is-vertical{width:12px;height:180px;padding:2px 0}.el-color-hue-slider.is-vertical .el-color-hue-slider__bar{background:linear-gradient(180deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red)}.el-color-hue-slider.is-vertical .el-color-hue-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-hue-slider__bar{position:relative;background:linear-gradient(90deg,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red);height:100%}.el-color-hue-slider__thumb{position:absolute;cursor:pointer;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.el-color-svpanel{position:relative;width:280px;height:180px}.el-color-svpanel__black,.el-color-svpanel__white{position:absolute;top:0;left:0;right:0;bottom:0}.el-color-svpanel__white{background:linear-gradient(90deg,#fff,hsla(0,0%,100%,0))}.el-color-svpanel__black{background:linear-gradient(0deg,#000,transparent)}.el-color-svpanel__cursor{position:absolute}.el-color-svpanel__cursor>div{cursor:head;width:4px;height:4px;box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);border-radius:50%;-ms-transform:translate(-2px,-2px);transform:translate(-2px,-2px)}.el-color-alpha-slider{position:relative;box-sizing:border-box;width:280px;height:12px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-alpha-slider.is-vertical{width:20px;height:180px}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__bar{background:linear-gradient(180deg,hsla(0,0%,100%,0) 0,#fff)}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-alpha-slider__bar{position:relative;background:linear-gradient(90deg,hsla(0,0%,100%,0) 0,#fff);height:100%}.el-color-alpha-slider__thumb{position:absolute;cursor:pointer;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.el-color-dropdown{width:300px}.el-color-dropdown__main-wrapper{margin-bottom:6px}.el-color-dropdown__main-wrapper:after{content:\"\";display:table;clear:both}.el-color-dropdown__btns{margin-top:6px;text-align:right}.el-color-dropdown__value{float:left;line-height:26px;font-size:12px;color:#1f2d3d}.el-color-dropdown__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.el-color-dropdown__btn[disabled]{color:#ccc;cursor:not-allowed}.el-color-dropdown__btn:hover{color:#20a0ff;border-color:#20a0ff}.el-color-dropdown__link-btn{cursor:pointer;color:#20a0ff;text-decoration:none;padding:15px;font-size:12px}.el-color-dropdown__link-btn:hover{color:#4db3ff}.el-color-picker{display:inline-block;position:relative;line-height:normal}.el-color-picker__trigger{display:inline-block;box-sizing:border-box;height:36px;padding:6px;border:1px solid #bfcbd9;border-radius:4px;font-size:0}.el-color-picker__color{position:relative;display:inline-block;box-sizing:border-box;border:1px solid #666;width:22px;height:22px;text-align:center}.el-color-picker__color.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-picker__color-inner{position:absolute;left:0;top:0;right:0;bottom:0}.el-color-picker__empty{font-size:12px;vertical-align:middle;color:#666;position:absolute;top:4px;left:4px}.el-color-picker__icon{display:inline-block;position:relative;top:-6px;margin-left:8px;width:12px;color:#888;font-size:12px}.el-input,.el-input__inner{width:100%;display:inline-block}.el-color-picker__panel{position:absolute;z-index:10;padding:6px;background-color:#fff;border:1px solid #d1dbe5;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.12)}.el-input{position:relative;font-size:14px}.el-input.is-disabled .el-input__inner{background-color:#eef1f6;border-color:#d1dbe5;color:#bbb;cursor:not-allowed}.el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#bfcbd9}.el-input.is-disabled .el-input__inner::-moz-placeholder{color:#bfcbd9}.el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#bfcbd9}.el-input.is-disabled .el-input__inner::placeholder{color:#bfcbd9}.el-input.is-active .el-input__inner{outline:0;border-color:#20a0ff}.el-input__inner{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #bfcbd9;box-sizing:border-box;color:#1f2d3d;font-size:inherit;height:36px;line-height:1;outline:0;padding:3px 10px;transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-button,.el-checkbox-button__inner{-webkit-appearance:none;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;outline:0;text-align:center}.el-input__inner::-webkit-input-placeholder{color:#97a8be}.el-input__inner::-moz-placeholder{color:#97a8be}.el-input__inner:-ms-input-placeholder{color:#97a8be}.el-input__inner::placeholder{color:#97a8be}.el-input__inner:hover{border-color:#8391a5}.el-input__inner:focus{outline:0;border-color:#20a0ff}.el-input__icon{position:absolute;width:35px;height:100%;right:0;top:0;text-align:center;color:#bfcbd9;transition:all .3s}.el-input__icon:after{content:\"\";height:100%;width:0;display:inline-block;vertical-align:middle}.el-input__icon+.el-input__inner{padding-right:35px}.el-input__icon.is-clickable:hover{cursor:pointer;color:#8391a5}.el-input__icon.is-clickable:hover+.el-input__inner{border-color:#8391a5}.el-input--large{font-size:16px}.el-input--large .el-input__inner{height:42px}.el-input--small{font-size:13px}.el-input--small .el-input__inner{height:30px}.el-input--mini{font-size:12px}.el-input--mini .el-input__inner{height:22px}.el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.el-input-group__append,.el-input-group__prepend{background-color:#fbfdff;color:#97a8be;vertical-align:middle;display:table-cell;position:relative;border:1px solid #bfcbd9;border-radius:4px;padding:0 10px;width:1px;white-space:nowrap}.el-input-group--prepend .el-input__inner,.el-input-group__append{border-top-left-radius:0;border-bottom-left-radius:0}.el-input-group--append .el-input__inner,.el-input-group__prepend{border-top-right-radius:0;border-bottom-right-radius:0}.el-input-group__append .el-button,.el-input-group__append .el-select,.el-input-group__prepend .el-button,.el-input-group__prepend .el-select{display:block;margin:-10px}.el-input-group__append button.el-button,.el-input-group__append div.el-select .el-input__inner,.el-input-group__append div.el-select:hover .el-input__inner,.el-input-group__prepend button.el-button,.el-input-group__prepend div.el-select .el-input__inner,.el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.el-input-group__append .el-button,.el-input-group__append .el-input,.el-input-group__prepend .el-button,.el-input-group__prepend .el-input{font-size:inherit}.el-button,.el-textarea__inner{font-size:14px;box-sizing:border-box}.el-input-group__prepend{border-right:0}.el-input-group__append{border-left:0}.el-textarea{display:inline-block;width:100%;vertical-align:bottom}.el-textarea.is-disabled .el-textarea__inner{background-color:#eef1f6;border-color:#d1dbe5;color:#bbb;cursor:not-allowed}.el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#bfcbd9}.el-textarea.is-disabled .el-textarea__inner::-moz-placeholder{color:#bfcbd9}.el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#bfcbd9}.el-textarea.is-disabled .el-textarea__inner::placeholder{color:#bfcbd9}.el-textarea__inner{display:block;resize:vertical;padding:5px 7px;line-height:1.5;width:100%;color:#1f2d3d;background-color:#fff;background-image:none;border:1px solid #bfcbd9;border-radius:4px;transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-textarea__inner::-webkit-input-placeholder{color:#97a8be}.el-textarea__inner::-moz-placeholder{color:#97a8be}.el-textarea__inner:-ms-input-placeholder{color:#97a8be}.el-textarea__inner::placeholder{color:#97a8be}.el-textarea__inner:hover{border-color:#8391a5}.el-textarea__inner:focus{outline:0;border-color:#20a0ff}.el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#fff;border:1px solid #c4c4c4;color:#1f2d3d;margin:0;padding:10px 15px;border-radius:4px}.el-button+.el-button{margin-left:10px}.el-button:focus,.el-button:hover{color:#20a0ff;border-color:#20a0ff}.el-button:active{color:#1d90e6;border-color:#1d90e6;outline:0}.el-button::-moz-focus-inner{border:0}.el-button [class*=el-icon-]+span{margin-left:5px}.el-button.is-loading{position:relative;pointer-events:none}.el-button.is-loading:before{pointer-events:none;content:\"\";position:absolute;left:-1px;top:-1px;right:-1px;bottom:-1px;border-radius:inherit;background-color:hsla(0,0%,100%,.35)}.el-button.is-disabled,.el-button.is-disabled:focus,.el-button.is-disabled:hover{color:#bfcbd9;cursor:not-allowed;background-image:none;background-color:#eef1f6;border-color:#d1dbe5}.el-checkbox,.el-checkbox__input{cursor:pointer;display:inline-block;position:relative;white-space:nowrap}.el-button.is-disabled.el-button--text{background-color:transparent}.el-button.is-disabled.is-plain,.el-button.is-disabled.is-plain:focus,.el-button.is-disabled.is-plain:hover{background-color:#fff;border-color:#d1dbe5;color:#bfcbd9}.el-button.is-active{color:#1d90e6;border-color:#1d90e6}.el-button.is-plain:focus,.el-button.is-plain:hover{background:#fff;border-color:#20a0ff;color:#20a0ff}.el-button.is-plain:active{background:#fff;border-color:#1d90e6;color:#1d90e6;outline:0}.el-button--primary{color:#fff;background-color:#20a0ff;border-color:#20a0ff}.el-button--primary:focus,.el-button--primary:hover{background:#4db3ff;border-color:#4db3ff;color:#fff}.el-button--primary.is-active,.el-button--primary:active{background:#1d90e6;border-color:#1d90e6;color:#fff}.el-button--primary:active{outline:0}.el-button--primary.is-plain{background:#fff;border:1px solid #bfcbd9;color:#1f2d3d}.el-button--primary.is-plain:focus,.el-button--primary.is-plain:hover{background:#fff;border-color:#20a0ff;color:#20a0ff}.el-button--primary.is-plain:active{background:#fff;border-color:#1d90e6;color:#1d90e6;outline:0}.el-button--success{color:#fff;background-color:#13ce66;border-color:#13ce66}.el-button--success:focus,.el-button--success:hover{background:#42d885;border-color:#42d885;color:#fff}.el-button--success.is-active,.el-button--success:active{background:#11b95c;border-color:#11b95c;color:#fff}.el-button--success:active{outline:0}.el-button--success.is-plain{background:#fff;border:1px solid #bfcbd9;color:#1f2d3d}.el-button--success.is-plain:focus,.el-button--success.is-plain:hover{background:#fff;border-color:#13ce66;color:#13ce66}.el-button--success.is-plain:active{background:#fff;border-color:#11b95c;color:#11b95c;outline:0}.el-button--warning{color:#fff;background-color:#f7ba2a;border-color:#f7ba2a}.el-button--warning:focus,.el-button--warning:hover{background:#f9c855;border-color:#f9c855;color:#fff}.el-button--warning.is-active,.el-button--warning:active{background:#dea726;border-color:#dea726;color:#fff}.el-button--warning:active{outline:0}.el-button--warning.is-plain{background:#fff;border:1px solid #bfcbd9;color:#1f2d3d}.el-button--warning.is-plain:focus,.el-button--warning.is-plain:hover{background:#fff;border-color:#f7ba2a;color:#f7ba2a}.el-button--warning.is-plain:active{background:#fff;border-color:#dea726;color:#dea726;outline:0}.el-button--danger{color:#fff;background-color:#ff4949;border-color:#ff4949}.el-button--danger:focus,.el-button--danger:hover{background:#ff6d6d;border-color:#ff6d6d;color:#fff}.el-button--danger.is-active,.el-button--danger:active{background:#e64242;border-color:#e64242;color:#fff}.el-button--danger:active{outline:0}.el-button--danger.is-plain{background:#fff;border:1px solid #bfcbd9;color:#1f2d3d}.el-button--danger.is-plain:focus,.el-button--danger.is-plain:hover{background:#fff;border-color:#ff4949;color:#ff4949}.el-button--danger.is-plain:active{background:#fff;border-color:#e64242;color:#e64242;outline:0}.el-button--info{color:#fff;background-color:#50bfff;border-color:#50bfff}.el-button--info:focus,.el-button--info:hover{background:#73ccff;border-color:#73ccff;color:#fff}.el-button--info.is-active,.el-button--info:active{background:#48ace6;border-color:#48ace6;color:#fff}.el-button--info:active{outline:0}.el-button--info.is-plain{background:#fff;border:1px solid #bfcbd9;color:#1f2d3d}.el-button--info.is-plain:focus,.el-button--info.is-plain:hover{background:#fff;border-color:#50bfff;color:#50bfff}.el-button--info.is-plain:active{background:#fff;border-color:#48ace6;color:#48ace6;outline:0}.el-button--large{padding:11px 19px;font-size:16px;border-radius:4px}.el-button--small{padding:7px 9px;font-size:12px;border-radius:4px}.el-button--mini{padding:4px;font-size:12px;border-radius:4px}.el-button--text{border:none;color:#20a0ff;background:0 0;padding-left:0;padding-right:0}.el-button--text:focus,.el-button--text:hover{color:#4db3ff}.el-button--text:active{color:#1d90e6}.el-button-group{display:inline-block;vertical-align:middle}.el-button-group .el-button--primary:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--primary:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--success:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--success:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--warning:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--warning:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--danger:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--danger:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--info:first-child{border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--info:last-child{border-left-color:hsla(0,0%,100%,.5)}.el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:hsla(0,0%,100%,.5);border-right-color:hsla(0,0%,100%,.5)}.el-button-group .el-button{float:left;position:relative}.el-button-group .el-button+.el-button{margin-left:0}.el-button-group .el-button:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.el-button-group .el-button:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.el-button-group .el-button:not(:first-child):not(:last-child){border-radius:0}.el-button-group .el-button:not(:last-child){margin-right:-1px}.el-button-group .el-button.is-active,.el-button-group .el-button:active,.el-button-group .el-button:focus,.el-button-group .el-button:hover{z-index:1}.el-checkbox{color:#1f2d3d;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.el-checkbox+.el-checkbox{margin-left:15px}.el-checkbox__input{outline:0;line-height:1;vertical-align:middle}.el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:#20a0ff;border-color:#0190fe}.el-checkbox__input.is-indeterminate .el-checkbox__inner:before{content:\"\";position:absolute;display:block;border:1px solid #fff;margin-top:-1px;left:3px;right:3px;top:50%}.el-checkbox__input.is-indeterminate .el-checkbox__inner:after{display:none}.el-checkbox__input.is-focus .el-checkbox__inner{border-color:#20a0ff}.el-checkbox__input.is-checked .el-checkbox__inner{background-color:#20a0ff;border-color:#0190fe}.el-checkbox__input.is-checked .el-checkbox__inner:after{-ms-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.el-checkbox__input.is-disabled .el-checkbox__inner{background-color:#eef1f6;border-color:#d1dbe5;cursor:not-allowed}.el-checkbox__input.is-disabled .el-checkbox__inner:after{cursor:not-allowed;border-color:#eef1f6}.el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:#d1dbe5;border-color:#d1dbe5}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner:after{border-color:#fff}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:#d1dbe5;border-color:#d1dbe5}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner:before{border-color:#fff}.el-checkbox__input.is-disabled+.el-checkbox__label{color:#bbb;cursor:not-allowed}.el-checkbox__inner{display:inline-block;position:relative;border:1px solid #bfcbd9;border-radius:4px;box-sizing:border-box;width:18px;height:18px;background-color:#fff;z-index:1;transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.el-checkbox__inner:hover{border-color:#20a0ff}.el-checkbox__inner:after{box-sizing:content-box;content:\"\";border:2px solid #fff;border-left:0;border-top:0;height:8px;left:5px;position:absolute;top:1px;-ms-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:4px;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;-ms-transform-origin:center;transform-origin:center}.el-checkbox__original{opacity:0;outline:0;position:absolute;margin:0;width:0;height:0;left:-999px}.el-checkbox-button,.el-checkbox-button__inner{position:relative;display:inline-block}.el-checkbox__label{font-size:14px;padding-left:5px}.el-checkbox-button.is-checked .el-checkbox-button__inner{color:#fff;background-color:#20a0ff;border-color:#20a0ff;box-shadow:-1px 0 0 0 #20a0ff}.el-checkbox-button.is-disabled .el-checkbox-button__inner{color:#bfcbd9;cursor:not-allowed;background-image:none;background-color:#eef1f6;border-color:#d1dbe5;box-shadow:none}.el-checkbox-button__inner,.el-transfer-panel{background:#fff;vertical-align:middle;box-sizing:border-box}.el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:#20a0ff}.el-checkbox-button:first-child .el-checkbox-button__inner{border-left:1px solid #bfcbd9;border-radius:4px 0 0 4px;box-shadow:none!important}.el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 4px 4px 0}.el-checkbox-button__inner{line-height:1;white-space:nowrap;border:1px solid #bfcbd9;border-left:0;color:#1f2d3d;margin:0;cursor:pointer;transition:all .3s cubic-bezier(.645,.045,.355,1);padding:10px 15px;font-size:14px;border-radius:0}.el-checkbox-button__inner:hover{color:#20a0ff}.el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.el-checkbox-button__original{opacity:0;outline:0;position:absolute;margin:0;left:-999px}.el-checkbox-button--large .el-checkbox-button__inner{padding:11px 19px;font-size:16px;border-radius:0}.el-checkbox-button--small .el-checkbox-button__inner{padding:7px 9px;font-size:12px;border-radius:0}.el-checkbox-button--mini .el-checkbox-button__inner{padding:4px;font-size:12px;border-radius:0}.el-transfer{font-size:14px}.el-transfer__buttons{display:inline-block;vertical-align:middle;padding:0 10px}.el-transfer__buttons .el-button{display:block;margin:0 auto;padding:8px 12px}.el-transfer-panel__item+.el-transfer-panel__item,.el-transfer__buttons .el-button [class*=el-icon-]+span{margin-left:0}.el-transfer__buttons .el-button:first-child{margin-bottom:6px}.el-transfer-panel{border:1px solid #d1dbe5;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);display:inline-block;width:200px;position:relative}.el-transfer-panel .el-transfer-panel__header{height:36px;line-height:36px;background:#fbfdff;margin:0;padding-left:20px;border-bottom:1px solid #d1dbe5;box-sizing:border-box;color:#1f2d3d}.el-transfer-panel .el-transfer-panel__footer{height:36px;background:#fff;margin:0;padding:0;border-top:1px solid #d1dbe5;position:absolute;bottom:0;left:0;width:100%;z-index:1}.el-transfer-panel .el-transfer-panel__footer:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-transfer-panel .el-transfer-panel__footer .el-checkbox{padding-left:20px;color:#8391a5}.el-transfer-panel .el-transfer-panel__empty{margin:0;height:32px;line-height:32px;padding:6px 20px 0;color:#8391a5}.el-transfer-panel .el-checkbox__label{padding-left:14px}.el-transfer-panel .el-checkbox__inner{width:14px;height:14px;border-radius:3px}.el-transfer-panel .el-checkbox__inner:after{height:6px;width:3px;left:4px}.el-transfer-panel__body{padding-bottom:36px;height:246px}.el-transfer-panel__list{margin:0;padding:6px 0;list-style:none;height:246px;overflow:auto;box-sizing:border-box}.el-transfer-panel__list.is-filterable{height:214px}.el-transfer-panel__item{height:32px;line-height:32px;padding-left:20px;display:block}.el-transfer-panel__item .el-checkbox__label{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;box-sizing:border-box;padding-left:28px}.el-transfer-panel__item .el-checkbox__input{position:absolute;top:9px}.el-transfer-panel__item.el-checkbox{color:#48576a}.el-transfer-panel__item:hover{background:#e4e8f1}.el-transfer-panel__filter{margin-top:10px;text-align:center;padding:0 10px;width:100%;box-sizing:border-box}.el-transfer-panel__filter .el-input__inner{height:22px;width:100%;display:inline-block;box-sizing:border-box}.el-transfer-panel__filter .el-input__icon{right:10px}.el-transfer-panel__filter .el-icon-circle-close{cursor:pointer}',\"\",{version:3,sources:[\"D:/桌面/YMall-front/node_modules/element-ui/lib/theme-default/index.css\"],names:[],mappings:\"AAAiB,8LAA8L,cAAc,UAAU,CAAC,kKAAkK,iBAAiB,CAAC,AAAuG,6FAAuB,UAAU,CAAC,gDAAgD,qBAAqB,WAAW,YAAY,qBAAqB,CAAC,mDAAmD,cAAc,UAAU,CAAC,yBAAyB,UAAU,CAAC,WAAW,0BAA0B,kGAA2H,gBAAgB,iBAAiB,CAAC,uCAAuC,oCAAoC,WAAW,kBAAkB,gBAAgB,oBAAoB,oBAAoB,cAAc,wBAAwB,qBAAqB,mCAAmC,iCAAiC,CAAC,2BAA2B,eAAe,CAAC,2BAA2B,eAAe,CAAC,4BAA4B,eAAe,CAAC,yBAAyB,eAAe,CAAC,6BAA6B,eAAe,CAAC,2BAA2B,eAAe,CAAC,4BAA4B,eAAe,CAAC,0BAA0B,eAAe,CAAC,sBAAsB,eAAe,CAAC,6BAA6B,eAAe,CAAC,6BAA6B,eAAe,CAAC,6BAA6B,eAAe,CAAC,sBAAsB,eAAe,CAAC,uBAAuB,eAAe,CAAC,6BAA6B,eAAe,CAAC,8BAA8B,eAAe,CAAC,wBAAwB,eAAe,CAAC,qBAAqB,eAAe,CAAC,uBAAuB,eAAe,CAAC,yBAAyB,eAAe,CAAC,qBAAqB,eAAe,CAAC,4BAA4B,eAAe,CAAC,wBAAwB,eAAe,CAAC,qBAAqB,eAAe,CAAC,wBAAwB,eAAe,CAAC,sBAAsB,eAAe,CAAC,qBAAqB,eAAe,CAAC,wBAAwB,eAAe,CAAC,qBAAqB,eAAe,CAAC,uBAAuB,eAAe,CAAC,wBAAwB,eAAe,CAAC,sBAAsB,eAAe,CAAC,yBAAyB,eAAe,CAAC,wBAAwB,eAAe,CAAC,qBAAqB,eAAe,CAAC,wBAAwB,eAAe,CAAC,wBAAwB,eAAe,CAAC,wBAAwB,eAAe,CAAC,qBAAqB,eAAe,CAAC,iBAAiB,qCAAqC,CAAC,gBAAgB,eAAe,CAAC,eAAe,gBAAgB,CAAC,oBAAoB,GAAG,mBAAoB,CAAC,GAAK,uBAAyB,CAAC,CAAC,eAAe,mBAAmB,gBAAgB,aAAa,CAAC,2CAA2C,cAAc,UAAU,CAAC,qBAAqB,UAAU,CAAC,0CAA0C,qBAAqB,eAAe,eAAe,YAAY,iBAAiB,mBAAmB,qBAAqB,CAAC,oCAAoC,WAAW,CAAC,0CAA0C,mBAAmB,kBAAkB,WAAW,CAAC,sBAAsB,YAAY,cAAc,cAAc,CAAC,4BAA4B,SAAS,CAAC,4BAA4B,aAAa,CAAC,+BAA+B,cAAc,sBAAsB,kBAAkB,CAAC,+EAA+E,cAAc,CAAC,kDAAkD,8BAAwC,qBAAqB,yBAAyB,eAAe,SAAS,aAAa,CAAC,oEAAoE,cAAc,cAAc,CAAC,yBAAyB,0BAA0B,cAAc,CAAC,yBAAyB,0BAA0B,aAAa,CAAC,iJAAiJ,yBAAyB,eAAe,iBAAiB,YAAY,cAAc,CAAC,mCAAmC,iBAAiB,CAAC,sBAAsB,iBAAiB,CAAC,iDAAiD,eAAe,oBAAoB,CAAC,uDAAuD,oBAAoB,CAAC,qBAAqB,gBAAgB,CAAC,sBAAsB,aAAa,CAAC,6BAA6B,WAAW,CAAC,uBAAuB,yBAAyB,kBAAkB,iBAAiB,gBAAgB,WAAW,kBAAkB,aAAa,sBAAsB,sBAAsB,yBAAyB,CAAC,uBAAuB,mBAAmB,qBAAqB,QAAQ,CAAC,oGAAoG,wBAAwB,QAAQ,CAAC,6BAA6B,UAAU,oBAAoB,CAAC,+CAA+C,yBAAyB,qBAAqB,CAAC,UAAmC,sBAAsB,AAAqB,iBAAiB,gBAAgB,YAAY,SAAS,CAAC,mCAA3H,yBAAyB,AAAsB,oBAAqB,CAA8H,wCAAwC,qBAAqB,CAAC,aAAa,cAAc,eAAe,gBAAgB,eAAe,eAAe,YAAY,iBAAiB,iBAAiB,CAAC,wBAAwB,8BAA8B,CAAC,sDAAsD,iBAAiB,aAAa,CAAC,uBAAuB,cAAc,gBAAgB,CAAC,mBAAmB,aAAa,CAAC,oBAAoB,qBAAqB,yBAAyB,WAAW,cAAc,CAAC,WAAW,kBAAkB,SAAS,+BAA+B,2BAA2B,gBAAgB,kBAAkB,oCAAoC,sBAAsB,kBAAkB,CAAC,iBAAiB,SAAS,CAAC,kBAAkB,SAAS,CAAC,kBAAkB,SAAS,CAAC,iBAAiB,WAAW,MAAM,gBAAgB,YAAY,aAAa,CAAC,oBAAoB,MAAM,QAAQ,SAAS,OAAO,eAAe,cAAc,QAAQ,CAAC,8BAA8B,qBAAqB,iBAAiB,CAAC,mBAAmB,mBAAmB,CAAC,sBAAsB,YAAY,eAAe,YAAY,UAAU,UAAU,eAAe,cAAc,CAAC,wCAAwC,aAAa,CAAC,4FAA4F,aAAa,CAAC,kBAAkB,cAAc,eAAe,gBAAgB,aAAa,CAAC,iBAAiB,kBAAkB,cAAc,cAAc,CAAC,mBAAmB,uBAAuB,iBAAiB,qBAAqB,CAAC,0BAA0B,4BAA4B,CAAC,0BAA0B,6BAA6B,CAAC,0BAA0B,GAAG,iCAAiC,SAAS,CAAC,GAAK,wBAA6B,SAAS,CAAC,CAAC,2BAA2B,GAAG,wBAA6B,SAAS,CAAC,GAAK,iCAAiC,SAAS,CAAC,CAAC,4BAA4B,aAAa,gEAAgE,CAAC,+BAA+B,gBAAgB,iBAAiB,eAAe,SAAS,eAAe,cAAc,eAAe,mBAAmB,gBAAgB,sBAAsB,CAAC,qCAAqC,wBAAwB,CAAC,2CAA2C,yBAAyB,UAAU,CAAC,sCAAsC,wBAAwB,CAAC,kEAAkE,qBAAqB,CAAC,uCAAuC,eAAe,4BAA4B,CAAC,kDAAkD,kBAAkB,CAAC,0CAA0C,kBAAkB,aAAa,kBAAkB,eAAe,UAAU,CAAC,wDAAwD,qBAAqB,CAAC,kCAAkC,iBAAiB,cAAc,sBAAsB,cAAc,iBAAiB,CAAC,kCAAkC,SAAS,SAAS,CAAC,aAAa,cAAc,cAAc,CAAC,8BAA8B,aAAa,CAAC,yCAAyC,UAAU,CAAC,wCAAwC,kBAAkB,gBAAgB,CAAC,2DAA2D,cAAc,CAAC,mBAAmB,eAAe,YAAY,CAAC,kBAAkB,aAAa,yBAAyB,6DAA6D,cAAc,WAAW,kBAAkB,MAAM,OAAO,eAAe,CAAC,wBAAwB,gBAAgB,iBAAiB,eAAe,SAAS,cAAc,CAAC,gDAAgD,yBAAyB,aAAa,CAAC,oCAAoC,eAAe,cAAc,mBAAmB,CAAC,iCAAiC,kBAAkB,eAAe,4BAA4B,CAAC,wCAAwC,WAAW,WAAW,cAAc,eAAe,qBAAqB,CAAC,iCAAiC,YAAY,iBAAiB,eAAe,cAAc,eAAe,eAAe,kBAAkB,2DAA2D,sBAAsB,kBAAkB,CAAC,SAAS,kBAAkB,gBAAgB,kBAAkB,SAAS,eAAe,wBAAwB,CAAC,+BAA+B,cAAc,UAAU,CAAC,eAAe,UAAU,CAAC,YAAY,eAAe,CAAC,eAAe,wBAAwB,CAAC,+DAA+D,aAAa,CAAC,2EAA2E,wBAAwB,CAAC,oCAAoC,wBAAwB,CAAC,wDAAwD,wBAAwB,CAAC,mCAAmC,WAAW,YAAY,iBAAiB,SAAS,eAAe,kBAAkB,sBAAsB,mCAAmC,CAAC,gFAAgF,aAAa,CAAC,iCAAiC,WAAW,iBAAiB,CAAC,0CAA0C,kBAAkB,SAAS,OAAO,yBAAyB,cAAc,sBAAsB,YAAY,eAAe,gEAAgE,CAAC,oDAAoD,YAAY,iBAAiB,mCAAmC,CAAC,+CAA+C,sBAAsB,WAAW,YAAY,iBAAiB,cAAc,CAAC,yDAAyD,gBAAgB,sBAAsB,gBAAgB,cAAc,eAAe,CAAC,uFAAuF,wBAAwB,CAAC,iKAAiK,+BAA+B,CAAC,mHAAmH,wBAAwB,CAAC,8JAA8J,wBAAwB,CAAC,8HAA8H,aAAa,CAAC,+FAA+F,aAAa,CAAC,mBAAmB,UAAU,CAAC,uHAAuH,SAAS,sBAAsB,WAAW,iBAAiB,CAAC,mIAAmI,YAAY,CAAC,6FAA6F,SAAS,QAAQ,gBAAgB,kBAAkB,oBAAoB,CAAC,+BAA+B,iBAAiB,CAAC,wCAAwC,kBAAkB,gBAAgB,MAAM,UAAU,UAAU,CAAC,oFAAoF,mBAAmB,cAAc,CAAC,gCAAgC,iBAAiB,WAAW,iBAAiB,CAAC,gBAAgB,qBAAqB,CAAC,0BAA0B,aAAa,CAAC,yBAAyB,cAAc,CAAC,8BAA8B,sBAAsB,iBAAiB,WAAW,iBAAiB,CAAC,qBAAqB,wBAAwB,CAAC,yDAAyD,wBAAwB,CAAC,0BAA0B,YAAY,iBAAiB,eAAe,eAAe,CAAC,iEAAiE,6BAA6B,wBAAyB,CAAC,yCAAyC,2BAA2B,CAAC,mBAAmB,iBAAiB,CAAC,qBAAqB,qBAAqB,CAAC,wBAAwB,kBAAkB,QAAQ,WAAW,gBAAgB,yBAAyB,cAAc,CAAC,4CAA4C,kBAAkB,oBAAoB,CAAC,uBAAuB,SAAS,CAAC,2BAA2B,iBAAiB,mBAAmB,eAAe,kBAAkB,aAAa,CAAC,yDAAyD,cAAc,qBAAqB,CAAC,2EAA2E,eAAe,SAAS,CAAC,UAAU,cAAc,eAAe,kBAAkB,CAAC,oBAAoB,gBAAgB,CAAC,iBAAiB,mBAAmB,eAAe,SAAS,CAAC,2CAA2C,oBAAoB,CAAC,6CAA6C,qBAAqB,kBAAkB,CAAC,mDAAoD,4CAA4C,uCAAuC,CAAC,8CAA8C,yBAAyB,qBAAqB,kBAAkB,CAAC,oDAAqD,mBAAmB,wBAAwB,CAAC,+DAA+D,kBAAkB,CAAC,yDAAyD,yBAAyB,oBAAoB,CAAC,gFAAiF,qBAAqB,CAAC,8CAA8C,WAAW,kBAAkB,CAAC,iBAAiB,yBAAyB,WAAW,YAAY,kBAAkB,eAAe,qBAAqB,CAAC,uBAAuB,oBAAoB,CAAC,uBAAwB,UAAU,WAAW,kBAAkB,sBAAsB,WAAW,kBAAkB,SAAS,QAAQ,4CAA4C,wCAAwC,uDAAuD,CAAC,mCAAmC,WAAW,YAAY,cAAc,CAAC,oBAAoB,UAAU,UAAU,kBAAkB,WAAW,MAAM,OAAO,QAAQ,SAAS,QAAQ,CAAC,yCAAyC,kBAAkB,oBAAoB,CAAC,iBAAiB,eAAe,gBAAgB,CAAC,gBAAgB,qBAAqB,WAAW,CAAC,0BAA0B,cAAc,CAAC,qDAAqD,8BAA8B,0BAA0B,yBAAyB,CAAC,oDAAoD,yBAAyB,CAAC,gEAAgE,iBAAiB,CAAC,wBAAwB,mBAAmB,gBAAgB,yBAAyB,cAAc,cAAc,wBAAwB,kBAAkB,sBAAsB,UAAU,SAAS,eAAe,kDAAkD,kBAAkB,eAAe,eAAe,CAAC,8BAA8B,aAAa,CAAC,0CAA0C,cAAc,CAAC,+CAA+C,eAAe,CAAC,6BAA6B,UAAU,UAAU,kBAAkB,WAAW,WAAW,CAAC,6DAA6D,WAAW,yBAAyB,qBAAqB,6BAA6B,CAAC,8DAA8D,cAAc,mBAAmB,sBAAsB,yBAAyB,qBAAqB,eAAe,CAAC,gDAAgD,kBAAkB,eAAe,eAAe,CAAC,gDAAgD,gBAAgB,eAAe,eAAe,CAAC,+CAA+C,YAAY,eAAe,eAAe,CAAC,WAAW,qBAAqB,kBAAkB,eAAe,iBAAiB,YAAY,qBAAqB,CAAC,sCAAsC,kBAAkB,eAAe,oBAAoB,CAAC,iEAAiE,SAAS,CAAC,wCAAwC,+BAA+B,4BAA4B,CAAC,6CAA6C,kCAAkC,CAAC,4DAA4D,uBAAuB,CAAC,uCAAuC,qBAAqB,wBAAwB,CAAC,iFAAiF,kBAAkB,CAAC,kBAAkB,eAAe,OAAO,KAAK,CAAC,oBAAoB,cAAc,QAAQ,UAAU,CAAC,0BAA0B,QAAQ,CAAC,2BAA2B,SAAS,CAAC,kBAAkB,YAAY,CAAC,iBAAiB,SAAS,qBAAqB,kBAAkB,yBAAyB,UAAU,mBAAmB,sBAAsB,mBAAmB,gDAAgD,CAAC,oCAAoC,MAAM,OAAO,kBAAkB,mBAAmB,yBAAyB,WAAW,YAAY,qBAAqB,CAAC,+DAA+D,SAAS,CAAC,gEAAgE,UAAU,CAAC,oBAAoB,kBAAkB,aAAa,yBAAyB,kBAAkB,sBAAsB,6DAA6D,sBAAsB,YAAY,CAAC,qEAAqE,SAAS,CAAC,mEAAmE,cAAc,qBAAqB,CAAC,yIAAyI,wBAAwB,CAAC,yEAA0E,kBAAkB,WAAW,0BAA0B,gBAAgB,eAAe,mCAAmC,iCAAiC,CAAC,2BAA2B,eAAe,SAAS,kBAAkB,WAAW,cAAc,CAAC,0BAA0B,gBAAgB,CAAC,0BAA0B,gBAAgB,cAAc,SAAS,qBAAqB,CAAC,0BAA0B,eAAe,iBAAiB,kBAAkB,mBAAmB,gBAAgB,uBAAuB,cAAc,YAAY,gBAAgB,sBAAsB,cAAc,CAAC,mCAAmC,WAAW,wBAAwB,CAAC,yCAAyC,wBAAwB,CAAC,+BAA+B,yBAAyB,CAAC,sCAAsC,cAAc,kBAAkB,CAAC,4CAA4C,qBAAqB,CAAC,iBAAiB,SAAS,SAAS,CAAC,2CAA2C,iBAAiB,CAAC,uBAAuB,gBAAgB,SAAS,SAAS,CAAC,wBAAwB,kBAAkB,eAAe,WAAW,YAAY,gBAAgB,CAAC,WAAW,qBAAqB,iBAAiB,CAAC,kCAAkC,oBAAoB,CAAC,4BAA4B,eAAe,kBAAkB,CAAC,kCAAkC,oBAAoB,CAAC,qCAAmD,eAAe,yBAAyB,AAAyF,iBAAiB,QAAQ,cAAc,CAAC,wFAAvL,cAAc,AAAwC,8CAA8C,yCAA2C,CAAqS,AAA7P,mDAAmD,cAAc,WAAW,YAAY,eAAe,UAAU,kBAAkB,AAAyF,kBAAmB,CAAc,yDAAyD,aAAa,CAAC,gDAAgD,+BAA+B,0BAA0B,CAAC,kDAAkD,kBAAkB,CAAC,wDAAwD,oBAAoB,CAAC,qBAAqB,aAAa,CAAC,0BAA0B,eAAe,CAAC,mBAAmB,YAAY,iBAAiB,sBAAsB,oBAAoB,CAAC,kBAAkB,YAAY,UAAU,UAAU,iBAAiB,WAAW,eAAe,wBAAwB,wBAAwB,qBAAqB,gBAAgB,YAAY,4BAA4B,CAAC,0BAA0B,WAAW,CAAC,kBAAkB,eAAe,kBAAkB,QAAQ,aAAa,WAAW,cAAc,iBAAiB,cAAc,CAAC,wBAAwB,aAAa,CAAC,iBAAiB,kBAAkB,mBAAmB,mBAAmB,UAAU,QAAQ,+BAA+B,0BAA0B,CAAC,oCAAoC,sBAAsB,iBAAiB,CAAC,gBAAgB,qBAAqB,YAAY,iBAAiB,eAAe,kBAAkB,WAAW,wBAAwB,CAAC,+BAA+B,cAAc,CAAC,UAAU,gBAAgB,WAAW,eAAe,sBAAsB,yBAAyB,eAAe,aAAa,CAAC,2BAA2B,mBAAmB,cAAc,CAAC,0BAA0B,YAAY,YAAY,uBAAuB,qBAAqB,CAAC,iCAAmC,WAAW,kBAAkB,yBAAyB,SAAS,CAAC,4CAA4C,gBAAgB,CAAC,0CAA0C,eAAe,CAAC,8CAA8C,iBAAiB,CAAC,kCAAkC,+BAA+B,CAAC,wCAAwC,WAAW,qBAAqB,sBAAsB,SAAS,CAAC,iCAAiC,kBAAkB,mBAAmB,sBAAsB,sBAAsB,CAAC,iBAAkB,OAAO,SAAS,WAAW,UAAU,CAAC,gBAAiB,MAAM,QAAQ,UAAU,WAAW,CAAC,4CAA4C,kBAAkB,qBAAqB,qBAAqB,CAAC,aAAa,mBAAmB,gBAAgB,yBAAyB,eAAe,CAAC,yBAAyB,cAAc,CAAC,iBAAiB,qBAAqB,iBAAiB,gBAAgB,kBAAkB,CAAC,iBAAiB,qBAAqB,CAAC,iCAAkC,qBAAqB,WAAW,UAAU,WAAW,kBAAkB,mBAAmB,iBAAiB,qBAAqB,CAAC,mBAAmB,iBAAiB,uBAAuB,iBAAiB,WAAW,qBAAqB,CAAC,6BAA6B,aAAa,CAAC,yBAAyB,eAAe,gBAAgB,gBAAgB,WAAW,YAAY,iBAAiB,gBAAgB,CAAC,oEAAoE,eAAe,CAAC,sBAAsB,qBAAqB,QAAQ,SAAS,SAAS,WAAW,kBAAkB,SAAS,SAAS,CAAC,iEAAiE,mCAAmC,iCAAiC,CAAC,gCAAgC,QAAQ,gBAAgB,+BAA+B,CAAC,iCAAiC,WAAW,6BAA6B,kBAAkB,CAAC,2CAA2C,2BAA2B,CAAC,6CAA6C,wBAAwB,CAAC,oBAAoB,OAAO,CAAC,gBAAgB,mBAAmB,qBAAqB,gBAAgB,CAAC,wKAAwK,kBAAkB,CAAC,kCAAkC,QAAQ,CAAC,aAAa,qBAAqB,CAAC,0BAA0B,kBAAkB,UAAU,CAAC,uBAAuB,kBAAkB,gBAAgB,kBAAkB,WAAW,WAAW,CAAC,sBAAsB,kBAAkB,SAAS,QAAQ,mCAAmC,+BAA+B,aAAa,CAAC,+BAA+B,UAAU,iBAAiB,CAAC,uBAAuB,kBAAkB,eAAe,WAAW,eAAe,qCAAqC,WAAW,CAAC,gCAAgC,kBAAkB,SAAS,QAAQ,iBAAiB,eAAe,CAAC,iCAAiC,4BAA4B,uBAAuB,CAAC,yBAAyB,kBAAkB,yBAAyB,gCAAgC,CAAC,+BAA+B,kCAAkC,CAAC,eAAe,eAAe,eAAe,CAAC,kDAAkD,+BAA+B,CAAC,kDAAkD,sBAAsB,CAAC,0CAA0C,8BAA8B,CAAC,wCAAwC,kBAAkB,MAAM,OAAO,6BAA6B,iBAAiB,CAAC,sDAAwD,WAAW,kBAAkB,OAAO,SAAS,WAAW,WAAW,yBAAyB,SAAS,CAAC,6BAA6B,kBAAkB,SAAS,QAAQ,wBAAwB,CAAC,uBAAuB,MAAM,UAAU,QAAQ,6BAA6B,CAAC,mKAAmK,UAAU,OAAO,CAAC,gCAAgC,kBAAkB,OAAO,MAAM,SAAS,CAAC,0CAA0C,yBAAyB,aAAa,CAAC,gCAAgC,kBAAkB,OAAO,SAAS,SAAS,CAAC,yCAAyC,6BAA6B,yBAAyB,aAAa,CAAC,8BAA8B,kBAAkB,OAAO,SAAS,gBAAgB,SAAS,CAAC,4EAA4E,UAAU,CAAC,0BAA0B,eAAe,CAAC,6BAA6B,4BAA4B,CAAC,oDAAoD,kBAAkB,CAAC,wEAAwE,yBAAyB,aAAa,CAAC,sEAAsE,yBAAyB,aAAa,CAAC,wBAAwB,cAAc,iBAAiB,CAAC,gEAAgE,mBAAmB,2BAA2B,CAAC,4EAA4E,kBAAkB,CAAC,sMAAsM,wBAAwB,CAAC,kCAAkC,kBAAkB,CAAC,+BAA+B,kBAAkB,WAAW,MAAM,SAAS,QAAQ,8BAA8B,UAAU,CAAC,iCAAiC,qBAAqB,iBAAiB,gBAAgB,cAAc,CAAC,mCAAmC,aAAa,CAAC,oDAAoD,qCAAqC,CAAC,0HAA0H,6BAA6B,CAAC,wDAAwD,yBAAyB,2BAA2B,CAAC,wFAAwF,SAAS,eAAe,CAAC,kCAAkC,kBAAkB,kBAAkB,CAAC,iBAAiB,yBAAyB,kBAAkB,sBAAsB,6DAA6D,sBAAsB,YAAY,CAAC,uBAAuB,cAAc,SAAS,gBAAgB,eAAe,CAAC,4BAA4B,iBAAiB,eAAe,eAAe,cAAc,CAAC,kCAAkC,yBAAyB,aAAa,CAAC,sCAAsC,yBAAyB,UAAU,CAAC,0BAA0B,eAAe,CAAC,yBAAyB,6BAA6B,WAAW,CAAC,gCAAgC,eAAe,YAAY,cAAc,eAAe,eAAe,aAAa,CAAC,sCAAsC,aAAa,CAAC,sCAAsC,SAAS,CAAC,4CAA4C,cAAc,kBAAkB,CAAC,iCAAiC,YAAY,CAAC,mDAAmD,cAAc,kBAAkB,eAAe,CAAC,yDAAyD,eAAe,CAAC,eAAe,eAAe,gBAAgB,gBAAgB,CAAC,kBAAkB,WAAW,YAAY,sBAAsB,kBAAkB,cAAc,CAAC,0DAA0D,UAAU,CAAC,wBAAwB,cAAc,iBAAiB,CAAC,+BAA+B,YAAY,kBAAkB,MAAM,QAAQ,QAAQ,SAAS,8BAA8B,kCAAkC,CAAC,iDAAiD,WAAW,YAAY,cAAc,gBAAgB,CAAC,kCAAkC,wBAAwB,CAAC,2BAA2B,wBAAwB,CAAC,iCAAiC,wBAAwB,CAAC,iGAAiG,mCAAmC,UAAU,CAAC,2BAA2B,yBAAyB,UAAU,mBAAmB,UAAU,CAAC,sMAAsM,SAAS,CAAC,uBAAuB,cAAc,aAAa,CAAC,+BAA+B,eAAe,YAAY,wBAAwB,CAAC,kBAAkB,YAAY,cAAc,eAAe,CAAC,sDAAsD,wBAAwB,CAAC,wDAAwD,wBAAwB,CAAC,mBAAmB,kBAAkB,iBAAiB,cAAc,CAAC,yBAAyB,aAAa,CAAC,+BAA+B,wBAAwB,CAAC,kCAAkC,yBAAyB,mBAAmB,UAAU,CAAC,gDAAgD,mCAAmC,UAAU,CAAC,wBAAwB,aAAa,CAAC,kBAAkB,kBAAkB,iBAAiB,cAAc,CAAC,wBAAwB,aAAa,CAAC,8BAA8B,wBAAwB,CAAC,iCAAiC,yBAAyB,mBAAmB,UAAU,CAAC,+CAA+C,mCAAmC,UAAU,CAAC,sBAAsB,eAAe,CAAC,4BAA4B,mBAAmB,UAAU,CAAC,6CAA6C,eAAe,CAAC,gDAAgD,QAAQ,CAAC,2CAA2C,eAAe,CAAC,kCAAkC,eAAe,CAAC,+BAA+B,eAAe,CAAC,8BAA8B,kBAAkB,kBAAkB,WAAW,CAAC,qCAAqC,UAAU,CAAC,kCAAkC,eAAe,iBAAiB,CAAC,+BAA+B,WAAW,UAAU,sBAAsB,SAAS,YAAY,CAAC,6EAA6E,WAAW,CAAC,0EAA0E,iBAAiB,iBAAiB,CAAC,uCAAuC,8BAA8B,CAAC,oCAAoC,sBAAsB,kBAAkB,CAAC,6CAA6C,gBAAgB,CAAC,mCAAmC,kBAAkB,gCAAgC,eAAe,oBAAoB,cAAc,WAAW,qBAAqB,CAAC,wDAAwD,eAAe,sBAAsB,mBAAmB,aAAa,CAAC,wCAAwC,kBAAkB,mBAAmB,aAAa,CAAC,yDAAyD,kBAAkB,SAAS,QAAQ,UAAU,eAAe,CAAC,sBAAsB,gBAAgB,gBAAgB,CAAC,+BAA+B,kBAAkB,kBAAkB,YAAY,CAAC,4BAA4B,sBAAsB,SAAS,oBAAoB,UAAU,oBAAoB,CAAC,8BAA8B,kBAAkB,kBAAkB,cAAc,CAAC,AAAuE,6CAA3C,kBAAkB,wBAAwB,CAAmJ,AAAlJ,iBAAiB,cAAc,AAAyB,0BAA0B,gBAAgB,AAAkB,iBAAiB,YAAY,CAAC,kEAAoE,WAAW,cAAc,UAAU,CAAC,0BAA0B,kBAAkB,WAAW,CAAC,yBAAyB,6BAA6B,YAAY,iBAAiB,sBAAsB,iBAAiB,CAAC,2BAA2B,cAAc,WAAW,SAAS,6BAA6B,iBAAiB,eAAe,cAAc,kBAAkB,gBAAgB,UAAU,cAAc,CAAC,iCAAiC,wBAAwB,CAAC,kCAAkC,yBAAyB,aAAa,CAAC,sBAAsB,yBAAyB,WAAW,iBAAiB,kBAAkB,eAAe,eAAe,6BAA6B,UAAU,cAAc,CAAC,gCAAgC,WAAW,kBAAkB,CAAC,2BAA2B,eAAe,cAAc,SAAS,eAAe,eAAe,UAAU,cAAc,CAAC,0GAA0G,aAAa,CAAC,2BAA2B,eAAe,cAAc,qBAAqB,aAAa,cAAc,CAAC,0DAA0D,kBAAkB,MAAM,SAAS,YAAY,+BAA+B,sBAAsB,gBAAgB,yBAAyB,aAAa,CAAC,wGAAwG,iBAAiB,CAAC,gBAAgB,eAAe,CAAC,0CAA0C,eAAe,CAAC,sBAAsB,mBAAmB,UAAU,CAAC,qCAAqC,eAAe,CAAC,4BAA4B,eAAe,CAAC,yBAAyB,eAAe,CAAC,6BAA6B,kBAAkB,mBAAmB,aAAa,CAAC,6BAA6B,kBAAkB,gCAAgC,eAAe,oBAAoB,cAAc,WAAW,qBAAqB,CAAC,wBAAwB,YAAY,iBAAiB,CAAC,8BAA8B,eAAe,cAAc,iBAAiB,kBAAkB,cAAc,CAAC,0BAA0B,UAAU,CAAC,0BAA0B,WAAW,CAAC,2BAA2B,aAAa,iBAAiB,CAAC,4BAA4B,WAAW,eAAe,iBAAiB,gBAAgB,CAAC,aAAa,aAAa,WAAW,CAAC,uCAAuC,iBAAiB,QAAQ,CAAC,kBAAkB,iBAAiB,cAAc,CAAC,0CAA0C,yBAAyB,UAAU,CAAC,gDAAgD,wBAAwB,CAAC,2BAA2B,cAAc,kBAAkB,CAAC,wBAAwB,yBAAyB,cAAc,CAAC,kHAAkH,2CAA2C,CAAC,sLAAsL,gGAAgG,CAAC,yDAAyD,UAAU,wBAAwB,mBAAmB,CAAC,0DAA0D,UAAU,wBAAwB,oBAAoB,gCAAgC,2BAA2B,CAAC,mDAAmD,UAAU,wBAAwB,mBAAmB,CAAC,gEAAgE,UAAU,wBAAwB,oBAAoB,mCAAmC,8BAA8B,CAAC,yDAAyD,UAAU,wBAAwB,mBAAmB,CAAC,4DAA4D,UAAU,uBAAyB,mBAAqB,8BAA8B,yBAAyB,CAAC,qDAAqD,UAAU,yBAA6B,oBAAwB,CAAC,qBAAqB,4FAA4F,CAAC,gCAAgC,2FAA2F,CAAC,4CAA4C,iBAAiB,CAAC,qCAAqC,UAAU,gCAAgC,2BAA2B,CAAC,uBAAuB,+CAA+C,CAAC,gBAAgB,kBAAkB,oBAAoB,CAAC,iCAAiC,kBAAkB,gBAAgB,sBAAsB,0BAA0B,gBAAgB,WAAW,QAAQ,CAAC,yBAAyB,WAAW,CAAC,oCAAoC,WAAW,CAAC,wCAAwC,WAAW,CAAC,uDAAuD,SAAS,CAAC,oEAAoE,cAAc,CAAC,0BAA0B,iBAAiB,cAAc,qBAAqB,UAAU,mBAAmB,iBAAiB,CAAC,uFAAuF,mBAAmB,CAAC,uBAAuB,UAAU,SAAS,gBAAgB,iBAAiB,CAAC,2DAA6D,WAAW,cAAc,WAAW,WAAW,CAAC,uBAAuB,YAAY,iBAAiB,cAAc,CAAC,yDAAyD,mBAAmB,cAAc,CAAC,6CAA6C,UAAU,CAAC,gCAAgC,cAAc,kBAAkB,CAAC,eAAe,aAAa,yBAAyB,sBAAsB,6DAA6D,kBAAkB,kBAAkB,YAAY,OAAO,aAAa,yBAAyB,qBAAqB,gBAAgB,CAAC,kCAAkC,gEAAgE,CAAC,8CAA8C,yBAAyB,qBAAqB,CAAC,wBAAwB,YAAY,kBAAkB,eAAe,CAAC,6DAA+D,YAAY,QAAQ,WAAW,kBAAkB,eAAe,iBAAiB,iBAAiB,yBAAyB,YAAY,WAAW,OAAO,QAAQ,sBAAsB,gBAAgB,eAAe,CAAC,8BAA+B,SAAS,gBAAgB,CAAC,+BAAgC,iBAAiB,iBAAiB,CAAC,0CAA2C,cAAc,CAAC,2CAA4C,sBAAsB,CAAC,uBAAuB,6BAA6B,YAAY,YAAY,iBAAiB,iBAAiB,qBAAqB,CAAC,oBAAoB,YAAY,iBAAiB,cAAc,aAAa,eAAe,6BAA6B,UAAU,eAAe,aAAa,CAAC,4BAA4B,gBAAgB,aAAa,CAAC,YAAY,kBAAkB,gBAAgB,gBAAgB,kBAAkB,yBAAyB,aAAa,aAAa,cAAc,CAAC,4DAA6D,kBAAkB,cAAc,QAAQ,SAAS,yBAAyB,kBAAkB,CAAC,2BAA2B,gBAAgB,CAAC,iCAAkC,YAAY,gBAAgB,CAAC,8BAA8B,kBAAkB,CAAC,6CAA6C,YAAY,SAAS,iBAAiB,yBAAyB,qBAAqB,CAAC,mDAAoD,WAAW,iBAAiB,sBAAsB,qBAAqB,CAAC,iCAAiC,eAAe,CAAC,gDAAgD,SAAS,SAAS,iBAAiB,mBAAmB,2BAA2B,CAAC,sDAAuD,QAAQ,iBAAiB,mBAAmB,wBAAwB,CAAC,gCAAgC,gBAAgB,CAAC,+CAA+C,QAAQ,UAAU,kBAAkB,2BAA2B,mBAAmB,CAAC,qDAAsD,YAAY,SAAS,wBAAwB,mBAAmB,CAAC,+BAA+B,iBAAiB,CAAC,8CAA8C,QAAQ,WAAW,kBAAkB,qBAAqB,yBAAyB,CAAC,oDAAqD,UAAU,YAAY,iBAAiB,qBAAqB,sBAAsB,CAAC,mBAAmB,cAAc,eAAe,cAAc,iBAAiB,CAAC,eAAe,6BAA6B,CAAC,eAAe,uCAAuC,CAAC,sBAAsB,GAAG,SAAS,CAAC,CAAC,uBAAuB,GAAK,SAAS,CAAC,CAAC,SAAS,eAAe,OAAO,MAAM,WAAW,YAAY,WAAW,eAAe,CAAC,gBAAgB,gBAAgB,qBAAqB,sBAAsB,sBAAsB,YAAY,kBAAkB,eAAe,gBAAgB,mCAAmC,0BAA0B,CAAC,yBAAyB,eAAe,MAAM,SAAS,OAAO,QAAQ,iBAAiB,CAAC,+BAAgC,WAAW,qBAAqB,YAAY,QAAQ,qBAAqB,CAAC,wBAAwB,kBAAkB,mBAAmB,CAAC,2BAA2B,kBAAkB,SAAS,WAAW,eAAe,YAAY,UAAU,UAAU,cAAc,CAAC,kDAAkD,UAAU,CAAC,gHAAgH,aAAa,CAAC,yBAAyB,kBAAkB,cAAc,eAAe,iBAAiB,CAAC,uBAAuB,gBAAgB,CAAC,gFAAgF,oBAAoB,CAAC,0BAA0B,cAAc,eAAe,gBAAgB,cAAc,CAAC,uBAAuB,eAAe,gBAAgB,eAAe,gBAAgB,YAAY,UAAU,CAAC,yBAAyB,QAAQ,CAAC,2BAA2B,SAAS,eAAe,CAAC,sBAAsB,uBAAuB,gBAAgB,CAAC,0CAA0C,gBAAgB,CAAC,8BAA8B,+BAA+B,0BAA0B,CAAC,wBAAwB,kBAAkB,QAAQ,+BAA+B,2BAA2B,wBAAwB,CAAC,6CAA6C,aAAa,CAAC,4CAA4C,aAAa,CAAC,wCAAwC,aAAa,CAAC,6CAA6C,aAAa,CAAC,0BAA0B,4BAA4B,CAAC,0BAA0B,6BAA6B,CAAC,0BAA0B,GAAG,iCAAiC,SAAS,CAAC,GAAK,wBAA6B,SAAS,CAAC,CAAC,2BAA2B,GAAG,wBAA6B,SAAS,CAAC,GAAK,iCAAiC,SAAS,CAAC,CAAC,eAAe,eAAe,aAAa,CAAC,0BAA0B,aAAa,aAAa,CAAC,qBAAqB,UAAU,CAAC,gQAAgQ,cAAc,WAAW,CAAC,0DAA0D,YAAY,CAAC,0DAA0D,6BAA6B,aAAa,CAAC,sEAAsE,cAAc,cAAc,CAAC,0CAA0C,eAAe,CAAC,yCAAyC,WAAW,qBAAqB,gBAAgB,gBAAgB,CAAC,+BAA+B,qBAAqB,kBAAkB,kBAAkB,CAAC,sCAAsC,WAAW,oBAAoB,CAAC,wCAAwC,qBAAqB,kBAAkB,CAAC,2DAA2D,aAAa,CAAC,cAAc,kBAAkB,CAAC,4BAA4B,eAAe,CAAC,yKAAyK,wBAAwB,CAAC,mFAAmF,oBAAoB,CAAC,sDAAsD,YAAY,cAAc,gBAAgB,CAAC,qBAAqB,iBAAiB,sBAAsB,WAAW,eAAe,cAAc,cAAc,yBAAyB,qBAAqB,CAAC,uBAAuB,iBAAiB,kBAAkB,cAAc,CAAC,qBAAqB,cAAc,eAAe,cAAc,gBAAgB,kBAAkB,SAAS,MAAM,CAAC,iBAAiB,gCAAgC,UAAU,kBAAkB,eAAe,CAAC,qBAAqB,kBAAkB,SAAS,OAAO,WAAW,yBAAyB,UAAU,wDAAwD,eAAe,CAAC,kBAAkB,YAAY,yBAAyB,YAAY,WAAW,iBAAiB,uBAAuB,kBAAkB,kBAAkB,eAAe,cAAc,eAAe,mBAAmB,CAAC,gCAAgC,wBAA2B,mBAAsB,CAAC,wBAAwB,aAAa,CAAC,mBAAmB,gBAAgB,mBAAmB,iBAAiB,CAAC,iCAAiC,cAAc,CAAC,qBAAqB,eAAe,CAAC,sCAAsC,kBAAkB,eAAe,iBAAiB,eAAe,aAAa,CAAC,mBAAmB,OAAO,CAAC,mBAAmB,MAAM,CAAC,cAAc,kBAAkB,yBAAyB,UAAU,CAAC,eAAe,eAAe,YAAY,sBAAsB,iBAAiB,qBAAqB,gBAAgB,eAAe,cAAc,iBAAiB,CAAC,8BAA8B,kBAAkB,kBAAkB,kDAAkD,eAAe,CAAC,qCAAqC,wBAA2B,oBAAuB,oBAAoB,CAAC,oCAAoC,yBAAyB,UAAU,CAAC,qBAAqB,cAAc,cAAc,CAAC,2BAA2B,WAAW,cAAc,CAAC,yBAAyB,aAAa,CAAC,kBAAkB,gBAAgB,iBAAiB,CAAC,qDAAqD,YAAY,CAAC,yDAAyD,oBAAoB,CAAC,8DAA8D,kBAAkB,eAAe,QAAQ,YAAY,sBAAsB,iBAAiB,gBAAgB,SAAS,WAAW,8BAA8B,yBAAyB,CAAC,oKAAoK,UAAU,CAAC,+CAA+C,6BAA6B,iDAAiD,CAAC,iEAAiE,kBAAkB,gBAAgB,CAAC,yDAAyD,yBAAyB,yBAAyB,yBAAyB,CAAC,qEAAqE,mBAAmB,iBAAiB,CAAC,sBAAsB,gBAAgB,wBAAwB,CAAC,wCAAwC,YAAY,CAAC,uCAAuC,yBAAyB,QAAQ,CAAC,sDAAsD,kDAAkD,6BAA6B,aAAa,kBAAkB,gBAAgB,CAAC,gEAAgE,sBAAsB,2BAA2B,yBAAyB,CAAC,4EAA4E,yBAAyB,CAAC,2EAA2E,0BAA0B,CAAC,oBAAoB,gCAAgC,CAAC,oBAAoB,kBAAkB,OAAO,QAAQ,gCAAgC,CAAC,mBAAmB,+BAA+B,CAAC,mBAAmB,kBAAkB,OAAO,QAAQ,+BAA+B,CAAC,8BAA8B,GAAG,UAAU,qBAAqB,0BAA0B,CAAC,GAAG,UAAU,qBAAqB,uBAAuB,CAAC,CAAC,8BAA8B,GAAG,qBAAqB,wBAAwB,SAAS,CAAC,GAAK,qBAAqB,2BAA2B,SAAS,CAAC,CAAC,6BAA6B,GAAG,UAAU,qBAAqB,2BAA2B,CAAC,GAAG,UAAU,qBAAqB,uBAAuB,CAAC,CAAC,6BAA6B,GAAG,qBAAqB,wBAAwB,SAAS,CAAC,GAAK,qBAAqB,4BAA4B,SAAS,CAAC,CAAC,QAAQ,yBAAyB,cAAc,YAAY,iBAAiB,eAAe,WAAW,kBAAkB,sBAAsB,4BAA4B,CAAC,uBAAuB,kBAAkB,kBAAkB,kBAAkB,eAAe,eAAe,yBAA6B,qBAAyB,YAAY,WAAW,iBAAiB,sBAAsB,SAAS,UAAU,CAAC,6BAA6B,sBAAsB,aAAa,CAAC,cAAc,yBAAyB,qBAAqB,aAAa,CAAC,mCAAmC,yBAAyB,UAAU,CAAC,qBAAqB,oBAAoB,CAAC,iBAAiB,qCAAqC,iCAAiC,aAAa,CAAC,sCAAsC,yBAAyB,UAAU,CAAC,wBAAwB,oBAAoB,CAAC,iBAAiB,qCAAqC,iCAAiC,aAAa,CAAC,sCAAsC,yBAAyB,UAAU,CAAC,wBAAwB,oBAAoB,CAAC,iBAAiB,qCAAqC,iCAAiC,aAAa,CAAC,sCAAsC,yBAAyB,UAAU,CAAC,wBAAwB,oBAAoB,CAAC,gBAAgB,oCAAoC,gCAAgC,aAAa,CAAC,qCAAqC,yBAAyB,UAAU,CAAC,uBAAuB,oBAAoB,CAAC,SAAS,eAAe,gBAAgB,wBAAwB,CAAC,sBAAsB,kBAAkB,gBAAgB,kBAAkB,WAAW,WAAW,CAAC,qBAAqB,kBAAkB,SAAS,QAAQ,mCAAmC,+BAA+B,aAAa,CAAC,sCAAsC,gBAAgB,4BAA4B,CAAC,kDAAkD,aAAa,CAAC,4EAA4E,qBAAqB,qBAAqB,CAAC,uBAAuB,iBAAiB,YAAY,cAAc,CAAC,sFAAsF,gBAAgB,CAAC,oCAAoC,qBAAqB,CAAC,6BAA6B,kBAAkB,CAAC,2BAA2B,eAAe,QAAQ,SAAS,iBAAiB,6BAA6B,qBAAqB,0BAA0B,sBAAsB,wBAAwB,oBAAoB,oCAAoC,CAAC,iCAAiC,sBAAsB,CAAC,oCAAoC,4BAA4B,uBAAuB,CAAC,mCAAmC,yBAAyB,cAAc,CAAC,qBAAqB,cAAc,CAAC,4BAA4B,iBAAiB,eAAe,aAAa,CAAC,4EAA4E,wBAAwB,CAAC,UAAU,WAAW,iBAAiB,SAAS,sBAAsB,kBAAkB,kBAAkB,sBAAsB,gBAAgB,WAAW,UAAU,cAAc,sBAAsB,CAAC,iCAAiC,WAAW,eAAe,cAAc,CAAC,mBAAmB,wBAAwB,CAAC,gBAAgB,wBAAwB,CAAC,mBAAmB,wBAAwB,CAAC,iBAAiB,wBAAwB,CAAC,mBAAmB,mBAAmB,aAAa,CAAC,gBAAgB,eAAe,WAAW,mBAAmB,WAAW,qBAAqB,CAAC,uBAAuB,eAAe,UAAU,CAAC,iBAAiB,eAAe,gBAAgB,CAAC,yBAAyB,eAAe,CAAC,oBAAoB,eAAe,WAAW,UAAU,SAAS,WAAW,kBAAkB,cAAc,CAAC,yIAAyI,SAAS,CAAC,gCAAgC,kBAAkB,eAAe,OAAO,CAAC,iBAAiB,YAAY,aAAa,sBAAsB,kBAAkB,eAAe,WAAW,sBAAsB,6DAA6D,uDAAuD,eAAe,CAAC,uCAAuC,aAAa,CAAC,uCAAuC,aAAa,CAAC,sCAAsC,aAAa,CAAC,kCAAkC,aAAa,CAAC,wBAAwB,aAAa,CAAC,qCAAqC,gBAAgB,CAAC,wBAAwB,gBAAgB,eAAe,cAAc,QAAQ,CAAC,0BAA0B,eAAe,iBAAiB,gBAAgB,cAAc,kBAAkB,CAAC,uBAAuB,WAAW,YAAY,eAAe,WAAW,kBAAkB,OAAO,CAAC,2BAA2B,SAAS,WAAW,kBAAkB,eAAe,cAAc,cAAc,CAAC,iCAAiC,aAAa,CAAC,4BAA4B,+BAA+B,2BAA2B,OAAO,CAAC,iBAAiB,qBAAqB,YAAY,kBAAkB,kBAAkB,CAAC,2BAA2B,aAAa,CAAC,kCAAkC,wBAAwB,qBAAqB,gBAAgB,kBAAkB,CAAC,sDAAsD,kBAAkB,CAAC,gHAAgH,qBAAqB,aAAa,CAAC,4HAA4H,cAAc,kBAAkB,CAAC,sDAAsD,YAAY,8BAA8B,WAAW,iBAAiB,QAAQ,kBAAkB,cAAc,eAAe,kBAAkB,SAAS,CAAC,kEAAkE,aAAa,CAAC,gMAAgM,oBAAoB,CAAC,8EAA8E,cAAc,kBAAkB,CAAC,2BAA2B,OAAO,CAAC,2BAA2B,UAAU,CAAC,wBAAwB,WAAW,CAAC,sGAAsG,iBAAiB,WAAW,cAAc,CAAC,mDAAmD,UAAU,CAAC,yCAAyC,kBAAkB,CAAC,wBAAwB,WAAW,CAAC,sGAAsG,iBAAiB,WAAW,cAAc,CAAC,mDAAmD,UAAU,CAAC,yCAAyC,kBAAkB,CAAC,oBAAoB,kBAAkB,kBAAkB,aAAa,aAAa,eAAe,eAAe,CAAC,4EAA6E,kBAAkB,cAAc,QAAQ,SAAS,yBAAyB,kBAAkB,CAAC,mCAAmC,gBAAgB,CAAC,yCAA0C,YAAY,gBAAgB,CAAC,sJAAsJ,UAAU,CAAC,sCAAsC,kBAAkB,CAAC,qDAAqD,YAAY,yBAAyB,qBAAqB,CAAC,2DAA4D,WAAW,iBAAiB,yBAAyB,qBAAqB,CAAC,yCAAyC,eAAe,CAAC,wDAAwD,SAAS,mBAAmB,2BAA2B,CAAC,8DAA+D,QAAQ,iBAAiB,mBAAmB,2BAA2B,CAAC,wCAAwC,gBAAgB,CAAC,uDAAuD,UAAU,2BAA2B,mBAAmB,CAAC,6DAA8D,YAAY,SAAS,2BAA2B,mBAAmB,CAAC,uCAAuC,iBAAiB,CAAC,sDAAsD,WAAW,qBAAqB,yBAAyB,CAAC,4DAA6D,UAAU,YAAY,iBAAiB,qBAAqB,yBAAyB,CAAC,6BAA6B,gBAAgB,wBAAwB,CAAC,8DAA8D,wBAAwB,CAAC,oEAAqE,qBAAqB,CAAC,iEAAiE,2BAA2B,CAAC,uEAAwE,wBAAwB,CAAC,+DAA+D,yBAAyB,CAAC,qEAAsE,sBAAsB,CAAC,gEAAgE,0BAA0B,CAAC,sEAAuE,uBAAuB,CAAC,4BAA4B,mBAAmB,UAAU,CAAC,mCAAmC,aAAa,CAAC,wEAAwE,qBAAqB,qBAAqB,CAAC,iBAAiB,UAAU,CAAC,uBAAuB,iBAAiB,CAAC,0CAA0C,UAAU,YAAY,aAAa,CAAC,uCAAuC,UAAU,YAAY,yBAAyB,CAAC,kDAAkD,SAAS,UAAW,CAAwD,0FAAxD,8BAA8B,yBAAyB,CAAiG,6CAA6C,mBAAmB,CAAC,+DAA+D,iBAAiB,WAAW,kBAAkB,YAAY,WAAW,eAAe,CAAC,gFAAgF,kBAAkB,iBAAiB,iBAAiB,CAAC,oLAAoL,SAAS,gBAAgB,yBAAyB,iBAAiB,sBAAsB,0DAA0D,CAAC,0FAA0F,WAAW,WAAW,6BAA6B,CAAC,0FAA0F,WAAW,8BAA8B,CAAC,qHAAqH,4BAA4B,4BAA4B,CAAC,gMAAgM,oBAAoB,CAAC,kMAAkM,oBAAoB,CAAC,mBAAmB,WAAW,WAAW,cAAc,yBAAyB,kBAAkB,kBAAkB,eAAe,qBAAqB,CAAC,8BAA8B,mBAAmB,UAAU,CAAC,4BAA4B,cAAc,CAAC,2FAA2F,wBAAwB,CAAC,0LAA0L,kBAAkB,CAAC,kKAAkK,uBAAuB,mBAAmB,kBAAkB,CAAC,kBAAkB,YAAY,cAAc,CAAC,gBAAgB,WAAW,yBAAyB,2BAA2B,8BAA8B,iBAAiB,CAAC,2BAA2B,WAAW,YAAY,kBAAkB,aAAa,UAAU,+BAA+B,2BAA2B,6BAA6B,kBAAkB,qBAAqB,gBAAgB,CAAC,iCAAiC,WAAW,CAAC,kEAAkE,oBAAoB,WAAW,CAAC,oCAAoC,wBAAwB,eAAe,CAAC,mBAAmB,WAAW,YAAY,yBAAyB,kBAAkB,eAAe,qBAAqB,gBAAgB,CAAC,8EAA8E,yBAAyB,qBAAqB,wBAAwB,CAAC,kDAAkD,oBAAoB,WAAW,CAAC,4BAA4B,wBAAwB,eAAe,CAAC,iBAAiB,kBAAkB,UAAU,WAAW,mBAAmB,yBAAyB,+BAA+B,0BAA0B,CAAC,iBAAiB,kBAAkB,cAAc,oCAAsC,SAAS,MAAM,QAAQ,SAAS,OAAO,sBAAsB,CAAC,+BAA+B,cAAc,CAAC,mDAAmD,gBAAgB,CAAC,6DAA6D,WAAW,WAAW,CAAC,oBAAoB,QAAQ,iBAAiB,WAAW,kBAAkB,iBAAiB,CAAC,owBAAowB,iBAAiB,CAAC,qCAAqC,cAAc,aAAa,cAAc,CAAC,8BAA8B,WAAW,YAAY,2CAA2C,CAAC,0BAA0B,iDAAiD,wBAAwB,oBAAoB,eAAe,eAAe,oBAAoB,CAAC,0BAA0B,GAAK,uBAAwB,CAAC,CAAC,wBAAwB,GAAG,uBAAuB,mBAAmB,CAAC,IAAI,wBAAwB,uBAAuB,CAAC,GAAK,wBAAwB,wBAAwB,CAAC,CAAC,QAAQ,qBAAqB,CAAC,6BAA6B,aAAa,CAAC,cAAc,UAAU,CAAC,cAAc,oBAAoB,YAAY,CAAC,yCAAyC,YAAY,CAAC,8BAA8B,mBAAmB,oBAAoB,CAAC,8BAA8B,sBAAsB,kBAAkB,CAAC,sCAAsC,yBAAyB,4BAA4B,CAAC,uCAAuC,sBAAsB,6BAA6B,CAAC,6BAA6B,kBAAkB,wBAAwB,CAAC,gCAAgC,qBAAqB,sBAAsB,CAAC,+PAA+P,WAAW,qBAAqB,CAAC,UAAU,OAAO,CAAC,iBAAiB,aAAa,CAAC,eAAe,OAAO,CAAC,eAAe,MAAM,CAAC,UAAU,cAAc,CAAC,iBAAiB,oBAAoB,CAAC,eAAe,cAAc,CAAC,eAAe,aAAa,CAAC,UAAU,cAAc,CAAC,iBAAiB,oBAAoB,CAAC,eAAe,cAAc,CAAC,eAAe,aAAa,CAAC,UAAU,WAAW,CAAC,iBAAiB,iBAAiB,CAAC,eAAe,WAAW,CAAC,eAAe,UAAU,CAAC,UAAU,eAAe,CAAC,iBAAiB,qBAAqB,CAAC,eAAe,eAAe,CAAC,eAAe,cAAc,CAAC,UAAU,eAAe,CAAC,iBAAiB,qBAAqB,CAAC,eAAe,eAAe,CAAC,eAAe,cAAc,CAAC,UAAU,SAAS,CAAC,iBAAiB,eAAe,CAAC,eAAe,SAAS,CAAC,eAAe,QAAQ,CAAC,UAAU,eAAe,CAAC,iBAAiB,qBAAqB,CAAC,eAAe,eAAe,CAAC,eAAe,cAAc,CAAC,UAAU,eAAe,CAAC,iBAAiB,qBAAqB,CAAC,eAAe,eAAe,CAAC,eAAe,cAAc,CAAC,UAAU,WAAW,CAAC,iBAAiB,iBAAiB,CAAC,eAAe,WAAW,CAAC,eAAe,UAAU,CAAC,WAAW,eAAe,CAAC,kBAAkB,qBAAqB,CAAC,gBAAgB,eAAe,CAAC,gBAAgB,cAAc,CAAC,WAAW,eAAe,CAAC,kBAAkB,qBAAqB,CAAC,gBAAgB,eAAe,CAAC,gBAAgB,cAAc,CAAC,WAAW,SAAS,CAAC,kBAAkB,eAAe,CAAC,gBAAgB,kBAAkB,SAAS,CAAC,gBAAgB,QAAQ,CAAC,WAAW,eAAe,CAAC,kBAAkB,qBAAqB,CAAC,gBAAgB,eAAe,CAAC,gBAAgB,cAAc,CAAC,WAAW,eAAe,CAAC,kBAAkB,qBAAqB,CAAC,gBAAgB,eAAe,CAAC,gBAAgB,cAAc,CAAC,WAAW,WAAW,CAAC,kBAAkB,iBAAiB,CAAC,gBAAgB,WAAW,CAAC,gBAAgB,UAAU,CAAC,WAAW,eAAe,CAAC,kBAAkB,qBAAqB,CAAC,gBAAgB,eAAe,CAAC,gBAAgB,cAAc,CAAC,WAAW,eAAe,CAAC,kBAAkB,qBAAqB,CAAC,gBAAgB,eAAe,CAAC,gBAAgB,cAAc,CAAC,WAAW,SAAS,CAAC,kBAAkB,eAAe,CAAC,gBAAgB,SAAS,CAAC,gBAAgB,QAAQ,CAAC,WAAW,eAAe,CAAC,kBAAkB,qBAAqB,CAAC,gBAAgB,eAAe,CAAC,gBAAgB,cAAc,CAAC,WAAW,eAAe,CAAC,kBAAkB,qBAAqB,CAAC,gBAAgB,eAAe,CAAC,gBAAgB,cAAc,CAAC,WAAW,WAAW,CAAC,kBAAkB,iBAAiB,CAAC,gBAAgB,WAAW,CAAC,gBAAgB,UAAU,CAAC,WAAW,eAAe,CAAC,kBAAkB,qBAAqB,CAAC,gBAAgB,eAAe,CAAC,gBAAgB,cAAc,CAAC,WAAW,eAAe,CAAC,kBAAkB,qBAAqB,CAAC,gBAAgB,eAAe,CAAC,gBAAgB,cAAc,CAAC,WAAW,UAAU,CAAC,kBAAkB,gBAAgB,CAAC,gBAAgB,UAAU,CAAC,gBAAgB,SAAS,CAAC,yBAAyB,aAAa,OAAO,CAAC,oBAAoB,aAAa,CAAC,kBAAkB,kBAAkB,OAAO,CAAC,kBAAkB,kBAAkB,MAAM,CAAC,aAAa,cAAc,CAAC,oBAAoB,oBAAoB,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,kBAAkB,kBAAkB,aAAa,CAAC,aAAa,cAAc,CAAC,oBAAoB,oBAAoB,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,kBAAkB,kBAAkB,aAAa,CAAC,aAAa,WAAW,CAAC,oBAAoB,iBAAiB,CAAC,kBAAkB,kBAAkB,WAAW,CAAC,kBAAkB,kBAAkB,UAAU,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,SAAS,CAAC,oBAAoB,eAAe,CAAC,kBAAkB,kBAAkB,SAAS,CAAC,kBAAkB,kBAAkB,QAAQ,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,WAAW,CAAC,oBAAoB,iBAAiB,CAAC,kBAAkB,kBAAkB,WAAW,CAAC,kBAAkB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,SAAS,CAAC,qBAAqB,eAAe,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,mBAAmB,kBAAkB,QAAQ,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,WAAW,CAAC,qBAAqB,iBAAiB,CAAC,mBAAmB,kBAAkB,WAAW,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,SAAS,CAAC,qBAAqB,eAAe,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,mBAAmB,kBAAkB,QAAQ,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,WAAW,CAAC,qBAAqB,iBAAiB,CAAC,mBAAmB,kBAAkB,WAAW,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,UAAU,CAAC,qBAAqB,gBAAgB,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,CAAC,yBAAyB,aAAa,OAAO,CAAC,oBAAoB,aAAa,CAAC,kBAAkB,kBAAkB,OAAO,CAAC,kBAAkB,kBAAkB,MAAM,CAAC,aAAa,cAAc,CAAC,oBAAoB,oBAAoB,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,kBAAkB,kBAAkB,aAAa,CAAC,aAAa,cAAc,CAAC,oBAAoB,oBAAoB,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,kBAAkB,kBAAkB,aAAa,CAAC,aAAa,WAAW,CAAC,oBAAoB,iBAAiB,CAAC,kBAAkB,kBAAkB,WAAW,CAAC,kBAAkB,kBAAkB,UAAU,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,SAAS,CAAC,oBAAoB,eAAe,CAAC,kBAAkB,kBAAkB,SAAS,CAAC,kBAAkB,kBAAkB,QAAQ,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,WAAW,CAAC,oBAAoB,iBAAiB,CAAC,kBAAkB,kBAAkB,WAAW,CAAC,kBAAkB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,SAAS,CAAC,qBAAqB,eAAe,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,mBAAmB,kBAAkB,QAAQ,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,WAAW,CAAC,qBAAqB,iBAAiB,CAAC,mBAAmB,kBAAkB,WAAW,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,SAAS,CAAC,qBAAqB,eAAe,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,mBAAmB,kBAAkB,QAAQ,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,WAAW,CAAC,qBAAqB,iBAAiB,CAAC,mBAAmB,kBAAkB,WAAW,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,UAAU,CAAC,qBAAqB,gBAAgB,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,CAAC,yBAAyB,aAAa,OAAO,CAAC,oBAAoB,aAAa,CAAC,kBAAkB,kBAAkB,OAAO,CAAC,kBAAkB,kBAAkB,MAAM,CAAC,aAAa,cAAc,CAAC,oBAAoB,oBAAoB,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,kBAAkB,kBAAkB,aAAa,CAAC,aAAa,cAAc,CAAC,oBAAoB,oBAAoB,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,kBAAkB,kBAAkB,aAAa,CAAC,aAAa,WAAW,CAAC,oBAAoB,iBAAiB,CAAC,kBAAkB,kBAAkB,WAAW,CAAC,kBAAkB,kBAAkB,UAAU,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,SAAS,CAAC,oBAAoB,eAAe,CAAC,kBAAkB,kBAAkB,SAAS,CAAC,kBAAkB,kBAAkB,QAAQ,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,WAAW,CAAC,oBAAoB,iBAAiB,CAAC,kBAAkB,kBAAkB,WAAW,CAAC,kBAAkB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,SAAS,CAAC,qBAAqB,eAAe,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,mBAAmB,kBAAkB,QAAQ,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,WAAW,CAAC,qBAAqB,iBAAiB,CAAC,mBAAmB,kBAAkB,WAAW,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,SAAS,CAAC,qBAAqB,eAAe,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,mBAAmB,kBAAkB,QAAQ,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,WAAW,CAAC,qBAAqB,iBAAiB,CAAC,mBAAmB,kBAAkB,WAAW,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,UAAU,CAAC,qBAAqB,gBAAgB,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,CAAC,0BAA0B,aAAa,OAAO,CAAC,oBAAoB,aAAa,CAAC,kBAAkB,kBAAkB,OAAO,CAAC,kBAAkB,kBAAkB,MAAM,CAAC,aAAa,cAAc,CAAC,oBAAoB,oBAAoB,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,kBAAkB,kBAAkB,aAAa,CAAC,aAAa,cAAc,CAAC,oBAAoB,oBAAoB,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,kBAAkB,kBAAkB,aAAa,CAAC,aAAa,WAAW,CAAC,oBAAoB,iBAAiB,CAAC,kBAAkB,kBAAkB,WAAW,CAAC,kBAAkB,kBAAkB,UAAU,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,SAAS,CAAC,oBAAoB,eAAe,CAAC,kBAAkB,kBAAkB,SAAS,CAAC,kBAAkB,kBAAkB,QAAQ,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,eAAe,CAAC,oBAAoB,qBAAqB,CAAC,kBAAkB,kBAAkB,eAAe,CAAC,kBAAkB,kBAAkB,cAAc,CAAC,aAAa,WAAW,CAAC,oBAAoB,iBAAiB,CAAC,kBAAkB,kBAAkB,WAAW,CAAC,kBAAkB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,SAAS,CAAC,qBAAqB,eAAe,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,mBAAmB,kBAAkB,QAAQ,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,WAAW,CAAC,qBAAqB,iBAAiB,CAAC,mBAAmB,kBAAkB,WAAW,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,SAAS,CAAC,qBAAqB,eAAe,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,mBAAmB,kBAAkB,QAAQ,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,WAAW,CAAC,qBAAqB,iBAAiB,CAAC,mBAAmB,kBAAkB,WAAW,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,eAAe,CAAC,qBAAqB,qBAAqB,CAAC,mBAAmB,kBAAkB,eAAe,CAAC,mBAAmB,kBAAkB,cAAc,CAAC,cAAc,UAAU,CAAC,qBAAqB,gBAAgB,CAAC,mBAAmB,kBAAkB,UAAU,CAAC,mBAAmB,kBAAkB,SAAS,CAAC,CAAC,8BAA8B,qBAAqB,YAAY,qBAAqB,CAAC,WAAW,qBAAqB,kBAAkB,cAAc,CAAC,kBAAkB,kBAAkB,WAAW,MAAM,OAAO,UAAU,uBAAuB,CAAC,kBAAkB,YAAY,CAAC,gBAAgB,eAAe,cAAc,cAAc,CAAC,yBAAyB,yBAAyB,0BAA0B,kBAAkB,sBAAsB,YAAY,aAAa,eAAe,kBAAkB,kBAAkB,CAAC,2BAA2B,eAAe,aAAa,CAAC,+BAA+B,qBAAqB,aAAa,CAAC,mBAAmB,sBAAsB,0BAA0B,kBAAkB,sBAAsB,YAAY,aAAa,kBAAkB,eAAe,kBAAkB,eAAe,CAAC,oCAAoC,cAAc,eAAe,iBAAiB,CAAC,uCAAuC,cAAc,iBAAiB,CAAC,mCAAmC,eAAe,cAAc,mBAAmB,gBAAgB,CAAC,mCAAmC,iBAAiB,CAAC,qCAAqC,0CAA0C,eAAe,eAAe,CAAC,yBAAyB,oBAAoB,CAAC,+BAA+B,sCAAsC,yBAAyB,CAAC,gBAAgB,SAAS,UAAU,eAAe,CAAC,2FAA2F,aAAa,CAAC,sBAAsB,4CAA4C,eAAe,cAAc,gBAAgB,eAAe,sBAAsB,kBAAkB,WAAW,iBAAiB,CAAC,uCAAuC,eAAe,eAAe,CAAC,mCAAmC,kBAAkB,SAAS,UAAU,CAAC,yCAAyC,kBAAkB,UAAU,OAAO,CAAC,kCAAkC,eAAe,CAAC,8CAA8C,aAAa,CAAC,qCAAqC,aAAa,kBAAkB,QAAQ,UAAU,eAAe,YAAY,cAAc,wBAAwB,mBAAmB,CAAC,2CAA2C,SAAS,CAAC,4BAA4B,wBAAwB,CAAC,2CAA2C,oBAAoB,CAAC,+CAA+C,YAAY,CAAC,oEAAoE,aAAa,CAAC,kEAAkE,cAAc,cAAc,CAAC,0EAA0E,YAAY,CAAC,2BAA2B,cAAc,cAAc,kBAAkB,gBAAgB,iBAAiB,uBAAuB,oBAAoB,CAAC,4CAA4C,cAAc,iBAAiB,YAAY,mBAAmB,CAAC,mCAAmC,kBAAkB,UAAU,MAAM,oBAAoB,YAAY,CAAC,6BAA6B,kBAAkB,WAAW,MAAM,eAAe,cAAc,YAAY,CAAC,mCAAmC,aAAa,CAAC,8BAA8B,SAAS,eAAe,kBAAkB,CAAC,oDAAoD,gBAAgB,sBAAsB,yBAAyB,kBAAkB,sBAAsB,YAAY,aAAa,mBAAmB,oBAAoB,CAAC,6IAA6I,UAAU,CAAC,gKAAgK,YAAY,CAAC,6EAA6E,aAAa,CAAC,yDAAyD,YAAY,CAAC,8DAA8D,WAAW,WAAW,CAAC,iEAAiE,kBAAkB,YAAY,SAAS,WAAW,YAAY,mBAAmB,kBAAkB,4BAA4B,wBAAwB,qCAAqC,CAAC,mEAAmE,eAAe,gBAAgB,uCAAuC,kCAAkC,CAAC,4DAA4D,kBAAkB,WAAW,YAAY,OAAO,MAAM,eAAe,kBAAkB,WAAW,UAAU,eAAe,gCAAgC,sBAAsB,CAAC,kEAAkE,qBAAqB,WAAW,YAAY,qBAAqB,CAAC,iEAAiE,aAAa,cAAc,CAAC,sEAAsE,gBAAgB,CAAC,yFAAyF,gBAAgB,kBAAkB,aAAa,CAAC,kEAAkE,SAAS,CAAC,uEAAuE,oBAAoB,CAAC,2CAA2C,QAAQ,SAAS,mCAAmC,+BAA+B,YAAY,WAAW,CAAC,8DAA8D,OAAO,CAAC,+CAA+C,gBAAgB,sBAAsB,yBAAyB,kBAAkB,sBAAsB,gBAAgB,4BAA4B,WAAW,CAAC,mIAAmI,UAAU,CAAC,wFAAwF,eAAe,gBAAgB,SAAS,WAAW,CAAC,wEAAwE,aAAa,CAAC,qFAAqF,iBAAiB,YAAY,CAAC,uFAAuF,YAAY,CAAC,yDAAyD,sBAAsB,qBAAqB,WAAW,YAAY,WAAW,kBAAkB,UAAU,iBAAiB,CAAC,oDAAoD,cAAc,eAAe,CAAC,sDAAsD,eAAe,cAAc,kBAAkB,SAAS,QAAQ,CAAC,4DAA4D,kBAAkB,YAAY,SAAS,WAAW,YAAY,mBAAmB,kBAAkB,4BAA4B,wBAAwB,yBAAyB,CAAC,8DAA8D,eAAe,gBAAgB,uCAAuC,kCAAkC,CAAC,sCAAsC,kBAAkB,QAAQ,CAAC,iBAAiB,kBAAkB,OAAO,MAAM,WAAW,YAAY,gBAAgB,WAAW,cAAc,CAAC,uBAAuB,qBAAqB,YAAY,qBAAqB,CAAC,qBAAqB,cAAc,WAAW,WAAW,CAAC,mCAAmC,UAAU,kBAAkB,SAAS,CAAC,wBAAwB,kBAAkB,YAAY,SAAS,WAAW,YAAY,mBAAmB,kBAAkB,4BAA4B,wBAAwB,qCAAqC,CAAC,0BAA0B,eAAe,gBAAgB,uCAAuC,mCAAmC,UAAU,CAAC,2BAA2B,qBAAqB,sBAAsB,gBAAgB,WAAW,CAAC,6CAA6C,SAAS,CAAC,0BAA0B,kBAAkB,MAAM,OAAO,WAAW,WAAW,CAAC,2BAA2B,kBAAkB,SAAS,OAAO,WAAW,YAAY,iCAAiC,iBAAiB,CAAC,gCAAgC,qBAAqB,WAAW,eAAe,eAAe,sBAAsB,iGAAiG,eAAe,CAAC,qCAAqC,UAAU,8BAA8B,CAAC,kDAAkD,gBAAgB,CAAC,sCAAsC,gCAAgC,2BAA2B,CAAC,2CAA2C,SAAS,CAAC,kCAAkC,WAAW,cAAc,eAAe,oBAAoB,iBAAiB,CAAC,wBAAwB,kBAAkB,SAAS,OAAO,sBAAsB,YAAY,WAAW,gBAAgB,uBAAuB,mBAAmB,gBAAgB,gBAAgB,eAAe,SAAS,iBAAiB,eAAe,aAAa,CAAC,aAAa,kBAAkB,aAAa,CAAC,kDAAkD,wBAAwB,CAAC,6CAA6C,aAAa,CAAC,gDAAgD,wBAAwB,CAAC,2CAA2C,aAAa,CAAC,mBAAmB,eAAe,cAAc,qBAAqB,sBAAsB,iBAAiB,aAAa,CAAC,qBAAqB,sBAAsB,aAAa,CAAC,qBAAqB,oBAAoB,CAAC,wCAAwC,kBAAkB,QAAQ,OAAO,WAAW,kBAAkB,SAAS,+BAAgC,0BAA2B,CAAC,0CAA0C,sBAAsB,oBAAoB,CAAC,8CAA8C,YAAY,CAAC,4CAA4C,gBAAgB,eAAe,aAAa,CAAC,yDAAyD,qBAAqB,qBAAqB,CAAC,2CAA2C,gBAAgB,cAAc,CAAC,iBAAiB,mBAAmB,WAAW,mBAAmB,qBAAqB,CAAC,wBAAwB,WAAW,oBAAoB,yBAAyB,gBAAgB,kBAAkB,qBAAqB,CAAC,wBAAwB,kBAAkB,OAAO,MAAM,YAAY,yBAAyB,iBAAiB,oBAAoB,aAAa,CAAC,4BAA4B,WAAW,eAAe,YAAY,CAAC,oBAAoB,GAAG,uBAAuB,CAAC,GAAK,0BAA0B,CAAC,CAAC,iBAAiB,UAAU,CAAC,kBAAkB,oCAAoC,WAAW,WAAW,CAAC,wBAAwB,eAAe,qBAAqB,wCAAwC,CAAC,kBAAkB,GAAK,uBAAwB,CAAC,CAAC,gBAAgB,GAAG,uBAAuB,mBAAmB,CAAC,IAAI,wBAAwB,qBAAqB,CAAC,GAAK,wBAAwB,sBAAsB,CAAC,CAAC,YAAY,6DAA6D,gBAAgB,kBAAkB,sBAAsB,kBAAkB,eAAe,SAAS,SAAS,+BAA+B,2BAA2B,sBAAsB,qCAAqC,eAAe,CAAC,kCAAkC,aAAa,CAAC,kCAAkC,aAAa,CAAC,iCAAiC,aAAa,CAAC,6BAA6B,aAAa,CAAC,mBAAmB,iBAAiB,kBAAkB,YAAY,iBAAiB,oBAAoB,aAAa,sBAAsB,kBAAkB,CAAC,qBAAqB,eAAe,kBAAkB,cAAc,kBAAkB,CAAC,iDAAiD,iBAAiB,CAAC,gCAAgC,aAAa,CAAC,iBAAiB,WAAW,YAAY,kBAAkB,OAAO,KAAK,CAAC,kBAAkB,sBAAsB,gBAAgB,CAAC,sBAAsB,QAAQ,QAAQ,kBAAkB,eAAe,cAAc,cAAc,CAAC,4BAA4B,aAAa,CAAC,qDAAqD,UAAU,oCAAoC,+BAA+B,CAAC,UAAU,kBAAkB,sBAAsB,oBAAoB,CAAC,mBAAmB,yBAAyB,mBAAmB,WAAW,qBAAqB,eAAe,YAAY,iBAAiB,cAAc,kBAAkB,qBAAqB,CAAC,0BAA0B,UAAU,WAAW,UAAU,QAAQ,iBAAiB,CAAC,4BAA4B,MAAM,WAAW,kBAAkB,gDAAgD,2CAA2C,CAAC,8BAA8B,kBAAkB,oBAAoB,CAAC,mCAAmC,SAAS,CAAC,SAAS,yBAAyB,kBAAkB,sBAAsB,gBAAgB,gEAAgE,CAAC,iBAAiB,kBAAkB,gCAAgC,qBAAqB,CAAC,eAAe,YAAY,CAAC,SAAS,YAAY,aAAa,CAAC,eAAe,YAAY,qBAAqB,CAAC,eAAe,eAAe,iBAAiB,cAAc,cAAc,CAAC,wCAAwC,kBAAkB,MAAM,MAAM,CAAC,qBAAqB,0BAA0B,qBAAqB,CAAC,kBAAkB,qBAAqB,eAAe,CAAC,eAAe,eAAe,qBAAqB,CAAC,UAAU,WAAW,CAAC,qCAAqC,YAAY,CAAC,8GAA8G,oBAAoB,CAAC,SAAS,kBAAkB,kBAAkB,CAAC,mCAAmC,eAAe,CAAC,oCAAoC,iBAAiB,CAAC,eAAe,kBAAkB,qBAAqB,wBAAwB,CAAC,2BAA2B,UAAU,sBAAsB,SAAS,SAAS,SAAS,CAAC,6BAA6B,SAAS,WAAW,UAAU,OAAO,CAAC,qCAAqC,SAAS,CAAC,qBAAqB,cAAc,iBAAiB,mBAAmB,qBAAqB,oBAAqB,sBAAsB,QAAQ,QAAQ,CAAC,eAAe,cAAc,gBAAgB,CAAC,iBAAiB,oBAAoB,qBAAqB,CAAC,eAAe,WAAW,YAAY,kBAAkB,6BAA6B,iBAAiB,eAAe,mBAAmB,mBAAoB,CAAC,yCAAyC,SAAS,eAAe,eAAe,SAAS,CAAC,yBAAyB,cAAc,oBAAoB,CAAC,wBAAwB,cAAc,oBAAoB,CAAC,0BAA0B,cAAc,oBAAoB,CAAC,iDAAiD,cAAc,oBAAoB,CAAC,uBAAuB,eAAe,iBAAiB,kBAAkB,CAAC,iCAAiC,WAAW,yBAAyB,oBAAoB,CAAC,gCAAgC,WAAW,yBAAyB,oBAAoB,CAAC,kCAAkC,WAAW,yBAAyB,oBAAoB,CAAC,+BAA+B,cAAc,sBAAsB,oBAAoB,CAAC,kCAAkC,WAAW,yBAAyB,oBAAoB,CAAC,eAAe,mBAAmB,mBAAmB,eAAe,CAAC,gBAAgB,eAAe,iBAAiB,oBAAoB,CAAC,0BAA0B,gBAAgB,aAAa,CAAC,yBAAyB,gBAAgB,aAAa,CAAC,2BAA2B,gBAAgB,aAAa,CAAC,wBAAwB,gBAAgB,aAAa,CAAC,2BAA2B,gBAAgB,aAAa,CAAC,sBAAsB,eAAe,gBAAgB,gBAAgB,CAAC,gCAAgC,aAAa,CAAC,+BAA+B,aAAa,CAAC,iCAAiC,aAAa,CAAC,8BAA8B,aAAa,CAAC,iCAAiC,aAAa,CAAC,aAAa,kBAAkB,iBAAiB,CAAC,wBAAwB,kBAAkB,YAAY,CAAC,oBAAoB,YAAY,UAAU,WAAW,YAAY,kBAAkB,oCAAoC,WAAW,kBAAkB,QAAQ,WAAW,+BAA+B,2BAA2B,kBAAkB,cAAc,CAAC,0BAA0B,mCAAmC,CAAC,sBAAsB,cAAc,CAAC,0BAA0B,SAAS,CAAC,2BAA2B,UAAU,CAAC,yBAAyB,kBAAkB,gBAAgB,SAAS,SAAS,+BAA+B,2BAA2B,SAAS,UAAU,SAAS,CAAC,kCAAkC,YAAY,kBAAkB,gBAAgB,mBAAmB,cAAc,CAAC,uEAAuE,WAAW,CAAC,yCAAyC,yBAAyB,WAAW,CAAC,iCAAiC,OAAO,QAAQ,mBAAmB,eAAe,iBAAiB,CAAC,sDAAsD,WAAW,YAAY,iBAAiB,cAAc,CAAC,yDAAyD,eAAe,CAAC,wBAAwB,qBAAqB,6BAA6B,iBAAiB,cAAc,CAAC,qCAAqC,WAAW,CAAC,yCAAyC,SAAS,CAAC,qBAAqB,cAAc,YAAY,WAAW,WAAW,sBAAsB,YAAY,SAAS,CAAC,6DAA6D,iDAAiD,6CAA6C,SAAS,CAAC,+DAA+D,gDAAgD,4CAA4C,SAAS,CAAC,cAAc,gBAAgB,iBAAiB,CAAC,sHAAsH,UAAU,gCAAiC,CAAC,oBAAoB,eAAe,CAAC,uDAAuD,QAAQ,QAAQ,CAAC,qBAAqB,kBAAkB,cAAc,QAAQ,SAAS,eAAe,sBAAsB,sCAAsC,+BAA+B,CAAC,2BAA2B,qCAAqC,CAAC,mBAAmB,kBAAkB,UAAU,WAAW,UAAU,kBAAkB,UAAU,gCAAiC,CAAC,yDAAyD,oCAAoC,CAAC,iCAAiC,WAAW,QAAQ,CAAC,qCAAqC,WAAW,CAAC,+BAA+B,UAAU,OAAO,CAAC,mCAAmC,UAAU,CAAC,mBAAmB,kBAAkB,MAAM,OAAO,WAAW,YAAY,qBAAqB,gBAAgB,SAAS,CAAC,6BAA6B,SAAS,CAAC,yBAAyB,SAAS,CAAC,qCAAqC,eAAe,SAAS,CAAC,yFAAyF,SAAS,CAAC,+HAA+H,WAAW,CAAC,mBAAmB,kBAAkB,WAAW,YAAY,MAAM,OAAO,sBAAsB,YAAY,cAAc,CAAC,aAAa,yBAAyB,eAAe,CAAC,6BAA6B,kBAAkB,CAAC,uFAAuF,4BAA4B,uBAAuB,CAAC,0BAA0B,YAAY,iBAAiB,kBAAkB,sBAAsB,cAAc,eAAe,gCAAgC,cAAc,CAAC,iCAAiC,iBAAiB,wBAAwB,CAAC,wBAAwB,mBAAmB,yBAAyB,gBAAgB,sBAAsB,+BAA+B,CAAC,2BAA2B,kBAAkB,eAAe,cAAc,6BAA6B,CAAC,aAAa,qBAAqB,iBAAiB,CAAC,qDAAqD,cAAc,CAAC,6BAA6B,eAAe,CAAC,mCAAmC,wBAAwB,CAAC,8CAA8C,6BAA6B,wBAAyB,CAAC,6CAA6C,UAAU,UAAU,CAAC,oBAAoB,kBAAkB,OAAO,MAAM,YAAY,iBAAiB,sBAAsB,cAAc,WAAW,mBAAmB,uBAAuB,gBAAgB,sBAAsB,eAAe,eAAe,eAAe,CAAC,yBAAyB,aAAa,CAAC,oBAAoB,cAAc,CAAC,wCAAwC,gBAAgB,CAAC,oBAAoB,cAAc,CAAC,wCAAwC,gBAAgB,CAAC,mBAAmB,mBAAmB,gBAAgB,kBAAkB,aAAa,yBAAyB,kBAAkB,4DAA4D,CAAC,kBAAkB,qBAAqB,mBAAmB,aAAa,cAAc,+BAA+B,sBAAsB,sBAAsB,SAAS,cAAc,eAAe,CAAC,6BAA6B,cAAc,CAAC,wBAAwB,eAAe,0BAA0B,kBAAkB,mBAAmB,gBAAgB,uBAAuB,cAAc,YAAY,gBAAgB,sBAAsB,cAAc,CAAC,8BAA8B,wBAAwB,CAAC,iCAAiC,WAAW,wBAAwB,CAAC,uCAAuC,wBAAwB,CAAC,kCAAkC,WAAW,wBAAwB,CAAC,wCAAwC,wBAAwB,CAAC,oCAAoC,cAAc,sBAAsB,kBAAkB,CAAC,0CAA0C,qBAAqB,CAAC,iCAAiC,eAAe,CAAC,0CAA0C,0BAA0B,gBAAgB,eAAe,wBAAwB,oBAAoB,cAAc,kBAAkB,WAAW,cAAc,CAAC,4BAA4B,YAAY,iBAAiB,aAAa,CAAC,oDAAoD,gBAAgB,CAAC,qBAAqB,kBAAkB,sBAAsB,YAAY,YAAY,qBAAqB,aAAa,CAAC,iCAAiC,WAAW,aAAa,aAAa,CAAC,2DAA2D,yFAAiG,CAAC,6DAA6D,OAAO,MAAM,WAAW,UAAU,CAAC,0BAA0B,kBAAkB,yFAAiG,WAAW,CAAC,4BAA4B,kBAAkB,eAAe,sBAAsB,OAAO,MAAM,UAAU,YAAY,kBAAkB,gBAAgB,yBAAyB,kCAAkC,SAAS,CAAC,kBAAkB,kBAAkB,YAAY,YAAY,CAAC,kDAAkD,kBAAkB,MAAM,OAAO,QAAQ,QAAQ,CAAC,yBAAyB,wDAA6D,CAAC,yBAAyB,iDAAqD,CAAC,0BAA0B,iBAAiB,CAAC,8BAA8B,YAAY,UAAU,WAAW,wFAAwF,kBAAkB,mCAAmC,8BAA8B,CAAC,uBAAuB,kBAAkB,sBAAsB,YAAY,YAAY,sJAAsJ,CAAC,mCAAmC,WAAW,YAAY,CAAC,+DAA+D,2DAAoF,CAAC,iEAAiE,OAAO,MAAM,WAAW,UAAU,CAAC,4BAA4B,kBAAkB,2DAAoF,WAAW,CAAC,8BAA8B,kBAAkB,eAAe,sBAAsB,OAAO,MAAM,UAAU,YAAY,kBAAkB,gBAAgB,yBAAyB,kCAAkC,SAAS,CAAC,mBAAmB,WAAW,CAAC,iCAAiC,iBAAiB,CAAC,uCAAwC,WAAW,cAAc,UAAU,CAAC,yBAAyB,eAAe,gBAAgB,CAAC,0BAA0B,WAAW,iBAAiB,eAAe,aAAa,CAAC,wBAAwB,yBAAyB,WAAW,iBAAiB,kBAAkB,eAAe,eAAe,6BAA6B,UAAU,cAAc,CAAC,kCAAkC,WAAW,kBAAkB,CAAC,8BAA8B,cAAc,oBAAoB,CAAC,6BAA6B,eAAe,cAAc,qBAAqB,aAAa,cAAc,CAAC,mCAAmC,aAAa,CAAC,iBAAiB,qBAAqB,kBAAkB,kBAAkB,CAAC,0BAA0B,qBAAqB,sBAAsB,YAAY,YAAY,yBAAyB,kBAAkB,WAAW,CAAC,wBAAwB,kBAAkB,qBAAqB,sBAAsB,sBAAsB,WAAW,YAAY,iBAAiB,CAAC,iCAAiC,4JAA4J,CAAC,8BAA8B,kBAAkB,OAAO,MAAM,QAAQ,QAAQ,CAAC,wBAAwB,eAAe,sBAAsB,WAAW,kBAAkB,QAAQ,QAAQ,CAAC,uBAAuB,qBAAqB,kBAAkB,SAAS,gBAAgB,WAAW,WAAW,cAAc,CAAC,2BAA2B,WAAW,oBAAoB,CAAC,wBAAwB,kBAAkB,WAAW,YAAY,sBAAsB,yBAAyB,4DAA4D,CAAC,UAAU,kBAAkB,cAAc,CAAC,uCAAuC,yBAAyB,qBAAqB,WAAW,kBAAkB,CAAC,kEAAkE,aAAa,CAAC,yDAAyD,aAAa,CAAC,6DAA6D,aAAa,CAAC,oDAAoD,aAAa,CAAC,qCAAqC,UAAU,oBAAoB,CAAC,iBAAiB,wBAAwB,qBAAqB,gBAAgB,sBAAsB,sBAAsB,kBAAkB,yBAAyB,sBAAsB,cAAc,kBAAkB,YAAY,cAAc,UAAU,iBAAiB,0DAA0D,CAAC,sCAAsC,wBAAwB,sBAAsB,yBAAyB,qBAAqB,UAAU,iBAAiB,CAAC,4CAA4C,aAAa,CAAC,mCAAmC,aAAa,CAAC,uCAAuC,aAAa,CAAC,8BAA8B,aAAa,CAAC,uBAAuB,oBAAoB,CAAC,uBAAuB,UAAU,oBAAoB,CAAC,gBAAgB,kBAAkB,WAAW,YAAY,QAAQ,MAAM,kBAAkB,cAAc,kBAAkB,CAAC,sBAAsB,WAAW,YAAY,QAAQ,qBAAqB,qBAAqB,CAAC,iCAAiC,kBAAkB,CAAC,mCAAmC,eAAe,aAAa,CAAC,oDAAoD,oBAAoB,CAAC,iBAAiB,cAAc,CAAC,kCAAkC,WAAW,CAAC,iBAAiB,cAAc,CAAC,kCAAkC,WAAW,CAAC,gBAAgB,cAAc,CAAC,iCAAiC,WAAW,CAAC,gBAAgB,mBAAmB,qBAAqB,WAAW,wBAAwB,CAAC,iCAAiC,sBAAsB,kBAAkB,CAAC,iDAAiD,yBAAyB,cAAc,sBAAsB,mBAAmB,kBAAkB,yBAAyB,kBAAkB,eAAe,UAAU,kBAAkB,CAAC,kEAAkE,yBAAyB,2BAA2B,CAAC,kEAAkE,0BAA0B,4BAA4B,CAAC,8IAA8I,cAAc,YAAY,CAAC,6TAA6T,yBAAyB,6BAA6B,cAAc,aAAa,eAAe,CAAC,4IAA4I,iBAAiB,CAAC,+BAA+B,eAAe,qBAAqB,CAAC,yBAAyB,cAAc,CAAC,wBAAwB,aAAa,CAAC,aAAa,qBAAqB,WAAW,qBAAqB,CAAC,6CAA6C,yBAAyB,qBAAqB,WAAW,kBAAkB,CAAC,wEAAwE,aAAa,CAAC,+DAA+D,aAAa,CAAC,mEAAmE,aAAa,CAAC,0DAA0D,aAAa,CAAC,oBAAoB,cAAc,gBAAgB,gBAAgB,gBAAgB,WAAW,cAAc,sBAAsB,sBAAsB,yBAAyB,kBAAkB,0DAA0D,CAAC,+CAA+C,aAAa,CAAC,sCAAsC,aAAa,CAAC,0CAA0C,aAAa,CAAC,iCAAiC,aAAa,CAAC,0BAA0B,oBAAoB,CAAC,0BAA0B,UAAU,oBAAoB,CAAC,WAAW,qBAAqB,cAAc,mBAAmB,eAAe,gBAAgB,yBAAyB,cAAc,SAAS,kBAAkB,iBAAiB,CAAC,sBAAsB,gBAAgB,CAAC,kCAAkC,cAAc,oBAAoB,CAAC,kBAAkB,cAAc,qBAAqB,SAAS,CAAC,6BAA6B,QAAQ,CAAC,kCAAkC,eAAe,CAAC,sBAAsB,kBAAkB,mBAAmB,CAAC,6BAA6B,oBAAoB,WAAW,kBAAkB,UAAU,SAAS,WAAW,YAAY,sBAAsB,oCAAsC,CAAC,iFAAiF,cAAc,mBAAmB,sBAAsB,yBAAyB,oBAAoB,CAAC,iCAAiC,eAAe,qBAAqB,kBAAkB,kBAAkB,CAAC,uCAAuC,4BAA4B,CAAC,4GAA4G,sBAAsB,qBAAqB,aAAa,CAAC,qBAAqB,cAAc,oBAAoB,CAAC,oDAAoD,gBAAgB,qBAAqB,aAAa,CAAC,2BAA2B,gBAAgB,qBAAqB,cAAc,SAAS,CAAC,oBAAoB,WAAW,yBAAyB,oBAAoB,CAAC,oDAAoD,mBAAmB,qBAAqB,UAAU,CAAC,yDAAyD,mBAAmB,qBAAqB,UAAU,CAAC,2BAA2B,SAAS,CAAC,6BAA6B,gBAAgB,yBAAyB,aAAa,CAAC,sEAAsE,gBAAgB,qBAAqB,aAAa,CAAC,oCAAoC,gBAAgB,qBAAqB,cAAc,SAAS,CAAC,oBAAoB,WAAW,yBAAyB,oBAAoB,CAAC,oDAAoD,mBAAmB,qBAAqB,UAAU,CAAC,yDAAyD,mBAAmB,qBAAqB,UAAU,CAAC,2BAA2B,SAAS,CAAC,6BAA6B,gBAAgB,yBAAyB,aAAa,CAAC,sEAAsE,gBAAgB,qBAAqB,aAAa,CAAC,oCAAoC,gBAAgB,qBAAqB,cAAc,SAAS,CAAC,oBAAoB,WAAW,yBAAyB,oBAAoB,CAAC,oDAAoD,mBAAmB,qBAAqB,UAAU,CAAC,yDAAyD,mBAAmB,qBAAqB,UAAU,CAAC,2BAA2B,SAAS,CAAC,6BAA6B,gBAAgB,yBAAyB,aAAa,CAAC,sEAAsE,gBAAgB,qBAAqB,aAAa,CAAC,oCAAoC,gBAAgB,qBAAqB,cAAc,SAAS,CAAC,mBAAmB,WAAW,yBAAyB,oBAAoB,CAAC,kDAAkD,mBAAmB,qBAAqB,UAAU,CAAC,uDAAuD,mBAAmB,qBAAqB,UAAU,CAAC,0BAA0B,SAAS,CAAC,4BAA4B,gBAAgB,yBAAyB,aAAa,CAAC,oEAAoE,gBAAgB,qBAAqB,aAAa,CAAC,mCAAmC,gBAAgB,qBAAqB,cAAc,SAAS,CAAC,iBAAiB,WAAW,yBAAyB,oBAAoB,CAAC,8CAA8C,mBAAmB,qBAAqB,UAAU,CAAC,mDAAmD,mBAAmB,qBAAqB,UAAU,CAAC,wBAAwB,SAAS,CAAC,0BAA0B,gBAAgB,yBAAyB,aAAa,CAAC,gEAAgE,gBAAgB,qBAAqB,aAAa,CAAC,iCAAiC,gBAAgB,qBAAqB,cAAc,SAAS,CAAC,kBAAkB,kBAAkB,eAAe,iBAAiB,CAAC,kBAAkB,gBAAgB,eAAe,iBAAiB,CAAC,iBAAiB,YAAY,eAAe,iBAAiB,CAAC,iBAAiB,YAAY,cAAc,eAAe,eAAe,eAAe,CAAC,8CAA8C,aAAa,CAAC,wBAAwB,aAAa,CAAC,iBAAiB,qBAAqB,qBAAqB,CAAC,iDAAiD,qCAAuC,CAAC,gDAAgD,oCAAsC,CAAC,wEAAwE,qCAAuC,qCAAuC,CAAC,iDAAiD,qCAAuC,CAAC,gDAAgD,oCAAsC,CAAC,wEAAwE,qCAAuC,qCAAuC,CAAC,iDAAiD,qCAAuC,CAAC,gDAAgD,oCAAsC,CAAC,wEAAwE,qCAAuC,qCAAuC,CAAC,gDAAgD,qCAAuC,CAAC,+CAA+C,oCAAsC,CAAC,uEAAuE,qCAAuC,qCAAuC,CAAC,8CAA8C,qCAAuC,CAAC,6CAA6C,oCAAsC,CAAC,qEAAqE,qCAAuC,qCAAuC,CAAC,4BAA4B,WAAW,iBAAiB,CAAC,uCAAuC,aAAa,CAAC,wCAAwC,0BAA0B,4BAA4B,CAAC,uCAAuC,yBAAyB,2BAA2B,CAAC,+DAA+D,eAAe,CAAC,6CAA6C,iBAAiB,CAAC,6IAA6I,SAAS,CAAC,aAAa,cAAc,sBAAsB,yBAAyB,oBAAoB,CAAC,0BAA0B,gBAAgB,CAAC,oBAAoB,UAAU,cAAc,qBAAqB,CAAC,yDAAyD,yBAAyB,oBAAoB,CAAC,gEAAiE,WAAW,kBAAkB,cAAc,sBAAsB,gBAAgB,SAAS,UAAU,OAAO,CAAC,+DAAgE,YAAY,CAAC,iDAAiD,oBAAoB,CAAC,mDAAmD,yBAAyB,oBAAoB,CAAC,yDAA0D,sCAAsC,iCAAiC,CAAC,oDAAoD,yBAAyB,qBAAqB,kBAAkB,CAAC,0DAA2D,mBAAmB,oBAAoB,CAAC,wEAAwE,kBAAkB,CAAC,+DAA+D,yBAAyB,oBAAoB,CAAC,qEAAsE,iBAAiB,CAAC,qEAAqE,yBAAyB,oBAAoB,CAAC,4EAA6E,iBAAiB,CAAC,oDAAoD,WAAW,kBAAkB,CAAC,oBAAoB,qBAAqB,kBAAkB,yBAAyB,kBAAkB,sBAAsB,WAAW,YAAY,sBAAsB,UAAU,kHAAkH,CAAC,0BAA0B,oBAAoB,CAAC,0BAA2B,uBAAuB,WAAW,sBAAsB,cAAc,aAAa,WAAW,SAAS,kBAAkB,QAAQ,sCAAsC,kCAAkC,UAAU,6DAA6D,4BAA4B,uBAAuB,CAAC,uBAAuB,UAAU,UAAU,kBAAkB,SAAS,QAAQ,SAAS,WAAW,CAAC,+CAA+C,kBAAkB,oBAAoB,CAAC,oBAAoB,eAAe,gBAAgB,CAAC,0DAA0D,WAAW,yBAAyB,qBAAqB,6BAA6B,CAAC,2DAA2D,cAAc,mBAAmB,sBAAsB,yBAAyB,qBAAqB,eAAe,CAAC,8CAA8C,gBAAgB,sBAAsB,qBAAqB,CAAC,wDAAwD,oBAAoB,CAAC,2DAA2D,8BAA8B,0BAA0B,yBAAyB,CAAC,0DAA0D,yBAAyB,CAAC,2BAA2B,cAAc,mBAAmB,yBAAyB,cAAc,cAAc,SAAS,eAAe,kDAAkD,kBAAkB,eAAe,eAAe,CAAC,iCAAiC,aAAa,CAAC,6CAA6C,cAAc,CAAC,kDAAkD,eAAe,CAAC,8BAA8B,UAAU,UAAU,kBAAkB,SAAS,WAAW,CAAC,sDAAsD,kBAAkB,eAAe,eAAe,CAAC,sDAAsD,gBAAgB,eAAe,eAAe,CAAC,qDAAqD,YAAY,eAAe,eAAe,CAAC,aAAa,cAAc,CAAC,sBAAsB,qBAAqB,sBAAsB,cAAc,CAAC,iCAAiC,cAAc,cAAc,gBAAgB,CAAC,0GAA0G,aAAa,CAAC,6CAA6C,iBAAiB,CAAC,mBAAmB,yBAAyB,6DAA6D,qBAAqB,YAAY,iBAAiB,CAAC,8CAA8C,YAAY,iBAAiB,mBAAmB,SAAS,kBAAkB,gCAAgC,sBAAsB,aAAa,CAAC,8CAA8C,YAAY,gBAAgB,SAAS,UAAU,6BAA6B,kBAAkB,SAAS,OAAO,WAAW,SAAS,CAAC,oDAAoD,qBAAqB,WAAW,YAAY,qBAAqB,CAAC,2DAA2D,kBAAkB,aAAa,CAAC,6CAA6C,SAAS,YAAY,iBAAiB,mBAAmB,aAAa,CAAC,uCAAuC,iBAAiB,CAAC,uCAAuC,WAAW,YAAY,iBAAiB,CAAC,6CAA8C,WAAW,UAAU,QAAQ,CAAC,yBAAyB,oBAAoB,YAAY,CAAC,yBAAyB,SAAS,cAAc,gBAAgB,aAAa,cAAc,qBAAqB,CAAC,uCAAuC,YAAY,CAAC,yBAAyB,YAAY,iBAAiB,kBAAkB,aAAa,CAAC,6CAA6C,WAAW,gBAAgB,uBAAuB,mBAAmB,cAAc,sBAAsB,iBAAiB,CAAC,6CAA6C,kBAAkB,OAAO,CAAC,qCAAqC,aAAa,CAAC,+BAA+B,kBAAkB,CAAC,2BAA2B,gBAAgB,kBAAkB,eAAe,WAAW,qBAAqB,CAAC,4CAA4C,YAAY,WAAW,qBAAqB,qBAAqB,CAAC,2CAA2C,UAAU,CAAC,iDAAiD,cAAc,CAAC\",file:\"index.css\",sourcesContent:['@charset \"UTF-8\";.el-breadcrumb:after,.el-breadcrumb:before,.el-button-group:after,.el-button-group:before,.el-form-item:after,.el-form-item:before,.el-form-item__content:after,.el-form-item__content:before{display:table;content:\"\"}.el-checkbox-button__original,.el-pagination--small .arrow.disabled,.el-table .hidden-columns,.el-table td.is-hidden>*,.el-table th.is-hidden>*,.el-table--hidden{visibility:hidden}.el-form-item__content:after{clear:both}.el-form-item:after{clear:both}.el-breadcrumb:after{clear:both}.el-button-group:after{clear:both}.el-autocomplete-suggestion.is-loading li:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-dialog__header:after,.el-dialog__header:before{display:table;content:\"\"}.el-dialog__header:after{clear:both}@font-face{font-family:element-icons;src:url(fonts/element-icons.woff?t=1472440741) format(\\'woff\\'),url(fonts/element-icons.ttf?t=1472440741) format(\\'truetype\\');font-weight:400;font-style:normal}[class*=\" el-icon-\"],[class^=el-icon-]{font-family:element-icons!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;vertical-align:baseline;display:inline-block;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-icon-arrow-down:before{content:\"\\\\e600\"}.el-icon-arrow-left:before{content:\"\\\\e601\"}.el-icon-arrow-right:before{content:\"\\\\e602\"}.el-icon-arrow-up:before{content:\"\\\\e603\"}.el-icon-caret-bottom:before{content:\"\\\\e604\"}.el-icon-caret-left:before{content:\"\\\\e605\"}.el-icon-caret-right:before{content:\"\\\\e606\"}.el-icon-caret-top:before{content:\"\\\\e607\"}.el-icon-check:before{content:\"\\\\e608\"}.el-icon-circle-check:before{content:\"\\\\e609\"}.el-icon-circle-close:before{content:\"\\\\e60a\"}.el-icon-circle-cross:before{content:\"\\\\e60b\"}.el-icon-close:before{content:\"\\\\e60c\"}.el-icon-upload:before{content:\"\\\\e60d\"}.el-icon-d-arrow-left:before{content:\"\\\\e60e\"}.el-icon-d-arrow-right:before{content:\"\\\\e60f\"}.el-icon-d-caret:before{content:\"\\\\e610\"}.el-icon-date:before{content:\"\\\\e611\"}.el-icon-delete:before{content:\"\\\\e612\"}.el-icon-document:before{content:\"\\\\e613\"}.el-icon-edit:before{content:\"\\\\e614\"}.el-icon-information:before{content:\"\\\\e615\"}.el-icon-loading:before{content:\"\\\\e616\"}.el-icon-menu:before{content:\"\\\\e617\"}.el-icon-message:before{content:\"\\\\e618\"}.el-icon-minus:before{content:\"\\\\e619\"}.el-icon-more:before{content:\"\\\\e61a\"}.el-icon-picture:before{content:\"\\\\e61b\"}.el-icon-plus:before{content:\"\\\\e61c\"}.el-icon-search:before{content:\"\\\\e61d\"}.el-icon-setting:before{content:\"\\\\e61e\"}.el-icon-share:before{content:\"\\\\e61f\"}.el-icon-star-off:before{content:\"\\\\e620\"}.el-icon-star-on:before{content:\"\\\\e621\"}.el-icon-time:before{content:\"\\\\e622\"}.el-icon-warning:before{content:\"\\\\e623\"}.el-icon-delete2:before{content:\"\\\\e624\"}.el-icon-upload2:before{content:\"\\\\e627\"}.el-icon-view:before{content:\"\\\\e626\"}.el-icon-loading{animation:rotating 1s linear infinite}.el-icon--right{margin-left:5px}.el-icon--left{margin-right:5px}@keyframes rotating{0%{transform:rotateZ(0)}100%{transform:rotateZ(360deg)}}.el-pagination{white-space:nowrap;padding:2px 5px;color:#48576a}.el-pagination:after,.el-pagination:before{display:table;content:\"\"}.el-pagination:after{clear:both}.el-pagination button,.el-pagination span{display:inline-block;font-size:13px;min-width:28px;height:28px;line-height:28px;vertical-align:top;box-sizing:border-box}.el-pagination .el-select .el-input{width:110px}.el-pagination .el-select .el-input input{padding-right:25px;border-radius:2px;height:28px}.el-pagination button{border:none;padding:0 6px;background:0 0}.el-pagination button:focus{outline:0}.el-pagination button:hover{color:#20a0ff}.el-pagination button.disabled{color:#e4e4e4;background-color:#fff;cursor:not-allowed}.el-pager li,.el-pager li.btn-quicknext:hover,.el-pager li.btn-quickprev:hover{cursor:pointer}.el-pagination .btn-next,.el-pagination .btn-prev{background:center center no-repeat #fff;background-size:16px;border:1px solid #d1dbe5;cursor:pointer;margin:0;color:#97a8be}.el-pagination .btn-next .el-icon,.el-pagination .btn-prev .el-icon{display:block;font-size:12px}.el-pagination .btn-prev{border-radius:2px 0 0 2px;border-right:0}.el-pagination .btn-next{border-radius:0 2px 2px 0;border-left:0}.el-pagination--small .btn-next,.el-pagination--small .btn-prev,.el-pagination--small .el-pager li,.el-pagination--small .el-pager li:last-child{border-color:transparent;font-size:12px;line-height:22px;height:22px;min-width:22px}.el-pagination--small .el-pager li{border-radius:2px}.el-pagination__sizes{margin:0 10px 0 0}.el-pagination__sizes .el-input .el-input__inner{font-size:13px;border-color:#d1dbe5}.el-pagination__sizes .el-input .el-input__inner:hover{border-color:#20a0ff}.el-pagination__jump{margin-left:10px}.el-pagination__total{margin:0 10px}.el-pagination__rightwrapper{float:right}.el-pagination__editor{border:1px solid #d1dbe5;border-radius:2px;line-height:18px;padding:4px 2px;width:30px;text-align:center;margin:0 6px;box-sizing:border-box;transition:border .3s;-moz-appearance:textfield}.el-pager,.el-pager li{vertical-align:top;display:inline-block;margin:0}.el-pagination__editor::-webkit-inner-spin-button,.el-pagination__editor::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.el-pagination__editor:focus{outline:0;border-color:#20a0ff}.el-autocomplete-suggestion__wrap,.el-pager li{border:1px solid #d1dbe5;box-sizing:border-box}.el-pager{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;list-style:none;font-size:0;padding:0}.el-date-table,.el-radio{-webkit-user-select:none;-ms-user-select:none}.el-date-table,.el-radio,.el-time-panel{-moz-user-select:none}.el-pager li{padding:0 4px;border-right:0;background:#fff;font-size:13px;min-width:28px;height:28px;line-height:28px;text-align:center}.el-pager li:last-child{border-right:1px solid #d1dbe5}.el-pager li.btn-quicknext,.el-pager li.btn-quickprev{line-height:28px;color:#97a8be}.el-pager li.active+li{border-left:0;padding-left:5px}.el-pager li:hover{color:#20a0ff}.el-pager li.active{border-color:#20a0ff;background-color:#20a0ff;color:#fff;cursor:default}.el-dialog{position:absolute;left:50%;-ms-transform:translateX(-50%);transform:translateX(-50%);background:#fff;border-radius:2px;box-shadow:0 1px 3px rgba(0,0,0,.3);box-sizing:border-box;margin-bottom:50px}.el-dialog--tiny{width:30%}.el-dialog--small{width:50%}.el-dialog--large{width:90%}.el-dialog--full{width:100%;top:0;margin-bottom:0;height:100%;overflow:auto}.el-dialog__wrapper{top:0;right:0;bottom:0;left:0;position:fixed;overflow:auto;margin:0}.el-autocomplete,.el-dropdown{display:inline-block;position:relative}.el-dialog__header{padding:20px 20px 0}.el-dialog__headerbtn{float:right;background:0 0;border:none;outline:0;padding:0;cursor:pointer;font-size:16px}.el-dialog__headerbtn .el-dialog__close{color:#bfcbd9}.el-dialog__headerbtn:focus .el-dialog__close,.el-dialog__headerbtn:hover .el-dialog__close{color:#20a0ff}.el-dialog__title{line-height:1;font-size:16px;font-weight:700;color:#1f2d3d}.el-dialog__body{padding:30px 20px;color:#48576a;font-size:14px}.el-dialog__footer{padding:10px 20px 15px;text-align:right;box-sizing:border-box}.dialog-fade-enter-active{animation:dialog-fade-in .3s}.dialog-fade-leave-active{animation:dialog-fade-out .3s}@keyframes dialog-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}100%{transform:translate3d(0,0,0);opacity:1}}@keyframes dialog-fade-out{0%{transform:translate3d(0,0,0);opacity:1}100%{transform:translate3d(0,-20px,0);opacity:0}}.el-autocomplete-suggestion{margin:5px 0;box-shadow:0 0 6px 0 rgba(0,0,0,.04),0 2px 4px 0 rgba(0,0,0,.12)}.el-autocomplete-suggestion li{list-style:none;line-height:36px;padding:0 10px;margin:0;cursor:pointer;color:#48576a;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.el-autocomplete-suggestion li:hover{background-color:#e4e8f1}.el-autocomplete-suggestion li.highlighted{background-color:#20a0ff;color:#fff}.el-autocomplete-suggestion li:active{background-color:#0082e6}.el-autocomplete-suggestion.is-loading li:hover,.el-dropdown-menu{background-color:#fff}.el-autocomplete-suggestion li.divider{margin-top:6px;border-top:1px solid #d1dbe5}.el-autocomplete-suggestion li.divider:last-child{margin-bottom:-6px}.el-autocomplete-suggestion.is-loading li{text-align:center;height:100px;line-height:100px;font-size:20px;color:#999}.el-autocomplete-suggestion.is-loading .el-icon-loading{vertical-align:middle}.el-autocomplete-suggestion__wrap{max-height:280px;overflow:auto;background-color:#fff;padding:6px 0;border-radius:2px}.el-autocomplete-suggestion__list{margin:0;padding:0}.el-dropdown{color:#48576a;font-size:14px}.el-dropdown .el-button-group{display:block}.el-dropdown .el-button-group .el-button{float:none}.el-dropdown .el-dropdown__caret-button{padding-right:5px;padding-left:5px}.el-dropdown .el-dropdown__caret-button .el-dropdown__icon{padding-left:0}.el-dropdown__icon{font-size:12px;margin:0 3px}.el-dropdown-menu{margin:5px 0;border:1px solid #d1dbe5;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.12);padding:6px 0;z-index:10;position:absolute;top:0;left:0;min-width:100px}.el-dropdown-menu__item{list-style:none;line-height:36px;padding:0 10px;margin:0;cursor:pointer}.el-dropdown-menu__item:not(.is-disabled):hover{background-color:#e4e8f1;color:#48576a}.el-dropdown-menu__item.is-disabled{cursor:default;color:#bfcbd9;pointer-events:none}.el-dropdown-menu__item--divided{position:relative;margin-top:6px;border-top:1px solid #d1dbe5}.el-dropdown-menu__item--divided:before{content:\\'\\';height:6px;display:block;margin:0 -10px;background-color:#fff}.el-menu-item,.el-submenu__title{height:56px;line-height:56px;font-size:14px;color:#48576a;padding:0 20px;cursor:pointer;position:relative;transition:border-color .3s,background-color .3s,color .3s;box-sizing:border-box;white-space:nowrap}.el-menu{border-radius:2px;list-style:none;position:relative;margin:0;padding-left:0;background-color:#eef1f6}.el-menu:after,.el-menu:before{display:table;content:\"\"}.el-menu:after{clear:both}.el-menu li{list-style:none}.el-menu--dark{background-color:#324157}.el-menu--dark .el-menu-item,.el-menu--dark .el-submenu__title{color:#bfcbd9}.el-menu--dark .el-menu-item:hover,.el-menu--dark .el-submenu__title:hover{background-color:#48576a}.el-menu--dark .el-submenu .el-menu{background-color:#1f2d3d}.el-menu--dark .el-submenu .el-menu .el-menu-item:hover{background-color:#48576a}.el-menu--horizontal .el-menu-item{float:left;height:60px;line-height:60px;margin:0;cursor:pointer;position:relative;box-sizing:border-box;border-bottom:5px solid transparent}.el-menu--horizontal .el-menu-item a,.el-menu--horizontal .el-menu-item a:hover{color:inherit}.el-menu--horizontal .el-submenu{float:left;position:relative}.el-menu--horizontal .el-submenu>.el-menu{position:absolute;top:65px;left:0;border:1px solid #d1dbe5;padding:5px 0;background-color:#fff;z-index:100;min-width:100%;box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.el-menu--horizontal .el-submenu .el-submenu__title{height:60px;line-height:60px;border-bottom:5px solid transparent}.el-menu--horizontal .el-submenu .el-menu-item{background-color:#fff;float:none;height:36px;line-height:36px;padding:0 10px}.el-menu--horizontal .el-submenu .el-submenu__icon-arrow{position:static;vertical-align:middle;margin-left:5px;color:#97a8be;margin-top:-3px}.el-menu--horizontal .el-menu-item:hover,.el-menu--horizontal .el-submenu__title:hover{background-color:#eef1f6}.el-menu--horizontal>.el-menu-item:hover,.el-menu--horizontal>.el-submenu.is-active .el-submenu__title,.el-menu--horizontal>.el-submenu:hover .el-submenu__title{border-bottom:5px solid #20a0ff}.el-menu--horizontal.el-menu--dark .el-menu-item:hover,.el-menu--horizontal.el-menu--dark .el-submenu__title:hover{background-color:#324157}.el-menu--horizontal.el-menu--dark .el-submenu .el-menu-item:hover,.el-menu--horizontal.el-menu--dark .el-submenu .el-submenu-title:hover,.el-menu-item:hover{background-color:#d1dbe5}.el-menu--horizontal.el-menu--dark .el-submenu .el-menu-item,.el-menu--horizontal.el-menu--dark .el-submenu .el-submenu-title{color:#48576a}.el-menu--horizontal.el-menu--dark .el-submenu .el-menu-item.is-active,.el-menu-item.is-active{color:#20a0ff}.el-menu--collapse{width:64px}.el-menu--collapse>.el-menu-item [class^=el-icon-],.el-menu--collapse>.el-submenu>.el-submenu__title [class^=el-icon-]{margin:0;vertical-align:middle;width:24px;text-align:center}.el-menu--collapse>.el-menu-item .el-submenu__icon-arrow,.el-menu--collapse>.el-submenu>.el-submenu__title .el-submenu__icon-arrow{display:none}.el-menu--collapse>.el-menu-item span,.el-menu--collapse>.el-submenu>.el-submenu__title span{height:0;width:0;overflow:hidden;visibility:hidden;display:inline-block}.el-menu--collapse .el-submenu{position:relative}.el-menu--collapse .el-submenu .el-menu{position:absolute;margin-left:5px;top:0;left:100%;z-index:10}.el-menu--collapse .el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{-ms-transform:none;transform:none}.el-menu-item [class^=el-icon-]{margin-right:5px;width:24px;text-align:center}.el-menu-item *{vertical-align:middle}.el-menu-item:first-child{margin-left:0}.el-menu-item:last-child{margin-right:0}.el-submenu [class^=el-icon-]{vertical-align:middle;margin-right:5px;width:24px;text-align:center}.el-submenu .el-menu{background-color:#e4e8f1}.el-submenu .el-menu-item:hover,.el-submenu__title:hover{background-color:#d1dbe5}.el-submenu .el-menu-item{height:50px;line-height:50px;padding:0 45px;min-width:200px}.el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{-ms-transform:rotate(180deg);transform:rotateZ(180deg)}.el-submenu.is-active .el-submenu__title{border-bottom-color:#20a0ff}.el-submenu__title{position:relative}.el-submenu__title *{vertical-align:middle}.el-submenu__icon-arrow{position:absolute;top:50%;right:20px;margin-top:-7px;transition:transform .3s;font-size:12px}.el-radio,.el-radio__inner,.el-radio__input{position:relative;display:inline-block}.el-menu-item-group>ul{padding:0}.el-menu-item-group__title{padding-top:15px;line-height:normal;font-size:14px;padding-left:20px;color:#97a8be}.el-radio-button__inner,.el-radio-group,.el-radio__input{line-height:1;vertical-align:middle}.horizontal-collapse-transition .el-submenu__title .el-submenu__icon-arrow{transition:.2s;opacity:0}.el-radio{color:#1f2d3d;cursor:pointer;white-space:nowrap}.el-radio+.el-radio{margin-left:15px}.el-radio__input{white-space:nowrap;cursor:pointer;outline:0}.el-radio__input.is-focus .el-radio__inner{border-color:#20a0ff}.el-radio__input.is-checked .el-radio__inner{border-color:#20a0ff;background:#20a0ff}.el-radio__input.is-checked .el-radio__inner::after{-ms-transform:translate(-50%,-50%) scale(1);transform:translate(-50%,-50%) scale(1)}.el-radio__input.is-disabled .el-radio__inner{background-color:#eef1f6;border-color:#d1dbe5;cursor:not-allowed}.el-radio__input.is-disabled .el-radio__inner::after{cursor:not-allowed;background-color:#eef1f6}.el-radio__input.is-disabled .el-radio__inner+.el-radio__label{cursor:not-allowed}.el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:#d1dbe5;border-color:#d1dbe5}.el-radio__inner,.el-radio__input.is-disabled.is-checked .el-radio__inner::after{background-color:#fff}.el-radio__input.is-disabled+.el-radio__label{color:#bbb;cursor:not-allowed}.el-radio__inner{border:1px solid #bfcbd9;width:18px;height:18px;border-radius:50%;cursor:pointer;box-sizing:border-box}.el-radio__inner:hover{border-color:#20a0ff}.el-radio__inner::after{width:6px;height:6px;border-radius:50%;background-color:#fff;content:\"\";position:absolute;left:50%;top:50%;-ms-transform:translate(-50%,-50%) scale(0);transform:translate(-50%,-50%) scale(0);transition:transform .15s cubic-bezier(.71,-.46,.88,.6)}.el-switch__core,.el-switch__label{width:46px;height:22px;cursor:pointer}.el-radio__original{opacity:0;outline:0;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.el-radio-button,.el-radio-button__inner{position:relative;display:inline-block}.el-radio__label{font-size:14px;padding-left:5px}.el-radio-group{display:inline-block;font-size:0}.el-radio-group .el-radio{font-size:14px}.el-radio-button:first-child .el-radio-button__inner{border-left:1px solid #bfcbd9;border-radius:4px 0 0 4px;box-shadow:none!important}.el-radio-button:last-child .el-radio-button__inner{border-radius:0 4px 4px 0}.el-radio-button:first-child:last-child .el-radio-button__inner{border-radius:4px}.el-radio-button__inner{white-space:nowrap;background:#fff;border:1px solid #bfcbd9;border-left:0;color:#1f2d3d;-webkit-appearance:none;text-align:center;box-sizing:border-box;outline:0;margin:0;cursor:pointer;transition:all .3s cubic-bezier(.645,.045,.355,1);padding:10px 15px;font-size:14px;border-radius:0}.el-radio-button__inner:hover{color:#20a0ff}.el-radio-button__inner [class*=el-icon-]{line-height:.9}.el-radio-button__inner [class*=el-icon-]+span{margin-left:5px}.el-radio-button__orig-radio{opacity:0;outline:0;position:absolute;z-index:-1;left:-999px}.el-radio-button__orig-radio:checked+.el-radio-button__inner{color:#fff;background-color:#20a0ff;border-color:#20a0ff;box-shadow:-1px 0 0 0 #20a0ff}.el-radio-button__orig-radio:disabled+.el-radio-button__inner{color:#bfcbd9;cursor:not-allowed;background-image:none;background-color:#eef1f6;border-color:#d1dbe5;box-shadow:none}.el-radio-button--large .el-radio-button__inner{padding:11px 19px;font-size:16px;border-radius:0}.el-radio-button--small .el-radio-button__inner{padding:7px 9px;font-size:12px;border-radius:0}.el-radio-button--mini .el-radio-button__inner{padding:4px;font-size:12px;border-radius:0}.el-switch{display:inline-block;position:relative;font-size:14px;line-height:22px;height:22px;vertical-align:middle}.el-switch__label,.el-switch__label *{position:absolute;font-size:14px;display:inline-block}.el-switch .label-fade-enter,.el-switch .label-fade-leave-active{opacity:0}.el-switch.is-disabled .el-switch__core{border-color:#e4e8f1!important;background:#e4e8f1!important}.el-switch.is-disabled .el-switch__core span{background-color:#fbfdff!important}.el-switch.is-disabled .el-switch__core~.el-switch__label *{color:#fbfdff!important}.el-switch.is-checked .el-switch__core{border-color:#20a0ff;background-color:#20a0ff}.el-switch.is-disabled .el-switch__core,.el-switch.is-disabled .el-switch__label{cursor:not-allowed}.el-switch__label{transition:.2s;left:0;top:0}.el-switch__label *{line-height:1;top:4px;color:#fff}.el-switch__label--left i{left:6px}.el-switch__label--right i{right:6px}.el-switch__input{display:none}.el-switch__core{margin:0;display:inline-block;position:relative;border:1px solid #bfcbd9;outline:0;border-radius:12px;box-sizing:border-box;background:#bfcbd9;transition:border-color .3s,background-color .3s}.el-switch__core .el-switch__button{top:0;left:0;position:absolute;border-radius:100%;transition:transform .3s;width:16px;height:16px;background-color:#fff}.el-switch--wide .el-switch__label.el-switch__label--left span{left:10px}.el-switch--wide .el-switch__label.el-switch__label--right span{right:10px}.el-select-dropdown{position:absolute;z-index:1001;border:1px solid #d1dbe5;border-radius:2px;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);box-sizing:border-box;margin:5px 0}.el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list{padding:0}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected{color:#20a0ff;background-color:#fff}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover,.el-select-dropdown__item.hover,.el-select-dropdown__item:hover{background-color:#e4e8f1}.el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after{position:absolute;right:10px;font-family:element-icons;content:\"\\\\E608\";font-size:11px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.el-select-dropdown__empty{padding:10px 0;margin:0;text-align:center;color:#999;font-size:14px}.el-select-dropdown__wrap{max-height:274px}.el-select-dropdown__list{list-style:none;padding:6px 0;margin:0;box-sizing:border-box}.el-select-dropdown__item{font-size:14px;padding:8px 10px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#48576a;height:36px;line-height:1.5;box-sizing:border-box;cursor:pointer}.el-select-dropdown__item.selected{color:#fff;background-color:#20a0ff}.el-select-dropdown__item.selected.hover{background-color:#1c8de0}.el-select-dropdown__item span{line-height:1.5!important}.el-select-dropdown__item.is-disabled{color:#bfcbd9;cursor:not-allowed}.el-select-dropdown__item.is-disabled:hover{background-color:#fff}.el-select-group{margin:0;padding:0}.el-select-group .el-select-dropdown__item{padding-left:20px}.el-select-group__wrap{list-style:none;margin:0;padding:0}.el-select-group__title{padding-left:10px;font-size:12px;color:#999;height:30px;line-height:30px}.el-select{display:inline-block;position:relative}.el-select:hover .el-input__inner{border-color:#8391a5}.el-select .el-input__inner{cursor:pointer;padding-right:35px}.el-select .el-input__inner:focus{border-color:#20a0ff}.el-select .el-input .el-input__icon{color:#bfcbd9;font-size:12px;transition:transform .3s;-ms-transform:translateY(-50%) rotate(180deg);transform:translateY(-50%) rotateZ(180deg);line-height:16px;top:50%;cursor:pointer}.el-select .el-input .el-input__icon.is-show-close{transition:0s;width:16px;height:16px;font-size:14px;right:8px;text-align:center;-ms-transform:translateY(-50%) rotate(180deg);transform:translateY(-50%) rotateZ(180deg);border-radius:100%;color:#bfcbd9}.el-select .el-input .el-input__icon.is-show-close:hover{color:#97a8be}.el-select .el-input .el-input__icon.is-reverse{-ms-transform:translateY(-50%);transform:translateY(-50%)}.el-select .el-input.is-disabled .el-input__inner{cursor:not-allowed}.el-select .el-input.is-disabled .el-input__inner:hover{border-color:#d1dbe5}.el-select>.el-input{display:block}.el-select .el-tag__close{margin-top:-2px}.el-select .el-tag{height:24px;line-height:24px;box-sizing:border-box;margin:3px 0 3px 6px}.el-select__input{border:none;outline:0;padding:0;margin-left:10px;color:#666;font-size:14px;vertical-align:baseline;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:28px;background-color:transparent}.el-select__input.is-mini{height:14px}.el-select__close{cursor:pointer;position:absolute;top:8px;z-index:1000;right:25px;color:#bfcbd9;line-height:18px;font-size:12px}.el-select__close:hover{color:#97a8be}.el-select__tags{position:absolute;line-height:normal;white-space:normal;z-index:1;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%)}.el-table,.el-table td,.el-table th{box-sizing:border-box;position:relative}.el-select__tag{display:inline-block;height:24px;line-height:24px;font-size:14px;border-radius:4px;color:#fff;background-color:#20a0ff}.el-select__tag .el-icon-close{font-size:12px}.el-table{overflow:hidden;width:100%;max-width:100%;background-color:#fff;border:1px solid #dfe6ec;font-size:14px;color:#1f2d3d}.el-table .el-tooltip.cell{white-space:nowrap;min-width:50px}.el-table td,.el-table th{height:40px;min-width:0;text-overflow:ellipsis;vertical-align:middle}.el-table::after,.el-table::before{content:\\'\\';position:absolute;background-color:#dfe6ec;z-index:1}.el-table td.is-right,.el-table th.is-right{text-align:right}.el-table td.is-left,.el-table th.is-left{text-align:left}.el-table td.is-center,.el-table th.is-center{text-align:center}.el-table td,.el-table th.is-leaf{border-bottom:1px solid #dfe6ec}.el-table td.gutter,.el-table th.gutter{width:15px;border-right-width:0;border-bottom-width:0;padding:0}.el-table .cell,.el-table th>div{padding-left:18px;padding-right:18px;box-sizing:border-box;text-overflow:ellipsis}.el-table::before{left:0;bottom:0;width:100%;height:1px}.el-table::after{top:0;right:0;width:1px;height:100%}.el-table .caret-wrapper,.el-table th>.cell{position:relative;display:inline-block;vertical-align:middle}.el-table th{white-space:nowrap;overflow:hidden;background-color:#eef1f6;text-align:left}.el-table th.is-sortable{cursor:pointer}.el-table th>div{display:inline-block;line-height:40px;overflow:hidden;white-space:nowrap}.el-table td>div{box-sizing:border-box}.el-table th.required>div::before{display:inline-block;content:\"\";width:8px;height:8px;border-radius:50%;background:#ff4d51;margin-right:5px;vertical-align:middle}.el-table th>.cell{word-wrap:normal;text-overflow:ellipsis;line-height:30px;width:100%;box-sizing:border-box}.el-table th>.cell.highlight{color:#20a0ff}.el-table .caret-wrapper{cursor:pointer;margin-left:5px;margin-top:-2px;width:16px;height:30px;overflow:visible;overflow:initial}.el-table .cell,.el-table__footer-wrapper,.el-table__header-wrapper{overflow:hidden}.el-table .sort-caret{display:inline-block;width:0;height:0;border:0;content:\"\";position:absolute;left:3px;z-index:2}.el-table .sort-caret.ascending,.el-table .sort-caret.descending{border-right:5px solid transparent;border-left:5px solid transparent}.el-table .sort-caret.ascending{top:9px;border-top:none;border-bottom:5px solid #97a8be}.el-table .sort-caret.descending{bottom:9px;border-top:5px solid #97a8be;border-bottom:none}.el-table .ascending .sort-caret.ascending{border-bottom-color:#48576a}.el-table .descending .sort-caret.descending{border-top-color:#48576a}.el-table td.gutter{width:0}.el-table .cell{white-space:normal;word-break:break-all;line-height:24px}.el-badge__content,.el-message__group p,.el-progress-bar__inner,.el-steps.is-horizontal,.el-tabs__nav,.el-tag,.el-time-spinner,.el-tree-node,.el-upload-list__item-name{white-space:nowrap}.el-table tr input[type=checkbox]{margin:0}.el-table tr{background-color:#fff}.el-table .hidden-columns{position:absolute;z-index:-1}.el-table__empty-block{position:relative;min-height:60px;text-align:center;width:100%;height:100%}.el-table__empty-text{position:absolute;left:50%;top:50%;-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#5e7382}.el-table__expand-column .cell{padding:0;text-align:center}.el-table__expand-icon{position:relative;cursor:pointer;color:#666;font-size:12px;transition:transform .2s ease-in-out;height:40px}.el-table__expand-icon>.el-icon{position:absolute;left:50%;top:50%;margin-left:-5px;margin-top:-5px}.el-table__expand-icon--expanded{-ms-transform:rotate(90deg);transform:rotate(90deg)}.el-table__expanded-cell{padding:20px 50px;background-color:#fbfdff;box-shadow:inset 0 2px 0 #f4f4f4}.el-table__expanded-cell:hover{background-color:#fbfdff!important}.el-table--fit{border-right:0;border-bottom:0}.el-table--border th,.el-table__fixed-right-patch{border-bottom:1px solid #dfe6ec}.el-table--fit td.gutter,.el-table--fit th.gutter{border-right-width:1px}.el-table--border td,.el-table--border th{border-right:1px solid #dfe6ec}.el-table__fixed,.el-table__fixed-right{position:absolute;top:0;left:0;box-shadow:1px 0 8px #d3d4d6;overflow-x:hidden}.el-table__fixed-right::before,.el-table__fixed::before{content:\\'\\';position:absolute;left:0;bottom:0;width:100%;height:1px;background-color:#dfe6ec;z-index:4}.el-table__fixed-right-patch{position:absolute;top:-1px;right:0;background-color:#eef1f6}.el-table__fixed-right{top:0;left:auto;right:0;box-shadow:-1px 0 8px #d3d4d6}.el-table__fixed-right .el-table__fixed-body-wrapper,.el-table__fixed-right .el-table__fixed-footer-wrapper,.el-table__fixed-right .el-table__fixed-header-wrapper{left:auto;right:0}.el-table__fixed-header-wrapper{position:absolute;left:0;top:0;z-index:3}.el-table__fixed-header-wrapper thead div{background-color:#eef1f6;color:#1f2d3d}.el-table__fixed-footer-wrapper{position:absolute;left:0;bottom:0;z-index:3}.el-table__fixed-footer-wrapper tbody td{border-top:1px solid #dfe6ec;background-color:#fbfdff;color:#1f2d3d}.el-table__fixed-body-wrapper{position:absolute;left:0;top:37px;overflow:hidden;z-index:3}.el-table__body-wrapper,.el-table__footer-wrapper,.el-table__header-wrapper{width:100%}.el-table__footer-wrapper{margin-top:-1px}.el-table__footer-wrapper td{border-top:1px solid #dfe6ec}.el-table__body,.el-table__footer,.el-table__header{table-layout:fixed}.el-table__footer-wrapper thead div,.el-table__header-wrapper thead div{background-color:#eef1f6;color:#1f2d3d}.el-table__footer-wrapper tbody td,.el-table__header-wrapper tbody td{background-color:#fbfdff;color:#1f2d3d}.el-table__body-wrapper{overflow:auto;position:relative}.el-table--striped .el-table__body tr.el-table__row--striped td{background:#FAFAFA;background-clip:padding-box}.el-table--striped .el-table__body tr.el-table__row--striped.current-row td{background:#edf7ff}.el-table__body tr.hover-row.current-row>td,.el-table__body tr.hover-row.el-table__row--striped.current-row>td,.el-table__body tr.hover-row.el-table__row--striped>td,.el-table__body tr.hover-row>td{background-color:#eef1f6}.el-table__body tr.current-row>td{background:#edf7ff}.el-table__column-resize-proxy{position:absolute;left:200px;top:0;bottom:0;width:0;border-left:1px solid #dfe6ec;z-index:10}.el-table__column-filter-trigger{display:inline-block;line-height:34px;margin-left:5px;cursor:pointer}.el-table__column-filter-trigger i{color:#97a8be}.el-table--enable-row-transition .el-table__body td{transition:background-color .25s ease}.el-fade-in-linear-enter-active,.el-fade-in-linear-leave-active,.fade-in-linear-enter-active,.fade-in-linear-leave-active{transition:opacity .2s linear}.el-table--enable-row-hover .el-table__body tr:hover>td{background-color:#eef1f6;background-clip:padding-box}.el-table--fluid-height .el-table__fixed,.el-table--fluid-height .el-table__fixed-right{bottom:0;overflow:hidden}.el-table-column--selection .cell{padding-left:14px;padding-right:14px}.el-table-filter{border:1px solid #d1dbe5;border-radius:2px;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.12);box-sizing:border-box;margin:2px 0}.el-table-filter__list{padding:5px 0;margin:0;list-style:none;min-width:100px}.el-table-filter__list-item{line-height:36px;padding:0 10px;cursor:pointer;font-size:14px}.el-table-filter__list-item:hover{background-color:#e4e8f1;color:#48576a}.el-table-filter__list-item.is-active{background-color:#20a0ff;color:#fff}.el-table-filter__content{min-width:100px}.el-table-filter__bottom{border-top:1px solid #d1dbe5;padding:8px}.el-table-filter__bottom button{background:0 0;border:none;color:#8391a5;cursor:pointer;font-size:14px;padding:0 3px}.el-table-filter__bottom button:hover{color:#20a0ff}.el-table-filter__bottom button:focus{outline:0}.el-table-filter__bottom button.is-disabled{color:#bfcbd9;cursor:not-allowed}.el-table-filter__checkbox-group{padding:10px}.el-table-filter__checkbox-group label.el-checkbox{display:block;margin-bottom:8px;margin-left:5px}.el-table-filter__checkbox-group .el-checkbox:last-child{margin-bottom:0}.el-date-table{font-size:12px;min-width:224px;user-select:none}.el-date-table td{width:32px;height:32px;box-sizing:border-box;text-align:center;cursor:pointer}.el-date-table td.next-month,.el-date-table td.prev-month{color:#ddd}.el-date-table td.today{color:#20a0ff;position:relative}.el-date-table td.today:before{content:\" \";position:absolute;top:0;right:0;width:0;height:0;border-top:.5em solid #20a0ff;border-left:.5em solid transparent}.el-month-table td .cell,.el-year-table td .cell{width:48px;height:32px;display:block;line-height:32px}.el-date-table td.available:hover{background-color:#e4e8f1}.el-date-table td.in-range{background-color:#d2ecff}.el-date-table td.in-range:hover{background-color:#afddff}.el-date-table td.current:not(.disabled),.el-date-table td.end-date,.el-date-table td.start-date{background-color:#20a0ff!important;color:#fff}.el-date-table td.disabled{background-color:#f4f4f4;opacity:1;cursor:not-allowed;color:#ccc}.el-fade-in-enter,.el-fade-in-leave-active,.el-fade-in-linear-enter,.el-fade-in-linear-leave,.el-fade-in-linear-leave-active,.fade-in-linear-enter,.fade-in-linear-leave,.fade-in-linear-leave-active{opacity:0}.el-date-table td.week{font-size:80%;color:#8391a5}.el-month-table,.el-year-table{font-size:12px;margin:-1px;border-collapse:collapse}.el-date-table th{padding:5px;color:#8391a5;font-weight:400}.el-date-table.is-week-mode .el-date-table__row:hover{background-color:#e4e8f1}.el-date-table.is-week-mode .el-date-table__row.current{background-color:#d2ecff}.el-month-table td{text-align:center;padding:20px 3px;cursor:pointer}.el-month-table td .cell{color:#48576a}.el-month-table td .cell:hover{background-color:#e4e8f1}.el-month-table td.disabled .cell{background-color:#f4f4f4;cursor:not-allowed;color:#ccc}.el-month-table td.current:not(.disabled) .cell{background-color:#20a0ff!important;color:#fff}.el-year-table .el-icon{color:#97a8be}.el-year-table td{text-align:center;padding:20px 3px;cursor:pointer}.el-year-table td .cell{color:#48576a}.el-year-table td .cell:hover{background-color:#e4e8f1}.el-year-table td.disabled .cell{background-color:#f4f4f4;cursor:not-allowed;color:#ccc}.el-year-table td.current:not(.disabled) .cell{background-color:#20a0ff!important;color:#fff}.el-date-range-picker{min-width:520px}.el-date-range-picker table{table-layout:fixed;width:100%}.el-date-range-picker .el-picker-panel__body{min-width:513px}.el-date-range-picker .el-picker-panel__content{margin:0}.el-date-range-picker.has-sidebar.has-time{min-width:766px}.el-date-range-picker.has-sidebar{min-width:620px}.el-date-range-picker.has-time{min-width:660px}.el-date-range-picker__header{position:relative;text-align:center;height:28px}.el-date-range-picker__header button{float:left}.el-date-range-picker__header div{font-size:14px;margin-right:50px}.el-date-range-picker__content{float:left;width:50%;box-sizing:border-box;margin:0;padding:16px}.el-date-range-picker__content.is-right .el-date-range-picker__header button{float:right}.el-date-range-picker__content.is-right .el-date-range-picker__header div{margin-left:50px;margin-right:50px}.el-date-range-picker__content.is-left{border-right:1px solid #e4e4e4}.el-date-range-picker__editors-wrap{box-sizing:border-box;display:table-cell}.el-date-range-picker__editors-wrap.is-right{text-align:right}.el-date-range-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px;display:table;width:100%;box-sizing:border-box}.el-date-range-picker__time-header>.el-icon-arrow-right{font-size:20px;vertical-align:middle;display:table-cell;color:#97a8be}.el-date-range-picker__time-picker-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-range-picker__time-picker-wrap .el-picker-panel{position:absolute;top:13px;right:0;z-index:1;background:#fff}.el-time-range-picker{min-width:354px;overflow:visible}.el-time-range-picker__content{position:relative;text-align:center;padding:10px}.el-time-range-picker__cell{box-sizing:border-box;margin:0;padding:4px 7px 7px;width:50%;display:inline-block}.el-time-range-picker__header{margin-bottom:5px;text-align:center;font-size:14px}.el-time-range-picker__body{border-radius:2px;border:1px solid #d1dbe5}.el-picker-panel{color:#48576a;border:1px solid #d1dbe5;box-shadow:0 2px 6px #ccc;background:#fff;border-radius:2px;line-height:20px;margin:5px 0}.el-picker-panel__body-wrapper::after,.el-picker-panel__body::after{content:\"\";display:table;clear:both}.el-picker-panel__content{position:relative;margin:15px}.el-picker-panel__footer{border-top:1px solid #e4e4e4;padding:4px;text-align:right;background-color:#fff;position:relative}.el-picker-panel__shortcut{display:block;width:100%;border:0;background-color:transparent;line-height:28px;font-size:14px;color:#48576a;padding-left:12px;text-align:left;outline:0;cursor:pointer}.el-picker-panel__shortcut:hover{background-color:#e4e8f1}.el-picker-panel__shortcut.active{background-color:#e6f1fe;color:#20a0ff}.el-picker-panel__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.el-picker-panel__btn[disabled]{color:#ccc;cursor:not-allowed}.el-picker-panel__icon-btn{font-size:12px;color:#97a8be;border:0;background:0 0;cursor:pointer;outline:0;margin-top:3px}.el-date-picker__header-label.active,.el-date-picker__header-label:hover,.el-picker-panel__icon-btn:hover{color:#20a0ff}.el-picker-panel__link-btn{cursor:pointer;color:#20a0ff;text-decoration:none;padding:15px;font-size:12px}.el-picker-panel [slot=sidebar],.el-picker-panel__sidebar{position:absolute;top:0;bottom:0;width:110px;border-right:1px solid #e4e4e4;box-sizing:border-box;padding-top:6px;background-color:#fbfdff;overflow:auto}.el-picker-panel [slot=sidebar]+.el-picker-panel__body,.el-picker-panel__sidebar+.el-picker-panel__body{margin-left:110px}.el-date-picker{min-width:254px}.el-date-picker .el-picker-panel__content{min-width:224px}.el-date-picker table{table-layout:fixed;width:100%}.el-date-picker.has-sidebar.has-time{min-width:434px}.el-date-picker.has-sidebar{min-width:370px}.el-date-picker.has-time{min-width:324px}.el-date-picker__editor-wrap{position:relative;display:table-cell;padding:0 5px}.el-date-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px;display:table;width:100%;box-sizing:border-box}.el-date-picker__header{margin:12px;text-align:center}.el-date-picker__header-label{font-size:14px;padding:0 5px;line-height:22px;text-align:center;cursor:pointer}.el-date-picker__prev-btn{float:left}.el-date-picker__next-btn{float:right}.el-date-picker__time-wrap{padding:10px;text-align:center}.el-date-picker__time-label{float:left;cursor:pointer;line-height:30px;margin-left:10px}.time-select{margin:5px 0;min-width:0}.time-select .el-picker-panel__content{max-height:200px;margin:0}.time-select-item{padding:8px 10px;font-size:14px}.time-select-item.selected:not(.disabled){background-color:#20a0ff;color:#fff}.time-select-item.selected:not(.disabled):hover{background-color:#20a0ff}.time-select-item.disabled{color:#d1dbe5;cursor:not-allowed}.time-select-item:hover{background-color:#e4e8f1;cursor:pointer}.el-fade-in-enter-active,.el-fade-in-leave-active,.el-zoom-in-center-enter-active,.el-zoom-in-center-leave-active{transition:all .3s cubic-bezier(.55,0,.1,1)}.el-zoom-in-bottom-enter-active,.el-zoom-in-bottom-leave-active,.el-zoom-in-left-enter-active,.el-zoom-in-left-leave-active,.el-zoom-in-top-enter-active,.el-zoom-in-top-leave-active{transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s}.el-zoom-in-center-enter,.el-zoom-in-center-leave-active{opacity:0;-ms-transform:scaleX(0);transform:scaleX(0)}.el-zoom-in-top-enter-active,.el-zoom-in-top-leave-active{opacity:1;-ms-transform:scaleY(1);transform:scaleY(1);-ms-transform-origin:center top;transform-origin:center top}.el-zoom-in-top-enter,.el-zoom-in-top-leave-active{opacity:0;-ms-transform:scaleY(0);transform:scaleY(0)}.el-zoom-in-bottom-enter-active,.el-zoom-in-bottom-leave-active{opacity:1;-ms-transform:scaleY(1);transform:scaleY(1);-ms-transform-origin:center bottom;transform-origin:center bottom}.el-zoom-in-bottom-enter,.el-zoom-in-bottom-leave-active{opacity:0;-ms-transform:scaleY(0);transform:scaleY(0)}.el-zoom-in-left-enter-active,.el-zoom-in-left-leave-active{opacity:1;-ms-transform:scale(1,1);transform:scale(1,1);-ms-transform-origin:top left;transform-origin:top left}.el-zoom-in-left-enter,.el-zoom-in-left-leave-active{opacity:0;-ms-transform:scale(.45,.45);transform:scale(.45,.45)}.collapse-transition{transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out}.horizontal-collapse-transition{transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out}.el-list-enter-active,.el-list-leave-active{transition:all 1s}.el-list-enter,.el-list-leave-active{opacity:0;-ms-transform:translateY(-30px);transform:translateY(-30px)}.el-opacity-transition{transition:opacity .3s cubic-bezier(.55,0,.1,1)}.el-date-editor{position:relative;display:inline-block}.el-date-editor .el-picker-panel{position:absolute;min-width:180px;box-sizing:border-box;box-shadow:0 2px 6px #ccc;background:#fff;z-index:10;top:41px}.el-date-editor.el-input{width:193px}.el-date-editor--daterange.el-input{width:220px}.el-date-editor--datetimerange.el-input{width:350px}.el-time-spinner.has-seconds .el-time-spinner__wrapper{width:33%}.el-time-spinner.has-seconds .el-time-spinner__wrapper:nth-child(2){margin-left:1%}.el-time-spinner__wrapper{max-height:190px;overflow:auto;display:inline-block;width:50%;vertical-align:top;position:relative}.el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default){padding-bottom:15px}.el-time-spinner__list{padding:0;margin:0;list-style:none;text-align:center}.el-time-spinner__list::after,.el-time-spinner__list::before{content:\\'\\';display:block;width:100%;height:80px}.el-time-spinner__item{height:32px;line-height:32px;font-size:12px}.el-time-spinner__item:hover:not(.disabled):not(.active){background:#e4e8f1;cursor:pointer}.el-time-spinner__item.active:not(.disabled){color:#fff}.el-time-spinner__item.disabled{color:#d1dbe5;cursor:not-allowed}.el-time-panel{margin:5px 0;border:1px solid #d1dbe5;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);border-radius:2px;position:absolute;width:180px;left:0;z-index:1000;-webkit-user-select:none;-ms-user-select:none;user-select:none}.el-popover,.el-tabs--border-card{box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.el-slider__button,.el-slider__button-wrapper{-webkit-user-select:none;-moz-user-select:none}.el-time-panel__content{font-size:0;position:relative;overflow:hidden}.el-time-panel__content::after,.el-time-panel__content::before{content:\":\";top:50%;color:#fff;position:absolute;font-size:14px;margin-top:-15px;line-height:16px;background-color:#20a0ff;height:32px;z-index:-1;left:0;right:0;box-sizing:border-box;padding-top:6px;text-align:left}.el-time-panel__content::after{left:50%;margin-left:-2px}.el-time-panel__content::before{padding-left:50%;margin-right:-2px}.el-time-panel__content.has-seconds::after{left:66.66667%}.el-time-panel__content.has-seconds::before{padding-left:33.33333%}.el-time-panel__footer{border-top:1px solid #e4e4e4;padding:4px;height:36px;line-height:25px;text-align:right;box-sizing:border-box}.el-time-panel__btn{border:none;line-height:28px;padding:0 5px;margin:0 5px;cursor:pointer;background-color:transparent;outline:0;font-size:12px;color:#8391a5}.el-time-panel__btn.confirm{font-weight:800;color:#20a0ff}.el-popover{position:absolute;background:#fff;min-width:150px;border-radius:2px;border:1px solid #d1dbe5;padding:10px;z-index:2000;font-size:12px}.el-popover .popper__arrow,.el-popover .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-popover .popper__arrow{border-width:6px}.el-popover .popper__arrow::after{content:\" \";border-width:6px}.el-popover[x-placement^=top]{margin-bottom:12px}.el-popover[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#d1dbe5;border-bottom-width:0}.el-popover[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.el-popover[x-placement^=bottom]{margin-top:12px}.el-popover[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#d1dbe5}.el-popover[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.el-popover[x-placement^=right]{margin-left:12px}.el-popover[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#d1dbe5;border-left-width:0}.el-popover[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.el-popover[x-placement^=left]{margin-right:12px}.el-popover[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#d1dbe5}.el-popover[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.el-popover__title{color:#1f2d3d;font-size:13px;line-height:1;margin-bottom:9px}.v-modal-enter{animation:v-modal-in .2s ease}.v-modal-leave{animation:v-modal-out .2s ease forwards}@keyframes v-modal-in{0%{opacity:0}}@keyframes v-modal-out{100%{opacity:0}}.v-modal{position:fixed;left:0;top:0;width:100%;height:100%;opacity:.5;background:#000}.el-message-box{text-align:left;display:inline-block;vertical-align:middle;background-color:#fff;width:420px;border-radius:3px;font-size:16px;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden}.el-message-box__wrapper{position:fixed;top:0;bottom:0;left:0;right:0;text-align:center}.el-message-box__wrapper::after{content:\"\";display:inline-block;height:100%;width:0;vertical-align:middle}.el-message-box__header{position:relative;padding:20px 20px 0}.el-message-box__headerbtn{position:absolute;top:19px;right:20px;background:0 0;border:none;outline:0;padding:0;cursor:pointer}.el-message-box__headerbtn .el-message-box__close{color:#999}.el-message-box__headerbtn:focus .el-message-box__close,.el-message-box__headerbtn:hover .el-message-box__close{color:#20a0ff}.el-message-box__content{padding:30px 20px;color:#48576a;font-size:14px;position:relative}.el-message-box__input{padding-top:15px}.el-message-box__input input.invalid,.el-message-box__input input.invalid:focus{border-color:#ff4949}.el-message-box__errormsg{color:#ff4949;font-size:12px;min-height:18px;margin-top:2px}.el-message-box__title{padding-left:0;margin-bottom:0;font-size:16px;font-weight:700;height:18px;color:#333}.el-message-box__message{margin:0}.el-message-box__message p{margin:0;line-height:1.4}.el-message-box__btns{padding:10px 20px 15px;text-align:right}.el-message-box__btns button:nth-child(2){margin-left:10px}.el-message-box__btns-reverse{-ms-flex-direction:row-reverse;flex-direction:row-reverse}.el-message-box__status{position:absolute;top:50%;-ms-transform:translateY(-50%);transform:translateY(-50%);font-size:36px!important}.el-message-box__status.el-icon-circle-check{color:#13ce66}.el-message-box__status.el-icon-information{color:#50bfff}.el-message-box__status.el-icon-warning{color:#f7ba2a}.el-message-box__status.el-icon-circle-cross{color:#ff4949}.msgbox-fade-enter-active{animation:msgbox-fade-in .3s}.msgbox-fade-leave-active{animation:msgbox-fade-out .3s}@keyframes msgbox-fade-in{0%{transform:translate3d(0,-20px,0);opacity:0}100%{transform:translate3d(0,0,0);opacity:1}}@keyframes msgbox-fade-out{0%{transform:translate3d(0,0,0);opacity:1}100%{transform:translate3d(0,-20px,0);opacity:0}}.el-breadcrumb{font-size:13px;line-height:1}.el-breadcrumb__separator{margin:0 8px;color:#bfcbd9}.el-breadcrumb__item{float:left}.el-breadcrumb__item:last-child .el-breadcrumb__item__inner,.el-breadcrumb__item:last-child .el-breadcrumb__item__inner a,.el-breadcrumb__item:last-child .el-breadcrumb__item__inner a:hover,.el-breadcrumb__item:last-child .el-breadcrumb__item__inner:hover{color:#97a8be;cursor:text}.el-breadcrumb__item:last-child .el-breadcrumb__separator{display:none}.el-breadcrumb__item__inner,.el-breadcrumb__item__inner a{transition:color .15s linear;color:#48576a}.el-breadcrumb__item__inner a:hover,.el-breadcrumb__item__inner:hover{color:#20a0ff;cursor:pointer}.el-form--label-left .el-form-item__label{text-align:left}.el-form--label-top .el-form-item__label{float:none;display:inline-block;text-align:left;padding:0 0 10px}.el-form--inline .el-form-item{display:inline-block;margin-right:10px;vertical-align:top}.el-form--inline .el-form-item__label{float:none;display:inline-block}.el-form--inline .el-form-item__content{display:inline-block;vertical-align:top}.el-form--inline.el-form--label-top .el-form-item__content{display:block}.el-form-item{margin-bottom:22px}.el-form-item .el-form-item{margin-bottom:0}.el-form-item.is-error .el-input-group__append .el-input__inner,.el-form-item.is-error .el-input-group__prepend .el-input__inner,.el-form-item.is-error .el-input__inner{border-color:transparent}.el-form-item.is-error .el-input__inner,.el-form-item.is-error .el-textarea__inner{border-color:#ff4949}.el-form-item.is-required .el-form-item__label:before{content:\\'*\\';color:#ff4949;margin-right:4px}.el-form-item__label{text-align:right;vertical-align:middle;float:left;font-size:14px;color:#48576a;line-height:1;padding:11px 12px 11px 0;box-sizing:border-box}.el-form-item__content{line-height:36px;position:relative;font-size:14px}.el-form-item__error{color:#ff4949;font-size:12px;line-height:1;padding-top:4px;position:absolute;top:100%;left:0}.el-tabs__header{border-bottom:1px solid #d1dbe5;padding:0;position:relative;margin:0 0 15px}.el-tabs__active-bar{position:absolute;bottom:0;left:0;height:3px;background-color:#20a0ff;z-index:1;transition:transform .3s cubic-bezier(.645,.045,.355,1);list-style:none}.el-tabs__new-tab{float:right;border:1px solid #d3dce6;height:18px;width:18px;line-height:18px;margin:12px 0 9px 10px;border-radius:3px;text-align:center;font-size:12px;color:#d3dce6;cursor:pointer;transition:all .15s}.el-tabs__new-tab .el-icon-plus{-ms-transform:scale(.8,.8);transform:scale(.8,.8)}.el-tabs__new-tab:hover{color:#20a0ff}.el-tabs__nav-wrap{overflow:hidden;margin-bottom:-1px;position:relative}.el-tabs__nav-wrap.is-scrollable{padding:0 15px}.el-tabs__nav-scroll{overflow:hidden}.el-tabs__nav-next,.el-tabs__nav-prev{position:absolute;cursor:pointer;line-height:44px;font-size:12px;color:#8391a5}.el-tabs__nav-next{right:0}.el-tabs__nav-prev{left:0}.el-tabs__nav{position:relative;transition:transform .3s;float:left}.el-tabs__item{padding:0 16px;height:42px;box-sizing:border-box;line-height:42px;display:inline-block;list-style:none;font-size:14px;color:#8391a5;position:relative}.el-tabs__item .el-icon-close{border-radius:50%;text-align:center;transition:all .3s cubic-bezier(.645,.045,.355,1);margin-left:5px}.el-tabs__item .el-icon-close:before{-ms-transform:scale(.7,.7);transform:scale(.7,.7);display:inline-block}.el-tabs__item .el-icon-close:hover{background-color:#97a8be;color:#fff}.el-tabs__item:hover{color:#1f2d3d;cursor:pointer}.el-tabs__item.is-disabled{color:#bbb;cursor:default}.el-tabs__item.is-active{color:#20a0ff}.el-tabs__content{overflow:hidden;position:relative}.el-tabs--card>.el-tabs__header .el-tabs__active-bar{display:none}.el-tag,.slideInLeft-transition,.slideInRight-transition{display:inline-block}.el-tabs--card>.el-tabs__header .el-tabs__item .el-icon-close{position:relative;font-size:12px;width:0;height:14px;vertical-align:middle;line-height:15px;overflow:hidden;top:-1px;right:-2px;-ms-transform-origin:100% 50%;transform-origin:100% 50%}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable .el-icon-close,.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover .el-icon-close{width:14px}.el-tabs--card>.el-tabs__header .el-tabs__item{border:1px solid transparent;transition:all .3s cubic-bezier(.645,.045,.355,1)}.el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover{padding-right:9px;padding-left:9px}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border:1px solid #d1dbe5;border-bottom-color:#fff;border-radius:4px 4px 0 0}.el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable{padding-right:16px;padding-left:16px}.el-tabs--border-card{background:#fff;border:1px solid #d1dbe5}.el-tabs--border-card>.el-tabs__content{padding:15px}.el-tabs--border-card>.el-tabs__header{background-color:#eef1f6;margin:0}.el-tabs--border-card>.el-tabs__header .el-tabs__item{transition:all .3s cubic-bezier(.645,.045,.355,1);border:1px solid transparent;border-top:0;margin-right:-1px;margin-left:-1px}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active{background-color:#fff;border-right-color:#d1dbe5;border-left-color:#d1dbe5}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active:first-child{border-left-color:#d1dbe5}.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active:last-child{border-right-color:#d1dbe5}.slideInRight-enter{animation:slideInRight-enter .3s}.slideInRight-leave{position:absolute;left:0;right:0;animation:slideInRight-leave .3s}.slideInLeft-enter{animation:slideInLeft-enter .3s}.slideInLeft-leave{position:absolute;left:0;right:0;animation:slideInLeft-leave .3s}@keyframes slideInRight-enter{0%{opacity:0;transform-origin:0 0;transform:translateX(100%)}to{opacity:1;transform-origin:0 0;transform:translateX(0)}}@keyframes slideInRight-leave{0%{transform-origin:0 0;transform:translateX(0);opacity:1}100%{transform-origin:0 0;transform:translateX(100%);opacity:0}}@keyframes slideInLeft-enter{0%{opacity:0;transform-origin:0 0;transform:translateX(-100%)}to{opacity:1;transform-origin:0 0;transform:translateX(0)}}@keyframes slideInLeft-leave{0%{transform-origin:0 0;transform:translateX(0);opacity:1}100%{transform-origin:0 0;transform:translateX(-100%);opacity:0}}.el-tag{background-color:#8391a5;padding:0 5px;height:24px;line-height:22px;font-size:12px;color:#fff;border-radius:4px;box-sizing:border-box;border:1px solid transparent}.el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;-ms-transform:scale(.75,.75);transform:scale(.75,.75);height:18px;width:18px;line-height:18px;vertical-align:middle;top:-1px;right:-2px}.el-tag .el-icon-close:hover{background-color:#fff;color:#8391a5}.el-tag--gray{background-color:#e4e8f1;border-color:#e4e8f1;color:#48576a}.el-tag--gray .el-tag__close:hover{background-color:#48576a;color:#fff}.el-tag--gray.is-hit{border-color:#48576a}.el-tag--primary{background-color:rgba(32,160,255,.1);border-color:rgba(32,160,255,.2);color:#20a0ff}.el-tag--primary .el-tag__close:hover{background-color:#20a0ff;color:#fff}.el-tag--primary.is-hit{border-color:#20a0ff}.el-tag--success{background-color:rgba(18,206,102,.1);border-color:rgba(18,206,102,.2);color:#13ce66}.el-tag--success .el-tag__close:hover{background-color:#13ce66;color:#fff}.el-tag--success.is-hit{border-color:#13ce66}.el-tag--warning{background-color:rgba(247,186,41,.1);border-color:rgba(247,186,41,.2);color:#f7ba2a}.el-tag--warning .el-tag__close:hover{background-color:#f7ba2a;color:#fff}.el-tag--warning.is-hit{border-color:#f7ba2a}.el-tag--danger{background-color:rgba(255,73,73,.1);border-color:rgba(255,73,73,.2);color:#ff4949}.el-tag--danger .el-tag__close:hover{background-color:#ff4949;color:#fff}.el-tag--danger.is-hit{border-color:#ff4949}.el-tree{cursor:default;background:#fff;border:1px solid #d1dbe5}.el-tree__empty-block{position:relative;min-height:60px;text-align:center;width:100%;height:100%}.el-tree__empty-text{position:absolute;left:50%;top:50%;-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#5e7382}.el-tree-node>.el-tree-node__children{overflow:hidden;background-color:transparent}.el-tree-node.is-expanded>.el-tree-node__children{display:block}.el-tree-node__expand-icon,.el-tree-node__label,.el-tree-node__loading-icon{display:inline-block;vertical-align:middle}.el-tree-node__content{line-height:36px;height:36px;cursor:pointer}.el-tree-node__content>.el-checkbox,.el-tree-node__content>.el-tree-node__expand-icon{margin-right:8px}.el-tree-node__content>.el-checkbox{vertical-align:middle}.el-tree-node__content:hover{background:#e4e8f1}.el-tree-node__expand-icon{cursor:pointer;width:0;height:0;margin-left:10px;border:6px solid transparent;border-right-width:0;border-left-color:#97a8be;border-left-width:7px;-ms-transform:rotate(0);transform:rotate(0);transition:transform .3s ease-in-out}.el-tree-node__expand-icon:hover{border-left-color:#999}.el-tree-node__expand-icon.expanded{-ms-transform:rotate(90deg);transform:rotate(90deg)}.el-tree-node__expand-icon.is-leaf{border-color:transparent;cursor:default}.el-tree-node__label{font-size:14px}.el-tree-node__loading-icon{margin-right:4px;font-size:14px;color:#97a8be}.el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content{background-color:#edf7ff}.el-alert{width:100%;padding:8px 16px;margin:0;box-sizing:border-box;border-radius:4px;position:relative;background-color:#fff;overflow:hidden;color:#fff;opacity:1;display:table;transition:opacity .2s}.el-alert .el-alert__description{color:#fff;font-size:12px;margin:5px 0 0}.el-alert--success{background-color:#13ce66}.el-alert--info{background-color:#50bfff}.el-alert--warning{background-color:#f7ba2a}.el-alert--error{background-color:#ff4949}.el-alert__content{display:table-cell;padding:0 8px}.el-alert__icon{font-size:16px;width:16px;display:table-cell;color:#fff;vertical-align:middle}.el-alert__icon.is-big{font-size:28px;width:28px}.el-alert__title{font-size:13px;line-height:18px}.el-alert__title.is-bold{font-weight:700}.el-alert__closebtn{font-size:12px;color:#fff;opacity:1;top:12px;right:15px;position:absolute;cursor:pointer}.el-alert-fade-enter,.el-alert-fade-leave-active,.el-loading-fade-enter,.el-loading-fade-leave-active,.el-notification-fade-leave-active{opacity:0}.el-alert__closebtn.is-customed{font-style:normal;font-size:13px;top:9px}.el-notification{width:330px;padding:20px;box-sizing:border-box;border-radius:2px;position:fixed;right:16px;background-color:#fff;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);transition:opacity .3s,transform .3s,right .3s,top .4s;overflow:hidden}.el-notification .el-icon-circle-check{color:#13ce66}.el-notification .el-icon-circle-cross{color:#ff4949}.el-notification .el-icon-information{color:#50bfff}.el-notification .el-icon-warning{color:#f7ba2a}.el-notification__group{margin-left:0}.el-notification__group.is-with-icon{margin-left:55px}.el-notification__title{font-weight:400;font-size:16px;color:#1f2d3d;margin:0}.el-notification__content{font-size:14px;line-height:21px;margin:10px 0 0;color:#8391a5;text-align:justify}.el-notification__icon{width:40px;height:40px;font-size:40px;float:left;position:relative;top:3px}.el-notification__closeBtn{top:20px;right:20px;position:absolute;cursor:pointer;color:#bfcbd9;font-size:14px}.el-notification__closeBtn:hover{color:#97a8be}.el-notification-fade-enter{-ms-transform:translateX(100%);transform:translateX(100%);right:0}.el-input-number{display:inline-block;width:180px;position:relative;line-height:normal}.el-input-number .el-input{display:block}.el-input-number .el-input__inner{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding-right:82px}.el-input-number.is-without-controls .el-input__inner{padding-right:10px}.el-input-number.is-disabled .el-input-number__decrease,.el-input-number.is-disabled .el-input-number__increase{border-color:#d1dbe5;color:#d1dbe5}.el-input-number.is-disabled .el-input-number__decrease:hover,.el-input-number.is-disabled .el-input-number__increase:hover{color:#d1dbe5;cursor:not-allowed}.el-input-number__decrease,.el-input-number__increase{height:auto;border-left:1px solid #bfcbd9;width:36px;line-height:34px;top:1px;text-align:center;color:#97a8be;cursor:pointer;position:absolute;z-index:1}.el-input-number__decrease:hover,.el-input-number__increase:hover{color:#20a0ff}.el-input-number__decrease:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled),.el-input-number__increase:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled){border-color:#20a0ff}.el-input-number__decrease.is-disabled,.el-input-number__increase.is-disabled{color:#d1dbe5;cursor:not-allowed}.el-input-number__increase{right:0}.el-input-number__decrease{right:37px}.el-input-number--large{width:200px}.el-input-number--large .el-input-number__decrease,.el-input-number--large .el-input-number__increase{line-height:40px;width:42px;font-size:16px}.el-input-number--large .el-input-number__decrease{right:43px}.el-input-number--large .el-input__inner{padding-right:94px}.el-input-number--small{width:130px}.el-input-number--small .el-input-number__decrease,.el-input-number--small .el-input-number__increase{line-height:28px;width:30px;font-size:13px}.el-input-number--small .el-input-number__decrease{right:31px}.el-input-number--small .el-input__inner{padding-right:70px}.el-tooltip__popper{position:absolute;border-radius:4px;padding:10px;z-index:2000;font-size:12px;line-height:1.2}.el-tooltip__popper .popper__arrow,.el-tooltip__popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.el-tooltip__popper .popper__arrow{border-width:6px}.el-tooltip__popper .popper__arrow::after{content:\" \";border-width:5px}.el-progress-bar__inner:after,.el-row:after,.el-row:before,.el-slider:after,.el-slider:before,.el-slider__button-wrapper:after,.el-upload-cover:after{content:\"\"}.el-tooltip__popper[x-placement^=top]{margin-bottom:12px}.el-tooltip__popper[x-placement^=top] .popper__arrow{bottom:-6px;border-top-color:#1f2d3d;border-bottom-width:0}.el-tooltip__popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-5px;border-top-color:#1f2d3d;border-bottom-width:0}.el-tooltip__popper[x-placement^=bottom]{margin-top:12px}.el-tooltip__popper[x-placement^=bottom] .popper__arrow{top:-6px;border-top-width:0;border-bottom-color:#1f2d3d}.el-tooltip__popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-5px;border-top-width:0;border-bottom-color:#1f2d3d}.el-tooltip__popper[x-placement^=right]{margin-left:12px}.el-tooltip__popper[x-placement^=right] .popper__arrow{left:-6px;border-right-color:#1f2d3d;border-left-width:0}.el-tooltip__popper[x-placement^=right] .popper__arrow::after{bottom:-5px;left:1px;border-right-color:#1f2d3d;border-left-width:0}.el-tooltip__popper[x-placement^=left]{margin-right:12px}.el-tooltip__popper[x-placement^=left] .popper__arrow{right:-6px;border-right-width:0;border-left-color:#1f2d3d}.el-tooltip__popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-5px;margin-left:-5px;border-right-width:0;border-left-color:#1f2d3d}.el-tooltip__popper.is-light{background:#fff;border:1px solid #1f2d3d}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow{border-top-color:#1f2d3d}.el-tooltip__popper.is-light[x-placement^=top] .popper__arrow::after{border-top-color:#fff}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow{border-bottom-color:#1f2d3d}.el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow::after{border-bottom-color:#fff}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow{border-left-color:#1f2d3d}.el-tooltip__popper.is-light[x-placement^=left] .popper__arrow::after{border-left-color:#fff}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow{border-right-color:#1f2d3d}.el-tooltip__popper.is-light[x-placement^=right] .popper__arrow::after{border-right-color:#fff}.el-tooltip__popper.is-dark{background:#1f2d3d;color:#fff}.el-slider:after,.el-slider:before{display:table}.el-slider__button-wrapper .el-tooltip,.el-slider__button-wrapper:after{display:inline-block;vertical-align:middle}.el-slider:after{clear:both}.el-slider.is-vertical{position:relative}.el-slider.is-vertical .el-slider__runway{width:4px;height:100%;margin:0 16px}.el-slider.is-vertical .el-slider__bar{width:4px;height:auto;border-radius:0 0 3px 3px}.el-slider.is-vertical .el-slider__button-wrapper{top:auto;left:-16px;-ms-transform:translateY(50%);transform:translateY(50%)}.el-slider.is-vertical .el-slider__stop{-ms-transform:translateY(50%);transform:translateY(50%)}.el-slider.is-vertical.el-slider--with-input{padding-bottom:64px}.el-slider.is-vertical.el-slider--with-input .el-slider__input{overflow:visible;float:none;position:absolute;bottom:22px;width:36px;margin-top:15px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input__inner{text-align:center;padding-left:5px;padding-right:5px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{top:30px;margin-top:-1px;border:1px solid #bfcbd9;line-height:20px;box-sizing:border-box;transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease{width:18px;right:18px;border-bottom-left-radius:4px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{width:19px;border-bottom-right-radius:4px}.el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase~.el-input .el-input__inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__increase{border-color:#8391a5}.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__decrease,.el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__increase{border-color:#20a0ff}.el-slider__runway{width:100%;height:4px;margin:16px 0;background-color:#e4e8f1;border-radius:3px;position:relative;cursor:pointer;vertical-align:middle}.el-slider__runway.show-input{margin-right:160px;width:auto}.el-slider__runway.disabled{cursor:default}.el-slider__runway.disabled .el-slider__bar,.el-slider__runway.disabled .el-slider__button{background-color:#bfcbd9}.el-slider__runway.disabled .el-slider__button-wrapper.dragging,.el-slider__runway.disabled .el-slider__button-wrapper.hover,.el-slider__runway.disabled .el-slider__button-wrapper:hover{cursor:not-allowed}.el-slider__runway.disabled .el-slider__button.dragging,.el-slider__runway.disabled .el-slider__button.hover,.el-slider__runway.disabled .el-slider__button:hover{-ms-transform:scale(1);transform:scale(1);cursor:not-allowed}.el-slider__input{float:right;margin-top:3px}.el-slider__bar{height:4px;background-color:#20a0ff;border-top-left-radius:3px;border-bottom-left-radius:3px;position:absolute}.el-slider__button-wrapper{width:36px;height:36px;position:absolute;z-index:1001;top:-16px;-ms-transform:translateX(-50%);transform:translateX(-50%);background-color:transparent;text-align:center;-ms-user-select:none;user-select:none}.el-slider__button-wrapper:after{height:100%}.el-slider__button-wrapper.hover,.el-slider__button-wrapper:hover{cursor:-webkit-grab;cursor:grab}.el-slider__button-wrapper.dragging{cursor:-webkit-grabbing;cursor:grabbing}.el-slider__button{width:12px;height:12px;background-color:#20a0ff;border-radius:50%;transition:.2s;-ms-user-select:none;user-select:none}.el-slider__button.dragging,.el-slider__button.hover,.el-slider__button:hover{-ms-transform:scale(1.5);transform:scale(1.5);background-color:#1c8de0}.el-slider__button.hover,.el-slider__button:hover{cursor:-webkit-grab;cursor:grab}.el-slider__button.dragging{cursor:-webkit-grabbing;cursor:grabbing}.el-slider__stop{position:absolute;width:4px;height:4px;border-radius:100%;background-color:#bfcbd9;-ms-transform:translateX(-50%);transform:translateX(-50%)}.el-loading-mask{position:absolute;z-index:10000;background-color:rgba(255,255,255,.9);margin:0;top:0;right:0;bottom:0;left:0;transition:opacity .3s}.el-loading-mask.is-fullscreen{position:fixed}.el-loading-mask.is-fullscreen .el-loading-spinner{margin-top:-25px}.el-loading-mask.is-fullscreen .el-loading-spinner .circular{width:50px;height:50px}.el-loading-spinner{top:50%;margin-top:-21px;width:100%;text-align:center;position:absolute}.el-col-pull-0,.el-col-pull-1,.el-col-pull-10,.el-col-pull-11,.el-col-pull-13,.el-col-pull-14,.el-col-pull-15,.el-col-pull-16,.el-col-pull-17,.el-col-pull-18,.el-col-pull-19,.el-col-pull-2,.el-col-pull-20,.el-col-pull-21,.el-col-pull-22,.el-col-pull-23,.el-col-pull-24,.el-col-pull-3,.el-col-pull-4,.el-col-pull-5,.el-col-pull-6,.el-col-pull-7,.el-col-pull-8,.el-col-pull-9,.el-col-push-0,.el-col-push-1,.el-col-push-10,.el-col-push-11,.el-col-push-12,.el-col-push-13,.el-col-push-14,.el-col-push-15,.el-col-push-16,.el-col-push-17,.el-col-push-18,.el-col-push-19,.el-col-push-2,.el-col-push-20,.el-col-push-21,.el-col-push-22,.el-col-push-23,.el-col-push-24,.el-col-push-3,.el-col-push-4,.el-col-push-5,.el-col-push-6,.el-col-push-7,.el-col-push-8,.el-col-push-9,.el-row{position:relative}.el-loading-spinner .el-loading-text{color:#20a0ff;margin:3px 0;font-size:14px}.el-loading-spinner .circular{width:42px;height:42px;animation:loading-rotate 2s linear infinite}.el-loading-spinner .path{animation:loading-dash 1.5s ease-in-out infinite;stroke-dasharray:90,150;stroke-dashoffset:0;stroke-width:2;stroke:#20a0ff;stroke-linecap:round}@keyframes loading-rotate{100%{transform:rotate(360deg)}}@keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}100%{stroke-dasharray:90,150;stroke-dashoffset:-120px}}.el-row{box-sizing:border-box}.el-row:after,.el-row:before{display:table}.el-row:after{clear:both}.el-row--flex{display:-ms-flexbox;display:flex}.el-row--flex:after,.el-row--flex:before{display:none}.el-row--flex.is-align-bottom{-ms-flex-align:end;align-items:flex-end}.el-row--flex.is-align-middle{-ms-flex-align:center;align-items:center}.el-row--flex.is-justify-space-around{-ms-flex-pack:distribute;justify-content:space-around}.el-row--flex.is-justify-space-between{-ms-flex-pack:justify;justify-content:space-between}.el-row--flex.is-justify-end{-ms-flex-pack:end;justify-content:flex-end}.el-row--flex.is-justify-center{-ms-flex-pack:center;justify-content:center}.el-col-1,.el-col-10,.el-col-11,.el-col-12,.el-col-13,.el-col-14,.el-col-15,.el-col-16,.el-col-17,.el-col-18,.el-col-19,.el-col-2,.el-col-20,.el-col-21,.el-col-22,.el-col-23,.el-col-24,.el-col-3,.el-col-4,.el-col-5,.el-col-6,.el-col-7,.el-col-8,.el-col-9{float:left;box-sizing:border-box}.el-col-0{width:0}.el-col-offset-0{margin-left:0}.el-col-pull-0{right:0}.el-col-push-0{left:0}.el-col-1{width:4.16667%}.el-col-offset-1{margin-left:4.16667%}.el-col-pull-1{right:4.16667%}.el-col-push-1{left:4.16667%}.el-col-2{width:8.33333%}.el-col-offset-2{margin-left:8.33333%}.el-col-pull-2{right:8.33333%}.el-col-push-2{left:8.33333%}.el-col-3{width:12.5%}.el-col-offset-3{margin-left:12.5%}.el-col-pull-3{right:12.5%}.el-col-push-3{left:12.5%}.el-col-4{width:16.66667%}.el-col-offset-4{margin-left:16.66667%}.el-col-pull-4{right:16.66667%}.el-col-push-4{left:16.66667%}.el-col-5{width:20.83333%}.el-col-offset-5{margin-left:20.83333%}.el-col-pull-5{right:20.83333%}.el-col-push-5{left:20.83333%}.el-col-6{width:25%}.el-col-offset-6{margin-left:25%}.el-col-pull-6{right:25%}.el-col-push-6{left:25%}.el-col-7{width:29.16667%}.el-col-offset-7{margin-left:29.16667%}.el-col-pull-7{right:29.16667%}.el-col-push-7{left:29.16667%}.el-col-8{width:33.33333%}.el-col-offset-8{margin-left:33.33333%}.el-col-pull-8{right:33.33333%}.el-col-push-8{left:33.33333%}.el-col-9{width:37.5%}.el-col-offset-9{margin-left:37.5%}.el-col-pull-9{right:37.5%}.el-col-push-9{left:37.5%}.el-col-10{width:41.66667%}.el-col-offset-10{margin-left:41.66667%}.el-col-pull-10{right:41.66667%}.el-col-push-10{left:41.66667%}.el-col-11{width:45.83333%}.el-col-offset-11{margin-left:45.83333%}.el-col-pull-11{right:45.83333%}.el-col-push-11{left:45.83333%}.el-col-12{width:50%}.el-col-offset-12{margin-left:50%}.el-col-pull-12{position:relative;right:50%}.el-col-push-12{left:50%}.el-col-13{width:54.16667%}.el-col-offset-13{margin-left:54.16667%}.el-col-pull-13{right:54.16667%}.el-col-push-13{left:54.16667%}.el-col-14{width:58.33333%}.el-col-offset-14{margin-left:58.33333%}.el-col-pull-14{right:58.33333%}.el-col-push-14{left:58.33333%}.el-col-15{width:62.5%}.el-col-offset-15{margin-left:62.5%}.el-col-pull-15{right:62.5%}.el-col-push-15{left:62.5%}.el-col-16{width:66.66667%}.el-col-offset-16{margin-left:66.66667%}.el-col-pull-16{right:66.66667%}.el-col-push-16{left:66.66667%}.el-col-17{width:70.83333%}.el-col-offset-17{margin-left:70.83333%}.el-col-pull-17{right:70.83333%}.el-col-push-17{left:70.83333%}.el-col-18{width:75%}.el-col-offset-18{margin-left:75%}.el-col-pull-18{right:75%}.el-col-push-18{left:75%}.el-col-19{width:79.16667%}.el-col-offset-19{margin-left:79.16667%}.el-col-pull-19{right:79.16667%}.el-col-push-19{left:79.16667%}.el-col-20{width:83.33333%}.el-col-offset-20{margin-left:83.33333%}.el-col-pull-20{right:83.33333%}.el-col-push-20{left:83.33333%}.el-col-21{width:87.5%}.el-col-offset-21{margin-left:87.5%}.el-col-pull-21{right:87.5%}.el-col-push-21{left:87.5%}.el-col-22{width:91.66667%}.el-col-offset-22{margin-left:91.66667%}.el-col-pull-22{right:91.66667%}.el-col-push-22{left:91.66667%}.el-col-23{width:95.83333%}.el-col-offset-23{margin-left:95.83333%}.el-col-pull-23{right:95.83333%}.el-col-push-23{left:95.83333%}.el-col-24{width:100%}.el-col-offset-24{margin-left:100%}.el-col-pull-24{right:100%}.el-col-push-24{left:100%}@media (max-width:768px){.el-col-xs-0{width:0}.el-col-xs-offset-0{margin-left:0}.el-col-xs-pull-0{position:relative;right:0}.el-col-xs-push-0{position:relative;left:0}.el-col-xs-1{width:4.16667%}.el-col-xs-offset-1{margin-left:4.16667%}.el-col-xs-pull-1{position:relative;right:4.16667%}.el-col-xs-push-1{position:relative;left:4.16667%}.el-col-xs-2{width:8.33333%}.el-col-xs-offset-2{margin-left:8.33333%}.el-col-xs-pull-2{position:relative;right:8.33333%}.el-col-xs-push-2{position:relative;left:8.33333%}.el-col-xs-3{width:12.5%}.el-col-xs-offset-3{margin-left:12.5%}.el-col-xs-pull-3{position:relative;right:12.5%}.el-col-xs-push-3{position:relative;left:12.5%}.el-col-xs-4{width:16.66667%}.el-col-xs-offset-4{margin-left:16.66667%}.el-col-xs-pull-4{position:relative;right:16.66667%}.el-col-xs-push-4{position:relative;left:16.66667%}.el-col-xs-5{width:20.83333%}.el-col-xs-offset-5{margin-left:20.83333%}.el-col-xs-pull-5{position:relative;right:20.83333%}.el-col-xs-push-5{position:relative;left:20.83333%}.el-col-xs-6{width:25%}.el-col-xs-offset-6{margin-left:25%}.el-col-xs-pull-6{position:relative;right:25%}.el-col-xs-push-6{position:relative;left:25%}.el-col-xs-7{width:29.16667%}.el-col-xs-offset-7{margin-left:29.16667%}.el-col-xs-pull-7{position:relative;right:29.16667%}.el-col-xs-push-7{position:relative;left:29.16667%}.el-col-xs-8{width:33.33333%}.el-col-xs-offset-8{margin-left:33.33333%}.el-col-xs-pull-8{position:relative;right:33.33333%}.el-col-xs-push-8{position:relative;left:33.33333%}.el-col-xs-9{width:37.5%}.el-col-xs-offset-9{margin-left:37.5%}.el-col-xs-pull-9{position:relative;right:37.5%}.el-col-xs-push-9{position:relative;left:37.5%}.el-col-xs-10{width:41.66667%}.el-col-xs-offset-10{margin-left:41.66667%}.el-col-xs-pull-10{position:relative;right:41.66667%}.el-col-xs-push-10{position:relative;left:41.66667%}.el-col-xs-11{width:45.83333%}.el-col-xs-offset-11{margin-left:45.83333%}.el-col-xs-pull-11{position:relative;right:45.83333%}.el-col-xs-push-11{position:relative;left:45.83333%}.el-col-xs-12{width:50%}.el-col-xs-offset-12{margin-left:50%}.el-col-xs-pull-12{position:relative;right:50%}.el-col-xs-push-12{position:relative;left:50%}.el-col-xs-13{width:54.16667%}.el-col-xs-offset-13{margin-left:54.16667%}.el-col-xs-pull-13{position:relative;right:54.16667%}.el-col-xs-push-13{position:relative;left:54.16667%}.el-col-xs-14{width:58.33333%}.el-col-xs-offset-14{margin-left:58.33333%}.el-col-xs-pull-14{position:relative;right:58.33333%}.el-col-xs-push-14{position:relative;left:58.33333%}.el-col-xs-15{width:62.5%}.el-col-xs-offset-15{margin-left:62.5%}.el-col-xs-pull-15{position:relative;right:62.5%}.el-col-xs-push-15{position:relative;left:62.5%}.el-col-xs-16{width:66.66667%}.el-col-xs-offset-16{margin-left:66.66667%}.el-col-xs-pull-16{position:relative;right:66.66667%}.el-col-xs-push-16{position:relative;left:66.66667%}.el-col-xs-17{width:70.83333%}.el-col-xs-offset-17{margin-left:70.83333%}.el-col-xs-pull-17{position:relative;right:70.83333%}.el-col-xs-push-17{position:relative;left:70.83333%}.el-col-xs-18{width:75%}.el-col-xs-offset-18{margin-left:75%}.el-col-xs-pull-18{position:relative;right:75%}.el-col-xs-push-18{position:relative;left:75%}.el-col-xs-19{width:79.16667%}.el-col-xs-offset-19{margin-left:79.16667%}.el-col-xs-pull-19{position:relative;right:79.16667%}.el-col-xs-push-19{position:relative;left:79.16667%}.el-col-xs-20{width:83.33333%}.el-col-xs-offset-20{margin-left:83.33333%}.el-col-xs-pull-20{position:relative;right:83.33333%}.el-col-xs-push-20{position:relative;left:83.33333%}.el-col-xs-21{width:87.5%}.el-col-xs-offset-21{margin-left:87.5%}.el-col-xs-pull-21{position:relative;right:87.5%}.el-col-xs-push-21{position:relative;left:87.5%}.el-col-xs-22{width:91.66667%}.el-col-xs-offset-22{margin-left:91.66667%}.el-col-xs-pull-22{position:relative;right:91.66667%}.el-col-xs-push-22{position:relative;left:91.66667%}.el-col-xs-23{width:95.83333%}.el-col-xs-offset-23{margin-left:95.83333%}.el-col-xs-pull-23{position:relative;right:95.83333%}.el-col-xs-push-23{position:relative;left:95.83333%}.el-col-xs-24{width:100%}.el-col-xs-offset-24{margin-left:100%}.el-col-xs-pull-24{position:relative;right:100%}.el-col-xs-push-24{position:relative;left:100%}}@media (min-width:768px){.el-col-sm-0{width:0}.el-col-sm-offset-0{margin-left:0}.el-col-sm-pull-0{position:relative;right:0}.el-col-sm-push-0{position:relative;left:0}.el-col-sm-1{width:4.16667%}.el-col-sm-offset-1{margin-left:4.16667%}.el-col-sm-pull-1{position:relative;right:4.16667%}.el-col-sm-push-1{position:relative;left:4.16667%}.el-col-sm-2{width:8.33333%}.el-col-sm-offset-2{margin-left:8.33333%}.el-col-sm-pull-2{position:relative;right:8.33333%}.el-col-sm-push-2{position:relative;left:8.33333%}.el-col-sm-3{width:12.5%}.el-col-sm-offset-3{margin-left:12.5%}.el-col-sm-pull-3{position:relative;right:12.5%}.el-col-sm-push-3{position:relative;left:12.5%}.el-col-sm-4{width:16.66667%}.el-col-sm-offset-4{margin-left:16.66667%}.el-col-sm-pull-4{position:relative;right:16.66667%}.el-col-sm-push-4{position:relative;left:16.66667%}.el-col-sm-5{width:20.83333%}.el-col-sm-offset-5{margin-left:20.83333%}.el-col-sm-pull-5{position:relative;right:20.83333%}.el-col-sm-push-5{position:relative;left:20.83333%}.el-col-sm-6{width:25%}.el-col-sm-offset-6{margin-left:25%}.el-col-sm-pull-6{position:relative;right:25%}.el-col-sm-push-6{position:relative;left:25%}.el-col-sm-7{width:29.16667%}.el-col-sm-offset-7{margin-left:29.16667%}.el-col-sm-pull-7{position:relative;right:29.16667%}.el-col-sm-push-7{position:relative;left:29.16667%}.el-col-sm-8{width:33.33333%}.el-col-sm-offset-8{margin-left:33.33333%}.el-col-sm-pull-8{position:relative;right:33.33333%}.el-col-sm-push-8{position:relative;left:33.33333%}.el-col-sm-9{width:37.5%}.el-col-sm-offset-9{margin-left:37.5%}.el-col-sm-pull-9{position:relative;right:37.5%}.el-col-sm-push-9{position:relative;left:37.5%}.el-col-sm-10{width:41.66667%}.el-col-sm-offset-10{margin-left:41.66667%}.el-col-sm-pull-10{position:relative;right:41.66667%}.el-col-sm-push-10{position:relative;left:41.66667%}.el-col-sm-11{width:45.83333%}.el-col-sm-offset-11{margin-left:45.83333%}.el-col-sm-pull-11{position:relative;right:45.83333%}.el-col-sm-push-11{position:relative;left:45.83333%}.el-col-sm-12{width:50%}.el-col-sm-offset-12{margin-left:50%}.el-col-sm-pull-12{position:relative;right:50%}.el-col-sm-push-12{position:relative;left:50%}.el-col-sm-13{width:54.16667%}.el-col-sm-offset-13{margin-left:54.16667%}.el-col-sm-pull-13{position:relative;right:54.16667%}.el-col-sm-push-13{position:relative;left:54.16667%}.el-col-sm-14{width:58.33333%}.el-col-sm-offset-14{margin-left:58.33333%}.el-col-sm-pull-14{position:relative;right:58.33333%}.el-col-sm-push-14{position:relative;left:58.33333%}.el-col-sm-15{width:62.5%}.el-col-sm-offset-15{margin-left:62.5%}.el-col-sm-pull-15{position:relative;right:62.5%}.el-col-sm-push-15{position:relative;left:62.5%}.el-col-sm-16{width:66.66667%}.el-col-sm-offset-16{margin-left:66.66667%}.el-col-sm-pull-16{position:relative;right:66.66667%}.el-col-sm-push-16{position:relative;left:66.66667%}.el-col-sm-17{width:70.83333%}.el-col-sm-offset-17{margin-left:70.83333%}.el-col-sm-pull-17{position:relative;right:70.83333%}.el-col-sm-push-17{position:relative;left:70.83333%}.el-col-sm-18{width:75%}.el-col-sm-offset-18{margin-left:75%}.el-col-sm-pull-18{position:relative;right:75%}.el-col-sm-push-18{position:relative;left:75%}.el-col-sm-19{width:79.16667%}.el-col-sm-offset-19{margin-left:79.16667%}.el-col-sm-pull-19{position:relative;right:79.16667%}.el-col-sm-push-19{position:relative;left:79.16667%}.el-col-sm-20{width:83.33333%}.el-col-sm-offset-20{margin-left:83.33333%}.el-col-sm-pull-20{position:relative;right:83.33333%}.el-col-sm-push-20{position:relative;left:83.33333%}.el-col-sm-21{width:87.5%}.el-col-sm-offset-21{margin-left:87.5%}.el-col-sm-pull-21{position:relative;right:87.5%}.el-col-sm-push-21{position:relative;left:87.5%}.el-col-sm-22{width:91.66667%}.el-col-sm-offset-22{margin-left:91.66667%}.el-col-sm-pull-22{position:relative;right:91.66667%}.el-col-sm-push-22{position:relative;left:91.66667%}.el-col-sm-23{width:95.83333%}.el-col-sm-offset-23{margin-left:95.83333%}.el-col-sm-pull-23{position:relative;right:95.83333%}.el-col-sm-push-23{position:relative;left:95.83333%}.el-col-sm-24{width:100%}.el-col-sm-offset-24{margin-left:100%}.el-col-sm-pull-24{position:relative;right:100%}.el-col-sm-push-24{position:relative;left:100%}}@media (min-width:992px){.el-col-md-0{width:0}.el-col-md-offset-0{margin-left:0}.el-col-md-pull-0{position:relative;right:0}.el-col-md-push-0{position:relative;left:0}.el-col-md-1{width:4.16667%}.el-col-md-offset-1{margin-left:4.16667%}.el-col-md-pull-1{position:relative;right:4.16667%}.el-col-md-push-1{position:relative;left:4.16667%}.el-col-md-2{width:8.33333%}.el-col-md-offset-2{margin-left:8.33333%}.el-col-md-pull-2{position:relative;right:8.33333%}.el-col-md-push-2{position:relative;left:8.33333%}.el-col-md-3{width:12.5%}.el-col-md-offset-3{margin-left:12.5%}.el-col-md-pull-3{position:relative;right:12.5%}.el-col-md-push-3{position:relative;left:12.5%}.el-col-md-4{width:16.66667%}.el-col-md-offset-4{margin-left:16.66667%}.el-col-md-pull-4{position:relative;right:16.66667%}.el-col-md-push-4{position:relative;left:16.66667%}.el-col-md-5{width:20.83333%}.el-col-md-offset-5{margin-left:20.83333%}.el-col-md-pull-5{position:relative;right:20.83333%}.el-col-md-push-5{position:relative;left:20.83333%}.el-col-md-6{width:25%}.el-col-md-offset-6{margin-left:25%}.el-col-md-pull-6{position:relative;right:25%}.el-col-md-push-6{position:relative;left:25%}.el-col-md-7{width:29.16667%}.el-col-md-offset-7{margin-left:29.16667%}.el-col-md-pull-7{position:relative;right:29.16667%}.el-col-md-push-7{position:relative;left:29.16667%}.el-col-md-8{width:33.33333%}.el-col-md-offset-8{margin-left:33.33333%}.el-col-md-pull-8{position:relative;right:33.33333%}.el-col-md-push-8{position:relative;left:33.33333%}.el-col-md-9{width:37.5%}.el-col-md-offset-9{margin-left:37.5%}.el-col-md-pull-9{position:relative;right:37.5%}.el-col-md-push-9{position:relative;left:37.5%}.el-col-md-10{width:41.66667%}.el-col-md-offset-10{margin-left:41.66667%}.el-col-md-pull-10{position:relative;right:41.66667%}.el-col-md-push-10{position:relative;left:41.66667%}.el-col-md-11{width:45.83333%}.el-col-md-offset-11{margin-left:45.83333%}.el-col-md-pull-11{position:relative;right:45.83333%}.el-col-md-push-11{position:relative;left:45.83333%}.el-col-md-12{width:50%}.el-col-md-offset-12{margin-left:50%}.el-col-md-pull-12{position:relative;right:50%}.el-col-md-push-12{position:relative;left:50%}.el-col-md-13{width:54.16667%}.el-col-md-offset-13{margin-left:54.16667%}.el-col-md-pull-13{position:relative;right:54.16667%}.el-col-md-push-13{position:relative;left:54.16667%}.el-col-md-14{width:58.33333%}.el-col-md-offset-14{margin-left:58.33333%}.el-col-md-pull-14{position:relative;right:58.33333%}.el-col-md-push-14{position:relative;left:58.33333%}.el-col-md-15{width:62.5%}.el-col-md-offset-15{margin-left:62.5%}.el-col-md-pull-15{position:relative;right:62.5%}.el-col-md-push-15{position:relative;left:62.5%}.el-col-md-16{width:66.66667%}.el-col-md-offset-16{margin-left:66.66667%}.el-col-md-pull-16{position:relative;right:66.66667%}.el-col-md-push-16{position:relative;left:66.66667%}.el-col-md-17{width:70.83333%}.el-col-md-offset-17{margin-left:70.83333%}.el-col-md-pull-17{position:relative;right:70.83333%}.el-col-md-push-17{position:relative;left:70.83333%}.el-col-md-18{width:75%}.el-col-md-offset-18{margin-left:75%}.el-col-md-pull-18{position:relative;right:75%}.el-col-md-push-18{position:relative;left:75%}.el-col-md-19{width:79.16667%}.el-col-md-offset-19{margin-left:79.16667%}.el-col-md-pull-19{position:relative;right:79.16667%}.el-col-md-push-19{position:relative;left:79.16667%}.el-col-md-20{width:83.33333%}.el-col-md-offset-20{margin-left:83.33333%}.el-col-md-pull-20{position:relative;right:83.33333%}.el-col-md-push-20{position:relative;left:83.33333%}.el-col-md-21{width:87.5%}.el-col-md-offset-21{margin-left:87.5%}.el-col-md-pull-21{position:relative;right:87.5%}.el-col-md-push-21{position:relative;left:87.5%}.el-col-md-22{width:91.66667%}.el-col-md-offset-22{margin-left:91.66667%}.el-col-md-pull-22{position:relative;right:91.66667%}.el-col-md-push-22{position:relative;left:91.66667%}.el-col-md-23{width:95.83333%}.el-col-md-offset-23{margin-left:95.83333%}.el-col-md-pull-23{position:relative;right:95.83333%}.el-col-md-push-23{position:relative;left:95.83333%}.el-col-md-24{width:100%}.el-col-md-offset-24{margin-left:100%}.el-col-md-pull-24{position:relative;right:100%}.el-col-md-push-24{position:relative;left:100%}}@media (min-width:1200px){.el-col-lg-0{width:0}.el-col-lg-offset-0{margin-left:0}.el-col-lg-pull-0{position:relative;right:0}.el-col-lg-push-0{position:relative;left:0}.el-col-lg-1{width:4.16667%}.el-col-lg-offset-1{margin-left:4.16667%}.el-col-lg-pull-1{position:relative;right:4.16667%}.el-col-lg-push-1{position:relative;left:4.16667%}.el-col-lg-2{width:8.33333%}.el-col-lg-offset-2{margin-left:8.33333%}.el-col-lg-pull-2{position:relative;right:8.33333%}.el-col-lg-push-2{position:relative;left:8.33333%}.el-col-lg-3{width:12.5%}.el-col-lg-offset-3{margin-left:12.5%}.el-col-lg-pull-3{position:relative;right:12.5%}.el-col-lg-push-3{position:relative;left:12.5%}.el-col-lg-4{width:16.66667%}.el-col-lg-offset-4{margin-left:16.66667%}.el-col-lg-pull-4{position:relative;right:16.66667%}.el-col-lg-push-4{position:relative;left:16.66667%}.el-col-lg-5{width:20.83333%}.el-col-lg-offset-5{margin-left:20.83333%}.el-col-lg-pull-5{position:relative;right:20.83333%}.el-col-lg-push-5{position:relative;left:20.83333%}.el-col-lg-6{width:25%}.el-col-lg-offset-6{margin-left:25%}.el-col-lg-pull-6{position:relative;right:25%}.el-col-lg-push-6{position:relative;left:25%}.el-col-lg-7{width:29.16667%}.el-col-lg-offset-7{margin-left:29.16667%}.el-col-lg-pull-7{position:relative;right:29.16667%}.el-col-lg-push-7{position:relative;left:29.16667%}.el-col-lg-8{width:33.33333%}.el-col-lg-offset-8{margin-left:33.33333%}.el-col-lg-pull-8{position:relative;right:33.33333%}.el-col-lg-push-8{position:relative;left:33.33333%}.el-col-lg-9{width:37.5%}.el-col-lg-offset-9{margin-left:37.5%}.el-col-lg-pull-9{position:relative;right:37.5%}.el-col-lg-push-9{position:relative;left:37.5%}.el-col-lg-10{width:41.66667%}.el-col-lg-offset-10{margin-left:41.66667%}.el-col-lg-pull-10{position:relative;right:41.66667%}.el-col-lg-push-10{position:relative;left:41.66667%}.el-col-lg-11{width:45.83333%}.el-col-lg-offset-11{margin-left:45.83333%}.el-col-lg-pull-11{position:relative;right:45.83333%}.el-col-lg-push-11{position:relative;left:45.83333%}.el-col-lg-12{width:50%}.el-col-lg-offset-12{margin-left:50%}.el-col-lg-pull-12{position:relative;right:50%}.el-col-lg-push-12{position:relative;left:50%}.el-col-lg-13{width:54.16667%}.el-col-lg-offset-13{margin-left:54.16667%}.el-col-lg-pull-13{position:relative;right:54.16667%}.el-col-lg-push-13{position:relative;left:54.16667%}.el-col-lg-14{width:58.33333%}.el-col-lg-offset-14{margin-left:58.33333%}.el-col-lg-pull-14{position:relative;right:58.33333%}.el-col-lg-push-14{position:relative;left:58.33333%}.el-col-lg-15{width:62.5%}.el-col-lg-offset-15{margin-left:62.5%}.el-col-lg-pull-15{position:relative;right:62.5%}.el-col-lg-push-15{position:relative;left:62.5%}.el-col-lg-16{width:66.66667%}.el-col-lg-offset-16{margin-left:66.66667%}.el-col-lg-pull-16{position:relative;right:66.66667%}.el-col-lg-push-16{position:relative;left:66.66667%}.el-col-lg-17{width:70.83333%}.el-col-lg-offset-17{margin-left:70.83333%}.el-col-lg-pull-17{position:relative;right:70.83333%}.el-col-lg-push-17{position:relative;left:70.83333%}.el-col-lg-18{width:75%}.el-col-lg-offset-18{margin-left:75%}.el-col-lg-pull-18{position:relative;right:75%}.el-col-lg-push-18{position:relative;left:75%}.el-col-lg-19{width:79.16667%}.el-col-lg-offset-19{margin-left:79.16667%}.el-col-lg-pull-19{position:relative;right:79.16667%}.el-col-lg-push-19{position:relative;left:79.16667%}.el-col-lg-20{width:83.33333%}.el-col-lg-offset-20{margin-left:83.33333%}.el-col-lg-pull-20{position:relative;right:83.33333%}.el-col-lg-push-20{position:relative;left:83.33333%}.el-col-lg-21{width:87.5%}.el-col-lg-offset-21{margin-left:87.5%}.el-col-lg-pull-21{position:relative;right:87.5%}.el-col-lg-push-21{position:relative;left:87.5%}.el-col-lg-22{width:91.66667%}.el-col-lg-offset-22{margin-left:91.66667%}.el-col-lg-pull-22{position:relative;right:91.66667%}.el-col-lg-push-22{position:relative;left:91.66667%}.el-col-lg-23{width:95.83333%}.el-col-lg-offset-23{margin-left:95.83333%}.el-col-lg-pull-23{position:relative;right:95.83333%}.el-col-lg-push-23{position:relative;left:95.83333%}.el-col-lg-24{width:100%}.el-col-lg-offset-24{margin-left:100%}.el-col-lg-pull-24{position:relative;right:100%}.el-col-lg-push-24{position:relative;left:100%}}.el-progress-bar__inner:after{display:inline-block;height:100%;vertical-align:middle}.el-upload{display:inline-block;text-align:center;cursor:pointer}.el-upload iframe{position:absolute;z-index:-1;top:0;left:0;opacity:0;filter:alpha(opacity=0)}.el-upload__input{display:none}.el-upload__tip{font-size:12px;color:#8391a5;margin-top:7px}.el-upload--picture-card{background-color:#fbfdff;border:1px dashed #c0ccda;border-radius:6px;box-sizing:border-box;width:148px;height:148px;cursor:pointer;line-height:146px;vertical-align:top}.el-upload--picture-card i{font-size:28px;color:#8c939d}.el-upload--picture-card:hover{border-color:#20a0ff;color:#20a0ff}.el-upload-dragger{background-color:#fff;border:1px dashed #d9d9d9;border-radius:6px;box-sizing:border-box;width:360px;height:180px;text-align:center;cursor:pointer;position:relative;overflow:hidden}.el-upload-dragger .el-upload__text{color:#97a8be;font-size:14px;text-align:center}.el-upload-dragger .el-upload__text em{color:#20a0ff;font-style:normal}.el-upload-dragger .el-icon-upload{font-size:67px;color:#97a8be;margin:40px 0 16px;line-height:50px}.el-upload-dragger+.el-upload__tip{text-align:center}.el-upload-dragger~.el-upload__files{border-top:1px solid rgba(191,203,217,.2);margin-top:7px;padding-top:5px}.el-upload-dragger:hover{border-color:#20a0ff}.el-upload-dragger.is-dragover{background-color:rgba(32,159,255,.06);border:2px dashed #20a0ff}.el-upload-list{margin:0;padding:0;list-style:none}.el-upload-list.is-disabled .el-upload-list__item:hover .el-upload-list__item-status-label{display:block}.el-upload-list__item{transition:all .5s cubic-bezier(.55,0,.1,1);font-size:14px;color:#48576a;line-height:1.8;margin-top:5px;box-sizing:border-box;border-radius:4px;width:100%;position:relative}.el-upload-list__item .el-progress-bar{margin-right:0;padding-right:0}.el-upload-list__item .el-progress{position:absolute;top:20px;width:100%}.el-upload-list__item .el-progress__text{position:absolute;top:-13px;right:0}.el-upload-list__item:first-child{margin-top:10px}.el-upload-list__item .el-icon-upload-success{color:#13ce66}.el-upload-list__item .el-icon-close{display:none;position:absolute;top:5px;right:5px;cursor:pointer;opacity:.75;color:#48576a;-ms-transform:scale(.7);transform:scale(.7)}.el-upload-list__item .el-icon-close:hover{opacity:1}.el-upload-list__item:hover{background-color:#eef1f6}.el-upload-list__item:hover .el-icon-close{display:inline-block}.el-upload-list__item:hover .el-progress__text{display:none}.el-upload-list__item.is-success .el-upload-list__item-status-label{display:block}.el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#20a0ff;cursor:pointer}.el-upload-list__item.is-success:hover .el-upload-list__item-status-label{display:none}.el-upload-list__item-name{color:#48576a;display:block;margin-right:40px;overflow:hidden;padding-left:4px;text-overflow:ellipsis;transition:color .3s}.el-upload-list__item-name [class^=el-icon]{color:#97a8be;margin-right:7px;height:100%;line-height:inherit}.el-upload-list__item-status-label{position:absolute;right:5px;top:0;line-height:inherit;display:none}.el-upload-list__item-delete{position:absolute;right:10px;top:0;font-size:12px;color:#48576a;display:none}.el-upload-list__item-delete:hover{color:#20a0ff}.el-upload-list--picture-card{margin:0;display:inline;vertical-align:top}.el-upload-list--picture-card .el-upload-list__item{overflow:hidden;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;box-sizing:border-box;width:148px;height:148px;margin:0 8px 8px 0;display:inline-block}.el-upload-list--picture-card .el-upload-list__item .el-icon-check,.el-upload-list--picture-card .el-upload-list__item .el-icon-circle-check{color:#fff}.el-upload-list--picture-card .el-upload-list__item .el-icon-close,.el-upload-list--picture-card .el-upload-list__item:hover .el-upload-list__item-status-label{display:none}.el-upload-list--picture-card .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture-card .el-upload-list__item-name{display:none}.el-upload-list--picture-card .el-upload-list__item-thumbnail{width:100%;height:100%}.el-upload-list--picture-card .el-upload-list__item-status-label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;-ms-transform:rotate(45deg);transform:rotate(45deg);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.el-upload-list--picture-card .el-upload-list__item-status-label i{font-size:12px;margin-top:11px;-ms-transform:rotate(-45deg) scale(.8);transform:rotate(-45deg) scale(.8)}.el-upload-list--picture-card .el-upload-list__item-actions{position:absolute;width:100%;height:100%;left:0;top:0;cursor:default;text-align:center;color:#fff;opacity:0;font-size:20px;background-color:rgba(0,0,0,.5);transition:opacity .3s}.el-upload-list--picture-card .el-upload-list__item-actions:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-upload-list--picture-card .el-upload-list__item-actions span{display:none;cursor:pointer}.el-upload-list--picture-card .el-upload-list__item-actions span+span{margin-left:15px}.el-upload-list--picture-card .el-upload-list__item-actions .el-upload-list__item-delete{position:static;font-size:inherit;color:inherit}.el-upload-list--picture-card .el-upload-list__item-actions:hover{opacity:1}.el-upload-list--picture-card .el-upload-list__item-actions:hover span{display:inline-block}.el-upload-list--picture-card .el-progress{top:50%;left:50%;-ms-transform:translate(-50%,-50%);transform:translate(-50%,-50%);bottom:auto;width:126px}.el-upload-list--picture-card .el-progress .el-progress__text{top:50%}.el-upload-list--picture .el-upload-list__item{overflow:hidden;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;box-sizing:border-box;margin-top:10px;padding:10px 10px 10px 90px;height:92px}.el-upload-list--picture .el-upload-list__item .el-icon-check,.el-upload-list--picture .el-upload-list__item .el-icon-circle-check{color:#fff}.el-upload-list--picture .el-upload-list__item:hover .el-upload-list__item-status-label{background:0 0;box-shadow:none;top:-2px;right:-12px}.el-upload-list--picture .el-upload-list__item:hover .el-progress__text{display:block}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name{line-height:70px;margin-top:0}.el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name i{display:none}.el-upload-list--picture .el-upload-list__item-thumbnail{vertical-align:middle;display:inline-block;width:70px;height:70px;float:left;position:relative;z-index:1;margin-left:-80px}.el-upload-list--picture .el-upload-list__item-name{display:block;margin-top:20px}.el-upload-list--picture .el-upload-list__item-name i{font-size:70px;line-height:1;position:absolute;left:9px;top:10px}.el-upload-list--picture .el-upload-list__item-status-label{position:absolute;right:-17px;top:-7px;width:46px;height:26px;background:#13ce66;text-align:center;-ms-transform:rotate(45deg);transform:rotate(45deg);box-shadow:0 1px 1px #ccc}.el-upload-list--picture .el-upload-list__item-status-label i{font-size:12px;margin-top:12px;-ms-transform:rotate(-45deg) scale(.8);transform:rotate(-45deg) scale(.8)}.el-upload-list--picture .el-progress{position:relative;top:-7px}.el-upload-cover{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;z-index:10;cursor:default}.el-upload-cover:after{display:inline-block;height:100%;vertical-align:middle}.el-upload-cover img{display:block;width:100%;height:100%}.el-upload-cover+.el-upload__inner{opacity:0;position:relative;z-index:1}.el-upload-cover__label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;-ms-transform:rotate(45deg);transform:rotate(45deg);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.el-upload-cover__label i{font-size:12px;margin-top:11px;-ms-transform:rotate(-45deg) scale(.8);transform:rotate(-45deg) scale(.8);color:#fff}.el-upload-cover__progress{display:inline-block;vertical-align:middle;position:static;width:243px}.el-upload-cover__progress+.el-upload__inner{opacity:0}.el-upload-cover__content{position:absolute;top:0;left:0;width:100%;height:100%}.el-upload-cover__interact{position:absolute;bottom:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.72);text-align:center}.el-upload-cover__interact .btn{display:inline-block;color:#fff;font-size:14px;cursor:pointer;vertical-align:middle;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;margin-top:60px}.el-upload-cover__interact .btn span{opacity:0;transition:opacity .15s linear}.el-upload-cover__interact .btn:not(:first-child){margin-left:35px}.el-upload-cover__interact .btn:hover{-ms-transform:translateY(-13px);transform:translateY(-13px)}.el-upload-cover__interact .btn:hover span{opacity:1}.el-upload-cover__interact .btn i{color:#fff;display:block;font-size:24px;line-height:inherit;margin:0 auto 5px}.el-upload-cover__title{position:absolute;bottom:0;left:0;background-color:#fff;height:36px;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400;text-align:left;padding:0 10px;margin:0;line-height:36px;font-size:14px;color:#48576a}.el-progress{position:relative;line-height:1}.el-progress.is-exception .el-progress-bar__inner{background-color:#ff4949}.el-progress.is-exception .el-progress__text{color:#ff4949}.el-progress.is-success .el-progress-bar__inner{background-color:#13ce66}.el-progress.is-success .el-progress__text{color:#13ce66}.el-progress__text{font-size:14px;color:#48576a;display:inline-block;vertical-align:middle;margin-left:10px;line-height:1}.el-progress__text i{vertical-align:middle;display:block}.el-progress--circle{display:inline-block}.el-progress--circle .el-progress__text{position:absolute;top:50%;left:0;width:100%;text-align:center;margin:0;-ms-transform:translate(0,-50%);transform:translate(0,-50%)}.el-progress--circle .el-progress__text i{vertical-align:middle;display:inline-block}.el-progress--without-text .el-progress__text{display:none}.el-progress--without-text .el-progress-bar{padding-right:0;margin-right:0;display:block}.el-progress-bar,.el-progress-bar__innerText,.el-spinner{display:inline-block;vertical-align:middle}.el-progress--text-inside .el-progress-bar{padding-right:0;margin-right:0}.el-progress-bar{padding-right:50px;width:100%;margin-right:-55px;box-sizing:border-box}.el-progress-bar__outer{height:6px;border-radius:100px;background-color:#e4e8f1;overflow:hidden;position:relative;vertical-align:middle}.el-progress-bar__inner{position:absolute;left:0;top:0;height:100%;background-color:#20a0ff;text-align:right;border-radius:100px;line-height:1}.el-progress-bar__innerText{color:#fff;font-size:12px;margin:0 5px}@keyframes progress{0%{background-position:0 0}100%{background-position:32px 0}}.el-time-spinner{width:100%}.el-spinner-inner{animation:rotate 2s linear infinite;width:50px;height:50px}.el-spinner-inner .path{stroke:#ececec;stroke-linecap:round;animation:dash 1.5s ease-in-out infinite}@keyframes rotate{100%{transform:rotate(360deg)}}@keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}100%{stroke-dasharray:90,150;stroke-dashoffset:-124}}.el-message{box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);min-width:300px;padding:10px 12px;box-sizing:border-box;border-radius:2px;position:fixed;left:50%;top:20px;-ms-transform:translateX(-50%);transform:translateX(-50%);background-color:#fff;transition:opacity .3s,transform .4s;overflow:hidden}.el-message .el-icon-circle-check{color:#13ce66}.el-message .el-icon-circle-cross{color:#ff4949}.el-message .el-icon-information{color:#50bfff}.el-message .el-icon-warning{color:#f7ba2a}.el-message__group{margin-left:38px;position:relative;height:20px;line-height:20px;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center}.el-message__group p{font-size:14px;margin:0 34px 0 0;color:#8391a5;text-align:justify}.el-step__head,.el-steps.is-horizontal.is-center{text-align:center}.el-message__group.is-with-icon{margin-left:0}.el-message__img{width:40px;height:40px;position:absolute;left:0;top:0}.el-message__icon{vertical-align:middle;margin-right:8px}.el-message__closeBtn{top:3px;right:0;position:absolute;cursor:pointer;color:#bfcbd9;font-size:14px}.el-message__closeBtn:hover{color:#97a8be}.el-message-fade-enter,.el-message-fade-leave-active{opacity:0;-ms-transform:translate(-50%,-100%);transform:translate(-50%,-100%)}.el-badge{position:relative;vertical-align:middle;display:inline-block}.el-badge__content{background-color:#ff4949;border-radius:10px;color:#fff;display:inline-block;font-size:12px;height:18px;line-height:18px;padding:0 6px;text-align:center;border:1px solid #fff}.el-badge__content.is-dot{width:8px;height:8px;padding:0;right:0;border-radius:50%}.el-badge__content.is-fixed{top:0;right:10px;position:absolute;-ms-transform:translateY(-50%) translateX(100%);transform:translateY(-50%) translateX(100%)}.el-rate__icon,.el-rate__item{position:relative;display:inline-block}.el-badge__content.is-fixed.is-dot{right:5px}.el-card{border:1px solid #d1dbe5;border-radius:4px;background-color:#fff;overflow:hidden;box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.el-card__header{padding:18px 20px;border-bottom:1px solid #d1dbe5;box-sizing:border-box}.el-card__body{padding:20px}.el-rate{height:20px;line-height:1}.el-rate__item{font-size:0;vertical-align:middle}.el-rate__icon{font-size:18px;margin-right:6px;color:#bfcbd9;transition:.3s}.el-rate__decimal,.el-rate__icon .path2{position:absolute;top:0;left:0}.el-rate__icon.hover{-ms-transform:scale(1.15);transform:scale(1.15)}.el-rate__decimal{display:inline-block;overflow:hidden}.el-rate__text{font-size:14px;vertical-align:middle}.el-steps{font-size:0}.el-steps>:last-child .el-step__line{display:none}.el-step.is-horizontal,.el-step.is-vertical .el-step__head,.el-step.is-vertical .el-step__main,.el-step__line{display:inline-block}.el-step{position:relative;vertical-align:top}.el-step:last-child .el-step__main{padding-right:0}.el-step.is-vertical .el-step__main{padding-left:10px}.el-step__line{position:absolute;border-color:inherit;background-color:#bfcbd9}.el-step__line.is-vertical{width:2px;box-sizing:border-box;top:32px;bottom:0;left:15px}.el-step__line.is-horizontal{top:15px;height:2px;left:32px;right:0}.el-step__line.is-icon.is-horizontal{right:4px}.el-step__line-inner{display:block;border-width:1px;border-style:solid;border-color:inherit;transition:all 150ms;box-sizing:border-box;width:0;height:0}.el-step__icon{display:block;line-height:28px}.el-step__icon>*{line-height:inherit;vertical-align:middle}.el-step__head{width:28px;height:28px;border-radius:50%;background-color:transparent;line-height:28px;font-size:28px;vertical-align:top;transition:all 150ms}.el-carousel__arrow,.el-carousel__button{margin:0;transition:.3s;cursor:pointer;outline:0}.el-step__head.is-finish{color:#20a0ff;border-color:#20a0ff}.el-step__head.is-error{color:#ff4949;border-color:#ff4949}.el-step__head.is-success{color:#13ce66;border-color:#13ce66}.el-step__head.is-process,.el-step__head.is-wait{color:#bfcbd9;border-color:#bfcbd9}.el-step__head.is-text{font-size:14px;border-width:2px;border-style:solid}.el-step__head.is-text.is-finish{color:#fff;background-color:#20a0ff;border-color:#20a0ff}.el-step__head.is-text.is-error{color:#fff;background-color:#ff4949;border-color:#ff4949}.el-step__head.is-text.is-success{color:#fff;background-color:#13ce66;border-color:#13ce66}.el-step__head.is-text.is-wait{color:#bfcbd9;background-color:#fff;border-color:#bfcbd9}.el-step__head.is-text.is-process{color:#fff;background-color:#bfcbd9;border-color:#bfcbd9}.el-step__main{white-space:normal;padding-right:10px;text-align:left}.el-step__title{font-size:14px;line-height:32px;display:inline-block}.el-step__title.is-finish{font-weight:700;color:#20a0ff}.el-step__title.is-error{font-weight:700;color:#ff4949}.el-step__title.is-success{font-weight:700;color:#13ce66}.el-step__title.is-wait{font-weight:400;color:#97a8be}.el-step__title.is-process{font-weight:700;color:#48576a}.el-step__description{font-size:12px;font-weight:400;line-height:14px}.el-step__description.is-finish{color:#20a0ff}.el-step__description.is-error{color:#ff4949}.el-step__description.is-success{color:#13ce66}.el-step__description.is-wait{color:#bfcbd9}.el-step__description.is-process{color:#8391a5}.el-carousel{overflow-x:hidden;position:relative}.el-carousel__container{position:relative;height:300px}.el-carousel__arrow{border:none;padding:0;width:36px;height:36px;border-radius:50%;background-color:rgba(31,45,61,.11);color:#fff;position:absolute;top:50%;z-index:10;-ms-transform:translateY(-50%);transform:translateY(-50%);text-align:center;font-size:12px}.el-carousel__arrow:hover{background-color:rgba(31,45,61,.23)}.el-carousel__arrow i{cursor:pointer}.el-carousel__arrow--left{left:16px}.el-carousel__arrow--right{right:16px}.el-carousel__indicators{position:absolute;list-style:none;bottom:0;left:50%;-ms-transform:translateX(-50%);transform:translateX(-50%);margin:0;padding:0;z-index:2}.el-carousel__indicators--outside{bottom:26px;text-align:center;position:static;-ms-transform:none;transform:none}.el-carousel__indicators--outside .el-carousel__indicator:hover button{opacity:.64}.el-carousel__indicators--outside button{background-color:#8391a5;opacity:.24}.el-carousel__indicators--labels{left:0;right:0;-ms-transform:none;transform:none;text-align:center}.el-carousel__indicators--labels .el-carousel__button{width:auto;height:auto;padding:2px 18px;font-size:12px}.el-carousel__indicators--labels .el-carousel__indicator{padding:6px 4px}.el-carousel__indicator{display:inline-block;background-color:transparent;padding:12px 4px;cursor:pointer}.el-carousel__indicator:hover button{opacity:.72}.el-carousel__indicator.is-active button{opacity:1}.el-carousel__button{display:block;opacity:.48;width:30px;height:2px;background-color:#fff;border:none;padding:0}.carousel-arrow-left-enter,.carousel-arrow-left-leave-active{-ms-transform:translateY(-50%) translateX(-10px);transform:translateY(-50%) translateX(-10px);opacity:0}.carousel-arrow-right-enter,.carousel-arrow-right-leave-active{-ms-transform:translateY(-50%) translateX(10px);transform:translateY(-50%) translateX(10px);opacity:0}.el-scrollbar{overflow:hidden;position:relative}.el-scrollbar:active .el-scrollbar__bar,.el-scrollbar:focus .el-scrollbar__bar,.el-scrollbar:hover .el-scrollbar__bar{opacity:1;transition:opacity 340ms ease-out}.el-scrollbar__wrap{overflow:scroll}.el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(151,168,190,.3);transition:.3s background-color}.el-scrollbar__thumb:hover{background-color:rgba(151,168,190,.5)}.el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;transition:opacity 120ms ease-out}.el-carousel__item--card,.el-carousel__item.is-animating{transition:transform .4s ease-in-out}.el-scrollbar__bar.is-horizontal{height:6px;left:2px}.el-scrollbar__bar.is-horizontal>div{height:100%}.el-scrollbar__bar.is-vertical{width:6px;top:2px}.el-scrollbar__bar.is-vertical>div{width:100%}.el-carousel__item{position:absolute;top:0;left:0;width:100%;height:100%;display:inline-block;overflow:hidden;z-index:0}.el-carousel__item.is-active{z-index:2}.el-carousel__item--card{width:50%}.el-carousel__item--card.is-in-stage{cursor:pointer;z-index:1}.el-carousel__item--card.is-active,.el-cascader .el-icon-circle-close,.el-cascader-menus{z-index:2}.el-carousel__item--card.is-in-stage.is-hover .el-carousel__mask,.el-carousel__item--card.is-in-stage:hover .el-carousel__mask{opacity:.12}.el-carousel__mask{position:absolute;width:100%;height:100%;top:0;left:0;background-color:#fff;opacity:.24;transition:.2s}.el-collapse{border:1px solid #dfe6ec;border-radius:0}.el-collapse-item:last-child{margin-bottom:-1px}.el-collapse-item.is-active>.el-collapse-item__header .el-collapse-item__header__arrow{-ms-transform:rotate(90deg);transform:rotate(90deg)}.el-collapse-item__header{height:43px;line-height:43px;padding-left:15px;background-color:#fff;color:#48576a;cursor:pointer;border-bottom:1px solid #dfe6ec;font-size:13px}.el-collapse-item__header__arrow{margin-right:8px;transition:transform .3s}.el-collapse-item__wrap{will-change:height;background-color:#fbfdff;overflow:hidden;box-sizing:border-box;border-bottom:1px solid #dfe6ec}.el-collapse-item__content{padding:10px 15px;font-size:13px;color:#1f2d3d;line-height:1.769230769230769}.el-cascader{display:inline-block;position:relative}.el-cascader .el-input,.el-cascader .el-input__inner{cursor:pointer}.el-cascader .el-input__icon{transition:none}.el-cascader .el-icon-caret-bottom{transition:transform .3s}.el-cascader .el-icon-caret-bottom.is-reverse{-ms-transform:rotate(180deg);transform:rotateZ(180deg)}.el-cascader.is-disabled .el-cascader__label{z-index:2;color:#bbb}.el-cascader__label{position:absolute;left:0;top:0;height:100%;line-height:36px;padding:0 25px 0 10px;color:#1f2d3d;width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;box-sizing:border-box;cursor:pointer;font-size:14px;text-align:left}.el-cascader__label span{color:#97a8be}.el-cascader--large{font-size:16px}.el-cascader--large .el-cascader__label{line-height:40px}.el-cascader--small{font-size:13px}.el-cascader--small .el-cascader__label{line-height:28px}.el-cascader-menus{white-space:nowrap;background:#fff;position:absolute;margin:5px 0;border:1px solid #d1dbe5;border-radius:2px;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04)}.el-cascader-menu{display:inline-block;vertical-align:top;height:204px;overflow:auto;border-right:solid 1px #d1dbe5;background-color:#fff;box-sizing:border-box;margin:0;padding:6px 0;min-width:160px}.el-cascader-menu:last-child{border-right:0}.el-cascader-menu__item{font-size:14px;padding:8px 30px 8px 10px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#48576a;height:36px;line-height:1.5;box-sizing:border-box;cursor:pointer}.el-cascader-menu__item:hover{background-color:#e4e8f1}.el-cascader-menu__item.selected{color:#fff;background-color:#20a0ff}.el-cascader-menu__item.selected.hover{background-color:#1c8de0}.el-cascader-menu__item.is-active{color:#fff;background-color:#20a0ff}.el-cascader-menu__item.is-active:hover{background-color:#1c8de0}.el-cascader-menu__item.is-disabled{color:#bfcbd9;background-color:#fff;cursor:not-allowed}.el-cascader-menu__item.is-disabled:hover{background-color:#fff}.el-cascader-menu__item__keyword{font-weight:700}.el-cascader-menu__item--extensible:after{font-family:element-icons;content:\"\\\\e606\";font-size:12px;-ms-transform:scale(.8);transform:scale(.8);color:#bfcbd9;position:absolute;right:10px;margin-top:1px}.el-cascader-menu--flexible{height:auto;max-height:180px;overflow:auto}.el-cascader-menu--flexible .el-cascader-menu__item{overflow:visible}.el-color-hue-slider{position:relative;box-sizing:border-box;width:280px;height:12px;background-color:red;padding:0 2px}.el-color-hue-slider.is-vertical{width:12px;height:180px;padding:2px 0}.el-color-hue-slider.is-vertical .el-color-hue-slider__bar{background:linear-gradient(to bottom,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.el-color-hue-slider.is-vertical .el-color-hue-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-hue-slider__bar{position:relative;background:linear-gradient(to right,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);height:100%}.el-color-hue-slider__thumb{position:absolute;cursor:pointer;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.el-color-svpanel{position:relative;width:280px;height:180px}.el-color-svpanel__black,.el-color-svpanel__white{position:absolute;top:0;left:0;right:0;bottom:0}.el-color-svpanel__white{background:linear-gradient(to right,#fff,rgba(255,255,255,0))}.el-color-svpanel__black{background:linear-gradient(to top,#000,rgba(0,0,0,0))}.el-color-svpanel__cursor{position:absolute}.el-color-svpanel__cursor>div{cursor:head;width:4px;height:4px;box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);border-radius:50%;-ms-transform:translate(-2px,-2px);transform:translate(-2px,-2px)}.el-color-alpha-slider{position:relative;box-sizing:border-box;width:280px;height:12px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-alpha-slider.is-vertical{width:20px;height:180px}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__bar{background:linear-gradient(to bottom,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%)}.el-color-alpha-slider.is-vertical .el-color-alpha-slider__thumb{left:0;top:0;width:100%;height:4px}.el-color-alpha-slider__bar{position:relative;background:linear-gradient(to right,rgba(255,255,255,0) 0,rgba(255,255,255,1) 100%);height:100%}.el-color-alpha-slider__thumb{position:absolute;cursor:pointer;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.el-color-dropdown{width:300px}.el-color-dropdown__main-wrapper{margin-bottom:6px}.el-color-dropdown__main-wrapper::after{content:\"\";display:table;clear:both}.el-color-dropdown__btns{margin-top:6px;text-align:right}.el-color-dropdown__value{float:left;line-height:26px;font-size:12px;color:#1f2d3d}.el-color-dropdown__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.el-color-dropdown__btn[disabled]{color:#ccc;cursor:not-allowed}.el-color-dropdown__btn:hover{color:#20a0ff;border-color:#20a0ff}.el-color-dropdown__link-btn{cursor:pointer;color:#20a0ff;text-decoration:none;padding:15px;font-size:12px}.el-color-dropdown__link-btn:hover{color:#4db3ff}.el-color-picker{display:inline-block;position:relative;line-height:normal}.el-color-picker__trigger{display:inline-block;box-sizing:border-box;height:36px;padding:6px;border:1px solid #bfcbd9;border-radius:4px;font-size:0}.el-color-picker__color{position:relative;display:inline-block;box-sizing:border-box;border:1px solid #666;width:22px;height:22px;text-align:center}.el-color-picker__color.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.el-color-picker__color-inner{position:absolute;left:0;top:0;right:0;bottom:0}.el-color-picker__empty{font-size:12px;vertical-align:middle;color:#666;position:absolute;top:4px;left:4px}.el-color-picker__icon{display:inline-block;position:relative;top:-6px;margin-left:8px;width:12px;color:#888;font-size:12px}.el-input,.el-input__inner{width:100%;display:inline-block}.el-color-picker__panel{position:absolute;z-index:10;padding:6px;background-color:#fff;border:1px solid #d1dbe5;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.12)}.el-input{position:relative;font-size:14px}.el-input.is-disabled .el-input__inner{background-color:#eef1f6;border-color:#d1dbe5;color:#bbb;cursor:not-allowed}.el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#bfcbd9}.el-input.is-disabled .el-input__inner::-moz-placeholder{color:#bfcbd9}.el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#bfcbd9}.el-input.is-disabled .el-input__inner::placeholder{color:#bfcbd9}.el-input.is-active .el-input__inner{outline:0;border-color:#20a0ff}.el-input__inner{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #bfcbd9;box-sizing:border-box;color:#1f2d3d;font-size:inherit;height:36px;line-height:1;outline:0;padding:3px 10px;transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-button,.el-checkbox-button__inner{-webkit-appearance:none;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;outline:0;text-align:center}.el-input__inner::-webkit-input-placeholder{color:#97a8be}.el-input__inner::-moz-placeholder{color:#97a8be}.el-input__inner:-ms-input-placeholder{color:#97a8be}.el-input__inner::placeholder{color:#97a8be}.el-input__inner:hover{border-color:#8391a5}.el-input__inner:focus{outline:0;border-color:#20a0ff}.el-input__icon{position:absolute;width:35px;height:100%;right:0;top:0;text-align:center;color:#bfcbd9;transition:all .3s}.el-input__icon:after{content:\\'\\';height:100%;width:0;display:inline-block;vertical-align:middle}.el-input__icon+.el-input__inner{padding-right:35px}.el-input__icon.is-clickable:hover{cursor:pointer;color:#8391a5}.el-input__icon.is-clickable:hover+.el-input__inner{border-color:#8391a5}.el-input--large{font-size:16px}.el-input--large .el-input__inner{height:42px}.el-input--small{font-size:13px}.el-input--small .el-input__inner{height:30px}.el-input--mini{font-size:12px}.el-input--mini .el-input__inner{height:22px}.el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.el-input-group__append,.el-input-group__prepend{background-color:#fbfdff;color:#97a8be;vertical-align:middle;display:table-cell;position:relative;border:1px solid #bfcbd9;border-radius:4px;padding:0 10px;width:1px;white-space:nowrap}.el-input-group--prepend .el-input__inner,.el-input-group__append{border-top-left-radius:0;border-bottom-left-radius:0}.el-input-group--append .el-input__inner,.el-input-group__prepend{border-top-right-radius:0;border-bottom-right-radius:0}.el-input-group__append .el-button,.el-input-group__append .el-select,.el-input-group__prepend .el-button,.el-input-group__prepend .el-select{display:block;margin:-10px}.el-input-group__append button.el-button,.el-input-group__append div.el-select .el-input__inner,.el-input-group__append div.el-select:hover .el-input__inner,.el-input-group__prepend button.el-button,.el-input-group__prepend div.el-select .el-input__inner,.el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.el-input-group__append .el-button,.el-input-group__append .el-input,.el-input-group__prepend .el-button,.el-input-group__prepend .el-input{font-size:inherit}.el-button,.el-textarea__inner{font-size:14px;box-sizing:border-box}.el-input-group__prepend{border-right:0}.el-input-group__append{border-left:0}.el-textarea{display:inline-block;width:100%;vertical-align:bottom}.el-textarea.is-disabled .el-textarea__inner{background-color:#eef1f6;border-color:#d1dbe5;color:#bbb;cursor:not-allowed}.el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#bfcbd9}.el-textarea.is-disabled .el-textarea__inner::-moz-placeholder{color:#bfcbd9}.el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#bfcbd9}.el-textarea.is-disabled .el-textarea__inner::placeholder{color:#bfcbd9}.el-textarea__inner{display:block;resize:vertical;padding:5px 7px;line-height:1.5;width:100%;color:#1f2d3d;background-color:#fff;background-image:none;border:1px solid #bfcbd9;border-radius:4px;transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.el-textarea__inner::-webkit-input-placeholder{color:#97a8be}.el-textarea__inner::-moz-placeholder{color:#97a8be}.el-textarea__inner:-ms-input-placeholder{color:#97a8be}.el-textarea__inner::placeholder{color:#97a8be}.el-textarea__inner:hover{border-color:#8391a5}.el-textarea__inner:focus{outline:0;border-color:#20a0ff}.el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#fff;border:1px solid #c4c4c4;color:#1f2d3d;margin:0;padding:10px 15px;border-radius:4px}.el-button+.el-button{margin-left:10px}.el-button:focus,.el-button:hover{color:#20a0ff;border-color:#20a0ff}.el-button:active{color:#1d90e6;border-color:#1d90e6;outline:0}.el-button::-moz-focus-inner{border:0}.el-button [class*=el-icon-]+span{margin-left:5px}.el-button.is-loading{position:relative;pointer-events:none}.el-button.is-loading:before{pointer-events:none;content:\\'\\';position:absolute;left:-1px;top:-1px;right:-1px;bottom:-1px;border-radius:inherit;background-color:rgba(255,255,255,.35)}.el-button.is-disabled,.el-button.is-disabled:focus,.el-button.is-disabled:hover{color:#bfcbd9;cursor:not-allowed;background-image:none;background-color:#eef1f6;border-color:#d1dbe5}.el-checkbox,.el-checkbox__input{cursor:pointer;display:inline-block;position:relative;white-space:nowrap}.el-button.is-disabled.el-button--text{background-color:transparent}.el-button.is-disabled.is-plain,.el-button.is-disabled.is-plain:focus,.el-button.is-disabled.is-plain:hover{background-color:#fff;border-color:#d1dbe5;color:#bfcbd9}.el-button.is-active{color:#1d90e6;border-color:#1d90e6}.el-button.is-plain:focus,.el-button.is-plain:hover{background:#fff;border-color:#20a0ff;color:#20a0ff}.el-button.is-plain:active{background:#fff;border-color:#1d90e6;color:#1d90e6;outline:0}.el-button--primary{color:#fff;background-color:#20a0ff;border-color:#20a0ff}.el-button--primary:focus,.el-button--primary:hover{background:#4db3ff;border-color:#4db3ff;color:#fff}.el-button--primary.is-active,.el-button--primary:active{background:#1d90e6;border-color:#1d90e6;color:#fff}.el-button--primary:active{outline:0}.el-button--primary.is-plain{background:#fff;border:1px solid #bfcbd9;color:#1f2d3d}.el-button--primary.is-plain:focus,.el-button--primary.is-plain:hover{background:#fff;border-color:#20a0ff;color:#20a0ff}.el-button--primary.is-plain:active{background:#fff;border-color:#1d90e6;color:#1d90e6;outline:0}.el-button--success{color:#fff;background-color:#13ce66;border-color:#13ce66}.el-button--success:focus,.el-button--success:hover{background:#42d885;border-color:#42d885;color:#fff}.el-button--success.is-active,.el-button--success:active{background:#11b95c;border-color:#11b95c;color:#fff}.el-button--success:active{outline:0}.el-button--success.is-plain{background:#fff;border:1px solid #bfcbd9;color:#1f2d3d}.el-button--success.is-plain:focus,.el-button--success.is-plain:hover{background:#fff;border-color:#13ce66;color:#13ce66}.el-button--success.is-plain:active{background:#fff;border-color:#11b95c;color:#11b95c;outline:0}.el-button--warning{color:#fff;background-color:#f7ba2a;border-color:#f7ba2a}.el-button--warning:focus,.el-button--warning:hover{background:#f9c855;border-color:#f9c855;color:#fff}.el-button--warning.is-active,.el-button--warning:active{background:#dea726;border-color:#dea726;color:#fff}.el-button--warning:active{outline:0}.el-button--warning.is-plain{background:#fff;border:1px solid #bfcbd9;color:#1f2d3d}.el-button--warning.is-plain:focus,.el-button--warning.is-plain:hover{background:#fff;border-color:#f7ba2a;color:#f7ba2a}.el-button--warning.is-plain:active{background:#fff;border-color:#dea726;color:#dea726;outline:0}.el-button--danger{color:#fff;background-color:#ff4949;border-color:#ff4949}.el-button--danger:focus,.el-button--danger:hover{background:#ff6d6d;border-color:#ff6d6d;color:#fff}.el-button--danger.is-active,.el-button--danger:active{background:#e64242;border-color:#e64242;color:#fff}.el-button--danger:active{outline:0}.el-button--danger.is-plain{background:#fff;border:1px solid #bfcbd9;color:#1f2d3d}.el-button--danger.is-plain:focus,.el-button--danger.is-plain:hover{background:#fff;border-color:#ff4949;color:#ff4949}.el-button--danger.is-plain:active{background:#fff;border-color:#e64242;color:#e64242;outline:0}.el-button--info{color:#fff;background-color:#50bfff;border-color:#50bfff}.el-button--info:focus,.el-button--info:hover{background:#73ccff;border-color:#73ccff;color:#fff}.el-button--info.is-active,.el-button--info:active{background:#48ace6;border-color:#48ace6;color:#fff}.el-button--info:active{outline:0}.el-button--info.is-plain{background:#fff;border:1px solid #bfcbd9;color:#1f2d3d}.el-button--info.is-plain:focus,.el-button--info.is-plain:hover{background:#fff;border-color:#50bfff;color:#50bfff}.el-button--info.is-plain:active{background:#fff;border-color:#48ace6;color:#48ace6;outline:0}.el-button--large{padding:11px 19px;font-size:16px;border-radius:4px}.el-button--small{padding:7px 9px;font-size:12px;border-radius:4px}.el-button--mini{padding:4px;font-size:12px;border-radius:4px}.el-button--text{border:none;color:#20a0ff;background:0 0;padding-left:0;padding-right:0}.el-button--text:focus,.el-button--text:hover{color:#4db3ff}.el-button--text:active{color:#1d90e6}.el-button-group{display:inline-block;vertical-align:middle}.el-button-group .el-button--primary:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--primary:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--success:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--success:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--warning:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--warning:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--danger:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--danger:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--info:first-child{border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button--info:last-child{border-left-color:rgba(255,255,255,.5)}.el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.el-button-group .el-button{float:left;position:relative}.el-button-group .el-button+.el-button{margin-left:0}.el-button-group .el-button:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.el-button-group .el-button:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.el-button-group .el-button:not(:first-child):not(:last-child){border-radius:0}.el-button-group .el-button:not(:last-child){margin-right:-1px}.el-button-group .el-button.is-active,.el-button-group .el-button:active,.el-button-group .el-button:focus,.el-button-group .el-button:hover{z-index:1}.el-checkbox{color:#1f2d3d;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.el-checkbox+.el-checkbox{margin-left:15px}.el-checkbox__input{outline:0;line-height:1;vertical-align:middle}.el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:#20a0ff;border-color:#0190fe}.el-checkbox__input.is-indeterminate .el-checkbox__inner::before{content:\\'\\';position:absolute;display:block;border:1px solid #fff;margin-top:-1px;left:3px;right:3px;top:50%}.el-checkbox__input.is-indeterminate .el-checkbox__inner::after{display:none}.el-checkbox__input.is-focus .el-checkbox__inner{border-color:#20a0ff}.el-checkbox__input.is-checked .el-checkbox__inner{background-color:#20a0ff;border-color:#0190fe}.el-checkbox__input.is-checked .el-checkbox__inner::after{-ms-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.el-checkbox__input.is-disabled .el-checkbox__inner{background-color:#eef1f6;border-color:#d1dbe5;cursor:not-allowed}.el-checkbox__input.is-disabled .el-checkbox__inner::after{cursor:not-allowed;border-color:#eef1f6}.el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:#d1dbe5;border-color:#d1dbe5}.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after{border-color:#fff}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:#d1dbe5;border-color:#d1dbe5}.el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner::before{border-color:#fff}.el-checkbox__input.is-disabled+.el-checkbox__label{color:#bbb;cursor:not-allowed}.el-checkbox__inner{display:inline-block;position:relative;border:1px solid #bfcbd9;border-radius:4px;box-sizing:border-box;width:18px;height:18px;background-color:#fff;z-index:1;transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.el-checkbox__inner:hover{border-color:#20a0ff}.el-checkbox__inner::after{box-sizing:content-box;content:\"\";border:2px solid #fff;border-left:0;border-top:0;height:8px;left:5px;position:absolute;top:1px;-ms-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:4px;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) .05s;-ms-transform-origin:center;transform-origin:center}.el-checkbox__original{opacity:0;outline:0;position:absolute;margin:0;width:0;height:0;left:-999px}.el-checkbox-button,.el-checkbox-button__inner{position:relative;display:inline-block}.el-checkbox__label{font-size:14px;padding-left:5px}.el-checkbox-button.is-checked .el-checkbox-button__inner{color:#fff;background-color:#20a0ff;border-color:#20a0ff;box-shadow:-1px 0 0 0 #20a0ff}.el-checkbox-button.is-disabled .el-checkbox-button__inner{color:#bfcbd9;cursor:not-allowed;background-image:none;background-color:#eef1f6;border-color:#d1dbe5;box-shadow:none}.el-checkbox-button__inner,.el-transfer-panel{background:#fff;vertical-align:middle;box-sizing:border-box}.el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:#20a0ff}.el-checkbox-button:first-child .el-checkbox-button__inner{border-left:1px solid #bfcbd9;border-radius:4px 0 0 4px;box-shadow:none!important}.el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 4px 4px 0}.el-checkbox-button__inner{line-height:1;white-space:nowrap;border:1px solid #bfcbd9;border-left:0;color:#1f2d3d;margin:0;cursor:pointer;transition:all .3s cubic-bezier(.645,.045,.355,1);padding:10px 15px;font-size:14px;border-radius:0}.el-checkbox-button__inner:hover{color:#20a0ff}.el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.el-checkbox-button__original{opacity:0;outline:0;position:absolute;margin:0;left:-999px}.el-checkbox-button--large .el-checkbox-button__inner{padding:11px 19px;font-size:16px;border-radius:0}.el-checkbox-button--small .el-checkbox-button__inner{padding:7px 9px;font-size:12px;border-radius:0}.el-checkbox-button--mini .el-checkbox-button__inner{padding:4px;font-size:12px;border-radius:0}.el-transfer{font-size:14px}.el-transfer__buttons{display:inline-block;vertical-align:middle;padding:0 10px}.el-transfer__buttons .el-button{display:block;margin:0 auto;padding:8px 12px}.el-transfer-panel__item+.el-transfer-panel__item,.el-transfer__buttons .el-button [class*=el-icon-]+span{margin-left:0}.el-transfer__buttons .el-button:first-child{margin-bottom:6px}.el-transfer-panel{border:1px solid #d1dbe5;box-shadow:0 2px 4px rgba(0,0,0,.12),0 0 6px rgba(0,0,0,.04);display:inline-block;width:200px;position:relative}.el-transfer-panel .el-transfer-panel__header{height:36px;line-height:36px;background:#fbfdff;margin:0;padding-left:20px;border-bottom:1px solid #d1dbe5;box-sizing:border-box;color:#1f2d3d}.el-transfer-panel .el-transfer-panel__footer{height:36px;background:#fff;margin:0;padding:0;border-top:1px solid #d1dbe5;position:absolute;bottom:0;left:0;width:100%;z-index:1}.el-transfer-panel .el-transfer-panel__footer:after{display:inline-block;content:\"\";height:100%;vertical-align:middle}.el-transfer-panel .el-transfer-panel__footer .el-checkbox{padding-left:20px;color:#8391a5}.el-transfer-panel .el-transfer-panel__empty{margin:0;height:32px;line-height:32px;padding:6px 20px 0;color:#8391a5}.el-transfer-panel .el-checkbox__label{padding-left:14px}.el-transfer-panel .el-checkbox__inner{width:14px;height:14px;border-radius:3px}.el-transfer-panel .el-checkbox__inner::after{height:6px;width:3px;left:4px}.el-transfer-panel__body{padding-bottom:36px;height:246px}.el-transfer-panel__list{margin:0;padding:6px 0;list-style:none;height:246px;overflow:auto;box-sizing:border-box}.el-transfer-panel__list.is-filterable{height:214px}.el-transfer-panel__item{height:32px;line-height:32px;padding-left:20px;display:block}.el-transfer-panel__item .el-checkbox__label{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;box-sizing:border-box;padding-left:28px}.el-transfer-panel__item .el-checkbox__input{position:absolute;top:9px}.el-transfer-panel__item.el-checkbox{color:#48576a}.el-transfer-panel__item:hover{background:#e4e8f1}.el-transfer-panel__filter{margin-top:10px;text-align:center;padding:0 10px;width:100%;box-sizing:border-box}.el-transfer-panel__filter .el-input__inner{height:22px;width:100%;display:inline-block;box-sizing:border-box}.el-transfer-panel__filter .el-input__icon{right:10px}.el-transfer-panel__filter .el-icon-circle-close{cursor:pointer}'],sourceRoot:\"\"}])},226:function(e,o,t){o=e.exports=t(163)(!0),o.push([e.i,'.move_in_cart[data-v-99a59cfe]{-webkit-animation:mymove-data-v-99a59cfe .5s ease-in-out;animation:mymove-data-v-99a59cfe .5s ease-in-out}@keyframes mymove-data-v-99a59cfe{0%{-webkit-transform:scale(1);transform:scale(1)}25%{-webkit-transform:scale(.8);transform:scale(.8)}50%{-webkit-transform:scale(1.2);transform:scale(1.2)}75%{-webkit-transform:scale(.9);transform:scale(.9)}to{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes mymove{0%{-webkit-transform:scale(1);transform:scale(1)}25%{-webkit-transform:scale(.8);transform:scale(.8)}50%{-webkit-transform:scale(1.2);transform:scale(1.2)}75%{-webkit-transform:scale(.9);transform:scale(.9)}to{-webkit-transform:scale(1);transform:scale(1)}}.header-box[data-v-99a59cfe]{background:#1a1a1a;background-image:linear-gradient(#000,#121212);width:100%}header[data-v-99a59cfe]{height:100px;z-index:30;position:relative}.w-box[data-v-99a59cfe]{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.w-box[data-v-99a59cfe],.w-box h1[data-v-99a59cfe]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%}.w-box h1>a[data-v-99a59cfe]{background:url(/static/images/global-logo-red@2x.png) no-repeat 50%;background-size:cover;display:block;width:50px;height:40px;text-indent:-9999px;background-position:0 0}.w-box .nav-list[data-v-99a59cfe]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin-right:22px}.w-box .nav-list .el-autocomplete[data-v-99a59cfe]{width:20vw}.w-box .nav-list a[data-v-99a59cfe]{width:110px;color:#c8c8c8;display:block;font-size:14px;padding:0 25px}.w-box .nav-list a[data-v-99a59cfe]:hover{color:#fff}.w-box .nav-list a[data-v-99a59cfe]:nth-child(2){margin-left:-10px}.w-box .nav-aside[data-v-99a59cfe]{position:relative}.w-box .nav-aside[data-v-99a59cfe]:before{background:#333;background:hsla(0,0%,100%,.2);content:\" \";width:1px;height:13px;overflow:hidden;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;left:0}.w-box .nav-aside.fixed[data-v-99a59cfe]{width:262px;position:fixed;left:50%;top:19px;margin-left:451px;margin-top:0;z-index:32;top:-40px;-webkit-transform:translate3d(0,59px,0);transform:translate3d(0,59px,0);transition:-webkit-transform .3s cubic-bezier(.165,.84,.44,1);transition:transform .3s cubic-bezier(.165,.84,.44,1);transition:transform .3s cubic-bezier(.165,.84,.44,1),-webkit-transform .3s cubic-bezier(.165,.84,.44,1)}.w-box .nav-aside.fixed .user:hover a[data-v-99a59cfe]:before{background-position:-215px 0}.w-box .nav-aside.fixed .shop:hover a[data-v-99a59cfe]:before{background-position:-210px -22px}.w-box .nav-aside[data-v-99a59cfe],.w-box .right-box[data-v-99a59cfe]{display:-webkit-box;display:-ms-flexbox;display:flex}.w-box .nav-aside[data-v-99a59cfe]{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.w-box .user[data-v-99a59cfe]{margin-left:41px;width:36px}.w-box .user:hover a[data-v-99a59cfe]:before{background-position:-5px 0}.w-box .user:hover .nav-user-wrapper[data-v-99a59cfe]{top:18px;visibility:visible;opacity:1;transition:opacity .15s ease-out}.w-box .user>a[data-v-99a59cfe]{position:relative;width:36px;height:20px;display:block;text-indent:-9999px}.w-box .user>a[data-v-99a59cfe]:before{content:\" \";position:absolute;left:8px;top:0;width:20px;height:20px;background:url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) -155px 0;background-size:240px 107px;transition:none}.w-box .user li+li[data-v-99a59cfe]{text-align:center;position:relative;border-top:1px solid #f5f5f5;line-height:44px;height:44px;color:#616161;font-size:12px}.w-box .user li+li[data-v-99a59cfe]:hover{background:#fafafa}.w-box .user li+li a[data-v-99a59cfe]{display:block;color:#616161}.w-box .user .nav-user-avatar>div[data-v-99a59cfe]{position:relative;margin:0 auto 8px;width:46px;height:46px;text-align:center}.w-box .user .nav-user-avatar>div[data-v-99a59cfe]:before{content:\"\";position:absolute;left:0;right:0;top:0;bottom:0;border-radius:50%;box-shadow:inset 0 0 0 1px rgba(0,0,0,.06)}.w-box .user .nav-user-avatar>div .avatar[data-v-99a59cfe]{border-radius:50%;display:block;width:100%;height:100%;background-repeat:no-repeat;background-size:contain}.w-box .user .nav-user-avatar .name[data-v-99a59cfe]{margin-bottom:16px;font-size:12px;line-height:1.5;text-align:center;color:#757575}.w-box .user .nav-user-wrapper[data-v-99a59cfe]{width:168px;-webkit-transform:translate(-50%);transform:translate(-50%);left:50%}.w-box .user .nav-user-list[data-v-99a59cfe]{width:168px}.w-box .user .nav-user-list[data-v-99a59cfe]:before{left:50%}.w-box .shop[data-v-99a59cfe]{position:relative;float:left;margin-left:21px;width:61px;z-index:99}.w-box .shop:hover a[data-v-99a59cfe]:before{content:\" \";background-position:0 -22px}.w-box .shop .nav-user-wrapper.active[data-v-99a59cfe]{top:18px;visibility:visible;opacity:1;transition:opacity .15s ease-out}.w-box .shop>a[data-v-99a59cfe]{position:absolute;left:0;top:0;bottom:0;display:block;right:0;z-index:1}.w-box .shop>a[data-v-99a59cfe]:before{display:block;width:30px;height:100%;content:\" \";background:url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) 0 -22px;background-size:240px 107px;background-position:-150px -22px}.w-box .shop .cart-num[data-v-99a59cfe]{position:relative;display:block;margin-left:31px;margin-top:-1px;min-width:30px;text-indent:0;line-height:20px}.w-box .shop .cart-num>i[data-v-99a59cfe]{background:#eb746b;background-image:linear-gradient(#eb746b,#e25147);box-shadow:inset 0 0 1px hsla(0,0%,100%,.15),0 1px 2px hsla(0,0%,100%,.15);text-align:center;font-style:normal;display:inline-block;width:20px;height:20px;line-height:20px;border-radius:10px;color:#fff;font-size:12px}.w-box .shop .cart-num>i.no[data-v-99a59cfe]{background:#969696;background-image:linear-gradient(#a4a4a4,#909090);box-shadow:inset 0 0 1px #838383,0 1px 2px #838383}.w-box .shop .nav-user-wrapper[data-v-99a59cfe]{right:0;width:360px}.w-box .shop .nav-user-wrapper .nav-user-list[data-v-99a59cfe]:before{right:34px}.w-box .shop .nav-user-list[data-v-99a59cfe]{padding:0;width:100%}.w-box .shop .nav-user-list .full[data-v-99a59cfe]{border-radius:8px;overflow:hidden}.w-box .shop .nav-user-list .nav-cart-items[data-v-99a59cfe]{max-height:363px;overflow-x:hidden;overflow-y:auto}.w-box .shop .nav-user-list .cart-item[data-v-99a59cfe]{height:120px;width:100%;overflow:hidden;border-top:1px solid #f0f0f0}.w-box .shop .nav-user-list .cart-item[data-v-99a59cfe]:hover{background:#fcfcfc}.w-box .shop .nav-user-list .cart-item:hover .del[data-v-99a59cfe]{display:block}.w-box .shop .nav-user-list li:first-child .cart-item[data-v-99a59cfe]:first-child{border-top:none;border-radius:8px 8px 0 0;overflow:hidden}.w-box .shop .nav-user-list .cart-item-inner[data-v-99a59cfe]{padding:20px;position:relative}.w-box .shop .nav-user-list .item-thumb[data-v-99a59cfe]{position:relative;float:left;width:80px;height:80px;border-radius:3px}.w-box .shop .nav-user-list .item-thumb[data-v-99a59cfe]:before{content:\"\";position:absolute;left:0;right:0;top:0;bottom:0;z-index:2;border:1px solid #f0f0f0;border:0 solid transparent;box-shadow:inset 0 0 0 1px rgba(0,0,0,.06);border-radius:3px}.w-box .shop .nav-user-list .item-thumb img[data-v-99a59cfe]{display:block;width:80px;height:80px;border-radius:3px;overflow:hidden}.w-box .shop .nav-user-list .item-desc[data-v-99a59cfe]{margin-left:98px;display:table;width:205px;height:80px}.w-box .shop .nav-user-list .item-desc h4[data-v-99a59cfe]{color:#000;width:185px;overflow:hidden;word-break:keep-all;white-space:nowrap;text-overflow:ellipsis;font-size:14px;line-height:16px;margin-bottom:10px}.w-box .shop .nav-user-list .item-desc .attrs span[data-v-99a59cfe]{position:relative;display:inline-block;margin-right:20px;font-size:14px;line-height:14px;color:#999}.w-box .shop .nav-user-list .item-desc .attrs span[data-v-99a59cfe]:last-child{margin-right:0}.w-box .shop .nav-user-list .item-desc h6[data-v-99a59cfe]{color:#cacaca;font-size:12px;line-height:14px;margin-top:20px}.w-box .shop .nav-user-list .item-desc h6 span[data-v-99a59cfe]{display:inline-block;font-weight:700;color:#cacaca}.w-box .shop .nav-user-list .item-desc h6 .price-icon[data-v-99a59cfe],.w-box .shop .nav-user-list .item-desc h6 .price-num[data-v-99a59cfe]{color:#d44d44}.w-box .shop .nav-user-list .item-desc h6 .price-num[data-v-99a59cfe]{margin-left:5px;font-size:14px}.w-box .shop .nav-user-list .item-desc h6 .item-num[data-v-99a59cfe]{margin-left:10px}.w-box .shop .nav-user-list .cart-cell[data-v-99a59cfe]{display:table-cell;vertical-align:middle}.w-box .shop .nav-user-list .del[data-v-99a59cfe]{display:none;overflow:hidden;position:absolute;right:20px;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.w-box .shop .nav-cart-total[data-v-99a59cfe]{box-sizing:content-box;position:relative;padding:20px;height:40px;background:#fafafa;border-top:1px solid #f0f0f0;border-radius:0 0 8px 8px;box-shadow:inset 0 -1px 0 hsla(0,0%,100%,.5),0 -3px 8px rgba(0,0,0,.04);background:linear-gradient(#fafafa,#f5f5f5)}.w-box .shop .nav-cart-total p[data-v-99a59cfe]{margin-bottom:4px;line-height:16px;font-size:12px;color:#c1c1c1}.w-box .shop .nav-cart-total h5[data-v-99a59cfe]{line-height:20px;font-size:14px;color:#6f6f6f}.w-box .shop .nav-cart-total h5 span[data-v-99a59cfe]{font-size:18px;color:#de4037;display:inline-block;font-weight:700}.w-box .shop .nav-cart-total h5 span[data-v-99a59cfe]:first-child{font-size:12px;margin-right:5px}.w-box .shop .nav-cart-total h6[data-v-99a59cfe]{position:absolute;right:20px;top:20px;width:108px}@media (max-height:780px){.nav-cart-items[data-v-99a59cfe]{max-height:423px!important}}@media (max-height:900px){.nav-cart-items[data-v-99a59cfe]{max-height:544px!important}}@media (max-height:1080px){.nav-cart-items[data-v-99a59cfe]{max-height:620px!important}}.nav-user-wrapper[data-v-99a59cfe]{position:absolute;z-index:30;padding-top:18px;opacity:0;visibility:hidden;top:-3000px}.nav-user-wrapper .nav-user-list[data-v-99a59cfe]{position:relative;padding-top:20px;background:#fff;border:1px solid #d6d6d6;border-color:rgba(0,0,0,.08);border-radius:8px;box-shadow:0 20px 40px rgba(0,0,0,.15);z-index:10}.nav-user-wrapper .nav-user-list[data-v-99a59cfe]:before{position:absolute;content:\" \";background:url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) no-repeat -49px -43px;background-size:240px 107px;width:20px;height:8px;top:-8px;margin-left:-10px}.nav-sub[data-v-99a59cfe]{position:relative;z-index:20;height:90px;background:#f7f7f7;box-shadow:0 2px 4px rgba(0,0,0,.04)}.nav-sub.fixed[data-v-99a59cfe]{position:fixed;z-index:21;height:60px;top:0;left:0;right:0;border-bottom:1px solid #dadada;background-image:linear-gradient(#fff,#f1f1f1)}.nav-sub .nav-sub-wrapper[data-v-99a59cfe]{padding:31px 0;height:90px;position:relative}.nav-sub .nav-sub-wrapper.fixed[data-v-99a59cfe]{padding:0;height:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.nav-sub .nav-sub-wrapper[data-v-99a59cfe]:after{content:\" \";position:absolute;top:89px;left:50%;margin-left:-610px;width:1220px;background:#000;height:1px;display:none;opacity:0;transition:opacity .3s ease-in}.nav-sub .w[data-v-99a59cfe]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.nav-sub .nav-list2[data-v-99a59cfe]{height:28px;line-height:28px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%}.nav-sub .nav-list2 li[data-v-99a59cfe]:first-child{padding-left:0}.nav-sub .nav-list2 li:first-child a[data-v-99a59cfe]{padding-left:10px}.nav-sub .nav-list2 li[data-v-99a59cfe]{position:relative;float:left;padding-left:2px}.nav-sub .nav-list2 li a[data-v-99a59cfe]{display:block;padding:0 10px;color:#666}.nav-sub .nav-list2 li a.active[data-v-99a59cfe]{font-weight:700}.nav-sub .nav-list2 li a[data-v-99a59cfe]:hover{color:#5683ea}.nav-sub .nav-list2 li[data-v-99a59cfe]:before{content:\" \";position:absolute;left:0;top:13px;width:2px;height:2px;background:#bdbdbd}@media (min-width:1px){.nav-sub .nav-sub-wrapper[data-v-99a59cfe]:after{display:block}}.cart-con[data-v-99a59cfe]{text-align:center;position:relative}.cart-con p[data-v-99a59cfe]{padding-top:185px;color:#333;font-size:16px}.cart-con[data-v-99a59cfe]:before{position:absolute;content:\" \";left:50%;-webkit-transform:translate(-50%,-70%);transform:translate(-50%,-70%);top:50%;width:76px;height:62px;background:url(\"/static/images/cart-empty-new.png\") no-repeat;background-size:cover}',\"\",{version:3,sources:[\"D:/桌面/YMall-front/src/common/header.vue\"],names:[],mappings:\"AACA,+BACE,yDAA0D,AAClD,gDAAkD,CAC3D,AACD,kCACA,GACI,2BAA4B,AACpB,kBAAoB,CAC/B,AACD,IACI,4BAA8B,AACtB,mBAAsB,CACjC,AACD,IACI,6BAA8B,AACtB,oBAAsB,CACjC,AACD,IACI,4BAA8B,AACtB,mBAAsB,CACjC,AACD,GACI,2BAA4B,AACpB,kBAAoB,CAC/B,CACA,AACD,0BACA,GACI,2BAA4B,AACpB,kBAAoB,CAC/B,AACD,IACI,4BAA8B,AACtB,mBAAsB,CACjC,AACD,IACI,6BAA8B,AACtB,oBAAsB,CACjC,AACD,IACI,4BAA8B,AACtB,mBAAsB,CACjC,AACD,GACI,2BAA4B,AACpB,kBAAoB,CAC/B,CACA,AACD,6BACE,mBAAoB,AACpB,+CAAiD,AACjD,UAAY,CACb,AACD,wBACE,aAAc,AACd,WAAY,AACZ,iBAAmB,CACpB,AACD,wBAIE,yBAA0B,AACtB,sBAAuB,AACnB,6BAA+B,CAKxC,AACD,mDAXE,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AAId,yBAA0B,AACtB,sBAAuB,AACnB,mBAAoB,AAC5B,WAAa,CAUd,AACD,6BACM,oEAAqE,AACrE,sBAAuB,AACvB,cAAe,AACf,WAAY,AACZ,YAAa,AACb,oBAAqB,AACrB,uBAAyB,CAC9B,AACD,kCACI,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,wBAAyB,AACrB,qBAAsB,AAClB,uBAAwB,AAChC,yBAA0B,AACtB,sBAAuB,AACnB,mBAAoB,AAC5B,iBAAmB,CACtB,AACD,mDACM,UAAY,CACjB,AACD,oCACM,YAAa,AACb,cAAe,AACf,cAAe,AACf,eAAgB,AAChB,cAAgB,CACrB,AACD,0CACQ,UAAY,CACnB,AACD,iDACM,iBAAmB,CACxB,AACD,mCACI,iBAAmB,CACtB,AACD,0CACM,gBAAiB,AACjB,8BAAqC,AACrC,YAAa,AACb,UAAW,AACX,YAAa,AACb,gBAAiB,AACjB,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,yBAA0B,AACtB,sBAAuB,AACnB,mBAAoB,AAC5B,MAAQ,CACb,AACD,yCACM,YAAa,AACb,eAAgB,AAChB,SAAU,AACV,SAAU,AACV,kBAAmB,AACnB,aAAc,AACd,WAAY,AACZ,UAAW,AACX,wCAA2C,AAC3C,gCAAmC,AACnC,8DAAsE,AACtE,sDAA8D,AAC9D,wGAAyH,CAC9H,AACD,8DACQ,4BAA8B,CACrC,AACD,8DACQ,gCAAkC,CACzC,AAMD,sEAJI,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CASjB,AAPD,mCAII,yBAA0B,AACtB,sBAAuB,AACnB,kBAAoB,CAC/B,AACD,8BACI,iBAAkB,AAClB,UAAY,CACf,AACD,6CACM,0BAA4B,CACjC,AACD,sDACM,SAAU,AACV,mBAAoB,AACpB,UAAW,AACX,gCAAkC,CACvC,AACD,gCACM,kBAAmB,AACnB,WAAY,AACZ,YAAa,AACb,cAAe,AACf,mBAAqB,CAC1B,AACD,uCACQ,YAAa,AACb,kBAAmB,AACnB,SAAU,AACV,MAAO,AACP,WAAY,AACZ,YAAa,AACb,6FAA8F,AAC9F,4BAA6B,AAC7B,eAAiB,CACxB,AACD,oCACM,kBAAmB,AACnB,kBAAmB,AACnB,6BAA8B,AAC9B,iBAAkB,AAClB,YAAa,AACb,cAAe,AACf,cAAgB,CACrB,AACD,0CACQ,kBAAoB,CAC3B,AACD,sCACQ,cAAe,AACf,aAAe,CACtB,AACD,mDACM,kBAAmB,AACnB,kBAAmB,AACnB,WAAY,AACZ,YAAa,AACb,iBAAmB,CACxB,AACD,0DACQ,WAAY,AACZ,kBAAmB,AACnB,OAAQ,AACR,QAAS,AACT,MAAO,AACP,SAAU,AACV,kBAAmB,AACnB,0CAAgD,CACvD,AACD,2DACQ,kBAAmB,AACnB,cAAe,AACf,WAAY,AACZ,YAAa,AACb,4BAA6B,AAC7B,uBAAyB,CAChC,AACD,qDACM,mBAAoB,AACpB,eAAgB,AAChB,gBAAiB,AACjB,kBAAmB,AACnB,aAAe,CACpB,AACD,gDACM,YAAa,AACb,kCAAmC,AAC3B,0BAA2B,AACnC,QAAU,CACf,AACD,6CACM,WAAa,CAClB,AACD,oDACQ,QAAU,CACjB,AACD,8BACI,kBAAmB,AACnB,WAAY,AACZ,iBAAkB,AAClB,WAAY,AACZ,UAAY,CACf,AACD,6CACM,YAAa,AACb,2BAA6B,CAClC,AACD,uDACM,SAAU,AACV,mBAAoB,AACpB,UAAW,AACX,gCAAkC,CACvC,AACD,gCACM,kBAAmB,AACnB,OAAQ,AACR,MAAO,AACP,SAAU,AACV,cAAe,AACf,QAAS,AACT,SAAW,CAChB,AACD,uCACQ,cAAe,AACf,WAAY,AACZ,YAAa,AACb,YAAa,AACb,4FAA6F,AAC7F,4BAA6B,AAC7B,gCAAkC,CACzC,AACD,wCACM,kBAAmB,AACnB,cAAe,AACf,iBAAkB,AAClB,gBAAiB,AACjB,eAAgB,AAChB,cAAe,AACf,gBAAkB,CACvB,AACD,0CACQ,mBAAoB,AACpB,kDAAoD,AACpD,2EAAyF,AACzF,kBAAmB,AACnB,kBAAmB,AACnB,qBAAsB,AACtB,WAAY,AACZ,YAAa,AACb,iBAAkB,AAClB,mBAAoB,AACpB,WAAY,AACZ,cAAgB,CACvB,AACD,6CACU,mBAAoB,AACpB,kDAAoD,AACpD,kDAAqD,CAC9D,AACD,gDACM,QAAS,AACT,WAAa,CAClB,AACD,sEACQ,UAAY,CACnB,AACD,6CACM,UAAW,AACX,UAAY,CACjB,AACD,mDACQ,kBAAmB,AACnB,eAAiB,CACxB,AACD,6DACQ,iBAAkB,AAClB,kBAAmB,AACnB,eAAiB,CACxB,AACD,wDACQ,aAAc,AACd,WAAY,AACZ,gBAAiB,AACjB,4BAA8B,CACrC,AACD,8DACU,kBAAoB,CAC7B,AACD,mEACY,aAAe,CAC1B,AACD,mFACQ,gBAAiB,AACjB,0BAA2B,AAC3B,eAAiB,CACxB,AACD,8DACQ,aAAc,AACd,iBAAmB,CAC1B,AACD,yDACQ,kBAAmB,AACnB,WAAY,AACZ,WAAY,AACZ,YAAa,AACb,iBAAmB,CAC1B,AACD,gEACU,WAAY,AACZ,kBAAmB,AACnB,OAAQ,AACR,QAAS,AACT,MAAO,AACP,SAAU,AACV,UAAW,AACX,yBAA0B,AAC1B,2BAA4B,AAC5B,2CAAgD,AAChD,iBAAmB,CAC5B,AACD,6DACU,cAAe,AACf,WAAY,AACZ,YAAa,AACb,kBAAmB,AACnB,eAAiB,CAC1B,AACD,wDACQ,iBAAkB,AAClB,cAAe,AACf,YAAa,AACb,WAAa,CACpB,AACD,2DACU,WAAY,AACZ,YAAa,AACb,gBAAiB,AACjB,oBAAqB,AACrB,mBAAoB,AACpB,uBAAwB,AACxB,eAAgB,AAChB,iBAAkB,AAClB,kBAAoB,CAC7B,AACD,oEACU,kBAAmB,AACnB,qBAAsB,AACtB,kBAAmB,AACnB,eAAgB,AAChB,iBAAkB,AAClB,UAAY,CACrB,AACD,+EACU,cAAgB,CACzB,AACD,2DACU,cAAe,AACf,eAAgB,AAChB,iBAAkB,AAClB,eAAiB,CAC1B,AACD,gEACY,qBAAsB,AACtB,gBAAiB,AACjB,aAAe,CAC1B,AACD,6IACY,aAAe,CAC1B,AACD,sEACY,gBAAiB,AACjB,cAAgB,CAC3B,AACD,qEACY,gBAAkB,CAC7B,AACD,wDACQ,mBAAoB,AACpB,qBAAuB,CAC9B,AACD,kDACQ,aAAc,AACd,gBAAiB,AACjB,kBAAmB,AACnB,WAAY,AACZ,QAAS,AACT,mCAAoC,AAC5B,0BAA4B,CAC3C,AACD,8CACM,uBAAwB,AACxB,kBAAmB,AACnB,aAAc,AACd,YAAa,AACb,mBAAoB,AACpB,6BAA8B,AAC9B,0BAA2B,AAC3B,wEAAoF,AACpF,2CAA8C,CACnD,AACD,gDACQ,kBAAmB,AACnB,iBAAkB,AAClB,eAAgB,AAChB,aAAe,CACtB,AACD,iDACQ,iBAAkB,AAClB,eAAgB,AAChB,aAAe,CACtB,AACD,sDACU,eAAgB,AAChB,cAAe,AACf,qBAAsB,AACtB,eAAiB,CAC1B,AACD,kEACU,eAAgB,AAChB,gBAAkB,CAC3B,AACD,iDACQ,kBAAmB,AACnB,WAAY,AACZ,SAAU,AACV,WAAa,CACpB,AACD,0BACA,iCACI,0BAA6B,CAChC,CACA,AACD,0BACA,iCACI,0BAA6B,CAChC,CACA,AACD,2BACA,iCACI,0BAA6B,CAChC,CACA,AACD,mCACE,kBAAmB,AACnB,WAAY,AACZ,iBAAkB,AAClB,UAAW,AACX,kBAAmB,AACnB,WAAa,CACd,AACD,kDACI,kBAAmB,AACnB,iBAAkB,AAClB,gBAAiB,AACjB,yBAA0B,AAC1B,6BAAkC,AAClC,kBAAmB,AACnB,uCAA4C,AAC5C,UAAY,CACf,AACD,yDACM,kBAAmB,AACnB,YAAa,AACb,0GAA2G,AAC3G,4BAA6B,AAC7B,WAAY,AACZ,WAAY,AACZ,SAAU,AACV,iBAAmB,CACxB,AACD,0BACE,kBAAmB,AACnB,WAAY,AACZ,YAAa,AACb,mBAAoB,AACpB,oCAA0C,CAC3C,AACD,gCACI,eAAgB,AAChB,WAAY,AACZ,YAAa,AACb,MAAO,AACP,OAAQ,AACR,QAAS,AACT,gCAAiC,AACjC,8CAAiD,CACpD,AACD,2CACI,eAAgB,AAChB,YAAa,AACb,iBAAmB,CACtB,AACD,iDACM,UAAW,AACX,YAAa,AACb,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,yBAA0B,AACtB,sBAAuB,AACnB,kBAAoB,CACjC,AACD,iDACM,YAAa,AACb,kBAAmB,AACnB,SAAU,AACV,SAAU,AACV,mBAAoB,AACpB,aAAc,AACd,gBAAiB,AACjB,WAAY,AACZ,aAAc,AACd,UAAW,AACX,8BAAgC,CACrC,AACD,6BACI,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,yBAA0B,AACtB,sBAAuB,AACnB,6BAA+B,CAC1C,AACD,qCACI,YAAa,AACb,iBAAkB,AAClB,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,yBAA0B,AACtB,sBAAuB,AACnB,mBAAoB,AAC5B,WAAa,CAChB,AACD,oDACM,cAAgB,CACrB,AACD,sDACQ,iBAAmB,CAC1B,AACD,wCACM,kBAAmB,AACnB,WAAY,AACZ,gBAAkB,CACvB,AACD,0CACQ,cAAe,AACf,eAAgB,AAChB,UAAY,CACnB,AACD,iDACU,eAAkB,CAC3B,AACD,gDACQ,aAAe,CACtB,AACD,+CACM,YAAa,AACb,kBAAmB,AACnB,OAAQ,AACR,SAAU,AACV,UAAW,AACX,WAAY,AACZ,kBAAoB,CACzB,AACD,uBACA,iDACI,aAAe,CAClB,CACA,AACD,2BAEE,kBAAmB,AACnB,iBAAmB,CACpB,AACD,6BACI,kBAAmB,AACnB,WAAe,AACf,cAAgB,CACnB,AACD,kCACE,kBAAmB,AACnB,YAAa,AACb,SAAU,AACV,uCAAyC,AACjC,+BAAiC,AACzC,QAAS,AACT,WAAY,AACZ,YAAa,AACb,8DAA+D,AAC/D,qBAAuB,CACxB\",file:\"header.vue\",sourcesContent:['\\n.move_in_cart[data-v-99a59cfe] {\\n  -webkit-animation: mymove-data-v-99a59cfe .5s ease-in-out;\\n          animation: mymove-data-v-99a59cfe .5s ease-in-out;\\n}\\n@keyframes mymove-data-v-99a59cfe {\\n0% {\\n    -webkit-transform: scale(1);\\n            transform: scale(1);\\n}\\n25% {\\n    -webkit-transform: scale(0.8);\\n            transform: scale(0.8);\\n}\\n50% {\\n    -webkit-transform: scale(1.2);\\n            transform: scale(1.2);\\n}\\n75% {\\n    -webkit-transform: scale(0.9);\\n            transform: scale(0.9);\\n}\\n100% {\\n    -webkit-transform: scale(1);\\n            transform: scale(1);\\n}\\n}\\n@-webkit-keyframes mymove {\\n0% {\\n    -webkit-transform: scale(1);\\n            transform: scale(1);\\n}\\n25% {\\n    -webkit-transform: scale(0.8);\\n            transform: scale(0.8);\\n}\\n50% {\\n    -webkit-transform: scale(1.2);\\n            transform: scale(1.2);\\n}\\n75% {\\n    -webkit-transform: scale(0.9);\\n            transform: scale(0.9);\\n}\\n100% {\\n    -webkit-transform: scale(1);\\n            transform: scale(1);\\n}\\n}\\n.header-box[data-v-99a59cfe] {\\n  background: #1a1a1a;\\n  background-image: linear-gradient(#000, #121212);\\n  width: 100%;\\n}\\nheader[data-v-99a59cfe] {\\n  height: 100px;\\n  z-index: 30;\\n  position: relative;\\n}\\n.w-box[data-v-99a59cfe] {\\n  display: -webkit-box;\\n  display: -ms-flexbox;\\n  display: flex;\\n  -webkit-box-pack: justify;\\n      -ms-flex-pack: justify;\\n          justify-content: space-between;\\n  -webkit-box-align: center;\\n      -ms-flex-align: center;\\n          align-items: center;\\n  height: 100%;\\n}\\n.w-box h1[data-v-99a59cfe] {\\n    height: 100%;\\n    display: -webkit-box;\\n    display: -ms-flexbox;\\n    display: flex;\\n    -webkit-box-align: center;\\n        -ms-flex-align: center;\\n            align-items: center;\\n}\\n.w-box h1 > a[data-v-99a59cfe] {\\n      background: url(/static/images/global-logo-red@2x.png) no-repeat 50%;\\n      background-size: cover;\\n      display: block;\\n      width: 50px;\\n      height: 40px;\\n      text-indent: -9999px;\\n      background-position: 0 0;\\n}\\n.w-box .nav-list[data-v-99a59cfe] {\\n    display: -webkit-box;\\n    display: -ms-flexbox;\\n    display: flex;\\n    -webkit-box-pack: center;\\n        -ms-flex-pack: center;\\n            justify-content: center;\\n    -webkit-box-align: center;\\n        -ms-flex-align: center;\\n            align-items: center;\\n    margin-right: 22px;\\n}\\n.w-box .nav-list .el-autocomplete[data-v-99a59cfe] {\\n      width: 20vw;\\n}\\n.w-box .nav-list a[data-v-99a59cfe] {\\n      width: 110px;\\n      color: #c8c8c8;\\n      display: block;\\n      font-size: 14px;\\n      padding: 0 25px;\\n}\\n.w-box .nav-list a[data-v-99a59cfe]:hover {\\n        color: #fff;\\n}\\n.w-box .nav-list a[data-v-99a59cfe]:nth-child(2) {\\n      margin-left: -10px;\\n}\\n.w-box .nav-aside[data-v-99a59cfe] {\\n    position: relative;\\n}\\n.w-box .nav-aside[data-v-99a59cfe]:before {\\n      background: #333;\\n      background: rgba(255, 255, 255, 0.2);\\n      content: \" \";\\n      width: 1px;\\n      height: 13px;\\n      overflow: hidden;\\n      display: -webkit-box;\\n      display: -ms-flexbox;\\n      display: flex;\\n      -webkit-box-align: center;\\n          -ms-flex-align: center;\\n              align-items: center;\\n      left: 0;\\n}\\n.w-box .nav-aside.fixed[data-v-99a59cfe] {\\n      width: 262px;\\n      position: fixed;\\n      left: 50%;\\n      top: 19px;\\n      margin-left: 451px;\\n      margin-top: 0;\\n      z-index: 32;\\n      top: -40px;\\n      -webkit-transform: translate3d(0, 59px, 0);\\n      transform: translate3d(0, 59px, 0);\\n      transition: -webkit-transform 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);\\n      transition: transform 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);\\n      transition: transform 0.3s cubic-bezier(0.165, 0.84, 0.44, 1), -webkit-transform 0.3s cubic-bezier(0.165, 0.84, 0.44, 1);\\n}\\n.w-box .nav-aside.fixed .user:hover a[data-v-99a59cfe]:before {\\n        background-position: -215px 0;\\n}\\n.w-box .nav-aside.fixed .shop:hover a[data-v-99a59cfe]:before {\\n        background-position: -210px -22px;\\n}\\n.w-box .right-box[data-v-99a59cfe] {\\n    display: -webkit-box;\\n    display: -ms-flexbox;\\n    display: flex;\\n}\\n.w-box .nav-aside[data-v-99a59cfe] {\\n    display: -webkit-box;\\n    display: -ms-flexbox;\\n    display: flex;\\n    -webkit-box-align: center;\\n        -ms-flex-align: center;\\n            align-items: center;\\n}\\n.w-box .user[data-v-99a59cfe] {\\n    margin-left: 41px;\\n    width: 36px;\\n}\\n.w-box .user:hover a[data-v-99a59cfe]:before {\\n      background-position: -5px 0;\\n}\\n.w-box .user:hover .nav-user-wrapper[data-v-99a59cfe] {\\n      top: 18px;\\n      visibility: visible;\\n      opacity: 1;\\n      transition: opacity .15s ease-out;\\n}\\n.w-box .user > a[data-v-99a59cfe] {\\n      position: relative;\\n      width: 36px;\\n      height: 20px;\\n      display: block;\\n      text-indent: -9999px;\\n}\\n.w-box .user > a[data-v-99a59cfe]:before {\\n        content: \" \";\\n        position: absolute;\\n        left: 8px;\\n        top: 0;\\n        width: 20px;\\n        height: 20px;\\n        background: url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) -155px 0;\\n        background-size: 240px 107px;\\n        transition: none;\\n}\\n.w-box .user li + li[data-v-99a59cfe] {\\n      text-align: center;\\n      position: relative;\\n      border-top: 1px solid #f5f5f5;\\n      line-height: 44px;\\n      height: 44px;\\n      color: #616161;\\n      font-size: 12px;\\n}\\n.w-box .user li + li[data-v-99a59cfe]:hover {\\n        background: #fafafa;\\n}\\n.w-box .user li + li a[data-v-99a59cfe] {\\n        display: block;\\n        color: #616161;\\n}\\n.w-box .user .nav-user-avatar > div[data-v-99a59cfe] {\\n      position: relative;\\n      margin: 0 auto 8px;\\n      width: 46px;\\n      height: 46px;\\n      text-align: center;\\n}\\n.w-box .user .nav-user-avatar > div[data-v-99a59cfe]:before {\\n        content: \"\";\\n        position: absolute;\\n        left: 0;\\n        right: 0;\\n        top: 0;\\n        bottom: 0;\\n        border-radius: 50%;\\n        box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);\\n}\\n.w-box .user .nav-user-avatar > div .avatar[data-v-99a59cfe] {\\n        border-radius: 50%;\\n        display: block;\\n        width: 100%;\\n        height: 100%;\\n        background-repeat: no-repeat;\\n        background-size: contain;\\n}\\n.w-box .user .nav-user-avatar .name[data-v-99a59cfe] {\\n      margin-bottom: 16px;\\n      font-size: 12px;\\n      line-height: 1.5;\\n      text-align: center;\\n      color: #757575;\\n}\\n.w-box .user .nav-user-wrapper[data-v-99a59cfe] {\\n      width: 168px;\\n      -webkit-transform: translate(-50%);\\n              transform: translate(-50%);\\n      left: 50%;\\n}\\n.w-box .user .nav-user-list[data-v-99a59cfe] {\\n      width: 168px;\\n}\\n.w-box .user .nav-user-list[data-v-99a59cfe]:before {\\n        left: 50%;\\n}\\n.w-box .shop[data-v-99a59cfe] {\\n    position: relative;\\n    float: left;\\n    margin-left: 21px;\\n    width: 61px;\\n    z-index: 99;\\n}\\n.w-box .shop:hover a[data-v-99a59cfe]:before {\\n      content: \" \";\\n      background-position: 0 -22px;\\n}\\n.w-box .shop .nav-user-wrapper.active[data-v-99a59cfe] {\\n      top: 18px;\\n      visibility: visible;\\n      opacity: 1;\\n      transition: opacity .15s ease-out;\\n}\\n.w-box .shop > a[data-v-99a59cfe] {\\n      position: absolute;\\n      left: 0;\\n      top: 0;\\n      bottom: 0;\\n      display: block;\\n      right: 0;\\n      z-index: 1;\\n}\\n.w-box .shop > a[data-v-99a59cfe]:before {\\n        display: block;\\n        width: 30px;\\n        height: 100%;\\n        content: \" \";\\n        background: url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) 0 -22px;\\n        background-size: 240px 107px;\\n        background-position: -150px -22px;\\n}\\n.w-box .shop .cart-num[data-v-99a59cfe] {\\n      position: relative;\\n      display: block;\\n      margin-left: 31px;\\n      margin-top: -1px;\\n      min-width: 30px;\\n      text-indent: 0;\\n      line-height: 20px;\\n}\\n.w-box .shop .cart-num > i[data-v-99a59cfe] {\\n        background: #eb746b;\\n        background-image: linear-gradient(#eb746b, #e25147);\\n        box-shadow: inset 0 0 1px rgba(255, 255, 255, 0.15), 0 1px 2px rgba(255, 255, 255, 0.15);\\n        text-align: center;\\n        font-style: normal;\\n        display: inline-block;\\n        width: 20px;\\n        height: 20px;\\n        line-height: 20px;\\n        border-radius: 10px;\\n        color: #fff;\\n        font-size: 12px;\\n}\\n.w-box .shop .cart-num > i.no[data-v-99a59cfe] {\\n          background: #969696;\\n          background-image: linear-gradient(#A4A4A4, #909090);\\n          box-shadow: inset 0 0 1px #838383, 0 1px 2px #838383;\\n}\\n.w-box .shop .nav-user-wrapper[data-v-99a59cfe] {\\n      right: 0;\\n      width: 360px;\\n}\\n.w-box .shop .nav-user-wrapper .nav-user-list[data-v-99a59cfe]:before {\\n        right: 34px;\\n}\\n.w-box .shop .nav-user-list[data-v-99a59cfe] {\\n      padding: 0;\\n      width: 100%;\\n}\\n.w-box .shop .nav-user-list .full[data-v-99a59cfe] {\\n        border-radius: 8px;\\n        overflow: hidden;\\n}\\n.w-box .shop .nav-user-list .nav-cart-items[data-v-99a59cfe] {\\n        max-height: 363px;\\n        overflow-x: hidden;\\n        overflow-y: auto;\\n}\\n.w-box .shop .nav-user-list .cart-item[data-v-99a59cfe] {\\n        height: 120px;\\n        width: 100%;\\n        overflow: hidden;\\n        border-top: 1px solid #f0f0f0;\\n}\\n.w-box .shop .nav-user-list .cart-item[data-v-99a59cfe]:hover {\\n          background: #fcfcfc;\\n}\\n.w-box .shop .nav-user-list .cart-item:hover .del[data-v-99a59cfe] {\\n            display: block;\\n}\\n.w-box .shop .nav-user-list li:first-child .cart-item[data-v-99a59cfe]:first-child {\\n        border-top: none;\\n        border-radius: 8px 8px 0 0;\\n        overflow: hidden;\\n}\\n.w-box .shop .nav-user-list .cart-item-inner[data-v-99a59cfe] {\\n        padding: 20px;\\n        position: relative;\\n}\\n.w-box .shop .nav-user-list .item-thumb[data-v-99a59cfe] {\\n        position: relative;\\n        float: left;\\n        width: 80px;\\n        height: 80px;\\n        border-radius: 3px;\\n}\\n.w-box .shop .nav-user-list .item-thumb[data-v-99a59cfe]:before {\\n          content: \"\";\\n          position: absolute;\\n          left: 0;\\n          right: 0;\\n          top: 0;\\n          bottom: 0;\\n          z-index: 2;\\n          border: 1px solid #f0f0f0;\\n          border: 0 solid transparent;\\n          box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.06);\\n          border-radius: 3px;\\n}\\n.w-box .shop .nav-user-list .item-thumb img[data-v-99a59cfe] {\\n          display: block;\\n          width: 80px;\\n          height: 80px;\\n          border-radius: 3px;\\n          overflow: hidden;\\n}\\n.w-box .shop .nav-user-list .item-desc[data-v-99a59cfe] {\\n        margin-left: 98px;\\n        display: table;\\n        width: 205px;\\n        height: 80px;\\n}\\n.w-box .shop .nav-user-list .item-desc h4[data-v-99a59cfe] {\\n          color: #000;\\n          width: 185px;\\n          overflow: hidden;\\n          word-break: keep-all;\\n          white-space: nowrap;\\n          text-overflow: ellipsis;\\n          font-size: 14px;\\n          line-height: 16px;\\n          margin-bottom: 10px;\\n}\\n.w-box .shop .nav-user-list .item-desc .attrs span[data-v-99a59cfe] {\\n          position: relative;\\n          display: inline-block;\\n          margin-right: 20px;\\n          font-size: 14px;\\n          line-height: 14px;\\n          color: #999;\\n}\\n.w-box .shop .nav-user-list .item-desc .attrs span[data-v-99a59cfe]:last-child {\\n          margin-right: 0;\\n}\\n.w-box .shop .nav-user-list .item-desc h6[data-v-99a59cfe] {\\n          color: #cacaca;\\n          font-size: 12px;\\n          line-height: 14px;\\n          margin-top: 20px;\\n}\\n.w-box .shop .nav-user-list .item-desc h6 span[data-v-99a59cfe] {\\n            display: inline-block;\\n            font-weight: 700;\\n            color: #cacaca;\\n}\\n.w-box .shop .nav-user-list .item-desc h6 .price-icon[data-v-99a59cfe], .w-box .shop .nav-user-list .item-desc h6 .price-num[data-v-99a59cfe] {\\n            color: #d44d44;\\n}\\n.w-box .shop .nav-user-list .item-desc h6 .price-num[data-v-99a59cfe] {\\n            margin-left: 5px;\\n            font-size: 14px;\\n}\\n.w-box .shop .nav-user-list .item-desc h6 .item-num[data-v-99a59cfe] {\\n            margin-left: 10px;\\n}\\n.w-box .shop .nav-user-list .cart-cell[data-v-99a59cfe] {\\n        display: table-cell;\\n        vertical-align: middle;\\n}\\n.w-box .shop .nav-user-list .del[data-v-99a59cfe] {\\n        display: none;\\n        overflow: hidden;\\n        position: absolute;\\n        right: 20px;\\n        top: 50%;\\n        -webkit-transform: translateY(-50%);\\n                transform: translateY(-50%);\\n}\\n.w-box .shop .nav-cart-total[data-v-99a59cfe] {\\n      box-sizing: content-box;\\n      position: relative;\\n      padding: 20px;\\n      height: 40px;\\n      background: #fafafa;\\n      border-top: 1px solid #f0f0f0;\\n      border-radius: 0 0 8px 8px;\\n      box-shadow: inset 0 -1px 0 rgba(255, 255, 255, 0.5), 0 -3px 8px rgba(0, 0, 0, 0.04);\\n      background: linear-gradient(#fafafa, #f5f5f5);\\n}\\n.w-box .shop .nav-cart-total p[data-v-99a59cfe] {\\n        margin-bottom: 4px;\\n        line-height: 16px;\\n        font-size: 12px;\\n        color: #c1c1c1;\\n}\\n.w-box .shop .nav-cart-total h5[data-v-99a59cfe] {\\n        line-height: 20px;\\n        font-size: 14px;\\n        color: #6f6f6f;\\n}\\n.w-box .shop .nav-cart-total h5 span[data-v-99a59cfe] {\\n          font-size: 18px;\\n          color: #de4037;\\n          display: inline-block;\\n          font-weight: 700;\\n}\\n.w-box .shop .nav-cart-total h5 span[data-v-99a59cfe]:first-child {\\n          font-size: 12px;\\n          margin-right: 5px;\\n}\\n.w-box .shop .nav-cart-total h6[data-v-99a59cfe] {\\n        position: absolute;\\n        right: 20px;\\n        top: 20px;\\n        width: 108px;\\n}\\n@media (max-height: 780px) {\\n.nav-cart-items[data-v-99a59cfe] {\\n    max-height: 423px !important;\\n}\\n}\\n@media (max-height: 900px) {\\n.nav-cart-items[data-v-99a59cfe] {\\n    max-height: 544px !important;\\n}\\n}\\n@media (max-height: 1080px) {\\n.nav-cart-items[data-v-99a59cfe] {\\n    max-height: 620px !important;\\n}\\n}\\n.nav-user-wrapper[data-v-99a59cfe] {\\n  position: absolute;\\n  z-index: 30;\\n  padding-top: 18px;\\n  opacity: 0;\\n  visibility: hidden;\\n  top: -3000px;\\n}\\n.nav-user-wrapper .nav-user-list[data-v-99a59cfe] {\\n    position: relative;\\n    padding-top: 20px;\\n    background: #fff;\\n    border: 1px solid #d6d6d6;\\n    border-color: rgba(0, 0, 0, 0.08);\\n    border-radius: 8px;\\n    box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);\\n    z-index: 10;\\n}\\n.nav-user-wrapper .nav-user-list[data-v-99a59cfe]:before {\\n      position: absolute;\\n      content: \" \";\\n      background: url(/static/images/account-icon@2x.32d87deb02b3d1c3cc5bcff0c26314ac.png) no-repeat -49px -43px;\\n      background-size: 240px 107px;\\n      width: 20px;\\n      height: 8px;\\n      top: -8px;\\n      margin-left: -10px;\\n}\\n.nav-sub[data-v-99a59cfe] {\\n  position: relative;\\n  z-index: 20;\\n  height: 90px;\\n  background: #f7f7f7;\\n  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);\\n}\\n.nav-sub.fixed[data-v-99a59cfe] {\\n    position: fixed;\\n    z-index: 21;\\n    height: 60px;\\n    top: 0;\\n    left: 0;\\n    right: 0;\\n    border-bottom: 1px solid #dadada;\\n    background-image: linear-gradient(#fff, #f1f1f1);\\n}\\n.nav-sub .nav-sub-wrapper[data-v-99a59cfe] {\\n    padding: 31px 0;\\n    height: 90px;\\n    position: relative;\\n}\\n.nav-sub .nav-sub-wrapper.fixed[data-v-99a59cfe] {\\n      padding: 0;\\n      height: 100%;\\n      display: -webkit-box;\\n      display: -ms-flexbox;\\n      display: flex;\\n      -webkit-box-align: center;\\n          -ms-flex-align: center;\\n              align-items: center;\\n}\\n.nav-sub .nav-sub-wrapper[data-v-99a59cfe]:after {\\n      content: \" \";\\n      position: absolute;\\n      top: 89px;\\n      left: 50%;\\n      margin-left: -610px;\\n      width: 1220px;\\n      background: #000;\\n      height: 1px;\\n      display: none;\\n      opacity: 0;\\n      transition: opacity .3s ease-in;\\n}\\n.nav-sub .w[data-v-99a59cfe] {\\n    display: -webkit-box;\\n    display: -ms-flexbox;\\n    display: flex;\\n    -webkit-box-pack: justify;\\n        -ms-flex-pack: justify;\\n            justify-content: space-between;\\n}\\n.nav-sub .nav-list2[data-v-99a59cfe] {\\n    height: 28px;\\n    line-height: 28px;\\n    display: -webkit-box;\\n    display: -ms-flexbox;\\n    display: flex;\\n    -webkit-box-align: center;\\n        -ms-flex-align: center;\\n            align-items: center;\\n    height: 100%;\\n}\\n.nav-sub .nav-list2 li[data-v-99a59cfe]:first-child {\\n      padding-left: 0;\\n}\\n.nav-sub .nav-list2 li:first-child a[data-v-99a59cfe] {\\n        padding-left: 10px;\\n}\\n.nav-sub .nav-list2 li[data-v-99a59cfe] {\\n      position: relative;\\n      float: left;\\n      padding-left: 2px;\\n}\\n.nav-sub .nav-list2 li a[data-v-99a59cfe] {\\n        display: block;\\n        padding: 0 10px;\\n        color: #666;\\n}\\n.nav-sub .nav-list2 li a.active[data-v-99a59cfe] {\\n          font-weight: bold;\\n}\\n.nav-sub .nav-list2 li a[data-v-99a59cfe]:hover {\\n        color: #5683EA;\\n}\\n.nav-sub .nav-list2 li[data-v-99a59cfe]:before {\\n      content: \\' \\';\\n      position: absolute;\\n      left: 0;\\n      top: 13px;\\n      width: 2px;\\n      height: 2px;\\n      background: #bdbdbd;\\n}\\n@media (min-width: 1px) {\\n.nav-sub .nav-sub-wrapper[data-v-99a59cfe]:after {\\n    display: block;\\n}\\n}\\n.cart-con[data-v-99a59cfe] {\\n  /*display: flex;*/\\n  text-align: center;\\n  position: relative;\\n}\\n.cart-con p[data-v-99a59cfe] {\\n    padding-top: 185px;\\n    color: #333333;\\n    font-size: 16px;\\n}\\n.cart-con[data-v-99a59cfe]:before {\\n  position: absolute;\\n  content: \\' \\';\\n  left: 50%;\\n  -webkit-transform: translate(-50%, -70%);\\n          transform: translate(-50%, -70%);\\n  top: 50%;\\n  width: 76px;\\n  height: 62px;\\n  background: url(\"/static/images/cart-empty-new.png\") no-repeat;\\n  background-size: cover;\\n}\\n'],sourceRoot:\"\"}])},227:function(e,o,t){var A=t(225);\"string\"==typeof A&&(A=[[e.i,A,\"\"]]),A.locals&&(e.exports=A.locals);t(164)(\"ed6c7b3e\",A,!0)},228:function(e,o,t){var A=t(226);\"string\"==typeof A&&(A=[[e.i,A,\"\"]]),A.locals&&(e.exports=A.locals);t(164)(\"47522583\",A,!0)},229:function(e,o,t){function A(e){t(228)}var l=t(96)(t(211),t(230),A,\"data-v-99a59cfe\",null);e.exports=l.exports},230:function(e,o){e.exports={render:function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"div\",{staticClass:\"header-box\"},[t(\"div\",[t(\"header\",{staticClass:\"w\"},[t(\"div\",{staticClass:\"w-box\"},[t(\"div\",{staticClass:\"nav-logo\"},[t(\"h1\",{on:{click:function(o){e.changePage(1)}}},[t(\"router-link\",{attrs:{to:\"/\",title:\"YMall商城官网\"}},[e._v(\"YMall商城\")])],1)]),e._v(\" \"),t(\"div\",{staticClass:\"right-box\"},[t(\"div\",{staticClass:\"nav-list\"},[t(\"el-autocomplete\",{attrs:{placeholder:\"请输入商品信息\",icon:\"search\",minlength:\"1\",maxlength:\"100\",\"fetch-suggestions\":e.querySearchAsync,\"on-icon-click\":e.handleIconClick},on:{select:e.handleSelect},model:{value:e.input,callback:function(o){e.input=o},expression:\"input\"}}),e._v(\" \"),t(\"router-link\",{attrs:{to:\"/goods\"}},[t(\"a\",{on:{click:function(o){e.changePage(2)}}},[e._v(\"全部商品\")])]),e._v(\" \"),t(\"router-link\",{attrs:{to:\"/thanks\"}},[t(\"a\",{on:{click:function(o){e.changePage(3)}}},[e._v(\"捐赠\")])])],1),e._v(\" \"),t(\"div\",{ref:\"aside\",staticClass:\"nav-aside\",class:{fixed:e.st}},[t(\"div\",{staticClass:\"user pr\"},[t(\"router-link\",{attrs:{to:\"/user\"}},[e._v(\"个人中心\")]),e._v(\" \"),e.login?t(\"div\",{staticClass:\"nav-user-wrapper pa\"},[t(\"div\",{staticClass:\"nav-user-list\"},[t(\"ul\",[t(\"li\",{staticClass:\"nav-user-avatar\"},[t(\"div\",[t(\"span\",{staticClass:\"avatar\",style:{backgroundImage:\"url(\"+e.userInfo.info.file+\")\"}})]),e._v(\" \"),t(\"p\",{staticClass:\"name\"},[e._v(e._s(e.userInfo.info.username))])]),e._v(\" \"),t(\"li\",[t(\"router-link\",{attrs:{to:\"/user/orderList\"}},[e._v(\"我的订单\")])],1),e._v(\" \"),t(\"li\",[t(\"router-link\",{attrs:{to:\"/user/information\"}},[e._v(\"账号资料\")])],1),e._v(\" \"),t(\"li\",[t(\"router-link\",{attrs:{to:\"/user/addressList\"}},[e._v(\"收货地址\")])],1),e._v(\" \"),t(\"li\",[t(\"router-link\",{attrs:{to:\"/user/support\"}},[e._v(\"售后服务\")])],1),e._v(\" \"),t(\"li\",[t(\"router-link\",{attrs:{to:\"/user/coupon\"}},[e._v(\"我的优惠\")])],1),e._v(\" \"),t(\"li\",[t(\"a\",{attrs:{href:\"javascript:;\"},on:{click:e._loginOut}},[e._v(\"退出\")])])])])]):e._e()],1),e._v(\" \"),t(\"div\",{ref:\"positionMsg\",staticClass:\"shop pr\",on:{mouseover:function(o){e.cartShowState(!0)},mouseout:function(o){e.cartShowState(!1)}}},[t(\"router-link\",{attrs:{to:\"/cart\"}}),e._v(\" \"),t(\"span\",{staticClass:\"cart-num\"},[t(\"i\",{staticClass:\"num\",class:{no:e.totalNum<=0,move_in_cart:e.receiveInCart}},[e._v(e._s(e.totalNum))])]),e._v(\" \"),t(\"div\",{directives:[{name:\"show\",rawName:\"v-show\",value:e.showCart,expression:\"showCart\"}],staticClass:\"nav-user-wrapper pa active\"},[t(\"div\",{staticClass:\"nav-user-list\"},[t(\"div\",{directives:[{name:\"show\",rawName:\"v-show\",value:e.totalNum,expression:\"totalNum\"}],staticClass:\"full\"},[t(\"div\",{staticClass:\"nav-cart-items\"},[t(\"ul\",e._l(e.cartList,function(o,A){return t(\"li\",{key:A,staticClass:\"clearfix\"},[t(\"div\",{staticClass:\"cart-item\"},[t(\"div\",{staticClass:\"cart-item-inner\"},[t(\"router-link\",{attrs:{to:\"goodsDetails?productId=\"+o.productId}},[t(\"div\",{staticClass:\"item-thumb\"},[t(\"img\",{attrs:{src:o.productImg}})]),e._v(\" \"),t(\"div\",{staticClass:\"item-desc\"},[t(\"div\",{staticClass:\"cart-cell\"},[t(\"h4\",[t(\"a\",{attrs:{href:\"\"},domProps:{textContent:e._s(o.productName)}})]),e._v(\" \"),t(\"h6\",[t(\"span\",{staticClass:\"price-icon\"},[e._v(\"¥\")]),t(\"span\",{staticClass:\"price-num\"},[e._v(e._s(o.salePrice))]),t(\"span\",{staticClass:\"item-num\"},[e._v(\"x \"+e._s(o.productNum))])])])])]),e._v(\" \"),t(\"div\",{staticClass:\"del-btn del\",on:{click:function(t){e.delGoods(o.productId)}}},[e._v(\"删除\")])],1)])])}))]),e._v(\" \"),t(\"div\",{staticClass:\"nav-cart-total\"},[t(\"p\",[e._v(\"共 \"),t(\"strong\",[e._v(e._s(e.totalNum))]),e._v(\" 件商品\")]),e._v(\" \"),t(\"h5\",[e._v(\"合计：\"),t(\"span\",{staticClass:\"price-icon\"},[e._v(\"¥\")]),t(\"span\",{staticClass:\"price-num\"},[e._v(e._s(e.totalPrice))])]),e._v(\" \"),t(\"h6\",[t(\"y-button\",{staticStyle:{height:\"40px\",width:\"100%\",margin:\"0\",color:\"#fff\",\"font-size\":\"14px\",\"line-height\":\"38px\"},attrs:{classStyle:\"main-btn\",text:\"去购物车\"},on:{btnClick:e.toCart}})],1)])]),e._v(\" \"),t(\"div\",{directives:[{name:\"show\",rawName:\"v-show\",value:!e.totalNum,expression:\"!totalNum\"}],staticClass:\"cart-con\",staticStyle:{height:\"313px\",\"text-align\":\"center\"}},[t(\"p\",[e._v(\"您的购物车竟然是空的!\")])])])])],1)])])])]),e._v(\" \"),e._t(\"nav\",[t(\"div\",{staticClass:\"nav-sub\",class:{fixed:e.st}},[t(\"div\",{staticClass:\"nav-sub-bg\"}),e._v(\" \"),t(\"div\",{staticClass:\"nav-sub-wrapper\",class:{fixed:e.st}},[t(\"div\",{staticClass:\"w\"},[t(\"ul\",{staticClass:\"nav-list2\"},[t(\"li\",[t(\"router-link\",{attrs:{to:\"/\"}},[t(\"a\",{class:{active:1===e.choosePage},on:{click:function(o){e.changePage(1)}}},[e._v(\"首页\")])])],1),e._v(\" \"),t(\"li\",[t(\"router-link\",{attrs:{to:\"/goods\"}},[t(\"a\",{class:{active:2===e.choosePage},on:{click:function(o){e.changePage(2)}}},[e._v(\"全部商品\")])])],1),e._v(\" \"),t(\"li\",[t(\"router-link\",{attrs:{to:\"/thanks\"}},[t(\"a\",{class:{active:3===e.choosePage},on:{click:function(o){e.changePage(3)}}},[e._v(\"捐赠名单\")])])],1),e._v(\" \"),e._m(0),e._v(\" \"),e._m(1),e._v(\" \"),e._m(2)]),e._v(\" \"),t(\"div\")])])])])],2)])},staticRenderFns:[function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"li\",[t(\"a\",{attrs:{href:\"http://xmadmin.yuu.cn\",target:\"_blank\"}},[e._v(\"后台管理系统\")])])},function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"li\",[t(\"a\",{attrs:{href:\"http://xpay.yuu.cn\",target:\"_blank\"}},[e._v(\"XPay支付系统\")])])},function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"li\",[t(\"a\",{attrs:{href:\"https://github.com/yuu/YMall\",target:\"_blank\"}},[e._v(\"Github\")])])}]}},280:function(e,o,t){\"use strict\";Object.defineProperty(o,\"__esModule\",{value:!0});var A=t(99),l=t.n(A),i=t(229),r=t.n(i),a=t(209),n=t.n(a),s=t(100);t.n(s);o.default={data:function(){return{}},computed:l()({},t.i(s.mapState)([\"cartPositionT\",\"cartPositionL\",\"showMoveImg\",\"elLeft\",\"elTop\",\"moveImgUrl\"])),methods:l()({},t.i(s.mapMutations)([\"ADD_ANIMATION\"]),{listenInCart:function(){this.ADD_ANIMATION({moveShow:!1,receiveInCart:!0})},beforeEnter:function(e){var o=e.style,t=e.children[0],A=t.style;o.transform=\"translate3d(0,\"+(this.elTop-this.cartPositionT)+\"px,0)\",A.transform=\"translate3d(\"+-(this.cartPositionL-this.elLeft)+\"px,0,0) scale(1.2)\"},afterEnter:function(e){var o=this,t=e.style,A=e.children[0],l=A.style;t.transform=\"translate3d(0,0,0)\",l.transform=\"translate3d(0,0,0) scale(.2)\",t.transition=\"transform .55s cubic-bezier(.29,.55,.51,1.08)\",l.transition=\"transform .55s linear\",A.addEventListener(\"transitionend\",function(){o.listenInCart()}),A.addEventListener(\"webkitAnimationEnd\",function(){o.listenInCart()})}}),components:{YHeader:r.a,YFooter:n.a}}},309:function(e,o,t){o=e.exports=t(163)(!0),o.push([e.i,\".main[data-v-90aa0c9c]{min-height:calc(100vh - 454px);background:#ededed;overflow:hidden;width:100%}.bn[data-v-90aa0c9c],.move_img div[data-v-90aa0c9c],.move_img img[data-v-90aa0c9c]{border-style:none;border-width:0;border:none}.move_img[data-v-90aa0c9c]{position:fixed;width:40px;height:40px;width:45px;z-index:29;height:45px}.move_img img[data-v-90aa0c9c]{border-radius:50%;width:100%;height:100%;display:block}\",\"\",{version:3,sources:[\"D:/桌面/YMall-front/src/page/index.vue\"],names:[],mappings:\"AACA,uBACE,+BAAgC,AAChC,mBAAoB,AACpB,gBAAiB,AACjB,UAAY,CACb,AACD,mFACE,kBAAmB,AACnB,eAAgB,AAChB,WAAa,CACd,AACD,2BACE,eAAgB,AAChB,WAAY,AACZ,YAAa,AACb,WAAY,AACZ,WAAY,AACZ,WAAa,CACd,AACD,+BACI,kBAAmB,AACnB,WAAY,AACZ,YAAa,AACb,aAAe,CAClB\",file:\"index.vue\",sourcesContent:[\"\\n.main[data-v-90aa0c9c] {\\n  min-height: calc(100vh - 454px);\\n  background: #ededed;\\n  overflow: hidden;\\n  width: 100%;\\n}\\n.bn[data-v-90aa0c9c], .move_img div[data-v-90aa0c9c], .move_img img[data-v-90aa0c9c] {\\n  border-style: none;\\n  border-width: 0;\\n  border: none;\\n}\\n.move_img[data-v-90aa0c9c] {\\n  position: fixed;\\n  width: 40px;\\n  height: 40px;\\n  width: 45px;\\n  z-index: 29;\\n  height: 45px;\\n}\\n.move_img img[data-v-90aa0c9c] {\\n    border-radius: 50%;\\n    width: 100%;\\n    height: 100%;\\n    display: block;\\n}\\n\"],sourceRoot:\"\"}])},334:function(e,o,t){var A=t(309);\"string\"==typeof A&&(A=[[e.i,A,\"\"]]),A.locals&&(e.exports=A.locals);t(164)(\"4119ceae\",A,!0)},362:function(e,o){e.exports={render:function(){var e=this,o=e.$createElement,t=e._self._c||o;return t(\"div\",[t(\"y-header\"),e._v(\" \"),t(\"router-view\",{staticClass:\"main\"}),e._v(\" \"),t(\"y-footer\"),e._v(\" \"),t(\"transition\",{on:{\"after-enter\":e.afterEnter,\"before-enter\":e.beforeEnter}},[e.showMoveImg?t(\"div\",{staticClass:\"move_img\",style:{left:e.cartPositionL-10+\"px\",top:e.cartPositionT-10+\"px\"}},[t(\"div\",[t(\"img\",{attrs:{src:e.moveImgUrl}})])]):e._e()])],1)},staticRenderFns:[]}}});\n//# sourceMappingURL=3.c565d4ee71bdb3ac0105.js.map\n"
  },
  {
    "path": "ymall-web-ui/static/js/7.0814cc986a8375eb2381.js",
    "content": "webpackJsonp([7],{171:function(t,e,n){function i(t){n(325)}var A=n(96)(n(260),n(353),i,\"data-v-50608b62\",null);t.exports=A.exports},192:function(t,e,n){function i(t){n(195)}var A=n(96)(n(193),n(196),i,\"data-v-b42a215c\",null);t.exports=A.exports},193:function(t,e,n){\"use strict\";Object.defineProperty(e,\"__esModule\",{value:!0}),e.default={props:{text:{type:[String,Number],default:\"一颗小按钮\"},inputType:{type:[String],default:\"button\"},classStyle:{type:String,default:\"default-btn\"}},methods:{btnClick:function(t){this.$emit(\"btnClick\",t)}}}},194:function(t,e,n){e=t.exports=n(163)(!0),e.push([t.i,\".default-btn[data-v-b42a215c],.disabled-btn[data-v-b42a215c],.main-btn[data-v-b42a215c]{width:100px;height:30px;line-height:28px;vertical-align:middle}input[data-v-b42a215c]{display:inline-block;cursor:pointer;text-align:center}.gray-btn[data-v-b42a215c]{border:1px solid #d5d5d5;color:#646464}.default-btn[data-v-b42a215c]{border:1px solid #e1e1e1;border-radius:4px;font-size:12px;color:#646464;background-color:#f9f9f9;background-image:linear-gradient(180deg,#fff,#f9f9f9)}.default-btn[data-v-b42a215c]:hover{background-color:#eee;background-image:linear-gradient(180deg,#f5f5f5,#eee)}.main-btn[data-v-b42a215c]{border:1px solid #5c81e3;border-radius:4px;font-size:12px;color:#fff;background-color:#678ee7;background-image:linear-gradient(180deg,#678ee7,#5078df)}.main-btn[data-v-b42a215c]:hover{background-color:#6c8cd4;background-image:linear-gradient(180deg,#6c8cd4,#4769c2)}.disabled-btn[data-v-b42a215c]{cursor:not-allowed;border:1px solid #afafaf;border-radius:4px;font-size:12px;color:#fff;background-color:#a9a9a9;background-image:linear-gradient(180deg,#b8b8b8,#a9a9a9)}\",\"\",{version:3,sources:[\"D:/桌面/YMall-front/src/components/YButton.vue\"],names:[],mappings:\"AAEA,wFACE,YAAa,AACb,YAAa,AACb,iBAAkB,AAClB,qBAAuB,CACxB,AACD,uBACE,qBAAsB,AACtB,eAAgB,AAChB,iBAAmB,CAOpB,AAGD,2BACE,yBAA0B,AAC1B,aAAe,CAChB,AACD,8BACE,yBAA0B,AAC1B,kBAAmB,AACnB,eAAgB,AAChB,cAAe,AACf,yBAA0B,AAC1B,qDAAyD,CAC1D,AACD,oCACI,sBAAuB,AACvB,qDAAyD,CAC5D,AACD,2BACE,yBAA0B,AAC1B,kBAAmB,AACnB,eAAgB,AAChB,WAAY,AACZ,yBAA0B,AAC1B,wDAA4D,CAC7D,AACD,iCACI,yBAA0B,AAC1B,wDAA4D,CAC/D,AACD,+BACE,mBAAoB,AACpB,yBAA0B,AAC1B,kBAAmB,AACnB,eAAgB,AAChB,WAAY,AACZ,yBAA0B,AAC1B,wDAA4D,CAC7D\",file:\"YButton.vue\",sourcesContent:['\\n@charset \"UTF-8\";\\n.default-btn[data-v-b42a215c], .main-btn[data-v-b42a215c], .disabled-btn[data-v-b42a215c] {\\n  width: 100px;\\n  height: 30px;\\n  line-height: 28px;\\n  vertical-align: middle;\\n}\\ninput[data-v-b42a215c] {\\n  display: inline-block;\\n  cursor: pointer;\\n  text-align: center;\\n  /*> span {*/\\n  /*user-select: none;*/\\n  /*display: inline-block;*/\\n  /*width: 100%;*/\\n  /*height: 100%;*/\\n  /*}*/\\n}\\n\\n/*灰色的按钮*/\\n.gray-btn[data-v-b42a215c] {\\n  border: 1px solid #d5d5d5;\\n  color: #646464;\\n}\\n.default-btn[data-v-b42a215c] {\\n  border: 1px solid #e1e1e1;\\n  border-radius: 4px;\\n  font-size: 12px;\\n  color: #646464;\\n  background-color: #f9f9f9;\\n  background-image: linear-gradient(180deg, #fff, #f9f9f9);\\n}\\n.default-btn[data-v-b42a215c]:hover {\\n    background-color: #eee;\\n    background-image: linear-gradient(180deg, #f5f5f5, #eee);\\n}\\n.main-btn[data-v-b42a215c] {\\n  border: 1px solid #5c81e3;\\n  border-radius: 4px;\\n  font-size: 12px;\\n  color: #fff;\\n  background-color: #678ee7;\\n  background-image: linear-gradient(180deg, #678ee7, #5078df);\\n}\\n.main-btn[data-v-b42a215c]:hover {\\n    background-color: #6c8cd4;\\n    background-image: linear-gradient(180deg, #6c8cd4, #4769c2);\\n}\\n.disabled-btn[data-v-b42a215c] {\\n  cursor: not-allowed;\\n  border: 1px solid #afafaf;\\n  border-radius: 4px;\\n  font-size: 12px;\\n  color: #fff;\\n  background-color: #a9a9a9;\\n  background-image: linear-gradient(180deg, #b8b8b8, #a9a9a9);\\n}\\n'],sourceRoot:\"\"}])},195:function(t,e,n){var i=n(194);\"string\"==typeof i&&(i=[[t.i,i,\"\"]]),i.locals&&(t.exports=i.locals);n(164)(\"1a40afec\",i,!0)},196:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement;return(t._self._c||e)(\"input\",{class:t.classStyle,attrs:{type:t.inputType,readonly:\"\",disabled:\"disabled-btn\"===t.classStyle},domProps:{value:t.text},on:{click:function(e){t.btnClick(e)}}})},staticRenderFns:[]}},197:function(t,e,n){\"use strict\";Object.defineProperty(e,\"__esModule\",{value:!0}),e.default={props:[\"title\"]}},198:function(t,e,n){e=t.exports=n(163)(!0),e.push([t.i,\".gray-box[data-v-527a1e5e]{position:relative;margin-bottom:30px;overflow:hidden;background:#fff;border-radius:8px;border:1px solid #dcdcdc;border-color:rgba(0,0,0,.14);box-shadow:0 3px 8px -6px rgba(0,0,0,.1)}.gray-box .title[data-v-527a1e5e]{padding-left:30px;position:relative;z-index:10;height:60px;padding:0 10px 0 24px;border-bottom:1px solid #d4d4d4;border-radius:8px 8px 0 0;box-shadow:0 1px 7px rgba(0,0,0,.06);background:#f3f3f3;background:linear-gradient(#fbfbfb,#ececec);line-height:60px;font-size:18px;color:#333;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.gray-box .title h2[data-v-527a1e5e]{font-size:18px;font-weight:400;color:#626262;display:inline-block}\",\"\",{version:3,sources:[\"D:/桌面/YMall-front/src/components/shelf.vue\"],names:[],mappings:\"AACA,2BACE,kBAAmB,AACnB,mBAAoB,AACpB,gBAAiB,AACjB,gBAAiB,AACjB,kBAAmB,AACnB,yBAA0B,AAC1B,6BAAkC,AAClC,wCAA8C,CAC/C,AACD,kCACI,kBAAmB,AACnB,kBAAmB,AACnB,WAAY,AACZ,YAAa,AACb,sBAAuB,AACvB,gCAAiC,AACjC,0BAA2B,AAC3B,qCAA0C,AAC1C,mBAAoB,AACpB,4CAA8C,AAC9C,iBAAkB,AAClB,eAAgB,AAChB,WAAY,AACZ,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,yBAA0B,AACtB,sBAAuB,AACnB,8BAA+B,AACvC,yBAA0B,AACtB,sBAAuB,AACnB,kBAAoB,CAC/B,AACD,qCACM,eAAgB,AAChB,gBAAiB,AACjB,cAAe,AACf,oBAAsB,CAC3B\",file:\"shelf.vue\",sourcesContent:[\"\\n.gray-box[data-v-527a1e5e] {\\n  position: relative;\\n  margin-bottom: 30px;\\n  overflow: hidden;\\n  background: #fff;\\n  border-radius: 8px;\\n  border: 1px solid #dcdcdc;\\n  border-color: rgba(0, 0, 0, 0.14);\\n  box-shadow: 0 3px 8px -6px rgba(0, 0, 0, 0.1);\\n}\\n.gray-box .title[data-v-527a1e5e] {\\n    padding-left: 30px;\\n    position: relative;\\n    z-index: 10;\\n    height: 60px;\\n    padding: 0 10px 0 24px;\\n    border-bottom: 1px solid #d4d4d4;\\n    border-radius: 8px 8px 0 0;\\n    box-shadow: rgba(0, 0, 0, 0.06) 0 1px 7px;\\n    background: #f3f3f3;\\n    background: linear-gradient(#fbfbfb, #ececec);\\n    line-height: 60px;\\n    font-size: 18px;\\n    color: #333;\\n    display: -webkit-box;\\n    display: -ms-flexbox;\\n    display: flex;\\n    -webkit-box-pack: justify;\\n        -ms-flex-pack: justify;\\n            justify-content: space-between;\\n    -webkit-box-align: center;\\n        -ms-flex-align: center;\\n            align-items: center;\\n}\\n.gray-box .title h2[data-v-527a1e5e] {\\n      font-size: 18px;\\n      font-weight: 400;\\n      color: #626262;\\n      display: inline-block;\\n}\\n\"],sourceRoot:\"\"}])},199:function(t,e,n){var i=n(198);\"string\"==typeof i&&(i=[[t.i,i,\"\"]]),i.locals&&(t.exports=i.locals);n(164)(\"4a53b068\",i,!0)},200:function(t,e,n){function i(t){n(199)}var A=n(96)(n(197),n(201),i,\"data-v-527a1e5e\",null);t.exports=A.exports},201:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(\"div\",{staticClass:\"gray-box\"},[n(\"div\",{staticClass:\"title\"},[n(\"h2\",[t._v(t._s(t.title))]),t._v(\" \"),n(\"div\",[t._t(\"right\")],2)]),t._v(\" \"),n(\"div\",[t._t(\"content\")],2)])},staticRenderFns:[]}},202:function(t,e,n){\"use strict\";n.d(e,\"s\",function(){return A}),n.d(e,\"e\",function(){return a}),n.d(e,\"g\",function(){return o}),n.d(e,\"r\",function(){return r}),n.d(e,\"q\",function(){return s}),n.d(e,\"f\",function(){return d}),n.d(e,\"i\",function(){return l}),n.d(e,\"j\",function(){return c}),n.d(e,\"k\",function(){return p}),n.d(e,\"l\",function(){return C}),n.d(e,\"m\",function(){return b}),n.d(e,\"h\",function(){return f}),n.d(e,\"o\",function(){return B}),n.d(e,\"a\",function(){return g}),n.d(e,\"b\",function(){return x}),n.d(e,\"n\",function(){return m}),n.d(e,\"p\",function(){return u}),n.d(e,\"c\",function(){return h}),n.d(e,\"d\",function(){return v});var i=n(98),A=function(t){return i.a.fetchGet(\"/goods/allGoods\",t)},a=function(t){return i.a.fetchPost(\"/member/cartList\",t)},o=function(t){return i.a.fetchPost(\"/member/addCart\",t)},r=function(t){return i.a.fetchPost(\"/member/cartEdit\",t)},s=function(t){return i.a.fetchPost(\"/member/editCheckAll\",t)},d=function(t){return i.a.fetchPost(\"/member/cartDel\",t)},l=function(t){return i.a.fetchPost(\"/member/addressList\",t)},c=function(t){return i.a.fetchPost(\"/member/updateAddress\",t)},p=function(t){return i.a.fetchPost(\"/member/addAddress\",t)},C=function(t){return i.a.fetchPost(\"/member/delAddress\",t)},b=function(t){return i.a.fetchPost(\"/member/addOrder\",t)},f=function(t){return i.a.fetchPost(\"/member/payOrder\",t)},B=function(t){return i.a.fetchGet(\"/member/orderList\",t)},g=function(t){return i.a.fetchGet(\"/member/orderDetail\",t)},x=function(t){return i.a.fetchPost(\"/member/cancelOrder\",t)},m=function(t){return i.a.fetchGet(\"/goods/productDet\",t)},u=function(t){return i.a.fetchGet(\"/member/delOrder\",t)},h=function(t){return i.a.fetchGet(\"/goods/search\",t)},v=function(t){return i.a.fetchQuickSearch(\"http://127.0.0.1:9200/item/itemList/_search?q=productName: \"+t)}},231:function(t,e,n){\"use strict\";Object.defineProperty(e,\"__esModule\",{value:!0});var i=n(99),A=n.n(i),a=n(192),o=n.n(a),r=n(202),s=n(100),d=(n.n(s),n(23));e.default={props:{msg:{}},data:function(){return{}},methods:A()({},n.i(s.mapMutations)([\"ADD_CART\",\"ADD_ANIMATION\",\"SHOW_CART\"]),{goodsDetails:function(t){this.$router.push({path:\"goodsDetails/productId=\"+t})},addCart:function(t,e,i,A){var a=this;if(!this.showMoveImg){this.login?n.i(r.g)({userId:n.i(d.a)(\"userId\"),productId:t,productNum:1}).then(function(n){a.ADD_CART({productId:t,salePrice:e,productName:i,productImg:A})}):this.ADD_CART({productId:t,salePrice:e,productName:i,productImg:A});var o=event.target,s=o.getBoundingClientRect().left+o.offsetWidth/2,l=o.getBoundingClientRect().top+o.offsetHeight/2;this.ADD_ANIMATION({moveShow:!0,elLeft:s,elTop:l,img:A}),this.showCart||this.SHOW_CART({showCart:!0})}}}),computed:A()({},n.i(s.mapState)([\"login\",\"showMoveImg\",\"showCart\"])),mounted:function(){},components:{YButton:o.a}}},232:function(t,e,n){e=t.exports=n(163)(!0),e.push([t.i,\".good-item .ds[data-v-0a1044c9]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.good-item[data-v-0a1044c9]{background:#fff;width:25%;transition:all .5s;height:430px}.good-item[data-v-0a1044c9]:hover{-webkit-transform:translateY(-3px);transform:translateY(-3px);box-shadow:1px 1px 20px #999}.good-item:hover .good-price p[data-v-0a1044c9]{display:none}.good-item:hover .ds[data-v-0a1044c9]{display:-webkit-box;display:-ms-flexbox;display:flex}.good-item .ds[data-v-0a1044c9]{width:100%;display:none}.good-item .good-img img[data-v-0a1044c9]{margin:50px auto 10px;width:206px;height:206px;display:block}.good-item .good-price[data-v-0a1044c9]{margin:15px 0;height:30px;text-align:center;line-height:30px;color:#e4393c;font-size:20px}.good-item .good-title[data-v-0a1044c9]{line-height:1.2;font-size:16px;color:#424242;margin:0 auto;padding:0 14px;text-align:center;overflow:hidden}.good-item h3[data-v-0a1044c9]{text-align:center;line-height:1.2;font-size:12px;color:#d0d0d0;padding:10px}\",\"\",{version:3,sources:[\"D:/桌面/YMall-front/src/components/mallGoods.vue\"],names:[],mappings:\"AACA,gCACE,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,yBAA0B,AACtB,sBAAuB,AACnB,mBAAoB,AAC5B,wBAAyB,AACrB,qBAAsB,AAClB,sBAAwB,CACjC,AACD,4BACE,gBAAiB,AACjB,UAAW,AACX,mBAAoB,AACpB,YAAc,CACf,AACD,kCACI,mCAAoC,AAC5B,2BAA4B,AACpC,4BAA8B,CACjC,AACD,gDACM,YAAc,CACnB,AACD,sCACM,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CACnB,AACD,gCACI,WAAY,AACZ,YAAc,CACjB,AACD,0CACI,sBAAuB,AACvB,YAAa,AACb,aAAc,AACd,aAAe,CAClB,AACD,wCACI,cAAe,AACf,YAAa,AACb,kBAAmB,AACnB,iBAAkB,AAClB,cAAe,AACf,cAAgB,CACnB,AACD,wCACI,gBAAiB,AACjB,eAAgB,AAChB,cAAe,AACf,cAAe,AACf,eAAgB,AAChB,kBAAmB,AACnB,eAAiB,CACpB,AACD,+BACI,kBAAmB,AACnB,gBAAiB,AACjB,eAAgB,AAChB,cAAe,AACf,YAAc,CACjB\",file:\"mallGoods.vue\",sourcesContent:[\"\\n.good-item .ds[data-v-0a1044c9] {\\n  display: -webkit-box;\\n  display: -ms-flexbox;\\n  display: flex;\\n  -webkit-box-align: center;\\n      -ms-flex-align: center;\\n          align-items: center;\\n  -webkit-box-pack: center;\\n      -ms-flex-pack: center;\\n          justify-content: center;\\n}\\n.good-item[data-v-0a1044c9] {\\n  background: #fff;\\n  width: 25%;\\n  transition: all .5s;\\n  height: 430px;\\n}\\n.good-item[data-v-0a1044c9]:hover {\\n    -webkit-transform: translateY(-3px);\\n            transform: translateY(-3px);\\n    box-shadow: 1px 1px 20px #999;\\n}\\n.good-item:hover .good-price p[data-v-0a1044c9] {\\n      display: none;\\n}\\n.good-item:hover .ds[data-v-0a1044c9] {\\n      display: -webkit-box;\\n      display: -ms-flexbox;\\n      display: flex;\\n}\\n.good-item .ds[data-v-0a1044c9] {\\n    width: 100%;\\n    display: none;\\n}\\n.good-item .good-img img[data-v-0a1044c9] {\\n    margin: 50px auto 10px;\\n    width: 206px;\\n    height: 206px;\\n    display: block;\\n}\\n.good-item .good-price[data-v-0a1044c9] {\\n    margin: 15px 0;\\n    height: 30px;\\n    text-align: center;\\n    line-height: 30px;\\n    color: #e4393c;\\n    font-size: 20px;\\n}\\n.good-item .good-title[data-v-0a1044c9] {\\n    line-height: 1.2;\\n    font-size: 16px;\\n    color: #424242;\\n    margin: 0 auto;\\n    padding: 0 14px;\\n    text-align: center;\\n    overflow: hidden;\\n}\\n.good-item h3[data-v-0a1044c9] {\\n    text-align: center;\\n    line-height: 1.2;\\n    font-size: 12px;\\n    color: #d0d0d0;\\n    padding: 10px;\\n}\\n\"],sourceRoot:\"\"}])},233:function(t,e,n){var i=n(232);\"string\"==typeof i&&(i=[[t.i,i,\"\"]]),i.locals&&(t.exports=i.locals);n(164)(\"756f94eb\",i,!0)},234:function(t,e,n){function i(t){n(233)}var A=n(96)(n(231),n(235),i,\"data-v-0a1044c9\",null);t.exports=A.exports},235:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(\"div\",{staticClass:\"good-item\"},[n(\"div\",{},[n(\"div\",{staticClass:\"good-img\"},[n(\"router-link\",{attrs:{to:\"goodsDetails?productId=\"+t.msg.productId}},[n(\"img\",{directives:[{name:\"lazy\",rawName:\"v-lazy\",value:t.msg.productImageBig,expression:\"msg.productImageBig\"}],attrs:{alt:t.msg.productName}})])],1),t._v(\" \"),n(\"h6\",{staticClass:\"good-title\",domProps:{innerHTML:t._s(t.msg.productName)}},[t._v(t._s(t.msg.productName))]),t._v(\" \"),n(\"h3\",{staticClass:\"sub-title ellipsis\"},[t._v(t._s(t.msg.sub_title))]),t._v(\" \"),n(\"div\",{staticClass:\"good-price pr\"},[n(\"div\",{staticClass:\"ds pa\"},[n(\"router-link\",{attrs:{to:\"goodsDetails?productId=\"+t.msg.productId}},[n(\"y-button\",{staticStyle:{margin:\"0 5px\"},attrs:{text:\"查看详情\"}})],1),t._v(\" \"),n(\"y-button\",{staticStyle:{margin:\"0 5px\"},attrs:{text:\"加入购物车\",classStyle:\"main-btn\"},on:{btnClick:function(e){t.addCart(t.msg.productId,t.msg.salePrice,t.msg.productName,t.msg.productImageBig)}}})],1),t._v(\" \"),n(\"p\",[n(\"span\",{staticStyle:{\"font-size\":\"16px\"}},[t._v(\"￥\")]),t._v(\"\\n        \"+t._s(t.msg.salePrice))])])])])},staticRenderFns:[]}},238:function(t,e,n){\"use strict\";Object.defineProperty(e,\"__esModule\",{value:!0}),e.default={props:[\"product\"]}},239:function(t,e,n){e=t.exports=n(163)(!0),e.push([t.i,\".item .img-box[data-v-05612554]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.item[data-v-05612554]{position:relative;height:429px;text-align:center}.item img[data-v-05612554]{display:block;width:206px;height:206px}.item .info[data-v-05612554]{width:100%;padding:0 10px}.item .info h6[data-v-05612554]{font-size:16px;color:#424242}.item .info h6[data-v-05612554],.item .info p[data-v-05612554]{overflow:hidden;line-height:1.2;white-space:nowrap;text-overflow:ellipsis}.item .info p[data-v-05612554]{padding-top:7px;font-size:12px;color:#b2b2b2}\",\"\",{version:3,sources:[\"D:/桌面/YMall-front/src/components/product.vue\"],names:[],mappings:\"AACA,gCACE,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,yBAA0B,AACtB,sBAAuB,AACnB,mBAAoB,AAC5B,wBAAyB,AACrB,qBAAsB,AAClB,sBAAwB,CACjC,AACD,uBACE,kBAAmB,AACnB,aAAc,AACd,iBAAmB,CACpB,AACD,2BACI,cAAe,AACf,YAAa,AACb,YAAc,CACjB,AACD,6BACI,WAAY,AACZ,cAAgB,CACnB,AACD,gCAEM,eAAgB,AAIhB,aAAe,CACpB,AACD,+DAPM,gBAAiB,AAEjB,gBAAiB,AACjB,mBAAoB,AACpB,sBAAwB,CAW7B,AARD,+BAEM,gBAAiB,AACjB,eAAgB,AAIhB,aAAe,CACpB\",file:\"product.vue\",sourcesContent:[\"\\n.item .img-box[data-v-05612554] {\\n  display: -webkit-box;\\n  display: -ms-flexbox;\\n  display: flex;\\n  -webkit-box-align: center;\\n      -ms-flex-align: center;\\n          align-items: center;\\n  -webkit-box-pack: center;\\n      -ms-flex-pack: center;\\n          justify-content: center;\\n}\\n.item[data-v-05612554] {\\n  position: relative;\\n  height: 429px;\\n  text-align: center;\\n}\\n.item img[data-v-05612554] {\\n    display: block;\\n    width: 206px;\\n    height: 206px;\\n}\\n.item .info[data-v-05612554] {\\n    width: 100%;\\n    padding: 0 10px;\\n}\\n.item .info h6[data-v-05612554] {\\n      overflow: hidden;\\n      font-size: 16px;\\n      line-height: 1.2;\\n      white-space: nowrap;\\n      text-overflow: ellipsis;\\n      color: #424242;\\n}\\n.item .info p[data-v-05612554] {\\n      overflow: hidden;\\n      padding-top: 7px;\\n      font-size: 12px;\\n      line-height: 1.2;\\n      white-space: nowrap;\\n      text-overflow: ellipsis;\\n      color: #b2b2b2;\\n}\\n\"],sourceRoot:\"\"}])},242:function(t,e,n){var i=n(239);\"string\"==typeof i&&(i=[[t.i,i,\"\"]]),i.locals&&(t.exports=i.locals);n(164)(\"3c58e94c\",i,!0)},248:function(t,e,n){function i(t){n(242)}var A=n(96)(n(238),n(249),i,\"data-v-05612554\",null);t.exports=A.exports},249:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(\"div\",{staticClass:\"item\",attrs:{id:\"product.spu.id\"}},[n(\"div\",{staticClass:\"img-box\"},[n(\"img\",{attrs:{src:t.product.spu.sku_info[0].ali_image,alt:\"\"}})]),t._v(\" \"),n(\"div\",{staticClass:\"info\"},[n(\"h6\",{staticClass:\"ellipsis\"},[t._v(t._s(t.product.spu.sku_info[0].title))]),t._v(\" \"),n(\"p\",[t._v(t._s(t.product.spu.sku_info[0].sub_title))])]),t._v(\" \"),n(\"p\",{staticClass:\"price\"},[n(\"i\",[t._v(\"¥\")]),t._v(\" \"),n(\"span\",[t._v(t._s(t.product.spu.price))])]),t._v(\" \"),t._m(0)])},staticRenderFns:[function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(\"ul\",{staticClass:\"dot-list\"},[n(\"li\")])}]}},260:function(t,e,n){\"use strict\";Object.defineProperty(e,\"__esModule\",{value:!0});var i=n(42),A=n(200),a=n.n(A),o=n(248),r=n.n(o),s=n(234),d=n.n(s),l=n(23);e.default={data:function(){return{banner:{},bgOpt:{px:0,py:0,w:0,h:0},floors:[],hot:[],loading:!0,notify:\"1\",dialogVisible:!1}},methods:{bgOver:function(t){this.bgOpt.px=t.offsetLeft,this.bgOpt.py=t.offsetTop,this.bgOpt.w=t.offsetWidth,this.bgOpt.h=t.offsetHeight},bgMove:function(t,e){var n=this.bgOpt,i=void 0,A=void 0,a=e.pageX-n.px,o=e.pageY-n.py;i=(n.w,a-n.w/2),A=(n.h,n.h/2-o),t.style[\"-webkit-transform\"]=\"rotateY(\"+i/50+\"deg) rotateX(\"+A/50+\"deg)\",t.style.transform=\"rotateY(\"+i/50+\"deg) rotateX(\"+A/50+\"deg)\"},bgOut:function(t){t.style[\"-webkit-transform\"]=\"rotateY(0deg) rotateX(0deg)\",t.style.transform=\"rotateY(0deg) rotateX(0deg)\"},showNotify:function(){var t=n.i(l.a)(\"notify\");this.notify!==t&&(this.dialogVisible=!0,n.i(l.b)(\"notify\",this.notify))}},mounted:function(){var t=this;n.i(i.b)().then(function(e){var n=e.result;t.floors=n.home_floors,t.hot=n.home_hot,t.loading=!1}),this.showNotify()},components:{YShelf:a.a,product:r.a,mallGoods:d.a}}},300:function(t,e,n){e=t.exports=n(163)(!0),e.push([t.i,'.home[data-v-50608b62]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.banner[data-v-50608b62],.banner div[data-v-50608b62],.banner span[data-v-50608b62]{font-family:Microsoft YaHei;transition:all .3s;-webkit-transition:all .3s;transition-timing-function:linear;-webkit-transition-timing-function:linear}.banner[data-v-50608b62]{-webkit-perspective:3000px;perspective:3000px;position:relative;z-index:19}.bg[data-v-50608b62]{position:relative;width:1220px;height:500px;margin:20px auto;background:url(\"http://static.smartisanos.cn/index/img/store/home/banner-3d-item-1-box-1_61bdc2f4f9.png\") 50% no-repeat;background-size:100% 100%;border-radius:10px;-webkit-transform-style:preserve-3d;transform-style:preserve-3d;-webkit-transform-origin:50% 50%;-webkit-transform:rotateY(0deg) rotateX(0deg)}.img[data-v-50608b62]{display:block;position:absolute;width:100%;height:100%;bottom:5px;left:0;background:url(\"http://static.smartisanos.cn/index/img/store/home/banner-3d-item-1-box-3_8fa7866d59.png\") 50% no-repeat;background-size:95% 100%}.text[data-v-50608b62]{top:20%;font-size:30px}.copyright[data-v-50608b62],.text[data-v-50608b62]{position:absolute;right:10%;color:#fff;text-align:right;font-weight:lighter}.copyright[data-v-50608b62]{bottom:10%;font-size:10px}.a[data-v-50608b62]{-webkit-transform:translateZ(40px)}.b[data-v-50608b62]{-webkit-transform:translateZ(20px)}.c[data-v-50608b62]{-webkit-transform:translateZ(0)}.sk_item[data-v-50608b62]{width:170px;height:225px;padding:0 14px 0 15px}.sk_item>div[data-v-50608b62]{width:100%}.sk_item a[data-v-50608b62]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;transition:all .3s}.sk_item a[data-v-50608b62]:hover{-webkit-transform:translateY(-5px);transform:translateY(-5px)}.sk_item img[data-v-50608b62]{width:130px;height:130px;margin:17px 0}.sk_item .sk_item_name[data-v-50608b62]{color:#999;display:block;max-width:100%;_width:100%;overflow:hidden;font-size:12px;text-align:left;height:32px;line-height:16px;word-wrap:break-word;word-break:break-all}.sk_item .sk_item_price[data-v-50608b62]{padding:3px 0;height:25px}.sk_item .price_new[data-v-50608b62]{font-size:18px;font-weight:700;margin-right:8px;color:#f10214}.sk_item .price_origin[data-v-50608b62]{color:#999;font-size:12px}.box[data-v-50608b62]{overflow:hidden;position:relative;z-index:0;margin-top:29px;box-sizing:border-box;border:1px solid rgba(0,0,0,.14);border-radius:8px;background:#fff;box-shadow:0 3px 8px -6px rgba(0,0,0,.1)}ul.box[data-v-50608b62]{display:-webkit-box;display:-ms-flexbox;display:flex}ul.box li[data-v-50608b62]{-webkit-box-flex:1;-ms-flex:1;flex:1}ul.box li img[data-v-50608b62]{display:block;width:305px;height:200px}.mt30[data-v-50608b62]{margin-top:30px}.hot[data-v-50608b62]{display:-webkit-box;display:-ms-flexbox;display:flex}.hot>div[data-v-50608b62]{-webkit-box-flex:1;-ms-flex:1;flex:1;width:25%}.floors[data-v-50608b62]{width:100%;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.floors .imgbanner[data-v-50608b62]{width:50%;height:430px}.floors img[data-v-50608b62]{display:block;width:100%;height:100%}',\"\",{version:3,sources:[\"D:/桌面/YMall-front/src/page/Home/home.vue\"],names:[],mappings:\"AACA,uBACE,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,4BAA6B,AAC7B,6BAA8B,AAC1B,0BAA2B,AACvB,qBAAuB,CAChC,AACD,oFACE,4BAA+B,AAC/B,mBAAoB,AACpB,2BAA4B,AAC5B,kCAAmC,AACnC,yCAA2C,CAC5C,AACD,yBACE,2BAA4B,AACpB,mBAAoB,AAC5B,kBAAmB,AACnB,UAAY,CACb,AACD,qBACE,kBAAmB,AACnB,aAAc,AACd,aAAc,AACd,iBAAkB,AAClB,wHAA4H,AAC5H,0BAA2B,AAC3B,mBAAoB,AACpB,oCAAqC,AAC7B,4BAA6B,AACrC,iCAAkC,AAClC,6CAA+C,CAChD,AACD,sBACE,cAAe,AACf,kBAAmB,AACnB,WAAY,AACZ,YAAa,AACb,WAAY,AACZ,OAAQ,AACR,wHAA4H,AAC5H,wBAA0B,CAC3B,AACD,uBAEE,QAAS,AAET,cAAgB,CAIjB,AACD,mDARE,kBAAmB,AAEnB,UAAW,AAEX,WAAY,AACZ,iBAAkB,AAClB,mBAAqB,CAUtB,AARD,4BAEE,WAAY,AAEZ,cAAgB,CAIjB,AACD,oBACE,kCAAoC,CACrC,AACD,oBACE,kCAAoC,CACrC,AACD,oBACE,+BAAmC,CACpC,AACD,0BACE,YAAa,AACb,aAAc,AACd,qBAAuB,CACxB,AACD,8BACI,UAAY,CACf,AACD,4BACI,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,4BAA6B,AAC7B,6BAA8B,AAC1B,0BAA2B,AACvB,sBAAuB,AAC/B,wBAAyB,AACrB,qBAAsB,AAClB,uBAAwB,AAChC,yBAA0B,AACtB,sBAAuB,AACnB,mBAAoB,AAC5B,kBAAoB,CACvB,AACD,kCACM,mCAAoC,AAC5B,0BAA4B,CACzC,AACD,8BACI,YAAa,AACb,aAAc,AACd,aAAe,CAClB,AACD,wCACI,WAAY,AACZ,cAAe,AACf,eAAgB,CAChB,WAAa,AACb,gBAAiB,AACjB,eAAgB,AAChB,gBAAiB,AACjB,YAAa,AACb,iBAAkB,AAClB,qBAAsB,AACtB,oBAAsB,CACzB,AACD,yCACI,cAAe,AACf,WAAa,CAChB,AACD,qCACI,eAAgB,AAChB,gBAAiB,AACjB,iBAAkB,AAClB,aAAe,CAClB,AACD,wCACI,WAAY,AACZ,cAAgB,CACnB,AACD,sBACE,gBAAiB,AACjB,kBAAmB,AACnB,UAAW,AACX,gBAAiB,AACjB,sBAAuB,AACvB,iCAAsC,AACtC,kBAAmB,AACnB,gBAAiB,AACjB,wCAA8C,CAC/C,AACD,wBACE,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CACf,AACD,2BACI,mBAAoB,AAChB,WAAY,AACR,MAAQ,CACnB,AACD,+BACM,cAAe,AACf,YAAa,AACb,YAAc,CACnB,AACD,uBACE,eAAiB,CAClB,AACD,sBACE,oBAAqB,AACrB,oBAAqB,AACrB,YAAc,CACf,AACD,0BACI,mBAAoB,AAChB,WAAY,AACR,OAAQ,AAChB,SAAW,CACd,AACD,yBACE,WAAY,AACZ,oBAAqB,AACrB,oBAAqB,AACrB,aAAc,AACd,mBAAoB,AAChB,eAAgB,AACpB,yBAA0B,AACtB,sBAAuB,AACnB,kBAAoB,CAC7B,AACD,oCACI,UAAW,AACX,YAAc,CACjB,AACD,6BACI,cAAe,AACf,WAAY,AACZ,WAAa,CAChB\",file:\"home.vue\",sourcesContent:['\\n.home[data-v-50608b62] {\\n  display: -webkit-box;\\n  display: -ms-flexbox;\\n  display: flex;\\n  -webkit-box-orient: vertical;\\n  -webkit-box-direction: normal;\\n      -ms-flex-direction: column;\\n          flex-direction: column;\\n}\\n.banner[data-v-50608b62], .banner span[data-v-50608b62], .banner div[data-v-50608b62] {\\n  font-family: \"Microsoft YaHei\";\\n  transition: all .3s;\\n  -webkit-transition: all .3s;\\n  transition-timing-function: linear;\\n  -webkit-transition-timing-function: linear;\\n}\\n.banner[data-v-50608b62] {\\n  -webkit-perspective: 3000px;\\n          perspective: 3000px;\\n  position: relative;\\n  z-index: 19;\\n}\\n.bg[data-v-50608b62] {\\n  position: relative;\\n  width: 1220px;\\n  height: 500px;\\n  margin: 20px auto;\\n  background: url(\"http://static.smartisanos.cn/index/img/store/home/banner-3d-item-1-box-1_61bdc2f4f9.png\") center no-repeat;\\n  background-size: 100% 100%;\\n  border-radius: 10px;\\n  -webkit-transform-style: preserve-3d;\\n          transform-style: preserve-3d;\\n  -webkit-transform-origin: 50% 50%;\\n  -webkit-transform: rotateY(0deg) rotateX(0deg);\\n}\\n.img[data-v-50608b62] {\\n  display: block;\\n  position: absolute;\\n  width: 100%;\\n  height: 100%;\\n  bottom: 5px;\\n  left: 0;\\n  background: url(\"http://static.smartisanos.cn/index/img/store/home/banner-3d-item-1-box-3_8fa7866d59.png\") center no-repeat;\\n  background-size: 95% 100%;\\n}\\n.text[data-v-50608b62] {\\n  position: absolute;\\n  top: 20%;\\n  right: 10%;\\n  font-size: 30px;\\n  color: #fff;\\n  text-align: right;\\n  font-weight: lighter;\\n}\\n.copyright[data-v-50608b62] {\\n  position: absolute;\\n  bottom: 10%;\\n  right: 10%;\\n  font-size: 10px;\\n  color: #fff;\\n  text-align: right;\\n  font-weight: lighter;\\n}\\n.a[data-v-50608b62] {\\n  -webkit-transform: translateZ(40px);\\n}\\n.b[data-v-50608b62] {\\n  -webkit-transform: translateZ(20px);\\n}\\n.c[data-v-50608b62] {\\n  -webkit-transform: translateZ(0px);\\n}\\n.sk_item[data-v-50608b62] {\\n  width: 170px;\\n  height: 225px;\\n  padding: 0 14px 0 15px;\\n}\\n.sk_item > div[data-v-50608b62] {\\n    width: 100%;\\n}\\n.sk_item a[data-v-50608b62] {\\n    display: -webkit-box;\\n    display: -ms-flexbox;\\n    display: flex;\\n    -webkit-box-orient: vertical;\\n    -webkit-box-direction: normal;\\n        -ms-flex-direction: column;\\n            flex-direction: column;\\n    -webkit-box-pack: center;\\n        -ms-flex-pack: center;\\n            justify-content: center;\\n    -webkit-box-align: center;\\n        -ms-flex-align: center;\\n            align-items: center;\\n    transition: all .3s;\\n}\\n.sk_item a[data-v-50608b62]:hover {\\n      -webkit-transform: translateY(-5px);\\n              transform: translateY(-5px);\\n}\\n.sk_item img[data-v-50608b62] {\\n    width: 130px;\\n    height: 130px;\\n    margin: 17px 0;\\n}\\n.sk_item .sk_item_name[data-v-50608b62] {\\n    color: #999;\\n    display: block;\\n    max-width: 100%;\\n    _width: 100%;\\n    overflow: hidden;\\n    font-size: 12px;\\n    text-align: left;\\n    height: 32px;\\n    line-height: 16px;\\n    word-wrap: break-word;\\n    word-break: break-all;\\n}\\n.sk_item .sk_item_price[data-v-50608b62] {\\n    padding: 3px 0;\\n    height: 25px;\\n}\\n.sk_item .price_new[data-v-50608b62] {\\n    font-size: 18px;\\n    font-weight: 700;\\n    margin-right: 8px;\\n    color: #f10214;\\n}\\n.sk_item .price_origin[data-v-50608b62] {\\n    color: #999;\\n    font-size: 12px;\\n}\\n.box[data-v-50608b62] {\\n  overflow: hidden;\\n  position: relative;\\n  z-index: 0;\\n  margin-top: 29px;\\n  box-sizing: border-box;\\n  border: 1px solid rgba(0, 0, 0, 0.14);\\n  border-radius: 8px;\\n  background: #fff;\\n  box-shadow: 0 3px 8px -6px rgba(0, 0, 0, 0.1);\\n}\\nul.box[data-v-50608b62] {\\n  display: -webkit-box;\\n  display: -ms-flexbox;\\n  display: flex;\\n}\\nul.box li[data-v-50608b62] {\\n    -webkit-box-flex: 1;\\n        -ms-flex: 1;\\n            flex: 1;\\n}\\nul.box li img[data-v-50608b62] {\\n      display: block;\\n      width: 305px;\\n      height: 200px;\\n}\\n.mt30[data-v-50608b62] {\\n  margin-top: 30px;\\n}\\n.hot[data-v-50608b62] {\\n  display: -webkit-box;\\n  display: -ms-flexbox;\\n  display: flex;\\n}\\n.hot > div[data-v-50608b62] {\\n    -webkit-box-flex: 1;\\n        -ms-flex: 1;\\n            flex: 1;\\n    width: 25%;\\n}\\n.floors[data-v-50608b62] {\\n  width: 100%;\\n  display: -webkit-box;\\n  display: -ms-flexbox;\\n  display: flex;\\n  -ms-flex-wrap: wrap;\\n      flex-wrap: wrap;\\n  -webkit-box-align: center;\\n      -ms-flex-align: center;\\n          align-items: center;\\n}\\n.floors .imgbanner[data-v-50608b62] {\\n    width: 50%;\\n    height: 430px;\\n}\\n.floors img[data-v-50608b62] {\\n    display: block;\\n    width: 100%;\\n    height: 100%;\\n}\\n'],sourceRoot:\"\"}])},325:function(t,e,n){var i=n(300);\"string\"==typeof i&&(i=[[t.i,i,\"\"]]),i.locals&&(t.exports=i.locals);n(164)(\"ce60f2c2\",i,!0)},353:function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(\"div\",{staticClass:\"home\"},[n(\"div\",{staticClass:\"banner\"},[n(\"a\",{attrs:{href:\"https://github.com/yuu/YMall\"}},[n(\"div\",{ref:\"bg\",staticClass:\"bg\",on:{mouseover:function(e){t.bgOver(t.$refs.bg)},mousemove:function(e){t.bgMove(t.$refs.bg,e)},mouseout:function(e){t.bgOut(t.$refs.bg)}}},[n(\"span\",{staticClass:\"img a\"}),t._v(\" \"),t._m(0),t._v(\" \"),n(\"span\",{staticClass:\"copyright c\"},[t._v(\"code by qingjin.me | picture from t.tt\")])])])]),t._v(\" \"),n(\"div\",{directives:[{name:\"loading\",rawName:\"v-loading\",value:t.loading,expression:\"loading\"}],attrs:{\"element-loading-text\":\"加载中...\"}},[n(\"section\",{staticClass:\"w mt30 clearfix\"},[n(\"y-shelf\",{attrs:{title:\"热门商品\"}},[n(\"div\",{staticClass:\"hot\",slot:\"content\"},t._l(t.hot,function(t,e){return n(\"mall-goods\",{key:e,attrs:{msg:t}})}))])],1),t._v(\" \"),t._l(t.floors,function(e,i){return n(\"section\",{key:i,staticClass:\"w mt30 clearfix\"},[n(\"y-shelf\",{attrs:{title:e.title}},[n(\"div\",{staticClass:\"floors\",slot:\"content\"},[n(\"div\",{staticClass:\"imgbanner\"},[n(\"a\",{attrs:{href:t.floors[i].image.link}},[n(\"img\",{directives:[{name:\"lazy\",rawName:\"v-lazy\",value:t.floors[i].image.image,expression:\"floors[i].image.image\"}],attrs:{alt:e.title}})])]),t._v(\" \"),t._l(e.tabs,function(t,e){return n(\"mall-goods\",{key:e,attrs:{msg:t}})})],2)])],1)})],2),t._v(\" \"),n(\"el-dialog\",{staticStyle:{width:\"70%\",margin:\"0 auto\"},attrs:{title:\"通知\",visible:t.dialogVisible,width:\"30%\"},on:{\"update:visible\":function(e){t.dialogVisible=e}}},[n(\"span\",[t._v(\"XPay个人支付收款系统已上线，赶快去支付体验吧！\")]),t._v(\" \"),n(\"span\",{staticClass:\"dialog-footer\",slot:\"footer\"},[n(\"el-button\",{attrs:{type:\"primary\"},on:{click:function(e){t.dialogVisible=!1}}},[t._v(\"知道了\")])],1)])],1)},staticRenderFns:[function(){var t=this,e=t.$createElement,n=t._self._c||e;return n(\"span\",{staticClass:\"text b\"},[t._v(\"以傲慢与偏执\"),n(\"br\"),t._v(\"回敬傲慢与偏见\")])}]}}});\n//# sourceMappingURL=7.0814cc986a8375eb2381.js.map\n"
  },
  {
    "path": "ymall-web-ui/static/js/app.e28b119acf7c187f0fbf.js",
    "content": "webpackJsonp([26],{0:function(n,t){n.exports=Vue},100:function(n,t){n.exports=Vuex},114:function(n,t,e){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0});var o=e(83),A=(e.n(o),e(68)),u=e.n(A),r=e(84),i=(e.n(r),e(69)),a=e.n(i),c=e(82),f=(e.n(c),e(67)),s=e.n(f),d=e(85),p=(e.n(d),e(39)),h=e.n(p),l=e(87),m=(e.n(l),e(40)),g=e.n(m),w=e(79),E=(e.n(w),e(65)),v=e.n(E),U=e(81),I=(e.n(U),e(22)),B=e.n(I),j=e(90),b=(e.n(j),e(73)),G=e.n(b),N=e(91),Q=(e.n(N),e(74)),M=e.n(Q),D=e(88),k=(e.n(D),e(71)),C=e.n(k),R=e(89),J=(e.n(R),e(72)),Y=e.n(J),O=e(75),P=(e.n(O),e(63)),F=e.n(P),T=e(80),x=(e.n(T),e(66)),y=e.n(x),S=e(78),V=(e.n(S),e(21)),H=e.n(V),L=e(86),Z=(e.n(L),e(70)),z=e.n(Z),K=e(77),q=(e.n(K),e(76)),W=(e.n(q),e(64)),X=e.n(W),_=e(0),$=e.n(_),nn=e(95),tn=e.n(nn),en=e(61),on=e(62),An=e(94),un=e.n(An),rn=e(93),an=e.n(rn),cn=e(92),fn=e.n(cn),sn=e(42),dn=e(23);$.a.use(X.a),$.a.use(z.a),$.a.use(H.a),$.a.use(y.a),$.a.use(F.a),$.a.use(Y.a),$.a.use(C.a),$.a.use(M.a),$.a.use(G.a),$.a.use(B.a),$.a.use(v.a),$.a.use(g.a),$.a.use(h.a),$.a.use(s.a.directive),$.a.prototype.$loading=s.a.service,$.a.prototype.$notify=a.a,$.a.prototype.$message=u.a,$.a.use(an.a),$.a.use(fn.a),$.a.use(un.a,{loading:\"/static/images/load.gif\"}),$.a.config.productionTip=!1;var pn=[\"/home\",\"/goods\",\"/login\",\"/register\",\"/goodsDetails\",\"/thanks\",\"/search\",\"/refreshsearch\"];en.a.beforeEach(function(n,t,o){var A={params:{token:e.i(dn.a)(\"token\")}};e.i(sn.a)(A).then(function(t){1!==t.result.state?-1!==pn.indexOf(n.path)?o():o(\"/login\"):(on.a.commit(\"RECORD_USERINFO\",{info:t.result}),\"/login\"===n.path&&o({path:\"/\"}),o())})}),new $.a({el:\"#app\",store:on.a,router:en.a,render:function(n){return n(tn.a)}})},115:function(n,t,e){\"use strict\";t.a={}},116:function(n,t,e){\"use strict\";e.d(t,\"a\",function(){return o}),e.d(t,\"b\",function(){return A}),e.d(t,\"h\",function(){return u}),e.d(t,\"g\",function(){return r}),e.d(t,\"c\",function(){return i}),e.d(t,\"d\",function(){return a}),e.d(t,\"e\",function(){return c}),e.d(t,\"f\",function(){return f});var o=\"INIT_BUYCART\",A=\"ADD_CART\",u=\"GET_USERINFO\",r=\"RECORD_USERINFO\",i=\"ADD_ANIMATION\",a=\"SHOW_CART\",c=\"REDUCE_CART\",f=\"EDIT_CART\"},117:function(n,t,e){\"use strict\";var o,A=e(123),u=e.n(A),r=e(99),i=e.n(r),a=e(116),c=e(23);t.a=(o={},u()(o,a.a,function(n){var t=e.i(c.a)(\"buyCart\");t&&(n.cartList=JSON.parse(t))}),u()(o,a.b,function(n,t){var o=t.productId,A=t.salePrice,u=t.productName,r=t.productImg,i=t.productNum,a=void 0===i?1:i,f=n.cartList,s=!0,d={productId:o,salePrice:A,productName:u,productImg:r};f.length&&f.forEach(function(n){n.productId===o&&n.productNum>=0&&(s=!1,n.productNum+=a)}),f.length&&!s||(d.productNum=a,d.checked=\"1\",f.push(d)),n.cartList=f,e.i(c.b)(\"buyCart\",f)}),u()(o,a.c,function(n,t){var e=t.moveShow,o=t.elLeft,A=t.elTop,u=t.img,r=t.cartPositionT,i=t.cartPositionL,a=t.receiveInCart;n.showMoveImg=e,o&&(n.elLeft=o,n.elTop=A),n.moveImgUrl=u,n.receiveInCart=a,r&&(n.cartPositionT=r,n.cartPositionL=i)}),u()(o,a.d,function(n,t){var e=t.showCart;n.showCart=e}),u()(o,a.e,function(n,t){var o=t.productId,A=n.cartList;A.forEach(function(n,t){n.productId===o&&(n.productNum>1?n.productNum--:A.splice(t,1))}),n.cartList=A,e.i(c.b)(\"buyCart\",n.cartList)}),u()(o,a.f,function(n,t){var o=t.productId,A=t.productNum,u=t.checked,r=n.cartList;A?r.forEach(function(n,t){n.productId===o&&(n.productNum=A,n.checked=u)}):o?r.forEach(function(n,t){n.productId===o&&r.splice(t,1)}):r.forEach(function(n){n.checked=u?\"1\":\"0\"}),n.cartList=r,e.i(c.b)(\"buyCart\",n.cartList)}),u()(o,a.g,function(n,t){n.userInfo=t,n.login=!0,e.i(c.b)(\"userInfo\",t)}),u()(o,a.h,function(n,t){n.userInfo&&n.userInfo.username!==t.username||n.login&&(t.message?n.userInfo=null:n.userInfo=i()({},t))}),o)},118:function(n,t,e){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default={name:\"app\"}},157:function(n,t){},159:function(n,t){n.exports={render:function(){var n=this,t=n.$createElement,e=n._self._c||t;return e(\"div\",{attrs:{id:\"app\"}},[e(\"router-view\",{staticClass:\"main\"})],1)},staticRenderFns:[]}},161:function(n,t){n.exports=VueRouter},162:function(n,t){n.exports=axios},165:function(n,t,e){n.exports=e.p+\"static/fonts/element-icons.b02bdc1.ttf\"},166:function(n,t){n.exports=\"data:application/font-woff;base64,d09GRgABAAAAAB9EABAAAAAANAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABbAAAABoAAAAcdCWJ3kdERUYAAAGIAAAAHQAAACAAWAAET1MvMgAAAagAAABNAAAAYFdvXOBjbWFwAAAB+AAAAFAAAAFS5mHtc2N2dCAAAAJIAAAAGAAAACQNZf70ZnBnbQAAAmAAAAT8AAAJljD3npVnYXNwAAAHXAAAAAgAAAAIAAAAEGdseWYAAAdkAAAUPAAAIUw4RPqwaGVhZAAAG6AAAAAvAAAANgxJKwtoaGVhAAAb0AAAAB4AAAAkCQwFDGhtdHgAABvwAAAAVgAAAKyk5AaSbG9jYQAAHEgAAABYAAAAWJwQpAxtYXhwAAAcoAAAACAAAAAgAU4CJG5hbWUAABzAAAABNQAAAit/uX3PcG9zdAAAHfgAAACyAAABsMLAXoJwcmVwAAAerAAAAJUAAACVpbm+ZnicY2BgYGQAgjO2i86D6MufP7fDaABY8wj8AAB4nGNgZGBg4ANiCQYQYGJgBEItIGYB8xgABhgAXQAAAHicY2Bh4WX8wsDKwMA0k+kMAwNDP4RmfM1gzMgJFGVgY2aAAUYBBgQISHNNYTjAUPFMnbnhfwNDDHMDQwNIDUiOWQKsRIGBEQCQ/wz4AAAAeJxjYGBgZoBgGQZGBhDwAfIYwXwWBgMgzQGETEC64pnKM/X//8Eshmdq////75ZikWKG6gIDRjYGOJcRpIeJARUwMtAMMNPOaJIAAAr1C6J4nGNgQANGDEbMEv8fMjf8b4DRAEVmCF94nJ1VaXfTRhSVvGRP2pLEUETbMROnNBqZsAUDLgQpsgvp4kBoJegiJzFd+AN87Gf9mqfQntOP/LTeO14SWnpO2xxL776ZO2/TexNxjKjseSCuUUdKXveksv5UKvGzpK7rXp4o6fWSumynnpIWUStNlczF/SO5RHUuVrJJsEnG616inqs874PSSzKsKEsi2iLayrwsTVNPHD9NtTi9ZJCmgZSMgp1Ko48QqlEvkaoOZUqHXr2eipsFUjYa8aijonoQKu4czzmljTpgpHKVw1yxWW3ke0nW8/qP0kSn2Nt+nGDDY/QjV4FUjMzA9jQeh08k09FeIjORf+y4TpSFUhtcAK9qsMegSvGhuPFBthPI1HjN8XVRqTQyFee6z7LZLB2PlRDlwd/YoZQbur+Ds9OmqFZjcfvAMwY5KZQoekgWgA5Tmaf2CNo8tEBmjfqj4hzwdQgvshBlKs+ULOhQBzJndveTYtrdSddkcaBfBjJvdveS3cfDRa+O9WW7vmAKZzF6khSLixHchzLrp0y71AhHGRdzwMU8XuLWtELIyAKMSiPMUVv4ntmoa5wdY290Ho/VU2TSRfzdTH49OKlY4TjLekfcSJy7x67rwlUgiwinGu8njizqUGWw+vvSkussOGGYZ8VCxZcXvncR+S8xbj+Qd0zhUr5rihLle6YoU54xRYVyGYWlXDHFFOWqKaYpa6aYoTxrilnKc0am/X/p+334Pocz5+Gb0oNvygvwTfkBfFN+CN+UH8E3pYJvyjp8U16Eb0pt4G0pUxGqmLF0+O0lWrWhajkzuMA+D2TNiPZFbwTSMEp11Ukpdb+lVf4k+euix2Prk5K6NWlsiLu6abP4+HTGb25dMuqGnatPjCPloT109dg0oVP7zeHfzl3dKi65q4hqw6g2IpgEgDbotwLxTfNsOxDzll18/EMwAtTPqTVUU3Xt1JUaD/K8q7sYnuTA44hjoI3rrq7ASxNTVkPz4WcpMhX7g7yplWrnsHX5ZFs1hzakwtsi9pVknKbtveRVSZWV96q0Xj6fhiF6ehbXhLZs3cmkEqFRM87x8K4qRdmRlnLUP0Lnl6K+B5xxdkHrwzHuRN1BtTXsdPj5ZiNrCyaGprS9E6BkLF0VY1HlWZxjdA1rHW/cEp6upycW8Sk2mY/CSnV9lI9uI80rdllm0ahKdXSX9lnsqzb9MjtoWB1nP2mqNu7qYVuNKlI9Vb4GtAd2Vt34UA8rPuqgUVU12+jayGM0LmvGfwzIYlz560arJtPv4JZqp81izV1Bc9+YLPdOL2+9yX4r56aRpv9Woy0jl/0cjvltEeDfOSh2U9ZAvTVpiHEB2QsYLtVE5w7N3cYg4jr7H53T/W/NwiA5q22N2Tz14erpKJI7THmcZZtZ1vUozVG0k8Q+RWKrw4nBTY3hWG7KBgbk7j+s38M94K4siw+8bSSAuM/axKie6uDuHlcjNOwruQ8YmWPHuQ2wA+ASxObYtSsdALvSJecOwGfkEDwgh+AhOQS75NwE+Jwcgi/IIfiSHIKvyLkF0COHYI8cgkfkEDwmpw2wTw7BE3IIviaH4BtyWgAJOQQpOQRPySF4ZmRzUuZvqch1oO8sugH0ve0aKFtQfjByZcLOqFh23yKyDywi9dDI1Qn1iIqlDiwi9blFpP5o5NqE+hMVS/3ZIlJ/sYjUF8aXmYGU13oveUcHfwIrvqx+AAEAAf//AA94nKVaC3Bc1Xk+/zn3uXe1e3fva6V9aXe1u5JWXq32aUlIun7IGGTZlsAPGTABHEUOIQkUcAgMESUEKMnQItl0SId2mEwyzWNipqV5kpB0ChNDQzLBtBPaztQJM23iaWdo+gi1rvufu7ItOWCcZnX3nHPP8z/nf33/WRFKsoRAlX6RMCKTPrdACGGUsH2EAtApQinsErAEWwiRJVHAbiwihku1SCZSrEVyWdD/7ZVX6BdX9mbpPI4VycDZf2bfZjFikwoZIbPkIByZOm7s3u9eTYF0hDpIaJ6wEITYQQKKAtfroCoBST0YgaAkSMGDRBO0w2FQiBRUpP0kIItU0ALCXBRCoY4Z0tERCG2OTx13cMapS8yoqIH533LKGE654/KmFOYva05350XTwTzOFwLl0P9vwrm5Obf3mmtGR6tDjnPNwWsOXrd/dHZ0dmpLqzE0Uh1xKk5lJjIUi/RarmGXQCpBNkSTkGnUC416mZbAyoiWaZshmpMKJShmZOxRzJbpGDhZybRr1Wa94EhyiKVgVKo2i2UoForQqI/TUajaSYDOeNc10Xwiyv4QArFi6iHvavoMWOlcKJQOdW/wrhpIZs3Ozm5DORKMRoMd0einFUnUBCqEQ/ktM7vdHsdWRVUUJe9zYrjL+na6j6Yh2Fns2tGnJ4SO7nj0pkfqzshI3lEBFhfBiHeHvjAR6Yrgc1+XbfSE9A4l1tWRixgmHPm5FjOCycLPUIRR9h4QCF0kSdLvFgNAiQMCpS4AoWSBARXoggiCcCN2TJKk4ZiOFC3l7WYLmmWQZBXKIEuW6UClZjs2/zrwL9H+EDwfpYVG1Lvdu9WoG2YUvgf8QwMAn1KkDljSN3RT3TsGCxHQ9Zite7fzZhE4SQSLZxdRZzhdWTed7HSsAJGAgMvbyDTvMoPUw2SfRfUSFDg9KZ+eFNKTyxah0igUC/xbBOnSC8LCpen16SFnF+nZy6aniasWQmAjO0KAx1JtIT3NVpN/W/RtpMe7zacHPuj98So98PhvQQ9+F5Fvn2jzzUE+BZBj1EVeUYHzjdAF3nM936AgySCloNni54Tk1PGccnhG/FukMVzX2+Kvi8Qc9df1Js6vSz9+abp9uhg5yr5OnyQacVyT0wnT/IRmeNtkPYKH0xaeQi6TlRx4KrErAR9ppadXxOl069kExOH9jR07Gv6Za2c/wzrYZhIk0l8EREDVK9RxqG1FTKkIUIhj5+aOHU3vs5CP745fmAc+8i7jm7jhgoTj7RbQt+Jx7ym+GMy/43jcy7E1e7mI0f5eoFl1wJZwL4XWRXuh9+H0n21OTTX9ucbP/rtYZgdIlIw8p+J4cKeO96DljKDHoAt8RuQawaXQ/IXX190495xlWroQLYko14U6rqniwraJvMzRnt6Ed29yeCYBLj2U3D2cWNmX6Isk4CFe9l6ghxLDu5NYh/qMMixwnQqTAhl1N6aAMi7AAlkggigsSCAycQH9GFvw3dg0d2OzBL3YNl3XC3rBjHU6umyUCJpHM0Wr47ReBgZSdpAW6hNIUhr8BCmjH3ztW4/t3v3Yt9qZ7D2mGIr8Q1muyab8R1DFtKoobPF8D5553/Mek2Xlh4rf+AQMKUoVh+H5XaA9TUqk4VZjukIErn94QCKIBOaRYgGl/xD6UkGcJqIozPBdTVrRLrMrKpkllPeqY5th1EdJRprRTmSLnO4iWg9sinaPg16G7hDoNg2c0FKapp04oUEAS5inAxdeG2CffvTR094vMIWvnNC0QJq3pbRA4OWXA2sGrKiPnj7fd90+wqTG91Hrz8QEgfJ9UBBQjedxDwSfQ3ju63THTJgJR8d9COh40LNUU9QMAWvWB6GQDeMmMJHMNO4KE7s6gdvEhDdfxIsRWW7g8S8fxaQhSUePShJ/P7rM32X56Hqe0EnZUmqKsrSkYGbJy0uY1GV5eVnGzFKWuI6f503eza7lDNcYLsEwg9xBneGcQDFWkWIZ7aKKBCOVaIwwQdVUuX6iP6HEu8caNU2w4GEsWeYoFuBhrLIs7x4s+DU/Xy149/i9rd/ojOPJqq0kHIGRPvKkq+mAIutG0WZNTB3XUAPz6O+AyQzkeY7mJCbPKSARIk1jJpFZEYhEtiHQsbFz6kJnbPWb9hJZZjOEsYCMunt5syEg0XrMTE/ejJjdqlPK1MYRLhRylVwFs6xkVaxKDjPTdmqNXLbQVi4bkQltnpx/fHlBWfrxsrKw/Pj8mwfMoPZp2ZA/EwgaB9jy/OGjyuHl5cPK0cPzy+zLtv56IPC6bvuyB6t8SpJRMugOjLYatd5U25cFOcdom2PU5xjzOTa4oSfXZwl6ybiki81fsvU9/C8lv5t/pu/pLtfoXQLRdcXdMNyoDVWKyUSMb77jXTZfHshl/c2/iz+fgAq68/w7NJ739RX2tiKG3tlpUgnAI+/a/B57p8HL2Dkl7z/7EHsY940+jGsnAURVQHjM8QFCGfONPJdeyibrZj3CnQwq43n/vNa/fb1rexcM1OPbVj61LV6DDeteb4nFIFHZurVCvxqLeW8Obd06xGMiUkIcdxLXd0gc7cMzqyrnowW4XgOVKLKq7AuATFBp9hJUkRnUIEICEo8tqti5h3eGhffo65ba3fwKSSXS/rUDGJOnMJPZLB/K1c9JJGKxRDqRTiVj8Vg8Gsk3MhE9aJUQ9ucsrnsIEmqZarMRqSNwaOQAQzf+pT/wPvxkNVEsJFghUSjGa0+u/B19wXsZ4ULojjuKiTP/kygWE0xJFO8482E6tvLXMHbWt0ESWcSzwD/SidHjANlItpLd5Ab3ADdPQIS5sBhiWKAy0DkiBwNUUWVlrkOjqiSp0zxXpRkdJFWazOe6ugjZOb39ys2brhhtNiqDfb25gfxAV7Yrm07iAp1NoxaJlLhRwVhFSkLO5DC9vaN6YRDERr1Z82MTf48Z3C0gsvCxVbbQYO9Spr+fiT3S2fcKHcrF6B/EcqlQ2Lu3J5HM4R4XG1Mri1NwT9jWdTv8dNgOh89n9Pv3x/OFrvsB7P6uQqErlhEF6nbjxz3zwlQDLT5pTMHPtUhE874Y1PUg7H3nMpfpPXiOX8Jz7ECJGnabaNAFxDEMkS+j81wMBAbCHFd6X7y5A6VkEoFwPGYbOg4L1qUweqE1HM4Zpi/ljUiNV+DJWPAN709mR+j4yOzsSKY/6YVSfb9O9uPDFr0nVn49PDs7TH8xPHvmuWR/XwqW+1MA/cl1tkZA5Bl1w7KE9IhkDNtujEO41GJ5KLZkB11eIXvttVCDN089f8/P7ipf/+Bfeq/sgTffeP6eN+4qP3g9158LeCFGekjdHSIgcdyGIsIQ3zDcp0iID3j4PkUyGdGzmUTcMvVYJIZwTV8PGIAHrDxeNXw/E+EvjYsQgvdGur801l9KZqtZfC4CBCdLYyV8vNNOJuN4/xvr7o6twQB+PEIEypAZGLUTKrRJJWwaXSQnkZFJy8rlDdEoRcwUtFFXrh1HpwBJzJbBd4LnoNNjuuPod790550vnX7pTifjwOJjvJo34ptfe+dLd2Mn7uYvnFeaDJIJst2d1CSVoVIxtHdzAUFhvp33C2jpfasxWa1ku6M6JSOtykR1or/YPZgd7HL0dDQdkEmYhoOhEicxCaaNEX1zDO0ju+h9fXv9ovZ6AeZ/Nbhly+CvKpvplqELRfhvzDZXzlW0S3DdlsH/rGzFmqGtNH+hYeUNrOc931pf78vcSdx3iZikQj7qhnosXURbkrMpqgWGGnE0pLYPJrmDC2wigsBtIdMYN7P92Gr6ng+x59zaNrdzTTVjwvRqo8CN6F+VWrFYN/IRMnyvKaE6zlocxkAkJaBmjdMJiISEHMrfILDFFdK3Lzr69AP3D9z/wNOj0X19Zxap3JkoOYxYpaQjSeHaZ+77dF/fIw/fWyyw0khPNFxdvHn3rps/UQsbPSPe2ytvMdWOhkKGIctUD234vf3bJ2+6OZv1MR4MIZGvop9Lu4l1vtyP1hBjiESjGguVjAyGTr6y15u72M2Zcjlz5mlM4dXy5jI+xPdbBAI4338RZD/6roybEpk/3TTPoe14EJUb/MNReZTrFAqxcFE+efMkPvDquizQrl3ztNdc5WGYDJFR0N3gaJVSeah3lYdB5FKVyCIV5YOESiKVDhFJECWMeQQmCuyQbwOUNn8Z46EbaMD5y7lfa4+k87/dUC4aQ5ccykeJMhHn1g50m5c7Bq339OpIBtv4VZ0NZHhjo14u9eQSXZahSiQMIRUZt94p51iZoo6FgSHcLAzSMsUXGkG3luHuCri/8j3X0tjevWP0pzz9FEhxw0yJ4vGAo0UFdgMNJOMJWd7en6ZLqX7vKvc6Fx9W2ju28iN/WGVsr/dJqgQ1UfT+1QgI4m1Mi0ZVdR+8kiqVUt4+SG4Yn9g/Pj6wGmus2p+4j7ZEQsVp1EPGUS6qkCjSGayik0YuZ+S6eVSa8S1fpm2IIxkuNrlMxDfO8DVvKV0qpeG20hUluI0XvSVe/AEmv9HUxrnFs99nz7MRlNskKbo9NsqqgqEl5RdV/EIPyxjd0xsJScSxk2wI4VJPW1RtMQQFjL/Gqe3YURljZR4hU+HYsdeOHYMDU9/42tar6/WlF1+8+n2JK182jGjDfIk3vXZs4Iqe1uTVL/7Ncr1+9fu8//jICaOBarHqC7+M53Et+RC5m9zuqh+69YN1gV87tO+N7VWfgGKHfoJyZV2VO343Ygj81CjsOd+LW6Su1bv2OWzltxTnBlKYROEJ3n3XHbd/+LadO2KOiEa7DBgeF3n8xAMR/w0lhkf//N4Sg1AULcDISpZ4wYdIaYxgsMaxsR+/zvTfEOsjXEr7t2atcZiAcT5Vq8kLrTaiGoK2vKFtYWdYIqJPZDJhUdQ69AGjW5L0YjA4+FBFCxZ1c8BAEewIimI4k5nQIwnUb1SDRCTs+kOCHeEBsz1Eq2zeUtG0Xt0Y4GLboYmCnsm4up4QuB3yhGs/9rE/P3JkD7yoJwVmbNw4EdaLWkenFmZUUjuCAwPBDlWSY0FDEAKFSHhi43CUCUndrNo5SX7HMdqGDZo/RjMFphV0fWLjRuPCGO+tuz5/Fz4oTjXEYX+Lsn4L2exO1IbQ4+/fi6ETjYQpEZnLAQplPhADkcJvAJVbbtq+7YrR3kKiy0E4lufwhPqX6vUWvyzNc37wUJLzDdEqHnut6vPDyfO4kl/O88oqr7JMzsx236KIXUzkgyXJpixyBrWQeey2eJ/j9DXHm30OP7olzQ51hEJ6eti0YzHbHE6Hw1hha3CYB1Axy9o4fqEpyVu8J+Hc50OBWBBHh9J/qvU1J5r+zGlVZPicVHVRoqzTtFsZf3LGJFFXX2OiKIiqiFVWZ6eFk2Y2WmZMkAU98BNRFUQlEBDROgqvqyE0maytz/TsI8IonvEV5BDZ4rqpLgpCfxG9Kp6zWxMpwkoBhAVuPBfQQYnkMMF1fJMqziIXxG2Hbtm9a3Sk2UjGo3jMou1kJbmJwstFuoUSXhhc1RIeufpqgIIvj0PR1wQsO2iReOeqgy++KrVHczVoVtvqkjqnSBK/jmLD4QDTgAp1NZE+HkICmWL8sne7fgM6blnGQOwGfXvvLw0FgbsQejaVUGsCBKmqn8gdyD5wojkcqovR6LOD9vhpp6ze0Hll5w1q2Tk9bg8+G42K9dBw84Q1PKKCwtToqd49XU8FFRYCgdqs0XMyIqPTjJzsaTAbwWcYbfdTXXt6T0VVpoB6xLJqR7r7x045zfBTfZsli2atkyMjJ60staTNfU+Fm86psf7uI0FuLs+dfZHEXOviu2x0MRSl1r92e89DKdLd1rB1ORsLBIOXQd8qRln1NTpJkA1k0t1M0NNSUfJxt8hxt6Tg0UvCgTUAXOb32pOpJJC+Yk8uuSE1EHOiEVUhOujoZEUffa9GCzSaDQFi9Oo4B7DZwpgfIiZRD7mVowRx+Myj3/nRdx6dwUz86TdvvfWbPPF+aiYSvYk/w9RcRPy+0O7A+7En2l0w8Y4mjTeNZNJ4LlFMkvWxjkNypOT28l9GBY4SsBqty9yFa+m2vbcsw/HvRNfdSJNVO9zwI9aIjwEujnB+5Uc27eeiW+iVcnYolxv6p85crhOMzmy2k8fuebR1b5yPK0bJFvIBssO9ioSIqoTUfeEOlLMAlUCR5jhC5PAQTxrjeE2Tp4ksazNEk7XJ+UM3Hbxu7trZXTuuunKTa9SNBv/UdKeE0Sj/4dEnmP9q6LzHu8Fj9hRwmI0xPDo3tM2ixftEzoWyuTbHRgGtJB+S5oyD+4NqCaUsUFKDXwmqA2rQT77iV/hN+1aeCQQordJAwBuBcrcov472aCaobprYsPLDDRObeL8fDwYa8b+PNwKDP1aD8EtvkU8Ji7zpXcqeST+28kg4FgzG6D/slCiVbsEVVx5pzexs0XtxZTX40VguF/tocK0sxEmNuFy2y0kq8zBfAmmByIJ8GIVcgGmqoK8Bhn0PoG7yO38QJoEMVXpyGOxHwx0BBUUoDnGVh3B+XJlsR5uj6DRsHpv5P99CcdwHP1yQuENpthweJqP+luk4TaFeffyJZG/yCS7T7UIyCbec2lKc2Dnxuc9/7v5NmyZ2vfranlPh/pT3hU3Hjz9YLj/op/D2Eh+zlOhLnC+s/OPP9vzk1Z3upk2fwLE4Q++WU+FUP0QwAPnkV48/ODj44PGvXri33IXnYGFMsMvd0d1JBRlcSeUZnsc8IjpRBvEQYjmRymL71oP/AwKZVfhvuNscm5JSf082mbCHnCE9HNQUmVjUCqCuZ87rBwrTuVseQHDUvuyJ+N63sfrTjo3CJYTPDMXz+UaezeTrhbz37YSxG992G4l4Xv+uMWx8V88vFrrAxU5xfu3Fc++FrgL9kjXn3cdvfuCTc1Y+Hou+blmvR2Px/P8BEpxdcHicY2BkYGAA4iUXFTLj+W2+MsizMIDA5c+f2xH0/wZWPeYGIJeDgQkkCgBf1AyCAHicY2BkYGBu+N/AEMOawAAErHoMjAyoQBsAVCkDJAAAeJxjLGNQYgACxlAGBuaXDDosQDYLAyMjEDOA2YwMzEA2NxgD2awJDHYQNWiYkYERiEHsVCDWBuIGIA7FqhYTq0P1GrPYMTCBMUJOFUz7MzAAAGi0Bh0AAAAAACgAKAAoAWQBsAH4AkACjAKyAtIC8gMYA1oDuAQcBIYE1gVaBdgGVAaUBxoHvggOCDQIiAjMCUgJyAnwCioLDAtMC5QMgg00DfIOQg6qDvgPsBA0EKYAAQAAACsAdwAGAAAAAAACACYANABsAAAAigF3AAAAAHicdY9Na8JAEIbfaNQWivTY45BL9bBhE6L4cZX4D3oXSTSQGkjWj0v/QQs99dxjf2ZfN0uhBxNm55mZd2dnADzgCx6un4cBHh134CNw3CW9Ovap+XbcQ+pNHfcx8D6o9Px7Zob21pU7uMOT4y5WeHbsU/PpuId3/DjuY+i9IUMJhQJbVDgAWamKbUX4y7RhagNjfY0drwlihND0C9r/Nm1uysycFlMVMUJaHUxa1btM4lDLQtxjpKmaq1hH1Nya54WVGg0r7QORe3xJM/xzbHCkr7Cn5jqqYIQTNSGHSDBmrNhbMLNU85zYDgpru4x20cV2TyyfeQasBzbK7dlwmKxuCg4ecY2lGJNvjqbaFwcjo5MO58lYVCkzUbVMtKi1xJruIlEi6izBOhCVi2puLvsLTjBRRQAAAHicbc3LNsJxGEbh3/47JHKIQomcwlomfV8Uw5Cb6ApMzLoCF46lPfSu9a49fEpV/vb9VbL8t/vfU6oyp2KFVdZYp8YGdTbZosE2O+yyR5N9DmjR5pAjjunQ5YQep5zR55wLLrnimgE33HJXW3x+zMbDoQ2bdmQf7KMd24l9ss92al/sq32zM/u+bOiHfuiHfuiHfuiHfuiHfuiHfuiHfuiHfuqnfuqnfuqnbk5+APaSXBUAAEu4AMhSWLEBAY5ZuQgACABjILABI0QgsAMjcLAORSAgS7gADlFLsAZTWliwNBuwKFlgZiCKVViwAiVhsAFFYyNisAIjRLMKCQUEK7MKCwUEK7MODwUEK1myBCgJRVJEswoNBgQrsQYBRLEkAYhRWLBAiFixBgNEsSYBiFFYuAQAiFixBgFEWVlZWbgB/4WwBI2xBQBEAAAA\"},23:function(n,t,e){\"use strict\";e.d(t,\"b\",function(){return u}),e.d(t,\"a\",function(){return r}),e.d(t,\"c\",function(){return i});var o=e(119),A=e.n(o),u=function(n,t){n&&(\"string\"!=typeof t&&(t=A()(t)),window.localStorage.setItem(n,t))},r=function(n){if(n)return window.localStorage.getItem(n)},i=function(n){n&&window.localStorage.removeItem(n)}},42:function(n,t,e){\"use strict\";e.d(t,\"h\",function(){return A}),e.d(t,\"c\",function(){return u}),e.d(t,\"a\",function(){return r}),e.d(t,\"f\",function(){return i}),e.d(t,\"e\",function(){return a}),e.d(t,\"d\",function(){return c}),e.d(t,\"b\",function(){return f}),e.d(t,\"g\",function(){return s});var o=e(98),A=function(n){return o.a.fetchPost(\"/member/login\",n)},u=function(n){return o.a.fetchGet(\"/member/loginOut\",n)},r=function(n){return o.a.fetchGet(\"/member/checkLogin\",n)},i=function(n){return o.a.fetchPost(\"/member/register\",n)},a=function(n){return o.a.fetchPost(\"/member/imgaeUpload\",n)},c=function(n){return o.a.fetchGet(\"/member/thanks\",n)},f=function(n){return o.a.fetchGet(\"/goods/productHome\",n)},s=function(n){return o.a.fetchGet(\"/member/geetestInit?t=\"+(new Date).getTime(),n)}},61:function(n,t,e){\"use strict\";var o=e(0),A=e.n(o),u=e(161),r=e.n(u),i=function(){return e.e(3).then(e.bind(null,191))},a=function(){return e.e(12).then(e.bind(null,172))},c=function(){return e.e(14).then(e.bind(null,173))},f=function(){return e.e(7).then(e.bind(null,171))},s=function(){return e.e(11).then(e.bind(null,169))},d=function(){return e.e(8).then(e.bind(null,170))},p=function(){return e.e(2).then(e.bind(null,167))},h=function(){return e.e(5).then(e.bind(null,175))},l=function(){return e.e(4).then(e.bind(null,190))},m=function(){return e.e(20).then(e.bind(null,187))},g=function(){return e.e(13).then(e.bind(null,186))},w=function(){return e.e(10).then(e.bind(null,183))},E=function(){return e.e(22).then(e.bind(null,185))},v=function(){return e.e(23).then(e.bind(null,184))},U=function(){return e.e(21).then(e.bind(null,189))},I=function(){return e.e(0).then(e.bind(null,168))},B=function(){return e.e(15).then(e.bind(null,176))},j=function(){return e.e(18).then(e.bind(null,177))},b=function(){return e.e(6).then(e.bind(null,182))},G=function(){return e.e(1).then(e.bind(null,181))},N=function(){return e.e(24).then(e.bind(null,180))},Q=function(){return e.e(9).then(e.bind(null,188))},M=function(){return e.e(19).then(e.bind(null,174))},D=function(){return e.e(16).then(e.bind(null,179))},k=function(){return e.e(17).then(e.bind(null,178))};A.a.use(r.a),t.a=new r.a({routes:[{path:\"/\",component:i,name:\"index\",redirect:\"/home\",children:[{path:\"home\",component:f},{path:\"goods\",component:s},{path:\"goodsDetails\",name:\"goodsDetails\",component:d},{path:\"thanks\",name:\"thanks\",component:b}]},{path:\"/login\",name:\"login\",component:a},{path:\"/register\",name:\"register\",component:c},{path:\"/cart\",name:\"cart\",component:p},{path:\"/refreshsearch\",name:\"refreshsearch\",component:N},{path:\"/order\",name:\"order\",component:h,children:[{path:\"paysuccess\",name:\"paysuccess\",component:j},{path:\"payment\",name:\"payment\",component:B},{path:\"/search\",name:\"search\",component:G},{path:\"alipay\",name:\"alipay\",component:M},{path:\"wechat\",name:\"wechat\",component:D},{path:\"qqpay\",name:\"qqpay\",component:k}]},{path:\"/user\",name:\"user\",component:l,redirect:\"/user/orderList\",children:[{path:\"orderList\",name:\"订单列表\",component:m},{path:\"orderDetail\",name:\"订单详情\",component:Q},{path:\"information\",name:\"账户资料\",component:g},{path:\"addressList\",name:\"收货地址\",component:w},{path:\"coupon\",name:\"我的优惠\",component:E},{path:\"support\",name:\"售后服务\",component:U},{path:\"aihuishou\",name:\"以旧换新\",component:v}]},{path:\"/checkout\",name:\"checkout\",component:I},{path:\"*\",redirect:\"/home\"}]})},62:function(n,t,e){\"use strict\";var o=e(0),A=e.n(o),u=e(100),r=e.n(u),i=e(117),a=e(115);A.a.use(r.a);var c={login:!1,userInfo:null,cartList:[],showMoveImg:!1,elLeft:0,elTop:0,moveImgUrl:null,cartPositionT:0,cartPositionL:0,receiveInCart:!1,showCart:!1};t.a=new r.a.Store({state:c,action:a.a,mutations:i.a})},75:function(n,t){},76:function(n,t){},77:function(n,t){},78:function(n,t){},79:function(n,t){},80:function(n,t){},81:function(n,t){},82:function(n,t){},83:function(n,t){},84:function(n,t){},85:function(n,t){},86:function(n,t){},87:function(n,t){},88:function(n,t){},89:function(n,t){},90:function(n,t){},91:function(n,t){},95:function(n,t,e){function o(n){e(157)}var A=e(96)(e(118),e(159),o,null,null);n.exports=A.exports},98:function(n,t,e){\"use strict\";var o=e(122),A=e.n(o),u=e(162),r=e.n(u);r.a.defaults.timeout=1e4,r.a.defaults.headers.post[\"Content-Type\"]=\"application/x-www=form-urlencoded\",t.a={fetchGet:function(n){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return new A.a(function(e,o){r.a.get(n,t).then(function(n){e(n.data)}).catch(function(n){o(n)})})},fetchQuickSearch:function(n){return new A.a(function(t,e){r.a.get(n).then(function(n){t(n.data)}).catch(function(n){e(n)})})},fetchPost:function(n){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};return new A.a(function(e,o){r.a.post(n,t).then(function(n){e(n.data)}).catch(function(n){o(n)})})}}}},[114]);\n//# sourceMappingURL=app.e28b119acf7c187f0fbf.js.map"
  }
]